summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortege <tege@gmplib.org>1996-05-08 09:10:48 +0200
committertege <tege@gmplib.org>1996-05-08 09:10:48 +0200
commitc6d715868f53b08c62a129ffd77fb585fd89c43b (patch)
tree82f36d2d8cbe7e07ad3e18d5c6e047e8796d861e
downloadgmp-c6d715868f53b08c62a129ffd77fb585fd89c43b.tar.gz
Initial revision
-rw-r--r--COPYING.LIB481
-rw-r--r--ChangeLog2948
-rw-r--r--INSTALL154
-rw-r--r--Makefile.in201
-rw-r--r--NEWS56
-rw-r--r--PROJECTS270
-rw-r--r--README137
-rw-r--r--SPEED156
-rwxr-xr-xconfig.guess592
-rwxr-xr-xconfig.sub1094
-rw-r--r--config/mt-m881101
-rw-r--r--config/mt-sprc8-gcc1
-rw-r--r--config/mt-supspc-gcc1
-rwxr-xr-xconfigure1263
-rw-r--r--configure.in32
-rw-r--r--cre-mparam.c16
-rw-r--r--demos/factorize.c233
-rw-r--r--gmp-impl.h330
-rw-r--r--gmp.h622
-rw-r--r--gmp.info78
-rw-r--r--gmp.info-11241
-rw-r--r--gmp.info-21029
-rw-r--r--gmp.info-3253
-rw-r--r--gmp.texi2476
-rw-r--r--longlong.h1404
-rwxr-xr-xmake.bat303
-rw-r--r--memory.c97
-rwxr-xr-xmkinstalldirs32
-rwxr-xr-xmove-if-change15
-rw-r--r--mp.h141
-rw-r--r--mp_bpl.c4
-rw-r--r--mp_clz_tab.c40
-rw-r--r--mp_set_fns.c48
-rw-r--r--mpbsd/Makefile.in84
-rw-r--r--mpbsd/configure.in20
-rw-r--r--mpbsd/itom.c54
-rw-r--r--mpbsd/mdiv.c39
-rw-r--r--mpbsd/mfree.c36
-rw-r--r--mpbsd/min.c89
-rw-r--r--mpbsd/mout.c96
-rw-r--r--mpbsd/move.c46
-rw-r--r--mpbsd/mtox.c81
-rw-r--r--mpbsd/realloc.c44
-rw-r--r--mpbsd/sdiv.c77
-rw-r--r--mpbsd/xtom.c110
-rw-r--r--mpf/Makefile.in115
-rw-r--r--mpf/abs.c56
-rw-r--r--mpf/add.c180
-rw-r--r--mpf/add_ui.c142
-rw-r--r--mpf/clear.c35
-rw-r--r--mpf/cmp.c114
-rw-r--r--mpf/cmp_si.c98
-rw-r--r--mpf/cmp_ui.c80
-rw-r--r--mpf/configure.in12
-rw-r--r--mpf/div.c143
-rw-r--r--mpf/div_2exp.c79
-rw-r--r--mpf/div_ui.c78
-rw-r--r--mpf/dump.c43
-rw-r--r--mpf/eq.c121
-rw-r--r--mpf/get_prc.c34
-rw-r--r--mpf/get_str.c500
-rw-r--r--mpf/init.c38
-rw-r--r--mpf/init2.c41
-rw-r--r--mpf/inp_str.c89
-rw-r--r--mpf/iset.c59
-rw-r--r--mpf/iset_d.c39
-rw-r--r--mpf/iset_si.c55
-rw-r--r--mpf/iset_str.c40
-rw-r--r--mpf/iset_ui.c40
-rw-r--r--mpf/mul.c94
-rw-r--r--mpf/mul_2exp.c89
-rw-r--r--mpf/mul_ui.c72
-rw-r--r--mpf/neg.c59
-rw-r--r--mpf/out_str.c89
-rw-r--r--mpf/random2.c65
-rw-r--r--mpf/reldiff.c52
-rw-r--r--mpf/set.c53
-rw-r--r--mpf/set_d.c97
-rw-r--r--mpf/set_dfl_prec.c40
-rw-r--r--mpf/set_prc.c57
-rw-r--r--mpf/set_prc_raw.c39
-rw-r--r--mpf/set_si.c51
-rw-r--r--mpf/set_str.c302
-rw-r--r--mpf/set_ui.c45
-rw-r--r--mpf/size.c35
-rw-r--r--mpf/sqrt.c79
-rw-r--r--mpf/sqrt_ui.c65
-rw-r--r--mpf/sub.c402
-rw-r--r--mpf/sub_ui.c49
-rw-r--r--mpf/tests/Makefile.in58
-rw-r--r--mpf/tests/configure.in11
-rw-r--r--mpf/tests/ref.c184
-rw-r--r--mpf/tests/t-add.c109
-rw-r--r--mpf/tests/t-conv.c117
-rw-r--r--mpf/tests/t-sqrt.c100
-rw-r--r--mpf/tests/t-sub.c114
-rw-r--r--mpf/ui_div.c116
-rw-r--r--mpf/ui_sub.c334
-rw-r--r--mpn/Makefile.in92
-rw-r--r--mpn/README15
-rw-r--r--mpn/a29k/add_n.s120
-rw-r--r--mpn/a29k/addmul_1.s113
-rw-r--r--mpn/a29k/lshift.s93
-rw-r--r--mpn/a29k/mul_1.s97
-rw-r--r--mpn/a29k/rshift.s89
-rw-r--r--mpn/a29k/sub_n.s120
-rw-r--r--mpn/a29k/submul_1.s116
-rw-r--r--mpn/alpha/README53
-rw-r--r--mpn/alpha/add_n.s120
-rw-r--r--mpn/alpha/addmul_1.s92
-rw-r--r--mpn/alpha/ev5/add_n.s148
-rw-r--r--mpn/alpha/ev5/lshift.s174
-rw-r--r--mpn/alpha/ev5/rshift.s172
-rw-r--r--mpn/alpha/ev5/sub_n.s149
-rw-r--r--mpn/alpha/gmp-mparam.h27
-rw-r--r--mpn/alpha/lshift.s109
-rw-r--r--mpn/alpha/mul_1.s85
-rw-r--r--mpn/alpha/rshift.s107
-rw-r--r--mpn/alpha/sub_n.s120
-rw-r--r--mpn/alpha/submul_1.s92
-rw-r--r--mpn/alpha/udiv_qrnnd.S151
-rw-r--r--mpn/bsd.h5
-rw-r--r--mpn/clipper/add_n.s26
-rw-r--r--mpn/clipper/mul_1.s25
-rw-r--r--mpn/clipper/sub_n.s26
-rw-r--r--mpn/config/t-freebsd1
-rw-r--r--mpn/configure.in165
-rw-r--r--mpn/cray/gmp-mparam.h27
-rw-r--r--mpn/generic/add_n.c62
-rw-r--r--mpn/generic/addmul_1.c65
-rw-r--r--mpn/generic/bdivmod.c129
-rw-r--r--mpn/generic/cmp.c56
-rw-r--r--mpn/generic/divmod_1.c208
-rw-r--r--mpn/generic/divrem.c245
-rw-r--r--mpn/generic/divrem_1.c58
-rw-r--r--mpn/generic/dump.c20
-rw-r--r--mpn/generic/gcd.c402
-rw-r--r--mpn/generic/gcd_1.c73
-rw-r--r--mpn/generic/gcdext.c422
-rw-r--r--mpn/generic/get_str.c211
-rw-r--r--mpn/generic/gmp-mparam.h27
-rw-r--r--mpn/generic/hamdist.c88
-rw-r--r--mpn/generic/inlines.c3
-rw-r--r--mpn/generic/lshift.c87
-rw-r--r--mpn/generic/mod_1.c197
-rw-r--r--mpn/generic/mul.c152
-rw-r--r--mpn/generic/mul_1.c59
-rw-r--r--mpn/generic/mul_n.c401
-rw-r--r--mpn/generic/perfsqr.c138
-rw-r--r--mpn/generic/popcount.c87
-rw-r--r--mpn/generic/pre_mod_1.c69
-rw-r--r--mpn/generic/random2.c93
-rw-r--r--mpn/generic/rshift.c88
-rw-r--r--mpn/generic/scan0.c62
-rw-r--r--mpn/generic/scan1.c62
-rw-r--r--mpn/generic/set_str.c154
-rw-r--r--mpn/generic/sqrtrem.c498
-rw-r--r--mpn/generic/sub_n.c62
-rw-r--r--mpn/generic/submul_1.c65
-rw-r--r--mpn/generic/udiv_w_sdiv.c125
-rw-r--r--mpn/hppa/README84
-rw-r--r--mpn/hppa/add_n.s58
-rw-r--r--mpn/hppa/hppa1_1/addmul_1.s102
-rw-r--r--mpn/hppa/hppa1_1/mul_1.s98
-rw-r--r--mpn/hppa/hppa1_1/pa7100/add_n.s75
-rw-r--r--mpn/hppa/hppa1_1/pa7100/addmul_1.S189
-rw-r--r--mpn/hppa/hppa1_1/pa7100/lshift.s83
-rw-r--r--mpn/hppa/hppa1_1/pa7100/rshift.s80
-rw-r--r--mpn/hppa/hppa1_1/pa7100/sub_n.s76
-rw-r--r--mpn/hppa/hppa1_1/pa7100/submul_1.S195
-rw-r--r--mpn/hppa/hppa1_1/submul_1.s111
-rw-r--r--mpn/hppa/hppa1_1/udiv_qrnnd.s75
-rw-r--r--mpn/hppa/lshift.s66
-rw-r--r--mpn/hppa/rshift.s63
-rw-r--r--mpn/hppa/sub_n.s59
-rw-r--r--mpn/hppa/udiv_qrnnd.s286
-rw-r--r--mpn/i960/README9
-rw-r--r--mpn/i960/add_n.s21
-rw-r--r--mpn/i960/addmul_1.s26
-rw-r--r--mpn/i960/mul_1.s23
-rw-r--r--mpn/i960/sub_n.s21
-rw-r--r--mpn/m68k/add_n.S80
-rw-r--r--mpn/m68k/lshift.S151
-rw-r--r--mpn/m68k/mc68020/addmul_1.S84
-rw-r--r--mpn/m68k/mc68020/mul_1.S91
-rw-r--r--mpn/m68k/mc68020/submul_1.S84
-rw-r--r--mpn/m68k/rshift.S150
-rw-r--r--mpn/m68k/sub_n.S80
-rw-r--r--mpn/m68k/syntax.h177
-rw-r--r--mpn/m88k/add_n.s104
-rw-r--r--mpn/m88k/mc88110/add_n.S200
-rw-r--r--mpn/m88k/mc88110/addmul_1.s61
-rw-r--r--mpn/m88k/mc88110/mul_1.s59
-rw-r--r--mpn/m88k/mc88110/sub_n.S276
-rw-r--r--mpn/m88k/mul_1.s127
-rw-r--r--mpn/m88k/sub_n.s106
-rw-r--r--mpn/mips2/add_n.s120
-rw-r--r--mpn/mips2/addmul_1.s97
-rw-r--r--mpn/mips2/lshift.s95
-rw-r--r--mpn/mips2/mul_1.s85
-rw-r--r--mpn/mips2/rshift.s92
-rw-r--r--mpn/mips2/sub_n.s120
-rw-r--r--mpn/mips2/submul_1.s97
-rw-r--r--mpn/mips3/README23
-rw-r--r--mpn/mips3/add_n.s120
-rw-r--r--mpn/mips3/addmul_1.s97
-rw-r--r--mpn/mips3/gmp-mparam.h27
-rw-r--r--mpn/mips3/lshift.s95
-rw-r--r--mpn/mips3/mul_1.s85
-rw-r--r--mpn/mips3/rshift.s92
-rw-r--r--mpn/mips3/sub_n.s120
-rw-r--r--mpn/mips3/submul_1.s97
-rw-r--r--mpn/mp_bases.c549
-rwxr-xr-xmpn/msdos/asm-syntax.h2
-rw-r--r--mpn/ns32k/add_n.s46
-rw-r--r--mpn/ns32k/addmul_1.s48
-rw-r--r--mpn/ns32k/mul_1.s47
-rw-r--r--mpn/ns32k/sub_n.s46
-rw-r--r--mpn/ns32k/submul_1.s48
-rw-r--r--mpn/power/add_n.s81
-rw-r--r--mpn/power/addmul_1.s123
-rw-r--r--mpn/power/lshift.s59
-rw-r--r--mpn/power/mul_1.s110
-rw-r--r--mpn/power/rshift.s57
-rw-r--r--mpn/power/sub_n.s82
-rw-r--r--mpn/power/submul_1.s128
-rw-r--r--mpn/powerpc32/add_n.s55
-rw-r--r--mpn/powerpc32/addmul_1.s68
-rw-r--r--mpn/powerpc32/lshift.s67
-rw-r--r--mpn/powerpc32/mul_1.s63
-rw-r--r--mpn/powerpc32/rshift.s65
-rw-r--r--mpn/powerpc32/sub_n.s56
-rw-r--r--mpn/powerpc32/submul_1.s70
-rw-r--r--mpn/powerpc64/gmp-mparam.h27
-rw-r--r--mpn/pyr/add_n.s54
-rw-r--r--mpn/pyr/addmul_1.s23
-rw-r--r--mpn/pyr/mul_1.s20
-rw-r--r--mpn/pyr/sub_n.s54
-rw-r--r--mpn/sh/add_n.s47
-rw-r--r--mpn/sh/sh2/addmul_1.s53
-rw-r--r--mpn/sh/sh2/mul_1.s50
-rw-r--r--mpn/sh/sh2/submul_1.s53
-rw-r--r--mpn/sh/sub_n.s47
-rw-r--r--mpn/sparc32/README36
-rw-r--r--mpn/sparc32/add_n.S226
-rw-r--r--mpn/sparc32/addmul_1.S147
-rw-r--r--mpn/sparc32/lshift.S95
-rw-r--r--mpn/sparc32/mul_1.S199
-rw-r--r--mpn/sparc32/rshift.S92
-rw-r--r--mpn/sparc32/sub_n.S311
-rw-r--r--mpn/sparc32/submul_1.S147
-rw-r--r--mpn/sparc32/udiv_fp.S145
-rw-r--r--mpn/sparc32/udiv_nfp.S188
-rw-r--r--mpn/sparc32/v8/addmul_1.S124
-rw-r--r--mpn/sparc32/v8/mul_1.S99
-rw-r--r--mpn/sparc32/v8/submul_1.S58
-rw-r--r--mpn/sparc32/v8/supersparc/udiv.S109
-rw-r--r--mpn/sparc64/add_n.s58
-rw-r--r--mpn/sparc64/addmul_1.s89
-rw-r--r--mpn/sparc64/gmp-mparam.h27
-rw-r--r--mpn/sparc64/lshift.s96
-rw-r--r--mpn/sparc64/mul_1.s86
-rw-r--r--mpn/sparc64/rshift.s93
-rw-r--r--mpn/sparc64/sub_n.s58
-rw-r--r--mpn/sparc64/submul_1.s89
-rw-r--r--mpn/sysv.h1
-rw-r--r--mpn/tests/add_n.c211
-rw-r--r--mpn/tests/addmul_1.c223
-rw-r--r--mpn/tests/divmod_1.c120
-rw-r--r--mpn/tests/divrem.c129
-rw-r--r--mpn/tests/lshift.c226
-rw-r--r--mpn/tests/mul_1.c212
-rw-r--r--mpn/tests/rshift.c227
-rw-r--r--mpn/tests/sub_n.c211
-rw-r--r--mpn/tests/submul_1.c218
-rw-r--r--mpn/tests/tst-addsub.c164
-rw-r--r--mpn/vax/add_n.s48
-rw-r--r--mpn/vax/addmul_1.s126
-rw-r--r--mpn/vax/gmp-mparam.h29
-rw-r--r--mpn/vax/mul_1.s123
-rw-r--r--mpn/vax/sub_n.s48
-rw-r--r--mpn/vax/submul_1.s126
-rw-r--r--mpn/x86/add_n.S106
-rw-r--r--mpn/x86/addmul_1.S76
-rw-r--r--mpn/x86/gmp-mparam.h29
-rw-r--r--mpn/x86/lshift.S85
-rw-r--r--mpn/x86/mul_1.S75
-rw-r--r--mpn/x86/pentium/README26
-rw-r--r--mpn/x86/pentium/add_n.S130
-rw-r--r--mpn/x86/pentium/addmul_1.S83
-rw-r--r--mpn/x86/pentium/lshift.S217
-rw-r--r--mpn/x86/pentium/mul_1.S79
-rw-r--r--mpn/x86/pentium/rshift.S217
-rw-r--r--mpn/x86/pentium/sub_n.S130
-rw-r--r--mpn/x86/pentium/submul_1.S83
-rw-r--r--mpn/x86/rshift.S87
-rw-r--r--mpn/x86/sub_n.S106
-rw-r--r--mpn/x86/submul_1.S76
-rw-r--r--mpn/x86/syntax.h62
-rw-r--r--mpn/z8000/add_n.s53
-rw-r--r--mpn/z8000/gmp-mparam.h27
-rw-r--r--mpn/z8000/mul_1.s68
-rw-r--r--mpn/z8000/sub_n.s54
-rw-r--r--mpn/z8000x/add_n.s56
-rw-r--r--mpn/z8000x/sub_n.s56
-rw-r--r--mpq/Makefile.in83
-rw-r--r--mpq/add.c85
-rw-r--r--mpq/canonicalize.c53
-rw-r--r--mpq/clear.c37
-rw-r--r--mpq/cmp.c120
-rw-r--r--mpq/cmp_ui.c84
-rw-r--r--mpq/configure.in12
-rw-r--r--mpq/div.c93
-rw-r--r--mpq/equal.c43
-rw-r--r--mpq/get_d.c154
-rw-r--r--mpq/get_den.c41
-rw-r--r--mpq/get_num.c42
-rw-r--r--mpq/init.c40
-rw-r--r--mpq/inv.c75
-rw-r--r--mpq/mul.c79
-rw-r--r--mpq/neg.c36
-rw-r--r--mpq/set.c49
-rw-r--r--mpq/set_den.c42
-rw-r--r--mpq/set_num.c42
-rw-r--r--mpq/set_si.c54
-rw-r--r--mpq/set_ui.c50
-rw-r--r--mpq/sub.c85
-rw-r--r--mpq/tests/Makefile.in48
-rw-r--r--mpq/tests/configure.in11
-rw-r--r--mpq/tests/t-cmp.c109
-rw-r--r--mpq/tests/t-cmp_ui.c102
-rw-r--r--mpq/tests/t-get_d.c88
-rw-r--r--mpz/Makefile.in177
-rw-r--r--mpz/abs.c51
-rw-r--r--mpz/add.c120
-rw-r--r--mpz/add_ui.c84
-rw-r--r--mpz/and.c278
-rw-r--r--mpz/array_init.c48
-rw-r--r--mpz/cdiv_q.c51
-rw-r--r--mpz/cdiv_q_ui.c64
-rw-r--r--mpz/cdiv_qr.c62
-rw-r--r--mpz/cdiv_qr_ui.c68
-rw-r--r--mpz/cdiv_r.c59
-rw-r--r--mpz/cdiv_r_ui.c54
-rw-r--r--mpz/cdiv_ui.c50
-rw-r--r--mpz/clear.c35
-rw-r--r--mpz/clrbit.c114
-rw-r--r--mpz/cmp.c75
-rw-r--r--mpz/cmp_si.c66
-rw-r--r--mpz/cmp_ui.c56
-rw-r--r--mpz/com.c93
-rw-r--r--mpz/configure.in12
-rw-r--r--mpz/divexact.c112
-rw-r--r--mpz/dmincl.c201
-rw-r--r--mpz/fac_ui.c157
-rw-r--r--mpz/fdiv_q.c51
-rw-r--r--mpz/fdiv_q_2exp.c94
-rw-r--r--mpz/fdiv_q_ui.c62
-rw-r--r--mpz/fdiv_qr.c62
-rw-r--r--mpz/fdiv_qr_ui.c66
-rw-r--r--mpz/fdiv_r.c58
-rw-r--r--mpz/fdiv_r_2exp.c88
-rw-r--r--mpz/fdiv_r_ui.c52
-rw-r--r--mpz/fdiv_ui.c48
-rw-r--r--mpz/gcd.c178
-rw-r--r--mpz/gcd_ui.c64
-rw-r--r--mpz/gcdext.c88
-rw-r--r--mpz/get_si.c43
-rw-r--r--mpz/get_str.c118
-rw-r--r--mpz/get_ui.c37
-rw-r--r--mpz/getlimbn.c38
-rw-r--r--mpz/hamdist.c62
-rw-r--r--mpz/init.c36
-rw-r--r--mpz/inp_raw.c101
-rw-r--r--mpz/inp_str.c138
-rw-r--r--mpz/invert.c43
-rw-r--r--mpz/ior.c243
-rw-r--r--mpz/iset.c49
-rw-r--r--mpz/iset_d.c40
-rw-r--r--mpz/iset_si.c49
-rw-r--r--mpz/iset_str.c44
-rw-r--r--mpz/iset_ui.c39
-rw-r--r--mpz/jacobi.c53
-rw-r--r--mpz/legendre.c184
-rw-r--r--mpz/mod.c63
-rw-r--r--mpz/mul.c127
-rw-r--r--mpz/mul_2exp.c76
-rw-r--r--mpz/mul_ui.c64
-rw-r--r--mpz/neg.c53
-rw-r--r--mpz/out_raw.c89
-rw-r--r--mpz/out_str.c108
-rw-r--r--mpz/perfsqr.c41
-rw-r--r--mpz/popcount.c42
-rw-r--r--mpz/pow_ui.c129
-rw-r--r--mpz/powm.c276
-rw-r--r--mpz/powm_ui.c234
-rw-r--r--mpz/pprime_p.c115
-rw-r--r--mpz/random.c56
-rw-r--r--mpz/random2.c48
-rw-r--r--mpz/realloc.c52
-rw-r--r--mpz/scan0.c35
-rw-r--r--mpz/scan1.c35
-rw-r--r--mpz/set.c48
-rw-r--r--mpz/set_d.c133
-rw-r--r--mpz/set_si.c48
-rw-r--r--mpz/set_str.c132
-rw-r--r--mpz/set_ui.c43
-rw-r--r--mpz/setbit.c113
-rw-r--r--mpz/size.c35
-rw-r--r--mpz/sizeinbase.c60
-rw-r--r--mpz/sqrt.c89
-rw-r--r--mpz/sqrtrem.c107
-rw-r--r--mpz/sub.c120
-rw-r--r--mpz/sub_ui.c84
-rw-r--r--mpz/tdiv_q.c133
-rw-r--r--mpz/tdiv_q_2exp.c68
-rw-r--r--mpz/tdiv_q_ui.c63
-rw-r--r--mpz/tdiv_qr.c39
-rw-r--r--mpz/tdiv_qr_ui.c78
-rw-r--r--mpz/tdiv_r.c37
-rw-r--r--mpz/tdiv_r_2exp.c79
-rw-r--r--mpz/tdiv_r_ui.c64
-rw-r--r--mpz/tests/Makefile.in126
-rw-r--r--mpz/tests/configure.in11
-rw-r--r--mpz/tests/convert.c80
-rw-r--r--mpz/tests/dive.c87
-rw-r--r--mpz/tests/io-binary.c76
-rw-r--r--mpz/tests/io.c86
-rw-r--r--mpz/tests/logic.c103
-rw-r--r--mpz/tests/reuse.c126
-rw-r--r--mpz/tests/t-fdiv.c118
-rw-r--r--mpz/tests/t-fdiv_ui.c117
-rw-r--r--mpz/tests/t-gcd2.c137
-rw-r--r--mpz/tests/t-mul.c264
-rw-r--r--mpz/tests/t-powm.c125
-rw-r--r--mpz/tests/t-powm_ui.c120
-rw-r--r--mpz/tests/t-sqrtrem.c98
-rw-r--r--mpz/tests/t-tdiv.c118
-rw-r--r--mpz/tests/t-tdiv_ui.c117
-rw-r--r--mpz/ui_pow_ui.c111
-rw-r--r--stack-alloc.c108
-rw-r--r--stack-alloc.h50
-rw-r--r--texinfo.tex4585
-rw-r--r--urandom.h64
-rw-r--r--version.c1
445 files changed, 59431 insertions, 0 deletions
diff --git a/COPYING.LIB b/COPYING.LIB
new file mode 100644
index 000000000..985f736a1
--- /dev/null
+++ b/COPYING.LIB
@@ -0,0 +1,481 @@
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 000000000..a9bda5fd4
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,2948 @@
+Wed Apr 24 05:33:28 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * Version 2.0 released.
+
+ * All files: Upfate FSF's address.
+
+ * Makefile.in (gmp_toc.html): New name for gmp.html.
+ (TAGS): Depend on force.
+
+ * mpf/tests/t-conv.c: Pass -base to mpf_set_str.
+
+Sat Apr 20 03:54:06 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * Makefile.in (ps): New target, depend on gmp.ps.
+
+Fri Apr 19 14:03:15 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * mpf/out_str.c: Print `@' before exponent, not `e'.
+
+ * make.bat: Update from Makefiles.
+
+Thu Apr 18 01:22:05 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * mpf/set_str.c: If parameter `base' is negative, expect exponent
+ to be decimal, otherwise in the same base as the mantissa.
+
+Wed Apr 17 17:28:36 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * mpf/set_dfl_prec.c: Don't return anything.
+ * gmp.h: Corresponding changes.
+
+ * mpf/set_dfl_prec.c: Use `unsigned long int' for bit counts.
+ * mpf/init2.c: Likewise.
+ * mpf/get_prc.c: Likewise.
+ * mpf/set_prc.c: Likewise.
+ * mpf/set_prc_raw.c: Likewise.
+ * mpz/popcount.c: Likewise.
+ * mpz/hamdist.c: Likewise.
+ * mpz/scan1.c: Likewise.
+ * mpz/scan0.c: Likewise.
+ * mpn/generic/popcount.c: Likewise.
+ * mpn/generic/hamdist.c: Likewise.
+ * mpn/generic/scan1.c: Likewise.
+ * mpn/generic/scan0.c: Likewise.
+ * gmp.h: Likewise.
+
+ * mpf/eq.c: New file, based on mpf/diff.c.
+ * mpf/diff.c: Delete.
+ * mpf/Makefile.in: Corresponding changes.
+ * gmp.h: Likewise.
+
+ * mpf/reldiff.c: New file.
+ * mpf/Makefile.in: Compile it.
+ * gmp.h: Declare mpf_reldiff.
+
+ * mpz/iset_d.c: New file.
+ * mpz/Makefile.in: Compile it.
+ * gmp.h: Declare mpz_init_set_d.
+
+Tue Apr 16 16:28:31 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * Makefile.in (gmp.html): Pass -acc to texi2html.
+
+Mon Apr 15 16:20:24 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * mpf/set_str.c: Switch off code for defaulting the base from the
+ leading characters.
+
+ * gmp.h (mp?_sign): Delete.
+ (mp?_sgn): New macros.
+
+Fri Apr 12 17:23:33 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * Makefile.in (gmp.dvi): Delete tmp.* at end of rule.
+
+Wed Apr 10 22:52:02 1996 Torbjorn Granlund (tege@tiny.tmg.se)
+
+ * mpf/random2.c: Change of `exp' param, mp_size_t => mp_exp_t.
+ * gmp.h: Corresponding change.
+
+ * gmp.h (mp_bits_per_limb): Make it const.
+
+Sat Mar 30 01:20:23 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * configure.in: Re-enable recognition of with_gcc.
+
+ * mpf/Makefile.in (.c.o): Pass XCFLAGS.
+ * mpn/Makefile.in (.c.o): Likewise.
+ * mpz/Makefile.in (.c.o): Likewise.
+ * mpq/Makefile.in (.c.o): Likewise.
+ * mpbsd/Makefile.in (.c.o): Likewise.
+ * mpf/tests/Makefile.in (.c.o): Likewise.
+ * mpz/tests/Makefile.in (.c.o): Likewise.
+ * mpq/tests/Makefile.in (.c.o): Likewise.
+
+ * Makefile.in (XCFLAGS): Default to empty.
+ (FLAGS_TO_PASS): Pass on XCFLAGS.
+ (.c.o): Pass XCFLAGS.
+
+ * config/mt-m88110 (XCFLAGS): Define instead of CC.
+ * config/mt-sprc8-gcc (XCFLAGS): Likewise.
+ * config/mt-supspc-gcc (XCFLAGS): Likewise.
+
+ * configure: Don't default CC to "gcc -O2" is -with-gcc=no was
+ specified.
+
+Mon Mar 25 01:07:54 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * urandom.h: Test for __SVR4 in addition to __svr4__.
+
+ * mp_bpl.c (mp_bits_per_limb): Declare as `const'.
+
+ * Makefile.in (CFLAGS): `-O2' => `-O'.
+ * mpn/Makefile.in (CFLAGS): Likewise.
+
+ * gmp-impl.h: Get rid of obsolete field access macros.
+
+ * mpn/mp_bases.c (__mp_bases): 1e39 => 1e38 to work around Solaris
+ cc compiler bug.
+
+ * gmp.h (__MPN): Make it work also for non-ANSI compilers.
+
+Thu Mar 21 01:07:54 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * mpf/sub.c: New special case for ediff <= 1 before generic code.
+ Simplify generic code for ediff == 0.
+ Rename uexp => exp.
+
+Mon Mar 11 18:24:57 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * mpf/tests/*.c: Use ref_mpf_sub for error calculation.
+ * mpf/tests/Makefile.in: Link ref.o to all executables.
+
+ * mpf/tests/t-sub.c: Make u = v + 1 with 50% probability.
+
+Sun Mar 10 21:03:17 1996 Torbjorn Granlund (tege@tiny.tmg.se)
+
+ * mpf/get_str.c: In digit development loop for fractions, change
+ loop condition from `<' to `<='.
+
+Thu Mar 7 04:58:11 1996 Torbjorn Granlund <tege@tiny.tmg.se>
+
+ * mpn/mp_bases.c (__mp_bases): 1e100 => 1e39 to avoid overflow warning.
+
+Wed Mar 6 01:10:42 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * mpf/tests/t-sqrt.c: New file.
+ * mpf/tests/Makefile.in: Corresponding changes.
+
+ * mpf/sqrt.c: Special case for square root of zero.
+
+ * mpq/add.c: Clean up variable names.
+ * mpq/sub.c: Update from mpq/add.c.
+
+ * mpz/divexact.c: abs => ABS.
+ * mpz/gcd.c: Likewise. Rewrite final fixup code, to decrease
+ allocation. Misc cleanups.
+
+Tue Mar 5 22:24:56 1996 Torbjorn Granlund <tege@tmg.se>
+
+ * mpn/configure.in: Recognize linuxoldld as a synonym for linuxaout.
+
+ * gmp.h (mpn_add, mpn_add_1, mpn_sub, mpn_sub_1): Add prototypes.
+
+ * mpn/configure.in: Use t-freebsd also for netbsd.
+
+Mon Mar 4 15:13:28 1996 Torbjorn Granlund <tege@tmg.se>
+
+ * mpq/Makefile.in (cmp.o): Depend on longlong.h.
+
+ * mpq/equal.c: New file.
+ * mpq/Makefile.in: Corresponding changes.
+
+ * mpf/tests/t-add.c: New file.
+ * mpf/tests/t-sub.c: Renamed from t-addsub.c.
+ * mpf/tests/ref.c: New file.
+ * mpf/tests/Makefile.in: Corresponding changes.
+
+ * gmp-impl.h (SIZ, ABSIZ, PTR, EXP, PREC, ALLOC): New #defines.
+
+Sun Mar 3 07:45:46 1996 Torbjorn Granlund <tege@tmg.se>
+
+ * mpf/set_str.c: In exponentialization code, allocate 3 extra
+ limbs, not just 2.
+
+ * mpf/get_str.c: Allocate sufficient space for tstr.
+ When calculating exp_in_base, round result down.
+
+ * mpf/tests/t-conv.c: New file.
+ * mpf/tests/Makefile.in: Corresponding changes.
+
+ * mp_bpl.c: New file.
+ * gmp.h: Declare it.
+ * Makefile.in: Corresponding changes.
+
+Sat Mar 2 06:27:56 1996 Torbjorn Granlund <tege@tmg.se>
+
+ * mpf/set_prc_raw.c: New file.
+ * mpf/set_prc.c: Renamed from set_prec.c.
+ * mpf/get_prc.c: New file.
+ * mpf/Makefile.in: Corresponding changes.
+ * gmp.h: Declare new functions.
+
+ * mpn/generic/gcdext.c: Add copyright header.
+
+Fri Mar 1 01:22:24 1996 Torbjorn Granlund <tege@tmg.se>
+
+ * mpn/configure.in: For ppc601, search "power" before "powerpc32".
+
+ * mp?/Makefile.in (AR_FLAGS): New variable.
+ (libmp?.a): Use it.
+
+ * make.bat: New file.
+ * mpn/msdos: New directory.
+ * mpn/msdos/asm-syntax.h: New file.
+
+ * mpn/Makefile.in (distclean maintainer-clean): Delete asm-syntax.h.
+
+ * config.sub: Recognize [ctj]90-cray.
+
+ * mpn/configure.in: Recognize [ctj]90-cray-unicos*.
+
+ * mpn/generic/gcdext.c: Don't use alloca directly, use TMP_* macros.
+
+ * mpn/generic/gcd.c: Split increment from use of USIZE to avoid
+ undefined behaviour.
+
+Thu Feb 29 04:11:24 1996 Torbjorn Granlund <tege@tmg.se>
+
+ * Makefile.in (install-info-files): Update for new install-info
+ behaviour.
+
+ * mpn/power/add_n.s: Rewrite.
+ * mpn/power/sub_n.s: Rewrite.
+
+Wed Feb 28 01:34:30 1996 Torbjorn Granlund <tege@tmg.se>
+
+ * mpz/pow_ui.c: Compute allocation more aggressively for small bases.
+ * mpz/ui_pow_ui.c: Likewise.
+
+ * mpn/mp_bases.c (__mp_bases): Put huge value in 2nd field for index 1.
+
+ * mpn/generic/sqrtrem.c: sizeof (mp_limb_t) => BYTES_PER_MP_LIMB.
+ * mpn/generic/gcd.c: Likewise.
+ (SIGN_BIT): Compute differently.
+
+Mon Feb 26 00:07:36 1996 Torbjorn Granlund <tege@tmg.se>
+
+ * All files: mp_limb => mp_limb_t, mp_limb_signed => mp_limb_signed_t.
+
+ * Makefile.in (install, install-bsdmp, install-info-files): Depend
+ on installdirs. chmod all installed files.
+
+Sun Feb 25 01:47:41 1996 Torbjorn Granlund <tege@tmg.se>
+
+ * mpbsd/configure.in: Delete debugging code.
+
+ * All Makefile.in: Update clean targets.
+
+ * Makefile.in (AR_FLAGS): New variable.
+ (libgmp.a): Use it.
+ (libmp.a): Likewise.
+
+ * VERSION: Delete file.
+
+ * Makefile.in (installdirs): New target.
+ * mkinstalldirs: New file (from the texinfo package).
+
+ * Makefile.in (INSTALL, INSTALL_DATA, INSTALL_PROGRAM): New variables.
+ (MAKEINFO, MAKEINFOFLAGS, TEXI2DVI): New variables.
+ (install-info): New target.
+ (install, install-bsdmp): Depend on install-info.
+ ($(srcdir)/gmp.info): Changed from plain gmp.info; put info files
+ into source directory.
+ (distclean, mostlyclean): New targets.
+ (maintainer-clean): New name for realclean.
+ (uninstall): New target.
+ (TAGS): New target.
+ (info, dvi): New targets.
+ (.PHONY): Assign.
+
+ * Makefile.in (install, install-bsdmp): Use INSTALL_DATA.
+
+ * mp{n,z,f,bsd}/move-if-change: Delete.
+
+ * mpbsd/Makefile.in (stamp-stddefh): Delete target.
+
+ * Makefile.in (.c.o): Pass CFLAGS last.
+ * mpbsd/Makefile.in (.c.o): Likewise.
+ * mpf/Makefile.in (.c.o): Likewise.
+ * mpq/Makefile.in (.c.o): Likewise.
+ * mpz/Makefile.in (.c.o): Likewise.
+ * mpn/Makefile.in (.c.o): Likewise.
+ (.S.o): Likewise.
+
+ * memory.c: Change allocation error message.
+
+ * Makefile.in (install): Prefix gmp.h with $(srcdir).
+ (install-bsdmp): Prefix mp.h with $(srcdir).
+
+ * mp{n,z,f,bsd}/{configure,config.sub}: Delete.
+
+ * Makefile.in (gmp.dvi): Set TEXINPUTS also for 2nd tex invocation
+ (install targets): Install gmp.info-N.
+
+Sat Feb 24 03:36:52 1996 Torbjorn Granlund <tege@tmg.se>
+
+ * mpf/get_str.c: Fix typo.
+
+ * mpz/legendre.c: Clarify expression with extra parens.
+
+ * version.c (gmp_version): Not static.
+
+ * mpf/iset_str.c: Properly return error code.
+
+ * mpf/add.c: Delete unused variables.
+ * mpf/inp_str.c: Likewise.
+ * mpq/get_d.c: Likewise.
+
+ * mpn/generic/dump.c: #include <stdio.h>.
+ * mpf/dump.c: Likewise.
+ * mpf/set_str.c: #include <ctype.h>.
+ (strtol): Declare.
+
+ * gmp.h: mpn_sqrt => mpn_sqrtrem.
+
+ * Makefile.in (clean, realclean): Clean in mpbsd.
+ (check): Test in mpf.
+
+ * mpf/Makefile.in (clean): Clean in tests.
+ * mpq/Makefile.in (clean): Clean in tests.
+
+ * mpf/tests/Makefile.in: New file.
+ * mpf/tests/configure.in: New file.
+ * mpf/tests/t-addsub.c: New file.
+
+ * mpf/sub_ui.c: Simply call mpf_sub for now.
+
+ * mpf/sub.c: Increase prec by 1.
+ * mpf/ui_sub.c: Likewise.
+
+Fri Feb 23 00:59:54 1996 Torbjorn Granlund <tege@tmg.se>
+
+ * mpf/ui_sub.c: Fix typos.
+
+ * mpf/get_str.c: When allocating space for tmp, allow for an extra
+ limb. In code for fraction conversion, add special case for bases
+ that are a power of 2.
+
+ * mpf/out_str.c: Output leading "0.".
+ Default base to 10, before computing string allocation.
+
+ * mpf/get_str.c: Make variables for string size have type size_t.
+ * gmp.h: Corresponding change.
+
+ * mpf/random2.c: Allow creation of prec+1 large mantissas.
+
+ * mpf/add_ui.c: Don't abort if u < 0; special case for u <= 0.
+ Fix typo in MPN_COPY offset.
+ * mpf/sub_ui.c: Analogous changes.
+
+ * mpf/set_prec.c: Rewrite.
+
+ * mpf/init2.c: Compute precision as in set_prec.c.
+
+ * mpf/div_2exp.c: Special case for u == 0.
+ * mpf/mul_2exp.c: Likewise. Write r->_mp_size always.
+
+ * mpf/sqrt_ui.c: mpn_sqrt => mpn_sqrtrem.
+ * mpf/sqrt.c: Likewise. When computing new exponent, round quotient
+ towards -infinity.
+
+ * mpf/add.c: Fix typos.
+ * mpf/sub.c: Fix typos.
+
+Thu Feb 22 00:24:48 1996 Torbjorn Granlund <tege@tmg.se>
+
+ * mpz/Makefile.in (stamp-stddefh): Delete target.
+ (test): Delete target.
+ * Makefile.in (stamp-stddefh): Delete target.
+ (cre-stddefh.o): Delete target.
+ (gmp.dvi): Set TEXINPUTS before invoking tex.
+
+ * cre-stddefh.c: Delete.
+
+ * mpz/sqrt.c: Fix typo.
+
+ * mpz/powm.c: Special case for mod == 0.
+ * mpz/powm_ui.c: Likewise.
+
+ * mpz/get_si.c: Handle -0x80000000 correctly.
+
+ * mpz/inp_str.c: Now retutns size_t.
+ Make it return number of bytes read or error indication.
+ * mpf/inp_str.c: Likewise.
+
+ * mpz/out_raw.c: Replace by mpz/out_binary.c, with modifications.
+ * mpz/inp_raw.c: Rewrite, using mpz/inp_binary as a base.
+ * mpz/inp_binary.c: Delete.
+
+ * mpn/Makefile.in (XCFLAGS): Remove variable.
+ (.c.o): Don't pass XCFLAGS.
+ (SFLAGS): Set to nothing.
+ (.S.o): Pass SFLAGS, not XCFLAGS.
+
+ * mpn/config/t-freebsd (SFLAGS): New name for XCFLAGS.
+
+ * mpf/out_str.c: Make return number of bytes written or error
+ indication.
+ * mpz/out_str.c: Likewise.
+ * gmp.h: Corresponding changes.
+
+ * gmp.h (__mpz_struct): mp_size_t => int.
+ (__mpq_struct): Likewise.
+ (__mpf_struct): Likewise.
+ (mp_size_t): int => long int.
+
+ * mpn/cray: New directory.
+ * mpn/cray/gmp-mparam.h: New file.
+ * mpn/configure.in: Recognize cray variants.
+
+ * Makefile.in: Set defaults for prefix, libdir, etc.
+ (install): New target.
+ (install-bsdmp): New target.
+ (gmp.html): New target.
+
+ * stack-alloc.c (__tmp_alloc): Cast void ptrs to char * in comparison.
+
+Wed Feb 21 04:35:02 1996 Torbjorn Granlund <tege@tmg.se>
+
+ * gmp.h: Sort mpn declarations.
+ (mpn_gcdext): Add declaration.
+
+ * mpn/generic/divrem_1.c: New file.
+ * mpn/Makefile.in (divrem_1.o): New rule.
+ * configure.in (functions): Add divrem_1.
+
+ * mpn/generic/divmod.c: Delete file.
+ * mpn/configure.in (functions): Delete divmod.
+ * Makefile.in (divmod.o): Delete rule.
+ * gmp.h (mpn_divmod): New #define.
+
+ * gmp.h (mpn_next_bit_set): Delete spurious declaration.
+
+ * mpn/generic/divrem.c (default case): In code assigning
+ most_significant_q_limb, move reassignment of n0 into if statement.
+
+ * gmp.h (mpf_inp_str): Fix typo.
+ (mpf_out_str): Make prototype match reality.
+ * mpf/inp_str.c: New file.
+ * mpf/out_str.c: New file.
+ * mpf/Makefile.in: Compile new files.
+
+ * mpn/Makefile.in (dump.o): Fix dependency path.
+ (inlines.o): Likewise.
+
+ * mpn/configure.in: Make m68060 be the same as m68000. Clean up
+ m68k configs.
+
+Tue Feb 20 01:35:11 1996 Torbjorn Granlund <tege@tmg.se>
+
+ * mpn/generic/sqrtrem.c: Renamed from sqrt.
+ * mpn/configure.in (functions): Corresponding change.
+ * mpn/Makefile.in: Likewise.
+ * mpz/sqrtrem.c: Likewise.
+ * mpz/sqrt.c: Likewise.
+ * mpn/generic/perfsqr.c: Likewise.
+
+ * Makefile.in (clean): Also remove libmp.a.
+ Don't compile cre-conv-tab.c or mp_bases.c.
+ cre-conv-tab.c: Delete file.
+ (gmp.ps): New rule.
+
+ * mpn/mp_bases.c: New file.
+ * mpn/Makefile.in: Compile mp_bases.c.
+
+ * mpz/set_str.c: Skip initial whitespace.
+ * mpf/set_str.c: Likewise.
+ * mpbsd/xtom.c: Likewise.
+
+ * gmp.h: Add missing mpz declarations.
+ Delete all formal parameter names from declarations.
+
+ * mpn/Makefile.in: Add dependencies for .c files.
+
+ * Makefile.in (check): Write recursive make calls separately, not as
+ a loop.
+ (FLAGS_TO_PASS): New variable. Use it for most recursive makes.
+
+Mon Feb 19 01:02:20 1996 Torbjorn Granlund <tege@tmg.se>
+
+ * mpn/Makefile.in (.S.o): Pipe cpp output to grep in order to delete
+ lines starting with #.
+ (CPP): Set to $(CC) -E to avoid gcc dependency.
+
+ * mpn/m68k/syntax.h (moveql): Define to moveq for MIT_SYNTAX.
+
+ * mpn/hppa/hppa1_1/pa7100/addmul_1.S: Fix typo in s1_ptr alignment
+ code.
+ * mpn/hppa/hppa1_1/pa7100/submul_1.S: Likewise.
+
+ * gmp.h: Fix typos in #defines of recently added mpn functions.
+
+ * mpz/inp_str.c: Skip all whitespace, not just plain space.
+ * mpbsd/min.c: Likewise.
+
+ * mpn/configure.in (functions): Add gcdext.
+ * mpn/generic/gcdext.c: New file.
+
+ * mpz/legendre.c: mpz_div_2exp => mpz_tdiv_q_2exp.
+
+ * gmp.h: Surround mpn declarations with extern "C" { ... }.
+
+ * Makefile.in (check): New target.
+
+ * mpq/get_d.c: Update comments. Use rsize instead of dsize + N_QLIMBS
+ when possible. Add special case for nsize == 0.
+
+ * gmp.h (mpq_get_d): Add declaration.
+ (mpq_canonicalize): Likewise.
+ (mpq_cmp_ui): Likewise.
+ (mpf_diff): Likewise.
+ (mpf_ui_sub): Likewise.
+ (mpf_set_prec): Likewise.
+ (mpf_random2): Likewise.
+
+ * gmp.h (mpz_cmp_ui): New #define.
+ (mpz_cmp_si): New #define.
+ (mpq_cmp_ui): New #define.
+ (mpz_sign): New #define.
+ (mpq_sign): New #define.
+ (mpf_sign): New #define.
+ (mpq_numref): New #define.
+ (mpq_denref): New #define.
+
+ * mpq/set_z.c: File deleted.
+ * mpq/Makefile.in: Corresponding changes.
+
+Sun Feb 18 01:34:47 1996 Torbjorn Granlund <tege@tmg.se>
+
+ * mpbsd/sdiv.c: Use _mp_realloc, not _mpz_realloc.
+
+ * mpz/inp_binary.c: Default stream to stdin.
+ * mpz/inp_str.c: Likewise.
+ * mpz/inp_raw.c: Likewise.
+ * mpz/out_binary.c: Default stream to stdout.
+ * mpz/out_raw.c: Likewise.
+ * mpz/out_str.c: Likewise.
+
+ * mpbsd/realloc.c: New file.
+ * mpbsd/Makefile.in: Corresponding changes.
+
+ * mpbsd/min.c: Rewrite (base on mpz/inp_str.c).
+ * mpbsd/mtox.c: Rewrite (base on mpz/get_str.c).
+
+ * mpbsd/mout.c: Rewrite (base on mpz/out_str) but make it output
+ spaces in each 10th position.
+ * mpbsd/xtom.c: Rewrite (base on mpz/set_str).
+
+ * mpq/tests/Makefile.in (st-cmp): New file.
+ * mpq/tests/configure.in (srcname): New file.
+
+ * mpz/tests/configure.in (srcname): Fix typo.
+
+ * mpq/cmp.c: Add check using number of significant bits, to avoid
+ general multiplication.
+
+Sat Feb 17 11:58:30 1996 Torbjorn Granlund <tege@tmg.se>
+
+ * mpq/cmp_ui.c: Store cy_limb after the mpn_mul_1 calls.
+
+ * mpq/tests: New directory.
+ * mpq/tests/t-cmp.c: New file.
+ * mpq/tests/t-cmp_ui.c: New file.
+
+ * mpz/tests/dive.c (main): Generate zero numerator.
+ (get_random_size) : Delete.
+
+ * mpz/divexact.c: Add special case for 0/x.
+
+ * gmp.h (mpz_mod): Add declaration.
+
+Fri Feb 16 18:18:39 1996 Andreas Schwab <schwab@informatik.uni-dortmund.de>
+
+ * mpn/m68k/*: Rewrite code not to use the INSN macros.
+ (L): New macro to properly prefix local labels for ELF.
+
+Fri Feb 16 00:20:56 1996 Torbjorn Granlund <tege@tmg.se>
+
+ * gmp-impl.h (ieee_double_extract): Use plain `unsigned int' for
+ fields.
+ * mpn/generic/inlines.c (_FORCE_INLINES): New #define. Delete
+ conditional __GNUC__.
+ * gmp.h (mpn_add, mpn_sub, mpn_add_1, mpn_sub_1):
+ Only define these if __GNUC__ || _FORCE_INLINES.
+ * mpf/random2.c: Add missing parameter in non-ANSI header.
+ * mpn/generic/gcd.c (SIGN_BIT): Do as #define to work around bug
+ in AIX compilers.
+ * mpq/get_d.c: #define N_QLIMBS.
+ * mpz/divexact.c: Obscure division by 0 to silent compiler warnings.
+ * stack-alloc.c: Cast void* pointer to char* before doing arithmetic
+ on it.
+
+ * Makefile.in (mpbsd/libmpbsd.a): New rule.
+ * configure.in (configdirs): Add mpbsd.
+
+ * gmp.h: Add declarations for a few missing mpn functions.
+
+ * Makefile.in (libmp.a): New rule.
+
+ * mpbsd/mdiv.c: #include "dmincl.c", not "mpz_dmincl.c"
+ * gmp.h: Move #define of __GNU_MP__ into the `#if __GNU_MP__' block.
+ * mp.h: Likewise. Update typedefs from gmp.h.
+ * mpbsd/configure.in: New file.
+ * mpbsd/Makefile.in: New file.
+ * mpbsd/configure: Link to master configure.
+ * mpbsd/config.sub: Link to master config.sub.
+
+ * Makefile.in: Set RANLIB_TEST.
+ * (libgmp.a): Use it.
+ * (libgmp.a): Do ranlib before moving the libgmp.a to the build
+ directory.
+ * mp?/Makefile.in: Don't use or set RANLIB.
+
+Thu Feb 15 16:38:41 1996 Torbjorn Granlund <tege@tmg.se>
+
+ * mpz/add_ui.c: MP_INT => mpz_t.
+ * mpz/cmp_ui.c: Likewise.
+ * mpz/fac_ui.c: Likewise.
+ * mpz/inp_binary.c: Likewise.
+ * mpz/inp_raw.c: Likewise.
+ * mpz/legendre.c: Likewise.
+ * mpz/jacobi.c: Likewise.
+ * mpz/out_binary.c: Likewise.
+ * mpz/out_raw.c: Likewise.
+ * mpz/random2.c: Likewise.
+ * mpz/random.c: Likewise.
+ * mpz/realloc.c: Likewise.
+
+ * mpz/legendre.c: __mpz_2factor(X) => mpz_scan1(X,0),
+ __mpz_odd_less1_2factor => mpz_scan1(X,1).
+ * mpz/ntsup.c: File deleted.
+ * mpz/Makefile.in: Corresponding changes.
+
+ * mpz/pprime_p: Use mpz_scan1 to avoid looping.
+
+ * mpz/fac_ui.c: Type of `k' and `p' is `unsigned long'.
+ * mpz/pprime_p.c: Pass long to *_ui functions.
+ * mpz/gcdext.c: Likewise.
+ * mpz/fdiv_r_2exp.c: Likewise.
+ * mpz/fac_ui.c: Likewise.
+
+ * mpz/powm.c: Don't use mpn_rshift when mod_shift_cnt is 0.
+
+ * mpz/tests/Makefile.in (st-sqrtrem): Fix typo.
+
+ * mpz/cmp_ui.c: #undef mpz_cmp_ui.
+ * mpz/cmp_si.c: #undef mpz_cmp_si.
+ * gmp.h (mpz_cmp_ui): New #define.
+ (mpz_cmp_si): New #define.
+
+Wed Feb 14 22:11:24 1996 Torbjorn Granlund <tege@tmg.se>
+
+ * gmp.h: Test __cplusplus in addition to __STDC__.
+ * gmp-impl.h: Likewise.
+
+ * gmp.h: Surround declarations with extern "C" { ... }.
+
+Tue Feb 13 15:20:45 1996 Torbjorn Granlund <tege@tmg.se>
+
+ * mpz/fdiv_r_2exp.c: Use MPN_NORMALIZE.
+ * mpz/tdiv_r_2exp.c: Likewise.
+
+ * mpz/fdiv_r_2exp.c: New file.
+ * mpz/fdiv_q_2exp.c: New file.
+ * mpz/tdiv_r_2exp.c: Renamed from mpz/mod_2exp.c.
+ * mpz/tdiv_q_2exp.c: Renamed from mpz/div_2exp.c
+ * mpz/Makefile.in: Corresponding changes.
+
+ * mpz/scan0.c,scan1.c: New files.
+ * mpz/Makefile.in: Compile them.
+
+ * gmp.h (mpn_normal_size): Delete.
+
+ * config.guess: Update from Cygnus version.
+
+ * mpn/m68k/rshift.S: Use INSN2 macro for lea instructions.
+ * mpn/m68k/lshift.S: Likewise.
+
+ * mpn/configure.in: Fix configuration for plain 68000.
+
+Mon Feb 12 01:06:06 1996 Torbjorn Granlund <tege@tmg.se>
+
+ * mpz/tests/t-powm.c: Generate negative BASE operand.
+
+ * mpz/powm.c: Make result always positive.
+
+Sun Feb 11 01:44:56 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * mpz/tests/*.c: Add t- prefix.
+ * mpz/tests/Makefile.in: Corresponding changes.
+ * mpz/tests/configure.in: Update srctrigger.
+
+ * mpz/tests/gcd.c: Generate negative operands.
+ * mpz/tests/gcd2.c: Likewise.
+
+ * mpz/gcdext.c: At end, if G is negative, negate all G, S, and T.
+
+Thu Feb 8 17:16:12 UTC 1996 Ken Weber <kweber@mat.ufrgs.br>
+
+ * mp{z,n}/gcd.c: Change mpn_gcd interface.
+ * gmp.h: Ditto.
+ * gmp.texi: update documentation.
+
+Mon Feb 7 23:58:43 1996 Andreas Schwab <schwab@informatik.uni-dortmund.de>
+
+ * mpn/m68k/{lshift,rshift}.S: New files.
+ * mpn/m68k/syntax.h: New ELF_SYNTAX macros.
+ (MEM_INDX, R, PROLOG, EPILOG): New macros.
+ * mpn/m68k/*.S: Use R macro with register name. Use PROLOG and EPILOG
+ macros. Rename `size' to `s_size' or s1_size to avoid clash with ELF
+ .size directive.
+ * mpn/configure.in: New target m68k-*-linux*.
+
+Wed Feb 7 07:41:31 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * Makefile.in (cre-conv-tab): Workaround for SunOS make.
+
+ * mpz/tests/reuse.c: New file.
+ * mpz/tests/Makefile.in: Handle reuse.c.
+
+Tue Feb 6 11:56:24 UTC 1996 Ken Weber <kweber@mat.ufrgs.br>
+
+ * mpz/gcd.c: Fix g->size when one op is 0 and g == other op.
+
+Tue Feb 6 01:36:39 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * gmp.h (mpz_divexact): Delete parameter names.
+ (mpz_lcm): Delete spurious declaration.
+
+ * mpz/dmincl.c: Fix typo.
+
+Mon Feb 5 01:11:56 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * mpn/generic/gcd.c (gcd_2): Declare consistently.
+
+ * mpz/tdiv_q.c: Optimize division by a single-limb divisor.
+ * mpz/dmincl.c: Likewise.
+
+ * mpz/add.c: Use MPN_NORMALIZE instead of mpn_normal_size.
+ * mpz/sub.c: Likewise.
+ * mpn/generic/sqrt.c: Likewise.
+
+ * mpn/tests/{add_n,sub_n,lshift,rshift}.c: Put garbage in the
+ destination arrays.
+
+Fri Feb 2 02:21:27 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * mpz/{jacobi.c,legendre.c,ntsup.c,invert.c}: New files.
+ * mpz/Makefile.in: Compile them.
+
+ * mpn/Makefile.in (INCLUDES): Don't search in `generic'.
+
+Thu Feb 1 02:15:11 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ Change from Ken Weber:
+ * mpz/divexact.c: Make it work when quot is identical to either input.
+
+ * mpf/ui_sub.c: New file.
+ * mpf/Makefile.in: Compile it.
+
+ * gmp-impl.h (MPZ_TMP_INIT): alloca -> TMP_ALLOC.
+ * mpz/{c,f}div_{q,qr,r}.c: Use TMP_DECL/TMP_MARK/TMP_FREE since
+ these use MPZ_TMP_INIT.
+ * mpz/mod.c: Likewise.
+ * mpq/{add,sub}.c: Likewise.
+ * mpq/canonicalize: Likewise.
+
+ * mpq/{add,sub,mul,div}.c: Use mpz_divexact. MP_INT -> mpz_t.
+ * mpq/canonicalize.c: Likewise.
+
+Wed Jan 31 01:45:00 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * mpn/generic/gcd.c: Misc changes from Ken.
+
+ * mpz/tests/gcd2.c: New file.
+ * mpz/tests/Makefile.in: Handle gcd2.c.
+
+ * mpn/generic/gcd.c (mpn_gcd): When GCD == ORIG_V, return vsize,
+ not orig_vsize. Fix parameter declaration.
+
+ * mpz/mod_ui.c: Delete file.
+ * mpz/Makefile.in: Don't try to compile mod_ui.
+
+ * mpz/cdiv_*_ui.c): Make them work right.
+ * gmp.h: Declare cdiv*.
+
+Tue Jan 30 02:22:56 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * mpz/{cdiv_q.c,cdiv_q_ui.c,cdiv_qr.c,cdiv_qr_ui.c,cdiv_r.c,
+ cdiv_r_ui.c,cdiv_ui.c}: New files.
+ * mpz/Makefile.in: Compile them.
+
+ * All files: Make file permissions right.
+
+ Changes from Ken Weber:
+ * mpn/generic/accelgcd.c: Delete.
+ * mpn/generic/bingcd.c: Delete.
+ * mpn/generic/numbits.c: Delete.
+ * mpn/generic/gcd.c: New file.
+ * mpn/configure.in (functions): Update accordingly.
+ * mpz/divexact.c: New file.
+ * mpz/Makefile.in: Compile divexact.c.
+ * mpz/gcd.c: Rewrite to accommodate for gcd changes in mpn.
+ * gmp.h: declare new functions, delete obsolete declarations.
+ * mpz/tests/dive.c: New file.
+ * mpz/tests/Makefile.in: Handle dive.c.
+
+Mon Jan 29 03:53:24 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * mpz/random.c: Handle negative SIZE parameter.
+
+ * mpz/tests/tdiv(_ui).c: New name for tst-dm(_ui).c.
+ * mpz/tests/tst-mdm(_ui).c: Delete.
+ * mpz/tests/fdiv(_ui).c: New test based in tst-mdm(_ui).
+ * mpz/tests/*.c: Get rid of tst- prefix for DOS 8+3 naming.
+ * mpz/tests/Makefile.in: Corresponding changes.
+ * mpz/tests/configure.in: Update srctrigger.
+
+ * mpn/generic/divmod.c: Update from divrem.
+ * mpn/generic/divrem.c: Misc cleanups.
+
+Sun Jan 28 03:25:08 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * All files: Use new TMP_ALLOC interface.
+
+ * mpz/powm_ui.c: Make Jan 25 changes to powm.c also here.
+
+ * mpz/tests/powm_ui.c: New file.
+ * mpz/tests/Makefile.in: Add rules for tst-powm and tst-powm_ui.
+
+ * Makefile.in: Update dependency list.
+ * mpf/Makefile.in: Likewise.
+ * mpz/Makefile.in: Likewise.
+ * mpq/Makefile.in: Likewise.
+ * Makefile.in: Set RANLIB simply to ranlib, and allow configure
+ to override it.
+
+ * mpz/Makefile.in (conf): Delete spurious target.
+ (mp_bases.c): Delete.
+ (cre-conv-tab rules): Delete.
+
+ * Makefile.in (cre-conv-tab): Greatly simplify.
+
+Sat Jan 27 13:38:15 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * stack-alloc.c: New file.
+ * stack-alloc.h: New file.
+
+ * gmp.h (__gmp_inline): Define using __inline__.
+
+Thu Jan 25 00:28:37 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * mpn/generic/scan0.c: New file.
+ * mpn/generic/scan1.c: Renamed from next_bit.c.
+ * mpn/configure.in (functions): Include scan0 and scan1.
+
+ * mpn/m68k/*: #include sysdep.h. Use C_GLOBAL_NAME.
+
+ * configure: Update from Cygnus version.
+ * config.guess: Likewise.
+ * config.sub: Likewise.
+ * configure: Pass --nfp to recursive configures.
+
+ * mpz/tests/tst-*.c: Adjust SIZE and reps.
+
+ * mpz/powm.c: Move esize==0 test earlier.
+ In final reduction of rp,rsize, don't call mpn_divmod unless
+ reduction is really needed.
+
+ * mpz/tests/tst-powm.c: Fix thinko in checking code.
+
+ * All files: Get rid of `__' prefix from mpn_* calls and declarations.
+ * gmp.h: #define __MPN.
+ * gmp.h: Use __MPN in #defines for mpn calls.
+
+ * mpn/generic/mul_n.c: Prepend `i' to internal routines.
+ * gmp-impl.h: Add #defines using __MPN for those internal routines.
+
+ * mpn/generic/sqrt.c: Change call to mpn_mul to mpn_mul_n.
+
+Wed Jan 24 13:28:19 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * mpn/sparc32/udiv_fp.S: New name for udiv_qrnnd.S.
+ * mpn/sparc32/udiv_nfp.S: New name for v8/udiv_qrnnd.S.
+ * mpn/sparc32/v8/supersparc: New directory.
+ * mpn/sparc32/v8/supersparc/udiv.S: New file.
+
+Tue Jan 23 01:10:11 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ This major contribution is from Ken Weber:
+ * mpn/generic/accelgcd.c: New file.
+ * mpn/generic/bdivmod.c: New file.
+ * mpn/generic/bingcd.c: New file.
+ * mpn/generic/gcd_1.c: Rewrite.
+ * mpn/generic/numbits.c: New file (to go away soon).
+ * mpz/gcd.c: Rewrite.
+ * mpz/tests/tst-gcd.c (SIZE): Now 128.
+ * gmp.h: Declare new functions.
+ * mpn/configure.in (functions): List new files.
+ * gmp-impl.h (MPN_SWAP): Delete.
+ (MPN_LESS_BITS_LIMB, MPN_LESS_BITS, MPN_MORE_BITS): Delete.
+ (MPN_COMPL_INCR, MPN_COMPL): Delete.
+
+Mon Jan 22 02:04:59 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * gmp.h (mpn_name): New #define.
+
+ * mpn/m88k/mc88110/addmul_1.s: New file.
+ * mpn/m88k/mc88110/add_n.S: New file.
+ * mpn/m88k/mc88110/sub_n.S: New file.
+
+ * mpn/m88k/sub_n.s: Correctly initialize carry.
+
+ * mpn/sparc32/{add_n.S,sub_n.S,lshift.S,rshift.S): `beq' => `be'.
+
+Sun Jan 21 00:04:35 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * mpn/sparc64/addmul_1.s: New file.
+ * mpn/sparc64/submul_1.s: New file.
+ * mpn/sparc64/rshift.s: New file.
+
+Sat Jan 20 00:32:54 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * mpz/iset.c: Fix typo introduced Dec 25.
+
+Wed Jan 17 13:16:44 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * config/mt-sprc8-gcc: New name for mt-sparc8-gcc.
+ * config/mt-sparcv8-gcc: Delete.
+ * configure.in: Corresponding changes.
+
+Tue Jan 16 16:31:01 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * gmp-impl.h: #include alloca.h when necessary.
+
+ * longlong.h: Test __alpha instead of __alpha__, since the former
+ is the standard symbol.
+
+Mon Jan 15 18:06:57 1996 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * mpn/sparc64/mul_1.s: Swap operands of mulx instructions.
+ * mpn/sparc64/lshift.s: New file.
+
+Fri Dec 29 17:34:03 1995 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * mpn/x86/pentium/add_n.S: Get rid of #defines for register names.
+ * mpn/x86/pentium/sub_n.S: Likewise.
+
+Thu Dec 28 03:16:57 1995 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * mpn/x86/pentium/mul_1.S: Rework loop to avoid AGI between update
+ of loop induction variable and load insn at beginning of loop.
+ * mpn/x86/pentium/addmul_1.S: Likewise.
+ * mpn/x86/pentium/submul_1.S: Likewise.
+
+Mon Dec 25 23:22:55 1995 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * All files: Prefix user-visible structure fields with _mp_.
+
+Fri Dec 22 20:42:17 1995 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * mpn/configure.in (m68k configs): Terminate path variable with
+ plain "m68k".
+
+Fri Dec 22 03:29:33 1995 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * mpn/sparc32/add_n.S: Update from sub_n.S to fix bugs, and to
+ clean things up.
+
+ * mpn/configure.in (m68k configs): Update #include path for new
+ mpn directory organization.
+
+Tue Dec 12 02:53:02 1995 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * gmp.h: Prefix all structure field with _mp_.
+ * gmp-impl.h: Define access macros for these fields.
+
+Sun Dec 10 00:47:17 1995 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * mpn/alpha/addmul_1.s: Prefix labels with `.'.
+ * mpn/alpha/submul_1.s: Likewise.
+ * mpn/alpha/[lr]shift.s: Likewise.
+ * mpn/alpha/udiv_qrnnd.S: Likewise.
+ * mpn/alpha/ev5/[lr]shift.s: Likewise.
+
+ * mpn/alpha/ev5/lshift.s: Fix typos.
+
+Fri Dec 1 14:28:20 1995 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * mpn/Makefile.in (.SUFFIXES): Define.
+
+Wed Nov 29 23:11:57 1995 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * mpn/sparc64/{add_n.s, sub_n.s}: New files.
+
+Tue Nov 28 06:03:13 1995 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * mpn/x86/syntax.h: Handle ELF_SYNTAX.
+ Rename GAS_SYNTAX => BSD_SYNTAX.
+
+ * mpn/configure.in: Handle linuxelf and SysV for x86 variants.
+
+Mon Nov 27 01:32:12 1995 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * mpn/hppa/hppa1_1/pa7100/submul_1.S: New file.
+
+Sun Nov 26 04:30:47 1995 Torbjorn Granlund <tege@noisy.tmg.se>
+
+ * mpn/hppa/hppa1_1/pa7100/addmul_1.S: New file.
+
+ * mpn/sparc32/add_n.S: Rewrite to use 64 bit loads/stores.
+ * mpn/sparc32/sub_n.S: Likewise.
+
+Fri Nov 17 00:18:46 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpn/configure.in: Handle m68k on NextStep.
+
+Thu Nov 16 02:30:26 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpn: Reorganize machine-specific directories.
+ * mpn/configure.in: Corresponding changes.
+ (sh, sh2): Handle these.
+ (m68k targets): Create asm-syntax.h.
+
+Thu Nov 9 02:20:50 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpn/generic/mul_n.c (____mpn_sqr_n): Delete code that calls abort.
+ (____mpn_mul_n): Likewise.
+
+Tue Nov 7 03:25:12 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpf/get_str.c: In exponentiation code (two places), don't swap
+ input and output areas when calling mpn_mul_1.
+ * mpf/set_str.c: Likewise.
+
+Fri Nov 3 02:35:58 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpf/Makefile.in: Make sure all objects are listed in dependency list;
+ delete spurious entries.
+
+ * mpf/mul.c: Handle U or V being 0. Allow prec+1 for result precision.
+
+ * mpf/set_prec.c: New computation of limb precision.
+ * mpf/set_dfl_prec.c: Likewise.
+
+ * mpf/random2.c: Fix typo computing exp.
+ * mpf/get_str.c: In (uexp > usize) case, set n_limbs as a function of
+ the user-requested number of digits, n_digits.
+
+Thu Nov 2 16:25:07 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpn/generic/divrem.c (case 2): Don't move np vector back, it is
+ never read.
+ (default case): Put most significant limb from np in new variable n2;
+ decrease size argument for MPN_COPY_DECR; use n2 instead of np[dsize].
+
+Wed Nov 1 02:59:53 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpn/sparc/[lr]shift.S: New files.
+
+Tue Oct 31 00:08:12 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpz/gcd_ui.c: Set w->size unconditionally when v is zero.
+
+ * gmp-impl.h (assert): Delete definition.
+
+ * mpf/sub.c: Delete all assert calls. Delete variable `cy'.
+
+ * mpf/neg.c: Use prec+1 as precision. Optimize for when arguments
+ are the same.
+ * mpf/abs.c: Likewise.
+ * mpf/{set,neg,abs}.c: Make structure and variable names similar.
+
+Mon Oct 30 12:45:26 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpf/random2.c (random): Test __SVR4 in addition to __svr4__.
+ * mpn/generic/random2.c (random): Likewise.
+
+Sun Oct 29 01:54:28 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpf/div.c: Special handle U or V being 0.
+
+ * mpf/random2.c: New file.
+
+ * longlong.h (i860 rshift_rhlc): Define.
+ (i960 udiv_qrnnd): Define.
+ (i960 count_leading_zeros): Define.
+ (i960 add_ssaaaa): Define.
+ (i960 sub_ddmmss): Define.
+ (i960 rshift_rhlc): Define.
+
+Sat Oct 28 19:09:15 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpn/pentium/rshift.S: Fix and generalize condition for when to use
+ special code for shift by 1.
+ * mpn/pentium/lshift.S: Likewise.
+
+Thu Oct 26 00:02:56 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * gmp.h: #undef __need_size_t.
+ * mp.h: Update from gmp.h.
+
+Wed Oct 25 00:17:27 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpf/Makefile.in: Compile set_prec.c.
+ * mpf/realloc.c: Delete this file.
+ * mpf/Makefile.in: Delete mentions of realloc.c.
+
+ * gmp.h (__mpf_struct): Get rid of `alloc' field.
+ * mpf/clear.c: Likewise.
+ * mpf/init*.c: Likewise.
+ * mpf/set_prec.c: Likewise.
+ * mpf/iset*.c: Likewise.
+
+ * mpf/iset_str.c: New file.
+
+ * mpn/configure.in: Handle pyramid.
+
+ * mpf/set.c: Use prec+1 as precision.
+
+ * mpf/set_prec.c: New file.
+
+Tue Oct 24 00:56:41 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpn/generic/divrem.c: New file. Will replace mpn/generic/divmod.c
+ when rest of source is converted.
+ * mpn/configure.in (functions): Add `divrem'
+ * mpn/generic/set_str.c: Never call __mpn_mul_1 with zero size.
+
+ * mpf/get_str.c: Completely rewritten.
+ * mpf/add.c: Fix several problems.
+ * mpf/sub.c: Compare operands from most significant end until
+ first difference, exclude skipped limbs from computation.
+ Accordingly simplify normalization code.
+ * mpf/set_str.c: Fix several problems.
+ * mpf/dump.c: New file.
+ * mpf/Makefile.in: Compile dump.c.
+ * mpf/init2.c: Set prec field correctly.
+
+Sun Oct 22 03:02:09 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * cre-conv-tab.c: #include math.h; don't declare log and floor.
+
+Sat Oct 21 23:04:10 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpf/mul_ui.c: Handle U being 0.
+
+Wed Oct 18 19:39:27 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpn/generic/set_str.c: Correctly handle input like "000000000000".
+ Misc cleanups.
+
+Tue Oct 17 15:14:13 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * longlong.h: Define COUNT_LEADING_ZEROS_0 for machines where
+ appropriate.
+
+Mon Oct 16 19:14:43 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpf/add.c: Rewrite.
+ * mpf/set_str.c: New file. Needs more work.
+
+Sat Oct 14 00:14:04 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpf/div_2exp.c: Vastly simplify.
+ * mpf/mul_2exp.c: Likewise.
+
+ * mpf/sub.c: Rewrite.
+
+ * gmp-impl.h (udiv_qrnnd_preinv2gen): Terminate comment.
+
+ * mpf/dump.c: Free allocated memory.
+
+ * gmp-impl.h (assert): Define.
+
+Wed Oct 11 13:31:00 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpn/pentium/rshift.S: Install new code to optimize shift-by-1.
+
+Tue Oct 10 00:37:21 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpn/pentium/lshift.S: Install new code to optimize shift-by-1.
+
+ * mpn/powerpc32/{lshift.s,rshift.s}: New files.
+
+ * configure.in: Fix typo.
+
+Sat Oct 7 08:17:09 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * longlong.h (smul_ppmm): Correct type of __m0 and __m1.
+
+Wed Oct 4 16:31:28 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpn/configure.in: Handle alphaev5.
+ * mpn/ev4: New name for alpha subdir.
+ * mpn/ev5: New subdir.
+ * mpn/ev5/lshift.s: New file.
+
+Tue Oct 3 15:06:45 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpn/alpha/mul_1.s: Avoid static increments of pointers; use
+ corresponding offsets in ldq and stq instructions instead.
+ (Loop): Swap cmpult and stq to save one cycle on EV5.
+
+ * mpn/tests/{add_n.s,sub_n.s,lshift.s,rshift.s,mul_1.s,addmul_1.s,
+ submul_1.s}: Don't check results if NOCHECK is defined.
+
+Mon Oct 2 11:40:18 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * longlong.h (mips umul_ppmm [32 and 64 bit versions]):
+ Make new variants, based on GCC version number, that use `l' and `h'
+ constraints instead of explicit mflo and mfhi instructions
+
+Sun Oct 1 00:17:47 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpn/mc88100/add_n.s: Decrease unrolling factor from 16 to 8.
+ * mpn/mc88100/sub_n.s: Likewise.
+
+ * config/mt-m88110: New file.
+ * configure.in: Use it.
+
+ * mpn/mc88110/mul_1.s: Fix thinko.
+
+Sat Sep 30 21:28:19 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpz/set_d.c: Declare `size' at function start.
+
+ * experimental: New directory for mpx and mpz2.
+
+ * mpz/tdiv_q.c: Clarify comments.
+ * mpz/{mod.c,mod_ui.c}: New file, for math mod function.
+
+ * mpn/sh2/{mul_1.s,addmul_1.s,submul_1.s}: New files.
+
+ * mpn/sh/{add_n.s,sub_n.s}: New files.
+
+ * mpn/pyr/{add_n.s,sub_n.s,mul_1.s,addmul_1.s}: New files.
+
+ * mpn/i960/{add_n.s,sub_n.s}: New files.
+
+ * mpn/alpha/addmul_1.s (Loop): Move decrement of r18 to before umulh,
+ to save cycles on EV5.
+ * mpn/alpha/submul_1.s: Ditto.
+ * mpn/alpha/mul_1.s: Ditto.
+
+Thu Sep 28 02:48:59 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * gmp.h (mp_limb, mp_limb_signed): Define as `long long' if
+ _LONG_LONG_LIMB is defined.
+
+ * longlong.h (m88110): Test __m88110__, not __mc88110__
+
+ * mpn/mc88110/mul_1.s: Rewrite.
+
+Tue Sep 26 23:29:05 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * config.sub: Update from current Cygnus version.
+
+ * mpn/configure.in: Recognize canonical m88*, not mc88*.
+
+Fri Sep 22 14:58:05 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpz/set_d.c: New file.
+ * mpz/Makefile.in: Build new files.
+
+ * mpq/get_d.c: Replace usage of scalbn with ldexp.
+
+ * mpn/{vax,i386}/gmp-mparam.h: New files.
+ * gmp-impl.h (ieee_double_extract): Define here.
+ * mpf/set_d.c (ieee_double_extract): Not here.
+
+Thu Sep 21 00:56:36 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * longlong.h (C umul_ppmm): Use UWtype, not USItype for temps.
+ (udiv_qrnnd): For cases implemented with call to __udiv_qrnnd,
+ protect with new symbol LONGLONG_STANDALONE.
+ (68000 umul_ppmm): Use %# prefix for immediate constants.
+
+Wed Sep 20 15:36:23 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpn/generic/divmod_1.c: Handle
+ divisor_limb == 1 << (BITS_PER_MP_LIMB - 1)
+ specifically also when normalization_steps != 0.
+
+Mon Sep 18 15:42:30 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpq/get_d.c: New file.
+
+Sun Sep 17 02:04:36 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * longlong.h (pyr): Botch up for now.
+
+Sat Sep 16 00:11:50 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpn/clipper/mul_1.s: New file.
+ * mpn/clipper/add_n.s: New file.
+ * mpn/clipper/sub_n.s: New file.
+ * mpn/configure.in: Handle clipper*-*-*.
+
+ * mpn/configure.in: Recognize rs6000-*-*.
+
+Fri Sep 15 00:41:34 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpn/alpha/add_n.s: New file.
+ * mpn/alpha/sub_n.s: New file.
+
+ * mpn/mips3: New name for mpn/r4000.
+ * mpn/mips2: New name for mpn/r3000.
+ * mpn/configure.in: Corresponding changes.
+
+ * mpn/generic/perfsqr.c (primes): Delete.
+ (residue_map): Delete.
+
+Thu Sep 14 00:07:58 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpn/r3000/sub_n.s: Fix typo.
+
+ * dm_trunc.c: Delete spurious file.
+
+ * mpz/out_binary.c: Fix typo.
+
+ * mpn/configure.in (per-target): Make mips*-*-irix6* imply r4000.
+
+ * gmp-impl.h: For sparc and sgi, include alloca.h.
+
+ * mpn/z8000/mul_1.s: Replace `test r' with `and r,r'. Replace
+ `ldk r,#0' with `xor r,r'.
+
+Wed Sep 6 00:58:38 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpz/inp_binary.c: New file.
+ * mpz/out_binary.c: New file.
+ * mpz/Makefile.in: Build new files.
+
+Tue Sep 5 22:53:51 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * gmp.h (__mpz_struct): Change `long int' => `mp_size_t' for alloc
+ and size fields.
+
+Sat Sep 2 17:47:59 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpn/r4000/{add_n.s,sub_n.s}: Optimize away some pointer arithmetic.
+ * mpn/r3000/{add_n.s,sub_n.s,lshift.s,rshift.s}: New files,
+ derived from r4000 code.
+
+Fri Sep 1 05:35:52 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpn/r3000/mul_1.s: Fix typo.
+
+ * mpn/powerpc32: Fix some old vs new mnemonic issues.
+
+ * mpn/powerpc32/{add_n.s,sub_n.s}: New files.
+ * mpn/r4000/{add_n.s,sub_n.s,lshift.s,rshift.s}: New files.
+
+Wed Aug 30 10:43:47 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpn/r3000/mul_1.s ($LC1): Use addiu for immediate add.
+ * mpn/r4000/{mul_1.s,addmul_1.s,submul_1.s}: New files.
+
+ * config.guess: Update to latest FSF revision.
+
+Mon Aug 28 02:18:13 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpz/out_str.c: Cast str to char * in fputs call.
+
+ * gmp-impl.h: Define UQItype, SItype, and USItype also
+ when not __GNUC__.
+
+Fri Aug 25 01:45:04 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpn/i386/syntax.h: Renamed from asm-syntax.h.
+ * mpn/mc68020/syntax.h: Renamed from asm-syntax.h.
+ * mpn/configure.in: Corresponding changes.
+
+Sun Aug 13 19:20:04 1995 Torbjorn Granlund <tege@bozo.tmg.se>
+
+ * mpn/generic/random2.c: Test __hpux, not hpux.
+
+Sat Apr 15 20:50:33 1995 Torbjorn Granlund (tege@tiny.cygnus.com)
+
+ * mpn/sparc/add_n.S: Make it work for PIC.
+ * mpn/sparc/sub_n.s: Likewise.
+ * mpn/sparc8/addmul_1.S: Likewise.
+ * mpn/sparc8/mul_1.S: Likewise.
+ * mpn/i386/add_n.S: Likewise.
+ * mpn/i386/sub_n.S: Likewise.
+
+Thu Apr 13 23:15:03 1995 Torbjorn Granlund (tege@tiny.cygnus.com)
+
+ * mpn/configure.in: Don't search power subdir for generic ppc configs.
+ Add some ppc cpu-specific configs. Misc clean up.
+
+Mon Apr 10 00:16:35 1995 Torbjorn Granlund (tege@tiny.cygnus.com)
+
+ * mpz/ui_pow_ui.c: Delete spurious code to handle negative results.
+
+Sun Apr 9 12:38:11 1995 Torbjorn Granlund (tege@tiny.cygnus.com)
+
+ * longlong.h (SPARC v8 udiv_qrnnd): Generate remainder in C,
+ not in asm.
+
+ * mpn/generic/sqrt.c (SQRT): Test for __SOFT_FLOAT.
+
+Tue Mar 28 00:19:52 1995 Torbjorn Granlund (tege@tiny.cygnus.com)
+
+ * mpn/generic/hamdist.c (popc_limb): Make Mar 16 change here too.
+
+Fri Mar 17 23:29:22 1995 Torbjorn Granlund (tege@tiny.cygnus.com)
+
+ * longlong.h (SH umul_ppmm): Define.
+
+Thu Mar 16 16:40:44 1995 Torbjorn Granlund (tege@tiny.cygnus.com)
+
+ * mpn/generic/popcount.c (popc_limb): Rearrange 32 bit case
+ to help CSE.
+
+Fri Mar 10 20:03:49 1995 Torbjorn Granlund (tege@tiny.cygnus.com)
+
+ * mpn/powerpc32/mul_1.s: Clear cy before entering loop.
+ Rearrange loop to save a cycle.
+ * mpn/powerpc32/addmul_1.s: New file.
+ * mpn/powerpc32/submul_1.s: New file.
+
+Fri Feb 17 22:44:45 1995 Torbjorn Granlund (tege@tiny.cygnus.com)
+
+ * mpn/configure.in: Set target_makefile_frag for freebsd
+ in new case stmt.
+ * mpn/config/t-freebsd: New file.
+ * mpn/Makefile.in: Add #### for frag insertion.
+ (XCFLAGS): Clear by default.
+ (.c.o, .S.o rules): Pass XCFLAGS.
+
+Tue Feb 7 16:27:50 1995 Torbjorn Granlund (tege@tiny.cygnus.com)
+
+ * longlong.h (68000 umul_ppmm): Merge improvements from henderson.
+
+Tue Jan 24 04:23:20 1995 Torbjorn Granlund (tege@tiny.cygnus.com)
+
+ * longlong.h (default umul_ppmm): Store input parameters in temporaries
+ to avoid reading them twice.
+ (default smul_ppmm): New definition.
+
+Thu Dec 29 04:20:07 1994 Jim Meyering (meyering@comco.com)
+
+ * generic/perfsqr.c (__mpn_perfect_square_p): Remove declaration
+ of unused variable.
+ * generic/pre_mod_1.c (__mpn_preinv_mod_1): Likewise.
+ * mpz/powm.c (pow): Likewise.
+
+ * mpz/and.c (mpz_and): Use {} instead of `;' for empty else clause
+ to placate `gcc -Wall'.
+ * mpz/ior.c (mpz_ior): Likewise.
+
+Wed Dec 28 13:31:40 1994 Torbjorn Granlund (tege@tiny.cygnus.com)
+
+ * mpn/m*68*/*.S: #include asm-syntax.h, not asm.h.
+
+Mon Dec 26 17:15:36 1994 Torbjorn Granlund (tege@tiny.cygnus.com)
+
+ * longlong.h: Test for more symbols, in __mc68000__ case.
+
+ * mpn/mpn/config.sub: Recognize m68060.
+ * mpn/configure.in: Change mc* to m* for 68k targets.
+ * mpn/Makefile.in (.S.o): Delete spurious creation of temp .c file.
+
+Mon Dec 19 01:56:30 1994 Torbjorn Granlund (tege@tiny.cygnus.com)
+
+ * config.sub: Recognize pentium as a valid CPU.
+ * mpn/configure.in: Handle pentium specifically, to use new assembly
+ code.
+
+Mon Dec 19 00:13:01 1994 Jim Meyering (meyering@comco.com)
+
+ * gmp.h: Define _GMP_H_HAVE_FILE if FILE, __STDIO_H__, or H_STDIO
+ is defined.
+ * gmp.h: test _GMP_H_HAVE_FILE instead of FILE everywhere else.
+
+Mon Dec 19 00:04:54 1994 Kent Boortz (boortz@sics.se)
+
+ * Makefile.in (recursive makes): Pass CFLAGS.
+
+Sun Dec 18 22:34:49 1994 Torbjorn Granlund (tege@tiny.cygnus.com)
+
+ * mpn/pentium: New directory.
+
+ * mpz/pprime.c: Make sure to mpz_clear all temporaries.
+
+ * longlong.h: Don't use udiv instruction when SUPERSPARC is defined.
+ * configure.in: Handle supersparc*-.
+ * config/mt-supspc-gcc: New file.
+ * config/mt-sparc8-gcc: New name for mt-sparcv8-gcc.
+
+Mon Dec 12 22:22:10 1994 Torbjorn Granlund (tege@tiny.cygnus.com)
+
+ * mpn/i386/*.S: #include "asm-syntax.h", not "asm.h".
+ #include sysdep.h before asm-syntax.h.
+
+ * mpn/mc68020/asm-syntax.h: #undef ALIGN before defining it.
+ * mpn/i386/asm-syntax.h: Likewise.
+
+ * mpn/mc68020/asm-syntax.h: New name for asm.h.
+ * mpn/i386/asm-syntax.h: New name for asm.h.
+
+Tue Dec 6 21:55:25 1994 Torbjorn Granlund (tege@tiny.cygnus.com)
+
+ * mpz/array_init.c: Fix typo in declaration.
+
+Fri Nov 18 19:50:52 1994 Torbjorn Granlund (tege@tiny.cygnus.com)
+
+ * mpn/Makefile.in (.S.o): Pass CFLAGS and INCLUDES.
+
+Mon Nov 14 00:34:12 1994 Torbjorn Granlund (tege@tiny.cygnus.com)
+
+ * mpn/generic/random2.c (random): Test for __svr4__.
+
+Wed Oct 12 23:28:16 1994 Torbjorn Granlund (tege@tiny.cygnus.com)
+
+ * cre-conv-tab.c (main): Avoid upper-case X in printf format string.
+
+Tue Aug 23 17:16:35 1994 Torbjorn Granlund (tege@tiny.cygnus.com)
+
+ * mpz/perfsqr.c: Use mpn_perfect_square_p.
+ * mpn/generic/perfsqr.c: New file.
+
+Wed Jul 6 13:46:51 1994 Torbjorn Granlund (tege@tiny.cygnus.com)
+
+ * mpz/array_init.c: New file.
+ * mpz/Makefile.in: Compile array_init.
+ * gmp.h: Declare mpz_array_init.
+
+Mon Jul 4 01:10:03 1994 Torbjorn Granlund (tege@tiny.cygnus.com)
+
+ * mpz/add.c: Fix bogus comment.
+ * mpz/sub.c: Likewise.
+
+Sat Jul 2 02:14:56 1994 Torbjorn Granlund (tege@adder.cygnus.com)
+
+ * mpn/generic/pre_mod_1.c: New file.
+ * mpz/perfsqr.c: Use __mpn_preinv_mod_1 when faster.
+
+Fri Jul 01 22:10:19 1994 Richard Earnshaw (rwe11@cl.cam.ac.uk)
+
+ * longlong.h (arm umul_ppmm): Fix typos in last change. Mark
+ hard-coded registers with "%|"
+
+Thu Jun 30 03:59:33 1994 Torbjorn Granlund (tege@tiny.cygnus.com)
+
+ * mpz/perfsqr.c: Define PP, etc, for machines with 64 bit limbs.
+ Use __mpn_mod_1.
+ * mpz/perfsqr.c: Don't clobber REM in quadratic residue check loop.
+
+Wed Jun 29 18:45:41 1994 Torbjorn Granlund (tege@adder.cygnus.com)
+
+ * mpn/generic/sqrt.c (SQRT): New asm for IBM POWER2.
+
+ * mpz/gcd_ui.c: Return 0 if result does not fit an unsigned long.
+
+ * gmp.h: Use "defined (__STDC__)" consistently.
+
+Tue Jun 28 18:44:58 1994 Torbjorn Granlund (tege@adder.cygnus.com)
+
+ * gmp.h (mpz_get_si): Don't use "signed" keyword for return type.
+
+ * mpz/tests/Makefile.in: Use CFLAGS for linking.
+
+ * Makefile.in (CFLAGS): Use -O2 here.
+ * mpn/Makefile (CFLAGS): Not here.
+
+ * mpq/cmp_ui.c: Fix typo.
+ * mpq/canonicalize.c: Fix typo.
+ * mpz/gcd_ui.c: Handle gcd(0,v) and gcd(u,0) correctly.
+ * mpn/generic/gcd_1.c: Fix braino in last change.
+
+Mon Jun 27 16:10:27 1994 Torbjorn Granlund (tege@rtl.cygnus.com)
+
+ * mpz/gcd_ui.c: Change return type and return result.
+ Allow destination param to be NULL.
+ * gmp.h: Corresponding change.
+ * mpn/generic/gcd_1.c: Handle zero return from mpn_mod_1.
+
+Tue Jun 14 02:17:43 1994 Torbjorn Granlund (tege@tiny.cygnus.com)
+
+ * mpn/i386/asm.h (ALIGN): Make it take a parameter.
+ * mpn/i386/*.S: Use ALIGN to align all loops.
+
+ * mpn/i386/*.S: Move colon inside C_GLOBAL_NAME expression.
+ (Makes old versions of GAS happy.)
+
+Sat May 28 01:43:54 1994 Torbjorn Granlund (tege@adder.cygnus.com)
+
+ * Many files: Delete unused variables and labels.
+ * mpn/generic/dump.c: cast printf width argument to int.
+
+Wed May 25 00:42:37 1994 Torbjorn Granlund (tege@thepub.cygnus.com)
+
+ * mpz/gcd.c (mpz_gcd): Normalize after __mpn_sub calls.
+ (xmod): Ignore return value of __mpn_divmod.
+ (xmod): Improve normalization code.
+
+Sat May 21 01:30:09 1994 Torbjorn Granlund (tege@adder.cygnus.com)
+
+ * mpz/gcdext.c: Cosmetic changes.
+
+ * mpz/fdiv_ui.c: New file.
+
+Fri May 20 00:24:53 1994 Torbjorn Granlund (tege@adder.cygnus.com)
+
+ * mpz/tests/Makefile.in: Use explicit rules for running tests,
+ not a shell loop.
+ (clean): Delete stmp-*.
+
+ * mpz/Makefile.in: Update.
+
+ * mpz/div_ui.c: Don't include longlong.h.
+ * mpz/dm_ui.c: Likewise.
+
+ * mpz/fdiv_q.c, mpz/fdiv_q_ui.c, mpz/fdiv_qr.c, mpz/fdiv_qr_ui.c,
+ mpz/fdiv_r.c, mpz/fdiv_r_ui.c: New files. Code partly from deleted
+ mdm.c, mdm_ui.c, etc, partly rewritten.
+ * mpz/dm_floor_ui.c, mpz/dm_floor.c: Delete.
+ * mpz/mdm.c, mpz/mdm_ui.c, mpz/mdiv.c, mpz/mdiv_ui.c, mpz/mmod.c,
+ mpz/mmod_ui.c: Delete.
+
+ * mpz/tdiv_q.c, mpz/tdiv_q_ui.c, mpz/tdiv_qr.c, mpz/tdiv_qr_ui.c,
+ mpz/tdiv_r.c, mpz/tdiv_r_ui.c:
+ New names for files implementing truncating division.
+ * mpz/div_ui.c, mpz/dm_ui.c, mpz/mod_ui.c: Simplify.
+
+ * mpn/Makefile.in (.S.o): Don't rely on CPP being defined, use CC
+ instead.
+ (clean): Delete tmp-*.
+
+Thu May 19 01:37:44 1994 Torbjorn Granlund (tege@adder.cygnus.com)
+
+ * mpz/cmp.c: Call __mpn_cmp.
+
+ * mpz/popcount.c: Fix typo.
+
+ * mpz/powm_ui.c: Simplify main loop. Keep principal operand size
+ smaller than MSIZE when possible.
+ * mpz/powm.c: Likewise.
+
+ * mpn/generic/sqrt.c: Move alloca calls into where the memory is
+ needed. Simplify.
+
+ * gmp.h: (_PROTO): New macro.
+ Add many function declarations; use _PROTO macro in all declarations.
+
+ * mpf/*.c: Prepend mpn calls with __.
+
+Wed May 18 20:57:06 1994 Torbjorn Granlund (tege@adder.cygnus.com)
+
+ * mpf/*ui*.c: Make ui argument `long' for consistency with mpz
+ functions.
+
+ * mpf/div_ui.c: Simplify.
+
+Tue May 17 01:05:14 1994 Torbjorn Granlund (tege@adder.cygnus.com)
+
+ * mpz/*.c: Prepend mpn calls with __.
+
+ * mpz/mul_ui.c: Use mpn_mul_1.
+
+Mon May 16 17:19:41 1994 Torbjorn Granlund (tege@adder.cygnus.com)
+
+ * mpn/i386/mul_1.S: Use C_GLOBAL_NAME.
+ * mpn/i386/mul_1.S, mpn/i386/addmul_1.S, mpn/i386/submul_1.S:
+ Nuke use of LAB.
+
+Sat May 14 14:21:02 1994 Torbjorn Granlund (tege@adder.cygnus.com)
+
+ * gmp-impl.h: Don't define abort here.
+
+ * mpz/pow_ui.c: Increase temporary allocation.
+ * mpz/ui_pow_ui.c: Likewise.
+
+ * gmp.h (mpz_add_1, mpz_sub_1): Don't call memcpy.
+
+ * All Makefile.in: Delete spurious -I arguments.
+ Update dependencies.
+
+ * mpz/popcount.c: New file.
+ * mpz/hamdist.c: New file.
+
+ * All configure: Latest version from Cygnus.
+
+ * mpq/Makefile.in: New file.
+ * mpq/configure.in: New file.
+ * Makefile.in, configure.in: Enable compilation of mpq.
+
+ * mpq/set_z.c: Fix typos.
+ * mpq/canonicalize.c: Fix typos.
+ * mpq/cmp_ui.c: Fix typos.
+
+ * mpf/add_ui.c: Read U->D into UP always. Delete spurious MPN_COPY.
+ * mpf/sub_ui.c: Likewise.
+
+ * gmp-impl.h: Don't redefine alloca.
+
+ * COPYING.LIB: Renamed from COPYING.
+
+Wed May 11 01:45:44 1994 Torbjorn Granlund (tege@adder.cygnus.com)
+
+ * mpz/powm_ui.c: When shifting E left by C+1, handle out-of-range
+ shift counts. Fix typo when testing negative_result.
+ * mpz/powm.c: Likewise.
+
+ * mpz/ui_pow_ui.c: New file.
+ * mpz/Makefile.in: Update.
+
+ * mpz/pow_ui.c: Call __mpn_mul_n instead of __mpn_mul when possible.
+
+ * mpz/div.c, mpz/div_ui.c, mpz/gcd.c: Prefix external mpn calls.
+ * mpz/gcd.c: Declare mpn_xmod.
+
+ * mpz/powm.c: Major changes to accommodate changed mpn semantics.
+ * mpz/powm_ui.c: Update from mpz/powm.c.
+
+ * mpz/tests/tst-io.c: New file.
+ * mpz/tests/tst-logic: New file.
+ * mpz/tests/Makefile.in: Update.
+
+ * mpz/inp_str.c: Get base right when checking for first digit.
+ * mpz/inp_str.c: Allocate more space for DEST when needed.
+
+ * mpz/com.c: Use mpn_add_1 and mpn_sub_1.
+ * mpz/and.c, mpz/ior.c: Likewise. Simplify somewhat.
+
+ * mpz/add_ui.c: Use mpn_add_1 and mpn_sub_1.
+ Rename parameters to be consistent with mpz/sub_ui.
+ General simplifications.
+ * mpz/sub_ui.x: Likewise.
+
+Tue Aug 10 19:41:16 1993 Torbjorn Granlund (tege@prudens.matematik.su.se)
+
+ * mpf: New directory.
+ * mpf/*.c: Merge basic set of mpf functions.
+
+ * Many logs missing...
+
+Sun Apr 25 18:40:26 1993 Torbjorn Granlund (tege@pde.nada.kth.se)
+
+ * memory.c: Use #if instead of #ifdef for __STDC__ for consistency.
+ * bsd/xtom.c: Likewise.
+
+ * mpz/div.c: Remove free_me and free_me_size and their usage.
+ Use mpn_divmod for division; corresponding changes in return value
+ convention.
+ * mpz/powm.c: `carry_digit' => `carry_limb'.
+ * bsd/sdiv.c: Clearify comment.
+
+Sun Apr 25 00:31:28 1993 Torbjorn Granlund (tege@pde.nada.kth.se)
+
+ * longlong.h (__udiv_qrnnd_c): Make all variables `unsigned long int'.
+
+Sat Apr 24 16:23:33 1993 Torbjorn Granlund (tege@pde.nada.kth.se)
+
+ * longlong.h (__udiv_qrnnd_c): Make all variables `unsigned long int'.
+
+ * gmp-impl.h: #define ABS.
+ * (Many files): Use ABS instead of abs.
+
+ * mpn/generic/sqrt.c, mpz/clrbit.c, mpz/get_si.c, mpz/mod_2exp.c,
+ mpz/pow_ui.c: Cast 1 to mp_limb before shifting.
+
+ * mpz/perfsqr.c: Use #if, not plain if for exclusion of code for
+ non-32-bit machines.
+
+Tue Apr 20 13:13:58 1993 Torbjorn Granlund (tege@du.nada.kth.se)
+
+ * mpn/generic/sqrt.c: Handle overflow for intermediate quotients by
+ rounding them down to fit.
+
+ * mpz/perfsqr.c (PP): Define in hexadecimal to avoid GCC warnings.
+
+ * mpz/inp_str.c (char_ok_for_base): New function.
+ (mpz_inp_str): Use it.
+
+Sun Mar 28 21:54:06 1993 Torbjorn Granlund (tege@cyklop.nada.kth.se)
+
+ * mpz/inp_raw.c: Allocate x_index, not xsize limbs.
+
+Mon Mar 15 11:44:06 1993 Torbjorn Granlund (tege@pde.nada.kth.se)
+
+ * mpz/pprime.c: Declare param `const'.
+ * gmp.h: Add declarations for mpz_com.
+
+Thu Feb 18 14:10:34 1993 Torbjorn Granlund (tege@pde.nada.kth.se)
+
+ * mpq/add.c, mpq/sub.c: Call mpz_clear for t.
+
+Fri Feb 12 20:27:34 1993 Torbjorn Granlund (tege@cyklop.nada.kth.se)
+
+ * mpz/inp_str.c: Recog minus sign as first character.
+
+Wed Feb 3 01:36:02 1993 Torbjorn Granlund (tege@cyklop.nada.kth.se)
+
+ * mpz/iset.c: Handle 0 size.
+
+Tue Feb 2 13:03:33 1993 Torbjorn Granlund (tege@cyklop.nada.kth.se)
+
+ * mpz/mod_ui.c: Initialize dividend_size before it's used.
+
+Mon Jan 4 09:11:15 1993 Torbjorn Granlund (tege@sics.se)
+
+ * bsd/itom.c: Declare param explicitly 'signed'.
+ * bsd/sdiv.c: Likewise.
+
+ * mpq/cmp.c: Remove unused variable tmp_size.
+ * mpz/powm_ui.c: Fix typo in esize==0 if stmt.
+ * mpz/powm.c: Likewise.
+
+Sun Nov 29 01:16:11 1992 Torbjorn Granlund (tege@sics.se)
+
+ * mpn/generic/divmod_1.c (mpn_divmod_1): Handle
+ divisor_limb == 1 << (BITS_PER_MP_LIMB - 1)
+ specifically.
+
+ * Reorganize sources. New directories mpn, mpn/MACH, mpn/generic,
+ mpz, mpq, bsd. Use full file name for change logs hereafter.
+
+Wed Oct 28 17:40:04 1992 Torbjorn Granlund (tege@jupiter.sics.se)
+
+ * longlong.h (__hppa umul_ppmm): Fix typos.
+ (__hppa sub_ddmmss): Swap input arguments.
+
+ * mpz_perfsqr.c (mpz_perfect_square_p): Avoid , before } in
+ initializator.
+
+Sun Oct 25 20:30:06 1992 Torbjorn Granlund (tege@jupiter.sics.se)
+
+ * mpz_pprime.c (mpz_probab_prime_p): Handle numbers <= 3
+ specifically (used to consider all negative numbers prime).
+
+ * mpz_powm_ui: `carry_digit' => `carry_limb'.
+
+ * sdiv: Handle zero dividend specifically. Replace most code in
+ this function with a call to mpn_divmod_1.
+
+Fri Sep 11 22:15:55 1992 Torbjorn Granlund (tege@tarrega.sics.se)
+
+ * mpq_clear: Don't free the MP_RAT!
+
+ * mpn_lshift, mpn_rshift, mpn_rshiftci: Remove `long' from 4:th arg.
+
+Thu Sep 3 01:47:07 1992 Torbjorn Granlund (tege@jupiter.sics.se)
+
+ * All files: Remove leading _ from mpn function names.
+
+Wed Sep 2 22:21:16 1992 Torbjorn Granlund (tege@jupiter.sics.se)
+
+ Fix from Jan-Hein Buhrman:
+ * mpz_mdiv.c, mpz_mmod.c, mpz_mdm.c: Make them work as documented.
+
+ * mpz_mmod.c, mpz_mdm.c: Move decl of TEMP_DIVISOR to reflect its
+ life.
+
+Sun Aug 30 18:37:15 1992 Torbjorn Granlund (tege@jupiter.sics.se)
+
+ * _mpz_get_str: Use mpz_sizeinbase for computing out_len.
+ * _mpz_get_str: Don't remove leading zeros. Abort if there are some.
+
+Wed Mar 4 17:56:56 1992 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * gmp.h: Change definition of MP_INT to make the & before params
+ optional. Use typedef to define it.
+ * mp.h: Use typedef to define MINT.
+
+Tue Feb 18 14:38:39 1992 Torbjorn Granlund (tege@zevs.sics.se)
+
+ longlong.h (hppa umul_ppmm): Add missing semicolon. Declare type
+ of __w1 and __w0.
+
+Fri Feb 14 21:33:21 1992 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * longlong.h: Make default count_leading_zeros work for machines >
+ 32 bits. Prepend `__' before local variables to avoid conflicts
+ with users' variables.
+
+ * mpn_dm_1.c: Remove udiv_qrnnd_preinv ...
+ * gmp-impl.h: ... and put it here.
+ * mpn_mod_1: Use udiv_qrnnd_preinv if it is faster than udiv_qrnnd.
+
+Tue Feb 11 17:20:12 1992 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpn_mul: Enhance base case by handling small multiplicands.
+ * mpn_dm_1.c: Revert last change.
+
+Mon Feb 10 11:55:15 1992 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpn_dm_1.c: Don't define udiv_qrnnd_preinv unless needed.
+
+Fri Feb 7 16:26:16 1992 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpn_mul: Replace code for base case.
+
+Thu Feb 6 15:10:42 1992 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpn_dm_1.c (_mpn_divmod_1): Add code for avoiding division by
+ pre-inverting divisor.
+
+Sun Feb 2 11:10:25 1992 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * longlong.h: Make __LLDEBUG__ work differently.
+ (_IBMR2): Reinsert old code.
+
+Sat Feb 1 16:43:00 1992 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * longlong.h (#ifdef _IBMR2): Replace udiv_qrnnd with new code
+ using floating point operations. Don't define
+ UDIV_NEEDS_NORMALIZATION any longer.
+
+Fri Jan 31 15:09:13 1992 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * longlong.h: Define UMUL_TIME and UDIV_TIME for most machines.
+ * longlong.h (#ifdef __hppa): Define umul_ppmm.
+
+Wed Jan 29 16:41:36 1992 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpn_cmp: Only one length parameter, assume operand lengths are
+ the same. Don't require normalization.
+ * mpq_cmp, mpz_add, mpz_sub, mpz_gcd, mpn_mul, mpn_sqrt: Change for
+ new mpn_cmp definition.
+
+Tue Jan 28 11:18:55 1992 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * _mpz_get_str: Fix typo in comment.
+
+Mon Jan 27 09:44:16 1992 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * Makefile.in: Add new files.
+
+ * mpn_dm_1.c: New file with function _mpn_divmod_1.
+ * mpz_dm_ui.c (mpz_divmod_ui): Use _mpn_divmod_1.
+ * mpz_div_ui: Likewise.
+
+ * mpn_mod_1.c: New file with function _mpn_mod_1.
+ * mpz_mod_ui: Use _mpn_mod_1.
+
+Thu Jan 23 18:54:09 1992 Torbjorn Granlund (tege@zevs.sics.se)
+
+ Bug found by Paul Zimmermann (zimmermann@inria.inria.fr):
+ * mpz_div_ui.c (mpz_div_ui), mpz_dm_ui.c (mpz_divmod_ui):
+ Handle dividend == 0.
+
+Wed Jan 22 12:02:26 1992 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpz_pprime.c: Use "" for #include.
+
+Sun Jan 19 13:36:55 1992 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpn_rshiftci.c (header): Correct comment.
+
+Wed Jan 15 18:56:04 1992 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpz_powm, mpz_powm_ui (if (bsize > msize)): Do alloca (bsize + 1)
+ to make space for ignored quotient at the end. (The quotient might
+ always be an extra limb.)
+
+Tue Jan 14 21:28:48 1992 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpz_powm_ui: Fix comment.
+ * mpz_powm: Likewise.
+
+Mon Jan 13 18:16:25 1992 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * tests/Makefile.in: Prepend $(TEST_PREFIX) to Makefile target.
+
+Sun Jan 12 13:54:28 1992 Torbjorn Granlund (tege@zevs.sics.se)
+
+ Fixes from Kazumaro Aoki:
+ * mpz_out_raw: Take abs of size to handle negative values.
+ * mpz_inp_raw: Reallocate before reading ptr from X.
+ * mpz_inp_raw: Store, don't read, size to x->size.
+
+Tue Jan 7 17:50:25 1992 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * gmp.h, mp.h: Remove parameter names from prototypes.
+
+Sun Dec 15 00:09:36 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * tests/Makefile.in: Prepend "./" to file names when executing
+ tests.
+
+ * Makefile.in: Fix many problems.
+
+Sat Dec 14 01:00:02 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpn_sqrt.c: New file with _mpn_sqrt.
+ * mpz_sqrt, mpz_sqrtrem, mpz_perfect_square_p: Use _mpn_sqrt.
+ * msqrt.c: Delete. Create from mpz_sqrtrem.c in Makefile.in.
+ * mpz_do_sqrt.c: Delete.
+ * Makefile.in: Update to reflect these changes.
+
+ * Makefile.in, configure, configure.subr: New files
+ (from bothner@cygnus.com).
+ * dist-Makefile: Delete.
+
+ * mpz_fac_ui: Fix comment.
+
+ * mpz_random2: Rewrite a bit to make it possible for the most
+ significant limb to be == 1.
+
+ * mpz_pprime.c (mpz_probab_prime_p): Remove \t\n.
+
+Fri Dec 13 23:10:02 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpz_do_sqrt: Simplify special case for U == 0.
+ * m*sqrt*.c, mpz_perfsqr.c (mpz_perfect_square_p):
+ Rename _mpz_impl_sqrt to _mpz_do_sqrt.
+
+Fri Dec 13 12:52:28 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * gmp-impl.h (MPZ_TMP_INIT): Cast to the right type.
+
+Thu Dec 12 22:17:29 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpn_add, mpn_sub, mpn_mul, mpn_div: Change type of several
+ variables to mp_size.
+
+Wed Dec 11 22:00:34 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpn_rshift.c: Fix header comments.
+
+Mon Dec 9 17:46:10 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ Released 1.2.
+
+ * gmp-impl.h (MPZ_TMP_INIT): Cast alloca return value.
+
+ * dist-Makefile: Add missing dependency for cre-mparam.
+
+ * mpz_mdiv.c, mpz_mmod.c, mpz_mdm.c, mpz_mdiv_ui.c,
+ mpz_mmod_ui.c, mpz_mdm_ui.c: Remove obsolete comment.
+
+ * dist-Makefile (clean): clean in tests subdir too.
+ * tests/Makefile: Define default values for ROOT and SUB.
+
+ * longlong.h (__a29k__ udiv_qrnnd): Change "q" to "1" for operand
+ 2 constraint.
+
+Mon Nov 11 00:06:05 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpz_sizeinb.c (mpz_sizeinbase): Special code for size == 0.
+
+Sat Nov 9 23:47:38 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ Released 1.1.94.
+
+ * dist-Makefile, Makefile, tests/Makefile: Merge tests into
+ distribution.
+
+Fri Nov 8 22:57:19 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * gmp.h: Don't use keyword `signed' for non-ANSI compilers.
+
+Thu Nov 7 22:06:46 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * longlong.h: Cosmetic changes to keep it identical to gcc2 version
+ of longlong.h.
+ * longlong.h (__ibm032__): Fix operand order for add_ssaaaa and
+ sub_ddmmss.
+
+Mon Nov 4 00:36:46 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpn_mul: Fix indentation.
+
+ * mpz_do_sqrt: Don't assume 32 bit limbs (had constant
+ 4294967296.0).
+ * mpz_do_sqrt: Handle overflow in conversion from double returned
+ by SQRT to mp_limb.
+
+ * gmp.h: Add missing function definitions.
+
+Sun Nov 3 18:25:25 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpz_pow_ui: Change type of `i' to int.
+
+ * ChangeLog: Add change log entry.
+ * ChangeLog: Add change log entry.
+ * ChangeLog: Add change log entry.
+ * ChangeLog: Add change log entry.
+ * ChangeLog: Add change log entry.
+ * ChangeLog: Add change log entry.
+ * ChangeLog: Add change log entry.
+ * ChangeLog: Add change log entry.
+Stack overflow.
+
+ * mpz_pow_ui.c: Fix typo in comment.
+
+ * dist-Makefile: Create rpow.c from mpz_powm_ui.c.
+ * mpz_powm_ui.c: Add code for rpow.
+ * rpow.c: Delete this file. The rpow function is now implemented
+ in mpz_powm_ui.c.
+
+ * mpz_fac_ui.c: New file.
+ * gmp.h, dist-Makefile: Add stuff for mpz_fac_ui.
+
+ Bug found by John Amanatides (amana@sasquatch.cs.yorku.ca):
+ * mpz_powm_ui, mpz_powm: Call _mpn_mul in the right way, with
+ the first argument not smaller than the second.
+
+Tue Oct 29 13:56:55 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * cre-conv-tab.c (main), cre-mparam.c (main): Fix typo in output
+ header text.
+
+Mon Oct 28 00:35:29 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpz_random2: Handle size == 0.
+
+ * gmp-impl.h (struct __mp_bases): Rename chars_per_limb_exactly to
+ chars_per_bit_exactly, and change its definition.
+ * cre-conv-tab.c (main): Output field according to its new
+ definition.
+ * mpz_out_str, _mpz_get_str, mpz_sizeinb, mout:
+ Use chars_per_bit_exactly.
+
+ * mpz_random2: Change the loop termination condition in order to
+ get a large most significant limb with higher probability.
+
+ * gmp.h: Add declaration of new mpz_random2 and mpz_get_si.
+ * mpz_get_si.c: New file.
+ * dist-Makefile: Add mpz_random2 and mpz_get_si.
+
+ * mpz_sizeinb.c (mpz_sizeinbase): Special code for base being a
+ power of 2, giving exact result.
+
+ * mpn_mul: Fix MPN_MUL_VERIFY in various ways.
+ * mpn_mul: New macro KARATSUBA_THRESHOLD.
+ * mpn_mul (karatsuba's algorithm): Don't write intermediate results
+ to prodp, use temporary pp instead. (Intermediate results can be
+ larger than the final result, possibly writing into hyperspace.)
+ * mpn_mul: Make smarter choice between Karatsuba's algorithm and the
+ shortcut algorithm.
+ * mpn_mul: Fix typo, cy instead of xcy. Unify carry handling code.
+
+Sun Oct 27 19:57:32 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpn_mul: In non-classical case, choose Karatsuba's algorithm only
+ when usize > 1.5 vsize.
+
+ * mpn_mul: Break between classical and Karatsuba's algorithm at
+ KARATSUBA_THRESHOLD, if defined. Default to 8.
+
+ * mpn_div: Kludge to fix stray memory read.
+
+Sat Oct 26 20:06:14 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpz_gcdext: Handle a = b = 0. Remove memory leakage by calling
+ mpz_clear for all temporary variables.
+
+ * mpz_gcd: Reduce w_bcnt in _mpn_lshift call to hold that
+ function's argument constraints. Compute wsize correctly.
+
+ * mpz_gcd: Fix typo in comment.
+
+ * memory.c (_mp_default_allocate, _mp_default_reallocate): Call
+ abort if allocation fails, don't just exit.
+
+Fri Oct 25 22:17:20 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpz_random2.c: New file.
+
+Thu Oct 17 18:06:42 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ Bugs found by Pierre-Joseph Gailly (pjg@sunbim.be):
+ * mpq_cmp: Take sign into account, don't just compare the
+ magnitudes.
+ * mpq_cmp: Call _mpn_mul in the right way, with the first argument
+ not smaller than the second.
+
+Wed Oct 16 19:27:32 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpz_random: Ensure the result is normalized.
+
+Tue Oct 15 14:55:13 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpz_clrbit: Support non-ANSI compilers.
+
+Wed Oct 9 18:03:28 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * longlong.h (68k add_ssaaaa, sub_ddmmss): Generalize constraints.
+
+Tue Oct 8 17:42:59 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpz_mdm_ui: Add comments.
+
+ * mpz_mdiv: Use MPZ_TMP_INIT instead of mpz_init.
+ * mpz_init_ui: Change spacing and header comment.
+
+Thu Oct 3 18:36:13 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * dist-Makefile: Prepend `./' before some filenames.
+
+Sun Sep 29 14:02:11 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ Released 1.1 (public).
+
+ * mpz_com: New name of mpz_not.
+ * dist-Makefile: Change mpz_not to mpz_com.
+
+Tue Sep 24 12:44:11 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * longlong.h: Fix header comment.
+
+Mon Sep 9 15:16:24 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ Released 1.0.92.
+
+ * mpn_mul.c (_mpn_mul): Handle leading zero limbs in non-Karatsuba
+ case.
+
+ * longlong.h (m68000 umul_ppmm): Clobber one register less by
+ slightly rearranging the code.
+
+Sun Sep 1 18:53:25 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * dist-Makefile (stamp-stddefh): Fix typo.
+
+Sat Aug 31 20:41:31 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ Released 1.0.91.
+
+ * mpz_mdiv.c, mpz_mmod.c, mpz_mdm.c, mpz_mdiv_ui.c,
+ mpz_mmod_ui.c, mpz_mdm_ui.c: New files and functions.
+ * gmp.h, gmp.texi: Define the new functions.
+
+Fri Aug 30 08:32:56 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpz_gcdext: Compute t argument from the other quantities at the
+ end, of the function, not in the loop. New feature: Allow t to be
+ NULL.
+
+ * mpz_add.c, mpz_sub.c, mpz_mul.c, mpz_powm.c, mpz_gcd.c: Don't
+ include "mp.h". Use type name `MP_INT' always.
+
+ * dist-Makefile, mpz_cmp.c: Merge mcmp.c from mpz_cmp.c.
+
+Wed Aug 28 00:45:11 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * dist-Makefile (documentation): Go via tmp.texi to avoid the
+ creation of gmp.dvi if any errors occur. Make tex read input
+ from /dev/null.
+
+Fri Aug 23 15:58:52 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * longlong.h (68020, i386): Don't define machine-dependent
+ __umulsidi3 (so the default definition is used).
+ * longlong.h (all machines): Cast all operands, sources and
+ destinations, to `unsigned long int'.
+ * longlong.h: Add gmicro support.
+
+Thu Aug 22 00:28:29 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * longlong.h: Rename BITS_PER_LONG to LONG_TYPE_SIZE.
+ * longlong.h (__ibm032__): Define count_leading_zeros and umul_ppmm.
+ * longlong.h: Define UMUL_TIME and UDIV_TIME for some CPUs.
+ * _mpz_get_str.c: Add code to do division by big_base using only
+ umul_qrnnd, if that is faster. Use UMUL_TIME and UDIV_TIME to
+ decide which variant to use.
+
+Wed Aug 21 15:45:23 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * longlong.h (__sparc__ umul_ppmm): Move two insn from end to the
+ nops. (Saves two insn.)
+
+ * longlong.h (__sparc__ umul_ppmm): Rewrite in order to avoid
+ branch, and to permit input/output register overlap.
+
+ * longlong.h (__29k__): Remove duplicated udiv_qrnnd definition.
+ * longlong.h (__29k__ umul_ppmm): Split asm instructions into two
+ asm statements (gives better code if either the upper or lower
+ part of the product is unused.
+
+Tue Aug 20 17:57:59 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * _mpz_get_str.c (outside of functions): Remove
+ num_to_ascii_lower_case and num_to_ascii_upper_case. Use string
+ constants in the function instead.
+
+Mon Aug 19 00:37:42 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * cre-conv-tab.c (main): Output table in hex. Output 4 fields, not
+ 3, for components 0 and 1.
+
+ * gmp.h: Add declaration of mpq_neg.
+
+ Released 1.0beta.13.
+
+ * _mpz_set_str.c (mpz_set_str): Cast EOF and SPC to char before
+ comparing to enum literals SPC and EOF. This makes the code work
+ for compilers where `char' is unsigned. (Bug found by Brian
+ Beuning).
+
+ Released 1.0beta.12.
+
+ * mpz_mod_ui: Remove references to quot. Remove quot_ptr, quot_size
+ declarations and assignment code.
+
+Sun Aug 18 14:44:26 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpz_mod_ui: Handle dividend < 0.
+
+ Released 1.0beta.11.
+
+ * mpz_dm_ui, mpz_div_ui, mpz_mod_ui, sdiv: Make them share the same
+ general structure, variable names, etc.
+
+ * sdiv: Un-normalize the remainder in n1 before it is negated.
+
+ * longlong.h: Mention UDIV_NEEDS_NORMALIZATION in description of
+ udiv_qrnnd.
+
+ * mpz_dm_ui.c (mpz_divmod_ui), mpz_div_ui.c (mpz_div_ui): Increment
+ the quotient size if the dividend size is incremented. (Bug found
+ by Brian Beuning.)
+
+ * mpz_mod_ui: Shift back the remainder, if UDIV_NEEDS_NORMALIZATION.
+ (Bug found by Brian Beuning.)
+
+ * mpz_mod_ui: Replace "digit" by "limb".
+
+ * mpz_perfsqr.c (mpz_perfect_square_p): Disable second test case
+ for non-32-bit machines (PP is hardwired for such machines).
+ * mpz_perfsqr.c (outside of functions): Define PP value with an L.
+
+ * mpn_mul.c (_mpn_mul): Add verification code that is activated if
+ DEBUG is defined. Replace "digit" by "limb".
+ * mpn_mul.c (_mpn_mul: Karatsuba's algorithm: 4.): Normalize temp
+ after the addition.
+ * mpn_mul.c (_mpn_mul: Karatsuba's algorithm: 1.): Compare u0_size
+ and v0_size, and according to the result, swap arguments in
+ recursive call. (Don't violate mpn_mul's own argument
+ constraints.)
+
+Fri Aug 16 13:47:12 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ Released 1.0beta.10.
+
+ * longlong.h (IBMR2): Add udiv_qrnnd.
+
+ * mpz_perfsqr: Remove unused variables.
+
+ * mpz_and (case for different signs): Initialize loop variable i!
+
+ * dist-Makefile: Update automatically generated dependencies.
+ * dist-Makefile (madd.c, msub.c, pow.c, mult.c, gcd.c): Add mp.h,
+ etc to dependency file lists.
+
+ * longlong.h (add_ssaaaa, sub_ddmmss [C default versions]): Make __x
+ `unsigned long int'.
+ * longlong.h: Add `int' after `unsigned' and `long' everywhere.
+
+Wed Aug 14 18:06:48 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * longlong.h: Add ARM, i860 support.
+
+ * mpn_lshift, mpn_rshift, mpn_rshiftci: Rename *_word with *_limb.
+
+Tue Aug 13 21:57:43 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * _mpz_get_str.c, _mpz_set_str.c, mpz_sizeinb.c (mpz_sizeinbase),
+ mpz_out_str.c, mout.c: Remove declaration of __mp_bases.
+ * gmp-impl.h: Put it here, and make it `const'.
+ * cre-conv-tab.c (main): Make struct __mp_bases `const'.
+
+Mon Aug 12 17:11:46 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * cre-conv-tab.c (main): Use %lu in printf for long ints.
+
+ * dist-Makefile: Fix cre-* dependencies.
+
+ * cre-conv-tab.c (main): Output field big_base_inverted.
+
+ * gmp-impl.h (struct bases): New field big_base_inverted.
+ * gmp-impl.h (struct bases): Change type of chars_per_limb_exactly
+ to float (in order to keep the structure smaller).
+
+ * mp.h, gmp.h: Change names of macros for avoiding multiple
+ includes.
+
+Fri Aug 9 18:01:36 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * _mpz_get_str: Only shift limb array if normalization_steps != 0
+ (optimization).
+
+ * longlong.h (sparc umul_ppmm): Use __asm__, not asm.
+ * longlong.h (IBMR2 umul_ppmm): Refer to __m0 and __m1, not to m0
+ and m1 (overlap between output and input operands did not work).
+ * longlong.h: Add VAX, ROMP and HP-PA support.
+ * longlong.h: Sort the machine dependent code in alphabetical order
+ on the CPU name.
+ * longlong.h: Hack comments.
+
+Thu Aug 8 14:13:36 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ Released 1.0beta.9.
+
+ * longlong.h: Define BITS_PER_LONG to 32 if it's not already
+ defined.
+ * Define __BITS4 to BITS_PER_LONG / 4.
+ * Don't assume 32 bit word size in "count_leading_zeros" C macro.
+ Use __BITS4 and BITS_PER_LONG instead.
+
+ * longlong.h: Don't #undef internal macros (reverse change of Aug 3).
+
+ * longlong.h (68k): Define add_ssaaaa sub_ddmmss, and umul_ppmm
+ even for plain mc68000.
+
+ * mpq_div: Flip the sign of the numerator *and* denominator of the
+ result if the intermediate denominator is negative.
+
+ * mpz_and.c, mpz_ior.c: Use MPN_COPY for all copying operations.
+
+ * mpz_and.c: Compute the result size more conservatively.
+ * mpz_ior.c: Likewise.
+
+ * mpz_realloc: Never allocate zero space even if NEW_SIZE == 0.
+
+ * dist-Makefile: Remove madd.c, msub.c, pow.c, mult.c, gcd.c from
+ BSDMP_SRCS.
+
+ * dist-Makefile: Create mult.c from mpz_mul.c.
+ * mult.c: Delete this file.
+
+ * _mpz_set_str: Normalize the result (for bases 2, 4, 8... it was
+ not done properly if the input string had many leading zeros).
+
+Sun Aug 4 16:54:14 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * dist-Makefile (gcd.c, pow.c, madd.c, msub.c): Make these targets
+ work with VPATH and GNU MP.
+
+ * mpz_gcd: Don't call mpz_set; inline its functionality.
+
+ * mpq_mul, mpq_div: Fix several serious typos.
+
+ * mpz_dmincl, mpz_div: Don't normalize the quotient if it's already
+ zero.
+
+ * mpq_neg.c: New file.
+
+ * dist-Makefile: Remove obsolete dependencies.
+
+ * mpz_sub: Fix typo.
+
+ Bugs found by Pierre-Joseph Gailly (pjg@sunbim.be):
+ * mpq_mul, mpq_div: Initialize tmp[12] variables even when the gcd
+ is just 1.
+ * mpz_gcd: Handle gcd(0,v) and gcd(u,0) in special cases.
+
+Sat Aug 3 23:45:28 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * longlong.h: Clean up comments.
+ * longlong.h: #undef internal macros.
+
+Fri Aug 2 18:29:11 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpq_set_si, mpq_set_ui: Canonicalize 0/x to 0/1.
+ * mpq_set_si, mpq_set_ui: Cosmetic formatting changes.
+
+ * mpz_dmincl.c: Normalize the remainder before shifting it back.
+
+ * mpz_dm_ui.c (mpz_divmod_ui): Handle rem == dividend.
+
+ * mpn_div.c: Fix comment.
+
+ * mpz_add.c, mpz_sub.c: Use __MP_INT (not MP_INT) for intermediate
+ type, in order to work for both GNU and Berkeley functions.
+
+ * dist-Makefile: Create gcd.c from mpz_gcd.c, pow.c from mpz_powm,
+ madd.c from mpz_add.c, msub.c from mpz_sub.c.
+ respectively.
+ * pow.c, gcd.c, mpz_powmincl.c, madd.c, msub.c: Remove these.
+ * mpz_powm.c, mpz_gcd.c, mpz_add.c, mpz_sub.c: #ifdef for GNU and
+ Berkeley function name variants.
+ * dist-Makefile: Add created files to "clean" target.
+
+Tue Jul 16 15:19:46 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpq_get_den: No need for absolute value of the size, the
+ denominator is always positive.
+
+ * mpz_get_ui: If the operand is zero, return zero. Don't read the
+ limb array!
+
+ * mpz_dmincl.c: Don't ignore the return value from _mpn_rshift, it
+ is the size of the remainder.
+
+Mon Jul 15 11:08:05 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * Several files: Remove unused variables and functions.
+
+ * gmp-impl.h: Declare _mpz_impl_sqrt.
+
+ * mpz_dm_ui (mpz_divmod_ui), sdiv: Shift back the remainder if
+ UDIV_NEEDS_NORMALIZATION. (Fix from Brian Beuning.)
+
+ * mpz_dm_ui.c, sdiv: Replace *digit with *limb.
+
+ * mpz_ior: Add missing else statement in -OP1 | -OP2 case.
+ * mpz_ior: Add missing else statement in OP1 | -OP2 case.
+ * mpz_ior: Swap also OP1 and OP2 pointers in -OP1 & OP2 case.
+ * mpz_ior: Duplicate _mpz_realloc code.
+
+ * mpz_and: Add missing else statement in -OP1 & -OP2 case.
+ * mpz_and: Rewrite OP1 & -OP2 case.
+ * mpz_and: Swap also OP1 and OP2 pointers in -OP1 & OP2 case.
+
+ * mpz_gcdext: Loop in d1.size (not b->size). (Fix from Brian
+ Beuning.)
+
+ * mpz_perfsqr: Fix argument order in _mpz_impl_sqrt call. (Fix from
+ Brian Beuning.)
+
+Fri Jul 12 17:10:33 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpq_set.c, mpq_set_ui.c, mpq_set_si.c, mpq_inv.c,
+ mpq_get_num.c, mpq_get_den.c, mpq_set_num.c, mpq_set_den.c:
+ New files.
+
+ * mpz_dmincl.c: Remove second re-allocation of rem->d. It
+ was never executed.
+
+ * dist-Makefile: Use `-r' instead of `-x' for test for ranlib (as
+ some unixes' test doesn't have the -r option).
+
+ * *.*: Cast allocated pointers to the appropriate type (makes old C
+ compilers happier).
+
+ * cre-conv-tab.c (main): Divide max_uli by 2 and multiply again
+ after conversion to double. (Kludge for broken C compilers.)
+
+ * dist-Makefile (stamp-stddefh): New target. Test if "stddef.h"
+ exists in the system and creates a minimal one if it does not
+ exist.
+ * cre-stddefh.c: New file.
+ * dist-Makefile: Make libgmp.a and libmp.a depend on stamp-stddefh.
+ * dist-Makefile (clean): Add some more.
+ * gmp.h, mp.h: Unconditionally include "stddef.h".
+
+Thu Jul 11 10:08:21 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * min: Do ungetc of last read character.
+ * min.c: include stdio.h.
+
+ * dist-Makefile: Go via tmp- files for cre* redirection.
+ * dist-Makefile: Add tmp* to "clean" target.
+
+ * dist-Makefile: Use LOCAL_CC for cre*, to simplyfy cross
+ compilation.
+
+ * gmp.h, mp.h: Don't define NULL here.
+ * gmp-impl.h: Define it here.
+
+Wed Jul 10 14:13:33 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpz_mod_2exp: Don't copy too much, overwriting most significant
+ limb.
+
+ * mpz_and, mpz_ior: Don't read op[12]_ptr from op[12] when
+ reallocating res, if op[12]_ptr got their value from alloca.
+
+ * mpz_and, mpz_ior: Clear up comments.
+
+ * cre-mparam.c: Output parameters for `short int' and `int'.
+
+ * mpz_and, mpz_ior: Negate negative op[12]_size in several places.
+
+Tue Jul 9 18:40:30 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * gmp.h, mp.h: Test for _SIZE_T defined before typedef'ing size_t.
+ (Fix for Sun lossage.)
+
+ * gmp.h: Add declaration of mpq_clear.
+
+ * dist-Makefile: Chack if "ranlib" exists, before using it.
+ * dist-Makefile: Add mpz_sqrtrem.c and mpz_size.c.
+ * mpz_powm: Fix typo, "pow" instead of "mpz_powm".
+
+Fri Jul 5 19:08:09 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * move: Remove incorrect comment.
+
+ * mpz_free, mpq_free: Rename to *_clear.
+ * dist-Makefile: Likewise.
+ * mpq_add, mpq_sub, mpq_mul, mpq_div: Likewise.
+
+ * mpz_dmincl.c: Don't call "move", inline its functionality.
+
+Thu Jul 4 00:06:39 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * Makefile: Include dist-Makefile. Fix dist target to include
+ dist-Makefile (with the name "Makefile" in the archive).
+
+ * dist-Makefile: New file made from Makefile. Add new mpz_...
+ functions.
+
+ * mpz_powincl.c New file for mpz_powm (Berkeley MP pow)
+ functionality. Avoids code duplication.
+ * pow.c, mpz_powm.c: Include mpz_powincl.c
+
+ * mpz_dmincl.c: New file containing general division code. Avoids
+ code duplication.
+ * mpz_dm.c (mpz_divmod), mpz_mod.c (mpz_mod), mdiv.c (mdiv): Include
+ mpz_dmincl.c.
+
+ * _mpz_get_str: Don't call memmove, unless HAS_MEMMOVE is defined.
+ Instead, write the overlapping memory copying inline.
+
+ * mpz_dm_ui.c: New name for mpz_divmod_ui.c (SysV file name limit).
+
+ * longlong.h: Don't use #elif.
+ * mpz_do_sqrt.c: Likewise.
+
+ * longlong.h: Use __asm__ instead of asm.
+ * longlong.h (sparc udiv_qrnnd): Make it to one string over several
+ lines.
+
+ * longlong.h: Preend __ll_ to B, highpart, and lowpart.
+
+ * longlong.h: Move array t in count_leading_zeros to the new file
+ mp_clz_tab.c. Rename the array __clz_tab.
+ * All files: #ifdef for traditional C compatibility.
+
+Wed Jul 3 11:42:14 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpz_and: Initialize res_ptr always (used to be initialized only
+ when reallocating).
+
+ * longlong.h (umul_ppmm [C variant]): Make __ul...__vh
+ `unsigned int', and cast the multiplications. This way
+ compilers more easily can choose cheaper multiplication
+ instructions.
+
+ * mpz_mod_2exp: Handle input argument < modulo argument.
+ * mpz_many: Make sure mp_size is the type for sizes, not int.
+
+ * mpz_init, mpz_init_set*, mpq_init, mpq_add, mpq_sub, mpq_mul,
+ mpq_div: Change mpz_init* interface. Structure pointer as first
+ arg to initialization function, no longer *return* struct.
+
+Sun Jun 30 19:21:44 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * Rename mpz_impl_sqrt.c to mpz_do_sqrt.c to satisfy SysV 14
+ character file name length limit.
+
+ * Most files: Rename MINT to MP_INT. Rename MRAT to MP_RAT.
+ * mpz_sizeinb.c: New file with function mpz_sizeinbase.
+ * mp_bases.c: New file, with array __mp_bases.
+ * _mpz_get_str, _mpz_set_str: Remove struct bases, use extern
+ __mp_bases instead.
+ * mout, mpz_out_str: Use array __mp_bases instead of function
+ _mpz_get_cvtlen.
+ * mpz_get_cvtlen.c: Remove.
+ * Makefile: Update.
+
+Sat Jun 29 21:57:28 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * longlong.h (__sparc8__ umul_ppmm): Insert 3 nop:s for wr delay.
+ * longlong.h (___IBMR2__): Define umul_ppmm, add_ssaaaa, sub_ddmmss.
+ * longlong.h (__sparc__): Don't call .umul; expand asm instead.
+ Don't define __umulsidi3 (i.e. use default definition).
+
+Mon Jun 24 17:37:23 1991 Torbjorn Granlund (tege@amon.sics.se)
+
+ * _mpz_get_str.c (num_to_ascii_lower_case, num_to_ascii_upper_case):
+ Swap 't' and 's'.
+
+Sat Jun 22 13:54:01 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpz_gcdext.c: New file.
+
+ * mpn_mul: Handle carry and unexpected operand sizes in last
+ additions/subtractions. (Bug trigged when v1_size == 1.)
+
+ * mp*_alloc*: Rename functions to mp*_init* (files to mp*_iset*.c).
+ * mpq_*: Call mpz_init*.
+
+ * mpz_pow_ui, rpow: Use _mpn_mul instead of mult. Restructure.
+
+Wed May 29 20:32:33 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpz_get_cvtlen: multiply by size.
+
+Sun May 26 15:01:15 1991 Torbjorn Granlund (tege@bella.nada.kth.se)
+
+ Alpha-release 0.95.
+
+ Fixes from Doug Lea (dl@g.oswego.edu):
+ * mpz_mul_ui: Loop to MULT_SIZE (not PROD_SIZE). Adjust PROD_SIZE
+ correctly.
+ * mpz_div: Prepend _ to mpz_realloc.
+ * mpz_set_xs, mpz_set_ds: Fix typos in function name.
+
+Sat May 25 22:51:16 1991 Torbjorn Granlund (tege@bella.nada.kth.se)
+
+ * mpz_divmod_ui: New function.
+
+ * sdiv: Make the sign of the remainder correct.
+
+Thu May 23 15:28:24 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * Alpha-release 0.94.
+
+ * mpz_mul_ui: Include longlong.h.
+
+ * mpz_perfsqr.c (mpz_perfect_square_p): Call _mpz_impl_sqrt instead
+ of msqrt.
+
+ * mpz_impl_sqrt: Don't call "move", inline its functionality.
+
+ * mdiv: Use MPN_COPY instead of memcpy.
+ * rpow, mpz_mul, mpz_mod_2exp: Likewise.
+ * pow.c: Likewise, and fix bug in the size arg.
+
+ * xtom: Don't use mpz_alloc, inline needed code instead. Call
+ _mpz_set_str instead of mpz_set_str.
+
+ * Makefile: Make two libraries, libmp.a and libgmp.a.
+
+Thu May 22 20:25:29 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * Add manual to distribution.
+ * Fold in many missing routines descibed in the manual.
+ * Update Makefile.
+
+Wed May 22 13:48:46 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpz_set_str: Make it handle 0x prefix OK.
+
+Sat May 18 18:31:02 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * memory.c (_mp_default_reallocate): Swap OLD_SIZE and NEW_SIZE
+ arguments.
+ * mpz_realloc (_mpz_realloc): Swap in call to _mp_reallocate_func.
+ * min: Likewise.
+
+Thu May 16 20:43:05 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * memory.c: Make the default allocations functions global.
+ * mp_set_fns (mp_set_memory_functions): Make a NULL pointer mean the
+ default memory function.
+
+Wed May 8 20:02:42 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpz_div: Handle DEN the same as QUOT correctly by copying DEN->D
+ even if no normalization is needed.
+ * mpz_div: Rework reallocation scheme, to avoid excess copying.
+
+ * mpz_sub_ui.c, mpz_add_ui.c: New files.
+
+ * mpz_cmp.c, mpz_cmp_ui.c: New files.
+
+ * mpz_mul_2exp: Handle zero input MINT correctly.
+
+ * mpn_rshiftci: Don't handle shift counts > BITS_PER_MP_DIGIT.
+
+ * mpz_out_raw.c, mpz_inp_raw.c: New files for raw I/O.
+
+Tue May 7 15:44:58 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpn_rshift: Don't handle shift counts > BITS_PER_MP_DIGIT.
+ * mpz_div_2exp: Don't call _mpn_rshift with cnt > BITS_PER_MP_DIGIT.
+ * gcd, mpz_gcd: Likewise.
+
+ * gcd, mpz_gcd: Handle common 2 factors correctly.
+
+Mon May 6 20:22:59 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * gmp-impl.h (MPN_COPY): Inline a loop instead of calling memcpy.
+
+ * gmp-impl.h, mpz_get_str, rpow: Swap DST and SRC in TMPCOPY* macros.
+
+Sun May 5 15:16:23 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpz_div: Remove test for QUOT == 0.
+
+Sun Apr 28 20:21:04 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * pow: Don't make MOD normalization in place, as it's a bad idea to
+ write on an input parameter.
+ * pow: Reduce BASE if it's > MOD.
+ * pow, mult, mpz_mul: Simplify realloc code.
+
+Sat Apr 27 21:03:11 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * Install multplication using Karatsuba's algorithm as default.
+
+Fri Apr 26 01:03:57 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * msqrt: Store in ROOT even for U==0, to make msqrt(0) defined.
+
+ * mpz_div_2exp.c, mpz_mul_2exp.c: New files for shifting right and
+ left, respectively.
+ * gmp.h: Add definitions for mpz_div_2exp and mpz_mul_2exp.
+
+ * mlshift.c, mrshift.c: Remove.
+
+Wed Apr 24 21:39:22 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * mpn_mul: Check only for m2_size == 0 in function header.
+
+Mon Apr 22 01:31:57 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * karatsuba.c: New file for Karatsuba's multplication algorithm.
+
+ * mpz_random, mpz_init, mpz_mod_2exp: New files and functions.
+
+ * mpn_cmp: Fix header comment.
+
+Sun Apr 21 00:10:44 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * pow: Switch off initial base reduction.
+
+Sat Apr 20 22:06:05 1991 Torbjorn Granlund (tege@echnaton.sics.se)
+
+ * mpz_get_str: Don't generate initial zeros for initial word.
+ Used to write outside of allocated storage.
+
+Mon Apr 15 15:48:08 1991 Torbjorn Granlund (tege@zevs.sics.se)
+
+ * _mpz_realloc: Make it accept size in number of mp_digits.
+ * Most functions: Use new _mpz_realloc definition.
+
+ * mpz_set_str: Remove calls _mp_free_func.
+
+ * Most functions: Rename mpn_* to _mpn_*. Rename mpz_realloc to
+ _mpz_realloc.
+ * mpn_lshift: Redefine _mpn_lshift to only handle small shifts.
+ * mdiv, mpz_div, ...: Changes for new definition of _mpn_lshift.
+ * msqrt, mp*_*shift*: Define cnt as unsigned (for speed).
+
+Sat Apr 6 14:05:16 1991 Torbjorn Granlund (tege@musta.nada.kth.se)
+
+ * mpn_mul: Multiply by the first digit in M2 in a special
+ loop instead of zeroing the product area.
+
+ * mpz_abs.c: New file.
+
+ * sdiv: Implement as mpz_div_si for speed.
+
+ * mpn_add: Make it work for second source operand == 0.
+
+ * msub: Negate the correct operand, i.e. V before swapping, not
+ the smaller of U and V!
+ * madd, msub: Update abs_* when swapping operands, and not after
+ (optimization).
+
+Fri Apr 5 00:19:36 1991 Torbjorn Granlund (tege@black.nada.kth.se)
+
+ * mpn_sub: Make it work for subtrahend == 0.
+
+ * madd, msub: Rewrite to minimize mpn_cmp calls. Ensure
+ mpn_cmp is called with positive sizes (used to be called
+ incorrectly with negative sizes sometimes).
+
+ * msqrt: Make it divide by zero if fed with a negative number.
+ * Remove if statement at end of precision calculation that was
+ never true.
+
+ * itom, mp.h: The argument is of type short, not int.
+
+ * mpz_realloc, gmp.h: Make mpz_realloc return the new digit pointer.
+
+ * mpz_get_str.c, mpz_set_str.c, mpz_new_str.c: Don't include mp.h.
+
+ * Add COPYING to distribution.
+
+ * mpz_div_ui.c, mpz_div_si.c, mpz_new_ui.c, mpz_new_si.c: New files.
+
+Fri Mar 15 00:26:29 1991 Torbjorn Granlund (tege@musta.nada.kth.se)
+
+ * Add Copyleft headers to all files.
+
+ * mpn_mul.c, mpn_div.c: Add header comments.
+ * mult.c, mdiv.c: Update header comments.
+
+ * mpq_add.c, mpq_sub.c, mpq_div.c, mpq_new.c, mpq_new_ui.c,
+ mpq_free.c: New files for rational arithmetics.
+
+ * mpn_lshift.c: Avoid writing the most significant word if it is 0.
+
+ * mdiv.c: Call mpn_lshift for the normalization.
+ * mdiv.c: Remove #ifdefs.
+
+ * Makefile: Add ChangeLog to DISTFILES.
+
+ * mpn_div.c: Make the add_back code work (by removing abort()).
+ * mpn_div.c: Make it return if the quotient is size as compared
+ with the difference NSIZE - DSIZE. If the stored quotient is
+ larger than that, return 1, otherwise 0.
+ * gmp.h: Fix mpn_div declaration.
+ * mdiv.c: Adopt call to mpn_div.
+ * mpz_div.c: New file (developed from mdiv.c).
+
+ * README: Update routine names.
+
+Thu Mar 14 18:45:28 1991 Torbjorn Granlund (tege@musta.nada.kth.se)
+
+ * mpq_mul.c: New file for rational multplication.
+
+ * gmp.h: Add definitions for rational arithmetics.
+
+ * mpn_div: Kludge the case where the high numerator digit > the
+ high denominator digit. (This code is going to be optimized later.)
+
+ * New files: gmp.h for GNU specific functions, gmp-common.h for
+ definitions common for mp.h and gmp.h.
+
+ * Ensure mp.h just defines what BSD mp.h defines.
+
+ * pow.c: Fix typo for bp allocation.
+
+ * Rename natural number functions to mpn_*, integer functions to
+ mpz_*.
+
+Tue Mar 5 18:47:04 1991 Torbjorn Granlund (tege@musta.nada.kth.se)
+
+ * mdiv.c (_mp_divide, case 2): Change test for estimate of Q from
+ "n0 >= r" to "n0 > r".
+
+ * msqrt: Tune the increasing precision scheme, to do fewer steps.
+
+Tue Mar 3 18:50:10 1991 Torbjorn Granlund (tege@musta.nada.kth.se)
+
+ * msqrt: Use the low level routines. Use low precision in the
+ beginning, and increase the precision as the result converges.
+ (This optimization gave a 6-fold speedup.)
+
+Local Variables:
+mode: indented-text
+left-margin: 8
+fill-column: 75
+version-control: never
+End:
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 000000000..38bfaa8b4
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,154 @@
+INSTALLING GMP
+==============
+
+These instructions are only for the impatient. Others should read the install
+instructions in the manual, gmp.info. Use "info -f gmp.info", or, if you
+don't have info, use type "C-h i g (gmp.info)Top" in emacs.
+
+Here are short instructions how to install MP, and some examples that help you
+get started using MP.
+
+First, you need to compile, and optionally install, MP. Since you're
+impatient, try this:
+
+ ./configure; make
+
+If that fails, or you care about the performance of MP, you need to read the
+full instructions in the chapter "Installing MP", in the manual.
+
+Next, you need to try some small test programs, for example the ones below.
+
+In MP programs, all variables need to be initialized before they are assigned,
+and cleared out before program flow leaves the scope in which it was declared.
+Here is an example of a program that reads two numbers from the command line,
+multiplies them, and prints the result to stdout.
+
+ #include <stdio.h>
+ #include <gmp.h> /* All MP programs need to include gmp.h */
+
+ main (int argc, char **argv)
+ {
+ mpz_t a, b, p;
+
+ /* Initialize variables */
+ mpz_init (a);
+ mpz_init (b);
+ mpz_init (p);
+
+ /* Assign a and b from base 10 strings in argv */
+ mpz_set_str (a, argv[1], 10);
+ mpz_set_str (b, argv[2], 10);
+
+ /* Multiply a and b and put the result in p */
+ mpz_mul (p, a, b);
+
+ /* Print p in base 10 */
+ mpz_out_str (stdout, 10, p);
+ fputc ('\n', stdout);
+
+ /* Clear out variables */
+ mpz_clear (a);
+ mpz_clear (b);
+ mpz_clear (p);
+ exit (0);
+ }
+
+
+In practice, that example would be written like this instead:
+
+ #include <stdio.h>
+ #include <gmp.h>
+
+ main (int argc, char **argv)
+ {
+ mpz_t a, b, p;
+
+ /* Initialize and assign a and b from base 10 strings in argv */
+ mpz_init_set_str (a, argv[1], 10);
+ mpz_init_set_str (b, argv[2], 10);
+ /* Initialize p */
+ mpz_init (p);
+
+ /* Multiply a and b and put the result in p */
+ mpz_mul (p, a, b);
+
+ /* Print p in base 10 */
+ mpz_out_str (stdout, 10, p);
+ fputc ('\n', stdout);
+
+ /* Since we're about to exit, no need to clear out variables */
+ exit (0);
+ }
+
+Finally, you have to compile your test program, and link it with the MP
+library. Assuming your working directory is still the gmp source directory,
+type:
+
+ gcc -g -I. example.c libgmp.a
+
+
+Now try to run the example:
+
+ a.out 98365871231256752134 319378318340103345227
+ 31415926535897932384618573336104570964418
+
+The functions used here all operate on the domain of signed integers.
+Functions operating on that domain have names starting with "mpz_". There are
+many more such functions than used in these examples. See the chapter
+"Integer Functions" in the manual, for a complete list.
+
+There are two other main classes of functions in MP. They operate on rational
+numbers and floating-point numbers, respectively. The chapters "Rational
+Number Functions", and "Floating-point Functions" documents these classes.
+
+To run a set of tests, do "make check". This will take a while.
+
+To create the printable documentation from the texinfo source, type "make
+dvi". This requires the "tex" command to be available in your search path.
+
+To install the library, do "make install".
+
+If you decide to use MP, It is a good idea you read at least the chapter "MP
+Basics" in the manual.
+
+
+Known Build Problems
+--------------------
+
+Note that GCC 2.7.2 (as well as 2.6.3) for the RS/6000 and PowerPC can not
+be used to compile GMP, due to a bug in GCC. If you want to use GCC, you
+need to apply the patch at the end of this file, or use a later version of
+the compiler.
+
+If you are on a Sequent Symmetry, use GAS instead of the system's assembler
+due to the latter's serious bugs.
+
+The system compiler on NeXT is a massacred and old gcc, even if the
+compiler calls itself cc. This compiler cannot be used to build GMP. You
+need to get a real gcc, and install that before you compile GMP. (NeXT
+might have fixed this in newer releases of their system.)
+
+Please report other problems to bug-gmp@prep.ai.mit.edu.
+
+
+Patch to apply to GCC 2.6.3 and 2.7.2:
+
+*** config/rs6000/rs6000.md Sun Feb 11 08:22:11 1996
+--- config/rs6000/rs6000.md.new Sun Feb 18 03:33:37 1996
+***************
+*** 920,926 ****
+ (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (not:SI (match_dup 1)))]
+ ""
+! "nor. %0,%2,%1"
+ [(set_attr "type" "compare")])
+
+ (define_insn ""
+--- 920,926 ----
+ (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (not:SI (match_dup 1)))]
+ ""
+! "nor. %0,%1,%1"
+ [(set_attr "type" "compare")])
+
+ (define_insn ""
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 000000000..6012140e6
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,201 @@
+# Top Makefile for GNU MP
+# Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+# This file is part of the GNU MP Library.
+
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+
+# The GNU MP Library 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 Library General Public
+# License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+
+srcdir = .
+
+prefix = /usr/local
+
+exec_prefix = $(prefix)
+libdir = $(exec_prefix)/lib
+infodir = $(prefix)/info
+includedir = $(prefix)/include
+
+CC = gcc
+LOCAL_CC = $(CC)
+CFLAGS = -g -O
+XCFLAGS =
+AR = ar
+AR_FLAGS = rc
+RANLIB_TEST = [ -f /usr/bin/ranlib -o -f /bin/ranlib ]
+RANLIB = ranlib
+SHELL = /bin/sh
+INSTALL = install -c
+INSTALL_PROGRAM = $(INSTALL)
+INSTALL_DATA = $(INSTALL)
+MAKEINFO = makeinfo
+MAKEINFOFLAGS =
+TEXI2DVI = texi2dvi
+LN = ln -s
+
+#### host and target specific makefile fragments come in here.
+###
+
+SRCS = memory.c mp_set_fns.c mp_clz_tab.c version.c stack-alloc.c mp_bpl.c
+OBJS = memory.o mp_set_fns.o mp_clz_tab.o version.o stack-alloc.o mp_bpl.o
+FILES = gmp.h mp.h gmp-impl.h longlong.h urandom.h move-if-change \
+ mkinstalldirs INSTALL COPYING.LIB ChangeLog Makefile.in \
+ NEWS README SPEED TODO config.guess config.sub configure configure.in \
+ gmp.info* gmp.texi texinfo.tex $(SRCS)
+
+INCLUDES = -I. -Impn -I$(srcdir)
+FLAGS_TO_PASS = "CC=$(CC)" "CFLAGS=$(CFLAGS)" "XCFLAGS=$(XCFLAGS)"
+
+all: libgmp.a
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(XCFLAGS) $<
+
+libgmp.a: mpn/libmpn.a mpz/libmpz.a mpf/libmpf.a mpq/libmpq.a $(OBJS)
+ rm -rf tmpdir
+ mkdir tmpdir
+ for i in mpn mpz mpf mpq; \
+ do \
+ mkdir tmpdir/$$i; \
+ ( cd tmpdir/$$i; $(AR) x ../../$$i/lib$$i.a ); \
+ done
+ cp $(OBJS) tmpdir
+ cd tmpdir; $(AR) $(AR_FLAGS) $@ *.o */*.o
+ if $(RANLIB_TEST) ; then $(RANLIB) tmpdir/$@; else true; fi
+ mv tmpdir/$@ .
+ rm -rf tmpdir
+
+libmp.a: mpn/libmpn.a mpbsd/libmpbsd.a $(OBJS)
+ rm -rf tmpdir
+ mkdir tmpdir
+ for i in mpn mpbsd; \
+ do \
+ mkdir tmpdir/$$i; \
+ ( cd tmpdir/$$i; $(AR) x ../../$$i/lib$$i.a ); \
+ done
+ cp $(OBJS) tmpdir
+ cd tmpdir; $(AR) $(AR_FLAGS) $@ *.o */*.o
+ if $(RANLIB_TEST) ; then $(RANLIB) tmpdir/$@; else true; fi
+ mv tmpdir/$@ .
+ rm -rf tmpdir
+
+mpn/libmpn.a: force
+ cd mpn; $(MAKE) $(FLAGS_TO_PASS) libmpn.a
+mpz/libmpz.a: force
+ cd mpz; $(MAKE) $(FLAGS_TO_PASS) libmpz.a
+mpf/libmpf.a: force
+ cd mpf; $(MAKE) $(FLAGS_TO_PASS) libmpf.a
+mpq/libmpq.a: force
+ cd mpq; $(MAKE) $(FLAGS_TO_PASS) libmpq.a
+mpbsd/libmpbsd.a: force
+ cd mpbsd; $(MAKE) $(FLAGS_TO_PASS) libmpbsd.a
+
+check: libgmp.a
+ cd mpz/tests; $(MAKE) $(FLAGS_TO_PASS) check
+ cd mpq/tests; $(MAKE) $(FLAGS_TO_PASS) check
+ cd mpf/tests; $(MAKE) $(FLAGS_TO_PASS) check
+
+doc: gmp.dvi gmp.info
+
+info: $(srcdir)/gmp.info
+$(srcdir)/gmp.info: $(srcdir)/gmp.texi
+ cd $(srcdir); $(MAKEINFO) gmp.texi
+
+dvi: gmp.dvi
+gmp.dvi: $(srcdir)/gmp.texi
+ rm -f tmp.texi
+ $(LN) $(srcdir)/gmp.texi tmp.texi
+ TEXINPUTS=.:$(srcdir) $(TEXI2DVI) tmp.texi
+ rm -f tmp.texi
+ mv tmp.dvi gmp.dvi
+ rm -f tmp.*
+
+ps: gmp.ps
+gmp.ps: gmp.dvi
+ dvips gmp.dvi -o gmp.ps
+
+html: gmp_toc.html
+gmp_toc.html: $(srcdir)/gmp.texi
+ texi2html -acc -split_chapter $(srcdir)/gmp.texi
+
+install-strip: install
+install: installdirs libgmp.a gmp.info install-info-files
+ $(INSTALL_DATA) libgmp.a $(libdir)/libgmp.a
+ -chmod a-x $(libdir)/libgmp.a
+ $(INSTALL_DATA) $(srcdir)/gmp.h $(includedir)/gmp.h
+ -chmod a-x $(includedir)/gmp.h
+install-bsdmp: installdirs libmp.a gmp.info install-info-files
+ $(INSTALL_DATA) libmp.a $(libdir)/libmp.a
+ -chmod a-x $(libdir)/libmp.a
+ $(INSTALL_DATA) $(srcdir)/mp.h $(includedir)/mp.h
+ -chmod a-x $(includedir)/mp.h
+install-info-files: installdirs $(srcdir)/gmp.info
+ cd $(srcdir); for f in gmp.info*; \
+ do $(INSTALL_DATA) $$f $(infodir)/$$f; done
+ -chmod a-x $(infodir)/gmp.info*
+ # Attempt to edit the info directory node
+ if $(SHELL) -c 'install-info --version' >/dev/null 2>&1; then \
+ install-info --dir-file=$(infodir)/dir $(infodir)/gmp.info; \
+ else true; fi
+
+installdirs: $(srcdir)/mkinstalldirs
+ $(srcdir)/mkinstalldirs $(includedir) $(libdir) $(infodir)
+
+uninstall:
+ rm -f $(libdir)/libgmp.a
+ rm -f $(includedir)/gmp.h
+ rm -f $(libdir)/libmp.a
+ rm -f $(includedir)/mp.h
+ rm -f $(infodir)/gmp.info*
+
+clean mostlyclean:
+ rm -f *.o libgmp.a libmp.a gmp.dvi gmp.ps tmp.* tmp-*
+ rm -f gmp.?? gmp.??s gmp.log gmp.toc gmp.*aux gmp*.html
+ -cd mpn; $(MAKE) $@
+ -cd mpz; $(MAKE) $@
+ -cd mpf; $(MAKE) $@
+ -cd mpq; $(MAKE) $@
+ -cd mpbsd; $(MAKE) $@
+distclean: clean
+ rm -f Makefile config.status
+ -cd mpn; $(MAKE) $@
+ -cd mpz; $(MAKE) $@
+ -cd mpf; $(MAKE) $@
+ -cd mpq; $(MAKE) $@
+ -cd mpbsd; $(MAKE) $@
+maintainer-clean: distclean
+ rm -f $(srcdir)/gmp.info*
+
+TAGS: force
+ cd $(srcdir); etags *.[ch] mp*/*.c mpn/generic/*.c >TAGS
+
+dist:
+ @echo "sorry, not supported target"
+ @exit 1
+
+Makefile: $(srcdir)/Makefile.in $(host_makefile_frag) $(target_makefile_frag)
+ $(SHELL) ./config.status
+
+H = $(srcdir)/gmp.h $(srcdir)/gmp-impl.h mpn/gmp-mparam.h
+
+memory.o: $(srcdir)/memory.c $(H)
+mp_bpl.o: $(srcdir)/mp_bpl.c
+mp_clz_tab.o: $(srcdir)/mp_clz_tab.c
+mp_set_fns.o: $(srcdir)/mp_set_fns.c $(H)
+stack-alloc.o: $(srcdir)/stack-alloc.c $(srcdir)/stack-alloc.h
+version.o: $(srcdir)/version.c
+
+force:
+.PNONY: check install install-bsdmp install-info-files install-strip uninstall
+.PHONY: doc clean distclean maintainer-clean force info dvi
diff --git a/NEWS b/NEWS
new file mode 100644
index 000000000..b61c84069
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,56 @@
+NOTEWORTHY CHANGES IN GNU MP IN VERSION 2
+
+* Division routines in the mpz class have changed. There are three classes of
+ functions, that rounds the quotient to -infinity, 0, and +infinity,
+ respectively. The first class of functions have names that begin with
+ mpz_fdiv (f is short for floor), the second class' names begin with mpz_tdiv
+ (t is short for trunc), and the third class' names begin with mpz_cdiv (c is
+ short for ceil).
+
+ The old division routines beginning with mpz_m are similar to the new
+ mpz_fdiv, with the exception that some of the new functions return useful
+ values.
+
+ The old function names can still be used. All the old functions names will
+ now do floor division, not trunc division as some of them used to. This was
+ changed to make the functions more compatible with common mathematical
+ practice.
+
+ The mpz_mod and mpz_mod_ui functions now compute the mathematical mod
+ function. I.e., the sign of the 2nd argument is ignored.
+
+* The mpq assignment functions do not canonicalize their results. A new
+ function, mpq_canonicalize must be called by the user if the result is not
+ known to be canonical.
+* The mpn functions are now documented. These functions are intended for
+ very time critical applications, or applications that need full control over
+ memory allocation. Note that the mpn interface is irregular and hard to
+ use.
+* New functions for arbitrary precision floating point arithmetic. Names
+ begin with `mpf_'. Associated type mpf_t.
+* New and improved mpz functions, including much faster GCD, fast exact
+ division (mpz_divexact), bit scan (mpz_scan0 and mpz_scan1), and number
+ theoretical functions like Jacobi (mpz_jacobi) and multiplicative inverse
+ (mpz_invert).
+* New variable types (mpz_t and mpq_t) are available that makes syntax of
+ mpz and mpq calls nicer (no need for & before variables). The MP_INT and
+ MP_RAT types are still available for compatibility.
+* Uses GNU configure. This makes it possible to choose target architecture
+ and CPU variant, and to compile into a separate object directory.
+* Carefully optimized assembly for important inner loops. Support for DEC
+ Alpha, Amd 29000, HPPA 1.0 and 1.1, Intel pentium and generic x86, Intel
+ i960, Motorola MC68000, MC68020, MC88100, and MC88110, Motorola/IBM
+ PowerPC, National NS32000, IBM POWER, MIPS R3000, R4000, SPARCv7,
+ SuperSPARC, generic SPARCv8, and DEC VAX. Some support also for ARM,
+ Clipper, IBM ROMP (RT), and Pyramid AP/XP.
+* Faster. Thanks to the assembler code, new algorithms, and general tuning.
+ In particular, the speed on machines without GCC is improved.
+* Support for machines without alloca.
+* Now under the LGPL.
+
+INCOMPATIBILITIES BETWEEN GMP 1 AND GMP 2
+
+* mpq assignment functions do not canonicalize their results.
+* mpz division functions round differently.
+* mpz mod functions now really compute mod.
+* mpz_powm and mpz_powm_ui now really use mod for reduction.
diff --git a/PROJECTS b/PROJECTS
new file mode 100644
index 000000000..3007bd731
--- /dev/null
+++ b/PROJECTS
@@ -0,0 +1,270 @@
+IDEAS ABOUT THINGS TO WORK ON
+
+* mpq_cmp: Maybe the most sensible thing to do would be to multiply the, say,
+ 4 most significant limbs of each operand and compare them. If that is not
+ sufficient, do the same for 8 limbs, etc.
+
+* Write mpi, the Multiple Precision Interval Arithmetic layer.
+
+* Write `mpX_eval' that take lambda-like expressions and a list of operands.
+
+* As a general rule, recognize special operand values in mpz and mpf, and
+ use shortcuts for speed. Examples: Recognize (small or all) 2^n in
+ multiplication and division. Recognize small bases in mpz_pow_ui.
+
+* Implement lazy allocation? mpz->d == 0 would mean no allocation made yet.
+
+* Maybe store one-limb numbers according to Per Bothner's idea:
+ struct {
+ mp_ptr d;
+ union {
+ mp_limb val; /* if (d == NULL). */
+ mp_size size; /* Length of data array, if (d != NULL). */
+ } u;
+ };
+ Problem: We can't normalize to that format unless we free the space
+ pointed to by d, and therefore small values will not be stored in a
+ canonical way.
+
+* Document complexity of all functions.
+
+* Add predicate functions mpz_fits_signedlong_p, mpz_fits_unsignedlong_p,
+ mpz_fits_signedint_p, etc.
+
+ mpz_floor (mpz, mpq), mpz_trunc (mpz, mpq), mpz_round (mpz, mpq).
+
+* Better random number generators. There should be fast (like mpz_random),
+ very good (mpz_veryrandom), and special purpose (like mpz_random2). Sizes
+ in *bits*, not in limbs.
+
+* It'd be possible to have an interface "s = add(a,b)" with automatic GC.
+ If the mpz_xinit routine remembers the address of the variable we could
+ walk-and-mark the list of remembered variables, and free the space
+ occupied by the remembered variables that didn't get marked. Fairly
+ standard.
+
+* Improve speed for non-gcc compilers by defining umul_ppmm, udiv_qrnnd,
+ etc, to call __umul_ppmm, __udiv_qrnnd. A typical definition for
+ umul_ppmm would be
+ #define umul_ppmm(ph,pl,m0,m1) \
+ {unsigned long __ph; (pl) = __umul_ppmm (&__ph, (m0), (m1)); (ph) = __ph;}
+ In order to maintain just one version of longlong.h (gmp and gcc), this
+ has to be done outside of longlong.h.
+
+Bennet Yee at CMU proposes:
+* mpz_{put,get}_raw for memory oriented I/O like other *_raw functions.
+* A function mpfatal that is called for exceptions. Let the user override
+ a default definition.
+
+* Make all computation mpz_* functions return a signed int indicating if the
+ result was zero, positive, or negative?
+
+* Implement mpz_cmpabs, mpz_xor, mpz_to_double, mpz_to_si, mpz_lcm, mpz_dpb,
+ mpz_ldb, various bit string operations. Also mpz_@_si for most @??
+
+* Add macros for looping efficiently over a number's limbs:
+ MPZ_LOOP_OVER_LIMBS_INCREASING(num,limb)
+ { user code manipulating limb}
+ MPZ_LOOP_OVER_LIMBS_DECREASING(num,limb)
+ { user code manipulating limb}
+
+Brian Beuning proposes:
+ 1. An array of small primes
+ 3. A function to factor a mpz_t. [How do we return the factors? Maybe
+ we just return one arbitrary factor? In the latter case, we have to
+ use a data structure that records the state of the factoring routine.]
+ 4. A routine to look for "small" divisors of an mpz_t
+ 5. A 'multiply mod n' routine based on Montgomery's algorithm.
+
+Dough Lea proposes:
+ 1. A way to find out if an integer fits into a signed int, and if so, a
+ way to convert it out.
+ 2. Similarly for double precision float conversion.
+ 3. A function to convert the ratio of two integers to a double. This
+ can be useful for mixed mode operations with integers, rationals, and
+ doubles.
+
+Elliptic curve method description in the Chapter `Algorithms in Number
+Theory' in the Handbook of Theoretical Computer Science, Elsevier,
+Amsterdam, 1990. Also in Carl Pomerance's lecture notes on Cryptology and
+Computational Number Theory, 1990.
+
+* Harald Kirsh suggests:
+ mpq_set_str (MP_RAT *r, char *numerator, char *denominator).
+
+* New function: mpq_get_ifstr (int_str, frac_str, base,
+ precision_in_som_way, rational_number). Convert RATIONAL_NUMBER to a
+ string in BASE and put the integer part in INT_STR and the fraction part
+ in FRAC_STR. (This function would do a division of the numerator and the
+ denominator.)
+
+* Should mpz_powm* handle negative exponents?
+
+* udiv_qrnnd: If the denominator is normalized, the n0 argument has very
+ little effect on the quotient. Maybe we can assume it is 0, and
+ compensate at a later stage?
+
+* Better sqrt: First calculate the reciprocal square root, then multiply by
+ the operand to get the square root. The reciprocal square root can be
+ obtained through Newton-Raphson without division. To compute sqrt(A), the
+ iteration is,
+
+ 2
+ x = x (3 - A x )/2.
+ i+1 i i
+
+ The final result can be computed without division using,
+
+ sqrt(A) = A x .
+ n
+
+* Newton-Raphson using multiplication: We get twice as many correct digits
+ in each iteration. So if we square x(k) as part of the iteration, the
+ result will have the leading digits in common with the entire result from
+ iteration k-1. A _mpn_mul_lowpart could help us take advantage of this.
+
+* Peter Montgomery: If 0 <= a, b < p < 2^31 and I want a modular product
+ a*b modulo p and the long long type is unavailable, then I can write
+
+ typedef signed long slong;
+ typedef unsigned long ulong;
+ slong a, b, p, quot, rem;
+
+ quot = (slong) (0.5 + (double)a * (double)b / (double)p);
+ rem = (slong)((ulong)a * (ulong)b - (ulong)p * (ulong)quot);
+ if (rem < 0} {rem += p; quot--;}
+
+* Speed modulo arithmetic, using Montgomery's method or my pre-inversion
+ method. In either case, special arithmetic calls would be needed,
+ mpz_mmmul, mpz_mmadd, mpz_mmsub, plus some kind of initialization
+ functions. Better yet: Write a new mpr layer.
+
+* mpz_powm* should not use division to reduce the result in the loop, but
+ instead pre-compute the reciprocal of the MOD argument and do reduced_val
+ = val-val*reciprocal(MOD)*MOD, or use Montgomery's method.
+
+* mpz_mod_2expplussi -- to reduce a bignum modulo (2**n)+s
+
+* It would be a quite important feature never to allocate more memory than
+ really necessary for a result. Sometimes we can achieve this cheaply, by
+ deferring reallocation until the result size is known.
+
+* New macro in longlong.h: shift_rhl that extracts a word by shifting two
+ words as a unit. (Supported by i386, i860, HP-PA, POWER, 29k.) Useful
+ for shifting multiple precision numbers.
+
+* The installation procedure should make a test run of multiplication to
+ decide the threshold values for algorithm switching between the available
+ methods.
+
+* Fast output conversion of x to base B:
+ 1. Find n, such that (B^n > x).
+ 2. Set y to (x*2^m)/(B^n), where m large enough to make 2^n ~~ B^n
+ 3. Multiply the low half of y by B^(n/2), and recursively convert the
+ result. Truncate the low half of y and convert that recursively.
+ Complexity: O(M(n)log(n))+O(D(n))!
+
+* Improve division using Newton-Raphson. Check out "Newton Iteration and
+ Integer Division" by Stephen Tate in "Synthesis of Parallel Algorithms",
+ Morgan Kaufmann, 1993 ("beware of some errors"...)
+
+* Improve implementation of Karatsuba's algorithm. For most operand sizes,
+ we can reduce the number of operations by splitting differently.
+
+* Faster multiplication: The best approach is to first implement Toom-Cook.
+ People report that it beats Karatsuba's algorithm already at about 100
+ limbs. FFT would probably never beat a well-written Toom-Cook (not even for
+ millions of bits).
+
+FFT:
+{
+ * Multiplication could be done with Montgomery's method combined with
+ the "three primes" method described in Lipson. Maybe this would be
+ faster than to Nussbaumer's method with 3 (simple) moduli?
+
+ * Maybe the modular tricks below are not needed: We are using very
+ special numbers, Fermat numbers with a small base and a large exponent,
+ and maybe it's possible to just subtract and add?
+
+ * Modify Nussbaumer's convolution algorithm, to use 3 words for each
+ coefficient, calculating in 3 relatively prime moduli (e.g.
+ 0xffffffff, 0x100000000, and 0x7fff on a 32-bit computer). Both all
+ operations and CRR would be very fast with such numbers.
+
+ * Optimize the Schoenhage-Stassen multiplication algorithm. Take advantage
+ of the real valued input to save half of the operations and half of the
+ memory. Use recursive FFT with large base cases, since recursive FFT has
+ better memory locality. A normal FFT get 100% cache misses for large
+ enough operands.
+
+ * In the 3-prime convolution method, it might sometimes be a win to use 2,
+ 3, or 5 primes. Imagine that using 3 primes would require a transform
+ length of 2^n. But 2 primes might still sometimes give us correct
+ results with that same transform length, or 5 primes might allow us to
+ decrease the transform size to 2^(n-1).
+
+ To optimize floating-point based complex FFT we have to think of:
+
+ 1. The normal implementation accesses all input exactly once for each of
+ the log(n) passes. This means that we will get 0% cache hit when n >
+ our cache. Remedy: Reorganize computation to compute partial passes,
+ maybe similar to a standard recursive FFT implementation. Use a large
+ `base case' to make any extra overhead of this organization negligible.
+
+ 2. Use base-4, base-8 and base-16 FFT instead of just radix-2. This can
+ reduce the number of operations by 2x.
+
+ 3. Inputs are real-valued. According to Knuth's "Seminumerical
+ Algorithms", exercise 4.6.4-14, we can save half the memory and half
+ the operations if we take advantage of that.
+
+ 4. Maybe make it possible to write the innermost loop in assembly, since
+ that could win us another 2x speedup. (If we write our FFT to avoid
+ cache-miss (see #1 above) it might be logical to write the `base case'
+ in assembly.)
+
+ 5. Avoid multiplication by 1, i, -1, -i. Similarly, optimize
+ multiplication by (+-\/2 +- i\/2).
+
+ 6. Put as many bits as possible in each double (but don't waste time if
+ that doesn't make the transform size become smaller).
+
+ 7. For n > some large number, we will get accuracy problems because of the
+ limited precision of our floating point arithmetic. This can easily be
+ solved by using the Karatsuba trick a few times until our operands
+ become small enough.
+
+ 8. Precompute the roots-of-unity and store them in a vector.
+}
+
+* When a division result is going to be just one limb, (i.e. nsize-dsize is
+ small) normalization could be done in the division loop.
+
+* Never allocate temporary space for a source param that overlaps with a
+ destination param needing reallocation. Instead malloc a new block for
+ the destination (and free the source before returning to the caller).
+
+* Parallel addition. Since each processors have to tell it is ready to the
+ next processor, we can use simplified synchronization, and actually write
+ it in C: For each processor (apart from the least significant):
+
+ while (*svar != my_number)
+ ;
+ *svar = my_number + 1;
+
+ The least significant processor does this:
+
+ *svar = my_number + 1; /* i.e., *svar = 1 */
+
+ Before starting the addition, one processor has to store 0 in *svar.
+
+ Other things to think about for parallel addition: To avoid false
+ (cache-line) sharing, allocate blocks on cache-line boundaries.
+
+
+Local Variables:
+mode: text
+fill-column: 77
+fill-prefix: " "
+version-control: never
+End:
diff --git a/README b/README
new file mode 100644
index 000000000..3afa67745
--- /dev/null
+++ b/README
@@ -0,0 +1,137 @@
+ THE GNU MP LIBRARY
+
+
+GNU MP is a library for arbitrary precision arithmetic, operating on signed
+integers, rational numbers, and floating point numbers. It has a rich set
+of functions, and the functions have a regular interface.
+
+GNU MP is designed to be as fast as possible, both for small operands and for
+huge operands. The speed is achieved by using fullwords as the basic
+arithmetic type, by using fast algorithms, by carefully optimized assembly
+code for the most common inner loops for a lots of CPUs, and by a general
+emphasis on speed (instead of simplicity or elegance).
+
+The speed of GNU MP is believed to be faster than any other similar library.
+The advantage for GNU MP increases with the operand sizes for certain
+operations, since GNU MP in many cases has asymptotically faster algorithms.
+
+
+ GETTING STARTED
+
+First, you have to configure and compiler GNU MP. Simply typing
+
+ ./configure; make
+
+will normally do a reasonable job, but will not give optimal library
+execution speed. So unless you're very unpatient, please read the detailed
+instructions in the file INSTALL or in gmp.texi.
+
+Once you have compiled the library, you should write some small example, and
+make sure you can compile them. A typical compilation command is this:
+
+ gcc -g your-file.c -I<gmp-source-dir> <gmp-bin-dir>libgmp.a -lm
+
+If you have installed the library, you can simply do:
+
+ gcc -g your-file.c -lgmp -lm
+
+The -lm is normally not needed, since only a few functions in GNU MP use the
+math library.
+
+Here is a sample program that declares 2 variables, initializes them as
+required, and sets one of them from a signed integer, and the other from a
+string of digits. It then prints the product of the two numbers in base 10.
+
+ #include <stdio.h>
+ #include "gmp.h"
+
+ main ()
+ {
+ mpz_t a, b, p;
+
+ mpz_init (a); /* initialize variables */
+ mpz_init (b);
+ mpz_init (p);
+
+ mpz_set_si (a, 756839); /* assign variables */
+ mpz_set_str (b, "314159265358979323846", 0);
+ mpz_mul (p, a, b); /* generate product */
+ mpz_out_str (stdout, 10, p); /* print number without newline */
+ puts (""); /* print newline */
+
+ mpz_clear (a); /* clear out variables */
+ mpz_clear (b);
+ mpz_clear (p);
+
+ exit (0);
+ }
+
+This might look tedious, with all initializing and clearing. Fortunately
+some of these operations can be combined, and other operations can often be
+avoided. The example above would be written differently by an experienced
+GNU MP user:
+
+ #include <stdio.h>
+ #include "gmp.h"
+
+ main ()
+ {
+ mpz_t b, p;
+
+ mpz_init (p);
+
+ mpz_init_set_str (b, "314159265358979323846", 0);
+ mpz_mul_ui (p, b, 756839); /* generate product */
+ mpz_out_str (stdout, 10, p); /* print number without newline */
+ puts (""); /* print newline */
+
+ exit (0);
+ }
+
+
+ OVERVIEW OF GNU MP
+
+There are five classes of functions in GNU MP.
+
+ 1. Signed integer arithmetic functions, mpz_*. These functions are intended
+ to be easy to use, with their regular interface. The associated type is
+ `mpz_t'.
+
+ 2. Rational arithmetic functions, mpq_*. For now, just a small set of
+ functions necessary for basic rational arithmetics. The associated type
+ is `mpq_t'.
+
+ 3. Floating-point arithmetic functions, mpf_*. If the C type `double'
+ doesn't give enough precision for your application, declare your
+ variables as `mpf_t' instead, set the precision to any number desired,
+ and call the functions in the mpf class for the arithmetic operations.
+
+ 4. Positive-integer, hard-to-use, very low overhead functions are in the
+ mpn_* class. No memory management is performed. The caller must ensure
+ enough space is available for the results. The set of functions is not
+ regular, nor is the calling interface. These functions accept input
+ arguments in the form of pairs consisting of a pointer to the least
+ significant word, and a integral size telling how many limbs (= words)
+ the pointer points to.
+
+ Almost all calculations, in the entire package, are made by calling these
+ low-level functions.
+
+ 5. Berkeley MP compatible functions.
+
+ To use these functions, include the file "mp.h". You can test if you are
+ using the GNU version by testing if the symbol __GNU_MP__ is defined.
+
+For more information on how to use GNU MP, please refer to the documentation.
+It is composed from the file gmp.texi, and can be displayed on the screen or
+printed. How to do that, as well how to build the library, is described in
+the INSTALL file in this directory.
+
+
+ REPORTING BUGS
+
+If you find a bug in the library, please make sure to tell us about it!
+
+Report bugs and propose modifications and enhancements to
+bug-gmp@prep.ai.mit.edu. What information is needed in a good bug report is
+described in the manual.
diff --git a/SPEED b/SPEED
new file mode 100644
index 000000000..e888e17e5
--- /dev/null
+++ b/SPEED
@@ -0,0 +1,156 @@
+==============================================================================
+Cycle counts and throughput for low-level routines in GNU MP as currently
+implemented.
+
+A range means that the timing is data-dependent. The slower number of such
+an interval is usually the best performance estimate.
+
+The throughput value, measured in Gb/s (gigabits per second) has a meaning
+only for comparison between CPUs.
+
+A star before a line means that all values on that line are estimates. A
+star before a number means that that number is an estimate. A `p' before a
+number means that the code is not complete, but the timing is believed to be
+accurate.
+
+ | mpn_lshift mpn_add_n mpn_mul_1 mpn_addmul_1
+ | mpn_rshift mpn_sub_n mpn_submul_1
+------------+-----------------------------------------------------------------
+DEC/Alpha |
+EV4 | 4.75 cycles/64b 7.75 cycles/64b 42 cycles/64b 42 cycles/64b
+ 200MHz | 2.7 Gb/s 1.65 Gb/s 20 Gb/s 20 Gb/s
+EV5 old code| 4.0 cycles/64b 5.5 cycles/64b 18 cycles/64b 18 cycles/64b
+ 267MHz | 4.27 Gb/s 3.10 Gb/s 61 Gb/s 61 Gb/s
+ 417MHz | 6.67 Gb/s 4.85 Gb/s 95 Gb/s 95 Gb/s
+EV5 tuned | 3.25 cycles/64b 4.75 cycles/64b
+ 267MHz | 5.25 Gb/s 3.59 Gb/s as above
+ 417MHz | 8.21 Gb/s 5.61 Gb/s
+------------+-----------------------------------------------------------------
+Sun/SPARC |
+SPARC v7 | 14.0 cycles/32b 8.5 cycles/32b 37-54 cycl/32b 37-54 cycl/32b
+SuperSPARC | 3 cycles/32b 2.5 cycles/32b 8.2 cycles/32b 10.8 cycles/32b
+ 50MHz | 0.53 Gb/s 0.64 Gb/s 6.2 Gb/s 4.7 Gb/s
+**SuperSPARC| tuned addmul and submul will take: 9.25 cycles/32b
+MicroSPARC2 | ? 6.65 cycles/32b 30 cycles/32b 31.5 cycles/32b
+ 110MHz | ? 0.53 Gb/s 3.75 Gb/s 3.58 Gb/s
+SuperSPARC2 | ? ? ? ?
+Ultra/32 (4)| 2.5 cycles/32b 6.5 cycles/32b 13-27 cyc/32b 16-30 cyc/32b
+ 182MHz | 2.33 Gb/s 0.896 Gb/s 14.3-6.9 Gb/s
+Ultra/64 (5)| 2.5 cycles/64b 10 cycles/64b 40-70 cyc/64b 46-76 cyc/64b
+ 182MHz | 4.66 Gb/s 1.16 Gb/s 18.6-11 Gb/s
+HalSPARC64 | ? ? ? ?
+------------+-----------------------------------------------------------------
+SGI/MIPS |
+R3000 | 6 cycles/32b 9.25 cycles/32b 16 cycles/32b 16 cycles/32b
+ 40MHz | 0.21 Gb/s 0.14 Gb/s 2.56 Gb/s 2.56 Gb/s
+R4400/32 | 8.6 cycles/32b 10 cycles/32b 16-18 19-21
+ 200MHz | 0.74 Gb/s 0.64 Gb/s 13-11 Gb/s 11-9.6 Gb/s
+*R4400/64 | 8.6 cycles/64b 10 cycles/64b 22 cycles/64b 22 cycles/64b
+ *200MHz | 1.48 Gb/s 1.28 Gb/s 37 Gb/s 37 Gb/s
+R4600/32 | 6 cycles/64b 9.25 cycles/32b 15 cycles/32b 19 cycles/32b
+ 134MHz | 0.71 Gb/s 0.46 Gb/s 9.1 Gb/s 7.2 Gb/s
+R4600/64 | 6 cycles/64b 9.25 cycles/64b ? ?
+ 134MHz | 1.4 Gb/s 0.93 Gb/s ? ?
+R8000/64 | 3 cycles/64b 4.6 cycles/64b 8 cycles/64b 8 cycles/64b
+ 75MHz | 1.6 Gb/s 1.0 Gb/s 38 Gb/s 38 Gb/s
+*R10000/64 | 2 cycles/64b 3 cycles/64b 11 cycles/64b 11 cycles/64b
+ *200MHz | 6.4 Gb/s 4.27 Gb/s 74 Gb/s 74 Gb/s
+ *250MHz | 8.0 Gb/s 5.33 Gb/s 93 Gb/s 93 Gb/s
+------------+-----------------------------------------------------------------
+Motorola |
+MC68020 | ? 24 cycles/32b 62 cycles/32b 70 cycles/32b
+MC68040 | ? 6 cycles/32b 24 cycles/32b 25 cycles/32b
+MC88100 | >5 cycles/32b 4.6 cycles/32b 16/21 cyc/32b p 18/23 cyc/32b
+MC88110 wt | ? 3.75 cycles/32b 6 cycles/32b 8.5 cyc/32b
+*MC88110 wb | ? 2.25 cycles/32b 4 cycles/32b 5 cycles/32b
+------------+-----------------------------------------------------------------
+HP/PA-RISC |
+PA7000 | 4 cycles/32b 5 cycles/32b 9 cycles/32b 11 cycles/32b
+ 67MHz | 0.53 Gb/s 0.43 Gb/s 7.6 Gb/s 6.2 Gb/s
+PA7100 | 3.25 cycles/32b 4.25 cycles/32b 7 cycles/32b 8 cycles/32b
+ 99MHz | 0.97 Gb/s 0.75 Gb/s 14 Gb/s 12.8 Gb/s
+PA7100LC | ? ? ? ?
+PA7200 (3) | 3 cycles/32b 4 cycles/32b 7 cycles/32b 6.5 cycles/32b
+ 100MHz | 1.07 Gb/s 0.80 14 Gb/s 15.8 Gb/s
+PA7300LC | ? ? ? ?
+*PA8000 | 3 cycles/64b 4 cycles/64b 7 cycles/64b 6.5 cycles/64b
+ 180MHz | 3.84 Gb/s 2.88 Gb/s 105 Gb/s 113 Gb/s
+------------+-----------------------------------------------------------------
+Intel/x86 |
+386DX | 20 cycles/32b 17 cycles/32b 41-70 cycl/32b 50-79 cycl/32b
+ 16.7MHz | 0.027 Gb/s 0.031 Gb/s 0.42-0.24 Gb/s 0.34-0.22 Gb/s
+486DX | ? ? ? ?
+486DX4 | 9.5 cycles/32b 9.25 cycles/32b 17-23 cycl/32b 20-26 cycl/32b
+ 100MHz | 0.34 Gb/s 0.35 Gb/s 6.0-4.5 Gb/s 5.1-3.9 Gb/s
+Pentium | 2/6 cycles/32b 2.5 cycles/32b 13 cycles/32b 14 cycles/32b
+ 167MHz | 2.7/0.89 Gb/s 2.1 Gb/s 13.1 Gb/s 12.2 Gb/s
+Pentium Pro | 2.5 cycles/32b 3.5 cycles/32b 6 cycles/32b 9 cycles/32b
+ 200MHz | 2.6 Gb/s 1.8 Gb/s 34 Gb/s 23 Gb/s
+------------+-----------------------------------------------------------------
+IBM/POWER |
+RIOS 1 | 3 cycles/32b 4 cycles/32b 11.5-12.5 c/32b 14.5/15.5 c/32b
+RIOS 2 | 2 cycles/32b 2 cycles/32b 7 cycles/32b 8.5 cycles/32b
+------------+-----------------------------------------------------------------
+PowerPC |
+PPC601 (1) | 3 cycles/32b 6 cycles/32b 11-16 cycl/32b 14-19 cycl/32b
+PPC601 (2) | 5 cycles/32b 6 cycles/32b 13-22 cycl/32b 16-25 cycl/32b
+ 67MHz (2) | 0.43 Gb/s 0.36 Gb/s 5.3-3.0 Gb/s 4.3-2.7 Gb/s
+PPC603 | ? ? ? ?
+*PPC604 | 2 3 2 3
+ *167MHz | 57 Gb/s
+PPC620 | ? ? ? ?
+------------+-----------------------------------------------------------------
+Tege |
+Model 1 | 2 cycles/64b 3 cycles/64b 2 cycles/64b 3 cycles/64b
+ 250MHz | 8 Gb/s 5.3 Gb/s 500 Gb/s 340 Gb/s
+ 500MHz | 16 Gb/s 11 Gb/s 1000 Gb/s 680 Gb/s
+____________|_________________________________________________________________
+(1) Using POWER and PowerPC instructions
+(2) Using only PowerPC instructions
+(3) Actual timing for shift/add/sub depends on code alignment. PA7000 code
+ is smaller and therefore often faster on this CPU.
+(4) Multiplication routines modified for bogus UltraSPARC early-out
+ optimization. Smaller operand is put in rs1, not rs2 as it should
+ according to the SPARC architecture manuals.
+(5) Preliminary timings, since there is no stable 64-bit environment.
+(6) Use mulu.d at least for mpn_lshift. With mak/extu/or, we can only get
+ to 2 cycles/32b.
+
+=============================================================================
+Estimated theoretical asymptotic cycle counts for low-level routines:
+
+ | mpn_lshift mpn_add_n mpn_mul_1 mpn_addmul_1
+ | mpn_rshift mpn_sub_n mpn_submul_1
+------------+-----------------------------------------------------------------
+DEC/Alpha |
+EV4 | 3 cycles/64b 5 cycles/64b 42 cycles/64b 42 cycles/64b
+EV5 | 3 cycles/64b 4 cycles/64b 18 cycles/64b 18 cycles/64b
+------------+-----------------------------------------------------------------
+Sun/SPARC |
+SuperSPARC | 2.5 cycles/32b 2 cycles/32b 8 cycles/32b 9 cycles/32b
+------------+-----------------------------------------------------------------
+SGI/MIPS |
+R4400/32 | 5 cycles/64b 8 cycles/64b 16 cycles/64b 16 cycles/64b
+R4400/64 | 5 cycles/64b 8 cycles/64b 22 cycles/64b 22 cycles/64b
+R4600 |
+------------+-----------------------------------------------------------------
+HP/PA-RISC |
+PA7100 | 3 cycles/32b 4 cycles/32b 6.5 cycles/32b 7.5 cycles/32b
+PA7100LC |
+------------+-----------------------------------------------------------------
+Motorola |
+MC88110 | 1.5 cyc/32b (6) 1.5 cycle/32b 1.5 cycles/32b 2.25 cycles/32b
+------------+-----------------------------------------------------------------
+Intel/x86 |
+486DX4 |
+Pentium P5x | 5 cycles/32b 2 cycles/32b 11.5 cycles/32b 13 cycles/32b
+Pentium Pro | 2 cycles/32b 3 cycles/32b 4 cycles/32b 6 cycles/32b
+------------+-----------------------------------------------------------------
+IBM/POWER |
+RIOS 1 | 3 cycles/32b 4 cycles/32b
+RIOS 2 | 1.5 cycles/32b 2 cycles/32b 4.5 cycles/32b 5.5 cycles/32b
+------------+-----------------------------------------------------------------
+PowerPC |
+PPC601 (1) | 3 cycles/32b ?4 cycles/32b
+PPC601 (2) | 4 cycles/32b ?4 cycles/32b
+____________|_________________________________________________________________
diff --git a/config.guess b/config.guess
new file mode 100755
index 000000000..afd200a33
--- /dev/null
+++ b/config.guess
@@ -0,0 +1,592 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 93, 94, 95, 1996 Free Software Foundation, Inc.
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Written by Per Bothner <bothner@cygnus.com>.
+# The master version of this file is at the FSF in /home/gd/gnu/lib.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit system type (host/target name).
+#
+# Only a few systems have been added to this list; please add others
+# (but try to keep the structure clean).
+#
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 8/24/94.)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ alpha:OSF1:[VX]*:*)
+ # After 1.2, OSF1 uses "V1.3" for uname -r.
+ # After 4.x, OSF1 uses "X4.x" for uname -r.
+ echo alpha-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VX]//'`
+ exit 0 ;;
+ alpha:OSF1:*:*)
+ # 1.2 uses "1.2" for uname -r.
+ echo alpha-dec-osf${UNAME_RELEASE}
+ exit 0 ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit 0 ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-cbm-sysv4
+ exit 0;;
+ amiga:NetBSD:*:*)
+ echo m68k-cbm-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit 0;;
+ Pyramid*:OSx*:*:*)
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit 0 ;;
+ sun4*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit 0 ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:NetBSD:*:*)
+ echo m68k-atari-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3*:NetBSD:*:*)
+ echo m68k-sun-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:NetBSD:*:*)
+ echo m68k-apple-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ mips:*:4*:UMIPS)
+ echo mips-mips-riscos4sysv
+ exit 0 ;;
+ mips:*:5*:RISCos)
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit 0 ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit 0 ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit 0 ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit 0 ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88100 ] ; then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \
+ -o ${TARGET_BINARY_INTERFACE}x = x ] ; then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit 0 ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit 0 ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit 0 ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit 0 ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i[34]86:AIX:*:*)
+ echo i386-ibm-aix
+ exit 0 ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ sed 's/^ //' << EOF >dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ echo rs6000-ibm-aix3.2.5
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit 0 ;;
+ *:AIX:*:4)
+ if /usr/sbin/lsattr -EHl proc0 | grep POWER >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=4.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit 0 ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit 0 ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit 0 ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit 0 ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit 0 ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit 0 ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit 0 ;;
+ 9000/[3478]??:HP-UX:*:*)
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/7?? | 9000/8?[679] ) HP_ARCH=hppa1.1 ;;
+ 9000/8?? ) HP_ARCH=hppa1.0 ;;
+ esac
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ 3050*:HI-UX:*:*)
+ sed 's/^ //' << EOF >dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ echo unknown-hitachi-hiuxwe2
+ exit 0 ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit 0 ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit 0 ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit 0 ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit 0 ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit 0 ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ CRAY*X-MP:*:*:*)
+ echo xmp-cray-unicos
+ exit 0 ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE}
+ exit 0 ;;
+ CRAY*C90:*:*:*)
+ echo c90-cray-unicos${UNAME_RELEASE}
+ exit 0 ;;
+ CRAY-2:*:*:*)
+ echo cray2-cray-unicos
+ exit 0 ;;
+ hp3[0-9][05]:NetBSD:*:*)
+ echo m68k-hp-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ i[34]86:BSD/386:*:* | *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:FreeBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit 0 ;;
+ *:NetBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ exit 0 ;;
+ i*:CYGWIN*:*)
+ echo i386-unknown-cygwin32
+ exit 0 ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin32
+ exit 0 ;;
+ *:GNU:*:*)
+ echo `echo ${UNAME_MACHINE}|sed -e 's,/.*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit 0 ;;
+ *:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us.
+ ld_help_string=`ld --help 2>&1`
+ if echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: elf_i[345]86"; then
+ echo "${UNAME_MACHINE}-unknown-linux" ; exit 0
+ elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: i[345]86linux"; then
+ echo "${UNAME_MACHINE}-unknown-linuxaout" ; exit 0
+ elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: i[345]86coff"; then
+ echo "${UNAME_MACHINE}-unknown-linuxcoff" ; exit 0
+ elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: m68kelf"; then
+ echo "${UNAME_MACHINE}-unknown-linux" ; exit 0
+ elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: m68klinux"; then
+ echo "${UNAME_MACHINE}-unknown-linuxaout" ; exit 0
+ elif test "${UNAME_MACHINE}" = "alpha" ; then
+ echo alpha-unknown-linux ; exit 0
+ else
+ # Either a pre-BFD a.out linker (linuxoldld) or one that does not give us
+ # useful --help. Gcc wants to distinguish between linuxoldld and linuxaout.
+ test ! -d /usr/lib/ldscripts/. \
+ && echo "${UNAME_MACHINE}-unknown-linuxoldld" && exit 0
+ # Determine whether the default compiler is a.out or elf
+ cat >dummy.c <<EOF
+main(argc, argv)
+int argc;
+char *argv[];
+{
+#ifdef __ELF__
+ printf ("%s-unknown-linux\n", argv[1]);
+#else
+ printf ("%s-unknown-linuxaout\n", argv[1]);
+#endif
+ return 0;
+}
+EOF
+ ${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ fi ;;
+# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions
+# are messed up and put the nodename in both sysname and nodename.
+ i[34]86:DYNIX/ptx:4*:*)
+ echo i386-sequent-sysv4
+ exit 0 ;;
+ i[34]86:*:4.*:* | i[34]86:SYSTEM_V:4.*:*)
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
+ else
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ i[34]86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-unknown-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ echo ${UNAME_MACHINE}-unknown-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-unknown-sysv32
+ fi
+ exit 0 ;;
+ Intel:Mach:3*:*)
+ echo i386-unknown-mach3
+ exit 0 ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit 0 ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit 0 ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit 0 ;;
+ M680[234]0:*:R3V[567]*:*)
+ test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+ 3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0)
+ uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4.3 && exit 0 ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4 && exit 0 ;;
+ m680[234]0:LynxOS:2.[23]*:*)
+ echo m68k-lynx-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit 0 ;;
+ i[34]86:LynxOS:2.[23]*:*)
+ echo i386-lynx-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ TSUNAMI:LynxOS:2.[23]*:*)
+ echo sparc-lynx-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ rs6000:LynxOS:2.[23]*:*)
+ echo rs6000-lynx-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit 0 ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+cat >dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ printf ("%s-next-nextstep%s\n", __ARCHITECTURE__, version==2 ? "2" : "3");
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-unknown-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+#if !defined (ultrix)
+ printf ("vax-dec-bsd\n"); exit (0);
+#else
+ printf ("vax-dec-ultrix\n"); exit (0);
+#endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0
+rm -f dummy.c dummy
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ c34*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ c38*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ c4*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ esac
+fi
+
+#echo '(Unable to guess system type)' 1>&2
+
+exit 1
diff --git a/config.sub b/config.sub
new file mode 100755
index 000000000..73515201b
--- /dev/null
+++ b/config.sub
@@ -0,0 +1,1094 @@
+#! /bin/sh
+# Configuration validation subroutine script, version 1.1.
+# Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+if [ x$1 = x ]
+then
+ echo Configuration name missing. 1>&2
+ echo "Usage: $0 CPU-MFR-OPSYS" 1>&2
+ echo "or $0 ALIAS" 1>&2
+ echo where ALIAS is a recognized configuration type. 1>&2
+ exit 1
+fi
+
+# First pass through any local machine types.
+case $1 in
+ *local*)
+ echo $1
+ exit 0
+ ;;
+ *)
+ ;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS (if any).
+basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+if [ $basic_machine != $1 ]
+then os=`echo $1 | sed 's/.*-/-/'`
+else os=; fi
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp )
+ os=
+ basic_machine=$1
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond ) # CYGNUS LOCAL
+ os=
+ basic_machine=$1
+ ;;
+ -apple*) # CYGNUS LOCAL
+ os=
+ basic_machine=$1
+ ;;
+ -scout) # CYGNUS LOCAL
+ ;;
+ -wrs) # CYGNUS LOCAL
+ os=vxworks
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ tahoe | i[345]86 | i860 | m68k | m68000 | m88k | ns32k | arm | armeb \
+ | armel | pyramid \
+ | tron | a29k | 580 | i960 | h8300 | hppa1.0 | hppa1.1 \
+ | alpha | we32k | ns16k | clipper | sparclite | i370 | sh \
+ | powerpc | powerpcle | sparc64 | 1750a | dsp16xx | mips64 | mipsel \
+ | pdp11 | mips64el | mips64orion | mips64orionel \
+ | sparc | supersparc | microsparc | ultrasparc)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m88110 | m680[012346]0 | m683?2 | m68360 | z8k | v70 | h8500 | w65) # CYGNUS LOCAL
+ basic_machine=$basic_machine-unknown
+ ;;
+ mips64vr4300 | mips64vr4300el) # CYGNUS LOCAL jsmith
+ basic_machine=$basic_machine-unknown
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ vax-* | tahoe-* | i[3456]86-* | i860-* | m68k-* | m68000-* | m88k-* \
+ | sparc-* | ns32k-* | fx80-* | arm-* | arme[lb]-* | c[123]* \
+ | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* | power-* \
+ | none-* | 580-* | cray2-* | h8300-* | i960-* | xmp-* | ymp-* \
+ | hppa1.0-* | hppa1.1-* | alpha-* | we32k-* | cydra-* | ns16k-* \
+ | pn-* | np1-* | xps100-* | clipper-* | orion-* | sparclite-* \
+ | pdp11-* | sh-* | powerpc-* | powerpcle-* | sparc64-* \
+ | mips64-* | mipsel-* | mips64el-* | mips64orion-* \
+ | mips64orionel-* | supersparc-* | microsparc-* | ultrasparc-*)
+ ;;
+ m88110-* | m680[012346]0-* | m683?2-* | m68360-* | z8k-* | h8500-*) # CYGNUS LOCAL
+ ;;
+ mips64vr4300-* | mips64vr4300el-*) # CYGNUS LOCAL jsmith
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd) # CYGNUS LOCAL
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif) # CYGNUS LOCAL
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ adobe68k) # CYGNUS LOCAL
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-cbm
+ ;;
+ amigados)
+ basic_machine=m68k-cbm
+ os=-amigados
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-cbm
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd) # CYGNUS LOCAL
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ arm | armel | armeb)
+ basic_machine=arm-arm
+ os=-aout
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ [ctj]90-cray)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ cray2)
+ basic_machine=cray2-cray
+ os=-unicos
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE) # CYGNUS LOCAL
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray) # CYGNUS LOCAL
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms) # CYGNUS LOCAL
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ w89k-*) # CYGNUS LOCAL
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ op50n-*) # CYGNUS LOCAL
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ op60c-*) # CYGNUS LOCAL
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ hppro) # CYGNUS LOCAL
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k7[0-9][0-9] | hp7[0-9][0-9] | hp9k8[0-9]7 | hp8[0-9]7)
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppaosf) # CYGNUS LOCAL
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i[3456]86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'`
+ os=-sysv32
+ ;;
+ i[3456]86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'`
+ os=-sysv4
+ ;;
+ i[3456]86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'`
+ os=-sysv
+ ;;
+ i[3456]86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'`
+ os=-solaris2
+ ;;
+ i386mach) # CYGNUS LOCAL
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta) # CYGNUS LOCAL
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ i386-go32 | go32) # CYGNUS LOCAL
+ basic_machine=i386-unknown
+ os=-go32
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ monitor) # CYGNUS LOCAL
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ msdos) # CYGNUS LOCAL
+ basic_machine=i386-unknown
+ os=-msdos
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown # CYGNUS LOCAL
+ os=-netbsd
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70) # CYGNUS LOCAL
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ OSE68000 | ose68000) # CYGNUS LOCAL
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k) # CYGNUS LOCAL
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pentium | p5)
+ basic_machine=i586-intel
+ ;;
+ pentiumpro | p6)
+ basic_machine=i686-intel
+ ;;
+ pentium-* | p5-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ k5)
+ # We don't have specific support for AMD's K5 yet, so just call it a Pentium
+ basic_machine=i586-amd
+ ;;
+ nexgen)
+ # We don't have specific support for Nexgen yet, so just call it a Pentium
+ basic_machine=i586-nexgen
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=rs6000-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ rom68k) # CYGNUS LOCAL
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ sa29200) # CYGNUS LOCAL
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sparclite-wrs) # CYGNUS LOCAL
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sparcfrw) # CYGNUS LOCAL
+ basic_machine=sparcfrw-sun
+ os=-sunos4
+ ;;
+ sparcfrwcompat) # CYGNUS LOCAL
+ basic_machine=sparcfrwcompat-sun
+ os=-sunos4
+ ;;
+ sparclitefrw) # CYGNUS LOCAL
+ basic_machine=sparclitefrw-fujitsu
+ ;;
+ sparclitefrwcompat) # CYGNUS LOCAL
+ basic_machine=sparclitefrwcompat-fujitsu
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000) # CYGNUS LOCAL
+ basic_machine=m68k-tandem
+ ;;
+ stratus) # CYGNUS LOCAL
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810) # CYGNUS LOCAL
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k) # CYGNUS LOCAL
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*) # CYGNUS LOCAL
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ xmp)
+ basic_machine=xmp-cray
+ os=-unicos
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ z8k-*-coff) # CYGNUS LOCAL
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k) # CYGNUS LOCAL
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n) # CYGNUS LOCAL
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c) # CYGNUS LOCAL
+ basic_machine=hppa1.1-oki
+ ;;
+ mips)
+ basic_machine=mips-mips
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sparc)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw) # CYGNUS LOCAL
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw) # CYGNUS LOCAL
+ basic_machine=powerpc-apple
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -unixware* | svr4*)
+ os=-sysv4
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative must end in a *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -lites* | -minix* | -genix* | -ultrix* | -irix* \
+ | -vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[3456]* \
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigados* | -msdos* | -moss* | -newsos* | -unicos* | -aos* \
+ | -nindy* | -vxworks* | -ebmon* | -hms* | -mvs* | -clix* \
+ | -riscos* | -linux* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -netbsd* | -freebsd* | -riscix* | -lites* \
+ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta | -udi \
+ | -eabi* | -ieee*)
+ ;;
+ # CYGNUS LOCAL
+ -go32 | -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -proelf | -os9* \
+ | -macos* | -mpw* | -magic* | -pe* | -win32)
+ ;;
+ -mac*) # CYGNUS LOCAL
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -386bsd) # CYGNUS LOCAL
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*) # CYGNUS LOCAL
+ os=-ose
+ ;;
+ -es1800*) # CYGNUS LOCAL
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco) # CYGNUS LOCAL
+ os=-aout
+ ;;
+ mips*-cisco) # CYGNUS LOCAL
+ os=-elf
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-wec) # CYGNUS LOCAL
+ os=-proelf
+ ;;
+ *-winbond) # CYGNUS LOCAL
+ os=-proelf
+ ;;
+ *-oki) # CYGNUS LOCAL
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigados
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ *-rom68k) # CYGNUS LOCAL
+ os=-coff
+ ;;
+ *-*bug) # CYGNUS LOCAL
+ os=-coff
+ ;;
+ *-apple) # CYGNUS LOCAL
+ os=-macos
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -bosx*) # CYGNUS LOCAL
+ vendor=bull
+ ;;
+ -lynxos*)
+ vendor=lynx
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -vxworks*)
+ vendor=wrs
+ ;;
+ -hms*) # CYGNUS LOCAL
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*) # CYGNUS LOCAL
+ vendor=apple
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
diff --git a/config/mt-m88110 b/config/mt-m88110
new file mode 100644
index 000000000..071f8fa1b
--- /dev/null
+++ b/config/mt-m88110
@@ -0,0 +1 @@
+XCFLAGS = -m88110
diff --git a/config/mt-sprc8-gcc b/config/mt-sprc8-gcc
new file mode 100644
index 000000000..bc706a961
--- /dev/null
+++ b/config/mt-sprc8-gcc
@@ -0,0 +1 @@
+XCFLAGS = -mv8
diff --git a/config/mt-supspc-gcc b/config/mt-supspc-gcc
new file mode 100644
index 000000000..92a0924d4
--- /dev/null
+++ b/config/mt-supspc-gcc
@@ -0,0 +1 @@
+XCFLAGS = -mv8 -DSUPERSPARC
diff --git a/configure b/configure
new file mode 100755
index 000000000..5d9e9954a
--- /dev/null
+++ b/configure
@@ -0,0 +1,1263 @@
+#!/bin/sh
+
+### WARNING: this file contains embedded tabs. Do not run untabify on this file.
+
+# Configuration script
+# Copyright (C) 1988, 90, 91, 92, 93, 94 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# This file was originally written by K. Richard Pixley.
+
+#
+# Shell script to create proper links to machine-dependent files in
+# preparation for compilation.
+#
+# If configure succeeds, it leaves its status in config.status.
+# If configure fails after disturbing the status quo,
+# config.status is removed.
+#
+
+export PATH || (echo "OOPS, this isn't sh. Desperation time. I will feed myself to sh."; sh $0 $argv; kill $$)
+
+remove=rm
+hard_link=ln
+symbolic_link='ln -s'
+
+#for Test
+#remove="echo rm"
+#hard_link="echo ln"
+#symbolic_link="echo ln -s"
+
+# clear some things potentially inherited from environment.
+
+Makefile=Makefile
+Makefile_in=Makefile.in
+arguments=
+build_alias=
+cache_file=
+cache_file_option=
+configdirs=
+exec_prefix=
+exec_prefixoption=
+fatal=
+floating_point=default
+gas=default
+host_alias=NOHOST
+host_makefile_frag=
+moveifchange=
+norecursion=
+other_options=
+package_makefile_frag=
+prefix=/usr/local
+progname=
+program_prefix=
+program_prefixoption=
+program_suffix=
+program_suffixoption=
+program_transform_name=
+program_transform_nameoption=
+redirect=">/dev/null"
+removing=
+site=
+site_makefile_frag=
+site_option=
+srcdir=
+srctrigger=
+subdirs=
+target_alias=NOTARGET
+target_makefile_frag=
+undefs=NOUNDEFS
+version="$Revision$"
+x11=default
+
+### we might need to use some other shell than /bin/sh for running subshells
+#
+config_shell=${CONFIG_SHELL-/bin/sh}
+
+NO_EDIT="This file was generated automatically by configure. Do not edit."
+
+## this is a little touchy and won't always work, but...
+##
+## if the argv[0] starts with a slash then it is an absolute name that can (and
+## must) be used as is.
+##
+## otherwise, if argv[0] has no slash in it, we can assume that it is on the
+## path. Since PATH might include "." we also add `pwd` to the end of PATH.
+##
+
+progname=$0
+# if PWD already has a value, it is probably wrong.
+if [ -n "$PWD" ]; then PWD=`pwd`; fi
+
+case "${progname}" in
+/*) ;;
+*/*) ;;
+*)
+ PATH=$PATH:${PWD=`pwd`} ; export PATH
+ ;;
+esac
+
+# Loop over all args
+
+while :
+do
+
+# Break out if there are no more args
+ case $# in
+ 0)
+ break
+ ;;
+ esac
+
+# Get the first arg, and shuffle
+ option=$1
+ shift
+
+# Make all options have two hyphens
+ orig_option=$option # Save original for error messages
+ case $option in
+ --*) ;;
+ -*) option=-$option ;;
+ esac
+
+# Split out the argument for options that take them
+ case $option in
+ --*=*)
+ optarg=`echo $option | sed -e 's/^[^=]*=//'`
+ arguments="$arguments $option"
+ ;;
+# These options have mandatory values. Since we didn't find an = sign,
+# the value must be in the next argument
+ --bu* | --cache* | --ex* | --ho* | --pre* | --program-p* | --program-s* | --program-t* | --si* | --sr* | --ta* | --tm* | --x-* | --bi* | --sb* | --li* | --da* | --sy* | --sh* | --lo* | --in* | --ol* | --ma*)
+ optarg=$1
+ shift
+ arguments="$arguments $option=$optarg"
+ ;;
+ --v)
+ arguments="$arguments -v"
+ ;;
+ --*)
+ arguments="$arguments $option"
+ ;;
+ esac
+
+# Now, process the options
+ case $option in
+
+ --build* | --bu*)
+ case "$build_alias" in
+ "") build_alias=$optarg ;;
+ *) echo '***' Can only configure for one build machine at a time. 1>&2
+ fatal=yes
+ ;;
+ esac
+ ;;
+ --cache*)
+ cache_file=$optarg
+ ;;
+ --disable-*)
+ enableopt=`echo ${option} | sed 's:^--disable-:enable_:;s:-:_:g'`
+ eval $enableopt=no
+ disableoptions="$disableoptions $option"
+ ;;
+ --enable-*)
+ case "$option" in
+ *=*) ;;
+ *) optarg=yes ;;
+ esac
+
+ enableopt=`echo ${option} | sed 's:^--::;s:=.*$::;s:-:_:g'`
+ eval $enableopt="$optarg"
+ enableoptions="$enableoptions $option"
+ ;;
+ --exec-prefix* | --ex*)
+ exec_prefix=$optarg
+ exec_prefixoption="--exec-prefix=$optarg"
+ ;;
+ --gas | --g*)
+ gas=yes
+ ;;
+ --help | --he*)
+ fatal=yes
+ ;;
+ --host* | --ho*)
+ case $host_alias in
+ NOHOST) host_alias=$optarg ;;
+ *) echo '***' Can only configure for one host at a time. 1>&2
+ fatal=yes
+ ;;
+ esac
+ ;;
+ --nfp | --nf*)
+ floating_point=no
+ floating_pointoption="--nfp"
+ ;;
+ --norecursion | --no*)
+ norecursion=yes
+ ;;
+ --prefix* | --pre*)
+ prefix=$optarg
+ prefixoption="--prefix=$optarg"
+ ;;
+ --program-prefix* | --program-p*)
+ program_prefix=$optarg
+ program_prefixoption="--program-prefix=$optarg"
+ ;;
+ --program-suffix* | --program-s*)
+ program_suffix=$optarg
+ program_suffixoption="--program-suffix=$optarg"
+ ;;
+ --program-transform-name* | --program-t*)
+ # Double any backslashes or dollar signs in the argument
+ program_transform_name="${program_transform_name} -e `echo ${optarg} | sed -e 's/\\\\/\\\\\\\\/g' -e 's/\\\$/$$/g'`"
+ program_transform_nameoption="${program_transform_nameoption} --program-transform-name='$optarg'"
+ ;;
+ --rm)
+ removing=--rm
+ ;;
+ --silent | --sil* | --quiet | --q*)
+ redirect=">/dev/null"
+ verbose=--silent
+ ;;
+ --site* | --sit*)
+ site=$optarg
+ site_option="--site=$optarg"
+ ;;
+ --srcdir*/ | --sr*/)
+ # Remove trailing slashes. Otherwise, when the file name gets
+ # bolted into an object file as debug info, it has two slashes
+ # in it. Ordinarily this is ok, but emacs takes double slash
+ # to mean "forget the first part".
+ srcdir=`echo $optarg | sed -e 's:/$::'`
+ ;;
+ --srcdir* | --sr*)
+ srcdir=$optarg
+ ;;
+ --target* | --ta*)
+ case $target_alias in
+ NOTARGET) target_alias=$optarg ;;
+ *) echo '***' Can only configure for one target at a time. 1>&2
+ fatal=yes
+ ;;
+ esac
+ ;;
+ --tmpdir* | --tm*)
+ TMPDIR=$optarg
+ tmpdiroption="--tmpdir=$optarg"
+ ;;
+ --verbose | --v | --verb*)
+ redirect=
+ verbose=--verbose
+ ;;
+ --version | --V | --vers*)
+ echo "This is Cygnus Configure version" `echo ${version} | sed 's/[ $:]//g'`
+ exit 0
+ ;;
+ --with-*)
+ case "$option" in
+ *=*) ;;
+ *) optarg=yes ;;
+ esac
+
+ withopt=`echo ${option} | sed 's:^--::;s:=.*$::;s:-:_:g'`
+ eval $withopt="$optarg"
+ withoptions="$withoptions $option"
+ ;;
+ --without-*)
+ withopt=`echo ${option} | sed 's:^--::;s:out::;s:-:_:g'`
+ eval $withopt=no
+ withoutoptions="$withoutoptions $option"
+ ;;
+ --x) with_x=yes
+ withoptions="$withoptions --with-x"
+ ;;
+ --x-i* | --x-l*) other_options="$other_options $orig_option"
+ ;;
+ --bi* | --sb* | --li* | --da* | --sy* | --sh* | --lo* | --in* | --ol* | --ma*)
+ # These options were added to autoconf for emacs.
+ ;;
+ --*)
+ echo "configure: Unrecognized option: \"$orig_option\"; use --help for usage." >&2
+ exit 1
+ ;;
+ *)
+ case $undefs in
+ NOUNDEFS) undefs=$option ;;
+ *) echo '***' Can only configure for one host and one target at a time. 1>&2
+ fatal=yes
+ ;;
+ esac
+ ;;
+ esac
+done
+
+# process host and target
+
+# Do some error checking and defaulting for the host and target type.
+# The inputs are:
+# configure --host=HOST --target=TARGET UNDEFS
+#
+# The rules are:
+# 1. You aren't allowed to specify --host, --target, and undefs at the
+# same time.
+# 2. Host defaults to undefs.
+# 3. If undefs is not specified, then host defaults to the current host,
+# as determined by config.guess.
+# 4. Target defaults to undefs.
+# 5. If undefs is not specified, then target defaults to host.
+
+case "${fatal}" in
+"")
+ # Make sure that host, target & undefs aren't all specified at the
+ # same time.
+ case $host_alias---$target_alias---$undefs in
+ NOHOST---*---* | *---NOTARGET---* | *---*---NOUNDEFS)
+ ;;
+ *) echo '***' Can only configure for one host and one target at a time. 1>&2
+ fatal=yes
+ break 2
+ ;;
+ esac
+
+ # Now, do defaulting for host.
+ case $host_alias in
+ NOHOST)
+ case $undefs in
+ NOUNDEFS)
+ # Neither --host option nor undefs were present.
+ # Call config.guess.
+ guesssys=`echo ${progname} | sed 's/configure$/config.guess/'`
+ if host_alias=`${guesssys}`
+ then
+ # If the string we are going to use for
+ # the target is a prefix of the string
+ # we just guessed for the host, then
+ # assume we are running native, and force
+ # the same string for both target and host.
+ case $target_alias in
+ NOTARGET) ;;
+ *)
+ if expr $host_alias : $target_alias >/dev/null
+ then
+ host_alias=$target_alias
+ fi
+ ;;
+ esac
+ echo "Configuring for a ${host_alias} host." 1>&2
+ arguments="--host=$host_alias $arguments"
+ else
+ echo 'Config.guess failed to determine the host type. You need to specify one.' 1>&2
+ fatal=yes
+ fi
+ ;;
+ *)
+ host_alias=$undefs
+ arguments="--host=$host_alias $arguments"
+ undefs=NOUNDEFS
+ ;;
+ esac
+ esac
+
+ # Do defaulting for target. If --target option isn't present, default
+ # to undefs. If undefs isn't present, default to host.
+ case $target_alias in
+ NOTARGET)
+ case $undefs in
+ NOUNDEFS)
+ target_alias=$host_alias
+ ;;
+ *)
+ target_alias=$undefs
+ arguments="--target=$target_alias $arguments"
+ ;;
+ esac
+ esac
+ ;;
+*) ;;
+esac
+
+if [ -n "${fatal}" -o "${host_alias}" = "help" ] ; then
+ exec 1>&2
+ echo Usage: configure [OPTIONS] [HOST]
+ echo
+ echo Options: [defaults in brackets]
+ echo ' --prefix=MYDIR install into MYDIR [/usr/local]'
+ echo ' --exec-prefix=MYDIR install host-dependent files into MYDIR [/usr/local]'
+ echo ' --help print this message [normal config]'
+ echo ' --build=BUILD configure for building on BUILD [BUILD=HOST]'
+ echo ' --host=HOST configure for HOST [determined via config.guess]'
+ echo ' --norecursion configure this directory only [recurse]'
+ echo ' --program-prefix=FOO prepend FOO to installed program names [""]'
+ echo ' --program-suffix=FOO append FOO to installed program names [""]'
+ echo ' --program-transform-name=P transform installed names by sed pattern P [""]'
+ echo ' --site=SITE configure with site-specific makefile for SITE'
+ echo ' --srcdir=DIR find the sources in DIR [. or ..]'
+ echo ' --target=TARGET configure for TARGET [TARGET=HOST]'
+ echo ' --tmpdir=TMPDIR create temporary files in TMPDIR [/tmp]'
+ echo ' --nfp configure for software floating point [hard float]'
+ echo ' --with-FOO, --with-FOO=BAR package FOO is available (parameter BAR)'
+ echo ' --without-FOO package FOO is NOT available'
+ echo ' --enable-FOO, --enable-FOO=BAR include feature FOO (parameter BAR)'
+ echo ' --disable-FOO do not include feature FOO'
+ echo
+ echo 'Where HOST and TARGET are something like "sparc-sunos", "mips-sgi-irix5", etc.'
+ echo
+ if [ -r config.status ] ; then
+ cat config.status
+ fi
+
+ exit 1
+fi
+
+configsub=`echo ${progname} | sed 's/configure$/config.sub/'`
+moveifchange=`echo ${progname} | sed 's/configure$/move-if-change/'`
+
+# this is a hack. sun4 must always be a valid host alias or this will fail.
+if ${configsub} sun4 >/dev/null 2>&1 ; then
+ true
+else
+ echo '***' cannot find config.sub. 1>&2
+ exit 1
+fi
+
+touch config.junk
+if ${moveifchange} config.junk config.trash ; then
+ true
+else
+ echo '***' cannot find move-if-change. 1>&2
+ exit 1
+fi
+rm -f config.junk config.trash
+
+case "${srcdir}" in
+"")
+ if [ -r configure.in ] ; then
+ srcdir=.
+ else
+ if [ -r ${progname}.in ] ; then
+ srcdir=`echo ${progname} | sed 's:/configure$::'`
+ else
+ echo '***' "Can't find configure.in. Try using --srcdir=some_dir" 1>&2
+ exit 1
+ fi
+ fi
+ ;;
+*)
+ # Set srcdir to "." if that's what it is.
+ # This is important for multilib support.
+ if [ ! -d ${srcdir} ] ; then
+ echo "Invalid source directory ${srcdir}" >&2
+ exit 1
+ fi
+ pwd=`pwd`
+ srcpwd=`cd ${srcdir} ; pwd`
+ if [ "${pwd}" = "${srcpwd}" ] ; then
+ srcdir=.
+ fi
+esac
+
+### warn about some conflicting configurations.
+
+case "${srcdir}" in
+".") ;;
+*)
+ if [ -f ${srcdir}/config.status ] ; then
+ echo '***' Cannot configure here in \"${PWD=`pwd`}\" when \"${srcdir}\" is currently configured. 1>&2
+ exit 1
+ fi
+esac
+
+# default exec_prefix
+case "${exec_prefixoption}" in
+"") exec_prefix="\$(prefix)" ;;
+*) ;;
+esac
+
+### break up ${srcdir}/configure.in.
+case "`grep '^# per\-host:' ${srcdir}/configure.in`" in
+"")
+ echo '***' ${srcdir}/configure.in has no \"per-host:\" line. 1>&2
+ # Check for a directory that's been converted to use autoconf since
+ # it was last configured.
+ if grep AC_OUTPUT ${srcdir}/configure.in >/dev/null ; then
+ echo '***' Hmm, looks like this directory has been autoconfiscated. 1>&2
+ if [ -r ${srcdir}/configure ] ; then
+ echo '***' Running the local configure script. 1>&2
+ case "${cache_file}" in
+ "") cache_file_option= ;;
+ *) cache_file_option="--cache-file=${cache_file}" ;;
+ esac
+ srcdiroption="--srcdir=${srcdir}"
+ case "${build_alias}" in
+ "") buildopt= ;;
+ *) buildopt="--build=${build_alias}" ;;
+ esac
+ eval exec ${config_shell} ${srcdir}/configure ${verbose} \
+ ${buildopt} --host=${host_alias} --target=${target_alias} \
+ ${prefixoption} ${tmpdiroption} ${exec_prefixoption} \
+ ${srcdiroption} \
+ ${program_prefixoption} ${program_suffixoption} \
+ ${program_transform_nameoption} ${site_option} \
+ ${withoptions} ${withoutoptions} \
+ ${enableoptions} ${disableoptions} ${floating_pointoption} \
+ ${cache_file_option} ${removing} ${other_options} ${redirect}
+ else
+ echo '***' There is no configure script present though. 1>&2
+ fi
+ fi
+ exit 1
+ ;;
+*) ;;
+esac
+
+case "`grep '^# per\-target:' ${srcdir}/configure.in`" in
+"")
+ echo '***' ${srcdir}/configure.in has no \"per-target:\" line. 1>&2
+ exit 1
+ ;;
+*) ;;
+esac
+
+case "${TMPDIR}" in
+"") TMPDIR=/tmp ; export TMPDIR ;;
+*) ;;
+esac
+
+# keep this filename short for &%*%$*# 14 char file names
+tmpfile=${TMPDIR}/cONf$$
+# Note that under many versions of sh a trap handler for 0 will *override* any
+# exit status you explicitly specify! At this point, the only non-error exit
+# is at the end of the script; these actions are duplicated there, minus
+# the "exit 1". Don't use "exit 0" anywhere after this without resetting the
+# trap handler, or you'll lose.
+trap "rm -f Makefile.tem ${tmpfile}.com ${tmpfile}.tgt ${tmpfile}.hst ${tmpfile}.pos; exit 1" 0 1 2 15
+
+# split ${srcdir}/configure.in into common, per-host, per-target,
+# and post-target parts. Post-target is optional.
+sed -e '/^# per\-host:/,$d' ${srcdir}/configure.in > ${tmpfile}.com
+sed -e '1,/^# per\-host:/d' -e '/^# per\-target:/,$d' ${srcdir}/configure.in > ${tmpfile}.hst
+if grep '^# post-target:' ${srcdir}/configure.in >/dev/null ; then
+ sed -e '1,/^# per\-target:/d' -e '/^# post\-target:/,$d' ${srcdir}/configure.in > ${tmpfile}.tgt
+ sed -e '1,/^# post\-target:/d' ${srcdir}/configure.in > ${tmpfile}.pos
+else
+ sed -e '1,/^# per\-target:/d' ${srcdir}/configure.in > ${tmpfile}.tgt
+ echo >${tmpfile}.pos
+fi
+
+### do common part of configure.in
+
+. ${tmpfile}.com
+
+# some sanity checks on configure.in
+case "${srctrigger}" in
+"")
+ echo '***' srctrigger not set in ${PWD=`pwd`}/configure.in. 1>&2
+ exit 1
+ ;;
+*) ;;
+esac
+
+case "${build_alias}" in
+"")
+ if result=`${config_shell} ${configsub} ${host_alias}` ; then
+ build_cpu=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'`
+ build_vendor=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'`
+ build_os=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'`
+ build=${build_cpu}-${build_vendor}-${build_os}
+ build_alias=${host_alias}
+ fi
+ ;;
+*)
+ if result=`${config_shell} ${configsub} ${build_alias}` ; then
+ buildopt="--build=${build_alias}"
+ build_cpu=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'`
+ build_vendor=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'`
+ build_os=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'`
+ build=${build_cpu}-${build_vendor}-${build_os}
+ else
+ echo "Unrecognized build system name ${build_alias}." 1>&2
+ exit 1
+ fi
+ ;;
+esac
+
+if result=`${config_shell} ${configsub} ${host_alias}` ; then
+ true
+else
+ echo "Unrecognized host system name ${host_alias}." 1>&2
+ exit 1
+fi
+host_cpu=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'`
+host_vendor=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'`
+host_os=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'`
+host=${host_cpu}-${host_vendor}-${host_os}
+
+. ${tmpfile}.hst
+
+if result=`${config_shell} ${configsub} ${target_alias}` ; then
+ true
+else
+ echo "Unrecognized target system name ${target_alias}." 1>&2
+ exit 1
+fi
+target_cpu=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'`
+target_vendor=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'`
+target_os=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'`
+target=${target_cpu}-${target_vendor}-${target_os}
+
+. ${tmpfile}.tgt
+
+# Find the source files, if location was not specified.
+case "${srcdir}" in
+"")
+ srcdirdefaulted=1
+ srcdir=.
+ if [ ! -r ${srctrigger} ] ; then
+ srcdir=..
+ fi
+ ;;
+*) ;;
+esac
+
+if [ ! -r ${srcdir}/${srctrigger} ] ; then
+ case "${srcdirdefaulted}" in
+ "") echo '***' "${progname}: Can't find ${srcname} sources in ${PWD=`pwd`}/${srcdir}" 1>&2 ;;
+ *) echo '***' "${progname}: Can't find ${srcname} sources in ${PWD=`pwd`}/. or ${PWD=`pwd`}/.." 1>&2 ;;
+ esac
+
+ echo '***' \(At least ${srctrigger} is missing.\) 1>&2
+ exit 1
+fi
+
+# Some systems (e.g., one of the i386-aix systems the gas testers are
+# using) don't handle "\$" correctly, so don't use it here.
+tooldir='$(exec_prefix)'/${target_alias}
+
+if [ "${host_alias}" != "${target_alias}" ] ; then
+ if [ "${program_prefixoption}" = "" ] ; then
+ if [ "${program_suffixoption}" = "" ] ; then
+ if [ "${program_transform_nameoption}" = "" ] ; then
+ program_prefix=${target_alias}- ;
+ fi
+ fi
+ fi
+fi
+
+# Merge program_prefix and program_suffix onto program_transform_name.
+# (program_suffix used to use $, but it's hard to preserve $ through both
+# make and sh.)
+if [ "${program_suffix}" != "" ] ; then
+ program_transform_name="-e s,\\\\(.*\\\\),\\\\1${program_suffix}, ${program_transform_name}"
+fi
+
+if [ "${program_prefix}" != "" ] ; then
+ program_transform_name="-e s,^,${program_prefix}, ${program_transform_name}"
+fi
+
+# If CC and CXX are not set in the environment, and the Makefile
+# exists, try to extract them from it. This is to handle running
+# ./config.status by hand.
+if [ -z "${CC}" -a -r Makefile ]; then
+ sed -n -e ':loop
+/\\$/ N
+/\\$/ b loop
+s/\\\n//g
+/^CC[ ]*=/ s/CC[ ]*=[ ]*\(.*\)/\1/p' < Makefile > Makefile.cc
+ CC=`tail -1 Makefile.cc`
+ rm -f Makefile.cc
+fi
+
+if [ -z "${CXX}" -a -r Makefile ]; then
+ sed -n -e ':loop
+/\\$/ N
+/\\$/ b loop
+s/\\\n//g
+/^CXX[ ]*=/ s/CXX[ ]*=[ ]*\(.*\)/\1/p' < Makefile > Makefile.cc
+ CXX=`tail -1 Makefile.cc`
+ rm -f Makefile.cc
+fi
+
+if [ "${build}" != "${host}" ]; then
+ # If we are doing a Canadian Cross, in which the host and build systems
+ # are not the same, we set reasonable default values for the tools.
+
+ tools="AR AR_FOR_TARGET AS AS_FOR_TARGET BISON CC_FOR_BUILD"
+ tools="${tools} CC_FOR_TARGET CXX_FOR_TARGET"
+ tools="${tools} DLLTOOL DLLTOOL_FOR_TARGET HOST_PREFIX"
+ tools="${tools} HOST_PREFIX_1 LD LD_FOR_TARGET LEX MAKEINFO NM"
+ tools="${tools} NM_FOR_TARGET RANLIB RANLIB_FOR_TARGET"
+
+ for var in ${tools}; do
+ if [ -z "`eval 'echo $'"${var}"`" -a -r Makefile ]; then
+ sed -n -e ':loop
+/\\$/ N
+/\\$/ b loop
+s/\\\n//g
+/^'"${var}"'[ ]*=/ s/'"${var}"'[ ]*=[ ]*\(.*\)/\1/p' \
+ < Makefile > Makefile.v
+ t=`tail -1 Makefile.v`
+ if [ -n "${t}" ]; then
+ eval "${var}='${t}'"
+ fi
+ rm -f Makefile.v
+ fi
+ done
+
+ AR=${AR-${host_alias}-ar}
+ AR_FOR_TARGET=${AR_FOR_TARGET-${target_alias}-ar}
+ AS=${AS-${host_alias}-as}
+ AS_FOR_TARGET=${AS_FOR_TARGET-${target_alias}-as}
+ CC=${CC-${host_alias}-gcc}
+ CXX=${CXX-${host_alias}-gcc}
+ CC_FOR_BUILD=${CC_FOR_BUILD-gcc}
+ CC_FOR_TARGET=${CC_FOR_TARGET-${target_alias}-gcc}
+ CXX_FOR_TARGET=${CXX_FOR_TARGET-${target_alias}-gcc}
+ DLLTOOL=${DLLTOOL-${host_alias}-dlltool}
+ DLLTOOL_FOR_TARGET=${DLLTOOL_FOR_TARGET-${target_alias}-dlltool}
+ HOST_PREFIX=${build_alias}-
+ HOST_PREFIX_1=${build_alias}-
+ LD=${LD-${host_alias}-ld}
+ LD_FOR_TARGET=${LD_FOR_TARGET-${target_alias}-ld}
+ MAKEINFO=${MAKEINFO-makeinfo}
+ NM=${NM-${host_alias}-nm}
+ NM_FOR_TARGET=${NM_FOR_TARGET-${target_alias}-nm}
+ RANLIB=${RANLIB-${host_alias}-ranlib}
+ RANLIB_FOR_TARGET=${RANLIB_FOR_TARGET-${target_alias}-ranlib}
+
+ if [ -z "${BISON}" ]; then
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:"
+ for dir in $PATH; do
+ test -z "$dir" && dir=.
+ if test -f $dir/byacc; then
+ BISON=byacc
+ break
+ fi
+ if test -f $dir/bison; then
+ BISON=bison
+ break
+ fi
+ if test -f $dir/yacc; then
+ BISON=yacc
+ break
+ fi
+ done
+ IFS="$save_ifs"
+ BISON=${BISON-bison}
+ fi
+
+ if [ -z "${LEX}" ]; then
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:"
+ for dir in $PATH; do
+ test -z "$dir" && dir=.
+ if test -f $dir/flex; then
+ LEX=flex
+ break
+ fi
+ if test -f $dir/lex; then
+ LEX=lex
+ break
+ fi
+ done
+ IFS="$save_ifs"
+ LEX=${LEX-flex}
+ fi
+
+ # Export variables which autoconf might try to set.
+ export AS
+ export AR
+ export CC_FOR_BUILD
+ export DLLTOOL
+ export LD
+ export NM
+ export RANLIB
+else
+ # If CC is still not set, try to get gcc.
+ if [ x$with_gcc != xno -a -z "${CC}" ]; then
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:"
+ for dir in $PATH; do
+ test -z "$dir" && dir=.
+ if test -f $dir/gcc; then
+ CC="gcc -O2"
+ break
+ fi
+ done
+ IFS="$save_ifs"
+ CC=${CC-cc}
+ fi
+
+ CXX=${CXX-"gcc"}
+fi
+
+export CC
+export CXX
+
+case "$host" in
+ *go32*)
+ enable_gdbtk=no ;;
+esac
+
+# Determine whether gdb needs tk/tcl or not.
+if [ "$enable_gdbtk" != "no" ]; then
+ GDB_TK="all-tcl all-tk"
+else
+ GDB_TK=""
+fi
+
+for subdir in . ${subdirs} ; do
+
+ # ${subdir} is relative path from . to the directory we're currently
+ # configuring.
+ # ${invsubdir} is inverse of ${subdir), *with* trailing /, if needed.
+ invsubdir=`echo ${subdir}/ | sed -e 's|\./||g' -e 's|[^/]*/|../|g'`
+
+ ### figure out what to do with srcdir
+ case "${srcdir}" in
+ ".") # no -srcdir option. We're building in place.
+ makesrcdir=. ;;
+ /*) # absolute path
+ makesrcdir=`echo ${srcdir}/${subdir} | sed -e 's|/\.$||'`
+ ;;
+ *) # otherwise relative
+ case "${subdir}" in
+ .) makesrcdir=${srcdir} ;;
+ *) makesrcdir=${invsubdir}${srcdir}/${subdir} ;;
+ esac
+ ;;
+ esac
+
+ if [ "${subdir}/" != "./" ] ; then
+ Makefile=${subdir}/Makefile
+ fi
+
+ if [ ! -d ${subdir} ] ; then
+ if mkdir ${subdir} ; then
+ true
+ else
+ echo '***' "${progname}: could not make ${PWD=`pwd`}/${subdir}" 1>&2
+ exit 1
+ fi
+ fi
+
+ case "${removing}" in
+ "")
+ case "${subdir}" in
+ .) ;;
+ *) eval echo Building in ${subdir} ${redirect} ;;
+ esac
+
+ # FIXME Should this be done recursively ??? (Useful for e.g. gdbtest)
+ # Set up the list of links to be made.
+ # ${links} is the list of link names, and ${files} is the list of names to link to.
+
+ # Make the links.
+ configlinks="${links}"
+ if [ -r ${subdir}/config.status ] ; then
+ mv -f ${subdir}/config.status ${subdir}/config.back
+ fi
+ while [ -n "${files}" ] ; do
+ # set file to car of files, files to cdr of files
+ set ${files}; file=$1; shift; files=$*
+ set ${links}; link=$1; shift; links=$*
+
+ if [ ! -r ${srcdir}/${file} ] ; then
+ echo '***' "${progname}: cannot create a link \"${link}\"," 1>&2
+ echo '***' "since the file \"${srcdir}/${file}\" does not exist." 1>&2
+ exit 1
+ fi
+
+ ${remove} -f ${link}
+ # Make a symlink if possible, otherwise try a hard link
+ if ${symbolic_link} ${srcdir}/${file} ${link} >/dev/null 2>&1 ; then
+ true
+ else
+ # We need to re-remove the file because Lynx leaves a
+ # very strange directory there when it fails an NFS symlink.
+ ${remove} -r -f ${link}
+ ${hard_link} ${srcdir}/${file} ${link}
+ fi
+ if [ ! -r ${link} ] ; then
+ echo '***' "${progname}: unable to link \"${link}\" to \"${srcdir}/${file}\"." 1>&2
+ exit 1
+ fi
+
+ echo "Linked \"${link}\" to \"${srcdir}/${file}\"."
+ done
+
+ # Create a .gdbinit file which runs the one in srcdir
+ # and tells GDB to look there for source files.
+
+ if [ -r ${srcdir}/${subdir}/.gdbinit ] ; then
+ case ${srcdir} in
+ .) ;;
+ *) cat > ${subdir}/.gdbinit <<EOF
+# ${NO_EDIT}
+dir ${makesrcdir}
+dir .
+source ${makesrcdir}/.gdbinit
+EOF
+ ;;
+ esac
+ fi
+
+ # Install a makefile, and make it set VPATH
+ # if necessary so that the sources are found.
+ # Also change its value of srcdir.
+ # NOTE: Makefile generation constitutes the majority of the time in configure. Hence, this section has
+ # been somewhat optimized and is perhaps a bit twisty.
+
+ # code is order so as to try to sed the smallest input files we know.
+
+ # the four makefile fragments MUST end up in the resulting Makefile in this order:
+ # package, target, host, and site. so do these separately because I don't trust the
+ # order of sed -e expressions.
+
+ if [ -f ${srcdir}/${subdir}/${Makefile_in} ] ; then
+
+ # Conditionalize for this site from "Makefile.in" (or whatever it's called) into Makefile.tem
+ rm -f ${subdir}/Makefile.tem
+ case "${site}" in
+ "") cp ${srcdir}/${subdir}/${Makefile_in} ${subdir}/Makefile.tem ;;
+ *)
+ site_makefile_frag=${srcdir}/config/ms-${site}
+
+ if [ -f ${site_makefile_frag} ] ; then
+ sed -e "/^####/ r ${site_makefile_frag}" ${srcdir}/${subdir}/${Makefile_in} \
+ > ${subdir}/Makefile.tem
+ else
+ cp ${srcdir}/${subdir}/${Makefile_in} ${subdir}/Makefile.tem
+ site_makefile_frag=
+ fi
+ ;;
+ esac
+ # working copy now in ${subdir}/Makefile.tem
+
+ # Conditionalize the makefile for this host.
+ rm -f ${Makefile}
+ case "${host_makefile_frag}" in
+ "") mv ${subdir}/Makefile.tem ${Makefile} ;;
+ *)
+ if [ ! -f ${host_makefile_frag} ] ; then
+ host_makefile_frag=${srcdir}/${host_makefile_frag}
+ fi
+ if [ -f ${host_makefile_frag} ] ; then
+ sed -e "/^####/ r ${host_makefile_frag}" ${subdir}/Makefile.tem > ${Makefile}
+ else
+ echo '***' Expected host makefile fragment \"${host_makefile_frag}\" 1>&2
+ echo '***' is missing in ${PWD=`pwd`}. 1>&2
+ mv ${subdir}/Makefile.tem ${Makefile}
+ fi
+ esac
+ # working copy now in ${Makefile}
+
+ # Conditionalize the makefile for this target.
+ rm -f ${subdir}/Makefile.tem
+ case "${target_makefile_frag}" in
+ "") mv ${Makefile} ${subdir}/Makefile.tem ;;
+ *)
+ if [ ! -f ${target_makefile_frag} ] ; then
+ target_makefile_frag=${srcdir}/${target_makefile_frag}
+ fi
+ if [ -f ${target_makefile_frag} ] ; then
+ sed -e "/^####/ r ${target_makefile_frag}" ${Makefile} > ${subdir}/Makefile.tem
+ else
+ mv ${Makefile} ${subdir}/Makefile.tem
+ target_makefile_frag=
+ fi
+ ;;
+ esac
+ # real copy now in ${subdir}/Makefile.tem
+
+ # Conditionalize the makefile for this package.
+ rm -f ${Makefile}
+ case "${package_makefile_frag}" in
+ "") mv ${subdir}/Makefile.tem ${Makefile} ;;
+ *)
+ if [ ! -f ${package_makefile_frag} ] ; then
+ package_makefile_frag=${srcdir}/${package_makefile_frag}
+ fi
+ if [ -f ${package_makefile_frag} ] ; then
+ sed -e "/^####/ r ${package_makefile_frag}" ${subdir}/Makefile.tem > ${Makefile}
+ rm -f ${subdir}/Makefile.tem
+ else
+ echo '***' Expected package makefile fragment \"${package_makefile_frag}\" 1>&2
+ echo '***' is missing in ${PWD=`pwd`}. 1>&2
+ mv ${subdir}/Makefile.tem ${Makefile}
+ fi
+ esac
+ # working copy now in ${Makefile}
+
+ mv ${Makefile} ${subdir}/Makefile.tem
+
+ # real copy now in ${subdir}/Makefile.tem
+
+ # prepend warning about editting, and a bunch of variables.
+ rm -f ${Makefile}
+ cat > ${Makefile} <<EOF
+# ${NO_EDIT}
+VPATH = ${makesrcdir}
+links = ${configlinks}
+host_alias = ${host_alias}
+host_cpu = ${host_cpu}
+host_vendor = ${host_vendor}
+host_os = ${host_os}
+host_canonical = ${host_cpu}-${host_vendor}-${host_os}
+target_alias = ${target_alias}
+target_cpu = ${target_cpu}
+target_vendor = ${target_vendor}
+target_os = ${target_os}
+target_canonical = ${target_cpu}-${target_vendor}-${target_os}
+EOF
+ case "${build}" in
+ "") ;;
+ *) cat >> ${Makefile} << EOF
+build_alias = ${build_alias}
+build_cpu = ${build_cpu}
+build_vendor = ${build_vendor}
+build_os = ${build_os}
+build_canonical = ${build_cpu}-${build_vendor}-${build_os}
+EOF
+ esac
+
+ case "${package_makefile_frag}" in
+ "") ;;
+ /*) echo package_makefile_frag = ${package_makefile_frag} >>${Makefile} ;;
+ *) echo package_makefile_frag = ${invsubdir}${package_makefile_frag} >>${Makefile} ;;
+ esac
+
+ case "${target_makefile_frag}" in
+ "") ;;
+ /*) echo target_makefile_frag = ${target_makefile_frag} >>${Makefile} ;;
+ *) echo target_makefile_frag = ${invsubdir}${target_makefile_frag} >>${Makefile} ;;
+ esac
+
+ case "${host_makefile_frag}" in
+ "") ;;
+ /*) echo host_makefile_frag = ${host_makefile_frag} >>${Makefile} ;;
+ *) echo host_makefile_frag = ${invsubdir}${host_makefile_frag} >>${Makefile} ;;
+ esac
+
+ if [ "${site_makefile_frag}" != "" ] ; then
+ echo site_makefile_frag = ${invsubdir}${site_makefile_frag} >>${Makefile}
+ fi
+
+ # reset prefix, exec_prefix, srcdir, SUBDIRS, NONSUBDIRS,
+ # remove any form feeds.
+ if [ -z "${subdirs}" ]; then
+ rm -f ${subdir}/Makefile.tem2
+ sed -e "s:^SUBDIRS[ ]*=.*$:SUBDIRS = ${configdirs}:" \
+ -e "s:^NONSUBDIRS[ ]*=.*$:NONSUBDIRS = ${noconfigdirs}:" \
+ ${subdir}/Makefile.tem > ${subdir}/Makefile.tem2
+ rm -f ${subdir}/Makefile.tem
+ mv ${subdir}/Makefile.tem2 ${subdir}/Makefile.tem
+ fi
+ sed -e "s:^prefix[ ]*=.*$:prefix = ${prefix}:" \
+ -e "s:^exec_prefix[ ]*=.*$:exec_prefix = ${exec_prefix}:" \
+ -e "/^CC[ ]*=/{
+ :loop1
+ /\\\\$/ N
+ /\\\\$/ b loop1
+ s/\\\\\\n//g
+ s%^CC[ ]*=.*$%CC = ${CC}%
+ }" \
+ -e "/^CXX[ ]*=/{
+ :loop2
+ /\\\\$/ N
+ /\\\\$/ b loop2
+ s/\\\\\\n//g
+ s%^CXX[ ]*=.*$%CXX = ${CXX}%
+ }" \
+ -e "s:^SHELL[ ]*=.*$:SHELL = ${config_shell}:" \
+ -e "s:^GDB_TK[ ]*=.*$:GDB_TK = ${GDB_TK}:" \
+ -e "s:^srcdir[ ]*=.*$:srcdir = ${makesrcdir}:" \
+ -e "s/ //" \
+ -e "s:^program_prefix[ ]*=.*$:program_prefix = ${program_prefix}:" \
+ -e "s:^program_suffix[ ]*=.*$:program_suffix = ${program_suffix}:" \
+ -e "s:^program_transform_name[ ]*=.*$:program_transform_name = ${program_transform_name}:" \
+ -e "s:^tooldir[ ]*=.*$:tooldir = ${tooldir}:" \
+ ${subdir}/Makefile.tem >> ${Makefile}
+
+ # If this is a Canadian Cross, preset the values of many more
+ # tools.
+ if [ "${build}" != "${host}" ]; then
+ for var in ${tools}; do
+ val=`eval 'echo $'"${var}"`
+ sed -e "/^${var}[ ]*=/{
+ :loop1
+ /\\\\$/ N
+ /\\\\$/ b loop1
+ s/\\\\\\n//g
+ s%^${var}[ ]*=.*$%${var} = ${val}%
+ }" ${Makefile} > ${Makefile}.tem
+ mv -f ${Makefile}.tem ${Makefile}
+ done
+ fi
+
+ # final copy now in ${Makefile}
+
+ else
+ echo "No Makefile.in found in ${srcdir}/${subdir}, unable to configure" 1>&2
+ fi
+
+ rm -f ${subdir}/Makefile.tem
+
+ case "${host_makefile_frag}" in
+ "") using= ;;
+ *) using="and \"${host_makefile_frag}\"" ;;
+ esac
+
+ case "${target_makefile_frag}" in
+ "") ;;
+ *) using="${using} and \"${target_makefile_frag}\"" ;;
+ esac
+
+ case "${site_makefile_frag}" in
+ "") ;;
+ *) using="${using} and \"${site_makefile_frag}\"" ;;
+ esac
+
+ newusing=`echo "${using}" | sed 's/and/using/'`
+ using=${newusing}
+ echo "Created \"${Makefile}\" in" ${PWD=`pwd`} ${using}
+
+ . ${tmpfile}.pos
+
+ # describe the chosen configuration in config.status.
+ # Make that file a shellscript which will reestablish
+ # the same configuration. Used in Makefiles to rebuild
+ # Makefiles.
+
+ case "${norecursion}" in
+ "") arguments="${arguments} --norecursion" ;;
+ *) ;;
+ esac
+
+ if [ ${subdir} = . ] ; then
+ echo "#!/bin/sh
+# ${NO_EDIT}
+# This directory was configured as follows:
+${progname}" ${arguments} "
+# ${using}" > ${subdir}/config.new
+ else
+ echo "#!/bin/sh
+# ${NO_EDIT}
+# This directory was configured as follows:
+cd ${invsubdir}
+${progname}" ${arguments} "
+# ${using}" > ${subdir}/config.new
+ fi
+ chmod a+x ${subdir}/config.new
+ if [ -r ${subdir}/config.back ] ; then
+ mv -f ${subdir}/config.back ${subdir}/config.status
+ fi
+ ${moveifchange} ${subdir}/config.new ${subdir}/config.status
+ ;;
+
+ *) rm -f ${Makefile} ${subdir}/config.status ${links} ;;
+ esac
+done
+
+# If there are subdirectories, then recur.
+if [ -z "${norecursion}" -a -n "${configdirs}" ] ; then
+ for configdir in ${configdirs} ; do
+
+ if [ -d ${srcdir}/${configdir} ] ; then
+ eval echo Configuring ${configdir}... ${redirect}
+ case "${srcdir}" in
+ ".") ;;
+ *)
+ if [ ! -d ./${configdir} ] ; then
+ if mkdir ./${configdir} ; then
+ true
+ else
+ echo '***' "${progname}: could not make ${PWD=`pwd`}/${configdir}" 1>&2
+ exit 1
+ fi
+ fi
+ ;;
+ esac
+
+ POPDIR=${PWD=`pwd`}
+ cd ${configdir}
+
+### figure out what to do with srcdir
+ case "${srcdir}" in
+ ".") newsrcdir=${srcdir} ;; # no -srcdir option. We're building in place.
+ /*) # absolute path
+ newsrcdir=${srcdir}/${configdir}
+ srcdiroption="--srcdir=${newsrcdir}"
+ ;;
+ *) # otherwise relative
+ newsrcdir=../${srcdir}/${configdir}
+ srcdiroption="--srcdir=${newsrcdir}"
+ ;;
+ esac
+
+ # Handle --cache-file=../XXX
+ case "${cache_file}" in
+ "") # empty
+ ;;
+ /*) # absolute path
+ cache_file_option="--cache-file=${cache_file}"
+ ;;
+ *) # relative path
+ cache_file_option="--cache-file=../${cache_file}"
+ ;;
+ esac
+
+### check for guested configure, otherwise fix possibly relative progname
+ if [ -f ${newsrcdir}/configure ] ; then
+ recprog=${newsrcdir}/configure
+ elif [ -f ${newsrcdir}/configure.in ] ; then
+ case "${progname}" in
+ /*) recprog=${progname} ;;
+ *) recprog=../${progname} ;;
+ esac
+ else
+ eval echo No configuration information in ${configdir} ${redirect}
+ recprog=
+ fi
+
+### The recursion line is here.
+ if [ ! -z "${recprog}" ] ; then
+ if eval ${config_shell} ${recprog} ${verbose} ${buildopt} --host=${host_alias} --target=${target_alias} \
+ ${prefixoption} ${tmpdiroption} ${exec_prefixoption} \
+ ${srcdiroption} ${program_prefixoption} ${program_suffixoption} ${program_transform_nameoption} ${site_option} ${withoptions} ${withoutoptions} ${enableoptions} ${disableoptions} ${floating_pointoption} ${cache_file_option} ${removing} ${other_options} ${redirect} ; then
+ true
+ else
+ echo Configure in `pwd` failed, exiting. 1>&2
+ exit 1
+ fi
+ fi
+
+ cd ${POPDIR}
+ fi
+ done
+fi
+
+# Perform the same cleanup as the trap handler, minus the "exit 1" of course,
+# and reset the trap handler.
+rm -f ${tmpfile}.com ${tmpfile}.tgt ${tmpfile}.hst ${tmpfile}.pos
+trap 0
+
+exit 0
+
+#
+# Local Variables:
+# fill-column: 131
+# End:
+#
+
+# end of configure
diff --git a/configure.in b/configure.in
new file mode 100644
index 000000000..c0a140883
--- /dev/null
+++ b/configure.in
@@ -0,0 +1,32 @@
+# This file is a shell script fragment that supplies the information
+# necessary for a configure script to process the program in
+# this directory. For more information, look at ../configure.
+
+configdirs="mpn mpz mpf mpq mpbsd"
+srctrigger=gmp-impl.h
+srcname="GNU Multi-Precision library"
+
+# per-host:
+
+# per-target:
+
+case "${target}" in
+ sparc8*)
+ if [ x$with_gcc != xno ]
+ then
+ target_makefile_frag=config/mt-sprc8-gcc
+ fi
+ ;;
+ supersparc*)
+ if [ x$with_gcc != xno ]
+ then
+ target_makefile_frag=config/mt-supspc-gcc
+ fi
+ ;;
+ m888110*)
+ if [ x$with_gcc != xno ]
+ then
+ target_makefile_frag=config/mt-m88110
+ fi
+ ;;
+esac
diff --git a/cre-mparam.c b/cre-mparam.c
new file mode 100644
index 000000000..2020c8a82
--- /dev/null
+++ b/cre-mparam.c
@@ -0,0 +1,16 @@
+#include "gmp.h"
+
+main ()
+{
+printf ("/* gmp-mparam.h -- Compiler/machine parameter header file.\n\n");
+printf (" *** CREATED BY A PROGRAM -- DO NOT EDIT ***\n\n");
+printf ("Copyright (C) 1996 Free Software Foundation, Inc. */\n\n");
+
+printf ("#define BITS_PER_MP_LIMB %d\n", 8 * sizeof (mp_limb_t));
+printf ("#define BYTES_PER_MP_LIMB %d\n", sizeof (mp_limb_t));
+printf ("#define BITS_PER_LONGINT %d\n", 8 * sizeof (long));
+printf ("#define BITS_PER_INT %d\n", 8 * sizeof (int));
+printf ("#define BITS_PER_SHORTINT %d\n", 8 * sizeof (short));
+printf ("#define BITS_PER_CHAR 8\n");
+exit (0);
+}
diff --git a/demos/factorize.c b/demos/factorize.c
new file mode 100644
index 000000000..4a965d316
--- /dev/null
+++ b/demos/factorize.c
@@ -0,0 +1,233 @@
+/* Factoring with Pollard's rho method.
+
+ Copyright (C) 1995 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+This program 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
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+
+int flag_mersenne = 0;
+
+static unsigned add[] = {4, 2, 4, 2, 4, 6, 2, 6};
+
+factor_using_division (t, limit)
+ mpz_t t;
+ unsigned int limit;
+{
+ mpz_t q, r;
+ unsigned long int f;
+ int i, ai;
+ unsigned *addv = add;
+
+ mpz_init (q);
+ mpz_init (r);
+
+ if (mpz_probab_prime_p (t, 50))
+ goto ready;
+
+ for (;;)
+ {
+ mpz_tdiv_qr_ui (q, r, t, 2);
+ if (mpz_cmp_ui (r, 0) != 0)
+ break;
+ mpz_set (t, q);
+ printf ("2 ");
+ fflush (stdout);
+ if (mpz_probab_prime_p (t, 50))
+ goto ready;
+ }
+
+ for (;;)
+ {
+ mpz_tdiv_qr_ui (q, r, t, 3);
+ if (mpz_cmp_ui (r, 0) != 0)
+ break;
+ mpz_set (t, q);
+ printf ("3 ");
+ fflush (stdout);
+ if (mpz_probab_prime_p (t, 50))
+ goto ready;
+ }
+
+ for (;;)
+ {
+ mpz_tdiv_qr_ui (q, r, t, 5);
+ if (mpz_cmp_ui (r, 0) != 0)
+ break;
+ mpz_set (t, q);
+ printf ("5 ");
+ fflush (stdout);
+ if (mpz_probab_prime_p (t, 50))
+ goto ready;
+ }
+
+ f = 7;
+ ai = 0;
+ for (;;)
+ {
+ mpz_tdiv_qr_ui (q, r, t, f);
+ if (mpz_cmp_ui (r, 0) != 0)
+ {
+ f += addv[ai];
+ if (f > limit)
+ goto ret;
+ ai = (ai + 1) & 7;
+ }
+ else
+ {
+ mpz_set (t, q);
+ printf ("%lu ", f);
+ fflush (stdout);
+ if (mpz_probab_prime_p (t, 50))
+ goto ready;
+ }
+ }
+
+ ready:
+ mpz_out_str (stdout, 10, t);
+ fflush (stdout);
+ mpz_set_ui (t, 1);
+ fputc (' ', stdout);
+ ret:
+ mpz_clear (q);
+ mpz_clear (r);
+}
+
+void
+factor_using_pollard_rho (m, a_int, x0, p)
+ mpz_t m;
+ long a_int;
+ long x0;
+ unsigned long p;
+{
+ mpz_t x, y, q;
+ mpz_t a;
+ mpz_t d;
+ mpz_t tmp;
+ mpz_t n;
+ int i = 1;
+ int j = 1;
+
+ mpz_init_set (n, m);
+
+ mpz_init (d);
+ mpz_init_set_ui (q, 1);
+ mpz_init (tmp);
+
+ mpz_init_set_si (a, a_int);
+ mpz_init_set_si (x, x0);
+ mpz_init_set_si (y, x0);
+
+ while (mpz_cmp_ui (n, 1) != 0)
+ {
+ if (flag_mersenne)
+ {
+ mpz_powm_ui (x, x, p, n); mpz_add (x, x, a);
+ mpz_powm_ui (y, y, p, n); mpz_add (y, y, a);
+ mpz_powm_ui (y, y, p, n); mpz_add (y, y, a);
+ }
+ else
+ {
+ mpz_mul (x, x, x); mpz_add (x, x, a); mpz_mod (x, x, n);
+ mpz_mul (y, y, y); mpz_add (y, y, a); mpz_mod (y, y, n);
+ mpz_mul (y, y, y); mpz_add (y, y, a); mpz_mod (y, y, n);
+ }
+
+ if (mpz_cmp (x, y) > 0)
+ mpz_sub (tmp, x, y);
+ else
+ mpz_sub (tmp, y, x);
+ mpz_mul (q, q, tmp);
+ mpz_mod (q, q, n);
+
+ if (++i % j == 0)
+ {
+ j += 1;
+ mpz_gcd (d, q, n);
+ if (mpz_cmp_ui (d, 1) != 0)
+ {
+ if (!mpz_probab_prime_p (d, 50))
+ factor_using_pollard_rho (d, (random () & 31) - 16,
+ (random () & 31), p);
+ else
+ {
+ mpz_out_str (stdout, 10, d);
+ fflush (stdout);
+ fputc (' ', stdout);
+ }
+ mpz_div (n, n, d);
+ if (mpz_probab_prime_p (n, 50))
+ {
+ mpz_out_str (stdout, 10, n);
+ fflush (stdout);
+ fputc (' ', stdout);
+ break;
+ }
+ }
+ }
+ }
+
+ mpz_clear (n);
+ mpz_clear (d);
+ mpz_clear (q);
+ mpz_clear (tmp);
+ mpz_clear (a);
+ mpz_clear (x);
+ mpz_clear (y);
+}
+
+factor (t, a, x0, p)
+ mpz_t t;
+ long a;
+ long x0;
+ unsigned long p;
+{
+ factor_using_division (t, 1000000);
+ factor_using_pollard_rho (t, a, x0, p);
+}
+
+main (argc, argv)
+ int argc;
+ char *argv[];
+{
+ mpz_t t;
+ long x0, a;
+ unsigned long p;
+ int i;
+
+ for (i = 1; i < argc; i++)
+ {
+ if (!strncmp (argv[i], "-Mp", 3))
+ {
+ p = atoi (argv[i] + 3);
+ mpz_init_set_ui (t, 1);
+ mpz_mul_2exp (t, t, p);
+ mpz_sub_ui (t, t, 1);
+ flag_mersenne = 1;
+ }
+ else
+ {
+ p = 0;
+ mpz_init_set_str (t, argv[i], 0);
+ }
+
+ a = -1;
+ x0 = 3;
+
+ factor (t, a, x0, p);
+ puts ("");
+ }
+}
diff --git a/gmp-impl.h b/gmp-impl.h
new file mode 100644
index 000000000..47a5d6e83
--- /dev/null
+++ b/gmp-impl.h
@@ -0,0 +1,330 @@
+/* Include file for internal GNU MP types and definitions.
+
+Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/* When using gcc, make sure to use its builtin alloca. */
+#if ! defined (alloca) && defined (__GNUC__)
+#define alloca __builtin_alloca
+#define HAVE_ALLOCA
+#endif
+
+/* When using cc, do whatever necessary to allow use of alloca. For many
+ machines, this means including alloca.h. IBM's compilers need a #pragma
+ in "each module that needs to use alloca". */
+#if ! defined (alloca)
+/* We need lots of variants for MIPS, to cover all versions and perversions
+ of OSes for MIPS. */
+#if defined (__mips) || defined (MIPSEL) || defined (MIPSEB) \
+ || defined (_MIPSEL) || defined (_MIPSEB) || defined (__sgi) \
+ || defined (__alpha) || defined (__sparc) || defined (sparc) \
+ || defined (__ksr__)
+#include <alloca.h>
+#define HAVE_ALLOCA
+#endif
+#if defined (_IBMR2)
+#pragma alloca
+#define HAVE_ALLOCA
+#endif
+#if defined (__DECC)
+#define alloca(x) __ALLOCA(x)
+#define HAVE_ALLOCA
+#endif
+#endif
+
+#if ! defined (HAVE_ALLOCA) || USE_STACK_ALLOC
+#include "stack-alloc.h"
+#else
+#define TMP_DECL(m)
+#define TMP_ALLOC(x) alloca(x)
+#define TMP_MARK(m)
+#define TMP_FREE(m)
+#endif
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+#if ! defined (__GNUC__)
+#define inline /* Empty */
+#endif
+
+#define ABS(x) (x >= 0 ? x : -x)
+#define MIN(l,o) ((l) < (o) ? (l) : (o))
+#define MAX(h,i) ((h) > (i) ? (h) : (i))
+
+/* Field access macros. */
+#define SIZ(x) ((x)->_mp_size)
+#define ABSIZ(x) ABS (SIZ (x))
+#define PTR(x) ((x)->_mp_d)
+#define EXP(x) ((x)->_mp_exp)
+#define PREC(x) ((x)->_mp_prec)
+#define ALLOC(x) ((x)->_mp_alloc)
+
+#include "gmp-mparam.h"
+/* #include "longlong.h" */
+
+#if defined (__STDC__) || defined (__cplusplus)
+void *malloc (size_t);
+void *realloc (void *, size_t);
+void free (void *);
+
+extern void * (*_mp_allocate_func) (size_t);
+extern void * (*_mp_reallocate_func) (void *, size_t, size_t);
+extern void (*_mp_free_func) (void *, size_t);
+
+void *_mp_default_allocate (size_t);
+void *_mp_default_reallocate (void *, size_t, size_t);
+void _mp_default_free (void *, size_t);
+
+#else
+
+#define const /* Empty */
+#define signed /* Empty */
+
+void *malloc ();
+void *realloc ();
+void free ();
+
+extern void * (*_mp_allocate_func) ();
+extern void * (*_mp_reallocate_func) ();
+extern void (*_mp_free_func) ();
+
+void *_mp_default_allocate ();
+void *_mp_default_reallocate ();
+void _mp_default_free ();
+#endif
+
+/* Copy NLIMBS *limbs* from SRC to DST. */
+#define MPN_COPY_INCR(DST, SRC, NLIMBS) \
+ do { \
+ mp_size_t __i; \
+ for (__i = 0; __i < (NLIMBS); __i++) \
+ (DST)[__i] = (SRC)[__i]; \
+ } while (0)
+#define MPN_COPY_DECR(DST, SRC, NLIMBS) \
+ do { \
+ mp_size_t __i; \
+ for (__i = (NLIMBS) - 1; __i >= 0; __i--) \
+ (DST)[__i] = (SRC)[__i]; \
+ } while (0)
+#define MPN_COPY MPN_COPY_INCR
+
+/* Zero NLIMBS *limbs* AT DST. */
+#define MPN_ZERO(DST, NLIMBS) \
+ do { \
+ mp_size_t __i; \
+ for (__i = 0; __i < (NLIMBS); __i++) \
+ (DST)[__i] = 0; \
+ } while (0)
+
+#define MPN_NORMALIZE(DST, NLIMBS) \
+ do { \
+ while (NLIMBS > 0) \
+ { \
+ if ((DST)[(NLIMBS) - 1] != 0) \
+ break; \
+ NLIMBS--; \
+ } \
+ } while (0)
+#define MPN_NORMALIZE_NOT_ZERO(DST, NLIMBS) \
+ do { \
+ while (1) \
+ { \
+ if ((DST)[(NLIMBS) - 1] != 0) \
+ break; \
+ NLIMBS--; \
+ } \
+ } while (0)
+
+/* Initialize the MP_INT X with space for NLIMBS limbs.
+ X should be a temporary variable, and it will be automatically
+ cleared out when the running function returns.
+ We use __x here to make it possible to accept both mpz_ptr and mpz_t
+ arguments. */
+#define MPZ_TMP_INIT(X, NLIMBS) \
+ do { \
+ mpz_ptr __x = (X); \
+ __x->_mp_alloc = (NLIMBS); \
+ __x->_mp_d = (mp_ptr) TMP_ALLOC ((NLIMBS) * BYTES_PER_MP_LIMB); \
+ } while (0)
+
+#define MPN_MUL_N_RECURSE(prodp, up, vp, size, tspace) \
+ do { \
+ if ((size) < KARATSUBA_THRESHOLD) \
+ impn_mul_n_basecase (prodp, up, vp, size); \
+ else \
+ impn_mul_n (prodp, up, vp, size, tspace); \
+ } while (0);
+#define MPN_SQR_N_RECURSE(prodp, up, size, tspace) \
+ do { \
+ if ((size) < KARATSUBA_THRESHOLD) \
+ impn_sqr_n_basecase (prodp, up, size); \
+ else \
+ impn_sqr_n (prodp, up, size, tspace); \
+ } while (0);
+
+/* Structure for conversion between internal binary format and
+ strings in base 2..36. */
+struct bases
+{
+ /* Number of digits in the conversion base that always fits in an mp_limb_t.
+ For example, for base 10 on a machine where a mp_limb_t has 32 bits this
+ is 9, since 10**9 is the largest number that fits into a mp_limb_t. */
+ int chars_per_limb;
+
+ /* log(2)/log(conversion_base) */
+ float chars_per_bit_exactly;
+
+ /* base**chars_per_limb, i.e. the biggest number that fits a word, built by
+ factors of base. Exception: For 2, 4, 8, etc, big_base is log2(base),
+ i.e. the number of bits used to represent each digit in the base. */
+ mp_limb_t big_base;
+
+ /* A BITS_PER_MP_LIMB bit approximation to 1/big_base, represented as a
+ fixed-point number. Instead of dividing by big_base an application can
+ choose to multiply by big_base_inverted. */
+ mp_limb_t big_base_inverted;
+};
+
+extern const struct bases __mp_bases[];
+extern mp_size_t __gmp_default_fp_limb_precision;
+
+/* Divide the two-limb number in (NH,,NL) by D, with DI being the largest
+ limb not larger than (2**(2*BITS_PER_MP_LIMB))/D - (2**BITS_PER_MP_LIMB).
+ If this would yield overflow, DI should be the largest possible number
+ (i.e., only ones). For correct operation, the most significant bit of D
+ has to be set. Put the quotient in Q and the remainder in R. */
+#define udiv_qrnnd_preinv(q, r, nh, nl, d, di) \
+ do { \
+ mp_limb_t _q, _ql, _r; \
+ mp_limb_t _xh, _xl; \
+ umul_ppmm (_q, _ql, (nh), (di)); \
+ _q += (nh); /* DI is 2**BITS_PER_MP_LIMB too small */\
+ umul_ppmm (_xh, _xl, _q, (d)); \
+ sub_ddmmss (_xh, _r, (nh), (nl), _xh, _xl); \
+ if (_xh != 0) \
+ { \
+ sub_ddmmss (_xh, _r, _xh, _r, 0, (d)); \
+ _q += 1; \
+ if (_xh != 0) \
+ { \
+ sub_ddmmss (_xh, _r, _xh, _r, 0, (d)); \
+ _q += 1; \
+ } \
+ } \
+ if (_r >= (d)) \
+ { \
+ _r -= (d); \
+ _q += 1; \
+ } \
+ (r) = _r; \
+ (q) = _q; \
+ } while (0)
+/* Like udiv_qrnnd_preinv, but for for any value D. DNORM is D shifted left
+ so that its most significant bit is set. LGUP is ceil(log2(D)). */
+#define udiv_qrnnd_preinv2gen(q, r, nh, nl, d, di, dnorm, lgup) \
+ do { \
+ mp_limb_t n2, n10, n1, nadj, q1; \
+ mp_limb_t _xh, _xl; \
+ n2 = ((nh) << (BITS_PER_MP_LIMB - (lgup))) + ((nl) >> 1 >> (l - 1));\
+ n10 = (nl) << (BITS_PER_MP_LIMB - (lgup)); \
+ n1 = ((mp_limb_signed_t) n10 >> (BITS_PER_MP_LIMB - 1)); \
+ nadj = n10 + (n1 & (dnorm)); \
+ umul_ppmm (_xh, _xl, di, n2 - n1); \
+ add_ssaaaa (_xh, _xl, _xh, _xl, 0, nadj); \
+ q1 = ~(n2 + _xh); \
+ umul_ppmm (_xh, _xl, q1, d); \
+ add_ssaaaa (_xh, _xl, _xh, _xl, nh, nl); \
+ _xh -= (d); \
+ (r) = _xl + ((d) & _xh); \
+ (q) = _xh - q1; \
+ } while (0)
+/* Exactly like udiv_qrnnd_preinv, but branch-free. It is not clear which
+ version to use. */
+#define udiv_qrnnd_preinv2norm(q, r, nh, nl, d, di) \
+ do { \
+ mp_limb_t n2, n10, n1, nadj, q1; \
+ mp_limb_t _xh, _xl; \
+ n2 = (nh); \
+ n10 = (nl); \
+ n1 = ((mp_limb_signed_t) n10 >> (BITS_PER_MP_LIMB - 1)); \
+ nadj = n10 + (n1 & (d)); \
+ umul_ppmm (_xh, _xl, di, n2 - n1); \
+ add_ssaaaa (_xh, _xl, _xh, _xl, 0, nadj); \
+ q1 = ~(n2 + _xh); \
+ umul_ppmm (_xh, _xl, q1, d); \
+ add_ssaaaa (_xh, _xl, _xh, _xl, nh, nl); \
+ _xh -= (d); \
+ (r) = _xl + ((d) & _xh); \
+ (q) = _xh - q1; \
+ } while (0)
+
+#if defined (__GNUC__)
+/* Define stuff for longlong.h. */
+typedef unsigned int UQItype __attribute__ ((mode (QI)));
+typedef int SItype __attribute__ ((mode (SI)));
+typedef unsigned int USItype __attribute__ ((mode (SI)));
+typedef int DItype __attribute__ ((mode (DI)));
+typedef unsigned int UDItype __attribute__ ((mode (DI)));
+#else
+typedef unsigned char UQItype;
+typedef long SItype;
+typedef unsigned long USItype;
+#endif
+
+typedef mp_limb_t UWtype;
+typedef unsigned int UHWtype;
+#define W_TYPE_SIZE BITS_PER_MP_LIMB
+
+/* Internal mpn calls */
+#define impn_mul_n_basecase __MPN(impn_mul_n_basecase)
+#define impn_mul_n __MPN(impn_mul_n)
+#define impn_sqr_n_basecase __MPN(impn_sqr_n_basecase)
+#define impn_sqr_n __MPN(impn_sqr_n)
+
+#ifndef IEEE_DOUBLE_BIG_ENDIAN
+#define IEEE_DOUBLE_BIG_ENDIAN 1
+#endif
+
+#if IEEE_DOUBLE_BIG_ENDIAN
+union ieee_double_extract
+{
+ struct
+ {
+ unsigned int sig:1;
+ unsigned int exp:11;
+ unsigned int manh:20;
+ unsigned int manl:32;
+ } s;
+ double d;
+};
+#else
+union ieee_double_extract
+{
+ struct
+ {
+ unsigned int manl:32;
+ unsigned int manh:20;
+ unsigned int exp:11;
+ unsigned int sig:1;
+ } s;
+ double d;
+};
+#endif
diff --git a/gmp.h b/gmp.h
new file mode 100644
index 000000000..ae9e095e6
--- /dev/null
+++ b/gmp.h
@@ -0,0 +1,622 @@
+/* gmp.h -- Definitions for GNU multiple precision functions.
+
+Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#ifndef __GMP_H__
+
+#ifndef __GNU_MP__
+#define __GNU_MP__ 2
+#define __need_size_t
+#include <stddef.h>
+#undef __need_size_t
+
+#if defined (__STDC__) || defined (__cplusplus)
+#define __gmp_const const
+#else
+#define __gmp_const
+#endif
+
+#if defined (__GNUC__)
+#define __gmp_inline __inline__
+#else
+#define __gmp_inline
+#endif
+
+#ifndef _EXTERN_INLINE
+#ifdef __GNUC__
+#define _EXTERN_INLINE extern __inline__
+#else
+#define _EXTERN_INLINE static
+#endif
+#endif
+
+#ifdef _SHORT_LIMB
+typedef unsigned int mp_limb_t;
+typedef int mp_limb_signed_t;
+#else
+#ifdef _LONG_LONG_LIMB
+typedef unsigned long long int mp_limb_t;
+typedef long long int mp_limb_signed_t;
+#else
+typedef unsigned long int mp_limb_t;
+typedef long int mp_limb_signed_t;
+#endif
+#endif
+
+typedef mp_limb_t * mp_ptr;
+typedef __gmp_const mp_limb_t * mp_srcptr;
+typedef long int mp_size_t;
+typedef long int mp_exp_t;
+
+#ifndef __MP_SMALL__
+typedef struct
+{
+ int _mp_alloc; /* Number of *limbs* allocated and pointed
+ to by the D field. */
+ int _mp_size; /* abs(SIZE) is the number of limbs
+ the last field points to. If SIZE
+ is negative this is a negative
+ number. */
+ mp_limb_t *_mp_d; /* Pointer to the limbs. */
+} __mpz_struct;
+#else
+typedef struct
+{
+ short int _mp_alloc; /* Number of *limbs* allocated and pointed
+ to by the D field. */
+ short int _mp_size; /* abs(SIZE) is the number of limbs
+ the last field points to. If SIZE
+ is negative this is a negative
+ number. */
+ mp_limb_t *_mp_d; /* Pointer to the limbs. */
+} __mpz_struct;
+#endif
+#endif /* __GNU_MP__ */
+
+/* User-visible types. */
+typedef __mpz_struct MP_INT;
+typedef __mpz_struct mpz_t[1];
+
+/* Structure for rational numbers. Zero is represented as 0/any, i.e.
+ the denominator is ignored. Negative numbers have the sign in
+ the numerator. */
+typedef struct
+{
+ __mpz_struct _mp_num;
+ __mpz_struct _mp_den;
+#if 0
+ int _mp_num_alloc; /* Number of limbs allocated
+ for the numerator. */
+ int _mp_num_size; /* The absolute value of this field is the
+ length of the numerator; the sign is the
+ sign of the entire rational number. */
+ mp_ptr _mp_num; /* Pointer to the numerator limbs. */
+ int _mp_den_alloc; /* Number of limbs allocated
+ for the denominator. */
+ int _mp_den_size; /* Length of the denominator. (This field
+ should always be positive.) */
+ mp_ptr _mp_den; /* Pointer to the denominator limbs. */
+#endif
+} __mpq_struct;
+
+typedef __mpq_struct MP_RAT;
+typedef __mpq_struct mpq_t[1];
+
+typedef struct
+{
+ int _mp_prec; /* Max precision, in number of `mp_limb_t's.
+ Set by mpf_init and modified by
+ mpf_set_prec. The area pointed to
+ by the `d' field contains `prec' + 1
+ limbs. */
+ int _mp_size; /* abs(SIZE) is the number of limbs
+ the last field points to. If SIZE
+ is negative this is a negative
+ number. */
+ mp_exp_t _mp_exp; /* Exponent, in the base of `mp_limb_t'. */
+ mp_limb_t *_mp_d; /* Pointer to the limbs. */
+} __mpf_struct;
+
+/* typedef __mpf_struct MP_FLOAT; */
+typedef __mpf_struct mpf_t[1];
+
+/* Types for function declarations in gmp files. */
+/* ??? Should not pollute user name space with these ??? */
+typedef __gmp_const __mpz_struct *mpz_srcptr;
+typedef __mpz_struct *mpz_ptr;
+typedef __gmp_const __mpf_struct *mpf_srcptr;
+typedef __mpf_struct *mpf_ptr;
+typedef __gmp_const __mpq_struct *mpq_srcptr;
+typedef __mpq_struct *mpq_ptr;
+
+#ifndef _PROTO
+#if defined (__STDC__) || defined (__cplusplus)
+#define _PROTO(x) x
+#else
+#define _PROTO(x) ()
+#endif
+#endif
+
+#ifndef __MPN
+#if defined (__STDC__) || defined (__cplusplus)
+#define __MPN(x) __mpn_##x
+#else
+#define __MPN(x) __mpn_/**/x
+#endif
+#endif
+
+#if defined (FILE) || defined (_STDIO_H_) || defined (__STDIO_H__) || defined (H_STDIO)
+#define _GMP_H_HAVE_FILE 1
+#endif
+
+void mp_set_memory_functions _PROTO ((void *(*) (size_t),
+ void *(*) (void *, size_t, size_t),
+ void (*) (void *, size_t)));
+extern const int mp_bits_per_limb;
+
+/**************** Integer (i.e. Z) routines. ****************/
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+void *_mpz_realloc _PROTO ((mpz_ptr, mp_size_t));
+
+void mpz_abs _PROTO ((mpz_ptr, mpz_srcptr));
+void mpz_add _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr));
+void mpz_add_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_and _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr));
+void mpz_array_init _PROTO ((mpz_ptr, mp_size_t, mp_size_t));
+void mpz_cdiv_q _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr));
+unsigned long int mpz_cdiv_q_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_cdiv_qr _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr));
+unsigned long int mpz_cdiv_qr_ui _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_cdiv_r _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr));
+unsigned long int mpz_cdiv_r_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+unsigned long int mpz_cdiv_ui _PROTO ((mpz_srcptr, unsigned long int));
+void mpz_clear _PROTO ((mpz_ptr));
+void mpz_clrbit _PROTO ((mpz_ptr, unsigned long int));
+int mpz_cmp _PROTO ((mpz_srcptr, mpz_srcptr));
+int mpz_cmp_si _PROTO ((mpz_srcptr, signed long int));
+int mpz_cmp_ui _PROTO ((mpz_srcptr, unsigned long int));
+void mpz_com _PROTO ((mpz_ptr, mpz_srcptr));
+void mpz_divexact _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr));
+void mpz_fac_ui _PROTO ((mpz_ptr, unsigned long int));
+void mpz_fdiv_q _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr));
+void mpz_fdiv_q_2exp _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+unsigned long int mpz_fdiv_q_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_fdiv_qr _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr));
+unsigned long int mpz_fdiv_qr_ui _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_fdiv_r _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr));
+void mpz_fdiv_r_2exp _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+unsigned long int mpz_fdiv_r_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+unsigned long int mpz_fdiv_ui _PROTO ((mpz_srcptr, unsigned long int));
+void mpz_gcd _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr));
+unsigned long int mpz_gcd_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_gcdext _PROTO ((mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr));
+/* signed */ long int mpz_get_si _PROTO ((mpz_srcptr));
+char *mpz_get_str _PROTO ((char *, int, mpz_srcptr));
+unsigned long int mpz_get_ui _PROTO ((mpz_srcptr));
+mp_limb_t mpz_getlimbn _PROTO ((mpz_srcptr, mp_size_t));
+unsigned long int mpz_hamdist _PROTO ((mpz_srcptr, mpz_srcptr));
+void mpz_init _PROTO ((mpz_ptr));
+#ifdef _GMP_H_HAVE_FILE
+size_t mpz_inp_binary _PROTO ((mpz_ptr, FILE *));
+size_t mpz_inp_raw _PROTO ((mpz_ptr, FILE *));
+size_t mpz_inp_str _PROTO ((mpz_ptr, FILE *, int));
+#endif
+void mpz_init_set _PROTO ((mpz_ptr, mpz_srcptr));
+void mpz_init_set_d _PROTO ((mpz_ptr, double));
+void mpz_init_set_si _PROTO ((mpz_ptr, signed long int));
+int mpz_init_set_str _PROTO ((mpz_ptr, const char *, int));
+void mpz_init_set_ui _PROTO ((mpz_ptr, unsigned long int));
+int mpz_invert _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr));
+void mpz_ior _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr));
+int mpz_jacobi _PROTO ((mpz_srcptr, mpz_srcptr));
+int mpz_legendre _PROTO ((mpz_srcptr, mpz_srcptr));
+void mpz_mod _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr));
+void mpz_mul _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr));
+void mpz_mul_2exp _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_mul_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_neg _PROTO ((mpz_ptr, mpz_srcptr));
+#ifdef _GMP_H_HAVE_FILE
+size_t mpz_out_binary _PROTO ((FILE *, mpz_srcptr));
+size_t mpz_out_raw _PROTO ((FILE *, mpz_srcptr));
+size_t mpz_out_str _PROTO ((FILE *, int, mpz_srcptr));
+#endif
+int mpz_perfect_square_p _PROTO ((mpz_srcptr));
+unsigned long int mpz_popcount _PROTO ((mpz_srcptr));
+void mpz_pow_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_powm _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr));
+void mpz_powm_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int, mpz_srcptr));
+int mpz_probab_prime_p _PROTO ((mpz_srcptr, int));
+void mpz_random _PROTO ((mpz_ptr, mp_size_t));
+void mpz_random2 _PROTO ((mpz_ptr, mp_size_t));
+unsigned long int mpz_scan0 _PROTO ((mpz_srcptr, unsigned long int));
+unsigned long int mpz_scan1 _PROTO ((mpz_srcptr, unsigned long int));
+void mpz_set _PROTO ((mpz_ptr, mpz_srcptr));
+void mpz_set_d _PROTO ((mpz_ptr, double));
+void mpz_set_si _PROTO ((mpz_ptr, signed long int));
+int mpz_set_str _PROTO ((mpz_ptr, const char *, int));
+void mpz_set_ui _PROTO ((mpz_ptr, unsigned long int));
+void mpz_setbit _PROTO ((mpz_ptr, unsigned long int));
+size_t mpz_size _PROTO ((mpz_srcptr));
+size_t mpz_sizeinbase _PROTO ((mpz_srcptr, int));
+void mpz_sqrt _PROTO ((mpz_ptr, mpz_srcptr));
+void mpz_sqrtrem _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr));
+void mpz_sub _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr));
+void mpz_sub_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_tdiv_q _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr));
+void mpz_tdiv_q_2exp _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_tdiv_q_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_tdiv_qr _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr));
+void mpz_tdiv_qr_ui _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_tdiv_r _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr));
+void mpz_tdiv_r_2exp _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_tdiv_r_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_ui_pow_ui _PROTO ((mpz_ptr, unsigned long int, unsigned long int));
+
+/**************** Rational (i.e. Q) routines. ****************/
+
+void mpq_init _PROTO ((mpq_ptr));
+void mpq_clear _PROTO ((mpq_ptr));
+void mpq_set _PROTO ((mpq_ptr, mpq_srcptr));
+void mpq_set_ui _PROTO ((mpq_ptr, unsigned long int, unsigned long int));
+void mpq_set_si _PROTO ((mpq_ptr, signed long int, unsigned long int));
+void mpq_add _PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr));
+void mpq_sub _PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr));
+void mpq_mul _PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr));
+void mpq_div _PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr));
+void mpq_neg _PROTO ((mpq_ptr, mpq_srcptr));
+int mpq_cmp _PROTO ((mpq_srcptr, mpq_srcptr));
+int mpq_cmp_ui _PROTO ((mpq_srcptr, unsigned long int, unsigned long int));
+void mpq_inv _PROTO ((mpq_ptr, mpq_srcptr));
+void mpq_set_num _PROTO ((mpq_ptr, mpz_srcptr));
+void mpq_set_den _PROTO ((mpq_ptr, mpz_srcptr));
+void mpq_get_num _PROTO ((mpz_ptr, mpq_srcptr));
+void mpq_get_den _PROTO ((mpz_ptr, mpq_srcptr));
+double mpq_get_d _PROTO ((mpq_srcptr));
+void mpq_canonicalize _PROTO ((mpq_ptr));
+
+/**************** Float (i.e. F) routines. ****************/
+
+void mpf_abs _PROTO ((mpf_ptr, mpf_srcptr));
+void mpf_add _PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr));
+void mpf_add_ui _PROTO ((mpf_ptr, mpf_srcptr, unsigned long int));
+void mpf_clear _PROTO ((mpf_ptr));
+int mpf_cmp _PROTO ((mpf_srcptr, mpf_srcptr));
+int mpf_cmp_si _PROTO ((mpf_srcptr, signed long int));
+int mpf_cmp_ui _PROTO ((mpf_srcptr, unsigned long int));
+void mpf_div _PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr));
+void mpf_div_2exp _PROTO ((mpf_ptr, mpf_srcptr, unsigned long int));
+void mpf_div_ui _PROTO ((mpf_ptr, mpf_srcptr, unsigned long int));
+void mpf_dump _PROTO ((mpf_srcptr));
+int mpf_eq _PROTO ((mpf_srcptr, mpf_srcptr, unsigned long int));
+unsigned long int mpf_get_prec _PROTO ((mpf_srcptr));
+char *mpf_get_str _PROTO ((char *, mp_exp_t *, int, size_t, mpf_srcptr));
+void mpf_init _PROTO ((mpf_ptr));
+void mpf_init2 _PROTO ((mpf_ptr, unsigned long int));
+#ifdef _GMP_H_HAVE_FILE
+size_t mpf_inp_str _PROTO ((mpf_ptr, FILE *, int));
+#endif
+void mpf_init_set _PROTO ((mpf_ptr, mpf_srcptr));
+void mpf_init_set_d _PROTO ((mpf_ptr, double));
+void mpf_init_set_si _PROTO ((mpf_ptr, signed long int));
+int mpf_init_set_str _PROTO ((mpf_ptr, char *, int));
+void mpf_init_set_ui _PROTO ((mpf_ptr, unsigned long int));
+void mpf_mul _PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr));
+void mpf_mul_2exp _PROTO ((mpf_ptr, mpf_srcptr, unsigned long int));
+void mpf_mul_ui _PROTO ((mpf_ptr, mpf_srcptr, unsigned long int));
+void mpf_neg _PROTO ((mpf_ptr, mpf_srcptr));
+#ifdef _GMP_H_HAVE_FILE
+size_t mpf_out_str _PROTO ((FILE *, int, size_t, mpf_srcptr));
+#endif
+void mpf_random2 _PROTO ((mpf_ptr, mp_size_t, mp_exp_t));
+void mpf_reldiff _PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr));
+void mpf_set _PROTO ((mpf_ptr, mpf_srcptr));
+void mpf_set_d _PROTO ((mpf_ptr, double));
+void mpf_set_default_prec _PROTO ((unsigned long int));
+void mpf_set_prec _PROTO ((mpf_ptr, unsigned long int));
+void mpf_set_prec_raw _PROTO ((mpf_ptr, unsigned long int));
+void mpf_set_si _PROTO ((mpf_ptr, signed long int));
+int mpf_set_str _PROTO ((mpf_ptr, const char *, int));
+void mpf_set_ui _PROTO ((mpf_ptr, unsigned long int));
+size_t mpf_size _PROTO ((mpf_srcptr));
+void mpf_sqrt _PROTO ((mpf_ptr, mpf_srcptr));
+void mpf_sqrt_ui _PROTO ((mpf_ptr, unsigned long int));
+void mpf_sub _PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr));
+void mpf_sub_ui _PROTO ((mpf_ptr, mpf_srcptr, unsigned long int));
+void mpf_ui_div _PROTO ((mpf_ptr, unsigned long int, mpf_srcptr));
+void mpf_ui_sub _PROTO ((mpf_ptr, unsigned long int, mpf_srcptr));
+#if defined (__cplusplus)
+}
+#endif
+/************ Low level positive-integer (i.e. N) routines. ************/
+
+/* This is ugly, but we need to make usr calls reach the prefixed function. */
+#define mpn_add __MPN(add)
+#define mpn_add_1 __MPN(add_1)
+#define mpn_add_n __MPN(add_n)
+#define mpn_addmul_1 __MPN(addmul_1)
+#define mpn_bdivmod __MPN(bdivmod)
+#define mpn_cmp __MPN(cmp)
+#define mpn_divmod_1 __MPN(divmod_1)
+#define mpn_divrem __MPN(divrem)
+#define mpn_divrem_1 __MPN(divrem_1)
+#define mpn_dump __MPN(dump)
+#define mpn_gcd __MPN(gcd)
+#define mpn_gcd_1 __MPN(gcd_1)
+#define mpn_gcdext __MPN(gcdext)
+#define mpn_get_str __MPN(get_str)
+#define mpn_hamdist __MPN(hamdist)
+#define mpn_lshift __MPN(lshift)
+#define mpn_mod_1 __MPN(mod_1)
+#define mpn_mul __MPN(mul)
+#define mpn_mul_1 __MPN(mul_1)
+#define mpn_mul_n __MPN(mul_n)
+#define mpn_perfect_square_p __MPN(perfect_square_p)
+#define mpn_popcount __MPN(popcount)
+#define mpn_preinv_mod_1 __MPN(preinv_mod_1)
+#define mpn_random2 __MPN(random2)
+#define mpn_rshift __MPN(rshift)
+#define mpn_scan0 __MPN(scan0)
+#define mpn_scan1 __MPN(scan1)
+#define mpn_set_str __MPN(set_str)
+#define mpn_sqrtrem __MPN(sqrtrem)
+#define mpn_sub __MPN(sub)
+#define mpn_sub_1 __MPN(sub_1)
+#define mpn_sub_n __MPN(sub_n)
+#define mpn_submul_1 __MPN(submul_1)
+#define mpn_udiv_w_sdiv __MPN(udiv_w_sdiv)
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+mp_limb_t mpn_add _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr,mp_size_t));
+mp_limb_t mpn_add_1 _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t));
+mp_limb_t mpn_add_n _PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t));
+mp_limb_t mpn_addmul_1 _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t));
+mp_limb_t mpn_bdivmod _PROTO ((mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, unsigned long int));
+int mpn_cmp _PROTO ((mp_srcptr, mp_srcptr, mp_size_t));
+mp_limb_t mpn_divmod_1 _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t));
+mp_limb_t mpn_divrem _PROTO ((mp_ptr, mp_size_t, mp_ptr, mp_size_t, mp_srcptr, mp_size_t));
+mp_limb_t mpn_divrem_1 _PROTO ((mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_limb_t));
+void mpn_dump _PROTO ((mp_srcptr, mp_size_t));
+mp_size_t mpn_gcd _PROTO ((mp_ptr, mp_ptr, mp_size_t, mp_ptr, mp_size_t));
+mp_limb_t mpn_gcd_1 _PROTO ((mp_srcptr, mp_size_t, mp_limb_t));
+mp_size_t mpn_gcdext _PROTO ((mp_ptr, mp_ptr, mp_ptr, mp_size_t, mp_ptr, mp_size_t));
+size_t mpn_get_str _PROTO ((unsigned char *, int, mp_ptr, mp_size_t));
+unsigned long int mpn_hamdist _PROTO ((mp_srcptr, mp_srcptr, mp_size_t));
+mp_limb_t mpn_lshift _PROTO ((mp_ptr, mp_srcptr, mp_size_t, unsigned int));
+mp_limb_t mpn_mod_1 _PROTO ((mp_srcptr, mp_size_t, mp_limb_t));
+mp_limb_t mpn_mul _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t));
+mp_limb_t mpn_mul_1 _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t));
+void mpn_mul_n _PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t));
+int mpn_perfect_square_p _PROTO ((mp_srcptr, mp_size_t));
+unsigned long int mpn_popcount _PROTO ((mp_srcptr, mp_size_t));
+mp_limb_t mpn_preinv_mod_1 _PROTO ((mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t));
+void mpn_random2 _PROTO ((mp_ptr, mp_size_t));
+mp_limb_t mpn_rshift _PROTO ((mp_ptr, mp_srcptr, mp_size_t, unsigned int));
+unsigned long int mpn_scan0 _PROTO ((mp_srcptr, unsigned long int));
+unsigned long int mpn_scan1 _PROTO ((mp_srcptr, unsigned long int));
+mp_size_t mpn_set_str _PROTO ((mp_ptr, const unsigned char *, size_t, int));
+mp_size_t mpn_sqrtrem _PROTO ((mp_ptr, mp_ptr, mp_srcptr, mp_size_t));
+mp_limb_t mpn_sub _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr,mp_size_t));
+mp_limb_t mpn_sub_1 _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t));
+mp_limb_t mpn_sub_n _PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t));
+mp_limb_t mpn_submul_1 _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t));
+#if defined (__cplusplus)
+}
+#endif
+
+#if defined (__GNUC__) || defined (_FORCE_INLINES)
+_EXTERN_INLINE mp_limb_t
+#if defined (__STDC__) || defined (__cplusplus)
+mpn_add_1 (register mp_ptr res_ptr,
+ register mp_srcptr s1_ptr,
+ register mp_size_t s1_size,
+ register mp_limb_t s2_limb)
+#else
+mpn_add_1 (res_ptr, s1_ptr, s1_size, s2_limb)
+ register mp_ptr res_ptr;
+ register mp_srcptr s1_ptr;
+ register mp_size_t s1_size;
+ register mp_limb_t s2_limb;
+#endif
+{
+ register mp_limb_t x;
+
+ x = *s1_ptr++;
+ s2_limb = x + s2_limb;
+ *res_ptr++ = s2_limb;
+ if (s2_limb < x)
+ {
+ while (--s1_size != 0)
+ {
+ x = *s1_ptr++ + 1;
+ *res_ptr++ = x;
+ if (x != 0)
+ goto fin;
+ }
+
+ return 1;
+ }
+
+ fin:
+ if (res_ptr != s1_ptr)
+ {
+ mp_size_t i;
+ for (i = 0; i < s1_size - 1; i++)
+ res_ptr[i] = s1_ptr[i];
+ }
+ return 0;
+}
+
+_EXTERN_INLINE mp_limb_t
+#if defined (__STDC__) || defined (__cplusplus)
+mpn_add (register mp_ptr res_ptr,
+ register mp_srcptr s1_ptr,
+ register mp_size_t s1_size,
+ register mp_srcptr s2_ptr,
+ register mp_size_t s2_size)
+#else
+mpn_add (res_ptr, s1_ptr, s1_size, s2_ptr, s2_size)
+ register mp_ptr res_ptr;
+ register mp_srcptr s1_ptr;
+ register mp_size_t s1_size;
+ register mp_srcptr s2_ptr;
+ register mp_size_t s2_size;
+#endif
+{
+ mp_limb_t cy_limb = 0;
+
+ if (s2_size != 0)
+ cy_limb = mpn_add_n (res_ptr, s1_ptr, s2_ptr, s2_size);
+
+ if (s1_size - s2_size != 0)
+ cy_limb = mpn_add_1 (res_ptr + s2_size,
+ s1_ptr + s2_size,
+ s1_size - s2_size,
+ cy_limb);
+ return cy_limb;
+}
+
+_EXTERN_INLINE mp_limb_t
+#if defined (__STDC__) || defined (__cplusplus)
+mpn_sub_1 (register mp_ptr res_ptr,
+ register mp_srcptr s1_ptr,
+ register mp_size_t s1_size,
+ register mp_limb_t s2_limb)
+#else
+mpn_sub_1 (res_ptr, s1_ptr, s1_size, s2_limb)
+ register mp_ptr res_ptr;
+ register mp_srcptr s1_ptr;
+ register mp_size_t s1_size;
+ register mp_limb_t s2_limb;
+#endif
+{
+ register mp_limb_t x;
+
+ x = *s1_ptr++;
+ s2_limb = x - s2_limb;
+ *res_ptr++ = s2_limb;
+ if (s2_limb > x)
+ {
+ while (--s1_size != 0)
+ {
+ x = *s1_ptr++;
+ *res_ptr++ = x - 1;
+ if (x != 0)
+ goto fin;
+ }
+
+ return 1;
+ }
+
+ fin:
+ if (res_ptr != s1_ptr)
+ {
+ mp_size_t i;
+ for (i = 0; i < s1_size - 1; i++)
+ res_ptr[i] = s1_ptr[i];
+ }
+ return 0;
+}
+
+_EXTERN_INLINE mp_limb_t
+#if defined (__STDC__) || defined (__cplusplus)
+mpn_sub (register mp_ptr res_ptr,
+ register mp_srcptr s1_ptr,
+ register mp_size_t s1_size,
+ register mp_srcptr s2_ptr,
+ register mp_size_t s2_size)
+#else
+mpn_sub (res_ptr, s1_ptr, s1_size, s2_ptr, s2_size)
+ register mp_ptr res_ptr;
+ register mp_srcptr s1_ptr;
+ register mp_size_t s1_size;
+ register mp_srcptr s2_ptr;
+ register mp_size_t s2_size;
+#endif
+{
+ mp_limb_t cy_limb = 0;
+
+ if (s2_size != 0)
+ cy_limb = mpn_sub_n (res_ptr, s1_ptr, s2_ptr, s2_size);
+
+ if (s1_size - s2_size != 0)
+ cy_limb = mpn_sub_1 (res_ptr + s2_size,
+ s1_ptr + s2_size,
+ s1_size - s2_size,
+ cy_limb);
+ return cy_limb;
+}
+#endif /* __GNUC__ */
+
+/* Allow faster testing for negative, zero, and positive. */
+#define mpz_sgn(Z) ((Z)->_mp_size < 0 ? -1 : (Z)->_mp_size > 0)
+#define mpf_sgn(F) ((F)->_mp_size < 0 ? -1 : (F)->_mp_size > 0)
+#define mpq_sgn(Q) ((Q)->_mp_num._mp_size < 0 ? -1 : (Q)->_mp_num._mp_size > 0)
+
+/* Allow direct user access to numerator and denominator of a mpq_t object. */
+#define mpq_numref(Q) (&((Q)->_mp_num))
+#define mpq_denref(Q) (&((Q)->_mp_den))
+
+/* When using GCC, optimize certain common comparisons. */
+#if defined (__GNUC__)
+#define mpz_cmp_ui(Z,UI) \
+ (__builtin_constant_p (UI) && (UI) == 0 \
+ ? mpz_sgn (Z) : mpz_cmp_ui (Z,UI))
+#define mpz_cmp_si(Z,UI) \
+ (__builtin_constant_p (UI) && (UI) == 0 ? mpz_sgn (Z) \
+ : __builtin_constant_p (UI) && (UI) > 0 ? mpz_cmp_ui (Z,UI) \
+ : mpz_cmp_si (Z,UI))
+#define mpq_cmp_ui(Q,NUI,DUI) \
+ (__builtin_constant_p (NUI) && (NUI) == 0 \
+ ? mpq_sgn (Q) : mpq_cmp_ui (Q,NUI,DUI))
+#endif
+
+#define mpn_divmod(qp,np,nsize,dp,dsize) mpn_divrem (qp,0,np,nsize,dp,dsize)
+#if 0
+#define mpn_divmod_1(qp,np,nsize,dlimb) mpn_divrem_1 (qp,0,np,nsize,dlimb)
+#endif
+
+/* Compatibility with GMP 1. */
+#define mpz_mdiv mpz_fdiv_q
+#define mpz_mdivmod mpz_fdiv_qr
+#define mpz_mmod mpz_fdiv_r
+#define mpz_mdiv_ui mpz_fdiv_q_ui
+#define mpz_mdivmod_ui(q,r,n,d) \
+ ((r == 0) ? mpz_fdiv_q_ui (q,n,d) : mpz_fdiv_qr_ui (q,r,n,d))
+#define mpz_mmod_ui(r,n,d) \
+ ((r == 0) ? mpz_fdiv_ui (n,d) : mpz_fdiv_r_ui (r,n,d))
+
+/* Useful synonyms, but not quite compatible with GMP 1. */
+#define mpz_div mpz_fdiv_q
+#define mpz_divmod mpz_fdiv_qr
+#define mpz_div_ui mpz_fdiv_q_ui
+#define mpz_divmod_ui mpz_fdiv_qr_ui
+#define mpz_mod_ui mpz_fdiv_r_ui
+#define mpz_div_2exp mpz_fdiv_q_2exp
+#define mpz_mod_2exp mpz_fdiv_r_2exp
+
+#define __GNU_MP_VERSION 2
+#define __GNU_MP_VERSION_MINOR 0
+#define __GMP_H__
+#endif /* __GMP_H__ */
diff --git a/gmp.info b/gmp.info
new file mode 100644
index 000000000..2c57a3fb7
--- /dev/null
+++ b/gmp.info
@@ -0,0 +1,78 @@
+This is Info file gmp.info, produced by Makeinfo-1.64 from the input
+file gmp.texi.
+
+START-INFO-DIR-ENTRY
+* gmp: (gmp.info). GNU Multiple Precision Arithmetic Library.
+END-INFO-DIR-ENTRY
+
+ This file documents GNU MP, a library for arbitrary-precision
+arithmetic.
+
+ This is a draft edition of the documentation, last updated April
+1996.
+
+ Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation,
+Inc.
+
+ Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+ Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+ Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be stated in a
+translation approved by the Foundation.
+
+
+Indirect:
+gmp.info-1: 1093
+gmp.info-2: 49714
+gmp.info-3: 92684
+
+Tag Table:
+(Indirect)
+Node: Top1093
+Node: Copying2101
+Node: Introduction to MP3801
+Node: Installing MP5731
+Node: MP Basics10170
+Node: Reporting Bugs16175
+Node: Integer Functions17695
+Node: Initializing Integers18302
+Node: Assigning Integers20418
+Node: Simultaneous Integer Init & Assign21593
+Node: Converting Integers23549
+Node: Integer Arithmetic25159
+Node: Comparison Functions35673
+Node: Integer Logic and Bit Fiddling36244
+Node: I/O of Integers38305
+Node: Miscellaneous Integer Functions40786
+Node: Rational Number Functions42456
+Node: Initializing Rationals43751
+Node: Assigning Rationals44871
+Node: Comparing Rationals45837
+Node: Applying Integer Functions46921
+Node: Miscellaneous Rational Functions47739
+Node: Floating-point Functions49714
+Node: Initializing Floats51562
+Node: Assigning Floats54314
+Node: Simultaneous Float Init & Assign55806
+Node: Converting Floats57323
+Node: Float Arithmetic58831
+Node: Float Comparison60883
+Node: I/O of Floats61807
+Node: Miscellaneous Float Functions63829
+Node: Low-level Functions64512
+Node: BSD Compatible Functions80873
+Node: Custom Allocation85211
+Node: Contributors87549
+Node: References89031
+Node: Concept Index90067
+Node: Function Index92684
+
+End Tag Table
diff --git a/gmp.info-1 b/gmp.info-1
new file mode 100644
index 000000000..ac75132ff
--- /dev/null
+++ b/gmp.info-1
@@ -0,0 +1,1241 @@
+This is Info file gmp.info, produced by Makeinfo-1.64 from the input
+file gmp.texi.
+
+START-INFO-DIR-ENTRY
+* gmp: (gmp.info). GNU Multiple Precision Arithmetic Library.
+END-INFO-DIR-ENTRY
+
+ This file documents GNU MP, a library for arbitrary-precision
+arithmetic.
+
+ This is a draft edition of the documentation, last updated April
+1996.
+
+ Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation,
+Inc.
+
+ Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+ Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+ Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be stated in a
+translation approved by the Foundation.
+
+
+File: gmp.info, Node: Top, Next: Copying, Prev: (dir), Up: (dir)
+
+GNU MP
+******
+
+ This manual documents how to install and use the GNU Multiple
+Precision Arithmetic Library, version 2.0.
+
+* Menu:
+
+* Copying:: GMP Copying Conditions (LGPL).
+* Introduction to MP:: Brief introduction to GNU MP.
+* Installing MP:: How to configure and compile the MP library.
+* MP Basics:: What every MP user should now.
+* Reporting Bugs:: How to usefully report bugs.
+* Integer Functions:: Functions for arithmetic on signed integers.
+* Rational Number Functions:: Functions for arithmetic on rational numbers.
+* Floating-point Functions:: Functions for arithmetic on floats.
+* Low-level Functions:: Fast functions for natural numbers.
+* BSD Compatible Functions:: All functions found in BSD MP.
+* Custom Allocation:: How to customize the internal allocation.
+
+* Contributors::
+* References::
+* Concept Index::
+* Function Index::
+
+
+File: gmp.info, Node: Copying, Next: Introduction to MP, Prev: Top, Up: Top
+
+GNU MP Copying Conditions
+*************************
+
+ This library is "free"; this means that everyone is free to use it
+and free to redistribute it on a free basis. The library is not in the
+public domain; it is copyrighted and there are restrictions on its
+distribution, but these restrictions are designed to permit everything
+that a good cooperating citizen would want to do. What is not allowed
+is to try to prevent others from further sharing any version of this
+library that they might get from you.
+
+ Specifically, we want to make sure that you have the right to give
+away copies of the library, that you receive source code or else can
+get it if you want it, that you can change this library or use pieces
+of it in new free programs, and that you know you can do these things.
+
+ To make sure that everyone has such rights, we have to forbid you to
+deprive anyone else of these rights. For example, if you distribute
+copies of the GNU MP library, you must give the recipients all the
+rights that you have. You must make sure that they, too, receive or
+can get the source code. And you must tell them their rights.
+
+ Also, for our own protection, we must make certain that everyone
+finds out that there is no warranty for the GNU MP library. If it is
+modified by someone else and passed on, we want their recipients to
+know that what they have is not what we distributed, so that any
+problems introduced by others will not reflect on our reputation.
+
+ The precise conditions of the license for the GNU MP library are
+found in the Library General Public License that accompany the source
+code.
+
+
+File: gmp.info, Node: Introduction to MP, Next: Installing MP, Prev: Copying, Up: Top
+
+Introduction to GNU MP
+**********************
+
+ GNU MP is a portable library written in C for arbitrary precision
+arithmetic on integers, rational numbers, and floating-point numbers.
+It aims to provide the fastest possible arithmetic for all applications
+that need higher precision than is directly supported by the basic C
+types.
+
+ Many applications use just a few hundred bits of precision; but some
+applications may need thousands or even millions of bits. MP is
+designed to give good performance for both, by choosing algorithms
+based on the sizes of the operands, and by carefully keeping the
+overhead at a minimum.
+
+ The speed of MP is achieved by using fullwords as the basic
+arithmetic type, by using sophisticated algorithms, by including
+carefully optimized assembly code for the most common inner loops for
+many different CPUs, and by a general emphasis on speed (as opposed to
+simplicity or elegance).
+
+ There is carefully optimized assembly code for these CPUs: DEC
+Alpha, Amd 29000, HPPA 1.0 and 1.1, Intel Pentium and generic x86,
+Intel i960, Motorola MC68000, MC68020, MC88100, and MC88110,
+Motorola/IBM PowerPC, National NS32000, IBM POWER, MIPS R3000, R4000,
+SPARCv7, SuperSPARC, generic SPARCv8, and DEC VAX. Some optimizations
+also for ARM, Clipper, IBM ROMP (RT), and Pyramid AP/XP.
+
+ This version of MP is released under a more liberal license than
+previous versions. It is now permitted to link MP to non-free
+programs, as long as MP source code is provided when distributing the
+non-free program.
+
+How to use this Manual
+======================
+
+ Everyone should read *Note MP Basics::. If you need to install the
+library yourself, you need to read *Note Installing MP::, too.
+
+ The rest of the manual can be used for later reference, although it
+is probably a good idea too glance through it.
+
+
+File: gmp.info, Node: Installing MP, Next: MP Basics, Prev: Introduction to MP, Up: Top
+
+Installing MP
+*************
+
+ To build MP, you first have to configure it for your CPU and
+operating system. You need a C compiler, preferably GCC, but any
+reasonable compiler should work. And you need a standard Unix `make'
+program, plus some other standard Unix utility programs.
+
+ (If you're on a MS-DOS machine, your can build MP using `make.bat'.
+It requires that djgpp is installed. It does not require
+configuration, nor is `make' needed; `make.bat' both configures and
+builds the library.)
+
+ Here are the steps needed to install the library on Unix systems:
+
+ 1. In most cases, `./configure --target=cpu-vendor-os', should work
+ both for native and cross-compilation. If you get error messages,
+ your machine might not be supported.
+
+ If you want to compile in a separate object directory, cd to that
+ directory, and prefix the configure command with the path to the
+ MP source directory. Not all `make' programs have the necessary
+ features to support this. In particular, SunOS and Slowaris
+ `make' have bugs that makes them unable to build from a separate
+ object directory. Use GNU `make' instead.
+
+ In addition to the standard cpu-vendor-os tuples, MP recognizes
+ sparc8 and supersparc as valid CPU names. Specifying these CPU
+ names for relevant systems will improve performance significantly.
+
+ In general, if you want a library that runs as fast as possible,
+ you should make sure you configure MP for the exact CPU type your
+ system uses.
+
+ If you have `gcc' in your `PATH', it will be used by default. To
+ override this, pass `-with-gcc=no' to `configure'.
+
+ 2. `make'
+
+ This will compile MP, and create a library archive file `libgmp.a'
+ in the working directory.
+
+ 3. `make check'
+
+ This will make sure MP was built correctly. If you get error
+ messages, please report this to `bug-gmp@prep.ai.mit.edu'. (*Note
+ Reporting Bugs::, for information on what to include in useful bug
+ reports.)
+
+ 4. `make install'
+
+ This will copy the file `gmp.h' and `libgmp.a', as well as the info
+ files, to `/usr/local' (or if you passed the `--prefix' option to
+ `configure', to the directory given as argument to `--prefix').
+
+If you wish to build and install the BSD MP compatible functions, use
+`make libmp.a' and `make install-bsdmp'.
+
+ There are some other useful make targets:
+
+ * `doc'
+
+ Create a DVI version of the manual, in `gmp.dvi' and a set of info
+ files, in `gmp.info', `gmp.info-1', `gmp.info-2', etc.
+
+ * `ps'
+
+ Create a Postscript version of the manual, in `gmp.ps'.
+
+ * `html'
+
+ Create a HTML version of the manual, in `gmp.html'.
+
+ * `clean'
+
+ Delete all object files and archive files, but not the
+ configuration files.
+
+ * `distclean'
+
+ Delete all files not included in the distribution.
+
+ * `uninstall'
+
+ Delete all files copied by `make install'.
+
+Known Build Problems
+====================
+
+ GCC 2.7.2 (as well as 2.6.3) for the RS/6000 and PowerPC can not be
+used to compile MP, due to a bug in GCC. If you want to use GCC for
+these machines, you need to apply the patch below to GCC, or use a
+later version of the compiler.
+
+ If you are on a Sequent Symmetry, use the GNU assembler instead of
+the system's assembler, since the latter has serious bugs.
+
+ The system compiler on NeXT is a massacred and old gcc, even if the
+compiler calls itself `cc'. This compiler cannot be used to build MP.
+You need to get a real gcc, and install that before you compile MP.
+(NeXT might have fixed this in newer releases of their system.)
+
+ Please report other problems to `bug-gmp@prep.ai.mit.edu'. *Note
+Reporting Bugs::.
+
+ Patch to apply to GCC 2.6.3 and 2.7.2:
+
+ *** config/rs6000/rs6000.md Sun Feb 11 08:22:11 1996
+ --- config/rs6000/rs6000.md.new Sun Feb 18 03:33:37 1996
+ ***************
+ *** 920,926 ****
+ (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (not:SI (match_dup 1)))]
+ ""
+ ! "nor. %0,%2,%1"
+ [(set_attr "type" "compare")])
+
+ (define_insn ""
+ --- 920,926 ----
+ (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (not:SI (match_dup 1)))]
+ ""
+ ! "nor. %0,%1,%1"
+ [(set_attr "type" "compare")])
+
+ (define_insn ""
+
+
+File: gmp.info, Node: MP Basics, Next: Reporting Bugs, Prev: Installing MP, Up: Top
+
+MP Basics
+*********
+
+ All declarations needed to use MP are collected in the include file
+`gmp.h'. It is designed to work with both C and C++ compilers.
+
+Nomenclature and Types
+======================
+
+In this manual, "integer" usually means a multiple precision integer, as
+defined by the MP library. The C data type for such integers is
+`mpz_t'. Here are some examples of how to declare such integers:
+
+ mpz_t sum;
+
+ struct foo { mpz_t x, y; };
+
+ mpz_t vec[20];
+
+"Rational number" means a multiple precision fraction. The C data type
+for these fractions is `mpq_t'. For example:
+
+ mpq_t quotient;
+
+"Floating point number" or "Float" for short, is an arbitrary precision
+mantissa with an limited precision exponent. The C data type for such
+objects is `mpf_t'.
+
+A "limb" means the part of a multi-precision number that fits in a
+single word. (We chose this word because a limb of the human body is
+analogous to a digit, only larger, and containing several digits.)
+Normally a limb contains 32 or 64 bits. The C data type for a limb is
+`mp_limb_t'.
+
+Function Classes
+================
+
+ There are six classes of functions in the MP library:
+
+ 1. Functions for signed integer arithmetic, with names beginning with
+ `mpz_'. The associated type is `mpz_t'. There are about 100
+ functions in this class.
+
+ 2. Functions for rational number arithmetic, with names beginning with
+ `mpq_'. The associated type is `mpq_t'. There are about 20
+ functions in this class, but the functions in the previous class
+ can be used for performing arithmetic on the numerator and
+ denominator separately.
+
+ 3. Functions for floating-point arithmetic, with names beginning with
+ `mpf_'. The associated type is `mpf_t'. There are about 50
+ functions is this class.
+
+ 4. Functions compatible with Berkeley MP, such as `itom', `madd', and
+ `mult'. The associated type is `MINT'.
+
+ 5. Fast low-level functions that operate on natural numbers. These
+ are used by the functions in the preceding groups, and you can
+ also call them directly from very time-critical user programs.
+ These functions' names begin with `mpn_'. There are about 30
+ (hard-to-use) functions in this class.
+
+ The associated type is array of `mp_limb_t'.
+
+ 6. Miscellaneous functions. Functions for setting up custom
+ allocation.
+
+MP Variable Conventions
+=======================
+
+ As a general rule, all MP functions expect output arguments before
+input arguments. This notation is based on an analogy with the
+assignment operator. (The BSD MP compatibility functions disobey this
+rule, having the output argument(s) last.)
+
+ MP allows you to use the same variable for both input and output in
+the same expression. For example, the main function for integer
+multiplication, `mpz_mul', can be used like this: `mpz_mul (x, x, x);'.
+This computes the square of X and put the result back in X.
+
+ Before you can assign to an MP variable, you need to initialize it
+by calling one of the special initialization functions. When you're
+done with a variable, you need to clear it out, using one of the
+functions for that purpose. Which function to use depends on the type
+of variable. See the chapters on integer functions, rational number
+functions, and floating-point functions for details.
+
+ A variable should only be initialized once, or at least cleared out
+between each initialization. After a variable has been initialized, it
+may be assigned to any number of times.
+
+ For efficiency reasons, avoid to initialize and clear out a variable
+in loops. Instead, initialize it before entering the loop, and clear
+it out after the loop has exited.
+
+ You don't need to be concerned about allocating additional space for
+MP variables. All functions in MP automatically allocate additional
+space when a variable does not already have enough space. They do not,
+however, reduce the space when a smaller number is stored in the
+object. Most of the time, this policy is best, since it avoids
+frequent re-allocation.
+
+Useful Macros and Constants
+===========================
+
+ - Global Constant: const int mp_bits_per_limb
+ The number of bits per limb.
+
+ - Macro: __GNU_MP_VERSION
+ - Macro: __GNU_MP_VERSION_MINOR
+ The major and minor MP version, respectively, as integers.
+
+Compatibility with Version 1.x
+==============================
+
+ This version of MP is upward compatible with previous versions of
+MP, with a few exceptions.
+
+ 1. Integer division functions round the result differently. The old
+ functions (`mpz_div', `mpz_divmod', `mpz_mdiv', `mpz_mdivmod',
+ etc) now all use floor rounding (i.e., they round the quotient to
+ -infinity). There are a lot of new functions for integer
+ division, giving the user better control over the rounding.
+
+ 2. The function `mpz_mod' now compute the true *mod* function.
+
+ 3. The functions `mpz_powm' and `mpz_powm_ui' now use *mod* for
+ reduction.
+
+ 4. The assignment functions for rational numbers do no longer
+ canonicalize their results. In the case a non-canonical result
+ could arise from an assignment, the user need to insert an
+ explicit call to `mpq_canonicalize'. This change was made for
+ efficiency.
+
+ 5. Output generated by `mpz_out_raw' in this release cannot be read
+ by `mpz_inp_raw' in previous releases. This change was made for
+ making the file format truly portable between machines with
+ different word sizes.
+
+ 6. Several `mpn' functions have changed. But they were intentionally
+ undocumented in previous releases.
+
+
+Getting the Latest Version of MP
+================================
+
+ The latest version of the MP library is available by anonymous ftp
+from from `prep.ai.mit.edu'. The file name is
+`/pub/gnu/gmp-M.N.tar.gz'. Many sites around the world mirror `prep';
+please use a mirror site near you.
+
+
+File: gmp.info, Node: Reporting Bugs, Next: Integer Functions, Prev: MP Basics, Up: Top
+
+Reporting Bugs
+**************
+
+ If you think you have found a bug in the MP library, please
+investigate it and report it. We have made this library available to
+you, and it is not to ask too much from you, to ask you to report the
+bugs that you find.
+
+ There are a few things you should think about when you put your bug
+report together.
+
+ You have to send us a test case that makes it possible for us to
+reproduce the bug. Include instructions on how to run the test case.
+
+ You also have to explain what is wrong; if you get a crash, or if
+the results printed are incorrect and in that case, in what way.
+
+ It is not uncommon that an observed problem is actually due to a bug
+in the compiler used when building MP; the MP code tends to explore
+interesting corners in compilers. Therefore, please include compiler
+version information in your bug report. This can be extracted using
+`what `which cc`', or, if you're using gcc, `gcc -v'. Also, include
+the output from `uname -a'.
+
+ If your bug report is good, we will do our best to help you to get a
+corrected version of the library; if the bug report is poor, we won't
+do anything about it (aside of chiding you to send better bug reports).
+
+ Send your bug report to: `bug-gmp@prep.ai.mit.edu'.
+
+ If you think something in this manual is unclear, or downright
+incorrect, or if the language needs to be improved, please send a note
+to the same address.
+
+
+File: gmp.info, Node: Integer Functions, Next: Rational Number Functions, Prev: Reporting Bugs, Up: Top
+
+Integer Functions
+*****************
+
+ This chapter describes the MP functions for performing integer
+arithmetic. These functions start with the prefix `mpz_'.
+
+ Arbitrary precision integers are stored in objects of type `mpz_t'.
+
+* Menu:
+
+* Initializing Integers::
+* Assigning Integers::
+* Simultaneous Integer Init & Assign::
+* Converting Integers::
+* Integer Arithmetic::
+* Comparison Functions::
+* Integer Logic and Bit Fiddling::
+* I/O of Integers::
+* Miscellaneous Integer Functions::
+
+
+File: gmp.info, Node: Initializing Integers, Next: Assigning Integers, Up: Integer Functions
+
+Initialization and Assignment Functions
+=======================================
+
+ The functions for integer arithmetic assume that all integer objects
+are initialized. You do that by calling the function `mpz_init'.
+
+ - Function: void mpz_init (mpz_t INTEGER)
+ Initialize INTEGER with limb space and set the initial numeric
+ value to 0. Each variable should normally only be initialized
+ once, or at least cleared out (using `mpz_clear') between each
+ initialization.
+
+ Here is an example of using `mpz_init':
+
+ {
+ mpz_t integ;
+ mpz_init (integ);
+ ...
+ mpz_add (integ, ...);
+ ...
+ mpz_sub (integ, ...);
+
+ /* Unless the program is about to exit, do ... */
+ mpz_clear (integ);
+ }
+
+As you can see, you can store new values any number of times, once an
+object is initialized.
+
+ - Function: void mpz_clear (mpz_t INTEGER)
+ Free the limb space occupied by INTEGER. Make sure to call this
+ function for all `mpz_t' variables when you are done with them.
+
+ - Function: void * _mpz_realloc (mpz_t INTEGER, mp_size_t NEW_ALLOC)
+ Change the limb space allocation to NEW_ALLOC limbs. This
+ function is not normally called from user code, but it can be used
+ to give memory back to the heap, or to increase the space of a
+ variable to avoid repeated automatic re-allocation.
+
+ - Function: void mpz_array_init (mpz_t INTEGER_ARRAY[], size_t
+ ARRAY_SIZE, mp_size_t FIXED_NUM_BITS)
+ Allocate *fixed* limb space for all ARRAY_SIZE integers in
+ INTEGER_ARRAY. The fixed allocation for each integer in the array
+ is enough to store FIXED_NUM_BITS. If the fixed space will be
+ insufficient for storing the result of a subsequent calculation,
+ the result is unpredictable.
+
+ This function is useful for decreasing the working set for some
+ algorithms that use large integer arrays.
+
+ There is no way to de-allocate the storage allocated by this
+ function. Don't call `mpz_clear'!
+
+
+File: gmp.info, Node: Assigning Integers, Next: Simultaneous Integer Init & Assign, Prev: Initializing Integers, Up: Integer Functions
+
+Assignment Functions
+--------------------
+
+ These functions assign new values to already initialized integers
+(*note Initializing Integers::.).
+
+ - Function: void mpz_set (mpz_t ROP, mpz_t OP)
+ - Function: void mpz_set_ui (mpz_t ROP, unsigned long int OP)
+ - Function: void mpz_set_si (mpz_t ROP, signed long int OP)
+ - Function: void mpz_set_d (mpz_t ROP, double OP)
+ Set the value of ROP from OP.
+
+ - Function: int mpz_set_str (mpz_t ROP, char *STR, int BASE)
+ Set the value of ROP from STR, a '\0'-terminated C string in base
+ BASE. White space is allowed in the string, and is simply
+ ignored. The base may vary from 2 to 36. If BASE is 0, the
+ actual base is determined from the leading characters: if the
+ first two characters are `0x' or `0X', hexadecimal is assumed,
+ otherwise if the first character is `0', octal is assumed,
+ otherwise decimal is assumed.
+
+ This function returns 0 if the entire string up to the '\0' is a
+ valid number in base BASE. Otherwise it returns -1.
+
+
+File: gmp.info, Node: Simultaneous Integer Init & Assign, Next: Converting Integers, Prev: Assigning Integers, Up: Integer Functions
+
+Combined Initialization and Assignment Functions
+------------------------------------------------
+
+ For convenience, MP provides a parallel series of initialize-and-set
+functions which initialize the output and then store the value there.
+These functions' names have the form `mpz_init_set...'
+
+ Here is an example of using one:
+
+ {
+ mpz_t pie;
+ mpz_init_set_str (pie, "3141592653589793238462643383279502884", 10);
+ ...
+ mpz_sub (pie, ...);
+ ...
+ mpz_clear (pie);
+ }
+
+Once the integer has been initialized by any of the `mpz_init_set...'
+functions, it can be used as the source or destination operand for the
+ordinary integer functions. Don't use an initialize-and-set function
+on a variable already initialized!
+
+ - Function: void mpz_init_set (mpz_t ROP, mpz_t OP)
+ - Function: void mpz_init_set_ui (mpz_t ROP, unsigned long int OP)
+ - Function: void mpz_init_set_si (mpz_t ROP, signed long int OP)
+ - Function: void mpz_init_set_d (mpz_t ROP, double OP)
+ Initialize ROP with limb space and set the initial numeric value
+ from OP.
+
+ - Function: int mpz_init_set_str (mpz_t ROP, char *STR, int BASE)
+ Initialize ROP and set its value from STR, a '\0'-terminated C
+ string in base BASE. White space is allowed in the string, and is
+ simply ignored. The base may vary from 2 to 36. If BASE is 0,
+ the actual base is determined from the leading characters: if the
+ first two characters are `0x' or `0X', hexadecimal is assumed,
+ otherwise if the first character is `0', octal is assumed,
+ otherwise decimal is assumed.
+
+ If the string is a correct base BASE number, the function returns
+ 0; if an error occurs it returns -1. ROP is initialized even if
+ an error occurs. (I.e., you have to call `mpz_clear' for it.)
+
+
+File: gmp.info, Node: Converting Integers, Next: Integer Arithmetic, Prev: Simultaneous Integer Init & Assign, Up: Integer Functions
+
+Conversion Functions
+====================
+
+ This section describes functions for converting arbitrary precision
+integers to standard C types. Functions for converting *to* arbitrary
+precision integers are described in *Note Assigning Integers:: and
+*Note I/O of Integers::.
+
+ - Function: unsigned long int mpz_get_ui (mpz_t OP)
+ Return the least significant part from OP. This function combined
+ with
+ `mpz_tdiv_q_2exp(..., OP, CHAR_BIT*sizeof(unsigned long int))' can
+ be used to extract the limbs of an integer efficiently.
+
+ - Function: signed long int mpz_get_si (mpz_t OP)
+ If OP fits into a `signed long int' return the value of OP.
+ Otherwise return the least significant part of OP, with the same
+ sign as OP.
+
+ If OP is too large to fit in a `signed long int', the returned
+ result is probably not very useful.
+
+ - Function: char * mpz_get_str (char *STR, int BASE, mpz_t OP)
+ Convert OP to a string of digits in base BASE. The base may vary
+ from 2 to 36.
+
+ If STR is NULL, space for the result string is allocated using the
+ default allocation function, and a pointer to the string is
+ returned.
+
+ If STR is not NULL, it should point to a block of storage enough
+ large for the result. To find out the right amount of space to
+ provide for STR, use `mpz_sizeinbase (OP, BASE) + 2'. The two
+ extra bytes are for a possible minus sign, and for the terminating
+ null character.
+
+
+File: gmp.info, Node: Integer Arithmetic, Next: Comparison Functions, Prev: Converting Integers, Up: Integer Functions
+
+Arithmetic Functions
+====================
+
+ - Function: void mpz_add (mpz_t ROP, mpz_t OP1, mpz_t OP2)
+ - Function: void mpz_add_ui (mpz_t ROP, mpz_t OP1, unsigned long int
+ OP2)
+ Set ROP to OP1 + OP2.
+
+ - Function: void mpz_sub (mpz_t ROP, mpz_t OP1, mpz_t OP2)
+ - Function: void mpz_sub_ui (mpz_t ROP, mpz_t OP1, unsigned long int
+ OP2)
+ Set ROP to OP1 - OP2.
+
+ - Function: void mpz_mul (mpz_t ROP, mpz_t OP1, mpz_t OP2)
+ - Function: void mpz_mul_ui (mpz_t ROP, mpz_t OP1, unsigned long int
+ OP2)
+ Set ROP to OP1 times OP2.
+
+ Division is undefined if the divisor is zero, and passing a zero
+divisor to the divide or modulo functions, as well passing a zero mod
+argument to the `mpz_powm' and `mpz_powm_ui' functions, will make these
+functions intentionally divide by zero. This gives the user the
+possibility to handle arithmetic exceptions in these functions in the
+same manner as other arithmetic exceptions.
+
+ There are three main groups of division functions:
+ * Functions that truncate the quotient towards 0. The names of these
+ functions start with `mpz_tdiv'. The `t' in the name is short for
+ `truncate'.
+
+ * Functions that round the quotient towards -infinity. The names of
+ these routines start with `mpz_fdiv'. The `f' in the name is
+ short for `floor'.
+
+ * Functions that round the quotient towards +infinity. The names of
+ these routines start with `mpz_cdiv'. The `c' in the name is
+ short for `ceil'.
+
+ For each rounding mode, there are a couple of variants. Here `q'
+means that the quotient is computed, while `r' means that the remainder
+is computed. Functions that compute both the quotient and remainder
+have `qr' in the name.
+
+ - Function: void mpz_tdiv_q (mpz_t ROP, mpz_t OP1, mpz_t OP2)
+ - Function: void mpz_tdiv_q_ui (mpz_t ROP, mpz_t OP1, unsigned long
+ int OP2)
+ Set ROP to [OP1 / OP2]. The quotient is truncated towards 0.
+
+ - Function: void mpz_tdiv_r (mpz_t ROP, mpz_t OP1, mpz_t OP2)
+ - Function: void mpz_tdiv_r_ui (mpz_t ROP, mpz_t OP1, unsigned long
+ int OP2)
+ Set ROP to (OP1 - [OP1 / OP2] * OP2). Unless the remainder is
+ zero, it has the same sign as the dividend.
+
+ - Function: void mpz_tdiv_qr (mpz_t ROP1, mpz_t ROP2, mpz_t OP1, mpz_t
+ OP2)
+ - Function: void mpz_tdiv_qr_ui (mpz_t ROP1, mpz_t ROP2, mpz_t OP1,
+ unsigned long int OP2)
+ Divide OP1 by OP2 and put the quotient in ROP1 and the remainder
+ in ROP2. The quotient is rounded towards 0. Unless the remainder
+ is zero, it has the same sign as the dividend.
+
+ If ROP1 and ROP2 are the same variable, the results are undefined.
+
+ - Function: void mpz_fdiv_q (mpz_t ROP1, mpz_t OP1, mpz_t OP2)
+ - Function: void mpz_fdiv_q_ui (mpz_t ROP, mpz_t OP1, unsigned long
+ int OP2)
+ Set ROP to OP1 / OP2. The quotient is rounded towards -infinity.
+
+ - Function: void mpz_fdiv_r (mpz_t ROP, mpz_t OP1, mpz_t OP2)
+ - Function: unsigned long int mpz_fdiv_r_ui (mpz_t ROP, mpz_t OP1,
+ unsigned long int OP2)
+ Divide OP1 by OP2 and put the remainder in ROP. Unless the
+ remainder is zero, it has the same sign as the divisor.
+
+ For `mpz_fdiv_r_ui' the remainder is small enough to fit in an
+ `unsigned long int', and is therefore returned.
+
+ - Function: void mpz_fdiv_qr (mpz_t ROP1, mpz_t ROP2, mpz_t OP1, mpz_t
+ OP2)
+ - Function: unsigned long int mpz_fdiv_qr_ui (mpz_t ROP1, mpz_t ROP2,
+ mpz_t OP1, unsigned long int OP2)
+ Divide OP1 by OP2 and put the quotient in ROP1 and the remainder
+ in ROP2. The quotient is rounded towards -infinity. Unless the
+ remainder is zero, it has the same sign as the divisor.
+
+ For `mpz_fdiv_qr_ui' the remainder is small enough to fit in an
+ `unsigned long int', and is therefore returned.
+
+ If ROP1 and ROP2 are the same variable, the results are undefined.
+
+ - Function: unsigned long int mpz_fdiv_ui (mpz_t OP1, unsigned long
+ int OP2)
+ This function is similar to `mpz_fdiv_r_ui', but the remainder is
+ only returned; it is not stored anywhere.
+
+ - Function: void mpz_cdiv_q (mpz_t ROP1, mpz_t OP1, mpz_t OP2)
+ - Function: void mpz_cdiv_q_ui (mpz_t ROP, mpz_t OP1, unsigned long
+ int OP2)
+ Set ROP to OP1 / OP2. The quotient is rounded towards +infinity.
+
+ - Function: void mpz_cdiv_r (mpz_t ROP, mpz_t OP1, mpz_t OP2)
+ - Function: unsigned long int mpz_cdiv_r_ui (mpz_t ROP, mpz_t OP1,
+ unsigned long int OP2)
+ Divide OP1 by OP2 and put the remainder in ROP. Unless the
+ remainder is zero, it has the opposite sign as the divisor.
+
+ For `mpz_cdiv_r_ui' the negated remainder is small enough to fit
+ in an `unsigned long int', and it is therefore returned.
+
+ - Function: void mpz_cdiv_qr (mpz_t ROP1, mpz_t ROP2, mpz_t OP1, mpz_t
+ OP2)
+ - Function: unsigned long int mpz_cdiv_qr_ui (mpz_t ROP1, mpz_t ROP2,
+ mpz_t OP1, unsigned long int OP2)
+ Divide OP1 by OP2 and put the quotient in ROP1 and the remainder
+ in ROP2. The quotient is rounded towards +infinity. Unless the
+ remainder is zero, it has the opposite sign as the divisor.
+
+ For `mpz_cdiv_qr_ui' the negated remainder is small enough to fit
+ in an `unsigned long int', and it is therefore returned.
+
+ If ROP1 and ROP2 are the same variable, the results are undefined.
+
+ - Function: unsigned long int mpz_cdiv_ui (mpz_t OP1, unsigned long
+ int OP2)
+ Return the negated remainder, similar to `mpz_cdiv_r_ui'. (The
+ difference is that this function doesn't store the remainder
+ anywhere.)
+
+ - Function: void mpz_mod (mpz_t ROP, mpz_t OP1, mpz_t OP2)
+ - Function: unsigned long int mpz_mod_ui (mpz_t ROP, mpz_t OP1,
+ unsigned long int OP2)
+ Set ROP to OP1 `mod' OP2. The sign of the divisor is ignored, and
+ the result is always non-negative.
+
+ For `mpz_mod_ui' the remainder is small enough to fit in an
+ `unsigned long int', and is therefore returned.
+
+ - Function: void mpz_divexact (mpz_t ROP, mpz_t OP1, mpz_t OP2)
+ Set ROP to OP1 / OP2. This function produces correct results only
+ when it is known in advance that OP2 divides OP1.
+
+ Since mpz_divexact is much faster than any of the other routines
+ that produce the quotient (*note References::. Jebelean), it is
+ the best choice for instances in which exact division is known to
+ occur, such as reducing a rational to lowest terms.
+
+ - Function: void mpz_sqrt (mpz_t ROP, mpz_t OP)
+ Set ROP to the truncated integer part of the square root of OP.
+
+ - Function: void mpz_sqrtrem (mpz_t ROP1, mpz_t ROP2, mpz_t OP)
+ Set ROP1 to the truncated integer part of the square root of OP,
+ like `mpz_sqrt'. Set ROP2 to OP-ROP1*ROP1, (i.e., zero if OP is a
+ perfect square).
+
+ If ROP1 and ROP2 are the same variable, the results are undefined.
+
+ - Function: int mpz_perfect_square_p (mpz_t OP)
+ Return non-zero if OP is a perfect square, i.e., if the square
+ root of OP is an integer. Return zero otherwise.
+
+ - Function: int mpz_probab_prime_p (mpz_t OP, int REPS)
+ If this function returns 0, OP is definitely not prime. If it
+ returns 1, then OP is `probably' prime. The probability of a
+ false positive is (1/4)**REPS. A reasonable value of reps is 25.
+
+ An implementation of the probabilistic primality test found in
+ Seminumerical Algorithms (*note References::. Knuth).
+
+ - Function: void mpz_powm (mpz_t ROP, mpz_t BASE, mpz_t EXP, mpz_t MOD)
+ - Function: void mpz_powm_ui (mpz_t ROP, mpz_t BASE, unsigned long int
+ EXP, mpz_t MOD)
+ Set ROP to (BASE raised to EXP) `mod' MOD. If EXP is negative,
+ the result is undefined.
+
+ - Function: void mpz_pow_ui (mpz_t ROP, mpz_t BASE, unsigned long int
+ EXP)
+ - Function: void mpz_ui_pow_ui (mpz_t ROP, unsigned long int BASE,
+ unsigned long int EXP)
+ Set ROP to BASE raised to EXP.
+
+ - Function: void mpz_fac_ui (mpz_t ROP, unsigned long int OP)
+ Set ROP to OP!, the factorial of OP.
+
+ - Function: void mpz_gcd (mpz_t ROP, mpz_t OP1, mpz_t OP2)
+ Set ROP to the greatest common divisor of OP1 and OP2.
+
+ - Function: unsigned long int mpz_gcd_ui (mpz_t ROP, mpz_t OP1,
+ unsigned long int OP2)
+ Compute the greatest common divisor of OP1 and OP2. If ROP is not
+ NULL, store the result there.
+
+ If the result is small enough to fit in an `unsigned long int', it
+ is returned. If the result does not fit, 0 is returned, and the
+ result is equal to the argument OP1. Note that the result will
+ always fit if OP2 is non-zero.
+
+ - Function: void mpz_gcdext (mpz_t G, mpz_t S, mpz_t T, mpz_t A, mpz_t
+ B)
+ Compute G, S, and T, such that AS + BT = G = `gcd' (A, B). If T is
+ NULL, that argument is not computed.
+
+ - Function: int mpz_invert (mpz_t ROP, mpz_t OP1, mpz_t OP2)
+ Compute the inverse of OP1 modulo OP2 and put the result in ROP.
+ Return non-zero if an inverse exist, zero otherwise. When the
+ function returns zero, do not assume anything about the value in
+ ROP.
+
+ - Function: void mpz_neg (mpz_t ROP, mpz_t OP)
+ Set ROP to -OP.
+
+ - Function: void mpz_abs (mpz_t ROP, mpz_t OP)
+ Set ROP to the absolute value of OP.
+
+ - Function: void mpz_mul_2exp (mpz_t ROP, mpz_t OP1, unsigned long int
+ OP2)
+ Set ROP to OP1 times 2 raised to OP2. This operation can also be
+ defined as a left shift, OP2 steps.
+
+ - Function: void mpz_tdiv_q_2exp (mpz_t ROP, mpz_t OP1, unsigned long
+ int OP2)
+ Set ROP to OP1 divided by 2 raised to OP2. The quotient is
+ rounded towards 0.
+
+ - Function: void mpz_fdiv_q_2exp (mpz_t ROP, mpz_t OP1, unsigned long
+ int OP2)
+ Set ROP to OP1 divided by 2 raised to OP2. The quotient is
+ rounded towards -infinity.
+
+ - Function: void mpz_tdiv_r_2exp (mpz_t ROP, mpz_t OP1, unsigned long
+ int OP2)
+ Divide OP1 by (2 raised to OP2) and put the remainder in ROP. The
+ sign of ROP will have the same sign as OP1, unless is becomes zero.
+
+ - Function: void mpz_fdiv_r_2exp (mpz_t ROP, mpz_t OP1, unsigned long
+ int OP2)
+ Divide OP1 by (2 raised to OP2) and put the remainder in ROP. The
+ sign of ROP will always be positive.
+
+ This operation can also be defined as masking of the OP2 least
+ significant bits.
+
+
+File: gmp.info, Node: Comparison Functions, Next: Integer Logic and Bit Fiddling, Prev: Integer Arithmetic, Up: Integer Functions
+
+Comparison Functions
+====================
+
+ - Function: int mpz_cmp (mpz_t OP1, mpz_t OP2)
+ - Function: int mpz_cmp_ui (mpz_t OP1, unsigned long int OP2)
+ - Function: int mpz_cmp_si (mpz_t OP1, signed long int OP2)
+ Compare OP1 and OP2. Return a positive value if OP1 > OP2, zero
+ if OP1 = OP2, and a negative value if OP1 < OP2.
+
+ - Function: int mpz_sgn (mpz_t OP)
+ Return +1 if OP > 0, 0 if OP = 0, and -1 if OP < 0.
+
+
+File: gmp.info, Node: Integer Logic and Bit Fiddling, Next: I/O of Integers, Prev: Comparison Functions, Up: Integer Functions
+
+Logical and Bit Manipulation Functions
+======================================
+
+ These functions behave as if two's complement arithmetic were used
+(although sign-magnitude is used by the actual implementation).
+
+ - Function: void mpz_and (mpz_t ROP, mpz_t OP1, mpz_t OP2)
+ Set ROP to OP1 logical-and OP2.
+
+ - Function: void mpz_ior (mpz_t ROP, mpz_t OP1, mpz_t OP2)
+ Set ROP to OP1 inclusive-or OP2.
+
+ - Function: void mpz_com (mpz_t ROP, mpz_t OP)
+ Set ROP to the one's complement of OP.
+
+ - Function: unsigned long int mpz_popcount (mpz_t OP)
+ For non-negative numbers, return the population count of OP. For
+ negative numbers, return the largest possible value (MAX_ULONG).
+
+ - Function: unsigned long int mpz_hamdist (mpz_t OP1, mpz_t OP2)
+ If OP1 and OP2 are both non-negative, return the hamming distance
+ between the two operands. Otherwise, return the largest possible
+ value (MAX_ULONG).
+
+ It is possible to extend this function to return a useful value
+ when the operands are both negative, but the current
+ implementation returns MAX_ULONG in this case. *Do not depend on
+ this behavior, since it will change in future versions of the
+ library.*
+
+ - Function: unsigned long int mpz_scan0 (mpz_t OP, unsigned long int
+ STARTING_BIT)
+ Scan OP, starting with bit STARTING_BIT, towards more significant
+ bits, until the first clear bit is found. Return the index of the
+ found bit.
+
+ - Function: unsigned long int mpz_scan1 (mpz_t OP, unsigned long int
+ STARTING_BIT)
+ Scan OP, starting with bit STARTING_BIT, towards more significant
+ bits, until the first set bit is found. Return the index of the
+ found bit.
+
+ - Function: void mpz_setbit (mpz_t ROP, unsigned long int BIT_INDEX)
+ Set bit BIT_INDEX in OP1.
+
+ - Function: void mpz_clrbit (mpz_t ROP, unsigned long int BIT_INDEX)
+ Clear bit BIT_INDEX in OP1.
+
+
+File: gmp.info, Node: I/O of Integers, Next: Miscellaneous Integer Functions, Prev: Integer Logic and Bit Fiddling, Up: Integer Functions
+
+Input and Output Functions
+==========================
+
+ Functions that perform input from a stdio stream, and functions that
+output to a stdio stream. Passing a NULL pointer for a STREAM argument
+to any of these functions will make them read from `stdin' and write to
+`stdout', respectively.
+
+ When using any of these functions, it is a good idea to include
+`stdio.h' before `gmp.h', since that will allow `gmp.h' to define
+prototypes for these functions.
+
+ - Function: size_t mpz_out_str (FILE *STREAM, int BASE, mpz_t OP)
+ Output OP on stdio stream STREAM, as a string of digits in base
+ BASE. The base may vary from 2 to 36.
+
+ Return the number of bytes written, or if an error occurred,
+ return 0.
+
+ - Function: size_t mpz_inp_str (mpz_t ROP, FILE *STREAM, int BASE)
+ Input a possibly white-space preceded string in base BASE from
+ stdio stream STREAM, and put the read integer in ROP. The base
+ may vary from 2 to 36. If BASE is 0, the actual base is
+ determined from the leading characters: if the first two
+ characters are `0x' or `0X', hexadecimal is assumed, otherwise if
+ the first character is `0', octal is assumed, otherwise decimal is
+ assumed.
+
+ Return the number of bytes read, or if an error occurred, return 0.
+
+ - Function: size_t mpz_out_raw (FILE *STREAM, mpz_t OP)
+ Output OP on stdio stream STREAM, in raw binary format. The
+ integer is written in a portable format, with 4 bytes of size
+ information, and that many bytes of limbs. Both the size and the
+ limbs are written in decreasing significance order (i.e., in
+ big-endian).
+
+ The output can be read with `mpz_inp_raw'.
+
+ Return the number of bytes written, or if an error occurred,
+ return 0.
+
+ The output of this can not be read by `mpz_inp_raw' from GMP 1,
+ because of changes necessary for compatibility between 32-bit and
+ 64-bit machines.
+
+ - Function: size_t mpz_inp_raw (mpz_t ROP, FILE *STREAM)
+ Input from stdio stream STREAM in the format written by
+ `mpz_out_raw', and put the result in ROP. Return the number of
+ bytes read, or if an error occurred, return 0.
+
+ This routine can read the output from `mpz_out_raw' also from GMP
+ 1, in spite of changes necessary for compatibility between 32-bit
+ and 64-bit machines.
+
+
+File: gmp.info, Node: Miscellaneous Integer Functions, Prev: I/O of Integers, Up: Integer Functions
+
+Miscellaneous Functions
+=======================
+
+ - Function: void mpz_random (mpz_t ROP, mp_size_t MAX_SIZE)
+ Generate a random integer of at most MAX_SIZE limbs. The generated
+ random number doesn't satisfy any particular requirements of
+ randomness. Negative random numbers are generated when MAX_SIZE
+ is negative.
+
+ - Function: void mpz_random2 (mpz_t ROP, mp_size_t MAX_SIZE)
+ Generate a random integer of at most MAX_SIZE limbs, with long
+ strings of zeros and ones in the binary representation. Useful
+ for testing functions and algorithms, since this kind of random
+ numbers have proven to be more likely to trigger corner-case bugs.
+ Negative random numbers are generated when MAX_SIZE is negative.
+
+ - Function: size_t mpz_size (mpz_t OP)
+ Return the size of OP measured in number of limbs. If OP is zero,
+ the returned value will be zero.
+
+ *This function is obsolete. It will disappear from future MP
+ releases.*
+
+ - Function: size_t mpz_sizeinbase (mpz_t OP, int BASE)
+ Return the size of OP measured in number of digits in base BASE.
+ The base may vary from 2 to 36. The returned value will be exact
+ or 1 too big. If BASE is a power of 2, the returned value will
+ always be exact.
+
+ This function is useful in order to allocate the right amount of
+ space before converting OP to a string. The right amount of
+ allocation is normally two more than the value returned by
+ `mpz_sizeinbase' (one extra for a minus sign and one for the
+ terminating '\0').
+
+
+File: gmp.info, Node: Rational Number Functions, Next: Floating-point Functions, Prev: Integer Functions, Up: Top
+
+Rational Number Functions
+*************************
+
+ This chapter describes the MP functions for performing arithmetic on
+rational numbers. These functions start with the prefix `mpq_'.
+
+ Rational numbers are stored in objects of type `mpq_t'.
+
+ All rational arithmetic functions assume operands have a canonical
+form, and canonicalize their result. The canonical from means that the
+denominator and the numerator have no common factors, and that the
+denominator is positive. Zero has the unique representation 0/1.
+
+ Pure assignment functions do not canonicalize the assigned variable.
+It is the responsibility of the user to canonicalize the assigned
+variable before any arithmetic operations are performed on that
+variable. *Note that this is an incompatible change from version 1 of
+the library.*
+
+ - Function: void mpq_canonicalize (mpq_t OP)
+ Remove any factors that are common to the numerator and
+ denominator of OP, and make the denominator positive.
+
+* Menu:
+
+* Initializing Rationals::
+* Assigning Rationals::
+* Simultaneous Integer Init & Assign::
+* Comparing Rationals::
+* Applying Integer Functions::
+* Miscellaneous Rational Functions::
+
+
+File: gmp.info, Node: Initializing Rationals, Next: Assigning Rationals, Prev: Rational Number Functions, Up: Rational Number Functions
+
+Initialization and Assignment Functions
+=======================================
+
+ - Function: void mpq_init (mpq_t DEST_RATIONAL)
+ Initialize DEST_RATIONAL and set it to 0/1. Each variable should
+ normally only be initialized once, or at least cleared out (using
+ the function `mpq_clear') between each initialization.
+
+ - Function: void mpq_clear (mpq_t RATIONAL_NUMBER)
+ Free the space occupied by RATIONAL_NUMBER. Make sure to call this
+ function for all `mpq_t' variables when you are done with them.
+
+ - Function: void mpq_set (mpq_t ROP, mpq_t OP)
+ Assign ROP from OP.
+
+ - Function: void mpq_set_ui (mpq_t ROP, unsigned long int OP1,
+ unsigned long int OP2)
+ - Function: void mpq_set_si (mpq_t ROP, signed long int OP1, unsigned
+ long int OP2)
+ Set the value of ROP to OP1/OP2. Note that if OP1 and OP2 have
+ common factors, ROP has to be passed to `mpq_canonicalize' before
+ any operations are performed on ROP.
+
+
+File: gmp.info, Node: Assigning Rationals, Next: Comparing Rationals, Prev: Initializing Rationals, Up: Rational Number Functions
+
+Arithmetic Functions
+====================
+
+ - Function: void mpq_add (mpq_t SUM, mpq_t ADDEND1, mpq_t ADDEND2)
+ Set SUM to ADDEND1 + ADDEND2.
+
+ - Function: void mpq_sub (mpq_t DIFFERENCE, mpq_t MINUEND, mpq_t
+ SUBTRAHEND)
+ Set DIFFERENCE to MINUEND - SUBTRAHEND.
+
+ - Function: void mpq_mul (mpq_t PRODUCT, mpq_t MULTIPLIER, mpq_t
+ MULTIPLICAND)
+ Set PRODUCT to MULTIPLIER times MULTIPLICAND
+
+ - Function: void mpq_div (mpq_t QUOTIENT, mpq_t DIVIDEND, mpq_t
+ DIVISOR)
+ Set QUOTIENT to DIVIDEND / DIVISOR.
+
+ - Function: void mpq_neg (mpq_t NEGATED_OPERAND, mpq_t OPERAND)
+ Set NEGATED_OPERAND to -OPERAND.
+
+ - Function: void mpq_inv (mpq_t INVERTED_NUMBER, mpq_t NUMBER)
+ Set INVERTED_NUMBER to 1 / NUMBER. If the new denominator is
+ zero, this routine will divide by zero.
+
+
+File: gmp.info, Node: Comparing Rationals, Next: Applying Integer Functions, Prev: Assigning Rationals, Up: Rational Number Functions
+
+Comparison Functions
+====================
+
+ - Function: int mpq_cmp (mpq_t OP1, mpq_t OP2)
+ Compare OP1 and OP2. Return a positive value if OP1 > OP2, zero
+ if OP1 = OP2, and a negative value if OP1 < OP2.
+
+ To determine if two rationals are equal, `mpq_equal' is faster
+ than this `mpq_cmp'.
+
+ - Function: int mpq_cmp_ui (mpq_t OP1, unsigned long int NUM2,
+ unsigned long int DEN2)
+ Compare OP1 and NUM2/DEN2. Return a positive value if OP1 >
+ NUM2/DEN2, zero if OP1 = NUM2/DEN2, and a negative value if OP1 <
+ NUM2/DEN2.
+
+ This routine allows that NUM2 and DEN2 have common factors.
+
+ - Function: int mpq_sgn (mpq_t OP)
+ Return +1 if OP > 0, 0 if OP = 0, and -1 if OP < 0.
+
+ - Function: int mpq_equal (mpq_t OP1, mpq_t OP2)
+ Return non-zero if OP1 and OP2 are equal, zero if they are
+ non-equal. Although `mpq_cmp' can be used for the same purpose,
+ this function is much faster.
+
+
+File: gmp.info, Node: Applying Integer Functions, Next: Miscellaneous Rational Functions, Prev: Comparing Rationals, Up: Rational Number Functions
+
+Applying Integer Functions to Rationals
+=======================================
+
+ The set of `mpq' functions is quite small. In particular, there are
+no functions for either input or output. But there are two macros that
+allow us to apply any `mpz' function on the numerator or denominator of
+a rational number. If these macros are used to assign to the rational
+number, `mpq_canonicalize' normally need to be called afterwards.
+
+ - Macro: mpz_t mpq_numref (mpq_t OP)
+ - Macro: mpz_t mpq_denref (mpq_t OP)
+ Return a reference to the numerator and denominator of OP,
+ respectively. The `mpz' functions can be used on the result of
+ these macros.
+
+
+File: gmp.info, Node: Miscellaneous Rational Functions, Prev: Applying Integer Functions, Up: Rational Number Functions
+
+Miscellaneous Functions
+=======================
+
+ These functions assign between either the numerator or denominator
+of a rational, and an integer. Instead of using these functions, it is
+preferable to use the more general mechanisms `mpq_numref' and
+`mpq_denref', together with `mpz_set'.
+
+ - Function: void mpq_set_num (mpq_t RATIONAL, mpz_t NUMERATOR)
+ Copy NUMERATOR to the numerator of RATIONAL. When this risks to
+ make the numerator and denominator of RATIONAL have common
+ factors, you have to pass RATIONAL to `mpq_canonicalize' before
+ any operations are performed on RATIONAL.
+
+ This function is equivalent to `mpz_set (mpq_numref (RATIONAL),
+ NUMERATOR)'.
+
+ - Function: void mpq_set_den (mpq_t RATIONAL, mpz_t DENOMINATOR)
+ Copy DENOMINATOR to the denominator of RATIONAL. When this risks
+ to make the numerator and denominator of RATIONAL have common
+ factors, or if the denominator might be negative, you have to pass
+ RATIONAL to `mpq_canonicalize' before any operations are performed
+ on RATIONAL.
+
+ *In version 1 of the library, negative denominators were handled by
+ copying the sign to the numerator. That is no longer done.*
+
+ This function is equivalent to `mpz_set (mpq_denref (RATIONAL),
+ DENOMINATORS)'.
+
+ - Function: void mpq_get_num (mpz_t NUMERATOR, mpq_t RATIONAL)
+ Copy the numerator of RATIONAL to the integer NUMERATOR, to
+ prepare for integer operations on the numerator.
+
+ This function is equivalent to `mpz_set (NUMERATOR, mpq_numref
+ (RATIONAL))'.
+
+ - Function: void mpq_get_den (mpz_t DENOMINATOR, mpq_t RATIONAL)
+ Copy the denominator of RATIONAL to the integer DENOMINATOR, to
+ prepare for integer operations on the denominator.
+
+ This function is equivalent to `mpz_set (DENOMINATOR, mpq_denref
+ (RATIONAL))'.
+
diff --git a/gmp.info-2 b/gmp.info-2
new file mode 100644
index 000000000..54e64bb5f
--- /dev/null
+++ b/gmp.info-2
@@ -0,0 +1,1029 @@
+This is Info file gmp.info, produced by Makeinfo-1.64 from the input
+file gmp.texi.
+
+START-INFO-DIR-ENTRY
+* gmp: (gmp.info). GNU Multiple Precision Arithmetic Library.
+END-INFO-DIR-ENTRY
+
+ This file documents GNU MP, a library for arbitrary-precision
+arithmetic.
+
+ This is a draft edition of the documentation, last updated April
+1996.
+
+ Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation,
+Inc.
+
+ Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+ Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+ Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be stated in a
+translation approved by the Foundation.
+
+
+File: gmp.info, Node: Floating-point Functions, Next: Low-level Functions, Prev: Rational Number Functions, Up: Top
+
+Floating-point Functions
+************************
+
+ This is a description of the *preliminary* interface for
+floating-point arithmetic in GNU MP 2.
+
+ The floating-point functions expect arguments of type `mpf_t'.
+
+ The MP floating-point functions have an interface that is similar to
+the MP integer functions. The function prefix for floating-point
+operations is `mpf_'.
+
+ There is one significant characteristic of floating-point numbers
+that has motivated a difference between this function class and other
+MP function classes: the inherent inexactness of floating point
+arithmetic. The user has to specify the precision of each variable. A
+computation that assigns a variable will take place with the precision
+of the assigned variable; the precision of variables used as input is
+ignored.
+
+ The precision of a calculation is defined as follows: Compute the
+requested operation exactly (with "infinite precision"), and truncate
+the result to the destination variable precision. Even if the user has
+asked for a very high precision, MP will not calculate with superfluous
+digits. For example, if two low-precision numbers of nearly equal
+magnitude are added, the precision of the result will be limited to
+what is required to represent the result accurately.
+
+ The MP floating-point functions are *not* intended as a smooth
+extension to the IEEE P754 arithmetic. Specifically, the results
+obtained on one computer often differs from the results obtained on a
+computer with a different word size.
+
+* Menu:
+
+* Initializing Floats::
+* Assigning Floats::
+* Simultaneous Float Init & Assign::
+* Converting Floats::
+* Float Arithmetic::
+* Float Comparison::
+* I/O of Floats::
+* Miscellaneous Float Functions::
+
+
+File: gmp.info, Node: Initializing Floats, Next: Assigning Floats, Up: Floating-point Functions
+
+Initialization and Assignment Functions
+=======================================
+
+ - Function: void mpf_set_default_prec (unsigned long int PREC)
+ Set the default precision to be *at least* PREC bits. All
+ subsequent calls to `mpf_init' will use this precision, but
+ previously initialized variables are unaffected.
+
+ An `mpf_t' object must be initialized before storing the first value
+in it. The functions `mpf_init' and `mpf_init2' are used for that
+purpose.
+
+ - Function: void mpf_init (mpf_t X)
+ Initialize X to 0. Normally, a variable should be initialized
+ once only or at least be cleared, using `mpf_clear', between
+ initializations. The precision of X is undefined unless a default
+ precision has already been established by a call to
+ `mpf_set_default_prec'.
+
+ - Function: void mpf_init2 (mpf_t X, unsigned long int PREC)
+ Initialize X to 0 and set its precision to be *at least* PREC
+ bits. Normally, a variable should be initialized once only or at
+ least be cleared, using `mpf_clear', between initializations.
+
+ - Function: void mpf_clear (mpf_t X)
+ Free the space occupied by X. Make sure to call this function for
+ all `mpf_t' variables when you are done with them.
+
+ Here is an example on how to initialize floating-point variables:
+ {
+ mpf_t x, y;
+ mpf_init (x); /* use default precision */
+ mpf_init2 (y, 256); /* precision *at least* 256 bits */
+ ...
+ /* Unless the program is about to exit, do ... */
+ mpf_clear (x);
+ mpf_clear (y);
+ }
+
+ The following three functions are useful for changing the precision
+during a calculation. A typical use would be for adjusting the
+precision gradually in iterative algorithms like Newton-Raphson, making
+the computation precision closely match the actual accurate part of the
+numbers.
+
+ - Function: void mpf_set_prec (mpf_t ROP, unsigned long int PREC)
+ Set the precision of ROP to be *at least* PREC bits. Since
+ changing the precision involves calls to `realloc', this routine
+ should not be called in a tight loop.
+
+ - Function: unsigned long int mpf_get_prec (mpf_t OP)
+ Return the precision actually used for assignments of OP.
+
+ - Function: void mpf_set_prec_raw (mpf_t ROP, unsigned long int PREC)
+ Set the precision of ROP to be *at least* PREC bits. This is a
+ low-level function that does not change the allocation. The PREC
+ argument must not be larger that the precision previously returned
+ by `mpf_get_prec'. It is crucial that the precision of ROP is
+ ultimately reset to exactly the value returned by `mpf_get_prec'.
+
+
+File: gmp.info, Node: Assigning Floats, Next: Simultaneous Float Init & Assign, Prev: Initializing Floats, Up: Floating-point Functions
+
+Assignment Functions
+--------------------
+
+ These functions assign new values to already initialized floats
+(*note Initializing Floats::.).
+
+ - Function: void mpf_set (mpf_t ROP, mpf_t OP)
+ - Function: void mpf_set_ui (mpf_t ROP, unsigned long int OP)
+ - Function: void mpf_set_si (mpf_t ROP, signed long int OP)
+ - Function: void mpf_set_d (mpf_t ROP, double OP)
+ Set the value of ROP from OP.
+
+ - Function: int mpf_set_str (mpf_t ROP, char *STR, int BASE)
+ Set the value of ROP from the string in STR. The string is of the
+ form `M@N' or, if the base is 10 or less, alternatively `MeN'.
+ `M' is the mantissa and `N' is the exponent. The mantissa is
+ always in the specified base. The exponent is either in the
+ specified base or, if BASE is negative, in decimal.
+
+ The argument BASE may be in the ranges 2 to 36, or -36 to -2.
+ Negative values are used to specify that the exponent is in
+ decimal.
+
+ Unlike the corresponding `mpz' function, the base will not be
+ determined from the leading characters of the string if BASE is 0.
+ This is so that numbers like `0.23' are not interpreted as octal.
+
+ White space is allowed in the string, and is simply ignored.
+
+ This function returns 0 if the entire string up to the '\0' is a
+ valid number in base BASE. Otherwise it returns -1.
+
+
+File: gmp.info, Node: Simultaneous Float Init & Assign, Next: Converting Floats, Prev: Assigning Floats, Up: Floating-point Functions
+
+Combined Initialization and Assignment Functions
+------------------------------------------------
+
+ For convenience, MP provides a parallel series of initialize-and-set
+functions which initialize the output and then store the value there.
+These functions' names have the form `mpf_init_set...'
+
+ Once the float has been initialized by any of the `mpf_init_set...'
+functions, it can be used as the source or destination operand for the
+ordinary float functions. Don't use an initialize-and-set function on
+a variable already initialized!
+
+ - Function: void mpf_init_set (mpf_t ROP, mpf_t OP)
+ - Function: void mpf_init_set_ui (mpf_t ROP, unsigned long int OP)
+ - Function: void mpf_init_set_si (mpf_t ROP, signed long int OP)
+ - Function: void mpf_init_set_d (mpf_t ROP, double OP)
+ Initialize ROP and set its value from OP.
+
+ The precision of ROP will be taken from the active default
+ precision, as set by `mpf_set_default_prec'.
+
+ - Function: int mpf_init_set_str (mpf_t ROP, char *STR, int BASE)
+ Initialize ROP and set its value from the string in STR. See
+ `mpf_set_str' above for details on the assignment operation.
+
+ Note that ROP is initialized even if an error occurs. (I.e., you
+ have to call `mpf_clear' for it.)
+
+ The precision of ROP will be taken from the active default
+ precision, as set by `mpf_set_default_prec'.
+
+
+File: gmp.info, Node: Converting Floats, Next: Float Arithmetic, Prev: Simultaneous Float Init & Assign, Up: Floating-point Functions
+
+Conversion Functions
+====================
+
+ - Function: char * mpf_get_str (char *STR, mp_exp_t *EXPPTR, int BASE,
+ size_t N_DIGITS, mpf_t OP)
+ Convert OP to a string of digits in base BASE. The base may vary
+ from 2 to 36. Generate at most N_DIGITS significant digits, or if
+ N_DIGITS is 0, the maximum number of digits accurately
+ representable by OP.
+
+ If STR is NULL, space for the mantissa is allocated using the
+ default allocation function, and a pointer to the string is
+ returned.
+
+ If STR is not NULL, it should point to a block of storage enough
+ large for the mantissa, i.e., N_DIGITS + 2. The two extra bytes
+ are for a possible minus sign, and for the terminating null
+ character.
+
+ The exponent is written through the pointer EXPPTR.
+
+ If N_DIGITS is 0, the maximum number of digits meaningfully
+ achievable from the precision of OP will be generated. Note that
+ the space requirements for STR in this case will be impossible for
+ the user to predetermine. Therefore, you need to pass NULL for
+ the string argument whenever N_DIGITS is 0.
+
+ The generated string is a fraction, with an implicit radix point
+ immediately to the left of the first digit. For example, the
+ number 3.1416 would be returned as "31416" in the string and 1
+ written at EXPPTR.
+
+
+File: gmp.info, Node: Float Arithmetic, Next: Float Comparison, Prev: Converting Floats, Up: Floating-point Functions
+
+Arithmetic Functions
+====================
+
+ - Function: void mpf_add (mpf_t ROP, mpf_t OP1, mpf_t OP2)
+ - Function: void mpf_add_ui (mpf_t ROP, mpf_t OP1, unsigned long int
+ OP2)
+ Set ROP to OP1 + OP2.
+
+ - Function: void mpf_sub (mpf_t ROP, mpf_t OP1, mpf_t OP2)
+ - Function: void mpf_ui_sub (mpf_t ROP, unsigned long int OP1, mpf_t
+ OP2)
+ - Function: void mpf_sub_ui (mpf_t ROP, mpf_t OP1, unsigned long int
+ OP2)
+ Set ROP to OP1 - OP2.
+
+ - Function: void mpf_mul (mpf_t ROP, mpf_t OP1, mpf_t OP2)
+ - Function: void mpf_mul_ui (mpf_t ROP, mpf_t OP1, unsigned long int
+ OP2)
+ Set ROP to OP1 times OP2.
+
+ Division is undefined if the divisor is zero, and passing a zero
+divisor to the divide functions will make these functions intentionally
+divide by zero. This gives the user the possibility to handle
+arithmetic exceptions in these functions in the same manner as other
+arithmetic exceptions.
+
+ - Function: void mpf_div (mpf_t ROP, mpf_t OP1, mpf_t OP2)
+ - Function: void mpf_ui_div (mpf_t ROP, unsigned long int OP1, mpf_t
+ OP2)
+ - Function: void mpf_div_ui (mpf_t ROP, mpf_t OP1, unsigned long int
+ OP2)
+ Set ROP to OP1 / OP2. rounded towards 0.
+
+ - Function: void mpf_sqrt (mpf_t ROP, mpf_t OP)
+ - Function: void mpf_sqrt_ui (mpf_t ROP, unsigned long int OP)
+ Set ROP to the square root of OP.
+
+ - Function: void mpf_pow_ui (mpf_t ROP, mpf_t OP1, unsigned long int
+ OP2)
+ Set ROP to OP1 raised to OP2.
+
+ - Function: void mpf_neg (mpf_t ROP, mpf_t OP)
+ Set ROP to -OP.
+
+ - Function: void mpf_abs (mpf_t ROP, mpf_t OP)
+ Set ROP to the absolute value of OP.
+
+ - Function: void mpf_mul_2exp (mpf_t ROP, mpf_t OP1, unsigned long int
+ OP2)
+ Set ROP to OP1 times 2 raised to OP2.
+
+ - Function: void mpf_div_2exp (mpf_t ROP, mpf_t OP1, unsigned long int
+ OP2)
+ Set ROP to OP1 divided by 2 raised to OP2.
+
+
+File: gmp.info, Node: Float Comparison, Next: I/O of Floats, Prev: Float Arithmetic, Up: Floating-point Functions
+
+Comparison Functions
+====================
+
+ - Function: int mpf_cmp (mpf_t OP1, mpf_t OP2)
+ - Function: int mpf_cmp_ui (mpf_t OP1, unsigned long int OP2)
+ - Function: int mpf_cmp_si (mpf_t OP1, signed long int OP2)
+ Compare OP1 and OP2. Return a positive value if OP1 > OP2, zero
+ if OP1 = OP2, and a negative value if OP1 < OP2.
+
+ - Function: int mpf_eq (mpf_t OP1, mpf_t OP2, unsigned long int op3)
+ Return non-zero if the first OP3 bits of OP1 and OP2 are equal,
+ zero otherwise. I.e., test of OP1 and OP2 are approximately equal.
+
+ - Function: void mpf_reldiff (mpf_t ROP, mpf_t OP1, mpf_t OP2)
+ Compute the relative difference between OP1 and OP2 and store the
+ result in ROP.
+
+ - Function: int mpf_sgn (mpf_t OP)
+ Return +1 if OP > 0, 0 if OP = 0, and -1 if OP < 0.
+
+
+File: gmp.info, Node: I/O of Floats, Next: Miscellaneous Float Functions, Prev: Float Comparison, Up: Floating-point Functions
+
+Input and Output Functions
+==========================
+
+ Functions that perform input from a stdio stream, and functions that
+output to a stdio stream. Passing a NULL pointer for a STREAM argument
+to any of these functions will make them read from `stdin' and write to
+`stdout', respectively.
+
+ When using any of these functions, it is a good idea to include
+`stdio.h' before `gmp.h', since that will allow `gmp.h' to define
+prototypes for these functions.
+
+ - Function: size_t mpf_out_str (FILE *STREAM, int BASE, size_t
+ N_DIGITS, mpf_t OP)
+ Output OP on stdio stream STREAM, as a string of digits in base
+ BASE. The base may vary from 2 to 36. Print at most N_DIGITS
+ significant digits, or if N_DIGITS is 0, the maximum number of
+ digits accurately representable by OP.
+
+ In addition to the significant digits, a leading `0.' and a
+ trailing exponent, in the form `@NNN', are printed.
+
+ Return the number of bytes written, or if an error occurred,
+ return 0.
+
+ - Function: size_t mpf_inp_str (mpf_t ROP, FILE *STREAM, int BASE)
+ Input a string in base BASE from stdio stream STREAM, and put the
+ read float in ROP. The string is of the form `M@N' or, if the
+ base is 10 or less, alternatively `MeN'. `M' is the mantissa and
+ `N' is the exponent. The mantissa is always in the specified
+ base. The exponent is either in the specified base or, if BASE is
+ negative, in decimal.
+
+ The argument BASE may be in the ranges 2 to 36, or -36 to -2.
+ Negative values are used to specify that the exponent is in
+ decimal.
+
+ Unlike the corresponding `mpz' function, the base will not be
+ determined from the leading characters of the string if BASE is 0.
+ This is so that numbers like `0.23' are not interpreted as octal.
+
+ Return the number of bytes read, or if an error occurred, return 0.
+
+
+File: gmp.info, Node: Miscellaneous Float Functions, Prev: I/O of Floats, Up: Floating-point Functions
+
+Miscellaneous Functions
+=======================
+
+ - Function: void mpf_random2 (mpf_t ROP, mp_size_t MAX_SIZE, mp_exp_t
+ MAX_EXP)
+ Generate a random float of at most MAX_SIZE limbs, with long
+ strings of zeros and ones in the binary representation. The
+ exponent of the number is in the interval -EXP to EXP. This
+ function is useful for testing functions and algorithms, since
+ this kind of random numbers have proven to be more likely to
+ trigger corner-case bugs. Negative random numbers are generated
+ when MAX_SIZE is negative.
+
+
+File: gmp.info, Node: Low-level Functions, Next: BSD Compatible Functions, Prev: Floating-point Functions, Up: Top
+
+Low-level Functions
+*******************
+
+ This chapter describes low-level MP functions, used to implement the
+high-level MP functions, but also intended for time-critical user code.
+
+ These functions start with the prefix `mpn_'.
+
+ The `mpn' functions are designed to be as fast as possible, *not* to
+provide a coherent calling interface. The different functions have
+somewhat similar interfaces, but there are variations that make them
+hard to use. These functions do as little as possible apart from the
+real multiple precision computation, so that no time is spent on things
+that not all callers need.
+
+ A source operand is specified by a pointer to the least significant
+limb and a limb count. A destination operand is specified by just a
+pointer. It is the responsibility of the caller to ensure that the
+destination has enough space for storing the result.
+
+ With this way of specifying operands, it is possible to perform
+computations on subranges of an argument, and store the result into a
+subrange of a destination.
+
+ A common requirement for all functions is that each source area
+needs at least one limb. No size argument may be zero.
+
+ The `mpn' functions is the base for the implementation of the `mpz_',
+`mpf_', and `mpq_' functions.
+
+ This example adds the number beginning at SRC1_PTR and the number
+beginning at SRC2_PTR and writes the sum at DEST_PTR. All areas have
+SIZE limbs.
+
+ cy = mpn_add_n (dest_ptr, src1_ptr, src2_ptr, size)
+
+In the notation used here, a source operand is identified by the
+pointer to the least significant limb, and the limb count in braces.
+For example, {s1_ptr, s1_size}.
+
+ - Function: mp_limb_t mpn_add_n (mp_limb_t * DEST_PTR, const mp_limb_t
+ * SRC1_PTR, const mp_limb_t * SRC2_PTR, mp_size_t SIZE)
+ Add {SRC1_PTR, SIZE} and {SRC2_PTR, SIZE}, and write the SIZE
+ least significant limbs of the result to DEST_PTR. Return carry,
+ either 0 or 1.
+
+ This is the lowest-level function for addition. It is the
+ preferred function for addition, since it is written in assembly
+ for most targets. For addition of a variable to itself (i.e.,
+ SRC1_PTR equals SRC2_PTR, use `mpn_lshift' with a count of 1 for
+ optimal speed.
+
+ - Function: mp_limb_t mpn_add_1 (mp_limb_t * DEST_PTR, const mp_limb_t
+ * SRC1_PTR, mp_size_t SIZE, mp_limb_t SRC2_LIMB)
+ Add {SRC1_PTR, SIZE} and SRC2_LIMB, and write the SIZE least
+ significant limbs of the result to DEST_PTR. Return carry, either
+ 0 or 1.
+
+ - Function: mp_limb_t mpn_add (mp_limb_t * DEST_PTR, const mp_limb_t *
+ SRC1_PTR, mp_size_t SRC1_SIZE, const mp_limb_t * SRC2_PTR,
+ mp_size_t SRC2_SIZE)
+ Add {SRC1_PTR, SRC1_SIZE} and {SRC2_PTR, SRC2_SIZE}, and write the
+ SRC1_SIZE least significant limbs of the result to DEST_PTR.
+ Return carry, either 0 or 1.
+
+ This function requires that SRC1_SIZE is greater than or equal to
+ SRC2_SIZE.
+
+ - Function: mp_limb_t mpn_sub_n (mp_limb_t * DEST_PTR, const mp_limb_t
+ * SRC1_PTR, const mp_limb_t * SRC2_PTR, mp_size_t SIZE)
+ Subtract {SRC2_PTR, SRC2_SIZE} from {SRC1_PTR, SIZE}, and write
+ the SIZE least significant limbs of the result to DEST_PTR.
+ Return borrow, either 0 or 1.
+
+ This is the lowest-level function for subtraction. It is the
+ preferred function for subtraction, since it is written in
+ assembly for most targets.
+
+ - Function: mp_limb_t mpn_sub_1 (mp_limb_t * DEST_PTR, const mp_limb_t
+ * SRC1_PTR, mp_size_t SIZE, mp_limb_t SRC2_LIMB)
+ Subtract SRC2_LIMB from {SRC1_PTR, SIZE}, and write the SIZE least
+ significant limbs of the result to DEST_PTR. Return borrow,
+ either 0 or 1.
+
+ - Function: mp_limb_t mpn_sub (mp_limb_t * DEST_PTR, const mp_limb_t *
+ SRC1_PTR, mp_size_t SRC1_SIZE, const mp_limb_t * SRC2_PTR,
+ mp_size_t SRC2_SIZE)
+ Subtract {SRC2_PTR, SRC2_SIZE} from {SRC1_PTR, SRC1_SIZE}, and
+ write the SRC1_SIZE least significant limbs of the result to
+ DEST_PTR. Return borrow, either 0 or 1.
+
+ This function requires that SRC1_SIZE is greater than or equal to
+ SRC2_SIZE.
+
+ - Function: void mpn_mul_n (mp_limb_t * DEST_PTR, const mp_limb_t *
+ SRC1_PTR, const mp_limb_t * SRC2_PTR, mp_size_t SIZE)
+ Multiply {SRC1_PTR, SIZE} and {SRC2_PTR, SIZE}, and write the
+ *entire* result to DEST_PTR.
+
+ The destination has to have space for 2SIZE limbs, even if the
+ significant result might be one limb smaller.
+
+ - Function: mp_limb_t mpn_mul_1 (mp_limb_t * DEST_PTR, const mp_limb_t
+ * SRC1_PTR, mp_size_t SIZE, mp_limb_t SRC2_LIMB)
+ Multiply {SRC1_PTR, SIZE} and SRC2_LIMB, and write the SIZE least
+ significant limbs of the product to DEST_PTR. Return the most
+ significant limb of the product.
+
+ This is a low-level function that is a building block for general
+ multiplication as well as other operations in MP. It is written
+ in assembly for most targets.
+
+ Don't call this function if SRC2_LIMB is a power of 2; use
+ `mpn_lshift' with a count equal to the logarithm of SRC2_LIMB
+ instead, for optimal speed.
+
+ - Function: mp_limb_t mpn_addmul_1 (mp_limb_t * DEST_PTR, const
+ mp_limb_t * SRC1_PTR, mp_size_t SIZE, mp_limb_t SRC2_LIMB)
+ Multiply {SRC1_PTR, SIZE} and SRC2_LIMB, and add the SIZE least
+ significant limbs of the product to {DEST_PTR, SIZE} and write the
+ result to DEST_PTR DEST_PTR. Return the most significant limb of
+ the product, plus carry-out from the addition.
+
+ This is a low-level function that is a building block for general
+ multiplication as well as other operations in MP. It is written
+ in assembly for most targets.
+
+ - Function: mp_limb_t mpn_submul_1 (mp_limb_t * DEST_PTR, const
+ mp_limb_t * SRC1_PTR, mp_size_t SIZE, mp_limb_t SRC2_LIMB)
+ Multiply {SRC1_PTR, SIZE} and SRC2_LIMB, and subtract the SIZE
+ least significant limbs of the product from {DEST_PTR, SIZE} and
+ write the result to DEST_PTR. Return the most significant limb of
+ the product, minus borrow-out from the subtraction.
+
+ This is a low-level function that is a building block for general
+ multiplication and division as well as other operations in MP. It
+ is written in assembly for most targets.
+
+ - Function: mp_limb_t mpn_mul (mp_limb_t * DEST_PTR, const mp_limb_t *
+ SRC1_PTR, mp_size_t SRC1_SIZE, const mp_limb_t * SRC2_PTR,
+ mp_size_t SRC2_SIZE)
+ Multiply {SRC1_PTR, SRC1_SIZE} and {SRC2_PTR, SRC2_SIZE}, and
+ write the result to DEST_PTR. Return the most significant limb of
+ the result.
+
+ The destination has to have space for SRC1_SIZE + SRC1_SIZE limbs,
+ even if the result might be one limb smaller.
+
+ This function requires that SRC1_SIZE is greater than or equal to
+ SRC2_SIZE. The destination must be distinct from either input
+ operands.
+
+ - Function: mp_size_t mpn_divrem (mp_limb_t * R1P, mp_size_t XSIZE,
+ mp_limb_t * RS2P, mp_size_t RS2SIZE, const mp_limb_t * S3P,
+ mp_size_t S3SIZE)
+ Divide {RS2P, RS2SIZE} by {S3P, S3SIZE}, and write the quotient at
+ R1P, with the exception of the most significant limb, which is
+ returned. The remainder replaces the dividend at RS2P.
+
+ In addition to an integer quotient, XSIZE fraction limbs are
+ developed, and stored after the integral limbs. For most usages,
+ XSIZE will be zero.
+
+ It is required that RS2SIZE is greater than or equal to S3SIZE.
+ It is required that the most significant bit of the divisor is set.
+
+ If the quotient is not needed, pass RS2P + S3SIZE as R1P. Aside
+ from that special case, no overlap between arguments is permitted.
+
+ Return the most significant limb of the quotient, either 0 or 1.
+
+ The area at R1P needs to be RS2SIZE - S3SIZE + XSIZE limbs large.
+
+ - Function: mp_limb_t mpn_divrem_1 (mp_limb_t * R1P, mp_size_t XSIZE,
+ mp_limb_t * S2P, mp_size_t S2SIZE, mp_limb_t S3LIMB)
+ Divide {S2P, S2SIZE} by S3LIMB, and write the quotient at R1P.
+ Return the remainder.
+
+ In addition to an integer quotient, XSIZE fraction limbs are
+ developed, and stored after the integral limbs. For most usages,
+ XSIZE will be zero.
+
+ The areas at R1P and S2P have to be identical or completely
+ separate, not partially overlapping.
+
+ - Function: mp_size_t mpn_divmod (mp_limb_t * R1P, mp_limb_t * RS2P,
+ mp_size_t RS2SIZE, const mp_limb_t * S3P, mp_size_t S3SIZE)
+ *This interface is obsolete. It will disappear from future
+ releases. Use `mpn_divrem' in its stead.*
+
+ - Function: mp_limb_t mpn_divmod_1 (mp_limb_t * R1P, mp_limb_t * S2P,
+ mp_size_t S2SIZE, mp_limb_t S3LIMB)
+ *This interface is obsolete. It will disappear from future
+ releases. Use `mpn_divrem_1' in its stead.*
+
+ - Function: mp_limb_t mpn_mod_1 (mp_limb_t * S1P, mp_size_t S1SIZE,
+ mp_limb_t S2LIMB)
+ Divide {S1P, S1SIZE} by S2LIMB, and return the remainder.
+
+ - Function: mp_limb_t mpn_pre_mod_1 (mp_limb_t * S1P, mp_size_t
+ S1SIZE, mp_limb_t S2LIMB, mp_limb_t S3LIMB)
+ *This interface is obsolete. It will disappear from future
+ releases. Use `mpn_mod_1' in its stead.*
+
+ - Function: mp_limb_t mpn_bdivmod (mp_limb_t * DEST_PTR, mp_limb_t *
+ S1P, mp_size_t S1SIZE, const mp_limb_t * S2P, mp_size_t
+ S2SIZE, unsigned long int D)
+ The function puts the low [D / BITS_PER_MP_LIMB] limbs of Q =
+ {S1P, S1SIZE} / {S2P, S2SIZE} mod 2^D at DEST_PTR, and returns the
+ high D mod BITS_PER_MP_LIMB bits of Q.
+
+ {S1P, S1SIZE} - Q * {S2P, S2SIZE} mod 2^(S1SIZE*BITS_PER_MP_LIMB)
+ is placed at S1P. Since the low [D / BITS_PER_MP_LIMB] limbs of
+ this difference are zero, it is possible to overwrite the low
+ limbs at S1P with this difference, provided DEST_PTR <= S1P.
+
+ This function requires that S1SIZE * BITS_PER_MP_LIMB >= D, and
+ that {S2P, S2SIZE} is odd.
+
+ *This interface is preliminary. It might change incompatibly in
+ future revisions.*
+
+ - Function: mp_limb_t mpn_lshift (mp_limb_t * DEST_PTR, const
+ mp_limb_t * SRC_PTR, mp_size_t SRC_SIZE, unsigned long int
+ COUNT)
+ Shift {SRC_PTR, SRC_SIZE} COUNT bits to the left, and write the
+ SRC_SIZE least significant limbs of the result to DEST_PTR. COUNT
+ might be in the range 1 to n - 1, on an n-bit machine. The bits
+ shifted out to the left are returned.
+
+ Overlapping of the destination space and the source space is
+ allowed in this function, provided DEST_PTR >= SRC_PTR.
+
+ This function is written in assembly for most targets.
+
+ - Function: mp_limp_t mpn_rshift (mp_limb_t * DEST_PTR, const
+ mp_limb_t * SRC_PTR, mp_size_t SRC_SIZE, unsigned long int
+ COUNT)
+ Shift {SRC_PTR, SRC_SIZE} COUNT bits to the right, and write the
+ SRC_SIZE most significant limbs of the result to DEST_PTR. COUNT
+ might be in the range 1 to n - 1, on an n-bit machine. The bits
+ shifted out to the right are returned.
+
+ Overlapping of the destination space and the source space is
+ allowed in this function, provided DEST_PTR <= SRC_PTR.
+
+ This function is written in assembly for most targets.
+
+ - Function: int mpn_cmp (const mp_limb_t * SRC1_PTR, const mp_limb_t *
+ SRC2_PTR, mp_size_t SIZE)
+ Compare {SRC1_PTR, SIZE} and {SRC2_PTR, SIZE} and return a
+ positive value if src1 > src2, 0 of they are equal, and a negative
+ value if src1 < src2.
+
+ - Function: mp_size_t mpn_gcd (mp_limb_t * DEST_PTR, mp_limb_t *
+ SRC1_PTR, mp_size_t SRC1_SIZE, mp_limb_t * SRC2_PTR,
+ mp_size_t SRC2_SIZE)
+ Puts at DEST_PTR the greatest common divisor of {SRC1_PTR,
+ SRC1_SIZE} and {SRC2_PTR, SRC2_SIZE}; both source operands are
+ destroyed by the operation. The size in limbs of the greatest
+ common divisor is returned.
+
+ {SRC1_PTR, SRC1_SIZE} must be odd, and {SRC2_PTR, SRC2_SIZE} must
+ have at least as many bits as {SRC1_PTR, SRC1_SIZE}.
+
+ *This interface is preliminary. It might change incompatibly in
+ future revisions.*
+
+ - Function: mp_limb_t mpn_gcd_1 (const mp_limb_t * SRC1_PTR, mp_size_t
+ SRC1_SIZE, mp_limb_t SRC2_LIMB)
+ Return the greatest common divisor of {SRC1_PTR, SRC1_SIZE} and
+ SRC2_LIMB, where SRC2_LIMB (as well as SRC1_SIZE) must be
+ different from 0.
+
+ - Function: mp_size_t mpn_gcdext (mp_limb_t * R1P, mp_limb_t * R2P,
+ mp_limb_t * S1P, mp_size_t S1SIZE, mp_limb_t * S2P, mp_size_t
+ S2SIZE)
+ Puts at R1P the greatest common divisor of {S1P, S1SIZE} and {S2P,
+ S2SIZE}. The first cofactor is written at R2P. Both source
+ operands are destroyed by the operation. The size in limbs of the
+ greatest common divisor is returned.
+
+ *This interface is preliminary. It might change incompatibly in
+ future revisions.*
+
+ - Function: mp_size_t mpn_sqrtrem (mp_limb_t * R1P, mp_limb_t * R2P,
+ const mp_limb_t * SP, mp_size_t SIZE)
+ Compute the square root of {SP, SIZE} and put the result at R1P.
+ Write the remainder at R2P, unless R2P is NULL.
+
+ Return the size of the remainder, whether R2P was NULL or non-NULL.
+ Iff the operand was a perfect square, the return value will be 0.
+
+ The areas at R1P and SP have to be distinct. The areas at R2P and
+ SP have to be identical or completely separate, not partially
+ overlapping.
+
+ The area at R1P needs to be SIZE / 2 limbs large. The area at R2P
+ needs to be SIZE limbs large.
+
+ *This interface is preliminary. It might change incompatibly in
+ future revisions.*
+
+ - Function: mp_size_t mpn_get_str (unsigned char *STR, int BASE,
+ mp_limb_t * S1P, mp_size_t S1SIZE)
+ Convert {S1P, S1SIZE} to a raw unsigned char array in base BASE.
+ The string is not in ASCII; to convert it to printable format, add
+ the ASCII codes for `0' or `A', depending on the base and range.
+ There may be leading zeros in the string.
+
+ The area at S1P is clobbered.
+
+ Return the number of characters in STR.
+
+ The area at STR has to have space for the largest possible number
+ represented by a S1SIZE long limb array, plus one extra character.
+
+ - Function: mp_size_t mpn_set_str (mp_limb_t * R1P, const char *STR,
+ size_t strsize, int BASE)
+ Convert the raw unsigned char array at STR of length STRSIZE to a
+ limb array {S1P, S1SIZE}. The base of STR is BASE.
+
+ Return the number of limbs stored in R1P.
+
+ - Function: unsigned long int mpn_scan0 (const mp_limb_t * S1P,
+ unsigned long int BIT)
+ Scan S1P from bit position BIT for the next clear bit.
+
+ It is required that there be a clear bit within the area at S1P at
+ or beyond bit position BIT, so that the function has something to
+ return.
+
+ *This interface is preliminary. It might change incompatibly in
+ future revisions.*
+
+ - Function: unsigned long int mpn_scan1 (const mp_limb_t * S1P,
+ unsigned long int BIT)
+ Scan S1P from bit position BIT for the next set bit.
+
+ It is required that there be a set bit within the area at S1P at or
+ beyond bit position BIT, so that the function has something to
+ return.
+
+ *This interface is preliminary. It might change incompatibly in
+ future revisions.*
+
+ - Function: void mpn_random2 (mp_limb_t * R1P, mp_size_t R1SIZE)
+ Generate a random number of length R1SIZE with long strings of
+ zeros and ones in the binary representation, and store it at R1P.
+
+ The generated random numbers are intended for testing the
+ correctness of the implementation of the `mpn' routines.
+
+ - Function: unsigned long int mpn_popcount (const mp_limb_t * S1P,
+ unsigned long int SIZE)
+ Count the number of set bits in {S1P, SIZE}.
+
+ - Function: unsigned long int mpn_hamdist (const mp_limb_t * S1P,
+ const mp_limb_t * S2P, unsigned long int SIZE)
+ Compute the hamming distance between {S1P, SIZE} and {S2P, SIZE}.
+
+ - Function: int mpn_perfect_square_p (const mp_limb_t * S1P, mp_size_t
+ SIZE)
+ Return non-zero iff {S1P, SIZE} is a perfect square.
+
+
+File: gmp.info, Node: BSD Compatible Functions, Next: Custom Allocation, Prev: Low-level Functions, Up: Top
+
+Berkeley MP Compatible Functions
+********************************
+
+ These functions are intended to be fully compatible with the
+Berkeley MP library which is available on many BSD derived U*ix systems.
+
+ The original Berkeley MP library has a usage restriction: you cannot
+use the same variable as both source and destination in a single
+function call. The compatible functions in GNU MP do not share this
+restriction--inputs and outputs may overlap.
+
+ It is not recommended that new programs are written using these
+functions. Apart from the incomplete set of functions, the interface
+for initializing `MINT' objects is more error prone, and the `pow'
+function collides with `pow' in `libm.a'.
+
+ Include the header `mp.h' to get the definition of the necessary
+types and functions. If you are on a BSD derived system, make sure to
+include GNU `mp.h' if you are going to link the GNU `libmp.a' to you
+program. This means that you probably need to give the -I<dir> option
+to the compiler, where <dir> is the directory where you have GNU `mp.h'.
+
+ - Function: MINT * itom (signed short int INITIAL_VALUE)
+ Allocate an integer consisting of a `MINT' object and dynamic limb
+ space. Initialize the integer to INITIAL_VALUE. Return a pointer
+ to the `MINT' object.
+
+ - Function: MINT * xtom (char *INITIAL_VALUE)
+ Allocate an integer consisting of a `MINT' object and dynamic limb
+ space. Initialize the integer from INITIAL_VALUE, a hexadecimal,
+ '\0'-terminate C string. Return a pointer to the `MINT' object.
+
+ - Function: void move (MINT *SRC, MINT *DEST)
+ Set DEST to SRC by copying. Both variables must be previously
+ initialized.
+
+ - Function: void madd (MINT *SRC_1, MINT *SRC_2, MINT *DESTINATION)
+ Add SRC_1 and SRC_2 and put the sum in DESTINATION.
+
+ - Function: void msub (MINT *SRC_1, MINT *SRC_2, MINT *DESTINATION)
+ Subtract SRC_2 from SRC_1 and put the difference in DESTINATION.
+
+ - Function: void mult (MINT *SRC_1, MINT *SRC_2, MINT *DESTINATION)
+ Multiply SRC_1 and SRC_2 and put the product in DESTINATION.
+
+ - Function: void mdiv (MINT *DIVIDEND, MINT *DIVISOR, MINT *QUOTIENT,
+ MINT *REMAINDER)
+ - Function: void sdiv (MINT *DIVIDEND, signed short int DIVISOR, MINT
+ *QUOTIENT, signed short int *REMAINDER)
+ Set QUOTIENT to DIVIDEND / DIVISOR, and REMAINDER to DIVIDEND mod
+ DIVISOR. The quotient is rounded towards zero; the remainder has
+ the same sign as the dividend unless it is zero.
+
+ Some implementations of these functions work differently--or not
+ at all--for negative arguments.
+
+ - Function: void msqrt (MINT *OPERAND, MINT *ROOT, MINT *REMAINDER)
+ Set ROOT to the truncated integer part of the square root of
+ OPERAND. Set REMAINDER to OPERAND-ROOT*ROOT, (i.e., zero if
+ OPERAND is a perfect square).
+
+ If ROOT and REMAINDER are the same variable, the results are
+ undefined.
+
+ - Function: void pow (MINT *BASE, MINT *EXP, MINT *MOD, MINT *DEST)
+ Set DEST to (BASE raised to EXP) modulo MOD.
+
+ - Function: void rpow (MINT *BASE, signed short int EXP, MINT *DEST)
+ Set DEST to BASE raised to EXP.
+
+ - Function: void gcd (MINT *OPERAND1, MINT *OPERAND2, MINT *RES)
+ Set RES to the greatest common divisor of OPERAND1 and OPERAND2.
+
+ - Function: int mcmp (MINT *OPERAND1, MINT *OPERAND2)
+ Compare OPERAND1 and OPERAND2. Return a positive value if
+ OPERAND1 > OPERAND2, zero if OPERAND1 = OPERAND2, and a negative
+ value if OPERAND1 < OPERAND2.
+
+ - Function: void min (MINT *DEST)
+ Input a decimal string from `stdin', and put the read integer in
+ DEST. SPC and TAB are allowed in the number string, and are
+ ignored.
+
+ - Function: void mout (MINT *SRC)
+ Output SRC to `stdout', as a decimal string. Also output a
+ newline.
+
+ - Function: char * mtox (MINT *OPERAND)
+ Convert OPERAND to a hexadecimal string, and return a pointer to
+ the string. The returned string is allocated using the default
+ memory allocation function, `malloc' by default.
+
+ - Function: void mfree (MINT *OPERAND)
+ De-allocate, the space used by OPERAND. *This function should
+ only be passed a value returned by `itom' or `xtom'.*
+
+
+File: gmp.info, Node: Custom Allocation, Next: Contributors, Prev: BSD Compatible Functions, Up: Top
+
+Custom Allocation
+*****************
+
+ By default, the MP functions use `malloc', `realloc', and `free' for
+memory allocation. If `malloc' or `realloc' fails, the MP library
+terminates execution after printing a fatal error message to standard
+error.
+
+ For some applications, you may wish to allocate memory in other
+ways, or you may not want to have a fatal error when there is no more
+memory available. To accomplish this, you can specify alternative
+memory allocation functions.
+
+ - Function: void mp_set_memory_functions (
+ void *(*ALLOC_FUNC_PTR) (size_t),
+ void *(*REALLOC_FUNC_PTR) (void *, size_t, size_t),
+ void (*FREE_FUNC_PTR) (void *, size_t))
+ Replace the current allocation functions from the arguments. If
+ an argument is NULL, the corresponding default function is
+ retained.
+
+ *Make sure to call this function in such a way that there are no
+ active MP objects that were allocated using the previously active
+ allocation function! Usually, that means that you have to call
+ this function before any other MP function.*
+
+ The functions you supply should fit the following declarations:
+
+ - Function: void * allocate_function (size_t ALLOC_SIZE)
+ This function should return a pointer to newly allocated space
+ with at least ALLOC_SIZE storage units.
+
+ - Function: void * reallocate_function (void *PTR, size_t OLD_SIZE,
+ size_t NEW_SIZE)
+ This function should return a pointer to newly allocated space of
+ at least NEW_SIZE storage units, after copying at least the first
+ OLD_SIZE storage units from PTR. It should also de-allocate the
+ space at PTR.
+
+ You can assume that the space at PTR was formerly returned from
+ `allocate_function' or `reallocate_function', for a request for
+ OLD_SIZE storage units.
+
+ - Function: void deallocate_function (void *PTR, size_t SIZE)
+ De-allocate the space pointed to by PTR.
+
+ You can assume that the space at PTR was formerly returned from
+ `allocate_function' or `reallocate_function', for a request for
+ SIZE storage units.
+
+ (A "storage unit" is the unit in which the `sizeof' operator returns
+the size of an object, normally an 8 bit byte.)
+
+
+File: gmp.info, Node: Contributors, Next: References, Prev: Custom Allocation, Up: Top
+
+Contributors
+************
+
+ I would like to thank Gunnar Sjoedin and Hans Riesel for their help
+with mathematical problems, Richard Stallman for his help with design
+issues and for revising the first version of this manual, Brian Beuning
+and Doug Lea for their testing of early versions of the library.
+
+ John Amanatides of York University in Canada contributed the function
+`mpz_probab_prime_p'.
+
+ Ken Weber (Kent State University, Universidade Federal do Rio Grande
+do Sul) contributed `mpz_gcd', `mpz_divexact', `mpn_gcd', and
+`mpn_bdivmod', partially supported by CNPq (Brazil) grant 301314194-2.
+
+ Per Bothner of Cygnus Support helped to set up MP to use Cygnus'
+configure. He has also made valuable suggestions and tested numerous
+intermediary releases.
+
+ Joachim Hollman was involved in the design of the `mpf' interface,
+and in the `mpz' design revisions for version 2.
+
+ Bennet Yee contributed the functions `mpz_jacobi' and `mpz_legendre'.
+
+ Andreas Schwab contributed the files `m68k/lshift.S' and
+`m68k/rshift.S'.
+
+ The development of floating point functions of GNU MP 2, were
+supported in part by the ESPRIT-BRA (Basic Research Activities) 6846
+project POSSO (POlynomial System SOlving).
+
+ GNU MP 2 was finished and released by TMG Datakonsult,
+Sodermannagatan 5, 116 23 STOCKHOLM, SWEDEN, in cooperation with the
+IDA Center for Computing Sciences, USA.
+
+
+File: gmp.info, Node: References, Prev: Contributors, Up: Top
+
+References
+**********
+
+ * Donald E. Knuth, "The Art of Computer Programming", vol 2,
+ "Seminumerical Algorithms", 2nd edition, Addison-Wesley, 1981.
+
+ * John D. Lipson, "Elements of Algebra and Algebraic Computing", The
+ Benjamin Cummings Publishing Company Inc, 1981.
+
+ * Richard M. Stallman, "Using and Porting GCC", Free Software
+ Foundation, 1995.
+
+ * Peter L. Montgomery, "Modular Multiplication Without Trial
+ Division", in Mathematics of Computation, volume 44, number 170,
+ April 1985.
+
+ * Torbjorn Granlund and Peter L. Montgomery, "Division by Invariant
+ Integers using Multiplication", in Proceedings of the SIGPLAN
+ PLDI'94 Conference, June 1994.
+
+ * Tudor Jebelean, "An algorithm for exact division", Journal of
+ Symbolic Computation, v. 15, 1993, pp. 169-180.
+
+ * Kenneth Weber, "The accelerated integer GCD algorithm", ACM
+ Transactions on Mathematical Software, v. 21 (March), 1995, pp.
+ 111-122.
+
+
+File: gmp.info, Node: Concept Index, Up: Top
+
+Concept Index
+*************
+
+* Menu:
+
+* gmp.h: MP Basics.
+* mp.h: BSD Compatible Functions.
+* Arithmetic functions <1>: Float Arithmetic.
+* Arithmetic functions: Integer Arithmetic.
+* Bit manipulation functions: Integer Logic and Bit Fiddling.
+* BSD MP compatible functions: BSD Compatible Functions.
+* Comparison functions: Float Comparison.
+* Conditions for copying GNU MP: Copying.
+* Conversion functions <1>: Converting Integers.
+* Conversion functions: Converting Floats.
+* Copying conditions: Copying.
+* Float arithmetic functions: Float Arithmetic.
+* Float assignment functions: Assigning Floats.
+* Float comparisons functions: Float Comparison.
+* Float functions: Floating-point Functions.
+* Float input and output functions: I/O of Floats.
+* Floating-point functions: Floating-point Functions.
+* Floating-point number: MP Basics.
+* I/O functions <1>: I/O of Floats.
+* I/O functions: I/O of Integers.
+* Initialization and assignment functions <1>: Simultaneous Float Init & Assign.
+* Initialization and assignment functions: Simultaneous Integer Init & Assign.
+* Input functions <1>: I/O of Integers.
+* Input functions: I/O of Floats.
+* Installation: Installing MP.
+* Integer: MP Basics.
+* Integer arithmetic functions: Integer Arithmetic.
+* Integer assignment functions: Assigning Integers.
+* Integer conversion functions: Converting Integers.
+* Integer functions: Integer Functions.
+* Integer input and output functions: I/O of Integers.
+* Limb: MP Basics.
+* Logical functions: Integer Logic and Bit Fiddling.
+* Low-level functions: Low-level Functions.
+* Miscellaneous float functions: Miscellaneous Float Functions.
+* Miscellaneous integer functions: Miscellaneous Integer Functions.
+* Output functions <1>: I/O of Floats.
+* Output functions: I/O of Integers.
+* Rational number: MP Basics.
+* Rational number functions: Rational Number Functions.
+* Reporting bugs: Reporting Bugs.
+* User-defined precision: Floating-point Functions.
+
diff --git a/gmp.info-3 b/gmp.info-3
new file mode 100644
index 000000000..174c5e2db
--- /dev/null
+++ b/gmp.info-3
@@ -0,0 +1,253 @@
+This is Info file gmp.info, produced by Makeinfo-1.64 from the input
+file gmp.texi.
+
+START-INFO-DIR-ENTRY
+* gmp: (gmp.info). GNU Multiple Precision Arithmetic Library.
+END-INFO-DIR-ENTRY
+
+ This file documents GNU MP, a library for arbitrary-precision
+arithmetic.
+
+ This is a draft edition of the documentation, last updated April
+1996.
+
+ Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation,
+Inc.
+
+ Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+ Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+ Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be stated in a
+translation approved by the Foundation.
+
+
+File: gmp.info, Node: Function Index, Up: Top
+
+Function and Type Index
+***********************
+
+* Menu:
+
+* mp_limb_t: MP Basics.
+* mpf_t: MP Basics.
+* mpq_t: MP Basics.
+* mpz_t: MP Basics.
+* __GNU_MP_VERSION: MP Basics.
+* __GNU_MP_VERSION_MINOR: MP Basics.
+* _mpz_realloc: Initializing Integers.
+* allocate_function: Custom Allocation.
+* deallocate_function: Custom Allocation.
+* gcd: BSD Compatible Functions.
+* itom: BSD Compatible Functions.
+* madd: BSD Compatible Functions.
+* mcmp: BSD Compatible Functions.
+* mdiv: BSD Compatible Functions.
+* mfree: BSD Compatible Functions.
+* min: BSD Compatible Functions.
+* mout: BSD Compatible Functions.
+* move: BSD Compatible Functions.
+* mp_set_memory_functions: Custom Allocation.
+* mpf_abs: Float Arithmetic.
+* mpf_add: Float Arithmetic.
+* mpf_add_ui: Float Arithmetic.
+* mpf_clear: Initializing Floats.
+* mpf_cmp: Float Comparison.
+* mpf_cmp_si: Float Comparison.
+* mpf_cmp_ui: Float Comparison.
+* mpf_div: Float Arithmetic.
+* mpf_div_2exp: Float Arithmetic.
+* mpf_div_ui: Float Arithmetic.
+* mpf_eq: Float Comparison.
+* mpf_get_prec: Initializing Floats.
+* mpf_get_str: Converting Floats.
+* mpf_init: Initializing Floats.
+* mpf_init2: Initializing Floats.
+* mpf_init_set: Simultaneous Float Init & Assign.
+* mpf_init_set_d: Simultaneous Float Init & Assign.
+* mpf_init_set_si: Simultaneous Float Init & Assign.
+* mpf_init_set_str: Simultaneous Float Init & Assign.
+* mpf_init_set_ui: Simultaneous Float Init & Assign.
+* mpf_inp_str: I/O of Floats.
+* mpf_mul: Float Arithmetic.
+* mpf_mul_2exp: Float Arithmetic.
+* mpf_mul_ui: Float Arithmetic.
+* mpf_neg: Float Arithmetic.
+* mpf_out_str: I/O of Floats.
+* mpf_pow_ui: Float Arithmetic.
+* mpf_random2: Miscellaneous Float Functions.
+* mpf_reldiff: Float Comparison.
+* mpf_set: Assigning Floats.
+* mpf_set_d: Assigning Floats.
+* mpf_set_default_prec: Initializing Floats.
+* mpf_set_prec: Initializing Floats.
+* mpf_set_prec_raw: Initializing Floats.
+* mpf_set_si: Assigning Floats.
+* mpf_set_str: Assigning Floats.
+* mpf_set_ui: Assigning Floats.
+* mpf_sgn: Float Comparison.
+* mpf_sqrt: Float Arithmetic.
+* mpf_sqrt_ui: Float Arithmetic.
+* mpf_sub: Float Arithmetic.
+* mpf_sub_ui: Float Arithmetic.
+* mpf_ui_div: Float Arithmetic.
+* mpf_ui_sub: Float Arithmetic.
+* mpn_add: Low-level Functions.
+* mpn_add_1: Low-level Functions.
+* mpn_add_n: Low-level Functions.
+* mpn_addmul_1: Low-level Functions.
+* mpn_bdivmod: Low-level Functions.
+* mpn_cmp: Low-level Functions.
+* mpn_divmod: Low-level Functions.
+* mpn_divmod_1: Low-level Functions.
+* mpn_divrem: Low-level Functions.
+* mpn_divrem_1: Low-level Functions.
+* mpn_gcd: Low-level Functions.
+* mpn_gcd_1: Low-level Functions.
+* mpn_gcdext: Low-level Functions.
+* mpn_get_str: Low-level Functions.
+* mpn_hamdist: Low-level Functions.
+* mpn_lshift: Low-level Functions.
+* mpn_mod_1: Low-level Functions.
+* mpn_mul: Low-level Functions.
+* mpn_mul_1: Low-level Functions.
+* mpn_mul_n: Low-level Functions.
+* mpn_perfect_square_p: Low-level Functions.
+* mpn_popcount: Low-level Functions.
+* mpn_pre_mod_1: Low-level Functions.
+* mpn_random2: Low-level Functions.
+* mpn_rshift: Low-level Functions.
+* mpn_scan0: Low-level Functions.
+* mpn_scan1: Low-level Functions.
+* mpn_set_str: Low-level Functions.
+* mpn_sqrtrem: Low-level Functions.
+* mpn_sub: Low-level Functions.
+* mpn_sub_1: Low-level Functions.
+* mpn_sub_n: Low-level Functions.
+* mpn_submul_1: Low-level Functions.
+* mpq_add: Assigning Rationals.
+* mpq_canonicalize: Rational Number Functions.
+* mpq_clear: Initializing Rationals.
+* mpq_cmp: Comparing Rationals.
+* mpq_cmp_ui: Comparing Rationals.
+* mpq_denref: Applying Integer Functions.
+* mpq_div: Assigning Rationals.
+* mpq_equal: Comparing Rationals.
+* mpq_get_den: Miscellaneous Rational Functions.
+* mpq_get_num: Miscellaneous Rational Functions.
+* mpq_init: Initializing Rationals.
+* mpq_inv: Assigning Rationals.
+* mpq_mul: Assigning Rationals.
+* mpq_neg: Assigning Rationals.
+* mpq_numref: Applying Integer Functions.
+* mpq_set: Initializing Rationals.
+* mpq_set_den: Miscellaneous Rational Functions.
+* mpq_set_num: Miscellaneous Rational Functions.
+* mpq_set_si: Initializing Rationals.
+* mpq_set_ui: Initializing Rationals.
+* mpq_sgn: Comparing Rationals.
+* mpq_sub: Assigning Rationals.
+* mpz_abs: Integer Arithmetic.
+* mpz_add: Integer Arithmetic.
+* mpz_add_ui: Integer Arithmetic.
+* mpz_and: Integer Logic and Bit Fiddling.
+* mpz_array_init: Initializing Integers.
+* mpz_cdiv_q: Integer Arithmetic.
+* mpz_cdiv_q_ui: Integer Arithmetic.
+* mpz_cdiv_qr: Integer Arithmetic.
+* mpz_cdiv_qr_ui: Integer Arithmetic.
+* mpz_cdiv_r: Integer Arithmetic.
+* mpz_cdiv_r_ui: Integer Arithmetic.
+* mpz_cdiv_ui: Integer Arithmetic.
+* mpz_clear: Initializing Integers.
+* mpz_clrbit: Integer Logic and Bit Fiddling.
+* mpz_cmp: Comparison Functions.
+* mpz_cmp_si: Comparison Functions.
+* mpz_cmp_ui: Comparison Functions.
+* mpz_com: Integer Logic and Bit Fiddling.
+* mpz_divexact: Integer Arithmetic.
+* mpz_fac_ui: Integer Arithmetic.
+* mpz_fdiv_q: Integer Arithmetic.
+* mpz_fdiv_q_2exp: Integer Arithmetic.
+* mpz_fdiv_q_ui: Integer Arithmetic.
+* mpz_fdiv_qr: Integer Arithmetic.
+* mpz_fdiv_qr_ui: Integer Arithmetic.
+* mpz_fdiv_r: Integer Arithmetic.
+* mpz_fdiv_r_2exp: Integer Arithmetic.
+* mpz_fdiv_r_ui: Integer Arithmetic.
+* mpz_fdiv_ui: Integer Arithmetic.
+* mpz_gcd: Integer Arithmetic.
+* mpz_gcd_ui: Integer Arithmetic.
+* mpz_gcdext: Integer Arithmetic.
+* mpz_get_si: Converting Integers.
+* mpz_get_str: Converting Integers.
+* mpz_get_ui: Converting Integers.
+* mpz_hamdist: Integer Logic and Bit Fiddling.
+* mpz_init: Initializing Integers.
+* mpz_init_set: Simultaneous Integer Init & Assign.
+* mpz_init_set_d: Simultaneous Integer Init & Assign.
+* mpz_init_set_si: Simultaneous Integer Init & Assign.
+* mpz_init_set_str: Simultaneous Integer Init & Assign.
+* mpz_init_set_ui: Simultaneous Integer Init & Assign.
+* mpz_inp_raw: I/O of Integers.
+* mpz_inp_str: I/O of Integers.
+* mpz_invert: Integer Arithmetic.
+* mpz_ior: Integer Logic and Bit Fiddling.
+* mpz_mod: Integer Arithmetic.
+* mpz_mod_ui: Integer Arithmetic.
+* mpz_mul: Integer Arithmetic.
+* mpz_mul_2exp: Integer Arithmetic.
+* mpz_mul_ui: Integer Arithmetic.
+* mpz_neg: Integer Arithmetic.
+* mpz_out_raw: I/O of Integers.
+* mpz_out_str: I/O of Integers.
+* mpz_perfect_square_p: Integer Arithmetic.
+* mpz_popcount: Integer Logic and Bit Fiddling.
+* mpz_pow_ui: Integer Arithmetic.
+* mpz_powm: Integer Arithmetic.
+* mpz_powm_ui: Integer Arithmetic.
+* mpz_probab_prime_p: Integer Arithmetic.
+* mpz_random: Miscellaneous Integer Functions.
+* mpz_random2: Miscellaneous Integer Functions.
+* mpz_scan0: Integer Logic and Bit Fiddling.
+* mpz_scan1: Integer Logic and Bit Fiddling.
+* mpz_set: Assigning Integers.
+* mpz_set_d: Assigning Integers.
+* mpz_set_si: Assigning Integers.
+* mpz_set_str: Assigning Integers.
+* mpz_set_ui: Assigning Integers.
+* mpz_setbit: Integer Logic and Bit Fiddling.
+* mpz_sgn: Comparison Functions.
+* mpz_size: Miscellaneous Integer Functions.
+* mpz_sizeinbase: Miscellaneous Integer Functions.
+* mpz_sqrt: Integer Arithmetic.
+* mpz_sqrtrem: Integer Arithmetic.
+* mpz_sub: Integer Arithmetic.
+* mpz_sub_ui: Integer Arithmetic.
+* mpz_tdiv_q: Integer Arithmetic.
+* mpz_tdiv_q_2exp: Integer Arithmetic.
+* mpz_tdiv_q_ui: Integer Arithmetic.
+* mpz_tdiv_qr: Integer Arithmetic.
+* mpz_tdiv_qr_ui: Integer Arithmetic.
+* mpz_tdiv_r: Integer Arithmetic.
+* mpz_tdiv_r_2exp: Integer Arithmetic.
+* mpz_tdiv_r_ui: Integer Arithmetic.
+* mpz_ui_pow_ui: Integer Arithmetic.
+* msqrt: BSD Compatible Functions.
+* msub: BSD Compatible Functions.
+* mtox: BSD Compatible Functions.
+* mult: BSD Compatible Functions.
+* pow: BSD Compatible Functions.
+* reallocate_function: Custom Allocation.
+* rpow: BSD Compatible Functions.
+* sdiv: BSD Compatible Functions.
+* xtom: BSD Compatible Functions.
+
+
diff --git a/gmp.texi b/gmp.texi
new file mode 100644
index 000000000..e52c58595
--- /dev/null
+++ b/gmp.texi
@@ -0,0 +1,2476 @@
+\input texinfo @c -*-texinfo-*-
+@c %**start of header
+@setfilename gmp.info
+@settitle GNU MP 2.0
+@synindex tp fn
+@iftex
+@afourpaper
+@end iftex
+@comment %**end of header
+
+@ifinfo
+@format
+START-INFO-DIR-ENTRY
+* gmp: (gmp.info). GNU Multiple Precision Arithmetic Library.
+END-INFO-DIR-ENTRY
+@end format
+@end ifinfo
+
+@c smallbook
+
+@iftex
+@finalout
+@end iftex
+
+@c Note: the edition number is listed in *three* places; please update
+@c all three. Also, update the month and year where appropriate.
+
+@c ==> Update edition number for settitle and subtitle, and in the
+@c ==> following paragraph; update date, too.
+
+
+@ifinfo
+This file documents GNU MP, a library for arbitrary-precision arithmetic.
+
+This is a draft edition of the documentation, last updated April 1996.
+
+Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+@end ifinfo
+
+@setchapternewpage on
+@headings double
+@titlepage
+@c use the new format for titles
+
+@title GNU MP
+@subtitle The GNU Multiple Precision Arithmetic Library
+@subtitle Edition 2.0
+@subtitle April 1996
+
+@author by Torbj@"orn Granlund, TMG Datakonsult
+
+@c Include the Distribution inside the titlepage so
+@c that headings are turned off.
+
+@tex
+\global\parindent=0pt
+\global\parskip=6pt
+\global\baselineskip=13pt
+@end tex
+
+@page
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+@sp 2
+
+Published by the Free Software Foundation @*
+59 Temple Place - Suite 330 @*
+Boston, MA 02111-1307, USA @*
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+@end titlepage
+
+@ifinfo
+@node Top, Copying, (dir), (dir)
+
+@top GNU MP
+
+This manual documents how to install and use the GNU Multiple Precision
+Arithmetic Library, version 2.0.
+
+@end ifinfo
+
+@menu
+* Copying:: GMP Copying Conditions (LGPL).
+* Introduction to MP:: Brief introduction to GNU MP.
+* Installing MP:: How to configure and compile the MP library.
+* MP Basics:: What every MP user should now.
+* Reporting Bugs:: How to usefully report bugs.
+* Integer Functions:: Functions for arithmetic on signed integers.
+* Rational Number Functions:: Functions for arithmetic on rational numbers.
+* Floating-point Functions:: Functions for arithmetic on floats.
+* Low-level Functions:: Fast functions for natural numbers.
+* BSD Compatible Functions:: All functions found in BSD MP.
+* Custom Allocation:: How to customize the internal allocation.
+
+* Contributors::
+* References::
+* Concept Index::
+* Function Index::
+@end menu
+
+@node Copying, Introduction to MP, Top, Top
+@comment node-name, next, previous, up
+@unnumbered GNU MP Copying Conditions
+@cindex Copying conditions
+@cindex Conditions for copying GNU MP
+
+This library is @dfn{free}; this means that everyone is free to use it and
+free to redistribute it on a free basis. The library is not in the public
+domain; it is copyrighted and there are restrictions on its distribution, but
+these restrictions are designed to permit everything that a good cooperating
+citizen would want to do. What is not allowed is to try to prevent others
+from further sharing any version of this library that they might get from
+you.@refill
+
+Specifically, we want to make sure that you have the right to give away copies
+of the library, that you receive source code or else can get it if you want
+it, that you can change this library or use pieces of it in new free programs,
+and that you know you can do these things.@refill
+
+To make sure that everyone has such rights, we have to forbid you to deprive
+anyone else of these rights. For example, if you distribute copies of the GNU
+MP library, you must give the recipients all the rights that you have. You
+must make sure that they, too, receive or can get the source code. And you
+must tell them their rights.@refill
+
+Also, for our own protection, we must make certain that everyone finds out
+that there is no warranty for the GNU MP library. If it is modified by
+someone else and passed on, we want their recipients to know that what they
+have is not what we distributed, so that any problems introduced by others
+will not reflect on our reputation.@refill
+
+The precise conditions of the license for the GNU MP library are found in the
+Library General Public License that accompany the source code.@refill
+
+@node Introduction to MP, Installing MP, Copying, Top
+@comment node-name, next, previous, up
+@chapter Introduction to GNU MP
+
+
+GNU MP is a portable library written in C for arbitrary precision arithmetic
+on integers, rational numbers, and floating-point numbers. It aims to provide
+the fastest possible arithmetic for all applications that need higher
+precision than is directly supported by the basic C types.
+
+Many applications use just a few hundred bits of precision; but some
+applications may need thousands or even millions of bits. MP is designed to
+give good performance for both, by choosing algorithms based on the sizes of
+the operands, and by carefully keeping the overhead at a minimum.
+
+The speed of MP is achieved by using fullwords as the basic arithmetic type,
+by using sophisticated algorithms, by including carefully optimized assembly
+code for the most common inner loops for many different CPUs, and by a general
+emphasis on speed (as opposed to simplicity or elegance).
+
+There is carefully optimized assembly code for these CPUs: DEC Alpha, Amd
+29000, HPPA 1.0 and 1.1, Intel Pentium and generic x86, Intel i960, Motorola
+MC68000, MC68020, MC88100, and MC88110, Motorola/IBM PowerPC, National
+NS32000, IBM POWER, MIPS R3000, R4000, SPARCv7, SuperSPARC, generic SPARCv8,
+and DEC VAX. Some optimizations also for ARM, Clipper, IBM ROMP (RT), and
+Pyramid AP/XP.
+
+This version of MP is released under a more liberal license than previous
+versions. It is now permitted to link MP to non-free programs, as long as MP
+source code is provided when distributing the non-free program.
+
+
+@section How to use this Manual
+
+Everyone should read @ref{MP Basics}. If you need to install the library
+yourself, you need to read @ref{Installing MP}, too.
+
+The rest of the manual can be used for later reference, although it is
+probably a good idea too glance through it.
+
+
+@node Installing MP, MP Basics, Introduction to MP, Top
+@comment node-name, next, previous, up
+@chapter Installing MP
+@cindex Installation
+
+To build MP, you first have to configure it for your CPU and operating system.
+You need a C compiler, preferably GCC, but any reasonable compiler should
+work. And you need a standard Unix @samp{make} program, plus some other
+standard Unix utility programs.
+
+(If you're on a MS-DOS machine, your can build MP using @file{make.bat}. It
+requires that djgpp is installed. It does not require configuration, nor is
+@samp{make} needed; @file{make.bat} both configures and builds the library.)
+
+Here are the steps needed to install the library on Unix systems:
+
+@enumerate
+@item
+In most cases, @samp{./configure --target=cpu-vendor-os}, should work both for
+native and cross-compilation. If you get error messages, your machine might
+not be supported.
+
+If you want to compile in a separate object directory, cd to that directory,
+and prefix the configure command with the path to the MP source directory.
+Not all @samp{make} programs have the necessary features to support this. In
+particular, SunOS and Slowaris @samp{make} have bugs that makes them unable to
+build from a separate object directory. Use GNU @samp{make} instead.
+
+In addition to the standard cpu-vendor-os tuples, MP recognizes sparc8 and
+supersparc as valid CPU names. Specifying these CPU names for relevant
+systems will improve performance significantly.
+
+In general, if you want a library that runs as fast as possible, you should
+make sure you configure MP for the exact CPU type your system uses.
+
+If you have @code{gcc} in your @code{PATH}, it will be used by default. To
+override this, pass @samp{-with-gcc=no} to @file{configure}.
+
+@item
+@samp{make}
+
+This will compile MP, and create a library archive file @file{libgmp.a} in the
+working directory.
+
+@item
+@samp{make check}
+
+This will make sure MP was built correctly. If you get error messages, please
+report this to @samp{bug-gmp@@prep.ai.mit.edu}. (@xref{Reporting Bugs}, for
+information on what to include in useful bug reports.)
+
+@item
+@samp{make install}
+
+This will copy the file @file{gmp.h} and @file{libgmp.a}, as well as the info
+files, to @file{/usr/local} (or if you passed the @samp{--prefix} option to
+@file{configure}, to the directory given as argument to @samp{--prefix}).
+@end enumerate
+
+@noindent
+If you wish to build and install the BSD MP compatible functions, use
+@samp{make libmp.a} and @samp{make install-bsdmp}.
+
+There are some other useful make targets:
+
+@itemize @bullet
+@item
+@samp{doc}
+
+Create a DVI version of the manual, in @file{gmp.dvi} and a set of info files,
+in @file{gmp.info}, @file{gmp.info-1}, @file{gmp.info-2}, etc.
+
+@item
+@samp{ps}
+
+Create a Postscript version of the manual, in @file{gmp.ps}.
+
+@item
+@samp{html}
+
+Create a HTML version of the manual, in @file{gmp.html}.
+
+@item
+@samp{clean}
+
+Delete all object files and archive files, but not the configuration files.
+
+@item
+@samp{distclean}
+
+Delete all files not included in the distribution.
+
+@item
+@samp{uninstall}
+
+Delete all files copied by @samp{make install}.
+@end itemize
+
+
+@section Known Build Problems
+
+GCC 2.7.2 (as well as 2.6.3) for the RS/6000 and PowerPC can not be used to
+compile MP, due to a bug in GCC. If you want to use GCC for these machines,
+you need to apply the patch below to GCC, or use a later version of the
+compiler.
+
+If you are on a Sequent Symmetry, use the GNU assembler instead of the
+system's assembler, since the latter has serious bugs.
+
+The system compiler on NeXT is a massacred and old gcc, even if the compiler
+calls itself @file{cc}. This compiler cannot be used to build MP. You need
+to get a real gcc, and install that before you compile MP. (NeXT might have
+fixed this in newer releases of their system.)
+
+Please report other problems to @samp{bug-gmp@@prep.ai.mit.edu}.
+@xref{Reporting Bugs}.
+
+
+Patch to apply to GCC 2.6.3 and 2.7.2:
+
+@example
+*** config/rs6000/rs6000.md Sun Feb 11 08:22:11 1996
+--- config/rs6000/rs6000.md.new Sun Feb 18 03:33:37 1996
+***************
+*** 920,926 ****
+ (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (not:SI (match_dup 1)))]
+ ""
+! "nor. %0,%2,%1"
+ [(set_attr "type" "compare")])
+
+ (define_insn ""
+--- 920,926 ----
+ (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (not:SI (match_dup 1)))]
+ ""
+! "nor. %0,%1,%1"
+ [(set_attr "type" "compare")])
+
+ (define_insn ""
+@end example
+
+@node MP Basics, Reporting Bugs, Installing MP, Top
+@comment node-name, next, previous, up
+@chapter MP Basics
+
+
+@cindex @file{gmp.h}
+All declarations needed to use MP are collected in the include file
+@file{gmp.h}. It is designed to work with both C and C++ compilers.
+
+
+@section Nomenclature and Types
+
+@cindex Integer
+@tindex @code{mpz_t}
+@noindent
+In this manual, @dfn{integer} usually means a multiple precision integer, as
+defined by the MP library. The C data type for such integers is @code{mpz_t}.
+Here are some examples of how to declare such integers:
+
+@example
+mpz_t sum;
+
+struct foo @{ mpz_t x, y; @};
+
+mpz_t vec[20];
+@end example
+
+@cindex Rational number
+@tindex @code{mpq_t}
+@noindent
+@dfn{Rational number} means a multiple precision fraction. The C data type
+for these fractions is @code{mpq_t}. For example:
+
+@example
+mpq_t quotient;
+@end example
+
+@cindex Floating-point number
+@tindex @code{mpf_t}
+@noindent
+@dfn{Floating point number} or @dfn{Float} for short, is an arbitrary precision
+mantissa with an limited precision exponent. The C data type for such objects
+is @code{mpf_t}.
+
+@cindex Limb
+@tindex @code{mp_limb_t}
+@noindent
+A @dfn{limb} means the part of a multi-precision number that fits in a single
+word. (We chose this word because a limb of the human body is analogous to a
+digit, only larger, and containing several digits.) Normally a limb contains
+32 or 64 bits. The C data type for a limb is @code{mp_limb_t}.
+
+
+@section Function Classes
+
+There are six classes of functions in the MP library:
+
+@enumerate
+@item
+Functions for signed integer arithmetic, with names beginning with
+@code{mpz_}. The associated type is @code{mpz_t}. There are about 100
+functions in this class.
+
+@item
+Functions for rational number arithmetic, with names beginning with
+@code{mpq_}. The associated type is @code{mpq_t}. There are about 20
+functions in this class, but the functions in the previous class can be used
+for performing arithmetic on the numerator and denominator separately.
+
+@item
+Functions for floating-point arithmetic, with names beginning with
+@code{mpf_}. The associated type is @code{mpf_t}. There are about 50
+functions is this class.
+
+@item
+Functions compatible with Berkeley MP, such as @code{itom}, @code{madd}, and
+@code{mult}. The associated type is @code{MINT}.
+
+@item
+Fast low-level functions that operate on natural numbers. These are used by
+the functions in the preceding groups, and you can also call them directly
+from very time-critical user programs. These functions' names begin with
+@code{mpn_}. There are about 30 (hard-to-use) functions in this class.
+
+The associated type is array of @code{mp_limb_t}.
+
+@item
+Miscellaneous functions. Functions for setting up custom allocation.
+@end enumerate
+
+
+@section MP Variable Conventions
+
+As a general rule, all MP functions expect output arguments before input
+arguments. This notation is based on an analogy with the assignment operator.
+(The BSD MP compatibility functions disobey this rule, having the output
+argument(s) last.)
+
+MP allows you to use the same variable for both input and output in the same
+expression. For example, the main function for integer multiplication,
+@code{mpz_mul}, can be used like this: @code{mpz_mul (x, x, x);}. This
+computes the square of @var{x} and put the result back in @var{x}.
+
+Before you can assign to an MP variable, you need to initialize it by calling
+one of the special initialization functions. When you're done with a
+variable, you need to clear it out, using one of the functions for that
+purpose. Which function to use depends on the type of variable. See the
+chapters on integer functions, rational number functions, and floating-point
+functions for details.
+
+A variable should only be initialized once, or at least cleared out between
+each initialization. After a variable has been initialized, it may be
+assigned to any number of times.
+
+For efficiency reasons, avoid to initialize and clear out a variable in loops.
+Instead, initialize it before entering the loop, and clear it out after the
+loop has exited.
+
+You don't need to be concerned about allocating additional space for MP
+variables. All functions in MP automatically allocate additional space when a
+variable does not already have enough space. They do not, however, reduce the
+space when a smaller number is stored in the object. Most of the time, this
+policy is best, since it avoids frequent re-allocation.
+
+
+@section Useful Macros and Constants
+
+@deftypevr {Global Constant} {const int} mp_bits_per_limb
+The number of bits per limb.
+@end deftypevr
+
+@defmac __GNU_MP_VERSION
+@defmacx __GNU_MP_VERSION_MINOR
+The major and minor MP version, respectively, as integers.
+@end defmac
+
+@section Compatibility with Version 1.x
+
+This version of MP is upward compatible with previous versions of MP, with a
+few exceptions.
+
+@enumerate
+@item Integer division functions round the result differently. The old
+functions (@code{mpz_div}, @code{mpz_divmod}, @code{mpz_mdiv},
+@code{mpz_mdivmod}, etc) now all use floor rounding (i.e., they round the
+quotient to @minus{}infinity). There are a lot of new functions for integer
+division, giving the user better control over the rounding.
+
+@item The function @code{mpz_mod} now compute the true @strong{mod} function.
+
+@item The functions @code{mpz_powm} and @code{mpz_powm_ui} now use
+@strong{mod} for reduction.
+
+@item The assignment functions for rational numbers do no longer canonicalize
+their results. In the case a non-canonical result could arise from an
+assignment, the user need to insert an explicit call to
+@code{mpq_canonicalize}. This change was made for efficiency.
+
+@item Output generated by @code{mpz_out_raw} in this release cannot be read
+by @code{mpz_inp_raw} in previous releases. This change was made for making
+the file format truly portable between machines with different word sizes.
+
+@item Several @code{mpn} functions have changed. But they were intentionally
+undocumented in previous releases.
+
+@end enumerate
+
+
+@section Getting the Latest Version of MP
+
+The latest version of the MP library is available by anonymous ftp from from
+@samp{prep.ai.mit.edu}. The file name is @file{/pub/gnu/gmp-M.N.tar.gz}.
+Many sites around the world mirror @samp{prep}; please use a mirror site near
+you.
+
+@node Reporting Bugs, Integer Functions, MP Basics, Top
+@comment node-name, next, previous, up
+@chapter Reporting Bugs
+@cindex Reporting bugs
+
+If you think you have found a bug in the MP library, please investigate it and
+report it. We have made this library available to you, and it is not to ask
+too much from you, to ask you to report the bugs that you find.
+
+There are a few things you should think about when you put your bug report
+together.
+
+You have to send us a test case that makes it possible for us to reproduce the
+bug. Include instructions on how to run the test case.
+
+You also have to explain what is wrong; if you get a crash, or if the results
+printed are incorrect and in that case, in what way.
+
+It is not uncommon that an observed problem is actually due to a bug in the
+compiler used when building MP; the MP code tends to explore interesting
+corners in compilers. Therefore, please include compiler version information
+in your bug report. This can be extracted using @samp{what `which cc`}, or,
+if you're using gcc, @samp{gcc -v}. Also, include the output from @samp{uname
+-a}.
+
+If your bug report is good, we will do our best to help you to get a corrected
+version of the library; if the bug report is poor, we won't do anything about
+it (aside of chiding you to send better bug reports).
+
+Send your bug report to: @samp{bug-gmp@@prep.ai.mit.edu}.
+
+If you think something in this manual is unclear, or downright incorrect, or if
+the language needs to be improved, please send a note to the same address.
+
+
+@node Integer Functions, Rational Number Functions, Reporting Bugs, Top
+@comment node-name, next, previous, up
+@chapter Integer Functions
+@cindex Integer functions
+
+This chapter describes the MP functions for performing integer arithmetic.
+These functions start with the prefix @code{mpz_}.
+
+Arbitrary precision integers are stored in objects of type @code{mpz_t}.
+
+@menu
+* Initializing Integers::
+* Assigning Integers::
+* Simultaneous Integer Init & Assign::
+* Converting Integers::
+* Integer Arithmetic::
+* Comparison Functions::
+* Integer Logic and Bit Fiddling::
+* I/O of Integers::
+* Miscellaneous Integer Functions::
+@end menu
+
+@node Initializing Integers, Assigning Integers, , Integer Functions
+@comment node-name, next, previous, up
+@section Initialization and Assignment Functions
+
+The functions for integer arithmetic assume that all integer objects are
+initialized. You do that by calling the function @code{mpz_init}.
+
+@deftypefun void mpz_init (mpz_t @var{integer})
+Initialize @var{integer} with limb space and set the initial numeric value to
+0. Each variable should normally only be initialized once, or at least cleared
+out (using @code{mpz_clear}) between each initialization.
+@end deftypefun
+
+Here is an example of using @code{mpz_init}:
+
+@example
+@{
+ mpz_t integ;
+ mpz_init (integ);
+ @dots{}
+ mpz_add (integ, @dots{});
+ @dots{}
+ mpz_sub (integ, @dots{});
+
+ /* Unless the program is about to exit, do ... */
+ mpz_clear (integ);
+@}
+@end example
+
+@noindent
+As you can see, you can store new values any number of times, once an
+object is initialized.
+
+@deftypefun void mpz_clear (mpz_t @var{integer})
+Free the limb space occupied by @var{integer}. Make sure to call this
+function for all @code{mpz_t} variables when you are done with them.
+@end deftypefun
+
+@deftypefun {void *} _mpz_realloc (mpz_t @var{integer}, mp_size_t @var{new_alloc})
+Change the limb space allocation to @var{new_alloc} limbs. This function is
+not normally called from user code, but it can be used to give memory back to
+the heap, or to increase the space of a variable to avoid repeated automatic
+re-allocation.
+@end deftypefun
+
+@deftypefun void mpz_array_init (mpz_t @var{integer_array}[], size_t @var{array_size}, mp_size_t @var{fixed_num_bits})
+Allocate @strong{fixed} limb space for all @var{array_size} integers in
+@var{integer_array}. The fixed allocation for each integer in the array is
+enough to store @var{fixed_num_bits}. If the fixed space will be insufficient
+for storing the result of a subsequent calculation, the result is
+unpredictable.
+
+This function is useful for decreasing the working set for some algorithms
+that use large integer arrays.
+
+There is no way to de-allocate the storage allocated by this function.
+Don't call @code{mpz_clear}!
+@end deftypefun
+
+
+@node Assigning Integers, Simultaneous Integer Init & Assign, Initializing Integers, Integer Functions
+@comment node-name, next, previous, up
+@subsection Assignment Functions
+@cindex Integer assignment functions
+
+These functions assign new values to already initialized integers
+(@pxref{Initializing Integers}).
+
+@deftypefun void mpz_set (mpz_t @var{rop}, mpz_t @var{op})
+@deftypefunx void mpz_set_ui (mpz_t @var{rop}, unsigned long int @var{op})
+@deftypefunx void mpz_set_si (mpz_t @var{rop}, signed long int @var{op})
+@deftypefunx void mpz_set_d (mpz_t @var{rop}, double @var{op})
+Set the value of @var{rop} from @var{op}.
+@end deftypefun
+
+@deftypefun int mpz_set_str (mpz_t @var{rop}, char *@var{str}, int @var{base})
+Set the value of @var{rop} from @var{str}, a '\0'-terminated C string in base
+@var{base}. White space is allowed in the string, and is simply ignored. The
+base may vary from 2 to 36. If @var{base} is 0, the actual base is determined
+from the leading characters: if the first two characters are `0x' or `0X',
+hexadecimal is assumed, otherwise if the first character is `0', octal is
+assumed, otherwise decimal is assumed.
+
+This function returns 0 if the entire string up to the '\0' is a valid
+number in base @var{base}. Otherwise it returns @minus{}1.
+@end deftypefun
+
+
+@node Simultaneous Integer Init & Assign, Converting Integers, Assigning Integers, Integer Functions
+@comment node-name, next, previous, up
+@subsection Combined Initialization and Assignment Functions
+@cindex Initialization and assignment functions
+
+For convenience, MP provides a parallel series of initialize-and-set functions
+which initialize the output and then store the value there. These functions'
+names have the form @code{mpz_init_set@dots{}}
+
+Here is an example of using one:
+
+@example
+@{
+ mpz_t pie;
+ mpz_init_set_str (pie, "3141592653589793238462643383279502884", 10);
+ @dots{}
+ mpz_sub (pie, @dots{});
+ @dots{}
+ mpz_clear (pie);
+@}
+@end example
+
+@noindent
+Once the integer has been initialized by any of the @code{mpz_init_set@dots{}}
+functions, it can be used as the source or destination operand for the ordinary
+integer functions. Don't use an initialize-and-set function on a variable
+already initialized!
+
+@deftypefun void mpz_init_set (mpz_t @var{rop}, mpz_t @var{op})
+@deftypefunx void mpz_init_set_ui (mpz_t @var{rop}, unsigned long int @var{op})
+@deftypefunx void mpz_init_set_si (mpz_t @var{rop}, signed long int @var{op})
+@deftypefunx void mpz_init_set_d (mpz_t @var{rop}, double @var{op})
+Initialize @var{rop} with limb space and set the initial numeric value from
+@var{op}.
+@end deftypefun
+
+@deftypefun int mpz_init_set_str (mpz_t @var{rop}, char *@var{str}, int @var{base})
+Initialize @var{rop} and set its value from @var{str}, a '\0'-terminated C
+string in base @var{base}. White space is allowed in the string, and is simply
+ignored. The base may vary from 2 to 36. If @var{base} is 0, the actual base
+is determined from the leading characters: if the first two characters are `0x'
+or `0X', hexadecimal is assumed, otherwise if the first character is `0', octal
+is assumed, otherwise decimal is assumed.
+
+If the string is a correct base @var{base} number, the function returns 0;
+if an error occurs it returns @minus{}1. @var{rop} is initialized even if
+an error occurs. (I.e., you have to call @code{mpz_clear} for it.)
+@end deftypefun
+
+
+@node Converting Integers, Integer Arithmetic, Simultaneous Integer Init & Assign, Integer Functions
+@comment node-name, next, previous, up
+@section Conversion Functions
+@cindex Integer conversion functions
+@cindex Conversion functions
+
+This section describes functions for converting arbitrary precision integers
+to standard C types. Functions for converting @strong{to} arbitrary
+precision integers are described in @ref{Assigning Integers} and @ref{I/O of
+Integers}.
+
+@deftypefun {unsigned long int} mpz_get_ui (mpz_t @var{op})
+Return the least significant part from @var{op}. This function combined
+with @* @code{mpz_tdiv_q_2exp(@dots{}, @var{op}, CHAR_BIT*sizeof(unsigned
+long int))} can be used to extract the limbs of an integer efficiently.
+@end deftypefun
+
+@deftypefun {signed long int} mpz_get_si (mpz_t @var{op})
+If @var{op} fits into a @code{signed long int} return the value of @var{op}.
+Otherwise return the least significant part of @var{op}, with the same sign
+as @var{op}.
+
+If @var{op} is too large to fit in a @code{signed long int}, the returned
+result is probably not very useful. @c To find out if the value will fit, use
+@c the function @code{mpz_fits_si}.
+@end deftypefun
+
+@deftypefun {char *} mpz_get_str (char *@var{str}, int @var{base}, mpz_t @var{op})
+Convert @var{op} to a string of digits in base @var{base}. The base may vary
+from 2 to 36.
+
+If @var{str} is NULL, space for the result string is allocated using the
+default allocation function, and a pointer to the string is returned.
+
+If @var{str} is not NULL, it should point to a block of storage enough large
+for the result. To find out the right amount of space to provide for
+@var{str}, use @code{mpz_sizeinbase (@var{op}, @var{base}) + 2}. The two
+extra bytes are for a possible minus sign, and for the terminating null
+character.
+@end deftypefun
+
+
+@need 2000
+@node Integer Arithmetic, Comparison Functions, Converting Integers, Integer Functions
+@comment node-name, next, previous, up
+@section Arithmetic Functions
+@cindex Integer arithmetic functions
+@cindex Arithmetic functions
+
+@deftypefun void mpz_add (mpz_t @var{rop}, mpz_t @var{op1}, mpz_t @var{op2})
+@deftypefunx void mpz_add_ui (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2})
+Set @var{rop} to @var{op1} + @var{op2}.
+@end deftypefun
+
+@deftypefun void mpz_sub (mpz_t @var{rop}, mpz_t @var{op1}, mpz_t @var{op2})
+@deftypefunx void mpz_sub_ui (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2})
+Set @var{rop} to @var{op1} @minus{} @var{op2}.
+@end deftypefun
+
+@deftypefun void mpz_mul (mpz_t @var{rop}, mpz_t @var{op1}, mpz_t @var{op2})
+@deftypefunx void mpz_mul_ui (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2})
+Set @var{rop} to @var{op1} times @var{op2}.
+@end deftypefun
+
+Division is undefined if the divisor is zero, and passing a zero divisor to
+the divide or modulo functions, as well passing a zero mod argument to the
+@code{mpz_powm} and @code{mpz_powm_ui} functions, will make these functions
+intentionally divide by zero. This gives the user the possibility to handle
+arithmetic exceptions in these functions in the same manner as other
+arithmetic exceptions.
+
+There are three main groups of division functions:
+@itemize @bullet
+@item
+Functions that truncate the quotient towards 0. The names of these
+functions start with @code{mpz_tdiv}. The @samp{t} in the name is short for
+@samp{truncate}.
+@item
+Functions that round the quotient towards @minus{}infinity. The names of
+these routines start with @code{mpz_fdiv}. The @samp{f} in the name is
+short for @samp{floor}.
+@item
+Functions that round the quotient towards +infinity. The names of
+these routines start with @code{mpz_cdiv}. The @samp{c} in the name is
+short for @samp{ceil}.
+@end itemize
+
+For each rounding mode, there are a couple of variants. Here @samp{q} means
+that the quotient is computed, while @samp{r} means that the remainder is
+computed. Functions that compute both the quotient and remainder have
+@samp{qr} in the name.
+
+@deftypefun void mpz_tdiv_q (mpz_t @var{rop}, mpz_t @var{op1}, mpz_t @var{op2})
+@deftypefunx void mpz_tdiv_q_ui (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2})
+Set @var{rop} to [@var{op1} / @var{op2}]. The quotient is truncated towards
+0.
+@end deftypefun
+
+@deftypefun void mpz_tdiv_r (mpz_t @var{rop}, mpz_t @var{op1}, mpz_t @var{op2})
+@deftypefunx void mpz_tdiv_r_ui (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2})
+Set @var{rop} to (@var{op1} - [@var{op1} / @var{op2}] * @var{op2}).
+Unless the remainder is zero, it has the same sign as the dividend.
+@end deftypefun
+
+@deftypefun void mpz_tdiv_qr (mpz_t @var{rop1}, mpz_t @var{rop2}, mpz_t @var{op1}, mpz_t @var{op2})
+@deftypefunx void mpz_tdiv_qr_ui (mpz_t @var{rop1}, mpz_t @var{rop2}, mpz_t @var{op1}, unsigned long int @var{op2})
+Divide @var{op1} by @var{op2} and put the quotient in @var{rop1} and the
+remainder in @var{rop2}. The quotient is rounded towards 0. Unless the
+remainder is zero, it has the same sign as the dividend.
+
+If @var{rop1} and @var{rop2} are the same variable, the results are
+undefined.
+@end deftypefun
+
+@deftypefun void mpz_fdiv_q (mpz_t @var{rop1}, mpz_t @var{op1}, mpz_t @var{op2})
+@deftypefunx void mpz_fdiv_q_ui (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2})
+@ifinfo
+Set @var{rop} to @var{op1} / @var{op2}. The quotient is rounded towards
+@minus{}infinity.
+@end ifinfo
+@iftex
+Set @var{rop} to
+@tex
+$\lfloor@var{op1} / @var{op2}\rfloor$.
+@end tex
+(I.e., round the quotient towards
+@tex
+$-\infty$.)
+@end tex
+@end iftex
+@end deftypefun
+
+@deftypefun void mpz_fdiv_r (mpz_t @var{rop}, mpz_t @var{op1}, mpz_t @var{op2})
+@deftypefunx {unsigned long int} mpz_fdiv_r_ui (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2})
+Divide @var{op1} by @var{op2} and put the remainder in @var{rop}. Unless
+the remainder is zero, it has the same sign as the divisor.
+
+For @code{mpz_fdiv_r_ui} the remainder is small enough to fit in an
+@code{unsigned long int}, and is therefore returned.
+@end deftypefun
+
+@deftypefun void mpz_fdiv_qr (mpz_t @var{rop1}, mpz_t @var{rop2}, mpz_t @var{op1}, mpz_t @var{op2})
+@deftypefunx {unsigned long int} mpz_fdiv_qr_ui (mpz_t @var{rop1}, mpz_t @var{rop2}, mpz_t @var{op1}, unsigned long int @var{op2})
+Divide @var{op1} by @var{op2} and put the quotient in @var{rop1} and the
+remainder in @var{rop2}. The quotient is rounded towards @minus{}infinity.
+Unless the remainder is zero, it has the same sign as the divisor.
+
+For @code{mpz_fdiv_qr_ui} the remainder is small enough to fit in an
+@code{unsigned long int}, and is therefore returned.
+
+If @var{rop1} and @var{rop2} are the same variable, the results are
+undefined.
+@end deftypefun
+
+@deftypefun {unsigned long int} mpz_fdiv_ui (mpz_t @var{op1}, unsigned long int @var{op2})
+This function is similar to @code{mpz_fdiv_r_ui}, but the remainder is only
+returned; it is not stored anywhere.
+@end deftypefun
+
+@deftypefun void mpz_cdiv_q (mpz_t @var{rop1}, mpz_t @var{op1}, mpz_t @var{op2})
+@deftypefunx void mpz_cdiv_q_ui (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2})
+@ifinfo
+Set @var{rop} to @var{op1} / @var{op2}. The quotient is rounded towards
++infinity.
+@end ifinfo
+@iftex
+Set @var{rop} to
+@tex
+$\lceil@var{op1} / @var{op2}\rceil$.
+@end tex
+(I.e., round the quotient towards
+@tex
+$+\infty$.)
+@end tex
+@end iftex
+@end deftypefun
+
+@deftypefun void mpz_cdiv_r (mpz_t @var{rop}, mpz_t @var{op1}, mpz_t @var{op2})
+@deftypefunx {unsigned long int} mpz_cdiv_r_ui (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2})
+Divide @var{op1} by @var{op2} and put the remainder in @var{rop}. Unless
+the remainder is zero, it has the opposite sign as the divisor.
+
+For @code{mpz_cdiv_r_ui} the negated remainder is small enough to fit in an
+@code{unsigned long int}, and it is therefore returned.
+@end deftypefun
+
+@deftypefun void mpz_cdiv_qr (mpz_t @var{rop1}, mpz_t @var{rop2}, mpz_t @var{op1}, mpz_t @var{op2})
+@deftypefunx {unsigned long int} mpz_cdiv_qr_ui (mpz_t @var{rop1}, mpz_t @var{rop2}, mpz_t @var{op1}, unsigned long int @var{op2})
+Divide @var{op1} by @var{op2} and put the quotient in @var{rop1} and the
+remainder in @var{rop2}. The quotient is rounded towards +infinity. Unless
+the remainder is zero, it has the opposite sign as the divisor.
+
+For @code{mpz_cdiv_qr_ui} the negated remainder is small enough to fit in an
+@code{unsigned long int}, and it is therefore returned.
+
+If @var{rop1} and @var{rop2} are the same variable, the results are
+undefined.
+@end deftypefun
+
+@deftypefun {unsigned long int} mpz_cdiv_ui (mpz_t @var{op1}, unsigned long int @var{op2})
+Return the negated remainder, similar to @code{mpz_cdiv_r_ui}. (The
+difference is that this function doesn't store the remainder anywhere.)
+@end deftypefun
+
+@deftypefun void mpz_mod (mpz_t @var{rop}, mpz_t @var{op1}, mpz_t @var{op2})
+@deftypefunx {unsigned long int} mpz_mod_ui (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2})
+Set @var{rop} to @var{op1} @code{mod} @var{op2}. The sign of the divisor is
+ignored, and the result is always non-negative.
+
+For @code{mpz_mod_ui} the remainder is small enough to fit in an
+@code{unsigned long int}, and is therefore returned.
+@end deftypefun
+
+@deftypefun void mpz_divexact (mpz_t @var{rop}, mpz_t @var{op1}, mpz_t @var{op2})
+Set @var{rop} to @var{op1} / @var{op2}. This function produces correct
+results only when it is known in advance that @var{op2} divides
+@var{op1}.
+
+Since mpz_divexact is much faster than any of the other routines that produce
+the quotient (@pxref{References} Jebelean), it is the best choice for
+instances in which exact division is known to occur, such as reducing a
+rational to lowest terms.
+@end deftypefun
+
+@deftypefun void mpz_sqrt (mpz_t @var{rop}, mpz_t @var{op})
+@ifinfo
+Set @var{rop} to the truncated integer part of the square root of
+@var{op}.
+@end ifinfo
+@iftex
+Set @var{rop} to
+@tex
+$\lfloor\sqrt{@var{op}}\rfloor$, the truncated integer part of the square
+root of @var{op}.
+@end tex
+@end iftex
+@end deftypefun
+
+@deftypefun void mpz_sqrtrem (mpz_t @var{rop1}, mpz_t @var{rop2}, mpz_t @var{op})
+@ifinfo
+Set @var{rop1} to the truncated integer part of the square root of @var{op},
+like @code{mpz_sqrt}. Set @var{rop2} to
+@var{op}@minus{}@var{rop1}*@var{rop1},
+@end ifinfo
+@iftex
+Set @var{rop1} to
+@tex
+$\lfloor\sqrt{@var{op}}\rfloor$,
+@end tex
+like @code{mpz_sqrt}. Set @var{rop2} to
+@tex
+$(@var{op} - @var{rop1}^2)$,
+@end tex
+@end iftex
+(i.e., zero if @var{op} is a perfect square).
+
+If @var{rop1} and @var{rop2} are the same variable, the results are
+undefined.
+@end deftypefun
+
+@deftypefun int mpz_perfect_square_p (mpz_t @var{op})
+Return non-zero if @var{op} is a perfect square, i.e., if the square root of
+@var{op} is an integer. Return zero otherwise.
+@end deftypefun
+
+@deftypefun int mpz_probab_prime_p (mpz_t @var{op}, int @var{reps})
+If this function returns 0, @var{op} is definitely not prime. If it returns
+1, then @var{op} is `probably' prime. The probability of a false positive is
+@ifinfo
+(1/4)**@var{reps}.
+@end ifinfo
+@iftex
+@tex
+$(1/4)^{{reps}}$.
+@end tex
+@end iftex
+A reasonable value of reps is 25.
+
+An implementation of the probabilistic primality test found in Seminumerical
+Algorithms (@pxref{References} Knuth).
+@end deftypefun
+
+@deftypefun void mpz_powm (mpz_t @var{rop}, mpz_t @var{base}, mpz_t @var{exp}, mpz_t @var{mod})
+@deftypefunx void mpz_powm_ui (mpz_t @var{rop}, mpz_t @var{base}, unsigned long int @var{exp}, mpz_t @var{mod})
+Set @var{rop} to (@var{base} raised to @var{exp}) @code{mod} @var{mod}. If
+@var{exp} is negative, the result is undefined.
+@end deftypefun
+
+@deftypefun void mpz_pow_ui (mpz_t @var{rop}, mpz_t @var{base}, unsigned long int @var{exp})
+@deftypefunx void mpz_ui_pow_ui (mpz_t @var{rop}, unsigned long int @var{base}, unsigned long int @var{exp})
+Set @var{rop} to @var{base} raised to @var{exp}.
+@end deftypefun
+
+@deftypefun void mpz_fac_ui (mpz_t @var{rop}, unsigned long int @var{op})
+Set @var{rop} to @var{op}!, the factorial of @var{op}.
+@end deftypefun
+
+@deftypefun void mpz_gcd (mpz_t @var{rop}, mpz_t @var{op1}, mpz_t @var{op2})
+Set @var{rop} to the greatest common divisor of @var{op1} and @var{op2}.
+@end deftypefun
+
+@deftypefun {unsigned long int} mpz_gcd_ui (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2})
+Compute the greatest common divisor of @var{op1} and @var{op2}. If
+@var{rop} is not NULL, store the result there.
+
+If the result is small enough to fit in an @code{unsigned long int}, it is
+returned. If the result does not fit, 0 is returned, and the result is equal
+to the argument @var{op1}. Note that the result will always fit if @var{op2}
+is non-zero.
+@end deftypefun
+
+@deftypefun void mpz_gcdext (mpz_t @var{g}, mpz_t @var{s}, mpz_t @var{t}, mpz_t @var{a}, mpz_t @var{b})
+Compute @var{g}, @var{s}, and @var{t}, such that @var{a}@var{s} +
+@var{b}@var{t} = @var{g} = @code{gcd} (@var{a}, @var{b}). If @var{t} is
+NULL, that argument is not computed.
+@end deftypefun
+
+@deftypefun int mpz_invert (mpz_t @var{rop}, mpz_t @var{op1}, mpz_t @var{op2})
+Compute the inverse of @var{op1} modulo @var{op2} and put the result in
+@var{rop}. Return non-zero if an inverse exist, zero otherwise. When the
+function returns zero, do not assume anything about the value in @var{rop}.
+@end deftypefun
+
+@deftypefun void mpz_neg (mpz_t @var{rop}, mpz_t @var{op})
+Set @var{rop} to @minus{}@var{op}.
+@end deftypefun
+
+@deftypefun void mpz_abs (mpz_t @var{rop}, mpz_t @var{op})
+Set @var{rop} to the absolute value of @var{op}.
+@end deftypefun
+
+@deftypefun void mpz_mul_2exp (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2})
+Set @var{rop} to @var{op1} times 2 raised to @var{op2}. This operation can
+also be defined as a left shift, @var{op2} steps.
+@end deftypefun
+
+@deftypefun void mpz_tdiv_q_2exp (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2})
+Set @var{rop} to @var{op1} divided by 2 raised to @var{op2}. The quotient is
+rounded towards 0.
+@end deftypefun
+
+@deftypefun void mpz_fdiv_q_2exp (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2})
+Set @var{rop} to @var{op1} divided by 2 raised to @var{op2}. The quotient is
+rounded towards @minus{}infinity.
+@end deftypefun
+
+@deftypefun void mpz_tdiv_r_2exp (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2})
+Divide @var{op1} by (2 raised to @var{op2}) and put the remainder in
+@var{rop}. The sign of @var{rop} will have the same sign as @var{op1}, unless
+is becomes zero.
+@end deftypefun
+
+@deftypefun void mpz_fdiv_r_2exp (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2})
+Divide @var{op1} by (2 raised to @var{op2}) and put the remainder in
+@var{rop}. The sign of @var{rop} will always be positive.
+
+This operation can also be defined as masking of the @var{op2} least
+significant bits.
+@end deftypefun
+
+@node Comparison Functions, Integer Logic and Bit Fiddling, Integer Arithmetic, Integer Functions
+@comment node-name, next, previous, up
+@section Comparison Functions
+
+@deftypefun int mpz_cmp (mpz_t @var{op1}, mpz_t @var{op2})
+@deftypefunx int mpz_cmp_ui (mpz_t @var{op1}, unsigned long int @var{op2})
+@deftypefunx int mpz_cmp_si (mpz_t @var{op1}, signed long int @var{op2})
+Compare @var{op1} and @var{op2}. Return a positive value if @var{op1} >
+@var{op2}, zero if @var{op1} = @var{op2}, and a negative value if @var{op1}
+< @var{op2}.
+@end deftypefun
+
+@deftypefun int mpz_sgn (mpz_t @var{op})
+Return +1 if @var{op} > 0, 0 if @var{op} = 0, and @minus{}1 if @var{op} < 0.
+@end deftypefun
+
+@node Integer Logic and Bit Fiddling, I/O of Integers, Comparison Functions, Integer Functions
+@comment node-name, next, previous, up
+@section Logical and Bit Manipulation Functions
+@cindex Logical functions
+@cindex Bit manipulation functions
+
+These functions behave as if two's complement arithmetic were used (although
+sign-magnitude is used by the actual implementation).
+
+@deftypefun void mpz_and (mpz_t @var{rop}, mpz_t @var{op1}, mpz_t @var{op2})
+Set @var{rop} to @var{op1} logical-and @var{op2}.
+@end deftypefun
+
+@deftypefun void mpz_ior (mpz_t @var{rop}, mpz_t @var{op1}, mpz_t @var{op2})
+Set @var{rop} to @var{op1} inclusive-or @var{op2}.
+@end deftypefun
+
+@c @deftypefun void mpz_xor (mpz_t @var{rop}, mpz_t @var{op1}, mpz_t @var{op2})
+@c Set @var{rop} to @var{op1} exclusive-or @var{op2}.
+@c @end deftypefun
+
+@deftypefun void mpz_com (mpz_t @var{rop}, mpz_t @var{op})
+Set @var{rop} to the one's complement of @var{op}.
+@end deftypefun
+
+@deftypefun {unsigned long int} mpz_popcount (mpz_t @var{op})
+For non-negative numbers, return the population count of @var{op}. For
+negative numbers, return the largest possible value (@var{MAX_ULONG}).
+@end deftypefun
+
+@deftypefun {unsigned long int} mpz_hamdist (mpz_t @var{op1}, mpz_t @var{op2})
+If @var{op1} and @var{op2} are both non-negative, return the hamming distance
+between the two operands. Otherwise, return the largest possible value
+(@var{MAX_ULONG}).
+
+It is possible to extend this function to return a useful value when the
+operands are both negative, but the current implementation returns
+@var{MAX_ULONG} in this case. @strong{Do not depend on this behavior, since
+it will change in future versions of the library.}
+@end deftypefun
+
+@deftypefun {unsigned long int} mpz_scan0 (mpz_t @var{op}, unsigned long int @var{starting_bit})
+Scan @var{op}, starting with bit @var{starting_bit}, towards more significant
+bits, until the first clear bit is found. Return the index of the found bit.
+@end deftypefun
+
+@deftypefun {unsigned long int} mpz_scan1 (mpz_t @var{op}, unsigned long int @var{starting_bit})
+Scan @var{op}, starting with bit @var{starting_bit}, towards more significant
+bits, until the first set bit is found. Return the index of the found bit.
+@end deftypefun
+
+@deftypefun void mpz_setbit (mpz_t @var{rop}, unsigned long int @var{bit_index})
+Set bit @var{bit_index} in @var{op1}.
+@end deftypefun
+
+@deftypefun void mpz_clrbit (mpz_t @var{rop}, unsigned long int @var{bit_index})
+Clear bit @var{bit_index} in @var{op1}.
+@end deftypefun
+
+@node I/O of Integers, Miscellaneous Integer Functions, Integer Logic and Bit Fiddling, Integer Functions
+@comment node-name, next, previous, up
+@section Input and Output Functions
+@cindex Integer input and output functions
+@cindex Input functions
+@cindex Output functions
+@cindex I/O functions
+
+Functions that perform input from a stdio stream, and functions that output to
+a stdio stream. Passing a NULL pointer for a @var{stream} argument to any of
+these functions will make them read from @code{stdin} and write to
+@code{stdout}, respectively.
+
+When using any of these functions, it is a good idea to include @file{stdio.h}
+before @file{gmp.h}, since that will allow @file{gmp.h} to define prototypes
+for these functions.
+
+@deftypefun size_t mpz_out_str (FILE *@var{stream}, int @var{base}, mpz_t @var{op})
+Output @var{op} on stdio stream @var{stream}, as a string of digits in base
+@var{base}. The base may vary from 2 to 36.
+
+Return the number of bytes written, or if an error occurred, return 0.
+@end deftypefun
+
+@deftypefun size_t mpz_inp_str (mpz_t @var{rop}, FILE *@var{stream}, int @var{base})
+Input a possibly white-space preceded string in base @var{base} from stdio
+stream @var{stream}, and put the read integer in @var{rop}. The base may vary
+from 2 to 36. If @var{base} is 0, the actual base is determined from the
+leading characters: if the first two characters are `0x' or `0X', hexadecimal
+is assumed, otherwise if the first character is `0', octal is assumed,
+otherwise decimal is assumed.
+
+Return the number of bytes read, or if an error occurred, return 0.
+@end deftypefun
+
+@deftypefun size_t mpz_out_raw (FILE *@var{stream}, mpz_t @var{op})
+Output @var{op} on stdio stream @var{stream}, in raw binary format. The
+integer is written in a portable format, with 4 bytes of size information, and
+that many bytes of limbs. Both the size and the limbs are written in
+decreasing significance order (i.e., in big-endian).
+
+The output can be read with @code{mpz_inp_raw}.
+
+Return the number of bytes written, or if an error occurred, return 0.
+
+The output of this can not be read by @code{mpz_inp_raw} from GMP 1, because
+of changes necessary for compatibility between 32-bit and 64-bit machines.
+@end deftypefun
+
+@deftypefun size_t mpz_inp_raw (mpz_t @var{rop}, FILE *@var{stream})
+Input from stdio stream @var{stream} in the format written by
+@code{mpz_out_raw}, and put the result in @var{rop}. Return the number of
+bytes read, or if an error occurred, return 0.
+
+This routine can read the output from @code{mpz_out_raw} also from GMP 1, in
+spite of changes necessary for compatibility between 32-bit and 64-bit
+machines.
+@end deftypefun
+
+
+@node Miscellaneous Integer Functions,, I/O of Integers, Integer Functions
+@comment node-name, next, previous, up
+@section Miscellaneous Functions
+@cindex Miscellaneous integer functions
+
+@deftypefun void mpz_random (mpz_t @var{rop}, mp_size_t @var{max_size})
+Generate a random integer of at most @var{max_size} limbs. The generated
+random number doesn't satisfy any particular requirements of randomness.
+Negative random numbers are generated when @var{max_size} is negative.
+@end deftypefun
+
+@deftypefun void mpz_random2 (mpz_t @var{rop}, mp_size_t @var{max_size})
+Generate a random integer of at most @var{max_size} limbs, with long strings
+of zeros and ones in the binary representation. Useful for testing functions
+and algorithms, since this kind of random numbers have proven to be more
+likely to trigger corner-case bugs. Negative random numbers are generated
+when @var{max_size} is negative.
+@end deftypefun
+
+@deftypefun size_t mpz_size (mpz_t @var{op})
+Return the size of @var{op} measured in number of limbs. If @var{op} is zero,
+the returned value will be zero.
+@c (@xref{Nomenclature}, for an explanation of the concept @dfn{limb}.)
+
+@strong{This function is obsolete. It will disappear from future MP
+releases.}
+@end deftypefun
+
+@deftypefun size_t mpz_sizeinbase (mpz_t @var{op}, int @var{base})
+Return the size of @var{op} measured in number of digits in base @var{base}.
+The base may vary from 2 to 36. The returned value will be exact or 1 too
+big. If @var{base} is a power of 2, the returned value will always be exact.
+
+This function is useful in order to allocate the right amount of space before
+converting @var{op} to a string. The right amount of allocation is normally
+two more than the value returned by @code{mpz_sizeinbase} (one extra for a
+minus sign and one for the terminating '\0').
+@end deftypefun
+
+
+@node Rational Number Functions, Floating-point Functions, Integer Functions, Top
+@comment node-name, next, previous, up
+@chapter Rational Number Functions
+@cindex Rational number functions
+
+This chapter describes the MP functions for performing arithmetic on rational
+numbers. These functions start with the prefix @code{mpq_}.
+
+Rational numbers are stored in objects of type @code{mpq_t}.
+
+All rational arithmetic functions assume operands have a canonical form, and
+canonicalize their result. The canonical from means that the denominator and
+the numerator have no common factors, and that the denominator is positive.
+Zero has the unique representation 0/1.
+
+Pure assignment functions do not canonicalize the assigned variable. It is
+the responsibility of the user to canonicalize the assigned variable before
+any arithmetic operations are performed on that variable. @strong{Note that
+this is an incompatible change from version 1 of the library.}
+
+@deftypefun void mpq_canonicalize (mpq_t @var{op})
+Remove any factors that are common to the numerator and denominator of
+@var{op}, and make the denominator positive.
+@end deftypefun
+
+@menu
+* Initializing Rationals::
+* Assigning Rationals::
+* Simultaneous Integer Init & Assign::
+* Comparing Rationals::
+* Applying Integer Functions::
+* Miscellaneous Rational Functions::
+@end menu
+
+@node Initializing Rationals, Assigning Rationals, Rational Number Functions, Rational Number Functions
+@comment node-name, next, previous, up
+@section Initialization and Assignment Functions
+
+@deftypefun void mpq_init (mpq_t @var{dest_rational})
+Initialize @var{dest_rational} and set it to 0/1. Each variable should
+normally only be initialized once, or at least cleared out (using the function
+@code{mpq_clear}) between each initialization.
+@end deftypefun
+
+@deftypefun void mpq_clear (mpq_t @var{rational_number})
+Free the space occupied by @var{rational_number}. Make sure to call this
+function for all @code{mpq_t} variables when you are done with them.
+@end deftypefun
+
+@deftypefun void mpq_set (mpq_t @var{rop}, mpq_t @var{op})
+Assign @var{rop} from @var{op}.
+@end deftypefun
+
+@deftypefun void mpq_set_ui (mpq_t @var{rop}, unsigned long int @var{op1}, unsigned long int @var{op2})
+@deftypefunx void mpq_set_si (mpq_t @var{rop}, signed long int @var{op1}, unsigned long int @var{op2})
+Set the value of @var{rop} to @var{op1}/@var{op2}. Note that if @var{op1} and
+@var{op2} have common factors, @var{rop} has to be passed to
+@code{mpq_canonicalize} before any operations are performed on @var{rop}.
+@end deftypefun
+
+@node Assigning Rationals, Comparing Rationals, Initializing Rationals, Rational Number Functions
+@comment node-name, next, previous, up
+@section Arithmetic Functions
+
+@deftypefun void mpq_add (mpq_t @var{sum}, mpq_t @var{addend1}, mpq_t @var{addend2})
+Set @var{sum} to @var{addend1} + @var{addend2}.
+@end deftypefun
+
+@deftypefun void mpq_sub (mpq_t @var{difference}, mpq_t @var{minuend}, mpq_t @var{subtrahend})
+Set @var{difference} to @var{minuend} @minus{} @var{subtrahend}.
+@end deftypefun
+
+@deftypefun void mpq_mul (mpq_t @var{product}, mpq_t @var{multiplier}, mpq_t @var{multiplicand})
+Set @var{product} to @var{multiplier} times @var{multiplicand}
+@end deftypefun
+
+@deftypefun void mpq_div (mpq_t @var{quotient}, mpq_t @var{dividend}, mpq_t @var{divisor})
+Set @var{quotient} to @var{dividend} / @var{divisor}.
+@end deftypefun
+
+@deftypefun void mpq_neg (mpq_t @var{negated_operand}, mpq_t @var{operand})
+Set @var{negated_operand} to @minus{}@var{operand}.
+@end deftypefun
+
+@deftypefun void mpq_inv (mpq_t @var{inverted_number}, mpq_t @var{number})
+Set @var{inverted_number} to 1 / @var{number}. If the new denominator is
+zero, this routine will divide by zero.
+@end deftypefun
+
+@node Comparing Rationals, Applying Integer Functions, Assigning Rationals, Rational Number Functions
+@comment node-name, next, previous, up
+@section Comparison Functions
+
+@deftypefun int mpq_cmp (mpq_t @var{op1}, mpq_t @var{op2})
+Compare @var{op1} and @var{op2}. Return a positive value if @var{op1} >
+@var{op2}, zero if @var{op1} = @var{op2}, and a negative value if @var{op1} <
+@var{op2}.
+
+To determine if two rationals are equal, @code{mpq_equal} is faster than this
+@code{mpq_cmp}.
+@end deftypefun
+
+@deftypefun int mpq_cmp_ui (mpq_t @var{op1}, unsigned long int @var{num2}, unsigned long int @var{den2})
+Compare @var{op1} and @var{num2}/@var{den2}. Return a positive value if
+@var{op1} > @var{num2}/@var{den2}, zero if @var{op1} = @var{num2}/@var{den2},
+and a negative value if @var{op1} < @var{num2}/@var{den2}.
+
+This routine allows that @var{num2} and @var{den2} have common factors.
+@end deftypefun
+
+@deftypefun int mpq_sgn (mpq_t @var{op})
+Return +1 if @var{op} > 0, 0 if @var{op} = 0, and @minus{}1 if @var{op} < 0.
+@end deftypefun
+
+@deftypefun int mpq_equal (mpq_t @var{op1}, mpq_t @var{op2})
+Return non-zero if @var{op1} and @var{op2} are equal, zero if they are
+non-equal. Although @code{mpq_cmp} can be used for the same purpose, this
+function is much faster.
+@end deftypefun
+
+@node Applying Integer Functions, Miscellaneous Rational Functions, Comparing Rationals, Rational Number Functions
+@comment node-name, next, previous, up
+@section Applying Integer Functions to Rationals
+
+The set of @code{mpq} functions is quite small. In particular, there are no
+functions for either input or output. But there are two macros that allow us
+to apply any @code{mpz} function on the numerator or denominator of a rational
+number. If these macros are used to assign to the rational number,
+@code{mpq_canonicalize} normally need to be called afterwards.
+
+@deftypefn Macro mpz_t mpq_numref (mpq_t @var{op})
+@deftypefnx Macro mpz_t mpq_denref (mpq_t @var{op})
+Return a reference to the numerator and denominator of @var{op}, respectively.
+The @code{mpz} functions can be used on the result of these macros.
+@end deftypefn
+
+@need 2000
+@node Miscellaneous Rational Functions, , Applying Integer Functions, Rational Number Functions
+@comment node-name, next, previous, up
+@section Miscellaneous Functions
+
+These functions assign between either the numerator or denominator of a
+rational, and an integer. Instead of using these functions, it is preferable
+to use the more general mechanisms @code{mpq_numref} and @code{mpq_denref},
+together with @code{mpz_set}.
+
+@deftypefun void mpq_set_num (mpq_t @var{rational}, mpz_t @var{numerator})
+Copy @var{numerator} to the numerator of @var{rational}. When this risks to
+make the numerator and denominator of @var{rational} have common factors, you
+have to pass @var{rational} to @code{mpq_canonicalize} before any operations
+are performed on @var{rational}.
+
+This function is equivalent to
+@code{mpz_set (mpq_numref (@var{rational}), @var{numerator})}.
+@end deftypefun
+
+@deftypefun void mpq_set_den (mpq_t @var{rational}, mpz_t @var{denominator})
+Copy @var{denominator} to the denominator of @var{rational}. When this risks
+to make the numerator and denominator of @var{rational} have common factors,
+or if the denominator might be negative, you have to pass @var{rational} to
+@code{mpq_canonicalize} before any operations are performed on @var{rational}.
+
+@strong{In version 1 of the library, negative denominators were handled by
+copying the sign to the numerator. That is no longer done.}
+
+This function is equivalent to
+@code{mpz_set (mpq_denref (@var{rational}), @var{denominators})}.
+@end deftypefun
+
+@deftypefun void mpq_get_num (mpz_t @var{numerator}, mpq_t @var{rational})
+Copy the numerator of @var{rational} to the integer @var{numerator}, to
+prepare for integer operations on the numerator.
+
+This function is equivalent to
+@code{mpz_set (@var{numerator}, mpq_numref (@var{rational}))}.
+@end deftypefun
+
+@deftypefun void mpq_get_den (mpz_t @var{denominator}, mpq_t @var{rational})
+Copy the denominator of @var{rational} to the integer @var{denominator}, to
+prepare for integer operations on the denominator.
+
+This function is equivalent to
+@code{mpz_set (@var{denominator}, mpq_denref (@var{rational}))}.
+@end deftypefun
+
+
+@node Floating-point Functions, Low-level Functions, Rational Number Functions, Top
+@comment node-name, next, previous, up
+@chapter Floating-point Functions
+@cindex Floating-point functions
+@cindex Float functions
+
+This is a description of the @emph{preliminary} interface for floating-point
+arithmetic in GNU MP 2.
+
+The floating-point functions expect arguments of type @code{mpf_t}.
+
+The MP floating-point functions have an interface that is similar to the MP
+integer functions. The function prefix for floating-point operations is
+@code{mpf_}.
+
+There is one significant characteristic of floating-point numbers that has
+motivated a difference between this function class and other MP function
+classes: the inherent inexactness of floating point arithmetic. The user has
+to specify the precision of each variable. A computation that assigns a
+variable will take place with the precision of the assigned variable; the
+precision of variables used as input is ignored.
+
+@cindex User-defined precision
+The precision of a calculation is defined as follows: Compute the requested
+operation exactly (with ``infinite precision''), and truncate the result to
+the destination variable precision. Even if the user has asked for a very
+high precision, MP will not calculate with superfluous digits. For example,
+if two low-precision numbers of nearly equal magnitude are added, the
+precision of the result will be limited to what is required to represent the
+result accurately.
+
+The MP floating-point functions are @emph{not} intended as a smooth extension
+to the IEEE P754 arithmetic. Specifically, the results obtained on one
+computer often differs from the results obtained on a computer with a
+different word size.
+
+@menu
+* Initializing Floats::
+* Assigning Floats::
+* Simultaneous Float Init & Assign::
+* Converting Floats::
+* Float Arithmetic::
+* Float Comparison::
+* I/O of Floats::
+* Miscellaneous Float Functions::
+@end menu
+
+@node Initializing Floats, Assigning Floats, , Floating-point Functions
+@comment node-name, next, previous, up
+@section Initialization and Assignment Functions
+
+@deftypefun void mpf_set_default_prec (unsigned long int @var{prec})
+Set the default precision to be @strong{at least} @var{prec} bits. All
+subsequent calls to @code{mpf_init} will use this precision, but previously
+initialized variables are unaffected.
+@end deftypefun
+
+An @code{mpf_t} object must be initialized before storing the first value in
+it. The functions @code{mpf_init} and @code{mpf_init2} are used for that
+purpose.
+
+@deftypefun void mpf_init (mpf_t @var{x})
+Initialize @var{x} to 0. Normally, a variable should be initialized once only
+or at least be cleared, using @code{mpf_clear}, between initializations. The
+precision of @var{x} is undefined unless a default precision has already been
+established by a call to @code{mpf_set_default_prec}.
+@end deftypefun
+
+@deftypefun void mpf_init2 (mpf_t @var{x}, unsigned long int @var{prec})
+Initialize @var{x} to 0 and set its precision to be @strong{at least}
+@var{prec} bits. Normally, a variable should be initialized once only or at
+least be cleared, using @code{mpf_clear}, between initializations.
+@end deftypefun
+
+@deftypefun void mpf_clear (mpf_t @var{x})
+Free the space occupied by @var{x}. Make sure to call this function for all
+@code{mpf_t} variables when you are done with them.
+@end deftypefun
+
+Here is an example on how to initialize floating-point variables:
+@example
+@{
+ mpf_t x, y;
+ mpf_init (x); /* use default precision */
+ mpf_init2 (y, 256); /* precision @emph{at least} 256 bits */
+ @dots{}
+ /* Unless the program is about to exit, do ... */
+ mpf_clear (x);
+ mpf_clear (y);
+@}
+@end example
+
+The following three functions are useful for changing the precision during a
+calculation. A typical use would be for adjusting the precision gradually in
+iterative algorithms like Newton-Raphson, making the computation precision
+closely match the actual accurate part of the numbers.
+
+@deftypefun void mpf_set_prec (mpf_t @var{rop}, unsigned long int @var{prec})
+Set the precision of @var{rop} to be @strong{at least} @var{prec} bits.
+Since changing the precision involves calls to @code{realloc}, this routine
+should not be called in a tight loop.
+@end deftypefun
+
+@deftypefun {unsigned long int} mpf_get_prec (mpf_t @var{op})
+Return the precision actually used for assignments of @var{op}.
+@end deftypefun
+
+@deftypefun void mpf_set_prec_raw (mpf_t @var{rop}, unsigned long int @var{prec})
+Set the precision of @var{rop} to be @strong{at least} @var{prec} bits. This
+is a low-level function that does not change the allocation. The @var{prec}
+argument must not be larger that the precision previously returned by
+@code{mpf_get_prec}. It is crucial that the precision of @var{rop} is
+ultimately reset to exactly the value returned by @code{mpf_get_prec}.
+@end deftypefun
+
+
+@node Assigning Floats, Simultaneous Float Init & Assign, Initializing Floats, Floating-point Functions
+@comment node-name, next, previous, up
+@subsection Assignment Functions
+@cindex Float assignment functions
+
+These functions assign new values to already initialized floats
+(@pxref{Initializing Floats}).
+
+@deftypefun void mpf_set (mpf_t @var{rop}, mpf_t @var{op})
+@deftypefunx void mpf_set_ui (mpf_t @var{rop}, unsigned long int @var{op})
+@deftypefunx void mpf_set_si (mpf_t @var{rop}, signed long int @var{op})
+@deftypefunx void mpf_set_d (mpf_t @var{rop}, double @var{op})
+Set the value of @var{rop} from @var{op}.
+@end deftypefun
+
+@deftypefun int mpf_set_str (mpf_t @var{rop}, char *@var{str}, int @var{base})
+Set the value of @var{rop} from the string in @var{str}. The string is of the
+form @samp{M@@N} or, if the base is 10 or less, alternatively @samp{MeN}.
+@samp{M} is the mantissa and @samp{N} is the exponent. The mantissa is always
+in the specified base. The exponent is either in the specified base or, if
+@var{base} is negative, in decimal.
+
+The argument @var{base} may be in the ranges 2 to 36, or @minus{}36 to
+@minus{}2. Negative values are used to specify that the exponent is in
+decimal.
+
+Unlike the corresponding @code{mpz} function, the base will not be determined
+from the leading characters of the string if @var{base} is 0. This is so that
+numbers like @samp{0.23} are not interpreted as octal.
+
+White space is allowed in the string, and is simply ignored.
+
+This function returns 0 if the entire string up to the '\0' is a valid number
+in base @var{base}. Otherwise it returns @minus{}1.
+@end deftypefun
+
+
+@node Simultaneous Float Init & Assign, Converting Floats, Assigning Floats, Floating-point Functions
+@comment node-name, next, previous, up
+@subsection Combined Initialization and Assignment Functions
+@cindex Initialization and assignment functions
+
+For convenience, MP provides a parallel series of initialize-and-set functions
+which initialize the output and then store the value there. These functions'
+names have the form @code{mpf_init_set@dots{}}
+
+Once the float has been initialized by any of the @code{mpf_init_set@dots{}}
+functions, it can be used as the source or destination operand for the ordinary
+float functions. Don't use an initialize-and-set function on a variable
+already initialized!
+
+@deftypefun void mpf_init_set (mpf_t @var{rop}, mpf_t @var{op})
+@deftypefunx void mpf_init_set_ui (mpf_t @var{rop}, unsigned long int @var{op})
+@deftypefunx void mpf_init_set_si (mpf_t @var{rop}, signed long int @var{op})
+@deftypefunx void mpf_init_set_d (mpf_t @var{rop}, double @var{op})
+Initialize @var{rop} and set its value from @var{op}.
+
+The precision of @var{rop} will be taken from the active default precision, as
+set by @code{mpf_set_default_prec}.
+@end deftypefun
+
+@deftypefun int mpf_init_set_str (mpf_t @var{rop}, char *@var{str}, int @var{base})
+Initialize @var{rop} and set its value from the string in @var{str}. See
+@code{mpf_set_str} above for details on the assignment operation.
+
+Note that @var{rop} is initialized even if an error occurs. (I.e., you have to
+call @code{mpf_clear} for it.)
+
+The precision of @var{rop} will be taken from the active default precision, as
+set by @code{mpf_set_default_prec}.
+@end deftypefun
+
+
+@node Converting Floats, Float Arithmetic, Simultaneous Float Init & Assign, Floating-point Functions
+@comment node-name, next, previous, up
+@section Conversion Functions
+@cindex Conversion functions
+
+@deftypefun {char *} mpf_get_str (char *@var{str}, mp_exp_t *@var{expptr}, int @var{base}, size_t @var{n_digits}, mpf_t @var{op})
+Convert @var{op} to a string of digits in base @var{base}. The base may vary
+from 2 to 36. Generate at most @var{n_digits} significant digits, or if
+@var{n_digits} is 0, the maximum number of digits accurately representable by
+@var{op}.
+
+If @var{str} is NULL, space for the mantissa is allocated using the default
+allocation function, and a pointer to the string is returned.
+
+If @var{str} is not NULL, it should point to a block of storage enough large
+for the mantissa, i.e., @var{n_digits} + 2. The two extra bytes are for a
+possible minus sign, and for the terminating null character.
+
+The exponent is written through the pointer @var{expptr}.
+
+If @var{n_digits} is 0, the maximum number of digits meaningfully achievable
+from the precision of @var{op} will be generated. Note that the space
+requirements for @var{str} in this case will be impossible for the user to
+predetermine. Therefore, you need to pass NULL for the string argument
+whenever @var{n_digits} is 0.
+
+The generated string is a fraction, with an implicit radix point immediately
+to the left of the first digit. For example, the number 3.1416 would be
+returned as "31416" in the string and 1 written at @var{expptr}.
+@end deftypefun
+
+
+@node Float Arithmetic, Float Comparison, Converting Floats, Floating-point Functions
+@comment node-name, next, previous, up
+@section Arithmetic Functions
+@cindex Float arithmetic functions
+@cindex Arithmetic functions
+
+@deftypefun void mpf_add (mpf_t @var{rop}, mpf_t @var{op1}, mpf_t @var{op2})
+@deftypefunx void mpf_add_ui (mpf_t @var{rop}, mpf_t @var{op1}, unsigned long int @var{op2})
+Set @var{rop} to @var{op1} + @var{op2}.
+@end deftypefun
+
+@deftypefun void mpf_sub (mpf_t @var{rop}, mpf_t @var{op1}, mpf_t @var{op2})
+@deftypefunx void mpf_ui_sub (mpf_t @var{rop}, unsigned long int @var{op1}, mpf_t @var{op2})
+@deftypefunx void mpf_sub_ui (mpf_t @var{rop}, mpf_t @var{op1}, unsigned long int @var{op2})
+Set @var{rop} to @var{op1} @minus{} @var{op2}.
+@end deftypefun
+
+@deftypefun void mpf_mul (mpf_t @var{rop}, mpf_t @var{op1}, mpf_t @var{op2})
+@deftypefunx void mpf_mul_ui (mpf_t @var{rop}, mpf_t @var{op1}, unsigned long int @var{op2})
+Set @var{rop} to @var{op1} times @var{op2}.
+@end deftypefun
+
+Division is undefined if the divisor is zero, and passing a zero divisor to
+the divide functions will make these functions intentionally divide by zero.
+This gives the user the possibility to handle arithmetic exceptions in these
+functions in the same manner as other arithmetic exceptions.
+
+@deftypefun void mpf_div (mpf_t @var{rop}, mpf_t @var{op1}, mpf_t @var{op2})
+@deftypefunx void mpf_ui_div (mpf_t @var{rop}, unsigned long int @var{op1}, mpf_t @var{op2})
+@deftypefunx void mpf_div_ui (mpf_t @var{rop}, mpf_t @var{op1}, unsigned long int @var{op2})
+Set @var{rop} to @var{op1} / @var{op2}.
+rounded towards 0.
+@end deftypefun
+
+@deftypefun void mpf_sqrt (mpf_t @var{rop}, mpf_t @var{op})
+@deftypefunx void mpf_sqrt_ui (mpf_t @var{rop}, unsigned long int @var{op})
+Set @var{rop} to the square root of @var{op}.
+@end deftypefun
+
+@deftypefun void mpf_pow_ui (mpf_t @var{rop}, mpf_t @var{op1}, unsigned long int @var{op2})
+Set @var{rop} to @var{op1} raised to @var{op2}.
+@end deftypefun
+
+@deftypefun void mpf_neg (mpf_t @var{rop}, mpf_t @var{op})
+Set @var{rop} to @minus{}@var{op}.
+@end deftypefun
+
+@deftypefun void mpf_abs (mpf_t @var{rop}, mpf_t @var{op})
+Set @var{rop} to the absolute value of @var{op}.
+@end deftypefun
+
+@deftypefun void mpf_mul_2exp (mpf_t @var{rop}, mpf_t @var{op1}, unsigned long int @var{op2})
+Set @var{rop} to @var{op1} times 2 raised to @var{op2}.
+@end deftypefun
+
+@deftypefun void mpf_div_2exp (mpf_t @var{rop}, mpf_t @var{op1}, unsigned long int @var{op2})
+Set @var{rop} to @var{op1} divided by 2 raised to @var{op2}.
+@end deftypefun
+
+@node Float Comparison, I/O of Floats, Float Arithmetic, Floating-point Functions
+@comment node-name, next, previous, up
+@section Comparison Functions
+@cindex Float comparisons functions
+@cindex Comparison functions
+
+@deftypefun int mpf_cmp (mpf_t @var{op1}, mpf_t @var{op2})
+@deftypefunx int mpf_cmp_ui (mpf_t @var{op1}, unsigned long int @var{op2})
+@deftypefunx int mpf_cmp_si (mpf_t @var{op1}, signed long int @var{op2})
+Compare @var{op1} and @var{op2}. Return a positive value if @var{op1} >
+@var{op2}, zero if @var{op1} = @var{op2}, and a negative value if @var{op1} <
+@var{op2}.
+@end deftypefun
+
+@deftypefun int mpf_eq (mpf_t @var{op1}, mpf_t @var{op2}, unsigned long int op3)
+Return non-zero if the first @var{op3} bits of @var{op1} and @var{op2} are
+equal, zero otherwise. I.e., test of @var{op1} and @var{op2} are
+approximately equal.
+@end deftypefun
+
+@deftypefun void mpf_reldiff (mpf_t @var{rop}, mpf_t @var{op1}, mpf_t @var{op2})
+Compute the relative difference between @var{op1} and @var{op2} and store the
+result in @var{rop}.
+@end deftypefun
+
+@deftypefun int mpf_sgn (mpf_t @var{op})
+Return +1 if @var{op} > 0, 0 if @var{op} = 0, and @minus{}1 if @var{op} < 0.
+@end deftypefun
+
+@node I/O of Floats, Miscellaneous Float Functions, Float Comparison, Floating-point Functions
+@comment node-name, next, previous, up
+@section Input and Output Functions
+@cindex Float input and output functions
+@cindex Input functions
+@cindex Output functions
+@cindex I/O functions
+
+Functions that perform input from a stdio stream, and functions that output to
+a stdio stream. Passing a NULL pointer for a @var{stream} argument to any of
+these functions will make them read from @code{stdin} and write to
+@code{stdout}, respectively.
+
+When using any of these functions, it is a good idea to include @file{stdio.h}
+before @file{gmp.h}, since that will allow @file{gmp.h} to define prototypes
+for these functions.
+
+@deftypefun size_t mpf_out_str (FILE *@var{stream}, int @var{base}, size_t @var{n_digits}, mpf_t @var{op})
+Output @var{op} on stdio stream @var{stream}, as a string of digits in
+base @var{base}. The base may vary from 2 to 36. Print at most
+@var{n_digits} significant digits, or if @var{n_digits} is 0, the maximum
+number of digits accurately representable by @var{op}.
+
+In addition to the significant digits, a leading @samp{0.} and a trailing
+exponent, in the form @samp{@@NNN}, are printed.
+
+Return the number of bytes written, or if an error occurred, return 0.
+@end deftypefun
+
+@deftypefun size_t mpf_inp_str (mpf_t @var{rop}, FILE *@var{stream}, int @var{base})
+Input a string in base @var{base} from stdio stream @var{stream}, and put the
+read float in @var{rop}. The string is of the form @samp{M@@N} or, if the
+base is 10 or less, alternatively @samp{MeN}. @samp{M} is the mantissa and
+@samp{N} is the exponent. The mantissa is always in the specified base. The
+exponent is either in the specified base or, if @var{base} is negative, in
+decimal.
+
+The argument @var{base} may be in the ranges 2 to 36, or @minus{}36 to
+@minus{}2. Negative values are used to specify that the exponent is in
+decimal.
+
+Unlike the corresponding @code{mpz} function, the base will not be determined
+from the leading characters of the string if @var{base} is 0. This is so that
+numbers like @samp{0.23} are not interpreted as octal.
+
+Return the number of bytes read, or if an error occurred, return 0.
+@end deftypefun
+
+@c @deftypefun void mpf_out_raw (FILE *@var{stream}, mpf_t @var{float})
+@c Output @var{float} on stdio stream @var{stream}, in raw binary
+@c format. The float is written in a portable format, with 4 bytes of
+@c size information, and that many bytes of limbs. Both the size and the
+@c limbs are written in decreasing significance order.
+@c @end deftypefun
+
+@c @deftypefun void mpf_inp_raw (mpf_t @var{float}, FILE *@var{stream})
+@c Input from stdio stream @var{stream} in the format written by
+@c @code{mpf_out_raw}, and put the result in @var{float}.
+@c @end deftypefun
+
+
+@node Miscellaneous Float Functions, , I/O of Floats, Floating-point Functions
+@comment node-name, next, previous, up
+@section Miscellaneous Functions
+@cindex Miscellaneous float functions
+
+@deftypefun void mpf_random2 (mpf_t @var{rop}, mp_size_t @var{max_size}, mp_exp_t @var{max_exp})
+Generate a random float of at most @var{max_size} limbs, with long strings of
+zeros and ones in the binary representation. The exponent of the number is in
+the interval @minus{}@var{exp} to @var{exp}. This function is useful for
+testing functions and algorithms, since this kind of random numbers have
+proven to be more likely to trigger corner-case bugs. Negative random numbers
+are generated when @var{max_size} is negative.
+@end deftypefun
+
+@c @deftypefun size_t mpf_size (mpf_t @var{op})
+@c Return the size of @var{op} measured in number of limbs. If @var{op} is
+@c zero, the returned value will be zero. (@xref{Nomenclature}, for an
+@c explanation of the concept @dfn{limb}.)
+@c
+@c @strong{This function is obsolete. It will disappear from future MP
+@c releases.}
+@c @end deftypefun
+
+@node Low-level Functions, BSD Compatible Functions, Floating-point Functions, Top
+@comment node-name, next, previous, up
+@chapter Low-level Functions
+@cindex Low-level functions
+
+This chapter describes low-level MP functions, used to implement the high-level
+MP functions, but also intended for time-critical user code.
+
+These functions start with the prefix @code{mpn_}.
+
+@c 1. Some of these function clobber input operands.
+@c
+
+The @code{mpn} functions are designed to be as fast as possible, @strong{not}
+to provide a coherent calling interface. The different functions have somewhat
+similar interfaces, but there are variations that make them hard to use. These
+functions do as little as possible apart from the real multiple precision
+computation, so that no time is spent on things that not all callers need.
+
+A source operand is specified by a pointer to the least significant limb and a
+limb count. A destination operand is specified by just a pointer. It is the
+responsibility of the caller to ensure that the destination has enough space
+for storing the result.
+
+With this way of specifying operands, it is possible to perform computations
+on subranges of an argument, and store the result into a subrange of a
+destination.
+
+A common requirement for all functions is that each source area needs at least
+one limb. No size argument may be zero.
+
+The @code{mpn} functions is the base for the implementation of the @code{mpz_},
+@code{mpf_}, and @code{mpq_} functions.
+
+This example adds the number beginning at @var{src1_ptr} and the number
+beginning at @var{src2_ptr} and writes the sum at @var{dest_ptr}. All areas
+have @var{size} limbs.
+
+@example
+cy = mpn_add_n (dest_ptr, src1_ptr, src2_ptr, size)
+@end example
+
+@noindent
+In the notation used here, a source operand is identified by the pointer to
+the least significant limb, and the limb count in braces. For example,
+@{s1_ptr, s1_size@}.
+
+@deftypefun mp_limb_t mpn_add_n (mp_limb_t * @var{dest_ptr}, const mp_limb_t * @var{src1_ptr}, const mp_limb_t * @var{src2_ptr}, mp_size_t @var{size})
+Add @{@var{src1_ptr}, @var{size}@} and @{@var{src2_ptr}, @var{size}@}, and
+write the @var{size} least significant limbs of the result to @var{dest_ptr}.
+Return carry, either 0 or 1.
+
+This is the lowest-level function for addition. It is the preferred function
+for addition, since it is written in assembly for most targets. For addition
+of a variable to itself (i.e., @var{src1_ptr} equals @var{src2_ptr}, use
+@code{mpn_lshift} with a count of 1 for optimal speed.
+@end deftypefun
+
+@deftypefun mp_limb_t mpn_add_1 (mp_limb_t * @var{dest_ptr}, const mp_limb_t * @var{src1_ptr}, mp_size_t @var{size}, mp_limb_t @var{src2_limb})
+Add @{@var{src1_ptr}, @var{size}@} and @var{src2_limb}, and write the
+@var{size} least significant limbs of the result to @var{dest_ptr}. Return
+carry, either 0 or 1.
+@end deftypefun
+
+@deftypefun mp_limb_t mpn_add (mp_limb_t * @var{dest_ptr}, const mp_limb_t * @var{src1_ptr}, mp_size_t @var{src1_size}, const mp_limb_t * @var{src2_ptr}, mp_size_t @var{src2_size})
+Add @{@var{src1_ptr}, @var{src1_size}@} and @{@var{src2_ptr},
+@var{src2_size}@}, and write the @var{src1_size} least significant limbs of
+the result to @var{dest_ptr}. Return carry, either 0 or 1.
+
+This function requires that @var{src1_size} is greater than or equal to
+@var{src2_size}.
+@end deftypefun
+
+@deftypefun mp_limb_t mpn_sub_n (mp_limb_t * @var{dest_ptr}, const mp_limb_t * @var{src1_ptr}, const mp_limb_t * @var{src2_ptr}, mp_size_t @var{size})
+Subtract @{@var{src2_ptr}, @var{src2_size}@} from @{@var{src1_ptr},
+@var{size}@}, and write the @var{size} least significant limbs of the result
+to @var{dest_ptr}. Return borrow, either 0 or 1.
+
+This is the lowest-level function for subtraction. It is the preferred
+function for subtraction, since it is written in assembly for most targets.
+@end deftypefun
+
+@deftypefun mp_limb_t mpn_sub_1 (mp_limb_t * @var{dest_ptr}, const mp_limb_t * @var{src1_ptr}, mp_size_t @var{size}, mp_limb_t @var{src2_limb})
+Subtract @var{src2_limb} from @{@var{src1_ptr}, @var{size}@}, and write the
+@var{size} least significant limbs of the result to @var{dest_ptr}. Return
+borrow, either 0 or 1.
+@end deftypefun
+
+@deftypefun mp_limb_t mpn_sub (mp_limb_t * @var{dest_ptr}, const mp_limb_t * @var{src1_ptr}, mp_size_t @var{src1_size}, const mp_limb_t * @var{src2_ptr}, mp_size_t @var{src2_size})
+Subtract @{@var{src2_ptr}, @var{src2_size}@} from @{@var{src1_ptr},
+@var{src1_size}@}, and write the @var{src1_size} least significant limbs of
+the result to @var{dest_ptr}. Return borrow, either 0 or 1.
+
+This function requires that @var{src1_size} is greater than or equal to
+@var{src2_size}.
+@end deftypefun
+
+@deftypefun void mpn_mul_n (mp_limb_t * @var{dest_ptr}, const mp_limb_t * @var{src1_ptr}, const mp_limb_t * @var{src2_ptr}, mp_size_t @var{size})
+Multiply @{@var{src1_ptr}, @var{size}@} and @{@var{src2_ptr}, @var{size}@},
+and write the @strong{entire} result to @var{dest_ptr}.
+
+The destination has to have space for 2@var{size} limbs, even if the
+significant result might be one limb smaller.
+@end deftypefun
+
+@deftypefun mp_limb_t mpn_mul_1 (mp_limb_t * @var{dest_ptr}, const mp_limb_t * @var{src1_ptr}, mp_size_t @var{size}, mp_limb_t @var{src2_limb})
+Multiply @{@var{src1_ptr}, @var{size}@} and @var{src2_limb}, and write the
+@var{size} least significant limbs of the product to @var{dest_ptr}. Return
+the most significant limb of the product.
+
+This is a low-level function that is a building block for general
+multiplication as well as other operations in MP. It is written in assembly
+for most targets.
+
+Don't call this function if @var{src2_limb} is a power of 2; use
+@code{mpn_lshift} with a count equal to the logarithm of @var{src2_limb}
+instead, for optimal speed.
+@end deftypefun
+
+@deftypefun mp_limb_t mpn_addmul_1 (mp_limb_t * @var{dest_ptr}, const mp_limb_t * @var{src1_ptr}, mp_size_t @var{size}, mp_limb_t @var{src2_limb})
+Multiply @{@var{src1_ptr}, @var{size}@} and @var{src2_limb}, and add the
+@var{size} least significant limbs of the product to @{@var{dest_ptr},
+@var{size}@} and write the result to @var{dest_ptr} @var{dest_ptr}. Return
+the most significant limb of the product, plus carry-out from the addition.
+
+This is a low-level function that is a building block for general
+multiplication as well as other operations in MP. It is written in assembly
+for most targets.
+@end deftypefun
+
+@deftypefun mp_limb_t mpn_submul_1 (mp_limb_t * @var{dest_ptr}, const mp_limb_t * @var{src1_ptr}, mp_size_t @var{size}, mp_limb_t @var{src2_limb})
+Multiply @{@var{src1_ptr}, @var{size}@} and @var{src2_limb}, and subtract the
+@var{size} least significant limbs of the product from @{@var{dest_ptr},
+@var{size}@} and write the result to @var{dest_ptr}. Return the most
+significant limb of the product, minus borrow-out from the subtraction.
+
+This is a low-level function that is a building block for general
+multiplication and division as well as other operations in MP. It is written
+in assembly for most targets.
+@end deftypefun
+
+@deftypefun mp_limb_t mpn_mul (mp_limb_t * @var{dest_ptr}, const mp_limb_t * @var{src1_ptr}, mp_size_t @var{src1_size}, const mp_limb_t * @var{src2_ptr}, mp_size_t @var{src2_size})
+Multiply @{@var{src1_ptr}, @var{src1_size}@} and @{@var{src2_ptr},
+@var{src2_size}@}, and write the result to @var{dest_ptr}. Return the most
+significant limb of the result.
+
+The destination has to have space for @var{src1_size} + @var{src1_size}
+limbs, even if the result might be one limb smaller.
+
+This function requires that @var{src1_size} is greater than or equal to
+@var{src2_size}. The destination must be distinct from either input operands.
+@end deftypefun
+
+@deftypefun mp_size_t mpn_divrem (mp_limb_t * @var{r1p}, mp_size_t @var{xsize}, mp_limb_t * @var{rs2p}, mp_size_t @var{rs2size}, const mp_limb_t * @var{s3p}, mp_size_t @var{s3size})
+Divide @{@var{rs2p}, @var{rs2size}@} by @{@var{s3p}, @var{s3size}@}, and
+write the quotient at @var{r1p}, with the exception of the most significant
+limb, which is returned. The remainder replaces the dividend at @var{rs2p}.
+
+In addition to an integer quotient, @var{xsize} fraction limbs are developed,
+and stored after the integral limbs. For most usages, @var{xsize} will be
+zero.
+
+It is required that @var{rs2size} is greater than or equal to @var{s3size}.
+It is required that the most significant bit of the divisor is set.
+
+If the quotient is not needed, pass @var{rs2p} + @var{s3size} as @var{r1p}.
+Aside from that special case, no overlap between arguments is permitted.
+
+Return the most significant limb of the quotient, either 0 or 1.
+
+The area at @var{r1p} needs to be @var{rs2size} @minus{} @var{s3size} +
+@var{xsize} limbs large.
+@end deftypefun
+
+@deftypefun mp_limb_t mpn_divrem_1 (mp_limb_t * @var{r1p}, mp_size_t @var{xsize}, mp_limb_t * @var{s2p}, mp_size_t @var{s2size}, mp_limb_t @var{s3limb})
+Divide @{@var{s2p}, @var{s2size}@} by @var{s3limb}, and write the quotient
+at @var{r1p}. Return the remainder.
+
+In addition to an integer quotient, @var{xsize} fraction limbs are developed,
+and stored after the integral limbs. For most usages, @var{xsize} will be
+zero.
+
+The areas at @var{r1p} and @var{s2p} have to be identical or completely
+separate, not partially overlapping.
+@end deftypefun
+
+@deftypefun mp_size_t mpn_divmod (mp_limb_t * @var{r1p}, mp_limb_t * @var{rs2p}, mp_size_t @var{rs2size}, const mp_limb_t * @var{s3p}, mp_size_t @var{s3size})
+@strong{This interface is obsolete. It will disappear from future releases.
+Use @code{mpn_divrem} in its stead.}
+@end deftypefun
+
+@deftypefun mp_limb_t mpn_divmod_1 (mp_limb_t * @var{r1p}, mp_limb_t * @var{s2p}, mp_size_t @var{s2size}, mp_limb_t @var{s3limb})
+@strong{This interface is obsolete. It will disappear from future releases.
+Use @code{mpn_divrem_1} in its stead.}
+@end deftypefun
+
+@deftypefun mp_limb_t mpn_mod_1 (mp_limb_t * @var{s1p}, mp_size_t @var{s1size}, mp_limb_t @var{s2limb})
+Divide @{@var{s1p}, @var{s1size}@} by @var{s2limb}, and return the remainder.
+@end deftypefun
+
+@deftypefun mp_limb_t mpn_pre_mod_1 (mp_limb_t * @var{s1p}, mp_size_t @var{s1size}, mp_limb_t @var{s2limb}, mp_limb_t @var{s3limb})
+@strong{This interface is obsolete. It will disappear from future releases.
+Use @code{mpn_mod_1} in its stead.}
+@end deftypefun
+
+@deftypefun mp_limb_t mpn_bdivmod (mp_limb_t * @var{dest_ptr}, mp_limb_t * @var{s1p}, mp_size_t @var{s1size}, const mp_limb_t * @var{s2p}, mp_size_t @var{s2size}, unsigned long int @var{d})
+The function puts the low [@var{d} / @var{BITS_PER_MP_LIMB}] limbs of
+@var{q} =
+@{@var{s1p}, @var{s1size}@} / @{@var{s2p}, @var{s2size}@}
+mod 2^@var{d}
+at @var{dest_ptr},
+and returns the high @var{d} mod @var{BITS_PER_MP_LIMB} bits of @var{q}.
+
+@{@var{s1p}, @var{s1size}@} - @var{q} * @{@var{s2p}, @var{s2size}@}
+mod 2^(@var{s1size}*@var{BITS_PER_MP_LIMB})
+is placed at @var{s1p}.
+Since the low [@var{d} / @var{BITS_PER_MP_LIMB}] limbs of
+this difference are zero, it is possible to overwrite the low limbs at
+@var{s1p} with this difference,
+provided @var{dest_ptr} <= @var{s1p}.
+
+This function requires that @var{s1size} * @var{BITS_PER_MP_LIMB} >= @var{D},
+and that @{@var{s2p}, @var{s2size}@} is odd.
+
+@strong{This interface is preliminary. It might change incompatibly in
+future revisions.}
+@end deftypefun
+
+@deftypefun mp_limb_t mpn_lshift (mp_limb_t * @var{dest_ptr}, const mp_limb_t * @var{src_ptr}, mp_size_t @var{src_size}, unsigned long int @var{count})
+Shift @{@var{src_ptr}, @var{src_size}@} @var{count} bits to the left, and
+write the @var{src_size} least significant limbs of the result to
+@var{dest_ptr}. @var{count} might be in the range 1 to n @minus{} 1, on an
+n-bit machine. The bits shifted out to the left are returned.
+
+Overlapping of the destination space and the source space is allowed in this
+function, provided @var{dest_ptr} >= @var{src_ptr}.
+
+This function is written in assembly for most targets.
+@end deftypefun
+
+@deftypefun mp_limp_t mpn_rshift (mp_limb_t * @var{dest_ptr}, const mp_limb_t * @var{src_ptr}, mp_size_t @var{src_size}, unsigned long int @var{count})
+Shift @{@var{src_ptr}, @var{src_size}@} @var{count} bits to the right, and
+write the @var{src_size} most significant limbs of the result to
+@var{dest_ptr}. @var{count} might be in the range 1 to n @minus{} 1, on an
+n-bit machine. The bits shifted out to the right are returned.
+
+Overlapping of the destination space and the source space is allowed in this
+function, provided @var{dest_ptr} <= @var{src_ptr}.
+
+This function is written in assembly for most targets.
+@end deftypefun
+
+@deftypefun int mpn_cmp (const mp_limb_t * @var{src1_ptr}, const mp_limb_t * @var{src2_ptr}, mp_size_t @var{size})
+Compare @{@var{src1_ptr}, @var{size}@} and @{@var{src2_ptr}, @var{size}@} and
+return a positive value if src1 > src2, 0 of they are equal, and a negative
+value if src1 < src2.
+@end deftypefun
+
+@deftypefun mp_size_t mpn_gcd (mp_limb_t * @var{dest_ptr}, mp_limb_t * @var{src1_ptr}, mp_size_t @var{src1_size}, mp_limb_t * @var{src2_ptr}, mp_size_t @var{src2_size})
+Puts at @var{dest_ptr} the greatest common divisor of @{@var{src1_ptr},
+@var{src1_size}@} and @{@var{src2_ptr}, @var{src2_size}@}; both source
+operands are destroyed by the operation. The size in limbs of the greatest
+common divisor is returned.
+
+@{@var{src1_ptr}, @var{src1_size}@} must be odd, and @{@var{src2_ptr},
+@var{src2_size}@} must have at least as many bits as @{@var{src1_ptr},
+@var{src1_size}@}.
+
+@strong{This interface is preliminary. It might change incompatibly in
+future revisions.}
+@end deftypefun
+
+@deftypefun mp_limb_t mpn_gcd_1 (const mp_limb_t * @var{src1_ptr}, mp_size_t @var{src1_size}, mp_limb_t @var{src2_limb})
+Return the greatest common divisor of @{@var{src1_ptr}, @var{src1_size}@}
+and @var{src2_limb}, where @var{src2_limb} (as well as @var{src1_size})
+must be different from 0.
+@end deftypefun
+
+@deftypefun mp_size_t mpn_gcdext (mp_limb_t * @var{r1p}, mp_limb_t * @var{r2p}, mp_limb_t * @var{s1p}, mp_size_t @var{s1size}, mp_limb_t * @var{s2p}, mp_size_t @var{s2size})
+Puts at @var{r1p} the greatest common divisor of @{@var{s1p}, @var{s1size}@}
+and @{@var{s2p}, @var{s2size}@}. The first cofactor is written at
+@var{r2p}. Both source operands are destroyed by the operation. The size
+in limbs of the greatest common divisor is returned.
+
+@strong{This interface is preliminary. It might change incompatibly in
+future revisions.}
+@end deftypefun
+
+@deftypefun mp_size_t mpn_sqrtrem (mp_limb_t * @var{r1p}, mp_limb_t * @var{r2p}, const mp_limb_t * @var{sp}, mp_size_t @var{size})
+Compute the square root of @{@var{sp}, @var{size}@} and put the result at
+@var{r1p}. Write the remainder at @var{r2p}, unless @var{r2p} is NULL.
+
+Return the size of the remainder, whether @var{r2p} was NULL or non-NULL.
+Iff the operand was a perfect square, the return value will be 0.
+
+The areas at @var{r1p} and @var{sp} have to be distinct. The areas at
+@var{r2p} and @var{sp} have to be identical or completely separate, not
+partially overlapping.
+
+The area at @var{r1p} needs to be @var{size} / 2 limbs large.
+The area at @var{r2p} needs to be @var{size} limbs large.
+
+@strong{This interface is preliminary. It might change incompatibly in
+future revisions.}
+@end deftypefun
+
+@deftypefun mp_size_t mpn_get_str (unsigned char *@var{str}, int @var{base}, mp_limb_t * @var{s1p}, mp_size_t @var{s1size})
+Convert @{@var{s1p}, @var{s1size}@} to a raw unsigned char array in base
+@var{base}. The string is not in ASCII; to convert it to printable format,
+add the ASCII codes for @samp{0} or @samp{A}, depending on the base and
+range. There may be leading zeros in the string.
+
+The area at @var{s1p} is clobbered.
+
+Return the number of characters in @var{str}.
+
+The area at @var{str} has to have space for the largest possible number
+represented by a @var{s1size} long limb array, plus one extra character.
+@end deftypefun
+
+@deftypefun mp_size_t mpn_set_str (mp_limb_t * @var{r1p}, const char *@var{str}, size_t {strsize}, int @var{base})
+Convert the raw unsigned char array at @var{str} of length @var{strsize} to
+a limb array @{@var{s1p}, @var{s1size}@}. The base of @var{str} is
+@var{base}.
+
+Return the number of limbs stored in @var{r1p}.
+@end deftypefun
+
+@deftypefun {unsigned long int} mpn_scan0 (const mp_limb_t * @var{s1p}, unsigned long int @var{bit})
+Scan @var{s1p} from bit position @var{bit} for the next clear bit.
+
+It is required that there be a clear bit within the area at @var{s1p} at or
+beyond bit position @var{bit}, so that the function has something to return.
+
+@strong{This interface is preliminary. It might change incompatibly in
+future revisions.}
+@end deftypefun
+
+@deftypefun {unsigned long int} mpn_scan1 (const mp_limb_t * @var{s1p}, unsigned long int @var{bit})
+Scan @var{s1p} from bit position @var{bit} for the next set bit.
+
+It is required that there be a set bit within the area at @var{s1p} at or
+beyond bit position @var{bit}, so that the function has something to return.
+
+@strong{This interface is preliminary. It might change incompatibly in
+future revisions.}
+@end deftypefun
+
+@deftypefun void mpn_random2 (mp_limb_t * @var{r1p}, mp_size_t @var{r1size})
+Generate a random number of length @var{r1size} with long strings of zeros
+and ones in the binary representation, and store it at @var{r1p}.
+
+The generated random numbers are intended for testing the correctness of the
+implementation of the @code{mpn} routines.
+@end deftypefun
+
+@deftypefun {unsigned long int} mpn_popcount (const mp_limb_t * @var{s1p}, unsigned long int @var{size})
+Count the number of set bits in @{@var{s1p}, @var{size}@}.
+@end deftypefun
+
+@deftypefun {unsigned long int} mpn_hamdist (const mp_limb_t * @var{s1p}, const mp_limb_t * @var{s2p}, unsigned long int @var{size})
+Compute the hamming distance between @{@var{s1p}, @var{size}@} and
+@{@var{s2p}, @var{size}@}.
+@end deftypefun
+
+@deftypefun int mpn_perfect_square_p (const mp_limb_t * @var{s1p}, mp_size_t @var{size})
+Return non-zero iff @{@var{s1p}, @var{size}@} is a perfect square.
+@end deftypefun
+
+
+@node BSD Compatible Functions, Custom Allocation, Low-level Functions, Top
+@comment node-name, next, previous, up
+@chapter Berkeley MP Compatible Functions
+@cindex BSD MP compatible functions
+
+These functions are intended to be fully compatible with the Berkeley MP
+library which is available on many BSD derived U*ix systems.
+
+The original Berkeley MP library has a usage restriction: you cannot use the
+same variable as both source and destination in a single function call. The
+compatible functions in GNU MP do not share this restriction---inputs and
+outputs may overlap.
+
+It is not recommended that new programs are written using these functions.
+Apart from the incomplete set of functions, the interface for initializing
+@code{MINT} objects is more error prone, and the @code{pow} function collides
+with @code{pow} in @file{libm.a}.
+
+@cindex @file{mp.h}
+Include the header @file{mp.h} to get the definition of the necessary types
+and functions. If you are on a BSD derived system, make sure to include GNU
+@file{mp.h} if you are going to link the GNU @file{libmp.a} to you program.
+This means that you probably need to give the -I<dir> option to the compiler,
+where <dir> is the directory where you have GNU @file{mp.h}.
+
+@deftypefun {MINT *} itom (signed short int @var{initial_value})
+Allocate an integer consisting of a @code{MINT} object and dynamic limb space.
+Initialize the integer to @var{initial_value}. Return a pointer to the
+@code{MINT} object.
+@end deftypefun
+
+@deftypefun {MINT *} xtom (char *@var{initial_value})
+Allocate an integer consisting of a @code{MINT} object and dynamic limb space.
+Initialize the integer from @var{initial_value}, a hexadecimal, '\0'-terminate
+C string. Return a pointer to the @code{MINT} object.
+@end deftypefun
+
+@deftypefun void move (MINT *@var{src}, MINT *@var{dest})
+Set @var{dest} to @var{src} by copying. Both variables must be previously
+initialized.
+@end deftypefun
+
+@deftypefun void madd (MINT *@var{src_1}, MINT *@var{src_2}, MINT *@var{destination})
+Add @var{src_1} and @var{src_2} and put the sum in @var{destination}.
+@end deftypefun
+
+@deftypefun void msub (MINT *@var{src_1}, MINT *@var{src_2}, MINT *@var{destination})
+Subtract @var{src_2} from @var{src_1} and put the difference in
+@var{destination}.
+@end deftypefun
+
+@deftypefun void mult (MINT *@var{src_1}, MINT *@var{src_2}, MINT *@var{destination})
+Multiply @var{src_1} and @var{src_2} and put the product in
+@var{destination}.
+@end deftypefun
+
+@deftypefun void mdiv (MINT *@var{dividend}, MINT *@var{divisor}, MINT *@var{quotient}, MINT *@var{remainder})
+@deftypefunx void sdiv (MINT *@var{dividend}, signed short int @var{divisor}, MINT *@var{quotient}, signed short int *@var{remainder})
+Set @var{quotient} to @var{dividend} / @var{divisor}, and @var{remainder} to
+@var{dividend} mod @var{divisor}. The quotient is rounded towards zero; the
+remainder has the same sign as the dividend unless it is zero.
+
+Some implementations of these functions work differently---or not at all---for
+negative arguments.
+@end deftypefun
+
+@deftypefun void msqrt (MINT *@var{operand}, MINT *@var{root}, MINT *@var{remainder})
+@ifinfo
+Set @var{root} to the truncated integer part of the square root of
+@var{operand}. Set @var{remainder} to
+@var{operand}@minus{}@var{root}*@var{root},
+@end ifinfo
+@iftex
+Set @var{root} to
+@tex
+$\lfloor\sqrt{@var{operand}}\rfloor$,
+@end tex
+like @code{mpz_sqrt}. Set @var{remainder} to
+@tex
+$(operand - root^2)$,
+@end tex
+@end iftex
+(i.e., zero if @var{operand} is a perfect square).
+
+If @var{root} and @var{remainder} are the same variable, the results are
+undefined.
+@end deftypefun
+
+@deftypefun void pow (MINT *@var{base}, MINT *@var{exp}, MINT *@var{mod}, MINT *@var{dest})
+Set @var{dest} to (@var{base} raised to @var{exp}) modulo @var{mod}.
+@end deftypefun
+
+@deftypefun void rpow (MINT *@var{base}, signed short int @var{exp}, MINT *@var{dest})
+Set @var{dest} to @var{base} raised to @var{exp}.
+@end deftypefun
+
+@deftypefun void gcd (MINT *@var{operand1}, MINT *@var{operand2}, MINT *@var{res})
+Set @var{res} to the greatest common divisor of @var{operand1} and
+@var{operand2}.
+@end deftypefun
+
+@deftypefun int mcmp (MINT *@var{operand1}, MINT *@var{operand2})
+Compare @var{operand1} and @var{operand2}. Return a positive value if
+@var{operand1} > @var{operand2}, zero if @var{operand1} =
+@var{operand2}, and a negative value if @var{operand1} < @var{operand2}.
+@end deftypefun
+
+@deftypefun void min (MINT *@var{dest})
+Input a decimal string from @code{stdin}, and put the read integer in
+@var{dest}. SPC and TAB are allowed in the number string, and are ignored.
+@end deftypefun
+
+@deftypefun void mout (MINT *@var{src})
+Output @var{src} to @code{stdout}, as a decimal string. Also output a newline.
+@end deftypefun
+
+@deftypefun {char *} mtox (MINT *@var{operand})
+Convert @var{operand} to a hexadecimal string, and return a pointer to the
+string. The returned string is allocated using the default memory allocation
+function, @code{malloc} by default.
+@end deftypefun
+
+@deftypefun void mfree (MINT *@var{operand})
+De-allocate, the space used by @var{operand}. @strong{This function should
+only be passed a value returned by @code{itom} or @code{xtom}.}
+@end deftypefun
+
+@node Custom Allocation, Contributors, BSD Compatible Functions, Top
+@comment node-name, next, previous, up
+@chapter Custom Allocation
+
+By default, the MP functions use @code{malloc}, @code{realloc}, and
+@code{free} for memory allocation. If @code{malloc} or @code{realloc} fails,
+the MP library terminates execution after printing a fatal error message to
+standard error.
+
+For some applications, you may wish to allocate memory in other ways, or you
+may not want to have a fatal error when there is no more memory available. To
+accomplish this, you can specify alternative memory allocation functions.
+
+@deftypefun void mp_set_memory_functions (@* void *(*@var{alloc_func_ptr}) (size_t), @* void *(*@var{realloc_func_ptr}) (void *, size_t, size_t), @* void (*@var{free_func_ptr}) (void *, size_t))
+Replace the current allocation functions from the arguments. If an argument
+is NULL, the corresponding default function is retained.
+
+@strong{Make sure to call this function in such a way that there are no active
+MP objects that were allocated using the previously active allocation
+function! Usually, that means that you have to call this function before any
+other MP function.}
+@end deftypefun
+
+The functions you supply should fit the following declarations:
+
+@deftypefun {void *} allocate_function (size_t @var{alloc_size})
+This function should return a pointer to newly allocated space with at least
+@var{alloc_size} storage units.
+@end deftypefun
+
+@deftypefun {void *} reallocate_function (void *@var{ptr}, size_t @var{old_size}, size_t @var{new_size})
+This function should return a pointer to newly allocated space of at least
+@var{new_size} storage units, after copying at least the first @var{old_size}
+storage units from @var{ptr}. It should also de-allocate the space at
+@var{ptr}.
+
+You can assume that the space at @var{ptr} was formerly returned from
+@code{allocate_function} or @code{reallocate_function}, for a request for
+@var{old_size} storage units.
+@end deftypefun
+
+@deftypefun void deallocate_function (void *@var{ptr}, size_t @var{size})
+De-allocate the space pointed to by @var{ptr}.
+
+You can assume that the space at @var{ptr} was formerly returned from
+@code{allocate_function} or @code{reallocate_function}, for a request for
+@var{size} storage units.
+@end deftypefun
+
+(A @dfn{storage unit} is the unit in which the @code{sizeof} operator returns
+the size of an object, normally an 8 bit byte.)
+
+
+@node Contributors, References, Custom Allocation, Top
+@comment node-name, next, previous, up
+@unnumbered Contributors
+
+I would like to thank Gunnar Sjoedin and Hans Riesel for their help with
+mathematical problems, Richard Stallman for his help with design issues and
+for revising the first version of this manual, Brian Beuning and Doug Lea for
+their testing of early versions of the library.
+
+John Amanatides of York University in Canada contributed the function
+@code{mpz_probab_prime_p}.
+
+Ken Weber (Kent State University, Universidade Federal do Rio Grande do Sul)
+contributed @code{mpz_gcd}, @code{mpz_divexact}, @code{mpn_gcd}, and
+@code{mpn_bdivmod}, partially supported by CNPq (Brazil) grant 301314194-2.
+
+Per Bothner of Cygnus Support helped to set up MP to use Cygnus' configure.
+He has also made valuable suggestions and tested numerous intermediary
+releases.
+
+Joachim Hollman was involved in the design of the @code{mpf} interface, and in
+the @code{mpz} design revisions for version 2.
+
+Bennet Yee contributed the functions @code{mpz_jacobi} and
+@code{mpz_legendre}.
+
+Andreas Schwab contributed the files @code{m68k/lshift.S} and
+@code{m68k/rshift.S}.
+
+The development of floating point functions of GNU MP 2, were supported in
+part by the ESPRIT-BRA (Basic Research Activities) 6846 project POSSO
+(POlynomial System SOlving).
+
+GNU MP 2 was finished and released by TMG Datakonsult, Sodermannagatan 5, 116
+23 STOCKHOLM, SWEDEN, in cooperation with the IDA Center for Computing
+Sciences, USA.
+
+
+@node References, , Contributors, Top
+@comment node-name, next, previous, up
+@unnumbered References
+
+@itemize @bullet
+
+@item
+Donald E. Knuth, "The Art of Computer Programming", vol 2,
+"Seminumerical Algorithms", 2nd edition, Addison-Wesley, 1981.
+
+@item
+John D. Lipson, "Elements of Algebra and Algebraic Computing",
+The Benjamin Cummings Publishing Company Inc, 1981.
+
+@item
+Richard M. Stallman, "Using and Porting GCC", Free Software Foundation,
+1995.
+
+@item
+Peter L. Montgomery, "Modular Multiplication Without Trial Division", in
+Mathematics of Computation, volume 44, number 170, April 1985.
+
+@item
+Torbjorn Granlund and Peter L. Montgomery, "Division by Invariant
+Integers using Multiplication", in Proceedings of the SIGPLAN
+PLDI'94 Conference, June 1994.
+
+@item
+Tudor Jebelean,
+"An algorithm for exact division",
+Journal of Symbolic Computation,
+v. 15, 1993, pp. 169-180.
+
+@item
+Kenneth Weber, "The accelerated integer GCD algorithm",
+ACM Transactions on Mathematical Software,
+v. 21 (March), 1995, pp. 111-122.
+@end itemize
+
+@node Concept Index, , , Top
+@comment node-name, next, previous, up
+@unnumbered Concept Index
+@printindex cp
+
+@node Function Index, , , Top
+@comment node-name, next, previous, up
+@unnumbered Function and Type Index
+@printindex fn
+
+
+@contents
+@bye
diff --git a/longlong.h b/longlong.h
new file mode 100644
index 000000000..89414f275
--- /dev/null
+++ b/longlong.h
@@ -0,0 +1,1404 @@
+/* longlong.h -- definitions for mixed size 32/64 bit arithmetic.
+
+Copyright (C) 1991, 1992, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+This file 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with this file; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/* You have to define the following before including this file:
+
+ UWtype -- An unsigned type, default type for operations (typically a "word")
+ UHWtype -- An unsigned type, at least half the size of UWtype.
+ UDWtype -- An unsigned type, at least twice as large a UWtype
+ W_TYPE_SIZE -- size in bits of UWtype
+
+ SItype, USItype -- Signed and unsigned 32 bit types.
+ DItype, UDItype -- Signed and unsigned 64 bit types.
+
+ On a 32 bit machine UWtype should typically be USItype;
+ on a 64 bit machine, UWtype should typically be UDItype.
+*/
+
+#define __BITS4 (W_TYPE_SIZE / 4)
+#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2))
+#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1))
+#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2))
+
+/* This is used to make sure no undesirable sharing between different libraries
+ that use this file takes place. */
+#ifndef __MPN
+#define __MPN(x) __##x
+#endif
+
+/* Define auxiliary asm macros.
+
+ 1) umul_ppmm(high_prod, low_prod, multipler, multiplicand) multiplies two
+ UWtype integers MULTIPLER and MULTIPLICAND, and generates a two UWtype
+ word product in HIGH_PROD and LOW_PROD.
+
+ 2) __umulsidi3(a,b) multiplies two UWtype integers A and B, and returns a
+ UDWtype product. This is just a variant of umul_ppmm.
+
+ 3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
+ denominator) divides a UDWtype, composed by the UWtype integers
+ HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient
+ in QUOTIENT and the remainder in REMAINDER. HIGH_NUMERATOR must be less
+ than DENOMINATOR for correct operation. If, in addition, the most
+ significant bit of DENOMINATOR must be 1, then the pre-processor symbol
+ UDIV_NEEDS_NORMALIZATION is defined to 1.
+
+ 4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
+ denominator). Like udiv_qrnnd but the numbers are signed. The quotient
+ is rounded towards 0.
+
+ 5) count_leading_zeros(count, x) counts the number of zero-bits from the
+ msb to the first non-zero bit in the UWtype X. This is the number of
+ steps X needs to be shifted left to set the msb. Undefined for X == 0,
+ unless the symbol COUNT_LEADING_ZEROS_0 is defined to some value.
+
+ 6) count_trailing_zeros(count, x) like count_leading_zeros, but counts
+ from the least significant end.
+
+ 7) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1,
+ high_addend_2, low_addend_2) adds two UWtype integers, composed by
+ HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2
+ respectively. The result is placed in HIGH_SUM and LOW_SUM. Overflow
+ (i.e. carry out) is not stored anywhere, and is lost.
+
+ 8) sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend,
+ high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers,
+ composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and
+ LOW_SUBTRAHEND_2 respectively. The result is placed in HIGH_DIFFERENCE
+ and LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere,
+ and is lost.
+
+ If any of these macros are left undefined for a particular CPU,
+ C macros are used. */
+
+/* The CPUs come in alphabetical order below.
+
+ Please add support for more CPUs here, or improve the current support
+ for the CPUs below! */
+
+#if defined (__GNUC__) && !defined (NO_ASM)
+
+/* We sometimes need to clobber "cc" with gcc2, but that would not be
+ understood by gcc1. Use cpp to avoid major code duplication. */
+#if __GNUC__ < 2
+#define __CLOBBER_CC
+#define __AND_CLOBBER_CC
+#else /* __GNUC__ >= 2 */
+#define __CLOBBER_CC : "cc"
+#define __AND_CLOBBER_CC , "cc"
+#endif /* __GNUC__ < 2 */
+
+#if (defined (__a29k__) || defined (_AM29K)) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("add %1,%4,%5
+ addc %0,%2,%3" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "%r" ((USItype)(ah)), \
+ "rI" ((USItype)(bh)), \
+ "%r" ((USItype)(al)), \
+ "rI" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("sub %1,%4,%5
+ subc %0,%2,%3" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "r" ((USItype)(ah)), \
+ "rI" ((USItype)(bh)), \
+ "r" ((USItype)(al)), \
+ "rI" ((USItype)(bl)))
+#define umul_ppmm(xh, xl, m0, m1) \
+ do { \
+ USItype __m0 = (m0), __m1 = (m1); \
+ __asm__ ("multiplu %0,%1,%2" \
+ : "=r" ((USItype)(xl)) \
+ : "r" (__m0), \
+ "r" (__m1)); \
+ __asm__ ("multmu %0,%1,%2" \
+ : "=r" ((USItype)(xh)) \
+ : "r" (__m0), \
+ "r" (__m1)); \
+ } while (0)
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ __asm__ ("dividu %0,%3,%4" \
+ : "=r" ((USItype)(q)), \
+ "=q" ((USItype)(r)) \
+ : "1" ((USItype)(n1)), \
+ "r" ((USItype)(n0)), \
+ "r" ((USItype)(d)))
+#define count_leading_zeros(count, x) \
+ __asm__ ("clz %0,%1" \
+ : "=r" ((USItype)(count)) \
+ : "r" ((USItype)(x)))
+#define COUNT_LEADING_ZEROS_0 32
+#endif /* __a29k__ */
+
+#if defined (__alpha) && W_TYPE_SIZE == 64
+#define umul_ppmm(ph, pl, m0, m1) \
+ do { \
+ UDItype __m0 = (m0), __m1 = (m1); \
+ __asm__ ("umulh %r1,%2,%0" \
+ : "=r" ((UDItype) ph) \
+ : "%rJ" (__m0), \
+ "rI" (__m1)); \
+ (pl) = __m0 * __m1; \
+ } while (0)
+#define UMUL_TIME 46
+#ifndef LONGLONG_STANDALONE
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ do { UDItype __r; \
+ (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \
+ (r) = __r; \
+ } while (0)
+extern UDItype __udiv_qrnnd ();
+#define UDIV_TIME 220
+#endif /* LONGLONG_STANDALONE */
+#endif /* __alpha */
+
+#if defined (__arm__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("adds %1, %4, %5
+ adc %0, %2, %3" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "%r" ((USItype)(ah)), \
+ "rI" ((USItype)(bh)), \
+ "%r" ((USItype)(al)), \
+ "rI" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("subs %1, %4, %5
+ sbc %0, %2, %3" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "r" ((USItype)(ah)), \
+ "rI" ((USItype)(bh)), \
+ "r" ((USItype)(al)), \
+ "rI" ((USItype)(bl)))
+#define umul_ppmm(xh, xl, a, b) \
+ __asm__ ("%@ Inlined umul_ppmm
+ mov %|r0, %2, lsr #16
+ mov %|r2, %3, lsr #16
+ bic %|r1, %2, %|r0, lsl #16
+ bic %|r2, %3, %|r2, lsl #16
+ mul %1, %|r1, %|r2
+ mul %|r2, %|r0, %|r2
+ mul %|r1, %0, %|r1
+ mul %0, %|r0, %0
+ adds %|r1, %|r2, %|r1
+ addcs %0, %0, #65536
+ adds %1, %1, %|r1, lsl #16
+ adc %0, %0, %|r1, lsr #16" \
+ : "=&r" ((USItype)(xh)), \
+ "=r" ((USItype)(xl)) \
+ : "r" ((USItype)(a)), \
+ "r" ((USItype)(b)) \
+ : "r0", "r1", "r2")
+#define UMUL_TIME 20
+#define UDIV_TIME 100
+#endif /* __arm__ */
+
+#if defined (__clipper__) && W_TYPE_SIZE == 32
+#define umul_ppmm(w1, w0, u, v) \
+ ({union {UDItype __ll; \
+ struct {USItype __l, __h;} __i; \
+ } __xx; \
+ __asm__ ("mulwux %2,%0" \
+ : "=r" (__xx.__ll) \
+ : "%0" ((USItype)(u)), \
+ "r" ((USItype)(v))); \
+ (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
+#define smul_ppmm(w1, w0, u, v) \
+ ({union {DItype __ll; \
+ struct {SItype __l, __h;} __i; \
+ } __xx; \
+ __asm__ ("mulwx %2,%0" \
+ : "=r" (__xx.__ll) \
+ : "%0" ((SItype)(u)), \
+ "r" ((SItype)(v))); \
+ (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
+#define __umulsidi3(u, v) \
+ ({UDItype __w; \
+ __asm__ ("mulwux %2,%0" \
+ : "=r" (__w) \
+ : "%0" ((USItype)(u)), \
+ "r" ((USItype)(v))); \
+ __w; })
+#endif /* __clipper__ */
+
+#if defined (__gmicro__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("add.w %5,%1
+ addx %3,%0" \
+ : "=g" ((USItype)(sh)), \
+ "=&g" ((USItype)(sl)) \
+ : "%0" ((USItype)(ah)), \
+ "g" ((USItype)(bh)), \
+ "%1" ((USItype)(al)), \
+ "g" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("sub.w %5,%1
+ subx %3,%0" \
+ : "=g" ((USItype)(sh)), \
+ "=&g" ((USItype)(sl)) \
+ : "0" ((USItype)(ah)), \
+ "g" ((USItype)(bh)), \
+ "1" ((USItype)(al)), \
+ "g" ((USItype)(bl)))
+#define umul_ppmm(ph, pl, m0, m1) \
+ __asm__ ("mulx %3,%0,%1" \
+ : "=g" ((USItype)(ph)), \
+ "=r" ((USItype)(pl)) \
+ : "%0" ((USItype)(m0)), \
+ "g" ((USItype)(m1)))
+#define udiv_qrnnd(q, r, nh, nl, d) \
+ __asm__ ("divx %4,%0,%1" \
+ : "=g" ((USItype)(q)), \
+ "=r" ((USItype)(r)) \
+ : "1" ((USItype)(nh)), \
+ "0" ((USItype)(nl)), \
+ "g" ((USItype)(d)))
+#define count_leading_zeros(count, x) \
+ __asm__ ("bsch/1 %1,%0" \
+ : "=g" (count) \
+ : "g" ((USItype)(x)), \
+ "0" ((USItype)0))
+#endif
+
+#if defined (__hppa) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("add %4,%5,%1
+ addc %2,%3,%0" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "%rM" ((USItype)(ah)), \
+ "rM" ((USItype)(bh)), \
+ "%rM" ((USItype)(al)), \
+ "rM" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("sub %4,%5,%1
+ subb %2,%3,%0" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "rM" ((USItype)(ah)), \
+ "rM" ((USItype)(bh)), \
+ "rM" ((USItype)(al)), \
+ "rM" ((USItype)(bl)))
+#if defined (_PA_RISC1_1)
+#define umul_ppmm(wh, wl, u, v) \
+ do { \
+ union {UDItype __ll; \
+ struct {USItype __h, __l;} __i; \
+ } __xx; \
+ __asm__ ("xmpyu %1,%2,%0" \
+ : "=*f" (__xx.__ll) \
+ : "*f" ((USItype)(u)), \
+ "*f" ((USItype)(v))); \
+ (wh) = __xx.__i.__h; \
+ (wl) = __xx.__i.__l; \
+ } while (0)
+#define UMUL_TIME 8
+#define UDIV_TIME 60
+#else
+#define UMUL_TIME 40
+#define UDIV_TIME 80
+#endif
+#ifndef LONGLONG_STANDALONE
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ do { USItype __r; \
+ (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \
+ (r) = __r; \
+ } while (0)
+extern USItype __udiv_qrnnd ();
+#endif /* LONGLONG_STANDALONE */
+#define count_leading_zeros(count, x) \
+ do { \
+ USItype __tmp; \
+ __asm__ ( \
+ "ldi 1,%0
+ extru,= %1,15,16,%%r0 ; Bits 31..16 zero?
+ extru,tr %1,15,16,%1 ; No. Shift down, skip add.
+ ldo 16(%0),%0 ; Yes. Perform add.
+ extru,= %1,23,8,%%r0 ; Bits 15..8 zero?
+ extru,tr %1,23,8,%1 ; No. Shift down, skip add.
+ ldo 8(%0),%0 ; Yes. Perform add.
+ extru,= %1,27,4,%%r0 ; Bits 7..4 zero?
+ extru,tr %1,27,4,%1 ; No. Shift down, skip add.
+ ldo 4(%0),%0 ; Yes. Perform add.
+ extru,= %1,29,2,%%r0 ; Bits 3..2 zero?
+ extru,tr %1,29,2,%1 ; No. Shift down, skip add.
+ ldo 2(%0),%0 ; Yes. Perform add.
+ extru %1,30,1,%1 ; Extract bit 1.
+ sub %0,%1,%0 ; Subtract it.
+ " : "=r" (count), "=r" (__tmp) : "1" (x)); \
+ } while (0)
+#endif /* hppa */
+
+#if (defined (__i370__) || defined (__mvs__)) && W_TYPE_SIZE == 32
+#define umul_ppmm(xh, xl, m0, m1) \
+ do { \
+ union {UDItype __ll; \
+ struct {USItype __h, __l;} __i; \
+ } __xx; \
+ USItype __m0 = (m0), __m1 = (m1); \
+ __asm__ ("mr %0,%3" \
+ : "=r" (__xx.__i.__h), \
+ "=r" (__xx.__i.__l) \
+ : "%1" (__m0), \
+ "r" (__m1)); \
+ (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \
+ (xh) += ((((SItype) __m0 >> 31) & __m1) \
+ + (((SItype) __m1 >> 31) & __m0)); \
+ } while (0)
+#define smul_ppmm(xh, xl, m0, m1) \
+ do { \
+ union {DItype __ll; \
+ struct {USItype __h, __l;} __i; \
+ } __xx; \
+ __asm__ ("mr %0,%3" \
+ : "=r" (__xx.__i.__h), \
+ "=r" (__xx.__i.__l) \
+ : "%1" (m0), \
+ "r" (m1)); \
+ (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \
+ } while (0)
+#define sdiv_qrnnd(q, r, n1, n0, d) \
+ do { \
+ union {DItype __ll; \
+ struct {USItype __h, __l;} __i; \
+ } __xx; \
+ __xx.__i.__h = n1; __xx.__i.__l = n0; \
+ __asm__ ("dr %0,%2" \
+ : "=r" (__xx.__ll) \
+ : "0" (__xx.__ll), "r" (d)); \
+ (q) = __xx.__i.__l; (r) = __xx.__i.__h; \
+ } while (0)
+#endif
+
+#if (defined (__i386__) || defined (__i486__)) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("addl %5,%1
+ adcl %3,%0" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "%0" ((USItype)(ah)), \
+ "g" ((USItype)(bh)), \
+ "%1" ((USItype)(al)), \
+ "g" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("subl %5,%1
+ sbbl %3,%0" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "0" ((USItype)(ah)), \
+ "g" ((USItype)(bh)), \
+ "1" ((USItype)(al)), \
+ "g" ((USItype)(bl)))
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ("mull %3" \
+ : "=a" ((USItype)(w0)), \
+ "=d" ((USItype)(w1)) \
+ : "%0" ((USItype)(u)), \
+ "rm" ((USItype)(v)))
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ __asm__ ("divl %4" \
+ : "=a" ((USItype)(q)), \
+ "=d" ((USItype)(r)) \
+ : "0" ((USItype)(n0)), \
+ "1" ((USItype)(n1)), \
+ "rm" ((USItype)(d)))
+#define count_leading_zeros(count, x) \
+ do { \
+ USItype __cbtmp; \
+ __asm__ ("bsrl %1,%0" \
+ : "=r" (__cbtmp) : "rm" ((USItype)(x))); \
+ (count) = __cbtmp ^ 31; \
+ } while (0)
+#define count_trailing_zeros(count, x) \
+ __asm__ ("bsfl %1,%0" : "=r" (count) : "rm" ((USItype)(x)))
+#ifndef UMUL_TIME
+#define UMUL_TIME 40
+#endif
+#ifndef UDIV_TIME
+#define UDIV_TIME 40
+#endif
+#endif /* 80x86 */
+
+#if defined (__i860__) && W_TYPE_SIZE == 32
+#define rshift_rhlc(r,h,l,c) \
+ __asm__ ("shr %3,r0,r0\;shrd %1,%2,%0" \
+ "=r" (r) : "r" (h), "r" (l), "rn" (c))
+#endif /* i860 */
+
+#if defined (__i960__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("cmpo 1,0\;addc %5,%4,%1\;addc %3,%2,%0" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "%dI" ((USItype)(ah)), \
+ "dI" ((USItype)(bh)), \
+ "%dI" ((USItype)(al)), \
+ "dI" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("cmpo 0,0\;subc %5,%4,%1\;subc %3,%2,%0" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "dI" ((USItype)(ah)), \
+ "dI" ((USItype)(bh)), \
+ "dI" ((USItype)(al)), \
+ "dI" ((USItype)(bl)))
+#define umul_ppmm(w1, w0, u, v) \
+ ({union {UDItype __ll; \
+ struct {USItype __l, __h;} __i; \
+ } __xx; \
+ __asm__ ("emul %2,%1,%0" \
+ : "=d" (__xx.__ll) \
+ : "%dI" ((USItype)(u)), \
+ "dI" ((USItype)(v))); \
+ (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
+#define __umulsidi3(u, v) \
+ ({UDItype __w; \
+ __asm__ ("emul %2,%1,%0" \
+ : "=d" (__w) \
+ : "%dI" ((USItype)(u)), \
+ "dI" ((USItype)(v))); \
+ __w; })
+#define udiv_qrnnd(q, r, nh, nl, d) \
+ do { \
+ union {UDItype __ll; \
+ struct {USItype __l, __h;} __i; \
+ } __nn; \
+ __nn.__i.__h = (nh); __nn.__i.__l = (nl); \
+ __asm__ ("ediv %d,%n,%0" \
+ : "=d" (__rq.__ll) \
+ : "dI" (__nn.__ll), \
+ "dI" ((USItype)(d))); \
+ (r) = __rq.__i.__l; (q) = __rq.__i.__h; \
+ } while (0)
+#define count_leading_zeros(count, x) \
+ do { \
+ USItype __cbtmp; \
+ __asm__ ("scanbit %1,%0" \
+ : "=r" (__cbtmp) \
+ : "r" ((USItype)(x))); \
+ (count) = __cbtmp ^ 31; \
+ } while (0)
+#define COUNT_LEADING_ZEROS_0 (-32) /* sic */
+#if defined (__i960mx) /* what is the proper symbol to test??? */
+#define rshift_rhlc(r,h,l,c) \
+ do { \
+ union {UDItype __ll; \
+ struct {USItype __l, __h;} __i; \
+ } __nn; \
+ __nn.__i.__h = (h); __nn.__i.__l = (l); \
+ __asm__ ("shre %2,%1,%0" \
+ : "=d" (r) : "dI" (__nn.__ll), "dI" (c)); \
+ }
+#endif /* i960mx */
+#endif /* i960 */
+
+#if (defined (__mc68000__) || defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("add%.l %5,%1
+ addx%.l %3,%0" \
+ : "=d" ((USItype)(sh)), \
+ "=&d" ((USItype)(sl)) \
+ : "%0" ((USItype)(ah)), \
+ "d" ((USItype)(bh)), \
+ "%1" ((USItype)(al)), \
+ "g" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("sub%.l %5,%1
+ subx%.l %3,%0" \
+ : "=d" ((USItype)(sh)), \
+ "=&d" ((USItype)(sl)) \
+ : "0" ((USItype)(ah)), \
+ "d" ((USItype)(bh)), \
+ "1" ((USItype)(al)), \
+ "g" ((USItype)(bl)))
+#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020))
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ("mulu%.l %3,%1:%0" \
+ : "=d" ((USItype)(w0)), \
+ "=d" ((USItype)(w1)) \
+ : "%0" ((USItype)(u)), \
+ "dmi" ((USItype)(v)))
+#define UMUL_TIME 45
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ __asm__ ("divu%.l %4,%1:%0" \
+ : "=d" ((USItype)(q)), \
+ "=d" ((USItype)(r)) \
+ : "0" ((USItype)(n0)), \
+ "1" ((USItype)(n1)), \
+ "dmi" ((USItype)(d)))
+#define UDIV_TIME 90
+#define sdiv_qrnnd(q, r, n1, n0, d) \
+ __asm__ ("divs%.l %4,%1:%0" \
+ : "=d" ((USItype)(q)), \
+ "=d" ((USItype)(r)) \
+ : "0" ((USItype)(n0)), \
+ "1" ((USItype)(n1)), \
+ "dmi" ((USItype)(d)))
+#define count_leading_zeros(count, x) \
+ __asm__ ("bfffo %1{%b2:%b2},%0" \
+ : "=d" ((USItype)(count)) \
+ : "od" ((USItype)(x)), "n" (0))
+#define COUNT_LEADING_ZEROS_0 32
+#else /* not mc68020 */
+#define umul_ppmm(xh, xl, a, b) \
+ do { USItype __umul_tmp1, __umul_tmp2; \
+ __asm__ ("| Inlined umul_ppmm
+ move%.l %5,%3
+ move%.l %2,%0
+ move%.w %3,%1
+ swap %3
+ swap %0
+ mulu %2,%1
+ mulu %3,%0
+ mulu %2,%3
+ swap %2
+ mulu %5,%2
+ add%.l %3,%2
+ jcc 1f
+ add%.l %#0x10000,%0
+1: move%.l %2,%3
+ clr%.w %2
+ swap %2
+ swap %3
+ clr%.w %3
+ add%.l %3,%1
+ addx%.l %2,%0
+ | End inlined umul_ppmm" \
+ : "=&d" ((USItype)(xh)), "=&d" ((USItype)(xl)), \
+ "=d" (__umul_tmp1), "=&d" (__umul_tmp2) \
+ : "%2" ((USItype)(a)), "d" ((USItype)(b))); \
+ } while (0)
+#define UMUL_TIME 100
+#define UDIV_TIME 400
+#endif /* not mc68020 */
+#endif /* mc68000 */
+
+#if defined (__m88000__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("addu.co %1,%r4,%r5
+ addu.ci %0,%r2,%r3" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "%rJ" ((USItype)(ah)), \
+ "rJ" ((USItype)(bh)), \
+ "%rJ" ((USItype)(al)), \
+ "rJ" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("subu.co %1,%r4,%r5
+ subu.ci %0,%r2,%r3" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "rJ" ((USItype)(ah)), \
+ "rJ" ((USItype)(bh)), \
+ "rJ" ((USItype)(al)), \
+ "rJ" ((USItype)(bl)))
+#define count_leading_zeros(count, x) \
+ do { \
+ USItype __cbtmp; \
+ __asm__ ("ff1 %0,%1" \
+ : "=r" (__cbtmp) \
+ : "r" ((USItype)(x))); \
+ (count) = __cbtmp ^ 31; \
+ } while (0)
+#define COUNT_LEADING_ZEROS_0 63 /* sic */
+#if defined (__m88110__)
+#define umul_ppmm(wh, wl, u, v) \
+ do { \
+ union {UDItype __ll; \
+ struct {USItype __h, __l;} __i; \
+ } __xx; \
+ __asm__ ("mulu.d %0,%1,%2" \
+ : "=r" (__xx.__ll) \
+ : "r" ((USItype)(u)), \
+ "r" ((USItype)(v))); \
+ (wh) = __xx.__i.__h; \
+ (wl) = __xx.__i.__l; \
+ } while (0)
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ ({union {UDItype __ll; \
+ struct {USItype __h, __l;} __i; \
+ } __xx; \
+ USItype __q; \
+ __xx.__i.__h = (n1); __xx.__i.__l = (n0); \
+ __asm__ ("divu.d %0,%1,%2" \
+ : "=r" (__q) \
+ : "r" (__xx.__ll), \
+ "r" ((USItype)(d))); \
+ (r) = (n0) - __q * (d); (q) = __q; })
+#define UMUL_TIME 5
+#define UDIV_TIME 25
+#else
+#define UMUL_TIME 17
+#define UDIV_TIME 150
+#endif /* __m88110__ */
+#endif /* __m88000__ */
+
+#if defined (__mips__) && W_TYPE_SIZE == 32
+#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ("multu %2,%3" \
+ : "=l" ((USItype)(w0)), \
+ "=h" ((USItype)(w1)) \
+ : "d" ((USItype)(u)), \
+ "d" ((USItype)(v)))
+#else
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ("multu %2,%3
+ mflo %0
+ mfhi %1" \
+ : "=d" ((USItype)(w0)), \
+ "=d" ((USItype)(w1)) \
+ : "d" ((USItype)(u)), \
+ "d" ((USItype)(v)))
+#endif
+#define UMUL_TIME 10
+#define UDIV_TIME 100
+#endif /* __mips__ */
+
+#if (defined (__mips) && __mips >= 3) && W_TYPE_SIZE == 64
+#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ("dmultu %2,%3" \
+ : "=l" ((UDItype)(w0)), \
+ "=h" ((UDItype)(w1)) \
+ : "d" ((UDItype)(u)), \
+ "d" ((UDItype)(v)))
+#else
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ("dmultu %2,%3
+ mflo %0
+ mfhi %1" \
+ : "=d" ((UDItype)(w0)), \
+ "=d" ((UDItype)(w1)) \
+ : "d" ((UDItype)(u)), \
+ "d" ((UDItype)(v)))
+#endif
+#define UMUL_TIME 20
+#define UDIV_TIME 140
+#endif /* __mips__ */
+
+#if defined (__ns32000__) && W_TYPE_SIZE == 32
+#define umul_ppmm(w1, w0, u, v) \
+ ({union {UDItype __ll; \
+ struct {USItype __l, __h;} __i; \
+ } __xx; \
+ __asm__ ("meid %2,%0" \
+ : "=g" (__xx.__ll) \
+ : "%0" ((USItype)(u)), \
+ "g" ((USItype)(v))); \
+ (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
+#define __umulsidi3(u, v) \
+ ({UDItype __w; \
+ __asm__ ("meid %2,%0" \
+ : "=g" (__w) \
+ : "%0" ((USItype)(u)), \
+ "g" ((USItype)(v))); \
+ __w; })
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ ({union {UDItype __ll; \
+ struct {USItype __l, __h;} __i; \
+ } __xx; \
+ __xx.__i.__h = (n1); __xx.__i.__l = (n0); \
+ __asm__ ("deid %2,%0" \
+ : "=g" (__xx.__ll) \
+ : "0" (__xx.__ll), \
+ "g" ((USItype)(d))); \
+ (r) = __xx.__i.__l; (q) = __xx.__i.__h; })
+#define count_trailing_zeros(count,x) \
+ do {
+ __asm__ ("ffsd %2,%0" \
+ : "=r" ((USItype) (count)) \
+ : "0" ((USItype) 0), \
+ "r" ((USItype) (x))); \
+ } while (0)
+#endif /* __ns32000__ */
+
+#if (defined (_ARCH_PPC) || defined (_IBMR2)) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ do { \
+ if (__builtin_constant_p (bh) && (bh) == 0) \
+ __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "%r" ((USItype)(ah)), \
+ "%r" ((USItype)(al)), \
+ "rI" ((USItype)(bl))); \
+ else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0) \
+ __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "%r" ((USItype)(ah)), \
+ "%r" ((USItype)(al)), \
+ "rI" ((USItype)(bl))); \
+ else \
+ __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "%r" ((USItype)(ah)), \
+ "r" ((USItype)(bh)), \
+ "%r" ((USItype)(al)), \
+ "rI" ((USItype)(bl))); \
+ } while (0)
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ do { \
+ if (__builtin_constant_p (ah) && (ah) == 0) \
+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "r" ((USItype)(bh)), \
+ "rI" ((USItype)(al)), \
+ "r" ((USItype)(bl))); \
+ else if (__builtin_constant_p (ah) && (ah) ==~(USItype) 0) \
+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "r" ((USItype)(bh)), \
+ "rI" ((USItype)(al)), \
+ "r" ((USItype)(bl))); \
+ else if (__builtin_constant_p (bh) && (bh) == 0) \
+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "r" ((USItype)(ah)), \
+ "rI" ((USItype)(al)), \
+ "r" ((USItype)(bl))); \
+ else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0) \
+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "r" ((USItype)(ah)), \
+ "rI" ((USItype)(al)), \
+ "r" ((USItype)(bl))); \
+ else \
+ __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "r" ((USItype)(ah)), \
+ "r" ((USItype)(bh)), \
+ "rI" ((USItype)(al)), \
+ "r" ((USItype)(bl))); \
+ } while (0)
+#define count_leading_zeros(count, x) \
+ __asm__ ("{cntlz|cntlzw} %0,%1" \
+ : "=r" ((USItype)(count)) \
+ : "r" ((USItype)(x)))
+#define COUNT_LEADING_ZEROS_0 32
+#if defined (_ARCH_PPC)
+#define umul_ppmm(ph, pl, m0, m1) \
+ do { \
+ USItype __m0 = (m0), __m1 = (m1); \
+ __asm__ ("mulhwu %0,%1,%2" \
+ : "=r" ((USItype) ph) \
+ : "%r" (__m0), \
+ "r" (__m1)); \
+ (pl) = __m0 * __m1; \
+ } while (0)
+#define UMUL_TIME 15
+#define smul_ppmm(ph, pl, m0, m1) \
+ do { \
+ SItype __m0 = (m0), __m1 = (m1); \
+ __asm__ ("mulhw %0,%1,%2" \
+ : "=r" ((SItype) ph) \
+ : "%r" (__m0), \
+ "r" (__m1)); \
+ (pl) = __m0 * __m1; \
+ } while (0)
+#define SMUL_TIME 14
+#define UDIV_TIME 120
+#else
+#define umul_ppmm(xh, xl, m0, m1) \
+ do { \
+ USItype __m0 = (m0), __m1 = (m1); \
+ __asm__ ("mul %0,%2,%3" \
+ : "=r" ((USItype)(xh)), \
+ "=q" ((USItype)(xl)) \
+ : "r" (__m0), \
+ "r" (__m1)); \
+ (xh) += ((((SItype) __m0 >> 31) & __m1) \
+ + (((SItype) __m1 >> 31) & __m0)); \
+ } while (0)
+#define UMUL_TIME 8
+#define smul_ppmm(xh, xl, m0, m1) \
+ __asm__ ("mul %0,%2,%3" \
+ : "=r" ((SItype)(xh)), \
+ "=q" ((SItype)(xl)) \
+ : "r" (m0), \
+ "r" (m1))
+#define SMUL_TIME 4
+#define sdiv_qrnnd(q, r, nh, nl, d) \
+ __asm__ ("div %0,%2,%4" \
+ : "=r" ((SItype)(q)), "=q" ((SItype)(r)) \
+ : "r" ((SItype)(nh)), "1" ((SItype)(nl)), "r" ((SItype)(d)))
+#define UDIV_TIME 100
+#endif
+#endif /* Power architecture variants. */
+
+#if defined (__pyr__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("addw %5,%1
+ addwc %3,%0" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "%0" ((USItype)(ah)), \
+ "g" ((USItype)(bh)), \
+ "%1" ((USItype)(al)), \
+ "g" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("subw %5,%1
+ subwb %3,%0" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "0" ((USItype)(ah)), \
+ "g" ((USItype)(bh)), \
+ "1" ((USItype)(al)), \
+ "g" ((USItype)(bl)))
+/* This insn works on Pyramids with AP, XP, or MI CPUs, but not with SP. */
+#define umul_ppmm(w1, w0, u, v) \
+ ({union {UDItype __ll; \
+ struct {USItype __h, __l;} __i; \
+ } __xx; \
+ __asm__ ("movw %1,%R0
+ uemul %2,%0" \
+ : "=&r" (__xx.__ll) \
+ : "g" ((USItype) (u)), \
+ "g" ((USItype)(v))); \
+ (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
+#endif /* __pyr__ */
+
+#if defined (__ibm032__) /* RT/ROMP */ && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("a %1,%5
+ ae %0,%3" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "%0" ((USItype)(ah)), \
+ "r" ((USItype)(bh)), \
+ "%1" ((USItype)(al)), \
+ "r" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("s %1,%5
+ se %0,%3" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "0" ((USItype)(ah)), \
+ "r" ((USItype)(bh)), \
+ "1" ((USItype)(al)), \
+ "r" ((USItype)(bl)))
+#define umul_ppmm(ph, pl, m0, m1) \
+ do { \
+ USItype __m0 = (m0), __m1 = (m1); \
+ __asm__ ( \
+ "s r2,r2
+ mts r10,%2
+ m r2,%3
+ m r2,%3
+ m r2,%3
+ m r2,%3
+ m r2,%3
+ m r2,%3
+ m r2,%3
+ m r2,%3
+ m r2,%3
+ m r2,%3
+ m r2,%3
+ m r2,%3
+ m r2,%3
+ m r2,%3
+ m r2,%3
+ m r2,%3
+ cas %0,r2,r0
+ mfs r10,%1" \
+ : "=r" ((USItype)(ph)), \
+ "=r" ((USItype)(pl)) \
+ : "%r" (__m0), \
+ "r" (__m1) \
+ : "r2"); \
+ (ph) += ((((SItype) __m0 >> 31) & __m1) \
+ + (((SItype) __m1 >> 31) & __m0)); \
+ } while (0)
+#define UMUL_TIME 20
+#define UDIV_TIME 200
+#define count_leading_zeros(count, x) \
+ do { \
+ if ((x) >= 0x10000) \
+ __asm__ ("clz %0,%1" \
+ : "=r" ((USItype)(count)) \
+ : "r" ((USItype)(x) >> 16)); \
+ else \
+ { \
+ __asm__ ("clz %0,%1" \
+ : "=r" ((USItype)(count)) \
+ : "r" ((USItype)(x))); \
+ (count) += 16; \
+ } \
+ } while (0)
+#endif /* RT/ROMP */
+
+#if defined (__sh2__) && W_TYPE_SIZE == 32
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ( \
+ "dmulu.l %2,%3
+ sts macl,%1
+ sts mach,%0" \
+ : "=r" ((USItype)(w1)), \
+ "=r" ((USItype)(w0)) \
+ : "r" ((USItype)(u)), \
+ "r" ((USItype)(v)) \
+ : "macl", "mach")
+#define UMUL_TIME 5
+#endif
+
+#if defined (__sparc__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("addcc %r4,%5,%1
+ addx %r2,%3,%0" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "%rJ" ((USItype)(ah)), \
+ "rI" ((USItype)(bh)), \
+ "%rJ" ((USItype)(al)), \
+ "rI" ((USItype)(bl)) \
+ __CLOBBER_CC)
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("subcc %r4,%5,%1
+ subx %r2,%3,%0" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "rJ" ((USItype)(ah)), \
+ "rI" ((USItype)(bh)), \
+ "rJ" ((USItype)(al)), \
+ "rI" ((USItype)(bl)) \
+ __CLOBBER_CC)
+#if defined (__sparc_v8__)
+/* Don't match immediate range because, 1) it is not often useful,
+ 2) the 'I' flag thinks of the range as a 13 bit signed interval,
+ while we want to match a 13 bit interval, sign extended to 32 bits,
+ but INTERPRETED AS UNSIGNED. */
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ("umul %2,%3,%1;rd %%y,%0" \
+ : "=r" ((USItype)(w1)), \
+ "=r" ((USItype)(w0)) \
+ : "r" ((USItype)(u)), \
+ "r" ((USItype)(v)))
+#define UMUL_TIME 5
+#ifndef SUPERSPARC /* SuperSPARC's udiv only handles 53 bit dividends */
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ do { \
+ USItype __q; \
+ __asm__ ("mov %1,%%y;nop;nop;nop;udiv %2,%3,%0" \
+ : "=r" ((USItype)(__q)) \
+ : "r" ((USItype)(n1)), \
+ "r" ((USItype)(n0)), \
+ "r" ((USItype)(d))); \
+ (r) = (n0) - __q * (d); \
+ (q) = __q; \
+ } while (0)
+#define UDIV_TIME 25
+#endif /* SUPERSPARC */
+#else /* ! __sparc_v8__ */
+#if defined (__sparclite__)
+/* This has hardware multiply but not divide. It also has two additional
+ instructions scan (ffs from high bit) and divscc. */
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ("umul %2,%3,%1;rd %%y,%0" \
+ : "=r" ((USItype)(w1)), \
+ "=r" ((USItype)(w0)) \
+ : "r" ((USItype)(u)), \
+ "r" ((USItype)(v)))
+#define UMUL_TIME 5
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ __asm__ ("! Inlined udiv_qrnnd
+ wr %%g0,%2,%%y ! Not a delayed write for sparclite
+ tst %%g0
+ divscc %3,%4,%%g1
+ divscc %%g1,%4,%%g1
+ divscc %%g1,%4,%%g1
+ divscc %%g1,%4,%%g1
+ divscc %%g1,%4,%%g1
+ divscc %%g1,%4,%%g1
+ divscc %%g1,%4,%%g1
+ divscc %%g1,%4,%%g1
+ divscc %%g1,%4,%%g1
+ divscc %%g1,%4,%%g1
+ divscc %%g1,%4,%%g1
+ divscc %%g1,%4,%%g1
+ divscc %%g1,%4,%%g1
+ divscc %%g1,%4,%%g1
+ divscc %%g1,%4,%%g1
+ divscc %%g1,%4,%%g1
+ divscc %%g1,%4,%%g1
+ divscc %%g1,%4,%%g1
+ divscc %%g1,%4,%%g1
+ divscc %%g1,%4,%%g1
+ divscc %%g1,%4,%%g1
+ divscc %%g1,%4,%%g1
+ divscc %%g1,%4,%%g1
+ divscc %%g1,%4,%%g1
+ divscc %%g1,%4,%%g1
+ divscc %%g1,%4,%%g1
+ divscc %%g1,%4,%%g1
+ divscc %%g1,%4,%%g1
+ divscc %%g1,%4,%%g1
+ divscc %%g1,%4,%%g1
+ divscc %%g1,%4,%%g1
+ divscc %%g1,%4,%0
+ rd %%y,%1
+ bl,a 1f
+ add %1,%4,%1
+1: ! End of inline udiv_qrnnd" \
+ : "=r" ((USItype)(q)), \
+ "=r" ((USItype)(r)) \
+ : "r" ((USItype)(n1)), \
+ "r" ((USItype)(n0)), \
+ "rI" ((USItype)(d)) \
+ : "%g1" __AND_CLOBBER_CC)
+#define UDIV_TIME 37
+#define count_leading_zeros(count, x) \
+ __asm__ ("scan %1,0,%0" \
+ : "=r" ((USItype)(x)) \
+ : "r" ((USItype)(count)))
+/* Early sparclites return 63 for an argument of 0, but they warn that future
+ implementations might change this. Therefore, leave COUNT_LEADING_ZEROS_0
+ undefined. */
+#endif /* __sparclite__ */
+#endif /* __sparc_v8__ */
+/* Default to sparc v7 versions of umul_ppmm and udiv_qrnnd. */
+#ifndef umul_ppmm
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ("! Inlined umul_ppmm
+ wr %%g0,%2,%%y ! SPARC has 0-3 delay insn after a wr
+ sra %3,31,%%g2 ! Don't move this insn
+ and %2,%%g2,%%g2 ! Don't move this insn
+ andcc %%g0,0,%%g1 ! Don't move this insn
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,%3,%%g1
+ mulscc %%g1,0,%%g1
+ add %%g1,%%g2,%0
+ rd %%y,%1" \
+ : "=r" ((USItype)(w1)), \
+ "=r" ((USItype)(w0)) \
+ : "%rI" ((USItype)(u)), \
+ "r" ((USItype)(v)) \
+ : "%g1", "%g2" __AND_CLOBBER_CC)
+#define UMUL_TIME 39 /* 39 instructions */
+#endif
+#ifndef udiv_qrnnd
+#ifndef LONGLONG_STANDALONE
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ do { USItype __r; \
+ (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \
+ (r) = __r; \
+ } while (0)
+extern USItype __udiv_qrnnd ();
+#define UDIV_TIME 140
+#endif /* LONGLONG_STANDALONE */
+#endif /* udiv_qrnnd */
+#endif /* __sparc__ */
+
+#if defined (__vax__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("addl2 %5,%1
+ adwc %3,%0" \
+ : "=g" ((USItype)(sh)), \
+ "=&g" ((USItype)(sl)) \
+ : "%0" ((USItype)(ah)), \
+ "g" ((USItype)(bh)), \
+ "%1" ((USItype)(al)), \
+ "g" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("subl2 %5,%1
+ sbwc %3,%0" \
+ : "=g" ((USItype)(sh)), \
+ "=&g" ((USItype)(sl)) \
+ : "0" ((USItype)(ah)), \
+ "g" ((USItype)(bh)), \
+ "1" ((USItype)(al)), \
+ "g" ((USItype)(bl)))
+#define umul_ppmm(xh, xl, m0, m1) \
+ do { \
+ union {UDItype __ll; \
+ struct {USItype __l, __h;} __i; \
+ } __xx; \
+ USItype __m0 = (m0), __m1 = (m1); \
+ __asm__ ("emul %1,%2,$0,%0" \
+ : "=g" (__xx.__ll) \
+ : "g" (__m0), \
+ "g" (__m1)); \
+ (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \
+ (xh) += ((((SItype) __m0 >> 31) & __m1) \
+ + (((SItype) __m1 >> 31) & __m0)); \
+ } while (0)
+#define sdiv_qrnnd(q, r, n1, n0, d) \
+ do { \
+ union {DItype __ll; \
+ struct {SItype __l, __h;} __i; \
+ } __xx; \
+ __xx.__i.__h = n1; __xx.__i.__l = n0; \
+ __asm__ ("ediv %3,%2,%0,%1" \
+ : "=g" (q), "=g" (r) \
+ : "g" (__xx.ll), "g" (d)); \
+ } while (0)
+#endif /* __vax__ */
+
+#if defined (__z8000__) && W_TYPE_SIZE == 16
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("add %H1,%H5\n\tadc %H0,%H3" \
+ : "=r" ((unsigned int)(sh)), \
+ "=&r" ((unsigned int)(sl)) \
+ : "%0" ((unsigned int)(ah)), \
+ "r" ((unsigned int)(bh)), \
+ "%1" ((unsigned int)(al)), \
+ "rQR" ((unsigned int)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("sub %H1,%H5\n\tsbc %H0,%H3" \
+ : "=r" ((unsigned int)(sh)), \
+ "=&r" ((unsigned int)(sl)) \
+ : "0" ((unsigned int)(ah)), \
+ "r" ((unsigned int)(bh)), \
+ "1" ((unsigned int)(al)), \
+ "rQR" ((unsigned int)(bl)))
+#define umul_ppmm(xh, xl, m0, m1) \
+ do { \
+ union {long int __ll; \
+ struct {unsigned int __h, __l;} __i; \
+ } __xx; \
+ unsigned int __m0 = (m0), __m1 = (m1); \
+ __asm__ ("mult %S0,%H3" \
+ : "=r" (__xx.__i.__h), \
+ "=r" (__xx.__i.__l) \
+ : "%1" (__m0), \
+ "rQR" (__m1)); \
+ (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \
+ (xh) += ((((signed int) __m0 >> 15) & __m1) \
+ + (((signed int) __m1 >> 15) & __m0)); \
+ } while (0)
+#endif /* __z8000__ */
+
+#endif /* __GNUC__ */
+
+
+#if !defined (umul_ppmm) && defined (__umulsidi3)
+#define umul_ppmm(ph, pl, m0, m1) \
+ { \
+ UDWtype __ll = __umulsidi3 (m0, m1); \
+ ph = (UWtype) (__ll >> W_TYPE_SIZE); \
+ pl = (UWtype) __ll; \
+ }
+#endif
+
+#if !defined (__umulsidi3)
+#define __umulsidi3(u, v) \
+ ({UWtype __hi, __lo; \
+ umul_ppmm (__hi, __lo, u, v); \
+ ((UDWtype) __hi << W_TYPE_SIZE) | __lo; })
+#endif
+
+/* If this machine has no inline assembler, use C macros. */
+
+#if !defined (add_ssaaaa)
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ do { \
+ UWtype __x; \
+ __x = (al) + (bl); \
+ (sh) = (ah) + (bh) + (__x < (al)); \
+ (sl) = __x; \
+ } while (0)
+#endif
+
+#if !defined (sub_ddmmss)
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ do { \
+ UWtype __x; \
+ __x = (al) - (bl); \
+ (sh) = (ah) - (bh) - (__x > (al)); \
+ (sl) = __x; \
+ } while (0)
+#endif
+
+#if !defined (umul_ppmm)
+#define umul_ppmm(w1, w0, u, v) \
+ do { \
+ UWtype __x0, __x1, __x2, __x3; \
+ UHWtype __ul, __vl, __uh, __vh; \
+ UWtype __u = (u), __v = (v); \
+ \
+ __ul = __ll_lowpart (__u); \
+ __uh = __ll_highpart (__u); \
+ __vl = __ll_lowpart (__v); \
+ __vh = __ll_highpart (__v); \
+ \
+ __x0 = (UWtype) __ul * __vl; \
+ __x1 = (UWtype) __ul * __vh; \
+ __x2 = (UWtype) __uh * __vl; \
+ __x3 = (UWtype) __uh * __vh; \
+ \
+ __x1 += __ll_highpart (__x0);/* this can't give carry */ \
+ __x1 += __x2; /* but this indeed can */ \
+ if (__x1 < __x2) /* did we get it? */ \
+ __x3 += __ll_B; /* yes, add it in the proper pos. */ \
+ \
+ (w1) = __x3 + __ll_highpart (__x1); \
+ (w0) = (__ll_lowpart (__x1) << W_TYPE_SIZE/2) + __ll_lowpart (__x0);\
+ } while (0)
+#endif
+
+#if !defined (umul_ppmm)
+#define smul_ppmm(w1, w0, u, v) \
+ do { \
+ UWtype __w1; \
+ UWtype __m0 = (u), __m1 = (v); \
+ umul_ppmm (__w1, w0, __m0, __m1); \
+ (w1) = __w1 - (-(__m0 >> (W_TYPE_SIZE - 1)) & __m1) \
+ - (-(__m1 >> (W_TYPE_SIZE - 1)) & __m0); \
+ } while (0)
+#endif
+
+/* Define this unconditionally, so it can be used for debugging. */
+#define __udiv_qrnnd_c(q, r, n1, n0, d) \
+ do { \
+ UWtype __d1, __d0, __q1, __q0, __r1, __r0, __m; \
+ __d1 = __ll_highpart (d); \
+ __d0 = __ll_lowpart (d); \
+ \
+ __r1 = (n1) % __d1; \
+ __q1 = (n1) / __d1; \
+ __m = (UWtype) __q1 * __d0; \
+ __r1 = __r1 * __ll_B | __ll_highpart (n0); \
+ if (__r1 < __m) \
+ { \
+ __q1--, __r1 += (d); \
+ if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\
+ if (__r1 < __m) \
+ __q1--, __r1 += (d); \
+ } \
+ __r1 -= __m; \
+ \
+ __r0 = __r1 % __d1; \
+ __q0 = __r1 / __d1; \
+ __m = (UWtype) __q0 * __d0; \
+ __r0 = __r0 * __ll_B | __ll_lowpart (n0); \
+ if (__r0 < __m) \
+ { \
+ __q0--, __r0 += (d); \
+ if (__r0 >= (d)) \
+ if (__r0 < __m) \
+ __q0--, __r0 += (d); \
+ } \
+ __r0 -= __m; \
+ \
+ (q) = (UWtype) __q1 * __ll_B | __q0; \
+ (r) = __r0; \
+ } while (0)
+
+/* If the processor has no udiv_qrnnd but sdiv_qrnnd, go through
+ __udiv_w_sdiv (defined in libgcc or elsewhere). */
+#if !defined (udiv_qrnnd) && defined (sdiv_qrnnd)
+#define udiv_qrnnd(q, r, nh, nl, d) \
+ do { \
+ UWtype __r; \
+ (q) = __MPN(udiv_w_sdiv) (&__r, nh, nl, d); \
+ (r) = __r; \
+ } while (0)
+#endif
+
+/* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c. */
+#if !defined (udiv_qrnnd)
+#define UDIV_NEEDS_NORMALIZATION 1
+#define udiv_qrnnd __udiv_qrnnd_c
+#endif
+
+#if !defined (count_leading_zeros)
+extern
+#ifdef __STDC__
+const
+#endif
+unsigned char __clz_tab[];
+#define count_leading_zeros(count, x) \
+ do { \
+ UWtype __xr = (x); \
+ UWtype __a; \
+ \
+ if (W_TYPE_SIZE <= 32) \
+ { \
+ __a = __xr < ((UWtype) 1 << 2*__BITS4) \
+ ? (__xr < ((UWtype) 1 << __BITS4) ? 0 : __BITS4) \
+ : (__xr < ((UWtype) 1 << 3*__BITS4) ? 2*__BITS4 : 3*__BITS4);\
+ } \
+ else \
+ { \
+ for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \
+ if (((__xr >> __a) & 0xff) != 0) \
+ break; \
+ } \
+ \
+ (count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \
+ } while (0)
+/* This version gives a well-defined value for zero. */
+#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE
+#endif
+
+#if !defined (count_trailing_zeros)
+/* Define count_trailing_zeros using count_leading_zeros. The latter might be
+ defined in asm, but if it is not, the C version above is good enough. */
+#define count_trailing_zeros(count, x) \
+ do { \
+ UWtype __ctz_x = (x); \
+ UWtype __ctz_c; \
+ count_leading_zeros (__ctz_c, __ctz_x & -__ctz_x); \
+ (count) = W_TYPE_SIZE - 1 - __ctz_c; \
+ } while (0)
+#endif
+
+#ifndef UDIV_NEEDS_NORMALIZATION
+#define UDIV_NEEDS_NORMALIZATION 0
+#endif
diff --git a/make.bat b/make.bat
new file mode 100755
index 000000000..6272dd508
--- /dev/null
+++ b/make.bat
@@ -0,0 +1,303 @@
+cd mpn
+copy msdos\asm-synt.h asm-synt.h
+copy bsd.h sysdep.h
+copy generic\inlines.c inlines.c
+copy x86\pentium\add_n.S add_n.S
+copy x86\pentium\addmul_1.S addmul_1.S
+copy generic\cmp.c cmp.c
+copy generic\divmod_1.c divmod_1.c
+copy generic\divrem.c divrem.c
+copy generic\divrem_1.c divrem_1.c
+copy generic\dump.c dump.c
+copy x86\pentium\lshift.S lshift.S
+copy generic\mod_1.c mod_1.c
+copy generic\mul.c mul.c
+copy x86\pentium\mul_1.S mul_1.S
+copy generic\mul_n.c mul_n.c
+copy generic\random2.c random2.c
+copy x86\pentium\rshift.S rshift.S
+copy generic\sqrtrem.c sqrtrem.c
+copy x86\pentium\sub_n.S sub_n.S
+copy x86\pentium\submul_1.S submul_1.S
+copy generic\get_str.c get_str.c
+copy generic\set_str.c set_str.c
+copy generic\scan0.c scan0.c
+copy generic\scan1.c scan1.c
+copy generic\popcount.c popcount.c
+copy generic\hamdist.c hamdist.c
+copy generic\gcd_1.c gcd_1.c
+copy generic\pre_mod_1.c pre_mod_1.c
+copy generic\perfsqr.c perfsqr.c
+copy generic\bdivmod.c bdivmod.c
+copy generic\gcd.c gcd.c
+copy generic\gcdext.c gcdext.c
+copy x86\gmp-mpar.h gmp-mpar.h
+cd ..
+
+cd mpbsd
+copy ..\mpz\add.c add.c
+copy ..\mpz\cmp.c cmp.c
+copy ..\mpz\gcd.c gcd.c
+copy ..\mpz\mul.c mul.c
+copy ..\mpz\pow_ui.c pow_ui.c
+copy ..\mpz\powm.c powm.c
+copy ..\mpz\sqrtrem.c sqrtrem.c
+copy ..\mpz\sub.c sub.c
+cd ..
+
+cd mpn
+gcc -c -I. -I.. -g -O mp_bases.c
+gcc -c -I. -I.. -g -O inlines.c
+gcc -E -I. -I.. -g -O add_n.S | grep -v '^#' >tmp-add_n.s
+gcc -c tmp-add_n.s -o add_n.o
+del tmp-add_n.s
+gcc -E -I. -I.. -g -O addmul_1.S | grep -v '^#' >tmp-addmul_1.s
+gcc -c tmp-addmul_1.s -o addmul_1.o
+del tmp-addmul_1.s
+gcc -c -I. -I.. -g -O cmp.c
+gcc -c -I. -I.. -g -O divmod_1.c
+gcc -c -I. -I.. -g -O divrem.c
+gcc -c -I. -I.. -g -O divrem_1.c
+gcc -c -I. -I.. -g -O dump.c
+gcc -E -I. -I.. -g -O lshift.S | grep -v '^#' >tmp-lshift.s
+gcc -c tmp-lshift.s -o lshift.o
+del tmp-lshift.s
+gcc -c -I. -I.. -g -O mod_1.c
+gcc -c -I. -I.. -g -O mul.c
+gcc -E -I. -I.. -g -O mul_1.S | grep -v '^#' >tmp-mul_1.s
+gcc -c tmp-mul_1.s -o mul_1.o
+del tmp-mul_1.s
+gcc -c -I. -I.. -g -O mul_n.c
+gcc -c -I. -I.. -g -O random2.c
+gcc -E -I. -I.. -g -O rshift.S | grep -v '^#' >tmp-rshift.s
+gcc -c tmp-rshift.s -o rshift.o
+del tmp-rshift.s
+gcc -c -I. -I.. -g -O sqrtrem.c
+gcc -E -I. -I.. -g -O sub_n.S | grep -v '^#' >tmp-sub_n.s
+gcc -c tmp-sub_n.s -o sub_n.o
+del tmp-sub_n.s
+gcc -E -I. -I.. -g -O submul_1.S | grep -v '^#' >tmp-submul_1.s
+gcc -c tmp-submul_1.s -o submul_1.o
+del tmp-submul_1.s
+gcc -c -I. -I.. -g -O get_str.c
+gcc -c -I. -I.. -g -O set_str.c
+gcc -c -I. -I.. -g -O scan0.c
+gcc -c -I. -I.. -g -O scan1.c
+gcc -c -I. -I.. -g -O popcount.c
+gcc -c -I. -I.. -g -O hamdist.c
+gcc -c -I. -I.. -g -O gcd_1.c
+gcc -c -I. -I.. -g -O pre_mod_1.c
+gcc -c -I. -I.. -g -O perfsqr.c
+gcc -c -I. -I.. -g -O bdivmod.c
+gcc -c -I. -I.. -g -O gcd.c
+gcc -c -I. -I.. -g -O gcdext.c
+del libmpn.a
+ar rc libmpn.a *.o
+cd ..
+
+cd mpz
+gcc -c -I. -I.. -I../mpn -g -O init.c
+gcc -c -I. -I.. -I../mpn -g -O set.c
+gcc -c -I. -I.. -I../mpn -g -O set_ui.c
+gcc -c -I. -I.. -I../mpn -g -O set_si.c
+gcc -c -I. -I.. -I../mpn -g -O set_str.c
+gcc -c -I. -I.. -I../mpn -g -O iset.c
+gcc -c -I. -I.. -I../mpn -g -O iset_ui.c
+gcc -c -I. -I.. -I../mpn -g -O iset_si.c
+gcc -c -I. -I.. -I../mpn -g -O iset_str.c
+gcc -c -I. -I.. -I../mpn -g -O clear.c
+gcc -c -I. -I.. -I../mpn -g -O get_ui.c
+gcc -c -I. -I.. -I../mpn -g -O get_si.c
+gcc -c -I. -I.. -I../mpn -g -O get_str.c
+gcc -c -I. -I.. -I../mpn -g -O size.c
+gcc -c -I. -I.. -I../mpn -g -O sizeinbase.c
+gcc -c -I. -I.. -I../mpn -g -O add.c
+gcc -c -I. -I.. -I../mpn -g -O add_ui.c
+gcc -c -I. -I.. -I../mpn -g -O sub.c
+gcc -c -I. -I.. -I../mpn -g -O sub_ui.c
+gcc -c -I. -I.. -I../mpn -g -O mul.c
+gcc -c -I. -I.. -I../mpn -g -O mul_ui.c
+gcc -c -I. -I.. -I../mpn -g -O gcd.c
+gcc -c -I. -I.. -I../mpn -g -O gcd_ui.c
+gcc -c -I. -I.. -I../mpn -g -O gcdext.c
+gcc -c -I. -I.. -I../mpn -g -O sqrt.c
+gcc -c -I. -I.. -I../mpn -g -O sqrtrem.c
+gcc -c -I. -I.. -I../mpn -g -O powm.c
+gcc -c -I. -I.. -I../mpn -g -O powm_ui.c
+gcc -c -I. -I.. -I../mpn -g -O cmp.c
+gcc -c -I. -I.. -I../mpn -g -O cmp_ui.c
+gcc -c -I. -I.. -I../mpn -g -O cmp_si.c
+gcc -c -I. -I.. -I../mpn -g -O mul_2exp.c
+gcc -c -I. -I.. -I../mpn -g -O fdiv_q_2exp.c
+gcc -c -I. -I.. -I../mpn -g -O fdiv_r_2exp.c
+gcc -c -I. -I.. -I../mpn -g -O tdiv_q_2exp.c
+gcc -c -I. -I.. -I../mpn -g -O tdiv_r_2exp.c
+gcc -c -I. -I.. -I../mpn -g -O abs.c
+gcc -c -I. -I.. -I../mpn -g -O neg.c
+gcc -c -I. -I.. -I../mpn -g -O com.c
+gcc -c -I. -I.. -I../mpn -g -O and.c
+gcc -c -I. -I.. -I../mpn -g -O ior.c
+gcc -c -I. -I.. -I../mpn -g -O inp_raw.c
+gcc -c -I. -I.. -I../mpn -g -O inp_str.c
+gcc -c -I. -I.. -I../mpn -g -O out_raw.c
+gcc -c -I. -I.. -I../mpn -g -O out_str.c
+gcc -c -I. -I.. -I../mpn -g -O perfsqr.c
+gcc -c -I. -I.. -I../mpn -g -O random.c
+gcc -c -I. -I.. -I../mpn -g -O random2.c
+gcc -c -I. -I.. -I../mpn -g -O pow_ui.c
+gcc -c -I. -I.. -I../mpn -g -O ui_pow_ui.c
+gcc -c -I. -I.. -I../mpn -g -O setbit.c
+gcc -c -I. -I.. -I../mpn -g -O clrbit.c
+gcc -c -I. -I.. -I../mpn -g -O fac_ui.c
+gcc -c -I. -I.. -I../mpn -g -O pprime_p.c
+gcc -c -I. -I.. -I../mpn -g -O realloc.c
+gcc -c -I. -I.. -I../mpn -g -O getlimbn.c
+gcc -c -I. -I.. -I../mpn -g -O popcount.c
+gcc -c -I. -I.. -I../mpn -g -O hamdist.c
+gcc -c -I. -I.. -I../mpn -g -O cdiv_qr.c
+gcc -c -I. -I.. -I../mpn -g -O cdiv_q.c
+gcc -c -I. -I.. -I../mpn -g -O cdiv_r.c
+gcc -c -I. -I.. -I../mpn -g -O cdiv_qr_ui.c
+gcc -c -I. -I.. -I../mpn -g -O cdiv_q_ui.c
+gcc -c -I. -I.. -I../mpn -g -O cdiv_r_ui.c
+gcc -c -I. -I.. -I../mpn -g -O cdiv_ui.c
+gcc -c -I. -I.. -I../mpn -g -O fdiv_qr.c
+gcc -c -I. -I.. -I../mpn -g -O fdiv_q.c
+gcc -c -I. -I.. -I../mpn -g -O fdiv_r.c
+gcc -c -I. -I.. -I../mpn -g -O fdiv_qr_ui.c
+gcc -c -I. -I.. -I../mpn -g -O fdiv_q_ui.c
+gcc -c -I. -I.. -I../mpn -g -O fdiv_r_ui.c
+gcc -c -I. -I.. -I../mpn -g -O fdiv_ui.c
+gcc -c -I. -I.. -I../mpn -g -O tdiv_qr.c
+gcc -c -I. -I.. -I../mpn -g -O tdiv_q.c
+gcc -c -I. -I.. -I../mpn -g -O tdiv_r.c
+gcc -c -I. -I.. -I../mpn -g -O tdiv_qr_ui.c
+gcc -c -I. -I.. -I../mpn -g -O tdiv_q_ui.c
+gcc -c -I. -I.. -I../mpn -g -O tdiv_r_ui.c
+gcc -c -I. -I.. -I../mpn -g -O mod.c
+gcc -c -I. -I.. -I../mpn -g -O set_d.c
+gcc -c -I. -I.. -I../mpn -g -O iset_d.c
+gcc -c -I. -I.. -I../mpn -g -O divexact.c
+gcc -c -I. -I.. -I../mpn -g -O array_init.c
+gcc -c -I. -I.. -I../mpn -g -O scan0.c
+gcc -c -I. -I.. -I../mpn -g -O scan1.c
+gcc -c -I. -I.. -I../mpn -g -O jacobi.c
+gcc -c -I. -I.. -I../mpn -g -O legendre.c
+gcc -c -I. -I.. -I../mpn -g -O invert.c
+del libmpz.a
+ar rc libmpz.a *.o
+cd ..
+
+cd mpf
+gcc -c -I. -I.. -I../mpn -g -O init.c
+gcc -c -I. -I.. -I../mpn -g -O init2.c
+gcc -c -I. -I.. -I../mpn -g -O set.c
+gcc -c -I. -I.. -I../mpn -g -O set_ui.c
+gcc -c -I. -I.. -I../mpn -g -O set_si.c
+gcc -c -I. -I.. -I../mpn -g -O set_str.c
+gcc -c -I. -I.. -I../mpn -g -O set_d.c
+gcc -c -I. -I.. -I../mpn -g -O iset.c
+gcc -c -I. -I.. -I../mpn -g -O iset_ui.c
+gcc -c -I. -I.. -I../mpn -g -O iset_si.c
+gcc -c -I. -I.. -I../mpn -g -O iset_str.c
+gcc -c -I. -I.. -I../mpn -g -O iset_d.c
+gcc -c -I. -I.. -I../mpn -g -O clear.c
+gcc -c -I. -I.. -I../mpn -g -O get_str.c
+gcc -c -I. -I.. -I../mpn -g -O dump.c
+gcc -c -I. -I.. -I../mpn -g -O size.c
+gcc -c -I. -I.. -I../mpn -g -O eq.c
+gcc -c -I. -I.. -I../mpn -g -O reldiff.c
+gcc -c -I. -I.. -I../mpn -g -O sqrt.c
+gcc -c -I. -I.. -I../mpn -g -O random2.c
+gcc -c -I. -I.. -I../mpn -g -O inp_str.c
+gcc -c -I. -I.. -I../mpn -g -O out_str.c
+gcc -c -I. -I.. -I../mpn -g -O add.c
+gcc -c -I. -I.. -I../mpn -g -O add_ui.c
+gcc -c -I. -I.. -I../mpn -g -O sub.c
+gcc -c -I. -I.. -I../mpn -g -O sub_ui.c
+gcc -c -I. -I.. -I../mpn -g -O ui_sub.c
+gcc -c -I. -I.. -I../mpn -g -O mul.c
+gcc -c -I. -I.. -I../mpn -g -O mul_ui.c
+gcc -c -I. -I.. -I../mpn -g -O div.c
+gcc -c -I. -I.. -I../mpn -g -O div_ui.c
+gcc -c -I. -I.. -I../mpn -g -O cmp.c
+gcc -c -I. -I.. -I../mpn -g -O cmp_ui.c
+gcc -c -I. -I.. -I../mpn -g -O cmp_si.c
+gcc -c -I. -I.. -I../mpn -g -O mul_2exp.c
+gcc -c -I. -I.. -I../mpn -g -O div_2exp.c
+gcc -c -I. -I.. -I../mpn -g -O abs.c
+gcc -c -I. -I.. -I../mpn -g -O neg.c
+gcc -c -I. -I.. -I../mpn -g -O set_dfl_prec.c
+gcc -c -I. -I.. -I../mpn -g -O set_prec.c
+gcc -c -I. -I.. -I../mpn -g -O ui_div.c
+gcc -c -I. -I.. -I../mpn -g -O sqrt_ui.c
+del libmpf.a
+ar cr libmpf.a *.o
+cd ..
+
+cd mpq
+gcc -c -I. -I.. -I../mpn -g -O add.c
+gcc -c -I. -I.. -I../mpn -g -O canonicalize.c
+gcc -c -I. -I.. -I../mpn -g -O clear.c
+gcc -c -I. -I.. -I../mpn -g -O cmp.c
+gcc -c -I. -I.. -I../mpn -g -O cmp_ui.c
+gcc -c -I. -I.. -I../mpn -g -O div.c
+gcc -c -I. -I.. -I../mpn -g -O get_d.c
+gcc -c -I. -I.. -I../mpn -g -O get_den.c
+gcc -c -I. -I.. -I../mpn -g -O get_num.c
+gcc -c -I. -I.. -I../mpn -g -O init.c
+gcc -c -I. -I.. -I../mpn -g -O inv.c
+gcc -c -I. -I.. -I../mpn -g -O mul.c
+gcc -c -I. -I.. -I../mpn -g -O neg.c
+gcc -c -I. -I.. -I../mpn -g -O set.c
+gcc -c -I. -I.. -I../mpn -g -O set_den.c
+gcc -c -I. -I.. -I../mpn -g -O set_num.c
+gcc -c -I. -I.. -I../mpn -g -O set_si.c
+gcc -c -I. -I.. -I../mpn -g -O set_ui.c
+gcc -c -I. -I.. -I../mpn -g -O sub.c
+del libmpq.a
+ar cr libmpq.a *.o
+cd ..
+
+gcc -c -I. -Impn -I.. -g -O memory.c
+gcc -c -I. -Impn -I.. -g -O mp_set_fns.c
+gcc -c -I. -Impn -I.. -g -O mp_clz_tab.c
+gcc -c -I. -Impn -I.. -g -O version.c
+gcc -c -I. -Impn -I.. -g -O stack-alloc.c
+deltree/y tmpdir
+
+md tmpdir
+
+md tmpdir\mpn
+cd tmpdir\mpn
+ar x ../../mpn/libmpn.a
+cd ..\..
+
+md tmpdir\mpz
+cd tmpdir\mpz
+ar x ../../mpz/libmpz.a
+cd ..\..
+
+md tmpdir\mpq
+cd tmpdir\mpq
+ar x ../../mpq/libmpq.a
+cd ..\..
+
+md tmpdir\mpf
+cd tmpdir\mpf
+ar x ../../mpf/libmpf.a
+cd ..\..
+
+copy memory.o tmpdir
+copy mp_set_fns.o tmpdir
+copy mp_clz_tab.o tmpdir
+copy version.o tmpdir
+copy stack-alloc.o tmpdir
+
+cd tmpdir
+ar rc libgmp.a *.o */*.o
+ranlib libgmp.a
+cd ..
+
+move/y tmpdir\libgmp.a libgmp.a
+deltree/y tmpdir
diff --git a/memory.c b/memory.c
new file mode 100644
index 000000000..9ee1da8a1
--- /dev/null
+++ b/memory.c
@@ -0,0 +1,97 @@
+/* Memory allocation routines.
+
+Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+#ifdef __NeXT__
+#define static
+#endif
+
+#if __STDC__
+void * (*_mp_allocate_func) (size_t) = _mp_default_allocate;
+void * (*_mp_reallocate_func) (void *, size_t, size_t)
+ = _mp_default_reallocate;
+void (*_mp_free_func) (void *, size_t) = _mp_default_free;
+#else
+void * (*_mp_allocate_func) () = _mp_default_allocate;
+void * (*_mp_reallocate_func) () = _mp_default_reallocate;
+void (*_mp_free_func) () = _mp_default_free;
+#endif
+
+/* Default allocation functions. In case of failure to allocate/reallocate
+ an error message is written to stderr and the program aborts. */
+
+void *
+#if __STDC__
+_mp_default_allocate (size_t size)
+#else
+_mp_default_allocate (size)
+ size_t size;
+#endif
+{
+ void *ret;
+
+ ret = malloc (size);
+ if (ret == 0)
+ {
+ perror ("cannot allocate in gmp");
+ abort ();
+ }
+
+ return ret;
+}
+
+void *
+#if __STDC__
+_mp_default_reallocate (void *oldptr, size_t old_size, size_t new_size)
+#else
+_mp_default_reallocate (oldptr, old_size, new_size)
+ void *oldptr;
+ size_t old_size;
+ size_t new_size;
+#endif
+{
+ void *ret;
+
+ ret = realloc (oldptr, new_size);
+ if (ret == 0)
+ {
+ perror ("cannot allocate in gmp");
+ abort ();
+ }
+
+ return ret;
+}
+
+void
+#if __STDC__
+_mp_default_free (void *blk_ptr, size_t blk_size)
+#else
+_mp_default_free (blk_ptr, blk_size)
+ void *blk_ptr;
+ size_t blk_size;
+#endif
+{
+ free (blk_ptr);
+}
diff --git a/mkinstalldirs b/mkinstalldirs
new file mode 100755
index 000000000..cd1fe0a79
--- /dev/null
+++ b/mkinstalldirs
@@ -0,0 +1,32 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+errstatus=0
+
+for file
+do
+ set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+ shift
+
+ pathcomp=
+ for d in ${1+"$@"} ; do
+ pathcomp="$pathcomp$d"
+ case "$pathcomp" in
+ -* ) pathcomp=./$pathcomp ;;
+ esac
+
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp" 1>&2
+ mkdir "$pathcomp" || errstatus=$?
+ fi
+
+ pathcomp="$pathcomp/"
+ done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
diff --git a/move-if-change b/move-if-change
new file mode 100755
index 000000000..ee9e355e3
--- /dev/null
+++ b/move-if-change
@@ -0,0 +1,15 @@
+#!/bin/sh
+if
+test -r $2
+then
+if
+cmp $1 $2 > /dev/null
+then
+echo $2 is unchanged
+rm -f $1
+else
+mv -f $1 $2
+fi
+else
+mv -f $1 $2
+fi
diff --git a/mp.h b/mp.h
new file mode 100644
index 000000000..830b26b3a
--- /dev/null
+++ b/mp.h
@@ -0,0 +1,141 @@
+/* mp.h -- Definitions for Berkeley compatible multiple precision functions.
+
+Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#ifndef __MP_H__
+
+#ifndef __GNU_MP__
+#define __GNU_MP__ 2
+#define __need_size_t
+#include <stddef.h>
+#undef __need_size_t
+
+#if defined (__STDC__) || defined (__cplusplus)
+#define __gmp_const const
+#else
+#define __gmp_const
+#endif
+
+#if defined (__GNUC__)
+#define __gmp_inline __inline__
+#else
+#define __gmp_inline
+#endif
+
+#ifndef _EXTERN_INLINE
+#ifdef __GNUC__
+#define _EXTERN_INLINE extern __inline__
+#else
+#define _EXTERN_INLINE static
+#endif
+#endif
+
+#ifdef _SHORT_LIMB
+typedef unsigned int mp_limb_t;
+typedef int mp_limb_signed_t;
+#else
+#ifdef _LONG_LONG_LIMB
+typedef unsigned long long int mp_limb_t;
+typedef long long int mp_limb_signed_t;
+#else
+typedef unsigned long int mp_limb_t;
+typedef long int mp_limb_signed_t;
+#endif
+#endif
+
+typedef mp_limb_t * mp_ptr;
+typedef __gmp_const mp_limb_t * mp_srcptr;
+typedef int mp_size_t;
+typedef long int mp_exp_t;
+
+#ifndef __MP_SMALL__
+typedef struct
+{
+ mp_size_t _mp_alloc; /* Number of *limbs* allocated and pointed
+ to by the D field. */
+ mp_size_t _mp_size; /* abs(SIZE) is the number of limbs
+ the last field points to. If SIZE
+ is negative this is a negative
+ number. */
+ mp_limb_t *_mp_d; /* Pointer to the limbs. */
+} __mpz_struct;
+#else
+typedef struct
+{
+ short int _mp_alloc; /* Number of *limbs* allocated and pointed
+ to by the D field. */
+ short int _mp_size; /* abs(SIZE) is the number of limbs
+ the last field points to. If SIZE
+ is negative this is a negative
+ number. */
+ mp_limb_t *_mp_d; /* Pointer to the limbs. */
+} __mpz_struct;
+#endif
+#endif /* __GNU_MP__ */
+
+/* User-visible types. */
+typedef __mpz_struct MINT;
+
+#ifdef __STDC__
+void mp_set_memory_functions (void *(*) (size_t),
+ void *(*) (void *, size_t, size_t),
+ void (*) (void *, size_t));
+MINT *itom (signed short int);
+MINT *xtom (const char *);
+void move (const MINT *, MINT *);
+void madd (const MINT *, const MINT *, MINT *);
+void msub (const MINT *, const MINT *, MINT *);
+void mult (const MINT *, const MINT *, MINT *);
+void mdiv (const MINT *, const MINT *, MINT *, MINT *);
+void sdiv (const MINT *, signed short int, MINT *, signed short int *);
+void msqrt (const MINT *, MINT *, MINT *);
+void pow (const MINT *, const MINT *, const MINT *, MINT *);
+void rpow (const MINT *, signed short int, MINT *);
+void gcd (const MINT *, const MINT *, MINT *);
+int mcmp (const MINT *, const MINT *);
+void min (MINT *);
+void mout (const MINT *);
+char *mtox (const MINT *);
+void mfree (MINT *);
+
+#else
+
+void mp_set_memory_functions ();
+MINT *itom ();
+MINT *xtom ();
+void move ();
+void madd ();
+void msub ();
+void mult ();
+void mdiv ();
+void sdiv ();
+void msqrt ();
+void pow ();
+void rpow ();
+void gcd ();
+int mcmp ();
+void min ();
+void mout ();
+char *mtox ();
+void mfree ();
+#endif
+
+#define __MP_H__
+#endif /* __MP_H__ */
diff --git a/mp_bpl.c b/mp_bpl.c
new file mode 100644
index 000000000..d817ac823
--- /dev/null
+++ b/mp_bpl.c
@@ -0,0 +1,4 @@
+#include "gmp.h"
+#include "gmp-impl.h"
+
+const int mp_bits_per_limb = BITS_PER_MP_LIMB;
diff --git a/mp_clz_tab.c b/mp_clz_tab.c
new file mode 100644
index 000000000..6fd7e9081
--- /dev/null
+++ b/mp_clz_tab.c
@@ -0,0 +1,40 @@
+/* __clz_tab -- support for longlong.h
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#if 0
+#include "gmp.h"
+#include "gmp-impl.h"
+#endif
+
+#if 0
+const
+#endif
+unsigned char __clz_tab[] =
+{
+ 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+};
diff --git a/mp_set_fns.c b/mp_set_fns.c
new file mode 100644
index 000000000..35a462c11
--- /dev/null
+++ b/mp_set_fns.c
@@ -0,0 +1,48 @@
+/* mp_set_memory_functions -- Set the allocate, reallocate, and free functions
+ for use by the mp package.
+
+Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mp_set_memory_functions (void *(*alloc_func) (size_t),
+ void *(*realloc_func) (void *, size_t, size_t),
+ void (*free_func) (void *, size_t))
+#else
+mp_set_memory_functions (alloc_func, realloc_func, free_func)
+ void *(*alloc_func) ();
+ void *(*realloc_func) ();
+ void (*free_func) ();
+#endif
+{
+ if (alloc_func == 0)
+ alloc_func = _mp_default_allocate;
+ if (realloc_func == 0)
+ realloc_func = _mp_default_reallocate;
+ if (free_func == 0)
+ free_func = _mp_default_free;
+
+ _mp_allocate_func = alloc_func;
+ _mp_reallocate_func = realloc_func;
+ _mp_free_func = free_func;
+}
diff --git a/mpbsd/Makefile.in b/mpbsd/Makefile.in
new file mode 100644
index 000000000..88d589756
--- /dev/null
+++ b/mpbsd/Makefile.in
@@ -0,0 +1,84 @@
+# Makefile for GNU MP/mpbsd functions
+# Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+# This file is part of the GNU MP Library.
+
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+
+# The GNU MP Library 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 Library General Public
+# License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+
+srcdir = .
+
+CC = gcc
+
+# If you cross compile on a machine with the same sizes of the integral
+# types ("int", "long int", "short int", and "char") define this as the
+# local compiler. Otherwise, you need to look for the uses of LOCAL_CC below,
+# and handle those cases manually.
+LOCAL_CC = $(CC)
+CFLAGS = -g -O
+AR = ar
+SHELL = /bin/sh
+
+#### host and target specific makefile fragments come in here.
+###
+
+MPBSD_LINKS = add.c cmp.c gcd.c mul.c pow_ui.c powm.c sqrtrem.c sub.c
+MPBSD_SRCS = itom.c mdiv.c mfree.c min.c mout.c move.c mtox.c sdiv.c xtom.c \
+ realloc.c $(MPBSD_LINKS)
+
+MPBSD_OBJS = itom.o mdiv.o mfree.o min.o mout.o move.o mtox.o sdiv.o xtom.o \
+ realloc.o add.o cmp.o gcd.o mul.o pow_ui.o powm.o sqrtrem.o sub.o
+
+INCLUDES = -I. -I.. -I$(srcdir)/../mpz -I../mpn -I$(srcdir)/..
+
+libmpbsd.a: Makefile.in $(MPBSD_OBJS)
+ rm -f $@
+ $(AR) cr $@ $(MPBSD_OBJS)
+
+.c.o:
+ $(CC) -c $(INCLUDES) -DBERKELEY_MP $(CFLAGS) $(XCFLAGS) $<
+
+check:
+ true
+
+clean mostlyclean:
+ rm -f *.o libmpbsd.a
+distclean maintainer-clean: clean
+ rm -f Makefile config.status $(MPBSD_LINKS)
+
+Makefile: $(srcdir)/Makefile.in
+ $(SHELL) ./config.status
+
+H = $(srcdir)/../gmp.h $(srcdir)/../gmp-impl.h ../mpn/gmp-mparam.h
+L = $(srcdir)/../longlong.h
+
+itom.o: $(srcdir)/itom.c ../mp.h $(H)
+mdiv.o: $(srcdir)/mdiv.c ../mp.h $(H) $(L) $(srcdir)/../mpz/dmincl.c
+mfree.o: $(srcdir)/mfree.c ../mp.h $(H)
+min.o: $(srcdir)/min.c ../mp.h $(H)
+mout.o: $(srcdir)/mout.c ../mp.h $(H)
+move.o: $(srcdir)/move.c ../mp.h $(H)
+mtox.o: $(srcdir)/mtox.c ../mp.h $(H)
+sdiv.o: $(srcdir)/sdiv.c ../mp.h $(H) $(L)
+xtom.o: $(srcdir)/xtom.c ../mp.h $(H)
+add.o: $(srcdir)/../mpz/add.c $(H)
+cmp.o: $(srcdir)/../mpz/cmp.c $(H)
+gcd.o: $(srcdir)/../mpz/gcd.c $(H) $(L)
+mul.o: $(srcdir)/../mpz/mul.c $(H)
+pow_ui.o: $(srcdir)/../mpz/pow_ui.c $(H) $(L)
+powm.o: $(srcdir)/../mpz/powm.c $(H) $(L)
+realloc.o: $(srcdir)/realloc.c $(H)
+sqrtrem.o: $(srcdir)/../mpz/sqrtrem.c $(H)
+sub.o: $(srcdir)/../mpz/sub.c $(H)
diff --git a/mpbsd/configure.in b/mpbsd/configure.in
new file mode 100644
index 000000000..ec220753b
--- /dev/null
+++ b/mpbsd/configure.in
@@ -0,0 +1,20 @@
+# This file is a shell script fragment that supplies the information
+# necessary for a configure script to process the program in
+# this directory. For more information, look at ../configure.
+
+configdirs=
+srctrigger=itom.c
+srcname="GNU Multi-Precision library/mpbsd"
+
+# per-host:
+
+# per-target:
+
+mpzfiles="add.c cmp.c gcd.c mul.c pow_ui.c powm.c sqrtrem.c sub.c"
+
+for fn in $mpzfiles
+ do
+ rm -f $fn
+ files="$files ../mpz/$fn"
+ links="$links $fn"
+ done
diff --git a/mpbsd/itom.c b/mpbsd/itom.c
new file mode 100644
index 000000000..719a4dcdc
--- /dev/null
+++ b/mpbsd/itom.c
@@ -0,0 +1,54 @@
+/* itom -- BSD compatible allocate and initiate a MINT.
+
+Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "mp.h"
+#include "gmp.h"
+#include "gmp-impl.h"
+
+MINT *
+#if __STDC__
+itom (signed short int n)
+#else
+itom (n)
+ short int n;
+#endif
+{
+ MINT *x;
+ mp_ptr xp;
+
+ x = (MINT *) (*_mp_allocate_func) (sizeof (MINT));
+ x->_mp_alloc = 1;
+ x->_mp_d = xp = (mp_ptr) (*_mp_allocate_func) (BYTES_PER_MP_LIMB);
+ if (n > 0)
+ {
+ x->_mp_size = 1;
+ xp[0] = n;
+ }
+ else if (n < 0)
+ {
+ x->_mp_size = -1;
+ xp[0] = -n;
+ }
+ else
+ x->_mp_size = 0;
+
+ return x;
+}
diff --git a/mpbsd/mdiv.c b/mpbsd/mdiv.c
new file mode 100644
index 000000000..103c2c307
--- /dev/null
+++ b/mpbsd/mdiv.c
@@ -0,0 +1,39 @@
+/* mdiv -- BSD compatible divide producing both remainder and quotient.
+
+Copyright (C) 1991, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "mp.h"
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+void
+#if __STDC__
+mdiv (const MINT *num, const MINT *den, MINT *quot, MINT *rem)
+#else
+mdiv (num, den, quot, rem)
+ const MINT *num;
+ const MINT *den;
+ MINT *quot;
+ MINT *rem;
+#endif
+
+#define COMPUTE_QUOTIENT
+#include "dmincl.c"
diff --git a/mpbsd/mfree.c b/mpbsd/mfree.c
new file mode 100644
index 000000000..ef931e3f4
--- /dev/null
+++ b/mpbsd/mfree.c
@@ -0,0 +1,36 @@
+/* mfree -- BSD compatible mfree.
+
+Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "mp.h"
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mfree (MINT *m)
+#else
+mfree (m)
+ MINT *m;
+#endif
+{
+ (*_mp_free_func) (m->_mp_d, m->_mp_alloc * BYTES_PER_MP_LIMB);
+ (*_mp_free_func) (m, sizeof (MINT));
+}
diff --git a/mpbsd/min.c b/mpbsd/min.c
new file mode 100644
index 000000000..6edb17166
--- /dev/null
+++ b/mpbsd/min.c
@@ -0,0 +1,89 @@
+/* min(MINT) -- Do decimal input from standard input and store result in
+ MINT.
+
+Copyright (C) 1991, 1994 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <ctype.h>
+#include "mp.h"
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+min (MINT *dest)
+#else
+min (dest)
+ MINT *dest;
+#endif
+{
+ char *str;
+ size_t alloc_size, str_size;
+ int c;
+ int negative;
+ mp_size_t dest_size;
+
+ alloc_size = 100;
+ str = (char *) (*_mp_allocate_func) (alloc_size);
+ str_size = 0;
+
+ /* Skip whitespace. */
+ do
+ c = getc (stdin);
+ while (isspace (c));
+
+ negative = 0;
+ if (c == '-')
+ {
+ negative = 1;
+ c = getc (stdin);
+ }
+
+ if (digit_value_in_base (c, 10) < 0)
+ return; /* error if no digits */
+
+ for (;;)
+ {
+ int dig;
+ if (str_size >= alloc_size)
+ {
+ size_t old_alloc_size = alloc_size;
+ alloc_size = alloc_size * 3 / 2;
+ str = (char *) (*_mp_reallocate_func) (str, old_alloc_size, alloc_size);
+ }
+ dig = digit_value_in_base (c, 10);
+ if (dig < 0)
+ break;
+ str[str_size++] = dig;
+ c = getc (stdin);
+ }
+
+ ungetc (c, stdin);
+
+ dest_size = str_size / __mp_bases[10].chars_per_limb + 1;
+ if (dest->_mp_alloc < dest_size)
+ _mp_realloc (dest, dest_size);
+
+ dest_size = mpn_set_str (dest->_mp_d, (unsigned char *) str, str_size, 10);
+ dest->_mp_size = negative ? -dest_size : dest_size;
+
+ (*_mp_free_func) (str, alloc_size);
+ return;
+}
diff --git a/mpbsd/mout.c b/mpbsd/mout.c
new file mode 100644
index 000000000..a6b62be85
--- /dev/null
+++ b/mpbsd/mout.c
@@ -0,0 +1,96 @@
+/* mout(MINT) -- Do decimal output of MINT to standard output.
+
+Copyright (C) 1991, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "mp.h"
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mout (const MINT *x)
+#else
+mout (x)
+ const MINT *x;
+#endif
+{
+ mp_ptr xp;
+ mp_size_t x_size = x->_mp_size;
+ unsigned char *str;
+ size_t str_size;
+ char *num_to_text;
+ int i;
+ TMP_DECL (marker);
+
+ if (x_size == 0)
+ {
+ fputc ('0', stdout);
+ return;
+ }
+ if (x_size < 0)
+ {
+ fputc ('-', stdout);
+ x_size = -x_size;
+ }
+
+ TMP_MARK (marker);
+ str_size = ((size_t) (x_size * BITS_PER_MP_LIMB
+ * __mp_bases[10].chars_per_bit_exactly)) + 3;
+ str = (unsigned char *) TMP_ALLOC (str_size);
+
+ /* Move the number to convert into temporary space, since mpn_get_str
+ clobbers its argument + needs one extra high limb.... */
+ xp = (mp_ptr) TMP_ALLOC ((x_size + 1) * BYTES_PER_MP_LIMB);
+ MPN_COPY (xp, x->_mp_d, x_size);
+
+ str_size = mpn_get_str (str, 10, xp, x_size);
+
+ /* mpn_get_str might make some leading zeros. Skip them. */
+ while (*str == 0)
+ {
+ str_size--;
+ str++;
+ }
+
+ /* Translate to printable chars. */
+ for (i = 0; i < str_size; i++)
+ str[i] = "0123456789"[str[i]];
+ str[str_size] = 0;
+
+ str_size = strlen (str);
+ if (str_size % 10 != 0)
+ {
+ fwrite (str, 1, str_size % 10, stdout);
+ str += str_size % 10;
+ str_size -= str_size % 10;
+ if (str_size != 0)
+ fputc (' ', stdout);
+ }
+ for (i = 0; i < str_size; i += 10)
+ {
+ fwrite (str, 1, 10, stdout);
+ str += 10;
+ if (i + 10 < str_size)
+ fputc (' ', stdout);
+ }
+ fputc ('\n', stdout);
+ TMP_FREE (marker);
+}
diff --git a/mpbsd/move.c b/mpbsd/move.c
new file mode 100644
index 000000000..8256cc704
--- /dev/null
+++ b/mpbsd/move.c
@@ -0,0 +1,46 @@
+/* move -- BSD compatible assignment.
+
+Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "mp.h"
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+move (const MINT *u, MINT *w)
+#else
+move (u, w)
+ const MINT *u;
+ MINT *w;
+#endif
+{
+ mp_size_t usize;
+ mp_size_t abs_usize;
+
+ usize = u->_mp_size;
+ abs_usize = ABS (usize);
+
+ if (w->_mp_alloc < abs_usize)
+ _mp_realloc (w, abs_usize);
+
+ w->_mp_size = usize;
+ MPN_COPY (w->_mp_d, u->_mp_d, abs_usize);
+}
diff --git a/mpbsd/mtox.c b/mpbsd/mtox.c
new file mode 100644
index 000000000..8baec2a1e
--- /dev/null
+++ b/mpbsd/mtox.c
@@ -0,0 +1,81 @@
+/* mtox -- Convert OPERAND to hexadecimal and return a malloc'ed string
+ with the result of the conversion.
+
+Copyright (C) 1991, 1994 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "mp.h"
+#include "gmp.h"
+#include "gmp-impl.h"
+
+char *
+#if __STDC__
+mtox (const MINT *x)
+#else
+mtox (x)
+ const MINT *x;
+#endif
+{
+ mp_ptr xp;
+ mp_size_t xsize = x->_mp_size;
+ mp_size_t xsign;
+ unsigned char *str, *s;
+ size_t str_size, i;
+ int zeros;
+ char *num_to_text;
+ TMP_DECL (marker);
+
+ if (xsize == 0)
+ {
+ str = (unsigned char *) (*_mp_allocate_func) (2);
+ str[0] = '0';
+ str[1] = 0;
+ return str;
+ }
+ xsign = xsize;
+ if (xsize < 0)
+ xsize = -xsize;
+
+ TMP_MARK (marker);
+ str_size = ((size_t) (xsize * BITS_PER_MP_LIMB
+ * __mp_bases[16].chars_per_bit_exactly)) + 3;
+ str = (unsigned char *) (*_mp_allocate_func) (str_size);
+ s = str;
+
+ if (xsign < 0)
+ *s++ = '-';
+
+ /* Move the number to convert into temporary space, since mpn_get_str
+ clobbers its argument + needs one extra high limb.... */
+ xp = (mp_ptr) TMP_ALLOC ((xsize + 1) * BYTES_PER_MP_LIMB);
+ MPN_COPY (xp, x->_mp_d, xsize);
+
+ str_size = mpn_get_str (s, 16, xp, xsize);
+
+ /* mpn_get_str might make some leading zeros. Skip them. */
+ for (zeros = 0; s[zeros] == 0; zeros++)
+ str_size--;
+
+ /* Translate to printable chars and move string down. */
+ for (i = 0; i < str_size; i++)
+ s[i] = "0123456789abcdef"[s[zeros + i]];
+ s[str_size] = 0;
+
+ return str;
+}
diff --git a/mpbsd/realloc.c b/mpbsd/realloc.c
new file mode 100644
index 000000000..64bee76f1
--- /dev/null
+++ b/mpbsd/realloc.c
@@ -0,0 +1,44 @@
+/* _mp_realloc -- make the MINT* have NEW_SIZE digits allocated.
+
+Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "mp.h"
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void *
+#if __STDC__
+_mp_realloc (MINT *m, mp_size_t new_size)
+#else
+_mp_realloc (m, new_size)
+ MINT *m;
+ mp_size_t new_size;
+#endif
+{
+ /* Never allocate zero space. */
+ if (new_size == 0)
+ new_size = 1;
+
+ m->_mp_d = (mp_ptr) (*_mp_reallocate_func) (m->_mp_d,
+ m->_mp_alloc * BYTES_PER_MP_LIMB,
+ new_size * BYTES_PER_MP_LIMB);
+ m->_mp_alloc = new_size;
+ return (void *) m->_mp_d;
+}
diff --git a/mpbsd/sdiv.c b/mpbsd/sdiv.c
new file mode 100644
index 000000000..6982e2009
--- /dev/null
+++ b/mpbsd/sdiv.c
@@ -0,0 +1,77 @@
+/* sdiv -- Divide a MINT by a short integer. Produce a MINT quotient
+ and a short remainder.
+
+Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "mp.h"
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+void
+#if __STDC__
+sdiv (const MINT *dividend, signed short int divisor_short, MINT *quot, short *rem_ptr)
+#else
+sdiv (dividend, divisor_short, quot, rem_ptr)
+ const MINT *dividend;
+ short int divisor_short;
+ MINT *quot;
+ short *rem_ptr;
+#endif
+{
+ mp_size_t sign_dividend;
+ signed long int sign_divisor;
+ mp_size_t dividend_size, quot_size;
+ mp_ptr dividend_ptr, quot_ptr;
+ mp_limb_t divisor_limb;
+ mp_limb_t remainder_limb;
+
+ sign_dividend = dividend->_mp_size;
+ dividend_size = ABS (dividend->_mp_size);
+
+ if (dividend_size == 0)
+ {
+ quot->_mp_size = 0;
+ *rem_ptr = 0;
+ return;
+ }
+
+ sign_divisor = divisor_short;
+ divisor_limb = ABS (divisor_short);
+
+ /* No need for temporary allocation and copying even if QUOT == DIVIDEND
+ as the divisor is just one limb, and thus no intermediate remainders
+ need to be stored. */
+
+ if (quot->_mp_alloc < dividend_size)
+ _mp_realloc (quot, dividend_size);
+
+ quot_ptr = quot->_mp_d;
+ dividend_ptr = dividend->_mp_d;
+
+ remainder_limb = mpn_divmod_1 (quot_ptr,
+ dividend_ptr, dividend_size, divisor_limb);
+
+ *rem_ptr = sign_dividend >= 0 ? remainder_limb : -remainder_limb;
+ /* The quotient is DIVIDEND_SIZE limbs, but the most significant
+ might be zero. Set QUOT_SIZE properly. */
+ quot_size = dividend_size - (quot_ptr[dividend_size - 1] == 0);
+ quot->_mp_size = (sign_divisor ^ sign_dividend) >= 0 ? quot_size : -quot_size;
+}
diff --git a/mpbsd/xtom.c b/mpbsd/xtom.c
new file mode 100644
index 000000000..5a529e8e4
--- /dev/null
+++ b/mpbsd/xtom.c
@@ -0,0 +1,110 @@
+/* xtom -- convert a hexadecimal string to a MINT, and return a pointer to
+ the MINT.
+
+Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "mp.h"
+#include "gmp.h"
+#include "gmp-impl.h"
+
+static int
+digit_value_in_base (c, base)
+ int c;
+ int base;
+{
+ int digit;
+
+ if (isdigit (c))
+ digit = c - '0';
+ else if (islower (c))
+ digit = c - 'a' + 10;
+ else if (isupper (c))
+ digit = c - 'A' + 10;
+ else
+ return -1;
+
+ if (digit < base)
+ return digit;
+ return -1;
+}
+
+MINT *
+#if __STDC__
+xtom (const char *str)
+#else
+xtom (str)
+ const char *str;
+#endif
+{
+ size_t str_size;
+ char *s, *begs;
+ size_t i;
+ mp_size_t xsize;
+ int c;
+ int negative;
+ MINT *x = (MINT *) (*_mp_allocate_func) (sizeof (MINT));
+ TMP_DECL (marker);
+
+ /* Skip whitespace. */
+ do
+ c = *str++;
+ while (isspace (c));
+
+ negative = 0;
+ if (c == '-')
+ {
+ negative = 1;
+ c = *str++;
+ }
+
+ if (digit_value_in_base (c, 16) < 0)
+ return 0; /* error if no digits */
+
+ TMP_MARK (marker);
+ str_size = strlen (str - 1);
+ s = begs = (char *) TMP_ALLOC (str_size + 1);
+
+ for (i = 0; i < str_size; i++)
+ {
+ if (!isspace (c))
+ {
+ int dig = digit_value_in_base (c, 16);
+ if (dig < 0)
+ {
+ TMP_FREE (marker);
+ return 0;
+ }
+ *s++ = dig;
+ }
+ c = *str++;
+ }
+
+ str_size = s - begs;
+
+ xsize = str_size / __mp_bases[16].chars_per_limb + 1;
+ x->_mp_alloc = xsize;
+ x->_mp_d = (mp_ptr) (*_mp_allocate_func) (xsize * BYTES_PER_MP_LIMB);
+
+ xsize = mpn_set_str (x->_mp_d, (unsigned char *) begs, str_size, 16);
+ x->_mp_size = negative ? -xsize : xsize;
+
+ TMP_FREE (marker);
+ return x;
+}
diff --git a/mpf/Makefile.in b/mpf/Makefile.in
new file mode 100644
index 000000000..0a77fdb63
--- /dev/null
+++ b/mpf/Makefile.in
@@ -0,0 +1,115 @@
+# Makefile for GNU MP/mpf functions
+# Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+# This file is part of the GNU MP Library.
+
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+
+# The GNU MP Library 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 Library General Public
+# License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+
+srcdir = .
+
+CC = gcc
+
+CFLAGS = -g -O
+AR = ar
+AR_FLAGS = rc
+SHELL = /bin/sh
+
+#### host and target specific makefile fragments come in here.
+###
+
+MPF_SRCS = init.c init2.c set.c set_ui.c set_si.c set_str.c set_d.c \
+ iset.c iset_ui.c iset_si.c iset_str.c iset_d.c clear.c get_str.c \
+ dump.c size.c eq.c reldiff.c sqrt.c random2.c inp_str.c out_str.c \
+ add.c add_ui.c sub.c sub_ui.c ui_sub.c mul.c mul_ui.c div.c div_ui.c \
+ cmp.c cmp_ui.c cmp_si.c mul_2exp.c div_2exp.c abs.c neg.c \
+ set_dfl_prec.c set_prc.c set_prc_raw.c get_prc.c ui_div.c sqrt_ui.c
+MPF_OBJS = init.o init2.o set.o set_ui.o set_si.o set_str.o set_d.o \
+ iset.o iset_ui.o iset_si.o iset_str.o iset_d.o clear.o get_str.o \
+ dump.o size.o eq.o reldiff.o sqrt.o random2.o inp_str.o out_str.o \
+ add.o add_ui.o sub.o sub_ui.o ui_sub.o mul.o mul_ui.o div.o div_ui.o \
+ cmp.o cmp_ui.o cmp_si.o mul_2exp.o div_2exp.o abs.o neg.o \
+ set_dfl_prec.o set_prc.o set_prc_raw.o get_prc.o ui_div.o sqrt_ui.o
+
+LATER_OBJS = inp_raw.o out_raw.o random.o pow_ui.o fac_ui.o
+
+INCLUDES = -I. -I.. -I../mpn -I$(srcdir)/..
+
+libmpf.a: Makefile.in $(MPF_OBJS)
+ rm -f $@
+ $(AR) $(AR_FLAGS) $@ $(MPF_OBJS)
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(XCFLAGS) $<
+
+test: libmpf.a
+ cd tests; $(MAKE) srcdir=$(srcdir) CC=$(CC) SHELL=$(SHELL)
+
+clean mostlyclean:
+ rm -f *.o libmpf.a
+ -cd tests; $(MAKE) $@
+distclean maintainer-clean: clean
+ rm -f Makefile config.status
+ -cd tests; $(MAKE) $@
+
+Makefile: $(srcdir)/Makefile.in
+ $(SHELL) ./config.status
+
+H = $(srcdir)/../gmp.h $(srcdir)/../gmp-impl.h ../mpn/gmp-mparam.h
+
+abs.o: $(srcdir)/abs.c $(H)
+add.o: $(srcdir)/add.c $(H)
+add_ui.o: $(srcdir)/add_ui.c $(H)
+clear.o: $(srcdir)/clear.c $(H)
+cmp.o: $(srcdir)/cmp.c $(H)
+cmp_si.o: $(srcdir)/cmp_si.c $(H)
+cmp_ui.o: $(srcdir)/cmp_ui.c $(H)
+eq.o: $(srcdir)/eq.c $(H)
+div.o: $(srcdir)/div.c $(H) $(srcdir)/../longlong.h
+div_2exp.o: $(srcdir)/div_2exp.c $(H)
+div_ui.o: $(srcdir)/div_ui.c $(H) $(srcdir)/../longlong.h
+dump.o: $(srcdir)/dump.c $(H)
+get_prc.o: $(srcdir)/get_prc.c $(H)
+get_str.o: $(srcdir)/get_str.c $(H) $(srcdir)/../longlong.h
+init.o: $(srcdir)/init.c $(H)
+init2.o: $(srcdir)/init2.c $(H)
+inp_str.o: $(srcdir)/inp_str.c $(H)
+iset.o: $(srcdir)/iset.c $(H)
+iset_d.o: $(srcdir)/iset_d.c $(H)
+iset_si.o: $(srcdir)/iset_si.c $(H)
+iset_str.o: $(srcdir)/iset_str.c $(H)
+iset_ui.o: $(srcdir)/iset_ui.c $(H)
+mul.o: $(srcdir)/mul.c $(H)
+mul_2exp.o: $(srcdir)/mul_2exp.c $(H)
+mul_ui.o: $(srcdir)/mul_ui.c $(H)
+neg.o: $(srcdir)/neg.c $(H)
+out_str.o: $(srcdir)/out_str.c $(H)
+random2.o: $(srcdir)/random2.c $(H)
+reldiff.o: $(srcdir)/reldiff.c $(H)
+set.o: $(srcdir)/set.c $(H)
+set_d.o: $(srcdir)/set_d.c $(H)
+set_dfl_prec.o: $(srcdir)/set_dfl_prec.c $(H)
+set_prc.o: $(srcdir)/set_prc.c $(H)
+set_prc_raw.o: $(srcdir)/set_prc_raw.c $(H)
+set_si.o: $(srcdir)/set_si.c $(H)
+set_str.o: $(srcdir)/set_str.c $(H) $(srcdir)/../longlong.h
+set_ui.o: $(srcdir)/set_ui.c $(H)
+size.o: $(srcdir)/size.c $(H)
+sqrt.o: $(srcdir)/sqrt.c $(H)
+sqrt_ui.o: $(srcdir)/sqrt_ui.c $(H)
+sub.o: $(srcdir)/sub.c $(H)
+sub_ui.o: $(srcdir)/sub_ui.c $(H)
+ui_div.o: $(srcdir)/ui_div.c $(H) $(srcdir)/../longlong.h
+ui_sub.o: $(srcdir)/ui_sub.c $(H)
diff --git a/mpf/abs.c b/mpf/abs.c
new file mode 100644
index 000000000..029007a5f
--- /dev/null
+++ b/mpf/abs.c
@@ -0,0 +1,56 @@
+/* mpf_abs -- Compute the absolute value of a float.
+
+Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpf_abs (mpf_ptr r, mpf_srcptr u)
+#else
+mpf_abs (r, u)
+ mpf_ptr r;
+ mpf_srcptr u;
+#endif
+{
+ mp_size_t size;
+
+ size = ABS (u->_mp_size);
+ if (r != u)
+ {
+ mp_size_t prec;
+ mp_ptr rp, up;
+
+ prec = r->_mp_prec + 1; /* lie not to lose precision in assignment */
+ rp = r->_mp_d;
+ up = u->_mp_d;
+
+ if (size > prec)
+ {
+ up += size - prec;
+ size = prec;
+ }
+
+ MPN_COPY (rp, up, size);
+ r->_mp_exp = u->_mp_exp;
+ }
+ r->_mp_size = size;
+}
diff --git a/mpf/add.c b/mpf/add.c
new file mode 100644
index 000000000..2db876fc6
--- /dev/null
+++ b/mpf/add.c
@@ -0,0 +1,180 @@
+/* mpf_add -- Add two floats.
+
+Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpf_add (mpf_ptr r, mpf_srcptr u, mpf_srcptr v)
+#else
+mpf_add (r, u, v)
+ mpf_ptr r;
+ mpf_srcptr u;
+ mpf_srcptr v;
+#endif
+{
+ mp_srcptr up, vp;
+ mp_ptr rp, tp;
+ mp_size_t usize, vsize, rsize;
+ mp_size_t prec;
+ mp_exp_t uexp;
+ mp_size_t ediff;
+ mp_limb_t cy;
+ int negate;
+ TMP_DECL (marker);
+
+ usize = u->_mp_size;
+ vsize = v->_mp_size;
+
+ /* Handle special cases that don't work in generic code below. */
+ if (usize == 0)
+ {
+ mpf_set (r, v);
+ return;
+ }
+ if (vsize == 0)
+ {
+ mpf_set (r, u);
+ return;
+ }
+
+ /* If signs of U and V are different, perform subtraction. */
+ if ((usize ^ vsize) < 0)
+ {
+ __mpf_struct v_negated;
+ v_negated._mp_size = -vsize;
+ v_negated._mp_exp = v->_mp_exp;
+ v_negated._mp_d = v->_mp_d;
+ mpf_sub (r, u, &v_negated);
+ return;
+ }
+
+ TMP_MARK (marker);
+
+ /* Signs are now known to be the same. */
+ negate = usize < 0;
+
+ /* Make U be the operand with the largest exponent. */
+ if (u->_mp_exp < v->_mp_exp)
+ {
+ mpf_srcptr t;
+ t = u; u = v; v = t;
+ usize = u->_mp_size;
+ vsize = v->_mp_size;
+ }
+
+ usize = ABS (usize);
+ vsize = ABS (vsize);
+ up = u->_mp_d;
+ vp = v->_mp_d;
+ rp = r->_mp_d;
+ prec = r->_mp_prec;
+ uexp = u->_mp_exp;
+ ediff = u->_mp_exp - v->_mp_exp;
+
+ /* If U extends beyond PREC, ignore the part that does. */
+ if (usize > prec)
+ {
+ up += usize - prec;
+ usize = prec;
+ }
+
+ /* If V extends beyond PREC, ignore the part that does.
+ Note that this may make vsize negative. */
+ if (vsize + ediff > prec)
+ {
+ vp += vsize + ediff - prec;
+ vsize = prec - ediff;
+ }
+
+#if 0
+ /* Locate the least significant non-zero limb in (the needed parts
+ of) U and V, to simplify the code below. */
+ while (up[0] == 0)
+ up++, usize--;
+ while (vp[0] == 0)
+ vp++, vsize--;
+#endif
+
+ /* Allocate temp space for the result. Allocate
+ just vsize + ediff later??? */
+ tp = (mp_ptr) TMP_ALLOC (prec * BYTES_PER_MP_LIMB);
+
+ if (ediff >= prec)
+ {
+ /* V completely cancelled. */
+ if (tp != up)
+ MPN_COPY (rp, up, usize);
+ rsize = usize;
+ }
+ else
+ {
+ /* uuuu | uuuu | uuuu | uuuu | uuuu */
+ /* vvvvvvv | vv | vvvvv | v | vv */
+
+ if (usize > ediff)
+ {
+ /* U and V partially overlaps. */
+ if (vsize + ediff <= usize)
+ {
+ /* uuuu */
+ /* v */
+ mp_size_t size;
+ size = usize - ediff - vsize;
+ MPN_COPY (tp, up, size);
+ cy = mpn_add (tp + size, up + size, usize - size, vp, vsize);
+ rsize = usize;
+ }
+ else
+ {
+ /* uuuu */
+ /* vvvvv */
+ mp_size_t size;
+ size = vsize + ediff - usize;
+ MPN_COPY (tp, vp, size);
+ cy = mpn_add (tp + size, up, usize, vp + size, usize - ediff);
+ rsize = vsize + ediff;
+ }
+ }
+ else
+ {
+ /* uuuu */
+ /* vv */
+ mp_size_t size;
+ size = vsize + ediff - usize;
+ MPN_COPY (tp, vp, vsize);
+ MPN_ZERO (tp + vsize, ediff - usize);
+ MPN_COPY (tp + size, up, usize);
+ cy = 0;
+ rsize = size + usize;
+ }
+
+ MPN_COPY (rp, tp, rsize);
+ rp[rsize] = cy;
+ rsize += cy;
+ uexp += cy;
+ }
+
+ r->_mp_size = negate ? -rsize : rsize;
+ r->_mp_exp = uexp;
+ TMP_FREE (marker);
+}
diff --git a/mpf/add_ui.c b/mpf/add_ui.c
new file mode 100644
index 000000000..794f0f1f6
--- /dev/null
+++ b/mpf/add_ui.c
@@ -0,0 +1,142 @@
+/* mpf_add_ui -- Add a float and an unsigned integer.
+
+Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpf_add_ui (mpf_ptr sum, mpf_srcptr u, unsigned long int v)
+#else
+mpf_add_ui (sum, u, v)
+ mpf_ptr sum;
+ mpf_srcptr u;
+ unsigned long int v;
+#endif
+{
+ mp_srcptr up = u->_mp_d;
+ mp_ptr sump = sum->_mp_d;
+ mp_size_t usize, sumsize;
+ mp_size_t prec = sum->_mp_prec;
+ mp_exp_t uexp = u->_mp_exp;
+
+ usize = u->_mp_size;
+ if (usize <= 0)
+ {
+ if (usize == 0)
+ {
+ mpf_set_ui (sum, v);
+ return;
+ }
+ else
+ {
+ __mpf_struct u_negated;
+ u_negated._mp_size = -usize;
+ u_negated._mp_exp = u->_mp_exp;
+ u_negated._mp_d = u->_mp_d;
+ mpf_sub_ui (sum, &u_negated, v);
+ sum->_mp_size = -(sum->_mp_size);
+ return;
+ }
+ }
+
+ if (v == 0)
+ {
+ sum_is_u:
+ if (u != sum)
+ {
+ sumsize = MIN (usize, prec);
+ MPN_COPY (sum->_mp_d, up + usize - sumsize, sumsize);
+ sum->_mp_size = sumsize;
+ sum->_mp_exp = u->_mp_exp;
+ }
+ return;
+ }
+
+ if (uexp > 0)
+ {
+ /* U >= 1. */
+ if (uexp > prec)
+ {
+ /* U >> V, V is not part of final result. */
+ goto sum_is_u;
+ }
+ else
+ {
+ /* U's "limb point" is somewhere between the first limb
+ and the PREC:th limb.
+ Both U and V are part of the final result. */
+ if (uexp > usize)
+ {
+ /* uuuuuu0000. */
+ /* + v. */
+ /* We begin with moving U to the top of SUM, to handle
+ samevar(U,SUM). */
+ MPN_COPY_DECR (sump + uexp - usize, up, usize);
+ sump[0] = v;
+ MPN_ZERO (sump + 1, uexp - usize - 1);
+#if 0 /* What is this??? */
+ if (sum == u)
+ MPN_COPY (sum->_mp_d, sump, uexp);
+#endif
+ sum->_mp_size = uexp;
+ sum->_mp_exp = uexp;
+ }
+ else
+ {
+ /* uuuuuu.uuuu */
+ /* + v. */
+ mp_limb_t cy_limb;
+ if (usize > prec)
+ {
+ /* Ignore excess limbs in U. */
+ up += usize - prec;
+ usize -= usize - prec; /* Eq. usize = prec */
+ }
+ if (sump != up)
+ MPN_COPY (sump, up, usize - uexp);
+ cy_limb = mpn_add_1 (sump + usize - uexp, up + usize - uexp,
+ uexp, (mp_limb_t) v);
+ sump[usize] = cy_limb;
+ sum->_mp_size = usize + cy_limb;
+ sum->_mp_exp = uexp + cy_limb;
+ }
+ }
+ }
+ else
+ {
+ /* U < 1, so V > U for sure. */
+ /* v. */
+ /* .0000uuuu */
+ if (usize + (-uexp) + 1 > prec)
+ {
+ /* Ignore excess limbs in U. */
+ up += usize + (-uexp) + 1 - prec;
+ usize -= usize + (-uexp) + 1 - prec;
+ }
+ if (sump != up)
+ MPN_COPY (sump, up, usize);
+ MPN_ZERO (sump + usize, -uexp);
+ sump[usize + (-uexp)] = v;
+ sum->_mp_size = usize + (-uexp) + 1;
+ sum->_mp_exp = 1;
+ }
+}
diff --git a/mpf/clear.c b/mpf/clear.c
new file mode 100644
index 000000000..beaf4ee3a
--- /dev/null
+++ b/mpf/clear.c
@@ -0,0 +1,35 @@
+/* mpf_clear -- de-allocate the space occupied by the dynamic digit space of
+ an integer.
+
+Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpf_clear (mpf_ptr m)
+#else
+mpf_clear (m)
+ mpf_ptr m;
+#endif
+{
+ (*_mp_free_func) (m->_mp_d, (m->_mp_prec + 1) * BYTES_PER_MP_LIMB);
+}
diff --git a/mpf/cmp.c b/mpf/cmp.c
new file mode 100644
index 000000000..d440e1152
--- /dev/null
+++ b/mpf/cmp.c
@@ -0,0 +1,114 @@
+/* mpf_cmp -- Compare two floats.
+
+Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+int
+#if __STDC__
+mpf_cmp (mpf_srcptr u, mpf_srcptr v)
+#else
+mpf_cmp (u, v)
+ mpf_srcptr u;
+ mpf_srcptr v;
+#endif
+{
+ mp_srcptr up, vp;
+ mp_size_t usize, vsize;
+ mp_exp_t uexp, vexp;
+ int cmp;
+ int usign;
+
+ uexp = u->_mp_exp;
+ vexp = v->_mp_exp;
+
+ usize = u->_mp_size;
+ vsize = v->_mp_size;
+
+ /* 1. Are the signs different? */
+ if ((usize ^ vsize) >= 0)
+ {
+ /* U and V are both non-negative or both negative. */
+ if (usize == 0)
+ /* vsize >= 0 */
+ return -(vsize != 0);
+ if (vsize == 0)
+ /* usize >= 0 */
+ return usize != 0;
+ /* Fall out. */
+ }
+ else
+ {
+ /* Either U or V is negative, but not both. */
+ return usize >= 0 ? 1 : -1;
+ }
+
+ /* U and V have the same sign and are both non-zero. */
+
+ usign = usize >= 0 ? 1 : -1;
+
+ /* 2. Are the exponents different? */
+ if (uexp > vexp)
+ return usign;
+ if (uexp < vexp)
+ return -usign;
+
+ usize = ABS (usize);
+ vsize = ABS (vsize);
+
+ up = u->_mp_d;
+ vp = v->_mp_d;
+
+#define STRICT_MPF_NORMALIZATION 0
+#if ! STRICT_MPF_NORMALIZATION
+ /* Ignore zeroes at the low end of U and V. */
+ while (up[0] == 0)
+ {
+ up++;
+ usize--;
+ }
+ while (vp[0] == 0)
+ {
+ vp++;
+ vsize--;
+ }
+#endif
+
+ if (usize > vsize)
+ {
+ cmp = mpn_cmp (up + usize - vsize, vp, vsize);
+ if (cmp == 0)
+ return usign;
+ }
+ else if (vsize > usize)
+ {
+ cmp = mpn_cmp (up, vp + vsize - usize, usize);
+ if (cmp == 0)
+ return -usign;
+ }
+ else
+ {
+ cmp = mpn_cmp (up, vp, usize);
+ if (cmp == 0)
+ return 0;
+ }
+ return cmp > 0 ? usign : -usign;
+}
diff --git a/mpf/cmp_si.c b/mpf/cmp_si.c
new file mode 100644
index 000000000..01f970812
--- /dev/null
+++ b/mpf/cmp_si.c
@@ -0,0 +1,98 @@
+/* mpf_cmp_si -- Compare a float with a signed integer.
+
+Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+int
+#if __STDC__
+mpf_cmp_si (mpf_srcptr u, long int vslimb)
+#else
+mpf_cmp_si (u, vslimb)
+ mpf_srcptr u;
+ long int vslimb;
+#endif
+{
+ mp_srcptr up;
+ mp_size_t usize;
+ mp_exp_t uexp;
+ int usign;
+
+ uexp = u->_mp_exp;
+ usize = u->_mp_size;
+
+ /* 1. Are the signs different? */
+ if ((usize < 0) == (vslimb < 0)) /* don't use xor, type size may differ */
+ {
+ /* U and V are both non-negative or both negative. */
+ if (usize == 0)
+ /* vslimb >= 0 */
+ return -(vslimb != 0);
+ if (vslimb == 0)
+ /* usize >= 0 */
+ return usize != 0;
+ /* Fall out. */
+ }
+ else
+ {
+ /* Either U or V is negative, but not both. */
+ return usize >= 0 ? 1 : -1;
+ }
+
+ /* U and V have the same sign and are both non-zero. */
+
+ usign = usize >= 0 ? 1 : -1;
+
+ /* 2. Are the exponents different (V's exponent == 1)? */
+ if (uexp > 1)
+ return usign;
+ if (uexp < 1)
+ return -usign;
+
+ usize = ABS (usize);
+ vslimb = ABS (vslimb);
+
+ up = u->_mp_d;
+
+#define STRICT_MPF_NORMALIZATION 0
+#if ! STRICT_MPF_NORMALIZATION
+ /* Ignore zeroes at the low end of U and V. */
+ while (*up == 0)
+ {
+ up++;
+ usize--;
+ }
+#endif
+
+ /* 3. Now, if the number of limbs are different, we have a difference
+ since we have made sure the trailing limbs are not zero. */
+ if (usize > 1)
+ return usign;
+
+ /* 4. Compare the mantissas. */
+ if (*up > vslimb)
+ return usign;
+ else if (*up < vslimb)
+ return -usign;
+
+ /* Wow, we got zero even if we tried hard to avoid it. */
+ return 0;
+}
diff --git a/mpf/cmp_ui.c b/mpf/cmp_ui.c
new file mode 100644
index 000000000..3a4911ba7
--- /dev/null
+++ b/mpf/cmp_ui.c
@@ -0,0 +1,80 @@
+/* mpf_cmp_ui -- Compare a float with an unsigned integer.
+
+Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+int
+#if __STDC__
+mpf_cmp_ui (mpf_srcptr u, unsigned long int vlimb)
+#else
+mpf_cmp_ui (u, vlimb)
+ mpf_srcptr u;
+ unsigned long int vlimb;
+#endif
+{
+ mp_srcptr up;
+ mp_size_t usize;
+ mp_exp_t uexp;
+
+ uexp = u->_mp_exp;
+ usize = u->_mp_size;
+
+ /* 1. Is U negative? */
+ if (usize < 0)
+ return -1;
+ /* We rely on usize being non-negative in the code that follows. */
+
+ if (vlimb == 0)
+ return usize != 0;
+
+ /* 2. Are the exponents different (V's exponent == 1)? */
+ if (uexp > 1)
+ return 1;
+ if (uexp < 1)
+ return -1;
+
+ up = u->_mp_d;
+
+#define STRICT_MPF_NORMALIZATION 0
+#if ! STRICT_MPF_NORMALIZATION
+ /* Ignore zeroes at the low end of U. */
+ while (*up == 0)
+ {
+ up++;
+ usize--;
+ }
+#endif
+
+ /* 3. Now, if the number of limbs are different, we have a difference
+ since we have made sure the trailing limbs are not zero. */
+ if (usize > 1)
+ return 1;
+
+ /* 4. Compare the mantissas. */
+ if (*up > vlimb)
+ return 1;
+ else if (*up < vlimb)
+ return -1;
+
+ /* Wow, we got zero even if we tried hard to avoid it. */
+ return 0;
+}
diff --git a/mpf/configure.in b/mpf/configure.in
new file mode 100644
index 000000000..b6ecf8b3e
--- /dev/null
+++ b/mpf/configure.in
@@ -0,0 +1,12 @@
+# This file is a shell script fragment that supplies the information
+# necessary for a configure script to process the program in
+# this directory. For more information, look at ../configure.
+
+configdirs=tests
+srctrigger=add_ui.c
+srcname="GNU Multi-Precision library/mpf"
+
+# per-host:
+
+# per-target:
+
diff --git a/mpf/div.c b/mpf/div.c
new file mode 100644
index 000000000..bd2d04dba
--- /dev/null
+++ b/mpf/div.c
@@ -0,0 +1,143 @@
+/* mpf_div -- Divide two floats.
+
+Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+void
+#if __STDC__
+mpf_div (mpf_ptr r, mpf_srcptr u, mpf_srcptr v)
+#else
+mpf_div (r, u, v)
+ mpf_ptr r;
+ mpf_srcptr u;
+ mpf_srcptr v;
+#endif
+{
+ mp_srcptr up, vp;
+ mp_ptr qp, rp, rrp;
+ mp_size_t usize = u->_mp_size;
+ mp_size_t vsize = v->_mp_size;
+ mp_size_t qsize, rsize;
+ mp_size_t sign_quotient = usize ^ vsize;
+ unsigned normalization_steps;
+ mp_limb_t q_limb;
+ mp_size_t prec;
+ mp_exp_t rexp;
+ TMP_DECL (marker);
+
+ prec = r->_mp_prec;
+ usize = ABS (usize);
+ vsize = ABS (vsize);
+
+ if (vsize == 0)
+ vsize = 1 / vsize; /* divide by zero as directed */
+ if (usize == 0)
+ {
+ r->_mp_size = 0;
+ r->_mp_exp = 0;
+ return;
+ }
+
+ TMP_MARK (marker);
+ rexp = u->_mp_exp - v->_mp_exp;
+
+ qp = r->_mp_d;
+ up = u->_mp_d;
+ vp = v->_mp_d;
+
+ if (vsize > prec)
+ {
+ vp += vsize - prec;
+ vsize = prec;
+ }
+
+ rsize = vsize + prec;
+
+ rp = (mp_ptr) TMP_ALLOC ((rsize + 1) * BYTES_PER_MP_LIMB);
+
+ if (usize > rsize)
+ {
+ up += usize - rsize;
+ usize = rsize;
+ rrp = rp;
+ }
+ else
+ {
+ MPN_ZERO (rp, rsize - usize);
+ rrp = rp + (rsize - usize);
+ }
+
+ count_leading_zeros (normalization_steps, vp[vsize - 1]);
+
+ /* Normalize the divisor and the dividend. */
+ if (normalization_steps != 0)
+ {
+ mp_ptr tp;
+ mp_limb_t nlimb;
+
+ /* Shift up the divisor setting the most significant bit of
+ the most significant word. Use temporary storage not to clobber
+ the original contents of the divisor. */
+ tp = (mp_ptr) TMP_ALLOC (vsize * BYTES_PER_MP_LIMB);
+ mpn_lshift (tp, vp, vsize, normalization_steps);
+ vp = tp;
+
+ /* Shift up the dividend, possibly introducing a new most
+ significant word. Move the shifted dividend in the remainder
+ meanwhile. */
+ nlimb = mpn_lshift (rrp, up, usize, normalization_steps);
+ if (nlimb != 0)
+ {
+ rrp[usize] = nlimb;
+ rsize++;
+ rexp++;
+ }
+ }
+ else
+ {
+ /* The divisor is already normalized, as required.
+ Copy it to temporary space if it overlaps with the quotient. */
+ if (vp == qp)
+ {
+ vp = (mp_ptr) TMP_ALLOC (vsize * BYTES_PER_MP_LIMB);
+ MPN_COPY ((mp_ptr) vp, qp, vsize);
+ }
+
+ /* Move the dividend to the remainder. */
+ MPN_COPY (rrp, up, usize);
+ }
+
+ q_limb = mpn_divmod (qp, rp, rsize, vp, vsize);
+
+ qsize = rsize - vsize;
+ if (q_limb)
+ {
+ qp[qsize] = q_limb;
+ qsize++;
+ rexp++;
+ }
+
+ r->_mp_size = sign_quotient >= 0 ? qsize : -qsize;
+ r->_mp_exp = rexp;
+ TMP_FREE (marker);
+}
diff --git a/mpf/div_2exp.c b/mpf/div_2exp.c
new file mode 100644
index 000000000..d7296254e
--- /dev/null
+++ b/mpf/div_2exp.c
@@ -0,0 +1,79 @@
+/* mpf_div_2exp -- Divide a float by 2^n.
+
+Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpf_div_2exp (mpf_ptr r, mpf_srcptr u, unsigned long int exp)
+#else
+mpf_div_2exp (r, u, exp)
+ mpf_ptr r;
+ mpf_srcptr u;
+ unsigned long int exp;
+#endif
+{
+ mp_srcptr up;
+ mp_ptr rp = r->_mp_d;
+ mp_size_t usize;
+ mp_size_t abs_usize;
+ mp_size_t prec = r->_mp_prec;
+ mp_exp_t uexp = u->_mp_exp;
+
+ usize = u->_mp_size;
+
+ if (usize == 0)
+ {
+ r->_mp_size = 0;
+ r->_mp_exp = 0;
+ return;
+ }
+
+ abs_usize = ABS (usize);
+ up = u->_mp_d;
+
+ if (abs_usize > prec)
+ {
+ up += abs_usize - prec;
+ abs_usize = prec;
+ }
+
+ if (exp % BITS_PER_MP_LIMB == 0)
+ {
+ if (rp != up)
+ MPN_COPY (rp, up, abs_usize);
+ r->_mp_exp = uexp - exp / BITS_PER_MP_LIMB;
+ }
+ else
+ {
+ /* Use mpn_lshift since mpn_rshift operates upwards, and we therefore
+ would clobber part of U before using that part, when R == U. */
+ mp_limb_t cy_limb;
+ cy_limb = mpn_lshift (rp, up, abs_usize, -exp % BITS_PER_MP_LIMB);
+ rp[abs_usize] = cy_limb;
+ cy_limb = cy_limb != 0;
+
+ abs_usize += cy_limb;
+ r->_mp_exp = uexp - exp / BITS_PER_MP_LIMB - 1 + cy_limb;
+ }
+ r->_mp_size = usize >= 0 ? abs_usize : -abs_usize;
+}
diff --git a/mpf/div_ui.c b/mpf/div_ui.c
new file mode 100644
index 000000000..9656395f2
--- /dev/null
+++ b/mpf/div_ui.c
@@ -0,0 +1,78 @@
+/* mpf_div_ui -- Divide a float with an unsigned integer.
+
+Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+void
+#if __STDC__
+mpf_div_ui (mpf_ptr r, mpf_srcptr u, unsigned long int v)
+#else
+mpf_div_ui (r, u, v)
+ mpf_ptr r;
+ mpf_srcptr u;
+ unsigned long int v;
+#endif
+{
+ mp_srcptr up;
+ mp_ptr qp, rp, rrp;
+ mp_size_t usize = u->_mp_size;
+ mp_size_t qsize, rsize;
+ mp_size_t sign_quotient = usize;
+ mp_limb_t q_limb;
+ mp_size_t prec;
+ mp_exp_t rexp;
+ TMP_DECL (marker);
+
+ TMP_MARK (marker);
+ prec = r->_mp_prec;
+ usize = ABS (usize);
+
+ rsize = prec;
+
+ qp = r->_mp_d;
+ up = u->_mp_d;
+ rp = (mp_ptr) TMP_ALLOC ((rsize + 1) * BYTES_PER_MP_LIMB);
+ if (usize > rsize)
+ {
+ up += usize - rsize;
+ usize = rsize;
+ rrp = rp;
+ }
+ else
+ {
+ MPN_ZERO (rp, rsize - usize);
+ rrp = rp + (rsize - usize);
+ }
+
+ /* Move the dividend to the remainder. */
+ MPN_COPY (rrp, up, usize);
+
+ mpn_divmod_1 (qp, rp, rsize, v);
+ q_limb = qp[rsize - 1];
+
+ qsize = rsize - (q_limb == 0);
+ rexp = u->_mp_exp - (q_limb == 0);
+ r->_mp_size = sign_quotient >= 0 ? qsize : -qsize;
+ r->_mp_exp = rexp;
+ TMP_FREE (marker);
+}
diff --git a/mpf/dump.c b/mpf/dump.c
new file mode 100644
index 000000000..46d5c05f2
--- /dev/null
+++ b/mpf/dump.c
@@ -0,0 +1,43 @@
+/* mpf_dump -- Dump a float to stdout.
+
+Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpf_dump (mpf_srcptr u)
+#else
+mpf_dump (u)
+ mpf_srcptr u;
+#endif
+{
+ mp_exp_t exp;
+ char *str;
+
+ str = mpf_get_str (0, &exp, 10, 0, u);
+ if (str[0] == '-')
+ printf ("-0.%se%ld\n", str + 1, exp);
+ else
+ printf ("0.%se%ld\n", str, exp);
+ (*_mp_free_func) (str, 0);/* ??? broken alloc interface, pass what size ??? */
+}
diff --git a/mpf/eq.c b/mpf/eq.c
new file mode 100644
index 000000000..a474a4dc0
--- /dev/null
+++ b/mpf/eq.c
@@ -0,0 +1,121 @@
+/* mpf_cmp2 -- Compare two floats up to a specified bit #.
+
+Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+int
+#if __STDC__
+mpf_cmp2 (mpf_srcptr u, mpf_srcptr v, unsigned long int n_bits)
+#else
+mpf_cmp2 (u, v, n_bits)
+ mpf_srcptr u;
+ mpf_srcptr v;
+ unsigned long int n_bits;
+#endif
+{
+ mp_srcptr up, vp;
+ mp_size_t usize, vsize, size, i;
+ mp_exp_t uexp, vexp;
+ int usign;
+
+ uexp = u->_mp_exp;
+ vexp = v->_mp_exp;
+
+ usize = u->_mp_size;
+ vsize = v->_mp_size;
+
+ /* 1. Are the signs different? */
+ if ((usize ^ vsize) >= 0)
+ {
+ /* U and V are both non-negative or both negative. */
+ if (usize == 0)
+ return vsize == 0;
+ if (vsize == 0)
+ return 0;
+
+ /* Fall out. */
+ }
+ else
+ {
+ /* Either U or V is negative, but not both. */
+ return 0;
+ }
+
+ /* U and V have the same sign and are both non-zero. */
+
+ usign = usize >= 0 ? 1 : -1;
+
+ /* 2. Are the exponents different? */
+ if (uexp > vexp)
+ return 0; /* ??? handle (uexp = vexp + 1) */
+ if (vexp > uexp)
+ return 0; /* ??? handle (vexp = uexp + 1) */
+
+ usize = ABS (usize);
+ vsize = ABS (vsize);
+
+ up = u->_mp_d;
+ vp = v->_mp_d;
+
+ /* Ignore zeroes at the low end of U and V. */
+ while (up[0] == 0)
+ {
+ up++;
+ usize--;
+ }
+ while (vp[0] == 0)
+ {
+ vp++;
+ vsize--;
+ }
+
+ if (usize > vsize)
+ {
+ if (vsize * BITS_PER_MP_LIMB < n_bits)
+ return 0; /* surely too different */
+ size = vsize;
+ }
+ else if (vsize > usize)
+ {
+ if (usize * BITS_PER_MP_LIMB < n_bits)
+ return 0; /* surely too different */
+ size = usize;
+ }
+ else
+ {
+ size = usize;
+ }
+
+ if (size > (n_bits + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB)
+ size = (n_bits + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB;
+
+ up += usize - size;
+ vp += vsize - size;
+
+ for (i = size - 1; i >= 0; i--)
+ {
+ if (up[i] != vp[i])
+ return 0;
+ }
+
+ return 1;
+}
diff --git a/mpf/get_prc.c b/mpf/get_prc.c
new file mode 100644
index 000000000..7f7e41f67
--- /dev/null
+++ b/mpf/get_prc.c
@@ -0,0 +1,34 @@
+/* mpf_get_prec(x) -- Return the precision in bits of x.
+
+Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+unsigned long int
+#if __STDC__
+mpf_get_prec (mpf_srcptr x)
+#else
+mpf_get_prec (x)
+ mpf_srcptr x;
+#endif
+{
+ return (unsigned long int) x->_mp_prec * BITS_PER_MP_LIMB - BITS_PER_MP_LIMB;
+}
diff --git a/mpf/get_str.c b/mpf/get_str.c
new file mode 100644
index 000000000..bfee18d07
--- /dev/null
+++ b/mpf/get_str.c
@@ -0,0 +1,500 @@
+/* mpf_get_str (digit_ptr, exp, base, n_digits, a) -- Convert the floating
+ point number A to a base BASE number and store N_DIGITS raw digits at
+ DIGIT_PTR, and the base BASE exponent in the word pointed to by EXP. For
+ example, the number 3.1416 would be returned as "31416" in DIGIT_PTR and
+ 1 in EXP.
+
+Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+/*
+ New algorithm for converting fractions (951019):
+ 0. Call the fraction to convert F.
+ 1. Compute [exp * log(2^BITS_PER_MP_LIMB)/log(B)], i.e.,
+ [exp * BITS_PER_MP_LIMB * __mp_bases[B].chars_per_bit_exactly]. Exp is
+ the number of limbs between the limb point and the most significant
+ non-zero limb. Call this result n.
+ 2. Compute B^n.
+ 3. F*B^n will now be just below 1, which can be converted easily. (Just
+ multiply by B repeatedly, and see the digits fall out as integers.)
+ We should interrupt the conversion process of F*B^n as soon as the number
+ of digits requested have been generated.
+
+ New algorithm for converting integers (951019):
+ 0. Call the integer to convert I.
+ 1. Compute [exp * log(2^BITS_PER_MP_LIMB)/log(B)], i.e.,
+ [exp BITS_PER_MP_LIMB * __mp_bases[B].chars_per_bit_exactly]. Exp is
+ the number of limbs between the limb point and the least significant
+ non-zero limb. Call this result n.
+ 2. Compute B^n.
+ 3. I/B^n can be converted easily. (Just divide by B repeatedly. In GMP,
+ this is best done by calling mpn_get_str.)
+ Note that converting I/B^n could yield more digits than requested. For
+ efficiency, the variable n above should be set larger in such cases, to
+ kill all undesired digits in the division in step 3.
+*/
+
+char *
+#if __STDC__
+mpf_get_str (char *digit_ptr, mp_exp_t *exp, int base, size_t n_digits, mpf_srcptr u)
+#else
+mpf_get_str (digit_ptr, exp, base, n_digits, u)
+ char *digit_ptr;
+ mp_exp_t *exp;
+ int base;
+ size_t n_digits;
+ mpf_srcptr u;
+#endif
+{
+ mp_size_t usize;
+ mp_exp_t uexp;
+ unsigned char *str;
+ size_t str_size;
+ char *num_to_text;
+ long i; /* should be size_t */
+ mp_ptr rp;
+ mp_limb_t big_base;
+ size_t digits_computed_so_far;
+ int dig_per_u;
+ mp_srcptr up;
+ unsigned char *tstr;
+ mp_exp_t exp_in_base;
+ TMP_DECL (marker);
+
+ TMP_MARK (marker);
+ usize = u->_mp_size;
+ uexp = u->_mp_exp;
+
+ if (base >= 0)
+ {
+ if (base == 0)
+ base = 10;
+ num_to_text = "0123456789abcdefghijklmnopqrstuvwxyz";
+ }
+ else
+ {
+ base = -base;
+ num_to_text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ }
+
+ /* Don't compute more digits than U can accurately represent.
+ Also, if 0 digits were requested, give *exactly* as many digits
+ as can be accurately represented. */
+ {
+ size_t max_digits = (((u->_mp_prec - 1) * BITS_PER_MP_LIMB)
+ * __mp_bases[base].chars_per_bit_exactly);
+ if (n_digits == 0 || n_digits > max_digits)
+ n_digits = max_digits;
+ }
+
+ if (digit_ptr == 0)
+ {
+ /* We didn't get a string from the user. Allocate one (and return
+ a pointer to it) with space for `-' and terminating null. */
+ digit_ptr = (char *) (*_mp_allocate_func) (n_digits + 2);
+ }
+
+ if (usize == 0)
+ {
+ *exp = 0;
+ *digit_ptr = 0;
+ return digit_ptr;
+ }
+
+ str = (unsigned char *) digit_ptr;
+
+ /* Allocate temporary digit space. We can't put digits directly in the user
+ area, since we almost always generate more digits than requested. */
+ tstr = (unsigned char *) TMP_ALLOC (n_digits + 3 * BITS_PER_MP_LIMB);
+
+ if (usize < 0)
+ {
+ *digit_ptr = '-';
+ str++;
+ usize = -usize;
+ }
+
+ digits_computed_so_far = 0;
+
+ if (uexp > usize)
+ {
+ /* The number has just an integral part. */
+ mp_size_t rsize;
+ mp_size_t exp_in_limbs;
+ mp_size_t msize;
+ mp_ptr tp, xp, mp;
+ int cnt;
+ mp_limb_t cy;
+ mp_size_t start_str;
+ mp_size_t n_limbs;
+
+ n_limbs = 2 + ((mp_size_t) (n_digits / __mp_bases[base].chars_per_bit_exactly)
+ / BITS_PER_MP_LIMB);
+
+ /* Compute n such that [u/B^n] contains (somewhat) more than n_digits
+ digits. (We compute less than that only if that is an exact number,
+ i.e., exp is small enough.) */
+
+ exp_in_limbs = uexp;
+
+ if (n_limbs >= exp_in_limbs)
+ {
+ /* The number is so small that we convert the entire number. */
+ exp_in_base = 0;
+ rp = (mp_ptr) TMP_ALLOC (exp_in_limbs * BYTES_PER_MP_LIMB);
+ MPN_ZERO (rp, exp_in_limbs - usize);
+ MPN_COPY (rp + (exp_in_limbs - usize), u->_mp_d, usize);
+ rsize = exp_in_limbs;
+ }
+ else
+ {
+ exp_in_limbs -= n_limbs;
+ exp_in_base = (((exp_in_limbs * BITS_PER_MP_LIMB - 1))
+ * __mp_bases[base].chars_per_bit_exactly);
+
+ rsize = exp_in_limbs + 1;
+ rp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB);
+ tp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB);
+
+ rp[0] = base;
+ rsize = 1;
+
+ count_leading_zeros (cnt, exp_in_base);
+ for (i = BITS_PER_MP_LIMB - cnt - 2; i >= 0; i--)
+ {
+ mpn_mul_n (tp, rp, rp, rsize);
+ rsize = 2 * rsize;
+ rsize -= tp[rsize - 1] == 0;
+ xp = tp; tp = rp; rp = xp;
+
+ if (((exp_in_base >> i) & 1) != 0)
+ {
+ cy = mpn_mul_1 (rp, rp, rsize, (mp_limb_t) base);
+ rp[rsize] = cy;
+ rsize += cy != 0;
+ }
+ }
+
+ mp = u->_mp_d;
+ msize = usize;
+
+ {
+ mp_ptr qp;
+ mp_limb_t qflag;
+ mp_size_t xtra;
+ if (msize < rsize)
+ {
+ mp_ptr tmp = (mp_ptr) TMP_ALLOC ((rsize+1)* BYTES_PER_MP_LIMB);
+ MPN_ZERO (tmp, rsize - msize);
+ MPN_COPY (tmp + rsize - msize, mp, msize);
+ mp = tmp;
+ msize = rsize;
+ }
+ else
+ {
+ mp_ptr tmp = (mp_ptr) TMP_ALLOC ((msize+1)* BYTES_PER_MP_LIMB);
+ MPN_COPY (tmp, mp, msize);
+ mp = tmp;
+ }
+ count_leading_zeros (cnt, rp[rsize - 1]);
+ cy = 0;
+ if (cnt != 0)
+ {
+ mpn_lshift (rp, rp, rsize, cnt);
+ cy = mpn_lshift (mp, mp, msize, cnt);
+ if (cy)
+ mp[msize++] = cy;
+ }
+
+ {
+ mp_size_t qsize = n_limbs + (cy != 0);
+ qp = (mp_ptr) TMP_ALLOC ((qsize + 1) * BYTES_PER_MP_LIMB);
+ xtra = qsize - (msize - rsize);
+ qflag = mpn_divrem (qp, xtra, mp, msize, rp, rsize);
+ qp[qsize] = qflag;
+ rsize = qsize + qflag;
+ rp = qp;
+ }
+ }
+ }
+
+ str_size = mpn_get_str (tstr, base, rp, rsize);
+
+ if (str_size > n_digits + 3 * BITS_PER_MP_LIMB)
+ abort ();
+
+ start_str = 0;
+ while (tstr[start_str] == 0)
+ start_str++;
+
+ for (i = start_str; i < str_size; i++)
+ {
+ tstr[digits_computed_so_far++] = tstr[i];
+ if (digits_computed_so_far > n_digits)
+ break;
+ }
+ exp_in_base = exp_in_base + str_size - start_str;
+ goto finish_up;
+ }
+
+ exp_in_base = 0;
+
+ if (uexp > 0)
+ {
+ /* The number has an integral part, convert that first.
+ If there is a fractional part too, it will be handled later. */
+ mp_size_t start_str;
+
+ rp = (mp_ptr) TMP_ALLOC (uexp * BYTES_PER_MP_LIMB);
+ up = u->_mp_d + usize - uexp;
+ MPN_COPY (rp, up, uexp);
+
+ str_size = mpn_get_str (tstr, base, rp, uexp);
+
+ start_str = 0;
+ while (tstr[start_str] == 0)
+ start_str++;
+
+ for (i = start_str; i < str_size; i++)
+ {
+ tstr[digits_computed_so_far++] = tstr[i];
+ if (digits_computed_so_far > n_digits)
+ {
+ exp_in_base = str_size - start_str;
+ goto finish_up;
+ }
+ }
+
+ exp_in_base = str_size - start_str;
+ /* Modify somewhat and fall out to convert fraction... */
+ usize -= uexp;
+ uexp = 0;
+ }
+
+ if (usize <= 0)
+ goto finish_up;
+
+ /* Convert the fraction. */
+ {
+ mp_size_t rsize, msize;
+ mp_ptr rp, tp, xp, mp;
+ int cnt;
+ mp_limb_t cy;
+ mp_exp_t nexp;
+
+ big_base = __mp_bases[base].big_base;
+ dig_per_u = __mp_bases[base].chars_per_limb;
+
+ /* Hack for correctly (although not efficiently) converting to bases that
+ are powers of 2. If we deem it important, we could handle powers of 2
+ by shifting and masking (just like mpn_get_str). */
+ if (big_base < 10) /* logarithm of base when power of two */
+ {
+ int logbase = big_base;
+ if (dig_per_u * logbase == BITS_PER_MP_LIMB)
+ dig_per_u--;
+ big_base = (mp_limb_t) 1 << (dig_per_u * logbase);
+ /* fall out to general code... */
+ }
+
+#if 0
+ if (0 && uexp == 0)
+ {
+ rp = (mp_ptr) TMP_ALLOC (usize * BYTES_PER_MP_LIMB);
+ up = u->_mp_d;
+ MPN_COPY (rp, up, usize);
+ rsize = usize;
+ nexp = 0;
+ }
+ else
+ {}
+#endif
+ uexp = -uexp;
+ if (u->_mp_d[usize - 1] == 0)
+ cnt = 0;
+ else
+ count_leading_zeros (cnt, u->_mp_d[usize - 1]);
+
+ nexp = ((uexp * BITS_PER_MP_LIMB) + cnt)
+ * __mp_bases[base].chars_per_bit_exactly;
+
+ if (nexp == 0)
+ {
+ rp = (mp_ptr) TMP_ALLOC (usize * BYTES_PER_MP_LIMB);
+ up = u->_mp_d;
+ MPN_COPY (rp, up, usize);
+ rsize = usize;
+ }
+ else
+ {
+ rsize = uexp + 2;
+ rp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB);
+ tp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB);
+
+ rp[0] = base;
+ rsize = 1;
+
+ count_leading_zeros (cnt, nexp);
+ for (i = BITS_PER_MP_LIMB - cnt - 2; i >= 0; i--)
+ {
+ mpn_mul_n (tp, rp, rp, rsize);
+ rsize = 2 * rsize;
+ rsize -= tp[rsize - 1] == 0;
+ xp = tp; tp = rp; rp = xp;
+
+ if (((nexp >> i) & 1) != 0)
+ {
+ cy = mpn_mul_1 (rp, rp, rsize, (mp_limb_t) base);
+ rp[rsize] = cy;
+ rsize += cy != 0;
+ }
+ }
+
+ /* Did our multiplier (base^nexp) cancel with uexp? */
+#if 0
+ if (uexp != rsize)
+ {
+ do
+ {
+ cy = mpn_mul_1 (rp, rp, rsize, big_base);
+ nexp += dig_per_u;
+ }
+ while (cy == 0);
+ rp[rsize++] = cy;
+ }
+#endif
+ mp = u->_mp_d;
+ msize = usize;
+
+ tp = (mp_ptr) TMP_ALLOC ((rsize + msize) * BYTES_PER_MP_LIMB);
+ if (rsize > msize)
+ cy = mpn_mul (tp, rp, rsize, mp, msize);
+ else
+ cy = mpn_mul (tp, mp, msize, rp, rsize);
+ rsize += msize;
+ rsize -= cy == 0;
+ rp = tp;
+
+ /* If we already output digits (for an integral part) pad
+ leading zeros. */
+ if (digits_computed_so_far != 0)
+ for (i = 0; i < nexp; i++)
+ tstr[digits_computed_so_far++] = 0;
+ }
+
+ while (digits_computed_so_far <= n_digits)
+ {
+ /* For speed: skip trailing zeroes. */
+ if (rp[0] == 0)
+ {
+ rp++;
+ rsize--;
+ if (rsize == 0)
+ {
+ n_digits = digits_computed_so_far;
+ break;
+ }
+ }
+
+ cy = mpn_mul_1 (rp, rp, rsize, big_base);
+ if (digits_computed_so_far == 0 && cy == 0)
+ {
+ abort ();
+ nexp += dig_per_u;
+ continue;
+ }
+ /* Convert N1 from BIG_BASE to a string of digits in BASE
+ using single precision operations. */
+ {
+ unsigned char *s = tstr + digits_computed_so_far + dig_per_u;
+ for (i = dig_per_u - 1; i >= 0; i--)
+ {
+ *--s = cy % base;
+ cy /= base;
+ }
+ }
+ digits_computed_so_far += dig_per_u;
+ }
+ if (exp_in_base == 0)
+ exp_in_base = -nexp;
+ }
+
+ finish_up:
+
+ /* We can have at most one leading 0. Remove it. */
+ if (tstr[0] == 0)
+ {
+ tstr++;
+ digits_computed_so_far--;
+ exp_in_base--;
+ }
+
+ /* We should normally have computed too many digits. Round the result
+ at the point indicated by n_digits. */
+ if (digits_computed_so_far > n_digits)
+ {
+ /* Round the result. */
+ if (tstr[n_digits] * 2 >= base)
+ {
+ digits_computed_so_far = n_digits;
+ for (i = n_digits - 1; i >= 0; i--)
+ {
+ unsigned int x;
+ x = ++(tstr[i]);
+ if (x < base)
+ goto rounded_ok;
+ digits_computed_so_far--;
+ }
+ tstr[0] = 1;
+ digits_computed_so_far = 1;
+ exp_in_base++;
+ rounded_ok:;
+ }
+ }
+
+ /* We might have fewer digits than requested as a result of rounding above,
+ (i.e. 0.999999 => 1.0) or because we have a number that simply doesn't
+ need many digits in this base (i.e., 0.125 in base 10). */
+ if (n_digits > digits_computed_so_far)
+ n_digits = digits_computed_so_far;
+
+ /* Remove trailing 0. There can be many zeros. */
+ while (n_digits != 0 && tstr[n_digits - 1] == 0)
+ n_digits--;
+
+ /* Translate to ascii and null-terminate. */
+ for (i = 0; i < n_digits; i++)
+ *str++ = num_to_text[tstr[i]];
+ *str = 0;
+ *exp = exp_in_base;
+ TMP_FREE (marker);
+ return digit_ptr;
+}
+
+#if COPY_THIS_TO_OTHER_PLACES
+ /* Use this expression in lots of places in the library instead of the
+ count_leading_zeros+expression that is used currently. This expression
+ is much more accurate and will save odles of memory. */
+ rsize = ((mp_size_t) (exp_in_base / __mp_bases[base].chars_per_bit_exactly)
+ + BITS_PER_MP_LIMB) / BITS_PER_MP_LIMB;
+#endif
diff --git a/mpf/init.c b/mpf/init.c
new file mode 100644
index 000000000..53701218f
--- /dev/null
+++ b/mpf/init.c
@@ -0,0 +1,38 @@
+/* mpf_init() -- Make a new multiple precision number with value 0.
+
+Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpf_init (mpf_ptr r)
+#else
+mpf_init (r)
+ mpf_ptr r;
+#endif
+{
+ mp_size_t prec = __gmp_default_fp_limb_precision;
+ r->_mp_d = (mp_ptr) (*_mp_allocate_func) ((prec + 1) * BYTES_PER_MP_LIMB);
+ r->_mp_prec = prec;
+ r->_mp_size = 0;
+ r->_mp_exp = 0;
+}
diff --git a/mpf/init2.c b/mpf/init2.c
new file mode 100644
index 000000000..a3e5752b2
--- /dev/null
+++ b/mpf/init2.c
@@ -0,0 +1,41 @@
+/* mpf_init2() -- Make a new multiple precision number with value 0.
+
+Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpf_init2 (mpf_ptr r, unsigned long int prec_in_bits)
+#else
+mpf_init2 (r, prec_in_bits)
+ mpf_ptr r;
+ unsigned long int prec_in_bits;
+#endif
+{
+ mp_size_t prec;
+
+ prec = (MAX (53, prec_in_bits) + 2 * BITS_PER_MP_LIMB - 1)/BITS_PER_MP_LIMB;
+ r->_mp_d = (mp_ptr) (*_mp_allocate_func) ((prec + 1) * BYTES_PER_MP_LIMB);
+ r->_mp_prec = prec;
+ r->_mp_size = 0;
+ r->_mp_exp = 0;
+}
diff --git a/mpf/inp_str.c b/mpf/inp_str.c
new file mode 100644
index 000000000..1d3cd4cc2
--- /dev/null
+++ b/mpf/inp_str.c
@@ -0,0 +1,89 @@
+/* mpf_inp_str(dest_float, stream, base) -- Input a number in base
+ BASE from stdio stream STREAM and store the result in DEST_FLOAT.
+
+Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <ctype.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+
+size_t
+#if __STDC__
+mpf_inp_str (mpf_ptr rop, FILE *stream, int base)
+#else
+mpf_inp_str (rop, stream, base)
+ mpf_ptr rop;
+ FILE *stream;
+ int base;
+#endif
+{
+ char *str;
+ size_t alloc_size, str_size;
+ int c;
+ size_t retval;
+ size_t nread;
+
+ if (stream == 0)
+ stream = stdin;
+
+ alloc_size = 100;
+ str = (char *) (*_mp_allocate_func) (alloc_size);
+ str_size = 0;
+ nread = 0;
+
+ /* Skip whitespace. */
+ do
+ {
+ c = getc (stream);
+ nread++;
+ }
+ while (isspace (c));
+
+ for (;;)
+ {
+ if (str_size >= alloc_size)
+ {
+ size_t old_alloc_size = alloc_size;
+ alloc_size = alloc_size * 3 / 2;
+ str = (char *) (*_mp_reallocate_func) (str, old_alloc_size, alloc_size);
+ }
+ if (c == EOF || isspace (c))
+ break;
+ str[str_size++] = c;
+ c = getc (stream);
+ }
+ ungetc (c, stream);
+
+ if (str_size >= alloc_size)
+ {
+ size_t old_alloc_size = alloc_size;
+ alloc_size = alloc_size * 3 / 2;
+ str = (char *) (*_mp_reallocate_func) (str, old_alloc_size, alloc_size);
+ }
+ str[str_size] = 0;
+
+ retval = mpf_set_str (rop, str, base);
+ if (retval == -1)
+ return 0; /* error */
+
+ (*_mp_free_func) (str, alloc_size);
+ return str_size + nread;
+}
diff --git a/mpf/iset.c b/mpf/iset.c
new file mode 100644
index 000000000..c2362e172
--- /dev/null
+++ b/mpf/iset.c
@@ -0,0 +1,59 @@
+/* mpf_init_set -- Initialize a float and assign it from another float.
+
+Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpf_init_set (mpf_ptr r, mpf_srcptr s)
+#else
+mpf_init_set (r, s)
+ mpf_ptr r;
+ mpf_srcptr s;
+#endif
+{
+ mp_ptr rp, sp;
+ mp_size_t ssize, size;
+ mp_size_t prec;
+
+ prec = __gmp_default_fp_limb_precision;
+ r->_mp_d = (mp_ptr) (*_mp_allocate_func) ((prec + 1) * BYTES_PER_MP_LIMB);
+ r->_mp_prec = prec;
+
+ prec++; /* lie not to lose precision in assignment */
+ ssize = s->_mp_size;
+ size = ABS (ssize);
+
+ rp = r->_mp_d;
+ sp = s->_mp_d;
+
+ if (size > prec)
+ {
+ sp += size - prec;
+ size = prec;
+ }
+
+ MPN_COPY (rp, sp, size);
+
+ r->_mp_exp = s->_mp_exp;
+ r->_mp_size = ssize >= 0 ? size : -size;
+}
diff --git a/mpf/iset_d.c b/mpf/iset_d.c
new file mode 100644
index 000000000..d09e8b89a
--- /dev/null
+++ b/mpf/iset_d.c
@@ -0,0 +1,39 @@
+/* mpf_init_set_d -- Initialize a float and assign it from a double.
+
+Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpf_init_set_d (mpf_ptr r, double val)
+#else
+mpf_init_set_d (r, val)
+ mpf_ptr r;
+ double val;
+#endif
+{
+ mp_size_t prec = __gmp_default_fp_limb_precision;
+ r->_mp_d = (mp_ptr) (*_mp_allocate_func) ((prec + 1) * BYTES_PER_MP_LIMB);
+ r->_mp_prec = prec;
+
+ mpf_set_d (r, val);
+}
diff --git a/mpf/iset_si.c b/mpf/iset_si.c
new file mode 100644
index 000000000..e67eef4cd
--- /dev/null
+++ b/mpf/iset_si.c
@@ -0,0 +1,55 @@
+/* mpf_init_set_si() -- Initialize a float and assign it from a signed int.
+
+Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpf_init_set_si (mpf_ptr r, long int val)
+#else
+mpf_init_set_si (r, val)
+ mpf_ptr r;
+ long int val;
+#endif
+{
+ mp_size_t prec = __gmp_default_fp_limb_precision;
+ r->_mp_d = (mp_ptr) (*_mp_allocate_func) ((prec + 1) * BYTES_PER_MP_LIMB);
+ r->_mp_prec = prec;
+
+ if (val > 0)
+ {
+ r->_mp_d[0] = val;
+ r->_mp_size = 1;
+ r->_mp_exp = 1;
+ }
+ else if (val < 0)
+ {
+ r->_mp_d[0] = -val;
+ r->_mp_size = -1;
+ r->_mp_exp = 1;
+ }
+ else
+ {
+ r->_mp_size = 0;
+ r->_mp_exp = 0;
+ }
+}
diff --git a/mpf/iset_str.c b/mpf/iset_str.c
new file mode 100644
index 000000000..5c267e7ea
--- /dev/null
+++ b/mpf/iset_str.c
@@ -0,0 +1,40 @@
+/* mpf_init_set_str -- Initialize a float and assign it from a string.
+
+Copyright (C) 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+int
+#if __STDC__
+mpf_init_set_str (mpf_ptr r, char *s, int base)
+#else
+mpf_init_set_str (r, s, base)
+ mpf_ptr r;
+ char *s;
+ int base;
+#endif
+{
+ mp_size_t prec = __gmp_default_fp_limb_precision;
+ r->_mp_d = (mp_ptr) (*_mp_allocate_func) ((prec + 1) * BYTES_PER_MP_LIMB);
+ r->_mp_prec = prec;
+
+ return mpf_set_str (r, s, base);
+}
diff --git a/mpf/iset_ui.c b/mpf/iset_ui.c
new file mode 100644
index 000000000..c6c24afaf
--- /dev/null
+++ b/mpf/iset_ui.c
@@ -0,0 +1,40 @@
+/* mpf_init_set_ui() -- Initialize a float and assign it from an unsigned int.
+
+Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpf_init_set_ui (mpf_ptr r, unsigned long int val)
+#else
+mpf_init_set_ui (r, val)
+ mpf_ptr r;
+ unsigned long int val;
+#endif
+{
+ mp_size_t prec = __gmp_default_fp_limb_precision;
+ r->_mp_d = (mp_ptr) (*_mp_allocate_func) ((prec + 1) * BYTES_PER_MP_LIMB);
+ r->_mp_prec = prec;
+ r->_mp_d[0] = val;
+ r->_mp_size = val != 0;
+ r->_mp_exp = val != 0;
+}
diff --git a/mpf/mul.c b/mpf/mul.c
new file mode 100644
index 000000000..e5a1f06b3
--- /dev/null
+++ b/mpf/mul.c
@@ -0,0 +1,94 @@
+/* mpf_mul -- Multiply two floats.
+
+Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpf_mul (mpf_ptr r, mpf_srcptr u, mpf_srcptr v)
+#else
+mpf_mul (r, u, v)
+ mpf_ptr r;
+ mpf_srcptr u;
+ mpf_srcptr v;
+#endif
+{
+ mp_srcptr up, vp;
+ mp_size_t usize, vsize;
+ mp_size_t sign_product;
+ mp_size_t prec = r->_mp_prec;
+ TMP_DECL (marker);
+
+ TMP_MARK (marker);
+ usize = u->_mp_size;
+ vsize = v->_mp_size;
+ sign_product = usize ^ vsize;
+
+ usize = ABS (usize);
+ vsize = ABS (vsize);
+
+ up = u->_mp_d;
+ vp = v->_mp_d;
+ if (usize > prec)
+ {
+ up += usize - prec;
+ usize = prec;
+ }
+ if (vsize > prec)
+ {
+ vp += vsize - prec;
+ vsize = prec;
+ }
+
+ if (usize == 0 || vsize == 0)
+ {
+ r->_mp_size = 0;
+ r->_mp_exp = 0; /* ??? */
+ }
+ else
+ {
+ mp_size_t rsize;
+ mp_limb_t cy_limb;
+ mp_ptr rp, tp;
+ mp_size_t adj;
+
+ rsize = usize + vsize;
+ tp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB);
+ cy_limb = (usize >= vsize
+ ? mpn_mul (tp, up, usize, vp, vsize)
+ : mpn_mul (tp, vp, vsize, up, usize));
+
+ adj = cy_limb == 0;
+ rsize -= adj;
+ prec++;
+ if (rsize > prec)
+ {
+ tp += rsize - prec;
+ rsize = prec;
+ }
+ rp = r->_mp_d;
+ MPN_COPY (rp, tp, rsize);
+ r->_mp_exp = u->_mp_exp + v->_mp_exp - adj;
+ r->_mp_size = sign_product >= 0 ? rsize : -rsize;
+ }
+ TMP_FREE (marker);
+}
diff --git a/mpf/mul_2exp.c b/mpf/mul_2exp.c
new file mode 100644
index 000000000..0ed35a0b1
--- /dev/null
+++ b/mpf/mul_2exp.c
@@ -0,0 +1,89 @@
+/* mpf_mul_2exp -- Multiply a float by 2^n.
+
+Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpf_mul_2exp (mpf_ptr r, mpf_srcptr u, unsigned long int exp)
+#else
+mpf_mul_2exp (r, u, exp)
+ mpf_ptr r;
+ mpf_srcptr u;
+ unsigned long int exp;
+#endif
+{
+ mp_srcptr up;
+ mp_ptr rp = r->_mp_d;
+ mp_size_t usize;
+ mp_size_t abs_usize;
+ mp_size_t prec = r->_mp_prec;
+ mp_exp_t uexp = u->_mp_exp;
+
+ usize = u->_mp_size;
+
+ if (usize == 0)
+ {
+ r->_mp_size = 0;
+ r->_mp_exp = 0;
+ return;
+ }
+
+ abs_usize = ABS (usize);
+ up = u->_mp_d;
+
+ if (abs_usize > prec)
+ {
+ up += abs_usize - prec;
+ abs_usize = prec;
+ }
+
+ if (exp % BITS_PER_MP_LIMB == 0)
+ {
+ if (rp != up)
+ MPN_COPY (rp, up, abs_usize);
+ r->_mp_size = usize >= 0 ? abs_usize : -abs_usize;
+ r->_mp_exp = uexp + exp / BITS_PER_MP_LIMB;
+ }
+ else
+ {
+ mp_limb_t cy_limb;
+ if (r != u)
+ {
+ cy_limb = mpn_lshift (rp, up, abs_usize, exp % BITS_PER_MP_LIMB);
+ rp[abs_usize] = cy_limb;
+ cy_limb = cy_limb != 0;
+ }
+ else
+ {
+ /* Use mpn_rshift since mpn_lshift operates downwards, and we
+ therefore would clobber part of U before using that part. */
+ cy_limb = mpn_rshift (rp + 1, up, abs_usize, -exp % BITS_PER_MP_LIMB);
+ rp[0] = cy_limb;
+ cy_limb = rp[abs_usize] != 0;
+ }
+
+ abs_usize += cy_limb;
+ r->_mp_size = usize >= 0 ? abs_usize : -abs_usize;
+ r->_mp_exp = uexp + exp / BITS_PER_MP_LIMB + cy_limb;
+ }
+}
diff --git a/mpf/mul_ui.c b/mpf/mul_ui.c
new file mode 100644
index 000000000..8299b4c21
--- /dev/null
+++ b/mpf/mul_ui.c
@@ -0,0 +1,72 @@
+/* mpf_mul_ui -- Multiply a float and an unsigned integer.
+
+Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpf_mul_ui (mpf_ptr r, mpf_srcptr u, unsigned long int v)
+#else
+mpf_mul_ui (r, u, v)
+ mpf_ptr r;
+ mpf_srcptr u;
+ unsigned long int v;
+#endif
+{
+ mp_srcptr up;
+ mp_size_t usize;
+ mp_size_t size;
+ mp_size_t prec = r->_mp_prec;
+ mp_limb_t cy_limb;
+ mp_ptr rp;
+
+ usize = u->_mp_size;
+ size = ABS (usize);
+
+ rp = r->_mp_d;
+ up = u->_mp_d;
+ if (size > prec)
+ {
+ up += size - prec;
+ size = prec;
+ }
+
+ /* Since we can do it at almost no cost, remove zero limbs at low end of
+ result. */
+ if (up[0] == 0)
+ up++, size--;
+
+ if (size == 0 || v == 0)
+ {
+ r->_mp_size = 0;
+ r->_mp_exp = 0; /* ??? */
+ }
+ else
+ {
+ cy_limb = mpn_mul_1 (rp, up, size, (mp_limb_t) v);
+ rp[size] = cy_limb;
+ cy_limb = cy_limb != 0;
+ r->_mp_exp = u->_mp_exp + cy_limb;
+ size += cy_limb;
+ r->_mp_size = usize >= 0 ? size : -size;
+ }
+}
diff --git a/mpf/neg.c b/mpf/neg.c
new file mode 100644
index 000000000..a4139fb90
--- /dev/null
+++ b/mpf/neg.c
@@ -0,0 +1,59 @@
+/* mpf_neg -- Negate a float.
+
+Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpf_neg (mpf_ptr r, mpf_srcptr u)
+#else
+mpf_neg (r, u)
+ mpf_ptr r;
+ mpf_srcptr u;
+#endif
+{
+ mp_size_t size;
+
+ size = -u->_mp_size;
+ if (r != u)
+ {
+ mp_size_t prec;
+ mp_size_t asize;
+ mp_ptr rp, up;
+
+ prec = r->_mp_prec + 1; /* lie not to lose precision in assignment */
+ asize = ABS (size);
+ rp = r->_mp_d;
+ up = u->_mp_d;
+
+ if (asize > prec)
+ {
+ up += asize - prec;
+ asize = prec;
+ }
+
+ MPN_COPY (rp, up, asize);
+ r->_mp_exp = u->_mp_exp;
+ size = size >= 0 ? asize : -asize;
+ }
+ r->_mp_size = size;
+}
diff --git a/mpf/out_str.c b/mpf/out_str.c
new file mode 100644
index 000000000..a1bd328ca
--- /dev/null
+++ b/mpf/out_str.c
@@ -0,0 +1,89 @@
+/* mpf_out_str (stream, base, n_digits, op) -- Print N_DIGITS digits from
+ the float OP to STREAM in base BASE. Return the number of characters
+ written, or 0 if an error occurred.
+
+Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+
+size_t
+#if __STDC__
+mpf_out_str (FILE *stream, int base, size_t n_digits, mpf_srcptr op)
+#else
+mpf_out_str (stream, base, n_digits, op)
+ FILE *stream;
+ int base;
+ size_t n_digits;
+ mpf_srcptr op;
+#endif
+{
+ char *str;
+ mp_exp_t exp;
+ size_t written;
+ TMP_DECL (marker);
+
+ TMP_MARK (marker);
+
+ if (base == 0)
+ base = 10;
+ if (n_digits == 0)
+ n_digits = (((op->_mp_prec - 1) * BITS_PER_MP_LIMB)
+ * __mp_bases[base].chars_per_bit_exactly);
+
+ if (stream == 0)
+ stream = stdout;
+
+ str = (char *) TMP_ALLOC (n_digits + 2); /* extra for minus sign and \0 */
+
+ mpf_get_str (str, &exp, base, n_digits, op);
+ n_digits = strlen (str);
+
+ written = 0;
+
+ /* Write sign */
+ if (str[0] == '-')
+ {
+ str++;
+ fputc ('-', stream);
+ written = 1;
+ }
+
+ fwrite ("0.", 1, 2, stream);
+ written += 2;
+
+ /* Write mantissa */
+ {
+ size_t fwret;
+ fwret = fwrite (str, 1, n_digits, stream);
+ written += fwret;
+ }
+
+ /* Write exponent */
+ {
+ int fpret;
+ fpret = fprintf (stream, "@%ld\n", exp);
+ written += fpret;
+ }
+
+ TMP_FREE (marker);
+ return ferror (stream) ? 0 : written;
+}
diff --git a/mpf/random2.c b/mpf/random2.c
new file mode 100644
index 000000000..b09128396
--- /dev/null
+++ b/mpf/random2.c
@@ -0,0 +1,65 @@
+/* mpf_random2 -- Generate a positive random mpf_t of specified size, with
+ long runs of consecutive ones and zeros in the binary representation.
+ Intended for testing of other MP routines.
+
+Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+#if defined (__hpux) || defined (__alpha__) || defined (__svr4__) || defined (__SVR4)
+/* HPUX lacks random(). DEC OSF/1 1.2 random() returns a double. */
+long mrand48 ();
+static inline long
+random ()
+{
+ return mrand48 ();
+}
+#else
+long random ();
+#endif
+
+void
+#if __STDC__
+mpf_random2 (mpf_ptr x, mp_size_t size, mp_exp_t exp)
+#else
+mpf_random2 (x, size, exp)
+ mpf_ptr x;
+ mp_size_t size;
+ mp_exp_t exp;
+#endif
+{
+ mp_size_t asize;
+ mp_size_t prec = x->_mp_prec;
+
+ asize = ABS (size);
+ if (asize != 0)
+ {
+ if (asize > prec + 1)
+ asize = prec + 1;
+
+ mpn_random2 (x->_mp_d, asize);
+ }
+
+ if (exp != 0)
+ exp = random () % (2 * exp) - exp;
+ x->_mp_exp = asize == 0 ? 0 : exp;
+ x->_mp_size = size < 0 ? -asize : asize;
+}
diff --git a/mpf/reldiff.c b/mpf/reldiff.c
new file mode 100644
index 000000000..97039abc1
--- /dev/null
+++ b/mpf/reldiff.c
@@ -0,0 +1,52 @@
+/* mpf_reldiff -- Generate the relative difference of two floats.
+
+Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpf_reldiff (mpf_t rdiff, const mpf_t x, const mpf_t y)
+#else
+mpf_reldiff (rdiff, x, y)
+ mpf_t rdiff;
+ const mpf_t x;
+ const mpf_t y;
+#endif
+{
+ if (mpf_cmp_ui (x, 0) == 0)
+ {
+ mpf_set_ui (rdiff, (unsigned long int) (mpf_sgn (y) != 0));
+ }
+ else
+ {
+ mpf_t d;
+ mp_limb_t tmp_limb[2];
+
+ d->_mp_prec = 1;
+ d->_mp_d = tmp_limb;
+
+ mpf_sub (d, x, y);
+ mpf_abs (d, d);
+ mpf_div (rdiff, d, x);
+ }
+}
+
diff --git a/mpf/set.c b/mpf/set.c
new file mode 100644
index 000000000..5778b85b0
--- /dev/null
+++ b/mpf/set.c
@@ -0,0 +1,53 @@
+/* mpf_set -- Assign a float from another float.
+
+Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpf_set (mpf_ptr r, mpf_srcptr u)
+#else
+mpf_set (r, u)
+ mpf_ptr r;
+ mpf_srcptr u;
+#endif
+{
+ mp_ptr rp, up;
+ mp_size_t size, asize;
+ mp_size_t prec;
+
+ prec = r->_mp_prec + 1; /* lie not to lose precision in assignment */
+ size = u->_mp_size;
+ asize = ABS (size);
+ rp = r->_mp_d;
+ up = u->_mp_d;
+
+ if (asize > prec)
+ {
+ up += asize - prec;
+ asize = prec;
+ }
+
+ MPN_COPY (rp, up, asize);
+ r->_mp_exp = u->_mp_exp;
+ r->_mp_size = size >= 0 ? asize : -asize;
+}
diff --git a/mpf/set_d.c b/mpf/set_d.c
new file mode 100644
index 000000000..b82e5f023
--- /dev/null
+++ b/mpf/set_d.c
@@ -0,0 +1,97 @@
+/* mpf_set_d -- Assign a float from a IEEE double.
+
+Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpf_set_d (mpf_ptr r, double d)
+#else
+mpf_set_d (r, d)
+ mpf_ptr r;
+ double d;
+#endif
+{
+ mp_ptr rp;
+ mp_size_t size;
+ mp_exp_t exp;
+ mp_limb_t manh, manl;
+ mp_limb_t man2, man1, man0;
+ union ieee_double_extract x;
+ unsigned sc;
+
+ /* ??? This needs more work since it assumes that limbs are 32 bits.
+ See mpz/set_d for ideas on how to handle 64-bit machines. */
+
+ if (d == 0)
+ {
+ r->_mp_exp = 0;
+ r->_mp_size = 0;
+ return;
+ }
+
+ rp = r->_mp_d;
+ x.d = d;
+
+ exp = x.s.exp;
+ sc = (unsigned) (exp + 2) % BITS_PER_MP_LIMB;
+
+ manh = 0x80000000 | (x.s.manh << 11) | (x.s.manl >> 21);
+ manl = x.s.manl << 11;
+ if (sc != 0)
+ {
+ man2 = manh >> (BITS_PER_MP_LIMB - sc);
+ man1 = (manl >> (BITS_PER_MP_LIMB - sc)) | (manh << sc);
+ man0 = manl << sc;
+ }
+ else
+ {
+ man2 = manh;
+ man1 = manl;
+ man0 = 0;
+ }
+
+ if (man0 == 0)
+ {
+ if (man1 == 0)
+ {
+ size = 1;
+ rp[0] = man2;
+ }
+ else
+ {
+ size = 2;
+ rp[1] = man2;
+ rp[0] = man1;
+ }
+ }
+ else
+ {
+ size = 3;
+ rp[2] = man2;
+ rp[1] = man1;
+ rp[0] = man0;
+ }
+
+ r->_mp_exp = (exp + 1) / BITS_PER_MP_LIMB - 1024 / BITS_PER_MP_LIMB + 1;
+ r->_mp_size = x.s.sig == 0 ? size : -size;
+}
diff --git a/mpf/set_dfl_prec.c b/mpf/set_dfl_prec.c
new file mode 100644
index 000000000..55069e4e4
--- /dev/null
+++ b/mpf/set_dfl_prec.c
@@ -0,0 +1,40 @@
+/* mpf_set_default_prec --
+
+Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+mp_size_t __gmp_default_fp_limb_precision
+ = (53 + 2 * BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB;
+
+void
+#if __STDC__
+mpf_set_default_prec (unsigned long int prec_in_bits)
+#else
+mpf_set_default_prec (prec_in_bits)
+ unsigned long int prec_in_bits;
+#endif
+{
+ mp_size_t prec;
+
+ prec = (MAX (53, prec_in_bits) + 2 * BITS_PER_MP_LIMB - 1)/BITS_PER_MP_LIMB;
+ __gmp_default_fp_limb_precision = prec;
+}
diff --git a/mpf/set_prc.c b/mpf/set_prc.c
new file mode 100644
index 000000000..10f2b0671
--- /dev/null
+++ b/mpf/set_prc.c
@@ -0,0 +1,57 @@
+/* mpf_set_prec(x) -- Change the precision of x.
+
+Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpf_set_prec (mpf_ptr x, unsigned long int prec_in_bits)
+#else
+mpf_set_prec (x, prec_in_bits)
+ mpf_ptr x;
+ unsigned long int prec_in_bits;
+#endif
+{
+ mp_size_t prec;
+ mp_size_t size = ABS (x->_mp_size);
+
+ prec = (MAX (53, prec_in_bits) + 2 * BITS_PER_MP_LIMB - 1)/BITS_PER_MP_LIMB;
+
+ /* We want the most significant limbs, so move the limbs down if we are
+ about to truncate the value. */
+ if (size > prec + 1)
+ {
+ mp_size_t offset = size - (prec + 1);
+ mp_ptr xp = x->_mp_d;
+
+ MPN_COPY (xp, xp + offset, prec + 1);
+ }
+
+ x->_mp_d = (mp_ptr) (*_mp_reallocate_func)
+ (x->_mp_d,
+ (x->_mp_prec + 1) * BYTES_PER_MP_LIMB, (prec + 1) * BYTES_PER_MP_LIMB);
+ x->_mp_prec = prec;
+
+ /* If the precision decreased, truncate the number. */
+ if (size > prec + 1)
+ x->_mp_size = x->_mp_size >= 0 ? (prec + 1) : -(prec + 1);
+}
diff --git a/mpf/set_prc_raw.c b/mpf/set_prc_raw.c
new file mode 100644
index 000000000..f55188a12
--- /dev/null
+++ b/mpf/set_prc_raw.c
@@ -0,0 +1,39 @@
+/* mpf_set_prec_raw(x,bits) -- Change the precision of x without changing
+ allocation. For proper operation, the original precision need to be reset
+ sooner or later.
+
+Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpf_set_prec_raw (mpf_ptr x, unsigned long int prec_in_bits)
+#else
+mpf_set_prec_raw (x, prec_in_bits)
+ mpf_ptr x;
+ unsigned long int prec_in_bits;
+#endif
+{
+ mp_size_t prec;
+ prec = (MAX (53, prec_in_bits) + 2 * BITS_PER_MP_LIMB - 1)/BITS_PER_MP_LIMB;
+ x->_mp_prec = prec;
+}
diff --git a/mpf/set_si.c b/mpf/set_si.c
new file mode 100644
index 000000000..f9b4b55eb
--- /dev/null
+++ b/mpf/set_si.c
@@ -0,0 +1,51 @@
+/* mpf_set_si() -- Assign a float from a signed int.
+
+Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpf_set_si (mpf_ptr x, long int val)
+#else
+mpf_set_si (x, val)
+ mpf_ptr x;
+ long int val;
+#endif
+{
+ if (val > 0)
+ {
+ x->_mp_d[0] = val;
+ x->_mp_size = 1;
+ x->_mp_exp = 1;
+ }
+ else if (val < 0)
+ {
+ x->_mp_d[0] = -val;
+ x->_mp_size = -1;
+ x->_mp_exp = 1;
+ }
+ else
+ {
+ x->_mp_size = 0;
+ x->_mp_exp = 0;
+ }
+}
diff --git a/mpf/set_str.c b/mpf/set_str.c
new file mode 100644
index 000000000..2ab9faebe
--- /dev/null
+++ b/mpf/set_str.c
@@ -0,0 +1,302 @@
+/* mpf_set_str (dest, string, base) -- Convert the string STRING
+ in base BASE to a float in dest. If BASE is zero, the leading characters
+ of STRING is used to figure out the base.
+
+Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <string.h>
+#include <ctype.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+long int strtol _PROTO ((const char *, char **ptr, int));
+
+static int
+digit_value_in_base (c, base)
+ int c;
+ int base;
+{
+ int digit;
+
+ if (isdigit (c))
+ digit = c - '0';
+ else if (islower (c))
+ digit = c - 'a' + 10;
+ else if (isupper (c))
+ digit = c - 'A' + 10;
+ else
+ return -1;
+
+ if (digit < base)
+ return digit;
+ return -1;
+}
+
+int
+#if __STDC__
+mpf_set_str (mpf_ptr x, const char *str, int base)
+#else
+mpf_set_str (x, str, base)
+ mpf_ptr x;
+ char *str;
+ int base;
+#endif
+{
+ size_t str_size;
+ char *s, *begs;
+ size_t i;
+ mp_size_t xsize;
+ int c;
+ int negative;
+ char *dotpos = 0;
+ int expflag;
+ int decimal_exponent_flag;
+ TMP_DECL (marker);
+
+ TMP_MARK (marker);
+
+ c = *str;
+
+ /* Skip whitespace. */
+ while (isspace (c))
+ c = *++str;
+
+ negative = 0;
+ if (c == '-')
+ {
+ negative = 1;
+ c = *++str;
+ }
+
+ decimal_exponent_flag = base < 0;
+ base = ABS (base);
+
+ if (digit_value_in_base (c, base == 0 ? 10 : base) < 0)
+ return -1; /* error if no digits */
+
+ /* If BASE is 0, try to find out the base by looking at the initial
+ characters. */
+ if (base == 0)
+ {
+ base = 10;
+#if 0
+ if (c == '0')
+ {
+ base = 8;
+ c = *++str;
+ if (c == 'x' || c == 'X')
+ base = 16;
+ }
+#endif
+ }
+
+ expflag = 0;
+ str_size = strlen (str);
+ for (i = 0; i < str_size; i++)
+ {
+ c = str[i];
+ if (c == '@' || (base <= 10 && (c == 'e' || c == 'E')))
+ {
+ expflag = 1;
+ str_size = i;
+ break;
+ }
+
+ }
+
+ s = begs = (char *) TMP_ALLOC (str_size + 1);
+
+ for (i = 0; i < str_size; i++)
+ {
+ c = *str;
+ if (!isspace (c))
+ {
+ int dig;
+
+ if (c == '.')
+ {
+ if (dotpos != 0)
+ {
+ TMP_FREE (marker);
+ return -1;
+ }
+ dotpos = s;
+ }
+ else
+ {
+ dig = digit_value_in_base (c, base);
+ if (dig < 0)
+ {
+ TMP_FREE (marker);
+ return -1;
+ }
+ *s++ = dig;
+ }
+ }
+ c = *++str;
+ }
+
+ str_size = s - begs;
+
+ xsize = str_size / __mp_bases[base].chars_per_limb + 2;
+ {
+ long exp_in_base;
+ mp_size_t rsize, msize;
+ int cnt, i;
+ mp_ptr mp, xp, tp, rp;
+ mp_limb_t cy;
+ mp_exp_t exp_in_limbs;
+ mp_size_t prec = x->_mp_prec;
+ int divflag;
+ mp_size_t xxx = 0;
+
+ mp = (mp_ptr) TMP_ALLOC (xsize * BYTES_PER_MP_LIMB);
+ msize = mpn_set_str (mp, (unsigned char *) begs, str_size, base);
+
+ if (msize == 0)
+ {
+ x->_mp_size = 0;
+ x->_mp_exp = 0;
+ TMP_FREE (marker);
+ return 0;
+ }
+
+ if (expflag != 0)
+ exp_in_base = strtol (str + 1, (char **) 0,
+ decimal_exponent_flag ? 10 : base);
+ else
+ exp_in_base = 0;
+ if (dotpos != 0)
+ exp_in_base -= s - dotpos;
+ divflag = exp_in_base < 0;
+ exp_in_base = ABS (exp_in_base);
+
+ if (exp_in_base == 0)
+ {
+ MPN_COPY (x->_mp_d, mp, msize);
+ x->_mp_size = negative ? -msize : msize;
+ x->_mp_exp = msize;
+ TMP_FREE (marker);
+ return 0;
+ }
+
+#if 1
+ rsize = (((mp_size_t) (exp_in_base / __mp_bases[base].chars_per_bit_exactly))
+ / BITS_PER_MP_LIMB + 3);
+#else
+ count_leading_zeros (cnt, (mp_limb_t) base);
+ rsize = exp_in_base - cnt * exp_in_base / BITS_PER_MP_LIMB + 1;
+#endif
+ rp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB);
+ tp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB);
+
+ rp[0] = base;
+ rsize = 1;
+
+ count_leading_zeros (cnt, exp_in_base);
+
+ for (i = BITS_PER_MP_LIMB - cnt - 2; i >= 0; i--)
+ {
+ mpn_mul_n (tp, rp, rp, rsize);
+ rsize = 2 * rsize;
+ rsize -= tp[rsize - 1] == 0;
+ xp = tp; tp = rp; rp = xp;
+
+ if (((exp_in_base >> i) & 1) != 0)
+ {
+ cy = mpn_mul_1 (rp, rp, rsize, (mp_limb_t) base);
+ rp[rsize] = cy;
+ rsize += cy != 0;
+ }
+ }
+
+ if (rsize > prec)
+ {
+ xxx += rsize - prec;
+ rp += rsize - prec;
+ rsize = prec;
+ }
+#if 0
+ if (msize > prec)
+ {
+ xxx -= msize - prec;
+ mp += msize - prec;
+ msize = prec;
+ }
+#endif
+ if (divflag)
+ {
+ mp_ptr qp;
+ mp_limb_t qflag;
+ mp_size_t xtra;
+ if (msize <= rsize)
+ {
+ /* Allocate extra limb for current divrem sematics. */
+ mp_ptr tmp = (mp_ptr) TMP_ALLOC ((rsize + 1) * BYTES_PER_MP_LIMB);
+ MPN_ZERO (tmp, rsize - msize);
+ MPN_COPY (tmp + rsize - msize, mp, msize);
+ mp = tmp;
+ xxx += rsize - msize;
+ msize = rsize;
+ }
+ count_leading_zeros (cnt, rp[rsize - 1]);
+ if (cnt != 0)
+ {
+ mpn_lshift (rp, rp, rsize, cnt);
+ cy = mpn_lshift (mp, mp, msize, cnt);
+ if (cy)
+ mp[msize++] = cy;
+ }
+ qp = (mp_ptr) TMP_ALLOC ((prec + 1) * BYTES_PER_MP_LIMB);
+ xtra = prec - (msize - rsize);
+ qflag = mpn_divrem (qp, xtra, mp, msize, rp, rsize);
+ qp[prec] = qflag;
+ tp = qp;
+ rsize = prec + qflag;
+ exp_in_limbs = rsize - xtra - xxx;
+ }
+ else
+ {
+ tp = (mp_ptr) TMP_ALLOC ((rsize + msize) * BYTES_PER_MP_LIMB);
+ if (rsize > msize)
+ mpn_mul (tp, rp, rsize, mp, msize);
+ else
+ mpn_mul (tp, mp, msize, rp, rsize);
+ rsize += msize;
+ rsize -= tp[rsize - 1] == 0;
+ exp_in_limbs = rsize + xxx;
+
+ if (rsize > prec)
+ {
+ xxx = rsize - prec;
+ tp += rsize - prec;
+ rsize = prec;
+ exp_in_limbs += 0;
+ }
+ }
+
+ MPN_COPY (x->_mp_d, tp, rsize);
+ x->_mp_size = negative ? -rsize : rsize;
+ x->_mp_exp = exp_in_limbs;
+ TMP_FREE (marker);
+ return 0;
+ }
+}
diff --git a/mpf/set_ui.c b/mpf/set_ui.c
new file mode 100644
index 000000000..ead0498aa
--- /dev/null
+++ b/mpf/set_ui.c
@@ -0,0 +1,45 @@
+/* mpf_set_ui() -- Assign a float from an unsigned int.
+
+Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpf_set_ui (mpf_ptr x, unsigned long int val)
+#else
+mpf_set_ui (x, val)
+ mpf_ptr x;
+ unsigned long int val;
+#endif
+{
+ if (val != 0)
+ {
+ x->_mp_d[0] = val;
+ x->_mp_size = 1;
+ x->_mp_exp = 1;
+ }
+ else
+ {
+ x->_mp_size = 0;
+ x->_mp_exp = 0;
+ }
+}
diff --git a/mpf/size.c b/mpf/size.c
new file mode 100644
index 000000000..23a57ec72
--- /dev/null
+++ b/mpf/size.c
@@ -0,0 +1,35 @@
+/* mpf_size(x) -- return the number of limbs currently used by the
+ value of the float X.
+
+Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+size_t
+#if __STDC__
+mpf_size (mpf_srcptr x)
+#else
+mpf_size (x)
+ mpf_srcptr x;
+#endif
+{
+ return ABS (x->_mp_size);
+}
diff --git a/mpf/sqrt.c b/mpf/sqrt.c
new file mode 100644
index 000000000..a0cc4ddb7
--- /dev/null
+++ b/mpf/sqrt.c
@@ -0,0 +1,79 @@
+/* mpf_sqrt -- Compute the square root of a float.
+
+Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/* This code is just correct if "unsigned char" has at least 8 bits. It
+ doesn't help to use CHAR_BIT from limits.h, as the real problem is
+ the static arrays. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpf_sqrt (mpf_ptr r, mpf_srcptr u)
+#else
+mpf_sqrt (r, u)
+ mpf_ptr r;
+ mpf_srcptr u;
+#endif
+{
+ mp_size_t usize;
+ mp_ptr up, tp;
+ mp_size_t prec;
+ mp_exp_t tsize, rexp;
+ TMP_DECL (marker);
+
+ usize = u->_mp_size;
+ if (usize <= 0)
+ {
+ usize = 1 / usize > 0; /* Divide by zero for negative OP. */
+ r->_mp_size = 0;
+ r->_mp_exp = 0;
+ return;
+ }
+
+ TMP_MARK (marker);
+
+ prec = r->_mp_prec;
+ rexp = (u->_mp_exp + 1) >> 1; /* round towards -inf */
+ tsize = 2 * prec + (u->_mp_exp & 1);
+
+ up = u->_mp_d;
+ tp = (mp_ptr) TMP_ALLOC (tsize * BYTES_PER_MP_LIMB);
+
+ if (usize > tsize)
+ {
+ up += usize - tsize;
+ usize = tsize;
+ MPN_COPY (tp, up, tsize);
+ }
+ else
+ {
+ MPN_ZERO (tp, tsize - usize);
+ MPN_COPY (tp + (tsize - usize), up, usize);
+ }
+
+ mpn_sqrtrem (r->_mp_d, NULL, tp, tsize);
+
+ r->_mp_size = (tsize + 1) / 2;
+ r->_mp_exp = rexp;
+ TMP_FREE (marker);
+}
diff --git a/mpf/sqrt_ui.c b/mpf/sqrt_ui.c
new file mode 100644
index 000000000..987ef0776
--- /dev/null
+++ b/mpf/sqrt_ui.c
@@ -0,0 +1,65 @@
+/* mpf_sqrt_ui -- Compute the square root of an unsigned integer.
+
+Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/* This code is just correct if "unsigned char" has at least 8 bits. It
+ doesn't help to use CHAR_BIT from limits.h, as the real problem is
+ the static arrays. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpf_sqrt_ui (mpf_ptr r, unsigned long int u)
+#else
+mpf_sqrt_ui (r, u)
+ mpf_ptr r;
+ unsigned long int u;
+#endif
+{
+ mp_size_t rsize;
+ mp_ptr tp;
+ mp_size_t prec;
+ TMP_DECL (marker);
+
+ if (u == 0)
+ {
+ r->_mp_size = 0;
+ r->_mp_exp = 0;
+ return;
+ }
+
+ TMP_MARK (marker);
+
+ prec = r->_mp_prec;
+ rsize = 2 * prec + 1;
+
+ tp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB);
+
+ MPN_ZERO (tp, rsize - 1);
+ tp[rsize - 1] = u;
+
+ mpn_sqrtrem (r->_mp_d, NULL, tp, rsize);
+
+ r->_mp_size = prec + 1;
+ r->_mp_exp = 1;
+ TMP_FREE (marker);
+}
diff --git a/mpf/sub.c b/mpf/sub.c
new file mode 100644
index 000000000..b87198263
--- /dev/null
+++ b/mpf/sub.c
@@ -0,0 +1,402 @@
+/* mpf_sub -- Subtract two floats.
+
+Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpf_sub (mpf_ptr r, mpf_srcptr u, mpf_srcptr v)
+#else
+mpf_sub (r, u, v)
+ mpf_ptr r;
+ mpf_srcptr u;
+ mpf_srcptr v;
+#endif
+{
+ mp_srcptr up, vp;
+ mp_ptr rp, tp;
+ mp_size_t usize, vsize, rsize;
+ mp_size_t prec;
+ mp_exp_t exp;
+ mp_size_t ediff;
+ int negate;
+ TMP_DECL (marker);
+
+ usize = u->_mp_size;
+ vsize = v->_mp_size;
+
+ /* Handle special cases that don't work in generic code below. */
+ if (usize == 0)
+ {
+ mpf_neg (r, v);
+ return;
+ }
+ if (vsize == 0)
+ {
+ mpf_set (r, u);
+ return;
+ }
+
+ /* If signs of U and V are different, perform addition. */
+ if ((usize ^ vsize) < 0)
+ {
+ __mpf_struct v_negated;
+ v_negated._mp_size = -vsize;
+ v_negated._mp_exp = v->_mp_exp;
+ v_negated._mp_d = v->_mp_d;
+ mpf_add (r, u, &v_negated);
+ return;
+ }
+
+ TMP_MARK (marker);
+
+ /* Signs are now known to be the same. */
+ negate = usize < 0;
+
+ /* Make U be the operand with the largest exponent. */
+ if (u->_mp_exp < v->_mp_exp)
+ {
+ mpf_srcptr t;
+ t = u; u = v; v = t;
+ negate ^= 1;
+ usize = u->_mp_size;
+ vsize = v->_mp_size;
+ }
+
+ usize = ABS (usize);
+ vsize = ABS (vsize);
+ up = u->_mp_d;
+ vp = v->_mp_d;
+ rp = r->_mp_d;
+ prec = r->_mp_prec + 1;
+ exp = u->_mp_exp;
+ ediff = u->_mp_exp - v->_mp_exp;
+
+ /* If ediff is 0 or 1, we might have a situation where the operands are
+ extremely close. We need to scan the operands from the most significant
+ end ignore the initial parts that are equal. */
+ if (ediff <= 1)
+ {
+ if (ediff == 0)
+ {
+ /* Skip leading limbs in U and V that are equal. */
+ if (up[usize - 1] == vp[vsize - 1])
+ {
+ /* This loop normally exits immediately. Optimize for that. */
+ do
+ {
+ usize--;
+ vsize--;
+ exp--;
+
+ if (usize == 0)
+ {
+ rsize = vsize;
+ tp = (mp_ptr) vp;
+ negate ^= 1;
+ goto normalize;
+ }
+ if (vsize == 0)
+ {
+ rsize = usize;
+ tp = (mp_ptr) up;
+ goto normalize;
+ }
+ }
+ while (up[usize - 1] == vp[vsize - 1]);
+ }
+
+ if (up[usize - 1] < vp[vsize - 1])
+ {
+ /* For simplicity, swap U and V. Note that since the loop above
+ wouldn't have exited unless up[usize - 1] and vp[vsize - 1]
+ were non-equal, this if-statement catches all cases where U
+ is smaller than V. */
+ { mp_srcptr tp = up; up = vp; vp = tp; }
+ { mp_size_t tsize = usize; usize = vsize; vsize = tsize; }
+ negate ^= 1;
+ /* negating ediff not necessary since it is 0. */
+ }
+
+ /* Check for
+ x+1 00000000 ...
+ x ffffffff ... */
+ if (up[usize - 1] != vp[vsize - 1] + 1)
+ goto general_case;
+ usize--;
+ vsize--;
+ exp--;
+ }
+ else /* ediff == 1 */
+ {
+ /* Check for
+ 1 00000000 ...
+ 0 ffffffff ... */
+
+ if (up[usize - 1] != 1 || vp[vsize - 1] != ~(mp_limb_t) 0
+ || (usize >= 2 && up[usize - 2] != 0))
+ goto general_case;
+
+ usize--;
+ exp--;
+ }
+
+ /* Skip sequences of 00000000/ffffffff */
+ while (vsize != 0 && usize != 0 && up[usize - 1] == 0
+ && vp[vsize - 1] == ~(mp_limb_t) 0)
+ {
+ usize--;
+ vsize--;
+ exp--;
+ }
+
+ if (usize == 0)
+ {
+ while (vsize != 0 && vp[vsize - 1] == ~(mp_limb_t) 0)
+ {
+ vsize--;
+ exp--;
+ }
+ }
+
+ if (usize > prec - 1)
+ {
+ up += usize - (prec - 1);
+ usize = prec - 1;
+ }
+ if (vsize > prec - 1)
+ {
+ vp += vsize - (prec - 1);
+ vsize = prec - 1;
+ }
+
+ tp = (mp_ptr) TMP_ALLOC (prec * BYTES_PER_MP_LIMB);
+ {
+ mp_limb_t cy_limb;
+ if (vsize == 0)
+ {
+ mp_size_t size, i;
+ size = usize;
+ for (i = 0; i < size; i++)
+ tp[i] = up[i];
+ tp[size] = 1;
+ rsize = size + 1;
+ exp++;
+ goto normalize;
+ }
+ if (usize == 0)
+ {
+ mp_size_t size, i;
+ size = vsize;
+ for (i = 0; i < size; i++)
+ tp[i] = ~vp[i];
+ cy_limb = 1 - mpn_add_1 (tp, tp, vsize, (mp_limb_t) 1);
+ rsize = vsize;
+ if (cy_limb == 0)
+ {
+ tp[rsize] = 1;
+ rsize++;
+ exp++;
+ }
+ goto normalize;
+ }
+ if (usize >= vsize)
+ {
+ /* uuuu */
+ /* vv */
+ mp_size_t size;
+ size = usize - vsize;
+ MPN_COPY (tp, up, size);
+ cy_limb = mpn_sub_n (tp + size, up + size, vp, vsize);
+ rsize = usize;
+ }
+ else /* (usize < vsize) */
+ {
+ /* uuuu */
+ /* vvvvvvv */
+ mp_size_t size, i;
+ size = vsize - usize;
+ for (i = 0; i < size; i++)
+ tp[i] = ~vp[i];
+ cy_limb = mpn_sub_n (tp + size, up, vp + size, usize);
+ cy_limb+= mpn_sub_1 (tp + size, tp + size, usize, (mp_limb_t) 1);
+ cy_limb-= mpn_add_1 (tp, tp, vsize, (mp_limb_t) 1);
+ rsize = vsize;
+ }
+ if (cy_limb == 0)
+ {
+ tp[rsize] = 1;
+ rsize++;
+ exp++;
+ }
+ goto normalize;
+ }
+ }
+
+general_case:
+ /* If U extends beyond PREC, ignore the part that does. */
+ if (usize > prec)
+ {
+ up += usize - prec;
+ usize = prec;
+ }
+
+ /* If V extends beyond PREC, ignore the part that does.
+ Note that this may make vsize negative. */
+ if (vsize + ediff > prec)
+ {
+ vp += vsize + ediff - prec;
+ vsize = prec - ediff;
+ }
+
+ /* Allocate temp space for the result. Allocate
+ just vsize + ediff later??? */
+ tp = (mp_ptr) TMP_ALLOC (prec * BYTES_PER_MP_LIMB);
+
+ if (ediff >= prec)
+ {
+ /* V completely cancelled. */
+ if (tp != up)
+ MPN_COPY (rp, up, usize);
+ rsize = usize;
+ }
+ else
+ {
+ /* Locate the least significant non-zero limb in (the needed
+ parts of) U and V, to simplify the code below. */
+ for (;;)
+ {
+ if (vsize == 0)
+ {
+ MPN_COPY (rp, up, usize);
+ rsize = usize;
+ goto done;
+ }
+ if (vp[0] != 0)
+ break;
+ vp++, vsize--;
+ }
+ for (;;)
+ {
+ if (usize == 0)
+ {
+ MPN_COPY (rp, vp, vsize);
+ rsize = vsize;
+ negate ^= 1;
+ goto done;
+ }
+ if (up[0] != 0)
+ break;
+ up++, usize--;
+ }
+
+ /* uuuu | uuuu | uuuu | uuuu | uuuu */
+ /* vvvvvvv | vv | vvvvv | v | vv */
+
+ if (usize > ediff)
+ {
+ /* U and V partially overlaps. */
+ if (ediff == 0)
+ {
+ /* Have to compare the leading limbs of u and v
+ to determine whether to compute u - v or v - u. */
+ if (usize >= vsize)
+ {
+ /* uuuu */
+ /* vv */
+ mp_size_t size;
+ size = usize - vsize;
+ MPN_COPY (tp, up, size);
+ mpn_sub_n (tp + size, up + size, vp, vsize);
+ rsize = usize;
+ }
+ else /* (usize < vsize) */
+ {
+ /* uuuu */
+ /* vvvvvvv */
+ mp_size_t size, i;
+ size = vsize - usize;
+ tp[0] = -vp[0];
+ for (i = 1; i < size; i++)
+ tp[i] = ~vp[i];
+ mpn_sub_n (tp + size, up, vp + size, usize);
+ mpn_sub_1 (tp + size, tp + size, usize, (mp_limb_t) 1);
+ rsize = vsize;
+ }
+ }
+ else
+ {
+ if (vsize + ediff <= usize)
+ {
+ /* uuuu */
+ /* v */
+ mp_size_t size;
+ size = usize - ediff - vsize;
+ MPN_COPY (tp, up, size);
+ mpn_sub (tp + size, up + size, usize - size, vp, vsize);
+ rsize = usize;
+ }
+ else
+ {
+ /* uuuu */
+ /* vvvvv */
+ mp_size_t size, i;
+ size = vsize + ediff - usize;
+ tp[0] = -vp[0];
+ for (i = 1; i < size; i++)
+ tp[i] = ~vp[i];
+ mpn_sub (tp + size, up, usize, vp + size, usize - ediff);
+ mpn_sub_1 (tp + size, tp + size, usize, (mp_limb_t) 1);
+ rsize = vsize + ediff;
+ }
+ }
+ }
+ else
+ {
+ /* uuuu */
+ /* vv */
+ mp_size_t size, i;
+ size = vsize + ediff - usize;
+ tp[0] = -vp[0];
+ for (i = 1; i < vsize; i++)
+ tp[i] = ~vp[i];
+ for (i = vsize; i < size; i++)
+ tp[i] = ~(mp_limb_t) 0;
+ mpn_sub_1 (tp + size, up, usize, (mp_limb_t) 1);
+ rsize = size + usize;
+ }
+
+ normalize:
+ /* Full normalize. Optimize later. */
+ while (rsize != 0 && tp[rsize - 1] == 0)
+ {
+ rsize--;
+ exp--;
+ }
+ MPN_COPY (rp, tp, rsize);
+ }
+
+ done:
+ r->_mp_size = negate ? -rsize : rsize;
+ r->_mp_exp = exp;
+ TMP_FREE (marker);
+}
diff --git a/mpf/sub_ui.c b/mpf/sub_ui.c
new file mode 100644
index 000000000..780621378
--- /dev/null
+++ b/mpf/sub_ui.c
@@ -0,0 +1,49 @@
+/* mpf_sub_ui -- Subtract an unsigned integer from a float.
+
+Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpf_sub_ui (mpf_ptr sum, mpf_srcptr u, unsigned long int v)
+#else
+mpf_sub_ui (sum, u, v)
+ mpf_ptr sum;
+ mpf_srcptr u;
+ unsigned long int v;
+#endif
+{
+ __mpf_struct vv;
+ mp_limb_t vl;
+
+ if (v == 0)
+ {
+ mpf_set (sum, u);
+ return;
+ }
+
+ vl = v;
+ vv._mp_size = 1;
+ vv._mp_d = &vl;
+ vv._mp_exp = 1;
+ mpf_sub (sum, u, &vv);
+}
diff --git a/mpf/tests/Makefile.in b/mpf/tests/Makefile.in
new file mode 100644
index 000000000..62815eba3
--- /dev/null
+++ b/mpf/tests/Makefile.in
@@ -0,0 +1,58 @@
+# Makefile for mpf/tests for GNU MP
+
+srcdir = .
+
+CC = gcc
+
+TEST_LIBS = ../../libgmp.a
+INCLUDES = -I../../mpn -I$(srcdir)/../..
+CFLAGS = -g -O
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(XCFLAGS) $<
+
+TEST_SRCS = t-add.c t-sub.c t-conv.c t-sqrt.c ref.c
+TEST_OBJS = t-add.o t-sub.o t-conv.o t-sqrt.o
+TESTS = t-add t-sub t-conv t-sqrt
+
+check: st-add st-sub st-conv st-sqrt
+ @echo "The tests passed."
+
+st-add: t-add
+ ./t-add
+ touch $@
+st-sub: t-sub
+ ./t-sub
+ touch $@
+st-conv: t-conv
+ ./t-conv
+ touch $@
+st-sqrt: t-sqrt
+ ./t-sqrt
+ touch $@
+
+H = $(srcdir)/../../gmp.h $(srcdir)/../../gmp-impl.h \
+ $(srcdir)/../../urandom.h ../../mpn/gmp-mparam.h
+
+t-add: t-add.o ref.o $(TEST_LIBS)
+ $(CC) -o $@ $@.o ref.o $(TEST_LIBS) $(CFLAGS)
+t-sub: t-sub.o ref.o $(TEST_LIBS)
+ $(CC) -o $@ $@.o ref.o $(TEST_LIBS) $(CFLAGS)
+t-conv: t-conv.o ref.o $(TEST_LIBS)
+ $(CC) -o $@ $@.o ref.o $(TEST_LIBS) $(CFLAGS)
+t-sqrt: t-sqrt.o ref.o $(TEST_LIBS)
+ $(CC) -o $@ $@.o ref.o $(TEST_LIBS) $(CFLAGS)
+
+t-add.o: $(srcdir)/t-add.c
+t-sub.o: $(srcdir)/t-sub.c
+t-conv.o: $(srcdir)/t-conv.c
+t-sqrt.o: $(srcdir)/t-sqrt.c
+t-ref.o: $(srcdir)/t-ref.c
+
+clean mostlyclean:
+ rm -f *.o st-* $(TESTS)
+distclean maintainer-clean: clean
+ rm -f Makefile config.status
+
+Makefile: $(srcdir)/Makefile.in
+ $(SHELL) ./config.status
diff --git a/mpf/tests/configure.in b/mpf/tests/configure.in
new file mode 100644
index 000000000..319219cd7
--- /dev/null
+++ b/mpf/tests/configure.in
@@ -0,0 +1,11 @@
+# This file is a shell script that supplies the information necessary
+# to tailor a template configure script into the configure script
+# appropriate for this directory. For more information, check any
+# existing configure script.
+
+srctrigger=t-add.c
+srcname="gmp/mpf/tests"
+
+# per-host:
+
+# per-target:
diff --git a/mpf/tests/ref.c b/mpf/tests/ref.c
new file mode 100644
index 000000000..474c699ac
--- /dev/null
+++ b/mpf/tests/ref.c
@@ -0,0 +1,184 @@
+/* Reference floating point routines.
+
+Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void ref_mpf_add (mpf_t, const mpf_t, const mpf_t);
+void ref_mpf_sub (mpf_t, const mpf_t, const mpf_t);
+
+void
+ref_mpf_add (mpf_t w, const mpf_t u, const mpf_t v)
+{
+ mp_size_t hi, lo, size;
+ mp_ptr ut, vt, wt;
+ int neg;
+ mp_exp_t exp;
+ mp_limb_t cy;
+ TMP_DECL (mark);
+
+ TMP_MARK (mark);
+
+ if (SIZ (u) == 0)
+ {
+ size = ABSIZ (v);
+ wt = TMP_ALLOC (size * BYTES_PER_MP_LIMB);
+ MPN_COPY (wt, PTR (v), size);
+ exp = EXP (v);
+ neg = SIZ (v) < 0;
+ goto done;
+ }
+ if (SIZ (v) == 0)
+ {
+ size = ABSIZ (u);
+ wt = TMP_ALLOC (size * BYTES_PER_MP_LIMB);
+ MPN_COPY (wt, PTR (u), size);
+ exp = EXP (u);
+ neg = SIZ (u) < 0;
+ goto done;
+ }
+ if ((SIZ (u) ^ SIZ (v)) < 0)
+ {
+ mpf_t tmp;
+ SIZ (tmp) = -SIZ (v);
+ EXP (tmp) = EXP (v);
+ PTR (tmp) = PTR (v);
+ ref_mpf_sub (w, u, tmp);
+ return;
+ }
+ neg = SIZ (u) < 0;
+
+ /* Compute the significance of the hi and lo end of the result. */
+ hi = MAX (EXP (u), EXP (v));
+ lo = MIN (EXP (u) - ABSIZ (u), EXP (v) - ABSIZ (v));
+ size = hi - lo;
+ ut = TMP_ALLOC ((size + 1) * BYTES_PER_MP_LIMB);
+ vt = TMP_ALLOC ((size + 1) * BYTES_PER_MP_LIMB);
+ wt = TMP_ALLOC ((size + 1) * BYTES_PER_MP_LIMB);
+ MPN_ZERO (ut, size);
+ MPN_ZERO (vt, size);
+ {int off;
+ off = size + (EXP (u) - hi) - ABSIZ (u);
+ MPN_COPY (ut + off, PTR (u), ABSIZ (u));
+ off = size + (EXP (v) - hi) - ABSIZ (v);
+ MPN_COPY (vt + off, PTR (v), ABSIZ (v));
+ }
+
+ cy = mpn_add_n (wt, ut, vt, size);
+ wt[size] = cy;
+ size += cy;
+ exp = hi + cy;
+
+done:
+ if (size > PREC (w))
+ {
+ wt += size - PREC (w);
+ size = PREC (w);
+ }
+ MPN_COPY (PTR (w), wt, size);
+ SIZ (w) = neg == 0 ? size : -size;
+ EXP (w) = exp;
+ TMP_FREE (mark);
+}
+
+void
+ref_mpf_sub (mpf_t w, const mpf_t u, const mpf_t v)
+{
+ mp_size_t hi, lo, size;
+ mp_ptr ut, vt, wt;
+ int neg;
+ mp_exp_t exp;
+ TMP_DECL (mark);
+
+ TMP_MARK (mark);
+
+ if (SIZ (u) == 0)
+ {
+ size = ABSIZ (v);
+ wt = TMP_ALLOC (size * BYTES_PER_MP_LIMB);
+ MPN_COPY (wt, PTR (v), size);
+ exp = EXP (v);
+ neg = SIZ (v) > 0;
+ goto done;
+ }
+ if (SIZ (v) == 0)
+ {
+ size = ABSIZ (u);
+ wt = TMP_ALLOC (size * BYTES_PER_MP_LIMB);
+ MPN_COPY (wt, PTR (u), size);
+ exp = EXP (u);
+ neg = SIZ (u) < 0;
+ goto done;
+ }
+ if ((SIZ (u) ^ SIZ (v)) < 0)
+ {
+ mpf_t tmp;
+ SIZ (tmp) = -SIZ (v);
+ EXP (tmp) = EXP (v);
+ PTR (tmp) = PTR (v);
+ ref_mpf_add (w, u, tmp);
+ if (SIZ (u) < 0)
+ mpf_neg (w, w);
+ return;
+ }
+ neg = SIZ (u) < 0;
+
+ /* Compute the significance of the hi and lo end of the result. */
+ hi = MAX (EXP (u), EXP (v));
+ lo = MIN (EXP (u) - ABSIZ (u), EXP (v) - ABSIZ (v));
+ size = hi - lo;
+ ut = TMP_ALLOC ((size + 1) * BYTES_PER_MP_LIMB);
+ vt = TMP_ALLOC ((size + 1) * BYTES_PER_MP_LIMB);
+ wt = TMP_ALLOC ((size + 1) * BYTES_PER_MP_LIMB);
+ MPN_ZERO (ut, size);
+ MPN_ZERO (vt, size);
+ {int off;
+ off = size + (EXP (u) - hi) - ABSIZ (u);
+ MPN_COPY (ut + off, PTR (u), ABSIZ (u));
+ off = size + (EXP (v) - hi) - ABSIZ (v);
+ MPN_COPY (vt + off, PTR (v), ABSIZ (v));
+ }
+
+ if (mpn_cmp (ut, vt, size) >= 0)
+ mpn_sub_n (wt, ut, vt, size);
+ else
+ {
+ mpn_sub_n (wt, vt, ut, size);
+ neg ^= 1;
+ }
+ exp = hi;
+ while (size != 0 && wt[size - 1] == 0)
+ {
+ size--;
+ exp--;
+ }
+
+done:
+ if (size > PREC (w))
+ {
+ wt += size - PREC (w);
+ size = PREC (w);
+ }
+ MPN_COPY (PTR (w), wt, size);
+ SIZ (w) = neg == 0 ? size : -size;
+ EXP (w) = exp;
+ TMP_FREE (mark);
+}
diff --git a/mpf/tests/t-add.c b/mpf/tests/t-add.c
new file mode 100644
index 000000000..93cf81a25
--- /dev/null
+++ b/mpf/tests/t-add.c
@@ -0,0 +1,109 @@
+/* Test mpf_neg, mpf_sub.
+
+Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+#ifndef SIZE
+#define SIZE 16
+#endif
+
+void ref_mpf_add (mpf_t, const mpf_t, const mpf_t);
+void ref_mpf_sub (mpf_t, const mpf_t, const mpf_t);
+
+main (int argc, char **argv)
+{
+ mp_size_t size;
+ mp_exp_t exp;
+ int reps = 100000;
+ int i;
+ mpf_t u, v, w, wref;
+ mp_size_t bprec = 100;
+ mpf_t rerr, max_rerr, limit_rerr;
+
+ if (argc > 1)
+ {
+ reps = strtol (argv[1], 0, 0);
+ if (argc > 2)
+ bprec = strtol (argv[2], 0, 0);
+ }
+
+ mpf_set_default_prec (bprec);
+
+ mpf_init_set_ui (limit_rerr, 1);
+ mpf_div_2exp (limit_rerr, limit_rerr, bprec);
+#if VERBOSE
+ mpf_dump (limit_rerr);
+#endif
+ mpf_init (rerr);
+ mpf_init_set_ui (max_rerr, 0);
+
+ mpf_init (u);
+ mpf_init (v);
+ mpf_init (w);
+ mpf_init (wref);
+ for (i = 0; i < reps; i++)
+ {
+ size = urandom () % (2 * SIZE) - SIZE;
+ exp = urandom () % SIZE;
+ mpf_random2 (u, size, exp);
+
+ size = urandom () % (2 * SIZE) - SIZE;
+ exp = urandom () % SIZE;
+ mpf_random2 (v, size, exp);
+
+ mpf_add (w, u, v);
+ ref_mpf_add (wref, u, v);
+
+ mpf_reldiff (rerr, w, wref);
+ if (mpf_cmp (rerr, max_rerr) > 0)
+ {
+ mpf_set (max_rerr, rerr);
+#if VERBOSE
+ mpf_dump (max_rerr);
+#endif
+ if (mpf_cmp (rerr, limit_rerr) > 0)
+ {
+ printf ("ERROR after %d tests\n", i);
+ printf (" u = "); mpf_dump (u);
+ printf (" v = "); mpf_dump (v);
+ printf ("wref = "); mpf_dump (wref);
+ printf (" w = "); mpf_dump (w);
+ abort ();
+ }
+ }
+ }
+
+ exit (0);
+}
+
+oo (mpf_t x)
+{
+ mp_size_t i;
+ printf (" exp = %d\n", x->_mp_exp);
+ printf ("size = %d\n", x->_mp_size);
+ for (i = ABS (x->_mp_size) - 1; i >= 0; i--)
+ printf ("%08X ", x->_mp_d[i]);
+ printf ("\n");
+ mpf_dump (x);
+}
diff --git a/mpf/tests/t-conv.c b/mpf/tests/t-conv.c
new file mode 100644
index 000000000..4467f0653
--- /dev/null
+++ b/mpf/tests/t-conv.c
@@ -0,0 +1,117 @@
+/* Test mpf_get_str and mpf_set_str.
+
+Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+#ifndef SIZE
+#define SIZE 10
+#endif
+
+#ifndef EXPO
+#define EXPO 20
+#endif
+
+main (int argc, char **argv)
+{
+ mpf_t x, y;
+ int reps = 20000;
+ int i;
+ mp_size_t bprec = 100;
+ mpf_t d, rerr, max_rerr, limit_rerr;
+ char *str;
+ long bexp;
+ long size, exp;
+ int base;
+ char buf[SIZE * BITS_PER_MP_LIMB + 5];
+
+ if (argc > 1)
+ {
+ reps = strtol (argv[1], 0, 0);
+ if (argc > 2)
+ bprec = strtol (argv[2], 0, 0);
+ }
+
+ mpf_set_default_prec (bprec);
+
+ mpf_init_set_ui (limit_rerr, 1);
+ mpf_div_2exp (limit_rerr, limit_rerr, bprec);
+#if VERBOSE
+ mpf_dump (limit_rerr);
+#endif
+ mpf_init (rerr);
+ mpf_init_set_ui (max_rerr, 0);
+
+ mpf_init (x);
+ mpf_init (y);
+ mpf_init (d);
+
+ for (i = 0; i < reps; i++)
+ {
+ size = urandom () % (2 * SIZE) - SIZE;
+ exp = urandom () % EXPO;
+ mpf_random2 (x, size, exp);
+
+ base = urandom () % 35 + 2;
+
+ str = mpf_get_str (0, &bexp, base, 0, x);
+
+ if (str[0] == '-')
+ sprintf (buf, "-0.%s@%ld", str + 1, bexp);
+ else
+ sprintf (buf, "0.%s@%ld", str, bexp);
+
+ mpf_set_str (y, buf, -base);
+ free (str);
+
+ mpf_reldiff (rerr, x, y);
+ if (mpf_cmp (rerr, max_rerr) > 0)
+ {
+ mpf_set (max_rerr, rerr);
+#if VERBOSE
+ mpf_dump (max_rerr);
+#endif
+ if (mpf_cmp (rerr, limit_rerr) > 0)
+ {
+ printf ("ERROR after %d tests\n", i);
+ printf ("base = %d\n", base);
+ printf (" x = "); mpf_dump (x);
+ printf (" y = "); mpf_dump (y);
+ abort ();
+ }
+ }
+ }
+
+ exit (0);
+}
+
+oo (mpf_t x)
+{
+ int i;
+ printf (" exp = %d\n", x->_mp_exp);
+ printf ("size = %d\n", x->_mp_size);
+ for (i = ABS (x->_mp_size) - 1; i >= 0; i--)
+ printf ("%08X ", x->_mp_d[i]);
+ printf ("\n");
+ mpf_dump (x);
+}
diff --git a/mpf/tests/t-sqrt.c b/mpf/tests/t-sqrt.c
new file mode 100644
index 000000000..af13836ec
--- /dev/null
+++ b/mpf/tests/t-sqrt.c
@@ -0,0 +1,100 @@
+/* Test mpf_sqrt, mpf_neg, mpf_sub.
+
+Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+#ifndef SIZE
+#define SIZE 16
+#endif
+
+main (int argc, char **argv)
+{
+ mp_size_t size;
+ mp_exp_t exp;
+ int reps = 100000;
+ int i;
+ mpf_t x, y, y2;
+ mp_size_t bprec = 100;
+ mpf_t rerr, max_rerr, limit_rerr;
+
+ if (argc > 1)
+ {
+ reps = strtol (argv[1], 0, 0);
+ if (argc > 2)
+ bprec = strtol (argv[2], 0, 0);
+ }
+
+ mpf_set_default_prec (bprec);
+
+ mpf_init_set_ui (limit_rerr, 1);
+ mpf_div_2exp (limit_rerr, limit_rerr, bprec);
+#if VERBOSE
+ mpf_dump (limit_rerr);
+#endif
+ mpf_init (rerr);
+ mpf_init_set_ui (max_rerr, 0);
+
+ mpf_init (x);
+ mpf_init (y);
+ mpf_init (y2);
+ for (i = 0; i < reps; i++)
+ {
+ size = urandom () % SIZE;
+ exp = urandom () % SIZE;
+ mpf_random2 (x, size, exp);
+
+ mpf_sqrt (y, x);
+ mpf_mul (y2, y, y);
+
+ mpf_reldiff (rerr, x, y2);
+ if (mpf_cmp (rerr, max_rerr) > 0)
+ {
+ mpf_set (max_rerr, rerr);
+#if VERBOSE
+ mpf_dump (max_rerr);
+#endif
+ if (mpf_cmp (rerr, limit_rerr) > 0)
+ {
+ printf ("ERROR after %d tests\n", i);
+ printf (" x = "); mpf_dump (x);
+ printf (" y = "); mpf_dump (y);
+ printf (" y2 = "); mpf_dump (y2);
+ abort ();
+ }
+ }
+ }
+
+ exit (0);
+}
+
+oo (mpf_t x)
+{
+ mp_size_t i;
+ printf (" exp = %d\n", x->_mp_exp);
+ printf ("size = %d\n", x->_mp_size);
+ for (i = ABS (x->_mp_size) - 1; i >= 0; i--)
+ printf ("%08X ", x->_mp_d[i]);
+ printf ("\n");
+ mpf_dump (x);
+}
diff --git a/mpf/tests/t-sub.c b/mpf/tests/t-sub.c
new file mode 100644
index 000000000..6ff9bcb86
--- /dev/null
+++ b/mpf/tests/t-sub.c
@@ -0,0 +1,114 @@
+/* Test mpf_neg, mpf_sub.
+
+Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+#ifndef SIZE
+#define SIZE 16
+#endif
+
+void ref_mpf_add (mpf_t, const mpf_t, const mpf_t);
+void ref_mpf_sub (mpf_t, const mpf_t, const mpf_t);
+
+main (int argc, char **argv)
+{
+ mp_size_t size;
+ mp_exp_t exp;
+ int reps = 1000000;
+ int i;
+ mpf_t u, v, w, wref;
+ mp_size_t bprec = 100;
+ mpf_t rerr, max_rerr, limit_rerr;
+
+ if (argc > 1)
+ {
+ reps = strtol (argv[1], 0, 0);
+ if (argc > 2)
+ bprec = strtol (argv[2], 0, 0);
+ }
+
+ mpf_set_default_prec (bprec);
+
+ mpf_init_set_ui (limit_rerr, 1);
+ mpf_div_2exp (limit_rerr, limit_rerr, bprec);
+#if VERBOSE
+ mpf_dump (limit_rerr);
+#endif
+ mpf_init (rerr);
+ mpf_init_set_ui (max_rerr, 0);
+
+ mpf_init (u);
+ mpf_init (v);
+ mpf_init (w);
+ mpf_init (wref);
+ for (i = 0; i < reps; i++)
+ {
+ size = urandom () % (2 * SIZE) - SIZE;
+ exp = urandom () % SIZE;
+ mpf_random2 (u, size, exp);
+
+ size = urandom () % (2 * SIZE) - SIZE;
+ exp = urandom () % SIZE;
+ mpf_random2 (v, size, exp);
+
+ if ((urandom () & 1) != 0)
+ mpf_add_ui (u, v, 1);
+ else if ((urandom () & 1) != 0)
+ mpf_sub_ui (u, v, 1);
+
+ mpf_sub (w, u, v);
+ ref_mpf_sub (wref, u, v);
+
+ mpf_reldiff (rerr, w, wref);
+ if (mpf_cmp (rerr, max_rerr) > 0)
+ {
+ mpf_set (max_rerr, rerr);
+#if VERBOSE
+ mpf_dump (max_rerr);
+#endif
+ if (mpf_cmp (rerr, limit_rerr) > 0)
+ {
+ printf ("ERROR after %d tests\n", i);
+ printf (" u = "); mpf_dump (u);
+ printf (" v = "); mpf_dump (v);
+ printf ("wref = "); mpf_dump (wref);
+ printf (" w = "); mpf_dump (w);
+ abort ();
+ }
+ }
+ }
+
+ exit (0);
+}
+
+oo (mpf_t x)
+{
+ mp_size_t i;
+ printf (" exp = %d\n", x->_mp_exp);
+ printf ("size = %d\n", x->_mp_size);
+ for (i = ABS (x->_mp_size) - 1; i >= 0; i--)
+ printf ("%08X ", x->_mp_d[i]);
+ printf ("\n");
+ mpf_dump (x);
+}
diff --git a/mpf/ui_div.c b/mpf/ui_div.c
new file mode 100644
index 000000000..5ec4d1c9e
--- /dev/null
+++ b/mpf/ui_div.c
@@ -0,0 +1,116 @@
+/* mpf_ui_div -- Divide an unsigned integer with a float.
+
+Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+void
+#if __STDC__
+mpf_ui_div (mpf_ptr r, unsigned long int dividend, mpf_srcptr v)
+#else
+mpf_ui_div (r, dividend, v)
+ mpf_ptr r;
+ unsigned long int dividend;
+ mpf_srcptr v;
+#endif
+{
+ mp_ptr up, vp;
+ mp_ptr rp;
+ mp_size_t usize, vsize, rsize;
+ mp_size_t abs_vsize;
+ mp_size_t prec;
+ unsigned normalization_steps;
+ mp_limb_t qlimb;
+ mp_exp_t rexp;
+ TMP_DECL (marker);
+
+ TMP_MARK (marker);
+ prec = r->_mp_prec;
+ rp = r->_mp_d;
+
+ vp = v->_mp_d;
+ rexp = 1 - v->_mp_exp;
+ vsize = v->_mp_size;
+ abs_vsize = ABS (vsize);
+
+ usize = abs_vsize + prec;
+ up = (mp_ptr) TMP_ALLOC ((usize + 1) * BYTES_PER_MP_LIMB);
+ MPN_ZERO (up, usize);
+
+ count_leading_zeros (normalization_steps, vp[abs_vsize - 1]);
+
+ /* Normalize the denominator and the numerator. */
+ if (normalization_steps != 0)
+ {
+ mp_ptr tp;
+ mp_limb_t dividend_high, dividend_low;
+
+ /* Shift up the divisor setting the most significant bit of
+ the most significant limb. Use temporary storage not to clobber
+ the original contents of the divisor. */
+ tp = (mp_ptr) TMP_ALLOC (abs_vsize * BYTES_PER_MP_LIMB);
+ mpn_lshift (tp, vp, abs_vsize, normalization_steps);
+ vp = tp;
+
+ /* Shift up the dividend, possibly introducing a new most
+ significant word. */
+ dividend_high = (mp_limb_t) dividend >> (BITS_PER_MP_LIMB - normalization_steps);
+ dividend_low = (mp_limb_t) dividend << normalization_steps;
+
+ if (dividend_high != 0)
+ {
+ up[usize] = dividend_high;
+ up[usize - 1] = dividend_low;
+ rexp++;
+ }
+ else
+ {
+ usize--;
+ up[usize] = dividend_low;
+ }
+ }
+ else
+ {
+ /* The divisor is already normalized, as required.
+ Copy it to temporary space if it overlaps with the quotient. */
+ if (vp == rp)
+ {
+ vp = (mp_ptr) TMP_ALLOC (abs_vsize * BYTES_PER_MP_LIMB);
+ MPN_COPY (vp, rp, abs_vsize);
+ }
+
+ usize--;
+ up[usize] = dividend;
+ }
+
+ qlimb = mpn_divmod (rp, up, usize + 1, vp, abs_vsize);
+ rsize = usize + 1 - abs_vsize;
+ if (qlimb)
+ {
+ rp[rsize] = qlimb;
+ rsize++;
+ rexp++;
+ }
+ r->_mp_size = vsize >= 0 ? rsize : -rsize;
+ r->_mp_exp = rexp;
+ TMP_FREE (marker);
+}
diff --git a/mpf/ui_sub.c b/mpf/ui_sub.c
new file mode 100644
index 000000000..acb9210a6
--- /dev/null
+++ b/mpf/ui_sub.c
@@ -0,0 +1,334 @@
+/* mpf_ui_sub -- Subtract a float from an unsigned long int.
+
+Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpf_ui_sub (mpf_ptr r, unsigned long int u, mpf_srcptr v)
+#else
+mpf_ui_sub (r, u, v)
+ mpf_ptr r;
+ unsigned long int u;
+ mpf_srcptr v;
+#endif
+{
+ mp_srcptr up, vp;
+ mp_ptr rp, tp;
+ mp_size_t usize, vsize, rsize;
+ mp_size_t prec;
+ mp_exp_t uexp;
+ mp_size_t ediff;
+ int negate;
+ mp_limb_t ulimb;
+ TMP_DECL (marker);
+
+ vsize = v->_mp_size;
+
+ /* Handle special cases that don't work in generic code below. */
+ if (u == 0)
+ {
+ mpf_neg (r, v);
+ return;
+ }
+ if (vsize == 0)
+ {
+ mpf_set_ui (r, u);
+ return;
+ }
+
+ /* If signs of U and V are different, perform addition. */
+ if (vsize < 0)
+ {
+ __mpf_struct v_negated;
+ v_negated._mp_size = -vsize;
+ v_negated._mp_exp = v->_mp_exp;
+ v_negated._mp_d = v->_mp_d;
+ mpf_add_ui (r, &v_negated, u);
+ return;
+ }
+
+ TMP_MARK (marker);
+
+ /* Signs are now known to be the same. */
+
+ ulimb = u;
+ /* Make U be the operand with the largest exponent. */
+ if (1 < v->_mp_exp)
+ {
+ negate = 1;
+ usize = ABS (vsize);
+ vsize = 1;
+ up = v->_mp_d;
+ vp = &ulimb;
+ rp = r->_mp_d;
+ prec = r->_mp_prec + 1;
+ uexp = v->_mp_exp;
+ ediff = uexp - 1;
+ }
+ else
+ {
+ negate = 0;
+ usize = 1;
+ vsize = ABS (vsize);
+ up = &ulimb;
+ vp = v->_mp_d;
+ rp = r->_mp_d;
+ prec = r->_mp_prec;
+ uexp = 1;
+ ediff = 1 - v->_mp_exp;
+ }
+
+ /* Ignore leading limbs in U and V that are equal. Doing
+ this helps increase the precision of the result. */
+ if (ediff == 0)
+ {
+ /* This loop normally exits immediately. Optimize for that. */
+ for (;;)
+ {
+ usize--;
+ vsize--;
+ if (up[usize] != vp[vsize])
+ break;
+ uexp--;
+ if (usize == 0)
+ goto Lu0;
+ if (vsize == 0)
+ goto Lv0;
+ }
+ usize++;
+ vsize++;
+ /* Note that either operand (but not both operands) might now have
+ leading zero limbs. It matters only that U is unnormalized if
+ vsize is now zero, and vice versa. And it is only in that case
+ that we have to adjust uexp. */
+ if (vsize == 0)
+ Lv0:
+ while (usize != 0 && up[usize - 1] == 0)
+ usize--, uexp--;
+ if (usize == 0)
+ Lu0:
+ while (vsize != 0 && vp[vsize - 1] == 0)
+ vsize--, uexp--;
+ }
+
+ /* If U extends beyond PREC, ignore the part that does. */
+ if (usize > prec)
+ {
+ up += usize - prec;
+ usize = prec;
+ }
+
+ /* If V extends beyond PREC, ignore the part that does.
+ Note that this may make vsize negative. */
+ if (vsize + ediff > prec)
+ {
+ vp += vsize + ediff - prec;
+ vsize = prec - ediff;
+ }
+
+ /* Allocate temp space for the result. Allocate
+ just vsize + ediff later??? */
+ tp = (mp_ptr) TMP_ALLOC (prec * BYTES_PER_MP_LIMB);
+
+ if (ediff >= prec)
+ {
+ /* V completely cancelled. */
+ if (tp != up)
+ MPN_COPY (rp, up, usize);
+ rsize = usize;
+ }
+ else
+ {
+ /* Locate the least significant non-zero limb in (the needed
+ parts of) U and V, to simplify the code below. */
+ for (;;)
+ {
+ if (vsize == 0)
+ {
+ MPN_COPY (rp, up, usize);
+ rsize = usize;
+ goto done;
+ }
+ if (vp[0] != 0)
+ break;
+ vp++, vsize--;
+ }
+ for (;;)
+ {
+ if (usize == 0)
+ {
+ MPN_COPY (rp, vp, vsize);
+ rsize = vsize;
+ negate ^= 1;
+ goto done;
+ }
+ if (up[0] != 0)
+ break;
+ up++, usize--;
+ }
+
+ /* uuuu | uuuu | uuuu | uuuu | uuuu */
+ /* vvvvvvv | vv | vvvvv | v | vv */
+
+ if (usize > ediff)
+ {
+ /* U and V partially overlaps. */
+ if (ediff == 0)
+ {
+ /* Have to compare the leading limbs of u and v
+ to determine whether to compute u - v or v - u. */
+ if (usize > vsize)
+ {
+ /* uuuu */
+ /* vv */
+ int cmp;
+ cmp = mpn_cmp (up + usize - vsize, vp, vsize);
+ if (cmp >= 0)
+ {
+ mp_size_t size;
+ size = usize - vsize;
+ MPN_COPY (tp, up, size);
+ mpn_sub_n (tp + size, up + size, vp, vsize);
+ rsize = usize;
+ }
+ else
+ {
+ /* vv */ /* Swap U and V. */
+ /* uuuu */
+ mp_size_t size, i;
+ size = usize - vsize;
+ tp[0] = -up[0];
+ for (i = 1; i < size; i++)
+ tp[i] = ~up[i];
+ mpn_sub_n (tp + size, vp, up + size, vsize);
+ mpn_sub_1 (tp + size, tp + size, vsize, (mp_limb_t) 1);
+ negate ^= 1;
+ rsize = usize;
+ }
+ }
+ else if (usize < vsize)
+ {
+ /* uuuu */
+ /* vvvvvvv */
+ int cmp;
+ cmp = mpn_cmp (up, vp + vsize - usize, usize);
+ if (cmp > 0)
+ {
+ mp_size_t size, i;
+ size = vsize - usize;
+ tp[0] = -vp[0];
+ for (i = 1; i < size; i++)
+ tp[i] = ~vp[i];
+ mpn_sub_n (tp + size, up, vp + size, usize);
+ mpn_sub_1 (tp + size, tp + size, usize, (mp_limb_t) 1);
+ rsize = vsize;
+ }
+ else
+ {
+ /* vvvvvvv */ /* Swap U and V. */
+ /* uuuu */
+ /* This is the only place we can get 0.0. */
+ mp_size_t size;
+ size = vsize - usize;
+ MPN_COPY (tp, vp, size);
+ mpn_sub_n (tp + size, vp + size, up, usize);
+ negate ^= 1;
+ rsize = vsize;
+ }
+ }
+ else
+ {
+ /* uuuu */
+ /* vvvv */
+ int cmp;
+ cmp = mpn_cmp (up, vp + vsize - usize, usize);
+ if (cmp > 0)
+ {
+ mpn_sub_n (tp, up, vp, usize);
+ rsize = usize;
+ }
+ else
+ {
+ mpn_sub_n (tp, vp, up, usize);
+ negate ^= 1;
+ rsize = usize;
+ /* can give zero */
+ }
+ }
+ }
+ else
+ {
+ if (vsize + ediff <= usize)
+ {
+ /* uuuu */
+ /* v */
+ mp_size_t size;
+ size = usize - ediff - vsize;
+ MPN_COPY (tp, up, size);
+ mpn_sub (tp + size, up + size, usize - size, vp, vsize);
+ rsize = usize;
+ }
+ else
+ {
+ /* uuuu */
+ /* vvvvv */
+ mp_size_t size, i;
+ size = vsize + ediff - usize;
+ tp[0] = -vp[0];
+ for (i = 1; i < size; i++)
+ tp[i] = ~vp[i];
+ mpn_sub (tp + size, up, usize, vp + size, usize - ediff);
+ mpn_sub_1 (tp + size, tp + size, usize, (mp_limb_t) 1);
+ rsize = vsize + ediff;
+ }
+ }
+ }
+ else
+ {
+ /* uuuu */
+ /* vv */
+ mp_size_t size, i;
+ size = vsize + ediff - usize;
+ tp[0] = -vp[0];
+ for (i = 1; i < vsize; i++)
+ tp[i] = ~vp[i];
+ for (i = vsize; i < size; i++)
+ tp[i] = ~(mp_limb_t) 0;
+ mpn_sub_1 (tp + size, up, usize, (mp_limb_t) 1);
+ rsize = size + usize;
+ }
+
+ /* Full normalize. Optimize later. */
+ while (rsize != 0 && tp[rsize - 1] == 0)
+ {
+ rsize--;
+ uexp--;
+ }
+ MPN_COPY (rp, tp, rsize);
+ }
+
+ done:
+ r->_mp_size = negate ? -rsize : rsize;
+ r->_mp_exp = uexp;
+ TMP_FREE (marker);
+}
diff --git a/mpn/Makefile.in b/mpn/Makefile.in
new file mode 100644
index 000000000..5028d14b1
--- /dev/null
+++ b/mpn/Makefile.in
@@ -0,0 +1,92 @@
+# Makefile for GNU MP/mpn functions
+# Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+# This file is part of the GNU MP Library.
+
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+
+# The GNU MP Library 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 Library General Public
+# License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+
+srcdir = .
+
+MPN_OBJECTS = This gets filled in by configure.in.
+MPN_LINKS = This gets filled in by configure.in.
+CC = gcc
+CPP = $(CC) -E
+CFLAGS = -g -O
+INCLUDES = -I. -I.. -I$(srcdir) -I$(srcdir)/..
+AR = ar
+AR_FLAGS = rc
+SFLAGS=
+
+#### host and target specific makefile fragments come in here.
+###
+
+libmpn.a: Makefile.in mp_bases.o $(MPN_OBJECTS)
+ rm -f $@
+ $(AR) $(AR_FLAGS) $@ mp_bases.o $(MPN_OBJECTS)
+
+.SUFFIXES: .c .s .S
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(XCFLAGS) $<
+
+.s.o:
+ $(CC) -c $(CFLAGS) $<
+
+.S.o:
+ $(CPP) $(SFLAGS) $(INCLUDES) $(CFLAGS) $< | grep -v '^#' >tmp-$*.s
+ $(CC) -c tmp-$*.s -o $@
+ rm -f tmp-$*.s
+
+clean mostlyclean:
+ rm -f *.o tmp-* libmpn.a
+ #-cd tests; $(MAKE) $@
+distclean maintainer-clean: clean
+ rm -f asm-syntax.h Makefile config.status $(MPN_LINKS)
+ -cd tests; $(MAKE) $@
+
+Makefile: $(srcdir)/Makefile.in
+ $(SHELL) ./config.status
+
+
+# Maybe configure could add dependencies here..?
+
+H = $(srcdir)/../gmp.h $(srcdir)/../gmp-impl.h gmp-mparam.h
+L = $(srcdir)/../longlong.h
+
+mp_bases.o: $(srcdir)/mp_bases.c $(H)
+bdivmod.o: bdivmod.c $(H) $(L)
+cmp.o: cmp.c $(H)
+divmod_1.o: divmod_1.c $(H) $(L)
+divrem.o: divrem.c $(H) $(L)
+divrem_1.o: divrem_1.c $(H) $(L)
+dump.o: dump.c $(H)
+gcd.o: gcd.c $(H) $(L)
+gcd_1.o: gcd_1.c $(H) $(L)
+gcdext.o: gcdext.c $(H) $(L)
+get_str.o: get_str.c $(H) $(L)
+hamdist.o: hamdist.c $(H)
+inlines.o: inlines.c $(srcdir)/../gmp.h
+mod_1.o: mod_1.c $(H) $(L)
+mul.o: mul.c $(H)
+mul_n.o: mul_n.c $(H)
+perfsqr.o: perfsqr.c $(H) $(L)
+popcount.o: popcount.c $(H)
+pre_mod_1.o: pre_mod_1.c $(H) $(L)
+random2.o: random2.c $(H)
+scan0.o: scan0.c $(H) $(L)
+scan1.o: scan1.c $(H) $(L)
+set_str.o: set_str.c $(H)
+sqrtrem.o: sqrtrem.c $(H) $(L)
diff --git a/mpn/README b/mpn/README
new file mode 100644
index 000000000..3da559e50
--- /dev/null
+++ b/mpn/README
@@ -0,0 +1,15 @@
+This directory contains all code for the mpn layer of GMP.
+
+Most subdirectories contain machine-dependent code, written in assembly or
+C. The `generic' subdirectory contains default code, used when there is no
+machine-dependent replacement for a particular machine.
+
+There is one subdirectory for each architecture. Note that e.g., 32-bit
+sparc and 64-bit sparc cannot share any code, and are therefore considered
+completely different architecture.
+
+A particular machine will only use code from one such subdirectory, and the
+`generic' subdirectory. The architecture-specific subdirectory contains a
+hierachy of directories for various architecture variants and
+implementations; the top-most level contains code that runs correctly on all
+variants.
diff --git a/mpn/a29k/add_n.s b/mpn/a29k/add_n.s
new file mode 100644
index 000000000..74c20e3f7
--- /dev/null
+++ b/mpn/a29k/add_n.s
@@ -0,0 +1,120 @@
+; 29000 __mpn_add -- Add two limb vectors of the same length > 0 and store
+; sum in a third limb vector.
+
+; Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+; This file is part of the GNU MP Library.
+
+; The GNU MP Library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Library General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or (at your
+; option) any later version.
+
+; The GNU MP Library 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 Library General Public
+; License for more details.
+
+; You should have received a copy of the GNU Library General Public License
+; along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+; MA 02111-1307, USA.
+
+
+; INPUT PARAMETERS
+; res_ptr lr2
+; s1_ptr lr3
+; s2_ptr lr4
+; size lr5
+
+; We use the loadm/storem instructions and operate on chunks of 8
+; limbs/per iteration, until less than 8 limbs remain.
+
+; The 29k has no addition or subtraction instructions that doesn't
+; affect carry, so we need to save and restore that as soon as we
+; adjust the pointers. gr116 is used for this purpose. Note that
+; gr116==0 means that carry should be set.
+
+ .sect .lit,lit
+ .text
+ .align 4
+ .global ___mpn_add_n
+ .word 0x60000
+___mpn_add_n:
+ srl gr117,lr5,3
+ sub gr118,gr117,1
+ jmpt gr118,Ltail
+ constn gr116,-1 ; init cy reg
+ sub gr117,gr117,2 ; count for jmpfdec
+
+; Main loop working 8 limbs/iteration.
+Loop: mtsrim cr,(8-1)
+ loadm 0,0,gr96,lr3
+ add lr3,lr3,32
+ mtsrim cr,(8-1)
+ loadm 0,0,gr104,lr4
+ add lr4,lr4,32
+
+ subr gr116,gr116,0 ; restore carry
+ addc gr96,gr96,gr104
+ addc gr97,gr97,gr105
+ addc gr98,gr98,gr106
+ addc gr99,gr99,gr107
+ addc gr100,gr100,gr108
+ addc gr101,gr101,gr109
+ addc gr102,gr102,gr110
+ addc gr103,gr103,gr111
+ subc gr116,gr116,gr116 ; gr116 = not(cy)
+
+ mtsrim cr,(8-1)
+ storem 0,0,gr96,lr2
+ jmpfdec gr117,Loop
+ add lr2,lr2,32
+
+; Code for the last up-to-7 limbs.
+; This code might look very strange, but it's hard to write it
+; differently without major slowdown.
+
+ and lr5,lr5,(8-1)
+Ltail: sub gr118,lr5,1 ; count for CR
+ jmpt gr118,Lend
+ sub gr117,lr5,2 ; count for jmpfdec
+
+ mtsr cr,gr118
+ loadm 0,0,gr96,lr3
+ mtsr cr,gr118
+ loadm 0,0,gr104,lr4
+
+ subr gr116,gr116,0 ; restore carry
+
+ jmpfdec gr117,L1
+ addc gr96,gr96,gr104
+ jmp Lstore
+ mtsr cr,gr118
+L1: jmpfdec gr117,L2
+ addc gr97,gr97,gr105
+ jmp Lstore
+ mtsr cr,gr118
+L2: jmpfdec gr117,L3
+ addc gr98,gr98,gr106
+ jmp Lstore
+ mtsr cr,gr118
+L3: jmpfdec gr117,L4
+ addc gr99,gr99,gr107
+ jmp Lstore
+ mtsr cr,gr118
+L4: jmpfdec gr117,L5
+ addc gr100,gr100,gr108
+ jmp Lstore
+ mtsr cr,gr118
+L5: jmpfdec gr117,L6
+ addc gr101,gr101,gr109
+ jmp Lstore
+ mtsr cr,gr118
+L6: addc gr102,gr102,gr110
+
+Lstore: storem 0,0,gr96,lr2
+ subc gr116,gr116,gr116 ; gr116 = not(cy)
+
+Lend: jmpi lr0
+ add gr96,gr116,1
diff --git a/mpn/a29k/addmul_1.s b/mpn/a29k/addmul_1.s
new file mode 100644
index 000000000..8c0ec96ce
--- /dev/null
+++ b/mpn/a29k/addmul_1.s
@@ -0,0 +1,113 @@
+; 29000 __mpn_addmul_1 -- Multiply a limb vector with a single limb and
+; add the product to a second limb vector.
+
+; Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+; This file is part of the GNU MP Library.
+
+; The GNU MP Library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Library General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or (at your
+; option) any later version.
+
+; The GNU MP Library 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 Library General Public
+; License for more details.
+
+; You should have received a copy of the GNU Library General Public License
+; along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+; MA 02111-1307, USA.
+
+
+; INPUT PARAMETERS
+; res_ptr lr2
+; s1_ptr lr3
+; size lr4
+; s2_limb lr5
+
+ .cputype 29050
+ .sect .lit,lit
+ .text
+ .align 4
+ .global ___mpn_addmul_1
+ .word 0x60000
+___mpn_addmul_1:
+ sub lr4,lr4,8
+ jmpt lr4,Ltail
+ const gr120,0 ; init cylimb reg
+
+ srl gr117,lr4,3 ; divide by 8
+ sub gr117,gr117,1 ; count for jmpfdec
+
+Loop: mtsrim cr,(8-1)
+ loadm 0,0,gr96,lr3
+ add lr3,lr3,32
+
+ multiplu gr104,gr96,lr5
+ multmu gr96,gr96,lr5
+ multiplu gr105,gr97,lr5
+ multmu gr97,gr97,lr5
+ multiplu gr106,gr98,lr5
+ multmu gr98,gr98,lr5
+ multiplu gr107,gr99,lr5
+ multmu gr99,gr99,lr5
+ multiplu gr108,gr100,lr5
+ multmu gr100,gr100,lr5
+ multiplu gr109,gr101,lr5
+ multmu gr101,gr101,lr5
+ multiplu gr110,gr102,lr5
+ multmu gr102,gr102,lr5
+ multiplu gr111,gr103,lr5
+ multmu gr103,gr103,lr5
+
+ add gr104,gr104,gr120
+ addc gr105,gr105,gr96
+ addc gr106,gr106,gr97
+ addc gr107,gr107,gr98
+ addc gr108,gr108,gr99
+ addc gr109,gr109,gr100
+ addc gr110,gr110,gr101
+ addc gr111,gr111,gr102
+ addc gr120,gr103,0
+
+ mtsrim cr,(8-1)
+ loadm 0,0,gr96,lr2
+
+ add gr104,gr96,gr104
+ addc gr105,gr97,gr105
+ addc gr106,gr98,gr106
+ addc gr107,gr99,gr107
+ addc gr108,gr100,gr108
+ addc gr109,gr101,gr109
+ addc gr110,gr102,gr110
+ addc gr111,gr103,gr111
+ addc gr120,gr120,0
+
+ mtsrim cr,(8-1)
+ storem 0,0,gr104,lr2
+ jmpfdec gr117,Loop
+ add lr2,lr2,32
+
+Ltail: and lr4,lr4,(8-1)
+ sub gr118,lr4,1 ; count for CR
+ jmpt gr118,Lend
+ sub lr4,lr4,2
+ sub lr2,lr2,4 ; offset res_ptr by one limb
+
+Loop2: load 0,0,gr116,lr3
+ add lr3,lr3,4
+ multiplu gr117,gr116,lr5
+ multmu gr118,gr116,lr5
+ add lr2,lr2,4
+ load 0,0,gr119,lr2
+ add gr117,gr117,gr120
+ addc gr118,gr118,0
+ add gr117,gr117,gr119
+ store 0,0,gr117,lr2
+ jmpfdec lr4,Loop2
+ addc gr120,gr118,0
+
+Lend: jmpi lr0
+ or gr96,gr120,0 ; copy
diff --git a/mpn/a29k/lshift.s b/mpn/a29k/lshift.s
new file mode 100644
index 000000000..7554e2cbb
--- /dev/null
+++ b/mpn/a29k/lshift.s
@@ -0,0 +1,93 @@
+; 29000 __mpn_lshift --
+
+; Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+; This file is part of the GNU MP Library.
+
+; The GNU MP Library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Library General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or (at your
+; option) any later version.
+
+; The GNU MP Library 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 Library General Public
+; License for more details.
+
+; You should have received a copy of the GNU Library General Public License
+; along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+; MA 02111-1307, USA.
+
+
+; INPUT PARAMETERS
+; res_ptr lr2
+; s1_ptr lr3
+; s2_ptr lr4
+; size lr5
+
+; We use the loadm/storem instructions and operate on chunks of 8
+; limbs/per iteration, until less than 8 limbs remain.
+
+ .sect .lit,lit
+ .text
+ .align 4
+ .global ___mpn_lshift
+ .word 0x60000
+___mpn_lshift:
+ sll gr116,lr4,2
+ add lr3,gr116,lr3
+ add lr2,gr116,lr2
+ sub lr3,lr3,4
+ load 0,0,gr119,lr3
+
+ subr gr116,lr5,32
+ srl gr96,gr119,gr116 ; return value
+ sub lr4,lr4,1 ; actual loop count is SIZE - 1
+
+ srl gr117,lr4,3 ; chuck count = (actual count) / 8
+ cpeq gr118,gr117,0
+ jmpt gr118,Ltail
+ mtsr fc,lr5
+
+ sub gr117,gr117,2 ; count for jmpfdec
+
+; Main loop working 8 limbs/iteration.
+Loop: sub lr3,lr3,32
+ mtsrim cr,(8-1)
+ loadm 0,0,gr100,lr3
+
+ extract gr109,gr119,gr107
+ extract gr108,gr107,gr106
+ extract gr107,gr106,gr105
+ extract gr106,gr105,gr104
+ extract gr105,gr104,gr103
+ extract gr104,gr103,gr102
+ extract gr103,gr102,gr101
+ extract gr102,gr101,gr100
+
+ sub lr2,lr2,32
+ mtsrim cr,(8-1)
+ storem 0,0,gr102,lr2
+ jmpfdec gr117,Loop
+ or gr119,gr100,0
+
+; Code for the last up-to-7 limbs.
+
+ and lr4,lr4,(8-1)
+Ltail: cpeq gr118,lr4,0
+ jmpt gr118,Lend
+ sub lr4,lr4,2 ; count for jmpfdec
+
+Loop2: sub lr3,lr3,4
+ load 0,0,gr116,lr3
+ extract gr117,gr119,gr116
+ sub lr2,lr2,4
+ store 0,0,gr117,lr2
+ jmpfdec lr4,Loop2
+ or gr119,gr116,0
+
+Lend: extract gr117,gr119,0
+ sub lr2,lr2,4
+ jmpi lr0
+ store 0,0,gr117,lr2
diff --git a/mpn/a29k/mul_1.s b/mpn/a29k/mul_1.s
new file mode 100644
index 000000000..5d120f48e
--- /dev/null
+++ b/mpn/a29k/mul_1.s
@@ -0,0 +1,97 @@
+; 29000 __mpn_mul_1 -- Multiply a limb vector with a single limb and
+; store the product in a second limb vector.
+
+; Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+; This file is part of the GNU MP Library.
+
+; The GNU MP Library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Library General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or (at your
+; option) any later version.
+
+; The GNU MP Library 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 Library General Public
+; License for more details.
+
+; You should have received a copy of the GNU Library General Public License
+; along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+; MA 02111-1307, USA.
+
+
+; INPUT PARAMETERS
+; res_ptr lr2
+; s1_ptr lr3
+; size lr4
+; s2_limb lr5
+
+ .cputype 29050
+ .sect .lit,lit
+ .text
+ .align 4
+ .global ___mpn_mul_1
+ .word 0x60000
+___mpn_mul_1:
+ sub lr4,lr4,8
+ jmpt lr4,Ltail
+ const gr120,0 ; init cylimb reg
+
+ srl gr117,lr4,3 ; divide by 8
+ sub gr117,gr117,1 ; count for jmpfdec
+
+Loop: mtsrim cr,(8-1)
+ loadm 0,0,gr96,lr3
+ add lr3,lr3,32
+
+ multiplu gr104,gr96,lr5
+ multmu gr96,gr96,lr5
+ multiplu gr105,gr97,lr5
+ multmu gr97,gr97,lr5
+ multiplu gr106,gr98,lr5
+ multmu gr98,gr98,lr5
+ multiplu gr107,gr99,lr5
+ multmu gr99,gr99,lr5
+ multiplu gr108,gr100,lr5
+ multmu gr100,gr100,lr5
+ multiplu gr109,gr101,lr5
+ multmu gr101,gr101,lr5
+ multiplu gr110,gr102,lr5
+ multmu gr102,gr102,lr5
+ multiplu gr111,gr103,lr5
+ multmu gr103,gr103,lr5
+
+ add gr104,gr104,gr120
+ addc gr105,gr105,gr96
+ addc gr106,gr106,gr97
+ addc gr107,gr107,gr98
+ addc gr108,gr108,gr99
+ addc gr109,gr109,gr100
+ addc gr110,gr110,gr101
+ addc gr111,gr111,gr102
+ addc gr120,gr103,0
+
+ mtsrim cr,(8-1)
+ storem 0,0,gr104,lr2
+ jmpfdec gr117,Loop
+ add lr2,lr2,32
+
+Ltail: and lr4,lr4,(8-1)
+ sub gr118,lr4,1 ; count for CR
+ jmpt gr118,Lend
+ sub lr4,lr4,2
+ sub lr2,lr2,4 ; offset res_ptr by one limb
+
+Loop2: load 0,0,gr116,lr3
+ add lr3,lr3,4
+ multiplu gr117,gr116,lr5
+ multmu gr118,gr116,lr5
+ add lr2,lr2,4
+ add gr117,gr117,gr120
+ store 0,0,gr117,lr2
+ jmpfdec lr4,Loop2
+ addc gr120,gr118,0
+
+Lend: jmpi lr0
+ or gr96,gr120,0 ; copy
diff --git a/mpn/a29k/rshift.s b/mpn/a29k/rshift.s
new file mode 100644
index 000000000..fe53b71e2
--- /dev/null
+++ b/mpn/a29k/rshift.s
@@ -0,0 +1,89 @@
+; 29000 __mpn_rshift --
+
+; Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+; This file is part of the GNU MP Library.
+
+; The GNU MP Library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Library General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or (at your
+; option) any later version.
+
+; The GNU MP Library 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 Library General Public
+; License for more details.
+
+; You should have received a copy of the GNU Library General Public License
+; along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+; MA 02111-1307, USA.
+
+
+; INPUT PARAMETERS
+; res_ptr lr2
+; s1_ptr lr3
+; s2_ptr lr4
+; size lr5
+
+; We use the loadm/storem instructions and operate on chunks of 8
+; limbs/per iteration, until less than 8 limbs remain.
+
+ .sect .lit,lit
+ .text
+ .align 4
+ .global ___mpn_rshift
+ .word 0x60000
+___mpn_rshift:
+ load 0,0,gr119,lr3
+ add lr3,lr3,4
+
+ subr gr116,lr5,32
+ sll gr96,gr119,gr116 ; return value
+ sub lr4,lr4,1 ; actual loop count is SIZE - 1
+
+ srl gr117,lr4,3 ; chuck count = (actual count) / 8
+ cpeq gr118,gr117,0
+ jmpt gr118,Ltail
+ mtsr fc,gr116
+
+ sub gr117,gr117,2 ; count for jmpfdec
+
+; Main loop working 8 limbs/iteration.
+Loop: mtsrim cr,(8-1)
+ loadm 0,0,gr100,lr3
+ add lr3,lr3,32
+
+ extract gr98,gr100,gr119
+ extract gr99,gr101,gr100
+ extract gr100,gr102,gr101
+ extract gr101,gr103,gr102
+ extract gr102,gr104,gr103
+ extract gr103,gr105,gr104
+ extract gr104,gr106,gr105
+ extract gr105,gr107,gr106
+
+ mtsrim cr,(8-1)
+ storem 0,0,gr98,lr2
+ add lr2,lr2,32
+ jmpfdec gr117,Loop
+ or gr119,gr107,0
+
+; Code for the last up-to-7 limbs.
+
+ and lr4,lr4,(8-1)
+Ltail: cpeq gr118,lr4,0
+ jmpt gr118,Lend
+ sub lr4,lr4,2 ; count for jmpfdec
+
+Loop2: load 0,0,gr100,lr3
+ add lr3,lr3,4
+ extract gr117,gr100,gr119
+ store 0,0,gr117,lr2
+ add lr2,lr2,4
+ jmpfdec lr4,Loop2
+ or gr119,gr100,0
+
+Lend: srl gr117,gr119,lr5
+ jmpi lr0
+ store 0,0,gr117,lr2
diff --git a/mpn/a29k/sub_n.s b/mpn/a29k/sub_n.s
new file mode 100644
index 000000000..3c8d61065
--- /dev/null
+++ b/mpn/a29k/sub_n.s
@@ -0,0 +1,120 @@
+; 29000 __mpn_sub -- Subtract two limb vectors of the same length > 0 and
+; store difference in a third limb vector.
+
+; Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+; This file is part of the GNU MP Library.
+
+; The GNU MP Library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Library General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or (at your
+; option) any later version.
+
+; The GNU MP Library 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 Library General Public
+; License for more details.
+
+; You should have received a copy of the GNU Library General Public License
+; along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+; MA 02111-1307, USA.
+
+
+; INPUT PARAMETERS
+; res_ptr lr2
+; s1_ptr lr3
+; s2_ptr lr4
+; size lr5
+
+; We use the loadm/storem instructions and operate on chunks of 8
+; limbs/per iteration, until less than 8 limbs remain.
+
+; The 29k has no addition or subtraction instructions that doesn't
+; affect carry, so we need to save and restore that as soon as we
+; adjust the pointers. gr116 is used for this purpose. Note that
+; gr116==0 means that carry should be set.
+
+ .sect .lit,lit
+ .text
+ .align 4
+ .global ___mpn_sub_n
+ .word 0x60000
+___mpn_sub_n:
+ srl gr117,lr5,3
+ sub gr118,gr117,1
+ jmpt gr118,Ltail
+ constn gr116,-1 ; init cy reg
+ sub gr117,gr117,2 ; count for jmpfdec
+
+; Main loop working 8 limbs/iteration.
+Loop: mtsrim cr,(8-1)
+ loadm 0,0,gr96,lr3
+ add lr3,lr3,32
+ mtsrim cr,(8-1)
+ loadm 0,0,gr104,lr4
+ add lr4,lr4,32
+
+ subr gr116,gr116,0 ; restore carry
+ subc gr96,gr96,gr104
+ subc gr97,gr97,gr105
+ subc gr98,gr98,gr106
+ subc gr99,gr99,gr107
+ subc gr100,gr100,gr108
+ subc gr101,gr101,gr109
+ subc gr102,gr102,gr110
+ subc gr103,gr103,gr111
+ subc gr116,gr116,gr116 ; gr116 = not(cy)
+
+ mtsrim cr,(8-1)
+ storem 0,0,gr96,lr2
+ jmpfdec gr117,Loop
+ add lr2,lr2,32
+
+; Code for the last up-to-7 limbs.
+; This code might look very strange, but it's hard to write it
+; differently without major slowdown.
+
+ and lr5,lr5,(8-1)
+Ltail: sub gr118,lr5,1 ; count for CR
+ jmpt gr118,Lend
+ sub gr117,lr5,2 ; count for jmpfdec
+
+ mtsr cr,gr118
+ loadm 0,0,gr96,lr3
+ mtsr cr,gr118
+ loadm 0,0,gr104,lr4
+
+ subr gr116,gr116,0 ; restore carry
+
+ jmpfdec gr117,L1
+ subc gr96,gr96,gr104
+ jmp Lstore
+ mtsr cr,gr118
+L1: jmpfdec gr117,L2
+ subc gr97,gr97,gr105
+ jmp Lstore
+ mtsr cr,gr118
+L2: jmpfdec gr117,L3
+ subc gr98,gr98,gr106
+ jmp Lstore
+ mtsr cr,gr118
+L3: jmpfdec gr117,L4
+ subc gr99,gr99,gr107
+ jmp Lstore
+ mtsr cr,gr118
+L4: jmpfdec gr117,L5
+ subc gr100,gr100,gr108
+ jmp Lstore
+ mtsr cr,gr118
+L5: jmpfdec gr117,L6
+ subc gr101,gr101,gr109
+ jmp Lstore
+ mtsr cr,gr118
+L6: subc gr102,gr102,gr110
+
+Lstore: storem 0,0,gr96,lr2
+ subc gr116,gr116,gr116 ; gr116 = not(cy)
+
+Lend: jmpi lr0
+ add gr96,gr116,1
diff --git a/mpn/a29k/submul_1.s b/mpn/a29k/submul_1.s
new file mode 100644
index 000000000..ca2ef72a9
--- /dev/null
+++ b/mpn/a29k/submul_1.s
@@ -0,0 +1,116 @@
+; 29000 __mpn_submul_1 -- Multiply a limb vector with a single limb and
+; subtract the product from a second limb vector.
+
+; Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+; This file is part of the GNU MP Library.
+
+; The GNU MP Library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Library General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or (at your
+; option) any later version.
+
+; The GNU MP Library 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 Library General Public
+; License for more details.
+
+; You should have received a copy of the GNU Library General Public License
+; along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+; MA 02111-1307, USA.
+
+
+; INPUT PARAMETERS
+; res_ptr lr2
+; s1_ptr lr3
+; size lr4
+; s2_limb lr5
+
+ .cputype 29050
+ .sect .lit,lit
+ .text
+ .align 4
+ .global ___mpn_submul_1
+ .word 0x60000
+___mpn_submul_1:
+ sub lr4,lr4,8
+ jmpt lr4,Ltail
+ const gr120,0 ; init cylimb reg
+
+ srl gr117,lr4,3 ; divide by 8
+ sub gr117,gr117,1 ; count for jmpfdec
+
+Loop: mtsrim cr,(8-1)
+ loadm 0,0,gr96,lr3
+ add lr3,lr3,32
+
+ multiplu gr104,gr96,lr5
+ multmu gr96,gr96,lr5
+ multiplu gr105,gr97,lr5
+ multmu gr97,gr97,lr5
+ multiplu gr106,gr98,lr5
+ multmu gr98,gr98,lr5
+ multiplu gr107,gr99,lr5
+ multmu gr99,gr99,lr5
+ multiplu gr108,gr100,lr5
+ multmu gr100,gr100,lr5
+ multiplu gr109,gr101,lr5
+ multmu gr101,gr101,lr5
+ multiplu gr110,gr102,lr5
+ multmu gr102,gr102,lr5
+ multiplu gr111,gr103,lr5
+ multmu gr103,gr103,lr5
+
+ add gr104,gr104,gr120
+ addc gr105,gr105,gr96
+ addc gr106,gr106,gr97
+ addc gr107,gr107,gr98
+ addc gr108,gr108,gr99
+ addc gr109,gr109,gr100
+ addc gr110,gr110,gr101
+ addc gr111,gr111,gr102
+ addc gr120,gr103,0
+
+ mtsrim cr,(8-1)
+ loadm 0,0,gr96,lr2
+
+ sub gr96,gr96,gr104
+ subc gr97,gr97,gr105
+ subc gr98,gr98,gr106
+ subc gr99,gr99,gr107
+ subc gr100,gr100,gr108
+ subc gr101,gr101,gr109
+ subc gr102,gr102,gr110
+ subc gr103,gr103,gr111
+
+ add gr104,gr103,gr111 ; invert carry from previus sub
+ addc gr120,gr120,0
+
+ mtsrim cr,(8-1)
+ storem 0,0,gr96,lr2
+ jmpfdec gr117,Loop
+ add lr2,lr2,32
+
+Ltail: and lr4,lr4,(8-1)
+ sub gr118,lr4,1 ; count for CR
+ jmpt gr118,Lend
+ sub lr4,lr4,2
+ sub lr2,lr2,4 ; offset res_ptr by one limb
+
+Loop2: load 0,0,gr116,lr3
+ add lr3,lr3,4
+ multiplu gr117,gr116,lr5
+ multmu gr118,gr116,lr5
+ add lr2,lr2,4
+ load 0,0,gr119,lr2
+ add gr117,gr117,gr120
+ addc gr118,gr118,0
+ sub gr119,gr119,gr117
+ add gr104,gr119,gr117 ; invert carry from previus sub
+ store 0,0,gr119,lr2
+ jmpfdec lr4,Loop2
+ addc gr120,gr118,0
+
+Lend: jmpi lr0
+ or gr96,gr120,0 ; copy
diff --git a/mpn/alpha/README b/mpn/alpha/README
new file mode 100644
index 000000000..55c0a2917
--- /dev/null
+++ b/mpn/alpha/README
@@ -0,0 +1,53 @@
+This directory contains mpn functions optimized for DEC Alpha processors.
+
+RELEVANT OPTIMIZATION ISSUES
+
+EV4
+
+1. This chip has very limited store bandwidth. The on-chip L1 cache is
+write-through, and a cache line is transfered from the store buffer to the
+off-chip L2 in as much 15 cycles on most systems. This delay hurts
+mpn_add_n, mpn_sub_n, mpn_lshift, and mpn_rshift.
+
+2. Pairing is possible between memory instructions and integer arithmetic
+instructions.
+
+3. mulq and umulh is documented to have a latency of 23 cycles, but 2 of
+these cycles are pipelined. Thus, multiply instructions can be issued at a
+rate of one each 21nd cycle.
+
+EV5
+
+1. The memory bandwidth of this chip seems excellent, both for loads and
+stores. Even when the working set is larger than the on-chip L1 and L2
+caches, the perfromance remain almost unaffected.
+
+2. mulq has a measured latency of 13 cycles and an issue rate of 1 each 8th
+cycle. umulh has a measured latency of 15 cycles and an issue rate of 1
+each 10th cycle. But the exact timing is somewhat confusing.
+
+3. mpn_add_n. With 4-fold unrolling, we need 37 instructions, whereof 12
+ are memory operations. This will take at least
+ ceil(37/2) [dual issue] + 1 [taken branch] = 20 cycles
+ We have 12 memory cycles, plus 4 after-store conflict cycles, or 16 data
+ cache cycles, which should be completely hidden in the 20 issue cycles.
+ The computation is inherently serial, with these dependencies:
+ addq
+ / \
+ addq cmpult
+ | |
+ cmpult |
+ \ /
+ or
+ I.e., there is a 4 cycle path for each limb, making 16 cycles the absolute
+ minimum. We could replace the `or' with a cmoveq/cmovne, which would save
+ a cycle on EV5, but that might waste a cycle on EV4. Also, cmov takes 2
+ cycles.
+ addq
+ / \
+ addq cmpult
+ | \
+ cmpult -> cmovne
+
+STATUS
+
diff --git a/mpn/alpha/add_n.s b/mpn/alpha/add_n.s
new file mode 100644
index 000000000..426556e39
--- /dev/null
+++ b/mpn/alpha/add_n.s
@@ -0,0 +1,120 @@
+ # Alpha __mpn_add_n -- Add two limb vectors of the same length > 0 and
+ # store sum in a third limb vector.
+
+ # Copyright (C) 1995 Free Software Foundation, Inc.
+
+ # This file is part of the GNU MP Library.
+
+ # The GNU MP Library is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU Library General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or (at your
+ # option) any later version.
+
+ # The GNU MP Library 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 Library General Public
+ # License for more details.
+
+ # You should have received a copy of the GNU Library General Public License
+ # along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+ # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ # MA 02111-1307, USA.
+
+
+ # INPUT PARAMETERS
+ # res_ptr $16
+ # s1_ptr $17
+ # s2_ptr $18
+ # size $19
+
+ .set noreorder
+ .set noat
+.text
+ .align 3
+ .globl __mpn_add_n
+ .ent __mpn_add_n
+__mpn_add_n:
+ .frame $30,0,$26,0
+
+ ldq $3,0($17)
+ ldq $4,0($18)
+
+ subq $19,1,$19
+ and $19,4-1,$2 # number of limbs in first loop
+ bis $31,$31,$0
+ beq $2,.L0 # if multiple of 4 limbs, skip first loop
+
+ subq $19,$2,$19
+
+.Loop0: subq $2,1,$2
+ ldq $5,8($17)
+ addq $4,$0,$4
+ ldq $6,8($18)
+ cmpult $4,$0,$1
+ addq $3,$4,$4
+ cmpult $4,$3,$0
+ stq $4,0($16)
+ or $0,$1,$0
+
+ addq $17,8,$17
+ addq $18,8,$18
+ bis $5,$5,$3
+ bis $6,$6,$4
+ addq $16,8,$16
+ bne $2,.Loop0
+
+.L0: beq $19,.Lend
+
+ .align 3
+.Loop: subq $19,4,$19
+
+ ldq $5,8($17)
+ addq $4,$0,$4
+ ldq $6,8($18)
+ cmpult $4,$0,$1
+ addq $3,$4,$4
+ cmpult $4,$3,$0
+ stq $4,0($16)
+ or $0,$1,$0
+
+ ldq $3,16($17)
+ addq $6,$0,$6
+ ldq $4,16($18)
+ cmpult $6,$0,$1
+ addq $5,$6,$6
+ cmpult $6,$5,$0
+ stq $6,8($16)
+ or $0,$1,$0
+
+ ldq $5,24($17)
+ addq $4,$0,$4
+ ldq $6,24($18)
+ cmpult $4,$0,$1
+ addq $3,$4,$4
+ cmpult $4,$3,$0
+ stq $4,16($16)
+ or $0,$1,$0
+
+ ldq $3,32($17)
+ addq $6,$0,$6
+ ldq $4,32($18)
+ cmpult $6,$0,$1
+ addq $5,$6,$6
+ cmpult $6,$5,$0
+ stq $6,24($16)
+ or $0,$1,$0
+
+ addq $17,32,$17
+ addq $18,32,$18
+ addq $16,32,$16
+ bne $19,.Loop
+
+.Lend: addq $4,$0,$4
+ cmpult $4,$0,$1
+ addq $3,$4,$4
+ cmpult $4,$3,$0
+ stq $4,0($16)
+ or $0,$1,$0
+ ret $31,($26),1
+
+ .end __mpn_add_n
diff --git a/mpn/alpha/addmul_1.s b/mpn/alpha/addmul_1.s
new file mode 100644
index 000000000..048238ae9
--- /dev/null
+++ b/mpn/alpha/addmul_1.s
@@ -0,0 +1,92 @@
+ # Alpha 21064 __mpn_addmul_1 -- Multiply a limb vector with a limb and add
+ # the result to a second limb vector.
+
+ # Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
+
+ # This file is part of the GNU MP Library.
+
+ # The GNU MP Library is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU Library General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or (at your
+ # option) any later version.
+
+ # The GNU MP Library 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 Library General Public
+ # License for more details.
+
+ # You should have received a copy of the GNU Library General Public License
+ # along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+ # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ # MA 02111-1307, USA.
+
+
+ # INPUT PARAMETERS
+ # res_ptr r16
+ # s1_ptr r17
+ # size r18
+ # s2_limb r19
+
+ # This code runs at 42 cycles/limb on EV4 and 18 cycles/limb on EV5.
+
+ .set noreorder
+ .set noat
+.text
+ .align 3
+ .globl __mpn_addmul_1
+ .ent __mpn_addmul_1 2
+__mpn_addmul_1:
+ .frame $30,0,$26
+
+ ldq $2,0($17) # $2 = s1_limb
+ addq $17,8,$17 # s1_ptr++
+ subq $18,1,$18 # size--
+ mulq $2,$19,$3 # $3 = prod_low
+ ldq $5,0($16) # $5 = *res_ptr
+ umulh $2,$19,$0 # $0 = prod_high
+ beq $18,.Lend1 # jump if size was == 1
+ ldq $2,0($17) # $2 = s1_limb
+ addq $17,8,$17 # s1_ptr++
+ subq $18,1,$18 # size--
+ addq $5,$3,$3
+ cmpult $3,$5,$4
+ stq $3,0($16)
+ addq $16,8,$16 # res_ptr++
+ beq $18,.Lend2 # jump if size was == 2
+
+ .align 3
+.Loop: mulq $2,$19,$3 # $3 = prod_low
+ ldq $5,0($16) # $5 = *res_ptr
+ addq $4,$0,$0 # cy_limb = cy_limb + 'cy'
+ subq $18,1,$18 # size--
+ umulh $2,$19,$4 # $4 = cy_limb
+ ldq $2,0($17) # $2 = s1_limb
+ addq $17,8,$17 # s1_ptr++
+ addq $3,$0,$3 # $3 = cy_limb + prod_low
+ cmpult $3,$0,$0 # $0 = carry from (cy_limb + prod_low)
+ addq $5,$3,$3
+ cmpult $3,$5,$5
+ stq $3,0($16)
+ addq $16,8,$16 # res_ptr++
+ addq $5,$0,$0 # combine carries
+ bne $18,.Loop
+
+.Lend2: mulq $2,$19,$3 # $3 = prod_low
+ ldq $5,0($16) # $5 = *res_ptr
+ addq $4,$0,$0 # cy_limb = cy_limb + 'cy'
+ umulh $2,$19,$4 # $4 = cy_limb
+ addq $3,$0,$3 # $3 = cy_limb + prod_low
+ cmpult $3,$0,$0 # $0 = carry from (cy_limb + prod_low)
+ addq $5,$3,$3
+ cmpult $3,$5,$5
+ stq $3,0($16)
+ addq $5,$0,$0 # combine carries
+ addq $4,$0,$0 # cy_limb = prod_high + cy
+ ret $31,($26),1
+.Lend1: addq $5,$3,$3
+ cmpult $3,$5,$5
+ stq $3,0($16)
+ addq $0,$5,$0
+ ret $31,($26),1
+
+ .end __mpn_addmul_1
diff --git a/mpn/alpha/ev5/add_n.s b/mpn/alpha/ev5/add_n.s
new file mode 100644
index 000000000..1251a1fb7
--- /dev/null
+++ b/mpn/alpha/ev5/add_n.s
@@ -0,0 +1,148 @@
+ # Alpha __mpn_add_n -- Add two limb vectors of the same length > 0 and
+ # store sum in a third limb vector.
+
+ # Copyright (C) 1995 Free Software Foundation, Inc.
+
+ # This file is part of the GNU MP Library.
+
+ # The GNU MP Library is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU Library General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or (at your
+ # option) any later version.
+
+ # The GNU MP Library 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 Library General Public
+ # License for more details.
+
+ # You should have received a copy of the GNU Library General Public License
+ # along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+ # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ # MA 02111-1307, USA.
+
+
+ # INPUT PARAMETERS
+ # res_ptr $16
+ # s1_ptr $17
+ # s2_ptr $18
+ # size $19
+
+ .set noreorder
+ .set noat
+.text
+ .align 3
+ .globl __mpn_add_n
+ .ent __mpn_add_n
+__mpn_add_n:
+ .frame $30,0,$26,0
+
+ or $31,$31,$25 # clear cy
+ subq $19,4,$19 # decr loop cnt
+ blt $19,.Lend2 # if less than 4 limbs, goto 2nd loop
+ # Start software pipeline for 1st loop
+ ldq $0,0($18)
+ ldq $1,8($18)
+ ldq $4,0($17)
+ ldq $5,8($17)
+ addq $17,32,$17 # update s1_ptr
+ ldq $2,16($18)
+ addq $0,$4,$20 # 1st main add
+ ldq $3,24($18)
+ subq $19,4,$19 # decr loop cnt
+ ldq $6,-16($17)
+ cmpult $20,$0,$25 # compute cy from last add
+ ldq $7,-8($17)
+ addq $1,$25,$28 # cy add
+ addq $18,32,$18 # update s2_ptr
+ addq $5,$28,$21 # 2nd main add
+ cmpult $28,$25,$8 # compute cy from last add
+ blt $19,.Lend1 # if less than 4 limbs remain, jump
+ # 1st loop handles groups of 4 limbs in a software pipeline
+ .align 4
+.Loop: cmpult $21,$28,$25 # compute cy from last add
+ ldq $0,0($18)
+ or $8,$25,$25 # combine cy from the two adds
+ ldq $1,8($18)
+ addq $2,$25,$28 # cy add
+ ldq $4,0($17)
+ addq $28,$6,$22 # 3rd main add
+ ldq $5,8($17)
+ cmpult $28,$25,$8 # compute cy from last add
+ cmpult $22,$28,$25 # compute cy from last add
+ stq $20,0($16)
+ or $8,$25,$25 # combine cy from the two adds
+ stq $21,8($16)
+ addq $3,$25,$28 # cy add
+ addq $28,$7,$23 # 4th main add
+ cmpult $28,$25,$8 # compute cy from last add
+ cmpult $23,$28,$25 # compute cy from last add
+ addq $17,32,$17 # update s1_ptr
+ or $8,$25,$25 # combine cy from the two adds
+ addq $16,32,$16 # update res_ptr
+ addq $0,$25,$28 # cy add
+ ldq $2,16($18)
+ addq $4,$28,$20 # 1st main add
+ ldq $3,24($18)
+ cmpult $28,$25,$8 # compute cy from last add
+ ldq $6,-16($17)
+ cmpult $20,$28,$25 # compute cy from last add
+ ldq $7,-8($17)
+ or $8,$25,$25 # combine cy from the two adds
+ subq $19,4,$19 # decr loop cnt
+ stq $22,-16($16)
+ addq $1,$25,$28 # cy add
+ stq $23,-8($16)
+ addq $5,$28,$21 # 2nd main add
+ addq $18,32,$18 # update s2_ptr
+ cmpult $28,$25,$8 # compute cy from last add
+ bge $19,.Loop
+ # Finish software pipeline for 1st loop
+.Lend1: cmpult $21,$28,$25 # compute cy from last add
+ or $8,$25,$25 # combine cy from the two adds
+ addq $2,$25,$28 # cy add
+ addq $28,$6,$22 # 3rd main add
+ cmpult $28,$25,$8 # compute cy from last add
+ cmpult $22,$28,$25 # compute cy from last add
+ stq $20,0($16)
+ or $8,$25,$25 # combine cy from the two adds
+ stq $21,8($16)
+ addq $3,$25,$28 # cy add
+ addq $28,$7,$23 # 4th main add
+ cmpult $28,$25,$8 # compute cy from last add
+ cmpult $23,$28,$25 # compute cy from last add
+ or $8,$25,$25 # combine cy from the two adds
+ addq $16,32,$16 # update res_ptr
+ stq $22,-16($16)
+ stq $23,-8($16)
+.Lend2: addq $19,4,$19 # restore loop cnt
+ beq $19,.Lret
+ # Start software pipeline for 2nd loop
+ ldq $0,0($18)
+ ldq $4,0($17)
+ subq $19,1,$19
+ beq $19,.Lend0
+ # 2nd loop handles remaining 1-3 limbs
+ .align 4
+.Loop0: addq $0,$25,$28 # cy add
+ ldq $0,8($18)
+ addq $4,$28,$20 # main add
+ ldq $4,8($17)
+ addq $18,8,$18
+ cmpult $28,$25,$8 # compute cy from last add
+ addq $17,8,$17
+ stq $20,0($16)
+ cmpult $20,$28,$25 # compute cy from last add
+ subq $19,1,$19 # decr loop cnt
+ or $8,$25,$25 # combine cy from the two adds
+ addq $16,8,$16
+ bne $19,.Loop0
+.Lend0: addq $0,$25,$28 # cy add
+ addq $4,$28,$20 # main add
+ cmpult $28,$25,$8 # compute cy from last add
+ cmpult $20,$28,$25 # compute cy from last add
+ stq $20,0($16)
+ or $8,$25,$25 # combine cy from the two adds
+
+.Lret: or $25,$31,$0 # return cy
+ ret $31,($26),1
+ .end __mpn_add_n
diff --git a/mpn/alpha/ev5/lshift.s b/mpn/alpha/ev5/lshift.s
new file mode 100644
index 000000000..ced55b720
--- /dev/null
+++ b/mpn/alpha/ev5/lshift.s
@@ -0,0 +1,174 @@
+ # Alpha EV5 __mpn_lshift --
+
+ # Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+
+ # This file is part of the GNU MP Library.
+
+ # The GNU MP Library is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU Library General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or (at your
+ # option) any later version.
+
+ # The GNU MP Library 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 Library General Public
+ # License for more details.
+
+ # You should have received a copy of the GNU Library General Public License
+ # along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+ # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ # MA 02111-1307, USA.
+
+
+ # INPUT PARAMETERS
+ # res_ptr r16
+ # s1_ptr r17
+ # size r18
+ # cnt r19
+
+ # This code runs at 3.25 cycles/limb on the EV5.
+
+ .set noreorder
+ .set noat
+.text
+ .align 3
+ .globl __mpn_lshift
+ .ent __mpn_lshift
+__mpn_lshift:
+ .frame $30,0,$26,0
+
+ s8addq $18,$17,$17 # make r17 point at end of s1
+ ldq $4,-8($17) # load first limb
+ subq $31,$19,$20
+ s8addq $18,$16,$16 # make r16 point at end of RES
+ subq $18,1,$18
+ and $18,4-1,$28 # number of limbs in first loop
+ srl $4,$20,$0 # compute function result
+
+ beq $28,.L0
+ subq $18,$28,$18
+
+ .align 3
+.Loop0: ldq $3,-16($17)
+ subq $16,8,$16
+ sll $4,$19,$5
+ subq $17,8,$17
+ subq $28,1,$28
+ srl $3,$20,$6
+ or $3,$3,$4
+ or $5,$6,$8
+ stq $8,0($16)
+ bne $28,.Loop0
+
+.L0: sll $4,$19,$24
+ beq $18,.Lend
+ # warm up phase 1
+ ldq $1,-16($17)
+ subq $18,4,$18
+ ldq $2,-24($17)
+ ldq $3,-32($17)
+ ldq $4,-40($17)
+ beq $18,.Lend1
+ # warm up phase 2
+ srl $1,$20,$7
+ sll $1,$19,$21
+ srl $2,$20,$8
+ ldq $1,-48($17)
+ sll $2,$19,$22
+ ldq $2,-56($17)
+ srl $3,$20,$5
+ or $7,$24,$7
+ sll $3,$19,$23
+ or $8,$21,$8
+ srl $4,$20,$6
+ ldq $3,-64($17)
+ sll $4,$19,$24
+ ldq $4,-72($17)
+ subq $18,4,$18
+ beq $18,.Lend2
+ .align 4
+ # main loop
+.Loop: stq $7,-8($16)
+ or $5,$22,$5
+ stq $8,-16($16)
+ or $6,$23,$6
+
+ srl $1,$20,$7
+ subq $18,4,$18
+ sll $1,$19,$21
+ unop # ldq $31,-96($17)
+
+ srl $2,$20,$8
+ ldq $1,-80($17)
+ sll $2,$19,$22
+ ldq $2,-88($17)
+
+ stq $5,-24($16)
+ or $7,$24,$7
+ stq $6,-32($16)
+ or $8,$21,$8
+
+ srl $3,$20,$5
+ unop # ldq $31,-96($17)
+ sll $3,$19,$23
+ subq $16,32,$16
+
+ srl $4,$20,$6
+ ldq $3,-96($17)
+ sll $4,$19,$24
+ ldq $4,-104($17)
+
+ subq $17,32,$17
+ bne $18,.Loop
+ # cool down phase 2/1
+.Lend2: stq $7,-8($16)
+ or $5,$22,$5
+ stq $8,-16($16)
+ or $6,$23,$6
+ srl $1,$20,$7
+ sll $1,$19,$21
+ srl $2,$20,$8
+ sll $2,$19,$22
+ stq $5,-24($16)
+ or $7,$24,$7
+ stq $6,-32($16)
+ or $8,$21,$8
+ srl $3,$20,$5
+ sll $3,$19,$23
+ srl $4,$20,$6
+ sll $4,$19,$24
+ # cool down phase 2/2
+ stq $7,-40($16)
+ or $5,$22,$5
+ stq $8,-48($16)
+ or $6,$23,$6
+ stq $5,-56($16)
+ stq $6,-64($16)
+ # cool down phase 2/3
+ stq $24,-72($16)
+ ret $31,($26),1
+
+ # cool down phase 1/1
+.Lend1: srl $1,$20,$7
+ sll $1,$19,$21
+ srl $2,$20,$8
+ sll $2,$19,$22
+ srl $3,$20,$5
+ or $7,$24,$7
+ sll $3,$19,$23
+ or $8,$21,$8
+ srl $4,$20,$6
+ sll $4,$19,$24
+ # cool down phase 1/2
+ stq $7,-8($16)
+ or $5,$22,$5
+ stq $8,-16($16)
+ or $6,$23,$6
+ stq $5,-24($16)
+ stq $6,-32($16)
+ stq $24,-40($16)
+ ret $31,($26),1
+
+.Lend: stq $24,-8($16)
+ ret $31,($26),1
+ .end __mpn_lshift
diff --git a/mpn/alpha/ev5/rshift.s b/mpn/alpha/ev5/rshift.s
new file mode 100644
index 000000000..6e24fef96
--- /dev/null
+++ b/mpn/alpha/ev5/rshift.s
@@ -0,0 +1,172 @@
+ # Alpha EV5 __mpn_rshift --
+
+ # Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+
+ # This file is part of the GNU MP Library.
+
+ # The GNU MP Library is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU Library General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or (at your
+ # option) any later version.
+
+ # The GNU MP Library 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 Library General Public
+ # License for more details.
+
+ # You should have received a copy of the GNU Library General Public License
+ # along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+ # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ # MA 02111-1307, USA.
+
+
+ # INPUT PARAMETERS
+ # res_ptr r16
+ # s1_ptr r17
+ # size r18
+ # cnt r19
+
+ # This code runs at 3.25 cycles/limb on the EV5.
+
+ .set noreorder
+ .set noat
+.text
+ .align 3
+ .globl __mpn_rshift
+ .ent __mpn_rshift
+__mpn_rshift:
+ .frame $30,0,$26,0
+
+ ldq $4,0($17) # load first limb
+ subq $31,$19,$20
+ subq $18,1,$18
+ and $18,4-1,$28 # number of limbs in first loop
+ sll $4,$20,$0 # compute function result
+
+ beq $28,.L0
+ subq $18,$28,$18
+
+ .align 3
+.Loop0: ldq $3,8($17)
+ addq $16,8,$16
+ srl $4,$19,$5
+ addq $17,8,$17
+ subq $28,1,$28
+ sll $3,$20,$6
+ or $3,$3,$4
+ or $5,$6,$8
+ stq $8,-8($16)
+ bne $28,.Loop0
+
+.L0: srl $4,$19,$24
+ beq $18,.Lend
+ # warm up phase 1
+ ldq $1,8($17)
+ subq $18,4,$18
+ ldq $2,16($17)
+ ldq $3,24($17)
+ ldq $4,32($17)
+ beq $18,.Lend1
+ # warm up phase 2
+ sll $1,$20,$7
+ srl $1,$19,$21
+ sll $2,$20,$8
+ ldq $1,40($17)
+ srl $2,$19,$22
+ ldq $2,48($17)
+ sll $3,$20,$5
+ or $7,$24,$7
+ srl $3,$19,$23
+ or $8,$21,$8
+ sll $4,$20,$6
+ ldq $3,56($17)
+ srl $4,$19,$24
+ ldq $4,64($17)
+ subq $18,4,$18
+ beq $18,.Lend2
+ .align 4
+ # main loop
+.Loop: stq $7,0($16)
+ or $5,$22,$5
+ stq $8,8($16)
+ or $6,$23,$6
+
+ sll $1,$20,$7
+ subq $18,4,$18
+ srl $1,$19,$21
+ unop # ldq $31,-96($17)
+
+ sll $2,$20,$8
+ ldq $1,72($17)
+ srl $2,$19,$22
+ ldq $2,80($17)
+
+ stq $5,16($16)
+ or $7,$24,$7
+ stq $6,24($16)
+ or $8,$21,$8
+
+ sll $3,$20,$5
+ unop # ldq $31,-96($17)
+ srl $3,$19,$23
+ addq $16,32,$16
+
+ sll $4,$20,$6
+ ldq $3,88($17)
+ srl $4,$19,$24
+ ldq $4,96($17)
+
+ addq $17,32,$17
+ bne $18,.Loop
+ # cool down phase 2/1
+.Lend2: stq $7,0($16)
+ or $5,$22,$5
+ stq $8,8($16)
+ or $6,$23,$6
+ sll $1,$20,$7
+ srl $1,$19,$21
+ sll $2,$20,$8
+ srl $2,$19,$22
+ stq $5,16($16)
+ or $7,$24,$7
+ stq $6,24($16)
+ or $8,$21,$8
+ sll $3,$20,$5
+ srl $3,$19,$23
+ sll $4,$20,$6
+ srl $4,$19,$24
+ # cool down phase 2/2
+ stq $7,32($16)
+ or $5,$22,$5
+ stq $8,40($16)
+ or $6,$23,$6
+ stq $5,48($16)
+ stq $6,56($16)
+ # cool down phase 2/3
+ stq $24,64($16)
+ ret $31,($26),1
+
+ # cool down phase 1/1
+.Lend1: sll $1,$20,$7
+ srl $1,$19,$21
+ sll $2,$20,$8
+ srl $2,$19,$22
+ sll $3,$20,$5
+ or $7,$24,$7
+ srl $3,$19,$23
+ or $8,$21,$8
+ sll $4,$20,$6
+ srl $4,$19,$24
+ # cool down phase 1/2
+ stq $7,0($16)
+ or $5,$22,$5
+ stq $8,8($16)
+ or $6,$23,$6
+ stq $5,16($16)
+ stq $6,24($16)
+ stq $24,32($16)
+ ret $31,($26),1
+
+.Lend: stq $24,0($16)
+ ret $31,($26),1
+ .end __mpn_rshift
diff --git a/mpn/alpha/ev5/sub_n.s b/mpn/alpha/ev5/sub_n.s
new file mode 100644
index 000000000..6743af50b
--- /dev/null
+++ b/mpn/alpha/ev5/sub_n.s
@@ -0,0 +1,149 @@
+ # Alpha __mpn_sub_n -- Subtract two limb vectors of the same length > 0 and
+ # store difference in a third limb vector.
+
+ # Copyright (C) 1995 Free Software Foundation, Inc.
+
+ # This file is part of the GNU MP Library.
+
+ # The GNU MP Library is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU Library General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or (at your
+ # option) any later version.
+
+ # The GNU MP Library 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 Library General Public
+ # License for more details.
+
+ # You should have received a copy of the GNU Library General Public License
+ # along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+ # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ # MA 02111-1307, USA.
+
+
+ # INPUT PARAMETERS
+ # res_ptr $16
+ # s1_ptr $17
+ # s2_ptr $18
+ # size $19
+
+ .set noreorder
+ .set noat
+.text
+ .align 3
+ .globl __mpn_sub_n
+ .ent __mpn_sub_n
+__mpn_sub_n:
+ .frame $30,0,$26,0
+
+ or $31,$31,$25 # clear cy
+ subq $19,4,$19 # decr loop cnt
+ blt $19,.Lend2 # if less than 4 limbs, goto 2nd loop
+ # Start software pipeline for 1st loop
+ ldq $0,0($18)
+ ldq $1,8($18)
+ ldq $4,0($17)
+ ldq $5,8($17)
+ addq $17,32,$17 # update s1_ptr
+ ldq $2,16($18)
+ subq $4,$0,$20 # 1st main sub
+ ldq $3,24($18)
+ subq $19,4,$19 # decr loop cnt
+ ldq $6,-16($17)
+ cmpult $4,$20,$25 # compute cy from last sub
+ ldq $7,-8($17)
+ addq $1,$25,$28 # cy add
+ addq $18,32,$18 # update s2_ptr
+ subq $5,$28,$21 # 2nd main sub
+ cmpult $28,$25,$8 # compute cy from last add
+ blt $19,.Lend1 # if less than 4 limbs remain, jump
+ # 1st loop handles groups of 4 limbs in a software pipeline
+ .align 4
+.Loop: cmpult $5,$21,$25 # compute cy from last add
+ ldq $0,0($18)
+ or $8,$25,$25 # combine cy from the two adds
+ ldq $1,8($18)
+ addq $2,$25,$28 # cy add
+ ldq $4,0($17)
+ subq $6,$28,$22 # 3rd main sub
+ ldq $5,8($17)
+ cmpult $28,$25,$8 # compute cy from last add
+ cmpult $6,$22,$25 # compute cy from last add
+ stq $20,0($16)
+ or $8,$25,$25 # combine cy from the two adds
+ stq $21,8($16)
+ addq $3,$25,$28 # cy add
+ subq $7,$28,$23 # 4th main sub
+ cmpult $28,$25,$8 # compute cy from last add
+ cmpult $7,$23,$25 # compute cy from last add
+ addq $17,32,$17 # update s1_ptr
+ or $8,$25,$25 # combine cy from the two adds
+ addq $16,32,$16 # update res_ptr
+ addq $0,$25,$28 # cy add
+ ldq $2,16($18)
+ subq $4,$28,$20 # 1st main sub
+ ldq $3,24($18)
+ cmpult $28,$25,$8 # compute cy from last add
+ ldq $6,-16($17)
+ cmpult $4,$20,$25 # compute cy from last add
+ ldq $7,-8($17)
+ or $8,$25,$25 # combine cy from the two adds
+ subq $19,4,$19 # decr loop cnt
+ stq $22,-16($16)
+ addq $1,$25,$28 # cy add
+ stq $23,-8($16)
+ subq $5,$28,$21 # 2nd main sub
+ addq $18,32,$18 # update s2_ptr
+ cmpult $28,$25,$8 # compute cy from last add
+ bge $19,.Loop
+ # Finish software pipeline for 1st loop
+.Lend1: cmpult $5,$21,$25 # compute cy from last add
+ or $8,$25,$25 # combine cy from the two adds
+ addq $2,$25,$28 # cy add
+ subq $6,$28,$22 # 3rd main sub
+ cmpult $28,$25,$8 # compute cy from last add
+ cmpult $6,$22,$25 # compute cy from last add
+ stq $20,0($16)
+ or $8,$25,$25 # combine cy from the two adds
+ stq $21,8($16)
+ addq $3,$25,$28 # cy add
+ subq $7,$28,$23 # 4th main sub
+ cmpult $28,$25,$8 # compute cy from last add
+ cmpult $7,$23,$25 # compute cy from last add
+ or $8,$25,$25 # combine cy from the two adds
+ addq $16,32,$16 # update res_ptr
+ stq $22,-16($16)
+ stq $23,-8($16)
+.Lend2: addq $19,4,$19 # restore loop cnt
+ beq $19,.Lret
+ # Start software pipeline for 2nd loop
+ ldq $0,0($18)
+ ldq $4,0($17)
+ subq $19,1,$19
+ beq $19,.Lend0
+ # 2nd loop handles remaining 1-3 limbs
+ .align 4
+.Loop0: addq $0,$25,$28 # cy add
+ ldq $0,8($18)
+ subq $4,$28,$20 # main sub
+ ldq $1,8($17)
+ addq $18,8,$18
+ cmpult $28,$25,$8 # compute cy from last add
+ addq $17,8,$17
+ stq $20,0($16)
+ cmpult $4,$20,$25 # compute cy from last add
+ subq $19,1,$19 # decr loop cnt
+ or $8,$25,$25 # combine cy from the two adds
+ addq $16,8,$16
+ or $1,$31,$4
+ bne $19,.Loop0
+.Lend0: addq $0,$25,$28 # cy add
+ subq $4,$28,$20 # main sub
+ cmpult $28,$25,$8 # compute cy from last add
+ cmpult $4,$20,$25 # compute cy from last add
+ stq $20,0($16)
+ or $8,$25,$25 # combine cy from the two adds
+
+.Lret: or $25,$31,$0 # return cy
+ ret $31,($26),1
+ .end __mpn_sub_n
diff --git a/mpn/alpha/gmp-mparam.h b/mpn/alpha/gmp-mparam.h
new file mode 100644
index 000000000..a3c66974d
--- /dev/null
+++ b/mpn/alpha/gmp-mparam.h
@@ -0,0 +1,27 @@
+/* gmp-mparam.h -- Compiler/machine parameter header file.
+
+Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#define BITS_PER_MP_LIMB 64
+#define BYTES_PER_MP_LIMB 8
+#define BITS_PER_LONGINT 64
+#define BITS_PER_INT 32
+#define BITS_PER_SHORTINT 16
+#define BITS_PER_CHAR 8
diff --git a/mpn/alpha/lshift.s b/mpn/alpha/lshift.s
new file mode 100644
index 000000000..13bd24a42
--- /dev/null
+++ b/mpn/alpha/lshift.s
@@ -0,0 +1,109 @@
+ # Alpha 21064 __mpn_lshift --
+
+ # Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+
+ # This file is part of the GNU MP Library.
+
+ # The GNU MP Library is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU Library General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or (at your
+ # option) any later version.
+
+ # The GNU MP Library 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 Library General Public
+ # License for more details.
+
+ # You should have received a copy of the GNU Library General Public License
+ # along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+ # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ # MA 02111-1307, USA.
+
+
+ # INPUT PARAMETERS
+ # res_ptr r16
+ # s1_ptr r17
+ # size r18
+ # cnt r19
+
+ # This code runs at 4.8 cycles/limb on the 21064. With infinite unrolling,
+ # it would take 4 cycles/limb. It should be possible to get down to 3
+ # cycles/limb since both ldq and stq can be paired with the other used
+ # instructions. But there are many restrictions in the 21064 pipeline that
+ # makes it hard, if not impossible, to get down to 3 cycles/limb:
+
+ # 1. ldq has a 3 cycle delay, srl and sll have a 2 cycle delay.
+ # 2. Only aligned instruction pairs can be paired.
+ # 3. The store buffer or silo might not be able to deal with the bandwidth.
+
+ .set noreorder
+ .set noat
+.text
+ .align 3
+ .globl __mpn_lshift
+ .ent __mpn_lshift
+__mpn_lshift:
+ .frame $30,0,$26,0
+
+ s8addq $18,$17,$17 # make r17 point at end of s1
+ ldq $4,-8($17) # load first limb
+ subq $17,8,$17
+ subq $31,$19,$7
+ s8addq $18,$16,$16 # make r16 point at end of RES
+ subq $18,1,$18
+ and $18,4-1,$20 # number of limbs in first loop
+ srl $4,$7,$0 # compute function result
+
+ beq $20,.L0
+ subq $18,$20,$18
+
+ .align 3
+.Loop0:
+ ldq $3,-8($17)
+ subq $16,8,$16
+ subq $17,8,$17
+ subq $20,1,$20
+ sll $4,$19,$5
+ srl $3,$7,$6
+ bis $3,$3,$4
+ bis $5,$6,$8
+ stq $8,0($16)
+ bne $20,.Loop0
+
+.L0: beq $18,.Lend
+
+ .align 3
+.Loop: ldq $3,-8($17)
+ subq $16,32,$16
+ subq $18,4,$18
+ sll $4,$19,$5
+ srl $3,$7,$6
+
+ ldq $4,-16($17)
+ sll $3,$19,$1
+ bis $5,$6,$8
+ stq $8,24($16)
+ srl $4,$7,$2
+
+ ldq $3,-24($17)
+ sll $4,$19,$5
+ bis $1,$2,$8
+ stq $8,16($16)
+ srl $3,$7,$6
+
+ ldq $4,-32($17)
+ sll $3,$19,$1
+ bis $5,$6,$8
+ stq $8,8($16)
+ srl $4,$7,$2
+
+ subq $17,32,$17
+ bis $1,$2,$8
+ stq $8,0($16)
+
+ bgt $18,.Loop
+
+.Lend: sll $4,$19,$8
+ stq $8,-8($16)
+ ret $31,($26),1
+ .end __mpn_lshift
diff --git a/mpn/alpha/mul_1.s b/mpn/alpha/mul_1.s
new file mode 100644
index 000000000..a1f5a94b9
--- /dev/null
+++ b/mpn/alpha/mul_1.s
@@ -0,0 +1,85 @@
+ # Alpha 21064 __mpn_mul_1 -- Multiply a limb vector with a limb and store
+ # the result in a second limb vector.
+
+ # Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
+
+ # This file is part of the GNU MP Library.
+
+ # The GNU MP Library is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU Library General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or (at your
+ # option) any later version.
+
+ # The GNU MP Library 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 Library General Public
+ # License for more details.
+
+ # You should have received a copy of the GNU Library General Public License
+ # along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+ # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ # MA 02111-1307, USA.
+
+
+ # INPUT PARAMETERS
+ # res_ptr r16
+ # s1_ptr r17
+ # size r18
+ # s2_limb r19
+
+ # This code runs at 42 cycles/limb on the EV4 and 18 cycles/limb on the EV5.
+
+ # To improve performance for long multiplications, we would use
+ # 'fetch' for S1 and 'fetch_m' for RES. It's not obvious how to use
+ # these instructions without slowing down the general code: 1. We can
+ # only have two prefetches in operation at any time in the Alpha
+ # architecture. 2. There will seldom be any special alignment
+ # between RES_PTR and S1_PTR. Maybe we can simply divide the current
+ # loop into an inner and outer loop, having the inner loop handle
+ # exactly one prefetch block?
+
+ .set noreorder
+ .set noat
+.text
+ .align 3
+ .globl __mpn_mul_1
+ .ent __mpn_mul_1 2
+__mpn_mul_1:
+ .frame $30,0,$26
+
+ ldq $2,0($17) # $2 = s1_limb
+ subq $18,1,$18 # size--
+ mulq $2,$19,$3 # $3 = prod_low
+ bic $31,$31,$4 # clear cy_limb
+ umulh $2,$19,$0 # $0 = prod_high
+ beq $18,Lend1 # jump if size was == 1
+ ldq $2,8($17) # $2 = s1_limb
+ subq $18,1,$18 # size--
+ stq $3,0($16)
+ beq $18,Lend2 # jump if size was == 2
+
+ .align 3
+Loop: mulq $2,$19,$3 # $3 = prod_low
+ addq $4,$0,$0 # cy_limb = cy_limb + 'cy'
+ subq $18,1,$18 # size--
+ umulh $2,$19,$4 # $4 = cy_limb
+ ldq $2,16($17) # $2 = s1_limb
+ addq $17,8,$17 # s1_ptr++
+ addq $3,$0,$3 # $3 = cy_limb + prod_low
+ stq $3,8($16)
+ cmpult $3,$0,$0 # $0 = carry from (cy_limb + prod_low)
+ addq $16,8,$16 # res_ptr++
+ bne $18,Loop
+
+Lend2: mulq $2,$19,$3 # $3 = prod_low
+ addq $4,$0,$0 # cy_limb = cy_limb + 'cy'
+ umulh $2,$19,$4 # $4 = cy_limb
+ addq $3,$0,$3 # $3 = cy_limb + prod_low
+ cmpult $3,$0,$0 # $0 = carry from (cy_limb + prod_low)
+ stq $3,8($16)
+ addq $4,$0,$0 # cy_limb = prod_high + cy
+ ret $31,($26),1
+Lend1: stq $3,0($16)
+ ret $31,($26),1
+
+ .end __mpn_mul_1
diff --git a/mpn/alpha/rshift.s b/mpn/alpha/rshift.s
new file mode 100644
index 000000000..389054ab0
--- /dev/null
+++ b/mpn/alpha/rshift.s
@@ -0,0 +1,107 @@
+ # Alpha 21064 __mpn_rshift --
+
+ # Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+
+ # This file is part of the GNU MP Library.
+
+ # The GNU MP Library is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU Library General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or (at your
+ # option) any later version.
+
+ # The GNU MP Library 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 Library General Public
+ # License for more details.
+
+ # You should have received a copy of the GNU Library General Public License
+ # along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+ # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ # MA 02111-1307, USA.
+
+
+ # INPUT PARAMETERS
+ # res_ptr r16
+ # s1_ptr r17
+ # size r18
+ # cnt r19
+
+ # This code runs at 4.8 cycles/limb on the 21064. With infinite unrolling,
+ # it would take 4 cycles/limb. It should be possible to get down to 3
+ # cycles/limb since both ldq and stq can be paired with the other used
+ # instructions. But there are many restrictions in the 21064 pipeline that
+ # makes it hard, if not impossible, to get down to 3 cycles/limb:
+
+ # 1. ldq has a 3 cycle delay, srl and sll have a 2 cycle delay.
+ # 2. Only aligned instruction pairs can be paired.
+ # 3. The store buffer or silo might not be able to deal with the bandwidth.
+
+ .set noreorder
+ .set noat
+.text
+ .align 3
+ .globl __mpn_rshift
+ .ent __mpn_rshift
+__mpn_rshift:
+ .frame $30,0,$26,0
+
+ ldq $4,0($17) # load first limb
+ addq $17,8,$17
+ subq $31,$19,$7
+ subq $18,1,$18
+ and $18,4-1,$20 # number of limbs in first loop
+ sll $4,$7,$0 # compute function result
+
+ beq $20,.L0
+ subq $18,$20,$18
+
+ .align 3
+.Loop0:
+ ldq $3,0($17)
+ addq $16,8,$16
+ addq $17,8,$17
+ subq $20,1,$20
+ srl $4,$19,$5
+ sll $3,$7,$6
+ bis $3,$3,$4
+ bis $5,$6,$8
+ stq $8,-8($16)
+ bne $20,.Loop0
+
+.L0: beq $18,.Lend
+
+ .align 3
+.Loop: ldq $3,0($17)
+ addq $16,32,$16
+ subq $18,4,$18
+ srl $4,$19,$5
+ sll $3,$7,$6
+
+ ldq $4,8($17)
+ srl $3,$19,$1
+ bis $5,$6,$8
+ stq $8,-32($16)
+ sll $4,$7,$2
+
+ ldq $3,16($17)
+ srl $4,$19,$5
+ bis $1,$2,$8
+ stq $8,-24($16)
+ sll $3,$7,$6
+
+ ldq $4,24($17)
+ srl $3,$19,$1
+ bis $5,$6,$8
+ stq $8,-16($16)
+ sll $4,$7,$2
+
+ addq $17,32,$17
+ bis $1,$2,$8
+ stq $8,-8($16)
+
+ bgt $18,.Loop
+
+.Lend: srl $4,$19,$8
+ stq $8,0($16)
+ ret $31,($26),1
+ .end __mpn_rshift
diff --git a/mpn/alpha/sub_n.s b/mpn/alpha/sub_n.s
new file mode 100644
index 000000000..3c90c1169
--- /dev/null
+++ b/mpn/alpha/sub_n.s
@@ -0,0 +1,120 @@
+ # Alpha __mpn_sub_n -- Subtract two limb vectors of the same length > 0 and
+ # store difference in a third limb vector.
+
+ # Copyright (C) 1995 Free Software Foundation, Inc.
+
+ # This file is part of the GNU MP Library.
+
+ # The GNU MP Library is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU Library General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or (at your
+ # option) any later version.
+
+ # The GNU MP Library 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 Library General Public
+ # License for more details.
+
+ # You should have received a copy of the GNU Library General Public License
+ # along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+ # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ # MA 02111-1307, USA.
+
+
+ # INPUT PARAMETERS
+ # res_ptr $16
+ # s1_ptr $17
+ # s2_ptr $18
+ # size $19
+
+ .set noreorder
+ .set noat
+.text
+ .align 3
+ .globl __mpn_sub_n
+ .ent __mpn_sub_n
+__mpn_sub_n:
+ .frame $30,0,$26,0
+
+ ldq $3,0($17)
+ ldq $4,0($18)
+
+ subq $19,1,$19
+ and $19,4-1,$2 # number of limbs in first loop
+ bis $31,$31,$0
+ beq $2,.L0 # if multiple of 4 limbs, skip first loop
+
+ subq $19,$2,$19
+
+.Loop0: subq $2,1,$2
+ ldq $5,8($17)
+ addq $4,$0,$4
+ ldq $6,8($18)
+ cmpult $4,$0,$1
+ subq $3,$4,$4
+ cmpult $3,$4,$0
+ stq $4,0($16)
+ or $0,$1,$0
+
+ addq $17,8,$17
+ addq $18,8,$18
+ bis $5,$5,$3
+ bis $6,$6,$4
+ addq $16,8,$16
+ bne $2,.Loop0
+
+.L0: beq $19,.Lend
+
+ .align 3
+.Loop: subq $19,4,$19
+
+ ldq $5,8($17)
+ addq $4,$0,$4
+ ldq $6,8($18)
+ cmpult $4,$0,$1
+ subq $3,$4,$4
+ cmpult $3,$4,$0
+ stq $4,0($16)
+ or $0,$1,$0
+
+ ldq $3,16($17)
+ addq $6,$0,$6
+ ldq $4,16($18)
+ cmpult $6,$0,$1
+ subq $5,$6,$6
+ cmpult $5,$6,$0
+ stq $6,8($16)
+ or $0,$1,$0
+
+ ldq $5,24($17)
+ addq $4,$0,$4
+ ldq $6,24($18)
+ cmpult $4,$0,$1
+ subq $3,$4,$4
+ cmpult $3,$4,$0
+ stq $4,16($16)
+ or $0,$1,$0
+
+ ldq $3,32($17)
+ addq $6,$0,$6
+ ldq $4,32($18)
+ cmpult $6,$0,$1
+ subq $5,$6,$6
+ cmpult $5,$6,$0
+ stq $6,24($16)
+ or $0,$1,$0
+
+ addq $17,32,$17
+ addq $18,32,$18
+ addq $16,32,$16
+ bne $19,.Loop
+
+.Lend: addq $4,$0,$4
+ cmpult $4,$0,$1
+ subq $3,$4,$4
+ cmpult $3,$4,$0
+ stq $4,0($16)
+ or $0,$1,$0
+ ret $31,($26),1
+
+ .end __mpn_sub_n
diff --git a/mpn/alpha/submul_1.s b/mpn/alpha/submul_1.s
new file mode 100644
index 000000000..1ed0c6a8d
--- /dev/null
+++ b/mpn/alpha/submul_1.s
@@ -0,0 +1,92 @@
+ # Alpha 21064 __mpn_submul_1 -- Multiply a limb vector with a limb and
+ # subtract the result from a second limb vector.
+
+ # Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
+
+ # This file is part of the GNU MP Library.
+
+ # The GNU MP Library is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU Library General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or (at your
+ # option) any later version.
+
+ # The GNU MP Library 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 Library General Public
+ # License for more details.
+
+ # You should have received a copy of the GNU Library General Public License
+ # along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+ # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ # MA 02111-1307, USA.
+
+
+ # INPUT PARAMETERS
+ # res_ptr r16
+ # s1_ptr r17
+ # size r18
+ # s2_limb r19
+
+ # This code runs at 42 cycles/limb on EV4 and 18 cycles/limb on EV5.
+
+ .set noreorder
+ .set noat
+.text
+ .align 3
+ .globl __mpn_submul_1
+ .ent __mpn_submul_1 2
+__mpn_submul_1:
+ .frame $30,0,$26
+
+ ldq $2,0($17) # $2 = s1_limb
+ addq $17,8,$17 # s1_ptr++
+ subq $18,1,$18 # size--
+ mulq $2,$19,$3 # $3 = prod_low
+ ldq $5,0($16) # $5 = *res_ptr
+ umulh $2,$19,$0 # $0 = prod_high
+ beq $18,.Lend1 # jump if size was == 1
+ ldq $2,0($17) # $2 = s1_limb
+ addq $17,8,$17 # s1_ptr++
+ subq $18,1,$18 # size--
+ subq $5,$3,$3
+ cmpult $5,$3,$4
+ stq $3,0($16)
+ addq $16,8,$16 # res_ptr++
+ beq $18,.Lend2 # jump if size was == 2
+
+ .align 3
+.Loop: mulq $2,$19,$3 # $3 = prod_low
+ ldq $5,0($16) # $5 = *res_ptr
+ addq $4,$0,$0 # cy_limb = cy_limb + 'cy'
+ subq $18,1,$18 # size--
+ umulh $2,$19,$4 # $4 = cy_limb
+ ldq $2,0($17) # $2 = s1_limb
+ addq $17,8,$17 # s1_ptr++
+ addq $3,$0,$3 # $3 = cy_limb + prod_low
+ cmpult $3,$0,$0 # $0 = carry from (cy_limb + prod_low)
+ subq $5,$3,$3
+ cmpult $5,$3,$5
+ stq $3,0($16)
+ addq $16,8,$16 # res_ptr++
+ addq $5,$0,$0 # combine carries
+ bne $18,.Loop
+
+.Lend2: mulq $2,$19,$3 # $3 = prod_low
+ ldq $5,0($16) # $5 = *res_ptr
+ addq $4,$0,$0 # cy_limb = cy_limb + 'cy'
+ umulh $2,$19,$4 # $4 = cy_limb
+ addq $3,$0,$3 # $3 = cy_limb + prod_low
+ cmpult $3,$0,$0 # $0 = carry from (cy_limb + prod_low)
+ subq $5,$3,$3
+ cmpult $5,$3,$5
+ stq $3,0($16)
+ addq $5,$0,$0 # combine carries
+ addq $4,$0,$0 # cy_limb = prod_high + cy
+ ret $31,($26),1
+.Lend1: subq $5,$3,$3
+ cmpult $5,$3,$5
+ stq $3,0($16)
+ addq $0,$5,$0
+ ret $31,($26),1
+
+ .end __mpn_submul_1
diff --git a/mpn/alpha/udiv_qrnnd.S b/mpn/alpha/udiv_qrnnd.S
new file mode 100644
index 000000000..d3d2cee93
--- /dev/null
+++ b/mpn/alpha/udiv_qrnnd.S
@@ -0,0 +1,151 @@
+ # Alpha 21064 __udiv_qrnnd
+
+ # Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
+
+ # This file is part of the GNU MP Library.
+
+ # The GNU MP Library is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU Library General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or (at your
+ # option) any later version.
+
+ # The GNU MP Library 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 Library General Public
+ # License for more details.
+
+ # You should have received a copy of the GNU Library General Public License
+ # along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+ # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ # MA 02111-1307, USA.
+
+
+ .set noreorder
+ .set noat
+.text
+ .align 3
+ .globl __udiv_qrnnd
+ .ent __udiv_qrnnd
+__udiv_qrnnd:
+ .frame $30,0,$26,0
+ .prologue 0
+#define cnt $2
+#define tmp $3
+#define rem_ptr $16
+#define n1 $17
+#define n0 $18
+#define d $19
+#define qb $20
+
+ ldiq cnt,16
+ blt d,.Largedivisor
+
+.Loop1: cmplt n0,0,tmp
+ addq n1,n1,n1
+ bis n1,tmp,n1
+ addq n0,n0,n0
+ cmpule d,n1,qb
+ subq n1,d,tmp
+ cmovne qb,tmp,n1
+ bis n0,qb,n0
+ cmplt n0,0,tmp
+ addq n1,n1,n1
+ bis n1,tmp,n1
+ addq n0,n0,n0
+ cmpule d,n1,qb
+ subq n1,d,tmp
+ cmovne qb,tmp,n1
+ bis n0,qb,n0
+ cmplt n0,0,tmp
+ addq n1,n1,n1
+ bis n1,tmp,n1
+ addq n0,n0,n0
+ cmpule d,n1,qb
+ subq n1,d,tmp
+ cmovne qb,tmp,n1
+ bis n0,qb,n0
+ cmplt n0,0,tmp
+ addq n1,n1,n1
+ bis n1,tmp,n1
+ addq n0,n0,n0
+ cmpule d,n1,qb
+ subq n1,d,tmp
+ cmovne qb,tmp,n1
+ bis n0,qb,n0
+ subq cnt,1,cnt
+ bgt cnt,.Loop1
+ stq n1,0(rem_ptr)
+ bis $31,n0,$0
+ ret $31,($26),1
+
+.Largedivisor:
+ and n0,1,$4
+
+ srl n0,1,n0
+ sll n1,63,tmp
+ or tmp,n0,n0
+ srl n1,1,n1
+
+ and d,1,$6
+ srl d,1,$5
+ addq $5,$6,$5
+
+.Loop2: cmplt n0,0,tmp
+ addq n1,n1,n1
+ bis n1,tmp,n1
+ addq n0,n0,n0
+ cmpule $5,n1,qb
+ subq n1,$5,tmp
+ cmovne qb,tmp,n1
+ bis n0,qb,n0
+ cmplt n0,0,tmp
+ addq n1,n1,n1
+ bis n1,tmp,n1
+ addq n0,n0,n0
+ cmpule $5,n1,qb
+ subq n1,$5,tmp
+ cmovne qb,tmp,n1
+ bis n0,qb,n0
+ cmplt n0,0,tmp
+ addq n1,n1,n1
+ bis n1,tmp,n1
+ addq n0,n0,n0
+ cmpule $5,n1,qb
+ subq n1,$5,tmp
+ cmovne qb,tmp,n1
+ bis n0,qb,n0
+ cmplt n0,0,tmp
+ addq n1,n1,n1
+ bis n1,tmp,n1
+ addq n0,n0,n0
+ cmpule $5,n1,qb
+ subq n1,$5,tmp
+ cmovne qb,tmp,n1
+ bis n0,qb,n0
+ subq cnt,1,cnt
+ bgt cnt,.Loop2
+
+ addq n1,n1,n1
+ addq $4,n1,n1
+ bne $6,.LOdd
+ stq n1,0(rem_ptr)
+ bis $31,n0,$0
+ ret $31,($26),1
+
+.LOdd:
+ /* q' in n0. r' in n1 */
+ addq n1,n0,n1
+ cmpult n1,n0,tmp # tmp := carry from addq
+ beq tmp,.LLp6
+ addq n0,1,n0
+ subq n1,d,n1
+.LLp6: cmpult n1,d,tmp
+ bne tmp,.LLp7
+ addq n0,1,n0
+ subq n1,d,n1
+.LLp7:
+ stq n1,0(rem_ptr)
+ bis $31,n0,$0
+ ret $31,($26),1
+
+ .end __udiv_qrnnd
diff --git a/mpn/bsd.h b/mpn/bsd.h
new file mode 100644
index 000000000..8a0cbced2
--- /dev/null
+++ b/mpn/bsd.h
@@ -0,0 +1,5 @@
+#if __STDC__
+#define C_SYMBOL_NAME(name) _##name
+#else
+#define C_SYMBOL_NAME(name) _/**/name
+#endif
diff --git a/mpn/clipper/add_n.s b/mpn/clipper/add_n.s
new file mode 100644
index 000000000..40ed1bd32
--- /dev/null
+++ b/mpn/clipper/add_n.s
@@ -0,0 +1,26 @@
+.text
+ .align 16
+.globl ___mpn_add_n
+___mpn_add_n:
+ subq $8,sp
+ storw r6,(sp)
+ loadw 12(sp),r2
+ loadw 16(sp),r3
+ loadq $0,r6 ; clear carry-save register
+
+.Loop: loadw (r1),r4
+ loadw (r2),r5
+ addwc r6,r6 ; restore carry from r6
+ addwc r5,r4
+ storw r4,(r0)
+ subwc r6,r6 ; save carry in r6
+ addq $4,r0
+ addq $4,r1
+ addq $4,r2
+ subq $1,r3
+ brne .Loop
+
+ negw r6,r0
+ loadw (sp),r6
+ addq $8,sp
+ ret sp
diff --git a/mpn/clipper/mul_1.s b/mpn/clipper/mul_1.s
new file mode 100644
index 000000000..f20ece02a
--- /dev/null
+++ b/mpn/clipper/mul_1.s
@@ -0,0 +1,25 @@
+.text
+ .align 16
+.globl ___mpn_mul_1
+___mpn_mul_1:
+ subq $8,sp
+ storw r6,(sp)
+ loadw 12(sp),r2
+ loadw 16(sp),r3
+ loadq $0,r6 ; clear carry limb
+
+.Loop: loadw (r1),r4
+ mulwux r3,r4
+ addw r6,r4 ; add old carry limb into low product limb
+ loadq $0,r6
+ addwc r5,r6 ; propagate cy into high product limb
+ storw r4,(r0)
+ addq $4,r0
+ addq $4,r1
+ subq $1,r2
+ brne .Loop
+
+ movw r6,r0
+ loadw 0(sp),r6
+ addq $8,sp
+ ret sp
diff --git a/mpn/clipper/sub_n.s b/mpn/clipper/sub_n.s
new file mode 100644
index 000000000..6f47d47c9
--- /dev/null
+++ b/mpn/clipper/sub_n.s
@@ -0,0 +1,26 @@
+.text
+ .align 16
+.globl ___mpn_sub_n
+___mpn_sub_n:
+ subq $8,sp
+ storw r6,(sp)
+ loadw 12(sp),r2
+ loadw 16(sp),r3
+ loadq $0,r6 ; clear carry-save register
+
+.Loop: loadw (r1),r4
+ loadw (r2),r5
+ addwc r6,r6 ; restore carry from r6
+ subwc r5,r4
+ storw r4,(r0)
+ subwc r6,r6 ; save carry in r6
+ addq $4,r0
+ addq $4,r1
+ addq $4,r2
+ subq $1,r3
+ brne .Loop
+
+ negw r6,r0
+ loadw (sp),r6
+ addq $8,sp
+ ret sp
diff --git a/mpn/config/t-freebsd b/mpn/config/t-freebsd
new file mode 100644
index 000000000..ba02fa768
--- /dev/null
+++ b/mpn/config/t-freebsd
@@ -0,0 +1 @@
+SFLAGS=-DBROKEN_ALIGN
diff --git a/mpn/configure.in b/mpn/configure.in
new file mode 100644
index 000000000..187cf9e9d
--- /dev/null
+++ b/mpn/configure.in
@@ -0,0 +1,165 @@
+# This file is a shell script fragment that supplies the information
+# necessary for a configure script to process the program in
+# this directory. For more information, look at ../configure.
+
+configdirs=
+srctrigger=powerpc32
+srcname="GNU Multi-Precision library/mpn"
+
+# per-host:
+
+# per-target:
+
+case "${target}" in
+ sparc9*-*-* | sparc64*-*-* | ultrasparc*-*-*) path="sparc64" ;;
+ sparc8*-*-* | microsparc*-*-*)
+ path="sparc32/v8 sparc"; ;;
+ supersparc*-*-*)
+ path="sparc32/v8/supersparc sparc32/v8 sparc"
+ extra_functions="udiv" ;;
+ sparc*-*-*) path="sparc32"
+ if [ x$floating_point = xno ]
+ then extra_functions="udiv_nfp"
+ else extra_functions="udiv_fp"
+ fi
+ ;;
+ hppa7000*-*-*) path="hppa/hppa1_1 hppa"; extra_functions="udiv_qrnnd" ;;
+ hppa1.0*-*-*) path="hppa"; extra_functions="udiv_qrnnd" ;;
+ hppa*-*-*) # assume pa7100
+ path="hppa/hppa1_1/pa7100 hppa/hppa1_1 hppa"
+ extra_functions="udiv_qrnnd" ;;
+ cray2-cray-unicos* | [xy]mp-cray-unicos* | [ctj]90-cray-unicos*)
+ path="cray" ;;
+ alphaev5-*-*) path="alpha/ev5 alpha"; extra_functions="udiv_qrnnd" ;;
+ alpha*-*-*) path="alpha"; extra_functions="udiv_qrnnd" ;;
+ am29000*-*-*) path="am29000" ;;
+ a29k*-*-*) path="am29000" ;;
+ i[34]86*-*-linuxaout* | i[34]86*-*-linuxoldld* | \
+ i[34]86*-*-*bsd*) # x86 running BSD or Linux with a.out
+ echo '#define BSD_SYNTAX' >asm-syntax.h
+ echo '#include "'$srcdir'/x86/syntax.h"' >>asm-syntax.h
+ path="x86" ;;
+ i[56]86*-*-linuxaout* | pentium-*-linuxaout* | pentiumpro-*-linuxaout* | \
+ i[56]86*-*-linuxoldld* | pentium-*-linuxoldld* | pentiumpro-*-linuxoldld* | \
+ i[56]86*-*-*bsd* | pentium-*-*bsd* | pentiumpro-*-*bsd*)
+ echo '#define BSD_SYNTAX' >asm-syntax.h
+ echo '#include "'$srcdir'/x86/syntax.h"' >>asm-syntax.h
+ path="x86/pentium x86" ;;
+ i[34]86*-*-*) # x86 with ELF/SysV format
+ echo '#define ELF_SYNTAX' >asm-syntax.h
+ echo '#include "'$srcdir'/x86/syntax.h"' >>asm-syntax.h
+ path="x86" ;;
+ i[56]86*-*-* | pentium-*-* | pentiumpro-*-*) # x86 with ELF/SysV format
+ echo '#define ELF_SYNTAX' >asm-syntax.h
+ echo '#include "'$srcdir'/x86/syntax.h"' >>asm-syntax.h
+ path="x86/pentium x86" ;;
+ i960*-*-*) path="i960" ;;
+# Motorola 68k configurations. Let m68k mean 68020-68040.
+# mc68000 or mc68060 configurations need to be specified explicitly
+ m680[234]0*-*-linuxaout* | m68k*-*-linuxaout*)
+ echo '#define MIT_SYNTAX' >asm-syntax.h
+ echo '#include "'$srcdir'/m68k/syntax.h"' >>asm-syntax.h
+ path="m68k/mc68020 m68k" ;;
+ m68060*-*-linuxaout*)
+ echo '#define MIT_SYNTAX' >asm-syntax.h
+ echo '#include "'$srcdir'/m68k/syntax.h"' >>asm-syntax.h
+ path="m68k" ;;
+ m680[234]0*-*-linux* | m68k*-*-linux*)
+ echo '#define ELF_SYNTAX' >asm-syntax.h
+ echo '#include "'$srcdir'/m68k/syntax.h"' >>asm-syntax.h
+ path="m68k/mc68020 m68k" ;;
+ m68060*-*-linux*)
+ echo '#define ELF_SYNTAX' >asm-syntax.h
+ echo '#include "'$srcdir'/m68k/syntax.h"' >>asm-syntax.h
+ path="m68k" ;;
+ m68000*-*-* | m68060*-*-*)
+ echo '#define MIT_SYNTAX' >asm-syntax.h
+ echo '#include "'$srcdir'/m68k/syntax.h"' >>asm-syntax.h
+ path="m68k/mc68000" ;;
+ m680[234]0*-*-* | m68k*-*-*)
+ echo '#define MIT_SYNTAX' >asm-syntax.h
+ echo '#include "'$srcdir'/m68k/syntax.h"' >>asm-syntax.h
+ path="m68k/mc68020 m68k" ;;
+ m88k*-*-* | m88k*-*-*) path="m88k" ;;
+ m88110*-*-*) path="m88k/mc88110 m88k" ;;
+ ns32k*-*-*) path="n32k" ;;
+ ppc601-*-*) path="power powerpc32" ;;
+ ppc620-*-* | powerpc64*-*-*) path="powerpc64" ;;
+ ppc60[234]*-*-* | powerpc*-*-*) path="powerpc32" ;;
+ pyramid-*-*) path="pyr" ;;
+ rs6000-*-* | power-*-* | power2-*-*)
+ path="power"; extra_functions="udiv_w_sdiv" ;;
+ sh-*-*) path="sh" ;;
+ sh2-*-*) path="sh/sh2 sh" ;;
+ mips[34]*-*-*) path="mips3" ;;
+ mips*-*-irix6*) path="mips3" ;;
+ mips*-*-*) path="mips2" ;;
+ vax*-*-*) path="vax"; extra_functions="udiv_w_sdiv" ;;
+ z8000x*-*-*) path="z8000x"; extra_functions="udiv_w_sdiv" ;;
+ z8000*-*-*) path="z8000"; extra_functions="udiv_w_sdiv" ;;
+ clipper*-*-*) path="clipper" ;;
+ *-*-*) ;;
+esac
+
+case "${target}" in
+ *-*-linuxaout* | *-*-linuxoldld*) config=bsd.h ;;
+ *-sysv* | *-solaris* | *-*-linux*) config="sysv.h" ;;
+ *) config="bsd.h" ;;
+esac
+
+case "${target}" in
+ i[3456]86*-*-freebsd* | pentium-*-freebsd* | pentiumpro-*-freebsd* | \
+ i[3456]86*-*-netbsd* | pentium-*-netbsd* | pentiumpro-*-netbsd*)
+ target_makefile_frag=config/t-freebsd ;;
+esac
+
+
+functions="${extra_functions} inlines add_n addmul_1 cmp divmod_1 \
+ divrem divrem_1 dump lshift mod_1 mul mul_1 mul_n random2 rshift sqrtrem \
+ sub_n submul_1 get_str set_str scan0 scan1 popcount hamdist gcd_1 \
+ pre_mod_1 perfsqr bdivmod gcd gcdext"
+
+path="$path generic"
+mpn_objects=
+
+for fn in $functions ; do
+ mpn_objects="$mpn_objects $fn.o"
+ for dir in $path ; do
+ rm -f $fn.[Ssc]
+ if test -f $srcdir/$dir/$fn.S ; then
+ files="$files $dir/$fn.S"
+ links="$links $fn.S"
+ break
+ elif test -f $srcdir/$dir/$fn.s ; then
+ files="$files $dir/$fn.s"
+ links="$links $fn.s"
+ break
+ elif test -f $srcdir/$dir/$fn.c ; then
+ files="$files $dir/$fn.c"
+ links="$links $fn.c"
+ break
+ fi
+ done
+done
+
+for dir in $path ; do
+ rm -f gmp-mparam.h
+ if test -f $srcdir/$dir/gmp-mparam.h ; then
+ files="$files $dir/gmp-mparam.h"
+ links="$links gmp-mparam.h"
+ break
+ fi
+done
+
+links="sysdep.h $links"
+files="$config $files"
+
+mpn_links=$links
+
+# post-target:
+
+sed <Makefile >Makefile.tmp \
+ -e "s/MPN_LINKS = .*/MPN_LINKS =${mpn_links}/" \
+ -e "s/MPN_OBJECTS = .*/MPN_OBJECTS =${mpn_objects}/"
+
+mv Makefile.tmp Makefile
diff --git a/mpn/cray/gmp-mparam.h b/mpn/cray/gmp-mparam.h
new file mode 100644
index 000000000..349c812d4
--- /dev/null
+++ b/mpn/cray/gmp-mparam.h
@@ -0,0 +1,27 @@
+/* gmp-mparam.h -- Compiler/machine parameter header file.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#define BITS_PER_MP_LIMB 64
+#define BYTES_PER_MP_LIMB 8
+#define BITS_PER_LONGINT 64
+#define BITS_PER_INT 64
+#define BITS_PER_SHORTINT 32
+#define BITS_PER_CHAR 8
diff --git a/mpn/generic/add_n.c b/mpn/generic/add_n.c
new file mode 100644
index 000000000..9d71df110
--- /dev/null
+++ b/mpn/generic/add_n.c
@@ -0,0 +1,62 @@
+/* mpn_add_n -- Add two limb vectors of equal, non-zero length.
+
+Copyright (C) 1992, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+mp_limb_t
+#if __STDC__
+mpn_add_n (mp_ptr res_ptr, mp_srcptr s1_ptr, mp_srcptr s2_ptr, mp_size_t size)
+#else
+mpn_add_n (res_ptr, s1_ptr, s2_ptr, size)
+ register mp_ptr res_ptr;
+ register mp_srcptr s1_ptr;
+ register mp_srcptr s2_ptr;
+ mp_size_t size;
+#endif
+{
+ register mp_limb_t x, y, cy;
+ register mp_size_t j;
+
+ /* The loop counter and index J goes from -SIZE to -1. This way
+ the loop becomes faster. */
+ j = -size;
+
+ /* Offset the base pointers to compensate for the negative indices. */
+ s1_ptr -= j;
+ s2_ptr -= j;
+ res_ptr -= j;
+
+ cy = 0;
+ do
+ {
+ y = s2_ptr[j];
+ x = s1_ptr[j];
+ y += cy; /* add previous carry to one addend */
+ cy = (y < cy); /* get out carry from that addition */
+ y = x + y; /* add other addend */
+ cy = (y < x) + cy; /* get out carry from that add, combine */
+ res_ptr[j] = y;
+ }
+ while (++j != 0);
+
+ return cy;
+}
diff --git a/mpn/generic/addmul_1.c b/mpn/generic/addmul_1.c
new file mode 100644
index 000000000..3a5e21400
--- /dev/null
+++ b/mpn/generic/addmul_1.c
@@ -0,0 +1,65 @@
+/* mpn_addmul_1 -- multiply the S1_SIZE long limb vector pointed to by S1_PTR
+ by S2_LIMB, add the S1_SIZE least significant limbs of the product to the
+ limb vector pointed to by RES_PTR. Return the most significant limb of
+ the product, adjusted for carry-out from the addition.
+
+Copyright (C) 1992, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+mp_limb_t
+mpn_addmul_1 (res_ptr, s1_ptr, s1_size, s2_limb)
+ register mp_ptr res_ptr;
+ register mp_srcptr s1_ptr;
+ mp_size_t s1_size;
+ register mp_limb_t s2_limb;
+{
+ register mp_limb_t cy_limb;
+ register mp_size_t j;
+ register mp_limb_t prod_high, prod_low;
+ register mp_limb_t x;
+
+ /* The loop counter and index J goes from -SIZE to -1. This way
+ the loop becomes faster. */
+ j = -s1_size;
+
+ /* Offset the base pointers to compensate for the negative indices. */
+ res_ptr -= j;
+ s1_ptr -= j;
+
+ cy_limb = 0;
+ do
+ {
+ umul_ppmm (prod_high, prod_low, s1_ptr[j], s2_limb);
+
+ prod_low += cy_limb;
+ cy_limb = (prod_low < cy_limb) + prod_high;
+
+ x = res_ptr[j];
+ prod_low = x + prod_low;
+ cy_limb += (prod_low < x);
+ res_ptr[j] = prod_low;
+ }
+ while (++j != 0);
+
+ return cy_limb;
+}
diff --git a/mpn/generic/bdivmod.c b/mpn/generic/bdivmod.c
new file mode 100644
index 000000000..ff4fb733b
--- /dev/null
+++ b/mpn/generic/bdivmod.c
@@ -0,0 +1,129 @@
+/* mpn/bdivmod.c: mpn_bdivmod for computing U/V mod 2^d.
+
+Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/* q_high = mpn_bdivmod (qp, up, usize, vp, vsize, d).
+
+ Puts the low d/BITS_PER_MP_LIMB limbs of Q = U / V mod 2^d at qp, and
+ returns the high d%BITS_PER_MP_LIMB bits of Q as the result.
+
+ Also, U - Q * V mod 2^(usize*BITS_PER_MP_LIMB) is placed at up. Since the
+ low d/BITS_PER_MP_LIMB limbs of this difference are zero, the code allows
+ the limb vectors at qp to overwrite the low limbs at up, provided qp <= up.
+
+ Preconditions:
+ 1. V is odd.
+ 2. usize * BITS_PER_MP_LIMB >= d.
+ 3. If Q and U overlap, qp <= up.
+
+ Ken Weber (kweber@mat.ufrgs.br, kweber@mcs.kent.edu)
+
+ Funding for this work has been partially provided by Conselho Nacional
+ de Desenvolvimento Cienti'fico e Tecnolo'gico (CNPq) do Brazil, Grant
+ 301314194-2, and was done while I was a visiting reseacher in the Instituto
+ de Matema'tica at Universidade Federal do Rio Grande do Sul (UFRGS).
+
+ References:
+ T. Jebelean, An algorithm for exact division, Journal of Symbolic
+ Computation, v. 15, 1993, pp. 169-180.
+
+ K. Weber, The accelerated integer GCD algorithm, ACM Transactions on
+ Mathematical Software, v. 21 (March), 1995, pp. 111-122. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+mp_limb_t
+#if __STDC__
+mpn_bdivmod (mp_ptr qp, mp_ptr up, mp_size_t usize,
+ mp_srcptr vp, mp_size_t vsize, unsigned long int d)
+#else
+mpn_bdivmod (qp, up, usize, vp, vsize, d)
+ mp_ptr qp;
+ mp_ptr up;
+ mp_size_t usize;
+ mp_srcptr vp;
+ mp_size_t vsize;
+ unsigned long int d;
+#endif
+{
+ /* Cache for v_inv is used to make mpn_accelgcd faster. */
+ static mp_limb_t previous_low_vlimb = 0;
+ static mp_limb_t v_inv; /* 1/V mod 2^BITS_PER_MP_LIMB. */
+
+ if (vp[0] != previous_low_vlimb) /* Cache miss; compute v_inv. */
+ {
+ mp_limb_t v = previous_low_vlimb = vp[0];
+ mp_limb_t make_zero = 1;
+ mp_limb_t two_i = 1;
+ v_inv = 0;
+ do
+ {
+ while ((two_i & make_zero) == 0)
+ two_i <<= 1, v <<= 1;
+ v_inv += two_i;
+ make_zero -= v;
+ }
+ while (make_zero);
+ }
+
+ /* Need faster computation for some common cases in mpn_accelgcd. */
+ if (usize == 2 && vsize == 2 &&
+ (d == BITS_PER_MP_LIMB || d == 2*BITS_PER_MP_LIMB))
+ {
+ mp_limb_t hi, lo;
+ mp_limb_t q = up[0] * v_inv;
+ umul_ppmm (hi, lo, q, vp[0]);
+ up[0] = 0, up[1] -= hi + q*vp[1], qp[0] = q;
+ if (d == 2*BITS_PER_MP_LIMB)
+ q = up[1] * v_inv, up[1] = 0, qp[1] = q;
+ return 0;
+ }
+
+ /* Main loop. */
+ while (d >= BITS_PER_MP_LIMB)
+ {
+ mp_limb_t q = up[0] * v_inv;
+ mp_limb_t b = mpn_submul_1 (up, vp, MIN (usize, vsize), q);
+ if (usize > vsize)
+ mpn_sub_1 (up + vsize, up + vsize, usize - vsize, b);
+ d -= BITS_PER_MP_LIMB;
+ up += 1, usize -= 1;
+ *qp++ = q;
+ }
+
+ if (d)
+ {
+ mp_limb_t b;
+ mp_limb_t q = (up[0] * v_inv) & (((mp_limb_t)1<<d) - 1);
+ switch (q)
+ {
+ case 0: return 0;
+ case 1: b = mpn_sub_n (up, up, vp, MIN (usize, vsize)); break;
+ default: b = mpn_submul_1 (up, vp, MIN (usize, vsize), q); break;
+ }
+ if (usize > vsize)
+ mpn_sub_1 (up + vsize, up + vsize, usize - vsize, b);
+ return q;
+ }
+
+ return 0;
+}
diff --git a/mpn/generic/cmp.c b/mpn/generic/cmp.c
new file mode 100644
index 000000000..4e9c60d86
--- /dev/null
+++ b/mpn/generic/cmp.c
@@ -0,0 +1,56 @@
+/* mpn_cmp -- Compare two low-level natural-number integers.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+/* Compare OP1_PTR/OP1_SIZE with OP2_PTR/OP2_SIZE.
+ There are no restrictions on the relative sizes of
+ the two arguments.
+ Return 1 if OP1 > OP2, 0 if they are equal, and -1 if OP1 < OP2. */
+
+int
+#if __STDC__
+mpn_cmp (mp_srcptr op1_ptr, mp_srcptr op2_ptr, mp_size_t size)
+#else
+mpn_cmp (op1_ptr, op2_ptr, size)
+ mp_srcptr op1_ptr;
+ mp_srcptr op2_ptr;
+ mp_size_t size;
+#endif
+{
+ mp_size_t i;
+ mp_limb_t op1_word, op2_word;
+
+ for (i = size - 1; i >= 0; i--)
+ {
+ op1_word = op1_ptr[i];
+ op2_word = op2_ptr[i];
+ if (op1_word != op2_word)
+ goto diff;
+ }
+ return 0;
+ diff:
+ /* This can *not* be simplified to
+ op2_word - op2_word
+ since that expression might give signed overflow. */
+ return (op1_word > op2_word) ? 1 : -1;
+}
diff --git a/mpn/generic/divmod_1.c b/mpn/generic/divmod_1.c
new file mode 100644
index 000000000..f93841f63
--- /dev/null
+++ b/mpn/generic/divmod_1.c
@@ -0,0 +1,208 @@
+/* mpn_divmod_1(quot_ptr, dividend_ptr, dividend_size, divisor_limb) --
+ Divide (DIVIDEND_PTR,,DIVIDEND_SIZE) by DIVISOR_LIMB.
+ Write DIVIDEND_SIZE limbs of quotient at QUOT_PTR.
+ Return the single-limb remainder.
+ There are no constraints on the value of the divisor.
+
+ QUOT_PTR and DIVIDEND_PTR might point to the same limb.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+#ifndef UMUL_TIME
+#define UMUL_TIME 1
+#endif
+
+#ifndef UDIV_TIME
+#define UDIV_TIME UMUL_TIME
+#endif
+
+/* FIXME: We should be using invert_limb (or invert_normalized_limb)
+ here (not udiv_qrnnd). */
+
+mp_limb_t
+#if __STDC__
+mpn_divmod_1 (mp_ptr quot_ptr,
+ mp_srcptr dividend_ptr, mp_size_t dividend_size,
+ mp_limb_t divisor_limb)
+#else
+mpn_divmod_1 (quot_ptr, dividend_ptr, dividend_size, divisor_limb)
+ mp_ptr quot_ptr;
+ mp_srcptr dividend_ptr;
+ mp_size_t dividend_size;
+ mp_limb_t divisor_limb;
+#endif
+{
+ mp_size_t i;
+ mp_limb_t n1, n0, r;
+ int dummy;
+
+ /* ??? Should this be handled at all? Rely on callers? */
+ if (dividend_size == 0)
+ return 0;
+
+ /* If multiplication is much faster than division, and the
+ dividend is large, pre-invert the divisor, and use
+ only multiplications in the inner loop. */
+
+ /* This test should be read:
+ Does it ever help to use udiv_qrnnd_preinv?
+ && Does what we save compensate for the inversion overhead? */
+ if (UDIV_TIME > (2 * UMUL_TIME + 6)
+ && (UDIV_TIME - (2 * UMUL_TIME + 6)) * dividend_size > UDIV_TIME)
+ {
+ int normalization_steps;
+
+ count_leading_zeros (normalization_steps, divisor_limb);
+ if (normalization_steps != 0)
+ {
+ mp_limb_t divisor_limb_inverted;
+
+ divisor_limb <<= normalization_steps;
+
+ /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The
+ result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the
+ most significant bit (with weight 2**N) implicit. */
+
+ /* Special case for DIVISOR_LIMB == 100...000. */
+ if (divisor_limb << 1 == 0)
+ divisor_limb_inverted = ~(mp_limb_t) 0;
+ else
+ udiv_qrnnd (divisor_limb_inverted, dummy,
+ -divisor_limb, 0, divisor_limb);
+
+ n1 = dividend_ptr[dividend_size - 1];
+ r = n1 >> (BITS_PER_MP_LIMB - normalization_steps);
+
+ /* Possible optimization:
+ if (r == 0
+ && divisor_limb > ((n1 << normalization_steps)
+ | (dividend_ptr[dividend_size - 2] >> ...)))
+ ...one division less... */
+
+ for (i = dividend_size - 2; i >= 0; i--)
+ {
+ n0 = dividend_ptr[i];
+ udiv_qrnnd_preinv (quot_ptr[i + 1], r, r,
+ ((n1 << normalization_steps)
+ | (n0 >> (BITS_PER_MP_LIMB - normalization_steps))),
+ divisor_limb, divisor_limb_inverted);
+ n1 = n0;
+ }
+ udiv_qrnnd_preinv (quot_ptr[0], r, r,
+ n1 << normalization_steps,
+ divisor_limb, divisor_limb_inverted);
+ return r >> normalization_steps;
+ }
+ else
+ {
+ mp_limb_t divisor_limb_inverted;
+
+ /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The
+ result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the
+ most significant bit (with weight 2**N) implicit. */
+
+ /* Special case for DIVISOR_LIMB == 100...000. */
+ if (divisor_limb << 1 == 0)
+ divisor_limb_inverted = ~(mp_limb_t) 0;
+ else
+ udiv_qrnnd (divisor_limb_inverted, dummy,
+ -divisor_limb, 0, divisor_limb);
+
+ i = dividend_size - 1;
+ r = dividend_ptr[i];
+
+ if (r >= divisor_limb)
+ r = 0;
+ else
+ {
+ quot_ptr[i] = 0;
+ i--;
+ }
+
+ for (; i >= 0; i--)
+ {
+ n0 = dividend_ptr[i];
+ udiv_qrnnd_preinv (quot_ptr[i], r, r,
+ n0, divisor_limb, divisor_limb_inverted);
+ }
+ return r;
+ }
+ }
+ else
+ {
+ if (UDIV_NEEDS_NORMALIZATION)
+ {
+ int normalization_steps;
+
+ count_leading_zeros (normalization_steps, divisor_limb);
+ if (normalization_steps != 0)
+ {
+ divisor_limb <<= normalization_steps;
+
+ n1 = dividend_ptr[dividend_size - 1];
+ r = n1 >> (BITS_PER_MP_LIMB - normalization_steps);
+
+ /* Possible optimization:
+ if (r == 0
+ && divisor_limb > ((n1 << normalization_steps)
+ | (dividend_ptr[dividend_size - 2] >> ...)))
+ ...one division less... */
+
+ for (i = dividend_size - 2; i >= 0; i--)
+ {
+ n0 = dividend_ptr[i];
+ udiv_qrnnd (quot_ptr[i + 1], r, r,
+ ((n1 << normalization_steps)
+ | (n0 >> (BITS_PER_MP_LIMB - normalization_steps))),
+ divisor_limb);
+ n1 = n0;
+ }
+ udiv_qrnnd (quot_ptr[0], r, r,
+ n1 << normalization_steps,
+ divisor_limb);
+ return r >> normalization_steps;
+ }
+ }
+ /* No normalization needed, either because udiv_qrnnd doesn't require
+ it, or because DIVISOR_LIMB is already normalized. */
+
+ i = dividend_size - 1;
+ r = dividend_ptr[i];
+
+ if (r >= divisor_limb)
+ r = 0;
+ else
+ {
+ quot_ptr[i] = 0;
+ i--;
+ }
+
+ for (; i >= 0; i--)
+ {
+ n0 = dividend_ptr[i];
+ udiv_qrnnd (quot_ptr[i], r, r, n0, divisor_limb);
+ }
+ return r;
+ }
+}
diff --git a/mpn/generic/divrem.c b/mpn/generic/divrem.c
new file mode 100644
index 000000000..1fe865a10
--- /dev/null
+++ b/mpn/generic/divrem.c
@@ -0,0 +1,245 @@
+/* mpn_divrem -- Divide natural numbers, producing both remainder and
+ quotient.
+
+Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+/* Divide num (NP/NSIZE) by den (DP/DSIZE) and write
+ the NSIZE-DSIZE least significant quotient limbs at QP
+ and the DSIZE long remainder at NP. If QEXTRA_LIMBS is
+ non-zero, generate that many fraction bits and append them after the
+ other quotient limbs.
+ Return the most significant limb of the quotient, this is always 0 or 1.
+
+ Preconditions:
+ 0. NSIZE >= DSIZE.
+ 1. The most significant bit of the divisor must be set.
+ 2. QP must either not overlap with the input operands at all, or
+ QP + DSIZE >= NP must hold true. (This means that it's
+ possible to put the quotient in the high part of NUM, right after the
+ remainder in NUM.
+ 3. NSIZE >= DSIZE, even if QEXTRA_LIMBS is non-zero. */
+
+mp_limb_t
+#if __STDC__
+mpn_divrem (mp_ptr qp, mp_size_t qextra_limbs,
+ mp_ptr np, mp_size_t nsize,
+ mp_srcptr dp, mp_size_t dsize)
+#else
+mpn_divrem (qp, qextra_limbs, np, nsize, dp, dsize)
+ mp_ptr qp;
+ mp_size_t qextra_limbs;
+ mp_ptr np;
+ mp_size_t nsize;
+ mp_srcptr dp;
+ mp_size_t dsize;
+#endif
+{
+ mp_limb_t most_significant_q_limb = 0;
+
+ switch (dsize)
+ {
+ case 0:
+ /* We are asked to divide by zero, so go ahead and do it! (To make
+ the compiler not remove this statement, return the value.) */
+ return 1 / dsize;
+
+ case 1:
+ {
+ mp_size_t i;
+ mp_limb_t n1;
+ mp_limb_t d;
+
+ d = dp[0];
+ n1 = np[nsize - 1];
+
+ if (n1 >= d)
+ {
+ n1 -= d;
+ most_significant_q_limb = 1;
+ }
+
+ qp += qextra_limbs;
+ for (i = nsize - 2; i >= 0; i--)
+ udiv_qrnnd (qp[i], n1, n1, np[i], d);
+ qp -= qextra_limbs;
+
+ for (i = qextra_limbs - 1; i >= 0; i--)
+ udiv_qrnnd (qp[i], n1, n1, 0, d);
+
+ np[0] = n1;
+ }
+ break;
+
+ case 2:
+ {
+ mp_size_t i;
+ mp_limb_t n1, n0, n2;
+ mp_limb_t d1, d0;
+
+ np += nsize - 2;
+ d1 = dp[1];
+ d0 = dp[0];
+ n1 = np[1];
+ n0 = np[0];
+
+ if (n1 >= d1 && (n1 > d1 || n0 >= d0))
+ {
+ sub_ddmmss (n1, n0, n1, n0, d1, d0);
+ most_significant_q_limb = 1;
+ }
+
+ for (i = qextra_limbs + nsize - 2 - 1; i >= 0; i--)
+ {
+ mp_limb_t q;
+ mp_limb_t r;
+
+ if (i >= qextra_limbs)
+ np--;
+ else
+ np[0] = 0;
+
+ if (n1 == d1)
+ {
+ /* Q should be either 111..111 or 111..110. Need special
+ treatment of this rare case as normal division would
+ give overflow. */
+ q = ~(mp_limb_t) 0;
+
+ r = n0 + d1;
+ if (r < d1) /* Carry in the addition? */
+ {
+ add_ssaaaa (n1, n0, r - d0, np[0], 0, d0);
+ qp[i] = q;
+ continue;
+ }
+ n1 = d0 - (d0 != 0);
+ n0 = -d0;
+ }
+ else
+ {
+ udiv_qrnnd (q, r, n1, n0, d1);
+ umul_ppmm (n1, n0, d0, q);
+ }
+
+ n2 = np[0];
+ q_test:
+ if (n1 > r || (n1 == r && n0 > n2))
+ {
+ /* The estimated Q was too large. */
+ q--;
+
+ sub_ddmmss (n1, n0, n1, n0, 0, d0);
+ r += d1;
+ if (r >= d1) /* If not carry, test Q again. */
+ goto q_test;
+ }
+
+ qp[i] = q;
+ sub_ddmmss (n1, n0, r, n2, n1, n0);
+ }
+ np[1] = n1;
+ np[0] = n0;
+ }
+ break;
+
+ default:
+ {
+ mp_size_t i;
+ mp_limb_t dX, d1, n0;
+
+ np += nsize - dsize;
+ dX = dp[dsize - 1];
+ d1 = dp[dsize - 2];
+ n0 = np[dsize - 1];
+
+ if (n0 >= dX)
+ {
+ if (n0 > dX || mpn_cmp (np, dp, dsize - 1) >= 0)
+ {
+ mpn_sub_n (np, np, dp, dsize);
+ n0 = np[dsize - 1];
+ most_significant_q_limb = 1;
+ }
+ }
+
+ for (i = qextra_limbs + nsize - dsize - 1; i >= 0; i--)
+ {
+ mp_limb_t q;
+ mp_limb_t n1, n2;
+ mp_limb_t cy_limb;
+
+ if (i >= qextra_limbs)
+ {
+ np--;
+ n2 = np[dsize];
+ }
+ else
+ {
+ n2 = np[dsize - 1];
+ MPN_COPY_DECR (np + 1, np, dsize);
+ np[0] = 0;
+ }
+
+ if (n0 == dX)
+ /* This might over-estimate q, but it's probably not worth
+ the extra code here to find out. */
+ q = ~(mp_limb_t) 0;
+ else
+ {
+ mp_limb_t r;
+
+ udiv_qrnnd (q, r, n0, np[dsize - 1], dX);
+ umul_ppmm (n1, n0, d1, q);
+
+ while (n1 > r || (n1 == r && n0 > np[dsize - 2]))
+ {
+ q--;
+ r += dX;
+ if (r < dX) /* I.e. "carry in previous addition?" */
+ break;
+ n1 -= n0 < d1;
+ n0 -= d1;
+ }
+ }
+
+ /* Possible optimization: We already have (q * n0) and (1 * n1)
+ after the calculation of q. Taking advantage of that, we
+ could make this loop make two iterations less. */
+
+ cy_limb = mpn_submul_1 (np, dp, dsize, q);
+
+ if (n2 != cy_limb)
+ {
+ mpn_add_n (np, np, dp, dsize);
+ q--;
+ }
+
+ qp[i] = q;
+ n0 = np[dsize - 1];
+ }
+ }
+ }
+
+ return most_significant_q_limb;
+}
diff --git a/mpn/generic/divrem_1.c b/mpn/generic/divrem_1.c
new file mode 100644
index 000000000..d21326738
--- /dev/null
+++ b/mpn/generic/divrem_1.c
@@ -0,0 +1,58 @@
+/* mpn_divrem_1(quot_ptr, qsize, dividend_ptr, dividend_size, divisor_limb) --
+ Divide (DIVIDEND_PTR,,DIVIDEND_SIZE) by DIVISOR_LIMB.
+ Write DIVIDEND_SIZE limbs of quotient at QUOT_PTR.
+ Return the single-limb remainder.
+ There are no constraints on the value of the divisor.
+
+ QUOT_PTR and DIVIDEND_PTR might point to the same limb.
+
+Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+mp_limb_t
+#if __STDC__
+mpn_divrem_1 (mp_ptr qp, mp_size_t qsize,
+ mp_srcptr dividend_ptr, mp_size_t dividend_size,
+ mp_limb_t divisor_limb)
+#else
+mpn_divrem_1 (qp, qsize, dividend_ptr, dividend_size, divisor_limb)
+ mp_ptr qp;
+ mp_size_t qsize;
+ mp_srcptr dividend_ptr;
+ mp_size_t dividend_size;
+ mp_limb_t divisor_limb;
+#endif
+{
+ mp_limb_t rlimb;
+ long i;
+
+ /* Develop integer part of quotient. */
+ rlimb = mpn_divmod_1 (qp + qsize, dividend_ptr, dividend_size, divisor_limb);
+
+ if (qsize != 0)
+ {
+ for (i = qsize - 1; i >= 0; i--)
+ udiv_qrnnd (qp[i], rlimb, rlimb, 0, divisor_limb);
+ }
+ return rlimb;
+}
diff --git a/mpn/generic/dump.c b/mpn/generic/dump.c
new file mode 100644
index 000000000..a5831c4cc
--- /dev/null
+++ b/mpn/generic/dump.c
@@ -0,0 +1,20 @@
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+mpn_dump (ptr, size)
+ mp_srcptr ptr;
+ mp_size_t size;
+{
+ if (size == 0)
+ printf ("0\n");
+ {
+ while (size)
+ {
+ size--;
+ printf ("%0*lX", (int) (2 * BYTES_PER_MP_LIMB), ptr[size]);
+ }
+ printf ("\n");
+ }
+}
diff --git a/mpn/generic/gcd.c b/mpn/generic/gcd.c
new file mode 100644
index 000000000..4a364e526
--- /dev/null
+++ b/mpn/generic/gcd.c
@@ -0,0 +1,402 @@
+/* mpn/gcd.c: mpn_gcd for gcd of two odd integers.
+
+Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/* Integer greatest common divisor of two unsigned integers, using
+ the accelerated algorithm (see reference below).
+
+ mp_size_t mpn_gcd (vp, vsize, up, usize).
+
+ Preconditions [U = (up, usize) and V = (vp, vsize)]:
+
+ 1. V is odd.
+ 2. numbits(U) >= numbits(V).
+
+ Both U and V are destroyed by the operation. The result is left at vp,
+ and its size is returned.
+
+ Ken Weber (kweber@mat.ufrgs.br, kweber@mcs.kent.edu)
+
+ Funding for this work has been partially provided by Conselho Nacional
+ de Desenvolvimento Cienti'fico e Tecnolo'gico (CNPq) do Brazil, Grant
+ 301314194-2, and was done while I was a visiting reseacher in the Instituto
+ de Matema'tica at Universidade Federal do Rio Grande do Sul (UFRGS).
+
+ Refer to
+ K. Weber, The accelerated integer GCD algorithm, ACM Transactions on
+ Mathematical Software, v. 21 (March), 1995, pp. 111-122. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+/* If MIN (usize, vsize) > ACCEL_THRESHOLD, then the accelerated algorithm is
+ used, otherwise the binary algorithm is used. This may be adjusted for
+ different architectures. */
+#ifndef ACCEL_THRESHOLD
+#define ACCEL_THRESHOLD 4
+#endif
+
+/* When U and V differ in size by more than BMOD_THRESHOLD, the accelerated
+ algorithm reduces using the bmod operation. Otherwise, the k-ary reduction
+ is used. 0 <= BMOD_THRESHOLD < BITS_PER_MP_LIMB. */
+enum
+ {
+ BMOD_THRESHOLD = BITS_PER_MP_LIMB/2,
+ };
+
+#define SIGN_BIT (~(~(mp_limb_t)0 >> 1))
+
+
+#define SWAP_LIMB(UL, VL) do{mp_limb_t __l=(UL);(UL)=(VL);(VL)=__l;}while(0)
+#define SWAP_PTR(UP, VP) do{mp_ptr __p=(UP);(UP)=(VP);(VP)=__p;}while(0)
+#define SWAP_SZ(US, VS) do{mp_size_t __s=(US);(US)=(VS);(VS)=__s;}while(0)
+#define SWAP_MPN(UP, US, VP, VS) do{SWAP_PTR(UP,VP);SWAP_SZ(US,VS);}while(0)
+
+/* Use binary algorithm to compute V <-- GCD (V, U) for usize, vsize == 2.
+ Both U and V must be odd. */
+static __gmp_inline mp_size_t
+#if __STDC__
+gcd_2 (mp_ptr vp, mp_srcptr up)
+#else
+gcd_2 (vp, up)
+ mp_ptr vp;
+ mp_srcptr up;
+#endif
+{
+ mp_limb_t u0, u1, v0, v1;
+ mp_size_t vsize;
+
+ u0 = up[0], u1 = up[1], v0 = vp[0], v1 = vp[1];
+
+ while (u1 != v1 && u0 != v0)
+ {
+ unsigned long int r;
+ if (u1 > v1)
+ {
+ u1 -= v1 + (u0 < v0), u0 -= v0;
+ count_trailing_zeros (r, u0);
+ u0 = u1 << (BITS_PER_MP_LIMB - r) | u0 >> r;
+ u1 >>= r;
+ }
+ else /* u1 < v1. */
+ {
+ v1 -= u1 + (v0 < u0), v0 -= u0;
+ count_trailing_zeros (r, v0);
+ v0 = v1 << (BITS_PER_MP_LIMB - r) | v0 >> r;
+ v1 >>= r;
+ }
+ }
+
+ vp[0] = v0, vp[1] = v1, vsize = 1 + (v1 != 0);
+
+ /* If U == V == GCD, done. Otherwise, compute GCD (V, |U - V|). */
+ if (u1 == v1 && u0 == v0)
+ return vsize;
+
+ v0 = (u0 == v0) ? (u1 > v1) ? u1-v1 : v1-u1 : (u0 > v0) ? u0-v0 : v0-u0;
+ vp[0] = mpn_gcd_1 (vp, vsize, v0);
+
+ return 1;
+}
+
+/* The function find_a finds 0 < N < 2^BITS_PER_MP_LIMB such that there exists
+ 0 < |D| < 2^BITS_PER_MP_LIMB, and N == D * C mod 2^(2*BITS_PER_MP_LIMB).
+ In the reference article, D was computed along with N, but it is better to
+ compute D separately as D <-- N / C mod 2^(BITS_PER_MP_LIMB + 1), treating
+ the result as a twos' complement signed integer.
+
+ Initialize N1 to C mod 2^(2*BITS_PER_MP_LIMB). According to the reference
+ article, N2 should be initialized to 2^(2*BITS_PER_MP_LIMB), but we use
+ 2^(2*BITS_PER_MP_LIMB) - N1 to start the calculations within double
+ precision. If N2 > N1 initially, the first iteration of the while loop
+ will swap them. In all other situations, N1 >= N2 is maintained. */
+
+static __gmp_inline mp_limb_t
+#if __STDC__
+find_a (mp_srcptr cp)
+#else
+find_a (cp)
+ mp_srcptr cp;
+#endif
+{
+ unsigned long int leading_zero_bits = 0;
+
+ mp_limb_t n1_l = cp[0]; /* N1 == n1_h * 2^BITS_PER_MP_LIMB + n1_l. */
+ mp_limb_t n1_h = cp[1];
+
+ mp_limb_t n2_l = -n1_l; /* N2 == n2_h * 2^BITS_PER_MP_LIMB + n2_l. */
+ mp_limb_t n2_h = ~n1_h;
+
+ /* Main loop. */
+ while (n2_h) /* While N2 >= 2^BITS_PER_MP_LIMB. */
+ {
+ /* N1 <-- N1 % N2. */
+ if ((SIGN_BIT >> leading_zero_bits & n2_h) == 0)
+ {
+ unsigned long int i;
+ count_leading_zeros (i, n2_h);
+ i -= leading_zero_bits, leading_zero_bits += i;
+ n2_h = n2_h<<i | n2_l>>(BITS_PER_MP_LIMB - i), n2_l <<= i;
+ do
+ {
+ if (n1_h > n2_h || (n1_h == n2_h && n1_l >= n2_l))
+ n1_h -= n2_h + (n1_l < n2_l), n1_l -= n2_l;
+ n2_l = n2_l>>1 | n2_h<<(BITS_PER_MP_LIMB - 1), n2_h >>= 1;
+ i -= 1;
+ }
+ while (i);
+ }
+ if (n1_h > n2_h || (n1_h == n2_h && n1_l >= n2_l))
+ n1_h -= n2_h + (n1_l < n2_l), n1_l -= n2_l;
+
+ SWAP_LIMB (n1_h, n2_h);
+ SWAP_LIMB (n1_l, n2_l);
+ }
+
+ return n2_l;
+}
+
+mp_size_t
+#if __STDC__
+mpn_gcd (mp_ptr gp, mp_ptr vp, mp_size_t vsize, mp_ptr up, mp_size_t usize)
+#else
+mpn_gcd (gp, vp, vsize, up, usize)
+ mp_ptr gp;
+ mp_ptr vp;
+ mp_size_t vsize;
+ mp_ptr up;
+ mp_size_t usize;
+#endif
+{
+ mp_ptr orig_vp = vp;
+ mp_size_t orig_vsize = vsize;
+ int binary_gcd_ctr; /* Number of times binary gcd will execute. */
+ TMP_DECL (marker);
+
+ TMP_MARK (marker);
+
+ /* Use accelerated algorithm if vsize is over ACCEL_THRESHOLD.
+ Two EXTRA limbs for U and V are required for kary reduction. */
+ if (vsize > ACCEL_THRESHOLD)
+ {
+ unsigned long int vbitsize, d;
+ mp_ptr orig_up = up;
+ mp_size_t orig_usize = usize;
+ mp_ptr anchor_up = (mp_ptr) TMP_ALLOC ((usize + 2) * BYTES_PER_MP_LIMB);
+
+ MPN_COPY (anchor_up, orig_up, usize);
+ up = anchor_up;
+
+ count_leading_zeros (d, up[usize-1]);
+ d = usize * BITS_PER_MP_LIMB - d;
+ count_leading_zeros (vbitsize, vp[vsize-1]);
+ vbitsize = vsize * BITS_PER_MP_LIMB - vbitsize;
+ d = d - vbitsize + 1;
+
+ /* Use bmod reduction to quickly discover whether V divides U. */
+ up[usize++] = 0; /* Insert leading zero. */
+ mpn_bdivmod (up, up, usize, vp, vsize, d);
+
+ /* Now skip U/V mod 2^d and any low zero limbs. */
+ d /= BITS_PER_MP_LIMB, up += d, usize -= d;
+ while (usize != 0 && up[0] == 0)
+ up++, usize--;
+
+ if (usize == 0) /* GCD == ORIG_V. */
+ goto done;
+
+ vp = (mp_ptr) TMP_ALLOC ((vsize + 2) * BYTES_PER_MP_LIMB);
+ MPN_COPY (vp, orig_vp, vsize);
+
+ do /* Main loop. */
+ {
+ if (up[usize-1] & SIGN_BIT) /* U < 0; take twos' compl. */
+ {
+ mp_size_t i;
+ anchor_up[0] = -up[0];
+ for (i = 1; i < usize; i++)
+ anchor_up[i] = ~up[i];
+ up = anchor_up;
+ }
+
+ MPN_NORMALIZE_NOT_ZERO (up, usize);
+
+ if ((up[0] & 1) == 0) /* Result even; remove twos. */
+ {
+ unsigned long int r;
+ count_trailing_zeros (r, up[0]);
+ mpn_rshift (anchor_up, up, usize, r);
+ usize -= (anchor_up[usize-1] == 0);
+ }
+ else if (anchor_up != up)
+ MPN_COPY (anchor_up, up, usize);
+
+ SWAP_MPN (anchor_up, usize, vp, vsize);
+ up = anchor_up;
+
+ if (vsize <= 2) /* Kary can't handle < 2 limbs and */
+ break; /* isn't efficient for == 2 limbs. */
+
+ d = vbitsize;
+ count_leading_zeros (vbitsize, vp[vsize-1]);
+ vbitsize = vsize * BITS_PER_MP_LIMB - vbitsize;
+ d = d - vbitsize + 1;
+
+ if (d > BMOD_THRESHOLD) /* Bmod reduction. */
+ {
+ up[usize++] = 0;
+ mpn_bdivmod (up, up, usize, vp, vsize, d);
+ d /= BITS_PER_MP_LIMB, up += d, usize -= d;
+ }
+ else /* Kary reduction. */
+ {
+ mp_limb_t bp[2], cp[2];
+
+ /* C <-- V/U mod 2^(2*BITS_PER_MP_LIMB). */
+ cp[0] = vp[0], cp[1] = vp[1];
+ mpn_bdivmod (cp, cp, 2, up, 2, 2*BITS_PER_MP_LIMB);
+
+ /* U <-- find_a (C) * U. */
+ up[usize] = mpn_mul_1 (up, up, usize, find_a (cp));
+ usize++;
+
+ /* B <-- A/C == U/V mod 2^(BITS_PER_MP_LIMB + 1).
+ bp[0] <-- U/V mod 2^BITS_PER_MP_LIMB and
+ bp[1] <-- ( (U - bp[0] * V)/2^BITS_PER_MP_LIMB ) / V mod 2. */
+ bp[0] = up[0], bp[1] = up[1];
+ mpn_bdivmod (bp, bp, 2, vp, 2, BITS_PER_MP_LIMB);
+ bp[1] &= 1; /* Since V is odd, division is unnecessary. */
+
+ up[usize++] = 0;
+ if (bp[1]) /* B < 0: U <-- U + (-B) * V. */
+ {
+ mp_limb_t c = mpn_addmul_1 (up, vp, vsize, -bp[0]);
+ mpn_add_1 (up + vsize, up + vsize, usize - vsize, c);
+ }
+ else /* B >= 0: U <-- U - B * V. */
+ {
+ mp_limb_t b = mpn_submul_1 (up, vp, vsize, bp[0]);
+ mpn_sub_1 (up + vsize, up + vsize, usize - vsize, b);
+ }
+
+ up += 2, usize -= 2; /* At least two low limbs are zero. */
+ }
+
+ /* Must remove low zero limbs before complementing. */
+ while (usize != 0 && up[0] == 0)
+ up++, usize--;
+ }
+ while (usize);
+
+ /* Compute GCD (ORIG_V, GCD (ORIG_U, V)). Binary will execute twice. */
+ up = orig_up, usize = orig_usize;
+ binary_gcd_ctr = 2;
+ }
+ else
+ binary_gcd_ctr = 1;
+
+ /* Finish up with the binary algorithm. Executes once or twice. */
+ for ( ; binary_gcd_ctr--; up = orig_vp, usize = orig_vsize)
+ {
+ if (usize > 2) /* First make U close to V in size. */
+ {
+ unsigned long int vbitsize, d;
+ count_leading_zeros (d, up[usize-1]);
+ d = usize * BITS_PER_MP_LIMB - d;
+ count_leading_zeros (vbitsize, vp[vsize-1]);
+ vbitsize = vsize * BITS_PER_MP_LIMB - vbitsize;
+ d = d - vbitsize - 1;
+ if (d != -(unsigned long int)1 && d > 2)
+ {
+ mpn_bdivmod (up, up, usize, vp, vsize, d); /* Result > 0. */
+ d /= (unsigned long int)BITS_PER_MP_LIMB, up += d, usize -= d;
+ }
+ }
+
+ /* Start binary GCD. */
+ do
+ {
+ mp_size_t zeros;
+
+ /* Make sure U is odd. */
+ MPN_NORMALIZE (up, usize);
+ while (up[0] == 0)
+ up += 1, usize -= 1;
+ if ((up[0] & 1) == 0)
+ {
+ unsigned long int r;
+ count_trailing_zeros (r, up[0]);
+ mpn_rshift (up, up, usize, r);
+ usize -= (up[usize-1] == 0);
+ }
+
+ /* Keep usize >= vsize. */
+ if (usize < vsize)
+ SWAP_MPN (up, usize, vp, vsize);
+
+ if (usize <= 2) /* Double precision. */
+ {
+ if (vsize == 1)
+ vp[0] = mpn_gcd_1 (up, usize, vp[0]);
+ else
+ vsize = gcd_2 (vp, up);
+ break; /* Binary GCD done. */
+ }
+
+ /* Count number of low zero limbs of U - V. */
+ for (zeros = 0; up[zeros] == vp[zeros] && ++zeros != vsize; )
+ continue;
+
+ /* If U < V, swap U and V; in any case, subtract V from U. */
+ if (zeros == vsize) /* Subtract done. */
+ up += zeros, usize -= zeros;
+ else if (usize == vsize)
+ {
+ mp_size_t size = vsize;
+ do
+ size--;
+ while (up[size] == vp[size]);
+ if (up[size] < vp[size]) /* usize == vsize. */
+ SWAP_PTR (up, vp);
+ up += zeros, usize = size + 1 - zeros;
+ mpn_sub_n (up, up, vp + zeros, usize);
+ }
+ else
+ {
+ mp_size_t size = vsize - zeros;
+ up += zeros, usize -= zeros;
+ if (mpn_sub_n (up, up, vp + zeros, size))
+ {
+ while (up[size] == 0) /* Propagate borrow. */
+ up[size++] = -(mp_limb_t)1;
+ up[size] -= 1;
+ }
+ }
+ }
+ while (usize); /* End binary GCD. */
+ }
+
+done:
+ if (vp != gp)
+ MPN_COPY (gp, vp, vsize);
+ TMP_FREE (marker);
+ return vsize;
+}
diff --git a/mpn/generic/gcd_1.c b/mpn/generic/gcd_1.c
new file mode 100644
index 000000000..ebcdfb591
--- /dev/null
+++ b/mpn/generic/gcd_1.c
@@ -0,0 +1,73 @@
+/* mpn_gcd_1 --
+
+Copyright (C) 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+/* Does not work for U == 0 or V == 0. It would be tough to make it work for
+ V == 0 since gcd(x,0) = x, and U does not generally fit in an mp_limb_t. */
+
+mp_limb_t
+mpn_gcd_1 (up, size, vlimb)
+ mp_srcptr up;
+ mp_size_t size;
+ mp_limb_t vlimb;
+{
+ mp_limb_t ulimb;
+ unsigned long int u_low_zero_bits, v_low_zero_bits;
+
+ if (size > 1)
+ {
+ ulimb = mpn_mod_1 (up, size, vlimb);
+ if (ulimb == 0)
+ return vlimb;
+ }
+ else
+ ulimb = up[0];
+
+ /* Need to eliminate low zero bits. */
+ count_trailing_zeros (u_low_zero_bits, ulimb);
+ ulimb >>= u_low_zero_bits;
+
+ count_trailing_zeros (v_low_zero_bits, vlimb);
+ vlimb >>= v_low_zero_bits;
+
+ while (ulimb != vlimb)
+ {
+ if (ulimb > vlimb)
+ {
+ ulimb -= vlimb;
+ do
+ ulimb >>= 1;
+ while ((ulimb & 1) == 0);
+ }
+ else /* vlimb > ulimb. */
+ {
+ vlimb -= ulimb;
+ do
+ vlimb >>= 1;
+ while ((vlimb & 1) == 0);
+ }
+ }
+
+ return ulimb << MIN (u_low_zero_bits, v_low_zero_bits);
+}
diff --git a/mpn/generic/gcdext.c b/mpn/generic/gcdext.c
new file mode 100644
index 000000000..f54b7b785
--- /dev/null
+++ b/mpn/generic/gcdext.c
@@ -0,0 +1,422 @@
+/* mpn_gcdext -- Extended Greatest Common Divisor.
+
+Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+#ifndef EXTEND
+#define EXTEND 1
+#endif
+
+#if STAT
+int arr[BITS_PER_MP_LIMB];
+#endif
+
+#define SGN(A) (((A) < 0) ? -1 : ((A) > 0))
+
+/* Idea 1: After we have performed a full division, don't shift operands back,
+ but instead account for the extra factors-of-2 thus introduced.
+ Idea 2: Simple generalization to use divide-and-conquer would give us an
+ algorithm that runs faster than O(n^2).
+ Idea 3: The input numbers need less space as the computation progresses,
+ while the s0 and s1 variables need more space. To save space, we
+ could make them share space, and have the latter variables grow
+ into the former. */
+
+/* Precondition: U >= V. */
+
+mp_size_t
+#if EXTEND
+mpn_gcdext (mp_ptr gp, mp_ptr s0p,
+ mp_ptr up, mp_size_t size, mp_ptr vp, mp_size_t vsize)
+#else
+mpn_gcd (mp_ptr gp,
+ mp_ptr up, mp_size_t size, mp_ptr vp, mp_size_t vsize)
+#endif
+{
+ mp_limb_t uh, vh;
+ mp_limb_signed_t A, B, C, D;
+ int cnt;
+ mp_ptr tp, wp;
+#if RECORD
+ mp_limb_signed_t min = 0, max = 0;
+#endif
+#if EXTEND
+ mp_ptr s1p;
+ mp_ptr orig_s0p = s0p;
+ mp_size_t ssize, orig_size = size;
+ TMP_DECL (mark);
+
+ TMP_MARK (mark);
+
+ tp = (mp_ptr) TMP_ALLOC ((size + 1) * BYTES_PER_MP_LIMB);
+ wp = (mp_ptr) TMP_ALLOC ((size + 1) * BYTES_PER_MP_LIMB);
+ s1p = (mp_ptr) TMP_ALLOC (size * BYTES_PER_MP_LIMB);
+
+ MPN_ZERO (s0p, size);
+ MPN_ZERO (s1p, size);
+
+ s0p[0] = 1;
+ s1p[0] = 0;
+ ssize = 1;
+#endif
+
+ if (size > vsize)
+ {
+ /* Normalize V (and shift up U the same amount). */
+ count_leading_zeros (cnt, vp[vsize - 1]);
+ if (cnt != 0)
+ {
+ mp_limb_t cy;
+ mpn_lshift (vp, vp, vsize, cnt);
+ cy = mpn_lshift (up, up, size, cnt);
+ up[size] = cy;
+ size += cy != 0;
+ }
+
+ mpn_divmod (up + vsize, up, size, vp, vsize);
+#if EXTEND
+ /* This is really what it boils down to in this case... */
+ s0p[0] = 0;
+ s1p[0] = 1;
+#endif
+ size = vsize;
+ if (cnt != 0)
+ {
+ mpn_rshift (up, up, size, cnt);
+ mpn_rshift (vp, vp, size, cnt);
+ }
+ {
+ mp_ptr xp;
+ xp = up; up = vp; vp = xp;
+ }
+ }
+
+ for (;;)
+ {
+ /* Figure out exact size of V. */
+ vsize = size;
+ MPN_NORMALIZE (vp, vsize);
+ if (vsize <= 1)
+ break;
+
+ /* Make UH be the most significant limb of U, and make VH be
+ corresponding bits from V. */
+ uh = up[size - 1];
+ vh = vp[size - 1];
+ count_leading_zeros (cnt, uh);
+ if (cnt != 0)
+ {
+ uh = (uh << cnt) | (up[size - 2] >> (BITS_PER_MP_LIMB - cnt));
+ vh = (vh << cnt) | (vp[size - 2] >> (BITS_PER_MP_LIMB - cnt));
+ }
+
+#if 0
+ /* For now, only handle BITS_PER_MP_LIMB-1 bits. This makes
+ room for sign bit. */
+ uh >>= 1;
+ vh >>= 1;
+#endif
+ A = 1;
+ B = 0;
+ C = 0;
+ D = 1;
+
+ for (;;)
+ {
+ mp_limb_signed_t q, T;
+ if (vh + C == 0 || vh + D == 0)
+ break;
+
+ q = (uh + A) / (vh + C);
+ if (q != (uh + B) / (vh + D))
+ break;
+
+ T = A - q * C;
+ A = C;
+ C = T;
+ T = B - q * D;
+ B = D;
+ D = T;
+ T = uh - q * vh;
+ uh = vh;
+ vh = T;
+ }
+
+#if RECORD
+ min = MIN (A, min); min = MIN (B, min);
+ min = MIN (C, min); min = MIN (D, min);
+ max = MAX (A, max); max = MAX (B, max);
+ max = MAX (C, max); max = MAX (D, max);
+#endif
+
+ if (B == 0)
+ {
+ mp_limb_t qh;
+ mp_size_t i;
+
+ /* This is quite rare. I.e., optimize something else! */
+
+ /* Normalize V (and shift up U the same amount). */
+ count_leading_zeros (cnt, vp[vsize - 1]);
+ if (cnt != 0)
+ {
+ mp_limb_t cy;
+ mpn_lshift (vp, vp, vsize, cnt);
+ cy = mpn_lshift (up, up, size, cnt);
+ up[size] = cy;
+ size += cy != 0;
+ }
+
+ qh = mpn_divmod (up + vsize, up, size, vp, vsize);
+#if EXTEND
+ MPN_COPY (tp, s0p, ssize);
+ for (i = 0; i < size - vsize; i++)
+ {
+ mp_limb_t cy;
+ cy = mpn_addmul_1 (tp + i, s1p, ssize, up[vsize + i]);
+ if (cy != 0)
+ tp[ssize++] = cy;
+ }
+ if (qh != 0)
+ {
+ mp_limb_t cy;
+ abort ();
+ /* XXX since qh == 1, mpn_addmul_1 is overkill */
+ cy = mpn_addmul_1 (tp + size - vsize, s1p, ssize, qh);
+ if (cy != 0)
+ tp[ssize++] = cy;
+ }
+#if 0
+ MPN_COPY (s0p, s1p, ssize); /* should be old ssize, kind of */
+ MPN_COPY (s1p, tp, ssize);
+#else
+ {
+ mp_ptr xp;
+ xp = s0p; s0p = s1p; s1p = xp;
+ xp = s1p; s1p = tp; tp = xp;
+ }
+#endif
+#endif
+ size = vsize;
+ if (cnt != 0)
+ {
+ mpn_rshift (up, up, size, cnt);
+ mpn_rshift (vp, vp, size, cnt);
+ }
+
+ {
+ mp_ptr xp;
+ xp = up; up = vp; vp = xp;
+ }
+ MPN_NORMALIZE (up, size);
+ }
+ else
+ {
+ /* T = U*A + V*B
+ W = U*C + V*D
+ U = T
+ V = W */
+
+ if (SGN(A) == SGN(B)) /* should be different sign */
+ abort ();
+ if (SGN(C) == SGN(D)) /* should be different sign */
+ abort ();
+#if STAT
+ { mp_limb_t x;
+ x = ABS (A) | ABS (B) | ABS (C) | ABS (D);
+ count_leading_zeros (cnt, x);
+ arr[BITS_PER_MP_LIMB - cnt]++; }
+#endif
+ if (A == 0)
+ {
+ if (B != 1) abort ();
+ MPN_COPY (tp, vp, size);
+ }
+ else
+ {
+ if (A < 0)
+ {
+ mpn_mul_1 (tp, vp, size, B);
+ mpn_submul_1 (tp, up, size, -A);
+ }
+ else
+ {
+ mpn_mul_1 (tp, up, size, A);
+ mpn_submul_1 (tp, vp, size, -B);
+ }
+ }
+ if (C < 0)
+ {
+ mpn_mul_1 (wp, vp, size, D);
+ mpn_submul_1 (wp, up, size, -C);
+ }
+ else
+ {
+ mpn_mul_1 (wp, up, size, C);
+ mpn_submul_1 (wp, vp, size, -D);
+ }
+
+ {
+ mp_ptr xp;
+ xp = tp; tp = up; up = xp;
+ xp = wp; wp = vp; vp = xp;
+ }
+
+#if EXTEND
+ { mp_limb_t cy;
+ MPN_ZERO (tp, orig_size);
+ if (A == 0)
+ {
+ if (B != 1) abort ();
+ MPN_COPY (tp, s1p, ssize);
+ }
+ else
+ {
+ if (A < 0)
+ {
+ cy = mpn_mul_1 (tp, s1p, ssize, B);
+ cy += mpn_addmul_1 (tp, s0p, ssize, -A);
+ }
+ else
+ {
+ cy = mpn_mul_1 (tp, s0p, ssize, A);
+ cy += mpn_addmul_1 (tp, s1p, ssize, -B);
+ }
+ if (cy != 0)
+ tp[ssize++] = cy;
+ }
+ MPN_ZERO (wp, orig_size);
+ if (C < 0)
+ {
+ cy = mpn_mul_1 (wp, s1p, ssize, D);
+ cy += mpn_addmul_1 (wp, s0p, ssize, -C);
+ }
+ else
+ {
+ cy = mpn_mul_1 (wp, s0p, ssize, C);
+ cy += mpn_addmul_1 (wp, s1p, ssize, -D);
+ }
+ if (cy != 0)
+ wp[ssize++] = cy;
+ }
+ {
+ mp_ptr xp;
+ xp = tp; tp = s0p; s0p = xp;
+ xp = wp; wp = s1p; s1p = xp;
+ }
+#endif
+#if 0 /* Is it a win to remove multiple zeros here? */
+ MPN_NORMALIZE (up, size);
+#else
+ if (up[size - 1] == 0)
+ size--;
+#endif
+ }
+ }
+
+#if RECORD
+ printf ("min: %ld\n", min);
+ printf ("max: %ld\n", max);
+#endif
+
+ if (vsize == 0)
+ {
+ if (gp != up)
+ MPN_COPY (gp, up, size);
+#if EXTEND
+ if (orig_s0p != s0p)
+ MPN_COPY (orig_s0p, s0p, ssize);
+#endif
+ TMP_FREE (mark);
+ return size;
+ }
+ else
+ {
+ mp_limb_t vl, ul, t;
+#if EXTEND
+ mp_limb_t cy;
+ mp_size_t i;
+#endif
+ vl = vp[0];
+#if EXTEND
+ t = mpn_divmod_1 (wp, up, size, vl);
+ MPN_COPY (tp, s0p, ssize);
+ for (i = 0; i < size; i++)
+ {
+ cy = mpn_addmul_1 (tp + i, s1p, ssize, wp[i]);
+ if (cy != 0)
+ tp[ssize++] = cy;
+ }
+#if 0
+ MPN_COPY (s0p, s1p, ssize);
+ MPN_COPY (s1p, tp, ssize);
+#else
+ {
+ mp_ptr xp;
+ xp = s0p; s0p = s1p; s1p = xp;
+ xp = s1p; s1p = tp; tp = xp;
+ }
+#endif
+#else
+ t = mpn_mod_1 (up, size, vl);
+#endif
+ ul = vl;
+ vl = t;
+ while (vl != 0)
+ {
+ mp_limb_t t;
+#if EXTEND
+ mp_limb_t q, cy;
+ q = ul / vl;
+ t = ul - q*vl;
+
+ MPN_COPY (tp, s0p, ssize);
+ cy = mpn_addmul_1 (tp, s1p, ssize, q);
+ if (cy != 0)
+ tp[ssize++] = cy;
+#if 0
+ MPN_COPY (s0p, s1p, ssize);
+ MPN_COPY (s1p, tp, ssize);
+#else
+ {
+ mp_ptr xp;
+ xp = s0p; s0p = s1p; s1p = xp;
+ xp = s1p; s1p = tp; tp = xp;
+ }
+#endif
+
+#else
+ t = ul % vl;
+#endif
+ ul = vl;
+ vl = t;
+ }
+ gp[0] = ul;
+#if EXTEND
+ if (orig_s0p != s0p)
+ MPN_COPY (orig_s0p, s0p, ssize);
+#endif
+ TMP_FREE (mark);
+ return 1;
+ }
+}
diff --git a/mpn/generic/get_str.c b/mpn/generic/get_str.c
new file mode 100644
index 000000000..0e7fc60ef
--- /dev/null
+++ b/mpn/generic/get_str.c
@@ -0,0 +1,211 @@
+/* mpn_get_str -- Convert a MSIZE long limb vector pointed to by MPTR
+ to a printable string in STR in base BASE.
+
+Copyright (C) 1991, 1992, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+/* Convert the limb vector pointed to by MPTR and MSIZE long to a
+ char array, using base BASE for the result array. Store the
+ result in the character array STR. STR must point to an array with
+ space for the largest possible number represented by a MSIZE long
+ limb vector + 1 extra character.
+
+ The result is NOT in Ascii, to convert it to printable format, add
+ '0' or 'A' depending on the base and range.
+
+ Return the number of digits in the result string.
+ This may include some leading zeros.
+
+ The limb vector pointed to by MPTR is clobbered. */
+
+size_t
+mpn_get_str (str, base, mptr, msize)
+ unsigned char *str;
+ int base;
+ mp_ptr mptr;
+ mp_size_t msize;
+{
+ mp_limb_t big_base;
+#if UDIV_NEEDS_NORMALIZATION || UDIV_TIME > 2 * UMUL_TIME
+ int normalization_steps;
+#endif
+#if UDIV_TIME > 2 * UMUL_TIME
+ mp_limb_t big_base_inverted;
+#endif
+ unsigned int dig_per_u;
+ mp_size_t out_len;
+ register unsigned char *s;
+
+ big_base = __mp_bases[base].big_base;
+
+ s = str;
+
+ /* Special case zero, as the code below doesn't handle it. */
+ if (msize == 0)
+ {
+ s[0] = 0;
+ return 1;
+ }
+
+ if ((base & (base - 1)) == 0)
+ {
+ /* The base is a power of 2. Make conversion from most
+ significant side. */
+ mp_limb_t n1, n0;
+ register int bits_per_digit = big_base;
+ register int x;
+ register int bit_pos;
+ register int i;
+
+ n1 = mptr[msize - 1];
+ count_leading_zeros (x, n1);
+
+ /* BIT_POS should be R when input ends in least sign. nibble,
+ R + bits_per_digit * n when input ends in n:th least significant
+ nibble. */
+
+ {
+ int bits;
+
+ bits = BITS_PER_MP_LIMB * msize - x;
+ x = bits % bits_per_digit;
+ if (x != 0)
+ bits += bits_per_digit - x;
+ bit_pos = bits - (msize - 1) * BITS_PER_MP_LIMB;
+ }
+
+ /* Fast loop for bit output. */
+ i = msize - 1;
+ for (;;)
+ {
+ bit_pos -= bits_per_digit;
+ while (bit_pos >= 0)
+ {
+ *s++ = (n1 >> bit_pos) & ((1 << bits_per_digit) - 1);
+ bit_pos -= bits_per_digit;
+ }
+ i--;
+ if (i < 0)
+ break;
+ n0 = (n1 << -bit_pos) & ((1 << bits_per_digit) - 1);
+ n1 = mptr[i];
+ bit_pos += BITS_PER_MP_LIMB;
+ *s++ = n0 | (n1 >> bit_pos);
+ }
+
+ *s = 0;
+
+ return s - str;
+ }
+ else
+ {
+ /* General case. The base is not a power of 2. Make conversion
+ from least significant end. */
+
+ /* If udiv_qrnnd only handles divisors with the most significant bit
+ set, prepare BIG_BASE for being a divisor by shifting it to the
+ left exactly enough to set the most significant bit. */
+#if UDIV_NEEDS_NORMALIZATION || UDIV_TIME > 2 * UMUL_TIME
+ count_leading_zeros (normalization_steps, big_base);
+ big_base <<= normalization_steps;
+#if UDIV_TIME > 2 * UMUL_TIME
+ /* Get the fixed-point approximation to 1/(BIG_BASE << NORMALIZATION_STEPS). */
+ big_base_inverted = __mp_bases[base].big_base_inverted;
+#endif
+#endif
+
+ dig_per_u = __mp_bases[base].chars_per_limb;
+ out_len = ((size_t) msize * BITS_PER_MP_LIMB
+ * __mp_bases[base].chars_per_bit_exactly) + 1;
+ s += out_len;
+
+ while (msize != 0)
+ {
+ int i;
+ mp_limb_t n0, n1;
+
+#if UDIV_NEEDS_NORMALIZATION || UDIV_TIME > 2 * UMUL_TIME
+ /* If we shifted BIG_BASE above, shift the dividend too, to get
+ the right quotient. We need to do this every loop,
+ since the intermediate quotients are OK, but the quotient from
+ one turn in the loop is going to be the dividend in the
+ next turn, and the dividend needs to be up-shifted. */
+ if (normalization_steps != 0)
+ {
+ n0 = mpn_lshift (mptr, mptr, msize, normalization_steps);
+
+ /* If the shifting gave a carry out limb, store it and
+ increase the length. */
+ if (n0 != 0)
+ {
+ mptr[msize] = n0;
+ msize++;
+ }
+ }
+#endif
+
+ /* Divide the number at TP with BIG_BASE to get a quotient and a
+ remainder. The remainder is our new digit in base BIG_BASE. */
+ i = msize - 1;
+ n1 = mptr[i];
+
+ if (n1 >= big_base)
+ n1 = 0;
+ else
+ {
+ msize--;
+ i--;
+ }
+
+ for (; i >= 0; i--)
+ {
+ n0 = mptr[i];
+#if UDIV_TIME > 2 * UMUL_TIME
+ udiv_qrnnd_preinv (mptr[i], n1, n1, n0, big_base, big_base_inverted);
+#else
+ udiv_qrnnd (mptr[i], n1, n1, n0, big_base);
+#endif
+ }
+
+#if UDIV_NEEDS_NORMALIZATION || UDIV_TIME > 2 * UMUL_TIME
+ /* If we shifted above (at previous UDIV_NEEDS_NORMALIZATION tests)
+ the remainder will be up-shifted here. Compensate. */
+ n1 >>= normalization_steps;
+#endif
+
+ /* Convert N1 from BIG_BASE to a string of digits in BASE
+ using single precision operations. */
+ for (i = dig_per_u - 1; i >= 0; i--)
+ {
+ *--s = n1 % base;
+ n1 /= base;
+ if (n1 == 0 && msize == 0)
+ break;
+ }
+ }
+
+ while (s != str)
+ *--s = 0;
+ return out_len;
+ }
+}
diff --git a/mpn/generic/gmp-mparam.h b/mpn/generic/gmp-mparam.h
new file mode 100644
index 000000000..7c885575b
--- /dev/null
+++ b/mpn/generic/gmp-mparam.h
@@ -0,0 +1,27 @@
+/* gmp-mparam.h -- Compiler/machine parameter header file.
+
+Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#define BITS_PER_MP_LIMB 32
+#define BYTES_PER_MP_LIMB 4
+#define BITS_PER_LONGINT 32
+#define BITS_PER_INT 32
+#define BITS_PER_SHORTINT 16
+#define BITS_PER_CHAR 8
diff --git a/mpn/generic/hamdist.c b/mpn/generic/hamdist.c
new file mode 100644
index 000000000..2190b636f
--- /dev/null
+++ b/mpn/generic/hamdist.c
@@ -0,0 +1,88 @@
+/* mpn_hamdist --
+
+Copyright (C) 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+#if defined __GNUC__
+#if defined __sparc_v9__ && BITS_PER_MP_LIMB == 64
+#define popc_limb(a) \
+ ({ \
+ DItype __res; \
+ asm ("popc %1,%0" : "=r" (__res) : "rI" (a)); \
+ __res; \
+ })
+#endif
+#endif
+
+#ifndef popc_limb
+
+/* Cool population count of a mp_limb_t.
+ You have to figure out how this works, I won't tell you! */
+
+static inline unsigned int
+popc_limb (x)
+ mp_limb_t x;
+{
+#if BITS_PER_MP_LIMB == 64
+ /* We have to go into some trouble to define these constants.
+ (For mp_limb_t being `long long'.) */
+ mp_limb_t cnst;
+ cnst = 0x55555555L | ((mp_limb_t) 0x55555555L << BITS_PER_MP_LIMB/2);
+ x = ((x & ~cnst) >> 1) + (x & cnst);
+ cnst = 0x33333333L | ((mp_limb_t) 0x33333333L << BITS_PER_MP_LIMB/2);
+ x = ((x & ~cnst) >> 2) + (x & cnst);
+ cnst = 0x0f0f0f0fL | ((mp_limb_t) 0x0f0f0f0fL << BITS_PER_MP_LIMB/2);
+ x = ((x >> 4) + x) & cnst;
+ x = ((x >> 8) + x);
+ x = ((x >> 16) + x);
+ x = ((x >> 32) + x) & 0xff;
+#endif
+#if BITS_PER_MP_LIMB == 32
+ x = ((x >> 1) & 0x55555555L) + (x & 0x55555555L);
+ x = ((x >> 2) & 0x33333333L) + (x & 0x33333333L);
+ x = ((x >> 4) + x) & 0x0f0f0f0fL;
+ x = ((x >> 8) + x);
+ x = ((x >> 16) + x) & 0xff;
+#endif
+ return x;
+}
+#endif
+
+unsigned long int
+#if __STDC__
+mpn_hamdist (mp_srcptr up, mp_srcptr vp, mp_size_t size)
+#else
+mpn_hamdist (up, vp, size)
+ register mp_srcptr up;
+ register mp_srcptr vp;
+ register mp_size_t size;
+#endif
+{
+ unsigned long int hamdist;
+ mp_size_t i;
+
+ hamdist = 0;
+ for (i = 0; i < size; i++)
+ hamdist += popc_limb (up[i] ^ vp[i]);
+
+ return hamdist;
+}
diff --git a/mpn/generic/inlines.c b/mpn/generic/inlines.c
new file mode 100644
index 000000000..dca305e6e
--- /dev/null
+++ b/mpn/generic/inlines.c
@@ -0,0 +1,3 @@
+#define _FORCE_INLINES
+#define _EXTERN_INLINE /* empty */
+#include "gmp.h"
diff --git a/mpn/generic/lshift.c b/mpn/generic/lshift.c
new file mode 100644
index 000000000..e244bc52f
--- /dev/null
+++ b/mpn/generic/lshift.c
@@ -0,0 +1,87 @@
+/* mpn_lshift -- Shift left low level.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+/* Shift U (pointed to by UP and USIZE digits long) CNT bits to the left
+ and store the USIZE least significant digits of the result at WP.
+ Return the bits shifted out from the most significant digit.
+
+ Argument constraints:
+ 1. 0 < CNT < BITS_PER_MP_LIMB
+ 2. If the result is to be written over the input, WP must be >= UP.
+*/
+
+mp_limb_t
+#if __STDC__
+mpn_lshift (register mp_ptr wp,
+ register mp_srcptr up, mp_size_t usize,
+ register unsigned int cnt)
+#else
+mpn_lshift (wp, up, usize, cnt)
+ register mp_ptr wp;
+ register mp_srcptr up;
+ mp_size_t usize;
+ register unsigned int cnt;
+#endif
+{
+ register mp_limb_t high_limb, low_limb;
+ register unsigned sh_1, sh_2;
+ register mp_size_t i;
+ mp_limb_t retval;
+
+#ifdef DEBUG
+ if (usize == 0 || cnt == 0)
+ abort ();
+#endif
+
+ sh_1 = cnt;
+#if 0
+ if (sh_1 == 0)
+ {
+ if (wp != up)
+ {
+ /* Copy from high end to low end, to allow specified input/output
+ overlapping. */
+ for (i = usize - 1; i >= 0; i--)
+ wp[i] = up[i];
+ }
+ return 0;
+ }
+#endif
+
+ wp += 1;
+ sh_2 = BITS_PER_MP_LIMB - sh_1;
+ i = usize - 1;
+ low_limb = up[i];
+ retval = low_limb >> sh_2;
+ high_limb = low_limb;
+ while (--i >= 0)
+ {
+ low_limb = up[i];
+ wp[i] = (high_limb << sh_1) | (low_limb >> sh_2);
+ high_limb = low_limb;
+ }
+ wp[i] = high_limb << sh_1;
+
+ return retval;
+}
diff --git a/mpn/generic/mod_1.c b/mpn/generic/mod_1.c
new file mode 100644
index 000000000..314d11b30
--- /dev/null
+++ b/mpn/generic/mod_1.c
@@ -0,0 +1,197 @@
+/* mpn_mod_1(dividend_ptr, dividend_size, divisor_limb) --
+ Divide (DIVIDEND_PTR,,DIVIDEND_SIZE) by DIVISOR_LIMB.
+ Return the single-limb remainder.
+ There are no constraints on the value of the divisor.
+
+Copyright (C) 1991, 1993, 1994, Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+#ifndef UMUL_TIME
+#define UMUL_TIME 1
+#endif
+
+#ifndef UDIV_TIME
+#define UDIV_TIME UMUL_TIME
+#endif
+
+/* FIXME: We should be using invert_limb (or invert_normalized_limb)
+ here (not udiv_qrnnd). */
+
+mp_limb_t
+#if __STDC__
+mpn_mod_1 (mp_srcptr dividend_ptr, mp_size_t dividend_size,
+ mp_limb_t divisor_limb)
+#else
+mpn_mod_1 (dividend_ptr, dividend_size, divisor_limb)
+ mp_srcptr dividend_ptr;
+ mp_size_t dividend_size;
+ mp_limb_t divisor_limb;
+#endif
+{
+ mp_size_t i;
+ mp_limb_t n1, n0, r;
+ int dummy;
+
+ /* Botch: Should this be handled at all? Rely on callers? */
+ if (dividend_size == 0)
+ return 0;
+
+ /* If multiplication is much faster than division, and the
+ dividend is large, pre-invert the divisor, and use
+ only multiplications in the inner loop. */
+
+ /* This test should be read:
+ Does it ever help to use udiv_qrnnd_preinv?
+ && Does what we save compensate for the inversion overhead? */
+ if (UDIV_TIME > (2 * UMUL_TIME + 6)
+ && (UDIV_TIME - (2 * UMUL_TIME + 6)) * dividend_size > UDIV_TIME)
+ {
+ int normalization_steps;
+
+ count_leading_zeros (normalization_steps, divisor_limb);
+ if (normalization_steps != 0)
+ {
+ mp_limb_t divisor_limb_inverted;
+
+ divisor_limb <<= normalization_steps;
+
+ /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The
+ result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the
+ most significant bit (with weight 2**N) implicit. */
+
+ /* Special case for DIVISOR_LIMB == 100...000. */
+ if (divisor_limb << 1 == 0)
+ divisor_limb_inverted = ~(mp_limb_t) 0;
+ else
+ udiv_qrnnd (divisor_limb_inverted, dummy,
+ -divisor_limb, 0, divisor_limb);
+
+ n1 = dividend_ptr[dividend_size - 1];
+ r = n1 >> (BITS_PER_MP_LIMB - normalization_steps);
+
+ /* Possible optimization:
+ if (r == 0
+ && divisor_limb > ((n1 << normalization_steps)
+ | (dividend_ptr[dividend_size - 2] >> ...)))
+ ...one division less... */
+
+ for (i = dividend_size - 2; i >= 0; i--)
+ {
+ n0 = dividend_ptr[i];
+ udiv_qrnnd_preinv (dummy, r, r,
+ ((n1 << normalization_steps)
+ | (n0 >> (BITS_PER_MP_LIMB - normalization_steps))),
+ divisor_limb, divisor_limb_inverted);
+ n1 = n0;
+ }
+ udiv_qrnnd_preinv (dummy, r, r,
+ n1 << normalization_steps,
+ divisor_limb, divisor_limb_inverted);
+ return r >> normalization_steps;
+ }
+ else
+ {
+ mp_limb_t divisor_limb_inverted;
+
+ /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The
+ result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the
+ most significant bit (with weight 2**N) implicit. */
+
+ /* Special case for DIVISOR_LIMB == 100...000. */
+ if (divisor_limb << 1 == 0)
+ divisor_limb_inverted = ~(mp_limb_t) 0;
+ else
+ udiv_qrnnd (divisor_limb_inverted, dummy,
+ -divisor_limb, 0, divisor_limb);
+
+ i = dividend_size - 1;
+ r = dividend_ptr[i];
+
+ if (r >= divisor_limb)
+ r = 0;
+ else
+ i--;
+
+ for (; i >= 0; i--)
+ {
+ n0 = dividend_ptr[i];
+ udiv_qrnnd_preinv (dummy, r, r,
+ n0, divisor_limb, divisor_limb_inverted);
+ }
+ return r;
+ }
+ }
+ else
+ {
+ if (UDIV_NEEDS_NORMALIZATION)
+ {
+ int normalization_steps;
+
+ count_leading_zeros (normalization_steps, divisor_limb);
+ if (normalization_steps != 0)
+ {
+ divisor_limb <<= normalization_steps;
+
+ n1 = dividend_ptr[dividend_size - 1];
+ r = n1 >> (BITS_PER_MP_LIMB - normalization_steps);
+
+ /* Possible optimization:
+ if (r == 0
+ && divisor_limb > ((n1 << normalization_steps)
+ | (dividend_ptr[dividend_size - 2] >> ...)))
+ ...one division less... */
+
+ for (i = dividend_size - 2; i >= 0; i--)
+ {
+ n0 = dividend_ptr[i];
+ udiv_qrnnd (dummy, r, r,
+ ((n1 << normalization_steps)
+ | (n0 >> (BITS_PER_MP_LIMB - normalization_steps))),
+ divisor_limb);
+ n1 = n0;
+ }
+ udiv_qrnnd (dummy, r, r,
+ n1 << normalization_steps,
+ divisor_limb);
+ return r >> normalization_steps;
+ }
+ }
+ /* No normalization needed, either because udiv_qrnnd doesn't require
+ it, or because DIVISOR_LIMB is already normalized. */
+
+ i = dividend_size - 1;
+ r = dividend_ptr[i];
+
+ if (r >= divisor_limb)
+ r = 0;
+ else
+ i--;
+
+ for (; i >= 0; i--)
+ {
+ n0 = dividend_ptr[i];
+ udiv_qrnnd (dummy, r, r, n0, divisor_limb);
+ }
+ return r;
+ }
+}
diff --git a/mpn/generic/mul.c b/mpn/generic/mul.c
new file mode 100644
index 000000000..dcf8cb4da
--- /dev/null
+++ b/mpn/generic/mul.c
@@ -0,0 +1,152 @@
+/* mpn_mul -- Multiply two natural numbers.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+/* Multiply the natural numbers u (pointed to by UP, with USIZE limbs)
+ and v (pointed to by VP, with VSIZE limbs), and store the result at
+ PRODP. USIZE + VSIZE limbs are always stored, but if the input
+ operands are normalized. Return the most significant limb of the
+ result.
+
+ NOTE: The space pointed to by PRODP is overwritten before finished
+ with U and V, so overlap is an error.
+
+ Argument constraints:
+ 1. USIZE >= VSIZE.
+ 2. PRODP != UP and PRODP != VP, i.e. the destination
+ must be distinct from the multiplier and the multiplicand. */
+
+/* If KARATSUBA_THRESHOLD is not already defined, define it to a
+ value which is good on most machines. */
+#ifndef KARATSUBA_THRESHOLD
+#define KARATSUBA_THRESHOLD 32
+#endif
+
+mp_limb_t
+#if __STDC__
+mpn_mul (mp_ptr prodp,
+ mp_srcptr up, mp_size_t usize,
+ mp_srcptr vp, mp_size_t vsize)
+#else
+mpn_mul (prodp, up, usize, vp, vsize)
+ mp_ptr prodp;
+ mp_srcptr up;
+ mp_size_t usize;
+ mp_srcptr vp;
+ mp_size_t vsize;
+#endif
+{
+ mp_ptr prod_endp = prodp + usize + vsize - 1;
+ mp_limb_t cy;
+ mp_ptr tspace;
+ TMP_DECL (marker);
+
+ if (vsize < KARATSUBA_THRESHOLD)
+ {
+ /* Handle simple cases with traditional multiplication.
+
+ This is the most critical code of the entire function. All
+ multiplies rely on this, both small and huge. Small ones arrive
+ here immediately. Huge ones arrive here as this is the base case
+ for Karatsuba's recursive algorithm below. */
+ mp_size_t i;
+ mp_limb_t cy_limb;
+ mp_limb_t v_limb;
+
+ if (vsize == 0)
+ return 0;
+
+ /* Multiply by the first limb in V separately, as the result can be
+ stored (not added) to PROD. We also avoid a loop for zeroing. */
+ v_limb = vp[0];
+ if (v_limb <= 1)
+ {
+ if (v_limb == 1)
+ MPN_COPY (prodp, up, usize);
+ else
+ MPN_ZERO (prodp, usize);
+ cy_limb = 0;
+ }
+ else
+ cy_limb = mpn_mul_1 (prodp, up, usize, v_limb);
+
+ prodp[usize] = cy_limb;
+ prodp++;
+
+ /* For each iteration in the outer loop, multiply one limb from
+ U with one limb from V, and add it to PROD. */
+ for (i = 1; i < vsize; i++)
+ {
+ v_limb = vp[i];
+ if (v_limb <= 1)
+ {
+ cy_limb = 0;
+ if (v_limb == 1)
+ cy_limb = mpn_add_n (prodp, prodp, up, usize);
+ }
+ else
+ cy_limb = mpn_addmul_1 (prodp, up, usize, v_limb);
+
+ prodp[usize] = cy_limb;
+ prodp++;
+ }
+ return cy_limb;
+ }
+
+ TMP_MARK (marker);
+
+ tspace = (mp_ptr) TMP_ALLOC (2 * vsize * BYTES_PER_MP_LIMB);
+ MPN_MUL_N_RECURSE (prodp, up, vp, vsize, tspace);
+
+ prodp += vsize;
+ up += vsize;
+ usize -= vsize;
+ if (usize >= vsize)
+ {
+ mp_ptr tp = (mp_ptr) TMP_ALLOC (2 * vsize * BYTES_PER_MP_LIMB);
+ do
+ {
+ MPN_MUL_N_RECURSE (tp, up, vp, vsize, tspace);
+ cy = mpn_add_n (prodp, prodp, tp, vsize);
+ mpn_add_1 (prodp + vsize, tp + vsize, vsize, cy);
+ prodp += vsize;
+ up += vsize;
+ usize -= vsize;
+ }
+ while (usize >= vsize);
+ }
+
+ /* True: usize < vsize. */
+
+ /* Make life simple: Recurse. */
+
+ if (usize != 0)
+ {
+ mpn_mul (tspace, vp, vsize, up, usize);
+ cy = mpn_add_n (prodp, prodp, tspace, vsize);
+ mpn_add_1 (prodp + vsize, tspace + vsize, usize, cy);
+ }
+
+ TMP_FREE (marker);
+ return *prod_endp;
+}
diff --git a/mpn/generic/mul_1.c b/mpn/generic/mul_1.c
new file mode 100644
index 000000000..2de680a64
--- /dev/null
+++ b/mpn/generic/mul_1.c
@@ -0,0 +1,59 @@
+/* mpn_mul_1 -- Multiply a limb vector with a single limb and
+ store the product in a second limb vector.
+
+Copyright (C) 1991, 1992, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+mp_limb_t
+mpn_mul_1 (res_ptr, s1_ptr, s1_size, s2_limb)
+ register mp_ptr res_ptr;
+ register mp_srcptr s1_ptr;
+ mp_size_t s1_size;
+ register mp_limb_t s2_limb;
+{
+ register mp_limb_t cy_limb;
+ register mp_size_t j;
+ register mp_limb_t prod_high, prod_low;
+
+ /* The loop counter and index J goes from -S1_SIZE to -1. This way
+ the loop becomes faster. */
+ j = -s1_size;
+
+ /* Offset the base pointers to compensate for the negative indices. */
+ s1_ptr -= j;
+ res_ptr -= j;
+
+ cy_limb = 0;
+ do
+ {
+ umul_ppmm (prod_high, prod_low, s1_ptr[j], s2_limb);
+
+ prod_low += cy_limb;
+ cy_limb = (prod_low < cy_limb) + prod_high;
+
+ res_ptr[j] = prod_low;
+ }
+ while (++j != 0);
+
+ return cy_limb;
+}
diff --git a/mpn/generic/mul_n.c b/mpn/generic/mul_n.c
new file mode 100644
index 000000000..b38e8ad17
--- /dev/null
+++ b/mpn/generic/mul_n.c
@@ -0,0 +1,401 @@
+/* mpn_mul_n -- Multiply two natural numbers of length n.
+
+Copyright (C) 1991, 1992, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+/* Multiply the natural numbers u (pointed to by UP) and v (pointed to by VP),
+ both with SIZE limbs, and store the result at PRODP. 2 * SIZE limbs are
+ always stored. Return the most significant limb.
+
+ Argument constraints:
+ 1. PRODP != UP and PRODP != VP, i.e. the destination
+ must be distinct from the multiplier and the multiplicand. */
+
+/* If KARATSUBA_THRESHOLD is not already defined, define it to a
+ value which is good on most machines. */
+#ifndef KARATSUBA_THRESHOLD
+#define KARATSUBA_THRESHOLD 32
+#endif
+
+/* The code can't handle KARATSUBA_THRESHOLD smaller than 2. */
+#if KARATSUBA_THRESHOLD < 2
+#undef KARATSUBA_THRESHOLD
+#define KARATSUBA_THRESHOLD 2
+#endif
+
+/* Handle simple cases with traditional multiplication.
+
+ This is the most critical code of multiplication. All multiplies rely
+ on this, both small and huge. Small ones arrive here immediately. Huge
+ ones arrive here as this is the base case for Karatsuba's recursive
+ algorithm below. */
+
+void
+#if __STDC__
+impn_mul_n_basecase (mp_ptr prodp, mp_srcptr up, mp_srcptr vp, mp_size_t size)
+#else
+impn_mul_n_basecase (prodp, up, vp, size)
+ mp_ptr prodp;
+ mp_srcptr up;
+ mp_srcptr vp;
+ mp_size_t size;
+#endif
+{
+ mp_size_t i;
+ mp_limb_t cy_limb;
+ mp_limb_t v_limb;
+
+ /* Multiply by the first limb in V separately, as the result can be
+ stored (not added) to PROD. We also avoid a loop for zeroing. */
+ v_limb = vp[0];
+ if (v_limb <= 1)
+ {
+ if (v_limb == 1)
+ MPN_COPY (prodp, up, size);
+ else
+ MPN_ZERO (prodp, size);
+ cy_limb = 0;
+ }
+ else
+ cy_limb = mpn_mul_1 (prodp, up, size, v_limb);
+
+ prodp[size] = cy_limb;
+ prodp++;
+
+ /* For each iteration in the outer loop, multiply one limb from
+ U with one limb from V, and add it to PROD. */
+ for (i = 1; i < size; i++)
+ {
+ v_limb = vp[i];
+ if (v_limb <= 1)
+ {
+ cy_limb = 0;
+ if (v_limb == 1)
+ cy_limb = mpn_add_n (prodp, prodp, up, size);
+ }
+ else
+ cy_limb = mpn_addmul_1 (prodp, up, size, v_limb);
+
+ prodp[size] = cy_limb;
+ prodp++;
+ }
+}
+
+void
+#if __STDC__
+impn_mul_n (mp_ptr prodp,
+ mp_srcptr up, mp_srcptr vp, mp_size_t size, mp_ptr tspace)
+#else
+impn_mul_n (prodp, up, vp, size, tspace)
+ mp_ptr prodp;
+ mp_srcptr up;
+ mp_srcptr vp;
+ mp_size_t size;
+ mp_ptr tspace;
+#endif
+{
+ if ((size & 1) != 0)
+ {
+ /* The size is odd, the code code below doesn't handle that.
+ Multiply the least significant (size - 1) limbs with a recursive
+ call, and handle the most significant limb of S1 and S2
+ separately. */
+ /* A slightly faster way to do this would be to make the Karatsuba
+ code below behave as if the size were even, and let it check for
+ odd size in the end. I.e., in essence move this code to the end.
+ Doing so would save us a recursive call, and potentially make the
+ stack grow a lot less. */
+
+ mp_size_t esize = size - 1; /* even size */
+ mp_limb_t cy_limb;
+
+ MPN_MUL_N_RECURSE (prodp, up, vp, esize, tspace);
+ cy_limb = mpn_addmul_1 (prodp + esize, up, esize, vp[esize]);
+ prodp[esize + esize] = cy_limb;
+ cy_limb = mpn_addmul_1 (prodp + esize, vp, size, up[esize]);
+
+ prodp[esize + size] = cy_limb;
+ }
+ else
+ {
+ /* Anatolij Alekseevich Karatsuba's divide-and-conquer algorithm.
+
+ Split U in two pieces, U1 and U0, such that
+ U = U0 + U1*(B**n),
+ and V in V1 and V0, such that
+ V = V0 + V1*(B**n).
+
+ UV is then computed recursively using the identity
+
+ 2n n n n
+ UV = (B + B )U V + B (U -U )(V -V ) + (B + 1)U V
+ 1 1 1 0 0 1 0 0
+
+ Where B = 2**BITS_PER_MP_LIMB. */
+
+ mp_size_t hsize = size >> 1;
+ mp_limb_t cy;
+ int negflg;
+
+ /*** Product H. ________________ ________________
+ |_____U1 x V1____||____U0 x V0_____| */
+ /* Put result in upper part of PROD and pass low part of TSPACE
+ as new TSPACE. */
+ MPN_MUL_N_RECURSE (prodp + size, up + hsize, vp + hsize, hsize, tspace);
+
+ /*** Product M. ________________
+ |_(U1-U0)(V0-V1)_| */
+ if (mpn_cmp (up + hsize, up, hsize) >= 0)
+ {
+ mpn_sub_n (prodp, up + hsize, up, hsize);
+ negflg = 0;
+ }
+ else
+ {
+ mpn_sub_n (prodp, up, up + hsize, hsize);
+ negflg = 1;
+ }
+ if (mpn_cmp (vp + hsize, vp, hsize) >= 0)
+ {
+ mpn_sub_n (prodp + hsize, vp + hsize, vp, hsize);
+ negflg ^= 1;
+ }
+ else
+ {
+ mpn_sub_n (prodp + hsize, vp, vp + hsize, hsize);
+ /* No change of NEGFLG. */
+ }
+ /* Read temporary operands from low part of PROD.
+ Put result in low part of TSPACE using upper part of TSPACE
+ as new TSPACE. */
+ MPN_MUL_N_RECURSE (tspace, prodp, prodp + hsize, hsize, tspace + size);
+
+ /*** Add/copy product H. */
+ MPN_COPY (prodp + hsize, prodp + size, hsize);
+ cy = mpn_add_n (prodp + size, prodp + size, prodp + size + hsize, hsize);
+
+ /*** Add product M (if NEGFLG M is a negative number). */
+ if (negflg)
+ cy -= mpn_sub_n (prodp + hsize, prodp + hsize, tspace, size);
+ else
+ cy += mpn_add_n (prodp + hsize, prodp + hsize, tspace, size);
+
+ /*** Product L. ________________ ________________
+ |________________||____U0 x V0_____| */
+ /* Read temporary operands from low part of PROD.
+ Put result in low part of TSPACE using upper part of TSPACE
+ as new TSPACE. */
+ MPN_MUL_N_RECURSE (tspace, up, vp, hsize, tspace + size);
+
+ /*** Add/copy Product L (twice). */
+
+ cy += mpn_add_n (prodp + hsize, prodp + hsize, tspace, size);
+ if (cy)
+ mpn_add_1 (prodp + hsize + size, prodp + hsize + size, hsize, cy);
+
+ MPN_COPY (prodp, tspace, hsize);
+ cy = mpn_add_n (prodp + hsize, prodp + hsize, tspace + hsize, hsize);
+ if (cy)
+ mpn_add_1 (prodp + size, prodp + size, size, 1);
+ }
+}
+
+void
+#if __STDC__
+impn_sqr_n_basecase (mp_ptr prodp, mp_srcptr up, mp_size_t size)
+#else
+impn_sqr_n_basecase (prodp, up, size)
+ mp_ptr prodp;
+ mp_srcptr up;
+ mp_size_t size;
+#endif
+{
+ mp_size_t i;
+ mp_limb_t cy_limb;
+ mp_limb_t v_limb;
+
+ /* Multiply by the first limb in V separately, as the result can be
+ stored (not added) to PROD. We also avoid a loop for zeroing. */
+ v_limb = up[0];
+ if (v_limb <= 1)
+ {
+ if (v_limb == 1)
+ MPN_COPY (prodp, up, size);
+ else
+ MPN_ZERO (prodp, size);
+ cy_limb = 0;
+ }
+ else
+ cy_limb = mpn_mul_1 (prodp, up, size, v_limb);
+
+ prodp[size] = cy_limb;
+ prodp++;
+
+ /* For each iteration in the outer loop, multiply one limb from
+ U with one limb from V, and add it to PROD. */
+ for (i = 1; i < size; i++)
+ {
+ v_limb = up[i];
+ if (v_limb <= 1)
+ {
+ cy_limb = 0;
+ if (v_limb == 1)
+ cy_limb = mpn_add_n (prodp, prodp, up, size);
+ }
+ else
+ cy_limb = mpn_addmul_1 (prodp, up, size, v_limb);
+
+ prodp[size] = cy_limb;
+ prodp++;
+ }
+}
+
+void
+#if __STDC__
+impn_sqr_n (mp_ptr prodp,
+ mp_srcptr up, mp_size_t size, mp_ptr tspace)
+#else
+impn_sqr_n (prodp, up, size, tspace)
+ mp_ptr prodp;
+ mp_srcptr up;
+ mp_size_t size;
+ mp_ptr tspace;
+#endif
+{
+ if ((size & 1) != 0)
+ {
+ /* The size is odd, the code code below doesn't handle that.
+ Multiply the least significant (size - 1) limbs with a recursive
+ call, and handle the most significant limb of S1 and S2
+ separately. */
+ /* A slightly faster way to do this would be to make the Karatsuba
+ code below behave as if the size were even, and let it check for
+ odd size in the end. I.e., in essence move this code to the end.
+ Doing so would save us a recursive call, and potentially make the
+ stack grow a lot less. */
+
+ mp_size_t esize = size - 1; /* even size */
+ mp_limb_t cy_limb;
+
+ MPN_SQR_N_RECURSE (prodp, up, esize, tspace);
+ cy_limb = mpn_addmul_1 (prodp + esize, up, esize, up[esize]);
+ prodp[esize + esize] = cy_limb;
+ cy_limb = mpn_addmul_1 (prodp + esize, up, size, up[esize]);
+
+ prodp[esize + size] = cy_limb;
+ }
+ else
+ {
+ mp_size_t hsize = size >> 1;
+ mp_limb_t cy;
+
+ /*** Product H. ________________ ________________
+ |_____U1 x U1____||____U0 x U0_____| */
+ /* Put result in upper part of PROD and pass low part of TSPACE
+ as new TSPACE. */
+ MPN_SQR_N_RECURSE (prodp + size, up + hsize, hsize, tspace);
+
+ /*** Product M. ________________
+ |_(U1-U0)(U0-U1)_| */
+ if (mpn_cmp (up + hsize, up, hsize) >= 0)
+ {
+ mpn_sub_n (prodp, up + hsize, up, hsize);
+ }
+ else
+ {
+ mpn_sub_n (prodp, up, up + hsize, hsize);
+ }
+
+ /* Read temporary operands from low part of PROD.
+ Put result in low part of TSPACE using upper part of TSPACE
+ as new TSPACE. */
+ MPN_SQR_N_RECURSE (tspace, prodp, hsize, tspace + size);
+
+ /*** Add/copy product H. */
+ MPN_COPY (prodp + hsize, prodp + size, hsize);
+ cy = mpn_add_n (prodp + size, prodp + size, prodp + size + hsize, hsize);
+
+ /*** Add product M (if NEGFLG M is a negative number). */
+ cy -= mpn_sub_n (prodp + hsize, prodp + hsize, tspace, size);
+
+ /*** Product L. ________________ ________________
+ |________________||____U0 x U0_____| */
+ /* Read temporary operands from low part of PROD.
+ Put result in low part of TSPACE using upper part of TSPACE
+ as new TSPACE. */
+ MPN_SQR_N_RECURSE (tspace, up, hsize, tspace + size);
+
+ /*** Add/copy Product L (twice). */
+
+ cy += mpn_add_n (prodp + hsize, prodp + hsize, tspace, size);
+ if (cy)
+ mpn_add_1 (prodp + hsize + size, prodp + hsize + size, hsize, cy);
+
+ MPN_COPY (prodp, tspace, hsize);
+ cy = mpn_add_n (prodp + hsize, prodp + hsize, tspace + hsize, hsize);
+ if (cy)
+ mpn_add_1 (prodp + size, prodp + size, size, 1);
+ }
+}
+
+/* This should be made into an inline function in gmp.h. */
+inline void
+#if __STDC__
+mpn_mul_n (mp_ptr prodp, mp_srcptr up, mp_srcptr vp, mp_size_t size)
+#else
+mpn_mul_n (prodp, up, vp, size)
+ mp_ptr prodp;
+ mp_srcptr up;
+ mp_srcptr vp;
+ mp_size_t size;
+#endif
+{
+ TMP_DECL (marker);
+ TMP_MARK (marker);
+ if (up == vp)
+ {
+ if (size < KARATSUBA_THRESHOLD)
+ {
+ impn_sqr_n_basecase (prodp, up, size);
+ }
+ else
+ {
+ mp_ptr tspace;
+ tspace = (mp_ptr) TMP_ALLOC (2 * size * BYTES_PER_MP_LIMB);
+ impn_sqr_n (prodp, up, size, tspace);
+ }
+ }
+ else
+ {
+ if (size < KARATSUBA_THRESHOLD)
+ {
+ impn_mul_n_basecase (prodp, up, vp, size);
+ }
+ else
+ {
+ mp_ptr tspace;
+ tspace = (mp_ptr) TMP_ALLOC (2 * size * BYTES_PER_MP_LIMB);
+ impn_mul_n (prodp, up, vp, size, tspace);
+ }
+ }
+ TMP_FREE (marker);
+}
diff --git a/mpn/generic/perfsqr.c b/mpn/generic/perfsqr.c
new file mode 100644
index 000000000..5a6e2afe2
--- /dev/null
+++ b/mpn/generic/perfsqr.c
@@ -0,0 +1,138 @@
+/* mpn_perfect_square_p(u,usize) -- Return non-zero if U is a perfect square,
+ zero otherwise.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+#ifndef UMUL_TIME
+#define UMUL_TIME 1
+#endif
+
+#ifndef UDIV_TIME
+#define UDIV_TIME UMUL_TIME
+#endif
+
+#if BITS_PER_MP_LIMB == 32
+#define PP 0xC0CFD797L /* 3 x 5 x 7 x 11 x 13 x ... x 29 */
+#define PP_INVERTED 0x53E5645CL
+#endif
+
+#if BITS_PER_MP_LIMB == 64
+#define PP 0xE221F97C30E94E1DL /* 3 x 5 x 7 x 11 x 13 x ... x 53 */
+#define PP_INVERTED 0x21CFE6CFC938B36BL
+#endif
+
+/* sq_res_0x100[x mod 0x100] == 1 iff x mod 0x100 is a quadratic residue
+ modulo 0x100. */
+static unsigned char const sq_res_0x100[0x100] =
+{
+ 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,
+};
+
+int
+#if __STDC__
+mpn_perfect_square_p (mp_srcptr up, mp_size_t usize)
+#else
+mpn_perfect_square_p (up, usize)
+ mp_srcptr up;
+ mp_size_t usize;
+#endif
+{
+ mp_limb_t rem;
+ mp_ptr root_ptr;
+ int res;
+ TMP_DECL (marker);
+
+ /* The first test excludes 55/64 (85.9%) of the perfect square candidates
+ in O(1) time. */
+ if ((sq_res_0x100[(unsigned int) up[0] % 0x100] & 1) == 0)
+ return 0;
+
+#if defined (PP)
+ /* The second test excludes 30652543/30808063 (99.5%) of the remaining
+ perfect square candidates in O(n) time. */
+
+ /* Firstly, compute REM = A mod PP. */
+ if (UDIV_TIME > (2 * UMUL_TIME + 6))
+ rem = mpn_preinv_mod_1 (up, usize, (mp_limb_t) PP, (mp_limb_t) PP_INVERTED);
+ else
+ rem = mpn_mod_1 (up, usize, (mp_limb_t) PP);
+
+ /* Now decide if REM is a quadratic residue modulo the factors in PP. */
+
+ /* If A is just a few limbs, computing the square root does not take long
+ time, so things might run faster if we limit this loop according to the
+ size of A. */
+
+#if BITS_PER_MP_LIMB == 64
+ if (((0x12DD703303AED3L >> rem % 53) & 1) == 0)
+ return 0;
+ if (((0x4351B2753DFL >> rem % 47) & 1) == 0)
+ return 0;
+ if (((0x35883A3EE53L >> rem % 43) & 1) == 0)
+ return 0;
+ if (((0x1B382B50737L >> rem % 41) & 1) == 0)
+ return 0;
+ if (((0x165E211E9BL >> rem % 37) & 1) == 0)
+ return 0;
+ if (((0x121D47B7L >> rem % 31) & 1) == 0)
+ return 0;
+#endif
+ if (((0x13D122F3L >> rem % 29) & 1) == 0)
+ return 0;
+ if (((0x5335FL >> rem % 23) & 1) == 0)
+ return 0;
+ if (((0x30AF3L >> rem % 19) & 1) == 0)
+ return 0;
+ if (((0x1A317L >> rem % 17) & 1) == 0)
+ return 0;
+ if (((0x161BL >> rem % 13) & 1) == 0)
+ return 0;
+ if (((0x23BL >> rem % 11) & 1) == 0)
+ return 0;
+ if (((0x017L >> rem % 7) & 1) == 0)
+ return 0;
+ if (((0x13L >> rem % 5) & 1) == 0)
+ return 0;
+ if (((0x3L >> rem % 3) & 1) == 0)
+ return 0;
+#endif
+
+ TMP_MARK (marker);
+
+ /* For the third and last test, we finally compute the square root,
+ to make sure we've really got a perfect square. */
+ root_ptr = (mp_ptr) TMP_ALLOC ((usize + 1) / 2 * BYTES_PER_MP_LIMB);
+
+ /* Iff mpn_sqrtrem returns zero, the square is perfect. */
+ res = ! mpn_sqrtrem (root_ptr, NULL, up, usize);
+ TMP_FREE (marker);
+ return res;
+}
diff --git a/mpn/generic/popcount.c b/mpn/generic/popcount.c
new file mode 100644
index 000000000..c48573a47
--- /dev/null
+++ b/mpn/generic/popcount.c
@@ -0,0 +1,87 @@
+/* popcount.c
+
+Copyright (C) 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+#if defined __GNUC__
+#if defined __sparc_v9__ && BITS_PER_MP_LIMB == 64
+#define popc_limb(a) \
+ ({ \
+ DItype __res; \
+ asm ("popc %1,%0" : "=r" (__res) : "rI" (a)); \
+ __res; \
+ })
+#endif
+#endif
+
+#ifndef popc_limb
+
+/* Cool population count of a mp_limb_t.
+ You have to figure out how this works, I won't tell you! */
+
+static inline unsigned int
+popc_limb (x)
+ mp_limb_t x;
+{
+#if BITS_PER_MP_LIMB == 64
+ /* We have to go into some trouble to define these constants.
+ (For mp_limb_t being `long long'.) */
+ mp_limb_t cnst;
+ cnst = 0x55555555L | ((mp_limb_t) 0x55555555L << BITS_PER_MP_LIMB/2);
+ x = ((x & ~cnst) >> 1) + (x & cnst);
+ cnst = 0x33333333L | ((mp_limb_t) 0x33333333L << BITS_PER_MP_LIMB/2);
+ x = ((x & ~cnst) >> 2) + (x & cnst);
+ cnst = 0x0f0f0f0fL | ((mp_limb_t) 0x0f0f0f0fL << BITS_PER_MP_LIMB/2);
+ x = ((x >> 4) + x) & cnst;
+ x = ((x >> 8) + x);
+ x = ((x >> 16) + x);
+ x = ((x >> 32) + x) & 0xff;
+#endif
+#if BITS_PER_MP_LIMB == 32
+ x = ((x >> 1) & 0x55555555L) + (x & 0x55555555L);
+ x = ((x >> 2) & 0x33333333L) + (x & 0x33333333L);
+ x = ((x >> 4) + x) & 0x0f0f0f0fL;
+ x = ((x >> 8) + x);
+ x = ((x >> 16) + x) & 0xff;
+#endif
+ return x;
+}
+#endif
+
+unsigned long int
+#if __STDC__
+mpn_popcount (register mp_srcptr p, register mp_size_t size)
+#else
+mpn_popcount (p, size)
+ register mp_srcptr p;
+ register mp_size_t size;
+#endif
+{
+ unsigned long int popcnt;
+ mp_size_t i;
+
+ popcnt = 0;
+ for (i = 0; i < size; i++)
+ popcnt += popc_limb (p[i]);
+
+ return popcnt;
+}
diff --git a/mpn/generic/pre_mod_1.c b/mpn/generic/pre_mod_1.c
new file mode 100644
index 000000000..92d413b13
--- /dev/null
+++ b/mpn/generic/pre_mod_1.c
@@ -0,0 +1,69 @@
+/* mpn_preinv_mod_1 (dividend_ptr, dividend_size, divisor_limb,
+ divisor_limb_inverted) --
+ Divide (DIVIDEND_PTR,,DIVIDEND_SIZE) by the normalized DIVISOR_LIMB.
+ DIVISOR_LIMB_INVERTED should be 2^(2*BITS_PER_MP_LIMB) / DIVISOR_LIMB +
+ - 2^BITS_PER_MP_LIMB.
+ Return the single-limb remainder.
+
+Copyright (C) 1991, 1993, 1994, Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+#ifndef UMUL_TIME
+#define UMUL_TIME 1
+#endif
+
+#ifndef UDIV_TIME
+#define UDIV_TIME UMUL_TIME
+#endif
+
+mp_limb_t
+#if __STDC__
+mpn_preinv_mod_1 (mp_srcptr dividend_ptr, mp_size_t dividend_size,
+ mp_limb_t divisor_limb, mp_limb_t divisor_limb_inverted)
+#else
+mpn_preinv_mod_1 (dividend_ptr, dividend_size, divisor_limb, divisor_limb_inverted)
+ mp_srcptr dividend_ptr;
+ mp_size_t dividend_size;
+ mp_limb_t divisor_limb;
+ mp_limb_t divisor_limb_inverted;
+#endif
+{
+ mp_size_t i;
+ mp_limb_t n0, r;
+ int dummy;
+
+ i = dividend_size - 1;
+ r = dividend_ptr[i];
+
+ if (r >= divisor_limb)
+ r = 0;
+ else
+ i--;
+
+ for (; i >= 0; i--)
+ {
+ n0 = dividend_ptr[i];
+ udiv_qrnnd_preinv (dummy, r, r, n0, divisor_limb, divisor_limb_inverted);
+ }
+ return r;
+}
diff --git a/mpn/generic/random2.c b/mpn/generic/random2.c
new file mode 100644
index 000000000..e4217a374
--- /dev/null
+++ b/mpn/generic/random2.c
@@ -0,0 +1,93 @@
+/* mpn_random2 -- Generate random numbers with relatively long strings
+ of ones and zeroes. Suitable for border testing.
+
+Copyright (C) 1992, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+#if defined (__hpux) || defined (__alpha__) || defined (__svr4__) || defined (__SVR4)
+/* HPUX lacks random(). DEC OSF/1 1.2 random() returns a double. */
+long mrand48 ();
+static inline long
+random ()
+{
+ return mrand48 ();
+}
+#else
+long random ();
+#endif
+
+/* It's a bit tricky to get this right, so please test the code well
+ if you hack with it. Some early versions of the function produced
+ random numbers with the leading limb == 0, and some versions never
+ made the most significant bit set. */
+
+void
+mpn_random2 (res_ptr, size)
+ mp_ptr res_ptr;
+ mp_size_t size;
+{
+ int n_bits;
+ int bit_pos;
+ mp_size_t limb_pos;
+ unsigned int ran;
+ mp_limb_t limb;
+
+ limb = 0;
+
+ /* Start off in a random bit position in the most significant limb. */
+ bit_pos = random () & (BITS_PER_MP_LIMB - 1);
+
+ /* Least significant bit of RAN chooses string of ones/string of zeroes.
+ Make most significant limb be non-zero by setting bit 0 of RAN. */
+ ran = random () | 1;
+
+ for (limb_pos = size - 1; limb_pos >= 0; )
+ {
+ n_bits = (ran >> 1) % BITS_PER_MP_LIMB + 1;
+ if ((ran & 1) != 0)
+ {
+ /* Generate a string of ones. */
+ if (n_bits >= bit_pos)
+ {
+ res_ptr[limb_pos--] = limb | ((((mp_limb_t) 2) << bit_pos) - 1);
+ bit_pos += BITS_PER_MP_LIMB;
+ limb = (~(mp_limb_t) 0) << (bit_pos - n_bits);
+ }
+ else
+ {
+ limb |= ((((mp_limb_t) 1) << n_bits) - 1) << (bit_pos - n_bits + 1);
+ }
+ }
+ else
+ {
+ /* Generate a string of zeroes. */
+ if (n_bits >= bit_pos)
+ {
+ res_ptr[limb_pos--] = limb;
+ limb = 0;
+ bit_pos += BITS_PER_MP_LIMB;
+ }
+ }
+ bit_pos -= n_bits;
+ ran = random ();
+ }
+}
diff --git a/mpn/generic/rshift.c b/mpn/generic/rshift.c
new file mode 100644
index 000000000..804f9be58
--- /dev/null
+++ b/mpn/generic/rshift.c
@@ -0,0 +1,88 @@
+/* mpn_rshift -- Shift right a low-level natural-number integer.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+/* Shift U (pointed to by UP and USIZE limbs long) CNT bits to the right
+ and store the USIZE least significant limbs of the result at WP.
+ The bits shifted out to the right are returned.
+
+ Argument constraints:
+ 1. 0 < CNT < BITS_PER_MP_LIMB
+ 2. If the result is to be written over the input, WP must be <= UP.
+*/
+
+mp_limb_t
+#if __STDC__
+mpn_rshift (register mp_ptr wp,
+ register mp_srcptr up, mp_size_t usize,
+ register unsigned int cnt)
+#else
+mpn_rshift (wp, up, usize, cnt)
+ register mp_ptr wp;
+ register mp_srcptr up;
+ mp_size_t usize;
+ register unsigned int cnt;
+#endif
+{
+ register mp_limb_t high_limb, low_limb;
+ register unsigned sh_1, sh_2;
+ register mp_size_t i;
+ mp_limb_t retval;
+
+#ifdef DEBUG
+ if (usize == 0 || cnt == 0)
+ abort ();
+#endif
+
+ sh_1 = cnt;
+
+#if 0
+ if (sh_1 == 0)
+ {
+ if (wp != up)
+ {
+ /* Copy from low end to high end, to allow specified input/output
+ overlapping. */
+ for (i = 0; i < usize; i++)
+ wp[i] = up[i];
+ }
+ return usize;
+ }
+#endif
+
+ wp -= 1;
+ sh_2 = BITS_PER_MP_LIMB - sh_1;
+ high_limb = up[0];
+ retval = high_limb << sh_2;
+ low_limb = high_limb;
+
+ for (i = 1; i < usize; i++)
+ {
+ high_limb = up[i];
+ wp[i] = (low_limb >> sh_1) | (high_limb << sh_2);
+ low_limb = high_limb;
+ }
+ wp[i] = low_limb >> sh_1;
+
+ return retval;
+}
diff --git a/mpn/generic/scan0.c b/mpn/generic/scan0.c
new file mode 100644
index 000000000..84b197ce2
--- /dev/null
+++ b/mpn/generic/scan0.c
@@ -0,0 +1,62 @@
+/* mpn_scan0 -- Scan from a given bit position for the next clear bit.
+
+Copyright (C) 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+/* Design issues:
+ 1. What if starting_bit is not within U? Caller's problem?
+ 2. Bit index should be 'unsigned'?
+
+ Argument constraints:
+ 1. U must sooner ot later have a limb != 1.
+ */
+
+unsigned long int
+#if __STDC__
+mpn_scan0 (register mp_srcptr up,
+ register unsigned long int starting_bit)
+#else
+mpn_scan0 (up, starting_bit)
+ register mp_srcptr up;
+ register unsigned long int starting_bit;
+#endif
+{
+ mp_size_t starting_word;
+ mp_limb_t alimb;
+ int cnt;
+ mp_srcptr p;
+
+ /* Start at the word implied by STARTING_BIT. */
+ starting_word = starting_bit / BITS_PER_MP_LIMB;
+ p = up + starting_word;
+ alimb = ~*p++;
+
+ /* Mask off any bits before STARTING_BIT in the first limb. */
+ alimb &= - (mp_limb_t) 1 << (starting_bit % BITS_PER_MP_LIMB);
+
+ while (alimb == 0)
+ alimb = ~*p++;
+
+ count_leading_zeros (cnt, alimb & -alimb);
+ return (p - up) * BITS_PER_MP_LIMB - 1 - cnt;
+}
diff --git a/mpn/generic/scan1.c b/mpn/generic/scan1.c
new file mode 100644
index 000000000..c95d090da
--- /dev/null
+++ b/mpn/generic/scan1.c
@@ -0,0 +1,62 @@
+/* mpn_scan1 -- Scan from a given bit position for the next set bit.
+
+Copyright (C) 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+/* Design issues:
+ 1. What if starting_bit is not within U? Caller's problem?
+ 2. Bit index should be 'unsigned'?
+
+ Argument constraints:
+ 1. U must sooner ot later have a limb != 0.
+ */
+
+unsigned long int
+#if __STDC__
+mpn_scan1 (register mp_srcptr up,
+ register unsigned long int starting_bit)
+#else
+mpn_scan1 (up, starting_bit)
+ register mp_srcptr up;
+ register unsigned long int starting_bit;
+#endif
+{
+ mp_size_t starting_word;
+ mp_limb_t alimb;
+ int cnt;
+ mp_srcptr p;
+
+ /* Start at the word implied by STARTING_BIT. */
+ starting_word = starting_bit / BITS_PER_MP_LIMB;
+ p = up + starting_word;
+ alimb = *p++;
+
+ /* Mask off any bits before STARTING_BIT in the first limb. */
+ alimb &= - (mp_limb_t) 1 << (starting_bit % BITS_PER_MP_LIMB);
+
+ while (alimb == 0)
+ alimb = *p++;
+
+ count_leading_zeros (cnt, alimb & -alimb);
+ return (p - up) * BITS_PER_MP_LIMB - 1 - cnt;
+}
diff --git a/mpn/generic/set_str.c b/mpn/generic/set_str.c
new file mode 100644
index 000000000..154b4b096
--- /dev/null
+++ b/mpn/generic/set_str.c
@@ -0,0 +1,154 @@
+/* mpn_set_str (mp_ptr res_ptr, const char *str, size_t str_len, int base)
+ -- Convert a STR_LEN long base BASE byte string pointed to by STR to a
+ limb vector pointed to by RES_PTR. Return the number of limbs in
+ RES_PTR.
+
+Copyright (C) 1991, 1992, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+mp_size_t
+mpn_set_str (xp, str, str_len, base)
+ mp_ptr xp;
+ const unsigned char *str;
+ size_t str_len;
+ int base;
+{
+ mp_size_t size;
+ mp_limb_t big_base;
+ int indigits_per_limb;
+ mp_limb_t res_digit;
+
+ big_base = __mp_bases[base].big_base;
+ indigits_per_limb = __mp_bases[base].chars_per_limb;
+
+/* size = str_len / indigits_per_limb + 1; */
+
+ size = 0;
+
+ if ((base & (base - 1)) == 0)
+ {
+ /* The base is a power of 2. Read the input string from
+ least to most significant character/digit. */
+
+ const unsigned char *s;
+ int next_bitpos;
+ int bits_per_indigit = big_base;
+
+ res_digit = 0;
+ next_bitpos = 0;
+
+ for (s = str + str_len - 1; s >= str; s--)
+ {
+ int inp_digit = *s;
+
+ res_digit |= (mp_limb_t) inp_digit << next_bitpos;
+ next_bitpos += bits_per_indigit;
+ if (next_bitpos >= BITS_PER_MP_LIMB)
+ {
+ xp[size++] = res_digit;
+ next_bitpos -= BITS_PER_MP_LIMB;
+ res_digit = inp_digit >> (bits_per_indigit - next_bitpos);
+ }
+ }
+
+ if (res_digit != 0)
+ xp[size++] = res_digit;
+ }
+ else
+ {
+ /* General case. The base is not a power of 2. */
+
+ size_t i;
+ int j;
+ mp_limb_t cy_limb;
+
+ for (i = indigits_per_limb; i < str_len; i += indigits_per_limb)
+ {
+ res_digit = *str++;
+ if (base == 10)
+ { /* This is a common case.
+ Help the compiler to avoid multiplication. */
+ for (j = 1; j < indigits_per_limb; j++)
+ res_digit = res_digit * 10 + *str++;
+ }
+ else
+ {
+ for (j = 1; j < indigits_per_limb; j++)
+ res_digit = res_digit * base + *str++;
+ }
+
+ if (size == 0)
+ {
+ if (res_digit != 0)
+ {
+ xp[0] = res_digit;
+ size = 1;
+ }
+ }
+ else
+ {
+ cy_limb = mpn_mul_1 (xp, xp, size, big_base);
+ cy_limb += mpn_add_1 (xp, xp, size, res_digit);
+ if (cy_limb != 0)
+ xp[size++] = cy_limb;
+ }
+ }
+
+ big_base = base;
+ res_digit = *str++;
+ if (base == 10)
+ { /* This is a common case.
+ Help the compiler to avoid multiplication. */
+ for (j = 1; j < str_len - (i - indigits_per_limb); j++)
+ {
+ res_digit = res_digit * 10 + *str++;
+ big_base *= 10;
+ }
+ }
+ else
+ {
+ for (j = 1; j < str_len - (i - indigits_per_limb); j++)
+ {
+ res_digit = res_digit * base + *str++;
+ big_base *= base;
+ }
+ }
+
+ if (size == 0)
+ {
+ if (res_digit != 0)
+ {
+ xp[0] = res_digit;
+ size = 1;
+ }
+ }
+ else
+ {
+ cy_limb = mpn_mul_1 (xp, xp, size, big_base);
+ cy_limb += mpn_add_1 (xp, xp, size, res_digit);
+ if (cy_limb != 0)
+ xp[size++] = cy_limb;
+ }
+ }
+
+ return size;
+}
diff --git a/mpn/generic/sqrtrem.c b/mpn/generic/sqrtrem.c
new file mode 100644
index 000000000..539480d37
--- /dev/null
+++ b/mpn/generic/sqrtrem.c
@@ -0,0 +1,498 @@
+/* mpn_sqrtrem (root_ptr, rem_ptr, op_ptr, op_size)
+
+ Write the square root of {OP_PTR, OP_SIZE} at ROOT_PTR.
+ Write the remainder at REM_PTR, if REM_PTR != NULL.
+ Return the size of the remainder.
+ (The size of the root is always half of the size of the operand.)
+
+ OP_PTR and ROOT_PTR may not point to the same object.
+ OP_PTR and REM_PTR may point to the same object.
+
+ If REM_PTR is NULL, only the root is computed and the return value of
+ the function is 0 if OP is a perfect square, and *any* non-zero number
+ otherwise.
+
+Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/* This code is just correct if "unsigned char" has at least 8 bits. It
+ doesn't help to use CHAR_BIT from limits.h, as the real problem is
+ the static arrays. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+/* Square root algorithm:
+
+ 1. Shift OP (the input) to the left an even number of bits s.t. there
+ are an even number of words and either (or both) of the most
+ significant bits are set. This way, sqrt(OP) has exactly half as
+ many words as OP, and has its most significant bit set.
+
+ 2. Get a 9-bit approximation to sqrt(OP) using the pre-computed tables.
+ This approximation is used for the first single-precision
+ iterations of Newton's method, yielding a full-word approximation
+ to sqrt(OP).
+
+ 3. Perform multiple-precision Newton iteration until we have the
+ exact result. Only about half of the input operand is used in
+ this calculation, as the square root is perfectly determinable
+ from just the higher half of a number. */
+
+/* Define this macro for IEEE P854 machines with a fast sqrt instruction. */
+#if defined __GNUC__ && ! defined __SOFT_FLOAT
+
+#if defined __sparc__
+#define SQRT(a) \
+ ({ \
+ double __sqrt_res; \
+ asm ("fsqrtd %1,%0" : "=f" (__sqrt_res) : "f" (a)); \
+ __sqrt_res; \
+ })
+#endif
+
+#if defined __HAVE_68881__
+#define SQRT(a) \
+ ({ \
+ double __sqrt_res; \
+ asm ("fsqrtx %1,%0" : "=f" (__sqrt_res) : "f" (a)); \
+ __sqrt_res; \
+ })
+#endif
+
+#if defined __hppa
+#define SQRT(a) \
+ ({ \
+ double __sqrt_res; \
+ asm ("fsqrt,dbl %1,%0" : "=fx" (__sqrt_res) : "fx" (a)); \
+ __sqrt_res; \
+ })
+#endif
+
+#if defined _ARCH_PWR2
+#define SQRT(a) \
+ ({ \
+ double __sqrt_res; \
+ asm ("fsqrt %0,%1" : "=f" (__sqrt_res) : "f" (a)); \
+ __sqrt_res; \
+ })
+#endif
+
+#endif
+
+#ifndef SQRT
+
+/* Tables for initial approximation of the square root. These are
+ indexed with bits 1-8 of the operand for which the square root is
+ calculated, where bit 0 is the most significant non-zero bit. I.e.
+ the most significant one-bit is not used, since that per definition
+ is one. Likewise, the tables don't return the highest bit of the
+ result. That bit must be inserted by or:ing the returned value with
+ 0x100. This way, we get a 9-bit approximation from 8-bit tables! */
+
+/* Table to be used for operands with an even total number of bits.
+ (Exactly as in the decimal system there are similarities between the
+ square root of numbers with the same initial digits and an even
+ difference in the total number of digits. Consider the square root
+ of 1, 10, 100, 1000, ...) */
+static unsigned char even_approx_tab[256] =
+{
+ 0x6a, 0x6a, 0x6b, 0x6c, 0x6c, 0x6d, 0x6e, 0x6e,
+ 0x6f, 0x70, 0x71, 0x71, 0x72, 0x73, 0x73, 0x74,
+ 0x75, 0x75, 0x76, 0x77, 0x77, 0x78, 0x79, 0x79,
+ 0x7a, 0x7b, 0x7b, 0x7c, 0x7d, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x80, 0x81, 0x81, 0x82, 0x83, 0x83, 0x84,
+ 0x85, 0x85, 0x86, 0x87, 0x87, 0x88, 0x89, 0x89,
+ 0x8a, 0x8b, 0x8b, 0x8c, 0x8d, 0x8d, 0x8e, 0x8f,
+ 0x8f, 0x90, 0x90, 0x91, 0x92, 0x92, 0x93, 0x94,
+ 0x94, 0x95, 0x96, 0x96, 0x97, 0x97, 0x98, 0x99,
+ 0x99, 0x9a, 0x9b, 0x9b, 0x9c, 0x9c, 0x9d, 0x9e,
+ 0x9e, 0x9f, 0xa0, 0xa0, 0xa1, 0xa1, 0xa2, 0xa3,
+ 0xa3, 0xa4, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7, 0xa7,
+ 0xa8, 0xa9, 0xa9, 0xaa, 0xaa, 0xab, 0xac, 0xac,
+ 0xad, 0xad, 0xae, 0xaf, 0xaf, 0xb0, 0xb0, 0xb1,
+ 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb5, 0xb5, 0xb6,
+ 0xb6, 0xb7, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba,
+ 0xbb, 0xbb, 0xbc, 0xbd, 0xbd, 0xbe, 0xbe, 0xbf,
+ 0xc0, 0xc0, 0xc1, 0xc1, 0xc2, 0xc2, 0xc3, 0xc3,
+ 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7, 0xc8,
+ 0xc9, 0xc9, 0xca, 0xca, 0xcb, 0xcb, 0xcc, 0xcc,
+ 0xcd, 0xce, 0xce, 0xcf, 0xcf, 0xd0, 0xd0, 0xd1,
+ 0xd1, 0xd2, 0xd3, 0xd3, 0xd4, 0xd4, 0xd5, 0xd5,
+ 0xd6, 0xd6, 0xd7, 0xd7, 0xd8, 0xd9, 0xd9, 0xda,
+ 0xda, 0xdb, 0xdb, 0xdc, 0xdc, 0xdd, 0xdd, 0xde,
+ 0xde, 0xdf, 0xe0, 0xe0, 0xe1, 0xe1, 0xe2, 0xe2,
+ 0xe3, 0xe3, 0xe4, 0xe4, 0xe5, 0xe5, 0xe6, 0xe6,
+ 0xe7, 0xe7, 0xe8, 0xe8, 0xe9, 0xea, 0xea, 0xeb,
+ 0xeb, 0xec, 0xec, 0xed, 0xed, 0xee, 0xee, 0xef,
+ 0xef, 0xf0, 0xf0, 0xf1, 0xf1, 0xf2, 0xf2, 0xf3,
+ 0xf3, 0xf4, 0xf4, 0xf5, 0xf5, 0xf6, 0xf6, 0xf7,
+ 0xf7, 0xf8, 0xf8, 0xf9, 0xf9, 0xfa, 0xfa, 0xfb,
+ 0xfb, 0xfc, 0xfc, 0xfd, 0xfd, 0xfe, 0xfe, 0xff,
+};
+
+/* Table to be used for operands with an odd total number of bits.
+ (Further comments before previous table.) */
+static unsigned char odd_approx_tab[256] =
+{
+ 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03,
+ 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07,
+ 0x07, 0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a, 0x0b,
+ 0x0b, 0x0c, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e, 0x0f,
+ 0x0f, 0x10, 0x10, 0x10, 0x11, 0x11, 0x12, 0x12,
+ 0x13, 0x13, 0x14, 0x14, 0x15, 0x15, 0x16, 0x16,
+ 0x16, 0x17, 0x17, 0x18, 0x18, 0x19, 0x19, 0x1a,
+ 0x1a, 0x1b, 0x1b, 0x1b, 0x1c, 0x1c, 0x1d, 0x1d,
+ 0x1e, 0x1e, 0x1f, 0x1f, 0x20, 0x20, 0x20, 0x21,
+ 0x21, 0x22, 0x22, 0x23, 0x23, 0x23, 0x24, 0x24,
+ 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x27, 0x28,
+ 0x28, 0x29, 0x29, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b,
+ 0x2c, 0x2c, 0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2f,
+ 0x2f, 0x30, 0x30, 0x30, 0x31, 0x31, 0x32, 0x32,
+ 0x32, 0x33, 0x33, 0x34, 0x34, 0x35, 0x35, 0x35,
+ 0x36, 0x36, 0x37, 0x37, 0x37, 0x38, 0x38, 0x39,
+ 0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3c,
+ 0x3c, 0x3d, 0x3d, 0x3d, 0x3e, 0x3e, 0x3f, 0x3f,
+ 0x40, 0x40, 0x40, 0x41, 0x41, 0x41, 0x42, 0x42,
+ 0x43, 0x43, 0x43, 0x44, 0x44, 0x45, 0x45, 0x45,
+ 0x46, 0x46, 0x47, 0x47, 0x47, 0x48, 0x48, 0x49,
+ 0x49, 0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c,
+ 0x4c, 0x4c, 0x4d, 0x4d, 0x4e, 0x4e, 0x4e, 0x4f,
+ 0x4f, 0x50, 0x50, 0x50, 0x51, 0x51, 0x51, 0x52,
+ 0x52, 0x53, 0x53, 0x53, 0x54, 0x54, 0x54, 0x55,
+ 0x55, 0x56, 0x56, 0x56, 0x57, 0x57, 0x57, 0x58,
+ 0x58, 0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b,
+ 0x5b, 0x5b, 0x5c, 0x5c, 0x5d, 0x5d, 0x5d, 0x5e,
+ 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x60, 0x61,
+ 0x61, 0x61, 0x62, 0x62, 0x62, 0x63, 0x63, 0x63,
+ 0x64, 0x64, 0x65, 0x65, 0x65, 0x66, 0x66, 0x66,
+ 0x67, 0x67, 0x67, 0x68, 0x68, 0x68, 0x69, 0x69,
+};
+#endif
+
+
+mp_size_t
+#if __STDC__
+mpn_sqrtrem (mp_ptr root_ptr, mp_ptr rem_ptr, mp_srcptr op_ptr, mp_size_t op_size)
+#else
+mpn_sqrtrem (root_ptr, rem_ptr, op_ptr, op_size)
+ mp_ptr root_ptr;
+ mp_ptr rem_ptr;
+ mp_srcptr op_ptr;
+ mp_size_t op_size;
+#endif
+{
+ /* R (root result) */
+ mp_ptr rp; /* Pointer to least significant word */
+ mp_size_t rsize; /* The size in words */
+
+ /* T (OP shifted to the left a.k.a. normalized) */
+ mp_ptr tp; /* Pointer to least significant word */
+ mp_size_t tsize; /* The size in words */
+ mp_ptr t_end_ptr; /* Pointer right beyond most sign. word */
+ mp_limb_t t_high0, t_high1; /* The two most significant words */
+
+ /* TT (temporary for numerator/remainder) */
+ mp_ptr ttp; /* Pointer to least significant word */
+
+ /* X (temporary for quotient in main loop) */
+ mp_ptr xp; /* Pointer to least significant word */
+ mp_size_t xsize; /* The size in words */
+
+ unsigned cnt;
+ mp_limb_t initial_approx; /* Initially made approximation */
+ mp_size_t tsizes[BITS_PER_MP_LIMB]; /* Successive calculation precisions */
+ mp_size_t tmp;
+ mp_size_t i;
+
+ mp_limb_t cy_limb;
+ TMP_DECL (marker);
+
+ /* If OP is zero, both results are zero. */
+ if (op_size == 0)
+ return 0;
+
+ count_leading_zeros (cnt, op_ptr[op_size - 1]);
+ tsize = op_size;
+ if ((tsize & 1) != 0)
+ {
+ cnt += BITS_PER_MP_LIMB;
+ tsize++;
+ }
+
+ rsize = tsize / 2;
+ rp = root_ptr;
+
+ TMP_MARK (marker);
+
+ /* Shift OP an even number of bits into T, such that either the most or
+ the second most significant bit is set, and such that the number of
+ words in T becomes even. This way, the number of words in R=sqrt(OP)
+ is exactly half as many as in OP, and the most significant bit of R
+ is set.
+
+ Also, the initial approximation is simplified by this up-shifted OP.
+
+ Finally, the Newtonian iteration which is the main part of this
+ program performs division by R. The fast division routine expects
+ the divisor to be "normalized" in exactly the sense of having the
+ most significant bit set. */
+
+ tp = (mp_ptr) TMP_ALLOC (tsize * BYTES_PER_MP_LIMB);
+
+ if ((cnt & ~1) % BITS_PER_MP_LIMB != 0)
+ t_high0 = mpn_lshift (tp + cnt / BITS_PER_MP_LIMB, op_ptr, op_size,
+ (cnt & ~1) % BITS_PER_MP_LIMB);
+ else
+ MPN_COPY (tp + cnt / BITS_PER_MP_LIMB, op_ptr, op_size);
+
+ if (cnt >= BITS_PER_MP_LIMB)
+ tp[0] = 0;
+
+ t_high0 = tp[tsize - 1];
+ t_high1 = tp[tsize - 2]; /* Never stray. TSIZE is >= 2. */
+
+/* Is there a fast sqrt instruction defined for this machine? */
+#ifdef SQRT
+ {
+ initial_approx = SQRT (t_high0 * 2.0
+ * ((mp_limb_t) 1 << (BITS_PER_MP_LIMB - 1))
+ + t_high1);
+ /* If t_high0,,t_high1 is big, the result in INITIAL_APPROX might have
+ become incorrect due to overflow in the conversion from double to
+ mp_limb_t above. It will typically be zero in that case, but might be
+ a small number on some machines. The most significant bit of
+ INITIAL_APPROX should be set, so that bit is a good overflow
+ indication. */
+ if ((mp_limb_signed_t) initial_approx >= 0)
+ initial_approx = ~(mp_limb_t)0;
+ }
+#else
+ /* Get a 9 bit approximation from the tables. The tables expect to
+ be indexed with the 8 high bits right below the highest bit.
+ Also, the highest result bit is not returned by the tables, and
+ must be or:ed into the result. The scheme gives 9 bits of start
+ approximation with just 256-entry 8 bit tables. */
+
+ if ((cnt & 1) == 0)
+ {
+ /* The most sign bit of t_high0 is set. */
+ initial_approx = t_high0 >> (BITS_PER_MP_LIMB - 8 - 1);
+ initial_approx &= 0xff;
+ initial_approx = even_approx_tab[initial_approx];
+ }
+ else
+ {
+ /* The most significant bit of T_HIGH0 is unset,
+ the second most significant is set. */
+ initial_approx = t_high0 >> (BITS_PER_MP_LIMB - 8 - 2);
+ initial_approx &= 0xff;
+ initial_approx = odd_approx_tab[initial_approx];
+ }
+ initial_approx |= 0x100;
+ initial_approx <<= BITS_PER_MP_LIMB - 8 - 1;
+
+ /* Perform small precision Newtonian iterations to get a full word
+ approximation. For small operands, these iteration will make the
+ entire job. */
+ if (t_high0 == ~(mp_limb_t)0)
+ initial_approx = t_high0;
+ else
+ {
+ mp_limb_t quot;
+
+ if (t_high0 >= initial_approx)
+ initial_approx = t_high0 + 1;
+
+ /* First get about 18 bits with pure C arithmetics. */
+ quot = t_high0 / (initial_approx >> BITS_PER_MP_LIMB/2) << BITS_PER_MP_LIMB/2;
+ initial_approx = (initial_approx + quot) / 2;
+ initial_approx |= (mp_limb_t) 1 << (BITS_PER_MP_LIMB - 1);
+
+ /* Now get a full word by one (or for > 36 bit machines) several
+ iterations. */
+ for (i = 16; i < BITS_PER_MP_LIMB; i <<= 1)
+ {
+ mp_limb_t ignored_remainder;
+
+ udiv_qrnnd (quot, ignored_remainder,
+ t_high0, t_high1, initial_approx);
+ initial_approx = (initial_approx + quot) / 2;
+ initial_approx |= (mp_limb_t) 1 << (BITS_PER_MP_LIMB - 1);
+ }
+ }
+#endif
+
+ rp[0] = initial_approx;
+ rsize = 1;
+
+#ifdef DEBUG
+ printf ("\n\nT = ");
+ mpn_dump (tp, tsize);
+#endif
+
+ if (tsize > 2)
+ {
+ /* Determine the successive precisions to use in the iteration. We
+ minimize the precisions, beginning with the highest (i.e. last
+ iteration) to the lowest (i.e. first iteration). */
+
+ xp = (mp_ptr) TMP_ALLOC (tsize * BYTES_PER_MP_LIMB);
+ ttp = (mp_ptr) TMP_ALLOC (tsize * BYTES_PER_MP_LIMB);
+
+ t_end_ptr = tp + tsize;
+
+ tmp = tsize / 2;
+ for (i = 0;; i++)
+ {
+ tsize = (tmp + 1) / 2;
+ if (tmp == tsize)
+ break;
+ tsizes[i] = tsize + tmp;
+ tmp = tsize;
+ }
+
+ /* Main Newton iteration loop. For big arguments, most of the
+ time is spent here. */
+
+ /* It is possible to do a great optimization here. The successive
+ divisors in the mpn_divmod call below has more and more leading
+ words equal to its predecessor. Therefore the beginning of
+ each division will repeat the same work as did the last
+ division. If we could guarantee that the leading words of two
+ consecutive divisors are the same (i.e. in this case, a later
+ divisor has just more digits at the end) it would be a simple
+ matter of just using the old remainder of the last division in
+ a subsequent division, to take care of this optimization. This
+ idea would surely make a difference even for small arguments. */
+
+ /* Loop invariants:
+
+ R <= shiftdown_to_same_size(floor(sqrt(OP))) < R + 1.
+ X - 1 < shiftdown_to_same_size(floor(sqrt(OP))) <= X.
+ R <= shiftdown_to_same_size(X). */
+
+ while (--i >= 0)
+ {
+ mp_limb_t cy;
+#ifdef DEBUG
+ mp_limb_t old_least_sign_r = rp[0];
+ mp_size_t old_rsize = rsize;
+
+ printf ("R = ");
+ mpn_dump (rp, rsize);
+#endif
+ tsize = tsizes[i];
+
+ /* Need to copy the numerator into temporary space, as
+ mpn_divmod overwrites its numerator argument with the
+ remainder (which we currently ignore). */
+ MPN_COPY (ttp, t_end_ptr - tsize, tsize);
+ cy = mpn_divmod (xp, ttp, tsize, rp, rsize);
+ xsize = tsize - rsize;
+
+#ifdef DEBUG
+ printf ("X =%d ", cy);
+ mpn_dump (xp, xsize);
+#endif
+
+ /* Add X and R with the most significant limbs aligned,
+ temporarily ignoring at least one limb at the low end of X. */
+ tmp = xsize - rsize;
+ cy += mpn_add_n (xp + tmp, rp, xp + tmp, rsize);
+
+ /* If T begins with more than 2 x BITS_PER_MP_LIMB of ones, we get
+ intermediate roots that'd need an extra bit. We don't want to
+ handle that since it would make the subsequent divisor
+ non-normalized, so round such roots down to be only ones in the
+ current precision. */
+ if (cy == 2)
+ {
+ mp_size_t j;
+ for (j = xsize; j >= 0; j--)
+ xp[j] = ~(mp_limb_t)0;
+ }
+
+ /* Divide X by 2 and put the result in R. This is the new
+ approximation. Shift in the carry from the addition. */
+ mpn_rshift (rp, xp, xsize, 1);
+ rp[xsize - 1] |= ((mp_limb_t) 1 << (BITS_PER_MP_LIMB - 1));
+ rsize = xsize;
+#ifdef DEBUG
+ if (old_least_sign_r != rp[rsize - old_rsize])
+ printf (">>>>>>>> %d: %0*lX, %0*lX <<<<<<<<\n",
+ i, 2 * BYTES_PER_MP_LIMB, old_least_sign_r,
+ 2 * BYTES_PER_MP_LIMB, rp[rsize - old_rsize]);
+#endif
+ }
+ }
+
+#ifdef DEBUG
+ printf ("(final) R = ");
+ mpn_dump (rp, rsize);
+#endif
+
+ /* We computed the square root of OP * 2**(2*floor(cnt/2)).
+ This has resulted in R being 2**floor(cnt/2) to large.
+ Shift it down here to fix that. */
+ if (cnt / 2 != 0)
+ {
+ mpn_rshift (rp, rp, rsize, cnt/2);
+ rsize -= rp[rsize - 1] == 0;
+ }
+
+ /* Calculate the remainder. */
+ mpn_mul_n (tp, rp, rp, rsize);
+ tsize = rsize + rsize;
+ tsize -= tp[tsize - 1] == 0;
+ if (op_size < tsize
+ || (op_size == tsize && mpn_cmp (op_ptr, tp, op_size) < 0))
+ {
+ /* R is too large. Decrement it. */
+
+ /* These operations can't overflow. */
+ cy_limb = mpn_sub_n (tp, tp, rp, rsize);
+ cy_limb += mpn_sub_n (tp, tp, rp, rsize);
+ mpn_sub_1 (tp + rsize, tp + rsize, tsize - rsize, cy_limb);
+ mpn_add_1 (tp, tp, tsize, (mp_limb_t) 1);
+
+ mpn_sub_1 (rp, rp, rsize, (mp_limb_t) 1);
+
+#ifdef DEBUG
+ printf ("(adjusted) R = ");
+ mpn_dump (rp, rsize);
+#endif
+ }
+
+ if (rem_ptr != NULL)
+ {
+ cy_limb = mpn_sub (rem_ptr, op_ptr, op_size, tp, tsize);
+ MPN_NORMALIZE (rem_ptr, op_size);
+ TMP_FREE (marker);
+ return op_size;
+ }
+ else
+ {
+ int res;
+ res = op_size != tsize || mpn_cmp (op_ptr, tp, op_size);
+ TMP_FREE (marker);
+ return res;
+ }
+}
diff --git a/mpn/generic/sub_n.c b/mpn/generic/sub_n.c
new file mode 100644
index 000000000..9d4b21675
--- /dev/null
+++ b/mpn/generic/sub_n.c
@@ -0,0 +1,62 @@
+/* mpn_sub_n -- Subtract two limb vectors of equal, non-zero length.
+
+Copyright (C) 1992, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+mp_limb_t
+#if __STDC__
+mpn_sub_n (mp_ptr res_ptr, mp_srcptr s1_ptr, mp_srcptr s2_ptr, mp_size_t size)
+#else
+mpn_sub_n (res_ptr, s1_ptr, s2_ptr, size)
+ register mp_ptr res_ptr;
+ register mp_srcptr s1_ptr;
+ register mp_srcptr s2_ptr;
+ mp_size_t size;
+#endif
+{
+ register mp_limb_t x, y, cy;
+ register mp_size_t j;
+
+ /* The loop counter and index J goes from -SIZE to -1. This way
+ the loop becomes faster. */
+ j = -size;
+
+ /* Offset the base pointers to compensate for the negative indices. */
+ s1_ptr -= j;
+ s2_ptr -= j;
+ res_ptr -= j;
+
+ cy = 0;
+ do
+ {
+ y = s2_ptr[j];
+ x = s1_ptr[j];
+ y += cy; /* add previous carry to subtrahend */
+ cy = (y < cy); /* get out carry from that addition */
+ y = x - y; /* main subtract */
+ cy = (y > x) + cy; /* get out carry from the subtract, combine */
+ res_ptr[j] = y;
+ }
+ while (++j != 0);
+
+ return cy;
+}
diff --git a/mpn/generic/submul_1.c b/mpn/generic/submul_1.c
new file mode 100644
index 000000000..b144283bd
--- /dev/null
+++ b/mpn/generic/submul_1.c
@@ -0,0 +1,65 @@
+/* mpn_submul_1 -- multiply the S1_SIZE long limb vector pointed to by S1_PTR
+ by S2_LIMB, subtract the S1_SIZE least significant limbs of the product
+ from the limb vector pointed to by RES_PTR. Return the most significant
+ limb of the product, adjusted for carry-out from the subtraction.
+
+Copyright (C) 1992, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+mp_limb_t
+mpn_submul_1 (res_ptr, s1_ptr, s1_size, s2_limb)
+ register mp_ptr res_ptr;
+ register mp_srcptr s1_ptr;
+ mp_size_t s1_size;
+ register mp_limb_t s2_limb;
+{
+ register mp_limb_t cy_limb;
+ register mp_size_t j;
+ register mp_limb_t prod_high, prod_low;
+ register mp_limb_t x;
+
+ /* The loop counter and index J goes from -SIZE to -1. This way
+ the loop becomes faster. */
+ j = -s1_size;
+
+ /* Offset the base pointers to compensate for the negative indices. */
+ res_ptr -= j;
+ s1_ptr -= j;
+
+ cy_limb = 0;
+ do
+ {
+ umul_ppmm (prod_high, prod_low, s1_ptr[j], s2_limb);
+
+ prod_low += cy_limb;
+ cy_limb = (prod_low < cy_limb) + prod_high;
+
+ x = res_ptr[j];
+ prod_low = x - prod_low;
+ cy_limb += (prod_low > x);
+ res_ptr[j] = prod_low;
+ }
+ while (++j != 0);
+
+ return cy_limb;
+}
diff --git a/mpn/generic/udiv_w_sdiv.c b/mpn/generic/udiv_w_sdiv.c
new file mode 100644
index 000000000..d9e71b78a
--- /dev/null
+++ b/mpn/generic/udiv_w_sdiv.c
@@ -0,0 +1,125 @@
+/* mpn_udiv_w_sdiv -- implement udiv_qrnnd on machines with only signed
+ division.
+
+ Contributed by Peter L. Montgomery.
+
+Copyright (C) 1992, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+mp_limb_t
+mpn_udiv_w_sdiv (rp, a1, a0, d)
+ mp_limb_t *rp, a1, a0, d;
+{
+ mp_limb_t q, r;
+ mp_limb_t c0, c1, b1;
+
+ if ((mp_limb_signed_t) d >= 0)
+ {
+ if (a1 < d - a1 - (a0 >> (BITS_PER_MP_LIMB - 1)))
+ {
+ /* dividend, divisor, and quotient are nonnegative */
+ sdiv_qrnnd (q, r, a1, a0, d);
+ }
+ else
+ {
+ /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */
+ sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (BITS_PER_MP_LIMB - 1));
+ /* Divide (c1*2^32 + c0) by d */
+ sdiv_qrnnd (q, r, c1, c0, d);
+ /* Add 2^31 to quotient */
+ q += (mp_limb_t) 1 << (BITS_PER_MP_LIMB - 1);
+ }
+ }
+ else
+ {
+ b1 = d >> 1; /* d/2, between 2^30 and 2^31 - 1 */
+ c1 = a1 >> 1; /* A/2 */
+ c0 = (a1 << (BITS_PER_MP_LIMB - 1)) + (a0 >> 1);
+
+ if (a1 < b1) /* A < 2^32*b1, so A/2 < 2^31*b1 */
+ {
+ sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
+
+ r = 2*r + (a0 & 1); /* Remainder from A/(2*b1) */
+ if ((d & 1) != 0)
+ {
+ if (r >= q)
+ r = r - q;
+ else if (q - r <= d)
+ {
+ r = r - q + d;
+ q--;
+ }
+ else
+ {
+ r = r - q + 2*d;
+ q -= 2;
+ }
+ }
+ }
+ else if (c1 < b1) /* So 2^31 <= (A/2)/b1 < 2^32 */
+ {
+ c1 = (b1 - 1) - c1;
+ c0 = ~c0; /* logical NOT */
+
+ sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
+
+ q = ~q; /* (A/2)/b1 */
+ r = (b1 - 1) - r;
+
+ r = 2*r + (a0 & 1); /* A/(2*b1) */
+
+ if ((d & 1) != 0)
+ {
+ if (r >= q)
+ r = r - q;
+ else if (q - r <= d)
+ {
+ r = r - q + d;
+ q--;
+ }
+ else
+ {
+ r = r - q + 2*d;
+ q -= 2;
+ }
+ }
+ }
+ else /* Implies c1 = b1 */
+ { /* Hence a1 = d - 1 = 2*b1 - 1 */
+ if (a0 >= -d)
+ {
+ q = -1;
+ r = a0 + d;
+ }
+ else
+ {
+ q = -2;
+ r = a0 + 2*d;
+ }
+ }
+ }
+
+ *rp = r;
+ return q;
+}
diff --git a/mpn/hppa/README b/mpn/hppa/README
new file mode 100644
index 000000000..5a2d5fd97
--- /dev/null
+++ b/mpn/hppa/README
@@ -0,0 +1,84 @@
+This directory contains mpn functions for various HP PA-RISC chips. Code
+that runs faster on the PA7100 and later implementations, is in the pa7100
+directory.
+
+RELEVANT OPTIMIZATION ISSUES
+
+ Load and Store timing
+
+On the PA7000 no memory instructions can issue the two cycles after a store.
+For the PA7100, this is reduced to one cycle.
+
+The PA7100 has a lookup-free cache, so it helps to schedule loads and the
+dependent instruction really far from each other.
+
+STATUS
+
+1. mpn_mul_1 could be improved to 6.5 cycles/limb on the PA7100, using the
+ instructions bwlow (but some sw pipelining is needed to avoid the
+ xmpyu-fstds delay):
+
+ fldds s1_ptr
+
+ xmpyu
+ fstds N(%r30)
+ xmpyu
+ fstds N(%r30)
+
+ ldws N(%r30)
+ ldws N(%r30)
+ ldws N(%r30)
+ ldws N(%r30)
+
+ addc
+ stws res_ptr
+ addc
+ stws res_ptr
+
+ addib Loop
+
+2. mpn_addmul_1 could be improved from the current 10 to 7.5 cycles/limb
+ (asymptotically) on the PA7100, using the instructions below. With proper
+ sw pipelining and the unrolling level below, the speed becomes 8
+ cycles/limb.
+
+ fldds s1_ptr
+ fldds s1_ptr
+
+ xmpyu
+ fstds N(%r30)
+ xmpyu
+ fstds N(%r30)
+ xmpyu
+ fstds N(%r30)
+ xmpyu
+ fstds N(%r30)
+
+ ldws N(%r30)
+ ldws N(%r30)
+ ldws N(%r30)
+ ldws N(%r30)
+ ldws N(%r30)
+ ldws N(%r30)
+ ldws N(%r30)
+ ldws N(%r30)
+ addc
+ addc
+ addc
+ addc
+ addc %r0,%r0,cy-limb
+
+ ldws res_ptr
+ ldws res_ptr
+ ldws res_ptr
+ ldws res_ptr
+ add
+ stws res_ptr
+ addc
+ stws res_ptr
+ addc
+ stws res_ptr
+ addc
+ stws res_ptr
+
+ addib
diff --git a/mpn/hppa/add_n.s b/mpn/hppa/add_n.s
new file mode 100644
index 000000000..b4a142836
--- /dev/null
+++ b/mpn/hppa/add_n.s
@@ -0,0 +1,58 @@
+; HP-PA __mpn_add_n -- Add two limb vectors of the same length > 0 and store
+; sum in a third limb vector.
+
+; Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+; This file is part of the GNU MP Library.
+
+; The GNU MP Library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Library General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or (at your
+; option) any later version.
+
+; The GNU MP Library 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 Library General Public
+; License for more details.
+
+; You should have received a copy of the GNU Library General Public License
+; along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+; MA 02111-1307, USA.
+
+
+; INPUT PARAMETERS
+; res_ptr gr26
+; s1_ptr gr25
+; s2_ptr gr24
+; size gr23
+
+; One might want to unroll this as for other processors, but it turns
+; out that the data cache contention after a store makes such
+; unrolling useless. We can't come under 5 cycles/limb anyway.
+
+ .code
+ .export __mpn_add_n
+__mpn_add_n
+ .proc
+ .callinfo frame=0,no_calls
+ .entry
+
+ ldws,ma 4(0,%r25),%r20
+ ldws,ma 4(0,%r24),%r19
+
+ addib,= -1,%r23,L$end ; check for (SIZE == 1)
+ add %r20,%r19,%r28 ; add first limbs ignoring cy
+
+L$loop ldws,ma 4(0,%r25),%r20
+ ldws,ma 4(0,%r24),%r19
+ stws,ma %r28,4(0,%r26)
+ addib,<> -1,%r23,L$loop
+ addc %r20,%r19,%r28
+
+L$end stws %r28,0(0,%r26)
+ bv 0(%r2)
+ addc %r0,%r0,%r28
+
+ .exit
+ .procend
diff --git a/mpn/hppa/hppa1_1/addmul_1.s b/mpn/hppa/hppa1_1/addmul_1.s
new file mode 100644
index 000000000..0fdcb3cb2
--- /dev/null
+++ b/mpn/hppa/hppa1_1/addmul_1.s
@@ -0,0 +1,102 @@
+; HP-PA-1.1 __mpn_addmul_1 -- Multiply a limb vector with a limb and
+; add the result to a second limb vector.
+
+; Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
+
+; This file is part of the GNU MP Library.
+
+; The GNU MP Library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Library General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or (at your
+; option) any later version.
+
+; The GNU MP Library 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 Library General Public
+; License for more details.
+
+; You should have received a copy of the GNU Library General Public License
+; along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+; MA 02111-1307, USA.
+
+
+; INPUT PARAMETERS
+; res_ptr r26
+; s1_ptr r25
+; size r24
+; s2_limb r23
+
+; This runs at 11 cycles/limb on a PA7000. With the used instructions, it
+; can not become faster due to data cache contention after a store. On the
+; PA7100 it runs at 10 cycles/limb, and that can not be improved either,
+; since only the xmpyu does not need the integer pipeline, so the only
+; dual-issue we will get are addc+xmpyu. Unrolling could gain a cycle/limb
+; on the PA7100.
+
+; There are some ideas described in mul_1.s that applies to this code too.
+
+ .code
+ .export __mpn_addmul_1
+__mpn_addmul_1
+ .proc
+ .callinfo frame=64,no_calls
+ .entry
+
+ ldo 64(%r30),%r30
+ fldws,ma 4(%r25),%fr5
+ stw %r23,-16(%r30) ; move s2_limb ...
+ addib,= -1,%r24,L$just_one_limb
+ fldws -16(%r30),%fr4 ; ... into fr4
+ add %r0,%r0,%r0 ; clear carry
+ xmpyu %fr4,%fr5,%fr6
+ fldws,ma 4(%r25),%fr7
+ fstds %fr6,-16(%r30)
+ xmpyu %fr4,%fr7,%fr8
+ ldw -12(%r30),%r19 ; least significant limb in product
+ ldw -16(%r30),%r28
+
+ fstds %fr8,-16(%r30)
+ addib,= -1,%r24,L$end
+ ldw -12(%r30),%r1
+
+; Main loop
+L$loop ldws 0(%r26),%r29
+ fldws,ma 4(%r25),%fr5
+ add %r29,%r19,%r19
+ stws,ma %r19,4(%r26)
+ addc %r28,%r1,%r19
+ xmpyu %fr4,%fr5,%fr6
+ ldw -16(%r30),%r28
+ fstds %fr6,-16(%r30)
+ addc %r0,%r28,%r28
+ addib,<> -1,%r24,L$loop
+ ldw -12(%r30),%r1
+
+L$end ldw 0(%r26),%r29
+ add %r29,%r19,%r19
+ stws,ma %r19,4(%r26)
+ addc %r28,%r1,%r19
+ ldw -16(%r30),%r28
+ ldws 0(%r26),%r29
+ addc %r0,%r28,%r28
+ add %r29,%r19,%r19
+ stws,ma %r19,4(%r26)
+ addc %r0,%r28,%r28
+ bv 0(%r2)
+ ldo -64(%r30),%r30
+
+L$just_one_limb
+ xmpyu %fr4,%fr5,%fr6
+ ldw 0(%r26),%r29
+ fstds %fr6,-16(%r30)
+ ldw -12(%r30),%r1
+ ldw -16(%r30),%r28
+ add %r29,%r1,%r19
+ stw %r19,0(%r26)
+ addc %r0,%r28,%r28
+ bv 0(%r2)
+ ldo -64(%r30),%r30
+
+ .exit
+ .procend
diff --git a/mpn/hppa/hppa1_1/mul_1.s b/mpn/hppa/hppa1_1/mul_1.s
new file mode 100644
index 000000000..cdd0c1d7f
--- /dev/null
+++ b/mpn/hppa/hppa1_1/mul_1.s
@@ -0,0 +1,98 @@
+; HP-PA-1.1 __mpn_mul_1 -- Multiply a limb vector with a limb and store
+; the result in a second limb vector.
+
+; Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
+
+; This file is part of the GNU MP Library.
+
+; The GNU MP Library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Library General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or (at your
+; option) any later version.
+
+; The GNU MP Library 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 Library General Public
+; License for more details.
+
+; You should have received a copy of the GNU Library General Public License
+; along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+; MA 02111-1307, USA.
+
+
+; INPUT PARAMETERS
+; res_ptr r26
+; s1_ptr r25
+; size r24
+; s2_limb r23
+
+; This runs at 9 cycles/limb on a PA7000. With the used instructions, it can
+; not become faster due to data cache contention after a store. On the
+; PA7100 it runs at 7 cycles/limb, and that can not be improved either, since
+; only the xmpyu does not need the integer pipeline, so the only dual-issue
+; we will get are addc+xmpyu. Unrolling would not help either CPU.
+
+; We could use fldds to read two limbs at a time from the S1 array, and that
+; could bring down the times to 8.5 and 6.5 cycles/limb for the PA7000 and
+; PA7100, respectively. We don't do that since it does not seem worth the
+; (alignment) troubles...
+
+; At least the PA7100 is rumored to be able to deal with cache-misses
+; without stalling instruction issue. If this is true, and the cache is
+; actually also lockup-free, we should use a deeper software pipeline, and
+; load from S1 very early! (The loads and stores to -12(sp) will surely be
+; in the cache.)
+
+ .code
+ .export __mpn_mul_1
+__mpn_mul_1
+ .proc
+ .callinfo frame=64,no_calls
+ .entry
+
+ ldo 64(%r30),%r30
+ fldws,ma 4(%r25),%fr5
+ stw %r23,-16(%r30) ; move s2_limb ...
+ addib,= -1,%r24,L$just_one_limb
+ fldws -16(%r30),%fr4 ; ... into fr4
+ add %r0,%r0,%r0 ; clear carry
+ xmpyu %fr4,%fr5,%fr6
+ fldws,ma 4(%r25),%fr7
+ fstds %fr6,-16(%r30)
+ xmpyu %fr4,%fr7,%fr8
+ ldw -12(%r30),%r19 ; least significant limb in product
+ ldw -16(%r30),%r28
+
+ fstds %fr8,-16(%r30)
+ addib,= -1,%r24,L$end
+ ldw -12(%r30),%r1
+
+; Main loop
+L$loop fldws,ma 4(%r25),%fr5
+ stws,ma %r19,4(%r26)
+ addc %r28,%r1,%r19
+ xmpyu %fr4,%fr5,%fr6
+ ldw -16(%r30),%r28
+ fstds %fr6,-16(%r30)
+ addib,<> -1,%r24,L$loop
+ ldw -12(%r30),%r1
+
+L$end stws,ma %r19,4(%r26)
+ addc %r28,%r1,%r19
+ ldw -16(%r30),%r28
+ stws,ma %r19,4(%r26)
+ addc %r0,%r28,%r28
+ bv 0(%r2)
+ ldo -64(%r30),%r30
+
+L$just_one_limb
+ xmpyu %fr4,%fr5,%fr6
+ fstds %fr6,-16(%r30)
+ ldw -16(%r30),%r28
+ ldo -64(%r30),%r30
+ bv 0(%r2)
+ fstws %fr6R,0(%r26)
+
+ .exit
+ .procend
diff --git a/mpn/hppa/hppa1_1/pa7100/add_n.s b/mpn/hppa/hppa1_1/pa7100/add_n.s
new file mode 100644
index 000000000..21fe16154
--- /dev/null
+++ b/mpn/hppa/hppa1_1/pa7100/add_n.s
@@ -0,0 +1,75 @@
+; HP-PA __mpn_add_n -- Add two limb vectors of the same length > 0 and store
+; sum in a third limb vector.
+; This is optimized for the PA7100, where is runs at 4.25 cycles/limb
+
+; Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+; This file is part of the GNU MP Library.
+
+; The GNU MP Library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Library General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or (at your
+; option) any later version.
+
+; The GNU MP Library 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 Library General Public
+; License for more details.
+
+; You should have received a copy of the GNU Library General Public License
+; along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+; MA 02111-1307, USA.
+
+
+; INPUT PARAMETERS
+; res_ptr gr26
+; s1_ptr gr25
+; s2_ptr gr24
+; size gr23
+
+ .code
+ .export __mpn_add_n
+__mpn_add_n
+ .proc
+ .callinfo frame=0,no_calls
+ .entry
+
+ ldws,ma 4(0,%r25),%r20
+ ldws,ma 4(0,%r24),%r19
+
+ addib,<= -5,%r23,L$rest
+ add %r20,%r19,%r28 ; add first limbs ignoring cy
+
+L$loop ldws,ma 4(0,%r25),%r20
+ ldws,ma 4(0,%r24),%r19
+ stws,ma %r28,4(0,%r26)
+ addc %r20,%r19,%r28
+ ldws,ma 4(0,%r25),%r20
+ ldws,ma 4(0,%r24),%r19
+ stws,ma %r28,4(0,%r26)
+ addc %r20,%r19,%r28
+ ldws,ma 4(0,%r25),%r20
+ ldws,ma 4(0,%r24),%r19
+ stws,ma %r28,4(0,%r26)
+ addc %r20,%r19,%r28
+ ldws,ma 4(0,%r25),%r20
+ ldws,ma 4(0,%r24),%r19
+ stws,ma %r28,4(0,%r26)
+ addib,> -4,%r23,L$loop
+ addc %r20,%r19,%r28
+
+L$rest addib,= 4,%r23,L$end
+ nop
+L$eloop ldws,ma 4(0,%r25),%r20
+ ldws,ma 4(0,%r24),%r19
+ stws,ma %r28,4(0,%r26)
+ addib,> -1,%r23,L$eloop
+ addc %r20,%r19,%r28
+
+L$end stws %r28,0(0,%r26)
+ bv 0(%r2)
+ addc %r0,%r0,%r28
+
+ .exit
+ .procend
diff --git a/mpn/hppa/hppa1_1/pa7100/addmul_1.S b/mpn/hppa/hppa1_1/pa7100/addmul_1.S
new file mode 100644
index 000000000..eb1d12bf6
--- /dev/null
+++ b/mpn/hppa/hppa1_1/pa7100/addmul_1.S
@@ -0,0 +1,189 @@
+; HP-PA 7100/7200 __mpn_addmul_1 -- Multiply a limb vector with a limb and
+; add the result to a second limb vector.
+
+; Copyright (C) 1995 Free Software Foundation, Inc.
+
+; This file is part of the GNU MP Library.
+
+; The GNU MP Library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Library General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or (at your
+; option) any later version.
+
+; The GNU MP Library 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 Library General Public
+; License for more details.
+
+; You should have received a copy of the GNU Library General Public License
+; along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+; MA 02111-1307, USA.
+
+; INPUT PARAMETERS
+#define res_ptr %r26
+#define s1_ptr %r25
+#define size %r24
+#define s2_limb %r23
+
+#define cylimb %r28
+#define s0 %r19
+#define s1 %r20
+#define s2 %r3
+#define s3 %r4
+#define lo0 %r21
+#define lo1 %r5
+#define lo2 %r6
+#define lo3 %r7
+#define hi0 %r22
+#define hi1 %r23 /* safe to reuse */
+#define hi2 %r29
+#define hi3 %r1
+
+ .code
+ .export __mpn_addmul_1
+__mpn_addmul_1
+ .proc
+ .callinfo frame=128,no_calls
+ .entry
+
+ ldo 128(%r30),%r30
+ stws s2_limb,-16(%r30)
+ add %r0,%r0,cylimb ; clear cy and cylimb
+ addib,< -4,size,L$few_limbs
+ fldws -16(%r30),%fr31R
+
+ ldo -112(%r30),%r31
+ stw %r3,-96(%r30)
+ stw %r4,-92(%r30)
+ stw %r5,-88(%r30)
+ stw %r6,-84(%r30)
+ stw %r7,-80(%r30)
+
+ bb,>=,n s1_ptr,29,L$0
+
+ fldws,ma 4(s1_ptr),%fr4
+ ldws 0(res_ptr),s0
+ xmpyu %fr4,%fr31R,%fr5
+ fstds %fr5,-16(%r31)
+ ldws -16(%r31),cylimb
+ ldws -12(%r31),lo0
+ add s0,lo0,s0
+ addib,< -1,size,L$few_limbs
+ stws,ma s0,4(res_ptr)
+
+; start software pipeline ----------------------------------------------------
+L$0 fldds,ma 8(s1_ptr),%fr4
+ fldds,ma 8(s1_ptr),%fr8
+
+ xmpyu %fr4L,%fr31R,%fr5
+ xmpyu %fr4R,%fr31R,%fr6
+ xmpyu %fr8L,%fr31R,%fr9
+ xmpyu %fr8R,%fr31R,%fr10
+
+ fstds %fr5,-16(%r31)
+ fstds %fr6,-8(%r31)
+ fstds %fr9,0(%r31)
+ fstds %fr10,8(%r31)
+
+ ldws -16(%r31),hi0
+ ldws -12(%r31),lo0
+ ldws -8(%r31),hi1
+ ldws -4(%r31),lo1
+ ldws 0(%r31),hi2
+ ldws 4(%r31),lo2
+ ldws 8(%r31),hi3
+ ldws 12(%r31),lo3
+
+ addc lo0,cylimb,lo0
+ addc lo1,hi0,lo1
+ addc lo2,hi1,lo2
+ addc lo3,hi2,lo3
+
+ addib,< -4,size,L$end
+ addc %r0,hi3,cylimb ; propagate carry into cylimb
+; main loop ------------------------------------------------------------------
+L$loop fldds,ma 8(s1_ptr),%fr4
+ fldds,ma 8(s1_ptr),%fr8
+
+ ldws 0(res_ptr),s0
+ xmpyu %fr4L,%fr31R,%fr5
+ ldws 4(res_ptr),s1
+ xmpyu %fr4R,%fr31R,%fr6
+ ldws 8(res_ptr),s2
+ xmpyu %fr8L,%fr31R,%fr9
+ ldws 12(res_ptr),s3
+ xmpyu %fr8R,%fr31R,%fr10
+
+ fstds %fr5,-16(%r31)
+ add s0,lo0,s0
+ fstds %fr6,-8(%r31)
+ addc s1,lo1,s1
+ fstds %fr9,0(%r31)
+ addc s2,lo2,s2
+ fstds %fr10,8(%r31)
+ addc s3,lo3,s3
+
+ ldws -16(%r31),hi0
+ ldws -12(%r31),lo0
+ ldws -8(%r31),hi1
+ ldws -4(%r31),lo1
+ ldws 0(%r31),hi2
+ ldws 4(%r31),lo2
+ ldws 8(%r31),hi3
+ ldws 12(%r31),lo3
+
+ addc lo0,cylimb,lo0
+ stws,ma s0,4(res_ptr)
+ addc lo1,hi0,lo1
+ stws,ma s1,4(res_ptr)
+ addc lo2,hi1,lo2
+ stws,ma s2,4(res_ptr)
+ addc lo3,hi2,lo3
+ stws,ma s3,4(res_ptr)
+
+ addib,>= -4,size,L$loop
+ addc %r0,hi3,cylimb ; propagate carry into cylimb
+; finish software pipeline ---------------------------------------------------
+L$end ldws 0(res_ptr),s0
+ ldws 4(res_ptr),s1
+ ldws 8(res_ptr),s2
+ ldws 12(res_ptr),s3
+
+ add s0,lo0,s0
+ stws,ma s0,4(res_ptr)
+ addc s1,lo1,s1
+ stws,ma s1,4(res_ptr)
+ addc s2,lo2,s2
+ stws,ma s2,4(res_ptr)
+ addc s3,lo3,s3
+ stws,ma s3,4(res_ptr)
+
+; restore callee-saves registers ---------------------------------------------
+ ldw -96(%r30),%r3
+ ldw -92(%r30),%r4
+ ldw -88(%r30),%r5
+ ldw -84(%r30),%r6
+ ldw -80(%r30),%r7
+
+L$few_limbs
+ addib,=,n 4,size,L$ret
+L$loop2 fldws,ma 4(s1_ptr),%fr4
+ ldws 0(res_ptr),s0
+ xmpyu %fr4,%fr31R,%fr5
+ fstds %fr5,-16(%r30)
+ ldws -16(%r30),hi0
+ ldws -12(%r30),lo0
+ addc lo0,cylimb,lo0
+ addc %r0,hi0,cylimb
+ add s0,lo0,s0
+ stws,ma s0,4(res_ptr)
+ addib,<> -1,size,L$loop2
+ nop
+
+L$ret addc %r0,cylimb,cylimb
+ bv 0(%r2)
+ ldo -128(%r30),%r30
+
+ .exit
+ .procend
diff --git a/mpn/hppa/hppa1_1/pa7100/lshift.s b/mpn/hppa/hppa1_1/pa7100/lshift.s
new file mode 100644
index 000000000..4c74a505a
--- /dev/null
+++ b/mpn/hppa/hppa1_1/pa7100/lshift.s
@@ -0,0 +1,83 @@
+; HP-PA __mpn_lshift --
+; This is optimized for the PA7100, where is runs at 3.25 cycles/limb
+
+; Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+; This file is part of the GNU MP Library.
+
+; The GNU MP Library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Library General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or (at your
+; option) any later version.
+
+; The GNU MP Library 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 Library General Public
+; License for more details.
+
+; You should have received a copy of the GNU Library General Public License
+; along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+; MA 02111-1307, USA.
+
+
+; INPUT PARAMETERS
+; res_ptr gr26
+; s_ptr gr25
+; size gr24
+; cnt gr23
+
+ .code
+ .export __mpn_lshift
+__mpn_lshift
+ .proc
+ .callinfo frame=64,no_calls
+ .entry
+
+ sh2add %r24,%r25,%r25
+ sh2add %r24,%r26,%r26
+ ldws,mb -4(0,%r25),%r22
+ subi 32,%r23,%r1
+ mtsar %r1
+ addib,= -1,%r24,L$0004
+ vshd %r0,%r22,%r28 ; compute carry out limb
+ ldws,mb -4(0,%r25),%r29
+ addib,<= -5,%r24,L$rest
+ vshd %r22,%r29,%r20
+
+L$loop ldws,mb -4(0,%r25),%r22
+ stws,mb %r20,-4(0,%r26)
+ vshd %r29,%r22,%r20
+ ldws,mb -4(0,%r25),%r29
+ stws,mb %r20,-4(0,%r26)
+ vshd %r22,%r29,%r20
+ ldws,mb -4(0,%r25),%r22
+ stws,mb %r20,-4(0,%r26)
+ vshd %r29,%r22,%r20
+ ldws,mb -4(0,%r25),%r29
+ stws,mb %r20,-4(0,%r26)
+ addib,> -4,%r24,L$loop
+ vshd %r22,%r29,%r20
+
+L$rest addib,= 4,%r24,L$end1
+ nop
+L$eloop ldws,mb -4(0,%r25),%r22
+ stws,mb %r20,-4(0,%r26)
+ addib,<= -1,%r24,L$end2
+ vshd %r29,%r22,%r20
+ ldws,mb -4(0,%r25),%r29
+ stws,mb %r20,-4(0,%r26)
+ addib,> -1,%r24,L$eloop
+ vshd %r22,%r29,%r20
+
+L$end1 stws,mb %r20,-4(0,%r26)
+ vshd %r29,%r0,%r20
+ bv 0(%r2)
+ stw %r20,-4(0,%r26)
+L$end2 stws,mb %r20,-4(0,%r26)
+L$0004 vshd %r22,%r0,%r20
+ bv 0(%r2)
+ stw %r20,-4(0,%r26)
+
+ .exit
+ .procend
diff --git a/mpn/hppa/hppa1_1/pa7100/rshift.s b/mpn/hppa/hppa1_1/pa7100/rshift.s
new file mode 100644
index 000000000..845418c53
--- /dev/null
+++ b/mpn/hppa/hppa1_1/pa7100/rshift.s
@@ -0,0 +1,80 @@
+; HP-PA __mpn_rshift --
+; This is optimized for the PA7100, where is runs at 3.25 cycles/limb
+
+; Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+; This file is part of the GNU MP Library.
+
+; The GNU MP Library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Library General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or (at your
+; option) any later version.
+
+; The GNU MP Library 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 Library General Public
+; License for more details.
+
+; You should have received a copy of the GNU Library General Public License
+; along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+; MA 02111-1307, USA.
+
+
+; INPUT PARAMETERS
+; res_ptr gr26
+; s_ptr gr25
+; size gr24
+; cnt gr23
+
+ .code
+ .export __mpn_rshift
+__mpn_rshift
+ .proc
+ .callinfo frame=64,no_calls
+ .entry
+
+ ldws,ma 4(0,%r25),%r22
+ mtsar %r23
+ addib,= -1,%r24,L$0004
+ vshd %r22,%r0,%r28 ; compute carry out limb
+ ldws,ma 4(0,%r25),%r29
+ addib,<= -5,%r24,L$rest
+ vshd %r29,%r22,%r20
+
+L$loop ldws,ma 4(0,%r25),%r22
+ stws,ma %r20,4(0,%r26)
+ vshd %r22,%r29,%r20
+ ldws,ma 4(0,%r25),%r29
+ stws,ma %r20,4(0,%r26)
+ vshd %r29,%r22,%r20
+ ldws,ma 4(0,%r25),%r22
+ stws,ma %r20,4(0,%r26)
+ vshd %r22,%r29,%r20
+ ldws,ma 4(0,%r25),%r29
+ stws,ma %r20,4(0,%r26)
+ addib,> -4,%r24,L$loop
+ vshd %r29,%r22,%r20
+
+L$rest addib,= 4,%r24,L$end1
+ nop
+L$eloop ldws,ma 4(0,%r25),%r22
+ stws,ma %r20,4(0,%r26)
+ addib,<= -1,%r24,L$end2
+ vshd %r22,%r29,%r20
+ ldws,ma 4(0,%r25),%r29
+ stws,ma %r20,4(0,%r26)
+ addib,> -1,%r24,L$eloop
+ vshd %r29,%r22,%r20
+
+L$end1 stws,ma %r20,4(0,%r26)
+ vshd %r0,%r29,%r20
+ bv 0(%r2)
+ stw %r20,0(0,%r26)
+L$end2 stws,ma %r20,4(0,%r26)
+L$0004 vshd %r0,%r22,%r20
+ bv 0(%r2)
+ stw %r20,0(0,%r26)
+
+ .exit
+ .procend
diff --git a/mpn/hppa/hppa1_1/pa7100/sub_n.s b/mpn/hppa/hppa1_1/pa7100/sub_n.s
new file mode 100644
index 000000000..1e1ebcf91
--- /dev/null
+++ b/mpn/hppa/hppa1_1/pa7100/sub_n.s
@@ -0,0 +1,76 @@
+; HP-PA __mpn_sub_n -- Subtract two limb vectors of the same length > 0 and
+; store difference in a third limb vector.
+; This is optimized for the PA7100, where is runs at 4.25 cycles/limb
+
+; Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+; This file is part of the GNU MP Library.
+
+; The GNU MP Library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Library General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or (at your
+; option) any later version.
+
+; The GNU MP Library 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 Library General Public
+; License for more details.
+
+; You should have received a copy of the GNU Library General Public License
+; along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+; MA 02111-1307, USA.
+
+
+; INPUT PARAMETERS
+; res_ptr gr26
+; s1_ptr gr25
+; s2_ptr gr24
+; size gr23
+
+ .code
+ .export __mpn_sub_n
+__mpn_sub_n
+ .proc
+ .callinfo frame=0,no_calls
+ .entry
+
+ ldws,ma 4(0,%r25),%r20
+ ldws,ma 4(0,%r24),%r19
+
+ addib,<= -5,%r23,L$rest
+ sub %r20,%r19,%r28 ; subtract first limbs ignoring cy
+
+L$loop ldws,ma 4(0,%r25),%r20
+ ldws,ma 4(0,%r24),%r19
+ stws,ma %r28,4(0,%r26)
+ subb %r20,%r19,%r28
+ ldws,ma 4(0,%r25),%r20
+ ldws,ma 4(0,%r24),%r19
+ stws,ma %r28,4(0,%r26)
+ subb %r20,%r19,%r28
+ ldws,ma 4(0,%r25),%r20
+ ldws,ma 4(0,%r24),%r19
+ stws,ma %r28,4(0,%r26)
+ subb %r20,%r19,%r28
+ ldws,ma 4(0,%r25),%r20
+ ldws,ma 4(0,%r24),%r19
+ stws,ma %r28,4(0,%r26)
+ addib,> -4,%r23,L$loop
+ subb %r20,%r19,%r28
+
+L$rest addib,= 4,%r23,L$end
+ nop
+L$eloop ldws,ma 4(0,%r25),%r20
+ ldws,ma 4(0,%r24),%r19
+ stws,ma %r28,4(0,%r26)
+ addib,> -1,%r23,L$eloop
+ subb %r20,%r19,%r28
+
+L$end stws %r28,0(0,%r26)
+ addc %r0,%r0,%r28
+ bv 0(%r2)
+ subi 1,%r28,%r28
+
+ .exit
+ .procend
diff --git a/mpn/hppa/hppa1_1/pa7100/submul_1.S b/mpn/hppa/hppa1_1/pa7100/submul_1.S
new file mode 100644
index 000000000..a71176e68
--- /dev/null
+++ b/mpn/hppa/hppa1_1/pa7100/submul_1.S
@@ -0,0 +1,195 @@
+; HP-PA 7100/7200 __mpn_submul_1 -- Multiply a limb vector with a limb and
+; subtract the result from a second limb vector.
+
+; Copyright (C) 1995 Free Software Foundation, Inc.
+
+; This file is part of the GNU MP Library.
+
+; The GNU MP Library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Library General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or (at your
+; option) any later version.
+
+; The GNU MP Library 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 Library General Public
+; License for more details.
+
+; You should have received a copy of the GNU Library General Public License
+; along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+; MA 02111-1307, USA.
+
+; INPUT PARAMETERS
+#define res_ptr %r26
+#define s1_ptr %r25
+#define size %r24
+#define s2_limb %r23
+
+#define cylimb %r28
+#define s0 %r19
+#define s1 %r20
+#define s2 %r3
+#define s3 %r4
+#define lo0 %r21
+#define lo1 %r5
+#define lo2 %r6
+#define lo3 %r7
+#define hi0 %r22
+#define hi1 %r23 /* safe to reuse */
+#define hi2 %r29
+#define hi3 %r1
+
+ .code
+ .export __mpn_submul_1
+__mpn_submul_1
+ .proc
+ .callinfo frame=128,no_calls
+ .entry
+
+ ldo 128(%r30),%r30
+ stws s2_limb,-16(%r30)
+ add %r0,%r0,cylimb ; clear cy and cylimb
+ addib,< -4,size,L$few_limbs
+ fldws -16(%r30),%fr31R
+
+ ldo -112(%r30),%r31
+ stw %r3,-96(%r30)
+ stw %r4,-92(%r30)
+ stw %r5,-88(%r30)
+ stw %r6,-84(%r30)
+ stw %r7,-80(%r30)
+
+ bb,>=,n s1_ptr,29,L$0
+
+ fldws,ma 4(s1_ptr),%fr4
+ ldws 0(res_ptr),s0
+ xmpyu %fr4,%fr31R,%fr5
+ fstds %fr5,-16(%r31)
+ ldws -16(%r31),cylimb
+ ldws -12(%r31),lo0
+ sub s0,lo0,s0
+ add s0,lo0,%r0 ; invert cy
+ addib,< -1,size,L$few_limbs
+ stws,ma s0,4(res_ptr)
+
+; start software pipeline ----------------------------------------------------
+L$0 fldds,ma 8(s1_ptr),%fr4
+ fldds,ma 8(s1_ptr),%fr8
+
+ xmpyu %fr4L,%fr31R,%fr5
+ xmpyu %fr4R,%fr31R,%fr6
+ xmpyu %fr8L,%fr31R,%fr9
+ xmpyu %fr8R,%fr31R,%fr10
+
+ fstds %fr5,-16(%r31)
+ fstds %fr6,-8(%r31)
+ fstds %fr9,0(%r31)
+ fstds %fr10,8(%r31)
+
+ ldws -16(%r31),hi0
+ ldws -12(%r31),lo0
+ ldws -8(%r31),hi1
+ ldws -4(%r31),lo1
+ ldws 0(%r31),hi2
+ ldws 4(%r31),lo2
+ ldws 8(%r31),hi3
+ ldws 12(%r31),lo3
+
+ addc lo0,cylimb,lo0
+ addc lo1,hi0,lo1
+ addc lo2,hi1,lo2
+ addc lo3,hi2,lo3
+
+ addib,< -4,size,L$end
+ addc %r0,hi3,cylimb ; propagate carry into cylimb
+; main loop ------------------------------------------------------------------
+L$loop fldds,ma 8(s1_ptr),%fr4
+ fldds,ma 8(s1_ptr),%fr8
+
+ ldws 0(res_ptr),s0
+ xmpyu %fr4L,%fr31R,%fr5
+ ldws 4(res_ptr),s1
+ xmpyu %fr4R,%fr31R,%fr6
+ ldws 8(res_ptr),s2
+ xmpyu %fr8L,%fr31R,%fr9
+ ldws 12(res_ptr),s3
+ xmpyu %fr8R,%fr31R,%fr10
+
+ fstds %fr5,-16(%r31)
+ sub s0,lo0,s0
+ fstds %fr6,-8(%r31)
+ subb s1,lo1,s1
+ fstds %fr9,0(%r31)
+ subb s2,lo2,s2
+ fstds %fr10,8(%r31)
+ subb s3,lo3,s3
+ subb %r0,%r0,lo0 ; these two insns ...
+ add lo0,lo0,%r0 ; ... just invert cy
+
+ ldws -16(%r31),hi0
+ ldws -12(%r31),lo0
+ ldws -8(%r31),hi1
+ ldws -4(%r31),lo1
+ ldws 0(%r31),hi2
+ ldws 4(%r31),lo2
+ ldws 8(%r31),hi3
+ ldws 12(%r31),lo3
+
+ addc lo0,cylimb,lo0
+ stws,ma s0,4(res_ptr)
+ addc lo1,hi0,lo1
+ stws,ma s1,4(res_ptr)
+ addc lo2,hi1,lo2
+ stws,ma s2,4(res_ptr)
+ addc lo3,hi2,lo3
+ stws,ma s3,4(res_ptr)
+
+ addib,>= -4,size,L$loop
+ addc %r0,hi3,cylimb ; propagate carry into cylimb
+; finish software pipeline ---------------------------------------------------
+L$end ldws 0(res_ptr),s0
+ ldws 4(res_ptr),s1
+ ldws 8(res_ptr),s2
+ ldws 12(res_ptr),s3
+
+ sub s0,lo0,s0
+ stws,ma s0,4(res_ptr)
+ subb s1,lo1,s1
+ stws,ma s1,4(res_ptr)
+ subb s2,lo2,s2
+ stws,ma s2,4(res_ptr)
+ subb s3,lo3,s3
+ stws,ma s3,4(res_ptr)
+ subb %r0,%r0,lo0 ; these two insns ...
+ add lo0,lo0,%r0 ; ... invert cy
+
+; restore callee-saves registers ---------------------------------------------
+ ldw -96(%r30),%r3
+ ldw -92(%r30),%r4
+ ldw -88(%r30),%r5
+ ldw -84(%r30),%r6
+ ldw -80(%r30),%r7
+
+L$few_limbs
+ addib,=,n 4,size,L$ret
+L$loop2 fldws,ma 4(s1_ptr),%fr4
+ ldws 0(res_ptr),s0
+ xmpyu %fr4,%fr31R,%fr5
+ fstds %fr5,-16(%r30)
+ ldws -16(%r30),hi0
+ ldws -12(%r30),lo0
+ addc lo0,cylimb,lo0
+ addc %r0,hi0,cylimb
+ sub s0,lo0,s0
+ add s0,lo0,%r0 ; invert cy
+ stws,ma s0,4(res_ptr)
+ addib,<> -1,size,L$loop2
+ nop
+
+L$ret addc %r0,cylimb,cylimb
+ bv 0(%r2)
+ ldo -128(%r30),%r30
+
+ .exit
+ .procend
diff --git a/mpn/hppa/hppa1_1/submul_1.s b/mpn/hppa/hppa1_1/submul_1.s
new file mode 100644
index 000000000..a4a385467
--- /dev/null
+++ b/mpn/hppa/hppa1_1/submul_1.s
@@ -0,0 +1,111 @@
+; HP-PA-1.1 __mpn_submul_1 -- Multiply a limb vector with a limb and
+; subtract the result from a second limb vector.
+
+; Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
+
+; This file is part of the GNU MP Library.
+
+; The GNU MP Library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Library General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or (at your
+; option) any later version.
+
+; The GNU MP Library 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 Library General Public
+; License for more details.
+
+; You should have received a copy of the GNU Library General Public License
+; along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+; MA 02111-1307, USA.
+
+
+; INPUT PARAMETERS
+; res_ptr r26
+; s1_ptr r25
+; size r24
+; s2_limb r23
+
+; This runs at 12 cycles/limb on a PA7000. With the used instructions, it
+; can not become faster due to data cache contention after a store. On the
+; PA7100 it runs at 11 cycles/limb, and that can not be improved either,
+; since only the xmpyu does not need the integer pipeline, so the only
+; dual-issue we will get are addc+xmpyu. Unrolling could gain a cycle/limb
+; on the PA7100.
+
+; There are some ideas described in mul_1.s that applies to this code too.
+
+; It seems possible to make this run as fast as __mpn_addmul_1, if we use
+; sub,>>= %r29,%r19,%r22
+; addi 1,%r28,%r28
+; but that requires reworking the hairy software pipeline...
+
+ .code
+ .export __mpn_submul_1
+__mpn_submul_1
+ .proc
+ .callinfo frame=64,no_calls
+ .entry
+
+ ldo 64(%r30),%r30
+ fldws,ma 4(%r25),%fr5
+ stw %r23,-16(%r30) ; move s2_limb ...
+ addib,= -1,%r24,L$just_one_limb
+ fldws -16(%r30),%fr4 ; ... into fr4
+ add %r0,%r0,%r0 ; clear carry
+ xmpyu %fr4,%fr5,%fr6
+ fldws,ma 4(%r25),%fr7
+ fstds %fr6,-16(%r30)
+ xmpyu %fr4,%fr7,%fr8
+ ldw -12(%r30),%r19 ; least significant limb in product
+ ldw -16(%r30),%r28
+
+ fstds %fr8,-16(%r30)
+ addib,= -1,%r24,L$end
+ ldw -12(%r30),%r1
+
+; Main loop
+L$loop ldws 0(%r26),%r29
+ fldws,ma 4(%r25),%fr5
+ sub %r29,%r19,%r22
+ add %r22,%r19,%r0
+ stws,ma %r22,4(%r26)
+ addc %r28,%r1,%r19
+ xmpyu %fr4,%fr5,%fr6
+ ldw -16(%r30),%r28
+ fstds %fr6,-16(%r30)
+ addc %r0,%r28,%r28
+ addib,<> -1,%r24,L$loop
+ ldw -12(%r30),%r1
+
+L$end ldw 0(%r26),%r29
+ sub %r29,%r19,%r22
+ add %r22,%r19,%r0
+ stws,ma %r22,4(%r26)
+ addc %r28,%r1,%r19
+ ldw -16(%r30),%r28
+ ldws 0(%r26),%r29
+ addc %r0,%r28,%r28
+ sub %r29,%r19,%r22
+ add %r22,%r19,%r0
+ stws,ma %r22,4(%r26)
+ addc %r0,%r28,%r28
+ bv 0(%r2)
+ ldo -64(%r30),%r30
+
+L$just_one_limb
+ xmpyu %fr4,%fr5,%fr6
+ ldw 0(%r26),%r29
+ fstds %fr6,-16(%r30)
+ ldw -12(%r30),%r1
+ ldw -16(%r30),%r28
+ sub %r29,%r1,%r22
+ add %r22,%r1,%r0
+ stw %r22,0(%r26)
+ addc %r0,%r28,%r28
+ bv 0(%r2)
+ ldo -64(%r30),%r30
+
+ .exit
+ .procend
diff --git a/mpn/hppa/hppa1_1/udiv_qrnnd.s b/mpn/hppa/hppa1_1/udiv_qrnnd.s
new file mode 100644
index 000000000..bf7dc70cd
--- /dev/null
+++ b/mpn/hppa/hppa1_1/udiv_qrnnd.s
@@ -0,0 +1,75 @@
+; HP-PA __udiv_qrnnd division support, used from longlong.h.
+; This version runs fast on PA 7000 and later.
+
+; Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+
+; This file is part of the GNU MP Library.
+
+; The GNU MP Library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Library General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or (at your
+; option) any later version.
+
+; The GNU MP Library 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 Library General Public
+; License for more details.
+
+; You should have received a copy of the GNU Library General Public License
+; along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+; MA 02111-1307, USA.
+
+
+; INPUT PARAMETERS
+; rem_ptr gr26
+; n1 gr25
+; n0 gr24
+; d gr23
+
+ .code
+L$0000 .word 0x43f00000
+ .word 0x0
+ .export __udiv_qrnnd
+__udiv_qrnnd
+ .proc
+ .callinfo frame=64,no_calls
+ .entry
+ ldo 64(%r30),%r30
+
+ stws %r25,-16(0,%r30) ; n_hi
+ stws %r24,-12(0,%r30) ; n_lo
+ ldil L'L$0000,%r19
+ ldo R'L$0000(%r19),%r19
+ fldds -16(0,%r30),%fr5
+ stws %r23,-12(0,%r30)
+ comib,<= 0,%r25,L$1
+ fcnvxf,dbl,dbl %fr5,%fr5
+ fldds 0(0,%r19),%fr4
+ fadd,dbl %fr4,%fr5,%fr5
+L$1
+ fcpy,sgl %fr0,%fr6L
+ fldws -12(0,%r30),%fr6R
+ fcnvxf,dbl,dbl %fr6,%fr4
+
+ fdiv,dbl %fr5,%fr4,%fr5
+
+ fcnvfx,dbl,dbl %fr5,%fr4
+ fstws %fr4R,-16(%r30)
+ xmpyu %fr4R,%fr6R,%fr6
+ ldws -16(%r30),%r28
+ fstds %fr6,-16(0,%r30)
+ ldws -12(0,%r30),%r21
+ ldws -16(0,%r30),%r20
+ sub %r24,%r21,%r22
+ subb %r25,%r20,%r19
+ comib,= 0,%r19,L$2
+ ldo -64(%r30),%r30
+
+ add %r22,%r23,%r22
+ ldo -1(%r28),%r28
+L$2 bv 0(%r2)
+ stws %r22,0(0,%r26)
+
+ .exit
+ .procend
diff --git a/mpn/hppa/lshift.s b/mpn/hppa/lshift.s
new file mode 100644
index 000000000..abac6ec20
--- /dev/null
+++ b/mpn/hppa/lshift.s
@@ -0,0 +1,66 @@
+; HP-PA __mpn_lshift --
+
+; Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+; This file is part of the GNU MP Library.
+
+; The GNU MP Library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Library General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or (at your
+; option) any later version.
+
+; The GNU MP Library 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 Library General Public
+; License for more details.
+
+; You should have received a copy of the GNU Library General Public License
+; along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+; MA 02111-1307, USA.
+
+
+; INPUT PARAMETERS
+; res_ptr gr26
+; s_ptr gr25
+; size gr24
+; cnt gr23
+
+ .code
+ .export __mpn_lshift
+__mpn_lshift
+ .proc
+ .callinfo frame=64,no_calls
+ .entry
+
+ sh2add %r24,%r25,%r25
+ sh2add %r24,%r26,%r26
+ ldws,mb -4(0,%r25),%r22
+ subi 32,%r23,%r1
+ mtsar %r1
+ addib,= -1,%r24,L$0004
+ vshd %r0,%r22,%r28 ; compute carry out limb
+ ldws,mb -4(0,%r25),%r29
+ addib,= -1,%r24,L$0002
+ vshd %r22,%r29,%r20
+
+L$loop ldws,mb -4(0,%r25),%r22
+ stws,mb %r20,-4(0,%r26)
+ addib,= -1,%r24,L$0003
+ vshd %r29,%r22,%r20
+ ldws,mb -4(0,%r25),%r29
+ stws,mb %r20,-4(0,%r26)
+ addib,<> -1,%r24,L$loop
+ vshd %r22,%r29,%r20
+
+L$0002 stws,mb %r20,-4(0,%r26)
+ vshd %r29,%r0,%r20
+ bv 0(%r2)
+ stw %r20,-4(0,%r26)
+L$0003 stws,mb %r20,-4(0,%r26)
+L$0004 vshd %r22,%r0,%r20
+ bv 0(%r2)
+ stw %r20,-4(0,%r26)
+
+ .exit
+ .procend
diff --git a/mpn/hppa/rshift.s b/mpn/hppa/rshift.s
new file mode 100644
index 000000000..c1480e5ab
--- /dev/null
+++ b/mpn/hppa/rshift.s
@@ -0,0 +1,63 @@
+; HP-PA __mpn_rshift --
+
+; Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+; This file is part of the GNU MP Library.
+
+; The GNU MP Library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Library General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or (at your
+; option) any later version.
+
+; The GNU MP Library 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 Library General Public
+; License for more details.
+
+; You should have received a copy of the GNU Library General Public License
+; along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+; MA 02111-1307, USA.
+
+
+; INPUT PARAMETERS
+; res_ptr gr26
+; s_ptr gr25
+; size gr24
+; cnt gr23
+
+ .code
+ .export __mpn_rshift
+__mpn_rshift
+ .proc
+ .callinfo frame=64,no_calls
+ .entry
+
+ ldws,ma 4(0,%r25),%r22
+ mtsar %r23
+ addib,= -1,%r24,L$0004
+ vshd %r22,%r0,%r28 ; compute carry out limb
+ ldws,ma 4(0,%r25),%r29
+ addib,= -1,%r24,L$0002
+ vshd %r29,%r22,%r20
+
+L$loop ldws,ma 4(0,%r25),%r22
+ stws,ma %r20,4(0,%r26)
+ addib,= -1,%r24,L$0003
+ vshd %r22,%r29,%r20
+ ldws,ma 4(0,%r25),%r29
+ stws,ma %r20,4(0,%r26)
+ addib,<> -1,%r24,L$loop
+ vshd %r29,%r22,%r20
+
+L$0002 stws,ma %r20,4(0,%r26)
+ vshd %r0,%r29,%r20
+ bv 0(%r2)
+ stw %r20,0(0,%r26)
+L$0003 stws,ma %r20,4(0,%r26)
+L$0004 vshd %r0,%r22,%r20
+ bv 0(%r2)
+ stw %r20,0(0,%r26)
+
+ .exit
+ .procend
diff --git a/mpn/hppa/sub_n.s b/mpn/hppa/sub_n.s
new file mode 100644
index 000000000..04fa3e1e3
--- /dev/null
+++ b/mpn/hppa/sub_n.s
@@ -0,0 +1,59 @@
+; HP-PA __mpn_sub_n -- Subtract two limb vectors of the same length > 0 and
+; store difference in a third limb vector.
+
+; Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+; This file is part of the GNU MP Library.
+
+; The GNU MP Library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Library General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or (at your
+; option) any later version.
+
+; The GNU MP Library 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 Library General Public
+; License for more details.
+
+; You should have received a copy of the GNU Library General Public License
+; along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+; MA 02111-1307, USA.
+
+
+; INPUT PARAMETERS
+; res_ptr gr26
+; s1_ptr gr25
+; s2_ptr gr24
+; size gr23
+
+; One might want to unroll this as for other processors, but it turns
+; out that the data cache contention after a store makes such
+; unrolling useless. We can't come under 5 cycles/limb anyway.
+
+ .code
+ .export __mpn_sub_n
+__mpn_sub_n
+ .proc
+ .callinfo frame=0,no_calls
+ .entry
+
+ ldws,ma 4(0,%r25),%r20
+ ldws,ma 4(0,%r24),%r19
+
+ addib,= -1,%r23,L$end ; check for (SIZE == 1)
+ sub %r20,%r19,%r28 ; subtract first limbs ignoring cy
+
+L$loop ldws,ma 4(0,%r25),%r20
+ ldws,ma 4(0,%r24),%r19
+ stws,ma %r28,4(0,%r26)
+ addib,<> -1,%r23,L$loop
+ subb %r20,%r19,%r28
+
+L$end stws %r28,0(0,%r26)
+ addc %r0,%r0,%r28
+ bv 0(%r2)
+ subi 1,%r28,%r28
+
+ .exit
+ .procend
diff --git a/mpn/hppa/udiv_qrnnd.s b/mpn/hppa/udiv_qrnnd.s
new file mode 100644
index 000000000..9b45eb40d
--- /dev/null
+++ b/mpn/hppa/udiv_qrnnd.s
@@ -0,0 +1,286 @@
+; HP-PA __udiv_qrnnd division support, used from longlong.h.
+; This version runs fast on pre-PA7000 CPUs.
+
+; Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+
+; This file is part of the GNU MP Library.
+
+; The GNU MP Library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Library General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or (at your
+; option) any later version.
+
+; The GNU MP Library 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 Library General Public
+; License for more details.
+
+; You should have received a copy of the GNU Library General Public License
+; along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+; MA 02111-1307, USA.
+
+
+; INPUT PARAMETERS
+; rem_ptr gr26
+; n1 gr25
+; n0 gr24
+; d gr23
+
+; The code size is a bit excessive. We could merge the last two ds;addc
+; sequences by simply moving the "bb,< Odd" instruction down. The only
+; trouble is the FFFFFFFF code that would need some hacking.
+
+ .code
+ .export __udiv_qrnnd
+__udiv_qrnnd
+ .proc
+ .callinfo frame=0,no_calls
+ .entry
+
+ comb,< %r23,0,L$largedivisor
+ sub %r0,%r23,%r1 ; clear cy as side-effect
+ ds %r0,%r1,%r0
+ addc %r24,%r24,%r24
+ ds %r25,%r23,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r23,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r23,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r23,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r23,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r23,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r23,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r23,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r23,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r23,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r23,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r23,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r23,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r23,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r23,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r23,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r23,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r23,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r23,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r23,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r23,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r23,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r23,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r23,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r23,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r23,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r23,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r23,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r23,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r23,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r23,%r25
+ addc %r24,%r24,%r28
+ ds %r25,%r23,%r25
+ comclr,>= %r25,%r0,%r0
+ addl %r25,%r23,%r25
+ stws %r25,0(0,%r26)
+ bv 0(%r2)
+ addc %r28,%r28,%r28
+
+L$largedivisor
+ extru %r24,31,1,%r19 ; r19 = n0 & 1
+ bb,< %r23,31,L$odd
+ extru %r23,30,31,%r22 ; r22 = d >> 1
+ shd %r25,%r24,1,%r24 ; r24 = new n0
+ extru %r25,30,31,%r25 ; r25 = new n1
+ sub %r0,%r22,%r21
+ ds %r0,%r21,%r0
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ comclr,>= %r25,%r0,%r0
+ addl %r25,%r22,%r25
+ sh1addl %r25,%r19,%r25
+ stws %r25,0(0,%r26)
+ bv 0(%r2)
+ addc %r24,%r24,%r28
+
+L$odd addib,sv,n 1,%r22,L$FF.. ; r22 = (d / 2 + 1)
+ shd %r25,%r24,1,%r24 ; r24 = new n0
+ extru %r25,30,31,%r25 ; r25 = new n1
+ sub %r0,%r22,%r21
+ ds %r0,%r21,%r0
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r24
+ ds %r25,%r22,%r25
+ addc %r24,%r24,%r28
+ comclr,>= %r25,%r0,%r0
+ addl %r25,%r22,%r25
+ sh1addl %r25,%r19,%r25
+; We have computed (n1,,n0) / (d + 1), q' = r28, r' = r25
+ add,nuv %r28,%r25,%r25
+ addl %r25,%r1,%r25
+ addc %r0,%r28,%r28
+ sub,<< %r25,%r23,%r0
+ addl %r25,%r1,%r25
+ stws %r25,0(0,%r26)
+ bv 0(%r2)
+ addc %r0,%r28,%r28
+
+; This is just a special case of the code above.
+; We come here when d == 0xFFFFFFFF
+L$FF.. add,uv %r25,%r24,%r24
+ sub,<< %r24,%r23,%r0
+ ldo 1(%r24),%r24
+ stws %r24,0(0,%r26)
+ bv 0(%r2)
+ addc %r0,%r25,%r28
+
+ .exit
+ .procend
diff --git a/mpn/i960/README b/mpn/i960/README
new file mode 100644
index 000000000..d68a0a83e
--- /dev/null
+++ b/mpn/i960/README
@@ -0,0 +1,9 @@
+This directory contains mpn functions for Intel i960 processors.
+
+RELEVANT OPTIMIZATION ISSUES
+
+The code in this directory is not well optimized.
+
+STATUS
+
+The code in this directory has not been tested.
diff --git a/mpn/i960/add_n.s b/mpn/i960/add_n.s
new file mode 100644
index 000000000..6031f6d4c
--- /dev/null
+++ b/mpn/i960/add_n.s
@@ -0,0 +1,21 @@
+.text
+ .align 4
+ .globl ___mpn_add_n
+___mpn_add_n:
+ mov 0,g6 # clear carry-save register
+ cmpo 1,0 # clear cy
+
+Loop: subo 1,g3,g3 # update loop counter
+ ld (g1),g5 # load from s1_ptr
+ addo 4,g1,g1 # s1_ptr++
+ ld (g2),g4 # load from s2_ptr
+ addo 4,g2,g2 # s2_ptr++
+ cmpo g6,1 # restore cy from g6, relies on cy being 0
+ addc g4,g5,g4 # main add
+ subc 0,0,g6 # save cy in g6
+ st g4,(g0) # store result to res_ptr
+ addo 4,g0,g0 # res_ptr++
+ cmpobne 0,g3,Loop # when branch is taken, clears C bit
+
+ mov g6,g0
+ ret
diff --git a/mpn/i960/addmul_1.s b/mpn/i960/addmul_1.s
new file mode 100644
index 000000000..1a3de95e5
--- /dev/null
+++ b/mpn/i960/addmul_1.s
@@ -0,0 +1,26 @@
+.text
+ .align 4
+ .globl ___mpn_mul_1
+___mpn_mul_1:
+ subo g2,0,g2
+ shlo 2,g2,g4
+ subo g4,g1,g1
+ subo g4,g0,g13
+ mov 0,g0
+
+ cmpo 1,0 # clear C bit on AC.cc
+
+Loop: ld (g1)[g2*4],g5
+ emul g3,g5,g6
+ ld (g13)[g2*4],g5
+
+ addc g0,g6,g6 # relies on that C bit is clear
+ addc 0,g7,g7
+ addc g5,g6,g6 # relies on that C bit is clear
+ st g6,(g13)[g2*4]
+ addc 0,g7,g0
+
+ addo g2,1,g2
+ cmpobne 0,g2,Loop # when branch is taken, clears C bit
+
+ ret
diff --git a/mpn/i960/mul_1.s b/mpn/i960/mul_1.s
new file mode 100644
index 000000000..e75ea42d3
--- /dev/null
+++ b/mpn/i960/mul_1.s
@@ -0,0 +1,23 @@
+.text
+ .align 4
+ .globl ___mpn_mul_1
+___mpn_mul_1:
+ subo g2,0,g2
+ shlo 2,g2,g4
+ subo g4,g1,g1
+ subo g4,g0,g13
+ mov 0,g0
+
+ cmpo 1,0 # clear C bit on AC.cc
+
+Loop: ld (g1)[g2*4],g5
+ emul g3,g5,g6
+
+ addc g0,g6,g6 # relies on that C bit is clear
+ st g6,(g13)[g2*4]
+ addc 0,g7,g0
+
+ addo g2,1,g2
+ cmpobne 0,g2,Loop # when branch is taken, clears C bit
+
+ ret
diff --git a/mpn/i960/sub_n.s b/mpn/i960/sub_n.s
new file mode 100644
index 000000000..13ebbfa9f
--- /dev/null
+++ b/mpn/i960/sub_n.s
@@ -0,0 +1,21 @@
+.text
+ .align 4
+ .globl ___mpn_sub_n
+___mpn_sub_n:
+ mov 1,g6 # set carry-save register
+ cmpo 1,0 # clear cy
+
+Loop: subo 1,g3,g3 # update loop counter
+ ld (g1),g5 # load from s1_ptr
+ addo 4,g1,g1 # s1_ptr++
+ ld (g2),g4 # load from s2_ptr
+ addo 4,g2,g2 # s2_ptr++
+ cmpo g6,1 # restore cy from g6, relies on cy being 0
+ subc g4,g5,g4 # main subtract
+ subc 0,0,g6 # save cy in g6
+ st g4,(g0) # store result to res_ptr
+ addo 4,g0,g0 # res_ptr++
+ cmpobne 0,g3,Loop # when branch is taken, cy will be 0
+
+ mov g6,g0
+ ret
diff --git a/mpn/m68k/add_n.S b/mpn/m68k/add_n.S
new file mode 100644
index 000000000..7ca5b95bc
--- /dev/null
+++ b/mpn/m68k/add_n.S
@@ -0,0 +1,80 @@
+/* mc68020 __mpn_add_n -- Add two limb vectors of the same length > 0 and store
+ sum in a third limb vector.
+
+Copyright (C) 1992, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/*
+ INPUT PARAMETERS
+ res_ptr (sp + 4)
+ s1_ptr (sp + 8)
+ s2_ptr (sp + 16)
+ size (sp + 12)
+*/
+
+#include "sysdep.h"
+#include "asm-syntax.h"
+
+ TEXT
+ ALIGN
+ GLOBL C_SYMBOL_NAME(__mpn_add_n)
+
+C_SYMBOL_NAME(__mpn_add_n:)
+PROLOG(__mpn_add_n)
+/* Save used registers on the stack. */
+ movel R(d2),MEM_PREDEC(sp)
+ movel R(a2),MEM_PREDEC(sp)
+
+/* Copy the arguments to registers. Better use movem? */
+ movel MEM_DISP(sp,12),R(a2)
+ movel MEM_DISP(sp,16),R(a0)
+ movel MEM_DISP(sp,20),R(a1)
+ movel MEM_DISP(sp,24),R(d2)
+
+ eorw #1,R(d2)
+ lsrl #1,R(d2)
+ bcc L(L1)
+ subql #1,R(d2) /* clears cy as side effect */
+
+L(Loop:)
+ movel MEM_POSTINC(a0),R(d0)
+ movel MEM_POSTINC(a1),R(d1)
+ addxl R(d1),R(d0)
+ movel R(d0),MEM_POSTINC(a2)
+L(L1:) movel MEM_POSTINC(a0),R(d0)
+ movel MEM_POSTINC(a1),R(d1)
+ addxl R(d1),R(d0)
+ movel R(d0),MEM_POSTINC(a2)
+
+ dbf R(d2),L(Loop) /* loop until 16 lsb of %4 == -1 */
+ subxl R(d0),R(d0) /* d0 <= -cy; save cy as 0 or -1 in d0 */
+ subl #0x10000,R(d2)
+ bcs L(L2)
+ addl R(d0),R(d0) /* restore cy */
+ bra L(Loop)
+
+L(L2:)
+ negl R(d0)
+
+/* Restore used registers from stack frame. */
+ movel MEM_POSTINC(sp),R(a2)
+ movel MEM_POSTINC(sp),R(d2)
+
+ rts
+EPILOG(__mpn_add_n)
diff --git a/mpn/m68k/lshift.S b/mpn/m68k/lshift.S
new file mode 100644
index 000000000..77184d6ee
--- /dev/null
+++ b/mpn/m68k/lshift.S
@@ -0,0 +1,151 @@
+/* mc68020 __mpn_lshift -- Shift left a low-level natural-number integer.
+
+Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/*
+ INPUT PARAMETERS
+ res_ptr (sp + 4)
+ s_ptr (sp + 8)
+ s_size (sp + 16)
+ cnt (sp + 12)
+*/
+
+#include "sysdep.h"
+#include "asm-syntax.h"
+
+#define res_ptr a1
+#define s_ptr a0
+#define s_size d6
+#define cnt d4
+
+ TEXT
+ ALIGN
+ GLOBL C_SYMBOL_NAME(__mpn_lshift)
+
+C_SYMBOL_NAME(__mpn_lshift:)
+PROLOG(__mpn_lshift)
+
+/* Save used registers on the stack. */
+ moveml R(d2)-R(d6)/R(a2),MEM_PREDEC(sp)
+
+/* Copy the arguments to registers. */
+ movel MEM_DISP(sp,28),R(res_ptr)
+ movel MEM_DISP(sp,32),R(s_ptr)
+ movel MEM_DISP(sp,36),R(s_size)
+ movel MEM_DISP(sp,40),R(cnt)
+
+ moveql #1,R(d5)
+ cmpl R(d5),R(cnt)
+ bne L(Lnormal)
+ cmpl R(s_ptr),R(res_ptr)
+ bls L(Lspecial) /* jump if s_ptr >= res_ptr */
+#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020))
+ lea MEM_INDX1(s_ptr,s_size,l,4),R(a2)
+#else /* not mc68020 */
+ movel R(s_size),R(d0)
+ asll #2,R(d0)
+ lea MEM_INDX(s_ptr,d0,l),R(a2)
+#endif
+ cmpl R(res_ptr),R(a2)
+ bls L(Lspecial) /* jump if res_ptr >= s_ptr + s_size */
+
+L(Lnormal:)
+ moveql #32,R(d5)
+ subl R(cnt),R(d5)
+
+#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020))
+ lea MEM_INDX1(s_ptr,s_size,l,4),R(s_ptr)
+ lea MEM_INDX1(res_ptr,s_size,l,4),R(res_ptr)
+#else /* not mc68000 */
+ movel R(s_size),R(d0)
+ asll #2,R(d0)
+ addl R(s_size),R(s_ptr)
+ addl R(s_size),R(res_ptr)
+#endif
+ movel MEM_PREDEC(s_ptr),R(d2)
+ movel R(d2),R(d0)
+ lsrl R(d5),R(d0) /* compute carry limb */
+
+ lsll R(cnt),R(d2)
+ movel R(d2),R(d1)
+ subql #1,R(s_size)
+ beq L(Lend)
+ lsrl #1,R(s_size)
+ bcs L(L1)
+ subql #1,R(s_size)
+
+L(Loop:)
+ movel MEM_PREDEC(s_ptr),R(d2)
+ movel R(d2),R(d3)
+ lsrl R(d5),R(d3)
+ orl R(d3),R(d1)
+ movel R(d1),MEM_PREDEC(res_ptr)
+ lsll R(cnt),R(d2)
+L(L1:)
+ movel MEM_PREDEC(s_ptr),R(d1)
+ movel R(d1),R(d3)
+ lsrl R(d5),R(d3)
+ orl R(d3),R(d2)
+ movel R(d2),MEM_PREDEC(res_ptr)
+ lsll R(cnt),R(d1)
+
+ dbf R(s_size),L(Loop)
+ subl #0x10000,R(s_size)
+ bcc L(Loop)
+
+L(Lend:)
+ movel R(d1),MEM_PREDEC(res_ptr) /* store least significant limb */
+
+/* Restore used registers from stack frame. */
+ moveml MEM_POSTINC(sp),R(d2)-R(d6)/R(a2)
+ rts
+
+/* We loop from least significant end of the arrays, which is only
+ permissable if the source and destination don't overlap, since the
+ function is documented to work for overlapping source and destination. */
+
+L(Lspecial:)
+ clrl R(d0) /* initialize carry */
+ eorw #1,R(s_size)
+ lsrl #1,R(s_size)
+ bcc L(LL1)
+ subql #1,R(s_size)
+
+L(LLoop:)
+ movel MEM_POSTINC(s_ptr),R(d2)
+ addxl R(d2),R(d2)
+ movel R(d2),MEM_POSTINC(res_ptr)
+L(LL1:)
+ movel MEM_POSTINC(s_ptr),R(d2)
+ addxl R(d2),R(d2)
+ movel R(d2),MEM_POSTINC(res_ptr)
+
+ dbf R(s_size),L(LLoop)
+ addxl R(d0),R(d0) /* save cy in lsb */
+ subl #0x10000,R(s_size)
+ bcs L(LLend)
+ lsrl #1,R(d0) /* restore cy */
+ bra L(LLoop)
+
+L(LLend:)
+/* Restore used registers from stack frame. */
+ moveml MEM_POSTINC(sp),R(d2)-R(d6)/R(a2)
+ rts
+EPILOG(__mpn_lshift)
diff --git a/mpn/m68k/mc68020/addmul_1.S b/mpn/m68k/mc68020/addmul_1.S
new file mode 100644
index 000000000..4b99c21f8
--- /dev/null
+++ b/mpn/m68k/mc68020/addmul_1.S
@@ -0,0 +1,84 @@
+/* mc68020 __mpn_addmul_1 -- Multiply a limb vector with a limb and add
+ the result to a second limb vector.
+
+Copyright (C) 1992, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/*
+ INPUT PARAMETERS
+ res_ptr (sp + 4)
+ s1_ptr (sp + 8)
+ s1_size (sp + 12)
+ s2_limb (sp + 16)
+*/
+
+#include "sysdep.h"
+#include "asm-syntax.h"
+
+ TEXT
+ ALIGN
+ GLOBL C_SYMBOL_NAME(__mpn_addmul_1)
+
+C_SYMBOL_NAME(__mpn_addmul_1:)
+PROLOG(__mpn_addmul_1)
+
+#define res_ptr a0
+#define s1_ptr a1
+#define s1_size d2
+#define s2_limb d4
+
+/* Save used registers on the stack. */
+ moveml R(d2)-R(d5),MEM_PREDEC(sp)
+
+/* Copy the arguments to registers. Better use movem? */
+ movel MEM_DISP(sp,20),R(res_ptr)
+ movel MEM_DISP(sp,24),R(s1_ptr)
+ movel MEM_DISP(sp,28),R(s1_size)
+ movel MEM_DISP(sp,32),R(s2_limb)
+
+ eorw #1,R(s1_size)
+ clrl R(d1)
+ clrl R(d5)
+ lsrl #1,R(s1_size)
+ bcc L(L1)
+ subql #1,R(s1_size)
+ subl R(d0),R(d0) /* (d0,cy) <= (0,0) */
+
+L(Loop:)
+ movel MEM_POSTINC(s1_ptr),R(d3)
+ mulul R(s2_limb),R(d1):R(d3)
+ addxl R(d0),R(d3)
+ addxl R(d5),R(d1)
+ addl R(d3),MEM_POSTINC(res_ptr)
+L(L1:) movel MEM_POSTINC(s1_ptr),R(d3)
+ mulul R(s2_limb),R(d0):R(d3)
+ addxl R(d1),R(d3)
+ addxl R(d5),R(d0)
+ addl R(d3),MEM_POSTINC(res_ptr)
+
+ dbf R(s1_size),L(Loop)
+ addxl R(d5),R(d0)
+ subl #0x10000,R(s1_size)
+ bcc L(Loop)
+
+/* Restore used registers from stack frame. */
+ moveml MEM_POSTINC(sp),R(d2)-R(d5)
+
+ rts
+EPILOG(__mpn_addmul_1)
diff --git a/mpn/m68k/mc68020/mul_1.S b/mpn/m68k/mc68020/mul_1.S
new file mode 100644
index 000000000..ef7d93721
--- /dev/null
+++ b/mpn/m68k/mc68020/mul_1.S
@@ -0,0 +1,91 @@
+/* mc68020 __mpn_mul_1 -- Multiply a limb vector with a limb and store
+ the result in a second limb vector.
+
+Copyright (C) 1992, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/*
+ INPUT PARAMETERS
+ res_ptr (sp + 4)
+ s1_ptr (sp + 8)
+ s1_size (sp + 12)
+ s2_limb (sp + 16)
+*/
+
+#include "sysdep.h"
+#include "asm-syntax.h"
+
+ TEXT
+ ALIGN
+ GLOBL C_SYMBOL_NAME(__mpn_mul_1)
+
+C_SYMBOL_NAME(__mpn_mul_1:)
+PROLOG(__mpn_mul_1)
+
+#define res_ptr a0
+#define s1_ptr a1
+#define s1_size d2
+#define s2_limb d4
+
+/* Save used registers on the stack. */
+ moveml R(d2)-R(d4),MEM_PREDEC(sp)
+#if 0
+ movel R(d2),MEM_PREDEC(sp)
+ movel R(d3),MEM_PREDEC(sp)
+ movel R(d4),MEM_PREDEC(sp)
+#endif
+
+/* Copy the arguments to registers. Better use movem? */
+ movel MEM_DISP(sp,16),R(res_ptr)
+ movel MEM_DISP(sp,20),R(s1_ptr)
+ movel MEM_DISP(sp,24),R(s1_size)
+ movel MEM_DISP(sp,28),R(s2_limb)
+
+ eorw #1,R(s1_size)
+ clrl R(d1)
+ lsrl #1,R(s1_size)
+ bcc L(L1)
+ subql #1,R(s1_size)
+ subl R(d0),R(d0) /* (d0,cy) <= (0,0) */
+
+L(Loop:)
+ movel MEM_POSTINC(s1_ptr),R(d3)
+ mulul R(s2_limb),R(d1):R(d3)
+ addxl R(d0),R(d3)
+ movel R(d3),MEM_POSTINC(res_ptr)
+L(L1:) movel MEM_POSTINC(s1_ptr),R(d3)
+ mulul R(s2_limb),R(d0):R(d3)
+ addxl R(d1),R(d3)
+ movel R(d3),MEM_POSTINC(res_ptr)
+
+ dbf R(s1_size),L(Loop)
+ clrl R(d3)
+ addxl R(d3),R(d0)
+ subl #0x10000,R(s1_size)
+ bcc L(Loop)
+
+/* Restore used registers from stack frame. */
+ moveml MEM_POSTINC(sp),R(d2)-R(d4)
+#if 0
+ movel MEM_POSTINC(sp),R(d4)
+ movel MEM_POSTINC(sp),R(d3)
+ movel MEM_POSTINC(sp),R(d2)
+#endif
+ rts
+EPILOG(__mpn_mul_1)
diff --git a/mpn/m68k/mc68020/submul_1.S b/mpn/m68k/mc68020/submul_1.S
new file mode 100644
index 000000000..9770c6cd6
--- /dev/null
+++ b/mpn/m68k/mc68020/submul_1.S
@@ -0,0 +1,84 @@
+/* mc68020 __mpn_submul_1 -- Multiply a limb vector with a limb and subtract
+ the result from a second limb vector.
+
+Copyright (C) 1992, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/*
+ INPUT PARAMETERS
+ res_ptr (sp + 4)
+ s1_ptr (sp + 8)
+ s1_size (sp + 12)
+ s2_limb (sp + 16)
+*/
+
+#include "sysdep.h"
+#include "asm-syntax.h"
+
+ TEXT
+ ALIGN
+ GLOBL C_SYMBOL_NAME(__mpn_submul_1)
+
+C_SYMBOL_NAME(__mpn_submul_1:)
+PROLOG(__mpn_submul_1)
+
+#define res_ptr a0
+#define s1_ptr a1
+#define s1_size d2
+#define s2_limb d4
+
+/* Save used registers on the stack. */
+ moveml R(d2)-R(d5),MEM_PREDEC(sp)
+
+/* Copy the arguments to registers. Better use movem? */
+ movel MEM_DISP(sp,20),R(res_ptr)
+ movel MEM_DISP(sp,24),R(s1_ptr)
+ movel MEM_DISP(sp,28),R(s1_size)
+ movel MEM_DISP(sp,32),R(s2_limb)
+
+ eorw #1,R(s1_size)
+ clrl R(d1)
+ clrl R(d5)
+ lsrl #1,R(s1_size)
+ bcc L(L1)
+ subql #1,R(s1_size)
+ subl R(d0),R(d0) /* (d0,cy) <= (0,0) */
+
+L(Loop:)
+ movel MEM_POSTINC(s1_ptr),R(d3)
+ mulul R(s2_limb),R(d1):R(d3)
+ addxl R(d0),R(d3)
+ addxl R(d5),R(d1)
+ subl R(d3),MEM_POSTINC(res_ptr)
+L(L1:) movel MEM_POSTINC(s1_ptr),R(d3)
+ mulul R(s2_limb),R(d0):R(d3)
+ addxl R(d1),R(d3)
+ addxl R(d5),R(d0)
+ subl R(d3),MEM_POSTINC(res_ptr)
+
+ dbf R(s1_size),L(Loop)
+ addxl R(d5),R(d0)
+ subl #0x10000,R(s1_size)
+ bcc L(Loop)
+
+/* Restore used registers from stack frame. */
+ moveml MEM_POSTINC(sp),R(d2)-R(d5)
+
+ rts
+EPILOG(__mpn_submul_1)
diff --git a/mpn/m68k/rshift.S b/mpn/m68k/rshift.S
new file mode 100644
index 000000000..01dde0ab5
--- /dev/null
+++ b/mpn/m68k/rshift.S
@@ -0,0 +1,150 @@
+/* mc68020 __mpn_rshift -- Shift right a low-level natural-number integer.
+
+Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/*
+ INPUT PARAMETERS
+ res_ptr (sp + 4)
+ s_ptr (sp + 8)
+ s_size (sp + 16)
+ cnt (sp + 12)
+*/
+
+#include "sysdep.h"
+#include "asm-syntax.h"
+
+#define res_ptr a1
+#define s_ptr a0
+#define s_size d6
+#define cnt d4
+
+ TEXT
+ ALIGN
+ GLOBL C_SYMBOL_NAME(__mpn_rshift)
+
+C_SYMBOL_NAME(__mpn_rshift:)
+PROLOG(__mpn_rshift)
+/* Save used registers on the stack. */
+ moveml R(d2)-R(d6)/R(a2),MEM_PREDEC(sp)
+
+/* Copy the arguments to registers. */
+ movel MEM_DISP(sp,28),R(res_ptr)
+ movel MEM_DISP(sp,32),R(s_ptr)
+ movel MEM_DISP(sp,36),R(s_size)
+ movel MEM_DISP(sp,40),R(cnt)
+
+ moveql #1,R(d5)
+ cmpl R(d5),R(cnt)
+ bne L(Lnormal)
+ cmpl R(res_ptr),R(s_ptr)
+ bls L(Lspecial) /* jump if res_ptr >= s_ptr */
+#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020))
+ lea MEM_INDX1(res_ptr,s_size,l,4),R(a2)
+#else /* not mc68020 */
+ movel R(s_size),R(d0)
+ asll #2,R(d0)
+ lea MEM_INDX(res_ptr,d0,l),R(a2)
+#endif
+ cmpl R(s_ptr),R(a2)
+ bls L(Lspecial) /* jump if s_ptr >= res_ptr + s_size */
+
+L(Lnormal:)
+ moveql #32,R(d5)
+ subl R(cnt),R(d5)
+ movel MEM_POSTINC(s_ptr),R(d2)
+ movel R(d2),R(d0)
+ lsll R(d5),R(d0) /* compute carry limb */
+
+ lsrl R(cnt),R(d2)
+ movel R(d2),R(d1)
+ subql #1,R(s_size)
+ beq L(Lend)
+ lsrl #1,R(s_size)
+ bcs L(L1)
+ subql #1,R(s_size)
+
+L(Loop:)
+ movel MEM_POSTINC(s_ptr),R(d2)
+ movel R(d2),R(d3)
+ lsll R(d5),R(d3)
+ orl R(d3),R(d1)
+ movel R(d1),MEM_POSTINC(res_ptr)
+ lsrl R(cnt),R(d2)
+L(L1:)
+ movel MEM_POSTINC(s_ptr),R(d1)
+ movel R(d1),R(d3)
+ lsll R(d5),R(d3)
+ orl R(d3),R(d2)
+ movel R(d2),MEM_POSTINC(res_ptr)
+ lsrl R(cnt),R(d1)
+
+ dbf R(s_size),L(Loop)
+ subl #0x10000,R(s_size)
+ bcc L(Loop)
+
+L(Lend:)
+ movel R(d1),MEM(res_ptr) /* store most significant limb */
+
+/* Restore used registers from stack frame. */
+ moveml MEM_POSTINC(sp),R(d2)-R(d6)/R(a2)
+ rts
+
+/* We loop from most significant end of the arrays, which is only
+ permissable if the source and destination don't overlap, since the
+ function is documented to work for overlapping source and destination. */
+
+L(Lspecial:)
+#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020))
+ lea MEM_INDX1(s_ptr,s_size,l,4),R(s_ptr)
+ lea MEM_INDX1(res_ptr,s_size,l,4),R(res_ptr)
+#else /* not mc68000 */
+ movel R(s_size),R(d0)
+ asll #2,R(d0)
+ addl R(s_size),R(s_ptr)
+ addl R(s_size),R(res_ptr)
+#endif
+
+ clrl R(d0) /* initialize carry */
+ eorw #1,R(s_size)
+ lsrl #1,R(s_size)
+ bcc L(LL1)
+ subql #1,R(s_size)
+
+L(LLoop:)
+ movel MEM_PREDEC(s_ptr),R(d2)
+ roxrl #1,R(d2)
+ movel R(d2),MEM_PREDEC(res_ptr)
+L(LL1:)
+ movel MEM_PREDEC(s_ptr),R(d2)
+ roxrl #1,R(d2)
+ movel R(d2),MEM_PREDEC(res_ptr)
+
+ dbf R(s_size),L(LLoop)
+ roxrl #1,R(d0) /* save cy in msb */
+ subl #0x10000,R(s_size)
+ bcs L(LLend)
+ addl R(d0),R(d0) /* restore cy */
+ bra L(LLoop)
+
+L(LLend:)
+/* Restore used registers from stack frame. */
+ moveml MEM_POSTINC(sp),R(d2)-R(d6)/R(a2)
+ rts
+EPILOG(__mpn_rshift)
diff --git a/mpn/m68k/sub_n.S b/mpn/m68k/sub_n.S
new file mode 100644
index 000000000..f94b0c728
--- /dev/null
+++ b/mpn/m68k/sub_n.S
@@ -0,0 +1,80 @@
+/* mc68020 __mpn_sub_n -- Subtract two limb vectors of the same length > 0 and
+ store difference in a third limb vector.
+
+Copyright (C) 1992, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/*
+ INPUT PARAMETERS
+ res_ptr (sp + 4)
+ s1_ptr (sp + 8)
+ s2_ptr (sp + 16)
+ size (sp + 12)
+*/
+
+#include "sysdep.h"
+#include "asm-syntax.h"
+
+ TEXT
+ ALIGN
+ GLOBL C_SYMBOL_NAME(__mpn_sub_n)
+
+C_SYMBOL_NAME(__mpn_sub_n:)
+PROLOG(__mpn_sub_n)
+/* Save used registers on the stack. */
+ movel R(d2),MEM_PREDEC(sp)
+ movel R(a2),MEM_PREDEC(sp)
+
+/* Copy the arguments to registers. Better use movem? */
+ movel MEM_DISP(sp,12),R(a2)
+ movel MEM_DISP(sp,16),R(a0)
+ movel MEM_DISP(sp,20),R(a1)
+ movel MEM_DISP(sp,24),R(d2)
+
+ eorw #1,R(d2)
+ lsrl #1,R(d2)
+ bcc L(L1)
+ subql #1,R(d2) /* clears cy as side effect */
+
+L(Loop:)
+ movel MEM_POSTINC(a0),R(d0)
+ movel MEM_POSTINC(a1),R(d1)
+ subxl R(d1),R(d0)
+ movel R(d0),MEM_POSTINC(a2)
+L(L1:) movel MEM_POSTINC(a0),R(d0)
+ movel MEM_POSTINC(a1),R(d1)
+ subxl R(d1),R(d0)
+ movel R(d0),MEM_POSTINC(a2)
+
+ dbf R(d2),L(Loop) /* loop until 16 lsb of %4 == -1 */
+ subxl R(d0),R(d0) /* d0 <= -cy; save cy as 0 or -1 in d0 */
+ subl #0x10000,R(d2)
+ bcs L(L2)
+ addl R(d0),R(d0) /* restore cy */
+ bra L(Loop)
+
+L(L2:)
+ negl R(d0)
+
+/* Restore used registers from stack frame. */
+ movel MEM_POSTINC(sp),R(a2)
+ movel MEM_POSTINC(sp),R(d2)
+
+ rts
+EPILOG(__mpn_sub_n)
diff --git a/mpn/m68k/syntax.h b/mpn/m68k/syntax.h
new file mode 100644
index 000000000..9d6f3522b
--- /dev/null
+++ b/mpn/m68k/syntax.h
@@ -0,0 +1,177 @@
+/* asm.h -- Definitions for 68k syntax variations.
+
+Copyright (C) 1992, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#undef ALIGN
+
+#ifdef MIT_SYNTAX
+#define PROLOG(name)
+#define EPILOG(name)
+#define R(r)r
+#define MEM(base)base@
+#define MEM_DISP(base,displacement)base@(displacement)
+#define MEM_INDX(base,idx,size_suffix)base@(idx:size_suffix)
+#define MEM_INDX1(base,idx,size_suffix,scale)base@(idx:size_suffix:scale)
+#define MEM_PREDEC(memory_base)memory_base@-
+#define MEM_POSTINC(memory_base)memory_base@+
+#define L(label) label
+#define TEXT .text
+#define ALIGN .even
+#define GLOBL .globl
+#define moveql moveq
+/* Use variable sized opcodes. */
+#define bcc jcc
+#define bcs jcs
+#define bls jls
+#define beq jeq
+#define bne jne
+#define bra jra
+#endif
+
+#ifdef SONY_SYNTAX
+#define PROLOG(name)
+#define EPILOG(name)
+#define R(r)r
+#define MEM(base)(base)
+#define MEM_DISP(base,displacement)(displacement,base)
+#define MEM_INDX(base,idx,size_suffix)(base,idx.size_suffix)
+#define MEM_INDX1(base,idx,size_suffix,scale)(base,idx.size_suffix*scale)
+#define MEM_PREDEC(memory_base)-(memory_base)
+#define MEM_POSTINC(memory_base)(memory_base)+
+#define L(label) label
+#define TEXT .text
+#define ALIGN .even
+#define GLOBL .globl
+#endif
+
+#ifdef MOTOROLA_SYNTAX
+#define PROLOG(name)
+#define EPILOG(name)
+#define R(r)r
+#define MEM(base)(base)
+#define MEM_DISP(base,displacement)(displacement,base)
+#define MEM_INDX(base,idx,size_suffix)(base,idx.size_suffix)
+#define MEM_INDX1(base,idx,size_suffix,scale)(base,idx.size_suffix*scale)
+#define MEM_PREDEC(memory_base)-(memory_base)
+#define MEM_POSTINC(memory_base)(memory_base)+
+#define L(label) label
+#define TEXT
+#define ALIGN
+#define GLOBL XDEF
+#define lea LEA
+#define movel MOVE.L
+#define moveml MOVEM.L
+#define moveql MOVEQ.L
+#define cmpl CMP.L
+#define orl OR.L
+#define clrl CLR.L
+#define eorw EOR.W
+#define lsrl LSR.L
+#define lsll LSL.L
+#define roxrl ROXR.L
+#define roxll ROXL.L
+#define addl ADD.L
+#define addxl ADDX.L
+#define addql ADDQ.L
+#define subl SUB.L
+#define subxl SUBX.L
+#define subql SUBQ.L
+#define negl NEG.L
+#define mulul MULU.L
+#define bcc BCC
+#define bcs BCS
+#define bls BLS
+#define beq BEQ
+#define bne BNE
+#define bra BRA
+#define dbf DBF
+#define rts RTS
+#define d0 D0
+#define d1 D1
+#define d2 D2
+#define d3 D3
+#define d4 D4
+#define d5 D5
+#define d6 D6
+#define d7 D7
+#define a0 A0
+#define a1 A1
+#define a2 A2
+#define a3 A3
+#define a4 A4
+#define a5 A5
+#define a6 A6
+#define a7 A7
+#define sp SP
+#endif
+
+#ifdef ELF_SYNTAX
+#define PROLOG(name) .type name,@function
+#define EPILOG(name) .size name,.-name
+#define MEM(base)(R(base))
+#define MEM_DISP(base,displacement)(displacement,R(base))
+#define MEM_PREDEC(memory_base)-(R(memory_base))
+#define MEM_POSTINC(memory_base)(R(memory_base))+
+#ifdef __STDC__
+#define R_(r)%##r
+#define R(r)R_(r)
+#define MEM_INDX_(base,idx,size_suffix)(R(base),R(idx##.##size_suffix))
+#define MEM_INDX(base,idx,size_suffix)MEM_INDX_(base,idx,size_suffix)
+#define MEM_INDX1_(base,idx,size_suffix,scale)(R(base),R(idx##.##size_suffix*scale))
+#define MEM_INDX1(base,idx,size_suffix,scale)MEM_INDX1_(base,idx,size_suffix,scale)
+#define L(label) .##label
+#else
+#define R(r)%/**/r
+#define MEM_INDX(base,idx,size_suffix)(R(base),R(idx).size_suffix)
+#define MEM_INDX1(base,idx,size_suffix,scale)(R(base),R(idx).size_suffix*scale)
+#define L(label) ./**/label
+#endif
+#define TEXT .text
+#define ALIGN .align 2
+#define GLOBL .globl
+#define bcc jbcc
+#define bcs jbcs
+#define bls jbls
+#define beq jbeq
+#define bne jbne
+#define bra jbra
+#endif
+
+#if defined (SONY_SYNTAX) || defined (ELF_SYNTAX)
+#define movel move.l
+#define moveml movem.l
+#define moveql moveq.l
+#define cmpl cmp.l
+#define orl or.l
+#define clrl clr.l
+#define eorw eor.w
+#define lsrl lsr.l
+#define lsll lsl.l
+#define roxrl roxr.l
+#define roxll roxl.l
+#define addl add.l
+#define addxl addx.l
+#define addql addq.l
+#define subl sub.l
+#define subxl subx.l
+#define subql subq.l
+#define negl neg.l
+#define mulul mulu.l
+#endif
diff --git a/mpn/m88k/add_n.s b/mpn/m88k/add_n.s
new file mode 100644
index 000000000..1b09ccef8
--- /dev/null
+++ b/mpn/m88k/add_n.s
@@ -0,0 +1,104 @@
+; mc88100 __mpn_add -- Add two limb vectors of the same length > 0 and store
+; sum in a third limb vector.
+
+; Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
+
+; This file is part of the GNU MP Library.
+
+; The GNU MP Library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Library General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or (at your
+; option) any later version.
+
+; The GNU MP Library 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 Library General Public
+; License for more details.
+
+; You should have received a copy of the GNU Library General Public License
+; along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+; MA 02111-1307, USA.
+
+
+; INPUT PARAMETERS
+; res_ptr r2
+; s1_ptr r3
+; s2_ptr r4
+; size r5
+
+; This code has been optimized to run one instruction per clock, avoiding
+; load stalls and writeback contention. As a result, the instruction
+; order is not always natural.
+
+; The speed is about 4.6 clocks/limb + 18 clocks/limb-vector on an 88100,
+; but on the 88110, it seems to run much slower, 6.6 clocks/limb.
+
+ text
+ align 16
+ global ___mpn_add_n
+___mpn_add_n:
+ ld r6,r3,0 ; read first limb from s1_ptr
+ extu r10,r5,3
+ ld r7,r4,0 ; read first limb from s2_ptr
+
+ subu.co r5,r0,r5 ; (clear carry as side effect)
+ mak r5,r5,3<4>
+ bcnd eq0,r5,Lzero
+
+ or r12,r0,lo16(Lbase)
+ or.u r12,r12,hi16(Lbase)
+ addu r12,r12,r5 ; r12 is address for entering in loop
+
+ extu r5,r5,2 ; divide by 4
+ subu r2,r2,r5 ; adjust res_ptr
+ subu r3,r3,r5 ; adjust s1_ptr
+ subu r4,r4,r5 ; adjust s2_ptr
+
+ or r8,r6,r0
+
+ jmp.n r12
+ or r9,r7,r0
+
+Loop: addu r3,r3,32
+ st r8,r2,28
+ addu r4,r4,32
+ ld r6,r3,0
+ addu r2,r2,32
+ ld r7,r4,0
+Lzero: subu r10,r10,1 ; add 0 + 8r limbs (adj loop cnt)
+Lbase: ld r8,r3,4
+ addu.cio r6,r6,r7
+ ld r9,r4,4
+ st r6,r2,0
+ ld r6,r3,8 ; add 7 + 8r limbs
+ addu.cio r8,r8,r9
+ ld r7,r4,8
+ st r8,r2,4
+ ld r8,r3,12 ; add 6 + 8r limbs
+ addu.cio r6,r6,r7
+ ld r9,r4,12
+ st r6,r2,8
+ ld r6,r3,16 ; add 5 + 8r limbs
+ addu.cio r8,r8,r9
+ ld r7,r4,16
+ st r8,r2,12
+ ld r8,r3,20 ; add 4 + 8r limbs
+ addu.cio r6,r6,r7
+ ld r9,r4,20
+ st r6,r2,16
+ ld r6,r3,24 ; add 3 + 8r limbs
+ addu.cio r8,r8,r9
+ ld r7,r4,24
+ st r8,r2,20
+ ld r8,r3,28 ; add 2 + 8r limbs
+ addu.cio r6,r6,r7
+ ld r9,r4,28
+ st r6,r2,24
+ bcnd.n ne0,r10,Loop ; add 1 + 8r limbs
+ addu.cio r8,r8,r9
+
+ st r8,r2,28 ; store most significant limb
+
+ jmp.n r1
+ addu.ci r2,r0,r0 ; return carry-out from most sign. limb
diff --git a/mpn/m88k/mc88110/add_n.S b/mpn/m88k/mc88110/add_n.S
new file mode 100644
index 000000000..39a44e557
--- /dev/null
+++ b/mpn/m88k/mc88110/add_n.S
@@ -0,0 +1,200 @@
+; mc88110 __mpn_add_n -- Add two limb vectors of the same length > 0 and store
+; sum in a third limb vector.
+
+; Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+
+; This file is part of the GNU MP Library.
+
+; The GNU MP Library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Library General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or (at your
+; option) any later version.
+
+; The GNU MP Library 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 Library General Public
+; License for more details.
+
+; You should have received a copy of the GNU Library General Public License
+; along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+; MA 02111-1307, USA.
+
+
+; INPUT PARAMETERS
+#define res_ptr r2
+#define s1_ptr r3
+#define s2_ptr r4
+#define size r5
+
+#include "sysdep.h"
+
+ text
+ align 16
+ global C_SYMBOL_NAME(__mpn_add_n)
+C_SYMBOL_NAME(__mpn_add_n):
+ addu.co r0,r0,r0 ; clear cy flag
+ xor r12,s2_ptr,res_ptr
+ bb1 2,r12,L1
+; ** V1a **
+L0: bb0 2,res_ptr,L_v1 ; branch if res_ptr is aligned?
+/* Add least significant limb separately to align res_ptr and s2_ptr */
+ ld r10,s1_ptr,0
+ addu s1_ptr,s1_ptr,4
+ ld r8,s2_ptr,0
+ addu s2_ptr,s2_ptr,4
+ subu size,size,1
+ addu.co r6,r10,r8
+ st r6,res_ptr,0
+ addu res_ptr,res_ptr,4
+L_v1: cmp r12,size,2
+ bb1 lt,r12,Lend2
+
+ ld r10,s1_ptr,0
+ ld r12,s1_ptr,4
+ ld.d r8,s2_ptr,0
+ subu size,size,10
+ bcnd lt0,size,Lfin1
+/* Add blocks of 8 limbs until less than 8 limbs remain */
+ align 8
+Loop1: subu size,size,8
+ addu.cio r6,r10,r8
+ ld r10,s1_ptr,8
+ addu.cio r7,r12,r9
+ ld r12,s1_ptr,12
+ ld.d r8,s2_ptr,8
+ st.d r6,res_ptr,0
+ addu.cio r6,r10,r8
+ ld r10,s1_ptr,16
+ addu.cio r7,r12,r9
+ ld r12,s1_ptr,20
+ ld.d r8,s2_ptr,16
+ st.d r6,res_ptr,8
+ addu.cio r6,r10,r8
+ ld r10,s1_ptr,24
+ addu.cio r7,r12,r9
+ ld r12,s1_ptr,28
+ ld.d r8,s2_ptr,24
+ st.d r6,res_ptr,16
+ addu.cio r6,r10,r8
+ ld r10,s1_ptr,32
+ addu.cio r7,r12,r9
+ ld r12,s1_ptr,36
+ addu s1_ptr,s1_ptr,32
+ ld.d r8,s2_ptr,32
+ addu s2_ptr,s2_ptr,32
+ st.d r6,res_ptr,24
+ addu res_ptr,res_ptr,32
+ bcnd ge0,size,Loop1
+
+Lfin1: addu size,size,8-2
+ bcnd lt0,size,Lend1
+/* Add blocks of 2 limbs until less than 2 limbs remain */
+Loope1: addu.cio r6,r10,r8
+ ld r10,s1_ptr,8
+ addu.cio r7,r12,r9
+ ld r12,s1_ptr,12
+ ld.d r8,s2_ptr,8
+ st.d r6,res_ptr,0
+ subu size,size,2
+ addu s1_ptr,s1_ptr,8
+ addu s2_ptr,s2_ptr,8
+ addu res_ptr,res_ptr,8
+ bcnd ge0,size,Loope1
+Lend1: addu.cio r6,r10,r8
+ addu.cio r7,r12,r9
+ st.d r6,res_ptr,0
+
+ bb0 0,size,Lret1
+/* Add last limb */
+ ld r10,s1_ptr,8
+ ld r8,s2_ptr,8
+ addu.cio r6,r10,r8
+ st r6,res_ptr,8
+
+Lret1: jmp.n r1
+ addu.ci r2,r0,r0 ; return carry-out from most sign. limb
+
+L1: xor r12,s1_ptr,res_ptr
+ bb1 2,r12,L2
+; ** V1b **
+ or r12,r0,s2_ptr
+ or s2_ptr,r0,s1_ptr
+ or s1_ptr,r0,r12
+ br L0
+
+; ** V2 **
+/* If we come here, the alignment of s1_ptr and res_ptr as well as the
+ alignment of s2_ptr and res_ptr differ. Since there are only two ways
+ things can be aligned (that we care about) we now know that the alignment
+ of s1_ptr and s2_ptr are the same. */
+
+L2: cmp r12,size,1
+ bb1 eq,r12,Ljone
+ bb0 2,s1_ptr,L_v2 ; branch if s1_ptr is aligned
+/* Add least significant limb separately to align res_ptr and s2_ptr */
+ ld r10,s1_ptr,0
+ addu s1_ptr,s1_ptr,4
+ ld r8,s2_ptr,0
+ addu s2_ptr,s2_ptr,4
+ subu size,size,1
+ addu.co r6,r10,r8
+ st r6,res_ptr,0
+ addu res_ptr,res_ptr,4
+
+L_v2: subu size,size,8
+ bcnd lt0,size,Lfin2
+/* Add blocks of 8 limbs until less than 8 limbs remain */
+ align 8
+Loop2: subu size,size,8
+ ld.d r8,s1_ptr,0
+ ld.d r6,s2_ptr,0
+ addu.cio r8,r8,r6
+ st r8,res_ptr,0
+ addu.cio r9,r9,r7
+ st r9,res_ptr,4
+ ld.d r8,s1_ptr,8
+ ld.d r6,s2_ptr,8
+ addu.cio r8,r8,r6
+ st r8,res_ptr,8
+ addu.cio r9,r9,r7
+ st r9,res_ptr,12
+ ld.d r8,s1_ptr,16
+ ld.d r6,s2_ptr,16
+ addu.cio r8,r8,r6
+ st r8,res_ptr,16
+ addu.cio r9,r9,r7
+ st r9,res_ptr,20
+ ld.d r8,s1_ptr,24
+ ld.d r6,s2_ptr,24
+ addu.cio r8,r8,r6
+ st r8,res_ptr,24
+ addu.cio r9,r9,r7
+ st r9,res_ptr,28
+ addu s1_ptr,s1_ptr,32
+ addu s2_ptr,s2_ptr,32
+ addu res_ptr,res_ptr,32
+ bcnd ge0,size,Loop2
+
+Lfin2: addu size,size,8-2
+ bcnd lt0,size,Lend2
+Loope2: ld.d r8,s1_ptr,0
+ ld.d r6,s2_ptr,0
+ addu.cio r8,r8,r6
+ st r8,res_ptr,0
+ addu.cio r9,r9,r7
+ st r9,res_ptr,4
+ subu size,size,2
+ addu s1_ptr,s1_ptr,8
+ addu s2_ptr,s2_ptr,8
+ addu res_ptr,res_ptr,8
+ bcnd ge0,size,Loope2
+Lend2: bb0 0,size,Lret2
+/* Add last limb */
+Ljone: ld r10,s1_ptr,0
+ ld r8,s2_ptr,0
+ addu.cio r6,r10,r8
+ st r6,res_ptr,0
+
+Lret2: jmp.n r1
+ addu.ci r2,r0,r0 ; return carry-out from most sign. limb
diff --git a/mpn/m88k/mc88110/addmul_1.s b/mpn/m88k/mc88110/addmul_1.s
new file mode 100644
index 000000000..2bd6f21af
--- /dev/null
+++ b/mpn/m88k/mc88110/addmul_1.s
@@ -0,0 +1,61 @@
+; mc88110 __mpn_addmul_1 -- Multiply a limb vector with a single limb and
+; store the product in a second limb vector.
+
+; Copyright (C) 1996 Free Software Foundation, Inc.
+
+; This file is part of the GNU MP Library.
+
+; The GNU MP Library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Library General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or (at your
+; option) any later version.
+
+; The GNU MP Library 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 Library General Public
+; License for more details.
+
+; You should have received a copy of the GNU Library General Public License
+; along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+; MA 02111-1307, USA.
+
+
+; INPUT PARAMETERS
+; res_ptr r2
+; s1_ptr r3
+; size r4
+; s2_limb r5
+
+ text
+ align 16
+ global ___mpn_addmul_1
+___mpn_addmul_1:
+ lda r3,r3[r4]
+ lda r8,r2[r4] ; RES_PTR in r8 since r2 is retval
+ subu r4,r0,r4
+ addu.co r2,r0,r0 ; r2 = cy = 0
+
+ ld r6,r3[r4]
+ addu r4,r4,1
+ subu r8,r8,4
+ bcnd.n eq0,r4,Lend
+ mulu.d r10,r6,r5
+
+Loop: ld r7,r8[r4]
+ ld r6,r3[r4]
+ addu.cio r9,r11,r2
+ addu.ci r2,r10,r0
+ addu.co r9,r9,r7
+ st r9,r8[r4]
+ addu r4,r4,1
+ mulu.d r10,r6,r5
+ bcnd ne0,r4,Loop
+
+Lend: ld r7,r8,0
+ addu.cio r9,r11,r2
+ addu.ci r2,r10,r0
+ addu.co r9,r9,r7
+ st r9,r8,0
+ jmp.n r1
+ addu.ci r2,r2,r0
diff --git a/mpn/m88k/mc88110/mul_1.s b/mpn/m88k/mc88110/mul_1.s
new file mode 100644
index 000000000..151890060
--- /dev/null
+++ b/mpn/m88k/mc88110/mul_1.s
@@ -0,0 +1,59 @@
+; mc88110 __mpn_mul_1 -- Multiply a limb vector with a single limb and
+; store the product in a second limb vector.
+
+; Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
+
+; This file is part of the GNU MP Library.
+
+; The GNU MP Library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Library General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or (at your
+; option) any later version.
+
+; The GNU MP Library 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 Library General Public
+; License for more details.
+
+; You should have received a copy of the GNU Library General Public License
+; along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+; MA 02111-1307, USA.
+
+
+; INPUT PARAMETERS
+; res_ptr r2
+; s1_ptr r3
+; size r4
+; s2_limb r5
+
+ text
+ align 16
+ global ___mpn_mul_1
+___mpn_mul_1:
+ ; Make S1_PTR and RES_PTR point at the end of their blocks
+ ; and negate SIZE.
+ lda r3,r3[r4]
+ lda r8,r2[r4] ; RES_PTR in r8 since r2 is retval
+ subu r4,r0,r4
+
+ addu.co r2,r0,r0 ; r2 = cy = 0
+
+ ld r6,r3[r4]
+ addu r4,r4,1
+ mulu.d r10,r6,r5
+ bcnd.n eq0,r4,Lend
+ subu r8,r8,8
+
+Loop: ld r6,r3[r4]
+ addu.cio r9,r11,r2
+ or r2,r10,r0 ; could be avoided if unrolled
+ addu r4,r4,1
+ mulu.d r10,r6,r5
+ bcnd.n ne0,r4,Loop
+ st r9,r8[r4]
+
+Lend: addu.cio r9,r11,r2
+ st r9,r8,4
+ jmp.n r1
+ addu.ci r2,r10,r0
diff --git a/mpn/m88k/mc88110/sub_n.S b/mpn/m88k/mc88110/sub_n.S
new file mode 100644
index 000000000..685f024fd
--- /dev/null
+++ b/mpn/m88k/mc88110/sub_n.S
@@ -0,0 +1,276 @@
+; mc88110 __mpn_sub_n -- Subtract two limb vectors of the same length > 0 and
+; store difference in a third limb vector.
+
+; Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+
+; This file is part of the GNU MP Library.
+
+; The GNU MP Library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Library General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or (at your
+; option) any later version.
+
+; The GNU MP Library 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 Library General Public
+; License for more details.
+
+; You should have received a copy of the GNU Library General Public License
+; along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+; MA 02111-1307, USA.
+
+
+; INPUT PARAMETERS
+#define res_ptr r2
+#define s1_ptr r3
+#define s2_ptr r4
+#define size r5
+
+#include "sysdep.h"
+
+ text
+ align 16
+ global C_SYMBOL_NAME(__mpn_sub_n)
+C_SYMBOL_NAME(__mpn_sub_n):
+ subu.co r0,r0,r0 ; set cy flag
+ xor r12,s2_ptr,res_ptr
+ bb1 2,r12,L1
+; ** V1a **
+L0: bb0 2,res_ptr,L_v1 ; branch if res_ptr is aligned
+/* Add least significant limb separately to align res_ptr and s2_ptr */
+ ld r10,s1_ptr,0
+ addu s1_ptr,s1_ptr,4
+ ld r8,s2_ptr,0
+ addu s2_ptr,s2_ptr,4
+ subu size,size,1
+ subu.co r6,r10,r8
+ st r6,res_ptr,0
+ addu res_ptr,res_ptr,4
+L_v1: cmp r12,size,2
+ bb1 lt,r12,Lend2
+
+ ld r10,s1_ptr,0
+ ld r12,s1_ptr,4
+ ld.d r8,s2_ptr,0
+ subu size,size,10
+ bcnd lt0,size,Lfin1
+/* Add blocks of 8 limbs until less than 8 limbs remain */
+ align 8
+Loop1: subu size,size,8
+ subu.cio r6,r10,r8
+ ld r10,s1_ptr,8
+ subu.cio r7,r12,r9
+ ld r12,s1_ptr,12
+ ld.d r8,s2_ptr,8
+ st.d r6,res_ptr,0
+ subu.cio r6,r10,r8
+ ld r10,s1_ptr,16
+ subu.cio r7,r12,r9
+ ld r12,s1_ptr,20
+ ld.d r8,s2_ptr,16
+ st.d r6,res_ptr,8
+ subu.cio r6,r10,r8
+ ld r10,s1_ptr,24
+ subu.cio r7,r12,r9
+ ld r12,s1_ptr,28
+ ld.d r8,s2_ptr,24
+ st.d r6,res_ptr,16
+ subu.cio r6,r10,r8
+ ld r10,s1_ptr,32
+ subu.cio r7,r12,r9
+ ld r12,s1_ptr,36
+ addu s1_ptr,s1_ptr,32
+ ld.d r8,s2_ptr,32
+ addu s2_ptr,s2_ptr,32
+ st.d r6,res_ptr,24
+ addu res_ptr,res_ptr,32
+ bcnd ge0,size,Loop1
+
+Lfin1: addu size,size,8-2
+ bcnd lt0,size,Lend1
+/* Add blocks of 2 limbs until less than 2 limbs remain */
+Loope1: subu.cio r6,r10,r8
+ ld r10,s1_ptr,8
+ subu.cio r7,r12,r9
+ ld r12,s1_ptr,12
+ ld.d r8,s2_ptr,8
+ st.d r6,res_ptr,0
+ subu size,size,2
+ addu s1_ptr,s1_ptr,8
+ addu s2_ptr,s2_ptr,8
+ addu res_ptr,res_ptr,8
+ bcnd ge0,size,Loope1
+Lend1: subu.cio r6,r10,r8
+ subu.cio r7,r12,r9
+ st.d r6,res_ptr,0
+
+ bb0 0,size,Lret1
+/* Add last limb */
+ ld r10,s1_ptr,8
+ ld r8,s2_ptr,8
+ subu.cio r6,r10,r8
+ st r6,res_ptr,8
+
+Lret1: addu.ci r2,r0,r0 ; return carry-out from most sign. limb
+ jmp.n r1
+ xor r2,r2,1
+
+L1: xor r12,s1_ptr,res_ptr
+ bb1 2,r12,L2
+; ** V1b **
+ bb0 2,res_ptr,L_v1b ; branch if res_ptr is aligned
+/* Add least significant limb separately to align res_ptr and s1_ptr */
+ ld r10,s2_ptr,0
+ addu s2_ptr,s2_ptr,4
+ ld r8,s1_ptr,0
+ addu s1_ptr,s1_ptr,4
+ subu size,size,1
+ subu.co r6,r8,r10
+ st r6,res_ptr,0
+ addu res_ptr,res_ptr,4
+L_v1b: cmp r12,size,2
+ bb1 lt,r12,Lend2
+
+ ld r10,s2_ptr,0
+ ld r12,s2_ptr,4
+ ld.d r8,s1_ptr,0
+ subu size,size,10
+ bcnd lt0,size,Lfin1b
+/* Add blocks of 8 limbs until less than 8 limbs remain */
+ align 8
+Loop1b: subu size,size,8
+ subu.cio r6,r8,r10
+ ld r10,s2_ptr,8
+ subu.cio r7,r9,r12
+ ld r12,s2_ptr,12
+ ld.d r8,s1_ptr,8
+ st.d r6,res_ptr,0
+ subu.cio r6,r8,r10
+ ld r10,s2_ptr,16
+ subu.cio r7,r9,r12
+ ld r12,s2_ptr,20
+ ld.d r8,s1_ptr,16
+ st.d r6,res_ptr,8
+ subu.cio r6,r8,r10
+ ld r10,s2_ptr,24
+ subu.cio r7,r9,r12
+ ld r12,s2_ptr,28
+ ld.d r8,s1_ptr,24
+ st.d r6,res_ptr,16
+ subu.cio r6,r8,r10
+ ld r10,s2_ptr,32
+ subu.cio r7,r9,r12
+ ld r12,s2_ptr,36
+ addu s2_ptr,s2_ptr,32
+ ld.d r8,s1_ptr,32
+ addu s1_ptr,s1_ptr,32
+ st.d r6,res_ptr,24
+ addu res_ptr,res_ptr,32
+ bcnd ge0,size,Loop1b
+
+Lfin1b: addu size,size,8-2
+ bcnd lt0,size,Lend1b
+/* Add blocks of 2 limbs until less than 2 limbs remain */
+Loope1b:subu.cio r6,r8,r10
+ ld r10,s2_ptr,8
+ subu.cio r7,r9,r12
+ ld r12,s2_ptr,12
+ ld.d r8,s1_ptr,8
+ st.d r6,res_ptr,0
+ subu size,size,2
+ addu s1_ptr,s1_ptr,8
+ addu s2_ptr,s2_ptr,8
+ addu res_ptr,res_ptr,8
+ bcnd ge0,size,Loope1b
+Lend1b: subu.cio r6,r8,r10
+ subu.cio r7,r9,r12
+ st.d r6,res_ptr,0
+
+ bb0 0,size,Lret1b
+/* Add last limb */
+ ld r10,s2_ptr,8
+ ld r8,s1_ptr,8
+ subu.cio r6,r8,r10
+ st r6,res_ptr,8
+
+Lret1b: addu.ci r2,r0,r0 ; return carry-out from most sign. limb
+ jmp.n r1
+ xor r2,r2,1
+
+; ** V2 **
+/* If we come here, the alignment of s1_ptr and res_ptr as well as the
+ alignment of s2_ptr and res_ptr differ. Since there are only two ways
+ things can be aligned (that we care about) we now know that the alignment
+ of s1_ptr and s2_ptr are the same. */
+
+L2: cmp r12,size,1
+ bb1 eq,r12,Ljone
+ bb0 2,s1_ptr,L_v2 ; branch if s1_ptr is aligned
+/* Add least significant limb separately to align res_ptr and s2_ptr */
+ ld r10,s1_ptr,0
+ addu s1_ptr,s1_ptr,4
+ ld r8,s2_ptr,0
+ addu s2_ptr,s2_ptr,4
+ subu size,size,1
+ subu.co r6,r10,r8
+ st r6,res_ptr,0
+ addu res_ptr,res_ptr,4
+
+L_v2: subu size,size,8
+ bcnd lt0,size,Lfin2
+/* Add blocks of 8 limbs until less than 8 limbs remain */
+ align 8
+Loop2: subu size,size,8
+ ld.d r8,s1_ptr,0
+ ld.d r6,s2_ptr,0
+ subu.cio r8,r8,r6
+ st r8,res_ptr,0
+ subu.cio r9,r9,r7
+ st r9,res_ptr,4
+ ld.d r8,s1_ptr,8
+ ld.d r6,s2_ptr,8
+ subu.cio r8,r8,r6
+ st r8,res_ptr,8
+ subu.cio r9,r9,r7
+ st r9,res_ptr,12
+ ld.d r8,s1_ptr,16
+ ld.d r6,s2_ptr,16
+ subu.cio r8,r8,r6
+ st r8,res_ptr,16
+ subu.cio r9,r9,r7
+ st r9,res_ptr,20
+ ld.d r8,s1_ptr,24
+ ld.d r6,s2_ptr,24
+ subu.cio r8,r8,r6
+ st r8,res_ptr,24
+ subu.cio r9,r9,r7
+ st r9,res_ptr,28
+ addu s1_ptr,s1_ptr,32
+ addu s2_ptr,s2_ptr,32
+ addu res_ptr,res_ptr,32
+ bcnd ge0,size,Loop2
+
+Lfin2: addu size,size,8-2
+ bcnd lt0,size,Lend2
+Loope2: ld.d r8,s1_ptr,0
+ ld.d r6,s2_ptr,0
+ subu.cio r8,r8,r6
+ st r8,res_ptr,0
+ subu.cio r9,r9,r7
+ st r9,res_ptr,4
+ subu size,size,2
+ addu s1_ptr,s1_ptr,8
+ addu s2_ptr,s2_ptr,8
+ addu res_ptr,res_ptr,8
+ bcnd ge0,size,Loope2
+Lend2: bb0 0,size,Lret2
+/* Add last limb */
+Ljone: ld r10,s1_ptr,0
+ ld r8,s2_ptr,0
+ subu.cio r6,r10,r8
+ st r6,res_ptr,0
+
+Lret2: addu.ci r2,r0,r0 ; return carry-out from most sign. limb
+ jmp.n r1
+ xor r2,r2,1
diff --git a/mpn/m88k/mul_1.s b/mpn/m88k/mul_1.s
new file mode 100644
index 000000000..26626bf95
--- /dev/null
+++ b/mpn/m88k/mul_1.s
@@ -0,0 +1,127 @@
+; mc88100 __mpn_mul_1 -- Multiply a limb vector with a single limb and
+; store the product in a second limb vector.
+
+; Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
+
+; This file is part of the GNU MP Library.
+
+; The GNU MP Library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Library General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or (at your
+; option) any later version.
+
+; The GNU MP Library 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 Library General Public
+; License for more details.
+
+; You should have received a copy of the GNU Library General Public License
+; along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+; MA 02111-1307, USA.
+
+
+; INPUT PARAMETERS
+; res_ptr r2
+; s1_ptr r3
+; size r4
+; s2_limb r5
+
+; Common overhead is about 11 cycles/invocation.
+
+; The speed for S2_LIMB >= 0x10000 is approximately 21 cycles/limb. (The
+; pipeline stalls 2 cycles due to WB contention.)
+
+; The speed for S2_LIMB < 0x10000 is approximately 16 cycles/limb. (The
+; pipeline stalls 2 cycles due to WB contention and 1 cycle due to latency.)
+
+; To enhance speed:
+; 1. Unroll main loop 4-8 times.
+; 2. Schedule code to avoid WB contention. It might be tempting to move the
+; ld instruction in the loops down to save 2 cycles (less WB contention),
+; but that looses because the ultimate value will be read from outside
+; the allocated space. But if we handle the ultimate multiplication in
+; the tail, we can do this.
+; 3. Make the multiplication with less instructions. I think the code for
+; (S2_LIMB >= 0x10000) is not minimal.
+; With these techniques the (S2_LIMB >= 0x10000) case would run in 17 or
+; less cycles/limb; the (S2_LIMB < 0x10000) case would run in 11
+; cycles/limb. (Assuming infinite unrolling.)
+
+ text
+ align 16
+ global ___mpn_mul_1
+___mpn_mul_1:
+
+ ; Make S1_PTR and RES_PTR point at the end of their blocks
+ ; and negate SIZE.
+ lda r3,r3[r4]
+ lda r6,r2[r4] ; RES_PTR in r6 since r2 is retval
+ subu r4,r0,r4
+
+ addu.co r2,r0,r0 ; r2 = cy = 0
+ ld r9,r3[r4]
+ mask r7,r5,0xffff ; r7 = lo(S2_LIMB)
+ extu r8,r5,16 ; r8 = hi(S2_LIMB)
+ bcnd.n eq0,r8,Lsmall ; jump if (hi(S2_LIMB) == 0)
+ subu r6,r6,4
+
+; General code for any value of S2_LIMB.
+
+ ; Make a stack frame and save r25 and r26
+ subu r31,r31,16
+ st.d r25,r31,8
+
+ ; Enter the loop in the middle
+ br.n L1
+ addu r4,r4,1
+
+Loop: ld r9,r3[r4]
+ st r26,r6[r4]
+; bcnd ne0,r0,0 ; bubble
+ addu r4,r4,1
+L1: mul r26,r9,r5 ; low word of product mul_1 WB ld
+ mask r12,r9,0xffff ; r12 = lo(s1_limb) mask_1
+ mul r11,r12,r7 ; r11 = prod_0 mul_2 WB mask_1
+ mul r10,r12,r8 ; r10 = prod_1a mul_3
+ extu r13,r9,16 ; r13 = hi(s1_limb) extu_1 WB mul_1
+ mul r12,r13,r7 ; r12 = prod_1b mul_4 WB extu_1
+ mul r25,r13,r8 ; r25 = prod_2 mul_5 WB mul_2
+ extu r11,r11,16 ; r11 = hi(prod_0) extu_2 WB mul_3
+ addu r10,r10,r11 ; addu_1 WB extu_2
+; bcnd ne0,r0,0 ; bubble WB addu_1
+ addu.co r10,r10,r12 ; WB mul_4
+ mask.u r10,r10,0xffff ; move the 16 most significant bits...
+ addu.ci r10,r10,r0 ; ...to the low half of the word...
+ rot r10,r10,16 ; ...and put carry in pos 16.
+ addu.co r26,r26,r2 ; add old carry limb
+ bcnd.n ne0,r4,Loop
+ addu.ci r2,r25,r10 ; compute new carry limb
+
+ st r26,r6[r4]
+ ld.d r25,r31,8
+ jmp.n r1
+ addu r31,r31,16
+
+; Fast code for S2_LIMB < 0x10000
+Lsmall:
+ ; Enter the loop in the middle
+ br.n SL1
+ addu r4,r4,1
+
+SLoop: ld r9,r3[r4] ;
+ st r8,r6[r4] ;
+ addu r4,r4,1 ;
+SL1: mul r8,r9,r5 ; low word of product
+ mask r12,r9,0xffff ; r12 = lo(s1_limb)
+ extu r13,r9,16 ; r13 = hi(s1_limb)
+ mul r11,r12,r7 ; r11 = prod_0
+ mul r12,r13,r7 ; r12 = prod_1b
+ addu.cio r8,r8,r2 ; add old carry limb
+ extu r10,r11,16 ; r11 = hi(prod_0)
+ addu r10,r10,r12 ;
+ bcnd.n ne0,r4,SLoop
+ extu r2,r10,16 ; r2 = new carry limb
+
+ jmp.n r1
+ st r8,r6[r4]
diff --git a/mpn/m88k/sub_n.s b/mpn/m88k/sub_n.s
new file mode 100644
index 000000000..7dfffc980
--- /dev/null
+++ b/mpn/m88k/sub_n.s
@@ -0,0 +1,106 @@
+; mc88100 __mpn_sub -- Subtract two limb vectors of the same length > 0 and
+; store difference in a third limb vector.
+
+; Copyright (C) 1992, 1994, 1996 Free Software Foundation, Inc.
+
+; This file is part of the GNU MP Library.
+
+; The GNU MP Library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Library General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or (at your
+; option) any later version.
+
+; The GNU MP Library 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 Library General Public
+; License for more details.
+
+; You should have received a copy of the GNU Library General Public License
+; along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+; MA 02111-1307, USA.
+
+
+; INPUT PARAMETERS
+; res_ptr r2
+; s1_ptr r3
+; s2_ptr r4
+; size r5
+
+; This code has been optimized to run one instruction per clock, avoiding
+; load stalls and writeback contention. As a result, the instruction
+; order is not always natural.
+
+; The speed is about 4.6 clocks/limb + 18 clocks/limb-vector on an 88100,
+; but on the 88110, it seems to run much slower, 6.6 clocks/limb.
+
+ text
+ align 16
+ global ___mpn_sub_n
+___mpn_sub_n:
+ ld r6,r3,0 ; read first limb from s1_ptr
+ extu r10,r5,3
+ ld r7,r4,0 ; read first limb from s2_ptr
+
+ subu r5,r0,r5
+ mak r5,r5,3<4>
+ bcnd.n eq0,r5,Lzero
+ subu.co r0,r0,r0 ; initialize carry
+
+ or r12,r0,lo16(Lbase)
+ or.u r12,r12,hi16(Lbase)
+ addu r12,r12,r5 ; r12 is address for entering in loop
+
+ extu r5,r5,2 ; divide by 4
+ subu r2,r2,r5 ; adjust res_ptr
+ subu r3,r3,r5 ; adjust s1_ptr
+ subu r4,r4,r5 ; adjust s2_ptr
+
+ or r8,r6,r0
+
+ jmp.n r12
+ or r9,r7,r0
+
+Loop: addu r3,r3,32
+ st r8,r2,28
+ addu r4,r4,32
+ ld r6,r3,0
+ addu r2,r2,32
+ ld r7,r4,0
+Lzero: subu r10,r10,1 ; subtract 0 + 8r limbs (adj loop cnt)
+Lbase: ld r8,r3,4
+ subu.cio r6,r6,r7
+ ld r9,r4,4
+ st r6,r2,0
+ ld r6,r3,8 ; subtract 7 + 8r limbs
+ subu.cio r8,r8,r9
+ ld r7,r4,8
+ st r8,r2,4
+ ld r8,r3,12 ; subtract 6 + 8r limbs
+ subu.cio r6,r6,r7
+ ld r9,r4,12
+ st r6,r2,8
+ ld r6,r3,16 ; subtract 5 + 8r limbs
+ subu.cio r8,r8,r9
+ ld r7,r4,16
+ st r8,r2,12
+ ld r8,r3,20 ; subtract 4 + 8r limbs
+ subu.cio r6,r6,r7
+ ld r9,r4,20
+ st r6,r2,16
+ ld r6,r3,24 ; subtract 3 + 8r limbs
+ subu.cio r8,r8,r9
+ ld r7,r4,24
+ st r8,r2,20
+ ld r8,r3,28 ; subtract 2 + 8r limbs
+ subu.cio r6,r6,r7
+ ld r9,r4,28
+ st r6,r2,24
+ bcnd.n ne0,r10,Loop ; subtract 1 + 8r limbs
+ subu.cio r8,r8,r9
+
+ st r8,r2,28 ; store most significant limb
+
+ addu.ci r2,r0,r0 ; return carry-out from most sign. limb
+ jmp.n r1
+ xor r2,r2,1
diff --git a/mpn/mips2/add_n.s b/mpn/mips2/add_n.s
new file mode 100644
index 000000000..f5525cec4
--- /dev/null
+++ b/mpn/mips2/add_n.s
@@ -0,0 +1,120 @@
+ # MIPS2 __mpn_add_n -- Add two limb vectors of the same length > 0 and
+ # store sum in a third limb vector.
+
+ # Copyright (C) 1995 Free Software Foundation, Inc.
+
+ # This file is part of the GNU MP Library.
+
+ # The GNU MP Library is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU Library General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or (at your
+ # option) any later version.
+
+ # The GNU MP Library 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 Library General Public
+ # License for more details.
+
+ # You should have received a copy of the GNU Library General Public License
+ # along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+ # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ # MA 02111-1307, USA.
+
+
+ # INPUT PARAMETERS
+ # res_ptr $4
+ # s1_ptr $5
+ # s2_ptr $6
+ # size $7
+
+ .text
+ .align 2
+ .globl __mpn_add_n
+ .ent __mpn_add_n
+__mpn_add_n:
+ .set noreorder
+ .set nomacro
+
+ lw $10,0($5)
+ lw $11,0($6)
+
+ addiu $7,$7,-1
+ and $9,$7,4-1 # number of limbs in first loop
+ beq $9,$0,.L0 # if multiple of 4 limbs, skip first loop
+ move $2,$0
+
+ subu $7,$7,$9
+
+.Loop0: addiu $9,$9,-1
+ lw $12,4($5)
+ addu $11,$11,$2
+ lw $13,4($6)
+ sltu $8,$11,$2
+ addu $11,$10,$11
+ sltu $2,$11,$10
+ sw $11,0($4)
+ or $2,$2,$8
+
+ addiu $5,$5,4
+ addiu $6,$6,4
+ move $10,$12
+ move $11,$13
+ bne $9,$0,.Loop0
+ addiu $4,$4,4
+
+.L0: beq $7,$0,.Lend
+ nop
+
+.Loop: addiu $7,$7,-4
+
+ lw $12,4($5)
+ addu $11,$11,$2
+ lw $13,4($6)
+ sltu $8,$11,$2
+ addu $11,$10,$11
+ sltu $2,$11,$10
+ sw $11,0($4)
+ or $2,$2,$8
+
+ lw $10,8($5)
+ addu $13,$13,$2
+ lw $11,8($6)
+ sltu $8,$13,$2
+ addu $13,$12,$13
+ sltu $2,$13,$12
+ sw $13,4($4)
+ or $2,$2,$8
+
+ lw $12,12($5)
+ addu $11,$11,$2
+ lw $13,12($6)
+ sltu $8,$11,$2
+ addu $11,$10,$11
+ sltu $2,$11,$10
+ sw $11,8($4)
+ or $2,$2,$8
+
+ lw $10,16($5)
+ addu $13,$13,$2
+ lw $11,16($6)
+ sltu $8,$13,$2
+ addu $13,$12,$13
+ sltu $2,$13,$12
+ sw $13,12($4)
+ or $2,$2,$8
+
+ addiu $5,$5,16
+ addiu $6,$6,16
+
+ bne $7,$0,.Loop
+ addiu $4,$4,16
+
+.Lend: addu $11,$11,$2
+ sltu $8,$11,$2
+ addu $11,$10,$11
+ sltu $2,$11,$10
+ sw $11,0($4)
+ j $31
+ or $2,$2,$8
+
+ .end __mpn_add_n
diff --git a/mpn/mips2/addmul_1.s b/mpn/mips2/addmul_1.s
new file mode 100644
index 000000000..6145771e3
--- /dev/null
+++ b/mpn/mips2/addmul_1.s
@@ -0,0 +1,97 @@
+ # MIPS __mpn_addmul_1 -- Multiply a limb vector with a single limb and
+ # add the product to a second limb vector.
+
+ # Copyright (C) 1992, 1994, 1996 Free Software Foundation, Inc.
+
+ # This file is part of the GNU MP Library.
+
+ # The GNU MP Library is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU Library General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or (at your
+ # option) any later version.
+
+ # The GNU MP Library 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 Library General Public
+ # License for more details.
+
+ # You should have received a copy of the GNU Library General Public License
+ # along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+ # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ # MA 02111-1307, USA.
+
+
+ # INPUT PARAMETERS
+ # res_ptr $4
+ # s1_ptr $5
+ # size $6
+ # s2_limb $7
+
+ .text
+ .align 4
+ .globl __mpn_addmul_1
+ .ent __mpn_addmul_1
+__mpn_addmul_1:
+ .set noreorder
+ .set nomacro
+
+ # warm up phase 0
+ lw $8,0($5)
+
+ # warm up phase 1
+ addiu $5,$5,4
+ multu $8,$7
+
+ addiu $6,$6,-1
+ beq $6,$0,$LC0
+ move $2,$0 # zero cy2
+
+ addiu $6,$6,-1
+ beq $6,$0,$LC1
+ lw $8,0($5) # load new s1 limb as early as possible
+
+Loop: lw $10,0($4)
+ mflo $3
+ mfhi $9
+ addiu $5,$5,4
+ addu $3,$3,$2 # add old carry limb to low product limb
+ multu $8,$7
+ lw $8,0($5) # load new s1 limb as early as possible
+ addiu $6,$6,-1 # decrement loop counter
+ sltu $2,$3,$2 # carry from previous addition -> $2
+ addu $3,$10,$3
+ sltu $10,$3,$10
+ addu $2,$2,$10
+ sw $3,0($4)
+ addiu $4,$4,4
+ bne $6,$0,Loop
+ addu $2,$9,$2 # add high product limb and carry from addition
+
+ # cool down phase 1
+$LC1: lw $10,0($4)
+ mflo $3
+ mfhi $9
+ addu $3,$3,$2
+ sltu $2,$3,$2
+ multu $8,$7
+ addu $3,$10,$3
+ sltu $10,$3,$10
+ addu $2,$2,$10
+ sw $3,0($4)
+ addiu $4,$4,4
+ addu $2,$9,$2 # add high product limb and carry from addition
+
+ # cool down phase 0
+$LC0: lw $10,0($4)
+ mflo $3
+ mfhi $9
+ addu $3,$3,$2
+ sltu $2,$3,$2
+ addu $3,$10,$3
+ sltu $10,$3,$10
+ addu $2,$2,$10
+ sw $3,0($4)
+ j $31
+ addu $2,$9,$2 # add high product limb and carry from addition
+
+ .end __mpn_addmul_1
diff --git a/mpn/mips2/lshift.s b/mpn/mips2/lshift.s
new file mode 100644
index 000000000..ee92d7916
--- /dev/null
+++ b/mpn/mips2/lshift.s
@@ -0,0 +1,95 @@
+ # MIPS2 __mpn_lshift --
+
+ # Copyright (C) 1995 Free Software Foundation, Inc.
+
+ # This file is part of the GNU MP Library.
+
+ # The GNU MP Library is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU Library General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or (at your
+ # option) any later version.
+
+ # The GNU MP Library 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 Library General Public
+ # License for more details.
+
+ # You should have received a copy of the GNU Library General Public License
+ # along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+ # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ # MA 02111-1307, USA.
+
+
+ # INPUT PARAMETERS
+ # res_ptr $4
+ # src_ptr $5
+ # size $6
+ # cnt $7
+
+ .text
+ .align 2
+ .globl __mpn_lshift
+ .ent __mpn_lshift
+__mpn_lshift:
+ .set noreorder
+ .set nomacro
+
+ sll $2,$6,2
+ addu $5,$5,$2 # make r5 point at end of src
+ lw $10,-4($5) # load first limb
+ subu $13,$0,$7
+ addu $4,$4,$2 # make r4 point at end of res
+ addiu $6,$6,-1
+ and $9,$6,4-1 # number of limbs in first loop
+ beq $9,$0,.L0 # if multiple of 4 limbs, skip first loop
+ srl $2,$10,$13 # compute function result
+
+ subu $6,$6,$9
+
+.Loop0: lw $3,-8($5)
+ addiu $4,$4,-4
+ addiu $5,$5,-4
+ addiu $9,$9,-1
+ sll $11,$10,$7
+ srl $12,$3,$13
+ move $10,$3
+ or $8,$11,$12
+ bne $9,$0,.Loop0
+ sw $8,0($4)
+
+.L0: beq $6,$0,.Lend
+ nop
+
+.Loop: lw $3,-8($5)
+ addiu $4,$4,-16
+ addiu $6,$6,-4
+ sll $11,$10,$7
+ srl $12,$3,$13
+
+ lw $10,-12($5)
+ sll $14,$3,$7
+ or $8,$11,$12
+ sw $8,12($4)
+ srl $9,$10,$13
+
+ lw $3,-16($5)
+ sll $11,$10,$7
+ or $8,$14,$9
+ sw $8,8($4)
+ srl $12,$3,$13
+
+ lw $10,-20($5)
+ sll $14,$3,$7
+ or $8,$11,$12
+ sw $8,4($4)
+ srl $9,$10,$13
+
+ addiu $5,$5,-16
+ or $8,$14,$9
+ bgtz $6,.Loop
+ sw $8,0($4)
+
+.Lend: sll $8,$10,$7
+ j $31
+ sw $8,-4($4)
+ .end __mpn_lshift
diff --git a/mpn/mips2/mul_1.s b/mpn/mips2/mul_1.s
new file mode 100644
index 000000000..d006fa122
--- /dev/null
+++ b/mpn/mips2/mul_1.s
@@ -0,0 +1,85 @@
+ # MIPS __mpn_mul_1 -- Multiply a limb vector with a single limb and
+ # store the product in a second limb vector.
+
+ # Copyright (C) 1992, 1994, 1996 Free Software Foundation, Inc.
+
+ # This file is part of the GNU MP Library.
+
+ # The GNU MP Library is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU Library General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or (at your
+ # option) any later version.
+
+ # The GNU MP Library 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 Library General Public
+ # License for more details.
+
+ # You should have received a copy of the GNU Library General Public License
+ # along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+ # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ # MA 02111-1307, USA.
+
+
+ # INPUT PARAMETERS
+ # res_ptr $4
+ # s1_ptr $5
+ # size $6
+ # s2_limb $7
+
+ .text
+ .align 4
+ .globl __mpn_mul_1
+ .ent __mpn_mul_1
+__mpn_mul_1:
+ .set noreorder
+ .set nomacro
+
+ # warm up phase 0
+ lw $8,0($5)
+
+ # warm up phase 1
+ addiu $5,$5,4
+ multu $8,$7
+
+ addiu $6,$6,-1
+ beq $6,$0,$LC0
+ move $2,$0 # zero cy2
+
+ addiu $6,$6,-1
+ beq $6,$0,$LC1
+ lw $8,0($5) # load new s1 limb as early as possible
+
+Loop: mflo $10
+ mfhi $9
+ addiu $5,$5,4
+ addu $10,$10,$2 # add old carry limb to low product limb
+ multu $8,$7
+ lw $8,0($5) # load new s1 limb as early as possible
+ addiu $6,$6,-1 # decrement loop counter
+ sltu $2,$10,$2 # carry from previous addition -> $2
+ sw $10,0($4)
+ addiu $4,$4,4
+ bne $6,$0,Loop
+ addu $2,$9,$2 # add high product limb and carry from addition
+
+ # cool down phase 1
+$LC1: mflo $10
+ mfhi $9
+ addu $10,$10,$2
+ sltu $2,$10,$2
+ multu $8,$7
+ sw $10,0($4)
+ addiu $4,$4,4
+ addu $2,$9,$2 # add high product limb and carry from addition
+
+ # cool down phase 0
+$LC0: mflo $10
+ mfhi $9
+ addu $10,$10,$2
+ sltu $2,$10,$2
+ sw $10,0($4)
+ j $31
+ addu $2,$9,$2 # add high product limb and carry from addition
+
+ .end __mpn_mul_1
diff --git a/mpn/mips2/rshift.s b/mpn/mips2/rshift.s
new file mode 100644
index 000000000..a8beb4057
--- /dev/null
+++ b/mpn/mips2/rshift.s
@@ -0,0 +1,92 @@
+ # MIPS2 __mpn_rshift --
+
+ # Copyright (C) 1995 Free Software Foundation, Inc.
+
+ # This file is part of the GNU MP Library.
+
+ # The GNU MP Library is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU Library General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or (at your
+ # option) any later version.
+
+ # The GNU MP Library 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 Library General Public
+ # License for more details.
+
+ # You should have received a copy of the GNU Library General Public License
+ # along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+ # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ # MA 02111-1307, USA.
+
+
+ # INPUT PARAMETERS
+ # res_ptr $4
+ # src_ptr $5
+ # size $6
+ # cnt $7
+
+ .text
+ .align 2
+ .globl __mpn_rshift
+ .ent __mpn_rshift
+__mpn_rshift:
+ .set noreorder
+ .set nomacro
+
+ lw $10,0($5) # load first limb
+ subu $13,$0,$7
+ addiu $6,$6,-1
+ and $9,$6,4-1 # number of limbs in first loop
+ beq $9,$0,.L0 # if multiple of 4 limbs, skip first loop
+ sll $2,$10,$13 # compute function result
+
+ subu $6,$6,$9
+
+.Loop0: lw $3,4($5)
+ addiu $4,$4,4
+ addiu $5,$5,4
+ addiu $9,$9,-1
+ srl $11,$10,$7
+ sll $12,$3,$13
+ move $10,$3
+ or $8,$11,$12
+ bne $9,$0,.Loop0
+ sw $8,-4($4)
+
+.L0: beq $6,$0,.Lend
+ nop
+
+.Loop: lw $3,4($5)
+ addiu $4,$4,16
+ addiu $6,$6,-4
+ srl $11,$10,$7
+ sll $12,$3,$13
+
+ lw $10,8($5)
+ srl $14,$3,$7
+ or $8,$11,$12
+ sw $8,-16($4)
+ sll $9,$10,$13
+
+ lw $3,12($5)
+ srl $11,$10,$7
+ or $8,$14,$9
+ sw $8,-12($4)
+ sll $12,$3,$13
+
+ lw $10,16($5)
+ srl $14,$3,$7
+ or $8,$11,$12
+ sw $8,-8($4)
+ sll $9,$10,$13
+
+ addiu $5,$5,16
+ or $8,$14,$9
+ bgtz $6,.Loop
+ sw $8,-4($4)
+
+.Lend: srl $8,$10,$7
+ j $31
+ sw $8,0($4)
+ .end __mpn_rshift
diff --git a/mpn/mips2/sub_n.s b/mpn/mips2/sub_n.s
new file mode 100644
index 000000000..3368ef29d
--- /dev/null
+++ b/mpn/mips2/sub_n.s
@@ -0,0 +1,120 @@
+ # MIPS2 __mpn_sub_n -- Subtract two limb vectors of the same length > 0 and
+ # store difference in a third limb vector.
+
+ # Copyright (C) 1995 Free Software Foundation, Inc.
+
+ # This file is part of the GNU MP Library.
+
+ # The GNU MP Library is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU Library General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or (at your
+ # option) any later version.
+
+ # The GNU MP Library 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 Library General Public
+ # License for more details.
+
+ # You should have received a copy of the GNU Library General Public License
+ # along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+ # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ # MA 02111-1307, USA.
+
+
+ # INPUT PARAMETERS
+ # res_ptr $4
+ # s1_ptr $5
+ # s2_ptr $6
+ # size $7
+
+ .text
+ .align 2
+ .globl __mpn_sub_n
+ .ent __mpn_sub_n
+__mpn_sub_n:
+ .set noreorder
+ .set nomacro
+
+ lw $10,0($5)
+ lw $11,0($6)
+
+ addiu $7,$7,-1
+ and $9,$7,4-1 # number of limbs in first loop
+ beq $9,$0,.L0 # if multiple of 4 limbs, skip first loop
+ move $2,$0
+
+ subu $7,$7,$9
+
+.Loop0: addiu $9,$9,-1
+ lw $12,4($5)
+ addu $11,$11,$2
+ lw $13,4($6)
+ sltu $8,$11,$2
+ subu $11,$10,$11
+ sltu $2,$10,$11
+ sw $11,0($4)
+ or $2,$2,$8
+
+ addiu $5,$5,4
+ addiu $6,$6,4
+ move $10,$12
+ move $11,$13
+ bne $9,$0,.Loop0
+ addiu $4,$4,4
+
+.L0: beq $7,$0,.Lend
+ nop
+
+.Loop: addiu $7,$7,-4
+
+ lw $12,4($5)
+ addu $11,$11,$2
+ lw $13,4($6)
+ sltu $8,$11,$2
+ subu $11,$10,$11
+ sltu $2,$10,$11
+ sw $11,0($4)
+ or $2,$2,$8
+
+ lw $10,8($5)
+ addu $13,$13,$2
+ lw $11,8($6)
+ sltu $8,$13,$2
+ subu $13,$12,$13
+ sltu $2,$12,$13
+ sw $13,4($4)
+ or $2,$2,$8
+
+ lw $12,12($5)
+ addu $11,$11,$2
+ lw $13,12($6)
+ sltu $8,$11,$2
+ subu $11,$10,$11
+ sltu $2,$10,$11
+ sw $11,8($4)
+ or $2,$2,$8
+
+ lw $10,16($5)
+ addu $13,$13,$2
+ lw $11,16($6)
+ sltu $8,$13,$2
+ subu $13,$12,$13
+ sltu $2,$12,$13
+ sw $13,12($4)
+ or $2,$2,$8
+
+ addiu $5,$5,16
+ addiu $6,$6,16
+
+ bne $7,$0,.Loop
+ addiu $4,$4,16
+
+.Lend: addu $11,$11,$2
+ sltu $8,$11,$2
+ subu $11,$10,$11
+ sltu $2,$10,$11
+ sw $11,0($4)
+ j $31
+ or $2,$2,$8
+
+ .end __mpn_sub_n
diff --git a/mpn/mips2/submul_1.s b/mpn/mips2/submul_1.s
new file mode 100644
index 000000000..1324b6609
--- /dev/null
+++ b/mpn/mips2/submul_1.s
@@ -0,0 +1,97 @@
+ # MIPS __mpn_submul_1 -- Multiply a limb vector with a single limb and
+ # subtract the product from a second limb vector.
+
+ # Copyright (C) 1992, 1994, 1996 Free Software Foundation, Inc.
+
+ # This file is part of the GNU MP Library.
+
+ # The GNU MP Library is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU Library General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or (at your
+ # option) any later version.
+
+ # The GNU MP Library 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 Library General Public
+ # License for more details.
+
+ # You should have received a copy of the GNU Library General Public License
+ # along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+ # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ # MA 02111-1307, USA.
+
+
+ # INPUT PARAMETERS
+ # res_ptr $4
+ # s1_ptr $5
+ # size $6
+ # s2_limb $7
+
+ .text
+ .align 4
+ .globl __mpn_submul_1
+ .ent __mpn_submul_1
+__mpn_submul_1:
+ .set noreorder
+ .set nomacro
+
+ # warm up phase 0
+ lw $8,0($5)
+
+ # warm up phase 1
+ addiu $5,$5,4
+ multu $8,$7
+
+ addiu $6,$6,-1
+ beq $6,$0,$LC0
+ move $2,$0 # zero cy2
+
+ addiu $6,$6,-1
+ beq $6,$0,$LC1
+ lw $8,0($5) # load new s1 limb as early as possible
+
+Loop: lw $10,0($4)
+ mflo $3
+ mfhi $9
+ addiu $5,$5,4
+ addu $3,$3,$2 # add old carry limb to low product limb
+ multu $8,$7
+ lw $8,0($5) # load new s1 limb as early as possible
+ addiu $6,$6,-1 # decrement loop counter
+ sltu $2,$3,$2 # carry from previous addition -> $2
+ subu $3,$10,$3
+ sgtu $10,$3,$10
+ addu $2,$2,$10
+ sw $3,0($4)
+ addiu $4,$4,4
+ bne $6,$0,Loop
+ addu $2,$9,$2 # add high product limb and carry from addition
+
+ # cool down phase 1
+$LC1: lw $10,0($4)
+ mflo $3
+ mfhi $9
+ addu $3,$3,$2
+ sltu $2,$3,$2
+ multu $8,$7
+ subu $3,$10,$3
+ sgtu $10,$3,$10
+ addu $2,$2,$10
+ sw $3,0($4)
+ addiu $4,$4,4
+ addu $2,$9,$2 # add high product limb and carry from addition
+
+ # cool down phase 0
+$LC0: lw $10,0($4)
+ mflo $3
+ mfhi $9
+ addu $3,$3,$2
+ sltu $2,$3,$2
+ subu $3,$10,$3
+ sgtu $10,$3,$10
+ addu $2,$2,$10
+ sw $3,0($4)
+ j $31
+ addu $2,$9,$2 # add high product limb and carry from addition
+
+ .end __mpn_submul_1
diff --git a/mpn/mips3/README b/mpn/mips3/README
new file mode 100644
index 000000000..e94b2c746
--- /dev/null
+++ b/mpn/mips3/README
@@ -0,0 +1,23 @@
+This directory contains mpn functions optimized for MIPS3. Example of
+processors that implement MIPS3 are R4000, R4400, R4600, R4700, and R8000.
+
+RELEVANT OPTIMIZATION ISSUES
+
+1. On the R4000 and R4400, branches, both the plain and the "likely" ones,
+ take 3 cycles to execute. (The fastest possible loop will take 4 cycles,
+ because of the delay insn.)
+
+ On the R4600, branches takes a single cycle
+
+ On the R8000, branches often take no noticable cycles, as they are
+ executed in a separate function unit..
+
+2. The R4000 and R4400 have a load latency of 4 cycles.
+
+3. On the R4000 and R4400, multiplies take a data-dependent number of
+ cycles, contrary to the SGI documentation. There seem to be 3 or 4
+ possible latencies.
+
+STATUS
+
+Good...
diff --git a/mpn/mips3/add_n.s b/mpn/mips3/add_n.s
new file mode 100644
index 000000000..996a449eb
--- /dev/null
+++ b/mpn/mips3/add_n.s
@@ -0,0 +1,120 @@
+ # MIPS3 __mpn_add_n -- Add two limb vectors of the same length > 0 and
+ # store sum in a third limb vector.
+
+ # Copyright (C) 1995 Free Software Foundation, Inc.
+
+ # This file is part of the GNU MP Library.
+
+ # The GNU MP Library is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU Library General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or (at your
+ # option) any later version.
+
+ # The GNU MP Library 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 Library General Public
+ # License for more details.
+
+ # You should have received a copy of the GNU Library General Public License
+ # along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+ # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ # MA 02111-1307, USA.
+
+
+ # INPUT PARAMETERS
+ # res_ptr $4
+ # s1_ptr $5
+ # s2_ptr $6
+ # size $7
+
+ .text
+ .align 2
+ .globl __mpn_add_n
+ .ent __mpn_add_n
+__mpn_add_n:
+ .set noreorder
+ .set nomacro
+
+ ld $10,0($5)
+ ld $11,0($6)
+
+ daddiu $7,$7,-1
+ and $9,$7,4-1 # number of limbs in first loop
+ beq $9,$0,.L0 # if multiple of 4 limbs, skip first loop
+ move $2,$0
+
+ dsubu $7,$7,$9
+
+.Loop0: daddiu $9,$9,-1
+ ld $12,8($5)
+ daddu $11,$11,$2
+ ld $13,8($6)
+ sltu $8,$11,$2
+ daddu $11,$10,$11
+ sltu $2,$11,$10
+ sd $11,0($4)
+ or $2,$2,$8
+
+ daddiu $5,$5,8
+ daddiu $6,$6,8
+ move $10,$12
+ move $11,$13
+ bne $9,$0,.Loop0
+ daddiu $4,$4,8
+
+.L0: beq $7,$0,.Lend
+ nop
+
+.Loop: daddiu $7,$7,-4
+
+ ld $12,8($5)
+ daddu $11,$11,$2
+ ld $13,8($6)
+ sltu $8,$11,$2
+ daddu $11,$10,$11
+ sltu $2,$11,$10
+ sd $11,0($4)
+ or $2,$2,$8
+
+ ld $10,16($5)
+ daddu $13,$13,$2
+ ld $11,16($6)
+ sltu $8,$13,$2
+ daddu $13,$12,$13
+ sltu $2,$13,$12
+ sd $13,8($4)
+ or $2,$2,$8
+
+ ld $12,24($5)
+ daddu $11,$11,$2
+ ld $13,24($6)
+ sltu $8,$11,$2
+ daddu $11,$10,$11
+ sltu $2,$11,$10
+ sd $11,16($4)
+ or $2,$2,$8
+
+ ld $10,32($5)
+ daddu $13,$13,$2
+ ld $11,32($6)
+ sltu $8,$13,$2
+ daddu $13,$12,$13
+ sltu $2,$13,$12
+ sd $13,24($4)
+ or $2,$2,$8
+
+ daddiu $5,$5,32
+ daddiu $6,$6,32
+
+ bne $7,$0,.Loop
+ daddiu $4,$4,32
+
+.Lend: daddu $11,$11,$2
+ sltu $8,$11,$2
+ daddu $11,$10,$11
+ sltu $2,$11,$10
+ sd $11,0($4)
+ j $31
+ or $2,$2,$8
+
+ .end __mpn_add_n
diff --git a/mpn/mips3/addmul_1.s b/mpn/mips3/addmul_1.s
new file mode 100644
index 000000000..cd75c1801
--- /dev/null
+++ b/mpn/mips3/addmul_1.s
@@ -0,0 +1,97 @@
+ # MIPS3 __mpn_addmul_1 -- Multiply a limb vector with a single limb and
+ # add the product to a second limb vector.
+
+ # Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
+
+ # This file is part of the GNU MP Library.
+
+ # The GNU MP Library is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU Library General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or (at your
+ # option) any later version.
+
+ # The GNU MP Library 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 Library General Public
+ # License for more details.
+
+ # You should have received a copy of the GNU Library General Public License
+ # along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+ # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ # MA 02111-1307, USA.
+
+
+ # INPUT PARAMETERS
+ # res_ptr $4
+ # s1_ptr $5
+ # size $6
+ # s2_limb $7
+
+ .text
+ .align 4
+ .globl __mpn_addmul_1
+ .ent __mpn_addmul_1
+__mpn_addmul_1:
+ .set noreorder
+ .set nomacro
+
+ # warm up phase 0
+ ld $8,0($5)
+
+ # warm up phase 1
+ daddiu $5,$5,8
+ dmultu $8,$7
+
+ daddiu $6,$6,-1
+ beq $6,$0,$LC0
+ move $2,$0 # zero cy2
+
+ daddiu $6,$6,-1
+ beq $6,$0,$LC1
+ ld $8,0($5) # load new s1 limb as early as possible
+
+Loop: ld $10,0($4)
+ mflo $3
+ mfhi $9
+ daddiu $5,$5,8
+ daddu $3,$3,$2 # add old carry limb to low product limb
+ dmultu $8,$7
+ ld $8,0($5) # load new s1 limb as early as possible
+ daddiu $6,$6,-1 # decrement loop counter
+ sltu $2,$3,$2 # carry from previous addition -> $2
+ daddu $3,$10,$3
+ sltu $10,$3,$10
+ daddu $2,$2,$10
+ sd $3,0($4)
+ daddiu $4,$4,8
+ bne $6,$0,Loop
+ daddu $2,$9,$2 # add high product limb and carry from addition
+
+ # cool down phase 1
+$LC1: ld $10,0($4)
+ mflo $3
+ mfhi $9
+ daddu $3,$3,$2
+ sltu $2,$3,$2
+ dmultu $8,$7
+ daddu $3,$10,$3
+ sltu $10,$3,$10
+ daddu $2,$2,$10
+ sd $3,0($4)
+ daddiu $4,$4,8
+ daddu $2,$9,$2 # add high product limb and carry from addition
+
+ # cool down phase 0
+$LC0: ld $10,0($4)
+ mflo $3
+ mfhi $9
+ daddu $3,$3,$2
+ sltu $2,$3,$2
+ daddu $3,$10,$3
+ sltu $10,$3,$10
+ daddu $2,$2,$10
+ sd $3,0($4)
+ j $31
+ daddu $2,$9,$2 # add high product limb and carry from addition
+
+ .end __mpn_addmul_1
diff --git a/mpn/mips3/gmp-mparam.h b/mpn/mips3/gmp-mparam.h
new file mode 100644
index 000000000..f3df7ff6e
--- /dev/null
+++ b/mpn/mips3/gmp-mparam.h
@@ -0,0 +1,27 @@
+/* gmp-mparam.h -- Compiler/machine parameter header file.
+
+Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#define BITS_PER_MP_LIMB 64
+#define BYTES_PER_MP_LIMB 8
+#define BITS_PER_LONGINT 32
+#define BITS_PER_INT 32
+#define BITS_PER_SHORTINT 16
+#define BITS_PER_CHAR 8
diff --git a/mpn/mips3/lshift.s b/mpn/mips3/lshift.s
new file mode 100644
index 000000000..324a6020c
--- /dev/null
+++ b/mpn/mips3/lshift.s
@@ -0,0 +1,95 @@
+ # MIPS3 __mpn_lshift --
+
+ # Copyright (C) 1995 Free Software Foundation, Inc.
+
+ # This file is part of the GNU MP Library.
+
+ # The GNU MP Library is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU Library General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or (at your
+ # option) any later version.
+
+ # The GNU MP Library 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 Library General Public
+ # License for more details.
+
+ # You should have received a copy of the GNU Library General Public License
+ # along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+ # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ # MA 02111-1307, USA.
+
+
+ # INPUT PARAMETERS
+ # res_ptr $4
+ # src_ptr $5
+ # size $6
+ # cnt $7
+
+ .text
+ .align 2
+ .globl __mpn_lshift
+ .ent __mpn_lshift
+__mpn_lshift:
+ .set noreorder
+ .set nomacro
+
+ dsll $2,$6,3
+ daddu $5,$5,$2 # make r5 point at end of src
+ ld $10,-8($5) # load first limb
+ dsubu $13,$0,$7
+ daddu $4,$4,$2 # make r4 point at end of res
+ daddiu $6,$6,-1
+ and $9,$6,4-1 # number of limbs in first loop
+ beq $9,$0,.L0 # if multiple of 4 limbs, skip first loop
+ dsrl $2,$10,$13 # compute function result
+
+ dsubu $6,$6,$9
+
+.Loop0: ld $3,-16($5)
+ daddiu $4,$4,-8
+ daddiu $5,$5,-8
+ daddiu $9,$9,-1
+ dsll $11,$10,$7
+ dsrl $12,$3,$13
+ move $10,$3
+ or $8,$11,$12
+ bne $9,$0,.Loop0
+ sd $8,0($4)
+
+.L0: beq $6,$0,.Lend
+ nop
+
+.Loop: ld $3,-16($5)
+ daddiu $4,$4,-32
+ daddiu $6,$6,-4
+ dsll $11,$10,$7
+ dsrl $12,$3,$13
+
+ ld $10,-24($5)
+ dsll $14,$3,$7
+ or $8,$11,$12
+ sd $8,24($4)
+ dsrl $9,$10,$13
+
+ ld $3,-32($5)
+ dsll $11,$10,$7
+ or $8,$14,$9
+ sd $8,16($4)
+ dsrl $12,$3,$13
+
+ ld $10,-40($5)
+ dsll $14,$3,$7
+ or $8,$11,$12
+ sd $8,8($4)
+ dsrl $9,$10,$13
+
+ daddiu $5,$5,-32
+ or $8,$14,$9
+ bgtz $6,.Loop
+ sd $8,0($4)
+
+.Lend: dsll $8,$10,$7
+ j $31
+ sd $8,-8($4)
+ .end __mpn_lshift
diff --git a/mpn/mips3/mul_1.s b/mpn/mips3/mul_1.s
new file mode 100644
index 000000000..281d0574a
--- /dev/null
+++ b/mpn/mips3/mul_1.s
@@ -0,0 +1,85 @@
+ # MIPS3 __mpn_mul_1 -- Multiply a limb vector with a single limb and
+ # store the product in a second limb vector.
+
+ # Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
+
+ # This file is part of the GNU MP Library.
+
+ # The GNU MP Library is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU Library General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or (at your
+ # option) any later version.
+
+ # The GNU MP Library 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 Library General Public
+ # License for more details.
+
+ # You should have received a copy of the GNU Library General Public License
+ # along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+ # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ # MA 02111-1307, USA.
+
+
+ # INPUT PARAMETERS
+ # res_ptr $4
+ # s1_ptr $5
+ # size $6
+ # s2_limb $7
+
+ .text
+ .align 4
+ .globl __mpn_mul_1
+ .ent __mpn_mul_1
+__mpn_mul_1:
+ .set noreorder
+ .set nomacro
+
+ # warm up phase 0
+ ld $8,0($5)
+
+ # warm up phase 1
+ daddiu $5,$5,8
+ dmultu $8,$7
+
+ daddiu $6,$6,-1
+ beq $6,$0,$LC0
+ move $2,$0 # zero cy2
+
+ daddiu $6,$6,-1
+ beq $6,$0,$LC1
+ ld $8,0($5) # load new s1 limb as early as possible
+
+Loop: mflo $10
+ mfhi $9
+ daddiu $5,$5,8
+ daddu $10,$10,$2 # add old carry limb to low product limb
+ dmultu $8,$7
+ ld $8,0($5) # load new s1 limb as early as possible
+ daddiu $6,$6,-1 # decrement loop counter
+ sltu $2,$10,$2 # carry from previous addition -> $2
+ sd $10,0($4)
+ daddiu $4,$4,8
+ bne $6,$0,Loop
+ daddu $2,$9,$2 # add high product limb and carry from addition
+
+ # cool down phase 1
+$LC1: mflo $10
+ mfhi $9
+ daddu $10,$10,$2
+ sltu $2,$10,$2
+ dmultu $8,$7
+ sd $10,0($4)
+ daddiu $4,$4,8
+ daddu $2,$9,$2 # add high product limb and carry from addition
+
+ # cool down phase 0
+$LC0: mflo $10
+ mfhi $9
+ daddu $10,$10,$2
+ sltu $2,$10,$2
+ sd $10,0($4)
+ j $31
+ daddu $2,$9,$2 # add high product limb and carry from addition
+
+ .end __mpn_mul_1
diff --git a/mpn/mips3/rshift.s b/mpn/mips3/rshift.s
new file mode 100644
index 000000000..9920e1a9e
--- /dev/null
+++ b/mpn/mips3/rshift.s
@@ -0,0 +1,92 @@
+ # MIPS3 __mpn_rshift --
+
+ # Copyright (C) 1995 Free Software Foundation, Inc.
+
+ # This file is part of the GNU MP Library.
+
+ # The GNU MP Library is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU Library General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or (at your
+ # option) any later version.
+
+ # The GNU MP Library 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 Library General Public
+ # License for more details.
+
+ # You should have received a copy of the GNU Library General Public License
+ # along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+ # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ # MA 02111-1307, USA.
+
+
+ # INPUT PARAMETERS
+ # res_ptr $4
+ # src_ptr $5
+ # size $6
+ # cnt $7
+
+ .text
+ .align 2
+ .globl __mpn_rshift
+ .ent __mpn_rshift
+__mpn_rshift:
+ .set noreorder
+ .set nomacro
+
+ ld $10,0($5) # load first limb
+ dsubu $13,$0,$7
+ daddiu $6,$6,-1
+ and $9,$6,4-1 # number of limbs in first loop
+ beq $9,$0,.L0 # if multiple of 4 limbs, skip first loop
+ dsll $2,$10,$13 # compute function result
+
+ dsubu $6,$6,$9
+
+.Loop0: ld $3,8($5)
+ daddiu $4,$4,8
+ daddiu $5,$5,8
+ daddiu $9,$9,-1
+ dsrl $11,$10,$7
+ dsll $12,$3,$13
+ move $10,$3
+ or $8,$11,$12
+ bne $9,$0,.Loop0
+ sd $8,-8($4)
+
+.L0: beq $6,$0,.Lend
+ nop
+
+.Loop: ld $3,8($5)
+ daddiu $4,$4,32
+ daddiu $6,$6,-4
+ dsrl $11,$10,$7
+ dsll $12,$3,$13
+
+ ld $10,16($5)
+ dsrl $14,$3,$7
+ or $8,$11,$12
+ sd $8,-32($4)
+ dsll $9,$10,$13
+
+ ld $3,24($5)
+ dsrl $11,$10,$7
+ or $8,$14,$9
+ sd $8,-24($4)
+ dsll $12,$3,$13
+
+ ld $10,32($5)
+ dsrl $14,$3,$7
+ or $8,$11,$12
+ sd $8,-16($4)
+ dsll $9,$10,$13
+
+ daddiu $5,$5,32
+ or $8,$14,$9
+ bgtz $6,.Loop
+ sd $8,-8($4)
+
+.Lend: dsrl $8,$10,$7
+ j $31
+ sd $8,0($4)
+ .end __mpn_rshift
diff --git a/mpn/mips3/sub_n.s b/mpn/mips3/sub_n.s
new file mode 100644
index 000000000..56c77d8bc
--- /dev/null
+++ b/mpn/mips3/sub_n.s
@@ -0,0 +1,120 @@
+ # MIPS3 __mpn_sub_n -- Subtract two limb vectors of the same length > 0 and
+ # store difference in a third limb vector.
+
+ # Copyright (C) 1995 Free Software Foundation, Inc.
+
+ # This file is part of the GNU MP Library.
+
+ # The GNU MP Library is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU Library General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or (at your
+ # option) any later version.
+
+ # The GNU MP Library 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 Library General Public
+ # License for more details.
+
+ # You should have received a copy of the GNU Library General Public License
+ # along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+ # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ # MA 02111-1307, USA.
+
+
+ # INPUT PARAMETERS
+ # res_ptr $4
+ # s1_ptr $5
+ # s2_ptr $6
+ # size $7
+
+ .text
+ .align 2
+ .globl __mpn_sub_n
+ .ent __mpn_sub_n
+__mpn_sub_n:
+ .set noreorder
+ .set nomacro
+
+ ld $10,0($5)
+ ld $11,0($6)
+
+ daddiu $7,$7,-1
+ and $9,$7,4-1 # number of limbs in first loop
+ beq $9,$0,.L0 # if multiple of 4 limbs, skip first loop
+ move $2,$0
+
+ dsubu $7,$7,$9
+
+.Loop0: daddiu $9,$9,-1
+ ld $12,8($5)
+ daddu $11,$11,$2
+ ld $13,8($6)
+ sltu $8,$11,$2
+ dsubu $11,$10,$11
+ sltu $2,$10,$11
+ sd $11,0($4)
+ or $2,$2,$8
+
+ daddiu $5,$5,8
+ daddiu $6,$6,8
+ move $10,$12
+ move $11,$13
+ bne $9,$0,.Loop0
+ daddiu $4,$4,8
+
+.L0: beq $7,$0,.Lend
+ nop
+
+.Loop: daddiu $7,$7,-4
+
+ ld $12,8($5)
+ daddu $11,$11,$2
+ ld $13,8($6)
+ sltu $8,$11,$2
+ dsubu $11,$10,$11
+ sltu $2,$10,$11
+ sd $11,0($4)
+ or $2,$2,$8
+
+ ld $10,16($5)
+ daddu $13,$13,$2
+ ld $11,16($6)
+ sltu $8,$13,$2
+ dsubu $13,$12,$13
+ sltu $2,$12,$13
+ sd $13,8($4)
+ or $2,$2,$8
+
+ ld $12,24($5)
+ daddu $11,$11,$2
+ ld $13,24($6)
+ sltu $8,$11,$2
+ dsubu $11,$10,$11
+ sltu $2,$10,$11
+ sd $11,16($4)
+ or $2,$2,$8
+
+ ld $10,32($5)
+ daddu $13,$13,$2
+ ld $11,32($6)
+ sltu $8,$13,$2
+ dsubu $13,$12,$13
+ sltu $2,$12,$13
+ sd $13,24($4)
+ or $2,$2,$8
+
+ daddiu $5,$5,32
+ daddiu $6,$6,32
+
+ bne $7,$0,.Loop
+ daddiu $4,$4,32
+
+.Lend: daddu $11,$11,$2
+ sltu $8,$11,$2
+ dsubu $11,$10,$11
+ sltu $2,$10,$11
+ sd $11,0($4)
+ j $31
+ or $2,$2,$8
+
+ .end __mpn_sub_n
diff --git a/mpn/mips3/submul_1.s b/mpn/mips3/submul_1.s
new file mode 100644
index 000000000..a9c9fa251
--- /dev/null
+++ b/mpn/mips3/submul_1.s
@@ -0,0 +1,97 @@
+ # MIPS3 __mpn_submul_1 -- Multiply a limb vector with a single limb and
+ # subtract the product from a second limb vector.
+
+ # Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
+
+ # This file is part of the GNU MP Library.
+
+ # The GNU MP Library is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU Library General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or (at your
+ # option) any later version.
+
+ # The GNU MP Library 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 Library General Public
+ # License for more details.
+
+ # You should have received a copy of the GNU Library General Public License
+ # along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+ # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ # MA 02111-1307, USA.
+
+
+ # INPUT PARAMETERS
+ # res_ptr $4
+ # s1_ptr $5
+ # size $6
+ # s2_limb $7
+
+ .text
+ .align 4
+ .globl __mpn_submul_1
+ .ent __mpn_submul_1
+__mpn_submul_1:
+ .set noreorder
+ .set nomacro
+
+ # warm up phase 0
+ ld $8,0($5)
+
+ # warm up phase 1
+ daddiu $5,$5,8
+ dmultu $8,$7
+
+ daddiu $6,$6,-1
+ beq $6,$0,$LC0
+ move $2,$0 # zero cy2
+
+ daddiu $6,$6,-1
+ beq $6,$0,$LC1
+ ld $8,0($5) # load new s1 limb as early as possible
+
+Loop: ld $10,0($4)
+ mflo $3
+ mfhi $9
+ daddiu $5,$5,8
+ daddu $3,$3,$2 # add old carry limb to low product limb
+ dmultu $8,$7
+ ld $8,0($5) # load new s1 limb as early as possible
+ daddiu $6,$6,-1 # decrement loop counter
+ sltu $2,$3,$2 # carry from previous addition -> $2
+ dsubu $3,$10,$3
+ sgtu $10,$3,$10
+ daddu $2,$2,$10
+ sd $3,0($4)
+ daddiu $4,$4,8
+ bne $6,$0,Loop
+ daddu $2,$9,$2 # add high product limb and carry from addition
+
+ # cool down phase 1
+$LC1: ld $10,0($4)
+ mflo $3
+ mfhi $9
+ daddu $3,$3,$2
+ sltu $2,$3,$2
+ dmultu $8,$7
+ dsubu $3,$10,$3
+ sgtu $10,$3,$10
+ daddu $2,$2,$10
+ sd $3,0($4)
+ daddiu $4,$4,8
+ daddu $2,$9,$2 # add high product limb and carry from addition
+
+ # cool down phase 0
+$LC0: ld $10,0($4)
+ mflo $3
+ mfhi $9
+ daddu $3,$3,$2
+ sltu $2,$3,$2
+ dsubu $3,$10,$3
+ sgtu $10,$3,$10
+ daddu $2,$2,$10
+ sd $3,0($4)
+ j $31
+ daddu $2,$9,$2 # add high product limb and carry from addition
+
+ .end __mpn_submul_1
diff --git a/mpn/mp_bases.c b/mpn/mp_bases.c
new file mode 100644
index 000000000..bbe39b029
--- /dev/null
+++ b/mpn/mp_bases.c
@@ -0,0 +1,549 @@
+/* __mp_bases -- Structure for conversion between internal binary
+ format and strings in base 2..255. The fields are explained in
+ gmp-impl.h.
+
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+#if BITS_PER_MP_LIMB == 32
+const struct bases __mp_bases[256] =
+{
+ /* 0 */ {0, 0.0, 0, 0},
+ /* 1 */ {0, 1e38, 0, 0},
+ /* 2 */ {32, 1.00000000, 0x1, 0x0},
+ /* 3 */ {20, 0.63092975, 0xcfd41b91, 0x3b563c24},
+ /* 4 */ {16, 0.50000000, 0x2, 0x0},
+ /* 5 */ {13, 0.43067656, 0x48c27395, 0xc25c2684},
+ /* 6 */ {12, 0.38685281, 0x81bf1000, 0xf91bd1b6},
+ /* 7 */ {11, 0.35620719, 0x75db9c97, 0x1607a2cb},
+ /* 8 */ {10, 0.33333333, 0x3, 0x0},
+ /* 9 */ {10, 0.31546488, 0xcfd41b91, 0x3b563c24},
+ /* 10 */ {9, 0.30103000, 0x3b9aca00, 0x12e0be82},
+ /* 11 */ {9, 0.28906483, 0x8c8b6d2b, 0xd24cde04},
+ /* 12 */ {8, 0.27894295, 0x19a10000, 0x3fa39ab5},
+ /* 13 */ {8, 0.27023815, 0x309f1021, 0x50f8ac5f},
+ /* 14 */ {8, 0.26264954, 0x57f6c100, 0x74843b1e},
+ /* 15 */ {8, 0.25595802, 0x98c29b81, 0xad0326c2},
+ /* 16 */ {8, 0.25000000, 0x4, 0x0},
+ /* 17 */ {7, 0.24465054, 0x18754571, 0x4ef0b6bd},
+ /* 18 */ {7, 0.23981247, 0x247dbc80, 0xc0fc48a1},
+ /* 19 */ {7, 0.23540891, 0x3547667b, 0x33838942},
+ /* 20 */ {7, 0.23137821, 0x4c4b4000, 0xad7f29ab},
+ /* 21 */ {7, 0.22767025, 0x6b5a6e1d, 0x313c3d15},
+ /* 22 */ {7, 0.22424382, 0x94ace180, 0xb8cca9e0},
+ /* 23 */ {7, 0.22106473, 0xcaf18367, 0x42ed6de9},
+ /* 24 */ {6, 0.21810429, 0xb640000, 0x67980e0b},
+ /* 25 */ {6, 0.21533828, 0xe8d4a51, 0x19799812},
+ /* 26 */ {6, 0.21274605, 0x1269ae40, 0xbce85396},
+ /* 27 */ {6, 0.21030992, 0x17179149, 0x62c103a9},
+ /* 28 */ {6, 0.20801460, 0x1cb91000, 0x1d353d43},
+ /* 29 */ {6, 0.20584683, 0x23744899, 0xce1decea},
+ /* 30 */ {6, 0.20379505, 0x2b73a840, 0x790fc511},
+ /* 31 */ {6, 0.20184909, 0x34e63b41, 0x35b865a0},
+ /* 32 */ {6, 0.20000000, 0x5, 0x0},
+ /* 33 */ {6, 0.19823986, 0x4cfa3cc1, 0xa9aed1b3},
+ /* 34 */ {6, 0.19656163, 0x5c13d840, 0x63dfc229},
+ /* 35 */ {6, 0.19495902, 0x6d91b519, 0x2b0fee30},
+ /* 36 */ {6, 0.19342640, 0x81bf1000, 0xf91bd1b6},
+ /* 37 */ {6, 0.19195872, 0x98ede0c9, 0xac89c3a9},
+ /* 38 */ {6, 0.19055141, 0xb3773e40, 0x6d2c32fe},
+ /* 39 */ {6, 0.18920036, 0xd1bbc4d1, 0x387907c9},
+ /* 40 */ {6, 0.18790182, 0xf4240000, 0xc6f7a0b},
+ /* 41 */ {5, 0.18665241, 0x6e7d349, 0x28928154},
+ /* 42 */ {5, 0.18544902, 0x7ca30a0, 0x6e8629d},
+ /* 43 */ {5, 0.18428883, 0x8c32bbb, 0xd373dca0},
+ /* 44 */ {5, 0.18316925, 0x9d46c00, 0xa0b17895},
+ /* 45 */ {5, 0.18208790, 0xaffacfd, 0x746811a5},
+ /* 46 */ {5, 0.18104260, 0xc46bee0, 0x4da6500f},
+ /* 47 */ {5, 0.18003133, 0xdab86ef, 0x2ba23582},
+ /* 48 */ {5, 0.17905223, 0xf300000, 0xdb20a88},
+ /* 49 */ {5, 0.17810359, 0x10d63af1, 0xe68d5ce4},
+ /* 50 */ {5, 0.17718382, 0x12a05f20, 0xb7cdfd9d},
+ /* 51 */ {5, 0.17629143, 0x1490aae3, 0x8e583933},
+ /* 52 */ {5, 0.17542506, 0x16a97400, 0x697cc3ea},
+ /* 53 */ {5, 0.17458343, 0x18ed2825, 0x48a5ca6c},
+ /* 54 */ {5, 0.17376534, 0x1b5e4d60, 0x2b52db16},
+ /* 55 */ {5, 0.17296969, 0x1dff8297, 0x111586a6},
+ /* 56 */ {5, 0.17219543, 0x20d38000, 0xf31d2b36},
+ /* 57 */ {5, 0.17144160, 0x23dd1799, 0xc8d76d19},
+ /* 58 */ {5, 0.17070728, 0x271f35a0, 0xa2cb1eb4},
+ /* 59 */ {5, 0.16999162, 0x2a9ce10b, 0x807c3ec3},
+ /* 60 */ {5, 0.16929381, 0x2e593c00, 0x617ec8bf},
+ /* 61 */ {5, 0.16861310, 0x3257844d, 0x45746cbe},
+ /* 62 */ {5, 0.16794878, 0x369b13e0, 0x2c0aa273},
+ /* 63 */ {5, 0.16730018, 0x3b27613f, 0x14f90805},
+ /* 64 */ {5, 0.16666667, 0x6, 0x0},
+ /* 65 */ {5, 0.16604765, 0x4528a141, 0xd9cf0829},
+ /* 66 */ {5, 0.16544255, 0x4aa51420, 0xb6fc4841},
+ /* 67 */ {5, 0.16485086, 0x50794633, 0x973054cb},
+ /* 68 */ {5, 0.16427205, 0x56a94400, 0x7a1dbe4b},
+ /* 69 */ {5, 0.16370566, 0x5d393975, 0x5f7fcd7f},
+ /* 70 */ {5, 0.16315122, 0x642d7260, 0x47196c84},
+ /* 71 */ {5, 0.16260831, 0x6b8a5ae7, 0x30b43635},
+ /* 72 */ {5, 0.16207652, 0x73548000, 0x1c1fa5f6},
+ /* 73 */ {5, 0.16155547, 0x7b908fe9, 0x930634a},
+ /* 74 */ {5, 0.16104477, 0x84435aa0, 0xef7f4a3c},
+ /* 75 */ {5, 0.16054409, 0x8d71d25b, 0xcf5552d2},
+ /* 76 */ {5, 0.16005307, 0x97210c00, 0xb1a47c8e},
+ /* 77 */ {5, 0.15957142, 0xa1563f9d, 0x9634b43e},
+ /* 78 */ {5, 0.15909881, 0xac16c8e0, 0x7cd3817d},
+ /* 79 */ {5, 0.15863496, 0xb768278f, 0x65536761},
+ /* 80 */ {5, 0.15817959, 0xc3500000, 0x4f8b588e},
+ /* 81 */ {5, 0.15773244, 0xcfd41b91, 0x3b563c24},
+ /* 82 */ {5, 0.15729325, 0xdcfa6920, 0x28928154},
+ /* 83 */ {5, 0.15686177, 0xeac8fd83, 0x1721bfb0},
+ /* 84 */ {5, 0.15643779, 0xf9461400, 0x6e8629d},
+ /* 85 */ {4, 0.15602107, 0x31c84b1, 0x491cc17c},
+ /* 86 */ {4, 0.15561139, 0x342ab10, 0x3a11d83b},
+ /* 87 */ {4, 0.15520856, 0x36a2c21, 0x2be074cd},
+ /* 88 */ {4, 0.15481238, 0x3931000, 0x1e7a02e7},
+ /* 89 */ {4, 0.15442266, 0x3bd5ee1, 0x11d10edd},
+ /* 90 */ {4, 0.15403922, 0x3e92110, 0x5d92c68},
+ /* 91 */ {4, 0.15366189, 0x4165ef1, 0xf50dbfb2},
+ /* 92 */ {4, 0.15329049, 0x4452100, 0xdf9f1316},
+ /* 93 */ {4, 0.15292487, 0x4756fd1, 0xcb52a684},
+ /* 94 */ {4, 0.15256487, 0x4a75410, 0xb8163e97},
+ /* 95 */ {4, 0.15221035, 0x4dad681, 0xa5d8f269},
+ /* 96 */ {4, 0.15186115, 0x5100000, 0x948b0fcd},
+ /* 97 */ {4, 0.15151715, 0x546d981, 0x841e0215},
+ /* 98 */ {4, 0.15117821, 0x57f6c10, 0x74843b1e},
+ /* 99 */ {4, 0.15084420, 0x5b9c0d1, 0x65b11e6e},
+ /* 100 */ {4, 0.15051500, 0x5f5e100, 0x5798ee23},
+ /* 101 */ {4, 0.15019048, 0x633d5f1, 0x4a30b99b},
+ /* 102 */ {4, 0.14987054, 0x673a910, 0x3d6e4d94},
+ /* 103 */ {4, 0.14955506, 0x6b563e1, 0x314825b0},
+ /* 104 */ {4, 0.14924394, 0x6f91000, 0x25b55f2e},
+ /* 105 */ {4, 0.14893706, 0x73eb721, 0x1aadaccb},
+ /* 106 */ {4, 0.14863434, 0x7866310, 0x10294ba2},
+ /* 107 */ {4, 0.14833567, 0x7d01db1, 0x620f8f6},
+ /* 108 */ {4, 0.14804096, 0x81bf100, 0xf91bd1b6},
+ /* 109 */ {4, 0.14775011, 0x869e711, 0xe6d37b2a},
+ /* 110 */ {4, 0.14746305, 0x8ba0a10, 0xd55cff6e},
+ /* 111 */ {4, 0.14717969, 0x90c6441, 0xc4ad2db2},
+ /* 112 */ {4, 0.14689994, 0x9610000, 0xb4b985cf},
+ /* 113 */ {4, 0.14662372, 0x9b7e7c1, 0xa5782bef},
+ /* 114 */ {4, 0.14635096, 0xa112610, 0x96dfdd2a},
+ /* 115 */ {4, 0.14608158, 0xa6cc591, 0x88e7e509},
+ /* 116 */ {4, 0.14581551, 0xacad100, 0x7b8813d3},
+ /* 117 */ {4, 0.14555268, 0xb2b5331, 0x6eb8b595},
+ /* 118 */ {4, 0.14529302, 0xb8e5710, 0x627289db},
+ /* 119 */ {4, 0.14503647, 0xbf3e7a1, 0x56aebc07},
+ /* 120 */ {4, 0.14478295, 0xc5c1000, 0x4b66dc33},
+ /* 121 */ {4, 0.14453241, 0xcc6db61, 0x4094d8a3},
+ /* 122 */ {4, 0.14428479, 0xd345510, 0x3632f7a5},
+ /* 123 */ {4, 0.14404003, 0xda48871, 0x2c3bd1f0},
+ /* 124 */ {4, 0.14379807, 0xe178100, 0x22aa4d5f},
+ /* 125 */ {4, 0.14355885, 0xe8d4a51, 0x19799812},
+ /* 126 */ {4, 0.14332233, 0xf05f010, 0x10a523e5},
+ /* 127 */ {4, 0.14308844, 0xf817e01, 0x828a237},
+ /* 128 */ {4, 0.14285714, 0x7, 0x0},
+ /* 129 */ {4, 0.14262838, 0x10818201, 0xf04ec452},
+ /* 130 */ {4, 0.14240211, 0x11061010, 0xe136444a},
+ /* 131 */ {4, 0.14217828, 0x118db651, 0xd2af9589},
+ /* 132 */ {4, 0.14195685, 0x12188100, 0xc4b42a83},
+ /* 133 */ {4, 0.14173777, 0x12a67c71, 0xb73dccf5},
+ /* 134 */ {4, 0.14152100, 0x1337b510, 0xaa4698c5},
+ /* 135 */ {4, 0.14130649, 0x13cc3761, 0x9dc8f729},
+ /* 136 */ {4, 0.14109421, 0x14641000, 0x91bf9a30},
+ /* 137 */ {4, 0.14088412, 0x14ff4ba1, 0x86257887},
+ /* 138 */ {4, 0.14067617, 0x159df710, 0x7af5c98c},
+ /* 139 */ {4, 0.14047033, 0x16401f31, 0x702c01a0},
+ /* 140 */ {4, 0.14026656, 0x16e5d100, 0x65c3ceb1},
+ /* 141 */ {4, 0.14006482, 0x178f1991, 0x5bb91502},
+ /* 142 */ {4, 0.13986509, 0x183c0610, 0x5207ec23},
+ /* 143 */ {4, 0.13966731, 0x18eca3c1, 0x48ac9c19},
+ /* 144 */ {4, 0.13947147, 0x19a10000, 0x3fa39ab5},
+ /* 145 */ {4, 0.13927753, 0x1a592841, 0x36e98912},
+ /* 146 */ {4, 0.13908545, 0x1b152a10, 0x2e7b3140},
+ /* 147 */ {4, 0.13889521, 0x1bd51311, 0x2655840b},
+ /* 148 */ {4, 0.13870677, 0x1c98f100, 0x1e7596ea},
+ /* 149 */ {4, 0.13852011, 0x1d60d1b1, 0x16d8a20d},
+ /* 150 */ {4, 0.13833519, 0x1e2cc310, 0xf7bfe87},
+ /* 151 */ {4, 0.13815199, 0x1efcd321, 0x85d2492},
+ /* 152 */ {4, 0.13797047, 0x1fd11000, 0x179a9f4},
+ /* 153 */ {4, 0.13779062, 0x20a987e1, 0xf59e80eb},
+ /* 154 */ {4, 0.13761241, 0x21864910, 0xe8b768db},
+ /* 155 */ {4, 0.13743580, 0x226761f1, 0xdc39d6d5},
+ /* 156 */ {4, 0.13726078, 0x234ce100, 0xd021c5d1},
+ /* 157 */ {4, 0.13708732, 0x2436d4d1, 0xc46b5e37},
+ /* 158 */ {4, 0.13691539, 0x25254c10, 0xb912f39c},
+ /* 159 */ {4, 0.13674498, 0x26185581, 0xae150294},
+ /* 160 */ {4, 0.13657605, 0x27100000, 0xa36e2eb1},
+ /* 161 */ {4, 0.13640859, 0x280c5a81, 0x991b4094},
+ /* 162 */ {4, 0.13624257, 0x290d7410, 0x8f19241e},
+ /* 163 */ {4, 0.13607797, 0x2a135bd1, 0x8564e6b7},
+ /* 164 */ {4, 0.13591477, 0x2b1e2100, 0x7bfbb5b4},
+ /* 165 */ {4, 0.13575295, 0x2c2dd2f1, 0x72dadcc8},
+ /* 166 */ {4, 0.13559250, 0x2d428110, 0x69ffc498},
+ /* 167 */ {4, 0.13543338, 0x2e5c3ae1, 0x6167f154},
+ /* 168 */ {4, 0.13527558, 0x2f7b1000, 0x5911016e},
+ /* 169 */ {4, 0.13511908, 0x309f1021, 0x50f8ac5f},
+ /* 170 */ {4, 0.13496386, 0x31c84b10, 0x491cc17c},
+ /* 171 */ {4, 0.13480991, 0x32f6d0b1, 0x417b26d8},
+ /* 172 */ {4, 0.13465720, 0x342ab100, 0x3a11d83b},
+ /* 173 */ {4, 0.13450572, 0x3563fc11, 0x32dee622},
+ /* 174 */ {4, 0.13435545, 0x36a2c210, 0x2be074cd},
+ /* 175 */ {4, 0.13420637, 0x37e71341, 0x2514bb58},
+ /* 176 */ {4, 0.13405847, 0x39310000, 0x1e7a02e7},
+ /* 177 */ {4, 0.13391173, 0x3a8098c1, 0x180ea5d0},
+ /* 178 */ {4, 0.13376614, 0x3bd5ee10, 0x11d10edd},
+ /* 179 */ {4, 0.13362168, 0x3d311091, 0xbbfb88e},
+ /* 180 */ {4, 0.13347832, 0x3e921100, 0x5d92c68},
+ /* 181 */ {4, 0.13333607, 0x3ff90031, 0x1c024c},
+ /* 182 */ {4, 0.13319491, 0x4165ef10, 0xf50dbfb2},
+ /* 183 */ {4, 0.13305481, 0x42d8eea1, 0xea30efa3},
+ /* 184 */ {4, 0.13291577, 0x44521000, 0xdf9f1316},
+ /* 185 */ {4, 0.13277777, 0x45d16461, 0xd555c0c9},
+ /* 186 */ {4, 0.13264079, 0x4756fd10, 0xcb52a684},
+ /* 187 */ {4, 0.13250483, 0x48e2eb71, 0xc193881f},
+ /* 188 */ {4, 0.13236988, 0x4a754100, 0xb8163e97},
+ /* 189 */ {4, 0.13223591, 0x4c0e0f51, 0xaed8b724},
+ /* 190 */ {4, 0.13210292, 0x4dad6810, 0xa5d8f269},
+ /* 191 */ {4, 0.13197089, 0x4f535d01, 0x9d15039d},
+ /* 192 */ {4, 0.13183981, 0x51000000, 0x948b0fcd},
+ /* 193 */ {4, 0.13170967, 0x52b36301, 0x8c394d1d},
+ /* 194 */ {4, 0.13158046, 0x546d9810, 0x841e0215},
+ /* 195 */ {4, 0.13145216, 0x562eb151, 0x7c3784f8},
+ /* 196 */ {4, 0.13132477, 0x57f6c100, 0x74843b1e},
+ /* 197 */ {4, 0.13119827, 0x59c5d971, 0x6d02985d},
+ /* 198 */ {4, 0.13107265, 0x5b9c0d10, 0x65b11e6e},
+ /* 199 */ {4, 0.13094791, 0x5d796e61, 0x5e8e5c64},
+ /* 200 */ {4, 0.13082402, 0x5f5e1000, 0x5798ee23},
+ /* 201 */ {4, 0.13070099, 0x614a04a1, 0x50cf7bde},
+ /* 202 */ {4, 0.13057879, 0x633d5f10, 0x4a30b99b},
+ /* 203 */ {4, 0.13045743, 0x65383231, 0x43bb66bd},
+ /* 204 */ {4, 0.13033688, 0x673a9100, 0x3d6e4d94},
+ /* 205 */ {4, 0.13021715, 0x69448e91, 0x374842ee},
+ /* 206 */ {4, 0.13009822, 0x6b563e10, 0x314825b0},
+ /* 207 */ {4, 0.12998007, 0x6d6fb2c1, 0x2b6cde75},
+ /* 208 */ {4, 0.12986271, 0x6f910000, 0x25b55f2e},
+ /* 209 */ {4, 0.12974613, 0x71ba3941, 0x2020a2c5},
+ /* 210 */ {4, 0.12963031, 0x73eb7210, 0x1aadaccb},
+ /* 211 */ {4, 0.12951524, 0x7624be11, 0x155b891f},
+ /* 212 */ {4, 0.12940092, 0x78663100, 0x10294ba2},
+ /* 213 */ {4, 0.12928734, 0x7aafdeb1, 0xb160fe9},
+ /* 214 */ {4, 0.12917448, 0x7d01db10, 0x620f8f6},
+ /* 215 */ {4, 0.12906235, 0x7f5c3a21, 0x14930ef},
+ /* 216 */ {4, 0.12895094, 0x81bf1000, 0xf91bd1b6},
+ /* 217 */ {4, 0.12884022, 0x842a70e1, 0xefdcb0c7},
+ /* 218 */ {4, 0.12873021, 0x869e7110, 0xe6d37b2a},
+ /* 219 */ {4, 0.12862089, 0x891b24f1, 0xddfeb94a},
+ /* 220 */ {4, 0.12851224, 0x8ba0a100, 0xd55cff6e},
+ /* 221 */ {4, 0.12840428, 0x8e2ef9d1, 0xcceced50},
+ /* 222 */ {4, 0.12829698, 0x90c64410, 0xc4ad2db2},
+ /* 223 */ {4, 0.12819034, 0x93669481, 0xbc9c75f9},
+ /* 224 */ {4, 0.12808435, 0x96100000, 0xb4b985cf},
+ /* 225 */ {4, 0.12797901, 0x98c29b81, 0xad0326c2},
+ /* 226 */ {4, 0.12787431, 0x9b7e7c10, 0xa5782bef},
+ /* 227 */ {4, 0.12777024, 0x9e43b6d1, 0x9e1771a9},
+ /* 228 */ {4, 0.12766680, 0xa1126100, 0x96dfdd2a},
+ /* 229 */ {4, 0.12756398, 0xa3ea8ff1, 0x8fd05c41},
+ /* 230 */ {4, 0.12746176, 0xa6cc5910, 0x88e7e509},
+ /* 231 */ {4, 0.12736016, 0xa9b7d1e1, 0x8225759d},
+ /* 232 */ {4, 0.12725915, 0xacad1000, 0x7b8813d3},
+ /* 233 */ {4, 0.12715874, 0xafac2921, 0x750eccf9},
+ /* 234 */ {4, 0.12705891, 0xb2b53310, 0x6eb8b595},
+ /* 235 */ {4, 0.12695967, 0xb5c843b1, 0x6884e923},
+ /* 236 */ {4, 0.12686100, 0xb8e57100, 0x627289db},
+ /* 237 */ {4, 0.12676290, 0xbc0cd111, 0x5c80c07b},
+ /* 238 */ {4, 0.12666537, 0xbf3e7a10, 0x56aebc07},
+ /* 239 */ {4, 0.12656839, 0xc27a8241, 0x50fbb19b},
+ /* 240 */ {4, 0.12647197, 0xc5c10000, 0x4b66dc33},
+ /* 241 */ {4, 0.12637609, 0xc91209c1, 0x45ef7c7c},
+ /* 242 */ {4, 0.12628075, 0xcc6db610, 0x4094d8a3},
+ /* 243 */ {4, 0.12618595, 0xcfd41b91, 0x3b563c24},
+ /* 244 */ {4, 0.12609168, 0xd3455100, 0x3632f7a5},
+ /* 245 */ {4, 0.12599794, 0xd6c16d31, 0x312a60c3},
+ /* 246 */ {4, 0.12590471, 0xda488710, 0x2c3bd1f0},
+ /* 247 */ {4, 0.12581200, 0xdddab5a1, 0x2766aa45},
+ /* 248 */ {4, 0.12571980, 0xe1781000, 0x22aa4d5f},
+ /* 249 */ {4, 0.12562811, 0xe520ad61, 0x1e06233c},
+ /* 250 */ {4, 0.12553692, 0xe8d4a510, 0x19799812},
+ /* 251 */ {4, 0.12544622, 0xec940e71, 0x15041c33},
+ /* 252 */ {4, 0.12535601, 0xf05f0100, 0x10a523e5},
+ /* 253 */ {4, 0.12526629, 0xf4359451, 0xc5c2749},
+ /* 254 */ {4, 0.12517705, 0xf817e010, 0x828a237},
+ /* 255 */ {4, 0.12508829, 0xfc05fc01, 0x40a1423},
+};
+#endif
+#if BITS_PER_MP_LIMB == 64
+const struct bases __mp_bases[256] =
+{
+ /* 0 */ {0, 0.0, 0, 0},
+ /* 1 */ {0, 1e38, 0, 0},
+ /* 2 */ {64, 1.00000000, 0x1, 0x0},
+ /* 3 */ {40, 0.63092975, 0xa8b8b452291fe821L, 0x846d550e37b5063dL},
+ /* 4 */ {32, 0.50000000, 0x2L, 0x0L},
+ /* 5 */ {27, 0.43067656, 0x6765c793fa10079dL, 0x3ce9a36f23c0fc90L},
+ /* 6 */ {24, 0.38685281, 0x41c21cb8e1000000L, 0xf24f62335024a295L},
+ /* 7 */ {22, 0.35620719, 0x3642798750226111L, 0x2df495ccaa57147bL},
+ /* 8 */ {21, 0.33333333, 0x3L, 0x0L},
+ /* 9 */ {20, 0.31546488, 0xa8b8b452291fe821L, 0x846d550e37b5063dL},
+ /* 10 */ {19, 0.30103000, 0x8ac7230489e80000L, 0xd83c94fb6d2ac34aL},
+ /* 11 */ {18, 0.28906483, 0x4d28cb56c33fa539L, 0xa8adf7ae45e7577bL},
+ /* 12 */ {17, 0.27894295, 0x1eca170c00000000L, 0xa10c2bec5da8f8fL},
+ /* 13 */ {17, 0.27023815, 0x780c7372621bd74dL, 0x10f4becafe412ec3L},
+ /* 14 */ {16, 0.26264954, 0x1e39a5057d810000L, 0xf08480f672b4e86L},
+ /* 15 */ {16, 0.25595802, 0x5b27ac993df97701L, 0x6779c7f90dc42f48L},
+ /* 16 */ {16, 0.25000000, 0x4L, 0x0L},
+ /* 17 */ {15, 0.24465054, 0x27b95e997e21d9f1L, 0x9c71e11bab279323L},
+ /* 18 */ {15, 0.23981247, 0x5da0e1e53c5c8000L, 0x5dfaa697ec6f6a1cL},
+ /* 19 */ {15, 0.23540891, 0xd2ae3299c1c4aedbL, 0x3711783f6be7e9ecL},
+ /* 20 */ {14, 0.23137821, 0x16bcc41e90000000L, 0x6849b86a12b9b01eL},
+ /* 21 */ {14, 0.22767025, 0x2d04b7fdd9c0ef49L, 0x6bf097ba5ca5e239L},
+ /* 22 */ {14, 0.22424382, 0x5658597bcaa24000L, 0x7b8015c8d7af8f08L},
+ /* 23 */ {14, 0.22106473, 0xa0e2073737609371L, 0x975a24b3a3151b38L},
+ /* 24 */ {13, 0.21810429, 0xc29e98000000000L, 0x50bd367972689db1L},
+ /* 25 */ {13, 0.21533828, 0x14adf4b7320334b9L, 0x8c240c4aecb13bb5L},
+ /* 26 */ {13, 0.21274605, 0x226ed36478bfa000L, 0xdbd2e56854e118c9L},
+ /* 27 */ {13, 0.21030992, 0x383d9170b85ff80bL, 0x2351ffcaa9c7c4aeL},
+ /* 28 */ {13, 0.20801460, 0x5a3c23e39c000000L, 0x6b24188ca33b0636L},
+ /* 29 */ {13, 0.20584683, 0x8e65137388122bcdL, 0xcc3dceaf2b8ba99dL},
+ /* 30 */ {13, 0.20379505, 0xdd41bb36d259e000L, 0x2832e835c6c7d6b6L},
+ /* 31 */ {12, 0.20184909, 0xaee5720ee830681L, 0x76b6aa272e1873c5L},
+ /* 32 */ {12, 0.20000000, 0x5L, 0x0L},
+ /* 33 */ {12, 0.19823986, 0x172588ad4f5f0981L, 0x61eaf5d402c7bf4fL},
+ /* 34 */ {12, 0.19656163, 0x211e44f7d02c1000L, 0xeeb658123ffb27ecL},
+ /* 35 */ {12, 0.19495902, 0x2ee56725f06e5c71L, 0x5d5e3762e6fdf509L},
+ /* 36 */ {12, 0.19342640, 0x41c21cb8e1000000L, 0xf24f62335024a295L},
+ /* 37 */ {12, 0.19195872, 0x5b5b57f8a98a5dd1L, 0x66ae7831762efb6fL},
+ /* 38 */ {12, 0.19055141, 0x7dcff8986ea31000L, 0x47388865a00f544L},
+ /* 39 */ {12, 0.18920036, 0xabd4211662a6b2a1L, 0x7d673c33a123b54cL},
+ /* 40 */ {12, 0.18790182, 0xe8d4a51000000000L, 0x19799812dea11197L},
+ /* 41 */ {11, 0.18665241, 0x7a32956ad081b79L, 0xc27e62e0686feaeL},
+ /* 42 */ {11, 0.18544902, 0x9f49aaff0e86800L, 0x9b6e7507064ce7c7L},
+ /* 43 */ {11, 0.18428883, 0xce583bb812d37b3L, 0x3d9ac2bf66cfed94L},
+ /* 44 */ {11, 0.18316925, 0x109b79a654c00000L, 0xed46bc50ce59712aL},
+ /* 45 */ {11, 0.18208790, 0x1543beff214c8b95L, 0x813d97e2c89b8d46L},
+ /* 46 */ {11, 0.18104260, 0x1b149a79459a3800L, 0x2e81751956af8083L},
+ /* 47 */ {11, 0.18003133, 0x224edfb5434a830fL, 0xdd8e0a95e30c0988L},
+ /* 48 */ {11, 0.17905223, 0x2b3fb00000000000L, 0x7ad4dd48a0b5b167L},
+ /* 49 */ {11, 0.17810359, 0x3642798750226111L, 0x2df495ccaa57147bL},
+ /* 50 */ {11, 0.17718382, 0x43c33c1937564800L, 0xe392010175ee5962L},
+ /* 51 */ {11, 0.17629143, 0x54411b2441c3cd8bL, 0x84eaf11b2fe7738eL},
+ /* 52 */ {11, 0.17542506, 0x6851455acd400000L, 0x3a1e3971e008995dL},
+ /* 53 */ {11, 0.17458343, 0x80a23b117c8feb6dL, 0xfd7a462344ffce25L},
+ /* 54 */ {11, 0.17376534, 0x9dff7d32d5dc1800L, 0x9eca40b40ebcef8aL},
+ /* 55 */ {11, 0.17296969, 0xc155af6faeffe6a7L, 0x52fa161a4a48e43dL},
+ /* 56 */ {11, 0.17219543, 0xebb7392e00000000L, 0x1607a2cbacf930c1L},
+ /* 57 */ {10, 0.17144160, 0x50633659656d971L, 0x97a014f8e3be55f1L},
+ /* 58 */ {10, 0.17070728, 0x5fa8624c7fba400L, 0x568df8b76cbf212cL},
+ /* 59 */ {10, 0.16999162, 0x717d9faa73c5679L, 0x20ba7c4b4e6ef492L},
+ /* 60 */ {10, 0.16929381, 0x86430aac6100000L, 0xe81ee46b9ef492f5L},
+ /* 61 */ {10, 0.16861310, 0x9e64d9944b57f29L, 0x9dc0d10d51940416L},
+ /* 62 */ {10, 0.16794878, 0xba5ca5392cb0400L, 0x5fa8ed2f450272a5L},
+ /* 63 */ {10, 0.16730018, 0xdab2ce1d022cd81L, 0x2ba9eb8c5e04e641L},
+ /* 64 */ {10, 0.16666667, 0x6L, 0x0L},
+ /* 65 */ {10, 0.16604765, 0x12aeed5fd3e2d281L, 0xb67759cc00287bf1L},
+ /* 66 */ {10, 0.16544255, 0x15c3da1572d50400L, 0x78621feeb7f4ed33L},
+ /* 67 */ {10, 0.16485086, 0x194c05534f75ee29L, 0x43d55b5f72943bc0L},
+ /* 68 */ {10, 0.16427205, 0x1d56299ada100000L, 0x173decb64d1d4409L},
+ /* 69 */ {10, 0.16370566, 0x21f2a089a4ff4f79L, 0xe29fb54fd6b6074fL},
+ /* 70 */ {10, 0.16315122, 0x2733896c68d9a400L, 0xa1f1f5c210d54e62L},
+ /* 71 */ {10, 0.16260831, 0x2d2cf2c33b533c71L, 0x6aac7f9bfafd57b2L},
+ /* 72 */ {10, 0.16207652, 0x33f506e440000000L, 0x3b563c2478b72ee2L},
+ /* 73 */ {10, 0.16155547, 0x3ba43bec1d062211L, 0x12b536b574e92d1bL},
+ /* 74 */ {10, 0.16104477, 0x4455872d8fd4e400L, 0xdf86c03020404fa5L},
+ /* 75 */ {10, 0.16054409, 0x4e2694539f2f6c59L, 0xa34adf02234eea8eL},
+ /* 76 */ {10, 0.16005307, 0x5938006c18900000L, 0x6f46eb8574eb59ddL},
+ /* 77 */ {10, 0.15957142, 0x65ad9912474aa649L, 0x42459b481df47cecL},
+ /* 78 */ {10, 0.15909881, 0x73ae9ff4241ec400L, 0x1b424b95d80ca505L},
+ /* 79 */ {10, 0.15863496, 0x836612ee9c4ce1e1L, 0xf2c1b982203a0dacL},
+ /* 80 */ {10, 0.15817959, 0x9502f90000000000L, 0xb7cdfd9d7bdbab7dL},
+ /* 81 */ {10, 0.15773244, 0xa8b8b452291fe821L, 0x846d550e37b5063dL},
+ /* 82 */ {10, 0.15729325, 0xbebf59a07dab4400L, 0x57931eeaf85cf64fL},
+ /* 83 */ {10, 0.15686177, 0xd7540d4093bc3109L, 0x305a944507c82f47L},
+ /* 84 */ {10, 0.15643779, 0xf2b96616f1900000L, 0xe007ccc9c22781aL},
+ /* 85 */ {9, 0.15602107, 0x336de62af2bca35L, 0x3e92c42e000eeed4L},
+ /* 86 */ {9, 0.15561139, 0x39235ec33d49600L, 0x1ebe59130db2795eL},
+ /* 87 */ {9, 0.15520856, 0x3f674e539585a17L, 0x268859e90f51b89L},
+ /* 88 */ {9, 0.15481238, 0x4645b6958000000L, 0xd24cde0463108cfaL},
+ /* 89 */ {9, 0.15442266, 0x4dcb74afbc49c19L, 0xa536009f37adc383L},
+ /* 90 */ {9, 0.15403922, 0x56064e1d18d9a00L, 0x7cea06ce1c9ace10L},
+ /* 91 */ {9, 0.15366189, 0x5f04fe2cd8a39fbL, 0x58db032e72e8ba43L},
+ /* 92 */ {9, 0.15329049, 0x68d74421f5c0000L, 0x388cc17cae105447L},
+ /* 93 */ {9, 0.15292487, 0x738df1f6ab4827dL, 0x1b92672857620ce0L},
+ /* 94 */ {9, 0.15256487, 0x7f3afbc9cfb5e00L, 0x18c6a9575c2ade4L},
+ /* 95 */ {9, 0.15221035, 0x8bf187fba88f35fL, 0xd44da7da8e44b24fL},
+ /* 96 */ {9, 0.15186115, 0x99c600000000000L, 0xaa2f78f1b4cc6794L},
+ /* 97 */ {9, 0.15151715, 0xa8ce21eb6531361L, 0x843c067d091ee4ccL},
+ /* 98 */ {9, 0.15117821, 0xb92112c1a0b6200L, 0x62005e1e913356e3L},
+ /* 99 */ {9, 0.15084420, 0xcad7718b8747c43L, 0x4316eed01dedd518L},
+ /* 100 */ {9, 0.15051500, 0xde0b6b3a7640000L, 0x2725dd1d243aba0eL},
+ /* 101 */ {9, 0.15019048, 0xf2d8cf5fe6d74c5L, 0xddd9057c24cb54fL},
+ /* 102 */ {9, 0.14987054, 0x1095d25bfa712600L, 0xedeee175a736d2a1L},
+ /* 103 */ {9, 0.14955506, 0x121b7c4c3698faa7L, 0xc4699f3df8b6b328L},
+ /* 104 */ {9, 0.14924394, 0x13c09e8d68000000L, 0x9ebbe7d859cb5a7cL},
+ /* 105 */ {9, 0.14893706, 0x15876ccb0b709ca9L, 0x7c828b9887eb2179L},
+ /* 106 */ {9, 0.14863434, 0x17723c2976da2a00L, 0x5d652ab99001adcfL},
+ /* 107 */ {9, 0.14833567, 0x198384e9c259048bL, 0x4114f1754e5d7b32L},
+ /* 108 */ {9, 0.14804096, 0x1bbde41dfeec0000L, 0x274b7c902f7e0188L},
+ /* 109 */ {9, 0.14775011, 0x1e241d6e3337910dL, 0xfc9e0fbb32e210cL},
+ /* 110 */ {9, 0.14746305, 0x20b91cee9901ee00L, 0xf4afa3e594f8ea1fL},
+ /* 111 */ {9, 0.14717969, 0x237ff9079863dfefL, 0xcd85c32e9e4437b0L},
+ /* 112 */ {9, 0.14689994, 0x267bf47000000000L, 0xa9bbb147e0dd92a8L},
+ /* 113 */ {9, 0.14662372, 0x29b08039fbeda7f1L, 0x8900447b70e8eb82L},
+ /* 114 */ {9, 0.14635096, 0x2d213df34f65f200L, 0x6b0a92adaad5848aL},
+ /* 115 */ {9, 0.14608158, 0x30d201d957a7c2d3L, 0x4f990ad8740f0ee5L},
+ /* 116 */ {9, 0.14581551, 0x34c6d52160f40000L, 0x3670a9663a8d3610L},
+ /* 117 */ {9, 0.14555268, 0x3903f855d8f4c755L, 0x1f5c44188057be3cL},
+ /* 118 */ {9, 0.14529302, 0x3d8de5c8ec59b600L, 0xa2bea956c4e4977L},
+ /* 119 */ {9, 0.14503647, 0x4269541d1ff01337L, 0xed68b23033c3637eL},
+ /* 120 */ {9, 0.14478295, 0x479b38e478000000L, 0xc99cf624e50549c5L},
+ /* 121 */ {9, 0.14453241, 0x4d28cb56c33fa539L, 0xa8adf7ae45e7577bL},
+ /* 122 */ {9, 0.14428479, 0x5317871fa13aba00L, 0x8a5bc740b1c113e5L},
+ /* 123 */ {9, 0.14404003, 0x596d2f44de9fa71bL, 0x6e6c7efb81cfbb9bL},
+ /* 124 */ {9, 0.14379807, 0x602fd125c47c0000L, 0x54aba5c5cada5f10L},
+ /* 125 */ {9, 0.14355885, 0x6765c793fa10079dL, 0x3ce9a36f23c0fc90L},
+ /* 126 */ {9, 0.14332233, 0x6f15be069b847e00L, 0x26fb43de2c8cd2a8L},
+ /* 127 */ {9, 0.14308844, 0x7746b3e82a77047fL, 0x12b94793db8486a1L},
+ /* 128 */ {9, 0.14285714, 0x7L, 0x0L},
+ /* 129 */ {9, 0.14262838, 0x894953f7ea890481L, 0xdd5deca404c0156dL},
+ /* 130 */ {9, 0.14240211, 0x932abffea4848200L, 0xbd51373330291de0L},
+ /* 131 */ {9, 0.14217828, 0x9dacb687d3d6a163L, 0x9fa4025d66f23085L},
+ /* 132 */ {9, 0.14195685, 0xa8d8102a44840000L, 0x842530ee2db4949dL},
+ /* 133 */ {9, 0.14173777, 0xb4b60f9d140541e5L, 0x6aa7f2766b03dc25L},
+ /* 134 */ {9, 0.14152100, 0xc15065d4856e4600L, 0x53035ba7ebf32e8dL},
+ /* 135 */ {9, 0.14130649, 0xceb1363f396d23c7L, 0x3d12091fc9fb4914L},
+ /* 136 */ {9, 0.14109421, 0xdce31b2488000000L, 0x28b1cb81b1ef1849L},
+ /* 137 */ {9, 0.14088412, 0xebf12a24bca135c9L, 0x15c35be67ae3e2c9L},
+ /* 138 */ {9, 0.14067617, 0xfbe6f8dbf88f4a00L, 0x42a17bd09be1ff0L},
+ /* 139 */ {8, 0.14047033, 0x1ef156c084ce761L, 0x8bf461f03cf0bbfL},
+ /* 140 */ {8, 0.14026656, 0x20c4e3b94a10000L, 0xf3fbb43f68a32d05L},
+ /* 141 */ {8, 0.14006482, 0x22b0695a08ba421L, 0xd84f44c48564dc19L},
+ /* 142 */ {8, 0.13986509, 0x24b4f35d7a4c100L, 0xbe58ebcce7956abeL},
+ /* 143 */ {8, 0.13966731, 0x26d397284975781L, 0xa5fac463c7c134b7L},
+ /* 144 */ {8, 0.13947147, 0x290d74100000000L, 0x8f19241e28c7d757L},
+ /* 145 */ {8, 0.13927753, 0x2b63b3a37866081L, 0x799a6d046c0ae1aeL},
+ /* 146 */ {8, 0.13908545, 0x2dd789f4d894100L, 0x6566e37d746a9e40L},
+ /* 147 */ {8, 0.13889521, 0x306a35e51b58721L, 0x526887dbfb5f788fL},
+ /* 148 */ {8, 0.13870677, 0x331d01712e10000L, 0x408af3382b8efd3dL},
+ /* 149 */ {8, 0.13852011, 0x35f14200a827c61L, 0x2fbb374806ec05f1L},
+ /* 150 */ {8, 0.13833519, 0x38e858b62216100L, 0x1fe7c0f0afce87feL},
+ /* 151 */ {8, 0.13815199, 0x3c03b2c13176a41L, 0x11003d517540d32eL},
+ /* 152 */ {8, 0.13797047, 0x3f44c9b21000000L, 0x2f5810f98eff0dcL},
+ /* 153 */ {8, 0.13779062, 0x42ad23cef3113c1L, 0xeb72e35e7840d910L},
+ /* 154 */ {8, 0.13761241, 0x463e546b19a2100L, 0xd27de19593dc3614L},
+ /* 155 */ {8, 0.13743580, 0x49f9fc3f96684e1L, 0xbaf391fd3e5e6fc2L},
+ /* 156 */ {8, 0.13726078, 0x4de1c9c5dc10000L, 0xa4bd38c55228c81dL},
+ /* 157 */ {8, 0.13708732, 0x51f77994116d2a1L, 0x8fc5a8de8e1de782L},
+ /* 158 */ {8, 0.13691539, 0x563cd6bb3398100L, 0x7bf9265bea9d3a3bL},
+ /* 159 */ {8, 0.13674498, 0x5ab3bb270beeb01L, 0x69454b325983dccdL},
+ /* 160 */ {8, 0.13657605, 0x5f5e10000000000L, 0x5798ee2308c39df9L},
+ /* 161 */ {8, 0.13640859, 0x643dce0ec16f501L, 0x46e40ba0fa66a753L},
+ /* 162 */ {8, 0.13624257, 0x6954fe21e3e8100L, 0x3717b0870b0db3a7L},
+ /* 163 */ {8, 0.13607797, 0x6ea5b9755f440a1L, 0x2825e6775d11cdebL},
+ /* 164 */ {8, 0.13591477, 0x74322a1c0410000L, 0x1a01a1c09d1b4dacL},
+ /* 165 */ {8, 0.13575295, 0x79fc8b6ae8a46e1L, 0xc9eb0a8bebc8f3eL},
+ /* 166 */ {8, 0.13559250, 0x80072a66d512100L, 0xffe357ff59e6a004L},
+ /* 167 */ {8, 0.13543338, 0x86546633b42b9c1L, 0xe7dfd1be05fa61a8L},
+ /* 168 */ {8, 0.13527558, 0x8ce6b0861000000L, 0xd11ed6fc78f760e5L},
+ /* 169 */ {8, 0.13511908, 0x93c08e16a022441L, 0xbb8db609dd29ebfeL},
+ /* 170 */ {8, 0.13496386, 0x9ae49717f026100L, 0xa71aec8d1813d532L},
+ /* 171 */ {8, 0.13480991, 0xa25577ae24c1a61L, 0x93b612a9f20fbc02L},
+ /* 172 */ {8, 0.13465720, 0xaa15f068e610000L, 0x814fc7b19a67d317L},
+ /* 173 */ {8, 0.13450572, 0xb228d6bf7577921L, 0x6fd9a03f2e0a4b7cL},
+ /* 174 */ {8, 0.13435545, 0xba91158ef5c4100L, 0x5f4615a38d0d316eL},
+ /* 175 */ {8, 0.13420637, 0xc351ad9aec0b681L, 0x4f8876863479a286L},
+ /* 176 */ {8, 0.13405847, 0xcc6db6100000000L, 0x4094d8a3041b60ebL},
+ /* 177 */ {8, 0.13391173, 0xd5e85d09025c181L, 0x32600b8ed883a09bL},
+ /* 178 */ {8, 0.13376614, 0xdfc4e816401c100L, 0x24df8c6eb4b6d1f1L},
+ /* 179 */ {8, 0.13362168, 0xea06b4c72947221L, 0x18097a8ee151acefL},
+ /* 180 */ {8, 0.13347832, 0xf4b139365210000L, 0xbd48cc8ec1cd8e3L},
+ /* 181 */ {8, 0.13333607, 0xffc80497d520961L, 0x3807a8d67485fbL},
+ /* 182 */ {8, 0.13319491, 0x10b4ebfca1dee100L, 0xea5768860b62e8d8L},
+ /* 183 */ {8, 0.13305481, 0x117492de921fc141L, 0xd54faf5b635c5005L},
+ /* 184 */ {8, 0.13291577, 0x123bb2ce41000000L, 0xc14a56233a377926L},
+ /* 185 */ {8, 0.13277777, 0x130a8b6157bdecc1L, 0xae39a88db7cd329fL},
+ /* 186 */ {8, 0.13264079, 0x13e15dede0e8a100L, 0x9c10bde69efa7ab6L},
+ /* 187 */ {8, 0.13250483, 0x14c06d941c0ca7e1L, 0x8ac36c42a2836497L},
+ /* 188 */ {8, 0.13236988, 0x15a7ff487a810000L, 0x7a463c8b84f5ef67L},
+ /* 189 */ {8, 0.13223591, 0x169859ddc5c697a1L, 0x6a8e5f5ad090fd4bL},
+ /* 190 */ {8, 0.13210292, 0x1791c60f6fed0100L, 0x5b91a2943596fc56L},
+ /* 191 */ {8, 0.13197089, 0x18948e8c0e6fba01L, 0x4d4667b1c468e8f0L},
+ /* 192 */ {8, 0.13183981, 0x19a1000000000000L, 0x3fa39ab547994dafL},
+ /* 193 */ {8, 0.13170967, 0x1ab769203dafc601L, 0x32a0a9b2faee1e2aL},
+ /* 194 */ {8, 0.13158046, 0x1bd81ab557f30100L, 0x26357ceac0e96962L},
+ /* 195 */ {8, 0.13145216, 0x1d0367a69fed1ba1L, 0x1a5a6f65caa5859eL},
+ /* 196 */ {8, 0.13132477, 0x1e39a5057d810000L, 0xf08480f672b4e86L},
+ /* 197 */ {8, 0.13119827, 0x1f7b2a18f29ac3e1L, 0x4383340615612caL},
+ /* 198 */ {8, 0.13107265, 0x20c850694c2aa100L, 0xf3c77969ee4be5a2L},
+ /* 199 */ {8, 0.13094791, 0x222173cc014980c1L, 0xe00993cc187c5ec9L},
+ /* 200 */ {8, 0.13082402, 0x2386f26fc1000000L, 0xcd2b297d889bc2b6L},
+ /* 201 */ {8, 0.13070099, 0x24f92ce8af296d41L, 0xbb214d5064862b22L},
+ /* 202 */ {8, 0.13057879, 0x2678863cd0ece100L, 0xa9e1a7ca7ea10e20L},
+ /* 203 */ {8, 0.13045743, 0x280563f0a9472d61L, 0x99626e72b39ea0cfL},
+ /* 204 */ {8, 0.13033688, 0x29a02e1406210000L, 0x899a5ba9c13fafd9L},
+ /* 205 */ {8, 0.13021715, 0x2b494f4efe6d2e21L, 0x7a80a705391e96ffL},
+ /* 206 */ {8, 0.13009822, 0x2d0134ef21cbc100L, 0x6c0cfe23de23042aL},
+ /* 207 */ {8, 0.12998007, 0x2ec84ef4da2ef581L, 0x5e377df359c944ddL},
+ /* 208 */ {8, 0.12986271, 0x309f102100000000L, 0x50f8ac5fc8f53985L},
+ /* 209 */ {8, 0.12974613, 0x3285ee02a1420281L, 0x44497266278e35b7L},
+ /* 210 */ {8, 0.12963031, 0x347d6104fc324100L, 0x382316831f7ee175L},
+ /* 211 */ {8, 0.12951524, 0x3685e47dade53d21L, 0x2c7f377833b8946eL},
+ /* 212 */ {8, 0.12940092, 0x389ff6bb15610000L, 0x2157c761ab4163efL},
+ /* 213 */ {8, 0.12928734, 0x3acc1912ebb57661L, 0x16a7071803cc49a9L},
+ /* 214 */ {8, 0.12917448, 0x3d0acff111946100L, 0xc6781d80f8224fcL},
+ /* 215 */ {8, 0.12906235, 0x3f5ca2e692eaf841L, 0x294092d370a900bL},
+ /* 216 */ {8, 0.12895094, 0x41c21cb8e1000000L, 0xf24f62335024a295L},
+ /* 217 */ {8, 0.12884022, 0x443bcb714399a5c1L, 0xe03b98f103fad6d2L},
+ /* 218 */ {8, 0.12873021, 0x46ca406c81af2100L, 0xcee3d32cad2a9049L},
+ /* 219 */ {8, 0.12862089, 0x496e106ac22aaae1L, 0xbe3f9df9277fdadaL},
+ /* 220 */ {8, 0.12851224, 0x4c27d39fa5410000L, 0xae46f0d94c05e933L},
+ /* 221 */ {8, 0.12840428, 0x4ef825c296e43ca1L, 0x9ef2280fb437a33dL},
+ /* 222 */ {8, 0.12829698, 0x51dfa61f5ad88100L, 0x9039ff426d3f284bL},
+ /* 223 */ {8, 0.12819034, 0x54def7a6d2f16901L, 0x82178c6d6b51f8f4L},
+ /* 224 */ {8, 0.12808435, 0x57f6c10000000000L, 0x74843b1ee4c1e053L},
+ /* 225 */ {8, 0.12797901, 0x5b27ac993df97701L, 0x6779c7f90dc42f48L},
+ /* 226 */ {8, 0.12787431, 0x5e7268b9bbdf8100L, 0x5af23c74f9ad9fe9L},
+ /* 227 */ {8, 0.12777024, 0x61d7a7932ff3d6a1L, 0x4ee7eae2acdc617eL},
+ /* 228 */ {8, 0.12766680, 0x65581f53c8c10000L, 0x43556aa2ac262a0bL},
+ /* 229 */ {8, 0.12756398, 0x68f48a385b8320e1L, 0x3835949593b8ddd1L},
+ /* 230 */ {8, 0.12746176, 0x6cada69ed07c2100L, 0x2d837fbe78458762L},
+ /* 231 */ {8, 0.12736016, 0x70843718cdbf27c1L, 0x233a7e150a54a555L},
+ /* 232 */ {8, 0.12725915, 0x7479027ea1000000L, 0x19561984a50ff8feL},
+ /* 233 */ {8, 0.12715874, 0x788cd40268f39641L, 0xfd211159fe3490fL},
+ /* 234 */ {8, 0.12705891, 0x7cc07b437ecf6100L, 0x6aa563e655033e3L},
+ /* 235 */ {8, 0.12695967, 0x8114cc6220762061L, 0xfbb614b3f2d3b14cL},
+ /* 236 */ {8, 0.12686100, 0x858aa0135be10000L, 0xeac0f8837fb05773L},
+ /* 237 */ {8, 0.12676290, 0x8a22d3b53c54c321L, 0xda6e4c10e8615ca5L},
+ /* 238 */ {8, 0.12666537, 0x8ede496339f34100L, 0xcab755a8d01fa67fL},
+ /* 239 */ {8, 0.12656839, 0x93bde80aec3a1481L, 0xbb95a9ae71aa3e0cL},
+ /* 240 */ {8, 0.12647197, 0x98c29b8100000000L, 0xad0326c296b4f529L},
+ /* 241 */ {8, 0.12637609, 0x9ded549671832381L, 0x9ef9f21eed31b7c1L},
+ /* 242 */ {8, 0.12628075, 0xa33f092e0b1ac100L, 0x91747422be14b0b2L},
+ /* 243 */ {8, 0.12618595, 0xa8b8b452291fe821L, 0x846d550e37b5063dL},
+ /* 244 */ {8, 0.12609168, 0xae5b564ac3a10000L, 0x77df79e9a96c06f6L},
+ /* 245 */ {8, 0.12599794, 0xb427f4b3be74c361L, 0x6bc6019636c7d0c2L},
+ /* 246 */ {8, 0.12590471, 0xba1f9a938041e100L, 0x601c4205aebd9e47L},
+ /* 247 */ {8, 0.12581200, 0xc0435871d1110f41L, 0x54ddc59756f05016L},
+ /* 248 */ {8, 0.12571980, 0xc694446f01000000L, 0x4a0648979c838c18L},
+ /* 249 */ {8, 0.12562811, 0xcd137a5b57ac3ec1L, 0x3f91b6e0bb3a053dL},
+ /* 250 */ {8, 0.12553692, 0xd3c21bcecceda100L, 0x357c299a88ea76a5L},
+ /* 251 */ {8, 0.12544622, 0xdaa150410b788de1L, 0x2bc1e517aecc56e3L},
+ /* 252 */ {8, 0.12535601, 0xe1b24521be010000L, 0x225f56ceb3da9f5dL},
+ /* 253 */ {8, 0.12526629, 0xe8f62df12777c1a1L, 0x1951136d53ad63acL},
+ /* 254 */ {8, 0.12517705, 0xf06e445906fc0100L, 0x1093d504b3cd7d93L},
+ /* 255 */ {8, 0.12508829, 0xf81bc845c81bf801L, 0x824794d1ec1814fL},
+};
+#endif
diff --git a/mpn/msdos/asm-syntax.h b/mpn/msdos/asm-syntax.h
new file mode 100755
index 000000000..e6327e074
--- /dev/null
+++ b/mpn/msdos/asm-syntax.h
@@ -0,0 +1,2 @@
+#define ELF_SYNTAX
+#include "x86/syntax.h"
diff --git a/mpn/ns32k/add_n.s b/mpn/ns32k/add_n.s
new file mode 100644
index 000000000..dde2e15b5
--- /dev/null
+++ b/mpn/ns32k/add_n.s
@@ -0,0 +1,46 @@
+# ns32000 __mpn_add_n -- Add two limb vectors of the same length > 0 and store
+# sum in a third limb vector.
+
+# Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+# This file is part of the GNU MP Library.
+
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+
+# The GNU MP Library 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 Library General Public
+# License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+
+
+ .align 1
+.globl ___mpn_add_n
+___mpn_add_n:
+ save [r3,r4,r5]
+ negd 28(sp),r3
+ movd r3,r0
+ lshd 2,r0
+ movd 24(sp),r4
+ subd r0,r4 # r4 -> to end of S2
+ movd 20(sp),r5
+ subd r0,r5 # r5 -> to end of S1
+ movd 16(sp),r2
+ subd r0,r2 # r2 -> to end of RES
+ subd r0,r0 # cy = 0
+
+Loop: movd r5[r3:d],r0
+ addcd r4[r3:d],r0
+ movd r0,r2[r3:d]
+ acbd 1,r3,Loop
+
+ scsd r0 # r0 = cy.
+ restore [r5,r4,r3]
+ ret 0
diff --git a/mpn/ns32k/addmul_1.s b/mpn/ns32k/addmul_1.s
new file mode 100644
index 000000000..205bfe3b3
--- /dev/null
+++ b/mpn/ns32k/addmul_1.s
@@ -0,0 +1,48 @@
+# ns32000 __mpn_addmul_1 -- Multiply a limb vector with a limb and add
+# the result to a second limb vector.
+
+# Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+# This file is part of the GNU MP Library.
+
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+
+# The GNU MP Library 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 Library General Public
+# License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+
+
+ .align 1
+.globl ___mpn_addmul_1
+___mpn_addmul_1:
+ save [r3,r4,r5,r6,r7]
+ negd 24(sp),r4
+ movd r4,r0
+ lshd 2,r0
+ movd 20(sp),r5
+ subd r0,r5 # r5 -> to end of S1
+ movd 16(sp),r6
+ subd r0,r6 # r6 -> to end of RES
+ subd r0,r0 # r0 = 0, cy = 0
+ movd 28(sp),r7 # r7 = s2_limb
+
+Loop: movd r5[r4:d],r2
+ meid r7,r2 # r2 = low_prod, r3 = high_prod
+ addcd r0,r2 # r2 = low_prod + cy_limb
+ movd r3,r0 # r0 = new cy_limb
+ addcd 0,r0
+ addd r2,r6[r4:d]
+ acbd 1,r4,Loop
+
+ addcd 0,r0
+ restore [r7,r6,r5,r4,r3]
+ ret 0
diff --git a/mpn/ns32k/mul_1.s b/mpn/ns32k/mul_1.s
new file mode 100644
index 000000000..64e4abbba
--- /dev/null
+++ b/mpn/ns32k/mul_1.s
@@ -0,0 +1,47 @@
+# ns32000 __mpn_mul_1 -- Multiply a limb vector with a limb and store
+# the result in a second limb vector.
+
+# Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+# This file is part of the GNU MP Library.
+
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+
+# The GNU MP Library 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 Library General Public
+# License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+
+
+ .align 1
+.globl ___mpn_mul_1
+___mpn_mul_1:
+ save [r3,r4,r5,r6,r7]
+ negd 24(sp),r4
+ movd r4,r0
+ lshd 2,r0
+ movd 20(sp),r5
+ subd r0,r5 # r5 -> to end of S1
+ movd 16(sp),r6
+ subd r0,r6 # r6 -> to end of RES
+ subd r0,r0 # r0 = 0, cy = 0
+ movd 28(sp),r7 # r7 = s2_limb
+
+Loop: movd r5[r4:d],r2
+ meid r7,r2 # r2 = low_prod, r3 = high_prod
+ addcd r0,r2 # r2 = low_prod + cy_limb
+ movd r3,r0 # r0 = new cy_limb
+ movd r2,r6[r4:d]
+ acbd 1,r4,Loop
+
+ addcd 0,r0
+ restore [r7,r6,r5,r4,r3]
+ ret 0
diff --git a/mpn/ns32k/sub_n.s b/mpn/ns32k/sub_n.s
new file mode 100644
index 000000000..ef6c889c5
--- /dev/null
+++ b/mpn/ns32k/sub_n.s
@@ -0,0 +1,46 @@
+# ns32000 __mpn_sub_n -- Subtract two limb vectors of the same length > 0 and
+# store difference in a third limb vector.
+
+# Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+# This file is part of the GNU MP Library.
+
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+
+# The GNU MP Library 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 Library General Public
+# License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+
+
+ .align 1
+.globl ___mpn_sub_n
+___mpn_sub_n:
+ save [r3,r4,r5]
+ negd 28(sp),r3
+ movd r3,r0
+ lshd 2,r0
+ movd 24(sp),r4
+ subd r0,r4 # r4 -> to end of S2
+ movd 20(sp),r5
+ subd r0,r5 # r5 -> to end of S1
+ movd 16(sp),r2
+ subd r0,r2 # r2 -> to end of RES
+ subd r0,r0 # cy = 0
+
+Loop: movd r5[r3:d],r0
+ subcd r4[r3:d],r0
+ movd r0,r2[r3:d]
+ acbd 1,r3,Loop
+
+ scsd r0 # r0 = cy.
+ restore [r5,r4,r3]
+ ret 0
diff --git a/mpn/ns32k/submul_1.s b/mpn/ns32k/submul_1.s
new file mode 100644
index 000000000..509309532
--- /dev/null
+++ b/mpn/ns32k/submul_1.s
@@ -0,0 +1,48 @@
+# ns32000 __mpn_submul_1 -- Multiply a limb vector with a limb and subtract
+# the result from a second limb vector.
+
+# Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+# This file is part of the GNU MP Library.
+
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+
+# The GNU MP Library 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 Library General Public
+# License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+
+
+ .align 1
+.globl ___mpn_submul_1
+___mpn_submul_1:
+ save [r3,r4,r5,r6,r7]
+ negd 24(sp),r4
+ movd r4,r0
+ lshd 2,r0
+ movd 20(sp),r5
+ subd r0,r5 # r5 -> to end of S1
+ movd 16(sp),r6
+ subd r0,r6 # r6 -> to end of RES
+ subd r0,r0 # r0 = 0, cy = 0
+ movd 28(sp),r7 # r7 = s2_limb
+
+Loop: movd r5[r4:d],r2
+ meid r7,r2 # r2 = low_prod, r3 = high_prod
+ addcd r0,r2 # r2 = low_prod + cy_limb
+ movd r3,r0 # r0 = new cy_limb
+ addcd 0,r0
+ subd r2,r6[r4:d]
+ acbd 1,r4,Loop
+
+ addcd 0,r0
+ restore [r7,r6,r5,r4,r3]
+ ret 0
diff --git a/mpn/power/add_n.s b/mpn/power/add_n.s
new file mode 100644
index 000000000..9e1c94897
--- /dev/null
+++ b/mpn/power/add_n.s
@@ -0,0 +1,81 @@
+# IBM POWER __mpn_add_n -- Add two limb vectors of equal, non-zero length.
+
+# Copyright (C) 1992, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+# This file is part of the GNU MP Library.
+
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+
+# The GNU MP Library 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 Library General Public
+# License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+
+
+# INPUT PARAMETERS
+# res_ptr r3
+# s1_ptr r4
+# s2_ptr r5
+# size r6
+
+ .toc
+ .extern __mpn_add_n[DS]
+ .extern .__mpn_add_n
+.csect [PR]
+ .align 2
+ .globl __mpn_add_n
+ .globl .__mpn_add_n
+ .csect __mpn_add_n[DS]
+__mpn_add_n:
+ .long .__mpn_add_n, TOC[tc0], 0
+ .csect [PR]
+.__mpn_add_n:
+ andil. 10,6,1 # odd or even number of limbs?
+ l 8,0(4) # load least significant s1 limb
+ l 0,0(5) # load least significant s2 limb
+ cal 3,-4(3) # offset res_ptr, it's updated before it's used
+ sri 10,6,1 # count for unrolled loop
+ a 7,0,8 # add least significant limbs, set cy
+ mtctr 10 # copy count into CTR
+ beq 0,Leven # branch if even # of limbs (# of limbs >= 2)
+
+# We have an odd # of limbs. Add the first limbs separately.
+ cmpi 1,10,0 # is count for unrolled loop zero?
+ bne 1,L1 # branch if not
+ st 7,4(3)
+ aze 3,10 # use the fact that r10 is zero...
+ br # return
+
+# We added least significant limbs. Now reload the next limbs to enter loop.
+L1: lu 8,4(4) # load s1 limb and update s1_ptr
+ lu 0,4(5) # load s2 limb and update s2_ptr
+ stu 7,4(3)
+ ae 7,0,8 # add limbs, set cy
+Leven: lu 9,4(4) # load s1 limb and update s1_ptr
+ lu 10,4(5) # load s2 limb and update s2_ptr
+ bdz Lend # If done, skip loop
+
+Loop: lu 8,4(4) # load s1 limb and update s1_ptr
+ lu 0,4(5) # load s2 limb and update s2_ptr
+ ae 11,9,10 # add previous limbs with cy, set cy
+ stu 7,4(3) #
+ lu 9,4(4) # load s1 limb and update s1_ptr
+ lu 10,4(5) # load s2 limb and update s2_ptr
+ ae 7,0,8 # add previous limbs with cy, set cy
+ stu 11,4(3) #
+ bdn Loop # decrement CTR and loop back
+
+Lend: ae 11,9,10 # add limbs with cy, set cy
+ st 7,4(3) #
+ st 11,8(3) #
+ lil 3,0 # load cy into ...
+ aze 3,3 # ... return value register
+ br
diff --git a/mpn/power/addmul_1.s b/mpn/power/addmul_1.s
new file mode 100644
index 000000000..2db69841c
--- /dev/null
+++ b/mpn/power/addmul_1.s
@@ -0,0 +1,123 @@
+# IBM POWER __mpn_addmul_1 -- Multiply a limb vector with a limb and add
+# the result to a second limb vector.
+
+# Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+# This file is part of the GNU MP Library.
+
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+
+# The GNU MP Library 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 Library General Public
+# License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+
+
+# INPUT PARAMETERS
+# res_ptr r3
+# s1_ptr r4
+# size r5
+# s2_limb r6
+
+# The RS/6000 has no unsigned 32x32->64 bit multiplication instruction. To
+# obtain that operation, we have to use the 32x32->64 signed multiplication
+# instruction, and add the appropriate compensation to the high limb of the
+# result. We add the multiplicand if the multiplier has its most significant
+# bit set, and we add the multiplier if the multiplicand has its most
+# significant bit set. We need to preserve the carry flag between each
+# iteration, so we have to compute the compensation carefully (the natural,
+# srai+and doesn't work). Since the POWER architecture has a branch unit
+# we can branch in zero cycles, so that's how we perform the additions.
+
+ .toc
+ .csect .__mpn_addmul_1[PR]
+ .align 2
+ .globl __mpn_addmul_1
+ .globl .__mpn_addmul_1
+ .csect __mpn_addmul_1[DS]
+__mpn_addmul_1:
+ .long .__mpn_addmul_1[PR], TOC[tc0], 0
+ .csect .__mpn_addmul_1[PR]
+.__mpn_addmul_1:
+
+ cal 3,-4(3)
+ l 0,0(4)
+ cmpi 0,6,0
+ mtctr 5
+ mul 9,0,6
+ srai 7,0,31
+ and 7,7,6
+ mfmq 8
+ cax 9,9,7
+ l 7,4(3)
+ a 8,8,7 # add res_limb
+ blt Lneg
+Lpos: bdz Lend
+
+Lploop: lu 0,4(4)
+ stu 8,4(3)
+ cmpi 0,0,0
+ mul 10,0,6
+ mfmq 0
+ ae 8,0,9 # low limb + old_cy_limb + old cy
+ l 7,4(3)
+ aze 10,10 # propagate cy to new cy_limb
+ a 8,8,7 # add res_limb
+ bge Lp0
+ cax 10,10,6 # adjust high limb for negative limb from s1
+Lp0: bdz Lend0
+ lu 0,4(4)
+ stu 8,4(3)
+ cmpi 0,0,0
+ mul 9,0,6
+ mfmq 0
+ ae 8,0,10
+ l 7,4(3)
+ aze 9,9
+ a 8,8,7
+ bge Lp1
+ cax 9,9,6 # adjust high limb for negative limb from s1
+Lp1: bdn Lploop
+
+ b Lend
+
+Lneg: cax 9,9,0
+ bdz Lend
+Lnloop: lu 0,4(4)
+ stu 8,4(3)
+ cmpi 0,0,0
+ mul 10,0,6
+ mfmq 7
+ ae 8,7,9
+ l 7,4(3)
+ ae 10,10,0 # propagate cy to new cy_limb
+ a 8,8,7 # add res_limb
+ bge Ln0
+ cax 10,10,6 # adjust high limb for negative limb from s1
+Ln0: bdz Lend0
+ lu 0,4(4)
+ stu 8,4(3)
+ cmpi 0,0,0
+ mul 9,0,6
+ mfmq 7
+ ae 8,7,10
+ l 7,4(3)
+ ae 9,9,0 # propagate cy to new cy_limb
+ a 8,8,7 # add res_limb
+ bge Ln1
+ cax 9,9,6 # adjust high limb for negative limb from s1
+Ln1: bdn Lnloop
+ b Lend
+
+Lend0: cal 9,0(10)
+Lend: st 8,4(3)
+ aze 3,9
+ br
diff --git a/mpn/power/lshift.s b/mpn/power/lshift.s
new file mode 100644
index 000000000..38169bf53
--- /dev/null
+++ b/mpn/power/lshift.s
@@ -0,0 +1,59 @@
+# IBM POWER __mpn_lshift --
+
+# Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+# This file is part of the GNU MP Library.
+
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+
+# The GNU MP Library 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 Library General Public
+# License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+
+
+# INPUT PARAMETERS
+# res_ptr r3
+# s_ptr r4
+# size r5
+# cnt r6
+
+ .toc
+ .extern __mpn_lshift[DS]
+ .extern .__mpn_lshift
+.csect [PR]
+ .align 2
+ .globl __mpn_lshift
+ .globl .__mpn_lshift
+ .csect __mpn_lshift[DS]
+__mpn_lshift:
+ .long .__mpn_lshift, TOC[tc0], 0
+ .csect [PR]
+.__mpn_lshift:
+ sli 0,5,2
+ cax 9,3,0
+ cax 4,4,0
+ sfi 8,6,32
+ mtctr 5 # put limb count in CTR loop register
+ lu 0,-4(4) # read most significant limb
+ sre 3,0,8 # compute carry out limb, and init MQ register
+ bdz Lend2 # if just one limb, skip loop
+ lu 0,-4(4) # read 2:nd most significant limb
+ sreq 7,0,8 # compute most significant limb of result
+ bdz Lend # if just two limb, skip loop
+Loop: lu 0,-4(4) # load next lower limb
+ stu 7,-4(9) # store previous result during read latency
+ sreq 7,0,8 # compute result limb
+ bdn Loop # loop back until CTR is zero
+Lend: stu 7,-4(9) # store 2:nd least significant limb
+Lend2: sle 7,0,6 # compute least significant limb
+ st 7,-4(9) # store it" \
+ br
diff --git a/mpn/power/mul_1.s b/mpn/power/mul_1.s
new file mode 100644
index 000000000..a72bce660
--- /dev/null
+++ b/mpn/power/mul_1.s
@@ -0,0 +1,110 @@
+# IBM POWER __mpn_mul_1 -- Multiply a limb vector with a limb and store
+# the result in a second limb vector.
+
+# Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+# This file is part of the GNU MP Library.
+
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+
+# The GNU MP Library 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 Library General Public
+# License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+
+
+# INPUT PARAMETERS
+# res_ptr r3
+# s1_ptr r4
+# size r5
+# s2_limb r6
+
+# The RS/6000 has no unsigned 32x32->64 bit multiplication instruction. To
+# obtain that operation, we have to use the 32x32->64 signed multiplication
+# instruction, and add the appropriate compensation to the high limb of the
+# result. We add the multiplicand if the multiplier has its most significant
+# bit set, and we add the multiplier if the multiplicand has its most
+# significant bit set. We need to preserve the carry flag between each
+# iteration, so we have to compute the compensation carefully (the natural,
+# srai+and doesn't work). Since the POWER architecture has a branch unit
+# we can branch in zero cycles, so that's how we perform the additions.
+
+ .toc
+ .csect .__mpn_mul_1[PR]
+ .align 2
+ .globl __mpn_mul_1
+ .globl .__mpn_mul_1
+ .csect __mpn_mul_1[DS]
+__mpn_mul_1:
+ .long .__mpn_mul_1[PR], TOC[tc0], 0
+ .csect .__mpn_mul_1[PR]
+.__mpn_mul_1:
+
+ cal 3,-4(3)
+ l 0,0(4)
+ cmpi 0,6,0
+ mtctr 5
+ mul 9,0,6
+ srai 7,0,31
+ and 7,7,6
+ mfmq 8
+ ai 0,0,0 # reset carry
+ cax 9,9,7
+ blt Lneg
+Lpos: bdz Lend
+Lploop: lu 0,4(4)
+ stu 8,4(3)
+ cmpi 0,0,0
+ mul 10,0,6
+ mfmq 0
+ ae 8,0,9
+ bge Lp0
+ cax 10,10,6 # adjust high limb for negative limb from s1
+Lp0: bdz Lend0
+ lu 0,4(4)
+ stu 8,4(3)
+ cmpi 0,0,0
+ mul 9,0,6
+ mfmq 0
+ ae 8,0,10
+ bge Lp1
+ cax 9,9,6 # adjust high limb for negative limb from s1
+Lp1: bdn Lploop
+ b Lend
+
+Lneg: cax 9,9,0
+ bdz Lend
+Lnloop: lu 0,4(4)
+ stu 8,4(3)
+ cmpi 0,0,0
+ mul 10,0,6
+ cax 10,10,0 # adjust high limb for negative s2_limb
+ mfmq 0
+ ae 8,0,9
+ bge Ln0
+ cax 10,10,6 # adjust high limb for negative limb from s1
+Ln0: bdz Lend0
+ lu 0,4(4)
+ stu 8,4(3)
+ cmpi 0,0,0
+ mul 9,0,6
+ cax 9,9,0 # adjust high limb for negative s2_limb
+ mfmq 0
+ ae 8,0,10
+ bge Ln1
+ cax 9,9,6 # adjust high limb for negative limb from s1
+Ln1: bdn Lnloop
+ b Lend
+
+Lend0: cal 9,0(10)
+Lend: st 8,4(3)
+ aze 3,9
+ br
diff --git a/mpn/power/rshift.s b/mpn/power/rshift.s
new file mode 100644
index 000000000..30d408a24
--- /dev/null
+++ b/mpn/power/rshift.s
@@ -0,0 +1,57 @@
+# IBM POWER __mpn_rshift --
+
+# Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+# This file is part of the GNU MP Library.
+
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+
+# The GNU MP Library 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 Library General Public
+# License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+
+
+# INPUT PARAMETERS
+# res_ptr r3
+# s_ptr r4
+# size r5
+# cnt r6
+
+ .toc
+ .extern __mpn_rshift[DS]
+ .extern .__mpn_rshift
+.csect [PR]
+ .align 2
+ .globl __mpn_rshift
+ .globl .__mpn_rshift
+ .csect __mpn_rshift[DS]
+__mpn_rshift:
+ .long .__mpn_rshift, TOC[tc0], 0
+ .csect [PR]
+.__mpn_rshift:
+ sfi 8,6,32
+ mtctr 5 # put limb count in CTR loop register
+ l 0,0(4) # read least significant limb
+ ai 9,3,-4 # adjust res_ptr since it's offset in the stu:s
+ sle 3,0,8 # compute carry limb, and init MQ register
+ bdz Lend2 # if just one limb, skip loop
+ lu 0,4(4) # read 2:nd least significant limb
+ sleq 7,0,8 # compute least significant limb of result
+ bdz Lend # if just two limb, skip loop
+Loop: lu 0,4(4) # load next higher limb
+ stu 7,4(9) # store previous result during read latency
+ sleq 7,0,8 # compute result limb
+ bdn Loop # loop back until CTR is zero
+Lend: stu 7,4(9) # store 2:nd most significant limb
+Lend2: sre 7,0,6 # compute most significant limb
+ st 7,4(9) # store it" \
+ br
diff --git a/mpn/power/sub_n.s b/mpn/power/sub_n.s
new file mode 100644
index 000000000..30d4fee86
--- /dev/null
+++ b/mpn/power/sub_n.s
@@ -0,0 +1,82 @@
+# IBM POWER __mpn_sub_n -- Subtract two limb vectors of equal, non-zero length.
+
+# Copyright (C) 1992, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+# This file is part of the GNU MP Library.
+
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+
+# The GNU MP Library 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 Library General Public
+# License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+
+
+# INPUT PARAMETERS
+# res_ptr r3
+# s1_ptr r4
+# s2_ptr r5
+# size r6
+
+ .toc
+ .extern __mpn_sub_n[DS]
+ .extern .__mpn_sub_n
+.csect [PR]
+ .align 2
+ .globl __mpn_sub_n
+ .globl .__mpn_sub_n
+ .csect __mpn_sub_n[DS]
+__mpn_sub_n:
+ .long .__mpn_sub_n, TOC[tc0], 0
+ .csect [PR]
+.__mpn_sub_n:
+ andil. 10,6,1 # odd or even number of limbs?
+ l 8,0(4) # load least significant s1 limb
+ l 0,0(5) # load least significant s2 limb
+ cal 3,-4(3) # offset res_ptr, it's updated before it's used
+ sri 10,6,1 # count for unrolled loop
+ sf 7,0,8 # subtract least significant limbs, set cy
+ mtctr 10 # copy count into CTR
+ beq 0,Leven # branch if even # of limbs (# of limbs >= 2)
+
+# We have an odd # of limbs. Add the first limbs separately.
+ cmpi 1,10,0 # is count for unrolled loop zero?
+ bne 1,L1 # branch if not
+ st 7,4(3)
+ sfe 3,0,0 # load !cy into ...
+ sfi 3,3,0 # ... return value register
+ br # return
+
+# We added least significant limbs. Now reload the next limbs to enter loop.
+L1: lu 8,4(4) # load s1 limb and update s1_ptr
+ lu 0,4(5) # load s2 limb and update s2_ptr
+ stu 7,4(3)
+ sfe 7,0,8 # subtract limbs, set cy
+Leven: lu 9,4(4) # load s1 limb and update s1_ptr
+ lu 10,4(5) # load s2 limb and update s2_ptr
+ bdz Lend # If done, skip loop
+
+Loop: lu 8,4(4) # load s1 limb and update s1_ptr
+ lu 0,4(5) # load s2 limb and update s2_ptr
+ sfe 11,10,9 # subtract previous limbs with cy, set cy
+ stu 7,4(3) #
+ lu 9,4(4) # load s1 limb and update s1_ptr
+ lu 10,4(5) # load s2 limb and update s2_ptr
+ sfe 7,0,8 # subtract previous limbs with cy, set cy
+ stu 11,4(3) #
+ bdn Loop # decrement CTR and loop back
+
+Lend: sfe 11,10,9 # subtract limbs with cy, set cy
+ st 7,4(3) #
+ st 11,8(3) #
+ sfe 3,0,0 # load !cy into ...
+ sfi 3,3,0 # ... return value register
+ br
diff --git a/mpn/power/submul_1.s b/mpn/power/submul_1.s
new file mode 100644
index 000000000..8e5946fe1
--- /dev/null
+++ b/mpn/power/submul_1.s
@@ -0,0 +1,128 @@
+# IBM POWER __mpn_submul_1 -- Multiply a limb vector with a limb and subtract
+# the result from a second limb vector.
+
+# Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+# This file is part of the GNU MP Library.
+
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+
+# The GNU MP Library 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 Library General Public
+# License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+
+
+# INPUT PARAMETERS
+# res_ptr r3
+# s1_ptr r4
+# size r5
+# s2_limb r6
+
+# The RS/6000 has no unsigned 32x32->64 bit multiplication instruction. To
+# obtain that operation, we have to use the 32x32->64 signed multiplication
+# instruction, and add the appropriate compensation to the high limb of the
+# result. We add the multiplicand if the multiplier has its most significant
+# bit set, and we add the multiplier if the multiplicand has its most
+# significant bit set. We need to preserve the carry flag between each
+# iteration, so we have to compute the compensation carefully (the natural,
+# srai+and doesn't work). Since the POWER architecture has a branch unit
+# we can branch in zero cycles, so that's how we perform the additions.
+
+ .toc
+ .csect .__mpn_submul_1[PR]
+ .align 2
+ .globl __mpn_submul_1
+ .globl .__mpn_submul_1
+ .csect __mpn_submul_1[DS]
+__mpn_submul_1:
+ .long .__mpn_submul_1[PR], TOC[tc0], 0
+ .csect .__mpn_submul_1[PR]
+.__mpn_submul_1:
+
+ cal 3,-4(3)
+ l 0,0(4)
+ cmpi 0,6,0
+ mtctr 5
+ mul 9,0,6
+ srai 7,0,31
+ and 7,7,6
+ mfmq 11
+ cax 9,9,7
+ l 7,4(3)
+ sf 8,11,7 # add res_limb
+ a 11,8,11 # invert cy (r11 is junk)
+ blt Lneg
+Lpos: bdz Lend
+
+Lploop: lu 0,4(4)
+ stu 8,4(3)
+ cmpi 0,0,0
+ mul 10,0,6
+ mfmq 0
+ ae 11,0,9 # low limb + old_cy_limb + old cy
+ l 7,4(3)
+ aze 10,10 # propagate cy to new cy_limb
+ sf 8,11,7 # add res_limb
+ a 11,8,11 # invert cy (r11 is junk)
+ bge Lp0
+ cax 10,10,6 # adjust high limb for negative limb from s1
+Lp0: bdz Lend0
+ lu 0,4(4)
+ stu 8,4(3)
+ cmpi 0,0,0
+ mul 9,0,6
+ mfmq 0
+ ae 11,0,10
+ l 7,4(3)
+ aze 9,9
+ sf 8,11,7
+ a 11,8,11 # invert cy (r11 is junk)
+ bge Lp1
+ cax 9,9,6 # adjust high limb for negative limb from s1
+Lp1: bdn Lploop
+
+ b Lend
+
+Lneg: cax 9,9,0
+ bdz Lend
+Lnloop: lu 0,4(4)
+ stu 8,4(3)
+ cmpi 0,0,0
+ mul 10,0,6
+ mfmq 7
+ ae 11,7,9
+ l 7,4(3)
+ ae 10,10,0 # propagate cy to new cy_limb
+ sf 8,11,7 # add res_limb
+ a 11,8,11 # invert cy (r11 is junk)
+ bge Ln0
+ cax 10,10,6 # adjust high limb for negative limb from s1
+Ln0: bdz Lend0
+ lu 0,4(4)
+ stu 8,4(3)
+ cmpi 0,0,0
+ mul 9,0,6
+ mfmq 7
+ ae 11,7,10
+ l 7,4(3)
+ ae 9,9,0 # propagate cy to new cy_limb
+ sf 8,11,7 # add res_limb
+ a 11,8,11 # invert cy (r11 is junk)
+ bge Ln1
+ cax 9,9,6 # adjust high limb for negative limb from s1
+Ln1: bdn Lnloop
+ b Lend
+
+Lend0: cal 9,0(10)
+Lend: st 8,4(3)
+ aze 3,9
+ br
diff --git a/mpn/powerpc32/add_n.s b/mpn/powerpc32/add_n.s
new file mode 100644
index 000000000..e2e97ee86
--- /dev/null
+++ b/mpn/powerpc32/add_n.s
@@ -0,0 +1,55 @@
+# PowerPC-32 __mpn_add_n -- Add two limb vectors of equal, non-zero length.
+
+# Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
+
+# This file is part of the GNU MP Library.
+
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+
+# The GNU MP Library 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 Library General Public
+# License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+
+
+# INPUT PARAMETERS
+# res_ptr r3
+# s1_ptr r4
+# s2_ptr r5
+# size r6
+
+ .toc
+ .extern __mpn_add_n[DS]
+ .extern .__mpn_add_n
+.csect [PR]
+ .align 2
+ .globl __mpn_add_n
+ .globl .__mpn_add_n
+ .csect __mpn_add_n[DS]
+__mpn_add_n:
+ .long .__mpn_add_n, TOC[tc0], 0
+ .csect [PR]
+.__mpn_add_n:
+ mtctr 6 # copy size into CTR
+ lwz 8,0(4) # load least significant s1 limb
+ lwz 0,0(5) # load least significant s2 limb
+ addi 3,3,-4 # offset res_ptr, it's updated before used
+ addc 7,0,8 # add least significant limbs, set cy
+ bdz Lend # If done, skip loop
+Loop: lwzu 8,4(4) # load s1 limb and update s1_ptr
+ lwzu 0,4(5) # load s2 limb and update s2_ptr
+ stwu 7,4(3) # store previous limb in load latency slot
+ adde 7,0,8 # add new limbs with cy, set cy
+ bdn Loop # decrement CTR and loop back
+Lend: stw 7,4(3) # store ultimate result limb
+ li 3,0 # load cy into ...
+ aze 3,3 # ... return value register
+ blr
diff --git a/mpn/powerpc32/addmul_1.s b/mpn/powerpc32/addmul_1.s
new file mode 100644
index 000000000..71a45e2ca
--- /dev/null
+++ b/mpn/powerpc32/addmul_1.s
@@ -0,0 +1,68 @@
+# PowerPC-32 __mpn_addmul_1 -- Multiply a limb vector with a limb and add
+# the result to a second limb vector.
+
+# Copyright (C) 1995 Free Software Foundation, Inc.
+
+# This file is part of the GNU MP Library.
+
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+
+# The GNU MP Library 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 Library General Public
+# License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+
+
+# INPUT PARAMETERS
+# res_ptr r3
+# s1_ptr r4
+# size r5
+# s2_limb r6
+
+# This is a fairly straightforward implementation. The timing of the PC601
+# is hard to understand, so I will wait to optimize this until I have some
+# hardware to play with.
+
+# The code trivially generalizes to 64 bit limbs for the PC620.
+
+ .toc
+ .csect .__mpn_addmul_1[PR]
+ .align 2
+ .globl __mpn_addmul_1
+ .globl .__mpn_addmul_1
+ .csect __mpn_addmul_1[DS]
+__mpn_addmul_1:
+ .long .__mpn_addmul_1[PR], TOC[tc0], 0
+ .csect .__mpn_addmul_1[PR]
+.__mpn_addmul_1:
+ mtctr 5
+
+ lwz 0,0(4)
+ mullw 7,0,6
+ mulhwu 10,0,6
+ lwz 9,0(3)
+ addc 8,7,9
+ addi 3,3,-4
+ bdz Lend
+
+Loop: lwzu 0,4(4)
+ stwu 8,4(3)
+ mullw 8,0,6
+ adde 7,8,10
+ mulhwu 10,0,6
+ lwz 9,4(3)
+ addze 10,10
+ addc 8,7,9
+ bdn Loop
+
+Lend: stw 8,4(3)
+ addze 3,10
+ blr
diff --git a/mpn/powerpc32/lshift.s b/mpn/powerpc32/lshift.s
new file mode 100644
index 000000000..a93aa75c7
--- /dev/null
+++ b/mpn/powerpc32/lshift.s
@@ -0,0 +1,67 @@
+# PowerPC-32 __mpn_lshift --
+
+# Copyright (C) 1995 Free Software Foundation, Inc.
+
+# This file is part of the GNU MP Library.
+
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+
+# The GNU MP Library 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 Library General Public
+# License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+
+
+# INPUT PARAMETERS
+# res_ptr r3
+# s1_ptr r4
+# size r5
+# cnt r6
+
+ .toc
+.csect .text[PR]
+ .align 2
+ .globl __mpn_lshift
+ .globl .__mpn_lshift
+ .csect __mpn_lshift[DS]
+__mpn_lshift:
+ .long .__mpn_lshift, TOC[tc0], 0
+ .csect .text[PR]
+.__mpn_lshift:
+ mtctr 5 # copy size into CTR
+ slwi 0,5,2
+ add 7,3,0 # make r7 point at end of res
+ add 4,4,0 # make r4 point at end of s1
+ subfic 8,6,32
+ lwzu 11,-4(4) # load first s1 limb
+ srw 3,11,8 # compute function return value
+ bdz Lend1
+
+Loop: lwzu 10,-4(4)
+ slw 9,11,6
+ srw 12,10,8
+ or 9,9,12
+ stwu 9,-4(7)
+ bdz Lend2
+ lwzu 11,-4(4)
+ slw 9,10,6
+ srw 12,11,8
+ or 9,9,12
+ stwu 9,-4(7)
+ bdn Loop
+
+Lend1: slw 0,11,6
+ stw 0,-4(7)
+ blr
+
+Lend2: slw 0,10,6
+ stw 0,-4(7)
+ blr
diff --git a/mpn/powerpc32/mul_1.s b/mpn/powerpc32/mul_1.s
new file mode 100644
index 000000000..a72dae774
--- /dev/null
+++ b/mpn/powerpc32/mul_1.s
@@ -0,0 +1,63 @@
+# PowerPC-32 __mpn_mul_1 -- Multiply a limb vector with a limb and store
+# the result in a second limb vector.
+
+# Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+
+# This file is part of the GNU MP Library.
+
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+
+# The GNU MP Library 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 Library General Public
+# License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+
+
+# INPUT PARAMETERS
+# res_ptr r3
+# s1_ptr r4
+# size r5
+# s2_limb r6
+
+# This is a fairly straightforward implementation. The timing of the PC601
+# is hard to understand, so I will wait to optimize this until I have some
+# hardware to play with.
+
+# The code trivially generalizes to 64 bit limbs for the PC620.
+
+ .toc
+ .csect .__mpn_mul_1[PR]
+ .align 2
+ .globl __mpn_mul_1
+ .globl .__mpn_mul_1
+ .csect __mpn_mul_1[DS]
+__mpn_mul_1:
+ .long .__mpn_mul_1[PR], TOC[tc0], 0
+ .csect .__mpn_mul_1[PR]
+.__mpn_mul_1:
+ mtctr 5
+
+ lwz 0,0(4)
+ mullw 7,0,6
+ mulhwu 10,0,6
+ addic 3,3,-4 # adjust res_ptr and reset carry
+ bdz Lend
+
+Loop: lwzu 0,4(4)
+ stwu 7,4(3)
+ mullw 8,0,6
+ adde 7,8,10
+ mulhwu 10,0,6
+ bdn Loop
+
+Lend: stw 7,4(3)
+ addze 3,10
+ blr
diff --git a/mpn/powerpc32/rshift.s b/mpn/powerpc32/rshift.s
new file mode 100644
index 000000000..c957fcdf0
--- /dev/null
+++ b/mpn/powerpc32/rshift.s
@@ -0,0 +1,65 @@
+# PowerPC-32 __mpn_rshift --
+
+# Copyright (C) 1995 Free Software Foundation, Inc.
+
+# This file is part of the GNU MP Library.
+
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+
+# The GNU MP Library 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 Library General Public
+# License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+
+
+# INPUT PARAMETERS
+# res_ptr r3
+# s1_ptr r4
+# size r5
+# cnt r6
+
+ .toc
+.csect .text[PR]
+ .align 2
+ .globl __mpn_rshift
+ .globl .__mpn_rshift
+ .csect __mpn_rshift[DS]
+__mpn_rshift:
+ .long .__mpn_rshift, TOC[tc0], 0
+ .csect .text[PR]
+.__mpn_rshift:
+ mtctr 5 # copy size into CTR
+ addi 7,3,-4 # move adjusted res_ptr to free return reg
+ subfic 8,6,32
+ lwz 11,0(4) # load first s1 limb
+ slw 3,11,8 # compute function return value
+ bdz Lend1
+
+Loop: lwzu 10,4(4)
+ srw 9,11,6
+ slw 12,10,8
+ or 9,9,12
+ stwu 9,4(7)
+ bdz Lend2
+ lwzu 11,4(4)
+ srw 9,10,6
+ slw 12,11,8
+ or 9,9,12
+ stwu 9,4(7)
+ bdn Loop
+
+Lend1: srw 0,11,6
+ stw 0,4(7)
+ blr
+
+Lend2: srw 0,10,6
+ stw 0,4(7)
+ blr
diff --git a/mpn/powerpc32/sub_n.s b/mpn/powerpc32/sub_n.s
new file mode 100644
index 000000000..c7634d680
--- /dev/null
+++ b/mpn/powerpc32/sub_n.s
@@ -0,0 +1,56 @@
+# PowerPC-32 __mpn_sub_n -- Subtract two limb vectors of the same length > 0
+# and store difference in a third limb vector.
+
+# Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
+
+# This file is part of the GNU MP Library.
+
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+
+# The GNU MP Library 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 Library General Public
+# License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+
+
+# INPUT PARAMETERS
+# res_ptr r3
+# s1_ptr r4
+# s2_ptr r5
+# size r6
+
+ .toc
+ .extern __mpn_sub_n[DS]
+ .extern .__mpn_sub_n
+.csect [PR]
+ .align 2
+ .globl __mpn_sub_n
+ .globl .__mpn_sub_n
+ .csect __mpn_sub_n[DS]
+__mpn_sub_n:
+ .long .__mpn_sub_n, TOC[tc0], 0
+ .csect [PR]
+.__mpn_sub_n:
+ mtctr 6 # copy size into CTR
+ lwz 8,0(4) # load least significant s1 limb
+ lwz 0,0(5) # load least significant s2 limb
+ addi 3,3,-4 # offset res_ptr, it's updated before used
+ subfc 7,0,8 # add least significant limbs, set cy
+ bdz Lend # If done, skip loop
+Loop: lwzu 8,4(4) # load s1 limb and update s1_ptr
+ lwzu 0,4(5) # load s2 limb and update s2_ptr
+ stwu 7,4(3) # store previous limb in load latency slot
+ subfe 7,0,8 # add new limbs with cy, set cy
+ bdn Loop # decrement CTR and loop back
+Lend: stw 7,4(3) # store ultimate result limb
+ subfe 3,0,0 # load !cy into ...
+ subfic 3,3,0 # ... return value register
+ blr
diff --git a/mpn/powerpc32/submul_1.s b/mpn/powerpc32/submul_1.s
new file mode 100644
index 000000000..a830ce87a
--- /dev/null
+++ b/mpn/powerpc32/submul_1.s
@@ -0,0 +1,70 @@
+# PowerPC-32 __mpn_submul_1 -- Multiply a limb vector with a limb and subtract
+# the result from a second limb vector.
+
+# Copyright (C) 1995 Free Software Foundation, Inc.
+
+# This file is part of the GNU MP Library.
+
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+
+# The GNU MP Library 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 Library General Public
+# License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+
+
+# INPUT PARAMETERS
+# res_ptr r3
+# s1_ptr r4
+# size r5
+# s2_limb r6
+
+# This is a fairly straightforward implementation. The timing of the PC601
+# is hard to understand, so I will wait to optimize this until I have some
+# hardware to play with.
+
+# The code trivially generalizes to 64 bit limbs for the PC620.
+
+ .toc
+ .csect .__mpn_submul_1[PR]
+ .align 2
+ .globl __mpn_submul_1
+ .globl .__mpn_submul_1
+ .csect __mpn_submul_1[DS]
+__mpn_submul_1:
+ .long .__mpn_submul_1[PR], TOC[tc0], 0
+ .csect .__mpn_submul_1[PR]
+.__mpn_submul_1:
+ mtctr 5
+
+ lwz 0,0(4)
+ mullw 7,0,6
+ mulhwu 10,0,6
+ lwz 9,0(3)
+ subfc 8,7,9
+ addc 7,7,8 # invert cy (r7 is junk)
+ addi 3,3,-4
+ bdz Lend
+
+Loop: lwzu 0,4(4)
+ stwu 8,4(3)
+ mullw 8,0,6
+ adde 7,8,10
+ mulhwu 10,0,6
+ lwz 9,4(3)
+ addze 10,10
+ subfc 8,7,9
+ addc 7,7,8 # invert cy (r7 is junk)
+ bdn Loop
+
+Lend: stw 8,4(3)
+ addze 3,10
+ blr
diff --git a/mpn/powerpc64/gmp-mparam.h b/mpn/powerpc64/gmp-mparam.h
new file mode 100644
index 000000000..48eb85de6
--- /dev/null
+++ b/mpn/powerpc64/gmp-mparam.h
@@ -0,0 +1,27 @@
+/* gmp-mparam.h -- Compiler/machine parameter header file.
+
+Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#define BITS_PER_MP_LIMB 64
+#define BYTES_PER_MP_LIMB 8
+#define BITS_PER_LONGINT 64
+#define BITS_PER_INT 32
+#define BITS_PER_SHORTINT 16
+#define BITS_PER_CHAR 8
diff --git a/mpn/pyr/add_n.s b/mpn/pyr/add_n.s
new file mode 100644
index 000000000..082362e9d
--- /dev/null
+++ b/mpn/pyr/add_n.s
@@ -0,0 +1,54 @@
+.text
+ .align 2
+.globl ___mpn_add_n
+___mpn_add_n:
+ movw $-1,tr0 # representation for carry clear
+
+ movw pr3,tr2
+ andw $3,tr2
+ beq Lend0
+ subw tr2,pr3
+
+Loop0: rsubw $0,tr0 # restore carry bit from carry-save register
+
+ movw (pr1),tr1
+ addwc (pr2),tr1
+ movw tr1,(pr0)
+
+ subwb tr0,tr0
+ addw $4,pr0
+ addw $4,pr1
+ addw $4,pr2
+ addw $-1,tr2
+ bne Loop0
+
+ mtstw pr3,pr3
+ beq Lend
+Lend0:
+Loop: rsubw $0,tr0 # restore carry bit from carry-save register
+
+ movw (pr1),tr1
+ addwc (pr2),tr1
+ movw tr1,(pr0)
+
+ movw 4(pr1),tr1
+ addwc 4(pr2),tr1
+ movw tr1,4(pr0)
+
+ movw 8(pr1),tr1
+ addwc 8(pr2),tr1
+ movw tr1,8(pr0)
+
+ movw 12(pr1),tr1
+ addwc 12(pr2),tr1
+ movw tr1,12(pr0)
+
+ subwb tr0,tr0
+ addw $16,pr0
+ addw $16,pr1
+ addw $16,pr2
+ addw $-4,pr3
+ bne Loop
+Lend:
+ mnegw tr0,pr0
+ ret
diff --git a/mpn/pyr/addmul_1.s b/mpn/pyr/addmul_1.s
new file mode 100644
index 000000000..dc4702541
--- /dev/null
+++ b/mpn/pyr/addmul_1.s
@@ -0,0 +1,23 @@
+.text
+ .align 2
+.globl ___mpn_addmul_1
+___mpn_addmul_1:
+ mova (pr0)[pr2*4],pr0
+ mova (pr1)[pr2*4],pr1
+ mnegw pr2,pr2
+ movw $0,tr3
+
+Loop: movw (pr1)[pr2*4],tr1
+ uemul pr3,tr0
+ addw tr3,tr1
+ movw $0,tr3
+ addwc tr0,tr3
+ movw (pr0)[pr2*0x4],tr0
+ addw tr0,tr1
+ addwc $0,tr3
+ movw tr1,(pr0)[pr2*4]
+ addw $1,pr2
+ bne Loop
+
+ movw tr3,pr0
+ ret
diff --git a/mpn/pyr/mul_1.s b/mpn/pyr/mul_1.s
new file mode 100644
index 000000000..ddd919b79
--- /dev/null
+++ b/mpn/pyr/mul_1.s
@@ -0,0 +1,20 @@
+.text
+ .align 2
+.globl ___mpn_mul_1
+___mpn_mul_1:
+ mova (pr0)[pr2*4],pr0
+ mova (pr1)[pr2*4],pr1
+ mnegw pr2,pr2
+ movw $0,tr3
+
+Loop: movw (pr1)[pr2*4],tr1
+ uemul pr3,tr0
+ addw tr3,tr1
+ movw $0,tr3
+ addwc tr0,tr3
+ movw tr1,(pr0)[pr2*4]
+ addw $1,pr2
+ bne Loop
+
+ movw tr3,pr0
+ ret
diff --git a/mpn/pyr/sub_n.s b/mpn/pyr/sub_n.s
new file mode 100644
index 000000000..6b4117ff5
--- /dev/null
+++ b/mpn/pyr/sub_n.s
@@ -0,0 +1,54 @@
+.text
+ .align 2
+.globl ___mpn_sub_n
+___mpn_sub_n:
+ movw $-1,tr0 # representation for carry clear
+
+ movw pr3,tr2
+ andw $3,tr2
+ beq Lend0
+ subw tr2,pr3
+
+Loop0: rsubw $0,tr0 # restore carry bit from carry-save register
+
+ movw (pr1),tr1
+ subwb (pr2),tr1
+ movw tr1,(pr0)
+
+ subwb tr0,tr0
+ addw $4,pr0
+ addw $4,pr1
+ addw $4,pr2
+ addw $-1,tr2
+ bne Loop0
+
+ mtstw pr3,pr3
+ beq Lend
+Lend0:
+Loop: rsubw $0,tr0 # restore carry bit from carry-save register
+
+ movw (pr1),tr1
+ subwb (pr2),tr1
+ movw tr1,(pr0)
+
+ movw 4(pr1),tr1
+ subwb 4(pr2),tr1
+ movw tr1,4(pr0)
+
+ movw 8(pr1),tr1
+ subwb 8(pr2),tr1
+ movw tr1,8(pr0)
+
+ movw 12(pr1),tr1
+ subwb 12(pr2),tr1
+ movw tr1,12(pr0)
+
+ subwb tr0,tr0
+ addw $16,pr0
+ addw $16,pr1
+ addw $16,pr2
+ addw $-4,pr3
+ bne Loop
+Lend:
+ mnegw tr0,pr0
+ ret
diff --git a/mpn/sh/add_n.s b/mpn/sh/add_n.s
new file mode 100644
index 000000000..93dad51e4
--- /dev/null
+++ b/mpn/sh/add_n.s
@@ -0,0 +1,47 @@
+! SH __mpn_add_n -- Add two limb vectors of the same length > 0 and store
+! sum in a third limb vector.
+
+! Copyright (C) 1995 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP Library is free software; you can redistribute it and/or modify
+! it under the terms of the GNU Library General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or (at your
+! option) any later version.
+
+! The GNU MP Library 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 Library General Public
+! License for more details.
+
+! You should have received a copy of the GNU Library General Public License
+! along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+! MA 02111-1307, USA.
+
+
+! INPUT PARAMETERS
+! res_ptr r4
+! s1_ptr r5
+! s2_ptr r6
+! size r7
+
+ .text
+ .align 2
+ .global ___mpn_add_n
+___mpn_add_n:
+ mov #0,r3 ! clear cy save reg
+
+Loop: mov.l @r5+,r1
+ mov.l @r6+,r2
+ shlr r3 ! restore cy
+ addc r2,r1
+ movt r3 ! save cy
+ mov.l r1,@r4
+ dt r7
+ bf.s Loop
+ add #4,r4
+
+ rts
+ movt r0 ! return carry-out from most sign. limb
diff --git a/mpn/sh/sh2/addmul_1.s b/mpn/sh/sh2/addmul_1.s
new file mode 100644
index 000000000..19d81da3d
--- /dev/null
+++ b/mpn/sh/sh2/addmul_1.s
@@ -0,0 +1,53 @@
+! SH2 __mpn_addmul_1 -- Multiply a limb vector with a limb and add
+! the result to a second limb vector.
+
+! Copyright (C) 1995 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP Library is free software; you can redistribute it and/or modify
+! it under the terms of the GNU Library General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or (at your
+! option) any later version.
+
+! The GNU MP Library 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 Library General Public
+! License for more details.
+
+! You should have received a copy of the GNU Library General Public License
+! along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+! MA 02111-1307, USA.
+
+
+! INPUT PARAMETERS
+! res_ptr r4
+! s1_ptr r5
+! size r6
+! s2_limb r7
+
+ .text
+ .align 1
+ .global ___mpn_addmul_1
+___mpn_addmul_1:
+ mov #0,r2 ! cy_limb = 0
+ mov #0,r0 ! Keep r0 = 0 for entire loop
+ clrt
+
+Loop: mov.l @r5+,r3
+ dmulu.l r3,r7
+ sts macl,r1
+ addc r2,r1 ! lo_prod += old cy_limb
+ sts mach,r2 ! new cy_limb = hi_prod
+ mov.l @r4,r3
+ addc r0,r2 ! cy_limb += T, T = 0
+ addc r3,r1
+ addc r0,r2 ! cy_limb += T, T = 0
+ dt r6
+ mov.l r1,@r4
+ bf.s Loop
+ add #4,r4
+
+ rts
+ mov r2,r0
diff --git a/mpn/sh/sh2/mul_1.s b/mpn/sh/sh2/mul_1.s
new file mode 100644
index 000000000..7ca275671
--- /dev/null
+++ b/mpn/sh/sh2/mul_1.s
@@ -0,0 +1,50 @@
+! SH2 __mpn_mul_1 -- Multiply a limb vector with a limb and store
+! the result in a second limb vector.
+
+! Copyright (C) 1995 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP Library is free software; you can redistribute it and/or modify
+! it under the terms of the GNU Library General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or (at your
+! option) any later version.
+
+! The GNU MP Library 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 Library General Public
+! License for more details.
+
+! You should have received a copy of the GNU Library General Public License
+! along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+! MA 02111-1307, USA.
+
+
+! INPUT PARAMETERS
+! res_ptr r4
+! s1_ptr r5
+! size r6
+! s2_limb r7
+
+ .text
+ .align 1
+ .global ___mpn_mul_1
+___mpn_mul_1:
+ mov #0,r2 ! cy_limb = 0
+ mov #0,r0 ! Keep r0 = 0 for entire loop
+ clrt
+
+Loop: mov.l @r5+,r3
+ dmulu.l r3,r7
+ sts macl,r1
+ addc r2,r1
+ sts mach,r2
+ addc r0,r2 ! propagate carry to cy_limb (dt clobbers T)
+ dt r6
+ mov.l r1,@r4
+ bf.s Loop
+ add #4,r4
+
+ rts
+ mov r2,r0
diff --git a/mpn/sh/sh2/submul_1.s b/mpn/sh/sh2/submul_1.s
new file mode 100644
index 000000000..9ef380ced
--- /dev/null
+++ b/mpn/sh/sh2/submul_1.s
@@ -0,0 +1,53 @@
+! SH2 __mpn_submul_1 -- Multiply a limb vector with a limb and subtract
+! the result from a second limb vector.
+
+! Copyright (C) 1995 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP Library is free software; you can redistribute it and/or modify
+! it under the terms of the GNU Library General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or (at your
+! option) any later version.
+
+! The GNU MP Library 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 Library General Public
+! License for more details.
+
+! You should have received a copy of the GNU Library General Public License
+! along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+! MA 02111-1307, USA.
+
+
+! INPUT PARAMETERS
+! res_ptr r4
+! s1_ptr r5
+! size r6
+! s2_limb r7
+
+ .text
+ .align 1
+ .global ___mpn_submul_1
+___mpn_submul_1:
+ mov #0,r2 ! cy_limb = 0
+ mov #0,r0 ! Keep r0 = 0 for entire loop
+ clrt
+
+Loop: mov.l @r5+,r3
+ dmulu.l r3,r7
+ sts macl,r1
+ addc r2,r1 ! lo_prod += old cy_limb
+ sts mach,r2 ! new cy_limb = hi_prod
+ mov.l @r4,r3
+ addc r0,r2 ! cy_limb += T, T = 0
+ subc r3,r1
+ addc r0,r2 ! cy_limb += T, T = 0
+ dt r6
+ mov.l r1,@r4
+ bf.s Loop
+ add #4,r4
+
+ rts
+ mov r2,r0
diff --git a/mpn/sh/sub_n.s b/mpn/sh/sub_n.s
new file mode 100644
index 000000000..6b201f60f
--- /dev/null
+++ b/mpn/sh/sub_n.s
@@ -0,0 +1,47 @@
+! SH __mpn_sub_n -- Subtract two limb vectors of the same length > 0 and store
+! difference in a third limb vector.
+
+! Copyright (C) 1995 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP Library is free software; you can redistribute it and/or modify
+! it under the terms of the GNU Library General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or (at your
+! option) any later version.
+
+! The GNU MP Library 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 Library General Public
+! License for more details.
+
+! You should have received a copy of the GNU Library General Public License
+! along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+! MA 02111-1307, USA.
+
+
+! INPUT PARAMETERS
+! res_ptr r4
+! s1_ptr r5
+! s2_ptr r6
+! size r7
+
+ .text
+ .align 2
+ .global ___mpn_sub_n
+___mpn_sub_n:
+ mov #0,r3 ! clear cy save reg
+
+Loop: mov.l @r5+,r1
+ mov.l @r6+,r2
+ shlr r3 ! restore cy
+ subc r2,r1
+ movt r3 ! save cy
+ mov.l r1,@r4
+ dt r7
+ bf.s Loop
+ add #4,r4
+
+ rts
+ movt r0 ! return carry-out from most sign. limb
diff --git a/mpn/sparc32/README b/mpn/sparc32/README
new file mode 100644
index 000000000..7c19df7bc
--- /dev/null
+++ b/mpn/sparc32/README
@@ -0,0 +1,36 @@
+This directory contains mpn functions for various SPARC chips. Code that
+runs only on version 8 SPARC implementations, is in the v8 subdirectory.
+
+RELEVANT OPTIMIZATION ISSUES
+
+ Load and Store timing
+
+On most early SPARC implementations, the ST instructions takes multiple
+cycles, while a STD takes just a single cycle more than an ST. For the CPUs
+in SPARCstation I and II, the times are 3 and 4 cycles, respectively.
+Therefore, combining two ST instrucitons into a STD when possible is a
+significant optimiation.
+
+Later SPARC implementations have single cycle ST.
+
+For SuperSPARC, we can perform just one memory instruction per cycle, even
+if up to two integer instructions can be executed in its pipeline. For
+programs that perform so many memory operations that there are not enough
+non-memory operations to issue in parallel with all memory operations, using
+LDD and STD when possible helps.
+
+STATUS
+
+1. On a SuperSPARC, mpn_lshift and mpn_rshift run at 3 cycles/limb, or 2.5
+ cycles/limb asymptotically. We could optimize speed for special counts
+ by using ADDXCC.
+
+2. On a SuperSPARC, mpn_add_n and mpn_sub_n runs at 2.5 cycles/limb, or 2
+ cycles/limb asymptotically.
+
+3. mpn_mul_1 runs at what is believed to be optimal speed.
+
+4. On SuperSPARC, mpn_addmul_1 and mpn_submul_1 could both be improved by a
+ cycle by avoiding one of the add instrucitons. See a29k/addmul_1.
+
+The speed of the code for other SPARC implementations is uncertain.
diff --git a/mpn/sparc32/add_n.S b/mpn/sparc32/add_n.S
new file mode 100644
index 000000000..9852c256a
--- /dev/null
+++ b/mpn/sparc32/add_n.S
@@ -0,0 +1,226 @@
+! SPARC __mpn_add_n -- Add two limb vectors of the same length > 0 and store
+! sum in a third limb vector.
+
+! Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP Library is free software; you can redistribute it and/or modify
+! it under the terms of the GNU Library General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or (at your
+! option) any later version.
+
+! The GNU MP Library 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 Library General Public
+! License for more details.
+
+! You should have received a copy of the GNU Library General Public License
+! along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+! MA 02111-1307, USA.
+
+
+! INPUT PARAMETERS
+#define res_ptr %o0
+#define s1_ptr %o1
+#define s2_ptr %o2
+#define size %o3
+
+#include "sysdep.h"
+
+ .text
+ .align 4
+ .global C_SYMBOL_NAME(__mpn_add_n)
+C_SYMBOL_NAME(__mpn_add_n):
+ xor s2_ptr,res_ptr,%g1
+ andcc %g1,4,%g0
+ bne L1 ! branch if alignment differs
+ nop
+! ** V1a **
+L0: andcc res_ptr,4,%g0 ! res_ptr unaligned? Side effect: cy=0
+ be L_v1 ! if no, branch
+ nop
+/* Add least significant limb separately to align res_ptr and s2_ptr */
+ ld [s1_ptr],%g4
+ add s1_ptr,4,s1_ptr
+ ld [s2_ptr],%g2
+ add s2_ptr,4,s2_ptr
+ add size,-1,size
+ addcc %g4,%g2,%o4
+ st %o4,[res_ptr]
+ add res_ptr,4,res_ptr
+L_v1: addx %g0,%g0,%o4 ! save cy in register
+ cmp size,2 ! if size < 2 ...
+ bl Lend2 ! ... branch to tail code
+ subcc %g0,%o4,%g0 ! restore cy
+
+ ld [s1_ptr+0],%g4
+ addcc size,-10,size
+ ld [s1_ptr+4],%g1
+ ldd [s2_ptr+0],%g2
+ blt Lfin1
+ subcc %g0,%o4,%g0 ! restore cy
+/* Add blocks of 8 limbs until less than 8 limbs remain */
+Loop1: addxcc %g4,%g2,%o4
+ ld [s1_ptr+8],%g4
+ addxcc %g1,%g3,%o5
+ ld [s1_ptr+12],%g1
+ ldd [s2_ptr+8],%g2
+ std %o4,[res_ptr+0]
+ addxcc %g4,%g2,%o4
+ ld [s1_ptr+16],%g4
+ addxcc %g1,%g3,%o5
+ ld [s1_ptr+20],%g1
+ ldd [s2_ptr+16],%g2
+ std %o4,[res_ptr+8]
+ addxcc %g4,%g2,%o4
+ ld [s1_ptr+24],%g4
+ addxcc %g1,%g3,%o5
+ ld [s1_ptr+28],%g1
+ ldd [s2_ptr+24],%g2
+ std %o4,[res_ptr+16]
+ addxcc %g4,%g2,%o4
+ ld [s1_ptr+32],%g4
+ addxcc %g1,%g3,%o5
+ ld [s1_ptr+36],%g1
+ ldd [s2_ptr+32],%g2
+ std %o4,[res_ptr+24]
+ addx %g0,%g0,%o4 ! save cy in register
+ addcc size,-8,size
+ add s1_ptr,32,s1_ptr
+ add s2_ptr,32,s2_ptr
+ add res_ptr,32,res_ptr
+ bge Loop1
+ subcc %g0,%o4,%g0 ! restore cy
+
+Lfin1: addcc size,8-2,size
+ blt Lend1
+ subcc %g0,%o4,%g0 ! restore cy
+/* Add blocks of 2 limbs until less than 2 limbs remain */
+Loope1: addxcc %g4,%g2,%o4
+ ld [s1_ptr+8],%g4
+ addxcc %g1,%g3,%o5
+ ld [s1_ptr+12],%g1
+ ldd [s2_ptr+8],%g2
+ std %o4,[res_ptr+0]
+ addx %g0,%g0,%o4 ! save cy in register
+ addcc size,-2,size
+ add s1_ptr,8,s1_ptr
+ add s2_ptr,8,s2_ptr
+ add res_ptr,8,res_ptr
+ bge Loope1
+ subcc %g0,%o4,%g0 ! restore cy
+Lend1: addxcc %g4,%g2,%o4
+ addxcc %g1,%g3,%o5
+ std %o4,[res_ptr+0]
+ addx %g0,%g0,%o4 ! save cy in register
+
+ andcc size,1,%g0
+ be Lret1
+ subcc %g0,%o4,%g0 ! restore cy
+/* Add last limb */
+ ld [s1_ptr+8],%g4
+ ld [s2_ptr+8],%g2
+ addxcc %g4,%g2,%o4
+ st %o4,[res_ptr+8]
+
+Lret1: retl
+ addx %g0,%g0,%o0 ! return carry-out from most sign. limb
+
+L1: xor s1_ptr,res_ptr,%g1
+ andcc %g1,4,%g0
+ bne L2
+ nop
+! ** V1b **
+ mov s2_ptr,%g1
+ mov s1_ptr,s2_ptr
+ b L0
+ mov %g1,s1_ptr
+
+! ** V2 **
+/* If we come here, the alignment of s1_ptr and res_ptr as well as the
+ alignment of s2_ptr and res_ptr differ. Since there are only two ways
+ things can be aligned (that we care about) we now know that the alignment
+ of s1_ptr and s2_ptr are the same. */
+
+L2: cmp size,1
+ be Ljone
+ nop
+ andcc s1_ptr,4,%g0 ! s1_ptr unaligned? Side effect: cy=0
+ be L_v2 ! if no, branch
+ nop
+/* Add least significant limb separately to align s1_ptr and s2_ptr */
+ ld [s1_ptr],%g4
+ add s1_ptr,4,s1_ptr
+ ld [s2_ptr],%g2
+ add s2_ptr,4,s2_ptr
+ add size,-1,size
+ addcc %g4,%g2,%o4
+ st %o4,[res_ptr]
+ add res_ptr,4,res_ptr
+
+L_v2: addx %g0,%g0,%o4 ! save cy in register
+ addcc size,-8,size
+ blt Lfin2
+ subcc %g0,%o4,%g0 ! restore cy
+/* Add blocks of 8 limbs until less than 8 limbs remain */
+Loop2: ldd [s1_ptr+0],%g2
+ ldd [s2_ptr+0],%o4
+ addxcc %g2,%o4,%g2
+ st %g2,[res_ptr+0]
+ addxcc %g3,%o5,%g3
+ st %g3,[res_ptr+4]
+ ldd [s1_ptr+8],%g2
+ ldd [s2_ptr+8],%o4
+ addxcc %g2,%o4,%g2
+ st %g2,[res_ptr+8]
+ addxcc %g3,%o5,%g3
+ st %g3,[res_ptr+12]
+ ldd [s1_ptr+16],%g2
+ ldd [s2_ptr+16],%o4
+ addxcc %g2,%o4,%g2
+ st %g2,[res_ptr+16]
+ addxcc %g3,%o5,%g3
+ st %g3,[res_ptr+20]
+ ldd [s1_ptr+24],%g2
+ ldd [s2_ptr+24],%o4
+ addxcc %g2,%o4,%g2
+ st %g2,[res_ptr+24]
+ addxcc %g3,%o5,%g3
+ st %g3,[res_ptr+28]
+ addx %g0,%g0,%o4 ! save cy in register
+ addcc size,-8,size
+ add s1_ptr,32,s1_ptr
+ add s2_ptr,32,s2_ptr
+ add res_ptr,32,res_ptr
+ bge Loop2
+ subcc %g0,%o4,%g0 ! restore cy
+
+Lfin2: addcc size,8-2,size
+ blt Lend2
+ subcc %g0,%o4,%g0 ! restore cy
+Loope2: ldd [s1_ptr+0],%g2
+ ldd [s2_ptr+0],%o4
+ addxcc %g2,%o4,%g2
+ st %g2,[res_ptr+0]
+ addxcc %g3,%o5,%g3
+ st %g3,[res_ptr+4]
+ addx %g0,%g0,%o4 ! save cy in register
+ addcc size,-2,size
+ add s1_ptr,8,s1_ptr
+ add s2_ptr,8,s2_ptr
+ add res_ptr,8,res_ptr
+ bge Loope2
+ subcc %g0,%o4,%g0 ! restore cy
+Lend2: andcc size,1,%g0
+ be Lret2
+ subcc %g0,%o4,%g0 ! restore cy
+/* Add last limb */
+Ljone: ld [s1_ptr],%g4
+ ld [s2_ptr],%g2
+ addxcc %g4,%g2,%o4
+ st %o4,[res_ptr]
+
+Lret2: retl
+ addx %g0,%g0,%o0 ! return carry-out from most sign. limb
diff --git a/mpn/sparc32/addmul_1.S b/mpn/sparc32/addmul_1.S
new file mode 100644
index 000000000..375d25db6
--- /dev/null
+++ b/mpn/sparc32/addmul_1.S
@@ -0,0 +1,147 @@
+! SPARC __mpn_addmul_1 -- Multiply a limb vector with a limb and add
+! the result to a second limb vector.
+
+! Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP Library is free software; you can redistribute it and/or modify
+! it under the terms of the GNU Library General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or (at your
+! option) any later version.
+
+! The GNU MP Library 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 Library General Public
+! License for more details.
+
+! You should have received a copy of the GNU Library General Public License
+! along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+! MA 02111-1307, USA.
+
+
+! INPUT PARAMETERS
+! res_ptr o0
+! s1_ptr o1
+! size o2
+! s2_limb o3
+
+#include "sysdep.h"
+
+.text
+ .align 4
+ .global C_SYMBOL_NAME(__mpn_addmul_1)
+C_SYMBOL_NAME(__mpn_addmul_1):
+ ! Make S1_PTR and RES_PTR point at the end of their blocks
+ ! and put (- 4 x SIZE) in index/loop counter.
+ sll %o2,2,%o2
+ add %o0,%o2,%o4 ! RES_PTR in o4 since o0 is retval
+ add %o1,%o2,%o1
+ sub %g0,%o2,%o2
+
+ cmp %o3,0xfff
+ bgu Large
+ nop
+
+ ld [%o1+%o2],%o5
+ mov 0,%o0
+ b L0
+ add %o4,-4,%o4
+Loop0:
+ addcc %o5,%g1,%g1
+ ld [%o1+%o2],%o5
+ addx %o0,%g0,%o0
+ st %g1,[%o4+%o2]
+L0: wr %g0,%o3,%y
+ sra %o5,31,%g2
+ and %o3,%g2,%g2
+ andcc %g1,0,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,0,%g1
+ sra %g1,20,%g4
+ sll %g1,12,%g1
+ rd %y,%g3
+ srl %g3,20,%g3
+ or %g1,%g3,%g1
+
+ addcc %g1,%o0,%g1
+ addx %g2,%g4,%o0 ! add sign-compensation and cy to hi limb
+ addcc %o2,4,%o2 ! loop counter
+ bne Loop0
+ ld [%o4+%o2],%o5
+
+ addcc %o5,%g1,%g1
+ addx %o0,%g0,%o0
+ retl
+ st %g1,[%o4+%o2]
+
+
+Large: ld [%o1+%o2],%o5
+ mov 0,%o0
+ sra %o3,31,%g4 ! g4 = mask of ones iff S2_LIMB < 0
+ b L1
+ add %o4,-4,%o4
+Loop:
+ addcc %o5,%g3,%g3
+ ld [%o1+%o2],%o5
+ addx %o0,%g0,%o0
+ st %g3,[%o4+%o2]
+L1: wr %g0,%o5,%y
+ and %o5,%g4,%g2
+ andcc %g0,%g0,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%g0,%g1
+ rd %y,%g3
+ addcc %g3,%o0,%g3
+ addx %g2,%g1,%o0
+ addcc %o2,4,%o2
+ bne Loop
+ ld [%o4+%o2],%o5
+
+ addcc %o5,%g3,%g3
+ addx %o0,%g0,%o0
+ retl
+ st %g3,[%o4+%o2]
diff --git a/mpn/sparc32/lshift.S b/mpn/sparc32/lshift.S
new file mode 100644
index 000000000..4f0595f2f
--- /dev/null
+++ b/mpn/sparc32/lshift.S
@@ -0,0 +1,95 @@
+! sparc __mpn_lshift --
+
+! Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP Library is free software; you can redistribute it and/or modify
+! it under the terms of the GNU Library General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or (at your
+! option) any later version.
+
+! The GNU MP Library 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 Library General Public
+! License for more details.
+
+! You should have received a copy of the GNU Library General Public License
+! along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+! MA 02111-1307, USA.
+
+
+! INPUT PARAMETERS
+! res_ptr %o0
+! src_ptr %o1
+! size %o2
+! cnt %o3
+
+#include "sysdep.h"
+
+ .text
+ .align 4
+ .global C_SYMBOL_NAME(__mpn_lshift)
+C_SYMBOL_NAME(__mpn_lshift):
+ sll %o2,2,%g1
+ add %o1,%g1,%o1 ! make %o1 point at end of src
+ ld [%o1-4],%g2 ! load first limb
+ sub %g0,%o3,%o5 ! negate shift count
+ add %o0,%g1,%o0 ! make %o0 point at end of res
+ add %o2,-1,%o2
+ andcc %o2,4-1,%g4 ! number of limbs in first loop
+ srl %g2,%o5,%g1 ! compute function result
+ be L0 ! if multiple of 4 limbs, skip first loop
+ st %g1,[%sp+80]
+
+ sub %o2,%g4,%o2 ! adjust count for main loop
+
+Loop0: ld [%o1-8],%g3
+ add %o0,-4,%o0
+ add %o1,-4,%o1
+ addcc %g4,-1,%g4
+ sll %g2,%o3,%o4
+ srl %g3,%o5,%g1
+ mov %g3,%g2
+ or %o4,%g1,%o4
+ bne Loop0
+ st %o4,[%o0+0]
+
+L0: tst %o2
+ be Lend
+ nop
+
+Loop: ld [%o1-8],%g3
+ add %o0,-16,%o0
+ addcc %o2,-4,%o2
+ sll %g2,%o3,%o4
+ srl %g3,%o5,%g1
+
+ ld [%o1-12],%g2
+ sll %g3,%o3,%g4
+ or %o4,%g1,%o4
+ st %o4,[%o0+12]
+ srl %g2,%o5,%g1
+
+ ld [%o1-16],%g3
+ sll %g2,%o3,%o4
+ or %g4,%g1,%g4
+ st %g4,[%o0+8]
+ srl %g3,%o5,%g1
+
+ ld [%o1-20],%g2
+ sll %g3,%o3,%g4
+ or %o4,%g1,%o4
+ st %o4,[%o0+4]
+ srl %g2,%o5,%g1
+
+ add %o1,-16,%o1
+ or %g4,%g1,%g4
+ bne Loop
+ st %g4,[%o0+0]
+
+Lend: sll %g2,%o3,%g2
+ st %g2,[%o0-4]
+ retl
+ ld [%sp+80],%o0
diff --git a/mpn/sparc32/mul_1.S b/mpn/sparc32/mul_1.S
new file mode 100644
index 000000000..142fd8ba2
--- /dev/null
+++ b/mpn/sparc32/mul_1.S
@@ -0,0 +1,199 @@
+! SPARC __mpn_mul_1 -- Multiply a limb vector with a limb and store
+! the result in a second limb vector.
+
+! Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP Library is free software; you can redistribute it and/or modify
+! it under the terms of the GNU Library General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or (at your
+! option) any later version.
+
+! The GNU MP Library 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 Library General Public
+! License for more details.
+
+! You should have received a copy of the GNU Library General Public License
+! along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+! MA 02111-1307, USA.
+
+
+! INPUT PARAMETERS
+! res_ptr o0
+! s1_ptr o1
+! size o2
+! s2_limb o3
+
+! ADD CODE FOR SMALL MULTIPLIERS!
+!1: ld
+! st
+!
+!2: ld ,a
+! addxcc a,a,x
+! st x,
+!
+!3_unrolled:
+! ld ,a
+! addxcc a,a,x1 ! 2a + cy
+! addx %g0,%g0,x2
+! addcc a,x1,x ! 3a + c
+! st x,
+!
+! ld ,a
+! addxcc a,a,y1
+! addx %g0,%g0,y2
+! addcc a,y1,x
+! st x,
+!
+!4_unrolled:
+! ld ,a
+! srl a,2,x1 ! 4a
+! addxcc y2,x1,x
+! sll a,30,x2
+! st x,
+!
+! ld ,a
+! srl a,2,y1
+! addxcc x2,y1,y
+! sll a,30,y2
+! st x,
+!
+!5_unrolled:
+! ld ,a
+! srl a,2,x1 ! 4a
+! addxcc a,x1,x ! 5a + c
+! sll a,30,x2
+! addx %g0,x2,x2
+! st x,
+!
+! ld ,a
+! srl a,2,y1
+! addxcc a,y1,x
+! sll a,30,y2
+! addx %g0,y2,y2
+! st x,
+!
+!8_unrolled:
+! ld ,a
+! srl a,3,x1 ! 8a
+! addxcc y2,x1,x
+! sll a,29,x2
+! st x,
+!
+! ld ,a
+! srl a,3,y1
+! addxcc x2,y1,y
+! sll a,29,y2
+! st x,
+
+#include "sysdep.h"
+
+.text
+ .align 4
+ .global C_SYMBOL_NAME(__mpn_mul_1)
+C_SYMBOL_NAME(__mpn_mul_1):
+ ! Make S1_PTR and RES_PTR point at the end of their blocks
+ ! and put (- 4 x SIZE) in index/loop counter.
+ sll %o2,2,%o2
+ add %o0,%o2,%o4 ! RES_PTR in o4 since o0 is retval
+ add %o1,%o2,%o1
+ sub %g0,%o2,%o2
+
+ cmp %o3,0xfff
+ bgu Large
+ nop
+
+ ld [%o1+%o2],%o5
+ mov 0,%o0
+ b L0
+ add %o4,-4,%o4
+Loop0:
+ st %g1,[%o4+%o2]
+L0: wr %g0,%o3,%y
+ sra %o5,31,%g2
+ and %o3,%g2,%g2
+ andcc %g1,0,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,0,%g1
+ sra %g1,20,%g4
+ sll %g1,12,%g1
+ rd %y,%g3
+ srl %g3,20,%g3
+ or %g1,%g3,%g1
+
+ addcc %g1,%o0,%g1
+ addx %g2,%g4,%o0 ! add sign-compensation and cy to hi limb
+ addcc %o2,4,%o2 ! loop counter
+ bne,a Loop0
+ ld [%o1+%o2],%o5
+
+ retl
+ st %g1,[%o4+%o2]
+
+
+Large: ld [%o1+%o2],%o5
+ mov 0,%o0
+ sra %o3,31,%g4 ! g4 = mask of ones iff S2_LIMB < 0
+ b L1
+ add %o4,-4,%o4
+Loop:
+ st %g3,[%o4+%o2]
+L1: wr %g0,%o5,%y
+ and %o5,%g4,%g2 ! g2 = S1_LIMB iff S2_LIMB < 0, else 0
+ andcc %g0,%g0,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%g0,%g1
+ rd %y,%g3
+ addcc %g3,%o0,%g3
+ addx %g2,%g1,%o0 ! add sign-compensation and cy to hi limb
+ addcc %o2,4,%o2 ! loop counter
+ bne,a Loop
+ ld [%o1+%o2],%o5
+
+ retl
+ st %g3,[%o4+%o2]
diff --git a/mpn/sparc32/rshift.S b/mpn/sparc32/rshift.S
new file mode 100644
index 000000000..fea4f3b92
--- /dev/null
+++ b/mpn/sparc32/rshift.S
@@ -0,0 +1,92 @@
+! sparc __mpn_rshift --
+
+! Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP Library is free software; you can redistribute it and/or modify
+! it under the terms of the GNU Library General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or (at your
+! option) any later version.
+
+! The GNU MP Library 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 Library General Public
+! License for more details.
+
+! You should have received a copy of the GNU Library General Public License
+! along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+! MA 02111-1307, USA.
+
+
+! INPUT PARAMETERS
+! res_ptr %o0
+! src_ptr %o1
+! size %o2
+! cnt %o3
+
+#include "sysdep.h"
+
+ .text
+ .align 4
+ .global C_SYMBOL_NAME(__mpn_rshift)
+C_SYMBOL_NAME(__mpn_rshift):
+ ld [%o1],%g2 ! load first limb
+ sub %g0,%o3,%o5 ! negate shift count
+ add %o2,-1,%o2
+ andcc %o2,4-1,%g4 ! number of limbs in first loop
+ sll %g2,%o5,%g1 ! compute function result
+ be L0 ! if multiple of 4 limbs, skip first loop
+ st %g1,[%sp+80]
+
+ sub %o2,%g4,%o2 ! adjust count for main loop
+
+Loop0: ld [%o1+4],%g3
+ add %o0,4,%o0
+ add %o1,4,%o1
+ addcc %g4,-1,%g4
+ srl %g2,%o3,%o4
+ sll %g3,%o5,%g1
+ mov %g3,%g2
+ or %o4,%g1,%o4
+ bne Loop0
+ st %o4,[%o0-4]
+
+L0: tst %o2
+ be Lend
+ nop
+
+Loop: ld [%o1+4],%g3
+ add %o0,16,%o0
+ addcc %o2,-4,%o2
+ srl %g2,%o3,%o4
+ sll %g3,%o5,%g1
+
+ ld [%o1+8],%g2
+ srl %g3,%o3,%g4
+ or %o4,%g1,%o4
+ st %o4,[%o0-16]
+ sll %g2,%o5,%g1
+
+ ld [%o1+12],%g3
+ srl %g2,%o3,%o4
+ or %g4,%g1,%g4
+ st %g4,[%o0-12]
+ sll %g3,%o5,%g1
+
+ ld [%o1+16],%g2
+ srl %g3,%o3,%g4
+ or %o4,%g1,%o4
+ st %o4,[%o0-8]
+ sll %g2,%o5,%g1
+
+ add %o1,16,%o1
+ or %g4,%g1,%g4
+ bne Loop
+ st %g4,[%o0-4]
+
+Lend: srl %g2,%o3,%g2
+ st %g2,[%o0-0]
+ retl
+ ld [%sp+80],%o0
diff --git a/mpn/sparc32/sub_n.S b/mpn/sparc32/sub_n.S
new file mode 100644
index 000000000..b7a11958e
--- /dev/null
+++ b/mpn/sparc32/sub_n.S
@@ -0,0 +1,311 @@
+! SPARC __mpn_sub_n -- Subtract two limb vectors of the same length > 0 and
+! store difference in a third limb vector.
+
+! Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP Library is free software; you can redistribute it and/or modify
+! it under the terms of the GNU Library General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or (at your
+! option) any later version.
+
+! The GNU MP Library 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 Library General Public
+! License for more details.
+
+! You should have received a copy of the GNU Library General Public License
+! along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+! MA 02111-1307, USA.
+
+
+! INPUT PARAMETERS
+#define res_ptr %o0
+#define s1_ptr %o1
+#define s2_ptr %o2
+#define size %o3
+
+#include "sysdep.h"
+
+ .text
+ .align 4
+ .global C_SYMBOL_NAME(__mpn_sub_n)
+C_SYMBOL_NAME(__mpn_sub_n):
+ xor s2_ptr,res_ptr,%g1
+ andcc %g1,4,%g0
+ bne L1 ! branch if alignment differs
+ nop
+! ** V1a **
+ andcc res_ptr,4,%g0 ! res_ptr unaligned? Side effect: cy=0
+ be L_v1 ! if no, branch
+ nop
+/* Add least significant limb separately to align res_ptr and s2_ptr */
+ ld [s1_ptr],%g4
+ add s1_ptr,4,s1_ptr
+ ld [s2_ptr],%g2
+ add s2_ptr,4,s2_ptr
+ add size,-1,size
+ subcc %g4,%g2,%o4
+ st %o4,[res_ptr]
+ add res_ptr,4,res_ptr
+L_v1: addx %g0,%g0,%o4 ! save cy in register
+ cmp size,2 ! if size < 2 ...
+ bl Lend2 ! ... branch to tail code
+ subcc %g0,%o4,%g0 ! restore cy
+
+ ld [s1_ptr+0],%g4
+ addcc size,-10,size
+ ld [s1_ptr+4],%g1
+ ldd [s2_ptr+0],%g2
+ blt Lfin1
+ subcc %g0,%o4,%g0 ! restore cy
+/* Add blocks of 8 limbs until less than 8 limbs remain */
+Loop1: subxcc %g4,%g2,%o4
+ ld [s1_ptr+8],%g4
+ subxcc %g1,%g3,%o5
+ ld [s1_ptr+12],%g1
+ ldd [s2_ptr+8],%g2
+ std %o4,[res_ptr+0]
+ subxcc %g4,%g2,%o4
+ ld [s1_ptr+16],%g4
+ subxcc %g1,%g3,%o5
+ ld [s1_ptr+20],%g1
+ ldd [s2_ptr+16],%g2
+ std %o4,[res_ptr+8]
+ subxcc %g4,%g2,%o4
+ ld [s1_ptr+24],%g4
+ subxcc %g1,%g3,%o5
+ ld [s1_ptr+28],%g1
+ ldd [s2_ptr+24],%g2
+ std %o4,[res_ptr+16]
+ subxcc %g4,%g2,%o4
+ ld [s1_ptr+32],%g4
+ subxcc %g1,%g3,%o5
+ ld [s1_ptr+36],%g1
+ ldd [s2_ptr+32],%g2
+ std %o4,[res_ptr+24]
+ addx %g0,%g0,%o4 ! save cy in register
+ addcc size,-8,size
+ add s1_ptr,32,s1_ptr
+ add s2_ptr,32,s2_ptr
+ add res_ptr,32,res_ptr
+ bge Loop1
+ subcc %g0,%o4,%g0 ! restore cy
+
+Lfin1: addcc size,8-2,size
+ blt Lend1
+ subcc %g0,%o4,%g0 ! restore cy
+/* Add blocks of 2 limbs until less than 2 limbs remain */
+Loope1: subxcc %g4,%g2,%o4
+ ld [s1_ptr+8],%g4
+ subxcc %g1,%g3,%o5
+ ld [s1_ptr+12],%g1
+ ldd [s2_ptr+8],%g2
+ std %o4,[res_ptr+0]
+ addx %g0,%g0,%o4 ! save cy in register
+ addcc size,-2,size
+ add s1_ptr,8,s1_ptr
+ add s2_ptr,8,s2_ptr
+ add res_ptr,8,res_ptr
+ bge Loope1
+ subcc %g0,%o4,%g0 ! restore cy
+Lend1: subxcc %g4,%g2,%o4
+ subxcc %g1,%g3,%o5
+ std %o4,[res_ptr+0]
+ addx %g0,%g0,%o4 ! save cy in register
+
+ andcc size,1,%g0
+ be Lret1
+ subcc %g0,%o4,%g0 ! restore cy
+/* Add last limb */
+ ld [s1_ptr+8],%g4
+ ld [s2_ptr+8],%g2
+ subxcc %g4,%g2,%o4
+ st %o4,[res_ptr+8]
+
+Lret1: retl
+ addx %g0,%g0,%o0 ! return carry-out from most sign. limb
+
+L1: xor s1_ptr,res_ptr,%g1
+ andcc %g1,4,%g0
+ bne L2
+ nop
+! ** V1b **
+ andcc res_ptr,4,%g0 ! res_ptr unaligned? Side effect: cy=0
+ be L_v1b ! if no, branch
+ nop
+/* Add least significant limb separately to align res_ptr and s1_ptr */
+ ld [s2_ptr],%g4
+ add s2_ptr,4,s2_ptr
+ ld [s1_ptr],%g2
+ add s1_ptr,4,s1_ptr
+ add size,-1,size
+ subcc %g2,%g4,%o4
+ st %o4,[res_ptr]
+ add res_ptr,4,res_ptr
+L_v1b: addx %g0,%g0,%o4 ! save cy in register
+ cmp size,2 ! if size < 2 ...
+ bl Lend2 ! ... branch to tail code
+ subcc %g0,%o4,%g0 ! restore cy
+
+ ld [s2_ptr+0],%g4
+ addcc size,-10,size
+ ld [s2_ptr+4],%g1
+ ldd [s1_ptr+0],%g2
+ blt Lfin1b
+ subcc %g0,%o4,%g0 ! restore cy
+/* Add blocks of 8 limbs until less than 8 limbs remain */
+Loop1b: subxcc %g2,%g4,%o4
+ ld [s2_ptr+8],%g4
+ subxcc %g3,%g1,%o5
+ ld [s2_ptr+12],%g1
+ ldd [s1_ptr+8],%g2
+ std %o4,[res_ptr+0]
+ subxcc %g2,%g4,%o4
+ ld [s2_ptr+16],%g4
+ subxcc %g3,%g1,%o5
+ ld [s2_ptr+20],%g1
+ ldd [s1_ptr+16],%g2
+ std %o4,[res_ptr+8]
+ subxcc %g2,%g4,%o4
+ ld [s2_ptr+24],%g4
+ subxcc %g3,%g1,%o5
+ ld [s2_ptr+28],%g1
+ ldd [s1_ptr+24],%g2
+ std %o4,[res_ptr+16]
+ subxcc %g2,%g4,%o4
+ ld [s2_ptr+32],%g4
+ subxcc %g3,%g1,%o5
+ ld [s2_ptr+36],%g1
+ ldd [s1_ptr+32],%g2
+ std %o4,[res_ptr+24]
+ addx %g0,%g0,%o4 ! save cy in register
+ addcc size,-8,size
+ add s1_ptr,32,s1_ptr
+ add s2_ptr,32,s2_ptr
+ add res_ptr,32,res_ptr
+ bge Loop1b
+ subcc %g0,%o4,%g0 ! restore cy
+
+Lfin1b: addcc size,8-2,size
+ blt Lend1b
+ subcc %g0,%o4,%g0 ! restore cy
+/* Add blocks of 2 limbs until less than 2 limbs remain */
+Loope1b:subxcc %g2,%g4,%o4
+ ld [s2_ptr+8],%g4
+ subxcc %g3,%g1,%o5
+ ld [s2_ptr+12],%g1
+ ldd [s1_ptr+8],%g2
+ std %o4,[res_ptr+0]
+ addx %g0,%g0,%o4 ! save cy in register
+ addcc size,-2,size
+ add s1_ptr,8,s1_ptr
+ add s2_ptr,8,s2_ptr
+ add res_ptr,8,res_ptr
+ bge Loope1b
+ subcc %g0,%o4,%g0 ! restore cy
+Lend1b: subxcc %g2,%g4,%o4
+ subxcc %g3,%g1,%o5
+ std %o4,[res_ptr+0]
+ addx %g0,%g0,%o4 ! save cy in register
+
+ andcc size,1,%g0
+ be Lret1b
+ subcc %g0,%o4,%g0 ! restore cy
+/* Add last limb */
+ ld [s2_ptr+8],%g4
+ ld [s1_ptr+8],%g2
+ subxcc %g2,%g4,%o4
+ st %o4,[res_ptr+8]
+
+Lret1b: retl
+ addx %g0,%g0,%o0 ! return carry-out from most sign. limb
+
+! ** V2 **
+/* If we come here, the alignment of s1_ptr and res_ptr as well as the
+ alignment of s2_ptr and res_ptr differ. Since there are only two ways
+ things can be aligned (that we care about) we now know that the alignment
+ of s1_ptr and s2_ptr are the same. */
+
+L2: cmp size,1
+ be Ljone
+ nop
+ andcc s1_ptr,4,%g0 ! s1_ptr unaligned? Side effect: cy=0
+ be L_v2 ! if no, branch
+ nop
+/* Add least significant limb separately to align s1_ptr and s2_ptr */
+ ld [s1_ptr],%g4
+ add s1_ptr,4,s1_ptr
+ ld [s2_ptr],%g2
+ add s2_ptr,4,s2_ptr
+ add size,-1,size
+ subcc %g4,%g2,%o4
+ st %o4,[res_ptr]
+ add res_ptr,4,res_ptr
+
+L_v2: addx %g0,%g0,%o4 ! save cy in register
+ addcc size,-8,size
+ blt Lfin2
+ subcc %g0,%o4,%g0 ! restore cy
+/* Add blocks of 8 limbs until less than 8 limbs remain */
+Loop2: ldd [s1_ptr+0],%g2
+ ldd [s2_ptr+0],%o4
+ subxcc %g2,%o4,%g2
+ st %g2,[res_ptr+0]
+ subxcc %g3,%o5,%g3
+ st %g3,[res_ptr+4]
+ ldd [s1_ptr+8],%g2
+ ldd [s2_ptr+8],%o4
+ subxcc %g2,%o4,%g2
+ st %g2,[res_ptr+8]
+ subxcc %g3,%o5,%g3
+ st %g3,[res_ptr+12]
+ ldd [s1_ptr+16],%g2
+ ldd [s2_ptr+16],%o4
+ subxcc %g2,%o4,%g2
+ st %g2,[res_ptr+16]
+ subxcc %g3,%o5,%g3
+ st %g3,[res_ptr+20]
+ ldd [s1_ptr+24],%g2
+ ldd [s2_ptr+24],%o4
+ subxcc %g2,%o4,%g2
+ st %g2,[res_ptr+24]
+ subxcc %g3,%o5,%g3
+ st %g3,[res_ptr+28]
+ addx %g0,%g0,%o4 ! save cy in register
+ addcc size,-8,size
+ add s1_ptr,32,s1_ptr
+ add s2_ptr,32,s2_ptr
+ add res_ptr,32,res_ptr
+ bge Loop2
+ subcc %g0,%o4,%g0 ! restore cy
+
+Lfin2: addcc size,8-2,size
+ blt Lend2
+ subcc %g0,%o4,%g0 ! restore cy
+Loope2: ldd [s1_ptr+0],%g2
+ ldd [s2_ptr+0],%o4
+ subxcc %g2,%o4,%g2
+ st %g2,[res_ptr+0]
+ subxcc %g3,%o5,%g3
+ st %g3,[res_ptr+4]
+ addx %g0,%g0,%o4 ! save cy in register
+ addcc size,-2,size
+ add s1_ptr,8,s1_ptr
+ add s2_ptr,8,s2_ptr
+ add res_ptr,8,res_ptr
+ bge Loope2
+ subcc %g0,%o4,%g0 ! restore cy
+Lend2: andcc size,1,%g0
+ be Lret2
+ subcc %g0,%o4,%g0 ! restore cy
+/* Add last limb */
+Ljone: ld [s1_ptr],%g4
+ ld [s2_ptr],%g2
+ subxcc %g4,%g2,%o4
+ st %o4,[res_ptr]
+
+Lret2: retl
+ addx %g0,%g0,%o0 ! return carry-out from most sign. limb
diff --git a/mpn/sparc32/submul_1.S b/mpn/sparc32/submul_1.S
new file mode 100644
index 000000000..a8ebd501a
--- /dev/null
+++ b/mpn/sparc32/submul_1.S
@@ -0,0 +1,147 @@
+! SPARC __mpn_submul_1 -- Multiply a limb vector with a limb and subtract
+! the result from a second limb vector.
+
+! Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP Library is free software; you can redistribute it and/or modify
+! it under the terms of the GNU Library General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or (at your
+! option) any later version.
+
+! The GNU MP Library 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 Library General Public
+! License for more details.
+
+! You should have received a copy of the GNU Library General Public License
+! along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+! MA 02111-1307, USA.
+
+
+! INPUT PARAMETERS
+! res_ptr o0
+! s1_ptr o1
+! size o2
+! s2_limb o3
+
+#include "sysdep.h"
+
+.text
+ .align 4
+ .global C_SYMBOL_NAME(__mpn_submul_1)
+C_SYMBOL_NAME(__mpn_submul_1):
+ ! Make S1_PTR and RES_PTR point at the end of their blocks
+ ! and put (- 4 x SIZE) in index/loop counter.
+ sll %o2,2,%o2
+ add %o0,%o2,%o4 ! RES_PTR in o4 since o0 is retval
+ add %o1,%o2,%o1
+ sub %g0,%o2,%o2
+
+ cmp %o3,0xfff
+ bgu Large
+ nop
+
+ ld [%o1+%o2],%o5
+ mov 0,%o0
+ b L0
+ add %o4,-4,%o4
+Loop0:
+ subcc %o5,%g1,%g1
+ ld [%o1+%o2],%o5
+ addx %o0,%g0,%o0
+ st %g1,[%o4+%o2]
+L0: wr %g0,%o3,%y
+ sra %o5,31,%g2
+ and %o3,%g2,%g2
+ andcc %g1,0,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,%o5,%g1
+ mulscc %g1,0,%g1
+ sra %g1,20,%g4
+ sll %g1,12,%g1
+ rd %y,%g3
+ srl %g3,20,%g3
+ or %g1,%g3,%g1
+
+ addcc %g1,%o0,%g1
+ addx %g2,%g4,%o0 ! add sign-compensation and cy to hi limb
+ addcc %o2,4,%o2 ! loop counter
+ bne Loop0
+ ld [%o4+%o2],%o5
+
+ subcc %o5,%g1,%g1
+ addx %o0,%g0,%o0
+ retl
+ st %g1,[%o4+%o2]
+
+
+Large: ld [%o1+%o2],%o5
+ mov 0,%o0
+ sra %o3,31,%g4 ! g4 = mask of ones iff S2_LIMB < 0
+ b L1
+ add %o4,-4,%o4
+Loop:
+ subcc %o5,%g3,%g3
+ ld [%o1+%o2],%o5
+ addx %o0,%g0,%o0
+ st %g3,[%o4+%o2]
+L1: wr %g0,%o5,%y
+ and %o5,%g4,%g2
+ andcc %g0,%g0,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%o3,%g1
+ mulscc %g1,%g0,%g1
+ rd %y,%g3
+ addcc %g3,%o0,%g3
+ addx %g2,%g1,%o0
+ addcc %o2,4,%o2
+ bne Loop
+ ld [%o4+%o2],%o5
+
+ subcc %o5,%g3,%g3
+ addx %o0,%g0,%o0
+ retl
+ st %g3,[%o4+%o2]
diff --git a/mpn/sparc32/udiv_fp.S b/mpn/sparc32/udiv_fp.S
new file mode 100644
index 000000000..d11227dff
--- /dev/null
+++ b/mpn/sparc32/udiv_fp.S
@@ -0,0 +1,145 @@
+! SPARC v7 __udiv_qrnnd division support, used from longlong.h.
+! This is for v7 CPUs with a floating-point unit.
+
+! Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP Library is free software; you can redistribute it and/or modify
+! it under the terms of the GNU Library General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or (at your
+! option) any later version.
+
+! The GNU MP Library 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 Library General Public
+! License for more details.
+
+! You should have received a copy of the GNU Library General Public License
+! along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+! MA 02111-1307, USA.
+
+
+! INPUT PARAMETERS
+! rem_ptr i0
+! n1 i1
+! n0 i2
+! d i3
+
+#include "sysdep.h"
+#undef ret /* Kludge for glibc */
+
+ .text
+ .align 8
+LC0: .double 0r4294967296
+LC1: .double 0r2147483648
+
+ .align 4
+ .global C_SYMBOL_NAME(__udiv_qrnnd)
+C_SYMBOL_NAME(__udiv_qrnnd):
+ !#PROLOGUE# 0
+ save %sp,-104,%sp
+ !#PROLOGUE# 1
+ st %i1,[%fp-8]
+ ld [%fp-8],%f10
+ sethi %hi(LC0),%o7
+ fitod %f10,%f4
+ ldd [%o7+%lo(LC0)],%f8
+ cmp %i1,0
+ bge L248
+ mov %i0,%i5
+ faddd %f4,%f8,%f4
+L248:
+ st %i2,[%fp-8]
+ ld [%fp-8],%f10
+ fmuld %f4,%f8,%f6
+ cmp %i2,0
+ bge L249
+ fitod %f10,%f2
+ faddd %f2,%f8,%f2
+L249:
+ st %i3,[%fp-8]
+ faddd %f6,%f2,%f2
+ ld [%fp-8],%f10
+ cmp %i3,0
+ bge L250
+ fitod %f10,%f4
+ faddd %f4,%f8,%f4
+L250:
+ fdivd %f2,%f4,%f2
+ sethi %hi(LC1),%o7
+ ldd [%o7+%lo(LC1)],%f4
+ fcmped %f2,%f4
+ nop
+ fbge,a L251
+ fsubd %f2,%f4,%f2
+ fdtoi %f2,%f2
+ st %f2,[%fp-8]
+ b L252
+ ld [%fp-8],%i4
+L251:
+ fdtoi %f2,%f2
+ st %f2,[%fp-8]
+ ld [%fp-8],%i4
+ sethi %hi(-2147483648),%g2
+ xor %i4,%g2,%i4
+L252:
+ wr %g0,%i4,%y
+ sra %i3,31,%g2
+ and %i4,%g2,%g2
+ andcc %g0,0,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,%i3,%g1
+ mulscc %g1,0,%g1
+ add %g1,%g2,%i0
+ rd %y,%g3
+ subcc %i2,%g3,%o7
+ subxcc %i1,%i0,%g0
+ be L253
+ cmp %o7,%i3
+
+ add %i4,-1,%i0
+ add %o7,%i3,%o7
+ st %o7,[%i5]
+ ret
+ restore
+L253:
+ blu L246
+ mov %i4,%i0
+ add %i4,1,%i0
+ sub %o7,%i3,%o7
+L246:
+ st %o7,[%i5]
+ ret
+ restore
diff --git a/mpn/sparc32/udiv_nfp.S b/mpn/sparc32/udiv_nfp.S
new file mode 100644
index 000000000..118d8a4a2
--- /dev/null
+++ b/mpn/sparc32/udiv_nfp.S
@@ -0,0 +1,188 @@
+! SPARC v7 __udiv_qrnnd division support, used from longlong.h.
+! This is for v7 CPUs without a floating-point unit.
+
+! Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP Library is free software; you can redistribute it and/or modify
+! it under the terms of the GNU Library General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or (at your
+! option) any later version.
+
+! The GNU MP Library 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 Library General Public
+! License for more details.
+
+! You should have received a copy of the GNU Library General Public License
+! along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+! MA 02111-1307, USA.
+
+
+! INPUT PARAMETERS
+! rem_ptr o0
+! n1 o1
+! n0 o2
+! d o3
+
+#include "sysdep.h"
+
+ .text
+ .align 4
+ .global C_SYMBOL_NAME(__udiv_qrnnd)
+C_SYMBOL_NAME(__udiv_qrnnd):
+ tst %o3
+ bneg Largedivisor
+ mov 8,%g1
+
+ b Lp1
+ addxcc %o2,%o2,%o2
+
+Lplop: bcc Ln1
+ addxcc %o2,%o2,%o2
+Lp1: addx %o1,%o1,%o1
+ subcc %o1,%o3,%o4
+ bcc Ln2
+ addxcc %o2,%o2,%o2
+Lp2: addx %o1,%o1,%o1
+ subcc %o1,%o3,%o4
+ bcc Ln3
+ addxcc %o2,%o2,%o2
+Lp3: addx %o1,%o1,%o1
+ subcc %o1,%o3,%o4
+ bcc Ln4
+ addxcc %o2,%o2,%o2
+Lp4: addx %o1,%o1,%o1
+ addcc %g1,-1,%g1
+ bne Lplop
+ subcc %o1,%o3,%o4
+ bcc Ln5
+ addxcc %o2,%o2,%o2
+Lp5: st %o1,[%o0]
+ retl
+ xnor %g0,%o2,%o0
+
+Lnlop: bcc Lp1
+ addxcc %o2,%o2,%o2
+Ln1: addx %o4,%o4,%o4
+ subcc %o4,%o3,%o1
+ bcc Lp2
+ addxcc %o2,%o2,%o2
+Ln2: addx %o4,%o4,%o4
+ subcc %o4,%o3,%o1
+ bcc Lp3
+ addxcc %o2,%o2,%o2
+Ln3: addx %o4,%o4,%o4
+ subcc %o4,%o3,%o1
+ bcc Lp4
+ addxcc %o2,%o2,%o2
+Ln4: addx %o4,%o4,%o4
+ addcc %g1,-1,%g1
+ bne Lnlop
+ subcc %o4,%o3,%o1
+ bcc Lp5
+ addxcc %o2,%o2,%o2
+Ln5: st %o4,[%o0]
+ retl
+ xnor %g0,%o2,%o0
+
+Largedivisor:
+ and %o2,1,%o5 ! %o5 = n0 & 1
+
+ srl %o2,1,%o2
+ sll %o1,31,%g2
+ or %g2,%o2,%o2 ! %o2 = lo(n1n0 >> 1)
+ srl %o1,1,%o1 ! %o1 = hi(n1n0 >> 1)
+
+ and %o3,1,%g2
+ srl %o3,1,%g3 ! %g3 = floor(d / 2)
+ add %g3,%g2,%g3 ! %g3 = ceil(d / 2)
+
+ b LLp1
+ addxcc %o2,%o2,%o2
+
+LLplop: bcc LLn1
+ addxcc %o2,%o2,%o2
+LLp1: addx %o1,%o1,%o1
+ subcc %o1,%g3,%o4
+ bcc LLn2
+ addxcc %o2,%o2,%o2
+LLp2: addx %o1,%o1,%o1
+ subcc %o1,%g3,%o4
+ bcc LLn3
+ addxcc %o2,%o2,%o2
+LLp3: addx %o1,%o1,%o1
+ subcc %o1,%g3,%o4
+ bcc LLn4
+ addxcc %o2,%o2,%o2
+LLp4: addx %o1,%o1,%o1
+ addcc %g1,-1,%g1
+ bne LLplop
+ subcc %o1,%g3,%o4
+ bcc LLn5
+ addxcc %o2,%o2,%o2
+LLp5: add %o1,%o1,%o1 ! << 1
+ tst %g2
+ bne Oddp
+ add %o5,%o1,%o1
+ st %o1,[%o0]
+ retl
+ xnor %g0,%o2,%o0
+
+LLnlop: bcc LLp1
+ addxcc %o2,%o2,%o2
+LLn1: addx %o4,%o4,%o4
+ subcc %o4,%g3,%o1
+ bcc LLp2
+ addxcc %o2,%o2,%o2
+LLn2: addx %o4,%o4,%o4
+ subcc %o4,%g3,%o1
+ bcc LLp3
+ addxcc %o2,%o2,%o2
+LLn3: addx %o4,%o4,%o4
+ subcc %o4,%g3,%o1
+ bcc LLp4
+ addxcc %o2,%o2,%o2
+LLn4: addx %o4,%o4,%o4
+ addcc %g1,-1,%g1
+ bne LLnlop
+ subcc %o4,%g3,%o1
+ bcc LLp5
+ addxcc %o2,%o2,%o2
+LLn5: add %o4,%o4,%o4 ! << 1
+ tst %g2
+ bne Oddn
+ add %o5,%o4,%o4
+ st %o4,[%o0]
+ retl
+ xnor %g0,%o2,%o0
+
+Oddp: xnor %g0,%o2,%o2
+ ! q' in %o2. r' in %o1
+ addcc %o1,%o2,%o1
+ bcc LLp6
+ addx %o2,0,%o2
+ sub %o1,%o3,%o1
+LLp6: subcc %o1,%o3,%g0
+ bcs LLp7
+ subx %o2,-1,%o2
+ sub %o1,%o3,%o1
+LLp7: st %o1,[%o0]
+ retl
+ mov %o2,%o0
+
+Oddn: xnor %g0,%o2,%o2
+ ! q' in %o2. r' in %o4
+ addcc %o4,%o2,%o4
+ bcc LLn6
+ addx %o2,0,%o2
+ sub %o4,%o3,%o4
+LLn6: subcc %o4,%o3,%g0
+ bcs LLn7
+ subx %o2,-1,%o2
+ sub %o4,%o3,%o4
+LLn7: st %o4,[%o0]
+ retl
+ mov %o2,%o0
diff --git a/mpn/sparc32/v8/addmul_1.S b/mpn/sparc32/v8/addmul_1.S
new file mode 100644
index 000000000..fb9ea7cf0
--- /dev/null
+++ b/mpn/sparc32/v8/addmul_1.S
@@ -0,0 +1,124 @@
+! SPARC v8 __mpn_addmul_1 -- Multiply a limb vector with a limb and
+! add the result to a second limb vector.
+
+! Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP Library is free software; you can redistribute it and/or modify
+! it under the terms of the GNU Library General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or (at your
+! option) any later version.
+
+! The GNU MP Library 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 Library General Public
+! License for more details.
+
+! You should have received a copy of the GNU Library General Public License
+! along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+! MA 02111-1307, USA.
+
+
+! INPUT PARAMETERS
+! res_ptr o0
+! s1_ptr o1
+! size o2
+! s2_limb o3
+
+#include "sysdep.h"
+
+.text
+ .align 4
+ .global C_SYMBOL_NAME(__mpn_addmul_1)
+C_SYMBOL_NAME(__mpn_addmul_1):
+ orcc %g0,%g0,%g2
+ ld [%o1+0],%o4 ! 1
+
+ sll %o2,4,%g1
+ and %g1,(4-1)<<4,%g1
+#if PIC
+ mov %o7,%g4 ! Save return address register
+ call 1f
+ add %o7,LL-1f,%g3
+1: mov %g4,%o7 ! Restore return address register
+#else
+ sethi %hi(LL),%g3
+ or %g3,%lo(LL),%g3
+#endif
+ jmp %g3+%g1
+ nop
+LL:
+LL00: add %o0,-4,%o0
+ b Loop00 /* 4, 8, 12, ... */
+ add %o1,-4,%o1
+ nop
+LL01: b Loop01 /* 1, 5, 9, ... */
+ nop
+ nop
+ nop
+LL10: add %o0,-12,%o0 /* 2, 6, 10, ... */
+ b Loop10
+ add %o1,4,%o1
+ nop
+LL11: add %o0,-8,%o0 /* 3, 7, 11, ... */
+ b Loop11
+ add %o1,-8,%o1
+ nop
+
+1: addcc %g3,%g2,%g3 ! 1
+ ld [%o1+4],%o4 ! 2
+ rd %y,%g2 ! 1
+ addx %g0,%g2,%g2
+ ld [%o0+0],%g1 ! 2
+ addcc %g1,%g3,%g3
+ st %g3,[%o0+0] ! 1
+Loop00: umul %o4,%o3,%g3 ! 2
+ ld [%o0+4],%g1 ! 2
+ addxcc %g3,%g2,%g3 ! 2
+ ld [%o1+8],%o4 ! 3
+ rd %y,%g2 ! 2
+ addx %g0,%g2,%g2
+ nop
+ addcc %g1,%g3,%g3
+ st %g3,[%o0+4] ! 2
+Loop11: umul %o4,%o3,%g3 ! 3
+ addxcc %g3,%g2,%g3 ! 3
+ ld [%o1+12],%o4 ! 4
+ rd %y,%g2 ! 3
+ add %o1,16,%o1
+ addx %g0,%g2,%g2
+ ld [%o0+8],%g1 ! 2
+ addcc %g1,%g3,%g3
+ st %g3,[%o0+8] ! 3
+Loop10: umul %o4,%o3,%g3 ! 4
+ addxcc %g3,%g2,%g3 ! 4
+ ld [%o1+0],%o4 ! 1
+ rd %y,%g2 ! 4
+ addx %g0,%g2,%g2
+ ld [%o0+12],%g1 ! 2
+ addcc %g1,%g3,%g3
+ st %g3,[%o0+12] ! 4
+ add %o0,16,%o0
+ addx %g0,%g2,%g2
+Loop01: addcc %o2,-4,%o2
+ bg 1b
+ umul %o4,%o3,%g3 ! 1
+
+ addcc %g3,%g2,%g3 ! 4
+ rd %y,%g2 ! 4
+ addx %g0,%g2,%g2
+ ld [%o0+0],%g1 ! 2
+ addcc %g1,%g3,%g3
+ st %g3,[%o0+0] ! 4
+ addx %g0,%g2,%o0
+
+ retl
+ nop
+
+
+! umul, ld, addxcc, rd, st
+
+! umul, ld, addxcc, rd, ld, addcc, st, addx
+
diff --git a/mpn/sparc32/v8/mul_1.S b/mpn/sparc32/v8/mul_1.S
new file mode 100644
index 000000000..b641feb45
--- /dev/null
+++ b/mpn/sparc32/v8/mul_1.S
@@ -0,0 +1,99 @@
+! SPARC v8 __mpn_mul_1 -- Multiply a limb vector with a single limb and
+! store the product in a second limb vector.
+
+! Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP Library is free software; you can redistribute it and/or modify
+! it under the terms of the GNU Library General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or (at your
+! option) any later version.
+
+! The GNU MP Library 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 Library General Public
+! License for more details.
+
+! You should have received a copy of the GNU Library General Public License
+! along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+! MA 02111-1307, USA.
+
+
+! INPUT PARAMETERS
+! res_ptr o0
+! s1_ptr o1
+! size o2
+! s2_limb o3
+
+#include "sysdep.h"
+
+.text
+ .align 8
+ .global C_SYMBOL_NAME(__mpn_mul_1)
+C_SYMBOL_NAME(__mpn_mul_1):
+ sll %o2,4,%g1
+ and %g1,(4-1)<<4,%g1
+#if PIC
+ mov %o7,%g4 ! Save return address register
+ call 1f
+ add %o7,LL-1f,%g3
+1: mov %g4,%o7 ! Restore return address register
+#else
+ sethi %hi(LL),%g3
+ or %g3,%lo(LL),%g3
+#endif
+ jmp %g3+%g1
+ ld [%o1+0],%o4 ! 1
+LL:
+LL00: add %o0,-4,%o0
+ add %o1,-4,%o1
+ b Loop00 /* 4, 8, 12, ... */
+ orcc %g0,%g0,%g2
+LL01: b Loop01 /* 1, 5, 9, ... */
+ orcc %g0,%g0,%g2
+ nop
+ nop
+LL10: add %o0,-12,%o0 /* 2, 6, 10, ... */
+ add %o1,4,%o1
+ b Loop10
+ orcc %g0,%g0,%g2
+ nop
+LL11: add %o0,-8,%o0 /* 3, 7, 11, ... */
+ add %o1,-8,%o1
+ b Loop11
+ orcc %g0,%g0,%g2
+
+Loop: addcc %g3,%g2,%g3 ! 1
+ ld [%o1+4],%o4 ! 2
+ st %g3,[%o0+0] ! 1
+ rd %y,%g2 ! 1
+Loop00: umul %o4,%o3,%g3 ! 2
+ addxcc %g3,%g2,%g3 ! 2
+ ld [%o1+8],%o4 ! 3
+ st %g3,[%o0+4] ! 2
+ rd %y,%g2 ! 2
+Loop11: umul %o4,%o3,%g3 ! 3
+ addxcc %g3,%g2,%g3 ! 3
+ ld [%o1+12],%o4 ! 4
+ add %o1,16,%o1
+ st %g3,[%o0+8] ! 3
+ rd %y,%g2 ! 3
+Loop10: umul %o4,%o3,%g3 ! 4
+ addxcc %g3,%g2,%g3 ! 4
+ ld [%o1+0],%o4 ! 1
+ st %g3,[%o0+12] ! 4
+ add %o0,16,%o0
+ rd %y,%g2 ! 4
+ addx %g0,%g2,%g2
+Loop01: addcc %o2,-4,%o2
+ bg Loop
+ umul %o4,%o3,%g3 ! 1
+
+ addcc %g3,%g2,%g3 ! 4
+ st %g3,[%o0+0] ! 4
+ rd %y,%g2 ! 4
+
+ retl
+ addx %g0,%g2,%o0
diff --git a/mpn/sparc32/v8/submul_1.S b/mpn/sparc32/v8/submul_1.S
new file mode 100644
index 000000000..e40119d01
--- /dev/null
+++ b/mpn/sparc32/v8/submul_1.S
@@ -0,0 +1,58 @@
+! SPARC v8 __mpn_submul_1 -- Multiply a limb vector with a limb and
+! subtract the result from a second limb vector.
+
+! Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP Library is free software; you can redistribute it and/or modify
+! it under the terms of the GNU Library General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or (at your
+! option) any later version.
+
+! The GNU MP Library 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 Library General Public
+! License for more details.
+
+! You should have received a copy of the GNU Library General Public License
+! along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+! MA 02111-1307, USA.
+
+
+! INPUT PARAMETERS
+! res_ptr o0
+! s1_ptr o1
+! size o2
+! s2_limb o3
+
+#include "sysdep.h"
+
+.text
+ .align 4
+ .global C_SYMBOL_NAME(__mpn_submul_1)
+C_SYMBOL_NAME(__mpn_submul_1):
+ sub %g0,%o2,%o2 ! negate ...
+ sll %o2,2,%o2 ! ... and scale size
+ sub %o1,%o2,%o1 ! o1 is offset s1_ptr
+ sub %o0,%o2,%g1 ! g1 is offset res_ptr
+
+ mov 0,%o0 ! clear cy_limb
+
+Loop: ld [%o1+%o2],%o4
+ ld [%g1+%o2],%g2
+ umul %o4,%o3,%o5
+ rd %y,%g3
+ addcc %o5,%o0,%o5
+ addx %g3,0,%o0
+ subcc %g2,%o5,%g2
+ addx %o0,0,%o0
+ st %g2,[%g1+%o2]
+
+ addcc %o2,4,%o2
+ bne Loop
+ nop
+
+ retl
+ nop
diff --git a/mpn/sparc32/v8/supersparc/udiv.S b/mpn/sparc32/v8/supersparc/udiv.S
new file mode 100644
index 000000000..ed688ee1d
--- /dev/null
+++ b/mpn/sparc32/v8/supersparc/udiv.S
@@ -0,0 +1,109 @@
+! SuperSPARC __udiv_qrnnd division support, used from longlong.h.
+! This is for SuperSPARC only, to compensate for its semi-functional
+! udiv instruction.
+
+! Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP Library is free software; you can redistribute it and/or modify
+! it under the terms of the GNU Library General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or (at your
+! option) any later version.
+
+! The GNU MP Library 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 Library General Public
+! License for more details.
+
+! You should have received a copy of the GNU Library General Public License
+! along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+! MA 02111-1307, USA.
+
+
+! INPUT PARAMETERS
+! rem_ptr i0
+! n1 i1
+! n0 i2
+! d i3
+
+#include "sysdep.h"
+#undef ret /* Kludge for glibc */
+
+ .text
+ .align 8
+LC0: .double 0r4294967296
+LC1: .double 0r2147483648
+
+ .align 4
+ .global C_SYMBOL_NAME(__udiv_qrnnd)
+C_SYMBOL_NAME(__udiv_qrnnd):
+ !#PROLOGUE# 0
+ save %sp,-104,%sp
+ !#PROLOGUE# 1
+ st %i1,[%fp-8]
+ ld [%fp-8],%f10
+ sethi %hi(LC0),%o7
+ fitod %f10,%f4
+ ldd [%o7+%lo(LC0)],%f8
+ cmp %i1,0
+ bge L248
+ mov %i0,%i5
+ faddd %f4,%f8,%f4
+L248:
+ st %i2,[%fp-8]
+ ld [%fp-8],%f10
+ fmuld %f4,%f8,%f6
+ cmp %i2,0
+ bge L249
+ fitod %f10,%f2
+ faddd %f2,%f8,%f2
+L249:
+ st %i3,[%fp-8]
+ faddd %f6,%f2,%f2
+ ld [%fp-8],%f10
+ cmp %i3,0
+ bge L250
+ fitod %f10,%f4
+ faddd %f4,%f8,%f4
+L250:
+ fdivd %f2,%f4,%f2
+ sethi %hi(LC1),%o7
+ ldd [%o7+%lo(LC1)],%f4
+ fcmped %f2,%f4
+ nop
+ fbge,a L251
+ fsubd %f2,%f4,%f2
+ fdtoi %f2,%f2
+ st %f2,[%fp-8]
+ b L252
+ ld [%fp-8],%i4
+L251:
+ fdtoi %f2,%f2
+ st %f2,[%fp-8]
+ ld [%fp-8],%i4
+ sethi %hi(-2147483648),%g2
+ xor %i4,%g2,%i4
+L252:
+ umul %i3,%i4,%g3
+ rd %y,%i0
+ subcc %i2,%g3,%o7
+ subxcc %i1,%i0,%g0
+ be L253
+ cmp %o7,%i3
+
+ add %i4,-1,%i0
+ add %o7,%i3,%o7
+ st %o7,[%i5]
+ ret
+ restore
+L253:
+ blu L246
+ mov %i4,%i0
+ add %i4,1,%i0
+ sub %o7,%i3,%o7
+L246:
+ st %o7,[%i5]
+ ret
+ restore
diff --git a/mpn/sparc64/add_n.s b/mpn/sparc64/add_n.s
new file mode 100644
index 000000000..01d1f4956
--- /dev/null
+++ b/mpn/sparc64/add_n.s
@@ -0,0 +1,58 @@
+! SPARC v9 __mpn_add_n -- Add two limb vectors of the same length > 0 and store
+! sum in a third limb vector.
+
+! Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP Library is free software; you can redistribute it and/or modify
+! it under the terms of the GNU Library General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or (at your
+! option) any later version.
+
+! The GNU MP Library 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 Library General Public
+! License for more details.
+
+! You should have received a copy of the GNU Library General Public License
+! along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+! MA 02111-1307, USA.
+
+
+! INPUT PARAMETERS
+! res_ptr %o0
+! s1_ptr %o1
+! s2_ptr %o2
+! size %o3
+
+.section ".text"
+ .align 4
+ .global __mpn_add_n
+ .type __mpn_add_n,#function
+ .proc 04
+__mpn_add_n:
+ sub %g0,%o3,%g3
+ sllx %o3,3,%g1
+ add %o1,%g1,%o1 ! make s1_ptr point at end
+ add %o2,%g1,%o2 ! make s2_ptr point at end
+ add %o0,%g1,%o0 ! make res_ptr point at end
+ mov 0,%o4 ! clear carry variable
+ sllx %g3,3,%o5 ! compute initial address index
+
+.Loop: ldx [%o2+%o5],%g1 ! load s2 limb
+ add %g3,1,%g3 ! increment loop count
+ ldx [%o1+%o5],%g2 ! load s1 limb
+ addcc %g1,%o4,%g1 ! add s2 limb and carry variable
+ movcc %xcc,0,%o4 ! if carry-out, o4 was 1; clear it
+ addcc %g1,%g2,%g1 ! add s1 limb to sum
+ stx %g1,[%o0+%o5] ! store result
+ add %o5,8,%o5 ! increment address index
+ brnz,pt %g3,.Loop
+ movcs %xcc,1,%o4 ! if s1 add gave carry, record it
+
+ retl
+ mov %o4,%o0
+.LLfe1:
+ .size __mpn_add_n,.LLfe1-__mpn_add_n
diff --git a/mpn/sparc64/addmul_1.s b/mpn/sparc64/addmul_1.s
new file mode 100644
index 000000000..8d8639080
--- /dev/null
+++ b/mpn/sparc64/addmul_1.s
@@ -0,0 +1,89 @@
+! SPARC v9 __mpn_addmul_1 -- Multiply a limb vector with a single limb and
+! add the product to a second limb vector.
+
+! Copyright (C) 1996 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP Library is free software; you can redistribute it and/or modify
+! it under the terms of the GNU Library General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or (at your
+! option) any later version.
+
+! The GNU MP Library 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 Library General Public
+! License for more details.
+
+! You should have received a copy of the GNU Library General Public License
+! along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+! MA 02111-1307, USA.
+
+
+! INPUT PARAMETERS
+! res_ptr o0
+! s1_ptr o1
+! size o2
+! s2_limb o3
+
+.section ".text"
+ .align 4
+ .global __mpn_addmul_1
+ .type __mpn_addmul_1,#function
+ .proc 016
+__mpn_addmul_1:
+ !#PROLOGUE# 0
+ save %sp,-160,%sp
+ !#PROLOGUE# 1
+ sub %g0,%i2,%o7
+ sllx %o7,3,%g5
+ sub %i1,%g5,%o3
+ sub %i0,%g5,%o4
+ mov 0,%o0 ! zero cy_limb
+
+ srl %i3,0,%o1 ! extract low 32 bits of s2_limb
+ srlx %i3,32,%i3 ! extract high 32 bits of s2_limb
+ mov 1,%o2
+ sllx %o2,32,%o2 ! o2 = 0x100000000
+
+ ! hi !
+ ! mid-1 !
+ ! mid-2 !
+ ! lo !
+.Loop:
+ sllx %o7,3,%g1
+ ldx [%o3+%g1],%g5
+ srl %g5,0,%i0 ! zero hi bits
+ srlx %g5,32,%g5
+ mulx %o1,%i0,%i4 ! lo product
+ mulx %i3,%i0,%i1 ! mid-1 product
+ mulx %o1,%g5,%l2 ! mid-2 product
+ mulx %i3,%g5,%i5 ! hi product
+ srlx %i4,32,%i0 ! extract high 32 bits of lo product...
+ add %i1,%i0,%i1 ! ...and add it to the mid-1 product
+ addcc %i1,%l2,%i1 ! add mid products
+ mov 0,%l0 ! we need the carry from that add...
+ movcs %xcc,%o2,%l0 ! ...compute it and...
+ add %i5,%l0,%i5 ! ...add to bit 32 of the hi product
+ sllx %i1,32,%i0 ! align low bits of mid product
+ srl %i4,0,%g5 ! zero high 32 bits of lo product
+ add %i0,%g5,%i0 ! combine into low 64 bits of result
+ srlx %i1,32,%i1 ! extract high bits of mid product...
+ add %i5,%i1,%i1 ! ...and add them to the high result
+ addcc %i0,%o0,%i0 ! add cy_limb to low 64 bits of result
+ mov 0,%g5
+ movcs %xcc,1,%g5
+ add %o7,1,%o7
+ ldx [%o4+%g1],%l1
+ addcc %l1,%i0,%i0
+ movcs %xcc,1,%g5
+ stx %i0,[%o4+%g1]
+ brnz %o7,.Loop
+ add %i1,%g5,%o0 ! compute new cy_limb
+
+ mov %o0,%i0
+ ret
+ restore
+.LLfe1:
+ .size __mpn_addmul_1,.LLfe1-__mpn_addmul_1
diff --git a/mpn/sparc64/gmp-mparam.h b/mpn/sparc64/gmp-mparam.h
new file mode 100644
index 000000000..a3c66974d
--- /dev/null
+++ b/mpn/sparc64/gmp-mparam.h
@@ -0,0 +1,27 @@
+/* gmp-mparam.h -- Compiler/machine parameter header file.
+
+Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#define BITS_PER_MP_LIMB 64
+#define BYTES_PER_MP_LIMB 8
+#define BITS_PER_LONGINT 64
+#define BITS_PER_INT 32
+#define BITS_PER_SHORTINT 16
+#define BITS_PER_CHAR 8
diff --git a/mpn/sparc64/lshift.s b/mpn/sparc64/lshift.s
new file mode 100644
index 000000000..ad1f667fa
--- /dev/null
+++ b/mpn/sparc64/lshift.s
@@ -0,0 +1,96 @@
+! SPARC v9 __mpn_lshift --
+
+! Copyright (C) 1996 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP Library is free software; you can redistribute it and/or modify
+! it under the terms of the GNU Library General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or (at your
+! option) any later version.
+
+! The GNU MP Library 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 Library General Public
+! License for more details.
+
+! You should have received a copy of the GNU Library General Public License
+! along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+! MA 02111-1307, USA.
+
+
+! INPUT PARAMETERS
+! res_ptr %o0
+! src_ptr %o1
+! size %o2
+! cnt %o3
+
+.section ".text"
+ .align 4
+ .global __mpn_lshift
+ .type __mpn_lshift,#function
+ .proc 04
+__mpn_lshift:
+ sllx %o2,3,%g1
+ add %o1,%g1,%o1 ! make %o1 point at end of src
+ ldx [%o1-8],%g2 ! load first limb
+ sub %g0,%o3,%o5 ! negate shift count
+ add %o0,%g1,%o0 ! make %o0 point at end of res
+ add %o2,-1,%o2
+ and %o2,4-1,%g4 ! number of limbs in first loop
+ srlx %g2,%o5,%g1 ! compute function result
+ brz,pn %g4,.L0 ! if multiple of 4 limbs, skip first loop
+ stx %g1,[%sp+80]
+
+ sub %o2,%g4,%o2 ! adjust count for main loop
+
+.Loop0: ldx [%o1-16],%g3
+ add %o0,-8,%o0
+ add %o1,-8,%o1
+ add %g4,-1,%g4
+ sllx %g2,%o3,%o4
+ srlx %g3,%o5,%g1
+ mov %g3,%g2
+ or %o4,%g1,%o4
+ brnz,pt %g4,.Loop0
+ stx %o4,[%o0+0]
+
+.L0: brz,pn %o2,.Lend
+ nop
+
+.Loop: ldx [%o1-16],%g3
+ add %o0,-32,%o0
+ add %o2,-4,%o2
+ sllx %g2,%o3,%o4
+ srlx %g3,%o5,%g1
+
+ ldx [%o1-24],%g2
+ sllx %g3,%o3,%g4
+ or %o4,%g1,%o4
+ stx %o4,[%o0+24]
+ srlx %g2,%o5,%g1
+
+ ldx [%o1-32],%g3
+ sllx %g2,%o3,%o4
+ or %g4,%g1,%g4
+ stx %g4,[%o0+16]
+ srlx %g3,%o5,%g1
+
+ ldx [%o1-40],%g2
+ sllx %g3,%o3,%g4
+ or %o4,%g1,%o4
+ stx %o4,[%o0+8]
+ srlx %g2,%o5,%g1
+
+ add %o1,-32,%o1
+ or %g4,%g1,%g4
+ brnz,pt %o2,.Loop
+ stx %g4,[%o0+0]
+
+.Lend: sllx %g2,%o3,%g2
+ stx %g2,[%o0-8]
+ retl
+ ldx [%sp+80],%o0
+.LLfe1:
+ .size __mpn_lshift,.LLfe1-__mpn_lshift
diff --git a/mpn/sparc64/mul_1.s b/mpn/sparc64/mul_1.s
new file mode 100644
index 000000000..91d6eb01b
--- /dev/null
+++ b/mpn/sparc64/mul_1.s
@@ -0,0 +1,86 @@
+! SPARC v9 __mpn_mul_1 -- Multiply a limb vector with a single limb and
+! store the product in a second limb vector.
+
+! Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP Library is free software; you can redistribute it and/or modify
+! it under the terms of the GNU Library General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or (at your
+! option) any later version.
+
+! The GNU MP Library 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 Library General Public
+! License for more details.
+
+! You should have received a copy of the GNU Library General Public License
+! along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+! MA 02111-1307, USA.
+
+
+! INPUT PARAMETERS
+! res_ptr o0
+! s1_ptr o1
+! size o2
+! s2_limb o3
+
+.section ".text"
+ .align 4
+ .global __mpn_mul_1
+ .type __mpn_mul_1,#function
+ .proc 016
+__mpn_mul_1:
+ !#PROLOGUE# 0
+ save %sp,-160,%sp
+ !#PROLOGUE# 1
+ sub %g0,%i2,%o7
+ sllx %o7,3,%g5
+ sub %i1,%g5,%o3
+ sub %i0,%g5,%o4
+ mov 0,%o0 ! zero cy_limb
+
+ srl %i3,0,%o1 ! extract low 32 bits of s2_limb
+ srlx %i3,32,%i3 ! extract high 32 bits of s2_limb
+ mov 1,%o2
+ sllx %o2,32,%o2 ! o2 = 0x100000000
+
+ ! hi !
+ ! mid-1 !
+ ! mid-2 !
+ ! lo !
+.Loop:
+ sllx %o7,3,%g1
+ ldx [%o3+%g1],%g5
+ srl %g5,0,%i0 ! zero hi bits
+ srlx %g5,32,%g5
+ mulx %o1,%i0,%i4 ! lo product
+ mulx %i3,%i0,%i1 ! mid-1 product
+ mulx %o1,%g5,%l2 ! mid-2 product
+ mulx %i3,%g5,%i5 ! hi product
+ srlx %i4,32,%i0 ! extract high 32 bits of lo product...
+ add %i1,%i0,%i1 ! ...and add it to the mid-1 product
+ addcc %i1,%l2,%i1 ! add mid products
+ mov 0,%l0 ! we need the carry from that add...
+ movcs %xcc,%o2,%l0 ! ...compute it and...
+ add %i5,%l0,%i5 ! ...add to bit 32 of the hi product
+ sllx %i1,32,%i0 ! align low bits of mid product
+ srl %i4,0,%g5 ! zero high 32 bits of lo product
+ add %i0,%g5,%i0 ! combine into low 64 bits of result
+ srlx %i1,32,%i1 ! extract high bits of mid product...
+ add %i5,%i1,%i1 ! ...and add them to the high result
+ addcc %i0,%o0,%i0 ! add cy_limb to low 64 bits of result
+ mov 0,%g5
+ movcs %xcc,1,%g5
+ add %o7,1,%o7
+ stx %i0,[%o4+%g1]
+ brnz %o7,.Loop
+ add %i1,%g5,%o0 ! compute new cy_limb
+
+ mov %o0,%i0
+ ret
+ restore
+.LLfe1:
+ .size __mpn_mul_1,.LLfe1-__mpn_mul_1
diff --git a/mpn/sparc64/rshift.s b/mpn/sparc64/rshift.s
new file mode 100644
index 000000000..ff6a38016
--- /dev/null
+++ b/mpn/sparc64/rshift.s
@@ -0,0 +1,93 @@
+! SPARC v9 __mpn_rshift --
+
+! Copyright (C) 1996 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP Library is free software; you can redistribute it and/or modify
+! it under the terms of the GNU Library General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or (at your
+! option) any later version.
+
+! The GNU MP Library 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 Library General Public
+! License for more details.
+
+! You should have received a copy of the GNU Library General Public License
+! along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+! MA 02111-1307, USA.
+
+
+! INPUT PARAMETERS
+! res_ptr %o0
+! src_ptr %o1
+! size %o2
+! cnt %o3
+
+.section ".text"
+ .align 4
+ .global __mpn_rshift
+ .type __mpn_rshift,#function
+ .proc 04
+__mpn_rshift:
+ ldx [%o1],%g2 ! load first limb
+ sub %g0,%o3,%o5 ! negate shift count
+ add %o2,-1,%o2
+ and %o2,4-1,%g4 ! number of limbs in first loop
+ sllx %g2,%o5,%g1 ! compute function result
+ brz,pn %g4,.L0 ! if multiple of 4 limbs, skip first loop
+ stx %g1,[%sp+80]
+
+ sub %o2,%g4,%o2 ! adjust count for main loop
+
+.Loop0: ldx [%o1+8],%g3
+ add %o0,8,%o0
+ add %o1,8,%o1
+ add %g4,-1,%g4
+ srlx %g2,%o3,%o4
+ sllx %g3,%o5,%g1
+ mov %g3,%g2
+ or %o4,%g1,%o4
+ brnz,pt %g4,.Loop0
+ stx %o4,[%o0-8]
+
+.L0: brz,pn %o2,.Lend
+ nop
+
+.Loop: ldx [%o1+8],%g3
+ add %o0,32,%o0
+ add %o2,-4,%o2
+ srlx %g2,%o3,%o4
+ sllx %g3,%o5,%g1
+
+ ldx [%o1+16],%g2
+ srlx %g3,%o3,%g4
+ or %o4,%g1,%o4
+ stx %o4,[%o0-32]
+ sllx %g2,%o5,%g1
+
+ ldx [%o1+24],%g3
+ srlx %g2,%o3,%o4
+ or %g4,%g1,%g4
+ stx %g4,[%o0-24]
+ sllx %g3,%o5,%g1
+
+ ldx [%o1+32],%g2
+ srlx %g3,%o3,%g4
+ or %o4,%g1,%o4
+ stx %o4,[%o0-16]
+ sllx %g2,%o5,%g1
+
+ add %o1,32,%o1
+ or %g4,%g1,%g4
+ brnz %o2,.Loop
+ stx %g4,[%o0-8]
+
+.Lend: srlx %g2,%o3,%g2
+ stx %g2,[%o0-0]
+ retl
+ ldx [%sp+80],%o0
+.LLfe1:
+ .size __mpn_rshift,.LLfe1-__mpn_rshift
diff --git a/mpn/sparc64/sub_n.s b/mpn/sparc64/sub_n.s
new file mode 100644
index 000000000..d4842b8cd
--- /dev/null
+++ b/mpn/sparc64/sub_n.s
@@ -0,0 +1,58 @@
+! SPARC v9 __mpn_sub_n -- Subtract two limb vectors of the same length > 0 and
+! store difference in a third limb vector.
+
+! Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP Library is free software; you can redistribute it and/or modify
+! it under the terms of the GNU Library General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or (at your
+! option) any later version.
+
+! The GNU MP Library 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 Library General Public
+! License for more details.
+
+! You should have received a copy of the GNU Library General Public License
+! along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+! MA 02111-1307, USA.
+
+
+! INPUT PARAMETERS
+! res_ptr %o0
+! s1_ptr %o1
+! s2_ptr %o2
+! size %o3
+
+.section ".text"
+ .align 4
+ .global __mpn_sub_n
+ .type __mpn_sub_n,#function
+ .proc 04
+__mpn_sub_n:
+ sub %g0,%o3,%g3
+ sllx %o3,3,%g1
+ add %o1,%g1,%o1 ! make s1_ptr point at end
+ add %o2,%g1,%o2 ! make s2_ptr point at end
+ add %o0,%g1,%o0 ! make res_ptr point at end
+ mov 0,%o4 ! clear carry variable
+ sllx %g3,3,%o5 ! compute initial address index
+
+.Loop: ldx [%o2+%o5],%g1 ! load s2 limb
+ add %g3,1,%g3 ! increment loop count
+ ldx [%o1+%o5],%g2 ! load s1 limb
+ addcc %g1,%o4,%g1 ! add s2 limb and carry variable
+ movcc %xcc,0,%o4 ! if carry-out, o4 was 1; clear it
+ subcc %g1,%g2,%g1 ! subtract s1 limb from sum
+ stx %g1,[%o0+%o5] ! store result
+ add %o5,8,%o5 ! increment address index
+ brnz,pt %g3,.Loop
+ movcs %xcc,1,%o4 ! if s1 subtract gave carry, record it
+
+ retl
+ mov %o4,%o0
+.LLfe1:
+ .size __mpn_sub_n,.LLfe1-__mpn_sub_n
diff --git a/mpn/sparc64/submul_1.s b/mpn/sparc64/submul_1.s
new file mode 100644
index 000000000..e79624347
--- /dev/null
+++ b/mpn/sparc64/submul_1.s
@@ -0,0 +1,89 @@
+! SPARC v9 __mpn_submul_1 -- Multiply a limb vector with a single limb and
+! subtract the product from a second limb vector.
+
+! Copyright (C) 1996 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP Library is free software; you can redistribute it and/or modify
+! it under the terms of the GNU Library General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or (at your
+! option) any later version.
+
+! The GNU MP Library 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 Library General Public
+! License for more details.
+
+! You should have received a copy of the GNU Library General Public License
+! along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+! MA 02111-1307, USA.
+
+
+! INPUT PARAMETERS
+! res_ptr o0
+! s1_ptr o1
+! size o2
+! s2_limb o3
+
+.section ".text"
+ .align 4
+ .global __mpn_submul_1
+ .type __mpn_submul_1,#function
+ .proc 016
+__mpn_submul_1:
+ !#PROLOGUE# 0
+ save %sp,-160,%sp
+ !#PROLOGUE# 1
+ sub %g0,%i2,%o7
+ sllx %o7,3,%g5
+ sub %i1,%g5,%o3
+ sub %i0,%g5,%o4
+ mov 0,%o0 ! zero cy_limb
+
+ srl %i3,0,%o1 ! extract low 32 bits of s2_limb
+ srlx %i3,32,%i3 ! extract high 32 bits of s2_limb
+ mov 1,%o2
+ sllx %o2,32,%o2 ! o2 = 0x100000000
+
+ ! hi !
+ ! mid-1 !
+ ! mid-2 !
+ ! lo !
+.Loop:
+ sllx %o7,3,%g1
+ ldx [%o3+%g1],%g5
+ srl %g5,0,%i0 ! zero hi bits
+ srlx %g5,32,%g5
+ mulx %o1,%i0,%i4 ! lo product
+ mulx %i3,%i0,%i1 ! mid-1 product
+ mulx %o1,%g5,%l2 ! mid-2 product
+ mulx %i3,%g5,%i5 ! hi product
+ srlx %i4,32,%i0 ! extract high 32 bits of lo product...
+ add %i1,%i0,%i1 ! ...and add it to the mid-1 product
+ addcc %i1,%l2,%i1 ! add mid products
+ mov 0,%l0 ! we need the carry from that add...
+ movcs %xcc,%o2,%l0 ! ...compute it and...
+ add %i5,%l0,%i5 ! ...add to bit 32 of the hi product
+ sllx %i1,32,%i0 ! align low bits of mid product
+ srl %i4,0,%g5 ! zero high 32 bits of lo product
+ add %i0,%g5,%i0 ! combine into low 64 bits of result
+ srlx %i1,32,%i1 ! extract high bits of mid product...
+ add %i5,%i1,%i1 ! ...and add them to the high result
+ addcc %i0,%o0,%i0 ! add cy_limb to low 64 bits of result
+ mov 0,%g5
+ movcs %xcc,1,%g5
+ add %o7,1,%o7
+ ldx [%o4+%g1],%l1
+ subcc %l1,%i0,%i0
+ movcs %xcc,1,%g5
+ stx %i0,[%o4+%g1]
+ brnz %o7,.Loop
+ add %i1,%g5,%o0 ! compute new cy_limb
+
+ mov %o0,%i0
+ ret
+ restore
+.LLfe1:
+ .size __mpn_submul_1,.LLfe1-__mpn_submul_1
diff --git a/mpn/sysv.h b/mpn/sysv.h
new file mode 100644
index 000000000..87c250902
--- /dev/null
+++ b/mpn/sysv.h
@@ -0,0 +1 @@
+#define C_SYMBOL_NAME(name) name
diff --git a/mpn/tests/add_n.c b/mpn/tests/add_n.c
new file mode 100644
index 000000000..c27d34710
--- /dev/null
+++ b/mpn/tests/add_n.c
@@ -0,0 +1,211 @@
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+
+#ifndef USG
+#include <sys/time.h>
+#include <sys/resource.h>
+
+unsigned long
+cputime ()
+{
+ struct rusage rus;
+
+ getrusage (0, &rus);
+ return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000;
+}
+#else
+#include <time.h>
+
+#ifndef CLOCKS_PER_SEC
+#define CLOCKS_PER_SEC 1000000
+#endif
+
+#if CLOCKS_PER_SEC >= 10000
+#define CLOCK_TO_MILLISEC(cl) ((cl) / (CLOCKS_PER_SEC / 1000))
+#else
+#define CLOCK_TO_MILLISEC(cl) ((cl) * 1000 / CLOCKS_PER_SEC)
+#endif
+
+unsigned long
+cputime ()
+{
+ return CLOCK_TO_MILLISEC (clock ());
+}
+#endif
+
+#define M * 1000000
+
+#ifndef CLOCK
+#if defined (__m88k__)
+#define CLOCK 20 M
+#elif defined (__i386__)
+#define CLOCK (16.666667 M)
+#elif defined (__m68k__)
+#define CLOCK (20 M)
+#elif defined (_IBMR2)
+#define CLOCK (25 M)
+#elif defined (__sparc__)
+#define CLOCK (20 M)
+#elif defined (__sun__)
+#define CLOCK (20 M)
+#elif defined (__mips)
+#define CLOCK (40 M)
+#elif defined (__hppa__)
+#define CLOCK (50 M)
+#elif defined (__alpha)
+#define CLOCK (133 M)
+#else
+#error "Don't know CLOCK of your machine"
+#endif
+#endif
+
+#ifndef OPS
+#define OPS 10000000
+#endif
+#ifndef SIZE
+#define SIZE 328
+#endif
+#ifndef TIMES
+#define TIMES OPS/SIZE
+#else
+#undef OPS
+#define OPS (SIZE*TIMES)
+#endif
+
+
+mp_limb_t
+#if __STDC__
+refmpn_add_n (mp_ptr res_ptr,
+ mp_srcptr s1_ptr, mp_srcptr s2_ptr, mp_size_t size)
+#else
+refmpn_add_n (res_ptr, s1_ptr, s2_ptr, size)
+ register mp_ptr res_ptr;
+ register mp_srcptr s1_ptr;
+ register mp_srcptr s2_ptr;
+ mp_size_t size;
+#endif
+{
+ register mp_limb_t x, y, cy;
+ register mp_size_t j;
+
+ /* The loop counter and index J goes from -SIZE to -1. This way
+ the loop becomes faster. */
+ j = -size;
+
+ /* Offset the base pointers to compensate for the negative indices. */
+ s1_ptr -= j;
+ s2_ptr -= j;
+ res_ptr -= j;
+
+ cy = 0;
+ do
+ {
+ y = s2_ptr[j];
+ x = s1_ptr[j];
+ y += cy; /* add previous carry to one addend */
+ cy = (y < cy); /* get out carry from that addition */
+ y = x + y; /* add other addend */
+ cy = (y < x) + cy; /* get out carry from that add, combine */
+ res_ptr[j] = y;
+ }
+ while (++j != 0);
+
+ return cy;
+}
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ mp_limb_t s1[SIZE];
+ mp_limb_t s2[SIZE];
+ mp_limb_t dx[SIZE+1];
+ mp_limb_t dy[SIZE+1];
+ int cyx, cyy;
+ int i;
+ long t0, t;
+ int test;
+ mp_size_t size;
+
+ for (test = 0; ; test++)
+ {
+#ifdef RANDOM
+ size = (random () % SIZE + 1);
+#else
+ size = SIZE;
+#endif
+
+ mpn_random2 (s1, size);
+ mpn_random2 (s2, size);
+
+ dx[size] = 0x12345678;
+ dy[size] = 0x12345678;
+
+#ifdef PRINT
+ mpn_print (s1, size);
+ mpn_print (s2, size);
+#endif
+ t0 = cputime();
+ for (i = 0; i < TIMES; i++)
+ cyx = refmpn_add_n (dx, s1, s2, size);
+ t = cputime() - t0;
+#if TIMES != 1
+ printf ("refmpn_add_n: %ldms (%.2f cycles/limb)\n",
+ t,
+ ((double) t * CLOCK) / (OPS * 1000.0));
+#endif
+#ifdef PRINT
+ printf ("%d ", cyx); mpn_print (dx, size);
+#endif
+
+ t0 = cputime();
+ for (i = 0; i < TIMES; i++)
+ cyx = mpn_add_n (dx, s1, s2, size);
+ t = cputime() - t0;
+#if TIMES != 1
+ printf ("mpn_add_n: %ldms (%.2f cycles/limb)\n",
+ t,
+ ((double) t * CLOCK) / (OPS * 1000.0));
+#endif
+#ifdef PRINT
+ printf ("%d ", cyx); mpn_print (dx, size);
+#endif
+
+#ifndef NOCHECK
+ /* Put garbage in the destination. */
+ for (i = 0; i < size; i++)
+ {
+ dx[i] = 0x7654321;
+ dy[i] = 0x1234567;
+ }
+
+ cyx = refmpn_add_n (dx, s1, s2, size);
+ cyy = mpn_add_n (dy, s1, s2, size);
+ if (cyx != cyy || mpn_cmp (dx, dy, size) != 0
+ || dx[size] != 0x12345678 || dy[size] != 0x12345678)
+ {
+#ifndef PRINT
+ printf ("%d ", cyx); mpn_print (dx, size);
+ printf ("%d ", cyy); mpn_print (dy, size);
+#endif
+ abort();
+ }
+#endif
+ }
+}
+
+mpn_print (mp_ptr p, mp_size_t size)
+{
+ mp_size_t i;
+
+ for (i = size - 1; i >= 0; i--)
+ {
+ printf ("%0*lX", (int) (2 * sizeof(mp_limb_t)), p[i]);
+#ifdef SPACE
+ if (i != 0)
+ printf (" ");
+#endif
+ }
+ puts ("");
+}
diff --git a/mpn/tests/addmul_1.c b/mpn/tests/addmul_1.c
new file mode 100644
index 000000000..23952a1cc
--- /dev/null
+++ b/mpn/tests/addmul_1.c
@@ -0,0 +1,223 @@
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+#ifndef USG
+#include <sys/time.h>
+#include <sys/resource.h>
+
+unsigned long
+cputime ()
+{
+ struct rusage rus;
+
+ getrusage (0, &rus);
+ return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000;
+}
+#else
+#include <time.h>
+
+#ifndef CLOCKS_PER_SEC
+#define CLOCKS_PER_SEC 1000000
+#endif
+
+#if CLOCKS_PER_SEC >= 10000
+#define CLOCK_TO_MILLISEC(cl) ((cl) / (CLOCKS_PER_SEC / 1000))
+#else
+#define CLOCK_TO_MILLISEC(cl) ((cl) * 1000 / CLOCKS_PER_SEC)
+#endif
+
+unsigned long
+cputime ()
+{
+ return CLOCK_TO_MILLISEC (clock ());
+}
+#endif
+
+#define M * 1000000
+
+#ifndef CLOCK
+#if defined (__m88k__)
+#define CLOCK 20 M
+#elif defined (__i386__)
+#define CLOCK (16.666667 M)
+#elif defined (__m68k__)
+#define CLOCK (20 M)
+#elif defined (_IBMR2)
+#define CLOCK (25 M)
+#elif defined (__sparc__)
+#define CLOCK (20 M)
+#elif defined (__sun__)
+#define CLOCK (20 M)
+#elif defined (__mips)
+#define CLOCK (40 M)
+#elif defined (__hppa__)
+#define CLOCK (50 M)
+#elif defined (__alpha)
+#define CLOCK (133 M)
+#else
+#error "Don't know CLOCK of your machine"
+#endif
+#endif
+
+#ifndef OPS
+#define OPS 20000000
+#endif
+#ifndef SIZE
+#define SIZE 496
+#endif
+#ifndef TIMES
+#define TIMES OPS/SIZE
+#else
+#undef OPS
+#define OPS (SIZE*TIMES)
+#endif
+
+mp_limb_t
+refmpn_addmul_1 (res_ptr, s1_ptr, s1_size, s2_limb)
+ register mp_ptr res_ptr;
+ register mp_srcptr s1_ptr;
+ mp_size_t s1_size;
+ register mp_limb_t s2_limb;
+{
+ register mp_limb_t cy_limb;
+ register mp_size_t j;
+ register mp_limb_t prod_high, prod_low;
+ register mp_limb_t x;
+
+ /* The loop counter and index J goes from -SIZE to -1. This way
+ the loop becomes faster. */
+ j = -s1_size;
+
+ /* Offset the base pointers to compensate for the negative indices. */
+ res_ptr -= j;
+ s1_ptr -= j;
+
+ cy_limb = 0;
+ do
+ {
+ umul_ppmm (prod_high, prod_low, s1_ptr[j], s2_limb);
+
+ prod_low += cy_limb;
+ cy_limb = (prod_low < cy_limb) + prod_high;
+
+ x = res_ptr[j];
+ prod_low = x + prod_low;
+ cy_limb += (prod_low < x);
+ res_ptr[j] = prod_low;
+ }
+ while (++j != 0);
+
+ return cy_limb;
+}
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ mp_limb_t s1[SIZE];
+ mp_limb_t dx[SIZE+2];
+ mp_limb_t dy[SIZE+2];
+ mp_limb_t cyx, cyy;
+ int i;
+ long t0, t;
+ int test;
+ mp_limb_t xlimb;
+ mp_size_t size;
+ double cyc;
+
+ for (test = 0; ; test++)
+ {
+#ifdef RANDOM
+ size = (random () % SIZE + 1);
+#else
+ size = SIZE;
+#endif
+
+ mpn_random2 (s1, size);
+ mpn_random2 (dy+1, size);
+
+ if (random () % 0x100 == 0)
+ xlimb = 0;
+ else
+ mpn_random2 (&xlimb, 1);
+
+ dy[size+1] = 0x12345678;
+ dy[0] = 0x87654321;
+
+#if defined (PRINT) || defined (XPRINT)
+ printf ("xlimb=%*lX\n", (int) (2 * sizeof(mp_limb_t)), xlimb);
+#endif
+#ifdef PRINT
+ mpn_print (dy+1, size);
+ mpn_print (s1, size);
+#endif
+
+ MPN_COPY (dx, dy, size+2);
+ t0 = cputime();
+ for (i = 0; i < TIMES; i++)
+ cyx = refmpn_addmul_1 (dx+1, s1, size, xlimb);
+ t = cputime() - t0;
+#if TIMES != 1
+ cyc = ((double) t * CLOCK) / (OPS * 1000.0);
+ printf ("refmpn_addmul_1: %5ldms (%.2f cycles/limb) [%.2f Gb/s]\n",
+ t,
+ cyc,
+ CLOCK/cyc*BITS_PER_MP_LIMB*BITS_PER_MP_LIMB);
+#endif
+
+ MPN_COPY (dx, dy, size+2);
+ t0 = cputime();
+ for (i = 0; i < TIMES; i++)
+ cyy = mpn_addmul_1 (dx+1, s1, size, xlimb);
+ t = cputime() - t0;
+#if TIMES != 1
+ cyc = ((double) t * CLOCK) / (OPS * 1000.0);
+ printf ("mpn_addmul_1: %5ldms (%.2f cycles/limb) [%.2f Gb/s]\n",
+ t,
+ cyc,
+ CLOCK/cyc*BITS_PER_MP_LIMB*BITS_PER_MP_LIMB);
+#endif
+
+ MPN_COPY (dx, dy, size+2);
+ cyx = refmpn_addmul_1 (dx+1, s1, size, xlimb);
+ cyy = mpn_addmul_1 (dy+1, s1, size, xlimb);
+
+#ifdef PRINT
+ printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyx);
+ mpn_print (dx+1, size);
+ printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyy);
+ mpn_print (dy+1, size);
+#endif
+
+#ifndef NOCHECK
+ if (cyx != cyy || mpn_cmp (dx, dy, size+2) != 0
+ || dx[size+1] != 0x12345678 || dx[0] != 0x87654321)
+ {
+#ifndef PRINT
+ printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyx);
+ mpn_print (dx+1, size);
+ printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyy);
+ mpn_print (dy+1, size);
+#endif
+ abort();
+ }
+#endif
+ }
+}
+
+mpn_print (mp_ptr p, mp_size_t size)
+{
+ mp_size_t i;
+
+ for (i = size - 1; i >= 0; i--)
+ {
+ printf ("%0*lX", (int) (2 * sizeof(mp_limb_t)), p[i]);
+#ifdef SPACE
+ if (i != 0)
+ printf (" ");
+#endif
+ }
+ puts ("");
+}
diff --git a/mpn/tests/divmod_1.c b/mpn/tests/divmod_1.c
new file mode 100644
index 000000000..f6b541ee4
--- /dev/null
+++ b/mpn/tests/divmod_1.c
@@ -0,0 +1,120 @@
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+#ifndef USG
+#include <sys/time.h>
+#include <sys/resource.h>
+
+unsigned long
+cputime ()
+{
+ struct rusage rus;
+
+ getrusage (0, &rus);
+ return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000;
+}
+#else
+#include <time.h>
+
+#ifndef CLOCKS_PER_SEC
+#define CLOCKS_PER_SEC 1000000
+#endif
+
+#if CLOCKS_PER_SEC >= 10000
+#define CLOCK_TO_MILLISEC(cl) ((cl) / (CLOCKS_PER_SEC / 1000))
+#else
+#define CLOCK_TO_MILLISEC(cl) ((cl) * 1000 / CLOCKS_PER_SEC)
+#endif
+
+unsigned long
+cputime ()
+{
+ return CLOCK_TO_MILLISEC (clock ());
+}
+#endif
+
+#define M * 1000000
+
+#ifndef CLOCK
+#if defined (__m88k__)
+#define CLOCK 20 M
+#elif defined (__i386__)
+#define CLOCK (16.666667 M)
+#elif defined (__m68k__)
+#define CLOCK (20 M)
+#elif defined (_IBMR2)
+#define CLOCK (25 M)
+#elif defined (__sparc__)
+#define CLOCK (20 M)
+#elif defined (__sun__)
+#define CLOCK (20 M)
+#elif defined (__mips)
+#define CLOCK (40 M)
+#elif defined (__hppa__)
+#define CLOCK (50 M)
+#elif defined (__alpha)
+#define CLOCK (133 M)
+#else
+#error "Don't know CLOCK of your machine"
+#endif
+#endif
+
+#ifndef OPS
+#define OPS 20000000
+#endif
+#ifndef SIZE
+#define SIZE 1000
+#endif
+#ifndef TIMES
+#define TIMES OPS/SIZE
+#else
+#undef OPS
+#define OPS (SIZE*TIMES)
+#endif
+
+main ()
+{
+ mp_limb_t nptr[SIZE];
+ mp_limb_t qptr[SIZE];
+ mp_limb_t pptr[SIZE];
+ mp_limb_t dlimb, rlimb, plimb;
+ mp_size_t nsize, qsize, psize;
+ int test;
+
+ for (test = 0; ; test++)
+ {
+#ifdef RANDOM
+ nsize = random () % SIZE + 1;
+#else
+ nsize = SIZE;
+#endif
+
+ mpn_random2 (nptr, nsize);
+
+ mpn_random2 (&dlimb, 1);
+ if (dlimb == 0)
+ abort ();
+
+ rlimb = mpn_divmod_1 (qptr, nptr, nsize, dlimb);
+ qsize = nsize - (qptr[nsize - 1] == 0);
+ if (qsize == 0)
+ {
+ plimb = rlimb;
+ psize = qsize;
+ }
+ else
+ {
+ plimb = mpn_mul_1 (pptr, qptr, qsize, dlimb);
+ psize = qsize;
+ plimb += mpn_add_1 (pptr, pptr, psize, rlimb);
+ }
+ if (plimb != 0)
+ pptr[psize++] = plimb;
+
+
+ if (nsize != psize || mpn_cmp (nptr, pptr, nsize) != 0)
+ abort ();
+ }
+}
diff --git a/mpn/tests/divrem.c b/mpn/tests/divrem.c
new file mode 100644
index 000000000..6eafc99e8
--- /dev/null
+++ b/mpn/tests/divrem.c
@@ -0,0 +1,129 @@
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+#ifndef USG
+#include <sys/time.h>
+#include <sys/resource.h>
+
+unsigned long
+cputime ()
+{
+ struct rusage rus;
+
+ getrusage (0, &rus);
+ return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000;
+}
+#else
+#include <time.h>
+
+#ifndef CLOCKS_PER_SEC
+#define CLOCKS_PER_SEC 1000000
+#endif
+
+#if CLOCKS_PER_SEC >= 10000
+#define CLOCK_TO_MILLISEC(cl) ((cl) / (CLOCKS_PER_SEC / 1000))
+#else
+#define CLOCK_TO_MILLISEC(cl) ((cl) * 1000 / CLOCKS_PER_SEC)
+#endif
+
+unsigned long
+cputime ()
+{
+ return CLOCK_TO_MILLISEC (clock ());
+}
+#endif
+
+#define M * 1000000
+
+#ifndef CLOCK
+#if defined (__m88k__)
+#define CLOCK 20 M
+#elif defined (__i386__)
+#define CLOCK (16.666667 M)
+#elif defined (__m68k__)
+#define CLOCK (20 M)
+#elif defined (_IBMR2)
+#define CLOCK (25 M)
+#elif defined (__sparc__)
+#define CLOCK (20 M)
+#elif defined (__sun__)
+#define CLOCK (20 M)
+#elif defined (__mips)
+#define CLOCK (40 M)
+#elif defined (__hppa__)
+#define CLOCK (50 M)
+#elif defined (__alpha)
+#define CLOCK (133 M)
+#else
+#error "Don't know CLOCK of your machine"
+#endif
+#endif
+
+#ifndef OPS
+#define OPS 20000000
+#endif
+#ifndef SIZE
+#define SIZE 100
+#endif
+#ifndef TIMES
+#define TIMES OPS/SIZE
+#else
+#undef OPS
+#define OPS (SIZE*TIMES)
+#endif
+
+main ()
+{
+ mp_limb_t nptr[2 * SIZE];
+ mp_limb_t dptr[SIZE];
+ mp_limb_t qptr[2 * SIZE];
+ mp_limb_t pptr[2 * SIZE];
+ mp_limb_t rptr[2 * SIZE];
+ mp_size_t nsize, dsize, qsize, rsize, psize;
+ int test;
+ mp_limb_t qlimb;
+
+ for (test = 0; ; test++)
+ {
+#ifdef RANDOM
+ nsize = random () % (2 * SIZE) + 1;
+ dsize = random () % nsize + 1;
+#else
+ nsize = 2 * SIZE;
+ dsize = SIZE;
+#endif
+
+ mpn_random2 (nptr, nsize);
+ mpn_random2 (dptr, dsize);
+ dptr[dsize - 1] |= (mp_limb_t) 1 << (BITS_PER_MP_LIMB - 1);
+
+ MPN_COPY (rptr, nptr, nsize);
+ qlimb = mpn_divrem (qptr, (mp_size_t) 0, rptr, nsize, dptr, dsize);
+ rsize = dsize;
+ qsize = nsize - dsize;
+ qptr[qsize] = qlimb;
+ qsize += qlimb;
+ if (qsize == 0 || qsize > 2 * SIZE)
+ {
+ continue; /* bogus */
+ }
+ else
+ {
+ mp_limb_t cy;
+ if (qsize > dsize)
+ mpn_mul (pptr, qptr, qsize, dptr, dsize);
+ else
+ mpn_mul (pptr, dptr, dsize, qptr, qsize);
+ psize = qsize + dsize;
+ psize -= pptr[psize - 1] == 0;
+ cy = mpn_add (pptr, pptr, psize, rptr, rsize);
+ pptr[psize] = cy;
+ psize += cy;
+ }
+
+ if (nsize != psize || mpn_cmp (nptr, pptr, nsize) != 0)
+ abort ();
+ }
+}
diff --git a/mpn/tests/lshift.c b/mpn/tests/lshift.c
new file mode 100644
index 000000000..f50c5dceb
--- /dev/null
+++ b/mpn/tests/lshift.c
@@ -0,0 +1,226 @@
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+#ifndef USG
+#include <sys/time.h>
+#include <sys/resource.h>
+
+unsigned long
+cputime ()
+{
+ struct rusage rus;
+
+ getrusage (0, &rus);
+ return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000;
+}
+#else
+#include <time.h>
+
+#ifndef CLOCKS_PER_SEC
+#define CLOCKS_PER_SEC 1000000
+#endif
+
+#if CLOCKS_PER_SEC >= 10000
+#define CLOCK_TO_MILLISEC(cl) ((cl) / (CLOCKS_PER_SEC / 1000))
+#else
+#define CLOCK_TO_MILLISEC(cl) ((cl) * 1000 / CLOCKS_PER_SEC)
+#endif
+
+unsigned long
+cputime ()
+{
+ return CLOCK_TO_MILLISEC (clock ());
+}
+#endif
+
+#define M * 1000000
+
+#ifndef CLOCK
+#if defined (__m88k__)
+#define CLOCK 20 M
+#elif defined (__i386__)
+#define CLOCK (16.666667 M)
+#elif defined (__m68k__)
+#define CLOCK (20 M)
+#elif defined (_IBMR2)
+#define CLOCK (25 M)
+#elif defined (__sparc__)
+#define CLOCK (20 M)
+#elif defined (__sun__)
+#define CLOCK (20 M)
+#elif defined (__mips)
+#define CLOCK (40 M)
+#elif defined (__hppa__)
+#define CLOCK (50 M)
+#elif defined (__alpha)
+#define CLOCK (133 M)
+#else
+#error "Don't know CLOCK of your machine"
+#endif
+#endif
+
+#ifndef OPS
+#define OPS 10000000
+#endif
+#ifndef SIZE
+#define SIZE 496
+#endif
+#ifndef TIMES
+#define TIMES OPS/SIZE
+#else
+#undef OPS
+#define OPS (SIZE*TIMES)
+#endif
+
+mp_limb_t
+refmpn_lshift (wp, up, usize, cnt)
+ register mp_ptr wp;
+ register mp_srcptr up;
+ mp_size_t usize;
+ register unsigned int cnt;
+{
+ register mp_limb_t high_limb, low_limb;
+ register unsigned sh_1, sh_2;
+ register mp_size_t i;
+ mp_limb_t retval;
+
+#ifdef DEBUG
+ if (usize == 0 || cnt == 0)
+ abort ();
+#endif
+
+ sh_1 = cnt;
+#if 0
+ if (sh_1 == 0)
+ {
+ if (wp != up)
+ {
+ /* Copy from high end to low end, to allow specified input/output
+ overlapping. */
+ for (i = usize - 1; i >= 0; i--)
+ wp[i] = up[i];
+ }
+ return 0;
+ }
+#endif
+
+ wp += 1;
+ sh_2 = BITS_PER_MP_LIMB - sh_1;
+ i = usize - 1;
+ low_limb = up[i];
+ retval = low_limb >> sh_2;
+ high_limb = low_limb;
+ while (--i >= 0)
+ {
+ low_limb = up[i];
+ wp[i] = (high_limb << sh_1) | (low_limb >> sh_2);
+ high_limb = low_limb;
+ }
+ wp[i] = high_limb << sh_1;
+
+ return retval;
+}
+
+#ifndef CNT
+#define CNT 4
+#endif
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ mp_limb_t s1[SIZE];
+ mp_limb_t dx[SIZE+2];
+ mp_limb_t dy[SIZE+2];
+ mp_limb_t cyx, cyy;
+ int i;
+ long t0, t;
+ int test;
+ int cnt = CNT;
+ mp_size_t size;
+
+ for (test = 0; ; test++)
+ {
+#ifdef RANDOM
+ size = (random () % SIZE + 1);
+#else
+ size = SIZE;
+#endif
+ mpn_random2 (s1, size);
+
+ dx[size+1] = 0x12345678;
+ dy[size+1] = 0x12345678;
+ dx[0] = 0x87654321;
+ dy[0] = 0x87654321;
+
+#ifdef PRINT
+ mpn_print (s1, size);
+#endif
+ t0 = cputime();
+ for (i = 0; i < TIMES; i++)
+ cyx = refmpn_lshift (dx+1, s1, size, cnt);
+ t = cputime() - t0;
+#if TIMES != 1
+ printf ("refmpn_lshift: %5ldms (%.2f cycles/limb)\n",
+ t,
+ ((double) t * CLOCK) / (OPS * 1000.0));
+#endif
+#ifdef PRINT
+ printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyx); mpn_print (dx+1, size);
+#endif
+
+ t0 = cputime();
+ for (i = 0; i < TIMES; i++)
+ cyy = mpn_lshift (dx+1, s1, size, cnt);
+ t = cputime() - t0;
+#if TIMES != 1
+ printf ("mpn_lshift: %5ldms (%.2f cycles/limb)\n",
+ t,
+ ((double) t * CLOCK) / (OPS * 1000.0));
+#endif
+#ifdef PRINT
+ printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyy); mpn_print (dx+1, size);
+#endif
+
+#ifndef NOCHECK
+ /* Put garbage in the destination. */
+ for (i = 1; i <= size; i++)
+ {
+ dx[i] = 0x7654321;
+ dy[i] = 0x1234567;
+ }
+
+ cyx = refmpn_lshift (dx+1, s1, size, cnt);
+ cyy = mpn_lshift (dy+1, s1, size, cnt);
+
+ if (cyx != cyy || mpn_cmp (dx, dy, size+2) != 0
+ || dx[size+1] != 0x12345678 || dx[0] != 0x87654321)
+ {
+#ifndef PRINT
+ printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyx);
+ mpn_print (dx+1, size);
+ printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyy);
+ mpn_print (dy+1, size);
+#endif
+ abort();
+ }
+#endif
+ }
+}
+
+mpn_print (mp_ptr p, mp_size_t size)
+{
+ mp_size_t i;
+
+ for (i = size - 1; i >= 0; i--)
+ {
+ printf ("%0*lX", (int) (2 * sizeof(mp_limb_t)), p[i]);
+#ifdef SPACE
+ if (i != 0)
+ printf (" ");
+#endif
+ }
+ puts ("");
+}
diff --git a/mpn/tests/mul_1.c b/mpn/tests/mul_1.c
new file mode 100644
index 000000000..2b522fa79
--- /dev/null
+++ b/mpn/tests/mul_1.c
@@ -0,0 +1,212 @@
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+#ifndef USG
+#include <sys/time.h>
+#include <sys/resource.h>
+
+unsigned long
+cputime ()
+{
+ struct rusage rus;
+
+ getrusage (0, &rus);
+ return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000;
+}
+#else
+#include <time.h>
+
+#ifndef CLOCKS_PER_SEC
+#define CLOCKS_PER_SEC 1000000
+#endif
+
+#if CLOCKS_PER_SEC >= 10000
+#define CLOCK_TO_MILLISEC(cl) ((cl) / (CLOCKS_PER_SEC / 1000))
+#else
+#define CLOCK_TO_MILLISEC(cl) ((cl) * 1000 / CLOCKS_PER_SEC)
+#endif
+
+unsigned long
+cputime ()
+{
+ return CLOCK_TO_MILLISEC (clock ());
+}
+#endif
+
+#define M * 1000000
+
+#ifndef CLOCK
+#if defined (__m88k__)
+#define CLOCK 20 M
+#elif defined (__i386__)
+#define CLOCK (16.666667 M)
+#elif defined (__m68k__)
+#define CLOCK (20 M)
+#elif defined (_IBMR2)
+#define CLOCK (25 M)
+#elif defined (__sparc__)
+#define CLOCK (20 M)
+#elif defined (__sun__)
+#define CLOCK (20 M)
+#elif defined (__mips)
+#define CLOCK (40 M)
+#elif defined (__hppa__)
+#define CLOCK (50 M)
+#elif defined (__alpha)
+#define CLOCK (133 M)
+#else
+#error "Don't know CLOCK of your machine"
+#endif
+#endif
+
+#ifndef OPS
+#define OPS 20000000
+#endif
+#ifndef SIZE
+#define SIZE 496
+#endif
+#ifndef TIMES
+#define TIMES OPS/SIZE
+#else
+#undef OPS
+#define OPS (SIZE*TIMES)
+#endif
+
+mp_limb_t
+refmpn_mul_1 (res_ptr, s1_ptr, s1_size, s2_limb)
+ register mp_ptr res_ptr;
+ register mp_srcptr s1_ptr;
+ mp_size_t s1_size;
+ register mp_limb_t s2_limb;
+{
+ register mp_limb_t cy_limb;
+ register mp_size_t j;
+ register mp_limb_t prod_high, prod_low;
+
+ /* The loop counter and index J goes from -S1_SIZE to -1. This way
+ the loop becomes faster. */
+ j = -s1_size;
+
+ /* Offset the base pointers to compensate for the negative indices. */
+ s1_ptr -= j;
+ res_ptr -= j;
+
+ cy_limb = 0;
+ do
+ {
+ umul_ppmm (prod_high, prod_low, s1_ptr[j], s2_limb);
+
+ prod_low += cy_limb;
+ cy_limb = (prod_low < cy_limb) + prod_high;
+
+ res_ptr[j] = prod_low;
+ }
+ while (++j != 0);
+
+ return cy_limb;
+}
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ mp_limb_t s1[SIZE];
+ mp_limb_t dx[SIZE+2];
+ mp_limb_t dy[SIZE+2];
+ mp_limb_t cyx, cyy;
+ int i;
+ long t0, t;
+ int test;
+ mp_limb_t xlimb;
+ mp_size_t size;
+
+ for (test = 0; ; test++)
+ {
+#ifdef RANDOM
+ size = (random () % SIZE + 1);
+#else
+ size = SIZE;
+#endif
+
+ mpn_random2 (s1, size);
+ mpn_random2 (dy+1, size);
+
+ if (random () % 0x100 == 0)
+ xlimb = 0;
+ else
+ mpn_random2 (&xlimb, 1);
+
+ dy[size+1] = 0x12345678;
+ dy[0] = 0x87654321;
+
+#if defined (PRINT) || defined (XPRINT)
+ printf ("xlimb=%*lX\n", (int) (2 * sizeof(mp_limb_t)), xlimb);
+#endif
+#ifdef PRINT
+ mpn_print (s1, size);
+#endif
+
+ MPN_COPY (dx, dy, size+2);
+ t0 = cputime();
+ for (i = 0; i < TIMES; i++)
+ cyx = refmpn_mul_1 (dx+1, s1, size, xlimb);
+ t = cputime() - t0;
+#if TIMES != 1
+ printf ("refmpn_mul_1: %5ldms (%.2f cycles/limb)\n",
+ t,
+ ((double) t * CLOCK) / (OPS * 1000.0));
+#endif
+
+ MPN_COPY (dx, dy, size+2);
+ t0 = cputime();
+ for (i = 0; i < TIMES; i++)
+ cyy = mpn_mul_1 (dx+1, s1, size, xlimb);
+ t = cputime() - t0;
+#if TIMES != 1
+ printf ("mpn_mul_1: %5ldms (%.2f cycles/limb)\n",
+ t,
+ ((double) t * CLOCK) / (OPS * 1000.0));
+#endif
+
+ cyx = refmpn_mul_1 (dx+1, s1, size, xlimb);
+ cyy = mpn_mul_1 (dy+1, s1, size, xlimb);
+
+#ifdef PRINT
+ printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyx);
+ mpn_print (dx+1, size);
+ printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyy);
+ mpn_print (dy+1, size);
+#endif
+
+#ifndef NOCHECK
+ if (cyx != cyy || mpn_cmp (dx, dy, size+2) != 0
+ || dx[size+1] != 0x12345678 || dx[0] != 0x87654321)
+ {
+#ifndef PRINT
+ printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyx);
+ mpn_print (dx+1, size);
+ printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyy);
+ mpn_print (dy+1, size);
+#endif
+ abort();
+ }
+#endif
+ }
+}
+
+mpn_print (mp_ptr p, mp_size_t size)
+{
+ mp_size_t i;
+
+ for (i = size - 1; i >= 0; i--)
+ {
+ printf ("%0*lX", (int) (2 * sizeof(mp_limb_t)), p[i]);
+#ifdef SPACE
+ if (i != 0)
+ printf (" ");
+#endif
+ }
+ puts ("");
+}
diff --git a/mpn/tests/rshift.c b/mpn/tests/rshift.c
new file mode 100644
index 000000000..2482bf340
--- /dev/null
+++ b/mpn/tests/rshift.c
@@ -0,0 +1,227 @@
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+#ifndef USG
+#include <sys/time.h>
+#include <sys/resource.h>
+
+unsigned long
+cputime ()
+{
+ struct rusage rus;
+
+ getrusage (0, &rus);
+ return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000;
+}
+#else
+#include <time.h>
+
+#ifndef CLOCKS_PER_SEC
+#define CLOCKS_PER_SEC 1000000
+#endif
+
+#if CLOCKS_PER_SEC >= 10000
+#define CLOCK_TO_MILLISEC(cl) ((cl) / (CLOCKS_PER_SEC / 1000))
+#else
+#define CLOCK_TO_MILLISEC(cl) ((cl) * 1000 / CLOCKS_PER_SEC)
+#endif
+
+unsigned long
+cputime ()
+{
+ return CLOCK_TO_MILLISEC (clock ());
+}
+#endif
+
+#define M * 1000000
+
+#ifndef CLOCK
+#if defined (__m88k__)
+#define CLOCK 20 M
+#elif defined (__i386__)
+#define CLOCK (16.666667 M)
+#elif defined (__m68k__)
+#define CLOCK (20 M)
+#elif defined (_IBMR2)
+#define CLOCK (25 M)
+#elif defined (__sparc__)
+#define CLOCK (20 M)
+#elif defined (__sun__)
+#define CLOCK (20 M)
+#elif defined (__mips)
+#define CLOCK (40 M)
+#elif defined (__hppa__)
+#define CLOCK (50 M)
+#elif defined (__alpha)
+#define CLOCK (133 M)
+#else
+#error "Don't know CLOCK of your machine"
+#endif
+#endif
+
+#ifndef OPS
+#define OPS 10000000
+#endif
+#ifndef SIZE
+#define SIZE 496
+#endif
+#ifndef TIMES
+#define TIMES OPS/SIZE
+#else
+#undef OPS
+#define OPS (SIZE*TIMES)
+#endif
+
+mp_limb_t
+refmpn_rshift (wp, up, usize, cnt)
+ register mp_ptr wp;
+ register mp_srcptr up;
+ mp_size_t usize;
+ register unsigned int cnt;
+{
+ register mp_limb_t high_limb, low_limb;
+ register unsigned sh_1, sh_2;
+ register mp_size_t i;
+ mp_limb_t retval;
+
+#ifdef DEBUG
+ if (usize == 0 || cnt == 0)
+ abort ();
+#endif
+
+ sh_1 = cnt;
+#if 0
+ if (sh_1 == 0)
+ {
+ if (wp != up)
+ {
+ /* Copy from low end to high end, to allow specified input/output
+ overlapping. */
+ for (i = 0; i < usize; i++)
+ wp[i] = up[i];
+ }
+ return 0;
+ }
+#endif
+
+ wp -= 1;
+ sh_2 = BITS_PER_MP_LIMB - sh_1;
+ high_limb = up[0];
+ retval = high_limb << sh_2;
+ low_limb = high_limb;
+
+ for (i = 1; i < usize; i++)
+ {
+ high_limb = up[i];
+ wp[i] = (low_limb >> sh_1) | (high_limb << sh_2);
+ low_limb = high_limb;
+ }
+ low_limb >>= sh_1;
+ wp[i] = low_limb;
+
+ return retval;
+}
+
+#ifndef CNT
+#define CNT 4
+#endif
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ mp_limb_t s1[SIZE];
+ mp_limb_t dx[SIZE+2];
+ mp_limb_t dy[SIZE+2];
+ mp_limb_t cyx, cyy;
+ int i;
+ long t0, t;
+ int test;
+ int cnt = CNT;
+ mp_size_t size;
+
+ for (test = 0; ; test++)
+ {
+#ifdef RANDOM
+ size = (random () % SIZE + 1);
+#else
+ size = SIZE;
+#endif
+ mpn_random2 (s1, size);
+
+ dx[size+1] = 0x12345678;
+ dy[size+1] = 0x12345678;
+ dx[0] = 0x87654321;
+ dy[0] = 0x87654321;
+
+#ifdef PRINT
+ mpn_print (s1, size);
+#endif
+ t0 = cputime();
+ for (i = 0; i < TIMES; i++)
+ cyx = refmpn_rshift (dx+1, s1, size, cnt);
+ t = cputime() - t0;
+#if TIMES != 1
+ printf ("refmpn_rshift: %5ldms (%.2f cycles/limb)\n",
+ t,
+ ((double) t * CLOCK) / (OPS * 1000.0));
+#endif
+#ifdef PRINT
+ printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyx); mpn_print (dx+1, size);
+#endif
+
+ t0 = cputime();
+ for (i = 0; i < TIMES; i++)
+ cyy = mpn_rshift (dx+1, s1, size, cnt);
+ t = cputime() - t0;
+#if TIMES != 1
+ printf ("mpn_rshift: %5ldms (%.2f cycles/limb)\n",
+ t,
+ ((double) t * CLOCK) / (OPS * 1000.0));
+#endif
+#ifdef PRINT
+ printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyy); mpn_print (dx+1, size);
+#endif
+
+#ifndef NOCHECK
+ /* Put garbage in the destination. */
+ for (i = 1; i <= size; i++)
+ {
+ dx[i] = 0x7654321;
+ dy[i] = 0x1234567;
+ }
+
+ cyx = refmpn_rshift (dx+1, s1, size, cnt);
+ cyy = mpn_rshift (dy+1, s1, size, cnt);
+
+ if (cyx != cyy || mpn_cmp (dx, dy, size+2) != 0
+ || dx[size+1] != 0x12345678 || dx[0] != 0x87654321)
+ {
+#ifndef PRINT
+ printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyx);
+ mpn_print (dx+1, size);
+ printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyy);
+ mpn_print (dy+1, size);
+#endif
+ abort();
+ }
+#endif
+ }
+}
+
+mpn_print (mp_ptr p, mp_size_t size)
+{
+ mp_size_t i;
+
+ for (i = size - 1; i >= 0; i--)
+ {
+ printf ("%0*lX", (int) (2 * sizeof(mp_limb_t)), p[i]);
+#ifdef SPACE
+ if (i != 0)
+ printf (" ");
+#endif
+ }
+ puts ("");
+}
diff --git a/mpn/tests/sub_n.c b/mpn/tests/sub_n.c
new file mode 100644
index 000000000..2b9031bbf
--- /dev/null
+++ b/mpn/tests/sub_n.c
@@ -0,0 +1,211 @@
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+
+#ifndef USG
+#include <sys/time.h>
+#include <sys/resource.h>
+
+unsigned long
+cputime ()
+{
+ struct rusage rus;
+
+ getrusage (0, &rus);
+ return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000;
+}
+#else
+#include <time.h>
+
+#ifndef CLOCKS_PER_SEC
+#define CLOCKS_PER_SEC 1000000
+#endif
+
+#if CLOCKS_PER_SEC >= 10000
+#define CLOCK_TO_MILLISEC(cl) ((cl) / (CLOCKS_PER_SEC / 1000))
+#else
+#define CLOCK_TO_MILLISEC(cl) ((cl) * 1000 / CLOCKS_PER_SEC)
+#endif
+
+unsigned long
+cputime ()
+{
+ return CLOCK_TO_MILLISEC (clock ());
+}
+#endif
+
+#define M * 1000000
+
+#ifndef CLOCK
+#if defined (__m88k__)
+#define CLOCK 20 M
+#elif defined (__i386__)
+#define CLOCK (16.666667 M)
+#elif defined (__m68k__)
+#define CLOCK (20 M)
+#elif defined (_IBMR2)
+#define CLOCK (25 M)
+#elif defined (__sparc__)
+#define CLOCK (20 M)
+#elif defined (__sun__)
+#define CLOCK (20 M)
+#elif defined (__mips)
+#define CLOCK (40 M)
+#elif defined (__hppa__)
+#define CLOCK (50 M)
+#elif defined (__alpha)
+#define CLOCK (133 M)
+#else
+#error "Don't know CLOCK of your machine"
+#endif
+#endif
+
+#ifndef OPS
+#define OPS 10000000
+#endif
+#ifndef SIZE
+#define SIZE 328
+#endif
+#ifndef TIMES
+#define TIMES OPS/SIZE
+#else
+#undef OPS
+#define OPS (SIZE*TIMES)
+#endif
+
+
+mp_limb_t
+#if __STDC__
+refmpn_sub_n (mp_ptr res_ptr,
+ mp_srcptr s1_ptr, mp_srcptr s2_ptr, mp_size_t size)
+#else
+refmpn_sub_n (res_ptr, s1_ptr, s2_ptr, size)
+ register mp_ptr res_ptr;
+ register mp_srcptr s1_ptr;
+ register mp_srcptr s2_ptr;
+ mp_size_t size;
+#endif
+{
+ register mp_limb_t x, y, cy;
+ register mp_size_t j;
+
+ /* The loop counter and index J goes from -SIZE to -1. This way
+ the loop becomes faster. */
+ j = -size;
+
+ /* Offset the base pointers to compensate for the negative indices. */
+ s1_ptr -= j;
+ s2_ptr -= j;
+ res_ptr -= j;
+
+ cy = 0;
+ do
+ {
+ y = s2_ptr[j];
+ x = s1_ptr[j];
+ y += cy; /* add previous carry to subtrahend */
+ cy = (y < cy); /* get out carry from that addition */
+ y = x - y; /* main subtract */
+ cy = (y > x) + cy; /* get out carry from the subtract, combine */
+ res_ptr[j] = y;
+ }
+ while (++j != 0);
+
+ return cy;
+}
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ mp_limb_t s1[SIZE];
+ mp_limb_t s2[SIZE];
+ mp_limb_t dx[SIZE+1];
+ mp_limb_t dy[SIZE+1];
+ int cyx, cyy;
+ int i;
+ long t0, t;
+ int test;
+ mp_size_t size;
+
+ for (test = 0; ; test++)
+ {
+#ifdef RANDOM
+ size = (random () % SIZE + 1);
+#else
+ size = SIZE;
+#endif
+
+ mpn_random2 (s1, size);
+ mpn_random2 (s2, size);
+
+ dx[size] = 0x12345678;
+ dy[size] = 0x12345678;
+
+#ifdef PRINT
+ mpn_print (s1, size);
+ mpn_print (s2, size);
+#endif
+ t0 = cputime();
+ for (i = 0; i < TIMES; i++)
+ cyx = refmpn_sub_n (dx, s1, s2, size);
+ t = cputime() - t0;
+#if TIMES != 1
+ printf ("refmpn_sub_n: %ldms (%.2f cycles/limb)\n",
+ t,
+ ((double) t * CLOCK) / (OPS * 1000.0));
+#endif
+#ifdef PRINT
+ printf ("%d ", cyx); mpn_print (dx, size);
+#endif
+
+ t0 = cputime();
+ for (i = 0; i < TIMES; i++)
+ cyx = mpn_sub_n (dx, s1, s2, size);
+ t = cputime() - t0;
+#if TIMES != 1
+ printf ("mpn_sub_n: %ldms (%.2f cycles/limb)\n",
+ t,
+ ((double) t * CLOCK) / (OPS * 1000.0));
+#endif
+#ifdef PRINT
+ printf ("%d ", cyx); mpn_print (dx, size);
+#endif
+
+#ifndef NOCHECK
+ /* Put garbage in the destination. */
+ for (i = 0; i < size; i++)
+ {
+ dx[i] = 0x7654321;
+ dy[i] = 0x1234567;
+ }
+
+ cyx = refmpn_sub_n (dx, s1, s2, size);
+ cyy = mpn_sub_n (dy, s1, s2, size);
+ if (cyx != cyy || mpn_cmp (dx, dy, size) != 0
+ || dx[size] != 0x12345678 || dy[size] != 0x12345678)
+ {
+#ifndef PRINT
+ printf ("%d ", cyx); mpn_print (dx, size);
+ printf ("%d ", cyy); mpn_print (dy, size);
+#endif
+ abort();
+ }
+#endif
+ }
+}
+
+mpn_print (mp_ptr p, mp_size_t size)
+{
+ mp_size_t i;
+
+ for (i = size - 1; i >= 0; i--)
+ {
+ printf ("%0*lX", (int) (2 * sizeof(mp_limb_t)), p[i]);
+#ifdef SPACE
+ if (i != 0)
+ printf (" ");
+#endif
+ }
+ puts ("");
+}
diff --git a/mpn/tests/submul_1.c b/mpn/tests/submul_1.c
new file mode 100644
index 000000000..0e464e613
--- /dev/null
+++ b/mpn/tests/submul_1.c
@@ -0,0 +1,218 @@
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+#ifndef USG
+#include <sys/time.h>
+#include <sys/resource.h>
+
+unsigned long
+cputime ()
+{
+ struct rusage rus;
+
+ getrusage (0, &rus);
+ return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000;
+}
+#else
+#include <time.h>
+
+#ifndef CLOCKS_PER_SEC
+#define CLOCKS_PER_SEC 1000000
+#endif
+
+#if CLOCKS_PER_SEC >= 10000
+#define CLOCK_TO_MILLISEC(cl) ((cl) / (CLOCKS_PER_SEC / 1000))
+#else
+#define CLOCK_TO_MILLISEC(cl) ((cl) * 1000 / CLOCKS_PER_SEC)
+#endif
+
+unsigned long
+cputime ()
+{
+ return CLOCK_TO_MILLISEC (clock ());
+}
+#endif
+
+#define M * 1000000
+
+#ifndef CLOCK
+#if defined (__m88k__)
+#define CLOCK 20 M
+#elif defined (__i386__)
+#define CLOCK (16.666667 M)
+#elif defined (__m68k__)
+#define CLOCK (20 M)
+#elif defined (_IBMR2)
+#define CLOCK (25 M)
+#elif defined (__sparc__)
+#define CLOCK (20 M)
+#elif defined (__sun__)
+#define CLOCK (20 M)
+#elif defined (__mips)
+#define CLOCK (40 M)
+#elif defined (__hppa__)
+#define CLOCK (50 M)
+#elif defined (__alpha)
+#define CLOCK (133 M)
+#else
+#error "Don't know CLOCK of your machine"
+#endif
+#endif
+
+#ifndef OPS
+#define OPS 20000000
+#endif
+#ifndef SIZE
+#define SIZE 496
+#endif
+#ifndef TIMES
+#define TIMES OPS/SIZE
+#else
+#undef OPS
+#define OPS (SIZE*TIMES)
+#endif
+
+mp_limb_t
+refmpn_submul_1 (res_ptr, s1_ptr, s1_size, s2_limb)
+ register mp_ptr res_ptr;
+ register mp_srcptr s1_ptr;
+ mp_size_t s1_size;
+ register mp_limb_t s2_limb;
+{
+ register mp_limb_t cy_limb;
+ register mp_size_t j;
+ register mp_limb_t prod_high, prod_low;
+ register mp_limb_t x;
+
+ /* The loop counter and index J goes from -SIZE to -1. This way
+ the loop becomes faster. */
+ j = -s1_size;
+
+ /* Offset the base pointers to compensate for the negative indices. */
+ res_ptr -= j;
+ s1_ptr -= j;
+
+ cy_limb = 0;
+ do
+ {
+ umul_ppmm (prod_high, prod_low, s1_ptr[j], s2_limb);
+
+ prod_low += cy_limb;
+ cy_limb = (prod_low < cy_limb) + prod_high;
+
+ x = res_ptr[j];
+ prod_low = x - prod_low;
+ cy_limb += (prod_low > x);
+ res_ptr[j] = prod_low;
+ }
+ while (++j != 0);
+
+ return cy_limb;
+}
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ mp_limb_t s1[SIZE];
+ mp_limb_t dx[SIZE+2];
+ mp_limb_t dy[SIZE+2];
+ mp_limb_t cyx, cyy;
+ int i;
+ long t0, t;
+ int test;
+ mp_limb_t xlimb;
+ mp_size_t size;
+
+ for (test = 0; ; test++)
+ {
+#ifdef RANDOM
+ size = (random () % SIZE + 1);
+#else
+ size = SIZE;
+#endif
+
+ mpn_random2 (s1, size);
+ mpn_random2 (dy+1, size);
+
+ if (random () % 0x100 == 0)
+ xlimb = 0;
+ else
+ mpn_random2 (&xlimb, 1);
+
+ dy[size+1] = 0x12345678;
+ dy[0] = 0x87654321;
+
+#if defined (PRINT) || defined (XPRINT)
+ printf ("xlimb=%*lX\n", (int) (2 * sizeof(mp_limb_t)), xlimb);
+#endif
+#ifdef PRINT
+ mpn_print (dy+1, size);
+ mpn_print (s1, size);
+#endif
+
+ MPN_COPY (dx, dy, size+2);
+ t0 = cputime();
+ for (i = 0; i < TIMES; i++)
+ cyx = refmpn_submul_1 (dx+1, s1, size, xlimb);
+ t = cputime() - t0;
+#if TIMES != 1
+ printf ("refmpn_submul_1: %5ldms (%.2f cycles/limb)\n",
+ t,
+ ((double) t * CLOCK) / (OPS * 1000.0));
+#endif
+
+ MPN_COPY (dx, dy, size+2);
+ t0 = cputime();
+ for (i = 0; i < TIMES; i++)
+ cyy = mpn_submul_1 (dx+1, s1, size, xlimb);
+ t = cputime() - t0;
+#if TIMES != 1
+ printf ("mpn_submul_1: %5ldms (%.2f cycles/limb)\n",
+ t,
+ ((double) t * CLOCK) / (OPS * 1000.0));
+#endif
+
+ MPN_COPY (dx, dy, size+2);
+ cyx = refmpn_submul_1 (dx+1, s1, size, xlimb);
+ cyy = mpn_submul_1 (dy+1, s1, size, xlimb);
+
+#ifdef PRINT
+ printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyx);
+ mpn_print (dx+1, size);
+ printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyy);
+ mpn_print (dy+1, size);
+#endif
+
+#ifndef NOCHECK
+ if (cyx != cyy || mpn_cmp (dx, dy, size+2) != 0
+ || dx[size+1] != 0x12345678 || dx[0] != 0x87654321)
+ {
+#ifndef PRINT
+ printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyx);
+ mpn_print (dx+1, size);
+ printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyy);
+ mpn_print (dy+1, size);
+#endif
+ abort();
+ }
+#endif
+ }
+}
+
+mpn_print (mp_ptr p, mp_size_t size)
+{
+ mp_size_t i;
+
+ for (i = size - 1; i >= 0; i--)
+ {
+ printf ("%0*lX", (int) (2 * sizeof(mp_limb_t)), p[i]);
+#ifdef SPACE
+ if (i != 0)
+ printf (" ");
+#endif
+ }
+ puts ("");
+}
diff --git a/mpn/tests/tst-addsub.c b/mpn/tests/tst-addsub.c
new file mode 100644
index 000000000..e02b9d5cc
--- /dev/null
+++ b/mpn/tests/tst-addsub.c
@@ -0,0 +1,164 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+
+#define ADD 1
+#define SUB 2
+
+#ifndef METHOD
+#define METHOD ADD
+#endif
+
+#if METHOD == ADD
+#define REFCALL refmpn_add_n
+#define TESTCALL mpn_add_n
+#endif
+
+#if METHOD == SUB
+#define REFCALL refmpn_sub_n
+#define TESTCALL mpn_sub_n
+#endif
+
+mp_limb_t refmpn_add_n ();
+mp_limb_t refmpn_sub_n ();
+
+#define SIZE 100
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ mp_size_t alloc_size, max_size, size, i, cumul_size;
+ mp_ptr s1, s2, dx, dy;
+ int s1_align, s2_align, d_align;
+ long pass, n_passes;
+ mp_limb_t cx, cy;
+
+ max_size = SIZE;
+ n_passes = 1000000;
+
+ argc--; argv++;
+ if (argc)
+ {
+ max_size = atol (*argv);
+ argc--; argv++;
+ }
+
+ alloc_size = max_size + 32;
+ s1 = malloc (alloc_size * BYTES_PER_MP_LIMB);
+ s2 = malloc (alloc_size * BYTES_PER_MP_LIMB);
+ dx = malloc (alloc_size * BYTES_PER_MP_LIMB);
+ dy = malloc (alloc_size * BYTES_PER_MP_LIMB);
+
+ cumul_size = 0;
+ for (pass = 0; pass < n_passes; pass++)
+ {
+ cumul_size += size;
+ if (cumul_size >= 1000000)
+ {
+ cumul_size -= 1000000;
+ printf ("%d ", pass); fflush (stdout);
+ }
+ s1_align = random () % 32;
+ s2_align = random () % 32;
+ d_align = random () % 32;
+
+ size = random () % max_size + 1;
+
+ mpn_random2 (s1 + s1_align, size);
+ mpn_random2 (s2 + s2_align, size);
+
+ for (i = 0; i < alloc_size; i++)
+ dx[i] = dy[i] = i + 0x9876500;
+
+ cx = TESTCALL (dx + d_align, s1 + s1_align, s2 + s2_align, size);
+ cy = REFCALL (dy + d_align, s1 + s1_align, s2 + s2_align, size);
+
+ if (cx != cy || mpn_cmp (dx, dy, alloc_size) != 0)
+ abort ();
+ }
+
+ printf ("%d passes OK\n", n_passes);
+ exit (0);
+}
+
+mp_limb_t
+#if __STDC__
+refmpn_add_n (mp_ptr res_ptr,
+ mp_srcptr s1_ptr, mp_srcptr s2_ptr, mp_size_t size)
+#else
+refmpn_add_n (res_ptr, s1_ptr, s2_ptr, size)
+ register mp_ptr res_ptr;
+ register mp_srcptr s1_ptr;
+ register mp_srcptr s2_ptr;
+ mp_size_t size;
+#endif
+{
+ register mp_limb_t x, y, cy;
+ register mp_size_t j;
+
+ /* The loop counter and index J goes from -SIZE to -1. This way
+ the loop becomes faster. */
+ j = -size;
+
+ /* Offset the base pointers to compensate for the negative indices. */
+ s1_ptr -= j;
+ s2_ptr -= j;
+ res_ptr -= j;
+
+ cy = 0;
+ do
+ {
+ y = s2_ptr[j];
+ x = s1_ptr[j];
+ y += cy; /* add previous carry to one addend */
+ cy = (y < cy); /* get out carry from that addition */
+ y = x + y; /* add other addend */
+ cy = (y < x) + cy; /* get out carry from that add, combine */
+ res_ptr[j] = y;
+ }
+ while (++j != 0);
+
+ return cy;
+}
+
+mp_limb_t
+#if __STDC__
+refmpn_sub_n (mp_ptr res_ptr,
+ mp_srcptr s1_ptr, mp_srcptr s2_ptr, mp_size_t size)
+#else
+refmpn_sub_n (res_ptr, s1_ptr, s2_ptr, size)
+ register mp_ptr res_ptr;
+ register mp_srcptr s1_ptr;
+ register mp_srcptr s2_ptr;
+ mp_size_t size;
+#endif
+{
+ register mp_limb_t x, y, cy;
+ register mp_size_t j;
+
+ /* The loop counter and index J goes from -SIZE to -1. This way
+ the loop becomes faster. */
+ j = -size;
+
+ /* Offset the base pointers to compensate for the negative indices. */
+ s1_ptr -= j;
+ s2_ptr -= j;
+ res_ptr -= j;
+
+ cy = 0;
+ do
+ {
+ y = s2_ptr[j];
+ x = s1_ptr[j];
+ y += cy; /* add previous carry to subtrahend */
+ cy = (y < cy); /* get out carry from that addition */
+ y = x - y; /* main subtract */
+ cy = (y > x) + cy; /* get out carry from the subtract, combine */
+ res_ptr[j] = y;
+ }
+ while (++j != 0);
+
+ return cy;
+}
diff --git a/mpn/vax/add_n.s b/mpn/vax/add_n.s
new file mode 100644
index 000000000..d4764e23a
--- /dev/null
+++ b/mpn/vax/add_n.s
@@ -0,0 +1,48 @@
+# VAX __mpn_add_n -- Add two limb vectors of the same length > 0 and store
+# sum in a third limb vector.
+
+# Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+# This file is part of the GNU MP Library.
+
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+
+# The GNU MP Library 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 Library General Public
+# License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+
+
+# INPUT PARAMETERS
+# res_ptr (sp + 4)
+# s1_ptr (sp + 8)
+# s2_ptr (sp + 12)
+# size (sp + 16)
+
+.text
+ .align 1
+.globl ___mpn_add_n
+___mpn_add_n:
+ .word 0x0
+ movl 16(ap),r0
+ movl 12(ap),r1
+ movl 8(ap),r2
+ movl 4(ap),r3
+ subl2 r4,r4
+
+Loop:
+ movl (r2)+,r4
+ adwc (r1)+,r4
+ movl r4,(r3)+
+ jsobgtr r0,Loop
+
+ adwc r0,r0
+ ret
diff --git a/mpn/vax/addmul_1.s b/mpn/vax/addmul_1.s
new file mode 100644
index 000000000..746d95ba7
--- /dev/null
+++ b/mpn/vax/addmul_1.s
@@ -0,0 +1,126 @@
+# VAX __mpn_addmul_1 -- Multiply a limb vector with a limb and add
+# the result to a second limb vector.
+
+# Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+# This file is part of the GNU MP Library.
+
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+
+# The GNU MP Library 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 Library General Public
+# License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+
+
+# INPUT PARAMETERS
+# res_ptr (sp + 4)
+# s1_ptr (sp + 8)
+# size (sp + 12)
+# s2_limb (sp + 16)
+
+.text
+ .align 1
+.globl ___mpn_addmul_1
+___mpn_addmul_1:
+ .word 0xfc0
+ movl 12(ap),r4
+ movl 8(ap),r8
+ movl 4(ap),r9
+ movl 16(ap),r6
+ jlss s2_big
+
+ clrl r3
+ incl r4
+ ashl $-1,r4,r7
+ jlbc r4,L1
+ clrl r11
+
+# Loop for S2_LIMB < 0x80000000
+Loop1: movl (r8)+,r1
+ jlss L1n0
+ emul r1,r6,$0,r2
+ addl2 r11,r2
+ adwc $0,r3
+ addl2 r2,(r9)+
+ adwc $0,r3
+L1: movl (r8)+,r1
+ jlss L1n1
+L1p1: emul r1,r6,$0,r10
+ addl2 r3,r10
+ adwc $0,r11
+ addl2 r10,(r9)+
+ adwc $0,r11
+
+ jsobgtr r7,Loop1
+ movl r11,r0
+ ret
+
+L1n0: emul r1,r6,$0,r2
+ addl2 r11,r2
+ adwc r6,r3
+ addl2 r2,(r9)+
+ adwc $0,r3
+ movl (r8)+,r1
+ jgeq L1p1
+L1n1: emul r1,r6,$0,r10
+ addl2 r3,r10
+ adwc r6,r11
+ addl2 r10,(r9)+
+ adwc $0,r11
+
+ jsobgtr r7,Loop1
+ movl r11,r0
+ ret
+
+
+s2_big: clrl r3
+ incl r4
+ ashl $-1,r4,r7
+ jlbc r4,L2
+ clrl r11
+
+# Loop for S2_LIMB >= 0x80000000
+Loop2: movl (r8)+,r1
+ jlss L2n0
+ emul r1,r6,$0,r2
+ addl2 r11,r2
+ adwc r1,r3
+ addl2 r2,(r9)+
+ adwc $0,r3
+L2: movl (r8)+,r1
+ jlss L2n1
+L2p1: emul r1,r6,$0,r10
+ addl2 r3,r10
+ adwc r1,r11
+ addl2 r10,(r9)+
+ adwc $0,r11
+
+ jsobgtr r7,Loop2
+ movl r11,r0
+ ret
+
+L2n0: emul r1,r6,$0,r2
+ addl2 r11,r2
+ adwc r6,r3
+ addl2 r2,(r9)+
+ adwc r1,r3
+ movl (r8)+,r1
+ jgeq L2p1
+L2n1: emul r1,r6,$0,r10
+ addl2 r3,r10
+ adwc r6,r11
+ addl2 r10,(r9)+
+ adwc r1,r11
+
+ jsobgtr r7,Loop2
+ movl r11,r0
+ ret
diff --git a/mpn/vax/gmp-mparam.h b/mpn/vax/gmp-mparam.h
new file mode 100644
index 000000000..d909cd2a5
--- /dev/null
+++ b/mpn/vax/gmp-mparam.h
@@ -0,0 +1,29 @@
+/* gmp-mparam.h -- Compiler/machine parameter header file.
+
+Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#define BITS_PER_MP_LIMB 32
+#define BYTES_PER_MP_LIMB 4
+#define BITS_PER_LONGINT 32
+#define BITS_PER_INT 32
+#define BITS_PER_SHORTINT 16
+#define BITS_PER_CHAR 8
+
+#define IEEE_DOUBLE_BIG_ENDIAN 0
diff --git a/mpn/vax/mul_1.s b/mpn/vax/mul_1.s
new file mode 100644
index 000000000..e2ff5a1bc
--- /dev/null
+++ b/mpn/vax/mul_1.s
@@ -0,0 +1,123 @@
+# VAX __mpn_mul_1 -- Multiply a limb vector with a limb and store
+# the result in a second limb vector.
+
+# Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+# This file is part of the GNU MP Library.
+
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+
+# The GNU MP Library 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 Library General Public
+# License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+
+
+# INPUT PARAMETERS
+# res_ptr (sp + 4)
+# s1_ptr (sp + 8)
+# size (sp + 12)
+# s2_limb (sp + 16)
+
+.text
+ .align 1
+.globl ___mpn_mul_1
+___mpn_mul_1:
+ .word 0xfc0
+ movl 12(ap),r4
+ movl 8(ap),r8
+ movl 4(ap),r9
+ movl 16(ap),r6
+ jlss s2_big
+
+# One might want to combine the addl2 and the store below, but that
+# is actually just slower according to my timing tests. (VAX 3600)
+
+ clrl r3
+ incl r4
+ ashl $-1,r4,r7
+ jlbc r4,L1
+ clrl r11
+
+# Loop for S2_LIMB < 0x80000000
+Loop1: movl (r8)+,r1
+ jlss L1n0
+ emul r1,r6,$0,r2
+ addl2 r11,r2
+ adwc $0,r3
+ movl r2,(r9)+
+L1: movl (r8)+,r1
+ jlss L1n1
+L1p1: emul r1,r6,$0,r10
+ addl2 r3,r10
+ adwc $0,r11
+ movl r10,(r9)+
+
+ jsobgtr r7,Loop1
+ movl r11,r0
+ ret
+
+L1n0: emul r1,r6,$0,r2
+ addl2 r11,r2
+ adwc r6,r3
+ movl r2,(r9)+
+ movl (r8)+,r1
+ jgeq L1p1
+L1n1: emul r1,r6,$0,r10
+ addl2 r3,r10
+ adwc r6,r11
+ movl r10,(r9)+
+
+ jsobgtr r7,Loop1
+ movl r11,r0
+ ret
+
+
+s2_big: clrl r3
+ incl r4
+ ashl $-1,r4,r7
+ jlbc r4,L2
+ clrl r11
+
+# Loop for S2_LIMB >= 0x80000000
+Loop2: movl (r8)+,r1
+ jlss L2n0
+ emul r1,r6,$0,r2
+ addl2 r11,r2
+ adwc r1,r3
+ movl r2,(r9)+
+L2: movl (r8)+,r1
+ jlss L2n1
+L2p1: emul r1,r6,$0,r10
+ addl2 r3,r10
+ adwc r1,r11
+ movl r10,(r9)+
+
+ jsobgtr r7,Loop2
+ movl r11,r0
+ ret
+
+L2n0: emul r1,r6,$0,r2
+ addl2 r1,r3
+ addl2 r11,r2
+ adwc r6,r3
+ movl r2,(r9)+
+ movl (r8)+,r1
+ jgeq L2p1
+L2n1: emul r1,r6,$0,r10
+ addl2 r1,r11
+ addl2 r3,r10
+ adwc r6,r11
+ movl r10,(r9)+
+
+ jsobgtr r7,Loop2
+ movl r11,r0
+ ret
diff --git a/mpn/vax/sub_n.s b/mpn/vax/sub_n.s
new file mode 100644
index 000000000..a891c4425
--- /dev/null
+++ b/mpn/vax/sub_n.s
@@ -0,0 +1,48 @@
+# VAX __mpn_sub_n -- Subtract two limb vectors of the same length > 0 and store
+# difference in a third limb vector.
+
+# Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+# This file is part of the GNU MP Library.
+
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+
+# The GNU MP Library 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 Library General Public
+# License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+
+
+# INPUT PARAMETERS
+# res_ptr (sp + 4)
+# s1_ptr (sp + 8)
+# s2_ptr (sp + 12)
+# size (sp + 16)
+
+.text
+ .align 1
+.globl ___mpn_sub_n
+___mpn_sub_n:
+ .word 0x0
+ movl 16(ap),r0
+ movl 12(ap),r1
+ movl 8(ap),r2
+ movl 4(ap),r3
+ subl2 r4,r4
+
+Loop:
+ movl (r2)+,r4
+ sbwc (r1)+,r4
+ movl r4,(r3)+
+ jsobgtr r0,Loop
+
+ adwc r0,r0
+ ret
diff --git a/mpn/vax/submul_1.s b/mpn/vax/submul_1.s
new file mode 100644
index 000000000..c473937ca
--- /dev/null
+++ b/mpn/vax/submul_1.s
@@ -0,0 +1,126 @@
+# VAX __mpn_submul_1 -- Multiply a limb vector with a limb and subtract
+# the result from a second limb vector.
+
+# Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+# This file is part of the GNU MP Library.
+
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+
+# The GNU MP Library 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 Library General Public
+# License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+
+
+# INPUT PARAMETERS
+# res_ptr (sp + 4)
+# s1_ptr (sp + 8)
+# size (sp + 12)
+# s2_limb (sp + 16)
+
+.text
+ .align 1
+.globl ___mpn_submul_1
+___mpn_submul_1:
+ .word 0xfc0
+ movl 12(ap),r4
+ movl 8(ap),r8
+ movl 4(ap),r9
+ movl 16(ap),r6
+ jlss s2_big
+
+ clrl r3
+ incl r4
+ ashl $-1,r4,r7
+ jlbc r4,L1
+ clrl r11
+
+# Loop for S2_LIMB < 0x80000000
+Loop1: movl (r8)+,r1
+ jlss L1n0
+ emul r1,r6,$0,r2
+ addl2 r11,r2
+ adwc $0,r3
+ subl2 r2,(r9)+
+ adwc $0,r3
+L1: movl (r8)+,r1
+ jlss L1n1
+L1p1: emul r1,r6,$0,r10
+ addl2 r3,r10
+ adwc $0,r11
+ subl2 r10,(r9)+
+ adwc $0,r11
+
+ jsobgtr r7,Loop1
+ movl r11,r0
+ ret
+
+L1n0: emul r1,r6,$0,r2
+ addl2 r11,r2
+ adwc r6,r3
+ subl2 r2,(r9)+
+ adwc $0,r3
+ movl (r8)+,r1
+ jgeq L1p1
+L1n1: emul r1,r6,$0,r10
+ addl2 r3,r10
+ adwc r6,r11
+ subl2 r10,(r9)+
+ adwc $0,r11
+
+ jsobgtr r7,Loop1
+ movl r11,r0
+ ret
+
+
+s2_big: clrl r3
+ incl r4
+ ashl $-1,r4,r7
+ jlbc r4,L2
+ clrl r11
+
+# Loop for S2_LIMB >= 0x80000000
+Loop2: movl (r8)+,r1
+ jlss L2n0
+ emul r1,r6,$0,r2
+ addl2 r11,r2
+ adwc r1,r3
+ subl2 r2,(r9)+
+ adwc $0,r3
+L2: movl (r8)+,r1
+ jlss L2n1
+L2p1: emul r1,r6,$0,r10
+ addl2 r3,r10
+ adwc r1,r11
+ subl2 r10,(r9)+
+ adwc $0,r11
+
+ jsobgtr r7,Loop2
+ movl r11,r0
+ ret
+
+L2n0: emul r1,r6,$0,r2
+ addl2 r11,r2
+ adwc r6,r3
+ subl2 r2,(r9)+
+ adwc r1,r3
+ movl (r8)+,r1
+ jgeq L2p1
+L2n1: emul r1,r6,$0,r10
+ addl2 r3,r10
+ adwc r6,r11
+ subl2 r10,(r9)+
+ adwc r1,r11
+
+ jsobgtr r7,Loop2
+ movl r11,r0
+ ret
diff --git a/mpn/x86/add_n.S b/mpn/x86/add_n.S
new file mode 100644
index 000000000..9c1b13322
--- /dev/null
+++ b/mpn/x86/add_n.S
@@ -0,0 +1,106 @@
+/* i80386 __mpn_add_n -- Add two limb vectors of the same length > 0 and store
+sum in a third limb vector.
+
+Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/*
+ INPUT PARAMETERS
+ res_ptr (sp + 4)
+ s1_ptr (sp + 8)
+ s2_ptr (sp + 12)
+ size (sp + 16)
+*/
+
+#include "sysdep.h"
+#include "asm-syntax.h"
+
+.text
+ ALIGN (3)
+ .globl C_SYMBOL_NAME(__mpn_add_n)
+C_SYMBOL_NAME(__mpn_add_n:)
+ pushl %edi
+ pushl %esi
+
+ movl 12(%esp),%edi /* res_ptr */
+ movl 16(%esp),%esi /* s1_ptr */
+ movl 20(%esp),%edx /* s2_ptr */
+ movl 24(%esp),%ecx /* size */
+
+ movl %ecx,%eax
+ shrl $3,%ecx /* compute count for unrolled loop */
+ negl %eax
+ andl $7,%eax /* get index where to start loop */
+ jz Loop /* necessary special case for 0 */
+ incl %ecx /* adjust loop count */
+ shll $2,%eax /* adjustment for pointers... */
+ subl %eax,%edi /* ... since they are offset ... */
+ subl %eax,%esi /* ... by a constant when we ... */
+ subl %eax,%edx /* ... enter the loop */
+ shrl $2,%eax /* restore previous value */
+#ifdef PIC
+/* Calculate start address in loop for PIC. Due to limitations in some
+ assemblers, Loop-L0-3 cannot be put into the leal */
+ call L0
+L0: leal (%eax,%eax,8),%eax
+ addl (%esp),%eax
+ addl $(Loop-L0-3),%eax
+ addl $4,%esp
+#else
+/* Calculate start address in loop for non-PIC. */
+ leal (Loop - 3)(%eax,%eax,8),%eax
+#endif
+ jmp *%eax /* jump into loop */
+ ALIGN (3)
+Loop: movl (%esi),%eax
+ adcl (%edx),%eax
+ movl %eax,(%edi)
+ movl 4(%esi),%eax
+ adcl 4(%edx),%eax
+ movl %eax,4(%edi)
+ movl 8(%esi),%eax
+ adcl 8(%edx),%eax
+ movl %eax,8(%edi)
+ movl 12(%esi),%eax
+ adcl 12(%edx),%eax
+ movl %eax,12(%edi)
+ movl 16(%esi),%eax
+ adcl 16(%edx),%eax
+ movl %eax,16(%edi)
+ movl 20(%esi),%eax
+ adcl 20(%edx),%eax
+ movl %eax,20(%edi)
+ movl 24(%esi),%eax
+ adcl 24(%edx),%eax
+ movl %eax,24(%edi)
+ movl 28(%esi),%eax
+ adcl 28(%edx),%eax
+ movl %eax,28(%edi)
+ leal 32(%edi),%edi
+ leal 32(%esi),%esi
+ leal 32(%edx),%edx
+ decl %ecx
+ jnz Loop
+
+ sbbl %eax,%eax
+ negl %eax
+
+ popl %esi
+ popl %edi
+ ret
diff --git a/mpn/x86/addmul_1.S b/mpn/x86/addmul_1.S
new file mode 100644
index 000000000..c11209d92
--- /dev/null
+++ b/mpn/x86/addmul_1.S
@@ -0,0 +1,76 @@
+/* i80386 __mpn_addmul_1 -- Multiply a limb vector with a limb and add
+ the result to a second limb vector.
+
+Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/*
+ INPUT PARAMETERS
+ res_ptr (sp + 4)
+ s1_ptr (sp + 8)
+ size (sp + 12)
+ s2_limb (sp + 16)
+*/
+
+#include "sysdep.h"
+#include "asm-syntax.h"
+
+#define res_ptr edi
+#define s1_ptr esi
+#define size ecx
+#define s2_limb ebp
+
+ TEXT
+ ALIGN (3)
+ GLOBL C_SYMBOL_NAME(__mpn_addmul_1)
+C_SYMBOL_NAME(__mpn_addmul_1:)
+
+ INSN1(push,l ,R(edi))
+ INSN1(push,l ,R(esi))
+ INSN1(push,l ,R(ebx))
+ INSN1(push,l ,R(ebp))
+
+ INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20))
+ INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24))
+ INSN2(mov,l ,R(size),MEM_DISP(esp,28))
+ INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32))
+
+ INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4))
+ INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4))
+ INSN1(neg,l ,R(size))
+ INSN2(xor,l ,R(ebx),R(ebx))
+ ALIGN (3)
+Loop:
+ INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4))
+ INSN1(mul,l ,R(s2_limb))
+ INSN2(add,l ,R(eax),R(ebx))
+ INSN2(adc,l ,R(edx),$0)
+ INSN2(add,l ,MEM_INDEX(res_ptr,size,4),R(eax))
+ INSN2(adc,l ,R(edx),$0)
+ INSN2(mov,l ,R(ebx),R(edx))
+
+ INSN1(inc,l ,R(size))
+ INSN1(jnz, ,Loop)
+ INSN2(mov,l ,R(eax),R(ebx))
+
+ INSN1(pop,l ,R(ebp))
+ INSN1(pop,l ,R(ebx))
+ INSN1(pop,l ,R(esi))
+ INSN1(pop,l ,R(edi))
+ ret
diff --git a/mpn/x86/gmp-mparam.h b/mpn/x86/gmp-mparam.h
new file mode 100644
index 000000000..d909cd2a5
--- /dev/null
+++ b/mpn/x86/gmp-mparam.h
@@ -0,0 +1,29 @@
+/* gmp-mparam.h -- Compiler/machine parameter header file.
+
+Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#define BITS_PER_MP_LIMB 32
+#define BYTES_PER_MP_LIMB 4
+#define BITS_PER_LONGINT 32
+#define BITS_PER_INT 32
+#define BITS_PER_SHORTINT 16
+#define BITS_PER_CHAR 8
+
+#define IEEE_DOUBLE_BIG_ENDIAN 0
diff --git a/mpn/x86/lshift.S b/mpn/x86/lshift.S
new file mode 100644
index 000000000..8173b92cb
--- /dev/null
+++ b/mpn/x86/lshift.S
@@ -0,0 +1,85 @@
+/* i80386 __mpn_lshift --
+
+Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/*
+ INPUT PARAMETERS
+ res_ptr (sp + 4)
+ s_ptr (sp + 8)
+ size (sp + 12)
+ cnt (sp + 16)
+*/
+
+#include "sysdep.h"
+#include "asm-syntax.h"
+
+.text
+ ALIGN (3)
+ .globl C_SYMBOL_NAME(__mpn_lshift)
+C_SYMBOL_NAME(__mpn_lshift:)
+ pushl %edi
+ pushl %esi
+ pushl %ebx
+
+ movl 16(%esp),%edi /* res_ptr */
+ movl 20(%esp),%esi /* s_ptr */
+ movl 24(%esp),%edx /* size */
+ movl 28(%esp),%ecx /* cnt */
+
+ subl $4,%esi /* adjust s_ptr */
+
+ movl (%esi,%edx,4),%ebx /* read most significant limb */
+ xorl %eax,%eax
+ shldl %cl,%ebx,%eax /* compute carry limb */
+ decl %edx
+ jz Lend
+ pushl %eax /* push carry limb onto stack */
+ testb $1,%edx
+ jnz L1 /* enter loop in the middle */
+ movl %ebx,%eax
+
+ ALIGN (3)
+Loop: movl (%esi,%edx,4),%ebx /* load next lower limb */
+ shldl %cl,%ebx,%eax /* compute result limb */
+ movl %eax,(%edi,%edx,4) /* store it */
+ decl %edx
+L1: movl (%esi,%edx,4),%eax
+ shldl %cl,%eax,%ebx
+ movl %ebx,(%edi,%edx,4)
+ decl %edx
+ jnz Loop
+
+ shll %cl,%eax /* compute least significant limb */
+ movl %eax,(%edi) /* store it */
+
+ popl %eax /* pop carry limb */
+
+ popl %ebx
+ popl %esi
+ popl %edi
+ ret
+
+Lend: shll %cl,%ebx /* compute least significant limb */
+ movl %ebx,(%edi) /* store it */
+
+ popl %ebx
+ popl %esi
+ popl %edi
+ ret
diff --git a/mpn/x86/mul_1.S b/mpn/x86/mul_1.S
new file mode 100644
index 000000000..b27139998
--- /dev/null
+++ b/mpn/x86/mul_1.S
@@ -0,0 +1,75 @@
+/* i80386 __mpn_mul_1 -- Multiply a limb vector with a limb and store
+ the result in a second limb vector.
+
+Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/*
+ INPUT PARAMETERS
+ res_ptr (sp + 4)
+ s1_ptr (sp + 8)
+ size (sp + 12)
+ s2_limb (sp + 16)
+*/
+
+#include "sysdep.h"
+#include "asm-syntax.h"
+
+#define res_ptr edi
+#define s1_ptr esi
+#define size ecx
+#define s2_limb ebp
+
+ TEXT
+ ALIGN (3)
+ GLOBL C_SYMBOL_NAME(__mpn_mul_1)
+C_SYMBOL_NAME(__mpn_mul_1:)
+
+ INSN1(push,l ,R(edi))
+ INSN1(push,l ,R(esi))
+ INSN1(push,l ,R(ebx))
+ INSN1(push,l ,R(ebp))
+
+ INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20))
+ INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24))
+ INSN2(mov,l ,R(size),MEM_DISP(esp,28))
+ INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32))
+
+ INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4))
+ INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4))
+ INSN1(neg,l ,R(size))
+ INSN2(xor,l ,R(ebx),R(ebx))
+ ALIGN (3)
+Loop:
+ INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4))
+ INSN1(mul,l ,R(s2_limb))
+ INSN2(add,l ,R(eax),R(ebx))
+ INSN2(mov,l ,MEM_INDEX(res_ptr,size,4),R(eax))
+ INSN2(adc,l ,R(edx),$0)
+ INSN2(mov,l ,R(ebx),R(edx))
+
+ INSN1(inc,l ,R(size))
+ INSN1(jnz, ,Loop)
+ INSN2(mov,l ,R(eax),R(ebx))
+
+ INSN1(pop,l ,R(ebp))
+ INSN1(pop,l ,R(ebx))
+ INSN1(pop,l ,R(esi))
+ INSN1(pop,l ,R(edi))
+ ret
diff --git a/mpn/x86/pentium/README b/mpn/x86/pentium/README
new file mode 100644
index 000000000..d73b08268
--- /dev/null
+++ b/mpn/x86/pentium/README
@@ -0,0 +1,26 @@
+This directory contains mpn functions optimized for Intel Pentium
+processors.
+
+RELEVANT OPTIMIZATION ISSUES
+
+1. Pentium doesn't allocate cache lines on writes, unlike most other modern
+processors. Since the functions in the mpn class do array writes, we have to
+handle allocating the destination cache lines by reading a word from it in the
+loops, to achieve the best performance.
+
+2. Pairing of memory operations requires that the two issued operations refer
+to different cache banks. The simplest way to insure this is to read/write
+two words from the same object. If we make operations on different objects,
+they might or might not be to the same cache bank.
+
+STATUS
+
+1. mpn_lshift and mpn_rshift run at about 6 cycles/limb, but the Pentium
+documentation indicates that they should take only 43/8 = 5.375 cycles/limb,
+or 5 cycles/limb asymptotically.
+
+2. mpn_add_n and mpn_sub_n run at asymptotically 2 cycles/limb. Due to loop
+overhead and other delays (cache refill?), they run at or near 2.5 cycles/limb.
+
+3. mpn_mul_1, mpn_addmul_1, mpn_submul_1 all run 1 cycle faster than they
+should...
diff --git a/mpn/x86/pentium/add_n.S b/mpn/x86/pentium/add_n.S
new file mode 100644
index 000000000..ac6f2819b
--- /dev/null
+++ b/mpn/x86/pentium/add_n.S
@@ -0,0 +1,130 @@
+/* Pentium __mpn_add_n -- Add two limb vectors of the same length > 0 and store
+ sum in a third limb vector.
+
+Copyright (C) 1992, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/*
+ INPUT PARAMETERS
+ res_ptr (sp + 4)
+ s1_ptr (sp + 8)
+ s2_ptr (sp + 12)
+ size (sp + 16)
+*/
+
+#include "sysdep.h"
+#include "asm-syntax.h"
+
+.text
+ ALIGN (3)
+ .globl C_SYMBOL_NAME(__mpn_add_n)
+C_SYMBOL_NAME(__mpn_add_n:)
+ pushl %edi
+ pushl %esi
+ pushl %ebx
+ pushl %ebp
+
+ movl 20(%esp),%edi /* res_ptr */
+ movl 24(%esp),%esi /* s1_ptr */
+ movl 28(%esp),%ebp /* s2_ptr */
+ movl 32(%esp),%ecx /* size */
+
+ movl (%ebp),%ebx
+
+ decl %ecx
+ movl %ecx,%edx
+ shrl $3,%ecx
+ andl $7,%edx
+ testl %ecx,%ecx /* zero carry flag */
+ jz Lend
+ pushl %edx
+
+ ALIGN (3)
+Loop: movl 28(%edi),%eax /* fetch destination cache line */
+ leal 32(%edi),%edi
+
+L1: movl (%esi),%eax
+ movl 4(%esi),%edx
+ adcl %ebx,%eax
+ movl 4(%ebp),%ebx
+ adcl %ebx,%edx
+ movl 8(%ebp),%ebx
+ movl %eax,-32(%edi)
+ movl %edx,-28(%edi)
+
+L2: movl 8(%esi),%eax
+ movl 12(%esi),%edx
+ adcl %ebx,%eax
+ movl 12(%ebp),%ebx
+ adcl %ebx,%edx
+ movl 16(%ebp),%ebx
+ movl %eax,-24(%edi)
+ movl %edx,-20(%edi)
+
+L3: movl 16(%esi),%eax
+ movl 20(%esi),%edx
+ adcl %ebx,%eax
+ movl 20(%ebp),%ebx
+ adcl %ebx,%edx
+ movl 24(%ebp),%ebx
+ movl %eax,-16(%edi)
+ movl %edx,-12(%edi)
+
+L4: movl 24(%esi),%eax
+ movl 28(%esi),%edx
+ adcl %ebx,%eax
+ movl 28(%ebp),%ebx
+ adcl %ebx,%edx
+ movl 32(%ebp),%ebx
+ movl %eax,-8(%edi)
+ movl %edx,-4(%edi)
+
+ leal 32(%esi),%esi
+ leal 32(%ebp),%ebp
+ decl %ecx
+ jnz Loop
+
+ popl %edx
+Lend:
+ decl %edx /* test %edx w/o clobbering carry */
+ js Lend2
+ incl %edx
+Loop2:
+ leal 4(%edi),%edi
+ movl (%esi),%eax
+ adcl %ebx,%eax
+ movl 4(%ebp),%ebx
+ movl %eax,-4(%edi)
+ leal 4(%esi),%esi
+ leal 4(%ebp),%ebp
+ decl %edx
+ jnz Loop2
+Lend2:
+ movl (%esi),%eax
+ adcl %ebx,%eax
+ movl %eax,(%edi)
+
+ sbbl %eax,%eax
+ negl %eax
+
+ popl %ebp
+ popl %ebx
+ popl %esi
+ popl %edi
+ ret
diff --git a/mpn/x86/pentium/addmul_1.S b/mpn/x86/pentium/addmul_1.S
new file mode 100644
index 000000000..7cfa5db68
--- /dev/null
+++ b/mpn/x86/pentium/addmul_1.S
@@ -0,0 +1,83 @@
+/* Pentium __mpn_addmul_1 -- Multiply a limb vector with a limb and add
+ the result to a second limb vector.
+
+Copyright (C) 1992, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/*
+ INPUT PARAMETERS
+ res_ptr (sp + 4)
+ s1_ptr (sp + 8)
+ size (sp + 12)
+ s2_limb (sp + 16)
+*/
+
+#include "sysdep.h"
+#include "asm-syntax.h"
+
+#define res_ptr edi
+#define s1_ptr esi
+#define size ecx
+#define s2_limb ebp
+
+ TEXT
+ ALIGN (3)
+ GLOBL C_SYMBOL_NAME(__mpn_addmul_1)
+C_SYMBOL_NAME(__mpn_addmul_1:)
+
+ INSN1(push,l ,R(edi))
+ INSN1(push,l ,R(esi))
+ INSN1(push,l ,R(ebx))
+ INSN1(push,l ,R(ebp))
+
+ INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20))
+ INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24))
+ INSN2(mov,l ,R(size),MEM_DISP(esp,28))
+ INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32))
+
+ INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4))
+ INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4))
+ INSN1(neg,l ,R(size))
+ INSN2(xor,l ,R(ebx),R(ebx))
+ ALIGN (3)
+
+Loop: INSN2(adc,l ,R(ebx),$0)
+ INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4))
+
+ INSN1(mul,l ,R(s2_limb))
+
+ INSN2(add,l ,R(eax),R(ebx))
+ INSN2(mov,l ,R(ebx),MEM_INDEX(res_ptr,size,4))
+
+ INSN2(adc,l ,R(edx),$0)
+ INSN2(add,l ,R(ebx),R(eax))
+
+ INSN2(mov,l ,MEM_INDEX(res_ptr,size,4),R(ebx))
+ INSN1(inc,l ,R(size))
+
+ INSN2(mov,l ,R(ebx),R(edx))
+ INSN1(jnz, ,Loop)
+
+ INSN2(adc,l ,R(ebx),$0)
+ INSN2(mov,l ,R(eax),R(ebx))
+ INSN1(pop,l ,R(ebp))
+ INSN1(pop,l ,R(ebx))
+ INSN1(pop,l ,R(esi))
+ INSN1(pop,l ,R(edi))
+ ret
diff --git a/mpn/x86/pentium/lshift.S b/mpn/x86/pentium/lshift.S
new file mode 100644
index 000000000..b29898356
--- /dev/null
+++ b/mpn/x86/pentium/lshift.S
@@ -0,0 +1,217 @@
+/* Pentium optimized __mpn_lshift --
+
+Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/*
+ INPUT PARAMETERS
+ res_ptr (sp + 4)
+ s_ptr (sp + 8)
+ size (sp + 12)
+ cnt (sp + 16)
+*/
+
+#include "sysdep.h"
+#include "asm-syntax.h"
+
+.text
+ ALIGN (3)
+ .globl C_SYMBOL_NAME(__mpn_lshift)
+C_SYMBOL_NAME(__mpn_lshift:)
+ pushl %edi
+ pushl %esi
+ pushl %ebx
+ pushl %ebp
+
+ movl 20(%esp),%edi /* res_ptr */
+ movl 24(%esp),%esi /* s_ptr */
+ movl 28(%esp),%ebp /* size */
+ movl 32(%esp),%ecx /* cnt */
+
+/* We can use faster code for shift-by-1 under certain conditions. */
+ cmp $1,%ecx
+ jne Lnormal
+ leal 4(%esi),%eax
+ cmpl %edi,%eax
+ jnc Lspecial /* jump if s_ptr + 1 >= res_ptr */
+ leal (%esi,%ebp,4),%eax
+ cmpl %eax,%edi
+ jnc Lspecial /* jump if res_ptr >= s_ptr + size */
+
+Lnormal:
+ leal -4(%edi,%ebp,4),%edi
+ leal -4(%esi,%ebp,4),%esi
+
+ movl (%esi),%edx
+ subl $4,%esi
+ xorl %eax,%eax
+ shldl %cl,%edx,%eax /* compute carry limb */
+ pushl %eax /* push carry limb onto stack */
+
+ decl %ebp
+ pushl %ebp
+ shrl $3,%ebp
+ jz Lend
+
+ movl (%edi),%eax /* fetch destination cache line */
+
+ ALIGN (2)
+Loop: movl -28(%edi),%eax /* fetch destination cache line */
+ movl %edx,%ebx
+
+ movl (%esi),%eax
+ movl -4(%esi),%edx
+ shldl %cl,%eax,%ebx
+ shldl %cl,%edx,%eax
+ movl %ebx,(%edi)
+ movl %eax,-4(%edi)
+
+ movl -8(%esi),%ebx
+ movl -12(%esi),%eax
+ shldl %cl,%ebx,%edx
+ shldl %cl,%eax,%ebx
+ movl %edx,-8(%edi)
+ movl %ebx,-12(%edi)
+
+ movl -16(%esi),%edx
+ movl -20(%esi),%ebx
+ shldl %cl,%edx,%eax
+ shldl %cl,%ebx,%edx
+ movl %eax,-16(%edi)
+ movl %edx,-20(%edi)
+
+ movl -24(%esi),%eax
+ movl -28(%esi),%edx
+ shldl %cl,%eax,%ebx
+ shldl %cl,%edx,%eax
+ movl %ebx,-24(%edi)
+ movl %eax,-28(%edi)
+
+ subl $32,%esi
+ subl $32,%edi
+ decl %ebp
+ jnz Loop
+
+Lend: popl %ebp
+ andl $7,%ebp
+ jz Lend2
+Loop2: movl (%esi),%eax
+ shldl %cl,%eax,%edx
+ movl %edx,(%edi)
+ movl %eax,%edx
+ subl $4,%esi
+ subl $4,%edi
+ decl %ebp
+ jnz Loop2
+
+Lend2: shll %cl,%edx /* compute least significant limb */
+ movl %edx,(%edi) /* store it */
+
+ popl %eax /* pop carry limb */
+
+ popl %ebp
+ popl %ebx
+ popl %esi
+ popl %edi
+ ret
+
+/* We loop from least significant end of the arrays, which is only
+ permissable if the source and destination don't overlap, since the
+ function is documented to work for overlapping source and destination.
+*/
+
+Lspecial:
+ movl (%esi),%edx
+ addl $4,%esi
+
+ decl %ebp
+ pushl %ebp
+ shrl $3,%ebp
+
+ addl %edx,%edx
+ incl %ebp
+ decl %ebp
+ jz LLend
+
+ movl (%edi),%eax /* fetch destination cache line */
+
+ ALIGN (2)
+LLoop: movl 28(%edi),%eax /* fetch destination cache line */
+ movl %edx,%ebx
+
+ movl (%esi),%eax
+ movl 4(%esi),%edx
+ adcl %eax,%eax
+ movl %ebx,(%edi)
+ adcl %edx,%edx
+ movl %eax,4(%edi)
+
+ movl 8(%esi),%ebx
+ movl 12(%esi),%eax
+ adcl %ebx,%ebx
+ movl %edx,8(%edi)
+ adcl %eax,%eax
+ movl %ebx,12(%edi)
+
+ movl 16(%esi),%edx
+ movl 20(%esi),%ebx
+ adcl %edx,%edx
+ movl %eax,16(%edi)
+ adcl %ebx,%ebx
+ movl %edx,20(%edi)
+
+ movl 24(%esi),%eax
+ movl 28(%esi),%edx
+ adcl %eax,%eax
+ movl %ebx,24(%edi)
+ adcl %edx,%edx
+ movl %eax,28(%edi)
+
+ leal 32(%esi),%esi /* use leal not to clobber carry */
+ leal 32(%edi),%edi
+ decl %ebp
+ jnz LLoop
+
+LLend: popl %ebp
+ sbbl %eax,%eax /* save carry in %eax */
+ andl $7,%ebp
+ jz LLend2
+ addl %eax,%eax /* restore carry from eax */
+LLoop2: movl %edx,%ebx
+ movl (%esi),%edx
+ adcl %edx,%edx
+ movl %ebx,(%edi)
+
+ leal 4(%esi),%esi /* use leal not to clobber carry */
+ leal 4(%edi),%edi
+ decl %ebp
+ jnz LLoop2
+
+ jmp LL1
+LLend2: addl %eax,%eax /* restore carry from eax */
+LL1: movl %edx,(%edi) /* store last limb */
+
+ sbbl %eax,%eax
+ negl %eax
+
+ popl %ebp
+ popl %ebx
+ popl %esi
+ popl %edi
+ ret
diff --git a/mpn/x86/pentium/mul_1.S b/mpn/x86/pentium/mul_1.S
new file mode 100644
index 000000000..4ac3050a6
--- /dev/null
+++ b/mpn/x86/pentium/mul_1.S
@@ -0,0 +1,79 @@
+/* Pentium __mpn_mul_1 -- Multiply a limb vector with a limb and store
+ the result in a second limb vector.
+
+Copyright (C) 1992, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/*
+ INPUT PARAMETERS
+ res_ptr (sp + 4)
+ s1_ptr (sp + 8)
+ size (sp + 12)
+ s2_limb (sp + 16)
+*/
+
+#include "sysdep.h"
+#include "asm-syntax.h"
+
+#define res_ptr edi
+#define s1_ptr esi
+#define size ecx
+#define s2_limb ebp
+
+ TEXT
+ ALIGN (3)
+ GLOBL C_SYMBOL_NAME(__mpn_mul_1)
+C_SYMBOL_NAME(__mpn_mul_1:)
+
+ INSN1(push,l ,R(edi))
+ INSN1(push,l ,R(esi))
+ INSN1(push,l ,R(ebx))
+ INSN1(push,l ,R(ebp))
+
+ INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20))
+ INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24))
+ INSN2(mov,l ,R(size),MEM_DISP(esp,28))
+ INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32))
+
+ INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4))
+ INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4))
+ INSN1(neg,l ,R(size))
+ INSN2(xor,l ,R(ebx),R(ebx))
+ ALIGN (3)
+
+Loop: INSN2(adc,l ,R(ebx),$0)
+ INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4))
+
+ INSN1(mul,l ,R(s2_limb))
+
+ INSN2(add,l ,R(ebx),R(eax))
+
+ INSN2(mov,l ,MEM_INDEX(res_ptr,size,4),R(ebx))
+ INSN1(inc,l ,R(size))
+
+ INSN2(mov,l ,R(ebx),R(edx))
+ INSN1(jnz, ,Loop)
+
+ INSN2(adc,l ,R(ebx),$0)
+ INSN2(mov,l ,R(eax),R(ebx))
+ INSN1(pop,l ,R(ebp))
+ INSN1(pop,l ,R(ebx))
+ INSN1(pop,l ,R(esi))
+ INSN1(pop,l ,R(edi))
+ ret
diff --git a/mpn/x86/pentium/rshift.S b/mpn/x86/pentium/rshift.S
new file mode 100644
index 000000000..38398edb1
--- /dev/null
+++ b/mpn/x86/pentium/rshift.S
@@ -0,0 +1,217 @@
+/* Pentium optimized __mpn_rshift --
+
+Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/*
+ INPUT PARAMETERS
+ res_ptr (sp + 4)
+ s_ptr (sp + 8)
+ size (sp + 12)
+ cnt (sp + 16)
+*/
+
+#include "sysdep.h"
+#include "asm-syntax.h"
+
+.text
+ ALIGN (3)
+ .globl C_SYMBOL_NAME(__mpn_rshift)
+C_SYMBOL_NAME(__mpn_rshift:)
+ pushl %edi
+ pushl %esi
+ pushl %ebx
+ pushl %ebp
+
+ movl 20(%esp),%edi /* res_ptr */
+ movl 24(%esp),%esi /* s_ptr */
+ movl 28(%esp),%ebp /* size */
+ movl 32(%esp),%ecx /* cnt */
+
+/* We can use faster code for shift-by-1 under certain conditions. */
+ cmp $1,%ecx
+ jne Lnormal
+ leal 4(%edi),%eax
+ cmpl %esi,%eax
+ jnc Lspecial /* jump if res_ptr + 1 >= s_ptr */
+ leal (%edi,%ebp,4),%eax
+ cmpl %eax,%esi
+ jnc Lspecial /* jump if s_ptr >= res_ptr + size */
+
+Lnormal:
+ movl (%esi),%edx
+ addl $4,%esi
+ xorl %eax,%eax
+ shrdl %cl,%edx,%eax /* compute carry limb */
+ pushl %eax /* push carry limb onto stack */
+
+ decl %ebp
+ pushl %ebp
+ shrl $3,%ebp
+ jz Lend
+
+ movl (%edi),%eax /* fetch destination cache line */
+
+ ALIGN (2)
+Loop: movl 28(%edi),%eax /* fetch destination cache line */
+ movl %edx,%ebx
+
+ movl (%esi),%eax
+ movl 4(%esi),%edx
+ shrdl %cl,%eax,%ebx
+ shrdl %cl,%edx,%eax
+ movl %ebx,(%edi)
+ movl %eax,4(%edi)
+
+ movl 8(%esi),%ebx
+ movl 12(%esi),%eax
+ shrdl %cl,%ebx,%edx
+ shrdl %cl,%eax,%ebx
+ movl %edx,8(%edi)
+ movl %ebx,12(%edi)
+
+ movl 16(%esi),%edx
+ movl 20(%esi),%ebx
+ shrdl %cl,%edx,%eax
+ shrdl %cl,%ebx,%edx
+ movl %eax,16(%edi)
+ movl %edx,20(%edi)
+
+ movl 24(%esi),%eax
+ movl 28(%esi),%edx
+ shrdl %cl,%eax,%ebx
+ shrdl %cl,%edx,%eax
+ movl %ebx,24(%edi)
+ movl %eax,28(%edi)
+
+ addl $32,%esi
+ addl $32,%edi
+ decl %ebp
+ jnz Loop
+
+Lend: popl %ebp
+ andl $7,%ebp
+ jz Lend2
+Loop2: movl (%esi),%eax
+ shrdl %cl,%eax,%edx /* compute result limb */
+ movl %edx,(%edi)
+ movl %eax,%edx
+ addl $4,%esi
+ addl $4,%edi
+ decl %ebp
+ jnz Loop2
+
+Lend2: shrl %cl,%edx /* compute most significant limb */
+ movl %edx,(%edi) /* store it */
+
+ popl %eax /* pop carry limb */
+
+ popl %ebp
+ popl %ebx
+ popl %esi
+ popl %edi
+ ret
+
+/* We loop from least significant end of the arrays, which is only
+ permissable if the source and destination don't overlap, since the
+ function is documented to work for overlapping source and destination.
+*/
+
+Lspecial:
+ leal -4(%edi,%ebp,4),%edi
+ leal -4(%esi,%ebp,4),%esi
+
+ movl (%esi),%edx
+ subl $4,%esi
+
+ decl %ebp
+ pushl %ebp
+ shrl $3,%ebp
+
+ shrl $1,%edx
+ incl %ebp
+ decl %ebp
+ jz LLend
+
+ movl (%edi),%eax /* fetch destination cache line */
+
+ ALIGN (2)
+LLoop: movl -28(%edi),%eax /* fetch destination cache line */
+ movl %edx,%ebx
+
+ movl (%esi),%eax
+ movl -4(%esi),%edx
+ rcrl $1,%eax
+ movl %ebx,(%edi)
+ rcrl $1,%edx
+ movl %eax,-4(%edi)
+
+ movl -8(%esi),%ebx
+ movl -12(%esi),%eax
+ rcrl $1,%ebx
+ movl %edx,-8(%edi)
+ rcrl $1,%eax
+ movl %ebx,-12(%edi)
+
+ movl -16(%esi),%edx
+ movl -20(%esi),%ebx
+ rcrl $1,%edx
+ movl %eax,-16(%edi)
+ rcrl $1,%ebx
+ movl %edx,-20(%edi)
+
+ movl -24(%esi),%eax
+ movl -28(%esi),%edx
+ rcrl $1,%eax
+ movl %ebx,-24(%edi)
+ rcrl $1,%edx
+ movl %eax,-28(%edi)
+
+ leal -32(%esi),%esi /* use leal not to clobber carry */
+ leal -32(%edi),%edi
+ decl %ebp
+ jnz LLoop
+
+LLend: popl %ebp
+ sbbl %eax,%eax /* save carry in %eax */
+ andl $7,%ebp
+ jz LLend2
+ addl %eax,%eax /* restore carry from eax */
+LLoop2: movl %edx,%ebx
+ movl (%esi),%edx
+ rcrl $1,%edx
+ movl %ebx,(%edi)
+
+ leal -4(%esi),%esi /* use leal not to clobber carry */
+ leal -4(%edi),%edi
+ decl %ebp
+ jnz LLoop2
+
+ jmp LL1
+LLend2: addl %eax,%eax /* restore carry from eax */
+LL1: movl %edx,(%edi) /* store last limb */
+
+ movl $0,%eax
+ rcrl $1,%eax
+
+ popl %ebp
+ popl %ebx
+ popl %esi
+ popl %edi
+ ret
diff --git a/mpn/x86/pentium/sub_n.S b/mpn/x86/pentium/sub_n.S
new file mode 100644
index 000000000..d1a2bc084
--- /dev/null
+++ b/mpn/x86/pentium/sub_n.S
@@ -0,0 +1,130 @@
+/* Pentium __mpn_sub_n -- Subtract two limb vectors of the same length > 0
+ and store difference in a third limb vector.
+
+Copyright (C) 1992, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/*
+ INPUT PARAMETERS
+ res_ptr (sp + 4)
+ s1_ptr (sp + 8)
+ s2_ptr (sp + 12)
+ size (sp + 16)
+*/
+
+#include "sysdep.h"
+#include "asm-syntax.h"
+
+.text
+ ALIGN (3)
+ .globl C_SYMBOL_NAME(__mpn_sub_n)
+C_SYMBOL_NAME(__mpn_sub_n:)
+ pushl %edi
+ pushl %esi
+ pushl %ebx
+ pushl %ebp
+
+ movl 20(%esp),%edi /* res_ptr */
+ movl 24(%esp),%esi /* s1_ptr */
+ movl 28(%esp),%ebp /* s2_ptr */
+ movl 32(%esp),%ecx /* size */
+
+ movl (%ebp),%ebx
+
+ decl %ecx
+ movl %ecx,%edx
+ shrl $3,%ecx
+ andl $7,%edx
+ testl %ecx,%ecx /* zero carry flag */
+ jz Lend
+ pushl %edx
+
+ ALIGN (3)
+Loop: movl 28(%edi),%eax /* fetch destination cache line */
+ leal 32(%edi),%edi
+
+L1: movl (%esi),%eax
+ movl 4(%esi),%edx
+ sbbl %ebx,%eax
+ movl 4(%ebp),%ebx
+ sbbl %ebx,%edx
+ movl 8(%ebp),%ebx
+ movl %eax,-32(%edi)
+ movl %edx,-28(%edi)
+
+L2: movl 8(%esi),%eax
+ movl 12(%esi),%edx
+ sbbl %ebx,%eax
+ movl 12(%ebp),%ebx
+ sbbl %ebx,%edx
+ movl 16(%ebp),%ebx
+ movl %eax,-24(%edi)
+ movl %edx,-20(%edi)
+
+L3: movl 16(%esi),%eax
+ movl 20(%esi),%edx
+ sbbl %ebx,%eax
+ movl 20(%ebp),%ebx
+ sbbl %ebx,%edx
+ movl 24(%ebp),%ebx
+ movl %eax,-16(%edi)
+ movl %edx,-12(%edi)
+
+L4: movl 24(%esi),%eax
+ movl 28(%esi),%edx
+ sbbl %ebx,%eax
+ movl 28(%ebp),%ebx
+ sbbl %ebx,%edx
+ movl 32(%ebp),%ebx
+ movl %eax,-8(%edi)
+ movl %edx,-4(%edi)
+
+ leal 32(%esi),%esi
+ leal 32(%ebp),%ebp
+ decl %ecx
+ jnz Loop
+
+ popl %edx
+Lend:
+ decl %edx /* test %edx w/o clobbering carry */
+ js Lend2
+ incl %edx
+Loop2:
+ leal 4(%edi),%edi
+ movl (%esi),%eax
+ sbbl %ebx,%eax
+ movl 4(%ebp),%ebx
+ movl %eax,-4(%edi)
+ leal 4(%esi),%esi
+ leal 4(%ebp),%ebp
+ decl %edx
+ jnz Loop2
+Lend2:
+ movl (%esi),%eax
+ sbbl %ebx,%eax
+ movl %eax,(%edi)
+
+ sbbl %eax,%eax
+ negl %eax
+
+ popl %ebp
+ popl %ebx
+ popl %esi
+ popl %edi
+ ret
diff --git a/mpn/x86/pentium/submul_1.S b/mpn/x86/pentium/submul_1.S
new file mode 100644
index 000000000..adf2d63e6
--- /dev/null
+++ b/mpn/x86/pentium/submul_1.S
@@ -0,0 +1,83 @@
+/* Pentium __mpn_submul_1 -- Multiply a limb vector with a limb and subtract
+ the result from a second limb vector.
+
+Copyright (C) 1992, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/*
+ INPUT PARAMETERS
+ res_ptr (sp + 4)
+ s1_ptr (sp + 8)
+ size (sp + 12)
+ s2_limb (sp + 16)
+*/
+
+#include "sysdep.h"
+#include "asm-syntax.h"
+
+#define res_ptr edi
+#define s1_ptr esi
+#define size ecx
+#define s2_limb ebp
+
+ TEXT
+ ALIGN (3)
+ GLOBL C_SYMBOL_NAME(__mpn_submul_1)
+C_SYMBOL_NAME(__mpn_submul_1:)
+
+ INSN1(push,l ,R(edi))
+ INSN1(push,l ,R(esi))
+ INSN1(push,l ,R(ebx))
+ INSN1(push,l ,R(ebp))
+
+ INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20))
+ INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24))
+ INSN2(mov,l ,R(size),MEM_DISP(esp,28))
+ INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32))
+
+ INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4))
+ INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4))
+ INSN1(neg,l ,R(size))
+ INSN2(xor,l ,R(ebx),R(ebx))
+ ALIGN (3)
+
+Loop: INSN2(adc,l ,R(ebx),$0)
+ INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4))
+
+ INSN1(mul,l ,R(s2_limb))
+
+ INSN2(add,l ,R(eax),R(ebx))
+ INSN2(mov,l ,R(ebx),MEM_INDEX(res_ptr,size,4))
+
+ INSN2(adc,l ,R(edx),$0)
+ INSN2(sub,l ,R(ebx),R(eax))
+
+ INSN2(mov,l ,MEM_INDEX(res_ptr,size,4),R(ebx))
+ INSN1(inc,l ,R(size))
+
+ INSN2(mov,l ,R(ebx),R(edx))
+ INSN1(jnz, ,Loop)
+
+ INSN2(adc,l ,R(ebx),$0)
+ INSN2(mov,l ,R(eax),R(ebx))
+ INSN1(pop,l ,R(ebp))
+ INSN1(pop,l ,R(ebx))
+ INSN1(pop,l ,R(esi))
+ INSN1(pop,l ,R(edi))
+ ret
diff --git a/mpn/x86/rshift.S b/mpn/x86/rshift.S
new file mode 100644
index 000000000..9abbf9a45
--- /dev/null
+++ b/mpn/x86/rshift.S
@@ -0,0 +1,87 @@
+/* i80386 __mpn_rshift --
+
+Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/*
+ INPUT PARAMETERS
+ res_ptr (sp + 4)
+ s_ptr (sp + 8)
+ size (sp + 12)
+ cnt (sp + 16)
+*/
+
+#include "sysdep.h"
+#include "asm-syntax.h"
+
+.text
+ ALIGN (3)
+ .globl C_SYMBOL_NAME(__mpn_rshift)
+C_SYMBOL_NAME(__mpn_rshift:)
+ pushl %edi
+ pushl %esi
+ pushl %ebx
+
+ movl 16(%esp),%edi /* res_ptr */
+ movl 20(%esp),%esi /* s_ptr */
+ movl 24(%esp),%edx /* size */
+ movl 28(%esp),%ecx /* cnt */
+
+ leal -4(%edi,%edx,4),%edi
+ leal (%esi,%edx,4),%esi
+ negl %edx
+
+ movl (%esi,%edx,4),%ebx /* read least significant limb */
+ xorl %eax,%eax
+ shrdl %cl,%ebx,%eax /* compute carry limb */
+ incl %edx
+ jz Lend
+ pushl %eax /* push carry limb onto stack */
+ testb $1,%edx
+ jnz L1 /* enter loop in the middle */
+ movl %ebx,%eax
+
+ ALIGN (3)
+Loop: movl (%esi,%edx,4),%ebx /* load next higher limb */
+ shrdl %cl,%ebx,%eax /* compute result limb */
+ movl %eax,(%edi,%edx,4) /* store it */
+ incl %edx
+L1: movl (%esi,%edx,4),%eax
+ shrdl %cl,%eax,%ebx
+ movl %ebx,(%edi,%edx,4)
+ incl %edx
+ jnz Loop
+
+ shrl %cl,%eax /* compute most significant limb */
+ movl %eax,(%edi) /* store it */
+
+ popl %eax /* pop carry limb */
+
+ popl %ebx
+ popl %esi
+ popl %edi
+ ret
+
+Lend: shrl %cl,%ebx /* compute most significant limb */
+ movl %ebx,(%edi) /* store it */
+
+ popl %ebx
+ popl %esi
+ popl %edi
+ ret
diff --git a/mpn/x86/sub_n.S b/mpn/x86/sub_n.S
new file mode 100644
index 000000000..ec93d1bd5
--- /dev/null
+++ b/mpn/x86/sub_n.S
@@ -0,0 +1,106 @@
+/* i80386 __mpn_sub_n -- Add two limb vectors of the same length > 0 and store
+ sum in a third limb vector.
+
+Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/*
+ INPUT PARAMETERS
+ res_ptr (sp + 4)
+ s1_ptr (sp + 8)
+ s2_ptr (sp + 12)
+ size (sp + 16)
+*/
+
+#include "sysdep.h"
+#include "asm-syntax.h"
+
+.text
+ ALIGN (3)
+ .globl C_SYMBOL_NAME(__mpn_sub_n)
+C_SYMBOL_NAME(__mpn_sub_n:)
+ pushl %edi
+ pushl %esi
+
+ movl 12(%esp),%edi /* res_ptr */
+ movl 16(%esp),%esi /* s1_ptr */
+ movl 20(%esp),%edx /* s2_ptr */
+ movl 24(%esp),%ecx /* size */
+
+ movl %ecx,%eax
+ shrl $3,%ecx /* compute count for unrolled loop */
+ negl %eax
+ andl $7,%eax /* get index where to start loop */
+ jz Loop /* necessary special case for 0 */
+ incl %ecx /* adjust loop count */
+ shll $2,%eax /* adjustment for pointers... */
+ subl %eax,%edi /* ... since they are offset ... */
+ subl %eax,%esi /* ... by a constant when we ... */
+ subl %eax,%edx /* ... enter the loop */
+ shrl $2,%eax /* restore previous value */
+#ifdef PIC
+/* Calculate start address in loop for PIC. Due to limitations in some
+ assemblers, Loop-L0-3 cannot be put into the leal */
+ call L0
+L0: leal (%eax,%eax,8),%eax
+ addl (%esp),%eax
+ addl $(Loop-L0-3),%eax
+ addl $4,%esp
+#else
+/* Calculate start address in loop for non-PIC. */
+ leal (Loop - 3)(%eax,%eax,8),%eax
+#endif
+ jmp *%eax /* jump into loop */
+ ALIGN (3)
+Loop: movl (%esi),%eax
+ sbbl (%edx),%eax
+ movl %eax,(%edi)
+ movl 4(%esi),%eax
+ sbbl 4(%edx),%eax
+ movl %eax,4(%edi)
+ movl 8(%esi),%eax
+ sbbl 8(%edx),%eax
+ movl %eax,8(%edi)
+ movl 12(%esi),%eax
+ sbbl 12(%edx),%eax
+ movl %eax,12(%edi)
+ movl 16(%esi),%eax
+ sbbl 16(%edx),%eax
+ movl %eax,16(%edi)
+ movl 20(%esi),%eax
+ sbbl 20(%edx),%eax
+ movl %eax,20(%edi)
+ movl 24(%esi),%eax
+ sbbl 24(%edx),%eax
+ movl %eax,24(%edi)
+ movl 28(%esi),%eax
+ sbbl 28(%edx),%eax
+ movl %eax,28(%edi)
+ leal 32(%edi),%edi
+ leal 32(%esi),%esi
+ leal 32(%edx),%edx
+ decl %ecx
+ jnz Loop
+
+ sbbl %eax,%eax
+ negl %eax
+
+ popl %esi
+ popl %edi
+ ret
diff --git a/mpn/x86/submul_1.S b/mpn/x86/submul_1.S
new file mode 100644
index 000000000..730e73204
--- /dev/null
+++ b/mpn/x86/submul_1.S
@@ -0,0 +1,76 @@
+/* i80386 __mpn_submul_1 -- Multiply a limb vector with a limb and subtract
+ the result from a second limb vector.
+
+Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/*
+ INPUT PARAMETERS
+ res_ptr (sp + 4)
+ s1_ptr (sp + 8)
+ size (sp + 12)
+ s2_limb (sp + 16)
+*/
+
+#include "sysdep.h"
+#include "asm-syntax.h"
+
+#define res_ptr edi
+#define s1_ptr esi
+#define size ecx
+#define s2_limb ebp
+
+ TEXT
+ ALIGN (3)
+ GLOBL C_SYMBOL_NAME(__mpn_submul_1)
+C_SYMBOL_NAME(__mpn_submul_1:)
+
+ INSN1(push,l ,R(edi))
+ INSN1(push,l ,R(esi))
+ INSN1(push,l ,R(ebx))
+ INSN1(push,l ,R(ebp))
+
+ INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20))
+ INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24))
+ INSN2(mov,l ,R(size),MEM_DISP(esp,28))
+ INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32))
+
+ INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4))
+ INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4))
+ INSN1(neg,l ,R(size))
+ INSN2(xor,l ,R(ebx),R(ebx))
+ ALIGN (3)
+Loop:
+ INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4))
+ INSN1(mul,l ,R(s2_limb))
+ INSN2(add,l ,R(eax),R(ebx))
+ INSN2(adc,l ,R(edx),$0)
+ INSN2(sub,l ,MEM_INDEX(res_ptr,size,4),R(eax))
+ INSN2(adc,l ,R(edx),$0)
+ INSN2(mov,l ,R(ebx),R(edx))
+
+ INSN1(inc,l ,R(size))
+ INSN1(jnz, ,Loop)
+ INSN2(mov,l ,R(eax),R(ebx))
+
+ INSN1(pop,l ,R(ebp))
+ INSN1(pop,l ,R(ebx))
+ INSN1(pop,l ,R(esi))
+ INSN1(pop,l ,R(edi))
+ ret
diff --git a/mpn/x86/syntax.h b/mpn/x86/syntax.h
new file mode 100644
index 000000000..c53c73c03
--- /dev/null
+++ b/mpn/x86/syntax.h
@@ -0,0 +1,62 @@
+/* asm.h -- Definitions for x86 syntax variations.
+
+Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+
+#undef ALIGN
+
+#if defined (BSD_SYNTAX) || defined (ELF_SYNTAX)
+#define R(r) %r
+#define MEM(base)(base)
+#define MEM_DISP(base,displacement)displacement(R(base))
+#define MEM_INDEX(base,index,size)(R(base),R(index),size)
+#ifdef __STDC__
+#define INSN1(mnemonic,size_suffix,dst)mnemonic##size_suffix dst
+#define INSN2(mnemonic,size_suffix,dst,src)mnemonic##size_suffix src,dst
+#else
+#define INSN1(mnemonic,size_suffix,dst)mnemonic/**/size_suffix dst
+#define INSN2(mnemonic,size_suffix,dst,src)mnemonic/**/size_suffix src,dst
+#endif
+#define TEXT .text
+#if defined (BSD_SYNTAX)
+#define ALIGN(log) .align log
+#endif
+#if defined (ELF_SYNTAX)
+#define ALIGN(log) .align 1<<(log)
+#endif
+#define GLOBL .globl
+#endif
+
+#ifdef INTEL_SYNTAX
+#define R(r) r
+#define MEM(base)[base]
+#define MEM_DISP(base,displacement)[base+(displacement)]
+#define MEM_INDEX(base,index,size)[base+index*size]
+#define INSN1(mnemonic,size_suffix,dst)mnemonic dst
+#define INSN2(mnemonic,size_suffix,dst,src)mnemonic dst,src
+#define TEXT .text
+#define ALIGN(log) .align log
+#define GLOBL .globl
+#endif
+
+#ifdef BROKEN_ALIGN
+#undef ALIGN
+#define ALIGN(log) .align log,0x90
+#endif
diff --git a/mpn/z8000/add_n.s b/mpn/z8000/add_n.s
new file mode 100644
index 000000000..a50fc3ef5
--- /dev/null
+++ b/mpn/z8000/add_n.s
@@ -0,0 +1,53 @@
+! Z8000 __mpn_add_n -- Add two limb vectors of equal, non-zero length.
+
+! Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP Library is free software; you can redistribute it and/or modify
+! it under the terms of the GNU Library General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or (at your
+! option) any later version.
+
+! The GNU MP Library 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 Library General Public
+! License for more details.
+
+! You should have received a copy of the GNU Library General Public License
+! along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+! MA 02111-1307, USA.
+
+
+! INPUT PARAMETERS
+! res_ptr r7
+! s1_ptr r6
+! s2_ptr r5
+! size r4
+
+! If we are really crazy, we can use push to write a few result words
+! backwards, using push just because it is faster than reg+disp. We'd
+! then add 2x the number of words written to r7...
+
+ unseg
+ .text
+ even
+ global ___mpn_add_n
+___mpn_add_n:
+ pop r0,@r6
+ pop r1,@r5
+ add r0,r1
+ ld @r7,r0
+ dec r4
+ jr eq,Lend
+Loop: pop r0,@r6
+ pop r1,@r5
+ adc r0,r1
+ inc r7,#2
+ ld @r7,r0
+ dec r4
+ jr ne,Loop
+Lend: ld r2,r4 ! use 0 already in r4
+ adc r2,r2
+ ret t
diff --git a/mpn/z8000/gmp-mparam.h b/mpn/z8000/gmp-mparam.h
new file mode 100644
index 000000000..e0a303e97
--- /dev/null
+++ b/mpn/z8000/gmp-mparam.h
@@ -0,0 +1,27 @@
+/* gmp-mparam.h -- Compiler/machine parameter header file.
+
+Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#define BITS_PER_MP_LIMB 16
+#define BYTES_PER_MP_LIMB 2
+#define BITS_PER_LONGINT 32
+#define BITS_PER_INT 16
+#define BITS_PER_SHORTINT 16
+#define BITS_PER_CHAR 8
diff --git a/mpn/z8000/mul_1.s b/mpn/z8000/mul_1.s
new file mode 100644
index 000000000..f1126b5ab
--- /dev/null
+++ b/mpn/z8000/mul_1.s
@@ -0,0 +1,68 @@
+! Z8000 __mpn_mul_1 -- Multiply a limb vector with a limb and store
+! the result in a second limb vector.
+
+! Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP Library is free software; you can redistribute it and/or modify
+! it under the terms of the GNU Library General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or (at your
+! option) any later version.
+
+! The GNU MP Library 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 Library General Public
+! License for more details.
+
+! You should have received a copy of the GNU Library General Public License
+! along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+! MA 02111-1307, USA.
+
+
+! INPUT PARAMETERS
+! res_ptr r7
+! s1_ptr r6
+! size r5
+! s2_limb r4
+
+ unseg
+ .text
+ even
+ global ___mpn_mul_1
+___mpn_mul_1:
+ sub r2,r2 ! zero carry limb
+ and r4,r4
+ jr mi,Lneg
+
+Lpos: pop r1,@r6
+ ld r9,r1
+ mult rr8,r4
+ and r1,r1 ! shift msb of loaded limb into cy
+ jr mi,Lp ! branch if loaded limb's msb is set
+ add r8,r4 ! hi_limb += sign_comp2
+Lp: add r9,r2 ! lo_limb += cy_limb
+ xor r2,r2
+ adc r2,r8
+ ld @r7,r9
+ inc r7,#2
+ dec r5
+ jr ne,Lpos
+ ret t
+
+Lneg: pop r1,@r6
+ ld r9,r1
+ mult rr8,r4
+ add r8,r1 ! hi_limb += sign_comp1
+ and r1,r1
+ jr mi,Ln
+ add r8,r4 ! hi_limb += sign_comp2
+Ln: add r9,r2 ! lo_limb += cy_limb
+ xor r2,r2
+ adc r2,r8
+ ld @r7,r9
+ inc r7,#2
+ dec r5
+ jr ne,Lneg
+ ret t
diff --git a/mpn/z8000/sub_n.s b/mpn/z8000/sub_n.s
new file mode 100644
index 000000000..272c671bd
--- /dev/null
+++ b/mpn/z8000/sub_n.s
@@ -0,0 +1,54 @@
+! Z8000 __mpn_sub_n -- Subtract two limb vectors of the same length > 0 and
+! store difference in a third limb vector.
+
+! Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP Library is free software; you can redistribute it and/or modify
+! it under the terms of the GNU Library General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or (at your
+! option) any later version.
+
+! The GNU MP Library 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 Library General Public
+! License for more details.
+
+! You should have received a copy of the GNU Library General Public License
+! along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+! MA 02111-1307, USA.
+
+
+! INPUT PARAMETERS
+! res_ptr r7
+! s1_ptr r6
+! s2_ptr r5
+! size r4
+
+! If we are really crazy, we can use push to write a few result words
+! backwards, using push just because it is faster than reg+disp. We'd
+! then add 2x the number of words written to r7...
+
+ unseg
+ .text
+ even
+ global ___mpn_sub_n
+___mpn_sub_n:
+ pop r0,@r6
+ pop r1,@r5
+ sub r0,r1
+ ld @r7,r0
+ dec r4
+ jr eq,Lend
+Loop: pop r0,@r6
+ pop r1,@r5
+ sbc r0,r1
+ inc r7,#2
+ ld @r7,r0
+ dec r4
+ jr ne,Loop
+Lend: ld r2,r4 ! use 0 already in r4
+ adc r2,r2
+ ret t
diff --git a/mpn/z8000x/add_n.s b/mpn/z8000x/add_n.s
new file mode 100644
index 000000000..c5c0d4275
--- /dev/null
+++ b/mpn/z8000x/add_n.s
@@ -0,0 +1,56 @@
+! Z8000 (32 bit limb version) __mpn_add_n -- Add two limb vectors of equal,
+! non-zero length.
+
+! Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP Library is free software; you can redistribute it and/or modify
+! it under the terms of the GNU Library General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or (at your
+! option) any later version.
+
+! The GNU MP Library 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 Library General Public
+! License for more details.
+
+! You should have received a copy of the GNU Library General Public License
+! along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+! MA 02111-1307, USA.
+
+
+! INPUT PARAMETERS
+! res_ptr r7
+! s1_ptr r6
+! s2_ptr r5
+! size r4
+
+! If we are really crazy, we can use push to write a few result words
+! backwards, using push just because it is faster than reg+disp. We'd
+! then add 2x the number of words written to r7...
+
+ segm
+ .text
+ even
+ global ___mpn_add_n
+___mpn_add_n:
+ popl rr0,@r6
+ popl rr8,@r5
+ addl rr0,rr8
+ ldl @r7,rr0
+ dec r4
+ jr eq,Lend
+Loop: popl rr0,@r6
+ popl rr8,@r5
+ adc r1,r9
+ adc r0,r8
+ inc r7,#4
+ ldl @r7,rr0
+ dec r4
+ jr ne,Loop
+Lend: ld r2,r4 ! use 0 already in r4
+ ld r3,r4
+ adc r2,r2
+ ret t
diff --git a/mpn/z8000x/sub_n.s b/mpn/z8000x/sub_n.s
new file mode 100644
index 000000000..9eeece69d
--- /dev/null
+++ b/mpn/z8000x/sub_n.s
@@ -0,0 +1,56 @@
+! Z8000 (32 bit limb version) __mpn_sub_n -- Subtract two limb vectors of the
+! same length > 0 and store difference in a third limb vector.
+
+! Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP Library is free software; you can redistribute it and/or modify
+! it under the terms of the GNU Library General Public License as published by
+! the Free Software Foundation; either version 2 of the License, or (at your
+! option) any later version.
+
+! The GNU MP Library 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 Library General Public
+! License for more details.
+
+! You should have received a copy of the GNU Library General Public License
+! along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+! MA 02111-1307, USA.
+
+
+! INPUT PARAMETERS
+! res_ptr r7
+! s1_ptr r6
+! s2_ptr r5
+! size r4
+
+! If we are really crazy, we can use push to write a few result words
+! backwards, using push just because it is faster than reg+disp. We'd
+! then add 2x the number of words written to r7...
+
+ segm
+ .text
+ even
+ global ___mpn_sub_n
+___mpn_sub_n:
+ popl rr0,@r6
+ popl rr8,@r5
+ subl rr0,rr8
+ ldl @r7,rr0
+ dec r4
+ jr eq,Lend
+Loop: popl rr0,@r6
+ popl rr8,@r5
+ sbc r1,r9
+ sbc r0,r8
+ inc r7,#4
+ ldl @r7,rr0
+ dec r4
+ jr ne,Loop
+Lend: ld r2,r4 ! use 0 already in r4
+ ld r3,r4
+ adc r2,r2
+ ret t
diff --git a/mpq/Makefile.in b/mpq/Makefile.in
new file mode 100644
index 000000000..26367f817
--- /dev/null
+++ b/mpq/Makefile.in
@@ -0,0 +1,83 @@
+# Makefile for GNU MP/mpq functions
+# Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+# This file is part of the GNU MP Library.
+
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+
+# The GNU MP Library 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 Library General Public
+# License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+
+srcdir = .
+
+CC = gcc
+
+CFLAGS = -g -O
+AR = ar
+AR_FLAGS = rc
+SHELL = /bin/sh
+
+#### host and target specific makefile fragments come in here.
+###
+
+MPQ_SRCS = add.c canonicalize.c clear.c cmp.c cmp_ui.c div.c get_d.c \
+ get_den.c get_num.c init.c inv.c mul.c neg.c set.c set_den.c set_num.c \
+ set_si.c set_ui.c sub.c equal.c
+MPQ_OBJS = add.o canonicalize.o clear.o cmp.o cmp_ui.o div.o get_d.o \
+ get_den.o get_num.o init.o inv.o mul.o neg.o set.o set_den.o set_num.o \
+ set_si.o set_ui.o sub.o equal.o
+
+INCLUDES = -I. -I.. -I../mpn -I$(srcdir)/..
+
+libmpq.a: Makefile.in $(MPQ_OBJS)
+ rm -f $@
+ $(AR) $(AR_FLAGS) $@ $(MPQ_OBJS)
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(XCFLAGS) $<
+
+test: libmpq.a
+ cd tests; $(MAKE) srcdir=$(srcdir) CC=$(CC) SHELL=$(SHELL)
+
+clean mostlyclean:
+ rm -f *.o libmpq.a
+ -cd tests; $(MAKE) $@
+distclean maintainer-clean: clean
+ rm -f Makefile config.status
+ -cd tests; $(MAKE) $@
+
+Makefile: $(srcdir)/Makefile.in
+ $(SHELL) ./config.status
+
+H = $(srcdir)/../gmp.h $(srcdir)/../gmp-impl.h ../mpn/gmp-mparam.h
+
+add.o: $(srcdir)/add.c $(H)
+canonicalize.o: $(srcdir)/canonicalize.c $(H)
+clear.o: $(srcdir)/clear.c $(H)
+cmp.o: $(srcdir)/cmp.c $(H) $(srcdir)/../longlong.h
+cmp_ui.o: $(srcdir)/cmp_ui.c $(H)
+div.o: $(srcdir)/div.c $(H)
+equal.o: $(srcdir)/equal.c $(H)
+get_d.o: $(srcdir)/get_d.c $(H) $(srcdir)/../longlong.h
+get_den.o: $(srcdir)/get_den.c $(H)
+get_num.o: $(srcdir)/get_num.c $(H)
+init.o: $(srcdir)/init.c $(H)
+inv.o: $(srcdir)/inv.c $(H)
+mul.o: $(srcdir)/mul.c $(H)
+neg.o: $(srcdir)/neg.c $(H)
+set.o: $(srcdir)/set.c $(H)
+set_den.o: $(srcdir)/set_den.c $(H)
+set_num.o: $(srcdir)/set_num.c $(H)
+set_si.o: $(srcdir)/set_si.c $(H)
+set_ui.o: $(srcdir)/set_ui.c $(H)
+sub.o: $(srcdir)/sub.c $(H)
diff --git a/mpq/add.c b/mpq/add.c
new file mode 100644
index 000000000..6b98b469e
--- /dev/null
+++ b/mpq/add.c
@@ -0,0 +1,85 @@
+/* mpq_add -- add two rational numbers.
+
+Copyright (C) 1991, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpq_add (mpq_ptr rop, mpq_srcptr op1, mpq_srcptr op2)
+#else
+mpq_add (rop, op1, op2)
+ mpq_ptr rop;
+ mpq_srcptr op1;
+ mpq_srcptr op2;
+#endif
+{
+ mpz_t gcd;
+ mpz_t tmp1, tmp2;
+ mp_size_t op1_num_size = ABS (op1->_mp_num._mp_size);
+ mp_size_t op1_den_size = ABS (op1->_mp_den._mp_size);
+ mp_size_t op2_num_size = ABS (op2->_mp_num._mp_size);
+ mp_size_t op2_den_size = ABS (op2->_mp_den._mp_size);
+ TMP_DECL (marker);
+
+ TMP_MARK (marker);
+ MPZ_TMP_INIT (gcd, MIN (op1_den_size, op2_den_size));
+ MPZ_TMP_INIT (tmp1, op1_num_size + op2_den_size);
+ MPZ_TMP_INIT (tmp2, op2_num_size + op1_den_size);
+
+ /* ROP might be identical to either operand, so don't store the
+ result there until we are finished with the input operands. We
+ dare to overwrite the numerator of ROP when we are finished
+ with the numerators of OP1 and OP2. */
+
+ mpz_gcd (gcd, &(op1->_mp_den), &(op2->_mp_den));
+ if (gcd->_mp_size > 1 || gcd->_mp_d[0] != 1)
+ {
+ mpz_t t;
+
+ mpz_divexact (tmp1, &(op2->_mp_den), gcd);
+ mpz_mul (tmp1, &(op1->_mp_num), tmp1);
+
+ mpz_divexact (tmp2, &(op1->_mp_den), gcd);
+ mpz_mul (tmp2, &(op2->_mp_num), tmp2);
+
+ MPZ_TMP_INIT (t, MAX (ABS (tmp1->_mp_size), ABS (tmp2->_mp_size)) + 1);
+
+ mpz_add (t, tmp1, tmp2);
+ mpz_divexact (tmp1, &(op1->_mp_den), gcd);
+ mpz_gcd (gcd, t, gcd);
+
+ mpz_divexact (&(rop->_mp_num), t, gcd);
+
+ mpz_divexact (tmp2, &(op2->_mp_den), gcd);
+ mpz_mul (&(rop->_mp_den), tmp1, tmp2);
+ }
+ else
+ {
+ /* The common divisor is 1. This is the case (for random input) with
+ probability 6/(pi**2). */
+ mpz_mul (tmp1, &(op1->_mp_num), &(op2->_mp_den));
+ mpz_mul (tmp2, &(op2->_mp_num), &(op1->_mp_den));
+ mpz_add (&(rop->_mp_num), tmp1, tmp2);
+ mpz_mul (&(rop->_mp_den), &(op1->_mp_den), &(op2->_mp_den));
+ }
+ TMP_FREE (marker);
+}
diff --git a/mpq/canonicalize.c b/mpq/canonicalize.c
new file mode 100644
index 000000000..901e6eb6c
--- /dev/null
+++ b/mpq/canonicalize.c
@@ -0,0 +1,53 @@
+/* mpq_canonicalize(op) -- Remove common factors of the denominator and
+ numerator in OP.
+
+Copyright (C) 1991, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpq_canonicalize (MP_RAT *op)
+#else
+mpq_canonicalize (op)
+ MP_RAT *op;
+#endif
+{
+ mpz_t gcd;
+ TMP_DECL (marker);
+
+ TMP_MARK (marker);
+
+ /* ??? Dunno if the 1+ is needed. */
+ MPZ_TMP_INIT (gcd, 1 + MAX (ABS (op->_mp_num._mp_size),
+ ABS (op->_mp_den._mp_size)));
+
+ mpz_gcd (gcd, &(op->_mp_num), &(op->_mp_den));
+ mpz_divexact (&(op->_mp_num), &(op->_mp_num), gcd);
+ mpz_divexact (&(op->_mp_den), &(op->_mp_den), gcd);
+
+ if (op->_mp_den._mp_size < 0)
+ {
+ op->_mp_num._mp_size = -op->_mp_num._mp_size;
+ op->_mp_den._mp_size = -op->_mp_den._mp_size;
+ }
+ TMP_FREE (marker);
+}
diff --git a/mpq/clear.c b/mpq/clear.c
new file mode 100644
index 000000000..2837cf2ad
--- /dev/null
+++ b/mpq/clear.c
@@ -0,0 +1,37 @@
+/* mpq_clear -- free the space occupied by a MP_RAT.
+
+Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpq_clear (MP_RAT *m)
+#else
+mpq_clear (m)
+ MP_RAT *m;
+#endif
+{
+ (*_mp_free_func) (m->_mp_num._mp_d,
+ m->_mp_num._mp_alloc * BYTES_PER_MP_LIMB);
+ (*_mp_free_func) (m->_mp_den._mp_d,
+ m->_mp_den._mp_alloc * BYTES_PER_MP_LIMB);
+}
diff --git a/mpq/cmp.c b/mpq/cmp.c
new file mode 100644
index 000000000..fc530e395
--- /dev/null
+++ b/mpq/cmp.c
@@ -0,0 +1,120 @@
+/* mpq_cmp(u,v) -- Compare U, V. Return postive, zero, or negative
+ based on if U > V, U == V, or U < V.
+
+Copyright (C) 1991, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+int
+#if __STDC__
+mpq_cmp (const MP_RAT *op1, const MP_RAT *op2)
+#else
+mpq_cmp (op1, op2)
+ const MP_RAT *op1;
+ const MP_RAT *op2;
+#endif
+{
+ mp_size_t num1_size = op1->_mp_num._mp_size;
+ mp_size_t den1_size = op1->_mp_den._mp_size;
+ mp_size_t num2_size = op2->_mp_num._mp_size;
+ mp_size_t den2_size = op2->_mp_den._mp_size;
+ mp_size_t tmp1_size, tmp2_size;
+ mp_ptr tmp1_ptr, tmp2_ptr;
+ mp_size_t num1_sign;
+ int cc;
+ TMP_DECL (marker);
+
+ if (num1_size == 0)
+ return -num2_size;
+ if (num2_size == 0)
+ return num1_size;
+ if ((num1_size ^ num2_size) < 0) /* I.e. are the signs different? */
+ return num1_size;
+
+ num1_sign = num1_size;
+ num1_size = ABS (num1_size);
+ num2_size = ABS (num2_size);
+
+ tmp1_size = num1_size + den2_size;
+ tmp2_size = num2_size + den1_size;
+
+ /* 1. Check to see if we can tell which operand is larger by just looking at
+ the number of limbs. */
+
+ /* NUM1 x DEN2 is either TMP1_SIZE limbs or TMP1_SIZE-1 limbs.
+ Same for NUM1 x DEN1 with respect to TMP2_SIZE. */
+ if (tmp1_size > tmp2_size + 1)
+ /* NUM1 x DEN2 is surely larger in magnitude than NUM2 x DEN1. */
+ return num1_sign;
+ if (tmp2_size > tmp1_size + 1)
+ /* NUM1 x DEN2 is surely smaller in magnitude than NUM2 x DEN1. */
+ return -num1_sign;
+
+ /* 2. Same, but compare the number of significant bits. */
+ {
+ int cnt1, cnt2;
+ unsigned long int bits1, bits2;
+
+ count_leading_zeros (cnt1, op1->_mp_num._mp_d[num1_size - 1]);
+ count_leading_zeros (cnt2, op2->_mp_den._mp_d[den2_size - 1]);
+ bits1 = tmp1_size * BITS_PER_MP_LIMB - cnt1 - cnt2;
+
+ count_leading_zeros (cnt1, op2->_mp_num._mp_d[num2_size - 1]);
+ count_leading_zeros (cnt2, op1->_mp_den._mp_d[den1_size - 1]);
+ bits2 = tmp2_size * BITS_PER_MP_LIMB - cnt1 - cnt2;
+
+ if (bits1 > bits2 + 1)
+ return num1_sign;
+ if (bits2 > bits1 + 1)
+ return -num1_sign;
+ }
+
+ /* 3. Finally, cross multiply and compare. */
+
+ TMP_MARK (marker);
+ tmp1_ptr = (mp_ptr) TMP_ALLOC (tmp1_size * BYTES_PER_MP_LIMB);
+ tmp2_ptr = (mp_ptr) TMP_ALLOC (tmp2_size * BYTES_PER_MP_LIMB);
+
+ if (num1_size >= den2_size)
+ tmp1_size -= 0 == mpn_mul (tmp1_ptr,
+ op1->_mp_num._mp_d, num1_size,
+ op2->_mp_den._mp_d, den2_size);
+ else
+ tmp1_size -= 0 == mpn_mul (tmp1_ptr,
+ op2->_mp_den._mp_d, den2_size,
+ op1->_mp_num._mp_d, num1_size);
+
+ if (num2_size >= den1_size)
+ tmp2_size -= 0 == mpn_mul (tmp2_ptr,
+ op2->_mp_num._mp_d, num2_size,
+ op1->_mp_den._mp_d, den1_size);
+ else
+ tmp2_size -= 0 == mpn_mul (tmp2_ptr,
+ op1->_mp_den._mp_d, den1_size,
+ op2->_mp_num._mp_d, num2_size);
+
+
+ cc = tmp1_size - tmp2_size != 0
+ ? tmp1_size - tmp2_size : mpn_cmp (tmp1_ptr, tmp2_ptr, tmp1_size);
+ TMP_FREE (marker);
+ return num1_sign < 0 ? -cc : cc;
+}
diff --git a/mpq/cmp_ui.c b/mpq/cmp_ui.c
new file mode 100644
index 000000000..bdecec5f8
--- /dev/null
+++ b/mpq/cmp_ui.c
@@ -0,0 +1,84 @@
+/* mpq_cmp_ui(u,vn,vd) -- Compare U with Vn/Vd. Return positive, zero, or
+ negative based on if U > V, U == V, or U < V. Vn and Vd may have
+ common factors.
+
+Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+/* gmp.h defines a macro for mpq_cmp_ui. */
+#undef mpq_cmp_ui
+
+int
+#if __STDC__
+mpq_cmp_ui (const MP_RAT *op1, unsigned long int num2, unsigned long int den2)
+#else
+mpq_cmp_ui (op1, num2, den2)
+ const MP_RAT *op1;
+ unsigned long int num2;
+ unsigned long int den2;
+#endif
+{
+ mp_size_t num1_size = op1->_mp_num._mp_size;
+ mp_size_t den1_size = op1->_mp_den._mp_size;
+ mp_size_t tmp1_size, tmp2_size;
+ mp_ptr tmp1_ptr, tmp2_ptr;
+ mp_size_t num1_sign;
+ mp_limb_t cy_limb;
+ int cc;
+ TMP_DECL (marker);
+
+ if (num1_size == 0)
+ return -(num2 != 0);
+ if (num1_size < 0)
+ return num1_size;
+ if (num2 == 0)
+ return num1_size;
+
+ num1_sign = num1_size;
+ num1_size = ABS (num1_size);
+
+ /* NUM1 x DEN2 is either TMP1_SIZE limbs or TMP1_SIZE-1 limbs.
+ Same for NUM1 x DEN1 with respect to TMP2_SIZE. */
+ if (num1_size > den1_size + 1)
+ /* NUM1 x DEN2 is surely larger in magnitude than NUM2 x DEN1. */
+ return num1_sign;
+ if (den1_size > num1_sign + 1)
+ /* NUM1 x DEN2 is surely smaller in magnitude than NUM2 x DEN1. */
+ return -num1_sign;
+
+ TMP_MARK (marker);
+ tmp1_ptr = (mp_ptr) TMP_ALLOC ((num1_size + 1) * BYTES_PER_MP_LIMB);
+ tmp2_ptr = (mp_ptr) TMP_ALLOC ((den1_size + 1) * BYTES_PER_MP_LIMB);
+
+ cy_limb = mpn_mul_1 (tmp1_ptr, op1->_mp_num._mp_d, num1_size, den2);
+ tmp1_ptr[num1_size] = cy_limb;
+ tmp1_size = num1_size + (cy_limb != 0);
+
+ cy_limb = mpn_mul_1 (tmp2_ptr, op1->_mp_den._mp_d, den1_size, num2);
+ tmp2_ptr[den1_size] = cy_limb;
+ tmp2_size = den1_size + (cy_limb != 0);
+
+ cc = tmp1_size - tmp2_size != 0
+ ? tmp1_size - tmp2_size : mpn_cmp (tmp1_ptr, tmp2_ptr, tmp1_size);
+ TMP_FREE (marker);
+ return (num1_sign < 0) ? -cc : cc;
+}
diff --git a/mpq/configure.in b/mpq/configure.in
new file mode 100644
index 000000000..b5d501ccf
--- /dev/null
+++ b/mpq/configure.in
@@ -0,0 +1,12 @@
+# This file is a shell script fragment that supplies the information
+# necessary for a configure script to process the program in
+# this directory. For more information, look at ../configure.
+
+configdirs=tests
+srctrigger=cmp_ui.c
+srcname="GNU Multi-Precision library/mpq"
+
+# per-host:
+
+# per-target:
+
diff --git a/mpq/div.c b/mpq/div.c
new file mode 100644
index 000000000..cd1f38817
--- /dev/null
+++ b/mpq/div.c
@@ -0,0 +1,93 @@
+/* mpq_div -- divide two rational numbers.
+
+Copyright (C) 1991, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpq_div (mpq_ptr quot, mpq_srcptr op1, mpq_srcptr op2)
+#else
+mpq_div (quot, op1, op2)
+ mpq_ptr quot;
+ mpq_srcptr op1;
+ mpq_srcptr op2;
+#endif
+{
+ mpz_t gcd1, gcd2;
+ mpz_t tmp1, tmp2;
+ mpz_t numtmp;
+
+ mpz_init (gcd1);
+ mpz_init (gcd2);
+ mpz_init (tmp1);
+ mpz_init (tmp2);
+ mpz_init (numtmp);
+
+ /* QUOT might be identical to either operand, so don't store the
+ result there until we are finished with the input operands. We
+ dare to overwrite the numerator of QUOT when we are finished
+ with the numerators of OP1 and OP2. */
+
+ mpz_gcd (gcd1, &(op1->_mp_num), &(op2->_mp_num));
+ mpz_gcd (gcd2, &(op2->_mp_den), &(op1->_mp_den));
+
+ if (gcd1->_mp_size > 1 || gcd1->_mp_d[0] != 1)
+ mpz_divexact (tmp1, &(op1->_mp_num), gcd1);
+ else
+ mpz_set (tmp1, &(op1->_mp_num));
+
+ if (gcd2->_mp_size > 1 || gcd2->_mp_d[0] != 1)
+ mpz_divexact (tmp2, &(op2->_mp_den), gcd2);
+ else
+ mpz_set (tmp2, &(op2->_mp_den));
+
+ mpz_mul (numtmp, tmp1, tmp2);
+
+ if (gcd1->_mp_size > 1 || gcd1->_mp_d[0] != 1)
+ mpz_divexact (tmp1, &(op2->_mp_num), gcd1);
+ else
+ mpz_set (tmp1, &(op2->_mp_num));
+
+ if (gcd2->_mp_size > 1 || gcd2->_mp_d[0] != 1)
+ mpz_divexact (tmp2, &(op1->_mp_den), gcd2);
+ else
+ mpz_set (tmp2, &(op1->_mp_den));
+
+ mpz_mul (&(quot->_mp_den), tmp1, tmp2);
+
+ /* We needed to go via NUMTMP to take care of QUOT being the same
+ as either input operands. Now move NUMTMP to QUOT->_mp_num. */
+ mpz_set (&(quot->_mp_num), numtmp);
+
+ /* Keep the denominator positive. */
+ if (quot->_mp_den._mp_size < 0)
+ {
+ quot->_mp_den._mp_size = -quot->_mp_den._mp_size;
+ quot->_mp_num._mp_size = -quot->_mp_num._mp_size;
+ }
+
+ mpz_clear (numtmp);
+ mpz_clear (tmp2);
+ mpz_clear (tmp1);
+ mpz_clear (gcd2);
+ mpz_clear (gcd1);
+}
diff --git a/mpq/equal.c b/mpq/equal.c
new file mode 100644
index 000000000..1864fbd00
--- /dev/null
+++ b/mpq/equal.c
@@ -0,0 +1,43 @@
+/* mpq_equal(u,v) -- Compare U, V. Return non-zero if they are equal, zero
+ if they are non-equal.
+
+Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+int
+#if __STDC__
+mpq_equal (const mpq_t op1, const mpq_t op2)
+#else
+mpq_equal (op1, op2)
+ const mpq_t op1;
+ const mpq_t op2;
+#endif
+{
+ mp_size_t num1_size = op1->_mp_num._mp_size;
+ mp_size_t den1_size = op1->_mp_den._mp_size;
+ mp_size_t num2_size = op2->_mp_num._mp_size;
+ mp_size_t den2_size = op2->_mp_den._mp_size;
+
+ return (num1_size == num2_size && den1_size == den2_size
+ && mpn_cmp (op1->_mp_num._mp_d, op2->_mp_num._mp_d, num1_size) == 0
+ && mpn_cmp (op1->_mp_den._mp_d, op2->_mp_den._mp_d, den1_size) == 0);
+}
diff --git a/mpq/get_d.c b/mpq/get_d.c
new file mode 100644
index 000000000..18c01a63f
--- /dev/null
+++ b/mpq/get_d.c
@@ -0,0 +1,154 @@
+/* double mpq_get_d (mpq_t src) -- Return the double approximation to SRC.
+
+Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+#include <math.h>
+
+/* Algorithm:
+ 1. Develop >= n bits of src.num / src.den, where n is the number of bits
+ in a double. This (partial) division will use all bits from the
+ denominator.
+ 2. Use the remainder to determine how to round the result.
+ 3. Assign the integral result to a temporary double.
+ 4. Scale the temporary double, and return the result.
+
+ An alternative algorithm, that would be faster:
+ 0. Let n be somewhat larger than the number of significant bits in a double.
+ 1. Extract the most significant n bits of the denominator, and an equal
+ number of bits from the numerator.
+ 2. Interpret the extracted numbers as integers, call them a and b
+ respectively, and develop n bits of the fractions ((a + 1) / b) and
+ (a / (b + 1)) using mpn_divrem.
+ 3. If the computed values are identical UP TO THE POSITION WE CARE ABOUT,
+ we are done. If they are different, repeat the algorithm from step 1,
+ but first let n = n * 2.
+ 4. If we end up using all bits from the numerator and denominator, fall
+ back to the first algorithm above.
+ 5. Just to make life harder, The computation of a + 1 and b + 1 above
+ might give carry-out... Needs special handling. It might work to
+ subtract 1 in both cases instead.
+*/
+
+double
+#if __STDC__
+mpq_get_d (const MP_RAT *src)
+#else
+mpq_get_d (src)
+ const MP_RAT *src;
+#endif
+{
+ mp_ptr np, dp;
+ mp_ptr rp;
+ mp_size_t nsize = src->_mp_num._mp_size;
+ mp_size_t dsize = src->_mp_den._mp_size;
+ mp_size_t qsize, rsize;
+ mp_size_t sign_quotient = nsize ^ dsize;
+ unsigned normalization_steps;
+ mp_limb_t qlimb;
+#define N_QLIMBS (1 + (sizeof (double) + BYTES_PER_MP_LIMB-1) / BYTES_PER_MP_LIMB)
+ mp_limb_t qp[N_QLIMBS + 1];
+ TMP_DECL (marker);
+
+ if (nsize == 0)
+ return 0.0;
+
+ TMP_MARK (marker);
+ nsize = ABS (nsize);
+ dsize = ABS (dsize);
+ np = src->_mp_num._mp_d;
+ dp = src->_mp_den._mp_d;
+
+ rsize = dsize + N_QLIMBS;
+ rp = (mp_ptr) TMP_ALLOC ((rsize + 1) * BYTES_PER_MP_LIMB);
+
+ count_leading_zeros (normalization_steps, dp[dsize - 1]);
+
+ /* Normalize the denominator, i.e. make its most significant bit set by
+ shifting it NORMALIZATION_STEPS bits to the left. Also shift the
+ numerator the same number of steps (to keep the quotient the same!). */
+ if (normalization_steps != 0)
+ {
+ mp_ptr tp;
+ mp_limb_t nlimb;
+
+ /* Shift up the denominator setting the most significant bit of
+ the most significant limb. Use temporary storage not to clobber
+ the original contents of the denominator. */
+ tp = (mp_ptr) TMP_ALLOC (dsize * BYTES_PER_MP_LIMB);
+ mpn_lshift (tp, dp, dsize, normalization_steps);
+ dp = tp;
+
+ if (rsize > nsize)
+ {
+ MPN_ZERO (rp, rsize - nsize);
+ nlimb = mpn_lshift (rp + (rsize - nsize),
+ np, nsize, normalization_steps);
+ }
+ else
+ {
+ nlimb = mpn_lshift (rp, np + (nsize - rsize),
+ rsize, normalization_steps);
+ }
+ if (nlimb != 0)
+ {
+ rp[rsize] = nlimb;
+ rsize++;
+ }
+ }
+ else
+ {
+ if (rsize > nsize)
+ {
+ MPN_ZERO (rp, rsize - nsize);
+ MPN_COPY (rp + (rsize - nsize), np, nsize);
+ }
+ else
+ {
+ MPN_COPY (rp, np + (nsize - rsize), rsize);
+ }
+ }
+
+ qlimb = mpn_divmod (qp, rp, rsize, dp, dsize);
+ qsize = rsize - dsize;
+ if (qlimb)
+ {
+ qp[qsize] = qlimb;
+ qsize++;
+ }
+
+ {
+ const double limbbase = 2.0 * ((mp_limb_t) 1 << (BITS_PER_MP_LIMB - 1));
+ double res;
+ mp_size_t i;
+
+ res = qp[qsize - 1];
+ for (i = qsize - 2; i >= 0; i--)
+ res = res * limbbase + qp[i];
+
+ res = ldexp (res, BITS_PER_MP_LIMB * (nsize - dsize - N_QLIMBS));
+
+ TMP_FREE (marker);
+ return sign_quotient >= 0 ? res : -res;
+ }
+}
diff --git a/mpq/get_den.c b/mpq/get_den.c
new file mode 100644
index 000000000..fc5e3871e
--- /dev/null
+++ b/mpq/get_den.c
@@ -0,0 +1,41 @@
+/* mpq_get_den(den,rat_src) -- Set DEN to the denominator of RAT_SRC.
+
+Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpq_get_den (MP_INT *den, const MP_RAT *src)
+#else
+mpq_get_den (den, src)
+ MP_INT *den;
+ const MP_RAT *src;
+#endif
+{
+ mp_size_t size = src->_mp_den._mp_size;
+
+ if (den->_mp_alloc < size)
+ _mpz_realloc (den, size);
+
+ MPN_COPY (den->_mp_d, src->_mp_den._mp_d, size);
+ den->_mp_size = size;
+}
diff --git a/mpq/get_num.c b/mpq/get_num.c
new file mode 100644
index 000000000..61f812fa7
--- /dev/null
+++ b/mpq/get_num.c
@@ -0,0 +1,42 @@
+ /* mpq_get_num(num,rat_src) -- Set NUM to the numerator of RAT_SRC.
+
+Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpq_get_num (MP_INT *num, const MP_RAT *src)
+#else
+mpq_get_num (num, src)
+ MP_INT *num;
+ const MP_RAT *src;
+#endif
+{
+ mp_size_t size = src->_mp_num._mp_size;
+ mp_size_t abs_size = ABS (size);
+
+ if (num->_mp_alloc < abs_size)
+ _mpz_realloc (num, abs_size);
+
+ MPN_COPY (num->_mp_d, src->_mp_num._mp_d, abs_size);
+ num->_mp_size = size;
+}
diff --git a/mpq/init.c b/mpq/init.c
new file mode 100644
index 000000000..ae6d8b396
--- /dev/null
+++ b/mpq/init.c
@@ -0,0 +1,40 @@
+/* mpq_init -- Make a new rational number with value 0/1.
+
+Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpq_init (MP_RAT *x)
+#else
+mpq_init (x)
+ MP_RAT *x;
+#endif
+{
+ x->_mp_num._mp_alloc = 1;
+ x->_mp_num._mp_d = (mp_ptr) (*_mp_allocate_func) (BYTES_PER_MP_LIMB);
+ x->_mp_num._mp_size = 0;
+ x->_mp_den._mp_alloc = 1;
+ x->_mp_den._mp_d = (mp_ptr) (*_mp_allocate_func) (BYTES_PER_MP_LIMB);
+ x->_mp_den._mp_d[0] = 1;
+ x->_mp_den._mp_size = 1;
+}
diff --git a/mpq/inv.c b/mpq/inv.c
new file mode 100644
index 000000000..745c78d05
--- /dev/null
+++ b/mpq/inv.c
@@ -0,0 +1,75 @@
+/* mpq_inv(dest,src) -- invert a rational number, i.e. set DEST to SRC
+ with the numerator and denominator swapped.
+
+Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpq_inv (MP_RAT *dest, const MP_RAT *src)
+#else
+mpq_inv (dest, src)
+ MP_RAT *dest;
+ const MP_RAT *src;
+#endif
+{
+ mp_size_t num_size = src->_mp_num._mp_size;
+ mp_size_t den_size = src->_mp_den._mp_size;
+
+ if (num_size == 0)
+ num_size = 1 / num_size; /* Divide by zero! */
+
+ if (num_size < 0)
+ {
+ num_size = -num_size;
+ den_size = -den_size;
+ }
+ dest->_mp_den._mp_size = num_size;
+ dest->_mp_num._mp_size = den_size;
+
+ /* If dest == src we may just swap the numerator and denominator, but
+ we have to ensure the new denominator is positive. */
+
+ if (dest == src)
+ {
+ mp_size_t alloc = dest->_mp_num._mp_alloc;
+ mp_ptr limb_ptr = dest->_mp_num._mp_d;
+
+ dest->_mp_num._mp_alloc = dest->_mp_den._mp_alloc;
+ dest->_mp_num._mp_d = dest->_mp_den._mp_d;
+
+ dest->_mp_den._mp_alloc = alloc;
+ dest->_mp_den._mp_d = limb_ptr;
+ }
+ else
+ {
+ den_size = ABS (den_size);
+ if (dest->_mp_num._mp_alloc < den_size)
+ _mpz_realloc (&(dest->_mp_num), den_size);
+
+ if (dest->_mp_den._mp_alloc < num_size)
+ _mpz_realloc (&(dest->_mp_den), num_size);
+
+ MPN_COPY (dest->_mp_num._mp_d, src->_mp_den._mp_d, den_size);
+ MPN_COPY (dest->_mp_den._mp_d, src->_mp_num._mp_d, num_size);
+ }
+}
diff --git a/mpq/mul.c b/mpq/mul.c
new file mode 100644
index 000000000..35f960c85
--- /dev/null
+++ b/mpq/mul.c
@@ -0,0 +1,79 @@
+/* mpq_mul -- mutiply two rational numbers.
+
+Copyright (C) 1991, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpq_mul (mpq_ptr prod, mpq_srcptr op1, mpq_srcptr op2)
+#else
+mpq_mul (prod, op1, op2)
+ mpq_ptr prod;
+ mpq_srcptr op1;
+ mpq_srcptr op2;
+#endif
+{
+ mpz_t gcd1, gcd2;
+ mpz_t tmp1, tmp2;
+
+ mpz_init (gcd1);
+ mpz_init (gcd2);
+ mpz_init (tmp1);
+ mpz_init (tmp2);
+
+ /* PROD might be identical to either operand, so don't store the
+ result there until we are finished with the input operands. We
+ dare to overwrite the numerator of PROD when we are finished
+ with the numerators of OP1 and OP2. */
+
+ mpz_gcd (gcd1, &(op1->_mp_num), &(op2->_mp_den));
+ mpz_gcd (gcd2, &(op2->_mp_num), &(op1->_mp_den));
+
+ if (gcd1->_mp_size > 1 || gcd1->_mp_d[0] != 1)
+ mpz_divexact (tmp1, &(op1->_mp_num), gcd1);
+ else
+ mpz_set (tmp1, &(op1->_mp_num));
+
+ if (gcd2->_mp_size > 1 || gcd2->_mp_d[0] != 1)
+ mpz_divexact (tmp2, &(op2->_mp_num), gcd2);
+ else
+ mpz_set (tmp2, &(op2->_mp_num));
+
+ mpz_mul (&(prod->_mp_num), tmp1, tmp2);
+
+ if (gcd1->_mp_size > 1 || gcd1->_mp_d[0] != 1)
+ mpz_divexact (tmp1, &(op2->_mp_den), gcd1);
+ else
+ mpz_set (tmp1, &(op2->_mp_den));
+
+ if (gcd2->_mp_size > 1 || gcd2->_mp_d[0] != 1)
+ mpz_divexact (tmp2, &(op1->_mp_den), gcd2);
+ else
+ mpz_set (tmp2, &(op1->_mp_den));
+
+ mpz_mul (&(prod->_mp_den), tmp1, tmp2);
+
+ mpz_clear (tmp2);
+ mpz_clear (tmp1);
+ mpz_clear (gcd2);
+ mpz_clear (gcd1);
+}
diff --git a/mpq/neg.c b/mpq/neg.c
new file mode 100644
index 000000000..ac54d271f
--- /dev/null
+++ b/mpq/neg.c
@@ -0,0 +1,36 @@
+/* mpq_neg(dst, src) -- Assign the negated value of SRC to DST.
+
+Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpq_neg (MP_RAT *dst, const MP_RAT *src)
+#else
+mpq_neg (dst, src)
+ MP_RAT *dst;
+ const MP_RAT *src;
+#endif
+{
+ mpz_neg (&dst->_mp_num, &src->_mp_num);
+ mpz_set (&dst->_mp_den, &src->_mp_den);
+}
diff --git a/mpq/set.c b/mpq/set.c
new file mode 100644
index 000000000..ef85639c5
--- /dev/null
+++ b/mpq/set.c
@@ -0,0 +1,49 @@
+/* mpq_set(dest,src) -- Set DEST to SRC.
+
+Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpq_set (MP_RAT *dest, const MP_RAT *src)
+#else
+mpq_set (dest, src)
+ MP_RAT *dest;
+ const MP_RAT *src;
+#endif
+{
+ mp_size_t num_size, den_size;
+ mp_size_t abs_num_size;
+
+ num_size = src->_mp_num._mp_size;
+ abs_num_size = ABS (num_size);
+ if (dest->_mp_num._mp_alloc < abs_num_size)
+ _mpz_realloc (&(dest->_mp_num), abs_num_size);
+ MPN_COPY (dest->_mp_num._mp_d, src->_mp_num._mp_d, abs_num_size);
+ dest->_mp_num._mp_size = num_size;
+
+ den_size = src->_mp_den._mp_size;
+ if (dest->_mp_den._mp_alloc < den_size)
+ _mpz_realloc (&(dest->_mp_den), den_size);
+ MPN_COPY (dest->_mp_den._mp_d, src->_mp_den._mp_d, den_size);
+ dest->_mp_den._mp_size = den_size;
+}
diff --git a/mpq/set_den.c b/mpq/set_den.c
new file mode 100644
index 000000000..4586c89f6
--- /dev/null
+++ b/mpq/set_den.c
@@ -0,0 +1,42 @@
+/* mpq_set_den(dest,den) -- Set the denominator of DEST from DEN.
+
+Copyright (C) 1991, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpq_set_den (MP_RAT *dest, const MP_INT *den)
+#else
+mpq_set_den (dest, den)
+ MP_RAT *dest;
+ const MP_INT *den;
+#endif
+{
+ mp_size_t size = den->_mp_size;
+ mp_size_t abs_size = ABS (size);
+
+ if (dest->_mp_den._mp_alloc < abs_size)
+ _mpz_realloc (&(dest->_mp_den), abs_size);
+
+ MPN_COPY (dest->_mp_den._mp_d, den->_mp_d, abs_size);
+ dest->_mp_den._mp_size = abs_size;
+}
diff --git a/mpq/set_num.c b/mpq/set_num.c
new file mode 100644
index 000000000..ce918ce2a
--- /dev/null
+++ b/mpq/set_num.c
@@ -0,0 +1,42 @@
+/* mpq_set_num(dest,num) -- Set the numerator of DEST from NUM.
+
+Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpq_set_num (MP_RAT *dest, const MP_INT *num)
+#else
+mpq_set_num (dest, num)
+ MP_RAT *dest;
+ const MP_INT *num;
+#endif
+{
+ mp_size_t size = num->_mp_size;
+ mp_size_t abs_size = ABS (size);
+
+ if (dest->_mp_num._mp_alloc < abs_size)
+ _mpz_realloc (&(dest->_mp_num), abs_size);
+
+ MPN_COPY (dest->_mp_num._mp_d, num->_mp_d, abs_size);
+ dest->_mp_num._mp_size = size;
+}
diff --git a/mpq/set_si.c b/mpq/set_si.c
new file mode 100644
index 000000000..cf1f9f0a1
--- /dev/null
+++ b/mpq/set_si.c
@@ -0,0 +1,54 @@
+/* mpq_set_si(dest,ulong_num,ulong_den) -- Set DEST to the retional number
+ ULONG_NUM/ULONG_DEN.
+
+Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpq_set_si (MP_RAT *dest, signed long int num, unsigned long int den)
+#else
+mpq_set_si (dest, num, den)
+ MP_RAT *dest;
+ signed long int num;
+ unsigned long int den;
+#endif
+{
+ unsigned long int abs_num;
+
+ abs_num = ABS (num);
+
+ if (num == 0)
+ {
+ /* Canonicalize 0/d to 0/1. */
+ den = 1;
+ dest->_mp_num._mp_size = 0;
+ }
+ else
+ {
+ dest->_mp_num._mp_d[0] = abs_num;
+ dest->_mp_num._mp_size = num > 0 ? 1 : -1;
+ }
+
+ dest->_mp_den._mp_d[0] = den;
+ dest->_mp_den._mp_size = 1;
+}
diff --git a/mpq/set_ui.c b/mpq/set_ui.c
new file mode 100644
index 000000000..aaa9fc282
--- /dev/null
+++ b/mpq/set_ui.c
@@ -0,0 +1,50 @@
+/* mpq_set_ui(dest,ulong_num,ulong_den) -- Set DEST to the retional number
+ ULONG_NUM/ULONG_DEN.
+
+Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpq_set_ui (MP_RAT *dest, unsigned long int num, unsigned long int den)
+#else
+mpq_set_ui (dest, num, den)
+ MP_RAT *dest;
+ unsigned long int num;
+ unsigned long int den;
+#endif
+{
+ if (num == 0)
+ {
+ /* Canonicalize 0/n to 0/1. */
+ den = 1;
+ dest->_mp_num._mp_size = 0;
+ }
+ else
+ {
+ dest->_mp_num._mp_d[0] = num;
+ dest->_mp_num._mp_size = 1;
+ }
+
+ dest->_mp_den._mp_d[0] = den;
+ dest->_mp_den._mp_size = 1;
+}
diff --git a/mpq/sub.c b/mpq/sub.c
new file mode 100644
index 000000000..9274ff8cb
--- /dev/null
+++ b/mpq/sub.c
@@ -0,0 +1,85 @@
+/* mpq_sub -- subtract two rational numbers.
+
+Copyright (C) 1991, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpq_sub (mpq_ptr rop, mpq_srcptr op1, mpq_srcptr op2)
+#else
+mpq_sub (rop, op1, op2)
+ mpq_ptr rop;
+ mpq_srcptr op1;
+ mpq_srcptr op2;
+#endif
+{
+ mpz_t gcd;
+ mpz_t tmp1, tmp2;
+ mp_size_t op1_num_size = ABS (op1->_mp_num._mp_size);
+ mp_size_t op1_den_size = ABS (op1->_mp_den._mp_size);
+ mp_size_t op2_num_size = ABS (op2->_mp_num._mp_size);
+ mp_size_t op2_den_size = ABS (op2->_mp_den._mp_size);
+ TMP_DECL (marker);
+
+ TMP_MARK (marker);
+ MPZ_TMP_INIT (gcd, MIN (op1_den_size, op2_den_size));
+ MPZ_TMP_INIT (tmp1, op1_num_size + op2_den_size);
+ MPZ_TMP_INIT (tmp2, op2_num_size + op1_den_size);
+
+ /* ROP might be identical to either operand, so don't store the
+ result there until we are finished with the input operands. We
+ dare to overwrite the numerator of ROP when we are finished
+ with the numerators of OP1 and OP2. */
+
+ mpz_gcd (gcd, &(op1->_mp_den), &(op2->_mp_den));
+ if (gcd->_mp_size > 1 || gcd->_mp_d[0] != 1)
+ {
+ mpz_t t;
+
+ mpz_divexact (tmp1, &(op2->_mp_den), gcd);
+ mpz_mul (tmp1, &(op1->_mp_num), tmp1);
+
+ mpz_divexact (tmp2, &(op1->_mp_den), gcd);
+ mpz_mul (tmp2, &(op2->_mp_num), tmp2);
+
+ MPZ_TMP_INIT (t, MAX (ABS (tmp1->_mp_size), ABS (tmp2->_mp_size)) + 1);
+
+ mpz_sub (t, tmp1, tmp2);
+ mpz_divexact (tmp1, &(op1->_mp_den), gcd);
+ mpz_gcd (gcd, t, gcd);
+
+ mpz_divexact (&(rop->_mp_num), t, gcd);
+
+ mpz_divexact (tmp2, &(op2->_mp_den), gcd);
+ mpz_mul (&(rop->_mp_den), tmp1, tmp2);
+ }
+ else
+ {
+ /* The common divisor is 1. This is the case (for random input) with
+ probability 6/(pi**2). */
+ mpz_mul (tmp1, &(op1->_mp_num), &(op2->_mp_den));
+ mpz_mul (tmp2, &(op2->_mp_num), &(op1->_mp_den));
+ mpz_sub (&(rop->_mp_num), tmp1, tmp2);
+ mpz_mul (&(rop->_mp_den), &(op1->_mp_den), &(op2->_mp_den));
+ }
+ TMP_FREE (marker);
+}
diff --git a/mpq/tests/Makefile.in b/mpq/tests/Makefile.in
new file mode 100644
index 000000000..8c1ffa6cb
--- /dev/null
+++ b/mpq/tests/Makefile.in
@@ -0,0 +1,48 @@
+# Makefile for mpq/tests for GNU MP
+
+srcdir = .
+
+CC = gcc
+
+TEST_LIBS = ../../libgmp.a
+INCLUDES = -I../../mpn -I$(srcdir)/../..
+CFLAGS = -g -O
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(XCFLAGS) $<
+
+TEST_SRCS = t-cmp.c t-cmp_ui.c t-get_d.c
+TEST_OBJS = t-cmp.o t-cmp_ui.o t-get_d.o
+TESTS = t-cmp t-cmp_ui t-get_d
+
+check: st-cmp st-cmp_ui st-get_d
+ @echo "The tests passed."
+
+st-cmp: t-cmp
+ ./t-cmp
+ touch $@
+st-cmp_ui: t-cmp_ui
+ ./t-cmp_ui
+ touch $@
+st-get_d: t-get_d
+ ./t-get_d
+ touch $@
+
+t-cmp: t-cmp.o $(TEST_LIBS)
+ $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+t-cmp_ui: t-cmp_ui.o $(TEST_LIBS)
+ $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+t-get_d: t-get_d.o $(TEST_LIBS)
+ $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+
+t-cmp.o: $(srcdir)/t-cmp.c
+t-cmp_ui.o: $(srcdir)/t-cmp_ui.c
+t-get_d.o: $(srcdir)/t-get_d.c
+
+clean mostlyclean:
+ rm -f *.o st-* $(TESTS)
+distclean maintainer-clean: clean
+ rm -f Makefile config.status
+
+Makefile: $(srcdir)/Makefile.in
+ $(SHELL) ./config.status
diff --git a/mpq/tests/configure.in b/mpq/tests/configure.in
new file mode 100644
index 000000000..5ee2138ac
--- /dev/null
+++ b/mpq/tests/configure.in
@@ -0,0 +1,11 @@
+# This file is a shell script that supplies the information necessary
+# to tailor a template configure script into the configure script
+# appropriate for this directory. For more information, check any
+# existing configure script.
+
+srctrigger=t-cmp.c
+srcname="gmp/mpq/tests"
+
+# per-host:
+
+# per-target:
diff --git a/mpq/tests/t-cmp.c b/mpq/tests/t-cmp.c
new file mode 100644
index 000000000..77e46f208
--- /dev/null
+++ b/mpq/tests/t-cmp.c
@@ -0,0 +1,109 @@
+/* Test mpq_cmp.
+
+Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+#define NUM(x) (&((x)->_mp_num))
+#define DEN(x) (&((x)->_mp_den))
+
+#define SGN(x) ((x) < 0 ? -1 : (x) > 0 ? 1 : 0)
+
+ref_mpq_cmp (a, b)
+ mpq_t a, b;
+{
+ mpz_t ai, bi;
+ int cc;
+
+ mpz_init (ai);
+ mpz_init (bi);
+
+ mpz_mul (ai, NUM (a), DEN (b));
+ mpz_mul (bi, NUM (b), DEN (a));
+ cc = mpz_cmp (ai, bi);
+ mpz_clear (ai);
+ mpz_clear (bi);
+ return cc;
+}
+
+#ifndef SIZE
+#define SIZE 8 /* increasing this lowers the probabilty of finding an error */
+#endif
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ mpq_t a, b;
+ mp_size_t size;
+ int reps = 100000;
+ int i;
+ int cc, ccref;
+
+ if (argc == 2)
+ reps = atoi (argv[1]);
+
+ mpq_init (a);
+ mpq_init (b);
+
+ for (i = 0; i < reps; i++)
+ {
+ size = urandom () % SIZE - SIZE/2;
+ mpz_random2 (NUM (a), size);
+ do
+ {
+ size = urandom () % SIZE - SIZE/2;
+ mpz_random2 (DEN (a), size);
+ }
+ while (mpz_cmp_ui (DEN (a), 0) == 0);
+
+ size = urandom () % SIZE - SIZE/2;
+ mpz_random2 (NUM (b), size);
+ do
+ {
+ size = urandom () % SIZE - SIZE/2;
+ mpz_random2 (DEN (b), size);
+ }
+ while (mpz_cmp_ui (DEN (b), 0) == 0);
+
+ mpq_canonicalize (a);
+ mpq_canonicalize (b);
+
+ ccref = ref_mpq_cmp (a, b);
+ cc = mpq_cmp (a, b);
+
+ if (SGN (ccref) != SGN (cc))
+ abort ();
+ }
+
+ exit (0);
+}
+
+dump (x)
+ mpq_t x;
+{
+ mpz_out_str (stdout, 10, NUM (x));
+ printf ("/");
+ mpz_out_str (stdout, 10, DEN (x));
+ printf ("\n");
+}
diff --git a/mpq/tests/t-cmp_ui.c b/mpq/tests/t-cmp_ui.c
new file mode 100644
index 000000000..f7b92ada3
--- /dev/null
+++ b/mpq/tests/t-cmp_ui.c
@@ -0,0 +1,102 @@
+/* Test mpq_cmp_ui.
+
+Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+#define NUM(x) (&((x)->_mp_num))
+#define DEN(x) (&((x)->_mp_den))
+
+#define SGN(x) ((x) < 0 ? -1 : (x) > 0 ? 1 : 0)
+
+ref_mpq_cmp_ui (a, bn, bd)
+ mpq_t a;
+ unsigned long int bn, bd;
+{
+ mpz_t ai, bi;
+ int cc;
+
+ mpz_init (ai);
+ mpz_init (bi);
+
+ mpz_mul_ui (ai, NUM (a), bd);
+ mpz_mul_ui (bi, DEN (a), bn);
+ cc = mpz_cmp (ai, bi);
+ mpz_clear (ai);
+ mpz_clear (bi);
+ return cc;
+}
+
+#ifndef SIZE
+#define SIZE 8 /* increasing this lowers the probabilty of finding an error */
+#endif
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ mpq_t a, b;
+ mp_size_t size;
+ int reps = 100000;
+ int i;
+ int cc, ccref;
+ unsigned long int bn, bd;
+
+ if (argc == 2)
+ reps = atoi (argv[1]);
+
+ mpq_init (a);
+ mpq_init (b);
+
+ for (i = 0; i < reps; i++)
+ {
+ size = urandom () % SIZE - SIZE/2;
+ mpz_random2 (NUM (a), size);
+ do
+ {
+ size = urandom () % SIZE - SIZE/2;
+ mpz_random2 (DEN (a), size);
+ }
+ while (mpz_cmp_ui (DEN (a), 0) == 0);
+
+ mpz_random2 (NUM (b), 1);
+ do
+ {
+ mpz_random2 (DEN (b), 1);
+ }
+ while (mpz_cmp_ui (DEN (b), 0) == 0);
+
+ mpq_canonicalize (a);
+ mpq_canonicalize (b);
+
+ bn = mpz_get_ui (NUM (b));
+ bd = mpz_get_ui (DEN (b));
+
+ ccref = ref_mpq_cmp_ui (a, bn, bd);
+ cc = mpq_cmp_ui (a, bn, bd);
+
+ if (SGN (ccref) != SGN (cc))
+ abort ();
+ }
+
+ exit (0);
+}
diff --git a/mpq/tests/t-get_d.c b/mpq/tests/t-get_d.c
new file mode 100644
index 000000000..db4f92633
--- /dev/null
+++ b/mpq/tests/t-get_d.c
@@ -0,0 +1,88 @@
+/* Test mpq_get_d
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+#ifndef SIZE
+#define SIZE 8
+#endif
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ mpq_t a;
+ mp_size_t size;
+ int reps = 10000;
+ int i, j;
+ double last_d, new_d;
+ mpz_t eps;
+
+ if (argc == 2)
+ reps = atoi (argv[1]);
+
+ /* The idea here is to test the monotonousness of mpq_get_d by adding
+ numbers to the numerator and denominator. */
+
+ mpq_init (a);
+ mpz_init (eps);
+
+ for (i = 0; i < reps; i++)
+ {
+ size = urandom () % SIZE - SIZE/2;
+ mpz_random2 (mpq_numref (a), size);
+ do
+ {
+ size = urandom () % SIZE - SIZE/2;
+ mpz_random2 (mpq_denref (a), size);
+ }
+ while (mpz_cmp_ui (mpq_denref (a), 0) == 0);
+
+ mpq_canonicalize (a);
+
+ last_d = mpq_get_d (a);
+ for (j = 0; j < 10; j++)
+ {
+ size = urandom () % SIZE;
+ mpz_random2 (eps, size);
+ mpz_add (mpq_numref (a), mpq_numref (a), eps);
+ mpq_canonicalize (a);
+ new_d = mpq_get_d (a);
+ if (last_d > new_d)
+ abort ();
+ last_d = new_d;
+ }
+ }
+
+ exit (0);
+}
+
+dump (x)
+ mpq_t x;
+{
+ mpz_out_str (stdout, 10, mpq_numref (x));
+ printf ("/");
+ mpz_out_str (stdout, 10, mpq_denref (x));
+ printf ("\n");
+}
diff --git a/mpz/Makefile.in b/mpz/Makefile.in
new file mode 100644
index 000000000..f285cb35f
--- /dev/null
+++ b/mpz/Makefile.in
@@ -0,0 +1,177 @@
+# Makefile for GNU MP/mpz functions
+# Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+# This file is part of the GNU MP Library.
+
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+
+# The GNU MP Library 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 Library General Public
+# License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+
+srcdir = .
+
+CC = gcc
+
+# If you cross compile on a machine with the same sizes of the integral
+# types ("int", "long int", "short int", and "char") define this as the
+# local compiler. Otherwise, you need to look for the uses of LOCAL_CC below,
+# and handle those cases manually.
+LOCAL_CC = $(CC)
+CFLAGS = -g -O
+AR = ar
+AR_FLAGS = rc
+SHELL = /bin/sh
+
+#### host and target specific makefile fragments come in here.
+###
+
+MPZ_SRCS = init.c set.c set_ui.c set_si.c set_str.c set_d.c \
+ iset.c iset_ui.c iset_si.c iset_str.c iset_d.c clear.c \
+ get_ui.c get_si.c get_str.c size.c sizeinbase.c \
+ add.c add_ui.c sub.c sub_ui.c mul.c mul_ui.c \
+ gcd.c gcd_ui.c gcdext.c sqrt.c sqrtrem.c powm.c powm_ui.c \
+ cmp.c cmp_ui.c cmp_si.c mul_2exp.c fdiv_q_2exp.c fdiv_r_2exp.c \
+ tdiv_q_2exp.c tdiv_r_2exp.c abs.c neg.c com.c and.c ior.c \
+ inp_raw.c inp_str.c out_raw.c out_str.c \
+ perfsqr.c random.c random2.c pow_ui.c ui_pow_ui.c setbit.c \
+ clrbit.c fac_ui.c pprime_p.c realloc.c getlimbn.c popcount.c hamdist.c \
+ cdiv_qr.c cdiv_q.c cdiv_r.c cdiv_qr_ui.c cdiv_q_ui.c cdiv_r_ui.c cdiv_ui.c \
+ fdiv_qr.c fdiv_q.c fdiv_r.c fdiv_qr_ui.c fdiv_q_ui.c fdiv_r_ui.c fdiv_ui.c \
+ tdiv_qr.c tdiv_q.c tdiv_r.c tdiv_qr_ui.c tdiv_q_ui.c tdiv_r_ui.c \
+ mod.c divexact.c array_init.c scan0.c scan1.c \
+ jacobi.c legendre.c invert.c
+MPZ_OBJS = init.o set.o set_ui.o set_si.o set_str.o set_d.o \
+ iset.o iset_ui.o iset_si.o iset_str.o iset_d.o clear.o \
+ get_ui.o get_si.o get_str.o size.o sizeinbase.o \
+ add.o add_ui.o sub.o sub_ui.o mul.o mul_ui.o \
+ gcd.o gcd_ui.o gcdext.o sqrt.o sqrtrem.o powm.o powm_ui.o \
+ cmp.o cmp_ui.o cmp_si.o mul_2exp.o fdiv_q_2exp.o fdiv_r_2exp.o \
+ tdiv_q_2exp.o tdiv_r_2exp.o abs.o neg.o com.o and.o ior.o \
+ inp_raw.o inp_str.o out_raw.o out_str.o \
+ perfsqr.o random.o random2.o pow_ui.o ui_pow_ui.o setbit.o \
+ clrbit.o fac_ui.o pprime_p.o realloc.o getlimbn.o popcount.o hamdist.o \
+ cdiv_qr.o cdiv_q.o cdiv_r.o cdiv_qr_ui.o cdiv_q_ui.o cdiv_r_ui.o cdiv_ui.o \
+ fdiv_qr.o fdiv_q.o fdiv_r.o fdiv_qr_ui.o fdiv_q_ui.o fdiv_r_ui.o fdiv_ui.o \
+ tdiv_qr.o tdiv_q.o tdiv_r.o tdiv_qr_ui.o tdiv_q_ui.o tdiv_r_ui.o \
+ mod.o divexact.o array_init.o scan0.o scan1.o \
+ jacobi.o legendre.o invert.o
+
+INCLUDES = -I. -I.. -I../mpn -I$(srcdir)/..
+
+libmpz.a: Makefile.in $(MPZ_OBJS)
+ rm -f $@
+ $(AR) $(AR_FLAGS) $@ $(MPZ_OBJS)
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(XCFLAGS) $<
+
+clean mostlyclean:
+ rm -f *.o libmpz.a
+ -cd tests; $(MAKE) $@
+distclean maintainer-clean: clean
+ rm -f Makefile config.status
+ -cd tests; $(MAKE) $@
+
+Makefile: $(srcdir)/Makefile.in
+ $(SHELL) ./config.status
+
+H = $(srcdir)/../gmp.h $(srcdir)/../gmp-impl.h ../mpn/gmp-mparam.h
+
+abs.o: $(srcdir)/abs.c $(H)
+add.o: $(srcdir)/add.c $(H)
+add_ui.o: $(srcdir)/add_ui.c $(H)
+and.o: $(srcdir)/and.c $(H)
+array_init.o: $(srcdir)/array_init.c $(H)
+cdiv_q.o: $(srcdir)/cdiv_q.c $(H)
+cdiv_q_ui.o: $(srcdir)/cdiv_q_ui.c $(H)
+cdiv_qr.o: $(srcdir)/cdiv_qr.c $(H)
+cdiv_qr_ui.o: $(srcdir)/cdiv_qr_ui.c $(H)
+cdiv_r.o: $(srcdir)/cdiv_r.c $(H)
+cdiv_r_ui.o: $(srcdir)/cdiv_r_ui.c $(H)
+cdiv_ui.o: $(srcdir)/cdiv_ui.c $(H)
+clear.o: $(srcdir)/clear.c $(H)
+clrbit.o: $(srcdir)/clrbit.c $(H)
+cmp.o: $(srcdir)/cmp.c $(H)
+cmp_si.o: $(srcdir)/cmp_si.c $(H)
+cmp_ui.o: $(srcdir)/cmp_ui.c $(H)
+com.o: $(srcdir)/com.c $(H)
+fdiv_q_2exp.o: $(srcdir)/fdiv_q_2exp.c $(H)
+fdiv_r_2exp.o: $(srcdir)/fdiv_r_2exp.c $(H)
+divexact.o: $(srcdir)/divexact.c $(H) $(srcdir)/../longlong.h
+fac_ui.o: $(srcdir)/fac_ui.c $(H) $(srcdir)/../longlong.h
+fdiv_q.o: $(srcdir)/fdiv_q.c $(H)
+fdiv_q_ui.o: $(srcdir)/fdiv_q_ui.c $(H)
+fdiv_qr.o: $(srcdir)/fdiv_qr.c $(H)
+fdiv_qr_ui.o: $(srcdir)/fdiv_qr_ui.c $(H)
+fdiv_r.o: $(srcdir)/fdiv_r.c $(H)
+fdiv_r_ui.o: $(srcdir)/fdiv_r_ui.c $(H)
+fdiv_ui.o: $(srcdir)/fdiv_ui.c $(H)
+gcd.o: $(srcdir)/gcd.c $(H) $(srcdir)/../longlong.h
+gcd_ui.o: $(srcdir)/gcd_ui.c $(H)
+gcdext.o: $(srcdir)/gcdext.c $(H)
+get_si.o: $(srcdir)/get_si.c $(H)
+get_str.o: $(srcdir)/get_str.c $(H)
+get_ui.o: $(srcdir)/get_ui.c $(H)
+getlimbn.o: $(srcdir)/getlimbn.c $(H)
+hamdist.o: $(srcdir)/hamdist.c $(H)
+init.o: $(srcdir)/init.c $(H)
+inp_raw.o: $(srcdir)/inp_raw.c $(H)
+inp_str.o: $(srcdir)/inp_str.c $(H)
+invert.o: $(srcdir)/invert.c $(H)
+ior.o: $(srcdir)/ior.c $(H)
+iset.o: $(srcdir)/iset.c $(H)
+iset_d.o: $(srcdir)/iset_d.c $(H)
+iset_si.o: $(srcdir)/iset_si.c $(H)
+iset_str.o: $(srcdir)/iset_str.c $(H)
+iset_ui.o: $(srcdir)/iset_ui.c $(H)
+jacobi.o: $(srcdir)/jacobi.c $(H)
+legendre.o: $(srcdir)/legendre.c $(H)
+mod.o: $(srcdir)/mod.c $(H)
+tdiv_q_2exp.o: $(srcdir)/tdiv_q_2exp.c $(H)
+tdiv_r_2exp.o: $(srcdir)/tdiv_r_2exp.c $(H)
+mul.o: $(srcdir)/mul.c $(H)
+mul_2exp.o: $(srcdir)/mul_2exp.c $(H)
+mul_ui.o: $(srcdir)/mul_ui.c $(H)
+neg.o: $(srcdir)/neg.c $(H)
+out_raw.o: $(srcdir)/out_raw.c $(H)
+out_str.o: $(srcdir)/out_str.c $(H)
+perfsqr.o: $(srcdir)/perfsqr.c $(H)
+popcount.o: $(srcdir)/popcount.c $(H)
+pow_ui.o: $(srcdir)/pow_ui.c $(H) $(srcdir)/../longlong.h
+powm.o: $(srcdir)/powm.c $(H) $(srcdir)/../longlong.h
+powm_ui.o: $(srcdir)/powm_ui.c $(H) $(srcdir)/../longlong.h
+pprime_p.o: $(srcdir)/pprime_p.c $(H)
+random.o: $(srcdir)/random.c $(H) $(srcdir)/../urandom.h
+random2.o: $(srcdir)/random2.c $(H)
+realloc.o: $(srcdir)/realloc.c $(H)
+scan0.o: $(srcdir)/scan0.c $(H)
+scan1.o: $(srcdir)/scan1.c $(H)
+set.o: $(srcdir)/set.c $(H)
+set_d.o: $(srcdir)/set_d.c $(H)
+set_si.o: $(srcdir)/set_si.c $(H)
+set_str.o: $(srcdir)/set_str.c $(H) $(srcdir)/../longlong.h
+set_ui.o: $(srcdir)/set_ui.c $(H)
+setbit.o: $(srcdir)/setbit.c $(H)
+size.o: $(srcdir)/size.c $(H)
+sizeinbase.o: $(srcdir)/sizeinbase.c $(H) $(srcdir)/../longlong.h
+sqrt.o: $(srcdir)/sqrt.c $(H)
+sqrtrem.o: $(srcdir)/sqrtrem.c $(H)
+sub.o: $(srcdir)/sub.c $(H)
+sub_ui.o: $(srcdir)/sub_ui.c $(H)
+tdiv_q.o: $(srcdir)/tdiv_q.c $(H) $(srcdir)/../longlong.h
+tdiv_q_ui.o: $(srcdir)/tdiv_q_ui.c $(H)
+tdiv_qr.o: $(srcdir)/tdiv_qr.c $(H) $(srcdir)/../longlong.h $(srcdir)/dmincl.c $(H)
+tdiv_qr_ui.o: $(srcdir)/tdiv_qr_ui.c $(H)
+tdiv_r.o: $(srcdir)/tdiv_r.c $(H) $(srcdir)/../longlong.h $(srcdir)/dmincl.c $(H)
+tdiv_r_ui.o: $(srcdir)/tdiv_r_ui.c $(H)
+ui_pow_ui.o: $(srcdir)/ui_pow_ui.c $(H) $(srcdir)/../longlong.h
diff --git a/mpz/abs.c b/mpz/abs.c
new file mode 100644
index 000000000..080cac60a
--- /dev/null
+++ b/mpz/abs.c
@@ -0,0 +1,51 @@
+/* mpz_abs(dst, src) -- Assign the absolute value of SRC to DST.
+
+Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_abs (mpz_ptr w, mpz_srcptr u)
+#else
+mpz_abs (w, u)
+ mpz_ptr w;
+ mpz_srcptr u;
+#endif
+{
+ mp_ptr wp, up;
+ mp_size_t size;
+
+ size = ABS (u->_mp_size);
+
+ if (u != w)
+ {
+ if (w->_mp_alloc < size)
+ _mpz_realloc (w, size);
+
+ wp = w->_mp_d;
+ up = u->_mp_d;
+
+ MPN_COPY (wp, up, size);
+ }
+
+ w->_mp_size = size;
+}
diff --git a/mpz/add.c b/mpz/add.c
new file mode 100644
index 000000000..10dd9704c
--- /dev/null
+++ b/mpz/add.c
@@ -0,0 +1,120 @@
+/* mpz_add -- Add two integers.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+#ifndef BERKELEY_MP
+void
+#if __STDC__
+mpz_add (mpz_ptr w, mpz_srcptr u, mpz_srcptr v)
+#else
+mpz_add (w, u, v)
+ mpz_ptr w;
+ mpz_srcptr u;
+ mpz_srcptr v;
+#endif
+#else /* BERKELEY_MP */
+void
+#if __STDC__
+madd (mpz_srcptr u, mpz_srcptr v, mpz_ptr w)
+#else
+madd (u, v, w)
+ mpz_srcptr u;
+ mpz_srcptr v;
+ mpz_ptr w;
+#endif
+#endif /* BERKELEY_MP */
+{
+ mp_srcptr up, vp;
+ mp_ptr wp;
+ mp_size_t usize, vsize, wsize;
+ mp_size_t abs_usize;
+ mp_size_t abs_vsize;
+
+ usize = u->_mp_size;
+ vsize = v->_mp_size;
+ abs_usize = ABS (usize);
+ abs_vsize = ABS (vsize);
+
+ if (abs_usize < abs_vsize)
+ {
+ /* Swap U and V. */
+ {const __mpz_struct *t = u; u = v; v = t;}
+ {mp_size_t t = usize; usize = vsize; vsize = t;}
+ {mp_size_t t = abs_usize; abs_usize = abs_vsize; abs_vsize = t;}
+ }
+
+ /* True: ABS_USIZE >= ABS_VSIZE. */
+
+ /* If not space for w (and possible carry), increase space. */
+ wsize = abs_usize + 1;
+ if (w->_mp_alloc < wsize)
+ _mpz_realloc (w, wsize);
+
+ /* These must be after realloc (u or v may be the same as w). */
+ up = u->_mp_d;
+ vp = v->_mp_d;
+ wp = w->_mp_d;
+
+ if ((usize ^ vsize) < 0)
+ {
+ /* U and V have different sign. Need to compare them to determine
+ which operand to subtract from which. */
+
+ /* This test is right since ABS_USIZE >= ABS_VSIZE. */
+ if (abs_usize != abs_vsize)
+ {
+ mpn_sub (wp, up, abs_usize, vp, abs_vsize);
+ wsize = abs_usize;
+ MPN_NORMALIZE (wp, wsize);
+ if (usize < 0)
+ wsize = -wsize;
+ }
+ else if (mpn_cmp (up, vp, abs_usize) < 0)
+ {
+ mpn_sub_n (wp, vp, up, abs_usize);
+ wsize = abs_usize;
+ MPN_NORMALIZE (wp, wsize);
+ if (usize >= 0)
+ wsize = -wsize;
+ }
+ else
+ {
+ mpn_sub_n (wp, up, vp, abs_usize);
+ wsize = abs_usize;
+ MPN_NORMALIZE (wp, wsize);
+ if (usize < 0)
+ wsize = -wsize;
+ }
+ }
+ else
+ {
+ /* U and V have same sign. Add them. */
+ mp_limb_t cy_limb = mpn_add (wp, up, abs_usize, vp, abs_vsize);
+ wp[abs_usize] = cy_limb;
+ wsize = abs_usize + cy_limb;
+ if (usize < 0)
+ wsize = -wsize;
+ }
+
+ w->_mp_size = wsize;
+}
diff --git a/mpz/add_ui.c b/mpz/add_ui.c
new file mode 100644
index 000000000..a1e430631
--- /dev/null
+++ b/mpz/add_ui.c
@@ -0,0 +1,84 @@
+/* mpz_add_ui -- Add an mpz_t and an unsigned one-word integer.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_add_ui (mpz_ptr w, mpz_srcptr u, unsigned long int v)
+#else
+mpz_add_ui (w, u, v)
+ mpz_ptr w;
+ mpz_srcptr u;
+ unsigned long int v;
+#endif
+{
+ mp_srcptr up;
+ mp_ptr wp;
+ mp_size_t usize, wsize;
+ mp_size_t abs_usize;
+
+ usize = u->_mp_size;
+ abs_usize = ABS (usize);
+
+ /* If not space for W (and possible carry), increase space. */
+ wsize = abs_usize + 1;
+ if (w->_mp_alloc < wsize)
+ _mpz_realloc (w, wsize);
+
+ /* These must be after realloc (U may be the same as W). */
+ up = u->_mp_d;
+ wp = w->_mp_d;
+
+ if (abs_usize == 0)
+ {
+ wp[0] = v;
+ w->_mp_size = v != 0;
+ return;
+ }
+
+ if (usize >= 0)
+ {
+ mp_limb_t cy;
+ cy = mpn_add_1 (wp, up, abs_usize, v);
+ wp[abs_usize] = cy;
+ wsize = abs_usize + cy;
+ }
+ else
+ {
+ /* The signs are different. Need exact comparison to determine
+ which operand to subtract from which. */
+ if (abs_usize == 1 && up[0] < v)
+ {
+ wp[0] = v - up[0];
+ wsize = 1;
+ }
+ else
+ {
+ mpn_sub_1 (wp, up, abs_usize, v);
+ /* Size can decrease with at most one limb. */
+ wsize = -(abs_usize - (wp[abs_usize - 1] == 0));
+ }
+ }
+
+ w->_mp_size = wsize;
+}
diff --git a/mpz/and.c b/mpz/and.c
new file mode 100644
index 000000000..838d4b1db
--- /dev/null
+++ b/mpz/and.c
@@ -0,0 +1,278 @@
+/* mpz_and -- Logical and.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_and (mpz_ptr res, mpz_srcptr op1, mpz_srcptr op2)
+#else
+mpz_and (res, op1, op2)
+ mpz_ptr res;
+ mpz_srcptr op1;
+ mpz_srcptr op2;
+#endif
+{
+ mp_srcptr op1_ptr, op2_ptr;
+ mp_size_t op1_size, op2_size;
+ mp_ptr res_ptr;
+ mp_size_t res_size;
+ mp_size_t i;
+ TMP_DECL (marker);
+
+ TMP_MARK (marker);
+ op1_size = op1->_mp_size;
+ op2_size = op2->_mp_size;
+
+ op1_ptr = op1->_mp_d;
+ op2_ptr = op2->_mp_d;
+ res_ptr = res->_mp_d;
+
+ if (op1_size >= 0)
+ {
+ if (op2_size >= 0)
+ {
+ res_size = MIN (op1_size, op2_size);
+ /* First loop finds the size of the result. */
+ for (i = res_size - 1; i >= 0; i--)
+ if ((op1_ptr[i] & op2_ptr[i]) != 0)
+ break;
+ res_size = i + 1;
+
+ /* Handle allocation, now then we know exactly how much space is
+ needed for the result. */
+ if (res->_mp_alloc < res_size)
+ {
+ _mpz_realloc (res, res_size);
+ op1_ptr = op1->_mp_d;
+ op2_ptr = op2->_mp_d;
+ res_ptr = res->_mp_d;
+ }
+
+ /* Second loop computes the real result. */
+ for (i = res_size - 1; i >= 0; i--)
+ res_ptr[i] = op1_ptr[i] & op2_ptr[i];
+
+ res->_mp_size = res_size;
+ return;
+ }
+ else /* op2_size < 0 */
+ {
+ /* Fall through to the code at the end of the function. */
+ }
+ }
+ else
+ {
+ if (op2_size < 0)
+ {
+ mp_ptr opx;
+ mp_limb_t cy;
+ mp_size_t res_alloc;
+
+ /* Both operands are negative, so will be the result.
+ -((-OP1) & (-OP2)) = -(~(OP1 - 1) & ~(OP2 - 1)) =
+ = ~(~(OP1 - 1) & ~(OP2 - 1)) + 1 =
+ = ((OP1 - 1) | (OP2 - 1)) + 1 */
+
+ /* It might seem as we could end up with an (invalid) result with
+ a leading zero-limb here when one of the operands is of the
+ type 1,,0,,..,,.0. But some analysis shows that we surely
+ would get carry into the zero-limb in this situation... */
+
+ op1_size = -op1_size;
+ op2_size = -op2_size;
+
+ res_alloc = 1 + MAX (op1_size, op2_size);
+
+ opx = (mp_ptr) TMP_ALLOC (op1_size * BYTES_PER_MP_LIMB);
+ mpn_sub_1 (opx, op1_ptr, op1_size, (mp_limb_t) 1);
+ op1_ptr = opx;
+
+ opx = (mp_ptr) TMP_ALLOC (op2_size * BYTES_PER_MP_LIMB);
+ mpn_sub_1 (opx, op2_ptr, op2_size, (mp_limb_t) 1);
+ op2_ptr = opx;
+
+ if (res->_mp_alloc < res_alloc)
+ {
+ _mpz_realloc (res, res_alloc);
+ res_ptr = res->_mp_d;
+ /* Don't re-read OP1_PTR and OP2_PTR. They point to
+ temporary space--never to the space RES->_mp_D used
+ to point to before reallocation. */
+ }
+
+ if (op1_size >= op2_size)
+ {
+ MPN_COPY (res_ptr + op2_size, op1_ptr + op2_size,
+ op1_size - op2_size);
+ for (i = op2_size - 1; i >= 0; i--)
+ res_ptr[i] = op1_ptr[i] | op2_ptr[i];
+ res_size = op1_size;
+ }
+ else
+ {
+ MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size,
+ op2_size - op1_size);
+ for (i = op1_size - 1; i >= 0; i--)
+ res_ptr[i] = op1_ptr[i] | op2_ptr[i];
+ res_size = op2_size;
+ }
+
+ cy = mpn_add_1 (res_ptr, res_ptr, res_size, (mp_limb_t) 1);
+ if (cy)
+ {
+ res_ptr[res_size] = cy;
+ res_size++;
+ }
+
+ res->_mp_size = -res_size;
+ TMP_FREE (marker);
+ return;
+ }
+ else
+ {
+ /* We should compute -OP1 & OP2. Swap OP1 and OP2 and fall
+ through to the code that handles OP1 & -OP2. */
+ {mpz_srcptr t = op1; op1 = op2; op2 = t;}
+ {mp_srcptr t = op1_ptr; op1_ptr = op2_ptr; op2_ptr = t;}
+ {mp_size_t t = op1_size; op1_size = op2_size; op2_size = t;}
+ }
+
+ }
+
+ {
+#if ANDNEW
+ mp_size_t op2_lim;
+ mp_size_t count;
+
+ /* OP2 must be negated as with infinite precision.
+
+ Scan from the low end for a non-zero limb. The first non-zero
+ limb is simply negated (two's complement). Any subsequent
+ limbs are one's complemented. Of course, we don't need to
+ handle more limbs than there are limbs in the other, positive
+ operand as the result for those limbs is going to become zero
+ anyway. */
+
+ /* Scan for the least significant. non-zero OP2 limb, and zero the
+ result meanwhile for those limb positions. (We will surely
+ find a non-zero limb, so we can write the loop with one
+ termination condition only.) */
+ for (i = 0; op2_ptr[i] == 0; i++)
+ res_ptr[i] = 0;
+ op2_lim = i;
+
+ op2_size = -op2_size;
+
+ if (op1_size <= op2_size)
+ {
+ /* The ones-extended OP2 is >= than the zero-extended OP1.
+ RES_SIZE <= OP1_SIZE. Find the exact size. */
+ for (i = op1_size - 1; i > op2_lim; i--)
+ if ((op1_ptr[i] & ~op2_ptr[i]) != 0)
+ break;
+ res_size = i + 1;
+ for (i = res_size - 1; i > op2_lim; i--)
+ res_ptr[i] = op1_ptr[i] & ~op2_ptr[i];
+ res_ptr[op2_lim] = op1_ptr[op2_lim] & -op2_ptr[op2_lim];
+ /* Yes, this *can* happen! */
+ MPN_NORMALIZE (res_ptr, res_size);
+ }
+ else
+ {
+ /* The ones-extended OP2 is < than the zero-extended OP1.
+ RES_SIZE == OP1_SIZE, since OP1 is normalized. */
+ res_size = op1_size;
+ MPN_COPY (res_ptr + op2_size, op1_ptr + op2_size, op1_size - op2_size);
+ for (i = op2_size - 1; i > op2_lim; i--)
+ res_ptr[i] = op1_ptr[i] & ~op2_ptr[i];
+ res_ptr[op2_lim] = op1_ptr[op2_lim] & -op2_ptr[op2_lim];
+ }
+
+ res->_mp_size = res_size;
+#else
+
+ /* OP1 is positive and zero-extended,
+ OP2 is negative and ones-extended.
+ The result will be positive.
+ OP1 & -OP2 = OP1 & ~(OP2 - 1). */
+
+ mp_ptr opx;
+
+ op2_size = -op2_size;
+ opx = (mp_ptr) TMP_ALLOC (op2_size * BYTES_PER_MP_LIMB);
+ mpn_sub_1 (opx, op2_ptr, op2_size, (mp_limb_t) 1);
+ op2_ptr = opx;
+
+ if (op1_size > op2_size)
+ {
+ /* The result has the same size as OP1, since OP1 is normalized
+ and longer than the ones-extended OP2. */
+ res_size = op1_size;
+
+ /* Handle allocation, now then we know exactly how much space is
+ needed for the result. */
+ if (res->_mp_alloc < res_size)
+ {
+ _mpz_realloc (res, res_size);
+ res_ptr = res->_mp_d;
+ op1_ptr = op1->_mp_d;
+ /* Don't re-read OP2_PTR. It points to temporary space--never
+ to the space RES->_mp_D used to point to before reallocation. */
+ }
+
+ MPN_COPY (res_ptr + op2_size, op1_ptr + op2_size,
+ res_size - op2_size);
+ for (i = op2_size - 1; i >= 0; i--)
+ res_ptr[i] = op1_ptr[i] & ~op2_ptr[i];
+
+ res->_mp_size = res_size;
+ }
+ else
+ {
+ /* Find out the exact result size. Ignore the high limbs of OP2,
+ OP1 is zero-extended and would make the result zero. */
+ for (i = op1_size - 1; i >= 0; i--)
+ if ((op1_ptr[i] & ~op2_ptr[i]) != 0)
+ break;
+ res_size = i + 1;
+
+ /* Handle allocation, now then we know exactly how much space is
+ needed for the result. */
+ if (res->_mp_alloc < res_size)
+ {
+ _mpz_realloc (res, res_size);
+ res_ptr = res->_mp_d;
+ op1_ptr = op1->_mp_d;
+ /* Don't re-read OP2_PTR. It points to temporary space--never
+ to the space RES->_mp_D used to point to before reallocation. */
+ }
+
+ for (i = res_size - 1; i >= 0; i--)
+ res_ptr[i] = op1_ptr[i] & ~op2_ptr[i];
+
+ res->_mp_size = res_size;
+ }
+#endif
+ }
+ TMP_FREE (marker);
+}
diff --git a/mpz/array_init.c b/mpz/array_init.c
new file mode 100644
index 000000000..8b2e85c90
--- /dev/null
+++ b/mpz/array_init.c
@@ -0,0 +1,48 @@
+/* mpz_array_init (array, array_size, size_per_elem) --
+
+Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_array_init (mpz_ptr arr, mp_size_t arr_size, mp_size_t nbits)
+#else
+mpz_array_init (arr, arr_size, nbits)
+ mpz_ptr arr;
+ mp_size_t arr_size;
+ mp_size_t nbits;
+#endif
+{
+ register mp_ptr p;
+ register size_t i;
+ mp_size_t nlimbs;
+
+ nlimbs = (nbits + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB;
+ p = (mp_ptr) (*_mp_allocate_func) (arr_size * nlimbs * BYTES_PER_MP_LIMB);
+
+ for (i = 0; i < arr_size; i++)
+ {
+ arr[i]._mp_alloc = nlimbs + 1; /* Yes, lie a little... */
+ arr[i]._mp_size = 0;
+ arr[i]._mp_d = p + i * nlimbs;
+ }
+}
diff --git a/mpz/cdiv_q.c b/mpz/cdiv_q.c
new file mode 100644
index 000000000..860a232f0
--- /dev/null
+++ b/mpz/cdiv_q.c
@@ -0,0 +1,51 @@
+/* mpz_cdiv_q -- Division rounding the quotient towards +infinity. The
+ remainder gets the opposite sign as the denominator.
+
+Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_cdiv_q (mpz_ptr quot, mpz_srcptr dividend, mpz_srcptr divisor)
+#else
+mpz_cdiv_q (quot, dividend, divisor)
+ mpz_ptr quot;
+ mpz_srcptr dividend;
+ mpz_srcptr divisor;
+#endif
+{
+ mp_size_t dividend_size = dividend->_mp_size;
+ mp_size_t divisor_size = divisor->_mp_size;
+ mpz_t rem;
+ TMP_DECL (marker);
+
+ TMP_MARK (marker);
+
+ MPZ_TMP_INIT (rem, 1 + ABS (dividend_size));
+
+ mpz_tdiv_qr (quot, rem, dividend, divisor);
+
+ if ((divisor_size ^ dividend_size) >= 0 && rem->_mp_size != 0)
+ mpz_add_ui (quot, quot, 1L);
+
+ TMP_FREE (marker);
+}
diff --git a/mpz/cdiv_q_ui.c b/mpz/cdiv_q_ui.c
new file mode 100644
index 000000000..7b6cfd7af
--- /dev/null
+++ b/mpz/cdiv_q_ui.c
@@ -0,0 +1,64 @@
+/* mpz_cdiv_q_ui -- Division rounding the quotient towards +infinity. The
+ remainder gets the opposite sign as the denominator. In order to make it
+ always fit into the return type, the negative of the true remainder is
+ returned.
+
+Copyright (C) 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+unsigned long int
+#if __STDC__
+mpz_cdiv_q_ui (mpz_ptr quot, mpz_srcptr dividend, unsigned long int divisor)
+#else
+mpz_cdiv_q_ui (quot, dividend, divisor)
+ mpz_ptr quot;
+ mpz_srcptr dividend;
+ unsigned long int divisor;
+#endif
+{
+ mp_size_t dividend_size;
+ mp_size_t size;
+ mp_ptr quot_ptr;
+ mp_limb_t remainder_limb;
+
+ dividend_size = dividend->_mp_size;
+ size = ABS (dividend_size);
+
+ if (quot->_mp_alloc < size)
+ _mpz_realloc (quot, size);
+
+ quot_ptr = quot->_mp_d;
+
+ remainder_limb = mpn_divmod_1 (quot_ptr, dividend->_mp_d, size,
+ (mp_limb_t) divisor);
+
+ if (remainder_limb != 0 && dividend_size >= 0)
+ {
+ mpn_add_1 (quot_ptr, quot_ptr, size, (mp_limb_t) 1);
+ remainder_limb = divisor - remainder_limb;
+ }
+
+ size -= size != 0 && quot_ptr[size - 1] == 0;
+ quot->_mp_size = dividend_size >= 0 ? size : -size;
+
+ return remainder_limb;
+}
diff --git a/mpz/cdiv_qr.c b/mpz/cdiv_qr.c
new file mode 100644
index 000000000..bf7d6dacb
--- /dev/null
+++ b/mpz/cdiv_qr.c
@@ -0,0 +1,62 @@
+/* mpz_cdiv_qr -- Division rounding the quotient towards +infinity. The
+ remainder gets the opposite sign as the denominator.
+
+Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_cdiv_qr (mpz_ptr quot, mpz_ptr rem, mpz_srcptr dividend, mpz_srcptr divisor)
+#else
+mpz_cdiv_qr (quot, rem, dividend, divisor)
+ mpz_ptr quot;
+ mpz_ptr rem;
+ mpz_srcptr dividend;
+ mpz_srcptr divisor;
+#endif
+{
+ mp_size_t divisor_size = divisor->_mp_size;
+ mpz_t temp_divisor; /* N.B.: lives until function returns! */
+ TMP_DECL (marker);
+
+ TMP_MARK (marker);
+
+ /* We need the original value of the divisor after the quotient and
+ remainder have been preliminary calculated. We have to copy it to
+ temporary space if it's the same variable as either QUOT or REM. */
+ if (quot == divisor || rem == divisor)
+ {
+ MPZ_TMP_INIT (temp_divisor, ABS (divisor_size));
+ mpz_set (temp_divisor, divisor);
+ divisor = temp_divisor;
+ }
+
+ mpz_tdiv_qr (quot, rem, dividend, divisor);
+
+ if ((divisor_size ^ dividend->_mp_size) >= 0 && rem->_mp_size != 0)
+ {
+ mpz_add_ui (quot, quot, 1L);
+ mpz_sub (rem, rem, divisor);
+ }
+
+ TMP_FREE (marker);
+}
diff --git a/mpz/cdiv_qr_ui.c b/mpz/cdiv_qr_ui.c
new file mode 100644
index 000000000..a780e772e
--- /dev/null
+++ b/mpz/cdiv_qr_ui.c
@@ -0,0 +1,68 @@
+/* mpz_cdiv_qr_ui -- Division rounding the quotient towards +infinity. The
+ remainder gets the opposite sign as the denominator. In order to make it
+ always fit into the return type, the negative of the true remainder is
+ returned.
+
+Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+unsigned long int
+#if __STDC__
+mpz_cdiv_qr_ui (mpz_ptr quot, mpz_ptr rem, mpz_srcptr dividend, unsigned long int divisor)
+#else
+mpz_cdiv_qr_ui (quot, rem, dividend, divisor)
+ mpz_ptr quot;
+ mpz_ptr rem;
+ mpz_srcptr dividend;
+ unsigned long int divisor;
+#endif
+{
+ mp_size_t dividend_size;
+ mp_size_t size;
+ mp_ptr quot_ptr;
+ mp_limb_t remainder_limb;
+
+ dividend_size = dividend->_mp_size;
+ size = ABS (dividend_size);
+
+ if (quot->_mp_alloc < size)
+ _mpz_realloc (quot, size);
+
+ quot_ptr = quot->_mp_d;
+
+ remainder_limb = mpn_divmod_1 (quot_ptr, dividend->_mp_d, size,
+ (mp_limb_t) divisor);
+
+ if (remainder_limb != 0 && dividend_size >= 0)
+ {
+ mpn_add_1 (quot_ptr, quot_ptr, size, (mp_limb_t) 1);
+ remainder_limb = divisor - remainder_limb;
+ }
+
+ size -= size != 0 && quot_ptr[size - 1] == 0;
+ quot->_mp_size = dividend_size >= 0 ? size : -size;
+
+ rem->_mp_d[0] = remainder_limb;
+ rem->_mp_size = -(remainder_limb != 0);
+
+ return remainder_limb;
+}
diff --git a/mpz/cdiv_r.c b/mpz/cdiv_r.c
new file mode 100644
index 000000000..d34d138ce
--- /dev/null
+++ b/mpz/cdiv_r.c
@@ -0,0 +1,59 @@
+/* mpz_cdiv_r -- Division rounding the quotient towards +infinity. The
+ remainder gets the opposite sign as the denominator.
+
+Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_cdiv_r (mpz_ptr rem, mpz_srcptr dividend, mpz_srcptr divisor)
+#else
+mpz_cdiv_r (rem, dividend, divisor)
+ mpz_ptr rem;
+ mpz_srcptr dividend;
+ mpz_srcptr divisor;
+#endif
+{
+ mp_size_t divisor_size = divisor->_mp_size;
+ mpz_t temp_divisor; /* N.B.: lives until function returns! */
+ TMP_DECL (marker);
+
+ TMP_MARK (marker);
+
+ /* We need the original value of the divisor after the remainder has been
+ preliminary calculated. We have to copy it to temporary space if it's
+ the same variable as REM. */
+ if (rem == divisor)
+ {
+
+ MPZ_TMP_INIT (temp_divisor, ABS (divisor_size));
+ mpz_set (temp_divisor, divisor);
+ divisor = temp_divisor;
+ }
+
+ mpz_tdiv_r (rem, dividend, divisor);
+
+ if ((divisor_size ^ dividend->_mp_size) >= 0 && rem->_mp_size != 0)
+ mpz_sub (rem, rem, divisor);
+
+ TMP_FREE (marker);
+}
diff --git a/mpz/cdiv_r_ui.c b/mpz/cdiv_r_ui.c
new file mode 100644
index 000000000..757a3f5f7
--- /dev/null
+++ b/mpz/cdiv_r_ui.c
@@ -0,0 +1,54 @@
+/* mpz_cdiv_r_ui -- Division rounding the quotient towards +infinity. The
+ remainder gets the opposite sign as the denominator. In order to make it
+ always fit into the return type, the negative of the true remainder is
+ returned.
+
+Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+unsigned long int
+#if __STDC__
+mpz_cdiv_r_ui (mpz_ptr rem, mpz_srcptr dividend, unsigned long int divisor)
+#else
+mpz_cdiv_r_ui (rem, dividend, divisor)
+ mpz_ptr rem;
+ mpz_srcptr dividend;
+ unsigned long int divisor;
+#endif
+{
+ mp_size_t dividend_size;
+ mp_size_t size;
+ mp_limb_t remainder_limb;
+
+ dividend_size = dividend->_mp_size;
+ size = ABS (dividend_size);
+
+ remainder_limb = mpn_mod_1 (dividend->_mp_d, size, (mp_limb_t) divisor);
+
+ if (remainder_limb != 0 && dividend_size >= 0)
+ remainder_limb = divisor - remainder_limb;
+
+ rem->_mp_d[0] = remainder_limb;
+ rem->_mp_size = -(remainder_limb != 0);
+
+ return remainder_limb;
+}
diff --git a/mpz/cdiv_ui.c b/mpz/cdiv_ui.c
new file mode 100644
index 000000000..df841ede8
--- /dev/null
+++ b/mpz/cdiv_ui.c
@@ -0,0 +1,50 @@
+/* mpz_cdiv_ui -- Division rounding the quotient towards +infinity. The
+ remainder gets the opposite sign as the denominator. In order to make it
+ always fit into the return type, the negative of the true remainder is
+ returned.
+
+Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+unsigned long int
+#if __STDC__
+mpz_cdiv_ui (mpz_srcptr dividend, unsigned long int divisor)
+#else
+mpz_cdiv_ui (dividend, divisor)
+ mpz_srcptr dividend;
+ unsigned long int divisor;
+#endif
+{
+ mp_size_t dividend_size;
+ mp_size_t size;
+ mp_limb_t remainder_limb;
+
+ dividend_size = dividend->_mp_size;
+ size = ABS (dividend_size);
+
+ remainder_limb = mpn_mod_1 (dividend->_mp_d, size, (mp_limb_t) divisor);
+
+ if (remainder_limb != 0 && dividend_size >= 0)
+ remainder_limb = divisor - remainder_limb;
+
+ return remainder_limb;
+}
diff --git a/mpz/clear.c b/mpz/clear.c
new file mode 100644
index 000000000..00f3cfdc6
--- /dev/null
+++ b/mpz/clear.c
@@ -0,0 +1,35 @@
+/* mpz_clear -- de-allocate the space occupied by the dynamic digit space of
+ an integer.
+
+Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_clear (mpz_ptr m)
+#else
+mpz_clear (m)
+ mpz_ptr m;
+#endif
+{
+ (*_mp_free_func) (m->_mp_d, m->_mp_alloc * BYTES_PER_MP_LIMB);
+}
diff --git a/mpz/clrbit.c b/mpz/clrbit.c
new file mode 100644
index 000000000..59d956535
--- /dev/null
+++ b/mpz/clrbit.c
@@ -0,0 +1,114 @@
+/* mpz_clrbit -- clear a specified bit.
+
+Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_clrbit (mpz_ptr d, unsigned long int bit_index)
+#else
+mpz_clrbit (d, bit_index)
+ mpz_ptr d;
+ unsigned long int bit_index;
+#endif
+{
+ mp_size_t dsize = d->_mp_size;
+ mp_ptr dp = d->_mp_d;
+ mp_size_t limb_index;
+
+ limb_index = bit_index / BITS_PER_MP_LIMB;
+ if (dsize >= 0)
+ {
+ if (limb_index < dsize)
+ {
+ dp[limb_index] &= ~((mp_limb_t) 1 << (bit_index % BITS_PER_MP_LIMB));
+ MPN_NORMALIZE (dp, dsize);
+ d->_mp_size = dsize;
+ }
+ else
+ ;
+ }
+ else
+ {
+ mp_size_t zero_bound;
+
+ /* Simulate two's complement arithmetic, i.e. simulate
+ 1. Set OP = ~(OP - 1) [with infinitely many leading ones].
+ 2. clear the bit.
+ 3. Set OP = ~OP + 1. */
+
+ dsize = -dsize;
+
+ /* No upper bound on this loop, we're sure there's a non-zero limb
+ sooner ot later. */
+ for (zero_bound = 0; ; zero_bound++)
+ if (dp[zero_bound] != 0)
+ break;
+
+ if (limb_index > zero_bound)
+ {
+ if (limb_index < dsize)
+ dp[limb_index] |= (mp_limb_t) 1 << (bit_index % BITS_PER_MP_LIMB);
+ else
+ {
+ /* Ugh. The bit should be cleared outside of the end of the
+ number. We have to increase the size of the number. */
+ if (d->_mp_alloc < limb_index + 1)
+ {
+ _mpz_realloc (d, limb_index + 1);
+ dp = d->_mp_d;
+ }
+ MPN_ZERO (dp + dsize, limb_index - dsize);
+ dp[limb_index] = (mp_limb_t) 1 << (bit_index % BITS_PER_MP_LIMB);
+ d->_mp_size = -(limb_index + 1);
+ }
+ }
+ else if (limb_index == zero_bound)
+ {
+ dp[limb_index] = ((dp[limb_index] - 1)
+ | ((mp_limb_t) 1 << (bit_index % BITS_PER_MP_LIMB))) + 1;
+ if (dp[limb_index] == 0)
+ {
+ mp_size_t i;
+ for (i = limb_index + 1; i < dsize; i++)
+ {
+ dp[i] += 1;
+ if (dp[i] != 0)
+ goto fin;
+ }
+ /* We got carry all way out beyond the end of D. Increase
+ its size (and allocation if necessary). */
+ dsize++;
+ if (d->_mp_alloc < dsize)
+ {
+ _mpz_realloc (d, dsize);
+ dp = d->_mp_d;
+ }
+ dp[i] = 1;
+ d->_mp_size = -dsize;
+ fin:;
+ }
+ }
+ else
+ ;
+ }
+}
diff --git a/mpz/cmp.c b/mpz/cmp.c
new file mode 100644
index 000000000..37be3349a
--- /dev/null
+++ b/mpz/cmp.c
@@ -0,0 +1,75 @@
+/* mpz_cmp(u,v) -- Compare U, V. Return postive, zero, or negative
+ based on if U > V, U == V, or U < V.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#ifdef BERKELEY_MP
+#include "mp.h"
+#endif
+#include "gmp.h"
+#include "gmp-impl.h"
+
+#ifndef BERKELEY_MP
+int
+#if __STDC__
+mpz_cmp (mpz_srcptr u, mpz_srcptr v)
+#else
+mpz_cmp (u, v)
+ mpz_srcptr u;
+ mpz_srcptr v;
+#endif
+#else /* BERKELEY_MP */
+int
+#if __STDC__
+mcmp (mpz_srcptr u, mpz_srcptr v)
+#else
+mcmp (u, v)
+ mpz_srcptr u;
+ mpz_srcptr v;
+#endif
+#endif /* BERKELEY_MP */
+{
+ mp_size_t usize = u->_mp_size;
+ mp_size_t vsize = v->_mp_size;
+ mp_size_t size;
+ mp_srcptr up, vp;
+ int cmp;
+
+ if (usize != vsize)
+ return usize - vsize;
+
+ if (usize == 0)
+ return 0;
+
+ size = ABS (usize);
+
+ up = u->_mp_d;
+ vp = v->_mp_d;
+
+ cmp = mpn_cmp (up, vp, size);
+
+ if (cmp == 0)
+ return 0;
+
+ if ((cmp < 0) == (usize < 0))
+ return 1;
+ else
+ return -1;
+}
diff --git a/mpz/cmp_si.c b/mpz/cmp_si.c
new file mode 100644
index 000000000..8063fd386
--- /dev/null
+++ b/mpz/cmp_si.c
@@ -0,0 +1,66 @@
+/* mpz_cmp_si(u,v) -- Compare an integer U with a single-word int V.
+ Return positive, zero, or negative based on if U > V, U == V, or U < V.
+
+Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+/* gmp.h defines a macro for mpz_cmp_si. */
+#undef mpz_cmp_si
+
+int
+#if __STDC__
+mpz_cmp_si (mpz_srcptr u, signed long int v_digit)
+#else
+mpz_cmp_si (u, v_digit)
+ mpz_srcptr u;
+ signed long int v_digit;
+#endif
+{
+ mp_size_t usize = u->_mp_size;
+ mp_size_t vsize;
+ mp_limb_t u_digit;
+
+ vsize = 0;
+ if (v_digit > 0)
+ vsize = 1;
+ else if (v_digit < 0)
+ {
+ vsize = -1;
+ v_digit = -v_digit;
+ }
+
+ if (usize != vsize)
+ return usize - vsize;
+
+ if (usize == 0)
+ return 0;
+
+ u_digit = u->_mp_d[0];
+
+ if (u_digit == v_digit)
+ return 0;
+
+ if (u_digit > v_digit)
+ return usize;
+ else
+ return -usize;
+}
diff --git a/mpz/cmp_ui.c b/mpz/cmp_ui.c
new file mode 100644
index 000000000..1a50b96e1
--- /dev/null
+++ b/mpz/cmp_ui.c
@@ -0,0 +1,56 @@
+/* mpz_cmp_ui.c -- Compare a mpz_t a with an mp_limb_t b. Return positive,
+ zero, or negative based on if a > b, a == b, or a < b.
+
+Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+/* gmp.h defines a macro for mpz_cmp_ui. */
+#undef mpz_cmp_ui
+
+int
+#if __STDC__
+mpz_cmp_ui (mpz_srcptr u, unsigned long int v_digit)
+#else
+mpz_cmp_ui (u, v_digit)
+ mpz_srcptr u;
+ unsigned long int v_digit;
+#endif
+{
+ mp_size_t usize = u->_mp_size;
+
+ if (usize == 0)
+ return -(v_digit != 0);
+
+ if (usize == 1)
+ {
+ mp_limb_t u_digit;
+
+ u_digit = u->_mp_d[0];
+ if (u_digit > v_digit)
+ return 1;
+ if (u_digit < v_digit)
+ return -1;
+ return 0;
+ }
+
+ return (usize > 0) ? 1 : -1;
+}
diff --git a/mpz/com.c b/mpz/com.c
new file mode 100644
index 000000000..559f2b6b2
--- /dev/null
+++ b/mpz/com.c
@@ -0,0 +1,93 @@
+/* mpz_com(mpz_ptr dst, mpz_ptr src) -- Assign the bit-complemented value of
+ SRC to DST.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_com (mpz_ptr dst, mpz_srcptr src)
+#else
+mpz_com (dst, src)
+ mpz_ptr dst;
+ mpz_srcptr src;
+#endif
+{
+ mp_size_t size = src->_mp_size;
+ mp_srcptr src_ptr;
+ mp_ptr dst_ptr;
+
+ if (size >= 0)
+ {
+ /* As with infinite precision: one's complement, two's complement.
+ But this can be simplified using the identity -x = ~x + 1.
+ So we're going to compute (~~x) + 1 = x + 1! */
+
+ if (dst->_mp_alloc < size + 1)
+ _mpz_realloc (dst, size + 1);
+
+ src_ptr = src->_mp_d;
+ dst_ptr = dst->_mp_d;
+
+ if (size == 0)
+ {
+ /* Special case, as mpn_add wants the first arg's size >= the
+ second arg's size. */
+ dst_ptr[0] = 1;
+ dst->_mp_size = -1;
+ return;
+ }
+
+ {
+ mp_limb_t cy;
+
+ cy = mpn_add_1 (dst_ptr, src_ptr, size, (mp_limb_t) 1);
+ if (cy)
+ {
+ dst_ptr[size] = cy;
+ size++;
+ }
+ }
+
+ /* Store a negative size, to indicate ones-extension. */
+ dst->_mp_size = -size;
+ }
+ else
+ {
+ /* As with infinite precision: two's complement, then one's complement.
+ But that can be simplified using the identity -x = ~(x - 1).
+ So we're going to compute ~~(x - 1) = x - 1! */
+ size = -size;
+
+ if (dst->_mp_alloc < size)
+ _mpz_realloc (dst, size);
+
+ src_ptr = src->_mp_d;
+ dst_ptr = dst->_mp_d;
+
+ mpn_sub_1 (dst_ptr, src_ptr, size, (mp_limb_t) 1);
+ size -= dst_ptr[size - 1] == 0;
+
+ /* Store a positive size, to indicate zero-extension. */
+ dst->_mp_size = size;
+ }
+}
diff --git a/mpz/configure.in b/mpz/configure.in
new file mode 100644
index 000000000..ed84461c1
--- /dev/null
+++ b/mpz/configure.in
@@ -0,0 +1,12 @@
+# This file is a shell script fragment that supplies the information
+# necessary for a configure script to process the program in
+# this directory. For more information, look at ../configure.
+
+configdirs=tests
+srctrigger=add_ui.c
+srcname="GNU Multi-Precision library/mpz"
+
+# per-host:
+
+# per-target:
+
diff --git a/mpz/divexact.c b/mpz/divexact.c
new file mode 100644
index 000000000..336c3ff42
--- /dev/null
+++ b/mpz/divexact.c
@@ -0,0 +1,112 @@
+/* mpz_divexact -- finds quotient when known that quot * den == num && den != 0.
+
+Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/* Ken Weber (kweber@mat.ufrgs.br, kweber@mcs.kent.edu)
+
+ Funding for this work has been partially provided by Conselho Nacional
+ de Desenvolvimento Cienti'fico e Tecnolo'gico (CNPq) do Brazil, Grant
+ 301314194-2, and was done while I was a visiting reseacher in the Instituto
+ de Matema'tica at Universidade Federal do Rio Grande do Sul (UFRGS).
+
+ References:
+ T. Jebelean, An algorithm for exact division, Journal of Symbolic
+ Computation, v. 15, 1993, pp. 169-180. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+void
+#if __STDC__
+mpz_divexact (mpz_ptr quot, mpz_srcptr num, mpz_srcptr den)
+#else
+mpz_divexact (quot, num, den)
+ mpz_ptr quot;
+ mpz_srcptr num;
+ mpz_srcptr den;
+#endif
+{
+ mp_ptr qp, tp;
+ mp_size_t qsize, tsize;
+
+ mp_srcptr np = num->_mp_d;
+ mp_srcptr dp = den->_mp_d;
+ mp_size_t nsize = ABS (num->_mp_size);
+ mp_size_t dsize = ABS (den->_mp_size);
+ TMP_DECL (marker);
+
+ /* Generate divide-by-zero error if dsize == 0. */
+ if (dsize == 0)
+ {
+ quot->_mp_size = 1 / dsize;
+ return;
+ }
+
+ if (nsize == 0)
+ {
+ quot->_mp_size = 0;
+ return;
+ }
+
+ qsize = nsize - dsize + 1;
+ if (quot->_mp_alloc < qsize)
+ _mpz_realloc (quot, qsize);
+ qp = quot->_mp_d;
+
+ TMP_MARK (marker);
+
+ /* QUOT <-- NUM/2^r, T <-- DEN/2^r where = r number of twos in DEN. */
+ while (dp[0] == 0)
+ np += 1, nsize -= 1, dp += 1, dsize -= 1;
+ tsize = MIN (qsize, dsize);
+ if (dp[0] & 1)
+ {
+ if (qp != dp)
+ MPN_COPY (qp, np, qsize);
+ if (qp == dp) /* QUOT and DEN overlap. */
+ {
+ tp = (mp_ptr) TMP_ALLOC (sizeof (mp_limb_t) * tsize);
+ MPN_COPY (tp, dp, tsize);
+ }
+ else
+ tp = (mp_ptr) dp;
+ }
+ else
+ {
+ unsigned long int r;
+ tp = (mp_ptr) TMP_ALLOC (sizeof (mp_limb_t) * tsize);
+ count_trailing_zeros (r, dp[0]);
+ mpn_rshift (tp, dp, tsize, r);
+ if (dsize > tsize)
+ tp[tsize-1] |= dp[tsize] << (BITS_PER_MP_LIMB - r);
+ mpn_rshift (qp, np, qsize, r);
+ if (nsize > qsize)
+ qp[qsize-1] |= np[qsize] << (BITS_PER_MP_LIMB - r);
+ }
+
+ /* Now QUOT <-- QUOT/T. */
+ mpn_bdivmod (qp, qp, qsize, tp, tsize, qsize * BITS_PER_MP_LIMB);
+ MPN_NORMALIZE (qp, qsize);
+
+ quot->_mp_size = (num->_mp_size < 0) == (den->_mp_size < 0) ? qsize : -qsize;
+
+ TMP_FREE (marker);
+}
diff --git a/mpz/dmincl.c b/mpz/dmincl.c
new file mode 100644
index 000000000..51bd08487
--- /dev/null
+++ b/mpz/dmincl.c
@@ -0,0 +1,201 @@
+/* dmincl.c -- include file for tdiv_qr.c, tdiv_r.c.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/* If den == quot, den needs temporary storage.
+ If den == rem, den needs temporary storage.
+ If num == quot, num needs temporary storage.
+ If den has temporary storage, it can be normalized while being copied,
+ i.e no extra storage should be allocated. */
+
+/* This is the function body of mdiv, mpz_divmod, and mpz_mod.
+
+ If COMPUTE_QUOTIENT is defined, the quotient is put in the MP_INT
+ object quot, otherwise that variable is not referenced at all.
+
+ The remainder is always computed, and the result is put in the MP_INT
+ object rem. */
+
+{
+ mp_ptr np, dp;
+ mp_ptr qp, rp;
+ mp_size_t nsize = num->_mp_size;
+ mp_size_t dsize = den->_mp_size;
+ mp_size_t qsize, rsize;
+ mp_size_t sign_remainder = nsize;
+#ifdef COMPUTE_QUOTIENT
+ mp_size_t sign_quotient = nsize ^ dsize;
+#endif
+ unsigned normalization_steps;
+ mp_limb_t q_limb;
+ TMP_DECL (marker);
+
+ nsize = ABS (nsize);
+ dsize = ABS (dsize);
+
+ /* Ensure space is enough for quotient and remainder. */
+
+ /* We need space for an extra limb in the remainder, because it's
+ up-shifted (normalized) below. */
+ rsize = nsize + 1;
+ if (rem->_mp_alloc < rsize)
+ _mpz_realloc (rem, rsize);
+
+ qsize = rsize - dsize; /* qsize cannot be bigger than this. */
+ if (qsize <= 0)
+ {
+ if (num != rem)
+ {
+ rem->_mp_size = num->_mp_size;
+ MPN_COPY (rem->_mp_d, num->_mp_d, nsize);
+ }
+#ifdef COMPUTE_QUOTIENT
+ /* This needs to follow the assignment to rem, in case the
+ numerator and quotient are the same. */
+ quot->_mp_size = 0;
+#endif
+ return;
+ }
+
+#ifdef COMPUTE_QUOTIENT
+ if (quot->_mp_alloc < qsize)
+ _mpz_realloc (quot, qsize);
+#endif
+
+ /* Read pointers here, when reallocation is finished. */
+ np = num->_mp_d;
+ dp = den->_mp_d;
+ rp = rem->_mp_d;
+
+ /* Optimize division by a single-limb divisor. */
+ if (dsize == 1)
+ {
+ mp_limb_t rlimb;
+#ifdef COMPUTE_QUOTIENT
+ qp = quot->_mp_d;
+ rlimb = mpn_divmod_1 (qp, np, nsize, dp[0]);
+ qsize -= qp[qsize - 1] == 0;
+ quot->_mp_size = sign_quotient >= 0 ? qsize : -qsize;
+#else
+ rlimb = mpn_mod_1 (np, nsize, dp[0]);
+#endif
+ rp[0] = rlimb;
+ rsize = rlimb != 0;
+ rem->_mp_size = sign_remainder >= 0 ? rsize : -rsize;
+ return;
+ }
+
+ TMP_MARK (marker);
+
+#ifdef COMPUTE_QUOTIENT
+ qp = quot->_mp_d;
+
+ /* Make sure QP and NP point to different objects. Otherwise the
+ numerator would be gradually overwritten by the quotient limbs. */
+ if (qp == np)
+ {
+ /* Copy NP object to temporary space. */
+ np = (mp_ptr) TMP_ALLOC (nsize * BYTES_PER_MP_LIMB);
+ MPN_COPY (np, qp, nsize);
+ }
+
+#else
+ /* Put quotient at top of remainder. */
+ qp = rp + dsize;
+#endif
+
+ count_leading_zeros (normalization_steps, dp[dsize - 1]);
+
+ /* Normalize the denominator, i.e. make its most significant bit set by
+ shifting it NORMALIZATION_STEPS bits to the left. Also shift the
+ numerator the same number of steps (to keep the quotient the same!). */
+ if (normalization_steps != 0)
+ {
+ mp_ptr tp;
+ mp_limb_t nlimb;
+
+ /* Shift up the denominator setting the most significant bit of
+ the most significant word. Use temporary storage not to clobber
+ the original contents of the denominator. */
+ tp = (mp_ptr) TMP_ALLOC (dsize * BYTES_PER_MP_LIMB);
+ mpn_lshift (tp, dp, dsize, normalization_steps);
+ dp = tp;
+
+ /* Shift up the numerator, possibly introducing a new most
+ significant word. Move the shifted numerator in the remainder
+ meanwhile. */
+ nlimb = mpn_lshift (rp, np, nsize, normalization_steps);
+ if (nlimb != 0)
+ {
+ rp[nsize] = nlimb;
+ rsize = nsize + 1;
+ }
+ else
+ rsize = nsize;
+ }
+ else
+ {
+ /* The denominator is already normalized, as required. Copy it to
+ temporary space if it overlaps with the quotient or remainder. */
+#ifdef COMPUTE_QUOTIENT
+ if (dp == rp || dp == qp)
+#else
+ if (dp == rp)
+#endif
+ {
+ mp_ptr tp;
+
+ tp = (mp_ptr) TMP_ALLOC (dsize * BYTES_PER_MP_LIMB);
+ MPN_COPY (tp, dp, dsize);
+ dp = tp;
+ }
+
+ /* Move the numerator to the remainder. */
+ if (rp != np)
+ MPN_COPY (rp, np, nsize);
+
+ rsize = nsize;
+ }
+
+ q_limb = mpn_divmod (qp, rp, rsize, dp, dsize);
+
+#ifdef COMPUTE_QUOTIENT
+ qsize = rsize - dsize;
+ if (q_limb)
+ {
+ qp[qsize] = q_limb;
+ qsize += 1;
+ }
+
+ quot->_mp_size = sign_quotient >= 0 ? qsize : -qsize;
+#endif
+
+ rsize = dsize;
+ MPN_NORMALIZE (rp, rsize);
+
+ if (normalization_steps != 0 && rsize != 0)
+ {
+ mpn_rshift (rp, rp, rsize, normalization_steps);
+ rsize -= rp[rsize - 1] == 0;
+ }
+
+ rem->_mp_size = sign_remainder >= 0 ? rsize : -rsize;
+ TMP_FREE (marker);
+}
diff --git a/mpz/fac_ui.c b/mpz/fac_ui.c
new file mode 100644
index 000000000..a170060a5
--- /dev/null
+++ b/mpz/fac_ui.c
@@ -0,0 +1,157 @@
+/* mpz_fac_ui(result, n) -- Set RESULT to N!.
+
+Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#ifdef DBG
+#include <stdio.h>
+#endif
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+void
+#if __STDC__
+mpz_fac_ui (mpz_ptr result, unsigned long int n)
+#else
+mpz_fac_ui (result, n)
+ mpz_ptr result;
+ unsigned long int n;
+#endif
+{
+#if SIMPLE_FAC
+
+ /* Be silly. Just multiply the numbers in ascending order. O(n**2). */
+
+ unsigned long int k;
+
+ mpz_set_ui (result, 1L);
+
+ for (k = 2; k <= n; k++)
+ mpz_mul_ui (result, result, k);
+#else
+
+ /* Be smarter. Multiply groups of numbers in ascending order until the
+ product doesn't fit in a limb. Multiply these partial product in a
+ balanced binary tree fashion, to make the operand have as equal sizes
+ as possible. When the operands have about the same size, mpn_mul
+ becomes faster. */
+
+ unsigned long int p, k;
+ mp_limb_t p1, p0;
+
+ /* Stack of partial products, used to make the computation balanced
+ (i.e. make the sizes of the multiplication operands equal). The
+ topmost position of MP_STACK will contain a one-limb partial product,
+ the second topmost will contain a two-limb partial product, and so
+ on. MP_STACK[0] will contain a partial product with 2**t limbs.
+ To compute n! MP_STACK needs to be less than
+ log(n)**2/log(BITS_PER_MP_LIMB), so 30 is surely enough. */
+#define MP_STACK_SIZE 30
+ mpz_t mp_stack[MP_STACK_SIZE];
+
+ /* TOP is an index into MP_STACK, giving the topmost element.
+ TOP_LIMIT_SO_FAR is the largets value it has taken so far. */
+ int top, top_limit_so_far;
+
+ /* Count of the total number of limbs put on MP_STACK so far. This
+ variable plays an essential role in making the compututation balanced.
+ See below. */
+ unsigned int tree_cnt;
+
+ top = top_limit_so_far = -1;
+ tree_cnt = 0;
+ p = 1;
+ for (k = 2; k <= n; k++)
+ {
+ /* Multiply the partial product in P with K. */
+ umul_ppmm (p1, p0, (mp_limb_t) p, (mp_limb_t) k);
+
+ /* Did we get overflow into the high limb, i.e. is the partial
+ product now more than one limb? */
+ if (p1 != 0)
+ {
+ tree_cnt++;
+
+ if (tree_cnt % 2 == 0)
+ {
+ mp_size_t i;
+
+ /* TREE_CNT is even (i.e. we have generated an even number of
+ one-limb partial products), which means that we have a
+ single-limb product on the top of MP_STACK. */
+
+ mpz_mul_ui (mp_stack[top], mp_stack[top], p);
+
+ /* If TREE_CNT is divisable by 4, 8,..., we have two
+ similar-sized partial products with 2, 4,... limbs at
+ the topmost two positions of MP_STACK. Multiply them
+ to form a new partial product with 4, 8,... limbs. */
+ for (i = 4; (tree_cnt & (i - 1)) == 0; i <<= 1)
+ {
+ mpz_mul (mp_stack[top - 1],
+ mp_stack[top], mp_stack[top - 1]);
+ top--;
+ }
+ }
+ else
+ {
+ /* Put the single-limb partial product in P on the stack.
+ (The next time we get a single-limb product, we will
+ multiply the two together.) */
+ top++;
+ if (top > top_limit_so_far)
+ {
+ if (top > MP_STACK_SIZE)
+ abort();
+ /* The stack is now bigger than ever, initialize the top
+ element. */
+ mpz_init_set_ui (mp_stack[top], p);
+ top_limit_so_far++;
+ }
+ else
+ mpz_set_ui (mp_stack[top], p);
+ }
+
+ /* We ignored the last result from umul_ppmm. Put K in P as the
+ first component of the next single-limb partial product. */
+ p = k;
+ }
+ else
+ /* We didn't get overflow in umul_ppmm. Put p0 in P and try
+ with one more value of K. */
+ p = p0; /* bogus if long != mp_limb_t */
+ }
+
+ /* We have partial products in mp_stack[0..top], in descending order.
+ We also have a small partial product in p.
+ Their product is the final result. */
+ if (top < 0)
+ mpz_set_ui (result, p);
+ else
+ mpz_mul_ui (result, mp_stack[top--], p);
+ while (top >= 0)
+ mpz_mul (result, result, mp_stack[top--]);
+
+ /* Free the storage allocated for MP_STACK. */
+ for (top = top_limit_so_far; top >= 0; top--)
+ mpz_clear (mp_stack[top]);
+#endif
+}
diff --git a/mpz/fdiv_q.c b/mpz/fdiv_q.c
new file mode 100644
index 000000000..3da943af9
--- /dev/null
+++ b/mpz/fdiv_q.c
@@ -0,0 +1,51 @@
+/* mpz_fdiv_q -- Division rounding the quotient towards -infinity.
+ The remainder gets the same sign as the denominator.
+
+Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_fdiv_q (mpz_ptr quot, mpz_srcptr dividend, mpz_srcptr divisor)
+#else
+mpz_fdiv_q (quot, dividend, divisor)
+ mpz_ptr quot;
+ mpz_srcptr dividend;
+ mpz_srcptr divisor;
+#endif
+{
+ mp_size_t dividend_size = dividend->_mp_size;
+ mp_size_t divisor_size = divisor->_mp_size;
+ mpz_t rem;
+ TMP_DECL (marker);
+
+ TMP_MARK (marker);
+
+ MPZ_TMP_INIT (rem, 1 + ABS (dividend_size));
+
+ mpz_tdiv_qr (quot, rem, dividend, divisor);
+
+ if ((divisor_size ^ dividend_size) < 0 && rem->_mp_size != 0)
+ mpz_sub_ui (quot, quot, 1L);
+
+ TMP_FREE (marker);
+}
diff --git a/mpz/fdiv_q_2exp.c b/mpz/fdiv_q_2exp.c
new file mode 100644
index 000000000..3f56baff2
--- /dev/null
+++ b/mpz/fdiv_q_2exp.c
@@ -0,0 +1,94 @@
+/* mpz_fdiv_q_2exp -- Divide an integer by 2**CNT. Round the quotient
+ towards -infinity.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_fdiv_q_2exp (mpz_ptr w, mpz_srcptr u, unsigned long int cnt)
+#else
+mpz_fdiv_q_2exp (w, u, cnt)
+ mpz_ptr w;
+ mpz_srcptr u;
+ unsigned long int cnt;
+#endif
+{
+ mp_size_t usize = u->_mp_size;
+ mp_size_t wsize;
+ mp_size_t abs_usize = ABS (usize);
+ mp_size_t limb_cnt;
+ mp_ptr wp;
+ mp_limb_t round = 0;
+
+ limb_cnt = cnt / BITS_PER_MP_LIMB;
+ wsize = abs_usize - limb_cnt;
+ if (wsize <= 0)
+ {
+ wp = w->_mp_d;
+ wsize = 0;
+ /* Set ROUND since we know we skip some non-zero words in this case.
+ Well, if U is zero, we don't, but then this will be taken care of
+ below, since rounding only really takes place for negative U. */
+ round = 1;
+ wp[0] = 1;
+ w->_mp_size = -(usize < 0);
+ return;
+ }
+ else
+ {
+ mp_size_t i;
+ mp_ptr up;
+
+ /* Make sure there is enough space. We make an extra limb
+ here to account for possible rounding at the end. */
+ if (w->_mp_alloc < wsize + 1)
+ _mpz_realloc (w, wsize + 1);
+
+ wp = w->_mp_d;
+ up = u->_mp_d;
+
+ /* Set ROUND if we are about skip some non-zero limbs. */
+ for (i = 0; i < limb_cnt && round == 0; i++)
+ round = up[i];
+
+ cnt %= BITS_PER_MP_LIMB;
+ if (cnt != 0)
+ {
+ round |= mpn_rshift (wp, up + limb_cnt, wsize, cnt);
+ wsize -= wp[wsize - 1] == 0;
+ }
+ else
+ {
+ MPN_COPY_INCR (wp, up + limb_cnt, wsize);
+ }
+ }
+
+ if (usize < 0 && round != 0)
+ {
+ mp_limb_t cy;
+ cy = mpn_add_1 (wp, wp, wsize, 1);
+ wp[wsize] = cy;
+ wsize += cy;
+ }
+ w->_mp_size = usize >= 0 ? wsize : -wsize;
+}
diff --git a/mpz/fdiv_q_ui.c b/mpz/fdiv_q_ui.c
new file mode 100644
index 000000000..3d6825d4f
--- /dev/null
+++ b/mpz/fdiv_q_ui.c
@@ -0,0 +1,62 @@
+/* mpz_fdiv_q_ui -- Division rounding the quotient towards -infinity.
+ The remainder gets the same sign as the denominator.
+
+Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+unsigned long int
+#if __STDC__
+mpz_fdiv_q_ui (mpz_ptr quot, mpz_srcptr dividend, unsigned long int divisor)
+#else
+mpz_fdiv_q_ui (quot, dividend, divisor)
+ mpz_ptr quot;
+ mpz_srcptr dividend;
+ unsigned long int divisor;
+#endif
+{
+ mp_size_t dividend_size;
+ mp_size_t size;
+ mp_ptr quot_ptr;
+ mp_limb_t remainder_limb;
+
+ dividend_size = dividend->_mp_size;
+ size = ABS (dividend_size);
+
+ if (quot->_mp_alloc < size)
+ _mpz_realloc (quot, size);
+
+ quot_ptr = quot->_mp_d;
+
+ remainder_limb = mpn_divmod_1 (quot_ptr, dividend->_mp_d, size,
+ (mp_limb_t) divisor);
+
+ if (remainder_limb != 0 && dividend_size < 0)
+ {
+ mpn_add_1 (quot_ptr, quot_ptr, size, (mp_limb_t) 1);
+ remainder_limb = divisor - remainder_limb;
+ }
+
+ size -= size != 0 && quot_ptr[size - 1] == 0;
+ quot->_mp_size = dividend_size >= 0 ? size : -size;
+
+ return remainder_limb;
+}
diff --git a/mpz/fdiv_qr.c b/mpz/fdiv_qr.c
new file mode 100644
index 000000000..2abb16ccb
--- /dev/null
+++ b/mpz/fdiv_qr.c
@@ -0,0 +1,62 @@
+/* mpz_fdiv_qr -- Division rounding the quotient towards -infinity.
+ The remainder gets the same sign as the denominator.
+
+Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_fdiv_qr (mpz_ptr quot, mpz_ptr rem, mpz_srcptr dividend, mpz_srcptr divisor)
+#else
+mpz_fdiv_qr (quot, rem, dividend, divisor)
+ mpz_ptr quot;
+ mpz_ptr rem;
+ mpz_srcptr dividend;
+ mpz_srcptr divisor;
+#endif
+{
+ mp_size_t divisor_size = divisor->_mp_size;
+ mpz_t temp_divisor; /* N.B.: lives until function returns! */
+ TMP_DECL (marker);
+
+ TMP_MARK (marker);
+
+ /* We need the original value of the divisor after the quotient and
+ remainder have been preliminary calculated. We have to copy it to
+ temporary space if it's the same variable as either QUOT or REM. */
+ if (quot == divisor || rem == divisor)
+ {
+ MPZ_TMP_INIT (temp_divisor, ABS (divisor_size));
+ mpz_set (temp_divisor, divisor);
+ divisor = temp_divisor;
+ }
+
+ mpz_tdiv_qr (quot, rem, dividend, divisor);
+
+ if ((divisor_size ^ dividend->_mp_size) < 0 && rem->_mp_size != 0)
+ {
+ mpz_sub_ui (quot, quot, 1L);
+ mpz_add (rem, rem, divisor);
+ }
+
+ TMP_FREE (marker);
+}
diff --git a/mpz/fdiv_qr_ui.c b/mpz/fdiv_qr_ui.c
new file mode 100644
index 000000000..a22b702a8
--- /dev/null
+++ b/mpz/fdiv_qr_ui.c
@@ -0,0 +1,66 @@
+/* mpz_fdiv_qr_ui -- Division rounding the quotient towards -infinity.
+ The remainder gets the same sign as the denominator.
+
+Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+unsigned long int
+#if __STDC__
+mpz_fdiv_qr_ui (mpz_ptr quot, mpz_ptr rem, mpz_srcptr dividend, unsigned long int divisor)
+#else
+mpz_fdiv_qr_ui (quot, rem, dividend, divisor)
+ mpz_ptr quot;
+ mpz_ptr rem;
+ mpz_srcptr dividend;
+ unsigned long int divisor;
+#endif
+{
+ mp_size_t dividend_size;
+ mp_size_t size;
+ mp_ptr quot_ptr;
+ mp_limb_t remainder_limb;
+
+ dividend_size = dividend->_mp_size;
+ size = ABS (dividend_size);
+
+ if (quot->_mp_alloc < size)
+ _mpz_realloc (quot, size);
+
+ quot_ptr = quot->_mp_d;
+
+ remainder_limb = mpn_divmod_1 (quot_ptr, dividend->_mp_d, size,
+ (mp_limb_t) divisor);
+
+ if (remainder_limb != 0 && dividend_size < 0)
+ {
+ mpn_add_1 (quot_ptr, quot_ptr, size, (mp_limb_t) 1);
+ remainder_limb = divisor - remainder_limb;
+ }
+
+ size -= size != 0 && quot_ptr[size - 1] == 0;
+ quot->_mp_size = dividend_size >= 0 ? size : -size;
+
+ rem->_mp_d[0] = remainder_limb;
+ rem->_mp_size = remainder_limb != 0;
+
+ return remainder_limb;
+}
diff --git a/mpz/fdiv_r.c b/mpz/fdiv_r.c
new file mode 100644
index 000000000..14e045bbe
--- /dev/null
+++ b/mpz/fdiv_r.c
@@ -0,0 +1,58 @@
+/* mpz_fdiv_r -- Division rounding the quotient towards -infinity.
+ The remainder gets the same sign as the denominator.
+
+Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_fdiv_r (mpz_ptr rem, mpz_srcptr dividend, mpz_srcptr divisor)
+#else
+mpz_fdiv_r (rem, dividend, divisor)
+ mpz_ptr rem;
+ mpz_srcptr dividend;
+ mpz_srcptr divisor;
+#endif
+{
+ mp_size_t divisor_size = divisor->_mp_size;
+ mpz_t temp_divisor; /* N.B.: lives until function returns! */
+ TMP_DECL (marker);
+
+ TMP_MARK (marker);
+
+ /* We need the original value of the divisor after the remainder has been
+ preliminary calculated. We have to copy it to temporary space if it's
+ the same variable as REM. */
+ if (rem == divisor)
+ {
+ MPZ_TMP_INIT (temp_divisor, ABS (divisor_size));
+ mpz_set (temp_divisor, divisor);
+ divisor = temp_divisor;
+ }
+
+ mpz_tdiv_r (rem, dividend, divisor);
+
+ if ((divisor_size ^ dividend->_mp_size) < 0 && rem->_mp_size != 0)
+ mpz_add (rem, rem, divisor);
+
+ TMP_FREE (marker);
+}
diff --git a/mpz/fdiv_r_2exp.c b/mpz/fdiv_r_2exp.c
new file mode 100644
index 000000000..04190b1b0
--- /dev/null
+++ b/mpz/fdiv_r_2exp.c
@@ -0,0 +1,88 @@
+/* mpz_fdiv_r_2exp -- Divide a integer by 2**CNT and produce a remainder.
+
+Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_fdiv_r_2exp (mpz_ptr res, mpz_srcptr in, unsigned long int cnt)
+#else
+mpz_fdiv_r_2exp (res, in, cnt)
+ mpz_ptr res;
+ mpz_srcptr in;
+ unsigned long int cnt;
+#endif
+{
+ mp_size_t in_size = ABS (in->_mp_size);
+ mp_size_t res_size;
+ mp_size_t limb_cnt = cnt / BITS_PER_MP_LIMB;
+ mp_srcptr in_ptr = in->_mp_d;
+
+ if (in_size > limb_cnt)
+ {
+ /* The input operand is (probably) greater than 2**CNT. */
+ mp_limb_t x;
+
+ x = in_ptr[limb_cnt] & (((mp_limb_t) 1 << cnt % BITS_PER_MP_LIMB) - 1);
+ if (x != 0)
+ {
+ res_size = limb_cnt + 1;
+ if (res->_mp_alloc < res_size)
+ _mpz_realloc (res, res_size);
+
+ res->_mp_d[limb_cnt] = x;
+ }
+ else
+ {
+ res_size = limb_cnt;
+ MPN_NORMALIZE (in_ptr, res_size);
+
+ if (res->_mp_alloc < res_size)
+ _mpz_realloc (res, res_size);
+
+ limb_cnt = res_size;
+ }
+ }
+ else
+ {
+ /* The input operand is smaller than 2**CNT. We perform a no-op,
+ apart from that we might need to copy IN to RES. */
+ res_size = in_size;
+ if (res->_mp_alloc < res_size)
+ _mpz_realloc (res, res_size);
+
+ limb_cnt = res_size;
+ }
+
+ if (res != in)
+ MPN_COPY (res->_mp_d, in->_mp_d, limb_cnt);
+ res->_mp_size = res_size;
+ if (in->_mp_size < 0 && res_size != 0)
+ {
+ /* Result should be 2^CNT - RES */
+ mpz_t tmp;
+ MPZ_TMP_INIT (tmp, limb_cnt + 1);
+ mpz_set_ui (tmp, 1L);
+ mpz_mul_2exp (tmp, tmp, cnt);
+ mpz_sub (res, tmp, res);
+ }
+}
diff --git a/mpz/fdiv_r_ui.c b/mpz/fdiv_r_ui.c
new file mode 100644
index 000000000..c4c37498c
--- /dev/null
+++ b/mpz/fdiv_r_ui.c
@@ -0,0 +1,52 @@
+/* mpz_fdiv_r_ui -- Division rounding the quotient towards -infinity.
+ The remainder gets the same sign as the denominator.
+
+Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+unsigned long int
+#if __STDC__
+mpz_fdiv_r_ui (mpz_ptr rem, mpz_srcptr dividend, unsigned long int divisor)
+#else
+mpz_fdiv_r_ui (rem, dividend, divisor)
+ mpz_ptr rem;
+ mpz_srcptr dividend;
+ unsigned long int divisor;
+#endif
+{
+ mp_size_t dividend_size;
+ mp_size_t size;
+ mp_limb_t remainder_limb;
+
+ dividend_size = dividend->_mp_size;
+ size = ABS (dividend_size);
+
+ remainder_limb = mpn_mod_1 (dividend->_mp_d, size, (mp_limb_t) divisor);
+
+ if (remainder_limb != 0 && dividend_size < 0)
+ remainder_limb = divisor - remainder_limb;
+
+ rem->_mp_d[0] = remainder_limb;
+ rem->_mp_size = remainder_limb != 0;
+
+ return remainder_limb;
+}
diff --git a/mpz/fdiv_ui.c b/mpz/fdiv_ui.c
new file mode 100644
index 000000000..4d018a229
--- /dev/null
+++ b/mpz/fdiv_ui.c
@@ -0,0 +1,48 @@
+/* mpz_fdiv_ui -- Division rounding the quotient towards -infinity.
+ The remainder gets the same sign as the denominator.
+
+Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+unsigned long int
+#if __STDC__
+mpz_fdiv_ui (mpz_srcptr dividend, unsigned long int divisor)
+#else
+mpz_fdiv_ui (dividend, divisor)
+ mpz_srcptr dividend;
+ unsigned long int divisor;
+#endif
+{
+ mp_size_t dividend_size;
+ mp_size_t size;
+ mp_limb_t remainder_limb;
+
+ dividend_size = dividend->_mp_size;
+ size = ABS (dividend_size);
+
+ remainder_limb = mpn_mod_1 (dividend->_mp_d, size, (mp_limb_t) divisor);
+
+ if (remainder_limb != 0 && dividend_size < 0)
+ remainder_limb = divisor - remainder_limb;
+
+ return remainder_limb;
+}
diff --git a/mpz/gcd.c b/mpz/gcd.c
new file mode 100644
index 000000000..f93030c8f
--- /dev/null
+++ b/mpz/gcd.c
@@ -0,0 +1,178 @@
+/* mpz/gcd.c: Calculate the greatest common divisor of two integers.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+void *_mpz_realloc ();
+
+#ifndef BERKELEY_MP
+void
+#if __STDC__
+mpz_gcd (mpz_ptr g, mpz_srcptr u, mpz_srcptr v)
+#else
+mpz_gcd (g, u, v)
+ mpz_ptr g;
+ mpz_srcptr u;
+ mpz_srcptr v;
+#endif
+#else /* BERKELEY_MP */
+void
+#if __STDC__
+gcd (mpz_srcptr u, mpz_srcptr v, mpz_ptr g)
+#else
+gcd (u, v, g)
+ mpz_ptr g;
+ mpz_srcptr u;
+ mpz_srcptr v;
+#endif
+#endif /* BERKELEY_MP */
+
+{
+ unsigned long int g_zero_bits, u_zero_bits, v_zero_bits;
+ mp_size_t g_zero_limbs, u_zero_limbs, v_zero_limbs;
+ mp_ptr tp;
+ mp_ptr up = u->_mp_d;
+ mp_size_t usize = ABS (u->_mp_size);
+ mp_ptr vp = v->_mp_d;
+ mp_size_t vsize = ABS (v->_mp_size);
+ mp_size_t gsize;
+ TMP_DECL (marker);
+
+ /* GCD(0, V) == V. */
+ if (usize == 0)
+ {
+ g->_mp_size = vsize;
+ if (g == v)
+ return;
+ if (g->_mp_alloc < vsize)
+ _mpz_realloc (g, vsize);
+ MPN_COPY (g->_mp_d, vp, vsize);
+ return;
+ }
+
+ /* GCD(U, 0) == U. */
+ if (vsize == 0)
+ {
+ g->_mp_size = usize;
+ if (g == u)
+ return;
+ if (g->_mp_alloc < usize)
+ _mpz_realloc (g, usize);
+ MPN_COPY (g->_mp_d, up, usize);
+ return;
+ }
+
+ if (usize == 1)
+ {
+ g->_mp_size = 1;
+ g->_mp_d[0] = mpn_gcd_1 (vp, vsize, up[0]);
+ return;
+ }
+
+ if (vsize == 1)
+ {
+ g->_mp_size = 1;
+ g->_mp_d[0] = mpn_gcd_1 (up, usize, vp[0]);
+ return;
+ }
+
+ TMP_MARK (marker);
+
+ /* Eliminate low zero bits from U and V and move to temporary storage. */
+ while (*up == 0)
+ up++;
+ u_zero_limbs = up - u->_mp_d;
+ usize -= u_zero_limbs;
+ count_trailing_zeros (u_zero_bits, *up);
+ tp = up;
+ up = (mp_ptr) TMP_ALLOC (usize * BYTES_PER_MP_LIMB);
+ if (u_zero_bits != 0)
+ {
+ mpn_rshift (up, tp, usize, u_zero_bits);
+ usize -= up[usize - 1] == 0;
+ }
+ else
+ MPN_COPY (up, tp, usize);
+
+ while (*vp == 0)
+ vp++;
+ v_zero_limbs = vp - v->_mp_d;
+ vsize -= v_zero_limbs;
+ count_trailing_zeros (v_zero_bits, *vp);
+ tp = vp;
+ vp = (mp_ptr) TMP_ALLOC (vsize * BYTES_PER_MP_LIMB);
+ if (v_zero_bits != 0)
+ {
+ mpn_rshift (vp, tp, vsize, v_zero_bits);
+ vsize -= vp[vsize - 1] == 0;
+ }
+ else
+ MPN_COPY (vp, tp, vsize);
+
+ if (u_zero_limbs > v_zero_limbs)
+ {
+ g_zero_limbs = v_zero_limbs;
+ g_zero_bits = v_zero_bits;
+ }
+ else if (u_zero_limbs < v_zero_limbs)
+ {
+ g_zero_limbs = u_zero_limbs;
+ g_zero_bits = u_zero_bits;
+ }
+ else /* Equal. */
+ {
+ g_zero_limbs = u_zero_limbs;
+ g_zero_bits = MIN (u_zero_bits, v_zero_bits);
+ }
+
+ /* Call mpn_gcd. The 1st argument must not have more bits than the 2nd. */
+ vsize = (usize < vsize || (usize == vsize && up[usize-1] < vp[vsize-1]))
+ ? mpn_gcd (vp, up, usize, vp, vsize)
+ : mpn_gcd (vp, vp, vsize, up, usize);
+
+ /* Here G <-- V << (g_zero_limbs*BITS_PER_MP_LIMB + g_zero_bits). */
+ gsize = vsize + g_zero_limbs;
+ if (g_zero_bits != 0)
+ {
+ mp_limb_t cy_limb;
+ gsize += (vp[vsize - 1] >> (BITS_PER_MP_LIMB - g_zero_bits)) != 0;
+ if (g->_mp_alloc < gsize)
+ _mpz_realloc (g, gsize);
+ MPN_ZERO (g->_mp_d, g_zero_limbs);
+
+ tp = g->_mp_d + g_zero_limbs;
+ cy_limb = mpn_lshift (tp, vp, vsize, g_zero_bits);
+ if (cy_limb != 0)
+ tp[vsize] = cy_limb;
+ }
+ else
+ {
+ if (g->_mp_alloc < gsize)
+ _mpz_realloc (g, gsize);
+ MPN_ZERO (g->_mp_d, g_zero_limbs);
+ MPN_COPY (g->_mp_d + g_zero_limbs, vp, vsize);
+ }
+
+ g->_mp_size = gsize;
+ TMP_FREE (marker);
+}
diff --git a/mpz/gcd_ui.c b/mpz/gcd_ui.c
new file mode 100644
index 000000000..388ab05cc
--- /dev/null
+++ b/mpz/gcd_ui.c
@@ -0,0 +1,64 @@
+/* mpz_gcd_ui -- Calculate the greatest common divisior of two integers.
+
+Copyright (C) 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+unsigned long int
+#if __STDC__
+mpz_gcd_ui (mpz_ptr w, mpz_srcptr u, unsigned long int v)
+#else
+mpz_gcd_ui (w, u, v)
+ mpz_ptr w;
+ mpz_srcptr u;
+ unsigned long int v;
+#endif
+{
+ mp_size_t size;
+ mp_limb_t res;
+
+ size = ABS (u->_mp_size);
+
+ if (size == 0)
+ res = v;
+ else if (v == 0)
+ {
+ if (w != NULL && u != w)
+ {
+ if (w->_mp_alloc < size)
+ _mpz_realloc (w, size);
+
+ MPN_COPY (w->_mp_d, u->_mp_d, size);
+ }
+ w->_mp_size = size;
+ /* We can't return any useful result for gcd(big,0). */
+ return size > 1 ? 0 : w->_mp_d[0];
+ }
+ else
+ res = mpn_gcd_1 (u->_mp_d, size, v);
+
+ if (w != NULL)
+ {
+ w->_mp_d[0] = res;
+ w->_mp_size = 1;
+ }
+ return res;
+}
diff --git a/mpz/gcdext.c b/mpz/gcdext.c
new file mode 100644
index 000000000..adf66b04a
--- /dev/null
+++ b/mpz/gcdext.c
@@ -0,0 +1,88 @@
+/* mpz_gcdext(g, s, t, a, b) -- Set G to gcd(a, b), and S and T such that
+ g = as + bt.
+
+Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+/* Botch: SLOW! */
+
+void
+#if __STDC__
+mpz_gcdext (mpz_ptr g, mpz_ptr s, mpz_ptr t, mpz_srcptr a, mpz_srcptr b)
+#else
+mpz_gcdext (g, s, t, a, b)
+ mpz_ptr g;
+ mpz_ptr s;
+ mpz_ptr t;
+ mpz_srcptr a;
+ mpz_srcptr b;
+#endif
+{
+ mpz_t s0, s1, q, r, x, d0, d1;
+
+ mpz_init_set_ui (s0, 1L);
+ mpz_init_set_ui (s1, 0L);
+ mpz_init (q);
+ mpz_init (r);
+ mpz_init (x);
+ mpz_init_set (d0, a);
+ mpz_init_set (d1, b);
+
+ while (d1->_mp_size != 0)
+ {
+ mpz_tdiv_qr (q, r, d0, d1);
+ mpz_set (d0, d1);
+ mpz_set (d1, r);
+
+ mpz_mul (x, s1, q);
+ mpz_sub (x, s0, x);
+ mpz_set (s0, s1);
+ mpz_set (s1, x);
+ }
+
+ if (t != NULL)
+ {
+ mpz_mul (x, s0, a);
+ mpz_sub (x, d0, x);
+ if (b->_mp_size == 0)
+ t->_mp_size = 0;
+ else
+ mpz_tdiv_q (t, x, b);
+ }
+ mpz_set (s, s0);
+ mpz_set (g, d0);
+ if (g->_mp_size < 0)
+ {
+ g->_mp_size = -g->_mp_size;
+ s->_mp_size = -s->_mp_size;
+ if (t != NULL)
+ t->_mp_size = -t->_mp_size;
+ }
+
+ mpz_clear (s0);
+ mpz_clear (s1);
+ mpz_clear (q);
+ mpz_clear (r);
+ mpz_clear (x);
+ mpz_clear (d0);
+ mpz_clear (d1);
+}
diff --git a/mpz/get_si.c b/mpz/get_si.c
new file mode 100644
index 000000000..45e0e5aec
--- /dev/null
+++ b/mpz/get_si.c
@@ -0,0 +1,43 @@
+/* mpz_get_si(integer) -- Return the least significant digit from INTEGER.
+
+Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+signed long int
+#if __STDC__
+mpz_get_si (mpz_srcptr op)
+#else
+mpz_get_si (op)
+ mpz_srcptr op;
+#endif
+{
+ mp_size_t size = op->_mp_size;
+ mp_limb_t low_limb = op->_mp_d[0];
+
+ if (size > 0)
+ return low_limb % ((mp_limb_t) 1 << (BITS_PER_MP_LIMB - 1));
+ else if (size < 0)
+ /* This convoluted expression is necessary to properly handle 0x80000000 */
+ return ~((low_limb - 1) % ((mp_limb_t) 1 << (BITS_PER_MP_LIMB - 1)));
+ else
+ return 0;
+}
diff --git a/mpz/get_str.c b/mpz/get_str.c
new file mode 100644
index 000000000..8ccf3efcd
--- /dev/null
+++ b/mpz/get_str.c
@@ -0,0 +1,118 @@
+/* mpz_get_str (string, base, mp_src) -- Convert the multiple precision
+ number MP_SRC to a string STRING of base BASE. If STRING is NULL
+ allocate space for the result. In any case, return a pointer to the
+ result. If STRING is not NULL, the caller must ensure enough space is
+ available to store the result.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+char *
+#if __STDC__
+mpz_get_str (char *res_str, int base, mpz_srcptr x)
+#else
+mpz_get_str (res_str, base, x)
+ char *res_str;
+ int base;
+ mpz_srcptr x;
+#endif
+{
+ mp_ptr xp;
+ mp_size_t x_size = x->_mp_size;
+ unsigned char *str;
+ char *return_str;
+ size_t str_size;
+ char *num_to_text;
+ int i;
+ TMP_DECL (marker);
+
+ TMP_MARK (marker);
+ if (base >= 0)
+ {
+ if (base == 0)
+ base = 10;
+ num_to_text = "0123456789abcdefghijklmnopqrstuvwxyz";
+ }
+ else
+ {
+ base = -base;
+ num_to_text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ }
+
+ /* We allways allocate space for the string. If the caller passed a
+ NULL pointer for RES_STR, we allocate permanent space and return
+ a pointer to that to the caller. */
+ str_size = ((size_t) (ABS (x_size) * BITS_PER_MP_LIMB
+ * __mp_bases[base].chars_per_bit_exactly)) + 3;
+ if (res_str == 0)
+ {
+ /* We didn't get a string from the user. Allocate one (and return
+ a pointer to it). */
+ res_str = (char *) (*_mp_allocate_func) (str_size);
+ /* Make str, the variable used for raw result from mpn_get_str,
+ point to the same string, but just after a possible minus sign. */
+ str = (unsigned char *) res_str + 1;
+ }
+ else
+ {
+ /* Use TMP_ALLOC to get temporary space, since we need a few extra bytes
+ that we can't expect to caller to supply us with. */
+ str = (unsigned char *) TMP_ALLOC (str_size);
+ }
+
+ return_str = res_str;
+
+ if (x_size == 0)
+ {
+ res_str[0] = '0';
+ res_str[1] = 0;
+ TMP_FREE (marker);
+ return res_str;
+ }
+ if (x_size < 0)
+ {
+ *res_str++ = '-';
+ x_size = -x_size;
+ }
+
+ /* Move the number to convert into temporary space, since mpn_get_str
+ clobbers its argument + needs one extra high limb.... */
+ xp = (mp_ptr) TMP_ALLOC ((x_size + 1) * BYTES_PER_MP_LIMB);
+ MPN_COPY (xp, x->_mp_d, x_size);
+
+ str_size = mpn_get_str (str, base, xp, x_size);
+
+ /* mpn_get_str might make some leading zeros. Skip them. */
+ while (*str == 0)
+ {
+ str_size--;
+ str++;
+ }
+
+ /* Translate result to printable chars and move result to RES_STR. */
+ for (i = 0; i < str_size; i++)
+ res_str[i] = num_to_text[str[i]];
+ res_str[str_size] = 0;
+
+ TMP_FREE (marker);
+ return return_str;
+}
diff --git a/mpz/get_ui.c b/mpz/get_ui.c
new file mode 100644
index 000000000..4bfb5e14d
--- /dev/null
+++ b/mpz/get_ui.c
@@ -0,0 +1,37 @@
+/* mpz_get_ui(integer) -- Return the least significant digit from INTEGER.
+
+Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+unsigned long int
+#if __STDC__
+mpz_get_ui (mpz_srcptr integer)
+#else
+mpz_get_ui (integer)
+ mpz_srcptr integer;
+#endif
+{
+ if (integer->_mp_size == 0)
+ return 0;
+ else
+ return integer->_mp_d[0];
+}
diff --git a/mpz/getlimbn.c b/mpz/getlimbn.c
new file mode 100644
index 000000000..c7a234b5a
--- /dev/null
+++ b/mpz/getlimbn.c
@@ -0,0 +1,38 @@
+/* mpz_getlimbn(integer,n) -- Return the N:th limb from INTEGER.
+
+Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+mp_limb_t
+#if __STDC__
+mpz_getlimbn (mpz_srcptr integer, mp_size_t n)
+#else
+mpz_getlimbn (integer, n)
+ mpz_srcptr integer;
+ mp_size_t n;
+#endif
+{
+ if (integer->_mp_size <= n || n < 0)
+ return 0;
+ else
+ return integer->_mp_d[n];
+}
diff --git a/mpz/hamdist.c b/mpz/hamdist.c
new file mode 100644
index 000000000..58c927316
--- /dev/null
+++ b/mpz/hamdist.c
@@ -0,0 +1,62 @@
+/* mpz_hamdist(mpz_ptr op1, mpz_ptr op2) -- Compute the hamming distance
+ between OP1 and OP2. If one of the operands is negative, return ~0. (We
+ could make the function well-defined when both operands are negative, but
+ that would probably not be worth the trouble.
+
+Copyright (C) 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+unsigned long int
+#if __STDC__
+mpz_hamdist (mpz_srcptr u, mpz_srcptr v)
+#else
+mpz_hamdist (u, v)
+ mpz_srcptr u;
+ mpz_srcptr v;
+#endif
+{
+ mp_srcptr up, vp;
+ mp_size_t usize, vsize, size;
+ unsigned long int count;
+
+ usize = u->_mp_size;
+ vsize = v->_mp_size;
+
+ if ((usize | vsize) < 0)
+ return ~ (unsigned long int) 0;
+
+ up = u->_mp_d;
+ vp = v->_mp_d;
+
+ if (usize > vsize)
+ {
+ count = mpn_popcount (up + vsize, usize - vsize);
+ size = vsize;
+ }
+ else
+ {
+ count = mpn_popcount (vp + usize, vsize - usize);
+ size = usize;
+ }
+
+ return count + mpn_hamdist (up, vp, size);
+}
diff --git a/mpz/init.c b/mpz/init.c
new file mode 100644
index 000000000..f8d8e207e
--- /dev/null
+++ b/mpz/init.c
@@ -0,0 +1,36 @@
+/* mpz_init() -- Make a new multiple precision number with value 0.
+
+Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_init (mpz_ptr x)
+#else
+mpz_init (x)
+ mpz_ptr x;
+#endif
+{
+ x->_mp_alloc = 1;
+ x->_mp_d = (mp_ptr) (*_mp_allocate_func) (BYTES_PER_MP_LIMB);
+ x->_mp_size = 0;
+}
diff --git a/mpz/inp_raw.c b/mpz/inp_raw.c
new file mode 100644
index 000000000..e1cec1d74
--- /dev/null
+++ b/mpz/inp_raw.c
@@ -0,0 +1,101 @@
+/* mpz_inp_raw -- Input a mpz_t in raw, but endianess, and wordsize
+ independent format (as output by mpz_out_raw).
+
+Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+size_t
+#if __STDC__
+mpz_inp_raw (mpz_ptr x, FILE *stream)
+#else
+mpz_inp_raw (x, stream)
+ mpz_ptr x;
+ FILE *stream;
+#endif
+{
+ int i;
+ mp_size_t s;
+ mp_size_t xsize;
+ mp_ptr xp;
+ unsigned int c;
+ mp_limb_t x_limb;
+ mp_size_t in_bytesize;
+ int neg_flag;
+
+ if (stream == 0)
+ stream = stdin;
+
+ /* Read 4-byte size */
+ in_bytesize = 0;
+ for (i = 4 - 1; i >= 0; i--)
+ {
+ c = fgetc (stream);
+ in_bytesize = (in_bytesize << BITS_PER_CHAR) | c;
+ }
+
+ /* Size is stored as a 32 bit word; sign extend in_bytesize for non-32 bit
+ machines. */
+ if (sizeof (mp_size_t) > 4)
+ in_bytesize |= (-(in_bytesize < 0)) << 31;
+
+ neg_flag = in_bytesize < 0;
+ in_bytesize = ABS (in_bytesize);
+ xsize = (in_bytesize + BYTES_PER_MP_LIMB - 1) / BYTES_PER_MP_LIMB;
+
+ if (xsize == 0)
+ {
+ x->_mp_size = 0;
+ return 4; /* we've read 4 bytes */
+ }
+
+ if (x->_mp_alloc < xsize)
+ _mpz_realloc (x, xsize);
+ xp = x->_mp_d;
+
+ x_limb = 0;
+ for (i = (in_bytesize - 1) % BYTES_PER_MP_LIMB; i >= 0; i--)
+ {
+ c = fgetc (stream);
+ x_limb = (x_limb << BITS_PER_CHAR) | c;
+ }
+ xp[xsize - 1] = x_limb;
+
+ for (s = xsize - 2; s >= 0; s--)
+ {
+ x_limb = 0;
+ for (i = BYTES_PER_MP_LIMB - 1; i >= 0; i--)
+ {
+ c = fgetc (stream);
+ x_limb = (x_limb << BITS_PER_CHAR) | c;
+ }
+ xp[s] = x_limb;
+ }
+
+ if (c == EOF)
+ return 0; /* error */
+
+ MPN_NORMALIZE (xp, xsize);
+ x->_mp_size = neg_flag ? -xsize : xsize;
+ return in_bytesize + 4;
+}
diff --git a/mpz/inp_str.c b/mpz/inp_str.c
new file mode 100644
index 000000000..715906237
--- /dev/null
+++ b/mpz/inp_str.c
@@ -0,0 +1,138 @@
+/* mpz_inp_str(dest_integer, stream, base) -- Input a number in base
+ BASE from stdio stream STREAM and store the result in DEST_INTEGER.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <ctype.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+
+static int
+digit_value_in_base (c, base)
+ int c;
+ int base;
+{
+ int digit;
+
+ if (isdigit (c))
+ digit = c - '0';
+ else if (islower (c))
+ digit = c - 'a' + 10;
+ else if (isupper (c))
+ digit = c - 'A' + 10;
+ else
+ return -1;
+
+ if (digit < base)
+ return digit;
+ return -1;
+}
+
+size_t
+#if __STDC__
+mpz_inp_str (mpz_ptr dest, FILE *stream, int base)
+#else
+mpz_inp_str (dest, stream, base)
+ mpz_ptr dest;
+ FILE *stream;
+ int base;
+#endif
+{
+ char *str;
+ size_t alloc_size, str_size;
+ int c;
+ int negative;
+ mp_size_t dest_size;
+ size_t nread;
+
+ if (stream == 0)
+ stream = stdin;
+
+ alloc_size = 100;
+ str = (char *) (*_mp_allocate_func) (alloc_size);
+ str_size = 0;
+ nread = 0;
+
+ /* Skip whitespace. */
+ do
+ {
+ c = getc (stream);
+ nread++;
+ }
+ while (isspace (c));
+
+ negative = 0;
+ if (c == '-')
+ {
+ negative = 1;
+ c = getc (stream);
+ }
+
+ if (digit_value_in_base (c, base == 0 ? 10 : base) < 0)
+ return 0; /* error if no digits */
+
+ /* If BASE is 0, try to find out the base by looking at the initial
+ characters. */
+ if (base == 0)
+ {
+ base = 10;
+ if (c == '0')
+ {
+ base = 8;
+ c = getc (stream);
+ nread++;
+ if (c == 'x' || c == 'X')
+ {
+ base = 16;
+ c = getc (stream);
+ nread++;
+ }
+ }
+ }
+
+ for (;;)
+ {
+ int dig;
+ if (str_size >= alloc_size)
+ {
+ size_t old_alloc_size = alloc_size;
+ alloc_size = alloc_size * 3 / 2;
+ str = (char *) (*_mp_reallocate_func) (str, old_alloc_size, alloc_size);
+ }
+ dig = digit_value_in_base (c, base);
+ if (dig < 0)
+ break;
+ str[str_size++] = dig;
+ c = getc (stream);
+ }
+
+ ungetc (c, stream);
+
+ dest_size = str_size / __mp_bases[base].chars_per_limb + 1;
+ if (dest->_mp_alloc < dest_size)
+ _mpz_realloc (dest, dest_size);
+
+ dest_size = mpn_set_str (dest->_mp_d, (unsigned char *) str, str_size, base);
+ dest->_mp_size = negative ? -dest_size : dest_size;
+
+ (*_mp_free_func) (str, alloc_size);
+ return str_size + nread;
+}
diff --git a/mpz/invert.c b/mpz/invert.c
new file mode 100644
index 000000000..ff1d6d937
--- /dev/null
+++ b/mpz/invert.c
@@ -0,0 +1,43 @@
+/* mpz_invert (inv, x, n). Find multiplicative inverse of X in Z(N).
+ If X has an inverse, return non-zero and store inverse in INVERSE,
+ otherwise, return 0 and put garbage in X.
+
+Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+
+int
+#if __STDC__
+mpz_invert (mpz_ptr inverse, mpz_srcptr x, mpz_srcptr n)
+#else
+mpz_invert (inverse, x, n)
+ mpz_ptr inverse;
+ mpz_srcptr x, n;
+#endif
+{
+ mpz_t gcd;
+ int rv;
+
+ mpz_init (gcd);
+ mpz_gcdext (gcd, inverse, (mpz_ptr) 0, x, n);
+ rv = gcd->_mp_size == 1 && (gcd->_mp_d)[0] == 1;
+ mpz_clear (gcd);
+ return rv;
+}
diff --git a/mpz/ior.c b/mpz/ior.c
new file mode 100644
index 000000000..77facfd3d
--- /dev/null
+++ b/mpz/ior.c
@@ -0,0 +1,243 @@
+/* mpz_ior -- Logical inclusive or.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_ior (mpz_ptr res, mpz_srcptr op1, mpz_srcptr op2)
+#else
+mpz_ior (res, op1, op2)
+ mpz_ptr res;
+ mpz_srcptr op1;
+ mpz_srcptr op2;
+#endif
+{
+ mp_srcptr op1_ptr, op2_ptr;
+ mp_size_t op1_size, op2_size;
+ mp_ptr res_ptr;
+ mp_size_t res_size;
+ mp_size_t i;
+ TMP_DECL (marker);
+
+ TMP_MARK (marker);
+ op1_size = op1->_mp_size;
+ op2_size = op2->_mp_size;
+
+ op1_ptr = op1->_mp_d;
+ op2_ptr = op2->_mp_d;
+ res_ptr = res->_mp_d;
+
+ if (op1_size >= 0)
+ {
+ if (op2_size >= 0)
+ {
+ if (op1_size >= op2_size)
+ {
+ if (res->_mp_alloc < op1_size)
+ {
+ _mpz_realloc (res, op1_size);
+ op1_ptr = op1->_mp_d;
+ op2_ptr = op2->_mp_d;
+ res_ptr = res->_mp_d;
+ }
+
+ if (res_ptr != op1_ptr)
+ MPN_COPY (res_ptr + op2_size, op1_ptr + op2_size,
+ op1_size - op2_size);
+ for (i = op2_size - 1; i >= 0; i--)
+ res_ptr[i] = op1_ptr[i] | op2_ptr[i];
+ res_size = op1_size;
+ }
+ else
+ {
+ if (res->_mp_alloc < op2_size)
+ {
+ _mpz_realloc (res, op2_size);
+ op1_ptr = op1->_mp_d;
+ op2_ptr = op2->_mp_d;
+ res_ptr = res->_mp_d;
+ }
+
+ if (res_ptr != op2_ptr)
+ MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size,
+ op2_size - op1_size);
+ for (i = op1_size - 1; i >= 0; i--)
+ res_ptr[i] = op1_ptr[i] | op2_ptr[i];
+ res_size = op2_size;
+ }
+
+ res->_mp_size = res_size;
+ return;
+ }
+ else /* op2_size < 0 */
+ {
+ /* Fall through to the code at the end of the function. */
+ }
+ }
+ else
+ {
+ if (op2_size < 0)
+ {
+ mp_ptr opx;
+ mp_limb_t cy;
+
+ /* Both operands are negative, so will be the result.
+ -((-OP1) | (-OP2)) = -(~(OP1 - 1) | ~(OP2 - 1)) =
+ = ~(~(OP1 - 1) | ~(OP2 - 1)) + 1 =
+ = ((OP1 - 1) & (OP2 - 1)) + 1 */
+
+ op1_size = -op1_size;
+ op2_size = -op2_size;
+
+ res_size = MIN (op1_size, op2_size);
+
+ /* Possible optimization: Decrease mpn_sub precision,
+ as we won't use the entire res of both. */
+ opx = (mp_ptr) TMP_ALLOC (res_size * BYTES_PER_MP_LIMB);
+ mpn_sub_1 (opx, op1_ptr, res_size, (mp_limb_t) 1);
+ op1_ptr = opx;
+
+ opx = (mp_ptr) TMP_ALLOC (res_size * BYTES_PER_MP_LIMB);
+ mpn_sub_1 (opx, op2_ptr, res_size, (mp_limb_t) 1);
+ op2_ptr = opx;
+
+ if (res->_mp_alloc < res_size)
+ {
+ _mpz_realloc (res, res_size);
+ res_ptr = res->_mp_d;
+ /* Don't re-read OP1_PTR and OP2_PTR. They point to
+ temporary space--never to the space RES->_mp_D used
+ to point to before reallocation. */
+ }
+
+ /* First loop finds the size of the result. */
+ for (i = res_size - 1; i >= 0; i--)
+ if ((op1_ptr[i] & op2_ptr[i]) != 0)
+ break;
+ res_size = i + 1;
+
+ if (res_size != 0)
+ {
+ /* Second loop computes the real result. */
+ for (i = res_size - 1; i >= 0; i--)
+ res_ptr[i] = op1_ptr[i] & op2_ptr[i];
+
+ cy = mpn_add_1 (res_ptr, res_ptr, res_size, (mp_limb_t) 1);
+ if (cy)
+ {
+ res_ptr[res_size] = cy;
+ res_size++;
+ }
+ }
+ else
+ {
+ res_ptr[0] = 1;
+ res_size = 1;
+ }
+
+ res->_mp_size = -res_size;
+ TMP_FREE (marker);
+ return;
+ }
+ else
+ {
+ /* We should compute -OP1 | OP2. Swap OP1 and OP2 and fall
+ through to the code that handles OP1 | -OP2. */
+ {mpz_srcptr t = op1; op1 = op2; op2 = t;}
+ {mp_srcptr t = op1_ptr; op1_ptr = op2_ptr; op2_ptr = t;}
+ {mp_size_t t = op1_size; op1_size = op2_size; op2_size = t;}
+ }
+ }
+
+ {
+ mp_ptr opx;
+ mp_limb_t cy;
+ mp_size_t res_alloc;
+ mp_size_t count;
+
+ /* Operand 2 negative, so will be the result.
+ -(OP1 | (-OP2)) = -(OP1 | ~(OP2 - 1)) =
+ = ~(OP1 | ~(OP2 - 1)) + 1 =
+ = (~OP1 & (OP2 - 1)) + 1 */
+
+ op2_size = -op2_size;
+
+ res_alloc = op2_size;
+
+ opx = (mp_ptr) TMP_ALLOC (op2_size * BYTES_PER_MP_LIMB);
+ mpn_sub_1 (opx, op2_ptr, op2_size, (mp_limb_t) 1);
+ op2_ptr = opx;
+
+ if (res->_mp_alloc < res_alloc)
+ {
+ _mpz_realloc (res, res_alloc);
+ op1_ptr = op1->_mp_d;
+ res_ptr = res->_mp_d;
+ /* Don't re-read OP2_PTR. It points to temporary space--never
+ to the space RES->_mp_D used to point to before reallocation. */
+ }
+
+ if (op1_size >= op2_size)
+ {
+ /* We can just ignore the part of OP1 that stretches above OP2,
+ because the result limbs are zero there. */
+
+ /* First loop finds the size of the result. */
+ for (i = op2_size - 1; i >= 0; i--)
+ if ((~op1_ptr[i] & op2_ptr[i]) != 0)
+ break;
+ res_size = i + 1;
+ count = res_size;
+ }
+ else
+ {
+ res_size = op2_size;
+
+ /* Copy the part of OP2 that stretches above OP1, to RES. */
+ MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size, op2_size - op1_size);
+ count = op1_size;
+ }
+
+ if (res_size != 0)
+ {
+ /* Second loop computes the real result. */
+ for (i = count - 1; i >= 0; i--)
+ res_ptr[i] = ~op1_ptr[i] & op2_ptr[i];
+
+ cy = mpn_add_1 (res_ptr, res_ptr, res_size, (mp_limb_t) 1);
+ if (cy)
+ {
+ res_ptr[res_size] = cy;
+ res_size++;
+ }
+ }
+ else
+ {
+ res_ptr[0] = 1;
+ res_size = 1;
+ }
+
+ res->_mp_size = -res_size;
+ }
+ TMP_FREE (marker);
+}
diff --git a/mpz/iset.c b/mpz/iset.c
new file mode 100644
index 000000000..c8a17dc67
--- /dev/null
+++ b/mpz/iset.c
@@ -0,0 +1,49 @@
+/* mpz_init_set (src_integer) -- Make a new multiple precision number with
+ a value copied from SRC_INTEGER.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_init_set (mpz_ptr w, mpz_srcptr u)
+#else
+mpz_init_set (w, u)
+ mpz_ptr w;
+ mpz_srcptr u;
+#endif
+{
+ mp_ptr wp, up;
+ mp_size_t usize, size;
+
+ usize = u->_mp_size;
+ size = ABS (usize);
+
+ w->_mp_alloc = MAX (size, 1);
+ w->_mp_d = (mp_ptr) (*_mp_allocate_func) (w->_mp_alloc * BYTES_PER_MP_LIMB);
+
+ wp = w->_mp_d;
+ up = u->_mp_d;
+
+ MPN_COPY (wp, up, size);
+ w->_mp_size = usize;
+}
diff --git a/mpz/iset_d.c b/mpz/iset_d.c
new file mode 100644
index 000000000..d81a0654f
--- /dev/null
+++ b/mpz/iset_d.c
@@ -0,0 +1,40 @@
+/* mpz_init_set_d(integer, val) -- Initialize and assign INTEGER with a double
+ value VAL.
+
+Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include <math.h>
+
+void
+#if __STDC__
+mpz_init_set_d (mpz_ptr dest, double val)
+#else
+mpz_init_set_d (dest, val)
+ mpz_ptr dest;
+ double val;
+#endif
+{
+ dest->_mp_alloc = 1;
+ dest->_mp_d = (mp_ptr) (*_mp_allocate_func) (BYTES_PER_MP_LIMB);
+ dest->_mp_size = 0;
+ mpz_set_d (dest, val);
+}
diff --git a/mpz/iset_si.c b/mpz/iset_si.c
new file mode 100644
index 000000000..af51f0578
--- /dev/null
+++ b/mpz/iset_si.c
@@ -0,0 +1,49 @@
+/* mpz_init_set_si(val) -- Make a new multiple precision number with
+ value val.
+
+Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_init_set_si (mpz_ptr x, signed long int val)
+#else
+mpz_init_set_si (x, val)
+ mpz_ptr x;
+ signed long int val;
+#endif
+{
+ x->_mp_alloc = 1;
+ x->_mp_d = (mp_ptr) (*_mp_allocate_func) (BYTES_PER_MP_LIMB);
+ if (val > 0)
+ {
+ x->_mp_d[0] = val;
+ x->_mp_size = 1;
+ }
+ else if (val < 0)
+ {
+ x->_mp_d[0] = -val;
+ x->_mp_size = -1;
+ }
+ else
+ x->_mp_size = 0;
+}
diff --git a/mpz/iset_str.c b/mpz/iset_str.c
new file mode 100644
index 000000000..e04ad5da2
--- /dev/null
+++ b/mpz/iset_str.c
@@ -0,0 +1,44 @@
+/* mpz_init_set_str(string, base) -- Convert the \0-terminated string
+ STRING in base BASE to a multiple precision integer. Return a MP_INT
+ structure representing the integer. Allow white space in the
+ string. If BASE == 0 determine the base in the C standard way,
+ i.e. 0xhh...h means base 16, 0oo...o means base 8, otherwise
+ assume base 10.
+
+Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+int
+#if __STDC__
+mpz_init_set_str (mpz_ptr x, const char *str, int base)
+#else
+mpz_init_set_str (x, str, base)
+ mpz_ptr x;
+ const char *str;
+ int base;
+#endif
+{
+ x->_mp_alloc = 1;
+ x->_mp_d = (mp_ptr) (*_mp_allocate_func) (BYTES_PER_MP_LIMB);
+
+ return mpz_set_str (x, str, base);
+}
diff --git a/mpz/iset_ui.c b/mpz/iset_ui.c
new file mode 100644
index 000000000..dc39f59ff
--- /dev/null
+++ b/mpz/iset_ui.c
@@ -0,0 +1,39 @@
+/* mpz_init_set_ui(val) -- Make a new multiple precision number with
+ value val.
+
+Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_init_set_ui (mpz_ptr x, unsigned long int val)
+#else
+mpz_init_set_ui (x, val)
+ mpz_ptr x;
+ unsigned long int val;
+#endif
+{
+ x->_mp_alloc = 1;
+ x->_mp_d = (mp_ptr) (*_mp_allocate_func) (BYTES_PER_MP_LIMB);
+ x->_mp_d[0] = val;
+ x->_mp_size = val != 0;
+}
diff --git a/mpz/jacobi.c b/mpz/jacobi.c
new file mode 100644
index 000000000..409f622fc
--- /dev/null
+++ b/mpz/jacobi.c
@@ -0,0 +1,53 @@
+/* mpz_jacobi (op1, op2).
+ Contributed by Bennet Yee (bsy) at Carnegie-Mellon University
+
+Copyright (C) 1991, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+
+/* Precondition: both p and q are positive */
+
+int
+#if __STDC__
+mpz_jacobi (mpz_srcptr pi, mpz_srcptr qi)
+#else
+mpz_jacobi (pi, qi)
+ mpz_srcptr pi, qi;
+#endif
+{
+#if GCDCHECK
+ int retval;
+ mpz_t gcdval;
+
+ mpz_init (gcdval);
+ mpz_gcd (gcdval, pi, qi);
+ if (!mpz_cmp_ui (gcdval, 1L))
+ {
+ /* J(ab,cb) = J(ab,c)J(ab,b) = J(ab,c)J(0,b) = J(ab,c)*0 */
+ retval = 0;
+ }
+ else
+ retval = mpz_legendre (pi, qi);
+ mpz_clear (gcdval);
+ return retval;
+#else
+ return mpz_legendre (pi, qi);
+#endif
+}
diff --git a/mpz/legendre.c b/mpz/legendre.c
new file mode 100644
index 000000000..4de16a631
--- /dev/null
+++ b/mpz/legendre.c
@@ -0,0 +1,184 @@
+/* mpz_legendre (op1, op2).
+ Contributed by Bennet Yee (bsy) at Carnegie-Mellon University
+
+Copyright (C) 1992, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+
+#if defined (DEBUG)
+#include <stdio.h>
+#endif
+
+/* Precondition: both p and q are positive */
+
+int
+#if __STDC__
+mpz_legendre (mpz_srcptr pi, mpz_srcptr qi)
+#else
+mpz_legendre (pi, qi)
+mpz_srcptr pi, qi;
+#endif
+{
+ mpz_t p, q, qdiv2;
+#ifdef Q_MINUS_1
+ mpz_t q_minus_1;
+#endif
+ mpz_ptr mtmp;
+ register mpz_ptr pptr, qptr;
+ register int retval = 1;
+ register unsigned long int s;
+
+ pptr = p;
+ mpz_init_set (pptr, pi);
+ qptr = q;
+ mpz_init_set (qptr, qi);
+
+#ifdef Q_MINUS_1
+ mpz_init (q_minus_1);
+#endif
+ mpz_init (qdiv2);
+
+tail_recurse2:
+#ifdef DEBUG
+ printf ("tail_recurse2: p=");
+ mpz_out_str (stdout, 10, pptr);
+ printf ("\nq=");
+ mpz_out_str (stdout, 10, qptr);
+ putchar ('\n');
+#endif
+ s = mpz_scan1 (qptr, 0);
+ if (s) mpz_tdiv_q_2exp (qptr, qptr, s); /* J(a,2) = 1 */
+#ifdef DEBUG
+ printf ("2 factor decomposition: p=");
+ mpz_out_str (stdout, 10, pptr);
+ printf ("\nq=");
+ mpz_out_str (stdout, 10, qptr);
+ putchar ('\n');
+#endif
+ /* postcondition q odd */
+ if (!mpz_cmp_ui (qptr, 1L)) /* J(a,1) = 1 */
+ goto done;
+ mpz_mod (pptr, pptr, qptr); /* J(a,q) = J(b,q) when a == b mod q */
+#ifdef DEBUG
+ printf ("mod out by q: p=");
+ mpz_out_str (stdout, 10, pptr);
+ printf ("\nq=");
+ mpz_out_str (stdout, 10, qptr);
+ putchar ('\n');
+#endif
+ /* quick calculation to get approximate size first */
+ /* precondition: p < q */
+ if ((mpz_sizeinbase (pptr, 2) + 1 >= mpz_sizeinbase (qptr,2))
+ && (mpz_tdiv_q_2exp (qdiv2, qptr, 1L), mpz_cmp (pptr, qdiv2) > 0))
+ {
+ /* p > q/2 */
+ mpz_sub (pptr, qptr, pptr);
+ /* J(-1,q) = (-1)^((q-1)/2), q odd */
+ if (mpz_get_ui (qptr) & 2)
+ retval = -retval;
+ }
+ /* p < q/2 */
+#ifdef Q_MINUS_1
+ mpz_sub_ui (q_minus_q, qptr, 1L);
+#endif
+tail_recurse: /* we use tail_recurse only if q has not changed */
+#ifdef DEBUG
+ printf ("tail_recurse1: p=");
+ mpz_out_str (stdout, 10, pptr);
+ printf ("\nq=");
+ mpz_out_str (stdout, 10, qptr);
+ putchar ('\n');
+#endif
+ /*
+ * J(0,q) = 0
+ * this occurs only if gcd(p,q) != 1 which is never true for
+ * Legendre function.
+ */
+ if (!mpz_cmp_ui (pptr, 0L))
+ {
+ retval = 0;
+ goto done;
+ }
+
+ if (!mpz_cmp_ui (pptr, 1L))
+ {
+ /* J(1,q) = 1 */
+ /* retval *= 1; */
+ goto done;
+ }
+#ifdef Q_MINUS_1
+ if (!mpz_cmp (pptr, q_minus_1))
+ {
+ /* J(-1,q) = (-1)^((q-1)/2) */
+ if (mpz_get_ui (qptr) & 2)
+ retval = -retval;
+ /* else retval *= 1; */
+ goto done;
+ }
+#endif
+ /*
+ * we do not handle J(xy,q) except for x==2
+ * since we do not want to factor
+ */
+ if ((s = mpz_scan1 (pptr, 0)) != 0)
+ {
+ /*
+ * J(2,q) = (-1)^((q^2-1)/8)
+ *
+ * Note that q odd guarantees that q^2-1 is divisible by 8:
+ * Let a: q=2a+1. q^2 = 4a^2+4a+1, (q^2-1)/8 = a(a+1)/2, qed
+ *
+ * Now, note that this means that the low two bits of _a_
+ * (or the low bits of q shifted over by 1 determines
+ * the factor).
+ */
+ mpz_tdiv_q_2exp (pptr, pptr, s);
+
+ /* even powers of 2 gives J(2,q)^{2n} = 1 */
+ if (s & 1)
+ {
+ s = mpz_get_ui (qptr) >> 1;
+ s = s * (s + 1);
+ if (s & 2)
+ retval = -retval;
+ }
+ goto tail_recurse;
+ }
+ /*
+ * we know p is odd since we have cast out 2s
+ * precondition that q is odd guarantees both odd.
+ *
+ * quadratic reciprocity
+ * J(p,q) = (-1)^((p-1)(q-1)/4) * J(q,p)
+ */
+ if ((s = mpz_scan1 (pptr, 1)) <= 2 && (s + mpz_scan1 (qptr, 1)) <= 2)
+ retval = -retval;
+
+ mtmp = pptr; pptr = qptr; qptr = mtmp;
+ goto tail_recurse2;
+done:
+ mpz_clear (p);
+ mpz_clear (q);
+ mpz_clear (qdiv2);
+#ifdef Q_MINUS_1
+ mpz_clear (q_minus_1);
+#endif
+ return retval;
+}
diff --git a/mpz/mod.c b/mpz/mod.c
new file mode 100644
index 000000000..b2b8b39bb
--- /dev/null
+++ b/mpz/mod.c
@@ -0,0 +1,63 @@
+/* mpz_mod -- The mathematical mod function.
+
+Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_mod (mpz_ptr rem, mpz_srcptr dividend, mpz_srcptr divisor)
+#else
+mpz_mod (rem, dividend, divisor)
+ mpz_ptr rem;
+ mpz_srcptr dividend;
+ mpz_srcptr divisor;
+#endif
+{
+ mp_size_t divisor_size = divisor->_mp_size;
+ mpz_t temp_divisor; /* N.B.: lives until function returns! */
+ TMP_DECL (marker);
+
+ TMP_MARK (marker);
+
+ /* We need the original value of the divisor after the remainder has been
+ preliminary calculated. We have to copy it to temporary space if it's
+ the same variable as REM. */
+ if (rem == divisor)
+ {
+ MPZ_TMP_INIT (temp_divisor, ABS (divisor_size));
+ mpz_set (temp_divisor, divisor);
+ divisor = temp_divisor;
+ }
+
+ mpz_tdiv_r (rem, dividend, divisor);
+
+ if (rem->_mp_size != 0)
+ {
+ if (dividend->_mp_size < 0)
+ if (divisor->_mp_size < 0)
+ mpz_sub (rem, rem, divisor);
+ else
+ mpz_add (rem, rem, divisor);
+ }
+
+ TMP_FREE (marker);
+}
diff --git a/mpz/mul.c b/mpz/mul.c
new file mode 100644
index 000000000..47ce8e354
--- /dev/null
+++ b/mpz/mul.c
@@ -0,0 +1,127 @@
+/* mpz_mul -- Multiply two integers.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+#ifndef BERKELEY_MP
+void
+#if __STDC__
+mpz_mul (mpz_ptr w, mpz_srcptr u, mpz_srcptr v)
+#else
+mpz_mul (w, u, v)
+ mpz_ptr w;
+ mpz_srcptr u;
+ mpz_srcptr v;
+#endif
+#else /* BERKELEY_MP */
+void
+#if __STDC__
+mult (mpz_srcptr u, mpz_srcptr v, mpz_ptr w)
+#else
+mult (u, v, w)
+ mpz_srcptr u;
+ mpz_srcptr v;
+ mpz_ptr w;
+#endif
+#endif /* BERKELEY_MP */
+{
+ mp_size_t usize = u->_mp_size;
+ mp_size_t vsize = v->_mp_size;
+ mp_size_t wsize;
+ mp_size_t sign_product;
+ mp_ptr up, vp;
+ mp_ptr wp;
+ mp_ptr free_me = NULL;
+ size_t free_me_size;
+ mp_limb_t cy_limb;
+ TMP_DECL (marker);
+
+ TMP_MARK (marker);
+ sign_product = usize ^ vsize;
+ usize = ABS (usize);
+ vsize = ABS (vsize);
+
+ if (usize < vsize)
+ {
+ /* Swap U and V. */
+ {const __mpz_struct *t = u; u = v; v = t;}
+ {mp_size_t t = usize; usize = vsize; vsize = t;}
+ }
+
+ up = u->_mp_d;
+ vp = v->_mp_d;
+ wp = w->_mp_d;
+
+ /* Ensure W has space enough to store the result. */
+ wsize = usize + vsize;
+ if (w->_mp_alloc < wsize)
+ {
+ if (wp == up || wp == vp)
+ {
+ free_me = wp;
+ free_me_size = w->_mp_alloc;
+ }
+ else
+ (*_mp_free_func) (wp, w->_mp_alloc * BYTES_PER_MP_LIMB);
+
+ w->_mp_alloc = wsize;
+ wp = (mp_ptr) (*_mp_allocate_func) (wsize * BYTES_PER_MP_LIMB);
+ w->_mp_d = wp;
+ }
+ else
+ {
+ /* Make U and V not overlap with W. */
+ if (wp == up)
+ {
+ /* W and U are identical. Allocate temporary space for U. */
+ up = (mp_ptr) TMP_ALLOC (usize * BYTES_PER_MP_LIMB);
+ /* Is V identical too? Keep it identical with U. */
+ if (wp == vp)
+ vp = up;
+ /* Copy to the temporary space. */
+ MPN_COPY (up, wp, usize);
+ }
+ else if (wp == vp)
+ {
+ /* W and V are identical. Allocate temporary space for V. */
+ vp = (mp_ptr) TMP_ALLOC (vsize * BYTES_PER_MP_LIMB);
+ /* Copy to the temporary space. */
+ MPN_COPY (vp, wp, vsize);
+ }
+ }
+
+ if (vsize == 0)
+ {
+ wsize = 0;
+ }
+ else
+ {
+ cy_limb = mpn_mul (wp, up, usize, vp, vsize);
+ wsize = usize + vsize;
+ wsize -= cy_limb == 0;
+ }
+
+ w->_mp_size = sign_product < 0 ? -wsize : wsize;
+ if (free_me != NULL)
+ (*_mp_free_func) (free_me, free_me_size * BYTES_PER_MP_LIMB);
+ TMP_FREE (marker);
+}
diff --git a/mpz/mul_2exp.c b/mpz/mul_2exp.c
new file mode 100644
index 000000000..4d66a9877
--- /dev/null
+++ b/mpz/mul_2exp.c
@@ -0,0 +1,76 @@
+/* mpz_mul_2exp -- Multiply a bignum by 2**CNT
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_mul_2exp (mpz_ptr w, mpz_srcptr u, unsigned long int cnt)
+#else
+mpz_mul_2exp (w, u, cnt)
+ mpz_ptr w;
+ mpz_srcptr u;
+ unsigned long int cnt;
+#endif
+{
+ mp_size_t usize = u->_mp_size;
+ mp_size_t abs_usize = ABS (usize);
+ mp_size_t wsize;
+ mp_size_t limb_cnt;
+ mp_ptr wp;
+ mp_limb_t wlimb;
+
+ if (usize == 0)
+ {
+ w->_mp_size = 0;
+ return;
+ }
+
+ limb_cnt = cnt / BITS_PER_MP_LIMB;
+ wsize = abs_usize + limb_cnt + 1;
+ if (w->_mp_alloc < wsize)
+ _mpz_realloc (w, wsize);
+
+ wp = w->_mp_d;
+ wsize = abs_usize + limb_cnt;
+
+ cnt %= BITS_PER_MP_LIMB;
+ if (cnt != 0)
+ {
+ wlimb = mpn_lshift (wp + limb_cnt, u->_mp_d, abs_usize, cnt);
+ if (wlimb != 0)
+ {
+ wp[wsize] = wlimb;
+ wsize++;
+ }
+ }
+ else
+ {
+ MPN_COPY_DECR (wp + limb_cnt, u->_mp_d, abs_usize);
+ }
+
+ /* Zero all whole limbs at low end. Do it here and not before calling
+ mpn_lshift, not to lose for U == W. */
+ MPN_ZERO (wp, limb_cnt);
+
+ w->_mp_size = usize >= 0 ? wsize : -wsize;
+}
diff --git a/mpz/mul_ui.c b/mpz/mul_ui.c
new file mode 100644
index 000000000..f1f726959
--- /dev/null
+++ b/mpz/mul_ui.c
@@ -0,0 +1,64 @@
+/* mpz_mul_ui(product, multiplier, small_multiplicand) -- Set
+ PRODUCT to MULTIPLICATOR times SMALL_MULTIPLICAND.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_mul_ui (mpz_ptr prod, mpz_srcptr mult, unsigned long int small_mult)
+#else
+mpz_mul_ui (prod, mult, small_mult)
+ mpz_ptr prod;
+ mpz_srcptr mult;
+ unsigned long int small_mult;
+#endif
+{
+ mp_size_t size = mult->_mp_size;
+ mp_size_t sign_product = size;
+ mp_limb_t cy;
+ mp_size_t prod_size;
+ mp_ptr prod_ptr;
+
+ size = ABS (size);
+
+ if (size == 0 || small_mult == 0)
+ {
+ prod->_mp_size = 0;
+ return;
+ }
+
+ prod_size = size + 1;
+ if (prod->_mp_alloc < prod_size)
+ _mpz_realloc (prod, prod_size);
+
+ prod_ptr = prod->_mp_d;
+
+ cy = mpn_mul_1 (prod_ptr, mult->_mp_d, size, (mp_limb_t) small_mult);
+ if (cy != 0)
+ {
+ prod_ptr[size] = cy;
+ size++;
+ }
+
+ prod->_mp_size = sign_product >= 0 ? size : -size;
+}
diff --git a/mpz/neg.c b/mpz/neg.c
new file mode 100644
index 000000000..0b48e5c7b
--- /dev/null
+++ b/mpz/neg.c
@@ -0,0 +1,53 @@
+/* mpz_neg(mpz_ptr dst, mpz_ptr src) -- Assign the negated value of SRC to DST.
+
+Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_neg (mpz_ptr w, mpz_srcptr u)
+#else
+mpz_neg (w, u)
+ mpz_ptr w;
+ mpz_srcptr u;
+#endif
+{
+ mp_ptr wp, up;
+ mp_size_t usize, size;
+
+ usize = u->_mp_size;
+
+ if (u != w)
+ {
+ size = ABS (usize);
+
+ if (w->_mp_alloc < size)
+ _mpz_realloc (w, size);
+
+ wp = w->_mp_d;
+ up = u->_mp_d;
+
+ MPN_COPY (wp, up, size);
+ }
+
+ w->_mp_size = -usize;
+}
diff --git a/mpz/out_raw.c b/mpz/out_raw.c
new file mode 100644
index 000000000..35d311b43
--- /dev/null
+++ b/mpz/out_raw.c
@@ -0,0 +1,89 @@
+/* mpz_out_raw -- Output a mpz_t in binary. Use an endianess and word size
+ independent format.
+
+Copyright (C) 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+size_t
+#if __STDC__
+mpz_out_raw (FILE *stream, mpz_srcptr x)
+#else
+mpz_out_raw (stream, x)
+ FILE *stream;
+ mpz_srcptr x;
+#endif
+{
+ int i;
+ mp_size_t s;
+ mp_size_t xsize = ABS (x->_mp_size);
+ mp_srcptr xp = x->_mp_d;
+ mp_size_t out_bytesize;
+ mp_limb_t hi_limb;
+ int n_bytes_in_hi_limb;
+
+ if (stream == 0)
+ stream = stdout;
+
+ if (xsize == 0)
+ {
+ for (i = 4 - 1; i >= 0; i--)
+ fputc (0, stream);
+ return ferror (stream) ? 0 : 4;
+ }
+
+ hi_limb = xp[xsize - 1];
+ for (i = BYTES_PER_MP_LIMB - 1; i > 0; i--)
+ {
+ if ((hi_limb >> i * BITS_PER_CHAR) != 0)
+ break;
+ }
+ n_bytes_in_hi_limb = i + 1;
+ out_bytesize = BYTES_PER_MP_LIMB * (xsize - 1) + n_bytes_in_hi_limb;
+ if (x->_mp_size < 0)
+ out_bytesize = -out_bytesize;
+
+ /* Make the size 4 bytes on all machines, to make the format portable. */
+ for (i = 4 - 1; i >= 0; i--)
+ fputc ((out_bytesize >> (i * BITS_PER_CHAR)) % (1 << BITS_PER_CHAR),
+ stream);
+
+ /* Output from the most significant limb to the least significant limb,
+ with each limb also output in decreasing significance order. */
+
+ /* Output the most significant limb separately, since we will only
+ output some of its bytes. */
+ for (i = n_bytes_in_hi_limb - 1; i >= 0; i--)
+ fputc ((hi_limb >> (i * BITS_PER_CHAR)) % (1 << BITS_PER_CHAR), stream);
+
+ /* Output the remaining limbs. */
+ for (s = xsize - 2; s >= 0; s--)
+ {
+ mp_limb_t x_limb;
+
+ x_limb = xp[s];
+ for (i = BYTES_PER_MP_LIMB - 1; i >= 0; i--)
+ fputc ((x_limb >> (i * BITS_PER_CHAR)) % (1 << BITS_PER_CHAR), stream);
+ }
+ return ferror (stream) ? 0 : ABS (out_bytesize) + 4;
+}
diff --git a/mpz/out_str.c b/mpz/out_str.c
new file mode 100644
index 000000000..909f53346
--- /dev/null
+++ b/mpz/out_str.c
@@ -0,0 +1,108 @@
+/* mpz_out_str(stream, base, integer) -- Output to STREAM the multi prec.
+ integer INTEGER in base BASE.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+
+size_t
+#if __STDC__
+mpz_out_str (FILE *stream, int base, mpz_srcptr x)
+#else
+mpz_out_str (stream, base, x)
+ FILE *stream;
+ int base;
+ mpz_srcptr x;
+#endif
+{
+ mp_ptr xp;
+ mp_size_t x_size = x->_mp_size;
+ unsigned char *str;
+ size_t str_size;
+ size_t i;
+ size_t written;
+ char *num_to_text;
+ TMP_DECL (marker);
+
+ if (stream == 0)
+ stream = stdout;
+
+ if (base >= 0)
+ {
+ if (base == 0)
+ base = 10;
+ num_to_text = "0123456789abcdefghijklmnopqrstuvwxyz";
+ }
+ else
+ {
+ base = -base;
+ num_to_text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ }
+
+ if (x_size == 0)
+ {
+ fputc ('0', stream);
+ return ferror (stream) ? 0 : 1;
+ }
+
+ written = 0;
+
+ if (x_size < 0)
+ {
+ fputc ('-', stream);
+ x_size = -x_size;
+ written = 1;
+ }
+
+ TMP_MARK (marker);
+ str_size = ((size_t) (x_size * BITS_PER_MP_LIMB
+ * __mp_bases[base].chars_per_bit_exactly)) + 3;
+ str = (unsigned char *) TMP_ALLOC (str_size);
+
+ /* Move the number to convert into temporary space, since mpn_get_str
+ clobbers its argument + needs one extra high limb.... */
+ xp = (mp_ptr) TMP_ALLOC ((x_size + 1) * BYTES_PER_MP_LIMB);
+ MPN_COPY (xp, x->_mp_d, x_size);
+
+ str_size = mpn_get_str (str, base, xp, x_size);
+
+ /* mpn_get_str might make some leading zeros. Skip them. */
+ while (*str == 0)
+ {
+ str_size--;
+ str++;
+ }
+
+ /* Translate to printable chars. */
+ for (i = 0; i < str_size; i++)
+ str[i] = num_to_text[str[i]];
+ str[str_size] = 0;
+
+ {
+ size_t fwret;
+ fwret = fwrite ((char *) str, 1, str_size, stream);
+ written += fwret;
+ }
+
+ TMP_FREE (marker);
+ return ferror (stream) ? 0 : written;
+}
diff --git a/mpz/perfsqr.c b/mpz/perfsqr.c
new file mode 100644
index 000000000..cdf1b5a27
--- /dev/null
+++ b/mpz/perfsqr.c
@@ -0,0 +1,41 @@
+/* mpz_perfect_square_p(arg) -- Return non-zero if ARG is a perfect square,
+ zero otherwise.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+int
+#if __STDC__
+mpz_perfect_square_p (mpz_srcptr a)
+#else
+mpz_perfect_square_p (a)
+ mpz_srcptr a;
+#endif
+{
+ mp_size_t asize = a->_mp_size;
+
+ /* No negative numbers are perfect squares. */
+ if (asize < 0)
+ return 0;
+
+ return mpn_perfect_square_p (a->_mp_d, asize);
+}
diff --git a/mpz/popcount.c b/mpz/popcount.c
new file mode 100644
index 000000000..a97938030
--- /dev/null
+++ b/mpz/popcount.c
@@ -0,0 +1,42 @@
+/* mpz_popcount(mpz_ptr op) -- Population count of OP. If the operand is
+ negative, return ~0 (a novel representation of infinity).
+
+Copyright (C) 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+unsigned long int
+#if __STDC__
+mpz_popcount (mpz_srcptr u)
+#else
+mpz_popcount (u)
+ mpz_srcptr u;
+#endif
+{
+ mp_size_t usize;
+
+ usize = u->_mp_size;
+
+ if ((usize) < 0)
+ return ~ (unsigned long int) 0;
+
+ return mpn_popcount (u->_mp_d, usize);
+}
diff --git a/mpz/pow_ui.c b/mpz/pow_ui.c
new file mode 100644
index 000000000..bb23f804c
--- /dev/null
+++ b/mpz/pow_ui.c
@@ -0,0 +1,129 @@
+/* mpz_pow_ui(res, base, exp) -- Set RES to BASE**EXP.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#ifdef BERKELEY_MP
+#include "mp.h"
+#endif
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+#ifndef BERKELEY_MP
+void
+#if __STDC__
+mpz_pow_ui (mpz_ptr r, mpz_srcptr b, unsigned long int e)
+#else
+mpz_pow_ui (r, b, e)
+ mpz_ptr r;
+ mpz_srcptr b;
+ unsigned long int e;
+#endif
+#else /* BERKELEY_MP */
+void
+#if __STDC__
+rpow (const MINT *b, signed short int e, MINT *r)
+#else
+rpow (b, e, r)
+ const MINT *b;
+ signed short int e;
+ MINT *r;
+#endif
+#endif /* BERKELEY_MP */
+{
+ mp_ptr rp, bp, tp, xp;
+ mp_size_t rsize, bsize;
+ int cnt, i;
+ mp_limb_t blimb;
+ TMP_DECL (marker);
+
+ bsize = ABS (b->_mp_size);
+
+ /* Single out cases that give result == 0 or 1. These tests are here
+ to simplify the general code below, not to optimize. */
+ if (bsize == 0
+#ifdef BERKELEY_MP
+ || e < 0
+#endif
+ )
+ {
+ r->_mp_size = 0;
+ return;
+ }
+ if (e == 0)
+ {
+ r->_mp_d[0] = 1;
+ r->_mp_size = 1;
+ return;
+ }
+
+ bp = b->_mp_d;
+
+ blimb = bp[bsize - 1];
+ if (bsize == 1 && blimb < 0x100)
+ {
+ /* Estimate space requirements accurately. Using the code from the
+ `else' path would over-estimate space requirements wildly. */
+ float lb = __mp_bases[blimb].chars_per_bit_exactly;
+ rsize = 2 + ((mp_size_t) (e / lb) / BITS_PER_MP_LIMB);
+ }
+ else
+ {
+ /* Over-estimate space requirements somewhat. */
+ count_leading_zeros (cnt, blimb);
+ rsize = bsize * e - cnt * e / BITS_PER_MP_LIMB + 1;
+ }
+
+ TMP_MARK (marker);
+
+ /* The two areas are used to alternatingly hold the input and recieve the
+ product for mpn_mul. (This scheme is used to fulfill the requirements
+ of mpn_mul; that the product space may not be the same as any of the
+ input operands.) */
+ rp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB);
+ tp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB);
+
+ MPN_COPY (rp, bp, bsize);
+ rsize = bsize;
+ count_leading_zeros (cnt, e);
+
+ for (i = BITS_PER_MP_LIMB - cnt - 2; i >= 0; i--)
+ {
+ mpn_mul_n (tp, rp, rp, rsize);
+ rsize = 2 * rsize;
+ rsize -= tp[rsize - 1] == 0;
+ xp = tp; tp = rp; rp = xp;
+
+ if ((e & ((mp_limb_t) 1 << i)) != 0)
+ {
+ rsize = rsize + bsize - (mpn_mul (tp, rp, rsize, bp, bsize) == 0);
+ xp = tp; tp = rp; rp = xp;
+ }
+ }
+
+ /* Now then we know the exact space requirements, reallocate if
+ necessary. */
+ if (r->_mp_alloc < rsize)
+ _mpz_realloc (r, rsize);
+
+ MPN_COPY (r->_mp_d, rp, rsize);
+ r->_mp_size = (e & 1) == 0 || b->_mp_size >= 0 ? rsize : -rsize;
+ TMP_FREE (marker);
+}
diff --git a/mpz/powm.c b/mpz/powm.c
new file mode 100644
index 000000000..5dcd1b128
--- /dev/null
+++ b/mpz/powm.c
@@ -0,0 +1,276 @@
+/* mpz_powm(res,base,exp,mod) -- Set RES to (base**exp) mod MOD.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+#ifndef BERKELEY_MP
+void
+#if __STDC__
+mpz_powm (mpz_ptr res, mpz_srcptr base, mpz_srcptr exp, mpz_srcptr mod)
+#else
+mpz_powm (res, base, exp, mod)
+ mpz_ptr res;
+ mpz_srcptr base;
+ mpz_srcptr exp;
+ mpz_srcptr mod;
+#endif
+#else /* BERKELEY_MP */
+void
+#if __STDC__
+pow (mpz_srcptr base, mpz_srcptr exp, mpz_srcptr mod, mpz_ptr res)
+#else
+pow (base, exp, mod, res)
+ mpz_srcptr base;
+ mpz_srcptr exp;
+ mpz_srcptr mod;
+ mpz_ptr res;
+#endif
+#endif /* BERKELEY_MP */
+{
+ mp_ptr rp, ep, mp, bp;
+ mp_size_t esize, msize, bsize, rsize;
+ mp_size_t size;
+ int mod_shift_cnt;
+ int negative_result;
+ mp_limb_t *free_me = NULL;
+ size_t free_me_size;
+ TMP_DECL (marker);
+
+ esize = ABS (exp->_mp_size);
+ msize = ABS (mod->_mp_size);
+ size = 2 * msize;
+
+ rp = res->_mp_d;
+ ep = exp->_mp_d;
+
+ if (msize == 0)
+ msize = 1 / msize; /* provoke a signal */
+
+ if (esize == 0)
+ {
+ /* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0
+ depending on if MOD equals 1. */
+ rp[0] = 1;
+ res->_mp_size = (msize == 1 && (mod->_mp_d)[0] == 1) ? 0 : 1;
+ return;
+ }
+
+ TMP_MARK (marker);
+
+ /* Normalize MOD (i.e. make its most significant bit set) as required by
+ mpn_divmod. This will make the intermediate values in the calculation
+ slightly larger, but the correct result is obtained after a final
+ reduction using the original MOD value. */
+
+ mp = (mp_ptr) TMP_ALLOC (msize * BYTES_PER_MP_LIMB);
+ count_leading_zeros (mod_shift_cnt, mod->_mp_d[msize - 1]);
+ if (mod_shift_cnt != 0)
+ mpn_lshift (mp, mod->_mp_d, msize, mod_shift_cnt);
+ else
+ MPN_COPY (mp, mod->_mp_d, msize);
+
+ bsize = ABS (base->_mp_size);
+ if (bsize > msize)
+ {
+ /* The base is larger than the module. Reduce it. */
+
+ /* Allocate (BSIZE + 1) with space for remainder and quotient.
+ (The quotient is (bsize - msize + 1) limbs.) */
+ bp = (mp_ptr) TMP_ALLOC ((bsize + 1) * BYTES_PER_MP_LIMB);
+ MPN_COPY (bp, base->_mp_d, bsize);
+ /* We don't care about the quotient, store it above the remainder,
+ at BP + MSIZE. */
+ mpn_divmod (bp + msize, bp, bsize, mp, msize);
+ bsize = msize;
+ /* Canonicalize the base, since we are going to multiply with it
+ quite a few times. */
+ MPN_NORMALIZE (bp, bsize);
+ }
+ else
+ bp = base->_mp_d;
+
+ if (bsize == 0)
+ {
+ res->_mp_size = 0;
+ TMP_FREE (marker);
+ return;
+ }
+
+ if (res->_mp_alloc < size)
+ {
+ /* We have to allocate more space for RES. If any of the input
+ parameters are identical to RES, defer deallocation of the old
+ space. */
+
+ if (rp == ep || rp == mp || rp == bp)
+ {
+ free_me = rp;
+ free_me_size = res->_mp_alloc;
+ }
+ else
+ (*_mp_free_func) (rp, res->_mp_alloc * BYTES_PER_MP_LIMB);
+
+ rp = (mp_ptr) (*_mp_allocate_func) (size * BYTES_PER_MP_LIMB);
+ res->_mp_alloc = size;
+ res->_mp_d = rp;
+ }
+ else
+ {
+ /* Make BASE, EXP and MOD not overlap with RES. */
+ if (rp == bp)
+ {
+ /* RES and BASE are identical. Allocate temp. space for BASE. */
+ bp = (mp_ptr) TMP_ALLOC (bsize * BYTES_PER_MP_LIMB);
+ MPN_COPY (bp, rp, bsize);
+ }
+ if (rp == ep)
+ {
+ /* RES and EXP are identical. Allocate temp. space for EXP. */
+ ep = (mp_ptr) TMP_ALLOC (esize * BYTES_PER_MP_LIMB);
+ MPN_COPY (ep, rp, esize);
+ }
+ if (rp == mp)
+ {
+ /* RES and MOD are identical. Allocate temporary space for MOD. */
+ mp = (mp_ptr) TMP_ALLOC (msize * BYTES_PER_MP_LIMB);
+ MPN_COPY (mp, rp, msize);
+ }
+ }
+
+ MPN_COPY (rp, bp, bsize);
+ rsize = bsize;
+
+ {
+ mp_size_t i;
+ mp_ptr xp = (mp_ptr) TMP_ALLOC (2 * (msize + 1) * BYTES_PER_MP_LIMB);
+ int c;
+ mp_limb_t e;
+ mp_limb_t carry_limb;
+
+ negative_result = (ep[0] & 1) && base->_mp_size < 0;
+
+ i = esize - 1;
+ e = ep[i];
+ count_leading_zeros (c, e);
+ e = (e << c) << 1; /* shift the exp bits to the left, lose msb */
+ c = BITS_PER_MP_LIMB - 1 - c;
+
+ /* Main loop.
+
+ Make the result be pointed to alternately by XP and RP. This
+ helps us avoid block copying, which would otherwise be necessary
+ with the overlap restrictions of mpn_divmod. With 50% probability
+ the result after this loop will be in the area originally pointed
+ by RP (==RES->_mp_d), and with 50% probability in the area originally
+ pointed to by XP. */
+
+ for (;;)
+ {
+ while (c != 0)
+ {
+ mp_ptr tp;
+ mp_size_t xsize;
+
+ mpn_mul_n (xp, rp, rp, rsize);
+ xsize = 2 * rsize;
+ if (xsize > msize)
+ {
+ mpn_divmod (xp + msize, xp, xsize, mp, msize);
+ xsize = msize;
+ }
+
+ tp = rp; rp = xp; xp = tp;
+ rsize = xsize;
+
+ if ((mp_limb_signed_t) e < 0)
+ {
+ mpn_mul (xp, rp, rsize, bp, bsize);
+ xsize = rsize + bsize;
+ if (xsize > msize)
+ {
+ mpn_divmod (xp + msize, xp, xsize, mp, msize);
+ xsize = msize;
+ }
+
+ tp = rp; rp = xp; xp = tp;
+ rsize = xsize;
+ }
+ e <<= 1;
+ c--;
+ }
+
+ i--;
+ if (i < 0)
+ break;
+ e = ep[i];
+ c = BITS_PER_MP_LIMB;
+ }
+
+ /* We shifted MOD, the modulo reduction argument, left MOD_SHIFT_CNT
+ steps. Adjust the result by reducing it with the original MOD.
+
+ Also make sure the result is put in RES->_mp_d (where it already
+ might be, see above). */
+
+ if (mod_shift_cnt != 0)
+ {
+ carry_limb = mpn_lshift (res->_mp_d, rp, rsize, mod_shift_cnt);
+ rp = res->_mp_d;
+ if (carry_limb != 0)
+ {
+ rp[rsize] = carry_limb;
+ rsize++;
+ }
+ }
+ else
+ {
+ MPN_COPY (res->_mp_d, rp, rsize);
+ rp = res->_mp_d;
+ }
+
+ if (rsize >= msize)
+ {
+ mpn_divmod (rp + msize, rp, rsize, mp, msize);
+ rsize = msize;
+ }
+
+ /* Remove any leading zero words from the result. */
+ if (mod_shift_cnt != 0)
+ mpn_rshift (rp, rp, rsize, mod_shift_cnt);
+ MPN_NORMALIZE (rp, rsize);
+ }
+
+ if (negative_result && rsize != 0)
+ {
+ if (mod_shift_cnt != 0)
+ mpn_rshift (mp, mp, msize, mod_shift_cnt);
+ mpn_sub (rp, mp, msize, rp, rsize);
+ rsize = msize;
+ MPN_NORMALIZE (rp, rsize);
+ }
+ res->_mp_size = rsize;
+
+ if (free_me != NULL)
+ (*_mp_free_func) (free_me, free_me_size * BYTES_PER_MP_LIMB);
+ TMP_FREE (marker);
+}
diff --git a/mpz/powm_ui.c b/mpz/powm_ui.c
new file mode 100644
index 000000000..596815a0e
--- /dev/null
+++ b/mpz/powm_ui.c
@@ -0,0 +1,234 @@
+/* mpz_powm_ui(res,base,exp,mod) -- Set RES to (base**exp) mod MOD.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+void
+#if __STDC__
+mpz_powm_ui (mpz_ptr res, mpz_srcptr base, unsigned long int exp, mpz_srcptr mod)
+#else
+mpz_powm_ui (res, base, exp, mod)
+ mpz_ptr res;
+ mpz_srcptr base;
+ unsigned long int exp;
+ mpz_srcptr mod;
+#endif
+{
+ mp_ptr rp, mp, bp;
+ mp_size_t msize, bsize, rsize;
+ mp_size_t size;
+ int mod_shift_cnt;
+ int negative_result;
+ mp_limb_t *free_me = NULL;
+ size_t free_me_size;
+ TMP_DECL (marker);
+
+ msize = ABS (mod->_mp_size);
+ size = 2 * msize;
+
+ rp = res->_mp_d;
+
+ if (msize == 0)
+ msize = 1 / msize; /* provoke a signal */
+
+ if (exp == 0)
+ {
+ rp[0] = 1;
+ res->_mp_size = (msize == 1 && (mod->_mp_d)[0] == 1) ? 0 : 1;
+ return;
+ }
+
+ TMP_MARK (marker);
+
+ /* Normalize MOD (i.e. make its most significant bit set) as required by
+ mpn_divmod. This will make the intermediate values in the calculation
+ slightly larger, but the correct result is obtained after a final
+ reduction using the original MOD value. */
+
+ mp = (mp_ptr) TMP_ALLOC (msize * BYTES_PER_MP_LIMB);
+ count_leading_zeros (mod_shift_cnt, mod->_mp_d[msize - 1]);
+ if (mod_shift_cnt != 0)
+ mpn_lshift (mp, mod->_mp_d, msize, mod_shift_cnt);
+ else
+ MPN_COPY (mp, mod->_mp_d, msize);
+
+ bsize = ABS (base->_mp_size);
+ if (bsize > msize)
+ {
+ /* The base is larger than the module. Reduce it. */
+
+ /* Allocate (BSIZE + 1) with space for remainder and quotient.
+ (The quotient is (bsize - msize + 1) limbs.) */
+ bp = (mp_ptr) TMP_ALLOC ((bsize + 1) * BYTES_PER_MP_LIMB);
+ MPN_COPY (bp, base->_mp_d, bsize);
+ /* We don't care about the quotient, store it above the remainder,
+ at BP + MSIZE. */
+ mpn_divmod (bp + msize, bp, bsize, mp, msize);
+ bsize = msize;
+ /* Canonicalize the base, since we are going to multiply with it
+ quite a few times. */
+ MPN_NORMALIZE (bp, bsize);
+ }
+ else
+ bp = base->_mp_d;
+
+ if (bsize == 0)
+ {
+ res->_mp_size = 0;
+ TMP_FREE (marker);
+ return;
+ }
+
+ if (res->_mp_alloc < size)
+ {
+ /* We have to allocate more space for RES. If any of the input
+ parameters are identical to RES, defer deallocation of the old
+ space. */
+
+ if (rp == mp || rp == bp)
+ {
+ free_me = rp;
+ free_me_size = res->_mp_alloc;
+ }
+ else
+ (*_mp_free_func) (rp, res->_mp_alloc * BYTES_PER_MP_LIMB);
+
+ rp = (mp_ptr) (*_mp_allocate_func) (size * BYTES_PER_MP_LIMB);
+ res->_mp_alloc = size;
+ res->_mp_d = rp;
+ }
+ else
+ {
+ /* Make BASE, EXP and MOD not overlap with RES. */
+ if (rp == bp)
+ {
+ /* RES and BASE are identical. Allocate temp. space for BASE. */
+ bp = (mp_ptr) TMP_ALLOC (bsize * BYTES_PER_MP_LIMB);
+ MPN_COPY (bp, rp, bsize);
+ }
+ if (rp == mp)
+ {
+ /* RES and MOD are identical. Allocate temporary space for MOD. */
+ mp = (mp_ptr) TMP_ALLOC (msize * BYTES_PER_MP_LIMB);
+ MPN_COPY (mp, rp, msize);
+ }
+ }
+
+ MPN_COPY (rp, bp, bsize);
+ rsize = bsize;
+
+ {
+ mp_ptr xp = (mp_ptr) TMP_ALLOC (2 * (msize + 1) * BYTES_PER_MP_LIMB);
+ int c;
+ mp_limb_t e;
+ mp_limb_t carry_limb;
+
+ negative_result = (exp & 1) && base->_mp_size < 0;
+
+ e = exp;
+ count_leading_zeros (c, e);
+ e = (e << c) << 1; /* shift the exp bits to the left, lose msb */
+ c = BITS_PER_MP_LIMB - 1 - c;
+
+ /* Main loop.
+
+ Make the result be pointed to alternately by XP and RP. This
+ helps us avoid block copying, which would otherwise be necessary
+ with the overlap restrictions of mpn_divmod. With 50% probability
+ the result after this loop will be in the area originally pointed
+ by RP (==RES->_mp_d), and with 50% probability in the area originally
+ pointed to by XP. */
+
+ while (c != 0)
+ {
+ mp_ptr tp;
+ mp_size_t xsize;
+
+ mpn_mul_n (xp, rp, rp, rsize);
+ xsize = 2 * rsize;
+ if (xsize > msize)
+ {
+ mpn_divmod (xp + msize, xp, xsize, mp, msize);
+ xsize = msize;
+ }
+
+ tp = rp; rp = xp; xp = tp;
+ rsize = xsize;
+
+ if ((mp_limb_signed_t) e < 0)
+ {
+ mpn_mul (xp, rp, rsize, bp, bsize);
+ xsize = rsize + bsize;
+ if (xsize > msize)
+ {
+ mpn_divmod (xp + msize, xp, xsize, mp, msize);
+ xsize = msize;
+ }
+
+ tp = rp; rp = xp; xp = tp;
+ rsize = xsize;
+ }
+ e <<= 1;
+ c--;
+ }
+
+ /* We shifted MOD, the modulo reduction argument, left MOD_SHIFT_CNT
+ steps. Adjust the result by reducing it with the original MOD.
+
+ Also make sure the result is put in RES->_mp_d (where it already
+ might be, see above). */
+
+ if (mod_shift_cnt != 0)
+ {
+ carry_limb = mpn_lshift (res->_mp_d, rp, rsize, mod_shift_cnt);
+ rp = res->_mp_d;
+ if (carry_limb != 0)
+ {
+ rp[rsize] = carry_limb;
+ rsize++;
+ }
+ }
+ else
+ {
+ MPN_COPY (res->_mp_d, rp, rsize);
+ rp = res->_mp_d;
+ }
+
+ if (rsize >= msize)
+ {
+ mpn_divmod (rp + msize, rp, rsize, mp, msize);
+ rsize = msize;
+ }
+
+ /* Remove any leading zero words from the result. */
+ if (mod_shift_cnt != 0)
+ mpn_rshift (rp, rp, rsize, mod_shift_cnt);
+ MPN_NORMALIZE (rp, rsize);
+ }
+
+ res->_mp_size = negative_result == 0 ? rsize : -rsize;
+
+ if (free_me != NULL)
+ (*_mp_free_func) (free_me, free_me_size * BYTES_PER_MP_LIMB);
+ TMP_FREE (marker);
+}
diff --git a/mpz/pprime_p.c b/mpz/pprime_p.c
new file mode 100644
index 000000000..494de14ca
--- /dev/null
+++ b/mpz/pprime_p.c
@@ -0,0 +1,115 @@
+/* mpz_probab_prime_p --
+ An implementation of the probabilistic primality test found in Knuth's
+ Seminumerical Algorithms book. If the function mpz_probab_prime_p()
+ returns 0 then n is not prime. If it returns 1, then n is 'probably'
+ prime. The probability of a false positive is (1/4)**reps, where
+ reps is the number of internal passes of the probabilistic algorithm.
+ Knuth indicates that 25 passes are reasonable.
+
+Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc.
+Contributed by John Amanatides.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+
+static int
+possibly_prime (n, n_minus_1, x, y, q, k)
+ mpz_srcptr n;
+ mpz_srcptr n_minus_1;
+ mpz_ptr x;
+ mpz_ptr y;
+ mpz_srcptr q;
+ unsigned long int k;
+{
+ unsigned long int i;
+
+ /* find random x s.t. 1 < x < n */
+ do
+ {
+ mpz_random (x, mpz_size (n));
+ mpz_mmod (x, x, n);
+ }
+ while (mpz_cmp_ui (x, 1L) <= 0);
+
+ mpz_powm (y, x, q, n);
+
+ if (mpz_cmp_ui (y, 1L) == 0 || mpz_cmp (y, n_minus_1) == 0)
+ return 1;
+
+ for (i = 1; i < k; i++)
+ {
+ mpz_powm_ui (y, y, 2L, n);
+ if (mpz_cmp (y, n_minus_1) == 0)
+ return 1;
+ if (mpz_cmp_ui (y, 1L) == 0)
+ return 0;
+ }
+ return 0;
+}
+
+int
+#if __STDC__
+mpz_probab_prime_p (mpz_srcptr m, int reps)
+#else
+mpz_probab_prime_p (m, reps)
+ mpz_srcptr m;
+ int reps;
+#endif
+{
+ mpz_t n, n_minus_1, x, y, q;
+ int i, is_prime;
+ unsigned long int k;
+
+ mpz_init (n);
+ /* Take the absolute value of M, to handle positive and negative primes. */
+ mpz_abs (n, m);
+
+ if (mpz_cmp_ui (n, 3L) <= 0)
+ {
+ mpz_clear (n);
+ return mpz_cmp_ui (n, 1L) > 0;
+ }
+
+ if ((mpz_get_ui (n) & 1) == 0)
+ {
+ mpz_clear (n);
+ return 0; /* even */
+ }
+
+ mpz_init (n_minus_1);
+ mpz_sub_ui (n_minus_1, n, 1L);
+ mpz_init (x);
+ mpz_init (y);
+
+ /* find q and k, s.t. n = 1 + 2**k * q */
+ mpz_init_set (q, n_minus_1);
+ k = mpz_scan1 (q, 0);
+ mpz_tdiv_q_2exp (q, q, k);
+
+ is_prime = 1;
+ for (i = 0; i < reps && is_prime; i++)
+ is_prime &= possibly_prime (n, n_minus_1, x, y, q, k);
+
+ mpz_clear (n_minus_1);
+ mpz_clear (n);
+ mpz_clear (x);
+ mpz_clear (y);
+ mpz_clear (q);
+ return is_prime;
+}
diff --git a/mpz/random.c b/mpz/random.c
new file mode 100644
index 000000000..ab41eef92
--- /dev/null
+++ b/mpz/random.c
@@ -0,0 +1,56 @@
+/* mpz_random -- Generate a random mpz_t of specified size.
+ This function is non-portable and generates poor random numbers.
+
+Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+void
+#if __STDC__
+mpz_random (mpz_ptr x, mp_size_t size)
+#else
+mpz_random (x, size)
+ mpz_ptr x;
+ mp_size_t size;
+#endif
+{
+ mp_size_t i;
+ mp_limb_t ran;
+ mp_ptr xp;
+ mp_size_t abs_size;
+
+ abs_size = ABS (size);
+
+ if (x->_mp_alloc < abs_size)
+ _mpz_realloc (x, abs_size);
+
+ xp = x->_mp_d;
+
+ for (i = 0; i < abs_size; i++)
+ {
+ ran = urandom ();
+ xp[i] = ran;
+ }
+
+ MPN_NORMALIZE (xp, abs_size);
+ x->_mp_size = size < 0 ? -abs_size : abs_size;
+}
diff --git a/mpz/random2.c b/mpz/random2.c
new file mode 100644
index 000000000..725a8b491
--- /dev/null
+++ b/mpz/random2.c
@@ -0,0 +1,48 @@
+/* mpz_random2 -- Generate a positive random mpz_t of specified size, with
+ long runs of consecutive ones and zeros in the binary representation.
+ Meant for testing of other MP routines.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_random2 (mpz_ptr x, mp_size_t size)
+#else
+mpz_random2 (x, size)
+ mpz_ptr x;
+ mp_size_t size;
+#endif
+{
+ mp_size_t abs_size;
+
+ abs_size = ABS (size);
+ if (abs_size != 0)
+ {
+ if (x->_mp_alloc < abs_size)
+ _mpz_realloc (x, abs_size);
+
+ mpn_random2 (x->_mp_d, abs_size);
+ }
+
+ x->_mp_size = size;
+}
diff --git a/mpz/realloc.c b/mpz/realloc.c
new file mode 100644
index 000000000..2c2a5da92
--- /dev/null
+++ b/mpz/realloc.c
@@ -0,0 +1,52 @@
+/* _mpz_realloc -- make the mpz_t have NEW_SIZE digits allocated.
+
+Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void *
+#if __STDC__
+_mpz_realloc (mpz_ptr m, mp_size_t new_size)
+#else
+_mpz_realloc (m, new_size)
+ mpz_ptr m;
+ mp_size_t new_size;
+#endif
+{
+ /* Never allocate zero space. */
+ if (new_size == 0)
+ new_size = 1;
+
+ m->_mp_d = (mp_ptr) (*_mp_reallocate_func) (m->_mp_d,
+ m->_mp_alloc * BYTES_PER_MP_LIMB,
+ new_size * BYTES_PER_MP_LIMB);
+ m->_mp_alloc = new_size;
+
+#if 0
+ /* This might break some code that reads the size field after
+ reallocation, in the case the reallocated destination and a
+ source argument are identical. */
+ if (ABS (m->_mp_size) > new_size)
+ m->_mp_size = 0;
+#endif
+
+ return (void *) m->_mp_d;
+}
diff --git a/mpz/scan0.c b/mpz/scan0.c
new file mode 100644
index 000000000..8e45aa324
--- /dev/null
+++ b/mpz/scan0.c
@@ -0,0 +1,35 @@
+/* mpz_scan0(op, startbit) -- Scan for the next set bit, starting at startbit.
+
+Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+unsigned long int
+#if __STDC__
+mpz_scan0 (mpz_srcptr u, unsigned long int starting_bit)
+#else
+mpz_scan0 (u, starting_bit)
+ mpz_srcptr u;
+ unsigned long int starting_bit;
+#endif
+{
+ return mpn_scan0 (u->_mp_d, starting_bit);
+}
diff --git a/mpz/scan1.c b/mpz/scan1.c
new file mode 100644
index 000000000..6ecb0aab3
--- /dev/null
+++ b/mpz/scan1.c
@@ -0,0 +1,35 @@
+/* mpz_scan1(op, startbit) -- Scan for the next set bit, starting at startbit.
+
+Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+unsigned long int
+#if __STDC__
+mpz_scan1 (mpz_srcptr u, unsigned long int starting_bit)
+#else
+mpz_scan1 (u, starting_bit)
+ mpz_srcptr u;
+ unsigned long int starting_bit;
+#endif
+{
+ return mpn_scan1 (u->_mp_d, starting_bit);
+}
diff --git a/mpz/set.c b/mpz/set.c
new file mode 100644
index 000000000..d94ab7485
--- /dev/null
+++ b/mpz/set.c
@@ -0,0 +1,48 @@
+/* mpz_set (dest_integer, src_integer) -- Assign DEST_INTEGER from SRC_INTEGER.
+
+Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_set (mpz_ptr w, mpz_srcptr u)
+#else
+mpz_set (w, u)
+ mpz_ptr w;
+ mpz_srcptr u;
+#endif
+{
+ mp_ptr wp, up;
+ mp_size_t usize, size;
+
+ usize = u->_mp_size;
+ size = ABS (usize);
+
+ if (w->_mp_alloc < size)
+ _mpz_realloc (w, size);
+
+ wp = w->_mp_d;
+ up = u->_mp_d;
+
+ MPN_COPY (wp, up, size);
+ w->_mp_size = usize;
+}
diff --git a/mpz/set_d.c b/mpz/set_d.c
new file mode 100644
index 000000000..c31beadc4
--- /dev/null
+++ b/mpz/set_d.c
@@ -0,0 +1,133 @@
+/* mpz_set_d(integer, val) -- Assign INTEGER with a double value VAL.
+
+Copyright (C) 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include <math.h>
+
+#define MP_BASE_AS_DOUBLE (2.0 * ((mp_limb_t) 1 << (BITS_PER_MP_LIMB - 1)))
+
+void
+#if __STDC__
+mpz_set_d (mpz_ptr dest, double val)
+#else
+mpz_set_d (dest, val)
+ mpz_ptr dest;
+ double val;
+#endif
+{
+ int negative;
+ double base;
+ int mexp;
+ unsigned exp;
+ mp_size_t size;
+
+ negative = val < 0;
+ val = fabs (val);
+
+ /* Zero is not handled correctly by the code below. */
+ if (val < 1)
+ {
+ dest->_mp_size = 0;
+ return;
+ }
+ /* Handle small arguments quickly. */
+ if (val < MP_BASE_AS_DOUBLE)
+ {
+ dest->_mp_d[0] = val;
+ dest->_mp_size = negative ? -1 : 1;
+ return;
+ }
+
+ base = frexp (val, &mexp);
+ exp = mexp;
+
+#if BITS_PER_MP_LIMB >= 64
+ {
+ double dlo, dhi;
+ mp_size_t lexp, bexp;
+ mp_limb_t l0, l1, l2;
+ mp_ptr rp = dest->_mp_d;
+
+ l0 = base * MP_BASE_AS_DOUBLE;
+ lexp = exp / BITS_PER_MP_LIMB;
+ bexp = exp % BITS_PER_MP_LIMB;
+ if (bexp != 0)
+ {
+ l1 = l0 >> (BITS_PER_MP_LIMB - bexp);
+ l0 = l0 << bexp;
+ }
+ else
+ {
+ l1 = l0;
+ l0 = 0;
+ lexp--;
+ }
+ MPN_ZERO (rp, lexp - 1);
+ rp[lexp - 1] = l0;
+ rp[lexp] = l1;
+ size = lexp + 1;
+ }
+#endif
+#if BITS_PER_MP_LIMB < 64
+ {
+ double dlo, dhi;
+ mp_size_t lexp, bexp;
+ mp_limb_t l0, l1, l2;
+ mp_ptr rp = dest->_mp_d;
+
+ dlo = modf (base * MP_BASE_AS_DOUBLE, &dhi);
+ l0 = dlo * MP_BASE_AS_DOUBLE;
+ l1 = dhi;
+ lexp = exp / BITS_PER_MP_LIMB;
+ bexp = exp % BITS_PER_MP_LIMB;
+ if (bexp != 0)
+ {
+ l2 = l1 >> (BITS_PER_MP_LIMB - bexp);
+ l1 = (l1 << bexp) | (l0 >> (BITS_PER_MP_LIMB - bexp));
+ l0 = l0 << bexp;
+ }
+ else
+ {
+ l2 = l1;
+ l1 = l0;
+ l0 = 0;
+ lexp--;
+ }
+ if (exp <= 2 * BITS_PER_MP_LIMB)
+ {
+ rp[0] = l1;
+ rp[1] = l2;
+ size = 2;
+ }
+ else
+ {
+ MPN_ZERO (rp, lexp - 2);
+ rp[lexp - 2] = l0;
+ rp[lexp - 1] = l1;
+ rp[lexp] = l2;
+ size = lexp + 1;
+ }
+ }
+#endif
+
+ dest->_mp_size = negative ? -size : size;
+}
diff --git a/mpz/set_si.c b/mpz/set_si.c
new file mode 100644
index 000000000..82a90a3cc
--- /dev/null
+++ b/mpz/set_si.c
@@ -0,0 +1,48 @@
+/* mpz_set_si(integer, val) -- Assign INTEGER with a small value VAL.
+
+Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_set_si (mpz_ptr dest, signed long int val)
+#else
+mpz_set_si (dest, val)
+ mpz_ptr dest;
+ signed long int val;
+#endif
+{
+ /* We don't check if the allocation is enough, since the rest of the
+ package ensures it's at least 1, which is what we need here. */
+ if (val > 0)
+ {
+ dest->_mp_d[0] = val;
+ dest->_mp_size = 1;
+ }
+ else if (val < 0)
+ {
+ dest->_mp_d[0] = -val;
+ dest->_mp_size = -1;
+ }
+ else
+ dest->_mp_size = 0;
+}
diff --git a/mpz/set_str.c b/mpz/set_str.c
new file mode 100644
index 000000000..d1334b1e0
--- /dev/null
+++ b/mpz/set_str.c
@@ -0,0 +1,132 @@
+/* mpz_set_str(mp_dest, string, base) -- Convert the \0-terminated
+ string STRING in base BASE to multiple precision integer in
+ MP_DEST. Allow white space in the string. If BASE == 0 determine
+ the base in the C standard way, i.e. 0xhh...h means base 16,
+ 0oo...o means base 8, otherwise assume base 10.
+
+Copyright (C) 1991, 1993, 1994, Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <ctype.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+static int
+digit_value_in_base (c, base)
+ int c;
+ int base;
+{
+ int digit;
+
+ if (isdigit (c))
+ digit = c - '0';
+ else if (islower (c))
+ digit = c - 'a' + 10;
+ else if (isupper (c))
+ digit = c - 'A' + 10;
+ else
+ return -1;
+
+ if (digit < base)
+ return digit;
+ return -1;
+}
+
+int
+#if __STDC__
+mpz_set_str (mpz_ptr x, const char *str, int base)
+#else
+mpz_set_str (x, str, base)
+ mpz_ptr x;
+ const char *str;
+ int base;
+#endif
+{
+ size_t str_size;
+ char *s, *begs;
+ size_t i;
+ mp_size_t xsize;
+ int c;
+ int negative;
+ TMP_DECL (marker);
+
+ /* Skip whitespace. */
+ do
+ c = *str++;
+ while (isspace (c));
+
+ negative = 0;
+ if (c == '-')
+ {
+ negative = 1;
+ c = *str++;
+ }
+
+ if (digit_value_in_base (c, base == 0 ? 10 : base) < 0)
+ return -1; /* error if no digits */
+
+ /* If BASE is 0, try to find out the base by looking at the initial
+ characters. */
+ if (base == 0)
+ {
+ base = 10;
+ if (c == '0')
+ {
+ base = 8;
+ c = *str++;
+ if (c == 'x' || c == 'X')
+ {
+ base = 16;
+ c = *str++;
+ }
+ }
+ }
+
+ TMP_MARK (marker);
+ str_size = strlen (str - 1);
+ s = begs = (char *) TMP_ALLOC (str_size + 1);
+
+ for (i = 0; i < str_size; i++)
+ {
+ if (!isspace (c))
+ {
+ int dig = digit_value_in_base (c, base);
+ if (dig < 0)
+ {
+ TMP_FREE (marker);
+ return -1;
+ }
+ *s++ = dig;
+ }
+ c = *str++;
+ }
+
+ str_size = s - begs;
+
+ xsize = str_size / __mp_bases[base].chars_per_limb + 1;
+ if (x->_mp_alloc < xsize)
+ _mpz_realloc (x, xsize);
+
+ xsize = mpn_set_str (x->_mp_d, (unsigned char *) begs, str_size, base);
+ x->_mp_size = negative ? -xsize : xsize;
+
+ TMP_FREE (marker);
+ return 0;
+}
diff --git a/mpz/set_ui.c b/mpz/set_ui.c
new file mode 100644
index 000000000..73f6cf54a
--- /dev/null
+++ b/mpz/set_ui.c
@@ -0,0 +1,43 @@
+/* mpz_set_ui(integer, val) -- Assign INTEGER with a small value VAL.
+
+Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_set_ui (mpz_ptr dest, unsigned long int val)
+#else
+mpz_set_ui (dest, val)
+ mpz_ptr dest;
+ unsigned long int val;
+#endif
+{
+ /* We don't check if the allocation is enough, since the rest of the
+ package ensures it's at least 1, which is what we need here. */
+ if (val > 0)
+ {
+ dest->_mp_d[0] = val;
+ dest->_mp_size = 1;
+ }
+ else
+ dest->_mp_size = 0;
+}
diff --git a/mpz/setbit.c b/mpz/setbit.c
new file mode 100644
index 000000000..af59e2cc7
--- /dev/null
+++ b/mpz/setbit.c
@@ -0,0 +1,113 @@
+/* mpz_setbit -- set a specified bit.
+
+Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_setbit (mpz_ptr d, unsigned long int bit_index)
+#else
+mpz_setbit (d, bit_index)
+ mpz_ptr d;
+ unsigned long int bit_index;
+#endif
+{
+ mp_size_t dsize = d->_mp_size;
+ mp_ptr dp = d->_mp_d;
+ mp_size_t limb_index;
+
+ limb_index = bit_index / BITS_PER_MP_LIMB;
+ if (dsize >= 0)
+ {
+ if (limb_index < dsize)
+ {
+ dp[limb_index] |= (mp_limb_t) 1 << (bit_index % BITS_PER_MP_LIMB);
+ d->_mp_size = dsize;
+ }
+ else
+ {
+ /* Ugh. The bit should be set outside of the end of the
+ number. We have to increase the size of the number. */
+ if (d->_mp_alloc < limb_index + 1)
+ {
+ _mpz_realloc (d, limb_index + 1);
+ dp = d->_mp_d;
+ }
+ MPN_ZERO (dp + dsize, limb_index - dsize);
+ dp[limb_index] = (mp_limb_t) 1 << (bit_index % BITS_PER_MP_LIMB);
+ d->_mp_size = limb_index + 1;
+ }
+ }
+ else
+ {
+ mp_size_t zero_bound;
+
+ /* Simulate two's complement arithmetic, i.e. simulate
+ 1. Set OP = ~(OP - 1) [with infinitely many leading ones].
+ 2. set the bit.
+ 3. Set OP = ~OP + 1. */
+
+ dsize = -dsize;
+
+ /* No upper bound on this loop, we're sure there's a non-zero limb
+ sooner ot later. */
+ for (zero_bound = 0; ; zero_bound++)
+ if (dp[zero_bound] != 0)
+ break;
+
+ if (limb_index > zero_bound)
+ {
+ if (limb_index < dsize)
+ dp[limb_index] &= ~((mp_limb_t) 1 << (bit_index % BITS_PER_MP_LIMB));
+ else
+ ;
+ }
+ else if (limb_index == zero_bound)
+ {
+ dp[limb_index] = ((dp[limb_index] - 1)
+ & ~((mp_limb_t) 1 << (bit_index % BITS_PER_MP_LIMB))) + 1;
+ if (dp[limb_index] == 0)
+ {
+ mp_size_t i;
+ for (i = limb_index + 1; i < dsize; i++)
+ {
+ dp[i] += 1;
+ if (dp[i] != 0)
+ goto fin;
+ }
+ /* We got carry all way out beyond the end of D. Increase
+ its size (and allocation if necessary). */
+ dsize++;
+ if (d->_mp_alloc < dsize)
+ {
+ _mpz_realloc (d, dsize);
+ dp = d->_mp_d;
+ }
+ dp[i] = 1;
+ d->_mp_size = -dsize;
+ fin:;
+ }
+ }
+ else
+ ;
+ }
+}
diff --git a/mpz/size.c b/mpz/size.c
new file mode 100644
index 000000000..0b09fbeb0
--- /dev/null
+++ b/mpz/size.c
@@ -0,0 +1,35 @@
+/* mpz_size(x) -- return the number of lims currently used by the
+ value of integer X.
+
+Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+size_t
+#if __STDC__
+mpz_size (mpz_srcptr x)
+#else
+mpz_size (x)
+ mpz_srcptr x;
+#endif
+{
+ return ABS (x->_mp_size);
+}
diff --git a/mpz/sizeinbase.c b/mpz/sizeinbase.c
new file mode 100644
index 000000000..51bd5558a
--- /dev/null
+++ b/mpz/sizeinbase.c
@@ -0,0 +1,60 @@
+/* mpz_sizeinbase(x, base) -- return an approximation to the number of
+ character the integer X would have printed in base BASE. The
+ approximation is never too small.
+
+Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+size_t
+#if __STDC__
+mpz_sizeinbase (mpz_srcptr x, int base)
+#else
+mpz_sizeinbase (x, base)
+ mpz_srcptr x;
+ int base;
+#endif
+{
+ mp_size_t size = ABS (x->_mp_size);
+ int lb_base, cnt;
+ size_t totbits;
+
+ /* Special case for X == 0. */
+ if (size == 0)
+ return 1;
+
+ /* Calculate the total number of significant bits of X. */
+ count_leading_zeros (cnt, x->_mp_d[size - 1]);
+ totbits = size * BITS_PER_MP_LIMB - cnt;
+
+ if ((base & (base - 1)) == 0)
+ {
+ /* Special case for powers of 2, giving exact result. */
+
+ count_leading_zeros (lb_base, base);
+ lb_base = BITS_PER_MP_LIMB - lb_base - 1;
+
+ return (totbits + lb_base - 1) / lb_base;
+ }
+ else
+ return (size_t) (totbits * __mp_bases[base].chars_per_bit_exactly) + 1;
+}
diff --git a/mpz/sqrt.c b/mpz/sqrt.c
new file mode 100644
index 000000000..c031d42cb
--- /dev/null
+++ b/mpz/sqrt.c
@@ -0,0 +1,89 @@
+/* mpz_sqrt(root, u) -- Set ROOT to floor(sqrt(U)).
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/* This code is just correct if "unsigned char" has at least 8 bits. It
+ doesn't help to use CHAR_BIT from limits.h, as the real problem is
+ the static arrays. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_sqrt (mpz_ptr root, mpz_srcptr op)
+#else
+mpz_sqrt (root, op)
+ mpz_ptr root;
+ mpz_srcptr op;
+#endif
+{
+ mp_size_t op_size, root_size;
+ mp_ptr root_ptr, op_ptr;
+ mp_ptr free_me = NULL;
+ mp_size_t free_me_size;
+ TMP_DECL (marker);
+
+ TMP_MARK (marker);
+ op_size = op->_mp_size;
+ if (op_size < 0)
+ op_size = 1 / (op_size > 0); /* Divide by zero for negative OP. */
+
+ /* The size of the root is accurate after this simple calculation. */
+ root_size = (op_size + 1) / 2;
+
+ root_ptr = root->_mp_d;
+ op_ptr = op->_mp_d;
+
+ if (root->_mp_alloc < root_size)
+ {
+ if (root_ptr == op_ptr)
+ {
+ free_me = root_ptr;
+ free_me_size = root->_mp_alloc;
+ }
+ else
+ (*_mp_free_func) (root_ptr, root->_mp_alloc * BYTES_PER_MP_LIMB);
+
+ root->_mp_alloc = root_size;
+ root_ptr = (mp_ptr) (*_mp_allocate_func) (root_size * BYTES_PER_MP_LIMB);
+ root->_mp_d = root_ptr;
+ }
+ else
+ {
+ /* Make OP not overlap with ROOT. */
+ if (root_ptr == op_ptr)
+ {
+ /* ROOT and OP are identical. Allocate temporary space for OP. */
+ op_ptr = (mp_ptr) TMP_ALLOC (op_size * BYTES_PER_MP_LIMB);
+ /* Copy to the temporary space. Hack: Avoid temporary variable
+ by using ROOT_PTR. */
+ MPN_COPY (op_ptr, root_ptr, op_size);
+ }
+ }
+
+ mpn_sqrtrem (root_ptr, NULL, op_ptr, op_size);
+
+ root->_mp_size = root_size;
+
+ if (free_me != NULL)
+ (*_mp_free_func) (free_me, free_me_size * BYTES_PER_MP_LIMB);
+ TMP_FREE (marker);
+}
diff --git a/mpz/sqrtrem.c b/mpz/sqrtrem.c
new file mode 100644
index 000000000..757cc5dd5
--- /dev/null
+++ b/mpz/sqrtrem.c
@@ -0,0 +1,107 @@
+/* mpz_sqrtrem(root,rem,x) -- Set ROOT to floor(sqrt(X)) and REM
+ to the remainder, i.e. X - ROOT**2.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+#ifndef BERKELEY_MP
+void
+#if __STDC__
+mpz_sqrtrem (mpz_ptr root, mpz_ptr rem, mpz_srcptr op)
+#else
+mpz_sqrtrem (root, rem, op)
+ mpz_ptr root;
+ mpz_ptr rem;
+ mpz_srcptr op;
+#endif
+#else /* BERKELEY_MP */
+void
+#if __STDC__
+msqrt (mpz_srcptr op, mpz_ptr root, mpz_ptr rem)
+#else
+msqrt (op, root, rem)
+ mpz_srcptr op;
+ mpz_ptr root;
+ mpz_ptr rem;
+#endif
+#endif /* BERKELEY_MP */
+{
+ mp_size_t op_size, root_size, rem_size;
+ mp_ptr root_ptr, op_ptr;
+ mp_ptr free_me = NULL;
+ mp_size_t free_me_size;
+ TMP_DECL (marker);
+
+ TMP_MARK (marker);
+ op_size = op->_mp_size;
+ if (op_size < 0)
+ op_size = 1 / (op_size > 0); /* Divide by zero for negative OP. */
+
+ if (rem->_mp_alloc < op_size)
+ _mpz_realloc (rem, op_size);
+
+ /* The size of the root is accurate after this simple calculation. */
+ root_size = (op_size + 1) / 2;
+
+ root_ptr = root->_mp_d;
+ op_ptr = op->_mp_d;
+
+ if (root->_mp_alloc < root_size)
+ {
+ if (root_ptr == op_ptr)
+ {
+ free_me = root_ptr;
+ free_me_size = root->_mp_alloc;
+ }
+ else
+ (*_mp_free_func) (root_ptr, root->_mp_alloc * BYTES_PER_MP_LIMB);
+
+ root->_mp_alloc = root_size;
+ root_ptr = (mp_ptr) (*_mp_allocate_func) (root_size * BYTES_PER_MP_LIMB);
+ root->_mp_d = root_ptr;
+ }
+ else
+ {
+ /* Make OP not overlap with ROOT. */
+ if (root_ptr == op_ptr)
+ {
+ /* ROOT and OP are identical. Allocate temporary space for OP. */
+ op_ptr = (mp_ptr) TMP_ALLOC (op_size * BYTES_PER_MP_LIMB);
+ /* Copy to the temporary space. Hack: Avoid temporary variable
+ by using ROOT_PTR. */
+ MPN_COPY (op_ptr, root_ptr, op_size);
+ }
+ }
+
+ rem_size = mpn_sqrtrem (root_ptr, rem->_mp_d, op_ptr, op_size);
+
+ root->_mp_size = root_size;
+
+ /* Write remainder size last, to enable us to define this function to
+ give only the square root remainder, if the user calls if with
+ ROOT == REM. */
+ rem->_mp_size = rem_size;
+
+ if (free_me != NULL)
+ (*_mp_free_func) (free_me, free_me_size * BYTES_PER_MP_LIMB);
+ TMP_FREE (marker);
+}
diff --git a/mpz/sub.c b/mpz/sub.c
new file mode 100644
index 000000000..56ef1a12a
--- /dev/null
+++ b/mpz/sub.c
@@ -0,0 +1,120 @@
+/* mpz_sub -- Subtract two integers.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+#ifndef BERKELEY_MP
+void
+#if __STDC__
+mpz_sub (mpz_ptr w, mpz_srcptr u, mpz_srcptr v)
+#else
+mpz_sub (w, u, v)
+ mpz_ptr w;
+ mpz_srcptr u;
+ mpz_srcptr v;
+#endif
+#else /* BERKELEY_MP */
+void
+#if __STDC__
+msub (mpz_srcptr u, mpz_srcptr v, mpz_ptr w)
+#else
+msub (u, v, w)
+ mpz_srcptr u;
+ mpz_srcptr v;
+ mpz_ptr w;
+#endif
+#endif /* BERKELEY_MP */
+{
+ mp_srcptr up, vp;
+ mp_ptr wp;
+ mp_size_t usize, vsize, wsize;
+ mp_size_t abs_usize;
+ mp_size_t abs_vsize;
+
+ usize = u->_mp_size;
+ vsize = -v->_mp_size; /* The "-" makes the difference from mpz_add */
+ abs_usize = ABS (usize);
+ abs_vsize = ABS (vsize);
+
+ if (abs_usize < abs_vsize)
+ {
+ /* Swap U and V. */
+ {const __mpz_struct *t = u; u = v; v = t;}
+ {mp_size_t t = usize; usize = vsize; vsize = t;}
+ {mp_size_t t = abs_usize; abs_usize = abs_vsize; abs_vsize = t;}
+ }
+
+ /* True: ABS_USIZE >= ABS_VSIZE. */
+
+ /* If not space for w (and possible carry), increase space. */
+ wsize = abs_usize + 1;
+ if (w->_mp_alloc < wsize)
+ _mpz_realloc (w, wsize);
+
+ /* These must be after realloc (u or v may be the same as w). */
+ up = u->_mp_d;
+ vp = v->_mp_d;
+ wp = w->_mp_d;
+
+ if ((usize ^ vsize) < 0)
+ {
+ /* U and V have different sign. Need to compare them to determine
+ which operand to subtract from which. */
+
+ /* This test is right since ABS_USIZE >= ABS_VSIZE. */
+ if (abs_usize != abs_vsize)
+ {
+ mpn_sub (wp, up, abs_usize, vp, abs_vsize);
+ wsize = abs_usize;
+ MPN_NORMALIZE (wp, wsize);
+ if (usize < 0)
+ wsize = -wsize;
+ }
+ else if (mpn_cmp (up, vp, abs_usize) < 0)
+ {
+ mpn_sub_n (wp, vp, up, abs_usize);
+ wsize = abs_usize;
+ MPN_NORMALIZE (wp, wsize);
+ if (usize >= 0)
+ wsize = -wsize;
+ }
+ else
+ {
+ mpn_sub_n (wp, up, vp, abs_usize);
+ wsize = abs_usize;
+ MPN_NORMALIZE (wp, wsize);
+ if (usize < 0)
+ wsize = -wsize;
+ }
+ }
+ else
+ {
+ /* U and V have same sign. Add them. */
+ mp_limb_t cy_limb = mpn_add (wp, up, abs_usize, vp, abs_vsize);
+ wp[abs_usize] = cy_limb;
+ wsize = abs_usize + cy_limb;
+ if (usize < 0)
+ wsize = -wsize;
+ }
+
+ w->_mp_size = wsize;
+}
diff --git a/mpz/sub_ui.c b/mpz/sub_ui.c
new file mode 100644
index 000000000..7dea4b6c0
--- /dev/null
+++ b/mpz/sub_ui.c
@@ -0,0 +1,84 @@
+/* mpz_sub_ui -- Subtract an unsigned one-word integer from an MP_INT.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_sub_ui (mpz_ptr w, mpz_srcptr u, unsigned long int v)
+#else
+mpz_sub_ui (w, u, v)
+ mpz_ptr w;
+ mpz_srcptr u;
+ unsigned long int v;
+#endif
+{
+ mp_srcptr up;
+ mp_ptr wp;
+ mp_size_t usize, wsize;
+ mp_size_t abs_usize;
+
+ usize = u->_mp_size;
+ abs_usize = ABS (usize);
+
+ /* If not space for W (and possible carry), increase space. */
+ wsize = abs_usize + 1;
+ if (w->_mp_alloc < wsize)
+ _mpz_realloc (w, wsize);
+
+ /* These must be after realloc (U may be the same as W). */
+ up = u->_mp_d;
+ wp = w->_mp_d;
+
+ if (abs_usize == 0)
+ {
+ wp[0] = v;
+ w->_mp_size = -(v != 0);
+ return;
+ }
+
+ if (usize < 0)
+ {
+ mp_limb_t cy;
+ cy = mpn_add_1 (wp, up, abs_usize, v);
+ wp[abs_usize] = cy;
+ wsize = -(abs_usize + cy);
+ }
+ else
+ {
+ /* The signs are different. Need exact comparison to determine
+ which operand to subtract from which. */
+ if (abs_usize == 1 && up[0] < v)
+ {
+ wp[0] = v - up[0];
+ wsize = -1;
+ }
+ else
+ {
+ mpn_sub_1 (wp, up, abs_usize, v);
+ /* Size can decrease with at most one limb. */
+ wsize = abs_usize - (wp[abs_usize - 1] == 0);
+ }
+ }
+
+ w->_mp_size = wsize;
+}
diff --git a/mpz/tdiv_q.c b/mpz/tdiv_q.c
new file mode 100644
index 000000000..b4d36368b
--- /dev/null
+++ b/mpz/tdiv_q.c
@@ -0,0 +1,133 @@
+/* mpz_tdiv_q -- divide two integers and produce a quotient.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+void
+#if __STDC__
+mpz_tdiv_q (mpz_ptr quot, mpz_srcptr num, mpz_srcptr den)
+#else
+mpz_tdiv_q (quot, num, den)
+ mpz_ptr quot;
+ mpz_srcptr num;
+ mpz_srcptr den;
+#endif
+{
+ mp_srcptr np, dp;
+ mp_ptr qp, rp;
+ mp_size_t nsize = num->_mp_size;
+ mp_size_t dsize = den->_mp_size;
+ mp_size_t qsize, rsize;
+ mp_size_t sign_quotient = nsize ^ dsize;
+ unsigned normalization_steps;
+ mp_limb_t q_limb;
+ TMP_DECL (marker);
+
+ nsize = ABS (nsize);
+ dsize = ABS (dsize);
+
+ /* Ensure space is enough for quotient. */
+
+ qsize = nsize - dsize + 1; /* qsize cannot be bigger than this. */
+ if (qsize <= 0)
+ {
+ quot->_mp_size = 0;
+ return;
+ }
+
+ if (quot->_mp_alloc < qsize)
+ _mpz_realloc (quot, qsize);
+
+ qp = quot->_mp_d;
+ np = num->_mp_d;
+ dp = den->_mp_d;
+
+ /* Optimize division by a single-limb divisor. */
+ if (dsize == 1)
+ {
+ mpn_divmod_1 (qp, np, nsize, dp[0]);
+ qsize -= qp[qsize - 1] == 0;
+ quot->_mp_size = sign_quotient >= 0 ? qsize : -qsize;
+ return;
+ }
+
+ TMP_MARK (marker);
+
+ rp = (mp_ptr) TMP_ALLOC ((nsize + 1) * BYTES_PER_MP_LIMB);
+
+ count_leading_zeros (normalization_steps, dp[dsize - 1]);
+
+ /* Normalize the denominator, i.e. make its most significant bit set by
+ shifting it NORMALIZATION_STEPS bits to the left. Also shift the
+ numerator the same number of steps (to keep the quotient the same!). */
+ if (normalization_steps != 0)
+ {
+ mp_ptr tp;
+ mp_limb_t nlimb;
+
+ /* Shift up the denominator setting the most significant bit of
+ the most significant word. Use temporary storage not to clobber
+ the original contents of the denominator. */
+ tp = (mp_ptr) TMP_ALLOC (dsize * BYTES_PER_MP_LIMB);
+ mpn_lshift (tp, dp, dsize, normalization_steps);
+ dp = tp;
+
+ /* Shift up the numerator, possibly introducing a new most
+ significant word. Move the shifted numerator in the remainder
+ meanwhile. */
+ nlimb = mpn_lshift (rp, np, nsize, normalization_steps);
+ if (nlimb != 0)
+ {
+ rp[nsize] = nlimb;
+ rsize = nsize + 1;
+ }
+ else
+ rsize = nsize;
+ }
+ else
+ {
+ /* The denominator is already normalized, as required. Copy it to
+ temporary space if it overlaps with the quotient. */
+ if (dp == qp)
+ {
+ dp = (mp_ptr) TMP_ALLOC (dsize * BYTES_PER_MP_LIMB);
+ MPN_COPY ((mp_ptr) dp, qp, dsize);
+ }
+
+ /* Move the numerator to the remainder. */
+ MPN_COPY (rp, np, nsize);
+ rsize = nsize;
+ }
+
+ q_limb = mpn_divmod (qp, rp, rsize, dp, dsize);
+
+ qsize = rsize - dsize;
+ if (q_limb)
+ {
+ qp[qsize] = q_limb;
+ qsize += 1;
+ }
+
+ quot->_mp_size = sign_quotient >= 0 ? qsize : -qsize;
+ TMP_FREE (marker);
+}
diff --git a/mpz/tdiv_q_2exp.c b/mpz/tdiv_q_2exp.c
new file mode 100644
index 000000000..e70d810e7
--- /dev/null
+++ b/mpz/tdiv_q_2exp.c
@@ -0,0 +1,68 @@
+/* mpz_tdiv_q_2exp -- Divide an integer by 2**CNT. Round the quotient
+ towards -infinity.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_tdiv_q_2exp (mpz_ptr w, mpz_srcptr u, unsigned long int cnt)
+#else
+mpz_tdiv_q_2exp (w, u, cnt)
+ mpz_ptr w;
+ mpz_srcptr u;
+ unsigned long int cnt;
+#endif
+{
+ mp_size_t usize, wsize;
+ mp_size_t limb_cnt;
+
+ usize = u->_mp_size;
+ limb_cnt = cnt / BITS_PER_MP_LIMB;
+ wsize = ABS (usize) - limb_cnt;
+ if (wsize <= 0)
+ w->_mp_size = 0;
+ else
+ {
+ mp_ptr wp;
+ mp_srcptr up;
+
+ if (w->_mp_alloc < wsize)
+ _mpz_realloc (w, wsize);
+
+ wp = w->_mp_d;
+ up = u->_mp_d;
+
+ cnt %= BITS_PER_MP_LIMB;
+ if (cnt != 0)
+ {
+ mpn_rshift (wp, up + limb_cnt, wsize, cnt);
+ wsize -= wp[wsize - 1] == 0;
+ }
+ else
+ {
+ MPN_COPY_INCR (wp, up + limb_cnt, wsize);
+ }
+
+ w->_mp_size = usize >= 0 ? wsize : -wsize;
+ }
+}
diff --git a/mpz/tdiv_q_ui.c b/mpz/tdiv_q_ui.c
new file mode 100644
index 000000000..9048e0aef
--- /dev/null
+++ b/mpz/tdiv_q_ui.c
@@ -0,0 +1,63 @@
+/* mpz_tdiv_q_ui(quot, dividend, divisor_limb)
+ -- Divide DIVIDEND by DIVISOR_LIMB and store the result in QUOT.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_tdiv_q_ui (mpz_ptr quot, mpz_srcptr dividend, unsigned long int divisor)
+#else
+mpz_tdiv_q_ui (quot, dividend, divisor)
+ mpz_ptr quot;
+ mpz_srcptr dividend;
+ unsigned long int divisor;
+#endif
+{
+ mp_size_t dividend_size;
+ mp_size_t size;
+ mp_ptr quot_ptr;
+
+ dividend_size = dividend->_mp_size;
+ size = ABS (dividend_size);
+
+ if (size == 0)
+ {
+ quot->_mp_size = 0;
+ return;
+ }
+
+ /* No need for temporary allocation and copying if QUOT == DIVIDEND as
+ the divisor is just one limb, and thus no intermediate remainders
+ need to be stored. */
+
+ if (quot->_mp_alloc < size)
+ _mpz_realloc (quot, size);
+
+ quot_ptr = quot->_mp_d;
+
+ mpn_divmod_1 (quot_ptr, dividend->_mp_d, size, (mp_limb_t) divisor);
+
+ /* The quotient is SIZE limbs, but the most significant might be zero. */
+ size -= quot_ptr[size - 1] == 0;
+ quot->_mp_size = dividend_size >= 0 ? size : -size;
+}
diff --git a/mpz/tdiv_qr.c b/mpz/tdiv_qr.c
new file mode 100644
index 000000000..500e19939
--- /dev/null
+++ b/mpz/tdiv_qr.c
@@ -0,0 +1,39 @@
+/* mpz_tdiv_qr(quot,rem,dividend,divisor) -- Set QUOT to DIVIDEND/DIVISOR,
+ and REM to DIVIDEND mod DIVISOR.
+
+Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+void
+#if __STDC__
+mpz_tdiv_qr (mpz_ptr quot, mpz_ptr rem, mpz_srcptr num, mpz_srcptr den)
+#else
+mpz_tdiv_qr (quot, rem, num, den)
+ mpz_ptr quot;
+ mpz_ptr rem;
+ mpz_srcptr num;
+ mpz_srcptr den;
+#endif
+
+#define COMPUTE_QUOTIENT
+#include "dmincl.c"
diff --git a/mpz/tdiv_qr_ui.c b/mpz/tdiv_qr_ui.c
new file mode 100644
index 000000000..cb5041cdc
--- /dev/null
+++ b/mpz/tdiv_qr_ui.c
@@ -0,0 +1,78 @@
+/* mpz_tdiv_qr_ui(quot,rem,dividend,short_divisor) --
+ Set QUOT to DIVIDEND / SHORT_DIVISOR
+ and REM to DIVIDEND mod SHORT_DIVISOR.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_tdiv_qr_ui (mpz_ptr quot, mpz_ptr rem, mpz_srcptr dividend, unsigned long int divisor)
+#else
+mpz_tdiv_qr_ui (quot, rem, dividend, divisor)
+ mpz_ptr quot;
+ mpz_ptr rem;
+ mpz_srcptr dividend;
+ unsigned long int divisor;
+#endif
+{
+ mp_size_t dividend_size;
+ mp_size_t size;
+ mp_ptr quot_ptr;
+ mp_limb_t remainder_limb;
+
+ dividend_size = dividend->_mp_size;
+ size = ABS (dividend_size);
+
+ if (size == 0)
+ {
+ quot->_mp_size = 0;
+ rem->_mp_size = 0;
+ return;
+ }
+
+ /* No need for temporary allocation and copying if QUOT == DIVIDEND as
+ the divisor is just one limb, and thus no intermediate remainders
+ need to be stored. */
+
+ if (quot->_mp_alloc < size)
+ _mpz_realloc (quot, size);
+
+ quot_ptr = quot->_mp_d;
+
+ remainder_limb = mpn_divmod_1 (quot_ptr, dividend->_mp_d, size,
+ (mp_limb_t) divisor);
+
+ if (remainder_limb == 0)
+ rem->_mp_size = 0;
+ else
+ {
+ /* Store the single-limb remainder. We don't check if there's space
+ for just one limb, since no function ever makes zero space. */
+ rem->_mp_size = dividend_size >= 0 ? 1 : -1;
+ rem->_mp_d[0] = remainder_limb;
+ }
+
+ /* The quotient is SIZE limbs, but the most significant might be zero. */
+ size -= quot_ptr[size - 1] == 0;
+ quot->_mp_size = dividend_size >= 0 ? size : -size;
+}
diff --git a/mpz/tdiv_r.c b/mpz/tdiv_r.c
new file mode 100644
index 000000000..813a0d4d7
--- /dev/null
+++ b/mpz/tdiv_r.c
@@ -0,0 +1,37 @@
+/* mpz_tdiv_r(rem, dividend, divisor) -- Set REM to DIVIDEND mod DIVISOR.
+
+Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+void
+#if __STDC__
+mpz_tdiv_r (mpz_ptr rem, mpz_srcptr num, mpz_srcptr den)
+#else
+mpz_tdiv_r (rem, num, den)
+ mpz_ptr rem;
+ mpz_srcptr num;
+ mpz_srcptr den;
+#endif
+
+#undef COMPUTE_QUOTIENT
+#include "dmincl.c"
diff --git a/mpz/tdiv_r_2exp.c b/mpz/tdiv_r_2exp.c
new file mode 100644
index 000000000..99d617e9f
--- /dev/null
+++ b/mpz/tdiv_r_2exp.c
@@ -0,0 +1,79 @@
+/* mpz_tdiv_r_2exp -- Divide a integer by 2**CNT and produce a remainder.
+
+Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_tdiv_r_2exp (mpz_ptr res, mpz_srcptr in, unsigned long int cnt)
+#else
+mpz_tdiv_r_2exp (res, in, cnt)
+ mpz_ptr res;
+ mpz_srcptr in;
+ unsigned long int cnt;
+#endif
+{
+ mp_size_t in_size = ABS (in->_mp_size);
+ mp_size_t res_size;
+ mp_size_t limb_cnt = cnt / BITS_PER_MP_LIMB;
+ mp_srcptr in_ptr = in->_mp_d;
+
+ if (in_size > limb_cnt)
+ {
+ /* The input operand is (probably) greater than 2**CNT. */
+ mp_limb_t x;
+
+ x = in_ptr[limb_cnt] & (((mp_limb_t) 1 << cnt % BITS_PER_MP_LIMB) - 1);
+ if (x != 0)
+ {
+ res_size = limb_cnt + 1;
+ if (res->_mp_alloc < res_size)
+ _mpz_realloc (res, res_size);
+
+ res->_mp_d[limb_cnt] = x;
+ }
+ else
+ {
+ res_size = limb_cnt;
+ MPN_NORMALIZE (in_ptr, res_size);
+
+ if (res->_mp_alloc < res_size)
+ _mpz_realloc (res, res_size);
+
+ limb_cnt = res_size;
+ }
+ }
+ else
+ {
+ /* The input operand is smaller than 2**CNT. We perform a no-op,
+ apart from that we might need to copy IN to RES. */
+ res_size = in_size;
+ if (res->_mp_alloc < res_size)
+ _mpz_realloc (res, res_size);
+
+ limb_cnt = res_size;
+ }
+
+ if (res != in)
+ MPN_COPY (res->_mp_d, in->_mp_d, limb_cnt);
+ res->_mp_size = in->_mp_size >= 0 ? res_size : -res_size;
+}
diff --git a/mpz/tdiv_r_ui.c b/mpz/tdiv_r_ui.c
new file mode 100644
index 000000000..0428b52c3
--- /dev/null
+++ b/mpz/tdiv_r_ui.c
@@ -0,0 +1,64 @@
+/* mpz_tdiv_r_ui(rem, dividend, divisor_limb)
+ -- Set REM to DIVDEND mod DIVISOR_LIMB.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+
+void
+#if __STDC__
+mpz_tdiv_r_ui (mpz_ptr rem, mpz_srcptr dividend, unsigned long int divisor)
+#else
+mpz_tdiv_r_ui (rem, dividend, divisor)
+ mpz_ptr rem;
+ mpz_srcptr dividend;
+ unsigned long int divisor;
+#endif
+{
+ mp_size_t dividend_size;
+ mp_size_t size;
+ mp_limb_t remainder_limb;
+
+ dividend_size = dividend->_mp_size;
+ size = ABS (dividend_size);
+
+ if (size == 0)
+ {
+ rem->_mp_size = 0;
+ return;
+ }
+
+ /* No need for temporary allocation and copying if QUOT == DIVIDEND as
+ the divisor is just one limb, and thus no intermediate remainders
+ need to be stored. */
+
+ remainder_limb = mpn_mod_1 (dividend->_mp_d, size, (mp_limb_t) divisor);
+
+ if (remainder_limb == 0)
+ rem->_mp_size = 0;
+ else
+ {
+ /* Store the single-limb remainder. We don't check if there's space
+ for just one limb, since no function ever makes zero space. */
+ rem->_mp_size = dividend_size >= 0 ? 1 : -1;
+ rem->_mp_d[0] = remainder_limb;
+ }
+}
diff --git a/mpz/tests/Makefile.in b/mpz/tests/Makefile.in
new file mode 100644
index 000000000..b2ac9a18b
--- /dev/null
+++ b/mpz/tests/Makefile.in
@@ -0,0 +1,126 @@
+# Makefile for mpz/tests for GNU MP
+
+srcdir = .
+
+CC = gcc
+
+TEST_LIBS = ../../libgmp.a
+INCLUDES = -I../../mpn -I$(srcdir)/../..
+CFLAGS = -g -O
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(XCFLAGS) $<
+
+TEST_SRCS = t-mul.c t-tdiv.c t-tdiv_ui.c t-fdiv.c t-fdiv_ui.c t-gcd.c \
+ t-gcd2.c dive.c t-sqrtrem.c convert.c io.c logic.c t-powm.c t-powm_ui.c \
+ reuse.c
+TEST_OBJS = t-mul.o t-tdiv.o t-tdiv_ui.o t-fdiv.o t-fdiv_ui.o t-gcd.o \
+ t-gcd2.o dive.o t-sqrtrem.o convert.o io.o logic.o t-powm.o t-powm_ui.o \
+ reuse.o
+TESTS = t-mul t-tdiv t-tdiv_ui t-fdiv t-fdiv_ui t-gcd t-gcd2 \
+ dive t-sqrtrem convert io logic t-powm t-powm_ui reuse
+
+check: st-mul st-tdiv st-tdiv_ui st-fdiv st-fdiv_ui st-gcd st-gcd2 st-dive \
+ st-sqrtrem st-convert st-io st-logic st-powm st-powm_ui st-reuse
+ @echo "The tests passed."
+
+st-mul: t-mul
+ ./t-mul
+ touch $@
+st-tdiv: t-tdiv
+ ./t-tdiv
+ touch $@
+st-tdiv_ui: t-tdiv_ui
+ ./t-tdiv_ui
+ touch $@
+st-fdiv: t-fdiv
+ ./t-fdiv
+ touch $@
+st-fdiv_ui: t-fdiv_ui
+ ./t-fdiv_ui
+ touch $@
+st-gcd: t-gcd
+ ./t-gcd
+ touch $@
+st-gcd2: t-gcd2
+ ./t-gcd2
+ touch $@
+st-dive: dive
+ ./dive
+ touch $@
+st-sqrtrem: t-sqrtrem
+ ./t-sqrtrem
+ touch $@
+st-convert: convert
+ ./convert
+ touch $@
+st-io: io
+ ./io
+ touch $@
+st-logic: logic
+ ./logic
+ touch $@
+st-powm: t-powm
+ ./t-powm
+ touch $@
+st-powm_ui: t-powm_ui
+ ./t-powm_ui
+ touch $@
+st-reuse: reuse
+ ./reuse
+ touch $@
+
+t-mul: t-mul.o $(TEST_LIBS)
+ $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+t-tdiv: t-tdiv.o $(TEST_LIBS)
+ $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+t-tdiv_ui: t-tdiv_ui.o $(TEST_LIBS)
+ $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+t-fdiv: t-fdiv.o $(TEST_LIBS)
+ $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+t-fdiv_ui: t-fdiv_ui.o $(TEST_LIBS)
+ $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+t-gcd: t-gcd.o $(TEST_LIBS)
+ $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+t-gcd2: t-gcd2.o $(TEST_LIBS)
+ $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+dive: dive.o $(TEST_LIBS)
+ $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+t-sqrtrem: t-sqrtrem.o $(TEST_LIBS)
+ $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+convert: convert.o $(TEST_LIBS)
+ $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+io: io.o $(TEST_LIBS)
+ $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+logic: logic.o $(TEST_LIBS)
+ $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+t-powm: t-powm.o $(TEST_LIBS)
+ $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+t-powm_ui: t-powm_ui.o $(TEST_LIBS)
+ $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+reuse: reuse.o $(TEST_LIBS)
+ $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+
+t-mul.o: $(srcdir)/t-mul.c
+t-tdiv.o: $(srcdir)/t-tdiv.c
+t-tdiv_ui.o: $(srcdir)/t-tdiv_ui.c
+t-fdiv.o: $(srcdir)/t-fdiv.c
+t-fdiv_ui.o: $(srcdir)/t-fdiv_ui.c
+t-gcd.o: $(srcdir)/t-gcd.c
+t-gcd2.o: $(srcdir)/t-gcd2.c
+dive.o: $(srcdir)/dive.c
+t-sqrtrem.o: $(srcdir)/t-sqrtrem.c
+convert.o: $(srcdir)/convert.c
+io.o: $(srcdir)/io.c
+logic.o: $(srcdir)/logic.c
+t-powm.o: $(srcdir)/t-powm.c
+t-powm_ui.o: $(srcdir)/t-powm_ui.c
+reuse.o: $(srcdir)/reuse.c
+
+clean mostlyclean:
+ rm -f *.o st-* $(TESTS)
+distclean maintainer-clean: clean
+ rm -f Makefile config.status
+
+Makefile: $(srcdir)/Makefile.in
+ $(SHELL) ./config.status
diff --git a/mpz/tests/configure.in b/mpz/tests/configure.in
new file mode 100644
index 000000000..dacc17741
--- /dev/null
+++ b/mpz/tests/configure.in
@@ -0,0 +1,11 @@
+# This file is a shell script that supplies the information necessary
+# to tailor a template configure script into the configure script
+# appropriate for this directory. For more information, check any
+# existing configure script.
+
+srctrigger=t-mul.c
+srcname="gmp/mpz/tests"
+
+# per-host:
+
+# per-target:
diff --git a/mpz/tests/convert.c b/mpz/tests/convert.c
new file mode 100644
index 000000000..1d8237099
--- /dev/null
+++ b/mpz/tests/convert.c
@@ -0,0 +1,80 @@
+/* Test conversion using mpz_get_str and mpz_set_str.
+
+Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+void debug_mp ();
+
+#ifndef SIZE
+#define SIZE 32
+#endif
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ MP_INT op1, op2;
+ mp_size_t size;
+ int i;
+ int reps = 100000;
+ char *str;
+ int base;
+
+ if (argc == 2)
+ reps = atoi (argv[1]);
+
+ mpz_init (&op1);
+ mpz_init (&op2);
+
+ for (i = 0; i < reps; i++)
+ {
+ size = urandom () % SIZE - SIZE/2;
+
+ mpz_random2 (&op1, size);
+ base = urandom () % 36 + 1;
+ if (base == 1)
+ base = 0;
+
+ str = mpz_get_str ((char *) 0, base, &op1);
+ mpz_set_str (&op2, str, base);
+ free (str);
+
+ if (mpz_cmp (&op1, &op2))
+ {
+ fprintf (stderr, "ERROR\n");
+ fprintf (stderr, "op1 = "); debug_mp (&op1, -16);
+ fprintf (stderr, "base = %d\n", base);
+ abort ();
+ }
+ }
+
+ exit (0);
+}
+
+void
+debug_mp (x, base)
+ MP_INT *x;
+{
+ mpz_out_str (stderr, base, x); fputc ('\n', stderr);
+}
diff --git a/mpz/tests/dive.c b/mpz/tests/dive.c
new file mode 100644
index 000000000..8d3516d83
--- /dev/null
+++ b/mpz/tests/dive.c
@@ -0,0 +1,87 @@
+/* Test mpz_mul, mpz_divexact.
+
+Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+void debug_mp ();
+
+#ifndef SIZE
+#define SIZE 32
+#endif
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ mpz_t op1, op2;
+ mpz_t prod, quot;
+ mp_size_t size;
+ int i;
+ int reps = 100000;
+
+ if (argc == 2)
+ reps = atoi (argv[1]);
+
+ mpz_init (op1);
+ mpz_init (op2);
+ mpz_init (prod);
+ mpz_init (quot);
+
+ for (i = 0; i < reps; i++)
+ {
+ size = urandom () % SIZE - SIZE/2;
+ mpz_random2 (op1, size);
+
+ do
+ {
+ size = urandom () % SIZE - SIZE/2;
+ mpz_random2 (op2, size);
+ }
+ while (mpz_cmp_ui (op2, 0) == 0);
+
+ mpz_mul (prod, op1, op2);
+
+ mpz_divexact (quot, prod, op2);
+ if (mpz_cmp (quot, op1) != 0)
+ dump_abort (quot, op1);
+ }
+
+ exit (0);
+}
+
+dump_abort (op1, op2)
+ mpz_t op1, op2;
+{
+ fprintf (stderr, "ERROR\n");
+ fprintf (stderr, "ref = "); debug_mp (op1, -16);
+ fprintf (stderr, "wrong = "); debug_mp (op2, -16);
+ abort();
+}
+
+void
+debug_mp (x, base)
+ mpz_t x;
+{
+ mpz_out_str (stderr, base, x); fputc ('\n', stderr);
+}
diff --git a/mpz/tests/io-binary.c b/mpz/tests/io-binary.c
new file mode 100644
index 000000000..c28f2a5ba
--- /dev/null
+++ b/mpz/tests/io-binary.c
@@ -0,0 +1,76 @@
+/* Test mpz_inp_binary and mpz_out_binary.
+
+ We write and read back some test strings, and both compare
+ the numerical result, and make sure the pattern on file is
+ what we expect. The latter is important for compatibility
+ between machines with different word sizes. */
+
+#include <stdio.h>
+#include "gmp.h"
+
+FILE *file;
+
+test (str, binary_len, binary_str)
+ char *str;
+ int binary_len;
+ char *binary_str;
+{
+ mpz_t x, y;
+ int n_written;
+ char buf[100];
+
+ mpz_init_set_str (x, str, 0);
+ mpz_init (y);
+
+ fseek (file, 0, SEEK_SET);
+ mpz_out_binary (file, x);
+ n_written = ftell (file);
+ if (n_written != binary_len)
+ abort ();
+
+ fseek (file, 0, SEEK_SET);
+ mpz_inp_binary (y, file);
+ if (n_written != ftell (file))
+ abort ();
+ if (mpz_cmp (x, y) != 0)
+ abort ();
+
+ fseek (file, 0, SEEK_SET);
+ fread (buf, n_written, 1, file);
+ if (memcmp (buf, binary_str, binary_len) != 0)
+ abort ();
+
+ mpz_clear (x);
+}
+
+main ()
+{
+ file = fopen ("xtmpfile", "w+");
+
+ test ("0", 4,
+ "\000\000\000\000");
+
+ test ("1", 5,
+ "\000\000\000\001\001");
+ test ("0x123", 6,
+ "\000\000\000\002\001\043");
+ test ("0xdeadbeef", 8,
+ "\000\000\000\004\336\255\276\357");
+ test ("0xbabefaced", 9,
+ "\000\000\000\005\013\253\357\254\355");
+ test ("0x123456789facade0", 12,
+ "\000\000\000\010\022\064\126\170\237\254\255\340");
+
+ test ("-1", 5,
+ "\377\377\377\377\001");
+ test ("-0x123", 6,
+ "\377\377\377\376\001\043");
+ test ("-0xdeadbeef", 8,
+ "\377\377\377\374\336\255\276\357");
+ test ("-0xbabefaced", 9,
+ "\377\377\377\373\013\253\357\254\355");
+ test ("-0x123456789facade0", 12,
+ "\377\377\377\370\022\064\126\170\237\254\255\340");
+
+ exit (0);
+}
diff --git a/mpz/tests/io.c b/mpz/tests/io.c
new file mode 100644
index 000000000..3dfa9a569
--- /dev/null
+++ b/mpz/tests/io.c
@@ -0,0 +1,86 @@
+/* Test conversion and I/O using mpz_out_str and mpz_inp_str.
+
+Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+void debug_mp ();
+
+#ifndef SIZE
+#define SIZE 16
+#endif
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ MP_INT op1, op2;
+ mp_size_t size;
+ int i;
+ int reps = 10000;
+ FILE *fsin, *fsout;
+ int fd[2];
+ int base;
+
+ if (argc == 2)
+ reps = atoi (argv[1]);
+
+ mpz_init (&op1);
+ mpz_init (&op2);
+
+ pipe (fd);
+ fsin = fdopen (fd[0], "r");
+ fsout = fdopen (fd[1], "w");
+
+ for (i = 0; i < reps; i++)
+ {
+ size = urandom () % SIZE - SIZE/2;
+
+ mpz_random2 (&op1, size);
+ base = urandom () % 36 + 1;
+ if (base == 1)
+ base = 0;
+
+ mpz_out_str (fsout, base, &op1);
+ putc (' ', fsout);
+ fflush (fsout);
+ mpz_inp_str (&op2, fsin, base);
+
+ if (mpz_cmp (&op1, &op2))
+ {
+ fprintf (stderr, "ERROR\n");
+ fprintf (stderr, "op1 = "); debug_mp (&op1, -16);
+ fprintf (stderr, "base = %d\n", base);
+ abort ();
+ }
+ }
+
+ exit (0);
+}
+
+void
+debug_mp (x, base)
+ MP_INT *x;
+{
+ mpz_out_str (stderr, base, x); fputc ('\n', stderr);
+}
diff --git a/mpz/tests/logic.c b/mpz/tests/logic.c
new file mode 100644
index 000000000..9021e43ea
--- /dev/null
+++ b/mpz/tests/logic.c
@@ -0,0 +1,103 @@
+/* Test mpz_com, mpz_and, and mpz_ior.
+
+Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+void debug_mp ();
+
+#ifndef SIZE
+#define SIZE 16
+#endif
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ mpz_t x, y, r1, r2;
+ mpz_t t1, t2, t3, t4;
+ mp_size_t xsize, ysize;
+ int i;
+ int reps = 100000;
+
+ if (argc == 2)
+ reps = atoi (argv[1]);
+
+ mpz_init (x);
+ mpz_init (y);
+ mpz_init (r1);
+ mpz_init (r2);
+ mpz_init (t1);
+ mpz_init (t2);
+ mpz_init (t3);
+ mpz_init (t4);
+
+ for (i = 0; i < reps; i++)
+ {
+ xsize = urandom () % SIZE - SIZE/2;
+ mpz_random2 (x, xsize);
+
+ ysize = urandom () % SIZE - SIZE/2;
+ mpz_random2 (y, ysize);
+
+ mpz_com (r1, x);
+ mpz_com (r1, r1);
+ if (mpz_cmp (r1, x) != 0)
+ dump_abort ();
+
+ mpz_com (r1, y);
+ mpz_com (r2, r1);
+ if (mpz_cmp (r2, y) != 0)
+ dump_abort ();
+
+ mpz_com (t1, x);
+ mpz_com (t2, y);
+ mpz_and (t3, t1, t2);
+ mpz_com (r1, t3);
+ mpz_ior (r2, x, y);
+ if (mpz_cmp (r1, r2) != 0)
+ dump_abort ();
+
+ mpz_com (t1, x);
+ mpz_com (t2, y);
+ mpz_ior (t3, t1, t2);
+ mpz_com (r1, t3);
+ mpz_and (r2, x, y);
+ if (mpz_cmp (r1, r2) != 0)
+ dump_abort ();
+ }
+
+ exit (0);
+}
+
+dump_abort ()
+{
+ abort();
+}
+
+void
+debug_mp (x, base)
+ MP_INT *x;
+{
+ mpz_out_str (stderr, base, x); fputc ('\n', stderr);
+}
diff --git a/mpz/tests/reuse.c b/mpz/tests/reuse.c
new file mode 100644
index 000000000..f9953c17d
--- /dev/null
+++ b/mpz/tests/reuse.c
@@ -0,0 +1,126 @@
+/* Test that routines allow reusing a source variable as destination. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+#ifndef SIZE
+#define SIZE 16
+#endif
+
+typedef void (*dss_func) (mpz_ptr, mpz_srcptr, mpz_srcptr);
+
+dss_func dss_funcs[] =
+{
+ mpz_add, mpz_and, mpz_cdiv_q, mpz_cdiv_r, mpz_fdiv_q, mpz_fdiv_r,
+ mpz_gcd, mpz_ior, mpz_mul, mpz_sub, mpz_tdiv_q, mpz_tdiv_r
+};
+
+char *dss_func_names[] =
+{
+ "mpz_add", "mpz_and", "mpz_cdiv_q", "mpz_cdiv_r", "mpz_fdiv_q", "mpz_fdiv_r",
+ "mpz_gcd", "mpz_ior", "mpz_mul", "mpz_sub", "mpz_tdiv_q", "mpz_tdiv_r"
+};
+
+char dss_func_division[] = {0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1};
+
+#if 0
+mpz_divexact /* requires special operands */
+#endif
+
+main ()
+{
+ int i;
+ int pass, reps = 10000;
+ mpz_t in1, in2, out1;
+ mpz_t res1, res2, res3;
+
+ mpz_init (in1);
+ mpz_init (in2);
+ mpz_init (out1);
+ mpz_init (res1);
+ mpz_init (res2);
+ mpz_init (res3);
+
+ for (pass = 1; pass <= reps; pass++)
+ {
+ mpz_random (in1, urandom () % SIZE - SIZE/2);
+ mpz_random (in2, urandom () % SIZE - SIZE/2);
+
+ for (i = 0; i < sizeof (dss_funcs) / sizeof (dss_func); i++)
+ {
+ if (dss_func_division[i] && mpz_cmp_ui (in2, 0) == 0)
+ continue;
+
+ (dss_funcs[i]) (res1, in1, in2);
+
+ mpz_set (out1, in1);
+ (dss_funcs[i]) (out1, out1, in2);
+ mpz_set (res2, out1);
+
+ mpz_set (out1, in2);
+ (dss_funcs[i]) (out1, in1, out1);
+ mpz_set (res3, out1);
+
+ if (mpz_cmp (res1, res2) != 0)
+ dump_abort (dss_func_names[i], in1, in2);
+ if (mpz_cmp (res1, res3) != 0)
+ dump_abort (dss_func_names[i], in1, in2);
+ }
+ }
+
+ exit (0);
+}
+
+dump_abort (name, in1, in2)
+ char *name;
+ mpz_t in1, in2;
+{
+ printf ("failure in %s (", name);
+ mpz_out_str (stdout, -16, in1);
+ printf (" ");
+ mpz_out_str (stdout, -16, in2);
+ printf (")\n");
+ abort ();
+}
+
+#if 0
+void mpz_add_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_div_2exp _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_mod_2exp _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_mul_2exp _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_mul_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_pow_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_sub_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_tdiv_q_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_tdiv_r_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+
+void mpz_abs _PROTO ((mpz_ptr, mpz_srcptr));
+void mpz_com _PROTO ((mpz_ptr, mpz_srcptr));
+void mpz_sqrt _PROTO ((mpz_ptr, mpz_srcptr));
+void mpz_neg _PROTO ((mpz_ptr, mpz_srcptr));
+
+void mpz_tdiv_qr_ui _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int));
+
+void mpz_powm_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int, mpz_srcptr));
+
+void mpz_gcdext _PROTO ((mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr));
+
+void mpz_cdiv_qr _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr));
+void mpz_fdiv_qr _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr));
+void mpz_tdiv_qr _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr));
+
+void mpz_powm _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr));
+
+void mpz_sqrtrem _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr));
+
+unsigned long int mpz_cdiv_qr_ui _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int));
+unsigned long int mpz_fdiv_qr_ui _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int));
+
+unsigned long int mpz_cdiv_q_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+unsigned long int mpz_cdiv_r_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+unsigned long int mpz_fdiv_q_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+unsigned long int mpz_fdiv_r_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+unsigned long int mpz_gcd_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+#endif
diff --git a/mpz/tests/t-fdiv.c b/mpz/tests/t-fdiv.c
new file mode 100644
index 000000000..9de22d703
--- /dev/null
+++ b/mpz/tests/t-fdiv.c
@@ -0,0 +1,118 @@
+/* Test mpz_abs, mpz_add, mpz_cmp, mpz_cmp_ui, mpz_fdiv_qr, mpz_fdiv_q,
+ mpz_fdiv_r, mpz_mul.
+
+Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+void debug_mp ();
+
+#ifndef SIZE
+#define SIZE 16
+#endif
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ mpz_t dividend, divisor;
+ mpz_t quotient, remainder;
+ mpz_t quotient2, remainder2;
+ mpz_t temp;
+ mp_size_t dividend_size, divisor_size;
+ int i;
+ int reps = 100000;
+
+ if (argc == 2)
+ reps = atoi (argv[1]);
+
+ mpz_init (dividend);
+ mpz_init (divisor);
+ mpz_init (quotient);
+ mpz_init (remainder);
+ mpz_init (quotient2);
+ mpz_init (remainder2);
+ mpz_init (temp);
+
+ for (i = 0; i < reps; i++)
+ {
+ dividend_size = urandom () % SIZE - SIZE/2;
+ mpz_random2 (dividend, dividend_size);
+
+ divisor_size = urandom () % SIZE - SIZE/2;
+ mpz_random2 (divisor, divisor_size);
+ if (mpz_cmp_ui (divisor, 0) == 0)
+ continue;
+
+ mpz_fdiv_qr (quotient, remainder, dividend, divisor);
+ mpz_fdiv_q (quotient2, dividend, divisor);
+ mpz_fdiv_r (remainder2, dividend, divisor);
+
+ /* First determine that the quotients and remainders computed
+ with different functions are equal. */
+ if (mpz_cmp (quotient, quotient2) != 0)
+ dump_abort (dividend, divisor);
+ if (mpz_cmp (remainder, remainder2) != 0)
+ dump_abort (dividend, divisor);
+
+ /* Check if the sign of the quotient is correct. */
+ if (mpz_cmp_ui (quotient, 0) != 0)
+ if ((mpz_cmp_ui (quotient, 0) < 0)
+ != ((mpz_cmp_ui (dividend, 0) ^ mpz_cmp_ui (divisor, 0)) < 0))
+ dump_abort (dividend, divisor);
+
+ /* Check if the remainder has the same sign as the divisor
+ (quotient rounded towards minus infinity). */
+ if (mpz_cmp_ui (remainder, 0) != 0)
+ if ((mpz_cmp_ui (remainder, 0) < 0) != (mpz_cmp_ui (divisor, 0) < 0))
+ dump_abort (dividend, divisor);
+
+ mpz_mul (temp, quotient, divisor);
+ mpz_add (temp, temp, remainder);
+ if (mpz_cmp (temp, dividend) != 0)
+ dump_abort (dividend, divisor);
+
+ mpz_abs (temp, divisor);
+ mpz_abs (remainder, remainder);
+ if (mpz_cmp (remainder, temp) >= 0)
+ dump_abort (dividend, divisor);
+ }
+
+ exit (0);
+}
+
+dump_abort (dividend, divisor)
+ mpz_t dividend, divisor;
+{
+ fprintf (stderr, "ERROR\n");
+ fprintf (stderr, "dividend = "); debug_mp (dividend, -16);
+ fprintf (stderr, "divisor = "); debug_mp (divisor, -16);
+ abort();
+}
+
+void
+debug_mp (x, base)
+ mpz_t x;
+{
+ mpz_out_str (stderr, base, x); fputc ('\n', stderr);
+}
diff --git a/mpz/tests/t-fdiv_ui.c b/mpz/tests/t-fdiv_ui.c
new file mode 100644
index 000000000..74ba9fcf7
--- /dev/null
+++ b/mpz/tests/t-fdiv_ui.c
@@ -0,0 +1,117 @@
+/* Test mpz_abs, mpz_add, mpz_cmp, mpz_cmp_ui, mpz_fdiv_qr_ui, mpz_fdiv_q_ui,
+ mpz_fdiv_r_ui, mpz_mul, mpz_mul_ui.
+
+Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+void debug_mp ();
+
+#ifndef SIZE
+#define SIZE 16
+#endif
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ mpz_t dividend;
+ mpz_t quotient, remainder;
+ mpz_t quotient2, remainder2;
+ mpz_t temp;
+ mp_size_t dividend_size;
+ mp_limb_t divisor;
+ int i;
+ int reps = 100000;
+
+ if (argc == 2)
+ reps = atoi (argv[1]);
+
+ mpz_init (dividend);
+ mpz_init (quotient);
+ mpz_init (remainder);
+ mpz_init (quotient2);
+ mpz_init (remainder2);
+ mpz_init (temp);
+
+ for (i = 0; i < reps; i++)
+ {
+ dividend_size = urandom () % SIZE - SIZE/2;
+ mpz_random2 (dividend, dividend_size);
+
+ divisor = urandom ();
+ if (divisor == 0)
+ continue;
+
+ mpz_fdiv_qr_ui (quotient, remainder, dividend, divisor);
+ mpz_fdiv_q_ui (quotient2, dividend, divisor);
+ mpz_fdiv_r_ui (remainder2, dividend, divisor);
+
+ /* First determine that the quotients and remainders computed
+ with different functions are equal. */
+ if (mpz_cmp (quotient, quotient2) != 0)
+ dump_abort (dividend, divisor);
+ if (mpz_cmp (remainder, remainder2) != 0)
+ dump_abort (dividend, divisor);
+
+ /* Check if the sign of the quotient is correct. */
+ if (mpz_cmp_ui (quotient, 0) != 0)
+ if ((mpz_cmp_ui (quotient, 0) < 0)
+ != (mpz_cmp_ui (dividend, 0) < 0))
+ dump_abort (dividend, divisor);
+
+ /* Check if the remainder has the same sign as the divisor
+ (quotient rounded towards minus infinity). */
+ if (mpz_cmp_ui (remainder, 0) != 0)
+ if (mpz_cmp_ui (remainder, 0) < 0)
+ dump_abort (dividend, divisor);
+
+ mpz_mul_ui (temp, quotient, divisor);
+ mpz_add (temp, temp, remainder);
+ if (mpz_cmp (temp, dividend) != 0)
+ dump_abort (dividend, divisor);
+
+ mpz_abs (remainder, remainder);
+ if (mpz_cmp_ui (remainder, divisor) >= 0)
+ dump_abort (dividend, divisor);
+ }
+
+ exit (0);
+}
+
+dump_abort (dividend, divisor)
+ mpz_t dividend;
+ mp_limb_t divisor;
+{
+ fprintf (stderr, "ERROR\n");
+ fprintf (stderr, "dividend = "); debug_mp (dividend, -16);
+ fprintf (stderr, "divisor = %lX\n", divisor);
+ abort();
+}
+
+void
+debug_mp (x, base)
+ mpz_t x;
+{
+ mpz_out_str (stderr, base, x); fputc ('\n', stderr);
+}
diff --git a/mpz/tests/t-gcd2.c b/mpz/tests/t-gcd2.c
new file mode 100644
index 000000000..b7ad67c03
--- /dev/null
+++ b/mpz/tests/t-gcd2.c
@@ -0,0 +1,137 @@
+/* Test mpz_gcd, mpz_gcdext, mpz_mul, mpz_tdiv_r, mpz_add, mpz_cmp,
+ mpz_cmp_ui, mpz_init_set, mpz_set, mpz_clear.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+void mpz_refgcd (), debug_mp ();
+
+#ifndef SIZE
+#define SIZE 128
+#endif
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ mpz_t op1, op2, x;
+ mpz_t refgcd, gcd, s, t;
+ mpz_t temp1, temp2;
+ mp_size_t op1_size, op2_size, x_size;
+ int i;
+ int reps = 1000;
+
+ if (argc == 2)
+ reps = atoi (argv[1]);
+
+ mpz_init (op1);
+ mpz_init (op2);
+ mpz_init (x);
+ mpz_init (refgcd);
+ mpz_init (gcd);
+ mpz_init (temp1);
+ mpz_init (temp2);
+ mpz_init (s);
+ mpz_init (t);
+
+ for (i = 0; i < reps; i++)
+ {
+ op1_size = urandom () % SIZE - SIZE/2;
+ op2_size = urandom () % SIZE - SIZE/2;
+ x_size = urandom () % SIZE/2;
+
+ mpz_random2 (op1, op1_size);
+ mpz_random2 (op2, op2_size);
+ mpz_random2 (x, x_size);
+ mpz_mul (op1, op1, x);
+ mpz_mul (op2, op2, x);
+
+ mpz_refgcd (refgcd, op1, op2);
+
+ mpz_gcd (gcd, op1, op2);
+ if (mpz_cmp (refgcd, gcd))
+ dump_abort (op1, op2);
+
+ mpz_gcdext (gcd, s, t, op1, op2);
+ if (mpz_cmp (refgcd, gcd))
+ dump_abort (op1, op2);
+
+ mpz_mul (temp1, s, op1);
+ mpz_mul (temp2, t, op2);
+ mpz_add (gcd, temp1, temp2);
+ if (mpz_cmp (refgcd, gcd))
+ dump_abort (op1, op2);
+ }
+
+ exit (0);
+}
+
+void
+mpz_refgcd (g, x, y)
+ mpz_t g;
+ mpz_t x, y;
+{
+ mpz_t xx, yy;
+
+ mpz_init (xx);
+ mpz_init (yy);
+
+ mpz_abs (xx, x);
+ mpz_abs (yy, y);
+
+ for (;;)
+ {
+ if (mpz_cmp_ui (yy, 0) == 0)
+ {
+ mpz_set (g, xx);
+ break;
+ }
+ mpz_tdiv_r (xx, xx, yy);
+ if (mpz_cmp_ui (xx, 0) == 0)
+ {
+ mpz_set (g, yy);
+ break;
+ }
+ mpz_tdiv_r (yy, yy, xx);
+ }
+
+ mpz_clear (xx);
+ mpz_clear (yy);
+}
+
+dump_abort (op1, op2)
+ mpz_t op1, op2;
+{
+ fprintf (stderr, "ERROR\n");
+ fprintf (stderr, "op1 = "); debug_mp (op1, -16);
+ fprintf (stderr, "op2 = "); debug_mp (op2, -16);
+ abort();
+}
+
+void
+debug_mp (x, base)
+ mpz_t x;
+{
+ mpz_out_str (stderr, base, x); fputc ('\n', stderr);
+}
diff --git a/mpz/tests/t-mul.c b/mpz/tests/t-mul.c
new file mode 100644
index 000000000..047b5db86
--- /dev/null
+++ b/mpz/tests/t-mul.c
@@ -0,0 +1,264 @@
+/* Test mpz_add, mpz_cmp, mpz_cmp_ui, mpz_divmod, mpz_mul.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+#include "urandom.h"
+
+void debug_mp ();
+mp_size_t _mpn_mul_classic ();
+void mpz_refmul ();
+
+#ifndef SIZE
+#define SIZE 128
+#endif
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ mpz_t multiplier, multiplicand;
+ mpz_t product, ref_product;
+ mpz_t quotient, remainder;
+ mp_size_t multiplier_size, multiplicand_size;
+ int i;
+ int reps = 10000;
+
+ if (argc == 2)
+ reps = atoi (argv[1]);
+
+ mpz_init (multiplier);
+ mpz_init (multiplicand);
+ mpz_init (product);
+ mpz_init (ref_product);
+ mpz_init (quotient);
+ mpz_init (remainder);
+
+ for (i = 0; i < reps; i++)
+ {
+ multiplier_size = urandom () % SIZE - SIZE/2;
+ multiplicand_size = urandom () % SIZE - SIZE/2;
+
+ mpz_random2 (multiplier, multiplier_size);
+ mpz_random2 (multiplicand, multiplicand_size);
+
+ mpz_mul (product, multiplier, multiplicand);
+ mpz_refmul (ref_product, multiplier, multiplicand);
+ if (mpz_cmp_ui (multiplicand, 0) != 0)
+ mpz_divmod (quotient, remainder, product, multiplicand);
+
+ if (mpz_cmp (product, ref_product))
+ dump_abort (multiplier, multiplicand);
+
+ if (mpz_cmp_ui (multiplicand, 0) != 0)
+ if (mpz_cmp_ui (remainder, 0) || mpz_cmp (quotient, multiplier))
+ dump_abort (multiplier, multiplicand);
+ }
+
+ exit (0);
+}
+
+void
+mpz_refmul (w, u, v)
+ mpz_t w;
+ const mpz_t u;
+ const mpz_t v;
+{
+ mp_size_t usize = u->_mp_size;
+ mp_size_t vsize = v->_mp_size;
+ mp_size_t wsize;
+ mp_size_t sign_product;
+ mp_ptr up, vp;
+ mp_ptr wp;
+ mp_ptr free_me = NULL;
+ size_t free_me_size;
+ TMP_DECL (marker);
+
+ TMP_MARK (marker);
+ sign_product = usize ^ vsize;
+ usize = ABS (usize);
+ vsize = ABS (vsize);
+
+ if (usize < vsize)
+ {
+ /* Swap U and V. */
+ {const __mpz_struct *t = u; u = v; v = t;}
+ {mp_size_t t = usize; usize = vsize; vsize = t;}
+ }
+
+ up = u->_mp_d;
+ vp = v->_mp_d;
+ wp = w->_mp_d;
+
+ /* Ensure W has space enough to store the result. */
+ wsize = usize + vsize;
+ if (w->_mp_alloc < wsize)
+ {
+ if (wp == up || wp == vp)
+ {
+ free_me = wp;
+ free_me_size = w->_mp_alloc;
+ }
+ else
+ (*_mp_free_func) (wp, w->_mp_alloc * BYTES_PER_MP_LIMB);
+
+ w->_mp_alloc = wsize;
+ wp = (mp_ptr) (*_mp_allocate_func) (wsize * BYTES_PER_MP_LIMB);
+ w->_mp_d = wp;
+ }
+ else
+ {
+ /* Make U and V not overlap with W. */
+ if (wp == up)
+ {
+ /* W and U are identical. Allocate temporary space for U. */
+ up = (mp_ptr) TMP_ALLOC (usize * BYTES_PER_MP_LIMB);
+ /* Is V identical too? Keep it identical with U. */
+ if (wp == vp)
+ vp = up;
+ /* Copy to the temporary space. */
+ MPN_COPY (up, wp, usize);
+ }
+ else if (wp == vp)
+ {
+ /* W and V are identical. Allocate temporary space for V. */
+ vp = (mp_ptr) TMP_ALLOC (vsize * BYTES_PER_MP_LIMB);
+ /* Copy to the temporary space. */
+ MPN_COPY (vp, wp, vsize);
+ }
+ }
+
+ wsize = _mpn_mul_classic (wp, up, usize, vp, vsize);
+ w->_mp_size = sign_product < 0 ? -wsize : wsize;
+ if (free_me != NULL)
+ (*_mp_free_func) (free_me, free_me_size * BYTES_PER_MP_LIMB);
+
+ TMP_FREE (marker);
+}
+
+mp_size_t
+_mpn_mul_classic (prodp, up, usize, vp, vsize)
+ mp_ptr prodp;
+ mp_srcptr up;
+ mp_size_t usize;
+ mp_srcptr vp;
+ mp_size_t vsize;
+{
+ mp_size_t n;
+ mp_size_t prod_size;
+ mp_limb_t cy;
+ mp_size_t i, j;
+ mp_limb_t prod_low, prod_high;
+ mp_limb_t cy_dig;
+ mp_limb_t v_limb, c;
+
+ if (vsize == 0)
+ return 0;
+
+ /* Offset UP and PRODP so that the inner loop can be faster. */
+ up += usize;
+ prodp += usize;
+
+ /* Multiply by the first limb in V separately, as the result can
+ be stored (not added) to PROD. We also avoid a loop for zeroing. */
+ v_limb = vp[0];
+ cy_dig = 0;
+ j = -usize;
+ do
+ {
+ umul_ppmm (prod_high, prod_low, up[j], v_limb);
+ add_ssaaaa (cy_dig, prodp[j], prod_high, prod_low, 0, cy_dig);
+ j++;
+ }
+ while (j < 0);
+
+ prodp[j] = cy_dig;
+ prodp++;
+
+ /* For each iteration in the outer loop, multiply one limb from
+ U with one limb from V, and add it to PROD. */
+ for (i = 1; i < vsize; i++)
+ {
+ v_limb = vp[i];
+ cy_dig = 0;
+ j = -usize;
+
+ /* Inner loops. Simulate the carry flag by jumping between
+ these loops. The first is used when there was no carry
+ in the previois iteration; the second when there was carry. */
+
+ do
+ {
+ umul_ppmm (prod_high, prod_low, up[j], v_limb);
+ add_ssaaaa (cy_dig, prod_low, prod_high, prod_low, 0, cy_dig);
+ c = prodp[j];
+ prod_low += c;
+ prodp[j] = prod_low;
+ if (prod_low < c)
+ goto cy_loop;
+ ncy_loop:
+ j++;
+ }
+ while (j < 0);
+
+ prodp[j] = cy_dig;
+ prodp++;
+ continue;
+
+ do
+ {
+ umul_ppmm (prod_high, prod_low, up[j], v_limb);
+ add_ssaaaa (cy_dig, prod_low, prod_high, prod_low, 0, cy_dig);
+ c = prodp[j];
+ prod_low += c + 1;
+ prodp[j] = prod_low;
+ if (prod_low > c)
+ goto ncy_loop;
+ cy_loop:
+ j++;
+ }
+ while (j < 0);
+
+ cy_dig += 1;
+ prodp[j] = cy_dig;
+ prodp++;
+ }
+
+ return usize + vsize - (cy_dig == 0);
+}
+
+dump_abort (multiplier, multiplicand)
+ mpz_t multiplier, multiplicand;
+{
+ fprintf (stderr, "ERROR\n");
+ fprintf (stderr, "multiplier = "); debug_mp (multiplier, -16);
+ fprintf (stderr, "multiplicand = "); debug_mp (multiplicand, -16);
+ abort();
+}
+
+void
+debug_mp (x, base)
+ mpz_t x;
+{
+ mpz_out_str (stderr, base, x); fputc ('\n', stderr);
+}
diff --git a/mpz/tests/t-powm.c b/mpz/tests/t-powm.c
new file mode 100644
index 000000000..02d7ca5d0
--- /dev/null
+++ b/mpz/tests/t-powm.c
@@ -0,0 +1,125 @@
+/* Test mpz_powm, mpz_mul. mpz_mod, mpz_mod_ui, mpz_div_ui.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+void debug_mp ();
+
+#ifndef SIZE
+#define SIZE 8
+#endif
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ mpz_t base, exp, mod;
+ mpz_t r1, r2, t1, exp2, base2;
+ mp_size_t base_size, exp_size, mod_size;
+ int i;
+ int reps = 10000;
+
+ if (argc == 2)
+ reps = atoi (argv[1]);
+
+ mpz_init (base);
+ mpz_init (exp);
+ mpz_init (mod);
+ mpz_init (r1);
+ mpz_init (r2);
+ mpz_init (t1);
+ mpz_init (exp2);
+ mpz_init (base2);
+
+ for (i = 0; i < reps; i++)
+ {
+ base_size = urandom () % SIZE - SIZE/2;
+ mpz_random2 (base, base_size);
+
+ exp_size = urandom () % SIZE;
+ mpz_random2 (exp, exp_size);
+
+ mod_size = urandom () % SIZE /* - SIZE/2 */;
+ mpz_random2 (mod, mod_size);
+ if (mpz_cmp_ui (mod, 0) == 0)
+ continue;
+
+ /* This is mathematically undefined. */
+ if (mpz_cmp_ui (base, 0) == 0 && mpz_cmp_ui (exp, 0) == 0)
+ continue;
+
+#if 0
+ putc ('\n', stderr);
+ debug_mp (base, -16);
+ debug_mp (exp, -16);
+ debug_mp (mod, -16);
+#endif
+
+ mpz_powm (r1, base, exp, mod);
+
+ mpz_set_ui (r2, 1);
+ mpz_set (base2, base);
+ mpz_set (exp2, exp);
+
+ mpz_mod (r2, r2, mod); /* needed when exp==0 and mod==1 */
+ while (mpz_cmp_ui (exp2, 0) != 0)
+ {
+ mpz_mod_ui (t1, exp2, 2);
+ if (mpz_cmp_ui (t1, 0) != 0)
+ {
+ mpz_mul (r2, r2, base2);
+ mpz_mod (r2, r2, mod);
+ }
+ mpz_mul (base2, base2, base2);
+ mpz_mod (base2, base2, mod);
+ mpz_div_ui (exp2, exp2, 2);
+ }
+
+#if 0
+ debug_mp (r1, -16);
+ debug_mp (r2, -16);
+#endif
+
+ if (mpz_cmp (r1, r2) != 0)
+ abort ();
+ }
+
+ exit (0);
+}
+
+dump_abort (dividend, divisor)
+ MP_INT *dividend, *divisor;
+{
+ fprintf (stderr, "ERROR\n");
+ fprintf (stderr, "dividend = "); debug_mp (dividend, -16);
+ fprintf (stderr, "divisor = "); debug_mp (divisor, -16);
+ abort();
+}
+
+void
+debug_mp (x, base)
+ MP_INT *x;
+{
+ mpz_out_str (stderr, base, x); fputc ('\n', stderr);
+}
diff --git a/mpz/tests/t-powm_ui.c b/mpz/tests/t-powm_ui.c
new file mode 100644
index 000000000..b88fa9820
--- /dev/null
+++ b/mpz/tests/t-powm_ui.c
@@ -0,0 +1,120 @@
+/* Test mpz_powm_ui, mpz_mul. mpz_mod, mpz_mod_ui, mpz_div_ui.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+void debug_mp ();
+
+#ifndef SIZE
+#define SIZE 8
+#endif
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ mpz_t base, mod;
+ mpz_t r1, r2, base2;
+ mp_size_t base_size, mod_size;
+ mp_limb_t exp, exp2;
+ int i;
+ int reps = 10000;
+
+ if (argc == 2)
+ reps = atoi (argv[1]);
+
+ mpz_init (base);
+ mpz_init (mod);
+ mpz_init (r1);
+ mpz_init (r2);
+ mpz_init (base2);
+
+ for (i = 0; i < reps; i++)
+ {
+ base_size = urandom () % SIZE /* - SIZE/2 */;
+ mpz_random2 (base, base_size);
+
+ mpn_random2 (&exp, 1);
+
+ mod_size = urandom () % SIZE /* - SIZE/2 */;
+ mpz_random2 (mod, mod_size);
+ if (mpz_cmp_ui (mod, 0) == 0)
+ continue;
+
+ /* This is mathematically undefined. */
+ if (mpz_cmp_ui (base, 0) == 0 && exp == 0)
+ continue;
+
+#if 0
+ putc ('\n', stderr);
+ debug_mp (base, -16);
+ debug_mp (mod, -16);
+#endif
+
+ mpz_powm_ui (r1, base, (unsigned long int) exp, mod);
+
+ mpz_set_ui (r2, 1);
+ mpz_set (base2, base);
+ exp2 = exp;
+
+ mpz_mod (r2, r2, mod); /* needed when exp==0 and mod==1 */
+ while (exp2 != 0)
+ {
+ if (exp2 % 2 != 0)
+ {
+ mpz_mul (r2, r2, base2);
+ mpz_mod (r2, r2, mod);
+ }
+ mpz_mul (base2, base2, base2);
+ mpz_mod (base2, base2, mod);
+ exp2 = exp2 / 2;
+ }
+
+#if 0
+ debug_mp (r1, -16);
+ debug_mp (r2, -16);
+#endif
+
+ if (mpz_cmp (r1, r2) != 0)
+ abort ();
+ }
+
+ exit (0);
+}
+
+dump_abort (dividend, divisor)
+ MP_INT *dividend, *divisor;
+{
+ fprintf (stderr, "ERROR\n");
+ fprintf (stderr, "dividend = "); debug_mp (dividend, -16);
+ fprintf (stderr, "divisor = "); debug_mp (divisor, -16);
+ abort();
+}
+
+void
+debug_mp (x, base)
+ MP_INT *x;
+{
+ mpz_out_str (stderr, base, x); fputc ('\n', stderr);
+}
diff --git a/mpz/tests/t-sqrtrem.c b/mpz/tests/t-sqrtrem.c
new file mode 100644
index 000000000..f5fcd09bc
--- /dev/null
+++ b/mpz/tests/t-sqrtrem.c
@@ -0,0 +1,98 @@
+/* Test mpz_add, mpz_add_ui, mpz_cmp, mpz_cmp, mpz_mul, mpz_sqrtrem.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+void debug_mp ();
+
+#ifndef SIZE
+#define SIZE 16
+#endif
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ mpz_t x2;
+ mpz_t x, rem;
+ mpz_t temp, temp2;
+ mp_size_t x2_size;
+ int i;
+ int reps = 100000;
+
+ if (argc == 2)
+ reps = atoi (argv[1]);
+
+ mpz_init (x2);
+ mpz_init (x);
+ mpz_init (rem);
+ mpz_init (temp);
+ mpz_init (temp2);
+
+ for (i = 0; i < reps; i++)
+ {
+ x2_size = urandom () % SIZE;
+
+ mpz_random2 (x2, x2_size);
+
+ mpz_sqrtrem (x, rem, x2);
+ mpz_mul (temp, x, x);
+
+ /* Is square of result > argument? */
+ if (mpz_cmp (temp, x2) > 0)
+ dump_abort (x2, x, rem);
+
+ mpz_add_ui (temp2, x, 1);
+ mpz_mul (temp2, temp2, temp2);
+
+ /* Is square of (result + 1) <= argument? */
+ if (mpz_cmp (temp2, x2) <= 0)
+ dump_abort (x2, x, rem);
+
+ mpz_add (temp2, temp, rem);
+
+ /* Is the remainder wrong? */
+ if (mpz_cmp (x2, temp2) != 0)
+ dump_abort (x2, x, rem);
+ }
+
+ exit (0);
+}
+
+dump_abort (x2, x, rem)
+ mpz_t x2, x, rem;
+{
+ fprintf (stderr, "ERROR\n");
+ fprintf (stderr, "x2 = "); debug_mp (x2, -16);
+ fprintf (stderr, "x = "); debug_mp (x, -16);
+ fprintf (stderr, "remainder = "); debug_mp (rem, -16);
+ abort();
+}
+
+void
+debug_mp (x, base)
+ mpz_t x;
+{
+ mpz_out_str (stderr, base, x); fputc ('\n', stderr);
+}
diff --git a/mpz/tests/t-tdiv.c b/mpz/tests/t-tdiv.c
new file mode 100644
index 000000000..d646ed8c5
--- /dev/null
+++ b/mpz/tests/t-tdiv.c
@@ -0,0 +1,118 @@
+/* Test mpz_abs, mpz_add, mpz_cmp, mpz_cmp_ui, mpz_tdiv_qr, mpz_tdiv_q,
+ mpz_tdiv_r, mpz_mul.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+void debug_mp ();
+
+#ifndef SIZE
+#define SIZE 16
+#endif
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ mpz_t dividend, divisor;
+ mpz_t quotient, remainder;
+ mpz_t quotient2, remainder2;
+ mpz_t temp;
+ mp_size_t dividend_size, divisor_size;
+ int i;
+ int reps = 100000;
+
+ if (argc == 2)
+ reps = atoi (argv[1]);
+
+ mpz_init (dividend);
+ mpz_init (divisor);
+ mpz_init (quotient);
+ mpz_init (remainder);
+ mpz_init (quotient2);
+ mpz_init (remainder2);
+ mpz_init (temp);
+
+ for (i = 0; i < reps; i++)
+ {
+ dividend_size = urandom () % SIZE - SIZE/2;
+ mpz_random2 (dividend, dividend_size);
+
+ divisor_size = urandom () % SIZE - SIZE/2;
+ mpz_random2 (divisor, divisor_size);
+ if (mpz_cmp_ui (divisor, 0) == 0)
+ continue;
+
+ mpz_tdiv_qr (quotient, remainder, dividend, divisor);
+ mpz_tdiv_q (quotient2, dividend, divisor);
+ mpz_tdiv_r (remainder2, dividend, divisor);
+
+ /* First determine that the quotients and remainders computed
+ with different functions are equal. */
+ if (mpz_cmp (quotient, quotient2) != 0)
+ dump_abort (dividend, divisor);
+ if (mpz_cmp (remainder, remainder2) != 0)
+ dump_abort (dividend, divisor);
+
+ /* Check if the sign of the quotient is correct. */
+ if (mpz_cmp_ui (quotient, 0) != 0)
+ if ((mpz_cmp_ui (quotient, 0) < 0)
+ != ((mpz_cmp_ui (dividend, 0) ^ mpz_cmp_ui (divisor, 0)) < 0))
+ dump_abort (dividend, divisor);
+
+ /* Check if the remainder has the same sign as the dividend
+ (quotient rounded towards 0). */
+ if (mpz_cmp_ui (remainder, 0) != 0)
+ if ((mpz_cmp_ui (remainder, 0) < 0) != (mpz_cmp_ui (dividend, 0) < 0))
+ dump_abort (dividend, divisor);
+
+ mpz_mul (temp, quotient, divisor);
+ mpz_add (temp, temp, remainder);
+ if (mpz_cmp (temp, dividend) != 0)
+ dump_abort (dividend, divisor);
+
+ mpz_abs (temp, divisor);
+ mpz_abs (remainder, remainder);
+ if (mpz_cmp (remainder, temp) >= 0)
+ dump_abort (dividend, divisor);
+ }
+
+ exit (0);
+}
+
+dump_abort (dividend, divisor)
+ mpz_t dividend, divisor;
+{
+ fprintf (stderr, "ERROR\n");
+ fprintf (stderr, "dividend = "); debug_mp (dividend, -16);
+ fprintf (stderr, "divisor = "); debug_mp (divisor, -16);
+ abort();
+}
+
+void
+debug_mp (x, base)
+ mpz_t x;
+{
+ mpz_out_str (stderr, base, x); fputc ('\n', stderr);
+}
diff --git a/mpz/tests/t-tdiv_ui.c b/mpz/tests/t-tdiv_ui.c
new file mode 100644
index 000000000..8d73b1108
--- /dev/null
+++ b/mpz/tests/t-tdiv_ui.c
@@ -0,0 +1,117 @@
+/* Test mpz_abs, mpz_add, mpz_cmp, mpz_cmp_ui, mpz_tdiv_qr_ui, mpz_tdiv_q_ui,
+ mpz_tdiv_r_ui, mpz_mul_ui.
+
+Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+void debug_mp ();
+
+#ifndef SIZE
+#define SIZE 16
+#endif
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ mpz_t dividend;
+ mpz_t quotient, remainder;
+ mpz_t quotient2, remainder2;
+ mpz_t temp;
+ mp_size_t dividend_size;
+ mp_limb_t divisor;
+ int i;
+ int reps = 100000;
+
+ if (argc == 2)
+ reps = atoi (argv[1]);
+
+ mpz_init (dividend);
+ mpz_init (quotient);
+ mpz_init (remainder);
+ mpz_init (quotient2);
+ mpz_init (remainder2);
+ mpz_init (temp);
+
+ for (i = 0; i < reps; i++)
+ {
+ dividend_size = urandom () % SIZE - SIZE/2;
+ mpz_random2 (dividend, dividend_size);
+
+ divisor = urandom ();
+ if (divisor == 0)
+ continue;
+
+ mpz_tdiv_qr_ui (quotient, remainder, dividend, divisor);
+ mpz_tdiv_q_ui (quotient2, dividend, divisor);
+ mpz_tdiv_r_ui (remainder2, dividend, divisor);
+
+ /* First determine that the quotients and remainders computed
+ with different functions are equal. */
+ if (mpz_cmp (quotient, quotient2) != 0)
+ dump_abort (dividend, divisor);
+ if (mpz_cmp (remainder, remainder2) != 0)
+ dump_abort (dividend, divisor);
+
+ /* Check if the sign of the quotient is correct. */
+ if (mpz_cmp_ui (quotient, 0) != 0)
+ if ((mpz_cmp_ui (quotient, 0) < 0)
+ != (mpz_cmp_ui (dividend, 0) < 0))
+ dump_abort (dividend, divisor);
+
+ /* Check if the remainder has the same sign as the dividend
+ (quotient rounded towards 0). */
+ if (mpz_cmp_ui (remainder, 0) != 0)
+ if ((mpz_cmp_ui (remainder, 0) < 0) != (mpz_cmp_ui (dividend, 0) < 0))
+ dump_abort (dividend, divisor);
+
+ mpz_mul_ui (temp, quotient, divisor);
+ mpz_add (temp, temp, remainder);
+ if (mpz_cmp (temp, dividend) != 0)
+ dump_abort (dividend, divisor);
+
+ mpz_abs (remainder, remainder);
+ if (mpz_cmp_ui (remainder, divisor) >= 0)
+ dump_abort (dividend, divisor);
+ }
+
+ exit (0);
+}
+
+dump_abort (dividend, divisor)
+ mpz_t dividend;
+ mp_limb_t divisor;
+{
+ fprintf (stderr, "ERROR\n");
+ fprintf (stderr, "dividend = "); debug_mp (dividend, -16);
+ fprintf (stderr, "divisor = %lX\n", divisor);
+ abort();
+}
+
+void
+debug_mp (x, base)
+ mpz_t x;
+{
+ mpz_out_str (stderr, base, x); fputc ('\n', stderr);
+}
diff --git a/mpz/ui_pow_ui.c b/mpz/ui_pow_ui.c
new file mode 100644
index 000000000..617d85dfa
--- /dev/null
+++ b/mpz/ui_pow_ui.c
@@ -0,0 +1,111 @@
+/* mpz_ui_pow_ui(res, base, exp) -- Set RES to BASE**EXP.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+void
+#if __STDC__
+mpz_ui_pow_ui (mpz_ptr r, unsigned long int b, unsigned long int e)
+#else
+mpz_ui_pow_ui (r, b, e)
+ mpz_ptr r;
+ unsigned long int b;
+ unsigned long int e;
+#endif
+{
+ mp_ptr rp, tp, xp;
+ mp_size_t rsize;
+ int cnt, i;
+ mp_limb_t blimb = b;
+ TMP_DECL (marker);
+
+ /* Single out cases that give result == 0 or 1. These tests are here
+ to simplify the general code below, not to optimize. */
+ if (blimb == 0)
+ {
+ r->_mp_size = 0;
+ return;
+ }
+ if (e == 0)
+ {
+ r->_mp_d[0] = 1;
+ r->_mp_size = 1;
+ return;
+ }
+
+ if (blimb < 0x100)
+ {
+ /* Estimate space requirements accurately. Using the code from the
+ `else' path would over-estimate space requirements wildly. */
+ float lb = __mp_bases[blimb].chars_per_bit_exactly;
+ rsize = 2 + ((mp_size_t) (e / lb) / BITS_PER_MP_LIMB);
+ }
+ else
+ {
+ /* Over-estimate space requirements somewhat. */
+ count_leading_zeros (cnt, blimb);
+ rsize = e - cnt * e / BITS_PER_MP_LIMB + 1;
+ }
+
+ TMP_MARK (marker);
+
+ /* The two areas are used to alternatingly hold the input and recieve the
+ product for mpn_mul. (This scheme is used to fulfill the requirements
+ of mpn_mul; that the product space may not be the same as any of the
+ input operands.) */
+ rp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB);
+ tp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB);
+
+ rp[0] = blimb;
+ rsize = 1;
+ count_leading_zeros (cnt, e);
+
+ for (i = BITS_PER_MP_LIMB - cnt - 2; i >= 0; i--)
+ {
+ mpn_mul_n (tp, rp, rp, rsize);
+ rsize = 2 * rsize;
+ rsize -= tp[rsize - 1] == 0;
+ xp = tp; tp = rp; rp = xp;
+
+ if ((e & ((mp_limb_t) 1 << i)) != 0)
+ {
+ mp_limb_t cy;
+ cy = mpn_mul_1 (tp, rp, rsize, blimb);
+ if (cy != 0)
+ {
+ tp[rsize] = cy;
+ rsize++;
+ }
+ xp = tp; tp = rp; rp = xp;
+ }
+ }
+
+ /* Now then we know the exact space requirements, reallocate if
+ necessary. */
+ if (r->_mp_alloc < rsize)
+ _mpz_realloc (r, rsize);
+
+ MPN_COPY (r->_mp_d, rp, rsize);
+ r->_mp_size = rsize;
+ TMP_FREE (marker);
+}
diff --git a/stack-alloc.c b/stack-alloc.c
new file mode 100644
index 000000000..d9619f622
--- /dev/null
+++ b/stack-alloc.c
@@ -0,0 +1,108 @@
+/* Stack allocation routines. This is intended for machines without support
+ for the `alloca' function.
+
+Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "stack-alloc.h"
+
+typedef struct tmp_stack tmp_stack;
+
+void *malloc ();
+static unsigned long max_total_allocation = 0;
+static unsigned long current_total_allocation = 0;
+
+static tmp_stack xxx = {&xxx, &xxx, 0};
+static tmp_stack *current = &xxx;
+
+/* Allocate a block of exactly <size> bytes. This should only be called
+ through the TMP_ALLOC macro, which takes care of rounding/alignment. */
+void *
+__tmp_alloc (size)
+ unsigned long size;
+{
+ void *this;
+
+ if (size > (char *) current->end - (char *) current->alloc_point)
+ {
+ void *chunk;
+ tmp_stack *header;
+ unsigned long chunk_size;
+ unsigned long now;
+
+ /* Allocate a chunk that makes the total current allocation somewhat
+ larger than the maximum allocation ever. If size is very large, we
+ allocate that much. */
+
+ now = current_total_allocation + size;
+ if (now > max_total_allocation)
+ {
+ /* We need more temporary memory than ever before. Increase
+ for future needs. */
+ now = now * 3 / 2;
+ chunk_size = now - current_total_allocation + sizeof (tmp_stack);
+ current_total_allocation = now;
+ max_total_allocation = current_total_allocation;
+ }
+ else
+ {
+ chunk_size = max_total_allocation - current_total_allocation + sizeof (tmp_stack);
+ current_total_allocation = max_total_allocation;
+ }
+
+ chunk = malloc (chunk_size);
+ header = chunk;
+ header->end = (char *) chunk + chunk_size;
+ header->alloc_point = (char *) chunk + sizeof (tmp_stack);
+ header->prev = current;
+ current = header;
+ }
+
+ this = current->alloc_point;
+ current->alloc_point = (char *) this + size;
+ return this;
+}
+
+/* Typically called at function entry. <mark> is assigned so that __tmp_free
+ can later be used to reclaim all subsecuently allocated storage. */
+void
+__tmp_mark (mark)
+ tmp_marker *mark;
+{
+ mark->which_chunk = current;
+ mark->alloc_point = current->alloc_point;
+}
+
+/* Free everything allocated since <mark> was assigned by __tmp_mark */
+void
+__tmp_free (mark)
+ tmp_marker *mark;
+{
+ while (mark->which_chunk != current)
+ {
+ tmp_stack *tmp;
+
+ tmp = current;
+ current = tmp->prev;
+ current_total_allocation -= (((char *) (tmp->end) - (char *) tmp)
+ - sizeof (tmp_stack));
+ free (tmp);
+ }
+ current->alloc_point = mark->alloc_point;
+}
diff --git a/stack-alloc.h b/stack-alloc.h
new file mode 100644
index 000000000..f5fbb8608
--- /dev/null
+++ b/stack-alloc.h
@@ -0,0 +1,50 @@
+/* Stack allocation routines. This is intended for machines without support
+ for the `alloca' function.
+
+Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+struct tmp_stack
+{
+ void *end;
+ void *alloc_point;
+ struct tmp_stack *prev;
+};
+
+struct tmp_marker
+{
+ struct tmp_stack *which_chunk;
+ void *alloc_point;
+};
+
+typedef struct tmp_marker tmp_marker;
+
+void *__tmp_alloc (unsigned long);
+void __tmp_mark (tmp_marker *);
+void __tmp_free (tmp_marker *);
+
+#ifndef __TMP_ALIGN
+#define __TMP_ALIGN 8
+#endif
+
+#define TMP_DECL(marker) tmp_marker marker
+#define TMP_ALLOC(size) \
+ __tmp_alloc (((unsigned long) (size) + __TMP_ALIGN - 1) & -__TMP_ALIGN)
+#define TMP_MARK(marker) __tmp_mark (&marker)
+#define TMP_FREE(marker) __tmp_free (&marker)
diff --git a/texinfo.tex b/texinfo.tex
new file mode 100644
index 000000000..d9a82c58a
--- /dev/null
+++ b/texinfo.tex
@@ -0,0 +1,4585 @@
+%% TeX macros to handle texinfo files
+
+% Copyright (C) 1985, 86, 88, 90, 91, 92, 93,
+% 94, 95, 1996 Free Software Foundation, Inc.
+
+%This texinfo.tex file is free software; you can redistribute it and/or
+%modify it under the terms of the GNU General Public License as
+%published by the Free Software Foundation; either version 2, or (at
+%your option) any later version.
+
+%This texinfo.tex file 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
+%General Public License for more details.
+
+%You should have received a copy of the GNU General Public License
+%along with this texinfo.tex file; see the file COPYING. If not, write
+%to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+%Boston, MA 02111-1307, USA.
+
+
+%In other words, you are welcome to use, share and improve this program.
+%You are forbidden to forbid anyone else to use, share and improve
+%what you give them. Help stamp out software-hoarding!
+
+
+% Send bug reports to bug-texinfo@prep.ai.mit.edu.
+% Please include a *precise* test case in each bug report.
+
+
+% Make it possible to create a .fmt file just by loading this file:
+% if the underlying format is not loaded, start by loading it now.
+% Added by gildea November 1993.
+\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
+
+% This automatically updates the version number based on RCS.
+\def\deftexinfoversion$#1: #2 ${\def\texinfoversion{#2}}
+\deftexinfoversion$Revision$
+\message{Loading texinfo package [Version \texinfoversion]:}
+
+% If in a .fmt file, print the version number
+% and turn on active characters that we couldn't do earlier because
+% they might have appeared in the input file name.
+\everyjob{\message{[Texinfo version \texinfoversion]}\message{}
+ \catcode`+=\active \catcode`\_=\active}
+
+% Save some parts of plain tex whose names we will redefine.
+
+\let\ptextilde=\~
+\let\ptexlbrace=\{
+\let\ptexrbrace=\}
+\let\ptexdots=\dots
+\let\ptexdot=\.
+\let\ptexstar=\*
+\let\ptexend=\end
+\let\ptexbullet=\bullet
+\let\ptexb=\b
+\let\ptexc=\c
+\let\ptexi=\i
+\let\ptext=\t
+\let\ptexl=\l
+\let\ptexL=\L
+
+% Be sure we're in horizontal mode when doing a tie, since we make space
+% equivalent to this in @example-like environments. Otherwise, a space
+% at the beginning of a line will start with \penalty -- and
+% since \penalty is valid in vertical mode, we'd end up putting the
+% penalty on the vertical list instead of in the new paragraph.
+{\catcode`@ = 11
+ % Avoid using \@M directly, because that causes trouble
+ % if the definition is written into an index file.
+ \global\let\tiepenalty = \@M
+ \gdef\tie{\leavevmode\penalty\tiepenalty\ }
+}
+\let\~ = \tie % And make it available as @~.
+
+\message{Basics,}
+\chardef\other=12
+
+% If this character appears in an error message or help string, it
+% starts a new line in the output.
+\newlinechar = `^^J
+
+% Set up fixed words for English.
+\ifx\putwordChapter\undefined{\gdef\putwordChapter{Chapter}}\fi%
+\def\putwordInfo{Info}%
+\ifx\putwordSee\undefined{\gdef\putwordSee{See}}\fi%
+\ifx\putwordsee\undefined{\gdef\putwordsee{see}}\fi%
+\ifx\putwordfile\undefined{\gdef\putwordfile{file}}\fi%
+\ifx\putwordpage\undefined{\gdef\putwordpage{page}}\fi%
+\ifx\putwordsection\undefined{\gdef\putwordsection{section}}\fi%
+\ifx\putwordSection\undefined{\gdef\putwordSection{Section}}\fi%
+\ifx\putwordTableofContents\undefined{\gdef\putwordTableofContents{Table of Contents}}\fi%
+\ifx\putwordShortContents\undefined{\gdef\putwordShortContents{Short Contents}}\fi%
+\ifx\putwordAppendix\undefined{\gdef\putwordAppendix{Appendix}}\fi%
+
+% Ignore a token.
+%
+\def\gobble#1{}
+
+\hyphenation{ap-pen-dix}
+\hyphenation{mini-buf-fer mini-buf-fers}
+\hyphenation{eshell}
+
+% Margin to add to right of even pages, to left of odd pages.
+\newdimen \bindingoffset \bindingoffset=0pt
+\newdimen \normaloffset \normaloffset=\hoffset
+\newdimen\pagewidth \newdimen\pageheight
+\pagewidth=\hsize \pageheight=\vsize
+
+% Sometimes it is convenient to have everything in the transcript file
+% and nothing on the terminal. We don't just call \tracingall here,
+% since that produces some useless output on the terminal.
+%
+\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}%
+\def\loggingall{\tracingcommands2 \tracingstats2
+ \tracingpages1 \tracingoutput1 \tracinglostchars1
+ \tracingmacros2 \tracingparagraphs1 \tracingrestores1
+ \showboxbreadth\maxdimen\showboxdepth\maxdimen
+}%
+
+%---------------------Begin change-----------------------
+%
+%%%% For @cropmarks command.
+% Dimensions to add cropmarks at corners Added by P. A. MacKay, 12 Nov. 1986
+%
+\newdimen\cornerlong \newdimen\cornerthick
+\newdimen \topandbottommargin
+\newdimen \outerhsize \newdimen \outervsize
+\cornerlong=1pc\cornerthick=.3pt % These set size of cropmarks
+\outerhsize=7in
+%\outervsize=9.5in
+% Alternative @smallbook page size is 9.25in
+\outervsize=9.25in
+\topandbottommargin=.75in
+%
+%---------------------End change-----------------------
+
+% \onepageout takes a vbox as an argument. Note that \pagecontents
+% does insertions itself, but you have to call it yourself.
+\chardef\PAGE=255 \output={\onepageout{\pagecontents\PAGE}}
+\def\onepageout#1{\hoffset=\normaloffset
+\ifodd\pageno \advance\hoffset by \bindingoffset
+\else \advance\hoffset by -\bindingoffset\fi
+{\escapechar=`\\\relax % makes sure backslash is used in output files.
+\shipout\vbox{{\let\hsize=\pagewidth \makeheadline} \pagebody{#1}%
+{\let\hsize=\pagewidth \makefootline}}}%
+\advancepageno \ifnum\outputpenalty>-20000 \else\dosupereject\fi}
+
+%%%% For @cropmarks command %%%%
+
+% Here is a modification of the main output routine for Near East Publications
+% This provides right-angle cropmarks at all four corners.
+% The contents of the page are centerlined into the cropmarks,
+% and any desired binding offset is added as an \hskip on either
+% site of the centerlined box. (P. A. MacKay, 12 November, 1986)
+%
+\def\croppageout#1{\hoffset=0pt % make sure this doesn't mess things up
+{\escapechar=`\\\relax % makes sure backslash is used in output files.
+ \shipout
+ \vbox to \outervsize{\hsize=\outerhsize
+ \vbox{\line{\ewtop\hfill\ewtop}}
+ \nointerlineskip
+ \line{\vbox{\moveleft\cornerthick\nstop}
+ \hfill
+ \vbox{\moveright\cornerthick\nstop}}
+ \vskip \topandbottommargin
+ \centerline{\ifodd\pageno\hskip\bindingoffset\fi
+ \vbox{
+ {\let\hsize=\pagewidth \makeheadline}
+ \pagebody{#1}
+ {\let\hsize=\pagewidth \makefootline}}
+ \ifodd\pageno\else\hskip\bindingoffset\fi}
+ \vskip \topandbottommargin plus1fill minus1fill
+ \boxmaxdepth\cornerthick
+ \line{\vbox{\moveleft\cornerthick\nsbot}
+ \hfill
+ \vbox{\moveright\cornerthick\nsbot}}
+ \nointerlineskip
+ \vbox{\line{\ewbot\hfill\ewbot}}
+ }}
+ \advancepageno
+ \ifnum\outputpenalty>-20000 \else\dosupereject\fi}
+%
+% Do @cropmarks to get crop marks
+\def\cropmarks{\let\onepageout=\croppageout }
+
+\newinsert\margin \dimen\margin=\maxdimen
+
+\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}}
+{\catcode`\@ =11
+\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi
+% marginal hacks, juha@viisa.uucp (Juha Takala)
+\ifvoid\margin\else % marginal info is present
+ \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi
+\dimen@=\dp#1 \unvbox#1
+\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi
+\ifr@ggedbottom \kern-\dimen@ \vfil \fi}
+}
+
+%
+% Here are the rules for the cropmarks. Note that they are
+% offset so that the space between them is truly \outerhsize or \outervsize
+% (P. A. MacKay, 12 November, 1986)
+%
+\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong}
+\def\nstop{\vbox
+ {\hrule height\cornerthick depth\cornerlong width\cornerthick}}
+\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong}
+\def\nsbot{\vbox
+ {\hrule height\cornerlong depth\cornerthick width\cornerthick}}
+
+% Parse an argument, then pass it to #1. The argument is the rest of
+% the input line (except we remove a trailing comment). #1 should be a
+% macro which expects an ordinary undelimited TeX argument.
+%
+\def\parsearg#1{%
+ \let\next = #1%
+ \begingroup
+ \obeylines
+ \futurelet\temp\parseargx
+}
+
+% If the next token is an obeyed space (from an @example environment or
+% the like), remove it and recurse. Otherwise, we're done.
+\def\parseargx{%
+ % \obeyedspace is defined far below, after the definition of \sepspaces.
+ \ifx\obeyedspace\temp
+ \expandafter\parseargdiscardspace
+ \else
+ \expandafter\parseargline
+ \fi
+}
+
+% Remove a single space (as the delimiter token to the macro call).
+{\obeyspaces %
+ \gdef\parseargdiscardspace {\futurelet\temp\parseargx}}
+
+{\obeylines %
+ \gdef\parseargline#1^^M{%
+ \endgroup % End of the group started in \parsearg.
+ %
+ % First remove any @c comment, then any @comment.
+ % Result of each macro is put in \toks0.
+ \argremovec #1\c\relax %
+ \expandafter\argremovecomment \the\toks0 \comment\relax %
+ %
+ % Call the caller's macro, saved as \next in \parsearg.
+ \expandafter\next\expandafter{\the\toks0}%
+ }%
+}
+
+% Since all \c{,omment} does is throw away the argument, we can let TeX
+% do that for us. The \relax here is matched by the \relax in the call
+% in \parseargline; it could be more or less anything, its purpose is
+% just to delimit the argument to the \c.
+\def\argremovec#1\c#2\relax{\toks0 = {#1}}
+\def\argremovecomment#1\comment#2\relax{\toks0 = {#1}}
+
+% \argremovec{,omment} might leave us with trailing spaces, though; e.g.,
+% @end itemize @c foo
+% will have two active spaces as part of the argument with the
+% `itemize'. Here we remove all active spaces from #1, and assign the
+% result to \toks0.
+%
+% This loses if there are any *other* active characters besides spaces
+% in the argument -- _ ^ +, for example -- since they get expanded.
+% Fortunately, Texinfo does not define any such commands. (If it ever
+% does, the catcode of the characters in questionwill have to be changed
+% here.) But this means we cannot call \removeactivespaces as part of
+% \argremovec{,omment}, since @c uses \parsearg, and thus the argument
+% that \parsearg gets might well have any character at all in it.
+%
+\def\removeactivespaces#1{%
+ \begingroup
+ \ignoreactivespaces
+ \edef\temp{#1}%
+ \global\toks0 = \expandafter{\temp}%
+ \endgroup
+}
+
+% Change the active space to expand to nothing.
+%
+\begingroup
+ \obeyspaces
+ \gdef\ignoreactivespaces{\obeyspaces\let =\empty}
+\endgroup
+
+
+\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next}
+
+%% These are used to keep @begin/@end levels from running away
+%% Call \inENV within environments (after a \begingroup)
+\newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi}
+\def\ENVcheck{%
+\ifENV\errmessage{Still within an environment. Type Return to continue.}
+\endgroup\fi} % This is not perfect, but it should reduce lossage
+
+% @begin foo is the same as @foo, for now.
+\newhelp\EMsimple{Type <Return> to continue.}
+
+\outer\def\begin{\parsearg\beginxxx}
+
+\def\beginxxx #1{%
+\expandafter\ifx\csname #1\endcsname\relax
+{\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else
+\csname #1\endcsname\fi}
+
+% @end foo executes the definition of \Efoo.
+%
+\def\end{\parsearg\endxxx}
+\def\endxxx #1{%
+ \removeactivespaces{#1}%
+ \edef\endthing{\the\toks0}%
+ %
+ \expandafter\ifx\csname E\endthing\endcsname\relax
+ \expandafter\ifx\csname \endthing\endcsname\relax
+ % There's no \foo, i.e., no ``environment'' foo.
+ \errhelp = \EMsimple
+ \errmessage{Undefined command `@end \endthing'}%
+ \else
+ \unmatchedenderror\endthing
+ \fi
+ \else
+ % Everything's ok; the right environment has been started.
+ \csname E\endthing\endcsname
+ \fi
+}
+
+% There is an environment #1, but it hasn't been started. Give an error.
+%
+\def\unmatchedenderror#1{%
+ \errhelp = \EMsimple
+ \errmessage{This `@end #1' doesn't have a matching `@#1'}%
+}
+
+% Define the control sequence \E#1 to give an unmatched @end error.
+%
+\def\defineunmatchedend#1{%
+ \expandafter\def\csname E#1\endcsname{\unmatchedenderror{#1}}%
+}
+
+
+% Single-spacing is done by various environments (specifically, in
+% \nonfillstart and \quotations).
+\newskip\singlespaceskip \singlespaceskip = 12.5pt
+\def\singlespace{%
+ % Why was this kern here? It messes up equalizing space above and below
+ % environments. --karl, 6may93
+ %{\advance \baselineskip by -\singlespaceskip
+ %\kern \baselineskip}%
+ \setleading \singlespaceskip
+}
+
+%% Simple single-character @ commands
+
+% @@ prints an @
+% Kludge this until the fonts are right (grr).
+\def\@{{\tt \char '100}}
+
+% This is turned off because it was never documented
+% and you can use @w{...} around a quote to suppress ligatures.
+%% Define @` and @' to be the same as ` and '
+%% but suppressing ligatures.
+%\def\`{{`}}
+%\def\'{{'}}
+
+% Used to generate quoted braces.
+
+\def\mylbrace {{\tt \char '173}}
+\def\myrbrace {{\tt \char '175}}
+\let\{=\mylbrace
+\let\}=\myrbrace
+
+% @: forces normal size whitespace following.
+\def\:{\spacefactor=1000 }
+
+% @* forces a line break.
+\def\*{\hfil\break\hbox{}\ignorespaces}
+
+% @. is an end-of-sentence period.
+\def\.{.\spacefactor=3000 }
+
+% @enddots{} is an end-of-sentence ellipsis.
+\gdef\enddots{$\mathinner{\ldotp\ldotp\ldotp\ldotp}$\spacefactor=3000}
+
+% @! is an end-of-sentence bang.
+\gdef\!{!\spacefactor=3000 }
+
+% @? is an end-of-sentence query.
+\gdef\?{?\spacefactor=3000 }
+
+% @w prevents a word break. Without the \leavevmode, @w at the
+% beginning of a paragraph, when TeX is still in vertical mode, would
+% produce a whole line of output instead of starting the paragraph.
+\def\w#1{\leavevmode\hbox{#1}}
+
+% @group ... @end group forces ... to be all on one page, by enclosing
+% it in a TeX vbox. We use \vtop instead of \vbox to construct the box
+% to keep its height that of a normal line. According to the rules for
+% \topskip (p.114 of the TeXbook), the glue inserted is
+% max (\topskip - \ht (first item), 0). If that height is large,
+% therefore, no glue is inserted, and the space between the headline and
+% the text is small, which looks bad.
+%
+\def\group{\begingroup
+ \ifnum\catcode13=\active \else
+ \errhelp = \groupinvalidhelp
+ \errmessage{@group invalid in context where filling is enabled}%
+ \fi
+ %
+ % The \vtop we start below produces a box with normal height and large
+ % depth; thus, TeX puts \baselineskip glue before it, and (when the
+ % next line of text is done) \lineskip glue after it. (See p.82 of
+ % the TeXbook.) Thus, space below is not quite equal to space
+ % above. But it's pretty close.
+ \def\Egroup{%
+ \egroup % End the \vtop.
+ \endgroup % End the \group.
+ }%
+ %
+ \vtop\bgroup
+ % We have to put a strut on the last line in case the @group is in
+ % the midst of an example, rather than completely enclosing it.
+ % Otherwise, the interline space between the last line of the group
+ % and the first line afterwards is too small. But we can't put the
+ % strut in \Egroup, since there it would be on a line by itself.
+ % Hence this just inserts a strut at the beginning of each line.
+ \everypar = {\strut}%
+ %
+ % Since we have a strut on every line, we don't need any of TeX's
+ % normal interline spacing.
+ \offinterlineskip
+ %
+ % OK, but now we have to do something about blank
+ % lines in the input in @example-like environments, which normally
+ % just turn into \lisppar, which will insert no space now that we've
+ % turned off the interline space. Simplest is to make them be an
+ % empty paragraph.
+ \ifx\par\lisppar
+ \edef\par{\leavevmode \par}%
+ %
+ % Reset ^^M's definition to new definition of \par.
+ \obeylines
+ \fi
+ %
+ % Do @comment since we are called inside an environment such as
+ % @example, where each end-of-line in the input causes an
+ % end-of-line in the output. We don't want the end-of-line after
+ % the `@group' to put extra space in the output. Since @group
+ % should appear on a line by itself (according to the Texinfo
+ % manual), we don't worry about eating any user text.
+ \comment
+}
+%
+% TeX puts in an \escapechar (i.e., `@') at the beginning of the help
+% message, so this ends up printing `@group can only ...'.
+%
+\newhelp\groupinvalidhelp{%
+group can only be used in environments such as @example,^^J%
+where each line of input produces a line of output.}
+
+% @need space-in-mils
+% forces a page break if there is not space-in-mils remaining.
+
+\newdimen\mil \mil=0.001in
+
+\def\need{\parsearg\needx}
+
+% Old definition--didn't work.
+%\def\needx #1{\par %
+%% This method tries to make TeX break the page naturally
+%% if the depth of the box does not fit.
+%{\baselineskip=0pt%
+%\vtop to #1\mil{\vfil}\kern -#1\mil\penalty 10000
+%\prevdepth=-1000pt
+%}}
+
+\def\needx#1{%
+ % Go into vertical mode, so we don't make a big box in the middle of a
+ % paragraph.
+ \par
+ %
+ % Don't add any leading before our big empty box, but allow a page
+ % break, since the best break might be right here.
+ \allowbreak
+ \nointerlineskip
+ \vtop to #1\mil{\vfil}%
+ %
+ % TeX does not even consider page breaks if a penalty added to the
+ % main vertical list is 10000 or more. But in order to see if the
+ % empty box we just added fits on the page, we must make it consider
+ % page breaks. On the other hand, we don't want to actually break the
+ % page after the empty box. So we use a penalty of 9999.
+ %
+ % There is an extremely small chance that TeX will actually break the
+ % page at this \penalty, if there are no other feasible breakpoints in
+ % sight. (If the user is using lots of big @group commands, which
+ % almost-but-not-quite fill up a page, TeX will have a hard time doing
+ % good page breaking, for example.) However, I could not construct an
+ % example where a page broke at this \penalty; if it happens in a real
+ % document, then we can reconsider our strategy.
+ \penalty9999
+ %
+ % Back up by the size of the box, whether we did a page break or not.
+ \kern -#1\mil
+ %
+ % Do not allow a page break right after this kern.
+ \nobreak
+}
+
+% @br forces paragraph break
+
+\let\br = \par
+
+% @dots{} output some dots
+
+\def\dots{$\ldots$}
+
+% @page forces the start of a new page
+
+\def\page{\par\vfill\supereject}
+
+% @exdent text....
+% outputs text on separate line in roman font, starting at standard page margin
+
+% This records the amount of indent in the innermost environment.
+% That's how much \exdent should take out.
+\newskip\exdentamount
+
+% This defn is used inside fill environments such as @defun.
+\def\exdent{\parsearg\exdentyyy}
+\def\exdentyyy #1{{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}}
+
+% This defn is used inside nofill environments such as @example.
+\def\nofillexdent{\parsearg\nofillexdentyyy}
+\def\nofillexdentyyy #1{{\advance \leftskip by -\exdentamount
+\leftline{\hskip\leftskip{\rm#1}}}}
+
+% @inmargin{TEXT} puts TEXT in the margin next to the current paragraph.
+
+\def\inmargin#1{%
+\strut\vadjust{\nobreak\kern-\strutdepth
+ \vtop to \strutdepth{\baselineskip\strutdepth\vss
+ \llap{\rightskip=\inmarginspacing \vbox{\noindent #1}}\null}}}
+\newskip\inmarginspacing \inmarginspacing=1cm
+\def\strutdepth{\dp\strutbox}
+
+%\hbox{{\rm#1}}\hfil\break}}
+
+% @include file insert text of that file as input.
+% Allow normal characters that we make active in the argument (a file name).
+\def\include{\begingroup
+ \catcode`\\=12
+ \catcode`~=12
+ \catcode`^=12
+ \catcode`_=12
+ \catcode`|=12
+ \catcode`<=12
+ \catcode`>=12
+ \catcode`+=12
+ \parsearg\includezzz}
+% Restore active chars for included file.
+\def\includezzz#1{\endgroup\begingroup
+ % Read the included file in a group so nested @include's work.
+ \def\thisfile{#1}%
+ \input\thisfile
+\endgroup}
+
+\def\thisfile{}
+
+% @center line outputs that line, centered
+
+\def\center{\parsearg\centerzzz}
+\def\centerzzz #1{{\advance\hsize by -\leftskip
+\advance\hsize by -\rightskip
+\centerline{#1}}}
+
+% @sp n outputs n lines of vertical space
+
+\def\sp{\parsearg\spxxx}
+\def\spxxx #1{\par \vskip #1\baselineskip}
+
+% @comment ...line which is ignored...
+% @c is the same as @comment
+% @ignore ... @end ignore is another way to write a comment
+
+\def\comment{\catcode 64=\other \catcode 123=\other \catcode 125=\other%
+\parsearg \commentxxx}
+
+\def\commentxxx #1{\catcode 64=0 \catcode 123=1 \catcode 125=2 }
+
+\let\c=\comment
+
+% Prevent errors for section commands.
+% Used in @ignore and in failing conditionals.
+\def\ignoresections{%
+\let\chapter=\relax
+\let\unnumbered=\relax
+\let\top=\relax
+\let\unnumberedsec=\relax
+\let\unnumberedsection=\relax
+\let\unnumberedsubsec=\relax
+\let\unnumberedsubsection=\relax
+\let\unnumberedsubsubsec=\relax
+\let\unnumberedsubsubsection=\relax
+\let\section=\relax
+\let\subsec=\relax
+\let\subsubsec=\relax
+\let\subsection=\relax
+\let\subsubsection=\relax
+\let\appendix=\relax
+\let\appendixsec=\relax
+\let\appendixsection=\relax
+\let\appendixsubsec=\relax
+\let\appendixsubsection=\relax
+\let\appendixsubsubsec=\relax
+\let\appendixsubsubsection=\relax
+\let\contents=\relax
+\let\smallbook=\relax
+\let\titlepage=\relax
+}
+
+% Used in nested conditionals, where we have to parse the Texinfo source
+% and so want to turn off most commands, in case they are used
+% incorrectly.
+%
+\def\ignoremorecommands{%
+ \let\defcv = \relax
+ \let\deffn = \relax
+ \let\deffnx = \relax
+ \let\defindex = \relax
+ \let\defivar = \relax
+ \let\defmac = \relax
+ \let\defmethod = \relax
+ \let\defop = \relax
+ \let\defopt = \relax
+ \let\defspec = \relax
+ \let\deftp = \relax
+ \let\deftypefn = \relax
+ \let\deftypefun = \relax
+ \let\deftypevar = \relax
+ \let\deftypevr = \relax
+ \let\defun = \relax
+ \let\defvar = \relax
+ \let\defvr = \relax
+ \let\ref = \relax
+ \let\xref = \relax
+ \let\printindex = \relax
+ \let\pxref = \relax
+ \let\settitle = \relax
+ \let\setchapternewpage = \relax
+ \let\setchapterstyle = \relax
+ \let\everyheading = \relax
+ \let\evenheading = \relax
+ \let\oddheading = \relax
+ \let\everyfooting = \relax
+ \let\evenfooting = \relax
+ \let\oddfooting = \relax
+ \let\headings = \relax
+ \let\include = \relax
+ \let\lowersections = \relax
+ \let\down = \relax
+ \let\raisesections = \relax
+ \let\up = \relax
+ \let\set = \relax
+ \let\clear = \relax
+ \let\item = \relax
+ \let\message = \relax
+}
+
+% Ignore @ignore ... @end ignore.
+%
+\def\ignore{\doignore{ignore}}
+
+% Also ignore @ifinfo, @ifhtml, @html, @menu, and @direntry text.
+%
+\def\ifinfo{\doignore{ifinfo}}
+\def\ifhtml{\doignore{ifhtml}}
+\def\html{\doignore{html}}
+\def\menu{\doignore{menu}}
+\def\direntry{\doignore{direntry}}
+
+% @dircategory CATEGORY -- specify a category of the dir file
+% which this file should belong to. Ignore this in TeX.
+
+\def\dircategory{\comment}
+
+% Ignore text until a line `@end #1'.
+%
+\def\doignore#1{\begingroup
+ % Don't complain about control sequences we have declared \outer.
+ \ignoresections
+ %
+ % Define a command to swallow text until we reach `@end #1'.
+ \long\def\doignoretext##1\end #1{\enddoignore}%
+ %
+ % Make sure that spaces turn into tokens that match what \doignoretext wants.
+ \catcode32 = 10
+ %
+ % And now expand that command.
+ \doignoretext
+}
+
+% What we do to finish off ignored text.
+%
+\def\enddoignore{\endgroup\ignorespaces}%
+
+\newif\ifwarnedobs\warnedobsfalse
+\def\obstexwarn{%
+ \ifwarnedobs\relax\else
+ % We need to warn folks that they may have trouble with TeX 3.0.
+ % This uses \immediate\write16 rather than \message to get newlines.
+ \immediate\write16{}
+ \immediate\write16{***WARNING*** for users of Unix TeX 3.0!}
+ \immediate\write16{This manual trips a bug in TeX version 3.0 (tex hangs).}
+ \immediate\write16{If you are running another version of TeX, relax.}
+ \immediate\write16{If you are running Unix TeX 3.0, kill this TeX process.}
+ \immediate\write16{ Then upgrade your TeX installation if you can.}
+ \immediate\write16{If you are stuck with version 3.0, run the}
+ \immediate\write16{ script ``tex3patch'' from the Texinfo distribution}
+ \immediate\write16{ to use a workaround.}
+ \immediate\write16{}
+ \global\warnedobstrue
+ \fi
+}
+
+% **In TeX 3.0, setting text in \nullfont hangs tex. For a
+% workaround (which requires the file ``dummy.tfm'' to be installed),
+% uncomment the following line:
+%%%%%\font\nullfont=dummy\let\obstexwarn=\relax
+
+% Ignore text, except that we keep track of conditional commands for
+% purposes of nesting, up to an `@end #1' command.
+%
+\def\nestedignore#1{%
+ \obstexwarn
+ % We must actually expand the ignored text to look for the @end
+ % command, so that nested ignore constructs work. Thus, we put the
+ % text into a \vbox and then do nothing with the result. To minimize
+ % the change of memory overflow, we follow the approach outlined on
+ % page 401 of the TeXbook: make the current font be a dummy font.
+ %
+ \setbox0 = \vbox\bgroup
+ % Don't complain about control sequences we have declared \outer.
+ \ignoresections
+ %
+ % Define `@end #1' to end the box, which will in turn undefine the
+ % @end command again.
+ \expandafter\def\csname E#1\endcsname{\egroup\ignorespaces}%
+ %
+ % We are going to be parsing Texinfo commands. Most cause no
+ % trouble when they are used incorrectly, but some commands do
+ % complicated argument parsing or otherwise get confused, so we
+ % undefine them.
+ %
+ % We can't do anything about stray @-signs, unfortunately;
+ % they'll produce `undefined control sequence' errors.
+ \ignoremorecommands
+ %
+ % Set the current font to be \nullfont, a TeX primitive, and define
+ % all the font commands to also use \nullfont. We don't use
+ % dummy.tfm, as suggested in the TeXbook, because not all sites
+ % might have that installed. Therefore, math mode will still
+ % produce output, but that should be an extremely small amount of
+ % stuff compared to the main input.
+ %
+ \nullfont
+ \let\tenrm = \nullfont \let\tenit = \nullfont \let\tensl = \nullfont
+ \let\tenbf = \nullfont \let\tentt = \nullfont \let\smallcaps = \nullfont
+ \let\tensf = \nullfont
+ % Similarly for index fonts (mostly for their use in
+ % smallexample)
+ \let\indrm = \nullfont \let\indit = \nullfont \let\indsl = \nullfont
+ \let\indbf = \nullfont \let\indtt = \nullfont \let\indsc = \nullfont
+ \let\indsf = \nullfont
+ %
+ % Don't complain when characters are missing from the fonts.
+ \tracinglostchars = 0
+ %
+ % Don't bother to do space factor calculations.
+ \frenchspacing
+ %
+ % Don't report underfull hboxes.
+ \hbadness = 10000
+ %
+ % Do minimal line-breaking.
+ \pretolerance = 10000
+ %
+ % Do not execute instructions in @tex
+ \def\tex{\doignore{tex}}
+}
+
+% @set VAR sets the variable VAR to an empty value.
+% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE.
+%
+% Since we want to separate VAR from REST-OF-LINE (which might be
+% empty), we can't just use \parsearg; we have to insert a space of our
+% own to delimit the rest of the line, and then take it out again if we
+% didn't need it. Make sure the catcode of space is correct to avoid
+% losing inside @example, for instance.
+%
+\def\set{\begingroup\catcode` =10 \parsearg\setxxx}
+\def\setxxx#1{\setyyy#1 \endsetyyy}
+\def\setyyy#1 #2\endsetyyy{%
+ \def\temp{#2}%
+ \ifx\temp\empty \global\expandafter\let\csname SET#1\endcsname = \empty
+ \else \setzzz{#1}#2\endsetzzz % Remove the trailing space \setxxx inserted.
+ \fi
+ \endgroup
+}
+% Can't use \xdef to pre-expand #2 and save some time, since \temp or
+% \next or other control sequences that we've defined might get us into
+% an infinite loop. Consider `@set foo @cite{bar}'.
+\def\setzzz#1#2 \endsetzzz{\expandafter\gdef\csname SET#1\endcsname{#2}}
+
+% @clear VAR clears (i.e., unsets) the variable VAR.
+%
+\def\clear{\parsearg\clearxxx}
+\def\clearxxx#1{\global\expandafter\let\csname SET#1\endcsname=\relax}
+
+% @value{foo} gets the text saved in variable foo.
+%
+\def\value#1{\expandafter
+ \ifx\csname SET#1\endcsname\relax
+ {\{No value for ``#1''\}}
+ \else \csname SET#1\endcsname \fi}
+
+% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined
+% with @set.
+%
+\def\ifset{\parsearg\ifsetxxx}
+\def\ifsetxxx #1{%
+ \expandafter\ifx\csname SET#1\endcsname\relax
+ \expandafter\ifsetfail
+ \else
+ \expandafter\ifsetsucceed
+ \fi
+}
+\def\ifsetsucceed{\conditionalsucceed{ifset}}
+\def\ifsetfail{\nestedignore{ifset}}
+\defineunmatchedend{ifset}
+
+% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been
+% defined with @set, or has been undefined with @clear.
+%
+\def\ifclear{\parsearg\ifclearxxx}
+\def\ifclearxxx #1{%
+ \expandafter\ifx\csname SET#1\endcsname\relax
+ \expandafter\ifclearsucceed
+ \else
+ \expandafter\ifclearfail
+ \fi
+}
+\def\ifclearsucceed{\conditionalsucceed{ifclear}}
+\def\ifclearfail{\nestedignore{ifclear}}
+\defineunmatchedend{ifclear}
+
+% @iftex always succeeds; we read the text following, through @end
+% iftex). But `@end iftex' should be valid only after an @iftex.
+%
+\def\iftex{\conditionalsucceed{iftex}}
+\defineunmatchedend{iftex}
+
+% We can't just want to start a group at @iftex (for example) and end it
+% at @end iftex, since then @set commands inside the conditional have no
+% effect (they'd get reverted at the end of the group). So we must
+% define \Eiftex to redefine itself to be its previous value. (We can't
+% just define it to fail again with an ``unmatched end'' error, since
+% the @ifset might be nested.)
+%
+\def\conditionalsucceed#1{%
+ \edef\temp{%
+ % Remember the current value of \E#1.
+ \let\nece{prevE#1} = \nece{E#1}%
+ %
+ % At the `@end #1', redefine \E#1 to be its previous value.
+ \def\nece{E#1}{\let\nece{E#1} = \nece{prevE#1}}%
+ }%
+ \temp
+}
+
+% We need to expand lots of \csname's, but we don't want to expand the
+% control sequences after we've constructed them.
+%
+\def\nece#1{\expandafter\noexpand\csname#1\endcsname}
+
+% @asis just yields its argument. Used with @table, for example.
+%
+\def\asis#1{#1}
+
+% @math means output in math mode.
+% We don't use $'s directly in the definition of \math because control
+% sequences like \math are expanded when the toc file is written. Then,
+% we read the toc file back, the $'s will be normal characters (as they
+% should be, according to the definition of Texinfo). So we must use a
+% control sequence to switch into and out of math mode.
+%
+% This isn't quite enough for @math to work properly in indices, but it
+% seems unlikely it will ever be needed there.
+%
+\let\implicitmath = $
+\def\math#1{\implicitmath #1\implicitmath}
+
+% @bullet and @minus need the same treatment as @math, just above.
+\def\bullet{\implicitmath\ptexbullet\implicitmath}
+\def\minus{\implicitmath-\implicitmath}
+
+\def\node{\ENVcheck\parsearg\nodezzz}
+\def\nodezzz#1{\nodexxx [#1,]}
+\def\nodexxx[#1,#2]{\gdef\lastnode{#1}}
+\let\nwnode=\node
+\let\lastnode=\relax
+
+\def\donoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\setref{\lastnode}\fi
+\global\let\lastnode=\relax}
+
+\def\unnumbnoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\unnumbsetref{\lastnode}\fi
+\global\let\lastnode=\relax}
+
+\def\appendixnoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\appendixsetref{\lastnode}\fi
+\global\let\lastnode=\relax}
+
+\let\refill=\relax
+
+% @setfilename is done at the beginning of every texinfo file.
+% So open here the files we need to have open while reading the input.
+% This makes it possible to make a .fmt file for texinfo.
+\def\setfilename{%
+ \readauxfile
+ \opencontents
+ \openindices
+ \fixbackslash % Turn off hack to swallow `\input texinfo'.
+ \global\let\setfilename=\comment % Ignore extra @setfilename cmds.
+ \comment % Ignore the actual filename.
+}
+
+\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend}
+
+\def\inforef #1{\inforefzzz #1,,,,**}
+\def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}},
+ node \samp{\ignorespaces#1{}}}
+
+\def\macro#1{\begingroup\ignoresections\catcode`\#=6\def\macrotemp{#1}\parsearg\macroxxx}
+\def\macroxxx#1#2 \end macro{%
+\expandafter\gdef\macrotemp#1{#2}%
+\endgroup}
+
+%\def\linemacro#1{\begingroup\ignoresections\catcode`\#=6\def\macrotemp{#1}\parsearg\linemacroxxx}
+%\def\linemacroxxx#1#2 \end linemacro{%
+%\let\parsearg=\relax
+%\edef\macrotempx{\csname M\butfirst\expandafter\string\macrotemp\endcsname}%
+%\expandafter\xdef\macrotemp{\parsearg\macrotempx}%
+%\expandafter\gdef\macrotempx#1{#2}%
+%\endgroup}
+
+%\def\butfirst#1{}
+
+\message{fonts,}
+
+% Font-change commands.
+
+% Texinfo supports the sans serif font style, which plain TeX does not.
+% So we set up a \sf analogous to plain's \rm, etc.
+\newfam\sffam
+\def\sf{\fam=\sffam \tensf}
+\let\li = \sf % Sometimes we call it \li, not \sf.
+
+% We don't need math for this one.
+\def\ttsl{\tenttsl}
+
+%% Try out Computer Modern fonts at \magstephalf
+\let\mainmagstep=\magstephalf
+
+% Set the font macro #1 to the font named #2, adding on the
+% specified font prefix (normally `cm').
+% #3 is the font's design size, #4 is a scale factor
+\def\setfont#1#2#3#4{\font#1=\fontprefix#2#3 scaled #4}
+
+% Use cm as the default font prefix.
+% To specify the font prefix, you must define \fontprefix
+% before you read in texinfo.tex.
+\ifx\fontprefix\undefined
+\def\fontprefix{cm}
+\fi
+% Support font families that don't use the same naming scheme as CM.
+\def\rmshape{r}
+\def\rmbshape{bx} %where the normal face is bold
+\def\bfshape{b}
+\def\bxshape{bx}
+\def\ttshape{tt}
+\def\ttbshape{tt}
+\def\ttslshape{sltt}
+\def\itshape{ti}
+\def\itbshape{bxti}
+\def\slshape{sl}
+\def\slbshape{bxsl}
+\def\sfshape{ss}
+\def\sfbshape{ss}
+\def\scshape{csc}
+\def\scbshape{csc}
+
+\ifx\bigger\relax
+\let\mainmagstep=\magstep1
+\setfont\textrm\rmshape{12}{1000}
+\setfont\texttt\ttshape{12}{1000}
+\else
+\setfont\textrm\rmshape{10}{\mainmagstep}
+\setfont\texttt\ttshape{10}{\mainmagstep}
+\fi
+% Instead of cmb10, you many want to use cmbx10.
+% cmbx10 is a prettier font on its own, but cmb10
+% looks better when embedded in a line with cmr10.
+\setfont\textbf\bfshape{10}{\mainmagstep}
+\setfont\textit\itshape{10}{\mainmagstep}
+\setfont\textsl\slshape{10}{\mainmagstep}
+\setfont\textsf\sfshape{10}{\mainmagstep}
+\setfont\textsc\scshape{10}{\mainmagstep}
+\setfont\textttsl\ttslshape{10}{\mainmagstep}
+\font\texti=cmmi10 scaled \mainmagstep
+\font\textsy=cmsy10 scaled \mainmagstep
+
+% A few fonts for @defun, etc.
+\setfont\defbf\bxshape{10}{\magstep1} %was 1314
+\setfont\deftt\ttshape{10}{\magstep1}
+\def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf}
+
+% Fonts for indices and small examples.
+% We actually use the slanted font rather than the italic,
+% because texinfo normally uses the slanted fonts for that.
+% Do not make many font distinctions in general in the index, since they
+% aren't very useful.
+\setfont\ninett\ttshape{9}{1000}
+\setfont\indrm\rmshape{9}{1000}
+\setfont\indit\slshape{9}{1000}
+\let\indsl=\indit
+\let\indtt=\ninett
+\let\indttsl=\ninett
+\let\indsf=\indrm
+\let\indbf=\indrm
+\setfont\indsc\scshape{10}{900}
+\font\indi=cmmi9
+\font\indsy=cmsy9
+
+% Fonts for headings
+\setfont\chaprm\rmbshape{12}{\magstep2}
+\setfont\chapit\itbshape{10}{\magstep3}
+\setfont\chapsl\slbshape{10}{\magstep3}
+\setfont\chaptt\ttbshape{12}{\magstep2}
+\setfont\chapttsl\ttslshape{10}{\magstep3}
+\setfont\chapsf\sfbshape{12}{\magstep2}
+\let\chapbf=\chaprm
+\setfont\chapsc\scbshape{10}{\magstep3}
+\font\chapi=cmmi12 scaled \magstep2
+\font\chapsy=cmsy10 scaled \magstep3
+
+\setfont\secrm\rmbshape{12}{\magstep1}
+\setfont\secit\itbshape{10}{\magstep2}
+\setfont\secsl\slbshape{10}{\magstep2}
+\setfont\sectt\ttbshape{12}{\magstep1}
+\setfont\secttsl\ttslshape{10}{\magstep2}
+\setfont\secsf\sfbshape{12}{\magstep1}
+\let\secbf\secrm
+\setfont\secsc\scbshape{10}{\magstep2}
+\font\seci=cmmi12 scaled \magstep1
+\font\secsy=cmsy10 scaled \magstep2
+
+% \setfont\ssecrm\bxshape{10}{\magstep1} % This size an font looked bad.
+% \setfont\ssecit\itshape{10}{\magstep1} % The letters were too crowded.
+% \setfont\ssecsl\slshape{10}{\magstep1}
+% \setfont\ssectt\ttshape{10}{\magstep1}
+% \setfont\ssecsf\sfshape{10}{\magstep1}
+
+%\setfont\ssecrm\bfshape{10}{1315} % Note the use of cmb rather than cmbx.
+%\setfont\ssecit\itshape{10}{1315} % Also, the size is a little larger than
+%\setfont\ssecsl\slshape{10}{1315} % being scaled magstep1.
+%\setfont\ssectt\ttshape{10}{1315}
+%\setfont\ssecsf\sfshape{10}{1315}
+
+%\let\ssecbf=\ssecrm
+
+\setfont\ssecrm\rmbshape{12}{\magstephalf}
+\setfont\ssecit\itbshape{10}{1315}
+\setfont\ssecsl\slbshape{10}{1315}
+\setfont\ssectt\ttbshape{12}{\magstephalf}
+\setfont\ssecttsl\ttslshape{10}{\magstep1}
+\setfont\ssecsf\sfbshape{12}{\magstephalf}
+\let\ssecbf\ssecrm
+\setfont\ssecsc\scbshape{10}{\magstep1}
+\font\sseci=cmmi12 scaled \magstephalf
+\font\ssecsy=cmsy10 scaled \magstep1
+% The smallcaps and symbol fonts should actually be scaled \magstep1.5,
+% but that is not a standard magnification.
+
+% Fonts for title page:
+\setfont\titlerm\rmbshape{12}{\magstep3}
+\let\authorrm = \secrm
+
+% In order for the font changes to affect most math symbols and letters,
+% we have to define the \textfont of the standard families. Since
+% texinfo doesn't allow for producing subscripts and superscripts, we
+% don't bother to reset \scriptfont and \scriptscriptfont (which would
+% also require loading a lot more fonts).
+%
+\def\resetmathfonts{%
+ \textfont0 = \tenrm \textfont1 = \teni \textfont2 = \tensy
+ \textfont\itfam = \tenit \textfont\slfam = \tensl \textfont\bffam = \tenbf
+ \textfont\ttfam = \tentt \textfont\sffam = \tensf
+}
+
+
+% The font-changing commands redefine the meanings of \tenSTYLE, instead
+% of just \STYLE. We do this so that font changes will continue to work
+% in math mode, where it is the current \fam that is relevant in most
+% cases, not the current font. Plain TeX does \def\bf{\fam=\bffam
+% \tenbf}, for example. By redefining \tenbf, we obviate the need to
+% redefine \bf itself.
+\def\textfonts{%
+ \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl
+ \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc
+ \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy \let\tenttsl=\textttsl
+ \resetmathfonts}
+\def\chapfonts{%
+ \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl
+ \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc
+ \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy \let\tenttsl=\chapttsl
+ \resetmathfonts}
+\def\secfonts{%
+ \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl
+ \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc
+ \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy \let\tenttsl=\secttsl
+ \resetmathfonts}
+\def\subsecfonts{%
+ \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl
+ \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc
+ \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy \let\tenttsl=\ssecttsl
+ \resetmathfonts}
+\def\indexfonts{%
+ \let\tenrm=\indrm \let\tenit=\indit \let\tensl=\indsl
+ \let\tenbf=\indbf \let\tentt=\indtt \let\smallcaps=\indsc
+ \let\tensf=\indsf \let\teni=\indi \let\tensy=\indsy \let\tenttsl=\indttsl
+ \resetmathfonts}
+
+% Set up the default fonts, so we can use them for creating boxes.
+%
+\textfonts
+
+% Count depth in font-changes, for error checks
+\newcount\fontdepth \fontdepth=0
+
+% Fonts for short table of contents.
+\setfont\shortcontrm\rmshape{12}{1000}
+\setfont\shortcontbf\bxshape{12}{1000}
+\setfont\shortcontsl\slshape{12}{1000}
+
+%% Add scribe-like font environments, plus @l for inline lisp (usually sans
+%% serif) and @ii for TeX italic
+
+% \smartitalic{ARG} outputs arg in italics, followed by an italic correction
+% unless the following character is such as not to need one.
+\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else\/\fi\fi\fi}
+\def\smartitalic#1{{\sl #1}\futurelet\next\smartitalicx}
+
+\let\i=\smartitalic
+\let\var=\smartitalic
+\let\dfn=\smartitalic
+\let\emph=\smartitalic
+\let\cite=\smartitalic
+
+\def\b#1{{\bf #1}}
+\let\strong=\b
+
+% We can't just use \exhyphenpenalty, because that only has effect at
+% the end of a paragraph. Restore normal hyphenation at the end of the
+% group within which \nohyphenation is presumably called.
+%
+\def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation}
+\def\restorehyphenation{\hyphenchar\font = `- }
+
+\def\t#1{%
+ {\tt \rawbackslash \frenchspacing #1}%
+ \null
+}
+\let\ttfont=\t
+\def\samp #1{`\tclose{#1}'\null}
+\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null}
+\def\ctrl #1{{\tt \rawbackslash \hat}#1}
+
+\let\file=\samp
+\let\url=\samp % perhaps include a hypertex \special eventually
+
+% @code is a modification of @t,
+% which makes spaces the same size as normal in the surrounding text.
+\def\tclose#1{%
+ {%
+ % Change normal interword space to be same as for the current font.
+ \spaceskip = \fontdimen2\font
+ %
+ % Switch to typewriter.
+ \tt
+ %
+ % But `\ ' produces the large typewriter interword space.
+ \def\ {{\spaceskip = 0pt{} }}%
+ %
+ % Turn off hyphenation.
+ \nohyphenation
+ %
+ \rawbackslash
+ \frenchspacing
+ #1%
+ }%
+ \null
+}
+
+% We *must* turn on hyphenation at `-' and `_' in \code.
+% Otherwise, it is too hard to avoid overfull hboxes
+% in the Emacs manual, the Library manual, etc.
+
+% Unfortunately, TeX uses one parameter (\hyphenchar) to control
+% both hyphenation at - and hyphenation within words.
+% We must therefore turn them both off (\tclose does that)
+% and arrange explicitly to hyphenate an a dash.
+% -- rms.
+{
+\catcode`\-=\active
+\catcode`\_=\active
+\global\def\code{\begingroup \catcode`\-=\active \let-\codedash \catcode`\_=\active \let_\codeunder \codex}
+% The following is used by \doprintindex to insure that long function names
+% wrap around. It is necessary for - and _ to be active before the index is
+% read from the file, as \entry parses the arguments long before \code is
+% ever called. -- mycroft
+\global\def\indexbreaks{\catcode`\-=\active \let-\realdash \catcode`\_=\active \let_\realunder}
+}
+
+\def\realdash{-}
+\def\realunder{_}
+\def\codedash{-\discretionary{}{}{}}
+\def\codeunder{\normalunderscore\discretionary{}{}{}}
+\def\codex #1{\tclose{#1}\endgroup}
+
+%\let\exp=\tclose %Was temporary
+
+% @kbd is like @code, except that if the argument is just one @key command,
+% then @kbd has no effect.
+%
+\def\xkey{\key}
+\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}%
+\ifx\one\xkey\ifx\threex\three \key{#2}%
+\else{\tclose{\ttsl\look}}\fi
+\else{\tclose{\ttsl\look}}\fi}
+
+% Check if we are currently using a typewriter font. Since all the
+% Computer Modern typewriter fonts have zero interword stretch (and
+% shrink), and it is reasonable to expect all typewriter fonts to have
+% this property, we can check that font parameter.
+%
+\def\ifmonospace{\ifdim\fontdimen3\font=0pt }
+
+% Typeset a dimension, e.g., `in' or `pt'. The only reason for the
+% argument is to make the input look right: @dmn{pt} instead of
+% @dmn{}pt.
+%
+\def\dmn#1{\thinspace #1}
+
+\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par}
+
+\def\l#1{{\li #1}\null} %
+
+\def\r#1{{\rm #1}} % roman font
+% Use of \lowercase was suggested.
+\def\sc#1{{\smallcaps#1}} % smallcaps font
+\def\ii#1{{\it #1}} % italic font
+
+\message{page headings,}
+
+\newskip\titlepagetopglue \titlepagetopglue = 1.5in
+\newskip\titlepagebottomglue \titlepagebottomglue = 2pc
+
+% First the title page. Must do @settitle before @titlepage.
+\def\titlefont#1{{\titlerm #1}}
+
+\newif\ifseenauthor
+\newif\iffinishedtitlepage
+
+\def\shorttitlepage{\parsearg\shorttitlepagezzz}
+\def\shorttitlepagezzz #1{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}%
+ \endgroup\page\hbox{}\page}
+
+\def\titlepage{\begingroup \parindent=0pt \textfonts
+ \let\subtitlerm=\tenrm
+% I deinstalled the following change because \cmr12 is undefined.
+% This change was not in the ChangeLog anyway. --rms.
+% \let\subtitlerm=\cmr12
+ \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}%
+ %
+ \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines}%
+ %
+ % Leave some space at the very top of the page.
+ \vglue\titlepagetopglue
+ %
+ % Now you can print the title using @title.
+ \def\title{\parsearg\titlezzz}%
+ \def\titlezzz##1{\leftline{\titlefont{##1}}
+ % print a rule at the page bottom also.
+ \finishedtitlepagefalse
+ \vskip4pt \hrule height 4pt width \hsize \vskip4pt}%
+ % No rule at page bottom unless we print one at the top with @title.
+ \finishedtitlepagetrue
+ %
+ % Now you can put text using @subtitle.
+ \def\subtitle{\parsearg\subtitlezzz}%
+ \def\subtitlezzz##1{{\subtitlefont \rightline{##1}}}%
+ %
+ % @author should come last, but may come many times.
+ \def\author{\parsearg\authorzzz}%
+ \def\authorzzz##1{\ifseenauthor\else\vskip 0pt plus 1filll\seenauthortrue\fi
+ {\authorfont \leftline{##1}}}%
+ %
+ % Most title ``pages'' are actually two pages long, with space
+ % at the top of the second. We don't want the ragged left on the second.
+ \let\oldpage = \page
+ \def\page{%
+ \iffinishedtitlepage\else
+ \finishtitlepage
+ \fi
+ \oldpage
+ \let\page = \oldpage
+ \hbox{}}%
+% \def\page{\oldpage \hbox{}}
+}
+
+\def\Etitlepage{%
+ \iffinishedtitlepage\else
+ \finishtitlepage
+ \fi
+ % It is important to do the page break before ending the group,
+ % because the headline and footline are only empty inside the group.
+ % If we use the new definition of \page, we always get a blank page
+ % after the title page, which we certainly don't want.
+ \oldpage
+ \endgroup
+ \HEADINGSon
+}
+
+\def\finishtitlepage{%
+ \vskip4pt \hrule height 2pt width \hsize
+ \vskip\titlepagebottomglue
+ \finishedtitlepagetrue
+}
+
+%%% Set up page headings and footings.
+
+\let\thispage=\folio
+
+\newtoks \evenheadline % Token sequence for heading line of even pages
+\newtoks \oddheadline % Token sequence for heading line of odd pages
+\newtoks \evenfootline % Token sequence for footing line of even pages
+\newtoks \oddfootline % Token sequence for footing line of odd pages
+
+% Now make Tex use those variables
+\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline
+ \else \the\evenheadline \fi}}
+\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline
+ \else \the\evenfootline \fi}\HEADINGShook}
+\let\HEADINGShook=\relax
+
+% Commands to set those variables.
+% For example, this is what @headings on does
+% @evenheading @thistitle|@thispage|@thischapter
+% @oddheading @thischapter|@thispage|@thistitle
+% @evenfooting @thisfile||
+% @oddfooting ||@thisfile
+
+\def\evenheading{\parsearg\evenheadingxxx}
+\def\oddheading{\parsearg\oddheadingxxx}
+\def\everyheading{\parsearg\everyheadingxxx}
+
+\def\evenfooting{\parsearg\evenfootingxxx}
+\def\oddfooting{\parsearg\oddfootingxxx}
+\def\everyfooting{\parsearg\everyfootingxxx}
+
+{\catcode`\@=0 %
+
+\gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish}
+\gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish}
+\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\everyheadingxxx #1{\everyheadingyyy #1@|@|@|@|\finish}
+\gdef\everyheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish}
+\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish}
+\gdef\oddfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\everyfootingxxx #1{\everyfootingyyy #1@|@|@|@|\finish}
+\gdef\everyfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}
+\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+%
+}% unbind the catcode of @.
+
+% @headings double turns headings on for double-sided printing.
+% @headings single turns headings on for single-sided printing.
+% @headings off turns them off.
+% @headings on same as @headings double, retained for compatibility.
+% @headings after turns on double-sided headings after this page.
+% @headings doubleafter turns on double-sided headings after this page.
+% @headings singleafter turns on single-sided headings after this page.
+% By default, they are off.
+
+\def\headings #1 {\csname HEADINGS#1\endcsname}
+
+\def\HEADINGSoff{
+\global\evenheadline={\hfil} \global\evenfootline={\hfil}
+\global\oddheadline={\hfil} \global\oddfootline={\hfil}}
+\HEADINGSoff
+% When we turn headings on, set the page number to 1.
+% For double-sided printing, put current file name in lower left corner,
+% chapter name on inside top of right hand pages, document
+% title on inside top of left hand pages, and page numbers on outside top
+% edge of all pages.
+\def\HEADINGSdouble{
+%\pagealignmacro
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+% For single-sided printing, chapter title goes across top left of page,
+% page number on top right.
+\def\HEADINGSsingle{
+%\pagealignmacro
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+\def\HEADINGSon{\HEADINGSdouble}
+
+\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex}
+\let\HEADINGSdoubleafter=\HEADINGSafter
+\def\HEADINGSdoublex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+
+\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex}
+\def\HEADINGSsinglex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+
+% Subroutines used in generating headings
+% Produces Day Month Year style of output.
+\def\today{\number\day\space
+\ifcase\month\or
+January\or February\or March\or April\or May\or June\or
+July\or August\or September\or October\or November\or December\fi
+\space\number\year}
+
+% Use this if you want the Month Day, Year style of output.
+%\def\today{\ifcase\month\or
+%January\or February\or March\or April\or May\or June\or
+%July\or August\or September\or October\or November\or December\fi
+%\space\number\day, \number\year}
+
+% @settitle line... specifies the title of the document, for headings
+% It generates no output of its own
+
+\def\thistitle{No Title}
+\def\settitle{\parsearg\settitlezzz}
+\def\settitlezzz #1{\gdef\thistitle{#1}}
+
+\message{tables,}
+
+% @tabs -- simple alignment
+
+% These don't work. For one thing, \+ is defined as outer.
+% So these macros cannot even be defined.
+
+%\def\tabs{\parsearg\tabszzz}
+%\def\tabszzz #1{\settabs\+#1\cr}
+%\def\tabline{\parsearg\tablinezzz}
+%\def\tablinezzz #1{\+#1\cr}
+%\def\&{&}
+
+% Tables -- @table, @ftable, @vtable, @item(x), @kitem(x), @xitem(x).
+
+% default indentation of table text
+\newdimen\tableindent \tableindent=.8in
+% default indentation of @itemize and @enumerate text
+\newdimen\itemindent \itemindent=.3in
+% margin between end of table item and start of table text.
+\newdimen\itemmargin \itemmargin=.1in
+
+% used internally for \itemindent minus \itemmargin
+\newdimen\itemmax
+
+% Note @table, @vtable, and @vtable define @item, @itemx, etc., with
+% these defs.
+% They also define \itemindex
+% to index the item name in whatever manner is desired (perhaps none).
+
+\newif\ifitemxneedsnegativevskip
+
+\def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi}
+
+\def\internalBitem{\smallbreak \parsearg\itemzzz}
+\def\internalBitemx{\itemxpar \parsearg\itemzzz}
+
+\def\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz}
+\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \itemxpar \parsearg\xitemzzz}
+
+\def\internalBkitem{\smallbreak \parsearg\kitemzzz}
+\def\internalBkitemx{\itemxpar \parsearg\kitemzzz}
+
+\def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}%
+ \itemzzz {#1}}
+
+\def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}%
+ \itemzzz {#1}}
+
+\def\itemzzz #1{\begingroup %
+ \advance\hsize by -\rightskip
+ \advance\hsize by -\tableindent
+ \setbox0=\hbox{\itemfont{#1}}%
+ \itemindex{#1}%
+ \nobreak % This prevents a break before @itemx.
+ %
+ % Be sure we are not still in the middle of a paragraph.
+ %{\parskip = 0in
+ %\par
+ %}%
+ %
+ % If the item text does not fit in the space we have, put it on a line
+ % by itself, and do not allow a page break either before or after that
+ % line. We do not start a paragraph here because then if the next
+ % command is, e.g., @kindex, the whatsit would get put into the
+ % horizontal list on a line by itself, resulting in extra blank space.
+ \ifdim \wd0>\itemmax
+ %
+ % Make this a paragraph so we get the \parskip glue and wrapping,
+ % but leave it ragged-right.
+ \begingroup
+ \advance\leftskip by-\tableindent
+ \advance\hsize by\tableindent
+ \advance\rightskip by0pt plus1fil
+ \leavevmode\unhbox0\par
+ \endgroup
+ %
+ % We're going to be starting a paragraph, but we don't want the
+ % \parskip glue -- logically it's part of the @item we just started.
+ \nobreak \vskip-\parskip
+ %
+ % Stop a page break at the \parskip glue coming up. Unfortunately
+ % we can't prevent a possible page break at the following
+ % \baselineskip glue.
+ \nobreak
+ \endgroup
+ \itemxneedsnegativevskipfalse
+ \else
+ % The item text fits into the space. Start a paragraph, so that the
+ % following text (if any) will end up on the same line. Since that
+ % text will be indented by \tableindent, we make the item text be in
+ % a zero-width box.
+ \noindent
+ \rlap{\hskip -\tableindent\box0}\ignorespaces%
+ \endgroup%
+ \itemxneedsnegativevskiptrue%
+ \fi
+}
+
+\def\item{\errmessage{@item while not in a table}}
+\def\itemx{\errmessage{@itemx while not in a table}}
+\def\kitem{\errmessage{@kitem while not in a table}}
+\def\kitemx{\errmessage{@kitemx while not in a table}}
+\def\xitem{\errmessage{@xitem while not in a table}}
+\def\xitemx{\errmessage{@xitemx while not in a table}}
+
+%% Contains a kludge to get @end[description] to work
+\def\description{\tablez{\dontindex}{1}{}{}{}{}}
+
+\def\table{\begingroup\inENV\obeylines\obeyspaces\tablex}
+{\obeylines\obeyspaces%
+\gdef\tablex #1^^M{%
+\tabley\dontindex#1 \endtabley}}
+
+\def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex}
+{\obeylines\obeyspaces%
+\gdef\ftablex #1^^M{%
+\tabley\fnitemindex#1 \endtabley
+\def\Eftable{\endgraf\afterenvbreak\endgroup}%
+\let\Etable=\relax}}
+
+\def\vtable{\begingroup\inENV\obeylines\obeyspaces\vtablex}
+{\obeylines\obeyspaces%
+\gdef\vtablex #1^^M{%
+\tabley\vritemindex#1 \endtabley
+\def\Evtable{\endgraf\afterenvbreak\endgroup}%
+\let\Etable=\relax}}
+
+\def\dontindex #1{}
+\def\fnitemindex #1{\doind {fn}{\code{#1}}}%
+\def\vritemindex #1{\doind {vr}{\code{#1}}}%
+
+{\obeyspaces %
+\gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup%
+\tablez{#1}{#2}{#3}{#4}{#5}{#6}}}
+
+\def\tablez #1#2#3#4#5#6{%
+\aboveenvbreak %
+\begingroup %
+\def\Edescription{\Etable}% Necessary kludge.
+\let\itemindex=#1%
+\ifnum 0#3>0 \advance \leftskip by #3\mil \fi %
+\ifnum 0#4>0 \tableindent=#4\mil \fi %
+\ifnum 0#5>0 \advance \rightskip by #5\mil \fi %
+\def\itemfont{#2}%
+\itemmax=\tableindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \tableindent %
+\exdentamount=\tableindent
+\parindent = 0pt
+\parskip = \smallskipamount
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def\Etable{\endgraf\afterenvbreak\endgroup}%
+\let\item = \internalBitem %
+\let\itemx = \internalBitemx %
+\let\kitem = \internalBkitem %
+\let\kitemx = \internalBkitemx %
+\let\xitem = \internalBxitem %
+\let\xitemx = \internalBxitemx %
+}
+
+% This is the counter used by @enumerate, which is really @itemize
+
+\newcount \itemno
+
+\def\itemize{\parsearg\itemizezzz}
+
+\def\itemizezzz #1{%
+ \begingroup % ended by the @end itemsize
+ \itemizey {#1}{\Eitemize}
+}
+
+\def\itemizey #1#2{%
+\aboveenvbreak %
+\itemmax=\itemindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \itemindent %
+\exdentamount=\itemindent
+\parindent = 0pt %
+\parskip = \smallskipamount %
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def#2{\endgraf\afterenvbreak\endgroup}%
+\def\itemcontents{#1}%
+\let\item=\itemizeitem}
+
+% Set sfcode to normal for the chars that usually have another value.
+% These are `.?!:;,'
+\def\frenchspacing{\sfcode46=1000 \sfcode63=1000 \sfcode33=1000
+ \sfcode58=1000 \sfcode59=1000 \sfcode44=1000 }
+
+% \splitoff TOKENS\endmark defines \first to be the first token in
+% TOKENS, and \rest to be the remainder.
+%
+\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}%
+
+% Allow an optional argument of an uppercase letter, lowercase letter,
+% or number, to specify the first label in the enumerated list. No
+% argument is the same as `1'.
+%
+\def\enumerate{\parsearg\enumeratezzz}
+\def\enumeratezzz #1{\enumeratey #1 \endenumeratey}
+\def\enumeratey #1 #2\endenumeratey{%
+ \begingroup % ended by the @end enumerate
+ %
+ % If we were given no argument, pretend we were given `1'.
+ \def\thearg{#1}%
+ \ifx\thearg\empty \def\thearg{1}\fi
+ %
+ % Detect if the argument is a single token. If so, it might be a
+ % letter. Otherwise, the only valid thing it can be is a number.
+ % (We will always have one token, because of the test we just made.
+ % This is a good thing, since \splitoff doesn't work given nothing at
+ % all -- the first parameter is undelimited.)
+ \expandafter\splitoff\thearg\endmark
+ \ifx\rest\empty
+ % Only one token in the argument. It could still be anything.
+ % A ``lowercase letter'' is one whose \lccode is nonzero.
+ % An ``uppercase letter'' is one whose \lccode is both nonzero, and
+ % not equal to itself.
+ % Otherwise, we assume it's a number.
+ %
+ % We need the \relax at the end of the \ifnum lines to stop TeX from
+ % continuing to look for a <number>.
+ %
+ \ifnum\lccode\expandafter`\thearg=0\relax
+ \numericenumerate % a number (we hope)
+ \else
+ % It's a letter.
+ \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax
+ \lowercaseenumerate % lowercase letter
+ \else
+ \uppercaseenumerate % uppercase letter
+ \fi
+ \fi
+ \else
+ % Multiple tokens in the argument. We hope it's a number.
+ \numericenumerate
+ \fi
+}
+
+% An @enumerate whose labels are integers. The starting integer is
+% given in \thearg.
+%
+\def\numericenumerate{%
+ \itemno = \thearg
+ \startenumeration{\the\itemno}%
+}
+
+% The starting (lowercase) letter is in \thearg.
+\def\lowercaseenumerate{%
+ \itemno = \expandafter`\thearg
+ \startenumeration{%
+ % Be sure we're not beyond the end of the alphabet.
+ \ifnum\itemno=0
+ \errmessage{No more lowercase letters in @enumerate; get a bigger
+ alphabet}%
+ \fi
+ \char\lccode\itemno
+ }%
+}
+
+% The starting (uppercase) letter is in \thearg.
+\def\uppercaseenumerate{%
+ \itemno = \expandafter`\thearg
+ \startenumeration{%
+ % Be sure we're not beyond the end of the alphabet.
+ \ifnum\itemno=0
+ \errmessage{No more uppercase letters in @enumerate; get a bigger
+ alphabet}
+ \fi
+ \char\uccode\itemno
+ }%
+}
+
+% Call itemizey, adding a period to the first argument and supplying the
+% common last two arguments. Also subtract one from the initial value in
+% \itemno, since @item increments \itemno.
+%
+\def\startenumeration#1{%
+ \advance\itemno by -1
+ \itemizey{#1.}\Eenumerate\flushcr
+}
+
+% @alphaenumerate and @capsenumerate are abbreviations for giving an arg
+% to @enumerate.
+%
+\def\alphaenumerate{\enumerate{a}}
+\def\capsenumerate{\enumerate{A}}
+\def\Ealphaenumerate{\Eenumerate}
+\def\Ecapsenumerate{\Eenumerate}
+
+% Definition of @item while inside @itemize.
+
+\def\itemizeitem{%
+\advance\itemno by 1
+{\let\par=\endgraf \smallbreak}%
+\ifhmode \errmessage{\in hmode at itemizeitem}\fi
+{\parskip=0in \hskip 0pt
+\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}%
+\vadjust{\penalty 1200}}%
+\flushcr}
+
+% @multitable macros
+% Amy Hendrickson, 8/18/94, 3/6/96
+%
+% @multitable ... @end multitable will make as many columns as desired.
+% Contents of each column will wrap at width given in preamble. Width
+% can be specified either with sample text given in a template line,
+% or in percent of \hsize, the current width of text on page.
+
+% Table can continue over pages but will only break between lines.
+
+% To make preamble:
+%
+% Either define widths of columns in terms of percent of \hsize:
+% @multitable @columnfractions .25 .3 .45
+% @item ...
+%
+% Numbers following @columnfractions are the percent of the total
+% current hsize to be used for each column. You may use as many
+% columns as desired.
+
+% Or use a template:
+% @multitable {Column 1 template} {Column 2 template} {Column 3 template}
+% @item ...
+% using the widest term desired in each column.
+%
+% For those who want to use more than one line's worth of words in
+% the preamble, break the line within one argument and it
+% will parse correctly, i.e.,
+%
+% @multitable {Column 1 template} {Column 2 template} {Column 3
+% template}
+% Not:
+% @multitable {Column 1 template} {Column 2 template}
+% {Column 3 template}
+
+% Each new table line starts with @item, each subsequent new column
+% starts with @tab. Empty columns may be produced by supplying @tab's
+% with nothing between them for as many times as empty columns are needed,
+% ie, @tab@tab@tab will produce two empty columns.
+
+% @item, @tab, @multicolumn or @endmulticolumn do not need to be on their
+% own lines, but it will not hurt if they are.
+
+% Sample multitable:
+
+% @multitable {Column 1 template} {Column 2 template} {Column 3 template}
+% @item first col stuff @tab second col stuff @tab third col
+% @item
+% first col stuff
+% @tab
+% second col stuff
+% @tab
+% third col
+% @item first col stuff @tab second col stuff
+% @tab Many paragraphs of text may be used in any column.
+%
+% They will wrap at the width determined by the template.
+% @item@tab@tab This will be in third column.
+% @end multitable
+
+% Default dimensions may be reset by user.
+% @multitableparskip is vertical space between paragraphs in table.
+% @multitableparindent is paragraph indent in table.
+% @multitablecolmargin is horizontal space to be left between columns.
+% @multitablelinespace is space to leave between table items, baseline
+% to baseline.
+% 0pt means it depends on current normal line spacing.
+
+%%%%
+% Dimensions
+
+\newskip\multitableparskip
+\newskip\multitableparindent
+\newdimen\multitablecolspace
+\newskip\multitablelinespace
+\multitableparskip=0pt
+\multitableparindent=6pt
+\multitablecolspace=12pt
+\multitablelinespace=0pt
+
+%%%%
+% Macros used to set up halign preamble:
+\let\endsetuptable\relax
+\def\xendsetuptable{\endsetuptable}
+\let\columnfractions\relax
+\def\xcolumnfractions{\columnfractions}
+\newif\ifsetpercent
+
+%% 2/1/96, to allow fractions to be given with more than one digit.
+\def\pickupwholefraction#1 {\global\advance\colcount by1 %
+\expandafter\xdef\csname col\the\colcount\endcsname{.#1\hsize}%
+\setuptable}
+
+\newcount\colcount
+\def\setuptable#1{\def\firstarg{#1}%
+\ifx\firstarg\xendsetuptable\let\go\relax%
+\else
+ \ifx\firstarg\xcolumnfractions\global\setpercenttrue%
+ \else
+ \ifsetpercent
+ \let\go\pickupwholefraction % In this case arg of setuptable
+ % is the decimal point before the
+ % number given in percent of hsize.
+ % We don't need this so we don't use it.
+ \else
+ \global\advance\colcount by1
+ \setbox0=\hbox{#1}%
+ \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}%
+ \fi%
+ \fi%
+\ifx\go\pickupwholefraction\else\let\go\setuptable\fi%
+\fi\go}
+
+%%%%
+% multitable syntax
+\def\tab{&\hskip1sp\relax} % 2/2/96
+ % tiny skip here makes sure this column space is
+ % maintained, even if it is never used.
+
+
+%%%%
+% @multitable ... @end multitable definitions:
+
+\def\multitable{\parsearg\dotable}
+
+\def\dotable#1{\bgroup
+\let\item\cr
+\tolerance=9500
+\hbadness=9500
+\setmultitablespacing
+\parskip=\multitableparskip
+\parindent=\multitableparindent
+\overfullrule=0pt
+\global\colcount=0\relax%
+\def\Emultitable{\global\setpercentfalse\global\everycr{}\cr\egroup\egroup}%
+ % To parse everything between @multitable and @item :
+\setuptable#1 \endsetuptable
+ % Need to reset this to 0 after \setuptable.
+\global\colcount=0\relax%
+ %
+ % This preamble sets up a generic column definition, which will
+ % be used as many times as user calls for columns.
+ % \vtop will set a single line and will also let text wrap and
+ % continue for many paragraphs if desired.
+\halign\bgroup&\global\advance\colcount by 1\relax%
+\multistrut\vtop{\hsize=\expandafter\csname col\the\colcount\endcsname
+ % In order to keep entries from bumping into each other
+ % we will add a \leftskip of \multitablecolspace to all columns after
+ % the first one.
+ % If a template has been used, we will add \multitablecolspace
+ % to the width of each template entry.
+ % If user has set preamble in terms of percent of \hsize
+ % we will use that dimension as the width of the column, and
+ % the \leftskip will keep entries from bumping into each other.
+ % Table will start at left margin and final column will justify at
+ % right margin.
+\ifnum\colcount=1
+\else
+ \ifsetpercent
+ \else
+ % If user has <not> set preamble in terms of percent of \hsize
+ % we will advance \hsize by \multitablecolspace
+ \advance\hsize by \multitablecolspace
+ \fi
+ % In either case we will make \leftskip=\multitablecolspace:
+\leftskip=\multitablecolspace
+\fi
+\noindent##}\cr%
+ % \everycr will reset column counter, \colcount, at the end of
+ % each line. Every column entry will cause \colcount to advance by one.
+ % The table preamble
+ % looks at the current \colcount to find the correct column width.
+\global\everycr{\noalign{%
+\filbreak%% keeps underfull box messages off when table breaks over pages.
+\global\colcount=0\relax}}
+}
+
+\def\setmultitablespacing{% test to see if user has set \multitablelinespace.
+% If so, do nothing. If not, give it an appropriate dimension based on
+% current baselineskip.
+\setbox0=\vbox{Xy}
+\ifdim\multitablelinespace=0pt
+%% strut to put in table in case some entry doesn't have descenders,
+%% to keep lines equally spaced
+\gdef\multistrut{\vrule height\ht0 depth\dp0 width0pt\relax}
+%% Test to see if parskip is larger than space between lines of
+%% table. If not, do nothing.
+%% If so, set to same dimension as multitablelinespace.
+\else
+\gdef\multistrut{\vrule height\multitablelinespace depth\dp0
+width0pt\relax} \fi
+\ifdim\multitableparskip>\multitablelinespace
+\global\multitableparskip=\multitablelinespace
+\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller
+ %% than skip between lines in the table.
+\fi%
+\ifdim\multitableparskip=0pt
+\global\multitableparskip=\multitablelinespace
+\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller
+ %% than skip between lines in the table.
+\fi}
+\message{indexing,}
+% Index generation facilities
+
+% Define \newwrite to be identical to plain tex's \newwrite
+% except not \outer, so it can be used within \newindex.
+{\catcode`\@=11
+\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}}
+
+% \newindex {foo} defines an index named foo.
+% It automatically defines \fooindex such that
+% \fooindex ...rest of line... puts an entry in the index foo.
+% It also defines \fooindfile to be the number of the output channel for
+% the file that accumulates this index. The file's extension is foo.
+% The name of an index should be no more than 2 characters long
+% for the sake of vms.
+
+\def\newindex #1{
+\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file
+\openout \csname#1indfile\endcsname \jobname.#1 % Open the file
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\doindex {#1}}
+}
+
+% @defindex foo == \newindex{foo}
+
+\def\defindex{\parsearg\newindex}
+
+% Define @defcodeindex, like @defindex except put all entries in @code.
+
+\def\newcodeindex #1{
+\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file
+\openout \csname#1indfile\endcsname \jobname.#1 % Open the file
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\docodeindex {#1}}
+}
+
+\def\defcodeindex{\parsearg\newcodeindex}
+
+% @synindex foo bar makes index foo feed into index bar.
+% Do this instead of @defindex foo if you don't want it as a separate index.
+\def\synindex #1 #2 {%
+\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
+\expandafter\let\csname#1indfile\endcsname=\synindexfoo
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\doindex {#2}}%
+}
+
+% @syncodeindex foo bar similar, but put all entries made for index foo
+% inside @code.
+\def\syncodeindex #1 #2 {%
+\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
+\expandafter\let\csname#1indfile\endcsname=\synindexfoo
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\docodeindex {#2}}%
+}
+
+% Define \doindex, the driver for all \fooindex macros.
+% Argument #1 is generated by the calling \fooindex macro,
+% and it is "foo", the name of the index.
+
+% \doindex just uses \parsearg; it calls \doind for the actual work.
+% This is because \doind is more useful to call from other macros.
+
+% There is also \dosubind {index}{topic}{subtopic}
+% which makes an entry in a two-level index such as the operation index.
+
+\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer}
+\def\singleindexer #1{\doind{\indexname}{#1}}
+
+% like the previous two, but they put @code around the argument.
+\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer}
+\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}}
+
+\def\indexdummies{%
+% Take care of the plain tex accent commands.
+\def\"{\realbackslash "}%
+\def\`{\realbackslash `}%
+\def\'{\realbackslash '}%
+\def\^{\realbackslash ^}%
+\def\~{\realbackslash ~}%
+\def\={\realbackslash =}%
+\def\b{\realbackslash b}%
+\def\c{\realbackslash c}%
+\def\d{\realbackslash d}%
+\def\u{\realbackslash u}%
+\def\v{\realbackslash v}%
+\def\H{\realbackslash H}%
+% Take care of the plain tex special European modified letters.
+\def\oe{\realbackslash oe}%
+\def\ae{\realbackslash ae}%
+\def\aa{\realbackslash aa}%
+\def\OE{\realbackslash OE}%
+\def\AE{\realbackslash AE}%
+\def\AA{\realbackslash AA}%
+\def\o{\realbackslash o}%
+\def\O{\realbackslash O}%
+\def\l{\realbackslash l}%
+\def\L{\realbackslash L}%
+\def\ss{\realbackslash ss}%
+% Take care of texinfo commands likely to appear in an index entry.
+\def\_{{\realbackslash _}}%
+\def\w{\realbackslash w }%
+\def\bf{\realbackslash bf }%
+\def\rm{\realbackslash rm }%
+\def\sl{\realbackslash sl }%
+\def\sf{\realbackslash sf}%
+\def\tt{\realbackslash tt}%
+\def\gtr{\realbackslash gtr}%
+\def\less{\realbackslash less}%
+\def\hat{\realbackslash hat}%
+\def\char{\realbackslash char}%
+\def\TeX{\realbackslash TeX}%
+\def\dots{\realbackslash dots }%
+\def\copyright{\realbackslash copyright }%
+\def\tclose##1{\realbackslash tclose {##1}}%
+\def\code##1{\realbackslash code {##1}}%
+\def\samp##1{\realbackslash samp {##1}}%
+\def\t##1{\realbackslash r {##1}}%
+\def\r##1{\realbackslash r {##1}}%
+\def\i##1{\realbackslash i {##1}}%
+\def\b##1{\realbackslash b {##1}}%
+\def\cite##1{\realbackslash cite {##1}}%
+\def\key##1{\realbackslash key {##1}}%
+\def\file##1{\realbackslash file {##1}}%
+\def\var##1{\realbackslash var {##1}}%
+\def\kbd##1{\realbackslash kbd {##1}}%
+\def\dfn##1{\realbackslash dfn {##1}}%
+\def\emph##1{\realbackslash emph {##1}}%
+\unsepspaces
+}
+
+% If an index command is used in an @example environment, any spaces
+% therein should become regular spaces in the raw index file, not the
+% expansion of \tie (\\leavevmode \penalty \@M \ ).
+{\obeyspaces
+ \gdef\unsepspaces{\obeyspaces\let =\space}}
+
+% \indexnofonts no-ops all font-change commands.
+% This is used when outputting the strings to sort the index by.
+\def\indexdummyfont#1{#1}
+\def\indexdummytex{TeX}
+\def\indexdummydots{...}
+
+\def\indexnofonts{%
+% Just ignore accents.
+\let\"=\indexdummyfont
+\let\`=\indexdummyfont
+\let\'=\indexdummyfont
+\let\^=\indexdummyfont
+\let\~=\indexdummyfont
+\let\==\indexdummyfont
+\let\b=\indexdummyfont
+\let\c=\indexdummyfont
+\let\d=\indexdummyfont
+\let\u=\indexdummyfont
+\let\v=\indexdummyfont
+\let\H=\indexdummyfont
+% Take care of the plain tex special European modified letters.
+\def\oe{oe}%
+\def\ae{ae}%
+\def\aa{aa}%
+\def\OE{OE}%
+\def\AE{AE}%
+\def\AA{AA}%
+\def\o{o}%
+\def\O{O}%
+\def\l{l}%
+\def\L{L}%
+\def\ss{ss}%
+\let\w=\indexdummyfont
+\let\t=\indexdummyfont
+\let\r=\indexdummyfont
+\let\i=\indexdummyfont
+\let\b=\indexdummyfont
+\let\emph=\indexdummyfont
+\let\strong=\indexdummyfont
+\let\cite=\indexdummyfont
+\let\sc=\indexdummyfont
+%Don't no-op \tt, since it isn't a user-level command
+% and is used in the definitions of the active chars like <, >, |...
+%\let\tt=\indexdummyfont
+\let\tclose=\indexdummyfont
+\let\code=\indexdummyfont
+\let\file=\indexdummyfont
+\let\samp=\indexdummyfont
+\let\kbd=\indexdummyfont
+\let\key=\indexdummyfont
+\let\var=\indexdummyfont
+\let\TeX=\indexdummytex
+\let\dots=\indexdummydots
+}
+
+% To define \realbackslash, we must make \ not be an escape.
+% We must first make another character (@) an escape
+% so we do not become unable to do a definition.
+
+{\catcode`\@=0 \catcode`\\=\other
+@gdef@realbackslash{\}}
+
+\let\indexbackslash=0 %overridden during \printindex.
+
+\let\SETmarginindex=\relax %initialize!
+% workhorse for all \fooindexes
+% #1 is name of index, #2 is stuff to put there
+\def\doind #1#2{%
+% Put the index entry in the margin if desired.
+\ifx\SETmarginindex\relax\else%
+\insert\margin{\hbox{\vrule height8pt depth3pt width0pt #2}}%
+\fi%
+{\count10=\lastpenalty %
+{\indexdummies % Must do this here, since \bf, etc expand at this stage
+\escapechar=`\\%
+{\let\folio=0% Expand all macros now EXCEPT \folio
+\def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now
+% so it will be output as is; and it will print as backslash in the indx.
+%
+% Now process the index-string once, with all font commands turned off,
+% to get the string to sort the index by.
+{\indexnofonts
+\xdef\temp1{#2}%
+}%
+% Now produce the complete index entry. We process the index-string again,
+% this time with font commands expanded, to get what to print in the index.
+\edef\temp{%
+\write \csname#1indfile\endcsname{%
+\realbackslash entry {\temp1}{\folio}{#2}}}%
+\temp }%
+}\penalty\count10}}
+
+\def\dosubind #1#2#3{%
+{\count10=\lastpenalty %
+{\indexdummies % Must do this here, since \bf, etc expand at this stage
+\escapechar=`\\%
+{\let\folio=0%
+\def\rawbackslashxx{\indexbackslash}%
+%
+% Now process the index-string once, with all font commands turned off,
+% to get the string to sort the index by.
+{\indexnofonts
+\xdef\temp1{#2 #3}%
+}%
+% Now produce the complete index entry. We process the index-string again,
+% this time with font commands expanded, to get what to print in the index.
+\edef\temp{%
+\write \csname#1indfile\endcsname{%
+\realbackslash entry {\temp1}{\folio}{#2}{#3}}}%
+\temp }%
+}\penalty\count10}}
+
+% The index entry written in the file actually looks like
+% \entry {sortstring}{page}{topic}
+% or
+% \entry {sortstring}{page}{topic}{subtopic}
+% The texindex program reads in these files and writes files
+% containing these kinds of lines:
+% \initial {c}
+% before the first topic whose initial is c
+% \entry {topic}{pagelist}
+% for a topic that is used without subtopics
+% \primary {topic}
+% for the beginning of a topic that is used with subtopics
+% \secondary {subtopic}{pagelist}
+% for each subtopic.
+
+% Define the user-accessible indexing commands
+% @findex, @vindex, @kindex, @cindex.
+
+\def\findex {\fnindex}
+\def\kindex {\kyindex}
+\def\cindex {\cpindex}
+\def\vindex {\vrindex}
+\def\tindex {\tpindex}
+\def\pindex {\pgindex}
+
+\def\cindexsub {\begingroup\obeylines\cindexsub}
+{\obeylines %
+\gdef\cindexsub "#1" #2^^M{\endgroup %
+\dosubind{cp}{#2}{#1}}}
+
+% Define the macros used in formatting output of the sorted index material.
+
+% This is what you call to cause a particular index to get printed.
+% Write
+% @unnumbered Function Index
+% @printindex fn
+
+\def\printindex{\parsearg\doprintindex}
+
+\def\doprintindex#1{%
+ \tex
+ \dobreak \chapheadingskip {10000}
+ \catcode`\%=\other\catcode`\&=\other\catcode`\#=\other
+ \catcode`\$=\other
+ \catcode`\~=\other
+ \indexbreaks
+ %
+ % The following don't help, since the chars were translated
+ % when the raw index was written, and their fonts were discarded
+ % due to \indexnofonts.
+ %\catcode`\"=\active
+ %\catcode`\^=\active
+ %\catcode`\_=\active
+ %\catcode`\|=\active
+ %\catcode`\<=\active
+ %\catcode`\>=\active
+ % %
+ \def\indexbackslash{\rawbackslashxx}
+ \indexfonts\rm \tolerance=9500 \advance\baselineskip -1pt
+ \begindoublecolumns
+ %
+ % See if the index file exists and is nonempty.
+ \openin 1 \jobname.#1s
+ \ifeof 1
+ % \enddoublecolumns gets confused if there is no text in the index,
+ % and it loses the chapter title and the aux file entries for the
+ % index. The easiest way to prevent this problem is to make sure
+ % there is some text.
+ (Index is nonexistent)
+ \else
+ %
+ % If the index file exists but is empty, then \openin leaves \ifeof
+ % false. We have to make TeX try to read something from the file, so
+ % it can discover if there is anything in it.
+ \read 1 to \temp
+ \ifeof 1
+ (Index is empty)
+ \else
+ \input \jobname.#1s
+ \fi
+ \fi
+ \closein 1
+ \enddoublecolumns
+ \Etex
+}
+
+% These macros are used by the sorted index file itself.
+% Change them to control the appearance of the index.
+
+% Same as \bigskipamount except no shrink.
+% \balancecolumns gets confused if there is any shrink.
+\newskip\initialskipamount \initialskipamount 12pt plus4pt
+
+\def\initial #1{%
+{\let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt
+\ifdim\lastskip<\initialskipamount
+\removelastskip \penalty-200 \vskip \initialskipamount\fi
+\line{\secbf#1\hfill}\kern 2pt\penalty10000}}
+
+% This typesets a paragraph consisting of #1, dot leaders, and then #2
+% flush to the right margin. It is used for index and table of contents
+% entries. The paragraph is indented by \leftskip.
+%
+\def\entry #1#2{\begingroup
+ %
+ % Start a new paragraph if necessary, so our assignments below can't
+ % affect previous text.
+ \par
+ %
+ % Do not fill out the last line with white space.
+ \parfillskip = 0in
+ %
+ % No extra space above this paragraph.
+ \parskip = 0in
+ %
+ % Do not prefer a separate line ending with a hyphen to fewer lines.
+ \finalhyphendemerits = 0
+ %
+ % \hangindent is only relevant when the entry text and page number
+ % don't both fit on one line. In that case, bob suggests starting the
+ % dots pretty far over on the line. Unfortunately, a large
+ % indentation looks wrong when the entry text itself is broken across
+ % lines. So we use a small indentation and put up with long leaders.
+ %
+ % \hangafter is reset to 1 (which is the value we want) at the start
+ % of each paragraph, so we need not do anything with that.
+ \hangindent=2em
+ %
+ % When the entry text needs to be broken, just fill out the first line
+ % with blank space.
+ \rightskip = 0pt plus1fil
+ %
+ % Start a ``paragraph'' for the index entry so the line breaking
+ % parameters we've set above will have an effect.
+ \noindent
+ %
+ % Insert the text of the index entry. TeX will do line-breaking on it.
+ #1%
+ % The following is kludged to not output a line of dots in the index if
+ % there are no page numbers. The next person who breaks this will be
+ % cursed by a Unix daemon.
+ \def\tempa{{\rm }}%
+ \def\tempb{#2}%
+ \edef\tempc{\tempa}%
+ \edef\tempd{\tempb}%
+ \ifx\tempc\tempd\ \else%
+ %
+ % If we must, put the page number on a line of its own, and fill out
+ % this line with blank space. (The \hfil is overwhelmed with the
+ % fill leaders glue in \indexdotfill if the page number does fit.)
+ \hfil\penalty50
+ \null\nobreak\indexdotfill % Have leaders before the page number.
+ %
+ % The `\ ' here is removed by the implicit \unskip that TeX does as
+ % part of (the primitive) \par. Without it, a spurious underfull
+ % \hbox ensues.
+ \ #2% The page number ends the paragraph.
+ \fi%
+ \par
+\endgroup}
+
+% Like \dotfill except takes at least 1 em.
+\def\indexdotfill{\cleaders
+ \hbox{$\mathsurround=0pt \mkern1.5mu ${\it .}$ \mkern1.5mu$}\hskip 1em plus 1fill}
+
+\def\primary #1{\line{#1\hfil}}
+
+\newskip\secondaryindent \secondaryindent=0.5cm
+
+\def\secondary #1#2{
+{\parfillskip=0in \parskip=0in
+\hangindent =1in \hangafter=1
+\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\par
+}}
+
+%% Define two-column mode, which is used in indexes.
+%% Adapted from the TeXbook, page 416.
+\catcode `\@=11
+
+\newbox\partialpage
+
+\newdimen\doublecolumnhsize
+
+\def\begindoublecolumns{\begingroup
+ % Grab any single-column material above us.
+ \output = {\global\setbox\partialpage
+ =\vbox{\unvbox255\kern -\topskip \kern \baselineskip}}%
+ \eject
+ %
+ % Now switch to the double-column output routine.
+ \output={\doublecolumnout}%
+ %
+ % Change the page size parameters. We could do this once outside this
+ % routine, in each of @smallbook, @afourpaper, and the default 8.5x11
+ % format, but then we repeat the same computation. Repeating a couple
+ % of assignments once per index is clearly meaningless for the
+ % execution time, so we may as well do it once.
+ %
+ % First we halve the line length, less a little for the gutter between
+ % the columns. We compute the gutter based on the line length, so it
+ % changes automatically with the paper format. The magic constant
+ % below is chosen so that the gutter has the same value (well, +- <
+ % 1pt) as it did when we hard-coded it.
+ %
+ % We put the result in a separate register, \doublecolumhsize, so we
+ % can restore it in \pagesofar, after \hsize itself has (potentially)
+ % been clobbered.
+ %
+ \doublecolumnhsize = \hsize
+ \advance\doublecolumnhsize by -.04154\hsize
+ \divide\doublecolumnhsize by 2
+ \hsize = \doublecolumnhsize
+ %
+ % Double the \vsize as well. (We don't need a separate register here,
+ % since nobody clobbers \vsize.)
+ \vsize = 2\vsize
+ \doublecolumnpagegoal
+}
+
+\def\enddoublecolumns{\eject \endgroup \pagegoal=\vsize \unvbox\partialpage}
+
+\def\doublecolumnsplit{\splittopskip=\topskip \splitmaxdepth=\maxdepth
+ \global\dimen@=\pageheight \global\advance\dimen@ by-\ht\partialpage
+ \global\setbox1=\vsplit255 to\dimen@ \global\setbox0=\vbox{\unvbox1}
+ \global\setbox3=\vsplit255 to\dimen@ \global\setbox2=\vbox{\unvbox3}
+ \ifdim\ht0>\dimen@ \setbox255=\vbox{\unvbox0\unvbox2} \global\setbox255=\copy5 \fi
+ \ifdim\ht2>\dimen@ \setbox255=\vbox{\unvbox0\unvbox2} \global\setbox255=\copy5 \fi
+}
+\def\doublecolumnpagegoal{%
+ \dimen@=\vsize \advance\dimen@ by-2\ht\partialpage \global\pagegoal=\dimen@
+}
+\def\pagesofar{\unvbox\partialpage %
+ \hsize=\doublecolumnhsize % have to restore this since output routine
+ \wd0=\hsize \wd2=\hsize \hbox to\pagewidth{\box0\hfil\box2}}
+\def\doublecolumnout{%
+ \setbox5=\copy255
+ {\vbadness=10000 \doublecolumnsplit}
+ \ifvbox255
+ \setbox0=\vtop to\dimen@{\unvbox0}
+ \setbox2=\vtop to\dimen@{\unvbox2}
+ \onepageout\pagesofar \unvbox255 \penalty\outputpenalty
+ \else
+ \setbox0=\vbox{\unvbox5}
+ \ifvbox0
+ \dimen@=\ht0 \advance\dimen@ by\topskip \advance\dimen@ by-\baselineskip
+ \divide\dimen@ by2 \splittopskip=\topskip \splitmaxdepth=\maxdepth
+ {\vbadness=10000
+ \loop \global\setbox5=\copy0
+ \setbox1=\vsplit5 to\dimen@
+ \setbox3=\vsplit5 to\dimen@
+ \ifvbox5 \global\advance\dimen@ by1pt \repeat
+ \setbox0=\vbox to\dimen@{\unvbox1}
+ \setbox2=\vbox to\dimen@{\unvbox3}
+ \global\setbox\partialpage=\vbox{\pagesofar}
+ \doublecolumnpagegoal
+ }
+ \fi
+ \fi
+}
+
+\catcode `\@=\other
+\message{sectioning,}
+% Define chapters, sections, etc.
+
+\newcount \chapno
+\newcount \secno \secno=0
+\newcount \subsecno \subsecno=0
+\newcount \subsubsecno \subsubsecno=0
+
+% This counter is funny since it counts through charcodes of letters A, B, ...
+\newcount \appendixno \appendixno = `\@
+\def\appendixletter{\char\the\appendixno}
+
+\newwrite \contentsfile
+% This is called from \setfilename.
+\def\opencontents{\openout \contentsfile = \jobname.toc}
+
+% Each @chapter defines this as the name of the chapter.
+% page headings and footings can use it. @section does likewise
+
+\def\thischapter{} \def\thissection{}
+\def\seccheck#1{\if \pageno<0 %
+\errmessage{@#1 not allowed after generating table of contents}\fi
+%
+}
+
+\def\chapternofonts{%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\def\result{\realbackslash result}
+\def\equiv{\realbackslash equiv}
+\def\expansion{\realbackslash expansion}
+\def\print{\realbackslash print}
+\def\TeX{\realbackslash TeX}
+\def\dots{\realbackslash dots}
+\def\copyright{\realbackslash copyright}
+\def\tt{\realbackslash tt}
+\def\bf{\realbackslash bf }
+\def\w{\realbackslash w}
+\def\less{\realbackslash less}
+\def\gtr{\realbackslash gtr}
+\def\hat{\realbackslash hat}
+\def\char{\realbackslash char}
+\def\tclose##1{\realbackslash tclose {##1}}
+\def\code##1{\realbackslash code {##1}}
+\def\samp##1{\realbackslash samp {##1}}
+\def\r##1{\realbackslash r {##1}}
+\def\b##1{\realbackslash b {##1}}
+\def\key##1{\realbackslash key {##1}}
+\def\file##1{\realbackslash file {##1}}
+\def\kbd##1{\realbackslash kbd {##1}}
+% These are redefined because @smartitalic wouldn't work inside xdef.
+\def\i##1{\realbackslash i {##1}}
+\def\cite##1{\realbackslash cite {##1}}
+\def\var##1{\realbackslash var {##1}}
+\def\emph##1{\realbackslash emph {##1}}
+\def\dfn##1{\realbackslash dfn {##1}}
+}
+
+\newcount\absseclevel % used to calculate proper heading level
+\newcount\secbase\secbase=0 % @raise/lowersections modify this count
+
+% @raisesections: treat @section as chapter, @subsection as section, etc.
+\def\raisesections{\global\advance\secbase by -1}
+\let\up=\raisesections % original BFox name
+
+% @lowersections: treat @chapter as section, @section as subsection, etc.
+\def\lowersections{\global\advance\secbase by 1}
+\let\down=\lowersections % original BFox name
+
+% Choose a numbered-heading macro
+% #1 is heading level if unmodified by @raisesections or @lowersections
+% #2 is text for heading
+\def\numhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+ \chapterzzz{#2}
+\or
+ \seczzz{#2}
+\or
+ \numberedsubseczzz{#2}
+\or
+ \numberedsubsubseczzz{#2}
+\else
+ \ifnum \absseclevel<0
+ \chapterzzz{#2}
+ \else
+ \numberedsubsubseczzz{#2}
+ \fi
+\fi
+}
+
+% like \numhead, but chooses appendix heading levels
+\def\apphead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+ \appendixzzz{#2}
+\or
+ \appendixsectionzzz{#2}
+\or
+ \appendixsubseczzz{#2}
+\or
+ \appendixsubsubseczzz{#2}
+\else
+ \ifnum \absseclevel<0
+ \appendixzzz{#2}
+ \else
+ \appendixsubsubseczzz{#2}
+ \fi
+\fi
+}
+
+% like \numhead, but chooses numberless heading levels
+\def\unnmhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+ \unnumberedzzz{#2}
+\or
+ \unnumberedseczzz{#2}
+\or
+ \unnumberedsubseczzz{#2}
+\or
+ \unnumberedsubsubseczzz{#2}
+\else
+ \ifnum \absseclevel<0
+ \unnumberedzzz{#2}
+ \else
+ \unnumberedsubsubseczzz{#2}
+ \fi
+\fi
+}
+
+
+\def\thischaptername{No Chapter Title}
+\outer\def\chapter{\parsearg\chapteryyy}
+\def\chapteryyy #1{\numhead0{#1}} % normally numhead0 calls chapterzzz
+\def\chapterzzz #1{\seccheck{chapter}%
+\secno=0 \subsecno=0 \subsubsecno=0
+\global\advance \chapno by 1 \message{\putwordChapter \the\chapno}%
+\chapmacro {#1}{\the\chapno}%
+\gdef\thissection{#1}%
+\gdef\thischaptername{#1}%
+% We don't substitute the actual chapter name into \thischapter
+% because we don't want its macros evaluated now.
+\xdef\thischapter{\putwordChapter{} \the\chapno: \noexpand\thischaptername}%
+{\chapternofonts%
+\edef\temp{{\realbackslash chapentry {#1}{\the\chapno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\global\let\section = \numberedsec
+\global\let\subsection = \numberedsubsec
+\global\let\subsubsection = \numberedsubsubsec
+}}
+
+\outer\def\appendix{\parsearg\appendixyyy}
+\def\appendixyyy #1{\apphead0{#1}} % normally apphead0 calls appendixzzz
+\def\appendixzzz #1{\seccheck{appendix}%
+\secno=0 \subsecno=0 \subsubsecno=0
+\global\advance \appendixno by 1 \message{Appendix \appendixletter}%
+\chapmacro {#1}{\putwordAppendix{} \appendixletter}%
+\gdef\thissection{#1}%
+\gdef\thischaptername{#1}%
+\xdef\thischapter{\putwordAppendix{} \appendixletter: \noexpand\thischaptername}%
+{\chapternofonts%
+\edef\temp{{\realbackslash chapentry
+ {#1}{\putwordAppendix{} \appendixletter}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\global\let\section = \appendixsec
+\global\let\subsection = \appendixsubsec
+\global\let\subsubsection = \appendixsubsubsec
+}}
+
+% @centerchap is like @unnumbered, but the heading is centered.
+\outer\def\centerchap{\parsearg\centerchapyyy}
+\def\centerchapyyy #1{{\let\unnumbchapmacro=\centerchapmacro \unnumberedyyy{#1}}}
+
+\outer\def\top{\parsearg\unnumberedyyy}
+\outer\def\unnumbered{\parsearg\unnumberedyyy}
+\def\unnumberedyyy #1{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz
+\def\unnumberedzzz #1{\seccheck{unnumbered}%
+\secno=0 \subsecno=0 \subsubsecno=0
+%
+% This used to be simply \message{#1}, but TeX fully expands the
+% argument to \message. Therefore, if #1 contained @-commands, TeX
+% expanded them. For example, in `@unnumbered The @cite{Book}', TeX
+% expanded @cite (which turns out to cause errors because \cite is meant
+% to be executed, not expanded).
+%
+% Anyway, we don't want the fully-expanded definition of @cite to appear
+% as a result of the \message, we just want `@cite' itself. We use
+% \the<toks register> to achieve this: TeX expands \the<toks> only once,
+% simply yielding the contents of the <toks register>.
+\toks0 = {#1}\message{(\the\toks0)}%
+%
+\unnumbchapmacro {#1}%
+\gdef\thischapter{#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbchapentry {#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\global\let\section = \unnumberedsec
+\global\let\subsection = \unnumberedsubsec
+\global\let\subsubsection = \unnumberedsubsubsec
+}}
+
+\outer\def\numberedsec{\parsearg\secyyy}
+\def\secyyy #1{\numhead1{#1}} % normally calls seczzz
+\def\seczzz #1{\seccheck{section}%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash secentry %
+{#1}{\the\chapno}{\the\secno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appendixsection{\parsearg\appendixsecyyy}
+\outer\def\appendixsec{\parsearg\appendixsecyyy}
+\def\appendixsecyyy #1{\apphead1{#1}} % normally calls appendixsectionzzz
+\def\appendixsectionzzz #1{\seccheck{appendixsection}%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash secentry %
+{#1}{\appendixletter}{\the\secno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsec{\parsearg\unnumberedsecyyy}
+\def\unnumberedsecyyy #1{\unnmhead1{#1}} % normally calls unnumberedseczzz
+\def\unnumberedseczzz #1{\seccheck{unnumberedsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\numberedsubsec{\parsearg\numberedsubsecyyy}
+\def\numberedsubsecyyy #1{\numhead2{#1}} % normally calls numberedsubseczzz
+\def\numberedsubseczzz #1{\seccheck{subsection}%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsecentry %
+{#1}{\the\chapno}{\the\secno}{\the\subsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appendixsubsec{\parsearg\appendixsubsecyyy}
+\def\appendixsubsecyyy #1{\apphead2{#1}} % normally calls appendixsubseczzz
+\def\appendixsubseczzz #1{\seccheck{appendixsubsec}%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsecentry %
+{#1}{\appendixletter}{\the\secno}{\the\subsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsubsec{\parsearg\unnumberedsubsecyyy}
+\def\unnumberedsubsecyyy #1{\unnmhead2{#1}} %normally calls unnumberedsubseczzz
+\def\unnumberedsubseczzz #1{\seccheck{unnumberedsubsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsubsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\numberedsubsubsec{\parsearg\numberedsubsubsecyyy}
+\def\numberedsubsubsecyyy #1{\numhead3{#1}} % normally numberedsubsubseczzz
+\def\numberedsubsubseczzz #1{\seccheck{subsubsection}%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}
+ {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsubsecentry %
+ {#1}
+ {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}
+ {\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appendixsubsubsec{\parsearg\appendixsubsubsecyyy}
+\def\appendixsubsubsecyyy #1{\apphead3{#1}} % normally appendixsubsubseczzz
+\def\appendixsubsubseczzz #1{\seccheck{appendixsubsubsec}%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}
+ {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsubsecentry{#1}%
+ {\appendixletter}
+ {\the\secno}{\the\subsecno}{\the\subsubsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubsecyyy}
+\def\unnumberedsubsubsecyyy #1{\unnmhead3{#1}} %normally unnumberedsubsubseczzz
+\def\unnumberedsubsubseczzz #1{\seccheck{unnumberedsubsubsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsubsubsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+% These are variants which are not "outer", so they can appear in @ifinfo.
+% Actually, they should now be obsolete; ordinary section commands should work.
+\def\infotop{\parsearg\unnumberedzzz}
+\def\infounnumbered{\parsearg\unnumberedzzz}
+\def\infounnumberedsec{\parsearg\unnumberedseczzz}
+\def\infounnumberedsubsec{\parsearg\unnumberedsubseczzz}
+\def\infounnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz}
+
+\def\infoappendix{\parsearg\appendixzzz}
+\def\infoappendixsec{\parsearg\appendixseczzz}
+\def\infoappendixsubsec{\parsearg\appendixsubseczzz}
+\def\infoappendixsubsubsec{\parsearg\appendixsubsubseczzz}
+
+\def\infochapter{\parsearg\chapterzzz}
+\def\infosection{\parsearg\sectionzzz}
+\def\infosubsection{\parsearg\subsectionzzz}
+\def\infosubsubsection{\parsearg\subsubsectionzzz}
+
+% These macros control what the section commands do, according
+% to what kind of chapter we are in (ordinary, appendix, or unnumbered).
+% Define them by default for a numbered chapter.
+\global\let\section = \numberedsec
+\global\let\subsection = \numberedsubsec
+\global\let\subsubsection = \numberedsubsubsec
+
+% Define @majorheading, @heading and @subheading
+
+% NOTE on use of \vbox for chapter headings, section headings, and
+% such:
+% 1) We use \vbox rather than the earlier \line to permit
+% overlong headings to fold.
+% 2) \hyphenpenalty is set to 10000 because hyphenation in a
+% heading is obnoxious; this forbids it.
+% 3) Likewise, headings look best if no \parindent is used, and
+% if justification is not attempted. Hence \raggedright.
+
+
+\def\majorheading{\parsearg\majorheadingzzz}
+\def\majorheadingzzz #1{%
+{\advance\chapheadingskip by 10pt \chapbreak }%
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 200}
+
+\def\chapheading{\parsearg\chapheadingzzz}
+\def\chapheadingzzz #1{\chapbreak %
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 200}
+
+\def\heading{\parsearg\secheadingi}
+
+\def\subheading{\parsearg\subsecheadingi}
+
+\def\subsubheading{\parsearg\subsubsecheadingi}
+
+% These macros generate a chapter, section, etc. heading only
+% (including whitespace, linebreaking, etc. around it),
+% given all the information in convenient, parsed form.
+
+%%% Args are the skip and penalty (usually negative)
+\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi}
+
+\def\setchapterstyle #1 {\csname CHAPF#1\endcsname}
+
+%%% Define plain chapter starts, and page on/off switching for it
+% Parameter controlling skip before chapter headings (if needed)
+
+\newskip \chapheadingskip \chapheadingskip = 30pt plus 8pt minus 4pt
+
+\def\chapbreak{\dobreak \chapheadingskip {-4000}}
+\def\chappager{\par\vfill\supereject}
+\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi}
+
+\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname}
+
+\def\CHAPPAGoff{
+\global\let\pchapsepmacro=\chapbreak
+\global\let\pagealignmacro=\chappager}
+
+\def\CHAPPAGon{
+\global\let\pchapsepmacro=\chappager
+\global\let\pagealignmacro=\chappager
+\global\def\HEADINGSon{\HEADINGSsingle}}
+
+\def\CHAPPAGodd{
+\global\let\pchapsepmacro=\chapoddpage
+\global\let\pagealignmacro=\chapoddpage
+\global\def\HEADINGSon{\HEADINGSdouble}}
+
+\CHAPPAGon
+
+\def\CHAPFplain{
+\global\let\chapmacro=\chfplain
+\global\let\unnumbchapmacro=\unnchfplain
+\global\let\centerchapmacro=\centerchfplain}
+
+\def\chfplain #1#2{%
+ \pchapsepmacro
+ {%
+ \chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #2\enspace #1}%
+ }%
+ \bigskip
+ \penalty5000
+}
+
+\def\unnchfplain #1{%
+\pchapsepmacro %
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 10000 %
+}
+
+\def\centerchfplain #1{%
+\pchapsepmacro %
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt
+ {\rm #1}\hfill}}\bigskip \par\penalty 10000 %
+}
+
+\CHAPFplain % The default
+
+\def\unnchfopen #1{%
+\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 10000 %
+}
+
+\def\chfopen #1#2{\chapoddpage {\chapfonts
+\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}%
+\par\penalty 5000 %
+}
+
+\def\centerchfopen #1{%
+\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt
+ \hfill {\rm #1}\hfill}}\bigskip \par\penalty 10000 %
+}
+
+\def\CHAPFopen{
+\global\let\chapmacro=\chfopen
+\global\let\unnumbchapmacro=\unnchfopen
+\global\let\centerchapmacro=\centerchfopen}
+
+% Parameter controlling skip before section headings.
+
+\newskip \subsecheadingskip \subsecheadingskip = 17pt plus 8pt minus 4pt
+\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}}
+
+\newskip \secheadingskip \secheadingskip = 21pt plus 8pt minus 4pt
+\def\secheadingbreak{\dobreak \secheadingskip {-1000}}
+
+% @paragraphindent is defined for the Info formatting commands only.
+\let\paragraphindent=\comment
+
+% Section fonts are the base font at magstep2, which produces
+% a size a bit more than 14 points in the default situation.
+
+\def\secheading #1#2#3{\secheadingi {#2.#3\enspace #1}}
+\def\plainsecheading #1{\secheadingi {#1}}
+\def\secheadingi #1{{\advance \secheadingskip by \parskip %
+\secheadingbreak}%
+{\secfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 }
+
+
+% Subsection fonts are the base font at magstep1,
+% which produces a size of 12 points.
+
+\def\subsecheading #1#2#3#4{\subsecheadingi {#2.#3.#4\enspace #1}}
+\def\subsecheadingi #1{{\advance \subsecheadingskip by \parskip %
+\subsecheadingbreak}%
+{\subsecfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 }
+
+\def\subsubsecfonts{\subsecfonts} % Maybe this should change:
+ % Perhaps make sssec fonts scaled
+ % magstep half
+\def\subsubsecheading #1#2#3#4#5{\subsubsecheadingi {#2.#3.#4.#5\enspace #1}}
+\def\subsubsecheadingi #1{{\advance \subsecheadingskip by \parskip %
+\subsecheadingbreak}%
+{\subsubsecfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000}
+
+
+\message{toc printing,}
+
+% Finish up the main text and prepare to read what we've written
+% to \contentsfile.
+
+\newskip\contentsrightmargin \contentsrightmargin=1in
+\def\startcontents#1{%
+ \pagealignmacro
+ \immediate\closeout \contentsfile
+ \ifnum \pageno>0
+ \pageno = -1 % Request roman numbered pages.
+ \fi
+ % Don't need to put `Contents' or `Short Contents' in the headline.
+ % It is abundantly clear what they are.
+ \unnumbchapmacro{#1}\def\thischapter{}%
+ \begingroup % Set up to handle contents files properly.
+ \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \catcode`\@=11
+ \catcode`\^=7 % to see ^^e4 as \"a etc. juha@piuha.ydi.vtt.fi
+ \raggedbottom % Worry more about breakpoints than the bottom.
+ \advance\hsize by -\contentsrightmargin % Don't use the full line length.
+}
+
+
+% Normal (long) toc.
+\outer\def\contents{%
+ \startcontents{\putwordTableofContents}%
+ \input \jobname.toc
+ \endgroup
+ \vfill \eject
+}
+
+% And just the chapters.
+\outer\def\summarycontents{%
+ \startcontents{\putwordShortContents}%
+ %
+ \let\chapentry = \shortchapentry
+ \let\unnumbchapentry = \shortunnumberedentry
+ % We want a true roman here for the page numbers.
+ \secfonts
+ \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl
+ \rm
+ \advance\baselineskip by 1pt % Open it up a little.
+ \def\secentry ##1##2##3##4{}
+ \def\unnumbsecentry ##1##2{}
+ \def\subsecentry ##1##2##3##4##5{}
+ \def\unnumbsubsecentry ##1##2{}
+ \def\subsubsecentry ##1##2##3##4##5##6{}
+ \def\unnumbsubsubsecentry ##1##2{}
+ \input \jobname.toc
+ \endgroup
+ \vfill \eject
+}
+\let\shortcontents = \summarycontents
+
+% These macros generate individual entries in the table of contents.
+% The first argument is the chapter or section name.
+% The last argument is the page number.
+% The arguments in between are the chapter number, section number, ...
+
+% Chapter-level things, for both the long and short contents.
+\def\chapentry#1#2#3{\dochapentry{#2\labelspace#1}{#3}}
+
+% See comments in \dochapentry re vbox and related settings
+\def\shortchapentry#1#2#3{%
+ \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno{#3}}%
+}
+
+% Typeset the label for a chapter or appendix for the short contents.
+% The arg is, e.g. `Appendix A' for an appendix, or `3' for a chapter.
+% We could simplify the code here by writing out an \appendixentry
+% command in the toc file for appendices, instead of using \chapentry
+% for both, but it doesn't seem worth it.
+\setbox0 = \hbox{\shortcontrm \putwordAppendix }
+\newdimen\shortappendixwidth \shortappendixwidth = \wd0
+
+\def\shortchaplabel#1{%
+ % We typeset #1 in a box of constant width, regardless of the text of
+ % #1, so the chapter titles will come out aligned.
+ \setbox0 = \hbox{#1}%
+ \dimen0 = \ifdim\wd0 > \shortappendixwidth \shortappendixwidth \else 0pt \fi
+ %
+ % This space should be plenty, since a single number is .5em, and the
+ % widest letter (M) is 1em, at least in the Computer Modern fonts.
+ % (This space doesn't include the extra space that gets added after
+ % the label; that gets put in in \shortchapentry above.)
+ \advance\dimen0 by 1.1em
+ \hbox to \dimen0{#1\hfil}%
+}
+
+\def\unnumbchapentry#1#2{\dochapentry{#1}{#2}}
+\def\shortunnumberedentry#1#2{\tocentry{#1}{\doshortpageno{#2}}}
+
+% Sections.
+\def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}}
+\def\unnumbsecentry#1#2{\dosecentry{#1}{#2}}
+
+% Subsections.
+\def\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}}
+\def\unnumbsubsecentry#1#2{\dosubsecentry{#1}{#2}}
+
+% And subsubsections.
+\def\subsubsecentry#1#2#3#4#5#6{%
+ \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}}
+\def\unnumbsubsubsecentry#1#2{\dosubsubsecentry{#1}{#2}}
+
+
+% This parameter controls the indentation of the various levels.
+\newdimen\tocindent \tocindent = 3pc
+
+% Now for the actual typesetting. In all these, #1 is the text and #2 is the
+% page number.
+%
+% If the toc has to be broken over pages, we would want to be at chapters
+% if at all possible; hence the \penalty.
+\def\dochapentry#1#2{%
+ \penalty-300 \vskip\baselineskip
+ \begingroup
+ \chapentryfonts
+ \tocentry{#1}{\dopageno{#2}}%
+ \endgroup
+ \nobreak\vskip .25\baselineskip
+}
+
+\def\dosecentry#1#2{\begingroup
+ \secentryfonts \leftskip=\tocindent
+ \tocentry{#1}{\dopageno{#2}}%
+\endgroup}
+
+\def\dosubsecentry#1#2{\begingroup
+ \subsecentryfonts \leftskip=2\tocindent
+ \tocentry{#1}{\dopageno{#2}}%
+\endgroup}
+
+\def\dosubsubsecentry#1#2{\begingroup
+ \subsubsecentryfonts \leftskip=3\tocindent
+ \tocentry{#1}{\dopageno{#2}}%
+\endgroup}
+
+% Final typesetting of a toc entry; we use the same \entry macro as for
+% the index entries, but we want to suppress hyphenation here. (We
+% can't do that in the \entry macro, since index entries might consist
+% of hyphenated-identifiers-that-do-not-fit-on-a-line-and-nothing-else.)
+%
+% \turnoffactive is for the sake of @" used for umlauts.
+\def\tocentry#1#2{\begingroup
+ \hyphenpenalty = 10000
+ \entry{\turnoffactive #1}{\turnoffactive #2}%
+\endgroup}
+
+% Space between chapter (or whatever) number and the title.
+\def\labelspace{\hskip1em \relax}
+
+\def\dopageno#1{{\rm #1}}
+\def\doshortpageno#1{{\rm #1}}
+
+\def\chapentryfonts{\secfonts \rm}
+\def\secentryfonts{\textfonts}
+\let\subsecentryfonts = \textfonts
+\let\subsubsecentryfonts = \textfonts
+
+
+\message{environments,}
+
+% Since these characters are used in examples, it should be an even number of
+% \tt widths. Each \tt character is 1en, so two makes it 1em.
+% Furthermore, these definitions must come after we define our fonts.
+\newbox\dblarrowbox \newbox\longdblarrowbox
+\newbox\pushcharbox \newbox\bullbox
+\newbox\equivbox \newbox\errorbox
+
+\let\ptexequiv = \equiv
+
+%{\tentt
+%\global\setbox\dblarrowbox = \hbox to 1em{\hfil$\Rightarrow$\hfil}
+%\global\setbox\longdblarrowbox = \hbox to 1em{\hfil$\mapsto$\hfil}
+%\global\setbox\pushcharbox = \hbox to 1em{\hfil$\dashv$\hfil}
+%\global\setbox\equivbox = \hbox to 1em{\hfil$\ptexequiv$\hfil}
+% Adapted from the manmac format (p.420 of TeXbook)
+%\global\setbox\bullbox = \hbox to 1em{\kern.15em\vrule height .75ex width .85ex
+% depth .1ex\hfil}
+%}
+
+\def\point{$\star$}
+
+\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}}
+\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}}
+\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}}
+
+\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}}
+
+% Adapted from the TeXbook's \boxit.
+{\tentt \global\dimen0 = 3em}% Width of the box.
+\dimen2 = .55pt % Thickness of rules
+% The text. (`r' is open on the right, `e' somewhat less so on the left.)
+\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt}
+
+\global\setbox\errorbox=\hbox to \dimen0{\hfil
+ \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right.
+ \advance\hsize by -2\dimen2 % Rules.
+ \vbox{
+ \hrule height\dimen2
+ \hbox{\vrule width\dimen2 \kern3pt % Space to left of text.
+ \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below.
+ \kern3pt\vrule width\dimen2}% Space to right.
+ \hrule height\dimen2}
+ \hfil}
+
+% The @error{} command.
+\def\error{\leavevmode\lower.7ex\copy\errorbox}
+
+% @tex ... @end tex escapes into raw Tex temporarily.
+% One exception: @ is still an escape character, so that @end tex works.
+% But \@ or @@ will get a plain tex @ character.
+
+\def\tex{\begingroup
+\catcode `\\=0 \catcode `\{=1 \catcode `\}=2
+\catcode `\$=3 \catcode `\&=4 \catcode `\#=6
+\catcode `\^=7 \catcode `\_=8 \catcode `\~=13 \let~=\tie
+\catcode `\%=14
+\catcode 43=12
+\catcode`\"=12
+\catcode`\==12
+\catcode`\|=12
+\catcode`\<=12
+\catcode`\>=12
+\escapechar=`\\
+%
+\let\~=\ptextilde
+\let\{=\ptexlbrace
+\let\}=\ptexrbrace
+\let\.=\ptexdot
+\let\*=\ptexstar
+\let\dots=\ptexdots
+\def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}
+\def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}
+\def\@{@}%
+\let\bullet=\ptexbullet
+\let\b=\ptexb \let\c=\ptexc \let\i=\ptexi \let\t=\ptext \let\l=\ptexl
+\let\L=\ptexL
+%
+\let\Etex=\endgroup}
+
+% Define @lisp ... @endlisp.
+% @lisp does a \begingroup so it can rebind things,
+% including the definition of @endlisp (which normally is erroneous).
+
+% Amount to narrow the margins by for @lisp.
+\newskip\lispnarrowing \lispnarrowing=0.4in
+
+% This is the definition that ^^M gets inside @lisp, @example, and other
+% such environments. \null is better than a space, since it doesn't
+% have any width.
+\def\lisppar{\null\endgraf}
+
+% Make each space character in the input produce a normal interword
+% space in the output. Don't allow a line break at this space, as this
+% is used only in environments like @example, where each line of input
+% should produce a line of output anyway.
+%
+{\obeyspaces %
+\gdef\sepspaces{\obeyspaces\let =\tie}}
+
+% Define \obeyedspace to be our active space, whatever it is. This is
+% for use in \parsearg.
+{\sepspaces%
+\global\let\obeyedspace= }
+
+% This space is always present above and below environments.
+\newskip\envskipamount \envskipamount = 0pt
+
+% Make spacing and below environment symmetrical. We use \parskip here
+% to help in doing that, since in @example-like environments \parskip
+% is reset to zero; thus the \afterenvbreak inserts no space -- but the
+% start of the next paragraph will insert \parskip
+%
+\def\aboveenvbreak{{\advance\envskipamount by \parskip
+\endgraf \ifdim\lastskip<\envskipamount
+\removelastskip \penalty-50 \vskip\envskipamount \fi}}
+
+\let\afterenvbreak = \aboveenvbreak
+
+% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins.
+\let\nonarrowing=\relax
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \cartouche: draw rectangle w/rounded corners around argument
+\font\circle=lcircle10
+\newdimen\circthick
+\newdimen\cartouter\newdimen\cartinner
+\newskip\normbskip\newskip\normpskip\newskip\normlskip
+\circthick=\fontdimen8\circle
+%
+\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth
+\def\ctr{{\hskip 6pt\circle\char'010}}
+\def\cbl{{\circle\char'012\hskip -6pt}}
+\def\cbr{{\hskip 6pt\circle\char'011}}
+\def\carttop{\hbox to \cartouter{\hskip\lskip
+ \ctl\leaders\hrule height\circthick\hfil\ctr
+ \hskip\rskip}}
+\def\cartbot{\hbox to \cartouter{\hskip\lskip
+ \cbl\leaders\hrule height\circthick\hfil\cbr
+ \hskip\rskip}}
+%
+\newskip\lskip\newskip\rskip
+
+\long\def\cartouche{%
+\begingroup
+ \lskip=\leftskip \rskip=\rightskip
+ \leftskip=0pt\rightskip=0pt %we want these *outside*.
+ \cartinner=\hsize \advance\cartinner by-\lskip
+ \advance\cartinner by-\rskip
+ \cartouter=\hsize
+ \advance\cartouter by 18pt % allow for 3pt kerns on either
+% side, and for 6pt waste from
+% each corner char
+ \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip
+ % Flag to tell @lisp, etc., not to narrow margin.
+ \let\nonarrowing=\comment
+ \vbox\bgroup
+ \baselineskip=0pt\parskip=0pt\lineskip=0pt
+ \carttop
+ \hbox\bgroup
+ \hskip\lskip
+ \vrule\kern3pt
+ \vbox\bgroup
+ \hsize=\cartinner
+ \kern3pt
+ \begingroup
+ \baselineskip=\normbskip
+ \lineskip=\normlskip
+ \parskip=\normpskip
+ \vskip -\parskip
+\def\Ecartouche{%
+ \endgroup
+ \kern3pt
+ \egroup
+ \kern3pt\vrule
+ \hskip\rskip
+ \egroup
+ \cartbot
+ \egroup
+\endgroup
+}}
+
+
+% This macro is called at the beginning of all the @example variants,
+% inside a group.
+\def\nonfillstart{%
+ \aboveenvbreak
+ \inENV % This group ends at the end of the body
+ \hfuzz = 12pt % Don't be fussy
+ \sepspaces % Make spaces be word-separators rather than space tokens.
+ \singlespace
+ \let\par = \lisppar % don't ignore blank lines
+ \obeylines % each line of input is a line of output
+ \parskip = 0pt
+ \parindent = 0pt
+ \emergencystretch = 0pt % don't try to avoid overfull boxes
+ % @cartouche defines \nonarrowing to inhibit narrowing
+ % at next level down.
+ \ifx\nonarrowing\relax
+ \advance \leftskip by \lispnarrowing
+ \exdentamount=\lispnarrowing
+ \let\exdent=\nofillexdent
+ \let\nonarrowing=\relax
+ \fi
+}
+
+% To ending an @example-like environment, we first end the paragraph
+% (via \afterenvbreak's vertical glue), and then the group. That way we
+% keep the zero \parskip that the environments set -- \parskip glue
+% will be inserted at the beginning of the next paragraph in the
+% document, after the environment.
+%
+\def\nonfillfinish{\afterenvbreak\endgroup}%
+
+% This macro is
+\def\lisp{\begingroup
+ \nonfillstart
+ \let\Elisp = \nonfillfinish
+ \tt
+ \rawbackslash % have \ input char produce \ char from current font
+ \gobble
+}
+
+% Define the \E... control sequence only if we are inside the
+% environment, so the error checking in \end will work.
+%
+% We must call \lisp last in the definition, since it reads the
+% return following the @example (or whatever) command.
+%
+\def\example{\begingroup \def\Eexample{\nonfillfinish\endgroup}\lisp}
+\def\smallexample{\begingroup \def\Esmallexample{\nonfillfinish\endgroup}\lisp}
+\def\smalllisp{\begingroup \def\Esmalllisp{\nonfillfinish\endgroup}\lisp}
+
+% @smallexample and @smalllisp. This is not used unless the @smallbook
+% command is given. Originally contributed by Pavel@xerox.
+%
+\def\smalllispx{\begingroup
+ \nonfillstart
+ \let\Esmalllisp = \nonfillfinish
+ \let\Esmallexample = \nonfillfinish
+ %
+ % Smaller interline space and fonts for small examples.
+ \setleading{10pt}%
+ \indexfonts \tt
+ \rawbackslash % make \ output the \ character from the current font (tt)
+ \gobble
+}
+
+% This is @display; same as @lisp except use roman font.
+%
+\def\display{\begingroup
+ \nonfillstart
+ \let\Edisplay = \nonfillfinish
+ \gobble
+}
+
+% This is @format; same as @display except don't narrow margins.
+%
+\def\format{\begingroup
+ \let\nonarrowing = t
+ \nonfillstart
+ \let\Eformat = \nonfillfinish
+ \gobble
+}
+
+% @flushleft (same as @format) and @flushright.
+%
+\def\flushleft{\begingroup
+ \let\nonarrowing = t
+ \nonfillstart
+ \let\Eflushleft = \nonfillfinish
+ \gobble
+}
+\def\flushright{\begingroup
+ \let\nonarrowing = t
+ \nonfillstart
+ \let\Eflushright = \nonfillfinish
+ \advance\leftskip by 0pt plus 1fill
+ \gobble}
+
+% @quotation does normal linebreaking (hence we can't use \nonfillstart)
+% and narrows the margins.
+%
+\def\quotation{%
+ \begingroup\inENV %This group ends at the end of the @quotation body
+ {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip
+ \singlespace
+ \parindent=0pt
+ % We have retained a nonzero parskip for the environment, since we're
+ % doing normal filling. So to avoid extra space below the environment...
+ \def\Equotation{\parskip = 0pt \nonfillfinish}%
+ %
+ % @cartouche defines \nonarrowing to inhibit narrowing at next level down.
+ \ifx\nonarrowing\relax
+ \advance\leftskip by \lispnarrowing
+ \advance\rightskip by \lispnarrowing
+ \exdentamount = \lispnarrowing
+ \let\nonarrowing = \relax
+ \fi
+}
+
+\message{defuns,}
+% Define formatter for defuns
+% First, allow user to change definition object font (\df) internally
+\def\setdeffont #1 {\csname DEF#1\endcsname}
+
+\newskip\defbodyindent \defbodyindent=.4in
+\newskip\defargsindent \defargsindent=50pt
+\newskip\deftypemargin \deftypemargin=12pt
+\newskip\deflastargmargin \deflastargmargin=18pt
+
+\newcount\parencount
+% define \functionparens, which makes ( and ) and & do special things.
+% \functionparens affects the group it is contained in.
+\def\activeparens{%
+\catcode`\(=\active \catcode`\)=\active \catcode`\&=\active
+\catcode`\[=\active \catcode`\]=\active}
+
+% Make control sequences which act like normal parenthesis chars.
+\let\lparen = ( \let\rparen = )
+
+{\activeparens % Now, smart parens don't turn on until &foo (see \amprm)
+
+% Be sure that we always have a definition for `(', etc. For example,
+% if the fn name has parens in it, \boldbrax will not be in effect yet,
+% so TeX would otherwise complain about undefined control sequence.
+\global\let(=\lparen \global\let)=\rparen
+\global\let[=\lbrack \global\let]=\rbrack
+
+\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 }
+\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb}
+% This is used to turn on special parens
+% but make & act ordinary (given that it's active).
+\gdef\boldbraxnoamp{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb\let&=\ampnr}
+
+% Definitions of (, ) and & used in args for functions.
+% This is the definition of ( outside of all parentheses.
+\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested %
+\global\advance\parencount by 1 }
+%
+% This is the definition of ( when already inside a level of parens.
+\gdef\opnested{\char`\(\global\advance\parencount by 1 }
+%
+\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0.
+% also in that case restore the outer-level definition of (.
+\ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi
+\global\advance \parencount by -1 }
+% If we encounter &foo, then turn on ()-hacking afterwards
+\gdef\amprm#1 {{\rm\&#1}\let(=\oprm \let)=\clrm\ }
+%
+\gdef\normalparens{\boldbrax\let&=\ampnr}
+} % End of definition inside \activeparens
+%% These parens (in \boldbrax) actually are a little bolder than the
+%% contained text. This is especially needed for [ and ]
+\def\opnr{{\sf\char`\(}} \def\clnr{{\sf\char`\)}} \def\ampnr{\&}
+\def\lbrb{{\bf\char`\[}} \def\rbrb{{\bf\char`\]}}
+
+% First, defname, which formats the header line itself.
+% #1 should be the function name.
+% #2 should be the type of definition, such as "Function".
+
+\def\defname #1#2{%
+% Get the values of \leftskip and \rightskip as they were
+% outside the @def...
+\dimen2=\leftskip
+\advance\dimen2 by -\defbodyindent
+\dimen3=\rightskip
+\advance\dimen3 by -\defbodyindent
+\noindent %
+\setbox0=\hbox{\hskip \deflastargmargin{\rm #2}\hskip \deftypemargin}%
+\dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line
+\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuations
+\parshape 2 0in \dimen0 \defargsindent \dimen1 %
+% Now output arg 2 ("Function" or some such)
+% ending at \deftypemargin from the right margin,
+% but stuck inside a box of width 0 so it does not interfere with linebreaking
+{% Adjust \hsize to exclude the ambient margins,
+% so that \rightline will obey them.
+\advance \hsize by -\dimen2 \advance \hsize by -\dimen3
+\rlap{\rightline{{\rm #2}\hskip \deftypemargin}}}%
+% Make all lines underfull and no complaints:
+\tolerance=10000 \hbadness=10000
+\advance\leftskip by -\defbodyindent
+\exdentamount=\defbodyindent
+{\df #1}\enskip % Generate function name
+}
+
+% Actually process the body of a definition
+% #1 should be the terminating control sequence, such as \Edefun.
+% #2 should be the "another name" control sequence, such as \defunx.
+% #3 should be the control sequence that actually processes the header,
+% such as \defunheader.
+
+\def\defparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2{\begingroup\obeylines\activeparens\spacesplit#3}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup %
+\catcode 61=\active % 61 is `='
+\obeylines\activeparens\spacesplit#3}
+
+\def\defmethparsebody #1#2#3#4 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\activeparens\spacesplit{#3{#4}}}
+
+\def\defopparsebody #1#2#3#4#5 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 ##2 {\def#4{##1}%
+\begingroup\obeylines\activeparens\spacesplit{#3{##2}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\activeparens\spacesplit{#3{#5}}}
+
+% These parsing functions are similar to the preceding ones
+% except that they do not make parens into active characters.
+% These are used for "variables" since they have no arguments.
+
+\def\defvarparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2{\begingroup\obeylines\spacesplit#3}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup %
+\catcode 61=\active %
+\obeylines\spacesplit#3}
+
+% This is used for \def{tp,vr}parsebody. It could probably be used for
+% some of the others, too, with some judicious conditionals.
+%
+\def\parsebodycommon#1#2#3{%
+ \begingroup\inENV %
+ \medbreak %
+ % Define the end token that this defining construct specifies
+ % so that it will exit this group.
+ \def#1{\endgraf\endgroup\medbreak}%
+ \def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}%
+ \parindent=0in
+ \advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+ \exdentamount=\defbodyindent
+ \begingroup\obeylines
+}
+
+\def\defvrparsebody#1#2#3#4 {%
+ \parsebodycommon{#1}{#2}{#3}%
+ \spacesplit{#3{#4}}%
+}
+
+% This loses on `@deftp {Data Type} {struct termios}' -- it thinks the
+% type is just `struct', because we lose the braces in `{struct
+% termios}' when \spacesplit reads its undelimited argument. Sigh.
+% \let\deftpparsebody=\defvrparsebody
+%
+% So, to get around this, we put \empty in with the type name. That
+% way, TeX won't find exactly `{...}' as an undelimited argument, and
+% won't strip off the braces.
+%
+\def\deftpparsebody #1#2#3#4 {%
+ \parsebodycommon{#1}{#2}{#3}%
+ \spacesplit{\parsetpheaderline{#3{#4}}}\empty
+}
+
+% Fine, but then we have to eventually remove the \empty *and* the
+% braces (if any). That's what this does, putting the result in \tptemp.
+%
+\def\removeemptybraces\empty#1\relax{\def\tptemp{#1}}%
+
+% After \spacesplit has done its work, this is called -- #1 is the final
+% thing to call, #2 the type name (which starts with \empty), and #3
+% (which might be empty) the arguments.
+%
+\def\parsetpheaderline#1#2#3{%
+ \removeemptybraces#2\relax
+ #1{\tptemp}{#3}%
+}%
+
+\def\defopvarparsebody #1#2#3#4#5 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 ##2 {\def#4{##1}%
+\begingroup\obeylines\spacesplit{#3{##2}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\spacesplit{#3{#5}}}
+
+% Split up #2 at the first space token.
+% call #1 with two arguments:
+% the first is all of #2 before the space token,
+% the second is all of #2 after that space token.
+% If #2 contains no space token, all of it is passed as the first arg
+% and the second is passed as empty.
+
+{\obeylines
+\gdef\spacesplit#1#2^^M{\endgroup\spacesplitfoo{#1}#2 \relax\spacesplitfoo}%
+\long\gdef\spacesplitfoo#1#2 #3#4\spacesplitfoo{%
+\ifx\relax #3%
+#1{#2}{}\else #1{#2}{#3#4}\fi}}
+
+% So much for the things common to all kinds of definitions.
+
+% Define @defun.
+
+% First, define the processing that is wanted for arguments of \defun
+% Use this to expand the args and terminate the paragraph they make up
+
+\def\defunargs #1{\functionparens \sl
+% Expand, preventing hyphenation at `-' chars.
+% Note that groups don't affect changes in \hyphenchar.
+\hyphenchar\tensl=0
+#1%
+\hyphenchar\tensl=45
+\ifnum\parencount=0 \else \errmessage{unbalanced parens in @def arguments}\fi%
+\interlinepenalty=10000
+\advance\rightskip by 0pt plus 1fil
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000%
+}
+
+\def\deftypefunargs #1{%
+% Expand, preventing hyphenation at `-' chars.
+% Note that groups don't affect changes in \hyphenchar.
+% Use \boldbraxnoamp, not \functionparens, so that & is not special.
+\boldbraxnoamp
+\tclose{#1}% avoid \code because of side effects on active chars
+\interlinepenalty=10000
+\advance\rightskip by 0pt plus 1fil
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000%
+}
+
+% Do complete processing of one @defun or @defunx line already parsed.
+
+% @deffn Command forward-char nchars
+
+\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader}
+
+\def\deffnheader #1#2#3{\doind {fn}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defun == @deffn Function
+
+\def\defun{\defparsebody\Edefun\defunx\defunheader}
+
+\def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Function}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @deftypefun int foobar (int @var{foo}, float @var{bar})
+
+\def\deftypefun{\defparsebody\Edeftypefun\deftypefunx\deftypefunheader}
+
+% #1 is the data type. #2 is the name and args.
+\def\deftypefunheader #1#2{\deftypefunheaderx{#1}#2 \relax}
+% #1 is the data type, #2 the name, #3 the args.
+\def\deftypefunheaderx #1#2 #3\relax{%
+\doind {fn}{\code{#2}}% Make entry in function index
+\begingroup\defname {\defheaderxcond#1\relax$$$#2}{Function}%
+\deftypefunargs {#3}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar})
+
+\def\deftypefn{\defmethparsebody\Edeftypefn\deftypefnx\deftypefnheader}
+
+% \defheaderxcond#1\relax$$$
+% puts #1 in @code, followed by a space, but does nothing if #1 is null.
+\def\defheaderxcond#1#2$$${\ifx#1\relax\else\code{#1#2} \fi}
+
+% #1 is the classification. #2 is the data type. #3 is the name and args.
+\def\deftypefnheader #1#2#3{\deftypefnheaderx{#1}{#2}#3 \relax}
+% #1 is the classification, #2 the data type, #3 the name, #4 the args.
+\def\deftypefnheaderx #1#2#3 #4\relax{%
+\doind {fn}{\code{#3}}% Make entry in function index
+\begingroup
+\normalparens % notably, turn off `&' magic, which prevents
+% at least some C++ text from working
+\defname {\defheaderxcond#2\relax$$$#3}{#1}%
+\deftypefunargs {#4}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defmac == @deffn Macro
+
+\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader}
+
+\def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Macro}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defspec == @deffn Special Form
+
+\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader}
+
+\def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Special Form}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% This definition is run if you use @defunx
+% anywhere other than immediately after a @defun or @defunx.
+
+\def\deffnx #1 {\errmessage{@deffnx in invalid context}}
+\def\defunx #1 {\errmessage{@defunx in invalid context}}
+\def\defmacx #1 {\errmessage{@defmacx in invalid context}}
+\def\defspecx #1 {\errmessage{@defspecx in invalid context}}
+\def\deftypefnx #1 {\errmessage{@deftypefnx in invalid context}}
+\def\deftypeunx #1 {\errmessage{@deftypeunx in invalid context}}
+
+% @defmethod, and so on
+
+% @defop {Funny Method} foo-class frobnicate argument
+
+\def\defop #1 {\def\defoptype{#1}%
+\defopparsebody\Edefop\defopx\defopheader\defoptype}
+
+\def\defopheader #1#2#3{%
+\dosubind {fn}{\code{#2}}{on #1}% Make entry in function index
+\begingroup\defname {#2}{\defoptype{} on #1}%
+\defunargs {#3}\endgroup %
+}
+
+% @defmethod == @defop Method
+
+\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader}
+
+\def\defmethodheader #1#2#3{%
+\dosubind {fn}{\code{#2}}{on #1}% entry in function index
+\begingroup\defname {#2}{Method on #1}%
+\defunargs {#3}\endgroup %
+}
+
+% @defcv {Class Option} foo-class foo-flag
+
+\def\defcv #1 {\def\defcvtype{#1}%
+\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype}
+
+\def\defcvarheader #1#2#3{%
+\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
+\begingroup\defname {#2}{\defcvtype{} of #1}%
+\defvarargs {#3}\endgroup %
+}
+
+% @defivar == @defcv {Instance Variable}
+
+\def\defivar{\defvrparsebody\Edefivar\defivarx\defivarheader}
+
+\def\defivarheader #1#2#3{%
+\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
+\begingroup\defname {#2}{Instance Variable of #1}%
+\defvarargs {#3}\endgroup %
+}
+
+% These definitions are run if you use @defmethodx, etc.,
+% anywhere other than immediately after a @defmethod, etc.
+
+\def\defopx #1 {\errmessage{@defopx in invalid context}}
+\def\defmethodx #1 {\errmessage{@defmethodx in invalid context}}
+\def\defcvx #1 {\errmessage{@defcvx in invalid context}}
+\def\defivarx #1 {\errmessage{@defivarx in invalid context}}
+
+% Now @defvar
+
+% First, define the processing that is wanted for arguments of @defvar.
+% This is actually simple: just print them in roman.
+% This must expand the args and terminate the paragraph they make up
+\def\defvarargs #1{\normalparens #1%
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000}
+
+% @defvr Counter foo-count
+
+\def\defvr{\defvrparsebody\Edefvr\defvrx\defvrheader}
+
+\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup}
+
+% @defvar == @defvr Variable
+
+\def\defvar{\defvarparsebody\Edefvar\defvarx\defvarheader}
+
+\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{Variable}%
+\defvarargs {#2}\endgroup %
+}
+
+% @defopt == @defvr {User Option}
+
+\def\defopt{\defvarparsebody\Edefopt\defoptx\defoptheader}
+
+\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{User Option}%
+\defvarargs {#2}\endgroup %
+}
+
+% @deftypevar int foobar
+
+\def\deftypevar{\defvarparsebody\Edeftypevar\deftypevarx\deftypevarheader}
+
+% #1 is the data type. #2 is the name.
+\def\deftypevarheader #1#2{%
+\doind {vr}{\code{#2}}% Make entry in variables index
+\begingroup\defname {\defheaderxcond#1\relax$$$#2}{Variable}%
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000
+\endgroup}
+
+% @deftypevr {Global Flag} int enable
+
+\def\deftypevr{\defvrparsebody\Edeftypevr\deftypevrx\deftypevrheader}
+
+\def\deftypevrheader #1#2#3{\doind {vr}{\code{#3}}%
+\begingroup\defname {\defheaderxcond#2\relax$$$#3}{#1}
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000
+\endgroup}
+
+% This definition is run if you use @defvarx
+% anywhere other than immediately after a @defvar or @defvarx.
+
+\def\defvrx #1 {\errmessage{@defvrx in invalid context}}
+\def\defvarx #1 {\errmessage{@defvarx in invalid context}}
+\def\defoptx #1 {\errmessage{@defoptx in invalid context}}
+\def\deftypevarx #1 {\errmessage{@deftypevarx in invalid context}}
+\def\deftypevrx #1 {\errmessage{@deftypevrx in invalid context}}
+
+% Now define @deftp
+% Args are printed in bold, a slight difference from @defvar.
+
+\def\deftpargs #1{\bf \defvarargs{#1}}
+
+% @deftp Class window height width ...
+
+\def\deftp{\deftpparsebody\Edeftp\deftpx\deftpheader}
+
+\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}%
+\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup}
+
+% This definition is run if you use @deftpx, etc
+% anywhere other than immediately after a @deftp, etc.
+
+\def\deftpx #1 {\errmessage{@deftpx in invalid context}}
+
+\message{cross reference,}
+% Define cross-reference macros
+\newwrite \auxfile
+
+\newif\ifhavexrefs % True if xref values are known.
+\newif\ifwarnedxrefs % True if we warned once that they aren't known.
+
+% \setref{foo} defines a cross-reference point named foo.
+
+\def\setref#1{%
+\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Ysectionnumberandtype}}
+
+\def\unnumbsetref#1{%
+\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Ynothing}}
+
+\def\appendixsetref#1{%
+\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Yappendixletterandtype}}
+
+% \xref, \pxref, and \ref generate cross-references to specified points.
+% For \xrefX, #1 is the node name, #2 the name of the Info
+% cross-reference, #3 the printed node name, #4 the name of the Info
+% file, #5 the name of the printed manual. All but the node name can be
+% omitted.
+%
+\def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]}
+\def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]}
+\def\ref#1{\xrefX[#1,,,,,,,]}
+\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup
+ \def\printedmanual{\ignorespaces #5}%
+ \def\printednodename{\ignorespaces #3}%
+ \setbox1=\hbox{\printedmanual}%
+ \setbox0=\hbox{\printednodename}%
+ \ifdim \wd0 = 0pt
+ % No printed node name was explicitly given.
+ \expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax
+ % Use the node name inside the square brackets.
+ \def\printednodename{\ignorespaces #1}%
+ \else
+ % Use the actual chapter/section title appear inside
+ % the square brackets. Use the real section title if we have it.
+ \ifdim \wd1>0pt%
+ % It is in another manual, so we don't have it.
+ \def\printednodename{\ignorespaces #1}%
+ \else
+ \ifhavexrefs
+ % We know the real title if we have the xref values.
+ \def\printednodename{\refx{#1-title}{}}%
+ \else
+ % Otherwise just copy the Info node name.
+ \def\printednodename{\ignorespaces #1}%
+ \fi%
+ \fi
+ \fi
+ \fi
+ %
+ % If we use \unhbox0 and \unhbox1 to print the node names, TeX does not
+ % insert empty discretionaries after hyphens, which means that it will
+ % not find a line break at a hyphen in a node names. Since some manuals
+ % are best written with fairly long node names, containing hyphens, this
+ % is a loss. Therefore, we give the text of the node name again, so it
+ % is as if TeX is seeing it for the first time.
+ \ifdim \wd1 > 0pt
+ \putwordsection{} ``\printednodename'' in \cite{\printedmanual}%
+ \else
+ % _ (for example) has to be the character _ for the purposes of the
+ % control sequence corresponding to the node, but it has to expand
+ % into the usual \leavevmode...\vrule stuff for purposes of
+ % printing. So we \turnoffactive for the \refx-snt, back on for the
+ % printing, back off for the \refx-pg.
+ {\turnoffactive \refx{#1-snt}{}}%
+ \space [\printednodename],\space
+ \turnoffactive \putwordpage\tie\refx{#1-pg}{}%
+ \fi
+\endgroup}
+
+% \dosetq is the interface for calls from other macros
+
+% Use \turnoffactive so that punctuation chars such as underscore
+% work in node names.
+\def\dosetq #1#2{{\let\folio=0 \turnoffactive \auxhat%
+\edef\next{\write\auxfile{\internalsetq {#1}{#2}}}%
+\next}}
+
+% \internalsetq {foo}{page} expands into
+% CHARACTERS 'xrdef {foo}{...expansion of \Ypage...}
+% When the aux file is read, ' is the escape character
+
+\def\internalsetq #1#2{'xrdef {#1}{\csname #2\endcsname}}
+
+% Things to be expanded by \internalsetq
+
+\def\Ypagenumber{\folio}
+
+\def\Ytitle{\thissection}
+
+\def\Ynothing{}
+
+\def\Ysectionnumberandtype{%
+\ifnum\secno=0 \putwordChapter\xreftie\the\chapno %
+\else \ifnum \subsecno=0 \putwordSection\xreftie\the\chapno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+\putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno %
+\else %
+\putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\def\Yappendixletterandtype{%
+\ifnum\secno=0 \putwordAppendix\xreftie'char\the\appendixno{}%
+\else \ifnum \subsecno=0 \putwordSection\xreftie'char\the\appendixno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+\putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno %
+\else %
+\putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\gdef\xreftie{'tie}
+
+% Use TeX 3.0's \inputlineno to get the line number, for better error
+% messages, but if we're using an old version of TeX, don't do anything.
+%
+\ifx\inputlineno\thisisundefined
+ \let\linenumber = \empty % Non-3.0.
+\else
+ \def\linenumber{\the\inputlineno:\space}
+\fi
+
+% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME.
+% If its value is nonempty, SUFFIX is output afterward.
+
+\def\refx#1#2{%
+ \expandafter\ifx\csname X#1\endcsname\relax
+ % If not defined, say something at least.
+ $\langle$un\-de\-fined$\rangle$%
+ \ifhavexrefs
+ \message{\linenumber Undefined cross reference `#1'.}%
+ \else
+ \ifwarnedxrefs\else
+ \global\warnedxrefstrue
+ \message{Cross reference values unknown; you must run TeX again.}%
+ \fi
+ \fi
+ \else
+ % It's defined, so just use it.
+ \csname X#1\endcsname
+ \fi
+ #2% Output the suffix in any case.
+}
+
+% Read the last existing aux file, if any. No error if none exists.
+
+% This is the macro invoked by entries in the aux file.
+\def\xrdef #1#2{
+{\catcode`\'=\other\expandafter \gdef \csname X#1\endcsname {#2}}}
+
+\def\readauxfile{%
+\begingroup
+\catcode `\^^@=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\^^C=\other
+\catcode `\^^D=\other
+\catcode `\^^E=\other
+\catcode `\^^F=\other
+\catcode `\^^G=\other
+\catcode `\^^H=\other
+\catcode `\ =\other
+\catcode `\^^L=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode 26=\other
+\catcode `\^^[=\other
+\catcode `\^^\=\other
+\catcode `\^^]=\other
+\catcode `\^^^=\other
+\catcode `\^^_=\other
+\catcode `\@=\other
+\catcode `\^=\other
+\catcode `\~=\other
+\catcode `\[=\other
+\catcode `\]=\other
+\catcode`\"=\other
+\catcode`\_=\other
+\catcode`\|=\other
+\catcode`\<=\other
+\catcode`\>=\other
+\catcode `\$=\other
+\catcode `\#=\other
+\catcode `\&=\other
+% `\+ does not work, so use 43.
+\catcode 43=\other
+% Make the characters 128-255 be printing characters
+{%
+ \count 1=128
+ \def\loop{%
+ \catcode\count 1=\other
+ \advance\count 1 by 1
+ \ifnum \count 1<256 \loop \fi
+ }%
+}%
+% the aux file uses ' as the escape.
+% Turn off \ as an escape so we do not lose on
+% entries which were dumped with control sequences in their names.
+% For example, 'xrdef {$\leq $-fun}{page ...} made by @defun ^^
+% Reference to such entries still does not work the way one would wish,
+% but at least they do not bomb out when the aux file is read in.
+\catcode `\{=1 \catcode `\}=2
+\catcode `\%=\other
+\catcode `\'=0
+\catcode`\^=7 % to make ^^e4 etc usable in xref tags
+\catcode `\\=\other
+\openin 1 \jobname.aux
+\ifeof 1 \else \closein 1 \input \jobname.aux \global\havexrefstrue
+\global\warnedobstrue
+\fi
+% Open the new aux file. Tex will close it automatically at exit.
+\openout \auxfile=\jobname.aux
+\endgroup}
+
+
+% Footnotes.
+
+\newcount \footnoteno
+
+% The trailing space in the following definition for supereject is
+% vital for proper filling; pages come out unaligned when you do a
+% pagealignmacro call if that space before the closing brace is
+% removed.
+\def\supereject{\par\penalty -20000\footnoteno =0 }
+
+% @footnotestyle is meaningful for info output only..
+\let\footnotestyle=\comment
+
+\let\ptexfootnote=\footnote
+
+{\catcode `\@=11
+%
+% Auto-number footnotes. Otherwise like plain.
+\gdef\footnote{%
+ \global\advance\footnoteno by \@ne
+ \edef\thisfootno{$^{\the\footnoteno}$}%
+ %
+ % In case the footnote comes at the end of a sentence, preserve the
+ % extra spacing after we do the footnote number.
+ \let\@sf\empty
+ \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\/\fi
+ %
+ % Remove inadvertent blank space before typesetting the footnote number.
+ \unskip
+ \thisfootno\@sf
+ \footnotezzz
+}%
+
+% Don't bother with the trickery in plain.tex to not require the
+% footnote text as a parameter. Our footnotes don't need to be so general.
+%
+\long\gdef\footnotezzz#1{\insert\footins{%
+ % We want to typeset this text as a normal paragraph, even if the
+ % footnote reference occurs in (for example) a display environment.
+ % So reset some parameters.
+ \interlinepenalty\interfootnotelinepenalty
+ \splittopskip\ht\strutbox % top baseline for broken footnotes
+ \splitmaxdepth\dp\strutbox
+ \floatingpenalty\@MM
+ \leftskip\z@skip
+ \rightskip\z@skip
+ \spaceskip\z@skip
+ \xspaceskip\z@skip
+ \parindent\defaultparindent
+ %
+ % Hang the footnote text off the number.
+ \hang
+ \textindent{\thisfootno}%
+ %
+ % Don't crash into the line above the footnote text. Since this
+ % expands into a box, it must come within the paragraph, lest it
+ % provide a place where TeX can split the footnote.
+ \footstrut
+ #1\strut}%
+}
+
+}%end \catcode `\@=11
+
+% Set the baselineskip to #1, and the lineskip and strut size
+% correspondingly. There is no deep meaning behind these magic numbers
+% used as factors; they just match (closely enough) what Knuth defined.
+%
+\def\lineskipfactor{.08333}
+\def\strutheightpercent{.70833}
+\def\strutdepthpercent {.29167}
+%
+\def\setleading#1{%
+ \normalbaselineskip = #1\relax
+ \normallineskip = \lineskipfactor\normalbaselineskip
+ \normalbaselines
+ \setbox\strutbox =\hbox{%
+ \vrule width0pt height\strutheightpercent\baselineskip
+ depth \strutdepthpercent \baselineskip
+ }%
+}
+
+% @| inserts a changebar to the left of the current line. It should
+% surround any changed text. This approach does *not* work if the
+% change spans more than two lines of output. To handle that, we would
+% have adopt a much more difficult approach (putting marks into the main
+% vertical list for the beginning and end of each change).
+%
+\def\|{%
+ % \vadjust can only be used in horizontal mode.
+ \leavevmode
+ %
+ % Append this vertical mode material after the current line in the output.
+ \vadjust{%
+ % We want to insert a rule with the height and depth of the current
+ % leading; that is exactly what \strutbox is supposed to record.
+ \vskip-\baselineskip
+ %
+ % \vadjust-items are inserted at the left edge of the type. So
+ % the \llap here moves out into the left-hand margin.
+ \llap{%
+ %
+ % For a thicker or thinner bar, change the `1pt'.
+ \vrule height\baselineskip width1pt
+ %
+ % This is the space between the bar and the text.
+ \hskip 12pt
+ }%
+ }%
+}
+
+% For a final copy, take out the rectangles
+% that mark overfull boxes (in case you have decided
+% that the text looks ok even though it passes the margin).
+%
+\def\finalout{\overfullrule=0pt}
+
+
+% End of control word definitions.
+
+\message{and turning on texinfo input format.}
+
+\def\openindices{%
+ \newindex{cp}%
+ \newcodeindex{fn}%
+ \newcodeindex{vr}%
+ \newcodeindex{tp}%
+ \newcodeindex{ky}%
+ \newcodeindex{pg}%
+}
+
+% Set some numeric style parameters, for 8.5 x 11 format.
+
+%\hsize = 6.5in
+\newdimen\defaultparindent \defaultparindent = 15pt
+\parindent = \defaultparindent
+\parskip 18pt plus 1pt
+\setleading{15pt}
+\advance\topskip by 1.2cm
+
+% Prevent underfull vbox error messages.
+\vbadness=10000
+
+% Following George Bush, just get rid of widows and orphans.
+\widowpenalty=10000
+\clubpenalty=10000
+
+% Use TeX 3.0's \emergencystretch to help line breaking, but if we're
+% using an old version of TeX, don't do anything. We want the amount of
+% stretch added to depend on the line length, hence the dependence on
+% \hsize. This makes it come to about 9pt for the 8.5x11 format.
+%
+\ifx\emergencystretch\thisisundefined
+ % Allow us to assign to \emergencystretch anyway.
+ \def\emergencystretch{\dimen0}%
+\else
+ \emergencystretch = \hsize
+ \divide\emergencystretch by 45
+\fi
+
+% Use @smallbook to reset parameters for 7x9.5 format (or else 7x9.25)
+\def\smallbook{
+
+% These values for secheadingskip and subsecheadingskip are
+% experiments. RJC 7 Aug 1992
+\global\secheadingskip = 17pt plus 6pt minus 3pt
+\global\subsecheadingskip = 14pt plus 6pt minus 3pt
+
+\global\lispnarrowing = 0.3in
+\setleading{12pt}
+\advance\topskip by -1cm
+\global\parskip 3pt plus 1pt
+\global\hsize = 5in
+\global\vsize=7.5in
+\global\tolerance=700
+\global\hfuzz=1pt
+\global\contentsrightmargin=0pt
+\global\deftypemargin=0pt
+\global\defbodyindent=.5cm
+
+\global\pagewidth=\hsize
+\global\pageheight=\vsize
+
+\global\let\smalllisp=\smalllispx
+\global\let\smallexample=\smalllispx
+\global\def\Esmallexample{\Esmalllisp}
+}
+
+% Use @afourpaper to print on European A4 paper.
+\def\afourpaper{
+\global\tolerance=700
+\global\hfuzz=1pt
+\setleading{12pt}
+\global\parskip 15pt plus 1pt
+
+\global\vsize= 53\baselineskip
+\advance\vsize by \topskip
+%\global\hsize= 5.85in % A4 wide 10pt
+\global\hsize= 6.5in
+\global\outerhsize=\hsize
+\global\advance\outerhsize by 0.5in
+\global\outervsize=\vsize
+\global\advance\outervsize by 0.6in
+
+\global\pagewidth=\hsize
+\global\pageheight=\vsize
+}
+
+% Allow control of the text dimensions. Parameters in order: textheight;
+% textwidth; voffset; hoffset; binding offset; topskip.
+% All require a dimension;
+% header is additional; added length extends the bottom of the page.
+
+\def\changepagesizes#1#2#3#4#5#6{
+ \global\vsize= #1
+ \global\topskip= #6
+ \advance\vsize by \topskip
+ \global\voffset= #3
+ \global\hsize= #2
+ \global\outerhsize=\hsize
+ \global\advance\outerhsize by 0.5in
+ \global\outervsize=\vsize
+ \global\advance\outervsize by 0.6in
+ \global\pagewidth=\hsize
+ \global\pageheight=\vsize
+ \global\normaloffset= #4
+ \global\bindingoffset= #5}
+
+% A specific text layout, 24x15cm overall, intended for A4 paper. Top margin
+% 29mm, hence bottom margin 28mm, nominal side margin 3cm.
+\def\afourlatex
+ {\global\tolerance=700
+ \global\hfuzz=1pt
+ \setleading{12pt}
+ \global\parskip 15pt plus 1pt
+ \advance\baselineskip by 1.6pt
+ \changepagesizes{237mm}{150mm}{3.6mm}{3.6mm}{3mm}{7mm}
+ }
+
+% Use @afourwide to print on European A4 paper in wide format.
+\def\afourwide{\afourpaper
+\changepagesizes{9.5in}{6.5in}{\hoffset}{\normaloffset}{\bindingoffset}{7mm}}
+
+% Define macros to output various characters with catcode for normal text.
+\catcode`\"=\other
+\catcode`\~=\other
+\catcode`\^=\other
+\catcode`\_=\other
+\catcode`\|=\other
+\catcode`\<=\other
+\catcode`\>=\other
+\catcode`\+=\other
+\def\normaldoublequote{"}
+\def\normaltilde{~}
+\def\normalcaret{^}
+\def\normalunderscore{_}
+\def\normalverticalbar{|}
+\def\normalless{<}
+\def\normalgreater{>}
+\def\normalplus{+}
+
+% This macro is used to make a character print one way in ttfont
+% where it can probably just be output, and another way in other fonts,
+% where something hairier probably needs to be done.
+%
+% #1 is what to print if we are indeed using \tt; #2 is what to print
+% otherwise. Since all the Computer Modern typewriter fonts have zero
+% interword stretch (and shrink), and it is reasonable to expect all
+% typewriter fonts to have this, we can check that font parameter.
+%
+\def\ifusingtt#1#2{\ifdim \fontdimen3\the\font=0pt #1\else #2\fi}
+
+% Turn off all special characters except @
+% (and those which the user can use as if they were ordinary).
+% Most of these we simply print from the \tt font, but for some, we can
+% use math or other variants that look better in normal text.
+
+\catcode`\"=\active
+\def\activedoublequote{{\tt \char '042}}
+\let"=\activedoublequote
+\catcode`\~=\active
+\def~{{\tt \char '176}}
+\chardef\hat=`\^
+\catcode`\^=\active
+\def\auxhat{\def^{'hat}}
+\def^{{\tt \hat}}
+
+\catcode`\_=\active
+\def_{\ifusingtt\normalunderscore\_}
+% Subroutine for the previous macro.
+\def\_{\leavevmode \kern.06em \vbox{\hrule width.3em height.1ex}}
+
+\catcode`\|=\active
+\def|{{\tt \char '174}}
+\chardef \less=`\<
+\catcode`\<=\active
+\def<{{\tt \less}}
+\chardef \gtr=`\>
+\catcode`\>=\active
+\def>{{\tt \gtr}}
+\catcode`\+=\active
+\def+{{\tt \char 43}}
+%\catcode 27=\active
+%\def^^[{$\diamondsuit$}
+
+% Set up an active definition for =, but don't enable it most of the time.
+{\catcode`\==\active
+\global\def={{\tt \char 61}}}
+
+\catcode`+=\active
+\catcode`\_=\active
+
+% If a .fmt file is being used, characters that might appear in a file
+% name cannot be active until we have parsed the command line.
+% So turn them off again, and have \everyjob (or @setfilename) turn them on.
+% \otherifyactive is called near the end of this file.
+\def\otherifyactive{\catcode`+=\other \catcode`\_=\other}
+
+\catcode`\@=0
+
+% \rawbackslashxx output one backslash character in current font
+\global\chardef\rawbackslashxx=`\\
+%{\catcode`\\=\other
+%@gdef@rawbackslashxx{\}}
+
+% \rawbackslash redefines \ as input to do \rawbackslashxx.
+{\catcode`\\=\active
+@gdef@rawbackslash{@let\=@rawbackslashxx }}
+
+% \normalbackslash outputs one backslash in fixed width font.
+\def\normalbackslash{{\tt\rawbackslashxx}}
+
+% Say @foo, not \foo, in error messages.
+\escapechar=`\@
+
+% \catcode 17=0 % Define control-q
+\catcode`\\=\active
+
+% Used sometimes to turn off (effectively) the active characters
+% even after parsing them.
+@def@turnoffactive{@let"=@normaldoublequote
+@let\=@realbackslash
+@let~=@normaltilde
+@let^=@normalcaret
+@let_=@normalunderscore
+@let|=@normalverticalbar
+@let<=@normalless
+@let>=@normalgreater
+@let+=@normalplus}
+
+@def@normalturnoffactive{@let"=@normaldoublequote
+@let\=@normalbackslash
+@let~=@normaltilde
+@let^=@normalcaret
+@let_=@normalunderscore
+@let|=@normalverticalbar
+@let<=@normalless
+@let>=@normalgreater
+@let+=@normalplus}
+
+% Make _ and + \other characters, temporarily.
+% This is canceled by @fixbackslash.
+@otherifyactive
+
+% If a .fmt file is being used, we don't want the `\input texinfo' to show up.
+% That is what \eatinput is for; after that, the `\' should revert to printing
+% a backslash.
+%
+@gdef@eatinput input texinfo{@fixbackslash}
+@global@let\ = @eatinput
+
+% On the other hand, perhaps the file did not have a `\input texinfo'. Then
+% the first `\{ in the file would cause an error. This macro tries to fix
+% that, assuming it is called before the first `\' could plausibly occur.
+% Also back turn on active characters that might appear in the input
+% file name, in case not using a pre-dumped format.
+%
+@gdef@fixbackslash{@ifx\@eatinput @let\ = @normalbackslash @fi
+ @catcode`+=@active @catcode`@_=@active}
+
+%% These look ok in all fonts, so just make them not special. The @rm below
+%% makes sure that the current font starts out as the newly loaded cmr10
+@catcode`@$=@other @catcode`@%=@other @catcode`@&=@other @catcode`@#=@other
+
+@textfonts
+@rm
+
+@c Local variables:
+@c page-delimiter: "^\\\\message"
+@c End:
diff --git a/urandom.h b/urandom.h
new file mode 100644
index 000000000..a2cd2e7ed
--- /dev/null
+++ b/urandom.h
@@ -0,0 +1,64 @@
+/* urandom.h -- define urandom returning a full unsigned long random value.
+
+Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#if defined (__hpux) || defined (__svr4__) || defined (__SVR4)
+/* HPUX lacks random(). */
+static inline unsigned long
+urandom ()
+{
+ return mrand48 ();
+}
+#define __URANDOM
+#endif
+
+#if defined (__alpha__) && !defined (__URANDOM)
+/* DEC OSF/1 1.2 random() returns a double. */
+long mrand48 ();
+static inline unsigned long
+urandom ()
+{
+ return mrand48 () | (mrand48 () << 32);
+}
+#define __URANDOM
+#endif
+
+#if BITS_PER_MP_LIMB == 32 && !defined (__URANDOM)
+long random ();
+static inline unsigned long
+urandom ()
+{
+ /* random() returns 31 bits, we want 32. */
+ return random () ^ (random () << 1);
+}
+#define __URANDOM
+#endif
+
+#if BITS_PER_MP_LIMB == 64 && !defined (__URANDOM)
+long random ();
+static inline unsigned long
+urandom ()
+{
+ /* random() returns 31 bits, we want 64. */
+ return random () ^ (random () << 31) ^ (random () << 62);
+}
+#define __URANDOM
+#endif
+
diff --git a/version.c b/version.c
new file mode 100644
index 000000000..e00a1b66f
--- /dev/null
+++ b/version.c
@@ -0,0 +1 @@
+static char *gmp_version = "2.0";