From dd9e0f894eec7e2a8cf85078330ddc0a6639090b Mon Sep 17 00:00:00 2001 From: Richard Kreckel Date: Fri, 28 Jan 2000 11:37:18 +0000 Subject: [PATCH] Initial revision --- COPYING | 340 ++ ChangeLog | 294 ++ FILES | 57 + INSTALL | 40 + INSTALL.generic | 161 + Makefile.devel | 48 + Makefile.in | 63 + NEWS | 479 ++ README | 41 + TODO | 31 + TODO-subclass | 27 + TODO-verylong | 4 + autoconf/acgeneral.m4 | 2650 ++++++++++ autoconf/aclocal.m4 | 937 ++++ autoconf/acspecific.m4 | 2867 ++++++++++ autoconf/autoconf | 159 + autoconf/autoconf.m4 | 27 + autoconf/config.guess | 1050 ++++ autoconf/config.sub | 1005 ++++ autoconf/floatparam.c | 107 + autoconf/intparam.c | 588 +++ autoconf/ltconfig | 1513 ++++++ autoconf/ltmain.sh | 2455 +++++++++ benchmarks/Makefile.in | 111 + benchmarks/README | 11 + benchmarks/bench2.txt | 63 + benchmarks/timebench1.LiDIA.cc | 167 + benchmarks/timebench1.cc | 198 + benchmarks/timebench1.gp | 30 + benchmarks/timebench1.lsp | 69 + benchmarks/timebench2.results | 133 + benchmarks/timebench2.sh | 7 + benchmarks/timebench2a.LiDIA.cc | 77 + benchmarks/timebench2a.cc | 81 + benchmarks/timebench2a.gp | 25 + benchmarks/timebench2ap.cc | 46 + benchmarks/timebench2ap.gp | 4 + benchmarks/timebench2b.LiDIA.cc | 202 + benchmarks/timebench2b.cc | 190 + benchmarks/timebench2b.gp | 36 + benchmarks/timebench2c.gp | 15 + benchmarks/timebench2d.gp | 5 + configure | 3233 ++++++++++++ configure.in | 161 + doc/Makefile.devel | 45 + doc/Makefile.in | 115 + doc/addnodes.el | 17 + doc/cln.dvi | Bin 0 -> 157376 bytes doc/cln.html | 4422 ++++++++++++++++ doc/cln.info | 3355 ++++++++++++ doc/cln.ps | 4639 +++++++++++++++++ doc/cln.tex | 3366 ++++++++++++ doc/cln.texi | 3665 +++++++++++++ doc/cln_1.html | 169 + doc/cln_10.html | 153 + doc/cln_11.html | 413 ++ doc/cln_12.html | 97 + doc/cln_13.html | 22 + doc/cln_2.html | 255 + doc/cln_3.html | 364 ++ doc/cln_4.html | 1804 +++++++ doc/cln_5.html | 418 ++ doc/cln_6.html | 112 + doc/cln_7.html | 215 + doc/cln_8.html | 123 + doc/cln_9.html | 323 ++ doc/cln_toc.html | 121 + doc/polynomial/Makefile.devel | 25 + doc/polynomial/README | 5 + doc/polynomial/diag_rational.dvi | Bin 0 -> 13132 bytes doc/polynomial/diag_rational.lyx | 763 +++ doc/polynomial/diag_rational.ps | 1315 +++++ doc/polynomial/diag_rational.tex | 269 + doc/polynomial/hermite.dvi | Bin 0 -> 4080 bytes doc/polynomial/hermite.lyx | 199 + doc/polynomial/hermite.ps | 647 +++ doc/polynomial/hermite.tex | 176 + doc/polynomial/laguerre.dvi | Bin 0 -> 7864 bytes doc/polynomial/laguerre.lyx | 316 ++ doc/polynomial/laguerre.ps | 864 +++ doc/polynomial/laguerre.tex | 214 + doc/polynomial/legendre.dvi | Bin 0 -> 8888 bytes doc/polynomial/legendre.lyx | 361 ++ doc/polynomial/legendre.ps | 889 ++++ doc/polynomial/legendre.tex | 224 + doc/polynomial/tchebychev.dvi | Bin 0 -> 6372 bytes doc/polynomial/tchebychev.lyx | 333 ++ doc/polynomial/tchebychev.ps | 726 +++ doc/polynomial/tchebychev.tex | 208 + doc/ratseries/README | 15 + doc/ratseries/paper/Makefile.devel | 38 + doc/ratseries/paper/README | 41 + doc/ratseries/paper/acm.bst | 1134 ++++ doc/ratseries/paper/acmconf.sty | 713 +++ doc/ratseries/paper/binsplit.bib | 131 + doc/ratseries/paper/binsplit.dvi | Bin 0 -> 59996 bytes doc/ratseries/paper/binsplit.ps | 3030 +++++++++++ doc/ratseries/paper/binsplit.tex | 1130 ++++ doc/ratseries/slides/Makefile.devel | 52 + doc/ratseries/slides/epsf.tex | 138 + doc/ratseries/slides/fig2.cln | 13 + doc/ratseries/slides/fig2.eps | 339 ++ doc/ratseries/slides/fig2.lidia | 13 + doc/ratseries/slides/fig2.maple | 13 + doc/ratseries/slides/fig2.pari | 13 + doc/ratseries/slides/fig2log.cln | 13 + doc/ratseries/slides/fig2log.lidia | 13 + doc/ratseries/slides/fig2log.maple | 14 + doc/ratseries/slides/fig2log.pari | 13 + doc/ratseries/slides/gnuplot-command | 7 + doc/ratseries/slides/slide0.dvi | Bin 0 -> 460 bytes doc/ratseries/slides/slide0.log | 6 + doc/ratseries/slides/slide0.ps | 304 ++ doc/ratseries/slides/slide0.tex | 26 + doc/ratseries/slides/slide1.dvi | Bin 0 -> 1220 bytes doc/ratseries/slides/slide1.log | 6 + doc/ratseries/slides/slide1.ps | 425 ++ doc/ratseries/slides/slide1.tex | 30 + doc/ratseries/slides/slide2.dvi | Bin 0 -> 1100 bytes doc/ratseries/slides/slide2.log | 6 + doc/ratseries/slides/slide2.ps | 408 ++ doc/ratseries/slides/slide2.tex | 28 + doc/ratseries/slides/slide3.dvi | Bin 0 -> 1700 bytes doc/ratseries/slides/slide3.log | 6 + doc/ratseries/slides/slide3.ps | 478 ++ doc/ratseries/slides/slide3.tex | 38 + doc/ratseries/slides/slide4.dvi | Bin 0 -> 1332 bytes doc/ratseries/slides/slide4.log | 20 + doc/ratseries/slides/slide4.ps | 450 ++ doc/ratseries/slides/slide4.tex | 28 + doc/ratseries/slides/slide5.dvi | Bin 0 -> 1116 bytes doc/ratseries/slides/slide5.log | 11 + doc/ratseries/slides/slide5.ps | 466 ++ doc/ratseries/slides/slide5.tex | 38 + doc/ratseries/slides/slide6.dvi | Bin 0 -> 488 bytes doc/ratseries/slides/slide6.log | 19 + doc/ratseries/slides/slide6.ps | 574 ++ doc/ratseries/slides/slide6.tex | 27 + doc/texinfo.tex | 4585 ++++++++++++++++ examples/Makefile.in | 111 + examples/atan_recip.cc | 273 + examples/atanh_recip.cc | 281 + examples/contfrac.cc | 45 + examples/e.cc | 121 + examples/fibonacci.cc | 143 + examples/legendre.cc | 72 + examples/lucaslehmer.cc | 82 + examples/nextprime.cc | 25 + examples/perfnum.cc | 11 + include/cl_GV.h | 299 ++ include/cl_GV_complex.h | 54 + include/cl_GV_integer.h | 84 + include/cl_GV_modinteger.h | 50 + include/cl_GV_number.h | 46 + include/cl_GV_rational.h | 54 + include/cl_GV_real.h | 54 + include/cl_SV.h | 180 + include/cl_SV_complex.h | 50 + include/cl_SV_integer.h | 47 + include/cl_SV_number.h | 58 + include/cl_SV_rational.h | 50 + include/cl_SV_real.h | 50 + include/cl_SV_ringelt.h | 62 + include/cl_V.h | 19 + include/cl_abort.h | 12 + include/cl_complex.h | 157 + include/cl_complex_class.h | 63 + include/cl_complex_io.h | 46 + include/cl_complex_ring.h | 14 + include/cl_condition.h | 40 + include/cl_config.h.in | 119 + include/cl_dfloat.h | 305 ++ include/cl_dfloat_class.h | 65 + include/cl_dfloat_io.h | 27 + include/cl_ffloat.h | 310 ++ include/cl_ffloat_class.h | 76 + include/cl_ffloat_io.h | 27 + include/cl_float.h | 655 +++ include/cl_float_class.h | 50 + include/cl_float_io.h | 79 + include/cl_floatformat.h | 16 + include/cl_input.h | 57 + include/cl_integer.h | 602 +++ include/cl_integer_class.h | 55 + include/cl_integer_io.h | 103 + include/cl_integer_ring.h | 14 + include/cl_io.h | 159 + include/cl_lfloat.h | 411 ++ include/cl_lfloat_class.h | 64 + include/cl_lfloat_io.h | 27 + include/cl_malloc.h | 13 + include/cl_modinteger.h | 470 ++ include/cl_modules.h | 203 + include/cl_null_ring.h | 12 + include/cl_number.h | 245 + include/cl_number_io.h | 34 + include/cl_numtheory.h | 86 + include/cl_object.h | 562 ++ include/cl_output.h | 70 + include/cl_proplist.h | 51 + include/cl_random.h | 43 + include/cl_rational.h | 302 ++ include/cl_rational_class.h | 57 + include/cl_rational_io.h | 76 + include/cl_rational_ring.h | 14 + include/cl_real.h | 519 ++ include/cl_real_class.h | 63 + include/cl_real_io.h | 55 + include/cl_real_ring.h | 14 + include/cl_ring.h | 446 ++ include/cl_sfloat.h | 304 ++ include/cl_sfloat_class.h | 43 + include/cl_sfloat_io.h | 27 + include/cl_string.h | 173 + include/cl_symbol.h | 50 + include/cl_timing.h | 74 + include/cl_types.h | 151 + include/cl_univpoly.h | 713 +++ include/cl_univpoly_complex.h | 222 + include/cl_univpoly_integer.h | 227 + include/cl_univpoly_modint.h | 209 + include/cl_univpoly_rational.h | 226 + include/cl_univpoly_real.h | 222 + include/cln.h | 141 + lidia-interface/LiDIA-patch1 | 321 ++ lidia-interface/LiDIA-patch2 | 27 + lidia-interface/README | 57 + lidia-interface/TAR-FILE-LIST | 236 + lidia-interface/bigint.o.i386-linux | Bin 0 -> 27412 bytes lidia-interface/bigint.o.needs | 104 + lidia-interface/bigint.o.undef | 62 + .../src/interfaces/integers/cln/bigint.c | 784 +++ .../src/interfaces/integers/cln/bigint_def.h | 40 + .../src/interfaces/integers/cln/makefile | 69 + .../src/kernel/integers/cln/README | 17 + .../src/kernel/integers/cln/cln/README.LiDIA | 6 + .../src/kernel/integers/cln/makefile | 178 + src/Makefile.devel | 16 + src/Makefile.in | 240 + src/Makeflags | 3 + src/Makerules.devel | 10 + src/TUNING | 50 + src/base/Makeflags | 3 + src/base/cl_N.h | 21 + src/base/cl_N_err_d0.cc | 19 + src/base/cl_abort.cc | 17 + src/base/cl_alloca.cc | 30 + src/base/cl_alloca.h | 84 + src/base/cl_as_err.cc | 34 + src/base/cl_base_config.h.in | 30 + src/base/cl_condition.cc | 18 + src/base/cl_debug.cc | 78 + src/base/cl_debugout.cc | 27 + src/base/cl_free.cc | 51 + src/base/cl_gmpconfig.h.in | 16 + src/base/cl_immclasses.cc | 13 + src/base/cl_iterator.h | 28 + src/base/cl_low.h | 1314 +++++ src/base/cl_macros.h | 251 + src/base/cl_malloc.cc | 35 + src/base/cl_notreached.cc | 24 + src/base/cl_offsetof.h | 14 + src/base/cl_sysdep.h | 64 + src/base/cl_xmacros.h | 13 + src/base/digit/Makeflags | 4 + src/base/digit/cl_2D.h | 40 + src/base/digit/cl_2D_div.cc | 44 + src/base/digit/cl_2D_exptpos.cc | 36 + src/base/digit/cl_D.h | 223 + src/base/digitseq/Makeflags | 4 + src/base/digitseq/cl_2DS.h | 27 + src/base/digitseq/cl_2DS_div.cc | 113 + src/base/digitseq/cl_2DS_recip.cc | 61 + src/base/digitseq/cl_DS.h | 2653 ++++++++++ src/base/digitseq/cl_DS_div.cc | 376 ++ src/base/digitseq/cl_DS_endian.h | 21 + src/base/digitseq/cl_DS_mul.cc | 473 ++ src/base/digitseq/cl_DS_mul_fftc.h | 1106 ++++ src/base/digitseq/cl_DS_mul_fftcs.h | 1155 ++++ src/base/digitseq/cl_DS_mul_fftm.h | 654 +++ src/base/digitseq/cl_DS_mul_fftp.h | 823 +++ src/base/digitseq/cl_DS_mul_fftp3.h | 672 +++ src/base/digitseq/cl_DS_mul_fftp3m.h | 858 +++ src/base/digitseq/cl_DS_mul_fftr.h | 1142 ++++ src/base/digitseq/cl_DS_mul_kara.h | 260 + src/base/digitseq/cl_DS_mul_kara_sqr.h | 82 + src/base/digitseq/cl_DS_mul_nuss.h | 1511 ++++++ src/base/digitseq/cl_DS_random.cc | 33 + src/base/digitseq/cl_DS_recip.cc | 160 + src/base/digitseq/cl_DS_recipsqrt.cc | 164 + src/base/digitseq/cl_DS_sqrt.cc | 356 ++ src/base/digitseq/cl_DS_trandom.cc | 45 + src/base/digitseq/cl_asm.h | 33 + src/base/digitseq/cl_asm_.cc | 33 + src/base/digitseq/cl_asm_arm.h | 10 + src/base/digitseq/cl_asm_arm_.cc | 3600 +++++++++++++ src/base/digitseq/cl_asm_hppa.h | 2 + src/base/digitseq/cl_asm_hppa_.cc | 75 + src/base/digitseq/cl_asm_i386.h | 11 + src/base/digitseq/cl_asm_i386_.cc | 2070 ++++++++ src/base/digitseq/cl_asm_m68k.h | 11 + src/base/digitseq/cl_asm_m68k_.cc | 1707 ++++++ src/base/digitseq/cl_asm_mips.h | 8 + src/base/digitseq/cl_asm_mips_.cc | 1140 ++++ src/base/digitseq/cl_asm_sparc.h | 11 + src/base/digitseq/cl_asm_sparc64.h | 10 + src/base/digitseq/cl_asm_sparc64_.cc | 2556 +++++++++ src/base/digitseq/cl_asm_sparc_.cc | 4229 +++++++++++++++ src/base/digitseq/digit_header | 57 + src/base/hash/Makeflags | 4 + src/base/hash/cl_hash.h | 190 + src/base/hash/cl_hash1.h | 163 + src/base/hash/cl_hash1weak.h | 93 + src/base/hash/cl_hash2.h | 165 + src/base/hash/cl_hash2weak.h | 93 + src/base/hash/cl_hashset.h | 149 + src/base/hash/cl_hashuniq.h | 160 + src/base/hash/cl_hashuniqweak.h | 93 + .../hash/cl_rcpointer2_hashweak_rcpointer.cc | 47 + .../hash/cl_rcpointer2_hashweak_rcpointer.h | 44 + .../hash/cl_rcpointer_hashweak_rcpointer.cc | 47 + .../hash/cl_rcpointer_hashweak_rcpointer.h | 39 + src/base/input/Makeflags | 4 + src/base/input/cl_read_err_bad.cc | 22 + src/base/input/cl_read_err_eof.cc | 19 + src/base/input/cl_read_err_junk.cc | 27 + src/base/low/Makeflags | 4 + src/base/low/cl_low_div.cc | 306 ++ src/base/low/cl_low_isqrt.cc | 60 + src/base/low/cl_low_isqrt2.cc | 59 + src/base/low/cl_low_mul.cc | 71 + src/base/output/Makeflags | 4 + src/base/output/cl_output_dec.cc | 57 + src/base/output/cl_output_hex.cc | 49 + src/base/output/cl_prin_globals.cc | 28 + src/base/proplist/Makeflags | 4 + src/base/proplist/cl_pl_add.cc | 23 + src/base/proplist/cl_pl_d.cc | 19 + src/base/proplist/cl_pl_get.cc | 19 + src/base/random/Makeflags | 4 + src/base/random/cl_UL_random.cc | 56 + src/base/random/cl_random_def.cc | 16 + src/base/random/cl_random_from.cc | 101 + src/base/random/cl_random_impl.h | 22 + src/base/ring/Makeflags | 4 + src/base/ring/cl_no_ring.cc | 147 + src/base/ring/cl_ring_debug.cc | 25 + src/base/string/Makeflags | 4 + src/base/string/cl_spushstring.h | 61 + src/base/string/cl_spushstring_append.cc | 28 + src/base/string/cl_spushstring_push.cc | 26 + src/base/string/cl_sstring.cc | 26 + src/base/string/cl_sstring.h | 10 + src/base/string/cl_st_c2.cc | 17 + src/base/string/cl_st_concat1.cc | 34 + src/base/string/cl_st_concat2.cc | 34 + src/base/string/cl_st_concat3.cc | 34 + src/base/string/cl_st_debug.cc | 49 + src/base/string/cl_st_hashcode.cc | 27 + src/base/string/cl_st_make0.cc | 23 + src/base/string/cl_st_make1.cc | 31 + src/base/string/cl_st_make2.cc | 30 + src/base/string/cl_st_null.cc | 17 + src/base/string/input/Makeflags | 4 + src/base/string/input/cl_st_get1.cc | 39 + src/base/string/input/cl_st_get2.cc | 49 + src/base/string/input/cl_st_getline1.cc | 32 + src/base/string/input/cl_st_getline2.cc | 47 + src/base/string/input/cl_st_gettoken.cc | 65 + src/base/string/misc/Makeflags | 4 + src/base/string/misc/cl_st_class.cc | 15 + src/base/string/output/Makeflags | 4 + src/base/string/output/cl_st_print.cc | 27 + src/base/symbol/Makeflags | 4 + src/base/symbol/cl_sy_hashcode.cc | 24 + src/base/symbol/cl_symbol.cc | 100 + src/complex/Makeflags | 3 + src/complex/algebraic/Makeflags | 4 + src/complex/algebraic/cl_C_abs.cc | 31 + src/complex/algebraic/cl_C_abs_aux.cc | 20 + src/complex/algebraic/cl_C_signum.cc | 34 + src/complex/algebraic/cl_C_sqrt.cc | 49 + src/complex/algebraic/cl_DF_hypot.cc | 57 + src/complex/algebraic/cl_FF_hypot.cc | 57 + src/complex/algebraic/cl_LF_hypot.cc | 73 + src/complex/algebraic/cl_R_hypot.cc | 88 + src/complex/algebraic/cl_SF_hypot.cc | 57 + src/complex/cl_C.h | 190 + src/complex/elem/Makeflags | 4 + src/complex/elem/cl_C_equal.cc | 53 + src/complex/elem/cl_C_from_R_R_complex.cc | 15 + src/complex/elem/cl_C_from_R_R_complex1.cc | 22 + src/complex/elem/cl_C_imagpart.cc | 22 + src/complex/elem/cl_C_minus.cc | 54 + src/complex/elem/cl_C_minus1.cc | 29 + src/complex/elem/cl_C_mul.cc | 54 + src/complex/elem/cl_C_plus.cc | 54 + src/complex/elem/cl_C_plus1.cc | 29 + src/complex/elem/cl_C_realpart.cc | 23 + src/complex/elem/cl_C_square.cc | 29 + src/complex/elem/cl_C_uminus.cc | 29 + src/complex/elem/cl_C_zerop.cc | 30 + src/complex/elem/division/Makeflags | 4 + src/complex/elem/division/cl_C_DF_recip.cc | 55 + src/complex/elem/division/cl_C_FF_recip.cc | 55 + src/complex/elem/division/cl_C_LF_recip.cc | 71 + src/complex/elem/division/cl_C_SF_recip.cc | 55 + src/complex/elem/division/cl_C_div.cc | 40 + src/complex/elem/division/cl_C_recip.cc | 111 + src/complex/input/Makeflags | 4 + src/complex/input/cl_N_from_string.cc | 26 + src/complex/input/cl_N_read.cc | 339 ++ src/complex/input/cl_N_read_stream.cc | 114 + src/complex/misc/Makeflags | 4 + src/complex/misc/cl_C_class.cc | 22 + src/complex/misc/cl_C_conjugate.cc | 26 + src/complex/misc/cl_C_debug.cc | 30 + src/complex/misc/cl_C_eqhashcode.cc | 31 + src/complex/misc/cl_C_expt.cc | 52 + src/complex/misc/cl_C_expt_I.cc | 54 + src/complex/misc/cl_N_as.cc | 42 + src/complex/output/Makeflags | 4 + src/complex/output/cl_N_aprint.cc | 17 + src/complex/output/cl_N_bprint.cc | 60 + src/complex/ring/Makeflags | 4 + src/complex/ring/cl_C_ring.cc | 159 + src/complex/transcendental/Makeflags | 4 + src/complex/transcendental/cl_C_acos.cc | 94 + src/complex/transcendental/cl_C_acosh.cc | 87 + src/complex/transcendental/cl_C_asin.cc | 39 + src/complex/transcendental/cl_C_asinh.cc | 80 + src/complex/transcendental/cl_C_asinh_aux.cc | 172 + src/complex/transcendental/cl_C_atan.cc | 39 + src/complex/transcendental/cl_C_atanh.cc | 60 + src/complex/transcendental/cl_C_atanh_aux.cc | 127 + src/complex/transcendental/cl_C_cis.cc | 34 + src/complex/transcendental/cl_C_cos.cc | 34 + src/complex/transcendental/cl_C_cosh.cc | 34 + src/complex/transcendental/cl_C_exp.cc | 34 + src/complex/transcendental/cl_C_expt_C.cc | 218 + src/complex/transcendental/cl_C_log.cc | 24 + src/complex/transcendental/cl_C_log2.cc | 96 + src/complex/transcendental/cl_C_phase.cc | 30 + src/complex/transcendental/cl_C_sin.cc | 36 + src/complex/transcendental/cl_C_sinh.cc | 36 + src/complex/transcendental/cl_C_tan.cc | 40 + src/complex/transcendental/cl_C_tanh.cc | 40 + src/complex/transcendental/cl_R_cis.cc | 21 + src/float/Makeflags | 3 + src/float/algebraic/Makeflags | 4 + src/float/algebraic/cl_F_sqrt.cc | 19 + src/float/base/Makeflags | 4 + src/float/base/cl_F_err_nan.cc | 19 + src/float/base/cl_F_err_ov.cc | 19 + src/float/base/cl_F_err_un.cc | 19 + src/float/base/cl_F_globals.cc | 15 + src/float/base/cl_ieee.cc | 52 + src/float/base/cl_ieee.h | 17 + src/float/cl_F.h | 281 + src/float/cl_float_config.h.in | 20 + src/float/conv/Makeflags | 4 + src/float/conv/cl_DF_to_FF.cc | 64 + src/float/conv/cl_DF_to_LF.cc | 47 + src/float/conv/cl_DF_to_SF.cc | 65 + src/float/conv/cl_DF_to_double.cc | 53 + src/float/conv/cl_DF_to_float.cc | 72 + src/float/conv/cl_FF_to_DF.cc | 28 + src/float/conv/cl_FF_to_LF.cc | 41 + src/float/conv/cl_FF_to_SF.cc | 40 + src/float/conv/cl_FF_to_double.cc | 64 + src/float/conv/cl_FF_to_float.cc | 35 + src/float/conv/cl_F_from_F.cc | 23 + src/float/conv/cl_F_from_F_f.cc | 22 + src/float/conv/cl_F_from_I.cc | 26 + src/float/conv/cl_F_from_I_def.cc | 26 + src/float/conv/cl_F_from_I_f.cc | 26 + src/float/conv/cl_F_from_RA.cc | 26 + src/float/conv/cl_F_from_RA_def.cc | 26 + src/float/conv/cl_F_from_RA_f.cc | 26 + src/float/conv/cl_F_to_DF.cc | 22 + src/float/conv/cl_F_to_FF.cc | 22 + src/float/conv/cl_F_to_LF.cc | 23 + src/float/conv/cl_F_to_SF.cc | 22 + src/float/conv/cl_F_to_double.cc | 26 + src/float/conv/cl_F_to_float.cc | 26 + src/float/conv/cl_LF_to_DF.cc | 75 + src/float/conv/cl_LF_to_FF.cc | 51 + src/float/conv/cl_LF_to_SF.cc | 51 + src/float/conv/cl_LF_to_double.cc | 107 + src/float/conv/cl_LF_to_float.cc | 59 + src/float/conv/cl_SF_to_DF.cc | 28 + src/float/conv/cl_SF_to_FF.cc | 24 + src/float/conv/cl_SF_to_LF.cc | 41 + src/float/conv/cl_SF_to_double.cc | 64 + src/float/conv/cl_SF_to_float.cc | 34 + src/float/dfloat/Makeflags | 3 + src/float/dfloat/algebraic/Makeflags | 4 + src/float/dfloat/algebraic/cl_DF_sqrt.cc | 148 + src/float/dfloat/cl_DF.h | 308 ++ src/float/dfloat/conv/Makeflags | 4 + src/float/dfloat/conv/cl_DF_from_double.cc | 60 + src/float/dfloat/conv/cl_DF_to_doublej.cc | 48 + src/float/dfloat/conv/cl_I_to_double.cc | 149 + src/float/dfloat/conv/cl_RA_to_double.cc | 186 + src/float/dfloat/division/Makeflags | 4 + src/float/dfloat/division/cl_DF_ceil22.cc | 22 + src/float/dfloat/division/cl_DF_fceil.cc | 24 + src/float/dfloat/division/cl_DF_floor22.cc | 22 + src/float/dfloat/division/cl_DF_recip.cc | 17 + src/float/dfloat/division/cl_DF_round22.cc | 22 + src/float/dfloat/division/cl_DF_trunc22.cc | 22 + src/float/dfloat/elem/Makeflags | 4 + src/float/dfloat/elem/cl_DF_compare.cc | 82 + src/float/dfloat/elem/cl_DF_div.cc | 222 + src/float/dfloat/elem/cl_DF_ffloor.cc | 24 + src/float/dfloat/elem/cl_DF_from_I.cc | 135 + src/float/dfloat/elem/cl_DF_from_RA.cc | 150 + src/float/dfloat/elem/cl_DF_fround.cc | 168 + src/float/dfloat/elem/cl_DF_ftrunc.cc | 62 + src/float/dfloat/elem/cl_DF_futrunc.cc | 82 + src/float/dfloat/elem/cl_DF_globals.cc | 32 + src/float/dfloat/elem/cl_DF_minus.cc | 43 + src/float/dfloat/elem/cl_DF_minusp.cc | 22 + src/float/dfloat/elem/cl_DF_mul.cc | 209 + src/float/dfloat/elem/cl_DF_plus.cc | 260 + src/float/dfloat/elem/cl_DF_plusp.cc | 28 + src/float/dfloat/elem/cl_DF_scale.cc | 63 + src/float/dfloat/elem/cl_DF_scale_I.cc | 69 + src/float/dfloat/elem/cl_DF_to_I.cc | 45 + src/float/dfloat/elem/cl_DF_uminus.cc | 32 + src/float/dfloat/elem/cl_DF_zerop.cc | 22 + src/float/dfloat/input/Makeflags | 4 + src/float/dfloat/input/cl_DF_from_string.cc | 27 + src/float/dfloat/misc/Makeflags | 4 + src/float/dfloat/misc/cl_DF_abs.cc | 20 + src/float/dfloat/misc/cl_DF_as.cc | 29 + src/float/dfloat/misc/cl_DF_class.cc | 15 + src/float/dfloat/misc/cl_DF_debug.cc | 25 + src/float/dfloat/misc/cl_DF_decode.cc | 42 + src/float/dfloat/misc/cl_DF_digits.cc | 19 + src/float/dfloat/misc/cl_DF_eqhashcode.cc | 32 + src/float/dfloat/misc/cl_DF_exponent.cc | 20 + src/float/dfloat/misc/cl_DF_idecode.cc | 43 + src/float/dfloat/misc/cl_DF_max.cc | 15 + src/float/dfloat/misc/cl_DF_min.cc | 15 + src/float/dfloat/misc/cl_DF_precision.cc | 23 + src/float/dfloat/misc/cl_DF_sign.cc | 23 + src/float/dfloat/misc/cl_DF_signum.cc | 25 + src/float/division/Makeflags | 4 + src/float/division/cl_F_ceil1.cc | 19 + src/float/division/cl_F_ceil2.cc | 30 + src/float/division/cl_F_ceil22.cc | 22 + src/float/division/cl_F_fceil1.cc | 19 + src/float/division/cl_F_fceil2.cc | 32 + src/float/division/cl_F_ffloor1.cc | 19 + src/float/division/cl_F_ffloor2.cc | 32 + src/float/division/cl_F_floor1.cc | 19 + src/float/division/cl_F_floor2.cc | 30 + src/float/division/cl_F_floor22.cc | 22 + src/float/division/cl_F_fround1.cc | 19 + src/float/division/cl_F_fround2.cc | 32 + src/float/division/cl_F_ftrunc1.cc | 19 + src/float/division/cl_F_ftrunc2.cc | 32 + src/float/division/cl_F_round1.cc | 19 + src/float/division/cl_F_round2.cc | 30 + src/float/division/cl_F_round22.cc | 22 + src/float/division/cl_F_trunc1.cc | 19 + src/float/division/cl_F_trunc2.cc | 30 + src/float/division/cl_F_trunc22.cc | 22 + src/float/elem/Makeflags | 4 + src/float/elem/cl_F_I_div.cc | 31 + src/float/elem/cl_F_I_mul.cc | 32 + src/float/elem/cl_F_RA_div.cc | 47 + src/float/elem/cl_F_RA_mul.cc | 32 + src/float/elem/cl_F_compare.cc | 20 + src/float/elem/cl_F_div.cc | 23 + src/float/elem/cl_F_minus.cc | 23 + src/float/elem/cl_F_minusp.cc | 29 + src/float/elem/cl_F_mul.cc | 23 + src/float/elem/cl_F_plus.cc | 23 + src/float/elem/cl_F_plusp.cc | 29 + src/float/elem/cl_F_recip.cc | 19 + src/float/elem/cl_F_scale.cc | 26 + src/float/elem/cl_F_scale_I.cc | 26 + src/float/elem/cl_F_square.cc | 19 + src/float/elem/cl_F_uminus.cc | 20 + src/float/elem/cl_F_zerop.cc | 29 + src/float/elem/cl_I_F_div.cc | 32 + src/float/elem/cl_RA_F_div.cc | 48 + src/float/ffloat/Makeflags | 3 + src/float/ffloat/algebraic/Makeflags | 4 + src/float/ffloat/algebraic/cl_FF_sqrt.cc | 65 + src/float/ffloat/cl_FF.h | 244 + src/float/ffloat/conv/Makeflags | 4 + src/float/ffloat/conv/cl_FF_from_float.cc | 40 + src/float/ffloat/conv/cl_FF_to_floatj.cc | 30 + src/float/ffloat/conv/cl_I_to_float.cc | 108 + src/float/ffloat/conv/cl_RA_to_float.cc | 104 + src/float/ffloat/division/Makeflags | 4 + src/float/ffloat/division/cl_FF_ceil22.cc | 22 + src/float/ffloat/division/cl_FF_fceil.cc | 24 + src/float/ffloat/division/cl_FF_floor22.cc | 22 + src/float/ffloat/division/cl_FF_recip.cc | 17 + src/float/ffloat/division/cl_FF_round22.cc | 22 + src/float/ffloat/division/cl_FF_trunc22.cc | 22 + src/float/ffloat/elem/Makeflags | 4 + src/float/ffloat/elem/cl_FF_compare.cc | 48 + src/float/ffloat/elem/cl_FF_div.cc | 103 + src/float/ffloat/elem/cl_FF_ffloor.cc | 24 + src/float/ffloat/elem/cl_FF_from_I.cc | 115 + src/float/ffloat/elem/cl_FF_from_RA.cc | 108 + src/float/ffloat/elem/cl_FF_fround.cc | 78 + src/float/ffloat/elem/cl_FF_ftrunc.cc | 34 + src/float/ffloat/elem/cl_FF_futrunc.cc | 45 + src/float/ffloat/elem/cl_FF_globals.cc | 24 + src/float/ffloat/elem/cl_FF_minus.cc | 32 + src/float/ffloat/elem/cl_FF_minusp.cc | 18 + src/float/ffloat/elem/cl_FF_mul.cc | 101 + src/float/ffloat/elem/cl_FF_plus.cc | 136 + src/float/ffloat/elem/cl_FF_plusp.cc | 28 + src/float/ffloat/elem/cl_FF_scale.cc | 49 + src/float/ffloat/elem/cl_FF_scale_I.cc | 55 + src/float/ffloat/elem/cl_FF_to_I.cc | 35 + src/float/ffloat/elem/cl_FF_uminus.cc | 23 + src/float/ffloat/elem/cl_FF_zerop.cc | 18 + src/float/ffloat/input/Makeflags | 4 + src/float/ffloat/input/cl_FF_from_string.cc | 27 + src/float/ffloat/misc/Makeflags | 4 + src/float/ffloat/misc/cl_FF_abs.cc | 20 + src/float/ffloat/misc/cl_FF_as.cc | 35 + src/float/ffloat/misc/cl_FF_class.cc | 26 + src/float/ffloat/misc/cl_FF_debug.cc | 25 + src/float/ffloat/misc/cl_FF_decode.cc | 29 + src/float/ffloat/misc/cl_FF_digits.cc | 19 + src/float/ffloat/misc/cl_FF_eqhashcode.cc | 24 + src/float/ffloat/misc/cl_FF_exponent.cc | 20 + src/float/ffloat/misc/cl_FF_idecode.cc | 54 + src/float/ffloat/misc/cl_FF_max.cc | 15 + src/float/ffloat/misc/cl_FF_min.cc | 15 + src/float/ffloat/misc/cl_FF_precision.cc | 23 + src/float/ffloat/misc/cl_FF_sign.cc | 23 + src/float/ffloat/misc/cl_FF_signum.cc | 25 + src/float/input/Makeflags | 4 + src/float/input/cl_F_from_string.cc | 27 + src/float/input/cl_F_read.cc | 178 + src/float/input/cl_F_read_stream.cc | 104 + src/float/input/cl_F_readparsed.cc | 93 + src/float/lfloat/Makeflags | 3 + src/float/lfloat/algebraic/Makeflags | 4 + src/float/lfloat/algebraic/cl_LF_sqrt.cc | 130 + src/float/lfloat/cl_LF.h | 140 + src/float/lfloat/cl_LF_impl.h | 149 + src/float/lfloat/division/Makeflags | 4 + src/float/lfloat/division/cl_LF_ceil22.cc | 22 + src/float/lfloat/division/cl_LF_fceil.cc | 24 + src/float/lfloat/division/cl_LF_floor22.cc | 22 + src/float/lfloat/division/cl_LF_recip.cc | 20 + src/float/lfloat/division/cl_LF_round22.cc | 22 + src/float/lfloat/division/cl_LF_trunc22.cc | 22 + src/float/lfloat/elem/Makeflags | 4 + src/float/lfloat/elem/cl_I_LF_div.cc | 33 + src/float/lfloat/elem/cl_LF_1minus.cc | 27 + src/float/lfloat/elem/cl_LF_1plus.cc | 240 + src/float/lfloat/elem/cl_LF_2minus.cc | 15 + src/float/lfloat/elem/cl_LF_2plus.cc | 15 + src/float/lfloat/elem/cl_LF_I_div.cc | 113 + src/float/lfloat/elem/cl_LF_I_mul.cc | 88 + src/float/lfloat/elem/cl_LF_RA_div.cc | 29 + src/float/lfloat/elem/cl_LF_RA_mul.cc | 49 + src/float/lfloat/elem/cl_LF_compare.cc | 103 + src/float/lfloat/elem/cl_LF_div.cc | 167 + src/float/lfloat/elem/cl_LF_ffloor.cc | 24 + src/float/lfloat/elem/cl_LF_from_I.cc | 116 + src/float/lfloat/elem/cl_LF_from_RA.cc | 142 + src/float/lfloat/elem/cl_LF_fround.cc | 134 + src/float/lfloat/elem/cl_LF_ftrunc.cc | 70 + src/float/lfloat/elem/cl_LF_futrunc.cc | 99 + src/float/lfloat/elem/cl_LF_globals.cc | 20 + src/float/lfloat/elem/cl_LF_minus1.cc | 19 + src/float/lfloat/elem/cl_LF_minusp.cc | 18 + src/float/lfloat/elem/cl_LF_mul.cc | 109 + src/float/lfloat/elem/cl_LF_plus1.cc | 19 + src/float/lfloat/elem/cl_LF_plusp.cc | 29 + src/float/lfloat/elem/cl_LF_scale.cc | 42 + src/float/lfloat/elem/cl_LF_scale_I.cc | 107 + src/float/lfloat/elem/cl_LF_square.cc | 89 + src/float/lfloat/elem/cl_LF_to_I.cc | 45 + src/float/lfloat/elem/cl_LF_uminus.cc | 28 + src/float/lfloat/elem/cl_LF_zerop.cc | 18 + src/float/lfloat/elem/cl_RA_LF_div.cc | 61 + src/float/lfloat/input/Makeflags | 4 + src/float/lfloat/input/cl_LF_from_string.cc | 27 + src/float/lfloat/misc/Makeflags | 4 + src/float/lfloat/misc/cl_LF_abs.cc | 20 + src/float/lfloat/misc/cl_LF_as.cc | 29 + src/float/lfloat/misc/cl_LF_class.cc | 15 + src/float/lfloat/misc/cl_LF_debug.cc | 25 + src/float/lfloat/misc/cl_LF_decode.cc | 30 + src/float/lfloat/misc/cl_LF_digits.cc | 18 + src/float/lfloat/misc/cl_LF_eqhashcode.cc | 29 + src/float/lfloat/misc/cl_LF_exponent.cc | 20 + src/float/lfloat/misc/cl_LF_extend.cc | 25 + src/float/lfloat/misc/cl_LF_idecode.cc | 38 + src/float/lfloat/misc/cl_LF_leninc.cc | 53 + src/float/lfloat/misc/cl_LF_lenincx.cc | 46 + src/float/lfloat/misc/cl_LF_max.cc | 15 + src/float/lfloat/misc/cl_LF_min.cc | 15 + src/float/lfloat/misc/cl_LF_precision.cc | 23 + src/float/lfloat/misc/cl_LF_shorten.cc | 44 + src/float/lfloat/misc/cl_LF_shortenrel.cc | 52 + src/float/lfloat/misc/cl_LF_shortenwith.cc | 49 + src/float/lfloat/misc/cl_LF_sign.cc | 24 + src/float/lfloat/misc/cl_LF_signum.cc | 26 + src/float/lfloat/misc/cl_LF_to_LF.cc | 19 + src/float/misc/Makeflags | 4 + src/float/misc/cl_F_abs.cc | 34 + src/float/misc/cl_F_as.cc | 37 + src/float/misc/cl_F_decode.cc | 105 + src/float/misc/cl_F_digits.cc | 29 + src/float/misc/cl_F_epsneg.cc | 63 + src/float/misc/cl_F_epspos.cc | 62 + src/float/misc/cl_F_eqhashcode.cc | 30 + src/float/misc/cl_F_exponent.cc | 29 + src/float/misc/cl_F_extendsqrt.cc | 37 + src/float/misc/cl_F_extendsqrtx.cc | 28 + src/float/misc/cl_F_idecode.cc | 29 + src/float/misc/cl_F_leastneg.cc | 58 + src/float/misc/cl_F_leastpos.cc | 58 + src/float/misc/cl_F_max.cc | 15 + src/float/misc/cl_F_min.cc | 15 + src/float/misc/cl_F_mostneg.cc | 52 + src/float/misc/cl_F_mostpos.cc | 52 + src/float/misc/cl_F_precision.cc | 29 + src/float/misc/cl_F_rational.cc | 49 + src/float/misc/cl_F_shortenrel.cc | 48 + src/float/misc/cl_F_sign.cc | 30 + src/float/misc/cl_F_sign2.cc | 22 + src/float/misc/cl_F_signum.cc | 29 + src/float/misc/cl_float_format.cc | 27 + src/float/output/Makeflags | 4 + src/float/output/cl_F_aprint.cc | 17 + src/float/output/cl_F_bprint.cc | 17 + src/float/output/cl_F_cprint.cc | 17 + src/float/output/cl_F_dprint.cc | 442 ++ src/float/output/cl_F_printb.cc | 42 + src/float/random/Makeflags | 4 + src/float/random/cl_F_random.cc | 37 + src/float/sfloat/Makeflags | 3 + src/float/sfloat/algebraic/Makeflags | 4 + src/float/sfloat/algebraic/cl_SF_sqrt.cc | 64 + src/float/sfloat/cl_SF.h | 133 + src/float/sfloat/division/Makeflags | 4 + src/float/sfloat/division/cl_SF_ceil22.cc | 22 + src/float/sfloat/division/cl_SF_fceil.cc | 24 + src/float/sfloat/division/cl_SF_ffloor.cc | 24 + src/float/sfloat/division/cl_SF_floor22.cc | 22 + src/float/sfloat/division/cl_SF_recip.cc | 17 + src/float/sfloat/division/cl_SF_round22.cc | 22 + src/float/sfloat/division/cl_SF_trunc22.cc | 22 + src/float/sfloat/elem/Makeflags | 4 + src/float/sfloat/elem/cl_SF_compare.cc | 48 + src/float/sfloat/elem/cl_SF_div.cc | 86 + src/float/sfloat/elem/cl_SF_from_I.cc | 114 + src/float/sfloat/elem/cl_SF_from_RA.cc | 104 + src/float/sfloat/elem/cl_SF_fround.cc | 77 + src/float/sfloat/elem/cl_SF_ftrunc.cc | 34 + src/float/sfloat/elem/cl_SF_futrunc.cc | 49 + src/float/sfloat/elem/cl_SF_minus.cc | 26 + src/float/sfloat/elem/cl_SF_minusp.cc | 18 + src/float/sfloat/elem/cl_SF_mul.cc | 96 + src/float/sfloat/elem/cl_SF_plus.cc | 124 + src/float/sfloat/elem/cl_SF_plusp.cc | 28 + src/float/sfloat/elem/cl_SF_scale.cc | 49 + src/float/sfloat/elem/cl_SF_scale_I.cc | 55 + src/float/sfloat/elem/cl_SF_to_I.cc | 29 + src/float/sfloat/elem/cl_SF_uminus.cc | 25 + src/float/sfloat/elem/cl_SF_zerop.cc | 18 + src/float/sfloat/input/Makeflags | 4 + src/float/sfloat/input/cl_SF_from_string.cc | 27 + src/float/sfloat/misc/Makeflags | 4 + src/float/sfloat/misc/cl_SF_abs.cc | 20 + src/float/sfloat/misc/cl_SF_as.cc | 29 + src/float/sfloat/misc/cl_SF_class.cc | 20 + src/float/sfloat/misc/cl_SF_debug.cc | 25 + src/float/sfloat/misc/cl_SF_decode.cc | 29 + src/float/sfloat/misc/cl_SF_digits.cc | 19 + src/float/sfloat/misc/cl_SF_eqhashcode.cc | 24 + src/float/sfloat/misc/cl_SF_exponent.cc | 20 + src/float/sfloat/misc/cl_SF_idecode.cc | 30 + src/float/sfloat/misc/cl_SF_max.cc | 15 + src/float/sfloat/misc/cl_SF_min.cc | 15 + src/float/sfloat/misc/cl_SF_precision.cc | 23 + src/float/sfloat/misc/cl_SF_sign.cc | 23 + src/float/sfloat/misc/cl_SF_signum.cc | 25 + src/float/transcendental/Makefile.devel | 16 + src/float/transcendental/Makeflags | 4 + src/float/transcendental/cl_F_atanhx.cc | 185 + src/float/transcendental/cl_F_atanx.cc | 258 + src/float/transcendental/cl_F_catalanconst.cc | 24 + .../transcendental/cl_F_catalanconst_def.cc | 23 + .../transcendental/cl_F_catalanconst_f.cc | 23 + .../transcendental/cl_F_catalanconst_var.cc | 33 + .../transcendental/cl_F_catalanconst_var.h | 29 + .../transcendental/cl_F_catalanconst_var.h.in | 2 + src/float/transcendental/cl_F_cos.cc | 91 + src/float/transcendental/cl_F_cosh.cc | 84 + src/float/transcendental/cl_F_coshsinh.cc | 90 + src/float/transcendental/cl_F_cossin.cc | 87 + src/float/transcendental/cl_F_eulerconst.cc | 24 + .../transcendental/cl_F_eulerconst_def.cc | 23 + src/float/transcendental/cl_F_eulerconst_f.cc | 23 + .../transcendental/cl_F_eulerconst_var.cc | 33 + .../transcendental/cl_F_eulerconst_var.h | 29 + .../transcendental/cl_F_eulerconst_var.h.in | 2 + src/float/transcendental/cl_F_exp.cc | 62 + src/float/transcendental/cl_F_exp1.cc | 24 + src/float/transcendental/cl_F_exp1_def.cc | 23 + src/float/transcendental/cl_F_exp1_f.cc | 23 + src/float/transcendental/cl_F_exp1_var.cc | 33 + src/float/transcendental/cl_F_exp1_var.h | 29 + src/float/transcendental/cl_F_exp1_var.h.in | 2 + src/float/transcendental/cl_F_expx.cc | 190 + src/float/transcendental/cl_F_ln.cc | 55 + src/float/transcendental/cl_F_ln10.cc | 23 + src/float/transcendental/cl_F_ln10_f.cc | 22 + src/float/transcendental/cl_F_ln10_var.cc | 33 + src/float/transcendental/cl_F_ln10_var.h | 29 + src/float/transcendental/cl_F_ln10_var.h.in | 2 + src/float/transcendental/cl_F_ln2.cc | 23 + src/float/transcendental/cl_F_ln2_f.cc | 22 + src/float/transcendental/cl_F_ln2_var.cc | 33 + src/float/transcendental/cl_F_ln2_var.h | 29 + src/float/transcendental/cl_F_ln2_var.h.in | 2 + src/float/transcendental/cl_F_lnx.cc | 248 + src/float/transcendental/cl_F_pi.cc | 24 + src/float/transcendental/cl_F_pi_def.cc | 23 + src/float/transcendental/cl_F_pi_f.cc | 23 + src/float/transcendental/cl_F_pi_var.cc | 33 + src/float/transcendental/cl_F_pi_var.h | 29 + src/float/transcendental/cl_F_pi_var.h.in | 23 + src/float/transcendental/cl_F_roundpi.cc | 20 + src/float/transcendental/cl_F_roundpi2.cc | 20 + src/float/transcendental/cl_F_sin.cc | 102 + src/float/transcendental/cl_F_sinh.cc | 77 + src/float/transcendental/cl_F_sinhx.cc | 206 + src/float/transcendental/cl_F_sinx.cc | 217 + src/float/transcendental/cl_F_tan.cc | 19 + src/float/transcendental/cl_F_tanh.cc | 19 + src/float/transcendental/cl_F_tran.h | 148 + src/float/transcendental/cl_F_zeta_int.cc | 24 + src/float/transcendental/cl_F_zeta_int_def.cc | 24 + src/float/transcendental/cl_F_zeta_int_f.cc | 24 + src/float/transcendental/cl_LF_atan_recip.cc | 50 + src/float/transcendental/cl_LF_atanh_recip.cc | 49 + .../transcendental/cl_LF_catalanconst.cc | 275 + src/float/transcendental/cl_LF_coshsinh.cc | 55 + .../transcendental/cl_LF_coshsinh_aux.cc | 117 + src/float/transcendental/cl_LF_cossin.cc | 55 + src/float/transcendental/cl_LF_cossin_aux.cc | 117 + src/float/transcendental/cl_LF_eulerconst.cc | 519 ++ src/float/transcendental/cl_LF_exp1.cc | 94 + src/float/transcendental/cl_LF_exp_aux.cc | 79 + src/float/transcendental/cl_LF_ln10.cc | 65 + src/float/transcendental/cl_LF_ln2.cc | 93 + src/float/transcendental/cl_LF_pi.cc | 277 + src/float/transcendental/cl_LF_ratseries.cc | 108 + src/float/transcendental/cl_LF_ratseries_.cc | 40 + src/float/transcendental/cl_LF_ratseries_a.cc | 76 + .../transcendental/cl_LF_ratseries_ab.cc | 84 + src/float/transcendental/cl_LF_ratseries_b.cc | 84 + src/float/transcendental/cl_LF_ratseries_p.cc | 87 + .../transcendental/cl_LF_ratseries_pa.cc | 87 + .../transcendental/cl_LF_ratseries_pab.cc | 95 + .../transcendental/cl_LF_ratseries_pb.cc | 95 + .../transcendental/cl_LF_ratseries_pq.cc | 188 + .../transcendental/cl_LF_ratseries_pqa.cc | 188 + .../transcendental/cl_LF_ratseries_pqab.cc | 204 + .../transcendental/cl_LF_ratseries_pqb.cc | 204 + src/float/transcendental/cl_LF_ratseries_q.cc | 84 + .../transcendental/cl_LF_ratseries_qa.cc | 84 + .../transcendental/cl_LF_ratseries_qab.cc | 92 + .../transcendental/cl_LF_ratseries_qb.cc | 92 + .../cl_LF_ratseries_stream_pq.cc | 98 + .../cl_LF_ratseries_stream_pqa.cc | 98 + .../cl_LF_ratseries_stream_pqab.cc | 106 + .../cl_LF_ratseries_stream_pqb.cc | 106 + .../transcendental/cl_LF_ratsumseries_pqcd.cc | 28 + .../cl_LF_ratsumseries_pqcd_aux.cc | 79 + .../transcendental/cl_LF_ratsumseries_pqd.cc | 28 + .../cl_LF_ratsumseries_pqd_aux.cc | 75 + src/float/transcendental/cl_LF_tran.h | 262 + src/float/transcendental/cl_LF_zeta3.cc | 83 + src/float/transcendental/cl_LF_zeta_int.cc | 144 + src/integer/2adic/Makeflags | 4 + src/integer/2adic/cl_I_2adic_div.cc | 50 + src/integer/2adic/cl_I_2adic_recip.cc | 40 + src/integer/Makeflags | 3 + src/integer/algebraic/Makeflags | 4 + src/integer/algebraic/cl_I_rootp.cc | 27 + src/integer/algebraic/cl_I_rootp_I.cc | 28 + src/integer/algebraic/cl_I_rootp_aux.cc | 196 + src/integer/algebraic/cl_I_sqrt.cc | 39 + src/integer/algebraic/cl_I_sqrtp.cc | 87 + src/integer/bitwise/Makeflags | 4 + src/integer/bitwise/cl_I_ash.cc | 88 + src/integer/bitwise/cl_I_ash.h | 12 + src/integer/bitwise/cl_I_ash_I.cc | 169 + src/integer/bitwise/cl_I_asherr.cc | 23 + src/integer/bitwise/cl_I_boole.cc | 50 + src/integer/bitwise/cl_I_byte.h | 29 + src/integer/bitwise/cl_I_dpb.cc | 21 + src/integer/bitwise/cl_I_dpf.cc | 24 + src/integer/bitwise/cl_I_fullbyte.cc | 21 + src/integer/bitwise/cl_I_ilength.cc | 38 + src/integer/bitwise/cl_I_ldb.cc | 48 + src/integer/bitwise/cl_I_ldbtest.cc | 48 + src/integer/bitwise/cl_I_ldbx.cc | 56 + src/integer/bitwise/cl_I_ldbxtest.cc | 57 + src/integer/bitwise/cl_I_log.h | 34 + src/integer/bitwise/cl_I_log_aux.cc | 53 + src/integer/bitwise/cl_I_logand.cc | 51 + src/integer/bitwise/cl_I_logandc2.cc | 45 + src/integer/bitwise/cl_I_logbitp.cc | 37 + src/integer/bitwise/cl_I_logbitp_I.cc | 50 + src/integer/bitwise/cl_I_logcount.cc | 37 + src/integer/bitwise/cl_I_logeqv.cc | 40 + src/integer/bitwise/cl_I_logior.cc | 40 + src/integer/bitwise/cl_I_lognand.cc | 51 + src/integer/bitwise/cl_I_lognor.cc | 40 + src/integer/bitwise/cl_I_lognot.cc | 34 + src/integer/bitwise/cl_I_logorc2.cc | 40 + src/integer/bitwise/cl_I_logtest.cc | 95 + src/integer/bitwise/cl_I_logxor.cc | 40 + src/integer/bitwise/cl_I_mkf.cc | 49 + src/integer/bitwise/cl_I_mkfx.cc | 50 + src/integer/cl_I.h | 659 +++ src/integer/conv/Makeflags | 4 + src/integer/conv/cl_I_digits_need.cc | 62 + src/integer/conv/cl_I_from_DS.cc | 41 + src/integer/conv/cl_I_from_L.cc | 104 + src/integer/conv/cl_I_from_L2.cc | 131 + src/integer/conv/cl_I_from_NDS.cc | 100 + src/integer/conv/cl_I_from_NUDS.cc | 27 + src/integer/conv/cl_I_from_Q.cc | 147 + src/integer/conv/cl_I_from_UDS.cc | 30 + src/integer/conv/cl_I_from_UL.cc | 92 + src/integer/conv/cl_I_from_UL2.cc | 102 + src/integer/conv/cl_I_from_UQ.cc | 154 + src/integer/conv/cl_I_from_digits.cc | 86 + src/integer/conv/cl_I_mul10plus.cc | 26 + src/integer/conv/cl_I_to_L.cc | 76 + src/integer/conv/cl_I_to_Q.cc | 139 + src/integer/conv/cl_I_to_UL.cc | 59 + src/integer/conv/cl_I_to_UQ.cc | 98 + src/integer/conv/cl_I_to_digits.cc | 411 ++ src/integer/division/Makeflags | 4 + src/integer/division/cl_I_ceil1.cc | 33 + src/integer/division/cl_I_ceil2.cc | 35 + src/integer/division/cl_I_exquo.cc | 27 + src/integer/division/cl_I_exquoerr.cc | 24 + src/integer/division/cl_I_exquopos.cc | 24 + src/integer/division/cl_I_floor1.cc | 33 + src/integer/division/cl_I_floor2.cc | 35 + src/integer/division/cl_I_mod.cc | 29 + src/integer/division/cl_I_rem.cc | 23 + src/integer/division/cl_I_round1.cc | 37 + src/integer/division/cl_I_round2.cc | 39 + src/integer/division/cl_I_trunc1.cc | 27 + src/integer/division/cl_I_trunc2.cc | 30 + src/integer/elem/Makeflags | 4 + src/integer/elem/cl_I_compare.cc | 103 + src/integer/elem/cl_I_div.cc | 88 + src/integer/elem/cl_I_equal.cc | 54 + src/integer/elem/cl_I_minus.cc | 206 + src/integer/elem/cl_I_minus1.cc | 33 + src/integer/elem/cl_I_minusp.cc | 19 + src/integer/elem/cl_I_mul.cc | 52 + src/integer/elem/cl_I_plus.cc | 201 + src/integer/elem/cl_I_plus1.cc | 33 + src/integer/elem/cl_I_plusp.cc | 26 + src/integer/elem/cl_I_square.cc | 51 + src/integer/elem/cl_I_uminus.cc | 43 + src/integer/elem/cl_I_zerop.cc | 19 + src/integer/gcd/Makeflags | 4 + src/integer/gcd/cl_I_gcd.cc | 519 ++ src/integer/gcd/cl_I_gcd_aux.cc | 59 + src/integer/gcd/cl_I_gcd_aux2.cc | 453 ++ src/integer/gcd/cl_I_lcm.cc | 32 + src/integer/gcd/cl_I_xgcd.cc | 530 ++ src/integer/gcd/cl_low_gcd.cc | 91 + src/integer/hash/Makeflags | 4 + src/integer/hash/cl_I_hash_gcobject.cc | 48 + src/integer/hash/cl_I_hash_gcobject.h | 39 + src/integer/hash/cl_I_hash_gcpointer.cc | 48 + src/integer/hash/cl_I_hash_gcpointer.h | 39 + src/integer/hash/cl_I_hash_pointer.cc | 48 + src/integer/hash/cl_I_hash_pointer.h | 39 + src/integer/hash/cl_I_hash_rcobject.cc | 48 + src/integer/hash/cl_I_hash_rcobject.h | 39 + src/integer/hash/cl_I_hash_rcpointer.cc | 48 + src/integer/hash/cl_I_hash_rcpointer.h | 39 + src/integer/hash/cl_I_hashcode.cc | 38 + src/integer/hash/cl_I_hashweak_rcpointer.cc | 48 + src/integer/hash/cl_I_hashweak_rcpointer.h | 39 + src/integer/input/Makeflags | 4 + src/integer/input/cl_I_from_string.cc | 26 + src/integer/input/cl_I_read.cc | 134 + src/integer/input/cl_I_read_stream.cc | 104 + src/integer/input/cl_I_readparsed.cc | 21 + src/integer/misc/Makeflags | 4 + src/integer/misc/cl_BN_class.cc | 15 + src/integer/misc/cl_FN_class.cc | 20 + src/integer/misc/cl_I_abs.cc | 22 + src/integer/misc/cl_I_as.cc | 38 + src/integer/misc/cl_I_debug.cc | 28 + src/integer/misc/cl_I_eqhashcode.cc | 133 + src/integer/misc/cl_I_exptpos.cc | 54 + src/integer/misc/cl_I_exptpos_I.cc | 56 + src/integer/misc/cl_I_max.cc | 15 + src/integer/misc/cl_I_min.cc | 15 + src/integer/misc/cl_I_oddp.cc | 30 + src/integer/misc/cl_I_ord2.cc | 44 + src/integer/misc/cl_I_power2p.cc | 40 + src/integer/misc/cl_I_signum.cc | 20 + src/integer/misc/combin/Makeflags | 4 + src/integer/misc/combin/cl_I_binomial.cc | 56 + src/integer/misc/combin/cl_I_combin.h | 13 + .../misc/combin/cl_I_doublefactorial.cc | 139 + src/integer/misc/combin/cl_I_factorial.cc | 99 + src/integer/misc/combin/cl_I_factorial_aux.cc | 32 + src/integer/output/Makeflags | 4 + src/integer/output/cl_I_aprint.cc | 17 + src/integer/output/cl_I_bprint.cc | 17 + src/integer/output/cl_I_cprint.cc | 17 + src/integer/output/cl_I_decstring.cc | 25 + src/integer/output/cl_I_dprint.cc | 47 + src/integer/output/cl_I_print.cc | 36 + src/integer/output/cl_I_print_string.cc | 40 + src/integer/random/Makeflags | 4 + src/integer/random/cl_I_random.cc | 34 + src/integer/random/cl_I_trandom.cc | 41 + src/integer/ring/Makeflags | 4 + src/integer/ring/cl_0_ring.cc | 129 + src/integer/ring/cl_I_ring.cc | 156 + src/modinteger/Makeflags | 3 + src/modinteger/cl_MI.cc | 178 + src/modinteger/cl_MI.h | 10 + src/modinteger/cl_MI_cond_composite.cc | 30 + src/modinteger/cl_MI_debug.cc | 31 + src/modinteger/cl_MI_err_comp.cc | 18 + src/modinteger/cl_MI_fix16.h | 71 + src/modinteger/cl_MI_fix29.h | 78 + src/modinteger/cl_MI_fix32.h | 80 + src/modinteger/cl_MI_int.h | 149 + src/modinteger/cl_MI_int32.h | 79 + src/modinteger/cl_MI_lshift.cc | 31 + src/modinteger/cl_MI_montgom.h | 222 + src/modinteger/cl_MI_pow2.h | 144 + src/modinteger/cl_MI_pow2m1.h | 85 + src/modinteger/cl_MI_pow2p1.h | 96 + src/modinteger/cl_MI_rshift.cc | 42 + src/modinteger/cl_MI_std.h | 350 ++ src/modpolynomial/Makeflags | 3 + src/numtheory/Makeflags | 3 + src/numtheory/cl_IF.h | 52 + src/numtheory/cl_IF_millerrabin.cc | 63 + src/numtheory/cl_IF_smallprimes.cc | 668 +++ src/numtheory/cl_IF_trialdiv.cc | 40 + src/numtheory/cl_IF_trialdiv1.cc | 27 + src/numtheory/cl_IF_trialdiv2.cc | 29 + src/numtheory/cl_nt_cornacchia1.cc | 101 + src/numtheory/cl_nt_cornacchia4.cc | 115 + src/numtheory/cl_nt_isprobprime.cc | 55 + src/numtheory/cl_nt_jacobi.cc | 68 + src/numtheory/cl_nt_jacobi_low.cc | 75 + src/numtheory/cl_nt_nextprobprime.cc | 31 + src/numtheory/cl_nt_sqrtmodp.cc | 307 ++ src/polynomial/Makeflags | 3 + src/polynomial/cl_UP.h | 31 + src/polynomial/elem/Makeflags | 5 + src/polynomial/elem/cl_UP.cc | 73 + src/polynomial/elem/cl_UP_GF2.h | 1044 ++++ src/polynomial/elem/cl_UP_MI.h | 471 ++ src/polynomial/elem/cl_UP_gen.h | 451 ++ src/polynomial/elem/cl_UP_named.cc | 73 + src/polynomial/elem/cl_UP_no_ring.cc | 202 + src/polynomial/elem/cl_UP_number.h | 453 ++ src/polynomial/elem/cl_UP_unnamed.cc | 61 + src/polynomial/elem/cl_asm_GF2.cc | 8 + src/polynomial/elem/cl_asm_sparc_GF2.cc | 642 +++ src/polynomial/misc/Makeflags | 4 + src/polynomial/misc/cl_UP_I_hermite.cc | 58 + src/polynomial/misc/cl_UP_I_laguerre.cc | 57 + src/polynomial/misc/cl_UP_I_tchebychev.cc | 56 + src/polynomial/misc/cl_UP_RA_legendre.cc | 60 + src/polynomial/misc/cl_UP_debug.cc | 31 + src/polynomial/misc/cl_UP_deriv.cc | 30 + src/rational/Makeflags | 3 + src/rational/algebraic/Makeflags | 4 + src/rational/algebraic/cl_RA_rootp.cc | 37 + src/rational/algebraic/cl_RA_rootp_I.cc | 37 + src/rational/algebraic/cl_RA_sqrtp.cc | 37 + src/rational/cl_RA.h | 172 + src/rational/division/Makeflags | 4 + src/rational/division/cl_RA_ceil1.cc | 29 + src/rational/division/cl_RA_ceil12.cc | 47 + src/rational/division/cl_RA_ceil2.cc | 35 + src/rational/division/cl_RA_ceil22.cc | 70 + src/rational/division/cl_RA_floor1.cc | 29 + src/rational/division/cl_RA_floor12.cc | 47 + src/rational/division/cl_RA_floor2.cc | 35 + src/rational/division/cl_RA_floor22.cc | 70 + src/rational/division/cl_RA_round1.cc | 29 + src/rational/division/cl_RA_round12.cc | 47 + src/rational/division/cl_RA_round2.cc | 35 + src/rational/division/cl_RA_round22.cc | 70 + src/rational/division/cl_RA_trunc1.cc | 29 + src/rational/division/cl_RA_trunc12.cc | 47 + src/rational/division/cl_RA_trunc2.cc | 35 + src/rational/division/cl_RA_trunc22.cc | 70 + src/rational/elem/Makeflags | 4 + src/rational/elem/cl_RA_compare.cc | 70 + src/rational/elem/cl_RA_denominator.cc | 19 + src/rational/elem/cl_RA_div.cc | 26 + src/rational/elem/cl_RA_equal.cc | 45 + src/rational/elem/cl_RA_from_I_I_div.cc | 27 + src/rational/elem/cl_RA_from_I_posI.cc | 22 + src/rational/elem/cl_RA_from_I_posI1.cc | 15 + src/rational/elem/cl_RA_from_I_posI_div.cc | 26 + src/rational/elem/cl_RA_minus.cc | 110 + src/rational/elem/cl_RA_minus1.cc | 29 + src/rational/elem/cl_RA_minusp.cc | 19 + src/rational/elem/cl_RA_mul.cc | 99 + src/rational/elem/cl_RA_numerator.cc | 19 + src/rational/elem/cl_RA_plus.cc | 99 + src/rational/elem/cl_RA_plus1.cc | 29 + src/rational/elem/cl_RA_plusp.cc | 26 + src/rational/elem/cl_RA_recip.cc | 33 + src/rational/elem/cl_RA_square.cc | 30 + src/rational/elem/cl_RA_uminus.cc | 30 + src/rational/elem/cl_RA_zerop.cc | 19 + src/rational/input/Makeflags | 4 + src/rational/input/cl_RA_from_string.cc | 26 + src/rational/input/cl_RA_read.cc | 153 + src/rational/input/cl_RA_read_stream.cc | 105 + src/rational/input/cl_RA_readparsed.cc | 28 + src/rational/misc/Makeflags | 4 + src/rational/misc/cl_RA_abs.cc | 23 + src/rational/misc/cl_RA_as.cc | 38 + src/rational/misc/cl_RA_class.cc | 22 + src/rational/misc/cl_RA_debug.cc | 30 + src/rational/misc/cl_RA_eqhashcode.cc | 29 + src/rational/misc/cl_RA_expt.cc | 24 + src/rational/misc/cl_RA_expt_I.cc | 27 + src/rational/misc/cl_RA_exptpos.cc | 29 + src/rational/misc/cl_RA_exptpos_I.cc | 29 + src/rational/misc/cl_RA_max.cc | 15 + src/rational/misc/cl_RA_min.cc | 15 + src/rational/misc/cl_RA_signum.cc | 21 + src/rational/output/Makeflags | 4 + src/rational/output/cl_RA_aprint.cc | 17 + src/rational/output/cl_RA_bprint.cc | 17 + src/rational/output/cl_RA_cprint.cc | 17 + src/rational/output/cl_RA_dprint.cc | 62 + src/rational/output/cl_RA_print.cc | 30 + src/rational/ring/Makeflags | 4 + src/rational/ring/cl_RA_ring.cc | 156 + src/rational/transcendental/Makeflags | 4 + src/rational/transcendental/cl_I_logp.cc | 70 + src/rational/transcendental/cl_RA_logp.cc | 103 + src/real/Makeflags | 3 + src/real/algebraic/Makeflags | 4 + src/real/algebraic/cl_RA_sqrt.cc | 24 + src/real/algebraic/cl_R_sqrt.cc | 21 + src/real/cl_R.h | 205 + src/real/conv/Makeflags | 4 + src/real/conv/cl_F_from_R.cc | 42 + src/real/conv/cl_F_from_R_def.cc | 24 + src/real/conv/cl_F_from_R_f.cc | 24 + src/real/conv/cl_R_to_DF.cc | 46 + src/real/conv/cl_R_to_FF.cc | 46 + src/real/conv/cl_R_to_LF.cc | 46 + src/real/conv/cl_R_to_SF.cc | 46 + src/real/conv/cl_R_to_double.cc | 52 + src/real/conv/cl_R_to_float.cc | 52 + src/real/division/Makeflags | 4 + src/real/division/cl_R_ceil1.cc | 17 + src/real/division/cl_R_ceil12.cc | 27 + src/real/division/cl_R_ceil2.cc | 18 + src/real/division/cl_R_ceil22.cc | 31 + src/real/division/cl_R_div_t.h | 22 + src/real/division/cl_R_fceil1.cc | 32 + src/real/division/cl_R_fceil12.cc | 27 + src/real/division/cl_R_fceil2.cc | 62 + src/real/division/cl_R_fceil22.cc | 34 + src/real/division/cl_R_ffloor1.cc | 32 + src/real/division/cl_R_ffloor12.cc | 27 + src/real/division/cl_R_ffloor2.cc | 62 + src/real/division/cl_R_ffloor22.cc | 34 + src/real/division/cl_R_floor1.cc | 17 + src/real/division/cl_R_floor12.cc | 27 + src/real/division/cl_R_floor2.cc | 18 + src/real/division/cl_R_floor22.cc | 31 + src/real/division/cl_R_fround1.cc | 32 + src/real/division/cl_R_fround12.cc | 27 + src/real/division/cl_R_fround2.cc | 62 + src/real/division/cl_R_fround22.cc | 34 + src/real/division/cl_R_ftrunc1.cc | 32 + src/real/division/cl_R_ftrunc12.cc | 27 + src/real/division/cl_R_ftrunc2.cc | 62 + src/real/division/cl_R_ftrunc22.cc | 34 + src/real/division/cl_R_mod.cc | 27 + src/real/division/cl_R_rem.cc | 27 + src/real/division/cl_R_round1.cc | 17 + src/real/division/cl_R_round12.cc | 27 + src/real/division/cl_R_round2.cc | 18 + src/real/division/cl_R_round22.cc | 31 + src/real/division/cl_R_trunc1.cc | 17 + src/real/division/cl_R_trunc12.cc | 27 + src/real/division/cl_R_trunc2.cc | 18 + src/real/division/cl_R_trunc22.cc | 31 + src/real/elem/Makeflags | 4 + src/real/elem/cl_R_compare.cc | 44 + src/real/elem/cl_R_div.cc | 97 + src/real/elem/cl_R_equal.cc | 52 + src/real/elem/cl_R_minus.cc | 23 + src/real/elem/cl_R_minus1.cc | 17 + src/real/elem/cl_R_minusp.cc | 29 + src/real/elem/cl_R_mul.cc | 92 + src/real/elem/cl_R_plus.cc | 23 + src/real/elem/cl_R_plus1.cc | 17 + src/real/elem/cl_R_plusp.cc | 20 + src/real/elem/cl_R_recip.cc | 17 + src/real/elem/cl_R_square.cc | 28 + src/real/elem/cl_R_uminus.cc | 29 + src/real/elem/cl_R_zerop.cc | 29 + src/real/format-output/Makeflags | 4 + src/real/format-output/TODO-format | 222 + src/real/format-output/cl_fmt_cardinal.cc | 134 + src/real/format-output/cl_fmt_floatstring.cc | 254 + src/real/format-output/cl_fmt_integer.cc | 65 + src/real/format-output/cl_fmt_newroman.cc | 54 + src/real/format-output/cl_fmt_oldroman.cc | 44 + src/real/format-output/cl_fmt_ordinal.cc | 83 + src/real/format-output/cl_fmt_paddedstring.cc | 26 + src/real/format-output/cl_fmt_scaleexp.cc | 114 + src/real/format-output/cl_fmt_tens.cc | 23 + src/real/format-output/cl_format.h | 74 + src/real/input/Makeflags | 4 + src/real/input/cl_R_from_string.cc | 26 + src/real/input/cl_R_read.cc | 266 + src/real/input/cl_R_read_stream.cc | 104 + src/real/misc/Makeflags | 4 + src/real/misc/cl_R_abs.cc | 20 + src/real/misc/cl_R_as.cc | 42 + src/real/misc/cl_R_contagion.cc | 43 + src/real/misc/cl_R_debug.cc | 25 + src/real/misc/cl_R_eqhashcode.cc | 27 + src/real/misc/cl_R_expt.cc | 54 + src/real/misc/cl_R_expt_I.cc | 56 + src/real/misc/cl_R_max.cc | 15 + src/real/misc/cl_R_min.cc | 15 + src/real/misc/cl_R_rational.cc | 15 + src/real/misc/cl_R_rationalize.cc | 113 + src/real/misc/cl_R_signum.cc | 26 + src/real/output/Makeflags | 4 + src/real/output/cl_R_aprint.cc | 17 + src/real/output/cl_R_bprint.cc | 17 + src/real/output/cl_R_cprint.cc | 28 + src/real/random/Makeflags | 4 + src/real/random/cl_R_random.cc | 37 + src/real/ring/Makeflags | 4 + src/real/ring/cl_R_ring.cc | 160 + src/real/transcendental/Makeflags | 4 + src/real/transcendental/cl_R_atan.cc | 17 + src/real/transcendental/cl_R_atan2.cc | 84 + src/real/transcendental/cl_R_cos.cc | 30 + src/real/transcendental/cl_R_cosh.cc | 30 + src/real/transcendental/cl_R_coshsinh.cc | 30 + src/real/transcendental/cl_R_cossin.cc | 30 + src/real/transcendental/cl_R_exp.cc | 30 + src/real/transcendental/cl_R_ln.cc | 30 + src/real/transcendental/cl_R_log.cc | 51 + src/real/transcendental/cl_R_sin.cc | 30 + src/real/transcendental/cl_R_sinh.cc | 30 + src/real/transcendental/cl_R_tan.cc | 19 + src/real/transcendental/cl_R_tanh.cc | 19 + src/timing/Makeflags | 3 + src/timing/cl_t_c1.cc | 29 + src/timing/cl_t_c2.cc | 57 + src/timing/cl_t_config.h.in | 45 + src/timing/cl_t_current.cc | 58 + src/timing/cl_t_current2.cc | 66 + src/timing/cl_t_d.cc | 15 + src/timing/cl_t_dec.cc | 21 + src/timing/cl_t_inc.cc | 21 + src/timing/cl_t_minus.cc | 24 + src/timing/cl_t_report.cc | 43 + src/timing/cl_t_td_minus.cc | 24 + src/timing/cl_t_td_plus.cc | 21 + src/vector/Makeflags | 3 + src/vector/cl_GV_I.cc | 492 ++ src/vector/cl_GV_I_copy.cc | 19 + src/vector/cl_GV_I_debug.cc | 24 + src/vector/cl_GV_io.h | 20 + src/vector/cl_GV_number.cc | 113 + src/vector/cl_GV_number_copy.cc | 19 + src/vector/cl_GV_number_debug.cc | 38 + src/vector/cl_SV_copy.cc | 25 + src/vector/cl_SV_io.h | 20 + src/vector/cl_SV_number.cc | 55 + src/vector/cl_SV_number_debug.cc | 33 + src/vector/cl_SV_ringelt.cc | 55 + src/vector/cl_SV_ringelt_debug.cc | 25 + src/vector/output/Makeflags | 4 + src/vector/output/cl_GV_number_aprint.cc | 39 + src/vector/output/cl_SV_aprint.cc | 35 + src/vector/output/cl_SV_number_aprint.cc | 38 + tests/.gdbinit | 6 + tests/FILES | 12 + tests/Makefile.in | 186 + tests/exam.cc | 47 + tests/exam.h | 119 + tests/exam_DF.cc | 7 + tests/exam_DF_div.cc | 457 ++ tests/exam_DF_floor.cc | 459 ++ tests/exam_DF_minus.cc | 457 ++ tests/exam_DF_mul.cc | 457 ++ tests/exam_DF_plus.cc | 457 ++ tests/exam_FF.cc | 7 + tests/exam_FF_div.cc | 424 ++ tests/exam_FF_floor.cc | 423 ++ tests/exam_FF_minus.cc | 457 ++ tests/exam_FF_mul.cc | 421 ++ tests/exam_FF_plus.cc | 457 ++ tests/exam_I.cc | 7 + tests/exam_I_div.cc | 299 ++ tests/exam_I_floor.cc | 295 ++ tests/exam_I_gcd.cc | 119 + tests/exam_I_minus.cc | 295 ++ tests/exam_I_mul.cc | 288 + tests/exam_I_plus.cc | 295 ++ tests/exam_I_sqrtp.cc | 24 + tests/exam_LF.cc | 7 + tests/exam_LF_div.cc | 457 ++ tests/exam_LF_floor.cc | 459 ++ tests/exam_LF_minus.cc | 457 ++ tests/exam_LF_mul.cc | 457 ++ tests/exam_LF_plus.cc | 457 ++ tests/exam_RA.cc | 7 + tests/exam_RA_div.cc | 142 + tests/exam_RA_floor.cc | 153 + tests/exam_RA_minus.cc | 169 + tests/exam_RA_mul.cc | 151 + tests/exam_RA_plus.cc | 169 + tests/exam_SF.cc | 7 + tests/exam_SF_div.cc | 421 ++ tests/exam_SF_floor.cc | 420 ++ tests/exam_SF_minus.cc | 457 ++ tests/exam_SF_mul.cc | 424 ++ tests/exam_SF_plus.cc | 457 ++ tests/main.cc | 110 + tests/test.h | 76 + tests/test_I.cc | 100 + tests/test_I.h | 4 + tests/test_I_GV.cc | 25 + tests/test_I_abs.cc | 13 + tests/test_I_ash.cc | 36 + tests/test_I_boole.cc | 28 + tests/test_I_compare.cc | 21 + tests/test_I_div.cc | 67 + tests/test_I_dpb.cc | 17 + tests/test_I_dpf.cc | 17 + tests/test_I_evenp.cc | 14 + tests/test_I_gcd.cc | 27 + tests/test_I_ilength.cc | 40 + tests/test_I_isqrt.cc | 29 + tests/test_I_ldb.cc | 15 + tests/test_I_ldbtest.cc | 15 + tests/test_I_logand.cc | 23 + tests/test_I_logandc1.cc | 14 + tests/test_I_logandc2.cc | 14 + tests/test_I_logbitp.cc | 26 + tests/test_I_logcount.cc | 26 + tests/test_I_logeqv.cc | 14 + tests/test_I_logior.cc | 24 + tests/test_I_lognand.cc | 14 + tests/test_I_lognor.cc | 14 + tests/test_I_lognot.cc | 18 + tests/test_I_logorc1.cc | 14 + tests/test_I_logorc2.cc | 14 + tests/test_I_logtest.cc | 33 + tests/test_I_logxor.cc | 29 + tests/test_I_minus.cc | 27 + tests/test_I_minus1.cc | 13 + tests/test_I_mkf.cc | 15 + tests/test_I_mul.cc | 41 + tests/test_I_oddp.cc | 14 + tests/test_I_ord2.cc | 18 + tests/test_I_plus.cc | 26 + tests/test_I_plus1.cc | 13 + tests/test_I_power2p.cc | 20 + tests/test_I_sqrtp.cc | 33 + tests/test_I_xgcd.cc | 31 + tests/test_MI.cc | 27 + tests/test_MI.h | 5 + tests/test_MI_canonhom.cc | 15 + tests/test_MI_div.cc | 19 + tests/test_MI_expt.cc | 52 + tests/test_MI_minus.cc | 35 + tests/test_MI_mul.cc | 54 + tests/test_MI_plus.cc | 33 + tests/test_MI_recip.cc | 18 + tests/test_nt.cc | 14 + tests/test_nt.h | 5 + tests/test_nt_jacobi.cc | 56 + tests/tests.cc | 35 + tests/timeLFRAmul.cc | 44 + tests/timeLFatan-compare.cc | 45 + tests/timeLFatan.cc | 46 + tests/timeLFatanh-compare.cc | 47 + tests/timeLFatanh.cc | 43 + tests/timeLFcos-compare.cc | 43 + tests/timeLFcos.cc | 37 + tests/timeLFcosh.cc | 47 + tests/timeLFexp-compare.cc | 45 + tests/timeLFexp.cc | 47 + tests/timeLFln-compare.cc | 44 + tests/timeLFln.cc | 47 + tests/timeLFsin-compare.cc | 52 + tests/timeLFsin.cc | 46 + tests/timeLFsinh.cc | 52 + tests/timeLFsqrt.cc | 31 + tests/timeMImisc5.cc | 58 + tests/timeMIpow2div.cc | 27 + tests/timeMIpow2recip.cc | 26 + tests/timeRALFdiv.cc | 44 + tests/timeRAtoLF.cc | 43 + tests/timeUPMImul.cc | 52 + tests/timecatalan.cc | 61 + tests/timediv.cc | 35 + tests/timediv2adic-compare.cc | 60 + tests/timediv2adic.cc | 46 + tests/timeeuler.cc | 77 + tests/timeexp1.cc | 27 + tests/timefact.cc | 24 + tests/timegcd.cc | 29 + tests/timemul-compare.cc | 50 + tests/timemul.cc | 28 + tests/timepi.cc | 57 + tests/timepi.out2-i486 | 6 + tests/timepi.out2-i586 | 6 + tests/timeprint-compare.cc | 44 + tests/timeprint.cc | 34 + tests/timerecip2adic-compare.cc | 54 + tests/timerecip2adic.cc | 35 + tests/timesqrt.cc | 26 + tests/timesqrtmodp.cc | 77 + tests/timesquare.cc | 34 + tests/timezeta3.cc | 47 + 1460 files changed, 183104 insertions(+) create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 FILES create mode 100644 INSTALL create mode 100644 INSTALL.generic create mode 100644 Makefile.devel create mode 100644 Makefile.in create mode 100644 NEWS create mode 100644 README create mode 100644 TODO create mode 100644 TODO-subclass create mode 100644 TODO-verylong create mode 100644 autoconf/acgeneral.m4 create mode 100644 autoconf/aclocal.m4 create mode 100644 autoconf/acspecific.m4 create mode 100755 autoconf/autoconf create mode 100644 autoconf/autoconf.m4 create mode 100755 autoconf/config.guess create mode 100755 autoconf/config.sub create mode 100644 autoconf/floatparam.c create mode 100644 autoconf/intparam.c create mode 100755 autoconf/ltconfig create mode 100644 autoconf/ltmain.sh create mode 100644 benchmarks/Makefile.in create mode 100644 benchmarks/README create mode 100644 benchmarks/bench2.txt create mode 100644 benchmarks/timebench1.LiDIA.cc create mode 100644 benchmarks/timebench1.cc create mode 100644 benchmarks/timebench1.gp create mode 100644 benchmarks/timebench1.lsp create mode 100644 benchmarks/timebench2.results create mode 100644 benchmarks/timebench2.sh create mode 100644 benchmarks/timebench2a.LiDIA.cc create mode 100644 benchmarks/timebench2a.cc create mode 100644 benchmarks/timebench2a.gp create mode 100644 benchmarks/timebench2ap.cc create mode 100644 benchmarks/timebench2ap.gp create mode 100644 benchmarks/timebench2b.LiDIA.cc create mode 100644 benchmarks/timebench2b.cc create mode 100644 benchmarks/timebench2b.gp create mode 100644 benchmarks/timebench2c.gp create mode 100644 benchmarks/timebench2d.gp create mode 100755 configure create mode 100644 configure.in create mode 100644 doc/Makefile.devel create mode 100644 doc/Makefile.in create mode 100644 doc/addnodes.el create mode 100644 doc/cln.dvi create mode 100644 doc/cln.html create mode 100644 doc/cln.info create mode 100644 doc/cln.ps create mode 100644 doc/cln.tex create mode 100644 doc/cln.texi create mode 100644 doc/cln_1.html create mode 100644 doc/cln_10.html create mode 100644 doc/cln_11.html create mode 100644 doc/cln_12.html create mode 100644 doc/cln_13.html create mode 100644 doc/cln_2.html create mode 100644 doc/cln_3.html create mode 100644 doc/cln_4.html create mode 100644 doc/cln_5.html create mode 100644 doc/cln_6.html create mode 100644 doc/cln_7.html create mode 100644 doc/cln_8.html create mode 100644 doc/cln_9.html create mode 100644 doc/cln_toc.html create mode 100644 doc/polynomial/Makefile.devel create mode 100644 doc/polynomial/README create mode 100644 doc/polynomial/diag_rational.dvi create mode 100644 doc/polynomial/diag_rational.lyx create mode 100644 doc/polynomial/diag_rational.ps create mode 100644 doc/polynomial/diag_rational.tex create mode 100644 doc/polynomial/hermite.dvi create mode 100644 doc/polynomial/hermite.lyx create mode 100644 doc/polynomial/hermite.ps create mode 100644 doc/polynomial/hermite.tex create mode 100644 doc/polynomial/laguerre.dvi create mode 100644 doc/polynomial/laguerre.lyx create mode 100644 doc/polynomial/laguerre.ps create mode 100644 doc/polynomial/laguerre.tex create mode 100644 doc/polynomial/legendre.dvi create mode 100644 doc/polynomial/legendre.lyx create mode 100644 doc/polynomial/legendre.ps create mode 100644 doc/polynomial/legendre.tex create mode 100644 doc/polynomial/tchebychev.dvi create mode 100644 doc/polynomial/tchebychev.lyx create mode 100644 doc/polynomial/tchebychev.ps create mode 100644 doc/polynomial/tchebychev.tex create mode 100644 doc/ratseries/README create mode 100644 doc/ratseries/paper/Makefile.devel create mode 100644 doc/ratseries/paper/README create mode 100644 doc/ratseries/paper/acm.bst create mode 100644 doc/ratseries/paper/acmconf.sty create mode 100644 doc/ratseries/paper/binsplit.bib create mode 100644 doc/ratseries/paper/binsplit.dvi create mode 100644 doc/ratseries/paper/binsplit.ps create mode 100644 doc/ratseries/paper/binsplit.tex create mode 100644 doc/ratseries/slides/Makefile.devel create mode 100644 doc/ratseries/slides/epsf.tex create mode 100644 doc/ratseries/slides/fig2.cln create mode 100644 doc/ratseries/slides/fig2.eps create mode 100644 doc/ratseries/slides/fig2.lidia create mode 100644 doc/ratseries/slides/fig2.maple create mode 100644 doc/ratseries/slides/fig2.pari create mode 100644 doc/ratseries/slides/fig2log.cln create mode 100644 doc/ratseries/slides/fig2log.lidia create mode 100644 doc/ratseries/slides/fig2log.maple create mode 100644 doc/ratseries/slides/fig2log.pari create mode 100644 doc/ratseries/slides/gnuplot-command create mode 100644 doc/ratseries/slides/slide0.dvi create mode 100644 doc/ratseries/slides/slide0.log create mode 100644 doc/ratseries/slides/slide0.ps create mode 100644 doc/ratseries/slides/slide0.tex create mode 100644 doc/ratseries/slides/slide1.dvi create mode 100644 doc/ratseries/slides/slide1.log create mode 100644 doc/ratseries/slides/slide1.ps create mode 100644 doc/ratseries/slides/slide1.tex create mode 100644 doc/ratseries/slides/slide2.dvi create mode 100644 doc/ratseries/slides/slide2.log create mode 100644 doc/ratseries/slides/slide2.ps create mode 100644 doc/ratseries/slides/slide2.tex create mode 100644 doc/ratseries/slides/slide3.dvi create mode 100644 doc/ratseries/slides/slide3.log create mode 100644 doc/ratseries/slides/slide3.ps create mode 100644 doc/ratseries/slides/slide3.tex create mode 100644 doc/ratseries/slides/slide4.dvi create mode 100644 doc/ratseries/slides/slide4.log create mode 100644 doc/ratseries/slides/slide4.ps create mode 100644 doc/ratseries/slides/slide4.tex create mode 100644 doc/ratseries/slides/slide5.dvi create mode 100644 doc/ratseries/slides/slide5.log create mode 100644 doc/ratseries/slides/slide5.ps create mode 100644 doc/ratseries/slides/slide5.tex create mode 100644 doc/ratseries/slides/slide6.dvi create mode 100644 doc/ratseries/slides/slide6.log create mode 100644 doc/ratseries/slides/slide6.ps create mode 100644 doc/ratseries/slides/slide6.tex create mode 100644 doc/texinfo.tex create mode 100644 examples/Makefile.in create mode 100644 examples/atan_recip.cc create mode 100644 examples/atanh_recip.cc create mode 100644 examples/contfrac.cc create mode 100644 examples/e.cc create mode 100644 examples/fibonacci.cc create mode 100644 examples/legendre.cc create mode 100644 examples/lucaslehmer.cc create mode 100644 examples/nextprime.cc create mode 100644 examples/perfnum.cc create mode 100644 include/cl_GV.h create mode 100644 include/cl_GV_complex.h create mode 100644 include/cl_GV_integer.h create mode 100644 include/cl_GV_modinteger.h create mode 100644 include/cl_GV_number.h create mode 100644 include/cl_GV_rational.h create mode 100644 include/cl_GV_real.h create mode 100644 include/cl_SV.h create mode 100644 include/cl_SV_complex.h create mode 100644 include/cl_SV_integer.h create mode 100644 include/cl_SV_number.h create mode 100644 include/cl_SV_rational.h create mode 100644 include/cl_SV_real.h create mode 100644 include/cl_SV_ringelt.h create mode 100644 include/cl_V.h create mode 100644 include/cl_abort.h create mode 100644 include/cl_complex.h create mode 100644 include/cl_complex_class.h create mode 100644 include/cl_complex_io.h create mode 100644 include/cl_complex_ring.h create mode 100644 include/cl_condition.h create mode 100644 include/cl_config.h.in create mode 100644 include/cl_dfloat.h create mode 100644 include/cl_dfloat_class.h create mode 100644 include/cl_dfloat_io.h create mode 100644 include/cl_ffloat.h create mode 100644 include/cl_ffloat_class.h create mode 100644 include/cl_ffloat_io.h create mode 100644 include/cl_float.h create mode 100644 include/cl_float_class.h create mode 100644 include/cl_float_io.h create mode 100644 include/cl_floatformat.h create mode 100644 include/cl_input.h create mode 100644 include/cl_integer.h create mode 100644 include/cl_integer_class.h create mode 100644 include/cl_integer_io.h create mode 100644 include/cl_integer_ring.h create mode 100644 include/cl_io.h create mode 100644 include/cl_lfloat.h create mode 100644 include/cl_lfloat_class.h create mode 100644 include/cl_lfloat_io.h create mode 100644 include/cl_malloc.h create mode 100644 include/cl_modinteger.h create mode 100644 include/cl_modules.h create mode 100644 include/cl_null_ring.h create mode 100644 include/cl_number.h create mode 100644 include/cl_number_io.h create mode 100644 include/cl_numtheory.h create mode 100644 include/cl_object.h create mode 100644 include/cl_output.h create mode 100644 include/cl_proplist.h create mode 100644 include/cl_random.h create mode 100644 include/cl_rational.h create mode 100644 include/cl_rational_class.h create mode 100644 include/cl_rational_io.h create mode 100644 include/cl_rational_ring.h create mode 100644 include/cl_real.h create mode 100644 include/cl_real_class.h create mode 100644 include/cl_real_io.h create mode 100644 include/cl_real_ring.h create mode 100644 include/cl_ring.h create mode 100644 include/cl_sfloat.h create mode 100644 include/cl_sfloat_class.h create mode 100644 include/cl_sfloat_io.h create mode 100644 include/cl_string.h create mode 100644 include/cl_symbol.h create mode 100644 include/cl_timing.h create mode 100644 include/cl_types.h create mode 100644 include/cl_univpoly.h create mode 100644 include/cl_univpoly_complex.h create mode 100644 include/cl_univpoly_integer.h create mode 100644 include/cl_univpoly_modint.h create mode 100644 include/cl_univpoly_rational.h create mode 100644 include/cl_univpoly_real.h create mode 100644 include/cln.h create mode 100644 lidia-interface/LiDIA-patch1 create mode 100644 lidia-interface/LiDIA-patch2 create mode 100644 lidia-interface/README create mode 100644 lidia-interface/TAR-FILE-LIST create mode 100644 lidia-interface/bigint.o.i386-linux create mode 100644 lidia-interface/bigint.o.needs create mode 100644 lidia-interface/bigint.o.undef create mode 100644 lidia-interface/src/interfaces/integers/cln/bigint.c create mode 100644 lidia-interface/src/interfaces/integers/cln/bigint_def.h create mode 100644 lidia-interface/src/interfaces/integers/cln/makefile create mode 100644 lidia-interface/src/kernel/integers/cln/README create mode 100644 lidia-interface/src/kernel/integers/cln/cln/README.LiDIA create mode 100755 lidia-interface/src/kernel/integers/cln/makefile create mode 100644 src/Makefile.devel create mode 100644 src/Makefile.in create mode 100644 src/Makeflags create mode 100644 src/Makerules.devel create mode 100644 src/TUNING create mode 100644 src/base/Makeflags create mode 100644 src/base/cl_N.h create mode 100644 src/base/cl_N_err_d0.cc create mode 100644 src/base/cl_abort.cc create mode 100644 src/base/cl_alloca.cc create mode 100644 src/base/cl_alloca.h create mode 100644 src/base/cl_as_err.cc create mode 100644 src/base/cl_base_config.h.in create mode 100644 src/base/cl_condition.cc create mode 100644 src/base/cl_debug.cc create mode 100644 src/base/cl_debugout.cc create mode 100644 src/base/cl_free.cc create mode 100644 src/base/cl_gmpconfig.h.in create mode 100644 src/base/cl_immclasses.cc create mode 100644 src/base/cl_iterator.h create mode 100644 src/base/cl_low.h create mode 100644 src/base/cl_macros.h create mode 100644 src/base/cl_malloc.cc create mode 100644 src/base/cl_notreached.cc create mode 100644 src/base/cl_offsetof.h create mode 100644 src/base/cl_sysdep.h create mode 100644 src/base/cl_xmacros.h create mode 100644 src/base/digit/Makeflags create mode 100644 src/base/digit/cl_2D.h create mode 100644 src/base/digit/cl_2D_div.cc create mode 100644 src/base/digit/cl_2D_exptpos.cc create mode 100644 src/base/digit/cl_D.h create mode 100644 src/base/digitseq/Makeflags create mode 100644 src/base/digitseq/cl_2DS.h create mode 100644 src/base/digitseq/cl_2DS_div.cc create mode 100644 src/base/digitseq/cl_2DS_recip.cc create mode 100644 src/base/digitseq/cl_DS.h create mode 100644 src/base/digitseq/cl_DS_div.cc create mode 100644 src/base/digitseq/cl_DS_endian.h create mode 100644 src/base/digitseq/cl_DS_mul.cc create mode 100644 src/base/digitseq/cl_DS_mul_fftc.h create mode 100644 src/base/digitseq/cl_DS_mul_fftcs.h create mode 100644 src/base/digitseq/cl_DS_mul_fftm.h create mode 100644 src/base/digitseq/cl_DS_mul_fftp.h create mode 100644 src/base/digitseq/cl_DS_mul_fftp3.h create mode 100644 src/base/digitseq/cl_DS_mul_fftp3m.h create mode 100644 src/base/digitseq/cl_DS_mul_fftr.h create mode 100644 src/base/digitseq/cl_DS_mul_kara.h create mode 100644 src/base/digitseq/cl_DS_mul_kara_sqr.h create mode 100644 src/base/digitseq/cl_DS_mul_nuss.h create mode 100644 src/base/digitseq/cl_DS_random.cc create mode 100644 src/base/digitseq/cl_DS_recip.cc create mode 100644 src/base/digitseq/cl_DS_recipsqrt.cc create mode 100644 src/base/digitseq/cl_DS_sqrt.cc create mode 100644 src/base/digitseq/cl_DS_trandom.cc create mode 100644 src/base/digitseq/cl_asm.h create mode 100644 src/base/digitseq/cl_asm_.cc create mode 100644 src/base/digitseq/cl_asm_arm.h create mode 100644 src/base/digitseq/cl_asm_arm_.cc create mode 100644 src/base/digitseq/cl_asm_hppa.h create mode 100644 src/base/digitseq/cl_asm_hppa_.cc create mode 100644 src/base/digitseq/cl_asm_i386.h create mode 100644 src/base/digitseq/cl_asm_i386_.cc create mode 100644 src/base/digitseq/cl_asm_m68k.h create mode 100644 src/base/digitseq/cl_asm_m68k_.cc create mode 100644 src/base/digitseq/cl_asm_mips.h create mode 100644 src/base/digitseq/cl_asm_mips_.cc create mode 100644 src/base/digitseq/cl_asm_sparc.h create mode 100644 src/base/digitseq/cl_asm_sparc64.h create mode 100644 src/base/digitseq/cl_asm_sparc64_.cc create mode 100644 src/base/digitseq/cl_asm_sparc_.cc create mode 100755 src/base/digitseq/digit_header create mode 100644 src/base/hash/Makeflags create mode 100644 src/base/hash/cl_hash.h create mode 100644 src/base/hash/cl_hash1.h create mode 100644 src/base/hash/cl_hash1weak.h create mode 100644 src/base/hash/cl_hash2.h create mode 100644 src/base/hash/cl_hash2weak.h create mode 100644 src/base/hash/cl_hashset.h create mode 100644 src/base/hash/cl_hashuniq.h create mode 100644 src/base/hash/cl_hashuniqweak.h create mode 100644 src/base/hash/cl_rcpointer2_hashweak_rcpointer.cc create mode 100644 src/base/hash/cl_rcpointer2_hashweak_rcpointer.h create mode 100644 src/base/hash/cl_rcpointer_hashweak_rcpointer.cc create mode 100644 src/base/hash/cl_rcpointer_hashweak_rcpointer.h create mode 100644 src/base/input/Makeflags create mode 100644 src/base/input/cl_read_err_bad.cc create mode 100644 src/base/input/cl_read_err_eof.cc create mode 100644 src/base/input/cl_read_err_junk.cc create mode 100644 src/base/low/Makeflags create mode 100644 src/base/low/cl_low_div.cc create mode 100644 src/base/low/cl_low_isqrt.cc create mode 100644 src/base/low/cl_low_isqrt2.cc create mode 100644 src/base/low/cl_low_mul.cc create mode 100644 src/base/output/Makeflags create mode 100644 src/base/output/cl_output_dec.cc create mode 100644 src/base/output/cl_output_hex.cc create mode 100644 src/base/output/cl_prin_globals.cc create mode 100644 src/base/proplist/Makeflags create mode 100644 src/base/proplist/cl_pl_add.cc create mode 100644 src/base/proplist/cl_pl_d.cc create mode 100644 src/base/proplist/cl_pl_get.cc create mode 100644 src/base/random/Makeflags create mode 100644 src/base/random/cl_UL_random.cc create mode 100644 src/base/random/cl_random_def.cc create mode 100644 src/base/random/cl_random_from.cc create mode 100644 src/base/random/cl_random_impl.h create mode 100644 src/base/ring/Makeflags create mode 100644 src/base/ring/cl_no_ring.cc create mode 100644 src/base/ring/cl_ring_debug.cc create mode 100644 src/base/string/Makeflags create mode 100644 src/base/string/cl_spushstring.h create mode 100644 src/base/string/cl_spushstring_append.cc create mode 100644 src/base/string/cl_spushstring_push.cc create mode 100644 src/base/string/cl_sstring.cc create mode 100644 src/base/string/cl_sstring.h create mode 100644 src/base/string/cl_st_c2.cc create mode 100644 src/base/string/cl_st_concat1.cc create mode 100644 src/base/string/cl_st_concat2.cc create mode 100644 src/base/string/cl_st_concat3.cc create mode 100644 src/base/string/cl_st_debug.cc create mode 100644 src/base/string/cl_st_hashcode.cc create mode 100644 src/base/string/cl_st_make0.cc create mode 100644 src/base/string/cl_st_make1.cc create mode 100644 src/base/string/cl_st_make2.cc create mode 100644 src/base/string/cl_st_null.cc create mode 100644 src/base/string/input/Makeflags create mode 100644 src/base/string/input/cl_st_get1.cc create mode 100644 src/base/string/input/cl_st_get2.cc create mode 100644 src/base/string/input/cl_st_getline1.cc create mode 100644 src/base/string/input/cl_st_getline2.cc create mode 100644 src/base/string/input/cl_st_gettoken.cc create mode 100644 src/base/string/misc/Makeflags create mode 100644 src/base/string/misc/cl_st_class.cc create mode 100644 src/base/string/output/Makeflags create mode 100644 src/base/string/output/cl_st_print.cc create mode 100644 src/base/symbol/Makeflags create mode 100644 src/base/symbol/cl_sy_hashcode.cc create mode 100644 src/base/symbol/cl_symbol.cc create mode 100644 src/complex/Makeflags create mode 100644 src/complex/algebraic/Makeflags create mode 100644 src/complex/algebraic/cl_C_abs.cc create mode 100644 src/complex/algebraic/cl_C_abs_aux.cc create mode 100644 src/complex/algebraic/cl_C_signum.cc create mode 100644 src/complex/algebraic/cl_C_sqrt.cc create mode 100644 src/complex/algebraic/cl_DF_hypot.cc create mode 100644 src/complex/algebraic/cl_FF_hypot.cc create mode 100644 src/complex/algebraic/cl_LF_hypot.cc create mode 100644 src/complex/algebraic/cl_R_hypot.cc create mode 100644 src/complex/algebraic/cl_SF_hypot.cc create mode 100644 src/complex/cl_C.h create mode 100644 src/complex/elem/Makeflags create mode 100644 src/complex/elem/cl_C_equal.cc create mode 100644 src/complex/elem/cl_C_from_R_R_complex.cc create mode 100644 src/complex/elem/cl_C_from_R_R_complex1.cc create mode 100644 src/complex/elem/cl_C_imagpart.cc create mode 100644 src/complex/elem/cl_C_minus.cc create mode 100644 src/complex/elem/cl_C_minus1.cc create mode 100644 src/complex/elem/cl_C_mul.cc create mode 100644 src/complex/elem/cl_C_plus.cc create mode 100644 src/complex/elem/cl_C_plus1.cc create mode 100644 src/complex/elem/cl_C_realpart.cc create mode 100644 src/complex/elem/cl_C_square.cc create mode 100644 src/complex/elem/cl_C_uminus.cc create mode 100644 src/complex/elem/cl_C_zerop.cc create mode 100644 src/complex/elem/division/Makeflags create mode 100644 src/complex/elem/division/cl_C_DF_recip.cc create mode 100644 src/complex/elem/division/cl_C_FF_recip.cc create mode 100644 src/complex/elem/division/cl_C_LF_recip.cc create mode 100644 src/complex/elem/division/cl_C_SF_recip.cc create mode 100644 src/complex/elem/division/cl_C_div.cc create mode 100644 src/complex/elem/division/cl_C_recip.cc create mode 100644 src/complex/input/Makeflags create mode 100644 src/complex/input/cl_N_from_string.cc create mode 100644 src/complex/input/cl_N_read.cc create mode 100644 src/complex/input/cl_N_read_stream.cc create mode 100644 src/complex/misc/Makeflags create mode 100644 src/complex/misc/cl_C_class.cc create mode 100644 src/complex/misc/cl_C_conjugate.cc create mode 100644 src/complex/misc/cl_C_debug.cc create mode 100644 src/complex/misc/cl_C_eqhashcode.cc create mode 100644 src/complex/misc/cl_C_expt.cc create mode 100644 src/complex/misc/cl_C_expt_I.cc create mode 100644 src/complex/misc/cl_N_as.cc create mode 100644 src/complex/output/Makeflags create mode 100644 src/complex/output/cl_N_aprint.cc create mode 100644 src/complex/output/cl_N_bprint.cc create mode 100644 src/complex/ring/Makeflags create mode 100644 src/complex/ring/cl_C_ring.cc create mode 100644 src/complex/transcendental/Makeflags create mode 100644 src/complex/transcendental/cl_C_acos.cc create mode 100644 src/complex/transcendental/cl_C_acosh.cc create mode 100644 src/complex/transcendental/cl_C_asin.cc create mode 100644 src/complex/transcendental/cl_C_asinh.cc create mode 100644 src/complex/transcendental/cl_C_asinh_aux.cc create mode 100644 src/complex/transcendental/cl_C_atan.cc create mode 100644 src/complex/transcendental/cl_C_atanh.cc create mode 100644 src/complex/transcendental/cl_C_atanh_aux.cc create mode 100644 src/complex/transcendental/cl_C_cis.cc create mode 100644 src/complex/transcendental/cl_C_cos.cc create mode 100644 src/complex/transcendental/cl_C_cosh.cc create mode 100644 src/complex/transcendental/cl_C_exp.cc create mode 100644 src/complex/transcendental/cl_C_expt_C.cc create mode 100644 src/complex/transcendental/cl_C_log.cc create mode 100644 src/complex/transcendental/cl_C_log2.cc create mode 100644 src/complex/transcendental/cl_C_phase.cc create mode 100644 src/complex/transcendental/cl_C_sin.cc create mode 100644 src/complex/transcendental/cl_C_sinh.cc create mode 100644 src/complex/transcendental/cl_C_tan.cc create mode 100644 src/complex/transcendental/cl_C_tanh.cc create mode 100644 src/complex/transcendental/cl_R_cis.cc create mode 100644 src/float/Makeflags create mode 100644 src/float/algebraic/Makeflags create mode 100644 src/float/algebraic/cl_F_sqrt.cc create mode 100644 src/float/base/Makeflags create mode 100644 src/float/base/cl_F_err_nan.cc create mode 100644 src/float/base/cl_F_err_ov.cc create mode 100644 src/float/base/cl_F_err_un.cc create mode 100644 src/float/base/cl_F_globals.cc create mode 100644 src/float/base/cl_ieee.cc create mode 100644 src/float/base/cl_ieee.h create mode 100644 src/float/cl_F.h create mode 100644 src/float/cl_float_config.h.in create mode 100644 src/float/conv/Makeflags create mode 100644 src/float/conv/cl_DF_to_FF.cc create mode 100644 src/float/conv/cl_DF_to_LF.cc create mode 100644 src/float/conv/cl_DF_to_SF.cc create mode 100644 src/float/conv/cl_DF_to_double.cc create mode 100644 src/float/conv/cl_DF_to_float.cc create mode 100644 src/float/conv/cl_FF_to_DF.cc create mode 100644 src/float/conv/cl_FF_to_LF.cc create mode 100644 src/float/conv/cl_FF_to_SF.cc create mode 100644 src/float/conv/cl_FF_to_double.cc create mode 100644 src/float/conv/cl_FF_to_float.cc create mode 100644 src/float/conv/cl_F_from_F.cc create mode 100644 src/float/conv/cl_F_from_F_f.cc create mode 100644 src/float/conv/cl_F_from_I.cc create mode 100644 src/float/conv/cl_F_from_I_def.cc create mode 100644 src/float/conv/cl_F_from_I_f.cc create mode 100644 src/float/conv/cl_F_from_RA.cc create mode 100644 src/float/conv/cl_F_from_RA_def.cc create mode 100644 src/float/conv/cl_F_from_RA_f.cc create mode 100644 src/float/conv/cl_F_to_DF.cc create mode 100644 src/float/conv/cl_F_to_FF.cc create mode 100644 src/float/conv/cl_F_to_LF.cc create mode 100644 src/float/conv/cl_F_to_SF.cc create mode 100644 src/float/conv/cl_F_to_double.cc create mode 100644 src/float/conv/cl_F_to_float.cc create mode 100644 src/float/conv/cl_LF_to_DF.cc create mode 100644 src/float/conv/cl_LF_to_FF.cc create mode 100644 src/float/conv/cl_LF_to_SF.cc create mode 100644 src/float/conv/cl_LF_to_double.cc create mode 100644 src/float/conv/cl_LF_to_float.cc create mode 100644 src/float/conv/cl_SF_to_DF.cc create mode 100644 src/float/conv/cl_SF_to_FF.cc create mode 100644 src/float/conv/cl_SF_to_LF.cc create mode 100644 src/float/conv/cl_SF_to_double.cc create mode 100644 src/float/conv/cl_SF_to_float.cc create mode 100644 src/float/dfloat/Makeflags create mode 100644 src/float/dfloat/algebraic/Makeflags create mode 100644 src/float/dfloat/algebraic/cl_DF_sqrt.cc create mode 100644 src/float/dfloat/cl_DF.h create mode 100644 src/float/dfloat/conv/Makeflags create mode 100644 src/float/dfloat/conv/cl_DF_from_double.cc create mode 100644 src/float/dfloat/conv/cl_DF_to_doublej.cc create mode 100644 src/float/dfloat/conv/cl_I_to_double.cc create mode 100644 src/float/dfloat/conv/cl_RA_to_double.cc create mode 100644 src/float/dfloat/division/Makeflags create mode 100644 src/float/dfloat/division/cl_DF_ceil22.cc create mode 100644 src/float/dfloat/division/cl_DF_fceil.cc create mode 100644 src/float/dfloat/division/cl_DF_floor22.cc create mode 100644 src/float/dfloat/division/cl_DF_recip.cc create mode 100644 src/float/dfloat/division/cl_DF_round22.cc create mode 100644 src/float/dfloat/division/cl_DF_trunc22.cc create mode 100644 src/float/dfloat/elem/Makeflags create mode 100644 src/float/dfloat/elem/cl_DF_compare.cc create mode 100644 src/float/dfloat/elem/cl_DF_div.cc create mode 100644 src/float/dfloat/elem/cl_DF_ffloor.cc create mode 100644 src/float/dfloat/elem/cl_DF_from_I.cc create mode 100644 src/float/dfloat/elem/cl_DF_from_RA.cc create mode 100644 src/float/dfloat/elem/cl_DF_fround.cc create mode 100644 src/float/dfloat/elem/cl_DF_ftrunc.cc create mode 100644 src/float/dfloat/elem/cl_DF_futrunc.cc create mode 100644 src/float/dfloat/elem/cl_DF_globals.cc create mode 100644 src/float/dfloat/elem/cl_DF_minus.cc create mode 100644 src/float/dfloat/elem/cl_DF_minusp.cc create mode 100644 src/float/dfloat/elem/cl_DF_mul.cc create mode 100644 src/float/dfloat/elem/cl_DF_plus.cc create mode 100644 src/float/dfloat/elem/cl_DF_plusp.cc create mode 100644 src/float/dfloat/elem/cl_DF_scale.cc create mode 100644 src/float/dfloat/elem/cl_DF_scale_I.cc create mode 100644 src/float/dfloat/elem/cl_DF_to_I.cc create mode 100644 src/float/dfloat/elem/cl_DF_uminus.cc create mode 100644 src/float/dfloat/elem/cl_DF_zerop.cc create mode 100644 src/float/dfloat/input/Makeflags create mode 100644 src/float/dfloat/input/cl_DF_from_string.cc create mode 100644 src/float/dfloat/misc/Makeflags create mode 100644 src/float/dfloat/misc/cl_DF_abs.cc create mode 100644 src/float/dfloat/misc/cl_DF_as.cc create mode 100644 src/float/dfloat/misc/cl_DF_class.cc create mode 100644 src/float/dfloat/misc/cl_DF_debug.cc create mode 100644 src/float/dfloat/misc/cl_DF_decode.cc create mode 100644 src/float/dfloat/misc/cl_DF_digits.cc create mode 100644 src/float/dfloat/misc/cl_DF_eqhashcode.cc create mode 100644 src/float/dfloat/misc/cl_DF_exponent.cc create mode 100644 src/float/dfloat/misc/cl_DF_idecode.cc create mode 100644 src/float/dfloat/misc/cl_DF_max.cc create mode 100644 src/float/dfloat/misc/cl_DF_min.cc create mode 100644 src/float/dfloat/misc/cl_DF_precision.cc create mode 100644 src/float/dfloat/misc/cl_DF_sign.cc create mode 100644 src/float/dfloat/misc/cl_DF_signum.cc create mode 100644 src/float/division/Makeflags create mode 100644 src/float/division/cl_F_ceil1.cc create mode 100644 src/float/division/cl_F_ceil2.cc create mode 100644 src/float/division/cl_F_ceil22.cc create mode 100644 src/float/division/cl_F_fceil1.cc create mode 100644 src/float/division/cl_F_fceil2.cc create mode 100644 src/float/division/cl_F_ffloor1.cc create mode 100644 src/float/division/cl_F_ffloor2.cc create mode 100644 src/float/division/cl_F_floor1.cc create mode 100644 src/float/division/cl_F_floor2.cc create mode 100644 src/float/division/cl_F_floor22.cc create mode 100644 src/float/division/cl_F_fround1.cc create mode 100644 src/float/division/cl_F_fround2.cc create mode 100644 src/float/division/cl_F_ftrunc1.cc create mode 100644 src/float/division/cl_F_ftrunc2.cc create mode 100644 src/float/division/cl_F_round1.cc create mode 100644 src/float/division/cl_F_round2.cc create mode 100644 src/float/division/cl_F_round22.cc create mode 100644 src/float/division/cl_F_trunc1.cc create mode 100644 src/float/division/cl_F_trunc2.cc create mode 100644 src/float/division/cl_F_trunc22.cc create mode 100644 src/float/elem/Makeflags create mode 100644 src/float/elem/cl_F_I_div.cc create mode 100644 src/float/elem/cl_F_I_mul.cc create mode 100644 src/float/elem/cl_F_RA_div.cc create mode 100644 src/float/elem/cl_F_RA_mul.cc create mode 100644 src/float/elem/cl_F_compare.cc create mode 100644 src/float/elem/cl_F_div.cc create mode 100644 src/float/elem/cl_F_minus.cc create mode 100644 src/float/elem/cl_F_minusp.cc create mode 100644 src/float/elem/cl_F_mul.cc create mode 100644 src/float/elem/cl_F_plus.cc create mode 100644 src/float/elem/cl_F_plusp.cc create mode 100644 src/float/elem/cl_F_recip.cc create mode 100644 src/float/elem/cl_F_scale.cc create mode 100644 src/float/elem/cl_F_scale_I.cc create mode 100644 src/float/elem/cl_F_square.cc create mode 100644 src/float/elem/cl_F_uminus.cc create mode 100644 src/float/elem/cl_F_zerop.cc create mode 100644 src/float/elem/cl_I_F_div.cc create mode 100644 src/float/elem/cl_RA_F_div.cc create mode 100644 src/float/ffloat/Makeflags create mode 100644 src/float/ffloat/algebraic/Makeflags create mode 100644 src/float/ffloat/algebraic/cl_FF_sqrt.cc create mode 100644 src/float/ffloat/cl_FF.h create mode 100644 src/float/ffloat/conv/Makeflags create mode 100644 src/float/ffloat/conv/cl_FF_from_float.cc create mode 100644 src/float/ffloat/conv/cl_FF_to_floatj.cc create mode 100644 src/float/ffloat/conv/cl_I_to_float.cc create mode 100644 src/float/ffloat/conv/cl_RA_to_float.cc create mode 100644 src/float/ffloat/division/Makeflags create mode 100644 src/float/ffloat/division/cl_FF_ceil22.cc create mode 100644 src/float/ffloat/division/cl_FF_fceil.cc create mode 100644 src/float/ffloat/division/cl_FF_floor22.cc create mode 100644 src/float/ffloat/division/cl_FF_recip.cc create mode 100644 src/float/ffloat/division/cl_FF_round22.cc create mode 100644 src/float/ffloat/division/cl_FF_trunc22.cc create mode 100644 src/float/ffloat/elem/Makeflags create mode 100644 src/float/ffloat/elem/cl_FF_compare.cc create mode 100644 src/float/ffloat/elem/cl_FF_div.cc create mode 100644 src/float/ffloat/elem/cl_FF_ffloor.cc create mode 100644 src/float/ffloat/elem/cl_FF_from_I.cc create mode 100644 src/float/ffloat/elem/cl_FF_from_RA.cc create mode 100644 src/float/ffloat/elem/cl_FF_fround.cc create mode 100644 src/float/ffloat/elem/cl_FF_ftrunc.cc create mode 100644 src/float/ffloat/elem/cl_FF_futrunc.cc create mode 100644 src/float/ffloat/elem/cl_FF_globals.cc create mode 100644 src/float/ffloat/elem/cl_FF_minus.cc create mode 100644 src/float/ffloat/elem/cl_FF_minusp.cc create mode 100644 src/float/ffloat/elem/cl_FF_mul.cc create mode 100644 src/float/ffloat/elem/cl_FF_plus.cc create mode 100644 src/float/ffloat/elem/cl_FF_plusp.cc create mode 100644 src/float/ffloat/elem/cl_FF_scale.cc create mode 100644 src/float/ffloat/elem/cl_FF_scale_I.cc create mode 100644 src/float/ffloat/elem/cl_FF_to_I.cc create mode 100644 src/float/ffloat/elem/cl_FF_uminus.cc create mode 100644 src/float/ffloat/elem/cl_FF_zerop.cc create mode 100644 src/float/ffloat/input/Makeflags create mode 100644 src/float/ffloat/input/cl_FF_from_string.cc create mode 100644 src/float/ffloat/misc/Makeflags create mode 100644 src/float/ffloat/misc/cl_FF_abs.cc create mode 100644 src/float/ffloat/misc/cl_FF_as.cc create mode 100644 src/float/ffloat/misc/cl_FF_class.cc create mode 100644 src/float/ffloat/misc/cl_FF_debug.cc create mode 100644 src/float/ffloat/misc/cl_FF_decode.cc create mode 100644 src/float/ffloat/misc/cl_FF_digits.cc create mode 100644 src/float/ffloat/misc/cl_FF_eqhashcode.cc create mode 100644 src/float/ffloat/misc/cl_FF_exponent.cc create mode 100644 src/float/ffloat/misc/cl_FF_idecode.cc create mode 100644 src/float/ffloat/misc/cl_FF_max.cc create mode 100644 src/float/ffloat/misc/cl_FF_min.cc create mode 100644 src/float/ffloat/misc/cl_FF_precision.cc create mode 100644 src/float/ffloat/misc/cl_FF_sign.cc create mode 100644 src/float/ffloat/misc/cl_FF_signum.cc create mode 100644 src/float/input/Makeflags create mode 100644 src/float/input/cl_F_from_string.cc create mode 100644 src/float/input/cl_F_read.cc create mode 100644 src/float/input/cl_F_read_stream.cc create mode 100644 src/float/input/cl_F_readparsed.cc create mode 100644 src/float/lfloat/Makeflags create mode 100644 src/float/lfloat/algebraic/Makeflags create mode 100644 src/float/lfloat/algebraic/cl_LF_sqrt.cc create mode 100644 src/float/lfloat/cl_LF.h create mode 100644 src/float/lfloat/cl_LF_impl.h create mode 100644 src/float/lfloat/division/Makeflags create mode 100644 src/float/lfloat/division/cl_LF_ceil22.cc create mode 100644 src/float/lfloat/division/cl_LF_fceil.cc create mode 100644 src/float/lfloat/division/cl_LF_floor22.cc create mode 100644 src/float/lfloat/division/cl_LF_recip.cc create mode 100644 src/float/lfloat/division/cl_LF_round22.cc create mode 100644 src/float/lfloat/division/cl_LF_trunc22.cc create mode 100644 src/float/lfloat/elem/Makeflags create mode 100644 src/float/lfloat/elem/cl_I_LF_div.cc create mode 100644 src/float/lfloat/elem/cl_LF_1minus.cc create mode 100644 src/float/lfloat/elem/cl_LF_1plus.cc create mode 100644 src/float/lfloat/elem/cl_LF_2minus.cc create mode 100644 src/float/lfloat/elem/cl_LF_2plus.cc create mode 100644 src/float/lfloat/elem/cl_LF_I_div.cc create mode 100644 src/float/lfloat/elem/cl_LF_I_mul.cc create mode 100644 src/float/lfloat/elem/cl_LF_RA_div.cc create mode 100644 src/float/lfloat/elem/cl_LF_RA_mul.cc create mode 100644 src/float/lfloat/elem/cl_LF_compare.cc create mode 100644 src/float/lfloat/elem/cl_LF_div.cc create mode 100644 src/float/lfloat/elem/cl_LF_ffloor.cc create mode 100644 src/float/lfloat/elem/cl_LF_from_I.cc create mode 100644 src/float/lfloat/elem/cl_LF_from_RA.cc create mode 100644 src/float/lfloat/elem/cl_LF_fround.cc create mode 100644 src/float/lfloat/elem/cl_LF_ftrunc.cc create mode 100644 src/float/lfloat/elem/cl_LF_futrunc.cc create mode 100644 src/float/lfloat/elem/cl_LF_globals.cc create mode 100644 src/float/lfloat/elem/cl_LF_minus1.cc create mode 100644 src/float/lfloat/elem/cl_LF_minusp.cc create mode 100644 src/float/lfloat/elem/cl_LF_mul.cc create mode 100644 src/float/lfloat/elem/cl_LF_plus1.cc create mode 100644 src/float/lfloat/elem/cl_LF_plusp.cc create mode 100644 src/float/lfloat/elem/cl_LF_scale.cc create mode 100644 src/float/lfloat/elem/cl_LF_scale_I.cc create mode 100644 src/float/lfloat/elem/cl_LF_square.cc create mode 100644 src/float/lfloat/elem/cl_LF_to_I.cc create mode 100644 src/float/lfloat/elem/cl_LF_uminus.cc create mode 100644 src/float/lfloat/elem/cl_LF_zerop.cc create mode 100644 src/float/lfloat/elem/cl_RA_LF_div.cc create mode 100644 src/float/lfloat/input/Makeflags create mode 100644 src/float/lfloat/input/cl_LF_from_string.cc create mode 100644 src/float/lfloat/misc/Makeflags create mode 100644 src/float/lfloat/misc/cl_LF_abs.cc create mode 100644 src/float/lfloat/misc/cl_LF_as.cc create mode 100644 src/float/lfloat/misc/cl_LF_class.cc create mode 100644 src/float/lfloat/misc/cl_LF_debug.cc create mode 100644 src/float/lfloat/misc/cl_LF_decode.cc create mode 100644 src/float/lfloat/misc/cl_LF_digits.cc create mode 100644 src/float/lfloat/misc/cl_LF_eqhashcode.cc create mode 100644 src/float/lfloat/misc/cl_LF_exponent.cc create mode 100644 src/float/lfloat/misc/cl_LF_extend.cc create mode 100644 src/float/lfloat/misc/cl_LF_idecode.cc create mode 100644 src/float/lfloat/misc/cl_LF_leninc.cc create mode 100644 src/float/lfloat/misc/cl_LF_lenincx.cc create mode 100644 src/float/lfloat/misc/cl_LF_max.cc create mode 100644 src/float/lfloat/misc/cl_LF_min.cc create mode 100644 src/float/lfloat/misc/cl_LF_precision.cc create mode 100644 src/float/lfloat/misc/cl_LF_shorten.cc create mode 100644 src/float/lfloat/misc/cl_LF_shortenrel.cc create mode 100644 src/float/lfloat/misc/cl_LF_shortenwith.cc create mode 100644 src/float/lfloat/misc/cl_LF_sign.cc create mode 100644 src/float/lfloat/misc/cl_LF_signum.cc create mode 100644 src/float/lfloat/misc/cl_LF_to_LF.cc create mode 100644 src/float/misc/Makeflags create mode 100644 src/float/misc/cl_F_abs.cc create mode 100644 src/float/misc/cl_F_as.cc create mode 100644 src/float/misc/cl_F_decode.cc create mode 100644 src/float/misc/cl_F_digits.cc create mode 100644 src/float/misc/cl_F_epsneg.cc create mode 100644 src/float/misc/cl_F_epspos.cc create mode 100644 src/float/misc/cl_F_eqhashcode.cc create mode 100644 src/float/misc/cl_F_exponent.cc create mode 100644 src/float/misc/cl_F_extendsqrt.cc create mode 100644 src/float/misc/cl_F_extendsqrtx.cc create mode 100644 src/float/misc/cl_F_idecode.cc create mode 100644 src/float/misc/cl_F_leastneg.cc create mode 100644 src/float/misc/cl_F_leastpos.cc create mode 100644 src/float/misc/cl_F_max.cc create mode 100644 src/float/misc/cl_F_min.cc create mode 100644 src/float/misc/cl_F_mostneg.cc create mode 100644 src/float/misc/cl_F_mostpos.cc create mode 100644 src/float/misc/cl_F_precision.cc create mode 100644 src/float/misc/cl_F_rational.cc create mode 100644 src/float/misc/cl_F_shortenrel.cc create mode 100644 src/float/misc/cl_F_sign.cc create mode 100644 src/float/misc/cl_F_sign2.cc create mode 100644 src/float/misc/cl_F_signum.cc create mode 100644 src/float/misc/cl_float_format.cc create mode 100644 src/float/output/Makeflags create mode 100644 src/float/output/cl_F_aprint.cc create mode 100644 src/float/output/cl_F_bprint.cc create mode 100644 src/float/output/cl_F_cprint.cc create mode 100644 src/float/output/cl_F_dprint.cc create mode 100644 src/float/output/cl_F_printb.cc create mode 100644 src/float/random/Makeflags create mode 100644 src/float/random/cl_F_random.cc create mode 100644 src/float/sfloat/Makeflags create mode 100644 src/float/sfloat/algebraic/Makeflags create mode 100644 src/float/sfloat/algebraic/cl_SF_sqrt.cc create mode 100644 src/float/sfloat/cl_SF.h create mode 100644 src/float/sfloat/division/Makeflags create mode 100644 src/float/sfloat/division/cl_SF_ceil22.cc create mode 100644 src/float/sfloat/division/cl_SF_fceil.cc create mode 100644 src/float/sfloat/division/cl_SF_ffloor.cc create mode 100644 src/float/sfloat/division/cl_SF_floor22.cc create mode 100644 src/float/sfloat/division/cl_SF_recip.cc create mode 100644 src/float/sfloat/division/cl_SF_round22.cc create mode 100644 src/float/sfloat/division/cl_SF_trunc22.cc create mode 100644 src/float/sfloat/elem/Makeflags create mode 100644 src/float/sfloat/elem/cl_SF_compare.cc create mode 100644 src/float/sfloat/elem/cl_SF_div.cc create mode 100644 src/float/sfloat/elem/cl_SF_from_I.cc create mode 100644 src/float/sfloat/elem/cl_SF_from_RA.cc create mode 100644 src/float/sfloat/elem/cl_SF_fround.cc create mode 100644 src/float/sfloat/elem/cl_SF_ftrunc.cc create mode 100644 src/float/sfloat/elem/cl_SF_futrunc.cc create mode 100644 src/float/sfloat/elem/cl_SF_minus.cc create mode 100644 src/float/sfloat/elem/cl_SF_minusp.cc create mode 100644 src/float/sfloat/elem/cl_SF_mul.cc create mode 100644 src/float/sfloat/elem/cl_SF_plus.cc create mode 100644 src/float/sfloat/elem/cl_SF_plusp.cc create mode 100644 src/float/sfloat/elem/cl_SF_scale.cc create mode 100644 src/float/sfloat/elem/cl_SF_scale_I.cc create mode 100644 src/float/sfloat/elem/cl_SF_to_I.cc create mode 100644 src/float/sfloat/elem/cl_SF_uminus.cc create mode 100644 src/float/sfloat/elem/cl_SF_zerop.cc create mode 100644 src/float/sfloat/input/Makeflags create mode 100644 src/float/sfloat/input/cl_SF_from_string.cc create mode 100644 src/float/sfloat/misc/Makeflags create mode 100644 src/float/sfloat/misc/cl_SF_abs.cc create mode 100644 src/float/sfloat/misc/cl_SF_as.cc create mode 100644 src/float/sfloat/misc/cl_SF_class.cc create mode 100644 src/float/sfloat/misc/cl_SF_debug.cc create mode 100644 src/float/sfloat/misc/cl_SF_decode.cc create mode 100644 src/float/sfloat/misc/cl_SF_digits.cc create mode 100644 src/float/sfloat/misc/cl_SF_eqhashcode.cc create mode 100644 src/float/sfloat/misc/cl_SF_exponent.cc create mode 100644 src/float/sfloat/misc/cl_SF_idecode.cc create mode 100644 src/float/sfloat/misc/cl_SF_max.cc create mode 100644 src/float/sfloat/misc/cl_SF_min.cc create mode 100644 src/float/sfloat/misc/cl_SF_precision.cc create mode 100644 src/float/sfloat/misc/cl_SF_sign.cc create mode 100644 src/float/sfloat/misc/cl_SF_signum.cc create mode 100644 src/float/transcendental/Makefile.devel create mode 100644 src/float/transcendental/Makeflags create mode 100644 src/float/transcendental/cl_F_atanhx.cc create mode 100644 src/float/transcendental/cl_F_atanx.cc create mode 100644 src/float/transcendental/cl_F_catalanconst.cc create mode 100644 src/float/transcendental/cl_F_catalanconst_def.cc create mode 100644 src/float/transcendental/cl_F_catalanconst_f.cc create mode 100644 src/float/transcendental/cl_F_catalanconst_var.cc create mode 100644 src/float/transcendental/cl_F_catalanconst_var.h create mode 100644 src/float/transcendental/cl_F_catalanconst_var.h.in create mode 100644 src/float/transcendental/cl_F_cos.cc create mode 100644 src/float/transcendental/cl_F_cosh.cc create mode 100644 src/float/transcendental/cl_F_coshsinh.cc create mode 100644 src/float/transcendental/cl_F_cossin.cc create mode 100644 src/float/transcendental/cl_F_eulerconst.cc create mode 100644 src/float/transcendental/cl_F_eulerconst_def.cc create mode 100644 src/float/transcendental/cl_F_eulerconst_f.cc create mode 100644 src/float/transcendental/cl_F_eulerconst_var.cc create mode 100644 src/float/transcendental/cl_F_eulerconst_var.h create mode 100644 src/float/transcendental/cl_F_eulerconst_var.h.in create mode 100644 src/float/transcendental/cl_F_exp.cc create mode 100644 src/float/transcendental/cl_F_exp1.cc create mode 100644 src/float/transcendental/cl_F_exp1_def.cc create mode 100644 src/float/transcendental/cl_F_exp1_f.cc create mode 100644 src/float/transcendental/cl_F_exp1_var.cc create mode 100644 src/float/transcendental/cl_F_exp1_var.h create mode 100644 src/float/transcendental/cl_F_exp1_var.h.in create mode 100644 src/float/transcendental/cl_F_expx.cc create mode 100644 src/float/transcendental/cl_F_ln.cc create mode 100644 src/float/transcendental/cl_F_ln10.cc create mode 100644 src/float/transcendental/cl_F_ln10_f.cc create mode 100644 src/float/transcendental/cl_F_ln10_var.cc create mode 100644 src/float/transcendental/cl_F_ln10_var.h create mode 100644 src/float/transcendental/cl_F_ln10_var.h.in create mode 100644 src/float/transcendental/cl_F_ln2.cc create mode 100644 src/float/transcendental/cl_F_ln2_f.cc create mode 100644 src/float/transcendental/cl_F_ln2_var.cc create mode 100644 src/float/transcendental/cl_F_ln2_var.h create mode 100644 src/float/transcendental/cl_F_ln2_var.h.in create mode 100644 src/float/transcendental/cl_F_lnx.cc create mode 100644 src/float/transcendental/cl_F_pi.cc create mode 100644 src/float/transcendental/cl_F_pi_def.cc create mode 100644 src/float/transcendental/cl_F_pi_f.cc create mode 100644 src/float/transcendental/cl_F_pi_var.cc create mode 100644 src/float/transcendental/cl_F_pi_var.h create mode 100644 src/float/transcendental/cl_F_pi_var.h.in create mode 100644 src/float/transcendental/cl_F_roundpi.cc create mode 100644 src/float/transcendental/cl_F_roundpi2.cc create mode 100644 src/float/transcendental/cl_F_sin.cc create mode 100644 src/float/transcendental/cl_F_sinh.cc create mode 100644 src/float/transcendental/cl_F_sinhx.cc create mode 100644 src/float/transcendental/cl_F_sinx.cc create mode 100644 src/float/transcendental/cl_F_tan.cc create mode 100644 src/float/transcendental/cl_F_tanh.cc create mode 100644 src/float/transcendental/cl_F_tran.h create mode 100644 src/float/transcendental/cl_F_zeta_int.cc create mode 100644 src/float/transcendental/cl_F_zeta_int_def.cc create mode 100644 src/float/transcendental/cl_F_zeta_int_f.cc create mode 100644 src/float/transcendental/cl_LF_atan_recip.cc create mode 100644 src/float/transcendental/cl_LF_atanh_recip.cc create mode 100644 src/float/transcendental/cl_LF_catalanconst.cc create mode 100644 src/float/transcendental/cl_LF_coshsinh.cc create mode 100644 src/float/transcendental/cl_LF_coshsinh_aux.cc create mode 100644 src/float/transcendental/cl_LF_cossin.cc create mode 100644 src/float/transcendental/cl_LF_cossin_aux.cc create mode 100644 src/float/transcendental/cl_LF_eulerconst.cc create mode 100644 src/float/transcendental/cl_LF_exp1.cc create mode 100644 src/float/transcendental/cl_LF_exp_aux.cc create mode 100644 src/float/transcendental/cl_LF_ln10.cc create mode 100644 src/float/transcendental/cl_LF_ln2.cc create mode 100644 src/float/transcendental/cl_LF_pi.cc create mode 100644 src/float/transcendental/cl_LF_ratseries.cc create mode 100644 src/float/transcendental/cl_LF_ratseries_.cc create mode 100644 src/float/transcendental/cl_LF_ratseries_a.cc create mode 100644 src/float/transcendental/cl_LF_ratseries_ab.cc create mode 100644 src/float/transcendental/cl_LF_ratseries_b.cc create mode 100644 src/float/transcendental/cl_LF_ratseries_p.cc create mode 100644 src/float/transcendental/cl_LF_ratseries_pa.cc create mode 100644 src/float/transcendental/cl_LF_ratseries_pab.cc create mode 100644 src/float/transcendental/cl_LF_ratseries_pb.cc create mode 100644 src/float/transcendental/cl_LF_ratseries_pq.cc create mode 100644 src/float/transcendental/cl_LF_ratseries_pqa.cc create mode 100644 src/float/transcendental/cl_LF_ratseries_pqab.cc create mode 100644 src/float/transcendental/cl_LF_ratseries_pqb.cc create mode 100644 src/float/transcendental/cl_LF_ratseries_q.cc create mode 100644 src/float/transcendental/cl_LF_ratseries_qa.cc create mode 100644 src/float/transcendental/cl_LF_ratseries_qab.cc create mode 100644 src/float/transcendental/cl_LF_ratseries_qb.cc create mode 100644 src/float/transcendental/cl_LF_ratseries_stream_pq.cc create mode 100644 src/float/transcendental/cl_LF_ratseries_stream_pqa.cc create mode 100644 src/float/transcendental/cl_LF_ratseries_stream_pqab.cc create mode 100644 src/float/transcendental/cl_LF_ratseries_stream_pqb.cc create mode 100644 src/float/transcendental/cl_LF_ratsumseries_pqcd.cc create mode 100644 src/float/transcendental/cl_LF_ratsumseries_pqcd_aux.cc create mode 100644 src/float/transcendental/cl_LF_ratsumseries_pqd.cc create mode 100644 src/float/transcendental/cl_LF_ratsumseries_pqd_aux.cc create mode 100644 src/float/transcendental/cl_LF_tran.h create mode 100644 src/float/transcendental/cl_LF_zeta3.cc create mode 100644 src/float/transcendental/cl_LF_zeta_int.cc create mode 100644 src/integer/2adic/Makeflags create mode 100644 src/integer/2adic/cl_I_2adic_div.cc create mode 100644 src/integer/2adic/cl_I_2adic_recip.cc create mode 100644 src/integer/Makeflags create mode 100644 src/integer/algebraic/Makeflags create mode 100644 src/integer/algebraic/cl_I_rootp.cc create mode 100644 src/integer/algebraic/cl_I_rootp_I.cc create mode 100644 src/integer/algebraic/cl_I_rootp_aux.cc create mode 100644 src/integer/algebraic/cl_I_sqrt.cc create mode 100644 src/integer/algebraic/cl_I_sqrtp.cc create mode 100644 src/integer/bitwise/Makeflags create mode 100644 src/integer/bitwise/cl_I_ash.cc create mode 100644 src/integer/bitwise/cl_I_ash.h create mode 100644 src/integer/bitwise/cl_I_ash_I.cc create mode 100644 src/integer/bitwise/cl_I_asherr.cc create mode 100644 src/integer/bitwise/cl_I_boole.cc create mode 100644 src/integer/bitwise/cl_I_byte.h create mode 100644 src/integer/bitwise/cl_I_dpb.cc create mode 100644 src/integer/bitwise/cl_I_dpf.cc create mode 100644 src/integer/bitwise/cl_I_fullbyte.cc create mode 100644 src/integer/bitwise/cl_I_ilength.cc create mode 100644 src/integer/bitwise/cl_I_ldb.cc create mode 100644 src/integer/bitwise/cl_I_ldbtest.cc create mode 100644 src/integer/bitwise/cl_I_ldbx.cc create mode 100644 src/integer/bitwise/cl_I_ldbxtest.cc create mode 100644 src/integer/bitwise/cl_I_log.h create mode 100644 src/integer/bitwise/cl_I_log_aux.cc create mode 100644 src/integer/bitwise/cl_I_logand.cc create mode 100644 src/integer/bitwise/cl_I_logandc2.cc create mode 100644 src/integer/bitwise/cl_I_logbitp.cc create mode 100644 src/integer/bitwise/cl_I_logbitp_I.cc create mode 100644 src/integer/bitwise/cl_I_logcount.cc create mode 100644 src/integer/bitwise/cl_I_logeqv.cc create mode 100644 src/integer/bitwise/cl_I_logior.cc create mode 100644 src/integer/bitwise/cl_I_lognand.cc create mode 100644 src/integer/bitwise/cl_I_lognor.cc create mode 100644 src/integer/bitwise/cl_I_lognot.cc create mode 100644 src/integer/bitwise/cl_I_logorc2.cc create mode 100644 src/integer/bitwise/cl_I_logtest.cc create mode 100644 src/integer/bitwise/cl_I_logxor.cc create mode 100644 src/integer/bitwise/cl_I_mkf.cc create mode 100644 src/integer/bitwise/cl_I_mkfx.cc create mode 100644 src/integer/cl_I.h create mode 100644 src/integer/conv/Makeflags create mode 100644 src/integer/conv/cl_I_digits_need.cc create mode 100644 src/integer/conv/cl_I_from_DS.cc create mode 100644 src/integer/conv/cl_I_from_L.cc create mode 100644 src/integer/conv/cl_I_from_L2.cc create mode 100644 src/integer/conv/cl_I_from_NDS.cc create mode 100644 src/integer/conv/cl_I_from_NUDS.cc create mode 100644 src/integer/conv/cl_I_from_Q.cc create mode 100644 src/integer/conv/cl_I_from_UDS.cc create mode 100644 src/integer/conv/cl_I_from_UL.cc create mode 100644 src/integer/conv/cl_I_from_UL2.cc create mode 100644 src/integer/conv/cl_I_from_UQ.cc create mode 100644 src/integer/conv/cl_I_from_digits.cc create mode 100644 src/integer/conv/cl_I_mul10plus.cc create mode 100644 src/integer/conv/cl_I_to_L.cc create mode 100644 src/integer/conv/cl_I_to_Q.cc create mode 100644 src/integer/conv/cl_I_to_UL.cc create mode 100644 src/integer/conv/cl_I_to_UQ.cc create mode 100644 src/integer/conv/cl_I_to_digits.cc create mode 100644 src/integer/division/Makeflags create mode 100644 src/integer/division/cl_I_ceil1.cc create mode 100644 src/integer/division/cl_I_ceil2.cc create mode 100644 src/integer/division/cl_I_exquo.cc create mode 100644 src/integer/division/cl_I_exquoerr.cc create mode 100644 src/integer/division/cl_I_exquopos.cc create mode 100644 src/integer/division/cl_I_floor1.cc create mode 100644 src/integer/division/cl_I_floor2.cc create mode 100644 src/integer/division/cl_I_mod.cc create mode 100644 src/integer/division/cl_I_rem.cc create mode 100644 src/integer/division/cl_I_round1.cc create mode 100644 src/integer/division/cl_I_round2.cc create mode 100644 src/integer/division/cl_I_trunc1.cc create mode 100644 src/integer/division/cl_I_trunc2.cc create mode 100644 src/integer/elem/Makeflags create mode 100644 src/integer/elem/cl_I_compare.cc create mode 100644 src/integer/elem/cl_I_div.cc create mode 100644 src/integer/elem/cl_I_equal.cc create mode 100644 src/integer/elem/cl_I_minus.cc create mode 100644 src/integer/elem/cl_I_minus1.cc create mode 100644 src/integer/elem/cl_I_minusp.cc create mode 100644 src/integer/elem/cl_I_mul.cc create mode 100644 src/integer/elem/cl_I_plus.cc create mode 100644 src/integer/elem/cl_I_plus1.cc create mode 100644 src/integer/elem/cl_I_plusp.cc create mode 100644 src/integer/elem/cl_I_square.cc create mode 100644 src/integer/elem/cl_I_uminus.cc create mode 100644 src/integer/elem/cl_I_zerop.cc create mode 100644 src/integer/gcd/Makeflags create mode 100644 src/integer/gcd/cl_I_gcd.cc create mode 100644 src/integer/gcd/cl_I_gcd_aux.cc create mode 100644 src/integer/gcd/cl_I_gcd_aux2.cc create mode 100644 src/integer/gcd/cl_I_lcm.cc create mode 100644 src/integer/gcd/cl_I_xgcd.cc create mode 100644 src/integer/gcd/cl_low_gcd.cc create mode 100644 src/integer/hash/Makeflags create mode 100644 src/integer/hash/cl_I_hash_gcobject.cc create mode 100644 src/integer/hash/cl_I_hash_gcobject.h create mode 100644 src/integer/hash/cl_I_hash_gcpointer.cc create mode 100644 src/integer/hash/cl_I_hash_gcpointer.h create mode 100644 src/integer/hash/cl_I_hash_pointer.cc create mode 100644 src/integer/hash/cl_I_hash_pointer.h create mode 100644 src/integer/hash/cl_I_hash_rcobject.cc create mode 100644 src/integer/hash/cl_I_hash_rcobject.h create mode 100644 src/integer/hash/cl_I_hash_rcpointer.cc create mode 100644 src/integer/hash/cl_I_hash_rcpointer.h create mode 100644 src/integer/hash/cl_I_hashcode.cc create mode 100644 src/integer/hash/cl_I_hashweak_rcpointer.cc create mode 100644 src/integer/hash/cl_I_hashweak_rcpointer.h create mode 100644 src/integer/input/Makeflags create mode 100644 src/integer/input/cl_I_from_string.cc create mode 100644 src/integer/input/cl_I_read.cc create mode 100644 src/integer/input/cl_I_read_stream.cc create mode 100644 src/integer/input/cl_I_readparsed.cc create mode 100644 src/integer/misc/Makeflags create mode 100644 src/integer/misc/cl_BN_class.cc create mode 100644 src/integer/misc/cl_FN_class.cc create mode 100644 src/integer/misc/cl_I_abs.cc create mode 100644 src/integer/misc/cl_I_as.cc create mode 100644 src/integer/misc/cl_I_debug.cc create mode 100644 src/integer/misc/cl_I_eqhashcode.cc create mode 100644 src/integer/misc/cl_I_exptpos.cc create mode 100644 src/integer/misc/cl_I_exptpos_I.cc create mode 100644 src/integer/misc/cl_I_max.cc create mode 100644 src/integer/misc/cl_I_min.cc create mode 100644 src/integer/misc/cl_I_oddp.cc create mode 100644 src/integer/misc/cl_I_ord2.cc create mode 100644 src/integer/misc/cl_I_power2p.cc create mode 100644 src/integer/misc/cl_I_signum.cc create mode 100644 src/integer/misc/combin/Makeflags create mode 100644 src/integer/misc/combin/cl_I_binomial.cc create mode 100644 src/integer/misc/combin/cl_I_combin.h create mode 100644 src/integer/misc/combin/cl_I_doublefactorial.cc create mode 100644 src/integer/misc/combin/cl_I_factorial.cc create mode 100644 src/integer/misc/combin/cl_I_factorial_aux.cc create mode 100644 src/integer/output/Makeflags create mode 100644 src/integer/output/cl_I_aprint.cc create mode 100644 src/integer/output/cl_I_bprint.cc create mode 100644 src/integer/output/cl_I_cprint.cc create mode 100644 src/integer/output/cl_I_decstring.cc create mode 100644 src/integer/output/cl_I_dprint.cc create mode 100644 src/integer/output/cl_I_print.cc create mode 100644 src/integer/output/cl_I_print_string.cc create mode 100644 src/integer/random/Makeflags create mode 100644 src/integer/random/cl_I_random.cc create mode 100644 src/integer/random/cl_I_trandom.cc create mode 100644 src/integer/ring/Makeflags create mode 100644 src/integer/ring/cl_0_ring.cc create mode 100644 src/integer/ring/cl_I_ring.cc create mode 100644 src/modinteger/Makeflags create mode 100644 src/modinteger/cl_MI.cc create mode 100644 src/modinteger/cl_MI.h create mode 100644 src/modinteger/cl_MI_cond_composite.cc create mode 100644 src/modinteger/cl_MI_debug.cc create mode 100644 src/modinteger/cl_MI_err_comp.cc create mode 100644 src/modinteger/cl_MI_fix16.h create mode 100644 src/modinteger/cl_MI_fix29.h create mode 100644 src/modinteger/cl_MI_fix32.h create mode 100644 src/modinteger/cl_MI_int.h create mode 100644 src/modinteger/cl_MI_int32.h create mode 100644 src/modinteger/cl_MI_lshift.cc create mode 100644 src/modinteger/cl_MI_montgom.h create mode 100644 src/modinteger/cl_MI_pow2.h create mode 100644 src/modinteger/cl_MI_pow2m1.h create mode 100644 src/modinteger/cl_MI_pow2p1.h create mode 100644 src/modinteger/cl_MI_rshift.cc create mode 100644 src/modinteger/cl_MI_std.h create mode 100644 src/modpolynomial/Makeflags create mode 100644 src/numtheory/Makeflags create mode 100644 src/numtheory/cl_IF.h create mode 100644 src/numtheory/cl_IF_millerrabin.cc create mode 100644 src/numtheory/cl_IF_smallprimes.cc create mode 100644 src/numtheory/cl_IF_trialdiv.cc create mode 100644 src/numtheory/cl_IF_trialdiv1.cc create mode 100644 src/numtheory/cl_IF_trialdiv2.cc create mode 100644 src/numtheory/cl_nt_cornacchia1.cc create mode 100644 src/numtheory/cl_nt_cornacchia4.cc create mode 100644 src/numtheory/cl_nt_isprobprime.cc create mode 100644 src/numtheory/cl_nt_jacobi.cc create mode 100644 src/numtheory/cl_nt_jacobi_low.cc create mode 100644 src/numtheory/cl_nt_nextprobprime.cc create mode 100644 src/numtheory/cl_nt_sqrtmodp.cc create mode 100644 src/polynomial/Makeflags create mode 100644 src/polynomial/cl_UP.h create mode 100644 src/polynomial/elem/Makeflags create mode 100644 src/polynomial/elem/cl_UP.cc create mode 100644 src/polynomial/elem/cl_UP_GF2.h create mode 100644 src/polynomial/elem/cl_UP_MI.h create mode 100644 src/polynomial/elem/cl_UP_gen.h create mode 100644 src/polynomial/elem/cl_UP_named.cc create mode 100644 src/polynomial/elem/cl_UP_no_ring.cc create mode 100644 src/polynomial/elem/cl_UP_number.h create mode 100644 src/polynomial/elem/cl_UP_unnamed.cc create mode 100644 src/polynomial/elem/cl_asm_GF2.cc create mode 100644 src/polynomial/elem/cl_asm_sparc_GF2.cc create mode 100644 src/polynomial/misc/Makeflags create mode 100644 src/polynomial/misc/cl_UP_I_hermite.cc create mode 100644 src/polynomial/misc/cl_UP_I_laguerre.cc create mode 100644 src/polynomial/misc/cl_UP_I_tchebychev.cc create mode 100644 src/polynomial/misc/cl_UP_RA_legendre.cc create mode 100644 src/polynomial/misc/cl_UP_debug.cc create mode 100644 src/polynomial/misc/cl_UP_deriv.cc create mode 100644 src/rational/Makeflags create mode 100644 src/rational/algebraic/Makeflags create mode 100644 src/rational/algebraic/cl_RA_rootp.cc create mode 100644 src/rational/algebraic/cl_RA_rootp_I.cc create mode 100644 src/rational/algebraic/cl_RA_sqrtp.cc create mode 100644 src/rational/cl_RA.h create mode 100644 src/rational/division/Makeflags create mode 100644 src/rational/division/cl_RA_ceil1.cc create mode 100644 src/rational/division/cl_RA_ceil12.cc create mode 100644 src/rational/division/cl_RA_ceil2.cc create mode 100644 src/rational/division/cl_RA_ceil22.cc create mode 100644 src/rational/division/cl_RA_floor1.cc create mode 100644 src/rational/division/cl_RA_floor12.cc create mode 100644 src/rational/division/cl_RA_floor2.cc create mode 100644 src/rational/division/cl_RA_floor22.cc create mode 100644 src/rational/division/cl_RA_round1.cc create mode 100644 src/rational/division/cl_RA_round12.cc create mode 100644 src/rational/division/cl_RA_round2.cc create mode 100644 src/rational/division/cl_RA_round22.cc create mode 100644 src/rational/division/cl_RA_trunc1.cc create mode 100644 src/rational/division/cl_RA_trunc12.cc create mode 100644 src/rational/division/cl_RA_trunc2.cc create mode 100644 src/rational/division/cl_RA_trunc22.cc create mode 100644 src/rational/elem/Makeflags create mode 100644 src/rational/elem/cl_RA_compare.cc create mode 100644 src/rational/elem/cl_RA_denominator.cc create mode 100644 src/rational/elem/cl_RA_div.cc create mode 100644 src/rational/elem/cl_RA_equal.cc create mode 100644 src/rational/elem/cl_RA_from_I_I_div.cc create mode 100644 src/rational/elem/cl_RA_from_I_posI.cc create mode 100644 src/rational/elem/cl_RA_from_I_posI1.cc create mode 100644 src/rational/elem/cl_RA_from_I_posI_div.cc create mode 100644 src/rational/elem/cl_RA_minus.cc create mode 100644 src/rational/elem/cl_RA_minus1.cc create mode 100644 src/rational/elem/cl_RA_minusp.cc create mode 100644 src/rational/elem/cl_RA_mul.cc create mode 100644 src/rational/elem/cl_RA_numerator.cc create mode 100644 src/rational/elem/cl_RA_plus.cc create mode 100644 src/rational/elem/cl_RA_plus1.cc create mode 100644 src/rational/elem/cl_RA_plusp.cc create mode 100644 src/rational/elem/cl_RA_recip.cc create mode 100644 src/rational/elem/cl_RA_square.cc create mode 100644 src/rational/elem/cl_RA_uminus.cc create mode 100644 src/rational/elem/cl_RA_zerop.cc create mode 100644 src/rational/input/Makeflags create mode 100644 src/rational/input/cl_RA_from_string.cc create mode 100644 src/rational/input/cl_RA_read.cc create mode 100644 src/rational/input/cl_RA_read_stream.cc create mode 100644 src/rational/input/cl_RA_readparsed.cc create mode 100644 src/rational/misc/Makeflags create mode 100644 src/rational/misc/cl_RA_abs.cc create mode 100644 src/rational/misc/cl_RA_as.cc create mode 100644 src/rational/misc/cl_RA_class.cc create mode 100644 src/rational/misc/cl_RA_debug.cc create mode 100644 src/rational/misc/cl_RA_eqhashcode.cc create mode 100644 src/rational/misc/cl_RA_expt.cc create mode 100644 src/rational/misc/cl_RA_expt_I.cc create mode 100644 src/rational/misc/cl_RA_exptpos.cc create mode 100644 src/rational/misc/cl_RA_exptpos_I.cc create mode 100644 src/rational/misc/cl_RA_max.cc create mode 100644 src/rational/misc/cl_RA_min.cc create mode 100644 src/rational/misc/cl_RA_signum.cc create mode 100644 src/rational/output/Makeflags create mode 100644 src/rational/output/cl_RA_aprint.cc create mode 100644 src/rational/output/cl_RA_bprint.cc create mode 100644 src/rational/output/cl_RA_cprint.cc create mode 100644 src/rational/output/cl_RA_dprint.cc create mode 100644 src/rational/output/cl_RA_print.cc create mode 100644 src/rational/ring/Makeflags create mode 100644 src/rational/ring/cl_RA_ring.cc create mode 100644 src/rational/transcendental/Makeflags create mode 100644 src/rational/transcendental/cl_I_logp.cc create mode 100644 src/rational/transcendental/cl_RA_logp.cc create mode 100644 src/real/Makeflags create mode 100644 src/real/algebraic/Makeflags create mode 100644 src/real/algebraic/cl_RA_sqrt.cc create mode 100644 src/real/algebraic/cl_R_sqrt.cc create mode 100644 src/real/cl_R.h create mode 100644 src/real/conv/Makeflags create mode 100644 src/real/conv/cl_F_from_R.cc create mode 100644 src/real/conv/cl_F_from_R_def.cc create mode 100644 src/real/conv/cl_F_from_R_f.cc create mode 100644 src/real/conv/cl_R_to_DF.cc create mode 100644 src/real/conv/cl_R_to_FF.cc create mode 100644 src/real/conv/cl_R_to_LF.cc create mode 100644 src/real/conv/cl_R_to_SF.cc create mode 100644 src/real/conv/cl_R_to_double.cc create mode 100644 src/real/conv/cl_R_to_float.cc create mode 100644 src/real/division/Makeflags create mode 100644 src/real/division/cl_R_ceil1.cc create mode 100644 src/real/division/cl_R_ceil12.cc create mode 100644 src/real/division/cl_R_ceil2.cc create mode 100644 src/real/division/cl_R_ceil22.cc create mode 100644 src/real/division/cl_R_div_t.h create mode 100644 src/real/division/cl_R_fceil1.cc create mode 100644 src/real/division/cl_R_fceil12.cc create mode 100644 src/real/division/cl_R_fceil2.cc create mode 100644 src/real/division/cl_R_fceil22.cc create mode 100644 src/real/division/cl_R_ffloor1.cc create mode 100644 src/real/division/cl_R_ffloor12.cc create mode 100644 src/real/division/cl_R_ffloor2.cc create mode 100644 src/real/division/cl_R_ffloor22.cc create mode 100644 src/real/division/cl_R_floor1.cc create mode 100644 src/real/division/cl_R_floor12.cc create mode 100644 src/real/division/cl_R_floor2.cc create mode 100644 src/real/division/cl_R_floor22.cc create mode 100644 src/real/division/cl_R_fround1.cc create mode 100644 src/real/division/cl_R_fround12.cc create mode 100644 src/real/division/cl_R_fround2.cc create mode 100644 src/real/division/cl_R_fround22.cc create mode 100644 src/real/division/cl_R_ftrunc1.cc create mode 100644 src/real/division/cl_R_ftrunc12.cc create mode 100644 src/real/division/cl_R_ftrunc2.cc create mode 100644 src/real/division/cl_R_ftrunc22.cc create mode 100644 src/real/division/cl_R_mod.cc create mode 100644 src/real/division/cl_R_rem.cc create mode 100644 src/real/division/cl_R_round1.cc create mode 100644 src/real/division/cl_R_round12.cc create mode 100644 src/real/division/cl_R_round2.cc create mode 100644 src/real/division/cl_R_round22.cc create mode 100644 src/real/division/cl_R_trunc1.cc create mode 100644 src/real/division/cl_R_trunc12.cc create mode 100644 src/real/division/cl_R_trunc2.cc create mode 100644 src/real/division/cl_R_trunc22.cc create mode 100644 src/real/elem/Makeflags create mode 100644 src/real/elem/cl_R_compare.cc create mode 100644 src/real/elem/cl_R_div.cc create mode 100644 src/real/elem/cl_R_equal.cc create mode 100644 src/real/elem/cl_R_minus.cc create mode 100644 src/real/elem/cl_R_minus1.cc create mode 100644 src/real/elem/cl_R_minusp.cc create mode 100644 src/real/elem/cl_R_mul.cc create mode 100644 src/real/elem/cl_R_plus.cc create mode 100644 src/real/elem/cl_R_plus1.cc create mode 100644 src/real/elem/cl_R_plusp.cc create mode 100644 src/real/elem/cl_R_recip.cc create mode 100644 src/real/elem/cl_R_square.cc create mode 100644 src/real/elem/cl_R_uminus.cc create mode 100644 src/real/elem/cl_R_zerop.cc create mode 100644 src/real/format-output/Makeflags create mode 100644 src/real/format-output/TODO-format create mode 100644 src/real/format-output/cl_fmt_cardinal.cc create mode 100644 src/real/format-output/cl_fmt_floatstring.cc create mode 100644 src/real/format-output/cl_fmt_integer.cc create mode 100644 src/real/format-output/cl_fmt_newroman.cc create mode 100644 src/real/format-output/cl_fmt_oldroman.cc create mode 100644 src/real/format-output/cl_fmt_ordinal.cc create mode 100644 src/real/format-output/cl_fmt_paddedstring.cc create mode 100644 src/real/format-output/cl_fmt_scaleexp.cc create mode 100644 src/real/format-output/cl_fmt_tens.cc create mode 100644 src/real/format-output/cl_format.h create mode 100644 src/real/input/Makeflags create mode 100644 src/real/input/cl_R_from_string.cc create mode 100644 src/real/input/cl_R_read.cc create mode 100644 src/real/input/cl_R_read_stream.cc create mode 100644 src/real/misc/Makeflags create mode 100644 src/real/misc/cl_R_abs.cc create mode 100644 src/real/misc/cl_R_as.cc create mode 100644 src/real/misc/cl_R_contagion.cc create mode 100644 src/real/misc/cl_R_debug.cc create mode 100644 src/real/misc/cl_R_eqhashcode.cc create mode 100644 src/real/misc/cl_R_expt.cc create mode 100644 src/real/misc/cl_R_expt_I.cc create mode 100644 src/real/misc/cl_R_max.cc create mode 100644 src/real/misc/cl_R_min.cc create mode 100644 src/real/misc/cl_R_rational.cc create mode 100644 src/real/misc/cl_R_rationalize.cc create mode 100644 src/real/misc/cl_R_signum.cc create mode 100644 src/real/output/Makeflags create mode 100644 src/real/output/cl_R_aprint.cc create mode 100644 src/real/output/cl_R_bprint.cc create mode 100644 src/real/output/cl_R_cprint.cc create mode 100644 src/real/random/Makeflags create mode 100644 src/real/random/cl_R_random.cc create mode 100644 src/real/ring/Makeflags create mode 100644 src/real/ring/cl_R_ring.cc create mode 100644 src/real/transcendental/Makeflags create mode 100644 src/real/transcendental/cl_R_atan.cc create mode 100644 src/real/transcendental/cl_R_atan2.cc create mode 100644 src/real/transcendental/cl_R_cos.cc create mode 100644 src/real/transcendental/cl_R_cosh.cc create mode 100644 src/real/transcendental/cl_R_coshsinh.cc create mode 100644 src/real/transcendental/cl_R_cossin.cc create mode 100644 src/real/transcendental/cl_R_exp.cc create mode 100644 src/real/transcendental/cl_R_ln.cc create mode 100644 src/real/transcendental/cl_R_log.cc create mode 100644 src/real/transcendental/cl_R_sin.cc create mode 100644 src/real/transcendental/cl_R_sinh.cc create mode 100644 src/real/transcendental/cl_R_tan.cc create mode 100644 src/real/transcendental/cl_R_tanh.cc create mode 100644 src/timing/Makeflags create mode 100644 src/timing/cl_t_c1.cc create mode 100644 src/timing/cl_t_c2.cc create mode 100644 src/timing/cl_t_config.h.in create mode 100644 src/timing/cl_t_current.cc create mode 100644 src/timing/cl_t_current2.cc create mode 100644 src/timing/cl_t_d.cc create mode 100644 src/timing/cl_t_dec.cc create mode 100644 src/timing/cl_t_inc.cc create mode 100644 src/timing/cl_t_minus.cc create mode 100644 src/timing/cl_t_report.cc create mode 100644 src/timing/cl_t_td_minus.cc create mode 100644 src/timing/cl_t_td_plus.cc create mode 100644 src/vector/Makeflags create mode 100644 src/vector/cl_GV_I.cc create mode 100644 src/vector/cl_GV_I_copy.cc create mode 100644 src/vector/cl_GV_I_debug.cc create mode 100644 src/vector/cl_GV_io.h create mode 100644 src/vector/cl_GV_number.cc create mode 100644 src/vector/cl_GV_number_copy.cc create mode 100644 src/vector/cl_GV_number_debug.cc create mode 100644 src/vector/cl_SV_copy.cc create mode 100644 src/vector/cl_SV_io.h create mode 100644 src/vector/cl_SV_number.cc create mode 100644 src/vector/cl_SV_number_debug.cc create mode 100644 src/vector/cl_SV_ringelt.cc create mode 100644 src/vector/cl_SV_ringelt_debug.cc create mode 100644 src/vector/output/Makeflags create mode 100644 src/vector/output/cl_GV_number_aprint.cc create mode 100644 src/vector/output/cl_SV_aprint.cc create mode 100644 src/vector/output/cl_SV_number_aprint.cc create mode 100644 tests/.gdbinit create mode 100644 tests/FILES create mode 100644 tests/Makefile.in create mode 100644 tests/exam.cc create mode 100644 tests/exam.h create mode 100644 tests/exam_DF.cc create mode 100644 tests/exam_DF_div.cc create mode 100644 tests/exam_DF_floor.cc create mode 100644 tests/exam_DF_minus.cc create mode 100644 tests/exam_DF_mul.cc create mode 100644 tests/exam_DF_plus.cc create mode 100644 tests/exam_FF.cc create mode 100644 tests/exam_FF_div.cc create mode 100644 tests/exam_FF_floor.cc create mode 100644 tests/exam_FF_minus.cc create mode 100644 tests/exam_FF_mul.cc create mode 100644 tests/exam_FF_plus.cc create mode 100644 tests/exam_I.cc create mode 100644 tests/exam_I_div.cc create mode 100644 tests/exam_I_floor.cc create mode 100644 tests/exam_I_gcd.cc create mode 100644 tests/exam_I_minus.cc create mode 100644 tests/exam_I_mul.cc create mode 100644 tests/exam_I_plus.cc create mode 100644 tests/exam_I_sqrtp.cc create mode 100644 tests/exam_LF.cc create mode 100644 tests/exam_LF_div.cc create mode 100644 tests/exam_LF_floor.cc create mode 100644 tests/exam_LF_minus.cc create mode 100644 tests/exam_LF_mul.cc create mode 100644 tests/exam_LF_plus.cc create mode 100644 tests/exam_RA.cc create mode 100644 tests/exam_RA_div.cc create mode 100644 tests/exam_RA_floor.cc create mode 100644 tests/exam_RA_minus.cc create mode 100644 tests/exam_RA_mul.cc create mode 100644 tests/exam_RA_plus.cc create mode 100644 tests/exam_SF.cc create mode 100644 tests/exam_SF_div.cc create mode 100644 tests/exam_SF_floor.cc create mode 100644 tests/exam_SF_minus.cc create mode 100644 tests/exam_SF_mul.cc create mode 100644 tests/exam_SF_plus.cc create mode 100644 tests/main.cc create mode 100644 tests/test.h create mode 100644 tests/test_I.cc create mode 100644 tests/test_I.h create mode 100644 tests/test_I_GV.cc create mode 100644 tests/test_I_abs.cc create mode 100644 tests/test_I_ash.cc create mode 100644 tests/test_I_boole.cc create mode 100644 tests/test_I_compare.cc create mode 100644 tests/test_I_div.cc create mode 100644 tests/test_I_dpb.cc create mode 100644 tests/test_I_dpf.cc create mode 100644 tests/test_I_evenp.cc create mode 100644 tests/test_I_gcd.cc create mode 100644 tests/test_I_ilength.cc create mode 100644 tests/test_I_isqrt.cc create mode 100644 tests/test_I_ldb.cc create mode 100644 tests/test_I_ldbtest.cc create mode 100644 tests/test_I_logand.cc create mode 100644 tests/test_I_logandc1.cc create mode 100644 tests/test_I_logandc2.cc create mode 100644 tests/test_I_logbitp.cc create mode 100644 tests/test_I_logcount.cc create mode 100644 tests/test_I_logeqv.cc create mode 100644 tests/test_I_logior.cc create mode 100644 tests/test_I_lognand.cc create mode 100644 tests/test_I_lognor.cc create mode 100644 tests/test_I_lognot.cc create mode 100644 tests/test_I_logorc1.cc create mode 100644 tests/test_I_logorc2.cc create mode 100644 tests/test_I_logtest.cc create mode 100644 tests/test_I_logxor.cc create mode 100644 tests/test_I_minus.cc create mode 100644 tests/test_I_minus1.cc create mode 100644 tests/test_I_mkf.cc create mode 100644 tests/test_I_mul.cc create mode 100644 tests/test_I_oddp.cc create mode 100644 tests/test_I_ord2.cc create mode 100644 tests/test_I_plus.cc create mode 100644 tests/test_I_plus1.cc create mode 100644 tests/test_I_power2p.cc create mode 100644 tests/test_I_sqrtp.cc create mode 100644 tests/test_I_xgcd.cc create mode 100644 tests/test_MI.cc create mode 100644 tests/test_MI.h create mode 100644 tests/test_MI_canonhom.cc create mode 100644 tests/test_MI_div.cc create mode 100644 tests/test_MI_expt.cc create mode 100644 tests/test_MI_minus.cc create mode 100644 tests/test_MI_mul.cc create mode 100644 tests/test_MI_plus.cc create mode 100644 tests/test_MI_recip.cc create mode 100644 tests/test_nt.cc create mode 100644 tests/test_nt.h create mode 100644 tests/test_nt_jacobi.cc create mode 100644 tests/tests.cc create mode 100644 tests/timeLFRAmul.cc create mode 100644 tests/timeLFatan-compare.cc create mode 100644 tests/timeLFatan.cc create mode 100644 tests/timeLFatanh-compare.cc create mode 100644 tests/timeLFatanh.cc create mode 100644 tests/timeLFcos-compare.cc create mode 100644 tests/timeLFcos.cc create mode 100644 tests/timeLFcosh.cc create mode 100644 tests/timeLFexp-compare.cc create mode 100644 tests/timeLFexp.cc create mode 100644 tests/timeLFln-compare.cc create mode 100644 tests/timeLFln.cc create mode 100644 tests/timeLFsin-compare.cc create mode 100644 tests/timeLFsin.cc create mode 100644 tests/timeLFsinh.cc create mode 100644 tests/timeLFsqrt.cc create mode 100644 tests/timeMImisc5.cc create mode 100644 tests/timeMIpow2div.cc create mode 100644 tests/timeMIpow2recip.cc create mode 100644 tests/timeRALFdiv.cc create mode 100644 tests/timeRAtoLF.cc create mode 100644 tests/timeUPMImul.cc create mode 100644 tests/timecatalan.cc create mode 100644 tests/timediv.cc create mode 100644 tests/timediv2adic-compare.cc create mode 100644 tests/timediv2adic.cc create mode 100644 tests/timeeuler.cc create mode 100644 tests/timeexp1.cc create mode 100644 tests/timefact.cc create mode 100644 tests/timegcd.cc create mode 100644 tests/timemul-compare.cc create mode 100644 tests/timemul.cc create mode 100644 tests/timepi.cc create mode 100644 tests/timepi.out2-i486 create mode 100644 tests/timepi.out2-i586 create mode 100644 tests/timeprint-compare.cc create mode 100644 tests/timeprint.cc create mode 100644 tests/timerecip2adic-compare.cc create mode 100644 tests/timerecip2adic.cc create mode 100644 tests/timesqrt.cc create mode 100644 tests/timesqrtmodp.cc create mode 100644 tests/timesquare.cc create mode 100644 tests/timezeta3.cc diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..12065f3 --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, 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 software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, 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 show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, 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 redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +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 give any other recipients of the Program a copy of this License +along with the Program. + +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 Program or any portion +of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +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 Program, 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 Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) 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; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, 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 executable. 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. + +If distribution of executable or 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 counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program 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. + + 5. 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 Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program 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. + + 7. 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 Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program 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 Program. + +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. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program 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. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 Program +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 Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, 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 + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. 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. + + + Copyright (C) 19yy + + 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. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..01e809c --- /dev/null +++ b/ChangeLog @@ -0,0 +1,294 @@ +2000-01-13 Richard Kreckel + + * Version 1.0.3 released. + +2000-01-13 Richard Kreckel + + * src/base/cl_macros.h (nonreturning_function): For egcs and newer + use __attribute__ ((__noreturn__)) instead of the __volatile__ + storage class. + (nonreturning): Remove macro. + * include/*: Minor fixes to stop -ansi -pedantic from complaining. + * include/cl_integer.h: (doublefactorial): New declaration. + * src/integer/misc/combin/cl_I_doublefactorial.cc: New file. + +1999-12-18 Bruno Haible + + * autoconf/acgeneral.m4 (AC_ARG_PROGRAM): Create conftestsed using + "cat", not "echo". + * autoconf/ltconfig: Improve support for recent FreeBSD 3. + * include/cl_GV.h (cl_GV_vectorops): Change return type from 'T' to + 'const T', to match definition in src/vector/cl_GV_number.cc. + Reported by Duncan Simpson . + * gmp/mpn/Makefile.in (.S.lo): Use 'if', not '&&', because '&&' may + yield return code 1. + +1999-09-07 Bruno Haible + + * Version 1.0.2 released. + +1999-09-06 Bruno Haible + + * src/rational/cl_RA.h (integerp, ratiop): Instead of returning a + boolean expression, write alternatives ending with either + "return cl_true;" or "return cl_false;". This way, g++ does a + better job inlining it. + * src/float/cl_F.h (longfloatp): Likewise. + * src/real/cl_R.h (rationalp, integerp, floatp): Likewise. + * src/complex/cl_C.h (realp, complexp): Likewise. + +1999-09-05 Bruno Haible + + * include/cl_integer.h (cl_equal_hashcode): New declaration. + * include/cl_rational.h (cl_equal_hashcode): New declaration. + * include/cl_sfloat.h (cl_equal_hashcode): New declaration. + * include/cl_ffloat.h (cl_equal_hashcode): New declaration. + * include/cl_dfloat.h (cl_equal_hashcode): New declaration. + * include/cl_lfloat.h (cl_equal_hashcode): New declaration. + * include/cl_float.h (cl_equal_hashcode): New declaration. + * include/cl_real.h (cl_equal_hashcode): New declaration. + * include/cl_complex.h (cl_equal_hashcode): New declaration. + * src/base/cl_N.h (equal_hashcode_low, equal_hashcode_one): New macros. + * src/integer/misc/cl_I_eqhashcode.cc: New file. + * src/rational/misc/cl_RA_eqhashcode.cc: New file. + * src/float/sfloat/misc/cl_SF_eqhashcode.cc: New file. + * src/float/ffloat/misc/cl_FF_eqhashcode.cc: New file. + * src/float/dfloat/misc/cl_DF_eqhashcode.cc: New file. + * src/float/lfloat/misc/cl_LF_eqhashcode.cc: New file. + * src/float/misc/cl_F_eqhashcode.cc: New file. + * src/real/misc/cl_R_eqhashcode.cc: New file. + * src/complex/misc/cl_C_eqhashcode.cc: New file. + * doc/cln.tex: Document `cl_equal_hashcode'. + +1999-09-05 Bruno Haible + + * include/cl_ring.h (cl_number_ring_ops): Add `contains' member. + (cl_number_ring): New class. + (cl_specialized_number_ring): Inherit from cl_number_ring. + (instanceof): New function. + * src/integer/ring/cl_I_ring.cc (cl_I_p): New function. + * src/integer/misc/cl_I_as.cc (cl_I_p): Add comment. + * src/rational/ring/cl_RA_ring.cc (cl_RA_p): New function. + * src/rational/misc/cl_RA_as.cc (cl_RA_p): Add comment. + * src/real/ring/cl_R_ring.cc (cl_R_p): New function. + * src/real/misc/cl_R_as.cc (cl_R_p): Add comment. + * src/complex/ring/cl_C_ring.cc (cl_N_p): New function. + * src/complex/misc/cl_N_as.cc (cl_N_p): Add comment. + * doc/cln.tex: Document `instanceof'. + +1999-09-05 Bruno Haible + + * include/cl_rational.h (numerator, denominator): New declarations. + * src/rational/elem/cl_RA_numerator.cc: New file. + * src/rational/elem/cl_RA_denominator.cc: New file. + * include/cl_integer.h (numerator, denominator): New inline functions. + * doc/cln.tex: Document `numerator' and `denominator'. + +1999-09-05 Bruno Haible + + * src/rational/algebraic/cl_RA_rootp.cc (rootp): Fix endless loop + in the integer case. + * src/rational/algebraic/cl_RA_rootp_I.cc (rootp): Likewise. + +1999-09-05 Bruno Haible + + * include/cl_config.h.in: Support for sparc64 CPU. + * include/cl_modules.h: Likewise. + * include/cl_types.h: Likewise. + * include/cl_object.h: Likewise. + * include/cl_GV.h: Likewise. + * src/Makefile.in: Likewise. + * src/base/cl_alloca.h: Likewise. + * src/base/cl_macros.h: Likewise. + * src/base/cl_sysdep.h: Likewise. + * src/base/cl_low.h: Likewise. + * src/base/digitseq/cl_asm.h: Likewise. + * src/base/digitseq/cl_asm_.cc: Likewise. + * src/base/digitseq/cl_asm_sparc64.h: New file. + * src/base/digitseq/cl_asm_sparc64_.cc: New file. + * src/modinteger/cl_MI_int.h: Support for sparc64 CPU. + * src/polynomial/elem/cl_UP_no_ring.cc: Likewise. + * src/polynomial/elem/cl_UP_GF2.h: Likewise. + * src/polynomial/elem/cl_asm_GF2.cc: Likewise. + +1999-09-04 Bruno Haible + + * src/base/digitseq/cl_asm_sparc_.cc (orc2_loop_up, orc2_loop_down): + Use the `orn' instruction. + +1999-08-14 Bruno Haible + + Assume all platforms have and clock_t. + * configure.in: Don't call CL_STDLIB_H and CL_CLOCK_T. + * src/base/cl_base_config.h.in (CLOCK_T): Remove definition. + * src/base/random/cl_random_from.cc: Use clock_t instead of CLOCK_T. + * src/timing/cl_t_config.h.in (CLOCK_T): Remove definition. + * src/timing/cl_t_current2.cc: Use clock_t instead of CLOCK_T. + +1999-07-18 Bruno Haible + + * gmp/config.guess: Link to autoconf/config.guess. + gmp/config.sub: Link to autoconf/config.sub. + Needed for Win32 platforms. + +1999-07-17 Bruno Haible + + * autoconf/aclocal.m4 (CL_CANONICAL_HOST_CPU): Distinguish "sparc" and + "sparc64" according to the C compiler, not the uname result. + +1999-06-17 Bruno Haible + + * src/base/digitseq/cl_asm_sparc_.cc (compare_loop_up): Fix + COUNTER_LOOPS version, fortunately not used yet. + + * include/cl_modules.h: Prepare for gcc version 3. + +1999-06-12 Bruno Haible + + * src/rational/elem/cl_RA_plus.cc, src/rational/elem/cl_RA_minus.cc: + Change the last call from I_I_to_RT to I_I_to_RA. + +1999-06-09 Bruno Haible + + * Version 1.0.1 released. + +1999-06-09 Bruno Haible + + * src/integer/cl_I.h (pFN_maxlength_digits_at): Define also when + intDsize==64. + +1999-06-08 Bruno Haible + + * autoconf/intparam.c (printf_underscored): Change argument type to + `const char*'. + * include/cl_modules.h (CL_OUTPUT_LABEL, CL_JUMP_TO): New macros. + (CL_PROVIDE, CL_PROVIDE_END): Use them. + * include/cl_string.h (cl_heap_string::operator new): Return 1, not 0. + * include/cl_GV.h (cl_GV_inner::operator new): Likewise. + * src/base/ring/cl_no_ring.cc (dummy_canonhom, dummy_expt_pos): Don't + cast a cl_I to void here. Works around a bug in g++-2.95. + * src/complex/misc/cl_C_class.cc: Include "cl_C.h". + * src/polynomial/elem/cl_UP_no_ring.cc (dummy_canonhom, + dummy_expt_pos): Don't cast a cl_I to void here. Works around a bug + in g++-2.95. + * src/polynomial/elem/cl_asm_sparc_GF2.cc (DECLARE_FUNCTION): New + macro. + * src/rational/misc/cl_RA_class.cc: Include "cl_RA.h". + * src/vector/cl_GV_I.cc (cl_heap_GV_I_general::operator new, + DEFINE_cl_heap_GV_I_bits): Return 1, not 0. + * src/vector/cl_GV_number.cc (cl_heap_GV_number_general::operator new): + Likewise. + +1999-06-01 Bruno Haible + + * autoconf/aclocal.m4 (CL_CANONICAL_HOST_CPU): Canonicalize alpha + variants to alpha. + +1999-05-29 Bruno Haible + + * src/base/digitseq/cl_asm_i386_.cc (DECLARE_FUNCTION): Treat + OpenBSD like NetBSD. + * src/base/digitseq/cl_asm_sparc_.cc (DECLARE_FUNCTION): Likewise. + * src/base/digitseq/cl_asm_m68k_.cc (DECLARE_FUNCTION): Treat + OpenBSD like NetBSD, and Linux/ELF like SVR4. + +1999-05-16 Bruno Haible + + * src/base/cl_low.h (integerlength32) [__rs6000__]: Use old assembler + syntax on AIX systems and new assembler syntax on non-AIX systems. + +1999-05-01 Bruno Haible + + * autoconf/config.guess, autoconf/config.sub: Upgrade to newest + version from GNU CVS. + +1999-04-24 Bruno Haible + + * src/integer/bitwise/cl_I_logand.cc (logand): Optimize the case when + either operand is a positive fixnum, O(1) instead of O(N). + * src/integer/bitwise/cl_I_lognand.cc (lognand): Likewise. + * src/integer/bitwise/cl_I_logandc2.cc (logandc2): Likewise for the + first operand. + +1999-04-14 Bruno Haible + + * autoconf/aclocal.m4 (CL_GLOBAL_CONSTRUCTORS): Add check whether + ctor/dtor needs to be exported. + * include/cl_config.h.in (CL_NEED_GLOBALIZE_CTORDTOR): New macro. + * include/cl_modules.h (CL_GLOBALIZE_JUMP_LABEL): Renamed from + CL_GLOBALIZE_LABEL. + (CL_GLOBALIZE_LABEL): New macro. + (CL_GLOBALIZE_CTORDTOR_LABEL): Renamed from CL_GLOBALIZE_ASM_LABEL. + (CL_PROVIDE): Update. + +1999-04-12 Bruno Haible + + * src/Makefile.in ($(ASMFILES_S)): On HPPA, ignore preprocessing + errors ("unterminated string or character constant"). + ($(ASMFILES_LO)): On HPPA, try with various settings of + COMPILER_PATH, in order to try /usr/ccs/bin/as and /bin/as. + +1999-04-11 Bruno Haible + + * INSTALL: Mention gmp problems on MIPS. + * doc/cln.tex: Likewise. + +1999-03-24 Mumit Khan + + * src/Makefile.in (SUBDIRS): Filter out CVS and RCS directories from + the source tree. + * include/cl_modules.h (CL_GLOBALIZE_LABEL): Define for Win32. + (CL_GLOBALIZE_ASM_LABEL): New macro. + (CL_PROVIDE): Use it. + * src/base/random/cl_random_from.cc: Handle WIN32. + * src/timing/cl_t_current.cc: Likewise. + +1999-03-15 Bruno Haible + + * autoconf/intparam.c (main7): Use %lX instead of %X for a `long'. + (main8): Adapt for C++. + +1999-03-09 Bruno Haible + + * INSTALL: Mention egcs-1.1 problems on Sparc. + * doc/cln.tex: Likewise. + +1999-03-08 Bruno Haible + + * autoconf/aclocal.m4 (CL_FPU_CONTROL): Fix the "checking for" + messages. + +1999-02-25 Bruno Haible + + * autoconf/aclocal.m4: In test programs, declare `int main()', not + `main()'. + + * lidia-interface/src/interfaces/integers/cln/bigint.c + (bigint_to_string): Fix for negative arguments. + + * src/base/cl_low.h: Check for `__sparc__', not `SPARC'. + * src/base/cl_alloca.h: Likewise. + + * src/base/cl_low.h: Eliminate CLISP style "# " comments. + * src/base/digitseq/cl_asm_arm_.cc, + src/base/digitseq/cl_asm_mips_.cc, + src/float/dfloat/elem/cl_DF_mul.cc: Likewise. + + * src/modinteger/cl_MI_pow2.h, + src/modinteger/cl_MI_pow2m1.h, + src/modinteger/cl_MI_pow2p1.h: Workaround g++-2.7.2 inlining bug. + +1999-01-18 Bruno Haible + + * autoconf/acgeneral.m4, + autoconf/acspecific.m4: Upgrade to autoconf-2.13. + * autoconf/config.guess, autoconf/config.sub: Likewise. + * autoconf/aclocal.m4 (CL_ALLOCA): Test for _MSC_VER and alloca being + a macro. Use ${ac_objext}. + * src/base/cl_macros.h (alloca): Put _MSC_VER test before the others, + conforming with CL_ALLOCA. + +1999-01-12 Bruno Haible + + * Version 1.0 released. + diff --git a/FILES b/FILES new file mode 100644 index 0000000..2b7a438 --- /dev/null +++ b/FILES @@ -0,0 +1,57 @@ +Files in this package: + + Documentation: + + README this text + COPYING free software license + doc/ documentation in texinfo, html, info, dvi, ps formats + + Source files: + src/ + + gmp slimmed down version of GNU gmp-2.0.2 + (optional) + base base routines of all of CLN + (mandatory) + integer integer numbers + (mandatory) + rational rational numbers + (needs integer) + float floating-point numbers + (needs integer, rational) + real real numbers + (needs integer, rational, float) + complex complex numbers + (needs integer, rational, float, real) + modinteger integers modulo n + (needs integer) + vector vectors + (needs integer, rational, float, real, complex) + polynomial polynomials + (needs integer, modinteger, vector) + modpolynomial polynomials modulo a given polynomial + (not yet implemented) + numtheory number theory functions + (needs integer, real) + timing timing routines + (standalone) + + Include files + include/ + + Sample programs + examples/ + + Sample programs used for tuning + benchmarks/ + + Verification tests: + tests/exam* tests for specific input (like a pupils' exam) + tests/test* coherence tests, for random input + + Installation: + + configure configuration script + configure.in autoconf-2.13 source for the configuration script + autoconf/* auxiliary configuration scripts + Makefile.in Makefile master diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..2afb7d1 --- /dev/null +++ b/INSTALL @@ -0,0 +1,40 @@ +Installation: +============= + +As with any autoconfiguring GNU software, installation is as easy as this: + +$ ./configure +$ make +$ make check +$ make install + +You need GNU make. On HP-UX, you also need GNU sed. + +Known to work with: + - Linux/x86, gcc-2.7.0, gcc-2.7.2, gcc-2.8.0, egcs-1.1 + - Solaris 2.4 (sparc), gcc-2.7.0, gcc-2.7.2, egcs-1.1 + - OSF/1 V4.0 (alpha), egcs-1.1 + - Irix 5.3, CC 4 + +The "make" step takes about 4 hours, on a 486 DX / 33 MHz / 8 MB. + +On Linux, g++ needs 15 MB to compile the tests. So better have +17 MB swap space and 1 MB room in $TMPDIR. + +If you use gcc and g++ version 2.7.x, don't add -O2 to the CXXFLAGS, because +"g++ -O" generates better code for libcln.a than "g++ -O2". + +If you use g++ version 2.8.x or egcs-2.91.x (a.k.a. egcs-1.1) or gcc-2.95.x, +I recommend adding "-fno-exceptions" to the CXXFLAGS. This will likely +generate better code. + +If you use g++ version egcs-2.91.x (egcs-1.1) or gcc-2.95.x on Sparc, add +either "-O" or "-O2 -fno-schedule-insns" to the CXXFLAGS. With full "-O2", +g++ miscompiles the division routines. Also, for --enable-shared to work, you +need egcs-1.1.2 or newer. + +On MIPS (SGI Irix 6), pass option "--without-gmp" to configure. gmp does +not work when compiled in "n32" binary format on Irix. + +More detailed installation instructions can be found in the documentation, +in the doc/ directory. diff --git a/INSTALL.generic b/INSTALL.generic new file mode 100644 index 0000000..f8d09bd --- /dev/null +++ b/INSTALL.generic @@ -0,0 +1,161 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the documentation so they +can be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes a while. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, `cd' to the directory where you want the +object files and executables to go and run the `configure' script. +`configure' automatically checks for the source code in the directory +that `configure' is in and in `..'. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--with-gmp' +`--without-gmp' + CLN builds upon GNU gmp by default. If you encounter problems + relating to gmp, try configuring without gmp. + +`configure' also accepts some other, not widely useful, options. + diff --git a/Makefile.devel b/Makefile.devel new file mode 100644 index 0000000..37eac94 --- /dev/null +++ b/Makefile.devel @@ -0,0 +1,48 @@ +# This is the developer's makefile, not the user's makefile. +# Don't use it unless you know exactly what you do! + + +# Some important programs: +SHELL = /bin/sh +MAKE = make + + +# GNU tar together with GNU gzip. Excellent performance. +PACK = tar +PACKOPT = cvfhz +PACKEXT = .tar.z + + +all : configures documentation + + +CONFIGURES = configure +CONFIGURES_IN = configure.in + +AUTOCONF_FILES = autoconf/aclocal.m4 autoconf/acgeneral.m4 autoconf/acspecific.m4 + +configures : $(CONFIGURES) + +configure : configure.in $(AUTOCONF_FILES) + autoconf/autoconf -m autoconf + +# ACLOCAL = /home/bruno/clisp/src/autoconf/aclocal.m4 +# ACSELECT = /home/bruno/clisp/src/autoconf/acselect +# OTHERMACROS = /home/bruno/clisp/src/autoconf/libtool.m4 +ACLOCAL = /home/kreckel/contrib/src/clisp/src/autoconf/aclocal.m4 +ACSELECT = /home/kreckel/contrib/src/clisp/src/autoconf/acselect +OTHERMACROS = /home/kreckel/contrib/src/clisp/src/autoconf/libtool.m4 + +autoconf/aclocal.m4 : $(ACLOCAL) + ($(ACSELECT) `cat $(CONFIGURES_IN) | grep '^[A-Z][A-Z]_' | sed 's,[^A-Z_].*$$,,g' | sort | uniq` < $(ACLOCAL) ; cat $(OTHERMACROS) | sed -e 's,AC_CANONICAL_HOST,CL_CANONICAL_HOST,g' -e 's,AC_PROG_RANLIB,CL_PROG_RANLIB,g') > autoconf/aclocal.m4 + +# Syntaxcheck +check-configures : $(CONFIGURES) + set -e; for f in $(CONFIGURES); do bash -x -n $$f; done + + +documentation : force + cd doc && $(MAKE) -f Makefile.devel documentation + +force : + diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..65fbfd6 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,63 @@ +# Makefile for cln + +#### Start of system configuration section. #### + +# Directories used by "make install": +prefix = @prefix@ +local_prefix = /usr/local +exec_prefix = @exec_prefix@ +datadir = @datadir@ +libdir = @libdir@ +includedir = @includedir@ +mandir = @mandir@ + +# Programs used by "make": +CC = @CC@ +CFLAGS = @CFLAGS@ +RM = rm -f +@SET_MAKE@ + +#### End of system configuration section. #### + +SHELL = /bin/sh + +all : force + if test -f gmp/Makefile; then cd gmp && $(MAKE) mpn/libmpn.la mp_clz_tab.lo CC='$(CC)' CFLAGS='$(CFLAGS)' LIBTOOL=../libtool; fi + cd @subdir@; $(MAKE) all + +install : force + cd @subdir@; $(MAKE) install + +installdirs : force + cd @subdir@; $(MAKE) installdirs + +uninstall : force + cd @subdir@; $(MAKE) uninstall + +check : force + cd @subdir@; $(MAKE) check + +mostlyclean : force + if test -f gmp/Makefile; then cd gmp; $(MAKE) mostlyclean; fi + cd @subdir@; $(MAKE) mostlyclean + +clean : force + if test -f gmp/Makefile; then cd gmp; $(MAKE) clean; fi + cd @subdir@; $(MAKE) clean + +distclean : force + if test -f gmp/Makefile; then cd gmp; $(MAKE) distclean; fi + cd @subdir@; if test -f Makefile; then $(MAKE) distclean; fi + $(RM) config.status config.log config.cache Makefile + $(RM) libtool + $(RM) include/cl_config.h include/cl_intparam.h include/cl_floatparam.h src/base/cl_base_config.h src/base/cl_gmpconfig.h src/float/cl_float_config.h src/timing/cl_t_config.h + +maintainer-clean : force + if test -f gmp/Makefile; then cd gmp; $(MAKE) maintainer-clean; fi + cd @subdir@; if test -f Makefile; then $(MAKE) maintainer-clean; fi + $(RM) config.status config.log config.cache Makefile + $(RM) libtool + $(RM) include/cl_config.h include/cl_intparam.h include/cl_floatparam.h src/base/cl_base_config.h src/base/cl_gmpconfig.h src/float/cl_float_config.h src/timing/cl_t_config.h + +force : + diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..1c4c6ce --- /dev/null +++ b/NEWS @@ -0,0 +1,479 @@ +2000-01-13, version 1.0.3 +========================= + +Functional changes +------------------ + +* New function + `cl_I doublefactorial (uintL n)'. + +Implementation changes +---------------------- + +* Fix several little configuration errors. + +* Fix some compilation errors with gcc-2.96 prereleases. + + +1999-09-07, version 1.0.2 +========================= + +Functional changes +------------------ + +* New functions + `cl_I numerator (const cl_RA&)' + `cl_I denominator (const cl_RA&)'. + Suggested by Richard Kreckel and Sylvain Pion. + +* New function `cl_equal_hashcode' for the classes cl_N, cl_R, cl_RA, cl_I, + cl_F, cl_SF, cl_FF, cl_DF, cl_LF. + Suggested by Richard Kreckel. + +Implementation changes +---------------------- + +* Fix an endless loop when either of the functions + `cl_boolean rootp (const cl_RA&, uintL, cl_RA*)', + `cl_boolean rootp (const cl_RA&, const cl_I&, cl_RA*)' + was called with an integer argument. Thanks to Richard Kreckel. + +* Fix a bug in the addition and subtraction of rational numbers which could + cause unnormalized rational numbers like 3/1 to be created. + + +1999-06-09, version 1.0.1 +========================= + +Algorithmic changes +------------------- + +* Speed up the functions `logand', `lognand', `logandc2'. + +Implementation changes +---------------------- + +* Fix compilation errors with gcc-2.7.2, egcs-1.1.2 and gcc-2.95. + +* Fix compilation errors on HPPA, MIPS, some versions of DEC Alpha, OpenBSD, + and SPARC with LiDIA. + +* Fix compilation errors on Win32. Thanks to Mumit Khan. + + +1999-01-12, version 1.0 +======================= + +Functional changes +------------------ + +* New include files, containing I/O functions: + + + + + + + The file now contains only I/O functions for characters and + C integers. + +* To access the base ring of a univariate polynomial ring, now use + `R->basering()' instead of `R->basering'. + +* Implement `plusp', `max', `min' for the classes cl_F, cl_SF, cl_FF, cl_DF, + cl_LF, cl_RA, cl_I. + +* Implement `abs' for the class cl_RA. + +* Replaced `read_number' with specialized functions `read_complex', + `read_real', `read_float', `read_rational', `read_integer'. + +* Replaced the functions + `void fprint (cl_ostream stream, int x)' + `void fprint (cl_ostream stream, unsigned int x)' + `void fprint (cl_ostream stream, long x)' + `void fprint (cl_ostream stream, unsigned long x)' + with + `void fprintdecimal (cl_ostream stream, int x)' + `void fprintdecimal (cl_ostream stream, unsigned int x)' + `void fprintdecimal (cl_ostream stream, long x)' + `void fprintdecimal (cl_ostream stream, unsigned long x)' + +Algorithmic changes +------------------- + +* The function `cl_I xgcd (const cl_I& a, const cl_I& b, cl_I* u, cl_I* v)' + now normalizes the resulting u and v to be of minimum absolute value. + (Suggested by the LiDIA group.) + +* The conversion from string to cl_F, cl_R, cl_N now chooses the format of + the resulting float depending on the number of significant digits present + in the input string. + +* Speed up the functions + `cl_R operator* (const cl_RA&, const cl_LF&)' + `cl_R operator* (const cl_LF&, const cl_RA&)' + `cl_R operator/ (const cl_RA&, const cl_LF&)' + `cl_LF operator/ (const cl_LF&, const cl_RA&)' + +Implementation changes +---------------------- + +* Fix for `cl_I ash (const cl_I& x, const cl_I& n)' when |n| is between + 2^29 and 2^37. + (Reported by Thomas Papanikolaou.) + +* Fixed a memory leak in the long-float truncate function. + (Reported by Keith Briggs.) + +* Fixed a memory leak in the modular integer exponentiation. + +* Reduced the stack space consumption. The default stack size (typically + 8 MB on Unix) should now be sufficient in order to run all CLN programs. + +* Portability fixes for m68k platforms. + (Reported and fixed by Roman Hodek.) + +Other changes +------------- + +* Restructured the sources. The subpackages + - base + - base + integer + - base + integer + rational + - base + integer + rational + float + - base + integer + rational + float + real + - base + integer + rational + float + real + complex + - base + integer + modinteger + are now self-contained. + +* The configuration script can be called with option `--enable-shared', + to build CLN as a shared library. + +* Updated the LiDIA interface. + + +1998-05-07, version 0.98 +======================== + +Implementation changes +---------------------- + +* Portability fixes for 64-bit platforms like DEC Alpha. + (Reported by John Cremona and Thomas Papanikolaou.) + + +1998-02-27 +========== + +Other changes +------------- + +* Portability fixes for new ISO/ANSI C++ compilers. + +* Updated the LiDIA interface for LiDIA version 1.3 and fixed a couple of + bugs. + + +1997-09-06 +========== + +Implementation changes +---------------------- + +* Portability fix for i686 platforms. + (Reported by Michael Pfeifer.) + + +1997-09-01 +========== + +Functional changes +------------------ + +* New include files: + , declaring general rings, + , , defining vectors, + , defining univariate polynomial rings. + +Algorithmic changes +------------------- + +* Speed up the internal computation of ln(2) and ln(10) by about 20%. + +* Speed up the computation of exp (for 1000 digits or more) by about 10%. + +Implementation changes +---------------------- + +* Portability fix for 64-bit platforms like DEC Alpha: + Fixed a bug: endless loop in `sqrt' for large precision. + (Reported by Blake Jones.) + +* Portability fix for RS/6000 platforms. + + +1997-02-21 +========== + +Algorithmic changes +------------------- + +* Speed up the computation of the elementary transcendental functions: + exp, sinh, cosh, asinh, atanh (for 100 digits) by about 30%, + log (for 100 digits) by about 25%, + sin, cos (for 1000 or 10000 digits) by about 20%, + asin, acos, atan (for 1000 digits) by about 25%. + +Implementation changes +---------------------- + +* Portability fix for SunOS 4 and other BSD platforms. + + +1997-01-31 +========== + +Algorithmic changes +------------------- + +* Fixed a bug: endless recursion in `cl_boolean sqrtp (const cl_RA&, cl_RA*)'. + +* Fixed a bug: Only the first 85% of the digits returned by `cl_eulerconst' + for moderate precision (< 11370 digits) were correct. + (Reported by Thomas Papanikolaou.) + +Implementation changes +---------------------- + +* Fix static initialization order bug. Requires g++ 2.7.0 or newer + (g++ 2.8.0 or newer on HPPA). + +* New method `debug_print()', for pretty printing of CLN objects, intended + to be called from the debugger. + + +1997-01-07 +========== + +Functional changes +------------------ + +* New functions `float cl_float_approx (const cl_R&)', + `double cl_double_approx (const cl_R&)' + for converting a real number to a C `float' or `double'. + +Algorithmic changes +------------------- + +* Speed up `cl_zeta' using Cohen-Villegas-Zagier convergence acceleration. + +Implementation changes +---------------------- + +* New function `cl_print', for pretty printing of CLN objects, intended to be + called from the debugger. + +* Portability fixes for 64-bit platforms like DEC Alpha. + + +1996-11-29 +========== + +Functional changes +------------------ + +* New include files: + , defining strings, + , defining symbols, + , defining property lists, + , defining conditions/exceptions. + +* New functions `cl_F cl_catalanconst ()', + `cl_F cl_catalanconst (const cl_F&)', + `cl_F cl_catalanconst (cl_float_format_t)' + which return Catalan's constant. + (Suggested by Thomas Papanikolaou.) + +* New functions `cl_F cl_zeta (int s)', + `cl_F cl_zeta (int s, const cl_F&)', + `cl_F cl_zeta (int s, cl_float_format_t)' + which return the Riemann zeta function at an integral point s>1. + +* New functions `cl_F cl_exp1 ()', + `cl_F cl_exp1 (const cl_F&)', + `cl_F cl_exp1 (cl_float_format_t)' + which return e = exp(1). + +* New function `cl_I binomial (uintL n, uintL k)' which returns the + binomial coefficient (n choose k). + +* New functions `int cl_I_to_int (const cl_I&)', + `unsigned int cl_I_to_uint (const cl_I&)', + `long cl_I_to_long (const cl_I&)', + `unsigned long cl_I_to_ulong (const cl_I&)' + for converting an integer to a C `int' or `long'. + +* New functions `float cl_float_approx (const cl_I&)', + `float cl_float_approx (const cl_RA&)', + `double cl_double_approx (const cl_I&)', + `double cl_double_approx (const cl_RA&)' + for converting a rational number to a C `float' or `double'. + +Implementation changes +---------------------- + +* Moved the sources to subdirectories. + (Suggested by Jörg Arndt.) + +Other changes +------------- + +* New benchmark for better comparing LiDIA, Pari and CLN. + +* Added an interface to LiDIA, allows using CLN as a replacement of libI. + (Suggested by Thomas Papanikolaou.) + +* Added an ILOG Talk interface, for interactive use of the library. + + +1996-10-13 +========== + +Functional changes +------------------ + +* New include file , defining modular integer rings. + +* New functions `cl_F cl_eulerconst ()', `cl_F cl_eulerconst (const cl_F&)', + `cl_F cl_eulerconst (cl_float_format_t)' which return Euler's constant. + +Algorithmic changes +------------------- + +* Speed up square root of large numbers by use of Newton's algorithm. + +* Speed up multiplication and division of large long-floats by small integers. + +* Speed up the computation of pi, e, exp, log, sin, cos, tan, sinh, cosh, tanh, + asin, acos, atan, asinh, acosh, atanh. + All of them are now computed with asymptotically fast algorithms, of + bit complexity O(log(N)^2*M(N)) = O(N^(1+epsilon)) for N digits. + +* Fixed several bugs in the transcendental functions routines. In particular, + the `log' function went into an endless loop. + +* Fixed a bug: The cl_I -> cl_DF and cl_I -> cl_LF conversions didn't work + correctly for negative integers. + + +1996-09-08 +========== + +Functional changes +------------------ + +* New include file , containing number theoretic functions, + for now only the Jacobi symbol. + +Algorithmic changes +------------------- + +* Speed up squaring of large numbers by 30%. + +* Speed up division of large numbers by use of Newton's algorithm. The + improvement is noticeable for numbers with at least about 1000 words = + 32000 bits = 10000 decimal digits. + +* Speed up the binary-to-decimal conversion of large numbers by use of + a divide-and-conquer method. The improvement is noticeable for numbers + of at least 1250 words = 40000 bits = 12000 decimal digits. + +* Fixed a bug: The functions `cl_boolean minusp (const type&)' and + `cl_boolean zerop (const type&)' were missing for type=cl_I and type=cl_RA. + +* Fixed a bug: The function `cl_boolean logtest (const cl_I&, const cl_I&)' + didn't work correctly if both arguments were bignums. + +* Fixed a bug: The function `cl_I mod (const cl_I&, const cl_I&)', when called + as `mod(-n*m,m)' (n>0), returned m instead of 0. + +* Fixed a bug: The function `uintL power2p (const cl_I&)' returned wrong + values for arguments x = 2^n, n >= 29. + +Implementation changes +---------------------- + +* Speed up CLN by using the low-level addition/subtraction, shift and + multiplication loops from GNU gmp-2.0.2. + +* Fixed a severe reference counting bug in the constructors + `type::type (const long)' and `type::type (const unsigned long)' + for type=cl_number, type=cl_N, type=cl_RA, type=cl_I that most often + caused a core dump. + +* CLN's word sequences can be chosen to be stored big-endian in memory + (like it was up to now) or little-endian (needed for interfacing to GMP). + + +1996-05-20 +========== + +Functional changes +------------------ + +* New include file , contains timing facilities. + +Algorithmic changes +------------------- + +* Speed up the multiplication of large numbers by use of an FFT based + algorithm (Schönhage-Strassen). The improvement is noticeable when both + factors have at least 1250 words = 40000 bits = 12000 decimal digits. + +* Speed up the functions `cl_I gcd (const cl_I&, const cl_I&)' and + `cl_I xgcd (const cl_I&, const cl_I&, cl_I*, cl_I*)' by a factor + of 1.5. Simple trick. + +* Speed up the function `cl_boolean sqrtp (const cl_I&, cl_I*)' using a + trick from Henri Cohen. + +* Fixed an endless loop in the function `uint32 gcd (uint32, uint32)' + which occurred when one of the arguments is zero. + +* Fixed an endless loop in the function `cl_I factorial (uintL)'. + +Implementation changes +---------------------- + +* now uses iostreams by default instead of stdio FILE pointers. + (Reported by Tito Flagella.) + +* Fixed linking error when compiling without -O. + (Reported by Tito Flagella.) + +* Fixed syntax error in . + (Reported by Tito Flagella.) + +* Fixed syntax errors in src/cl_DS.h and src/cl_FF_plus.h. + (Reported by Marcus Daniels.) + +* More portability fixes. + +* Configuration now supports the --srcdir option. + (Reported by Marcus Daniels.) + + +1996-01-03 +========== + +* Compiles well on Sparc, using gcc. + +* Mail to beta testers. + + +1995-12-06 +========== + +* Compiles well on Linux, using gcc. + diff --git a/README b/README new file mode 100644 index 0000000..bc5fe58 --- /dev/null +++ b/README @@ -0,0 +1,41 @@ +Class Library for Numbers + +Copyright (c) Bruno Haible 1988-2000 + +GPL + +Features: +- Rich set of number classes: + Integer (unlimited precision), rational, + short float, single float, double float, + long float (unlimited precision), complex, + modular integer, univariate polynomial. +- Elementary, logical, transcendental functions. +- C++ as implementation language brings + - efficiency, + - type safety, + - algebraic syntax. +- Memory efficiency: + - Small integers and short floats are immediate, + not heap allocated. + - Automatic, non-interruptive garbage collection. +- Speed efficiency: + - Assembly language kernel for some CPUs, + - Karatsuba and Schönhage-Strassen multiplication. +- Interoperability: + - Garbage collection with no burden on + the main application, + - hooks for memory allocation and exceptions. + +Requires: C++ compiler g++. +The following C++ features are used: +classes, member functions, +overloading of functions and operators, +constructors and destructors, inline, const, +multiple inheritance, templates. +The following C++ features are not used: +new, delete, virtual inheritance, +exceptions. + +Homepage: http://clisp.cons.org/~haible/packages-cln.html + diff --git a/TODO b/TODO new file mode 100644 index 0000000..55f5de3 --- /dev/null +++ b/TODO @@ -0,0 +1,31 @@ +- polynomial division and gcd +- polynomial documentation +7. add combinatorial, linear algebra, factorization, polynomial functions + as in SAC-2. +7. finite fields, e.g. + - gf256_log_2, gf256_antilog_2, gf256_power_of_2, gf256_add, gf256_minus, + gf256_subtract, gf256_mul, gf256_inv, gf256_div, gf256_product, gf256_exp, + gf256_term, gfmul, gfadd, gfinv, gfexp. + more polynomial operations: + x(), power, >>, <<, division, scalmult, content, primitivepart, + gcd, xgcd, no_of_real_roots, factorization. + modular polynomials: powmod etc. +7. chinese remainder algorithm, maybe Hensel-lifting as in Magnum. +8. factor and primality testing for small integers +8. primality test in Z: + + polynomials cl_MUP_MI, cl_MUP_I + use integer FFT for multiplication in cl_UP_MI and cl_MUP_MI + + - Pollard rho + + - complex values of j() + - Hilbert polynomial for j() 7.6.1 + + roots of polynomials mod N 1.6.1 + + - elliptic curves, Jacobi representation + - m.P on elliptic curve + + Atkin's algorithm +10. factoring in Z: + - small prime table, + - Pollard rho, + - multiple polynomial quadratic sieve + +Document the timing class + diff --git a/TODO-subclass b/TODO-subclass new file mode 100644 index 0000000..c250b3a --- /dev/null +++ b/TODO-subclass @@ -0,0 +1,27 @@ +SUBCLASS_cl_... + + +cl_MI_export.h:class cl_heap_modint_ring : public cl_heap { +cl_hash.h:struct cl_heap_hashtable : public cl_heap { +cl_hash1.h:struct cl_heap_hashtable_1 : public cl_heap_hashtable > { +cl_hash1weak.h:struct cl_heap_weak_hashtable_1 : public cl_heap_hashtable_1 { +cl_hash2.h:struct cl_heap_hashtable_2 : public cl_heap_hashtable > { +cl_hashset.h:struct cl_heap_hashtable_set : public cl_heap_hashtable > { +cl_hashuniq.h:struct cl_heap_hashtable_uniq : public cl_heap_hashtable > { +cl_hashuniqweak.h:struct cl_heap_weak_hashtable_uniq : public cl_heap_hashtable_uniq { +cl_string.h:struct cl_heap_string : public cl_heap { +cl_V_I.cc:struct cl_heap_V_I_general : public cl_heap_V_I { +cl_C.h:struct cl_heap_complex : cl_heap { +cl_DF.h:struct cl_heap_dfloat : cl_heap { +cl_FF.h:struct cl_heap_ffloat : cl_heap { +cl_I.h:struct cl_heap_bignum : cl_heap { +cl_LF.h:struct cl_heap_lfloat : cl_heap { +cl_RA.h:struct cl_heap_ratio : cl_heap { +cl_V_I.h:struct cl_heap_V_I : cl_heap { + +cl_C.h: cl_heap_complex* p = (cl_heap_complex*) cl_malloc_hook(sizeof(cl_heap_complex)); +cl_DF.h: cl_heap_dfloat* p = (cl_heap_dfloat*) cl_malloc_hook(sizeof(cl_heap_dfloat)); +cl_DF.h: cl_heap_dfloat* p = (cl_heap_dfloat*) cl_malloc_hook(sizeof(cl_heap_dfloat)); +cl_FF.h: cl_heap_ffloat* p = (cl_heap_ffloat*) cl_malloc_hook(sizeof(cl_heap_ffloat)); +cl_RA.h: cl_heap_ratio* p = (cl_heap_ratio*) cl_malloc_hook(sizeof(cl_heap_ratio)); +cl_V_I.cc: var cl_heap_V_I_general* hv = (cl_heap_V_I_general*) cl_malloc_hook(offsetofa(cl_heap_V_I_general,data)+sizeof(cl_I)*len); diff --git a/TODO-verylong b/TODO-verylong new file mode 100644 index 0000000..76a6d46 --- /dev/null +++ b/TODO-verylong @@ -0,0 +1,4 @@ +Optimizations for very long numbers: +- gcd: recursive Euklid-Lehmer or Binary-Weber algorithms, +- Gamma function for rational x. + diff --git a/autoconf/acgeneral.m4 b/autoconf/acgeneral.m4 new file mode 100644 index 0000000..71d72a9 --- /dev/null +++ b/autoconf/acgeneral.m4 @@ -0,0 +1,2650 @@ +dnl Parameterized macros. +dnl Requires GNU m4. +dnl This file is part of Autoconf. +dnl Copyright (C) 1992, 93, 94, 95, 96, 1998 Free Software Foundation, Inc. +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception, the Free Software Foundation gives unlimited +dnl permission to copy, distribute and modify the configure scripts that +dnl are the output of Autoconf. You need not follow the terms of the GNU +dnl General Public License when using or distributing such scripts, even +dnl though portions of the text of Autoconf appear in them. The GNU +dnl General Public License (GPL) does govern all other use of the material +dnl that constitutes the Autoconf program. +dnl +dnl Certain portions of the Autoconf source text are designed to be copied +dnl (in certain cases, depending on the input) into the output of +dnl Autoconf. We call these the "data" portions. The rest of the Autoconf +dnl source text consists of comments plus executable code that decides which +dnl of the data portions to output in any given case. We call these +dnl comments and executable code the "non-data" portions. Autoconf never +dnl copies any of the non-data portions into its output. +dnl +dnl This special exception to the GPL applies to versions of Autoconf +dnl released by the Free Software Foundation. When you make and +dnl distribute a modified version of Autoconf, you may extend this special +dnl exception to the GPL to apply to your modified version as well, *unless* +dnl your modified version has the potential to copy into its output some +dnl of the text that was the non-data portion of the version that you started +dnl with. (In other words, unless your change moves or copies text from +dnl the non-data portions to the data portions.) If your modification has +dnl such potential, you must delete any notice of this special exception +dnl to the GPL from your modified version. +dnl +dnl Written by David MacKenzie, with help from +dnl Franc,ois Pinard, Karl Berry, Richard Pixley, Ian Lance Taylor, +dnl Roland McGrath, Noah Friedman, david d zuhn, and many others. +dnl +dnl Changed by Bruno Haible, 18 January 1999 +dnl +divert(-1)dnl Throw away output until AC_INIT is called. +changequote([, ]) + +define(AC_ACVERSION, 2.13) + +dnl Some old m4's don't support m4exit. But they provide +dnl equivalent functionality by core dumping because of the +dnl long macros we define. +ifdef([__gnu__], , [errprint(Autoconf requires GNU m4. +Install it before installing Autoconf or set the +M4 environment variable to its path name. +)m4exit(2)]) + +undefine([eval]) +undefine([include]) +undefine([shift]) +undefine([format]) + + +dnl ### Defining macros + + +dnl m4 output diversions. We let m4 output them all in order at the end, +dnl except that we explicitly undivert AC_DIVERSION_SED, AC_DIVERSION_CMDS, +dnl and AC_DIVERSION_ICMDS. + +dnl AC_DIVERSION_NOTICE - 1 (= 0) AC_REQUIRE'd #! /bin/sh line +define(AC_DIVERSION_NOTICE, 1)dnl copyright notice & option help strings +define(AC_DIVERSION_INIT, 2)dnl initialization code +define(AC_DIVERSION_NORMAL_4, 3)dnl AC_REQUIRE'd code, 4 level deep +define(AC_DIVERSION_NORMAL_3, 4)dnl AC_REQUIRE'd code, 3 level deep +define(AC_DIVERSION_NORMAL_2, 5)dnl AC_REQUIRE'd code, 2 level deep +define(AC_DIVERSION_NORMAL_1, 6)dnl AC_REQUIRE'd code, 1 level deep +define(AC_DIVERSION_NORMAL, 7)dnl the tests and output code +define(AC_DIVERSION_SED, 8)dnl variable substitutions in config.status +define(AC_DIVERSION_CMDS, 9)dnl extra shell commands in config.status +define(AC_DIVERSION_ICMDS, 10)dnl extra initialization in config.status + +dnl Change the diversion stream to STREAM, while stacking old values. +dnl AC_DIVERT_PUSH(STREAM) +define(AC_DIVERT_PUSH, +[pushdef([AC_DIVERSION_CURRENT], $1)dnl +divert(AC_DIVERSION_CURRENT)dnl +]) + +dnl Change the diversion stream to its previous value, unstacking it. +dnl AC_DIVERT_POP() +define(AC_DIVERT_POP, +[popdef([AC_DIVERSION_CURRENT])dnl +divert(AC_DIVERSION_CURRENT)dnl +]) + +dnl Initialize the diversion setup. +define([AC_DIVERSION_CURRENT], AC_DIVERSION_NORMAL) +dnl This will be popped by AC_REQUIRE in AC_INIT. +pushdef([AC_DIVERSION_CURRENT], AC_DIVERSION_NOTICE) + +dnl The prologue for Autoconf macros. +dnl AC_PRO(MACRO-NAME) +define(AC_PRO, +[define([AC_PROVIDE_$1], )dnl +ifelse(AC_DIVERSION_CURRENT, AC_DIVERSION_NORMAL, +[AC_DIVERT_PUSH(builtin(eval, AC_DIVERSION_CURRENT - 1))], +[pushdef([AC_DIVERSION_CURRENT], AC_DIVERSION_CURRENT)])dnl +]) + +dnl The Epilogue for Autoconf macros. +dnl AC_EPI() +define(AC_EPI, +[AC_DIVERT_POP()dnl +ifelse(AC_DIVERSION_CURRENT, AC_DIVERSION_NORMAL, +[undivert(AC_DIVERSION_NORMAL_4)dnl +undivert(AC_DIVERSION_NORMAL_3)dnl +undivert(AC_DIVERSION_NORMAL_2)dnl +undivert(AC_DIVERSION_NORMAL_1)dnl +])dnl +]) + +dnl Define a macro which automatically provides itself. Add machinery +dnl so the macro automatically switches expansion to the diversion +dnl stack if it is not already using it. In this case, once finished, +dnl it will bring back all the code accumulated in the diversion stack. +dnl This, combined with AC_REQUIRE, achieves the topological ordering of +dnl macros. We don't use this macro to define some frequently called +dnl macros that are not involved in ordering constraints, to save m4 +dnl processing. +dnl AC_DEFUN(NAME, EXPANSION) +define([AC_DEFUN], +[define($1, [AC_PRO([$1])$2[]AC_EPI()])]) + + +dnl ### Initialization + + +dnl AC_INIT_NOTICE() +AC_DEFUN(AC_INIT_NOTICE, +[# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version] AC_ACVERSION [ +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +[#] Any additions from configure.in:]) + +dnl AC_PREFIX_DEFAULT(PREFIX) +AC_DEFUN(AC_PREFIX_DEFAULT, +[AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)dnl +ac_default_prefix=$1 +AC_DIVERT_POP()]) + +dnl AC_INIT_PARSE_ARGS() +AC_DEFUN(AC_INIT_PARSE_ARGS, +[ +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +dnl Installation directory options. +dnl These are left unexpanded so users can "make install exec_prefix=/foo" +dnl and all the variables that are supposed to be based on exec_prefix +dnl by default will actually change. +dnl Use braces instead of parens because sh, perl, etc. also accept them. +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in +changequote(, )dnl + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; +changequote([, ])dnl + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. +changequote(, )dnl + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then +changequote([, ])dnl + AC_MSG_ERROR($ac_feature: invalid feature name) + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. +changequote(, )dnl + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then +changequote([, ])dnl + AC_MSG_ERROR($ac_feature: invalid feature name) + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +changequote(, )dnl +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +changequote([, ])dnl +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version AC_ACVERSION" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. +changequote(, )dnl + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then +changequote([, ])dnl + AC_MSG_ERROR($ac_package: invalid package name) + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. +changequote(, )dnl + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then +changequote([, ])dnl + AC_MSG_ERROR($ac_package: invalid package name) + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) AC_MSG_ERROR([$ac_option: invalid option; use --help to show usage]) + ;; + + *) +changequote(, )dnl + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then +changequote([, ])dnl + AC_MSG_WARN($ac_option: invalid host type) + fi + if test "x$nonopt" != xNONE; then + AC_MSG_ERROR(can only configure for one host and one target at a time) + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + AC_MSG_ERROR(missing argument to --`echo $ac_prev | sed 's/_/-/g'`) +fi +]) + +dnl Try to have only one #! line, so the script doesn't look funny +dnl for users of AC_REVISION. +dnl AC_INIT_BINSH() +AC_DEFUN(AC_INIT_BINSH, +[#! /bin/sh +]) + +dnl AC_INIT(UNIQUE-FILE-IN-SOURCE-DIR) +AC_DEFUN(AC_INIT, +[sinclude(acsite.m4)dnl +sinclude(./aclocal.m4)dnl +AC_REQUIRE([AC_INIT_BINSH])dnl +AC_INIT_NOTICE +AC_DIVERT_POP()dnl to NORMAL +AC_DIVERT_PUSH(AC_DIVERSION_INIT)dnl +AC_INIT_PARSE_ARGS +AC_INIT_PREPARE($1)dnl +AC_DIVERT_POP()dnl to NORMAL +]) + +dnl AC_INIT_PREPARE(UNIQUE-FILE-IN-SOURCE-DIR) +AC_DEFUN(AC_INIT_PREPARE, +[trap 'rm -fr conftest* confdefs* core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +define(AC_FD_MSG, 6)dnl +[#] AC_FD_MSG checking for... messages and results +define(AC_FD_CC, 5)dnl +[#] AC_FD_CC compiler messages saved in config.log +if test "$silent" = yes; then + exec AC_FD_MSG>/dev/null +else + exec AC_FD_MSG>&1 +fi +exec AC_FD_CC>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&AC_FD_CC + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; +changequote(<<, >>)dnl +dnl If you change this globbing pattern, test it on an old shell -- +dnl it's sensitive. Putting any kind of quote in it causes syntax errors. + *" "*|*" "*|*[\[\]\~\<<#>>\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; +changequote([, ])dnl + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=$1 + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=[$]0 +changequote(, )dnl + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` +changequote([, ])dnl + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + AC_MSG_ERROR(can not find sources in $ac_confdir or ..) + else + AC_MSG_ERROR(can not find sources in $srcdir) + fi +fi +dnl Double slashes in pathnames in object file debugging info +dnl mess up M-x gdb in Emacs. +changequote(, )dnl +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` +changequote([, ])dnl + +dnl Let the site file select an alternate cache file if it wants to. +AC_SITE_LOAD +AC_CACHE_LOAD +AC_LANG_C +dnl By default always use an empty string as the executable +dnl extension. Only change it if the script calls AC_EXEEXT. +ac_exeext= +dnl By default assume that objects files use an extension of .o. Only +dnl change it if the script calls AC_OBJEXT. +ac_objext=o +AC_PROG_ECHO_N +dnl Substitute for predefined variables. +AC_SUBST(SHELL)dnl +AC_SUBST(CFLAGS)dnl +AC_SUBST(CPPFLAGS)dnl +AC_SUBST(CXXFLAGS)dnl +AC_SUBST(FFLAGS)dnl +AC_SUBST(DEFS)dnl +AC_SUBST(LDFLAGS)dnl +AC_SUBST(LIBS)dnl +AC_SUBST(exec_prefix)dnl +AC_SUBST(prefix)dnl +AC_SUBST(program_transform_name)dnl +dnl Installation directory options. +AC_SUBST(bindir)dnl +AC_SUBST(sbindir)dnl +AC_SUBST(libexecdir)dnl +AC_SUBST(datadir)dnl +AC_SUBST(sysconfdir)dnl +AC_SUBST(sharedstatedir)dnl +AC_SUBST(localstatedir)dnl +AC_SUBST(libdir)dnl +AC_SUBST(includedir)dnl +AC_SUBST(oldincludedir)dnl +AC_SUBST(infodir)dnl +AC_SUBST(mandir)dnl +]) + + +dnl ### Selecting optional features + + +dnl AC_ARG_ENABLE(FEATURE, HELP-STRING, ACTION-IF-TRUE [, ACTION-IF-FALSE]) +AC_DEFUN(AC_ARG_ENABLE, +[AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)dnl +ac_help="$ac_help +[$2]" +AC_DIVERT_POP()dnl +[#] Check whether --enable-[$1] or --disable-[$1] was given. +if test "[${enable_]patsubst([$1], -, _)+set}" = set; then + enableval="[$enable_]patsubst([$1], -, _)" + ifelse([$3], , :, [$3]) +ifelse([$4], , , [else + $4 +])dnl +fi +]) + +AC_DEFUN(AC_ENABLE, +[AC_OBSOLETE([$0], [; instead use AC_ARG_ENABLE])dnl +AC_ARG_ENABLE([$1], [ --enable-$1], [$2], [$3])dnl +]) + + +dnl ### Working with optional software + + +dnl AC_ARG_WITH(PACKAGE, HELP-STRING, ACTION-IF-TRUE [, ACTION-IF-FALSE]) +AC_DEFUN(AC_ARG_WITH, +[AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)dnl +ac_help="$ac_help +[$2]" +AC_DIVERT_POP()dnl +[#] Check whether --with-[$1] or --without-[$1] was given. +if test "[${with_]patsubst([$1], -, _)+set}" = set; then + withval="[$with_]patsubst([$1], -, _)" + ifelse([$3], , :, [$3]) +ifelse([$4], , , [else + $4 +])dnl +fi +]) + +AC_DEFUN(AC_WITH, +[AC_OBSOLETE([$0], [; instead use AC_ARG_WITH])dnl +AC_ARG_WITH([$1], [ --with-$1], [$2], [$3])dnl +]) + + +dnl ### Transforming program names. + + +dnl AC_ARG_PROGRAM() +AC_DEFUN(AC_ARG_PROGRAM, +[if test "$program_transform_name" = s,x,x,; then + program_transform_name= +else + # Double any \ or $. echo might interpret backslashes. + cat <<\EOF_SED > conftestsed +s,\\,\\\\,g; s,\$,$$,g +EOF_SED + program_transform_name="`echo $program_transform_name|sed -f conftestsed`" + rm -f conftestsed +fi +test "$program_prefix" != NONE && + program_transform_name="s,^,${program_prefix},; $program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" + +# sed with no file args requires a program. +test "$program_transform_name" = "" && program_transform_name="s,x,x," +]) + + +dnl ### Version numbers + + +dnl AC_REVISION(REVISION-INFO) +AC_DEFUN(AC_REVISION, +[AC_REQUIRE([AC_INIT_BINSH])dnl +[# From configure.in] translit([$1], $")]) + +dnl Subroutines of AC_PREREQ. + +dnl Change the dots in NUMBER into commas. +dnl AC_PREREQ_SPLIT(NUMBER) +define(AC_PREREQ_SPLIT, +[translit($1, ., [, ])]) + +dnl Default the ternary version number to 0 (e.g., 1, 7 -> 1, 7, 0). +dnl AC_PREREQ_CANON(MAJOR, MINOR [,TERNARY]) +define(AC_PREREQ_CANON, +[$1, $2, ifelse([$3], , 0, [$3])]) + +dnl Complain and exit if version number 1 is less than version number 2. +dnl PRINTABLE2 is the printable version of version number 2. +dnl AC_PREREQ_COMPARE(MAJOR1, MINOR1, TERNARY1, MAJOR2, MINOR2, TERNARY2, +dnl PRINTABLE2) +define(AC_PREREQ_COMPARE, +[ifelse(builtin([eval], +[$3 + $2 * 1000 + $1 * 1000000 < $6 + $5 * 1000 + $4 * 1000000]), 1, +[errprint(dnl +FATAL ERROR: Autoconf version $7 or higher is required for this script +)m4exit(3)])]) + +dnl Complain and exit if the Autoconf version is less than VERSION. +dnl AC_PREREQ(VERSION) +define(AC_PREREQ, +[AC_PREREQ_COMPARE(AC_PREREQ_CANON(AC_PREREQ_SPLIT(AC_ACVERSION)), +AC_PREREQ_CANON(AC_PREREQ_SPLIT([$1])), [$1])]) + + +dnl ### Getting the canonical system type + + +dnl Find install-sh, config.sub, config.guess, and Cygnus configure +dnl in directory DIR. These are auxiliary files used in configuration. +dnl DIR can be either absolute or relative to $srcdir. +dnl AC_CONFIG_AUX_DIR(DIR) +AC_DEFUN(AC_CONFIG_AUX_DIR, +[AC_CONFIG_AUX_DIRS($1 $srcdir/$1)]) + +dnl The default is `$srcdir' or `$srcdir/..' or `$srcdir/../..'. +dnl There's no need to call this macro explicitly; just AC_REQUIRE it. +AC_DEFUN(AC_CONFIG_AUX_DIR_DEFAULT, +[AC_CONFIG_AUX_DIRS($srcdir $srcdir/.. $srcdir/../..)]) + +dnl Internal subroutine. +dnl Search for the configuration auxiliary files in directory list $1. +dnl We look only for install-sh, so users of AC_PROG_INSTALL +dnl do not automatically need to distribute the other auxiliary files. +dnl AC_CONFIG_AUX_DIRS(DIR ...) +AC_DEFUN(AC_CONFIG_AUX_DIRS, +[ac_aux_dir= +for ac_dir in $1; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + AC_MSG_ERROR([can not find install-sh or install.sh in $1]) +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. +AC_PROVIDE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +]) + +dnl Canonicalize the host, target, and build system types. +AC_DEFUN(AC_CANONICAL_SYSTEM, +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +AC_BEFORE([$0], [AC_ARG_PROGRAM]) +# Do some error checking and defaulting for the host and target type. +# The inputs are: +# configure --host=HOST --target=TARGET --build=BUILD NONOPT +# +# The rules are: +# 1. You are not allowed to specify --host, --target, and nonopt at the +# same time. +# 2. Host defaults to nonopt. +# 3. If nonopt is not specified, then host defaults to the current host, +# as determined by config.guess. +# 4. Target and build default to nonopt. +# 5. If nonopt is not specified, then target and build default to host. + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +case $host---$target---$nonopt in +NONE---*---* | *---NONE---* | *---*---NONE) ;; +*) AC_MSG_ERROR(can only configure for one host and one target at a time) ;; +esac + +AC_CANONICAL_HOST +AC_CANONICAL_TARGET +AC_CANONICAL_BUILD +test "$host_alias" != "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- +]) + +dnl Subroutines of AC_CANONICAL_SYSTEM. + +AC_DEFUN(AC_CANONICAL_HOST, +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl + +# Make sure we can run config.sub. +if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then : +else AC_MSG_ERROR(can not run $ac_config_sub) +fi + +AC_MSG_CHECKING(host system type) + +dnl Set host_alias. +host_alias=$host +case "$host_alias" in +NONE) + case $nonopt in + NONE) + if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then : + else AC_MSG_ERROR(can not guess host type; you must specify one) + fi ;; + *) host_alias=$nonopt ;; + esac ;; +esac + +dnl Set the other host vars. +changequote(<<, >>)dnl +host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias` +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +changequote([, ])dnl +AC_MSG_RESULT($host) +AC_SUBST(host)dnl +AC_SUBST(host_alias)dnl +AC_SUBST(host_cpu)dnl +AC_SUBST(host_vendor)dnl +AC_SUBST(host_os)dnl +]) + +dnl Internal use only. +AC_DEFUN(AC_CANONICAL_TARGET, +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +AC_MSG_CHECKING(target system type) + +dnl Set target_alias. +target_alias=$target +case "$target_alias" in +NONE) + case $nonopt in + NONE) target_alias=$host_alias ;; + *) target_alias=$nonopt ;; + esac ;; +esac + +dnl Set the other target vars. +changequote(<<, >>)dnl +target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias` +target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +changequote([, ])dnl +AC_MSG_RESULT($target) +AC_SUBST(target)dnl +AC_SUBST(target_alias)dnl +AC_SUBST(target_cpu)dnl +AC_SUBST(target_vendor)dnl +AC_SUBST(target_os)dnl +]) + +dnl Internal use only. +AC_DEFUN(AC_CANONICAL_BUILD, +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +AC_MSG_CHECKING(build system type) + +dnl Set build_alias. +build_alias=$build +case "$build_alias" in +NONE) + case $nonopt in + NONE) build_alias=$host_alias ;; + *) build_alias=$nonopt ;; + esac ;; +esac + +dnl Set the other build vars. +changequote(<<, >>)dnl +build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias` +build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +changequote([, ])dnl +AC_MSG_RESULT($build) +AC_SUBST(build)dnl +AC_SUBST(build_alias)dnl +AC_SUBST(build_cpu)dnl +AC_SUBST(build_vendor)dnl +AC_SUBST(build_os)dnl +]) + + +dnl AC_VALIDATE_CACHED_SYSTEM_TUPLE[(cmd)] +dnl if the cache file is inconsistent with the current host, +dnl target and build system types, execute CMD or print a default +dnl error message. +AC_DEFUN(AC_VALIDATE_CACHED_SYSTEM_TUPLE, [ + AC_REQUIRE([AC_CANONICAL_SYSTEM]) + AC_MSG_CHECKING([cached system tuple]) + if { test x"${ac_cv_host_system_type+set}" = x"set" && + test x"$ac_cv_host_system_type" != x"$host"; } || + { test x"${ac_cv_build_system_type+set}" = x"set" && + test x"$ac_cv_build_system_type" != x"$build"; } || + { test x"${ac_cv_target_system_type+set}" = x"set" && + test x"$ac_cv_target_system_type" != x"$target"; }; then + AC_MSG_RESULT([different]) + ifelse($#, 1, [$1], + [AC_MSG_ERROR([remove config.cache and re-run configure])]) + else + AC_MSG_RESULT(ok) + fi + ac_cv_host_system_type="$host" + ac_cv_build_system_type="$build" + ac_cv_target_system_type="$target" +]) + + +dnl ### Caching test results + + +dnl Look for site or system specific initialization scripts. +dnl AC_SITE_LOAD() +define(AC_SITE_LOAD, +[# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done +]) + +dnl AC_CACHE_LOAD() +define(AC_CACHE_LOAD, +[if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi +]) + +dnl AC_CACHE_SAVE() +define(AC_CACHE_SAVE, +[cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +dnl Allow a site initialization script to override cache values. +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +changequote(, )dnl +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +changequote([, ])dnl +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache +]) + +dnl The name of shell var CACHE-ID must contain `_cv_' in order to get saved. +dnl AC_CACHE_VAL(CACHE-ID, COMMANDS-TO-SET-IT) +define(AC_CACHE_VAL, +[dnl We used to use the below line, but it fails if the 1st arg is a +dnl shell variable, so we need the eval. +dnl if test "${$1+set}" = set; then +dnl the '' avoids an AIX 4.1 sh bug ("invalid expansion"). +if eval "test \"`echo '$''{'$1'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&AC_FD_MSG +else + $2 +fi +]) + +dnl AC_CACHE_CHECK(MESSAGE, CACHE-ID, COMMANDS) +define(AC_CACHE_CHECK, +[AC_MSG_CHECKING([$1]) +AC_CACHE_VAL([$2], [$3])dnl +AC_MSG_RESULT([$]$2)]) + + +dnl ### Defining symbols + + +dnl Set VARIABLE to VALUE, verbatim, or 1. +dnl AC_DEFINE(VARIABLE [, VALUE]) +define(AC_DEFINE, +[cat >> confdefs.h <<\EOF +[#define] $1 ifelse($#, 2, [$2], $#, 3, [$2], 1) +EOF +]) + +dnl Similar, but perform shell substitutions $ ` \ once on VALUE. +define(AC_DEFINE_UNQUOTED, +[cat >> confdefs.h <&AC_FD_MSG +echo "configure:__oline__: checking $1" >&AC_FD_CC]) + +dnl AC_CHECKING(FEATURE-DESCRIPTION) +define(AC_CHECKING, +[echo "checking $1" 1>&AC_FD_MSG +echo "configure:__oline__: checking $1" >&AC_FD_CC]) + +dnl AC_MSG_RESULT(RESULT-DESCRIPTION) +define(AC_MSG_RESULT, +[echo "$ac_t""$1" 1>&AC_FD_MSG]) + +dnl AC_MSG_RESULTPROTO(RESULT-PROTOTYPE-DESCRIPTION) +define(AC_MSG_RESULTPROTO, +[AC_MSG_RESULT(${ac_tt}[$1]) +dnl ac_proto=`echo "$1" | tr -s ' '` +dnl AC_MSG_RESULT(${ac_tt}${ac_proto}) +]) + +dnl AC_VERBOSE(RESULT-DESCRIPTION) +define(AC_VERBOSE, +[AC_OBSOLETE([$0], [; instead use AC_MSG_RESULT])dnl +echo " $1" 1>&AC_FD_MSG]) + +dnl AC_MSG_WARN(PROBLEM-DESCRIPTION) +define(AC_MSG_WARN, +[echo "configure: warning: $1" 1>&2]) + +dnl AC_MSG_ERROR(ERROR-DESCRIPTION) +define(AC_MSG_ERROR, +[{ echo "configure: error: $1" 1>&2; exit 1; }]) + + +dnl ### Selecting which language to use for testing + + +dnl AC_LANG_C() +AC_DEFUN(AC_LANG_C, +[define([AC_LANG], [C])dnl +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&AC_FD_CC' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&AC_FD_CC' +cross_compiling=$ac_cv_prog_cc_cross +]) + +dnl AC_LANG_CPLUSPLUS() +AC_DEFUN(AC_LANG_CPLUSPLUS, +[define([AC_LANG], [CPLUSPLUS])dnl +ac_ext=C +# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&AC_FD_CC' +ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&AC_FD_CC' +cross_compiling=$ac_cv_prog_cxx_cross +]) + +dnl AC_LANG_FORTRAN77() +AC_DEFUN(AC_LANG_FORTRAN77, +[define([AC_LANG], [FORTRAN77])dnl +ac_ext=f +ac_compile='${F77-f77} -c $FFLAGS conftest.$ac_ext 1>&AC_FD_CC' +ac_link='${F77-f77} -o conftest${ac_exeext} $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&AC_FD_CC' +cross_compiling=$ac_cv_prog_f77_cross +]) + +dnl Push the current language on a stack. +dnl AC_LANG_SAVE() +define(AC_LANG_SAVE, +[pushdef([AC_LANG_STACK], AC_LANG)]) + +dnl Restore the current language from the stack. +dnl AC_LANG_RESTORE() +pushdef([AC_LANG_RESTORE], +[ifelse(AC_LANG_STACK, [C], [AC_LANG_C],dnl +AC_LANG_STACK, [CPLUSPLUS], [AC_LANG_CPLUSPLUS],dnl +AC_LANG_STACK, [FORTRAN77], [AC_LANG_FORTRAN77])[]popdef([AC_LANG_STACK])]) + +dnl Expands to the "extern ..." prefix used for system declarations. +dnl AC_LANG_EXTERN() +define(AC_LANG_EXTERN, +[extern +#ifdef __cplusplus +"C" +#endif +]) + + +dnl ### Compiler-running mechanics + + +dnl The purpose of this macro is to "configure:123: command line" +dnl written into config.log for every test run. +dnl AC_TRY_EVAL(VARIABLE) +AC_DEFUN(AC_TRY_EVAL, +[{ (eval echo configure:__oline__: \"[$]$1\") 1>&AC_FD_CC; dnl +(eval [$]$1) 2>&AC_FD_CC; }]) + +dnl AC_TRY_COMMAND(COMMAND) +AC_DEFUN(AC_TRY_COMMAND, +[{ ac_try='$1'; AC_TRY_EVAL(ac_try); }]) + + +dnl ### Dependencies between macros + + +dnl AC_BEFORE(THIS-MACRO-NAME, CALLED-MACRO-NAME) +define(AC_BEFORE, +[ifdef([AC_PROVIDE_$2], [errprint(__file__:__line__: [$2 was called before $1 +])])]) + +dnl AC_REQUIRE(MACRO-NAME) +define(AC_REQUIRE, +[ifdef([AC_PROVIDE_$1], , +[AC_DIVERT_PUSH(builtin(eval, AC_DIVERSION_CURRENT - 1))dnl +indir([$1]) +AC_DIVERT_POP()dnl +])]) + +dnl AC_PROVIDE(MACRO-NAME) +define(AC_PROVIDE, +[define([AC_PROVIDE_$1], )]) + +dnl AC_OBSOLETE(THIS-MACRO-NAME [, SUGGESTION]) +define(AC_OBSOLETE, +[errprint(__file__:__line__: warning: [$1] is obsolete[$2] +)]) + + +dnl ### Checking for programs + + +dnl AC_CHECK_PROG(VARIABLE, PROG-TO-CHECK-FOR, VALUE-IF-FOUND +dnl [, [VALUE-IF-NOT-FOUND] [, [PATH] [, [REJECT]]]]) +AC_DEFUN(AC_CHECK_PROG, +[# Extract the first word of "$2", so it can be a program name with args. +set dummy $2; ac_word=[$]2 +AC_MSG_CHECKING([for $ac_word]) +AC_CACHE_VAL(ac_cv_prog_$1, +[if test -n "[$]$1"; then + ac_cv_prog_$1="[$]$1" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" +ifelse([$6], , , [ ac_prog_rejected=no +])dnl +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="ifelse([$5], , $PATH, [$5])" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then +ifelse([$6], , , dnl +[ if test "[$ac_dir/$ac_word]" = "$6"; then + ac_prog_rejected=yes + continue + fi +])dnl + ac_cv_prog_$1="$3" + break + fi + done + IFS="$ac_save_ifs" +ifelse([$6], , , [if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy [$]ac_cv_prog_$1 + shift + if test [$]# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set $1 to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "[$]@" + shift + ac_cv_prog_$1="[$]@" +ifelse([$2], [$4], dnl +[ else + # Default is a loser. + AC_MSG_ERROR([$1=$6 unacceptable, but no other $4 found in dnl +ifelse([$5], , [\$]PATH, [$5])]) +])dnl + fi +fi +])dnl +dnl If no 4th arg is given, leave the cache variable unset, +dnl so AC_CHECK_PROGS will keep looking. +ifelse([$4], , , [ test -z "[$]ac_cv_prog_$1" && ac_cv_prog_$1="$4" +])dnl +fi])dnl +$1="$ac_cv_prog_$1" +if test -n "[$]$1"; then + AC_MSG_RESULT([$]$1) +else + AC_MSG_RESULT(no) +fi +AC_SUBST($1)dnl +]) + +dnl AC_PATH_PROG(VARIABLE, PROG-TO-CHECK-FOR [, VALUE-IF-NOT-FOUND [, PATH]]) +AC_DEFUN(AC_PATH_PROG, +[# Extract the first word of "$2", so it can be a program name with args. +set dummy $2; ac_word=[$]2 +AC_MSG_CHECKING([for $ac_word]) +AC_CACHE_VAL(ac_cv_path_$1, +[case "[$]$1" in + /*) + ac_cv_path_$1="[$]$1" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_$1="[$]$1" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="ifelse([$4], , $PATH, [$4])" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_$1="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" +dnl If no 3rd arg is given, leave the cache variable unset, +dnl so AC_PATH_PROGS will keep looking. +ifelse([$3], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$3" +])dnl + ;; +esac])dnl +$1="$ac_cv_path_$1" +if test -n "[$]$1"; then + AC_MSG_RESULT([$]$1) +else + AC_MSG_RESULT(no) +fi +AC_SUBST($1)dnl +]) + +dnl AC_CHECK_PROGS(VARIABLE, PROGS-TO-CHECK-FOR [, VALUE-IF-NOT-FOUND +dnl [, PATH]]) +AC_DEFUN(AC_CHECK_PROGS, +[for ac_prog in $2 +do +AC_CHECK_PROG($1, [$]ac_prog, [$]ac_prog, , $4) +test -n "[$]$1" && break +done +ifelse([$3], , , [test -n "[$]$1" || $1="$3" +])]) + +dnl AC_PATH_PROGS(VARIABLE, PROGS-TO-CHECK-FOR [, VALUE-IF-NOT-FOUND +dnl [, PATH]]) +AC_DEFUN(AC_PATH_PROGS, +[for ac_prog in $2 +do +AC_PATH_PROG($1, [$]ac_prog, , $4) +test -n "[$]$1" && break +done +ifelse([$3], , , [test -n "[$]$1" || $1="$3" +])]) + +dnl Internal subroutine. +AC_DEFUN(AC_CHECK_TOOL_PREFIX, +[AC_REQUIRE([AC_CANONICAL_HOST])AC_REQUIRE([AC_CANONICAL_BUILD])dnl +if test $host != $build; then + ac_tool_prefix=${host_alias}- +else + ac_tool_prefix= +fi +]) + +dnl AC_CHECK_TOOL(VARIABLE, PROG-TO-CHECK-FOR[, VALUE-IF-NOT-FOUND [, PATH]]) +AC_DEFUN(AC_CHECK_TOOL, +[AC_REQUIRE([AC_CHECK_TOOL_PREFIX])dnl +AC_CHECK_PROG($1, ${ac_tool_prefix}$2, ${ac_tool_prefix}$2, + ifelse([$3], , [$2], ), $4) +ifelse([$3], , , [ +if test -z "$ac_cv_prog_$1"; then +if test -n "$ac_tool_prefix"; then + AC_CHECK_PROG($1, $2, $2, $3) +else + $1="$3" +fi +fi]) +]) + +dnl Guess the value for the `prefix' variable by looking for +dnl the argument program along PATH and taking its parent. +dnl Example: if the argument is `gcc' and we find /usr/local/gnu/bin/gcc, +dnl set `prefix' to /usr/local/gnu. +dnl This comes too late to find a site file based on the prefix, +dnl and it might use a cached value for the path. +dnl No big loss, I think, since most configures don't use this macro anyway. +dnl AC_PREFIX_PROGRAM(PROGRAM) +AC_DEFUN(AC_PREFIX_PROGRAM, +[if test "x$prefix" = xNONE; then +changequote(<<, >>)dnl +define(<>, translit($1, [a-z], [A-Z]))dnl +changequote([, ])dnl +dnl We reimplement AC_MSG_CHECKING (mostly) to avoid the ... in the middle. +echo $ac_n "checking for prefix by $ac_c" 1>&AC_FD_MSG +AC_PATH_PROG(AC_VAR_NAME, $1) +changequote(<<, >>)dnl + if test -n "$ac_cv_path_<<>>AC_VAR_NAME"; then + prefix=`echo $ac_cv_path_<<>>AC_VAR_NAME|sed 's%/[^/][^/]*//*[^/][^/]*$%%'` +changequote([, ])dnl + fi +fi +undefine([AC_VAR_NAME])dnl +]) + +dnl Try to compile, link and execute TEST-PROGRAM. Set WORKING-VAR to +dnl `yes' if the current compiler works, otherwise set it ti `no'. Set +dnl CROSS-VAR to `yes' if the compiler and linker produce non-native +dnl executables, otherwise set it to `no'. Before calling +dnl `AC_TRY_COMPILER()', call `AC_LANG_*' to set-up for the right +dnl language. +dnl +dnl AC_TRY_COMPILER(TEST-PROGRAM, WORKING-VAR, CROSS-VAR) +AC_DEFUN(AC_TRY_COMPILER, +[cat > conftest.$ac_ext << EOF +ifelse(AC_LANG, [FORTRAN77], , +[ +[#]line __oline__ "configure" +#include "confdefs.h" +]) +[$1] +EOF +if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + [$2]=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + [$3]=no + else + [$3]=yes + fi +else + echo "configure: failed program was:" >&AC_FD_CC + cat conftest.$ac_ext >&AC_FD_CC + [$2]=no +fi +rm -fr conftest*]) + + +dnl ### Checking for libraries + + +dnl AC_TRY_LINK_FUNC(func, action-if-found, action-if-not-found) +dnl Try to link a program that calls FUNC, handling GCC builtins. If +dnl the link succeeds, execute ACTION-IF-FOUND; otherwise, execute +dnl ACTION-IF-NOT-FOUND. + +AC_DEFUN(AC_TRY_LINK_FUNC, +AC_TRY_LINK(dnl +ifelse([$1], [main], , dnl Avoid conflicting decl of main. +[/* Override any gcc2 internal prototype to avoid an error. */ +]ifelse(AC_LANG, CPLUSPLUS, [#ifdef __cplusplus +extern "C" +#endif +])dnl +[/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $1(); +]), +[$1()], +[$2], +[$3])) + + +dnl AC_SEARCH_LIBS(FUNCTION, SEARCH-LIBS [, ACTION-IF-FOUND +dnl [, ACTION-IF-NOT-FOUND [, OTHER-LIBRARIES]]]) +dnl Search for a library defining FUNC, if it's not already available. + +AC_DEFUN(AC_SEARCH_LIBS, +[AC_PREREQ([2.13]) +AC_CACHE_CHECK([for library containing $1], [ac_cv_search_$1], +[ac_func_search_save_LIBS="$LIBS" +ac_cv_search_$1="no" +AC_TRY_LINK_FUNC([$1], [ac_cv_search_$1="none required"]) +test "$ac_cv_search_$1" = "no" && for i in $2; do +LIBS="-l$i $5 $ac_func_search_save_LIBS" +AC_TRY_LINK_FUNC([$1], +[ac_cv_search_$1="-l$i" +break]) +done +LIBS="$ac_func_search_save_LIBS"]) +if test "$ac_cv_search_$1" != "no"; then + test "$ac_cv_search_$1" = "none required" || LIBS="$ac_cv_search_$1 $LIBS" + $3 +else : + $4 +fi]) + + + +dnl AC_CHECK_LIB(LIBRARY, FUNCTION [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND +dnl [, OTHER-LIBRARIES]]]) +AC_DEFUN(AC_CHECK_LIB, +[AC_MSG_CHECKING(ifelse([$2], [main], [for -l$1], [for $2 in -l$1])) +dnl Use a cache variable name containing both the library and function name, +dnl because the test really is for library $1 defining function $2, not +dnl just for library $1. Separate tests with the same $1 and different $2s +dnl may have different results. +ac_lib_var=`echo ifelse([$2],main,[$1],[$1[_]$2]) | sed 'y%./+-%__p_%'` +AC_CACHE_VAL(ac_cv_lib_$ac_lib_var, +[ac_save_LIBS="$LIBS" +LIBS="-l$1 $5 $LIBS" +AC_TRY_LINK(ifelse(AC_LANG, [FORTRAN77], , +ifelse([$2], [main], , dnl Avoid conflicting decl of main. +[/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $2(); +])), + [$2()], + eval "ac_cv_lib_$ac_lib_var=yes", + eval "ac_cv_lib_$ac_lib_var=no") +LIBS="$ac_save_LIBS" +])dnl +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + AC_MSG_RESULT(yes) + ifelse([$3], , +[changequote(, )dnl + ac_tr_lib=HAVE_LIB`echo $1 | sed -e 's/[^a-zA-Z0-9_]/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` +changequote([, ])dnl + AC_DEFINE_UNQUOTED($ac_tr_lib) + LIBS="-l$1 $LIBS" +], [$3]) +else + AC_MSG_RESULT(no) +ifelse([$4], , , [$4 +])dnl +fi +]) + +dnl AC_HAVE_LIBRARY(LIBRARY, [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND +dnl [, OTHER-LIBRARIES]]]) +AC_DEFUN(AC_HAVE_LIBRARY, +[AC_OBSOLETE([$0], [; instead use AC_CHECK_LIB])dnl +changequote(<<, >>)dnl +define(<>, dnl +patsubst(patsubst($1, <>, <<\1>>), <<-l>>, <<>>))dnl +define(<>, ac_cv_lib_<<>>AC_LIB_NAME)dnl +changequote([, ])dnl +AC_MSG_CHECKING([for -l[]AC_LIB_NAME]) +AC_CACHE_VAL(AC_CV_NAME, +[ac_save_LIBS="$LIBS" +LIBS="-l[]AC_LIB_NAME[] $4 $LIBS" +AC_TRY_LINK( , [int main()], AC_CV_NAME=yes, AC_CV_NAME=no) +LIBS="$ac_save_LIBS" +])dnl +AC_MSG_RESULT($AC_CV_NAME) +if test "$AC_CV_NAME" = yes; then + ifelse([$2], , +[AC_DEFINE([HAVE_LIB]translit(AC_LIB_NAME, [a-z], [A-Z])) + LIBS="-l[]AC_LIB_NAME[] $LIBS" +], [$2]) +ifelse([$3], , , [else + $3 +])dnl +fi +undefine([AC_LIB_NAME])dnl +undefine([AC_CV_NAME])dnl +]) + + +dnl ### Examining declarations + + +dnl AC_TRY_CPP(INCLUDES, [ACTION-IF-TRUE [, ACTION-IF-FALSE]]) +AC_DEFUN(AC_TRY_CPP, +[AC_REQUIRE_CPP()dnl +cat > conftest.$ac_ext <&AC_FD_CC + echo "configure: failed program was:" >&AC_FD_CC + cat conftest.$ac_ext >&AC_FD_CC +ifelse([$3], , , [ rm -rf conftest* + $3 +])dnl +fi +rm -f conftest*]) + +dnl AC_EGREP_HEADER(PATTERN, HEADER-FILE, ACTION-IF-FOUND [, +dnl ACTION-IF-NOT-FOUND]) +AC_DEFUN(AC_EGREP_HEADER, +[AC_EGREP_CPP([$1], [#include <$2>], [$3], [$4])]) + +dnl Because this macro is used by AC_PROG_GCC_TRADITIONAL, which must +dnl come early, it is not included in AC_BEFORE checks. +dnl AC_EGREP_CPP(PATTERN, PROGRAM, [ACTION-IF-FOUND [, +dnl ACTION-IF-NOT-FOUND]]) +AC_DEFUN(AC_EGREP_CPP, +[AC_REQUIRE_CPP()dnl +cat > conftest.$ac_ext <&AC_FD_CC | +dnl Prevent m4 from eating character classes: +changequote(, )dnl + egrep "$1" >/dev/null 2>&1; then +changequote([, ])dnl + ifelse([$3], , :, [rm -rf conftest* + $3]) +ifelse([$4], , , [else + rm -rf conftest* + $4 +])dnl +fi +rm -f conftest* +]) + + +dnl ### Examining syntax + + +dnl AC_TRY_COMPILE(INCLUDES, FUNCTION-BODY, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +AC_DEFUN(AC_TRY_COMPILE, +[cat > conftest.$ac_ext <&AC_FD_CC + cat conftest.$ac_ext >&AC_FD_CC +ifelse([$4], , , [ rm -rf conftest* + $4 +])dnl +fi +rm -f conftest*]) + + +dnl ### Examining libraries + + +dnl AC_COMPILE_CHECK(ECHO-TEXT, INCLUDES, FUNCTION-BODY, +dnl ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]) +AC_DEFUN(AC_COMPILE_CHECK, +[AC_OBSOLETE([$0], [; instead use AC_TRY_COMPILE or AC_TRY_LINK, and AC_MSG_CHECKING and AC_MSG_RESULT])dnl +ifelse([$1], , , [AC_CHECKING([for $1]) +])dnl +AC_TRY_LINK([$2], [$3], [$4], [$5]) +]) + +dnl AC_TRY_LINK(INCLUDES, FUNCTION-BODY, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +AC_DEFUN(AC_TRY_LINK, +[cat > conftest.$ac_ext <&AC_FD_CC + cat conftest.$ac_ext >&AC_FD_CC +ifelse([$4], , , [ rm -rf conftest* + $4 +])dnl +fi +rm -f conftest*]) + + +dnl ### Checking for run-time features + + +dnl AC_TRY_RUN(PROGRAM, [ACTION-IF-TRUE [, ACTION-IF-FALSE +dnl [, ACTION-IF-CROSS-COMPILING]]]) +AC_DEFUN(AC_TRY_RUN, +[if test "$cross_compiling" = yes; then + ifelse([$4], , + [errprint(__file__:__line__: warning: [AC_TRY_RUN] called without default to allow cross compiling +)dnl + AC_MSG_ERROR(can not run test program while cross compiling)], + [$4]) +else + AC_TRY_RUN_NATIVE([$1], [$2], [$3]) +fi +]) + +dnl Like AC_TRY_RUN but assumes a native-environment (non-cross) compiler. +dnl AC_TRY_RUN_NATIVE(PROGRAM, [ACTION-IF-TRUE [, ACTION-IF-FALSE]]) +AC_DEFUN(AC_TRY_RUN_NATIVE, +[cat > conftest.$ac_ext </dev/null +then +dnl Don't remove the temporary files here, so they can be examined. + ifelse([$2], , :, [$2]) +else + echo "configure: failed program was:" >&AC_FD_CC + cat conftest.$ac_ext >&AC_FD_CC +ifelse([$3], , , [ rm -fr conftest* + $3 +])dnl +fi +if test -f core; then + coredir=core`/bin/sh -c 'echo $$'` + mkdir $coredir + cp confdefs.h $coredir/confdefs.h + mv conftest.c $coredir/conftest.c + mv conftest $coredir/conftest + mv core $coredir/core + echo "warning: test program dumped core -- see subdirectory $coredir" +fi +rm -fr conftest*]) + + +dnl ### Checking for header files + + +dnl AC_CHECK_HEADER(HEADER-FILE, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +AC_DEFUN(AC_CHECK_HEADER, +[dnl Do the transliteration at runtime so arg 1 can be a shell variable. +ac_safe=`echo "$1" | sed 'y%./+-%__p_%'` +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(ac_cv_header_$ac_safe, +[AC_TRY_CPP([#include <$1>], eval "ac_cv_header_$ac_safe=yes", + eval "ac_cv_header_$ac_safe=no")])dnl +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) +else + AC_MSG_RESULT(no) +ifelse([$3], , , [$3 +])dnl +fi +]) + +dnl AC_CHECK_HEADERS(HEADER-FILE... [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +AC_DEFUN(AC_CHECK_HEADERS, +[for ac_hdr in $1 +do +AC_CHECK_HEADER($ac_hdr, +[changequote(, )dnl + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` +changequote([, ])dnl + AC_DEFINE_UNQUOTED($ac_tr_hdr) $2], $3)dnl +done +]) + + +dnl ### Checking for the existence of files + +dnl AC_CHECK_FILE(FILE, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +AC_DEFUN(AC_CHECK_FILE, +[AC_REQUIRE([AC_PROG_CC]) +dnl Do the transliteration at runtime so arg 1 can be a shell variable. +ac_safe=`echo "$1" | sed 'y%./+-%__p_%'` +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(ac_cv_file_$ac_safe, +[if test "$cross_compiling" = yes; then + errprint(__file__:__line__: warning: Cannot check for file existence when cross compiling +)dnl + AC_MSG_ERROR(Cannot check for file existence when cross compiling) +else + if test -r $1; then + eval "ac_cv_file_$ac_safe=yes" + else + eval "ac_cv_file_$ac_safe=no" + fi +fi])dnl +if eval "test \"`echo '$ac_cv_file_'$ac_safe`\" = yes"; then + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) +else + AC_MSG_RESULT(no) +ifelse([$3], , , [$3]) +fi +]) + +dnl AC_CHECK_FILES(FILE... [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +AC_DEFUN(AC_CHECK_FILES, +[for ac_file in $1 +do +AC_CHECK_FILE($ac_file, +[changequote(, )dnl + ac_tr_file=HAVE_`echo $ac_file | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` +changequote([, ])dnl + AC_DEFINE_UNQUOTED($ac_tr_file) $2], $3)dnl +done +]) + + +dnl ### Checking for library functions + + +dnl AC_CHECK_FUNC(FUNCTION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +AC_DEFUN(AC_CHECK_FUNC, +[AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(ac_cv_func_$1, +[AC_TRY_LINK( +dnl Don't include because on OSF/1 3.0 it includes +dnl which includes which contains a prototype for +dnl select. Similarly for bzero. +[/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $1(); below. */ +#include +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $1(); +], [ +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$1) || defined (__stub___$1) +choke me +#else +$1(); +#endif +], eval "ac_cv_func_$1=yes", eval "ac_cv_func_$1=no")]) +if eval "test \"`echo '$ac_cv_func_'$1`\" = yes"; then + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) +else + AC_MSG_RESULT(no) +ifelse([$3], , , [$3 +])dnl +fi +]) + +dnl AC_CHECK_FUNCS(FUNCTION... [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +AC_DEFUN(AC_CHECK_FUNCS, +[for ac_func in $1 +do +AC_CHECK_FUNC($ac_func, +[changequote(, )dnl + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` +changequote([, ])dnl + AC_DEFINE_UNQUOTED($ac_tr_func) $2], $3)dnl +done +]) + +dnl AC_REPLACE_FUNCS(FUNCTION...) +AC_DEFUN(AC_REPLACE_FUNCS, +[AC_CHECK_FUNCS([$1], , [LIBOBJS="$LIBOBJS ${ac_func}.${ac_objext}"]) +AC_SUBST(LIBOBJS)dnl +]) + + +dnl ### Checking compiler characteristics + + +dnl AC_CHECK_SIZEOF(TYPE [, CROSS-SIZE]) +AC_DEFUN(AC_CHECK_SIZEOF, +[changequote(<<, >>)dnl +dnl The name to #define. +define(<>, translit(sizeof_$1, [a-z *], [A-Z_P]))dnl +dnl The cache variable name. +define(<>, translit(ac_cv_sizeof_$1, [ *], [_p]))dnl +changequote([, ])dnl +AC_MSG_CHECKING(size of $1) +AC_CACHE_VAL(AC_CV_NAME, +[AC_TRY_RUN([#include +int main() +{ + FILE *f=fopen("conftestval", "w"); + if (!f) exit(1); + fprintf(f, "%d\n", sizeof($1)); + exit(0); +}], AC_CV_NAME=`cat conftestval`, AC_CV_NAME=0, ifelse([$2], , , AC_CV_NAME=$2))])dnl +AC_MSG_RESULT($AC_CV_NAME) +AC_DEFINE_UNQUOTED(AC_TYPE_NAME, $AC_CV_NAME) +undefine([AC_TYPE_NAME])dnl +undefine([AC_CV_NAME])dnl +]) + + +dnl ### Checking for typedefs + + +dnl AC_CHECK_TYPE(TYPE, DEFAULT) +AC_DEFUN(AC_CHECK_TYPE, +[AC_REQUIRE([AC_HEADER_STDC])dnl +AC_MSG_CHECKING(for $1) +AC_CACHE_VAL(ac_cv_type_$1, +[AC_EGREP_CPP(dnl +changequote(<<,>>)dnl +<<(^|[^a-zA-Z_0-9])$1[^a-zA-Z_0-9]>>dnl +changequote([,]), [#include +#if defined(STDC_HEADERS) || defined(HAVE_STDLIB_H) +#include +#endif +#if defined(STDC_HEADERS) || defined(HAVE_STDDEF_H) +#include +#endif], ac_cv_type_$1=yes, ac_cv_type_$1=no)])dnl +AC_MSG_RESULT($ac_cv_type_$1) +if test $ac_cv_type_$1 = no; then + AC_DEFINE($1, $2) +fi +]) + + +dnl ### Creating output files + + +dnl AC_CONFIG_HEADER(HEADER-TO-CREATE ...) +AC_DEFUN(AC_CONFIG_HEADER, +[define(AC_LIST_HEADER, $1)]) + +dnl Link each of the existing files SOURCE... to the corresponding +dnl link name in DEST... +dnl AC_LINK_FILES(SOURCE..., DEST...) +AC_DEFUN(AC_LINK_FILES, +[dnl +define([AC_LIST_FILES], ifdef([AC_LIST_FILES], [AC_LIST_FILES ],)[$1])dnl +define([AC_LIST_LINKS], ifdef([AC_LIST_LINKS], [AC_LIST_LINKS ],)[$2])]) + +dnl Add additional commands for AC_OUTPUT to put into config.status. +dnl Use diversions instead of macros so we can be robust in the +dnl presence of commas in $1 and/or $2. +dnl AC_OUTPUT_COMMANDS(EXTRA-CMDS, INIT-CMDS) +AC_DEFUN(AC_OUTPUT_COMMANDS, +[AC_DIVERT_PUSH(AC_DIVERSION_CMDS)dnl +[$1] +AC_DIVERT_POP()dnl +AC_DIVERT_PUSH(AC_DIVERSION_ICMDS)dnl +[$2] +AC_DIVERT_POP()]) + +dnl AC_CONFIG_SUBDIRS(DIR ...) +AC_DEFUN(AC_CONFIG_SUBDIRS, +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +define([AC_LIST_SUBDIRS], ifdef([AC_LIST_SUBDIRS], [AC_LIST_SUBDIRS ],)[$1])dnl +subdirs="AC_LIST_SUBDIRS" +AC_SUBST(subdirs)dnl +]) + +dnl The big finish. +dnl Produce config.status, config.h, and links; and configure subdirs. +dnl AC_OUTPUT([FILE...] [, EXTRA-CMDS] [, INIT-CMDS]) +define(AC_OUTPUT, +[trap '' 1 2 15 +AC_CACHE_SAVE +trap 'rm -fr conftest* confdefs* core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='$(prefix)' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then +changequote(, )dnl + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +changequote([, ])dnl +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +ifdef([AC_LIST_HEADER], [DEFS=-DHAVE_CONFIG_H], [AC_OUTPUT_MAKE_DEFS()]) + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +[#] [$]0 [$]ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +changequote(, )dnl +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +changequote([, ])dnl +for ac_option +do + case "[\$]ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running [\$]{CONFIG_SHELL-/bin/sh} [$]0 [$]ac_configure_args --no-create --no-recursion" + exec [\$]{CONFIG_SHELL-/bin/sh} [$]0 [$]ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version AC_ACVERSION" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "[\$]ac_cs_usage"; exit 0 ;; + *) echo "[\$]ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ifdef([AC_PROVIDE_AC_PROG_INSTALL], [ac_given_INSTALL="$INSTALL" +])dnl + +changequote(<<, >>)dnl +ifdef(<>, +<>, +<>) +changequote([, ])dnl +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +undivert(AC_DIVERSION_CMDS)dnl +$2 +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 +dnl config.status should not do recursion. +ifdef([AC_LIST_SUBDIRS], [AC_OUTPUT_SUBDIRS(AC_LIST_SUBDIRS)])dnl +])dnl + +dnl Set the DEFS variable to the -D options determined earlier. +dnl This is a subroutine of AC_OUTPUT. +dnl It is called inside configure, outside of config.status. +dnl AC_OUTPUT_MAKE_DEFS() +define(AC_OUTPUT_MAKE_DEFS, +[# Transform confdefs.h into DEFS. +dnl Using a here document instead of a string reduces the quoting nightmare. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +cat > conftest.defs <<\EOF +changequote(<<, >>)dnl +s%<<#define>> \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g +s%[ `~<<#>>$^&*(){}\\|;'"<>?]%\\&%g +s%\[%\\&%g +s%\]%\\&%g +s%\$%$$%g +changequote([, ])dnl +EOF +DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '` +rm -f conftest.defs +]) + +dnl Do the variable substitutions to create the Makefiles or whatever. +dnl This is a subroutine of AC_OUTPUT. It is called inside an unquoted +dnl here document whose contents are going into config.status, but +dnl upon returning, the here document is being quoted. +dnl AC_OUTPUT_FILES(FILE...) +define(AC_OUTPUT_FILES, +[# Protect against being on the right side of a sed subst in config.status. +changequote(, )dnl +sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g; + s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF +changequote([, ])dnl +dnl These here document variables are unquoted when configure runs +dnl but quoted when config.status runs, so variables are expanded once. +$ac_vpsub +dnl Shell code in configure.in might set extrasub. +$extrasub +dnl Insert the sed substitutions of variables. +undivert(AC_DIVERSION_SED) +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then +changequote(, )dnl + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` +changequote([, ])dnl + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. +changequote(, )dnl + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` +changequote([, ])dnl + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + +ifdef([AC_PROVIDE_AC_PROG_INSTALL], +[ case "$ac_given_INSTALL" in +changequote(, )dnl + [/$]*) INSTALL="$ac_given_INSTALL" ;; +changequote([, ])dnl + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac +])dnl + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +ifdef([AC_PROVIDE_AC_PROG_INSTALL], [s%@INSTALL@%$INSTALL%g +])dnl +dnl The parens around the eval prevent an "illegal io" in Ultrix sh. +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +dnl This would break Makefile dependencies. +dnl if cmp -s $ac_file conftest.out 2>/dev/null; then +dnl echo "$ac_file is unchanged" +dnl rm -f conftest.out +dnl else +dnl rm -f $ac_file +dnl mv conftest.out $ac_file +dnl fi +fi; done +rm -f conftest.s* +]) + +dnl Create the config.h files from the config.h.in files. +dnl This is a subroutine of AC_OUTPUT. It is called inside a quoted +dnl here document whose contents are going into config.status. +dnl AC_OUTPUT_HEADER(HEADER-FILE...) +define(AC_OUTPUT_HEADER, +[changequote(<<, >>)dnl +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='<<$>>%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' +# ac_f turns "#define NAME" without trailing blanks into "#define NAME VALUE". +ac_fA='s%^\([ ]*\)#\([ ]*\)define\([ ][ ]*\)' +ac_fB='<<$>>%\1#\2define\3' +ac_fC=' ' +ac_fD='%g' +changequote([, ])dnl + +if test "${CONFIG_HEADERS+set}" != set; then +EOF +dnl Support passing AC_CONFIG_HEADER a value containing shell variables. +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then +changequote(, )dnl + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac +changequote([, ])dnl + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +dnl Using a here document instead of a string reduces the quoting nightmare. +dnl Putting comments in sed scripts is not portable. +cat > conftest.hdr <<\EOF +changequote(<<, >>)dnl +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%<<#define>> \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +s%ac_e%ac_f%gp +changequote([, ])dnl +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +dnl This is not necessary at all: Just write +dnl #ifndef _POSIX_SOURCE +dnl #undef _POSIX_SOURCE +dnl #endif +dnl instead of +dnl #undef _POSIX_SOURCE +dnl +dnl # This sed command replaces #undef with comments. This is necessary, for +dnl # example, in the case of _POSIX_SOURCE, which is predefined and required +dnl # on some systems where configure will not decide to define it. +dnl cat >> conftest.vals <<\EOF +dnl changequote(, )dnl +dnl s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +dnl changequote([, ])dnl +dnl EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +dnl Now back to your regularly scheduled config.status. +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. +changequote(, )dnl + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` +changequote([, ])dnl + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +]) + +dnl This is a subroutine of AC_OUTPUT. It is called inside a quoted +dnl here document whose contents are going into config.status. +dnl AC_OUTPUT_LINKS(SOURCE..., DEST...) +define(AC_OUTPUT_LINKS, +[EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +srcdir=$ac_given_srcdir +while test -n "$ac_sources"; do + set $ac_dests; ac_dest=[$]1; shift; ac_dests=[$]* + set $ac_sources; ac_source=[$]1; shift; ac_sources=[$]* + + echo "linking $srcdir/$ac_source to $ac_dest" + + if test ! -r $srcdir/$ac_source; then + AC_MSG_ERROR($srcdir/$ac_source: File not found) + fi + rm -f $ac_dest + + # Make relative symlinks. + # Remove last slash and all that follows it. Not all systems have dirname. +changequote(, )dnl + ac_dest_dir=`echo $ac_dest|sed 's%/[^/][^/]*$%%'` +changequote([, ])dnl + if test "$ac_dest_dir" != "$ac_dest" && test "$ac_dest_dir" != .; then + # The dest file is in a subdirectory. + test ! -d "$ac_dest_dir" && mkdir "$ac_dest_dir" + ac_dest_dir_suffix="/`echo $ac_dest_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dest_dir_suffix. +changequote(, )dnl + ac_dots=`echo $ac_dest_dir_suffix|sed 's%/[^/]*%../%g'` +changequote([, ])dnl + else + ac_dest_dir_suffix= ac_dots= + fi + + case "$srcdir" in +changequote(, )dnl + [/$]*) ac_rel_source="$srcdir/$ac_source" ;; +changequote([, ])dnl + *) ac_rel_source="$ac_dots$srcdir/$ac_source" ;; + esac + + # Make a symlink if possible; otherwise try a hard link. + if ln -s $ac_rel_source $ac_dest 2>/dev/null || + ln $srcdir/$ac_source $ac_dest; then : + else + AC_MSG_ERROR(can not link $ac_dest to $srcdir/$ac_source) + fi +done +]) + +dnl This is a subroutine of AC_OUTPUT. +dnl It is called after running config.status. +dnl AC_OUTPUT_SUBDIRS(DIRECTORY...) +define(AC_OUTPUT_SUBDIRS, +[ +if test "$no_recursion" != yes; then + + # Remove --cache-file and --srcdir arguments so they do not pile up. + ac_sub_configure_args= + ac_prev= + for ac_arg in $ac_configure_args; do + if test -n "$ac_prev"; then + ac_prev= + continue + fi + case "$ac_arg" in + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + ;; + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + ;; + *) ac_sub_configure_args="$ac_sub_configure_args $ac_arg" ;; + esac + done + + for ac_config_dir in $1; do + + # Do not complain, so a configure script can configure whichever + # parts of a large source tree are present. + if test ! -d $srcdir/$ac_config_dir; then + continue + fi + + echo configuring in $ac_config_dir + + case "$srcdir" in + .) ;; + *) + if test -d ./$ac_config_dir || mkdir ./$ac_config_dir; then :; + else + AC_MSG_ERROR(can not create `pwd`/$ac_config_dir) + fi + ;; + esac + + ac_popdir=`pwd` + cd $ac_config_dir + +changequote(, )dnl + # A "../" for each directory in /$ac_config_dir. + ac_dots=`echo $ac_config_dir|sed -e 's%^\./%%' -e 's%[^/]$%&/%' -e 's%[^/]*/%../%g'` +changequote([, ])dnl + + case "$srcdir" in + .) # No --srcdir option. We are building in place. + ac_sub_srcdir=$srcdir ;; + /*) # Absolute path. + ac_sub_srcdir=$srcdir/$ac_config_dir ;; + *) # Relative path. + ac_sub_srcdir=$ac_dots$srcdir/$ac_config_dir ;; + esac + + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_sub_srcdir/configure; then + ac_sub_configure=$ac_sub_srcdir/configure + elif test -f $ac_sub_srcdir/configure.in; then + ac_sub_configure=$ac_configure + else + AC_MSG_WARN(no configuration information is in $ac_config_dir) + ac_sub_configure= + fi + + # The recursion is here. + if test -n "$ac_sub_configure"; then + + # Make the cache file name correct relative to the subdirectory. + case "$cache_file" in + /*) ac_sub_cache_file=$cache_file ;; + *) # Relative path. + if test -n "$ac_dots"; then + ac_sub_cache_file="$ac_dots"`echo "$cache_file" | sed 's,^\./,,'` + else + ac_sub_cache_file="$cache_file" + fi + ;; + esac +ifdef([AC_PROVIDE_AC_PROG_INSTALL], + [ case "$ac_given_INSTALL" in +changequote(, )dnl + [/$]*) INSTALL="$ac_given_INSTALL" ;; +changequote([, ])dnl + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac +])dnl + + echo "[running ${CONFIG_SHELL-/bin/sh} $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file] --srcdir=$ac_sub_srcdir" + # The eval makes quoting arguments work. + if eval ${CONFIG_SHELL-/bin/sh} $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_sub_srcdir + then : + else + AC_MSG_ERROR($ac_sub_configure failed for $ac_config_dir) + fi + fi + + cd $ac_popdir + done +fi +]) diff --git a/autoconf/aclocal.m4 b/autoconf/aclocal.m4 new file mode 100644 index 0000000..2042cf7 --- /dev/null +++ b/autoconf/aclocal.m4 @@ -0,0 +1,937 @@ +dnl local autoconf macros +dnl Bruno Haible 21.9.1997 +dnl Marcus Daniels 10.4.1997 +dnl +AC_PREREQ(2.12)dnl +dnl +dnl without AC_MSG_...: with AC_MSG_... and caching: +dnl AC_TRY_CPP CL_CPP_CHECK +dnl AC_TRY_COMPILE CL_COMPILE_CHECK +dnl AC_TRY_LINK CL_LINK_CHECK +dnl AC_TRY_RUN CL_RUN_CHECK - would require cross-compiling support +dnl Usage: +dnl AC_TRY_CPP(INCLUDES, +dnl ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]) +dnl CL_CPP_CHECK(ECHO-TEXT, CACHE-ID, +dnl INCLUDES, +dnl ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]) +dnl AC_TRY_xxx(INCLUDES, FUNCTION-BODY, +dnl ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]) +dnl CL_xxx_CHECK(ECHO-TEXT, CACHE-ID, +dnl INCLUDES, FUNCTION-BODY, +dnl ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]) +dnl +define(CL_CPP_CHECK, +[AC_MSG_CHECKING(for $1) +AC_CACHE_VAL($2,[ +AC_TRY_CPP([$3], $2=yes, $2=no) +]) +AC_MSG_RESULT([$]$2) +if test [$]$2 = yes; then + ifelse([$4], , :, [$4]) +ifelse([$5], , , [else + $5 +])dnl +fi +])dnl +dnl +define(CL_COMPILE_CHECK, +[AC_MSG_CHECKING(for $1) +AC_CACHE_VAL($2,[ +AC_TRY_COMPILE([$3],[$4], $2=yes, $2=no) +]) +AC_MSG_RESULT([$]$2) +if test [$]$2 = yes; then + ifelse([$5], , :, [$5]) +ifelse([$6], , , [else + $6 +])dnl +fi +])dnl +dnl +define(CL_LINK_CHECK, +[AC_MSG_CHECKING(for $1) +AC_CACHE_VAL($2,[ +AC_TRY_LINK([$3],[$4], $2=yes, $2=no) +]) +AC_MSG_RESULT([$]$2) +if test [$]$2 = yes; then + ifelse([$5], , :, [$5]) +ifelse([$6], , , [else + $6 +])dnl +fi +])dnl +dnl +dnl CL_PROTO(IDENTIFIER, ACTION-IF-NOT-FOUND, FINAL-PROTOTYPE) +define(CL_PROTO, +[AC_MSG_CHECKING([for $1 declaration]) +AC_CACHE_VAL(cl_cv_proto_[$1], [$2 +cl_cv_proto_$1="$3"]) +cl_cv_proto_$1=`echo "[$]cl_cv_proto_$1" | tr -s ' ' | sed -e 's/( /(/'` +AC_MSG_RESULTPROTO([$]cl_cv_proto_$1) +])dnl +dnl +dnl CL_PROTO_RET(INCLUDES, DECL, CACHE-ID, TYPE-IF-OK, TYPE-IF-FAILS) +define(CL_PROTO_RET, +[AC_TRY_COMPILE([$1] +AC_LANG_EXTERN[$2 +], [], $3="$4", $3="$5") +])dnl +dnl +dnl CL_PROTO_TRY(INCLUDES, ANSI-DECL, TRAD-DECL, ACTION-IF-OK, ACTION-IF-FAILS) +define(CL_PROTO_TRY, +[AC_TRY_COMPILE([$1] +AC_LANG_EXTERN +[#if defined(__STDC__) || defined(__cplusplus) +$2 +#else +$3 +#endif +], [], [$4], [$5]) +])dnl +dnl +dnl CL_PROTO_CONST(INCLUDES, ANSI-DECL, TRAD-DECL, CACHE-ID) +define(CL_PROTO_CONST, +[CL_PROTO_TRY([$1], [$2], [$3], $4="", $4="const")] +)dnl +dnl +dnl CL_SILENT(ACTION) +dnl performs ACTION, with AC_MSG_CHECKING and AC_MSG_RESULT being defined away. +define(CL_SILENT, +[pushdef([AC_MSG_CHECKING],[:])dnl +pushdef([AC_CHECKING],[:])dnl +pushdef([AC_MSG_RESULT],[:])dnl +pushdef([AC_MSG_RESULTPROTO],[:])dnl +$1[]dnl +popdef([AC_MSG_RESULTPROTO])dnl +popdef([AC_MSG_RESULT])dnl +popdef([AC_CHECKING])dnl +popdef([AC_MSG_CHECKING])dnl +])dnl +dnl +AC_DEFUN(CL_AS_UNDERSCORE, +[AC_BEFORE([$0], [CL_GLOBAL_CONSTRUCTORS]) +AC_CACHE_CHECK(for underscore in external names, cl_cv_prog_as_underscore, [ +cat > conftest.c </dev/null 2>&1 +if grep _foo conftest.s >/dev/null ; then + cl_cv_prog_as_underscore=yes +else + cl_cv_prog_as_underscore=no +fi +rm -f conftest* +]) +if test $cl_cv_prog_as_underscore = yes; then + AS_UNDERSCORE=true + AC_DEFINE(ASM_UNDERSCORE) +else + AS_UNDERSCORE=false +fi +AC_SUBST(AS_UNDERSCORE)dnl +])dnl +dnl +AC_DEFUN(CL_PROG_RANLIB, [AC_CHECK_PROG(RANLIB, ranlib, ranlib, true)])dnl +dnl +AC_DEFUN(CL_PROG_INSTALL, +[dnl This is mostly copied from AC_PROG_INSTALL. +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +AC_MSG_CHECKING(for a BSD compatible install) +if test -z "$INSTALL"; then +AC_CACHE_VAL(cl_cv_path_install, +[ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + for ac_prog in ginstall installbsd scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + # OSF/1 installbsd also uses dspmsg, but is usable. + : + else + if test $ac_prog = installbsd && + grep src/bos $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX installbsd doesn't work without option "-g". + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + fi + done + ;; + esac + done + IFS="$ac_save_ifs" + # As a last resort, use cp. + test -z "$cl_cv_path_install" && cl_cv_path_install="cp" +])dnl + INSTALL="$cl_cv_path_install" +fi +dnl We do special magic for INSTALL instead of AC_SUBST, to get +dnl relative paths right. +AC_MSG_RESULT($INSTALL) +AC_SUBST(INSTALL)dnl +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='$(INSTALL)' +AC_SUBST(INSTALL_PROGRAM)dnl +if test -z "$INSTALL_DATA"; then + case "$INSTALL" in + cp | */cp ) INSTALL_DATA='$(INSTALL)' ;; + * ) INSTALL_DATA='$(INSTALL) -m 644' ;; + esac +fi +AC_SUBST(INSTALL_DATA)dnl +])dnl +dnl +AC_DEFUN(CL_CANONICAL_HOST, +[AC_REQUIRE([AC_PROG_CC]) dnl Actually: AC_REQUIRE([CL_CC_WORKS]) +dnl Set ac_aux_dir before the cache check, because AM_PROG_LIBTOOL needs it. +ac_aux_dir=${srcdir}/$1 +AC_CACHE_CHECK(host system type, cl_cv_host, [ +dnl A substitute for AC_CONFIG_AUX_DIR_DEFAULT, so we don't need install.sh. +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +dnl Mostly copied from AC_CANONICAL_HOST. +# Make sure we can run config.sub. +if $ac_config_sub sun4 >/dev/null 2>&1; then : +else AC_MSG_ERROR(can not run $ac_config_sub) +fi +host_alias=$host +case "$host_alias" in +NONE) + case $nonopt in + NONE) dnl config.guess needs to compile things + host_alias=`export CC; $ac_config_guess` ;; + *) host_alias=$nonopt ;; + esac ;; +esac +# Don't fail just because the system is not listed in GNU's database. +if test -n "$host_alias"; then + host=`$ac_config_sub $host_alias` +else + host=unknown-unknown-unknown +fi +cl_cv_host="$host" +]) +host="$cl_cv_host" +host_cpu=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'` +AC_SUBST(host)dnl +AC_SUBST(host_cpu)dnl +AC_SUBST(host_vendor)dnl +AC_SUBST(host_os)dnl +])dnl +dnl +AC_DEFUN(CL_CANONICAL_HOST_CPU, +[AC_REQUIRE([CL_CANONICAL_HOST])AC_REQUIRE([AC_PROG_CC]) +case "$host_cpu" in +changequote(,)dnl + i[4567]86 ) + host_cpu=i386 + ;; + alphaev[4-7] | alphaev56 | alphapca5[67] ) + host_cpu=alpha + ;; + hppa1.0 | hppa1.1 | hppa2.0 ) + host_cpu=hppa + ;; + powerpc ) + host_cpu=rs6000 + ;; + c1 | c2 | c32 | c34 | c38 | c4 ) + host_cpu=convex + ;; +changequote([,])dnl + mips ) + AC_CACHE_CHECK([for 64-bit MIPS], cl_cv_host_mips64, [ +AC_EGREP_CPP(yes, +[#if defined(_MIPS_SZLONG) +#if (_MIPS_SZLONG == 64) +/* We should also check for (_MIPS_SZPTR == 64), but gcc keeps this at 32. */ + yes +#endif +#endif +], cl_cv_host_mips64=yes, cl_cv_host_mips64=no) +]) +if test $cl_cv_host_mips64 = yes; then + host_cpu=mips64 +fi + ;; +dnl UltraSPARCs running Linux have `uname -m` = "sparc64", but the C compiler +dnl still generates 32-bit code. + sparc | sparc64 ) + AC_CACHE_CHECK([for 64-bit SPARC], cl_cv_host_sparc64, [ +AC_EGREP_CPP(yes, +[#if defined(__sparcv9) || defined(__arch64__) + yes +#endif +], cl_cv_host_sparc64=yes, cl_cv_host_sparc64=no) +]) +if test $cl_cv_host_sparc64 = yes; then + host_cpu=sparc64 +else + host_cpu=sparc +fi + ;; +esac +dnl was AC_DEFINE_UNQUOTED(__${host_cpu}__) but KAI C++ 3.2d doesn't like this +cat >> confdefs.h <>32 == z)); + } +}], +cl_cv_c_longlong=yes, cl_cv_c_longlong=no, +dnl When cross-compiling, don't assume anything. +cl_cv_c_longlong="guessing no") +]) +case "$cl_cv_c_longlong" in + *yes) AC_DEFINE(HAVE_LONGLONG) ;; + *no) ;; +esac +])dnl +dnl +AC_DEFUN(CL_LONGDOUBLE, +[AC_CACHE_CHECK(for long double type, cl_cv_c_longdouble, [ +AC_TRY_RUN([int main() +{ long double x = 2.7182818284590452354L; x = x*x; exit (x==0.0L); }], +cl_cv_c_longdouble=yes, cl_cv_c_longdouble=no, +dnl When cross-compiling, don't assume anything. +cl_cv_c_longdouble="guessing no") +]) +case "$cl_cv_c_longdouble" in + *yes) AC_DEFINE(HAVE_LONGDOUBLE) ;; + *no) ;; +esac +])dnl +dnl +AC_DEFUN(CL_TEMPLATE_NULL, +[CL_COMPILE_CHECK([working template<>], cl_cv_c_templatenull, +[template class c {}; template <> class c { int x; };], , +AC_DEFINE(HAVE_TEMPLATE_NULL)) +])dnl +dnl +AC_DEFUN(CL_UNISTD_H, +[AC_CHECK_HEADERS(unistd.h)] +)dnl +dnl +AC_DEFUN(CL_ALLOCA, +[# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works +# for constant arguments. Useless! +CL_LINK_CHECK(working alloca.h, cl_cv_header_alloca_h, +[#include ], [char *p = (char *) alloca(2 * sizeof(int));], +AC_DEFINE(HAVE_ALLOCA_H))dnl +decl="#ifdef __GNUC__ +#define alloca __builtin_alloca +#else +#ifdef _MSC_VER +#include +#define alloca _alloca +#else +#ifdef HAVE_ALLOCA_H +#include +#else +#ifdef _AIX + #pragma alloca +#else +#ifndef alloca +char *alloca (); +#endif +#endif +#endif +#endif +#endif +" +CL_LINK_CHECK([alloca], cl_cv_func_alloca, +$decl, [char *p = (char *) alloca(1);], + , [alloca_missing=1])dnl +if test -n "$alloca_missing"; then + # The SVR3 libPW and SVR4 libucb both contain incompatible functions + # that cause trouble. Some versions do not even contain alloca or + # contain a buggy version. If you still want to use their alloca, + # use ar to extract alloca.o from them instead of compiling alloca.c. + ALLOCA=alloca.${ac_objext} + AC_DEFINE(NO_ALLOCA) +fi +AC_SUBST(ALLOCA)dnl +])dnl +dnl +AC_DEFUN(CL_FPU_CONTROL, +[dnl Check for Linux with and fpu_control_t or __setfpucw(). +dnl glibc versions since October 1998 define fpu_control_t. Earlier versions +dnl define and declare __setfpucw(). Very early Linux libc versions have none, +dnl and __fpu_control is of type `unsigned short'. +CL_COMPILE_CHECK([fpu_control_t], cl_cv_type_fpu_control_t, +[#include ], [fpu_control_t x;], +AC_DEFINE(HAVE_FPU_CONTROL_T)) +CL_COMPILE_CHECK([__setfpucw], cl_cv_func_setfpucw, +[#include ], [__setfpucw(_FPU_IEEE);], +AC_DEFINE(HAVE_SETFPUCW)) +])dnl +dnl +AC_DEFUN(CL_PERROR, +[AC_MSG_CHECKING(for perror declaration) +AC_CACHE_VAL(cl_cv_proto_perror, [ +AC_TRY_COMPILE([ +/* Some systems declare perror() in , some in , some don't + declare it at all. */ +#include +#include +]AC_LANG_EXTERN[double perror ();], [], +cl_cv_proto_perror=no, cl_cv_proto_perror=yes) +]) +AC_MSG_RESULT([$cl_cv_proto_perror]) +if test $cl_cv_proto_perror = yes; then +AC_DEFINE(HAVE_PERROR_DECL) +fi +])dnl +dnl +AC_DEFUN(CL_RUSAGE, +[AC_CHECK_HEADERS(sys/resource.h sys/times.h)dnl +if test $ac_cv_header_sys_resource_h = yes; then + dnl HAVE_SYS_RESOURCE_H defined + CL_LINK_CHECK([getrusage], cl_cv_func_getrusage, +[#include /* NetBSD 1.0 needs this */ +#include +#include ], + [struct rusage x; int y = RUSAGE_SELF; getrusage(y,&x); x.ru_utime.tv_sec;], + AC_DEFINE(HAVE_GETRUSAGE))dnl + if test $cl_cv_func_getrusage = yes; then + CL_PROTO([getrusage], [ + CL_PROTO_TRY([ +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include /* NetBSD 1.0 needs this */ +#include +#include +], +[int getrusage (int who, struct rusage * rusage);], +[int getrusage();], +[cl_cv_proto_getrusage_arg1="int"], +[cl_cv_proto_getrusage_arg1="enum __rusage_who"]) +], [extern int getrusage ($cl_cv_proto_getrusage_arg1, struct rusage *);]) + AC_DEFINE_UNQUOTED(RUSAGE_WHO_T,$cl_cv_proto_getrusage_arg1) + fi +fi +])dnl +dnl +AC_DEFUN(CL_GETTIMEOFDAY, +[AC_BEFORE([$0], [CL_TIMES_CLOCK]) +AC_CHECK_FUNCS(gettimeofday)dnl +if test $ac_cv_func_gettimeofday = yes; then +dnl HAVE_GETTIMEOFDAY is defined +CL_PROTO([gettimeofday], [ +CL_PROTO_TRY([ +#include +#include +], [int gettimeofday (struct timeval * tp, struct timezone * tzp);], +[int gettimeofday();], +cl_cv_proto_gettimeofday_dots=no +cl_cv_proto_gettimeofday_arg2="struct timezone *", +CL_PROTO_TRY([ +#include +#include +], [int gettimeofday (struct timeval * tp, void * tzp);], +[int gettimeofday();], +cl_cv_proto_gettimeofday_dots=no +cl_cv_proto_gettimeofday_arg2="void *", +cl_cv_proto_gettimeofday_dots=yes +cl_cv_proto_gettimeofday_arg2="...")) +], [extern int gettimeofday (struct timeval *, $cl_cv_proto_gettimeofday_arg2);]) +if test $cl_cv_proto_gettimeofday_dots = yes; then +AC_DEFINE(GETTIMEOFDAY_DOTS) +else +AC_DEFINE_UNQUOTED(GETTIMEOFDAY_TZP_T,$cl_cv_proto_gettimeofday_arg2) +fi +fi +])dnl +dnl +AC_DEFUN(CL_FTIME, +[AC_BEFORE([$0], [CL_TIMES_CLOCK]) +AC_CHECK_FUNCS(ftime)])dnl +dnl +AC_DEFUN(CL_TIMES_CLOCK, +[AC_REQUIRE([CL_GETTIMEOFDAY])dnl +AC_REQUIRE([CL_FTIME])dnl +if test $ac_cv_func_gettimeofday = no -a $ac_cv_func_ftime = no; then +AC_CHECK_FUNC(times, , no_times=1)dnl +if test -z "$no_times"; then +AC_CACHE_CHECK(for times return value, cl_cv_func_times_return, [ +AC_TRY_RUN([ +#include +#include /* needed for CLK_TCK */ +#ifndef CLK_TCK +#include /* needed for CLK_TCK on SYSV PTX */ +#endif +#include +int main () +{ struct tms buffer; + clock_t result1; + clock_t result2; + int ticks; + result1 = times(&buffer); + if ((result1 == (clock_t)0) || (result1 == (clock_t)(-1))) exit(1); + sleep(1); + result2 = times(&buffer); + if ((result2 == (clock_t)0) || (result2 == (clock_t)(-1))) exit(1); + ticks = result2 - result1; + exit(!((ticks >= CLK_TCK/2) && (ticks <= 3*CLK_TCK/2))); +}], cl_cv_func_times_return=yes, cl_cv_func_times_return=no, +dnl When cross-compiling, don't assume anything. +cl_cv_func_times_return="guessing no") +]) +case "$cl_cv_func_times_return" in + *yes) AC_DEFINE(HAVE_TIMES_CLOCK) ;; + *no) ;; +esac +fi +fi +])dnl +dnl +AC_DEFUN(CL_GLOBAL_CONSTRUCTORS, +[AC_REQUIRE([CL_AS_UNDERSCORE])dnl +if test -n "$GCC"; then +AC_CACHE_CHECK(for the global constructors function prefix, +cl_cv_cplusplus_ctorprefix, [ +cat > conftest.cc << EOF +struct foo { foo (); }; +foo foobar; +EOF +# look for the assembly language name in the .s file +AC_TRY_COMMAND(${CXX-g++} $CXXFLAGS -S conftest.cc) >/dev/null 2>&1 +if grep '_GLOBAL_\$I\$foobar' conftest.s >/dev/null ; then + cl_cv_cplusplus_ctorprefix='_GLOBAL_$I$' +else + if grep '_GLOBAL_\.I\.foobar' conftest.s >/dev/null ; then + cl_cv_cplusplus_ctorprefix='_GLOBAL_.I.' + else + if grep '_GLOBAL__I_foobar' conftest.s >/dev/null ; then + cl_cv_cplusplus_ctorprefix='_GLOBAL__I_' + else + cl_cv_cplusplus_ctorprefix=unknown + fi + fi +fi +rm -f conftest* +]) +if test "$cl_cv_cplusplus_ctorprefix" '!=' unknown; then + ac_value='"'"$cl_cv_cplusplus_ctorprefix"'"' + AC_DEFINE_UNQUOTED(CL_GLOBAL_CONSTRUCTOR_PREFIX,$ac_value) + ac_value=`echo "$ac_value" | sed -e 's,I,D,'` + AC_DEFINE_UNQUOTED(CL_GLOBAL_DESTRUCTOR_PREFIX,$ac_value) +dnl Check whether the global constructors/destructors functions are file-scope +dnl only by default. This is the case in egcs-1.1.2 or newer. +AC_CACHE_CHECK(whether the global constructors function need to be exported, +cl_cv_cplusplus_ctorexport, [ +cat > conftest1.cc << EOF +struct foo { foo (); }; +foo foobar; +EOF +cat > conftest2.cc << EOF +#include "confdefs.h" +#ifdef ASM_UNDERSCORE +#define ASM_UNDERSCORE_PREFIX "_" +#else +#define ASM_UNDERSCORE_PREFIX "" +#endif +struct foo { foo (); }; +foo::foo () {} +extern "C" void ctor (void) __asm__ (ASM_UNDERSCORE_PREFIX CL_GLOBAL_CONSTRUCTOR_PREFIX "foobar"); +int main() { ctor(); return 0; } +EOF +if AC_TRY_COMMAND(${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest1.cc conftest2.cc $LIBS 1>&5) >/dev/null 2>&1 && test -s conftest${ac_exeext}; then + cl_cv_cplusplus_ctorexport=no +else + cl_cv_cplusplus_ctorexport=yes +fi +rm -f conftest* +]) +if test "$cl_cv_cplusplus_ctorexport" = yes; then + AC_DEFINE(CL_NEED_GLOBALIZE_CTORDTOR) +fi +fi +fi +])dnl +dnl +AC_DEFUN(CL_CHAR_UNSIGNED, +[dnl This is mostly copied from AC_C_CHAR_UNSIGNED. +AC_CACHE_CHECK(whether characters are unsigned, ac_cv_c_char_unsigned, [ +if test $ac_cv_prog_gcc = yes; then + # GCC predefines this symbol on systems where it applies. +AC_EGREP_CPP(yes, +[#ifdef __CHAR_UNSIGNED__ + yes +#endif +], ac_cv_c_char_unsigned=yes, ac_cv_c_char_unsigned=no) +else +AC_TRY_RUN( +[/* volatile prevents gcc2 from optimizing the test away on sparcs. */ +#if !defined(__STDC__) || __STDC__ != 1 +#define volatile +#endif +int main() { + volatile char c = 255; exit(c < 0); +}], ac_cv_c_char_unsigned=yes, ac_cv_c_char_unsigned=no, +ac_cv_c_char_unsigned="guessing no") +fi]) +if test $ac_cv_prog_gcc = no; then + # GCC defines __CHAR_UNSIGNED__ by itself, no need to fix up. + case "$ac_cv_c_char_unsigned" in + *yes) AC_DEFINE(__CHAR_UNSIGNED__) ;; + *no) ;; + esac +fi +])dnl +dnl +AC_DEFUN(CL_BOOL, +[AC_LANG_SAVE() +AC_LANG_CPLUSPLUS() +CL_COMPILE_CHECK([bool type], cl_cv_cplusplus_bool, , [bool x;], +AC_DEFINE(HAVE_BOOL), AC_DEFINE(bool,int))dnl +AC_LANG_RESTORE() +])dnl +dnl +AC_DEFUN(CL_MACHINE, +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([CL_CHAR_UNSIGNED])dnl +cl_machine_file_c=$2 +cl_machine_file_h=$3 +if test $cross_compiling = no; then +if test -z "$[$4]"; then +AC_CHECKING(for [$1]) +cat > conftest.$ac_ext <> conftest.$ac_ext +ORIGCC="$CC" +if test $ac_cv_prog_gcc = yes; then +# gcc -O (gcc version <= 2.3.2) crashes when compiling long long shifts for +# target 80386. Strip "-O". +CC=`echo "$CC " | sed -e 's/-O //g'` +fi +AC_TRY_EVAL(ac_link) +CC="$ORIGCC" +if test -s conftest; then + echo "creating $cl_machine_file_h" + ./conftest > conftest.h + if cmp -s "$cl_machine_file_h" conftest.h 2>/dev/null; then + # The file exists and we would not be changing it + rm -f conftest.h + else + rm -f "$cl_machine_file_h" + mv conftest.h "$cl_machine_file_h" + fi + [$4]=1 +else + echo "creation of $cl_machine_file_h failed" +fi +rm -f conftest* +fi +else +echo "cross-compiling - cannot create $cl_machine_file_h" +fi +])dnl +dnl +## libtool.m4 - Configure libtool for the target system. -*-Shell-script-*- +## Copyright (C) 1996-1998 Free Software Foundation, Inc. +## Gordon Matzigkeit , 1996 +## +## 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. +## +## 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. + +# serial 24 AM_PROG_LIBTOOL +AC_DEFUN(AM_PROG_LIBTOOL, +[AC_REQUIRE([AM_ENABLE_SHARED])dnl +AC_REQUIRE([AM_ENABLE_STATIC])dnl +AC_REQUIRE([CL_CANONICAL_HOST])dnl +AC_REQUIRE([CL_PROG_RANLIB])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AM_PROG_LD])dnl +AC_REQUIRE([AM_PROG_NM])dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +dnl +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +# Check for any special flags to pass to ltconfig. +libtool_flags= +test "$enable_shared" = no && libtool_flags="$libtool_flags --disable-shared" +test "$enable_static" = no && libtool_flags="$libtool_flags --disable-static" +test "$silent" = yes && libtool_flags="$libtool_flags --silent" +test "$ac_cv_prog_gcc" = yes && libtool_flags="$libtool_flags --with-gcc" +test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld" + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case "$host" in +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line __oline__ "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case "`/usr/bin/file conftest.o`" in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + CFLAGS="$CFLAGS -belf" + ;; +esac + +# Actually configure libtool. ac_aux_dir is where install-sh is found. +CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \ +LD="$LD" NM="$NM" RANLIB="$RANLIB" LN_S="$LN_S" \ +${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig \ +$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $host \ +|| AC_MSG_ERROR([libtool configure failed]) +]) + +# AM_ENABLE_SHARED - implement the --enable-shared flag +# Usage: AM_ENABLE_SHARED[(DEFAULT)] +# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to +# `yes'. +AC_DEFUN(AM_ENABLE_SHARED, +[define([AM_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE(shared, +changequote(<<, >>)dnl +<< --enable-shared build shared libraries [default=>>AM_ENABLE_SHARED_DEFAULT] +changequote([, ])dnl +[ --enable-shared=PKGS only build shared libraries if the current package + appears as an element in the PKGS list], +[p=${PACKAGE-default} +case "$enableval" in +yes) enable_shared=yes ;; +no) enable_shared=no ;; +*) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac], +enable_shared=AM_ENABLE_SHARED_DEFAULT)dnl +]) + +# AM_DISABLE_SHARED - set the default shared flag to --disable-shared +AC_DEFUN(AM_DISABLE_SHARED, +[AM_ENABLE_SHARED(no)]) + +# AM_DISABLE_STATIC - set the default static flag to --disable-static +AC_DEFUN(AM_DISABLE_STATIC, +[AM_ENABLE_STATIC(no)]) + +# AM_ENABLE_STATIC - implement the --enable-static flag +# Usage: AM_ENABLE_STATIC[(DEFAULT)] +# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to +# `yes'. +AC_DEFUN(AM_ENABLE_STATIC, +[define([AM_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE(static, +changequote(<<, >>)dnl +<< --enable-static build static libraries [default=>>AM_ENABLE_STATIC_DEFAULT] +changequote([, ])dnl +[ --enable-static=PKGS only build shared libraries if the current package + appears as an element in the PKGS list], +[p=${PACKAGE-default} +case "$enableval" in +yes) enable_static=yes ;; +no) enable_static=no ;; +*) + enable_static=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac], +enable_static=AM_ENABLE_STATIC_DEFAULT)dnl +]) + + +# AM_PROG_LD - find the path to the GNU or non-GNU linker +AC_DEFUN(AM_PROG_LD, +[AC_ARG_WITH(gnu-ld, +[ --with-gnu-ld assume the C compiler uses GNU ld [default=no]], +test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no) +AC_REQUIRE([AC_PROG_CC]) +ac_prog=ld +if test "$ac_cv_prog_gcc" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by GCC]) + ac_prog=`($CC -print-prog-name=ld) 2>&5` + case "$ac_prog" in + # Accept absolute paths. + /* | [A-Za-z]:\\*) + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(ac_cv_path_LD, +[if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog"; then + ac_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then + test "$with_gnu_ld" != no && break + else + test "$with_gnu_ld" != yes && break + fi + fi + done + IFS="$ac_save_ifs" +else + ac_cv_path_LD="$LD" # Let the user override the test with a path. +fi]) +LD="$ac_cv_path_LD" +if test -n "$LD"; then + AC_MSG_RESULT($LD) +else + AC_MSG_RESULT(no) +fi +test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) +AC_SUBST(LD) +AM_PROG_LD_GNU +]) + +AC_DEFUN(AM_PROG_LD_GNU, +[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], ac_cv_prog_gnu_ld, +[# I'd rather use --version here, but apparently some GNU ld's only accept -v. +if $LD -v 2>&1 &5; then + ac_cv_prog_gnu_ld=yes +else + ac_cv_prog_gnu_ld=no +fi]) +]) + +# AM_PROG_NM - find the path to a BSD-compatible name lister +AC_DEFUN(AM_PROG_NM, +[AC_MSG_CHECKING([for BSD-compatible nm]) +AC_CACHE_VAL(ac_cv_path_NM, +[case "$NM" in +/* | [A-Za-z]:\\*) + ac_cv_path_NM="$NM" # Let the user override the test with a path. + ;; +*) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in /usr/ucb /usr/ccs/bin $PATH /bin; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/nm; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + ac_cv_path_NM="$ac_dir/nm -B" + elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + ac_cv_path_NM="$ac_dir/nm -p" + else + ac_cv_path_NM="$ac_dir/nm" + fi + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm + ;; +esac]) +NM="$ac_cv_path_NM" +AC_MSG_RESULT([$NM]) +AC_SUBST(NM) +]) diff --git a/autoconf/acspecific.m4 b/autoconf/acspecific.m4 new file mode 100644 index 0000000..2f2d9e8 --- /dev/null +++ b/autoconf/acspecific.m4 @@ -0,0 +1,2867 @@ +dnl Macros that test for specific features. +dnl This file is part of Autoconf. +dnl Copyright (C) 1992, 93, 94, 95, 96, 1998 Free Software Foundation, Inc. +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception, the Free Software Foundation gives unlimited +dnl permission to copy, distribute and modify the configure scripts that +dnl are the output of Autoconf. You need not follow the terms of the GNU +dnl General Public License when using or distributing such scripts, even +dnl though portions of the text of Autoconf appear in them. The GNU +dnl General Public License (GPL) does govern all other use of the material +dnl that constitutes the Autoconf program. +dnl +dnl Certain portions of the Autoconf source text are designed to be copied +dnl (in certain cases, depending on the input) into the output of +dnl Autoconf. We call these the "data" portions. The rest of the Autoconf +dnl source text consists of comments plus executable code that decides which +dnl of the data portions to output in any given case. We call these +dnl comments and executable code the "non-data" portions. Autoconf never +dnl copies any of the non-data portions into its output. +dnl +dnl This special exception to the GPL applies to versions of Autoconf +dnl released by the Free Software Foundation. When you make and +dnl distribute a modified version of Autoconf, you may extend this special +dnl exception to the GPL to apply to your modified version as well, *unless* +dnl your modified version has the potential to copy into its output some +dnl of the text that was the non-data portion of the version that you started +dnl with. (In other words, unless your change moves or copies text from +dnl the non-data portions to the data portions.) If your modification has +dnl such potential, you must delete any notice of this special exception +dnl to the GPL from your modified version. +dnl +dnl Written by David MacKenzie, with help from +dnl Franc,ois Pinard, Karl Berry, Richard Pixley, Ian Lance Taylor, +dnl Roland McGrath, Noah Friedman, david d zuhn, and many others. +dnl +dnl Changed by Bruno Haible, 18 January 1999 + + +dnl ### Checks for programs + + +dnl Check whether to use -n, \c, or newline-tab to separate +dnl checking messages from result messages. +dnl Idea borrowed from dist 3.0. +dnl Internal use only. +AC_DEFUN(AC_PROG_ECHO_N, +[if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' ac_tt= + else + ac_n=-n ac_c= ac_t= ac_tt=' + ' + fi +else + ac_n= ac_c='\c' ac_t= ac_tt=' + ' +fi +]) + +AC_DEFUN(AC_PROG_CC, +[AC_BEFORE([$0], [AC_PROG_CPP])dnl +AC_CHECK_PROG(CC, gcc, gcc) +if test -z "$CC"; then + AC_CHECK_PROG(CC, cc, cc, , , /usr/ucb/cc) + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + AC_CHECK_PROG(CC, cl, cl) ;; + esac + fi + test -z "$CC" && AC_MSG_ERROR([no acceptable cc found in \$PATH]) +fi + +AC_PROG_CC_WORKS +AC_PROG_CC_GNU + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +dnl Check whether -g works, even if CFLAGS is set, in case the package +dnl plays around with CFLAGS (such as to build both debugging and +dnl normal versions of a library), tasteless as that idea is. +ac_test_CFLAGS="${CFLAGS+set}" +ac_save_CFLAGS="$CFLAGS" +CFLAGS= +dnl AC_PROG_CC_G +if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" +dnl # This doesn't work on Linux (libc-4.5.26): Because of differences between +dnl # the shared and the static libraries there are less symbols available +dnl # without -g than with -g. It is therefore better to run the configuration +dnl # without -g and to add -g afterwards than the contrary. So don't add +dnl # -g to the CFLAGS now. +dnl elif test $ac_cv_prog_cc_g = yes; then +dnl if test "$GCC" = yes; then +dnl CFLAGS="-g -O2" +dnl else +dnl CFLAGS="-g" +dnl fi +else + if test "$GCC" = yes; then +dnl CFLAGS="-O" + # Add "-O" to both the CC and CPP commands, to eliminate possible confusion + # that results from __OPTIMIZE__ being defined for CC but not CPP. +changequote(, )dnl + if echo "$CC " | grep ' -O[1-9 ]' > /dev/null 2>&1; then +changequote([, ])dnl + : # already optimizing + else + CC="$CC -O" + ac_cv_prog_CC="$CC" + fi + else + CFLAGS= + fi +fi +]) + +AC_DEFUN(AC_PROG_CXX, +[AC_BEFORE([$0], [AC_PROG_CXXCPP])dnl +AC_CHECK_PROGS(CXX, $CCC c++ g++ gcc CC cxx cc++ cl, gcc) + +AC_PROG_CXX_WORKS +AC_PROG_CXX_GNU + +if test $ac_cv_prog_gxx = yes; then + GXX=yes +else + GXX= +fi + +dnl Check whether -g works, even if CXXFLAGS is set, in case the package +dnl plays around with CXXFLAGS (such as to build both debugging and +dnl normal versions of a library), tasteless as that idea is. +ac_test_CXXFLAGS="${CXXFLAGS+set}" +ac_save_CXXFLAGS="$CXXFLAGS" +CXXFLAGS= +dnl AC_PROG_CXX_G +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS="$ac_save_CXXFLAGS" +dnl # This doesn't work on Linux (libc-4.5.26): Because of differences between +dnl # the shared and the static libraries there are less symbols available +dnl # without -g than with -g. It is therefore better to run the configuration +dnl # without -g and to add -g afterwards than the contrary. So don't add +dnl # -g to the CFLAGS now. +dnl elif test $ac_cv_prog_cxx_g = yes; then +dnl if test "$GXX" = yes; then +dnl CXXFLAGS="-g -O2" +dnl else +dnl CXXFLAGS="-g" +dnl fi +else + if test "$GXX" = yes; then +dnl CXXFLAGS="-O" + # Add "-O" to both the CXX and CXXCPP commands, to eliminate possible confu- + # sion that results from __OPTIMIZE__ being defined for CXX but not CXXCPP. +changequote(, )dnl + if echo "$CXX " | grep ' -O[1-9 ]' > /dev/null; then +changequote([, ])dnl + : # already optimizing + else + CXX="$CXX -O" + ac_cv_prog_CXX="$CXX" + fi + else + CXXFLAGS= + fi +fi +]) + +dnl Determine a Fortran 77 compiler to use. If `F77' is not already set +dnl in the environment, check for `g77', `f77' and `f2c', in that order. +dnl Set the output variable `F77' to the name of the compiler found. +dnl +dnl If using `g77' (the GNU Fortran 77 compiler), then `AC_PROG_F77' +dnl will set the shell variable `G77' to `yes', and empty otherwise. If +dnl the output variable `FFLAGS' was not already set in the environment, +dnl then set it to `-g -02' for `g77' (or `-O2' where `g77' does not +dnl accept `-g'). Otherwise, set `FFLAGS' to `-g' for all other Fortran +dnl 77 compilers. +dnl +dnl AC_PROG_F77() +AC_DEFUN(AC_PROG_F77, +[AC_BEFORE([$0], [AC_PROG_CPP])dnl +if test -z "$F77"; then + AC_CHECK_PROGS(F77, g77 f77 f2c) + test -z "$F77" && AC_MSG_ERROR([no acceptable Fortran 77 compiler found in \$PATH]) +fi + +AC_PROG_F77_WORKS +AC_PROG_F77_GNU + +if test $ac_cv_prog_g77 = yes; then + G77=yes +dnl Check whether -g works, even if FFLAGS is set, in case the package +dnl plays around with FFLAGS (such as to build both debugging and +dnl normal versions of a library), tasteless as that idea is. + ac_test_FFLAGS="${FFLAGS+set}" + ac_save_FFLAGS="$FFLAGS" + FFLAGS= + AC_PROG_F77_G + if test "$ac_test_FFLAGS" = set; then + FFLAGS="$ac_save_FFLAGS" + elif test $ac_cv_prog_f77_g = yes; then + FFLAGS="-g -O2" + else + FFLAGS="-O2" + fi +else + G77= + test "${FFLAGS+set}" = set || FFLAGS="-g" +fi +]) + +AC_DEFUN(AC_PROG_CC_WORKS, +[AC_MSG_CHECKING([whether the C compiler ($CC $CFLAGS $LDFLAGS) works]) +AC_LANG_SAVE +AC_LANG_C +AC_TRY_COMPILER([int main(){return(0);}], ac_cv_prog_cc_works, ac_cv_prog_cc_cross) +AC_LANG_RESTORE +AC_MSG_RESULT($ac_cv_prog_cc_works) +if test $ac_cv_prog_cc_works = no; then + AC_MSG_ERROR([installation or configuration problem: C compiler cannot create executables.]) +fi +AC_MSG_CHECKING([whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler]) +AC_MSG_RESULT($ac_cv_prog_cc_cross) +cross_compiling=$ac_cv_prog_cc_cross +]) + +AC_DEFUN(AC_PROG_CXX_WORKS, +[AC_MSG_CHECKING([whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works]) +AC_LANG_SAVE +AC_LANG_CPLUSPLUS +AC_TRY_COMPILER([int main(){return(0);}], ac_cv_prog_cxx_works, ac_cv_prog_cxx_cross) +AC_LANG_RESTORE +AC_MSG_RESULT($ac_cv_prog_cxx_works) +if test $ac_cv_prog_cxx_works = no; then + AC_MSG_ERROR([installation or configuration problem: C++ compiler cannot create executables.]) +fi +AC_MSG_CHECKING([whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler]) +AC_MSG_RESULT($ac_cv_prog_cxx_cross) +cross_compiling=$ac_cv_prog_cxx_cross +]) + +dnl Test whether the Fortran 77 compiler can compile and link a trivial +dnl Fortran program. Also, test whether the Fortran 77 compiler is a +dnl cross-compiler (which may realistically be the case if the Fortran +dnl compiler is `g77'). +dnl +dnl AC_PROG_F77_WORKS() +AC_DEFUN(AC_PROG_F77_WORKS, +[AC_MSG_CHECKING([whether the Fortran 77 compiler ($F77 $FFLAGS $LDFLAGS) works]) +AC_LANG_SAVE +AC_LANG_FORTRAN77 +AC_TRY_COMPILER(dnl +[ program conftest + end +], ac_cv_prog_f77_works, ac_cv_prog_f77_cross) +AC_LANG_RESTORE +AC_MSG_RESULT($ac_cv_prog_f77_works) +if test $ac_cv_prog_f77_works = no; then + AC_MSG_ERROR([installation or configuration problem: Fortran 77 compiler cannot create executables.]) +fi +AC_MSG_CHECKING([whether the Fortran 77 compiler ($F77 $FFLAGS $LDFLAGS) is a cross-compiler]) +AC_MSG_RESULT($ac_cv_prog_f77_cross) +cross_compiling=$ac_cv_prog_f77_cross +]) + +AC_DEFUN(AC_PROG_CC_GNU, +[AC_CACHE_CHECK(whether we are using GNU C, ac_cv_prog_gcc, +[dnl The semicolon is to pacify NeXT's syntax-checking cpp. +cat > conftest.c </dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi])]) + +AC_DEFUN(AC_PROG_CXX_GNU, +[AC_CACHE_CHECK(whether we are using GNU C++, ac_cv_prog_gxx, +[dnl The semicolon is to pacify NeXT's syntax-checking cpp. +cat > conftest.C </dev/null 2>&1; then + ac_cv_prog_gxx=yes +else + ac_cv_prog_gxx=no +fi])]) + +dnl Test whether for Fortran 77 compiler is `g77' (the GNU Fortran 77 +dnl Compiler). This test depends on whether the Fortran 77 compiler can +dnl do CPP pre-processing. +dnl +dnl AC_PROG_F77_GNU() +AC_DEFUN(AC_PROG_F77_GNU, +[AC_CACHE_CHECK(whether we are using GNU Fortran 77, ac_cv_prog_g77, +[cat > conftest.fpp </dev/null 2>&1; then + ac_cv_prog_g77=yes +else + ac_cv_prog_g77=no +fi])]) + +AC_DEFUN(AC_PROG_CC_G, +[AC_CACHE_CHECK(whether ${CC-cc} accepts -g, ac_cv_prog_cc_g, +[echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* +])]) + +AC_DEFUN(AC_PROG_CXX_G, +[AC_CACHE_CHECK(whether ${CXX-g++} accepts -g, ac_cv_prog_cxx_g, +[echo 'void f(){}' > conftest.cc +if test -z "`${CXX-g++} -g -c conftest.cc 2>&1`"; then + ac_cv_prog_cxx_g=yes +else + ac_cv_prog_cxx_g=no +fi +rm -f conftest* +])]) + +dnl Test whether the Fortran 77 compiler can accept the `-g' option to +dnl enable debugging. +dnl +dnl AC_PROG_F77_G() +AC_DEFUN(AC_PROG_F77_G, +[AC_CACHE_CHECK(whether $F77 accepts -g, ac_cv_prog_f77_g, +[cat > conftest.f << EOF + program conftest + end +EOF +if test -z "`$F77 -g -c conftest.f 2>&1`"; then + ac_cv_prog_f77_g=yes +else + ac_cv_prog_f77_g=no +fi +rm -f conftest* +])]) + +AC_DEFUN(AC_PROG_GCC_TRADITIONAL, +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_CPP])dnl +if test $ac_cv_prog_gcc = yes; then + AC_CACHE_CHECK(whether -traditional is needed for ${CC-cc} on this system, + ac_cv_prog_gcc_traditional, +[ ac_pattern="Autoconf.*'x'" + AC_EGREP_CPP($ac_pattern, [#include +Autoconf TIOCGETP], + ac_cv_prog_gcc_traditional=yes, ac_cv_prog_gcc_traditional=no) + + if test $ac_cv_prog_gcc_traditional = no; then + AC_EGREP_CPP($ac_pattern, [#include +Autoconf TCGETA], + ac_cv_prog_gcc_traditional=yes) + fi + if test $ac_cv_prog_gcc_traditional = no; then + # On some USL SVR4 systems, gcc's fixinc.svr4 modifies and + # in such a way that "#include " results in a + # syntax error because of `sigset_t' if gcc is called with __STDC__=1 + # but __STRICT_ANSI__ undefined. Remedy: use -traditional. + ac_prog=' +#include +#include +#ifdef __cplusplus +extern "C" void exit(int); +#endif +int main() { exit(0); }' + echo "$ac_prog" > conftest.c + if eval $ac_link; then + : + else + ac_prog=' +#undef __STDC__ +#include +#include +#ifdef __cplusplus +extern "C" void exit(int); +#endif +int main() { exit(0); }' + echo "$ac_prog" > conftest.c + if eval $ac_link; then + ac_cv_prog_gcc_traditional=yes + fi + fi + rm -f conftest* + fi]) + if test $ac_cv_prog_gcc_traditional = yes; then + CC="$CC -traditional" + fi +fi +]) + +AC_DEFUN(AC_PROG_CC_C_O, +[if test "x$CC" != xcc; then + AC_MSG_CHECKING(whether $CC and cc understand -c and -o together) +else + AC_MSG_CHECKING(whether cc understands -c and -o together) +fi +set dummy $CC; ac_cc="`echo [$]2 | +changequote(, )dnl + sed -e 's/[^a-zA-Z0-9_]/_/g' -e 's/^[0-9]/_/'`" +changequote([, ])dnl +AC_CACHE_VAL(ac_cv_prog_cc_${ac_cc}_c_o, +[echo 'foo(){}' > conftest.c +# Make sure it works both with $CC and with simple cc. +# We do the test twice because some compilers refuse to overwrite an +# existing .o file with -o, though they will create one. +ac_try='${CC-cc} -c conftest.c -o conftest.o 1>&AC_FD_CC' +if AC_TRY_EVAL(ac_try) && + test -f conftest.o && AC_TRY_EVAL(ac_try); +then + eval ac_cv_prog_cc_${ac_cc}_c_o=yes + if test "x$CC" != xcc; then + # Test first that cc exists at all. + if AC_TRY_COMMAND(cc -c conftest.c 1>&AC_FD_CC); then + ac_try='cc -c conftest.c -o conftest.o 1>&AC_FD_CC' + if AC_TRY_EVAL(ac_try) && + test -f conftest.o && AC_TRY_EVAL(ac_try); + then + # cc works too. + : + else + # cc exists but doesn't like -o. + eval ac_cv_prog_cc_${ac_cc}_c_o=no + fi + fi + fi +else + eval ac_cv_prog_cc_${ac_cc}_c_o=no +fi +rm -f conftest* +])dnl +if eval "test \"`echo '$ac_cv_prog_cc_'${ac_cc}_c_o`\" = yes"; then + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(no) + AC_DEFINE(NO_MINUS_C_MINUS_O) +fi +]) + +dnl Test if the Fortran 77 compiler accepts the options `-c' and `-o' +dnl simultaneously, and define `F77_NO_MINUS_C_MINUS_O' if it does not. +dnl +dnl The usefulness of this macro is questionable, as I can't really see +dnl why anyone would use it. The only reason I include it is for +dnl completeness, since a similar test exists for the C compiler. +dnl +dnl AC_PROG_F77_C_O +AC_DEFUN(AC_PROG_F77_C_O, +[AC_BEFORE([$0], [AC_PROG_F77])dnl +AC_MSG_CHECKING(whether $F77 understand -c and -o together) +set dummy $F77; ac_f77="`echo [$]2 | +changequote(, )dnl +sed -e 's/[^a-zA-Z0-9_]/_/g' -e 's/^[0-9]/_/'`" +changequote([, ])dnl +AC_CACHE_VAL(ac_cv_prog_f77_${ac_f77}_c_o, +[cat > conftest.f << EOF + program conftest + end +EOF +# We do the `AC_TRY_EVAL' test twice because some compilers refuse to +# overwrite an existing `.o' file with `-o', although they will create +# one. +ac_try='$F77 $FFLAGS -c conftest.f -o conftest.o 1>&AC_FD_CC' +if AC_TRY_EVAL(ac_try) && test -f conftest.o && AC_TRY_EVAL(ac_try); then + eval ac_cv_prog_f77_${ac_f77}_c_o=yes +else + eval ac_cv_prog_f77_${ac_f77}_c_o=no +fi +rm -f conftest* +])dnl +if eval "test \"`echo '$ac_cv_prog_f77_'${ac_f77}_c_o`\" = yes"; then + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(no) + AC_DEFINE(F77_NO_MINUS_C_MINUS_O) +fi +]) + +dnl Define SET_MAKE to set ${MAKE} if make doesn't. +AC_DEFUN(AC_PROG_MAKE_SET, +[AC_MSG_CHECKING([whether ${MAKE-make} sets \$(MAKE)]) +set dummy ${MAKE-make}; ac_make=`echo "[$]2" | sed 'y%./+-%__p_%'` +AC_CACHE_VAL(ac_cv_prog_make_${ac_make}_set, +[cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +changequote(, )dnl +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +changequote([, ])dnl +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake])dnl +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + AC_MSG_RESULT(yes) + SET_MAKE= +else + AC_MSG_RESULT(no) + SET_MAKE="MAKE=${MAKE-make}" +fi +AC_SUBST([SET_MAKE])dnl +]) + +AC_DEFUN(AC_PROG_RANLIB, +[AC_CHECK_PROG(RANLIB, ranlib, ranlib, :)]) + +dnl Check for mawk first since it's generally faster. +AC_DEFUN(AC_PROG_AWK, +[AC_CHECK_PROGS(AWK, mawk gawk nawk awk, )]) + +AC_DEFUN(AC_PROG_YACC, +[AC_CHECK_PROGS(YACC, 'bison -y' byacc, yacc)]) + +AC_DEFUN(AC_PROG_CPP, +[AC_MSG_CHECKING(how to run the C preprocessor) +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +AC_CACHE_VAL(ac_cv_prog_CPP, +[ # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + if test -n "$GCC"; then +dnl This is already part of AC_PROG_CC. +dnl # Use the same optimization flags than for CC, because some things may +dnl # depend upon __OPTIMIZE__. +dnl CPP="$CPP -O" + # Suppress warning messages. +dnl # When using gcc -traditional on machines that have , +dnl # the "-Dconst=" from AC_C_CONST and the "#define const __const" from +dnl # generate a warning. Unless suppressed, this warning +dnl # causes later tests using AC_TRY_CPP to fail. + CPP="$CPP -w" + fi + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. On NeXTstep 3.1 the same holds for /lib/cpp; use + # "cc -E -traditional-cpp" instead. +dnl Use a header file that comes with gcc, so configuring glibc +dnl with a fresh cross-compiler works. + AC_TRY_CPP([#include +Syntax Error], ac_have_cpp=1) + if test -z "$ac_have_cpp"; then + CPP="${CC-cc} -E -traditional-cpp" + AC_TRY_CPP([#include +Syntax Error], ac_have_cpp=1) + if test -n "$ac_have_cpp"; then + CC="${CC-cc} -traditional-cpp" + else + CPP="${CC-cc} -nologo -E" + AC_TRY_CPP([#include +Syntax Error], ac_have_cpp=1) + if test -n "$ac_have_cpp"; then + CC="${CC-cc} -nologo" + else + CPP=/lib/cpp + fi + fi + fi + ac_cv_prog_CC="$CC" + ac_cv_prog_CPP="$CPP"])dnl + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +AC_MSG_RESULT($CPP) +AC_SUBST(CPP)dnl +]) + +AC_DEFUN(AC_PROG_CXXCPP, +[AC_MSG_CHECKING(how to run the C++ preprocessor) +if test -z "$CXXCPP"; then +AC_CACHE_VAL(ac_cv_prog_CXXCPP, +[AC_LANG_SAVE[]dnl +AC_LANG_CPLUSPLUS[]dnl + CXXCPP="${CXX-g++} -E" + AC_TRY_CPP([#include ], , CXXCPP=/lib/cpp) + ac_cv_prog_CXXCPP="$CXXCPP" +AC_LANG_RESTORE[]dnl +fi])dnl +CXXCPP="$ac_cv_prog_CXXCPP" +AC_MSG_RESULT($CXXCPP) +AC_SUBST(CXXCPP)dnl +]) + +dnl Require finding the C or C++ preprocessor, whichever is the +dnl current language. +AC_DEFUN(AC_REQUIRE_CPP, +[ifelse(AC_LANG, C, [AC_REQUIRE([AC_PROG_CPP])], [AC_REQUIRE([AC_PROG_CXXCPP])])]) + +AC_DEFUN(AC_PROG_LEX, +[AC_CHECK_PROG(LEX, flex, flex, lex) +if test -z "$LEXLIB" +then + case "$LEX" in + flex*) ac_lib=fl ;; + *) ac_lib=l ;; + esac + AC_CHECK_LIB($ac_lib, yywrap, LEXLIB="-l$ac_lib") +fi +AC_SUBST(LEXLIB)]) + +dnl Check if lex declares yytext as a char * by default, not a char[]. +undefine([AC_DECL_YYTEXT]) +AC_DEFUN(AC_DECL_YYTEXT, +[AC_REQUIRE_CPP()dnl +AC_REQUIRE([AC_PROG_LEX])dnl +AC_CACHE_CHECK(lex output file root, ac_cv_prog_lex_root, +[# The minimal lex program is just a single line: %%. But some broken lexes +# (Solaris, I think it was) want two %% lines, so accommodate them. +echo '%% +%%' | $LEX +if test -f lex.yy.c; then + ac_cv_prog_lex_root=lex.yy +elif test -f lexyy.c; then + ac_cv_prog_lex_root=lexyy +else + AC_MSG_ERROR(cannot find output from $LEX; giving up) +fi]) +LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root +AC_SUBST(LEX_OUTPUT_ROOT)dnl + +AC_CACHE_CHECK(whether yytext is a pointer, ac_cv_prog_lex_yytext_pointer, +[# POSIX says lex can declare yytext either as a pointer or an array; the +# default is implementation-dependent. Figure out which it is, since +# not all implementations provide the %pointer and %array declarations. +ac_cv_prog_lex_yytext_pointer=no +echo 'extern char *yytext;' >>$LEX_OUTPUT_ROOT.c +ac_save_LIBS="$LIBS" +LIBS="$LIBS $LEXLIB" +AC_TRY_LINK(`cat $LEX_OUTPUT_ROOT.c`, , ac_cv_prog_lex_yytext_pointer=yes) +LIBS="$ac_save_LIBS" +rm -f "${LEX_OUTPUT_ROOT}.c" +]) +if test $ac_cv_prog_lex_yytext_pointer = yes; then + AC_DEFINE(YYTEXT_POINTER) +fi +]) + +AC_DEFUN(AC_PROG_INSTALL, +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +AC_MSG_CHECKING(for a BSD compatible install) +if test -z "$INSTALL"; then +AC_CACHE_VAL(ac_cv_path_install, +[ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + if test $ac_prog = installbsd && + grep src/bos $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX installbsd doesn't work without option "-g". + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" +])dnl + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +dnl We do special magic for INSTALL instead of AC_SUBST, to get +dnl relative paths right. +AC_MSG_RESULT($INSTALL) + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' +AC_SUBST(INSTALL_PROGRAM)dnl + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' +AC_SUBST(INSTALL_SCRIPT)dnl + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' +AC_SUBST(INSTALL_DATA)dnl +]) + +AC_DEFUN(AC_PROG_LN_S, +[AC_MSG_CHECKING(whether ln -s works) +AC_CACHE_VAL(ac_cv_prog_LN_S, +[rm -f conftestdata +if ln -s X conftestdata 2>/dev/null +then + rm -f conftestdata + ac_cv_prog_LN_S="ln -s" +else + ac_cv_prog_LN_S=ln +fi])dnl +LN_S="$ac_cv_prog_LN_S" +if test "$ac_cv_prog_LN_S" = "ln -s"; then + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(no) +fi +AC_SUBST(LN_S)dnl +]) + +define(AC_RSH, +[errprint(__file__:__line__: [$0] has been removed; replace it with equivalent code +)m4exit(4)]) + + +dnl ### Checks for header files + + +AC_DEFUN(AC_HEADER_STDC, +[AC_REQUIRE_CPP()dnl +AC_CACHE_CHECK(for ANSI C header files, ac_cv_header_stdc, +[AC_TRY_CPP([#include +#include +#include +#include ], ac_cv_header_stdc=yes, ac_cv_header_stdc=no) + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. +AC_EGREP_HEADER(memchr, string.h, , ac_cv_header_stdc=no) +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. +AC_EGREP_HEADER(free, stdlib.h, , ac_cv_header_stdc=no) +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. +AC_TRY_RUN([#include +#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int main () { int i; for (i = 0; i < 256; i++) +if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); +exit (0); } +], , ac_cv_header_stdc=no, :) +fi]) +if test $ac_cv_header_stdc = yes; then + AC_DEFINE(STDC_HEADERS) +fi +]) + +AC_DEFUN(AC_UNISTD_H, +[AC_OBSOLETE([$0], [; instead use AC_CHECK_HEADERS(unistd.h)])dnl +AC_CHECK_HEADER(unistd.h, AC_DEFINE(HAVE_UNISTD_H))]) + +AC_DEFUN(AC_USG, +[AC_OBSOLETE([$0], + [; instead use AC_CHECK_HEADERS(string.h) and HAVE_STRING_H])dnl +AC_MSG_CHECKING([for BSD string and memory functions]) +AC_TRY_LINK([#include ], [rindex(0, 0); bzero(0, 0);], + [AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no); AC_DEFINE(USG)])]) + + +dnl If memchr and the like aren't declared in , include . +dnl To avoid problems, don't check for gcc2 built-ins. +AC_DEFUN(AC_MEMORY_H, +[AC_OBSOLETE([$0], [; instead use AC_CHECK_HEADERS(memory.h) and HAVE_MEMORY_H])dnl +AC_MSG_CHECKING(whether string.h declares mem functions) +AC_EGREP_HEADER(memchr, string.h, ac_found=yes, ac_found=no) +AC_MSG_RESULT($ac_found) +if test $ac_found = no; then + AC_CHECK_HEADER(memory.h, [AC_DEFINE(NEED_MEMORY_H)]) +fi +]) + +AC_DEFUN(AC_HEADER_MAJOR, +[AC_CACHE_CHECK(whether sys/types.h defines makedev, + ac_cv_header_sys_types_h_makedev, +[AC_TRY_LINK([#include ], [return makedev(0, 0);], + ac_cv_header_sys_types_h_makedev=yes, ac_cv_header_sys_types_h_makedev=no) +]) + +if test $ac_cv_header_sys_types_h_makedev = no; then +AC_CHECK_HEADER(sys/mkdev.h, [AC_DEFINE(MAJOR_IN_MKDEV)]) + + if test $ac_cv_header_sys_mkdev_h = no; then +AC_CHECK_HEADER(sys/sysmacros.h, [AC_DEFINE(MAJOR_IN_SYSMACROS)]) + fi +fi +]) + +AC_DEFUN(AC_HEADER_DIRENT, +[ac_header_dirent=no +AC_CHECK_HEADERS_DIRENT(dirent.h sys/ndir.h sys/dir.h ndir.h, + [ac_header_dirent=$ac_hdr; break]) +# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. +if test $ac_header_dirent = dirent.h; then +AC_CHECK_LIB(dir, opendir, LIBS="$LIBS -ldir") +else +AC_CHECK_LIB(x, opendir, LIBS="$LIBS -lx") +fi +]) + +dnl Like AC_CHECK_HEADER, except also make sure that HEADER-FILE +dnl defines the type `DIR'. dirent.h on NextStep 3.2 doesn't. +dnl AC_CHECK_HEADER_DIRENT(HEADER-FILE, ACTION-IF-FOUND) +AC_DEFUN(AC_CHECK_HEADER_DIRENT, +[ac_safe=`echo "$1" | sed 'y%./+-%__p_%'` +AC_MSG_CHECKING([for $1 that defines DIR]) +AC_CACHE_VAL(ac_cv_header_dirent_$ac_safe, +[AC_TRY_COMPILE([#include +#include <$1>], [DIR *dirp = 0;], + eval "ac_cv_header_dirent_$ac_safe=yes", + eval "ac_cv_header_dirent_$ac_safe=no")])dnl +if eval "test \"`echo '$ac_cv_header_dirent_'$ac_safe`\" = yes"; then + AC_MSG_RESULT(yes) + $2 +else + AC_MSG_RESULT(no) +fi +]) + +dnl Like AC_CHECK_HEADERS, except succeed only for a HEADER-FILE that +dnl defines `DIR'. +dnl AC_CHECK_HEADERS_DIRENT(HEADER-FILE... [, ACTION]) +define(AC_CHECK_HEADERS_DIRENT, +[for ac_hdr in $1 +do +AC_CHECK_HEADER_DIRENT($ac_hdr, +[changequote(, )dnl + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` +changequote([, ])dnl + AC_DEFINE_UNQUOTED($ac_tr_hdr) $2])dnl +done]) + +AC_DEFUN(AC_DIR_HEADER, +[AC_OBSOLETE([$0], [; instead use AC_HEADER_DIRENT])dnl +ac_header_dirent=no +for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do + AC_CHECK_HEADER_DIRENT($ac_hdr, [ac_header_dirent=$ac_hdr; break]) +done + +case "$ac_header_dirent" in +dirent.h) AC_DEFINE(DIRENT) ;; +sys/ndir.h) AC_DEFINE(SYSNDIR) ;; +sys/dir.h) AC_DEFINE(SYSDIR) ;; +ndir.h) AC_DEFINE(NDIR) ;; +esac + +AC_CACHE_CHECK(whether closedir returns void, ac_cv_func_closedir_void, +[AC_TRY_RUN([#include +#include <$ac_header_dirent> +int closedir(); int main() { exit(closedir(opendir(".")) != 0); }], + ac_cv_func_closedir_void=no, ac_cv_func_closedir_void=yes, ac_cv_func_closedir_void=yes)]) +if test $ac_cv_func_closedir_void = yes; then + AC_DEFINE(VOID_CLOSEDIR) +fi +]) + +AC_DEFUN(AC_HEADER_STAT, +[AC_CACHE_CHECK(whether stat file-mode macros are broken, + ac_cv_header_stat_broken, +[AC_EGREP_CPP([You lose], [#include +#include + +#if defined(S_ISBLK) && defined(S_IFDIR) +# if S_ISBLK (S_IFDIR) +You lose. +# endif +#endif + +#if defined(S_ISBLK) && defined(S_IFCHR) +# if S_ISBLK (S_IFCHR) +You lose. +# endif +#endif + +#if defined(S_ISLNK) && defined(S_IFREG) +# if S_ISLNK (S_IFREG) +You lose. +# endif +#endif + +#if defined(S_ISSOCK) && defined(S_IFREG) +# if S_ISSOCK (S_IFREG) +You lose. +# endif +#endif +], ac_cv_header_stat_broken=yes, ac_cv_header_stat_broken=no)]) +if test $ac_cv_header_stat_broken = yes; then + AC_DEFINE(STAT_MACROS_BROKEN) +fi +]) + +AC_DEFUN(AC_DECL_SYS_SIGLIST, +[AC_CACHE_CHECK([for sys_siglist declaration in signal.h or unistd.h], + ac_cv_decl_sys_siglist, +[AC_TRY_COMPILE([#include +#include +/* NetBSD declares sys_siglist in unistd.h. */ +#ifdef HAVE_UNISTD_H +#include +#endif], [char *msg = *(sys_siglist + 1);], + ac_cv_decl_sys_siglist=yes, ac_cv_decl_sys_siglist=no)]) +if test $ac_cv_decl_sys_siglist = yes; then + AC_DEFINE(SYS_SIGLIST_DECLARED) +fi +]) + +AC_DEFUN(AC_HEADER_SYS_WAIT, +[AC_CACHE_CHECK([for sys/wait.h that is POSIX.1 compatible], + ac_cv_header_sys_wait_h, +[AC_TRY_COMPILE([#include +#include +#ifndef WEXITSTATUS +#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) +#endif +#ifndef WIFEXITED +#define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif], [int s; +wait (&s); +s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;], +ac_cv_header_sys_wait_h=yes, ac_cv_header_sys_wait_h=no)]) +if test $ac_cv_header_sys_wait_h = yes; then + AC_DEFINE(HAVE_SYS_WAIT_H) +fi +]) + + +dnl ### Checks for typedefs + + +AC_DEFUN(AC_TYPE_GETGROUPS, +[AC_REQUIRE([AC_TYPE_UID_T])dnl +AC_CACHE_CHECK(type of array argument to getgroups, ac_cv_type_getgroups, +[AC_TRY_RUN( +changequote(<<, >>)dnl +<< +/* Thanks to Mike Rendell for this test. */ +#include +#define NGID 256 +#undef MAX +#define MAX(x, y) ((x) > (y) ? (x) : (y)) +int main() +{ + gid_t gidset[NGID]; + int i, n; + union { gid_t gval; long lval; } val; + + val.lval = -1; + for (i = 0; i < NGID; i++) + gidset[i] = val.gval; + n = getgroups (sizeof (gidset) / MAX (sizeof (int), sizeof (gid_t)) - 1, + gidset); + /* Exit non-zero if getgroups seems to require an array of ints. This + happens when gid_t is short but getgroups modifies an array of ints. */ + exit ((n > 0 && gidset[n] != val.gval) ? 1 : 0); +} +>>, +changequote([, ])dnl + ac_cv_type_getgroups=gid_t, ac_cv_type_getgroups=int, + ac_cv_type_getgroups=cross) +if test $ac_cv_type_getgroups = cross; then + dnl When we can't run the test program (we are cross compiling), presume + dnl that has either an accurate prototype for getgroups or none. + dnl Old systems without prototypes probably use int. + AC_EGREP_HEADER([getgroups.*int.*gid_t], unistd.h, + ac_cv_type_getgroups=gid_t, ac_cv_type_getgroups=int) +fi]) +AC_DEFINE_UNQUOTED(GETGROUPS_T, $ac_cv_type_getgroups) +]) + +AC_DEFUN(AC_TYPE_UID_T, +[AC_CACHE_CHECK(for uid_t in sys/types.h, ac_cv_type_uid_t, +[AC_EGREP_HEADER(uid_t, sys/types.h, + ac_cv_type_uid_t=yes, ac_cv_type_uid_t=no)]) +if test $ac_cv_type_uid_t = no; then + AC_DEFINE(uid_t, int) + AC_DEFINE(gid_t, int) +fi +]) + +AC_DEFUN(AC_TYPE_SIZE_T, +[AC_CHECK_TYPE(size_t, unsigned)]) + +AC_DEFUN(AC_TYPE_PID_T, +[AC_CHECK_TYPE(pid_t, int)]) + +AC_DEFUN(AC_TYPE_OFF_T, +[AC_CHECK_TYPE(off_t, long)]) + +AC_DEFUN(AC_TYPE_MODE_T, +[AC_CHECK_TYPE(mode_t, int)]) + +dnl Note that identifiers starting with SIG are reserved by ANSI C. +AC_DEFUN(AC_TYPE_SIGNAL, +[AC_CACHE_CHECK([return type of signal handlers], ac_cv_type_signal, +[AC_TRY_COMPILE([#include +#include +#ifdef signal +#undef signal +#endif +extern +#ifdef __cplusplus +"C" void (*signal (int, void (*)(int)))(int); +#else +void (*signal ()) (); +#endif +], +[int i;], ac_cv_type_signal=void, ac_cv_type_signal=int)]) +AC_DEFINE_UNQUOTED(RETSIGTYPE, $ac_cv_type_signal) +]) + + +dnl ### Checks for functions + + +AC_DEFUN(AC_FUNC_CLOSEDIR_VOID, +[AC_REQUIRE([AC_HEADER_DIRENT])dnl +AC_CACHE_CHECK(whether closedir returns void, ac_cv_func_closedir_void, +[AC_TRY_RUN([#include +#include <$ac_header_dirent> +int closedir(); int main() { exit(closedir(opendir(".")) != 0); }], + ac_cv_func_closedir_void=no, ac_cv_func_closedir_void=yes, ac_cv_func_closedir_void=yes)]) +if test $ac_cv_func_closedir_void = yes; then + AC_DEFINE(CLOSEDIR_VOID) +fi +]) + +AC_DEFUN(AC_FUNC_FNMATCH, +[AC_CACHE_CHECK(for working fnmatch, ac_cv_func_fnmatch_works, +# Some versions of Solaris or SCO have a broken fnmatch function. +# So we run a test program. If we are cross-compiling, take no chance. +# Thanks to John Oleynick and Franc,ois Pinard for this test. +[AC_TRY_RUN([int main() { exit (fnmatch ("a*", "abc", 0) != 0); }], +ac_cv_func_fnmatch_works=yes, ac_cv_func_fnmatch_works=no, +ac_cv_func_fnmatch_works=no)]) +if test $ac_cv_func_fnmatch_works = yes; then + AC_DEFINE(HAVE_FNMATCH) +fi +]) + +AC_DEFUN(AC_FUNC_MMAP, +[AC_CHECK_HEADERS(unistd.h) +AC_CHECK_FUNCS(getpagesize) +AC_CACHE_CHECK(for working mmap, ac_cv_func_mmap_fixed_mapped, +[AC_TRY_RUN([ +/* Thanks to Mike Haertel and Jim Avera for this test. + Here is a matrix of mmap possibilities: + mmap private not fixed + mmap private fixed at somewhere currently unmapped + mmap private fixed at somewhere already mapped + mmap shared not fixed + mmap shared fixed at somewhere currently unmapped + mmap shared fixed at somewhere already mapped + For private mappings, we should verify that changes cannot be read() + back from the file, nor mmap's back from the file at a different + address. (There have been systems where private was not correctly + implemented like the infamous i386 svr4.0, and systems where the + VM page cache was not coherent with the filesystem buffer cache + like early versions of FreeBSD and possibly contemporary NetBSD.) + For shared mappings, we should conversely verify that changes get + propogated back to all the places they're supposed to be. + + Grep wants private fixed already mapped. + The main things grep needs to know about mmap are: + * does it exist and is it safe to write into the mmap'd area + * how to use it (BSD variants) */ +#include +#include +#include + +/* This mess was copied from the GNU getpagesize.h. */ +#ifndef HAVE_GETPAGESIZE +# ifdef HAVE_UNISTD_H +# include +# endif + +/* Assume that all systems that can run configure have sys/param.h. */ +# ifndef HAVE_SYS_PARAM_H +# define HAVE_SYS_PARAM_H 1 +# endif + +# ifdef _SC_PAGESIZE +# define getpagesize() sysconf(_SC_PAGESIZE) +# else /* no _SC_PAGESIZE */ +# ifdef HAVE_SYS_PARAM_H +# include +# ifdef EXEC_PAGESIZE +# define getpagesize() EXEC_PAGESIZE +# else /* no EXEC_PAGESIZE */ +# ifdef NBPG +# define getpagesize() NBPG * CLSIZE +# ifndef CLSIZE +# define CLSIZE 1 +# endif /* no CLSIZE */ +# else /* no NBPG */ +# ifdef NBPC +# define getpagesize() NBPC +# else /* no NBPC */ +# ifdef PAGESIZE +# define getpagesize() PAGESIZE +# endif /* PAGESIZE */ +# endif /* no NBPC */ +# endif /* no NBPG */ +# endif /* no EXEC_PAGESIZE */ +# else /* no HAVE_SYS_PARAM_H */ +# define getpagesize() 8192 /* punt totally */ +# endif /* no HAVE_SYS_PARAM_H */ +# endif /* no _SC_PAGESIZE */ + +#endif /* no HAVE_GETPAGESIZE */ + +#ifdef __cplusplus +extern "C" { void *malloc(unsigned); } +#else +char *malloc(); +#endif + +int +main() +{ + char *data, *data2, *data3; + int i, pagesize; + int fd; + + pagesize = getpagesize(); + + /* + * First, make a file with some known garbage in it. + */ + data = malloc(pagesize); + if (!data) + exit(1); + for (i = 0; i < pagesize; ++i) + *(data + i) = rand(); + umask(0); + fd = creat("conftestmmap", 0600); + if (fd < 0) + exit(1); + if (write(fd, data, pagesize) != pagesize) + exit(1); + close(fd); + + /* + * Next, try to mmap the file at a fixed address which + * already has something else allocated at it. If we can, + * also make sure that we see the same garbage. + */ + fd = open("conftestmmap", O_RDWR); + if (fd < 0) + exit(1); + data2 = malloc(2 * pagesize); + if (!data2) + exit(1); + data2 += (pagesize - ((int) data2 & (pagesize - 1))) & (pagesize - 1); + if (data2 != mmap(data2, pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED, fd, 0L)) + exit(1); + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data2 + i)) + exit(1); + + /* + * Finally, make sure that changes to the mapped area + * do not percolate back to the file as seen by read(). + * (This is a bug on some variants of i386 svr4.0.) + */ + for (i = 0; i < pagesize; ++i) + *(data2 + i) = *(data2 + i) + 1; + data3 = malloc(pagesize); + if (!data3) + exit(1); + if (read(fd, data3, pagesize) != pagesize) + exit(1); + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data3 + i)) + exit(1); + close(fd); + unlink("conftestmmap"); + exit(0); +} +], ac_cv_func_mmap_fixed_mapped=yes, ac_cv_func_mmap_fixed_mapped=no, +ac_cv_func_mmap_fixed_mapped=no)]) +if test $ac_cv_func_mmap_fixed_mapped = yes; then + AC_DEFINE(HAVE_MMAP) +fi +]) + +AC_DEFUN(AC_FUNC_GETPGRP, +[AC_CACHE_CHECK(whether getpgrp takes no argument, ac_cv_func_getpgrp_void, +[AC_TRY_RUN([ +/* + * If this system has a BSD-style getpgrp(), + * which takes a pid argument, exit unsuccessfully. + * + * Snarfed from Chet Ramey's bash pgrp.c test program + */ +#include +#include + +int pid; +int pg1, pg2, pg3, pg4; +int ng, np, s, child; + +int main() +{ + pid = getpid(); + pg1 = getpgrp(0); + pg2 = getpgrp(); + pg3 = getpgrp(pid); + pg4 = getpgrp(1); + + /* + * If all of these values are the same, it's pretty sure that + * we're on a system that ignores getpgrp's first argument. + */ + if (pg2 == pg4 && pg1 == pg3 && pg2 == pg3) + exit(0); + + child = fork(); + if (child < 0) + exit(1); + else if (child == 0) { + np = getpid(); + /* + * If this is Sys V, this will not work; pgrp will be + * set to np because setpgrp just changes a pgrp to be + * the same as the pid. + */ + setpgrp(np, pg1); + ng = getpgrp(0); /* Same result for Sys V and BSD */ + if (ng == pg1) { + exit(1); + } else { + exit(0); + } + } else { + wait(&s); + exit(s>>8); + } +} +], ac_cv_func_getpgrp_void=yes, ac_cv_func_getpgrp_void=no, + AC_MSG_ERROR(cannot check getpgrp if cross compiling)) +]) +if test $ac_cv_func_getpgrp_void = yes; then + AC_DEFINE(GETPGRP_VOID) +fi +]) + +AC_DEFUN(AC_FUNC_SETPGRP, +[AC_CACHE_CHECK(whether setpgrp takes no argument, ac_cv_func_setpgrp_void, +AC_TRY_RUN([ +#ifdef HAVE_UNISTD_H +#include +#endif + +/* + * If this system has a BSD-style setpgrp, which takes arguments, exit + * successfully. + */ +int main() +{ + if (setpgrp(1,1) == -1) + exit(0); + else + exit(1); +} +], ac_cv_func_setpgrp_void=no, ac_cv_func_setpgrp_void=yes, + AC_MSG_ERROR(cannot check setpgrp if cross compiling)) +) +if test $ac_cv_func_setpgrp_void = yes; then + AC_DEFINE(SETPGRP_VOID) +fi +]) + +AC_DEFUN(AC_FUNC_VPRINTF, +[AC_CHECK_FUNC(vprintf, AC_DEFINE(HAVE_VPRINTF)) +if test "$ac_cv_func_vprintf" != yes; then +AC_CHECK_FUNC(_doprnt, AC_DEFINE(HAVE_DOPRNT)) +fi +]) + +AC_DEFUN(AC_FUNC_VFORK, +[AC_REQUIRE([AC_TYPE_PID_T])dnl +AC_CHECK_HEADER(vfork.h, AC_DEFINE(HAVE_VFORK_H)) +AC_CACHE_CHECK(for working vfork, ac_cv_func_vfork_works, +[AC_TRY_RUN([/* Thanks to Paul Eggert for this test. */ +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_VFORK_H +#include +#endif +/* On some sparc systems, changes by the child to local and incoming + argument registers are propagated back to the parent. + The compiler is told about this with #include , + but some compilers (e.g. gcc -O) don't grok . + Test for this by using a static variable whose address + is put into a register that is clobbered by the vfork. */ +static int +#ifdef __cplusplus +sparc_address_test (int arg) +#else +sparc_address_test (arg) int arg; +#endif +{ + static pid_t child; + if (!child) { + child = vfork (); + if (child < 0) { + perror ("vfork"); + _exit(2); + } + if (!child) { + arg = getpid(); + write(-1, "", 0); + _exit (arg); + } + } +} +int main() { + pid_t parent = getpid (); + pid_t child; + + ((int (*)()) sparc_address_test) (); + + child = vfork (); + + if (child == 0) { + /* Here is another test for sparc vfork register problems. + This test uses lots of local variables, at least + as many local variables as main has allocated so far + including compiler temporaries. 4 locals are enough for + gcc 1.40.3 on a Solaris 4.1.3 sparc, but we use 8 to be safe. + A buggy compiler should reuse the register of parent + for one of the local variables, since it will think that + parent can't possibly be used any more in this routine. + Assigning to the local variable will thus munge parent + in the parent process. */ + pid_t + p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(), + p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid(); + /* Convince the compiler that p..p7 are live; otherwise, it might + use the same hardware register for all 8 local variables. */ + if (p != p1 || p != p2 || p != p3 || p != p4 + || p != p5 || p != p6 || p != p7) + _exit(1); + + /* On some systems (e.g. IRIX 3.3), + vfork doesn't separate parent from child file descriptors. + If the child closes a descriptor before it execs or exits, + this munges the parent's descriptor as well. + Test for this by closing stdout in the child. */ + _exit(close(fileno(stdout)) != 0); + } else { + int status; + struct stat st; + + while (wait(&status) != child) + ; + exit( + /* Was there some problem with vforking? */ + child < 0 + + /* Did the child fail? (This shouldn't happen.) */ + || status + + /* Did the vfork/compiler bug occur? */ + || parent != getpid() + + /* Did the file descriptor bug occur? */ + || fstat(fileno(stdout), &st) != 0 + ); + } +}], +ac_cv_func_vfork_works=yes, ac_cv_func_vfork_works=no, AC_CHECK_FUNC(vfork) +ac_cv_func_vfork_works=$ac_cv_func_vfork)]) +if test $ac_cv_func_vfork_works = no; then + AC_DEFINE(vfork, fork) +fi +]) + +AC_DEFUN(AC_FUNC_WAIT3, +[AC_CACHE_CHECK(for wait3 that fills in rusage, ac_cv_func_wait3_rusage, +[AC_TRY_RUN([#include +#include +#include +#include +/* HP-UX has wait3 but does not fill in rusage at all. */ +int main() { + struct rusage r; + int i; + /* Use a field that we can force nonzero -- + voluntary context switches. + For systems like NeXT and OSF/1 that don't set it, + also use the system CPU time. And page faults (I/O) for Linux. */ + r.ru_nvcsw = 0; + r.ru_stime.tv_sec = 0; + r.ru_stime.tv_usec = 0; + r.ru_majflt = r.ru_minflt = 0; + switch (fork()) { + case 0: /* Child. */ + sleep(1); /* Give up the CPU. */ + _exit(0); + case -1: _exit(0); /* What can we do? */ + default: /* Parent. */ + wait3(&i, 0, &r); + sleep(2); /* Avoid "text file busy" from rm on fast HP-UX machines. */ + exit(r.ru_nvcsw == 0 && r.ru_majflt == 0 && r.ru_minflt == 0 + && r.ru_stime.tv_sec == 0 && r.ru_stime.tv_usec == 0); + } +}], ac_cv_func_wait3_rusage=yes, ac_cv_func_wait3_rusage=no, +ac_cv_func_wait3_rusage=no)]) +if test $ac_cv_func_wait3_rusage = yes; then + AC_DEFINE(HAVE_WAIT3) +fi +]) + +AC_DEFUN(AC_FUNC_ALLOCA, +[AC_REQUIRE_CPP()dnl Set CPP; we run AC_EGREP_CPP conditionally. +# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works +# for constant arguments. Useless! +AC_CACHE_CHECK([for working alloca.h], ac_cv_header_alloca_h, +[AC_TRY_LINK([#include ], [char *p = alloca(2 * sizeof(int));], + ac_cv_header_alloca_h=yes, ac_cv_header_alloca_h=no)]) +if test $ac_cv_header_alloca_h = yes; then + AC_DEFINE(HAVE_ALLOCA_H) +fi + +AC_CACHE_CHECK([for alloca], ac_cv_func_alloca_works, +[AC_TRY_LINK([ +#ifdef __GNUC__ +# define alloca __builtin_alloca +#else +# ifdef _MSC_VER +# include +# define alloca _alloca +# else +# if HAVE_ALLOCA_H +# include +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca /* predefined by HP cc +Olibcalls */ +char *alloca (); +# endif +# endif +# endif +# endif +#endif +], [char *p = (char *) alloca(1);], + ac_cv_func_alloca_works=yes, ac_cv_func_alloca_works=no)]) +if test $ac_cv_func_alloca_works = yes; then + AC_DEFINE(HAVE_ALLOCA) +fi + +if test $ac_cv_func_alloca_works = no; then + # The SVR3 libPW and SVR4 libucb both contain incompatible functions + # that cause trouble. Some versions do not even contain alloca or + # contain a buggy version. If you still want to use their alloca, + # use ar to extract alloca.o from them instead of compiling alloca.c. + ALLOCA=alloca.${ac_objext} + AC_DEFINE(C_ALLOCA) + +AC_CACHE_CHECK(whether alloca needs Cray hooks, ac_cv_os_cray, +[AC_EGREP_CPP(webecray, +[#if defined(CRAY) && ! defined(CRAY2) +webecray +#else +wenotbecray +#endif +], ac_cv_os_cray=yes, ac_cv_os_cray=no)]) +if test $ac_cv_os_cray = yes; then +for ac_func in _getb67 GETB67 getb67; do + AC_CHECK_FUNC($ac_func, [AC_DEFINE_UNQUOTED(CRAY_STACKSEG_END, $ac_func) + break]) +done +fi + +AC_CACHE_CHECK(stack direction for C alloca, ac_cv_c_stack_direction, +[AC_TRY_RUN([find_stack_direction () +{ + static char *addr = 0; + auto char dummy; + if (addr == 0) + { + addr = &dummy; + return find_stack_direction (); + } + else + return (&dummy > addr) ? 1 : -1; +} +int main () +{ + exit (find_stack_direction() < 0); +}], ac_cv_c_stack_direction=1, ac_cv_c_stack_direction=-1, + ac_cv_c_stack_direction=0)]) +AC_DEFINE_UNQUOTED(STACK_DIRECTION, $ac_cv_c_stack_direction) +fi +AC_SUBST(ALLOCA)dnl +]) + +AC_DEFUN(AC_FUNC_GETLOADAVG, +[ac_have_func=no # yes means we've found a way to get the load average. + +# Some systems with -lutil have (and need) -lkvm as well, some do not. +# On Solaris, -lkvm requires nlist from -lelf, so check that first +# to get the right answer into the cache. +AC_CHECK_LIB(elf, elf_begin, LIBS="-lelf $LIBS") +AC_CHECK_LIB(kvm, kvm_open, LIBS="-lkvm $LIBS") +# Check for the 4.4BSD definition of getloadavg. +AC_CHECK_LIB(util, getloadavg, + [LIBS="-lutil $LIBS" ac_have_func=yes ac_cv_func_getloadavg_setgid=yes]) + +if test $ac_have_func = no; then + # There is a commonly available library for RS/6000 AIX. + # Since it is not a standard part of AIX, it might be installed locally. + ac_getloadavg_LIBS="$LIBS"; LIBS="-L/usr/local/lib $LIBS" + AC_CHECK_LIB(getloadavg, getloadavg, + LIBS="-lgetloadavg $LIBS", LIBS="$ac_getloadavg_LIBS") +fi + +# Make sure it is really in the library, if we think we found it. +AC_REPLACE_FUNCS(getloadavg) + +if test $ac_cv_func_getloadavg = yes; then + AC_DEFINE(HAVE_GETLOADAVG) + ac_have_func=yes +else + # Figure out what our getloadavg.c needs. + ac_have_func=no + AC_CHECK_HEADER(sys/dg_sys_info.h, + [ac_have_func=yes; AC_DEFINE(DGUX) + AC_CHECK_LIB(dgc, dg_sys_info)]) + + # We cannot check for , because Solaris 2 does not use dwarf (it + # uses stabs), but it is still SVR4. We cannot check for because + # Irix 4.0.5F has the header but not the library. + if test $ac_have_func = no && test $ac_cv_lib_elf_elf_begin = yes; then + ac_have_func=yes; AC_DEFINE(SVR4) + fi + + if test $ac_have_func = no; then + AC_CHECK_HEADER(inq_stats/cpustats.h, + [ac_have_func=yes; AC_DEFINE(UMAX) + AC_DEFINE(UMAX4_3)]) + fi + + if test $ac_have_func = no; then + AC_CHECK_HEADER(sys/cpustats.h, + [ac_have_func=yes; AC_DEFINE(UMAX)]) + fi + + if test $ac_have_func = no; then + AC_CHECK_HEADERS(mach/mach.h) + fi + + AC_CHECK_HEADER(nlist.h, + [AC_DEFINE(NLIST_STRUCT) + AC_CACHE_CHECK([for n_un in struct nlist], ac_cv_struct_nlist_n_un, + [AC_TRY_COMPILE([#include ], + [struct nlist n; n.n_un.n_name = 0;], + ac_cv_struct_nlist_n_un=yes, ac_cv_struct_nlist_n_un=no)]) + if test $ac_cv_struct_nlist_n_un = yes; then + AC_DEFINE(NLIST_NAME_UNION) + fi + ])dnl +fi # Do not have getloadavg in system libraries. + +# Some definitions of getloadavg require that the program be installed setgid. +dnl FIXME Don't hardwire the path of getloadavg.c in the top-level directory. +AC_CACHE_CHECK(whether getloadavg requires setgid, + ac_cv_func_getloadavg_setgid, +[AC_EGREP_CPP([Yowza Am I SETGID yet], +[#include "$srcdir/getloadavg.c" +#ifdef LDAV_PRIVILEGED +Yowza Am I SETGID yet +#endif], + ac_cv_func_getloadavg_setgid=yes, ac_cv_func_getloadavg_setgid=no)]) +if test $ac_cv_func_getloadavg_setgid = yes; then + NEED_SETGID=true; AC_DEFINE(GETLOADAVG_PRIVILEGED) +else + NEED_SETGID=false +fi +AC_SUBST(NEED_SETGID)dnl + +if test $ac_cv_func_getloadavg_setgid = yes; then + AC_CACHE_CHECK(group of /dev/kmem, ac_cv_group_kmem, +[changequote(, )dnl + # On Solaris, /dev/kmem is a symlink. Get info on the real file. + ac_ls_output=`ls -lgL /dev/kmem 2>/dev/null` + # If we got an error (system does not support symlinks), try without -L. + test -z "$ac_ls_output" && ac_ls_output=`ls -lg /dev/kmem` + ac_cv_group_kmem=`echo $ac_ls_output \ + | sed -ne 's/[ ][ ]*/ /g; + s/^.[sSrwx-]* *[0-9]* *\([^0-9]*\) *.*/\1/; + / /s/.* //;p;'` +changequote([, ])dnl +]) + KMEM_GROUP=$ac_cv_group_kmem +fi +AC_SUBST(KMEM_GROUP)dnl +]) + +AC_DEFUN(AC_FUNC_UTIME_NULL, +[AC_CACHE_CHECK(whether utime accepts a null argument, ac_cv_func_utime_null, +[rm -f conftestdata; > conftestdata +# Sequent interprets utime(file, 0) to mean use start of epoch. Wrong. +AC_TRY_RUN([#include +#include +int main() { +struct stat s, t; +exit(!(stat ("conftestdata", &s) == 0 && utime("conftestdata", (long *)0) == 0 +&& stat("conftestdata", &t) == 0 && t.st_mtime >= s.st_mtime +&& t.st_mtime - s.st_mtime < 120)); +}], ac_cv_func_utime_null=yes, ac_cv_func_utime_null=no, + ac_cv_func_utime_null=no) +rm -f core]) +if test $ac_cv_func_utime_null = yes; then + AC_DEFINE(HAVE_UTIME_NULL) +fi +]) + +AC_DEFUN(AC_FUNC_STRCOLL, +[AC_CACHE_CHECK(for working strcoll, ac_cv_func_strcoll_works, +[AC_TRY_RUN([#include +int main () +{ + exit (strcoll ("abc", "def") >= 0 || + strcoll ("ABC", "DEF") >= 0 || + strcoll ("123", "456") >= 0); +}], ac_cv_func_strcoll_works=yes, ac_cv_func_strcoll_works=no, +ac_cv_func_strcoll_works=no)]) +if test $ac_cv_func_strcoll_works = yes; then + AC_DEFINE(HAVE_STRCOLL) +fi +]) + +AC_DEFUN(AC_FUNC_SETVBUF_REVERSED, +[AC_CACHE_CHECK(whether setvbuf arguments are reversed, + ac_cv_func_setvbuf_reversed, +[AC_TRY_RUN([#include +/* If setvbuf has the reversed format, exit 0. */ +int main () { + /* This call has the arguments reversed. + A reversed system may check and see that the address of main + is not _IOLBF, _IONBF, or _IOFBF, and return nonzero. */ + if (setvbuf(stdout, _IOLBF, (char *) main, BUFSIZ) != 0) + exit(1); + putc('\r', stdout); + exit(0); /* Non-reversed systems segv here. */ +}], ac_cv_func_setvbuf_reversed=yes, ac_cv_func_setvbuf_reversed=no) +rm -f core]) +if test $ac_cv_func_setvbuf_reversed = yes; then + AC_DEFINE(SETVBUF_REVERSED) +fi +]) + +AC_DEFUN(AC_FUNC_GETMNTENT, +[# getmntent is in -lsun on Irix 4, -lseq on Dynix/PTX, -lgen on Unixware. +AC_CHECK_LIB(sun, getmntent, LIBS="-lsun $LIBS", + [AC_CHECK_LIB(seq, getmntent, LIBS="-lseq $LIBS", + [AC_CHECK_LIB(gen, getmntent, LIBS="-lgen $LIBS")])]) +AC_CHECK_FUNC(getmntent, [AC_DEFINE(HAVE_GETMNTENT)])]) + +AC_DEFUN(AC_FUNC_STRFTIME, +[AC_CHECK_FUNC(strftime, [AC_DEFINE(HAVE_STRFTIME)], +[# strftime is in -lintl on SCO UNIX. +AC_CHECK_LIB(intl, strftime, +[AC_DEFINE(HAVE_STRFTIME) +LIBS="-lintl $LIBS"])])]) + +AC_DEFUN(AC_FUNC_MEMCMP, +[AC_CACHE_CHECK(for 8-bit clean memcmp, ac_cv_func_memcmp_clean, +[AC_TRY_RUN([ +int main() +{ + char c0 = 0x40, c1 = 0x80, c2 = 0x81; + exit(memcmp(&c0, &c2, 1) < 0 && memcmp(&c1, &c2, 1) < 0 ? 0 : 1); +} +], ac_cv_func_memcmp_clean=yes, ac_cv_func_memcmp_clean=no, +ac_cv_func_memcmp_clean=no)]) +test $ac_cv_func_memcmp_clean = no && LIBOBJS="$LIBOBJS memcmp.${ac_objext}" +AC_SUBST(LIBOBJS)dnl +]) + +AC_DEFUN(AC_FUNC_SELECT_ARGTYPES, +[AC_MSG_CHECKING([types of arguments for select()]) + AC_CACHE_VAL(ac_cv_func_select_arg234,dnl + [AC_CACHE_VAL(ac_cv_func_select_arg1,dnl + [AC_CACHE_VAL(ac_cv_func_select_arg5,dnl + [for ac_cv_func_select_arg234 in 'fd_set *' 'int *' 'void *'; do + for ac_cv_func_select_arg1 in 'int' 'size_t' 'unsigned long' 'unsigned'; do + for ac_cv_func_select_arg5 in 'struct timeval *' 'const struct timeval *'; do + AC_TRY_COMPILE(dnl +[#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_SYS_SELECT_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +extern select ($ac_cv_func_select_arg1,$ac_cv_func_select_arg234,$ac_cv_func_select_arg234,$ac_cv_func_select_arg234,$ac_cv_func_select_arg5);],,dnl + [ac_not_found=no ; break 3],ac_not_found=yes) + done + done + done + ])dnl AC_CACHE_VAL + ])dnl AC_CACHE_VAL + ])dnl AC_CACHE_VAL + if test "$ac_not_found" = yes; then + ac_cv_func_select_arg1=int + ac_cv_func_select_arg234='int *' + ac_cv_func_select_arg5='struct timeval *' + fi + AC_MSG_RESULT([$ac_cv_func_select_arg1,$ac_cv_func_select_arg234,$ac_cv_func_select_arg5]) + AC_DEFINE_UNQUOTED(SELECT_TYPE_ARG1,$ac_cv_func_select_arg1) + AC_DEFINE_UNQUOTED(SELECT_TYPE_ARG234,($ac_cv_func_select_arg234)) + AC_DEFINE_UNQUOTED(SELECT_TYPE_ARG5,($ac_cv_func_select_arg5)) +]) + + +dnl ### Checks for structure members + + +AC_DEFUN(AC_HEADER_TIME, +[AC_CACHE_CHECK([whether time.h and sys/time.h may both be included], + ac_cv_header_time, +[AC_TRY_COMPILE([#include +#include +#include ], +[struct tm *tp;], ac_cv_header_time=yes, ac_cv_header_time=no)]) +if test $ac_cv_header_time = yes; then + AC_DEFINE(TIME_WITH_SYS_TIME) +fi +]) + +AC_DEFUN(AC_STRUCT_TM, +[AC_CACHE_CHECK([whether struct tm is in sys/time.h or time.h], + ac_cv_struct_tm, +[AC_TRY_COMPILE([#include +#include ], +[struct tm *tp; tp->tm_sec;], + ac_cv_struct_tm=time.h, ac_cv_struct_tm=sys/time.h)]) +if test $ac_cv_struct_tm = sys/time.h; then + AC_DEFINE(TM_IN_SYS_TIME) +fi +]) + +AC_DEFUN(AC_STRUCT_TIMEZONE, +[AC_REQUIRE([AC_STRUCT_TM])dnl +AC_CACHE_CHECK([for tm_zone in struct tm], ac_cv_struct_tm_zone, +[AC_TRY_COMPILE([#include +#include <$ac_cv_struct_tm>], [struct tm tm; tm.tm_zone;], + ac_cv_struct_tm_zone=yes, ac_cv_struct_tm_zone=no)]) +if test "$ac_cv_struct_tm_zone" = yes; then + AC_DEFINE(HAVE_TM_ZONE) +else + AC_CACHE_CHECK(for tzname, ac_cv_var_tzname, +[AC_TRY_LINK( +changequote(<<, >>)dnl +<<#include +#ifndef tzname /* For SGI. */ +extern char *tzname[]; /* RS6000 and others reject char **tzname. */ +#endif>>, +changequote([, ])dnl +[atoi(*tzname);], ac_cv_var_tzname=yes, ac_cv_var_tzname=no)]) + if test $ac_cv_var_tzname = yes; then + AC_DEFINE(HAVE_TZNAME) + fi +fi +]) + +AC_DEFUN(AC_STRUCT_ST_BLOCKS, +[AC_CACHE_CHECK([for st_blocks in struct stat], ac_cv_struct_st_blocks, +[AC_TRY_COMPILE([#include +#include ], [struct stat s; s.st_blocks;], +ac_cv_struct_st_blocks=yes, ac_cv_struct_st_blocks=no)]) +if test $ac_cv_struct_st_blocks = yes; then + AC_DEFINE(HAVE_ST_BLOCKS) +else + LIBOBJS="$LIBOBJS fileblocks.${ac_objext}" +fi +AC_SUBST(LIBOBJS)dnl +]) + +AC_DEFUN(AC_STRUCT_ST_BLKSIZE, +[AC_CACHE_CHECK([for st_blksize in struct stat], ac_cv_struct_st_blksize, +[AC_TRY_COMPILE([#include +#include ], [struct stat s; s.st_blksize;], +ac_cv_struct_st_blksize=yes, ac_cv_struct_st_blksize=no)]) +if test $ac_cv_struct_st_blksize = yes; then + AC_DEFINE(HAVE_ST_BLKSIZE) +fi +]) + +AC_DEFUN(AC_STRUCT_ST_RDEV, +[AC_CACHE_CHECK([for st_rdev in struct stat], ac_cv_struct_st_rdev, +[AC_TRY_COMPILE([#include +#include ], [struct stat s; s.st_rdev;], +ac_cv_struct_st_rdev=yes, ac_cv_struct_st_rdev=no)]) +if test $ac_cv_struct_st_rdev = yes; then + AC_DEFINE(HAVE_ST_RDEV) +fi +]) + + +dnl ### Checks for compiler characteristics + + +AC_DEFUN(AC_C_CROSS, +[AC_OBSOLETE([$0], [; it has been merged into AC_PROG_CC])]) + +AC_DEFUN(AC_C_CHAR_UNSIGNED, +[AC_CACHE_CHECK(whether char is unsigned, ac_cv_c_char_unsigned, +[if test "$GCC" = yes; then + # GCC predefines this symbol on systems where it applies. +AC_EGREP_CPP(yes, +[#ifdef __CHAR_UNSIGNED__ + yes +#endif +], ac_cv_c_char_unsigned=yes, ac_cv_c_char_unsigned=no) +else +AC_TRY_RUN( +[/* volatile prevents gcc2 from optimizing the test away on sparcs. */ +#if !defined(__STDC__) || __STDC__ != 1 +#define volatile +#endif +int main() { + volatile char c = 255; exit(c < 0); +}], ac_cv_c_char_unsigned=yes, ac_cv_c_char_unsigned=no) +fi]) +if test $ac_cv_c_char_unsigned = yes && test "$GCC" != yes; then + AC_DEFINE(__CHAR_UNSIGNED__) +fi +]) + +AC_DEFUN(AC_C_LONG_DOUBLE, +[AC_CACHE_CHECK(for long double, ac_cv_c_long_double, +[if test "$GCC" = yes; then + ac_cv_c_long_double=yes +else +AC_TRY_RUN([int main() { +/* The Stardent Vistra knows sizeof(long double), but does not support it. */ +long double foo = 0.0; +/* On Ultrix 4.3 cc, long double is 4 and double is 8. */ +exit(sizeof(long double) < sizeof(double)); }], +ac_cv_c_long_double=yes, ac_cv_c_long_double=no) +fi]) +if test $ac_cv_c_long_double = yes; then + AC_DEFINE(HAVE_LONG_DOUBLE) +fi +]) + +AC_DEFUN(AC_INT_16_BITS, +[AC_OBSOLETE([$0], [; instead use AC_CHECK_SIZEOF(int)])dnl +AC_MSG_CHECKING(whether int is 16 bits) +AC_TRY_RUN([int main() { exit(sizeof(int) != 2); }], + [AC_MSG_RESULT(yes) + AC_DEFINE(INT_16_BITS)], AC_MSG_RESULT(no)) +]) + +AC_DEFUN(AC_LONG_64_BITS, +[AC_OBSOLETE([$0], [; instead use AC_CHECK_SIZEOF(long)])dnl +AC_MSG_CHECKING(whether long int is 64 bits) +AC_TRY_RUN([int main() { exit(sizeof(long int) != 8); }], + [AC_MSG_RESULT(yes) + AC_DEFINE(LONG_64_BITS)], AC_MSG_RESULT(no)) +]) + +AC_DEFUN(AC_C_BIGENDIAN, +[AC_CACHE_CHECK(whether byte ordering is bigendian, ac_cv_c_bigendian, +[ac_cv_c_bigendian=unknown +# See if sys/param.h defines the BYTE_ORDER macro. +AC_TRY_COMPILE([#include +#include ], [ +#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN + bogus endian macros +#endif], [# It does; now see whether it defined to BIG_ENDIAN or not. +AC_TRY_COMPILE([#include +#include ], [ +#if BYTE_ORDER != BIG_ENDIAN + not big endian +#endif], ac_cv_c_bigendian=yes, ac_cv_c_bigendian=no)]) +if test $ac_cv_c_bigendian = unknown; then +AC_TRY_RUN([int main () { + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long l; + char c[sizeof (long)]; + } u; + u.l = 1; + exit (u.c[sizeof (long) - 1] == 1); +}], ac_cv_c_bigendian=no, ac_cv_c_bigendian=yes) +fi]) +if test $ac_cv_c_bigendian = yes; then + AC_DEFINE(WORDS_BIGENDIAN) +fi +]) + +dnl Do nothing if the compiler accepts the inline keyword. +dnl Otherwise define inline to __inline__ or __inline if one of those work, +dnl otherwise define inline to be empty. +AC_DEFUN(AC_C_INLINE, +[AC_CACHE_CHECK([for inline], ac_cv_c_inline, +[ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + AC_TRY_COMPILE(, [} $ac_kw foo() {], [ac_cv_c_inline=$ac_kw; break]) +done +]) +case "$ac_cv_c_inline" in + inline | yes) ;; + no) AC_DEFINE(inline, ) ;; + *) AC_DEFINE_UNQUOTED(inline, $ac_cv_c_inline) ;; +esac +]) + +AC_DEFUN(AC_C_CONST, +[dnl This message is consistent in form with the other checking messages, +dnl and with the result message. +AC_CACHE_CHECK([for working const], ac_cv_c_const, +[AC_TRY_COMPILE(, +changequote(<<, >>)dnl +<< +#ifndef __cplusplus +/* Ultrix mips cc rejects this. */ +typedef int charset[2]; const charset x; +#endif +/* SunOS 4.1.1 cc rejects this. */ +char const *const *ccp; +char **p; +/* NEC SVR4.0.2 mips cc rejects this. */ +struct point {int x, y;}; +static struct point const zero = {0,0}; +/* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in an arm + of an if-expression whose if-part is not a constant expression */ +const char *g = "string"; +ccp = &g + (g ? g-g : 0); +/* HPUX 7.0 cc rejects these. */ +++ccp; +p = (char**) ccp; +ccp = (char const *const *) p; +{ /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; +} +{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; +} +{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; +} +{ /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; +} +{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; +} +>>, +changequote([, ])dnl +ac_cv_c_const=yes, ac_cv_c_const=no)]) +if test $ac_cv_c_const = no; then + AC_DEFINE(const, ) +fi +]) + +AC_DEFUN(AC_C_STRINGIZE, [ +AC_REQUIRE([AC_PROG_CPP]) +AC_MSG_CHECKING([for preprocessor stringizing operator]) +AC_CACHE_VAL(ac_cv_c_stringize, +AC_EGREP_CPP([#teststring],[ +#define x(y) #y + +char *s = x(teststring); +], ac_cv_c_stringize=no, ac_cv_c_stringize=yes)) +if test "${ac_cv_c_stringize}" = yes +then + AC_DEFINE(HAVE_STRINGIZE) +fi +AC_MSG_RESULT([${ac_cv_c_stringize}]) +])dnl + +define(AC_ARG_ARRAY, +[errprint(__file__:__line__: [$0] has been removed; don't do unportable things with arguments +)m4exit(4)]) + +dnl Check the object extension used by the compiler: typically .o or +dnl .obj. If this is called, some other behaviour will change, +dnl determined by ac_objext. +AC_DEFUN(AC_OBJEXT, +[AC_MSG_CHECKING([for object suffix]) +AC_CACHE_VAL(ac_cv_objext, +[rm -f conftest* +echo 'int i = 1;' > conftest.$ac_ext +if AC_TRY_EVAL(ac_compile); then + for ac_file in conftest.*; do + case $ac_file in + *.c) ;; + *) ac_cv_objext=`echo $ac_file | sed -e s/conftest.//` ;; + esac + done +else + AC_MSG_ERROR([installation or configuration problem; compiler does not work]) +fi +rm -f conftest*]) +AC_MSG_RESULT($ac_cv_objext) +OBJEXT=$ac_cv_objext +ac_objext=$ac_cv_objext +AC_SUBST(OBJEXT)]) + +dnl Determine the linker flags (e.g. `-L' and `-l') for the Fortran 77 +dnl intrinsic and run-time libraries that are required to successfully +dnl link a Fortran 77 program or shared library. The output variable +dnl FLIBS is set to these flags. +dnl +dnl This macro is intended to be used in those situations when it is +dnl necessary to mix, e.g. C++ and Fortran 77, source code into a single +dnl program or shared library. +dnl +dnl For example, if object files from a C++ and Fortran 77 compiler must +dnl be linked together, then the C++ compiler/linker must be used for +dnl linking (since special C++-ish things need to happen at link time +dnl like calling global constructors, instantiating templates, enabling +dnl exception support, etc.). +dnl +dnl However, the Fortran 77 intrinsic and run-time libraries must be +dnl linked in as well, but the C++ compiler/linker doesn't know how to +dnl add these Fortran 77 libraries. Hence, the macro +dnl `AC_F77_LIBRARY_LDFLAGS' was created to determine these Fortran 77 +dnl libraries. +dnl +dnl This macro was packaged in its current form by Matthew D. Langston +dnl . However, nearly all of this macro +dnl came from the `OCTAVE_FLIBS' macro in `octave-2.0.13/aclocal.m4', +dnl and full credit should go to John W. Eaton for writing this +dnl extremely useful macro. Thank you John. +dnl +dnl AC_F77_LIBRARY_LDFLAGS() +AC_DEFUN(AC_F77_LIBRARY_LDFLAGS, +[AC_MSG_CHECKING([for Fortran 77 libraries]) +AC_REQUIRE([AC_PROG_F77]) +AC_REQUIRE([AC_CANONICAL_HOST]) +AC_CACHE_VAL(ac_cv_flibs, +[changequote(, )dnl +dnl Write a minimal program and compile it with -v. I don't know what +dnl to do if your compiler doesn't have -v... +echo " END" > conftest.f +foutput=`${F77} -v -o conftest conftest.f 2>&1` +dnl +dnl The easiest thing to do for xlf output is to replace all the commas +dnl with spaces. Try to only do that if the output is really from xlf, +dnl since doing that causes problems on other systems. +dnl +xlf_p=`echo $foutput | grep xlfentry` +if test -n "$xlf_p"; then + foutput=`echo $foutput | sed 's/,/ /g'` +fi +dnl +ld_run_path=`echo $foutput | \ + sed -n -e 's/^.*LD_RUN_PATH *= *\([^ ]*\).*/\1/p'` +dnl +dnl We are only supposed to find this on Solaris systems... +dnl Uh, the run path should be absolute, shouldn't it? +dnl +case "$ld_run_path" in + /*) + if test "$ac_cv_prog_gcc" = yes; then + ld_run_path="-Xlinker -R -Xlinker $ld_run_path" + else + ld_run_path="-R $ld_run_path" + fi + ;; + *) + ld_run_path= + ;; +esac +dnl +flibs= +lflags= +dnl +dnl If want_arg is set, we know we want the arg to be added to the list, +dnl so we don't have to examine it. +dnl +want_arg= +dnl +for arg in $foutput; do + old_want_arg=$want_arg + want_arg= +dnl +dnl None of the options that take arguments expect the argument to +dnl start with a -, so pretend we didn't see anything special. +dnl + if test -n "$old_want_arg"; then + case "$arg" in + -*) + old_want_arg= + ;; + esac + fi + case "$old_want_arg" in + '') + case $arg in + /*.a) + exists=false + for f in $lflags; do + if test x$arg = x$f; then + exists=true + fi + done + if $exists; then + arg= + else + lflags="$lflags $arg" + fi + ;; + -bI:*) + exists=false + for f in $lflags; do + if test x$arg = x$f; then + exists=true + fi + done + if $exists; then + arg= + else + if test "$ac_cv_prog_gcc" = yes; then + lflags="$lflags -Xlinker $arg" + else + lflags="$lflags $arg" + fi + fi + ;; + -lang* | -lcrt0.o | -lc | -lgcc) + arg= + ;; + -[lLR]) + want_arg=$arg + arg= + ;; + -[lLR]*) + exists=false + for f in $lflags; do + if test x$arg = x$f; then + exists=true + fi + done + if $exists; then + arg= + else + case "$arg" in + -lkernel32) + case "$canonical_host_type" in + *-*-cygwin*) + arg= + ;; + *) + lflags="$lflags $arg" + ;; + esac + ;; + -lm) + ;; + *) + lflags="$lflags $arg" + ;; + esac + fi + ;; + -u) + want_arg=$arg + arg= + ;; + -Y) + want_arg=$arg + arg= + ;; + *) + arg= + ;; + esac + ;; + -[lLR]) + arg="$old_want_arg $arg" + ;; + -u) + arg="-u $arg" + ;; + -Y) +dnl +dnl Should probably try to ensure unique directory options here too. +dnl This probably only applies to Solaris systems, and then will only +dnl work with gcc... +dnl + arg=`echo $arg | sed -e 's%^P,%%'` + SAVE_IFS=$IFS + IFS=: + list= + for elt in $arg; do + list="$list -L$elt" + done + IFS=$SAVE_IFS + arg="$list" + ;; + esac +dnl + if test -n "$arg"; then + flibs="$flibs $arg" + fi +done +if test -n "$ld_run_path"; then + flibs_result="$ld_run_path $flibs" +else + flibs_result="$flibs" +fi +changequote([, ])dnl +ac_cv_flibs="$flibs_result"]) +FLIBS="$ac_cv_flibs" +AC_SUBST(FLIBS)dnl +AC_MSG_RESULT($FLIBS) +]) + + +dnl ### Checks for operating system services + + +AC_DEFUN(AC_SYS_INTERPRETER, +[# Pull the hash mark out of the macro call to avoid m4 problems. +ac_msg="whether #! works in shell scripts" +AC_CACHE_CHECK($ac_msg, ac_cv_sys_interpreter, +[echo '#! /bin/cat +exit 69 +' > conftest +chmod u+x conftest +(SHELL=/bin/sh; export SHELL; ./conftest >/dev/null) +if test $? -ne 69; then + ac_cv_sys_interpreter=yes +else + ac_cv_sys_interpreter=no +fi +rm -f conftest]) +interpval="$ac_cv_sys_interpreter" +]) + +define(AC_HAVE_POUNDBANG, +[errprint(__file__:__line__: [$0 has been replaced by AC_SYS_INTERPRETER, taking no arguments +])m4exit(4)]) + +AC_DEFUN(AC_SYS_LONG_FILE_NAMES, +[AC_CACHE_CHECK(for long file names, ac_cv_sys_long_file_names, +[ac_cv_sys_long_file_names=yes +# Test for long file names in all the places we know might matter: +# . the current directory, where building will happen +# $prefix/lib where we will be installing things +# $exec_prefix/lib likewise +# eval it to expand exec_prefix. +# $TMPDIR if set, where it might want to write temporary files +# if $TMPDIR is not set: +# /tmp where it might want to write temporary files +# /var/tmp likewise +# /usr/tmp likewise +if test -n "$TMPDIR" && test -d "$TMPDIR" && test -w "$TMPDIR"; then + ac_tmpdirs="$TMPDIR" +else + ac_tmpdirs='/tmp /var/tmp /usr/tmp' +fi +for ac_dir in . $ac_tmpdirs `eval echo $prefix/lib $exec_prefix/lib` ; do + test -d $ac_dir || continue + test -w $ac_dir || continue # It is less confusing to not echo anything here. + (echo 1 > $ac_dir/conftest9012345) 2>/dev/null + (echo 2 > $ac_dir/conftest9012346) 2>/dev/null + val=`cat $ac_dir/conftest9012345 2>/dev/null` + if test ! -f $ac_dir/conftest9012345 || test "$val" != 1; then + ac_cv_sys_long_file_names=no + rm -f $ac_dir/conftest9012345 $ac_dir/conftest9012346 2>/dev/null + break + fi + rm -f $ac_dir/conftest9012345 $ac_dir/conftest9012346 2>/dev/null +done]) +if test $ac_cv_sys_long_file_names = yes; then + AC_DEFINE(HAVE_LONG_FILE_NAMES) +fi +]) + +AC_DEFUN(AC_SYS_RESTARTABLE_SYSCALLS, +[AC_CACHE_CHECK(for restartable system calls, ac_cv_sys_restartable_syscalls, +[AC_TRY_RUN( +[/* Exit 0 (true) if wait returns something other than -1, + i.e. the pid of the child, which means that wait was restarted + after getting the signal. */ +#include +#include +ucatch (isig) { } +int main () { + int i = fork (), status; + if (i == 0) { sleep (3); kill (getppid (), SIGINT); sleep (3); exit (0); } + signal (SIGINT, ucatch); + status = wait(&i); + if (status == -1) wait(&i); + exit (status == -1); +} +], ac_cv_sys_restartable_syscalls=yes, ac_cv_sys_restartable_syscalls=no)]) +if test $ac_cv_sys_restartable_syscalls = yes; then + AC_DEFINE(HAVE_RESTARTABLE_SYSCALLS) +fi +]) + +AC_DEFUN(AC_PATH_X, +[AC_REQUIRE_CPP()dnl Set CPP; we run AC_PATH_X_DIRECT conditionally. +# If we find X, set shell vars x_includes and x_libraries to the +# paths, otherwise set no_x=yes. +# Uses ac_ vars as temps to allow command line to override cache and checks. +# --without-x overrides everything else, but does not touch the cache. +AC_MSG_CHECKING(for X) + +AC_ARG_WITH(x, [ --with-x use the X Window System]) +# $have_x is `yes', `no', `disabled', or empty when we do not yet know. +if test "x$with_x" = xno; then + # The user explicitly disabled X. + have_x=disabled +else + if test "x$x_includes" != xNONE && test "x$x_libraries" != xNONE; then + # Both variables are already set. + have_x=yes + else +AC_CACHE_VAL(ac_cv_have_x, +[# One or both of the vars are not set, and there is no cached value. +ac_x_includes=NO ac_x_libraries=NO +AC_PATH_X_XMKMF +AC_PATH_X_DIRECT +if test "$ac_x_includes" = NO || test "$ac_x_libraries" = NO; then + # Didn't find X anywhere. Cache the known absence of X. + ac_cv_have_x="have_x=no" +else + # Record where we found X for the cache. + ac_cv_have_x="have_x=yes \ + ac_x_includes=$ac_x_includes ac_x_libraries=$ac_x_libraries" +fi])dnl + fi + eval "$ac_cv_have_x" +fi # $with_x != no + +if test "$have_x" != yes; then + AC_MSG_RESULT($have_x) + no_x=yes +else + # If each of the values was on the command line, it overrides each guess. + test "x$x_includes" = xNONE && x_includes=$ac_x_includes + test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries + # Update the cache value to reflect the command line values. + ac_cv_have_x="have_x=yes \ + ac_x_includes=$x_includes ac_x_libraries=$x_libraries" + AC_MSG_RESULT([libraries $x_libraries, headers $x_includes]) +fi +]) + +dnl Internal subroutine of AC_PATH_X. +dnl Set ac_x_includes and/or ac_x_libraries. +AC_DEFUN(AC_PATH_X_XMKMF, +[rm -fr conftestdir +if mkdir conftestdir; then + cd conftestdir + # Make sure to not put "make" in the Imakefile rules, since we grep it out. + cat > Imakefile <<'EOF' +acfindx: + @echo 'ac_im_incroot="${INCROOT}"; ac_im_usrlibdir="${USRLIBDIR}"; ac_im_libdir="${LIBDIR}"' +EOF + if (xmkmf) >/dev/null 2>/dev/null && test -f Makefile; then + # GNU make sometimes prints "make[1]: Entering...", which would confuse us. + eval `${MAKE-make} acfindx 2>/dev/null | grep -v make` + # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. + for ac_extension in a so sl; do + if test ! -f $ac_im_usrlibdir/libX11.$ac_extension && + test -f $ac_im_libdir/libX11.$ac_extension; then + ac_im_usrlibdir=$ac_im_libdir; break + fi + done + # Screen out bogus values from the imake configuration. They are + # bogus both because they are the default anyway, and because + # using them would break gcc on systems where it needs fixed includes. + case "$ac_im_incroot" in + /usr/include) ;; + *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes="$ac_im_incroot" ;; + esac + case "$ac_im_usrlibdir" in + /usr/lib | /lib) ;; + *) test -d "$ac_im_usrlibdir" && ac_x_libraries="$ac_im_usrlibdir" ;; + esac + fi + cd .. + rm -fr conftestdir +fi +]) + +dnl Internal subroutine of AC_PATH_X. +dnl Set ac_x_includes and/or ac_x_libraries. +AC_DEFUN(AC_PATH_X_DIRECT, +[if test "$ac_x_includes" = NO; then + # Guess where to find include files, by looking for this one X11 .h file. + test -z "$x_direct_test_include" && x_direct_test_include=X11/Intrinsic.h + + # First, try using that file with no special directory specified. +AC_TRY_CPP([#include <$x_direct_test_include>], +[# We can compile using X headers with no special include directory. +ac_x_includes=], +[# Look for the header file in a standard set of common directories. +# Check X11 before X11Rn because it is often a symlink to the current release. + for ac_dir in \ + /usr/X11/include \ + /usr/X11R6/include \ + /usr/X11R5/include \ + /usr/X11R4/include \ + \ + /usr/include/X11 \ + /usr/include/X11R6 \ + /usr/include/X11R5 \ + /usr/include/X11R4 \ + \ + /usr/local/X11/include \ + /usr/local/X11R6/include \ + /usr/local/X11R5/include \ + /usr/local/X11R4/include \ + \ + /usr/local/include/X11 \ + /usr/local/include/X11R6 \ + /usr/local/include/X11R5 \ + /usr/local/include/X11R4 \ + \ + /usr/X386/include \ + /usr/x386/include \ + /usr/XFree86/include/X11 \ + \ + /usr/include \ + /usr/local/include \ + /usr/unsupported/include \ + /usr/athena/include \ + /usr/local/x11r5/include \ + /usr/lpp/Xamples/include \ + \ + /usr/openwin/include \ + /usr/openwin/share/include \ + ; \ + do + if test -r "$ac_dir/$x_direct_test_include"; then + ac_x_includes=$ac_dir + break + fi + done]) +fi # $ac_x_includes = NO + +if test "$ac_x_libraries" = NO; then + # Check for the libraries. + + test -z "$x_direct_test_library" && x_direct_test_library=Xt + test -z "$x_direct_test_function" && x_direct_test_function=XtMalloc + + # See if we find them without any special options. + # Don't add to $LIBS permanently. + ac_save_LIBS="$LIBS" + LIBS="-l$x_direct_test_library $LIBS" +AC_TRY_LINK(, [${x_direct_test_function}()], +[LIBS="$ac_save_LIBS" +# We can link X programs with no special library path. +ac_x_libraries=], +[LIBS="$ac_save_LIBS" +# First see if replacing the include by lib works. +# Check X11 before X11Rn because it is often a symlink to the current release. +for ac_dir in `echo "$ac_x_includes" | sed s/include/lib/` \ + /usr/X11/lib \ + /usr/X11R6/lib \ + /usr/X11R5/lib \ + /usr/X11R4/lib \ + \ + /usr/lib/X11 \ + /usr/lib/X11R6 \ + /usr/lib/X11R5 \ + /usr/lib/X11R4 \ + \ + /usr/local/X11/lib \ + /usr/local/X11R6/lib \ + /usr/local/X11R5/lib \ + /usr/local/X11R4/lib \ + \ + /usr/local/lib/X11 \ + /usr/local/lib/X11R6 \ + /usr/local/lib/X11R5 \ + /usr/local/lib/X11R4 \ + \ + /usr/X386/lib \ + /usr/x386/lib \ + /usr/XFree86/lib/X11 \ + \ + /usr/lib \ + /usr/local/lib \ + /usr/unsupported/lib \ + /usr/athena/lib \ + /usr/local/x11r5/lib \ + /usr/lpp/Xamples/lib \ + /lib/usr/lib/X11 \ + \ + /usr/openwin/lib \ + /usr/openwin/share/lib \ + ; \ +do +dnl Don't even attempt the hair of trying to link an X program! + for ac_extension in a so sl; do + if test -r $ac_dir/lib${x_direct_test_library}.$ac_extension; then + ac_x_libraries=$ac_dir + break 2 + fi + done +done]) +fi # $ac_x_libraries = NO +]) + +dnl Find additional X libraries, magic flags, etc. +AC_DEFUN(AC_PATH_XTRA, +[AC_REQUIRE([AC_PATH_X])dnl +if test "$no_x" = yes; then + # Not all programs may use this symbol, but it does not hurt to define it. + AC_DEFINE(X_DISPLAY_MISSING) + X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS= +else + if test -n "$x_includes"; then + X_CFLAGS="$X_CFLAGS -I$x_includes" + fi + + # It would also be nice to do this for all -L options, not just this one. + if test -n "$x_libraries"; then + X_LIBS="$X_LIBS -L$x_libraries" +dnl FIXME banish uname from this macro! + # For Solaris; some versions of Sun CC require a space after -R and + # others require no space. Words are not sufficient . . . . + case "`(uname -sr) 2>/dev/null`" in + "SunOS 5"*) + AC_MSG_CHECKING(whether -R must be followed by a space) + ac_xsave_LIBS="$LIBS"; LIBS="$LIBS -R$x_libraries" + AC_TRY_LINK(, , ac_R_nospace=yes, ac_R_nospace=no) + if test $ac_R_nospace = yes; then + AC_MSG_RESULT(no) + X_LIBS="$X_LIBS -R$x_libraries" + else + LIBS="$ac_xsave_LIBS -R $x_libraries" + AC_TRY_LINK(, , ac_R_space=yes, ac_R_space=no) + if test $ac_R_space = yes; then + AC_MSG_RESULT(yes) + X_LIBS="$X_LIBS -R $x_libraries" + else + AC_MSG_RESULT(neither works) + fi + fi + LIBS="$ac_xsave_LIBS" + esac + fi + + # Check for system-dependent libraries X programs must link with. + # Do this before checking for the system-independent R6 libraries + # (-lICE), since we may need -lsocket or whatever for X linking. + + if test "$ISC" = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet" + else + # Martyn.Johnson@cl.cam.ac.uk says this is needed for Ultrix, if the X + # libraries were built with DECnet support. And karl@cs.umb.edu says + # the Alpha needs dnet_stub (dnet does not exist). + AC_CHECK_LIB(dnet, dnet_ntoa, [X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet"]) + if test $ac_cv_lib_dnet_dnet_ntoa = no; then + AC_CHECK_LIB(dnet_stub, dnet_ntoa, + [X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub"]) + fi + + # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT, + # to get the SysV transport functions. + # chad@anasazi.com says the Pyramis MIS-ES running DC/OSx (SVR4) + # needs -lnsl. + # The nsl library prevents programs from opening the X display + # on Irix 5.2, according to dickey@clark.net. + AC_CHECK_FUNC(gethostbyname) + if test $ac_cv_func_gethostbyname = no; then + AC_CHECK_LIB(nsl, gethostbyname, X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl") + fi + + # lieder@skyler.mavd.honeywell.com says without -lsocket, + # socket/setsockopt and other routines are undefined under SCO ODT + # 2.0. But -lsocket is broken on IRIX 5.2 (and is not necessary + # on later versions), says simon@lia.di.epfl.ch: it contains + # gethostby* variants that don't use the nameserver (or something). + # -lsocket must be given before -lnsl if both are needed. + # We assume that if connect needs -lnsl, so does gethostbyname. + AC_CHECK_FUNC(connect) + if test $ac_cv_func_connect = no; then + AC_CHECK_LIB(socket, connect, X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS", , + $X_EXTRA_LIBS) + fi + + # gomez@mi.uni-erlangen.de says -lposix is necessary on A/UX. + AC_CHECK_FUNC(remove) + if test $ac_cv_func_remove = no; then + AC_CHECK_LIB(posix, remove, X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix") + fi + + # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. + AC_CHECK_FUNC(shmat) + if test $ac_cv_func_shmat = no; then + AC_CHECK_LIB(ipc, shmat, X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc") + fi + fi + + # Check for libraries that X11R6 Xt/Xaw programs need. + ac_save_LDFLAGS="$LDFLAGS" + test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries" + # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to + # check for ICE first), but we must link in the order -lSM -lICE or + # we get undefined symbols. So assume we have SM if we have ICE. + # These have to be linked with before -lX11, unlike the other + # libraries we check for below, so use a different variable. + # --interran@uluru.Stanford.EDU, kb@cs.umb.edu. + AC_CHECK_LIB(ICE, IceConnectionNumber, + [X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE"], , $X_EXTRA_LIBS) + LDFLAGS="$ac_save_LDFLAGS" + +fi +AC_SUBST(X_CFLAGS)dnl +AC_SUBST(X_PRE_LIBS)dnl +AC_SUBST(X_LIBS)dnl +AC_SUBST(X_EXTRA_LIBS)dnl +]) + +dnl The old Cygwin32 macro is deprecated. +AC_DEFUN(AC_CYGWIN32, +[AC_OBSOLETE([$0], [; instead use AC_CYGWIN])dnl +AC_CYGWIN]) + +dnl Check for Cygwin. This is a way to set the right value for +dnl EXEEXT. +AC_DEFUN(AC_CYGWIN, +[AC_CACHE_CHECK(for Cygwin environment, ac_cv_cygwin, +[AC_TRY_COMPILE(,[ +#ifndef __CYGWIN__ +#define __CYGWIN__ __CYGWIN32__ +#endif +return __CYGWIN__;], +ac_cv_cygwin=yes, ac_cv_cygwin=no) +rm -f conftest*]) +CYGWIN= +test "$ac_cv_cygwin" = yes && CYGWIN=yes]) + +dnl Check for mingw32. This is another way to set the right value for +dnl EXEEXT. +AC_DEFUN(AC_MINGW32, +[AC_CACHE_CHECK(for mingw32 environment, ac_cv_mingw32, +[AC_TRY_COMPILE(,[return __MINGW32__;], +ac_cv_mingw32=yes, ac_cv_mingw32=no) +rm -f conftest*]) +MINGW32= +test "$ac_cv_mingw32" = yes && MINGW32=yes]) + +dnl Check for the extension used for executables. This knows that we +dnl add .exe for Cygwin or mingw32. Otherwise, it compiles a test +dnl executable. If this is called, the executable extensions will be +dnl automatically used by link commands run by the configure script. +AC_DEFUN(AC_EXEEXT, +[AC_REQUIRE([AC_CYGWIN]) +AC_REQUIRE([AC_MINGW32]) +AC_MSG_CHECKING([for executable suffix]) +AC_CACHE_VAL(ac_cv_exeext, +[if test "$CYGWIN" = yes || test "$MINGW32" = yes; then + ac_cv_exeext=.exe +else + rm -f conftest* + echo 'int main () { return 0; }' > conftest.$ac_ext + ac_cv_exeext= + if AC_TRY_EVAL(ac_link); then + for file in conftest.*; do + case $file in + *.c | *.o | *.obj) ;; + *) ac_cv_exeext=`echo $file | sed -e s/conftest//` ;; + esac + done + else + AC_MSG_ERROR([installation or configuration problem: compiler cannot create executables.]) + fi + rm -f conftest* + test x"${ac_cv_exeext}" = x && ac_cv_exeext=no +fi]) +EXEEXT="" +test x"${ac_cv_exeext}" != xno && EXEEXT=${ac_cv_exeext} +AC_MSG_RESULT(${ac_cv_exeext}) +dnl Setting ac_exeext will implicitly change the ac_link command. +ac_exeext=$EXEEXT +AC_SUBST(EXEEXT)]) + + +dnl ### Checks for UNIX variants +dnl These are kludges which should be replaced by a single POSIX check. +dnl They aren't cached, to discourage their use. + + +AC_DEFUN(AC_AIX, +[AC_BEFORE([$0], [AC_TRY_COMPILE])dnl +AC_BEFORE([$0], [AC_TRY_RUN])dnl +AC_MSG_CHECKING(for AIX) +AC_CACHE_VAL(ac_cv_sys_aix,[ +AC_EGREP_CPP(yes, +[#ifdef _AIX + yes +#endif +], [ac_cv_sys_aix=yes], [ac_cv_sys_aix=no])]) +AC_MSG_RESULT($ac_cv_sys_aix) +if test $ac_cv_sys_aix = yes; then + AC_DEFINE(_ALL_SOURCE) +fi +]) + +AC_DEFUN(AC_MINIX, +[AC_BEFORE([$0], [AC_TRY_COMPILE])dnl +AC_BEFORE([$0], [AC_TRY_RUN])dnl +AC_CHECK_HEADER(minix/config.h, MINIX=yes, MINIX=) +if test "$MINIX" = yes; then + AC_DEFINE(_POSIX_SOURCE) + AC_DEFINE(_POSIX_1_SOURCE, 2) + AC_DEFINE(_MINIX) +fi +]) + +AC_DEFUN(AC_ISC_POSIX, +[AC_REQUIRE([AC_PROG_CC])dnl +AC_BEFORE([$0], [AC_TRY_COMPILE])dnl +AC_BEFORE([$0], [AC_TRY_RUN])dnl +AC_MSG_CHECKING(for POSIXized ISC) +AC_CACHE_VAL(ac_cv_sys_isc_posix,[ +if test -d /etc/conf/kconfig.d && + grep _POSIX_VERSION [/usr/include/sys/unistd.h] >/dev/null 2>&1 +then + ac_cv_sys_isc_posix=yes +else + ac_cv_sys_isc_posix=no +fi +]) +AC_MSG_RESULT($ac_cv_sys_isc_posix) +if test $ac_cv_sys_isc_posix = yes; then + ISC=yes # If later tests want to check for ISC. + AC_DEFINE(_POSIX_SOURCE) + if test "$GCC" = yes; then + CC="$CC -posix" + else + CC="$CC -Xp" + fi +else + ISC= +fi +]) + +AC_DEFUN(AC_XENIX_DIR, +[AC_OBSOLETE([$0], [; instead use AC_HEADER_DIRENT])dnl +AC_REQUIRE([AC_DIR_HEADER])dnl +AC_MSG_CHECKING(for Xenix) +AC_EGREP_CPP(yes, +[#if defined(M_XENIX) && !defined(M_UNIX) + yes +#endif +], [AC_MSG_RESULT(yes); XENIX=yes], [AC_MSG_RESULT(no); XENIX=]) +if test "$XENIX" = yes; then + # Make sure -ldir precedes -lx. + test $ac_header_dirent = dirent.h && LIBS="-ldir $LIBS" + LIBS="$LIBS -lx" +fi +]) + +AC_DEFUN(AC_DYNIX_SEQ, +[AC_OBSOLETE([$0], [; instead use AC_FUNC_GETMNTENT])dnl +AC_CHECK_LIB(seq, getmntent, LIBS="-lseq $LIBS") +]) + +AC_DEFUN(AC_IRIX_SUN, +[AC_OBSOLETE([$0], [; instead use AC_FUNC_GETMNTENT or AC_CHECK_LIB(sun, getpwnam)])dnl +AC_CHECK_LIB(sun, getmntent, LIBS="-lsun $LIBS") +]) + +AC_DEFUN(AC_SCO_INTL, +[AC_OBSOLETE([$0], [; instead use AC_FUNC_STRFTIME])dnl +AC_CHECK_LIB(intl, strftime, LIBS="-lintl $LIBS") +]) diff --git a/autoconf/autoconf b/autoconf/autoconf new file mode 100755 index 0000000..3dfdcba --- /dev/null +++ b/autoconf/autoconf @@ -0,0 +1,159 @@ +#! /bin/sh +# autoconf -- create `configure' using m4 macros +# Copyright (C) 1992, 1993, 1994, 1996 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; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# If given no args, create `configure' from template file `configure.in'. +# With one arg, create a configure script on standard output from +# the given template file. + +usage="\ +Usage: autoconf [-h] [--help] [-m dir] [--macrodir=dir] + [-l dir] [--localdir=dir] [--version] [template-file]" + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +: ${AC_MACRODIR=/usr/share/autoconf} +: ${M4=/usr/bin/m4} +: ${AWK=/usr/bin/awk} +case "${M4}" in +/*) # Handle the case that m4 has moved since we were configured. + # It may have been found originally in a build directory. + test -f "${M4}" || M4=m4 ;; +esac + +: ${TMPDIR=/tmp} +tmpout=${TMPDIR}/acout.$$ +localdir= +show_version=no + +while test $# -gt 0 ; do + case "${1}" in + -h | --help | --h* ) + echo "${usage}" 1>&2; exit 0 ;; + --localdir=* | --l*=* ) + localdir="`echo \"${1}\" | sed -e 's/^[^=]*=//'`" + shift ;; + -l | --localdir | --l*) + shift + test $# -eq 0 && { echo "${usage}" 1>&2; exit 1; } + localdir="${1}" + shift ;; + --macrodir=* | --m*=* ) + AC_MACRODIR="`echo \"${1}\" | sed -e 's/^[^=]*=//'`" + shift ;; + -m | --macrodir | --m* ) + shift + test $# -eq 0 && { echo "${usage}" 1>&2; exit 1; } + AC_MACRODIR="${1}" + shift ;; + --version | --v* ) + show_version=yes; shift ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "${usage}" 1>&2; exit 1 ;; + * ) + break ;; + esac +done + +if test $show_version = yes; then + version=`sed -n 's/define.AC_ACVERSION.[ ]*\([0-9.]*\).*/\1/p' \ + $AC_MACRODIR/acgeneral.m4` + echo "Autoconf version $version" + exit 0 +fi + +case $# in + 0) infile=configure.in ;; + 1) infile="$1" ;; + *) echo "$usage" >&2; exit 1 ;; +esac + +trap 'rm -f $tmpin $tmpout; exit 1' 1 2 15 + +tmpin=${TMPDIR}/acin.$$ # Always set this, to avoid bogus errors from some rm's. +if test z$infile = z-; then + infile=$tmpin + cat > $infile +elif test ! -r "$infile"; then + echo "autoconf: ${infile}: No such file or directory" >&2 + exit 1 +fi + +if test -n "$localdir"; then + use_localdir="-I$localdir -DAC_LOCALDIR=$localdir" +else + use_localdir= +fi + +# Use the frozen version of Autoconf if available. +r= f= +# Some non-GNU m4's don't reject the --help option, so give them /dev/null. +case `$M4 --help < /dev/null 2>&1` in +*reload-state*) test -r $AC_MACRODIR/autoconf.m4f && { r=--reload f=f; } ;; +*traditional*) ;; +*) echo Autoconf requires GNU m4 1.1 or later >&2; rm -f $tmpin; exit 1 ;; +esac + +$M4 -I$AC_MACRODIR $use_localdir $r autoconf.m4$f $infile > $tmpout || + { rm -f $tmpin $tmpout; exit 2; } + +# You could add your own prefixes to pattern if you wanted to check for +# them too, e.g. pattern='\(AC_\|ILT_\)', except that UNIX sed doesn't do +# alternation. +pattern="AC_" + +status=0 +if grep "^[^#]*${pattern}" $tmpout > /dev/null 2>&1; then + echo "autoconf: Undefined macros:" >&2 + sed -n "s/^[^#]*\\(${pattern}[_A-Za-z0-9]*\\).*/\\1/p" $tmpout | + while read macro; do + grep -n "^[^#]*$macro" $infile /dev/null + test $? -eq 1 && echo >&2 "***BUG in Autoconf--please report*** $macro" + done | sort -u >&2 + status=1 +fi + +if test $# -eq 0; then + exec 4> configure; chmod +x configure +else + exec 4>&1 +fi + +# Put the real line numbers into configure to make config.log more helpful. +$AWK ' +/__oline__/ { printf "%d:", NR + 1 } + { print } +' $tmpout | sed ' +/__oline__/s/^\([0-9][0-9]*\):\(.*\)__oline__/\2\1/ +' >&4 + +rm -f $tmpout + +exit $status diff --git a/autoconf/autoconf.m4 b/autoconf/autoconf.m4 new file mode 100644 index 0000000..19ca824 --- /dev/null +++ b/autoconf/autoconf.m4 @@ -0,0 +1,27 @@ +dnl Driver that loads the Autoconf macro files. +dnl Requires GNU m4. +dnl This file is part of Autoconf. +dnl Copyright (C) 1994 Free Software Foundation, Inc. +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl Written by David MacKenzie. +dnl +include(acgeneral.m4)dnl +builtin(include, acspecific.m4)dnl +dnl Do not sinclude acsite.m4 here, because it may not be installed +dnl yet when Autoconf is frozen. +dnl Do not sinclude ./aclocal.m4 here, to prevent it from being frozen. diff --git a/autoconf/config.guess b/autoconf/config.guess new file mode 100755 index 0000000..8bcd4af --- /dev/null +++ b/autoconf/config.guess @@ -0,0 +1,1050 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 93, 94, 95, 96, 97, 1998 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 . +# The master version of this file is at the FSF in /home/gd/gnu/lib. +# Please send patches to the Autoconf mailing list . +# +# Changed by Bruno Haible, 1 May 1999. +# The master version of this file is in +# ftp://ftp2.cons.org/pub/lisp/clisp/source/. +# +# 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). +# + +# Use $HOST_CC if defined. $CC may point to a cross-compiler +if test x"$CC_FOR_BUILD" = x; then + if test x"$HOST_CC" != x; then + CC_FOR_BUILD="$HOST_CC" + else + if test x"$CC" != x; then + CC_FOR_BUILD="$CC" + else + CC_FOR_BUILD=cc + fi + fi +fi + + +# 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 +# This is needed to find uname on SunOS 4.0.3. +elif (test -f /usr/5bin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/usr/5bin +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 + +dummy=dummy-$$ +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:*:*) + if test $UNAME_RELEASE = "V4.0"; then + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + fi + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + cat <$dummy.s + .globl main + .ent main +main: + .frame \$30,0,\$26,0 + .prologue 0 + .long 0x47e03d80 # implver $0 + lda \$2,259 + .long 0x47e20c21 # amask $2,$1 + srl \$1,8,\$2 + sll \$2,2,\$2 + sll \$0,3,\$0 + addl \$1,\$0,\$0 + addl \$2,\$0,\$0 + ret \$31,(\$26),1 + .end main +EOF + $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null + if test "$?" = 0 ; then + ./$dummy + case "$?" in + 7) + UNAME_MACHINE="alpha" + ;; + 15) + UNAME_MACHINE="alphaev5" + ;; + 14) + UNAME_MACHINE="alphaev56" + ;; + 10) + UNAME_MACHINE="alphapca56" + ;; + 16) + UNAME_MACHINE="alphaev6" + ;; + esac + fi + rm -f $dummy.s $dummy + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr [[A-Z]] [[a-z]]` + 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 ;; + amiga:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit 0 ;; + arc64:OpenBSD:*:*) + echo mips64el-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + hkmips:OpenBSD:*:*) + echo mips-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + pmax:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sgi:OpenBSD:*:*) + echo mips-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + wgrisc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0;; + arm32:NetBSD:*:*) + echo arm-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + exit 0 ;; + SR2?01:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit 0;; + Pyramid*:OSx*:*:*|MIS*:OSx*:*:*|MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit 0 ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit 0 ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + i86pc:SunOS:5.*:*) + echo i386-pc-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:*:*|sun:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit 0 ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit 0 ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit 0 ;; + atari*:NetBSD:*:*) + echo m68k-atari-netbsd${UNAME_RELEASE} + exit 0 ;; + atari*:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit 0 ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit 0 ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit 0 ;; + sun3*:NetBSD:*:*) + echo m68k-sun-netbsd${UNAME_RELEASE} + exit 0 ;; + sun3*:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:NetBSD:*:*) + echo m68k-apple-netbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit 0 ;; + macppc:NetBSD:*:*) + echo powerpc-apple-netbsd${UNAME_RELEASE} + exit 0 ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit 0 ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit 0 ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + sed 's/^ //' << EOF >$dummy.c + #if defined(__STDC__) || defined(__cplusplus) + int main (int argc, char *argv[]) + #else + main(argc, argv) + int argc; + char *argv[]; + #endif + { + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy \ + && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + 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=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; 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?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 + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + $CC_FOR_BUILD $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) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'` + if /usr/sbin/lsattr -EHl ${IBM_CPU_ID} | 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/[34678]??:HP-UX:*:*) + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/6?? | 9000/7?? | 9000/80[024] | 9000/8?[136790] | 9000/892 ) + sed 's/^ //' << EOF >$dummy.c + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + ($CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy` + rm -f $dummy.c $dummy + 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 + 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_FOR_BUILD $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 ;; + *9??*:MPE*:*:*) + echo hppa1.0-hp-mpeix + exit 0 ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit 0 ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit 0 ;; + i?86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + 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*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ + exit 0 ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} + exit 0 ;; + CRAY*T3E:*:*:*) + echo t3e-cray-unicosmk${UNAME_RELEASE} + exit 0 ;; + CRAY-2:*:*:*) + echo cray2-cray-unicos + exit 0 ;; + F300:UNIX_System_V:*:*) + FUJITSU_SYS=`uname -p | tr [A-Z] [a-z] | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit 0 ;; + F301:UNIX_System_V:*:*) + echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'` + exit 0 ;; + hp3[0-9][05]:NetBSD:*:*) + echo m68k-hp-netbsd${UNAME_RELEASE} + exit 0 ;; + hp300:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + i?86:BSD/386:*:* | i?86:BSD/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit 0 ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:FreeBSD:*:*) + if test -x /usr/bin/objformat; then + if test "elf" = "`/usr/bin/objformat`"; then + echo ${UNAME_MACHINE}-unknown-freebsdelf`echo ${UNAME_RELEASE}|sed -e 's/[-_].*//'` + exit 0 + fi + fi + 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 ;; + *:OpenBSD:*:*) + echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + exit 0 ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit 0 ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit 0 ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit 0 ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + *:GNU:*:*) + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit 0 ;; + *:Linux:*:*) + # uname on the ARM produces all sorts of strangeness, and we need to + # filter it out. + case "$UNAME_MACHINE" in + armv*) UNAME_MACHINE=$UNAME_MACHINE ;; + arm* | sa110*) UNAME_MACHINE="arm" ;; + esac + + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + ld_help_string=`cd /; ld --help 2>&1` + ld_supported_emulations=`echo $ld_help_string \ + | sed -ne '/supported emulations:/!d + s/[ ][ ]*/ /g + s/.*supported emulations: *// + s/ .*// + p'` + case "$ld_supported_emulations" in + i?86linux) echo "${UNAME_MACHINE}-pc-linuxaout" ; exit 0 ;; + i?86coff) echo "${UNAME_MACHINE}-pc-linuxcoff" ; exit 0 ;; + sparclinux) echo "${UNAME_MACHINE}-unknown-linuxaout" ; exit 0 ;; + armlinux) echo "${UNAME_MACHINE}-unknown-linuxaout" ; exit 0 ;; + m68klinux) echo "${UNAME_MACHINE}-unknown-linuxaout" ; exit 0 ;; + elf32ppc) echo "powerpc-unknown-linux" ; exit 0 ;; + esac + + if test "${UNAME_MACHINE}" = "alpha" ; then + sed 's/^ //' <$dummy.s + .globl main + .ent main + main: + .frame \$30,0,\$26,0 + .prologue 0 + .long 0x47e03d80 # implver $0 + lda \$2,259 + .long 0x47e20c21 # amask $2,$1 + srl \$1,8,\$2 + sll \$2,2,\$2 + sll \$0,3,\$0 + addl \$1,\$0,\$0 + addl \$2,\$0,\$0 + ret \$31,(\$26),1 + .end main +EOF + LIBC="libc6" + $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null + if test "$?" = 0 ; then + ./$dummy + case "$?" in + 7) + UNAME_MACHINE="alpha" + ;; + 15) + UNAME_MACHINE="alphaev5" + ;; + 14) + UNAME_MACHINE="alphaev56" + ;; + 10) + UNAME_MACHINE="alphapca56" + ;; + 16) + UNAME_MACHINE="alphaev6" + ;; + esac + + objdump --private-headers $dummy | \ + grep ld.so.1 > /dev/null + if test "$?" = 0 ; then + LIBC="libc5" + fi + fi + rm -f $dummy.s $dummy + echo ${UNAME_MACHINE}-unknown-linux${LIBC} ; exit 0 + elif test "${UNAME_MACHINE}" = "mips" ; then + cat >$dummy.c </dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + 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. + # If ld does not provide *any* "supported emulations:" + # that means it is gnuoldld. + echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations:" + test $? != 0 && echo "${UNAME_MACHINE}-pc-linuxoldld" && exit 0 + + case "${UNAME_MACHINE}" in + i?86) + VENDOR=pc; + ;; + *) + VENDOR=unknown; + ;; + esac + # Determine whether the default compiler is a.out or elf + cat >$dummy.c < +#if defined(__STDC__) || defined(__cplusplus) +int main (int argc, char *argv[]) +#else +main(argc, argv) + int argc; + char *argv[]; +#endif +{ +#ifdef __ELF__ +# ifdef __GLIBC__ +# if __GLIBC__ >= 2 + printf ("%s-${VENDOR}-linuxlibc6\n", argv[1]); +# else + printf ("%s-${VENDOR}-linuxlibc5\n", argv[1]); +# endif +# else + printf ("%s-${VENDOR}-linuxlibc5\n", argv[1]); +# endif +#else + printf ("%s-${VENDOR}-linuxaout\n", argv[1]); +#endif + return 0; +} +EOF + $CC_FOR_BUILD $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?86:DYNIX/ptx:4*:*) + echo i386-sequent-sysv4 + exit 0 ;; + i?86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit 0 ;; + i?86:*:4.*:* | i?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}-pc-sysv${UNAME_RELEASE} + fi + exit 0 ;; + i?86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /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}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit 0 ;; + i?86:UnixWare:*:*) + if /bin/uname -X 2>/dev/null >/dev/null ; then + (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + fi + echo ${UNAME_MACHINE}-unixware-${UNAME_RELEASE}-${UNAME_VERSION} + exit 0 ;; + pc:*:*:*) + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit 0 ;; + Intel:Mach:3*:*) + echo i386-pc-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 ;; + M68*:*:R3V[567]*:*) + test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; + 3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4.3${OS_REL} && exit 0 + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4 && exit 0 ;; + m68*:LynxOS:2.*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 ;; + i?86:LynxOS:2.*:* | i?86:LynxOS:3.[01]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit 0 ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + 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 ;; + PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit 0 ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit 0 ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit 0 ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit 0 ;; + news*:NEWS-OS:*:6*) + echo mips-sony-newsos6 + exit 0 ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R4000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit 0 ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit 0 ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit 0 ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit 0 ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit 0 ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${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 < +# include +#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 + 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`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + 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-pc-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_FOR_BUILD $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/autoconf/config.sub b/autoconf/config.sub new file mode 100755 index 0000000..33bcdba --- /dev/null +++ b/autoconf/config.sub @@ -0,0 +1,1005 @@ +#! /bin/sh +# Configuration validation subroutine script, version 1.1. +# Copyright (C) 1991, 92-97, 1998 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. + +# Changed by Bruno Haible, 1 May 1999. +# The master version of this file is in +# ftp://ftp2.cons.org/pub/lisp/clisp/source/. + +# 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 +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM-GNUSTUFF +# 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 or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + linux-gnu*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### 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 | \ + -apple) + os= + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco5) + os=sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; +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 | i860 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \ + | arme[lb] | pyramid | mn10200 | mn10300 | tron | a29k \ + | 580 | i960 | h8300 \ + | hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w \ + | alpha | alphaev[4-7] | alphaev56 | alphapca5[67] \ + | we32k | ns16k | clipper | i370 | sh | powerpc | powerpcle \ + | 1750a | dsp16xx | pdp11 | mips64 | mipsel | mips64el \ + | mips64orion | mips64orionel | mipstx39 | mipstx39el \ + | sparc | sparclet | sparclite | sparc64 | v850) + basic_machine=$basic_machine-unknown + ;; + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i[34567]86) + basic_machine=$basic_machine-pc + ;; + # 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[34567]86-* | i860-* | m32r-* | m68k-* | m68000-* \ + | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \ + | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \ + | power-* | none-* | 580-* | cray2-* | h8300-* | i960-* \ + | xmp-* | ymp-* \ + | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* \ + | alpha-* | alphaev[4-7]-* | alphaev56-* | alphapca5[67] \ + | we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \ + | clipper-* | orion-* \ + | sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \ + | sparc64-* | mips64-* | mipsel-* \ + | mips64el-* | mips64orion-* | mips64orionel-* \ + | mipstx39-* | mipstx39el-* \ + | f301-* | armv*-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + 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 + ;; + amigaos | amigados) + basic_machine=m68k-cbm + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-cbm + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + 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 + ;; + [ctj]90-cray) + basic_machine=c90-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 + ;; + 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 + ;; + 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 + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9] | hp9k4[0-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k78[0-9] | hp78[0-9] | hp9k80[24] | hp80[24] | hp9k8[67]1 | hp8[67]1 | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + basic_machine=hppa2.0-hp + ;; + hp9k7[0-9][0-9] | hp7[0-9][0-9] | hp9k8[0-9][13679] | hp8[0-9][13679] | hp9k892 | hp892) + basic_machine=hppa1.1-hp + ;; + hp9k[68][0-9][0-9] | hp[68][0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + os=-mpeix + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + os=-mpeix + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + os=-mvs + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i[34567]86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i[34567]86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i[34567]86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i[34567]86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + 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 + ;; + mipsel*-linux*) + basic_machine=mipsel-unknown + os=-linux-gnu + ;; + mips*-linux*) + basic_machine=mips-unknown + os=-linux-gnu + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netwinder) + basic_machine=armv4l-corel + os=-linux + ;; + 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 + ;; + 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 + ;; + 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 | k5 | nexen) + basic_machine=i586-pc + ;; + pentiumpro | p6 | k6 | 6x86) + basic_machine=i686-pc + ;; + pentiumii | pentium2) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | nexen-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | k6-* | 6x86-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + 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 + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + 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 + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + xmp) + basic_machine=xmp-cray + os=-unicos + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + *mint | *MiNT) + basic_machine=m68k-atari + os=-mint + ;; + 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. + mips) + if [ x$os = x-linux-gnu ]; then + basic_machine=mips-unknown + else + basic_machine=mips-mips + fi + ;; + 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 + ;; + *) + 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 + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # 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* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ + | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -rhapsody* \ + | -openstep* | -mpeix* | -oskit*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -linux*) + # To whom it may concern: + # - The name of Linux is Linux. + # - The kernel of the GNU system is the Hurd. This is stated + # in the documentation of the GNU C preprocessor, section + # "Assertions". Hence Linux is not a GNU system. + #os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -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 + ;; + -ctix* | -uts*) + os=-sysv + ;; + -ns2 ) + os=-nextstep2 + ;; + # 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*) + ;; + -xenix) + os=-xenix + ;; + -*mint | -*MiNT) + os=-mint + ;; + -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 + ;; + arm*-corel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + 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 + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-ibm) + os=-aix + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-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 + ;; + f301-fujitsu) + os=-uxpv + ;; + *-atari*) + os=-mint + ;; + *) + 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 + ;; + -aix*) + vendor=ibm + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -vxsim* | -vxworks*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -*mint | -*MiNT) + vendor=atari + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os diff --git a/autoconf/floatparam.c b/autoconf/floatparam.c new file mode 100644 index 0000000..83fcbe4 --- /dev/null +++ b/autoconf/floatparam.c @@ -0,0 +1,107 @@ +/* Determine some float parameters, much like gcc's "enquire.c". */ +/* Bruno Haible 24.8.1996 */ + +/* This program expects to be compiled by an ANSI C or C++ compiler. */ + +#include + +#if !(defined(__STDC__) || defined(__cplusplus)) +/* Only for use in function parameter lists and as function return type. */ +#define void +#endif + +typedef int boolean; +#define TRUE 1 +#define FALSE 0 + +#ifdef HAVE_LONGDOUBLE +typedef long double ldouble; +#endif + +static void header (void) +{ + printf("/* Rounding modes, for use below */\n"); + printf("#define rounds_to_nearest 0 /* 0.5 ulp */\n"); + printf("#define rounds_to_zero 1 /* 1 ulp */\n"); + printf("#define rounds_to_infinity 2 /* 1 ulp */\n"); + printf("#define rounds_to_minus_infinity 3 /* 1 ulp */\n"); + printf("\n"); +} + +#define check(type,typeprefix,typestr,equalfn,mainfn) \ +static boolean equalfn (type* x, type* y); \ +static void mainfn (void) \ +{ \ + int mant_bits; \ + int epsilon_bits = -1; \ + int negepsilon_bits = -1; \ + { type x = 1.0; type y; type z; \ + for (y = 1.0; ; y = 0.5*y) \ + { z = x + y; if (equalfn(&x,&z)) break; \ + z = z - x; if (!equalfn(&y,&z)) break; \ + epsilon_bits++; \ + } } \ + { type x = 1.0; type y; type z; \ + for (y = -1.0; ; y = 0.5*y) \ + { z = x + y; if (equalfn(&x,&z)) break; \ + z = z - x; if (!equalfn(&y,&z)) break; \ + negepsilon_bits++; \ + } } \ + printf("/* Properties of type `%s': */\n",typestr); \ + printf("/* Largest n for which 1+2^(-n) is exactly represented is %d. */\n",epsilon_bits); \ + printf("/* Largest n for which 1-2^(-n) is exactly represented is %d. */\n",negepsilon_bits); \ + if (negepsilon_bits <= epsilon_bits) \ + { printf("#error \"No exponent jump at 1.0 for type %s!\"\n",typestr); \ + mant_bits = -1; \ + } \ + else \ + { if (negepsilon_bits > epsilon_bits+1) \ + printf("/* Base for type `%s' is 2^%d\n",typestr,negepsilon_bits-epsilon_bits); \ + mant_bits = epsilon_bits+1; \ + printf("#define %s_mant_bits %d\n",typeprefix,mant_bits); \ + } \ + { int i; type x, y1, y2, ys1, ys2, z1, z2, zs1, zs2; \ + x = 1.0; for (i = 0; i < epsilon_bits; i++) { x = 0.5*x; } \ + y1 = 1.0 + 5.0*x; y2 = 1.0 + 6.0*x; \ + ys1 = 1.0 + 5.4*x; ys2 = 1.0 + 5.6*x; \ + z1 = -1.0 + (-5.0)*x; z2 = -1.0 + (-6.0)*x; \ + zs1 = -1.0 + (-5.4)*x; zs2 = -1.0 + (-5.6)*x; \ + if (equalfn(&ys1,&y1) && equalfn(&ys2,&y2) && equalfn(&zs1,&z1) && equalfn(&zs2,&z2)) \ + printf("#define %s_rounds rounds_to_nearest\n",typeprefix); \ + else if (equalfn(&ys1,&y1) && equalfn(&ys2,&y1) && equalfn(&zs1,&z1) && equalfn(&zs2,&z1)) \ + printf("#define %s_rounds rounds_to_zero\n",typeprefix); \ + else if (equalfn(&ys1,&y2) && equalfn(&ys2,&y2) && equalfn(&zs1,&z1) && equalfn(&zs2,&z1)) \ + printf("#define %s_rounds rounds_to_infinity\n",typeprefix); \ + else if (equalfn(&ys1,&y1) && equalfn(&ys2,&y1) && equalfn(&zs1,&z2) && equalfn(&zs2,&z2)) \ + printf("#define %s_rounds rounds_to_minus_infinity\n",typeprefix); \ + else \ + printf("#error \"Unknown rounding mode for type %s!\"\n",typestr); \ + } \ + printf("\n"); \ +} \ +static boolean equalfn (type* x, type* y) { return *x == *y; } \ + +check(float,"float","float",equal_float,main_float) +check(double,"double","double",equal_double,main_double) +#ifdef HAVE_LONGDOUBLE +check(ldouble,"long_double","long double",equal_ldouble,main_ldouble) +#endif + + +int main() +{ + header(); + main_float(); + main_double(); +#ifdef HAVE_LONGDOUBLE + main_ldouble(); +#endif + +#if defined(__cplusplus) + if (ferror(stdout)) return 1; + return 0; +#else + if (ferror(stdout)) { exit(1); } + exit(0); +#endif +} diff --git a/autoconf/intparam.c b/autoconf/intparam.c new file mode 100644 index 0000000..eb2ae97 --- /dev/null +++ b/autoconf/intparam.c @@ -0,0 +1,588 @@ +#line 1 "intparam.d" +/* Bestimmung einiger Maschinen-Parameter und -Abhängigkeiten */ +/* und Ausgabe in ein Include-File */ +/* Bruno Haible 10.9.1991, 12.10.1992, 6.12.1992, 24.10.1993 */ + +/* Auf einigen Systemen werden in die Typen uchar, ushort, uint, */ +/* ulong definiert. Normalerweise reicht _POSIX_SOURCE aus, dies zu verhindern, */ +/* bei AIX 3.2.5 (rs6000-ibm-aix3.2.5) jedoch nicht. Wir müssen Gewalt anwenden. */ +#define _POSIX_SOURCE +#define uchar os_uchar +#define ushort os_ushort +#define uint os_uint +#define ulong os_ulong +#include +#undef ulong +#undef uint +#undef ushort +#undef uchar + +#if !(defined(__STDC__) || defined(__cplusplus)) +/* Only for use in function parameter lists and as function return type. */ +#define void +#endif + +#define loop while(1) + +typedef int boolean; +#define TRUE 1 +#define FALSE 0 + +#ifdef __CHAR_UNSIGNED__ +typedef signed char schar; +#else +typedef char schar; +#endif +typedef unsigned char uchar; +typedef unsigned short ushort; +typedef unsigned /* int */ uint; +typedef unsigned long ulong; +#ifdef HAVE_LONGLONG +typedef long long longlong; +typedef unsigned long long ulonglong; +#endif +typedef int (function)(); + +static int random_table[256] = /* 2048 zufällige Bits, hier von pi */ + { 0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,0xC4,0xC6,0x62,0x8B, + 0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74, + 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79, + 0x8E,0x34,0x04,0xDD,0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B, + 0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,0x4F,0xE1,0x35,0x6D, + 0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6, + 0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6, + 0xF4,0x06,0xB7,0xED,0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5, + 0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,0x49,0x28,0x66,0x51, + 0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05, + 0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8, + 0xFD,0x24,0xCF,0x5F,0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96, + 0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,0x9E,0xD5,0x29,0x07, + 0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04, + 0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46, + 0x2E,0x36,0xCE,0x3B,0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03, + 0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F,0xB5,0xC5,0x5D,0xF0, + 0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18, + 0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18, + 0x98,0xFA,0x05,0x10,0x15,0x72,0x8E,0x5A,0x8A,0xAA,0xC4,0x2D, + 0xAD,0x33,0x17,0x0D,0x04,0x50,0x7A,0x33,0xA8,0x55,0x21,0xAB, + 0xDF,0x1C,0xBA,0x65, + }; +#define random_table_length (8*256) +static int random_position = -1; +int next_random_bit(void) + { random_position++; + if (random_position==random_table_length) random_position = 0; + return (random_table[random_position/8] >> (random_position % 8)) & 1; + } + +#if defined(__STDC__) || defined(__cplusplus) +void printf_underscored (const char* string) +#else +void printf_underscored(string) + char* string; +#endif + { char c; + while (!((c = *string++) == '\0')) { printf("%c",(c==' ' ? '_' : c)); } + } + +/* string_length(string) is the same as strlen(string). */ +/* Better avoid to depend on . */ +#if defined(__STDC__) || defined(__cplusplus) +int string_length (char* string) +#else +int string_length(string) + char* string; +#endif + { int count = 0; + while (!(*string++ == '\0')) { count++; } + return count; + } + +static int char_bitsize, short_bitsize, int_bitsize, long_bitsize; +static int uchar_bitsize, ushort_bitsize, uint_bitsize, ulong_bitsize; +static boolean char_uchar_same, short_ushort_same, int_uint_same, long_ulong_same; +static int pointer_bitsize; +#ifdef HAVE_LONGLONG +static int longlong_bitsize, ulonglong_bitsize; +static boolean longlong_ulonglong_same; +#endif + +void main1(void) { +#define get_integer_bitsize(type,where) \ + { type x = 1; \ + int bits = 0; \ + loop \ + { if (x==0) break; \ + x = x+x; \ + bits++; \ + if (bits==1000) { bits = -1; break; } \ + } \ + where = bits; \ + } +#define print_integer_bitsize(type,typestr,where) \ + { if (where >= 0) \ + { printf("/* Integers of t%spe %s have %ld bits. */\n","y",typestr,(long)where); \ + if (!(typestr[0] == 'u')) \ + { printf("#define "); printf_underscored(typestr); printf("_bitsize %ld\n",(long)where); } \ + printf("\n"); \ + } \ + else \ + { printf("#error \"Integers of t%spe %s have no binary representation!!\"\n","y",typestr); } \ + if (!(where == char_bitsize * sizeof(type))) \ + { printf("#error \"Formula BITSIZE(T) = SIZEOF(T) * BITSPERBYTE does not hold for t%spe %s!!\"\n","y",typestr); } \ + } + get_integer_bitsize(schar,char_bitsize); + get_integer_bitsize(short,short_bitsize); + get_integer_bitsize(int,int_bitsize); + get_integer_bitsize(long,long_bitsize); + print_integer_bitsize(schar,"char",char_bitsize); + print_integer_bitsize(short,"short",short_bitsize); + print_integer_bitsize(int,"int",int_bitsize); + print_integer_bitsize(long,"long",long_bitsize); +#ifdef HAVE_LONGLONG + get_integer_bitsize(longlong,longlong_bitsize); + print_integer_bitsize(longlong,"long long",longlong_bitsize); +#endif + get_integer_bitsize(uchar,uchar_bitsize); + get_integer_bitsize(ushort,ushort_bitsize); + get_integer_bitsize(uint,uint_bitsize); + get_integer_bitsize(ulong,ulong_bitsize); + print_integer_bitsize(uchar,"unsigned char",uchar_bitsize); + print_integer_bitsize(ushort,"unsigned short",ushort_bitsize); + print_integer_bitsize(uint,"unsigned int",uint_bitsize); + print_integer_bitsize(ulong,"unsigned long",ulong_bitsize); +#ifdef HAVE_LONGLONG + get_integer_bitsize(ulonglong,ulonglong_bitsize); + print_integer_bitsize(ulonglong,"unsigned long long",ulonglong_bitsize); +#endif +} + +void main2(void) { +#define compare_integer_bitsizes(typestr1,typestr2,type1_bitsize,type2_bitsize) \ + { if (!(type1_bitsize==type2_bitsize)) \ + printf("#error \"Integer types %s and %s have different sizes!!\"\n",typestr1,typestr2); \ + } + compare_integer_bitsizes("char","unsigned char",char_bitsize,uchar_bitsize); + compare_integer_bitsizes("short","unsigned short",short_bitsize,ushort_bitsize); + compare_integer_bitsizes("int","unsigned int",int_bitsize,uint_bitsize); + compare_integer_bitsizes("long","unsigned long",long_bitsize,ulong_bitsize); +#ifdef HAVE_LONGLONG + compare_integer_bitsizes("long long","unsigned long long",longlong_bitsize,ulonglong_bitsize); +#endif +} + +#define get_a_random(type,bitsize,where) \ + { type x = 0; \ + int i = bitsize; \ + while (i>0) { x = (x<<1) + next_random_bit(); i--; } \ + where = x; \ + } +#define get_a_random_twice(type1,type2,bitsize,where1,where2) \ + { type1 x1 = 0; type2 x2 = 0; \ + int i = bitsize; \ + while (i>0) \ + { type1 b = next_random_bit(); \ + x1 = ((x1<<1) + b); x2 = ((x2<<1) + b); \ + i--; \ + } \ + where1 = x1; where2 = x2; \ + } + +void main3(void) { +#define compare_integer_representation(type1,type2,typestr1,typestr2,type1_bitsize,type2_bitsize,where) \ + { if ((type1_bitsize>=0) && (type2_bitsize>=0) && (type1_bitsize==type2_bitsize)) \ + { int i,j; \ + type1 sample1; type2 sample2; \ + where = TRUE; \ + for (i = 0; i<100; i++) \ + { get_a_random_twice(type1,type2,type1_bitsize,sample1,sample2); \ + if (!(sample1 == (type1)(sample2))) { where = FALSE; } \ + if (!(sample2 == (type2)(sample1))) { where = FALSE; } \ + } \ + for (i = 0; i<100; i++) \ + { get_a_random(type1,type1_bitsize,sample1); \ + sample2 = (type2)(sample1); \ + for (j = 0; j < type1_bitsize; j++) \ + if (!( ((sample1 & ((type1)1<= 0) \ + { int i,j,shc; \ + type sample1,sample2; \ + boolean left_works = TRUE, right_works = TRUE; \ + for (i = 0; i<100; i++) \ + { get_a_random(type,type_bitsize,sample1); \ + for (shc = 0; shc < type_bitsize; shc++) \ + { sample2 = sample1 << shc; \ + for (j=0; j < type_bitsize; j++) \ + { if (!( ((sample2 & ((type)1<> shc; \ + for (j=0; j < type_bitsize; j++) \ + { if (!( ((sample2 & ((type)1<= type_bitsize-shc ? TRUE : ((sample1 & ((type)1<<(j+shc))) == 0)) \ + ) ) \ + { right_works = FALSE; } \ + } } } \ + if (!left_works) \ + { printf("#error \"Left shift of integers of t%spe %s does not work!!\"\n","y",typestr); } \ + if (!right_works) \ + { printf("#error \"Right shift of integers of t%spe %s does not work!!\"\n","y",typestr); } \ + } +#define test_integer_sshift(type,typestr,type_bitsize) \ + if (type_bitsize >= 0) \ + { int i,j,shc; \ + type sample1,sample2; \ + boolean left_works = TRUE, right_works = TRUE; \ + for (i = 0; i<100; i++) \ + { get_a_random(type,type_bitsize,sample1); \ + for (shc = 0; shc < type_bitsize; shc++) \ + { sample2 = sample1 << shc; \ + for (j=0; j < type_bitsize; j++) \ + { if (!( ((sample2 & ((type)1<> shc; \ + for (j=0; j < type_bitsize; j++) \ + { if (!( ((sample2 & ((type)1<=type_bitsize ? type_bitsize-1 : j+shc))) == 0) \ + ) ) \ + { right_works = FALSE; } \ + } } } \ + if (!left_works) \ + { printf("#error \"Left shift of integers of t%spe %s does not work!!\"\n","y",typestr); } \ + if (!right_works) \ + { printf("#error \"Right shift of integers of t%spe %s does not work!!\"\n","y",typestr); } \ + } + test_integer_ushift(uchar,"unsigned char",uchar_bitsize); + test_integer_ushift(ushort,"unsigned short",ushort_bitsize); + test_integer_ushift(uint,"unsigned int",uint_bitsize); + test_integer_ushift(ulong,"unsigned long",ulong_bitsize); +#ifdef HAVE_LONGLONG + test_integer_ushift(ulonglong,"unsigned long long",ulonglong_bitsize); +#endif + test_integer_sshift(schar,"char",char_bitsize); + test_integer_sshift(short,"short",short_bitsize); + test_integer_sshift(int,"int",int_bitsize); + test_integer_sshift(long,"long",long_bitsize); +#ifdef HAVE_LONGLONG + test_integer_sshift(longlong,"long long",longlong_bitsize); +#endif +} + +void main5(void) { +#define test_integer_casts(type1,type2,typestr1,typestr2,type1_bitsize,type2_bitsize,want) \ + if (type1_bitsize <= type2_bitsize) \ + { int i,j; \ + boolean modifies = FALSE; \ + boolean zero_extends = TRUE; \ + boolean sign_extends = TRUE; \ + for (i = 0; i<100; i++) \ + { type1 sample1; \ + type2 sample2; \ + get_a_random(type1,type1_bitsize,sample1); \ + sample2 = (type2)sample1; \ + if (!(sample1 == (type1)sample2)) { modifies = TRUE; } \ + for (j = 0; jdummy2) +#define get_alignment(type,typestr) \ + { struct { char dummy1; type dummy2; } dummy; \ + long alignment = (char*)&dummy.dummy2 - (char*)&dummy; \ + printf("/* Type %s has sizeof = %ld and alignment = %ld. */\n",typestr,(long)sizeof(type),alignment); \ + if (!(typestr[0] == 'u') && !(typestr[string_length(typestr)-1] == '*')) \ + { printf("#define sizeof_"); printf_underscored(typestr); printf(" %ld\n",(long)sizeof(type)); \ + printf("#define alignment_"); printf_underscored(typestr); printf(" %ld\n",alignment); \ + } \ + if (!((alignment & (alignment-1)) == 0)) \ + printf("#error \"The alignment %ld of t%spe %s is not a power of two!!\"\n",alignment,"y",typestr); \ + printf("\n"); \ + } + get_alignment(char,"char"); get_alignment(uchar,"unsigned char"); + get_alignment(short,"short"); get_alignment(ushort,"unsigned short"); + get_alignment(int,"int"); get_alignment(uint,"unsigned int"); + get_alignment(long,"long"); get_alignment(ulong,"unsigned long"); +#ifdef HAVE_LONGLONG + get_alignment(longlong,"long long"); get_alignment(ulonglong,"unsigned long long"); +#endif + get_alignment(float,"float"); + get_alignment(double,"double"); + get_alignment(char*,"char *"); + get_alignment(long*,"long *"); + get_alignment(function*,"function *"); +} + +void main9(void) { +#define get_endian(type,typestr,type_bitsize) \ + { if (type_bitsize == uchar_bitsize * sizeof(type)) \ + { auto union { uchar einzeln[sizeof(type)]; type gesamt; } x; \ + int i,j; \ + boolean big_endian = TRUE; \ + boolean little_endian = TRUE; \ + for (i = 0; i<100; i++) \ + { type sample; \ + get_a_random(type,type_bitsize,sample); \ + x.gesamt = sample; \ + for (j = 0; j>= uchar_bitsize) \ + { if (!( (sample & (((type)1< 0) + { printf("/* Stack grows up, ca. %ld bytes per function call. */\n",(long)stack_direction); + printf("#define stack_grows_up\n"); + } + else if (stack_direction < 0) + { printf("/* Stack grows down, ca. %ld bytes per function call. */\n",-(long)stack_direction); + printf("#define stack_grows_down\n"); + } + else + printf("#error \"Unknown stack model -- incorrect C semantics!!\"\n"); + } + +int main() +{ main1(); + main2(); + main3(); + main4(); + main5(); + main6(); + main7(); + main8(); + main9(); + main10(); +#if defined(__cplusplus) + if (ferror(stdout)) return 1; + return 0; +#else + if (ferror(stdout)) { exit(1); } + exit(0); +#endif +} diff --git a/autoconf/ltconfig b/autoconf/ltconfig new file mode 100755 index 0000000..ee8fc55 --- /dev/null +++ b/autoconf/ltconfig @@ -0,0 +1,1513 @@ +#! /bin/sh + +# ltconfig - Create a system-specific libtool. +# Copyright (C) 1996-1998 Free Software Foundation, Inc. +# Gordon Matzigkeit , 1996 +# +# 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. + +# A lot of this script is taken from autoconf-2.10. + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "${CDPATH+set}" = set; then CDPATH=; export CDPATH; fi + +echo=echo +if test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then : +else + # The Solaris and AIX default echo program unquotes backslashes. + # This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # So, we emulate echo with printf '%s\n' + echo="printf %s\\n" + if test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then : + else + # Oops. We have no working printf. Try to find a not-so-buggy echo. + echo=echo + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:" + for dir in $PATH /usr/ucb; do + if test -f $dir/echo && test "X`$dir/echo '\t'`" = 'X\t'; then + echo="$dir/echo" + break + fi + done + IFS="$save_ifs" + fi +fi + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e s/^X//' +sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g' + +# The name of this program. +progname=`$echo "X$0" | $Xsed -e 's%^.*/%%'` + +# Constants: +PROGRAM=ltconfig +PACKAGE=libtool +VERSION=1.2 +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.c 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.c $LIBS 1>&5' +rm="rm -f" + +help="Try \`$progname --help' for more information." + +# Global variables: +can_build_shared=yes +enable_shared=yes +# All known linkers require a `.a' archive for static linking. +enable_static=yes +ltmain= +silent= +srcdir= +ac_config_guess= +ac_config_sub= +host= +nonopt= +verify_host=yes +with_gcc=no +with_gnu_ld=no + +old_AR="$AR" +old_CC="$CC" +old_CFLAGS="$CFLAGS" +old_CPPFLAGS="$CPPFLAGS" +old_LD="$LD" +old_LN_S="$LN_S" +old_NM="$NM" +old_RANLIB="$RANLIB" + +# Parse the command line options. +args= +prev= +for option +do + case "$option" in + -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + eval "$prev=\$option" + prev= + continue + fi + + case "$option" in + --help) cat <&2 + echo "$help" 1>&2 + exit 1 + ;; + + *) + if test -z "$ltmain"; then + ltmain="$option" + elif test -z "$host"; then +# This generates an unnecessary warning for sparc-sun-solaris4.1.3_U1 +# if test -n "`echo $option| sed 's/[-a-z0-9.]//g'`"; then +# echo "$progname: warning \`$option' is not a valid host type" 1>&2 +# fi + host="$option" + else + echo "$progname: too many arguments" 1>&2 + echo "$help" 1>&2 + exit 1 + fi ;; + esac +done + +if test -z "$ltmain"; then + echo "$progname: you must specify a LTMAIN file" 1>&2 + echo "$help" 1>&2 + exit 1 +fi + +if test -f "$ltmain"; then : +else + echo "$progname: \`$ltmain' does not exist" 1>&2 + echo "$help" 1>&2 + exit 1 +fi + +# Quote any args containing shell metacharacters. +ltconfig_args= +for arg +do + case "$arg" in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ltconfig_args="$ltconfig_args '$arg'" ;; + *) ltconfig_args="$ltconfig_args $arg" ;; + esac +done + +# A relevant subset of AC_INIT. + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 5 compiler messages saved in config.log +# 6 checking for... messages and results +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>>./config.log + +# NLS nuisances. +# Only set LANG and LC_ALL to C if already set. +# These must not be set unconditionally because not all systems understand +# e.g. LANG=C (notably SCO). +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LANG+set}" = set; then LANG=C; export LANG; fi + +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + +if test -z "$srcdir"; then + # Assume the source directory is the same one as the path to ltmain.sh. + srcdir=`$echo "$ltmain" | $Xsed -e 's%/[^/]*$%%'` + test "$srcdir" = "$ltmain" && srcdir=. +fi + +trap "$rm conftest*; exit 1" 1 2 15 +if test "$verify_host" = yes; then + # Check for config.guess and config.sub. + ac_aux_dir= + for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/config.guess; then + ac_aux_dir=$ac_dir + break + fi + done + if test -z "$ac_aux_dir"; then + echo "$progname: cannot find config.guess in $srcdir $srcdir/.. $srcdir/../.." 1>&2 + echo "$help" 1>&2 + exit 1 + fi + ac_config_guess=$ac_aux_dir/config.guess + ac_config_sub=$ac_aux_dir/config.sub + + # Make sure we can run config.sub. + if $ac_config_sub sun4 >/dev/null 2>&1; then : + else + echo "$progname: cannot run $ac_config_sub" 1>&2 + echo "$help" 1>&2 + exit 1 + fi + + echo $ac_n "checking host system type""... $ac_c" 1>&6 + + host_alias=$host + case "$host_alias" in + "") + if host_alias=`$ac_config_guess`; then : + else + echo "$progname: cannot guess host type; you must specify one" 1>&2 + echo "$help" 1>&2 + exit 1 + fi ;; + esac + host=`$ac_config_sub $host_alias` + echo "$ac_t$host" 1>&6 + + # Make sure the host verified. + test -z "$host" && exit 1 + +elif test -z "$host"; then + echo "$progname: you must specify a host type if you use \`--no-verify'" 1>&2 + echo "$help" 1>&2 + exit 1 +else + host_alias=$host +fi + +# Transform linux* to *-*-linux-gnu*, to support old configure scripts. +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +case "$host_os" in +linux-gnu*) ;; +linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'` +esac + +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + +case "$host_os" in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "${COLLECT_NAMES+set}" != set; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR cru $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +# Set a sane default for `AR'. +test -z "$AR" && AR=ar + +# If RANLIB is not set, then run the test. +if test "${RANLIB+set}" != "set"; then + result=no + + echo $ac_n "checking for ranlib... $ac_c" 1>&6 + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:" + for dir in $PATH; do + test -z "$dir" && dir=. + if test -f $dir/ranlib; then + RANLIB="ranlib" + result="ranlib" + break + fi + done + IFS="$save_ifs" + + echo "$ac_t$result" 1>&6 +fi + +if test -n "$RANLIB"; then + old_archive_cmds="$old_archive_cmds;\$RANLIB \$oldlib" + old_postinstall_cmds="\$RANLIB \$oldlib;$old_postinstall_cmds" +fi + +# Check to see if we are using GCC. +if test "$with_gcc" != yes || test -z "$CC"; then + # If CC is not set, then try to find GCC or a usable CC. + if test -z "$CC"; then + echo $ac_n "checking for gcc... $ac_c" 1>&6 + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:" + for dir in $PATH; do + IFS="$save_ifs" + test -z "$dir" && dir=. + if test -f $dir/gcc; then + CC="gcc" + break + fi + done + IFS="$save_ifs" + + if test -n "$CC"; then + echo "$ac_t$CC" 1>&6 + else + echo "$ac_t"no 1>&6 + fi + fi + + # Not "gcc", so try "cc", rejecting "/usr/ucb/cc". + if test -z "$CC"; then + echo $ac_n "checking for cc... $ac_c" 1>&6 + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:" + cc_rejected=no + for dir in $PATH; do + test -z "$dir" && dir=. + if test -f $dir/cc; then + if test "$dir/cc" = "/usr/ucb/cc"; then + cc_rejected=yes + continue + fi + CC="cc" + break + fi + done + IFS="$save_ifs" + if test $cc_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same name, so the bogon will be chosen + # first if we set CC to just the name; use the full file name. + shift + set dummy "$dir/cc" "$@" + shift + CC="$@" + fi + fi + + if test -n "$CC"; then + echo "$ac_t$CC" 1>&6 + else + echo "$ac_t"no 1>&6 + fi + + if test -z "$CC"; then + echo "$progname: error: no acceptable cc found in \$PATH" 1>&2 + exit 1 + fi + fi + + # Now see if the compiler is really GCC. + with_gcc=no + echo $ac_n "checking whether we are using GNU C... $ac_c" 1>&6 + echo "$progname:424: checking whether we are using GNU C" >&5 + + $rm conftest.c + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + with_gcc=yes + fi + $rm conftest.c + echo "$ac_t$with_gcc" 1>&6 +fi + +# Allow CC to be a program name with arguments. +set dummy $CC +compiler="$2" + +echo $ac_n "checking for $compiler option to produce PIC... $ac_c" 1>&6 +pic_flag= +special_shlib_compile_flags= +wl= +link_static_flag= +no_builtin_flag= + +if test "$with_gcc" = yes; then + wl='-Wl,' + link_static_flag='-static' + no_builtin_flag=' -fno-builtin' + + case "$host_os" in + aix3* | aix4* | irix5* | irix6* | osf3* | osf4*) + # PIC is the default for these OSes. + ;; + os2*) + # We can build DLLs from non-PIC. + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + pic_flag='-m68020 -resident32 -malways-restore-a4' + ;; + *) + pic_flag='-fPIC' + ;; + esac +else + # PORTME Check for PIC flags for the system compiler. + case "$host_os" in + aix3* | aix4*) + # All AIX code is PIC. + link_static_flag='-bnso -bI:/lib/syscalls.exp' + ;; + + hpux9* | hpux10*) + # Is there a better link_static_flag that works with the bundled CC? + wl='-Wl,' + link_static_flag="${wl}-a ${wl}archive" + pic_flag='+Z' + ;; + + irix5* | irix6*) + wl='-Wl,' + link_static_flag='-non_shared' + # PIC (with -KPIC) is the default. + ;; + + os2*) + # We can build DLLs from non-PIC. + ;; + + osf3* | osf4*) + # All OSF/1 code is PIC. + wl='-Wl,' + link_static_flag='-non_shared' + ;; + + sco3.2v5*) + pic_flag='-Kpic' + link_static_flag='-dn' + special_shlib_compile_flags='-belf' + ;; + + solaris2*) + pic_flag='-KPIC' + link_static_flag='-Bstatic' + wl='-Wl,' + ;; + + sunos4*) + pic_flag='-PIC' + link_static_flag='-Bstatic' + wl='-Qoption ld ' + ;; + + sysv4.2uw2*) + pic_flag='-KPIC' + link_static_flag='-Bstatic' + wl='-Wl,' + ;; + + uts4*) + pic_flag='-pic' + link_static_flag='-Bstatic' + ;; + + *) + can_build_shared=no + ;; + esac +fi + +if test -n "$pic_flag"; then + echo "$ac_t$pic_flag" 1>&6 + + # Check to make sure the pic_flag actually works. + echo $ac_n "checking if $compiler PIC flag $pic_flag works... $ac_c" 1>&6 + $rm conftest* + echo 'int x;' > conftest.c + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $pic_flag -DPIC" + echo "$progname:547: checking if $compiler PIC flag $pic_flag works" >&5 + if { (eval echo $progname:548: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.o; then + # Append any warnings to the config.log. + cat conftest.err 1>&5 + + # On HP-UX, both CC and GCC only warn that PIC is supported... then they + # create non-PIC objects. So, if there were any warnings, we assume that + # PIC is not supported. + if test -s conftest.err; then + echo "$ac_t"no 1>&6 + can_build_shared=no + pic_flag= + else + echo "$ac_t"yes 1>&6 + pic_flag=" $pic_flag" + fi + else + # Append any errors to the config.log. + cat conftest.err 1>&5 + can_build_shared=no + pic_flag= + echo "$ac_t"no 1>&6 + fi + CFLAGS="$save_CFLAGS" + $rm conftest* +else + echo "$ac_t"none 1>&6 +fi + +# Check for any special shared library compilation flags. +if test -n "$special_shlib_compile_flags"; then + echo "$progname: warning: \`$CC' requires \`$special_shlib_compile_flags' to build shared libraries" 1>&2 + if echo "$old_CC $old_CFLAGS " | egrep -e "[ ]$special_shlib_compile_flags[ ]" >/dev/null; then : + else + echo "$progname: add \`$special_shlib_compile_flags' to the CC or CFLAGS env variable and reconfigure" 1>&2 + can_build_shared=no + fi +fi + +echo $ac_n "checking if $compiler static flag $link_static_flag works... $ac_c" 1>&6 +$rm conftest* +echo 'main(){return(0);}' > conftest.c +save_LDFLAGS="$LDFLAGS" +LDFLAGS="$LDFLAGS $link_static_flag" +echo "$progname:591: checking if $compiler static flag $link_static_flag works" >&5 +if { (eval echo $progname:592: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + echo "$ac_t$link_static_flag" 1>&6 +else + echo "$ac_t"none 1>&6 + link_static_flag= +fi +LDFLAGS="$save_LDFLAGS" +$rm conftest* + +if test -z "$LN_S"; then + # Check to see if we can use ln -s, or we need hard links. + echo $ac_n "checking whether ln -s works... $ac_c" 1>&6 + $rm conftestdata + if ln -s X conftestdata 2>/dev/null; then + $rm conftestdata + LN_S="ln -s" + else + LN_S=ln + fi + if test "$LN_S" = "ln -s"; then + echo "$ac_t"yes 1>&6 + else + echo "$ac_t"no 1>&6 + fi +fi + +# Make sure LD is an absolute path. +if test -z "$LD"; then + ac_prog=ld + if test "$with_gcc" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + echo $ac_n "checking for ld used by GCC... $ac_c" 1>&6 + echo "$progname:624: checking for ld used by GCC" >&5 + ac_prog=`($CC -print-prog-name=ld) 2>&5` + case "$ac_prog" in + # Accept absolute paths. + /* | [A-Za-z]:\\*) + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we are not using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac + elif test "$with_gnu_ld" = yes; then + echo $ac_n "checking for GNU ld... $ac_c" 1>&6 + echo "$progname:642: checking for GNU ld" >&5 + else + echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6 + echo "$progname:645: checking for non-GNU ld" >&5 + fi + + if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog"; then + LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + if "$LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then + test "$with_gnu_ld" != no && break + else + test "$with_gnu_ld" != yes && break + fi + fi + done + IFS="$ac_save_ifs" + fi + + if test -n "$LD"; then + echo "$ac_t$LD" 1>&6 + else + echo "$ac_t"no 1>&6 + fi + + if test -z "$LD"; then + echo "$progname: error: no acceptable ld found in \$PATH" 1>&2 + exit 1 + fi +fi + +# Check to see if it really is or is not GNU ld. +echo $ac_n "checking if the linker ($LD) is GNU ld... $ac_c" 1>&6 +# I'd rather use --version here, but apparently some GNU ld's only accept -v. +if $LD -v 2>&1 &5; then + with_gnu_ld=yes +else + with_gnu_ld=no +fi +echo "$ac_t$with_gnu_ld" 1>&6 + +# See if the linker supports building shared libraries. +echo $ac_n "checking whether the linker ($LD) supports shared libraries... $ac_c" 1>&6 + +allow_undefined_flag= +no_undefined_flag= +archive_cmds= +old_archive_from_new_cmds= +export_dynamic_flag_spec= +hardcode_libdir_flag_spec= +hardcode_libdir_separator= +hardcode_direct=no +hardcode_minus_L=no +hardcode_shlibpath_var=unsupported +runpath_var= + +case "$host_os" in +amigaos* | sunos4*) + # On these operating systems, we should treat GNU ld like the system ld. + gnu_ld_acts_native=yes + ;; +*) + gnu_ld_acts_native=no + ;; +esac + +ld_shlibs=yes +if test "$with_gnu_ld" = yes && test "$gnu_ld_acts_native" != yes; then + + # See if GNU ld supports shared libraries. + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared ${wl}-soname $wl$soname -o $lib$libobjs' + runpath_var=LD_RUN_PATH + ld_shlibs=yes + else + ld_shlibs=no + fi + + if test "$ld_shlibs" = yes; then + hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec='${wl}--export-dynamic' + fi +else + # PORTME fill in a description of your system's linker (not GNU ld) + case "$host_os" in + aix3*) + allow_undefined_flag=unsupported + archive_cmds='$NM$libobjs | $global_symbol_pipe | sed '\''s/.* //'\'' > $lib.exp;$LD -o $objdir/$soname$libobjs -bE:$lib.exp -T512 -H512 -bM:SRE;$AR cru $lib $objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$with_gcc" = yes && test -z "$link_static_flag"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix4*) + allow_undefined_flag=unsupported + archive_cmds='$NM$libobjs | $global_symbol_pipe | sed '\''s/.* //'\'' > $lib.exp;$CC -o $objdir/$soname$libobjs ${wl}-bE:$lib.exp ${wl}-bM:SRE ${wl}-bnoentry;$AR cru $lib $objdir/$soname' + hardcode_direct=yes + hardcode_minus_L=yes + ;; + + amigaos*) + archive_cmds='$rm $objdir/a2ixlibrary.data;$echo "#define NAME $libname" > $objdir/a2ixlibrary.data;$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data;$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data;$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data;$AR cru $lib$libobjs;$RANLIB $lib;(cd $objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib$libobjs /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds='$LD -Bshareable -o $lib$libobjs' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3, at last, uses gcc -shared to do shared libraries. + freebsd3 | freebsdelf3*) + archive_cmds='$CC -shared -o $lib$libobjs' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + archive_cmds='$rm $objdir/$soname;$LD -b +s +b $install_libdir -o $objdir/$soname$libobjs;mv $objdir/$soname $lib' + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + export_dynamic_flag_spec='${wl}-E' + ;; + + hpux10*) + archive_cmds='$LD -b +h $soname +s +b $install_libdir -o $lib$libobjs' + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + export_dynamic_flag_spec='${wl}-E' + ;; + + irix5* | irix6*) + archive_cmds='$LD -shared -o $lib -soname $soname -set_version $verstring$libobjs' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + ;; + + netbsd*) + # Tested with NetBSD 1.2 ld + archive_cmds='$LD -Bshareable -o $lib$libobjs' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + openbsd*) + archive_cmds='$LD -Bshareable -o $lib$libobjs' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $objdir/$libname.def;$echo "DESCRIPTION \"$libname\"" >> $objdir/$libname.def;$echo DATA >> $objdir/$libname.def;$echo " SINGLE NONSHARED" >> $objdir/$libname.def;$echo EXPORTS >> $objdir/$libname.def;emxexp$libobjs >> $objdir/$libname.def;$CC -Zdll -Zcrtdll -o $lib$libobjs $objdir/$libname.def' + old_archive_from_new_cmds='emximp -o $objdir/$libname.a $objdir/$libname.def' + ;; + + osf3* | osf4*) + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$LD -shared${allow_undefined_flag} -o $lib -soname $soname -set_version $verstring$libobjs$deplibs' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + sco3.2v5*) + archive_cmds='$LD -G -o $lib$libobjs' + hardcode_direct=yes + ;; + + solaris2*) + no_undefined_flag=' -z text' + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib$libobjs' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + + # Solaris 2 before 2.5 hardcodes -L paths. + case "$host_os" in + solaris2.[0-4]*) + hardcode_minus_L=yes + ;; + esac + ;; + + sunos4*) + if test "$with_gcc" = yes; then + archive_cmds='$CC -shared -o $lib$libobjs' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib$libobjs' + fi + + if test "$with_gnu_ld" = yes; then + export_dynamic_flag_spec='${wl}-export-dynamic' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib$libobjs' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=no + hardcode_minus_L=no + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + can_build_shared=no + ;; + esac +fi +echo "$ac_t$ld_shlibs" 1>&6 + +if test -z "$NM"; then + echo $ac_n "checking for BSD-compatible nm... $ac_c" 1>&6 + case "$NM" in + /* | [A-Za-z]:\\*) ;; # Let the user override the test with a path. + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in /usr/ucb /usr/ccs/bin $PATH /bin; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/nm; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + NM="$ac_dir/nm -B" + elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + NM="$ac_dir/nm -p" + else + NM="$ac_dir/nm" + fi + break + fi + done + IFS="$ac_save_ifs" + test -z "$NM" && NM=nm + ;; + esac + echo "$ac_t$NM" 1>&6 +fi + +# Check for command to grab the raw symbol name followed by C symbol from nm. +echo $ac_n "checking command to parse $NM output... $ac_c" 1>&6 + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRSTU]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Transform the above into a raw symbol and a C symbol. +symxfrm='\1 \1' + +# Define system-specific variables. +case "$host_os" in +aix*) + symcode='[BCDTU]' + ;; +irix*) + # Cannot use undefined symbols on IRIX because inlined functions mess us up. + symcode='[BCDEGRST]' + ;; +solaris2*) + symcode='[BDTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then + symcode='[ABCDGISTUW]' +fi + +# Write the raw and C identifiers. +global_symbol_pipe="sed -n -e 's/^.* $symcode $sympat$/$symxfrm/p'" + +# Check to see that the pipe works correctly. +pipe_works=no +$rm conftest* +cat > conftest.c <&5 +if { (eval echo $progname:972: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.o; then + # Now try to grab the symbols. + nlist=conftest.nm + if { echo "$progname:975: eval \"$NM conftest.o | $global_symbol_pipe > $nlist\"" >&5; eval "$NM conftest.o | $global_symbol_pipe > $nlist 2>&5"; } && test -s "$nlist"; then + + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + wcout=`wc "$nlist" 2>/dev/null` + count=`$echo "X$wcout" | $Xsed -e 's/^[ ]*\([0-9][0-9]*\).*$/\1/'` + (test "$count" -ge 0) 2>/dev/null || count=-1 + else + rm -f "$nlist"T + count=-1 + fi + + # Make sure that we snagged all the symbols we need. + if egrep ' nm_test_var$' "$nlist" >/dev/null; then + if egrep ' nm_test_func$' "$nlist" >/dev/null; then + cat < conftest.c +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + sed 's/^.* \(.*\)$/extern char \1;/' < "$nlist" >> conftest.c + + cat <> conftest.c +#if defined (__STDC__) && __STDC__ +# define __ptr_t void * +#else +# define __ptr_t char * +#endif + +/* The number of symbols in dld_preloaded_symbols, -1 if unsorted. */ +int dld_preloaded_symbol_count = $count; + +/* The mapping between symbol names and symbols. */ +struct { + char *name; + __ptr_t address; +} +dld_preloaded_symbols[] = +{ +EOF + sed 's/^\(.*\) \(.*\)$/ {"\1", (__ptr_t) \&\2},/' < "$nlist" >> conftest.c + cat <<\EOF >> conftest.c + {0, (__ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.o conftestm.o + save_LIBS="$LIBS" + save_CFLAGS="$CFLAGS" + LIBS='conftestm.o' + CFLAGS="$CFLAGS$no_builtin_flag" + if { (eval echo $progname:1033: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + pipe_works=yes + else + echo "$progname: failed program was:" >&5 + cat conftest.c >&5 + fi + LIBS="$save_LIBS" + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $global_symbol_pipe" >&5 + fi +else + echo "$progname: failed program was:" >&5 + cat conftest.c >&5 +fi +$rm conftest* + +# Do not use the global_symbol_pipe unless it works. +echo "$ac_t$pipe_works" 1>&6 +test "$pipe_works" = yes || global_symbol_pipe= + +# Check hardcoding attributes. +echo $ac_n "checking how to hardcode library paths into programs... $ac_c" 1>&6 +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || \ + test -n "$runpath_var"; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct" != no && \ + test "$hardcode_minus_L" != no && \ + test "$hardcode_shlibpath_var" != no; then + + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +elif test "$hardcode_direct" != yes && \ + test "$hardcode_minus_L" != yes && \ + test "$hardcode_shlibpath_var" != yes; then + # We cannot hardcode anything. + hardcode_action=unsupported +else + # We can only hardcode existing directories. + hardcode_action=relink +fi +echo "$ac_t$hardcode_action" 1>&6 +test "$hardcode_action" = unsupported && can_build_shared=no + + +reload_flag= +reload_cmds='$LD$reload_flag -o $output$reload_objs' +echo $ac_n "checking for $LD option to produce relocatable object files... $ac_c" 1>&6 +# PORTME Some linker may need a different reload flag. +reload_flag='-r' +echo "$ac_t$reload_flag" +test -n "$reload_flag" && reload_flag=" $reload_flag" + +# PORTME Fill in your ld.so characteristics +library_names_spec= +libname_spec='lib$name' +soname_spec= +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +version_type=none +dynamic_linker="$host_os ld.so" + +echo $ac_n "checking dynamic linker characteristics... $ac_c" 1>&6 +case "$host_os" in +aix3* | aix4*) + version_type=linux + library_names_spec='${libname}${release}.so.$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}.so.$major' + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done' + ;; + +freebsd2* | freebsd3 | freebsdelf3*) + version_type=sunos + library_names_spec='${libname}${release}.so.$versuffix $libname.so' + finish_cmds='PATH="$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + ;; + +gnu*) + version_type=sunos + library_names_spec='${libname}${release}.so.$versuffix' + shlibpath_var=LD_LIBRARY_PATH + ;; + +hpux9* | hpux10*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + dynamic_linker="$host_os dld.sl" + version_type=sunos + shlibpath_var=SHLIB_PATH + library_names_spec='${libname}${release}.sl.$versuffix ${libname}${release}.sl.$major $libname.sl' + soname_spec='${libname}${release}.sl.$major' + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +irix5* | irix6*) + version_type=osf + soname_spec='${libname}${release}.so' + library_names_spec='${libname}${release}.so.$versuffix $libname.so' + shlibpath_var=LD_LIBRARY_PATH + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux-gnu*) + version_type=linux + library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major $libname.so' + soname_spec='${libname}${release}.so.$major' + finish_cmds='PATH="$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + + if test -f /lib/ld.so.1; then + dynamic_linker='GNU ld.so' + else + # Only the GNU ld.so supports shared libraries on MkLinux. + case "$host_cpu" in + powerpc*) dynamic_linker=no ;; + *) dynamic_linker='Linux ld.so' ;; + esac + fi + ;; + +netbsd* | openbsd*) + version_type=sunos + library_names_spec='${libname}${release}.so.$versuffix' + finish_cmds='PATH="$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + ;; + +os2*) + libname_spec='$name' + library_names_spec='$libname.dll $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4*) + version_type=osf + soname_spec='${libname}${release}.so' + library_names_spec='${libname}${release}.so.$versuffix $libname.so' + shlibpath_var=LD_LIBRARY_PATH + ;; + +sco3.2v5*) + version_type=osf + soname_spec='${libname}${release}.so.$major' + library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major $libname.so' + shlibpath_var=LD_LIBRARY_PATH + ;; + +solaris2*) + version_type=linux + library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major $libname.so' + soname_spec='${libname}${release}.so.$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}.so.$versuffix' + finish_cmds='PATH="$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + ;; + +sysv4.2uw2*) + version_type=linux + library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major $libname.so' + soname_spec='${libname}${release}.so.$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major $libname.so' + soname_spec='${libname}${release}.so.$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +echo "$ac_t$dynamic_linker" +test "$dynamic_linker" = no && can_build_shared=no + +# Report the final consequences. +echo "checking if libtool supports shared libraries... $can_build_shared" 1>&6 + +echo $ac_n "checking whether to build shared libraries... $ac_c" 1>&6 +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case "$host_os" in +aix*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds;\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; +esac + +echo "$ac_t$enable_shared" 1>&6 + +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes + +echo "checking whether to build static libraries... $enable_static" 1>&6 + +echo $ac_n "checking for objdir... $ac_c" 1>&6 +rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + objdir=_libs +fi +rmdir .libs 2>/dev/null +echo "$ac_t$objdir" 1>&6 + +# Copy echo and quote the copy, instead of the original, because it is +# used later. +ltecho="$echo" + +# Now quote all the things that may contain metacharacters. +for var in ltecho old_CC old_CFLAGS old_CPPFLAGS old_LD old_NM old_RANLIB \ + old_LN_S AR CC LD LN_S NM reload_flag reload_cmds wl pic_flag \ + link_static_flag no_builtin_flag export_dynamic_flag_spec \ + libname_spec library_names_spec soname_spec RANLIB \ + old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \ + old_postuninstall_cmds archive_cmds postinstall_cmds postuninstall_cmds \ + allow_undefined_flag no_undefined_flag \ + finish_cmds finish_eval global_symbol_pipe \ + hardcode_libdir_flag_spec hardcode_libdir_separator; do + + case "$var" in + reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | archive_cmds | \ + postinstall_cmds | postuninstall_cmds | finish_cmds) + # Double-quote double-evaled strings. + eval "$var=\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\"\`" + ;; + *) + eval "$var=\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`" + ;; + esac +done + +ofile=libtool +trap "$rm $ofile; exit 1" 1 2 15 +echo creating $ofile +$rm $ofile +cat < $ofile +#! /bin/sh + +# libtool - Provide generalized library-building support services. +# Generated automatically by $PROGRAM - GNU $PACKAGE $VERSION +# NOTE: Changes made to this file will be lost: look at ltconfig or ltmain.sh. +# +# Copyright (C) 1996-1998 Free Software Foundation, Inc. +# Gordon Matzigkeit , 1996 +# +# 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. +# +# 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. + +# This program was configured as follows, +# on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# +# CC="$old_CC" CFLAGS="$old_CFLAGS" CPPFLAGS="$old_CPPFLAGS" \\ +# LD="$old_LD" NM="$old_NM" RANLIB="$old_RANLIB" LN_S="$old_LN_S" \\ +# $0$ltconfig_args +# +# Compiler and other test output produced by $progname, useful for +# debugging $progname, is in ./config.log if it exists. + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="sed -e s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "\${CDPATH+set}" = set; then CDPATH=; export CDPATH; fi + +# An echo program that does not interpret backslashes. +echo="$ltecho" + +# The version of $progname that generated this script. +LTCONFIG_VERSION="$VERSION" + +# Shell to use when invoking shell scripts. +SHELL=${CONFIG_SHELL-/bin/sh} + +# Whether or not to build libtool libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build old-style libraries. +build_old_libs=$enable_static + +# The host system. +host_alias="$host_alias" +host="$host" + +# The archiver. +AR="$AR" + +# The default C compiler. +CC="$CC" + +# The linker used to build libraries. +LD="$LD" + +# Whether we need hard or soft links. +LN_S="$LN_S" + +# A BSD-compatible nm program. +NM="$NM" + +# The name of the directory that contains temporary libtool files. +objdir="$objdir" + +# How to create relocatable object files. +reload_flag="$reload_flag" +reload_cmds="$reload_cmds" + +# How to pass a linker flag through the compiler. +wl="$wl" + +# Additional compiler flags for building library objects. +pic_flag="$pic_flag" + +# Compiler flag to prevent dynamic linking. +link_static_flag="$link_static_flag" + +# Compiler flag to turn off builtin functions. +no_builtin_flag="$no_builtin_flag" + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec="$export_dynamic_flag_spec" + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec="$libname_spec" + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec="$library_names_spec" + +# The coded name of the library, if different from the real name. +soname_spec="$soname_spec" + +# Commands used to build and install an old-style archive. +RANLIB="$RANLIB" +old_archive_cmds="$old_archive_cmds" +old_postinstall_cmds="$old_postinstall_cmds" +old_postuninstall_cmds="$old_postuninstall_cmds" + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds="$old_archive_from_new_cmds" + +# Commands used to build and install a shared archive. +archive_cmds="$archive_cmds" +postinstall_cmds="$postinstall_cmds" +postuninstall_cmds="$postuninstall_cmds" + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag="$allow_undefined_flag" + +# Flag that forces no undefined symbols. +no_undefined_flag="$no_undefined_flag" + +# Commands used to finish a libtool library installation in a directory. +finish_cmds="$finish_cmds" + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval="$finish_eval" + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe="$global_symbol_pipe" + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec="$hardcode_libdir_flag_spec" + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator="$hardcode_libdir_separator" + +# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +EOF + +case "$host_os" in +aix3*) + cat <<\EOF >> $ofile +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "${COLLECT_NAMES+set}" != set; then + COLLECT_NAMES= + export COLLECT_NAMES +fi + +EOF + ;; +esac + +# Append the ltmain.sh script. +cat "$ltmain" >> $ofile || (rm -f $ofile; exit 1) + +chmod +x $ofile +exit 0 + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/autoconf/ltmain.sh b/autoconf/ltmain.sh new file mode 100644 index 0000000..e9723c0 --- /dev/null +++ b/autoconf/ltmain.sh @@ -0,0 +1,2455 @@ +# ltmain.sh - Provide generalized library-building support services. +# NOTE: Changing this file will not affect anything until you rerun ltconfig. +# +# Copyright (C) 1996-1998 Free Software Foundation, Inc. +# Gordon Matzigkeit , 1996 +# +# 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. +# +# 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. + +# The name of this program. +progname=`$echo "$0" | sed 's%^.*/%%'` +modename="$progname" + +# Constants. +PROGRAM=ltmain.sh +PACKAGE=libtool +VERSION=1.2 + +default_mode= +help="Try \`$progname --help' for more information." +magic="%%%MAGIC variable%%%" +mkdir="mkdir" +mv="mv -f" +rm="rm -f" + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e s/^X//' +sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g' + +# NLS nuisances. +# Only set LANG and LC_ALL to C if already set. +# These must not be set unconditionally because not all systems understand +# e.g. LANG=C (notably SCO). +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LANG+set}" = set; then LANG=C; export LANG; fi + +if test "$LTCONFIG_VERSION" != "$VERSION"; then + echo "$modename: ltconfig version \`$LTCONFIG_VERSION' does not match $PROGRAM version \`$VERSION'" 1>&2 + echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit 1 +fi + +if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then + echo "$modename: not configured to build any kind of library" 1>&2 + echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit 1 +fi + +# Global variables. +mode=$default_mode +nonopt= +prev= +prevopt= +run= +show="$echo" +show_help= +execute_dlfiles= + +# Parse our command line options once, thoroughly. +while test $# -gt 0 +do + arg="$1" + shift + + case "$arg" in + -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case "$prev" in + execute_dlfiles) + eval "$prev=\"\$$prev \$arg\"" + ;; + *) + eval "$prev=\$arg" + ;; + esac + + prev= + prevopt= + continue + fi + + # Have we seen a non-optional argument yet? + case "$arg" in + --help) + show_help=yes + ;; + + --version) + echo "$PROGRAM (GNU $PACKAGE) $VERSION" + exit 0 + ;; + + --dry-run | -n) + run=: + ;; + + --features) + echo "host: $host" + if test "$build_libtool_libs" = yes; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test "$build_old_libs" = yes; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + exit 0 + ;; + + --finish) mode="finish" ;; + + --mode) prevopt="--mode" prev=mode ;; + --mode=*) mode="$optarg" ;; + + --quiet | --silent) + show=: + ;; + + -dlopen) + prevopt="-dlopen" + prev=execute_dlfiles + ;; + + -*) + $echo "$modename: unrecognized option \`$arg'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + + *) + nonopt="$arg" + break + ;; + esac +done + +if test -n "$prevopt"; then + $echo "$modename: option \`$prevopt' requires an argument" 1>&2 + $echo "$help" 1>&2 + exit 1 +fi + +if test -z "$show_help"; then + + # Infer the operation mode. + if test -z "$mode"; then + case "$nonopt" in + *cc | *++ | gcc* | *-gcc*) + mode=link + for arg + do + case "$arg" in + -c) + mode=compile + break + ;; + esac + done + ;; + *db | *dbx) + mode=execute + ;; + *install*|cp|mv) + mode=install + ;; + *rm) + mode=uninstall + ;; + *) + # If we have no mode, but dlfiles were specified, then do execute mode. + test -n "$execute_dlfiles" && mode=execute + + # Just use the default operation mode. + if test -z "$mode"; then + if test -n "$nonopt"; then + $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 + else + $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 + fi + fi + ;; + esac + fi + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$execute_dlfiles" && test "$mode" != execute; then + $echo "$modename: unrecognized option \`-dlopen'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$modename --help --mode=$mode' for more information." + + # These modes are in order of execution frequency so that they run quickly. + case "$mode" in + # libtool compile mode + compile) + modename="$modename: compile" + # Get the compilation command and the source file. + base_compile= + lastarg= + srcfile="$nonopt" + suppress_output= + + for arg + do + # Accept any command-line options. + case "$arg" in + -o) + $echo "$modename: you cannot specify the output filename with \`-o'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + esac + + # Accept the current argument as the source file. + lastarg="$srcfile" + srcfile="$arg" + + # Aesthetically quote the previous argument. + + # Backslashify any backslashes, double quotes, and dollar signs. + # These are the only characters that are still specially + # interpreted inside of double-quoted scrings. + lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` + + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly in scan + # sets, so we specify it separately. + case "$lastarg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + lastarg="\"$lastarg\"" + ;; + esac + + # Add the previous argument to base_compile. + if test -z "$base_compile"; then + base_compile="$lastarg" + else + base_compile="$base_compile $lastarg" + fi + done + + # Get the name of the library object. + libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` + + # Recognize several different file suffixes. + xform='[cCFSfms]' + case "$libobj" in + *.ada) xform=ada ;; + *.adb) xform=adb ;; + *.ads) xform=ads ;; + *.asm) xform=asm ;; + *.c++) xform=c++ ;; + *.cc) xform=cc ;; + *.cpp) xform=cpp ;; + *.cxx) xform=cxx ;; + *.f90) xform=f90 ;; + *.for) xform=for ;; + esac + + libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` + + case "$libobj" in + *.lo) obj=`$echo "X$libobj" | $Xsed -e 's/\.lo$/.o/'` ;; + *) + $echo "$modename: cannot determine name of library object from \`$srcfile'" 1>&2 + exit 1 + ;; + esac + + if test -z "$base_compile"; then + $echo "$modename: you must specify a compilation command" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + $run $rm $obj $libobj + trap "$run $rm $obj $libobj; exit 1" 1 2 15 + else + $run $rm $libobj + trap "$run $rm $libobj; exit 1" 1 2 15 + fi + + # Only build a PIC object if we are building libtool libraries. + if test "$build_libtool_libs" = yes; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + # All platforms use -DPIC, to notify preprocessed assembler code. + $show "$base_compile$pic_flag -DPIC $srcfile" + if $run eval "$base_compile\$pic_flag -DPIC \$srcfile"; then : + else + test -n "$obj" && $run $rm $obj + exit 1 + fi + + # If we have no pic_flag, then copy the object into place and finish. + if test -z "$pic_flag"; then + $show "$LN_S $obj $libobj" + $run $LN_S $obj $libobj + exit $? + fi + + # Just move the object, then go on to compile the next one + $show "$mv $obj $libobj" + $run $mv $obj $libobj || exit 1 + + # Allow error messages only from the first compilation. + suppress_output=' >/dev/null 2>&1' + fi + + # Only build a position-dependent object if we build old libraries. + if test "$build_old_libs" = yes; then + # Suppress compiler output if we already did a PIC compilation. + $show "$base_compile $srcfile$suppress_output" + if $run eval "$base_compile \$srcfile$suppress_output"; then : + else + $run $rm $obj $libobj + exit 1 + fi + fi + + # Create an invalid libtool object if no PIC, so that we do not + # accidentally link it into a program. + if test "$build_libtool_libs" != yes; then + $show "echo timestamp > $libobj" + $run eval "echo timestamp > \$libobj" || exit $? + fi + + exit 0 + ;; + + # libtool link mode + link) + modename="$modename: link" + CC="$nonopt" + allow_undefined=yes + compile_command="$CC" + finalize_command="$CC" + + compile_shlibpath= + finalize_shlibpath= + deplibs= + dlfiles= + dlprefiles= + export_dynamic=no + hardcode_libdirs= + libobjs= + link_against_libtool_libs= + ltlibs= + objs= + olibobjs= + prev= + prevarg= + release= + rpath= + perm_rpath= + temp_rpath= + vinfo= + + # We need to know -static, to get the right output filenames. + for arg + do + case "$arg" in + -all-static | -static) + if test "X$arg" = "X-all-static" && test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then + $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2 + fi + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + for arg + do + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case "$prev" in + output) + compile_command="$compile_command @OUTPUT@" + finalize_command="$finalize_command @OUTPUT@" + ;; + esac + + case "$prev" in + dlfiles|dlprefiles) + case "$arg" in + *.la | *.lo) ;; # We handle these cases below. + *) + dlprefiles="$dlprefiles $arg" + test "$prev" = dlfiles && dlfiles="$dlfiles $arg" + prev= + ;; + esac + ;; + release) + release="-$arg" + prev= + continue + ;; + rpath) + rpath="$rpath $arg" + prev= + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi + + prevarg="$arg" + + case "$arg" in + -all-static) + if test -n "$link_static_flag"; then + compile_command="$compile_command $link_static_flag" + finalize_command="$finalize_command $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + if test "$export_dynamic" != yes; then + export_dynamic=yes + if test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + else + arg= + fi + + # Add the symbol object into the linking commands. + compile_command="$compile_command @SYMFILE@" + finalize_command="$finalize_command @SYMFILE@" + fi + ;; + + -L*) + dir=`$echo "X$arg" | $Xsed -e 's%^-L\(.*\)$%\1%'` + case "$dir" in + /* | [A-Za-z]:\\*) + # Add the corresponding hardcode_libdir_flag, if it is not identical. + ;; + *) + $echo "$modename: \`-L$dir' cannot specify a relative directory" 1>&2 + exit 1 + ;; + esac + deplibs="$deplibs $arg" + ;; + + -l*) deplibs="$deplibs $arg" ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -o) prev=output ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -static) + # If we have no pic_flag, then this is the same as -all-static. + if test -z "$pic_flag" && test -n "$link_static_flag"; then + compile_command="$compile_command $link_static_flag" + finalize_command="$finalize_command $link_static_flag" + fi + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + # Some other compiler flag. + -* | +*) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + ;; + + *.o | *.a) + # A standard object. + objs="$objs $arg" + ;; + + *.lo) + # A library object. + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + if test "$build_libtool_libs" = yes; then + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles "`$echo "X$arg" | $Xsed -e 's/\.lo$/\.o/'` + prev= + fi + libobjs="$libobjs $arg" + olibobjs="$olibobjs "`$echo "X$arg" | $Xsed -e 's/\.lo$/\.o/'` + ;; + + *.la) + # A libtool-controlled library. + + dlname= + libdir= + library_names= + old_library= + + # Check to see that this really is a libtool archive. + if (sed -e '2q' $arg | egrep '^# Generated by ltmain\.sh') >/dev/null 2>&1; then : + else + $echo "$modename: \`$arg' is not a valid libtool archive" 1>&2 + exit 1 + fi + + # If there is no directory component, then add one. + case "$arg" in + */* | *\\*) . $arg ;; + *) . ./$arg ;; + esac + + if test -z "$libdir"; then + $echo "$modename: \`$arg' contains no -rpath information" 1>&2 + exit 1 + fi + + # Get the name of the library we link against. + linklib= + for l in $old_library $library_names; do + linklib="$l" + done + + if test -z "$linklib"; then + $echo "$modename: cannot find name of link library for \`$arg'" 1>&2 + exit 1 + fi + + # Find the relevant object directory and library name. + name=`$echo "X$arg" | $Xsed -e 's%^.*/%%' -e 's/\.la$//' -e 's/^lib//'` + dir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$dir" = "X$arg"; then + dir="$objdir" + else + dir="$dir/$objdir" + fi + + # This library was specified with -dlopen. + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + if test -z "$dlname"; then + # If there is no dlname, we need to preload. + prev=dlprefiles + else + # We should not create a dependency on this library, but we + # may need any libraries it requires. + compile_command="$compile_command$dependency_libs" + finalize_command="$finalize_command$dependency_libs" + prev= + continue + fi + fi + + # The library was specified with -dlpreopen. + if test "$prev" = dlprefiles; then + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + dlprefiles="$dlprefiles $dir/$old_library" + else + dlprefiles="$dlprefiles $dir/$linklib" + fi + prev= + fi + + if test "$build_libtool_libs" = yes && test -n "$library_names"; then + link_against_libtool_libs="$link_against_libtool_libs $arg" + if test -n "$shlibpath_var"; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath " in + *" $dir "*) ;; + *) temp_rpath="$temp_rpath $dir" ;; + esac + fi + + # This is the magic to use -rpath. + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + # Put the magic libdir with the hardcode flag. + hardcode_libdirs="$libdir" + libdir="@HARDCODE_LIBDIRS@" + else + # Just accumulate the unique libdirs. + case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + libdir= + fi + fi + + if test -n "$libdir"; then + eval flag=\"$hardcode_libdir_flag_spec\" + + compile_command="$compile_command $flag" + finalize_command="$finalize_command $flag" + fi + elif test -n "$runpath_var"; then + # Do the same for the permanent run path. + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + + + case "$hardcode_action" in + immediate) + if test "$hardcode_direct" = no; then + compile_command="$compile_command $dir/$linklib" + elif test "$hardcode_minus_L" = no; then + compile_command="$compile_command -L$dir -l$name" + elif test "$hardcode_shlibpath_var" = no; then + compile_shlibpath="$compile_shlibpath$dir:" + compile_command="$compile_command -l$name" + fi + ;; + + relink) + # We need an absolute path. + case "$dir" in + /* | [A-Za-z]:\\*) ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2 + exit 1 + fi + dir="$absdir" + ;; + esac + + if test "$hardcode_direct" = yes; then + compile_command="$compile_command $dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + compile_command="$compile_command -L$dir -l$name" + elif test "$hardcode_shlibpath_var" = yes; then + compile_shlibpath="$compile_shlibpath$dir:" + compile_command="$compile_command -l$name" + fi + ;; + + *) + $echo "$modename: \`$hardcode_action' is an unknown hardcode action" 1>&2 + exit 1 + ;; + esac + + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes; then + finalize_command="$finalize_command $libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + finalize_command="$finalize_command -L$libdir -l$name" + elif test "$hardcode_shlibpath_var" = yes; then + finalize_shlibpath="$finalize_shlibpath$libdir:" + finalize_command="$finalize_command -l$name" + else + # We cannot seem to hardcode it, guess we'll fake it. + finalize_command="$finalize_command -L$libdir -l$name" + fi + else + # Transform directly to old archives if we don't build new libraries. + if test -n "$pic_flag" && test -z "$old_library"; then + $echo "$modename: cannot find static library for \`$arg'" 1>&2 + exit 1 + fi + + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_command="$compile_command $dir/$linklib" + finalize_command="$finalize_command $dir/$linklib" + else + compile_command="$compile_command -L$dir -l$name" + finalize_command="$finalize_command -L$dir -l$name" + fi + fi + + # Add in any libraries that this one depends upon. + compile_command="$compile_command$dependency_libs" + finalize_command="$finalize_command$dependency_libs" + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + ;; + esac + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + done + + if test -n "$prev"; then + $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + if test -n "$vinfo" && test -n "$release"; then + $echo "$modename: you cannot specify both \`-version-info' and \`-release'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + oldlib= + oldobjs= + case "$output" in + "") + $echo "$modename: you must specify an output file" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + + */* | *\\*) + $echo "$modename: output file \`$output' must have no directory components" 1>&2 + exit 1 + ;; + + *.a) + # Now set the variables for building old libraries. + build_libtool_libs=no + build_old_libs=yes + oldlib="$output" + $show "$rm $oldlib" + $run $rm $oldlib + ;; + + *.la) + # Make sure we only generate libraries of the form `libNAME.la'. + case "$output" in + lib*) ;; + *) + $echo "$modename: libtool library \`$arg' must begin with \`lib'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + esac + + name=`$echo "X$output" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + eval libname=\"$libname_spec\" + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + current=0 + revision=0 + age=0 + + if test -n "$objs"; then + $echo "$modename: cannot build libtool library \`$output' from non-libtool objects:$objs" 2>&1 + exit 1 + fi + + # How the heck are we supposed to write a wrapper for a shared library? + if test -n "$link_against_libtool_libs"; then + $echo "$modename: libtool library \`$output' may not depend on uninstalled libraries:$link_against_libtool_libs" 1>&2 + exit 1 + fi + + if test -n "$dlfiles$dlprefiles"; then + $echo "$modename: warning: \`-dlopen' is ignored while creating libtool libraries" 1>&2 + # Nullify the symbol file. + compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi + + if test -z "$rpath"; then + $echo "$modename: you must specify an installation directory with \`-rpath'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + set dummy $rpath + if test $# -gt 2; then + $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 + fi + install_libdir="$2" + + # Parse the version information argument. + IFS="${IFS= }"; save_ifs="$IFS"; IFS=':' + set dummy $vinfo + IFS="$save_ifs" + + if test -n "$5"; then + $echo "$modename: too many parameters to \`-version-info'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + test -n "$2" && current="$2" + test -n "$3" && revision="$3" + test -n "$4" && age="$4" + + # Check that each of the things are valid numbers. + case "$current" in + 0 | [1-9] | [1-9][0-9]*) ;; + *) + $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + ;; + esac + + case "$revision" in + 0 | [1-9] | [1-9][0-9]*) ;; + *) + $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + ;; + esac + + case "$age" in + 0 | [1-9] | [1-9][0-9]*) ;; + *) + $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + ;; + esac + + if test $age -gt $current; then + $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + fi + + # Calculate the version variables. + version_vars="version_type current age revision" + case "$version_type" in + none) ;; + + linux) + version_vars="$version_vars major versuffix" + major=`expr $current - $age` + versuffix="$major.$age.$revision" + ;; + + osf) + version_vars="$version_vars versuffix verstring" + major=`expr $current - $age` + versuffix="$current.$age.$revision" + verstring="$versuffix" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test $loop != 0; do + iface=`expr $current - $loop` + loop=`expr $loop - 1` + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + verstring="$verstring:${current}.0" + ;; + + sunos) + version_vars="$version_vars major versuffix" + major="$current" + versuffix="$current.$revision" + ;; + + *) + $echo "$modename: unknown library version type \`$version_type'" 1>&2 + echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit 1 + ;; + esac + + # Create the output directory, or remove our outputs if we need to. + if test -d $objdir; then + $show "$rm $objdir/$output $objdir/$libname.* $objdir/${libname}${release}.*" + $run $rm $objdir/$output $objdir/$libname.* $objdir/${libname}${release}.* + else + $show "$mkdir $objdir" + $run $mkdir $objdir + status=$? + if test $status -eq 0 || test -d $objdir; then : + else + exit $status + fi + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + + # Add libc to deplibs on all systems. + dependency_libs="$deplibs" + deplibs="$deplibs -lc" + + if test "$build_libtool_libs" = yes; then + # Get the real and link names of the library. + eval library_names=\"$library_names_spec\" + set dummy $library_names + realname="$2" + shift; shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + lib="$objdir/$realname" + for link + do + linknames="$linknames $link" + done + + # Use standard objects if they are PIC. + test -z "$pic_flag" && libobjs="$olibobjs" + + # Do each of the archive commands. + eval cmds=\"$archive_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + # Create links to the real library. + for linkname in $linknames; do + $show "(cd $objdir && $LN_S $realname $linkname)" + $run eval '(cd $objdir && $LN_S $realname $linkname)' || exit $? + done + + # If -export-dynamic was specified, set the dlname. + if test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + + # Now set the variables for building old libraries. + oldlib="$objdir/$libname.a" + ;; + + *.lo | *.o) + if test -n "$link_against_libtool_libs"; then + $echo "$modename: error: cannot link libtool libraries into reloadable objects" 1>&2 + exit 1 + fi + + if test -n "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored while creating objects" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles"; then + $echo "$modename: warning: \`-dlopen' is ignored while creating objects" 1>&2 + # Nullify the symbol file. + compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored while creating objects" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored while creating objects" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored while creating objects" 1>&2 + fi + + case "$output" in + *.lo) + if test -n "$objs"; then + $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 + exit 1 + fi + libobj="$output" + obj=`$echo "X$output" | $Xsed -e 's/\.lo$/.o/'` + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $run $rm $obj $libobj + + # Create the old-style object. + reload_objs="$objs $olibobjs" + + output="$obj" + eval cmds=\"$reload_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + # Exit if we aren't doing a library object file. + test -z "$libobj" && exit 0 + + if test "$build_libtool_libs" != yes; then + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + $show "echo timestamp > $libobj" + $run eval "echo timestamp > $libobj" || exit $? + exit 0 + fi + + if test -n "$pic_flag"; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs" + output="$libobj" + eval cmds=\"$reload_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + else + # Just create a symlink. + $show "$LN_S $obj $libobj" + $run $LN_S $obj $libobj || exit 1 + fi + + exit 0 + ;; + + *) + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored while linking programs" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored while creating objects" 1>&2 + fi + + if test -n "$rpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + # Put the magic libdir with the hardcode flag. + hardcode_libdirs="$libdir" + libdir="@HARDCODE_LIBDIRS@" + else + # Just accumulate the unique libdirs. + case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + libdir= + fi + fi + + if test -n "$libdir"; then + eval flag=\"$hardcode_libdir_flag_spec\" + + compile_command="$compile_command $flag" + finalize_command="$finalize_command $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + done + fi + + # Substitute the hardcoded libdirs into the compile commands. + if test -n "$hardcode_libdir_separator"; then + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@HARDCODE_LIBDIRS@%$hardcode_libdirs%g"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@HARDCODE_LIBDIRS@%$hardcode_libdirs%g"` + fi + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$echo "X$compile_command " | $Xsed -e 's/\.lo /.o /g' -e 's/ $//'` + finalize_command=`$echo "X$finalize_command " | $Xsed -e 's/\.lo /.o /g' -e 's/ $//'` + fi + + if test "$export_dynamic" = yes && test -n "$NM" && test -n "$global_symbol_pipe"; then + dlsyms="${output}S.c" + else + dlsyms= + fi + + if test -n "$dlsyms"; then + # Add our own program objects to the preloaded list. + dlprefiles=`$echo "X$objs$dlprefiles " | $Xsed -e 's/\.lo /.o /g' -e 's/ $//'` + + # Discover the nlist of each of the dlfiles. + nlist="$objdir/${output}.nm" + + if test -d $objdir; then + $show "$rm $nlist ${nlist}T" + $run $rm "$nlist" "${nlist}T" + else + $show "$mkdir $objdir" + $run $mkdir $objdir + status=$? + if test $status -eq 0 || test -d $objdir; then : + else + exit $status + fi + fi + + for arg in $dlprefiles; do + $show "extracting global C symbols from \`$arg'" + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + # Parse the name list into a source file. + $show "creating $objdir/$dlsyms" + if test -z "$run"; then + # Make sure we at least have an empty file. + test -f "$nlist" || : > "$nlist" + + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + wcout=`wc "$nlist" 2>/dev/null` + count=`echo "X$wcout" | $Xsed -e 's/^[ ]*\([0-9][0-9]*\).*$/\1/'` + (test "$count" -ge 0) 2>/dev/null || count=-1 + else + $rm "$nlist"T + count=-1 + fi + + case "$dlsyms" in + "") ;; + *.c) + $echo > "$objdir/$dlsyms" "\ +/* $dlsyms - symbol resolution table for \`$output' dlsym emulation. */ +/* Generated by $PROGRAM - GNU $PACKAGE $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +/* Prevent the only kind of declaration conflicts we can make. */ +#define dld_preloaded_symbol_count some_other_symbol +#define dld_preloaded_symbols some_other_symbol + +/* External symbol declarations for the compiler. */\ +" + + if test -f "$nlist"; then + sed -e 's/^.* \(.*\)$/extern char \1;/' < "$nlist" >> "$objdir/$dlsyms" + else + echo '/* NONE */' >> "$objdir/$dlsyms" + fi + + $echo >> "$objdir/$dlsyms" "\ + +#undef dld_preloaded_symbol_count +#undef dld_preloaded_symbols + +#if defined (__STDC__) && __STDC__ +# define __ptr_t void * +#else +# define __ptr_t char * +#endif + +/* The number of symbols in dld_preloaded_symbols, -1 if unsorted. */ +int dld_preloaded_symbol_count = $count; + +/* The mapping between symbol names and symbols. */ +struct { + char *name; + __ptr_t address; +} +dld_preloaded_symbols[] = +{\ +" + + if test -f "$nlist"; then + sed 's/^\(.*\) \(.*\)$/ {"\1", (__ptr_t) \&\2},/' < "$nlist" >> "$objdir/$dlsyms" + fi + + $echo >> "$objdir/$dlsyms" "\ + {0, (__ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif\ +" + ;; + + *) + $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 + exit 1 + ;; + esac + fi + + # Now compile the dynamic symbol file. + $show "(cd $objdir && $CC -c$no_builtin_flag \"$dlsyms\")" + $run eval '(cd $objdir && $CC -c$no_builtin_flag "$dlsyms")' || exit $? + + # Transform the symbol file into the correct name. + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$objdir/${output}S.o%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$objdir/${output}S.o%"` + elif test "$export_dynamic" != yes; then + test -n "$dlfiles$dlprefiles" && $echo "$modename: warning: \`-dlopen' and \`-dlpreopen' are ignored without \`-export-dynamic'" 1>&2 + else + # We keep going just in case the user didn't refer to + # dld_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 + + # Nullify the symbol file. + compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi + + if test -z "$link_against_libtool_libs" || test "$build_libtool_libs" != yes; then + # Replace the output file specification. + compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + finalize_command=`$echo "X$finalize_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + + # We have no uninstalled library dependencies, so finalize right now. + $show "$compile_command" + $run eval "$compile_command" + exit $? + fi + + # Replace the output file specification. + compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$objdir/$output"'%g'` + finalize_command=`$echo "X$finalize_command" | $Xsed -e 's%@OUTPUT@%'"$objdir/$output"'T%g'` + + # Create the binary in the object directory, then wrap it. + if test -d $objdir; then : + else + $show "$mkdir $objdir" + $run $mkdir $objdir + status=$? + if test $status -eq 0 || test -d $objdir; then : + else + exit $status + fi + fi + + if test -n "$shlibpath_var"; then + # We should set the shlibpath_var + rpath= + for dir in $temp_rpath; do + case "$dir" in + /* | [A-Za-z]:\\*) + # Absolute path. + rpath="$rpath$dir:" + ;; + *) + # Relative path: add a thisdir entry. + rpath="$rpath\$thisdir/$dir:" + ;; + esac + done + temp_rpath="$rpath" + fi + + # Delete the old output file. + $run $rm $output + + if test -n "$compile_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + compile_command="$runpath_var=\"$rpath\$$runpath_var\" $compile_command" + finalize_command="$runpath_var=\"$rpath\$$runpath_var\" $finalize_command" + fi + + case "$hardcode_action" in + relink) + # AGH! Flame the AIX and HP-UX people for me, will ya? + $echo "$modename: warning: using a buggy system linker" 1>&2 + $echo "$modename: relinking will be required before \`$output' can be installed" 1>&2 + ;; + esac + + $show "$compile_command" + $run eval "$compile_command" || exit $? + + # Now create the wrapper script. + $show "creating $output" + + # Quote the finalize command for shipping. + finalize_command=`$echo "X$finalize_command" | $Xsed -e "$sed_quote_subst"` + + # Quote $echo for shipping. + qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` + + # Only actually do things if our run command is non-null. + if test -z "$run"; then + $rm $output + trap "$rm $output; exit 1" 1 2 15 + + $echo > $output "\ +#! /bin/sh + +# $output - temporary wrapper script for $objdir/$output +# Generated by ltmain.sh - GNU $PACKAGE $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of \``pwd`'. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e s/^X//' +sed_quote_subst='$sed_quote_subst' + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test \"\${CDPATH+set}\" = set; then CDPATH=; export CDPATH; fi + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + link_against_libtool_libs='$link_against_libtool_libs' + finalize_command=\"$finalize_command\" +else + # When we are sourced in execute mode, \$file and \$echo are already set. + if test \"\$libtool_execute_magic\" = \"$magic\"; then : + else + echo=\"$qecho\" + file=\"\$0\" + fi\ +" + $echo >> $output "\ + + # Find the directory that this script lives in. + thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | sed -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + /* | [A-Za-z]:\\*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | sed -n 's/.*-> //p'\` + done + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" + + progdir=\"\$thisdir/$objdir\" + program='$output' + + if test -f \"\$progdir/\$program\"; then" + + # Export our shlibpath_var if we have one. + if test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $echo >> $output "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/:*\$//'\` + + export $shlibpath_var +" + fi + + $echo >> $output "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + + # Export the path to the program. + PATH=\"\$progdir:\$PATH\" + export PATH + + exec \$program \${1+\"\$@\"} + + \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" + exit 1 + fi + else + # The program doesn't exist. + \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2 + \$echo \"This script is just a wrapper for \$program.\" 1>&2 + echo \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" + chmod +x $output + fi + exit 0 + ;; + esac + + # See if we need to build an old-fashioned archive. + if test "$build_old_libs" = "yes"; then + # Transform .lo files to .o files. + oldobjs="$objs $olibobjs" + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + eval cmds=\"$old_archive_from_new_cmds\" + else + eval cmds=\"$old_archive_cmds\" + fi + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + # Now create the libtool archive. + case "$output" in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.a" + + $show "creating $output" + + # Only create the output if not a dry run. + if test -z "$run"; then + $echo > $output "\ +# $output - a libtool library file +# Generated by ltmain.sh - GNU $PACKAGE $VERSION + +# The name that we can dlopen(3). +dlname='$dlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Directory that this library needs to be installed in: +libdir='$install_libdir'\ +" + fi + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + $show "(cd $objdir && $LN_S ../$output $output)" + $run eval "(cd $objdir && $LN_S ../$output $output)" || exit 1 + ;; + esac + exit 0 + ;; + + # libtool install mode + install) + modename="$modename: install" + + # There may be an optional /bin/sh argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL"; then + # Aesthetically quote it. + arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$arg " + arg="$1" + shift + else + install_prog= + arg="$nonopt" + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog$arg" + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir= + stripme= + for arg + do + if test -n "$dest"; then + files="$files $dest" + dest="$arg" + continue + fi + + case "$arg" in + -d) isdir=yes ;; + -f) prev="-f" ;; + -g) prev="-g" ;; + -m) prev="-m" ;; + -o) prev="-o" ;; + -s) + stripme=" -s" + continue + ;; + -*) ;; + + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + prev= + else + dest="$arg" + continue + fi + ;; + esac + + # Aesthetically quote the argument. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog $arg" + done + + if test -z "$install_prog"; then + $echo "$modename: you must specify an install program" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + if test -n "$prev"; then + $echo "$modename: the \`$prev' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + if test -z "$files"; then + if test -z "$dest"; then + $echo "$modename: no file or destination specified" 1>&2 + else + $echo "$modename: you must specify a destination" 1>&2 + fi + $echo "$help" 1>&2 + exit 1 + fi + + # Strip any trailing slash from the destination. + dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test -n "$isdir"; then + destdir="$dest" + destname= + else + destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` + test "X$destdir" = "X$dest" && destdir=. + destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` + + # Not a directory, so check to see that there is only one file specified. + set dummy $files + if test $# -gt 2; then + $echo "$modename: \`$dest' is not a directory" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + fi + case "$destdir" in + /* | [A-Za-z]:\\*) ;; + *) + for file in $files; do + case "$file" in + *.lo) ;; + *) + $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case "$file" in + *.a) + # Do the static libraries later. + staticlibs="$staticlibs $file" + ;; + + *.la) + # Check to see that this really is a libtool archive. + if (sed -e '2q' $file | egrep '^# Generated by ltmain\.sh') >/dev/null 2>&1; then : + else + $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + library_names= + old_library= + # If there is no directory component, then add one. + case "$file" in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) current_libdirs="$current_libdirs $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) future_libdirs="$future_libdirs $libdir" ;; + esac + fi + + dir="`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/" + test "X$dir" = "X$file/" && dir= + dir="$dir$objdir" + + # See the names of the shared library. + set dummy $library_names + if test -n "$2"; then + realname="$2" + shift + shift + + # Install the shared library and build the symlinks. + $show "$install_prog $dir/$realname $destdir/$realname" + $run eval "$install_prog $dir/$realname $destdir/$realname" || exit $? + test "X$dlname" = "X$realname" && dlname= + + if test $# -gt 0; then + # Delete the old symlinks. + rmcmd="$rm" + for linkname + do + rmcmd="$rmcmd $destdir/$linkname" + done + $show "$rmcmd" + $run $rmcmd + + # ... and create new ones. + for linkname + do + test "X$dlname" = "X$linkname" && dlname= + $show "(cd $destdir && $LN_S $realname $linkname)" + $run eval "(cd $destdir && $LN_S $realname $linkname)" + done + fi + + if test -n "$dlname"; then + # Install the dynamically-loadable library. + $show "$install_prog $dir/$dlname $destdir/$dlname" + $run eval "$install_prog $dir/$dlname $destdir/$dlname" || exit $? + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + eval cmds=\"$postinstall_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + # Install the pseudo-library for information purposes. + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + $show "$install_prog $file $destdir/$name" + $run eval "$install_prog $file $destdir/$name" || exit $? + + # Maybe install the static library, too. + test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case "$destfile" in + *.lo) + staticdest=`$echo "X$destfile" | $Xsed -e 's/\.lo$/\.o/'` + ;; + *.o) + staticdest="$destfile" + destfile= + ;; + *) + $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + esac + + # Install the libtool object if requested. + if test -n "$destfile"; then + $show "$install_prog $file $destfile" + $run eval "$install_prog $file $destfile" || exit $? + fi + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + staticobj=`$echo "X$file" | $Xsed -e 's/\.lo$/\.o/'` + + $show "$install_prog $staticobj $staticdest" + $run eval "$install_prog \$staticobj \$staticdest" || exit $? + fi + exit 0 + ;; + + *) + # Do a test to see if this is really a libtool program. + if (sed -e '4q' $file | egrep '^# Generated by ltmain\.sh') >/dev/null 2>&1; then + link_against_libtool_libs= + finalize_command= + + # If there is no directory component, then add one. + case "$file" in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Check the variables that should have been set. + if test -z "$link_against_libtool_libs" || test -z "$finalize_command"; then + $echo "$modename: invalid libtool wrapper script \`$file'" 1>&2 + exit 1 + fi + + finalize=yes + for lib in $link_against_libtool_libs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + # If there is no directory component, then add one. + case "$lib" in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + fi + libfile="$libdir/`$echo "X$lib" | $Xsed -e 's%^.*/%%g'`" + if test -z "$libdir"; then + $echo "$modename: warning: \`$lib' contains no -rpath information" 1>&2 + elif test -f "$libfile"; then : + else + $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 + finalize=no + fi + done + + if test "$hardcode_action" = relink; then + if test "$finalize" = yes; then + $echo "$modename: warning: relinking \`$file' on behalf of your buggy system linker" 1>&2 + $show "$finalize_command" + if $run eval "$finalize_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + continue + fi + file="$objdir/$file"T + else + $echo "$modename: warning: cannot relink \`$file' on behalf of your buggy system linker" 1>&2 + fi + else + # Install the binary that we compiled earlier. + file=`$echo "X$file" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + $show "$install_prog$stripme $file $dest" + $run eval "$install_prog\$stripme \$file \$dest" || exit $? + ;; + esac + done + + for file in $staticlibs; do + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + $show "$install_prog $file $oldlib" + $run eval "$install_prog \$file \$oldlib" || exit $? + + # Do each command in the postinstall commands. + eval cmds=\"$old_postinstall_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$future_libdirs"; then + $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 + fi + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + test -n "$run" && current_libdirs=" -n$current_libdirs" + exec $SHELL $0 --finish$current_libdirs + exit 1 + fi + + exit 0 + ;; + + # libtool finish mode + finish) + modename="$modename: finish" + libdirs="$nonopt" + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for dir + do + libdirs="$libdirs $dir" + done + + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + eval cmds=\"$finish_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" + done + IFS="$save_ifs" + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $run eval "$cmds" + fi + done + fi + + echo "------------------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + echo " $libdir" + done + echo + echo "To link against installed libraries in a given directory, LIBDIR," + echo "you must use the \`-LLIBDIR' flag during linking." + echo + echo " You will also need to do one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the \`$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the \`$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + echo " - use the \`$flag' linker flag" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + echo + echo "See any operating system documentation about shared libraries for" + echo "more information, such as the ld(1) and ld.so(8) manual pages." + echo "------------------------------------------------------------------------------" + exit 0 + ;; + + # libtool execute mode + execute) + modename="$modename: execute" + + # The first argument is the command name. + cmd="$nonopt" + if test -z "$cmd"; then + $echo "$modename: you must specify a COMMAND" 1>&2 + $echo "$help" + exit 1 + fi + + # Handle -dlopen flags immediately. + for file in $execute_dlfiles; do + if test -f "$file"; then : + else + $echo "$modename: \`$file' is not a file" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + dir= + case "$file" in + *.la) + # Check to see that this really is a libtool archive. + if (sed -e '2q' $file | egrep '^# Generated by ltmain\.sh') >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + # Read the libtool library. + dlname= + library_names= + + # If there is no directory component, then add one. + case "$file" in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" + continue + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + + if test -f "$dir/$objdir/$dlname"; then + dir="$dir/$objdir" + else + $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 + exit 1 + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + ;; + + *) + $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case "$file" in + -*) ;; + *) + # Do a test to see if this is really a libtool program. + if (sed -e '4q' $file | egrep '^# Generated by ltmain\.sh') >/dev/null 2>&1; then + # If there is no directory component, then add one. + case "$file" in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` + args="$args \"$file\"" + done + + if test -z "$run"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + + # Now actually exec the command. + eval "exec \$cmd$args" + + $echo "$modename: cannot exec \$cmd$args" + exit 1 + else + # Display what would be done. + eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" + $echo "export $shlibpath_var" + $echo "$cmd$args" + exit 0 + fi + ;; + + # libtool uninstall mode + uninstall) + modename="$modename: uninstall" + rm="$nonopt" + files= + + for arg + do + case "$arg" in + -*) rm="$rm $arg" ;; + *) files="$files $arg" ;; + esac + done + + if test -z "$rm"; then + $echo "$modename: you must specify an RM program" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + for file in $files; do + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + + rmfiles="$file" + + case "$name" in + *.la) + # Possibly a libtool archive, so verify it. + if (sed -e '2q' $file | egrep '^# Generated by ltmain\.sh') >/dev/null 2>&1; then + . $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + rmfiles="$rmfiles $dir/$n" + test "X$n" = "X$dlname" && dlname= + done + test -n "$dlname" && rmfiles="$rmfiles $dir/$dlname" + test -n "$old_library" && rmfiles="$rmfiles $dir/$old_library" + + $show "$rm $rmfiles" + $run $rm $rmfiles + + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + eval cmds=\"$postuninstall_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" + done + IFS="$save_ifs" + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + eval cmds=\"$old_postuninstall_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" + done + IFS="$save_ifs" + fi + + # FIXME: should reinstall the best remaining shared library. + fi + ;; + + *.lo) + if test "$build_old_libs" = yes; then + oldobj=`$echo "X$name" | $Xsed -e 's/\.lo$/\.o/'` + rmfiles="$rmfiles $dir/$oldobj" + fi + $show "$rm $rmfiles" + $run $rm $rmfiles + ;; + + *) + $show "$rm $rmfiles" + $run $rm $rmfiles + ;; + esac + done + exit 0 + ;; + + "") + $echo "$modename: you must specify a MODE" 1>&2 + $echo "$generic_help" 1>&2 + exit 1 + ;; + esac + + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$generic_help" 1>&2 + exit 1 +fi # test -z "$show_help" + +# We need to display help for each of the modes. +case "$mode" in +"") $echo \ +"Usage: $modename [OPTION]... [MODE-ARG]... + +Provide generalized library-building support services. + +-n, --dry-run display commands without modifying any files + --features display configuration information and exit + --finish same as \`--mode=finish' + --help display this help message and exit + --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] + --quiet same as \`--silent' + --silent don't print informational messages + --version print version information + +MODE must be one of the following: + + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for +a more detailed description of MODE." + exit 0 + ;; + +compile) + $echo \ +"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + +execute) + $echo \ +"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + +finish) + $echo \ +"Usage: $modename [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + +install) + $echo \ +"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + +link) + $echo \ +"Usage: $modename [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to dld_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -static do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only +library objects (\`.lo' files) may be specified, and \`-rpath' is required. + +If OUTPUT-FILE ends in \`.a', then a standard library is created using \`ar' +and \`ranlib'. + +If OUTPUT-FILE ends in \`.lo' or \`.o', then a reloadable object file is +created, otherwise an executable program is created." + ;; + +uninstall) + $echo +"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + +*) + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; +esac + +echo +$echo "Try \`$modename --help' for more information about other modes." + +exit 0 + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/benchmarks/Makefile.in b/benchmarks/Makefile.in new file mode 100644 index 0000000..5b42dc9 --- /dev/null +++ b/benchmarks/Makefile.in @@ -0,0 +1,111 @@ +# Makefile for cln/benchmarks + +#### Start of system configuration section. #### + +# Directories used by "make": +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ + +# Programs used by "make": +# C compiler +CC = @CC@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +# C++ compiler +CXX = @CXX@ +CXXFLAGS = @CXXFLAGS@ +CXXCPP = @CXXCPP@ +INCLUDES = -I../include -I$(top_srcdir)/include -I$(top_srcdir)/src @GMP_INCLUDES@ -I$(srcdir) +CPPFLAGS += $(INCLUDES) +LIBTOOL = @LIBTOOL@ +LIBTOOL_LINK = $(LIBTOOL) --mode=link +MV = mv +LN = ln +RM = rm -f +@SET_MAKE@ + +#### End of system configuration section. #### + +SHELL = /bin/sh + +# Needed by $(LIBTOOL). +top_builddir = .. + +VPATH = $(srcdir) + +FILES_CC := $(notdir $(wildcard $(srcdir)/*.cc)) +FILES_CC := $(filter-out %.i.cc, $(FILES_CC)) + +FILES_I_CC := $(patsubst %.cc,%.i.cc,$(FILES_CC)) + +FILES_S := $(patsubst %.cc,%.s,$(FILES_CC)) + +FILES_O := $(patsubst %.cc,%.o,$(FILES_CC)) + +OBJECTS = $(FILES_O) + +LIBS = ../src/libcln.la -lm +LIBDEPS = ../src/libcln.la + +PROGRAMS = timebench1 timebench2a timebench2ap timebench2b +MODULES_timebench1 = timebench1 +MODULES_timebench2a = timebench2a +MODULES_timebench2ap = timebench2ap +MODULES_timebench2b = timebench2b + +all : timebench2a timebench2ap timebench2b + +%.s : %.c + $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -S $< -o $@ + +%.s : %.cc + $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -S $< -o $@ + +ifdef notyet + +%.o : %.c + $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ + +%.o : %.cc + $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ + +else + +$(FILES_O) : %.o : %.s + $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ + +endif + +%.i : %.c + $(CPP) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) $< > $@ + +%.i.cc : %.cc + $(CXXCPP) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) $< > $@ + +timebench1 : $(patsubst %,%.o,$(MODULES_timebench1)) +timebench2a : $(patsubst %,%.o,$(MODULES_timebench2a)) +timebench2ap : $(patsubst %,%.o,$(MODULES_timebench2ap)) +timebench2b : $(patsubst %,%.o,$(MODULES_timebench2b)) +$(PROGRAMS) : % : $(LIBDEPS) + $(LIBTOOL_LINK) $(CXX) $(CXXFLAGS) $(TARGET_ARCH) $(patsubst %,%.o,$(MODULES_$(*F))) $(LIBS) -o $@ + + +install : all + +installdirs : + +uninstall : + +check : all + +mostlyclean : clean + +clean : force + $(RM) *.s *.o *.a $(PROGRAMS) a.out core + +distclean : clean + $(RM) config.status config.log config.cache Makefile + +maintainer-clean : distclean + +force : diff --git a/benchmarks/README b/benchmarks/README new file mode 100644 index 0000000..96b1618 --- /dev/null +++ b/benchmarks/README @@ -0,0 +1,11 @@ +Bench1 is a benchmark for the transcendental functions I found on the LiDIA +home page. + +Some of its tests are not good because they fall into pitfalls of some systems +(for example exp(log(2)) is not a good test because in CLN, exp(x) begins +by computing x mod log(2)). Also it fails to benchmark the most basic +operations: multiplication and division. + +Bench2 is a benchmark jointly designed by the LiDIA and CLN developers to +overcome these flaws. + diff --git a/benchmarks/bench2.txt b/benchmarks/bench2.txt new file mode 100644 index 0000000..fda950c --- /dev/null +++ b/benchmarks/bench2.txt @@ -0,0 +1,63 @@ +Benchmark for Computer-Algebra Libraries +======================================== + +(jointly developed by the LiDIA and CLN developers, 1996) + +A. Elementary integer computations +B. Transcendental functions +C. Elementary polynomial functions +D. Polynomial factorization + +A. Elementary integer computations: + The tests are run with N = 100, 1000, 10000, 100000 decimal digits. + Precompute x1 = floor((sqrt(5)+1)/2 * 10^(2N)) + x2 = floor(sqrt(3) * 10^N) + x3 = 10^N+1 + Then time the following operations: + 1. Multiplication x1*x2, + 2. Division (with remainder) x1 / x2, + 3. integer_sqrt(x3), + 4. gcd(x1,x2), +A'. (from Pari) + u=1;v=1;p=1;q=1;for(k=1..1000){w=u+v;u=v;v=w;p=p*w;q=lcm(q,w);} + +B. Transcendental functions: The tests are run with a precision of + N = 100, 1000, 10000, 100000 decimal digits. + Precompute x1 = sqrt(2) + x2 = sqrt(3) + x3 = log(2) + Then time the following operations: + 1. Multiplication x1*x2, + 2. Square root sqrt(x3), + 3. pi (once), + 4. Euler's constant C (once), + 5. e (once), + 6. exp(-x1), + 7. log(x2), + 8. sin(5*x1), + 9. cos(5*x1), + 10. asin(x3), + 11. acos(x3), + 12. atan(x3), + 13. sinh(x2), + 14. cosh(x2), + 15. asinh(x3), + 16. acosh(1+x3), + 17. atanh(x3). + +C. Univariate polynomials: The tests are run with degree N = 100, 1000, and + with coefficient bound M = 10^9, 10^20. + Precompute p1(X) = sum(i=0..2N, (floor(sqrt(5)*M*i) mod M)*(-1)^i * X^i) + p2(X) = sum(i=0..N, (floor(sqrt(3)*M*i) mod M) * x^i + Then time the following operations: + 1. Multiplication p1(X)*p2(X), + 2. Pseudo-division p1(X)*c^N = p2(X)*q(X)+r(X), + 3. gcd(p1(X),p2(X)). + +D. Factorization of univariate polynomials: The benchmark by J. von zur Gathen. + For N = 500, precompute p := smallest prime >= pi*2^N. + Then time the following operation: + 1. Factorize X^N+X+1 mod p in the ring F_p[X]. + [von zur Gathen: A Polynomial Factorization Challenge. + SIGSAM Bulletin 26,2 (1992), 22-24.] + diff --git a/benchmarks/timebench1.LiDIA.cc b/benchmarks/timebench1.LiDIA.cc new file mode 100644 index 0000000..77ab958 --- /dev/null +++ b/benchmarks/timebench1.LiDIA.cc @@ -0,0 +1,167 @@ +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 1) + exit(1); + + bigfloat::precision(1000); + + cerr << "pi\n"; + { bigfloat p; + { timer t; t.set_print_mode(0); t.start_timer(); + p = Pi(); + t.stop_timer(); cerr << t << endl; + } + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { bigfloat p = Pi(); } + t.stop_timer(); cerr << t << endl; + } + cout << p << endl << endl; + } + + cerr << "gamma\n"; + { bigfloat p; + { timer t; t.set_print_mode(0); t.start_timer(); + p = Euler(); + t.stop_timer(); cerr << t << endl; + } + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { bigfloat p = Euler(); } + t.stop_timer(); cerr << t << endl; + } + cout << p << endl << endl; + } + + cerr << "e\n"; + { bigfloat p = E(); + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { bigfloat p = E(); } + t.stop_timer(); cerr << t << endl; + } + cout << p << endl << endl; + } + + cerr << "sqrt(3)\n"; + { bigfloat p = sqrt((bigfloat)3); + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { bigfloat p = sqrt((bigfloat)3); } + t.stop_timer(); cerr << t << endl; + } + cout << p << endl << endl; + } + + cerr << "exp(log(2))\n"; + { bigfloat p = exp(log((bigfloat)2)); + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { bigfloat p = exp(log((bigfloat)2)); } + t.stop_timer(); cerr << t << endl; + } + cout << p << endl << endl; + } + + cerr << "log(exp(2))\n"; + { bigfloat p = log(exp((bigfloat)2)); + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { bigfloat p = log(exp((bigfloat)2)); } + t.stop_timer(); cerr << t << endl; + } + cout << p << endl << endl; + } + + cerr << "sin(pi/3)\n"; + { bigfloat p = sin(Pi()/3); + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { bigfloat p = sin(Pi()/3); } + t.stop_timer(); cerr << t << endl; + } + cout << p << endl << endl; + } + + cerr << "cos(pi/3)\n"; + { bigfloat p = cos(Pi()/3); + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { bigfloat p = cos(Pi()/3); } + t.stop_timer(); cerr << t << endl; + } + cout << p << endl << endl; + } + + cerr << "arcsin(sqrt(3)/2)\n"; + { bigfloat p = asin(sqrt((bigfloat)3)/2); + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { bigfloat p = asin(sqrt((bigfloat)3)/2); } + t.stop_timer(); cerr << t << endl; + } + cout << p << endl << endl; + } + + cerr << "arccos(sqrt(3)/2)\n"; + { bigfloat p = acos(sqrt((bigfloat)3)/2); + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { bigfloat p = acos(sqrt((bigfloat)3)/2); } + t.stop_timer(); cerr << t << endl; + } + cout << p << endl << endl; + } + + cerr << "sinh(log(2))\n"; + { bigfloat p = sinh(log((bigfloat)2)); + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { bigfloat p = sinh(log((bigfloat)2)); } + t.stop_timer(); cerr << t << endl; + } + cout << p << endl << endl; + } + + cerr << "cosh(log(2))\n"; + { bigfloat p = cosh(log((bigfloat)2)); + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { bigfloat p = cosh(log((bigfloat)2)); } + t.stop_timer(); cerr << t << endl; + } + cout << p << endl << endl; + } + + cerr << "arsinh(pi)\n"; + { bigfloat p = asinh(Pi()); + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { bigfloat p = asinh(Pi()); } + t.stop_timer(); cerr << t << endl; + } + cout << p << endl << endl; + } + + cerr << "arcosh(pi)\n"; + { bigfloat p = acosh(Pi()); + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { bigfloat p = acosh(Pi()); } + t.stop_timer(); cerr << t << endl; + } + cout << p << endl << endl; + } + +} + + + diff --git a/benchmarks/timebench1.cc b/benchmarks/timebench1.cc new file mode 100644 index 0000000..e2bad84 --- /dev/null +++ b/benchmarks/timebench1.cc @@ -0,0 +1,198 @@ +// Benchmarks from the LiDIA home page + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Timings on Linux i486 33 MHz, 1000 decimal places = 104 32-bit words. +// Function LiDIA Pari CLISP CLN +// pi 0.17 / 0 0.38 / 0 0.12 / 0 +// gamma 7.51 / 0 -- 3.75 / 0 +// e 1.20 5.06 / 0.20 0.66 / 0.10 +// multiplication 0.018 0.010 0.010 +// sqrt(3) 0.051 0.012 0.01 +// exp(log(2)) 3.13 0.08 / 3.94 0.04 +// log(exp(2)) 3.07 4.93 / 2.75 1.34 +// sin(pi/3) 1.53 2.98 0.58 +// cos(pi/3) 1.59 2.16 0.58 +// arcsin(sqrt(3)/2) 4.24 2.22 1.26 +// arccos(sqrt(3)/2) 4.26 2.22 1.26 +// sinh(log(2)) 3.16 2.02 0.03 +// cosh(log(2)) 3.17 2.09 0.04 +// arsinh(pi) 1.93 2.62 0.65 +// arcosh(pi) 1.95 2.26 0.69 +// (Versions: Pari 1.39, clisp-1996-07-22, cln-1996-11-17.) + +// Timings on Solaris Sparc 20, 75 MHz, 1000 decimal places = 104 32-bit words. +// Function LiDIA Pari CLISP CLN +// pi 0.06 / 0 0.04 / 0 0.028 / 0 +// gamma 1.98 / 0 1.26 / 0 1.99 / 0 +// e 0 0.15 0.15 +// multiplication +// sqrt(3) 0.0025 0.01 0.0025 +// exp(log(2)) 0.25 0.39 0.010 +// log(exp(2)) 0.21 0.39 0.31 +// sin(pi/3) 0.071 0.18 0.13 +// cos(pi/3) 0.070 0.19 0.13 +// arcsin(sqrt(3)/2) 0.30 0.55 0.27 +// arccos(sqrt(3)/2) 0.30 0.55 0.27 +// sinh(log(2)) 0.25 0.41 0.010 +// cosh(log(2)) 0.25 0.40 0.010 +// arsinh(pi) 0.16 0.26 0.144 +// arcosh(pi) 0.16 0.26 0.153 +// (Versions: Pari 1.39, LiDIA 1.2.1 with libI, cln-1996-10-13.) + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 1) + exit(1); + + fprint(cl_stderr, "Number of repetitions: "); + fprintdecimal(cl_stderr, repetitions); + fprint(cl_stderr, "\n"); + + cl_float_format_t prec = cl_float_format(1000); + + fprint(cl_stderr, "pi\n"); + { cl_F p; + { CL_TIMING; p = cl_pi(prec); } + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_F p = cl_pi(prec); } + } + cout << p << endl << endl; + } + + fprint(cl_stderr, "gamma\n"); + { cl_F p; + { CL_TIMING; p = cl_eulerconst(prec); } + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_F p = cl_eulerconst(prec); } + } + cout << p << endl << endl; + } + + fprint(cl_stderr, "e\n"); + { cl_F p = cl_exp1(prec); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_F p = cl_exp1(prec); } + } + cout << p << endl << endl; + } + + fprint(cl_stderr, "sqrt(3)\n"); + { cl_R p = sqrt(cl_float(3,prec)); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_R p = sqrt(cl_float(3,prec)); } + } + cout << p << endl << endl; + } + + fprint(cl_stderr, "exp(log(2))\n"); + { cl_N p = exp(log(cl_float(2,prec))); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_N p = exp(log(cl_float(2,prec))); } + } + cout << p << endl << endl; + } + + fprint(cl_stderr, "log(exp(2))\n"); + { cl_N p = log(exp(cl_float(2,prec))); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_N p = log(exp(cl_float(2,prec))); } + } + cout << p << endl << endl; + } + + fprint(cl_stderr, "sin(pi/3)\n"); + { cl_R p = sin(cl_pi(prec)/3); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_R p = sin(cl_pi(prec)/3); } + } + cout << p << endl << endl; + } + + fprint(cl_stderr, "cos(pi/3)\n"); + { cl_R p = cos(cl_pi(prec)/3); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_R p = cos(cl_pi(prec)/3); } + } + cout << p << endl << endl; + } + + fprint(cl_stderr, "arcsin(sqrt(3)/2)\n"); + { cl_N p = asin(sqrt(cl_float(3,prec))/2); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_N p = asin(sqrt(cl_float(3,prec))/2); } + } + cout << p << endl << endl; + } + + fprint(cl_stderr, "arccos(sqrt(3)/2)\n"); + { cl_N p = acos(sqrt(cl_float(3,prec))/2); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_N p = acos(sqrt(cl_float(3,prec))/2); } + } + cout << p << endl << endl; + } + + fprint(cl_stderr, "sinh(log(2))\n"); + { cl_N p = sinh(log(cl_float(2,prec))); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_N p = sinh(log(cl_float(2,prec))); } + } + cout << p << endl << endl; + } + + fprint(cl_stderr, "cosh(log(2))\n"); + { cl_N p = cosh(log(cl_float(2,prec))); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_N p = cosh(log(cl_float(2,prec))); } + } + cout << p << endl << endl; + } + + fprint(cl_stderr, "arsinh(pi)\n"); + { cl_N p = asinh(cl_pi(prec)); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_N p = asinh(cl_pi(prec)); } + } + cout << p << endl << endl; + } + + fprint(cl_stderr, "arcosh(pi)\n"); + { cl_N p = acosh(cl_pi(prec)); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_N p = acosh(cl_pi(prec)); } + } + cout << p << endl << endl; + } + +} diff --git a/benchmarks/timebench1.gp b/benchmarks/timebench1.gp new file mode 100644 index 0000000..9ca1d49 --- /dev/null +++ b/benchmarks/timebench1.gp @@ -0,0 +1,30 @@ +\precision=1000 +# +pi +pi +euler +euler +exp(1) +exp(1) +sqrt(3) +sqrt(3) +exp(log(2)) +exp(log(2)) +log(exp(2)) +log(exp(2)) +sin(pi/3) +sin(pi/3) +cos(pi/3) +cos(pi/3) +asin(sqrt(3)/2) +asin(sqrt(3)/2) +acos(sqrt(3)/2) +acos(sqrt(3)/2) +sinh(log(2)) +sinh(log(2)) +cosh(log(2)) +cosh(log(2)) +asinh(pi) +asinh(pi) +acosh(pi) +acosh(pi) diff --git a/benchmarks/timebench1.lsp b/benchmarks/timebench1.lsp new file mode 100644 index 0000000..77dea48 --- /dev/null +++ b/benchmarks/timebench1.lsp @@ -0,0 +1,69 @@ +(progn + (format t "~%pi") + (time (setf (long-float-digits) 3322)) + (time pi) +) + +(progn + (format t "~%gamma not yet implemented in CLISP") +) + +(progn + (format t "~%e") + (time (exp 1L0)) +) + +(progn + (format t "~%sqrt(3)") + (time (sqrt 3L0)) +) + +(progn + (format t "~%exp(log(2))") + (time (exp (log 2L0))) +) + +(progn + (format t "~%log(exp(2))") + (time (log (exp 2L0))) +) + +(progn + (format t "~%sin(pi/3)") + (time (sin (/ pi 3))) +) + +(progn + (format t "~%cos(pi/3)") + (time (cos (/ pi 3))) +) + +(progn + (format t "~%arcsin(sqrt(3)/2)") + (time (asin (/ (sqrt 3L0) 2))) +) + +(progn + (format t "~%arccos(sqrt(3)/2)") + (time (acos (/ (sqrt 3L0) 2))) +) + +(progn + (format t "~%sinh(log(2))") + (time (sinh (log 2L0))) +) + +(progn + (format t "~%cosh(log(2))") + (time (cosh (log 2L0))) +) + +(progn + (format t "~%arsinh(pi)") + (time (asinh pi)) +) + +(progn + (format t "~%arcosh(pi)") + (time (acosh pi)) +) diff --git a/benchmarks/timebench2.results b/benchmarks/timebench2.results new file mode 100644 index 0000000..6de8af5 --- /dev/null +++ b/benchmarks/timebench2.results @@ -0,0 +1,133 @@ +Timings on Linux i486 33 MHz + +A. + +N=100 + +Function LiDIA/libI LiDIA/cln Pari CLN-1996-11-17 + multiplication 0.00046 0.00042 0.001 0.00042 + division 0.00041 0.00034 0.001 0.00033 + isqrt 0.026 0.00013 0.002 0.00013 + gcd 0.00595 0.00170 0.009 0.00169 + +N=1000 + +Function LiDIA/libI LiDIA/cln Pari CLN-1996-11-17 + multiplication 0.022 0.019 0.2 0.019 + division 0.021 0.019 0.15 0.019 + isqrt 6.49 0.002 0.1 0.002 + gcd 0.166 0.070 0.5 0.071 + +N=10000 + +Function LiDIA/libI LiDIA/cln Pari CLN-1996-11-17 + multiplication 2.22 0.72 7 0.72 + division 1.98 1.39 3.8 1.38 + isqrt 5509 0.17 12.1 0.17 + gcd 38.9 5.4 --- 5.4 + +N=100000 + +Function LiDIA/libI LiDIA/cln Pari CLN-1996-11-17 + multiplication 6.9 + division 20.4 + isqrt 10.2 + gcd 428 + +A'. + LiDIA/libI LiDIA/cln Pari CLN-1996-11-17 +N=100 0.2 0.07 +N=200 1.4 0.70 +N=1000 525 271 + +B. + +N=100 + +Function LiDIA/libI LiDIA/cln Pari CLN-1997-02-08 + multiplication 0.00054 0.00058 0.000 0.00026 + sqrt 0.0033 0.0040 0.002 0.00028 + pi 0.01 0.02 0.005 0 + eulerconst 0.27 0.40 0.12 0.17 + e 0.02 0.01 0.011 0 + exp 0.021 0.025 0.012 0.014 + log 0.041 0.051 0.021 0.014 + sin 0.021 0.028 0.014 0.013 + cos 0.021 0.027 0.012 0.012 + asin 0.072 0.081 0.047 0.015 + acos 0.073 0.081 0.048 0.016 + atan 0.067 0.076 0.039 0.014 + sinh 0.022 0.025 0.012 0.014 + cosh 0.022 0.025 0.012 0.014 + asinh 0.045 0.056 0.026 0.013 + acosh 0.048 0.060 0.029 0.015 + atanh 0.049 0.061 0.028 0.015 + +N=1000 + +Function LiDIA/libI LiDIA/cln Pari CLN-1997-02-08 + multiplication 0.013 0.010 0.018 0.010 + sqrt 0.048 0.042 0.049 0.011 + pi 0.28 0.25 0.174 0.12 + eulerconst 10.0 9.4 7.6 4.6 + e 0.12 0.09 1.19 0.06 + exp 1.11 0.73 1.33 0.70 + log 1.48 1.28 1.81 0.65 + sin 0.76 0.66 1.56 0.51 + cos 0.75 0.65 1.62 0.49 + asin 3.03 2.52 4.10 0.84 + acos 3.03 2.52 4.10 0.84 + atan 2.93 2.44 3.96 0.79 + sinh 1.11 0.73 1.31 0.71 + cosh 1.11 0.73 1.31 0.71 + asinh 1.60 1.40 1.89 0.65 + acosh 1.65 1.44 1.98 0.73 + atanh 1.60 1.40 1.88 0.69 + +N=10000 + +Function LiDIA/libI LiDIA/cln Pari CLN-1997-02-08 + multiplication 0.51 0.36 1.75 0.37 + sqrt 4.58 3.36 5.6 0.95 + pi 23.8 17.8 16.7 6.0 + eulerconst 1045 817 1128 327 + e 5.5 3.30 360 2.39 + exp 130 75.1 373 40.2 + log 301 224 562 32.3 + sin 83.6 61.9 475 53.4 + cos 83.5 61.7 474 52.1 + asin 866 567 1281 72.4 + acos 865 567 1282 72.4 + atan 860 561 1274 69.9 + sinh 130 75.1 378 41.5 + cosh 129 75.1 377 41.4 + asinh 313 232 578 31.1 + acosh 311 231 583 36.9 + atanh 314 233 573 36.6 + +N=100000 + +Function LiDIA/libI LiDIA/cln Pari CLN-1996-11-17 + multiplication 19.3 4.63 4.58 + sqrt 298 55.8 19.5 + pi 199 122 + eulerconst 6952 + e 42 + exp 860 + log 735 + sin 1483 + cos 1571 + asin 1440 + acos 1441 + atan 1407 + sinh 877 + cosh 877 + asinh 758 + acosh 813 + atanh 813 + +Versions: + LiDIA 1.2.1 with libI + LiDIA 1.2.1 with cln-1996-11-17 (based on gmp 2.0.2) + Pari 1.39 + cln-1997-02-08 and cln-1996-11-17 (both based on gmp 2.0.2) diff --git a/benchmarks/timebench2.sh b/benchmarks/timebench2.sh new file mode 100644 index 0000000..c6cea79 --- /dev/null +++ b/benchmarks/timebench2.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +./timebench2a -n 100 -r 1000 > /dev/null +./timebench2a -n 1000 -r 100 > /dev/null +./timebench2a -n 10000 > /dev/null +./timebench2a -n 100000 > /dev/null +./timebench2ap diff --git a/benchmarks/timebench2a.LiDIA.cc b/benchmarks/timebench2a.LiDIA.cc new file mode 100644 index 0000000..1662cac --- /dev/null +++ b/benchmarks/timebench2a.LiDIA.cc @@ -0,0 +1,77 @@ +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int digits = 100; + int repetitions = 1; + while (argc >= 3) { + if (!strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + continue; + } + if (!strcmp(argv[1],"-n")) { + digits = atoi(argv[2]); + argc -= 2; argv += 2; + continue; + } + break; + } + if (argc < 1) + exit(1); + + cerr << "Number of digits: " << digits << "\n"; + cerr << "Number of repetitions: " << repetitions << "\n"; + + bigint pow; power(pow, (bigint)10,digits); + bigfloat::precision(digits*2); + bigint x1; truncate(x1, ((sqrt((bigfloat)5)+1)/2) * (pow*pow)); + bigfloat::precision(digits); + bigint x2; truncate(x2, sqrt((bigfloat)3) * pow); + bigint x3 = pow+1; + + cerr << "multiplication\n"; + { bigint r = x1*x2; + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { bigint r = x1*x2; } + t.stop_timer(); cerr << t << endl; + } + cout << r << endl << endl; + } + + cerr << "division\n"; + { bigint q; bigint r; div_rem(q,r, x1,x2); + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { bigint q; bigint r; div_rem(q,r, x1,x2); } + t.stop_timer(); cerr << t << endl; + } + cout << q << endl << r << endl << endl; + } + + cerr << "isqrt\n"; + { bigint r; sqrt(r, x3); + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { bigint r; sqrt(r, x3); } + t.stop_timer(); cerr << t << endl; + } + cout << r << endl << endl; + } + + cerr << "gcd\n"; + { bigint r = gcd(x1,x2); + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { bigint r = gcd(x1,x2); } + t.stop_timer(); cerr << t << endl; + } + cout << r << endl << endl; + } + +} diff --git a/benchmarks/timebench2a.cc b/benchmarks/timebench2a.cc new file mode 100644 index 0000000..fc27c1c --- /dev/null +++ b/benchmarks/timebench2a.cc @@ -0,0 +1,81 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int digits = 100; + int repetitions = 1; + while (argc >= 3) { + if (!strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + continue; + } + if (!strcmp(argv[1],"-n")) { + digits = atoi(argv[2]); + argc -= 2; argv += 2; + continue; + } + break; + } + if (argc < 1) + exit(1); + + fprint(cl_stderr, "Number of digits: "); + fprintdecimal(cl_stderr, digits); + fprint(cl_stderr, "\n"); + fprint(cl_stderr, "Number of repetitions: "); + fprintdecimal(cl_stderr, repetitions); + fprint(cl_stderr, "\n"); + + cl_float_format_t prec = cl_float_format(digits); + cl_float_format_t prec2 = cl_float_format(digits*2); + cl_I pow = expt_pos(10,digits); + cl_I x1 = floor1((sqrt(cl_float(5,prec2))+1)/2 * expt_pos(pow,2)); + cl_I x2 = floor1(sqrt(cl_float(3,prec)) * pow); + cl_I x3 = pow+1; + + fprint(cl_stderr, "multiplication\n"); + { cl_I r = x1*x2; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { r = x1*x2; } + } + cout << r << endl << endl; + } + + fprint(cl_stderr, "division\n"); + { cl_I_div_t qr = floor2(x1,x2); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { qr = floor2(x1,x2); } + } + cout << qr.quotient << endl << qr.remainder << endl << endl; + } + + fprint(cl_stderr, "isqrt\n"); + { cl_I r = isqrt(x3); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { r = isqrt(x3); } + } + cout << r << endl << endl; + } + + fprint(cl_stderr, "gcd\n"); + { cl_I r = gcd(x1,x2); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { r = gcd(x1,x2); } + } + cout << r << endl << endl; + } + +} diff --git a/benchmarks/timebench2a.gp b/benchmarks/timebench2a.gp new file mode 100644 index 0000000..405e551 --- /dev/null +++ b/benchmarks/timebench2a.gp @@ -0,0 +1,25 @@ +n=100 +\precision=2*n +x1=floor((sqrt(5)+1)/2 * 10^(2*n)) +\precision=n +x2=floor(sqrt(3) * 10^n) +\precision=15 +x3=10^n+1 +# +0 +x1*x2 +0 +x1*x2 +0 +divres(x1,x2) +0 +divres(x1,x2) +0 +isqrt(x3) +0 +isqrt(x3) +0 +gcd(x1,x2) +0 +gcd(x1,x2) +0 diff --git a/benchmarks/timebench2ap.cc b/benchmarks/timebench2ap.cc new file mode 100644 index 0000000..561ef71 --- /dev/null +++ b/benchmarks/timebench2ap.cc @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int limit = 1000; + int repetitions = 1; + while (argc >= 3) { + if (!strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + continue; + } + if (!strcmp(argv[1],"-l")) { + limit = atoi(argv[2]); + argc -= 2; argv += 2; + continue; + } + break; + } + if (argc < 1) + exit(1); + + fprint(cl_stderr, "Limit: "); + fprintdecimal(cl_stderr, limit); + fprint(cl_stderr, "\n"); + fprint(cl_stderr, "Number of repetitions: "); + fprintdecimal(cl_stderr, repetitions); + fprint(cl_stderr, "\n"); + + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_I u = 1, v = 1, p = 1, q = 1; + for (int k = 1; k <= limit; k++) + { cl_I w = u+v; + u = v; v = w; + p = p*w; q = lcm(q,w); + } + } + } + +} diff --git a/benchmarks/timebench2ap.gp b/benchmarks/timebench2ap.gp new file mode 100644 index 0000000..e39f41d --- /dev/null +++ b/benchmarks/timebench2ap.gp @@ -0,0 +1,4 @@ +u=1;v=1;p=1;q=1; +# +for(k=1,1000,w=u+v;u=v;v=w;p=p*w;q=lcm(q,w);) + diff --git a/benchmarks/timebench2b.LiDIA.cc b/benchmarks/timebench2b.LiDIA.cc new file mode 100644 index 0000000..c71ed45 --- /dev/null +++ b/benchmarks/timebench2b.LiDIA.cc @@ -0,0 +1,202 @@ +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int digits = 100; + int repetitions = 1; + while (argc >= 3) { + if (!strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + continue; + } + if (!strcmp(argv[1],"-n")) { + digits = atoi(argv[2]); + argc -= 2; argv += 2; + continue; + } + break; + } + if (argc < 1) + exit(1); + + cerr << "Number of digits: " << digits << "\n"; + cerr << "Number of repetitions (except for pi,euler,e): " << repetitions << "\n"; + + bigfloat::precision(digits); + bigfloat x1 = sqrt((bigfloat)2); + bigfloat x2 = sqrt((bigfloat)3); + bigfloat x3 = log((bigfloat)2); + + cerr << "multiplication\n"; + { bigfloat r = x1*x2; + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { r = x1*x2; } + t.stop_timer(); cerr << t << endl; + } + cout << r << endl << endl; + } + + cerr << "sqrt\n"; + { bigfloat r = sqrt(x3); + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { r = sqrt(x3); } + t.stop_timer(); cerr << t << endl; + } + cout << r << endl << endl; + } + + cerr << "pi\n"; + { bigfloat r; + { timer t; t.set_print_mode(0); t.start_timer(); + r = Pi(); + t.stop_timer(); cerr << t << endl; + } + cout << r << endl << endl; + } + + cerr << "eulerconst\n"; + { bigfloat r; + { timer t; t.set_print_mode(0); t.start_timer(); + r = Euler(); + t.stop_timer(); cerr << t << endl; + } + cout << r << endl << endl; + } + + cerr << "e\n"; + { bigfloat r; + { timer t; t.set_print_mode(0); t.start_timer(); + r = E(); + t.stop_timer(); cerr << t << endl; + } + cout << r << endl << endl; + } + + cerr << "exp\n"; + { bigfloat r = exp(-x1); + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { r = exp(-x1); } + t.stop_timer(); cerr << t << endl; + } + cout << r << endl << endl; + } + + cerr << "log\n"; + { bigfloat r = log(x2); + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { r = log(x2); } + t.stop_timer(); cerr << t << endl; + } + cout << r << endl << endl; + } + + cerr << "sin\n"; + { bigfloat r = sin(5*x1); + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { r = sin(5*x1); } + t.stop_timer(); cerr << t << endl; + } + cout << r << endl << endl; + } + + cerr << "cos\n"; + { bigfloat r = cos(5*x1); + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { r = cos(5*x1); } + t.stop_timer(); cerr << t << endl; + } + cout << r << endl << endl; + } + + cerr << "asin\n"; + { bigfloat r = asin(x3); + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { r = asin(x3); } + t.stop_timer(); cerr << t << endl; + } + cout << r << endl << endl; + } + + cerr << "acos\n"; + { bigfloat r = acos(x3); + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { r = acos(x3); } + t.stop_timer(); cerr << t << endl; + } + cout << r << endl << endl; + } + + cerr << "atan\n"; + { bigfloat r = atan(x3); + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { r = atan(x3); } + t.stop_timer(); cerr << t << endl; + } + cout << r << endl << endl; + } + + cerr << "sinh\n"; + { bigfloat r = sinh(x2); + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { r = sinh(x2); } + t.stop_timer(); cerr << t << endl; + } + cout << r << endl << endl; + } + + cerr << "cosh\n"; + { bigfloat r = cosh(x2); + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { r = cosh(x2); } + t.stop_timer(); cerr << t << endl; + } + cout << r << endl << endl; + } + + cerr << "asinh\n"; + { bigfloat r = asinh(x3); + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { r = asinh(x3); } + t.stop_timer(); cerr << t << endl; + } + cout << r << endl << endl; + } + + cerr << "acosh\n"; + { bigfloat r = acosh(1+x3); + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { r = acosh(1+x3); } + t.stop_timer(); cerr << t << endl; + } + cout << r << endl << endl; + } + + cerr << "atanh\n"; + { bigfloat r = atanh(x3); + { timer t; t.set_print_mode(0); t.start_timer(); + for (int rep = repetitions; rep > 0; rep--) + { r = atanh(x3); } + t.stop_timer(); cerr << t << endl; + } + cout << r << endl << endl; + } + +} diff --git a/benchmarks/timebench2b.cc b/benchmarks/timebench2b.cc new file mode 100644 index 0000000..f683045 --- /dev/null +++ b/benchmarks/timebench2b.cc @@ -0,0 +1,190 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int digits = 100; + int repetitions = 1; + while (argc >= 3) { + if (!strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + continue; + } + if (!strcmp(argv[1],"-n")) { + digits = atoi(argv[2]); + argc -= 2; argv += 2; + continue; + } + break; + } + if (argc < 1) + exit(1); + + fprint(cl_stderr, "Number of digits: "); + fprintdecimal(cl_stderr, digits); + fprint(cl_stderr, "\n"); + fprint(cl_stderr, "Number of repetitions (except for pi,euler,e): "); + fprintdecimal(cl_stderr, repetitions); + fprint(cl_stderr, "\n"); + + cl_float_format_t prec = cl_float_format(digits); + cl_F x1 = sqrt(cl_float(2,prec)); + cl_F x2 = sqrt(cl_float(3,prec)); + cl_F x3 = The(cl_F)(log(cl_float(2,prec))); + + fprint(cl_stderr, "multiplication\n"); + { cl_F r = x1*x2; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { r = x1*x2; } + } + cout << r << endl << endl; + } + + fprint(cl_stderr, "sqrt\n"); + { cl_F r = sqrt(x3); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { r = sqrt(x3); } + } + cout << r << endl << endl; + } + + fprint(cl_stderr, "pi\n"); + { cl_F r; + { CL_TIMING; r = cl_pi(prec); } + cout << r << endl << endl; + } + + fprint(cl_stderr, "eulerconst\n"); + { cl_F r; + { CL_TIMING; r = cl_eulerconst(prec); } + cout << r << endl << endl; + } + + fprint(cl_stderr, "e\n"); + { cl_F r; + { CL_TIMING; r = cl_exp1(prec); } + cout << r << endl << endl; + } + + fprint(cl_stderr, "exp\n"); + { cl_F r = exp(-x1); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { r = exp(-x1); } + } + cout << r << endl << endl; + } + + fprint(cl_stderr, "log\n"); + { cl_N r = log(x2); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { r = log(x2); } + } + cout << r << endl << endl; + } + + fprint(cl_stderr, "sin\n"); + { cl_R r = sin(5*x1); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { r = sin(5*x1); } + } + cout << r << endl << endl; + } + + fprint(cl_stderr, "cos\n"); + { cl_R r = cos(5*x1); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { r = cos(5*x1); } + } + cout << r << endl << endl; + } + + fprint(cl_stderr, "asin\n"); + { cl_N r = asin(x3); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { r = asin(x3); } + } + cout << r << endl << endl; + } + + fprint(cl_stderr, "acos\n"); + { cl_N r = acos(x3); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { r = acos(x3); } + } + cout << r << endl << endl; + } + + fprint(cl_stderr, "atan\n"); + { cl_F r = atan(x3); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { r = atan(x3); } + } + cout << r << endl << endl; + } + + fprint(cl_stderr, "sinh\n"); + { cl_F r = sinh(x2); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { r = sinh(x2); } + } + cout << r << endl << endl; + } + + fprint(cl_stderr, "cosh\n"); + { cl_F r = cosh(x2); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { r = cosh(x2); } + } + cout << r << endl << endl; + } + + fprint(cl_stderr, "asinh\n"); + { cl_N r = asinh(x3); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { r = asinh(x3); } + } + cout << r << endl << endl; + } + + fprint(cl_stderr, "acosh\n"); + { cl_N r = acosh(1+x3); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { r = acosh(1+x3); } + } + cout << r << endl << endl; + } + + fprint(cl_stderr, "atanh\n"); + { cl_N r = atanh(x3); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { r = atanh(x3); } + } + cout << r << endl << endl; + } + +} diff --git a/benchmarks/timebench2b.gp b/benchmarks/timebench2b.gp new file mode 100644 index 0000000..b0a3d2b --- /dev/null +++ b/benchmarks/timebench2b.gp @@ -0,0 +1,36 @@ +\precision=100 +x1=sqrt(2) +x2=sqrt(3) +x3=log(2) +# +x1*x2 +x1*x2 +sqrt(x3) +sqrt(x3) +pi +euler +exp(1) +exp(-x1) +exp(-x1) +log(x2) +log(x2) +sin(5*x1) +sin(5*x1) +cos(5*x1) +cos(5*x1) +asin(x3) +asin(x3) +acos(x3) +acos(x3) +atan(x3) +atan(x3) +sinh(x2) +sinh(x2) +cosh(x2) +cosh(x2) +asinh(x3) +asinh(x3) +acosh(1+x3) +acosh(1+x3) +atanh(x3) +atanh(x3) diff --git a/benchmarks/timebench2c.gp b/benchmarks/timebench2c.gp new file mode 100644 index 0000000..692e0d9 --- /dev/null +++ b/benchmarks/timebench2c.gp @@ -0,0 +1,15 @@ +n=100 +lm=9 +m=10^lm +\precision=lm+5 +root3=sqrt(3) +root5=sqrt(5) +p1 = sum(0,j=0,2*n,divres(floor(root5*m*j),m)[2]*(-1)^j*x^j) +p2 = sum(0,j=0,n,divres(floor(root3*m*j),m)[2]*x^j) +# +p1*p2 +p1*p2 +divres(p1,p2) +divres(p1,p2) +gcd(p1,p2) +gcd(p1,p2) diff --git a/benchmarks/timebench2d.gp b/benchmarks/timebench2d.gp new file mode 100644 index 0000000..a0560a6 --- /dev/null +++ b/benchmarks/timebench2d.gp @@ -0,0 +1,5 @@ +n=500 +\precision=floor(n*log(2)/log(10)+5) +p=nextprime(ceil(pi*2^500)) +# +factor(mod(x^n+x+1,p)) diff --git a/configure b/configure new file mode 100755 index 0000000..6501c8e --- /dev/null +++ b/configure @@ -0,0 +1,3233 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.13 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --enable-shared build shared libraries [default=no] + --enable-shared=PKGS only build shared libraries if the current package + appears as an element in the PKGS list" +ac_help="$ac_help + --enable-static build static libraries [default=yes] + --enable-static=PKGS only build shared libraries if the current package + appears as an element in the PKGS list" +ac_help="$ac_help + --with-gnu-ld assume the C compiler uses GNU ld [default=no]" +ac_help="$ac_help + --with-gmp use fast GNU gmp low-level functions" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.13" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=src/integer/gcd/cl_I_gcd.cc + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' ac_tt= + else + ac_n=-n ac_c= ac_t= ac_tt=' + ' + fi +else + ac_n= ac_c='\c' ac_t= ac_tt=' + ' +fi + + + +echo $ac_n "checking whether ${MAKE-make} sets \$(MAKE)""... $ac_c" 1>&6 +echo "configure:541: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + +extrasub="$extrasub"' +/@subdir@/{ +h +g +s/@subdir@/src/ +p +g +s/@subdir@/tests/ +p +g +s/@subdir@/benchmarks/ +p +g +s/@subdir@/examples/ +p +g +s/@subdir@/doc/ +p +d +} +' +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:591: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:621: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_prog_rejected=no + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + # Extract the first word of "cl", so it can be a program name with args. +set dummy cl; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:672: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="cl" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + ;; + esac + fi + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:704: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext << EOF + +#line 715 "configure" +#include "confdefs.h" + +int main(){return(0);} +EOF +if { (eval echo configure:720: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:746: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:751: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +ac_test_CFLAGS="${CFLAGS+set}" +ac_save_CFLAGS="$CFLAGS" +CFLAGS= +if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" +else + if test "$GCC" = yes; then + # Add "-O" to both the CC and CPP commands, to eliminate possible confusion + # that results from __OPTIMIZE__ being defined for CC but not CPP. + if echo "$CC " | grep ' -O[1-9 ]' > /dev/null 2>&1; then + : # already optimizing + else + CC="$CC -O" + ac_cv_prog_CC="$CC" + fi + else + CFLAGS= + fi +fi + + echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:795: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + if test -n "$GCC"; then + # Suppress warning messages. + CPP="$CPP -w" + fi + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. On NeXTstep 3.1 the same holds for /lib/cpp; use + # "cc -E -traditional-cpp" instead. + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:821: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + ac_have_cpp=1 +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* + if test -z "$ac_have_cpp"; then + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:841: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + ac_have_cpp=1 +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* + if test -n "$ac_have_cpp"; then + CC="${CC-cc} -traditional-cpp" + else + CPP="${CC-cc} -nologo -E" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:863: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + ac_have_cpp=1 +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* + if test -n "$ac_have_cpp"; then + CC="${CC-cc} -nologo" + else + CPP=/lib/cpp + fi + fi + fi + ac_cv_prog_CC="$CC" + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + + for ac_prog in $CCC c++ g++ gcc CC cxx cc++ cl +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:895: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CXX="$ac_prog" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CXX="$ac_cv_prog_CXX" +if test -n "$CXX"; then + echo "$ac_t""$CXX" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$CXX" && break +done +test -n "$CXX" || CXX="gcc" + + +echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:927: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5 + +ac_ext=C +# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cxx_cross + +cat > conftest.$ac_ext << EOF + +#line 938 "configure" +#include "confdefs.h" + +int main(){return(0);} +EOF +if { (eval echo configure:943: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cxx_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cxx_cross=no + else + ac_cv_prog_cxx_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cxx_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cxx_works" 1>&6 +if test $ac_cv_prog_cxx_works = no; then + { echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:969: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6 +cross_compiling=$ac_cv_prog_cxx_cross + +echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6 +echo "configure:974: checking whether we are using GNU C++" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.C <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gxx=yes +else + ac_cv_prog_gxx=no +fi +fi +echo "$ac_t""$ac_cv_prog_gxx" 1>&6 + +if test $ac_cv_prog_gxx = yes; then + GXX=yes +else + GXX= +fi + +ac_test_CXXFLAGS="${CXXFLAGS+set}" +ac_save_CXXFLAGS="$CXXFLAGS" +CXXFLAGS= +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS="$ac_save_CXXFLAGS" +else + if test "$GXX" = yes; then + # Add "-O" to both the CXX and CXXCPP commands, to eliminate possible confu- + # sion that results from __OPTIMIZE__ being defined for CXX but not CXXCPP. + if echo "$CXX " | grep ' -O[1-9 ]' > /dev/null; then + : # already optimizing + else + CXX="$CXX -O" + ac_cv_prog_CXX="$CXX" + fi + else + CXXFLAGS= + fi +fi + + echo $ac_n "checking how to run the C++ preprocessor""... $ac_c" 1>&6 +echo "configure:1018: checking how to run the C++ preprocessor" >&5 +if test -z "$CXXCPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CXXCPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_ext=C +# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cxx_cross + CXXCPP="${CXX-g++} -E" + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1036: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CXXCPP=/lib/cpp +fi +rm -f conftest* + ac_cv_prog_CXXCPP="$CXXCPP" +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross +fi +fi +CXXCPP="$ac_cv_prog_CXXCPP" +echo "$ac_t""$CXXCPP" 1>&6 + + +echo $ac_n "checking for underscore in external names""... $ac_c" 1>&6 +echo "configure:1062: checking for underscore in external names" >&5 +if eval "test \"`echo '$''{'cl_cv_prog_as_underscore'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + +cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } >/dev/null 2>&1 +if grep _foo conftest.s >/dev/null ; then + cl_cv_prog_as_underscore=yes +else + cl_cv_prog_as_underscore=no +fi +rm -f conftest* + +fi +echo "$ac_t""$cl_cv_prog_as_underscore" 1>&6 +if test $cl_cv_prog_as_underscore = yes; then + AS_UNDERSCORE=true + cat >> confdefs.h <<\EOF +#define ASM_UNDERSCORE 1 +EOF + +else + AS_UNDERSCORE=false +fi + + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1094: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RANLIB="ranlib" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB="true" +fi +fi +RANLIB="$ac_cv_prog_RANLIB" +if test -n "$RANLIB"; then + echo "$ac_t""$RANLIB" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + # Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:1132: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'cl_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + for ac_prog in ginstall installbsd scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + # OSF/1 installbsd also uses dspmsg, but is usable. + : + else + if test $ac_prog = installbsd && + grep src/bos $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX installbsd doesn't work without option "-g". + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + fi + done + ;; + esac + done + IFS="$ac_save_ifs" + # As a last resort, use cp. + test -z "$cl_cv_path_install" && cl_cv_path_install="cp" + +fi + INSTALL="$cl_cv_path_install" +fi +echo "$ac_t""$INSTALL" 1>&6 +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='$(INSTALL)' +if test -z "$INSTALL_DATA"; then + case "$INSTALL" in + cp | */cp ) INSTALL_DATA='$(INSTALL)' ;; + * ) INSTALL_DATA='$(INSTALL) -m 644' ;; + esac +fi + + ac_aux_dir=${srcdir}/autoconf +echo $ac_n "checking host system type""... $ac_c" 1>&6 +echo "configure:1186: checking host system type" >&5 +if eval "test \"`echo '$''{'cl_cv_host'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +# Make sure we can run config.sub. +if $ac_config_sub sun4 >/dev/null 2>&1; then : +else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } +fi +host_alias=$host +case "$host_alias" in +NONE) + case $nonopt in + NONE) host_alias=`export CC; $ac_config_guess` ;; + *) host_alias=$nonopt ;; + esac ;; +esac +# Don't fail just because the system is not listed in GNU's database. +if test -n "$host_alias"; then + host=`$ac_config_sub $host_alias` +else + host=unknown-unknown-unknown +fi +cl_cv_host="$host" + +fi +echo "$ac_t""$cl_cv_host" 1>&6 +host="$cl_cv_host" +host_cpu=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'` + + +case "$host_cpu" in + i[4567]86 ) + host_cpu=i386 + ;; + alphaev[4-7] | alphaev56 | alphapca5[67] ) + host_cpu=alpha + ;; + hppa1.0 | hppa1.1 | hppa2.0 ) + host_cpu=hppa + ;; + powerpc ) + host_cpu=rs6000 + ;; + c1 | c2 | c32 | c34 | c38 | c4 ) + host_cpu=convex + ;; + mips ) + echo $ac_n "checking for 64-bit MIPS""... $ac_c" 1>&6 +echo "configure:1239: checking for 64-bit MIPS" >&5 +if eval "test \"`echo '$''{'cl_cv_host_mips64'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + +cat > conftest.$ac_ext <&5 | + egrep "yes" >/dev/null 2>&1; then + rm -rf conftest* + cl_cv_host_mips64=yes +else + rm -rf conftest* + cl_cv_host_mips64=no +fi +rm -f conftest* + + +fi +echo "$ac_t""$cl_cv_host_mips64" 1>&6 +if test $cl_cv_host_mips64 = yes; then + host_cpu=mips64 +fi + ;; + sparc | sparc64 ) + echo $ac_n "checking for 64-bit SPARC""... $ac_c" 1>&6 +echo "configure:1274: checking for 64-bit SPARC" >&5 +if eval "test \"`echo '$''{'cl_cv_host_sparc64'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + +cat > conftest.$ac_ext <&5 | + egrep "yes" >/dev/null 2>&1; then + rm -rf conftest* + cl_cv_host_sparc64=yes +else + rm -rf conftest* + cl_cv_host_sparc64=no +fi +rm -f conftest* + + +fi +echo "$ac_t""$cl_cv_host_sparc64" 1>&6 +if test $cl_cv_host_sparc64 = yes; then + host_cpu=sparc64 +else + host_cpu=sparc +fi + ;; +esac +cat >> confdefs.h <&6 +echo "configure:1373: checking for ld used by GCC" >&5 + ac_prog=`($CC -print-prog-name=ld) 2>&5` + case "$ac_prog" in + # Accept absolute paths. + /* | A-Za-z:\\*) + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + echo $ac_n "checking for GNU ld""... $ac_c" 1>&6 +echo "configure:1391: checking for GNU ld" >&5 +else + echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6 +echo "configure:1394: checking for non-GNU ld" >&5 +fi +if eval "test \"`echo '$''{'ac_cv_path_LD'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog"; then + ac_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then + test "$with_gnu_ld" != no && break + else + test "$with_gnu_ld" != yes && break + fi + fi + done + IFS="$ac_save_ifs" +else + ac_cv_path_LD="$LD" # Let the user override the test with a path. +fi +fi + +LD="$ac_cv_path_LD" +if test -n "$LD"; then + echo "$ac_t""$LD" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi +test -z "$LD" && { echo "configure: error: no acceptable ld found in \$PATH" 1>&2; exit 1; } + +echo $ac_n "checking if the linker ($LD) is GNU ld""... $ac_c" 1>&6 +echo "configure:1430: checking if the linker ($LD) is GNU ld" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gnu_ld'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # I'd rather use --version here, but apparently some GNU ld's only accept -v. +if $LD -v 2>&1 &5; then + ac_cv_prog_gnu_ld=yes +else + ac_cv_prog_gnu_ld=no +fi +fi +echo "$ac_t""$ac_cv_prog_gnu_ld" 1>&6 + + +echo $ac_n "checking for BSD-compatible nm""... $ac_c" 1>&6 +echo "configure:1445: checking for BSD-compatible nm" >&5 +if eval "test \"`echo '$''{'ac_cv_path_NM'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$NM" in +/* | A-Za-z:\\*) + ac_cv_path_NM="$NM" # Let the user override the test with a path. + ;; +*) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in /usr/ucb /usr/ccs/bin $PATH /bin; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/nm; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + ac_cv_path_NM="$ac_dir/nm -B" + elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + ac_cv_path_NM="$ac_dir/nm -p" + else + ac_cv_path_NM="$ac_dir/nm" + fi + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm + ;; +esac +fi + +NM="$ac_cv_path_NM" +echo "$ac_t""$NM" 1>&6 + + +echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6 +echo "configure:1482: checking whether ln -s works" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + rm -f conftestdata +if ln -s X conftestdata 2>/dev/null +then + rm -f conftestdata + ac_cv_prog_LN_S="ln -s" +else + ac_cv_prog_LN_S=ln +fi +fi +LN_S="$ac_cv_prog_LN_S" +if test "$ac_cv_prog_LN_S" = "ln -s"; then + echo "$ac_t""yes" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + +# Check for any special flags to pass to ltconfig. +libtool_flags= +test "$enable_shared" = no && libtool_flags="$libtool_flags --disable-shared" +test "$enable_static" = no && libtool_flags="$libtool_flags --disable-static" +test "$silent" = yes && libtool_flags="$libtool_flags --silent" +test "$ac_cv_prog_gcc" = yes && libtool_flags="$libtool_flags --with-gcc" +test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld" + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case "$host" in +*-*-irix6*) + # Find out which ABI we are using. + echo '#line 1518 "configure"' > conftest.$ac_ext + if { (eval echo configure:1519: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + case "`/usr/bin/file conftest.o`" in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + CFLAGS="$CFLAGS -belf" + ;; +esac + +# Actually configure libtool. ac_aux_dir is where install-sh is found. +CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \ +LD="$LD" NM="$NM" RANLIB="$RANLIB" LN_S="$LN_S" \ +${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig \ +$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $host \ +|| { echo "configure: error: libtool configure failed" 1>&2; exit 1; } + + ac_ext=C +# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cxx_cross + + +ac_ext=C +# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cxx_cross + +echo $ac_n "checking for bool type""... $ac_c" 1>&6 +echo "configure:1564: checking for bool type" >&5 +if eval "test \"`echo '$''{'cl_cv_cplusplus_bool'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + +cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + cl_cv_cplusplus_bool=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + cl_cv_cplusplus_bool=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$cl_cv_cplusplus_bool" 1>&6 +if test $cl_cv_cplusplus_bool = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_BOOL 1 +EOF + +else + cat >> confdefs.h <<\EOF +#define bool int +EOF + +fi +ac_ext=C +# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cxx_cross + + + echo $ac_n "checking for long long type""... $ac_c" 1>&6 +echo "configure:1611: checking for long long type" >&5 +if eval "test \"`echo '$''{'cl_cv_c_longlong'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + +if test "$cross_compiling" = yes; then + cl_cv_c_longlong="guessing no" +else + cat > conftest.$ac_ext <>32 == z)); + } +} +EOF +if { (eval echo configure:1644: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + cl_cv_c_longlong=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + cl_cv_c_longlong=no +fi +if test -f core; then + coredir=core`/bin/sh -c 'echo $$'` + mkdir $coredir + cp confdefs.h $coredir/confdefs.h + mv conftest.c $coredir/conftest.c + mv conftest $coredir/conftest + mv core $coredir/core + echo "warning: test program dumped core -- see subdirectory $coredir" +fi +rm -fr conftest* +fi + + +fi +echo "$ac_t""$cl_cv_c_longlong" 1>&6 +case "$cl_cv_c_longlong" in + *yes) cat >> confdefs.h <<\EOF +#define HAVE_LONGLONG 1 +EOF + ;; + *no) ;; +esac + + echo $ac_n "checking for long double type""... $ac_c" 1>&6 +echo "configure:1677: checking for long double type" >&5 +if eval "test \"`echo '$''{'cl_cv_c_longdouble'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + +if test "$cross_compiling" = yes; then + cl_cv_c_longdouble="guessing no" +else + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + cl_cv_c_longdouble=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + cl_cv_c_longdouble=no +fi +if test -f core; then + coredir=core`/bin/sh -c 'echo $$'` + mkdir $coredir + cp confdefs.h $coredir/confdefs.h + mv conftest.c $coredir/conftest.c + mv conftest $coredir/conftest + mv core $coredir/core + echo "warning: test program dumped core -- see subdirectory $coredir" +fi +rm -fr conftest* +fi + + +fi +echo "$ac_t""$cl_cv_c_longdouble" 1>&6 +case "$cl_cv_c_longdouble" in + *yes) cat >> confdefs.h <<\EOF +#define HAVE_LONGDOUBLE 1 +EOF + ;; + *no) ;; +esac + + echo $ac_n "checking for working template<>""... $ac_c" 1>&6 +echo "configure:1727: checking for working template<>" >&5 +if eval "test \"`echo '$''{'cl_cv_c_templatenull'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + +cat > conftest.$ac_ext < class c {}; template <> class c { int x; }; +int main() { + +; return 0; } +EOF +if { (eval echo configure:1740: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + cl_cv_c_templatenull=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + cl_cv_c_templatenull=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$cl_cv_c_templatenull" 1>&6 +if test $cl_cv_c_templatenull = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_TEMPLATE_NULL 1 +EOF + +fi + + + if test -n "$GCC"; then +echo $ac_n "checking for the global constructors function prefix""... $ac_c" 1>&6 +echo "configure:1764: checking for the global constructors function prefix" >&5 +if eval "test \"`echo '$''{'cl_cv_cplusplus_ctorprefix'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + +cat > conftest.cc << EOF +struct foo { foo (); }; +foo foobar; +EOF +# look for the assembly language name in the .s file +{ ac_try='${CXX-g++} $CXXFLAGS -S conftest.cc'; { (eval echo configure:1774: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } >/dev/null 2>&1 +if grep '_GLOBAL_\$I\$foobar' conftest.s >/dev/null ; then + cl_cv_cplusplus_ctorprefix='_GLOBAL_$I$' +else + if grep '_GLOBAL_\.I\.foobar' conftest.s >/dev/null ; then + cl_cv_cplusplus_ctorprefix='_GLOBAL_.I.' + else + if grep '_GLOBAL__I_foobar' conftest.s >/dev/null ; then + cl_cv_cplusplus_ctorprefix='_GLOBAL__I_' + else + cl_cv_cplusplus_ctorprefix=unknown + fi + fi +fi +rm -f conftest* + +fi +echo "$ac_t""$cl_cv_cplusplus_ctorprefix" 1>&6 +if test "$cl_cv_cplusplus_ctorprefix" '!=' unknown; then + ac_value='"'"$cl_cv_cplusplus_ctorprefix"'"' + cat >> confdefs.h <> confdefs.h <&6 +echo "configure:1804: checking whether the global constructors function need to be exported" >&5 +if eval "test \"`echo '$''{'cl_cv_cplusplus_ctorexport'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + +cat > conftest1.cc << EOF +struct foo { foo (); }; +foo foobar; +EOF +cat > conftest2.cc << EOF +#include "confdefs.h" +#ifdef ASM_UNDERSCORE +#define ASM_UNDERSCORE_PREFIX "_" +#else +#define ASM_UNDERSCORE_PREFIX "" +#endif +struct foo { foo (); }; +foo::foo () {} +extern "C" void ctor (void) __asm__ (ASM_UNDERSCORE_PREFIX CL_GLOBAL_CONSTRUCTOR_PREFIX "foobar"); +int main() { ctor(); return 0; } +EOF +if { ac_try='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest1.cc conftest2.cc $LIBS 1>&5'; { (eval echo configure:1825: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } >/dev/null 2>&1 && test -s conftest${ac_exeext}; then + cl_cv_cplusplus_ctorexport=no +else + cl_cv_cplusplus_ctorexport=yes +fi +rm -f conftest* + +fi +echo "$ac_t""$cl_cv_cplusplus_ctorexport" 1>&6 +if test "$cl_cv_cplusplus_ctorexport" = yes; then + cat >> confdefs.h <<\EOF +#define CL_NEED_GLOBALIZE_CTORDTOR 1 +EOF + +fi +fi +fi + + for ac_hdr in unistd.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1847: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1857: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + + + # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works +# for constant arguments. Useless! +echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6 +echo "configure:1887: checking for working alloca.h" >&5 +if eval "test \"`echo '$''{'cl_cv_header_alloca_h'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + +cat > conftest.$ac_ext < +int main() { +char *p = (char *) alloca(2 * sizeof(int)); +; return 0; } +EOF +if { (eval echo configure:1900: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + cl_cv_header_alloca_h=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + cl_cv_header_alloca_h=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$cl_cv_header_alloca_h" 1>&6 +if test $cl_cv_header_alloca_h = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_ALLOCA_H 1 +EOF + +fi +decl="#ifdef __GNUC__ +#define alloca __builtin_alloca +#else +#ifdef _MSC_VER +#include +#define alloca _alloca +#else +#ifdef HAVE_ALLOCA_H +#include +#else +#ifdef _AIX + #pragma alloca +#else +#ifndef alloca +char *alloca (); +#endif +#endif +#endif +#endif +#endif +" +echo $ac_n "checking for alloca""... $ac_c" 1>&6 +echo "configure:1942: checking for alloca" >&5 +if eval "test \"`echo '$''{'cl_cv_func_alloca'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + cl_cv_func_alloca=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + cl_cv_func_alloca=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$cl_cv_func_alloca" 1>&6 +if test $cl_cv_func_alloca = yes; then + : +else + alloca_missing=1 +fi +if test -n "$alloca_missing"; then + # The SVR3 libPW and SVR4 libucb both contain incompatible functions + # that cause trouble. Some versions do not even contain alloca or + # contain a buggy version. If you still want to use their alloca, + # use ar to extract alloca.o from them instead of compiling alloca.c. + ALLOCA=alloca.${ac_objext} + cat >> confdefs.h <<\EOF +#define NO_ALLOCA 1 +EOF + +fi + + echo $ac_n "checking for fpu_control_t""... $ac_c" 1>&6 +echo "configure:1987: checking for fpu_control_t" >&5 +if eval "test \"`echo '$''{'cl_cv_type_fpu_control_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + +cat > conftest.$ac_ext < +int main() { +fpu_control_t x; +; return 0; } +EOF +if { (eval echo configure:2000: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + cl_cv_type_fpu_control_t=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + cl_cv_type_fpu_control_t=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$cl_cv_type_fpu_control_t" 1>&6 +if test $cl_cv_type_fpu_control_t = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_FPU_CONTROL_T 1 +EOF + +fi + +echo $ac_n "checking for __setfpucw""... $ac_c" 1>&6 +echo "configure:2022: checking for __setfpucw" >&5 +if eval "test \"`echo '$''{'cl_cv_func_setfpucw'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + +cat > conftest.$ac_ext < +int main() { +__setfpucw(_FPU_IEEE); +; return 0; } +EOF +if { (eval echo configure:2035: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + cl_cv_func_setfpucw=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + cl_cv_func_setfpucw=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$cl_cv_func_setfpucw" 1>&6 +if test $cl_cv_func_setfpucw = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_SETFPUCW 1 +EOF + +fi + + + +for ac_func in gettimeofday +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2061: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2092: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done +if test $ac_cv_func_gettimeofday = yes; then +echo $ac_n "checking for gettimeofday declaration""... $ac_c" 1>&6 +echo "configure:2117: checking for gettimeofday declaration" >&5 +if eval "test \"`echo '$''{'cl_cv_proto_gettimeofday'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + +cat > conftest.$ac_ext < +#include + +extern +#ifdef __cplusplus +"C" +#endif + +#if defined(__STDC__) || defined(__cplusplus) +int gettimeofday (struct timeval * tp, struct timezone * tzp); +#else +int gettimeofday(); +#endif + +int main() { + +; return 0; } +EOF +if { (eval echo configure:2144: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + cl_cv_proto_gettimeofday_dots=no +cl_cv_proto_gettimeofday_arg2="struct timezone *" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + cat > conftest.$ac_ext < +#include + +extern +#ifdef __cplusplus +"C" +#endif + +#if defined(__STDC__) || defined(__cplusplus) +int gettimeofday (struct timeval * tp, void * tzp); +#else +int gettimeofday(); +#endif + +int main() { + +; return 0; } +EOF +if { (eval echo configure:2174: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + cl_cv_proto_gettimeofday_dots=no +cl_cv_proto_gettimeofday_arg2="void *" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + cl_cv_proto_gettimeofday_dots=yes +cl_cv_proto_gettimeofday_arg2="..." +fi +rm -f conftest* + +fi +rm -f conftest* + + +cl_cv_proto_gettimeofday="extern int gettimeofday (struct timeval *, $cl_cv_proto_gettimeofday_arg2);" +fi + +cl_cv_proto_gettimeofday=`echo "$cl_cv_proto_gettimeofday" | tr -s ' ' | sed -e 's/( /(/'` +echo "$ac_t""${ac_tt}$cl_cv_proto_gettimeofday" 1>&6 + + +if test $cl_cv_proto_gettimeofday_dots = yes; then +cat >> confdefs.h <<\EOF +#define GETTIMEOFDAY_DOTS 1 +EOF + +else +cat >> confdefs.h <&6 +echo "configure:2215: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2246: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + if test $ac_cv_func_gettimeofday = no -a $ac_cv_func_ftime = no; then +echo $ac_n "checking for times""... $ac_c" 1>&6 +echo "configure:2272: checking for times" >&5 +if eval "test \"`echo '$''{'ac_cv_func_times'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char times(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_times) || defined (__stub___times) +choke me +#else +times(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2303: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_times=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_times=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'times`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +no_times=1 +fi +if test -z "$no_times"; then +echo $ac_n "checking for times return value""... $ac_c" 1>&6 +echo "configure:2324: checking for times return value" >&5 +if eval "test \"`echo '$''{'cl_cv_func_times_return'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + +if test "$cross_compiling" = yes; then + cl_cv_func_times_return="guessing no" +else + cat > conftest.$ac_ext < +#include /* needed for CLK_TCK */ +#ifndef CLK_TCK +#include /* needed for CLK_TCK on SYSV PTX */ +#endif +#include +int main () +{ struct tms buffer; + clock_t result1; + clock_t result2; + int ticks; + result1 = times(&buffer); + if ((result1 == (clock_t)0) || (result1 == (clock_t)(-1))) exit(1); + sleep(1); + result2 = times(&buffer); + if ((result2 == (clock_t)0) || (result2 == (clock_t)(-1))) exit(1); + ticks = result2 - result1; + exit(!((ticks >= CLK_TCK/2) && (ticks <= 3*CLK_TCK/2))); +} +EOF +if { (eval echo configure:2359: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + cl_cv_func_times_return=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + cl_cv_func_times_return=no +fi +if test -f core; then + coredir=core`/bin/sh -c 'echo $$'` + mkdir $coredir + cp confdefs.h $coredir/confdefs.h + mv conftest.c $coredir/conftest.c + mv conftest $coredir/conftest + mv core $coredir/core + echo "warning: test program dumped core -- see subdirectory $coredir" +fi +rm -fr conftest* +fi + + +fi +echo "$ac_t""$cl_cv_func_times_return" 1>&6 +case "$cl_cv_func_times_return" in + *yes) cat >> confdefs.h <<\EOF +#define HAVE_TIMES_CLOCK 1 +EOF + ;; + *no) ;; +esac +fi +fi + + for ac_hdr in sys/resource.h sys/times.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2397: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2407: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done +if test $ac_cv_header_sys_resource_h = yes; then + echo $ac_n "checking for getrusage""... $ac_c" 1>&6 +echo "configure:2434: checking for getrusage" >&5 +if eval "test \"`echo '$''{'cl_cv_func_getrusage'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + +cat > conftest.$ac_ext < /* NetBSD 1.0 needs this */ +#include +#include +int main() { +struct rusage x; int y = RUSAGE_SELF; getrusage(y,&x); x.ru_utime.tv_sec; +; return 0; } +EOF +if { (eval echo configure:2449: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + cl_cv_func_getrusage=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + cl_cv_func_getrusage=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$cl_cv_func_getrusage" 1>&6 +if test $cl_cv_func_getrusage = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_GETRUSAGE 1 +EOF + +fi + if test $cl_cv_func_getrusage = yes; then + echo $ac_n "checking for getrusage declaration""... $ac_c" 1>&6 +echo "configure:2471: checking for getrusage declaration" >&5 +if eval "test \"`echo '$''{'cl_cv_proto_getrusage'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + cat > conftest.$ac_ext < +#ifdef HAVE_UNISTD_H +#include +#endif +#include /* NetBSD 1.0 needs this */ +#include +#include + +extern +#ifdef __cplusplus +"C" +#endif + +#if defined(__STDC__) || defined(__cplusplus) +int getrusage (int who, struct rusage * rusage); +#else +int getrusage(); +#endif + +int main() { + +; return 0; } +EOF +if { (eval echo configure:2503: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + cl_cv_proto_getrusage_arg1="int" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + cl_cv_proto_getrusage_arg1="enum __rusage_who" +fi +rm -f conftest* + + +cl_cv_proto_getrusage="extern int getrusage ($cl_cv_proto_getrusage_arg1, struct rusage *);" +fi + +cl_cv_proto_getrusage=`echo "$cl_cv_proto_getrusage" | tr -s ' ' | sed -e 's/( /(/'` +echo "$ac_t""${ac_tt}$cl_cv_proto_getrusage" 1>&6 + + + cat >> confdefs.h <&6 +echo "configure:2530: checking for perror declaration" >&5 +if eval "test \"`echo '$''{'cl_cv_proto_perror'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + +cat > conftest.$ac_ext <, some in , some don't + declare it at all. */ +#include +#include +extern +#ifdef __cplusplus +"C" +#endif +double perror (); +int main() { + +; return 0; } +EOF +if { (eval echo configure:2552: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + cl_cv_proto_perror=no +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + cl_cv_proto_perror=yes +fi +rm -f conftest* + +fi + +echo "$ac_t""$cl_cv_proto_perror" 1>&6 +if test $cl_cv_proto_perror = yes; then +cat >> confdefs.h <<\EOF +#define HAVE_PERROR_DECL 1 +EOF + +fi + + echo $ac_n "checking whether characters are unsigned""... $ac_c" 1>&6 +echo "configure:2574: checking whether characters are unsigned" >&5 +if eval "test \"`echo '$''{'ac_cv_c_char_unsigned'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + +if test $ac_cv_prog_gcc = yes; then + # GCC predefines this symbol on systems where it applies. +cat > conftest.$ac_ext <&5 | + egrep "yes" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_c_char_unsigned=yes +else + rm -rf conftest* + ac_cv_c_char_unsigned=no +fi +rm -f conftest* + +else +if test "$cross_compiling" = yes; then + ac_cv_c_char_unsigned="guessing no" +else + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_c_char_unsigned=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_c_char_unsigned=no +fi +if test -f core; then + coredir=core`/bin/sh -c 'echo $$'` + mkdir $coredir + cp confdefs.h $coredir/confdefs.h + mv conftest.c $coredir/conftest.c + mv conftest $coredir/conftest + mv core $coredir/core + echo "warning: test program dumped core -- see subdirectory $coredir" +fi +rm -fr conftest* +fi + +fi +fi +echo "$ac_t""$ac_cv_c_char_unsigned" 1>&6 +if test $ac_cv_prog_gcc = no; then + # GCC defines __CHAR_UNSIGNED__ by itself, no need to fix up. + case "$ac_cv_c_char_unsigned" in + *yes) cat >> confdefs.h <<\EOF +#define __CHAR_UNSIGNED__ 1 +EOF + ;; + *no) ;; + esac +fi + + test -d 'include' || mkdir 'include' +cl_machine_file_c=${srcdir}/autoconf/intparam.c +cl_machine_file_h=include/cl_intparam.h +if test $cross_compiling = no; then +if test -z "$cl_cv_file_intparam_h"; then +echo "checking for integer types and behaviour" 1>&6 +echo "configure:2658: checking for integer types and behaviour" >&5 +cat > conftest.$ac_ext <> conftest.$ac_ext +ORIGCC="$CC" +if test $ac_cv_prog_gcc = yes; then +# gcc -O (gcc version <= 2.3.2) crashes when compiling long long shifts for +# target 80386. Strip "-O". +CC=`echo "$CC " | sed -e 's/-O //g'` +fi +{ (eval echo configure:2669: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } +CC="$ORIGCC" +if test -s conftest; then + echo "creating $cl_machine_file_h" + ./conftest > conftest.h + if cmp -s "$cl_machine_file_h" conftest.h 2>/dev/null; then + # The file exists and we would not be changing it + rm -f conftest.h + else + rm -f "$cl_machine_file_h" + mv conftest.h "$cl_machine_file_h" + fi + cl_cv_file_intparam_h=1 +else + echo "creation of $cl_machine_file_h failed" +fi +rm -f conftest* +fi +else +echo "cross-compiling - cannot create $cl_machine_file_h" +fi + + cl_machine_file_c=${srcdir}/autoconf/floatparam.c +cl_machine_file_h=include/cl_floatparam.h +if test $cross_compiling = no; then +if test -z "$cl_cv_file_floatparam_h"; then +echo "checking for floating-point types and behaviour" 1>&6 +echo "configure:2696: checking for floating-point types and behaviour" >&5 +cat > conftest.$ac_ext <> conftest.$ac_ext +ORIGCC="$CC" +if test $ac_cv_prog_gcc = yes; then +# gcc -O (gcc version <= 2.3.2) crashes when compiling long long shifts for +# target 80386. Strip "-O". +CC=`echo "$CC " | sed -e 's/-O //g'` +fi +{ (eval echo configure:2707: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } +CC="$ORIGCC" +if test -s conftest; then + echo "creating $cl_machine_file_h" + ./conftest > conftest.h + if cmp -s "$cl_machine_file_h" conftest.h 2>/dev/null; then + # The file exists and we would not be changing it + rm -f conftest.h + else + rm -f "$cl_machine_file_h" + mv conftest.h "$cl_machine_file_h" + fi + cl_cv_file_floatparam_h=1 +else + echo "creation of $cl_machine_file_h failed" +fi +rm -f conftest* +fi +else +echo "cross-compiling - cannot create $cl_machine_file_h" +fi + + # Check whether --with-gmp or --without-gmp was given. +if test "${with_gmp+set}" = set; then + withval="$with_gmp" + : +fi + +if test -z "$with_gmp"; then + if test -d "${srcdir}/gmp"; then + with_gmp=yes + else + with_gmp=no + fi +fi +if test "$with_gmp" = yes; then + cat >> confdefs.h <<\EOF +#define CL_USE_GMP 1 +EOF + + GMP_INCLUDES='-I$(top_srcdir)/gmp' + GMP_OBJDEPS='../gmp/mpn/libmpn.la' + GMP_OBJS='../gmp/mpn/*.lo ../gmp/*.lo' +else + GMP_INCLUDES='' + GMP_OBJDEPS='' + GMP_OBJS='' +fi + + + +for f in 'tests/.gdbinit'; do + if test '!' -f "$f"; then + echo "creating $f" + g=`echo "$f" | sed -e 's,/[^/]*$,,'` + test "$g" = "$f" || test -d "$g" || mkdir "$g" + cp "$srcdir/$f" "$f" + fi +done +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='$(prefix)' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.13" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir + +trap 'rm -fr `echo "Makefile src/Makefile tests/Makefile benchmarks/Makefile examples/Makefile doc/Makefile include/cl_config.h src/base/cl_base_config.h src/base/cl_gmpconfig.h src/float/cl_float_config.h src/timing/cl_t_config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@FFLAGS@%$FFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@SET_MAKE@%$SET_MAKE%g +s%@CC@%$CC%g +s%@CPP@%$CPP%g +s%@CXX@%$CXX%g +s%@CXXCPP@%$CXXCPP%g +s%@AS_UNDERSCORE@%$AS_UNDERSCORE%g +s%@RANLIB@%$RANLIB%g +s%@INSTALL@%$INSTALL%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@host@%$host%g +s%@host_cpu@%$host_cpu%g +s%@host_vendor@%$host_vendor%g +s%@host_os@%$host_os%g +s%@LD@%$LD%g +s%@NM@%$NM%g +s%@LN_S@%$LN_S%g +s%@LIBTOOL@%$LIBTOOL%g +s%@ALLOCA@%$ALLOCA%g +s%@GMP_INCLUDES@%$GMP_INCLUDES%g +s%@GMP_OBJDEPS@%$GMP_OBJDEPS%g +s%@GMP_OBJS@%$GMP_OBJS%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' +# ac_f turns "#define NAME" without trailing blanks into "#define NAME VALUE". +ac_fA='s%^\([ ]*\)#\([ ]*\)define\([ ][ ]*\)' +ac_fB='$%\1#\2define\3' +ac_fC=' ' +ac_fD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +s%ac_e%ac_f%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + +if test "$with_gmp" = yes; then + +if test "$no_recursion" != yes; then + + # Remove --cache-file and --srcdir arguments so they do not pile up. + ac_sub_configure_args= + ac_prev= + for ac_arg in $ac_configure_args; do + if test -n "$ac_prev"; then + ac_prev= + continue + fi + case "$ac_arg" in + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + ;; + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + ;; + *) ac_sub_configure_args="$ac_sub_configure_args $ac_arg" ;; + esac + done + + for ac_config_dir in gmp; do + + # Do not complain, so a configure script can configure whichever + # parts of a large source tree are present. + if test ! -d $srcdir/$ac_config_dir; then + continue + fi + + echo configuring in $ac_config_dir + + case "$srcdir" in + .) ;; + *) + if test -d ./$ac_config_dir || mkdir ./$ac_config_dir; then :; + else + { echo "configure: error: can not create `pwd`/$ac_config_dir" 1>&2; exit 1; } + fi + ;; + esac + + ac_popdir=`pwd` + cd $ac_config_dir + + # A "../" for each directory in /$ac_config_dir. + ac_dots=`echo $ac_config_dir|sed -e 's%^\./%%' -e 's%[^/]$%&/%' -e 's%[^/]*/%../%g'` + + case "$srcdir" in + .) # No --srcdir option. We are building in place. + ac_sub_srcdir=$srcdir ;; + /*) # Absolute path. + ac_sub_srcdir=$srcdir/$ac_config_dir ;; + *) # Relative path. + ac_sub_srcdir=$ac_dots$srcdir/$ac_config_dir ;; + esac + + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_sub_srcdir/configure; then + ac_sub_configure=$ac_sub_srcdir/configure + elif test -f $ac_sub_srcdir/configure.in; then + ac_sub_configure=$ac_configure + else + echo "configure: warning: no configuration information is in $ac_config_dir" 1>&2 + ac_sub_configure= + fi + + # The recursion is here. + if test -n "$ac_sub_configure"; then + + # Make the cache file name correct relative to the subdirectory. + case "$cache_file" in + /*) ac_sub_cache_file=$cache_file ;; + *) # Relative path. + if test -n "$ac_dots"; then + ac_sub_cache_file="$ac_dots"`echo "$cache_file" | sed 's,^\./,,'` + else + ac_sub_cache_file="$cache_file" + fi + ;; + esac + + echo "running ${CONFIG_SHELL-/bin/sh} $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_sub_srcdir" + # The eval makes quoting arguments work. + if eval ${CONFIG_SHELL-/bin/sh} $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_sub_srcdir + then : + else + { echo "configure: error: $ac_sub_configure failed for $ac_config_dir" 1>&2; exit 1; } + fi + fi + + cd $ac_popdir + done +fi + +fi diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..672c920 --- /dev/null +++ b/configure.in @@ -0,0 +1,161 @@ +dnl AUTOCONF configuration for CLN +dnl Bruno Haible 8.1.1999 +dnl +dnl configure.in ------>> configure +dnl +dnl configure ------>> config.status +dnl --->> include/cl_config.h +dnl Makefile.in --->> Makefile +dnl src/Makefile.in --->> src/Makefile +dnl +dnl Makefile ------>> libcln.a +dnl +dnl +AC_INIT(src/integer/gcd/cl_I_gcd.cc) +AC_CONFIG_HEADER(include/cl_config.h src/base/cl_base_config.h src/base/cl_gmpconfig.h src/float/cl_float_config.h src/timing/cl_t_config.h) +AC_PROG_MAKE_SET +dnl This piece of sed script replaces every line containing '@subdir@' +dnl by several consecutive lines, each referencing one subdir. +extrasub="$extrasub"' +/@subdir@/{ +h +g +s/@subdir@/src/ +p +g +s/@subdir@/tests/ +p +g +s/@subdir@/benchmarks/ +p +g +s/@subdir@/examples/ +p +g +s/@subdir@/doc/ +p +d +} +' +dnl +dnl checks for programs +dnl +AC_PROG_CC + dnl sets variable CC +AC_PROG_CPP + dnl sets variable CPP +AC_PROG_CXX + dnl sets variable CXX +AC_PROG_CXXCPP + dnl sets variable CXXCPP +CL_AS_UNDERSCORE + dnl sets variable AS_UNDERSCORE, DEFS ASM_UNDERSCORE +CL_PROG_RANLIB + dnl sets variable RANLIB +CL_PROG_INSTALL + dnl sets variables INSTALL, INSTALL_DATA, INSTALL_PROGRAM +dnl +dnl check for host type +dnl +CL_CANONICAL_HOST(autoconf) + dnl sets variables host, host_cpu, host_vendor, host_os +CL_CANONICAL_HOST_CPU + dnl DEFS __${host_cpu}__ +dnl +dnl check for build configuration +dnl +PACKAGE=cln +AM_DISABLE_SHARED +AM_PROG_LIBTOOL + dnl sets variable LIBTOOL +dnl +dnl checks for compiler characteristics +dnl +AC_LANG_CPLUSPLUS +dnl +CL_BOOL + dnl DEFS HAVE_BOOL, bool +CL_LONGLONG + dnl DEFS HAVE_LONGLONG +CL_LONGDOUBLE + dnl DEFS HAVE_LONGDOUBLE +CL_TEMPLATE_NULL + dnl DEFS HAVE_TEMPLATE_NULL +CL_GLOBAL_CONSTRUCTORS + dnl DEFS CL_GLOBAL_CONSTRUCTOR_PREFIX, CL_GLOBAL_DESTRUCTOR_PREFIX +dnl +dnl checks for header files +dnl +CL_UNISTD_H + dnl DEFS HAVE_UNISTD_H if exist unistd.h +dnl +dnl checks for typedefs +dnl +dnl +dnl checks for functions and declarations +dnl +CL_ALLOCA + dnl set variable ALLOCA, DEFS NO_ALLOCA +CL_FPU_CONTROL + dnl DEFS HAVE_FPU_CONTROL_T, HAVE_SETFPUCW +CL_GETTIMEOFDAY + dnl DEFS HAVE_GETTIMEOFDAY, GETTIMEOFDAY_DOTS, GETTIMEOFDAY_TZP_T +CL_FTIME + dnl DEFS HAVE_FTIME +CL_TIMES_CLOCK + dnl DEFS HAVE_TIMES_CLOCK +CL_RUSAGE + dnl DEFS HAVE_SYS_RESOURCE_H, HAVE_GETRUSAGE, HAVE_SYS_TIMES_H +CL_PERROR + dnl DEFS HAVE_PERROR_DECL +dnl +dnl checks for compiler characteristics +dnl +CL_CHAR_UNSIGNED + dnl DEFS __CHAR_UNSIGNED__ if char is unsigned +test -d 'include' || mkdir 'include' +CL_MACHINE([integer types and behaviour],${srcdir}/autoconf/intparam.c,include/cl_intparam.h,cl_cv_file_intparam_h) + dnl builds include/cl_intparam.h +CL_MACHINE([floating-point types and behaviour],${srcdir}/autoconf/floatparam.c,include/cl_floatparam.h,cl_cv_file_floatparam_h) + dnl builds include/cl_floatparam.h +dnl +dnl interfacing to GNU gmp +dnl +AC_ARG_WITH(gmp, [ --with-gmp use fast GNU gmp low-level functions]) +if test -z "$with_gmp"; then + if test -d "${srcdir}/gmp"; then + with_gmp=yes + else + with_gmp=no + fi +fi +if test "$with_gmp" = yes; then + AC_DEFINE(CL_USE_GMP) + GMP_INCLUDES='-I$(top_srcdir)/gmp' + GMP_OBJDEPS='../gmp/mpn/libmpn.la' + GMP_OBJS='../gmp/mpn/*.lo ../gmp/*.lo' +else + GMP_INCLUDES='' + GMP_OBJDEPS='' + GMP_OBJS='' +fi +AC_SUBST(GMP_INCLUDES) +AC_SUBST(GMP_OBJDEPS) +AC_SUBST(GMP_OBJS) +dnl +dnl That's it. +dnl +for f in 'tests/.gdbinit'; do + if test '!' -f "$f"; then + echo "creating $f" +changequote(,)dnl + g=`echo "$f" | sed -e 's,/[^/]*$,,'` +changequote([,])dnl + test "$g" = "$f" || test -d "$g" || mkdir "$g" + cp "$srcdir/$f" "$f" + fi +done +AC_OUTPUT(Makefile src/Makefile tests/Makefile benchmarks/Makefile examples/Makefile doc/Makefile) +if test "$with_gmp" = yes; then + AC_OUTPUT_SUBDIRS(gmp) +fi diff --git a/doc/Makefile.devel b/doc/Makefile.devel new file mode 100644 index 0000000..5c52163 --- /dev/null +++ b/doc/Makefile.devel @@ -0,0 +1,45 @@ +# This is the developer's makefile, not the user's makefile. +# Don't use it unless you know exactly what you do! + + +PACKAGE = cln + + +# Some important programs: +SHELL = /bin/sh +MAKE = make + +TEXI2DVI = texi2dvi +DVIPS = dvips -D600 +MAKEINFO = LANGUAGE= makeinfo +TEXI2HTML = texi2html +EMACS = emacs + + +all : documentation + +documentation : $(PACKAGE).dvi $(PACKAGE).ps $(PACKAGE).info $(PACKAGE).html $(PACKAGE)_toc.html + +$(PACKAGE).dvi : $(PACKAGE).texi + $(TEXI2DVI) $(PACKAGE).texi + rm -f *.aux *.toc *.cp *.fn *.ky *.pg *.tp *.vr *.my *.log + +$(PACKAGE).ps : $(PACKAGE).dvi + $(DVIPS) -o $(PACKAGE).ps $(PACKAGE).dvi + +$(PACKAGE).info : $(PACKAGE).texi + $(MAKEINFO) --no-split $(PACKAGE).texi + +$(PACKAGE).html : $(PACKAGE).texi + $(TEXI2HTML) -expandinfo -number -monolithic $(PACKAGE).texi + +$(PACKAGE)_toc.html : $(PACKAGE).texi + $(TEXI2HTML) -expandinfo -number -split_chapter $(PACKAGE).texi + +$(PACKAGE).texi : $(PACKAGE).tex + rm -f $(PACKAGE).texi + cp $(PACKAGE).tex $(PACKAGE).texi + $(EMACS) -batch $(PACKAGE).texi -load addnodes.el -f save-buffer + mv $(PACKAGE).texi $(PACKAGE).texi~ + sed -e 's,@detailmenu,,g' -e 's,@end detailmenu,,g' < $(PACKAGE).texi~ > $(PACKAGE).texi + rm -f *~ diff --git a/doc/Makefile.in b/doc/Makefile.in new file mode 100644 index 0000000..7e89470 --- /dev/null +++ b/doc/Makefile.in @@ -0,0 +1,115 @@ +# Makefile for cln/doc + +#### Start of system configuration section. #### + +# Directories used by "make": +srcdir = @srcdir@ + +# Directories used by "make install": +prefix = @prefix@ +local_prefix = /usr/local +exec_prefix = @exec_prefix@ +datadir = @datadir@ +infodir = @infodir@ +mandir = @mandir@ +htmldir = $(datadir)/html +dvidir = $(datadir)/dvi + +# Programs used by "make": +RM = rm -f +@SET_MAKE@ + +# Programs used by "make" if you have changed the documentation files: +TEX = tex +TEXI2DVI = texi2dvi +DVIPS = dvips -D600 +MAKEINFO = LANGUAGE= makeinfo +TEXI2HTML = texi2html +EMACS = emacs + +# Programs used by "make install": +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ + +#### End of system configuration section. #### + +PACKAGE = cln + +SHELL = /bin/sh + +VPATH = $(srcdir) + +all : info dvi ps html + + +info : $(srcdir)/$(PACKAGE).info + +$(srcdir)/$(PACKAGE).info : $(srcdir)/$(PACKAGE).texi + cd $(srcdir) && $(MAKEINFO) --no-split $(PACKAGE).texi + +$(srcdir)/$(PACKAGE).texi : $(srcdir)/$(PACKAGE).tex + cp $< $@ + $(EMACS) -batch $@ -load addnodes.el -f save-buffer + mv $@ $@~ + sed -e 's,@detailmenu,,g' -e 's,@end detailmenu,,g' < $@~ > $@ + $(RM) $@~ + + +dvi : $(srcdir)/$(PACKAGE).dvi + +$(srcdir)/$(PACKAGE).dvi : $(srcdir)/$(PACKAGE).texi + cd $(srcdir) && $(TEXI2DVI) $(PACKAGE).texi + + +ps : $(srcdir)/$(PACKAGE).ps + +$(srcdir)/$(PACKAGE).ps : $(srcdir)/$(PACKAGE).dvi + $(DVIPS) -o $@ $< + + +html : $(PACKAGE).html $(PACKAGE)_toc.html + +$(PACKAGE).html : $(srcdir)/$(PACKAGE).texi + cd $(srcdir) && $(TEXI2HTML) -expandinfo -number -monolithic $(PACKAGE).texi + +$(PACKAGE)_toc.html : $(srcdir)/$(PACKAGE).texi + cd $(srcdir) && $(TEXI2HTML) -expandinfo -number -split_chapter $(PACKAGE).texi + + +install : all force + if [ ! -d $(infodir) ] ; then mkdir $(infodir) ; fi + $(INSTALL_DATA) $(srcdir)/$(PACKAGE).info $(infodir)/$(PACKAGE).info + if [ ! -d $(datadir) ] ; then mkdir $(datadir) ; fi + if [ ! -d $(htmldir) ] ; then mkdir $(htmldir) ; fi + $(INSTALL_DATA) $(srcdir)/$(PACKAGE)_*.html $(htmldir) + if [ ! -d $(dvidir) ] ; then mkdir $(dvidir) ; fi + $(INSTALL_DATA) $(srcdir)/$(PACKAGE).dvi $(dvidir)/$(PACKAGE).dvi + +installdirs : force + if [ ! -d $(infodir) ] ; then mkdir $(infodir) ; fi + if [ ! -d $(datadir) ] ; then mkdir $(datadir) ; fi + if [ ! -d $(htmldir) ] ; then mkdir $(htmldir) ; fi + if [ ! -d $(dvidir) ] ; then mkdir $(dvidir) ; fi + +uninstall : force + $(RM) $(infodir)/$(PACKAGE).info + $(RM) $(htmldir)/$(PACKAGE)_*.html + $(RM) $(dvidir)/$(PACKAGE).dvi + +check : all + +mostlyclean : clean + +clean : force + $(RM) *~ *.aux *.toc *.cp *.fn *.ky *.pg *.tp *.vr *.my *.log core + +distclean : clean + $(RM) Makefile + +maintainer-clean : distclean + $(RM) *.info *.dvi *.ps *.html + if [ -f $(PACKAGE).tex ] ; then $(RM) $(PACKAGE).texi ; fi + +force : + diff --git a/doc/addnodes.el b/doc/addnodes.el new file mode 100644 index 0000000..130c0d4 --- /dev/null +++ b/doc/addnodes.el @@ -0,0 +1,17 @@ +;; Emacs Lisp program to insert nodes and menus in a TeXinfo file. + +(texinfo-mode) +(texinfo-insert-node-lines + (save-excursion (beginning-of-buffer) (point)) + (save-excursion (end-of-buffer) (point)) + t +) +(texinfo-master-menu t) +;; The following is not needed because it is already done by the +;; (texinfo-master-menu t) command. +; (texinfo-every-node-update) +;; The following should not be needed because it should already done by the +;; (texinfo-master-menu t) command. Alas, `texinfo-master-menu' is buggy: +;; It forgets to create the `Customizing' menu... +(texinfo-all-menus-update) + diff --git a/doc/cln.dvi b/doc/cln.dvi new file mode 100644 index 0000000000000000000000000000000000000000..faa44fd49e72b93a521f3718d067f81628f8072c GIT binary patch literal 157376 zcmeFadw|?!bvM3bW|JTR0l}&ukOW~j+1>0VcamsWNLa}QlAu&$!tBiK?vS}Gb4hj) zmDWmC*wx`%hp|x?G(}TeMAUk}Rg2mm?WJ@6n07pI-X8f1P;pRe$@)j=NjV z`OJ+ii!j3ccxG^{r}yz!^>5qJQCaZd`(sXjI#wt++fsx1Sbp3Y%H^FMrA+ymSDimt zZuyIUP38-eQ;QaMzojJ#IKK78t#_aDq4eU3C$ExW&lnmC413k!+wXX2ywW-}ba}p% z%{f=aQiJK_IE$=cW_zwU{?Q@1(x;9nf0GeJlT8o&ubVKo^|V1b@1nE`ME}Zu9ctbIvm-o$*GsNv`k!6 z8ce4OBgsT%UiPPhe-1btKN331^Zt7MlYQU&$%Zli?8RbFcYVW%;OS*?3^3Xi&t(f; zx%}`Zrxwd5oL#ASbtINgI9KPB@#=wUGA%>ZHyps<2a@TR4X3iPcvm91sn#`lWHBMZ z%Ogaav$^2lfn94Zu z+-NFUaB@RVaRhH>@M0;Jc1H8L>cLckLyRQ(P*o6JElwVNE+)<9im7;#h~vQW=IGnE z*IhUqeZYz3lNc&lNahc|9bhJ$T-J%D(`MGL$$LWJNA~_Y1inli20xR-WQo)w49Jym z<&8@yWfRG~0Y95a75UKQy%V7MN~Go1gMu~}2i5UZcDSP)S$v;=<*}l?p9C^fSP2$V zN*D2H<80?^f zeZCHsgcQ54gR^Wx&uI8_CRtho*X6G1b2XT6dPoy(^5qyhL^^jLC|HP7z3SR z@>EtaL;!p z$d;ce{cSOyE4RFLV?sv(kjqk|m~h(;E)WQbIccBxjps7Z17@!drHUiM9|uy|giv%A z%P(b|L1C^!mq1$NKqE1ZluyM$$0JT5StJXCcQaLe)`?TnCkyK*k5WoZlo$S{{Md6R z%je#gFl$W?W8XMbn@n5Erc;>|g$5Wlo+3}RcT65R>s5P$FYgjqV`-u;2wex*IWW(b zbPf+^hdW0}ODR5Gl-C?CiHy5mUODeQ1CO;#mY47SYHc?*R-QQ>uj+vQZ!uUp$swA4 zeMJsZdHS!n<+8(EFW+@$T6Aa`{n(;(a%>h0-mc`6jzPp=ud~>jqM+GnBire(D!fW* zFrl+(4EVNR0o|dQugj(mmY+#n5zD8*CIo;2B$pn~<}#^Ry3jQ_wG{iaXCzsP9?cX= zgGJ0ZE<(o0L&|P}-cK8#oD6V5*;W9jL$W2uV)0^nT%=vG>KnmFQ3dBfHdj5Ag@~Fw zLM4FLE0Kf$4)kC&*c63PSDb)Q|8XI}$|oUilTIDf@6_V4tP-+QDqz_(KK$>d2xmq` zq4EO+%B{o0se{;cVCDvnQoEFxwbCn-jAikqFmS5qP-G>sUg$GS6&oDPCl3N~pky+~ zUjJmUdLV;@2A6a}{1Am0m~f89$WsRd@54#Qf>kY2kO%1dN)O)rIA0$sWkqxpoVNP% zT8C5bLXap_$YAsZ)n)=A^kie?s2ZFj?cUA(Goue&+c}>W_F5`co(vGekf3 zsBdk_F(JdO=*3vNqZ0k~$1y9GR2<2q;vEjmjNu$;G>KpE=Ljh39kdPxom@H<4~_;X zC#OhG6ipzhRGy+dK-4oAeGm;$Z@a$IQxIZE>*K<=^h za1wq4HV~r~#zkSq#soQkNX+L-4p|(`EpjBx0UJq%8}Tzhh37nPMJ*@G%EyYiJoc&p zaGZXJ(gFB^nJY5R+w)8^lfzPUbFcx$^%>AX5UPid`D21!@;rIOc&|N@X(1 z1Vw8HO%rD%85^bgfp$K3^IwrfAS%5U}eY3_p-=I-QJnsz?_e zguDdOF9u6`NH541VIDu)ry48^5u;mAKLDaj=CjE(zUPS50H!ske~4y*^Lm_GpW%+ z4cg+~p?WNzsX{J62&IgC>AXp?-a5AjjLP<$bS4SD)q@n9N(@9wQX$Po< z9fN0w^0|z&b;oti*6r80u7}gxz$yc<(c*W>@K?t`*ig+eCj((X|6vp|P(%6?4Hn1MK8}s(i8-^nkPl4Ou{tTyzh4zke>#_l8 zVp;iaxUz33|K_%#Ty_MM*0~$DJ$5_mWU8ffCzw{L&4-TGo`pmQ7C%yn{@^?s%cPL; z%xIAgC-`98$$^A9BM0%}(pwr}=vhb_3Ozv=N3a8fLVRUlh(aMBOQgoY1~gAa<22Ae zI1G@$zMveYVoAmdDS%=PJZ!Kr<8q2L((h2QdZ;S?Zw!vSu_j>fPQx_!4h0!ftQOcF z)CHtc=!U^k9vYc0H1|9M*-sD25>vyD3NPL}WStGTQXmKV^aW=mM}zzT=$U9zc}gKu zRk{S$!RX@10T-|`Jx41ts~Aqp>0fLj1$&L71!_&JcY5b3u?IiY7nXlN=~ZXSdkz4s z>V4ltZ4W{eqI{BKW`X(&aYQt@EwZQw79XODgHq%af+n&#EIM}wh`#Y^u7oWb2XAE{ z>8|+V9TO9eU)9^yQ(pMOcV3f+)p}D2BvMQkF!9Uy?UUDv*LV8TfA)KQk6(*-@YaGv zTmO@LzIWTl_O$q(K(MFx@jc6zLo987{93E!Cnt|AdEck7l*81Rl}OJI21}`Qg5s#d z8OIJmi)ND`C&cQ+w6QP3uKD=<&G90lGwJavM907i)$RH?gi<-u^X2-mOgPlrwWh1v zsbPDw$wTn8=2Qnum8%KadTN{2IE;7{(jC~k}A_MEm;dsFT z0{rtpB$M!3hnEgPvE;zYhdfhkC>bl35JeH?3mK7EUtYNXmBv#A-~RJ15TkWqU9(TV zKsXA^fJ2$!a8N7m*Q8dkw%>?=vY@F3GRVUV7pnp=gIet09iWjkBsy(zJk{ZNq7qg? z7LH2_A~lZhK_W1-Knmn9!&0&`Y}Irtqb;GULtvqf4WPNB-c61&SWV z`P9dZVS7cqK)M!l)m&Q5CrYEyV#ndgUyE7?i9oUc)lKm{=pIy0vCXZG{1x0FiNF(! z9aY_DN+!-+>!5uv4~r(wCUW^p3-XmyQ>0d*21N@13Ke4oAX#N&k=85pkOp)7vKuk| z+59{EE3=o~E5ovzVzifH^m1-9=o4GMo$EFWocgX5ts52s0up8 z5--S@^l?Ld*gg-)lQBfUhrBV=%_Fhf_(Qa($mJ`<2$w+Ak`UssO8}a40Ft1m2uoCr zV^@}9P}Lh2P~rNZ@{o^&9}2$M&EK!9Z^wd$;Lz3zU58r-UI78;$RfSz^({;6OdAR7 zSA`+4tWj7ZvVlcOG^~ViQGy!>^wD+`sSV=~*gizQ%O4QQ1P`Np>arhEp0=KQqs&O_ zUADlfA)5qKm>vMQ2C?Lv151+W5I_Ml45pAVjPelDaEoDG8w(vf;CdODGLtG8^(n%G z(_xloNRGuBwg%X+E@|>G(5f=a8HUdu!yMQRxShZ@$T`Cp$GD&1NJc(_b2>XmlIc;B z({3z;)9Rac1`~D@7ha4wt-PYr4KuD=|)?wi(VfSEAV0(e8VgpdP1PUT&2tpCV|1DYE_9%w8$k;JD) z=eU}HI<-z%a$OF&gK1_^l!O{E|1n0@=8Fe?L-g>%RVEZMS$@aU^d<1PE|YI1*Mt zO#jI9>EfZQi=uyt5@88`h^`1=HGd5EX=U#iSsP;1CLn4oGNV_aYqz1HO$cD}X}t zBfvfkHxUsIfOh@$Gr$%!!rV9J2wq^6Ie~cZ#FZM<2?{vUTYvw?CByOf5~p9F*|?;0 zCw{;FdVIQkx%}q)+((=~Y3Liq>3jw3zBOIF{_&j7;U&&qth(GbeAEujmwXRjf4w`6 zJno;#Cu9w@I?dXyp5Qb?*<7b*1kEs~z8RP^{O<7qpyk@x+qJHzYjw9Dj$WrTJlHgg zpTh`#a6C_{bvC-VrR4>0oV_+)71G8#az#j<&3i>^($xc}Krbc5(2$j>Tbx1+!kq@VDsL#AM#Tpi{LK{uR=GjTB-G@>%m~H|OPDYj%fm#@gFa>aN@VBd zn3if2CT`@0`;Dz; z!-s_t%wCh}#qDUA(wd4lz_>%u>mUTVfl7u`38 zT|~wJ;7I(#iCp$l=+;C6R#E59ULeLwb7Al5*4-U`dmHwYI=7uW@u;XpF{_cqA>aVc zgy9Jw$(_Ex#H!>?N2V|kMt}U>nIK%-HO2t6$K+$6^R5G3v99vM54=o1hTjWv&N~pm zlq9RVu%_1apBgAffBY8DPsZXvI{*zU3`!QwWCa!s18M8-E=Me@Ln#C>(kWJejJs=9 zY{)Lfk$@L#0O+3ooOe&Zn7|sQft+l)n<3SX^8EK5<%T4Y$^k8KUw~^YQ+5dJkX005 zs3l72Bm&EYY=J8|Clgo+bTe1-N{j+W9V;;#jBW3kQhM-gGj)s-CM@R$TdAEl!!;DH z;^nTb);l}tn84ER9L|hZYjE(4SHk4dyFbhi6D0j)p$eO# zdI+n9VOynbA!!-d(+L2tB@H*!vwbA(K@{$2$rWPrL^!7>HC{emiC*_diR4fW0nLuX z(LcJ1{xwZb_2F#*kIpBYsv@}e@fH4ri&*I5SVphA4)!nJR1DcS)g|meV154CXV9LUq;}7OOHbPG6tEL-S}~!YTciGP@{`|bc+YnhlNbQSV6}auEPHrulRx=K5D#T8g6t+ ztt$;&BBq*T4V(J5bi$0A4U)BL%6y`HYKh9mC{o#Yx&+k>=Y%R5BnHMDWqDlOfp-(f zr)@XXSCk6*73mxZVFdRLH*Nhw5~Pvh4pt>{RIWw z*@=3UAw=+zMwFmAruPUNxuA0N>kqrmDyG%yBW|U{d7p5Ge-D{x~UEYOU+fM};5q zF$q7e;2XM#+Bo4W0yyhKU#!K78WXTWt`fcPapYK%kVQXVbYlq~cs|()=gyDTj;hvW zU`_!`3_9aHTbpiCp3XZ5s*a{hN?$C~Q}BWwUKIFBp_0wqY`uzWy+Vx5VkIGZeFaEet@Xw{kxi7KnfB=P_WugTNN zqZgPcQT<|zk^1$A&7fQ4|$yi_j8uS}?{ z+FJF>;Y`gBPzCu(-6OGwszlZ$FW`*8zK3N}MG*-id>38%_{5zp_kRD%Ix2VuVf0C0 z@6MKcE;<}f@6YOI_u!Ft+_QCq`$^ZxChXvyEf4H}=PmwU%CCR#)UG7zTOb!WqJJuC7aW4`ih@uKbGi|9wm4<)41~WwQ_j zpqD$Jx&|NY-csrN%x}2lEhv`Ue}(+q#`WLX^47&q@|}WREs-g!w;wqCD-rlBZU34) zy5#+jt745_|M9^XTp%UoI^I#tBf9{D2@d2SQc@_rbG)Zu-u>bm14SEShE9S3O;LeV zJ2LX{m;;`w8XYMc)}_o5nOBK!IK|ZBQi(D;4L^>4E{0MPF4DCy_LX%KJ1MUrD|HYX zccrkRzNeuCMG$-l2y;W!c+i><&|9?CXkJ8~yWc|q3jx7rD1U=xKn{?RUDoqU9)@8* zcpFB@%NP=Mhx)Ig<^ZqhkaP^fFVoWmR0S9lcu|YCgs%gG^BXaFQBD8}Ou0uh&Z#4B zDtNYKG)%Z+4vCteA`Q8Iz6vx7^j21KQg^|aQw~~i$9FX>*uFv+LQ8NV@Dr)iuuid` z97HD*w%AuP9X?8tf$c=Cr+&pZ(PsZlQqma&QN(#+eR;u=DU>Wg(NIX8`W3A)Bm6KQ z2H&G57ZcH|U+|1&J&DLGs%Okx!QvI! zooT+4ZGqB8m1~w&VNM-6X6y;(bu*yc6{`Bc#-Oyl>VXVpV^5zfoSky)7(7YkxHhC5 zh5Y^0um!9iPjyoQbYVtxKSwu_2B|&kx^~LWFk|k?bkeP(3#*!TneKl5KePO&<^%W(OnjX5k zNEQWMz#XopbM&N#unk~MU4nYXg%awVsxh@S19Md(SN?xs?!Zp+GpV*p!7#uu2sHv7 z@E?ryOP3&~VEW=)Q-+fVIRjA&aFy;NvrN&?9^IMM`sM)rv33lDl9Q2`H;D~N@QCe4wRI%rJ z__;zEDCLDcYr&`nVSow06tnG;J&2_b&-?*V^kVj`;*dIr7E7s38smYUD89qm&$oT+aLI zSA9=Q4h{#5^3-{@mJ%o(KYg3X7sHh(~`wSzEb zy+sek>-?+}AeAF;*-z!!*V{P=CoaSAGiw~%H8bf+b|^nBi>%6l46gv961nhH%qF@K zDF75FqI|=a(3(;*py~e4?Zi`gIIGGM^j$!r;;S=s3#EL>NhZMyG8~?A%X01V=`*^g zRTxZy>%Vu=7z+nVnZgo)4CBO|8k{55yLj84xoER54WhsjVwCR)(kY6CJLTLF$eXDE zkgqF1rI=xhcaWvf$Ac_)Jf!jzq^Jj3CK*aWzNHe~y8-YSfgQ9r@D&|Ltl1S)jFw<6 zB34aJO?mz^``Y%9gpKBx8i#-chMf#%FK>Y)ty3OJyeN85C5R(?>Yf8zV54wodsg<&JM-vcyyS`SFz zX~HkOoSy<@2p>tS)Z1WdZox$N4t00+Im;dW+v)CF$){_Oa$;OUx-rt)-L(ewyZESTSh$sqc@)ulNt#LAVRbzDNpHwl$ym!n<4|XUT&Ku)5D7A znKy&D-jUR*V=M|$8rG-%)r+vf<>;Xaly<-xu0#)gi7Rd#N~NzGeRb;qq5e@dg=07s zj1}A;J&A+Czf?ovhtLdjG({AseeAzE%U+qZvxuCuGQkq~J?SK(B)@wazL`X}46kU| zLO3{Rrzl)jmt;Zh+ml3av%XKAo%P-KhLg0u*M+R_-6(>C&#aOa z&dp~bZK-^QE3La$7__NYSA`m|5JkQU;!@DCV3{$ZYvV>|90@PHkEIUBcyz%fbEw?} z(xJ*N$kXyv)8&$z6h{TxK(zzg5Mma>QhD5t{sF^p%|5*4e& z{{RXaNk*_swJ4v)8CHU%Gh{NgqDbXtqwF0?C195=;S>z+qfU!ZX)YNqgjgaWTY#Rx zfTTRGmC^UBSVb^YbmGhWBVM;{#T zUCG6B7iYWpg`3VDz*#Alj)RSnGlVGiJRs&rc&3eq9tN(w^2&1bpFdiVB{OBBM|>;M zZ_k^a5!7M;0`dj}atzVVK$qcIcTP?xY66L+EG zWE!%oM9;|^>_=DpGKBpri2eC(r%Z=^ywTG$SHhbP{j2)^PosbQ(uAB)_M?CNHOEK) zf>(U$#L=%)Ho-rmq?LJ}x!z!Z-s5c{>~9mUf7`!Ihkd-!*E?72H(~qzXW&TCT(}+r zC$n3;JO@dsO|^~A>XncL51tE1z0>P7d~w#E2c5Y@v+e4Wxh5+LOkk(x5GZuCN;}cv ze+j~liETNi?edHWowgl0XKy-oGp$&)1jM^r($zjWwYJnYu@g30|06JZae@`_z7n-5 z;e-AzXqWJv#74A0#qFr=m8>2X^5s1yr^a!mPe-<0^BGFv7Wv& zXbKf7(eFG!3(p^WvgQBK>#Q?zcEolt0@xm<+iN}YphBUag_vG~=NF`1#OXLC2l?>2 zFANL;0?2_%!`T z-d&iQcrg5e)oP$pDd3_h0-)XaJ(ah}(1%Avf{>gEQY@kG!~NkIP`Y%0fCVg-$e!Cx z4jL$yI09dAiJ!yEKKkg{X)DC4QWlP*4~d^h*p4$JrGnxau^=Ez+B>RdVAa)bQ66TN zgVdZ1rGjIe&mO2g9C>R={H6vV_<=e2;yFk3p}x6Rs)nknOQD~<)9hGn+IMhBA;9#4 zJFflKCk*zfI*r9noU+glm~DDjHoLhK!NRVlMQL+4wE82E*3XTz&1s!Rmo=-UH z5Q;p99XRlu#t;!YvUoBB1`~-92@o_70)x=YfzTV3AZQjA1oqF;0bL6WGgRUkF334A zy3Vdlv-r2^sgtqqmmGLbPj|?`ml(Gc*7QTXYLkw}DEE>--;0d1K5#g)>`#KRNNidE z)rf6d(I~NQ+iFI#D^=ou2luxB>Jg;h9JHX(=qTf%5+X$)As8iB> z*DVOn-c?=@`~2o|^p>xap|AqK^JW6E!I9|?Vjmh~@zr{F6?sLr$IKnhoS7;%5^ zq$;xm(h8%B^NE1Z$Dq^~NJ@ba-Q#@-#$A!wpxF#92SFz8j)&|?-GW5k`rYgtV<89@ z{Os>U3W+(50Hq}3K*|z!qHAJHe&id7;I_S91~yq(0?A^IOduGBBvcOVEyg8e2-($; zhSEweB9Az8A*;-LdDZ5YYPG(|dU21xX7i8ql3NFUJ@qaLRggF*`KZ()!aMvL_K- zC;FGcL?dZTx!{JntQx*LPd34vK#V1YxD43SClQO^pU>ASt98 zR9)%-^$m{MaXg0UP4)+;pD(7#KqFW+;F z7SsWM1h|Z&nA}+gNr3O@r(%b|cQfjuN_5X-!~~U*YthOt+(6fyRlA4}!lp%-zWobL z(Z?9j3ttQ=T!}vSwTM9DOgsYLU?3!q`4I@xW-C$WYRjWoAiw}RU>zZ+!dWXI&Moc{ zgo-Eu^9Klru`4dN=1~G(RKFAgM7$=WCS*F+AYn4F1N;P*>hr{Mhbxnq96`0Bl#`;s zjmsL)B14?o-=7=WpDzuj4ixssOM}V%!?2J>A#azg?CV{Ht}1=KYgVpYyKe2O)evP% zE;IG6NG_VZ3&bYJ_wg^eO}G<%C}E#au%b*03y|tt5mKJ4mFg|Jy5YT#JaWJ6y+A9T zn+X1L+#3Jba2Y>4c9I8qYI6N<{@`}G%d4&29+B6vSeh`yVfRCcMioj7+ z+fi-uC>s({-3m$4w2g^iZqf$$f6_)HWT@J*v^ zyzs8*U*nTmYR2L@D~5nRH-m^dh*ps$<~orN5Jl)PcoL5zI@Qb+j9zrqm5(7avl4yj zIuginSX+3UT&-MR!HBL=hk`ipkkA(3wWK9G??TNKrK=XiE}ljhHz$^RC-iNztuoSn z$+_Ynm(t5I4OEkq%PsF-P&c%r)0p@4kJ-H#*zL%9uYuhl6JklWl#Bb#t;BzDO8dO^ zcAp*Ha(e98^5}=VTfP`m8A1jQuWPUYL}w3*Nw82peljpW?jgc(GlX-1PHZx{&6 zH9d-)Hd8N;@VkRy_&Q)_q5uZdBA7T7fE0c1h|Qdazg!@c($vwyI#c3n(cZ9h)V9}c zo@+ju&fB80fqexUfq5Y>Xc@5YyH$L#)BNPq2Z$22BK#Z_`-5#r4W$<5=Vf*hZA)Gg!wftYG*&p zPNQaa3<+7~EBH8eu*&abY;S5}uVG$5XJ!_Xw3CAoI63+VAq-uRlH@$lE2oVAZ$tFB*w)kCG1lIG znX_Vr15VRH&@8-r-xya2f`r16qH_*6_Jd!pSi!*tvgSZ%8a+*5$!NR|TH99*EA{zE zp?fAG8@kWp-<}Jan20Ooc!!jhSbfS9h_vjb929~lkHZ~pzwGX5=tlUHl|0?CrTlbk zt9=*Sx}C2FPkA5`Gu8FUcTCi-lm@DZOnzc7Bmm{Smfldlp;%k{5*z;$p%;pXKzS3I zjkCUwfgB)E2Jj^w$zPgRmNRE2&2HP*MNTbwl{0PMPTAw*EE323wEuK;Of1QO9L}g5 z{`8F~%+v}JvHFk<5fWm^4}&0@tB0iPOU=ymF@lE*5K@_1_o9DcoNA?3-NL+rS;#KX zQWW11mOQff`fDd@S0VafBsaRUF~9-(*Hn~0_2T&9+$$m%q7emq!)RYSwMr(w789Fp zWTB~%BB~tII_^o3qOwQizy7Y~A60Wuu%u{WYsI_554Tn(gwFb}k9Y-%ByjVMn!k{2 zt$*{|-N~f0+w^Da>ssl&8hBu{KdGb95Y1~u*^Dyt(9<0RUz$kyF-KZcVvulU<(Lp` z>H?`>)}`#)T!|j|U0^LzXGhgeBRRMV7uE$`?*Tibf09PP$E4oFn@WnUg=EG4H?8K_ z^Bv&?lw#@NJoX!tM1WoAIj#~k1eK*w zlv#D>#z{DGxqPXV3nrVYwqfN}LxNS%UlsI+oh0>1fRWV4JO-)8RKx@OS`+WX2Pm+e z8ri2pzkRK%LAOv@CFz)UclEC6S=+mo|693gUH8gWy?v|tR(JQVU9)mcPv5HE)vJ3~ zu3NKa)tcUwYr5C3S))c42Tuhquu~3*X{J+_VICTA5)qc^YBlz zd1biOD0HKHxa0I$=tVrTZ}Z8i#y+TH|6Kr(9+k*xUjvu2!H^tJaKjS#oO0X>pBd>( z!wbT`LRX|j@mP4A$41}i;;Xl8Gb7MVw|~2k1PpIlWd$xY0Q)gg=K5HGPXHQ^f#C!+ zDR_GgvbVQ?TSZeZEVXa`L%0|fp-QYNBS&~qCR~ZE8;6LcH|N_QJ@gIec3y7kB#i_{ ztH^F@w}xj$V1lE>V`4=Sm<#q5WSh;;lMZG(O@UaE^izHf?eL%bx znJjk418pn2VckthJ2*A)Tr$U$H11@$ww?}m5LkGVQ$3d+f^HWTyHXl{+O35Orj9b% zJJ?h~6(zSXpfWt$$%GqufZL0VOjz}5$wf%-HuG+2OPZL{4ldTt?8QNLT>`s0mS%F& zG`J)d@F^3C{Inf%p#~8`a6Hn1uD&vG6vmEh@m_dMhof416}7ft1lEp}$eTA&7>_Dx zm`B^)mn1=FZNho)+F@)$YX=HC5dE9?jobLEjpn-X1*EoAHk<#V7SViQe_`xZ9@(~~ zg7IsK49aFtr_YjmPfnk$4Cyn=qtSccJPnUVAA4I<9<>ZO zGjC$tIq>Gui$DGL8L4{332x*SrqK{Y*tt!n5bJn)VxEp?C_T*OOpjQ>kzpGO92g0U?6#3FpJ8h3k^IEk!rTo*6o-tF%t7aj)!-y zt4O_tv>{^3@5lwJ@AW_~Wtq&1Cy!uSI3Pw|inWakLrlvjxUX3rr3!-6W}5}e@ef_9 z6geKDC1cBIP-{gyf%2&m`OV9HtvHAdRBpHa%Ufy2y3XRtuGP+~ciAH+uKIvg5`AvJ zs+~3Mjt%`uP0j%Dr@|g)`Cd7Lfhlh)p;^4v^(~>JZiixGpX4hE?&KIAvlPS+FLB1K zRM$Vp-L39N6b`OA8nB9hjNy#0QkWDuYL9>wgA8!s6p5D>q=^f3V_Ujr_fB_V( zG)-u#xrl@9QL!SePwnc80Yc0{&d#TyzJOHD1f5Vl}`E%sdokGu}!kD!h|fc z5nE65m)Xvnllh#AOOGV^9Y5FXfY2j9q7S2|(cItwN!hd}>}G$z9{%X;fec#T|B%LB zr5ZHgjQ|2KglLrkqt%PYukl5z-44xu&%|>>TvbEtd42`-w8Y>vUTt|nR19`TLvNNN zrb#*ar4_No37EWhUpM>=K?@RaHJJZ!y1V;$P1C;qoMy8L{BPUwjfJxDZyC#UXQyfl zJ?+m_cugs!OvZO|03?N+6RMzNHl)cc7FK7^kU>|YjR;me1V08Fi5K8<@-jKjNi_K9 z#nwwmpuhw8SSPw)db=)_p$)s<;K15V-$P3*B;|}H!D(fCF@?0D@^7%+U(rQ&bWaPz z#g6%m2>dzd8WFCK_3*nmg?%~1YY)Gx9$P+`sv#6p|A}P%QiTpi|E7OIB9>CkOV=KW zW2yEuo~TK8zOa&E-c*Py^V=!wC?*w+Ks- zF2##-vEhpo7}~`H0vJG&9pCf0&YX>+X=y2}IyqGnZu%EC0$|YHSc3O0DcN}-AQx`k?CSJ+Vw^Xx^#56!Ck!4&!q4Ep0Mgt$xJGJz*t0lWOyRDGz z$Xc2>68^w(r?br~?wt6T5+I2*->{1Aw@!1gY@=ol;4@&A$%Kq&0Li! znuV;U%o1w?#sgp=N>B@p(clTYH1j3 zXN4R^A$JHJAc-#8D5KM&h$5@J8$jEh zT0LuaYIXeXlT)kVo}?khWq^9-waJCXKHN>qyPL4QqtE-NcQv?TnV4uycjH4kdm1Vv zpO~D1@&e@yMJI+!N&F?F8r@KxAqz~=G2XKikrtDI);qf2kxG4V<{C;Iun*E?ic zkRyh9V@gqU&kW9j5icy{dvGaN%@ielJexR_{5m@%;m&Dv@WN$U=i4d>w|YrxH295I zduN?Ir*5C7xcO6f0jft$dh_+||CM zXGNccF*j}m5Wdg2+}N{gAoxxrVvrSV zY!bMOoH}Y?_s%lvisW8%TbqLc(4`ae@Ju&1z|Q9dZRsN7QXyoKb9n|r^wuNBOZdDo zjO3IKtOBo^%BgRFhGQN`q)R=XL^))3m?IeZ5E`N&od7~(pcjISfry-q-TOw^%v;|H z1(1rVN%&Iyqm)VG3~kt;Z$(2xQ)~Ygv?8b`+r_Tp*@CRLBH}KZsjyl>gMYPK@@-l z$x=>XR|_J@EhXTRP~-NnhRSqYg;nYvhj(}!9yY#Y?R5_;(T{62t=$qxVj8O`xi6^K z1XPlcCH$ICfrN|e(ZucfmIRh(jW=XT0(nnd-Vz$MZ4A#bR!uJVHlMqN$8nMlHmd27 zg{I=hjFML3yoXl%+~JmY@$GRpOzXRk5HJ3tbMw#3yF_8MiENv$2bb*Xb?vy4^P%hA z2irQWFW2cKs4|A99S2a&)_adxQb6rw^gD0ELzU>eKRr~+1Dw3HxX?GGuw6RU4W`f` z88?B>f9N)2zVCIfjawpvpa4@w<>{8{A?~xG7-9!*4({4z?FjrG_rcPrFPQCZKX*=? zU8od$evt9(^*)mYH%HIr->ttoIg@2=DCo?irk2FoGAn{a)0SDD?d)mCr>JOAI%>=4 z2g`dZ(G?d6eOP7Zsz!-S;xzP%3+fmV3|-G~Tduvjjz3cVE2C8qh~HSxZmM;|$>;t~ zo&B+2X*j^Q`^5T2hmHa`-dSeg(YSB>Fs@>>se-)IwrUk1hG3dbwV;p+F_SL@j$$#*?kJZ#{Ma0Ct zFI5<^$h8s8SBl;?l_ode?f=aW(S1%!^AHmBe$2cb*sYDM>@~HsOFq(Jl z!9HuI1QaBh5^ulpa9*1#sDpwPY85_@^}z5)aR_`&IF3FfVLAf|#zPJD+W%?56`Z(F z#yM@FbjBFAhxcj$iD-Uo3s`(^7!kYIOz(O(g(dD7?hasLHO{?crkel?SO(9Vja|^v z@|M3mIm;m2#WK*d5L-c7=58n{Xw3-LS~u7$x+Vhj0@66{I`R3K(`mQ6h?XH!=lt}E zU`xa~4c`H&Il~0Y5WSl`(*C`FgX=8a9SgP{r;r_&p!O-MTu}!UNGZV$S_;^#4*I`o zMkwJD>He?_56$fdKkY9%uVr=ZfQ#45e8r-yCw1|Ene#fFJ!4bQ<^ypG5q7s;z#^xe3+;4x-oL#}T0y|;*0xwi3eu}bE3BEDBUjtd ziVAY5%0!i1IuMiB_>tSchc`uN84D$r`Ist-kur@XqBE3dvA|N0FqZn{lIGZh7ZFNa zM4dGh(pl){35nHl>$lMmAGzEJ~l@YBfJX{LL)Zzy3bipB5_wiP)^%7Qfm0dlvzh zFnVc5$JXEn;XWo`))wc2N)^WFc26JI%h>uSP zCp`3V2xNwFK{-2NWWd9#f5(@iLK2U?<=j5Fu167$9kl-G2FjYi_ui2X3Mc$!;wiLh z5E>r7(T&SwatYWbZLz^Y+)Tau7FVzox&oQrVjd4 zv1K)L1w4A5VM{@n84a_zKw}oLkl*R81G2U;c$<9F#J_vxgD&?i}e$-}Qco2k11*;CE8+kXXH{bo=A*k)t(rH8r znf{Qi7!NOuKy+F|JG=Nym4=~aSCz>68X9+ zitHGb!s)1Tbl>g1x^R>KS5{#vgcFjjKJti32tx+ifiQ%>fCRBjHUN=w0{DO*@0ArH z1H!kZ&4APvGnCW#1!d13h!rsUzuAa2=a_^!FI|n=k1}1WI zS+nCNTTJe&Fy!|53YD7J>Olfu21Ms@oI6k=aB&B3xnXH#5{Sg*nGgixs>-3i{17i8 z)NO)u`alVJ_yRkkZd%Lqsolyv&JkH_RuG|Q6cIC{r9Ts1P?&Z9rkd&DLrLw?a`d;!AT6Uq1vXPw zq|NJ9qi}vu8TzpiDK3^srwAPwbR4uDw1kc@jBIC3%05ZbgScKX=eXsh+EL4?YcDC8 zvZEIXUW93xjWTG{crP;h2=?b$?+Tfsr(yzf+&!;mT-0WQ+_qI}f?)38%!H@%m8#+r zC)*Jcv_U$A@YoIE0qVt-23lO=36CFsgURO%u0qFGMy|-g!udb^hHOQ1;>ATDf&w(J zmwX0{Buo;J4rUi@@vq1T3BORbp!W#Q9nDPPDzs2EeSC^Gs#HueSL8{;$E^eshY>hH zjwT*Yj)JVrxq8$-`O*|}Jdf02(=lGSVMopG)DBsIj|Z?1IQw|B%lW&M<X8X{Yaw+j*$7y#?E3t4D>y3ySaTuuV$DjsQcZrE$KSi z+P8ppTTO+g>&-BIByIMPypoHULx+Z>X(`Hovq{{cQD6fJ98<8GK~VjT{kFxWNks9g zG8&hJKacu47LB30Cq3k#{|FLWFpRVVMw?laEQ*I8E0J&PNAZKXBb5XAia(w|JEP{k z-#j^^CfsF>i1iLPfoRz4Hsu{!K{2Sd+vp; zvWPKFKX5k9cp*@!!acw=BsQUJY)SoQRUY97AxltYwes=TX<^`6nml{TPop9Zby0B? z<0Hw+W+3UNRf4jo{pb5S|6|R;%Q;lWGL)(inp#SL#4UIGQIH1o0jsU-gXVKc1zuD6 znHL`-TGMG%U0yg(yexYoDXyawX=G-^U52bj3-YKGnAwXo8Yh=Q!=;><8U3INZQX{S zaEG;DaWt>ik=hfs#hB_A+@j;mT5alfB|74u^A>NcsT{*uaUMU}&P9Vqab%`Al1ar~ z;X|`?>8HLYRV%x=pI~OIKWV94!m1aE$%$wQehbOsl^t5i68Xg+67hJFV$R%~!+Y3W zGf=HPpyDfkBZ3?|Q%~-L@c}~wE)qKh8HSa+7VtO+#0B3a+!Ahtx4RbJNh_;xQU3SXqZ_%zb4s7{P?63y!323i3b;L^*BA=nQ||=2%|PAmA)m(X7_~Mn zK|w0k;+v=`Qd@VfoN>6rr+)h?*k{IqlZsmIxF;$g_HgG$>nDec_Mmr~Rav#J>HzEH zxGL*kmLtD9f`-g2DJ4!f5_GuXJgwV~lEl<9UYn4Vm&>hp|MMO?i~pXO0rg0orAA@H znR&1fj?1hxWxNr?ouesdgLhy|=Wlm#USl*RMvfTHd{L%99>Su3@e~n;8ys+HfOnLS z)ogO4M=*oxTF5)C-4?mRCKRmT&_|K?YbSSc7=*|~7 z$L2r926w*oJ2#Q&(dyzqDXJMoCZL`)Ho%%m%tq9@4!2(T?}F;jq-H?1F_hh^^E%K< zxHdQzN{i8|9ZclC-^CGQi!Zq%)e3#ca(?cKe4cXxA!z)d3HeoX1@929@AQ9=;%7Jw zi%R|<-zBDWeGtYVsJOu#Y<>StM)U|GF|-OfaVl}f)nspQ8zKD}`jntvr;gLDWxOi* zjdcvVCAH)PutuzX1%3{KLHy!HaV1S7#UfP&;Nl~O;1Yy49Tp%%&(~rm6ZwIo3(H)> zWwG?k0>FPb81kUW;b5)on0~R8N#W%}PP)qlq+~HJ6aV2l{Spbn+x4Q9K!C6A#b~GK6|q7JQKU>|r;u8YCE{ksNn{-k<@FLN4TnsjE&aiVg{lE#WOr>E9*aX0W1P z&?SSK5vh{3_e>+S2Xm=Jga0r+Y?wNc9E!n+)DC%Ok=*a@=l>X1pjax>zZG`im){4Y zJeOsZIWe>%pj=WaFpX7WnNchj+KO9fY8% zfx>n3{bym_UZoAT8Ds7T+HLjJE)=sBOx_6}n~anHIdYBn_wf)Hz3BUHMBZ$>Y8$Ra zusMJG)z(P$68CRN7gQEFtT0@9kl_r~xHnPJ<9%`+8wf zVPgDOR0kuCxX3wek~k7g#9VSQ0LH2Y2!l6tH!=hkFIHvn+i5qA<_a{prTP_i;eK_1 zD}ZO1DEMvji9U5(of18@OmN!zB1u1G5fNkUY>NHwGdMe4aQ0$)+{F$vjab2{j>zXH zB@m}&yKoa^3~n;J25^s@<<=fsraKr^W$01u$5L~qjjpf9@^QYd^!t7dTw~c@si*gZ z&Q3j+x_P-o4SG6n-q+jSz5=#ZbiEKzAy#BpGm=57uqatLJg;`K9ih_(PC5gV{`ps+ z3-!`5-h2mg!sU5%#j!A_t>`6?kYH|f!=1|5 z)GK-s=ZU=JA6@@PMzxk6&4+wJnhICl2#HzGMxKc>b8LJ<*~J>UxS<@kd07uTI9esL z@d+`;+ySc_s{~bFsJmlqs%ncVSMJ706&|HG-NSj=pAx^M3Ejhkr&+!Y?x8-RdnmJa zB1mBN9&EsEy?J?Rnb}vfX1l%7ySCZwm2HKUr*pb{3O7aubOBj#|J$*zxYuRd^maR( z@E5eS+;KY$6#REK|33EWlQU9QhRT3Qs6tnVNH$)UdgmWji$=x6|<2p zm2pIz(H280x6HFL=)d`Bjb?^T4MMWwPtWwVMpg8k|4n$**EG?J8T?E0gvG8e#0&p@ zd5Rqm7JT9kL%bGjaVy7H&?SG;=FPiy4D8st-f=?^ z{nFK`5*hpqPtzhhK6*uw@d|6s({M9o2(XLmZCn92a-5lv4iQ&;8D$BK;o(MY=+V4A zJE0fx;*54ci8k5q24gpR^Fs2us!AYz!S!FZvV|Kj-Af3MAhZWpeITqd^R5^yhYYd9 zk^iXrq&LoNsB(t)4lxPDwccOExK=H2XR4wd(aYUl^Js`d+Lv`wde?nT7qwNon#1lmZxrR@1%(B>BMjC&I+eDWk4dm zROWrF49)3@R*v9`R;o)Kl2&eYGf=@7rWdO`OCpgc@pr&*R#h_aRB26p+)B3TG^Wnx z*O;x3-tNgai~y8|PEnTeDW#fOmaFVkw&_f*eP3;qZ<2Gc-!zU}!B@?sB}t=fUbAyr zRVrdrJ2oC!`tf%(bGD(cHadM>Ju6S#!`1_8)(ypgb8v9+^t2wX28;sZ9?!YOa7K9@ z-@7HC)A_d3fdv&Xt#e!7Wu05O7UQb%(Rc8^i$NrEn|QX^4ca&2;lc163F(}$3=&@D zbK;fwjq}jUO*s}Kl3wY^v*Dgupkd$~4``Afy&MJlL>yD|GHapei+g6$3uj{_wX}S$ z<>btyRUtFUHAzFOSFAS;;V1%5)-OJK?uJeNQe5l;L7;Cu5^#=3JntC4;vkVEZ+y>k zQ~Ylqhwv(`qZj*KWbUOg*v;lZ7(eH-7g!B23n$q~DZ0wDaFIvg8+Xzh=You^Q7#e>1jUZ~7+t(w|XpMqYXQ9Q39nYE)U;N&G6)s+%@< zReqHjefVXb%8cH1ZWGmpPgS+qk#xP+j>IxsY+_ciYw3XTZU@%ftW80bP3 ziWhKSeLT@zp0582Eg({WGWI8*YPy5w30+OEguZ15;bEdlLvOoA587_F3zZKU!&~%* zbGS?Md&XwiB~~$XhD{vbRynjKsW>*6O|#g=J{ia)!v~jcG}RFZ73j*^wFb4LeCmt7 z<89%>$eoQ_Xl5YJxmwri0ou(b5g1>F55I;nPaZoS=A$3}4KOdYqNP~ZP5B>n$ECoHbK*c0AJHsx}FjCqS+Z?U%B+;jIeMo z+v~q51hKs2^41Itj z!BtL2Jk2MWBl%3NIr@Do4_5JptX(OzxX5NH5pGTvMIhYs!ik#sSa+FUcu^pvKoN?v zUBgfmWcv#88jZpxq~M_u@>1z|-1P8Nc*A8XbTmWlGXj6jGPRB3!G#q^C_;eN3$Rh9 z%i#t++~CZ|+wtSfIqR+W%^G$(E0O(Y9cP-ROPgMHOkF0MkITT;u@Dfq#olXUdldb= zEfz5`)B{StIp_wLSk`HA+qT>=x_E?(1&=N!#SAdtU>a1FBVD(moD2z(GjBVXN*;1> zSt8DPGkM~m$;qXKs>WY4Xb4uUqS3F^WgsKcbt}p{OjNCi+gx$Mqa5|ttFDvPLEJq| zn+sP$SEXJJ)&q1V^%lM=Txu^JE}_;xc@O|`0%;S;M|cFtr$Zz!*ia5Qb>ZR{PL%r| zd#c{Eh8MSObh_kUcXxLW|7UKc!vmeG{onWSA0B~2QiFX`iAX37YZ3Yi4oWLp>}z#)YqJ!EEB!eAKNk1F>S`fC{>FIK_qf7Eeu_H#;@) z^}jkfHPNiM>j04sB(RgSmq6kjKBnLTq$Xr`Vrt%j25H0v(^^|)XhlOez&1Qpt!?5s#ekR6aRwF~eTDt*Cht8b{F*zXzjx^o) zp}vAL)t|~$64Pr}MUht`-+U7;^+cH|=!#{gBhp?}&f6HB*R$HM-rI~m#3>T#`^&4Y z&=uN+%yxpnKEZ5|t48Hs18B~ICc`!Vm#fTs@GU&mgD=`qJDK^Z+!~SGA5Z7m0Q1Qm z=5L%i<1t)W<^CS;SCn$tPvgFi)t~^8Du>#F}w9HGa96;_dUd#_Xnkp?=Syz zWFX&s!cX3#By2SH!uBY@Br}P%nWO7yIf7dQSue`dIk4%CSwiPp+YQ4k0ZObvvfgJ> zoIg90;*p0>&ZJn|B>e9?g$cughtQ6v0-E}VI5dt*%pq+<$W_90;H}pX{BF1%h6QlS z%1oR{>(VMRRu*Gke6Gj2aSsTiEJx4%z!u?yAb1$qf1Cp}k0W{N%Nl{#X!GBAmxYaX zjGm?=fNgShIX~k$D#~7{Znx+gu)~`D+J9b-Cvg*l9=O7V7(fpXr>7Rttj0;cl-zJB zcZ+N@##tO~y2D6p1ncsTaOyxwQ6+NuM*x9g9a^BUAb2IxD~=FNV-DI}JKY_)&0Z3~ z&EDl9c>?9WT-7%>@H7YRQUg}^sC6&Z#iGMe>*rCfE4ai$mJZ9d`koDk-LY-&W%s;_ z+rwjW>Vkh-I#E9VN7vaVW4x>xB5WM(8(-`27M5+m;myg*%jmJwInv;aWddAFmYc>-k%c07O7WYL3h_w(hP99M1BupIHbZO5vGr?dk( z;BcX+e2JHHaZf3a34I%1?6AYb5^$fRLu{WCnc#}>bYd{bPkw^sp#E}rG@soyQ&Jv*5^-#t7Kt|^MGEx6W*RUM!p&$>I-AS7=jE_U8Y8A+V^~i@ zXo_L5i|cf1B%^6KF)_HmQBusbGGFY`a-%dXCHQk%nI~3E({C5kiP12olZS}lpn#Ya zkh|7ka5&F#t><#LVos2PhSRaQ3E0%L3JfbfzW5J2vwGXR*@Uz?+FOto1$96EMIxDZ zAw6M7ppAD@Z3qe5`k8v{XC5EdNq8!5i5R)dG8Io1F>zreHALa|k2tP2Z6{Msg>|R$ zV6qapEScv)9vrSmMkH6_nIRblaRYl+S1guHtZ-oeP%4Rv-+=2i6WR@-RwCb8;|qh~ z0KbsqG{`q+B$|_dJU5yG;#~nB&*k$;o3kj0myhnLdM5y>TqG@aT*NAlwP0@fST1M8 z^@Bzi$qLa;m-4FVBIinQcIDB_%Au9Z$-xs_I*O2G;g;kKk&zZC%s8lTi7@8e=S6bu z@u>%xF4ExEy(dj-xzR$BLRuQPgUUE)8}@gQRoCABn~yeaat6Ds$b|Xig;8ESJDcZw zmz(fVsW00 zP8NP}05`x^@RQ^r(J^=f+i>J1!#9eejt+k}pr~E-EM}&J7gc*n(2Lw)f_d=TaA?(Z zQ3lKB^2K-wlunZ#doGtv%Hdh`m5l4XdV#UmgKR{jdDnpD5{Z!Ug{V{bdNdH2u>?tI zA%lrVmZ)*+H0{pOBQe7({Q(4+RXEmWx&rmKJH{kD@_gVV1XA)~GW+bqq_;iK2otX| z!#??ZH8>`=5QbdN~EHC=Hge z;v~OWqP4z-V$l*=uDVdN;-w{rU|MNk1QuKcmg|VVB(0eCSE#>qR~=e5uj-p=xd=}h zQa0NXUHL`dauMtZZ;R7L(|Q~>c{gKza%`{O8G2ChVjjg!H{EC@Hvi54IeBWYf1G@dzx$-fS4!Gj*(t=q~Ae2*yjJ(2TB%23=Huj-p$T#_q1h+IKhWHYo%=JCitWr z7Y}h*V3}>{;hJ-pHr_1KI5v63MJ+ZZ97?hXMYET5#Eq?pU5-1a^rB}}ymx&>R%s0~ zcS8mDzBV90d$$@J0E=H5im?(hYZoW101WfAii=)fu1Dl3=d{Ob%w0>>Y?X+uc2|J` z2TY3fR|Sn#w#A1@Tb28a{L3EA9ZKeVrxUDWxWnY^(8>kJ0O5V<;IffmNye)Onl)uY zfDEjT(+;$8d*xm1DR~a3WbOXI2!GL1Xf?wR1{qlqiC0QTE6~6DHA*Y0ZM)G^-93ly z;-5i=(OMU-ZC!iqt2JM{u1ijB?kHu@SYi-8Cd3Kaj!np6x=>RIDrDacqQh|*xFnOl zUI(X}&2Ko^d@uXGilHcv_+u0PQ_zT9$ios4Cdx>-F0hvSNe{!QK@nfeXl=R60OE!O z;vUI{=^AP@#_*$UKIAjHE|{Is^`jS^l+o4KtShe|W$d_Efx89-E^|uumxKPZ#EPnq zJnEvVZ7-Z=wp~d$72Oyc7U$o?pLj~(d~Qdqh{H`kAnGOOWiFSX%g3)fXlE#2_AM+rj+waHT|$+tN$&2{VL z5LO5!xXFd4is5s%7gS!PaZXBcmllvf-W-T1Ev{~K>OISPmxUvf%k=&_FO-!lfj7N( zMbiY}Ykke)*~0gnd1p)yUm`RUp#+!)4*<5$5A0!vQI{!ppn~LKTIE<)@3NKtC#!f2 zN(smABoT(R$U#_NIP$F>&Xn*)BS1vvGVG^h7pdBGn{&Y1jp&WpqR(Dfa7xf&z0Pse)oRMqO9!hB}2GhvR<9tb`2M zLW`myh8POeY^qQ|xIM#I>V03>16|=NF6?1$NTdlq4dqAV64H7bjQ)KExW~QwlK6>1 zV6y$bZlM6iDS^VRd<(!_QoD-~cH^cVvuy;+ZcE>S6o|A&oAd0ec}hZ5IE2{U`~nmo~6gxT*DfZNM8w#zyp@iG?mVtwO}_^0P@H~ z)?xc!9t{T#UA*S?I6FmJAh{s+5i7D2581`dJ0A0H_OSG0<*C<@=Ycb6Y2j7+Vy3m7 z^sA$Dfhw=Vtu2q*a=yA8hGzA8H<|RKzbT5>^1zuO3AkO}V@}OA1npzA3pkUyuvu-Ry0ZXKYQ;@l?i~)b?)eF;7$-Jju%DuDFRD^d0AA&|8jme)Pk0m^2 zd-2kb>l~Ze}0-30w6bAS731MGC{*Nd|vI35%`tp&G(Q{Tq-#n{m_Sm))Xkn zNj169&!V2>kBp6S7=;qH$T*@}`#2~?&~TnB0Iox)t+rGof_JpO^$oGrufk zjqAU~#x-n#NWJi(wHaX5f+-E6r=u^}7Jgpv5fo{LwBr(zgwK3bBt#V=9xn-d(JX8! zJo3A1PR^X_g-3Gtyf^keI&t??ANbkVC!~IbSQApsrPGK66JHk7xW(b(KePS4xDsW*aQ+a~~jfAg{wsDBYUIx*y+W z4la2*uHc=8+%8FUxjT!>KdK3wQ=#PmktM2JveM~T0n!5Wy2b7PE=L?iMxiqR97H3S z_)M_CI?x?*4=vN^WpA?*$n{0-xhlbgzfsYlksO++dRBlqn+;)6Ri81v-(%c|0xnaB z5Ga9P@qw)s4eQZlHt>yHV*`ss29wynNC1t=y4_`~yV*=mY&rI^oLal*HO5izp`+f9 zX7qPFbkKn;fzg5;*lsxo{`k~Nc^G{udwTSg5g)G{vyTJX?eIukBaPj)A)G45T*scN z5Dv8X@_uvl2AnF4MT1NBNH+xlqJbwGHrVpCD%>|0-JP&Mlo7ZRJZL)=1z#riu%rGD z-C&SwlI*gM>3_V6v?_5Q)~a$9W_0i3f#DL4?JyosXo{u^fq7|=Fb@5uaqYBN!D@Aw zjf4axUC@{%L~XGl6g`Q#WZyC_LbZsSnvR}pcmZB~L9bK{-$EH*6?0}zE{3&(6ykdr^2^~AI-BC!v2a5v&sJB} zuayz1#hkgf6yf4~??o{>vX!QBV9`-01-VKrb{9*%@4Z(=g}KMc7<+mZ4KxJ*E+N1) zjE=ehN`Xzf)SLPEJkth19fQ*w3Cbt~hwY(^I;k<@$U?yIK-B#oWeca0z^zAtR0@h$UAb_$eFS)5j{gyrFCjgVdn2lWDx?zM2L( zC&sO_K6&I~tYoLSQK+9p=QdD;NB!g^Y<|r3-h=`85#+M*kJyzv9neZp1B+jH#l)3z z3Nt^>LI6*Oiw_AqQt79PmiAQ^*jB+rkcDxGGQ?U_aX-VMnY7jg3AQu2LUF$q>K!z} zNbGhqDsH;7lq9C&z-i-Hjzq9fDXEeFc2B^$K>@!8237b)xwM4#v7A6>ikD}Gu93$A z`a)qdBSGHdyk1E1!V#YXV3G%%9o|BaMIXLVkS1peg2?hfYKp5iIXtm2@nfxQ;jJif zk_wOx`aw04L8c*DB?&dt#9wjQT7f?iv_?O8o(H@Sn;zsKX^m?5k*Sa`c>F2W@}TbJ zgdtZYm>eyn(h{_3MyDZsle@x}1APvE;Li^$%O_0X5Kak;L09ito@6CzeL zzDpct7X~-l(8P5M@8KtI=N`JTJju2j70L{RUwBKP5{}h5+j$SxCvK-=fc+h_k~;i6 zg6k0VpFM|uAfLyxrZ9@pH;(b%0Xv2z^T1tsKH|YZ?>j#TDW`6l9EY7nG0&)8MibX` z4Pu6Qg*u^*aN=Kbc~F(TG^2TkCXe;98z`9Gr(CEP24OrM=)m>vS~`iq2SxdocK+Pe zzNBYG-;!z#_EsIgAtnPz^GRDbW<3em|F((ml35rZEiI>K@6GOnc zSV};h9U6g}A3+rooFB2ZKuv*TQ{ajCH#~>5ks-YDM20{~{mK(fD%6BSrY@;|V1meZ zW5$vf7#A+-khlWuk;x-Vw(Zesd23d*S*#!sf;O`p0EM2ozt%k1@ErC(^yudMaMi73 zuzTqk?*htl8L+^1I>;i~n5C}jWkA3g+}e94YMaZEWp9Oxh-WL2Wk=m_h4YZshy%+b zs6evFM6eF}EK$NWZBE;0Az4D3@^*bcKoLk)eDpngAfYs=k#rWJBB;Ir>(H#8zS1?a zsS?d@g*Up0r)Y6Ij~n{X2lnIqEduGdKq@7WkiF%go6?eg3yP#b;Tjxw0f=p`x^-X( zYaEBr$dwL9KC&IbGtt7`maMud~X6RFc6zL-E! zONU1iKYvd@su8H(8Px)+0AGO+dTD0DiBBCDoBYGz(*g^fz{gzlayoOF60_TkxWj}= zAnTEb>=p~#IRwPpl644bSt5oIC){W*^}r{mE_?_K!Gn?@5dY4XH5p)?djD4#k;e`h zsX!C+LS^1Ryf@~$@D_SuV9|em%80(>T>}z!^1OR4*@`P1POc`?IVfS2+@qY2s!9Be=EubZ?y>}YDJGx9}jn=n! z`g%JNK@ECRk}=%OY835aqlaNwPKe`gIslxhKY-NYnxqWLKsPWmsN%)J%;sA-drSzM z3}78$`v@f{r1UrUgiE%Jl0iy9ZB0n#*asNBbT`G-A@0Jp&XjM^p3%G~fFFjO>86eE zRzXU7WrM@gGEb8)ot-8>_wPZUg=_>0SW^J28k!R$Ffour zWjE4zr7Xid44I(C4sccunAvuR>RV;(;r?BgT$YPtYczE*N+Ex9uoLPyI)q z9R#&Jf8n4o-s!PnphqqtPiBctaso$c9)QJydC1sie9g1|YoK@7@UQ)^y%u^__sS#P zG<6A>GMpU0gkZVn`j&5W+CnvXRvm;srdpVJtj=d~tYy#QSS#i*7RaXAj!1TB;QvSI zs7f;Dk~yICcw}?SvpCkiXK^fu-)E0EAjD@sm}l8sJUh$g#V1)9x;kXpG-CnybhIm{ z6-om}O3hk0VQt3|DA1l^;pFxN6f+d#CgwM4q4l@Xr6;-j~41 zRh9X6x~r3P5(qLX`rZh#C7q>{Ueehh!H|s>ve4;(A`*J3?v$ynie1%78c>)w;5-=; zxs;X#Q3DPjaREjhbw-_W8Mpc2LqTv{sxS;PN@mf?h>D8u|Np*o?mhQbb*DNZ>R|hu z0s7XxXZg-|zI~Aqk7wacO%&D$`i+bPGC0n4e2bn9OqVdIc6myVm}p%c4>dwkwRO*g`0-6_}6Wd zHsx2gMe9@UeWu-O_|&EDi&(*$HFr=zY)2phc1%d+WrENo9RdOx zq{#ZI!;y*XZf&HyGcsjqj=R8Xh)vUb0Kx)mC4^`jWi4r8a`EiMM$p83XqFZG;wRnX zKgzC%Z@>mb6{GU&4hqq}owri3Dn-=X2#eWpa}1}d`>tF+cgo2AaPZGA+cJXGPddPu z0|A=@E_&fh>><$CNN8qZ!&GA@E-<1Q@dd?V4(~um;oiirFg~7RflAjNl7O3ASJaf=0(RiV9vkYyrR3IN z$dF|1?%v+`PK0UmvLcI*^-0(>EteTdHDUXlE!({(4j{evz6ygbFhQl=IV4{s#PHXL z*l%1J5DSg@2}1H{-WNp3mCintDoHrW_x6;|?jc`3J1zg*V?!BqdB-Y6!s|!Riw6BuW_HwRatJMR4VsMolk?ZlnI=Q|vZ;dbQk}`pYvy z+mMqj&OH zf4=VYD>9ND(2I;BNtP#K(MGe^tNZfXkyW?nV>NXb{bHXtW#*q9;&)!%SFb7#vO?zw z4WT(|){<8abbS!XgfKCi6`8i}`PdgeX8H))5Hs4E1=GQk1d|yR4VXwK8@HBY5iOVw zTG4P%5^sVWH*g;L1PBjOY0-}m9qb+wGsKV=OTPnu^GZ<~D8E+BQgQQnU=ruYpw=L( z`|ds!{M6fY{pD99&u%tH;PsHwKut8~WW?JezxO-816`8w=nH+p3mQiiec_Ve1$gKO z?9T^yiFlcrnK=E6S0f~RHsqwa57N~E2yMr8B@3iiq(WdC&fu$LQo)(<%{@N#Z$s_u+Wfj7SL-(9K-?*O> zeFek}<|JYe^pz2X1(bpY6BmMmZ8hBM7gI5~gNO@Tc#MIdBpsPKFeCJ1XT_pWLTis_ zE8%chLvgk%)6J?*rknG&amaK_BiaopF{F(>6azz0F!f$t9>8}jr68&+57>9`)cYS4 zq@%<7sp;Lxfp`xnbT3nL44bHb{p>?v1xelw(uaA6Y-5&ODM9v_e~6J(Pfa(GRQv0W zWMMn=-|}K-PM1WL_y9(fJmdKV90uqev7LOBq$}RHzxLtx+a+3ouIF7i0@%AubKvg6 z)ukq)WbJc#%2ip=;j2sYin9wnxp)@Czz+{slfPcCZpQmX0P|O4W;LWFAKUwY5(zl> zvseQhbh%G%1cu|X!`_#rvEPCMB3BCkE#xQcqwz=gV*m62_G%`v?$dm%?Iz38>@(jZ zB7PvWoxnSi_l60PCEcI$OQ3T#e#ajv;m%Sw(o7~8&d>t_Rl^Tl zMr}7C+Cu5<)r}5}{-xiZC>aGSGaWepoMzPv#BD1|11-iD`Drdb6PSZ02&Nhlip~s+ zCpD3V|J08-0mFw-tI?sNbwfx3G7U0E@qY~&U$}0`&$2N7z(|d45eFr~ABqO{>@NjZ z^Y+5l6fB=`w|ytC7Ew6<5-4&=sMBN&6>fj+cY1uC1TJJ0VqJa7Ua#i9g#ppY*Zp*M z$EL``+?K929h2;CDFg|m+;f+e%#SpciJ8+jAmNM9b=%kJ+Z zH8HR94g8hKf)=6H+#9bJpQ7Aa`V{di(E-l6RA2WHld}L3{7JZ)IkfIOgb(Fe64P(q z^Wi4pg^+fI(@@syMJS^9Im|N5kZygKPP~Q%{Q6vYS;-De?4qe?XpRf#$}}1kMT`71Git$kcV<}<~F&!aO@Zq6MMhLiYby= zKW$DySLGVoaeN>D|OCR52w72{yR(R!6#YPge-+LPjYShOd4(dI)`LL`Y~Q3~Xv#x@IfQ)18f zSp@C~%R77dJB7+@B$SC=XvHaPzapHeh>8PT-t13y4`gQLG9sI5IRGrRe_+o#~Cl*o`5*L6J-c^ zyh2+b_AA}CG94%$e*~LEJgo+Euukxf1a%-%zdspn92G@I#Ruyh6FNDU7Zuzs{19u@ z$J>$#$VWmK%%PH3%w-wNRNuCA|2FJA6X#tft@07opx5ty3FX-NyI(_POXnWtqLGK@{EKF8mRz@d-HH@cb{bZ@ z_u$U{-48gFnFkUSYi2{vCtC*gD{qnTg5aUzJ_Hz17SXf^)(5!`NHYtVI=y&++sRrC{#}(|YrCk}gST)kW(*(vW|l$d zRSY3f^`da%kDydH+mZy=}qDj zp|cfeErAV|WK4m{K-FJvFJCLgM}NI1HXb3{;@J7jSQBV<7ko*}}Y+_k4+5; zgtS^VDZov-kTQQ*P;K#TlTdc*rYO>+khVGyZ$eoUF+2)Qq5YfYz#wqc#JS2r8F-2T z+CuaL+cy`=;b|rYRE;63WS3{PJid{+>*=Bz;uT?x{#S0ak*sazb<*>Q=wuZatvI0u zakticV|9Y^@?!OZ@}g*sQPF$7#BT!=#T_8-QxJ*GoX=2iurWr>rbhXE!aEZ+l2Il_&aEE zcWywfX7r08Q_-t`Q-A5~-Z2a~0vNMLbNDnVM9*J6B0i>p3P<3AZ}89$&qe|d99;D8 z!QBF55I%j8fLsJm1@Qqxu{5R2{0A=j^v72X;dA7oJO@-{$S z(%88P^Mo?@0vmwsz7?65hI8>N;9r5wj#H2Ui&_!}Pe>@dNbxi469pr~8lj-h&&z*ML5hOgQ zFafn<*3$^ohr%n(OW+B3pgl0kd6R$9bSRZV5G=h1^CdD7$q;ChTJRl87z>6V@ipjD z%r4>b2F_qMgpP*LpO0yDf}kLUpupvjC?HM(=u;~aS+#y@)T~5R0L)?Y=Of>8&7ZOF zbyZ{jL;wzukLJ(%#&;Zp`4js>ZGPDM^05c<)*6FwhAF>HsR`6XgjTSB#vbT=LF}KH z*w{a@7|I=HPXsCL{KNno1;c*(|UoIwqqz)p5dglgGgcTOwYYv34W2O}1ZfO}Yop-100FRVrF_ z&AUD>FdX0m{}zN?^-D;DZwxj2H}HbGPemTq&>&53Gc+O6K;O`ebTum&GpPYJpBXg+ z3k2^k`KG~XNLVi`pIIz1WwWXRszwBS4r1&Z0y#fV+n?W8&c>M8i80d++pq!}x1zI? zSxKP}830n>5=zTjeTy@aKjuxe?tQ-1OE7L78Jh>O9EioLI$#Kn=KC8a8gw%(L4T@2D_ zN#-C^J0SQ_f~H?dDU`|X+X>2oszbI`2r8K~*d~*&Z&+%)2rknQJ=}_z{FHJO#7>x0 z8YXYyoR+)gijbc)YRQgiomm(_MSZra>yzXw!&N;Jy6$`(B87kia(DJia3HLd?US0HaN0 z%p~5i98%yDn_HcLv*DC+2sqL5fpSbG7ahPgxvjfVC~0qTGwxDIz&Pq1m-@cAZ=<_f zkWug3e+@05K@qob4$9J9Ll*Tjr=!J@^QGc$opFw0A zW2dFiU>u4w6XYeBIyZam>;<{tNX)K7D|C$zYJRo6!~Mm4SzKo#J@a)xd#5PLdL<0I z(<4#C3lKo9O$uoE;gS;u?(-PrCz{n0<{^VLvu_PJk`N1Yg{!jJ6h0^gFa@5q4QBKgPI}A zobTG1PL6Eb)r};ALEluh70jJwTHO^LUc$=V)s01ixliPi=<7Sr)Uu^ zO3ma-T6$()%I!it@~~uy{_uXWh*c;`482}eqEJWBdDXFwtv{{6Iu=XZStrG<+a~S) z)|5qU5v6$VGmDv?B5yz+U+`BC?JXi|izmr=QCozA8LT}xN>&oWEr1aaHF+V_+*b49 z1OHj#*H$38>(%=K8omSkxvggZ)jwsO5B`n#G?Z%F^6cIs-xoEL)!fuiN4y0cM0Z+H zEz{x%a2#QMBr3P0zFd?IcUggKIA1>E=(Btmy3RJs=+@B>QK#yt9|ks5RsGH4avJF< zwk=Mnc4=p^wu{U9#4Zpx+WDk3176KBoL(-P<3)nAwIHrDkavLuE+=$sdwDiESoL4aXlXtb@851E16YfOkPDPtxW8+hBLs`uuU1rjJmqg zs9Y4~1M|MmX2lE73Om{ngSkh>G>+-|GA!Z>E?ZEM2<~^XkBt(U%KxHj=1$!?*3^9Y zxaRE)1?$bPj=NkrzZ&kcD8gN2bJjgY*csS%uF@TriR~7?WzzDo02o1=U{jL83m_Xk z&V_TwSa3E%60C~Bxmw2yED1bThK5jhvUTc3D(JwZcQZe>i~LJG+PtZ3RvD0aI{PVJ z8ir@8LjbV|F~vOk;qiy!g8f6`X8zLUqo#oR103=T;RAO1-Z%yfuCc}ogo%Pa6EMum zb>ceC#KQF&k(qJLTs-nXuuqiK!)D+B=MC6(cH0ksWqrfU+mqh5}Y27wy)yRrP?GaSm`^*vwIvdhn&CM(18{p!G zM9TZ^@E2_I-hmD8`)4|!mS|cohR?LgtC$k6-ijt)66DCeNGSeOkBhYA)&6{ot=~?~ z29br4NkuQb&bXu{nf43XwBYHx(`;lov{ZvVSmbPT#)MmAngm_Vt}-j zgQ11V1%luNztoJ|0rj|?&CrPdg@8t9M|{jFyQBcgjO+V2V?4v$Yq%89W44?}46lH%VNPxkYN$O|iCFRLiUIBHy1Iw<*B*RGz=Cj;?_U~UFaTQk_79dC+jv@o z>Au{eIXNWFw_;&^x%N4QA_aEjS~7STiIs3F4h@UDGJ*VF@y5sijU7yCP9j|#rPg-C z!jSAMFlhqiTQEH;lCRz+RmhMz(}yr8)9QwLoLrs_9gQ2=4zup^3s{j%%jxu`QI4HE zw-tcgQItaC1x){$C%2?QzTihjPi9hn8}bc+MyrnPz< z&LjYmgQY4(<1|s1rtk4_%h43AKf3Mq>i`7*KfJfT|GKJy3#bbU-DrI?N)CNPub#2LFO_p#cFfprs5WVi9dnxKn|yYkhXe1^C*B#kS)B zMUQS9#_Mxo<D2+ z3koG=yLW(aA;hJZ>jk#VP?tXJ&(OF~AR%jvK;0500wtE&$RNu9{W82Kl6Hk_(XQp+FOALS_)Jlj|PdgT!P0mt0UzsxK27gXseB z)t1M{ZjjcNYQ_Z`!WDY_|B$NyFcKpOF3XZg1d*XLbx*#Xh5*t_7O*O9lx9ft_v5+L ze9$Nb(_C{t5{bAlX_*U}0JE3OGk1)VU74+S}X1t&}1{seX6N6kFVUT01*v<`cHEs8C zH43-;zM~7ckEvc*L7wXO+JgpGf%?7nV2Hq2Dr7FcV?od&V7P0aeP0)^g3r5vRmr3f zb;?+B+0C@hQu48Z*MLvK_(UqGu@ymGM<2%%tez-WK6p>=x>z=Bher}V-56u6*`!SI zL%soy13NK^;5dZV#qVoWK}7NZ*Lly=e1>+hQ1kE^t}E%V5l+ZejAR0#@HDhO! zPYz|*R0t;-)GSF@n#i`Po|y?Z*cqv|iSlePL?^Tax73W;`f`C{<$nh*KE`J)WuNhE zU@;j(8Lzy6J&}=6OgAOY#l z;+PY2&1=C+EEoh^ZJdtH>}4nz$QXt*$JJO`xdJ^axzp158;gicU>@pp>TKwa3 z*O}6f#9iRJRXnITcAgk7Y_sAx{ zqAysKRG%$?TZv;{66n>=irD-ld~F5?0--5<>~__t7B!Al$6oP0uG$b;Epu$wj^9RG z`{efXs$9ESwd{bX<}N>An+vOBo5^#JiET#fI|X-T6rhcPVQz;AoHIlTU!?U_Kv2P# ze*7utO4@1Wj_+*V-OIB<$xflhFylLj6?=EDN@9Z54q8ol@LMmy(YOSq%(z$){q+Kx zcgrDTiAES{S>?nvIEN{$f3;%omCMbS1sIS7aD%TxkJzG_$tNNf5<(Zf*av>XI6OBS z8AZQ`paWVvkOFa7!_FZzOOLnR2@^jE`v^0rkz)nP7=?*J>l2yGu(9|16r&F`I&|wo zR$OjM?D4`j{7pS8r~BsNbT(m|gYTI;VmE~lUkE=HkPF^O^n>+c(|Xxx$gBVQW2F&) zhg1_F^SV1U7toG`osvHL+Y}p6HG8aJD3;T5$fCPXsqz-oE|!IvqQx+{8X)ix*)7S% zHqJ8!Fx@%qF!{RIY|xRs*ry-sU<)S6*>dhG>9A-9K!Yi;{dnQjm|1|<-@Z;4caf`)tr#iSrU zI2)#)5Nnh58j_PZHr%NHOisRBQUIw$_JD0a44UEy!FQki-Jy^W1%f6GMI+H|Avvls z6K5JwMorrcLf#2qJ45;;vvZ+-D@mAseaUJ(lxF=RZegb;I9TXMHPMSgAC2Eo4s0{v zN&<~45`7md!r9aEnI~uhsCpz^+M9A3fl^KAqQOUyKs`>;>20hbW)VHdjVchUV}-Z? z(4{~?X|7H{$y`}MKv^m(5-RCo>y+qNOV5}-O|x9szgrSdELs{-@Ap2ll=g3YxgQqq z9$LZqE#SXFEvNXL598D!TUTD~hXI5P+i-P|m1LYsemPVaNj1^3gl1~Jb0Uk89nk$HRBqoiB3``=0})GZ@EU}2}=5!4LD!~B=Z({ z&2V0~)xfSui>5v?)=awzYC%%pBr!OcL*YzVlnVNy$n83^7=fbZ!|e8<^zeWx0U?FN zw=qgR?t`;l@!uk>>8M0+%gjyG{V4Jvs3F#bQ`J?G@xrJ@Aq}Y7NMg|BhrIO7$*pE4 z0d|Zm0N~bv(~dIh&g{^9lxa5!x};oa|CuVICb31|8gm^be1w2KKQRGEitJzv{)Xl^ z7ExV2_PX>Bm**!v+Oj;ie4qD{(;uO5@w&9Uflr%S-U#+F`R%ijlx?n-oB!*>9kv;` zB&5cIZ%!AOTl!^HVI^FM9+UVXQ_UXt-5jZuOR-FksIAiG@*3YZChHD<~{i7|O{`l>xg_ss4^>Bv&%4T(4I+ZU4M zYM*-zKSa?f7@l14R2amI-F+<+GL1|sf{~$0(7~no1viH})Csg%2o{dLKuofnG8z}6 ztDKd~v^d<=f7t48)n}QpU`8DkPIAg97Ey40c!WHMfRwgWM@p~#&GC@ZXzdvxSYnt1HHGP|2bQ>WQXGPe zv&BQ7I3vjYC38qh5d4O+0yALnH4s9h*^iRICHi?LAx+xT$?duM!V!|ABV z02V(O?-ut$cUG+zY9LKy(y08p?1zD3w;z9j-b#oS7RVZ={Yb(uG{#vRg|;Ag*4~5~ z0|YsliAXs^$m*kUn&ZvE{k`f-QU(w;euL*YMVyOO?rVRu+w3YQ6bval1`EL~hM2$u zpG6M+ACfzCEx>I1fw-zORFlI97`0}? zh5`Q`4PCQ*z_KP>F#jrDLbW`-L$))#Ge;*0;ykqAV=BIzNCJ5h{-C7dh?ATwL5x^- zmt!ombkc8*LBp|lE-KK<0M@p=l%9>tyRc^22i80?=&yRUUrw3X$$TH?GK#S}Kv9^# zRnG*im1p@DH9a2r#a{)B4GfZ}N#Mq)G%8q5h)M;IE6^z}5E20V$OX*dUkhI@4``K% z@`+oq8v0^#G+7-R{Z>NIB1}s45x@peTZLxkV$W)=$pRej;bWRh{&?( z(nL}#rh|^~HIrtvfZKG#lo>v-qsO9bzV6Dq%!lGWLcRIoY-|k|wtI-~PR7TeP=!z) z?CDGEuqP=XAiJapOv1^#nwS;ZrCiS-v?E6^09n2t(y%0~z z)D074&sA+r{Nw9OB%%X82u5^}{KLp^LL^kpry<^ka|o#*CqtQCgmhT<84RFU5xx&2 zny5JjRp(1xb;B(Cdn8_FX}BJY`j+~reHz@QRk;=N?$^VfMzzuD}*;CN&BdE>xAg3<2M zhGSy4{@0=3_4BHL5!yKaSTK7_Ct`{!Y?#?`0v5dDt|kc2Bt$qy+ta@Zt%q-LvF3Ll z2`ZmY*^+P!ohC}M(y|CZeuLLS%L)ZnB0WuBih|NcQgV6bohp}SrtHwleiatx$l-0( zvBR4_e?06kn$S;xkdXUmV?u~DxJfQ-8D^PRh&l()eHh_;AjnFMXzP|@7L>#^2*>u) z0)gZlL6Qm!Tv-|^a@D>AXK!K@7ow?3Tm8$4!t;z5nTI(k^D_^nXjWrbY5)tKUWLGb*b|WuX|$=wa#N7USx$z zh<74gqTowsYpD|k7pEhFb*B6BY(93$7r8~4JihVYqOkjuj~(tu%Hst5iP|jU8MBAH z*sd!w!xAUNQ-*ty+V2~7LKZS&3&@nYg?@ejC1eRZeiK_XCOy2bWdjjoOIHRSTf`3k zv>!i-H9*3ap~dslz#n2(5X8vm>)w4W_sqE2e|`!wFN8D5cM`r=zzWNP_wIlr!U^63 zOewgR%<<97#9=Um3CuGyGB$62?W5;fJx=1d)TTu1h6$3Al17qoAzm5B)eSju9 z=L+J7;BEr}g*8_*l`nJ2%4LS*A85P_b_J}e7VUmeY2ohg$1>nJH()4#)j)UOudsag z=W15(zK`L?xp+rKsAe+f^$JUOejWc{RV-XA_@H`>)O+f0EE!Uh8_es5<-!?2Yl;mQ z(f;X(KB>qrX?K`DB*|(*;)P~eDoFc>m^!%|T7+4<+Gg3q^6A<-__dTnAW1_&rcH5x ziEa7YmeBpSY{95uro43CZ>{ABRw|mhZDuyeKCH@Y++)TE0vzh9sA*W!I zOzuTwUC5L`t4e%e2+s7T78{k~4+`Vh=u0oP(0(%Zn5FZJD{{@jxWoe|Ce#tO%HvG& zs&YVv{~YsFsOgF3EmEnh#*9p^XW)y2tK~<;47~N{sD};9dRPRMXm7{3 zu3tm!8+b<-CMGVpx}RhQnNuz`wZLkvlG!Sx`@zh4&2q8g11jRh4NZmH{pY8crYXh> z#@cg~xiC>La+FT)MJ$(CU*+9E1TP^10Va}oKYcI)SA>)smy?#Pw*&}S384xDqGTj} zO&q!e(Hw5MYvPb%nSc(Yh56Ke;o7*{s}p&0A3YwCr!5kv05B7mL+)N$`nYr?8e27-)dlh`$ShhDE=q zyYV9R)WYYg!SB5c9nvGze8|%4u98uK#E6_iSPBE+`3}OUDD6J-RzaE^o$C@;R7OzL zbj!#BJZs7|r*m*~irly>nZ^#-jjHO#(r7Ghugs?rj`lZ6&Ba=K}+Zm>=eBLOpT zMZ_=|7NEz0m%A|Zamfdvf728&Z<=X8mD;Wf9Ju-9!mIiq_GkA{HDiGFK_%gVze`DR z%Xet|{#-|v*#tI{YEUp5X;=?@oQPud680*EzK2Ahj3hL2IJ9gBE_EZVYPd%`mg0OU z2>WeRO*I-eHZpZ+wo7STy=!aWB!!aunFR{u@TY=+PLf0D#xodO{1$LiBE%H&(YwLk z2aL(wW>K&M95m>m?u^Eo;N<~yw;+{suLcIvNG_2AREbk@BM65d^DbzZBwwM~#}^TU zxOhWajQfs@B4kP8ZBRVcplggyL_O9Xmf$)vJxpx;K|vq6ZyeGFXSm_gFG9uTGMT-iNWK3bRBD zV>e*Dik)8iW1hFhNCR6#0poR-{x~|nOK82==RZ~+H?Gd6NJ4_4FUaJDA&OBS_U^*& zK(8A7gf_F3`{t5-SvI`QvdHqWFh@&V2w{nC#67d{3>Bi5F-Iso+l?q5Z`87Nb=&g_ zg}PQeu;>?|P}hoIh_tX;!aL%b{jq=kxwWH&p->3<8eu4^KlcuFji?my8vQWm-+Xhl zq!8`GnUpa*Tm3s)THdPHP&Gy_=k^^_mWB?J$ z5$FxQud3^2ch5aN^b0XCT zrLd~aTw>p@VhRf}6dWE#a!R!`*tbWYL5`&(1s;f&8WJp5bK3SaM55g!RzeJr4b21a zLveVv49!)o1^>!0e3YdQ;@!{^jW`rFo*)u(2-U+dQi27SsSPA_LNEYGQ>t_Jqq(QV z$#BL}U%Gc;;QU>PF0u(E)1lR)VbVdo?UL#^>OK7tj!IivOS2euI?R27ZiX_#{lzj`k zPz#5u*a#8pVYS2;J-I$$tvuC28R(R;#q7cY|k^jC^5)9~zZt+=Fq+eBRx=__Vc zDG(qR8QCnCVRL=yAy}yOeEh9}!h|5#g?(vjX{Tt}&iT z8o^`rYCp-xzVneRBK~lFVOT~vah!>?z2O6@F{aRho&ai_A_fvY?stFeBFSyQZigUO z&$=ER-G{mhyU_=?u!AmBF-|B1f+|f0ZrBS+Mn3k$=k0!Sw*HYVLPlwQ!D*0nU|>KD z9t|rAsT_gsdFXksw6@%CbRxnP%f(r!0k*0E&paGWuE#%O~dAU7E z<%K8;HFvf9OLt#iWi+i4oNpJ(Q?u9m(Aa9L8wlkBEtP5H(hN6ZCHCeWjv zF|J@8{0;!IdzZsDzvBV}UZ$q0HD7tL@6Mn_(8*n(QEw=nOJqNP` zd}vIT9s&>si9m*n=^f*iv}Bs%oLwf;sp5SsDGZvW9RoqISjtOSV4PtaEXs#MEU{Iq zxu?E(&+xzi6D=m+pV??&2t*!=@5ap7uZe5bHiAt_NK~d~Flb0{4IVO%_}sH`xEMe^4OgG9FM+O9{a3>a)a_M?~drqP5_$P*G`y4zNH zv48!Cp?E(Kne>Z2$cYOaXD}|N@kC}2c2p2Dazyb9z?O^dAMIc$2k0 zTWKYC-PC$j>oV~9`tRRcIzPuh^7y3Kmu5LU#(N=&Q>RiKqK#&LVK^nWaFCag+-@Q* z!lRXs2jS`*JwP}t&uCv(IYbq8Fxc(d@rl6&6kv}Tz7!?xJD3Pctlt_kxcw& zObH@~fHr}BZjW$F5sqZP6ke&qx)N{~b=37I2@x1d#id!HWFxHmnL}aW;7DZAyO5lM z&Ue5NwAfNRnLLA{bGg-6DbcocG1>AJXOspPFWo_YO!sgvs-Y{ol?D?#GmMKs zeS_|yK@@R|3Iv<9<~BrDj;S;c%!m>Tgppw-VS3i2D`*N+*iBLlsU?T}UJx3*D+&|@ zgygt;M=CgjaRkKK@^-tA8hk$%ed@|$+TgJLUsf$-*8fVUbyku1k2&8D8jQPFUAYo ziNf6}Z`zU8A8x`a78`%Kaj!S2<-mboPyYM+TRy)0{>A&e8Pje;#V3ER(YN-_kK2l( zW{Uxl#gR$aiAXmst{txg1)yz^DO)(k-hjKT$g=5V=0f@z zCq68LF9AlDL6C$Va!#s)1y)#RVI`on;FO^uq}iz4k`PoO8IT4Z25&)Gsfr;FhChSL z8zJA#}p*dA|`fsI8oHnIGkp?kQ0G$jk=h{0$MgxhHZniA+YT&BRWW z*?{au%vB*NU-#M1iM-Q0yffhwZ=IF4GPsj`p+I?Z_i#2%Ym6ciEFMt&m_i2jj9g?Y z;6gW$m+CJC`_^?}eSOF_)%?@61cq=ah9vB-drv8JSW*Op0k`k_GU~hIEQeTj02>$> zVUD4ddr@Pg5AxP`UWwBhiu0H50%`+-B_qTY^yGbCcGXcLpi`p+OA7c(zV6xYQ+i`< zu!k>L<<&j=l^}W-$m>=C#J!TBigW>~ROH-1613dL4UTLasth+RC@+Cj;*7vqV`{7= zAA9&lzmg#@t7wRj1tGssi-MlQx`$ALU%vz!%t;n9QG+%I$TJELk}uJLaUj0+0Mr9l ziu=JRgFs%)XbXe(0Weac8lgQsjImqtO>`plCko1p2BxR8|Q1eBD|$VUVT0&0Nd(u~Ft&Ox;o;V5W-Y*G8;YGYy|*-i_N!APmCwzl%}XA?>G z0RYt=YoDeGB4VM#>0%L}%ILC3t7l^g8XDruT+>%>^}0(|;keds@oJym ziZfXKy4T@JVf~gl3v%3%=B(oT9o&glqIb5#4VxX2o&d83X%>j@iT7&7l*m5OWt*Fn zEe4y(4D|w|dVqTisEKn&7*}?*Fl=?KYEPGRT!`gkAh;)MQ~zlWq%Q#;k`ovJHxMEv zhYq>5_9M$Vm4S9{2JOXU-9B3I0)i_GN*E-iCXWg`teXn5Tv|As8CsZ3gJs!+Db7JN zK$h(nlV85}oA0s95UoxOL5{abS|;*dD%t?cU^>qKXBXCG4JRVO7vdtf8+;|m%NK@? z(`5In`*!1C;}E(lFBIcqkzVYSU&s;}&zT~k?7-w06{qdh{pvR7tcA=_zZW|@4QNIR z!-N1Jj||($m70<`NR|o+Zl+jGI@ET}i%A%Rii%?mt|s}GG#`TlVQClCppx*J0Ff~d z7{5wxRAI98t)2a$`}az_>2wdp6lM{cFsb$N6ua|sX}-$^5`VeifIZL84X6PG!-E)z z^#g;y^ztipaBa%q435JQ^oLmjH!Zo>tGREX)2O@dr?W%ChRes6SI5Wx;jVG>v855E zTi`;ZLgFvi9z;0^XK>0F!?g*>j=q_V+9}D56_$E&3I|_y14=A0xsXXB4w%L}4>A&P z$~Ysa4Sg48n-cJv!1Lo`y!Z<2Zv3oyalZ z`N)$=fzvFHG=zC#Muu}8MQ1Jv|Fa?Ujru%v2d$a@p8Hw}fVW)yvMlwl~Frh9{7 zz&Q2Mw(aRO?6{PICCLpQ7k%UttL`4Ku+W$CM8gNkfgyqQNdQamQgO9?mRT6z(;HXa z%O4Vk1nk>+eTzH@cCD$Z?h9I7i^i~I@EWziWFq6N4lR_87fcJcVq1J6_#`s15em6| zwZ&Mm!tY?`EW!wRv~t*aT7 zxyT19I*2A-<>;&10+k~C1qp^2_~i?e?lOvs5m^46ML4B;fZXn4#xe9pcR(xDAMBX+n0h7o1#F(d87)QlTo#TFMUwuo7oNLB$Uwp><@6#Bt9 z4$iUZ`y0Z*h7dV0ANR-sN?^PQN{oB303$e9IYx|szyKjIVmU&Ld%yr6xI)nLcvAR| zL59lX^=s@G6cHi5HcuwN28Kv8uG2Y)t)cQS#0_!i_(912G1_k{>@GY8(Iq^FQ|M1^ zYatpJ(Bl==(c^CpkDDGxD@6&#^mpW9Kp+WL*cAiZe8`mT$`0dmI(mv}p15m`lIUQ< zu$^N3Gr1NDoyG8Ue+uWy8H?1oXNigrl_yeSMT|O@dHhho043C|{W1vTz}*vzcU~+`4Tk=1`Cc_`c1K4;Ft);U+D7Mi~nYYO$Tmz?Psq;o>P0?d#csG!55 zWP@v)Ii9pF?;&MHI^wJ{4XT+L>41``onRiK zyUb(?IPn)+TDUV5$y0}P$oFp-AZ)5jE!!H#SjiM`LZBHQi?BZg6Ac*{q11JK7Fcd# zd+ewTL4jl~JRT0iUroUbHbPmPg*5)d%L!;gFO9uw2^Wl;!J?&jZXM(Pr+VB#B?T)L zjeOm!p1>&Lb(H&saw5DCBvHH&s2#SyZdnsooS_6ZqV-1jT&peEvjP@SamKQCYk(3j zEs_W%76S+YiQl%CPSc6;ikg~R{t`TMWp#Y>+x6q-o6-7H2=jzG8s8r~@F!QJJb=09 zjVXkKqnLiKrMa1%Os9P1haKn(fj6Z;uQW#~AhQWhY4%q@?{hsA{3qO-3elhyI_ipt z;MZ9wHWKX=F++BFOnX}!d*wYOedbZa&FEj)ZsfU)WD*iLxT=q(iucDxnr((I@2|viGAtyMg!4O>MfrAyV3}GW zKo-Vg72xm1w*qV_f9Ax!*puihm~!rb7ItW%tXGi64Kc(h#Rk^{ zE%?Y~LeUu*p@HNnpJ(Ef)uiuD={nqjC@B+mja3iC(R(}fT_!CcUko=^r$&(GozIfC zpqXVl38_JgAlrh+67Xrj$>e~Rg{?@NS%3tQDNB|rNkVv&NetC4Nv2$fe2IB^6#2TI zha~#WFzbblt#h5d5%s^awM!xC_7TYlQiJ0C-C#|a&z~S4Yr7%vvuCg-<3|hDKy1G3D`p4bXdw%K5y245 zhIzTh?eQeS%SD)Fyq4rdBO(RcP#~}SBt+a{v@q3-KyUKjf1`^Ch5wUfD@)@&kFDE> zha3|=b{6#)B??W7%*IgCL6dgyE27;Q#DUBUwq)l=*r*MG#@w2QpkgTjsMLe_z*a+S zC}A4>TCwRPvmD|?i!-DWdb)^|?VJgK`H#m)Nr4+q{5G$F{6w)2%jeG$1}BQG@-bHC zNhf-FMgQwhO&F3%X2Pl^LnL3fp~P9&Ar+m1k!AGJco|7y(J;FdQXMcIL;*37Cm}jn znN)->W^g&4M%)}+>d#$a=Eua)GypeVMom)TFkpqw{M}$pDyxDo`H%()O@IIpI+8(# zNqp{!D}&N12-%}Pd#}bD)nC>nKr?=P!zLNN`GrknfBezpn(ipi1(3{6^ok~naH6Gc}D`sE~Swa>iVz|ge(SS-uNb2GiAmD=l_K!kG5#Y z?HbAT;f03!C#jVvY&VqMM}ghOS7|;F-T~qPwHX-Z2Ukf>K4Zj71ARS+RQJ=YTs2jK zdsy=)$ihSibDN)Q`5(J(ln2)zIb_3e`lR@RBPVEbc5iM6(!OF-UL&1;yt*TY7$+)E zk;RBsPq`9+#U1Nr?P-h>9H!4F}FCOTfl# zW6K=+iay+&K~&ausTC-|3Ej9c(;iv;tOw^kY@cRP#P-(-u zsgL$1hx5mZ^@jQE=VF5f@)%RiTfsO7oCe{ zGC-85e>QG17$Y&!u5I4|w!z@9QKMAgbv?jrA-NeF+3{sJZsg2668-yYfBd6xEG+xm z4G$HJ01syF#*0EJw0(rQJf!{PF$@61AX*_Iz1cz{i{vx_q+qEq1LY+e#s@D>QIgDs zH{k}_BxtHxu&#%$xS}(#&~EaaCA|47a@W!{H_*Eiml_s`m9Pw5%l|ij<3F4CENyOY z?^)bDA2b+zLSGF1z!j~0`ANH>JLsS-ZHw9$FJ0Q){Fb-O&%K2|V=+Ft5uFmV%9>1n zIsWcLWe(5fth3B_=PZp3y6R#s{EK!!L3#G zL%+dU{`x@*cX$hg5x;_zNd^<}#vHr8DV98t$BpT19Bk_KXKWW_fbNa~8R*;%IlTR9 zQbX55yC2VtofmA%Sbqwbv4E~kLp!vvH*Nz1sJ&SGd4BdjF5BzRpiHH&I2rytW-P?H zy7|~ouH+Sic?OjcAW=>I^gnd@)JR7D$rMXYkV*hbCQ@!tCKEL?c(csufDJNR1a}nQ zn&|>T6hvyu|Gfy~=VNbwLKEV7=^>TbTZJ1BvY`Rq!p($?U}BM;ao;UPA=sHo;j&iE zf#D9f@+welGPl7nP{AZ{L>Kc9_?O&AxIZ}L&nyVR*j|uPE`YxeC0e;&*^l{XC1Jq( z(s)kGoQlJ)glcSOupD29$Yt#FvY7))x0OW-vcpIaMYg#ZG>UHXB4 zSiC68^`B{JWh#pEBBYNuK7B|$Cas$Gu$DcWG3o}W;eAk?2H-V0``oM%n`2vRz=6Aw zVfbgm0#A$+VsF9&NmY&$pg_?uPKy(|N&k`Mh!MeWYNB+g|Wzw)j z`tQBCcfLfbsf^b95aQM7UuLSk_+@d7{LPwZAo{RM;c#Jc`Nm^HvjSZJQuG_=8Y>IZ zF*TVsGYoZ+!bkuL(9Z9@S@^WXlew>(4x`3AxClYsf6X{|GF?`AE`lh zXKyl1qcF<3p^$-aNNx*OG|KQPQ?MP>8CL8x6qzmI|1F#FE8YMM?pH7FU1h z!V!ynIQ{QGEhr~e0SKyCgau3&ov2njEW;!fWE<7tqEF^11e}Y%V~UKJFX%2Yg9w-SY>S_j*c#r6s-}?P)eLC>uupG zo0`o0cGv#jqPV?TIUm>qLYkIT`N2lHPP18+5pW!c&%~+&ZEjU{6#c(i$3fBCqZA$K zYOQMVaKHojZ{WgBmLxDXjVcMCU9j((tmCy3GBh-jk4@d^yoO7m8RtAT5tOF3<8q)H z0UaxvU>Sn1uWjQ(5-4t5C=jFWouYyuE|iQ!T#;#1di&GmRtIQ>% zX`CCLcn*v9T@&91AqfAPlUuPj=d=tz^=&7W#MADuDjC5)RD3UE=g@V04!f9D8bFvC zuDymGJ2(e(ur**-U~Wj-`$8Se?OD|9)9^4#qUp@VEG1 zb*uYz)~xQfNsoNuJ;g-Xy1KmQyVujqLn22ag~r6c9sYu*@L|5WSSg62cS>7pN9tBc zCAjaIHWs)>2DMlBq0Ok3(bjsTW8F!s^HNZ78WuLScd%zqHqp|2xMRV-{FIwsDK9P9 zmz(%EfVE(scS`v6KEX`YrK<&Uw-(aHk91~ zG(FUFEmHNGcBFmt5GU79$N6MrJp zo}F1-L^>rWBDbRhLO*1x@-w-0`gIdWa^jC<>JL6#Z1<035iiMV8s2aq!Z~){dh&x4 z=WxQ$!4j=w{kJ#uUw%+rj2sNn1ly>sY#IWkLp7NF_5J-cRWtgDbwf>caQs)st4)9O z#iYb|Gv6@#@I_1Lt)zz0reY`(VR|Ky-9`k{XEg*};}hSR!0bO5%=Q{?nO0nCC{dfT zYwJp}mU+mtdXPCA%I8gb$!QaZ_<|jx*YNau=MaQLuh#qna)ZbPnsoYA6R>~5V1G2y z?=>8GN3o^Zzah%2gII8w`ZBk^_OB*Ro!1TAmUcTbu)0RI5IX%DOn15oS>aLo8fOdCU4I=zaXx4yCMMFdN) zp|v**3nMp#Vc|zv1kPnJE3MH6-n8smm`l(+G@6s~h(1}O$O^mKF>0f{OA~1&fLA5Uj6lub&BK0EU!&Aj6e{$kDd=hSt(VKSOpA=iH4Qvqti(msQ1E;;$J~VHA{mKbomIJe4LD~goyBHLq zK_ZMS1Lo+}+%aPUY-M1xxcK|}x7Uz9zu2$4N*cf!xl zoBFGNFSac4&tr+62PLO$#+&r7-4kbU!q4DD-$ifQXKpLDw)khflxHj<_eg%tpiPMB zGb&A$1EK2HnOzfyf6RyPO?~R7Vr!uIF10QKiH^s4K*tZV?gvtTlgtdpXf}&yMdk{5)H1wV^YM7A!@B zJ>0^JMs`Zom>zU8j{>abQFxaSKJtgDrP_`CuK(>d-1m5~Rebx1K_Vbkj2=cJ4H0gj z8=Wa`O|PE--7%A{=#hF2YxWddMQ<@67h$_IfnHK6Rsih32KCpx+E@R20_evLbZ^?T zO~uwgKwd^NQP!J7%HGiuVoat}zAyp$;|6^>-hcnU%uxv5FH;tNNqT@y@50=z_EnEh zoIuql0Gyse$OZ`v&sUeg@S9Wp1crw{^wVO(&0u)jL$f3QuHH1%qiY7Adj)tqZo<8#r5LLaYM=pqL(Yiq$Br{ta#TV+;Jci7(|FPuEYxrPC zu`O_kq1Xh@xD&R6^dLKBhQb&MCXXB$j$X~-2|aT3%jPwF?%TyS8!HYfFMM%RPycX+ zx!M{cV*1vQNx~@ljwSzt(I_h9{=WY9ruA(vwzZ?9sss|ZYuaPbkj<-o6~K&)zlpR* zO%k0s^}|SOT!PYhHm|W=^^p##wH9aX3~Nke^&T`gL7V0{Dxac7JX)4ZF6pEZbhG~- zO9ID>tKPJYZ!H33ng`OZT7mQ|i-;qap`XAX4OGSp#S{I$H+|kC#Wov|-L8tsCaGK$ zKBk%*UksrwCmNhD^!Q%G6?2P=nh`{K_@c$6(w$(6;DWc;PmpI3E2_#$$El3@o_F$% z*BriRQJWS4SVB0X(-})Eu+v$6KRcbF+=80>YL~A4V}!jo^XyLpM(qv@T%s&6XbMLT z7zC4Qcbr>W4or~us%>-C(hsj;^20?OhBDVBCXa^I`}`ntoCOTkgMP<86!{8l*0t|G zed1L7Q}L!JHx?Hy7Am`xw|~pX;2pO-#5_8B2J@f*eJF;f9ZfW&?hPM&F%toA=K3>m z*_S$(-MG-VXhTwO(g!D`w$b(4YOnF{>pgGU^^X*Byh=WnD)|7?(;Us{qa;L(mtH*8>-%L<54#@?4@uQV5GMkc1JaIe{>qDi zl6j}>I{)xR?Z~?FHFV=Ktk6tQP~1R3r4(<{B-A0D&_V?Uqti97;qiNl0J72zY3xv?j;1@XyNf^nVjzRq^_ZIO3-!Bq@{%PWx2`tW z(yZ#><=Y`eNZ$e$2Fn#M@Frb4kyCi$5Ic(K)&A{Go3*lt6I5D`(-W80hB&(NNq$%S z{k;fbi$M;Z~FXsJP8`bTcjNB)(p(z zG}E}%-X{GBC9S{>|44k8-pSuO7cANJQ3kOn+MJhEB)yZqNCYPQp9urb?~W;Z4VOPs z#Mu~T+hV<;(jtq;!nRnqHvh*2)i_~P<5>9zOzo$Kj!qc!DhaAX%`tXu_9k6*;l#=P z!JM2otu0erY*X$)1cg(tvHj$D-GXLv-lUVBpE$b{c6MIFzbq&&Mss#;0gqz&zo{zN zyte64KiK@CyVfDtJQ{5d-Y@0ao#r53-HizK{o`TzAZcT2``#%#UyrzfMUGJvEmb5y z*tWvzx2>?eNmKsc#637+_uy#U$7}fhZ;Lo7=_A9kmN+O;$b;gDv|6JZl_`$sccZ%X zii!G`;}_(-hUNys+X!T>8u%2VCHMBD50h8(t1T1P;&*l}yoPVw7&;bV-OjNv#3a(K z2KPex)p)hJxqk#lfUJihVHnwNg&O*J#{BYK}hE|()GmK{-&$uq_e+mpJuaoda1nYJe7AZmUmC??+?8@N`Idt7s(jT+cL%l^7JL^ z@3&*f)AP-<8ZrOY@QC)9>tA={_AqHE>TY5fx4gQqh$o%!TVHR#DC|BqKQBTJ4n nG{@gP + + + +CLN, a Class Library for Numbers + + +

CLN, a Class Library for Numbers

+
by Bruno Haible
+

+


+

Table of Contents

+ +


+ + +

1. Introduction

+ +

+CLN is a library for computations with all kinds of numbers. +It has a rich set of number classes: + + + +

    +
  • + +Integers (with unlimited precision), + +
  • + +Rational numbers, + +
  • + +Floating-point numbers: + + +
      +
    • + +Short float, +
    • + +Single float, +
    • + +Double float, +
    • + +Long float (with unlimited precision), +
    + +
  • + +Complex numbers, + +
  • + +Modular integers (integers modulo a fixed integer), + +
  • + +Univariate polynomials. +
+ +

+The subtypes of the complex numbers among these are exactly the +types of numbers known to the Common Lisp language. Therefore +CLN can be used for Common Lisp implementations, giving +`CLN' another meaning: it becomes an abbreviation of +"Common Lisp Numbers". + + +

+The CLN package implements + + + +

    +
  • + +Elementary functions (+, -, *, /, sqrt, +comparisons, ...), + +
  • + +Logical functions (logical and, or, not, ...), + +
  • + +Transcendental functions (exponential, logarithmic, trigonometric, hyperbolic +functions and their inverse functions). +
+ +

+CLN is a C++ library. Using C++ as an implementation language provides + + + +

    +
  • + +efficiency: it compiles to machine code, +
  • + +type safety: the C++ compiler knows about the number types and complains +if, for example, you try to assign a float to an integer variable. +
  • + +algebraic syntax: You can use the +, -, *, =, +==, ... operators as in C or C++. +
+ +

+CLN is memory efficient: + + + +

    +
  • + +Small integers and short floats are immediate, not heap allocated. +
  • + +Heap-allocated memory is reclaimed through an automatic, non-interruptive +garbage collection. +
+ +

+CLN is speed efficient: + + + +

    +
  • + +The kernel of CLN has been written in assembly language for some CPUs +(i386, m68k, sparc, mips, arm). +
  • + +On all CPUs, CLN uses the superefficient low-level routines from GNU +GMP version 2. +
  • + +It uses Karatsuba multiplication, which is significantly faster +for large numbers than the standard multiplication algorithm. +
  • + +For very large numbers (more than 12000 decimal digits), it uses +Schönhage-Strassen +multiplication, which is an asymptotically +optimal multiplication algorithm, for multiplication, division and +radix conversion. +
+ +

+CLN aims at being easily integrated into larger software packages: + + + +

    +
  • + +The garbage collection imposes no burden on the main application. +
  • + +The library provides hooks for memory allocation and exceptions. +
+ + + +

2. Installation

+ +

+This section describes how to install the CLN package on your system. + + + + +

2.1 Prerequisites

+ + + +

2.1.1 C++ compiler

+ +

+To build CLN, you need a C++ compiler. +Actually, you need GNU g++ 2.7.0 or newer. +On HPPA, you need GNU g++ 2.8.0 or newer. +I recommend GNU egcs 1.1 or newer. + + +

+The following C++ features are used: +classes, member functions, +overloading of functions and operators, +constructors and destructors, inline, const, +multiple inheritance, templates. + + +

+The following C++ features are not used: +new, delete, virtual inheritance, +exceptions. + + +

+CLN relies on semi-automatic ordering of initializations +of static and global variables, a feature which I could +implement for GNU g++ only. + + + + +

2.1.2 Make utility

+ +

+To build CLN, you also need to have GNU make installed. + + + + +

2.1.3 Sed utility

+ +

+To build CLN on HP-UX, you also need to have GNU sed installed. +This is because the libtool script, which creates the CLN library, relies +on sed, and the vendor's sed utility on these systems is too +limited. + + + + +

2.2 Building the library

+ +

+As with any autoconfiguring GNU software, installation is as easy as this: + + + +

+$ ./configure
+$ make
+$ make check
+
+ +

+If on your system, `make' is not GNU make, you have to use +`gmake' instead of `make' above. + + +

+The configure command checks out some features of your system and +C++ compiler and builds the Makefiles. The make command +builds the library. This step may take 4 hours on an average workstation. +The make check runs some test to check that no important subroutine +has been miscompiled. + + +

+The configure command accepts options. To get a summary of them, try + + + +

+$ ./configure --help
+
+ +

+Some of the options are explained in detail in the `INSTALL.generic' file. + + +

+You can specify the C compiler, the C++ compiler and their options through +the following environment variables when running configure: + + +

+ +
CC +
+Specifies the C compiler. + +
CFLAGS +
+Flags to be given to the C compiler when compiling programs (not when linking). + +
CXX +
+Specifies the C++ compiler. + +
CXXFLAGS +
+Flags to be given to the C++ compiler when compiling programs (not when linking). +
+ +

+Examples: + + + +

+$ CC="gcc" CFLAGS="-O" CXX="g++" CXXFLAGS="-O" ./configure
+$ CC="gcc -V 2.7.2" CFLAGS="-O -g" \
+  CXX="g++ -V 2.7.2" CXXFLAGS="-O -g" ./configure
+$ CC="gcc -V 2.8.1" CFLAGS="-O -fno-exceptions" \
+  CXX="g++ -V 2.8.1" CXXFLAGS="-O -fno-exceptions" ./configure
+$ CC="gcc -V egcs-2.91.60" CFLAGS="-O2 -fno-exceptions" \
+  CXX="g++ -V egcs-2.91.60" CFLAGS="-O2 -fno-exceptions" ./configure
+
+ +

+Note that for these environment variables to take effect, you have to set +them (assuming a Bourne-compatible shell) on the same line as the +configure command. If you made the settings in earlier shell +commands, you have to export the environment variables before +calling configure. In a csh shell, you have to use the +`setenv' command for setting each of the environment variables. + + +

+On Linux, g++ needs 15 MB to compile the tests. So you should better +have 17 MB swap space and 1 MB room in $TMPDIR. + + +

+If you use g++ version 2.7.x, don't add `-O2' to the CXXFLAGS, +because `g++ -O' generates better code for CLN than `g++ -O2'. + + +

+If you use g++ version 2.8.x or egcs-2.91.x (a.k.a. egcs-1.1) or +gcc-2.95.x, I recommend adding `-fno-exceptions' to the CXXFLAGS. +This will likely generate better code. + + +

+If you use g++ version egcs-2.91.x (egcs-1.1) or gcc-2.95.x on Sparc, +add either `-O' or `-O2 -fno-schedule-insns' to the CXXFLAGS. +With full `-O2', g++ miscompiles the division routines. Also, for +--enable-shared to work, you need egcs-1.1.2 or newer. + + +

+On MIPS (SGI Irix 6), pass option --without-gmp to configure. gmp does +not work when compiled in `n32' binary format on Irix. + + +

+By default, only a static library is built. You can build CLN as a shared +library too, by calling configure with the option `--enable-shared'. +To get it built as a shared library only, call configure with the options +`--enable-shared --disable-static'. + + +

+If you use g++ version egcs-2.91.x (egcs-1.1) on Sparc, you cannot +use `--enable-shared' because g++ would miscompile parts of the +library. + + + + +

2.3 Installing the library

+ +

+As with any autoconfiguring GNU software, installation is as easy as this: + + + +

+$ make install
+
+ +

+The `make install' command installs the library and the include files +into public places (`/usr/local/lib/' and `/usr/local/include/', +if you haven't specified a --prefix option to configure). +This step may require superuser privileges. + + +

+If you have already built the library and wish to install it, but didn't +specify --prefix=... at configure time, just re-run +configure, giving it the same options as the first time, plus +the --prefix=... option. + + + + +

2.4 Cleaning up

+ +

+You can remove system-dependent files generated by make through + + + +

+$ make clean
+
+ +

+You can remove all files generated by make, thus reverting to a +virgin distribution of CLN, through + + + +

+$ make distclean
+
+ + + +

3. Ordinary number types

+ +

+CLN implements the following class hierarchy: + + + +

+                        Number
+                       cl_number
+                     <cl_number.h>
+                          |
+                          |
+                 Real or complex number
+                        cl_N
+                     <cl_complex.h>
+                          |
+                          |
+                     Real number
+                        cl_R
+                      <cl_real.h>
+                          |
+      +-------------------+-------------------+
+      |                                       |
+Rational number                     Floating-point number
+    cl_RA                                   cl_F
+<cl_rational.h>                          <cl_float.h>
+      |                                       |
+      |                  +-------------+-------------+-------------+
+   Integer               |             |             |             |
+    cl_I            Short-Float   Single-Float  Double-Float   Long-Float
+ <cl_integer.h>        cl_SF         cl_FF         cl_DF         cl_LF
+                   <cl_sfloat.h> <cl_ffloat.h> <cl_dfloat.h> <cl_lfloat.h>
+
+ +

+The base class cl_number is an abstract base class. +It is not useful to declare a variable of this type except if you want +to completely disable compile-time type checking and use run-time type +checking instead. + + +

+The class cl_N comprises real and complex numbers. There is +no special class for complex numbers since complex numbers with imaginary +part 0 are automatically converted to real numbers. + + +

+The class cl_R comprises real numbers of different kinds. It is an +abstract class. + + +

+The class cl_RA comprises exact real numbers: rational numbers, including +integers. There is no special class for non-integral rational numbers +since rational numbers with denominator 1 are automatically converted +to integers. + + +

+The class cl_F implements floating-point approximations to real numbers. +It is an abstract class. + + + + +

3.1 Exact numbers

+ +

+Some numbers are represented as exact numbers: there is no loss of information +when such a number is converted from its mathematical value to its internal +representation. On exact numbers, the elementary operations (+, +-, *, /, comparisons, ...) compute the completely +correct result. + + +

+In CLN, the exact numbers are: + + + +

    +
  • + +rational numbers (including integers), +
  • + +complex numbers whose real and imaginary parts are both rational numbers. +
+ +

+Rational numbers are always normalized to the form +numerator/denominator where the numerator and denominator +are coprime integers and the denominator is positive. If the resulting +denominator is 1, the rational number is converted to an integer. + + +

+Small integers (typically in the range -2^30...2^30-1, +for 32-bit machines) are especially efficient, because they consume no heap +allocation. Otherwise the distinction between these immediate integers +(called "fixnums") and heap allocated integers (called "bignums") +is completely transparent. + + + + +

3.2 Floating-point numbers

+ +

+Not all real numbers can be represented exactly. (There is an easy mathematical +proof for this: Only a countable set of numbers can be stored exactly in +a computer, even if one assumes that it has unlimited storage. But there +are uncountably many real numbers.) So some approximation is needed. +CLN implements ordinary floating-point numbers, with mantissa and exponent. + + +

+The elementary operations (+, -, *, /, ...) +only return approximate results. For example, the value of the expression +(cl_F) 0.3 + (cl_F) 0.4 prints as `0.70000005', not as +`0.7'. Rounding errors like this one are inevitable when computing +with floating-point numbers. + + +

+Nevertheless, CLN rounds the floating-point results of the operations +, +-, *, /, sqrt according to the "round-to-even" +rule: It first computes the exact mathematical result and then returns the +floating-point number which is nearest to this. If two floating-point numbers +are equally distant from the ideal result, the one with a 0 in its least +significant mantissa bit is chosen. + + +

+Similarly, testing floating point numbers for equality `x == y' +is gambling with random errors. Better check for `abs(x - y) < epsilon' +for some well-chosen epsilon. + + +

+Floating point numbers come in four flavors: + + + +

    +
  • + +Short floats, type cl_SF. +They have 1 sign bit, 8 exponent bits (including the exponent's sign), +and 17 mantissa bits (including the "hidden" bit). +They don't consume heap allocation. + +
  • + +Single floats, type cl_FF. +They have 1 sign bit, 8 exponent bits (including the exponent's sign), +and 24 mantissa bits (including the "hidden" bit). +In CLN, they are represented as IEEE single-precision floating point numbers. +This corresponds closely to the C/C++ type `float'. + +
  • + +Double floats, type cl_DF. +They have 1 sign bit, 11 exponent bits (including the exponent's sign), +and 53 mantissa bits (including the "hidden" bit). +In CLN, they are represented as IEEE double-precision floating point numbers. +This corresponds closely to the C/C++ type `double'. + +
  • + +Long floats, type cl_LF. +They have 1 sign bit, 32 exponent bits (including the exponent's sign), +and n mantissa bits (including the "hidden" bit), where n >= 64. +The precision of a long float is unlimited, but once created, a long float +has a fixed precision. (No "lazy recomputation".) +
+ +

+Of course, computations with long floats are more expensive than those +with smaller floating-point formats. + + +

+CLN does not implement features like NaNs, denormalized numbers and +gradual underflow. If the exponent range of some floating-point type +is too limited for your application, choose another floating-point type +with larger exponent range. + + +

+As a user of CLN, you can forget about the differences between the +four floating-point types and just declare all your floating-point +variables as being of type cl_F. This has the advantage that +when you change the precision of some computation (say, from cl_DF +to cl_LF), you don't have to change the code, only the precision +of the initial values. Also, many transcendental functions have been +declared as returning a cl_F when the argument is a cl_F, +but such declarations are missing for the types cl_SF, cl_FF, +cl_DF, cl_LF. (Such declarations would be wrong if +the floating point contagion rule happened to change in the future.) + + + + +

3.3 Complex numbers

+ +

+Complex numbers, as implemented by the class cl_N, have a real +part and an imaginary part, both real numbers. A complex number whose +imaginary part is the exact number 0 is automatically converted +to a real number. + + +

+Complex numbers can arise from real numbers alone, for example +through application of sqrt or transcendental functions. + + + + +

3.4 Conversions

+ +

+Conversions from any class to any its superclasses ("base classes" in +C++ terminology) is done automatically. + + +

+Conversions from the C built-in types `long' and `unsigned long' +are provided for the classes cl_I, cl_RA, cl_R, +cl_N and cl_number. + + +

+Conversions from the C built-in types `int' and `unsigned int' +are provided for the classes cl_I, cl_RA, cl_R, +cl_N and cl_number. However, these conversions emphasize +efficiency. Their range is therefore limited: + + + +

    +
  • + +The conversion from `int' works only if the argument is < 2^29 and > -2^29. +
  • + +The conversion from `unsigned int' works only if the argument is < 2^29. +
+ +

+In a declaration like `cl_I x = 10;' the C++ compiler is able to +do the conversion of 10 from `int' to `cl_I' at compile time +already. On the other hand, code like `cl_I x = 1000000000;' is +in error. +So, if you want to be sure that an `int' whose magnitude is not guaranteed +to be < 2^29 is correctly converted to a `cl_I', first convert it to a +`long'. Similarly, if a large `unsigned int' is to be converted to a +`cl_I', first convert it to an `unsigned long'. + + +

+Conversions from the C built-in type `float' are provided for the classes +cl_FF, cl_F, cl_R, cl_N and cl_number. + + +

+Conversions from the C built-in type `double' are provided for the classes +cl_DF, cl_F, cl_R, cl_N and cl_number. + + +

+Conversions from `const char *' are provided for the classes +cl_I, cl_RA, +cl_SF, cl_FF, cl_DF, cl_LF, cl_F, +cl_R, cl_N. +The easiest way to specify a value which is outside of the range of the +C++ built-in types is therefore to specify it as a string, like this: + +

+   cl_I order_of_rubiks_cube_group = "43252003274489856000";
+
+ +

+Note that this conversion is done at runtime, not at compile-time. + + +

+Conversions from cl_I to the C built-in types `int', +`unsigned int', `long', `unsigned long' are provided through +the functions + + +

+ +
int cl_I_to_int (const cl_I& x) +
+
unsigned int cl_I_to_uint (const cl_I& x) +
+
long cl_I_to_long (const cl_I& x) +
+
unsigned long cl_I_to_ulong (const cl_I& x) +
+Returns x as element of the C type ctype. If x is not +representable in the range of ctype, a runtime error occurs. +
+ +

+Conversions from the classes cl_I, cl_RA, +cl_SF, cl_FF, cl_DF, cl_LF, cl_F and +cl_R +to the C built-in types `float' and `double' are provided through +the functions + + +

+ +
float cl_float_approx (const type& x) +
+
double cl_double_approx (const type& x) +
+Returns an approximation of x of C type ctype. +If abs(x) is too close to 0 (underflow), 0 is returned. +If abs(x) is too large (overflow), an IEEE infinity is returned. +
+ +

+Conversions from any class to any of its subclasses ("derived classes" in +C++ terminology) are not provided. Instead, you can assert and check +that a value belongs to a certain subclass, and return it as element of that +class, using the `As' and `The' macros. +As(type)(value) checks that value belongs to +type and returns it as such. +The(type)(value) assumes that value belongs to +type and returns it as such. It is your responsibility to ensure +that this assumption is valid. +Example: + + + +

+   cl_I x = ...;
+   if (!(x >= 0)) abort();
+   cl_I ten_x = The(cl_I)(expt(10,x)); // If x >= 0, 10^x is an integer.
+                // In general, it would be a rational number.
+
+ + + +

4. Functions on numbers

+ +

+Each of the number classes declares its mathematical operations in the +corresponding include file. For example, if your code operates with +objects of type cl_I, it should #include <cl_integer.h>. + + + + +

4.1 Constructing numbers

+ +

+Here is how to create number objects "from nothing". + + + + +

4.1.1 Constructing integers

+ +

+cl_I objects are most easily constructed from C integers and from +strings. See section 3.4 Conversions. + + + + +

4.1.2 Constructing rational numbers

+ +

+cl_RA objects can be constructed from strings. The syntax +for rational numbers is described in section 5.1 Internal and printed representation. +Another standard way to produce a rational number is through application +of `operator /' or `recip' on integers. + + + + +

4.1.3 Constructing floating-point numbers

+ +

+cl_F objects with low precision are most easily constructed from +C `float' and `double'. See section 3.4 Conversions. + + +

+To construct a cl_F with high precision, you can use the conversion +from `const char *', but you have to specify the desired precision +within the string. (See section 5.1 Internal and printed representation.) +Example: + +

+   cl_F e = "0.271828182845904523536028747135266249775724709369996e+1_40";
+
+ +

+will set `e' to the given value, with a precision of 40 decimal digits. + + +

+The programmatic way to construct a cl_F with high precision is +through the cl_float conversion function, see +section 4.11.1 Conversion to floating-point numbers. For example, to compute +e to 40 decimal places, first construct 1.0 to 40 decimal places +and then apply the exponential function: + +

+   cl_float_format_t precision = cl_float_format(40);
+   cl_F e = exp(cl_float(1,precision));
+
+ + + +

4.1.4 Constructing complex numbers

+ +

+Non-real cl_N objects are normally constructed through the function + +

+   cl_N complex (const cl_R& realpart, const cl_R& imagpart)
+
+ +

+See section 4.4 Elementary complex functions. + + + + +

4.2 Elementary functions

+ +

+Each of the classes cl_N, cl_R, cl_RA, cl_I, +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines the following operations: + + +

+ +
type operator + (const type&, const type&) +
+Addition. + +
type operator - (const type&, const type&) +
+Subtraction. + +
type operator - (const type&) +
+Returns the negative of the argument. + +
type plus1 (const type& x) +
+Returns x + 1. + +
type minus1 (const type& x) +
+Returns x - 1. + +
type operator * (const type&, const type&) +
+Multiplication. + +
type square (const type& x) +
+Returns x * x. +
+ +

+Each of the classes cl_N, cl_R, cl_RA, +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines the following operations: + + +

+ +
type operator / (const type&, const type&) +
+Division. + +
type recip (const type&) +
+Returns the reciprocal of the argument. +
+ +

+The class cl_I doesn't define a `/' operation because +in the C/C++ language this operator, applied to integral types, +denotes the `floor' or `truncate' operation (which one of these, +is implementation dependent). (See section 4.6 Rounding functions) +Instead, cl_I defines an "exact quotient" function: + + +

+ +
cl_I exquo (const cl_I& x, const cl_I& y) +
+Checks that y divides x, and returns the quotient x/y. +
+ +

+The following exponentiation functions are defined: + + +

+ +
cl_I expt_pos (const cl_I& x, const cl_I& y) +
+
cl_RA expt_pos (const cl_RA& x, const cl_I& y) +
+y must be > 0. Returns x^y. + +
cl_RA expt (const cl_RA& x, const cl_I& y) +
+
cl_R expt (const cl_R& x, const cl_I& y) +
+
cl_N expt (const cl_N& x, const cl_I& y) +
+Returns x^y. +
+ +

+Each of the classes cl_R, cl_RA, cl_I, +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines the following operation: + + +

+ +
type abs (const type& x) +
+Returns the absolute value of x. +This is x if x >= 0, and -x if x <= 0. +
+ +

+The class cl_N implements this as follows: + + +

+ +
cl_R abs (const cl_N x) +
+Returns the absolute value of x. +
+ +

+Each of the classes cl_N, cl_R, cl_RA, cl_I, +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines the following operation: + + +

+ +
type signum (const type& x) +
+Returns the sign of x, in the same number format as x. +This is defined as x / abs(x) if x is non-zero, and +x if x is zero. If x is real, the value is either +0 or 1 or -1. +
+ + + +

4.3 Elementary rational functions

+ +

+Each of the classes cl_RA, cl_I defines the following operations: + + +

+ +
cl_I numerator (const type& x) +
+Returns the numerator of x. + +
cl_I denominator (const type& x) +
+Returns the denominator of x. +
+ +

+The numerator and denominator of a rational number are normalized in such +a way that they have no factor in common and the denominator is positive. + + + + +

4.4 Elementary complex functions

+ +

+The class cl_N defines the following operation: + + +

+ +
cl_N complex (const cl_R& a, const cl_R& b) +
+Returns the complex number a+bi, that is, the complex number with +real part a and imaginary part b. +
+ +

+Each of the classes cl_N, cl_R defines the following operations: + + +

+ +
cl_R realpart (const type& x) +
+Returns the real part of x. + +
cl_R imagpart (const type& x) +
+Returns the imaginary part of x. + +
type conjugate (const type& x) +
+Returns the complex conjugate of x. +
+ +

+We have the relations + + + +

    +
  • + +x = complex(realpart(x), imagpart(x)) +
  • + +conjugate(x) = complex(realpart(x), -imagpart(x)) +
+ + + +

4.5 Comparisons

+ +

+Each of the classes cl_N, cl_R, cl_RA, cl_I, +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines the following operations: + + +

+ +
bool operator == (const type&, const type&) +
+
bool operator != (const type&, const type&) +
+Comparison, as in C and C++. + +
uint32 cl_equal_hashcode (const type&) +
+Returns a 32-bit hash code that is the same for any two numbers which are +the same according to ==. This hash code depends on the number's value, +not its type or precision. + +
cl_boolean zerop (const type& x) +
+Compare against zero: x == 0 +
+ +

+Each of the classes cl_R, cl_RA, cl_I, +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines the following operations: + + +

+ +
cl_signean cl_compare (const type& x, const type& y) +
+Compares x and y. Returns +1 if x>y, +-1 if x<y, 0 if x=y. + +
bool operator <= (const type&, const type&) +
+
bool operator < (const type&, const type&) +
+
bool operator >= (const type&, const type&) +
+
bool operator > (const type&, const type&) +
+Comparison, as in C and C++. + +
cl_boolean minusp (const type& x) +
+Compare against zero: x < 0 + +
cl_boolean plusp (const type& x) +
+Compare against zero: x > 0 + +
type max (const type& x, const type& y) +
+Return the maximum of x and y. + +
type min (const type& x, const type& y) +
+Return the minimum of x and y. +
+ +

+When a floating point number and a rational number are compared, the float +is first converted to a rational number using the function rational. +Since a floating point number actually represents an interval of real numbers, +the result might be surprising. +For example, (cl_F)(cl_R)"1/3" == (cl_R)"1/3" returns false because +there is no floating point number whose value is exactly 1/3. + + + + +

4.6 Rounding functions

+ +

+When a real number is to be converted to an integer, there is no "best" +rounding. The desired rounding function depends on the application. +The Common Lisp and ISO Lisp standards offer four rounding functions: + + +

+ +
floor(x) +
+This is the largest integer <=x. + +
ceiling(x) +
+This is the smallest integer >=x. + +
truncate(x) +
+Among the integers between 0 and x (inclusive) the one nearest to x. + +
round(x) +
+The integer nearest to x. If x is exactly halfway between two +integers, choose the even one. +
+ +

+These functions have different advantages: + + +

+floor and ceiling are translation invariant: +floor(x+n) = floor(x) + n and ceiling(x+n) = ceiling(x) + n +for every x and every integer n. + + +

+On the other hand, truncate and round are symmetric: +truncate(-x) = -truncate(x) and round(-x) = -round(x), +and furthermore round is unbiased: on the "average", it rounds +down exactly as often as it rounds up. + + +

+The functions are related like this: + + + +

    +
  • + +ceiling(m/n) = floor((m+n-1)/n) = floor((m-1)/n)+1 +for rational numbers m/n (m, n integers, n>0), and +
  • + +truncate(x) = sign(x) * floor(abs(x)) +
+ +

+Each of the classes cl_R, cl_RA, +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines the following operations: + + +

+ +
cl_I floor1 (const type& x) +
+Returns floor(x). +
cl_I ceiling1 (const type& x) +
+Returns ceiling(x). +
cl_I truncate1 (const type& x) +
+Returns truncate(x). +
cl_I round1 (const type& x) +
+Returns round(x). +
+ +

+Each of the classes cl_R, cl_RA, cl_I, +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines the following operations: + + +

+ +
cl_I floor1 (const type& x, const type& y) +
+Returns floor(x/y). +
cl_I ceiling1 (const type& x, const type& y) +
+Returns ceiling(x/y). +
cl_I truncate1 (const type& x, const type& y) +
+Returns truncate(x/y). +
cl_I round1 (const type& x, const type& y) +
+Returns round(x/y). +
+ +

+These functions are called `floor1', ... here instead of +`floor', ..., because on some systems, system dependent include +files define `floor' and `ceiling' as macros. + + +

+In many cases, one needs both the quotient and the remainder of a division. +It is more efficient to compute both at the same time than to perform +two divisions, one for quotient and the next one for the remainder. +The following functions therefore return a structure containing both +the quotient and the remainder. The suffix `2' indicates the number +of "return values". The remainder is defined as follows: + + + +

    +
  • + +for the computation of quotient = floor(x), +remainder = x - quotient, +
  • + +for the computation of quotient = floor(x,y), +remainder = x - quotient*y, +
+ +

+and similarly for the other three operations. + + +

+Each of the classes cl_R, cl_RA, +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines the following operations: + + +

+ +
struct type_div_t { cl_I quotient; type remainder; }; +
+
type_div_t floor2 (const type& x) +
+
type_div_t ceiling2 (const type& x) +
+
type_div_t truncate2 (const type& x) +
+
type_div_t round2 (const type& x) +
+
+ +

+Each of the classes cl_R, cl_RA, cl_I, +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines the following operations: + + +

+ +
struct type_div_t { cl_I quotient; type remainder; }; +
+
type_div_t floor2 (const type& x, const type& y) +
+
type_div_t ceiling2 (const type& x, const type& y) +
+
type_div_t truncate2 (const type& x, const type& y) +
+
type_div_t round2 (const type& x, const type& y) +
+
+ +

+Sometimes, one wants the quotient as a floating-point number (of the +same format as the argument, if the argument is a float) instead of as +an integer. The prefix `f' indicates this. + + +

+Each of the classes +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines the following operations: + + +

+ +
type ffloor (const type& x) +
+
type fceiling (const type& x) +
+
type ftruncate (const type& x) +
+
type fround (const type& x) +
+
+ +

+and similarly for class cl_R, but with return type cl_F. + + +

+The class cl_R defines the following operations: + + +

+ +
cl_F ffloor (const type& x, const type& y) +
+
cl_F fceiling (const type& x, const type& y) +
+
cl_F ftruncate (const type& x, const type& y) +
+
cl_F fround (const type& x, const type& y) +
+
+ +

+These functions also exist in versions which return both the quotient +and the remainder. The suffix `2' indicates this. + + +

+Each of the classes +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines the following operations: + + +

+ +
struct type_fdiv_t { type quotient; type remainder; }; +
+
type_fdiv_t ffloor2 (const type& x) +
+
type_fdiv_t fceiling2 (const type& x) +
+
type_fdiv_t ftruncate2 (const type& x) +
+
type_fdiv_t fround2 (const type& x) +
+
+

+and similarly for class cl_R, but with quotient type cl_F. + + +

+The class cl_R defines the following operations: + + +

+ +
struct type_fdiv_t { cl_F quotient; cl_R remainder; }; +
+
type_fdiv_t ffloor2 (const type& x, const type& y) +
+
type_fdiv_t fceiling2 (const type& x, const type& y) +
+
type_fdiv_t ftruncate2 (const type& x, const type& y) +
+
type_fdiv_t fround2 (const type& x, const type& y) +
+
+ +

+Other applications need only the remainder of a division. +The remainder of `floor' and `ffloor' is called `mod' +(abbreviation of "modulo"). The remainder `truncate' and +`ftruncate' is called `rem' (abbreviation of "remainder"). + + + +

    +
  • + +mod(x,y) = floor2(x,y).remainder = x - floor(x/y)*y +
  • + +rem(x,y) = truncate2(x,y).remainder = x - truncate(x/y)*y +
+ +

+If x and y are both >= 0, mod(x,y) = rem(x,y) >= 0. +In general, mod(x,y) has the sign of y or is zero, +and rem(x,y) has the sign of x or is zero. + + +

+The classes cl_R, cl_I define the following operations: + + +

+ +
type mod (const type& x, const type& y) +
+
type rem (const type& x, const type& y) +
+
+ + + +

4.7 Roots

+ +

+Each of the classes cl_R, +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines the following operation: + + +

+ +
type sqrt (const type& x) +
+x must be >= 0. This function returns the square root of x, +normalized to be >= 0. If x is the square of a rational number, +sqrt(x) will be a rational number, else it will return a +floating-point approximation. +
+ +

+The classes cl_RA, cl_I define the following operation: + + +

+ +
cl_boolean sqrtp (const type& x, type* root) +
+This tests whether x is a perfect square. If so, it returns true +and the exact square root in *root, else it returns false. +
+ +

+Furthermore, for integers, similarly: + + +

+ +
cl_boolean isqrt (const type& x, type* root) +
+x should be >= 0. This function sets *root to +floor(sqrt(x)) and returns the same value as sqrtp: +the boolean value (expt(*root,2) == x). +
+ +

+For nth roots, the classes cl_RA, cl_I +define the following operation: + + +

+ +
cl_boolean rootp (const type& x, const cl_I& n, type* root) +
+x must be >= 0. n must be > 0. +This tests whether x is an nth power of a rational number. +If so, it returns true and the exact root in *root, else it returns +false. +
+ +

+The only square root function which accepts negative numbers is the one +for class cl_N: + + +

+ +
cl_N sqrt (const cl_N& z) +
+Returns the square root of z, as defined by the formula +sqrt(z) = exp(log(z)/2). Conversion to a floating-point type +or to a complex number are done if necessary. The range of the result is the +right half plane realpart(sqrt(z)) >= 0 +including the positive imaginary axis and 0, but excluding +the negative imaginary axis. +The result is an exact number only if z is an exact number. +
+ + + +

4.8 Transcendental functions

+ +

+The transcendental functions return an exact result if the argument +is exact and the result is exact as well. Otherwise they must return +inexact numbers even if the argument is exact. +For example, cos(0) = 1 returns the rational number 1. + + + + +

4.8.1 Exponential and logarithmic functions

+ +
+ +
cl_R exp (const cl_R& x) +
+
cl_N exp (const cl_N& x) +
+Returns the exponential function of x. This is e^x where +e is the base of the natural logarithms. The range of the result +is the entire complex plane excluding 0. + +
cl_R ln (const cl_R& x) +
+x must be > 0. Returns the (natural) logarithm of x. + +
cl_N log (const cl_N& x) +
+Returns the (natural) logarithm of x. If x is real and positive, +this is ln(x). In general, log(x) = log(abs(x)) + i*phase(x). +The range of the result is the strip in the complex plane +-pi < imagpart(log(x)) <= pi. + +
cl_R phase (const cl_N& x) +
+Returns the angle part of x in its polar representation as a +complex number. That is, phase(x) = atan(realpart(x),imagpart(x)). +This is also the imaginary part of log(x). +The range of the result is the interval -pi < phase(x) <= pi. +The result will be an exact number only if zerop(x) or +if x is real and positive. + +
cl_R log (const cl_R& a, const cl_R& b) +
+a and b must be > 0. Returns the logarithm of a with +respect to base b. log(a,b) = ln(a)/ln(b). +The result can be exact only if a = 1 or if a and b +are both rational. + +
cl_N log (const cl_N& a, const cl_N& b) +
+Returns the logarithm of a with respect to base b. +log(a,b) = log(a)/log(b). + +
cl_N expt (const cl_N& x, const cl_N& y) +
+Exponentiation: Returns x^y = exp(y*log(x)). +
+ +

+The constant e = exp(1) = 2.71828... is returned by the following functions: + + +

+ +
cl_F cl_exp1 (cl_float_format_t f) +
+Returns e as a float of format f. + +
cl_F cl_exp1 (const cl_F& y) +
+Returns e in the float format of y. + +
cl_F cl_exp1 (void) +
+Returns e as a float of format cl_default_float_format. +
+ + + +

4.8.2 Trigonometric functions

+ +
+ +
cl_R sin (const cl_R& x) +
+Returns sin(x). The range of the result is the interval +-1 <= sin(x) <= 1. + +
cl_N sin (const cl_N& z) +
+Returns sin(z). The range of the result is the entire complex plane. + +
cl_R cos (const cl_R& x) +
+Returns cos(x). The range of the result is the interval +-1 <= cos(x) <= 1. + +
cl_N cos (const cl_N& x) +
+Returns cos(z). The range of the result is the entire complex plane. + +
struct cl_cos_sin_t { cl_R cos; cl_R sin; }; +
+
cl_cos_sin_t cl_cos_sin (const cl_R& x) +
+Returns both sin(x) and cos(x). This is more efficient than +computing them separately. The relation cos^2 + sin^2 = 1 will +hold only approximately. + +
cl_R tan (const cl_R& x) +
+
cl_N tan (const cl_N& x) +
+Returns tan(x) = sin(x)/cos(x). + +
cl_N cis (const cl_R& x) +
+
cl_N cis (const cl_N& x) +
+Returns exp(i*x). The name `cis' means "cos + i sin", because +e^(i*x) = cos(x) + i*sin(x). + +
cl_N asin (const cl_N& z) +
+Returns arcsin(z). This is defined as +arcsin(z) = log(iz+sqrt(1-z^2))/i and satisfies +arcsin(-z) = -arcsin(z). +The range of the result is the strip in the complex domain +-pi/2 <= realpart(arcsin(z)) <= pi/2, excluding the numbers +with realpart = -pi/2 and imagpart < 0 and the numbers +with realpart = pi/2 and imagpart > 0. + +
cl_N acos (const cl_N& z) +
+Returns arccos(z). This is defined as +arccos(z) = pi/2 - arcsin(z) = log(z+i*sqrt(1-z^2))/i +and satisfies arccos(-z) = pi - arccos(z). +The range of the result is the strip in the complex domain +0 <= realpart(arcsin(z)) <= pi, excluding the numbers +with realpart = 0 and imagpart < 0 and the numbers +with realpart = pi and imagpart > 0. + +
cl_R atan (const cl_R& x, const cl_R& y) +
+Returns the angle of the polar representation of the complex number +x+iy. This is atan(y/x) if x>0. The range of +the result is the interval -pi < atan(x,y) <= pi. The result will +be an exact number only if x > 0 and y is the exact 0. +WARNING: In Common Lisp, this function is called as (atan y x), +with reversed order of arguments. + +
cl_R atan (const cl_R& x) +
+Returns arctan(x). This is the same as atan(1,x). The range +of the result is the interval -pi/2 < atan(x) < pi/2. The result +will be an exact number only if x is the exact 0. + +
cl_N atan (const cl_N& z) +
+Returns arctan(z). This is defined as +arctan(z) = (log(1+iz)-log(1-iz)) / 2i and satisfies +arctan(-z) = -arctan(z). The range of the result is +the strip in the complex domain +-pi/2 <= realpart(arctan(z)) <= pi/2, excluding the numbers +with realpart = -pi/2 and imagpart >= 0 and the numbers +with realpart = pi/2 and imagpart <= 0. + +
+ +

+The constant pi = 3.14... is returned by the following functions: + + +

+ +
cl_F cl_pi (cl_float_format_t f) +
+Returns pi as a float of format f. + +
cl_F cl_pi (const cl_F& y) +
+Returns pi in the float format of y. + +
cl_F cl_pi (void) +
+Returns pi as a float of format cl_default_float_format. +
+ + + +

4.8.3 Hyperbolic functions

+ +
+ +
cl_R sinh (const cl_R& x) +
+Returns sinh(x). + +
cl_N sinh (const cl_N& z) +
+Returns sinh(z). The range of the result is the entire complex plane. + +
cl_R cosh (const cl_R& x) +
+Returns cosh(x). The range of the result is the interval +cosh(x) >= 1. + +
cl_N cosh (const cl_N& z) +
+Returns cosh(z). The range of the result is the entire complex plane. + +
struct cl_cosh_sinh_t { cl_R cosh; cl_R sinh; }; +
+
cl_cosh_sinh_t cl_cosh_sinh (const cl_R& x) +
+Returns both sinh(x) and cosh(x). This is more efficient than +computing them separately. The relation cosh^2 - sinh^2 = 1 will +hold only approximately. + +
cl_R tanh (const cl_R& x) +
+
cl_N tanh (const cl_N& x) +
+Returns tanh(x) = sinh(x)/cosh(x). + +
cl_N asinh (const cl_N& z) +
+Returns arsinh(z). This is defined as +arsinh(z) = log(z+sqrt(1+z^2)) and satisfies +arsinh(-z) = -arsinh(z). +The range of the result is the strip in the complex domain +-pi/2 <= imagpart(arsinh(z)) <= pi/2, excluding the numbers +with imagpart = -pi/2 and realpart > 0 and the numbers +with imagpart = pi/2 and realpart < 0. + +
cl_N acosh (const cl_N& z) +
+Returns arcosh(z). This is defined as +arcosh(z) = 2*log(sqrt((z+1)/2)+sqrt((z-1)/2)). +The range of the result is the half-strip in the complex domain +-pi < imagpart(arcosh(z)) <= pi, realpart(arcosh(z)) >= 0, +excluding the numbers with realpart = 0 and -pi < imagpart < 0. + +
cl_N atanh (const cl_N& z) +
+Returns artanh(z). This is defined as +artanh(z) = (log(1+z)-log(1-z)) / 2 and satisfies +artanh(-z) = -artanh(z). The range of the result is +the strip in the complex domain +-pi/2 <= imagpart(artanh(z)) <= pi/2, excluding the numbers +with imagpart = -pi/2 and realpart <= 0 and the numbers +with imagpart = pi/2 and realpart >= 0. +
+ + + +

4.8.4 Euler gamma

+ +

+Euler's constant C = 0.577... is returned by the following functions: + + +

+ +
cl_F cl_eulerconst (cl_float_format_t f) +
+Returns Euler's constant as a float of format f. + +
cl_F cl_eulerconst (const cl_F& y) +
+Returns Euler's constant in the float format of y. + +
cl_F cl_eulerconst (void) +
+Returns Euler's constant as a float of format cl_default_float_format. +
+ +

+Catalan's constant G = 0.915... is returned by the following functions: + + +

+ +
cl_F cl_catalanconst (cl_float_format_t f) +
+Returns Catalan's constant as a float of format f. + +
cl_F cl_catalanconst (const cl_F& y) +
+Returns Catalan's constant in the float format of y. + +
cl_F cl_catalanconst (void) +
+Returns Catalan's constant as a float of format cl_default_float_format. +
+ + + +

4.8.5 Riemann zeta

+ +

+Riemann's zeta function at an integral point s>1 is returned by the +following functions: + + +

+ +
cl_F cl_zeta (int s, cl_float_format_t f) +
+Returns Riemann's zeta function at s as a float of format f. + +
cl_F cl_zeta (int s, const cl_F& y) +
+Returns Riemann's zeta function at s in the float format of y. + +
cl_F cl_zeta (int s) +
+Returns Riemann's zeta function at s as a float of format +cl_default_float_format. +
+ + + +

4.9 Functions on integers

+ + + +

4.9.1 Logical functions

+ +

+Integers, when viewed as in two's complement notation, can be thought as +infinite bit strings where the bits' values eventually are constant. +For example, + +

+    17 = ......00010001
+    -6 = ......11111010
+
+ +

+The logical operations view integers as such bit strings and operate +on each of the bit positions in parallel. + + +

+ +
cl_I lognot (const cl_I& x) +
+
cl_I operator ~ (const cl_I& x) +
+Logical not, like ~x in C. This is the same as -1-x. + +
cl_I logand (const cl_I& x, const cl_I& y) +
+
cl_I operator & (const cl_I& x, const cl_I& y) +
+Logical and, like x & y in C. + +
cl_I logior (const cl_I& x, const cl_I& y) +
+
cl_I operator | (const cl_I& x, const cl_I& y) +
+Logical (inclusive) or, like x | y in C. + +
cl_I logxor (const cl_I& x, const cl_I& y) +
+
cl_I operator ^ (const cl_I& x, const cl_I& y) +
+Exclusive or, like x ^ y in C. + +
cl_I logeqv (const cl_I& x, const cl_I& y) +
+Bitwise equivalence, like ~(x ^ y) in C. + +
cl_I lognand (const cl_I& x, const cl_I& y) +
+Bitwise not and, like ~(x & y) in C. + +
cl_I lognor (const cl_I& x, const cl_I& y) +
+Bitwise not or, like ~(x | y) in C. + +
cl_I logandc1 (const cl_I& x, const cl_I& y) +
+Logical and, complementing the first argument, like ~x & y in C. + +
cl_I logandc2 (const cl_I& x, const cl_I& y) +
+Logical and, complementing the second argument, like x & ~y in C. + +
cl_I logorc1 (const cl_I& x, const cl_I& y) +
+Logical or, complementing the first argument, like ~x | y in C. + +
cl_I logorc2 (const cl_I& x, const cl_I& y) +
+Logical or, complementing the second argument, like x | ~y in C. +
+ +

+These operations are all available though the function +

+ +
cl_I boole (cl_boole op, const cl_I& x, const cl_I& y) +
+
+

+where op must have one of the 16 values (each one stands for a function +which combines two bits into one bit): boole_clr, boole_set, +boole_1, boole_2, boole_c1, boole_c2, +boole_and, boole_ior, boole_xor, boole_eqv, +boole_nand, boole_nor, boole_andc1, boole_andc2, +boole_orc1, boole_orc2. + + +

+Other functions that view integers as bit strings: + + +

+ +
cl_boolean logtest (const cl_I& x, const cl_I& y) +
+Returns true if some bit is set in both x and y, i.e. if +logand(x,y) != 0. + +
cl_boolean logbitp (const cl_I& n, const cl_I& x) +
+Returns true if the nth bit (from the right) of x is set. +Bit 0 is the least significant bit. + +
uintL logcount (const cl_I& x) +
+Returns the number of one bits in x, if x >= 0, or +the number of zero bits in x, if x < 0. +
+ +

+The following functions operate on intervals of bits in integers. +The type + +

+struct cl_byte { uintL size; uintL position; };
+
+ +

+represents the bit interval containing the bits +position...position+size-1 of an integer. +The constructor cl_byte(size,position) constructs a cl_byte. + + +

+ +
cl_I ldb (const cl_I& n, const cl_byte& b) +
+extracts the bits of n described by the bit interval b +and returns them as a nonnegative integer with b.size bits. + +
cl_boolean ldb_test (const cl_I& n, const cl_byte& b) +
+Returns true if some bit described by the bit interval b is set in +n. + +
cl_I dpb (const cl_I& newbyte, const cl_I& n, const cl_byte& b) +
+Returns n, with the bits described by the bit interval b +replaced by newbyte. Only the lowest b.size bits of +newbyte are relevant. +
+ +

+The functions ldb and dpb implicitly shift. The following +functions are their counterparts without shifting: + + +

+ +
cl_I mask_field (const cl_I& n, const cl_byte& b) +
+returns an integer with the bits described by the bit interval b +copied from the corresponding bits in n, the other bits zero. + +
cl_I deposit_field (const cl_I& newbyte, const cl_I& n, const cl_byte& b) +
+returns an integer where the bits described by the bit interval b +come from newbyte and the other bits come from n. +
+ +

+The following relations hold: + + + +

    +
  • + +ldb (n, b) = mask_field(n, b) >> b.position, +
  • + +dpb (newbyte, n, b) = deposit_field (newbyte << b.position, n, b), +
  • + +deposit_field(newbyte,n,b) = n ^ mask_field(n,b) ^ mask_field(new_byte,b). +
+ +

+The following operations on integers as bit strings are efficient shortcuts +for common arithmetic operations: + + +

+ +
cl_boolean oddp (const cl_I& x) +
+Returns true if the least significant bit of x is 1. Equivalent to +mod(x,2) != 0. + +
cl_boolean evenp (const cl_I& x) +
+Returns true if the least significant bit of x is 0. Equivalent to +mod(x,2) == 0. + +
cl_I operator << (const cl_I& x, const cl_I& n) +
+Shifts x by n bits to the left. n should be >=0. +Equivalent to x * expt(2,n). + +
cl_I operator >> (const cl_I& x, const cl_I& n) +
+Shifts x by n bits to the right. n should be >=0. +Bits shifted out to the right are thrown away. +Equivalent to floor(x / expt(2,n)). + +
cl_I ash (const cl_I& x, const cl_I& y) +
+Shifts x by y bits to the left (if y>=0) or +by -y bits to the right (if y<=0). In other words, this +returns floor(x * expt(2,y)). + +
uintL integer_length (const cl_I& x) +
+Returns the number of bits (excluding the sign bit) needed to represent x +in two's complement notation. This is the smallest n >= 0 such that +-2^n <= x < 2^n. If x > 0, this is the unique n > 0 such that +2^(n-1) <= x < 2^n. + +
uintL ord2 (const cl_I& x) +
+x must be non-zero. This function returns the number of 0 bits at the +right of x in two's complement notation. This is the largest n >= 0 +such that 2^n divides x. + +
uintL power2p (const cl_I& x) +
+x must be > 0. This function checks whether x is a power of 2. +If x = 2^(n-1), it returns n. Else it returns 0. +(See also the function logp.) +
+ + + +

4.9.2 Number theoretic functions

+ +
+ +
uint32 gcd (uint32 a, uint32 b) +
+
cl_I gcd (const cl_I& a, const cl_I& b) +
+This function returns the greatest common divisor of a and b, +normalized to be >= 0. + +
cl_I xgcd (const cl_I& a, const cl_I& b, cl_I* u, cl_I* v) +
+This function ("extended gcd") returns the greatest common divisor g of +a and b and at the same time the representation of g +as an integral linear combination of a and b: +u and v with u*a+v*b = g, g >= 0. +u and v will be normalized to be of smallest possible absolute +value, in the following sense: If a and b are non-zero, and +abs(a) != abs(b), u and v will satisfy the inequalities +abs(u) <= abs(b)/(2*g), abs(v) <= abs(a)/(2*g). + +
cl_I lcm (const cl_I& a, const cl_I& b) +
+This function returns the least common multiple of a and b, +normalized to be >= 0. + +
cl_boolean logp (const cl_I& a, const cl_I& b, cl_RA* l) +
+
cl_boolean logp (const cl_RA& a, const cl_RA& b, cl_RA* l) +
+a must be > 0. b must be >0 and != 1. If log(a,b) is +rational number, this function returns true and sets *l = log(a,b), else +it returns false. +
+ + + +

4.9.3 Combinatorial functions

+ +
+ +
cl_I factorial (uintL n) +
+n must be a small integer >= 0. This function returns the factorial +n! = 1*2*...*n. + +
cl_I doublefactorial (uintL n) +
+n must be a small integer >= 0. This function returns the +doublefactorial n!! = 1*3*...*n or +n!! = 2*4*...*n, respectively. + +
cl_I binomial (uintL n, uintL k) +
+n and k must be small integers >= 0. This function returns the +binomial coefficient +(n choose k) = n! / k! (n-k)! +for 0 <= k <= n, 0 else. +
+ + + +

4.10 Functions on floating-point numbers

+ +

+Recall that a floating-point number consists of a sign s, an +exponent e and a mantissa m. The value of the number is +(-1)^s * 2^e * m. + + +

+Each of the classes +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines the following operations. + + +

+ +
type scale_float (const type& x, sintL delta) +
+
type scale_float (const type& x, const cl_I& delta) +
+Returns x*2^delta. This is more efficient than an explicit multiplication +because it copies x and modifies the exponent. +
+ +

+The following functions provide an abstract interface to the underlying +representation of floating-point numbers. + + +

+ +
sintL float_exponent (const type& x) +
+Returns the exponent e of x. +For x = 0.0, this is 0. For x non-zero, this is the unique +integer with 2^(e-1) <= abs(x) < 2^e. + +
sintL float_radix (const type& x) +
+Returns the base of the floating-point representation. This is always 2. + +
type float_sign (const type& x) +
+Returns the sign s of x as a float. The value is 1 for +x >= 0, -1 for x < 0. + +
uintL float_digits (const type& x) +
+Returns the number of mantissa bits in the floating-point representation +of x, including the hidden bit. The value only depends on the type +of x, not on its value. + +
uintL float_precision (const type& x) +
+Returns the number of significant mantissa bits in the floating-point +representation of x. Since denormalized numbers are not supported, +this is the same as float_digits(x) if x is non-zero, and +0 if x = 0. +
+ +

+The complete internal representation of a float is encoded in the type +cl_decoded_float (or cl_decoded_sfloat, cl_decoded_ffloat, +cl_decoded_dfloat, cl_decoded_lfloat, respectively), defined by + +

+struct cl_decoded_typefloat {
+        type mantissa; cl_I exponent; type sign;
+};
+
+ +

+and returned by the function + + +

+ +
cl_decoded_typefloat decode_float (const type& x) +
+For x non-zero, this returns (-1)^s, e, m with +x = (-1)^s * 2^e * m and 0.5 <= m < 1.0. For x = 0, +it returns (-1)^s=1, e=0, m=0. +e is the same as returned by the function float_exponent. +
+ +

+A complete decoding in terms of integers is provided as type + +

+struct cl_idecoded_float {
+        cl_I mantissa; cl_I exponent; cl_I sign;
+};
+
+ +

+by the following function: + + +

+ +
cl_idecoded_float integer_decode_float (const type& x) +
+For x non-zero, this returns (-1)^s, e, m with +x = (-1)^s * 2^e * m and m an integer with float_digits(x) +bits. For x = 0, it returns (-1)^s=1, e=0, m=0. +WARNING: The exponent e is not the same as the one returned by +the functions decode_float and float_exponent. +
+ +

+Some other function, implemented only for class cl_F: + + +

+ +
cl_F float_sign (const cl_F& x, const cl_F& y) +
+This returns a floating point number whose precision and absolute value +is that of y and whose sign is that of x. If x is +zero, it is treated as positive. Same for y. +
+ + + +

4.11 Conversion functions

+ + + +

4.11.1 Conversion to floating-point numbers

+ +

+The type cl_float_format_t describes a floating-point format. + + +

+ +
cl_float_format_t cl_float_format (uintL n) +
+Returns the smallest float format which guarantees at least n +decimal digits in the mantissa (after the decimal point). + +
cl_float_format_t cl_float_format (const cl_F& x) +
+Returns the floating point format of x. + +
cl_float_format_t cl_default_float_format +
+Global variable: the default float format used when converting rational numbers +to floats. +
+ +

+To convert a real number to a float, each of the types +cl_R, cl_F, cl_I, cl_RA, +int, unsigned int, float, double +defines the following operations: + + +

+ +
cl_F cl_float (const type&x, cl_float_format_t f) +
+Returns x as a float of format f. +
cl_F cl_float (const type&x, const cl_F& y) +
+Returns x in the float format of y. +
cl_F cl_float (const type&x) +
+Returns x as a float of format cl_default_float_format if +it is an exact number, or x itself if it is already a float. +
+ +

+Of course, converting a number to a float can lose precision. + + +

+Every floating-point format has some characteristic numbers: + + +

+ +
cl_F most_positive_float (cl_float_format_t f) +
+Returns the largest (most positive) floating point number in float format f. + +
cl_F most_negative_float (cl_float_format_t f) +
+Returns the smallest (most negative) floating point number in float format f. + +
cl_F least_positive_float (cl_float_format_t f) +
+Returns the least positive floating point number (i.e. > 0 but closest to 0) +in float format f. + +
cl_F least_negative_float (cl_float_format_t f) +
+Returns the least negative floating point number (i.e. < 0 but closest to 0) +in float format f. + +
cl_F float_epsilon (cl_float_format_t f) +
+Returns the smallest floating point number e > 0 such that 1+e != 1. + +
cl_F float_negative_epsilon (cl_float_format_t f) +
+Returns the smallest floating point number e > 0 such that 1-e != 1. +
+ + + +

4.11.2 Conversion to rational numbers

+ +

+Each of the classes cl_R, cl_RA, cl_F +defines the following operation: + + +

+ +
cl_RA rational (const type& x) +
+Returns the value of x as an exact number. If x is already +an exact number, this is x. If x is a floating-point number, +the value is a rational number whose denominator is a power of 2. +
+ +

+In order to convert back, say, (cl_F)(cl_R)"1/3" to 1/3, there is +the function + + +

+ +
cl_RA rationalize (const cl_R& x) +
+If x is a floating-point number, it actually represents an interval +of real numbers, and this function returns the rational number with +smallest denominator (and smallest numerator, in magnitude) +which lies in this interval. +If x is already an exact number, this function returns x. +
+ +

+If x is any float, one has + + + +

    +
  • + +cl_float(rational(x),x) = x +
  • + +cl_float(rationalize(x),x) = x +
+ + + +

4.12 Random number generators

+ +

+A random generator is a machine which produces (pseudo-)random numbers. +The include file <cl_random.h> defines a class cl_random_state +which contains the state of a random generator. If you make a copy +of the random number generator, the original one and the copy will produce +the same sequence of random numbers. + + +

+The following functions return (pseudo-)random numbers in different formats. +Calling one of these modifies the state of the random number generator in +a complicated but deterministic way. + + +

+The global variable + +

+cl_random_state cl_default_random_state
+
+ +

+contains a default random number generator. It is used when the functions +below are called without cl_random_state argument. + + +

+ +
uint32 random32 (cl_random_state& randomstate) +
+
uint32 random32 () +
+Returns a random unsigned 32-bit number. All bits are equally random. + +
cl_I random_I (cl_random_state& randomstate, const cl_I& n) +
+
cl_I random_I (const cl_I& n) +
+n must be an integer > 0. This function returns a random integer x +in the range 0 <= x < n. + +
cl_F random_F (cl_random_state& randomstate, const cl_F& n) +
+
cl_F random_F (const cl_F& n) +
+n must be a float > 0. This function returns a random floating-point +number of the same format as n in the range 0 <= x < n. + +
cl_R random_R (cl_random_state& randomstate, const cl_R& n) +
+
cl_R random_R (const cl_R& n) +
+Behaves like random_I if n is an integer and like random_F +if n is a float. +
+ + + +

4.13 Obfuscating operators

+ +

+The modifying C/C++ operators +=, -=, *=, /=, +&=, |=, ^=, <<=, >>= +are not available by default because their +use tends to make programs unreadable. It is trivial to get away without +them. However, if you feel that you absolutely need these operators +to get happy, then add + +

+#define WANT_OBFUSCATING_OPERATORS
+
+ +

+to the beginning of your source files, before the inclusion of any CLN +include files. This flag will enable the following operators: + + +

+For the classes cl_N, cl_R, cl_RA, +cl_F, cl_SF, cl_FF, cl_DF, cl_LF: + + +

+ +
type& operator += (type&, const type&) +
+
type& operator -= (type&, const type&) +
+
type& operator *= (type&, const type&) +
+
type& operator /= (type&, const type&) +
+
+ +

+For the class cl_I: + + +

+ +
type& operator += (type&, const type&) +
+
type& operator -= (type&, const type&) +
+
type& operator *= (type&, const type&) +
+
type& operator &= (type&, const type&) +
+
type& operator |= (type&, const type&) +
+
type& operator ^= (type&, const type&) +
+
type& operator <<= (type&, const type&) +
+
type& operator >>= (type&, const type&) +
+
+ +

+For the classes cl_N, cl_R, cl_RA, cl_I, +cl_F, cl_SF, cl_FF, cl_DF, cl_LF: + + +

+ +
type& operator ++ (type& x) +
+The prefix operator ++x. + +
void operator ++ (type& x, int) +
+The postfix operator x++. + +
type& operator -- (type& x) +
+The prefix operator --x. + +
void operator -- (type& x, int) +
+The postfix operator x--. +
+ +

+Note that by using these obfuscating operators, you wouldn't gain efficiency: +In CLN `x += y;' is exactly the same as `x = x+y;', not more +efficient. + + + + +

5. Input/Output

+ + + +

5.1 Internal and printed representation

+ +

+All computations deal with the internal representations of the numbers. + + +

+Every number has an external representation as a sequence of ASCII characters. +Several external representations may denote the same number, for example, +"20.0" and "20.000". + + +

+Converting an internal to an external representation is called "printing", +converting an external to an internal representation is called "reading". +In CLN, is it always true that conversion of an internal to an external +representation and then back to an internal representation will yield the +same internal representation. Symbolically: read(print(x)) == x. +This is called "print-read consistency". + + +

+Different types of numbers have different external representations (case +is insignificant): + + +

+ +
Integers +
+External representation: sign{digit}+. The reader also accepts the +Common Lisp syntaxes sign{digit}+. with a trailing dot +for decimal integers +and the #nR, #b, #o, #x prefixes. + +
Rational numbers +
+External representation: sign{digit}+/{digit}+. +The #nR, #b, #o, #x prefixes are allowed +here as well. + +
Floating-point numbers +
+External representation: sign{digit}*exponent or +sign{digit}*.{digit}*exponent or +sign{digit}*.{digit}+. A precision specifier +of the form _prec may be appended. There must be at least +one digit in the non-exponent part. The exponent has the syntax +expmarker expsign {digit}+. +The exponent marker is + + +
    +
  • + +`s' for short-floats, +
  • + +`f' for single-floats, +
  • + +`d' for double-floats, +
  • + +`L' for long-floats, +
+ +or `e', which denotes a default float format. The precision specifying +suffix has the syntax _prec where prec denotes the number of +valid mantissa digits (in decimal, excluding leading zeroes), cf. also +function `cl_float_format'. + +
Complex numbers +
+External representation: + +
    +
  • + +In algebraic notation: realpart+imagparti. Of course, +if imagpart is negative, its printed representation begins with +a `-', and the `+' between realpart and imagpart +may be omitted. Note that this notation cannot be used when the imagpart +is rational and the rational number's base is >18, because the `i' +is then read as a digit. +
  • + +In Common Lisp notation: #C(realpart imagpart). +
+ +
+ + + +

5.2 Input functions

+ +

+Including <cl_io.h> defines a type cl_istream, which is +the type of the first argument to all input functions. Unless you build +and use CLN with the macro CL_IO_STDIO being defined, cl_istream +is the same as istream&. + + +

+The variable + +

    +
  • + +cl_istream cl_stdin +
+ +

+contains the standard input stream. + + +

+These are the simple input functions: + + +

+ +
int freadchar (cl_istream stream) +
+Reads a character from stream. Returns cl_EOF (not a `char'!) +if the end of stream was encountered or an error occurred. + +
int funreadchar (cl_istream stream, int c) +
+Puts back c onto stream. c must be the result of the +last freadchar operation on stream. +
+ +

+Each of the classes cl_N, cl_R, cl_RA, cl_I, +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines, in <cl_type_io.h>, the following input function: + + +

+ +
cl_istream operator>> (cl_istream stream, type& result) +
+Reads a number from stream and stores it in the result. +
+ +

+The most flexible input functions, defined in <cl_type_io.h>, +are the following: + + +

+ +
cl_N read_complex (cl_istream stream, const cl_read_flags& flags) +
+
cl_R read_real (cl_istream stream, const cl_read_flags& flags) +
+
cl_F read_float (cl_istream stream, const cl_read_flags& flags) +
+
cl_RA read_rational (cl_istream stream, const cl_read_flags& flags) +
+
cl_I read_integer (cl_istream stream, const cl_read_flags& flags) +
+Reads a number from stream. The flags are parameters which +affect the input syntax. Whitespace before the number is silently skipped. + +
cl_N read_complex (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse) +
+
cl_R read_real (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse) +
+
cl_F read_float (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse) +
+
cl_RA read_rational (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse) +
+
cl_I read_integer (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse) +
+Reads a number from a string in memory. The flags are parameters which +affect the input syntax. The string starts at string and ends at +string_limit (exclusive limit). string_limit may also be +NULL, denoting the entire string, i.e. equivalent to +string_limit = string + strlen(string). If end_of_parse is +NULL, the string in memory must contain exactly one number and nothing +more, else a fatal error will be signalled. If end_of_parse +is not NULL, *end_of_parse will be assigned a pointer past +the last parsed character (i.e. string_limit if nothing came after +the number). Whitespace is not allowed. +
+ +

+The structure cl_read_flags contains the following fields: + + +

+ +
cl_read_syntax_t syntax +
+The possible results of the read operation. Possible values are +syntax_number, syntax_real, syntax_rational, +syntax_integer, syntax_float, syntax_sfloat, +syntax_ffloat, syntax_dfloat, syntax_lfloat. + +
cl_read_lsyntax_t lsyntax +
+Specifies the language-dependent syntax variant for the read operation. +Possible values are + +
+ +
lsyntax_standard +
+accept standard algebraic notation only, no complex numbers, +
lsyntax_algebraic +
+accept the algebraic notation x+yi for complex numbers, +
lsyntax_commonlisp +
+accept the #b, #o, #x syntaxes for binary, octal, +hexadecimal numbers, +#baseR for rational numbers in a given base, +#c(realpart imagpart) for complex numbers, +
lsyntax_all +
+accept all of these extensions. +
+ +
unsigned int rational_base +
+The base in which rational numbers are read. + +
cl_float_format_t float_flags.default_float_format +
+The float format used when reading floats with exponent marker `e'. + +
cl_float_format_t float_flags.default_lfloat_format +
+The float format used when reading floats with exponent marker `l'. + +
cl_boolean float_flags.mantissa_dependent_float_format +
+When this flag is true, floats specified with more digits than corresponding +to the exponent marker they contain, but without _nnn suffix, will get a +precision corresponding to their number of significant digits. +
+ + + +

5.3 Output functions

+ +

+Including <cl_io.h> defines a type cl_ostream, which is +the type of the first argument to all output functions. Unless you build +and use CLN with the macro CL_IO_STDIO being defined, cl_ostream +is the same as ostream&. + + +

+The variable + +

    +
  • + +cl_ostream cl_stdout +
+ +

+contains the standard output stream. + + +

+The variable + +

    +
  • + +cl_ostream cl_stderr +
+ +

+contains the standard error output stream. + + +

+These are the simple output functions: + + +

+ +
void fprintchar (cl_ostream stream, char c) +
+Prints the character x literally on the stream. + +
void fprint (cl_ostream stream, const char * string) +
+Prints the string literally on the stream. + +
void fprintdecimal (cl_ostream stream, int x) +
+
void fprintdecimal (cl_ostream stream, const cl_I& x) +
+Prints the integer x in decimal on the stream. + +
void fprintbinary (cl_ostream stream, const cl_I& x) +
+Prints the integer x in binary (base 2, without prefix) +on the stream. + +
void fprintoctal (cl_ostream stream, const cl_I& x) +
+Prints the integer x in octal (base 8, without prefix) +on the stream. + +
void fprinthexadecimal (cl_ostream stream, const cl_I& x) +
+Prints the integer x in hexadecimal (base 16, without prefix) +on the stream. +
+ +

+Each of the classes cl_N, cl_R, cl_RA, cl_I, +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines, in <cl_type_io.h>, the following output functions: + + +

+ +
void fprint (cl_ostream stream, const type& x) +
+
cl_ostream operator<< (cl_ostream stream, const type& x) +
+Prints the number x on the stream. The output may depend +on the global printer settings in the variable cl_default_print_flags. +The ostream flags and settings (flags, width and locale) are +ignored. +
+ +

+The most flexible output function, defined in <cl_type_io.h>, +are the following: + +

+void print_complex  (cl_ostream stream, const cl_print_flags& flags,
+                     const cl_N& z);
+void print_real     (cl_ostream stream, const cl_print_flags& flags,
+                     const cl_R& z);
+void print_float    (cl_ostream stream, const cl_print_flags& flags,
+                     const cl_F& z);
+void print_rational (cl_ostream stream, const cl_print_flags& flags,
+                     const cl_RA& z);
+void print_integer  (cl_ostream stream, const cl_print_flags& flags,
+                     const cl_I& z);
+
+ +

+Prints the number x on the stream. The flags are +parameters which affect the output. + + +

+The structure type cl_print_flags contains the following fields: + + +

+ +
unsigned int rational_base +
+The base in which rational numbers are printed. Default is 10. + +
cl_boolean rational_readably +
+If this flag is true, rational numbers are printed with radix specifiers in +Common Lisp syntax (#nR or #b or #o or #x +prefixes, trailing dot). Default is false. + +
cl_boolean float_readably +
+If this flag is true, type specific exponent markers have precedence over 'E'. +Default is false. + +
cl_float_format_t default_float_format +
+Floating point numbers of this format will be printed using the 'E' exponent +marker. Default is cl_float_format_ffloat. + +
cl_boolean complex_readably +
+If this flag is true, complex numbers will be printed using the Common Lisp +syntax #C(realpart imagpart). Default is false. + +
cl_string univpoly_varname +
+Univariate polynomials with no explicit indeterminate name will be printed +using this variable name. Default is "x". +
+ +

+The global variable cl_default_print_flags contains the default values, +used by the function fprint, + + + + +

6. Rings

+ +

+CLN has a class of abstract rings. + + + +

+                         Ring
+                       cl_ring
+                      <cl_ring.h>
+
+ +

+Rings can be compared for equality: + + +

+ +
bool operator== (const cl_ring&, const cl_ring&) +
+
bool operator!= (const cl_ring&, const cl_ring&) +
+These compare two rings for equality. +
+ +

+Given a ring R, the following members can be used. + + +

+ +
void R->fprint (cl_ostream stream, const cl_ring_element& x) +
+
cl_boolean R->equal (const cl_ring_element& x, const cl_ring_element& y) +
+
cl_ring_element R->zero () +
+
cl_boolean R->zerop (const cl_ring_element& x) +
+
cl_ring_element R->plus (const cl_ring_element& x, const cl_ring_element& y) +
+
cl_ring_element R->minus (const cl_ring_element& x, const cl_ring_element& y) +
+
cl_ring_element R->uminus (const cl_ring_element& x) +
+
cl_ring_element R->one () +
+
cl_ring_element R->canonhom (const cl_I& x) +
+
cl_ring_element R->mul (const cl_ring_element& x, const cl_ring_element& y) +
+
cl_ring_element R->square (const cl_ring_element& x) +
+
cl_ring_element R->expt_pos (const cl_ring_element& x, const cl_I& y) +
+
+ +

+The following rings are built-in. + + +

+ +
cl_null_ring cl_0_ring +
+The null ring, containing only zero. + +
cl_complex_ring cl_C_ring +
+The ring of complex numbers. This corresponds to the type cl_N. + +
cl_real_ring cl_R_ring +
+The ring of real numbers. This corresponds to the type cl_R. + +
cl_rational_ring cl_RA_ring +
+The ring of rational numbers. This corresponds to the type cl_RA. + +
cl_integer_ring cl_I_ring +
+The ring of integers. This corresponds to the type cl_I. +
+ +

+Type tests can be performed for any of cl_C_ring, cl_R_ring, +cl_RA_ring, cl_I_ring: + + +

+ +
cl_boolean instanceof (const cl_number& x, const cl_number_ring& R) +
+Tests whether the given number is an element of the number ring R. +
+ + + +

7. Modular integers

+ + + +

7.1 Modular integer rings

+ +

+CLN implements modular integers, i.e. integers modulo a fixed integer N. +The modulus is explicitly part of every modular integer. CLN doesn't +allow you to (accidentally) mix elements of different modular rings, +e.g. (3 mod 4) + (2 mod 5) will result in a runtime error. +(Ideally one would imagine a generic data type cl_MI(N), but C++ +doesn't have generic types. So one has to live with runtime checks.) + + +

+The class of modular integer rings is + + + +

+                         Ring
+                       cl_ring
+                      <cl_ring.h>
+                          |
+                          |
+                 Modular integer ring
+                    cl_modint_ring
+                   <cl_modinteger.h>
+
+ +

+and the class of all modular integers (elements of modular integer rings) is + + + +

+                    Modular integer
+                         cl_MI
+                   <cl_modinteger.h>
+
+ +

+Modular integer rings are constructed using the function + + +

+ +
cl_modint_ring cl_find_modint_ring (const cl_I& N) +
+This function returns the modular ring `Z/NZ'. It takes care +of finding out about special cases of N, like powers of two +and odd numbers for which Montgomery multiplication will be a win, +and precomputes any necessary auxiliary data for computing modulo N. +There is a cache table of rings, indexed by N (or, more precisely, +by abs(N)). This ensures that the precomputation costs are reduced +to a minimum. +
+ +

+Modular integer rings can be compared for equality: + + +

+ +
bool operator== (const cl_modint_ring&, const cl_modint_ring&) +
+
bool operator!= (const cl_modint_ring&, const cl_modint_ring&) +
+These compare two modular integer rings for equality. Two different calls +to cl_find_modint_ring with the same argument necessarily return the +same ring because it is memoized in the cache table. +
+ + + +

7.2 Functions on modular integers

+ +

+Given a modular integer ring R, the following members can be used. + + +

+ +
cl_I R->modulus +
+This is the ring's modulus, normalized to be nonnegative: abs(N). + +
cl_MI R->zero() +
+This returns 0 mod N. + +
cl_MI R->one() +
+This returns 1 mod N. + +
cl_MI R->canonhom (const cl_I& x) +
+This returns x mod N. + +
cl_I R->retract (const cl_MI& x) +
+This is a partial inverse function to R->canonhom. It returns the +standard representative (>=0, <N) of x. + +
cl_MI R->random(cl_random_state& randomstate) +
+
cl_MI R->random() +
+This returns a random integer modulo N. +
+ +

+The following operations are defined on modular integers. + + +

+ +
cl_modint_ring x.ring () +
+Returns the ring to which the modular integer x belongs. + +
cl_MI operator+ (const cl_MI&, const cl_MI&) +
+Returns the sum of two modular integers. One of the arguments may also be +a plain integer. + +
cl_MI operator- (const cl_MI&, const cl_MI&) +
+Returns the difference of two modular integers. One of the arguments may also be +a plain integer. + +
cl_MI operator- (const cl_MI&) +
+Returns the negative of a modular integer. + +
cl_MI operator* (const cl_MI&, const cl_MI&) +
+Returns the product of two modular integers. One of the arguments may also be +a plain integer. + +
cl_MI square (const cl_MI&) +
+Returns the square of a modular integer. + +
cl_MI recip (const cl_MI& x) +
+Returns the reciprocal x^-1 of a modular integer x. x +must be coprime to the modulus, otherwise an error message is issued. + +
cl_MI div (const cl_MI& x, const cl_MI& y) +
+Returns the quotient x*y^-1 of two modular integers x, y. +y must be coprime to the modulus, otherwise an error message is issued. + +
cl_MI expt_pos (const cl_MI& x, const cl_I& y) +
+y must be > 0. Returns x^y. + +
cl_MI expt (const cl_MI& x, const cl_I& y) +
+Returns x^y. If y is negative, x must be coprime to the +modulus, else an error message is issued. + +
cl_MI operator<< (const cl_MI& x, const cl_I& y) +
+Returns x*2^y. + +
cl_MI operator>> (const cl_MI& x, const cl_I& y) +
+Returns x*2^-y. When y is positive, the modulus must be odd, +or an error message is issued. + +
bool operator== (const cl_MI&, const cl_MI&) +
+
bool operator!= (const cl_MI&, const cl_MI&) +
+Compares two modular integers, belonging to the same modular integer ring, +for equality. + +
cl_boolean zerop (const cl_MI& x) +
+Returns true if x is 0 mod N. +
+ +

+The following output functions are defined (see also the chapter on +input/output). + + +

+ +
void fprint (cl_ostream stream, const cl_MI& x) +
+
cl_ostream operator<< (cl_ostream stream, const cl_MI& x) +
+Prints the modular integer x on the stream. The output may depend +on the global printer settings in the variable cl_default_print_flags. +
+ + + +

8. Symbolic data types

+ +

+CLN implements two symbolic (non-numeric) data types: strings and symbols. + + + + +

8.1 Strings

+ +

+The class + + + +

+                      String
+                     cl_string
+                    <cl_string.h>
+
+ +

+implements immutable strings. + + +

+Strings are constructed through the following constructors: + + +

+ +
cl_string (const char * s) +
+Returns an immutable copy of the (zero-terminated) C string s. + +
cl_string (const char * ptr, unsigned long len) +
+Returns an immutable copy of the len characters at +ptr[0], ..., ptr[len-1]. NUL characters are allowed. +
+ +

+The following functions are available on strings: + + +

+ +
operator = +
+Assignment from cl_string and const char *. + +
s.length() +
+
strlen(s) +
+Returns the length of the string s. + +
s[i] +
+Returns the ith character of the string s. +i must be in the range 0 <= i < s.length(). + +
bool equal (const cl_string& s1, const cl_string& s2) +
+Compares two strings for equality. One of the arguments may also be a +plain const char *. +
+ + + +

8.2 Symbols

+ +

+Symbols are uniquified strings: all symbols with the same name are shared. +This means that comparison of two symbols is fast (effectively just a pointer +comparison), whereas comparison of two strings must in the worst case walk +both strings until their end. +Symbols are used, for example, as tags for properties, as names of variables +in polynomial rings, etc. + + +

+Symbols are constructed through the following constructor: + + +

+ +
cl_symbol (const cl_string& s) +
+Looks up or creates a new symbol with a given name. +
+ +

+The following operations are available on symbols: + + +

+ +
cl_string (const cl_symbol& sym) +
+Conversion to cl_string: Returns the string which names the symbol +sym. + +
bool equal (const cl_symbol& sym1, const cl_symbol& sym2) +
+Compares two symbols for equality. This is very fast. +
+ + + +

9. Univariate polynomials

+ + + +

9.1 Univariate polynomial rings

+ +

+CLN implements univariate polynomials (polynomials in one variable) over an +arbitrary ring. The indeterminate variable may be either unnamed (and will be +printed according to cl_default_print_flags.univpoly_varname, which +defaults to `x') or carry a given name. The base ring and the +indeterminate are explicitly part of every polynomial. CLN doesn't allow you to +(accidentally) mix elements of different polynomial rings, e.g. +(a^2+1) * (b^3-1) will result in a runtime error. (Ideally this should +return a multivariate polynomial, but they are not yet implemented in CLN.) + + +

+The classes of univariate polynomial rings are + + + +

+                           Ring
+                         cl_ring
+                        <cl_ring.h>
+                            |
+                            |
+                 Univariate polynomial ring
+                      cl_univpoly_ring
+                      <cl_univpoly.h>
+                            |
+           +----------------+-------------------+
+           |                |                   |
+ Complex polynomial ring    |    Modular integer polynomial ring
+ cl_univpoly_complex_ring   |        cl_univpoly_modint_ring
+  <cl_univpoly_complex.h>   |        <cl_univpoly_modint.h>
+                            |
+           +----------------+
+           |                |
+   Real polynomial ring     |
+   cl_univpoly_real_ring    |
+    <cl_univpoly_real.h>    |
+                            |
+           +----------------+
+           |                |
+ Rational polynomial ring   |
+ cl_univpoly_rational_ring  |
+  <cl_univpoly_rational.h>  |
+                            |
+           +----------------+
+           |
+ Integer polynomial ring
+ cl_univpoly_integer_ring
+  <cl_univpoly_integer.h>
+
+ +

+and the corresponding classes of univariate polynomials are + + + +

+                   Univariate polynomial
+                          cl_UP
+                      <cl_univpoly.h>
+                            |
+           +----------------+-------------------+
+           |                |                   |
+   Complex polynomial       |      Modular integer polynomial
+        cl_UP_N             |                cl_UP_MI
+  <cl_univpoly_complex.h>   |        <cl_univpoly_modint.h>
+                            |
+           +----------------+
+           |                |
+     Real polynomial        |
+        cl_UP_R             |
+    <cl_univpoly_real.h>    |
+                            |
+           +----------------+
+           |                |
+   Rational polynomial      |
+        cl_UP_RA            |
+  <cl_univpoly_rational.h>  |
+                            |
+           +----------------+
+           |
+   Integer polynomial
+        cl_UP_I
+  <cl_univpoly_integer.h>
+
+ +

+Univariate polynomial rings are constructed using the functions + + +

+ +
cl_univpoly_ring cl_find_univpoly_ring (const cl_ring& R) +
+
cl_univpoly_ring cl_find_univpoly_ring (const cl_ring& R, const cl_symbol& varname) +
+This function returns the polynomial ring `R[X]', unnamed or named. +R may be an arbitrary ring. This function takes care of finding out +about special cases of R, such as the rings of complex numbers, +real numbers, rational numbers, integers, or modular integer rings. +There is a cache table of rings, indexed by R and varname. +This ensures that two calls of this function with the same arguments will +return the same polynomial ring. + +
cl_univpoly_complex_ring cl_find_univpoly_ring (const cl_complex_ring& R) +
+
cl_univpoly_complex_ring cl_find_univpoly_ring (const cl_complex_ring& R, const cl_symbol& varname) +
+
cl_univpoly_real_ring cl_find_univpoly_ring (const cl_real_ring& R) +
+
cl_univpoly_real_ring cl_find_univpoly_ring (const cl_real_ring& R, const cl_symbol& varname) +
+
cl_univpoly_rational_ring cl_find_univpoly_ring (const cl_rational_ring& R) +
+
cl_univpoly_rational_ring cl_find_univpoly_ring (const cl_rational_ring& R, const cl_symbol& varname) +
+
cl_univpoly_integer_ring cl_find_univpoly_ring (const cl_integer_ring& R) +
+
cl_univpoly_integer_ring cl_find_univpoly_ring (const cl_integer_ring& R, const cl_symbol& varname) +
+
cl_univpoly_modint_ring cl_find_univpoly_ring (const cl_modint_ring& R) +
+
cl_univpoly_modint_ring cl_find_univpoly_ring (const cl_modint_ring& R, const cl_symbol& varname) +
+These functions are equivalent to the general cl_find_univpoly_ring, +only the return type is more specific, according to the base ring's type. +
+ + + +

9.2 Functions on univariate polynomials

+ +

+Given a univariate polynomial ring R, the following members can be used. + + +

+ +
cl_ring R->basering() +
+This returns the base ring, as passed to `cl_find_univpoly_ring'. + +
cl_UP R->zero() +
+This returns 0 in R, a polynomial of degree -1. + +
cl_UP R->one() +
+This returns 1 in R, a polynomial of degree <= 0. + +
cl_UP R->canonhom (const cl_I& x) +
+This returns x in R, a polynomial of degree <= 0. + +
cl_UP R->monomial (const cl_ring_element& x, uintL e) +
+This returns a sparse polynomial: x * X^e, where X is the +indeterminate. + +
cl_UP R->create (sintL degree) +
+Creates a new polynomial with a given degree. The zero polynomial has degree +-1. After creating the polynomial, you should put in the coefficients, +using the set_coeff member function, and then call the finalize +member function. +
+ +

+The following are the only destructive operations on univariate polynomials. + + +

+ +
void set_coeff (cl_UP& x, uintL index, const cl_ring_element& y) +
+This changes the coefficient of X^index in x to be y. +After changing a polynomial and before applying any "normal" operation on it, +you should call its finalize member function. + +
void finalize (cl_UP& x) +
+This function marks the endpoint of destructive modifications of a polynomial. +It normalizes the internal representation so that subsequent computations have +less overhead. Doing normal computations on unnormalized polynomials may +produce wrong results or crash the program. +
+ +

+The following operations are defined on univariate polynomials. + + +

+ +
cl_univpoly_ring x.ring () +
+Returns the ring to which the univariate polynomial x belongs. + +
cl_UP operator+ (const cl_UP&, const cl_UP&) +
+Returns the sum of two univariate polynomials. + +
cl_UP operator- (const cl_UP&, const cl_UP&) +
+Returns the difference of two univariate polynomials. + +
cl_UP operator- (const cl_UP&) +
+Returns the negative of a univariate polynomial. + +
cl_UP operator* (const cl_UP&, const cl_UP&) +
+Returns the product of two univariate polynomials. One of the arguments may +also be a plain integer or an element of the base ring. + +
cl_UP square (const cl_UP&) +
+Returns the square of a univariate polynomial. + +
cl_UP expt_pos (const cl_UP& x, const cl_I& y) +
+y must be > 0. Returns x^y. + +
bool operator== (const cl_UP&, const cl_UP&) +
+
bool operator!= (const cl_UP&, const cl_UP&) +
+Compares two univariate polynomials, belonging to the same univariate +polynomial ring, for equality. + +
cl_boolean zerop (const cl_UP& x) +
+Returns true if x is 0 in R. + +
sintL degree (const cl_UP& x) +
+Returns the degree of the polynomial. The zero polynomial has degree -1. + +
cl_ring_element coeff (const cl_UP& x, uintL index) +
+Returns the coefficient of X^index in the polynomial x. + +
cl_ring_element x (const cl_ring_element& y) +
+Evaluation: If x is a polynomial and y belongs to the base ring, +then `x(y)' returns the value of the substitution of y into +x. + +
cl_UP deriv (const cl_UP& x) +
+Returns the derivative of the polynomial x with respect to the +indeterminate X. +
+ +

+The following output functions are defined (see also the chapter on +input/output). + + +

+ +
void fprint (cl_ostream stream, const cl_UP& x) +
+
cl_ostream operator<< (cl_ostream stream, const cl_UP& x) +
+Prints the univariate polynomial x on the stream. The output may +depend on the global printer settings in the variable +cl_default_print_flags. +
+ + + +

9.3 Special polynomials

+ +

+The following functions return special polynomials. + + +

+ +
cl_UP_I cl_tschebychev (sintL n) +
+Returns the n-th Tchebychev polynomial (n >= 0). + +
cl_UP_I cl_hermite (sintL n) +
+Returns the n-th Hermite polynomial (n >= 0). + +
cl_UP_RA cl_legendre (sintL n) +
+Returns the n-th Legendre polynomial (n >= 0). + +
cl_UP_I cl_laguerre (sintL n) +
+Returns the n-th Laguerre polynomial (n >= 0). +
+ +

+Information how to derive the differential equation satisfied by each +of these polynomials from their definition can be found in the +doc/polynomial/ directory. + + + + +

10. Internals

+ + + +

10.1 Why C++ ?

+ +

+Using C++ as an implementation language provides + + + +

    +
  • + +Efficiency: It compiles to machine code. + +
  • + +Portability: It runs on all platforms supporting a C++ compiler. Because +of the availability of GNU C++, this includes all currently used 32-bit and +64-bit platforms, independently of the quality of the vendor's C++ compiler. + +
  • + +Type safety: The C++ compilers knows about the number types and complains if, +for example, you try to assign a float to an integer variable. However, +a drawback is that C++ doesn't know about generic types, hence a restriction +like that operation+ (const cl_MI&, const cl_MI&) requires that both +arguments belong to the same modular ring cannot be expressed as a compile-time +information. + +
  • + +Algebraic syntax: The elementary operations +, -, *, +=, ==, ... can be used in infix notation, which is more +convenient than Lisp notation `(+ x y)' or C notation `add(x,y,&z)'. +
+ +

+With these language features, there is no need for two separate languages, +one for the implementation of the library and one in which the library's users +can program. This means that a prototype implementation of an algorithm +can be integrated into the library immediately after it has been tested and +debugged. No need to rewrite it in a low-level language after having prototyped +in a high-level language. + + + + +

10.2 Memory efficiency

+ +

+In order to save memory allocations, CLN implements: + + + +

    +
  • + +Object sharing: An operation like x+0 returns x without copying +it. +
  • + +Garbage collection: A reference counting mechanism makes sure that any +number object's storage is freed immediately when the last reference to the +object is gone. +
  • + +Small integers are represented as immediate values instead of pointers +to heap allocated storage. This means that integers > -2^29, +< 2^29 don't consume heap memory, unless they were explicitly allocated +on the heap. +
+ + + +

10.3 Speed efficiency

+ +

+Speed efficiency is obtained by the combination of the following tricks +and algorithms: + + + +

    +
  • + +Small integers, being represented as immediate values, don't require +memory access, just a couple of instructions for each elementary operation. +
  • + +The kernel of CLN has been written in assembly language for some CPUs +(i386, m68k, sparc, mips, arm). +
  • + +On all CPUs, CLN uses the superefficient low-level routines from GNU +GMP version 2. +
  • + +For large numbers, CLN uses, instead of the standard O(N^2) +algorithm, the Karatsuba multiplication, which is an +O(N^1.6) +algorithm. +
  • + +For very large numbers (more than 12000 decimal digits), CLN uses +Schönhage-Strassen +multiplication, which is an asymptotically +optimal multiplication algorithm. +
  • + +These fast multiplication algorithms also give improvements in the speed +of division and radix conversion. +
+ + + +

10.4 Garbage collection

+ +

+All the number classes are reference count classes: They only contain a pointer +to an object in the heap. Upon construction, assignment and destruction of +number objects, only the objects' reference count are manipulated. + + +

+Memory occupied by number objects are automatically reclaimed as soon as +their reference count drops to zero. + + +

+For number rings, another strategy is implemented: There is a cache of, +for example, the modular integer rings. A modular integer ring is destroyed +only if its reference count dropped to zero and the cache is about to be +resized. The effect of this strategy is that recently used rings remain +cached, whereas undue memory consumption through cached rings is avoided. + + + + +

11. Using the library

+ +

+For the following discussion, we will assume that you have installed +the CLN source in $CLN_DIR and built it in $CLN_TARGETDIR. +For example, for me it's CLN_DIR="$HOME/cln" and +CLN_TARGETDIR="$HOME/cln/linuxelf". You might define these as +environment variables, or directly substitute the appropriate values. + + + + +

11.1 Compiler options

+ +

+Until you have installed CLN in a public place, the following options are +needed: + + +

+When you compile CLN application code, add the flags + +

+   -I$CLN_DIR/include -I$CLN_TARGETDIR/include
+
+ +

+to the C++ compiler's command line (make variable CFLAGS or CXXFLAGS). +When you link CLN application code to form an executable, add the flags + +

+   $CLN_TARGETDIR/src/libcln.a
+
+ +

+to the C/C++ compiler's command line (make variable LIBS). + + +

+If you did a make install, the include files are installed in a +public directory (normally /usr/local/include), hence you don't +need special flags for compiling. The library has been installed to a +public directory as well (normally /usr/local/lib), hence when +linking a CLN application it is sufficient to give the flag -lcln. + + + + +

11.2 Include files

+ +

+Here is a summary of the include files and their contents. + + +

+ +
<cl_object.h> +
+General definitions, reference counting, garbage collection. +
<cl_number.h> +
+The class cl_number. +
<cl_complex.h> +
+Functions for class cl_N, the complex numbers. +
<cl_real.h> +
+Functions for class cl_R, the real numbers. +
<cl_float.h> +
+Functions for class cl_F, the floats. +
<cl_sfloat.h> +
+Functions for class cl_SF, the short-floats. +
<cl_ffloat.h> +
+Functions for class cl_FF, the single-floats. +
<cl_dfloat.h> +
+Functions for class cl_DF, the double-floats. +
<cl_lfloat.h> +
+Functions for class cl_LF, the long-floats. +
<cl_rational.h> +
+Functions for class cl_RA, the rational numbers. +
<cl_integer.h> +
+Functions for class cl_I, the integers. +
<cl_io.h> +
+Input/Output. +
<cl_complex_io.h> +
+Input/Output for class cl_N, the complex numbers. +
<cl_real_io.h> +
+Input/Output for class cl_R, the real numbers. +
<cl_float_io.h> +
+Input/Output for class cl_F, the floats. +
<cl_sfloat_io.h> +
+Input/Output for class cl_SF, the short-floats. +
<cl_ffloat_io.h> +
+Input/Output for class cl_FF, the single-floats. +
<cl_dfloat_io.h> +
+Input/Output for class cl_DF, the double-floats. +
<cl_lfloat_io.h> +
+Input/Output for class cl_LF, the long-floats. +
<cl_rational_io.h> +
+Input/Output for class cl_RA, the rational numbers. +
<cl_integer_io.h> +
+Input/Output for class cl_I, the integers. +
<cl_input.h> +
+Flags for customizing input operations. +
<cl_output.h> +
+Flags for customizing output operations. +
<cl_malloc.h> +
+cl_malloc_hook, cl_free_hook. +
<cl_abort.h> +
+cl_abort. +
<cl_condition.h> +
+Conditions/exceptions. +
<cl_string.h> +
+Strings. +
<cl_symbol.h> +
+Symbols. +
<cl_proplist.h> +
+Property lists. +
<cl_ring.h> +
+General rings. +
<cl_null_ring.h> +
+The null ring. +
<cl_complex_ring.h> +
+The ring of complex numbers. +
<cl_real_ring.h> +
+The ring of real numbers. +
<cl_rational_ring.h> +
+The ring of rational numbers. +
<cl_integer_ring.h> +
+The ring of integers. +
<cl_numtheory.h> +
+Number threory functions. +
<cl_modinteger.h> +
+Modular integers. +
<cl_V.h> +
+Vectors. +
<cl_GV.h> +
+General vectors. +
<cl_GV_number.h> +
+General vectors over cl_number. +
<cl_GV_complex.h> +
+General vectors over cl_N. +
<cl_GV_real.h> +
+General vectors over cl_R. +
<cl_GV_rational.h> +
+General vectors over cl_RA. +
<cl_GV_integer.h> +
+General vectors over cl_I. +
<cl_GV_modinteger.h> +
+General vectors of modular integers. +
<cl_SV.h> +
+Simple vectors. +
<cl_SV_number.h> +
+Simple vectors over cl_number. +
<cl_SV_complex.h> +
+Simple vectors over cl_N. +
<cl_SV_real.h> +
+Simple vectors over cl_R. +
<cl_SV_rational.h> +
+Simple vectors over cl_RA. +
<cl_SV_integer.h> +
+Simple vectors over cl_I. +
<cl_SV_ringelt.h> +
+Simple vectors of general ring elements. +
<cl_univpoly.h> +
+Univariate polynomials. +
<cl_univpoly_integer.h> +
+Univariate polynomials over the integers. +
<cl_univpoly_rational.h> +
+Univariate polynomials over the rational numbers. +
<cl_univpoly_real.h> +
+Univariate polynomials over the real numbers. +
<cl_univpoly_complex.h> +
+Univariate polynomials over the complex numbers. +
<cl_univpoly_modint.h> +
+Univariate polynomials over modular integer rings. +
<cl_timing.h> +
+Timing facilities. +
<cln.h> +
+Includes all of the above. +
+ + + +

11.3 An Example

+ +

+A function which computes the nth Fibonacci number can be written as follows. + + + +

+#include <cl_integer.h>
+#include <cl_real.h>
+
+// Returns F_n, computed as the nearest integer to
+// ((1+sqrt(5))/2)^n/sqrt(5). Assume n>=0.
+const cl_I fibonacci (int n)
+{
+        // Need a precision of ((1+sqrt(5))/2)^-n.
+        cl_float_format_t prec = cl_float_format((int)(0.208987641*n+5));
+        cl_R sqrt5 = sqrt(cl_float(5,prec));
+        cl_R phi = (1+sqrt5)/2;
+        return round1( expt(phi,n)/sqrt5 );
+}
+
+ +

+Let's explain what is going on in detail. + + +

+The include file <cl_integer.h> is necessary because the type +cl_I is used in the function, and the include file <cl_real.h> +is needed for the type cl_R and the floating point number functions. +The order of the include files does not matter. + + +

+Then comes the function declaration. The argument is an int, the +result an integer. The return type is defined as `const cl_I', not +simply `cl_I', because that allows the compiler to detect typos like +`fibonacci(n) = 100'. It would be possible to declare the return +type as const cl_R (real number) or even const cl_N (complex +number). We use the most specialized possible return type because functions +which call `fibonacci' will be able to profit from the compiler's type +analysis: Adding two integers is slightly more efficient than adding the +same objects declared as complex numbers, because it needs less type +dispatch. Also, when linking to CLN as a non-shared library, this minimizes +the size of the resulting executable program. + + +

+The result will be computed as expt(phi,n)/sqrt(5), rounded to the nearest +integer. In order to get a correct result, the absolute error should be less +than 1/2, i.e. the relative error should be less than sqrt(5)/(2*expt(phi,n)). +To this end, the first line computes a floating point precision for sqrt(5) +and phi. + + +

+Then sqrt(5) is computed by first converting the integer 5 to a floating point +number and than taking the square root. The converse, first taking the square +root of 5, and then converting to the desired precision, would not work in +CLN: The square root would be computed to a default precision (normally +single-float precision), and the following conversion could not help about +the lacking accuracy. This is because CLN is not a symbolic computer algebra +system and does not represent sqrt(5) in a non-numeric way. + + +

+The type cl_R for sqrt5 and, in the following line, phi is the only +possible choice. You cannot write cl_F because the C++ compiler can +only infer that cl_float(5,prec) is a real number. You cannot write +cl_N because a `round1' does not exist for general complex +numbers. + + +

+When the function returns, all the local variables in the function are +automatically reclaimed (garbage collected). Only the result survives and +gets passed to the caller. + + + + +

11.4 Debugging support

+ +

+When debugging a CLN application with GNU gdb, two facilities are +available from the library: + + + +

    +
  • The library does type checks, range checks, consistency checks at + +many places. When one of these fails, the function cl_abort() is +called. Its default implementation is to perform an exit(1), so +you won't have a core dump. But for debugging, it is best to set a +breakpoint at this function: + +
    +(gdb) break cl_abort
    +
    + +When this breakpoint is hit, look at the stack's backtrace: + +
    +(gdb) where
    +
    + +
  • The debugger's normal print command doesn't know about + +CLN's types and therefore prints mostly useless hexadecimal addresses. +CLN offers a function cl_print, callable from the debugger, +for printing number objects. In order to get this function, you have +to define the macro `CL_DEBUG' and then include all the header files +for which you want cl_print debugging support. For example: + +
    +#define CL_DEBUG
    +#include <cl_string.h>
    +
    + +Now, if you have in your program a variable cl_string s, and +inspect it under gdb, the output may look like this: + +
    +(gdb) print s
    +$7 = {<cl_gcpointer> = { = {pointer = 0x8055b60, heappointer = 0x8055b60,
    +  word = 134568800}}, }
    +(gdb) call cl_print(s)
    +(cl_string) ""
    +$8 = 134568800
    +
    + +Note that the output of cl_print goes to the program's error output, +not to gdb's standard output. + +Note, however, that the above facility does not work with all CLN types, +only with number objects and similar. Therefore CLN offers a member function +debug_print() on all CLN types. The same macro `CL_DEBUG' +is needed for this member function to be implemented. Under gdb, +you call it like this: + +
    +(gdb) print s
    +$7 = {<cl_gcpointer> = { = {pointer = 0x8055b60, heappointer = 0x8055b60,
    +  word = 134568800}}, }
    +(gdb) call s.debug_print()
    +(cl_string) ""
    +(gdb) define cprint
    +>call ($1).debug_print()
    +>end
    +(gdb) cprint s
    +(cl_string) ""
    +
    + +Unfortunately, this feature does not seem to work under all circumstances. +
+ + + +

12. Customizing

+ + + +

12.1 Error handling

+ +

+When a fatal error occurs, an error message is output to the standard error +output stream, and the function cl_abort is called. The default +version of this function (provided in the library) terminates the application. +To catch such a fatal error, you need to define the function cl_abort +yourself, with the prototype + +

+#include <cl_abort.h>
+void cl_abort (void);
+
+ +

+This function must not return control to its caller. + + + + +

12.2 Floating-point underflow

+ +

+Floating point underflow denotes the situation when a floating-point number +is to be created which is so close to 0 that its exponent is too +low to be represented internally. By default, this causes a fatal error. +If you set the global variable + +

+cl_boolean cl_inhibit_floating_point_underflow
+
+ +

+to cl_true, the error will be inhibited, and a floating-point zero +will be generated instead. +The default value of cl_inhibit_floating_point_underflow is +cl_false. + + + + +

12.3 Customizing I/O

+ +

+The output of the function fprint may be customized by changing the +value of the global variable cl_default_print_flags. + + + + +

12.4 Customizing the memory allocator

+ +

+Every memory allocation of CLN is done through the function pointer +cl_malloc_hook. Freeing of this memory is done through the function +pointer cl_free_hook. The default versions of these functions, +provided in the library, call malloc and free and check +the malloc result against NULL. +If you want to provide another memory allocator, you need to define +the variables cl_malloc_hook and cl_free_hook yourself, +like this: + +

+#include <cl_malloc.h>
+void* (*cl_malloc_hook) (size_t size) = ...;
+void (*cl_free_hook) (void* ptr)      = ...;
+
+ +

+The cl_malloc_hook function must not return a NULL pointer. + + +

+It is not possible to change the memory allocator at runtime, because +it is already called at program startup by the constructors of some +global variables. + + + + +

Index

+ +

+Jump to: +

+ + +


+This document was generated on 14 January 2000 using +texi2html 1.56k. + + diff --git a/doc/cln.info b/doc/cln.info new file mode 100644 index 0000000..2b72212 --- /dev/null +++ b/doc/cln.info @@ -0,0 +1,3355 @@ +This is Info file cln.info, produced by Makeinfo version 1.68 from the +input file cln.texi. + +This file documents CLN, a Class Library for Numbers. + +Published by Bruno Haible, `' and Richard +Kreckel, `'. + +Copyright (C) Bruno Haible 1995, 1996, 1997, 1998, 1999, 2000. + +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 author. + + +File: cln.info, Node: Top, Next: Introduction, Prev: (dir), Up: (dir) + +* Menu: + +* Introduction:: +* Installation:: +* Ordinary number types:: +* Functions on numbers:: +* Input/Output:: +* Rings:: +* Modular integers:: +* Symbolic data types:: +* Univariate polynomials:: +* Internals:: +* Using the library:: +* Customizing:: +* Index:: + + -- The Detailed Node Listing -- + +Installation + +* Prerequisites:: +* Building the library:: +* Installing the library:: +* Cleaning up:: + +Prerequisites + +* C++ compiler:: +* Make utility:: +* Sed utility:: + +Ordinary number types + +* Exact numbers:: +* Floating-point numbers:: +* Complex numbers:: +* Conversions:: + +Functions on numbers + +* Constructing numbers:: +* Elementary functions:: +* Elementary rational functions:: +* Elementary complex functions:: +* Comparisons:: +* Rounding functions:: +* Roots:: +* Transcendental functions:: +* Functions on integers:: +* Functions on floating-point numbers:: +* Conversion functions:: +* Random number generators:: +* Obfuscating operators:: + +Constructing numbers + +* Constructing integers:: +* Constructing rational numbers:: +* Constructing floating-point numbers:: +* Constructing complex numbers:: + +Transcendental functions + +* Exponential and logarithmic functions:: +* Trigonometric functions:: +* Hyperbolic functions:: +* Euler gamma:: +* Riemann zeta:: + +Functions on integers + +* Logical functions:: +* Number theoretic functions:: +* Combinatorial functions:: + +Conversion functions + +* Conversion to floating-point numbers:: +* Conversion to rational numbers:: + +Input/Output + +* Internal and printed representation:: +* Input functions:: +* Output functions:: + +Modular integers + +* Modular integer rings:: +* Functions on modular integers:: + +Symbolic data types + +* Strings:: +* Symbols:: + +Univariate polynomials + +* Univariate polynomial rings:: +* Functions on univariate polynomials:: +* Special polynomials:: + +Internals + +* Why C++ ?:: +* Memory efficiency:: +* Speed efficiency:: +* Garbage collection:: + +Using the library + +* Compiler options:: +* Include files:: +* An Example:: +* Debugging support:: + +Customizing + +* Error handling:: +* Floating-point underflow:: +* Customizing I/O:: +* Customizing the memory allocator:: + + +File: cln.info, Node: Introduction, Next: Installation, Prev: Top, Up: Top + +Introduction +************ + +CLN is a library for computations with all kinds of numbers. It has a +rich set of number classes: + + * Integers (with unlimited precision), + + * Rational numbers, + + * Floating-point numbers: + + - Short float, + + - Single float, + + - Double float, + + - Long float (with unlimited precision), + + * Complex numbers, + + * Modular integers (integers modulo a fixed integer), + + * Univariate polynomials. + +The subtypes of the complex numbers among these are exactly the types +of numbers known to the Common Lisp language. Therefore `CLN' can be +used for Common Lisp implementations, giving `CLN' another meaning: it +becomes an abbreviation of "Common Lisp Numbers". + +The CLN package implements + + * Elementary functions (`+', `-', `*', `/', `sqrt', comparisons, + ...), + + * Logical functions (logical `and', `or', `not', ...), + + * Transcendental functions (exponential, logarithmic, trigonometric, + hyperbolic functions and their inverse functions). + +CLN is a C++ library. Using C++ as an implementation language provides + + * efficiency: it compiles to machine code, + + * type safety: the C++ compiler knows about the number types and + complains if, for example, you try to assign a float to an integer + variable. + + * algebraic syntax: You can use the `+', `-', `*', `=', `==', ... + operators as in C or C++. + +CLN is memory efficient: + + * Small integers and short floats are immediate, not heap allocated. + + * Heap-allocated memory is reclaimed through an automatic, + non-interruptive garbage collection. + +CLN is speed efficient: + + * The kernel of CLN has been written in assembly language for some + CPUs (`i386', `m68k', `sparc', `mips', `arm'). + + * On all CPUs, CLN uses the superefficient low-level routines from + GNU GMP version 2. + + * It uses Karatsuba multiplication, which is significantly faster + for large numbers than the standard multiplication algorithm. + + * For very large numbers (more than 12000 decimal digits), it uses + Schönhage-Strassen multiplication, which is an asymptotically + optimal multiplication algorithm, for multiplication, division and + radix conversion. + +CLN aims at being easily integrated into larger software packages: + + * The garbage collection imposes no burden on the main application. + + * The library provides hooks for memory allocation and exceptions. + + +File: cln.info, Node: Installation, Next: Ordinary number types, Prev: Introduction, Up: Top + +Installation +************ + +This section describes how to install the CLN package on your system. + +* Menu: + +* Prerequisites:: +* Building the library:: +* Installing the library:: +* Cleaning up:: + + +File: cln.info, Node: Prerequisites, Next: Building the library, Prev: Installation, Up: Installation + +Prerequisites +============= + +* Menu: + +* C++ compiler:: +* Make utility:: +* Sed utility:: + + +File: cln.info, Node: C++ compiler, Next: Make utility, Prev: Prerequisites, Up: Prerequisites + +C++ compiler +------------ + +To build CLN, you need a C++ compiler. Actually, you need GNU `g++ +2.7.0' or newer. On HPPA, you need GNU `g++ 2.8.0' or newer. I +recommend GNU `egcs 1.1' or newer. + +The following C++ features are used: classes, member functions, +overloading of functions and operators, constructors and destructors, +inline, const, multiple inheritance, templates. + +The following C++ features are not used: `new', `delete', virtual +inheritance, exceptions. + +CLN relies on semi-automatic ordering of initializations of static and +global variables, a feature which I could implement for GNU g++ only. + + +File: cln.info, Node: Make utility, Next: Sed utility, Prev: C++ compiler, Up: Prerequisites + +Make utility +------------ + +To build CLN, you also need to have GNU `make' installed. + + +File: cln.info, Node: Sed utility, Prev: Make utility, Up: Prerequisites + +Sed utility +----------- + +To build CLN on HP-UX, you also need to have GNU `sed' installed. This +is because the libtool script, which creates the CLN library, relies on +`sed', and the vendor's `sed' utility on these systems is too limited. + + +File: cln.info, Node: Building the library, Next: Installing the library, Prev: Prerequisites, Up: Installation + +Building the library +==================== + +As with any autoconfiguring GNU software, installation is as easy as +this: + + $ ./configure + $ make + $ make check + +If on your system, `make' is not GNU `make', you have to use `gmake' +instead of `make' above. + +The `configure' command checks out some features of your system and C++ +compiler and builds the `Makefile's. The `make' command builds the +library. This step may take 4 hours on an average workstation. The +`make check' runs some test to check that no important subroutine has +been miscompiled. + +The `configure' command accepts options. To get a summary of them, try + + $ ./configure --help + +Some of the options are explained in detail in the `INSTALL.generic' +file. + +You can specify the C compiler, the C++ compiler and their options +through the following environment variables when running `configure': + +`CC' + Specifies the C compiler. + +`CFLAGS' + Flags to be given to the C compiler when compiling programs (not + when linking). + +`CXX' + Specifies the C++ compiler. + +`CXXFLAGS' + Flags to be given to the C++ compiler when compiling programs (not + when linking). + +Examples: + + $ CC="gcc" CFLAGS="-O" CXX="g++" CXXFLAGS="-O" ./configure + $ CC="gcc -V 2.7.2" CFLAGS="-O -g" \ + CXX="g++ -V 2.7.2" CXXFLAGS="-O -g" ./configure + $ CC="gcc -V 2.8.1" CFLAGS="-O -fno-exceptions" \ + CXX="g++ -V 2.8.1" CXXFLAGS="-O -fno-exceptions" ./configure + $ CC="gcc -V egcs-2.91.60" CFLAGS="-O2 -fno-exceptions" \ + CXX="g++ -V egcs-2.91.60" CFLAGS="-O2 -fno-exceptions" ./configure + +Note that for these environment variables to take effect, you have to +set them (assuming a Bourne-compatible shell) on the same line as the +`configure' command. If you made the settings in earlier shell +commands, you have to `export' the environment variables before calling +`configure'. In a `csh' shell, you have to use the `setenv' command for +setting each of the environment variables. + +On Linux, `g++' needs 15 MB to compile the tests. So you should better +have 17 MB swap space and 1 MB room in $TMPDIR. + +If you use `g++' version 2.7.x, don't add `-O2' to the CXXFLAGS, +because `g++ -O' generates better code for CLN than `g++ -O2'. + +If you use `g++' version 2.8.x or egcs-2.91.x (a.k.a. egcs-1.1) or +gcc-2.95.x, I recommend adding `-fno-exceptions' to the CXXFLAGS. This +will likely generate better code. + +If you use `g++' version egcs-2.91.x (egcs-1.1) or gcc-2.95.x on Sparc, +add either `-O' or `-O2 -fno-schedule-insns' to the CXXFLAGS. With +full `-O2', `g++' miscompiles the division routines. Also, for +-enable-shared to work, you need egcs-1.1.2 or newer. + +On MIPS (SGI Irix 6), pass option `--without-gmp' to configure. gmp does +not work when compiled in `n32' binary format on Irix. + +By default, only a static library is built. You can build CLN as a +shared library too, by calling `configure' with the option +`--enable-shared'. To get it built as a shared library only, call +`configure' with the options `--enable-shared --disable-static'. + +If you use `g++' version egcs-2.91.x (egcs-1.1) on Sparc, you cannot +use `--enable-shared' because `g++' would miscompile parts of the +library. + + +File: cln.info, Node: Installing the library, Next: Cleaning up, Prev: Building the library, Up: Installation + +Installing the library +====================== + +As with any autoconfiguring GNU software, installation is as easy as +this: + + $ make install + +The `make install' command installs the library and the include files +into public places (`/usr/local/lib/' and `/usr/local/include/', if you +haven't specified a `--prefix' option to `configure'). This step may +require superuser privileges. + +If you have already built the library and wish to install it, but didn't +specify `--prefix=...' at configure time, just re-run `configure', +giving it the same options as the first time, plus the `--prefix=...' +option. + + +File: cln.info, Node: Cleaning up, Prev: Installing the library, Up: Installation + +Cleaning up +=========== + +You can remove system-dependent files generated by `make' through + + $ make clean + +You can remove all files generated by `make', thus reverting to a +virgin distribution of CLN, through + + $ make distclean + + +File: cln.info, Node: Ordinary number types, Next: Functions on numbers, Prev: Installation, Up: Top + +Ordinary number types +********************* + +CLN implements the following class hierarchy: + + Number + cl_number + + | + | + Real or complex number + cl_N + + | + | + Real number + cl_R + + | + +-------------------+-------------------+ + | | + Rational number Floating-point number + cl_RA cl_F + + | | + | +-------------+-------------+-------------+ + Integer | | | | + cl_I Short-Float Single-Float Double-Float Long-Float + cl_SF cl_FF cl_DF cl_LF + + +The base class `cl_number' is an abstract base class. It is not useful +to declare a variable of this type except if you want to completely +disable compile-time type checking and use run-time type checking +instead. + +The class `cl_N' comprises real and complex numbers. There is no +special class for complex numbers since complex numbers with imaginary +part `0' are automatically converted to real numbers. + +The class `cl_R' comprises real numbers of different kinds. It is an +abstract class. + +The class `cl_RA' comprises exact real numbers: rational numbers, +including integers. There is no special class for non-integral rational +numbers since rational numbers with denominator `1' are automatically +converted to integers. + +The class `cl_F' implements floating-point approximations to real +numbers. It is an abstract class. + +* Menu: + +* Exact numbers:: +* Floating-point numbers:: +* Complex numbers:: +* Conversions:: + + +File: cln.info, Node: Exact numbers, Next: Floating-point numbers, Prev: Ordinary number types, Up: Ordinary number types + +Exact numbers +============= + +Some numbers are represented as exact numbers: there is no loss of +information when such a number is converted from its mathematical value +to its internal representation. On exact numbers, the elementary +operations (`+', `-', `*', `/', comparisons, ...) compute the completely +correct result. + +In CLN, the exact numbers are: + + * rational numbers (including integers), + + * complex numbers whose real and imaginary parts are both rational + numbers. + +Rational numbers are always normalized to the form +`NUMERATOR/DENOMINATOR' where the numerator and denominator are coprime +integers and the denominator is positive. If the resulting denominator +is `1', the rational number is converted to an integer. + +Small integers (typically in the range `-2^30'...`2^30-1', for 32-bit +machines) are especially efficient, because they consume no heap +allocation. Otherwise the distinction between these immediate integers +(called "fixnums") and heap allocated integers (called "bignums") is +completely transparent. + + +File: cln.info, Node: Floating-point numbers, Next: Complex numbers, Prev: Exact numbers, Up: Ordinary number types + +Floating-point numbers +====================== + +Not all real numbers can be represented exactly. (There is an easy +mathematical proof for this: Only a countable set of numbers can be +stored exactly in a computer, even if one assumes that it has unlimited +storage. But there are uncountably many real numbers.) So some +approximation is needed. CLN implements ordinary floating-point +numbers, with mantissa and exponent. + +The elementary operations (`+', `-', `*', `/', ...) only return +approximate results. For example, the value of the expression `(cl_F) +0.3 + (cl_F) 0.4' prints as `0.70000005', not as `0.7'. Rounding errors +like this one are inevitable when computing with floating-point numbers. + +Nevertheless, CLN rounds the floating-point results of the operations +`+', `-', `*', `/', `sqrt' according to the "round-to-even" rule: It +first computes the exact mathematical result and then returns the +floating-point number which is nearest to this. If two floating-point +numbers are equally distant from the ideal result, the one with a `0' +in its least significant mantissa bit is chosen. + +Similarly, testing floating point numbers for equality `x == y' is +gambling with random errors. Better check for `abs(x - y) < epsilon' +for some well-chosen `epsilon'. + +Floating point numbers come in four flavors: + + * Short floats, type `cl_SF'. They have 1 sign bit, 8 exponent bits + (including the exponent's sign), and 17 mantissa bits (including + the "hidden" bit). They don't consume heap allocation. + + * Single floats, type `cl_FF'. They have 1 sign bit, 8 exponent + bits (including the exponent's sign), and 24 mantissa bits + (including the "hidden" bit). In CLN, they are represented as + IEEE single-precision floating point numbers. This corresponds + closely to the C/C++ type `float'. + + * Double floats, type `cl_DF'. They have 1 sign bit, 11 exponent + bits (including the exponent's sign), and 53 mantissa bits + (including the "hidden" bit). In CLN, they are represented as + IEEE double-precision floating point numbers. This corresponds + closely to the C/C++ type `double'. + + * Long floats, type `cl_LF'. They have 1 sign bit, 32 exponent bits + (including the exponent's sign), and n mantissa bits (including + the "hidden" bit), where n >= 64. The precision of a long float + is unlimited, but once created, a long float has a fixed + precision. (No "lazy recomputation".) + +Of course, computations with long floats are more expensive than those +with smaller floating-point formats. + +CLN does not implement features like NaNs, denormalized numbers and +gradual underflow. If the exponent range of some floating-point type is +too limited for your application, choose another floating-point type +with larger exponent range. + +As a user of CLN, you can forget about the differences between the four +floating-point types and just declare all your floating-point variables +as being of type `cl_F'. This has the advantage that when you change +the precision of some computation (say, from `cl_DF' to `cl_LF'), you +don't have to change the code, only the precision of the initial +values. Also, many transcendental functions have been declared as +returning a `cl_F' when the argument is a `cl_F', but such declarations +are missing for the types `cl_SF', `cl_FF', `cl_DF', `cl_LF'. (Such +declarations would be wrong if the floating point contagion rule +happened to change in the future.) + + +File: cln.info, Node: Complex numbers, Next: Conversions, Prev: Floating-point numbers, Up: Ordinary number types + +Complex numbers +=============== + +Complex numbers, as implemented by the class `cl_N', have a real part +and an imaginary part, both real numbers. A complex number whose +imaginary part is the exact number `0' is automatically converted to a +real number. + +Complex numbers can arise from real numbers alone, for example through +application of `sqrt' or transcendental functions. + + +File: cln.info, Node: Conversions, Prev: Complex numbers, Up: Ordinary number types + +Conversions +=========== + +Conversions from any class to any its superclasses ("base classes" in +C++ terminology) is done automatically. + +Conversions from the C built-in types `long' and `unsigned long' are +provided for the classes `cl_I', `cl_RA', `cl_R', `cl_N' and +`cl_number'. + +Conversions from the C built-in types `int' and `unsigned int' are +provided for the classes `cl_I', `cl_RA', `cl_R', `cl_N' and +`cl_number'. However, these conversions emphasize efficiency. Their +range is therefore limited: + + - The conversion from `int' works only if the argument is < 2^29 and + > -2^29. + + - The conversion from `unsigned int' works only if the argument is < + 2^29. + +In a declaration like `cl_I x = 10;' the C++ compiler is able to do the +conversion of `10' from `int' to `cl_I' at compile time already. On the +other hand, code like `cl_I x = 1000000000;' is in error. So, if you +want to be sure that an `int' whose magnitude is not guaranteed to be < +2^29 is correctly converted to a `cl_I', first convert it to a `long'. +Similarly, if a large `unsigned int' is to be converted to a `cl_I', +first convert it to an `unsigned long'. + +Conversions from the C built-in type `float' are provided for the +classes `cl_FF', `cl_F', `cl_R', `cl_N' and `cl_number'. + +Conversions from the C built-in type `double' are provided for the +classes `cl_DF', `cl_F', `cl_R', `cl_N' and `cl_number'. + +Conversions from `const char *' are provided for the classes `cl_I', +`cl_RA', `cl_SF', `cl_FF', `cl_DF', `cl_LF', `cl_F', `cl_R', `cl_N'. +The easiest way to specify a value which is outside of the range of the +C++ built-in types is therefore to specify it as a string, like this: + cl_I order_of_rubiks_cube_group = "43252003274489856000"; +Note that this conversion is done at runtime, not at compile-time. + +Conversions from `cl_I' to the C built-in types `int', `unsigned int', +`long', `unsigned long' are provided through the functions + +`int cl_I_to_int (const cl_I& x)' +`unsigned int cl_I_to_uint (const cl_I& x)' +`long cl_I_to_long (const cl_I& x)' +`unsigned long cl_I_to_ulong (const cl_I& x)' + Returns `x' as element of the C type CTYPE. If `x' is not + representable in the range of CTYPE, a runtime error occurs. + +Conversions from the classes `cl_I', `cl_RA', `cl_SF', `cl_FF', +`cl_DF', `cl_LF', `cl_F' and `cl_R' to the C built-in types `float' and +`double' are provided through the functions + +`float cl_float_approx (const TYPE& x)' +`double cl_double_approx (const TYPE& x)' + Returns an approximation of `x' of C type CTYPE. If `abs(x)' is + too close to 0 (underflow), 0 is returned. If `abs(x)' is too + large (overflow), an IEEE infinity is returned. + +Conversions from any class to any of its subclasses ("derived classes" +in C++ terminology) are not provided. Instead, you can assert and check +that a value belongs to a certain subclass, and return it as element of +that class, using the `As' and `The' macros. `As(TYPE)(VALUE)' checks +that VALUE belongs to TYPE and returns it as such. `The(TYPE)(VALUE)' +assumes that VALUE belongs to TYPE and returns it as such. It is your +responsibility to ensure that this assumption is valid. Example: + + cl_I x = ...; + if (!(x >= 0)) abort(); + cl_I ten_x = The(cl_I)(expt(10,x)); // If x >= 0, 10^x is an integer. + // In general, it would be a rational number. + + +File: cln.info, Node: Functions on numbers, Next: Input/Output, Prev: Ordinary number types, Up: Top + +Functions on numbers +******************** + +Each of the number classes declares its mathematical operations in the +corresponding include file. For example, if your code operates with +objects of type `cl_I', it should `#include '. + +* Menu: + +* Constructing numbers:: +* Elementary functions:: +* Elementary rational functions:: +* Elementary complex functions:: +* Comparisons:: +* Rounding functions:: +* Roots:: +* Transcendental functions:: +* Functions on integers:: +* Functions on floating-point numbers:: +* Conversion functions:: +* Random number generators:: +* Obfuscating operators:: + + +File: cln.info, Node: Constructing numbers, Next: Elementary functions, Prev: Functions on numbers, Up: Functions on numbers + +Constructing numbers +==================== + +Here is how to create number objects "from nothing". + +* Menu: + +* Constructing integers:: +* Constructing rational numbers:: +* Constructing floating-point numbers:: +* Constructing complex numbers:: + + +File: cln.info, Node: Constructing integers, Next: Constructing rational numbers, Prev: Constructing numbers, Up: Constructing numbers + +Constructing integers +--------------------- + +`cl_I' objects are most easily constructed from C integers and from +strings. See *Note Conversions::. + + +File: cln.info, Node: Constructing rational numbers, Next: Constructing floating-point numbers, Prev: Constructing integers, Up: Constructing numbers + +Constructing rational numbers +----------------------------- + +`cl_RA' objects can be constructed from strings. The syntax for +rational numbers is described in *Note Internal and printed +representation::. Another standard way to produce a rational number is +through application of `operator /' or `recip' on integers. + + +File: cln.info, Node: Constructing floating-point numbers, Next: Constructing complex numbers, Prev: Constructing rational numbers, Up: Constructing numbers + +Constructing floating-point numbers +----------------------------------- + +`cl_F' objects with low precision are most easily constructed from C +`float' and `double'. See *Note Conversions::. + +To construct a `cl_F' with high precision, you can use the conversion +from `const char *', but you have to specify the desired precision +within the string. (See *Note Internal and printed representation::.) +Example: + cl_F e = "0.271828182845904523536028747135266249775724709369996e+1_40"; +will set `e' to the given value, with a precision of 40 decimal digits. + +The programmatic way to construct a `cl_F' with high precision is +through the `cl_float' conversion function, see *Note Conversion to +floating-point numbers::. For example, to compute `e' to 40 decimal +places, first construct 1.0 to 40 decimal places and then apply the +exponential function: + cl_float_format_t precision = cl_float_format(40); + cl_F e = exp(cl_float(1,precision)); + + +File: cln.info, Node: Constructing complex numbers, Prev: Constructing floating-point numbers, Up: Constructing numbers + +Constructing complex numbers +---------------------------- + +Non-real `cl_N' objects are normally constructed through the function + cl_N complex (const cl_R& realpart, const cl_R& imagpart) +See *Note Elementary complex functions::. + + +File: cln.info, Node: Elementary functions, Next: Elementary rational functions, Prev: Constructing numbers, Up: Functions on numbers + +Elementary functions +==================== + +Each of the classes `cl_N', `cl_R', `cl_RA', `cl_I', `cl_F', `cl_SF', +`cl_FF', `cl_DF', `cl_LF' defines the following operations: + +`TYPE operator + (const TYPE&, const TYPE&)' + Addition. + +`TYPE operator - (const TYPE&, const TYPE&)' + Subtraction. + +`TYPE operator - (const TYPE&)' + Returns the negative of the argument. + +`TYPE plus1 (const TYPE& x)' + Returns `x + 1'. + +`TYPE minus1 (const TYPE& x)' + Returns `x - 1'. + +`TYPE operator * (const TYPE&, const TYPE&)' + Multiplication. + +`TYPE square (const TYPE& x)' + Returns `x * x'. + +Each of the classes `cl_N', `cl_R', `cl_RA', `cl_F', `cl_SF', `cl_FF', +`cl_DF', `cl_LF' defines the following operations: + +`TYPE operator / (const TYPE&, const TYPE&)' + Division. + +`TYPE recip (const TYPE&)' + Returns the reciprocal of the argument. + +The class `cl_I' doesn't define a `/' operation because in the C/C++ +language this operator, applied to integral types, denotes the `floor' +or `truncate' operation (which one of these, is implementation +dependent). (*Note Rounding functions::) Instead, `cl_I' defines an +"exact quotient" function: + +`cl_I exquo (const cl_I& x, const cl_I& y)' + Checks that `y' divides `x', and returns the quotient `x'/`y'. + +The following exponentiation functions are defined: + +`cl_I expt_pos (const cl_I& x, const cl_I& y)' +`cl_RA expt_pos (const cl_RA& x, const cl_I& y)' + `y' must be > 0. Returns `x^y'. + +`cl_RA expt (const cl_RA& x, const cl_I& y)' +`cl_R expt (const cl_R& x, const cl_I& y)' +`cl_N expt (const cl_N& x, const cl_I& y)' + Returns `x^y'. + +Each of the classes `cl_R', `cl_RA', `cl_I', `cl_F', `cl_SF', `cl_FF', +`cl_DF', `cl_LF' defines the following operation: + +`TYPE abs (const TYPE& x)' + Returns the absolute value of `x'. This is `x' if `x >= 0', and + `-x' if `x <= 0'. + +The class `cl_N' implements this as follows: + +`cl_R abs (const cl_N x)' + Returns the absolute value of `x'. + +Each of the classes `cl_N', `cl_R', `cl_RA', `cl_I', `cl_F', `cl_SF', +`cl_FF', `cl_DF', `cl_LF' defines the following operation: + +`TYPE signum (const TYPE& x)' + Returns the sign of `x', in the same number format as `x'. This + is defined as `x / abs(x)' if `x' is non-zero, and `x' if `x' is + zero. If `x' is real, the value is either 0 or 1 or -1. + + +File: cln.info, Node: Elementary rational functions, Next: Elementary complex functions, Prev: Elementary functions, Up: Functions on numbers + +Elementary rational functions +============================= + +Each of the classes `cl_RA', `cl_I' defines the following operations: + +`cl_I numerator (const TYPE& x)' + Returns the numerator of `x'. + +`cl_I denominator (const TYPE& x)' + Returns the denominator of `x'. + +The numerator and denominator of a rational number are normalized in +such a way that they have no factor in common and the denominator is +positive. + + +File: cln.info, Node: Elementary complex functions, Next: Comparisons, Prev: Elementary rational functions, Up: Functions on numbers + +Elementary complex functions +============================ + +The class `cl_N' defines the following operation: + +`cl_N complex (const cl_R& a, const cl_R& b)' + Returns the complex number `a+bi', that is, the complex number with + real part `a' and imaginary part `b'. + +Each of the classes `cl_N', `cl_R' defines the following operations: + +`cl_R realpart (const TYPE& x)' + Returns the real part of `x'. + +`cl_R imagpart (const TYPE& x)' + Returns the imaginary part of `x'. + +`TYPE conjugate (const TYPE& x)' + Returns the complex conjugate of `x'. + +We have the relations + + `x = complex(realpart(x), imagpart(x))' + + `conjugate(x) = complex(realpart(x), -imagpart(x))' + + +File: cln.info, Node: Comparisons, Next: Rounding functions, Prev: Elementary complex functions, Up: Functions on numbers + +Comparisons +=========== + +Each of the classes `cl_N', `cl_R', `cl_RA', `cl_I', `cl_F', `cl_SF', +`cl_FF', `cl_DF', `cl_LF' defines the following operations: + +`bool operator == (const TYPE&, const TYPE&)' +`bool operator != (const TYPE&, const TYPE&)' + Comparison, as in C and C++. + +`uint32 cl_equal_hashcode (const TYPE&)' + Returns a 32-bit hash code that is the same for any two numbers + which are the same according to `=='. This hash code depends on + the number's value, not its type or precision. + +`cl_boolean zerop (const TYPE& x)' + Compare against zero: `x == 0' + +Each of the classes `cl_R', `cl_RA', `cl_I', `cl_F', `cl_SF', `cl_FF', +`cl_DF', `cl_LF' defines the following operations: + +`cl_signean cl_compare (const TYPE& x, const TYPE& y)' + Compares `x' and `y'. Returns +1 if `x'>`y', -1 if `x'<`y', 0 if + `x'=`y'. + +`bool operator <= (const TYPE&, const TYPE&)' +`bool operator < (const TYPE&, const TYPE&)' +`bool operator >= (const TYPE&, const TYPE&)' +`bool operator > (const TYPE&, const TYPE&)' + Comparison, as in C and C++. + +`cl_boolean minusp (const TYPE& x)' + Compare against zero: `x < 0' + +`cl_boolean plusp (const TYPE& x)' + Compare against zero: `x > 0' + +`TYPE max (const TYPE& x, const TYPE& y)' + Return the maximum of `x' and `y'. + +`TYPE min (const TYPE& x, const TYPE& y)' + Return the minimum of `x' and `y'. + +When a floating point number and a rational number are compared, the +float is first converted to a rational number using the function +`rational'. Since a floating point number actually represents an +interval of real numbers, the result might be surprising. For example, +`(cl_F)(cl_R)"1/3" == (cl_R)"1/3"' returns false because there is no +floating point number whose value is exactly `1/3'. + + +File: cln.info, Node: Rounding functions, Next: Roots, Prev: Comparisons, Up: Functions on numbers + +Rounding functions +================== + +When a real number is to be converted to an integer, there is no "best" +rounding. The desired rounding function depends on the application. +The Common Lisp and ISO Lisp standards offer four rounding functions: + +`floor(x)' + This is the largest integer <=`x'. + +`ceiling(x)' + This is the smallest integer >=`x'. + +`truncate(x)' + Among the integers between 0 and `x' (inclusive) the one nearest + to `x'. + +`round(x)' + The integer nearest to `x'. If `x' is exactly halfway between two + integers, choose the even one. + +These functions have different advantages: + +`floor' and `ceiling' are translation invariant: `floor(x+n) = floor(x) ++ n' and `ceiling(x+n) = ceiling(x) + n' for every `x' and every +integer `n'. + +On the other hand, `truncate' and `round' are symmetric: `truncate(-x) += -truncate(x)' and `round(-x) = -round(x)', and furthermore `round' is +unbiased: on the "average", it rounds down exactly as often as it +rounds up. + +The functions are related like this: + + `ceiling(m/n) = floor((m+n-1)/n) = floor((m-1)/n)+1' for rational + numbers `m/n' (`m', `n' integers, `n'>0), and + + `truncate(x) = sign(x) * floor(abs(x))' + +Each of the classes `cl_R', `cl_RA', `cl_F', `cl_SF', `cl_FF', `cl_DF', +`cl_LF' defines the following operations: + +`cl_I floor1 (const TYPE& x)' + Returns `floor(x)'. + +`cl_I ceiling1 (const TYPE& x)' + Returns `ceiling(x)'. + +`cl_I truncate1 (const TYPE& x)' + Returns `truncate(x)'. + +`cl_I round1 (const TYPE& x)' + Returns `round(x)'. + +Each of the classes `cl_R', `cl_RA', `cl_I', `cl_F', `cl_SF', `cl_FF', +`cl_DF', `cl_LF' defines the following operations: + +`cl_I floor1 (const TYPE& x, const TYPE& y)' + Returns `floor(x/y)'. + +`cl_I ceiling1 (const TYPE& x, const TYPE& y)' + Returns `ceiling(x/y)'. + +`cl_I truncate1 (const TYPE& x, const TYPE& y)' + Returns `truncate(x/y)'. + +`cl_I round1 (const TYPE& x, const TYPE& y)' + Returns `round(x/y)'. + +These functions are called `floor1', ... here instead of `floor', ..., +because on some systems, system dependent include files define `floor' +and `ceiling' as macros. + +In many cases, one needs both the quotient and the remainder of a +division. It is more efficient to compute both at the same time than +to perform two divisions, one for quotient and the next one for the +remainder. The following functions therefore return a structure +containing both the quotient and the remainder. The suffix `2' +indicates the number of "return values". The remainder is defined as +follows: + + * for the computation of `quotient = floor(x)', `remainder = x - + quotient', + + * for the computation of `quotient = floor(x,y)', `remainder = x - + quotient*y', + +and similarly for the other three operations. + +Each of the classes `cl_R', `cl_RA', `cl_F', `cl_SF', `cl_FF', `cl_DF', +`cl_LF' defines the following operations: + +`struct TYPE_div_t { cl_I quotient; TYPE remainder; };' +`TYPE_div_t floor2 (const TYPE& x)' +`TYPE_div_t ceiling2 (const TYPE& x)' +`TYPE_div_t truncate2 (const TYPE& x)' +`TYPE_div_t round2 (const TYPE& x)' +Each of the classes `cl_R', `cl_RA', `cl_I', `cl_F', `cl_SF', `cl_FF', +`cl_DF', `cl_LF' defines the following operations: + +`struct TYPE_div_t { cl_I quotient; TYPE remainder; };' +`TYPE_div_t floor2 (const TYPE& x, const TYPE& y)' +`TYPE_div_t ceiling2 (const TYPE& x, const TYPE& y)' +`TYPE_div_t truncate2 (const TYPE& x, const TYPE& y)' +`TYPE_div_t round2 (const TYPE& x, const TYPE& y)' +Sometimes, one wants the quotient as a floating-point number (of the +same format as the argument, if the argument is a float) instead of as +an integer. The prefix `f' indicates this. + +Each of the classes `cl_F', `cl_SF', `cl_FF', `cl_DF', `cl_LF' defines +the following operations: + +`TYPE ffloor (const TYPE& x)' +`TYPE fceiling (const TYPE& x)' +`TYPE ftruncate (const TYPE& x)' +`TYPE fround (const TYPE& x)' +and similarly for class `cl_R', but with return type `cl_F'. + +The class `cl_R' defines the following operations: + +`cl_F ffloor (const TYPE& x, const TYPE& y)' +`cl_F fceiling (const TYPE& x, const TYPE& y)' +`cl_F ftruncate (const TYPE& x, const TYPE& y)' +`cl_F fround (const TYPE& x, const TYPE& y)' +These functions also exist in versions which return both the quotient +and the remainder. The suffix `2' indicates this. + +Each of the classes `cl_F', `cl_SF', `cl_FF', `cl_DF', `cl_LF' defines +the following operations: + +`struct TYPE_fdiv_t { TYPE quotient; TYPE remainder; };' +`TYPE_fdiv_t ffloor2 (const TYPE& x)' +`TYPE_fdiv_t fceiling2 (const TYPE& x)' +`TYPE_fdiv_t ftruncate2 (const TYPE& x)' +`TYPE_fdiv_t fround2 (const TYPE& x)' +and similarly for class `cl_R', but with quotient type `cl_F'. + +The class `cl_R' defines the following operations: + +`struct TYPE_fdiv_t { cl_F quotient; cl_R remainder; };' +`TYPE_fdiv_t ffloor2 (const TYPE& x, const TYPE& y)' +`TYPE_fdiv_t fceiling2 (const TYPE& x, const TYPE& y)' +`TYPE_fdiv_t ftruncate2 (const TYPE& x, const TYPE& y)' +`TYPE_fdiv_t fround2 (const TYPE& x, const TYPE& y)' +Other applications need only the remainder of a division. The +remainder of `floor' and `ffloor' is called `mod' (abbreviation of +"modulo"). The remainder `truncate' and `ftruncate' is called `rem' +(abbreviation of "remainder"). + + * `mod(x,y) = floor2(x,y).remainder = x - floor(x/y)*y' + + * `rem(x,y) = truncate2(x,y).remainder = x - truncate(x/y)*y' + +If `x' and `y' are both >= 0, `mod(x,y) = rem(x,y) >= 0'. In general, +`mod(x,y)' has the sign of `y' or is zero, and `rem(x,y)' has the sign +of `x' or is zero. + +The classes `cl_R', `cl_I' define the following operations: + +`TYPE mod (const TYPE& x, const TYPE& y)' +`TYPE rem (const TYPE& x, const TYPE& y)' + +File: cln.info, Node: Roots, Next: Transcendental functions, Prev: Rounding functions, Up: Functions on numbers + +Roots +===== + +Each of the classes `cl_R', `cl_F', `cl_SF', `cl_FF', `cl_DF', `cl_LF' +defines the following operation: + +`TYPE sqrt (const TYPE& x)' + `x' must be >= 0. This function returns the square root of `x', + normalized to be >= 0. If `x' is the square of a rational number, + `sqrt(x)' will be a rational number, else it will return a + floating-point approximation. + +The classes `cl_RA', `cl_I' define the following operation: + +`cl_boolean sqrtp (const TYPE& x, TYPE* root)' + This tests whether `x' is a perfect square. If so, it returns true + and the exact square root in `*root', else it returns false. + +Furthermore, for integers, similarly: + +`cl_boolean isqrt (const TYPE& x, TYPE* root)' + `x' should be >= 0. This function sets `*root' to `floor(sqrt(x))' + and returns the same value as `sqrtp': the boolean value + `(expt(*root,2) == x)'. + +For `n'th roots, the classes `cl_RA', `cl_I' define the following +operation: + +`cl_boolean rootp (const TYPE& x, const cl_I& n, TYPE* root)' + `x' must be >= 0. `n' must be > 0. This tests whether `x' is an + `n'th power of a rational number. If so, it returns true and the + exact root in `*root', else it returns false. + +The only square root function which accepts negative numbers is the one +for class `cl_N': + +`cl_N sqrt (const cl_N& z)' + Returns the square root of `z', as defined by the formula `sqrt(z) + = exp(log(z)/2)'. Conversion to a floating-point type or to a + complex number are done if necessary. The range of the result is + the right half plane `realpart(sqrt(z)) >= 0' including the + positive imaginary axis and 0, but excluding the negative + imaginary axis. The result is an exact number only if `z' is an + exact number. + + +File: cln.info, Node: Transcendental functions, Next: Functions on integers, Prev: Roots, Up: Functions on numbers + +Transcendental functions +======================== + +The transcendental functions return an exact result if the argument is +exact and the result is exact as well. Otherwise they must return +inexact numbers even if the argument is exact. For example, `cos(0) = +1' returns the rational number `1'. + +* Menu: + +* Exponential and logarithmic functions:: +* Trigonometric functions:: +* Hyperbolic functions:: +* Euler gamma:: +* Riemann zeta:: + + +File: cln.info, Node: Exponential and logarithmic functions, Next: Trigonometric functions, Prev: Transcendental functions, Up: Transcendental functions + +Exponential and logarithmic functions +------------------------------------- + +`cl_R exp (const cl_R& x)' +`cl_N exp (const cl_N& x)' + Returns the exponential function of `x'. This is `e^x' where `e' + is the base of the natural logarithms. The range of the result is + the entire complex plane excluding 0. + +`cl_R ln (const cl_R& x)' + `x' must be > 0. Returns the (natural) logarithm of x. + +`cl_N log (const cl_N& x)' + Returns the (natural) logarithm of x. If `x' is real and positive, + this is `ln(x)'. In general, `log(x) = log(abs(x)) + i*phase(x)'. + The range of the result is the strip in the complex plane `-pi < + imagpart(log(x)) <= pi'. + +`cl_R phase (const cl_N& x)' + Returns the angle part of `x' in its polar representation as a + complex number. That is, `phase(x) = + atan(realpart(x),imagpart(x))'. This is also the imaginary part + of `log(x)'. The range of the result is the interval `-pi < + phase(x) <= pi'. The result will be an exact number only if + `zerop(x)' or if `x' is real and positive. + +`cl_R log (const cl_R& a, const cl_R& b)' + `a' and `b' must be > 0. Returns the logarithm of `a' with respect + to base `b'. `log(a,b) = ln(a)/ln(b)'. The result can be exact + only if `a = 1' or if `a' and `b' are both rational. + +`cl_N log (const cl_N& a, const cl_N& b)' + Returns the logarithm of `a' with respect to base `b'. `log(a,b) + = log(a)/log(b)'. + +`cl_N expt (const cl_N& x, const cl_N& y)' + Exponentiation: Returns `x^y = exp(y*log(x))'. + +The constant e = exp(1) = 2.71828... is returned by the following +functions: + +`cl_F cl_exp1 (cl_float_format_t f)' + Returns e as a float of format `f'. + +`cl_F cl_exp1 (const cl_F& y)' + Returns e in the float format of `y'. + +`cl_F cl_exp1 (void)' + Returns e as a float of format `cl_default_float_format'. + + +File: cln.info, Node: Trigonometric functions, Next: Hyperbolic functions, Prev: Exponential and logarithmic functions, Up: Transcendental functions + +Trigonometric functions +----------------------- + +`cl_R sin (const cl_R& x)' + Returns `sin(x)'. The range of the result is the interval `-1 <= + sin(x) <= 1'. + +`cl_N sin (const cl_N& z)' + Returns `sin(z)'. The range of the result is the entire complex + plane. + +`cl_R cos (const cl_R& x)' + Returns `cos(x)'. The range of the result is the interval `-1 <= + cos(x) <= 1'. + +`cl_N cos (const cl_N& x)' + Returns `cos(z)'. The range of the result is the entire complex + plane. + +`struct cl_cos_sin_t { cl_R cos; cl_R sin; };' +`cl_cos_sin_t cl_cos_sin (const cl_R& x)' + Returns both `sin(x)' and `cos(x)'. This is more efficient than + computing them separately. The relation `cos^2 + sin^2 = 1' will + hold only approximately. + +`cl_R tan (const cl_R& x)' +`cl_N tan (const cl_N& x)' + Returns `tan(x) = sin(x)/cos(x)'. + +`cl_N cis (const cl_R& x)' +`cl_N cis (const cl_N& x)' + Returns `exp(i*x)'. The name `cis' means "cos + i sin", because + `e^(i*x) = cos(x) + i*sin(x)'. + +`cl_N asin (const cl_N& z)' + Returns `arcsin(z)'. This is defined as `arcsin(z) = + log(iz+sqrt(1-z^2))/i' and satisfies `arcsin(-z) = -arcsin(z)'. + The range of the result is the strip in the complex domain `-pi/2 + <= realpart(arcsin(z)) <= pi/2', excluding the numbers with + `realpart = -pi/2' and `imagpart < 0' and the numbers with + `realpart = pi/2' and `imagpart > 0'. + +`cl_N acos (const cl_N& z)' + Returns `arccos(z)'. This is defined as `arccos(z) = pi/2 - + arcsin(z) = log(z+i*sqrt(1-z^2))/i' and satisfies `arccos(-z) = pi + - arccos(z)'. The range of the result is the strip in the complex + domain `0 <= realpart(arcsin(z)) <= pi', excluding the numbers + with `realpart = 0' and `imagpart < 0' and the numbers with + `realpart = pi' and `imagpart > 0'. + +`cl_R atan (const cl_R& x, const cl_R& y)' + Returns the angle of the polar representation of the complex number + `x+iy'. This is `atan(y/x)' if `x>0'. The range of the result is + the interval `-pi < atan(x,y) <= pi'. The result will be an exact + number only if `x > 0' and `y' is the exact `0'. WARNING: In + Common Lisp, this function is called as `(atan y x)', with + reversed order of arguments. + +`cl_R atan (const cl_R& x)' + Returns `arctan(x)'. This is the same as `atan(1,x)'. The range of + the result is the interval `-pi/2 < atan(x) < pi/2'. The result + will be an exact number only if `x' is the exact `0'. + +`cl_N atan (const cl_N& z)' + Returns `arctan(z)'. This is defined as `arctan(z) = + (log(1+iz)-log(1-iz)) / 2i' and satisfies `arctan(-z) = + -arctan(z)'. The range of the result is the strip in the complex + domain `-pi/2 <= realpart(arctan(z)) <= pi/2', excluding the + numbers with `realpart = -pi/2' and `imagpart >= 0' and the numbers + with `realpart = pi/2' and `imagpart <= 0'. + +The constant pi = 3.14... is returned by the following functions: + +`cl_F cl_pi (cl_float_format_t f)' + Returns pi as a float of format `f'. + +`cl_F cl_pi (const cl_F& y)' + Returns pi in the float format of `y'. + +`cl_F cl_pi (void)' + Returns pi as a float of format `cl_default_float_format'. + + +File: cln.info, Node: Hyperbolic functions, Next: Euler gamma, Prev: Trigonometric functions, Up: Transcendental functions + +Hyperbolic functions +-------------------- + +`cl_R sinh (const cl_R& x)' + Returns `sinh(x)'. + +`cl_N sinh (const cl_N& z)' + Returns `sinh(z)'. The range of the result is the entire complex + plane. + +`cl_R cosh (const cl_R& x)' + Returns `cosh(x)'. The range of the result is the interval + `cosh(x) >= 1'. + +`cl_N cosh (const cl_N& z)' + Returns `cosh(z)'. The range of the result is the entire complex + plane. + +`struct cl_cosh_sinh_t { cl_R cosh; cl_R sinh; };' +`cl_cosh_sinh_t cl_cosh_sinh (const cl_R& x)' + Returns both `sinh(x)' and `cosh(x)'. This is more efficient than + computing them separately. The relation `cosh^2 - sinh^2 = 1' will + hold only approximately. + +`cl_R tanh (const cl_R& x)' +`cl_N tanh (const cl_N& x)' + Returns `tanh(x) = sinh(x)/cosh(x)'. + +`cl_N asinh (const cl_N& z)' + Returns `arsinh(z)'. This is defined as `arsinh(z) = + log(z+sqrt(1+z^2))' and satisfies `arsinh(-z) = -arsinh(z)'. The + range of the result is the strip in the complex domain `-pi/2 <= + imagpart(arsinh(z)) <= pi/2', excluding the numbers with `imagpart + = -pi/2' and `realpart > 0' and the numbers with `imagpart = pi/2' + and `realpart < 0'. + +`cl_N acosh (const cl_N& z)' + Returns `arcosh(z)'. This is defined as `arcosh(z) = + 2*log(sqrt((z+1)/2)+sqrt((z-1)/2))'. The range of the result is + the half-strip in the complex domain `-pi < imagpart(arcosh(z)) <= + pi, realpart(arcosh(z)) >= 0', excluding the numbers with + `realpart = 0' and `-pi < imagpart < 0'. + +`cl_N atanh (const cl_N& z)' + Returns `artanh(z)'. This is defined as `artanh(z) = + (log(1+z)-log(1-z)) / 2' and satisfies `artanh(-z) = -artanh(z)'. + The range of the result is the strip in the complex domain `-pi/2 + <= imagpart(artanh(z)) <= pi/2', excluding the numbers with + `imagpart = -pi/2' and `realpart <= 0' and the numbers with + `imagpart = pi/2' and `realpart >= 0'. + + +File: cln.info, Node: Euler gamma, Next: Riemann zeta, Prev: Hyperbolic functions, Up: Transcendental functions + +Euler gamma +----------- + +Euler's constant C = 0.577... is returned by the following functions: + +`cl_F cl_eulerconst (cl_float_format_t f)' + Returns Euler's constant as a float of format `f'. + +`cl_F cl_eulerconst (const cl_F& y)' + Returns Euler's constant in the float format of `y'. + +`cl_F cl_eulerconst (void)' + Returns Euler's constant as a float of format + `cl_default_float_format'. + +Catalan's constant G = 0.915... is returned by the following functions: + +`cl_F cl_catalanconst (cl_float_format_t f)' + Returns Catalan's constant as a float of format `f'. + +`cl_F cl_catalanconst (const cl_F& y)' + Returns Catalan's constant in the float format of `y'. + +`cl_F cl_catalanconst (void)' + Returns Catalan's constant as a float of format + `cl_default_float_format'. + + +File: cln.info, Node: Riemann zeta, Prev: Euler gamma, Up: Transcendental functions + +Riemann zeta +------------ + +Riemann's zeta function at an integral point `s>1' is returned by the +following functions: + +`cl_F cl_zeta (int s, cl_float_format_t f)' + Returns Riemann's zeta function at `s' as a float of format `f'. + +`cl_F cl_zeta (int s, const cl_F& y)' + Returns Riemann's zeta function at `s' in the float format of `y'. + +`cl_F cl_zeta (int s)' + Returns Riemann's zeta function at `s' as a float of format + `cl_default_float_format'. + + +File: cln.info, Node: Functions on integers, Next: Functions on floating-point numbers, Prev: Transcendental functions, Up: Functions on numbers + +Functions on integers +===================== + +* Menu: + +* Logical functions:: +* Number theoretic functions:: +* Combinatorial functions:: + + +File: cln.info, Node: Logical functions, Next: Number theoretic functions, Prev: Functions on integers, Up: Functions on integers + +Logical functions +----------------- + +Integers, when viewed as in two's complement notation, can be thought as +infinite bit strings where the bits' values eventually are constant. +For example, + 17 = ......00010001 + -6 = ......11111010 + +The logical operations view integers as such bit strings and operate on +each of the bit positions in parallel. + +`cl_I lognot (const cl_I& x)' +`cl_I operator ~ (const cl_I& x)' + Logical not, like `~x' in C. This is the same as `-1-x'. + +`cl_I logand (const cl_I& x, const cl_I& y)' +`cl_I operator & (const cl_I& x, const cl_I& y)' + Logical and, like `x & y' in C. + +`cl_I logior (const cl_I& x, const cl_I& y)' +`cl_I operator | (const cl_I& x, const cl_I& y)' + Logical (inclusive) or, like `x | y' in C. + +`cl_I logxor (const cl_I& x, const cl_I& y)' +`cl_I operator ^ (const cl_I& x, const cl_I& y)' + Exclusive or, like `x ^ y' in C. + +`cl_I logeqv (const cl_I& x, const cl_I& y)' + Bitwise equivalence, like `~(x ^ y)' in C. + +`cl_I lognand (const cl_I& x, const cl_I& y)' + Bitwise not and, like `~(x & y)' in C. + +`cl_I lognor (const cl_I& x, const cl_I& y)' + Bitwise not or, like `~(x | y)' in C. + +`cl_I logandc1 (const cl_I& x, const cl_I& y)' + Logical and, complementing the first argument, like `~x & y' in C. + +`cl_I logandc2 (const cl_I& x, const cl_I& y)' + Logical and, complementing the second argument, like `x & ~y' in C. + +`cl_I logorc1 (const cl_I& x, const cl_I& y)' + Logical or, complementing the first argument, like `~x | y' in C. + +`cl_I logorc2 (const cl_I& x, const cl_I& y)' + Logical or, complementing the second argument, like `x | ~y' in C. + +These operations are all available though the function +`cl_I boole (cl_boole op, const cl_I& x, const cl_I& y)' +where `op' must have one of the 16 values (each one stands for a +function which combines two bits into one bit): `boole_clr', +`boole_set', `boole_1', `boole_2', `boole_c1', `boole_c2', `boole_and', +`boole_ior', `boole_xor', `boole_eqv', `boole_nand', `boole_nor', +`boole_andc1', `boole_andc2', `boole_orc1', `boole_orc2'. + +Other functions that view integers as bit strings: + +`cl_boolean logtest (const cl_I& x, const cl_I& y)' + Returns true if some bit is set in both `x' and `y', i.e. if + `logand(x,y) != 0'. + +`cl_boolean logbitp (const cl_I& n, const cl_I& x)' + Returns true if the `n'th bit (from the right) of `x' is set. Bit + 0 is the least significant bit. + +`uintL logcount (const cl_I& x)' + Returns the number of one bits in `x', if `x' >= 0, or the number + of zero bits in `x', if `x' < 0. + +The following functions operate on intervals of bits in integers. The +type + struct cl_byte { uintL size; uintL position; }; +represents the bit interval containing the bits +`position'...`position+size-1' of an integer. The constructor +`cl_byte(size,position)' constructs a `cl_byte'. + +`cl_I ldb (const cl_I& n, const cl_byte& b)' + extracts the bits of `n' described by the bit interval `b' and + returns them as a nonnegative integer with `b.size' bits. + +`cl_boolean ldb_test (const cl_I& n, const cl_byte& b)' + Returns true if some bit described by the bit interval `b' is set + in `n'. + +`cl_I dpb (const cl_I& newbyte, const cl_I& n, const cl_byte& b)' + Returns `n', with the bits described by the bit interval `b' + replaced by `newbyte'. Only the lowest `b.size' bits of `newbyte' + are relevant. + +The functions `ldb' and `dpb' implicitly shift. The following functions +are their counterparts without shifting: + +`cl_I mask_field (const cl_I& n, const cl_byte& b)' + returns an integer with the bits described by the bit interval `b' + copied from the corresponding bits in `n', the other bits zero. + +`cl_I deposit_field (const cl_I& newbyte, const cl_I& n, const cl_byte& b)' + returns an integer where the bits described by the bit interval `b' + come from `newbyte' and the other bits come from `n'. + +The following relations hold: + + `ldb (n, b) = mask_field(n, b) >> b.position', + + `dpb (newbyte, n, b) = deposit_field (newbyte << b.position, n, + b)', + + `deposit_field(newbyte,n,b) = n ^ mask_field(n,b) ^ + mask_field(new_byte,b)'. + +The following operations on integers as bit strings are efficient +shortcuts for common arithmetic operations: + +`cl_boolean oddp (const cl_I& x)' + Returns true if the least significant bit of `x' is 1. Equivalent + to `mod(x,2) != 0'. + +`cl_boolean evenp (const cl_I& x)' + Returns true if the least significant bit of `x' is 0. Equivalent + to `mod(x,2) == 0'. + +`cl_I operator << (const cl_I& x, const cl_I& n)' + Shifts `x' by `n' bits to the left. `n' should be >=0. Equivalent + to `x * expt(2,n)'. + +`cl_I operator >> (const cl_I& x, const cl_I& n)' + Shifts `x' by `n' bits to the right. `n' should be >=0. Bits + shifted out to the right are thrown away. Equivalent to `floor(x + / expt(2,n))'. + +`cl_I ash (const cl_I& x, const cl_I& y)' + Shifts `x' by `y' bits to the left (if `y'>=0) or by `-y' bits to + the right (if `y'<=0). In other words, this returns `floor(x * + expt(2,y))'. + +`uintL integer_length (const cl_I& x)' + Returns the number of bits (excluding the sign bit) needed to + represent `x' in two's complement notation. This is the smallest n + >= 0 such that -2^n <= x < 2^n. If x > 0, this is the unique n > 0 + such that 2^(n-1) <= x < 2^n. + +`uintL ord2 (const cl_I& x)' + `x' must be non-zero. This function returns the number of 0 bits + at the right of `x' in two's complement notation. This is the + largest n >= 0 such that 2^n divides `x'. + +`uintL power2p (const cl_I& x)' + `x' must be > 0. This function checks whether `x' is a power of 2. + If `x' = 2^(n-1), it returns n. Else it returns 0. (See also the + function `logp'.) + + +File: cln.info, Node: Number theoretic functions, Next: Combinatorial functions, Prev: Logical functions, Up: Functions on integers + +Number theoretic functions +-------------------------- + +`uint32 gcd (uint32 a, uint32 b)' +`cl_I gcd (const cl_I& a, const cl_I& b)' + This function returns the greatest common divisor of `a' and `b', + normalized to be >= 0. + +`cl_I xgcd (const cl_I& a, const cl_I& b, cl_I* u, cl_I* v)' + This function ("extended gcd") returns the greatest common divisor + `g' of `a' and `b' and at the same time the representation of `g' + as an integral linear combination of `a' and `b': `u' and `v' with + `u*a+v*b = g', `g' >= 0. `u' and `v' will be normalized to be of + smallest possible absolute value, in the following sense: If `a' + and `b' are non-zero, and `abs(a) != abs(b)', `u' and `v' will + satisfy the inequalities `abs(u) <= abs(b)/(2*g)', `abs(v) <= + abs(a)/(2*g)'. + +`cl_I lcm (const cl_I& a, const cl_I& b)' + This function returns the least common multiple of `a' and `b', + normalized to be >= 0. + +`cl_boolean logp (const cl_I& a, const cl_I& b, cl_RA* l)' +`cl_boolean logp (const cl_RA& a, const cl_RA& b, cl_RA* l)' + `a' must be > 0. `b' must be >0 and != 1. If log(a,b) is rational + number, this function returns true and sets *l = log(a,b), else it + returns false. + + +File: cln.info, Node: Combinatorial functions, Prev: Number theoretic functions, Up: Functions on integers + +Combinatorial functions +----------------------- + +`cl_I factorial (uintL n)' + `n' must be a small integer >= 0. This function returns the + factorial `n'! = `1*2*...*n'. + +`cl_I doublefactorial (uintL n)' + `n' must be a small integer >= 0. This function returns the + doublefactorial `n'!! = `1*3*...*n' or `n'!! = `2*4*...*n', + respectively. + +`cl_I binomial (uintL n, uintL k)' + `n' and `k' must be small integers >= 0. This function returns the + binomial coefficient (`n' choose `k') = `n'! / `k'! `(n-k)'! for + 0 <= k <= n, 0 else. + + +File: cln.info, Node: Functions on floating-point numbers, Next: Conversion functions, Prev: Functions on integers, Up: Functions on numbers + +Functions on floating-point numbers +=================================== + +Recall that a floating-point number consists of a sign `s', an exponent +`e' and a mantissa `m'. The value of the number is `(-1)^s * 2^e * m'. + +Each of the classes `cl_F', `cl_SF', `cl_FF', `cl_DF', `cl_LF' defines +the following operations. + +`TYPE scale_float (const TYPE& x, sintL delta)' +`TYPE scale_float (const TYPE& x, const cl_I& delta)' + Returns `x*2^delta'. This is more efficient than an explicit + multiplication because it copies `x' and modifies the exponent. + +The following functions provide an abstract interface to the underlying +representation of floating-point numbers. + +`sintL float_exponent (const TYPE& x)' + Returns the exponent `e' of `x'. For `x = 0.0', this is 0. For + `x' non-zero, this is the unique integer with `2^(e-1) <= abs(x) < + 2^e'. + +`sintL float_radix (const TYPE& x)' + Returns the base of the floating-point representation. This is + always `2'. + +`TYPE float_sign (const TYPE& x)' + Returns the sign `s' of `x' as a float. The value is 1 for `x' >= + 0, -1 for `x' < 0. + +`uintL float_digits (const TYPE& x)' + Returns the number of mantissa bits in the floating-point + representation of `x', including the hidden bit. The value only + depends on the type of `x', not on its value. + +`uintL float_precision (const TYPE& x)' + Returns the number of significant mantissa bits in the + floating-point representation of `x'. Since denormalized numbers + are not supported, this is the same as `float_digits(x)' if `x' is + non-zero, and 0 if `x' = 0. + +The complete internal representation of a float is encoded in the type +`cl_decoded_float' (or `cl_decoded_sfloat', `cl_decoded_ffloat', +`cl_decoded_dfloat', `cl_decoded_lfloat', respectively), defined by + struct cl_decoded_TYPEfloat { + TYPE mantissa; cl_I exponent; TYPE sign; + }; + +and returned by the function + +`cl_decoded_TYPEfloat decode_float (const TYPE& x)' + For `x' non-zero, this returns `(-1)^s', `e', `m' with `x = (-1)^s + * 2^e * m' and `0.5 <= m < 1.0'. For `x' = 0, it returns + `(-1)^s'=1, `e'=0, `m'=0. `e' is the same as returned by the + function `float_exponent'. + +A complete decoding in terms of integers is provided as type + struct cl_idecoded_float { + cl_I mantissa; cl_I exponent; cl_I sign; + }; +by the following function: + +`cl_idecoded_float integer_decode_float (const TYPE& x)' + For `x' non-zero, this returns `(-1)^s', `e', `m' with `x = (-1)^s + * 2^e * m' and `m' an integer with `float_digits(x)' bits. For `x' + = 0, it returns `(-1)^s'=1, `e'=0, `m'=0. WARNING: The exponent + `e' is not the same as the one returned by the functions + `decode_float' and `float_exponent'. + +Some other function, implemented only for class `cl_F': + +`cl_F float_sign (const cl_F& x, const cl_F& y)' + This returns a floating point number whose precision and absolute + value is that of `y' and whose sign is that of `x'. If `x' is + zero, it is treated as positive. Same for `y'. + + +File: cln.info, Node: Conversion functions, Next: Random number generators, Prev: Functions on floating-point numbers, Up: Functions on numbers + +Conversion functions +==================== + +* Menu: + +* Conversion to floating-point numbers:: +* Conversion to rational numbers:: + + +File: cln.info, Node: Conversion to floating-point numbers, Next: Conversion to rational numbers, Prev: Conversion functions, Up: Conversion functions + +Conversion to floating-point numbers +------------------------------------ + +The type `cl_float_format_t' describes a floating-point format. + +`cl_float_format_t cl_float_format (uintL n)' + Returns the smallest float format which guarantees at least `n' + decimal digits in the mantissa (after the decimal point). + +`cl_float_format_t cl_float_format (const cl_F& x)' + Returns the floating point format of `x'. + +`cl_float_format_t cl_default_float_format' + Global variable: the default float format used when converting + rational numbers to floats. + +To convert a real number to a float, each of the types `cl_R', `cl_F', +`cl_I', `cl_RA', `int', `unsigned int', `float', `double' defines the +following operations: + +`cl_F cl_float (const TYPE&x, cl_float_format_t f)' + Returns `x' as a float of format `f'. + +`cl_F cl_float (const TYPE&x, const cl_F& y)' + Returns `x' in the float format of `y'. + +`cl_F cl_float (const TYPE&x)' + Returns `x' as a float of format `cl_default_float_format' if it + is an exact number, or `x' itself if it is already a float. + +Of course, converting a number to a float can lose precision. + +Every floating-point format has some characteristic numbers: + +`cl_F most_positive_float (cl_float_format_t f)' + Returns the largest (most positive) floating point number in float + format `f'. + +`cl_F most_negative_float (cl_float_format_t f)' + Returns the smallest (most negative) floating point number in + float format `f'. + +`cl_F least_positive_float (cl_float_format_t f)' + Returns the least positive floating point number (i.e. > 0 but + closest to 0) in float format `f'. + +`cl_F least_negative_float (cl_float_format_t f)' + Returns the least negative floating point number (i.e. < 0 but + closest to 0) in float format `f'. + +`cl_F float_epsilon (cl_float_format_t f)' + Returns the smallest floating point number e > 0 such that `1+e != + 1'. + +`cl_F float_negative_epsilon (cl_float_format_t f)' + Returns the smallest floating point number e > 0 such that `1-e != + 1'. + + +File: cln.info, Node: Conversion to rational numbers, Prev: Conversion to floating-point numbers, Up: Conversion functions + +Conversion to rational numbers +------------------------------ + +Each of the classes `cl_R', `cl_RA', `cl_F' defines the following +operation: + +`cl_RA rational (const TYPE& x)' + Returns the value of `x' as an exact number. If `x' is already an + exact number, this is `x'. If `x' is a floating-point number, the + value is a rational number whose denominator is a power of 2. + +In order to convert back, say, `(cl_F)(cl_R)"1/3"' to `1/3', there is +the function + +`cl_RA rationalize (const cl_R& x)' + If `x' is a floating-point number, it actually represents an + interval of real numbers, and this function returns the rational + number with smallest denominator (and smallest numerator, in + magnitude) which lies in this interval. If `x' is already an + exact number, this function returns `x'. + +If `x' is any float, one has + + `cl_float(rational(x),x) = x' + + `cl_float(rationalize(x),x) = x' + + +File: cln.info, Node: Random number generators, Next: Obfuscating operators, Prev: Conversion functions, Up: Functions on numbers + +Random number generators +======================== + +A random generator is a machine which produces (pseudo-)random numbers. +The include file `' defines a class `cl_random_state' +which contains the state of a random generator. If you make a copy of +the random number generator, the original one and the copy will produce +the same sequence of random numbers. + +The following functions return (pseudo-)random numbers in different +formats. Calling one of these modifies the state of the random number +generator in a complicated but deterministic way. + +The global variable + cl_random_state cl_default_random_state +contains a default random number generator. It is used when the +functions below are called without `cl_random_state' argument. + +`uint32 random32 (cl_random_state& randomstate)' +`uint32 random32 ()' + Returns a random unsigned 32-bit number. All bits are equally + random. + +`cl_I random_I (cl_random_state& randomstate, const cl_I& n)' +`cl_I random_I (const cl_I& n)' + `n' must be an integer > 0. This function returns a random integer + `x' in the range `0 <= x < n'. + +`cl_F random_F (cl_random_state& randomstate, const cl_F& n)' +`cl_F random_F (const cl_F& n)' + `n' must be a float > 0. This function returns a random + floating-point number of the same format as `n' in the range `0 <= + x < n'. + +`cl_R random_R (cl_random_state& randomstate, const cl_R& n)' +`cl_R random_R (const cl_R& n)' + Behaves like `random_I' if `n' is an integer and like `random_F' + if `n' is a float. + + +File: cln.info, Node: Obfuscating operators, Prev: Random number generators, Up: Functions on numbers + +Obfuscating operators +===================== + +The modifying C/C++ operators `+=', `-=', `*=', `/=', `&=', `|=', `^=', +`<<=', `>>=' are not available by default because their use tends to +make programs unreadable. It is trivial to get away without them. +However, if you feel that you absolutely need these operators to get +happy, then add + #define WANT_OBFUSCATING_OPERATORS +to the beginning of your source files, before the inclusion of any CLN +include files. This flag will enable the following operators: + +For the classes `cl_N', `cl_R', `cl_RA', `cl_F', `cl_SF', `cl_FF', +`cl_DF', `cl_LF': + +`TYPE& operator += (TYPE&, const TYPE&)' +`TYPE& operator -= (TYPE&, const TYPE&)' +`TYPE& operator *= (TYPE&, const TYPE&)' +`TYPE& operator /= (TYPE&, const TYPE&)' +For the class `cl_I': + +`TYPE& operator += (TYPE&, const TYPE&)' +`TYPE& operator -= (TYPE&, const TYPE&)' +`TYPE& operator *= (TYPE&, const TYPE&)' +`TYPE& operator &= (TYPE&, const TYPE&)' +`TYPE& operator |= (TYPE&, const TYPE&)' +`TYPE& operator ^= (TYPE&, const TYPE&)' +`TYPE& operator <<= (TYPE&, const TYPE&)' +`TYPE& operator >>= (TYPE&, const TYPE&)' +For the classes `cl_N', `cl_R', `cl_RA', `cl_I', `cl_F', `cl_SF', +`cl_FF', `cl_DF', `cl_LF': + +`TYPE& operator ++ (TYPE& x)' + The prefix operator `++x'. + +`void operator ++ (TYPE& x, int)' + The postfix operator `x++'. + +`TYPE& operator -- (TYPE& x)' + The prefix operator `--x'. + +`void operator -- (TYPE& x, int)' + The postfix operator `x--'. + +Note that by using these obfuscating operators, you wouldn't gain +efficiency: In CLN `x += y;' is exactly the same as `x = x+y;', not +more efficient. + + +File: cln.info, Node: Input/Output, Next: Rings, Prev: Functions on numbers, Up: Top + +Input/Output +************ + +* Menu: + +* Internal and printed representation:: +* Input functions:: +* Output functions:: + + +File: cln.info, Node: Internal and printed representation, Next: Input functions, Prev: Input/Output, Up: Input/Output + +Internal and printed representation +=================================== + +All computations deal with the internal representations of the numbers. + +Every number has an external representation as a sequence of ASCII +characters. Several external representations may denote the same +number, for example, "20.0" and "20.000". + +Converting an internal to an external representation is called +"printing", converting an external to an internal representation is +called "reading". In CLN, is it always true that conversion of an +internal to an external representation and then back to an internal +representation will yield the same internal representation. +Symbolically: `read(print(x)) == x'. This is called "print-read +consistency". + +Different types of numbers have different external representations (case +is insignificant): + +Integers + External representation: SIGN{DIGIT}+. The reader also accepts the + Common Lisp syntaxes SIGN{DIGIT}+`.' with a trailing dot for + decimal integers and the `#NR', `#b', `#o', `#x' prefixes. + +Rational numbers + External representation: SIGN{DIGIT}+`/'{DIGIT}+. The `#NR', + `#b', `#o', `#x' prefixes are allowed here as well. + +Floating-point numbers + External representation: SIGN{DIGIT}*EXPONENT or + SIGN{DIGIT}*`.'{DIGIT}*EXPONENT or SIGN{DIGIT}*`.'{DIGIT}+. A + precision specifier of the form _PREC may be appended. There must + be at least one digit in the non-exponent part. The exponent has + the syntax EXPMARKER EXPSIGN {DIGIT}+. The exponent marker is + + `s' for short-floats, + + `f' for single-floats, + + `d' for double-floats, + + `L' for long-floats, + + or `e', which denotes a default float format. The precision + specifying suffix has the syntax _PREC where PREC denotes the + number of valid mantissa digits (in decimal, excluding leading + zeroes), cf. also function `cl_float_format'. + +Complex numbers + External representation: + In algebraic notation: `REALPART+IMAGPARTi'. Of course, if + IMAGPART is negative, its printed representation begins with + a `-', and the `+' between REALPART and IMAGPART may be + omitted. Note that this notation cannot be used when the + IMAGPART is rational and the rational number's base is >18, + because the `i' is then read as a digit. + + In Common Lisp notation: `#C(REALPART IMAGPART)'. + + +File: cln.info, Node: Input functions, Next: Output functions, Prev: Internal and printed representation, Up: Input/Output + +Input functions +=============== + +Including `' defines a type `cl_istream', which is the type of +the first argument to all input functions. Unless you build and use CLN +with the macro CL_IO_STDIO being defined, `cl_istream' is the same as +`istream&'. + +The variable + `cl_istream cl_stdin' contains the standard input stream. + +These are the simple input functions: + +`int freadchar (cl_istream stream)' + Reads a character from `stream'. Returns `cl_EOF' (not a `char'!) + if the end of stream was encountered or an error occurred. + +`int funreadchar (cl_istream stream, int c)' + Puts back `c' onto `stream'. `c' must be the result of the last + `freadchar' operation on `stream'. + +Each of the classes `cl_N', `cl_R', `cl_RA', `cl_I', `cl_F', `cl_SF', +`cl_FF', `cl_DF', `cl_LF' defines, in `', the following +input function: + +`cl_istream operator>> (cl_istream stream, TYPE& result)' + Reads a number from `stream' and stores it in the `result'. + +The most flexible input functions, defined in `', are the +following: + +`cl_N read_complex (cl_istream stream, const cl_read_flags& flags)' +`cl_R read_real (cl_istream stream, const cl_read_flags& flags)' +`cl_F read_float (cl_istream stream, const cl_read_flags& flags)' +`cl_RA read_rational (cl_istream stream, const cl_read_flags& flags)' +`cl_I read_integer (cl_istream stream, const cl_read_flags& flags)' + Reads a number from `stream'. The `flags' are parameters which + affect the input syntax. Whitespace before the number is silently + skipped. + +`cl_N read_complex (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse)' +`cl_R read_real (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse)' +`cl_F read_float (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse)' +`cl_RA read_rational (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse)' +`cl_I read_integer (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse)' + Reads a number from a string in memory. The `flags' are parameters + which affect the input syntax. The string starts at `string' and + ends at `string_limit' (exclusive limit). `string_limit' may also + be `NULL', denoting the entire string, i.e. equivalent to + `string_limit = string + strlen(string)'. If `end_of_parse' is + `NULL', the string in memory must contain exactly one number and + nothing more, else a fatal error will be signalled. If + `end_of_parse' is not `NULL', `*end_of_parse' will be assigned a + pointer past the last parsed character (i.e. `string_limit' if + nothing came after the number). Whitespace is not allowed. + +The structure `cl_read_flags' contains the following fields: + +`cl_read_syntax_t syntax' + The possible results of the read operation. Possible values are + `syntax_number', `syntax_real', `syntax_rational', + `syntax_integer', `syntax_float', `syntax_sfloat', + `syntax_ffloat', `syntax_dfloat', `syntax_lfloat'. + +`cl_read_lsyntax_t lsyntax' + Specifies the language-dependent syntax variant for the read + operation. Possible values are + + `lsyntax_standard' + accept standard algebraic notation only, no complex numbers, + + `lsyntax_algebraic' + accept the algebraic notation `X+Yi' for complex numbers, + + `lsyntax_commonlisp' + accept the `#b', `#o', `#x' syntaxes for binary, octal, + hexadecimal numbers, `#BASER' for rational numbers in a given + base, `#c(REALPART IMAGPART)' for complex numbers, + + `lsyntax_all' + accept all of these extensions. + +`unsigned int rational_base' + The base in which rational numbers are read. + +`cl_float_format_t float_flags.default_float_format' + The float format used when reading floats with exponent marker `e'. + +`cl_float_format_t float_flags.default_lfloat_format' + The float format used when reading floats with exponent marker `l'. + +`cl_boolean float_flags.mantissa_dependent_float_format' + When this flag is true, floats specified with more digits than + corresponding to the exponent marker they contain, but without + _NNN suffix, will get a precision corresponding to their number of + significant digits. + + +File: cln.info, Node: Output functions, Prev: Input functions, Up: Input/Output + +Output functions +================ + +Including `' defines a type `cl_ostream', which is the type of +the first argument to all output functions. Unless you build and use +CLN with the macro CL_IO_STDIO being defined, `cl_ostream' is the same +as `ostream&'. + +The variable + `cl_ostream cl_stdout' contains the standard output stream. + +The variable + `cl_ostream cl_stderr' contains the standard error output stream. + +These are the simple output functions: + +`void fprintchar (cl_ostream stream, char c)' + Prints the character `x' literally on the `stream'. + +`void fprint (cl_ostream stream, const char * string)' + Prints the `string' literally on the `stream'. + +`void fprintdecimal (cl_ostream stream, int x)' +`void fprintdecimal (cl_ostream stream, const cl_I& x)' + Prints the integer `x' in decimal on the `stream'. + +`void fprintbinary (cl_ostream stream, const cl_I& x)' + Prints the integer `x' in binary (base 2, without prefix) on the + `stream'. + +`void fprintoctal (cl_ostream stream, const cl_I& x)' + Prints the integer `x' in octal (base 8, without prefix) on the + `stream'. + +`void fprinthexadecimal (cl_ostream stream, const cl_I& x)' + Prints the integer `x' in hexadecimal (base 16, without prefix) on + the `stream'. + +Each of the classes `cl_N', `cl_R', `cl_RA', `cl_I', `cl_F', `cl_SF', +`cl_FF', `cl_DF', `cl_LF' defines, in `', the following +output functions: + +`void fprint (cl_ostream stream, const TYPE& x)' +`cl_ostream operator<< (cl_ostream stream, const TYPE& x)' + Prints the number `x' on the `stream'. The output may depend on + the global printer settings in the variable + `cl_default_print_flags'. The `ostream' flags and settings + (flags, width and locale) are ignored. + +The most flexible output function, defined in `', are the +following: + void print_complex (cl_ostream stream, const cl_print_flags& flags, + const cl_N& z); + void print_real (cl_ostream stream, const cl_print_flags& flags, + const cl_R& z); + void print_float (cl_ostream stream, const cl_print_flags& flags, + const cl_F& z); + void print_rational (cl_ostream stream, const cl_print_flags& flags, + const cl_RA& z); + void print_integer (cl_ostream stream, const cl_print_flags& flags, + const cl_I& z); +Prints the number `x' on the `stream'. The `flags' are parameters which +affect the output. + +The structure type `cl_print_flags' contains the following fields: + +`unsigned int rational_base' + The base in which rational numbers are printed. Default is `10'. + +`cl_boolean rational_readably' + If this flag is true, rational numbers are printed with radix + specifiers in Common Lisp syntax (`#NR' or `#b' or `#o' or `#x' + prefixes, trailing dot). Default is false. + +`cl_boolean float_readably' + If this flag is true, type specific exponent markers have + precedence over 'E'. Default is false. + +`cl_float_format_t default_float_format' + Floating point numbers of this format will be printed using the + 'E' exponent marker. Default is `cl_float_format_ffloat'. + +`cl_boolean complex_readably' + If this flag is true, complex numbers will be printed using the + Common Lisp syntax `#C(REALPART IMAGPART)'. Default is false. + +`cl_string univpoly_varname' + Univariate polynomials with no explicit indeterminate name will be + printed using this variable name. Default is `"x"'. + +The global variable `cl_default_print_flags' contains the default +values, used by the function `fprint', + + +File: cln.info, Node: Rings, Next: Modular integers, Prev: Input/Output, Up: Top + +Rings +***** + +CLN has a class of abstract rings. + + Ring + cl_ring + + +Rings can be compared for equality: + +`bool operator== (const cl_ring&, const cl_ring&)' +`bool operator!= (const cl_ring&, const cl_ring&)' + These compare two rings for equality. + +Given a ring `R', the following members can be used. + +`void R->fprint (cl_ostream stream, const cl_ring_element& x)' +`cl_boolean R->equal (const cl_ring_element& x, const cl_ring_element& y)' +`cl_ring_element R->zero ()' +`cl_boolean R->zerop (const cl_ring_element& x)' +`cl_ring_element R->plus (const cl_ring_element& x, const cl_ring_element& y)' +`cl_ring_element R->minus (const cl_ring_element& x, const cl_ring_element& y)' +`cl_ring_element R->uminus (const cl_ring_element& x)' +`cl_ring_element R->one ()' +`cl_ring_element R->canonhom (const cl_I& x)' +`cl_ring_element R->mul (const cl_ring_element& x, const cl_ring_element& y)' +`cl_ring_element R->square (const cl_ring_element& x)' +`cl_ring_element R->expt_pos (const cl_ring_element& x, const cl_I& y)' +The following rings are built-in. + +`cl_null_ring cl_0_ring' + The null ring, containing only zero. + +`cl_complex_ring cl_C_ring' + The ring of complex numbers. This corresponds to the type `cl_N'. + +`cl_real_ring cl_R_ring' + The ring of real numbers. This corresponds to the type `cl_R'. + +`cl_rational_ring cl_RA_ring' + The ring of rational numbers. This corresponds to the type `cl_RA'. + +`cl_integer_ring cl_I_ring' + The ring of integers. This corresponds to the type `cl_I'. + +Type tests can be performed for any of `cl_C_ring', `cl_R_ring', +`cl_RA_ring', `cl_I_ring': + +`cl_boolean instanceof (const cl_number& x, const cl_number_ring& R)' + Tests whether the given number is an element of the number ring R. + + +File: cln.info, Node: Modular integers, Next: Symbolic data types, Prev: Rings, Up: Top + +Modular integers +**************** + +* Menu: + +* Modular integer rings:: +* Functions on modular integers:: + + +File: cln.info, Node: Modular integer rings, Next: Functions on modular integers, Prev: Modular integers, Up: Modular integers + +Modular integer rings +===================== + +CLN implements modular integers, i.e. integers modulo a fixed integer N. +The modulus is explicitly part of every modular integer. CLN doesn't +allow you to (accidentally) mix elements of different modular rings, +e.g. `(3 mod 4) + (2 mod 5)' will result in a runtime error. (Ideally +one would imagine a generic data type `cl_MI(N)', but C++ doesn't have +generic types. So one has to live with runtime checks.) + +The class of modular integer rings is + + Ring + cl_ring + + | + | + Modular integer ring + cl_modint_ring + + +and the class of all modular integers (elements of modular integer +rings) is + + Modular integer + cl_MI + + +Modular integer rings are constructed using the function + +`cl_modint_ring cl_find_modint_ring (const cl_I& N)' + This function returns the modular ring `Z/NZ'. It takes care of + finding out about special cases of `N', like powers of two and odd + numbers for which Montgomery multiplication will be a win, and + precomputes any necessary auxiliary data for computing modulo `N'. + There is a cache table of rings, indexed by `N' (or, more + precisely, by `abs(N)'). This ensures that the precomputation + costs are reduced to a minimum. + +Modular integer rings can be compared for equality: + +`bool operator== (const cl_modint_ring&, const cl_modint_ring&)' +`bool operator!= (const cl_modint_ring&, const cl_modint_ring&)' + These compare two modular integer rings for equality. Two + different calls to `cl_find_modint_ring' with the same argument + necessarily return the same ring because it is memoized in the + cache table. + + +File: cln.info, Node: Functions on modular integers, Prev: Modular integer rings, Up: Modular integers + +Functions on modular integers +============================= + +Given a modular integer ring `R', the following members can be used. + +`cl_I R->modulus' + This is the ring's modulus, normalized to be nonnegative: `abs(N)'. + +`cl_MI R->zero()' + This returns `0 mod N'. + +`cl_MI R->one()' + This returns `1 mod N'. + +`cl_MI R->canonhom (const cl_I& x)' + This returns `x mod N'. + +`cl_I R->retract (const cl_MI& x)' + This is a partial inverse function to `R->canonhom'. It returns the + standard representative (`>=0', `random(cl_random_state& randomstate)' +`cl_MI R->random()' + This returns a random integer modulo `N'. + +The following operations are defined on modular integers. + +`cl_modint_ring x.ring ()' + Returns the ring to which the modular integer `x' belongs. + +`cl_MI operator+ (const cl_MI&, const cl_MI&)' + Returns the sum of two modular integers. One of the arguments may + also be a plain integer. + +`cl_MI operator- (const cl_MI&, const cl_MI&)' + Returns the difference of two modular integers. One of the + arguments may also be a plain integer. + +`cl_MI operator- (const cl_MI&)' + Returns the negative of a modular integer. + +`cl_MI operator* (const cl_MI&, const cl_MI&)' + Returns the product of two modular integers. One of the arguments + may also be a plain integer. + +`cl_MI square (const cl_MI&)' + Returns the square of a modular integer. + +`cl_MI recip (const cl_MI& x)' + Returns the reciprocal `x^-1' of a modular integer `x'. `x' must + be coprime to the modulus, otherwise an error message is issued. + +`cl_MI div (const cl_MI& x, const cl_MI& y)' + Returns the quotient `x*y^-1' of two modular integers `x', `y'. + `y' must be coprime to the modulus, otherwise an error message is + issued. + +`cl_MI expt_pos (const cl_MI& x, const cl_I& y)' + `y' must be > 0. Returns `x^y'. + +`cl_MI expt (const cl_MI& x, const cl_I& y)' + Returns `x^y'. If `y' is negative, `x' must be coprime to the + modulus, else an error message is issued. + +`cl_MI operator<< (const cl_MI& x, const cl_I& y)' + Returns `x*2^y'. + +`cl_MI operator>> (const cl_MI& x, const cl_I& y)' + Returns `x*2^-y'. When `y' is positive, the modulus must be odd, + or an error message is issued. + +`bool operator== (const cl_MI&, const cl_MI&)' +`bool operator!= (const cl_MI&, const cl_MI&)' + Compares two modular integers, belonging to the same modular + integer ring, for equality. + +`cl_boolean zerop (const cl_MI& x)' + Returns true if `x' is `0 mod N'. + +The following output functions are defined (see also the chapter on +input/output). + +`void fprint (cl_ostream stream, const cl_MI& x)' +`cl_ostream operator<< (cl_ostream stream, const cl_MI& x)' + Prints the modular integer `x' on the `stream'. The output may + depend on the global printer settings in the variable + `cl_default_print_flags'. + + +File: cln.info, Node: Symbolic data types, Next: Univariate polynomials, Prev: Modular integers, Up: Top + +Symbolic data types +******************* + +CLN implements two symbolic (non-numeric) data types: strings and +symbols. + +* Menu: + +* Strings:: +* Symbols:: + + +File: cln.info, Node: Strings, Next: Symbols, Prev: Symbolic data types, Up: Symbolic data types + +Strings +======= + +The class + + String + cl_string + + +implements immutable strings. + +Strings are constructed through the following constructors: + +`cl_string (const char * s)' + Returns an immutable copy of the (zero-terminated) C string `s'. + +`cl_string (const char * ptr, unsigned long len)' + Returns an immutable copy of the `len' characters at `ptr[0]', + ..., `ptr[len-1]'. NUL characters are allowed. + +The following functions are available on strings: + +`operator =' + Assignment from `cl_string' and `const char *'. + +`s.length()' +`strlen(s)' + Returns the length of the string `s'. + +`s[i]' + Returns the `i'th character of the string `s'. `i' must be in the + range `0 <= i < s.length()'. + +`bool equal (const cl_string& s1, const cl_string& s2)' + Compares two strings for equality. One of the arguments may also + be a plain `const char *'. + + +File: cln.info, Node: Symbols, Prev: Strings, Up: Symbolic data types + +Symbols +======= + +Symbols are uniquified strings: all symbols with the same name are +shared. This means that comparison of two symbols is fast (effectively +just a pointer comparison), whereas comparison of two strings must in +the worst case walk both strings until their end. Symbols are used, +for example, as tags for properties, as names of variables in +polynomial rings, etc. + +Symbols are constructed through the following constructor: + +`cl_symbol (const cl_string& s)' + Looks up or creates a new symbol with a given name. + +The following operations are available on symbols: + +`cl_string (const cl_symbol& sym)' + Conversion to `cl_string': Returns the string which names the + symbol `sym'. + +`bool equal (const cl_symbol& sym1, const cl_symbol& sym2)' + Compares two symbols for equality. This is very fast. + + +File: cln.info, Node: Univariate polynomials, Next: Internals, Prev: Symbolic data types, Up: Top + +Univariate polynomials +********************** + +* Menu: + +* Univariate polynomial rings:: +* Functions on univariate polynomials:: +* Special polynomials:: + + +File: cln.info, Node: Univariate polynomial rings, Next: Functions on univariate polynomials, Prev: Univariate polynomials, Up: Univariate polynomials + +Univariate polynomial rings +=========================== + +CLN implements univariate polynomials (polynomials in one variable) +over an arbitrary ring. The indeterminate variable may be either +unnamed (and will be printed according to +`cl_default_print_flags.univpoly_varname', which defaults to `x') or +carry a given name. The base ring and the indeterminate are explicitly +part of every polynomial. CLN doesn't allow you to (accidentally) mix +elements of different polynomial rings, e.g. `(a^2+1) * (b^3-1)' will +result in a runtime error. (Ideally this should return a multivariate +polynomial, but they are not yet implemented in CLN.) + +The classes of univariate polynomial rings are + + Ring + cl_ring + + | + | + Univariate polynomial ring + cl_univpoly_ring + + | + +----------------+-------------------+ + | | | + Complex polynomial ring | Modular integer polynomial ring + cl_univpoly_complex_ring | cl_univpoly_modint_ring + | + | + +----------------+ + | | + Real polynomial ring | + cl_univpoly_real_ring | + | + | + +----------------+ + | | + Rational polynomial ring | + cl_univpoly_rational_ring | + | + | + +----------------+ + | + Integer polynomial ring + cl_univpoly_integer_ring + + +and the corresponding classes of univariate polynomials are + + Univariate polynomial + cl_UP + + | + +----------------+-------------------+ + | | | + Complex polynomial | Modular integer polynomial + cl_UP_N | cl_UP_MI + | + | + +----------------+ + | | + Real polynomial | + cl_UP_R | + | + | + +----------------+ + | | + Rational polynomial | + cl_UP_RA | + | + | + +----------------+ + | + Integer polynomial + cl_UP_I + + +Univariate polynomial rings are constructed using the functions + +`cl_univpoly_ring cl_find_univpoly_ring (const cl_ring& R)' +`cl_univpoly_ring cl_find_univpoly_ring (const cl_ring& R, const cl_symbol& varname)' + This function returns the polynomial ring `R[X]', unnamed or named. + `R' may be an arbitrary ring. This function takes care of finding + out about special cases of `R', such as the rings of complex + numbers, real numbers, rational numbers, integers, or modular + integer rings. There is a cache table of rings, indexed by `R' + and `varname'. This ensures that two calls of this function with + the same arguments will return the same polynomial ring. + +`cl_univpoly_complex_ring cl_find_univpoly_ring (const cl_complex_ring& R)' +`cl_univpoly_complex_ring cl_find_univpoly_ring (const cl_complex_ring& R, const cl_symbol& varname)' +`cl_univpoly_real_ring cl_find_univpoly_ring (const cl_real_ring& R)' +`cl_univpoly_real_ring cl_find_univpoly_ring (const cl_real_ring& R, const cl_symbol& varname)' +`cl_univpoly_rational_ring cl_find_univpoly_ring (const cl_rational_ring& R)' +`cl_univpoly_rational_ring cl_find_univpoly_ring (const cl_rational_ring& R, const cl_symbol& varname)' +`cl_univpoly_integer_ring cl_find_univpoly_ring (const cl_integer_ring& R)' +`cl_univpoly_integer_ring cl_find_univpoly_ring (const cl_integer_ring& R, const cl_symbol& varname)' +`cl_univpoly_modint_ring cl_find_univpoly_ring (const cl_modint_ring& R)' +`cl_univpoly_modint_ring cl_find_univpoly_ring (const cl_modint_ring& R, const cl_symbol& varname)' + These functions are equivalent to the general + `cl_find_univpoly_ring', only the return type is more specific, + according to the base ring's type. + + +File: cln.info, Node: Functions on univariate polynomials, Next: Special polynomials, Prev: Univariate polynomial rings, Up: Univariate polynomials + +Functions on univariate polynomials +=================================== + +Given a univariate polynomial ring `R', the following members can be +used. + +`cl_ring R->basering()' + This returns the base ring, as passed to `cl_find_univpoly_ring'. + +`cl_UP R->zero()' + This returns `0 in R', a polynomial of degree -1. + +`cl_UP R->one()' + This returns `1 in R', a polynomial of degree <= 0. + +`cl_UP R->canonhom (const cl_I& x)' + This returns `x in R', a polynomial of degree <= 0. + +`cl_UP R->monomial (const cl_ring_element& x, uintL e)' + This returns a sparse polynomial: `x * X^e', where `X' is the + indeterminate. + +`cl_UP R->create (sintL degree)' + Creates a new polynomial with a given degree. The zero polynomial + has degree `-1'. After creating the polynomial, you should put in + the coefficients, using the `set_coeff' member function, and then + call the `finalize' member function. + +The following are the only destructive operations on univariate +polynomials. + +`void set_coeff (cl_UP& x, uintL index, const cl_ring_element& y)' + This changes the coefficient of `X^index' in `x' to be `y'. After + changing a polynomial and before applying any "normal" operation + on it, you should call its `finalize' member function. + +`void finalize (cl_UP& x)' + This function marks the endpoint of destructive modifications of a + polynomial. It normalizes the internal representation so that + subsequent computations have less overhead. Doing normal + computations on unnormalized polynomials may produce wrong results + or crash the program. + +The following operations are defined on univariate polynomials. + +`cl_univpoly_ring x.ring ()' + Returns the ring to which the univariate polynomial `x' belongs. + +`cl_UP operator+ (const cl_UP&, const cl_UP&)' + Returns the sum of two univariate polynomials. + +`cl_UP operator- (const cl_UP&, const cl_UP&)' + Returns the difference of two univariate polynomials. + +`cl_UP operator- (const cl_UP&)' + Returns the negative of a univariate polynomial. + +`cl_UP operator* (const cl_UP&, const cl_UP&)' + Returns the product of two univariate polynomials. One of the + arguments may also be a plain integer or an element of the base + ring. + +`cl_UP square (const cl_UP&)' + Returns the square of a univariate polynomial. + +`cl_UP expt_pos (const cl_UP& x, const cl_I& y)' + `y' must be > 0. Returns `x^y'. + +`bool operator== (const cl_UP&, const cl_UP&)' +`bool operator!= (const cl_UP&, const cl_UP&)' + Compares two univariate polynomials, belonging to the same + univariate polynomial ring, for equality. + +`cl_boolean zerop (const cl_UP& x)' + Returns true if `x' is `0 in R'. + +`sintL degree (const cl_UP& x)' + Returns the degree of the polynomial. The zero polynomial has + degree `-1'. + +`cl_ring_element coeff (const cl_UP& x, uintL index)' + Returns the coefficient of `X^index' in the polynomial `x'. + +`cl_ring_element x (const cl_ring_element& y)' + Evaluation: If `x' is a polynomial and `y' belongs to the base + ring, then `x(y)' returns the value of the substitution of `y' into + `x'. + +`cl_UP deriv (const cl_UP& x)' + Returns the derivative of the polynomial `x' with respect to the + indeterminate `X'. + +The following output functions are defined (see also the chapter on +input/output). + +`void fprint (cl_ostream stream, const cl_UP& x)' +`cl_ostream operator<< (cl_ostream stream, const cl_UP& x)' + Prints the univariate polynomial `x' on the `stream'. The output + may depend on the global printer settings in the variable + `cl_default_print_flags'. + + +File: cln.info, Node: Special polynomials, Prev: Functions on univariate polynomials, Up: Univariate polynomials + +Special polynomials +=================== + +The following functions return special polynomials. + +`cl_UP_I cl_tschebychev (sintL n)' + Returns the n-th Tchebychev polynomial (n >= 0). + +`cl_UP_I cl_hermite (sintL n)' + Returns the n-th Hermite polynomial (n >= 0). + +`cl_UP_RA cl_legendre (sintL n)' + Returns the n-th Legendre polynomial (n >= 0). + +`cl_UP_I cl_laguerre (sintL n)' + Returns the n-th Laguerre polynomial (n >= 0). + +Information how to derive the differential equation satisfied by each +of these polynomials from their definition can be found in the +`doc/polynomial/' directory. + + +File: cln.info, Node: Internals, Next: Using the library, Prev: Univariate polynomials, Up: Top + +Internals +********* + +* Menu: + +* Why C++ ?:: +* Memory efficiency:: +* Speed efficiency:: +* Garbage collection:: + + +File: cln.info, Node: Why C++ ?, Next: Memory efficiency, Prev: Internals, Up: Internals + +Why C++ ? +========= + +Using C++ as an implementation language provides + + * Efficiency: It compiles to machine code. + + * Portability: It runs on all platforms supporting a C++ compiler. + Because of the availability of GNU C++, this includes all + currently used 32-bit and 64-bit platforms, independently of the + quality of the vendor's C++ compiler. + + * Type safety: The C++ compilers knows about the number types and + complains if, for example, you try to assign a float to an integer + variable. However, a drawback is that C++ doesn't know about + generic types, hence a restriction like that `operation+ (const + cl_MI&, const cl_MI&)' requires that both arguments belong to the + same modular ring cannot be expressed as a compile-time + information. + + * Algebraic syntax: The elementary operations `+', `-', `*', `=', + `==', ... can be used in infix notation, which is more convenient + than Lisp notation `(+ x y)' or C notation `add(x,y,&z)'. + +With these language features, there is no need for two separate +languages, one for the implementation of the library and one in which +the library's users can program. This means that a prototype +implementation of an algorithm can be integrated into the library +immediately after it has been tested and debugged. No need to rewrite +it in a low-level language after having prototyped in a high-level +language. + + +File: cln.info, Node: Memory efficiency, Next: Speed efficiency, Prev: Why C++ ?, Up: Internals + +Memory efficiency +================= + +In order to save memory allocations, CLN implements: + + * Object sharing: An operation like `x+0' returns `x' without copying + it. + + * Garbage collection: A reference counting mechanism makes sure that + any number object's storage is freed immediately when the last + reference to the object is gone. + + * Small integers are represented as immediate values instead of + pointers to heap allocated storage. This means that integers `> + -2^29', `< 2^29' don't consume heap memory, unless they were + explicitly allocated on the heap. + + +File: cln.info, Node: Speed efficiency, Next: Garbage collection, Prev: Memory efficiency, Up: Internals + +Speed efficiency +================ + +Speed efficiency is obtained by the combination of the following tricks +and algorithms: + + * Small integers, being represented as immediate values, don't + require memory access, just a couple of instructions for each + elementary operation. + + * The kernel of CLN has been written in assembly language for some + CPUs (`i386', `m68k', `sparc', `mips', `arm'). + + * On all CPUs, CLN uses the superefficient low-level routines from + GNU GMP version 2. + + * For large numbers, CLN uses, instead of the standard `O(N^2)' + algorithm, the Karatsuba multiplication, which is an `O(N^1.6)' + algorithm. + + * For very large numbers (more than 12000 decimal digits), CLN uses + Schönhage-Strassen multiplication, which is an asymptotically + optimal multiplication algorithm. + + * These fast multiplication algorithms also give improvements in the + speed of division and radix conversion. + + +File: cln.info, Node: Garbage collection, Prev: Speed efficiency, Up: Internals + +Garbage collection +================== + +All the number classes are reference count classes: They only contain a +pointer to an object in the heap. Upon construction, assignment and +destruction of number objects, only the objects' reference count are +manipulated. + +Memory occupied by number objects are automatically reclaimed as soon as +their reference count drops to zero. + +For number rings, another strategy is implemented: There is a cache of, +for example, the modular integer rings. A modular integer ring is +destroyed only if its reference count dropped to zero and the cache is +about to be resized. The effect of this strategy is that recently used +rings remain cached, whereas undue memory consumption through cached +rings is avoided. + + +File: cln.info, Node: Using the library, Next: Customizing, Prev: Internals, Up: Top + +Using the library +***************** + +For the following discussion, we will assume that you have installed +the CLN source in `$CLN_DIR' and built it in `$CLN_TARGETDIR'. For +example, for me it's `CLN_DIR="$HOME/cln"' and +`CLN_TARGETDIR="$HOME/cln/linuxelf"'. You might define these as +environment variables, or directly substitute the appropriate values. + +* Menu: + +* Compiler options:: +* Include files:: +* An Example:: +* Debugging support:: + + +File: cln.info, Node: Compiler options, Next: Include files, Prev: Using the library, Up: Using the library + +Compiler options +================ + +Until you have installed CLN in a public place, the following options +are needed: + +When you compile CLN application code, add the flags + -I$CLN_DIR/include -I$CLN_TARGETDIR/include +to the C++ compiler's command line (`make' variable CFLAGS or CXXFLAGS). +When you link CLN application code to form an executable, add the flags + $CLN_TARGETDIR/src/libcln.a +to the C/C++ compiler's command line (`make' variable LIBS). + +If you did a `make install', the include files are installed in a +public directory (normally `/usr/local/include'), hence you don't need +special flags for compiling. The library has been installed to a public +directory as well (normally `/usr/local/lib'), hence when linking a CLN +application it is sufficient to give the flag `-lcln'. + + +File: cln.info, Node: Include files, Next: An Example, Prev: Compiler options, Up: Using the library + +Include files +============= + +Here is a summary of the include files and their contents. + +`' + General definitions, reference counting, garbage collection. + +`' + The class cl_number. + +`' + Functions for class cl_N, the complex numbers. + +`' + Functions for class cl_R, the real numbers. + +`' + Functions for class cl_F, the floats. + +`' + Functions for class cl_SF, the short-floats. + +`' + Functions for class cl_FF, the single-floats. + +`' + Functions for class cl_DF, the double-floats. + +`' + Functions for class cl_LF, the long-floats. + +`' + Functions for class cl_RA, the rational numbers. + +`' + Functions for class cl_I, the integers. + +`' + Input/Output. + +`' + Input/Output for class cl_N, the complex numbers. + +`' + Input/Output for class cl_R, the real numbers. + +`' + Input/Output for class cl_F, the floats. + +`' + Input/Output for class cl_SF, the short-floats. + +`' + Input/Output for class cl_FF, the single-floats. + +`' + Input/Output for class cl_DF, the double-floats. + +`' + Input/Output for class cl_LF, the long-floats. + +`' + Input/Output for class cl_RA, the rational numbers. + +`' + Input/Output for class cl_I, the integers. + +`' + Flags for customizing input operations. + +`' + Flags for customizing output operations. + +`' + `cl_malloc_hook', `cl_free_hook'. + +`' + `cl_abort'. + +`' + Conditions/exceptions. + +`' + Strings. + +`' + Symbols. + +`' + Property lists. + +`' + General rings. + +`' + The null ring. + +`' + The ring of complex numbers. + +`' + The ring of real numbers. + +`' + The ring of rational numbers. + +`' + The ring of integers. + +`' + Number threory functions. + +`' + Modular integers. + +`' + Vectors. + +`' + General vectors. + +`' + General vectors over cl_number. + +`' + General vectors over cl_N. + +`' + General vectors over cl_R. + +`' + General vectors over cl_RA. + +`' + General vectors over cl_I. + +`' + General vectors of modular integers. + +`' + Simple vectors. + +`' + Simple vectors over cl_number. + +`' + Simple vectors over cl_N. + +`' + Simple vectors over cl_R. + +`' + Simple vectors over cl_RA. + +`' + Simple vectors over cl_I. + +`' + Simple vectors of general ring elements. + +`' + Univariate polynomials. + +`' + Univariate polynomials over the integers. + +`' + Univariate polynomials over the rational numbers. + +`' + Univariate polynomials over the real numbers. + +`' + Univariate polynomials over the complex numbers. + +`' + Univariate polynomials over modular integer rings. + +`' + Timing facilities. + +`' + Includes all of the above. + + +File: cln.info, Node: An Example, Next: Debugging support, Prev: Include files, Up: Using the library + +An Example +========== + +A function which computes the nth Fibonacci number can be written as +follows. + + #include + #include + + // Returns F_n, computed as the nearest integer to + // ((1+sqrt(5))/2)^n/sqrt(5). Assume n>=0. + const cl_I fibonacci (int n) + { + // Need a precision of ((1+sqrt(5))/2)^-n. + cl_float_format_t prec = cl_float_format((int)(0.208987641*n+5)); + cl_R sqrt5 = sqrt(cl_float(5,prec)); + cl_R phi = (1+sqrt5)/2; + return round1( expt(phi,n)/sqrt5 ); + } + +Let's explain what is going on in detail. + +The include file `' is necessary because the type `cl_I' +is used in the function, and the include file `' is needed +for the type `cl_R' and the floating point number functions. The order +of the include files does not matter. + +Then comes the function declaration. The argument is an `int', the +result an integer. The return type is defined as `const cl_I', not +simply `cl_I', because that allows the compiler to detect typos like +`fibonacci(n) = 100'. It would be possible to declare the return type +as `const cl_R' (real number) or even `const cl_N' (complex number). We +use the most specialized possible return type because functions which +call `fibonacci' will be able to profit from the compiler's type +analysis: Adding two integers is slightly more efficient than adding the +same objects declared as complex numbers, because it needs less type +dispatch. Also, when linking to CLN as a non-shared library, this +minimizes the size of the resulting executable program. + +The result will be computed as expt(phi,n)/sqrt(5), rounded to the +nearest integer. In order to get a correct result, the absolute error +should be less than 1/2, i.e. the relative error should be less than +sqrt(5)/(2*expt(phi,n)). To this end, the first line computes a +floating point precision for sqrt(5) and phi. + +Then sqrt(5) is computed by first converting the integer 5 to a +floating point number and than taking the square root. The converse, +first taking the square root of 5, and then converting to the desired +precision, would not work in CLN: The square root would be computed to +a default precision (normally single-float precision), and the +following conversion could not help about the lacking accuracy. This is +because CLN is not a symbolic computer algebra system and does not +represent sqrt(5) in a non-numeric way. + +The type `cl_R' for sqrt5 and, in the following line, phi is the only +possible choice. You cannot write `cl_F' because the C++ compiler can +only infer that `cl_float(5,prec)' is a real number. You cannot write +`cl_N' because a `round1' does not exist for general complex numbers. + +When the function returns, all the local variables in the function are +automatically reclaimed (garbage collected). Only the result survives +and gets passed to the caller. + + +File: cln.info, Node: Debugging support, Prev: An Example, Up: Using the library + +Debugging support +================= + +When debugging a CLN application with GNU `gdb', two facilities are +available from the library: + + * The library does type checks, range checks, consistency checks at + many places. When one of these fails, the function `cl_abort()' is + called. Its default implementation is to perform an `exit(1)', so + you won't have a core dump. But for debugging, it is best to set a + breakpoint at this function: + (gdb) break cl_abort + When this breakpoint is hit, look at the stack's backtrace: + (gdb) where + + * The debugger's normal `print' command doesn't know about CLN's + types and therefore prints mostly useless hexadecimal addresses. + CLN offers a function `cl_print', callable from the debugger, for + printing number objects. In order to get this function, you have + to define the macro `CL_DEBUG' and then include all the header + files for which you want `cl_print' debugging support. For example: + #define CL_DEBUG + #include + Now, if you have in your program a variable `cl_string s', and + inspect it under `gdb', the output may look like this: + (gdb) print s + $7 = { = { = {pointer = 0x8055b60, heappointer = 0x8055b60, + word = 134568800}}, } + (gdb) call cl_print(s) + (cl_string) "" + $8 = 134568800 + Note that the output of `cl_print' goes to the program's error + output, not to gdb's standard output. + + Note, however, that the above facility does not work with all CLN + types, only with number objects and similar. Therefore CLN offers + a member function `debug_print()' on all CLN types. The same macro + `CL_DEBUG' is needed for this member function to be implemented. + Under `gdb', you call it like this: + (gdb) print s + $7 = { = { = {pointer = 0x8055b60, heappointer = 0x8055b60, + word = 134568800}}, } + (gdb) call s.debug_print() + (cl_string) "" + (gdb) define cprint + >call ($1).debug_print() + >end + (gdb) cprint s + (cl_string) "" + Unfortunately, this feature does not seem to work under all + circumstances. + + +File: cln.info, Node: Customizing, Next: Index, Prev: Using the library, Up: Top + +Customizing +*********** + +* Menu: + +* Error handling:: +* Floating-point underflow:: +* Customizing I/O:: +* Customizing the memory allocator:: + + +File: cln.info, Node: Error handling, Next: Floating-point underflow, Prev: Customizing, Up: Customizing + +Error handling +============== + +When a fatal error occurs, an error message is output to the standard +error output stream, and the function `cl_abort' is called. The default +version of this function (provided in the library) terminates the +application. To catch such a fatal error, you need to define the +function `cl_abort' yourself, with the prototype + #include + void cl_abort (void); +This function must not return control to its caller. + + +File: cln.info, Node: Floating-point underflow, Next: Customizing I/O, Prev: Error handling, Up: Customizing + +Floating-point underflow +======================== + +Floating point underflow denotes the situation when a floating-point +number is to be created which is so close to `0' that its exponent is +too low to be represented internally. By default, this causes a fatal +error. If you set the global variable + cl_boolean cl_inhibit_floating_point_underflow +to `cl_true', the error will be inhibited, and a floating-point zero +will be generated instead. The default value of +`cl_inhibit_floating_point_underflow' is `cl_false'. + + +File: cln.info, Node: Customizing I/O, Next: Customizing the memory allocator, Prev: Floating-point underflow, Up: Customizing + +Customizing I/O +=============== + +The output of the function `fprint' may be customized by changing the +value of the global variable `cl_default_print_flags'. + + +File: cln.info, Node: Customizing the memory allocator, Prev: Customizing I/O, Up: Customizing + +Customizing the memory allocator +================================ + +Every memory allocation of CLN is done through the function pointer +`cl_malloc_hook'. Freeing of this memory is done through the function +pointer `cl_free_hook'. The default versions of these functions, +provided in the library, call `malloc' and `free' and check the +`malloc' result against `NULL'. If you want to provide another memory +allocator, you need to define the variables `cl_malloc_hook' and +`cl_free_hook' yourself, like this: + #include + void* (*cl_malloc_hook) (size_t size) = ...; + void (*cl_free_hook) (void* ptr) = ...; +The `cl_malloc_hook' function must not return a `NULL' pointer. + +It is not possible to change the memory allocator at runtime, because +it is already called at program startup by the constructors of some +global variables. + + +File: cln.info, Node: Index, Prev: Customizing, Up: Top + +Index +***** + +* Menu: + + +Tag Table: +Node: Top957 +Node: Introduction3124 +Node: Installation5626 +Node: Prerequisites5920 +Node: C++ compiler6118 +Node: Make utility6833 +Node: Sed utility7019 +Node: Building the library7339 +Node: Installing the library10650 +Node: Cleaning up11373 +Node: Ordinary number types11698 +Node: Exact numbers14045 +Node: Floating-point numbers15210 +Node: Complex numbers18789 +Node: Conversions19286 +Node: Functions on numbers22752 +Node: Constructing numbers23455 +Node: Constructing integers23827 +Node: Constructing rational numbers24117 +Node: Constructing floating-point numbers24592 +Node: Constructing complex numbers25712 +Node: Elementary functions26076 +Node: Elementary rational functions28543 +Node: Elementary complex functions29115 +Node: Comparisons29943 +Node: Rounding functions31842 +Node: Roots37619 +Node: Transcendental functions39500 +Node: Exponential and logarithmic functions40056 +Node: Trigonometric functions42073 +Node: Hyperbolic functions45416 +Node: Euler gamma47489 +Node: Riemann zeta48405 +Node: Functions on integers48961 +Node: Logical functions49249 +Node: Number theoretic functions55202 +Node: Combinatorial functions56569 +Node: Functions on floating-point numbers57247 +Node: Conversion functions60478 +Node: Conversion to floating-point numbers60758 +Node: Conversion to rational numbers62981 +Node: Random number generators64035 +Node: Obfuscating operators65709 +Node: Input/Output67439 +Node: Internal and printed representation67649 +Node: Input functions70191 +Node: Output functions74742 +Node: Rings78478 +Node: Modular integers80402 +Node: Modular integer rings80602 +Node: Functions on modular integers82692 +Node: Symbolic data types85702 +Node: Strings85965 +Node: Symbols87030 +Node: Univariate polynomials87932 +Node: Univariate polynomial rings88190 +Node: Functions on univariate polynomials93144 +Node: Special polynomials96925 +Node: Internals97645 +Node: Why C++ ?97859 +Node: Memory efficiency99360 +Node: Speed efficiency100058 +Node: Garbage collection101122 +Node: Using the library101949 +Node: Compiler options102483 +Node: Include files103401 +Node: An Example107042 +Node: Debugging support110067 +Node: Customizing112417 +Node: Error handling112645 +Node: Floating-point underflow113219 +Node: Customizing I/O113858 +Node: Customizing the memory allocator114151 +Node: Index115108 + +End Tag Table diff --git a/doc/cln.ps b/doc/cln.ps new file mode 100644 index 0000000..069aa6e --- /dev/null +++ b/doc/cln.ps @@ -0,0 +1,4639 @@ +%!PS-Adobe-2.0 +%%Creator: dvips(k) 5.86 Copyright 1999 Radical Eye Software +%%Title: cln.dvi +%%Pages: 71 +%%PageOrder: Ascend +%%BoundingBox: 0 0 596 842 +%%EndComments +%DVIPSWebPage: (www.radicaleye.com) +%DVIPSCommandLine: /usr/local/teTeX/bin/ix86-linux-libc6/dvips -D600 -o +%+ cln.ps cln.dvi +%DVIPSParameters: dpi=600, compressed +%DVIPSSource: TeX output 2000.01.14:2236 +%%BeginProcSet: texc.pro +%! +/TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S +N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 +mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 +0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ +landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize +mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ +matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round +exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ +statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] +N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin +/FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array +/BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 +array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N +df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A +definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get +}B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} +B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr +1 add N}if}B/id 0 N/rw 0 N/rc 0 N/gp 0 N/cp 0 N/G 0 N/CharBuilder{save 3 +1 roll S A/base get 2 index get S/BitMaps get S get/Cd X pop/ctr 0 N Cdx +0 Cx Cy Ch sub Cx Cw add Cy setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx +sub Cy .1 sub]/id Ci N/rw Cw 7 add 8 idiv string N/rc 0 N/gp 0 N/cp 0 N{ +rc 0 ne{rc 1 sub/rc X rw}{G}ifelse}imagemask restore}B/G{{id gp get/gp +gp 1 add N A 18 mod S 18 idiv pl S get exec}loop}B/adv{cp add/cp X}B +/chg{rw cp id gp 4 index getinterval putinterval A gp add/gp X adv}B/nd{ +/cp 0 N rw exit}B/lsh{rw cp 2 copy get A 0 eq{pop 1}{A 255 eq{pop 254}{ +A A add 255 and S 1 and or}ifelse}ifelse put 1 adv}B/rsh{rw cp 2 copy +get A 0 eq{pop 128}{A 255 eq{pop 127}{A 2 idiv S 128 and or}ifelse} +ifelse put 1 adv}B/clr{rw cp 2 index string putinterval adv}B/set{rw cp +fillstr 0 4 index getinterval putinterval adv}B/fillstr 18 string 0 1 17 +{2 copy 255 put pop}for N/pl[{adv 1 chg}{adv 1 chg nd}{1 add chg}{1 add +chg nd}{adv lsh}{adv lsh nd}{adv rsh}{adv rsh nd}{1 add adv}{/rc X nd}{ +1 add set}{1 add clr}{adv 2 chg}{adv 2 chg nd}{pop nd}]A{bind pop} +forall N/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn +/BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put +}if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ +bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A +mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ +SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ +userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X +1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 +index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N +/p{show}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 N/Ry 0 N/V{}B/RV/v{ +/Ry X/Rx X V}B statusdict begin/product where{pop false[(Display)(NeXT) +(LaserWriter 16/600)]{A length product length le{A length product exch 0 +exch getinterval eq{pop true exit}if}{pop}ifelse}forall}{false}ifelse +end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{BDot}imagemask +grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat{BDot} +imagemask grestore}}ifelse B/QV{gsave newpath transform round exch round +exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 rlineto +fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B/M{S p +delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M}B/g{0 M} +B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p -3 w}B/n{ +p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{0 S +rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end + +%%EndProcSet +TeXDict begin 39158280 55380996 1000 600 600 (cln.dvi) +@start +%DVIPSBitmapFont: Fa cmti10 10.95 1 +/Fa 1 47 df<120FEA1F80EA3FC0127F12FFA3EA7F801300123C0A0A77891C>46 +D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fb cmbxti10 14.4 1 +/Fb 1 47 df<13FCEA03FF481380121F4813C0A25AA2B5FCA31480A26C13005B6C5AEA1F +F0EA07C0121271912B>46 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fc cmr9 9 11 +/Fc 11 121 df<14C01301EB03005B130E5B5B137813705B12015B1203485AA248C7FCA3 +121EA3123E123CA2127CA4127812F8B01278127CA4123CA2123E121EA37EA36C7EA26C7E +12017F12001370137813387F7F7F7FEB01C01300124A79B71E>40 +D<7E7E126012707E7E7E120F7E6C7E7F12017F6C7EA21378A37FA3133E131EA2131FA47F +1480B014005BA4131EA2133E133CA35BA35BA2485A5B12035B48C7FC5A120E5A5A5A1260 +5A5A114A7BB71E>I73 +D<153FEC0FFFA2EC007F81AFEB07F0EB3FFCEBFC0F3901E003BF4848C6B4FC48487F48C7 +FC4880123EA2127E127CA212FCA8127CA2127E123EA27E6C5C6C6C5B3903C001BF3A01E0 +033F802600F81E13FCEB3FFCD90FE0130026357DB32B>100 DI105 +D<3903F01FC000FFEB7FF09038F1E0F83907F3807C3903F6007E01FC133E153F5BA35BB3 +A2486CEB7F80B538C7FFFCA226217EA02B>110 DI115 +D<1330A51370A313F0A2120112031207121FB512FEA23803F000B01403A81201EBF80612 +00140CEB7E1CEB1FF8EB07E0182F7FAD1E>I120 +D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fd cmtt12 14.4 1 +/Fd 1 44 df<157815FC4A7EB3A2003FB812E04817F0B912F8A46C17F06C17E0C7D801FE +C8FCB3A26E5A157835347CBE3E>43 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fe cmsy7 7 1 +/Fe 1 1 df0 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Ff cmr7 7 5 +/Ff 5 55 df<1238127C12FEA6127CAA1238AA12101200A51238127C12FEA3127C123807 +297BA813>33 D<1306130C13181330136013E0EA01C0EA0380A2EA07005A120E121EA212 +1C123CA35AA512F85AAB7E1278A57EA3121C121EA2120E120F7EEA0380A2EA01C0EA00E0 +136013301318130C13060F3B7AAB1A>40 D<12C012607E7E7E120E7EEA0380A2EA01C013 +E0120013F0A213701378A3133CA5133E131EAB133E133CA51378A3137013F0A213E01201 +13C0EA0380A2EA0700120E120C5A5A5A5A0F3B7DAB1A>I<13381378EA01F8121F12FE12 +E01200B3AB487EB512F8A215267BA521>49 D54 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fg cmmi7 7 3 +/Fg 3 111 df<1238127C12FEA3127C123807077A8614>58 D<1378EA07FC5BEA0078A3 +5BA4485AA43903C00780EC1FC0EC3860EC60E0380780C1EB8103138290388401C0D80F18 +C7FC5B13E07FEA1FFE381E3F80EB07C06D7EEA3C011560A30078EBC0C01303903801C180 +A200F0EBE300EB00FE0060133C1B297CA723>107 D<3907C01FC0390FE07FE03918F0E0 +F03930718078EB7B00D8607E1338017C133C01781338D8C0F813785B1200A248485BA34A +5AEA03C01660EC03C0A23A07800780C0A2ED8180ED8300390F000386EC01FC00066D5A23 +1B7D9929>110 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fh cmex10 10 2 +/Fh 2 2 df<1430147014E0EB01C0EB0380A2EB0700130E131E131C133C5BA25BA2485A +A212035B1207A2485AA348C7FCA45A123EA3127EA5127CA212FCB3A2127CA2127EA5123E +A3123F7EA46C7EA36C7EA212037F1201A26C7EA21378A27F131C131E130E7FEB0380A2EB +01C0EB00E0147014301462738226>0 D<124012E012707E7EA27E7E7F12037F6C7EA26C +7EA21378A2137C133C133EA27FA3EB0F80A414C01307A314E0A51303A214F0B3A214E0A2 +1307A514C0A3130F1480A4EB1F00A3133EA2133C137C1378A25BA2485AA2485A5B120790 +C7FC120E5AA25A5A5A124014627C8226>I E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fi cmsl10 10.95 20 +/Fi 20 122 df97 D<133FEA1FFFA3C6FC7F137EA65BA6485AA5EC0FF03903F03FFE9138F01F80 +9039F3C007C09039F70003E001FC6D7E498048486D7EA249147EA2167FA2485AA31780A2 +170048485CA54B5A48C7FC5EA24B5AA24B5A485D4B5A4B5AD87D8091C7FC0079147ED878 +C05B39F06003F039E0380FC026C01FFFC8FC380007F8294076BE33>IIII<177C913907F803FE91393FFE0F8F9139FC0F9C1F +903901F007F0903A03E003E01ED907C0EBF00C90260F80011300011F80133F14004980A3 +01FE495AA3017E5C15075E013E5C013F495A6D49C7FCEC803E903837C0FC903861FFF090 +38607F8001E0C9FC5B1201A47F7F6CB512F8EDFF806D14E06D8090B67E3A03E0000FFCD8 +0F80EB00FE48C8127E003E81123C007C815AA4163EA25E00785D007C4A5A6C4A5A6CEC0F +C0D807C0013FC7FC3903F801FC39007FFFF0010F90C8FC303D7FA82D>103 +D<147814FCEB01FE130314FFEB07FE130314FCEB01F8EB00F01400ACEB07F03801FFE0A3 +EA001F130FA214C0A6EB1F80A6EB3F00A6137EA65BA5EA03FE387FFFE0A2B5FC183E7DBD +19>105 D<147EEB3FFEA3130113005CA6495AA6495AA6494890B5FC17FE5D9238007FE0 +EE3F00163C49485B16E04B5A4BC7FC1506151C90381F80305DEC81C0EC83E0EC87F0149F +90383F31F81461ECC0FCEC807C90383E007E153E49133F8182150F826F7E5B6F7EA26F7E +00014A7E486C497EB539E01FFFF017E05D303F7EBE30>107 D<147EEB1FFE133FA21301 +130014FCA6EB01F8A6EB03F0A6EB07E0A6EB0FC0A6EB1F80A6EB3F00A6137EA65BA5EA03 +FE387FFFF0A2B5FC173F7DBE19>I<902707E00FF0EB07F82803FFC03FFEEB1FFFDBF01F +9038780F80913CC1C00F80E007C03E001FC30007C18003E0D90FC6ECC30002CC02E614F0 +4A14EC02B014F802E05CA24A5CA2011F020FEC07E04A5CA549C74848EB0FC0A6017E4AC7 +EA1F80A649027EEC3F00A4000103FE5C486C496CECFF80B5D8F07FD9F83F13FCA346287C +A74D>I<903907E00FF03A03FFC07FFCEDF03E9138C1801F3B001FC7000F80EB0FCE02D8 +14C0149814B014E0A25CA2011FEC1F805CA549C7EA3F00A6017E147EA6495CA400011401 +486C497EB500F0B512F0A32C287CA733>II<9138FE03FC903A +7FFC0FFF8092383C07E09238F001F0903A03FDC000F86DB4C77E4A147E4A147F834A1580 +A218C0171F495AA318E0A218C04948143FA5EF7F80495A18005F5F16015F011F4A5A4C5A +5F6E495A4C5A02B049C7FCD93F1813FC91380E03F0913807FFC0DA01FEC8FC91CAFCA213 +7EA65BA41201487EB512F0A3333A80A733>I<903907E01F803A03FFC07FE09138C1E1F0 +ECC3833A001FC607F8EB0FCC16F014989138B003E0ED018002E0C7FCA25C131FA25CA449 +C8FCA6137EA65BA41201487EB512FCA325287EA724>114 D<9138FF80800107EBE1C090 +391F0073800138131F49130F491307485A000314034914001207A37F150201F090C7FC13 +FC3803FFE06C13FE6C6D7E6D13E06D7F010F7F01007F140FEC01FE0010EB007E0038143E +A3151EA2151C0078143C127C15385D007E14F0007F495A39F38003C026E1E01FC7FC38C0 +7FFCEB1FE0222A7DA824>I<1303A45B1306A2130EA2131EA25BA2137C13FC1201120700 +1FB512C0B6FCA2D801F8C7FCA3485AA6485AA6485AA51403381F8006A65C1300A26D5AA2 +000F5B6C6C5A3803E1C06CB45AD8007EC7FC1A3978B723>III< +48B539803FFFC0A2150026000FFC90381FF800D903F8EB0FC094C7FC0101140E6D6C5B6E +5B027E5B027F5B6E485A91381F838003C3C8FCEC0FC615ECEC07F86E5A811401811403EC +067EEC0C7F4A7E02387FEC701F4A6C7ED901C07F9038038007D907007F010E1303496D7E +013C8013FCD807FE49B4FCB5010F13F85DA232277FA630>120 D<90B539C003FFF05E18 +E0902707FC000113006D48EB00FC4A14706D7E17605F16016E5C01004AC7FCA216068002 +7E5B161C1618027F5B805EA26F5AEC1F815E0383C8FC15C3EC0FC615CE15CC15F814075D +A25D14035D5DA292C9FCA21406140E140C5CA25C1218007E5B00FE5BA2495A4848CAFCEA +F806EA600CEA7838EA3FF0EA0FC0343A80A630>I E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fj cmtt12 13.14 1 +/Fj 1 44 df43 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fk cmbx12 13.14 42 +/Fk 42 123 df<923803FFF0037FEBFE7C0203B612FC141F91397FFE001FDAFFE0133F01 +030180137F4990C7FC495A4A14FF4948147F495AA24A143F017F151FAFB9FCA526007FF0 +C7121FB3B3A2003FB5D8E00FB512F8A53D4D7ECC44>13 D45 +D +I<15F014011407141F147FEB03FF137FB6FCA313FC1380C7FCB3B3B2007FB712E0A52B47 +77C63D>49 DIII<000316E001C0140301FC141F9039FFC003FF91B612C0178017005E5E5E5E16C05E +4BC7FC15F001E7138001E0C9FCABEC1FFC91B512C001E314F001EF14FC9039FFE00FFE91 +390003FF8001FC6D13C001F06D13E04915F049147F17F8C9FC17FC163F17FEA317FFA3EA +0F80EA3FE0487E7F12FF7FA217FE5BA2EE7FFC6C5A01C015F86CC8FCEEFFF06C6C5B6D15 +E06C6C010713C0D807F84913806CB490387FFE006C90B55A6C6C14F0011F14C0010749C7 +FC010013E030487AC63D>I56 +DI67 D69 D72 +D76 DII82 DI<003FBB12C0A5DA80019038F8001FD9F800160148487113E001C0183F49181F +90C7170FA2007E1907A3007C1903A500FC1AF0481901A5C894C7FCB3B3A749B812F8A54C +4A7CC955>I97 +DI<913807FF80 +027F13F80103B512FE010FECFF804948C613C0D97FF0EB1FE04948EB3FF04849137F4849 +EBFFF84890C7FCA2485A121F49EC7FF0123FEE3FE0EE0F80484891C7FCA312FFAB127FA2 +7FA2123FA2001F163E7F120F6D157C6C6D14FC6C16F86C6DEB01F06C01F013076D6CEB0F +E06DB4EB7F80010F90B51200010314FCD9007F13F0020790C7FC2F337CB137>IIIIII<13FC487E3807FF80A2487F487FA66C5B6C5BA2D801FEC7FC6C5A90C8FCACEB7F +C0B5FCA512037EB3B3B61280A5194D7BCC22>I107 +DII<903A7FC001FF80B5010F13F0033F13FC4B13FF9126C1FE077F9138C3F0030003 +9026C7C0017F6C1480DACF008002DE7F02DC8114F8A25CA35CB3AAB6D8C07FEBFFE0A53B +317BB044>I<913807FF80027F13F80103B6FC010F15C090261FFE017F903A7FF0003FF8 +D9FFC0EB0FFC48496D7E4890C76C7E4817804980000F17C048486E13E0A2003F17F04915 +7FA2007F17F8A400FF17FCAB007F17F8A36C6CEDFFF0A3001F17E06D5C000F17C06C6C4A +13806C17006C6D495A6C01E0EB1FFC6D6C495A903A3FFE01FFF0010FB612C0010392C7FC +D9007F13F80207138036337DB13D>I<90397FC007FEB590383FFFE002C1B512F802C714 +FE913ACFF80FFF809126FFC0037F000391C713F06C01FC6E7E4A143F4A814A6E7E170F84 +198083A219C0A283A219E0AA19C05FA31980A24D1300A24D5A804D5A6E4A5A6E4A5A6E49 +5B6E6C485B9126EFF01F5B02E7B548C7FC02E114F8DAE07F13C0DB0FFCC8FC92CAFCAFB6 +12C0A53B467CB044>I<9039FF801FC0B5EB7FF8913881FFFE02837FDA87E11380EC8F83 +0003D99F0713C06C139E14BC14B814F84A6C1380A26F13009138E0007C93C7FCA35CB3A8 +B612E0A52A317CB032>114 DI<14F8A613 +01A41303A21307A2130FA2131F133F137F13FF1203000F90B512F0B7FCA426007FF8C7FC +B3A6167CAA013F14F880131FED01F090380FFE03903907FF07E06DEBFFC06D1480903900 +7FFE00EC0FF826467EC430>III120 +D<007FB500C090387FFFE0A5C601F0C73803F8006E5D017F5E6E1407013F5E6E140F011F +5E6E141FA26D6D91C7FC5F6D153E6F137E6D157C6F13FC6D5DEDF0016D5DEDF803027F5C +15FC1607DA3FFE5B160F021F5CEDFF1F6E91C8FC16BF6E13BE16FE6E5BA36E5BA26E5BA2 +6F5AA26F5AA26F5AA393C9FC5D153E157E157CD81F8013FC486C5B387FE001D8FFF05B14 +035D14074A5A49485A007F49CAFCEBC07E383F81FC6CB45A6C5B6C13C0C648CBFC3B467E +AF41>I<001FB712FCA4DA000113F801F84913F001E04913E05B494913C04B138048C748 +1300A24B5A4B5A003E495B5E5C4A5B4A5BC75C5C4A90C7FC4A5A4A5AA2495B4949137C49 +5B5D5B495B4990C712F85C137F495A48491301485BA248491303484913074849130F161F +4890C7EA7FF04848EB03FFB8FCA42E307DAF37>I E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fl cmmi10 10.95 3 +/Fl 3 80 df<121E123FEA7F80EAFFC0A4EA7F80EA3F00121E0A0A798919>58 +D<49B592B512F082A290C76D913807FE00DA01BFED01F0705D039F6F5AA29126031FF04A +5A150F82150702066D4AC7FC1503A26F7E020C16068281834A017F5CA2707EA24A6E5B16 +1F83160F4A6E5B1607A2834A01035C8316018349486D5CA21880177F49C8EBC180173F18 +E1171F010604E3C8FCEF0FF3A218FB49ED07FEA21703A2496F5AA3013815006001FC1678 +EA03FE267FFFF01538B56C15304A15104C3E7DBD49>78 DI E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fm cmbx12 17.28 42 +/Fm 42 123 df<19F0F001F819FC1803A2180719F8180F19F0A2181F19E0183F19C0A218 +7F198018FF1900A25F60170360A2170760170F60A2171F60173F60A2177F60A217FF95C7 +FC5E5FA216035F16075FA2160F5F161F5FA2163F5F167F5FA216FF94C8FC5D5EA215035E +15075EA2150F5E151F5EA2153F5E157F5EA215FF93C9FC5C5DA214035D14075DA2140F5D +141F5DA2143F5D147F5DA214FF92CAFC5B5CA213035C13075CA2130F5CA2131F5C133F5C +A2137F5C13FF91CBFCA25A5B12035BA212075B120F5BA2121F5B123F5BA2127F5B12FF90 +CCFCA25A127E123C3E9077EB51>47 DI<16F04B7E1507151F153F +EC01FF1407147F010FB5FCB7FCA41487EBF007C7FCB3B3B3B3007FB91280A6395E74DD51 +>IIII<01C0EE01C0D801F0160701FE163FD9FFE0EC03FFDAFF8090B5 +FC92B71280190060606060606095C7FC5F17F817E017804CC8FC16F0D9FC3F90C9FC91CB +FCAEED3FFE0203B512E0020F14FC023F14FF91B712C001FDD9E00F13F09027FFFE00037F +02F801007F02E06EB4FC02808091C86C13804917C04917E049816C4817F090C914F8A371 +13FCA219FEA419FFA3EA03F0EA0FFC487E487E487FA2B57EA319FEA35C19FC6C90C85A49 +17F85BD83FF017F001805D001F18E07F6C6C4B13C06D4B13806C6C92B51200D803FE4A5B +6C6C6C495B6C01E0010F5BD97FFE017F13E0011FB75A6D93C7FC010315FC010015E0023F +91C8FC020313E0406078DD51>IIIII<942601FFFEED03C0057FD9FFF014070407B600FE140F043F6F +6C131F4BB800E0133F030705F8137F031F9127F0007FFE13FF037F49C73807FF014AB500 +E0020013C302070280ED3FE74A49C96CB5FC4A01F81607027F01E08291B54882494A8249 +49CB7E49498449498449864949845D49498490B5855D48874891CDFC1D7F485BA2481C3F +5CA25A1D1F5C5AA34899C7FCA25CA4B5FCAE7EA480A27EA2F50FC07E80A27EA2806CF41F +80A26C7F1D3F6C6E1A007E6F197E7F6D6D616F18016D6D616D1A036D6D4E5A6D6D4E5A6D +6D6C4D5A6D6E173F6E6D4D5A021F01F84C48C7FC6E01FEEE07FC6E6D6C4B5A020102F0ED +7FF06E6C01FE913803FFC0031FD9FFF0013F5B030791B648C8FC030117F8DB003F16E004 +0793C9FCDC007F14F8050149CAFC626677E375>67 D70 D73 D77 D<94381FFFE00407B67E043F15F04BB712FE030FEEFFC0033FD9FC0014F092B500 +C0010F13FC020349C7000113FF4A01F86E6C7F021F01E0031F13E04A496F7F4A90C90003 +7F4A48707F0103497013FF4949717FA24949717F4949717F4949717F49874B8390B58648 +91CB6C7FA24849727FA2481D804A84481DC0A348497313E0A3481DF0A448497313F8A5B5 +1CFCB06C1DF8A26E61A46C1DF0A36E96B5FC6C1DE0A36C6D4E14C0A26C1D806E606C1D00 +A26C6E4D5BA26C6E4D5BA26D6D4D5B6D6D4D5B6D636F5F6D6D94B55A6D6D4C5C6D6D4C91 +C7FC6D6E4B5B6D6E4B5B023F01F0033F13F06E6D4B5B6E01FE4AB55A0203D9FFC0010F91 +C8FC020002FC90B512FC033F90B712F0030F17C0030394C9FCDB007F15F804071580DC00 +1F01E0CAFC666677E379>79 D82 +DI<001FBEFCA64849C79126E0000F1480 +02E0180091C8171F498601F81A0349864986A2491B7FA2491B3F007F1DC090C9181FA400 +7E1C0FA600FE1DE0481C07A5CA95C7FCB3B3B3A3021FBAFCA663617AE070>II<913803FFF8027FEBFFC0 +0103B612F8010F15FE013F6F7E90277FFC003F13E0D9FFC001077F4801F06D7F486F7F6E +6D7F48707E6E6E7FA2717FA2856C5B836C4982A238007FC0011FC8FC90C9FCA7043FB5FC +031FB6FC0203B7FC143F91B5EAF00F0107EBFE00011F13F0017F13C090B5C7FC00035B48 +13F8485B5C5A485B5C5AA2B5C8FCA45FA36C6D143B177B17736C6D14F36C6DD901E37F6E +D907C313FF6C01FCD91F8114FE000301FFD9FF0114FF6C9138FFFE006C6C4A7F011F02F0 +131F010302C0010313FE9026001FFCCAFC48437BC14E>97 D<903807FF80B6FCA6C6FC7F +7FB3A8EFFFF0040FEBFF80043F14F00381B612FC038315FF92268FFE0080DBBFF0010F13 +E0DBFF8001037F93C76C7F03FC6E7F4B6F7E4B6F7E4B6F13805D7313C01BE0A27313F0A2 +1BF8A37313FCA51BFEAC1BFCA41BF861A21BF0A24F13E0A21BC0616F17804F13006F5D6F +4B5A6F4A5B4A6C4A5B9126FC7F804913E09126F81FE0011F5B9127F00FFC01B55A4A6CB6 +48C7FCDAC00115F84A6C6C14C091C7001F49C8FC90C8000113E04F657BE35A>I<92380F +FFE092B6FC020715E0023F15F891B712FE499039FE001FFF010701F0010113804901C001 +0713C0494915E0017F90C75A4A16F049485C485B485B5A5C487013E0A248496E13C0A248 +04011300EF007C95C7FC485BA5B5FCAC7EA3807EA36C7F19FC7E806CEF01F8806CEF03F0 +6C6D15076E16E06C6D150F6D6DEC1FC06D6DEC3F806D6DECFF00010701FCEB03FE6D9039 +FF801FFC010091B512F0023F15C0020F92C7FC020014F8030F13803E437BC148>II<92380FFFC04AB512FC +020FECFF80023F15E091B712F80103D9FE017F499039F0003FFE4901C0EB0FFF4990C76C +7F49486E7F49486E7F49486E7F48844849157F48844A153F48845A4A151F855AA3485B72 +1380A3B5FCA391B9FCA31A000280CBFCA67EA3807EA37E6E160F6CF01F80A26C6D163F6C +19006E5E6C6D16FE6C606D6C15016D6C6CEC07F86D6D4A5A6D01F0EC3FE0010301FC49B4 +5A6D9026FFC01F90C7FC6D6C90B55A021F15F8020715E0020092C8FC030713F041437CC1 +4A>III<903807FF80B6FCA6C6FC7F7FB3A8 +EF0FFF94B512F0040314FC040F14FF4C8193267FC03F7F9326FE001F7FDB81F86D7FDB83 +E07FDB87C06D7F5E038FC780159E039C8015BC03B88215F0A35DA35DB3B3B7D8F007B712 +80A651647BE35A>II<903807FF80B6FCA6C6FC7F7FB3B3B3B3ADB712E0A623647BE32C>108 +D<902607FF80D90FFFEE7FF8B691B500F00207B57E040302FC021F14E0040F02FF027F14 +F84C6F90B67E93267FC03F9027C003FE017F9326FE001F9027E007F0007FC6DA81F86D90 +26F00FC06D7F6DD983E06D4AC77E6DD987C06DD9F83E6E7F4C163C038FC76E4882039E5F +039C6E4A8003BC16FD03B8DCFFC08203F05FA34B94C8FCA34B5EB3B3B7D8F007B7D8803F +B612FCA67E417BC087>I<902607FF80EB0FFFB691B512F0040314FC040F14FF4C819326 +7FC03F7F9326FE001F7FC6DA81F86D7F6DD983E07F6DD987C06D7F5E038FC780159E039C +8015BC03B88215F0A35DA35DB3B3B7D8F007B71280A651417BC05A>I<923807FFE092B6 +FC020715E0021F15F8027F15FE494848C66C6C7E010701F0010F13E04901C001037F4990 +C87F49486F7E49486F7E49486F7E48496F13804819C04A814819E04819F04A814819F8A3 +48496F13FCA34819FEA4B518FFAD6C19FEA46C6D4B13FCA36C19F8A26C6D4B13F0A26C6D +4B13E06C19C06E5D6C19806C6D4B13006D6C4B5A6D6C4B5A6D01C001035B010701F0010F +13E06D01FE017F5B010090B7C7FC023F15FC020715E0020092C8FC030713E048437CC151 +>I<902607FF80EBFFF0B6010FEBFF80043F14F00381B612FC038315FF92268FFE0080DB +BFF0011F13E0C6DAFF806D7F6D91C700037F6D01FC6E7F4B6E7F4B824B6F13804B811BC0 +7313E0A27313F0A21BF885A21BFCA385A21BFEAC1BFC61A31BF8A2611BF0A24F13E0A21B +C0616F4B13801B006F92B5FC6F4A5B6F4A5B6F4A5B6F6C011F13E0DBDFE0495B9226CFFC +03B55A03C7B648C7FC03C115F8DBC07F14C0041F49C8FC040113E093CBFCB3A3B712F0A6 +4F5D7BC05A>I114 DII<902607FFC0ED3FFEB60207B5FCA6C6EE00076D +826D82B3B3A260A360A2606D160E181E606D6D147C4E7F6D6D4948806D6DD907E0ECFF80 +6D01FEEB3FC06D90B65A023F5D020F14FC020314F0DA001F018002F0C7FC51427BC05A> +II<007FB600C0017FB512F8A6D8001F01F8C70003EBE0006D040090C7FC6D +6D4A5A6D6D4A5A6D6D4A5A70495A6D4C5A6E7F6E6D495A6E6D495A7049C8FC6E4A5A6E6D +485A6E6D485A6E13FFEF8FF06EEC9FE06FEBFFC06F5C6F91C9FC5F6F5B816F7F6F7F8481 +707F8493B57E4B805D4B80DB0FF37FDB1FE17F04C080153F4B486C7F4B486C7F4A486D7F +4A486D7F4A5A4B6D7F020F6E7F4A486D7F4A486D804A5A4AC86C7F49486F7F4A6F7F0103 +707FEB3FFFB600F049B7FCA650407EBF55>120 DI<0007B912E019F0A4 +02FCC714E04801C016C091C7481480495C491700494A5B494A5B5E495E4C5B494A5B93B5 +FC604B5C001F4A91C7FC495B5F4B5B4B5B5DC85C4B5B92B55A5C5F4A91C8FC5C4A5B5E4A +5B5C4CEB03F04A5B91B55A5B5E4991C7FC494914074917E05D495B495B49160F5D90B55A +484A141F5A92C8123F4849157F484915FF485E4A14074849021F13C0484BB5FCBAFCA47E +3C407CBF48>I E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fn cmtt10 10.95 85 +/Fn 85 127 df<121C127FA2EAFF80B2EA7F00B1123EC7FCA9121C127FA2EAFF80A3EA7F +00A2121C09396DB830>33 D<003C131E00FEEB3F80A26C137FA248133FB3007E1400007C +7F003C131E191B75B830>I<903903800380496C487E496C487EA8011F131F02C05BA400 +3FB612FE4881B81280A36C16006C5D3A003F803F80017F137F020090C7FCA9495B495B00 +3FB612FE4881B81280A36C16006C5D2701FC01FCC7FCA30003130301F85BA86C486C5A6C +486C5A29387DB730>I<147814FCA5EB03FF011F13E090B512FC4880000780481580261F +FCFC13C001F0EB3FE0D83FC0130FD87F80EB07F001001303007E15F812FE5A1507A3ED03 +F07E007E91C7FC127FEA3F8013E0EA1FF8EA0FFF7E6CEBFF80C614F0013F7F010F13FE01 +007F168002FC13C0153FED0FE0ED07F0A21503007E15F81501B4FCA35A1503A2007E15F0 +007F1407ED0FE0D83FC0131FD81FE0EB7FC09039FCFDFF806CB612006C5C6C5CC614F001 +3F13C0D903FEC7FCEB00FCA6147825477BBE30>I38 D<141E147F14FF5BEB03FEEB07F8EB0FF0EB1FE0EB3FC0EB7F80EBFF005B48 +5A485A5B12075B120F5B121F5B123F90C7FCA25A127EA412FE5AAB7E127EA4127F7EA27F +121F7F120F7F12077F12037F6C7E6C7E7FEB7F80EB3FC0EB1FE0EB0FF0EB07F8EB03FEEB +01FF7F147F141E184771BE30>40 D<127812FE7E7F6C7EEA1FE06C7E6C7E6C7E6C7E6C7E +7FEB3F80EB1FC0130F14E0130714F0130314F8130114FC1300A214FE147EA4147F143FAB +147F147EA414FE14FCA2130114F8130314F0130714E0130F14C0131FEB3F80EB7F005B48 +5A485A485A485A485AEA7FC0485A90C7FC5A1278184778BE30>I<14E0497EA70030EC01 +80007CEC07C000FFEC1FE00181133F01E113FF267FF9F313C0261FFDF713000007B512FC +000114F06C5C013F1380D90FFEC7FC90383FFF8090B512E04880000714FC391FFDF7FF26 +7FF9F313C026FFE1F013E00181133F0101131F007CEC07C00030EC0180000091C7FCA76D +5A23277AAE30>I<141C143E147FAF003FB612FE4881B81280A36C16006C5DC76CC8FCAF +143E141C29297DAF30>II<00 +3FB612E04815F0B712F8A36C15F06C15E025077B9E30>I<120EEA3F80EA7FC0EAFFE0A5 +EA7FC0EA3F80EA0E000B0B6E8A30>I<16E0ED01F0ED03F8A2150716F0150F16E0151F16 +C0153F1680A2157F16005D5D14015D14035D14075D140F5D141F5DA2143F5D147F92C7FC +5C5C13015C13035C13075C130F5C131F5CA2133F5C137F91C8FC5B5B12015B12035B1207 +5B120F5BA2121F5B123F5B127F90C9FC5A5AA2127C123825477BBE30>IIIIII<000FB612804815C0A416800180C8FCAEEB81FF018F13E001BF13F890B57E81 +81D9FE0113809039F0007FC049131F49EB0FE04913076CC713F0C81203A216F81501A412 +3C127EB4FC150316F015074815E0007E140F007FEC1FC06D137FD83FE0EBFF80261FF807 +13006CB55A6C5C6C5C6C14E0D8003F1380D907F8C7FC25397BB730>II<1278B712FC +16FEA416FC00FCC7EA03F8ED07F0ED0FE00078EC1FC0C8EA3F80ED7F00157E15FE4A5A5D +4A5A14075D140F5D4A5AA24AC7FCA2147EA214FE5C13015CA213035CA213075CA3130F5C +A5131F5CA96DC8FCA2273A7CB830>I<49B4FC011F13F0017F13FC90B57E0003ECFF8048 +15C04848C613E0D81FF8EB3FF001E0130F4848EB07F849130348C7EA01FC007E1400A500 +7F14016C15F86D13036C6CEB07F06C6CEB0FE0D807F8EB3FC03A03FF01FF806C90B51200 +6C6C13FC011F13F0497F90B512FE48802607FE0013C0D80FF0EB1FE04848EB0FF0D83F80 +EB03F890C712014815FC007E140000FE15FE48157EA66C15FE007E15FC007F14016C6CEB +03F86D13076C6CEB0FF001F8133FD80FFEEBFFE06CB612C06C1580C6ECFE006D5B011F13 +F0010190C7FC273A7CB830>II59 D<16E0ED01F0ED07F8150F153FEDFFF04A13E0020713 +C04A1300EC3FFEEC7FF8903801FFE0495B010F90C7FC495AEB7FF8495A000313C0485BD8 +1FFEC8FC485AEA7FF0485A138013E06C7EEA3FFC6C7E3807FF806C7FC613F06D7EEB1FFE +6D7E010313C06D7F9038007FF8EC3FFEEC0FFF6E13C0020113E06E13F0ED3FF8150F1507 +ED01F0ED00E0252F7BB230>I<003FB612FE4881B81280A36C16006C5DCBFCA7003FB612 +FE4881B81280A36C16006C5D29157DA530>I<1238127CB4FC7F13E0EA7FF86C7E6CB4FC +00077F6C13E0C67FEB3FFC6D7E903807FF806D7F010013F06E7EEC1FFE6E7E020313C06E +13E09138007FF0ED3FF8150F153FED7FF0913801FFE04A13C0020F13004A5AEC7FF84A5A +010313C0495BD91FFEC7FC495AEBFFF000035B481380001F90C8FCEA3FFC485AEAFFE013 +8090C9FC127C1238252F7BB230>I64 DI<007FB512F0B612FE6F7E82826C813A03F0001FF815076F7E150115008216 +7EA516FE5E15015E15074B5AED7FE090B65A5E4BC7FC6F7E16E0829039F0000FF8ED03FC +ED00FE167E167F82A2EE1F80A6163F17005EA2ED01FE1503ED0FFC007FB65AB7FC16E05E +93C7FC6C14FC29387EB730>I<91383F801C903901FFF03E0107EBFC7E011F13FE4913FF +4914FE9038FFC07F48EB001F4848130F49130748481303484813015B48481300A2485A16 +7E90C8FC5A127E163C160012FEA25AAA7EA2127EA2163C007F157E7E7FA26C7E16FE6C6C +14FC6D13016C6C14F86C6C13036DEB07F06C6C130F6C9038C03FE06DB512C06D14806D14 +00010713FC010113F09038003F80273A7CB830>I<007FB512E015FCB67E6F7E6C81823A +03F0007FF0ED1FF815076F7E6F7E1500167FA2EE3F80A2161F17C0A2160FA317E01607AB +160F17C0A3161F1780163FA2EE7F00A216FE15014B5A1507ED1FF8ED7FF0007FB65A5EB7 +5A93C7FC6C14FC15E02B387FB730>I<007FB612FEB8FCA47ED803F0C7123FA8161E93C7 +FCA4157815FCA490B5FCA6EBF000A4157892C8FCA5EE0780EE0FC0A9007FB7FCB8FCA46C +16802A387DB730>I<007FB7128017C0B8FCA27EA2D801F8C7120FA8EE078093C7FCA515 +1E153FA490B6FCA69038F8003FA4151E92C8FCAE387FFFF080B5FCA27E5C2A387EB730> +I<027F1370903903FFC0F8010F13F1013F13FD4913FF90B6FC4813C0EC003FD803FC131F +4848130F5B484813075B001F14035B123F90C71201A25A127E6F5A93C7FC12FE5AA992B5 +FC17805C7E007E7F1700ED01F8127F6C1403A27F121F6D1307120F7F6C6C130F6D131F6C +6C133F6CB4137FEC80FF6C90B5FC6D13FD6D13F9010F13F10103EBC0F0D9007EC8FC293A +7DB830>I<3B7FFF803FFFC0B56C4813E0A46C496C13C03B03F00001F800B290B6FCA690 +38F00001B3A23B7FFF803FFFC0B56C4813E0A46C496C13C02B387EB730>I<007FB512FE +B7FCA46C14FE390007E000B3B3A8007FB512FEB7FCA46C14FE203878B730>I<387FFFF8 +B5FC80A25C7ED801F8C9FCB3B0160FEE1F80A9007FB7FCB8FCA46C160029387DB730>76 +DII<90383FFFE048B512FC00 +0714FF4815804815C04815E09038F0007F01C0131F4848EB0FF090C71207A2007E1403A3 +00FE15F8481401B3A96C1403A2007E15F0A3007F1407A26D130F6C6CEB1FE001F813FF90 +B6FC6C15C06C15806C1500000114FCD8003F13E0253A7BB830>I<007FB512E0B612FC15 +FF16C016E06C15F03903F0003FED0FF8ED03FC1501ED00FEA2167E167F163FA6167F167E +16FEA2ED01FC1503ED0FF8ED3FF090B6FC16E016C0160015FC15E001F0C8FCB0387FFF80 +B57EA46C5B28387DB730>I<007FB5FCB612E015F815FE816C812603F0017F6E6C7E151F +6F7E15071503821501A515035E1507150F4B5A157F4A485A90B65A93C7FC5D5D8181D9F0 +017FEC007FED1FC0150F821507A917F0EEE1F8A316F13A7FFF8003F3B500C0EBFFF0A26F +13E0816C49EB7FC0C9EA1F002D397EB730>82 D<90390FF801C090397FFF03E048B512C3 +4814F74814FF5A381FF007383FE001903880007F48C7123F007E141F12FE48140FA21507 +A46CEC03C0007E91C7FC127F6C7E13E0EA1FF86CB47E6C13F86CEBFF806C14F0D8003F13 +FC01077F9038007FFF020713809138007FC0153FED0FE0ED07F01503A216F80078140112 +FCA56C140316F06C14077F6DEB0FE001F0EB3FC001FE13FF90B61280160000FD5CD8F87F +13F8011F13E0D870011380253A7BB830>I<007FB712C0B812E0A53AFC001F8007A80078 +ED03C0C791C7FCB3B1010FB5FC4980A46D91C7FC2B387EB730>I<3B7FFF800FFFF0B56C +4813F8A46C496C13F0D803F0C7EA7E00B3B16D14FE00015DA26D1301A26C6C495AA2017F +495A90393FC01FE0ECF07F6DB55A6D5C6D91C7FC6D5B010013F8EC1FC02D397FB730>I< +D87FFE90380FFFC0B54913E0A46C486D13C0D807E0903800FC00A26D130100035DA36D13 +0300015DA36D130700005DA36D130F017E5CA3017F131F6D5CA3EC803F011F91C7FCA490 +380FC07EA46D6C5AA4903803F1F8A401015B14FBA301005B14FFA36E5AA36E5A2B397EB7 +30>II<3A3FFF807FFE92B5FC487FA26C5B6F5A3A00FC001FC0 +6D5C017E133F017F91C7FC6D5BEC807E011F13FE6E5AEB0FE15DEB07F35DEB03FF5D7F6D +5BA26E5AA26EC8FCA24A7EA24A7EA2497FA2903803FBF014F3903807F1F814E190380FE0 +FC14C0011F137EEC807F013F7F02007F49131F017E8001FE130F49800001140749801503 +D87FFF90381FFFC05DB5008014E0A26C010014C0812B387EB730>I<003FB612FC4815FE +A416FC007EC71201ED03F8ED07F0A2ED0FE0ED1FC0A2ED3F80003CEC7F00C8FC15FE4A5A +5D14034A5A4A5AA24A5A4A5AA24AC7FC14FEA2495A495AA2495A495AA2495A495A91C8FC +5B13FE4848143C167E485A485AA2485A485AA2485A48C8FC90B612FEB7FCA46C15FC2738 +7CB730>90 D<007FB5FCB61280A4150000FCC8FCB3B3B3A5B6FC1580A46C140019476DBE +30>I<1238127C12FEA27E7E7F123F7F121F7F120FA27F12077F12037F12017F12007F7F +80133F80131FA280130F801307801303801301801300808081143F81141FA281140F8114 +0781140381140181140081811680153FA216C0151F16E0150F16F0150716F81503A2ED01 +F0ED00E025477BBE30>I<007FB5FCB61280A47EC7121FB3B3B3A5007FB5FCB6FCA46C14 +0019477DBE30>I<1307EB1FC0497EEBFFF8000313FE000FEBFF80D81FFD13C0D87FF813 +F039FFE03FF8EB800FEB0007007CEB01F00070EB00701D0D77B730>I<003FB612E04815 +F0B712F8A36C15F06C15E025077B7D30>I97 +DI<49B47E010F13F0013F13FC497F48B6FC +4815803907FE007F13F8485A485A49EB3F004848130C90C9FC5A127EA212FE5AA87E127E +A2127FED07806C6CEB0FC07F6C6C131F6C6C148001FC133F6CB4EBFF006C90B5FC6C5C6C +5C013F13F0010F13C0D901FEC7FC222A79A830>I<913803FFC0825CA280A2EC0007AAEB +01FC90380FFF87013F13E790B512F74814FF5A3807FE03380FF80049137F4848133F4848 +131F49130F48C7FC1507127E12FEA25AA77E150F127EA2007F141F7E6D133F6C6C137F6D +13FF380FF8012607FE07EBFFC06CB7FC6C02F713E06C14E76D01C713C0011F1303D903F8 +C8FC2B397DB730>II<15 +7F913803FFE0020F13F0143F4A13F8A2ECFF07EB01FE9138FC03F0903903F800C04A1300 +A8007FB612C0B712E0A46C15C0260003F0C7FCB3A9003FB6FCA2481580A26C1500A22539 +7DB830>IIIIII<387FFFF0B57EA47EEA0001B3 +B3A8007FB612E0B712F0A46C15E024387AB730>I<903901F001F03A7F8FFC0FFC3AFFDF +FE1FFE90B5487E92B51280A23A7FFE1FFE1F3B07FC0FFC0FC001F813F89039F007F00701 +E013E0A401C013C0B3A23B7FFC1FFC1FFC3BFFFE3FFE3FFEA43B7FFC1FFC1FFC2F2880A7 +30>IIII<903901FC01E090390FFF83F0013F13E390B512F3 +4814FB4814FF481301380FF80049133F4848131F4848130F5B48C71207A2127E150312FE +5AA77E1507127E127F150F6C7E151F6C6C133F6D137FD80FF813FF3807FE036CB6FC6C14 +FB6C14F36D13C3011F1303EB03F890C7FCAD4AB512E04A14F0A46E14E02C3C7CA730>I< +ED0FF0D87FFFEB7FFEB50081B5FC1487028F1480149F6C9038BFF07F39001FFFC0923800 +3F004A130C4A90C7FC5C5C5CA25CA45CAF007FB512FCB6FC81A25D7E29287DA730>I<90 +381FFC0E90B5129F000714FF5A5A5A387FE007EB800100FEC77E5A81A37E007F141E01C0 +90C7FCEA3FF8381FFFE06C13FF000314C0C614F0010F13FC9038007FFEEC03FFEC007F00 +78EC3F8000FC141FED0FC0A27EA27E151F01C0EB3F806D137F9039F803FF0090B6FC5D5D +00F814F0013F13C0267007FEC7FC222A79A830>III<3B7FFF803FFFC0B56C4813E0A46C496C13C03B01F00001 +F000A26D130300005DA2017C495AA36D495AA36D49C7FCA390380F803EA36D6C5AA2ECE0 +FC01035BA214F101015BA214FB01005BA214FF6E5AA3021FC8FC2B277EA630>I<3B7FFF +800FFFF06E5AB515F8A26C16F04A7ED807C0C7EA1F00A26D5C0003153EA56D147E000115 +7CEC0FC0EC1FE0EC3FF0A32600F87F5BEC7DF8147CA214FC01786D5AA290387CF87C137D +157D14F0013DEB3DE0013F133FA2ECE01FA2011F5C6D486C5A2D277FA630>I<263FFFC0 +B5FC48168014E1A214C06C16003A007E001F806D49C7FCEB1F80157E6D6C5A6D6C5AEB03 +F1903801F3F0ECFFE06D5B147F6E5A92C8FCA2814A7E4A7EEB01F3ECF1F0903803E0F849 +487E010F137C49487EEC003F496D7E017E6D7E4913073B7FFF803FFF806E4813C0B5FCA2 +7E4A6C13802A277EA630>I<3B7FFF803FFFC06E4813E0B5FCA27E4A6C13C03B01F80001 +F000120015036D5C137C4B5A7FA2013F495A7FA26E48C7FC130F14C00107133EA214E001 +035BA2EB01F05DA2EB00F85D1479147D5D143FA26E5AA36E5AA2141F92C8FCA25C143EA2 +147E147C120F486C5AEA3FC113C3EB07F0495A13FF6C5B5C6C90C9FCEA07FCEA01F02B3C +7EA630>I<003FB612FC4815FEA416FC007EC7EA07F8ED0FF0ED1FE0ED3FC0ED7F80003C +ECFF00C7485AEC07FC4A5A4A5A4A5A4A5A4A5A4990C7FC495A495A495A495A495A495A49 +C7121E4848143F485A485A485A485A485A48B7FCB8FCA46C15FE28277DA630>II<1238127C12FEB3B3B3AD127C123807476CBE30>II<01781338D803FE137C3907FF80FE001F13C1 +48EBE7FC4813FF01CF13F8D8FF0713F0486C13C0D87C0013800038EB3C001F0B78B730> +I E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fo cmsy10 10.95 3 +/Fo 3 16 df<007FB812F8B912FCA26C17F83604789847>0 D13 +D15 +D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fp cmr10 10.95 83 +/Fp 83 128 df11 +DIII<121E123FEA7F80EAFFC0A7EA +7F80AAEA3F00AA121EAB120CA5C7FCA9121E123FEA7F80EAFFC0A4EA7F80EA3F00121E0A +4179C019>33 D<001E130F003FEB1F80397F803FC039FFC07FE0A201E013F0A2007F133F +393F601FB0001EEB0F3000001300A5491360A3484813C0A23903000180A20006EB0300A2 +481306485B485B002013101C1C7DBE2D>I<14E0A4EB07FC90383FFF804913E03901F8E3 +F03903E0E078D80780131CD80F007F001E8081481580007C14011278ED06C000F8140F15 +1F153FA36CEC1F80ED0F0092C7FC127E127FA2EA3FC013E0EA1FFE13FF6C13FC6C13FF6C +14C06C806C6C7F011F7F01037F01007F14E7ECE1FFECE07FED3F80151FA2ED0FC0121812 +3C007E1407B4FCA35A5A00C015801260150F16006C5C151E6C5C121C6C14F8390780E1F0 +3903F0EFE0C6B51280D93FFEC7FCEB0FF8EB00E0A422497BC32D>36 +D<121E123FEA7F80EAFFC0A213E0A2127FEA3F60121E1200A513C0A3EA0180A2EA0300A2 +1206A25A5A5A12200B1C79BE19>39 D<1430147014E0EB01C0EB0380EB0700130EA25B5B +1378137013F05B1201485AA2485AA348C7FCA35A121EA2123EA2123CA2127CA5127812F8 +B21278127CA5123CA2123EA2121EA2121F7EA36C7EA36C7EA26C7E12007F137013781338 +7F7FA27FEB0380EB01C0EB00E014701430145A77C323>I<7E7E7E12707E7E7EA27E6C7E +7F12017F12007F1378A27FA37FA3131F7FA21480A21307A214C0A5130314E0B214C01307 +A51480A2130FA21400A25B131EA35BA35BA25B5B12015B12035B48C7FC120EA25A5A5A5A +5A5A135A7AC323>II<121E123FEA7F80EAFFC0A213E0A2127FEA3F60121E1200A513C0A3 +EA0180A2EA0300A21206A25A5A5A12200B1C798919>44 DI<12 +1E123FEA7F80EAFFC0A4EA7F80EA3F00121E0A0A798919>III<14C013031307131F137FEA07FFB5FC139FEAF81F1200B3B3ACEB7F +F0B612F8A31D3D78BC2D>III<150EA2151E153EA2157E15FEA214011403157E1406140E140C1418143814 +30146014E014C0EB0180130314001306130E130C5B133813305B13E05B485A120390C7FC +1206120E120C5A123812305A12E0B8FCA3C8EAFE00AC4A7E49B6FCA3283E7EBD2D>I<00 +021403D807C0130F01F813FE90B55A5D5D5D158092C7FC38063FF890C9FCADEB01FE9038 +0FFF8090383E03E090387001F09038C00078D80780137C90C77E153F0002EC1F80C8FC16 +C0A2ED0FE0A316F0A4123E127F5A7FA290C713E0A248141F006015C0A200701580003014 +3F003815000018147E000E5C6C495A3903C003F03901F00FE06CB55A013F90C7FCEB07F8 +243F7CBC2D>II<123012 +38123E003FB612FCA316F84815F0A216E00070C812C00060EC0180A2ED030015065A5D5D +A2C85A5D15E05D4A5A140392C7FC1406A2140E5CA2143C14381478A214F85CA21301A213 +03A3495AA4130FA6131FA96D5A6D5A26407BBD2D>III<121E123FEA7F80EAFFC0A4EA7F80EA3F +00121EC7FCB3121E123FEA7F80EAFFC0A4EA7F80EA3F00121E0A2779A619>I<007FB912 +E0BA12F0A26C18E0CDFCAE007FB912E0BA12F0A26C18E03C167BA147>61 +D63 D<1507A34B7EA34B7EA24B7EA34B7E156FA2EDEFF815C7A291380187FC1583 +A291380303FE1501A291380600FFA34A6D7EA34A6D7EA34A6D7EA20270800260130FA202 +E0804A1307A201018191B6FCA2498191C71201A201068182A2496F7EA3496F7EA3496F7E +A21370717E13F0486C82D80FFEED3FFCB500E0010FB512F8A33D417DC044>65 +DIIIIIIII75 DIIIII82 +DI<003FB91280A3903AE0007FE00090C76C48131F007EEF0F +C0007C17070078170300701701A300601700A5481860A5C81600B3B14B7E4B7E0107B612 +FEA33B3D7DBC42>IIII<007FB5D8C003B512E0A3C66C48C7387FFC00D93FF8EC1FE0 +6D48EC0F806D6C92C7FC170E6D6C140C6D6C5C17386D6C14306D6D5B17E06E6C5B023F49 +5AEDE003DA1FF090C8FC020F1306EDF80E6E6C5A1618913803FE386E6C5A16606E13E06F +5AA26F7E6F7EA26F7E4B7EA2ED33FEED71FF156103C07F0201137F03807F4A486C7E5C02 +066D7E4A6D7E141C02186D7E4A6D7E147002606D7E4A6D7F13014A6E7E49C86C7E5B0106 +6F7E010E6F7E133F496C812607FFC0EC3FFFB500F80103B512FEA33F3E7EBD44>II91 D<6D1340000114C039030001800006EB0300481306A2485BA248 +5BA2485BA3485BA500CFEB678039DF806FC039FFC07FE001E013F0A2007F133FA2393FC0 +1FE0391F800FC0390F0007801C1C73BE2D>II<13801201EA030012065AA25AA25AA25AA35AA512CFEADF80EAFFC013E0A2 +127FA2EA3FC0EA1F80EA0F000B1C7ABE19>96 DII<49B4FC010F13E090383F00F8017C131C49130648 +48131F48485B0007EC7F80485A121F5B003FEC3F00151E007F91C7FC90C9FCA35AA97EA2 +7F123F16C0121F6DEB0180120F6C6CEB0300A26C6C13066C6C5BD8007C133890383F01F0 +90380FFFC0D901FEC7FC222A7DA828>IIII<167C903903F801FF90391F +FF0787903A7E0FCE0F809038F803F83901F001F03B03E000F8070000076EC7FCA2484813 +7EA2001F147FA6000F147EA26C6C5BA200035C6C6C485A6D485A39037E0FC0D91FFFC8FC +380703F80006CAFCA2120EA2120F7E7F7F6CB512F015FE6C6E7E6C15E00003813A07C000 +1FF848C7EA03FC001E140048157E007C153E0078153F00F881A50078151E007C153E6C5D +001E15786C5DD807C0EB03E0D803F0EB0FC0D800FE017FC7FC90383FFFFC010313C0293D +7EA82D>II< +EA01E0487E487E487EA46C5A6C5A6C5AC8FCACEA01F8127FA3120712031201B3AC487EB5 +12E0A3133E7DBD19>I<14F0EB01F8EB03FCEB07FEA4EB03FCEB01F8EB00F01400AC14FE +137FA313011300147EB3B3A6123C007E137CB413FC14F8A2EB01F0007E13E0383803C038 +1E0780380FFF00EA01FC175184BD1C>III<2703F003FCEB01FE00FF903B0FFF8007FFC0913B3C0FC01E07E0 +913B7003E03801F00007903BC001F06000F82603F1806D487F2601F300EBF98001F6D900 +FBC7127C04FF147E01FC5CA3495CB3A6486C496C14FFB528F07FFFF83F13FCA346287CA7 +4D>I<3903F003F800FFEB1FFF91383C0F8091386007C00007496C7E2603F1807F3801F3 +0001F613018213FCA35BB3A6486C497EB500F0B512F0A32C287CA733>I<14FF010713E0 +90381F81F890387E007E01F8131F4848EB0F804848EB07C04848EB03E0000F15F04848EB +01F8A2003F15FCA248C812FEA44815FFA96C15FEA36C6CEB01FCA3001F15F86C6CEB03F0 +A26C6CEB07E06C6CEB0FC06C6CEB1F80D8007EEB7E0090383F81FC90380FFFF0010090C7 +FC282A7EA82D>I<3901F807F800FFEB3FFF9138781FC09138C007E03A07F98001F02603 +FB007FD801FE6D7E49147E49147FEE3F80A2EE1FC0A217E0A2160F17F0A917E0161FA217 +C0A2EE3F80A26DEC7F00167E6D5C4B5A01FB495A9039F9C007E09039F8F01F80DA3FFEC7 +FCEC0FF091C9FCAD487EB512F0A32C3A7DA733>I<02FF13180107EBC03890381F80E090 +397E0030784913184848130C4848EB06F8485A000F1403485AA248481301A2127FA290C7 +FC5AA97E7FA2123FA26C7E15036C7E000714076C7E6C6C130D00001419017E137190383F +81E190380FFF81903801FE0190C7FCAD4B7E92B512F0A32C3A7DA730>I<3903F007E000 +FFEB1FF0EC7878ECE0FC3907F181FE12033801F3019038F600FCA2153001FC1300A35BB3 +A5487EB512FCA31F287EA724>I<90387FC0603901FFF8E03807C03D380E000748130348 +1301481300A212F01560A27EA27E007F140013C0EA3FFE381FFFE06C13FC6C7F6C7FC614 +80010F13C09038007FE0EC0FF00040130300C0EB01F814007E1578A37E15707E15E07E6C +EB01C000F3EB038039E1E01F0038C0FFFCEB1FE01D2A7DA824>I<1318A61338A41378A2 +13F8A2120112031207001FB512C0B6FCA2D801F8C7FCB3A21560A9000014C07F137CEC01 +80133E90381F8700EB07FEEB01F81B397EB723>IIII<3B7FFFC00FFFE0A3000390390007FE +00C648EB03F0017E6D5A6DEB03801480011F49C7FC90380FC00E903807E00C6E5A903803 +F83801015B6D6C5AEC7EC0EC7F80143F141F6E7E81141FEC3BF0EC71F8ECE1FC14C09038 +01807E01037FD907007F01066D7E49130F496D7E01386D7E017880EA01F8D80FFCEB07FE +B590381FFFF8A32D277FA630>II<001FB61280A29039E0003F0090C7127E001E14FE +001C495A5D0018495A003813075D0030495A141F4A5A92C7FC147EC712FE495A5C495A13 +075C495A011FEB0180EB3F801400137E13FE485A491303485A000715005B48485B001F5C +485A90C7123F007E49B4FCB7FCA221277EA628>II<001C130E00 +7EEB1F80007F133F39FF807FC0A3397F003F80007E131F001CEB0E001A0977BD2D>127 +D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fq cmbx12 14.4 58 +/Fq 58 123 df12 DII45 DII<913803FFC0023F13FC91B6FC010315C0 +010F010013F0D91FFCEB3FF8D93FF0EB0FFC49486D7E49486D7E48496D13804817C091C8 +FC4817E04817F049157FA2001F17F8A2003F17FCA249153FA2007F17FEA600FF17FFB3A5 +007F17FEA6003F17FC6D157FA3001F17F8A3000F17F06D15FF6C17E0A26C6D4913C06C6D +491380A26C6D491300D97FF8EB1FFED91FFCEB3FF8903A0FFF81FFF06D90B55A01011580 +D9003F01FCC7FC020313C0384F7BCD43>I<157815FC14031407141F14FF130F0007B5FC +B6FCA2147F13F0EAF800C7FCB3B3B3A6007FB712FEA52F4E76CD43>II<91380FFF8091B512FC010314FF010F15C090263FF00313F09026FF +800013FC4848C76C7ED803F86E7E4980D807FC168001FF16C0487F82486D15E0A3805CA2 +7E4A4913C07E6C90C7FCD800FC168090C85A18005F167F4C5A5F4B13E04B5B030F5BDB7F +FEC7FC91B512F816C016FCEEFF80DA000713E0030013F8707E70B4FC7013807013C018E0 +7013F0A218F88218FCA318FEEA01C0EA0FF8487E487E487EA2B57E18FCA44C13F86C90C7 +FC18F0495C6C4816E001F04A13C06C484A1380D80FF84A1300D807FE4A5A2703FFF0035B +C690B612F0013F15C0010F92C7FC010114F8D9001F1380374F7ACD43>I<177C17FEA216 +0116031607160FA2161F163F167FA216FF5D5DA25D5DED1FBFED3F3F153E157C15FCEC01 +F815F0EC03E01407EC0FC01580EC1F005C147E147C5C1301495A495A5C495A131F49C7FC +133E5B13FC485A5B485A1207485A485A90C8FC123E127E5ABA12C0A5C96C48C7FCAF020F +B712C0A53A4F7CCE43>I<0003160ED807E0153E01FCEC03FED9FFE0137F91B65A5F5F5F +5F5F94C7FC5E16F85E16C04BC8FC15F801E090C9FC91CAFCABEC0FFF027F13F001E3B512 +FC01E714FF9026FFF80713C0DAC0017F49C713F8496E7E01F0143F496E7E49816C5AC914 +8018C082A218E0A318F0A3EA07C0EA1FF0487E487EA2487EA318E0A25B18C06C485C4916 +8013C0003EC81400003F5D6C6C5D6C6C4A5A6D4A5AD807F8495B6C6C01075B2701FFC03F +5B6C90B6C7FC013F14FC010F14F0010314809026007FF8C8FC344F79CD43>II<121F7F7FEBFF8091B81280A448180060A26060606060A2485F0180C86CC7 +FC007EC912FE5F007C15014C5A4C5A4C5A4C5A485E163F4CC8FC16FEC8485A5E15034B5A +150F5E4B5A153FA24B5AA24BC9FCA25C5C5D1407A34A5AA2141FA3143FA34A5AA414FFA6 +5BAB6D5B6E5A6E5A6E5A395279D043>I<913807FFC0027F13FC49B67E010715E090261F +FC007FD93FC0EB3FFC4948EB0FFE49C76C7E48488048486E138082484816C0A2000FEE7F +E0A3121F7FA27F7F6E15C002E014FF8002FC15806C01FF5BDBC00313006F485A6C02F85B +9238FE0FF86C9138FF3FF06CEDFFE017806C4BC7FC7F6D6E7E010F15E06D81010115FC49 +81010F81013F1680EB7FC32601FF8015C048496C14E04848131F4848010714F0497F001F +020014F84848143F160F48486E13FC1601824848157F173F171FA2170FA318F8A26C7E18 +F0171F6C6C16E0A26C6CED3FC06DED7F806C6C15FF6C6C6C4913006C01E0EB0FFE6C01FC +EB7FF86C6CB65A011F15C0010792C7FC010014F8020F1380364F7ACD43>I<913807FF80 +027F13F00103B512FC010F14FF90261FFE0113C0903A7FF8007FE0D9FFE06D7E48496D7E +48496D7E486F7E4890C77FA2486F1380A2484816C0A2007F17E0A28200FF17F0A418F8A6 +18FCA2127F5EA3123F5E6C7EA26C5DA26C6D5B6C153D6C6D13396C6D13F990397FF801F1 +011FB512E16D02C113F8010314019038007FFCEC00401500A218F05EA218E013F0EA03FC +486C16C0486C5C1880487F18005E5F91C7485A4C5A6C48147F495DD807F049485A4B5B6C +6C010F5B6CB4D93FFEC7FC6C90B55A6D14F0011F14C0010749C8FC010013E0364F7ACD43 +>I63 D<171F4D7E4D7EA24D7EA34C7FA24C7FA34C7FA34C7FA24C7FA34C80 +83047F80167E8304FE804C7E03018116F8830303814C7E03078116E083030F814C7E031F +81168083033F8293C77E4B82157E8403FE824B800201835D840203834B800207835D844A +B87EA24A83A3DA3F80C88092C97E4A84A2027E8202FE844A82010185A24A820103854A82 +010785A24A82010F855C011F717FEBFFFCB600F8020FB712E0A55B547BD366>65 +DI<932601FFF8EC01C0047F +D9FF8013030303B600F01307031F03FC131F92B8133F0203DAE001EBC07F020F01FCC738 +3FF0FF023F01E0EC07F94A01806EB5FC4A48C9FC010301F8824949824949824949824949 +824990CA7E4948835C48854849187FA24849183FA2485B1B1F5AA24849180FA45A4A95C7 +FCA3B5FCAE7EA3806CF207C0A46C7FA26C1A0F1C806C7FA26C6DF01F00A26C6D183E7E6E +606D6C18FC6D6D4C5A6D6D4C5A6D6D16076D6D4C5A6D6D4C5A010001FE4C5A6E6C6C03FF +C7FC6E01E0EC03FC020F01FCEC1FF80203903AFFE001FFE0020091B61280031F4BC8FC03 +0315F8DB007F14C0040101FCC9FC525479D261>IIII<932601FFF8EC +01C0047FD9FF8013030303B600F01307031F03FC131F92B8133F0203DAE001EBC07F020F +01FCC7383FF0FF023F01E0EC07F94A01806EB5FC4A48C9FC010301F88249498249498249 +49824949824990CA7E4948835C48854849187FA24849183FA2485B1B1F5AA24849180FA4 +5A4A95C8FCA3B5FCAE6C057FB712E0A280A27E95C7003FEBC000A36C7FA27E807EA26C7F +A26C7F7E806D7E6D7F6D7F6D7F6D6D5E6D13FC01006D93B5FC6E6C6C5C6E01E0EC07FB02 +0F01FCEC1FF10203D9FFE0EBFFE0020091B6EAC03F031FEE001F030303FC1307DB007F02 +E01301040101FCCAFC5B5479D26A>III77 D<93380FFFC00303B6FC031F15E092B712FC0203D9FC0013FF020F01C0010F13 +C0023F90C7000313F0DA7FFC02007F494848ED7FFE4901E0ED1FFF49496F7F49496F7F49 +90C96C7F49854948707F4948707FA24849717E48864A83481B804A83481BC0A2481BE04A +83A2481BF0A348497113F8A5B51AFCAF6C1BF86E5FA46C1BF0A26E5F6C1BE0A36C6D4D13 +C0A26C6D4D1380A26C1B006C6D4D5A6E5E6C626D6C4C5B6D6D4B5B6D6D4B5B6D6D4B5B6D +6D4B5B6D6D4B90C7FC6D6D4B5A6D01FF02035B023F01E0011F13F0020F01FC90B512C002 +0390B7C8FC020016FC031F15E0030392C9FCDB001F13E0565479D265>79 +DI82 D<91260FFF80130791B500F85B01 +0302FF5B010FEDC03F013FEDF07F90267FF8006D5A2601FFC0EB07FD4890C70001B5FC48 +486E7E49814848150F48488183003F825B007F82A284A200FF83A27F84A27F7F7F6D93C7 +FC6C13C014F014FF6C14F0EDFF806C15F8EEFF806C16F017FC6C16FF6C836C17E06C836D +82011F826D821303010082020F16801400030715C0ED007F1603DC007F13E083170F7113 +F08383127800F882A3187FA27E19E0A37E19C06C17FF6D17807F6D4B13006D5D6D5E01FE +4B5AD9FFC0EC1FF802F84A5A903B1FFFC003FFE0D8FE0790B65AD8FC0193C7FC486C6C14 +FC48010714E0489026003FFEC8FC3C5479D24B>I<003FBC1280A59126C0003F9038C000 +7F49C71607D87FF8060113C001E08449197F49193F90C8171FA2007E1A0FA3007C1A07A5 +00FC1BE0481A03A6C994C7FCB3B3AC91B912F0A553517BD05E>II87 +D +97 DI<913801FFF8021FEBFF8091B612E0010315F8010F9038800FFE4948C77ED93FF813 +03D9FFF0491380485B4A4913C0485B5A4890C7FCA2486F13805B003F6F1300EE00FC94C7 +FC485AA412FFAB127FA27FA2123FA2001FEE03E07F7E6EEC07C07E6EEC0F806C6D141F6C +EE3F006C6D147ED97FFC5CD91FFEEB03F8903A0FFFC01FF0010390B55A01001580021F01 +FCC7FC020113E033387CB63C>I<4DB47E0407B5FCA5EE001F1707B3A4EDFFC0021F13FC +91B6FC010315C7010F9038C01FE7903A1FFE0003F7D93FF86DB5FCD9FFF06D7E48498048 +49805C48824890C8FCA2485AA2123FA2485AA412FFAB127FA46C7EA3121FA26C7E6C5E6E +5C6C7F6C5E6C6D49B5FCD97FF84914E06D6CD90FEFEBFF80903A0FFF807FCF010390B512 +0F010014FE023F13F00203018049C7FC41547CD24B>I<913803FFC0023F13FC49B6FC01 +0715C04901817F903A3FFC003FF0D97FF06D7E4948EB07FC48498048496D7E5A91C76C13 +805A486F13C05B003F17E0A2177F485A18F0A312FFA390B8FCA318E001FCCAFCA5127FA3 +7F123FA2001F17E06DED01F07E17036C6D15E06C16076C6DEC0FC06C6DEC1F806D6CEC3F +006D6C14FED91FFEEB03FC903A0FFFC03FF8010390B55A010015C0021F49C7FC020113F0 +34387CB63D>IIII<137F497E487F487F487F487FA76C5B6C5B6C5B6C5B6DC7FC90C8FCADEB3FF0B5FCA5 +12017EB3B3A6B612E0A51B547BD325>I108 DII<913801FFE0021F +13FE91B612C0010315F0010F9038807FFC903A1FFC000FFED97FF0903803FF8049486D7F +48496D7F48496E7EA24890C86C7E488349151F001F83A2003F834981A2007F1880A400FF +18C0AC007F1880A36C6C4B1300A3001F5FA26C6C4B5AA26C6D4A5A6C5F6C6D4A5A6C6D49 +5B6D6C495BD93FFC010F90C7FC903A0FFF807FFC6D90B55A010015C0023F91C8FC020113 +E03A387CB643>III<90397FE001FCB590380F +FF80033F13E04B13F09238FE1FF89139E1F03FFC0003EBE3E0C69138C07FFEECE7801500 +14EF14EE02FEEB3FFC5CEE1FF8EE07E04A90C7FCA55CB3AAB612FCA52F367CB537>I<90 +3901FFE007011FEBFC1F017FEBFF7F48B7FC3907FE001FD80FF01307D81FC01301497F00 +3F8148C87EA34881A27FA27F01F091C7FC13FC387FFFC014FEECFFF06C14FEEDFFC06C81 +6C15F86C810001816C81013F1580010715C01300020714E0EC001F1503030013F0007815 +7F00F8153F161F7E160FA27E17E07EA26DEC1FC07F6DEC3F806DEC7F0001FCEB01FE9039 +FF800FFC013FB55AD8FC1F14E0D8F803148027E0007FF8C7FC2C387CB635>I<143EA614 +7EA414FEA21301A313031307A2130F131F133F13FF5A000F90B6FCB8FCA426003FFEC8FC +B3A9EE07C0AB011FEC0F80807FEE1F006D1380EDC03E6D6D5A0100EBFFF86E5B021F5B02 +0190C7FC2A4D7ECB34>IIII<00 +7FB500F090387FFFFEA5C66C48C7000F90C7FC6D6CEC03F86D6D495A6D6D495A6D4B5A6F +495A6D6D91C8FC6D6D137E6D6D5B91387FFE014C5A6E6C485A6EEB8FE06EEBCFC06EEBFF +806E91C9FCA26E5B6E5B6F7E6F7EA26F7F834B7F4B7F92B5FCDA01FD7F03F87F4A486C7E +4A486C7E020F7FDA1FC0804A486C7F4A486C7F02FE6D7F4A6D7F495A49486D7F01076F7E +49486E7E49486E7FEBFFF0B500FE49B612C0A542357EB447>II<001FB8FC1880A3912680007F130001FCC75B01F014FF49495B49495B495D5D48C748 +5B4B5B5F5D003E4A90C7FC4B5A5E5C4A5B5EC75A4A5B4A5B5E5C4A90C8FC4A5A5D5B4949 +EB0F80495B5D5B495B4B131F4916004990C7FC495A4A5C5A485B48495C5C485E48495B48 +49130791C7485A4815FFB8FCA37E31357CB43C>I E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fr cmbx12 20.736 16 +/Fr 16 122 df<13FF000313C04813F0487F487F487F5A801580B6FCA215C0A315E0A27E +A37E7E7E6C13F76C13E7C61387EB0007A2140F15C0A3141FA21580143FA215005C147E14 +FEA2495AA2495A495AA2495A495A133F495A49C7FC485A485A485A485A6C5A6C5A6C5A1B +3A729836>44 D<96267FFFE01670063FB616F80503B700E01401053F04FC14034CB91407 +040706C0130F043F06F0131F93B626FE000F01FC133F030303809026007FFE137F030F02 +FCC8390FFF80FF4B02E0030313C1037F91CA13E392B500FCEF3FF7020302F071B5FC4A4A +17074A0280834A91CB7E4A01FC844A498591B54885494A854988494A85495C93CD7E4988 +495B49885D90B51C7F5D481E3F485CA21F1F485CA2481E0F5D5AA21F075D5AA2F703F09C +C7FC5AA392D1FCA2B6FCB27EA281A37EA3F701F06CF603F881A37E816C1E0720F06C80A3 +6C6E1B0F6C1FE06F1B1F7F6F1CC06D1D3F6D6DF37F807F70F2FF006D6E626D6E19016D52 +5A6D6E4F5A6E6D190F6E01FE4F5A6E6D4F5A6E6E4E5A6E02E04D485A6E6E4D90C7FC0200 +02FCEF0FFE6F01FFEF3FFC031F02E0EEFFF06F02FC03075B0303DAFFC0023F1380030003 +FE0107B5C8FC043F91B712FC040718F0040118C0DC003F94C9FC050316F8DD003F1580DE +007F01F0CAFC757A75F78C>67 D76 D78 D<92383FFFF8020FB612E0027F15FC01 +03B87E010F17E04983499026E0007F13FCD97FFCC7000F7F496C02037F486D6E806F6D6C +7F86486E6E7F727F86848684866C5CA26C91C86C806D5A6D5A6D5AEB03C090CAFCA80507 +B6FC041FB7FC0303B8FC157F0203B9FC021FECFE0391B612800103ECF800010F14C04991 +C7FC017F13FC90B512F04814C0485C4891C8FC485B485BA2485BA2485BA2B5FC5CA360A3 +60806C5FA26C6D153E6E5D6C05FC806C01FFDA03F8806C6ED90FF014FC6C02E090263FE0 +7FEBFFFC6C9128FC03FFC03F14FE6C91B61280013F4B487E010F4B1307010303F01301D9 +003F0280D9001F13FC020101F8CBFC57507ACE5E>97 D<903801FFFCB6FCA7C67E131F7F +B3AEF0FFFC050FEBFFE0057F14FE4CB77E040716E0041F16F84CD9007F13FEDCFFF00107 +7F03FD01C001018092B5C86C7F04FC6F7F04F06F7F4C6F7F4C6F7F4C6F7F93C9804B7014 +80A27414C0A21DE0A27513F0A21DF8A37513FCA51DFEAF1DFCA45113F8A31DF0A398B512 +E0A21DC0501480A26F4C1400705F62704B5B705F70033F5BDBF7F84B5BDBE3FE92B55A92 +26C1FF80010391C7FC038001E0011F5B9226007FFC90B55A4A011FB712F04A6D16C04A01 +0393C8FC4A010015F84A021F14C090C9000301F0C9FC5F797AF76C>I101 DI105 D<903801FFFCB6FCA7C67E131F7F +B3B3B3B3B3ADB812C0A72A7879F735>108 D<902601FFF891260FFFE093383FFF80B692 +B500FE0303B512F805036E6C020F14FE050F03E0023F6E7E053F03F891B712E04D6F4982 +9426FFF01F6D49D9C07F7F4CD900076D902707FC001F7FC66CDA07FC01019126801FF001 +077F011FDA0FF0EF3FC06DDA1FC06D6E48C76C7F4DDCE07E83043EC86C02F8804CEFE1F0 +04FC05F3844C60DBF9F06FD9F7C0804C6003FB06FF844C95C9FC15FF4C5FA393C95CA44B +60B3B3A7B8D8E003B8D8800FB712FEA7974E79CDA2>I<93381FFFE00303B6FC031F15E0 +92B712FC020316FF020F17C0023FD9FC0014F091B500C0010F13FC4991C700037F4901FC +02007F010F496F13C049496F7F49496F7F4B8149496F7F90B5C96C7F4886A24849707F48 +1B80A248497014C0A2481BE0A348497113F0A3481BF8A5B51AFCAE6C1BF8A46C1BF06E94 +B5FCA36C1BE0A26C6D4C14C0A26C1B806E5E6C1B006C6E4B5BA26C6E4B5B6D6D4B5B6D6D +4B5B6D6D4B5B6D6D92B55A6D01FF02035C6D02C0010F91C7FC010002FC90B512FC6E90B7 +5A021F17E00207178002014CC8FCDA003F15F0030392C9FCDB001F13E056507BCE61> +111 D<902601FFF8EB07FEB691383FFFC094B512F04C800407804C8093391FFC3FFF9326 +3FE07F1380C66C0380B512C0011F4A5A6DDAFC0114E0A2EDF9F816F015FB16E015FF4C6C +14C0A24C6D1380721300725A93C76C5AF001E095C8FCA25DA55DB3B3A4B812F8A7434E7A +CD4F>114 D<912603FFFCEB0780027F9039FFE00FC00103B6EAF83F010FEDFEFF013F92 +B5FC49EB00072601FFF01300480180141F4890C81207D80FFC8183484881123F49167F12 +7F183FA300FF171F7FA27F7F6DEE0F8002C092C7FC14F014FE6CEBFFF0EDFF8016FE6CED +FFE017FC6C16FF6C17C0846C17F86C836C836C6C826D17806D17C0010717E01301D9003F +16F0020716F8EC001F030015FC1607EE007F171F050713FE007C160100FE82187F7E183F +A2181F7FA26D17FCA27FA26DEE3FF87F19F06D167F6D17E06D6C15FF6E020313C002F04A +138002FC023F1300913AFFC003FFFE01E790B65A01C316F0010016C048013F92C7FC4801 +0714F80070D9007F90C8FC3F507ACE4C>I117 D121 D E +%EndDVIPSBitmapFont +end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: A4 + +%%EndSetup +%%Page: 1 1 +1 0 bop 0 1386 a Fr(CLN,)65 b(a)g(Class)h(Library)g(for)e(Num)-5 +b(b)5 b(ers)p 0 1486 3900 34 v 0 5068 a Fq(b)l(y)45 b(Bruno)f(Haible)p +0 5141 3900 17 v eop +%%Page: 2 2 +2 1 bop 0 3355 a Fp(Cop)m(yrigh)m(t)452 3352 y(c)427 +3355 y Fo(\015)30 b Fp(Bruno)g(Haible)h(1995,)i(1996,)f(1997,)g(1998,)h +(1999,)f(2000.)0 3878 y(Published)19 b(b)m(y)h(Bruno)g(Haible,)j +Fn()14 b Fp(and)20 b(Ric)m(hard)g(Krec)m(k)m +(el,)k Fn()p Fp(.)0 4152 y(P)m(ermission)g(is)h(gran) +m(ted)g(to)h(mak)m(e)f(and)f(distribute)g(v)m(erbatim)h(copies)g(of)g +(this)g(man)m(ual)f(pro)m(vided)h(the)g(cop)m(yrigh)m(t)0 +4276 y(notice)32 b(and)d(this)i(p)s(ermission)d(notice)k(are)e(preserv) +m(ed)g(on)h(all)g(copies.)0 4550 y(P)m(ermission)c(is)h(gran)m(ted)h +(to)g(cop)m(y)f(and)g(distribute)f(mo)s(di\014ed)f(v)m(ersions)i(of)h +(this)e(man)m(ual)h(under)e(the)i(conditions)0 4675 y(for)d(v)m +(erbatim)f(cop)m(ying,)k(pro)m(vided)c(that)i(the)f(en)m(tire)h +(resulting)f(deriv)m(ed)g(w)m(ork)g(is)g(distributed)f(under)g(the)h +(terms)0 4799 y(of)31 b(a)f(p)s(ermission)f(notice)i(iden)m(tical)h(to) +g(this)e(one.)0 5073 y(P)m(ermission)38 b(is)h(gran)m(ted)h(to)g(cop)m +(y)g(and)f(distribute)f(translations)i(of)f(this)g(man)m(ual)g(in)m(to) +h(another)f(language,)0 5198 y(under)27 b(the)h(ab)s(o)m(v)m(e)h +(conditions)g(for)f(mo)s(di\014ed)e(v)m(ersions,)j(except)g(that)f +(this)g(p)s(ermission)e(notice)k(ma)m(y)e(b)s(e)f(stated)0 +5322 y(in)j(a)h(translation)g(appro)m(v)m(ed)g(b)m(y)f(the)h(author.)p +eop +%%Page: 1 3 +1 2 bop 0 -116 a Fp(Chapter)30 b(1:)41 b(In)m(tro)s(duction)2892 +b(1)0 366 y Fm(1)80 b(In)l(tro)t(duction)0 719 y Fp(CLN)30 +b(is)g(a)h(library)f(for)g(computations)g(with)g(all)i(kinds)d(of)i(n)m +(um)m(b)s(ers.)38 b(It)30 b(has)h(a)f(ric)m(h)h(set)g(of)f(n)m(um)m(b)s +(er)e(classes:)75 993 y Fo(\017)60 b Fp(In)m(tegers)31 +b(\(with)g(unlimited)e(precision\),)75 1137 y Fo(\017)60 +b Fp(Rational)32 b(n)m(um)m(b)s(ers,)75 1281 y Fo(\017)60 +b Fp(Floating-p)s(oin)m(t)33 b(n)m(um)m(b)s(ers:)229 +1425 y Fo(\000)60 b Fp(Short)30 b(\015oat,)229 1569 y +Fo(\000)60 b Fp(Single)31 b(\015oat,)229 1713 y Fo(\000)60 +b Fp(Double)31 b(\015oat,)229 1857 y Fo(\000)60 b Fp(Long)31 +b(\015oat)g(\(with)f(unlimited)f(precision\),)75 2001 +y Fo(\017)60 b Fp(Complex)29 b(n)m(um)m(b)s(ers,)75 2145 +y Fo(\017)60 b Fp(Mo)s(dular)30 b(in)m(tegers)i(\(in)m(tegers)g(mo)s +(dulo)c(a)j(\014xed)f(in)m(teger\),)75 2289 y Fo(\017)60 +b Fp(Univ)-5 b(ariate)32 b(p)s(olynomials.)0 2583 y(The)38 +b(subt)m(yp)s(es)g(of)h(the)g(complex)f(n)m(um)m(b)s(ers)f(among)h +(these)h(are)g(exactly)i(the)e(t)m(yp)s(es)g(of)g(n)m(um)m(b)s(ers)d +(kno)m(wn)i(to)0 2707 y(the)29 b(Common)d(Lisp)j(language.)41 +b(Therefore)29 b Fn(CLN)f Fp(can)h(b)s(e)f(used)g(for)h(Common)d(Lisp)i +(implemen)m(tations,)h(giving)0 2832 y(`)p Fn(CLN)p Fp(')h(another)h +(meaning:)40 b(it)30 b(b)s(ecomes)g(an)g(abbreviation)h(of)g(\\Common)d +(Lisp)i(Num)m(b)s(ers".)0 3106 y(The)g(CLN)g(pac)m(k)-5 +b(age)32 b(implemen)m(ts)75 3380 y Fo(\017)60 b Fp(Elemen)m(tary)30 +b(functions)g(\()p Fn(+)p Fp(,)h Fn(-)p Fp(,)f Fn(*)p +Fp(,)g Fn(/)p Fp(,)h Fn(sqrt)p Fp(,)e(comparisons,)h +Fl(:)15 b(:)g(:)q Fp(\),)75 3524 y Fo(\017)60 b Fp(Logical)32 +b(functions)e(\(logical)j Fn(and)p Fp(,)d Fn(or)p Fp(,)g +Fn(not)p Fp(,)g Fl(:)15 b(:)g(:)q Fp(\),)75 3668 y Fo(\017)60 +b Fp(T)-8 b(ranscenden)m(tal)40 b(functions)f(\(exp)s(onen)m(tial,)k +(logarithmic,)f(trigonometric,)g(h)m(yp)s(erb)s(olic)d(functions)g(and) +180 3792 y(their)30 b(in)m(v)m(erse)i(functions\).)0 +4086 y(CLN)e(is)g(a)h(C)p Fn(++)f Fp(library)-8 b(.)40 +b(Using)31 b(C)p Fn(++)e Fp(as)i(an)f(implemen)m(tation)g(language)i +(pro)m(vides)75 4360 y Fo(\017)60 b Fp(e\016ciency:)42 +b(it)31 b(compiles)f(to)h(mac)m(hine)f(co)s(de,)75 4504 +y Fo(\017)60 b Fp(t)m(yp)s(e)33 b(safet)m(y:)48 b(the)33 +b(C)p Fn(++)f Fp(compiler)h(kno)m(ws)f(ab)s(out)h(the)g(n)m(um)m(b)s +(er)e(t)m(yp)s(es)i(and)g(complains)f(if,)i(for)f(example,)180 +4628 y(y)m(ou)e(try)f(to)h(assign)g(a)g(\015oat)g(to)g(an)f(in)m(teger) +i(v)-5 b(ariable.)75 4773 y Fo(\017)60 b Fp(algebraic)32 +b(syn)m(tax:)41 b(Y)-8 b(ou)31 b(can)g(use)f(the)h Fn(+)p +Fp(,)f Fn(-)p Fp(,)g Fn(*)p Fp(,)g Fn(=)p Fp(,)h Fn(==)p +Fp(,)f Fl(:)15 b(:)g(:)31 b Fp(op)s(erators)g(as)f(in)g(C)g(or)h(C)p +Fn(++)p Fp(.)0 5066 y(CLN)f(is)g(memory)f(e\016cien)m(t:)75 +5340 y Fo(\017)60 b Fp(Small)30 b(in)m(tegers)h(and)f(short)g(\015oats) +h(are)g(immediate,)e(not)i(heap)f(allo)s(cated.)p eop +%%Page: 2 4 +2 3 bop 0 -116 a Fp(Chapter)30 b(1:)41 b(In)m(tro)s(duction)2892 +b(2)75 366 y Fo(\017)60 b Fp(Heap-allo)s(cated)40 b(memory)35 +b(is)i(reclaimed)g(through)f(an)h(automatic,)j(non-in)m(terruptiv)m(e)d +(garbage)i(collec-)180 491 y(tion.)0 790 y(CLN)30 b(is)g(sp)s(eed)g +(e\016cien)m(t:)75 1064 y Fo(\017)60 b Fp(The)27 b(k)m(ernel)h(of)f +(CLN)g(has)g(b)s(een)g(written)g(in)g(assem)m(bly)g(language)h(for)f +(some)g(CPUs)g(\()p Fn(i386)p Fp(,)g Fn(m68k)p Fp(,)g +Fn(sparc)p Fp(,)180 1188 y Fn(mips)p Fp(,)i Fn(arm)p +Fp(\).)75 1338 y Fo(\017)60 b Fp(On)30 b(all)h(CPUs,)f(CLN)g(uses)g +(the)g(sup)s(ere\016cien)m(t)h(lo)m(w-lev)m(el)i(routines)d(from)f(GNU) +i(GMP)g(v)m(ersion)g(2.)75 1487 y Fo(\017)60 b Fp(It)28 +b(uses)g(Karatsuba)g(m)m(ultiplication,)i(whic)m(h)e(is)g(signi\014can) +m(tly)i(faster)e(for)g(large)h(n)m(um)m(b)s(ers)d(than)i(the)h(stan-) +180 1612 y(dard)g(m)m(ultiplication)j(algorithm.)75 1761 +y Fo(\017)60 b Fp(F)-8 b(or)41 b(v)m(ery)g(large)h(n)m(um)m(b)s(ers)c +(\(more)h(than)i(12000)h(decimal)f(digits\),)j(it)d(uses)f(Sc)m(h\177) +-45 b(onhage-Strassen)41 b(m)m(ul-)180 1886 y(tiplication,)k(whic)m(h)c +(is)f(an)h(asymptotically)h(optimal)e(m)m(ultiplication)i(algorithm,)h +(for)e(m)m(ultiplication,)180 2010 y(division)30 b(and)g(radix)g(con)m +(v)m(ersion.)0 2309 y(CLN)g(aims)g(at)h(b)s(eing)f(easily)h(in)m +(tegrated)h(in)m(to)g(larger)f(soft)m(w)m(are)g(pac)m(k)-5 +b(ages:)75 2583 y Fo(\017)60 b Fp(The)30 b(garbage)i(collection)h(imp)s +(oses)28 b(no)j(burden)d(on)i(the)h(main)e(application.)75 +2733 y Fo(\017)60 b Fp(The)30 b(library)g(pro)m(vides)g(ho)s(oks)g(for) +g(memory)f(allo)s(cation)j(and)e(exceptions.)p eop +%%Page: 3 5 +3 4 bop 0 -116 a Fp(Chapter)30 b(2:)41 b(Installation)2939 +b(3)0 366 y Fm(2)80 b(Installation)0 808 y Fp(This)30 +b(section)h(describ)s(es)f(ho)m(w)g(to)h(install)g(the)g(CLN)f(pac)m(k) +-5 b(age)32 b(on)f(y)m(our)f(system.)0 1379 y Fq(2.1)68 +b(Prerequisites)0 1917 y Fk(2.1.1)63 b(C)p Fj(++)30 b +Fk(compiler)0 2204 y Fp(T)-8 b(o)27 b(build)f(CLN,)g(y)m(ou)h(need)f(a) +h(C)p Fn(++)f Fp(compiler.)39 b(Actually)-8 b(,)29 b(y)m(ou)e(need)g +(GNU)g Fn(g++)i(2.7.0)c Fp(or)i(new)m(er.)39 b(On)26 +b(HPP)-8 b(A,)0 2329 y(y)m(ou)31 b(need)f(GNU)h Fn(g++)e(2.8.0)g +Fp(or)i(new)m(er.)40 b(I)30 b(recommend)f(GNU)i Fn(egcs)e(1.1)g +Fp(or)i(new)m(er.)0 2616 y(The)44 b(follo)m(wing)j(C)p +Fn(++)d Fp(features)h(are)g(used:)69 b(classes,)50 b(mem)m(b)s(er)42 +b(functions,)49 b(o)m(v)m(erloading)e(of)e(functions)g(and)0 +2741 y(op)s(erators,)31 b(constructors)f(and)g(destructors,)h(inline,)f +(const,)i(m)m(ultiple)e(inheritance,)h(templates.)0 3028 +y(The)f(follo)m(wing)i(C)p Fn(++)d Fp(features)i(are)g(not)f(used:)40 +b Fn(new)p Fp(,)30 b Fn(delete)p Fp(,)f(virtual)h(inheritance,)i +(exceptions.)0 3316 y(CLN)38 b(relies)h(on)f(semi-automatic)h(ordering) +f(of)g(initializations)j(of)e(static)g(and)f(global)i(v)-5 +b(ariables,)41 b(a)d(feature)0 3441 y(whic)m(h)30 b(I)g(could)h +(implemen)m(t)e(for)h(GNU)h(g)p Fn(++)f Fp(only)-8 b(.)0 +3978 y Fk(2.1.2)63 b(Mak)m(e)29 b(utilit)m(y)0 4266 y +Fp(T)-8 b(o)31 b(build)e(CLN,)h(y)m(ou)h(also)g(need)g(to)g(ha)m(v)m(e) +g(GNU)g Fn(make)e Fp(installed.)0 4803 y Fk(2.1.3)63 +b(Sed)30 b(utilit)m(y)0 5091 y Fp(T)-8 b(o)36 b(build)e(CLN)g(on)h +(HP-UX,)h(y)m(ou)g(also)g(need)f(to)g(ha)m(v)m(e)i(GNU)e +Fn(sed)g Fp(installed.)55 b(This)34 b(is)i(b)s(ecause)f(the)g(libto)s +(ol)0 5215 y(script,)c(whic)m(h)f(creates)i(the)f(CLN)f(library)-8 +b(,)31 b(relies)g(on)g Fn(sed)p Fp(,)f(and)g(the)g(v)m(endor's)h +Fn(sed)f Fp(utilit)m(y)h(on)g(these)g(systems)0 5340 +y(is)f(to)s(o)i(limited.)p eop +%%Page: 4 6 +4 5 bop 0 -116 a Fp(Chapter)30 b(2:)41 b(Installation)2939 +b(4)0 366 y Fq(2.2)68 b(Building)31 b(the)f(library)0 +647 y Fp(As)g(with)g(an)m(y)h(auto)s(con\014guring)f(GNU)h(soft)m(w)m +(are,)h(installation)h(is)d(as)h(easy)g(as)f(this:)240 +906 y Fn($)47 b(./configure)240 1010 y($)g(make)240 1114 +y($)g(make)g(check)0 1394 y Fp(If)30 b(on)g(y)m(our)g(system,)g(`)p +Fn(make)p Fp(')g(is)g(not)h(GNU)g Fn(make)p Fp(,)e(y)m(ou)i(ha)m(v)m(e) +h(to)f(use)f(`)p Fn(gmake)p Fp(')f(instead)i(of)g(`)p +Fn(make)p Fp(')e(ab)s(o)m(v)m(e.)0 1675 y(The)34 b Fn(configure)f +Fp(command)f(c)m(hec)m(ks)37 b(out)e(some)f(features)h(of)g(y)m(our)g +(system)f(and)g(C)p Fn(++)g Fp(compiler)h(and)f(builds)0 +1799 y(the)e Fn(Makefile)p Fp(s.)42 b(The)31 b Fn(make)f +Fp(command)f(builds)i(the)g(library)-8 b(.)45 b(This)30 +b(step)i(ma)m(y)f(tak)m(e)i(4)f(hours)e(on)i(an)f(a)m(v)m(erage)0 +1924 y(w)m(orkstation.)78 b(The)42 b Fn(make)29 b(check)41 +b Fp(runs)f(some)i(test)h(to)g(c)m(hec)m(k)h(that)f(no)f(imp)s(ortan)m +(t)f(subroutine)h(has)g(b)s(een)0 2048 y(miscompiled.)0 +2329 y(The)30 b Fn(configure)e Fp(command)g(accepts)k(options.)41 +b(T)-8 b(o)30 b(get)i(a)f(summary)c(of)j(them,)g(try)240 +2588 y Fn($)47 b(./configure)e(--help)0 2868 y Fp(Some)29 +b(of)i(the)g(options)f(are)h(explained)g(in)f(detail)h(in)f(the)h(`)p +Fn(INSTALL.generic)p Fp(')26 b(\014le.)0 3149 y(Y)-8 +b(ou)28 b(can)g(sp)s(ecify)g(the)g(C)f(compiler,)h(the)g(C)p +Fn(++)f Fp(compiler)g(and)g(their)h(options)g(through)f(the)h(follo)m +(wing)i(en)m(viron-)0 3273 y(men)m(t)g(v)-5 b(ariables)31 +b(when)e(running)g Fn(configure)p Fp(:)0 3585 y Fn(CC)384 +b Fp(Sp)s(eci\014es)30 b(the)g(C)g(compiler.)0 3772 y +Fn(CFLAGS)192 b Fp(Flags)32 b(to)f(b)s(e)f(giv)m(en)h(to)g(the)g(C)f +(compiler)f(when)h(compiling)g(programs)f(\(not)i(when)e(linking\).)0 +3959 y Fn(CXX)336 b Fp(Sp)s(eci\014es)30 b(the)g(C)p +Fn(++)g Fp(compiler.)0 4146 y Fn(CXXFLAGS)96 b Fp(Flags)32 +b(to)f(b)s(e)f(giv)m(en)h(to)g(the)g(C)p Fn(++)e Fp(compiler)h(when)f +(compiling)h(programs)f(\(not)i(when)f(linking\).)0 4458 +y(Examples:)240 4717 y Fn($)47 b(CC="gcc")f(CFLAGS="-O")f(CXX="g++")g +(CXXFLAGS="-O")f(./configure)240 4821 y($)j(CC="gcc)f(-V)h(2.7.2")g +(CFLAGS="-O)e(-g")h(\\)335 4925 y(CXX="g++)g(-V)h(2.7.2")f +(CXXFLAGS="-O)f(-g")i(./configure)240 5029 y($)g(CC="gcc)f(-V)h(2.8.1") +g(CFLAGS="-O)e(-fno-exceptions")e(\\)335 5132 y(CXX="g++)j(-V)h(2.8.1") +f(CXXFLAGS="-O)f(-fno-exceptions")e(./configure)240 5236 +y($)k(CC="gcc)f(-V)h(egcs-2.91.60")e(CFLAGS="-O2)f(-fno-exceptions")g +(\\)335 5340 y(CXX="g++)i(-V)h(egcs-2.91.60")d(CFLAGS="-O2)h +(-fno-exceptions")e(./configure)p eop +%%Page: 5 7 +5 6 bop 0 -116 a Fp(Chapter)30 b(2:)41 b(Installation)2939 +b(5)0 366 y(Note)28 b(that)g(for)f(these)h(en)m(vironmen)m(t)e(v)-5 +b(ariables)28 b(to)g(tak)m(e)h(e\013ect,)g(y)m(ou)e(ha)m(v)m(e)i(to)f +(set)f(them)f(\(assuming)g(a)i(Bourne-)0 491 y(compatible)i(shell\))f +(on)g(the)h(same)f(line)g(as)h(the)f Fn(configure)e Fp(command.)38 +b(If)29 b(y)m(ou)g(made)f(the)i(settings)g(in)f(earlier)0 +616 y(shell)f(commands,)e(y)m(ou)i(ha)m(v)m(e)g(to)h +Fn(export)d Fp(the)h(en)m(vironmen)m(t)g(v)-5 b(ariables)29 +b(b)s(efore)e(calling)i Fn(configure)p Fp(.)37 b(In)27 +b(a)h Fn(csh)0 740 y Fp(shell,)j(y)m(ou)g(ha)m(v)m(e)g(to)g(use)f(the)h +(`)p Fn(setenv)p Fp(')e(command)f(for)i(setting)i(eac)m(h)f(of)g(the)f +(en)m(vironmen)m(t)g(v)-5 b(ariables.)0 1017 y(On)34 +b(Lin)m(ux,)i Fn(g++)e Fp(needs)g(15)i(MB)f(to)h(compile)f(the)g +(tests.)55 b(So)34 b(y)m(ou)i(should)d(b)s(etter)i(ha)m(v)m(e)h(17)g +(MB)g(sw)m(ap)e(space)0 1142 y(and)c(1)h(MB)g(ro)s(om)e(in)h($TMPDIR.)0 +1419 y(If)d(y)m(ou)h(use)g Fn(g++)e Fp(v)m(ersion)i(2.7.x,)i(don't)e +(add)f(`)p Fn(-O2)p Fp(')g(to)i(the)f(CXXFLA)m(GS,)g(b)s(ecause)g(`)p +Fn(g++)h(-O)p Fp(')f(generates)h(b)s(etter)0 1544 y(co)s(de)i(for)f +(CLN)g(than)g(`)p Fn(g++)g(-O2)p Fp('.)0 1821 y(If)40 +b(y)m(ou)i(use)e Fn(g++)g Fp(v)m(ersion)h(2.8.x)i(or)e(egcs-2.91.x)j +(\(a.k.a.)73 b(egcs-1.1\))44 b(or)d(gcc-2.95.x,)47 b(I)41 +b(recommend)d(adding)0 1946 y(`)p Fn(-fno-exceptions)p +Fp(')27 b(to)k(the)f(CXXFLA)m(GS.)i(This)d(will)i(lik)m(ely)h(generate) +g(b)s(etter)e(co)s(de.)0 2223 y(If)50 b(y)m(ou)g(use)g +Fn(g++)g Fp(v)m(ersion)g(egcs-2.91.x)k(\(egcs-1.1\))f(or)d(gcc-2.95.x)k +(on)c(Sparc,)55 b(add)50 b(either)g(`)p Fn(-O)p Fp(')g(or)h(`)p +Fn(-O2)0 2347 y(-fno-schedule-insns)p Fp(')21 b(to)26 +b(the)g(CXXFLA)m(GS.)g(With)g(full)g(`)p Fn(-O2)p Fp(',)g +Fn(g++)f Fp(miscompiles)f(the)i(division)g(routines.)0 +2472 y(Also,)31 b(for)f({enable-shared)h(to)g(w)m(ork,)g(y)m(ou)g(need) +f(egcs-1.1.2)k(or)c(new)m(er.)0 2749 y(On)23 b(MIPS)h(\(SGI)g(Irix)g +(6\),)i(pass)e(option)g Fn(--without-gmp)d Fp(to)k(con\014gure.)38 +b(gmp)23 b(do)s(es)h(not)g(w)m(ork)g(when)f(compiled)0 +2874 y(in)30 b(`)p Fn(n32)p Fp(')g(binary)g(format)f(on)i(Irix.)0 +3151 y(By)36 b(default,)i(only)e(a)h(static)h(library)d(is)h(built.)58 +b(Y)-8 b(ou)36 b(can)h(build)e(CLN)g(as)i(a)f(shared)f(library)h(to)s +(o,)i(b)m(y)e(calling)0 3275 y Fn(configure)43 b Fp(with)i(the)g +(option)h(`)p Fn(--enable-shared)p Fp('.)82 b(T)-8 b(o)46 +b(get)g(it)g(built)f(as)h(a)f(shared)g(library)g(only)-8 +b(,)50 b(call)0 3400 y Fn(configure)28 b Fp(with)i(the)g(options)h(`)p +Fn(--enable-shared)c(--disable-static)p Fp('.)0 3677 +y(If)j(y)m(ou)g(use)g Fn(g++)f Fp(v)m(ersion)i(egcs-2.91.x)i +(\(egcs-1.1\))h(on)c(Sparc,)f(y)m(ou)i(cannot)g(use)e(`)p +Fn(--enable-shared)p Fp(')e(b)s(ecause)0 3802 y Fn(g++)i +Fp(w)m(ould)i(miscompile)e(parts)h(of)g(the)h(library)-8 +b(.)0 4280 y Fq(2.3)68 b(Installing)32 b(the)f(library)0 +4557 y Fp(As)f(with)g(an)m(y)h(auto)s(con\014guring)f(GNU)h(soft)m(w)m +(are,)h(installation)h(is)d(as)h(easy)g(as)f(this:)240 +4814 y Fn($)47 b(make)g(install)0 5091 y Fp(The)20 b(`)p +Fn(make)29 b(install)p Fp(')19 b(command)f(installs)j(the)f(library)g +(and)g(the)g(include)g(\014les)h(in)m(to)g(public)e(places)i(\(`)p +Fn(/usr/local/lib/)p Fp(')0 5215 y(and)28 b(`)p Fn(/usr/local/include/) +p Fp(',)d(if)k(y)m(ou)h(ha)m(v)m(en't)g(sp)s(eci\014ed)f(a)g +Fn(--prefix)e Fp(option)j(to)f Fn(configure)p Fp(\).)39 +b(This)28 b(step)0 5340 y(ma)m(y)i(require)g(sup)s(eruser)e +(privileges.)p eop +%%Page: 6 8 +6 7 bop 0 -116 a Fp(Chapter)30 b(2:)41 b(Installation)2939 +b(6)0 366 y(If)40 b(y)m(ou)i(ha)m(v)m(e)g(already)f(built)g(the)g +(library)f(and)g(wish)g(to)i(install)g(it,)i(but)c(didn't)g(sp)s(ecify) +h Fn(--prefix=)p Fl(:)15 b(:)g(:)39 b Fp(at)0 491 y(con\014gure)g +(time,)i(just)d(re-run)g Fn(configure)p Fp(,)h(giving)h(it)f(the)g +(same)g(options)g(as)g(the)g(\014rst)f(time,)j(plus)d(the)i +Fn(--)0 616 y(prefix=)p Fl(:)15 b(:)g(:)29 b Fp(option.)0 +1064 y Fq(2.4)68 b(Cleaning)32 b(up)0 1338 y Fp(Y)-8 +b(ou)31 b(can)g(remo)m(v)m(e)f(system-dep)s(enden)m(t)f(\014les)i +(generated)g(b)m(y)f Fn(make)f Fp(through)240 1591 y +Fn($)47 b(make)g(clean)0 1865 y Fp(Y)-8 b(ou)28 b(can)f(remo)m(v)m(e)h +(all)g(\014les)f(generated)h(b)m(y)f Fn(make)p Fp(,)g(th)m(us)g(rev)m +(erting)h(to)g(a)g(virgin)f(distribution)f(of)i(CLN,)f(through)240 +2118 y Fn($)47 b(make)g(distclean)p eop +%%Page: 7 9 +7 8 bop 0 -116 a Fp(Chapter)30 b(3:)41 b(Ordinary)29 +b(n)m(um)m(b)s(er)f(t)m(yp)s(es)2457 b(7)0 366 y Fm(3)80 +b(Ordinary)32 b(n)l(um)l(b)t(er)27 b(t)l(yp)t(es)0 809 +y Fp(CLN)j(implemen)m(ts)f(the)h(follo)m(wing)i(class)f(hierarc)m(h)m +(y:)1385 1076 y Fn(Number)1338 1180 y(cl_number)1242 +1283 y()1481 1387 y(|)1481 1491 y(|)1051 +1595 y(Real)47 b(or)g(complex)f(number)1385 1698 y(cl_N)1242 +1802 y()1481 1906 y(|)1481 2010 y(|)1242 +2114 y(Real)h(number)1385 2217 y(cl_R)1290 2321 y()1481 +2425 y(|)526 2529 y(+-------------------+-----)o(---)o(----)o(----)o +(---)o(+)526 2632 y(|)1861 b(|)240 2736 y(Rational)46 +b(number)1000 b(Floating-point)44 b(number)431 2840 y(cl_RA)1669 +b(cl_F)240 2944 y()1237 b()526 +3048 y(|)1861 b(|)526 3151 y(|)859 b(+-------------+----------)o(---+)o +(---)o(----)o(----)o(--+)383 3255 y(Integer)714 b(|)620 +b(|)h(|)f(|)431 3359 y(cl_I)572 b(Short-Float)140 b(Single-Float)92 +b(Double-Float)140 b(Long-Float)288 3463 y()378 +b(cl_SF)428 b(cl_FF)g(cl_DF)g(cl_LF)1147 3566 y()44 +b()g()g()0 3854 +y Fp(The)36 b(base)g(class)h Fn(cl_number)d Fp(is)i(an)g(abstract)h +(base)f(class.)59 b(It)36 b(is)g(not)h(useful)e(to)i(declare)g(a)g(v)-5 +b(ariable)37 b(of)f(this)0 3979 y(t)m(yp)s(e)f(except)i(if)e(y)m(ou)g +(w)m(an)m(t)h(to)g(completely)g(disable)g(compile-time)f(t)m(yp)s(e)g +(c)m(hec)m(king)i(and)e(use)g(run-time)f(t)m(yp)s(e)0 +4103 y(c)m(hec)m(king)e(instead.)0 4391 y(The)25 b(class)h +Fn(cl_N)f Fp(comprises)f(real)i(and)f(complex)g(n)m(um)m(b)s(ers.)37 +b(There)25 b(is)g(no)h(sp)s(ecial)g(class)g(for)f(complex)g(n)m(um)m(b) +s(ers)0 4515 y(since)31 b(complex)f(n)m(um)m(b)s(ers)e(with)i +(imaginary)g(part)g Fn(0)g Fp(are)h(automatically)h(con)m(v)m(erted)g +(to)f(real)g(n)m(um)m(b)s(ers.)0 4803 y(The)f(class)h +Fn(cl_R)e Fp(comprises)h(real)h(n)m(um)m(b)s(ers)d(of)i(di\013eren)m(t) +h(kinds.)40 b(It)30 b(is)h(an)f(abstract)h(class.)0 5091 +y(The)41 b(class)i Fn(cl_RA)e Fp(comprises)f(exact)k(real)e(n)m(um)m(b) +s(ers:)62 b(rational)43 b(n)m(um)m(b)s(ers,)f(including)g(in)m(tegers.) +76 b(There)42 b(is)0 5215 y(no)34 b(sp)s(ecial)g(class)h(for)f(non-in)m +(tegral)h(rational)h(n)m(um)m(b)s(ers)31 b(since)j(rational)i(n)m(um)m +(b)s(ers)31 b(with)j(denominator)f Fn(1)h Fp(are)0 5340 +y(automatically)e(con)m(v)m(erted)g(to)f(in)m(tegers.)p +eop +%%Page: 8 10 +8 9 bop 0 -116 a Fp(Chapter)30 b(3:)41 b(Ordinary)29 +b(n)m(um)m(b)s(er)f(t)m(yp)s(es)2457 b(8)0 366 y(The)30 +b(class)h Fn(cl_F)e Fp(implemen)m(ts)g(\015oating-p)s(oin)m(t)j(appro)m +(ximations)e(to)h(real)g(n)m(um)m(b)s(ers.)38 b(It)31 +b(is)f(an)g(abstract)i(class.)0 802 y Fq(3.1)68 b(Exact)31 +b(n)l(um)l(b)t(ers)0 1076 y Fp(Some)42 b(n)m(um)m(b)s(ers)e(are)j +(represen)m(ted)f(as)h(exact)h(n)m(um)m(b)s(ers:)63 b(there)42 +b(is)h(no)f(loss)h(of)g(information)f(when)f(suc)m(h)i(a)0 +1200 y(n)m(um)m(b)s(er)25 b(is)i(con)m(v)m(erted)i(from)d(its)h +(mathematical)h(v)-5 b(alue)28 b(to)g(its)f(in)m(ternal)h(represen)m +(tation.)41 b(On)26 b(exact)j(n)m(um)m(b)s(ers,)0 1325 +y(the)i(elemen)m(tary)f(op)s(erations)h(\()p Fn(+)p Fp(,)g +Fn(-)p Fp(,)f Fn(*)p Fp(,)g Fn(/)p Fp(,)h(comparisons,)e +Fl(:)15 b(:)g(:)q Fp(\))31 b(compute)f(the)g(completely)h(correct)h +(result.)0 1599 y(In)e(CLN,)g(the)g(exact)i(n)m(um)m(b)s(ers)c(are:)75 +1873 y Fo(\017)60 b Fp(rational)32 b(n)m(um)m(b)s(ers)c(\(including)i +(in)m(tegers\),)75 2019 y Fo(\017)60 b Fp(complex)30 +b(n)m(um)m(b)s(ers)e(whose)i(real)h(and)f(imaginary)g(parts)g(are)h(b)s +(oth)e(rational)j(n)m(um)m(b)s(ers.)0 2314 y(Rational)26 +b(n)m(um)m(b)s(ers)d(are)i(alw)m(a)m(ys)h(normalized)e(to)i(the)f(form) +e Fi(n)m(umerator)7 b Fn(/)p Fi(denominator)29 b Fp(where)24 +b(the)h(n)m(umerator)0 2439 y(and)e(denominator)f(are)i(coprime)e(in)m +(tegers)i(and)f(the)g(denominator)g(is)g(p)s(ositiv)m(e.)39 +b(If)23 b(the)g(resulting)h(denominator)0 2564 y(is)30 +b Fn(1)p Fp(,)h(the)f(rational)i(n)m(um)m(b)s(er)c(is)i(con)m(v)m +(erted)i(to)f(an)g(in)m(teger.)0 2838 y(Small)d(in)m(tegers)j(\(t)m +(ypically)g(in)e(the)g(range)h Fn(-2^30)p Fl(:)15 b(:)g(:)p +Fn(2^30-1)p Fp(,)28 b(for)h(32-bit)h(mac)m(hines\))f(are)h(esp)s +(ecially)g(e\016cien)m(t,)0 2962 y(b)s(ecause)c(they)g(consume)f(no)h +(heap)g(allo)s(cation.)41 b(Otherwise)26 b(the)g(distinction)h(b)s(et)m +(w)m(een)f(these)h(immediate)e(in)m(te-)0 3087 y(gers)31 +b(\(called)h(\\\014xn)m(ums"\))d(and)g(heap)i(allo)s(cated)h(in)m +(tegers)g(\(called)g(\\bign)m(ums"\))d(is)i(completely)g(transparen)m +(t.)0 3522 y Fq(3.2)68 b(Floating-p)t(oin)l(t)32 b(n)l(um)l(b)t(ers)0 +3796 y Fp(Not)37 b(all)g(real)g(n)m(um)m(b)s(ers)d(can)j(b)s(e)e +(represen)m(ted)i(exactly)-8 b(.)60 b(\(There)36 b(is)h(an)f(easy)h +(mathematical)f(pro)s(of)g(for)g(this:)0 3920 y(Only)31 +b(a)h(coun)m(table)h(set)f(of)g(n)m(um)m(b)s(ers)d(can)j(b)s(e)f +(stored)g(exactly)j(in)d(a)h(computer,)f(ev)m(en)h(if)g(one)g(assumes)e +(that)i(it)0 4045 y(has)f(unlimited)e(storage.)45 b(But)31 +b(there)g(are)g(uncoun)m(tably)g(man)m(y)f(real)i(n)m(um)m(b)s(ers.\)) +41 b(So)31 b(some)f(appro)m(ximation)h(is)0 4169 y(needed.)40 +b(CLN)30 b(implemen)m(ts)f(ordinary)h(\015oating-p)s(oin)m(t)h(n)m(um)m +(b)s(ers,)e(with)h(man)m(tissa)g(and)g(exp)s(onen)m(t.)0 +4443 y(The)c(elemen)m(tary)i(op)s(erations)f(\()p Fn(+)p +Fp(,)g Fn(-)p Fp(,)h Fn(*)p Fp(,)f Fn(/)p Fp(,)h Fl(:)15 +b(:)g(:)q Fp(\))27 b(only)g(return)e(appro)m(ximate)i(results.)40 +b(F)-8 b(or)27 b(example,)g(the)g(v)-5 b(alue)0 4568 +y(of)31 b(the)h(expression)f Fn(\(cl_F\))d(0.3)i(+)g(\(cl_F\))f(0.4)h +Fp(prin)m(ts)h(as)g(`)p Fn(0.70000005)p Fp(',)e(not)j(as)f(`)p +Fn(0.7)p Fp('.)43 b(Rounding)30 b(errors)0 4692 y(lik)m(e)i(this)e(one) +h(are)f(inevitable)i(when)d(computing)h(with)g(\015oating-p)s(oin)m(t)i +(n)m(um)m(b)s(ers.)0 4966 y(Nev)m(ertheless,)41 b(CLN)36 +b(rounds)g(the)h(\015oating-p)s(oin)m(t)i(results)e(of)g(the)g(op)s +(erations)h Fn(+)p Fp(,)h Fn(-)p Fp(,)f Fn(*)p Fp(,)h +Fn(/)p Fp(,)g Fn(sqrt)d Fp(according)0 5091 y(to)c(the)f(\\round-to-ev) +m(en")h(rule:)42 b(It)31 b(\014rst)f(computes)g(the)h(exact)h +(mathematical)f(result)g(and)g(then)f(returns)g(the)0 +5215 y(\015oating-p)s(oin)m(t)37 b(n)m(um)m(b)s(er)c(whic)m(h)i(is)h +(nearest)g(to)h(this.)56 b(If)35 b(t)m(w)m(o)i(\015oating-p)s(oin)m(t)g +(n)m(um)m(b)s(ers)c(are)j(equally)g(distan)m(t)0 5340 +y(from)29 b(the)h(ideal)i(result,)e(the)h(one)f(with)g(a)h +Fn(0)f Fp(in)g(its)h(least)h(signi\014can)m(t)f(man)m(tissa)f(bit)h(is) +f(c)m(hosen.)p eop +%%Page: 9 11 +9 10 bop 0 -116 a Fp(Chapter)30 b(3:)41 b(Ordinary)29 +b(n)m(um)m(b)s(er)f(t)m(yp)s(es)2457 b(9)0 366 y(Similarly)-8 +b(,)48 b(testing)d(\015oating)g(p)s(oin)m(t)f(n)m(um)m(b)s(ers)e(for)i +(equalit)m(y)i(`)p Fn(x)30 b(==)g(y)p Fp(')44 b(is)h(gam)m(bling)f +(with)g(random)e(errors.)0 491 y(Better)32 b(c)m(hec)m(k)g(for)e(`)p +Fn(abs\(x)f(-)h(y\))g(<)g(epsilon)p Fp(')f(for)h(some)f(w)m(ell-c)m +(hosen)k Fn(epsilon)p Fp(.)0 850 y(Floating)f(p)s(oin)m(t)f(n)m(um)m(b) +s(ers)d(come)i(in)g(four)g(\015a)m(v)m(ors:)75 1209 y +Fo(\017)60 b Fp(Short)24 b(\015oats,)j(t)m(yp)s(e)d Fn(cl_SF)p +Fp(.)38 b(They)24 b(ha)m(v)m(e)i(1)f(sign)g(bit,)h(8)f(exp)s(onen)m(t)f +(bits)h(\(including)g(the)g(exp)s(onen)m(t's)f(sign\),)180 +1333 y(and)30 b(17)h(man)m(tissa)f(bits)h(\(including)f(the)g +(\\hidden")g(bit\).)41 b(They)30 b(don't)h(consume)e(heap)h(allo)s +(cation.)75 1568 y Fo(\017)60 b Fp(Single)40 b(\015oats,)i(t)m(yp)s(e)e +Fn(cl_FF)p Fp(.)66 b(They)39 b(ha)m(v)m(e)h(1)g(sign)g(bit,)h(8)f(exp)s +(onen)m(t)g(bits)f(\(including)g(the)h(exp)s(onen)m(t's)180 +1692 y(sign\),)j(and)c(24)h(man)m(tissa)g(bits)g(\(including)f(the)h +(\\hidden")f(bit\).)69 b(In)39 b(CLN,)h(they)g(are)g(represen)m(ted)g +(as)180 1817 y(IEEE)g(single-precision)h(\015oating)g(p)s(oin)m(t)g(n)m +(um)m(b)s(ers.)68 b(This)39 b(corresp)s(onds)g(closely)j(to)f(the)f +(C/C)p Fn(++)g Fp(t)m(yp)s(e)180 1941 y(`)p Fn(float)p +Fp('.)75 2176 y Fo(\017)60 b Fp(Double)34 b(\015oats,)i(t)m(yp)s(e)e +Fn(cl_DF)p Fp(.)50 b(They)34 b(ha)m(v)m(e)h(1)f(sign)g(bit,)h(11)g(exp) +s(onen)m(t)f(bits)g(\(including)g(the)g(exp)s(onen)m(t's)180 +2300 y(sign\),)43 b(and)c(53)h(man)m(tissa)g(bits)g(\(including)f(the)h +(\\hidden")f(bit\).)69 b(In)39 b(CLN,)h(they)g(are)g(represen)m(ted)g +(as)180 2425 y(IEEE)d(double-precision)g(\015oating)h(p)s(oin)m(t)f(n)m +(um)m(b)s(ers.)59 b(This)36 b(corresp)s(onds)g(closely)j(to)f(the)f +(C/C)p Fn(++)g Fp(t)m(yp)s(e)180 2549 y(`)p Fn(double)p +Fp('.)75 2784 y Fo(\017)60 b Fp(Long)23 b(\015oats,)i(t)m(yp)s(e)e +Fn(cl_LF)p Fp(.)37 b(They)22 b(ha)m(v)m(e)i(1)f(sign)g(bit,)i(32)e(exp) +s(onen)m(t)g(bits)g(\(including)f(the)h(exp)s(onen)m(t's)g(sign\),)180 +2908 y(and)k(n)h(man)m(tissa)g(bits)g(\(including)g(the)g(\\hidden")g +(bit\),)h(where)e(n)h Fn(>)p Fp(=)f(64.)41 b(The)28 b(precision)g(of)g +(a)h(long)f(\015oat)180 3033 y(is)i(unlimited,)g(but)f(once)i(created,) +h(a)f(long)g(\015oat)g(has)f(a)h(\014xed)f(precision.)40 +b(\(No)32 b(\\lazy)g(recomputation".\))0 3501 y(Of)27 +b(course,)h(computations)f(with)g(long)g(\015oats)h(are)g(more)e(exp)s +(ensiv)m(e)h(than)g(those)h(with)f(smaller)g(\015oating-p)s(oin)m(t)0 +3626 y(formats.)0 3985 y(CLN)40 b(do)s(es)g(not)h(implemen)m(t)e +(features)h(lik)m(e)i(NaNs,)i(denormalized)c(n)m(um)m(b)s(ers)e(and)h +(gradual)i(under\015o)m(w.)69 b(If)0 4109 y(the)31 b(exp)s(onen)m(t)h +(range)f(of)g(some)g(\015oating-p)s(oin)m(t)h(t)m(yp)s(e)g(is)f(to)s(o) +h(limited)f(for)g(y)m(our)g(application,)i(c)m(ho)s(ose)f(another)0 +4234 y(\015oating-p)s(oin)m(t)g(t)m(yp)s(e)e(with)g(larger)h(exp)s +(onen)m(t)g(range.)0 4593 y(As)i(a)g(user)f(of)h(CLN,)g(y)m(ou)g(can)g +(forget)h(ab)s(out)f(the)g(di\013erences)g(b)s(et)m(w)m(een)g(the)g +(four)g(\015oating-p)s(oin)m(t)h(t)m(yp)s(es)f(and)0 +4717 y(just)i(declare)i(all)g(y)m(our)e(\015oating-p)s(oin)m(t)i(v)-5 +b(ariables)37 b(as)f(b)s(eing)f(of)h(t)m(yp)s(e)g Fn(cl_F)p +Fp(.)56 b(This)35 b(has)h(the)g(adv)-5 b(an)m(tage)37 +b(that)0 4842 y(when)27 b(y)m(ou)h(c)m(hange)h(the)f(precision)f(of)h +(some)f(computation)h(\(sa)m(y)-8 b(,)30 b(from)c Fn(cl_DF)h +Fp(to)h Fn(cl_LF)p Fp(\),)f(y)m(ou)i(don't)e(ha)m(v)m(e)i(to)0 +4966 y(c)m(hange)h(the)g(co)s(de,)g(only)f(the)h(precision)f(of)g(the)h +(initial)g(v)-5 b(alues.)41 b(Also,)30 b(man)m(y)f(transcenden)m(tal)h +(functions)f(ha)m(v)m(e)0 5091 y(b)s(een)f(declared)i(as)f(returning)g +(a)g Fn(cl_F)f Fp(when)g(the)i(argumen)m(t)e(is)i(a)f +Fn(cl_F)p Fp(,)g(but)f(suc)m(h)h(declarations)i(are)e(missing)0 +5215 y(for)g(the)g(t)m(yp)s(es)g Fn(cl_SF)p Fp(,)f Fn(cl_FF)p +Fp(,)f Fn(cl_DF)p Fp(,)h Fn(cl_LF)p Fp(.)39 b(\(Suc)m(h)29 +b(declarations)h(w)m(ould)f(b)s(e)f(wrong)g(if)h(the)g(\015oating)h(p)s +(oin)m(t)0 5340 y(con)m(tagion)j(rule)d(happ)s(ened)e(to)j(c)m(hange)h +(in)e(the)h(future.\))p eop +%%Page: 10 12 +10 11 bop 0 -116 a Fp(Chapter)30 b(3:)41 b(Ordinary)29 +b(n)m(um)m(b)s(er)f(t)m(yp)s(es)2411 b(10)0 366 y Fq(3.3)68 +b(Complex)31 b(n)l(um)l(b)t(ers)0 654 y Fp(Complex)25 +b(n)m(um)m(b)s(ers,)g(as)i(implemen)m(ted)e(b)m(y)h(the)h(class)g +Fn(cl_N)p Fp(,)f(ha)m(v)m(e)h(a)g(real)g(part)f(and)g(an)g(imaginary)g +(part,)i(b)s(oth)0 778 y(real)38 b(n)m(um)m(b)s(ers.)59 +b(A)38 b(complex)f(n)m(um)m(b)s(er)e(whose)i(imaginary)g(part)g(is)g +(the)h(exact)h(n)m(um)m(b)s(er)c Fn(0)i Fp(is)g(automatically)0 +903 y(con)m(v)m(erted)32 b(to)f(a)g(real)g(n)m(um)m(b)s(er.)0 +1190 y(Complex)h(n)m(um)m(b)s(ers)e(can)k(arise)f(from)e(real)j(n)m(um) +m(b)s(ers)c(alone,)35 b(for)e(example)g(through)f(application)i(of)f +Fn(sqrt)f Fp(or)0 1315 y(transcenden)m(tal)f(functions.)0 +1883 y Fq(3.4)68 b(Con)l(v)l(ersions)0 2170 y Fp(Con)m(v)m(ersions)42 +b(from)d(an)m(y)j(class)f(to)h(an)m(y)g(its)f(sup)s(erclasses)g +(\(\\base)h(classes")g(in)f(C)p Fn(++)f Fp(terminology\))i(is)f(done)0 +2295 y(automatically)-8 b(.)0 2582 y(Con)m(v)m(ersions)24 +b(from)e(the)i(C)f(built-in)h(t)m(yp)s(es)f(`)p Fn(long)p +Fp(')g(and)h(`)p Fn(unsigned)k(long)p Fp(')23 b(are)h(pro)m(vided)f +(for)g(the)h(classes)h Fn(cl_I)p Fp(,)0 2706 y Fn(cl_RA)p +Fp(,)k Fn(cl_R)p Fp(,)h Fn(cl_N)f Fp(and)h Fn(cl_number)p +Fp(.)0 2994 y(Con)m(v)m(ersions)h(from)e(the)i(C)f(built-in)g(t)m(yp)s +(es)g(`)p Fn(int)p Fp(')g(and)g(`)p Fn(unsigned)f(int)p +Fp(')h(are)g(pro)m(vided)g(for)h(the)f(classes)i Fn(cl_I)p +Fp(,)0 3118 y Fn(cl_RA)p Fp(,)h Fn(cl_R)p Fp(,)g Fn(cl_N)f +Fp(and)g Fn(cl_number)p Fp(.)47 b(Ho)m(w)m(ev)m(er,)36 +b(these)e(con)m(v)m(ersions)g(emphasize)e(e\016ciency)-8 +b(.)51 b(Their)33 b(range)0 3243 y(is)d(therefore)h(limited:)49 +3530 y Fo(\000)60 b Fp(The)30 b(con)m(v)m(ersion)i(from)c(`)p +Fn(int)p Fp(')i(w)m(orks)h(only)f(if)h(the)f(argumen)m(t)g(is)g +Fn(<)g Fp(2)p Fn(^)p Fp(29)i(and)e Fn(>)g Fp(-2)p Fn(^)p +Fp(29.)49 3693 y Fo(\000)60 b Fp(The)30 b(con)m(v)m(ersion)i(from)c(`)p +Fn(unsigned)h(int)p Fp(')h(w)m(orks)g(only)g(if)h(the)f(argumen)m(t)g +(is)h Fn(<)f Fp(2)p Fn(^)p Fp(29.)0 4018 y(In)g(a)g(declaration)i(lik)m +(e)g(`)p Fn(cl_I)d(x)h(=)g(10;)p Fp(')g(the)g(C)p Fn(++)f +Fp(compiler)h(is)h(able)f(to)h(do)f(the)h(con)m(v)m(ersion)g(of)g +Fn(10)f Fp(from)e(`)p Fn(int)p Fp(')0 4143 y(to)43 b(`)p +Fn(cl_I)p Fp(')e(at)i(compile)g(time)e(already)-8 b(.)78 +b(On)41 b(the)h(other)h(hand,)h(co)s(de)f(lik)m(e)g(`)p +Fn(cl_I)30 b(x)g(=)g(1000000000;)p Fp(')39 b(is)j(in)0 +4267 y(error.)g(So,)31 b(if)g(y)m(ou)g(w)m(an)m(t)h(to)g(b)s(e)e(sure)g +(that)h(an)g(`)p Fn(int)p Fp(')g(whose)f(magnitude)h(is)f(not)i(guaran) +m(teed)g(to)f(b)s(e)f Fn(<)h Fp(2)p Fn(^)p Fp(29)h(is)0 +4392 y(correctly)j(con)m(v)m(erted)f(to)g(a)g(`)p Fn(cl_I)p +Fp(',)f(\014rst)f(con)m(v)m(ert)j(it)f(to)g(a)f(`)p Fn(long)p +Fp('.)48 b(Similarly)-8 b(,)34 b(if)f(a)h(large)g(`)p +Fn(unsigned)28 b(int)p Fp(')33 b(is)0 4516 y(to)e(b)s(e)f(con)m(v)m +(erted)i(to)f(a)g(`)p Fn(cl_I)p Fp(',)f(\014rst)f(con)m(v)m(ert)j(it)f +(to)g(an)f(`)p Fn(unsigned)f(long)p Fp('.)0 4804 y(Con)m(v)m(ersions)h +(from)f(the)h(C)f(built-in)h(t)m(yp)s(e)g(`)p Fn(float)p +Fp(')f(are)h(pro)m(vided)g(for)f(the)h(classes)h Fn(cl_FF)p +Fp(,)e Fn(cl_F)p Fp(,)g Fn(cl_R)p Fp(,)g Fn(cl_N)0 4928 +y Fp(and)h Fn(cl_number)p Fp(.)0 5215 y(Con)m(v)m(ersions)d(from)e(the) +i(C)f(built-in)g(t)m(yp)s(e)h(`)p Fn(double)p Fp(')e(are)i(pro)m(vided) +g(for)f(the)h(classes)g Fn(cl_DF)p Fp(,)f Fn(cl_F)p Fp(,)h +Fn(cl_R)p Fp(,)f Fn(cl_N)0 5340 y Fp(and)k Fn(cl_number)p +Fp(.)p eop +%%Page: 11 13 +11 12 bop 0 -116 a Fp(Chapter)30 b(3:)41 b(Ordinary)29 +b(n)m(um)m(b)s(er)f(t)m(yp)s(es)2411 b(11)0 366 y(Con)m(v)m(ersions)35 +b(from)f(`)p Fn(const)29 b(char)g(*)p Fp(')35 b(are)g(pro)m(vided)g +(for)f(the)i(classes)f Fn(cl_I)p Fp(,)h Fn(cl_RA)p Fp(,)e +Fn(cl_SF)p Fp(,)h Fn(cl_FF)p Fp(,)g Fn(cl_DF)p Fp(,)0 +491 y Fn(cl_LF)p Fp(,)e Fn(cl_F)p Fp(,)h Fn(cl_R)p Fp(,)g +Fn(cl_N)p Fp(.)50 b(The)33 b(easiest)i(w)m(a)m(y)g(to)g(sp)s(ecify)e(a) +h(v)-5 b(alue)34 b(whic)m(h)g(is)g(outside)g(of)g(the)g(range)g(of)g +(the)0 616 y(C)p Fn(++)29 b Fp(built-in)i(t)m(yp)s(es)f(is)g(therefore) +h(to)g(sp)s(ecify)f(it)h(as)g(a)g(string,)f(lik)m(e)i(this:)383 +869 y Fn(cl_I)47 b(order_of_rubiks_cube_gro)o(up)41 b(=)48 +b("43252003274489856000";)0 1143 y Fp(Note)32 b(that)f(this)f(con)m(v)m +(ersion)i(is)e(done)g(at)h(run)m(time,)f(not)g(at)h(compile-time.)0 +1417 y(Con)m(v)m(ersions)h(from)f Fn(cl_I)g Fp(to)h(the)g(C)g(built-in) +g(t)m(yp)s(es)g(`)p Fn(int)p Fp(',)g(`)p Fn(unsigned)c(int)p +Fp(',)k(`)p Fn(long)p Fp(',)g(`)p Fn(unsigned)d(long)p +Fp(')i(are)0 1541 y(pro)m(vided)f(through)g(the)g(functions)0 +1840 y Fn(int)f(cl_I_to_int)f(\(const)g(cl_I&)h(x\))0 +1965 y(unsigned)f(int)i(cl_I_to_uint)d(\(const)h(cl_I&)h(x\))0 +2089 y(long)g(cl_I_to_long)e(\(const)i(cl_I&)g(x\))0 +2214 y(unsigned)f(long)h(cl_I_to_ulong)e(\(const)i(cl_I&)g(x\))480 +2338 y Fp(Returns)37 b Fn(x)h Fp(as)h(elemen)m(t)f(of)h(the)f(C)g(t)m +(yp)s(e)g Fi(ct)m(yp)s(e)p Fp(.)65 b(If)38 b Fn(x)f Fp(is)i(not)f +(represen)m(table)h(in)f(the)g(range)h(of)480 2463 y +Fi(ct)m(yp)s(e)p Fp(,)31 b(a)g(run)m(time)e(error)h(o)s(ccurs.)0 +2762 y(Con)m(v)m(ersions)35 b(from)e(the)h(classes)i +Fn(cl_I)p Fp(,)e Fn(cl_RA)p Fp(,)g Fn(cl_SF)p Fp(,)g +Fn(cl_FF)p Fp(,)g Fn(cl_DF)p Fp(,)h Fn(cl_LF)p Fp(,)f +Fn(cl_F)f Fp(and)h Fn(cl_R)f Fp(to)i(the)f(C)0 2886 y(built-in)c(t)m +(yp)s(es)h(`)p Fn(float)p Fp(')e(and)h(`)p Fn(double)p +Fp(')f(are)i(pro)m(vided)f(through)f(the)i(functions)0 +3185 y Fn(float)e(cl_float_approx)d(\(const)j Fi(t)m(yp)s(e)5 +b Fn(&)30 b(x\))0 3310 y(double)f(cl_double_approx)d(\(const)i +Fi(t)m(yp)s(e)5 b Fn(&)31 b(x\))480 3434 y Fp(Returns)25 +b(an)h(appro)m(ximation)g(of)g Fn(x)f Fp(of)h(C)g(t)m(yp)s(e)g +Fi(ct)m(yp)s(e)p Fp(.)39 b(If)26 b Fn(abs\(x\))e Fp(is)i(to)s(o)g +(close)i(to)e(0)g(\(under\015o)m(w\),)480 3559 y(0)31 +b(is)f(returned.)40 b(If)30 b Fn(abs\(x\))e Fp(is)j(to)s(o)g(large)g +(\(o)m(v)m(er\015o)m(w\),)i(an)d(IEEE)g(in\014nit)m(y)g(is)h(returned.) +0 3858 y(Con)m(v)m(ersions)g(from)e(an)m(y)i(class)g(to)g(an)m(y)g(of)g +(its)g(sub)s(classes)f(\(\\deriv)m(ed)h(classes")h(in)e(C)p +Fn(++)g Fp(terminology\))h(are)g(not)0 3982 y(pro)m(vided.)40 +b(Instead,)31 b(y)m(ou)f(can)h(assert)g(and)e(c)m(hec)m(k)j(that)f(a)g +(v)-5 b(alue)31 b(b)s(elongs)f(to)h(a)f(certain)i(sub)s(class,)d(and)h +(return)0 4107 y(it)38 b(as)f(elemen)m(t)h(of)g(that)f(class,)j(using)d +(the)h(`)p Fn(As)p Fp(')f(and)g(`)p Fn(The)p Fp(')f(macros.)61 +b Fn(As\()p Fi(t)m(yp)s(e)5 b Fn(\)\()p Fi(v)-5 b(alue)5 +b Fn(\))37 b Fp(c)m(hec)m(ks)i(that)e Fi(v)-5 b(alue)0 +4231 y Fp(b)s(elongs)29 b(to)h Fi(t)m(yp)s(e)35 b Fp(and)29 +b(returns)f(it)i(as)f(suc)m(h.)40 b Fn(The\()p Fi(t)m(yp)s(e)5 +b Fn(\)\()p Fi(v)-5 b(alue)5 b Fn(\))29 b Fp(assumes)f(that)i +Fi(v)-5 b(alue)35 b Fp(b)s(elongs)29 b(to)h Fi(t)m(yp)s(e)35 +b Fp(and)0 4356 y(returns)29 b(it)i(as)g(suc)m(h.)40 +b(It)31 b(is)f(y)m(our)g(resp)s(onsibilit)m(y)h(to)g(ensure)e(that)i +(this)g(assumption)d(is)j(v)-5 b(alid.)41 b(Example:)383 +4609 y Fn(cl_I)47 b(x)g(=)h Fl(:)15 b(:)g(:)q Fn(;)383 +4713 y(if)47 b(\(!\(x)g(>=)g(0\)\))g(abort\(\);)383 4816 +y(cl_I)g(ten_x)f(=)i(The\(cl_I\)\(expt\(10,x\)\);)41 +b(//)48 b(If)f(x)g(>=)g(0,)h(10^x)e(is)h(an)h(integer.)1004 +4920 y(//)f(In)g(general,)f(it)h(would)f(be)h(a)h(rational)d(number.)p +eop +%%Page: 12 14 +12 13 bop 0 -116 a Fp(Chapter)30 b(4:)41 b(F)-8 b(unctions)31 +b(on)f(n)m(um)m(b)s(ers)2463 b(12)0 366 y Fm(4)80 b(F)-13 +b(unctions)29 b(on)h(n)l(um)l(b)t(ers)0 754 y Fp(Eac)m(h)i(of)f(the)g +(n)m(um)m(b)s(er)e(classes)i(declares)h(its)g(mathematical)f(op)s +(erations)g(in)g(the)g(corresp)s(onding)f(include)h(\014le.)0 +879 y(F)-8 b(or)26 b(example,)g(if)g(y)m(our)f(co)s(de)g(op)s(erates)h +(with)f(ob)5 b(jects)26 b(of)f(t)m(yp)s(e)h Fn(cl_I)p +Fp(,)f(it)h(should)e Fn(#include)29 b()p +Fp(.)0 1353 y Fq(4.1)68 b(Constructing)31 b(n)l(um)l(b)t(ers)0 +1630 y Fp(Here)g(is)f(ho)m(w)h(to)g(create)h(n)m(um)m(b)s(er)c(ob)5 +b(jects)31 b(\\from)e(nothing".)0 2071 y Fk(4.1.1)63 +b(Constructing)30 b(in)m(tegers)0 2348 y Fn(cl_I)i Fp(ob)5 +b(jects)33 b(are)g(most)f(easily)i(constructed)f(from)e(C)i(in)m +(tegers)h(and)e(from)f(strings.)48 b(See)32 b(Section)i(3.4)g([Con-)0 +2472 y(v)m(ersions],)d(page)g(10.)0 2913 y Fk(4.1.2)63 +b(Constructing)30 b(rational)h(n)m(um)m(b)s(ers)0 3190 +y Fn(cl_RA)k Fp(ob)5 b(jects)38 b(can)f(b)s(e)f(constructed)h(from)e +(strings.)60 b(The)37 b(syn)m(tax)g(for)f(rational)i(n)m(um)m(b)s(ers)d +(is)i(describ)s(ed)e(in)0 3314 y(Section)40 b(5.1)h([In)m(ternal)f(and) +e(prin)m(ted)h(represen)m(tation],)k(page)e(37.)68 b(Another)39 +b(standard)g(w)m(a)m(y)h(to)g(pro)s(duce)f(a)0 3439 y(rational)32 +b(n)m(um)m(b)s(er)c(is)i(through)g(application)h(of)g(`)p +Fn(operator)d(/)p Fp(')j(or)f(`)p Fn(recip)p Fp(')f(on)i(in)m(tegers.)0 +3880 y Fk(4.1.3)63 b(Constructing)30 b(\015oating-p)s(oin)m(t)i(n)m(um) +m(b)s(ers)0 4157 y Fn(cl_F)39 b Fp(ob)5 b(jects)41 b(with)f(lo)m(w)i +(precision)e(are)h(most)f(easily)h(constructed)g(from)e(C)h(`)p +Fn(float)p Fp(')f(and)h(`)p Fn(double)p Fp('.)70 b(See)0 +4281 y(Section)31 b(3.4)h([Con)m(v)m(ersions],)f(page)g(10.)0 +4558 y(T)-8 b(o)42 b(construct)g(a)h Fn(cl_F)d Fp(with)i(high)f +(precision,)k(y)m(ou)d(can)h(use)e(the)h(con)m(v)m(ersion)h(from)d(`)p +Fn(const)30 b(char)f(*)p Fp(',)45 b(but)0 4683 y(y)m(ou)33 +b(ha)m(v)m(e)h(to)f(sp)s(ecify)f(the)g(desired)g(precision)h(within)f +(the)h(string.)47 b(\(See)33 b(Section)g(5.1)g([In)m(ternal)h(and)d +(prin)m(ted)0 4807 y(represen)m(tation],)h(page)f(37.\))42 +b(Example:)383 5063 y Fn(cl_F)47 b(e)g(=)h("0.27182818284590452353)o +(6028)o(7471)o(352)o(6624)o(9775)o(724)o(7093)o(6999)o(6e+)o(1_40)o(";) +0 5340 y Fp(will)31 b(set)g(`)p Fn(e)p Fp(')f(to)h(the)g(giv)m(en)g(v) +-5 b(alue,)31 b(with)f(a)h(precision)g(of)f(40)h(decimal)g(digits.)p +eop +%%Page: 13 15 +13 14 bop 0 -116 a Fp(Chapter)30 b(4:)41 b(F)-8 b(unctions)31 +b(on)f(n)m(um)m(b)s(ers)2463 b(13)0 366 y(The)25 b(programmatic)f(w)m +(a)m(y)j(to)f(construct)f(a)h Fn(cl_F)e Fp(with)h(high)g(precision)h +(is)f(through)g(the)h Fn(cl_float)d Fp(con)m(v)m(ersion)0 +491 y(function,)29 b(see)h(Section)g(4.11.1)i([Con)m(v)m(ersion)e(to)g +(\015oating-p)s(oin)m(t)h(n)m(um)m(b)s(ers],)c(page)j(32.)42 +b(F)-8 b(or)30 b(example,)f(to)h(com-)0 616 y(pute)d +Fn(e)f Fp(to)i(40)f(decimal)g(places,)i(\014rst)d(construct)h(1.0)h(to) +g(40)f(decimal)g(places)h(and)e(then)g(apply)h(the)g(exp)s(onen)m(tial) +0 740 y(function:)383 993 y Fn(cl_float_format_t)43 b(precision)j(=)h +(cl_float_format\(40\);)383 1097 y(cl_F)g(e)g(=)h +(exp\(cl_float\(1,precisio)o(n\)\);)0 1505 y Fk(4.1.4)63 +b(Constructing)30 b(complex)g(n)m(um)m(b)s(ers)0 1779 +y Fp(Non-real)h Fn(cl_N)f Fp(ob)5 b(jects)31 b(are)g(normally)e +(constructed)i(through)e(the)i(function)383 2032 y Fn(cl_N)47 +b(complex)f(\(const)g(cl_R&)g(realpart,)f(const)i(cl_R&)f(imagpart\))0 +2306 y Fp(See)31 b(Section)g(4.4)g([Elemen)m(tary)g(complex)f +(functions],)g(page)h(15.)0 2748 y Fq(4.2)68 b(Elemen)l(tary)32 +b(functions)0 3022 y Fp(Eac)m(h)22 b(of)g(the)g(classes)h +Fn(cl_N)p Fp(,)g Fn(cl_R)p Fp(,)f Fn(cl_RA)p Fp(,)g Fn(cl_I)p +Fp(,)h Fn(cl_F)p Fp(,)g Fn(cl_SF)p Fp(,)f Fn(cl_FF)p +Fp(,)g Fn(cl_DF)p Fp(,)g Fn(cl_LF)f Fp(de\014nes)g(the)g(follo)m(wing)0 +3146 y(op)s(erations:)0 3443 y Fi(t)m(yp)s(e)36 b Fn(operator)28 +b(+)i(\(const)e Fi(t)m(yp)s(e)5 b Fn(&,)31 b(const)d +Fi(t)m(yp)s(e)5 b Fn(&\))480 3568 y Fp(Addition.)0 3739 +y Fi(t)m(yp)s(e)36 b Fn(operator)28 b(-)i(\(const)e Fi(t)m(yp)s(e)5 +b Fn(&,)31 b(const)d Fi(t)m(yp)s(e)5 b Fn(&\))480 3863 +y Fp(Subtraction.)0 4034 y Fi(t)m(yp)s(e)36 b Fn(operator)28 +b(-)i(\(const)e Fi(t)m(yp)s(e)5 b Fn(&\))480 4159 y Fp(Returns)29 +b(the)i(negativ)m(e)i(of)d(the)h(argumen)m(t.)0 4329 +y Fi(t)m(yp)s(e)36 b Fn(plus1)29 b(\(const)f Fi(t)m(yp)s(e)5 +b Fn(&)31 b(x\))480 4454 y Fp(Returns)e Fn(x)h(+)h(1)p +Fp(.)0 4625 y Fi(t)m(yp)s(e)36 b Fn(minus1)28 b(\(const)h +Fi(t)m(yp)s(e)5 b Fn(&)30 b(x\))480 4749 y Fp(Returns)f +Fn(x)h(-)h(1)p Fp(.)0 4920 y Fi(t)m(yp)s(e)36 b Fn(operator)28 +b(*)i(\(const)e Fi(t)m(yp)s(e)5 b Fn(&,)31 b(const)d +Fi(t)m(yp)s(e)5 b Fn(&\))480 5045 y Fp(Multiplication.)0 +5215 y Fi(t)m(yp)s(e)36 b Fn(square)28 b(\(const)h Fi(t)m(yp)s(e)5 +b Fn(&)30 b(x\))480 5340 y Fp(Returns)f Fn(x)h(*)h(x)p +Fp(.)p eop +%%Page: 14 16 +14 15 bop 0 -116 a Fp(Chapter)30 b(4:)41 b(F)-8 b(unctions)31 +b(on)f(n)m(um)m(b)s(ers)2463 b(14)0 366 y(Eac)m(h)39 +b(of)g(the)g(classes)h Fn(cl_N)p Fp(,)g Fn(cl_R)p Fp(,)f +Fn(cl_RA)p Fp(,)h Fn(cl_F)p Fp(,)g Fn(cl_SF)p Fp(,)f +Fn(cl_FF)p Fp(,)h Fn(cl_DF)p Fp(,)g Fn(cl_LF)d Fp(de\014nes)h(the)g +(follo)m(wing)0 491 y(op)s(erations:)0 796 y Fi(t)m(yp)s(e)e +Fn(operator)28 b(/)i(\(const)e Fi(t)m(yp)s(e)5 b Fn(&,)31 +b(const)d Fi(t)m(yp)s(e)5 b Fn(&\))480 921 y Fp(Division.)0 +1101 y Fi(t)m(yp)s(e)36 b Fn(recip)29 b(\(const)f Fi(t)m(yp)s(e)5 +b Fn(&\))480 1225 y Fp(Returns)29 b(the)i(recipro)s(cal)g(of)g(the)f +(argumen)m(t.)0 1530 y(The)d(class)g Fn(cl_I)f Fp(do)s(esn't)h +(de\014ne)g(a)g(`)p Fn(/)p Fp(')g(op)s(eration)h(b)s(ecause)f(in)g(the) +g(C/C)p Fn(++)f Fp(language)j(this)e(op)s(erator,)h(applied)0 +1655 y(to)j(in)m(tegral)h(t)m(yp)s(es,)f(denotes)f(the)h(`)p +Fn(floor)p Fp(')e(or)h(`)p Fn(truncate)p Fp(')f(op)s(eration)i(\(whic)m +(h)f(one)h(of)f(these,)h(is)g(implemen)m(ta-)0 1780 y(tion)j(dep)s +(enden)m(t\).)48 b(\(See)34 b(Section)f(4.6)i([Rounding)d(functions],)i +(page)g(17\))g(Instead,)g Fn(cl_I)e Fp(de\014nes)g(an)h(\\exact)0 +1904 y(quotien)m(t")f(function:)0 2209 y Fn(cl_I)d(exquo)g(\(const)g +(cl_I&)g(x,)h(const)e(cl_I&)h(y\))480 2334 y Fp(Chec)m(ks)i(that)g +Fn(y)f Fp(divides)g Fn(x)p Fp(,)g(and)g(returns)f(the)h(quotien)m(t)i +Fn(x)p Fp(/)p Fn(y)p Fp(.)0 2638 y(The)e(follo)m(wing)i(exp)s(onen)m +(tiation)f(functions)f(are)h(de\014ned:)0 2943 y Fn(cl_I)e(expt_pos)f +(\(const)h(cl_I&)g(x,)h(const)f(cl_I&)g(y\))0 3068 y(cl_RA)g(expt_pos)f +(\(const)h(cl_RA&)f(x,)i(const)f(cl_I&)g(y\))480 3193 +y(y)h Fp(m)m(ust)f(b)s(e)h Fn(>)g Fp(0.)41 b(Returns)30 +b Fn(x^y)p Fp(.)0 3373 y Fn(cl_RA)f(expt)g(\(const)g(cl_RA&)f(x,)i +(const)f(cl_I&)g(y\))0 3497 y(cl_R)g(expt)g(\(const)g(cl_R&)g(x,)h +(const)f(cl_I&)g(y\))0 3622 y(cl_N)g(expt)g(\(const)g(cl_N&)g(x,)h +(const)f(cl_I&)g(y\))480 3747 y Fp(Returns)g Fn(x^y)p +Fp(.)0 4052 y(Eac)m(h)39 b(of)g(the)g(classes)h Fn(cl_R)p +Fp(,)g Fn(cl_RA)p Fp(,)f Fn(cl_I)p Fp(,)h Fn(cl_F)p Fp(,)g +Fn(cl_SF)p Fp(,)f Fn(cl_FF)p Fp(,)h Fn(cl_DF)p Fp(,)g +Fn(cl_LF)d Fp(de\014nes)h(the)g(follo)m(wing)0 4176 y(op)s(eration:)0 +4481 y Fi(t)m(yp)s(e)e Fn(abs)29 b(\(const)g Fi(t)m(yp)s(e)5 +b Fn(&)30 b(x\))480 4606 y Fp(Returns)f(the)i(absolute)g(v)-5 +b(alue)31 b(of)f Fn(x)p Fp(.)41 b(This)29 b(is)i Fn(x)f +Fp(if)g Fn(x)g(>=)g(0)p Fp(,)g(and)g Fn(-x)g Fp(if)g +Fn(x)g(<=)g(0)p Fp(.)0 4911 y(The)g(class)h Fn(cl_N)e +Fp(implemen)m(ts)g(this)h(as)h(follo)m(ws:)0 5215 y Fn(cl_R)e(abs)h +(\(const)e(cl_N)i(x\))480 5340 y Fp(Returns)f(the)i(absolute)g(v)-5 +b(alue)31 b(of)f Fn(x)p Fp(.)p eop +%%Page: 15 17 +15 16 bop 0 -116 a Fp(Chapter)30 b(4:)41 b(F)-8 b(unctions)31 +b(on)f(n)m(um)m(b)s(ers)2463 b(15)0 366 y(Eac)m(h)22 +b(of)g(the)g(classes)h Fn(cl_N)p Fp(,)g Fn(cl_R)p Fp(,)f +Fn(cl_RA)p Fp(,)g Fn(cl_I)p Fp(,)h Fn(cl_F)p Fp(,)g Fn(cl_SF)p +Fp(,)f Fn(cl_FF)p Fp(,)g Fn(cl_DF)p Fp(,)g Fn(cl_LF)f +Fp(de\014nes)g(the)g(follo)m(wing)0 491 y(op)s(eration:)0 +798 y Fi(t)m(yp)s(e)36 b Fn(signum)28 b(\(const)h Fi(t)m(yp)s(e)5 +b Fn(&)30 b(x\))480 922 y Fp(Returns)g(the)i(sign)f(of)g +Fn(x)p Fp(,)h(in)f(the)g(same)g(n)m(um)m(b)s(er)e(format)h(as)i +Fn(x)p Fp(.)42 b(This)31 b(is)g(de\014ned)f(as)i Fn(x)e(/)g(abs\(x\)) +480 1047 y Fp(if)g Fn(x)g Fp(is)h(non-zero,)g(and)f Fn(x)g +Fp(if)g Fn(x)g Fp(is)h(zero.)41 b(If)30 b Fn(x)g Fp(is)g(real,)i(the)e +(v)-5 b(alue)31 b(is)g(either)f(0)h(or)f(1)h(or)g(-1.)0 +1531 y Fq(4.3)68 b(Elemen)l(tary)32 b(rational)g(functions)0 +1808 y Fp(Eac)m(h)f(of)g(the)f(classes)i Fn(cl_RA)p Fp(,)d +Fn(cl_I)g Fp(de\014nes)g(the)i(follo)m(wing)h(op)s(erations:)0 +2115 y Fn(cl_I)d(numerator)f(\(const)h Fi(t)m(yp)s(e)5 +b Fn(&)30 b(x\))480 2240 y Fp(Returns)f(the)i(n)m(umerator)e(of)i +Fn(x)p Fp(.)0 2422 y Fn(cl_I)e(denominator)f(\(const)g +Fi(t)m(yp)s(e)5 b Fn(&)31 b(x\))480 2546 y Fp(Returns)e(the)i +(denominator)f(of)g Fn(x)p Fp(.)0 2853 y(The)c(n)m(umerator)h(and)f +(denominator)g(of)h(a)h(rational)g(n)m(um)m(b)s(er)c(are)k(normalized)e +(in)h(suc)m(h)g(a)g(w)m(a)m(y)h(that)g(they)f(ha)m(v)m(e)0 +2978 y(no)j(factor)i(in)e(common)e(and)i(the)h(denominator)e(is)i(p)s +(ositiv)m(e.)0 3462 y Fq(4.4)68 b(Elemen)l(tary)32 b(complex)f +(functions)0 3739 y Fp(The)f(class)h Fn(cl_N)e Fp(de\014nes)h(the)g +(follo)m(wing)i(op)s(eration:)0 4046 y Fn(cl_N)d(complex)g(\(const)f +(cl_R&)h(a,)h(const)f(cl_R&)g(b\))480 4171 y Fp(Returns)i(the)h +(complex)f(n)m(um)m(b)s(er)f Fn(a+bi)p Fp(,)h(that)i(is,)f(the)g +(complex)g(n)m(um)m(b)s(er)d(with)j(real)g(part)g Fn(a)g +Fp(and)480 4295 y(imaginary)e(part)g Fn(b)p Fp(.)0 4602 +y(Eac)m(h)h(of)g(the)f(classes)i Fn(cl_N)p Fp(,)d Fn(cl_R)g +Fp(de\014nes)h(the)g(follo)m(wing)i(op)s(erations:)0 +4909 y Fn(cl_R)d(realpart)f(\(const)h Fi(t)m(yp)s(e)5 +b Fn(&)30 b(x\))480 5033 y Fp(Returns)f(the)i(real)g(part)f(of)h +Fn(x)p Fp(.)0 5215 y Fn(cl_R)e(imagpart)f(\(const)h Fi(t)m(yp)s(e)5 +b Fn(&)30 b(x\))480 5340 y Fp(Returns)f(the)i(imaginary)f(part)g(of)h +Fn(x)p Fp(.)p eop +%%Page: 16 18 +16 17 bop 0 -116 a Fp(Chapter)30 b(4:)41 b(F)-8 b(unctions)31 +b(on)f(n)m(um)m(b)s(ers)2463 b(16)0 366 y Fi(t)m(yp)s(e)36 +b Fn(conjugate)27 b(\(const)i Fi(t)m(yp)s(e)5 b Fn(&)31 +b(x\))480 491 y Fp(Returns)e(the)i(complex)f(conjugate)i(of)e +Fn(x)p Fp(.)0 795 y(W)-8 b(e)32 b(ha)m(v)m(e)f(the)g(relations)180 +1071 y Fn(x)f(=)g(complex\(realpart\(x\),)25 b(imagpart\(x\)\))180 +1223 y(conjugate\(x\))i(=)j(complex\(realpart\(x\),)25 +b(-imagpart\(x\)\))0 1693 y Fq(4.5)68 b(Comparisons)0 +1969 y Fp(Eac)m(h)22 b(of)g(the)g(classes)h Fn(cl_N)p +Fp(,)g Fn(cl_R)p Fp(,)f Fn(cl_RA)p Fp(,)g Fn(cl_I)p Fp(,)h +Fn(cl_F)p Fp(,)g Fn(cl_SF)p Fp(,)f Fn(cl_FF)p Fp(,)g +Fn(cl_DF)p Fp(,)g Fn(cl_LF)f Fp(de\014nes)g(the)g(follo)m(wing)0 +2094 y(op)s(erations:)0 2397 y Fn(bool)29 b(operator)f(==)i(\(const)f +Fi(t)m(yp)s(e)5 b Fn(&,)30 b(const)f Fi(t)m(yp)s(e)5 +b Fn(&\))0 2522 y(bool)29 b(operator)f(!=)i(\(const)f +Fi(t)m(yp)s(e)5 b Fn(&,)30 b(const)f Fi(t)m(yp)s(e)5 +b Fn(&\))480 2646 y Fp(Comparison,)29 b(as)i(in)f(C)g(and)f(C)p +Fn(++)p Fp(.)0 2825 y Fn(uint32)g(cl_equal_hashcode)c(\(const)k +Fi(t)m(yp)s(e)5 b Fn(&\))480 2950 y Fp(Returns)31 b(a)h(32-bit)i(hash)d +(co)s(de)h(that)h(is)f(the)g(same)f(for)h(an)m(y)g(t)m(w)m(o)i(n)m(um)m +(b)s(ers)29 b(whic)m(h)j(are)g(the)h(same)480 3075 y(according)e(to)g +Fn(==)p Fp(.)40 b(This)29 b(hash)g(co)s(de)i(dep)s(ends)d(on)i(the)g(n) +m(um)m(b)s(er's)e(v)-5 b(alue,)31 b(not)f(its)g(t)m(yp)s(e)g(or)h +(preci-)480 3199 y(sion.)0 3378 y Fn(cl_boolean)d(zerop)h(\(const)f +Fi(t)m(yp)s(e)5 b Fn(&)31 b(x\))480 3503 y Fp(Compare)e(against)j +(zero:)41 b Fn(x)30 b(==)g(0)0 3806 y Fp(Eac)m(h)39 b(of)g(the)g +(classes)h Fn(cl_R)p Fp(,)g Fn(cl_RA)p Fp(,)f Fn(cl_I)p +Fp(,)h Fn(cl_F)p Fp(,)g Fn(cl_SF)p Fp(,)f Fn(cl_FF)p +Fp(,)h Fn(cl_DF)p Fp(,)g Fn(cl_LF)d Fp(de\014nes)h(the)g(follo)m(wing)0 +3931 y(op)s(erations:)0 4235 y Fn(cl_signean)28 b(cl_compare)f(\(const) +i Fi(t)m(yp)s(e)5 b Fn(&)30 b(x,)g(const)f Fi(t)m(yp)s(e)5 +b Fn(&)30 b(y\))480 4359 y Fp(Compares)f Fn(x)h Fp(and)g +Fn(y)p Fp(.)40 b(Returns)30 b Fn(+)p Fp(1)g(if)g Fn(x>y)p +Fp(,)g(-1)h(if)g Fn(x=)i(\(const)f +Fi(t)m(yp)s(e)5 b Fn(&,)30 b(const)f Fi(t)m(yp)s(e)5 +b Fn(&\))0 4912 y(bool)29 b(operator)f(>)i(\(const)f +Fi(t)m(yp)s(e)5 b Fn(&,)30 b(const)f Fi(t)m(yp)s(e)5 +b Fn(&\))480 5036 y Fp(Comparison,)29 b(as)i(in)f(C)g(and)f(C)p +Fn(++)p Fp(.)0 5215 y Fn(cl_boolean)f(minusp)g(\(const)h +Fi(t)m(yp)s(e)5 b Fn(&)30 b(x\))480 5340 y Fp(Compare)f(against)j +(zero:)41 b Fn(x)30 b(<)g(0)p eop +%%Page: 17 19 +17 18 bop 0 -116 a Fp(Chapter)30 b(4:)41 b(F)-8 b(unctions)31 +b(on)f(n)m(um)m(b)s(ers)2463 b(17)0 366 y Fn(cl_boolean)28 +b(plusp)h(\(const)f Fi(t)m(yp)s(e)5 b Fn(&)31 b(x\))480 +491 y Fp(Compare)e(against)j(zero:)41 b Fn(x)30 b(>)g(0)0 +656 y Fi(t)m(yp)s(e)36 b Fn(max)29 b(\(const)g Fi(t)m(yp)s(e)5 +b Fn(&)30 b(x,)g(const)f Fi(t)m(yp)s(e)5 b Fn(&)30 b(y\))480 +780 y Fp(Return)g(the)g(maxim)m(um)d(of)k Fn(x)f Fp(and)g +Fn(y)p Fp(.)0 945 y Fi(t)m(yp)s(e)36 b Fn(min)29 b(\(const)g +Fi(t)m(yp)s(e)5 b Fn(&)30 b(x,)g(const)f Fi(t)m(yp)s(e)5 +b Fn(&)30 b(y\))480 1069 y Fp(Return)g(the)g(minim)m(um)d(of)j +Fn(x)g Fp(and)g Fn(y)p Fp(.)0 1363 y(When)h(a)h(\015oating)g(p)s(oin)m +(t)f(n)m(um)m(b)s(er)e(and)h(a)i(rational)g(n)m(um)m(b)s(er)d(are)j +(compared,)f(the)g(\015oat)h(is)f(\014rst)f(con)m(v)m(erted)j(to)0 +1488 y(a)e(rational)h(n)m(um)m(b)s(er)c(using)i(the)h(function)f +Fn(rational)p Fp(.)39 b(Since)31 b(a)g(\015oating)g(p)s(oin)m(t)g(n)m +(um)m(b)s(er)d(actually)k(represen)m(ts)0 1612 y(an)h(in)m(terv)-5 +b(al)34 b(of)g(real)g(n)m(um)m(b)s(ers,)d(the)j(result)f(migh)m(t)g(b)s +(e)f(surprising.)48 b(F)-8 b(or)34 b(example,)g Fn +(\(cl_F\)\(cl_R\)"1/3")26 b(==)0 1737 y(\(cl_R\)"1/3")h +Fp(returns)i(false)i(b)s(ecause)g(there)f(is)h(no)f(\015oating)h(p)s +(oin)m(t)g(n)m(um)m(b)s(er)d(whose)i(v)-5 b(alue)31 b(is)f(exactly)i +Fn(1/3)p Fp(.)0 2166 y Fq(4.6)68 b(Rounding)30 b(functions)0 +2440 y Fp(When)37 b(a)g(real)h(n)m(um)m(b)s(er)d(is)i(to)h(b)s(e)e(con) +m(v)m(erted)j(to)e(an)g(in)m(teger,)k(there)c(is)g(no)g(\\b)s(est")g +(rounding.)60 b(The)36 b(desired)0 2564 y(rounding)g(function)g(dep)s +(ends)f(on)i(the)g(application.)61 b(The)36 b(Common)e(Lisp)j(and)f +(ISO)g(Lisp)g(standards)g(o\013er)0 2689 y(four)30 b(rounding)f +(functions:)0 2983 y Fn(floor\(x\))96 b Fp(This)30 b(is)g(the)h +(largest)g(in)m(teger)h Fn(<)p Fp(=)p Fn(x)p Fp(.)0 3148 +y Fn(ceiling\(x\))480 3272 y Fp(This)e(is)g(the)h(smallest)f(in)m +(teger)i Fn(>)p Fp(=)p Fn(x)p Fp(.)0 3437 y Fn(truncate\(x\))480 +3561 y Fp(Among)e(the)g(in)m(tegers)i(b)s(et)m(w)m(een)f(0)g(and)e +Fn(x)h Fp(\(inclusiv)m(e\))i(the)f(one)g(nearest)f(to)i +Fn(x)p Fp(.)0 3726 y Fn(round\(x\))96 b Fp(The)29 b(in)m(teger)h +(nearest)f(to)h Fn(x)p Fp(.)40 b(If)29 b Fn(x)f Fp(is)h(exactly)i +(halfw)m(a)m(y)f(b)s(et)m(w)m(een)g(t)m(w)m(o)g(in)m(tegers,)h(c)m(ho)s +(ose)f(the)f(ev)m(en)480 3850 y(one.)0 4144 y(These)h(functions)g(ha)m +(v)m(e)i(di\013eren)m(t)e(adv)-5 b(an)m(tages:)0 4418 +y Fn(floor)38 b Fp(and)g Fn(ceiling)g Fp(are)h(translation)h(in)m(v)-5 +b(arian)m(t:)60 b Fn(floor\(x+n\))28 b(=)i(floor\(x\))e(+)i(n)39 +b Fp(and)f Fn(ceiling\(x+n\))27 b(=)0 4543 y(ceiling\(x\))h(+)i(n)g +Fp(for)g(ev)m(ery)h Fn(x)f Fp(and)g(ev)m(ery)h(in)m(teger)h +Fn(n)p Fp(.)0 4817 y(On)46 b(the)h(other)g(hand,)j Fn(truncate)44 +b Fp(and)i Fn(round)f Fp(are)i(symmetric:)72 b Fn(truncate\(-x\))27 +b(=)j(-truncate\(x\))44 b Fp(and)0 4941 y Fn(round\(-x\))28 +b(=)i(-round\(x\))p Fp(,)38 b(and)g(furthermore)e Fn(round)h +Fp(is)h(un)m(biased:)57 b(on)38 b(the)h(\\a)m(v)m(erage",)44 +b(it)39 b(rounds)d(do)m(wn)0 5066 y(exactly)c(as)f(often)g(as)f(it)h +(rounds)e(up.)0 5340 y(The)h(functions)g(are)h(related)g(lik)m(e)h +(this:)p eop +%%Page: 18 20 +18 19 bop 0 -116 a Fp(Chapter)30 b(4:)41 b(F)-8 b(unctions)31 +b(on)f(n)m(um)m(b)s(ers)2463 b(18)180 366 y Fn(ceiling\(m/n\))27 +b(=)j(floor\(\(m+n-1\)/n\))c(=)k(floor\(\(m-1\)/n\)+1)g +Fp(for)35 b(rational)h(n)m(um)m(b)s(ers)c Fn(m/n)i Fp(\()p +Fn(m)p Fp(,)i Fn(n)f Fp(in-)180 491 y(tegers,)d Fn(n>)p +Fp(0\),)e(and)180 646 y Fn(truncate\(x\))d(=)j(sign\(x\))f(*)h +(floor\(abs\(x\)\))0 957 y Fp(Eac)m(h)24 b(of)f(the)h(classes)g +Fn(cl_R)p Fp(,)g Fn(cl_RA)p Fp(,)g Fn(cl_F)p Fp(,)f Fn(cl_SF)p +Fp(,)h Fn(cl_FF)p Fp(,)f Fn(cl_DF)p Fp(,)h Fn(cl_LF)e +Fp(de\014nes)g(the)i(follo)m(wing)g(op)s(erations:)0 +1268 y Fn(cl_I)29 b(floor1)g(\(const)g Fi(t)m(yp)s(e)5 +b Fn(&)30 b(x\))480 1392 y Fp(Returns)f Fn(floor\(x\))p +Fp(.)0 1578 y Fn(cl_I)g(ceiling1)f(\(const)h Fi(t)m(yp)s(e)5 +b Fn(&)30 b(x\))480 1703 y Fp(Returns)f Fn(ceiling\(x\))p +Fp(.)0 1889 y Fn(cl_I)g(truncate1)f(\(const)h Fi(t)m(yp)s(e)5 +b Fn(&)30 b(x\))480 2014 y Fp(Returns)f Fn(truncate\(x\))p +Fp(.)0 2200 y Fn(cl_I)g(round1)g(\(const)g Fi(t)m(yp)s(e)5 +b Fn(&)30 b(x\))480 2324 y Fp(Returns)f Fn(round\(x\))p +Fp(.)0 2635 y(Eac)m(h)39 b(of)g(the)g(classes)h Fn(cl_R)p +Fp(,)g Fn(cl_RA)p Fp(,)f Fn(cl_I)p Fp(,)h Fn(cl_F)p Fp(,)g +Fn(cl_SF)p Fp(,)f Fn(cl_FF)p Fp(,)h Fn(cl_DF)p Fp(,)g +Fn(cl_LF)d Fp(de\014nes)h(the)g(follo)m(wing)0 2760 y(op)s(erations:)0 +3070 y Fn(cl_I)29 b(floor1)g(\(const)g Fi(t)m(yp)s(e)5 +b Fn(&)30 b(x,)g(const)f Fi(t)m(yp)s(e)5 b Fn(&)30 b(y\))480 +3195 y Fp(Returns)f Fn(floor\(x/y\))p Fp(.)0 3381 y Fn(cl_I)g(ceiling1) +f(\(const)h Fi(t)m(yp)s(e)5 b Fn(&)30 b(x,)g(const)f +Fi(t)m(yp)s(e)5 b Fn(&)30 b(y\))480 3505 y Fp(Returns)f +Fn(ceiling\(x/y\))p Fp(.)0 3692 y Fn(cl_I)g(truncate1)f(\(const)h +Fi(t)m(yp)s(e)5 b Fn(&)30 b(x,)g(const)f Fi(t)m(yp)s(e)5 +b Fn(&)30 b(y\))480 3816 y Fp(Returns)f Fn(truncate\(x/y\))p +Fp(.)0 4002 y Fn(cl_I)g(round1)g(\(const)g Fi(t)m(yp)s(e)5 +b Fn(&)30 b(x,)g(const)f Fi(t)m(yp)s(e)5 b Fn(&)30 b(y\))480 +4127 y Fp(Returns)f Fn(round\(x/y\))p Fp(.)0 4437 y(These)41 +b(functions)g(are)h(called)h(`)p Fn(floor1)p Fp(',)g +Fl(:)15 b(:)g(:)42 b Fp(here)g(instead)f(of)h(`)p Fn(floor)p +Fp(',)i Fl(:)15 b(:)g(:)q Fp(,)44 b(b)s(ecause)d(on)h(some)f(systems,)0 +4562 y(system)30 b(dep)s(enden)m(t)f(include)h(\014les)g(de\014ne)g(`)p +Fn(floor)p Fp(')f(and)h(`)p Fn(ceiling)p Fp(')f(as)i(macros.)0 +4842 y(In)k(man)m(y)g(cases,)j(one)e(needs)g(b)s(oth)f(the)h(quotien)m +(t)h(and)e(the)h(remainder)e(of)i(a)g(division.)57 b(It)36 +b(is)g(more)e(e\016cien)m(t)0 4966 y(to)j(compute)e(b)s(oth)g(at)i(the) +f(same)f(time)g(than)h(to)h(p)s(erform)c(t)m(w)m(o)k(divisions,)h(one)e +(for)f(quotien)m(t)i(and)f(the)g(next)0 5091 y(one)h(for)g(the)h +(remainder.)59 b(The)37 b(follo)m(wing)h(functions)f(therefore)g +(return)g(a)g(structure)g(con)m(taining)h(b)s(oth)f(the)0 +5215 y(quotien)m(t)28 b(and)e(the)h(remainder.)38 b(The)27 +b(su\016x)e(`)p Fn(2)p Fp(')i(indicates)h(the)f(n)m(um)m(b)s(er)e(of)i +(\\return)f(v)-5 b(alues".)40 b(The)27 b(remainder)0 +5340 y(is)j(de\014ned)g(as)g(follo)m(ws:)p eop +%%Page: 19 21 +19 20 bop 0 -116 a Fp(Chapter)30 b(4:)41 b(F)-8 b(unctions)31 +b(on)f(n)m(um)m(b)s(ers)2463 b(19)75 366 y Fo(\017)60 +b Fp(for)30 b(the)h(computation)f(of)h Fn(quotient)d(=)i(floor\(x\))p +Fp(,)e Fn(remainder)g(=)i(x)g(-)g(quotient)p Fp(,)75 +540 y Fo(\017)60 b Fp(for)30 b(the)h(computation)f(of)h +Fn(quotient)d(=)i(floor\(x,y\))p Fp(,)e Fn(remainder)f(=)j(x)g(-)g +(quotient*y)p Fp(,)0 888 y(and)g(similarly)g(for)g(the)g(other)h(three) +g(op)s(erations.)0 1186 y(Eac)m(h)24 b(of)f(the)h(classes)g +Fn(cl_R)p Fp(,)g Fn(cl_RA)p Fp(,)g Fn(cl_F)p Fp(,)f Fn(cl_SF)p +Fp(,)h Fn(cl_FF)p Fp(,)f Fn(cl_DF)p Fp(,)h Fn(cl_LF)e +Fp(de\014nes)g(the)i(follo)m(wing)g(op)s(erations:)0 +1534 y Fn(struct)29 b Fi(t)m(yp)s(e)5 b Fn(_div_t)29 +b({)h(cl_I)f(quotient;)f Fi(t)m(yp)s(e)35 b Fn(remainder;)28 +b(};)0 1659 y Fi(t)m(yp)s(e)5 b Fn(_div_t)29 b(floor2)g(\(const)f +Fi(t)m(yp)s(e)5 b Fn(&)31 b(x\))0 1783 y Fi(t)m(yp)s(e)5 +b Fn(_div_t)29 b(ceiling2)f(\(const)h Fi(t)m(yp)s(e)5 +b Fn(&)30 b(x\))0 1908 y Fi(t)m(yp)s(e)5 b Fn(_div_t)29 +b(truncate2)f(\(const)h Fi(t)m(yp)s(e)5 b Fn(&)30 b(x\))0 +2032 y Fi(t)m(yp)s(e)5 b Fn(_div_t)29 b(round2)g(\(const)f +Fi(t)m(yp)s(e)5 b Fn(&)31 b(x\))0 2330 y Fp(Eac)m(h)39 +b(of)g(the)g(classes)h Fn(cl_R)p Fp(,)g Fn(cl_RA)p Fp(,)f +Fn(cl_I)p Fp(,)h Fn(cl_F)p Fp(,)g Fn(cl_SF)p Fp(,)f Fn(cl_FF)p +Fp(,)h Fn(cl_DF)p Fp(,)g Fn(cl_LF)d Fp(de\014nes)h(the)g(follo)m(wing)0 +2455 y(op)s(erations:)0 2803 y Fn(struct)29 b Fi(t)m(yp)s(e)5 +b Fn(_div_t)29 b({)h(cl_I)f(quotient;)f Fi(t)m(yp)s(e)35 +b Fn(remainder;)28 b(};)0 2927 y Fi(t)m(yp)s(e)5 b Fn(_div_t)29 +b(floor2)g(\(const)f Fi(t)m(yp)s(e)5 b Fn(&)31 b(x,)e(const)g +Fi(t)m(yp)s(e)5 b Fn(&)31 b(y\))0 3052 y Fi(t)m(yp)s(e)5 +b Fn(_div_t)29 b(ceiling2)f(\(const)h Fi(t)m(yp)s(e)5 +b Fn(&)30 b(x,)g(const)f Fi(t)m(yp)s(e)5 b Fn(&)30 b(y\))0 +3176 y Fi(t)m(yp)s(e)5 b Fn(_div_t)29 b(truncate2)f(\(const)h +Fi(t)m(yp)s(e)5 b Fn(&)30 b(x,)g(const)f Fi(t)m(yp)s(e)5 +b Fn(&)30 b(y\))0 3301 y Fi(t)m(yp)s(e)5 b Fn(_div_t)29 +b(round2)g(\(const)f Fi(t)m(yp)s(e)5 b Fn(&)31 b(x,)e(const)g +Fi(t)m(yp)s(e)5 b Fn(&)31 b(y\))0 3599 y Fp(Sometimes,)24 +b(one)h(w)m(an)m(ts)f(the)h(quotien)m(t)g(as)f(a)h(\015oating-p)s(oin)m +(t)g(n)m(um)m(b)s(er)d(\(of)i(the)h(same)e(format)h(as)g(the)g(argumen) +m(t,)0 3724 y(if)30 b(the)h(argumen)m(t)f(is)g(a)h(\015oat\))g(instead) +g(of)f(as)h(an)f(in)m(teger.)42 b(The)30 b(pre\014x)g(`)p +Fn(f)p Fp(')g(indicates)h(this.)0 4022 y(Eac)m(h)g(of)g(the)f(classes)i +Fn(cl_F)p Fp(,)d Fn(cl_SF)p Fp(,)g Fn(cl_FF)p Fp(,)g +Fn(cl_DF)p Fp(,)h Fn(cl_LF)e Fp(de\014nes)i(the)h(follo)m(wing)g(op)s +(erations:)0 4370 y Fi(t)m(yp)s(e)36 b Fn(ffloor)28 b(\(const)h +Fi(t)m(yp)s(e)5 b Fn(&)30 b(x\))0 4494 y Fi(t)m(yp)s(e)36 +b Fn(fceiling)28 b(\(const)g Fi(t)m(yp)s(e)5 b Fn(&)31 +b(x\))0 4619 y Fi(t)m(yp)s(e)36 b Fn(ftruncate)27 b(\(const)i +Fi(t)m(yp)s(e)5 b Fn(&)31 b(x\))0 4743 y Fi(t)m(yp)s(e)36 +b Fn(fround)28 b(\(const)h Fi(t)m(yp)s(e)5 b Fn(&)30 +b(x\))0 5042 y Fp(and)g(similarly)g(for)g(class)h Fn(cl_R)p +Fp(,)e(but)h(with)g(return)f(t)m(yp)s(e)i Fn(cl_F)p Fp(.)0 +5340 y(The)f(class)h Fn(cl_R)e Fp(de\014nes)h(the)g(follo)m(wing)i(op)s +(erations:)p eop +%%Page: 20 22 +20 21 bop 0 -116 a Fp(Chapter)30 b(4:)41 b(F)-8 b(unctions)31 +b(on)f(n)m(um)m(b)s(ers)2463 b(20)0 366 y Fn(cl_F)29 +b(ffloor)g(\(const)g Fi(t)m(yp)s(e)5 b Fn(&)30 b(x,)g(const)f +Fi(t)m(yp)s(e)5 b Fn(&)30 b(y\))0 491 y(cl_F)f(fceiling)f(\(const)h +Fi(t)m(yp)s(e)5 b Fn(&)30 b(x,)g(const)f Fi(t)m(yp)s(e)5 +b Fn(&)30 b(y\))0 616 y(cl_F)f(ftruncate)f(\(const)h +Fi(t)m(yp)s(e)5 b Fn(&)30 b(x,)g(const)f Fi(t)m(yp)s(e)5 +b Fn(&)30 b(y\))0 740 y(cl_F)f(fround)g(\(const)g Fi(t)m(yp)s(e)5 +b Fn(&)30 b(x,)g(const)f Fi(t)m(yp)s(e)5 b Fn(&)30 b(y\))0 +1024 y Fp(These)25 b(functions)h(also)g(exist)h(in)e(v)m(ersions)h +(whic)m(h)g(return)e(b)s(oth)h(the)h(quotien)m(t)h(and)e(the)h +(remainder.)38 b(The)25 b(su\016x)0 1149 y(`)p Fn(2)p +Fp(')31 b(indicates)g(this.)0 1433 y(Eac)m(h)g(of)g(the)f(classes)i +Fn(cl_F)p Fp(,)d Fn(cl_SF)p Fp(,)g Fn(cl_FF)p Fp(,)g +Fn(cl_DF)p Fp(,)h Fn(cl_LF)e Fp(de\014nes)i(the)h(follo)m(wing)g(op)s +(erations:)0 1752 y Fn(struct)e Fi(t)m(yp)s(e)5 b Fn(_fdiv_t)28 +b({)i Fi(t)m(yp)s(e)36 b Fn(quotient;)28 b Fi(t)m(yp)s(e)36 +b Fn(remainder;)27 b(};)0 1876 y Fi(t)m(yp)s(e)5 b Fn(_fdiv_t)29 +b(ffloor2)f(\(const)h Fi(t)m(yp)s(e)5 b Fn(&)30 b(x\))0 +2001 y Fi(t)m(yp)s(e)5 b Fn(_fdiv_t)29 b(fceiling2)f(\(const)g +Fi(t)m(yp)s(e)5 b Fn(&)31 b(x\))0 2126 y Fi(t)m(yp)s(e)5 +b Fn(_fdiv_t)29 b(ftruncate2)e(\(const)i Fi(t)m(yp)s(e)5 +b Fn(&)30 b(x\))0 2250 y Fi(t)m(yp)s(e)5 b Fn(_fdiv_t)29 +b(fround2)f(\(const)h Fi(t)m(yp)s(e)5 b Fn(&)30 b(x\))0 +2534 y Fp(and)g(similarly)g(for)g(class)h Fn(cl_R)p Fp(,)e(but)h(with)g +(quotien)m(t)i(t)m(yp)s(e)e Fn(cl_F)p Fp(.)0 2818 y(The)g(class)h +Fn(cl_R)e Fp(de\014nes)h(the)g(follo)m(wing)i(op)s(erations:)0 +3137 y Fn(struct)d Fi(t)m(yp)s(e)5 b Fn(_fdiv_t)28 b({)i(cl_F)g +(quotient;)d(cl_R)j(remainder;)d(};)0 3262 y Fi(t)m(yp)s(e)5 +b Fn(_fdiv_t)29 b(ffloor2)f(\(const)h Fi(t)m(yp)s(e)5 +b Fn(&)30 b(x,)g(const)f Fi(t)m(yp)s(e)5 b Fn(&)30 b(y\))0 +3386 y Fi(t)m(yp)s(e)5 b Fn(_fdiv_t)29 b(fceiling2)f(\(const)g +Fi(t)m(yp)s(e)5 b Fn(&)31 b(x,)e(const)g Fi(t)m(yp)s(e)5 +b Fn(&)31 b(y\))0 3511 y Fi(t)m(yp)s(e)5 b Fn(_fdiv_t)29 +b(ftruncate2)e(\(const)i Fi(t)m(yp)s(e)5 b Fn(&)30 b(x,)g(const)f +Fi(t)m(yp)s(e)5 b Fn(&)30 b(y\))0 3635 y Fi(t)m(yp)s(e)5 +b Fn(_fdiv_t)29 b(fround2)f(\(const)h Fi(t)m(yp)s(e)5 +b Fn(&)30 b(x,)g(const)f Fi(t)m(yp)s(e)5 b Fn(&)30 b(y\))0 +3920 y Fp(Other)i(applications)h(need)f(only)g(the)h(remainder)d(of)j +(a)f(division.)47 b(The)31 b(remainder)g(of)h(`)p Fn(floor)p +Fp(')g(and)f(`)p Fn(ffloor)p Fp(')0 4044 y(is)37 b(called)h(`)p +Fn(mod)p Fp(')e(\(abbreviation)h(of)g(\\mo)s(dulo"\).)59 +b(The)36 b(remainder)g(`)p Fn(truncate)p Fp(')e(and)i(`)p +Fn(ftruncate)p Fp(')f(is)i(called)0 4169 y(`)p Fn(rem)p +Fp(')30 b(\(abbreviation)h(of)g(\\remainder"\).)75 4453 +y Fo(\017)60 b Fn(mod\(x,y\))28 b(=)i(floor2\(x,y\).remainder)25 +b(=)30 b(x)g(-)g(floor\(x/y\)*y)75 4612 y Fo(\017)60 +b Fn(rem\(x,y\))28 b(=)i(truncate2\(x,y\).remainder)24 +b(=)30 b(x)g(-)g(truncate\(x/y\)*y)0 4931 y Fp(If)g Fn(x)f +Fp(and)h Fn(y)f Fp(are)i(b)s(oth)e Fn(>)p Fp(=)g(0,)i +Fn(mod\(x,y\))d(=)i(rem\(x,y\))e(>=)i(0)p Fp(.)41 b(In)29 +b(general,)i Fn(mod\(x,y\))d Fp(has)i(the)g(sign)g(of)g +Fn(y)g Fp(or)g(is)0 5056 y(zero,)h(and)f Fn(rem\(x,y\))e +Fp(has)i(the)h(sign)f(of)h Fn(x)f Fp(or)g(is)h(zero.)0 +5340 y(The)f(classes)h Fn(cl_R)p Fp(,)f Fn(cl_I)f Fp(de\014ne)h(the)g +(follo)m(wing)i(op)s(erations:)p eop +%%Page: 21 23 +21 22 bop 0 -116 a Fp(Chapter)30 b(4:)41 b(F)-8 b(unctions)31 +b(on)f(n)m(um)m(b)s(ers)2463 b(21)0 366 y Fi(t)m(yp)s(e)36 +b Fn(mod)29 b(\(const)g Fi(t)m(yp)s(e)5 b Fn(&)30 b(x,)g(const)f +Fi(t)m(yp)s(e)5 b Fn(&)30 b(y\))0 491 y Fi(t)m(yp)s(e)36 +b Fn(rem)29 b(\(const)g Fi(t)m(yp)s(e)5 b Fn(&)30 b(x,)g(const)f +Fi(t)m(yp)s(e)5 b Fn(&)30 b(y\))0 906 y Fq(4.7)68 b(Ro)t(ots)0 +1180 y Fp(Eac)m(h)31 b(of)g(the)f(classes)i Fn(cl_R)p +Fp(,)d Fn(cl_F)p Fp(,)g Fn(cl_SF)p Fp(,)h Fn(cl_FF)p +Fp(,)f Fn(cl_DF)p Fp(,)g Fn(cl_LF)g Fp(de\014nes)g(the)i(follo)m(wing)h +(op)s(eration:)0 1476 y Fi(t)m(yp)s(e)k Fn(sqrt)29 b(\(const)g +Fi(t)m(yp)s(e)5 b Fn(&)30 b(x\))480 1601 y(x)35 b Fp(m)m(ust)f(b)s(e)g +Fn(>)p Fp(=)h(0.)55 b(This)35 b(function)g(returns)e(the)j(square)f(ro) +s(ot)g(of)g Fn(x)p Fp(,)i(normalized)d(to)i(b)s(e)f Fn(>)p +Fp(=)f(0.)480 1725 y(If)c Fn(x)h Fp(is)g(the)g(square)f(of)h(a)g +(rational)h(n)m(um)m(b)s(er,)d Fn(sqrt\(x\))g Fp(will)i(b)s(e)f(a)i +(rational)g(n)m(um)m(b)s(er,)d(else)i(it)h(will)480 1850 +y(return)d(a)i(\015oating-p)s(oin)m(t)h(appro)m(ximation.)0 +2146 y(The)e(classes)h Fn(cl_RA)p Fp(,)e Fn(cl_I)h Fp(de\014ne)f(the)i +(follo)m(wing)h(op)s(eration:)0 2442 y Fn(cl_boolean)c(sqrtp)h(\(const) +f Fi(t)m(yp)s(e)5 b Fn(&)31 b(x,)e Fi(t)m(yp)s(e)5 b +Fn(*)31 b(root\))480 2567 y Fp(This)25 b(tests)i(whether)f +Fn(x)g Fp(is)g(a)g(p)s(erfect)g(square.)39 b(If)26 b(so,)i(it)e +(returns)f(true)h(and)g(the)g(exact)i(square)e(ro)s(ot)480 +2691 y(in)k Fn(*root)p Fp(,)f(else)i(it)g(returns)f(false.)0 +2988 y(F)-8 b(urthermore,)30 b(for)g(in)m(tegers,)i(similarly:)0 +3284 y Fn(cl_boolean)c(isqrt)h(\(const)f Fi(t)m(yp)s(e)5 +b Fn(&)31 b(x,)e Fi(t)m(yp)s(e)5 b Fn(*)31 b(root\))480 +3408 y(x)f Fp(should)g(b)s(e)g Fn(>)p Fp(=)g(0.)42 b(This)30 +b(function)h(sets)g Fn(*root)e Fp(to)i Fn(floor\(sqrt\(x\)\))c +Fp(and)j(returns)g(the)h(same)480 3533 y(v)-5 b(alue)31 +b(as)f Fn(sqrtp)p Fp(:)40 b(the)30 b(b)s(o)s(olean)h(v)-5 +b(alue)31 b Fn(\(expt\(*root,2\))26 b(==)k(x\))p Fp(.)0 +3829 y(F)-8 b(or)31 b Fn(n)p Fp(th)f(ro)s(ots,)h(the)f(classes)i +Fn(cl_RA)p Fp(,)d Fn(cl_I)g Fp(de\014ne)h(the)g(follo)m(wing)i(op)s +(eration:)0 4125 y Fn(cl_boolean)c(rootp)h(\(const)f +Fi(t)m(yp)s(e)5 b Fn(&)31 b(x,)e(const)g(cl_I&)g(n,)h +Fi(t)m(yp)s(e)5 b Fn(*)30 b(root\))480 4250 y(x)36 b +Fp(m)m(ust)f(b)s(e)g Fn(>)p Fp(=)g(0.)58 b Fn(n)36 b +Fp(m)m(ust)f(b)s(e)g Fn(>)h Fp(0.)58 b(This)35 b(tests)i(whether)e +Fn(x)h Fp(is)g(an)g Fn(n)p Fp(th)f(p)s(o)m(w)m(er)h(of)g(a)h(rational) +480 4374 y(n)m(um)m(b)s(er.)h(If)30 b(so,)h(it)g(returns)e(true)h(and)g +(the)h(exact)h(ro)s(ot)e(in)g Fn(*root)p Fp(,)g(else)h(it)g(returns)e +(false.)0 4670 y(The)h(only)g(square)g(ro)s(ot)h(function)f(whic)m(h)g +(accepts)i(negativ)m(e)h(n)m(um)m(b)s(ers)28 b(is)i(the)h(one)f(for)g +(class)h Fn(cl_N)p Fp(:)0 4966 y Fn(cl_N)e(sqrt)g(\(const)g(cl_N&)g +(z\))480 5091 y Fp(Returns)38 b(the)i(square)f(ro)s(ot)h(of)f +Fn(z)p Fp(,)j(as)d(de\014ned)g(b)m(y)g(the)g(form)m(ula)g +Fn(sqrt\(z\))28 b(=)i(exp\(log\(z\)/2\))p Fp(.)480 5215 +y(Con)m(v)m(ersion)44 b(to)g(a)f(\015oating-p)s(oin)m(t)i(t)m(yp)s(e)e +(or)h(to)g(a)f(complex)g(n)m(um)m(b)s(er)e(are)j(done)f(if)g(necessary) +-8 b(.)480 5340 y(The)31 b(range)h(of)g(the)g(result)g(is)g(the)g(righ) +m(t)g(half)g(plane)g Fn(realpart\(sqrt\(z\)\))25 b(>=)30 +b(0)h Fp(including)h(the)p eop +%%Page: 22 24 +22 23 bop 0 -116 a Fp(Chapter)30 b(4:)41 b(F)-8 b(unctions)31 +b(on)f(n)m(um)m(b)s(ers)2463 b(22)480 366 y(p)s(ositiv)m(e)35 +b(imaginary)e(axis)h(and)g(0,)h(but)e(excluding)h(the)g(negativ)m(e)i +(imaginary)d(axis.)52 b(The)33 b(result)480 491 y(is)d(an)h(exact)h(n)m +(um)m(b)s(er)c(only)i(if)g Fn(z)g Fp(is)h(an)f(exact)i(n)m(um)m(b)s +(er.)0 930 y Fq(4.8)68 b(T)-11 b(ranscenden)l(tal)31 +b(functions)0 1204 y Fp(The)c(transcenden)m(tal)h(functions)e(return)h +(an)g(exact)h(result)f(if)g(the)h(argumen)m(t)e(is)i(exact)g(and)f(the) +g(result)g(is)g(exact)0 1329 y(as)k(w)m(ell.)44 b(Otherwise)31 +b(they)g(m)m(ust)f(return)g(inexact)i(n)m(um)m(b)s(ers)d(ev)m(en)j(if)f +(the)g(argumen)m(t)g(is)g(exact.)44 b(F)-8 b(or)32 b(example,)0 +1453 y Fn(cos\(0\))d(=)h(1)g Fp(returns)f(the)h(rational)i(n)m(um)m(b)s +(er)c Fn(1)p Fp(.)0 1860 y Fk(4.8.1)63 b(Exp)s(onen)m(tial)30 +b(and)g(logarithmic)g(functions)0 2156 y Fn(cl_R)f(exp)h(\(const)e +(cl_R&)h(x\))0 2281 y(cl_N)g(exp)h(\(const)e(cl_N&)h(x\))480 +2405 y Fp(Returns)j(the)h(exp)s(onen)m(tial)h(function)f(of)g +Fn(x)p Fp(.)48 b(This)32 b(is)h Fn(e^x)f Fp(where)g Fn(e)h +Fp(is)g(the)g(base)g(of)g(the)g(natural)480 2530 y(logarithms.)41 +b(The)29 b(range)i(of)g(the)f(result)h(is)f(the)h(en)m(tire)g(complex)f +(plane)g(excluding)h(0.)0 2700 y Fn(cl_R)e(ln)h(\(const)f(cl_R&)g(x\)) +480 2824 y(x)h Fp(m)m(ust)f(b)s(e)h Fn(>)g Fp(0.)41 b(Returns)30 +b(the)g(\(natural\))h(logarithm)g(of)f(x.)0 2994 y Fn(cl_N)f(log)h +(\(const)e(cl_N&)h(x\))480 3119 y Fp(Returns)43 b(the)i(\(natural\))f +(logarithm)h(of)f(x.)82 b(If)44 b Fn(x)f Fp(is)i(real)f(and)g(p)s +(ositiv)m(e,)49 b(this)44 b(is)g Fn(ln\(x\))p Fp(.)81 +b(In)480 3243 y(general,)34 b Fn(log\(x\))29 b(=)h(log\(abs\(x\)\))d(+) +j(i*phase\(x\))p Fp(.)45 b(The)32 b(range)g(of)h(the)g(result)f(is)h +(the)f(strip)g(in)480 3368 y(the)f(complex)f(plane)g +Fn(-pi)g(<)g(imagpart\(log\(x\)\))25 b(<=)30 b(pi)p Fp(.)0 +3538 y Fn(cl_R)f(phase)g(\(const)g(cl_N&)g(x\))480 3662 +y Fp(Returns)38 b(the)h(angle)g(part)g(of)g Fn(x)f Fp(in)g(its)h(p)s +(olar)g(represen)m(tation)g(as)g(a)g(complex)g(n)m(um)m(b)s(er.)63 +b(That)480 3787 y(is,)34 b Fn(phase\(x\))28 b(=)i +(atan\(realpart\(x\),imagpart)o(\(x\)\))o Fp(.)43 b(This)33 +b(is)g(also)h(the)f(imaginary)g(part)g(of)480 3911 y +Fn(log\(x\))p Fp(.)41 b(The)31 b(range)g(of)g(the)h(result)f(is)g(the)g +(in)m(terv)-5 b(al)32 b Fn(-pi)e(<)g(phase\(x\))e(<=)i(pi)p +Fp(.)42 b(The)31 b(result)g(will)480 4036 y(b)s(e)f(an)g(exact)i(n)m +(um)m(b)s(er)c(only)i(if)h Fn(zerop\(x\))d Fp(or)i(if)h +Fn(x)f Fp(is)g(real)h(and)f(p)s(ositiv)m(e.)0 4206 y +Fn(cl_R)f(log)h(\(const)e(cl_R&)h(a,)h(const)f(cl_R&)g(b\))480 +4330 y(a)j Fp(and)g Fn(b)g Fp(m)m(ust)g(b)s(e)g Fn(>)g +Fp(0.)48 b(Returns)31 b(the)i(logarithm)g(of)f Fn(a)g +Fp(with)h(resp)s(ect)f(to)i(base)e Fn(b)p Fp(.)47 b Fn(log\(a,b\))28 +b(=)480 4455 y(ln\(a\)/ln\(b\))p Fp(.)38 b(The)30 b(result)g(can)g(b)s +(e)g(exact)i(only)f(if)f Fn(a)g(=)g(1)g Fp(or)g(if)h +Fn(a)f Fp(and)g Fn(b)g Fp(are)g(b)s(oth)g(rational.)0 +4624 y Fn(cl_N)f(log)h(\(const)e(cl_N&)h(a,)h(const)f(cl_N&)g(b\))480 +4749 y Fp(Returns)g(the)i(logarithm)f(of)h Fn(a)f Fp(with)g(resp)s(ect) +g(to)i(base)e Fn(b)p Fp(.)40 b Fn(log\(a,b\))29 b(=)h +(log\(a\)/log\(b\))p Fp(.)0 4919 y Fn(cl_N)f(expt)g(\(const)g(cl_N&)g +(x,)h(const)f(cl_N&)g(y\))480 5043 y Fp(Exp)s(onen)m(tiation:)42 +b(Returns)29 b Fn(x^y)g(=)h(exp\(y*log\(x\)\))p Fp(.)0 +5340 y(The)g(constan)m(t)i(e)e(=)g(exp\(1\))i(=)e(2.71828)p +Fl(:)15 b(:)g(:)34 b Fp(is)c(returned)g(b)m(y)g(the)g(follo)m(wing)i +(functions:)p eop +%%Page: 23 25 +23 24 bop 0 -116 a Fp(Chapter)30 b(4:)41 b(F)-8 b(unctions)31 +b(on)f(n)m(um)m(b)s(ers)2463 b(23)0 366 y Fn(cl_F)29 +b(cl_exp1)g(\(cl_float_format_t)c(f\))480 491 y Fp(Returns)k(e)i(as)g +(a)g(\015oat)g(of)f(format)g Fn(f)p Fp(.)0 657 y Fn(cl_F)f(cl_exp1)g +(\(const)f(cl_F&)h(y\))480 782 y Fp(Returns)g(e)i(in)f(the)h(\015oat)g +(format)f(of)g Fn(y)p Fp(.)0 948 y Fn(cl_F)f(cl_exp1)g(\(void\))480 +1073 y Fp(Returns)g(e)i(as)g(a)g(\015oat)g(of)f(format)g +Fn(cl_default_float_format)p Fp(.)0 1472 y Fk(4.8.2)63 +b(T)-10 b(rigonometric)30 b(functions)0 1767 y Fn(cl_R)f(sin)h(\(const) +e(cl_R&)h(x\))480 1892 y Fp(Returns)g Fn(sin\(x\))p Fp(.)39 +b(The)30 b(range)h(of)g(the)f(result)g(is)h(the)f(in)m(terv)-5 +b(al)32 b Fn(-1)e(<=)f(sin\(x\))g(<=)h(1)p Fp(.)0 2058 +y Fn(cl_N)f(sin)h(\(const)e(cl_N&)h(z\))480 2183 y Fp(Returns)g +Fn(sin\(z\))p Fp(.)39 b(The)30 b(range)h(of)g(the)f(result)g(is)h(the)f +(en)m(tire)i(complex)e(plane.)0 2349 y Fn(cl_R)f(cos)h(\(const)e(cl_R&) +h(x\))480 2474 y Fp(Returns)g Fn(cos\(x\))p Fp(.)39 b(The)30 +b(range)h(of)g(the)f(result)g(is)h(the)f(in)m(terv)-5 +b(al)32 b Fn(-1)e(<=)f(cos\(x\))g(<=)h(1)p Fp(.)0 2640 +y Fn(cl_N)f(cos)h(\(const)e(cl_N&)h(x\))480 2764 y Fp(Returns)g +Fn(cos\(z\))p Fp(.)39 b(The)30 b(range)h(of)g(the)f(result)g(is)h(the)f +(en)m(tire)i(complex)e(plane.)0 2931 y Fn(struct)f(cl_cos_sin_t)e({)j +(cl_R)f(cos;)g(cl_R)g(sin;)h(};)0 3055 y(cl_cos_sin_t)d(cl_cos_sin)h +(\(const)g(cl_R&)h(x\))480 3180 y Fp(Returns)k(b)s(oth)h +Fn(sin\(x\))f Fp(and)g Fn(cos\(x\))p Fp(.)51 b(This)34 +b(is)g(more)g(e\016cien)m(t)i(than)e(computing)f(them)g(sepa-)480 +3304 y(rately)-8 b(.)42 b(The)30 b(relation)i Fn(cos^2)d(+)h(sin^2)e(=) +j(1)f Fp(will)g(hold)g(only)h(appro)m(ximately)-8 b(.)0 +3471 y Fn(cl_R)29 b(tan)h(\(const)e(cl_R&)h(x\))0 3595 +y(cl_N)g(tan)h(\(const)e(cl_N&)h(x\))480 3720 y Fp(Returns)g +Fn(tan\(x\))g(=)h(sin\(x\)/cos\(x\))p Fp(.)0 3886 y Fn(cl_N)f(cis)h +(\(const)e(cl_R&)h(x\))0 4011 y(cl_N)g(cis)h(\(const)e(cl_N&)h(x\))480 +4135 y Fp(Returns)h Fn(exp\(i*x\))p Fp(.)41 b(The)30 +b(name)g(`)p Fn(cis)p Fp(')h(means)f(\\cos)i Fn(+)f Fp(i)g(sin",)g(b)s +(ecause)g Fn(e^\(i*x\))e(=)h(cos\(x\))e(+)480 4260 y(i*sin\(x\))p +Fp(.)0 4426 y Fn(cl_N)h(asin)g(\(const)g(cl_N&)g(z\))480 +4551 y Fp(Returns)24 b Fn(arcsin\(z\))p Fp(.)37 b(This)24 +b(is)h(de\014ned)f(as)h Fn(arcsin\(z\))j(=)i(log\(iz+sqrt\(1-z^2\)\)/i) +20 b Fp(and)k(sat-)480 4675 y(is\014es)g Fn(arcsin\(-z\))j(=)j +(-arcsin\(z\))p Fp(.)36 b(The)23 b(range)i(of)f(the)g(result)f(is)h +(the)g(strip)g(in)f(the)h(complex)g(do-)480 4800 y(main)g +Fn(-pi/2)29 b(<=)h(realpart\(arcsin\(z\)\))25 b(<=)30 +b(pi/2)p Fp(,)25 b(excluding)g(the)h(n)m(um)m(b)s(ers)c(with)j +Fn(realpart)480 4925 y(=)30 b(-pi/2)c Fp(and)g Fn(imagpart)i(<)i(0)d +Fp(and)f(the)h(n)m(um)m(b)s(ers)e(with)i Fn(realpart)h(=)i(pi/2)25 +b Fp(and)i Fn(imagpart)h(>)i(0)p Fp(.)0 5091 y Fn(cl_N)f(acos)g +(\(const)g(cl_N&)g(z\))480 5215 y Fp(Returns)19 b Fn(arccos\(z\))p +Fp(.)35 b(This)20 b(is)g(de\014ned)f(as)i Fn(arccos\(z\))27 +b(=)j(pi/2)g(-)g(arcsin\(z\))d(=)k(log\(z+i*sqrt\(1-)480 +5340 y(z^2\)\)/i)36 b Fp(and)i(satis\014es)g Fn(arccos\(-z\))28 +b(=)i(pi)g(-)g(arccos\(z\))p Fp(.)61 b(The)38 b(range)h(of)f(the)g +(result)h(is)f(the)p eop +%%Page: 24 26 +24 25 bop 0 -116 a Fp(Chapter)30 b(4:)41 b(F)-8 b(unctions)31 +b(on)f(n)m(um)m(b)s(ers)2463 b(24)480 366 y(strip)40 +b(in)f(the)i(complex)e(domain)g Fn(0)30 b(<=)g(realpart\(arcsin\(z\)\)) +25 b(<=)30 b(pi)p Fp(,)42 b(excluding)e(the)g(n)m(um-)480 +491 y(b)s(ers)33 b(with)g Fn(realpart)28 b(=)i(0)k Fp(and)f +Fn(imagpart)28 b(<)i(0)k Fp(and)f(the)h(n)m(um)m(b)s(ers)e(with)h +Fn(realpart)28 b(=)i(pi)k Fp(and)480 616 y Fn(imagpart)28 +b(>)i(0)p Fp(.)0 785 y Fn(cl_R)f(atan)g(\(const)g(cl_R&)g(x,)h(const)f +(cl_R&)g(y\))480 910 y Fp(Returns)37 b(the)i(angle)g(of)g(the)f(p)s +(olar)g(represen)m(tation)h(of)g(the)f(complex)g(n)m(um)m(b)s(er)e +Fn(x+iy)p Fp(.)63 b(This)38 b(is)480 1034 y Fn(atan\(y/x\))27 +b Fp(if)i Fn(x>0)p Fp(.)40 b(The)28 b(range)i(of)f(the)h(result)f(is)h +(the)f(in)m(terv)-5 b(al)31 b Fn(-pi)e(<)h(atan\(x,y\))e(<=)i(pi)p +Fp(.)39 b(The)480 1159 y(result)j(will)g(b)s(e)f(an)g(exact)i(n)m(um)m +(b)s(er)d(only)h(if)h Fn(x)30 b(>)g(0)41 b Fp(and)h Fn(y)f +Fp(is)h(the)f(exact)j Fn(0)p Fp(.)74 b(W)-10 b(ARNING:)43 +b(In)480 1283 y(Common)26 b(Lisp,)i(this)g(function)g(is)g(called)h(as) +g Fn(\(atan)g(y)h(x\))p Fp(,)e(with)g(rev)m(ersed)g(order)g(of)g +(argumen)m(ts.)0 1453 y Fn(cl_R)h(atan)g(\(const)g(cl_R&)g(x\))480 +1578 y Fp(Returns)36 b Fn(arctan\(x\))p Fp(.)59 b(This)37 +b(is)g(the)g(same)g(as)g Fn(atan\(1,x\))p Fp(.)59 b(The)37 +b(range)g(of)h(the)f(result)g(is)h(the)480 1702 y(in)m(terv)-5 +b(al)34 b Fn(-pi/2)29 b(<)h(atan\(x\))e(<)i(pi/2)p Fp(.)47 +b(The)32 b(result)g(will)h(b)s(e)f(an)h(exact)h(n)m(um)m(b)s(er)c(only) +j(if)g Fn(x)f Fp(is)h(the)480 1827 y(exact)f Fn(0)p Fp(.)0 +1996 y Fn(cl_N)d(atan)g(\(const)g(cl_N&)g(z\))480 2121 +y Fp(Returns)43 b Fn(arctan\(z\))p Fp(.)80 b(This)44 +b(is)g(de\014ned)g(as)g Fn(arctan\(z\))28 b(=)i +(\(log\(1+iz\)-log\(1-iz\)\))25 b(/)30 b(2i)480 2245 +y Fp(and)23 b(satis\014es)h Fn(arctan\(-z\))k(=)i(-arctan\(z\))p +Fp(.)35 b(The)23 b(range)h(of)g(the)g(result)f(is)h(the)g(strip)f(in)g +(the)h(com-)480 2370 y(plex)45 b(domain)f Fn(-pi/2)29 +b(<=)h(realpart\(arctan\(z\)\))25 b(<=)30 b(pi/2)p Fp(,)47 +b(excluding)e(the)h(n)m(um)m(b)s(ers)c(with)480 2494 +y Fn(realpart)28 b(=)i(-pi/2)42 b Fp(and)h Fn(imagpart)28 +b(>=)i(0)42 b Fp(and)h(the)h(n)m(um)m(b)s(ers)c(with)j +Fn(realpart)28 b(=)i(pi/2)43 b Fp(and)480 2619 y Fn(imagpart)28 +b(<=)i(0)p Fp(.)0 2915 y(The)g(constan)m(t)i(pi)e(=)g(3.14)p +Fl(:)15 b(:)g(:)33 b Fp(is)d(returned)f(b)m(y)h(the)h(follo)m(wing)h +(functions:)0 3212 y Fn(cl_F)d(cl_pi)g(\(cl_float_format_t)d(f\))480 +3336 y Fp(Returns)j(pi)i(as)f(a)h(\015oat)g(of)f(format)g +Fn(f)p Fp(.)0 3506 y Fn(cl_F)f(cl_pi)g(\(const)g(cl_F&)g(y\))480 +3631 y Fp(Returns)g(pi)i(in)f(the)g(\015oat)h(format)f(of)g +Fn(y)p Fp(.)0 3800 y Fn(cl_F)f(cl_pi)g(\(void\))480 3925 +y Fp(Returns)g(pi)i(as)f(a)h(\015oat)g(of)f(format)g +Fn(cl_default_float_format)p Fp(.)0 4331 y Fk(4.8.3)63 +b(Hyp)s(erb)s(olic)31 b(functions)0 4627 y Fn(cl_R)e(sinh)g(\(const)g +(cl_R&)g(x\))480 4752 y Fp(Returns)g Fn(sinh\(x\))p Fp(.)0 +4921 y Fn(cl_N)g(sinh)g(\(const)g(cl_N&)g(z\))480 5046 +y Fp(Returns)g Fn(sinh\(z\))p Fp(.)39 b(The)30 b(range)h(of)f(the)h +(result)f(is)h(the)f(en)m(tire)h(complex)g(plane.)0 5215 +y Fn(cl_R)e(cosh)g(\(const)g(cl_R&)g(x\))480 5340 y Fp(Returns)g +Fn(cosh\(x\))p Fp(.)39 b(The)30 b(range)h(of)f(the)h(result)f(is)h(the) +f(in)m(terv)-5 b(al)32 b Fn(cosh\(x\))c(>=)i(1)p Fp(.)p +eop +%%Page: 25 27 +25 26 bop 0 -116 a Fp(Chapter)30 b(4:)41 b(F)-8 b(unctions)31 +b(on)f(n)m(um)m(b)s(ers)2463 b(25)0 366 y Fn(cl_N)29 +b(cosh)g(\(const)g(cl_N&)g(z\))480 491 y Fp(Returns)g +Fn(cosh\(z\))p Fp(.)39 b(The)30 b(range)h(of)f(the)h(result)f(is)h(the) +f(en)m(tire)h(complex)g(plane.)0 667 y Fn(struct)e(cl_cosh_sinh_t)d({)k +(cl_R)f(cosh;)g(cl_R)h(sinh;)e(};)0 792 y(cl_cosh_sinh_t)e +(cl_cosh_sinh)i(\(const)g(cl_R&)h(x\))480 916 y Fp(Returns)44 +b(b)s(oth)h Fn(sinh\(x\))e Fp(and)i Fn(cosh\(x\))p Fp(.)83 +b(This)44 b(is)i(more)e(e\016cien)m(t)j(than)e(computing)f(them)480 +1041 y(separately)-8 b(.)42 b(The)30 b(relation)i Fn(cosh^2)c(-)j +(sinh^2)d(=)i(1)g Fp(will)h(hold)f(only)g(appro)m(ximately)-8 +b(.)0 1217 y Fn(cl_R)29 b(tanh)g(\(const)g(cl_R&)g(x\))0 +1342 y(cl_N)g(tanh)g(\(const)g(cl_N&)g(x\))480 1466 y +Fp(Returns)g Fn(tanh\(x\))g(=)h(sinh\(x\)/cosh\(x\))p +Fp(.)0 1643 y Fn(cl_N)f(asinh)g(\(const)g(cl_N&)g(z\))480 +1767 y Fp(Returns)22 b Fn(arsinh\(z\))p Fp(.)36 b(This)22 +b(is)i(de\014ned)d(as)j Fn(arsinh\(z\))k(=)i(log\(z+sqrt\(1+z^2\)\))18 +b Fp(and)k(satis\014es)480 1892 y Fn(arsinh\(-z\))28 +b(=)i(-arsinh\(z\))p Fp(.)37 b(The)27 b(range)h(of)g(the)g(result)g(is) +g(the)g(strip)f(in)h(the)g(complex)f(domain)480 2016 +y Fn(-pi/2)i(<=)h(imagpart\(arsinh\(z\)\))25 b(<=)30 +b(pi/2)p Fp(,)39 b(excluding)f(the)h(n)m(um)m(b)s(ers)c(with)j +Fn(imagpart)28 b(=)i(-)480 2141 y(pi/2)f Fp(and)h Fn(realpart)e(>)i(0)g +Fp(and)g(the)g(n)m(um)m(b)s(ers)e(with)i Fn(imagpart)f(=)h(pi/2)f +Fp(and)h Fn(realpart)e(<)i(0)p Fp(.)0 2317 y Fn(cl_N)f(acosh)g(\(const) +g(cl_N&)g(z\))480 2442 y Fp(Returns)d Fn(arcosh\(z\))p +Fp(.)37 b(This)26 b(is)h(de\014ned)f(as)h Fn(arcosh\(z\))h(=)i +(2*log\(sqrt\(\(z+1\)/2\)+sqr)o(t\(\(z)o(-)480 2566 y(1\)/2\)\))p +Fp(.)102 b(The)51 b(range)h(of)g(the)g(result)f(is)g(the)h(half-strip)f +(in)h(the)f(complex)g(domain)g Fn(-pi)29 b(<)480 2691 +y(imagpart\(arcosh\(z\)\))c(<=)30 b(pi,)f(realpart\(arcosh\(z\)\))c(>=) +30 b(0)p Fp(,)76 b(excluding)67 b(the)f(n)m(um)m(b)s(ers)480 +2815 y(with)30 b Fn(realpart)e(=)i(0)g Fp(and)g Fn(-pi)g(<)g(imagpart)e +(<)i(0)p Fp(.)0 2991 y Fn(cl_N)f(atanh)g(\(const)g(cl_N&)g(z\))480 +3116 y Fp(Returns)38 b Fn(artanh\(z\))p Fp(.)64 b(This)39 +b(is)g(de\014ned)f(as)h Fn(artanh\(z\))28 b(=)i +(\(log\(1+z\)-log\(1-z\)\))25 b(/)30 b(2)39 b Fp(and)480 +3241 y(satis\014es)f Fn(artanh\(-z\))27 b(=)j(-artanh\(z\))p +Fp(.)58 b(The)37 b(range)g(of)g(the)g(result)g(is)g(the)h(strip)e(in)h +(the)g(com-)480 3365 y(plex)45 b(domain)f Fn(-pi/2)29 +b(<=)h(imagpart\(artanh\(z\)\))25 b(<=)30 b(pi/2)p Fp(,)47 +b(excluding)e(the)h(n)m(um)m(b)s(ers)c(with)480 3490 +y Fn(imagpart)28 b(=)i(-pi/2)42 b Fp(and)h Fn(realpart)28 +b(<=)i(0)42 b Fp(and)h(the)h(n)m(um)m(b)s(ers)c(with)j +Fn(imagpart)28 b(=)i(pi/2)43 b Fp(and)480 3614 y Fn(realpart)28 +b(>=)i(0)p Fp(.)0 4038 y Fk(4.8.4)63 b(Euler)30 b(gamma)0 +4313 y Fp(Euler's)g(constan)m(t)i(C)e(=)g(0.577)p Fl(:)15 +b(:)g(:)33 b Fp(is)e(returned)e(b)m(y)h(the)h(follo)m(wing)g +(functions:)0 4614 y Fn(cl_F)e(cl_eulerconst)e(\(cl_float_format_t)e +(f\))480 4738 y Fp(Returns)k(Euler's)i(constan)m(t)g(as)g(a)g(\015oat)g +(of)f(format)g Fn(f)p Fp(.)0 4915 y Fn(cl_F)f(cl_eulerconst)e(\(const)i +(cl_F&)g(y\))480 5039 y Fp(Returns)g(Euler's)i(constan)m(t)g(in)f(the)h +(\015oat)g(format)f(of)g Fn(y)p Fp(.)0 5215 y Fn(cl_F)f(cl_eulerconst)e +(\(void\))480 5340 y Fp(Returns)i(Euler's)i(constan)m(t)g(as)g(a)g +(\015oat)g(of)f(format)g Fn(cl_default_float_format)p +Fp(.)p eop +%%Page: 26 28 +26 27 bop 0 -116 a Fp(Chapter)30 b(4:)41 b(F)-8 b(unctions)31 +b(on)f(n)m(um)m(b)s(ers)2463 b(26)0 366 y(Catalan's)32 +b(constan)m(t)f(G)g(=)f(0.915)p Fl(:)15 b(:)g(:)33 b +Fp(is)e(returned)e(b)m(y)h(the)h(follo)m(wing)h(functions:)0 +676 y Fn(cl_F)d(cl_catalanconst)d(\(cl_float_format_t)g(f\))480 +800 y Fp(Returns)j(Catalan's)j(constan)m(t)g(as)e(a)h(\015oat)g(of)g +(format)e Fn(f)p Fp(.)0 985 y Fn(cl_F)g(cl_catalanconst)d(\(const)j +(cl_F&)g(y\))480 1110 y Fp(Returns)g(Catalan's)j(constan)m(t)g(in)e +(the)g(\015oat)h(format)f(of)h Fn(y)p Fp(.)0 1294 y Fn(cl_F)e +(cl_catalanconst)d(\(void\))480 1419 y Fp(Returns)j(Catalan's)j +(constan)m(t)g(as)e(a)h(\015oat)g(of)g(format)e Fn +(cl_default_float_format)p Fp(.)0 1881 y Fk(4.8.5)63 +b(Riemann)29 b(zeta)0 2160 y Fp(Riemann's)g(zeta)j(function)e(at)h(an)g +(in)m(tegral)h(p)s(oin)m(t)e Fn(s>1)f Fp(is)i(returned)e(b)m(y)h(the)h +(follo)m(wing)h(functions:)0 2470 y Fn(cl_F)d(cl_zeta)g(\(int)g(s,)h +(cl_float_format_t)25 b(f\))480 2594 y Fp(Returns)k(Riemann's)h(zeta)i +(function)e(at)h Fn(s)f Fp(as)g(a)h(\015oat)g(of)g(format)e +Fn(f)p Fp(.)0 2779 y Fn(cl_F)g(cl_zeta)g(\(int)g(s,)h(const)f(cl_F&)f +(y\))480 2904 y Fp(Returns)h(Riemann's)h(zeta)i(function)e(at)h +Fn(s)f Fp(in)g(the)g(\015oat)h(format)f(of)h Fn(y)p Fp(.)0 +3088 y Fn(cl_F)e(cl_zeta)g(\(int)g(s\))480 3213 y Fp(Returns)e +(Riemann's)g(zeta)j(function)d(at)i Fn(s)f Fp(as)g(a)h(\015oat)f(of)h +(format)e Fn(cl_default_float_format)p Fp(.)0 3708 y +Fq(4.9)68 b(F)-11 b(unctions)30 b(on)g(in)l(tegers)0 +4170 y Fk(4.9.1)63 b(Logical)30 b(functions)0 4450 y +Fp(In)m(tegers,)e(when)c(view)m(ed)i(as)g(in)f(t)m(w)m(o's)i(complemen) +m(t)e(notation,)j(can)e(b)s(e)f(though)m(t)h(as)f(in\014nite)h(bit)f +(strings)g(where)0 4574 y(the)31 b(bits')f(v)-5 b(alues)31 +b(ev)m(en)m(tually)h(are)f(constan)m(t.)42 b(F)-8 b(or)31 +b(example,)431 4832 y Fn(17)47 b(=)h(......00010001)431 +4936 y(-6)f(=)h(......11111010)0 5215 y Fp(The)30 b(logical)i(op)s +(erations)f(view)f(in)m(tegers)h(as)g(suc)m(h)f(bit)g(strings)g(and)f +(op)s(erate)i(on)f(eac)m(h)h(of)g(the)f(bit)g(p)s(ositions)g(in)0 +5340 y(parallel.)p eop +%%Page: 27 29 +27 28 bop 0 -116 a Fp(Chapter)30 b(4:)41 b(F)-8 b(unctions)31 +b(on)f(n)m(um)m(b)s(ers)2463 b(27)0 366 y Fn(cl_I)29 +b(lognot)g(\(const)g(cl_I&)f(x\))0 491 y(cl_I)h(operator)f(~)i(\(const) +f(cl_I&)g(x\))480 616 y Fp(Logical)j(not,)f(lik)m(e)h +Fn(~x)e Fp(in)g(C.)g(This)g(is)g(the)h(same)e(as)i Fn(-1-x)p +Fp(.)0 776 y Fn(cl_I)e(logand)g(\(const)g(cl_I&)f(x,)i(const)f(cl_I&)g +(y\))0 900 y(cl_I)g(operator)f(&)i(\(const)f(cl_I&)g(x,)h(const)f +(cl_I&)g(y\))480 1025 y Fp(Logical)j(and,)e(lik)m(e)i +Fn(x)e(&)g(y)g Fp(in)g(C.)0 1185 y Fn(cl_I)f(logior)g(\(const)g(cl_I&)f +(x,)i(const)f(cl_I&)g(y\))0 1309 y(cl_I)g(operator)f(|)i(\(const)f +(cl_I&)g(x,)h(const)f(cl_I&)g(y\))480 1434 y Fp(Logical)j(\(inclusiv)m +(e\))g(or,)f(lik)m(e)h Fn(x)e(|)g(y)g Fp(in)g(C.)0 1594 +y Fn(cl_I)f(logxor)g(\(const)g(cl_I&)f(x,)i(const)f(cl_I&)g(y\))0 +1718 y(cl_I)g(operator)f(^)i(\(const)f(cl_I&)g(x,)h(const)f(cl_I&)g +(y\))480 1843 y Fp(Exclusiv)m(e)i(or,)g(lik)m(e)h Fn(x)e(^)g(y)g +Fp(in)g(C.)0 2003 y Fn(cl_I)f(logeqv)g(\(const)g(cl_I&)f(x,)i(const)f +(cl_I&)g(y\))480 2127 y Fp(Bit)m(wise)j(equiv)-5 b(alence,)32 +b(lik)m(e)g Fn(~\(x)d(^)h(y\))g Fp(in)g(C.)0 2288 y Fn(cl_I)f(lognand)g +(\(const)f(cl_I&)h(x,)h(const)f(cl_I&)g(y\))480 2412 +y Fp(Bit)m(wise)j(not)f(and,)f(lik)m(e)h Fn(~\(x)f(&)g(y\))g +Fp(in)g(C.)0 2572 y Fn(cl_I)f(lognor)g(\(const)g(cl_I&)f(x,)i(const)f +(cl_I&)g(y\))480 2697 y Fp(Bit)m(wise)j(not)f(or,)f(lik)m(e)i +Fn(~\(x)d(|)h(y\))g Fp(in)g(C.)0 2857 y Fn(cl_I)f(logandc1)f(\(const)h +(cl_I&)g(x,)h(const)f(cl_I&)g(y\))480 2981 y Fp(Logical)j(and,)e +(complemen)m(ting)g(the)h(\014rst)e(argumen)m(t,)h(lik)m(e)i +Fn(~x)e(&)g(y)g Fp(in)g(C.)0 3141 y Fn(cl_I)f(logandc2)f(\(const)h +(cl_I&)g(x,)h(const)f(cl_I&)g(y\))480 3266 y Fp(Logical)j(and,)e +(complemen)m(ting)g(the)h(second)f(argumen)m(t,)g(lik)m(e)i +Fn(x)e(&)g(~y)g Fp(in)g(C.)0 3426 y Fn(cl_I)f(logorc1)g(\(const)f +(cl_I&)h(x,)h(const)f(cl_I&)g(y\))480 3550 y Fp(Logical)j(or,)f +(complemen)m(ting)f(the)g(\014rst)g(argumen)m(t,)g(lik)m(e)i +Fn(~x)d(|)i(y)f Fp(in)g(C.)0 3710 y Fn(cl_I)f(logorc2)g(\(const)f +(cl_I&)h(x,)h(const)f(cl_I&)g(y\))480 3835 y Fp(Logical)j(or,)f +(complemen)m(ting)f(the)g(second)h(argumen)m(t,)f(lik)m(e)i +Fn(x)e(|)g(~y)f Fp(in)h(C.)0 4127 y(These)g(op)s(erations)h(are)g(all)g +(a)m(v)-5 b(ailable)33 b(though)d(the)g(function)0 4418 +y Fn(cl_I)f(boole)g(\(cl_boole)f(op,)h(const)g(cl_I&)g(x,)h(const)f +(cl_I&)g(y\))0 4692 y Fp(where)i Fn(op)g Fp(m)m(ust)g(ha)m(v)m(e)i(one) +f(of)g(the)g(16)h(v)-5 b(alues)32 b(\(eac)m(h)h(one)f(stands)g(for)f(a) +i(function)e(whic)m(h)h(com)m(bines)f(t)m(w)m(o)i(bits)0 +4817 y(in)m(to)24 b(one)f(bit\):)38 b Fn(boole_clr)p +Fp(,)22 b Fn(boole_set)p Fp(,)h Fn(boole_1)p Fp(,)f Fn(boole_2)p +Fp(,)h Fn(boole_c1)p Fp(,)g Fn(boole_c2)p Fp(,)f Fn(boole_and)p +Fp(,)h Fn(boole_)0 4941 y(ior)p Fp(,)37 b Fn(boole_xor)p +Fp(,)e Fn(boole_eqv)p Fp(,)g Fn(boole_nand)p Fp(,)g Fn(boole_nor)p +Fp(,)g Fn(boole_andc1)p Fp(,)g Fn(boole_andc2)p Fp(,)f +Fn(boole_orc1)p Fp(,)0 5066 y Fn(boole_orc2)p Fp(.)0 +5340 y(Other)c(functions)g(that)h(view)f(in)m(tegers)i(as)f(bit)f +(strings:)p eop +%%Page: 28 30 +28 29 bop 0 -116 a Fp(Chapter)30 b(4:)41 b(F)-8 b(unctions)31 +b(on)f(n)m(um)m(b)s(ers)2463 b(28)0 366 y Fn(cl_boolean)28 +b(logtest)g(\(const)h(cl_I&)g(x,)g(const)g(cl_I&)g(y\))480 +491 y Fp(Returns)g(true)i(if)f(some)g(bit)g(is)h(set)f(in)h(b)s(oth)e +Fn(x)h Fp(and)g Fn(y)p Fp(,)g(i.e.)42 b(if)30 b Fn(logand\(x,y\))d(!=)j +(0)p Fp(.)0 671 y Fn(cl_boolean)e(logbitp)g(\(const)h(cl_I&)g(n,)g +(const)g(cl_I&)g(x\))480 795 y Fp(Returns)f(true)g(if)g(the)h +Fn(n)p Fp(th)f(bit)g(\(from)g(the)g(righ)m(t\))h(of)g +Fn(x)f Fp(is)h(set.)40 b(Bit)30 b(0)e(is)h(the)g(least)g(signi\014can)m +(t)h(bit.)0 975 y Fn(uintL)f(logcount)f(\(const)h(cl_I&)g(x\))480 +1100 y Fp(Returns)d(the)i(n)m(um)m(b)s(er)c(of)k(one)f(bits)g(in)g +Fn(x)p Fp(,)h(if)f Fn(x)g(>)p Fp(=)f(0,)j(or)e(the)g(n)m(um)m(b)s(er)e +(of)i(zero)h(bits)f(in)g Fn(x)p Fp(,)h(if)f Fn(x)f(<)h +Fp(0.)0 1404 y(The)j(follo)m(wing)i(functions)e(op)s(erate)h(on)f(in)m +(terv)-5 b(als)31 b(of)g(bits)f(in)g(in)m(tegers.)42 +b(The)30 b(t)m(yp)s(e)240 1660 y Fn(struct)46 b(cl_byte)g({)h(uintL)g +(size;)f(uintL)g(position;)g(};)0 1937 y Fp(represen)m(ts)39 +b(the)g(bit)g(in)m(terv)-5 b(al)41 b(con)m(taining)f(the)f(bits)g +Fn(position)p Fl(:)15 b(:)g(:)o Fn(position+size-1)35 +b Fp(of)k(an)g(in)m(teger.)68 b(The)0 2061 y(constructor)31 +b Fn(cl_byte\(size,position\))24 b Fp(constructs)31 b(a)f +Fn(cl_byte)p Fp(.)0 2366 y Fn(cl_I)f(ldb)h(\(const)e(cl_I&)h(n,)h +(const)f(cl_byte&)f(b\))480 2490 y Fp(extracts)g(the)f(bits)f(of)h +Fn(n)f Fp(describ)s(ed)g(b)m(y)g(the)h(bit)g(in)m(terv)-5 +b(al)27 b Fn(b)g Fp(and)f(returns)f(them)g(as)i(a)g(nonnegativ)m(e)480 +2615 y(in)m(teger)32 b(with)e Fn(b.size)e Fp(bits.)0 +2794 y Fn(cl_boolean)g(ldb_test)g(\(const)g(cl_I&)h(n,)h(const)f +(cl_byte&)f(b\))480 2919 y Fp(Returns)h(true)i(if)f(some)g(bit)g +(describ)s(ed)f(b)m(y)i(the)f(bit)h(in)m(terv)-5 b(al)31 +b Fn(b)f Fp(is)h(set)g(in)f Fn(n)p Fp(.)0 3099 y Fn(cl_I)f(dpb)h +(\(const)e(cl_I&)h(newbyte,)f(const)h(cl_I&)g(n,)h(const)f(cl_byte&)f +(b\))480 3223 y Fp(Returns)f Fn(n)p Fp(,)h(with)f(the)h(bits)g(describ) +s(ed)e(b)m(y)i(the)f(bit)h(in)m(terv)-5 b(al)29 b Fn(b)e +Fp(replaced)h(b)m(y)g Fn(newbyte)p Fp(.)38 b(Only)27 +b(the)480 3348 y(lo)m(w)m(est)32 b Fn(b.size)d Fp(bits)h(of)h +Fn(newbyte)d Fp(are)j(relev)-5 b(an)m(t.)0 3652 y(The)28 +b(functions)h Fn(ldb)f Fp(and)g Fn(dpb)g Fp(implicitly)h(shift.)40 +b(The)29 b(follo)m(wing)h(functions)e(are)i(their)f(coun)m(terparts)g +(without)0 3777 y(shifting:)0 4081 y Fn(cl_I)g(mask_field)f(\(const)g +(cl_I&)h(n,)h(const)f(cl_byte&)f(b\))480 4206 y Fp(returns)j(an)g(in)m +(teger)j(with)d(the)h(bits)g(describ)s(ed)f(b)m(y)h(the)g(bit)g(in)m +(terv)-5 b(al)33 b Fn(b)e Fp(copied)i(from)d(the)i(corre-)480 +4330 y(sp)s(onding)d(bits)h(in)g Fn(n)p Fp(,)g(the)h(other)g(bits)f +(zero.)0 4510 y Fn(cl_I)f(deposit_field)e(\(const)i(cl_I&)g(newbyte,)f +(const)h(cl_I&)g(n,)g(const)g(cl_byte&)f(b\))480 4634 +y Fp(returns)34 b(an)h(in)m(teger)i(where)d(the)i(bits)f(describ)s(ed)f +(b)m(y)h(the)h(bit)f(in)m(terv)-5 b(al)36 b Fn(b)f Fp(come)g(from)f +Fn(newbyte)480 4759 y Fp(and)c(the)g(other)h(bits)f(come)h(from)d +Fn(n)p Fp(.)0 5063 y(The)i(follo)m(wing)i(relations)f(hold:)180 +5340 y Fn(ldb)e(\(n,)h(b\))g(=)g(mask_field\(n,)d(b\))i(>>)h +(b.position)p Fp(,)p eop +%%Page: 29 31 +29 30 bop 0 -116 a Fp(Chapter)30 b(4:)41 b(F)-8 b(unctions)31 +b(on)f(n)m(um)m(b)s(ers)2463 b(29)180 366 y Fn(dpb)29 +b(\(newbyte,)f(n,)i(b\))g(=)g(deposit_field)d(\(newbyte)h(<<)h +(b.position,)f(n,)i(b\))p Fp(,)180 522 y Fn(deposit_field\(newbyte,n,)o +(b\))24 b(=)30 b(n)g(^)g(mask_field\(n,b\))c(^)31 b +(mask_field\(new_byte,b\))p Fp(.)0 832 y(The)36 b(follo)m(wing)i(op)s +(erations)f(on)g(in)m(tegers)h(as)f(bit)f(strings)h(are)g(e\016cien)m +(t)h(shortcuts)e(for)h(common)e(arithmetic)0 957 y(op)s(erations:)0 +1267 y Fn(cl_boolean)28 b(oddp)h(\(const)f(cl_I&)h(x\))480 +1392 y Fp(Returns)g(true)i(if)f(the)h(least)g(signi\014can)m(t)g(bit)g +(of)f Fn(x)g Fp(is)h(1.)41 b(Equiv)-5 b(alen)m(t)31 b(to)g +Fn(mod\(x,2\))d(!=)i(0)p Fp(.)0 1578 y Fn(cl_boolean)e(evenp)h(\(const) +f(cl_I&)h(x\))480 1702 y Fp(Returns)g(true)i(if)f(the)h(least)g +(signi\014can)m(t)g(bit)g(of)f Fn(x)g Fp(is)h(0.)41 b(Equiv)-5 +b(alen)m(t)31 b(to)g Fn(mod\(x,2\))d(==)i(0)p Fp(.)0 +1888 y Fn(cl_I)f(operator)f(<<)i(\(const)f(cl_I&)g(x,)g(const)g(cl_I&)g +(n\))480 2013 y Fp(Shifts)h Fn(x)g Fp(b)m(y)g Fn(n)g +Fp(bits)g(to)h(the)g(left.)41 b Fn(n)30 b Fp(should)g(b)s(e)f +Fn(>)p Fp(=0.)41 b(Equiv)-5 b(alen)m(t)31 b(to)g Fn(x)f(*)g +(expt\(2,n\))p Fp(.)0 2199 y Fn(cl_I)f(operator)f(>>)i(\(const)f(cl_I&) +g(x,)g(const)g(cl_I&)g(n\))480 2323 y Fp(Shifts)24 b +Fn(x)g Fp(b)m(y)g Fn(n)g Fp(bits)g(to)h(the)g(righ)m(t.)39 +b Fn(n)24 b Fp(should)f(b)s(e)h Fn(>)p Fp(=0.)39 b(Bits)25 +b(shifted)f(out)g(to)h(the)g(righ)m(t)g(are)f(thro)m(wn)480 +2448 y(a)m(w)m(a)m(y)-8 b(.)43 b(Equiv)-5 b(alen)m(t)31 +b(to)g Fn(floor\(x)e(/)h(expt\(2,n\)\))p Fp(.)0 2634 +y Fn(cl_I)f(ash)h(\(const)e(cl_I&)h(x,)h(const)f(cl_I&)g(y\))480 +2759 y Fp(Shifts)34 b Fn(x)h Fp(b)m(y)g Fn(y)f Fp(bits)h(to)h(the)f +(left)h(\(if)f Fn(y>)p Fp(=0\))g(or)g(b)m(y)g Fn(-y)f +Fp(bits)h(to)h(the)f(righ)m(t)h(\(if)f Fn(y<)p Fp(=0\).)54 +b(In)35 b(other)480 2883 y(w)m(ords,)30 b(this)g(returns)g +Fn(floor\(x)e(*)i(expt\(2,y\)\))p Fp(.)0 3069 y Fn(uintL)f +(integer_length)d(\(const)j(cl_I&)g(x\))480 3194 y Fp(Returns)40 +b(the)h(n)m(um)m(b)s(er)e(of)j(bits)f(\(excluding)g(the)h(sign)f(bit\)) +g(needed)g(to)h(represen)m(t)f Fn(x)g Fp(in)f(t)m(w)m(o's)480 +3318 y(complemen)m(t)28 b(notation.)41 b(This)27 b(is)i(the)f(smallest) +h(n)f Fn(>)p Fp(=)f(0)i(suc)m(h)f(that)h(-2)p Fn(^)p +Fp(n)f Fn(<)p Fp(=)g(x)g Fn(<)g Fp(2)p Fn(^)p Fp(n.)40 +b(If)28 b(x)g Fn(>)g Fp(0,)480 3443 y(this)i(is)h(the)f(unique)g(n)g +Fn(>)g Fp(0)g(suc)m(h)g(that)h(2)p Fn(^)p Fp(\(n-1\))h +Fn(<)p Fp(=)e(x)g Fn(<)g Fp(2)p Fn(^)p Fp(n.)0 3629 y +Fn(uintL)f(ord2)g(\(const)g(cl_I&)g(x\))480 3753 y(x)36 +b Fp(m)m(ust)g(b)s(e)g(non-zero.)61 b(This)36 b(function)g(returns)g +(the)h(n)m(um)m(b)s(er)d(of)j(0)g(bits)g(at)h(the)f(righ)m(t)g(of)g +Fn(x)f Fp(in)480 3878 y(t)m(w)m(o's)c(complemen)m(t)d(notation.)42 +b(This)30 b(is)g(the)h(largest)h(n)d Fn(>)p Fp(=)h(0)h(suc)m(h)f(that)h +(2)p Fn(^)p Fp(n)f(divides)g Fn(x)p Fp(.)0 4064 y Fn(uintL)f(power2p)f +(\(const)h(cl_I&)g(x\))480 4188 y(x)24 b Fp(m)m(ust)g(b)s(e)g +Fn(>)g Fp(0.)40 b(This)23 b(function)i(c)m(hec)m(ks)h(whether)e +Fn(x)g Fp(is)h(a)g(p)s(o)m(w)m(er)g(of)g(2.)39 b(If)24 +b Fn(x)g Fp(=)h(2)p Fn(^)p Fp(\(n-1\),)i(it)e(returns)480 +4313 y(n.)40 b(Else)31 b(it)g(returns)e(0.)41 b(\(See)31 +b(also)g(the)g(function)f Fn(logp)p Fp(.\))0 4780 y Fk(4.9.2)63 +b(Num)m(b)s(er)30 b(theoretic)g(functions)0 5091 y Fn(uint32)f(gcd)g +(\(uint32)g(a,)g(uint32)g(b\))0 5215 y(cl_I)g(gcd)h(\(const)e(cl_I&)h +(a,)h(const)f(cl_I&)g(b\))480 5340 y Fp(This)h(function)g(returns)f +(the)h(greatest)j(common)28 b(divisor)i(of)h Fn(a)f Fp(and)g +Fn(b)p Fp(,)g(normalized)g(to)h(b)s(e)f Fn(>)p Fp(=)f(0.)p +eop +%%Page: 30 32 +30 31 bop 0 -116 a Fp(Chapter)30 b(4:)41 b(F)-8 b(unctions)31 +b(on)f(n)m(um)m(b)s(ers)2463 b(30)0 366 y Fn(cl_I)29 +b(xgcd)g(\(const)g(cl_I&)g(a,)h(const)f(cl_I&)g(b,)g(cl_I*)g(u,)h +(cl_I*)f(v\))480 491 y Fp(This)h(function)h(\(\\extended)g(gcd"\))h +(returns)e(the)h(greatest)h(common)d(divisor)i Fn(g)f +Fp(of)h Fn(a)g Fp(and)f Fn(b)h Fp(and)480 616 y(at)39 +b(the)f(same)g(time)g(the)g(represen)m(tation)i(of)e +Fn(g)g Fp(as)g(an)g(in)m(tegral)i(linear)f(com)m(bination)f(of)h +Fn(a)f Fp(and)480 740 y Fn(b)p Fp(:)53 b Fn(u)36 b Fp(and)g +Fn(v)g Fp(with)h Fn(u*a+v*b)28 b(=)i(g)p Fp(,)38 b Fn(g)e(>)p +Fp(=)g(0.)60 b Fn(u)36 b Fp(and)g Fn(v)h Fp(will)g(b)s(e)f(normalized)g +(to)h(b)s(e)f(of)h(smallest)480 865 y(p)s(ossible)g(absolute)h(v)-5 +b(alue,)40 b(in)e(the)f(follo)m(wing)i(sense:)55 b(If)37 +b Fn(a)h Fp(and)e Fn(b)i Fp(are)g(non-zero,)i(and)d Fn(abs\(a\))480 +989 y(!=)30 b(abs\(b\))p Fp(,)35 b Fn(u)g Fp(and)f Fn(v)h +Fp(will)h(satisfy)g(the)f(inequalities)i Fn(abs\(u\))29 +b(<=)g(abs\(b\)/\(2*g\))p Fp(,)34 b Fn(abs\(v\))29 b(<=)480 +1114 y(abs\(a\)/\(2*g\))p Fp(.)0 1275 y Fn(cl_I)g(lcm)h(\(const)e +(cl_I&)h(a,)h(const)f(cl_I&)g(b\))480 1400 y Fp(This)h(function)g +(returns)f(the)h(least)i(common)d(m)m(ultiple)h(of)g +Fn(a)g Fp(and)g Fn(b)p Fp(,)g(normalized)g(to)h(b)s(e)f +Fn(>)p Fp(=)g(0.)0 1562 y Fn(cl_boolean)e(logp)h(\(const)f(cl_I&)h(a,)h +(const)f(cl_I&)g(b,)h(cl_RA*)e(l\))0 1686 y(cl_boolean)g(logp)h +(\(const)f(cl_RA&)h(a,)h(const)f(cl_RA&)f(b,)i(cl_RA*)f(l\))480 +1811 y(a)35 b Fp(m)m(ust)g(b)s(e)g Fn(>)h Fp(0.)57 b +Fn(b)36 b Fp(m)m(ust)e(b)s(e)h Fn(>)p Fp(0)h(and)f(!=)h(1.)57 +b(If)36 b(log\(a,b\))i(is)d(rational)i(n)m(um)m(b)s(er,)f(this)f +(function)480 1935 y(returns)29 b(true)h(and)g(sets)h(*l)g(=)f +(log\(a,b\),)j(else)e(it)g(returns)e(false.)0 2325 y +Fk(4.9.3)63 b(Com)m(binatorial)29 b(functions)0 2618 +y Fn(cl_I)g(factorial)f(\(uintL)h(n\))480 2742 y(n)h +Fp(m)m(ust)f(b)s(e)h(a)h(small)f(in)m(teger)h Fn(>)p +Fp(=)f(0.)41 b(This)30 b(function)g(returns)f(the)i(factorial)h +Fn(n)p Fp(!)40 b(=)30 b Fn(1*2*)p Fl(:)15 b(:)g(:)p Fn(*n)p +Fp(.)0 2904 y Fn(cl_I)29 b(doublefactorial)d(\(uintL)j(n\))480 +3028 y(n)44 b Fp(m)m(ust)g(b)s(e)g(a)h(small)f(in)m(teger)i +Fn(>)p Fp(=)e(0.)84 b(This)43 b(function)i(returns)e(the)i +(doublefactorial)h Fn(n)p Fp(!!)83 b(=)480 3153 y Fn(1*3*)p +Fl(:)15 b(:)g(:)p Fn(*n)30 b Fp(or)g Fn(n)p Fp(!!)41 +b(=)30 b Fn(2*4*)p Fl(:)15 b(:)g(:)p Fn(*n)p Fp(,)30 +b(resp)s(ectiv)m(ely)-8 b(.)0 3315 y Fn(cl_I)29 b(binomial)f(\(uintL)h +(n,)h(uintL)f(k\))480 3439 y(n)36 b Fp(and)h Fn(k)f Fp(m)m(ust)g(b)s(e) +g(small)g(in)m(tegers)i Fn(>)p Fp(=)e(0.)60 b(This)36 +b(function)h(returns)e(the)i(binomial)f(co)s(e\016cien)m(t)480 +3494 y Fh(\000)518 3523 y Fg(n)520 3595 y(k)559 3494 +y Fh(\001)622 3564 y Fp(=)828 3528 y Fg(n)p Ff(!)p 728 +3543 261 4 v 728 3595 a Fg(n)p Ff(!\()p Fg(n)p Fe(\000)p +Fg(k)q Ff(\)!)1029 3564 y Fp(for)30 b(0)h Fn(<)p Fp(=)e(k)i +Fn(<)p Fp(=)e(n,)h(0)h(else.)0 4001 y Fq(4.10)68 b(F)-11 +b(unctions)30 b(on)g(\015oating-p)t(oin)l(t)i(n)l(um)l(b)t(ers)0 +4275 y Fp(Recall)27 b(that)g(a)f(\015oating-p)s(oin)m(t)h(n)m(um)m(b)s +(er)d(consists)i(of)g(a)g(sign)g Fn(s)p Fp(,)g(an)g(exp)s(onen)m(t)g +Fn(e)f Fp(and)g(a)i(man)m(tissa)e Fn(m)p Fp(.)39 b(The)25 +b(v)-5 b(alue)0 4400 y(of)31 b(the)f(n)m(um)m(b)s(er)e(is)j +Fn(\(-1\)^s)d(*)i(2^e)g(*)g(m)p Fp(.)0 4674 y(Eac)m(h)h(of)g(the)f +(classes)i Fn(cl_F)p Fp(,)d Fn(cl_SF)p Fp(,)g Fn(cl_FF)p +Fp(,)g Fn(cl_DF)p Fp(,)h Fn(cl_LF)e Fp(de\014nes)i(the)h(follo)m(wing)g +(op)s(erations.)0 4966 y Fi(t)m(yp)s(e)36 b Fn(scale_float)27 +b(\(const)i Fi(t)m(yp)s(e)5 b Fn(&)30 b(x,)g(sintL)f(delta\))0 +5091 y Fi(t)m(yp)s(e)36 b Fn(scale_float)27 b(\(const)i +Fi(t)m(yp)s(e)5 b Fn(&)30 b(x,)g(const)f(cl_I&)g(delta\))480 +5215 y Fp(Returns)35 b Fn(x*2^delta)p Fp(.)57 b(This)35 +b(is)h(more)g(e\016cien)m(t)i(than)e(an)g(explicit)i(m)m(ultiplication) +f(b)s(ecause)f(it)480 5340 y(copies)31 b Fn(x)f Fp(and)g(mo)s(di\014es) +f(the)h(exp)s(onen)m(t.)p eop +%%Page: 31 33 +31 32 bop 0 -116 a Fp(Chapter)30 b(4:)41 b(F)-8 b(unctions)31 +b(on)f(n)m(um)m(b)s(ers)2463 b(31)0 366 y(The)31 b(follo)m(wing)j +(functions)d(pro)m(vide)h(an)g(abstract)h(in)m(terface)g(to)g(the)f +(underlying)f(represen)m(tation)i(of)f(\015oating-)0 +491 y(p)s(oin)m(t)e(n)m(um)m(b)s(ers.)0 792 y Fn(sintL)f +(float_exponent)d(\(const)j Fi(t)m(yp)s(e)5 b Fn(&)30 +b(x\))480 916 y Fp(Returns)g(the)h(exp)s(onen)m(t)g Fn(e)f +Fp(of)h Fn(x)p Fp(.)41 b(F)-8 b(or)32 b Fn(x)e(=)g(0.0)p +Fp(,)g(this)h(is)g(0.)42 b(F)-8 b(or)31 b Fn(x)g Fp(non-zero,)g(this)g +(is)g(the)g(unique)480 1041 y(in)m(teger)h(with)e Fn(2^\(e-1\))e(<=)i +(abs\(x\))f(<)h(2^e)p Fp(.)0 1217 y Fn(sintL)f(float_radix)e(\(const)i +Fi(t)m(yp)s(e)5 b Fn(&)30 b(x\))480 1341 y Fp(Returns)f(the)i(base)g +(of)f(the)h(\015oating-p)s(oin)m(t)g(represen)m(tation.)42 +b(This)30 b(is)g(alw)m(a)m(ys)i Fn(2)p Fp(.)0 1518 y +Fi(t)m(yp)s(e)k Fn(float_sign)27 b(\(const)i Fi(t)m(yp)s(e)5 +b Fn(&)30 b(x\))480 1642 y Fp(Returns)f(the)i(sign)f +Fn(s)g Fp(of)h Fn(x)f Fp(as)h(a)f(\015oat.)42 b(The)30 +b(v)-5 b(alue)31 b(is)f(1)h(for)f Fn(x)g(>)p Fp(=)g(0,)h(-1)g(for)f +Fn(x)g(<)g Fp(0.)0 1818 y Fn(uintL)f(float_digits)e(\(const)i +Fi(t)m(yp)s(e)5 b Fn(&)30 b(x\))480 1943 y Fp(Returns)24 +b(the)h(n)m(um)m(b)s(er)e(of)i(man)m(tissa)g(bits)f(in)h(the)g +(\015oating-p)s(oin)m(t)h(represen)m(tation)g(of)f Fn(x)p +Fp(,)h(including)480 2067 y(the)31 b(hidden)e(bit.)40 +b(The)30 b(v)-5 b(alue)31 b(only)g(dep)s(ends)d(on)i(the)h(t)m(yp)s(e)f +(of)h Fn(x)p Fp(,)f(not)h(on)f(its)h(v)-5 b(alue.)0 2243 +y Fn(uintL)29 b(float_precision)d(\(const)j Fi(t)m(yp)s(e)5 +b Fn(&)30 b(x\))480 2368 y Fp(Returns)21 b(the)h(n)m(um)m(b)s(er)d(of)j +(signi\014can)m(t)h(man)m(tissa)f(bits)g(in)f(the)h(\015oating-p)s(oin) +m(t)h(represen)m(tation)g(of)f Fn(x)p Fp(.)480 2493 y(Since)32 +b(denormalized)f(n)m(um)m(b)s(ers)e(are)j(not)f(supp)s(orted,)g(this)g +(is)h(the)f(same)g(as)h Fn(float_digits\(x\))480 2617 +y Fp(if)e Fn(x)g Fp(is)h(non-zero,)g(and)f(0)g(if)h Fn(x)f +Fp(=)g(0.)0 2918 y(The)h(complete)h(in)m(ternal)h(represen)m(tation)g +(of)f(a)g(\015oat)g(is)g(enco)s(ded)f(in)h(the)g(t)m(yp)s(e)f +Fn(cl_decoded_float)d Fp(\(or)k Fn(cl_)0 3042 y(decoded_sfloat)p +Fp(,)39 b Fn(cl_decoded_ffloat)p Fp(,)f Fn(cl_decoded_dfloat)p +Fp(,)h Fn(cl_decoded_lfloat)p Fp(,)f(resp)s(ectiv)m(ely\),)0 +3167 y(de\014ned)29 b(b)m(y)240 3421 y Fn(struct)46 b(cl_decoded_)p +Fi(t)m(yp)s(e)5 b Fn(float)44 b({)622 3525 y Fi(t)m(yp)s(e)53 +b Fn(mantissa;)45 b(cl_I)i(exponent;)e Fi(t)m(yp)s(e)53 +b Fn(sign;)240 3628 y(};)0 3903 y Fp(and)30 b(returned)f(b)m(y)h(the)h +(function)0 4204 y Fn(cl_decoded_)p Fi(t)m(yp)s(e)5 b +Fn(float)26 b(decode_float)h(\(const)i Fi(t)m(yp)s(e)5 +b Fn(&)30 b(x\))480 4329 y Fp(F)-8 b(or)38 b Fn(x)f Fp(non-zero,)j +(this)d(returns)f Fn(\(-1\)^s)p Fp(,)h Fn(e)p Fp(,)i +Fn(m)e Fp(with)g Fn(x)30 b(=)g(\(-1\)^s)f(*)h(2^e)f(*)h(m)37 +b Fp(and)g Fn(0.5)29 b(<=)h(m)g(<)480 4453 y(1.0)p Fp(.)63 +b(F)-8 b(or)39 b Fn(x)f Fp(=)g(0,)i(it)f(returns)e Fn(\(-1\)^s)p +Fp(=1,)i Fn(e)p Fp(=0,)h Fn(m)p Fp(=0.)64 b Fn(e)37 b +Fp(is)i(the)f(same)f(as)i(returned)e(b)m(y)h(the)480 +4578 y(function)30 b Fn(float_exponent)p Fp(.)0 4878 +y(A)g(complete)h(deco)s(ding)g(in)f(terms)f(of)i(in)m(tegers)g(is)g +(pro)m(vided)f(as)g(t)m(yp)s(e)240 5132 y Fn(struct)46 +b(cl_idecoded_float)d({)622 5236 y(cl_I)j(mantissa;)g(cl_I)g(exponent;) +g(cl_I)g(sign;)240 5340 y(};)p eop +%%Page: 32 34 +32 33 bop 0 -116 a Fp(Chapter)30 b(4:)41 b(F)-8 b(unctions)31 +b(on)f(n)m(um)m(b)s(ers)2463 b(32)0 366 y(b)m(y)30 b(the)h(follo)m +(wing)h(function:)0 670 y Fn(cl_idecoded_float)26 b +(integer_decode_float)e(\(const)29 b Fi(t)m(yp)s(e)5 +b Fn(&)31 b(x\))480 794 y Fp(F)-8 b(or)33 b Fn(x)g Fp(non-zero,)h(this) +e(returns)g Fn(\(-1\)^s)p Fp(,)f Fn(e)p Fp(,)j Fn(m)e +Fp(with)g Fn(x)e(=)g(\(-1\)^s)f(*)h(2^e)f(*)h(m)j Fp(and)f +Fn(m)g Fp(an)h(in)m(teger)480 919 y(with)e Fn(float_digits\(x\))c +Fp(bits.)43 b(F)-8 b(or)32 b Fn(x)f Fp(=)g(0,)h(it)g(returns)e +Fn(\(-1\)^s)p Fp(=1,)g Fn(e)p Fp(=0,)i Fn(m)p Fp(=0.)43 +b(W)-10 b(ARNING:)480 1043 y(The)35 b(exp)s(onen)m(t)h +Fn(e)f Fp(is)h(not)g(the)g(same)f(as)h(the)g(one)g(returned)f(b)m(y)g +(the)h(functions)f Fn(decode_float)480 1168 y Fp(and)30 +b Fn(float_exponent)p Fp(.)0 1471 y(Some)f(other)i(function,)f +(implemen)m(ted)f(only)i(for)f(class)h Fn(cl_F)p Fp(:)0 +1774 y Fn(cl_F)e(float_sign)f(\(const)g(cl_F&)h(x,)h(const)f(cl_F&)g +(y\))480 1899 y Fp(This)34 b(returns)g(a)i(\015oating)g(p)s(oin)m(t)f +(n)m(um)m(b)s(er)e(whose)i(precision)h(and)e(absolute)i(v)-5 +b(alue)36 b(is)f(that)h(of)f Fn(y)480 2023 y Fp(and)30 +b(whose)g(sign)g(is)h(that)g(of)f Fn(x)p Fp(.)41 b(If)30 +b Fn(x)g Fp(is)g(zero,)h(it)g(is)g(treated)g(as)g(p)s(ositiv)m(e.)41 +b(Same)30 b(for)g Fn(y)p Fp(.)0 2491 y Fq(4.11)68 b(Con)l(v)l(ersion)32 +b(functions)0 2925 y Fk(4.11.1)63 b(Con)m(v)m(ersion)31 +b(to)f(\015oating-p)s(oin)m(t)h(n)m(um)m(b)s(ers)0 3201 +y Fp(The)f(t)m(yp)s(e)g Fn(cl_float_format_t)c Fp(describ)s(es)k(a)g +(\015oating-p)s(oin)m(t)i(format.)0 3505 y Fn(cl_float_format_t)26 +b(cl_float_format)g(\(uintL)j(n\))480 3629 y Fp(Returns)40 +b(the)h(smallest)g(\015oat)h(format)e(whic)m(h)h(guaran)m(tees)h(at)g +(least)g Fn(n)f Fp(decimal)g(digits)g(in)g(the)480 3754 +y(man)m(tissa)30 b(\(after)i(the)e(decimal)g(p)s(oin)m(t\).)0 +3932 y Fn(cl_float_format_t)c(cl_float_format)g(\(const)j(cl_F&)f(x\)) +480 4057 y Fp(Returns)h(the)i(\015oating)g(p)s(oin)m(t)g(format)e(of)i +Fn(x)p Fp(.)0 4236 y Fn(cl_float_format_t)26 b(cl_default_float_format) +480 4360 y Fp(Global)41 b(v)-5 b(ariable:)60 b(the)40 +b(default)g(\015oat)g(format)f(used)g(when)g(con)m(v)m(erting)i +(rational)g(n)m(um)m(b)s(ers)c(to)480 4485 y(\015oats.)0 +4788 y(T)-8 b(o)37 b(con)m(v)m(ert)i(a)f(real)f(n)m(um)m(b)s(er)e(to)j +(a)f(\015oat,)j(eac)m(h)e(of)f(the)g(t)m(yp)s(es)g Fn(cl_R)p +Fp(,)h Fn(cl_F)p Fp(,)g Fn(cl_I)p Fp(,)g Fn(cl_RA)p Fp(,)f +Fn(int)p Fp(,)h Fn(unsigned)0 4912 y(int)p Fp(,)30 b +Fn(float)p Fp(,)f Fn(double)g Fp(de\014nes)g(the)i(follo)m(wing)g(op)s +(erations:)0 5215 y Fn(cl_F)e(cl_float)f(\(const)h Fi(t)m(yp)s(e)5 +b Fn(&x,)30 b(cl_float_format_t)25 b(f\))480 5340 y Fp(Returns)k +Fn(x)h Fp(as)h(a)g(\015oat)g(of)f(format)g Fn(f)p Fp(.)p +eop +%%Page: 33 35 +33 34 bop 0 -116 a Fp(Chapter)30 b(4:)41 b(F)-8 b(unctions)31 +b(on)f(n)m(um)m(b)s(ers)2463 b(33)0 366 y Fn(cl_F)29 +b(cl_float)f(\(const)h Fi(t)m(yp)s(e)5 b Fn(&x,)30 b(const)f(cl_F&)g +(y\))480 491 y Fp(Returns)g Fn(x)h Fp(in)h(the)f(\015oat)h(format)f(of) +g Fn(y)p Fp(.)0 667 y Fn(cl_F)f(cl_float)f(\(const)h +Fi(t)m(yp)s(e)5 b Fn(&x\))480 792 y Fp(Returns)30 b Fn(x)g +Fp(as)h(a)g(\015oat)h(of)f(format)f Fn(cl_default_float_format)24 +b Fp(if)31 b(it)g(is)g(an)g(exact)h(n)m(um)m(b)s(er,)d(or)480 +916 y Fn(x)h Fp(itself)h(if)g(it)f(is)h(already)g(a)g(\015oat.)0 +1217 y(Of)f(course,)h(con)m(v)m(erting)h(a)f(n)m(um)m(b)s(er)d(to)j(a)f +(\015oat)i(can)e(lose)h(precision.)0 1491 y(Ev)m(ery)g(\015oating-p)s +(oin)m(t)g(format)f(has)g(some)g(c)m(haracteristic)j(n)m(um)m(b)s(ers:) +0 1792 y Fn(cl_F)c(most_positive_float)c(\(cl_float_format_t)h(f\))480 +1916 y Fp(Returns)j(the)i(largest)h(\(most)e(p)s(ositiv)m(e\))i +(\015oating)f(p)s(oin)m(t)f(n)m(um)m(b)s(er)e(in)i(\015oat)h(format)f +Fn(f)p Fp(.)0 2092 y Fn(cl_F)f(most_negative_float)c +(\(cl_float_format_t)h(f\))480 2217 y Fp(Returns)j(the)i(smallest)g +(\(most)f(negativ)m(e\))j(\015oating)e(p)s(oin)m(t)f(n)m(um)m(b)s(er)e +(in)i(\015oat)h(format)f Fn(f)p Fp(.)0 2393 y Fn(cl_F)f +(least_positive_float)c(\(cl_float_format_t)g(f\))480 +2517 y Fp(Returns)39 b(the)i(least)g(p)s(ositiv)m(e)g(\015oating)g(p)s +(oin)m(t)f(n)m(um)m(b)s(er)e(\(i.e.)71 b Fn(>)40 b Fp(0)h(but)e +(closest)j(to)f(0\))f(in)g(\015oat)480 2642 y(format)30 +b Fn(f)p Fp(.)0 2818 y Fn(cl_F)f(least_negative_float)c +(\(cl_float_format_t)g(f\))480 2943 y Fp(Returns)38 b(the)h(least)h +(negativ)m(e)h(\015oating)f(p)s(oin)m(t)f(n)m(um)m(b)s(er)d(\(i.e.)67 +b Fn(<)39 b Fp(0)g(but)f(closest)j(to)e(0\))h(in)e(\015oat)480 +3067 y(format)30 b Fn(f)p Fp(.)0 3243 y Fn(cl_F)f(float_epsilon)e +(\(cl_float_format_t)e(f\))480 3368 y Fp(Returns)k(the)i(smallest)g +(\015oating)g(p)s(oin)m(t)f(n)m(um)m(b)s(er)e(e)j Fn(>)f +Fp(0)h(suc)m(h)f(that)h Fn(1+e)e(!=)h(1)p Fp(.)0 3544 +y Fn(cl_F)f(float_negative_epsilon)c(\(cl_float_format_t)g(f\))480 +3668 y Fp(Returns)k(the)i(smallest)g(\015oating)g(p)s(oin)m(t)f(n)m(um) +m(b)s(er)e(e)j Fn(>)f Fp(0)h(suc)m(h)f(that)h Fn(1-e)e(!=)h(1)p +Fp(.)0 4091 y Fk(4.11.2)63 b(Con)m(v)m(ersion)31 b(to)f(rational)g(n)m +(um)m(b)s(ers)0 4365 y Fp(Eac)m(h)h(of)g(the)f(classes)i +Fn(cl_R)p Fp(,)d Fn(cl_RA)p Fp(,)g Fn(cl_F)g Fp(de\014nes)h(the)g +(follo)m(wing)i(op)s(eration:)0 4666 y Fn(cl_RA)d(rational)f(\(const)h +Fi(t)m(yp)s(e)5 b Fn(&)30 b(x\))480 4790 y Fp(Returns)g(the)h(v)-5 +b(alue)32 b(of)f Fn(x)f Fp(as)i(an)e(exact)j(n)m(um)m(b)s(er.)40 +b(If)31 b Fn(x)f Fp(is)h(already)h(an)f(exact)h(n)m(um)m(b)s(er,)d +(this)i(is)g Fn(x)p Fp(.)480 4915 y(If)f Fn(x)g Fp(is)g(a)h +(\015oating-p)s(oin)m(t)g(n)m(um)m(b)s(er,)d(the)j(v)-5 +b(alue)30 b(is)h(a)f(rational)i(n)m(um)m(b)s(er)c(whose)i(denominator)f +(is)i(a)480 5039 y(p)s(o)m(w)m(er)f(of)h(2.)0 5340 y(In)f(order)g(to)h +(con)m(v)m(ert)h(bac)m(k,)f(sa)m(y)-8 b(,)32 b Fn +(\(cl_F\)\(cl_R\)"1/3")25 b Fp(to)31 b Fn(1/3)p Fp(,)f(there)h(is)f +(the)h(function)p eop +%%Page: 34 36 +34 35 bop 0 -116 a Fp(Chapter)30 b(4:)41 b(F)-8 b(unctions)31 +b(on)f(n)m(um)m(b)s(ers)2463 b(34)0 366 y Fn(cl_RA)29 +b(rationalize)e(\(const)i(cl_R&)g(x\))480 491 y Fp(If)i +Fn(x)h Fp(is)g(a)g(\015oating-p)s(oin)m(t)i(n)m(um)m(b)s(er,)c(it)i +(actually)i(represen)m(ts)e(an)g(in)m(terv)-5 b(al)33 +b(of)f(real)g(n)m(um)m(b)s(ers,)f(and)480 616 y(this)43 +b(function)g(returns)f(the)h(rational)i(n)m(um)m(b)s(er)40 +b(with)j(smallest)h(denominator)e(\(and)h(smallest)480 +740 y(n)m(umerator,)31 b(in)h(magnitude\))f(whic)m(h)h(lies)g(in)g +(this)g(in)m(terv)-5 b(al.)46 b(If)31 b Fn(x)h Fp(is)g(already)g(an)g +(exact)h(n)m(um)m(b)s(er,)480 865 y(this)d(function)g(returns)f +Fn(x)p Fp(.)0 1185 y(If)h Fn(x)g Fp(is)g(an)m(y)h(\015oat,)g(one)g(has) +180 1470 y Fn(cl_float\(rational\(x\),x\))24 b(=)30 b(x)180 +1630 y(cl_float\(rationalize\(x\),)o(x\))24 b(=)30 b(x)0 +2175 y Fq(4.12)68 b(Random)31 b(n)l(um)l(b)t(er)f(generators)0 +2460 y Fp(A)c(random)f(generator)j(is)e(a)h(mac)m(hine)f(whic)m(h)g +(pro)s(duces)f(\(pseudo-\)random)g(n)m(um)m(b)s(ers.)37 +b(The)26 b(include)g(\014le)g Fn()34 +b Fp(de\014nes)i(a)i(class)f Fn(cl_random_state)c Fp(whic)m(h)j(con)m +(tains)i(the)g(state)g(of)f(a)g(random)e(generator.)61 +b(If)0 2709 y(y)m(ou)31 b(mak)m(e)g(a)g(cop)m(y)h(of)f(the)g(random)e +(n)m(um)m(b)s(er)f(generator,)k(the)f(original)h(one)f(and)f(the)h(cop) +m(y)h(will)f(pro)s(duce)f(the)0 2834 y(same)g(sequence)h(of)f(random)f +(n)m(um)m(b)s(ers.)0 3118 y(The)e(follo)m(wing)i(functions)e(return)f +(\(pseudo-\)random)g(n)m(um)m(b)s(ers)f(in)i(di\013eren)m(t)h(formats.) +39 b(Calling)28 b(one)g(of)f(these)0 3243 y(mo)s(di\014es)i(the)h +(state)i(of)e(the)h(random)e(n)m(um)m(b)s(er)f(generator)j(in)f(a)h +(complicated)g(but)f(deterministic)g(w)m(a)m(y)-8 b(.)0 +3528 y(The)30 b(global)i(v)-5 b(ariable)240 3792 y Fn(cl_random_state) +44 b(cl_default_random_state)0 4076 y Fp(con)m(tains)25 +b(a)e(default)h(random)d(n)m(um)m(b)s(er)g(generator.)40 +b(It)23 b(is)h(used)e(when)h(the)g(functions)g(b)s(elo)m(w)h(are)f +(called)i(without)0 4201 y Fn(cl_random_state)h Fp(argumen)m(t.)0 +4521 y Fn(uint32)j(random32)f(\(cl_random_state&)d(randomstate\))0 +4646 y(uint32)k(random32)f(\(\))480 4770 y Fp(Returns)h(a)i(random)e +(unsigned)g(32-bit)j(n)m(um)m(b)s(er.)38 b(All)31 b(bits)f(are)h +(equally)g(random.)0 4966 y Fn(cl_I)e(random_I)f(\(cl_random_state&)e +(randomstate,)h(const)i(cl_I&)g(n\))0 5091 y(cl_I)g(random_I)f(\(const) +h(cl_I&)g(n\))480 5215 y(n)i Fp(m)m(ust)g(b)s(e)g(an)h(in)m(teger)h +Fn(>)f Fp(0.)45 b(This)31 b(function)g(returns)g(a)h(random)e(in)m +(teger)j Fn(x)f Fp(in)f(the)h(range)h Fn(0)d(<=)480 5340 +y(x)g(<)g(n)p Fp(.)p eop +%%Page: 35 37 +35 36 bop 0 -116 a Fp(Chapter)30 b(4:)41 b(F)-8 b(unctions)31 +b(on)f(n)m(um)m(b)s(ers)2463 b(35)0 366 y Fn(cl_F)29 +b(random_F)f(\(cl_random_state&)e(randomstate,)h(const)i(cl_F&)g(n\))0 +491 y(cl_F)g(random_F)f(\(const)h(cl_F&)g(n\))480 616 +y(n)36 b Fp(m)m(ust)g(b)s(e)g(a)h(\015oat)g Fn(>)g Fp(0.)60 +b(This)36 b(function)g(returns)g(a)h(random)e(\015oating-p)s(oin)m(t)j +(n)m(um)m(b)s(er)c(of)j(the)480 740 y(same)30 b(format)f(as)i +Fn(n)f Fp(in)g(the)h(range)f Fn(0)h(<=)e(x)h(<)g(n)p +Fp(.)0 932 y Fn(cl_R)f(random_R)f(\(cl_random_state&)e(randomstate,)h +(const)i(cl_R&)g(n\))0 1057 y(cl_R)g(random_R)f(\(const)h(cl_R&)g(n\)) +480 1181 y Fp(Beha)m(v)m(es)j(lik)m(e)g Fn(random_I)c +Fp(if)i Fn(n)g Fp(is)h(an)f(in)m(teger)i(and)e(lik)m(e)h +Fn(random_F)d Fp(if)j Fn(n)f Fp(is)g(a)h(\015oat.)0 1709 +y Fq(4.13)68 b(Obfuscating)31 b(op)t(erators)0 1991 y +Fp(The)i(mo)s(difying)f(C/C)p Fn(++)h Fp(op)s(erators)h +Fn(+=)p Fp(,)g Fn(-=)p Fp(,)g Fn(*=)p Fp(,)h Fn(/=)p +Fp(,)f Fn(&=)p Fp(,)g Fn(|=)p Fp(,)g Fn(^=)p Fp(,)g Fn(<<=)p +Fp(,)g Fn(>>=)f Fp(are)h(not)g(a)m(v)-5 b(ailable)36 +b(b)m(y)e(default)0 2116 y(b)s(ecause)41 b(their)g(use)g(tends)g(to)g +(mak)m(e)g(programs)f(unreadable.)72 b(It)41 b(is)h(trivial)g(to)g(get) +g(a)m(w)m(a)m(y)h(without)e(them.)0 2240 y(Ho)m(w)m(ev)m(er,)33 +b(if)d(y)m(ou)h(feel)g(that)g(y)m(ou)g(absolutely)g(need)f(these)h(op)s +(erators)f(to)h(get)h(happ)m(y)-8 b(,)30 b(then)g(add)240 +2502 y Fn(#define)46 b(WANT_OBFUSCATING_OPERATO)o(RS)0 +2785 y Fp(to)34 b(the)g(b)s(eginning)f(of)h(y)m(our)f(source)h +(\014les,)h(b)s(efore)e(the)h(inclusion)f(of)h(an)m(y)g(CLN)f(include)g +(\014les.)51 b(This)33 b(\015ag)h(will)0 2910 y(enable)d(the)f(follo)m +(wing)i(op)s(erators:)0 3192 y(F)-8 b(or)31 b(the)g(classes)g +Fn(cl_N)p Fp(,)f Fn(cl_R)p Fp(,)f Fn(cl_RA)p Fp(,)g Fn(cl_F)p +Fp(,)h Fn(cl_SF)p Fp(,)f Fn(cl_FF)p Fp(,)g Fn(cl_DF)p +Fp(,)g Fn(cl_LF)p Fp(:)0 3509 y Fi(t)m(yp)s(e)5 b Fn(&)30 +b(operator)e(+=)i(\()p Fi(t)m(yp)s(e)5 b Fn(&,)30 b(const)f +Fi(t)m(yp)s(e)5 b Fn(&\))0 3633 y Fi(t)m(yp)s(e)g Fn(&)30 +b(operator)e(-=)i(\()p Fi(t)m(yp)s(e)5 b Fn(&,)30 b(const)f +Fi(t)m(yp)s(e)5 b Fn(&\))0 3758 y Fi(t)m(yp)s(e)g Fn(&)30 +b(operator)e(*=)i(\()p Fi(t)m(yp)s(e)5 b Fn(&,)30 b(const)f +Fi(t)m(yp)s(e)5 b Fn(&\))0 3883 y Fi(t)m(yp)s(e)g Fn(&)30 +b(operator)e(/=)i(\()p Fi(t)m(yp)s(e)5 b Fn(&,)30 b(const)f +Fi(t)m(yp)s(e)5 b Fn(&\))0 4165 y Fp(F)-8 b(or)31 b(the)g(class)g +Fn(cl_I)p Fp(:)0 4482 y Fi(t)m(yp)s(e)5 b Fn(&)30 b(operator)e(+=)i(\() +p Fi(t)m(yp)s(e)5 b Fn(&,)30 b(const)f Fi(t)m(yp)s(e)5 +b Fn(&\))0 4606 y Fi(t)m(yp)s(e)g Fn(&)30 b(operator)e(-=)i(\()p +Fi(t)m(yp)s(e)5 b Fn(&,)30 b(const)f Fi(t)m(yp)s(e)5 +b Fn(&\))0 4731 y Fi(t)m(yp)s(e)g Fn(&)30 b(operator)e(*=)i(\()p +Fi(t)m(yp)s(e)5 b Fn(&,)30 b(const)f Fi(t)m(yp)s(e)5 +b Fn(&\))0 4855 y Fi(t)m(yp)s(e)g Fn(&)30 b(operator)e(&=)i(\()p +Fi(t)m(yp)s(e)5 b Fn(&,)30 b(const)f Fi(t)m(yp)s(e)5 +b Fn(&\))0 4980 y Fi(t)m(yp)s(e)g Fn(&)30 b(operator)e(|=)i(\()p +Fi(t)m(yp)s(e)5 b Fn(&,)30 b(const)f Fi(t)m(yp)s(e)5 +b Fn(&\))0 5104 y Fi(t)m(yp)s(e)g Fn(&)30 b(operator)e(^=)i(\()p +Fi(t)m(yp)s(e)5 b Fn(&,)30 b(const)f Fi(t)m(yp)s(e)5 +b Fn(&\))0 5229 y Fi(t)m(yp)s(e)g Fn(&)30 b(operator)e(<<=)i(\()p +Fi(t)m(yp)s(e)5 b Fn(&,)30 b(const)f Fi(t)m(yp)s(e)5 +b Fn(&\))0 5353 y Fi(t)m(yp)s(e)g Fn(&)30 b(operator)e(>>=)i(\()p +Fi(t)m(yp)s(e)5 b Fn(&,)30 b(const)f Fi(t)m(yp)s(e)5 +b Fn(&\))p eop +%%Page: 36 38 +36 37 bop 0 -116 a Fp(Chapter)30 b(4:)41 b(F)-8 b(unctions)31 +b(on)f(n)m(um)m(b)s(ers)2463 b(36)0 366 y(F)-8 b(or)31 +b(the)g(classes)g Fn(cl_N)p Fp(,)f Fn(cl_R)p Fp(,)f Fn(cl_RA)p +Fp(,)g Fn(cl_I)p Fp(,)h Fn(cl_F)p Fp(,)f Fn(cl_SF)p Fp(,)g +Fn(cl_FF)p Fp(,)h Fn(cl_DF)p Fp(,)f Fn(cl_LF)p Fp(:)0 +665 y Fi(t)m(yp)s(e)5 b Fn(&)30 b(operator)e(++)i(\()p +Fi(t)m(yp)s(e)5 b Fn(&)30 b(x\))480 790 y Fp(The)g(pre\014x)f(op)s +(erator)i Fn(++x)p Fp(.)0 964 y Fn(void)e(operator)f(++)i(\()p +Fi(t)m(yp)s(e)5 b Fn(&)30 b(x,)g(int\))480 1089 y Fp(The)g(p)s +(ost\014x)f(op)s(erator)i Fn(x++)p Fp(.)0 1263 y Fi(t)m(yp)s(e)5 +b Fn(&)30 b(operator)e(--)i(\()p Fi(t)m(yp)s(e)5 b Fn(&)30 +b(x\))480 1388 y Fp(The)g(pre\014x)f(op)s(erator)i Fn(--x)p +Fp(.)0 1562 y Fn(void)e(operator)f(--)i(\()p Fi(t)m(yp)s(e)5 +b Fn(&)30 b(x,)g(int\))480 1687 y Fp(The)g(p)s(ost\014x)f(op)s(erator)i +Fn(x--)p Fp(.)0 1985 y(Note)j(that)e(b)m(y)g(using)g(these)h +(obfuscating)g(op)s(erators,)g(y)m(ou)f(w)m(ouldn't)g(gain)h +(e\016ciency:)46 b(In)31 b(CLN)h(`)p Fn(x)e(+=)g(y;)p +Fp(')i(is)0 2110 y(exactly)g(the)f(same)e(as)i(`)p Fn(x)f(=)g(x+y;)p +Fp(',)g(not)h(more)e(e\016cien)m(t.)p eop +%%Page: 37 39 +37 38 bop 0 -116 a Fp(Chapter)30 b(5:)41 b(Input/Output)2784 +b(37)0 366 y Fm(5)80 b(Input/Output)0 933 y Fq(5.1)68 +b(In)l(ternal)32 b(and)e(prin)l(ted)g(represen)l(tation)0 +1209 y Fp(All)h(computations)f(deal)h(with)f(the)h(in)m(ternal)g +(represen)m(tations)g(of)g(the)f(n)m(um)m(b)s(ers.)0 +1484 y(Ev)m(ery)i(n)m(um)m(b)s(er)d(has)j(an)f(external)i(represen)m +(tation)g(as)f(a)g(sequence)g(of)g(ASCI)s(I)e(c)m(haracters.)46 +b(Sev)m(eral)33 b(external)0 1609 y(represen)m(tations)e(ma)m(y)f +(denote)h(the)g(same)f(n)m(um)m(b)s(er,)e(for)i(example,)g +Fn(")p Fp(20.0)p Fn(")i Fp(and)d Fn(")p Fp(20.000)p Fn(")p +Fp(.)0 1884 y(Con)m(v)m(erting)38 b(an)g(in)m(ternal)g(to)g(an)f +(external)i(represen)m(tation)f(is)g(called)g(\\prin)m(ting",)j(con)m +(v)m(erting)e(an)e(external)0 2009 y(to)43 b(an)e(in)m(ternal)i +(represen)m(tation)g(is)f(called)h(\\reading".)76 b(In)41 +b(CLN,)h(is)g(it)g(alw)m(a)m(ys)i(true)d(that)i(con)m(v)m(ersion)g(of)0 +2133 y(an)d(in)m(ternal)g(to)g(an)g(external)g(represen)m(tation)h(and) +e(then)g(bac)m(k)i(to)f(an)g(in)m(ternal)g(represen)m(tation)h(will)f +(yield)0 2258 y(the)34 b(same)e(in)m(ternal)j(represen)m(tation.)50 +b(Sym)m(b)s(olically:)d Fn(read\(print\(x\)\))27 b(==)i(x)p +Fp(.)50 b(This)33 b(is)g(called)i(\\prin)m(t-read)0 2382 +y(consistency".)0 2658 y(Di\013eren)m(t)d(t)m(yp)s(es)e(of)h(n)m(um)m +(b)s(ers)d(ha)m(v)m(e)j(di\013eren)m(t)g(external)g(represen)m(tations) +h(\(case)f(is)g(insigni\014can)m(t\):)0 2959 y(In)m(tegers)167 +b(External)30 b(represen)m(tation:)41 b Fi(sign)p Fn({)p +Fi(digit)r Fn(}+)p Fp(.)g(The)29 b(reader)g(also)i(accepts)g(the)e +(Common)e(Lisp)i(syn-)480 3084 y(taxes)39 b Fi(sign)p +Fn({)p Fi(digit)r Fn(}+.)f Fp(with)h(a)f(trailing)i(dot)e(for)h +(decimal)f(in)m(tegers)i(and)d(the)i Fn(#)p Fi(n)p Fn(R)p +Fp(,)g Fn(#b)p Fp(,)i Fn(#o)p Fp(,)f Fn(#x)480 3208 y +Fp(pre\014xes.)0 3386 y(Rational)32 b(n)m(um)m(b)s(ers)480 +3510 y(External)37 b(represen)m(tation:)56 b Fi(sign)p +Fn({)p Fi(digit)r Fn(}+/{)p Fi(digit)r Fn(}+)p Fp(.)k(The)37 +b Fn(#)p Fi(n)p Fn(R)p Fp(,)h Fn(#b)p Fp(,)g Fn(#o)p +Fp(,)h Fn(#x)d Fp(pre\014xes)g(are)i(al-)480 3635 y(lo)m(w)m(ed)32 +b(here)e(as)g(w)m(ell.)0 3812 y(Floating-p)s(oin)m(t)j(n)m(um)m(b)s +(ers)480 3937 y(External)48 b(represen)m(tation:)76 b +Fi(sign)p Fn({)p Fi(digit)r Fn(})p Fp(*)p Fi(exp)s(onen)m(t)50 +b Fp(or)d Fi(sign)p Fn({)p Fi(digit)r Fn(})p Fp(*)p Fn(.{)p +Fi(digit)r Fn(})p Fp(*)p Fi(exp)s(onen)m(t)k Fp(or)480 +4061 y Fi(sign)p Fn({)p Fi(digit)r Fn(})p Fp(*)p Fn(.{)p +Fi(digit)r Fn(}+)p Fp(.)40 b(A)26 b(precision)g(sp)s(eci\014er)f(of)h +(the)h(form)p 2684 4061 28 4 v 57 w Fi(prec)k Fp(ma)m(y)26 +b(b)s(e)f(app)s(ended.)37 b(There)480 4186 y(m)m(ust)h(b)s(e)h(at)i +(least)g(one)e(digit)i(in)e(the)h(non-exp)s(onen)m(t)f(part.)69 +b(The)39 b(exp)s(onen)m(t)g(has)h(the)f(syn)m(tax)480 +4310 y Fi(expmark)m(er)d(expsign)30 b Fn({)p Fi(digit)r +Fn(}+)p Fp(.)41 b(The)30 b(exp)s(onen)m(t)g(mark)m(er)g(is)660 +4461 y(`)p Fn(s)p Fp(')h(for)f(short-\015oats,)660 4612 +y(`)p Fn(f)p Fp(')h(for)f(single-\015oats,)660 4763 y(`)p +Fn(d)p Fp(')h(for)f(double-\015oats,)660 4914 y(`)p Fn(L)p +Fp(')h(for)f(long-\015oats,)480 5091 y(or)25 b(`)p Fn(e)p +Fp(',)i(whic)m(h)e(denotes)h(a)g(default)f(\015oat)h(format.)39 +b(The)25 b(precision)g(sp)s(ecifying)g(su\016x)g(has)g(the)g(syn-)480 +5215 y(tax)p 638 5215 V 57 w Fi(prec)30 b Fp(where)23 +b Fi(prec)30 b Fp(denotes)24 b(the)g(n)m(um)m(b)s(er)e(of)i(v)-5 +b(alid)25 b(man)m(tissa)f(digits)g(\(in)g(decimal,)i(excluding)480 +5340 y(leading)31 b(zero)s(es\),)h(cf.)41 b(also)31 b(function)f(`)p +Fn(cl_float_format)p Fp('.)p eop +%%Page: 38 40 +38 39 bop 0 -116 a Fp(Chapter)30 b(5:)41 b(Input/Output)2784 +b(38)0 366 y(Complex)29 b(n)m(um)m(b)s(ers)480 491 y(External)i +(represen)m(tation:)660 646 y(In)h(algebraic)i(notation:)46 +b Fi(realpart)r Fn(+)p Fi(imagpart)r Fn(i)p Fp(.)g(Of)32 +b(course,)h(if)g Fi(imagpart)h Fp(is)e(negativ)m(e,)k(its)660 +771 y(prin)m(ted)23 b(represen)m(tation)h(b)s(egins)f(with)g(a)h(`)p +Fn(-)p Fp(',)h(and)e(the)h(`)p Fn(+)p Fp(')f(b)s(et)m(w)m(een)h +Fi(realpart)i Fp(and)d Fi(imagpart)660 895 y Fp(ma)m(y)37 +b(b)s(e)h(omitted.)63 b(Note)39 b(that)g(this)e(notation)j(cannot)e(b)s +(e)f(used)g(when)g(the)h Fi(imagpart)i Fp(is)660 1020 +y(rational)c(and)f(the)g(rational)h(n)m(um)m(b)s(er's)d(base)i(is)g +Fn(>)p Fp(18,)i(b)s(ecause)e(the)g(`)p Fn(i)p Fp(')g(is)g(then)g(read)f +(as)i(a)660 1144 y(digit.)660 1299 y(In)30 b(Common)e(Lisp)h(notation:) +42 b Fn(#C\()p Fi(realpart)32 b(imagpart)r Fn(\))p Fp(.)0 +1799 y Fq(5.2)68 b(Input)30 b(functions)0 2078 y Fp(Including)24 +b Fn()e Fp(de\014nes)i(a)h(t)m(yp)s(e)g Fn(cl_istream)p +Fp(,)e(whic)m(h)h(is)h(the)g(t)m(yp)s(e)g(of)g(the)g(\014rst)f(argumen) +m(t)g(to)h(all)h(input)0 2203 y(functions.)38 b(Unless)24 +b(y)m(ou)g(build)f(and)g(use)g(CLN)g(with)h(the)g(macro)f(CL)p +2375 2203 28 4 v 32 w(IO)p 2511 2203 V 33 w(STDIO)f(b)s(eing)i +(de\014ned,)g Fn(cl_istream)0 2327 y Fp(is)30 b(the)h(same)f(as)g +Fn(istream&)p Fp(.)0 2607 y(The)g(v)-5 b(ariable)180 +2887 y Fn(cl_istream)28 b(cl_stdin)0 3197 y Fp(con)m(tains)k(the)e +(standard)g(input)f(stream.)0 3476 y(These)h(are)h(the)f(simple)g +(input)f(functions:)0 3787 y Fn(int)g(freadchar)f(\(cl_istream)g +(stream\))480 3911 y Fp(Reads)33 b(a)h(c)m(haracter)h(from)c +Fn(stream)p Fp(.)48 b(Returns)32 b Fn(cl_EOF)f Fp(\(not)j(a)g(`)p +Fn(char)p Fp('!\))48 b(if)33 b(the)h(end)e(of)i(stream)480 +4036 y(w)m(as)d(encoun)m(tered)g(or)f(an)g(error)g(o)s(ccurred.)0 +4221 y Fn(int)f(funreadchar)f(\(cl_istream)f(stream,)h(int)i(c\))480 +4346 y Fp(Puts)37 b(bac)m(k)i Fn(c)f Fp(on)m(to)h Fn(stream)p +Fp(.)61 b Fn(c)38 b Fp(m)m(ust)e(b)s(e)i(the)g(result)g(of)g(the)g +(last)g Fn(freadchar)e Fp(op)s(eration)i(on)480 4471 +y Fn(stream)p Fp(.)0 4781 y(Eac)m(h)d(of)g(the)g(classes)g +Fn(cl_N)p Fp(,)g Fn(cl_R)p Fp(,)g Fn(cl_RA)p Fp(,)f Fn(cl_I)p +Fp(,)h Fn(cl_F)p Fp(,)f Fn(cl_SF)p Fp(,)h Fn(cl_FF)p +Fp(,)f Fn(cl_DF)p Fp(,)h Fn(cl_LF)e Fp(de\014nes,)i(in)f +Fn()p Fp(,)29 +b(the)i(follo)m(wing)h(input)d(function:)0 5215 y Fn(cl_istream)f +(operator>>)f(\(cl_istream)g(stream,)i Fi(t)m(yp)s(e)5 +b Fn(&)30 b(result\))480 5340 y Fp(Reads)g(a)h(n)m(um)m(b)s(er)d(from)h +Fn(stream)g Fp(and)h(stores)g(it)h(in)f(the)h Fn(result)p +Fp(.)p eop +%%Page: 39 41 +39 40 bop 0 -116 a Fp(Chapter)30 b(5:)41 b(Input/Output)2784 +b(39)0 366 y(The)30 b(most)g(\015exible)g(input)g(functions,)g +(de\014ned)f(in)h Fn()p +Fp(,)28 b(are)j(the)f(follo)m(wing:)0 659 y Fn(cl_N)f(read_complex)e +(\(cl_istream)h(stream,)g(const)h(cl_read_flags&)d(flags\))0 +783 y(cl_R)j(read_real)f(\(cl_istream)f(stream,)i(const)g +(cl_read_flags&)d(flags\))0 908 y(cl_F)j(read_float)f(\(cl_istream)f +(stream,)h(const)h(cl_read_flags&)e(flags\))0 1033 y(cl_RA)i +(read_rational)e(\(cl_istream)g(stream,)h(const)h(cl_read_flags&)e +(flags\))0 1157 y(cl_I)i(read_integer)e(\(cl_istream)h(stream,)g(const) +h(cl_read_flags&)d(flags\))480 1282 y Fp(Reads)d(a)g(n)m(um)m(b)s(er)e +(from)h Fn(stream)p Fp(.)36 b(The)23 b Fn(flags)e Fp(are)i(parameters)g +(whic)m(h)f(a\013ect)j(the)e(input)f(syn)m(tax.)480 1406 +y(Whitespace)32 b(b)s(efore)e(the)g(n)m(um)m(b)s(er)e(is)j(silen)m(tly) +h(skipp)s(ed.)0 1568 y Fn(cl_N)d(read_complex)e(\(const)i +(cl_read_flags&)d(flags,)j(const)g(char)g(*)h(string,)f(const)g(char)g +(*)0 1692 y(string_limit,)e(const)i(char)g(*)h(*)g(end_of_parse\))0 +1817 y(cl_R)f(read_real)f(\(const)h(cl_read_flags&)d(flags,)j(const)g +(char)g(*)h(string,)e(const)h(char)h(*)0 1941 y(string_limit,)d(const)i +(char)g(*)h(*)g(end_of_parse\))0 2066 y(cl_F)f(read_float)f(\(const)g +(cl_read_flags&)f(flags,)i(const)g(char)g(*)h(string,)e(const)h(char)g +(*)0 2190 y(string_limit,)e(const)i(char)g(*)h(*)g(end_of_parse\))0 +2315 y(cl_RA)f(read_rational)e(\(const)h(cl_read_flags&)f(flags,)h +(const)h(char)h(*)g(string,)e(const)h(char)g(*)0 2439 +y(string_limit,)e(const)i(char)g(*)h(*)g(end_of_parse\))0 +2564 y(cl_I)f(read_integer)e(\(const)i(cl_read_flags&)d(flags,)j(const) +g(char)g(*)h(string,)f(const)g(char)g(*)0 2688 y(string_limit,)e(const) +i(char)g(*)h(*)g(end_of_parse\))480 2813 y Fp(Reads)g(a)h(n)m(um)m(b)s +(er)d(from)h(a)i(string)f(in)g(memory)-8 b(.)39 b(The)30 +b Fn(flags)f Fp(are)i(parameters)f(whic)m(h)g(a\013ect)i(the)480 +2938 y(input)26 b(syn)m(tax.)40 b(The)27 b(string)g(starts)g(at)h +Fn(string)d Fp(and)h(ends)g(at)i Fn(string_limit)c Fp(\(exclusiv)m(e)29 +b(limit\).)480 3062 y Fn(string_limit)24 b Fp(ma)m(y)j(also)h(b)s(e)e +Fn(NULL)p Fp(,)h(denoting)h(the)f(en)m(tire)h(string,)g(i.e.)40 +b(equiv)-5 b(alen)m(t)29 b(to)f Fn(string_)480 3187 y(limit)h(=)h +(string)f(+)h(strlen\(string\))p Fp(.)57 b(If)37 b Fn(end_of_parse)d +Fp(is)j Fn(NULL)p Fp(,)h(the)g(string)f(in)g(memory)480 +3311 y(m)m(ust)26 b(con)m(tain)i(exactly)h(one)f(n)m(um)m(b)s(er)d(and) +h(nothing)h(more,)g(else)h(a)g(fatal)g(error)f(will)g(b)s(e)g +(signalled.)480 3436 y(If)33 b Fn(end_of_parse)c Fp(is)k(not)h +Fn(NULL)p Fp(,)f Fn(*end_of_parse)c Fp(will)k(b)s(e)g(assigned)g(a)h(p) +s(oin)m(ter)f(past)g(the)g(last)480 3560 y(parsed)h(c)m(haracter)i +(\(i.e.)55 b Fn(string_limit)31 b Fp(if)k(nothing)f(came)h(after)g(the) +g(n)m(um)m(b)s(er\).)51 b(Whitespace)480 3685 y(is)30 +b(not)h(allo)m(w)m(ed.)0 3977 y(The)f(structure)g Fn(cl_read_flags)d +Fp(con)m(tains)k(the)g(follo)m(wing)g(\014elds:)0 4270 +y Fn(cl_read_syntax_t)26 b(syntax)480 4394 y Fp(The)c(p)s(ossible)f +(results)h(of)h(the)f(read)g(op)s(eration.)38 b(P)m(ossible)23 +b(v)-5 b(alues)23 b(are)f Fn(syntax_number)p Fp(,)f Fn(syntax_)480 +4519 y(real)p Fp(,)37 b Fn(syntax_rational)p Fp(,)e Fn(syntax_integer)p +Fp(,)g Fn(syntax_float)p Fp(,)g Fn(syntax_sfloat)p Fp(,)g +Fn(syntax_)480 4643 y(ffloat)p Fp(,)29 b Fn(syntax_dfloat)p +Fp(,)e Fn(syntax_lfloat)p Fp(.)0 4805 y Fn(cl_read_lsyntax_t)f(lsyntax) +480 4929 y Fp(Sp)s(eci\014es)e(the)i(language-dep)s(enden)m(t)g(syn)m +(tax)f(v)-5 b(arian)m(t)26 b(for)f(the)g(read)g(op)s(eration.)40 +b(P)m(ossible)26 b(v)-5 b(alues)480 5054 y(are)480 5215 +y Fn(lsyntax_standard)960 5340 y Fp(accept)32 b(standard)d(algebraic)j +(notation)g(only)-8 b(,)31 b(no)g(complex)f(n)m(um)m(b)s(ers,)p +eop +%%Page: 40 42 +40 41 bop 0 -116 a Fp(Chapter)30 b(5:)41 b(Input/Output)2784 +b(40)480 366 y Fn(lsyntax_algebraic)960 491 y Fp(accept)32 +b(the)e(algebraic)i(notation)g Fi(x)6 b Fn(+)p Fi(y)i +Fn(i)30 b Fp(for)g(complex)g(n)m(um)m(b)s(ers,)480 679 +y Fn(lsyntax_commonlisp)960 804 y Fp(accept)44 b(the)f +Fn(#b)p Fp(,)i Fn(#o)p Fp(,)g Fn(#x)d Fp(syn)m(taxes)h(for)g(binary)-8 +b(,)45 b(o)s(ctal,)i(hexadecimal)c(n)m(um)m(b)s(ers,)960 +928 y Fn(#)p Fi(base)5 b Fn(R)42 b Fp(for)g(rational)h(n)m(um)m(b)s +(ers)d(in)h(a)i(giv)m(en)g(base,)i Fn(#c\()p Fi(realpart)33 +b(imagpart)r Fn(\))41 b Fp(for)960 1053 y(complex)30 +b(n)m(um)m(b)s(ers,)480 1241 y Fn(lsyntax_all)960 1365 +y Fp(accept)i(all)f(of)g(these)f(extensions.)0 1553 y +Fn(unsigned)e(int)i(rational_base)480 1678 y Fp(The)g(base)g(in)g(whic) +m(h)h(rational)g(n)m(um)m(b)s(ers)d(are)j(read.)0 1866 +y Fn(cl_float_format_t)26 b(float_flags.default_flo)o(at_f)o(orm)o(at) +480 1990 y Fp(The)k(\015oat)h(format)f(used)f(when)h(reading)g +(\015oats)h(with)f(exp)s(onen)m(t)g(mark)m(er)g(`)p Fn(e)p +Fp('.)0 2178 y Fn(cl_float_format_t)c(float_flags.default_lfl)o(oat_)o +(for)o(mat)480 2303 y Fp(The)k(\015oat)h(format)f(used)f(when)h +(reading)g(\015oats)h(with)f(exp)s(onen)m(t)g(mark)m(er)g(`)p +Fn(l)p Fp('.)0 2491 y Fn(cl_boolean)e(float_flags.mantissa_de)o(pen)o +(dent)o(_flo)o(at_)o(form)o(at)480 2615 y Fp(When)k(this)g(\015ag)g(is) +g(true,)g(\015oats)h(sp)s(eci\014ed)e(with)g(more)g(digits)i(than)f +(corresp)s(onding)f(to)h(the)g(ex-)480 2740 y(p)s(onen)m(t)25 +b(mark)m(er)f(they)i(con)m(tain,)h(but)e(without)p 2123 +2740 28 4 v 58 w Fi(nnn)f Fp(su\016x,)h(will)h(get)g(a)g(precision)f +(corresp)s(onding)480 2864 y(to)31 b(their)g(n)m(um)m(b)s(er)d(of)i +(signi\014can)m(t)h(digits.)0 3374 y Fq(5.3)68 b(Output)30 +b(functions)0 3655 y Fp(Including)40 b Fn()d +Fp(de\014nes)j(a)h(t)m(yp)s(e)f Fn(cl_ostream)p Fp(,)h(whic)m(h)f(is)g +(the)h(t)m(yp)s(e)f(of)h(the)f(\014rst)g(argumen)m(t)g(to)h(all)0 +3780 y(output)e(functions.)66 b(Unless)39 b(y)m(ou)g(build)f(and)g(use) +h(CLN)f(with)h(the)g(macro)g(CL)p 2847 3780 V 32 w(IO)p +2983 3780 V 32 w(STDIO)f(b)s(eing)h(de\014ned,)0 3904 +y Fn(cl_ostream)28 b Fp(is)i(the)h(same)e(as)i Fn(ostream&)p +Fp(.)0 4185 y(The)f(v)-5 b(ariable)180 4466 y Fn(cl_ostream)28 +b(cl_stdout)0 4778 y Fp(con)m(tains)k(the)e(standard)g(output)g +(stream.)0 5059 y(The)g(v)-5 b(ariable)180 5340 y Fn(cl_ostream)28 +b(cl_stderr)p eop +%%Page: 41 43 +41 42 bop 0 -116 a Fp(Chapter)30 b(5:)41 b(Input/Output)2784 +b(41)0 366 y(con)m(tains)32 b(the)e(standard)g(error)g(output)g +(stream.)0 643 y(These)g(are)h(the)f(simple)g(output)g(functions:)0 +948 y Fn(void)f(fprintchar)f(\(cl_ostream)f(stream,)h(char)i(c\))480 +1072 y Fp(Prin)m(ts)g(the)h(c)m(haracter)h Fn(x)e Fp(literally)i(on)e +(the)h Fn(stream)p Fp(.)0 1252 y Fn(void)e(fprint)g(\(cl_ostream)e +(stream,)i(const)f(char)i(*)g(string\))480 1376 y Fp(Prin)m(ts)g(the)h +Fn(string)d Fp(literally)33 b(on)d(the)g Fn(stream)p +Fp(.)0 1556 y Fn(void)f(fprintdecimal)e(\(cl_ostream)g(stream,)i(int)g +(x\))0 1681 y(void)g(fprintdecimal)e(\(cl_ostream)g(stream,)i(const)g +(cl_I&)g(x\))480 1805 y Fp(Prin)m(ts)h(the)h(in)m(teger)h +Fn(x)e Fp(in)g(decimal)g(on)g(the)h Fn(stream)p Fp(.)0 +1985 y Fn(void)e(fprintbinary)e(\(cl_ostream)h(stream,)g(const)h(cl_I&) +g(x\))480 2110 y Fp(Prin)m(ts)h(the)h(in)m(teger)h Fn(x)e +Fp(in)g(binary)f(\(base)i(2,)g(without)g(pre\014x\))e(on)h(the)h +Fn(stream)p Fp(.)0 2289 y Fn(void)e(fprintoctal)f(\(cl_ostream)f +(stream,)h(const)h(cl_I&)g(x\))480 2414 y Fp(Prin)m(ts)h(the)h(in)m +(teger)h Fn(x)e Fp(in)g(o)s(ctal)h(\(base)g(8,)g(without)g(pre\014x\))e +(on)i(the)f Fn(stream)p Fp(.)0 2594 y Fn(void)f(fprinthexadecimal)d +(\(cl_ostream)h(stream,)i(const)f(cl_I&)h(x\))480 2718 +y Fp(Prin)m(ts)h(the)h(in)m(teger)h Fn(x)e Fp(in)g(hexadecimal)g +(\(base)h(16,)h(without)e(pre\014x\))g(on)g(the)h Fn(stream)p +Fp(.)0 3023 y(Eac)m(h)k(of)g(the)g(classes)g Fn(cl_N)p +Fp(,)g Fn(cl_R)p Fp(,)g Fn(cl_RA)p Fp(,)f Fn(cl_I)p Fp(,)h +Fn(cl_F)p Fp(,)f Fn(cl_SF)p Fp(,)h Fn(cl_FF)p Fp(,)f +Fn(cl_DF)p Fp(,)h Fn(cl_LF)e Fp(de\014nes,)i(in)f Fn()p Fp(,)29 b(the)i(follo)m(wing)h +(output)e(functions:)0 3451 y Fn(void)f(fprint)g(\(cl_ostream)e +(stream,)i(const)f Fi(t)m(yp)s(e)5 b Fn(&)31 b(x\))0 +3576 y(cl_ostream)d(operator<<)f(\(cl_ostream)g(stream,)i(const)g +Fi(t)m(yp)s(e)5 b Fn(&)30 b(x\))480 3700 y Fp(Prin)m(ts)38 +b(the)h(n)m(um)m(b)s(er)d Fn(x)i Fp(on)g(the)h Fn(stream)p +Fp(.)63 b(The)38 b(output)g(ma)m(y)g(dep)s(end)f(on)h(the)h(global)g +(prin)m(ter)480 3825 y(settings)k(in)e(the)h(v)-5 b(ariable)43 +b Fn(cl_default_print_flags)p Fp(.)69 b(The)42 b Fn(ostream)e +Fp(\015ags)i(and)f(settings)480 3950 y(\(\015ags,)31 +b(width)f(and)g(lo)s(cale\))i(are)f(ignored.)0 4254 y(The)f(most)g +(\015exible)g(output)g(function,)g(de\014ned)g(in)g Fn()p Fp(,)28 b(are)j(the)f(follo)m(wing:)240 +4510 y Fn(void)47 b(print_complex)92 b(\(cl_ostream)44 +b(stream,)i(const)g(cl_print_flags&)e(flags,)1242 4614 +y(const)j(cl_N&)f(z\);)240 4717 y(void)h(print_real)236 +b(\(cl_ostream)44 b(stream,)i(const)g(cl_print_flags&)e(flags,)1242 +4821 y(const)j(cl_R&)f(z\);)240 4925 y(void)h(print_float)188 +b(\(cl_ostream)44 b(stream,)i(const)g(cl_print_flags&)e(flags,)1242 +5029 y(const)j(cl_F&)f(z\);)240 5132 y(void)h(print_rational)d +(\(cl_ostream)g(stream,)i(const)g(cl_print_flags&)e(flags,)1242 +5236 y(const)j(cl_RA&)f(z\);)240 5340 y(void)h(print_integer)92 +b(\(cl_ostream)44 b(stream,)i(const)g(cl_print_flags&)e(flags,)p +eop +%%Page: 42 44 +42 43 bop 0 -116 a Fp(Chapter)30 b(5:)41 b(Input/Output)2784 +b(42)1242 366 y Fn(const)47 b(cl_I&)f(z\);)0 640 y Fp(Prin)m(ts)30 +b(the)h(n)m(um)m(b)s(er)d Fn(x)i Fp(on)g(the)h Fn(stream)p +Fp(.)39 b(The)30 b Fn(flags)f Fp(are)h(parameters)g(whic)m(h)g +(a\013ect)i(the)f(output.)0 914 y(The)f(structure)g(t)m(yp)s(e)g +Fn(cl_print_flags)d Fp(con)m(tains)k(the)g(follo)m(wing)h(\014elds:)0 +1213 y Fn(unsigned)c(int)i(rational_base)480 1338 y Fp(The)g(base)g(in) +g(whic)m(h)h(rational)g(n)m(um)m(b)s(ers)d(are)j(prin)m(ted.)40 +b(Default)32 b(is)e Fn(10)p Fp(.)0 1512 y Fn(cl_boolean)e +(rational_readably)480 1637 y Fp(If)i(this)h(\015ag)g(is)g(true,)g +(rational)h(n)m(um)m(b)s(ers)c(are)j(prin)m(ted)f(with)h(radix)f(sp)s +(eci\014ers)g(in)g(Common)f(Lisp)480 1761 y(syn)m(tax)i(\()p +Fn(#)p Fi(n)p Fn(R)f Fp(or)g Fn(#b)g Fp(or)g Fn(#o)g +Fp(or)g Fn(#x)g Fp(pre\014xes,)g(trailing)h(dot\).)41 +b(Default)32 b(is)e(false.)0 1936 y Fn(cl_boolean)e(float_readably)480 +2060 y Fp(If)i(this)g(\015ag)g(is)g(true,)h(t)m(yp)s(e)f(sp)s(eci\014c) +g(exp)s(onen)m(t)g(mark)m(ers)f(ha)m(v)m(e)j(precedence)e(o)m(v)m(er)i +('E'.)f(Default)g(is)480 2185 y(false.)0 2359 y Fn(cl_float_format_t)26 +b(default_float_format)480 2484 y Fp(Floating)35 b(p)s(oin)m(t)e(n)m +(um)m(b)s(ers)d(of)j(this)g(format)g(will)g(b)s(e)f(prin)m(ted)h(using) +f(the)h('E')g(exp)s(onen)m(t)g(mark)m(er.)480 2608 y(Default)e(is)g +Fn(cl_float_format_ffloat)p Fp(.)0 2782 y Fn(cl_boolean)d +(complex_readably)480 2907 y Fp(If)37 b(this)f(\015ag)i(is)f(true,)h +(complex)f(n)m(um)m(b)s(ers)e(will)i(b)s(e)f(prin)m(ted)h(using)f(the)i +(Common)c(Lisp)i(syn)m(tax)480 3031 y Fn(#C\()p Fi(realpart)c(imagpart) +r Fn(\))p Fp(.)40 b(Default)32 b(is)e(false.)0 3206 y +Fn(cl_string)e(univpoly_varname)480 3330 y Fp(Univ)-5 +b(ariate)31 b(p)s(olynomials)f(with)f(no)h(explicit)h(indeterminate)f +(name)f(will)i(b)s(e)e(prin)m(ted)h(using)f(this)480 +3455 y(v)-5 b(ariable)31 b(name.)40 b(Default)31 b(is)g +Fn("x")p Fp(.)0 3754 y(The)38 b(global)i(v)-5 b(ariable)40 +b Fn(cl_default_print_flags)32 b Fp(con)m(tains)40 b(the)f(default)g(v) +-5 b(alues,)41 b(used)d(b)m(y)g(the)h(function)0 3878 +y Fn(fprint)p Fp(,)p eop +%%Page: 43 45 +43 44 bop 0 -116 a Fp(Chapter)30 b(6:)41 b(Rings)3120 +b(43)0 366 y Fm(6)80 b(Rings)0 754 y Fp(CLN)30 b(has)g(a)h(class)g(of)g +(abstract)g(rings.)1433 1010 y Fn(Ring)1338 1113 y(cl_ring)1290 +1217 y()0 1494 y Fp(Rings)f(can)h(b)s(e)f(compared)f(for)h +(equalit)m(y:)0 1798 y Fn(bool)f(operator==)f(\(const)g(cl_ring&,)g +(const)h(cl_ring&\))0 1923 y(bool)g(operator!=)f(\(const)g(cl_ring&,)g +(const)h(cl_ring&\))480 2047 y Fp(These)h(compare)g(t)m(w)m(o)i(rings)e +(for)g(equalit)m(y)-8 b(.)0 2352 y(Giv)m(en)31 b(a)g(ring)f +Fn(R)p Fp(,)g(the)h(follo)m(wing)h(mem)m(b)s(ers)27 b(can)k(b)s(e)f +(used.)0 2656 y Fn(void)f(R->fprint)f(\(cl_ostream)f(stream,)i(const)g +(cl_ring_element&)d(x\))0 2780 y(cl_boolean)i(R->equal)g(\(const)g +(cl_ring_element&)e(x,)k(const)f(cl_ring_element&)d(y\))0 +2905 y(cl_ring_element)g(R->zero)j(\(\))0 3030 y(cl_boolean)f(R->zerop) +g(\(const)g(cl_ring_element&)e(x\))0 3154 y(cl_ring_element)g(R->plus)j +(\(const)f(cl_ring_element&)e(x,)k(const)f(cl_ring_element&)d(y\))0 +3279 y(cl_ring_element)g(R->minus)i(\(const)h(cl_ring_element&)d(x,)k +(const)f(cl_ring_element&)d(y\))0 3403 y(cl_ring_element)g(R->uminus)i +(\(const)h(cl_ring_element&)d(x\))0 3528 y(cl_ring_element)g(R->one)j +(\(\))0 3652 y(cl_ring_element)d(R->canonhom)i(\(const)g(cl_I&)h(x\))0 +3777 y(cl_ring_element)d(R->mul)j(\(const)g(cl_ring_element&)c(x,)30 +b(const)f(cl_ring_element&)d(y\))0 3901 y(cl_ring_element)g(R->square)i +(\(const)h(cl_ring_element&)d(x\))0 4026 y(cl_ring_element)g +(R->expt_pos)i(\(const)g(cl_ring_element&)e(x,)k(const)f(cl_I&)g(y\))0 +4302 y Fp(The)h(follo)m(wing)i(rings)e(are)g(built-in.)0 +4607 y Fn(cl_null_ring)d(cl_0_ring)480 4731 y Fp(The)j(n)m(ull)g(ring,) +h(con)m(taining)g(only)g(zero.)0 4911 y Fn(cl_complex_ring)26 +b(cl_C_ring)480 5036 y Fp(The)k(ring)g(of)h(complex)f(n)m(um)m(b)s +(ers.)38 b(This)29 b(corresp)s(onds)g(to)j(the)e(t)m(yp)s(e)h +Fn(cl_N)p Fp(.)0 5215 y Fn(cl_real_ring)c(cl_R_ring)480 +5340 y Fp(The)j(ring)g(of)h(real)g(n)m(um)m(b)s(ers.)38 +b(This)29 b(corresp)s(onds)g(to)i(the)g(t)m(yp)s(e)g +Fn(cl_R)p Fp(.)p eop +%%Page: 44 46 +44 45 bop 0 -116 a Fp(Chapter)30 b(6:)41 b(Rings)3120 +b(44)0 366 y Fn(cl_rational_ring)26 b(cl_RA_ring)480 +491 y Fp(The)k(ring)g(of)h(rational)g(n)m(um)m(b)s(ers.)38 +b(This)30 b(corresp)s(onds)f(to)i(the)g(t)m(yp)s(e)f +Fn(cl_RA)p Fp(.)0 665 y Fn(cl_integer_ring)c(cl_I_ring)480 +790 y Fp(The)k(ring)g(of)h(in)m(tegers.)41 b(This)30 +b(corresp)s(onds)f(to)i(the)g(t)m(yp)s(e)f Fn(cl_I)p +Fp(.)0 1089 y(T)m(yp)s(e)g(tests)h(can)g(b)s(e)e(p)s(erformed)f(for)i +(an)m(y)h(of)g Fn(cl_C_ring)p Fp(,)d Fn(cl_R_ring)p Fp(,)g +Fn(cl_RA_ring)p Fp(,)g Fn(cl_I_ring)p Fp(:)0 1388 y Fn(cl_boolean)g +(instanceof)f(\(const)i(cl_number&)e(x,)j(const)f(cl_number_ring&)d +(R\))480 1512 y Fp(T)-8 b(ests)31 b(whether)f(the)g(giv)m(en)i(n)m(um)m +(b)s(er)c(is)i(an)g(elemen)m(t)h(of)g(the)f(n)m(um)m(b)s(er)e(ring)i +(R.)p eop +%%Page: 45 47 +45 46 bop 0 -116 a Fp(Chapter)30 b(7:)41 b(Mo)s(dular)30 +b(in)m(tegers)2670 b(45)0 366 y Fm(7)80 b(Mo)t(dular)32 +b(in)l(tegers)0 1011 y Fq(7.1)68 b(Mo)t(dular)30 b(in)l(teger)i(rings)0 +1292 y Fp(CLN)24 b(implemen)m(ts)f(mo)s(dular)g(in)m(tegers,)k(i.e.)40 +b(in)m(tegers)26 b(mo)s(dulo)d(a)i(\014xed)f(in)m(teger)i(N.)f(The)g +(mo)s(dulus)d(is)i(explicitly)0 1417 y(part)34 b(of)f(ev)m(ery)i(mo)s +(dular)d(in)m(teger.)52 b(CLN)33 b(do)s(esn't)g(allo)m(w)i(y)m(ou)g(to) +f(\(acciden)m(tally\))j(mix)c(elemen)m(ts)h(of)f(di\013eren)m(t)0 +1541 y(mo)s(dular)20 b(rings,)k(e.g.)39 b Fn(\(3)30 b(mod)f(4\))h(+)g +(\(2)g(mod)f(5\))22 b Fp(will)g(result)g(in)g(a)h(run)m(time)e(error.) +37 b(\(Ideally)23 b(one)g(w)m(ould)f(imagine)0 1666 y(a)28 +b(generic)g(data)g(t)m(yp)s(e)f Fn(cl_MI\(N\))p Fp(,)f(but)g(C)p +Fn(++)g Fp(do)s(esn't)h(ha)m(v)m(e)i(generic)f(t)m(yp)s(es.)39 +b(So)28 b(one)f(has)g(to)h(liv)m(e)g(with)f(run)m(time)0 +1790 y(c)m(hec)m(ks.\))0 2072 y(The)j(class)h(of)g(mo)s(dular)d(in)m +(teger)k(rings)e(is)1433 2332 y Fn(Ring)1338 2436 y(cl_ring)1290 +2540 y()1481 2644 y(|)1481 2748 y(|)1051 2851 +y(Modular)46 b(integer)g(ring)1195 2955 y(cl_modint_ring)1147 +3059 y()0 3340 y Fp(and)30 b(the)g(class)h(of)g(all)g +(mo)s(dular)e(in)m(tegers)i(\(elemen)m(ts)g(of)g(mo)s(dular)d(in)m +(teger)k(rings\))e(is)1195 3601 y Fn(Modular)45 b(integer)1433 +3705 y(cl_MI)1147 3808 y()0 4090 y Fp(Mo)s(dular)30 +b(in)m(teger)i(rings)e(are)g(constructed)h(using)f(the)h(function)0 +4404 y Fn(cl_modint_ring)26 b(cl_find_modint_ring)g(\(const)i(cl_I&)h +(N\))480 4528 y Fp(This)23 b(function)h(returns)e(the)i(mo)s(dular)e +(ring)i(`)p Fn(Z/NZ)p Fp('.)37 b(It)24 b(tak)m(es)i(care)e(of)g +(\014nding)f(out)h(ab)s(out)f(sp)s(ecial)480 4653 y(cases)34 +b(of)f Fn(N)p Fp(,)g(lik)m(e)h(p)s(o)m(w)m(ers)f(of)g(t)m(w)m(o)i(and)d +(o)s(dd)g(n)m(um)m(b)s(ers)e(for)j(whic)m(h)f(Mon)m(tgomery)i(m)m +(ultiplication)480 4777 y(will)39 b(b)s(e)f(a)h(win,)h(and)e +(precomputes)f(an)m(y)h(necessary)h(auxiliary)h(data)f(for)f(computing) +g(mo)s(dulo)480 4902 y Fn(N)p Fp(.)45 b(There)32 b(is)f(a)i(cac)m(he)g +(table)g(of)f(rings,)g(indexed)g(b)m(y)g Fn(N)f Fp(\(or,)i(more)e +(precisely)-8 b(,)34 b(b)m(y)e Fn(abs\(N\))p Fp(\).)44 +b(This)480 5026 y(ensures)29 b(that)i(the)g(precomputation)f(costs)h +(are)g(reduced)e(to)j(a)e(minim)m(um.)0 5340 y(Mo)s(dular)g(in)m(teger) +i(rings)e(can)g(b)s(e)g(compared)f(for)i(equalit)m(y:)p +eop +%%Page: 46 48 +46 47 bop 0 -116 a Fp(Chapter)30 b(7:)41 b(Mo)s(dular)30 +b(in)m(tegers)2670 b(46)0 366 y Fn(bool)29 b(operator==)f(\(const)g +(cl_modint_ring&,)e(const)j(cl_modint_ring&\))0 491 y(bool)g +(operator!=)f(\(const)g(cl_modint_ring&,)e(const)j(cl_modint_ring&\)) +480 616 y Fp(These)e(compare)g(t)m(w)m(o)h(mo)s(dular)e(in)m(teger)i +(rings)f(for)g(equalit)m(y)-8 b(.)42 b(Tw)m(o)27 b(di\013eren)m(t)h +(calls)g(to)g Fn(cl_find_)480 740 y(modint_ring)34 b +Fp(with)i(the)h(same)f(argumen)m(t)g(necessarily)h(return)f(the)h(same) +f(ring)g(b)s(ecause)h(it)g(is)480 865 y(memoized)29 b(in)h(the)h(cac)m +(he)h(table.)0 1318 y Fq(7.2)68 b(F)-11 b(unctions)30 +b(on)g(mo)t(dular)g(in)l(tegers)0 1593 y Fp(Giv)m(en)h(a)g(mo)s(dular)d +(in)m(teger)k(ring)e Fn(R)p Fp(,)h(the)f(follo)m(wing)i(mem)m(b)s(ers)c +(can)i(b)s(e)g(used.)0 1893 y Fn(cl_I)f(R->modulus)480 +2017 y Fp(This)h(is)g(the)h(ring's)f(mo)s(dulus,)e(normalized)i(to)h(b) +s(e)e(nonnegativ)m(e:)43 b Fn(abs\(N\))p Fp(.)0 2193 +y Fn(cl_MI)29 b(R->zero\(\))480 2317 y Fp(This)h(returns)f +Fn(0)h(mod)f(N)p Fp(.)0 2493 y Fn(cl_MI)g(R->one\(\))480 +2617 y Fp(This)h(returns)f Fn(1)h(mod)f(N)p Fp(.)0 2793 +y Fn(cl_MI)g(R->canonhom)e(\(const)i(cl_I&)g(x\))480 +2917 y Fp(This)h(returns)f Fn(x)h(mod)f(N)p Fp(.)0 3093 +y Fn(cl_I)g(R->retract)f(\(const)g(cl_MI&)h(x\))480 3217 +y Fp(This)20 b(is)h(a)g(partial)g(in)m(v)m(erse)h(function)e(to)i +Fn(R->canonhom)p Fp(.)34 b(It)21 b(returns)e(the)i(standard)f(represen) +m(tativ)m(e)480 3342 y(\()p Fn(>=0)p Fp(,)30 b Fn(random\(cl_random_stat) +o(e&)24 b(randomstate\))0 3642 y(cl_MI)29 b(R->random\(\))480 +3766 y Fp(This)h(returns)f(a)h(random)f(in)m(teger)j(mo)s(dulo)d +Fn(N)p Fp(.)0 4066 y(The)h(follo)m(wing)i(op)s(erations)e(are)h +(de\014ned)e(on)i(mo)s(dular)d(in)m(tegers.)0 4366 y +Fn(cl_modint_ring)e(x.ring)j(\(\))480 4491 y Fp(Returns)g(the)i(ring)f +(to)h(whic)m(h)f(the)h(mo)s(dular)d(in)m(teger)k Fn(x)e +Fp(b)s(elongs.)0 4666 y Fn(cl_MI)f(operator+)f(\(const)g(cl_MI&,)h +(const)g(cl_MI&\))480 4791 y Fp(Returns)j(the)h(sum)f(of)h(t)m(w)m(o)h +(mo)s(dular)d(in)m(tegers.)51 b(One)32 b(of)i(the)f(argumen)m(ts)f(ma)m +(y)h(also)h(b)s(e)f(a)g(plain)480 4915 y(in)m(teger.)0 +5091 y Fn(cl_MI)c(operator-)f(\(const)g(cl_MI&,)h(const)g(cl_MI&\))480 +5215 y Fp(Returns)k(the)h(di\013erence)h(of)f(t)m(w)m(o)i(mo)s(dular)c +(in)m(tegers.)53 b(One)33 b(of)i(the)f(argumen)m(ts)f(ma)m(y)h(also)h +(b)s(e)f(a)480 5340 y(plain)c(in)m(teger.)p eop +%%Page: 47 49 +47 48 bop 0 -116 a Fp(Chapter)30 b(7:)41 b(Mo)s(dular)30 +b(in)m(tegers)2670 b(47)0 366 y Fn(cl_MI)29 b(operator-)f(\(const)g +(cl_MI&\))480 491 y Fp(Returns)h(the)i(negativ)m(e)i(of)d(a)h(mo)s +(dular)d(in)m(teger.)0 663 y Fn(cl_MI)h(operator*)f(\(const)g(cl_MI&,)h +(const)g(cl_MI&\))480 787 y Fp(Returns)37 b(the)i(pro)s(duct)e(of)h(t)m +(w)m(o)i(mo)s(dular)c(in)m(tegers.)65 b(One)38 b(of)g(the)h(argumen)m +(ts)e(ma)m(y)h(also)h(b)s(e)f(a)480 912 y(plain)30 b(in)m(teger.)0 +1084 y Fn(cl_MI)f(square)g(\(const)f(cl_MI&\))480 1208 +y Fp(Returns)h(the)i(square)f(of)h(a)f(mo)s(dular)f(in)m(teger.)0 +1380 y Fn(cl_MI)g(recip)g(\(const)g(cl_MI&)f(x\))480 +1505 y Fp(Returns)c(the)i(recipro)s(cal)f Fn(x^-1)f Fp(of)i(a)f(mo)s +(dular)e(in)m(teger)k Fn(x)p Fp(.)38 b Fn(x)25 b Fp(m)m(ust)f(b)s(e)h +(coprime)f(to)i(the)f(mo)s(dulus,)480 1629 y(otherwise)31 +b(an)f(error)g(message)h(is)f(issued.)0 1801 y Fn(cl_MI)f(div)g +(\(const)g(cl_MI&)g(x,)h(const)e(cl_MI&)h(y\))480 1926 +y Fp(Returns)j(the)h(quotien)m(t)h Fn(x*y^-1)e Fp(of)h(t)m(w)m(o)h(mo)s +(dular)d(in)m(tegers)j Fn(x)p Fp(,)g Fn(y)p Fp(.)48 b +Fn(y)33 b Fp(m)m(ust)e(b)s(e)i(coprime)f(to)i(the)480 +2050 y(mo)s(dulus,)28 b(otherwise)j(an)f(error)g(message)g(is)h +(issued.)0 2222 y Fn(cl_MI)e(expt_pos)f(\(const)h(cl_MI&)f(x,)i(const)f +(cl_I&)g(y\))480 2347 y(y)h Fp(m)m(ust)f(b)s(e)h Fn(>)g +Fp(0.)41 b(Returns)30 b Fn(x^y)p Fp(.)0 2519 y Fn(cl_MI)f(expt)g +(\(const)g(cl_MI&)f(x,)i(const)f(cl_I&)g(y\))480 2643 +y Fp(Returns)d Fn(x^y)p Fp(.)39 b(If)26 b Fn(y)h Fp(is)g(negativ)m(e,)j +Fn(x)d Fp(m)m(ust)f(b)s(e)h(coprime)f(to)i(the)f(mo)s(dulus,)e(else)j +(an)f(error)g(message)480 2768 y(is)j(issued.)0 2940 +y Fn(cl_MI)f(operator<<)f(\(const)g(cl_MI&)h(x,)h(const)f(cl_I&)f(y\)) +480 3064 y Fp(Returns)h Fn(x*2^y)p Fp(.)0 3236 y Fn(cl_MI)g(operator>>) +f(\(const)g(cl_MI&)h(x,)h(const)f(cl_I&)f(y\))480 3361 +y Fp(Returns)g Fn(x*2^-y)p Fp(.)38 b(When)29 b Fn(y)f +Fp(is)h(p)s(ositiv)m(e,)i(the)e(mo)s(dulus)d(m)m(ust)i(b)s(e)g(o)s(dd,) +g(or)h(an)g(error)f(message)h(is)480 3485 y(issued.)0 +3657 y Fn(bool)g(operator==)f(\(const)g(cl_MI&,)h(const)g(cl_MI&\))0 +3782 y(bool)g(operator!=)f(\(const)g(cl_MI&,)h(const)g(cl_MI&\))480 +3906 y Fp(Compares)24 b(t)m(w)m(o)i(mo)s(dular)d(in)m(tegers,)28 +b(b)s(elonging)e(to)f(the)h(same)e(mo)s(dular)f(in)m(teger)k(ring,)f +(for)f(equal-)480 4031 y(it)m(y)-8 b(.)0 4203 y Fn(cl_boolean)28 +b(zerop)h(\(const)f(cl_MI&)h(x\))480 4327 y Fp(Returns)g(true)i(if)f +Fn(x)g Fp(is)g Fn(0)g(mod)g(N)p Fp(.)0 4625 y(The)g(follo)m(wing)i +(output)e(functions)g(are)g(de\014ned)g(\(see)h(also)g(the)g(c)m +(hapter)g(on)f(input/output\).)0 4923 y Fn(void)f(fprint)g +(\(cl_ostream)e(stream,)i(const)f(cl_MI&)h(x\))0 5047 +y(cl_ostream)f(operator<<)f(\(cl_ostream)g(stream,)i(const)g(cl_MI&)f +(x\))480 5172 y Fp(Prin)m(ts)36 b(the)h(mo)s(dular)e(in)m(teger)j +Fn(x)e Fp(on)g(the)h Fn(stream)p Fp(.)57 b(The)36 b(output)h(ma)m(y)f +(dep)s(end)e(on)j(the)g(global)480 5296 y(prin)m(ter)30 +b(settings)h(in)f(the)h(v)-5 b(ariable)31 b Fn(cl_default_print_flags)p +Fp(.)p eop +%%Page: 48 50 +48 49 bop 0 -116 a Fp(Chapter)30 b(8:)41 b(Sym)m(b)s(olic)29 +b(data)i(t)m(yp)s(es)2536 b(48)0 366 y Fm(8)80 b(Sym)l(b)t(olic)31 +b(data)f(t)l(yp)t(es)0 784 y Fp(CLN)g(implemen)m(ts)f(t)m(w)m(o)j(sym)m +(b)s(olic)d(\(non-n)m(umeric\))h(data)h(t)m(yp)s(es:)41 +b(strings)30 b(and)g(sym)m(b)s(ols.)0 1310 y Fq(8.1)68 +b(Strings)0 1593 y Fp(The)30 b(class)1290 1855 y Fn(String)1242 +1959 y(cl_string)1195 2062 y()0 2345 y Fp(implemen)m(ts)f +(imm)m(utable)g(strings.)0 2628 y(Strings)h(are)h(constructed)f +(through)g(the)h(follo)m(wing)g(constructors:)0 2944 +y Fn(cl_string)d(\(const)h(char)g(*)h(s\))480 3069 y +Fp(Returns)f(an)i(imm)m(utable)e(cop)m(y)i(of)f(the)h +(\(zero-terminated\))h(C)e(string)g Fn(s)p Fp(.)0 3260 +y Fn(cl_string)e(\(const)h(char)g(*)h(ptr,)f(unsigned)f(long)h(len\)) +480 3385 y Fp(Returns)34 b(an)h(imm)m(utable)f(cop)m(y)h(of)g(the)h +Fn(len)e Fp(c)m(haracters)i(at)g Fn(ptr[0])p Fp(,)f Fl(:)15 +b(:)g(:)q Fp(,)36 b Fn(ptr[len-1])p Fp(.)52 b(NUL)480 +3509 y(c)m(haracters)32 b(are)f(allo)m(w)m(ed.)0 3826 +y(The)f(follo)m(wing)i(functions)e(are)g(a)m(v)-5 b(ailable)33 +b(on)d(strings:)0 4142 y Fn(operator)e(=)480 4267 y Fp(Assignmen)m(t)i +(from)f Fn(cl_string)f Fp(and)h Fn(const)g(char)h(*)p +Fp(.)0 4458 y Fn(s.length\(\))0 4583 y(strlen\(s\))480 +4707 y Fp(Returns)f(the)i(length)g(of)f(the)h(string)f +Fn(s)p Fp(.)0 4899 y Fn(s[i])288 b Fp(Returns)24 b(the)h +Fn(i)p Fp(th)f(c)m(haracter)j(of)e(the)f(string)h Fn(s)p +Fp(.)39 b Fn(i)24 b Fp(m)m(ust)g(b)s(e)g(in)h(the)f(range)i +Fn(0)k(<=)f(i)h(<)g(s.length\(\))p Fp(.)0 5091 y Fn(bool)f(equal)g +(\(const)g(cl_string&)e(s1,)j(const)f(cl_string&)e(s2\))480 +5215 y Fp(Compares)34 b(t)m(w)m(o)i(strings)f(for)g(equalit)m(y)-8 +b(.)57 b(One)35 b(of)g(the)h(argumen)m(ts)e(ma)m(y)h(also)h(b)s(e)f(a)g +(plain)g Fn(const)480 5340 y(char)29 b(*)p Fp(.)p eop +%%Page: 49 51 +49 50 bop 0 -116 a Fp(Chapter)30 b(8:)41 b(Sym)m(b)s(olic)29 +b(data)i(t)m(yp)s(es)2536 b(49)0 366 y Fq(8.2)68 b(Sym)l(b)t(ols)0 +640 y Fp(Sym)m(b)s(ols)40 b(are)j(uniqui\014ed)d(strings:)64 +b(all)43 b(sym)m(b)s(ols)e(with)h(the)g(same)g(name)f(are)i(shared.)75 +b(This)41 b(means)g(that)0 765 y(comparison)34 b(of)i(t)m(w)m(o)g(sym)m +(b)s(ols)e(is)h(fast)h(\(e\013ectiv)m(ely)i(just)d(a)g(p)s(oin)m(ter)g +(comparison\),)h(whereas)f(comparison)g(of)0 890 y(t)m(w)m(o)26 +b(strings)f(m)m(ust)f(in)g(the)h(w)m(orst)h(case)g(w)m(alk)f(b)s(oth)f +(strings)h(un)m(til)g(their)g(end.)38 b(Sym)m(b)s(ols)24 +b(are)h(used,)g(for)g(example,)0 1014 y(as)31 b(tags)g(for)f(prop)s +(erties,)g(as)h(names)e(of)i(v)-5 b(ariables)31 b(in)f(p)s(olynomial)f +(rings,)i(etc.)0 1288 y(Sym)m(b)s(ols)e(are)h(constructed)h(through)f +(the)g(follo)m(wing)i(constructor:)0 1587 y Fn(cl_symbol)c(\(const)h +(cl_string&)e(s\))480 1711 y Fp(Lo)s(oks)j(up)g(or)g(creates)i(a)f(new) +e(sym)m(b)s(ol)h(with)g(a)g(giv)m(en)i(name.)0 2010 y(The)e(follo)m +(wing)i(op)s(erations)e(are)h(a)m(v)-5 b(ailable)33 b(on)d(sym)m(b)s +(ols:)0 2309 y Fn(cl_string)e(\(const)h(cl_symbol&)e(sym\))480 +2434 y Fp(Con)m(v)m(ersion)k(to)g Fn(cl_string)p Fp(:)38 +b(Returns)30 b(the)g(string)h(whic)m(h)f(names)f(the)i(sym)m(b)s(ol)e +Fn(sym)p Fp(.)0 2608 y Fn(bool)g(equal)g(\(const)g(cl_symbol&)e(sym1,)i +(const)g(cl_symbol&)f(sym2\))480 2733 y Fp(Compares)h(t)m(w)m(o)j(sym)m +(b)s(ols)d(for)h(equalit)m(y)-8 b(.)43 b(This)29 b(is)i(v)m(ery)f +(fast.)p eop +%%Page: 50 52 +50 51 bop 0 -116 a Fp(Chapter)30 b(9:)41 b(Univ)-5 b(ariate)32 +b(p)s(olynomials)2423 b(50)0 366 y Fm(9)80 b(Univ)-9 +b(ariate)33 b(p)t(olynomials)0 907 y Fq(9.1)68 b(Univ)-7 +b(ariate)32 b(p)t(olynomial)g(rings)0 1181 y Fp(CLN)d(implemen)m(ts)e +(univ)-5 b(ariate)30 b(p)s(olynomials)f(\(p)s(olynomials)f(in)h(one)h +(v)-5 b(ariable\))30 b(o)m(v)m(er)g(an)f(arbitrary)g(ring.)40 +b(The)0 1305 y(indeterminate)h(v)-5 b(ariable)43 b(ma)m(y)e(b)s(e)g +(either)i(unnamed)c(\(and)i(will)h(b)s(e)g(prin)m(ted)f(according)i(to) +f Fn(cl_default_)0 1430 y(print_flags.univpoly_var)o(name)o +Fp(,)23 b(whic)m(h)28 b(defaults)g(to)g(`)p Fn(x)p Fp('\))h(or)f(carry) +g(a)g(giv)m(en)h(name.)39 b(The)28 b(base)g(ring)g(and)0 +1554 y(the)h(indeterminate)f(are)g(explicitly)i(part)f(of)f(ev)m(ery)h +(p)s(olynomial.)40 b(CLN)28 b(do)s(esn't)g(allo)m(w)i(y)m(ou)e(to)i +(\(acciden)m(tally\))0 1679 y(mix)h(elemen)m(ts)h(of)f(di\013eren)m(t)h +(p)s(olynomial)f(rings,)h(e.g.)46 b Fn(\(a^2+1\))28 b(*)i(\(b^3-1\))g +Fp(will)i(result)f(in)h(a)g(run)m(time)e(error.)0 1803 +y(\(Ideally)h(this)g(should)e(return)g(a)i(m)m(ultiv)-5 +b(ariate)31 b(p)s(olynomial,)f(but)g(they)h(are)f(not)h(y)m(et)g +(implemen)m(ted)e(in)h(CLN.\))0 2077 y(The)g(classes)h(of)g(univ)-5 +b(ariate)31 b(p)s(olynomial)f(rings)f(are)1529 2330 y +Fn(Ring)1433 2434 y(cl_ring)1385 2538 y()1576 +2642 y(|)1576 2746 y(|)1051 2849 y(Univariate)45 b(polynomial)g(ring) +1290 2953 y(cl_univpoly_ring)1290 3057 y()1576 +3161 y(|)765 3264 y(+----------------+------)o(----)o(----)o(---)o(--+) +765 3368 y(|)763 b(|)907 b(|)288 3472 y(Complex)46 b(polynomial)f(ring) +189 b(|)i(Modular)46 b(integer)g(polynomial)f(ring)288 +3576 y(cl_univpoly_complex_rin)o(g)137 b(|)382 b +(cl_univpoly_modint_ring)335 3680 y()137 +b(|)382 b()1576 3783 y(|)765 3887 +y(+----------------+)765 3991 y(|)763 b(|)383 4095 y(Real)47 +b(polynomial)e(ring)237 b(|)383 4198 y(cl_univpoly_real_ring)185 +b(|)431 4302 y()g(|)1576 4406 y(|)765 +4510 y(+----------------+)765 4614 y(|)763 b(|)288 4717 +y(Rational)45 b(polynomial)g(ring)142 b(|)288 4821 y +(cl_univpoly_rational_ri)o(ng)89 b(|)335 4925 y +()g(|)1576 5029 y(|)765 5132 +y(+----------------+)765 5236 y(|)288 5340 y(Integer)46 +b(polynomial)f(ring)p eop +%%Page: 51 53 +51 52 bop 0 -116 a Fp(Chapter)30 b(9:)41 b(Univ)-5 b(ariate)32 +b(p)s(olynomials)2423 b(51)288 366 y Fn(cl_univpoly_integer_rin)o(g)335 +470 y()0 784 y Fp(and)30 b(the)g(corresp)s +(onding)g(classes)h(of)g(univ)-5 b(ariate)31 b(p)s(olynomials)e(are) +1147 1077 y Fn(Univariate)45 b(polynomial)1481 1181 y(cl_UP)1290 +1285 y()1576 1389 y(|)765 1492 y +(+----------------+------)o(----)o(----)o(---)o(--+)765 +1596 y(|)763 b(|)907 b(|)383 1700 y(Complex)46 b(polynomial)331 +b(|)286 b(Modular)46 b(integer)g(polynomial)622 1804 +y(cl_UP_N)618 b(|)764 b(cl_UP_MI)335 1908 y()137 +b(|)382 b()1576 2011 y(|)765 2115 +y(+----------------+)765 2219 y(|)763 b(|)479 2323 y(Real)46 +b(polynomial)379 b(|)622 2426 y(cl_UP_R)618 b(|)431 2530 +y()185 b(|)1576 2634 y(|)765 2738 +y(+----------------+)765 2842 y(|)763 b(|)383 2945 y(Rational)46 +b(polynomial)283 b(|)622 3049 y(cl_UP_RA)570 b(|)335 +3153 y()89 b(|)1576 3257 y(|)765 +3360 y(+----------------+)765 3464 y(|)383 3568 y(Integer)46 +b(polynomial)622 3672 y(cl_UP_I)335 3776 y()0 +4089 y Fp(Univ)-5 b(ariate)32 b(p)s(olynomial)d(rings)h(are)h +(constructed)g(using)f(the)g(functions)0 4468 y Fn(cl_univpoly_ring)c +(cl_find_univpoly_ring)e(\(const)29 b(cl_ring&)f(R\))0 +4593 y(cl_univpoly_ring)e(cl_find_univpoly_ring)e(\(const)29 +b(cl_ring&)f(R,)i(const)f(cl_symbol&)f(varname\))480 +4717 y Fp(This)36 b(function)h(returns)f(the)i(p)s(olynomial)e(ring)h +(`)p Fn(R[X])p Fp(',)h(unnamed)d(or)i(named.)60 b Fn(R)37 +b Fp(ma)m(y)g(b)s(e)f(an)480 4842 y(arbitrary)g(ring.)56 +b(This)35 b(function)h(tak)m(es)h(care)f(of)g(\014nding)f(out)h(ab)s +(out)f(sp)s(ecial)i(cases)f(of)g Fn(R)p Fp(,)h(suc)m(h)480 +4966 y(as)28 b(the)g(rings)g(of)g(complex)g(n)m(um)m(b)s(ers,)e(real)i +(n)m(um)m(b)s(ers,)f(rational)i(n)m(um)m(b)s(ers,)d(in)m(tegers,)k(or)e +(mo)s(dular)480 5091 y(in)m(teger)j(rings.)40 b(There)30 +b(is)g(a)g(cac)m(he)i(table)e(of)g(rings,)g(indexed)g(b)m(y)f +Fn(R)h Fp(and)f Fn(varname)p Fp(.)39 b(This)29 b(ensures)480 +5215 y(that)24 b(t)m(w)m(o)h(calls)g(of)e(this)h(function)f(with)g(the) +h(same)f(argumen)m(ts)g(will)h(return)e(the)i(same)f(p)s(olynomial)480 +5340 y(ring.)p eop +%%Page: 52 54 +52 53 bop 0 -116 a Fp(Chapter)30 b(9:)41 b(Univ)-5 b(ariate)32 +b(p)s(olynomials)2423 b(52)0 366 y Fn(cl_univpoly_complex_ring)24 +b(cl_find_univpoly_ring)g(\(const)29 b(cl_complex_ring&)d(R\))0 +491 y(cl_univpoly_complex_ring)e(cl_find_univpoly_ring)g(\(const)29 +b(cl_complex_ring&)d(R,)k(const)0 616 y(cl_symbol&)e(varname\))0 +740 y(cl_univpoly_real_ring)d(cl_find_univpoly_ring)f(\(const)29 +b(cl_real_ring&)e(R\))0 865 y(cl_univpoly_real_ring)e +(cl_find_univpoly_ring)f(\(const)29 b(cl_real_ring&)e(R,)i(const)0 +989 y(cl_symbol&)f(varname\))0 1114 y(cl_univpoly_rational_rin)o(g)c +(cl_find_univpoly_ring)h(\(const)k(cl_rational_ring&)c(R\))0 +1238 y(cl_univpoly_rational_rin)o(g)f(cl_find_univpoly_ring)h(\(const)k +(cl_rational_ring&)c(R,)30 b(const)0 1363 y(cl_symbol&)e(varname\))0 +1487 y(cl_univpoly_integer_ring)c(cl_find_univpoly_ring)g(\(const)29 +b(cl_integer_ring&)d(R\))0 1612 y(cl_univpoly_integer_ring)e +(cl_find_univpoly_ring)g(\(const)29 b(cl_integer_ring&)d(R,)k(const)0 +1736 y(cl_symbol&)e(varname\))0 1861 y(cl_univpoly_modint_ring)c +(cl_find_univpoly_ring)h(\(const)j(cl_modint_ring&)e(R\))0 +1985 y(cl_univpoly_modint_ring)e(cl_find_univpoly_ring)h(\(const)j +(cl_modint_ring&)e(R,)k(const)0 2110 y(cl_symbol&)e(varname\))480 +2234 y Fp(These)c(functions)f(are)i(equiv)-5 b(alen)m(t)26 +b(to)e(the)h(general)g Fn(cl_find_univpoly_ring)p Fp(,)20 +b(only)k(the)g(return)480 2359 y(t)m(yp)s(e)31 b(is)f(more)f(sp)s +(eci\014c,)i(according)g(to)g(the)g(base)f(ring's)h(t)m(yp)s(e.)0 +2845 y Fq(9.2)68 b(F)-11 b(unctions)30 b(on)g(univ)-7 +b(ariate)31 b(p)t(olynomials)0 3123 y Fp(Giv)m(en)g(a)g(univ)-5 +b(ariate)31 b(p)s(olynomial)f(ring)g Fn(R)p Fp(,)g(the)h(follo)m(wing)h +(mem)m(b)s(ers)27 b(can)k(b)s(e)f(used.)0 3430 y Fn(cl_ring)e +(R->basering\(\))480 3555 y Fp(This)i(returns)f(the)h(base)h(ring,)f +(as)h(passed)f(to)h(`)p Fn(cl_find_univpoly_ring)p Fp('.)0 +3737 y Fn(cl_UP)e(R->zero\(\))480 3862 y Fp(This)h(returns)f +Fn(0)h(in)g(R)p Fp(,)g(a)h(p)s(olynomial)e(of)i(degree)g(-1.)0 +4045 y Fn(cl_UP)e(R->one\(\))480 4169 y Fp(This)h(returns)f +Fn(1)h(in)g(R)p Fp(,)g(a)h(p)s(olynomial)e(of)i(degree)g +Fn(<)p Fp(=)f(0.)0 4352 y Fn(cl_UP)f(R->canonhom)e(\(const)i(cl_I&)g +(x\))480 4476 y Fp(This)h(returns)f Fn(x)h(in)g(R)p Fp(,)g(a)h(p)s +(olynomial)e(of)i(degree)g Fn(<)p Fp(=)f(0.)0 4659 y +Fn(cl_UP)f(R->monomial)e(\(const)i(cl_ring_element&)d(x,)k(uintL)f(e\)) +480 4784 y Fp(This)h(returns)f(a)h(sparse)g(p)s(olynomial:)41 +b Fn(x)30 b(*)g(X^e)p Fp(,)f(where)h Fn(X)g Fp(is)h(the)f +(indeterminate.)0 4966 y Fn(cl_UP)f(R->create)f(\(sintL)g(degree\))480 +5091 y Fp(Creates)38 b(a)g(new)f(p)s(olynomial)f(with)i(a)f(giv)m(en)i +(degree.)62 b(The)37 b(zero)h(p)s(olynomial)f(has)g(degree)h +Fn(-1)p Fp(.)480 5215 y(After)29 b(creating)i(the)e(p)s(olynomial,)f(y) +m(ou)i(should)e(put)g(in)h(the)g(co)s(e\016cien)m(ts,)i(using)d(the)h +Fn(set_coeff)480 5340 y Fp(mem)m(b)s(er)f(function,)i(and)g(then)g +(call)i(the)e Fn(finalize)e Fp(mem)m(b)s(er)g(function.)p +eop +%%Page: 53 55 +53 54 bop 0 -116 a Fp(Chapter)30 b(9:)41 b(Univ)-5 b(ariate)32 +b(p)s(olynomials)2423 b(53)0 366 y(The)30 b(follo)m(wing)i(are)e(the)h +(only)g(destructiv)m(e)g(op)s(erations)g(on)f(univ)-5 +b(ariate)31 b(p)s(olynomials.)0 677 y Fn(void)e(set_coeff)f(\(cl_UP&)g +(x,)i(uintL)f(index,)g(const)g(cl_ring_element&)d(y\))480 +802 y Fp(This)i(c)m(hanges)j(the)e(co)s(e\016cien)m(t)i(of)f +Fn(X^index)d Fp(in)i Fn(x)g Fp(to)h(b)s(e)f Fn(y)p Fp(.)40 +b(After)29 b(c)m(hanging)h(a)g(p)s(olynomial)f(and)480 +926 y(b)s(efore)35 b(applying)h(an)m(y)g Fn(")p Fp(normal)p +Fn(")f Fp(op)s(eration)h(on)g(it,)i(y)m(ou)e(should)f(call)i(its)f +Fn(finalize)e Fp(mem)m(b)s(er)480 1051 y(function.)0 +1237 y Fn(void)29 b(finalize)f(\(cl_UP&)h(x\))480 1361 +y Fp(This)f(function)g(marks)f(the)h(endp)s(oin)m(t)g(of)h(destructiv)m +(e)g(mo)s(di\014cations)f(of)g(a)h(p)s(olynomial.)40 +b(It)28 b(nor-)480 1486 y(malizes)23 b(the)f(in)m(ternal)h(represen)m +(tation)h(so)e(that)h(subsequen)m(t)f(computations)g(ha)m(v)m(e)i(less) +e(o)m(v)m(erhead.)480 1611 y(Doing)32 b(normal)e(computations)h(on)g +(unnormalized)f(p)s(olynomials)g(ma)m(y)h(pro)s(duce)e(wrong)i(results) +480 1735 y(or)f(crash)g(the)h(program.)0 2046 y(The)f(follo)m(wing)i +(op)s(erations)e(are)h(de\014ned)e(on)i(univ)-5 b(ariate)31 +b(p)s(olynomials.)0 2356 y Fn(cl_univpoly_ring)26 b(x.ring)j(\(\))480 +2481 y Fp(Returns)g(the)i(ring)f(to)h(whic)m(h)f(the)h(univ)-5 +b(ariate)31 b(p)s(olynomial)f Fn(x)g Fp(b)s(elongs.)0 +2667 y Fn(cl_UP)f(operator+)f(\(const)g(cl_UP&,)h(const)g(cl_UP&\))480 +2792 y Fp(Returns)g(the)i(sum)d(of)j(t)m(w)m(o)h(univ)-5 +b(ariate)31 b(p)s(olynomials.)0 2978 y Fn(cl_UP)e(operator-)f(\(const)g +(cl_UP&,)h(const)g(cl_UP&\))480 3102 y Fp(Returns)g(the)i(di\013erence) +g(of)f(t)m(w)m(o)i(univ)-5 b(ariate)31 b(p)s(olynomials.)0 +3288 y Fn(cl_UP)e(operator-)f(\(const)g(cl_UP&\))480 +3413 y Fp(Returns)h(the)i(negativ)m(e)i(of)d(a)h(univ)-5 +b(ariate)31 b(p)s(olynomial.)0 3599 y Fn(cl_UP)e(operator*)f(\(const)g +(cl_UP&,)h(const)g(cl_UP&\))480 3724 y Fp(Returns)e(the)h(pro)s(duct)e +(of)i(t)m(w)m(o)h(univ)-5 b(ariate)28 b(p)s(olynomials.)39 +b(One)27 b(of)h(the)g(argumen)m(ts)f(ma)m(y)g(also)i(b)s(e)480 +3848 y(a)i(plain)f(in)m(teger)i(or)e(an)g(elemen)m(t)h(of)g(the)f(base) +h(ring.)0 4034 y Fn(cl_UP)e(square)g(\(const)f(cl_UP&\))480 +4159 y Fp(Returns)h(the)i(square)f(of)h(a)f(univ)-5 b(ariate)31 +b(p)s(olynomial.)0 4345 y Fn(cl_UP)e(expt_pos)f(\(const)h(cl_UP&)f(x,)i +(const)f(cl_I&)g(y\))480 4470 y(y)h Fp(m)m(ust)f(b)s(e)h +Fn(>)g Fp(0.)41 b(Returns)30 b Fn(x^y)p Fp(.)0 4656 y +Fn(bool)f(operator==)f(\(const)g(cl_UP&,)h(const)g(cl_UP&\))0 +4780 y(bool)g(operator!=)f(\(const)g(cl_UP&,)h(const)g(cl_UP&\))480 +4905 y Fp(Compares)39 b(t)m(w)m(o)j(univ)-5 b(ariate)41 +b(p)s(olynomials,)h(b)s(elonging)e(to)h(the)g(same)f(univ)-5 +b(ariate)41 b(p)s(olynomial)480 5029 y(ring,)30 b(for)h(equalit)m(y)-8 +b(.)0 5215 y Fn(cl_boolean)28 b(zerop)h(\(const)f(cl_UP&)h(x\))480 +5340 y Fp(Returns)g(true)i(if)f Fn(x)g Fp(is)g Fn(0)g(in)g(R)p +Fp(.)p eop +%%Page: 54 56 +54 55 bop 0 -116 a Fp(Chapter)30 b(9:)41 b(Univ)-5 b(ariate)32 +b(p)s(olynomials)2423 b(54)0 366 y Fn(sintL)29 b(degree)g(\(const)f +(cl_UP&)h(x\))480 491 y Fp(Returns)g(the)i(degree)g(of)g(the)f(p)s +(olynomial.)40 b(The)30 b(zero)h(p)s(olynomial)f(has)g(degree)h +Fn(-1)p Fp(.)0 665 y Fn(cl_ring_element)26 b(coeff)j(\(const)g(cl_UP&)f +(x,)i(uintL)f(index\))480 790 y Fp(Returns)g(the)i(co)s(e\016cien)m(t)h +(of)f Fn(X^index)d Fp(in)i(the)h(p)s(olynomial)f Fn(x)p +Fp(.)0 964 y Fn(cl_ring_element)c(x)k(\(const)f(cl_ring_element&)d(y\)) +480 1089 y Fp(Ev)-5 b(aluation:)40 b(If)25 b Fn(x)h Fp(is)h(a)f(p)s +(olynomial)g(and)g Fn(y)g Fp(b)s(elongs)g(to)h(the)f(base)h(ring,)g +(then)f(`)p Fn(x\(y\))p Fp(')g(returns)f(the)480 1213 +y(v)-5 b(alue)31 b(of)f(the)h(substitution)f(of)h Fn(y)f +Fp(in)m(to)h Fn(x)p Fp(.)0 1388 y Fn(cl_UP)e(deriv)g(\(const)g(cl_UP&)f +(x\))480 1512 y Fp(Returns)h(the)i(deriv)-5 b(ativ)m(e)32 +b(of)e(the)h(p)s(olynomial)f Fn(x)g Fp(with)g(resp)s(ect)g(to)h(the)g +(indeterminate)f Fn(X)p Fp(.)0 1811 y(The)g(follo)m(wing)i(output)e +(functions)g(are)g(de\014ned)g(\(see)h(also)g(the)g(c)m(hapter)g(on)f +(input/output\).)0 2110 y Fn(void)f(fprint)g(\(cl_ostream)e(stream,)i +(const)f(cl_UP&)h(x\))0 2234 y(cl_ostream)f(operator<<)f(\(cl_ostream)g +(stream,)i(const)g(cl_UP&)f(x\))480 2359 y Fp(Prin)m(ts)39 +b(the)g(univ)-5 b(ariate)40 b(p)s(olynomial)f Fn(x)f +Fp(on)h(the)h Fn(stream)p Fp(.)65 b(The)39 b(output)g(ma)m(y)f(dep)s +(end)g(on)h(the)480 2484 y(global)32 b(prin)m(ter)e(settings)h(in)f +(the)h(v)-5 b(ariable)31 b Fn(cl_default_print_flags)p +Fp(.)0 2932 y Fq(9.3)68 b(Sp)t(ecial)31 b(p)t(olynomials)0 +3206 y Fp(The)f(follo)m(wing)i(functions)e(return)f(sp)s(ecial)i(p)s +(olynomials.)0 3505 y Fn(cl_UP_I)d(cl_tschebychev)f(\(sintL)i(n\))480 +3629 y Fp(Returns)g(the)i(n-th)f(Tc)m(heb)m(yc)m(hev)h(p)s(olynomial)f +(\(n)g Fn(>)p Fp(=)g(0\).)0 3804 y Fn(cl_UP_I)e(cl_hermite)g(\(sintL)h +(n\))480 3928 y Fp(Returns)g(the)i(n-th)f(Hermite)g(p)s(olynomial)g +(\(n)g Fn(>)p Fp(=)g(0\).)0 4102 y Fn(cl_UP_RA)e(cl_legendre)f(\(sintL) +i(n\))480 4227 y Fp(Returns)g(the)i(n-th)f(Legendre)g(p)s(olynomial)g +(\(n)g Fn(>)p Fp(=)g(0\).)0 4401 y Fn(cl_UP_I)e(cl_laguerre)g(\(sintL)g +(n\))480 4526 y Fp(Returns)h(the)i(n-th)f(Laguerre)h(p)s(olynomial)e +(\(n)h Fn(>)p Fp(=)g(0\).)0 4825 y(Information)24 b(ho)m(w)h(to)h +(deriv)m(e)f(the)g(di\013eren)m(tial)i(equation)f(satis\014ed)f(b)m(y)f +(eac)m(h)j(of)e(these)g(p)s(olynomials)f(from)g(their)0 +4949 y(de\014nition)30 b(can)h(b)s(e)e(found)g(in)i(the)f +Fn(doc/polynomial/)c Fp(directory)-8 b(.)p eop +%%Page: 55 57 +55 56 bop 0 -116 a Fp(Chapter)30 b(10:)41 b(In)m(ternals)2950 +b(55)0 366 y Fm(10)80 b(In)l(ternals)0 944 y Fq(10.1)68 +b(Wh)l(y)31 b(C)p Fd(++)e Fq(?)0 1220 y Fp(Using)i(C)p +Fn(++)e Fp(as)i(an)f(implemen)m(tation)g(language)i(pro)m(vides)75 +1496 y Fo(\017)60 b Fp(E\016ciency:)41 b(It)31 b(compiles)f(to)h(mac)m +(hine)f(co)s(de.)75 1648 y Fo(\017)60 b Fp(P)m(ortabilit)m(y:)43 +b(It)29 b(runs)f(on)i(all)g(platforms)f(supp)s(orting)f(a)i(C)p +Fn(++)e Fp(compiler.)40 b(Because)31 b(of)f(the)g(a)m(v)-5 +b(ailabilit)m(y)33 b(of)180 1772 y(GNU)j(C)p Fn(++)p +Fp(,)f(this)g(includes)g(all)h(curren)m(tly)f(used)f(32-bit)i(and)f +(64-bit)h(platforms,)f(indep)s(enden)m(tly)g(of)g(the)180 +1897 y(qualit)m(y)d(of)e(the)h(v)m(endor's)f(C)p Fn(++)f +Fp(compiler.)75 2049 y Fo(\017)60 b Fp(T)m(yp)s(e)26 +b(safet)m(y:)40 b(The)25 b(C)p Fn(++)g Fp(compilers)h(kno)m(ws)g(ab)s +(out)g(the)g(n)m(um)m(b)s(er)e(t)m(yp)s(es)j(and)e(complains)h(if,)h +(for)f(example,)180 2173 y(y)m(ou)41 b(try)f(to)h(assign)g(a)f(\015oat) +h(to)g(an)g(in)m(teger)g(v)-5 b(ariable.)72 b(Ho)m(w)m(ev)m(er,)45 +b(a)c(dra)m(wbac)m(k)f(is)h(that)g(C)p Fn(++)e Fp(do)s(esn't)180 +2298 y(kno)m(w)i(ab)s(out)f(generic)h(t)m(yp)s(es,)j(hence)c(a)h +(restriction)h(lik)m(e)g(that)f Fn(operation+)27 b(\(const)i(cl_MI&,)f +(const)180 2422 y(cl_MI&\))i Fp(requires)i(that)h(b)s(oth)f(argumen)m +(ts)g(b)s(elong)g(to)h(the)g(same)e(mo)s(dular)g(ring)h(cannot)h(b)s(e) +e(expressed)180 2547 y(as)g(a)f(compile-time)h(information.)75 +2698 y Fo(\017)60 b Fp(Algebraic)34 b(syn)m(tax:)46 b(The)32 +b(elemen)m(tary)h(op)s(erations)g Fn(+)p Fp(,)g Fn(-)p +Fp(,)g Fn(*)p Fp(,)g Fn(=)p Fp(,)g Fn(==)p Fp(,)g(...)48 +b(can)33 b(b)s(e)f(used)f(in)i(in\014x)e(notation,)180 +2823 y(whic)m(h)f(is)h(more)e(con)m(v)m(enien)m(t)k(than)d(Lisp)f +(notation)j(`)p Fn(\(+)e(x)g(y\))p Fp(')g(or)g(C)g(notation)i(`)p +Fn(add\(x,y,&z\))p Fp('.)0 3126 y(With)c(these)g(language)h(features,)g +(there)f(is)f(no)h(need)f(for)g(t)m(w)m(o)i(separate)g(languages,)h +(one)d(for)h(the)g(implemen)m(ta-)0 3251 y(tion)i(of)h(the)f(library)f +(and)h(one)g(in)g(whic)m(h)g(the)g(library's)f(users)h(can)g(program.) +39 b(This)29 b(means)g(that)i(a)f(protot)m(yp)s(e)0 3375 +y(implemen)m(tation)36 b(of)g(an)f(algorithm)h(can)h(b)s(e)e(in)m +(tegrated)i(in)m(to)g(the)f(library)g(immediately)f(after)i(it)f(has)g +(b)s(een)0 3500 y(tested)g(and)f(debugged.)55 b(No)36 +b(need)g(to)g(rewrite)f(it)h(in)f(a)h(lo)m(w-lev)m(el)i(language)f +(after)f(ha)m(ving)g(protot)m(yp)s(ed)f(in)h(a)0 3624 +y(high-lev)m(el)c(language.)0 4093 y Fq(10.2)68 b(Memory)31 +b(e\016ciency)0 4369 y Fp(In)f(order)g(to)h(sa)m(v)m(e)h(memory)c(allo) +s(cations,)33 b(CLN)d(implemen)m(ts:)75 4645 y Fo(\017)60 +b Fp(Ob)5 b(ject)31 b(sharing:)40 b(An)30 b(op)s(eration)h(lik)m(e)g +Fn(x+0)f Fp(returns)f Fn(x)h Fp(without)g(cop)m(ying)i(it.)75 +4797 y Fo(\017)60 b Fp(Garbage)42 b(collection:)64 b(A)41 +b(reference)g(coun)m(ting)h(mec)m(hanism)d(mak)m(es)i(sure)f(that)h(an) +m(y)g(n)m(um)m(b)s(er)e(ob)5 b(ject's)180 4922 y(storage)32 +b(is)e(freed)g(immediately)g(when)f(the)i(last)g(reference)g(to)g(the)g +(ob)5 b(ject)31 b(is)f(gone.)75 5073 y Fo(\017)60 b Fp(Small)20 +b(in)m(tegers)j(are)e(represen)m(ted)g(as)g(immediate)f(v)-5 +b(alues)22 b(instead)f(of)g(p)s(oin)m(ters)g(to)h(heap)f(allo)s(cated)i +(storage.)180 5198 y(This)44 b(means)g(that)i(in)m(tegers)g +Fn(>)30 b(-2^29)p Fp(,)48 b Fn(<)30 b(2^29)44 b Fp(don't)h(consume)f +(heap)h(memory)-8 b(,)47 b(unless)d(they)h(w)m(ere)180 +5322 y(explicitly)32 b(allo)s(cated)g(on)f(the)f(heap.)p +eop +%%Page: 56 58 +56 57 bop 0 -116 a Fp(Chapter)30 b(10:)41 b(In)m(ternals)2950 +b(56)0 366 y Fq(10.3)68 b(Sp)t(eed)30 b(e\016ciency)0 +640 y Fp(Sp)s(eed)f(e\016ciency)j(is)e(obtained)h(b)m(y)f(the)h(com)m +(bination)f(of)h(the)f(follo)m(wing)i(tric)m(ks)f(and)f(algorithms:)75 +914 y Fo(\017)60 b Fp(Small)38 b(in)m(tegers,)43 b(b)s(eing)c(represen) +m(ted)g(as)g(immediate)f(v)-5 b(alues,)42 b(don't)d(require)g(memory)e +(access,)43 b(just)c(a)180 1039 y(couple)31 b(of)f(instructions)h(for)f +(eac)m(h)h(elemen)m(tary)g(op)s(eration.)75 1188 y Fo(\017)60 +b Fp(The)27 b(k)m(ernel)h(of)f(CLN)g(has)g(b)s(een)g(written)g(in)g +(assem)m(bly)g(language)h(for)f(some)g(CPUs)g(\()p Fn(i386)p +Fp(,)g Fn(m68k)p Fp(,)g Fn(sparc)p Fp(,)180 1313 y Fn(mips)p +Fp(,)i Fn(arm)p Fp(\).)75 1462 y Fo(\017)60 b Fp(On)30 +b(all)h(CPUs,)f(CLN)g(uses)g(the)g(sup)s(ere\016cien)m(t)h(lo)m(w-lev)m +(el)i(routines)d(from)f(GNU)i(GMP)g(v)m(ersion)g(2.)75 +1612 y Fo(\017)60 b Fp(F)-8 b(or)32 b(large)g(n)m(um)m(b)s(ers,)e(CLN)h +(uses,)g(instead)g(of)h(the)f(standard)g Fn(O\(N^2\))e +Fp(algorithm,)j(the)g(Karatsuba)f(m)m(ul-)180 1736 y(tiplication,)i +(whic)m(h)d(is)g(an)91 b Fl(O)s Fp(\()p Fl(N)1368 1703 +y Ff(1)p Fg(:)p Ff(6)1458 1736 y Fp(\))31 b(algorithm.)75 +1886 y Fo(\017)60 b Fp(F)-8 b(or)31 b(v)m(ery)f(large)h(n)m(um)m(b)s +(ers)c(\(more)i(than)h(12000)i(decimal)e(digits\),)h(CLN)e(uses)g(Sc)m +(h\177)-45 b(onhage-Strassen)31 b(m)m(ul-)180 2010 y(tiplication,)i +(whic)m(h)d(is)g(an)g(asymptotically)i(optimal)e(m)m(ultiplication)i +(algorithm.)75 2160 y Fo(\017)60 b Fp(These)27 b(fast)h(m)m +(ultiplication)h(algorithms)e(also)i(giv)m(e)g(impro)m(v)m(emen)m(ts)d +(in)i(the)f(sp)s(eed)g(of)h(division)f(and)g(radix)180 +2284 y(con)m(v)m(ersion.)0 2733 y Fq(10.4)68 b(Garbage)31 +b(collection)0 3007 y Fp(All)39 b(the)f(n)m(um)m(b)s(er)e(classes)j +(are)g(reference)g(coun)m(t)f(classes:)58 b(They)37 b(only)i(con)m +(tain)g(a)g(p)s(oin)m(ter)f(to)h(an)f(ob)5 b(ject)39 +b(in)0 3131 y(the)h(heap.)71 b(Up)s(on)39 b(construction,)44 +b(assignmen)m(t)c(and)f(destruction)i(of)f(n)m(um)m(b)s(er)e(ob)5 +b(jects,)44 b(only)c(the)h(ob)5 b(jects')0 3256 y(reference)31 +b(coun)m(t)g(are)g(manipulated.)0 3530 y(Memory)g(o)s(ccupied)g(b)m(y)g +(n)m(um)m(b)s(er)d(ob)5 b(jects)32 b(are)g(automatically)h(reclaimed)e +(as)g(so)s(on)g(as)h(their)f(reference)g(coun)m(t)0 3654 +y(drops)e(to)i(zero.)0 3928 y(F)-8 b(or)31 b(n)m(um)m(b)s(er)d(rings,)i +(another)g(strategy)h(is)f(implemen)m(ted:)39 b(There)30 +b(is)g(a)h(cac)m(he)g(of,)g(for)f(example,)g(the)g(mo)s(dular)0 +4053 y(in)m(teger)k(rings.)49 b(A)33 b(mo)s(dular)e(in)m(teger)j(ring)f +(is)g(destro)m(y)m(ed)h(only)f(if)g(its)g(reference)h(coun)m(t)f(dropp) +s(ed)e(to)j(zero)g(and)0 4177 y(the)40 b(cac)m(he)i(is)e(ab)s(out)g(to) +g(b)s(e)g(resized.)70 b(The)39 b(e\013ect)j(of)e(this)g(strategy)h(is)f +(that)h(recen)m(tly)g(used)e(rings)h(remain)0 4302 y(cac)m(hed,)32 +b(whereas)e(undue)f(memory)f(consumption)h(through)g(cac)m(hed)j(rings) +e(is)g(a)m(v)m(oided.)p eop +%%Page: 57 59 +57 58 bop 0 -116 a Fp(Chapter)30 b(11:)41 b(Using)31 +b(the)f(library)2621 b(57)0 366 y Fm(11)80 b(Using)30 +b(the)g(library)0 729 y Fp(F)-8 b(or)43 b(the)g(follo)m(wing)g +(discussion,)i(w)m(e)e(will)g(assume)e(that)i(y)m(ou)g(ha)m(v)m(e)g +(installed)g(the)g(CLN)f(source)g(in)g Fn($CLN_)0 854 +y(DIR)37 b Fp(and)g(built)h(it)g(in)g Fn($CLN_TARGETDIR)p +Fp(.)60 b(F)-8 b(or)38 b(example,)i(for)e(me)f(it's)h +Fn(CLN_DIR="$HOME/cln")33 b Fp(and)k Fn(CLN_)0 978 y +(TARGETDIR="$HOME/cln/lin)o(uxel)o(f")p Fp(.)g(Y)-8 b(ou)32 +b(migh)m(t)f(de\014ne)g(these)h(as)f(en)m(vironmen)m(t)g(v)-5 +b(ariables,)33 b(or)e(directly)0 1103 y(substitute)f(the)h(appropriate) +f(v)-5 b(alues.)0 1540 y Fq(11.1)68 b(Compiler)32 b(options)0 +1814 y Fp(Un)m(til)f(y)m(ou)g(ha)m(v)m(e)h(installed)f(CLN)f(in)g(a)h +(public)e(place,)j(the)e(follo)m(wing)i(options)f(are)g(needed:)0 +2088 y(When)f(y)m(ou)h(compile)f(CLN)g(application)i(co)s(de,)f(add)e +(the)i(\015ags)383 2341 y Fn(-I$CLN_DIR/include)43 b +(-I$CLN_TARGETDIR/include)0 2615 y Fp(to)25 b(the)f(C)p +Fn(++)f Fp(compiler's)h(command)e(line)j(\()p Fn(make)e +Fp(v)-5 b(ariable)25 b(CFLA)m(GS)f(or)g(CXXFLA)m(GS\).)i(When)e(y)m(ou) +g(link)g(CLN)0 2740 y(application)32 b(co)s(de)e(to)h(form)e(an)i +(executable,)h(add)e(the)g(\015ags)383 2993 y Fn +($CLN_TARGETDIR/src/libcln)o(.a)0 3267 y Fp(to)h(the)g(C/C)p +Fn(++)e Fp(compiler's)h(command)e(line)j(\()p Fn(make)f +Fp(v)-5 b(ariable)31 b(LIBS\).)0 3541 y(If)20 b(y)m(ou)g(did)g(a)h +Fn(make)29 b(install)p Fp(,)20 b(the)h(include)f(\014les)g(are)h +(installed)g(in)f(a)g(public)g(directory)h(\(normally)f +Fn(/usr/local/include)p Fp(\),)0 3665 y(hence)k(y)m(ou)f(don't)h(need)f +(sp)s(ecial)h(\015ags)g(for)f(compiling.)38 b(The)23 +b(library)g(has)h(b)s(een)e(installed)j(to)f(a)g(public)e(directory)0 +3790 y(as)33 b(w)m(ell)h(\(normally)f Fn(/usr/local/lib)p +Fp(\),)e(hence)i(when)f(linking)h(a)h(CLN)f(application)h(it)g(is)f +(su\016cien)m(t)h(to)f(giv)m(e)0 3915 y(the)e(\015ag)f +Fn(-lcln)p Fp(.)0 4352 y Fq(11.2)68 b(Include)30 b(\014les)0 +4626 y Fp(Here)h(is)f(a)h(summary)c(of)k(the)f(include)h(\014les)f(and) +g(their)g(con)m(ten)m(ts.)0 4922 y Fn()480 +5047 y Fp(General)h(de\014nitions,)f(reference)h(coun)m(ting,)h +(garbage)f(collection.)0 5215 y Fn()480 +5340 y Fp(The)f(class)h(cl)p 950 5340 28 4 v 33 w(n)m(um)m(b)s(er.)p +eop +%%Page: 58 60 +58 59 bop 0 -116 a Fp(Chapter)30 b(11:)41 b(Using)31 +b(the)f(library)2621 b(58)0 366 y Fn()480 +491 y Fp(F)-8 b(unctions)31 b(for)f(class)h(cl)p 1318 +491 28 4 v 34 w(N,)f(the)h(complex)f(n)m(um)m(b)s(ers.)0 +670 y Fn()480 794 y Fp(F)-8 b(unctions)31 +b(for)f(class)h(cl)p 1318 794 V 34 w(R,)f(the)h(real)g(n)m(um)m(b)s +(ers.)0 973 y Fn()480 1097 y Fp(F)-8 b(unctions)31 +b(for)f(class)h(cl)p 1318 1097 V 34 w(F,)f(the)h(\015oats.)0 +1276 y Fn()480 1400 y Fp(F)-8 b(unctions)31 +b(for)f(class)h(cl)p 1318 1400 V 34 w(SF,)f(the)h(short-\015oats.)0 +1579 y Fn()480 1703 y Fp(F)-8 b(unctions)31 +b(for)f(class)h(cl)p 1318 1703 V 34 w(FF,)g(the)f(single-\015oats.)0 +1882 y Fn()480 2006 y Fp(F)-8 b(unctions)31 +b(for)f(class)h(cl)p 1318 2006 V 34 w(DF,)g(the)f(double-\015oats.)0 +2185 y Fn()480 2309 y Fp(F)-8 b(unctions)31 +b(for)f(class)h(cl)p 1318 2309 V 34 w(LF,)f(the)h(long-\015oats.)0 +2488 y Fn()480 2612 y Fp(F)-8 b(unctions)31 +b(for)f(class)h(cl)p 1318 2612 V 34 w(RA,)f(the)h(rational)g(n)m(um)m +(b)s(ers.)0 2791 y Fn()480 2916 y Fp(F)-8 +b(unctions)31 b(for)f(class)h(cl)p 1318 2916 V 34 w(I,)f(the)h(in)m +(tegers.)0 3094 y Fn()480 3219 y Fp(Input/Output.)0 +3397 y Fn()480 3522 y Fp(Input/Output)d(for)j(class)g +(cl)p 1491 3522 V 33 w(N,)g(the)f(complex)g(n)m(um)m(b)s(ers.)0 +3700 y Fn()480 3825 y Fp(Input/Output)e(for)j(class)g(cl) +p 1491 3825 V 33 w(R,)g(the)f(real)h(n)m(um)m(b)s(ers.)0 +4003 y Fn()480 4128 y Fp(Input/Output)d(for)j(class)g +(cl)p 1491 4128 V 33 w(F,)g(the)g(\015oats.)0 4306 y +Fn()480 4431 y Fp(Input/Output)d(for)j(class)g(cl)p +1491 4431 V 33 w(SF,)f(the)h(short-\015oats.)0 4609 y +Fn()480 4734 y Fp(Input/Output)d(for)j(class)g(cl)p +1491 4734 V 33 w(FF,)g(the)g(single-\015oats.)0 4912 +y Fn()480 5037 y Fp(Input/Output)d(for)j(class)g(cl)p +1491 5037 V 33 w(DF,)g(the)g(double-\015oats.)0 5215 +y Fn()480 5340 y Fp(Input/Output)d(for)j(class)g(cl)p +1491 5340 V 33 w(LF,)g(the)f(long-\015oats.)p eop +%%Page: 59 61 +59 60 bop 0 -116 a Fp(Chapter)30 b(11:)41 b(Using)31 +b(the)f(library)2621 b(59)0 366 y Fn()480 +491 y Fp(Input/Output)28 b(for)j(class)g(cl)p 1491 491 +28 4 v 33 w(RA,)g(the)f(rational)i(n)m(um)m(b)s(ers.)0 +670 y Fn()480 794 y Fp(Input/Output)c(for)j(class)g +(cl)p 1491 794 V 33 w(I,)f(the)h(in)m(tegers.)0 973 y +Fn()480 1097 y Fp(Flags)h(for)e(customizing)g(input)g(op)s +(erations.)0 1276 y Fn()480 1400 y Fp(Flags)i(for)e +(customizing)g(output)g(op)s(erations.)0 1579 y Fn()480 +1703 y(cl_malloc_hook)p Fp(,)d Fn(cl_free_hook)p Fp(.)0 +1882 y Fn()480 2006 y(cl_abort)p Fp(.)0 2185 +y Fn()480 2309 y Fp(Conditions/exceptions.)0 +2488 y Fn()480 2612 y Fp(Strings.)0 2791 +y Fn()480 2916 y Fp(Sym)m(b)s(ols.)0 3094 +y Fn()480 3219 y Fp(Prop)s(ert)m(y)j(lists.)0 +3397 y Fn()480 3522 y Fp(General)h(rings.)0 +3700 y Fn()480 3825 y Fp(The)f(n)m(ull)g(ring.)0 +4003 y Fn()480 4128 y Fp(The)g(ring)g(of)h(complex)f +(n)m(um)m(b)s(ers.)0 4306 y Fn()480 4431 +y Fp(The)g(ring)g(of)h(real)g(n)m(um)m(b)s(ers.)0 4609 +y Fn()480 4734 y Fp(The)f(ring)g(of)h(rational)g(n) +m(um)m(b)s(ers.)0 4912 y Fn()480 5037 +y Fp(The)f(ring)g(of)h(in)m(tegers.)0 5215 y Fn()480 +5340 y Fp(Num)m(b)s(er)d(threory)i(functions.)p eop +%%Page: 60 62 +60 61 bop 0 -116 a Fp(Chapter)30 b(11:)41 b(Using)31 +b(the)f(library)2621 b(60)0 366 y Fn()480 +491 y Fp(Mo)s(dular)30 b(in)m(tegers.)0 659 y Fn()96 +b Fp(V)-8 b(ectors.)0 827 y Fn()480 952 y Fp(General)31 +b(v)m(ectors.)0 1120 y Fn()480 1244 y +Fp(General)g(v)m(ectors)h(o)m(v)m(er)g(cl)p 1393 1244 +28 4 v 33 w(n)m(um)m(b)s(er.)0 1412 y Fn()480 +1537 y Fp(General)f(v)m(ectors)h(o)m(v)m(er)g(cl)p 1393 +1537 V 33 w(N.)0 1705 y Fn()480 1829 y +Fp(General)f(v)m(ectors)h(o)m(v)m(er)g(cl)p 1393 1829 +V 33 w(R.)0 1997 y Fn()480 2122 y Fp(General)f(v)m +(ectors)h(o)m(v)m(er)g(cl)p 1393 2122 V 33 w(RA.)0 2290 +y Fn()480 2414 y Fp(General)f(v)m(ectors)h(o)m(v)m(er) +g(cl)p 1393 2414 V 33 w(I.)0 2582 y Fn()480 +2707 y Fp(General)f(v)m(ectors)h(of)f(mo)s(dular)d(in)m(tegers.)0 +2875 y Fn()480 3000 y Fp(Simple)h(v)m(ectors.)0 +3168 y Fn()480 3292 y Fp(Simple)g(v)m(ectors)j(o)m(v)m +(er)g(cl)p 1352 3292 V 33 w(n)m(um)m(b)s(er.)0 3460 y +Fn()480 3585 y Fp(Simple)d(v)m(ectors)j(o)m(v)m(er)g +(cl)p 1352 3585 V 33 w(N.)0 3753 y Fn()480 +3877 y Fp(Simple)d(v)m(ectors)j(o)m(v)m(er)g(cl)p 1352 +3877 V 33 w(R.)0 4045 y Fn()480 4170 +y Fp(Simple)d(v)m(ectors)j(o)m(v)m(er)g(cl)p 1352 4170 +V 33 w(RA.)0 4338 y Fn()480 4462 y Fp(Simple)d(v)m +(ectors)j(o)m(v)m(er)g(cl)p 1352 4462 V 33 w(I.)0 4630 +y Fn()480 4755 y Fp(Simple)d(v)m(ectors)j(of)e +(general)i(ring)e(elemen)m(ts.)0 4923 y Fn()480 +5047 y Fp(Univ)-5 b(ariate)32 b(p)s(olynomials.)0 5215 +y Fn()480 5340 y Fp(Univ)-5 b(ariate)32 +b(p)s(olynomials)d(o)m(v)m(er)j(the)f(in)m(tegers.)p +eop +%%Page: 61 63 +61 62 bop 0 -116 a Fp(Chapter)30 b(11:)41 b(Using)31 +b(the)f(library)2621 b(61)0 366 y Fn()480 +491 y Fp(Univ)-5 b(ariate)32 b(p)s(olynomials)d(o)m(v)m(er)j(the)f +(rational)g(n)m(um)m(b)s(ers.)0 671 y Fn()480 +795 y Fp(Univ)-5 b(ariate)32 b(p)s(olynomials)d(o)m(v)m(er)j(the)f +(real)g(n)m(um)m(b)s(ers.)0 975 y Fn()480 +1099 y Fp(Univ)-5 b(ariate)32 b(p)s(olynomials)d(o)m(v)m(er)j(the)f +(complex)f(n)m(um)m(b)s(ers.)0 1279 y Fn()480 +1403 y Fp(Univ)-5 b(ariate)32 b(p)s(olynomials)d(o)m(v)m(er)j(mo)s +(dular)c(in)m(teger)k(rings.)0 1583 y Fn()480 +1707 y Fp(Timing)d(facilities.)0 1887 y Fn()144 +b Fp(Includes)30 b(all)h(of)f(the)h(ab)s(o)m(v)m(e.)0 +2359 y Fq(11.3)68 b(An)30 b(Example)0 2635 y Fp(A)g(function)h(whic)m +(h)f(computes)f(the)i(n)m(th)f(Fib)s(onacci)h(n)m(um)m(b)s(er)d(can)j +(b)s(e)f(written)g(as)h(follo)m(ws.)240 2891 y Fn(#include)46 +b()240 2995 y(#include)g()240 +3203 y(//)h(Returns)f(F_n,)h(computed)e(as)i(the)g(nearest)f(integer)g +(to)240 3306 y(//)h(\(\(1+sqrt\(5\)\)/2\)^n/sqrt\(5\))o(.)42 +b(Assume)k(n>=0.)240 3410 y(const)g(cl_I)h(fibonacci)e(\(int)i(n\))240 +3514 y({)622 3618 y(//)g(Need)g(a)g(precision)e(of)j +(\(\(1+sqrt\(5\)\)/2\)^-n.)622 3722 y(cl_float_format_t)43 +b(prec)k(=)g(cl_float_format\(\(int\)\(0.)o(2089)o(8764)o(1*n)o(+5\)\)) +o(;)622 3825 y(cl_R)f(sqrt5)h(=)g(sqrt\(cl_float\(5,prec\)\);)622 +3929 y(cl_R)f(phi)h(=)h(\(1+sqrt5\)/2;)622 4033 y(return)e(round1\()g +(expt\(phi,n\)/sqrt5)d(\);)240 4137 y(})0 4413 y Fp(Let's)31 +b(explain)g(what)f(is)g(going)i(on)e(in)g(detail.)0 4690 +y(The)j(include)h(\014le)g Fn()c Fp(is)k(necessary)g(b)s +(ecause)g(the)g(t)m(yp)s(e)g Fn(cl_I)e Fp(is)i(used)f(in)h(the)g +(function,)h(and)0 4814 y(the)30 b(include)g(\014le)g +Fn()d Fp(is)j(needed)g(for)g(the)g(t)m(yp)s(e)h +Fn(cl_R)e Fp(and)g(the)h(\015oating)h(p)s(oin)m(t)f(n)m(um)m(b)s(er)e +(functions.)0 4939 y(The)i(order)g(of)g(the)h(include)f(\014les)g(do)s +(es)g(not)h(matter.)0 5215 y(Then)h(comes)i(the)f(function)h +(declaration.)51 b(The)33 b(argumen)m(t)g(is)g(an)h Fn(int)p +Fp(,)f(the)h(result)f(an)h(in)m(teger.)51 b(The)33 b(return)0 +5340 y(t)m(yp)s(e)26 b(is)g(de\014ned)f(as)h(`)p Fn(const)j(cl_I)p +Fp(',)d(not)h(simply)d(`)p Fn(cl_I)p Fp(',)i(b)s(ecause)g(that)h(allo)m +(ws)g(the)f(compiler)g(to)h(detect)g(t)m(yp)s(os)p eop +%%Page: 62 64 +62 63 bop 0 -116 a Fp(Chapter)30 b(11:)41 b(Using)31 +b(the)f(library)2621 b(62)0 366 y(lik)m(e)40 b(`)p Fn(fibonacci\(n\))27 +b(=)j(100)p Fp('.)64 b(It)39 b(w)m(ould)f(b)s(e)g(p)s(ossible)g(to)h +(declare)g(the)g(return)e(t)m(yp)s(e)i(as)g Fn(const)29 +b(cl_R)37 b Fp(\(real)0 491 y(n)m(um)m(b)s(er\))28 b(or)h(ev)m(en)i +Fn(const)e(cl_N)f Fp(\(complex)i(n)m(um)m(b)s(er\).)39 +b(W)-8 b(e)31 b(use)e(the)h(most)f(sp)s(ecialized)i(p)s(ossible)e +(return)g(t)m(yp)s(e)0 616 y(b)s(ecause)34 b(functions)f(whic)m(h)g +(call)i(`)p Fn(fibonacci)p Fp(')d(will)i(b)s(e)f(able)h(to)g(pro\014t)f +(from)f(the)i(compiler's)f(t)m(yp)s(e)h(analysis:)0 740 +y(Adding)j(t)m(w)m(o)h(in)m(tegers)h(is)e(sligh)m(tly)h(more)f +(e\016cien)m(t)h(than)f(adding)g(the)h(same)e(ob)5 b(jects)38 +b(declared)g(as)f(complex)0 865 y(n)m(um)m(b)s(ers,)30 +b(b)s(ecause)i(it)g(needs)g(less)g(t)m(yp)s(e)g(dispatc)m(h.)46 +b(Also,)33 b(when)e(linking)h(to)h(CLN)e(as)h(a)h(non-shared)e(library) +-8 b(,)0 989 y(this)30 b(minimizes)f(the)i(size)g(of)f(the)h(resulting) +f(executable)i(program.)0 1269 y(The)37 b(result)g(will)g(b)s(e)g +(computed)f(as)h(expt\(phi,n\)/sqrt\(5\),)k(rounded)35 +b(to)j(the)g(nearest)f(in)m(teger.)63 b(In)36 b(order)h(to)0 +1394 y(get)h(a)f(correct)h(result,)h(the)e(absolute)h(error)e(should)g +(b)s(e)g(less)h(than)g(1/2,)j(i.e.)61 b(the)37 b(relativ)m(e)i(error)e +(should)f(b)s(e)0 1518 y(less)28 b(than)g +(sqrt\(5\)/\(2*expt\(phi,n\)\).)43 b(T)-8 b(o)29 b(this)f(end,)g(the)h +(\014rst)e(line)i(computes)e(a)i(\015oating)g(p)s(oin)m(t)f(precision)g +(for)0 1643 y(sqrt\(5\))j(and)f(phi.)0 1923 y(Then)37 +b(sqrt\(5\))i(is)e(computed)g(b)m(y)h(\014rst)f(con)m(v)m(erting)j(the) +e(in)m(teger)h(5)f(to)h(a)f(\015oating)h(p)s(oin)m(t)e(n)m(um)m(b)s(er) +f(and)h(than)0 2047 y(taking)j(the)f(square)f(ro)s(ot.)67 +b(The)38 b(con)m(v)m(erse,)43 b(\014rst)38 b(taking)i(the)f(square)f +(ro)s(ot)h(of)g(5,)j(and)c(then)h(con)m(v)m(erting)h(to)0 +2172 y(the)c(desired)g(precision,)h(w)m(ould)f(not)g(w)m(ork)g(in)g +(CLN:)g(The)f(square)h(ro)s(ot)g(w)m(ould)g(b)s(e)f(computed)g(to)h(a)h +(default)0 2296 y(precision)e(\(normally)g(single-\015oat)h +(precision\),)h(and)e(the)g(follo)m(wing)h(con)m(v)m(ersion)g(could)f +(not)h(help)e(ab)s(out)h(the)0 2421 y(lac)m(king)i(accuracy)-8 +b(.)58 b(This)35 b(is)h(b)s(ecause)f(CLN)g(is)h(not)g(a)g(sym)m(b)s +(olic)f(computer)f(algebra)j(system)d(and)h(do)s(es)h(not)0 +2545 y(represen)m(t)30 b(sqrt\(5\))i(in)e(a)h(non-n)m(umeric)d(w)m(a)m +(y)-8 b(.)0 2825 y(The)38 b(t)m(yp)s(e)h Fn(cl_R)f Fp(for)h(sqrt5)g +(and,)i(in)d(the)h(follo)m(wing)i(line,)g(phi)d(is)h(the)g(only)g(p)s +(ossible)g(c)m(hoice.)68 b(Y)-8 b(ou)39 b(cannot)0 2950 +y(write)28 b Fn(cl_F)e Fp(b)s(ecause)i(the)f(C)p Fn(++)g +Fp(compiler)g(can)h(only)f(infer)g(that)h Fn(cl_float\(5,prec\))23 +b Fp(is)28 b(a)g(real)g(n)m(um)m(b)s(er.)37 b(Y)-8 b(ou)0 +3074 y(cannot)31 b(write)g Fn(cl_N)e Fp(b)s(ecause)h(a)h(`)p +Fn(round1)p Fp(')e(do)s(es)h(not)h(exist)g(for)f(general)h(complex)f(n) +m(um)m(b)s(ers.)0 3354 y(When)44 b(the)h(function)f(returns,)j(all)e +(the)g(lo)s(cal)g(v)-5 b(ariables)45 b(in)f(the)h(function)f(are)h +(automatically)h(reclaimed)0 3479 y(\(garbage)32 b(collected\).)43 +b(Only)30 b(the)h(result)f(surviv)m(es)g(and)g(gets)h(passed)f(to)h +(the)g(caller.)0 3982 y Fq(11.4)68 b(Debugging)31 b(supp)t(ort)0 +4262 y Fp(When)f(debugging)g(a)h(CLN)f(application)i(with)e(GNU)h +Fn(gdb)p Fp(,)f(t)m(w)m(o)h(facilities)i(are)e(a)m(v)-5 +b(ailable)33 b(from)28 b(the)j(library:)75 4542 y Fo(\017)60 +b Fp(The)32 b(library)h(do)s(es)f(t)m(yp)s(e)h(c)m(hec)m(ks,)j(range)d +(c)m(hec)m(ks,)i(consistency)f(c)m(hec)m(ks)g(at)g(man)m(y)e(places.)49 +b(When)33 b(one)g(of)180 4666 y(these)40 b(fails,)i(the)e(function)f +Fn(cl_abort\(\))d Fp(is)j(called.)69 b(Its)39 b(default)h(implemen)m +(tation)f(is)g(to)h(p)s(erform)d(an)180 4791 y Fn(exit\(1\))p +Fp(,)29 b(so)i(y)m(ou)f(w)m(on't)i(ha)m(v)m(e)f(a)g(core)h(dump.)38 +b(But)31 b(for)f(debugging,)h(it)g(is)f(b)s(est)g(to)i(set)f(a)g +(breakp)s(oin)m(t)f(at)180 4915 y(this)g(function:)420 +5050 y Fn(\(gdb\))46 b(break)h(cl_abort)180 5205 y Fp(When)30 +b(this)g(breakp)s(oin)m(t)h(is)f(hit,)h(lo)s(ok)g(at)g(the)f(stac)m +(k's)i(bac)m(ktrace:)420 5340 y Fn(\(gdb\))46 b(where)p +eop +%%Page: 63 65 +63 64 bop 0 -116 a Fp(Chapter)30 b(11:)41 b(Using)31 +b(the)f(library)2621 b(63)75 366 y Fo(\017)60 b Fp(The)27 +b(debugger's)g(normal)g Fn(print)f Fp(command)f(do)s(esn't)j(kno)m(w)f +(ab)s(out)h(CLN's)f(t)m(yp)s(es)g(and)g(therefore)h(prin)m(ts)180 +491 y(mostly)43 b(useless)h(hexadecimal)g(addresses.)80 +b(CLN)43 b(o\013ers)h(a)g(function)f Fn(cl_print)p Fp(,)i(callable)h +(from)c(the)180 616 y(debugger,)37 b(for)e(prin)m(ting)g(n)m(um)m(b)s +(er)e(ob)5 b(jects.)57 b(In)35 b(order)g(to)h(get)g(this)g(function,)g +(y)m(ou)g(ha)m(v)m(e)h(to)f(de\014ne)f(the)180 740 y(macro)24 +b(`)p Fn(CL_DEBUG)p Fp(')f(and)h(then)h(include)f(all)h(the)g(header)g +(\014les)f(for)h(whic)m(h)f(y)m(ou)h(w)m(an)m(t)h Fn(cl_print)c +Fp(debugging)180 865 y(supp)s(ort.)39 b(F)-8 b(or)31 +b(example:)420 993 y Fn(#define)46 b(CL_DEBUG)420 1097 +y(#include)g()180 1247 y Fp(No)m(w,)26 b(if)f(y)m(ou)f(ha) +m(v)m(e)i(in)e(y)m(our)g(program)f(a)i(v)-5 b(ariable)25 +b Fn(cl_string)i(s)p Fp(,)f(and)e(insp)s(ect)g(it)g(under)f +Fn(gdb)p Fp(,)i(the)f(output)180 1371 y(ma)m(y)30 b(lo)s(ok)h(lik)m(e)h +(this:)420 1500 y Fn(\(gdb\))46 b(print)h(s)420 1604 +y($7)g(=)h({)43 b(=)48 b({)f(=)h({pointer)d(=)j +(0x8055b60,)d(heappointer)f(=)k(0x8055b60,)515 1707 y(word)f(=)h +(134568800}},)c(})420 1811 y(\(gdb\))i(call)h(cl_print\(s\))420 +1915 y(\(cl_string\))e("")420 2019 y($8)i(=)h(134568800)180 +2168 y Fp(Note)34 b(that)f(the)g(output)f(of)h Fn(cl_print)d +Fp(go)s(es)k(to)f(the)g(program's)e(error)h(output,)h(not)g(to)h(gdb's) +e(standard)180 2293 y(output.)180 2442 y(Note,)38 b(ho)m(w)m(ev)m(er,)g +(that)d(the)g(ab)s(o)m(v)m(e)i(facilit)m(y)g(do)s(es)d(not)i(w)m(ork)f +(with)f(all)i(CLN)f(t)m(yp)s(es,)h(only)g(with)e(n)m(um)m(b)s(er)180 +2567 y(ob)5 b(jects)42 b(and)e(similar.)72 b(Therefore)41 +b(CLN)g(o\013ers)g(a)h(mem)m(b)s(er)c(function)j Fn(debug_print\(\))c +Fp(on)k(all)h(CLN)180 2691 y(t)m(yp)s(es.)63 b(The)37 +b(same)g(macro)h(`)p Fn(CL_DEBUG)p Fp(')e(is)h(needed)h(for)f(this)h +(mem)m(b)s(er)d(function)j(to)g(b)s(e)f(implemen)m(ted.)180 +2816 y(Under)30 b Fn(gdb)p Fp(,)f(y)m(ou)i(call)h(it)f(lik)m(e)g(this:) +420 2944 y Fn(\(gdb\))46 b(print)h(s)420 3048 y($7)g(=)h +({)43 b(=)48 b({)f(=)h({pointer)d(=)j(0x8055b60,)d +(heappointer)f(=)k(0x8055b60,)515 3152 y(word)f(=)h(134568800}},)c(}) +420 3256 y(\(gdb\))i(call)h(s.debug_print\(\))420 3359 +y(\(cl_string\))e("")420 3463 y(\(gdb\))h(define)g(cprint)420 +3567 y(>call)g(\($1\).debug_print\(\))420 3671 y(>end)420 +3775 y(\(gdb\))g(cprint)g(s)420 3878 y(\(cl_string\))f("")180 +4028 y Fp(Unfortunately)-8 b(,)31 b(this)g(feature)f(do)s(es)g(not)h +(seem)f(to)h(w)m(ork)f(under)f(all)i(circumstances.)p +eop +%%Page: 64 66 +64 65 bop 0 -116 a Fp(Chapter)30 b(12:)41 b(Customizing)2803 +b(64)0 366 y Fm(12)80 b(Customizing)0 1146 y Fq(12.1)68 +b(Error)31 b(handling)0 1438 y Fp(When)36 b(a)g(fatal)h(error)f(o)s +(ccurs,)i(an)d(error)h(message)g(is)g(output)g(to)h(the)f(standard)f +(error)h(output)f(stream,)j(and)0 1562 y(the)k(function)f +Fn(cl_abort)e Fp(is)j(called.)76 b(The)41 b(default)h(v)m(ersion)g(of)f +(this)h(function)f(\(pro)m(vided)h(in)f(the)h(library\))0 +1687 y(terminates)32 b(the)g(application.)46 b(T)-8 b(o)32 +b(catc)m(h)h(suc)m(h)f(a)g(fatal)h(error,)f(y)m(ou)g(need)f(to)i +(de\014ne)e(the)h(function)f Fn(cl_abort)0 1811 y Fp(y)m(ourself,)g +(with)f(the)h(protot)m(yp)s(e)240 2083 y Fn(#include)46 +b()240 2186 y(void)h(cl_abort)e(\(void\);)0 +2478 y Fp(This)30 b(function)g(m)m(ust)f(not)i(return)e(con)m(trol)j +(to)f(its)f(caller.)0 3087 y Fq(12.2)68 b(Floating-p)t(oin)l(t)32 +b(under\015o)l(w)0 3379 y Fp(Floating)c(p)s(oin)m(t)d(under\015o)m(w)g +(denotes)h(the)g(situation)g(when)f(a)h(\015oating-p)s(oin)m(t)h(n)m +(um)m(b)s(er)c(is)j(to)g(b)s(e)f(created)i(whic)m(h)0 +3503 y(is)32 b(so)g(close)h(to)f Fn(0)g Fp(that)g(its)g(exp)s(onen)m(t) +g(is)g(to)s(o)h(lo)m(w)f(to)h(b)s(e)e(represen)m(ted)h(in)m(ternally)-8 +b(.)46 b(By)32 b(default,)h(this)e(causes)i(a)0 3628 +y(fatal)f(error.)40 b(If)30 b(y)m(ou)h(set)f(the)h(global)h(v)-5 +b(ariable)240 3899 y Fn(cl_boolean)45 b(cl_inhibit_floating_poin)o +(t_un)o(derf)o(low)0 4190 y Fp(to)36 b Fn(cl_true)p Fp(,)f(the)h(error) +f(will)h(b)s(e)f(inhibited,)h(and)f(a)h(\015oating-p)s(oin)m(t)h(zero)f +(will)g(b)s(e)f(generated)h(instead.)56 b(The)0 4315 +y(default)31 b(v)-5 b(alue)30 b(of)h Fn(cl_inhibit_floating_poin)o +(t_un)o(der)o(flow)24 b Fp(is)30 b Fn(cl_false)p Fp(.)0 +4924 y Fq(12.3)68 b(Customizing)32 b(I/O)0 5215 y Fp(The)27 +b(output)g(of)h(the)f(function)h Fn(fprint)d Fp(ma)m(y)i(b)s(e)g +(customized)h(b)m(y)f(c)m(hanging)h(the)g(v)-5 b(alue)28 +b(of)g(the)f(global)i(v)-5 b(ariable)0 5340 y Fn +(cl_default_print_flags)p Fp(.)p eop +%%Page: 65 67 +65 66 bop 0 -116 a Fp(Chapter)30 b(12:)41 b(Customizing)2803 +b(65)0 366 y Fq(12.4)68 b(Customizing)32 b(the)e(memory)h(allo)t(cator) +0 640 y Fp(Ev)m(ery)j(memory)d(allo)s(cation)36 b(of)e(CLN)f(is)h(done) +f(through)g(the)g(function)h(p)s(oin)m(ter)f Fn(cl_malloc_hook)p +Fp(.)47 b(F)-8 b(reeing)0 765 y(of)31 b(this)g(memory)e(is)i(done)f +(through)g(the)h(function)g(p)s(oin)m(ter)g Fn(cl_free_hook)p +Fp(.)39 b(The)30 b(default)h(v)m(ersions)g(of)g(these)0 +890 y(functions,)e(pro)m(vided)f(in)g(the)h(library)-8 +b(,)29 b(call)h Fn(malloc)d Fp(and)h Fn(free)f Fp(and)h(c)m(hec)m(k)i +(the)f Fn(malloc)e Fp(result)h(against)i Fn(NULL)p Fp(.)0 +1014 y(If)25 b(y)m(ou)h(w)m(an)m(t)h(to)f(pro)m(vide)g(another)g +(memory)d(allo)s(cator,)29 b(y)m(ou)d(need)f(to)i(de\014ne)e(the)h(v)-5 +b(ariables)26 b Fn(cl_malloc_hook)0 1139 y Fp(and)k Fn(cl_free_hook)d +Fp(y)m(ourself,)k(lik)m(e)g(this:)240 1392 y Fn(#include)46 +b()240 1496 y(void*)g(\(*cl_malloc_hook\))d(\(size_t)j +(size\))h(=)g Fl(:)15 b(:)g(:)q Fn(;)240 1599 y(void)47 +b(\(*cl_free_hook\))c(\(void*)j(ptr\))286 b(=)47 b Fl(:)15 +b(:)g(:)q Fn(;)0 1873 y Fp(The)30 b Fn(cl_malloc_hook)c +Fp(function)k(m)m(ust)g(not)g(return)g(a)g Fn(NULL)g +Fp(p)s(oin)m(ter.)0 2147 y(It)24 b(is)g(not)g(p)s(ossible)f(to)i(c)m +(hange)g(the)f(memory)e(allo)s(cator)k(at)f(run)m(time,)f(b)s(ecause)g +(it)g(is)g(already)g(called)i(at)e(program)0 2272 y(startup)30 +b(b)m(y)g(the)h(constructors)f(of)h(some)f(global)h(v)-5 +b(ariables.)p eop +%%Page: 66 68 +66 67 bop 0 -116 a Fp(Index)3586 b(66)0 366 y Fm(Index)0 +831 y Fc(\(Index)24 b(is)i(nonexisten)n(t\))p eop +%%Page: -1 69 +-1 68 bop 3875 -116 a Fp(i)0 366 y Fm(T)-13 b(able)31 +b(of)f(Con)l(ten)l(ts)0 715 y Fq(1)135 b(In)l(tro)t(duction)40 +b Fb(.)20 b(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f +(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.) +f(.)85 b Fq(1)0 995 y(2)135 b(Installation)14 b Fb(.)22 +b(.)d(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f +(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.) +f(.)59 b Fq(3)299 1151 y Fp(2.1)92 b(Prerequisites)15 +b Fa(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)44 +b Fp(3)598 1276 y(2.1.1)93 b(C)p Fn(++)29 b Fp(compiler)14 +b Fa(.)g(.)h(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)43 b Fp(3)598 1400 y(2.1.2)93 +b(Mak)m(e)31 b(utilit)m(y)14 b Fa(.)i(.)f(.)h(.)f(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)43 +b Fp(3)598 1525 y(2.1.3)93 b(Sed)29 b(utilit)m(y)h Fa(.)15 +b(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)58 b Fp(3)299 1649 y(2.2)92 +b(Building)30 b(the)h(library)25 b Fa(.)15 b(.)g(.)g(.)g(.)g(.)g(.)g(.) +h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.) +f(.)55 b Fp(4)299 1774 y(2.3)92 b(Installing)31 b(the)g(library)8 +b Fa(.)15 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)38 b Fp(5)299 +1898 y(2.4)92 b(Cleaning)31 b(up)8 b Fa(.)14 b(.)h(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)38 b Fp(6)0 2147 +y Fq(3)135 b(Ordinary)45 b(n)l(um)l(b)t(er)f(t)l(yp)t(es)31 +b Fb(.)19 b(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h +(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)75 b Fq(7)299 2303 +y Fp(3.1)92 b(Exact)31 b(n)m(um)m(b)s(ers)14 b Fa(.)f(.)i(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.) +f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)44 b Fp(8)299 2428 +y(3.2)92 b(Floating-p)s(oin)m(t)33 b(n)m(um)m(b)s(ers)17 +b Fa(.)12 b(.)j(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)47 b Fp(8)299 2552 y(3.3)92 +b(Complex)29 b(n)m(um)m(b)s(ers)17 b Fa(.)c(.)i(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)47 b Fp(10)299 2677 y(3.4)92 b(Con)m(v)m(ersions)10 +b Fa(.)16 b(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)40 +b Fp(10)0 2926 y Fq(4)135 b(F)-11 b(unctions)44 b(on)h(n)l(um)l(b)t +(ers)38 b Fb(.)20 b(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f +(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)83 b Fq(12)299 +3081 y Fp(4.1)92 b(Constructing)30 b(n)m(um)m(b)s(ers)21 +b Fa(.)13 b(.)i(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)50 b Fp(12)598 3206 y(4.1.1)93 +b(Constructing)30 b(in)m(tegers)24 b Fa(.)15 b(.)g(.)h(.)f(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)53 b Fp(12)598 3330 y(4.1.2)93 +b(Constructing)30 b(rational)h(n)m(um)m(b)s(ers)11 b +Fa(.)i(.)i(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h +(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)40 b Fp(12)598 3455 y(4.1.3)93 +b(Constructing)30 b(\015oating-p)s(oin)m(t)h(n)m(um)m(b)s(ers)25 +b Fa(.)15 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)56 b Fp(12)598 3579 y(4.1.4)93 b(Constructing)30 +b(complex)g(n)m(um)m(b)s(ers)21 b Fa(.)15 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)53 +b Fp(13)299 3704 y(4.2)92 b(Elemen)m(tary)30 b(functions)17 +b Fa(.)e(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)46 b Fp(13)299 3829 y(4.3)92 +b(Elemen)m(tary)30 b(rational)i(functions)20 b Fa(.)14 +b(.)h(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)49 +b Fp(15)299 3953 y(4.4)92 b(Elemen)m(tary)30 b(complex)g(functions)11 +b Fa(.)k(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)40 +b Fp(15)299 4078 y(4.5)92 b(Comparisons)13 b Fa(.)g(.)i(.)g(.)g(.)g(.)g +(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h +(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)42 b Fp(16)299 4202 +y(4.6)92 b(Rounding)29 b(functions)9 b Fa(.)15 b(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)h(.)38 b Fp(17)299 4327 y(4.7)92 b(Ro)s(ots)24 b +Fa(.)15 b(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)53 b Fp(21)299 4451 y(4.8)92 b(T)-8 +b(ranscenden)m(tal)31 b(functions)8 b Fa(.)15 b(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)38 +b Fp(22)598 4576 y(4.8.1)93 b(Exp)s(onen)m(tial)30 b(and)g(logarithmic) +h(functions)9 b Fa(.)15 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)38 b Fp(22)598 4700 y(4.8.2)93 +b(T)-8 b(rigonometric)30 b(functions)17 b Fa(.)e(.)h(.)f(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)47 b Fp(23)598 4825 y(4.8.3)93 +b(Hyp)s(erb)s(olic)29 b(functions)15 b Fa(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)44 b Fp(24)598 4949 +y(4.8.4)93 b(Euler)29 b(gamma)12 b Fa(.)i(.)h(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)41 +b Fp(25)598 5074 y(4.8.5)93 b(Riemann)29 b(zeta)e Fa(.)15 +b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)55 b Fp(26)299 5198 y(4.9)92 b(F)-8 b(unctions)31 +b(on)f(in)m(tegers)17 b Fa(.)f(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)46 +b Fp(26)598 5323 y(4.9.1)93 b(Logical)32 b(functions)25 +b Fa(.)15 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)55 b Fp(26)p eop +%%Page: -2 70 +-2 69 bop 3849 -116 a Fp(ii)598 83 y(4.9.2)93 b(Num)m(b)s(er)28 +b(theoretic)k(functions)11 b Fa(.)k(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.) +40 b Fp(29)598 208 y(4.9.3)93 b(Com)m(binatorial)30 b(functions)12 +b Fa(.)j(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)42 +b Fp(30)299 332 y(4.10)92 b(F)-8 b(unctions)31 b(on)g(\015oating-p)s +(oin)m(t)g(n)m(um)m(b)s(ers)19 b Fa(.)12 b(.)j(.)h(.)f(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)48 b Fp(30)299 457 y(4.11)92 b(Con)m(v)m(ersion)31 +b(functions)25 b Fa(.)15 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)54 b Fp(32)598 +581 y(4.11.1)93 b(Con)m(v)m(ersion)31 b(to)g(\015oating-p)s(oin)m(t)h +(n)m(um)m(b)s(ers)9 b Fa(.)j(.)j(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)38 b Fp(32)598 706 y(4.11.2)93 +b(Con)m(v)m(ersion)31 b(to)g(rational)h(n)m(um)m(b)s(ers)15 +b Fa(.)d(.)j(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)44 b Fp(33)299 830 y(4.12)92 +b(Random)29 b(n)m(um)m(b)s(er)f(generators)16 b Fa(.)g(.)f(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)45 b +Fp(34)299 955 y(4.13)92 b(Obfuscating)30 b(op)s(erators)21 +b Fa(.)16 b(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)50 b Fp(35)0 1204 y Fq(5)135 +b(Input/Output)28 b Fb(.)18 b(.)i(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h +(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.) +g(.)h(.)f(.)h(.)72 b Fq(37)299 1359 y Fp(5.1)92 b(In)m(ternal)31 +b(and)e(prin)m(ted)h(represen)m(tation)20 b Fa(.)d(.)e(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)h(.)49 b Fp(37)299 1484 y(5.2)92 b(Input)29 +b(functions)e Fa(.)15 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)57 +b Fp(38)299 1609 y(5.3)92 b(Output)29 b(functions)12 +b Fa(.)j(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)42 b Fp(40)0 +1858 y Fq(6)135 b(Rings)23 b Fb(.)d(.)g(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f +(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.) +h(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)68 +b Fq(43)0 2138 y(7)135 b(Mo)t(dular)44 b(in)l(tegers)28 +b Fb(.)22 b(.)d(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f +(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)73 +b Fq(45)299 2293 y Fp(7.1)92 b(Mo)s(dular)30 b(in)m(teger)i(rings)10 +b Fa(.)k(.)h(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)39 b Fp(45)299 2418 y(7.2)92 +b(F)-8 b(unctions)31 b(on)f(mo)s(dular)e(in)m(tegers)j +Fa(.)15 b(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)59 +b Fp(46)0 2667 y Fq(8)135 b(Sym)l(b)t(olic)45 b(data)g(t)l(yp)t(es)30 +b Fb(.)20 b(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f +(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)74 b Fq(48)299 +2823 y Fp(8.1)92 b(Strings)22 b Fa(.)14 b(.)h(.)g(.)g(.)g(.)g(.)h(.)f +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)51 b Fp(48)299 +2947 y(8.2)92 b(Sym)m(b)s(ols)17 b Fa(.)c(.)i(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h +(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)46 b Fp(49)0 +3196 y Fq(9)135 b(Univ)-7 b(ariate)46 b(p)t(olynomials)41 +b Fb(.)19 b(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h +(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)84 b Fq(50)299 3352 y +Fp(9.1)92 b(Univ)-5 b(ariate)32 b(p)s(olynomial)d(rings)16 +b Fa(.)f(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)46 b Fp(50)299 3477 y(9.2)92 b(F)-8 b(unctions)31 +b(on)f(univ)-5 b(ariate)31 b(p)s(olynomials)20 b Fa(.)14 +b(.)h(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)49 b Fp(52)299 +3601 y(9.3)92 b(Sp)s(ecial)31 b(p)s(olynomials)25 b Fa(.)15 +b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)56 b Fp(54)0 3850 y Fq(10)135 +b(In)l(ternals)21 b Fb(.)f(.)g(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f +(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.) +h(.)f(.)h(.)f(.)h(.)f(.)g(.)66 b Fq(55)299 4006 y Fp(10.1)92 +b(Wh)m(y)31 b(C)p Fn(++)f Fp(?)19 b Fa(.)14 b(.)h(.)g(.)g(.)h(.)f(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)48 b Fp(55)299 4130 y(10.2)92 +b(Memory)30 b(e\016ciency)15 b Fa(.)h(.)f(.)h(.)f(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)44 +b Fp(55)299 4255 y(10.3)92 b(Sp)s(eed)30 b(e\016ciency)19 +b Fa(.)d(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)48 b Fp(56)299 +4379 y(10.4)92 b(Garbage)32 b(collection)e Fa(.)15 b(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)57 b Fp(56)0 4628 y Fq(11)135 b(Using)46 b(the)f(library)26 +b Fb(.)20 b(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f +(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)71 +b Fq(57)299 4784 y Fp(11.1)92 b(Compiler)30 b(options)12 +b Fa(.)j(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)41 b Fp(57)299 +4909 y(11.2)92 b(Include)30 b(\014les)10 b Fa(.)15 b(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)39 b Fp(57)299 5033 +y(11.3)92 b(An)30 b(Example)19 b Fa(.)c(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)49 b Fp(61)299 5158 y(11.4)92 b(Debugging)32 +b(supp)s(ort)17 b Fa(.)c(.)i(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)46 +b Fp(62)p eop +%%Page: -3 71 +-3 70 bop 3824 -116 a Fp(iii)0 83 y Fq(12)135 b(Customizing)40 +b Fb(.)20 b(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f +(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)84 +b Fq(64)299 239 y Fp(12.1)92 b(Error)30 b(handling)17 +b Fa(.)d(.)h(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)46 +b Fp(64)299 363 y(12.2)92 b(Floating-p)s(oin)m(t)33 b(under\015o)m(w)11 +b Fa(.)j(.)h(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)40 b Fp(64)299 488 y(12.3)92 b(Customizing)30 +b(I/O)16 b Fa(.)f(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)45 +b Fp(64)299 612 y(12.4)92 b(Customizing)30 b(the)h(memory)d(allo)s +(cator)k Fa(.)15 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)59 +b Fp(65)0 861 y Fq(Index)31 b Fb(.)19 b(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h +(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.) +g(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)76 +b Fq(66)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/cln.tex b/doc/cln.tex new file mode 100644 index 0000000..b83dfa8 --- /dev/null +++ b/doc/cln.tex @@ -0,0 +1,3366 @@ +\input texinfo @c -*-texinfo-*- +@c %**start of header +@setfilename cln.info +@settitle CLN, a Class Library for Numbers +@c @setchapternewpage off +@c For `info' only. +@paragraphindent 0 +@c For TeX only. +@iftex +@c I hate putting "@noindent" in front of every paragraph. +@parindent=0pt +@end iftex +@c %**end of header + + +@c My own index. +@defindex my +@c Don't need the other types of indices. +@synindex cp my +@synindex fn my +@synindex vr my +@synindex ky my +@synindex pg my +@synindex tp my + + +@c For `info' only. +@ifinfo +This file documents @sc{cln}, a Class Library for Numbers. + +Published by Bruno Haible, @code{} and +Richard Kreckel, @code{}. + +Copyright (C) Bruno Haible 1995, 1996, 1997, 1998, 1999, 2000. + +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 author. +@end ifinfo + + +@c For TeX only. +@c prevent ugly black rectangles on overfull hbox lines: +@finalout +@titlepage +@title CLN, a Class Library for Numbers + +@author by Bruno Haible +@page +@vskip 0pt plus 1filll +Copyright @copyright{} Bruno Haible 1995, 1996, 1997, 1998, 1999, 2000. + +@sp 2 +Published by Bruno Haible, @code{} and +Richard Kreckel, @code{}. + +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 author. + +@end titlepage +@page + + +@node Top, Introduction, (dir), (dir) + +@c @menu +@c * Introduction:: Introduction +@c @end menu + + +@node Introduction, Top, Top, Top +@comment node-name, next, previous, up +@chapter Introduction + +@noindent +CLN is a library for computations with all kinds of numbers. +It has a rich set of number classes: + +@itemize @bullet +@item +Integers (with unlimited precision), + +@item +Rational numbers, + +@item +Floating-point numbers: + +@itemize @minus +@item +Short float, +@item +Single float, +@item +Double float, +@item +Long float (with unlimited precision), +@end itemize + +@item +Complex numbers, + +@item +Modular integers (integers modulo a fixed integer), + +@item +Univariate polynomials. +@end itemize + +@noindent +The subtypes of the complex numbers among these are exactly the +types of numbers known to the Common Lisp language. Therefore +@code{CLN} can be used for Common Lisp implementations, giving +@samp{CLN} another meaning: it becomes an abbreviation of +``Common Lisp Numbers''. + +@noindent +The CLN package implements + +@itemize @bullet +@item +Elementary functions (@code{+}, @code{-}, @code{*}, @code{/}, @code{sqrt}, +comparisons, @dots{}), + +@item +Logical functions (logical @code{and}, @code{or}, @code{not}, @dots{}), + +@item +Transcendental functions (exponential, logarithmic, trigonometric, hyperbolic +functions and their inverse functions). +@end itemize + +@noindent +CLN is a C++ library. Using C++ as an implementation language provides + +@itemize @bullet +@item +efficiency: it compiles to machine code, +@item +type safety: the C++ compiler knows about the number types and complains +if, for example, you try to assign a float to an integer variable. +@item +algebraic syntax: You can use the @code{+}, @code{-}, @code{*}, @code{=}, +@code{==}, @dots{} operators as in C or C++. +@end itemize + +@noindent +CLN is memory efficient: + +@itemize @bullet +@item +Small integers and short floats are immediate, not heap allocated. +@item +Heap-allocated memory is reclaimed through an automatic, non-interruptive +garbage collection. +@end itemize + +@noindent +CLN is speed efficient: + +@itemize @bullet +@item +The kernel of CLN has been written in assembly language for some CPUs +(@code{i386}, @code{m68k}, @code{sparc}, @code{mips}, @code{arm}). +@item +On all CPUs, CLN uses the superefficient low-level routines from GNU +GMP version 2. +@item +It uses Karatsuba multiplication, which is significantly faster +for large numbers than the standard multiplication algorithm. +@item +For very large numbers (more than 12000 decimal digits), it uses +@iftex +Sch{@"o}nhage-Strassen +@end iftex +@ifinfo +Schönhage-Strassen +@end ifinfo +multiplication, which is an asymptotically +optimal multiplication algorithm, for multiplication, division and +radix conversion. +@end itemize + +@noindent +CLN aims at being easily integrated into larger software packages: + +@itemize @bullet +@item +The garbage collection imposes no burden on the main application. +@item +The library provides hooks for memory allocation and exceptions. +@end itemize + + +@chapter Installation + +This section describes how to install the CLN package on your system. + + +@section Prerequisites + +@subsection C++ compiler + +To build CLN, you need a C++ compiler. +Actually, you need GNU @code{g++ 2.7.0} or newer. +On HPPA, you need GNU @code{g++ 2.8.0} or newer. +I recommend GNU @code{egcs 1.1} or newer. + +The following C++ features are used: +classes, member functions, +overloading of functions and operators, +constructors and destructors, inline, const, +multiple inheritance, templates. + +The following C++ features are not used: +@code{new}, @code{delete}, virtual inheritance, +exceptions. + +CLN relies on semi-automatic ordering of initializations +of static and global variables, a feature which I could +implement for GNU g++ only. + +@ignore +@comment cl_modules.h requires g++ +Therefore nearly any C++ compiler will do. + +The following C++ compilers are known to compile CLN: +@itemize @minus +@item +GNU @code{g++ 2.7.0}, @code{g++ 2.7.2} +@item +SGI @code{CC 4} +@end itemize + +The following C++ compilers are known to be unusable for CLN: +@itemize @minus +@item +On SunOS 4, @code{CC 2.1}, because it doesn't grok @code{//} comments +in lines containing @code{#if} or @code{#elif} preprocessor commands. +@item +On AIX 3.2.5, @code{xlC}, because it doesn't grok the template syntax +in @code{cl_SV.h} and @code{cl_GV.h}, because it forces most class types +to have default constructors, and because it probably miscompiles the +integer multiplication routines. +@item +On AIX 4.1.4.0, @code{xlC}, because when optimizing, it sometimes converts +@code{short}s to @code{int}s by zero-extend. +@item +GNU @code{g++ 2.5.8} +@item +On HPPA, GNU @code{g++ 2.7.x}, because the semi-automatic ordering of +initializations will not work. +@end itemize +@end ignore + +@subsection Make utility + +To build CLN, you also need to have GNU @code{make} installed. + +@subsection Sed utility + +To build CLN on HP-UX, you also need to have GNU @code{sed} installed. +This is because the libtool script, which creates the CLN library, relies +on @code{sed}, and the vendor's @code{sed} utility on these systems is too +limited. + + +@section Building the library + +As with any autoconfiguring GNU software, installation is as easy as this: + +@example +$ ./configure +$ make +$ make check +@end example + +If on your system, @samp{make} is not GNU @code{make}, you have to use +@samp{gmake} instead of @samp{make} above. + +The @code{configure} command checks out some features of your system and +C++ compiler and builds the @code{Makefile}s. The @code{make} command +builds the library. This step may take 4 hours on an average workstation. +The @code{make check} runs some test to check that no important subroutine +has been miscompiled. + +The @code{configure} command accepts options. To get a summary of them, try + +@example +$ ./configure --help +@end example + +Some of the options are explained in detail in the @samp{INSTALL.generic} file. + +You can specify the C compiler, the C++ compiler and their options through +the following environment variables when running @code{configure}: + +@table @code +@item CC +Specifies the C compiler. + +@item CFLAGS +Flags to be given to the C compiler when compiling programs (not when linking). + +@item CXX +Specifies the C++ compiler. + +@item CXXFLAGS +Flags to be given to the C++ compiler when compiling programs (not when linking). +@end table + +Examples: + +@example +$ CC="gcc" CFLAGS="-O" CXX="g++" CXXFLAGS="-O" ./configure +$ CC="gcc -V 2.7.2" CFLAGS="-O -g" \ + CXX="g++ -V 2.7.2" CXXFLAGS="-O -g" ./configure +$ CC="gcc -V 2.8.1" CFLAGS="-O -fno-exceptions" \ + CXX="g++ -V 2.8.1" CXXFLAGS="-O -fno-exceptions" ./configure +$ CC="gcc -V egcs-2.91.60" CFLAGS="-O2 -fno-exceptions" \ + CXX="g++ -V egcs-2.91.60" CFLAGS="-O2 -fno-exceptions" ./configure +@end example +@ignore +@comment cl_modules.h requires g++ +You should not mix GNU and non-GNU compilers. So, if @code{CXX} is a non-GNU +compiler, @code{CC} should be set to a non-GNU compiler as well. Examples: + +@example +$ CC="cc" CFLAGS="-O" CXX="CC" CXXFLAGS="-O" ./configure +$ CC="gcc -V 2.7.0" CFLAGS="-g" CXX="g++ -V 2.7.0" CXXFLAGS="-g" ./configure +@end example + +On SGI Irix 5, if you wish not to use @code{g++}: + +@example +$ CC="cc" CFLAGS="-O" CXX="CC" CXXFLAGS="-O -Olimit 16000" ./configure +@end example + +On SGI Irix 6, if you wish not to use @code{g++}: + +@example +$ CC="cc -32" CFLAGS="-O" CXX="CC -32" CXXFLAGS="-O -Olimit 34000" \ + ./configure --without-gmp +$ CC="cc -n32" CFLAGS="-O" CXX="CC -n32" CXXFLAGS="-O \ + -OPT:const_copy_limit=32400 -OPT:global_limit=32400 -OPT:fprop_limit=4000" \ + ./configure --without-gmp +@end example +@end ignore + +Note that for these environment variables to take effect, you have to set +them (assuming a Bourne-compatible shell) on the same line as the +@code{configure} command. If you made the settings in earlier shell +commands, you have to @code{export} the environment variables before +calling @code{configure}. In a @code{csh} shell, you have to use the +@samp{setenv} command for setting each of the environment variables. + +On Linux, @code{g++} needs 15 MB to compile the tests. So you should better +have 17 MB swap space and 1 MB room in $TMPDIR. + +If you use @code{g++} version 2.7.x, don't add @samp{-O2} to the CXXFLAGS, +because @samp{g++ -O} generates better code for CLN than @samp{g++ -O2}. + +If you use @code{g++} version 2.8.x or egcs-2.91.x (a.k.a. egcs-1.1) or +gcc-2.95.x, I recommend adding @samp{-fno-exceptions} to the CXXFLAGS. +This will likely generate better code. + +If you use @code{g++} version egcs-2.91.x (egcs-1.1) or gcc-2.95.x on Sparc, +add either @samp{-O} or @samp{-O2 -fno-schedule-insns} to the CXXFLAGS. +With full @samp{-O2}, @code{g++} miscompiles the division routines. Also, for +--enable-shared to work, you need egcs-1.1.2 or newer. + +On MIPS (SGI Irix 6), pass option @code{--without-gmp} to configure. gmp does +not work when compiled in @samp{n32} binary format on Irix. + +By default, only a static library is built. You can build CLN as a shared +library too, by calling @code{configure} with the option @samp{--enable-shared}. +To get it built as a shared library only, call @code{configure} with the options +@samp{--enable-shared --disable-static}. + +If you use @code{g++} version egcs-2.91.x (egcs-1.1) on Sparc, you cannot +use @samp{--enable-shared} because @code{g++} would miscompile parts of the +library. + + +@section Installing the library + +As with any autoconfiguring GNU software, installation is as easy as this: + +@example +$ make install +@end example + +The @samp{make install} command installs the library and the include files +into public places (@file{/usr/local/lib/} and @file{/usr/local/include/}, +if you haven't specified a @code{--prefix} option to @code{configure}). +This step may require superuser privileges. + +If you have already built the library and wish to install it, but didn't +specify @code{--prefix=@dots{}} at configure time, just re-run +@code{configure}, giving it the same options as the first time, plus +the @code{--prefix=@dots{}} option. + + +@section Cleaning up + +You can remove system-dependent files generated by @code{make} through + +@example +$ make clean +@end example + +You can remove all files generated by @code{make}, thus reverting to a +virgin distribution of CLN, through + +@example +$ make distclean +@end example + + +@chapter Ordinary number types + +CLN implements the following class hierarchy: + +@example + Number + cl_number + + | + | + Real or complex number + cl_N + + | + | + Real number + cl_R + + | + +-------------------+-------------------+ + | | +Rational number Floating-point number + cl_RA cl_F + + | | + | +-------------+-------------+-------------+ + Integer | | | | + cl_I Short-Float Single-Float Double-Float Long-Float + cl_SF cl_FF cl_DF cl_LF + +@end example + +The base class @code{cl_number} is an abstract base class. +It is not useful to declare a variable of this type except if you want +to completely disable compile-time type checking and use run-time type +checking instead. + +The class @code{cl_N} comprises real and complex numbers. There is +no special class for complex numbers since complex numbers with imaginary +part @code{0} are automatically converted to real numbers. + +The class @code{cl_R} comprises real numbers of different kinds. It is an +abstract class. + +The class @code{cl_RA} comprises exact real numbers: rational numbers, including +integers. There is no special class for non-integral rational numbers +since rational numbers with denominator @code{1} are automatically converted +to integers. + +The class @code{cl_F} implements floating-point approximations to real numbers. +It is an abstract class. + + +@section Exact numbers + +Some numbers are represented as exact numbers: there is no loss of information +when such a number is converted from its mathematical value to its internal +representation. On exact numbers, the elementary operations (@code{+}, +@code{-}, @code{*}, @code{/}, comparisons, @dots{}) compute the completely +correct result. + +In CLN, the exact numbers are: + +@itemize @bullet +@item +rational numbers (including integers), +@item +complex numbers whose real and imaginary parts are both rational numbers. +@end itemize + +Rational numbers are always normalized to the form +@code{@var{numerator}/@var{denominator}} where the numerator and denominator +are coprime integers and the denominator is positive. If the resulting +denominator is @code{1}, the rational number is converted to an integer. + +Small integers (typically in the range @code{-2^30}@dots{}@code{2^30-1}, +for 32-bit machines) are especially efficient, because they consume no heap +allocation. Otherwise the distinction between these immediate integers +(called ``fixnums'') and heap allocated integers (called ``bignums'') +is completely transparent. + + +@section Floating-point numbers + +Not all real numbers can be represented exactly. (There is an easy mathematical +proof for this: Only a countable set of numbers can be stored exactly in +a computer, even if one assumes that it has unlimited storage. But there +are uncountably many real numbers.) So some approximation is needed. +CLN implements ordinary floating-point numbers, with mantissa and exponent. + +The elementary operations (@code{+}, @code{-}, @code{*}, @code{/}, @dots{}) +only return approximate results. For example, the value of the expression +@code{(cl_F) 0.3 + (cl_F) 0.4} prints as @samp{0.70000005}, not as +@samp{0.7}. Rounding errors like this one are inevitable when computing +with floating-point numbers. + +Nevertheless, CLN rounds the floating-point results of the operations @code{+}, +@code{-}, @code{*}, @code{/}, @code{sqrt} according to the ``round-to-even'' +rule: It first computes the exact mathematical result and then returns the +floating-point number which is nearest to this. If two floating-point numbers +are equally distant from the ideal result, the one with a @code{0} in its least +significant mantissa bit is chosen. + +Similarly, testing floating point numbers for equality @samp{x == y} +is gambling with random errors. Better check for @samp{abs(x - y) < epsilon} +for some well-chosen @code{epsilon}. + +Floating point numbers come in four flavors: + +@itemize @bullet +@item +Short floats, type @code{cl_SF}. +They have 1 sign bit, 8 exponent bits (including the exponent's sign), +and 17 mantissa bits (including the ``hidden'' bit). +They don't consume heap allocation. + +@item +Single floats, type @code{cl_FF}. +They have 1 sign bit, 8 exponent bits (including the exponent's sign), +and 24 mantissa bits (including the ``hidden'' bit). +In CLN, they are represented as IEEE single-precision floating point numbers. +This corresponds closely to the C/C++ type @samp{float}. + +@item +Double floats, type @code{cl_DF}. +They have 1 sign bit, 11 exponent bits (including the exponent's sign), +and 53 mantissa bits (including the ``hidden'' bit). +In CLN, they are represented as IEEE double-precision floating point numbers. +This corresponds closely to the C/C++ type @samp{double}. + +@item +Long floats, type @code{cl_LF}. +They have 1 sign bit, 32 exponent bits (including the exponent's sign), +and n mantissa bits (including the ``hidden'' bit), where n >= 64. +The precision of a long float is unlimited, but once created, a long float +has a fixed precision. (No ``lazy recomputation''.) +@end itemize + +Of course, computations with long floats are more expensive than those +with smaller floating-point formats. + +CLN does not implement features like NaNs, denormalized numbers and +gradual underflow. If the exponent range of some floating-point type +is too limited for your application, choose another floating-point type +with larger exponent range. + +As a user of CLN, you can forget about the differences between the +four floating-point types and just declare all your floating-point +variables as being of type @code{cl_F}. This has the advantage that +when you change the precision of some computation (say, from @code{cl_DF} +to @code{cl_LF}), you don't have to change the code, only the precision +of the initial values. Also, many transcendental functions have been +declared as returning a @code{cl_F} when the argument is a @code{cl_F}, +but such declarations are missing for the types @code{cl_SF}, @code{cl_FF}, +@code{cl_DF}, @code{cl_LF}. (Such declarations would be wrong if +the floating point contagion rule happened to change in the future.) + + +@section Complex numbers + +Complex numbers, as implemented by the class @code{cl_N}, have a real +part and an imaginary part, both real numbers. A complex number whose +imaginary part is the exact number @code{0} is automatically converted +to a real number. + +Complex numbers can arise from real numbers alone, for example +through application of @code{sqrt} or transcendental functions. + + +@section Conversions + +Conversions from any class to any its superclasses (``base classes'' in +C++ terminology) is done automatically. + +Conversions from the C built-in types @samp{long} and @samp{unsigned long} +are provided for the classes @code{cl_I}, @code{cl_RA}, @code{cl_R}, +@code{cl_N} and @code{cl_number}. + +Conversions from the C built-in types @samp{int} and @samp{unsigned int} +are provided for the classes @code{cl_I}, @code{cl_RA}, @code{cl_R}, +@code{cl_N} and @code{cl_number}. However, these conversions emphasize +efficiency. Their range is therefore limited: + +@itemize @minus +@item +The conversion from @samp{int} works only if the argument is < 2^29 and > -2^29. +@item +The conversion from @samp{unsigned int} works only if the argument is < 2^29. +@end itemize + +In a declaration like @samp{cl_I x = 10;} the C++ compiler is able to +do the conversion of @code{10} from @samp{int} to @samp{cl_I} at compile time +already. On the other hand, code like @samp{cl_I x = 1000000000;} is +in error. +So, if you want to be sure that an @samp{int} whose magnitude is not guaranteed +to be < 2^29 is correctly converted to a @samp{cl_I}, first convert it to a +@samp{long}. Similarly, if a large @samp{unsigned int} is to be converted to a +@samp{cl_I}, first convert it to an @samp{unsigned long}. + +Conversions from the C built-in type @samp{float} are provided for the classes +@code{cl_FF}, @code{cl_F}, @code{cl_R}, @code{cl_N} and @code{cl_number}. + +Conversions from the C built-in type @samp{double} are provided for the classes +@code{cl_DF}, @code{cl_F}, @code{cl_R}, @code{cl_N} and @code{cl_number}. + +Conversions from @samp{const char *} are provided for the classes +@code{cl_I}, @code{cl_RA}, +@code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF}, @code{cl_F}, +@code{cl_R}, @code{cl_N}. +The easiest way to specify a value which is outside of the range of the +C++ built-in types is therefore to specify it as a string, like this: +@example + cl_I order_of_rubiks_cube_group = "43252003274489856000"; +@end example +Note that this conversion is done at runtime, not at compile-time. + +Conversions from @code{cl_I} to the C built-in types @samp{int}, +@samp{unsigned int}, @samp{long}, @samp{unsigned long} are provided through +the functions + +@table @code +@item int cl_I_to_int (const cl_I& x) +@itemx unsigned int cl_I_to_uint (const cl_I& x) +@itemx long cl_I_to_long (const cl_I& x) +@itemx unsigned long cl_I_to_ulong (const cl_I& x) +Returns @code{x} as element of the C type @var{ctype}. If @code{x} is not +representable in the range of @var{ctype}, a runtime error occurs. +@end table + +Conversions from the classes @code{cl_I}, @code{cl_RA}, +@code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF}, @code{cl_F} and +@code{cl_R} +to the C built-in types @samp{float} and @samp{double} are provided through +the functions + +@table @code +@item float cl_float_approx (const @var{type}& x) +@itemx double cl_double_approx (const @var{type}& x) +Returns an approximation of @code{x} of C type @var{ctype}. +If @code{abs(x)} is too close to 0 (underflow), 0 is returned. +If @code{abs(x)} is too large (overflow), an IEEE infinity is returned. +@end table + +Conversions from any class to any of its subclasses (``derived classes'' in +C++ terminology) are not provided. Instead, you can assert and check +that a value belongs to a certain subclass, and return it as element of that +class, using the @samp{As} and @samp{The} macros. +@code{As(@var{type})(@var{value})} checks that @var{value} belongs to +@var{type} and returns it as such. +@code{The(@var{type})(@var{value})} assumes that @var{value} belongs to +@var{type} and returns it as such. It is your responsibility to ensure +that this assumption is valid. +Example: + +@example +@group + cl_I x = @dots{}; + if (!(x >= 0)) abort(); + cl_I ten_x = The(cl_I)(expt(10,x)); // If x >= 0, 10^x is an integer. + // In general, it would be a rational number. +@end group +@end example + + +@chapter Functions on numbers + +Each of the number classes declares its mathematical operations in the +corresponding include file. For example, if your code operates with +objects of type @code{cl_I}, it should @code{#include }. + + +@section Constructing numbers + +Here is how to create number objects ``from nothing''. + + +@subsection Constructing integers + +@code{cl_I} objects are most easily constructed from C integers and from +strings. See @ref{Conversions}. + + +@subsection Constructing rational numbers + +@code{cl_RA} objects can be constructed from strings. The syntax +for rational numbers is described in @ref{Internal and printed representation}. +Another standard way to produce a rational number is through application +of @samp{operator /} or @samp{recip} on integers. + + +@subsection Constructing floating-point numbers + +@code{cl_F} objects with low precision are most easily constructed from +C @samp{float} and @samp{double}. See @ref{Conversions}. + +To construct a @code{cl_F} with high precision, you can use the conversion +from @samp{const char *}, but you have to specify the desired precision +within the string. (See @ref{Internal and printed representation}.) +Example: +@example + cl_F e = "0.271828182845904523536028747135266249775724709369996e+1_40"; +@end example +will set @samp{e} to the given value, with a precision of 40 decimal digits. + +The programmatic way to construct a @code{cl_F} with high precision is +through the @code{cl_float} conversion function, see +@ref{Conversion to floating-point numbers}. For example, to compute +@code{e} to 40 decimal places, first construct 1.0 to 40 decimal places +and then apply the exponential function: +@example + cl_float_format_t precision = cl_float_format(40); + cl_F e = exp(cl_float(1,precision)); +@end example + + +@subsection Constructing complex numbers + +Non-real @code{cl_N} objects are normally constructed through the function +@example + cl_N complex (const cl_R& realpart, const cl_R& imagpart) +@end example +See @ref{Elementary complex functions}. + + +@section Elementary functions + +Each of the classes @code{cl_N}, @code{cl_R}, @code{cl_RA}, @code{cl_I}, +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines the following operations: + +@table @code +@item @var{type} operator + (const @var{type}&, const @var{type}&) +Addition. + +@item @var{type} operator - (const @var{type}&, const @var{type}&) +Subtraction. + +@item @var{type} operator - (const @var{type}&) +Returns the negative of the argument. + +@item @var{type} plus1 (const @var{type}& x) +Returns @code{x + 1}. + +@item @var{type} minus1 (const @var{type}& x) +Returns @code{x - 1}. + +@item @var{type} operator * (const @var{type}&, const @var{type}&) +Multiplication. + +@item @var{type} square (const @var{type}& x) +Returns @code{x * x}. +@end table + +Each of the classes @code{cl_N}, @code{cl_R}, @code{cl_RA}, +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines the following operations: + +@table @code +@item @var{type} operator / (const @var{type}&, const @var{type}&) +Division. + +@item @var{type} recip (const @var{type}&) +Returns the reciprocal of the argument. +@end table + +The class @code{cl_I} doesn't define a @samp{/} operation because +in the C/C++ language this operator, applied to integral types, +denotes the @samp{floor} or @samp{truncate} operation (which one of these, +is implementation dependent). (@xref{Rounding functions}) +Instead, @code{cl_I} defines an ``exact quotient'' function: + +@table @code +@item cl_I exquo (const cl_I& x, const cl_I& y) +Checks that @code{y} divides @code{x}, and returns the quotient @code{x}/@code{y}. +@end table + +The following exponentiation functions are defined: + +@table @code +@item cl_I expt_pos (const cl_I& x, const cl_I& y) +@itemx cl_RA expt_pos (const cl_RA& x, const cl_I& y) +@code{y} must be > 0. Returns @code{x^y}. + +@item cl_RA expt (const cl_RA& x, const cl_I& y) +@itemx cl_R expt (const cl_R& x, const cl_I& y) +@itemx cl_N expt (const cl_N& x, const cl_I& y) +Returns @code{x^y}. +@end table + +Each of the classes @code{cl_R}, @code{cl_RA}, @code{cl_I}, +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines the following operation: + +@table @code +@item @var{type} abs (const @var{type}& x) +Returns the absolute value of @code{x}. +This is @code{x} if @code{x >= 0}, and @code{-x} if @code{x <= 0}. +@end table + +The class @code{cl_N} implements this as follows: + +@table @code +@item cl_R abs (const cl_N x) +Returns the absolute value of @code{x}. +@end table + +Each of the classes @code{cl_N}, @code{cl_R}, @code{cl_RA}, @code{cl_I}, +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines the following operation: + +@table @code +@item @var{type} signum (const @var{type}& x) +Returns the sign of @code{x}, in the same number format as @code{x}. +This is defined as @code{x / abs(x)} if @code{x} is non-zero, and +@code{x} if @code{x} is zero. If @code{x} is real, the value is either +0 or 1 or -1. +@end table + + +@section Elementary rational functions + +Each of the classes @code{cl_RA}, @code{cl_I} defines the following operations: + +@table @code +@item cl_I numerator (const @var{type}& x) +Returns the numerator of @code{x}. + +@item cl_I denominator (const @var{type}& x) +Returns the denominator of @code{x}. +@end table + +The numerator and denominator of a rational number are normalized in such +a way that they have no factor in common and the denominator is positive. + + +@section Elementary complex functions + +The class @code{cl_N} defines the following operation: + +@table @code +@item cl_N complex (const cl_R& a, const cl_R& b) +Returns the complex number @code{a+bi}, that is, the complex number with +real part @code{a} and imaginary part @code{b}. +@end table + +Each of the classes @code{cl_N}, @code{cl_R} defines the following operations: + +@table @code +@item cl_R realpart (const @var{type}& x) +Returns the real part of @code{x}. + +@item cl_R imagpart (const @var{type}& x) +Returns the imaginary part of @code{x}. + +@item @var{type} conjugate (const @var{type}& x) +Returns the complex conjugate of @code{x}. +@end table + +We have the relations + +@itemize @asis +@item +@code{x = complex(realpart(x), imagpart(x))} +@item +@code{conjugate(x) = complex(realpart(x), -imagpart(x))} +@end itemize + + +@section Comparisons + +Each of the classes @code{cl_N}, @code{cl_R}, @code{cl_RA}, @code{cl_I}, +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines the following operations: + +@table @code +@item bool operator == (const @var{type}&, const @var{type}&) +@itemx bool operator != (const @var{type}&, const @var{type}&) +Comparison, as in C and C++. + +@item uint32 cl_equal_hashcode (const @var{type}&) +Returns a 32-bit hash code that is the same for any two numbers which are +the same according to @code{==}. This hash code depends on the number's value, +not its type or precision. + +@item cl_boolean zerop (const @var{type}& x) +Compare against zero: @code{x == 0} +@end table + +Each of the classes @code{cl_R}, @code{cl_RA}, @code{cl_I}, +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines the following operations: + +@table @code +@item cl_signean cl_compare (const @var{type}& x, const @var{type}& y) +Compares @code{x} and @code{y}. Returns +1 if @code{x}>@code{y}, +-1 if @code{x}<@code{y}, 0 if @code{x}=@code{y}. + +@item bool operator <= (const @var{type}&, const @var{type}&) +@itemx bool operator < (const @var{type}&, const @var{type}&) +@itemx bool operator >= (const @var{type}&, const @var{type}&) +@itemx bool operator > (const @var{type}&, const @var{type}&) +Comparison, as in C and C++. + +@item cl_boolean minusp (const @var{type}& x) +Compare against zero: @code{x < 0} + +@item cl_boolean plusp (const @var{type}& x) +Compare against zero: @code{x > 0} + +@item @var{type} max (const @var{type}& x, const @var{type}& y) +Return the maximum of @code{x} and @code{y}. + +@item @var{type} min (const @var{type}& x, const @var{type}& y) +Return the minimum of @code{x} and @code{y}. +@end table + +When a floating point number and a rational number are compared, the float +is first converted to a rational number using the function @code{rational}. +Since a floating point number actually represents an interval of real numbers, +the result might be surprising. +For example, @code{(cl_F)(cl_R)"1/3" == (cl_R)"1/3"} returns false because +there is no floating point number whose value is exactly @code{1/3}. + + +@section Rounding functions + +When a real number is to be converted to an integer, there is no ``best'' +rounding. The desired rounding function depends on the application. +The Common Lisp and ISO Lisp standards offer four rounding functions: + +@table @code +@item floor(x) +This is the largest integer <=@code{x}. + +@item ceiling(x) +This is the smallest integer >=@code{x}. + +@item truncate(x) +Among the integers between 0 and @code{x} (inclusive) the one nearest to @code{x}. + +@item round(x) +The integer nearest to @code{x}. If @code{x} is exactly halfway between two +integers, choose the even one. +@end table + +These functions have different advantages: + +@code{floor} and @code{ceiling} are translation invariant: +@code{floor(x+n) = floor(x) + n} and @code{ceiling(x+n) = ceiling(x) + n} +for every @code{x} and every integer @code{n}. + +On the other hand, @code{truncate} and @code{round} are symmetric: +@code{truncate(-x) = -truncate(x)} and @code{round(-x) = -round(x)}, +and furthermore @code{round} is unbiased: on the ``average'', it rounds +down exactly as often as it rounds up. + +The functions are related like this: + +@itemize @asis +@item +@code{ceiling(m/n) = floor((m+n-1)/n) = floor((m-1)/n)+1} +for rational numbers @code{m/n} (@code{m}, @code{n} integers, @code{n}>0), and +@item +@code{truncate(x) = sign(x) * floor(abs(x))} +@end itemize + +Each of the classes @code{cl_R}, @code{cl_RA}, +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines the following operations: + +@table @code +@item cl_I floor1 (const @var{type}& x) +Returns @code{floor(x)}. +@item cl_I ceiling1 (const @var{type}& x) +Returns @code{ceiling(x)}. +@item cl_I truncate1 (const @var{type}& x) +Returns @code{truncate(x)}. +@item cl_I round1 (const @var{type}& x) +Returns @code{round(x)}. +@end table + +Each of the classes @code{cl_R}, @code{cl_RA}, @code{cl_I}, +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines the following operations: + +@table @code +@item cl_I floor1 (const @var{type}& x, const @var{type}& y) +Returns @code{floor(x/y)}. +@item cl_I ceiling1 (const @var{type}& x, const @var{type}& y) +Returns @code{ceiling(x/y)}. +@item cl_I truncate1 (const @var{type}& x, const @var{type}& y) +Returns @code{truncate(x/y)}. +@item cl_I round1 (const @var{type}& x, const @var{type}& y) +Returns @code{round(x/y)}. +@end table + +These functions are called @samp{floor1}, @dots{} here instead of +@samp{floor}, @dots{}, because on some systems, system dependent include +files define @samp{floor} and @samp{ceiling} as macros. + +In many cases, one needs both the quotient and the remainder of a division. +It is more efficient to compute both at the same time than to perform +two divisions, one for quotient and the next one for the remainder. +The following functions therefore return a structure containing both +the quotient and the remainder. The suffix @samp{2} indicates the number +of ``return values''. The remainder is defined as follows: + +@itemize @bullet +@item +for the computation of @code{quotient = floor(x)}, +@code{remainder = x - quotient}, +@item +for the computation of @code{quotient = floor(x,y)}, +@code{remainder = x - quotient*y}, +@end itemize + +and similarly for the other three operations. + +Each of the classes @code{cl_R}, @code{cl_RA}, +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines the following operations: + +@table @code +@item struct @var{type}_div_t @{ cl_I quotient; @var{type} remainder; @}; +@itemx @var{type}_div_t floor2 (const @var{type}& x) +@itemx @var{type}_div_t ceiling2 (const @var{type}& x) +@itemx @var{type}_div_t truncate2 (const @var{type}& x) +@itemx @var{type}_div_t round2 (const @var{type}& x) +@end table + +Each of the classes @code{cl_R}, @code{cl_RA}, @code{cl_I}, +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines the following operations: + +@table @code +@item struct @var{type}_div_t @{ cl_I quotient; @var{type} remainder; @}; +@itemx @var{type}_div_t floor2 (const @var{type}& x, const @var{type}& y) +@itemx @var{type}_div_t ceiling2 (const @var{type}& x, const @var{type}& y) +@itemx @var{type}_div_t truncate2 (const @var{type}& x, const @var{type}& y) +@itemx @var{type}_div_t round2 (const @var{type}& x, const @var{type}& y) +@end table + +Sometimes, one wants the quotient as a floating-point number (of the +same format as the argument, if the argument is a float) instead of as +an integer. The prefix @samp{f} indicates this. + +Each of the classes +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines the following operations: + +@table @code +@item @var{type} ffloor (const @var{type}& x) +@itemx @var{type} fceiling (const @var{type}& x) +@itemx @var{type} ftruncate (const @var{type}& x) +@itemx @var{type} fround (const @var{type}& x) +@end table + +and similarly for class @code{cl_R}, but with return type @code{cl_F}. + +The class @code{cl_R} defines the following operations: + +@table @code +@item cl_F ffloor (const @var{type}& x, const @var{type}& y) +@itemx cl_F fceiling (const @var{type}& x, const @var{type}& y) +@itemx cl_F ftruncate (const @var{type}& x, const @var{type}& y) +@itemx cl_F fround (const @var{type}& x, const @var{type}& y) +@end table + +These functions also exist in versions which return both the quotient +and the remainder. The suffix @samp{2} indicates this. + +Each of the classes +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines the following operations: + +@table @code +@item struct @var{type}_fdiv_t @{ @var{type} quotient; @var{type} remainder; @}; +@itemx @var{type}_fdiv_t ffloor2 (const @var{type}& x) +@itemx @var{type}_fdiv_t fceiling2 (const @var{type}& x) +@itemx @var{type}_fdiv_t ftruncate2 (const @var{type}& x) +@itemx @var{type}_fdiv_t fround2 (const @var{type}& x) +@end table +and similarly for class @code{cl_R}, but with quotient type @code{cl_F}. + +The class @code{cl_R} defines the following operations: + +@table @code +@item struct @var{type}_fdiv_t @{ cl_F quotient; cl_R remainder; @}; +@itemx @var{type}_fdiv_t ffloor2 (const @var{type}& x, const @var{type}& y) +@itemx @var{type}_fdiv_t fceiling2 (const @var{type}& x, const @var{type}& y) +@itemx @var{type}_fdiv_t ftruncate2 (const @var{type}& x, const @var{type}& y) +@itemx @var{type}_fdiv_t fround2 (const @var{type}& x, const @var{type}& y) +@end table + +Other applications need only the remainder of a division. +The remainder of @samp{floor} and @samp{ffloor} is called @samp{mod} +(abbreviation of ``modulo''). The remainder @samp{truncate} and +@samp{ftruncate} is called @samp{rem} (abbreviation of ``remainder''). + +@itemize @bullet +@item +@code{mod(x,y) = floor2(x,y).remainder = x - floor(x/y)*y} +@item +@code{rem(x,y) = truncate2(x,y).remainder = x - truncate(x/y)*y} +@end itemize + +If @code{x} and @code{y} are both >= 0, @code{mod(x,y) = rem(x,y) >= 0}. +In general, @code{mod(x,y)} has the sign of @code{y} or is zero, +and @code{rem(x,y)} has the sign of @code{x} or is zero. + +The classes @code{cl_R}, @code{cl_I} define the following operations: + +@table @code +@item @var{type} mod (const @var{type}& x, const @var{type}& y) +@itemx @var{type} rem (const @var{type}& x, const @var{type}& y) +@end table + + +@section Roots + +Each of the classes @code{cl_R}, +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines the following operation: + +@table @code +@item @var{type} sqrt (const @var{type}& x) +@code{x} must be >= 0. This function returns the square root of @code{x}, +normalized to be >= 0. If @code{x} is the square of a rational number, +@code{sqrt(x)} will be a rational number, else it will return a +floating-point approximation. +@end table + +The classes @code{cl_RA}, @code{cl_I} define the following operation: + +@table @code +@item cl_boolean sqrtp (const @var{type}& x, @var{type}* root) +This tests whether @code{x} is a perfect square. If so, it returns true +and the exact square root in @code{*root}, else it returns false. +@end table + +Furthermore, for integers, similarly: + +@table @code +@item cl_boolean isqrt (const @var{type}& x, @var{type}* root) +@code{x} should be >= 0. This function sets @code{*root} to +@code{floor(sqrt(x))} and returns the same value as @code{sqrtp}: +the boolean value @code{(expt(*root,2) == x)}. +@end table + +For @code{n}th roots, the classes @code{cl_RA}, @code{cl_I} +define the following operation: + +@table @code +@item cl_boolean rootp (const @var{type}& x, const cl_I& n, @var{type}* root) +@code{x} must be >= 0. @code{n} must be > 0. +This tests whether @code{x} is an @code{n}th power of a rational number. +If so, it returns true and the exact root in @code{*root}, else it returns +false. +@end table + +The only square root function which accepts negative numbers is the one +for class @code{cl_N}: + +@table @code +@item cl_N sqrt (const cl_N& z) +Returns the square root of @code{z}, as defined by the formula +@code{sqrt(z) = exp(log(z)/2)}. Conversion to a floating-point type +or to a complex number are done if necessary. The range of the result is the +right half plane @code{realpart(sqrt(z)) >= 0} +including the positive imaginary axis and 0, but excluding +the negative imaginary axis. +The result is an exact number only if @code{z} is an exact number. +@end table + + +@section Transcendental functions + + +The transcendental functions return an exact result if the argument +is exact and the result is exact as well. Otherwise they must return +inexact numbers even if the argument is exact. +For example, @code{cos(0) = 1} returns the rational number @code{1}. + + +@subsection Exponential and logarithmic functions + +@table @code +@item cl_R exp (const cl_R& x) +@itemx cl_N exp (const cl_N& x) +Returns the exponential function of @code{x}. This is @code{e^x} where +@code{e} is the base of the natural logarithms. The range of the result +is the entire complex plane excluding 0. + +@item cl_R ln (const cl_R& x) +@code{x} must be > 0. Returns the (natural) logarithm of x. + +@item cl_N log (const cl_N& x) +Returns the (natural) logarithm of x. If @code{x} is real and positive, +this is @code{ln(x)}. In general, @code{log(x) = log(abs(x)) + i*phase(x)}. +The range of the result is the strip in the complex plane +@code{-pi < imagpart(log(x)) <= pi}. + +@item cl_R phase (const cl_N& x) +Returns the angle part of @code{x} in its polar representation as a +complex number. That is, @code{phase(x) = atan(realpart(x),imagpart(x))}. +This is also the imaginary part of @code{log(x)}. +The range of the result is the interval @code{-pi < phase(x) <= pi}. +The result will be an exact number only if @code{zerop(x)} or +if @code{x} is real and positive. + +@item cl_R log (const cl_R& a, const cl_R& b) +@code{a} and @code{b} must be > 0. Returns the logarithm of @code{a} with +respect to base @code{b}. @code{log(a,b) = ln(a)/ln(b)}. +The result can be exact only if @code{a = 1} or if @code{a} and @code{b} +are both rational. + +@item cl_N log (const cl_N& a, const cl_N& b) +Returns the logarithm of @code{a} with respect to base @code{b}. +@code{log(a,b) = log(a)/log(b)}. + +@item cl_N expt (const cl_N& x, const cl_N& y) +Exponentiation: Returns @code{x^y = exp(y*log(x))}. +@end table + +The constant e = exp(1) = 2.71828@dots{} is returned by the following functions: + +@table @code +@item cl_F cl_exp1 (cl_float_format_t f) +Returns e as a float of format @code{f}. + +@item cl_F cl_exp1 (const cl_F& y) +Returns e in the float format of @code{y}. + +@item cl_F cl_exp1 (void) +Returns e as a float of format @code{cl_default_float_format}. +@end table + + +@subsection Trigonometric functions + +@table @code +@item cl_R sin (const cl_R& x) +Returns @code{sin(x)}. The range of the result is the interval +@code{-1 <= sin(x) <= 1}. + +@item cl_N sin (const cl_N& z) +Returns @code{sin(z)}. The range of the result is the entire complex plane. + +@item cl_R cos (const cl_R& x) +Returns @code{cos(x)}. The range of the result is the interval +@code{-1 <= cos(x) <= 1}. + +@item cl_N cos (const cl_N& x) +Returns @code{cos(z)}. The range of the result is the entire complex plane. + +@item struct cl_cos_sin_t @{ cl_R cos; cl_R sin; @}; +@itemx cl_cos_sin_t cl_cos_sin (const cl_R& x) +Returns both @code{sin(x)} and @code{cos(x)}. This is more efficient than +computing them separately. The relation @code{cos^2 + sin^2 = 1} will +hold only approximately. + +@item cl_R tan (const cl_R& x) +@itemx cl_N tan (const cl_N& x) +Returns @code{tan(x) = sin(x)/cos(x)}. + +@item cl_N cis (const cl_R& x) +@itemx cl_N cis (const cl_N& x) +Returns @code{exp(i*x)}. The name @samp{cis} means ``cos + i sin'', because +@code{e^(i*x) = cos(x) + i*sin(x)}. + +@item cl_N asin (const cl_N& z) +Returns @code{arcsin(z)}. This is defined as +@code{arcsin(z) = log(iz+sqrt(1-z^2))/i} and satisfies +@code{arcsin(-z) = -arcsin(z)}. +The range of the result is the strip in the complex domain +@code{-pi/2 <= realpart(arcsin(z)) <= pi/2}, excluding the numbers +with @code{realpart = -pi/2} and @code{imagpart < 0} and the numbers +with @code{realpart = pi/2} and @code{imagpart > 0}. +@ignore +Proof: This follows from arcsin(z) = arsinh(iz)/i and the corresponding +results for arsinh. +@end ignore + +@item cl_N acos (const cl_N& z) +Returns @code{arccos(z)}. This is defined as +@code{arccos(z) = pi/2 - arcsin(z) = log(z+i*sqrt(1-z^2))/i} +@ignore + Kahan's formula: + @code{arccos(z) = 2*log(sqrt((1+z)/2)+i*sqrt((1-z)/2))/i} +@end ignore +and satisfies @code{arccos(-z) = pi - arccos(z)}. +The range of the result is the strip in the complex domain +@code{0 <= realpart(arcsin(z)) <= pi}, excluding the numbers +with @code{realpart = 0} and @code{imagpart < 0} and the numbers +with @code{realpart = pi} and @code{imagpart > 0}. +@ignore +Proof: This follows from the results about arcsin. +@end ignore + +@item cl_R atan (const cl_R& x, const cl_R& y) +Returns the angle of the polar representation of the complex number +@code{x+iy}. This is @code{atan(y/x)} if @code{x>0}. The range of +the result is the interval @code{-pi < atan(x,y) <= pi}. The result will +be an exact number only if @code{x > 0} and @code{y} is the exact @code{0}. +WARNING: In Common Lisp, this function is called as @code{(atan y x)}, +with reversed order of arguments. + +@item cl_R atan (const cl_R& x) +Returns @code{arctan(x)}. This is the same as @code{atan(1,x)}. The range +of the result is the interval @code{-pi/2 < atan(x) < pi/2}. The result +will be an exact number only if @code{x} is the exact @code{0}. + +@item cl_N atan (const cl_N& z) +Returns @code{arctan(z)}. This is defined as +@code{arctan(z) = (log(1+iz)-log(1-iz)) / 2i} and satisfies +@code{arctan(-z) = -arctan(z)}. The range of the result is +the strip in the complex domain +@code{-pi/2 <= realpart(arctan(z)) <= pi/2}, excluding the numbers +with @code{realpart = -pi/2} and @code{imagpart >= 0} and the numbers +with @code{realpart = pi/2} and @code{imagpart <= 0}. +@ignore +Proof: arctan(z) = artanh(iz)/i, we know the range of the artanh function. +@end ignore + +@end table + +The constant pi = 3.14@dots{} is returned by the following functions: + +@table @code +@item cl_F cl_pi (cl_float_format_t f) +Returns pi as a float of format @code{f}. + +@item cl_F cl_pi (const cl_F& y) +Returns pi in the float format of @code{y}. + +@item cl_F cl_pi (void) +Returns pi as a float of format @code{cl_default_float_format}. +@end table + + +@subsection Hyperbolic functions + +@table @code +@item cl_R sinh (const cl_R& x) +Returns @code{sinh(x)}. + +@item cl_N sinh (const cl_N& z) +Returns @code{sinh(z)}. The range of the result is the entire complex plane. + +@item cl_R cosh (const cl_R& x) +Returns @code{cosh(x)}. The range of the result is the interval +@code{cosh(x) >= 1}. + +@item cl_N cosh (const cl_N& z) +Returns @code{cosh(z)}. The range of the result is the entire complex plane. + +@item struct cl_cosh_sinh_t @{ cl_R cosh; cl_R sinh; @}; +@itemx cl_cosh_sinh_t cl_cosh_sinh (const cl_R& x) +Returns both @code{sinh(x)} and @code{cosh(x)}. This is more efficient than +computing them separately. The relation @code{cosh^2 - sinh^2 = 1} will +hold only approximately. + +@item cl_R tanh (const cl_R& x) +@itemx cl_N tanh (const cl_N& x) +Returns @code{tanh(x) = sinh(x)/cosh(x)}. + +@item cl_N asinh (const cl_N& z) +Returns @code{arsinh(z)}. This is defined as +@code{arsinh(z) = log(z+sqrt(1+z^2))} and satisfies +@code{arsinh(-z) = -arsinh(z)}. +@ignore +Proof: Knowing the range of log, we know -pi < imagpart(arsinh(z)) <= pi. +Actually, z+sqrt(1+z^2) can never be real and <0, so +-pi < imagpart(arsinh(z)) < pi. +We have (z+sqrt(1+z^2))*(-z+sqrt(1+(-z)^2)) = (1+z^2)-z^2 = 1, hence the +logs of both factors sum up to 0 mod 2*pi*i, hence to 0. +@end ignore +The range of the result is the strip in the complex domain +@code{-pi/2 <= imagpart(arsinh(z)) <= pi/2}, excluding the numbers +with @code{imagpart = -pi/2} and @code{realpart > 0} and the numbers +with @code{imagpart = pi/2} and @code{realpart < 0}. +@ignore +Proof: Write z = x+iy. Because of arsinh(-z) = -arsinh(z), we may assume +that z is in Range(sqrt), that is, x>=0 and, if x=0, then y>=0. +If x > 0, then Re(z+sqrt(1+z^2)) = x + Re(sqrt(1+z^2)) >= x > 0, +so -pi/2 < imagpart(log(z+sqrt(1+z^2))) < pi/2. +If x = 0 and y >= 0, arsinh(z) = log(i*y+sqrt(1-y^2)). + If y <= 1, the realpart is 0 and the imagpart is >= 0 and <= pi/2. + If y >= 1, the imagpart is pi/2 and the realpart is + log(y+sqrt(y^2-1)) >= log(y) >= 0. +@end ignore +@ignore +Moreover, if z is in Range(sqrt), +log(sqrt(1+z^2)+z) = 2 artanh(z/(1+sqrt(1+z^2))) +(for a proof, see file src/cl_C_asinh.cc). +@end ignore + +@item cl_N acosh (const cl_N& z) +Returns @code{arcosh(z)}. This is defined as +@code{arcosh(z) = 2*log(sqrt((z+1)/2)+sqrt((z-1)/2))}. +The range of the result is the half-strip in the complex domain +@code{-pi < imagpart(arcosh(z)) <= pi, realpart(arcosh(z)) >= 0}, +excluding the numbers with @code{realpart = 0} and @code{-pi < imagpart < 0}. +@ignore +Proof: sqrt((z+1)/2) and sqrt((z-1)/2)) lie in Range(sqrt), hence does +their sum, hence its log has an imagpart <= pi/2 and > -pi/2. +If z is in Range(sqrt), we have + sqrt(z+1)*sqrt(z-1) = sqrt(z^2-1) + ==> (sqrt((z+1)/2)+sqrt((z-1)/2))^2 = (z+1)/2 + sqrt(z^2-1) + (z-1)/2 + = z + sqrt(z^2-1) + ==> arcosh(z) = log(z+sqrt(z^2-1)) mod 2*pi*i + and since the imagpart of both expressions is > -pi, <= pi + ==> arcosh(z) = log(z+sqrt(z^2-1)) + To prove that the realpart of this is >= 0, write z = x+iy with x>=0, + z^2-1 = u+iv with u = x^2-y^2-1, v = 2xy, + sqrt(z^2-1) = p+iq with p = sqrt((sqrt(u^2+v^2)+u)/2) >= 0, + q = sqrt((sqrt(u^2+v^2)-u)/2) * sign(v), + then |z+sqrt(z^2-1)|^2 = |x+iy + p+iq|^2 + = (x+p)^2 + (y+q)^2 + = x^2 + 2xp + p^2 + y^2 + 2yq + q^2 + >= x^2 + p^2 + y^2 + q^2 (since x>=0, p>=0, yq>=0) + = x^2 + y^2 + sqrt(u^2+v^2) + >= x^2 + y^2 + |u| + >= x^2 + y^2 - u + = 1 + 2*y^2 + >= 1 + hence realpart(log(z+sqrt(z^2-1))) = log(|z+sqrt(z^2-1)|) >= 0. + Equality holds only if y = 0 and u <= 0, i.e. 0 <= x < 1. + In this case arcosh(z) = log(x+i*sqrt(1-x^2)) has imagpart >=0. +Otherwise, -z is in Range(sqrt). + If y != 0, sqrt((z+1)/2) = i^sign(y) * sqrt((-z-1)/2), + sqrt((z-1)/2) = i^sign(y) * sqrt((-z+1)/2), + hence arcosh(z) = sign(y)*pi/2*i + arcosh(-z), + and this has realpart > 0. + If y = 0 and -1<=x<=0, we still have sqrt(z+1)*sqrt(z-1) = sqrt(z^2-1), + ==> arcosh(z) = log(z+sqrt(z^2-1)) = log(x+i*sqrt(1-x^2)) + has realpart = 0 and imagpart > 0. + If y = 0 and x<=-1, however, sqrt(z+1)*sqrt(z-1) = - sqrt(z^2-1), + ==> arcosh(z) = log(z-sqrt(z^2-1)) = pi*i + arcosh(-z). + This has realpart >= 0 and imagpart = pi. +@end ignore + +@item cl_N atanh (const cl_N& z) +Returns @code{artanh(z)}. This is defined as +@code{artanh(z) = (log(1+z)-log(1-z)) / 2} and satisfies +@code{artanh(-z) = -artanh(z)}. The range of the result is +the strip in the complex domain +@code{-pi/2 <= imagpart(artanh(z)) <= pi/2}, excluding the numbers +with @code{imagpart = -pi/2} and @code{realpart <= 0} and the numbers +with @code{imagpart = pi/2} and @code{realpart >= 0}. +@ignore +Proof: Write z = x+iy. Examine + imagpart(artanh(z)) = (atan(1+x,y) - atan(1-x,-y))/2. + Case 1: y = 0. + x > 1 ==> imagpart = -pi/2, realpart = 1/2 log((x+1)/(x-1)) > 0, + x < -1 ==> imagpart = pi/2, realpart = 1/2 log((-x-1)/(-x+1)) < 0, + |x| < 1 ==> imagpart = 0 + Case 2: y > 0. + imagpart(artanh(z)) + = (atan(1+x,y) - atan(1-x,-y))/2 + = ((pi/2 - atan((1+x)/y)) - (-pi/2 - atan((1-x)/-y)))/2 + = (pi - atan((1+x)/y) - atan((1-x)/y))/2 + > (pi - pi/2 - pi/2 )/2 = 0 + and (1+x)/y > (1-x)/y + ==> atan((1+x)/y) > atan((-1+x)/y) = - atan((1-x)/y) + ==> imagpart < pi/2. + Hence 0 < imagpart < pi/2. + Case 3: y < 0. + By artanh(z) = -artanh(-z) and case 2, -pi/2 < imagpart < 0. +@end ignore +@end table + + +@subsection Euler gamma + +Euler's constant C = 0.577@dots{} is returned by the following functions: + +@table @code +@item cl_F cl_eulerconst (cl_float_format_t f) +Returns Euler's constant as a float of format @code{f}. + +@item cl_F cl_eulerconst (const cl_F& y) +Returns Euler's constant in the float format of @code{y}. + +@item cl_F cl_eulerconst (void) +Returns Euler's constant as a float of format @code{cl_default_float_format}. +@end table + +Catalan's constant G = 0.915@dots{} is returned by the following functions: + +@table @code +@item cl_F cl_catalanconst (cl_float_format_t f) +Returns Catalan's constant as a float of format @code{f}. + +@item cl_F cl_catalanconst (const cl_F& y) +Returns Catalan's constant in the float format of @code{y}. + +@item cl_F cl_catalanconst (void) +Returns Catalan's constant as a float of format @code{cl_default_float_format}. +@end table + + +@subsection Riemann zeta + +Riemann's zeta function at an integral point @code{s>1} is returned by the +following functions: + +@table @code +@item cl_F cl_zeta (int s, cl_float_format_t f) +Returns Riemann's zeta function at @code{s} as a float of format @code{f}. + +@item cl_F cl_zeta (int s, const cl_F& y) +Returns Riemann's zeta function at @code{s} in the float format of @code{y}. + +@item cl_F cl_zeta (int s) +Returns Riemann's zeta function at @code{s} as a float of format +@code{cl_default_float_format}. +@end table + + +@section Functions on integers + +@subsection Logical functions + +Integers, when viewed as in two's complement notation, can be thought as +infinite bit strings where the bits' values eventually are constant. +For example, +@example + 17 = ......00010001 + -6 = ......11111010 +@end example + +The logical operations view integers as such bit strings and operate +on each of the bit positions in parallel. + +@table @code +@item cl_I lognot (const cl_I& x) +@itemx cl_I operator ~ (const cl_I& x) +Logical not, like @code{~x} in C. This is the same as @code{-1-x}. + +@item cl_I logand (const cl_I& x, const cl_I& y) +@itemx cl_I operator & (const cl_I& x, const cl_I& y) +Logical and, like @code{x & y} in C. + +@item cl_I logior (const cl_I& x, const cl_I& y) +@itemx cl_I operator | (const cl_I& x, const cl_I& y) +Logical (inclusive) or, like @code{x | y} in C. + +@item cl_I logxor (const cl_I& x, const cl_I& y) +@itemx cl_I operator ^ (const cl_I& x, const cl_I& y) +Exclusive or, like @code{x ^ y} in C. + +@item cl_I logeqv (const cl_I& x, const cl_I& y) +Bitwise equivalence, like @code{~(x ^ y)} in C. + +@item cl_I lognand (const cl_I& x, const cl_I& y) +Bitwise not and, like @code{~(x & y)} in C. + +@item cl_I lognor (const cl_I& x, const cl_I& y) +Bitwise not or, like @code{~(x | y)} in C. + +@item cl_I logandc1 (const cl_I& x, const cl_I& y) +Logical and, complementing the first argument, like @code{~x & y} in C. + +@item cl_I logandc2 (const cl_I& x, const cl_I& y) +Logical and, complementing the second argument, like @code{x & ~y} in C. + +@item cl_I logorc1 (const cl_I& x, const cl_I& y) +Logical or, complementing the first argument, like @code{~x | y} in C. + +@item cl_I logorc2 (const cl_I& x, const cl_I& y) +Logical or, complementing the second argument, like @code{x | ~y} in C. +@end table + +These operations are all available though the function +@table @code +@item cl_I boole (cl_boole op, const cl_I& x, const cl_I& y) +@end table +where @code{op} must have one of the 16 values (each one stands for a function +which combines two bits into one bit): @code{boole_clr}, @code{boole_set}, +@code{boole_1}, @code{boole_2}, @code{boole_c1}, @code{boole_c2}, +@code{boole_and}, @code{boole_ior}, @code{boole_xor}, @code{boole_eqv}, +@code{boole_nand}, @code{boole_nor}, @code{boole_andc1}, @code{boole_andc2}, +@code{boole_orc1}, @code{boole_orc2}. + +Other functions that view integers as bit strings: + +@table @code +@item cl_boolean logtest (const cl_I& x, const cl_I& y) +Returns true if some bit is set in both @code{x} and @code{y}, i.e. if +@code{logand(x,y) != 0}. + +@item cl_boolean logbitp (const cl_I& n, const cl_I& x) +Returns true if the @code{n}th bit (from the right) of @code{x} is set. +Bit 0 is the least significant bit. + +@item uintL logcount (const cl_I& x) +Returns the number of one bits in @code{x}, if @code{x} >= 0, or +the number of zero bits in @code{x}, if @code{x} < 0. +@end table + +The following functions operate on intervals of bits in integers. +The type +@example +struct cl_byte @{ uintL size; uintL position; @}; +@end example +represents the bit interval containing the bits +@code{position}@dots{}@code{position+size-1} of an integer. +The constructor @code{cl_byte(size,position)} constructs a @code{cl_byte}. + +@table @code +@item cl_I ldb (const cl_I& n, const cl_byte& b) +extracts the bits of @code{n} described by the bit interval @code{b} +and returns them as a nonnegative integer with @code{b.size} bits. + +@item cl_boolean ldb_test (const cl_I& n, const cl_byte& b) +Returns true if some bit described by the bit interval @code{b} is set in +@code{n}. + +@item cl_I dpb (const cl_I& newbyte, const cl_I& n, const cl_byte& b) +Returns @code{n}, with the bits described by the bit interval @code{b} +replaced by @code{newbyte}. Only the lowest @code{b.size} bits of +@code{newbyte} are relevant. +@end table + +The functions @code{ldb} and @code{dpb} implicitly shift. The following +functions are their counterparts without shifting: + +@table @code +@item cl_I mask_field (const cl_I& n, const cl_byte& b) +returns an integer with the bits described by the bit interval @code{b} +copied from the corresponding bits in @code{n}, the other bits zero. + +@item cl_I deposit_field (const cl_I& newbyte, const cl_I& n, const cl_byte& b) +returns an integer where the bits described by the bit interval @code{b} +come from @code{newbyte} and the other bits come from @code{n}. +@end table + +The following relations hold: + +@itemize @asis +@item +@code{ldb (n, b) = mask_field(n, b) >> b.position}, +@item +@code{dpb (newbyte, n, b) = deposit_field (newbyte << b.position, n, b)}, +@item +@code{deposit_field(newbyte,n,b) = n ^ mask_field(n,b) ^ mask_field(new_byte,b)}. +@end itemize + +The following operations on integers as bit strings are efficient shortcuts +for common arithmetic operations: + +@table @code +@item cl_boolean oddp (const cl_I& x) +Returns true if the least significant bit of @code{x} is 1. Equivalent to +@code{mod(x,2) != 0}. + +@item cl_boolean evenp (const cl_I& x) +Returns true if the least significant bit of @code{x} is 0. Equivalent to +@code{mod(x,2) == 0}. + +@item cl_I operator << (const cl_I& x, const cl_I& n) +Shifts @code{x} by @code{n} bits to the left. @code{n} should be >=0. +Equivalent to @code{x * expt(2,n)}. + +@item cl_I operator >> (const cl_I& x, const cl_I& n) +Shifts @code{x} by @code{n} bits to the right. @code{n} should be >=0. +Bits shifted out to the right are thrown away. +Equivalent to @code{floor(x / expt(2,n))}. + +@item cl_I ash (const cl_I& x, const cl_I& y) +Shifts @code{x} by @code{y} bits to the left (if @code{y}>=0) or +by @code{-y} bits to the right (if @code{y}<=0). In other words, this +returns @code{floor(x * expt(2,y))}. + +@item uintL integer_length (const cl_I& x) +Returns the number of bits (excluding the sign bit) needed to represent @code{x} +in two's complement notation. This is the smallest n >= 0 such that +-2^n <= x < 2^n. If x > 0, this is the unique n > 0 such that +2^(n-1) <= x < 2^n. + +@item uintL ord2 (const cl_I& x) +@code{x} must be non-zero. This function returns the number of 0 bits at the +right of @code{x} in two's complement notation. This is the largest n >= 0 +such that 2^n divides @code{x}. + +@item uintL power2p (const cl_I& x) +@code{x} must be > 0. This function checks whether @code{x} is a power of 2. +If @code{x} = 2^(n-1), it returns n. Else it returns 0. +(See also the function @code{logp}.) +@end table + + +@subsection Number theoretic functions + +@table @code +@item uint32 gcd (uint32 a, uint32 b) +@itemx cl_I gcd (const cl_I& a, const cl_I& b) +This function returns the greatest common divisor of @code{a} and @code{b}, +normalized to be >= 0. + +@item cl_I xgcd (const cl_I& a, const cl_I& b, cl_I* u, cl_I* v) +This function (``extended gcd'') returns the greatest common divisor @code{g} of +@code{a} and @code{b} and at the same time the representation of @code{g} +as an integral linear combination of @code{a} and @code{b}: +@code{u} and @code{v} with @code{u*a+v*b = g}, @code{g} >= 0. +@code{u} and @code{v} will be normalized to be of smallest possible absolute +value, in the following sense: If @code{a} and @code{b} are non-zero, and +@code{abs(a) != abs(b)}, @code{u} and @code{v} will satisfy the inequalities +@code{abs(u) <= abs(b)/(2*g)}, @code{abs(v) <= abs(a)/(2*g)}. + +@item cl_I lcm (const cl_I& a, const cl_I& b) +This function returns the least common multiple of @code{a} and @code{b}, +normalized to be >= 0. + +@item cl_boolean logp (const cl_I& a, const cl_I& b, cl_RA* l) +@itemx cl_boolean logp (const cl_RA& a, const cl_RA& b, cl_RA* l) +@code{a} must be > 0. @code{b} must be >0 and != 1. If log(a,b) is +rational number, this function returns true and sets *l = log(a,b), else +it returns false. +@end table + + +@subsection Combinatorial functions + +@table @code +@item cl_I factorial (uintL n) +@code{n} must be a small integer >= 0. This function returns the factorial +@code{n}! = @code{1*2*@dots{}*n}. + +@item cl_I doublefactorial (uintL n) +@code{n} must be a small integer >= 0. This function returns the +doublefactorial @code{n}!! = @code{1*3*@dots{}*n} or +@code{n}!! = @code{2*4*@dots{}*n}, respectively. + +@item cl_I binomial (uintL n, uintL k) +@code{n} and @code{k} must be small integers >= 0. This function returns the +binomial coefficient +@tex +${n \choose k} = {n! \over n! (n-k)!}$ +@end tex +@ifinfo +(@code{n} choose @code{k}) = @code{n}! / @code{k}! @code{(n-k)}! +@end ifinfo +for 0 <= k <= n, 0 else. +@end table + + +@section Functions on floating-point numbers + +Recall that a floating-point number consists of a sign @code{s}, an +exponent @code{e} and a mantissa @code{m}. The value of the number is +@code{(-1)^s * 2^e * m}. + +Each of the classes +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines the following operations. + +@table @code +@item @var{type} scale_float (const @var{type}& x, sintL delta) +@itemx @var{type} scale_float (const @var{type}& x, const cl_I& delta) +Returns @code{x*2^delta}. This is more efficient than an explicit multiplication +because it copies @code{x} and modifies the exponent. +@end table + +The following functions provide an abstract interface to the underlying +representation of floating-point numbers. + +@table @code +@item sintL float_exponent (const @var{type}& x) +Returns the exponent @code{e} of @code{x}. +For @code{x = 0.0}, this is 0. For @code{x} non-zero, this is the unique +integer with @code{2^(e-1) <= abs(x) < 2^e}. + +@item sintL float_radix (const @var{type}& x) +Returns the base of the floating-point representation. This is always @code{2}. + +@item @var{type} float_sign (const @var{type}& x) +Returns the sign @code{s} of @code{x} as a float. The value is 1 for +@code{x} >= 0, -1 for @code{x} < 0. + +@item uintL float_digits (const @var{type}& x) +Returns the number of mantissa bits in the floating-point representation +of @code{x}, including the hidden bit. The value only depends on the type +of @code{x}, not on its value. + +@item uintL float_precision (const @var{type}& x) +Returns the number of significant mantissa bits in the floating-point +representation of @code{x}. Since denormalized numbers are not supported, +this is the same as @code{float_digits(x)} if @code{x} is non-zero, and +0 if @code{x} = 0. +@end table + +The complete internal representation of a float is encoded in the type +@code{cl_decoded_float} (or @code{cl_decoded_sfloat}, @code{cl_decoded_ffloat}, +@code{cl_decoded_dfloat}, @code{cl_decoded_lfloat}, respectively), defined by +@example +struct cl_decoded_@var{type}float @{ + @var{type} mantissa; cl_I exponent; @var{type} sign; +@}; +@end example + +and returned by the function + +@table @code +@item cl_decoded_@var{type}float decode_float (const @var{type}& x) +For @code{x} non-zero, this returns @code{(-1)^s}, @code{e}, @code{m} with +@code{x = (-1)^s * 2^e * m} and @code{0.5 <= m < 1.0}. For @code{x} = 0, +it returns @code{(-1)^s}=1, @code{e}=0, @code{m}=0. +@code{e} is the same as returned by the function @code{float_exponent}. +@end table + +A complete decoding in terms of integers is provided as type +@example +struct cl_idecoded_float @{ + cl_I mantissa; cl_I exponent; cl_I sign; +@}; +@end example +by the following function: + +@table @code +@item cl_idecoded_float integer_decode_float (const @var{type}& x) +For @code{x} non-zero, this returns @code{(-1)^s}, @code{e}, @code{m} with +@code{x = (-1)^s * 2^e * m} and @code{m} an integer with @code{float_digits(x)} +bits. For @code{x} = 0, it returns @code{(-1)^s}=1, @code{e}=0, @code{m}=0. +WARNING: The exponent @code{e} is not the same as the one returned by +the functions @code{decode_float} and @code{float_exponent}. +@end table + +Some other function, implemented only for class @code{cl_F}: + +@table @code +@item cl_F float_sign (const cl_F& x, const cl_F& y) +This returns a floating point number whose precision and absolute value +is that of @code{y} and whose sign is that of @code{x}. If @code{x} is +zero, it is treated as positive. Same for @code{y}. +@end table + + +@section Conversion functions + +@subsection Conversion to floating-point numbers + +The type @code{cl_float_format_t} describes a floating-point format. + +@table @code +@item cl_float_format_t cl_float_format (uintL n) +Returns the smallest float format which guarantees at least @code{n} +decimal digits in the mantissa (after the decimal point). + +@item cl_float_format_t cl_float_format (const cl_F& x) +Returns the floating point format of @code{x}. + +@item cl_float_format_t cl_default_float_format +Global variable: the default float format used when converting rational numbers +to floats. +@end table + +To convert a real number to a float, each of the types +@code{cl_R}, @code{cl_F}, @code{cl_I}, @code{cl_RA}, +@code{int}, @code{unsigned int}, @code{float}, @code{double} +defines the following operations: + +@table @code +@item cl_F cl_float (const @var{type}&x, cl_float_format_t f) +Returns @code{x} as a float of format @code{f}. +@item cl_F cl_float (const @var{type}&x, const cl_F& y) +Returns @code{x} in the float format of @code{y}. +@item cl_F cl_float (const @var{type}&x) +Returns @code{x} as a float of format @code{cl_default_float_format} if +it is an exact number, or @code{x} itself if it is already a float. +@end table + +Of course, converting a number to a float can lose precision. + +Every floating-point format has some characteristic numbers: + +@table @code +@item cl_F most_positive_float (cl_float_format_t f) +Returns the largest (most positive) floating point number in float format @code{f}. + +@item cl_F most_negative_float (cl_float_format_t f) +Returns the smallest (most negative) floating point number in float format @code{f}. + +@item cl_F least_positive_float (cl_float_format_t f) +Returns the least positive floating point number (i.e. > 0 but closest to 0) +in float format @code{f}. + +@item cl_F least_negative_float (cl_float_format_t f) +Returns the least negative floating point number (i.e. < 0 but closest to 0) +in float format @code{f}. + +@item cl_F float_epsilon (cl_float_format_t f) +Returns the smallest floating point number e > 0 such that @code{1+e != 1}. + +@item cl_F float_negative_epsilon (cl_float_format_t f) +Returns the smallest floating point number e > 0 such that @code{1-e != 1}. +@end table + + +@subsection Conversion to rational numbers + +Each of the classes @code{cl_R}, @code{cl_RA}, @code{cl_F} +defines the following operation: + +@table @code +@item cl_RA rational (const @var{type}& x) +Returns the value of @code{x} as an exact number. If @code{x} is already +an exact number, this is @code{x}. If @code{x} is a floating-point number, +the value is a rational number whose denominator is a power of 2. +@end table + +In order to convert back, say, @code{(cl_F)(cl_R)"1/3"} to @code{1/3}, there is +the function + +@table @code +@item cl_RA rationalize (const cl_R& x) +If @code{x} is a floating-point number, it actually represents an interval +of real numbers, and this function returns the rational number with +smallest denominator (and smallest numerator, in magnitude) +which lies in this interval. +If @code{x} is already an exact number, this function returns @code{x}. +@end table + +If @code{x} is any float, one has + +@itemize @asis +@item +@code{cl_float(rational(x),x) = x} +@item +@code{cl_float(rationalize(x),x) = x} +@end itemize + + +@section Random number generators + + +A random generator is a machine which produces (pseudo-)random numbers. +The include file @code{} defines a class @code{cl_random_state} +which contains the state of a random generator. If you make a copy +of the random number generator, the original one and the copy will produce +the same sequence of random numbers. + +The following functions return (pseudo-)random numbers in different formats. +Calling one of these modifies the state of the random number generator in +a complicated but deterministic way. + +The global variable +@example +cl_random_state cl_default_random_state +@end example +contains a default random number generator. It is used when the functions +below are called without @code{cl_random_state} argument. + +@table @code +@item uint32 random32 (cl_random_state& randomstate) +@itemx uint32 random32 () +Returns a random unsigned 32-bit number. All bits are equally random. + +@item cl_I random_I (cl_random_state& randomstate, const cl_I& n) +@itemx cl_I random_I (const cl_I& n) +@code{n} must be an integer > 0. This function returns a random integer @code{x} +in the range @code{0 <= x < n}. + +@item cl_F random_F (cl_random_state& randomstate, const cl_F& n) +@itemx cl_F random_F (const cl_F& n) +@code{n} must be a float > 0. This function returns a random floating-point +number of the same format as @code{n} in the range @code{0 <= x < n}. + +@item cl_R random_R (cl_random_state& randomstate, const cl_R& n) +@itemx cl_R random_R (const cl_R& n) +Behaves like @code{random_I} if @code{n} is an integer and like @code{random_F} +if @code{n} is a float. +@end table + + +@section Obfuscating operators + +The modifying C/C++ operators @code{+=}, @code{-=}, @code{*=}, @code{/=}, +@code{&=}, @code{|=}, @code{^=}, @code{<<=}, @code{>>=} +are not available by default because their +use tends to make programs unreadable. It is trivial to get away without +them. However, if you feel that you absolutely need these operators +to get happy, then add +@example +#define WANT_OBFUSCATING_OPERATORS +@end example +to the beginning of your source files, before the inclusion of any CLN +include files. This flag will enable the following operators: + +For the classes @code{cl_N}, @code{cl_R}, @code{cl_RA}, +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF}: + +@table @code +@item @var{type}& operator += (@var{type}&, const @var{type}&) +@itemx @var{type}& operator -= (@var{type}&, const @var{type}&) +@itemx @var{type}& operator *= (@var{type}&, const @var{type}&) +@itemx @var{type}& operator /= (@var{type}&, const @var{type}&) +@end table + +For the class @code{cl_I}: + +@table @code +@item @var{type}& operator += (@var{type}&, const @var{type}&) +@itemx @var{type}& operator -= (@var{type}&, const @var{type}&) +@itemx @var{type}& operator *= (@var{type}&, const @var{type}&) +@itemx @var{type}& operator &= (@var{type}&, const @var{type}&) +@itemx @var{type}& operator |= (@var{type}&, const @var{type}&) +@itemx @var{type}& operator ^= (@var{type}&, const @var{type}&) +@itemx @var{type}& operator <<= (@var{type}&, const @var{type}&) +@itemx @var{type}& operator >>= (@var{type}&, const @var{type}&) +@end table + +For the classes @code{cl_N}, @code{cl_R}, @code{cl_RA}, @code{cl_I}, +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF}: + +@table @code +@item @var{type}& operator ++ (@var{type}& x) +The prefix operator @code{++x}. + +@item void operator ++ (@var{type}& x, int) +The postfix operator @code{x++}. + +@item @var{type}& operator -- (@var{type}& x) +The prefix operator @code{--x}. + +@item void operator -- (@var{type}& x, int) +The postfix operator @code{x--}. +@end table + +Note that by using these obfuscating operators, you wouldn't gain efficiency: +In CLN @samp{x += y;} is exactly the same as @samp{x = x+y;}, not more +efficient. + + +@chapter Input/Output + +@section Internal and printed representation + +All computations deal with the internal representations of the numbers. + +Every number has an external representation as a sequence of ASCII characters. +Several external representations may denote the same number, for example, +"20.0" and "20.000". + +Converting an internal to an external representation is called ``printing'', +converting an external to an internal representation is called ``reading''. +In CLN, is it always true that conversion of an internal to an external +representation and then back to an internal representation will yield the +same internal representation. Symbolically: @code{read(print(x)) == x}. +This is called ``print-read consistency''. + +Different types of numbers have different external representations (case +is insignificant): + +@table @asis +@item Integers +External representation: @var{sign}@{@var{digit}@}+. The reader also accepts the +Common Lisp syntaxes @var{sign}@{@var{digit}@}+@code{.} with a trailing dot +for decimal integers +and the @code{#@var{n}R}, @code{#b}, @code{#o}, @code{#x} prefixes. + +@item Rational numbers +External representation: @var{sign}@{@var{digit}@}+@code{/}@{@var{digit}@}+. +The @code{#@var{n}R}, @code{#b}, @code{#o}, @code{#x} prefixes are allowed +here as well. + +@item Floating-point numbers +External representation: @var{sign}@{@var{digit}@}*@var{exponent} or +@var{sign}@{@var{digit}@}*@code{.}@{@var{digit}@}*@var{exponent} or +@var{sign}@{@var{digit}@}*@code{.}@{@var{digit}@}+. A precision specifier +of the form _@var{prec} may be appended. There must be at least +one digit in the non-exponent part. The exponent has the syntax +@var{expmarker} @var{expsign} @{@var{digit}@}+. +The exponent marker is + +@itemize @asis +@item +@samp{s} for short-floats, +@item +@samp{f} for single-floats, +@item +@samp{d} for double-floats, +@item +@samp{L} for long-floats, +@end itemize + +or @samp{e}, which denotes a default float format. The precision specifying +suffix has the syntax _@var{prec} where @var{prec} denotes the number of +valid mantissa digits (in decimal, excluding leading zeroes), cf. also +function @samp{cl_float_format}. + +@item Complex numbers +External representation: +@itemize @asis +@item +In algebraic notation: @code{@var{realpart}+@var{imagpart}i}. Of course, +if @var{imagpart} is negative, its printed representation begins with +a @samp{-}, and the @samp{+} between @var{realpart} and @var{imagpart} +may be omitted. Note that this notation cannot be used when the @var{imagpart} +is rational and the rational number's base is >18, because the @samp{i} +is then read as a digit. +@item +In Common Lisp notation: @code{#C(@var{realpart} @var{imagpart})}. +@end itemize +@end table + + +@section Input functions + +Including @code{} defines a type @code{cl_istream}, which is +the type of the first argument to all input functions. Unless you build +and use CLN with the macro CL_IO_STDIO being defined, @code{cl_istream} +is the same as @code{istream&}. + +The variable +@itemize @asis +@item +@code{cl_istream cl_stdin} +@end itemize +contains the standard input stream. + +These are the simple input functions: + +@table @code +@item int freadchar (cl_istream stream) +Reads a character from @code{stream}. Returns @code{cl_EOF} (not a @samp{char}!) +if the end of stream was encountered or an error occurred. + +@item int funreadchar (cl_istream stream, int c) +Puts back @code{c} onto @code{stream}. @code{c} must be the result of the +last @code{freadchar} operation on @code{stream}. +@end table + +Each of the classes @code{cl_N}, @code{cl_R}, @code{cl_RA}, @code{cl_I}, +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines, in @code{}, the following input function: + +@table @code +@item cl_istream operator>> (cl_istream stream, @var{type}& result) +Reads a number from @code{stream} and stores it in the @code{result}. +@end table + +The most flexible input functions, defined in @code{}, +are the following: + +@table @code +@item cl_N read_complex (cl_istream stream, const cl_read_flags& flags) +@itemx cl_R read_real (cl_istream stream, const cl_read_flags& flags) +@itemx cl_F read_float (cl_istream stream, const cl_read_flags& flags) +@itemx cl_RA read_rational (cl_istream stream, const cl_read_flags& flags) +@itemx cl_I read_integer (cl_istream stream, const cl_read_flags& flags) +Reads a number from @code{stream}. The @code{flags} are parameters which +affect the input syntax. Whitespace before the number is silently skipped. + +@item cl_N read_complex (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse) +@itemx cl_R read_real (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse) +@itemx cl_F read_float (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse) +@itemx cl_RA read_rational (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse) +@itemx cl_I read_integer (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse) +Reads a number from a string in memory. The @code{flags} are parameters which +affect the input syntax. The string starts at @code{string} and ends at +@code{string_limit} (exclusive limit). @code{string_limit} may also be +@code{NULL}, denoting the entire string, i.e. equivalent to +@code{string_limit = string + strlen(string)}. If @code{end_of_parse} is +@code{NULL}, the string in memory must contain exactly one number and nothing +more, else a fatal error will be signalled. If @code{end_of_parse} +is not @code{NULL}, @code{*end_of_parse} will be assigned a pointer past +the last parsed character (i.e. @code{string_limit} if nothing came after +the number). Whitespace is not allowed. +@end table + +The structure @code{cl_read_flags} contains the following fields: + +@table @code +@item cl_read_syntax_t syntax +The possible results of the read operation. Possible values are +@code{syntax_number}, @code{syntax_real}, @code{syntax_rational}, +@code{syntax_integer}, @code{syntax_float}, @code{syntax_sfloat}, +@code{syntax_ffloat}, @code{syntax_dfloat}, @code{syntax_lfloat}. + +@item cl_read_lsyntax_t lsyntax +Specifies the language-dependent syntax variant for the read operation. +Possible values are + +@table @code +@item lsyntax_standard +accept standard algebraic notation only, no complex numbers, +@item lsyntax_algebraic +accept the algebraic notation @code{@var{x}+@var{y}i} for complex numbers, +@item lsyntax_commonlisp +accept the @code{#b}, @code{#o}, @code{#x} syntaxes for binary, octal, +hexadecimal numbers, +@code{#@var{base}R} for rational numbers in a given base, +@code{#c(@var{realpart} @var{imagpart})} for complex numbers, +@item lsyntax_all +accept all of these extensions. +@end table + +@item unsigned int rational_base +The base in which rational numbers are read. + +@item cl_float_format_t float_flags.default_float_format +The float format used when reading floats with exponent marker @samp{e}. + +@item cl_float_format_t float_flags.default_lfloat_format +The float format used when reading floats with exponent marker @samp{l}. + +@item cl_boolean float_flags.mantissa_dependent_float_format +When this flag is true, floats specified with more digits than corresponding +to the exponent marker they contain, but without @var{_nnn} suffix, will get a +precision corresponding to their number of significant digits. +@end table + + +@section Output functions + +Including @code{} defines a type @code{cl_ostream}, which is +the type of the first argument to all output functions. Unless you build +and use CLN with the macro CL_IO_STDIO being defined, @code{cl_ostream} +is the same as @code{ostream&}. + +The variable +@itemize @asis +@item +@code{cl_ostream cl_stdout} +@end itemize +contains the standard output stream. + +The variable +@itemize @asis +@item +@code{cl_ostream cl_stderr} +@end itemize +contains the standard error output stream. + +These are the simple output functions: + +@table @code +@item void fprintchar (cl_ostream stream, char c) +Prints the character @code{x} literally on the @code{stream}. + +@item void fprint (cl_ostream stream, const char * string) +Prints the @code{string} literally on the @code{stream}. + +@item void fprintdecimal (cl_ostream stream, int x) +@itemx void fprintdecimal (cl_ostream stream, const cl_I& x) +Prints the integer @code{x} in decimal on the @code{stream}. + +@item void fprintbinary (cl_ostream stream, const cl_I& x) +Prints the integer @code{x} in binary (base 2, without prefix) +on the @code{stream}. + +@item void fprintoctal (cl_ostream stream, const cl_I& x) +Prints the integer @code{x} in octal (base 8, without prefix) +on the @code{stream}. + +@item void fprinthexadecimal (cl_ostream stream, const cl_I& x) +Prints the integer @code{x} in hexadecimal (base 16, without prefix) +on the @code{stream}. +@end table + +Each of the classes @code{cl_N}, @code{cl_R}, @code{cl_RA}, @code{cl_I}, +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines, in @code{}, the following output functions: + +@table @code +@item void fprint (cl_ostream stream, const @var{type}& x) +@itemx cl_ostream operator<< (cl_ostream stream, const @var{type}& x) +Prints the number @code{x} on the @code{stream}. The output may depend +on the global printer settings in the variable @code{cl_default_print_flags}. +The @code{ostream} flags and settings (flags, width and locale) are +ignored. +@end table + +The most flexible output function, defined in @code{}, +are the following: +@example +void print_complex (cl_ostream stream, const cl_print_flags& flags, + const cl_N& z); +void print_real (cl_ostream stream, const cl_print_flags& flags, + const cl_R& z); +void print_float (cl_ostream stream, const cl_print_flags& flags, + const cl_F& z); +void print_rational (cl_ostream stream, const cl_print_flags& flags, + const cl_RA& z); +void print_integer (cl_ostream stream, const cl_print_flags& flags, + const cl_I& z); +@end example +Prints the number @code{x} on the @code{stream}. The @code{flags} are +parameters which affect the output. + +The structure type @code{cl_print_flags} contains the following fields: + +@table @code +@item unsigned int rational_base +The base in which rational numbers are printed. Default is @code{10}. + +@item cl_boolean rational_readably +If this flag is true, rational numbers are printed with radix specifiers in +Common Lisp syntax (@code{#@var{n}R} or @code{#b} or @code{#o} or @code{#x} +prefixes, trailing dot). Default is false. + +@item cl_boolean float_readably +If this flag is true, type specific exponent markers have precedence over 'E'. +Default is false. + +@item cl_float_format_t default_float_format +Floating point numbers of this format will be printed using the 'E' exponent +marker. Default is @code{cl_float_format_ffloat}. + +@item cl_boolean complex_readably +If this flag is true, complex numbers will be printed using the Common Lisp +syntax @code{#C(@var{realpart} @var{imagpart})}. Default is false. + +@item cl_string univpoly_varname +Univariate polynomials with no explicit indeterminate name will be printed +using this variable name. Default is @code{"x"}. +@end table + +The global variable @code{cl_default_print_flags} contains the default values, +used by the function @code{fprint}, + + +@chapter Rings + +CLN has a class of abstract rings. + +@example + Ring + cl_ring + +@end example + +Rings can be compared for equality: + +@table @code +@item bool operator== (const cl_ring&, const cl_ring&) +@itemx bool operator!= (const cl_ring&, const cl_ring&) +These compare two rings for equality. +@end table + +Given a ring @code{R}, the following members can be used. + +@table @code +@item void R->fprint (cl_ostream stream, const cl_ring_element& x) +@itemx cl_boolean R->equal (const cl_ring_element& x, const cl_ring_element& y) +@itemx cl_ring_element R->zero () +@itemx cl_boolean R->zerop (const cl_ring_element& x) +@itemx cl_ring_element R->plus (const cl_ring_element& x, const cl_ring_element& y) +@itemx cl_ring_element R->minus (const cl_ring_element& x, const cl_ring_element& y) +@itemx cl_ring_element R->uminus (const cl_ring_element& x) +@itemx cl_ring_element R->one () +@itemx cl_ring_element R->canonhom (const cl_I& x) +@itemx cl_ring_element R->mul (const cl_ring_element& x, const cl_ring_element& y) +@itemx cl_ring_element R->square (const cl_ring_element& x) +@itemx cl_ring_element R->expt_pos (const cl_ring_element& x, const cl_I& y) +@end table + +The following rings are built-in. + +@table @code +@item cl_null_ring cl_0_ring +The null ring, containing only zero. + +@item cl_complex_ring cl_C_ring +The ring of complex numbers. This corresponds to the type @code{cl_N}. + +@item cl_real_ring cl_R_ring +The ring of real numbers. This corresponds to the type @code{cl_R}. + +@item cl_rational_ring cl_RA_ring +The ring of rational numbers. This corresponds to the type @code{cl_RA}. + +@item cl_integer_ring cl_I_ring +The ring of integers. This corresponds to the type @code{cl_I}. +@end table + +Type tests can be performed for any of @code{cl_C_ring}, @code{cl_R_ring}, +@code{cl_RA_ring}, @code{cl_I_ring}: + +@table @code +@item cl_boolean instanceof (const cl_number& x, const cl_number_ring& R) +Tests whether the given number is an element of the number ring R. +@end table + + +@chapter Modular integers + +@section Modular integer rings + +CLN implements modular integers, i.e. integers modulo a fixed integer N. +The modulus is explicitly part of every modular integer. CLN doesn't +allow you to (accidentally) mix elements of different modular rings, +e.g. @code{(3 mod 4) + (2 mod 5)} will result in a runtime error. +(Ideally one would imagine a generic data type @code{cl_MI(N)}, but C++ +doesn't have generic types. So one has to live with runtime checks.) + +The class of modular integer rings is + +@example + Ring + cl_ring + + | + | + Modular integer ring + cl_modint_ring + +@end example + +and the class of all modular integers (elements of modular integer rings) is + +@example + Modular integer + cl_MI + +@end example + +Modular integer rings are constructed using the function + +@table @code +@item cl_modint_ring cl_find_modint_ring (const cl_I& N) +This function returns the modular ring @samp{Z/NZ}. It takes care +of finding out about special cases of @code{N}, like powers of two +and odd numbers for which Montgomery multiplication will be a win, +and precomputes any necessary auxiliary data for computing modulo @code{N}. +There is a cache table of rings, indexed by @code{N} (or, more precisely, +by @code{abs(N)}). This ensures that the precomputation costs are reduced +to a minimum. +@end table + +Modular integer rings can be compared for equality: + +@table @code +@item bool operator== (const cl_modint_ring&, const cl_modint_ring&) +@itemx bool operator!= (const cl_modint_ring&, const cl_modint_ring&) +These compare two modular integer rings for equality. Two different calls +to @code{cl_find_modint_ring} with the same argument necessarily return the +same ring because it is memoized in the cache table. +@end table + +@section Functions on modular integers + +Given a modular integer ring @code{R}, the following members can be used. + +@table @code +@item cl_I R->modulus +This is the ring's modulus, normalized to be nonnegative: @code{abs(N)}. + +@item cl_MI R->zero() +This returns @code{0 mod N}. + +@item cl_MI R->one() +This returns @code{1 mod N}. + +@item cl_MI R->canonhom (const cl_I& x) +This returns @code{x mod N}. + +@item cl_I R->retract (const cl_MI& x) +This is a partial inverse function to @code{R->canonhom}. It returns the +standard representative (@code{>=0}, @code{random(cl_random_state& randomstate) +@itemx cl_MI R->random() +This returns a random integer modulo @code{N}. +@end table + +The following operations are defined on modular integers. + +@table @code +@item cl_modint_ring x.ring () +Returns the ring to which the modular integer @code{x} belongs. + +@item cl_MI operator+ (const cl_MI&, const cl_MI&) +Returns the sum of two modular integers. One of the arguments may also be +a plain integer. + +@item cl_MI operator- (const cl_MI&, const cl_MI&) +Returns the difference of two modular integers. One of the arguments may also be +a plain integer. + +@item cl_MI operator- (const cl_MI&) +Returns the negative of a modular integer. + +@item cl_MI operator* (const cl_MI&, const cl_MI&) +Returns the product of two modular integers. One of the arguments may also be +a plain integer. + +@item cl_MI square (const cl_MI&) +Returns the square of a modular integer. + +@item cl_MI recip (const cl_MI& x) +Returns the reciprocal @code{x^-1} of a modular integer @code{x}. @code{x} +must be coprime to the modulus, otherwise an error message is issued. + +@item cl_MI div (const cl_MI& x, const cl_MI& y) +Returns the quotient @code{x*y^-1} of two modular integers @code{x}, @code{y}. +@code{y} must be coprime to the modulus, otherwise an error message is issued. + +@item cl_MI expt_pos (const cl_MI& x, const cl_I& y) +@code{y} must be > 0. Returns @code{x^y}. + +@item cl_MI expt (const cl_MI& x, const cl_I& y) +Returns @code{x^y}. If @code{y} is negative, @code{x} must be coprime to the +modulus, else an error message is issued. + +@item cl_MI operator<< (const cl_MI& x, const cl_I& y) +Returns @code{x*2^y}. + +@item cl_MI operator>> (const cl_MI& x, const cl_I& y) +Returns @code{x*2^-y}. When @code{y} is positive, the modulus must be odd, +or an error message is issued. + +@item bool operator== (const cl_MI&, const cl_MI&) +@itemx bool operator!= (const cl_MI&, const cl_MI&) +Compares two modular integers, belonging to the same modular integer ring, +for equality. + +@item cl_boolean zerop (const cl_MI& x) +Returns true if @code{x} is @code{0 mod N}. +@end table + +The following output functions are defined (see also the chapter on +input/output). + +@table @code +@item void fprint (cl_ostream stream, const cl_MI& x) +@itemx cl_ostream operator<< (cl_ostream stream, const cl_MI& x) +Prints the modular integer @code{x} on the @code{stream}. The output may depend +on the global printer settings in the variable @code{cl_default_print_flags}. +@end table + + +@chapter Symbolic data types + +CLN implements two symbolic (non-numeric) data types: strings and symbols. + +@section Strings + +The class + +@example + String + cl_string + +@end example + +implements immutable strings. + +Strings are constructed through the following constructors: + +@table @code +@item cl_string (const char * s) +Returns an immutable copy of the (zero-terminated) C string @code{s}. + +@item cl_string (const char * ptr, unsigned long len) +Returns an immutable copy of the @code{len} characters at +@code{ptr[0]}, @dots{}, @code{ptr[len-1]}. NUL characters are allowed. +@end table + +The following functions are available on strings: + +@table @code +@item operator = +Assignment from @code{cl_string} and @code{const char *}. + +@item s.length() +@itemx strlen(s) +Returns the length of the string @code{s}. + +@item s[i] +Returns the @code{i}th character of the string @code{s}. +@code{i} must be in the range @code{0 <= i < s.length()}. + +@item bool equal (const cl_string& s1, const cl_string& s2) +Compares two strings for equality. One of the arguments may also be a +plain @code{const char *}. +@end table + +@section Symbols + +Symbols are uniquified strings: all symbols with the same name are shared. +This means that comparison of two symbols is fast (effectively just a pointer +comparison), whereas comparison of two strings must in the worst case walk +both strings until their end. +Symbols are used, for example, as tags for properties, as names of variables +in polynomial rings, etc. + +Symbols are constructed through the following constructor: + +@table @code +@item cl_symbol (const cl_string& s) +Looks up or creates a new symbol with a given name. +@end table + +The following operations are available on symbols: + +@table @code +@item cl_string (const cl_symbol& sym) +Conversion to @code{cl_string}: Returns the string which names the symbol +@code{sym}. + +@item bool equal (const cl_symbol& sym1, const cl_symbol& sym2) +Compares two symbols for equality. This is very fast. +@end table + + +@chapter Univariate polynomials + +@section Univariate polynomial rings + +CLN implements univariate polynomials (polynomials in one variable) over an +arbitrary ring. The indeterminate variable may be either unnamed (and will be +printed according to @code{cl_default_print_flags.univpoly_varname}, which +defaults to @samp{x}) or carry a given name. The base ring and the +indeterminate are explicitly part of every polynomial. CLN doesn't allow you to +(accidentally) mix elements of different polynomial rings, e.g. +@code{(a^2+1) * (b^3-1)} will result in a runtime error. (Ideally this should +return a multivariate polynomial, but they are not yet implemented in CLN.) + +The classes of univariate polynomial rings are + +@example + Ring + cl_ring + + | + | + Univariate polynomial ring + cl_univpoly_ring + + | + +----------------+-------------------+ + | | | + Complex polynomial ring | Modular integer polynomial ring + cl_univpoly_complex_ring | cl_univpoly_modint_ring + | + | + +----------------+ + | | + Real polynomial ring | + cl_univpoly_real_ring | + | + | + +----------------+ + | | + Rational polynomial ring | + cl_univpoly_rational_ring | + | + | + +----------------+ + | + Integer polynomial ring + cl_univpoly_integer_ring + +@end example + +and the corresponding classes of univariate polynomials are + +@example + Univariate polynomial + cl_UP + + | + +----------------+-------------------+ + | | | + Complex polynomial | Modular integer polynomial + cl_UP_N | cl_UP_MI + | + | + +----------------+ + | | + Real polynomial | + cl_UP_R | + | + | + +----------------+ + | | + Rational polynomial | + cl_UP_RA | + | + | + +----------------+ + | + Integer polynomial + cl_UP_I + +@end example + +Univariate polynomial rings are constructed using the functions + +@table @code +@item cl_univpoly_ring cl_find_univpoly_ring (const cl_ring& R) +@itemx cl_univpoly_ring cl_find_univpoly_ring (const cl_ring& R, const cl_symbol& varname) +This function returns the polynomial ring @samp{R[X]}, unnamed or named. +@code{R} may be an arbitrary ring. This function takes care of finding out +about special cases of @code{R}, such as the rings of complex numbers, +real numbers, rational numbers, integers, or modular integer rings. +There is a cache table of rings, indexed by @code{R} and @code{varname}. +This ensures that two calls of this function with the same arguments will +return the same polynomial ring. + +@item cl_univpoly_complex_ring cl_find_univpoly_ring (const cl_complex_ring& R) +@itemx cl_univpoly_complex_ring cl_find_univpoly_ring (const cl_complex_ring& R, const cl_symbol& varname) +@itemx cl_univpoly_real_ring cl_find_univpoly_ring (const cl_real_ring& R) +@itemx cl_univpoly_real_ring cl_find_univpoly_ring (const cl_real_ring& R, const cl_symbol& varname) +@itemx cl_univpoly_rational_ring cl_find_univpoly_ring (const cl_rational_ring& R) +@itemx cl_univpoly_rational_ring cl_find_univpoly_ring (const cl_rational_ring& R, const cl_symbol& varname) +@itemx cl_univpoly_integer_ring cl_find_univpoly_ring (const cl_integer_ring& R) +@itemx cl_univpoly_integer_ring cl_find_univpoly_ring (const cl_integer_ring& R, const cl_symbol& varname) +@itemx cl_univpoly_modint_ring cl_find_univpoly_ring (const cl_modint_ring& R) +@itemx cl_univpoly_modint_ring cl_find_univpoly_ring (const cl_modint_ring& R, const cl_symbol& varname) +These functions are equivalent to the general @code{cl_find_univpoly_ring}, +only the return type is more specific, according to the base ring's type. +@end table + +@section Functions on univariate polynomials + +Given a univariate polynomial ring @code{R}, the following members can be used. + +@table @code +@item cl_ring R->basering() +This returns the base ring, as passed to @samp{cl_find_univpoly_ring}. + +@item cl_UP R->zero() +This returns @code{0 in R}, a polynomial of degree -1. + +@item cl_UP R->one() +This returns @code{1 in R}, a polynomial of degree <= 0. + +@item cl_UP R->canonhom (const cl_I& x) +This returns @code{x in R}, a polynomial of degree <= 0. + +@item cl_UP R->monomial (const cl_ring_element& x, uintL e) +This returns a sparse polynomial: @code{x * X^e}, where @code{X} is the +indeterminate. + +@item cl_UP R->create (sintL degree) +Creates a new polynomial with a given degree. The zero polynomial has degree +@code{-1}. After creating the polynomial, you should put in the coefficients, +using the @code{set_coeff} member function, and then call the @code{finalize} +member function. +@end table + +The following are the only destructive operations on univariate polynomials. + +@table @code +@item void set_coeff (cl_UP& x, uintL index, const cl_ring_element& y) +This changes the coefficient of @code{X^index} in @code{x} to be @code{y}. +After changing a polynomial and before applying any "normal" operation on it, +you should call its @code{finalize} member function. + +@item void finalize (cl_UP& x) +This function marks the endpoint of destructive modifications of a polynomial. +It normalizes the internal representation so that subsequent computations have +less overhead. Doing normal computations on unnormalized polynomials may +produce wrong results or crash the program. +@end table + +The following operations are defined on univariate polynomials. + +@table @code +@item cl_univpoly_ring x.ring () +Returns the ring to which the univariate polynomial @code{x} belongs. + +@item cl_UP operator+ (const cl_UP&, const cl_UP&) +Returns the sum of two univariate polynomials. + +@item cl_UP operator- (const cl_UP&, const cl_UP&) +Returns the difference of two univariate polynomials. + +@item cl_UP operator- (const cl_UP&) +Returns the negative of a univariate polynomial. + +@item cl_UP operator* (const cl_UP&, const cl_UP&) +Returns the product of two univariate polynomials. One of the arguments may +also be a plain integer or an element of the base ring. + +@item cl_UP square (const cl_UP&) +Returns the square of a univariate polynomial. + +@item cl_UP expt_pos (const cl_UP& x, const cl_I& y) +@code{y} must be > 0. Returns @code{x^y}. + +@item bool operator== (const cl_UP&, const cl_UP&) +@itemx bool operator!= (const cl_UP&, const cl_UP&) +Compares two univariate polynomials, belonging to the same univariate +polynomial ring, for equality. + +@item cl_boolean zerop (const cl_UP& x) +Returns true if @code{x} is @code{0 in R}. + +@item sintL degree (const cl_UP& x) +Returns the degree of the polynomial. The zero polynomial has degree @code{-1}. + +@item cl_ring_element coeff (const cl_UP& x, uintL index) +Returns the coefficient of @code{X^index} in the polynomial @code{x}. + +@item cl_ring_element x (const cl_ring_element& y) +Evaluation: If @code{x} is a polynomial and @code{y} belongs to the base ring, +then @samp{x(y)} returns the value of the substitution of @code{y} into +@code{x}. + +@item cl_UP deriv (const cl_UP& x) +Returns the derivative of the polynomial @code{x} with respect to the +indeterminate @code{X}. +@end table + +The following output functions are defined (see also the chapter on +input/output). + +@table @code +@item void fprint (cl_ostream stream, const cl_UP& x) +@itemx cl_ostream operator<< (cl_ostream stream, const cl_UP& x) +Prints the univariate polynomial @code{x} on the @code{stream}. The output may +depend on the global printer settings in the variable +@code{cl_default_print_flags}. +@end table + +@section Special polynomials + +The following functions return special polynomials. + +@table @code +@item cl_UP_I cl_tschebychev (sintL n) +Returns the n-th Tchebychev polynomial (n >= 0). + +@item cl_UP_I cl_hermite (sintL n) +Returns the n-th Hermite polynomial (n >= 0). + +@item cl_UP_RA cl_legendre (sintL n) +Returns the n-th Legendre polynomial (n >= 0). + +@item cl_UP_I cl_laguerre (sintL n) +Returns the n-th Laguerre polynomial (n >= 0). +@end table + +Information how to derive the differential equation satisfied by each +of these polynomials from their definition can be found in the +@code{doc/polynomial/} directory. + + +@chapter Internals + +@section Why C++ ? + +Using C++ as an implementation language provides + +@itemize @bullet +@item +Efficiency: It compiles to machine code. + +@item +Portability: It runs on all platforms supporting a C++ compiler. Because +of the availability of GNU C++, this includes all currently used 32-bit and +64-bit platforms, independently of the quality of the vendor's C++ compiler. + +@item +Type safety: The C++ compilers knows about the number types and complains if, +for example, you try to assign a float to an integer variable. However, +a drawback is that C++ doesn't know about generic types, hence a restriction +like that @code{operation+ (const cl_MI&, const cl_MI&)} requires that both +arguments belong to the same modular ring cannot be expressed as a compile-time +information. + +@item +Algebraic syntax: The elementary operations @code{+}, @code{-}, @code{*}, +@code{=}, @code{==}, ... can be used in infix notation, which is more +convenient than Lisp notation @samp{(+ x y)} or C notation @samp{add(x,y,&z)}. +@end itemize + +With these language features, there is no need for two separate languages, +one for the implementation of the library and one in which the library's users +can program. This means that a prototype implementation of an algorithm +can be integrated into the library immediately after it has been tested and +debugged. No need to rewrite it in a low-level language after having prototyped +in a high-level language. + + +@section Memory efficiency + +In order to save memory allocations, CLN implements: + +@itemize @bullet +@item +Object sharing: An operation like @code{x+0} returns @code{x} without copying +it. +@item +Garbage collection: A reference counting mechanism makes sure that any +number object's storage is freed immediately when the last reference to the +object is gone. +@item +Small integers are represented as immediate values instead of pointers +to heap allocated storage. This means that integers @code{> -2^29}, +@code{< 2^29} don't consume heap memory, unless they were explicitly allocated +on the heap. +@end itemize + + +@section Speed efficiency + +Speed efficiency is obtained by the combination of the following tricks +and algorithms: + +@itemize @bullet +@item +Small integers, being represented as immediate values, don't require +memory access, just a couple of instructions for each elementary operation. +@item +The kernel of CLN has been written in assembly language for some CPUs +(@code{i386}, @code{m68k}, @code{sparc}, @code{mips}, @code{arm}). +@item +On all CPUs, CLN uses the superefficient low-level routines from GNU +GMP version 2. +@item +For large numbers, CLN uses, instead of the standard @code{O(N^2)} +algorithm, the Karatsuba multiplication, which is an +@iftex +@tex +$O(N^{1.6})$ +@end tex +@end iftex +@ifinfo +@code{O(N^1.6)} +@end ifinfo +algorithm. +@item +For very large numbers (more than 12000 decimal digits), CLN uses +@iftex +Sch{@"o}nhage-Strassen +@end iftex +@ifinfo +Schönhage-Strassen +@end ifinfo +multiplication, which is an asymptotically +optimal multiplication algorithm. +@item +These fast multiplication algorithms also give improvements in the speed +of division and radix conversion. +@end itemize + + +@section Garbage collection + +All the number classes are reference count classes: They only contain a pointer +to an object in the heap. Upon construction, assignment and destruction of +number objects, only the objects' reference count are manipulated. + +Memory occupied by number objects are automatically reclaimed as soon as +their reference count drops to zero. + +For number rings, another strategy is implemented: There is a cache of, +for example, the modular integer rings. A modular integer ring is destroyed +only if its reference count dropped to zero and the cache is about to be +resized. The effect of this strategy is that recently used rings remain +cached, whereas undue memory consumption through cached rings is avoided. + + +@chapter Using the library + +For the following discussion, we will assume that you have installed +the CLN source in @code{$CLN_DIR} and built it in @code{$CLN_TARGETDIR}. +For example, for me it's @code{CLN_DIR="$HOME/cln"} and +@code{CLN_TARGETDIR="$HOME/cln/linuxelf"}. You might define these as +environment variables, or directly substitute the appropriate values. + + +@section Compiler options + +Until you have installed CLN in a public place, the following options are +needed: + +When you compile CLN application code, add the flags +@example + -I$CLN_DIR/include -I$CLN_TARGETDIR/include +@end example +to the C++ compiler's command line (@code{make} variable CFLAGS or CXXFLAGS). +When you link CLN application code to form an executable, add the flags +@example + $CLN_TARGETDIR/src/libcln.a +@end example +to the C/C++ compiler's command line (@code{make} variable LIBS). + +If you did a @code{make install}, the include files are installed in a +public directory (normally @code{/usr/local/include}), hence you don't +need special flags for compiling. The library has been installed to a +public directory as well (normally @code{/usr/local/lib}), hence when +linking a CLN application it is sufficient to give the flag @code{-lcln}. + + +@section Include files + +Here is a summary of the include files and their contents. + +@table @code +@item +General definitions, reference counting, garbage collection. +@item +The class cl_number. +@item +Functions for class cl_N, the complex numbers. +@item +Functions for class cl_R, the real numbers. +@item +Functions for class cl_F, the floats. +@item +Functions for class cl_SF, the short-floats. +@item +Functions for class cl_FF, the single-floats. +@item +Functions for class cl_DF, the double-floats. +@item +Functions for class cl_LF, the long-floats. +@item +Functions for class cl_RA, the rational numbers. +@item +Functions for class cl_I, the integers. +@item +Input/Output. +@item +Input/Output for class cl_N, the complex numbers. +@item +Input/Output for class cl_R, the real numbers. +@item +Input/Output for class cl_F, the floats. +@item +Input/Output for class cl_SF, the short-floats. +@item +Input/Output for class cl_FF, the single-floats. +@item +Input/Output for class cl_DF, the double-floats. +@item +Input/Output for class cl_LF, the long-floats. +@item +Input/Output for class cl_RA, the rational numbers. +@item +Input/Output for class cl_I, the integers. +@item +Flags for customizing input operations. +@item +Flags for customizing output operations. +@item +@code{cl_malloc_hook}, @code{cl_free_hook}. +@item +@code{cl_abort}. +@item +Conditions/exceptions. +@item +Strings. +@item +Symbols. +@item +Property lists. +@item +General rings. +@item +The null ring. +@item +The ring of complex numbers. +@item +The ring of real numbers. +@item +The ring of rational numbers. +@item +The ring of integers. +@item +Number threory functions. +@item +Modular integers. +@item +Vectors. +@item +General vectors. +@item +General vectors over cl_number. +@item +General vectors over cl_N. +@item +General vectors over cl_R. +@item +General vectors over cl_RA. +@item +General vectors over cl_I. +@item +General vectors of modular integers. +@item +Simple vectors. +@item +Simple vectors over cl_number. +@item +Simple vectors over cl_N. +@item +Simple vectors over cl_R. +@item +Simple vectors over cl_RA. +@item +Simple vectors over cl_I. +@item +Simple vectors of general ring elements. +@item +Univariate polynomials. +@item +Univariate polynomials over the integers. +@item +Univariate polynomials over the rational numbers. +@item +Univariate polynomials over the real numbers. +@item +Univariate polynomials over the complex numbers. +@item +Univariate polynomials over modular integer rings. +@item +Timing facilities. +@item +Includes all of the above. +@end table + + +@section An Example + +A function which computes the nth Fibonacci number can be written as follows. + +@example +#include +#include + +// Returns F_n, computed as the nearest integer to +// ((1+sqrt(5))/2)^n/sqrt(5). Assume n>=0. +const cl_I fibonacci (int n) +@{ + // Need a precision of ((1+sqrt(5))/2)^-n. + cl_float_format_t prec = cl_float_format((int)(0.208987641*n+5)); + cl_R sqrt5 = sqrt(cl_float(5,prec)); + cl_R phi = (1+sqrt5)/2; + return round1( expt(phi,n)/sqrt5 ); +@} +@end example + +Let's explain what is going on in detail. + +The include file @code{} is necessary because the type +@code{cl_I} is used in the function, and the include file @code{} +is needed for the type @code{cl_R} and the floating point number functions. +The order of the include files does not matter. + +Then comes the function declaration. The argument is an @code{int}, the +result an integer. The return type is defined as @samp{const cl_I}, not +simply @samp{cl_I}, because that allows the compiler to detect typos like +@samp{fibonacci(n) = 100}. It would be possible to declare the return +type as @code{const cl_R} (real number) or even @code{const cl_N} (complex +number). We use the most specialized possible return type because functions +which call @samp{fibonacci} will be able to profit from the compiler's type +analysis: Adding two integers is slightly more efficient than adding the +same objects declared as complex numbers, because it needs less type +dispatch. Also, when linking to CLN as a non-shared library, this minimizes +the size of the resulting executable program. + +The result will be computed as expt(phi,n)/sqrt(5), rounded to the nearest +integer. In order to get a correct result, the absolute error should be less +than 1/2, i.e. the relative error should be less than sqrt(5)/(2*expt(phi,n)). +To this end, the first line computes a floating point precision for sqrt(5) +and phi. + +Then sqrt(5) is computed by first converting the integer 5 to a floating point +number and than taking the square root. The converse, first taking the square +root of 5, and then converting to the desired precision, would not work in +CLN: The square root would be computed to a default precision (normally +single-float precision), and the following conversion could not help about +the lacking accuracy. This is because CLN is not a symbolic computer algebra +system and does not represent sqrt(5) in a non-numeric way. + +The type @code{cl_R} for sqrt5 and, in the following line, phi is the only +possible choice. You cannot write @code{cl_F} because the C++ compiler can +only infer that @code{cl_float(5,prec)} is a real number. You cannot write +@code{cl_N} because a @samp{round1} does not exist for general complex +numbers. + +When the function returns, all the local variables in the function are +automatically reclaimed (garbage collected). Only the result survives and +gets passed to the caller. + + +@section Debugging support + +When debugging a CLN application with GNU @code{gdb}, two facilities are +available from the library: + +@itemize @bullet +@item The library does type checks, range checks, consistency checks at +many places. When one of these fails, the function @code{cl_abort()} is +called. Its default implementation is to perform an @code{exit(1)}, so +you won't have a core dump. But for debugging, it is best to set a +breakpoint at this function: +@example +(gdb) break cl_abort +@end example +When this breakpoint is hit, look at the stack's backtrace: +@example +(gdb) where +@end example + +@item The debugger's normal @code{print} command doesn't know about +CLN's types and therefore prints mostly useless hexadecimal addresses. +CLN offers a function @code{cl_print}, callable from the debugger, +for printing number objects. In order to get this function, you have +to define the macro @samp{CL_DEBUG} and then include all the header files +for which you want @code{cl_print} debugging support. For example: +@example +#define CL_DEBUG +#include +@end example +Now, if you have in your program a variable @code{cl_string s}, and +inspect it under @code{gdb}, the output may look like this: +@example +(gdb) print s +$7 = @{ = @{ = @{pointer = 0x8055b60, heappointer = 0x8055b60, + word = 134568800@}@}, @} +(gdb) call cl_print(s) +(cl_string) "" +$8 = 134568800 +@end example +Note that the output of @code{cl_print} goes to the program's error output, +not to gdb's standard output. + +Note, however, that the above facility does not work with all CLN types, +only with number objects and similar. Therefore CLN offers a member function +@code{debug_print()} on all CLN types. The same macro @samp{CL_DEBUG} +is needed for this member function to be implemented. Under @code{gdb}, +you call it like this: +@example +(gdb) print s +$7 = @{ = @{ = @{pointer = 0x8055b60, heappointer = 0x8055b60, + word = 134568800@}@}, @} +(gdb) call s.debug_print() +(cl_string) "" +(gdb) define cprint +>call ($1).debug_print() +>end +(gdb) cprint s +(cl_string) "" +@end example +Unfortunately, this feature does not seem to work under all circumstances. +@end itemize + + +@chapter Customizing + +@section Error handling + +When a fatal error occurs, an error message is output to the standard error +output stream, and the function @code{cl_abort} is called. The default +version of this function (provided in the library) terminates the application. +To catch such a fatal error, you need to define the function @code{cl_abort} +yourself, with the prototype +@example +#include +void cl_abort (void); +@end example +This function must not return control to its caller. + + +@section Floating-point underflow + +Floating point underflow denotes the situation when a floating-point number +is to be created which is so close to @code{0} that its exponent is too +low to be represented internally. By default, this causes a fatal error. +If you set the global variable +@example +cl_boolean cl_inhibit_floating_point_underflow +@end example +to @code{cl_true}, the error will be inhibited, and a floating-point zero +will be generated instead. +The default value of @code{cl_inhibit_floating_point_underflow} is +@code{cl_false}. + + +@section Customizing I/O + +The output of the function @code{fprint} may be customized by changing the +value of the global variable @code{cl_default_print_flags}. + + +@section Customizing the memory allocator + +Every memory allocation of CLN is done through the function pointer +@code{cl_malloc_hook}. Freeing of this memory is done through the function +pointer @code{cl_free_hook}. The default versions of these functions, +provided in the library, call @code{malloc} and @code{free} and check +the @code{malloc} result against @code{NULL}. +If you want to provide another memory allocator, you need to define +the variables @code{cl_malloc_hook} and @code{cl_free_hook} yourself, +like this: +@example +#include +void* (*cl_malloc_hook) (size_t size) = @dots{}; +void (*cl_free_hook) (void* ptr) = @dots{}; +@end example +The @code{cl_malloc_hook} function must not return a @code{NULL} pointer. + +It is not possible to change the memory allocator at runtime, because +it is already called at program startup by the constructors of some +global variables. + + + + +@c Indices + +@unnumbered Index + +@printindex my + + +@c Table of contents +@contents + + +@bye diff --git a/doc/cln.texi b/doc/cln.texi new file mode 100644 index 0000000..5f89fc2 --- /dev/null +++ b/doc/cln.texi @@ -0,0 +1,3665 @@ +\input texinfo @c -*-texinfo-*- +@c %**start of header +@setfilename cln.info +@settitle CLN, a Class Library for Numbers +@c @setchapternewpage off +@c For `info' only. +@paragraphindent 0 +@c For TeX only. +@iftex +@c I hate putting "@noindent" in front of every paragraph. +@parindent=0pt +@end iftex +@c %**end of header + + +@c My own index. +@defindex my +@c Don't need the other types of indices. +@synindex cp my +@synindex fn my +@synindex vr my +@synindex ky my +@synindex pg my +@synindex tp my + + +@c For `info' only. +@ifinfo +This file documents @sc{cln}, a Class Library for Numbers. + +Published by Bruno Haible, @code{} and +Richard Kreckel, @code{}. + +Copyright (C) Bruno Haible 1995, 1996, 1997, 1998, 1999, 2000. + +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 author. +@end ifinfo + + +@c For TeX only. +@c prevent ugly black rectangles on overfull hbox lines: +@finalout +@titlepage +@title CLN, a Class Library for Numbers + +@author by Bruno Haible +@page +@vskip 0pt plus 1filll +Copyright @copyright{} Bruno Haible 1995, 1996, 1997, 1998, 1999, 2000. + +@sp 2 +Published by Bruno Haible, @code{} and +Richard Kreckel, @code{}. + +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 author. + +@end titlepage +@page + + +@node Top, Introduction, (dir), (dir) + +@c @menu +@c * Introduction:: Introduction +@c @end menu + +@menu +* Introduction:: +* Installation:: +* Ordinary number types:: +* Functions on numbers:: +* Input/Output:: +* Rings:: +* Modular integers:: +* Symbolic data types:: +* Univariate polynomials:: +* Internals:: +* Using the library:: +* Customizing:: +* Index:: + + --- The Detailed Node Listing --- + +Installation + +* Prerequisites:: +* Building the library:: +* Installing the library:: +* Cleaning up:: + +Prerequisites + +* C++ compiler:: +* Make utility:: +* Sed utility:: + +Ordinary number types + +* Exact numbers:: +* Floating-point numbers:: +* Complex numbers:: +* Conversions:: + +Functions on numbers + +* Constructing numbers:: +* Elementary functions:: +* Elementary rational functions:: +* Elementary complex functions:: +* Comparisons:: +* Rounding functions:: +* Roots:: +* Transcendental functions:: +* Functions on integers:: +* Functions on floating-point numbers:: +* Conversion functions:: +* Random number generators:: +* Obfuscating operators:: + +Constructing numbers + +* Constructing integers:: +* Constructing rational numbers:: +* Constructing floating-point numbers:: +* Constructing complex numbers:: + +Transcendental functions + +* Exponential and logarithmic functions:: +* Trigonometric functions:: +* Hyperbolic functions:: +* Euler gamma:: +* Riemann zeta:: + +Functions on integers + +* Logical functions:: +* Number theoretic functions:: +* Combinatorial functions:: + +Conversion functions + +* Conversion to floating-point numbers:: +* Conversion to rational numbers:: + +Input/Output + +* Internal and printed representation:: +* Input functions:: +* Output functions:: + +Modular integers + +* Modular integer rings:: +* Functions on modular integers:: + +Symbolic data types + +* Strings:: +* Symbols:: + +Univariate polynomials + +* Univariate polynomial rings:: +* Functions on univariate polynomials:: +* Special polynomials:: + +Internals + +* Why C++ ?:: +* Memory efficiency:: +* Speed efficiency:: +* Garbage collection:: + +Using the library + +* Compiler options:: +* Include files:: +* An Example:: +* Debugging support:: + +Customizing + +* Error handling:: +* Floating-point underflow:: +* Customizing I/O:: +* Customizing the memory allocator:: +@end menu + +@node Introduction, Installation, Top, Top +@comment node-name, next, previous, up +@chapter Introduction + +@noindent +CLN is a library for computations with all kinds of numbers. +It has a rich set of number classes: + +@itemize @bullet +@item +Integers (with unlimited precision), + +@item +Rational numbers, + +@item +Floating-point numbers: + +@itemize @minus +@item +Short float, +@item +Single float, +@item +Double float, +@item +Long float (with unlimited precision), +@end itemize + +@item +Complex numbers, + +@item +Modular integers (integers modulo a fixed integer), + +@item +Univariate polynomials. +@end itemize + +@noindent +The subtypes of the complex numbers among these are exactly the +types of numbers known to the Common Lisp language. Therefore +@code{CLN} can be used for Common Lisp implementations, giving +@samp{CLN} another meaning: it becomes an abbreviation of +``Common Lisp Numbers''. + +@noindent +The CLN package implements + +@itemize @bullet +@item +Elementary functions (@code{+}, @code{-}, @code{*}, @code{/}, @code{sqrt}, +comparisons, @dots{}), + +@item +Logical functions (logical @code{and}, @code{or}, @code{not}, @dots{}), + +@item +Transcendental functions (exponential, logarithmic, trigonometric, hyperbolic +functions and their inverse functions). +@end itemize + +@noindent +CLN is a C++ library. Using C++ as an implementation language provides + +@itemize @bullet +@item +efficiency: it compiles to machine code, +@item +type safety: the C++ compiler knows about the number types and complains +if, for example, you try to assign a float to an integer variable. +@item +algebraic syntax: You can use the @code{+}, @code{-}, @code{*}, @code{=}, +@code{==}, @dots{} operators as in C or C++. +@end itemize + +@noindent +CLN is memory efficient: + +@itemize @bullet +@item +Small integers and short floats are immediate, not heap allocated. +@item +Heap-allocated memory is reclaimed through an automatic, non-interruptive +garbage collection. +@end itemize + +@noindent +CLN is speed efficient: + +@itemize @bullet +@item +The kernel of CLN has been written in assembly language for some CPUs +(@code{i386}, @code{m68k}, @code{sparc}, @code{mips}, @code{arm}). +@item +On all CPUs, CLN uses the superefficient low-level routines from GNU +GMP version 2. +@item +It uses Karatsuba multiplication, which is significantly faster +for large numbers than the standard multiplication algorithm. +@item +For very large numbers (more than 12000 decimal digits), it uses +@iftex +Sch{@"o}nhage-Strassen +@end iftex +@ifinfo +Schönhage-Strassen +@end ifinfo +multiplication, which is an asymptotically +optimal multiplication algorithm, for multiplication, division and +radix conversion. +@end itemize + +@noindent +CLN aims at being easily integrated into larger software packages: + +@itemize @bullet +@item +The garbage collection imposes no burden on the main application. +@item +The library provides hooks for memory allocation and exceptions. +@end itemize + + +@node Installation, Ordinary number types, Introduction, Top +@chapter Installation + +This section describes how to install the CLN package on your system. + + +@menu +* Prerequisites:: +* Building the library:: +* Installing the library:: +* Cleaning up:: +@end menu + +@node Prerequisites, Building the library, Installation, Installation +@section Prerequisites + +@menu +* C++ compiler:: +* Make utility:: +* Sed utility:: +@end menu + +@node C++ compiler, Make utility, Prerequisites, Prerequisites +@subsection C++ compiler + +To build CLN, you need a C++ compiler. +Actually, you need GNU @code{g++ 2.7.0} or newer. +On HPPA, you need GNU @code{g++ 2.8.0} or newer. +I recommend GNU @code{egcs 1.1} or newer. + +The following C++ features are used: +classes, member functions, +overloading of functions and operators, +constructors and destructors, inline, const, +multiple inheritance, templates. + +The following C++ features are not used: +@code{new}, @code{delete}, virtual inheritance, +exceptions. + +CLN relies on semi-automatic ordering of initializations +of static and global variables, a feature which I could +implement for GNU g++ only. + +@ignore +@comment cl_modules.h requires g++ +Therefore nearly any C++ compiler will do. + +The following C++ compilers are known to compile CLN: +@itemize @minus +@item +GNU @code{g++ 2.7.0}, @code{g++ 2.7.2} +@item +SGI @code{CC 4} +@end itemize + +The following C++ compilers are known to be unusable for CLN: +@itemize @minus +@item +On SunOS 4, @code{CC 2.1}, because it doesn't grok @code{//} comments +in lines containing @code{#if} or @code{#elif} preprocessor commands. +@item +On AIX 3.2.5, @code{xlC}, because it doesn't grok the template syntax +in @code{cl_SV.h} and @code{cl_GV.h}, because it forces most class types +to have default constructors, and because it probably miscompiles the +integer multiplication routines. +@item +On AIX 4.1.4.0, @code{xlC}, because when optimizing, it sometimes converts +@code{short}s to @code{int}s by zero-extend. +@item +GNU @code{g++ 2.5.8} +@item +On HPPA, GNU @code{g++ 2.7.x}, because the semi-automatic ordering of +initializations will not work. +@end itemize +@end ignore + +@node Make utility, Sed utility, C++ compiler, Prerequisites +@subsection Make utility + +To build CLN, you also need to have GNU @code{make} installed. + +@node Sed utility, , Make utility, Prerequisites +@subsection Sed utility + +To build CLN on HP-UX, you also need to have GNU @code{sed} installed. +This is because the libtool script, which creates the CLN library, relies +on @code{sed}, and the vendor's @code{sed} utility on these systems is too +limited. + + +@node Building the library, Installing the library, Prerequisites, Installation +@section Building the library + +As with any autoconfiguring GNU software, installation is as easy as this: + +@example +$ ./configure +$ make +$ make check +@end example + +If on your system, @samp{make} is not GNU @code{make}, you have to use +@samp{gmake} instead of @samp{make} above. + +The @code{configure} command checks out some features of your system and +C++ compiler and builds the @code{Makefile}s. The @code{make} command +builds the library. This step may take 4 hours on an average workstation. +The @code{make check} runs some test to check that no important subroutine +has been miscompiled. + +The @code{configure} command accepts options. To get a summary of them, try + +@example +$ ./configure --help +@end example + +Some of the options are explained in detail in the @samp{INSTALL.generic} file. + +You can specify the C compiler, the C++ compiler and their options through +the following environment variables when running @code{configure}: + +@table @code +@item CC +Specifies the C compiler. + +@item CFLAGS +Flags to be given to the C compiler when compiling programs (not when linking). + +@item CXX +Specifies the C++ compiler. + +@item CXXFLAGS +Flags to be given to the C++ compiler when compiling programs (not when linking). +@end table + +Examples: + +@example +$ CC="gcc" CFLAGS="-O" CXX="g++" CXXFLAGS="-O" ./configure +$ CC="gcc -V 2.7.2" CFLAGS="-O -g" \ + CXX="g++ -V 2.7.2" CXXFLAGS="-O -g" ./configure +$ CC="gcc -V 2.8.1" CFLAGS="-O -fno-exceptions" \ + CXX="g++ -V 2.8.1" CXXFLAGS="-O -fno-exceptions" ./configure +$ CC="gcc -V egcs-2.91.60" CFLAGS="-O2 -fno-exceptions" \ + CXX="g++ -V egcs-2.91.60" CFLAGS="-O2 -fno-exceptions" ./configure +@end example +@ignore +@comment cl_modules.h requires g++ +You should not mix GNU and non-GNU compilers. So, if @code{CXX} is a non-GNU +compiler, @code{CC} should be set to a non-GNU compiler as well. Examples: + +@example +$ CC="cc" CFLAGS="-O" CXX="CC" CXXFLAGS="-O" ./configure +$ CC="gcc -V 2.7.0" CFLAGS="-g" CXX="g++ -V 2.7.0" CXXFLAGS="-g" ./configure +@end example + +On SGI Irix 5, if you wish not to use @code{g++}: + +@example +$ CC="cc" CFLAGS="-O" CXX="CC" CXXFLAGS="-O -Olimit 16000" ./configure +@end example + +On SGI Irix 6, if you wish not to use @code{g++}: + +@example +$ CC="cc -32" CFLAGS="-O" CXX="CC -32" CXXFLAGS="-O -Olimit 34000" \ + ./configure --without-gmp +$ CC="cc -n32" CFLAGS="-O" CXX="CC -n32" CXXFLAGS="-O \ + -OPT:const_copy_limit=32400 -OPT:global_limit=32400 -OPT:fprop_limit=4000" \ + ./configure --without-gmp +@end example +@end ignore + +Note that for these environment variables to take effect, you have to set +them (assuming a Bourne-compatible shell) on the same line as the +@code{configure} command. If you made the settings in earlier shell +commands, you have to @code{export} the environment variables before +calling @code{configure}. In a @code{csh} shell, you have to use the +@samp{setenv} command for setting each of the environment variables. + +On Linux, @code{g++} needs 15 MB to compile the tests. So you should better +have 17 MB swap space and 1 MB room in $TMPDIR. + +If you use @code{g++} version 2.7.x, don't add @samp{-O2} to the CXXFLAGS, +because @samp{g++ -O} generates better code for CLN than @samp{g++ -O2}. + +If you use @code{g++} version 2.8.x or egcs-2.91.x (a.k.a. egcs-1.1) or +gcc-2.95.x, I recommend adding @samp{-fno-exceptions} to the CXXFLAGS. +This will likely generate better code. + +If you use @code{g++} version egcs-2.91.x (egcs-1.1) or gcc-2.95.x on Sparc, +add either @samp{-O} or @samp{-O2 -fno-schedule-insns} to the CXXFLAGS. +With full @samp{-O2}, @code{g++} miscompiles the division routines. Also, for +--enable-shared to work, you need egcs-1.1.2 or newer. + +On MIPS (SGI Irix 6), pass option @code{--without-gmp} to configure. gmp does +not work when compiled in @samp{n32} binary format on Irix. + +By default, only a static library is built. You can build CLN as a shared +library too, by calling @code{configure} with the option @samp{--enable-shared}. +To get it built as a shared library only, call @code{configure} with the options +@samp{--enable-shared --disable-static}. + +If you use @code{g++} version egcs-2.91.x (egcs-1.1) on Sparc, you cannot +use @samp{--enable-shared} because @code{g++} would miscompile parts of the +library. + + +@node Installing the library, Cleaning up, Building the library, Installation +@section Installing the library + +As with any autoconfiguring GNU software, installation is as easy as this: + +@example +$ make install +@end example + +The @samp{make install} command installs the library and the include files +into public places (@file{/usr/local/lib/} and @file{/usr/local/include/}, +if you haven't specified a @code{--prefix} option to @code{configure}). +This step may require superuser privileges. + +If you have already built the library and wish to install it, but didn't +specify @code{--prefix=@dots{}} at configure time, just re-run +@code{configure}, giving it the same options as the first time, plus +the @code{--prefix=@dots{}} option. + + +@node Cleaning up, , Installing the library, Installation +@section Cleaning up + +You can remove system-dependent files generated by @code{make} through + +@example +$ make clean +@end example + +You can remove all files generated by @code{make}, thus reverting to a +virgin distribution of CLN, through + +@example +$ make distclean +@end example + + +@node Ordinary number types, Functions on numbers, Installation, Top +@chapter Ordinary number types + +CLN implements the following class hierarchy: + +@example + Number + cl_number + + | + | + Real or complex number + cl_N + + | + | + Real number + cl_R + + | + +-------------------+-------------------+ + | | +Rational number Floating-point number + cl_RA cl_F + + | | + | +-------------+-------------+-------------+ + Integer | | | | + cl_I Short-Float Single-Float Double-Float Long-Float + cl_SF cl_FF cl_DF cl_LF + +@end example + +The base class @code{cl_number} is an abstract base class. +It is not useful to declare a variable of this type except if you want +to completely disable compile-time type checking and use run-time type +checking instead. + +The class @code{cl_N} comprises real and complex numbers. There is +no special class for complex numbers since complex numbers with imaginary +part @code{0} are automatically converted to real numbers. + +The class @code{cl_R} comprises real numbers of different kinds. It is an +abstract class. + +The class @code{cl_RA} comprises exact real numbers: rational numbers, including +integers. There is no special class for non-integral rational numbers +since rational numbers with denominator @code{1} are automatically converted +to integers. + +The class @code{cl_F} implements floating-point approximations to real numbers. +It is an abstract class. + + +@menu +* Exact numbers:: +* Floating-point numbers:: +* Complex numbers:: +* Conversions:: +@end menu + +@node Exact numbers, Floating-point numbers, Ordinary number types, Ordinary number types +@section Exact numbers + +Some numbers are represented as exact numbers: there is no loss of information +when such a number is converted from its mathematical value to its internal +representation. On exact numbers, the elementary operations (@code{+}, +@code{-}, @code{*}, @code{/}, comparisons, @dots{}) compute the completely +correct result. + +In CLN, the exact numbers are: + +@itemize @bullet +@item +rational numbers (including integers), +@item +complex numbers whose real and imaginary parts are both rational numbers. +@end itemize + +Rational numbers are always normalized to the form +@code{@var{numerator}/@var{denominator}} where the numerator and denominator +are coprime integers and the denominator is positive. If the resulting +denominator is @code{1}, the rational number is converted to an integer. + +Small integers (typically in the range @code{-2^30}@dots{}@code{2^30-1}, +for 32-bit machines) are especially efficient, because they consume no heap +allocation. Otherwise the distinction between these immediate integers +(called ``fixnums'') and heap allocated integers (called ``bignums'') +is completely transparent. + + +@node Floating-point numbers, Complex numbers, Exact numbers, Ordinary number types +@section Floating-point numbers + +Not all real numbers can be represented exactly. (There is an easy mathematical +proof for this: Only a countable set of numbers can be stored exactly in +a computer, even if one assumes that it has unlimited storage. But there +are uncountably many real numbers.) So some approximation is needed. +CLN implements ordinary floating-point numbers, with mantissa and exponent. + +The elementary operations (@code{+}, @code{-}, @code{*}, @code{/}, @dots{}) +only return approximate results. For example, the value of the expression +@code{(cl_F) 0.3 + (cl_F) 0.4} prints as @samp{0.70000005}, not as +@samp{0.7}. Rounding errors like this one are inevitable when computing +with floating-point numbers. + +Nevertheless, CLN rounds the floating-point results of the operations @code{+}, +@code{-}, @code{*}, @code{/}, @code{sqrt} according to the ``round-to-even'' +rule: It first computes the exact mathematical result and then returns the +floating-point number which is nearest to this. If two floating-point numbers +are equally distant from the ideal result, the one with a @code{0} in its least +significant mantissa bit is chosen. + +Similarly, testing floating point numbers for equality @samp{x == y} +is gambling with random errors. Better check for @samp{abs(x - y) < epsilon} +for some well-chosen @code{epsilon}. + +Floating point numbers come in four flavors: + +@itemize @bullet +@item +Short floats, type @code{cl_SF}. +They have 1 sign bit, 8 exponent bits (including the exponent's sign), +and 17 mantissa bits (including the ``hidden'' bit). +They don't consume heap allocation. + +@item +Single floats, type @code{cl_FF}. +They have 1 sign bit, 8 exponent bits (including the exponent's sign), +and 24 mantissa bits (including the ``hidden'' bit). +In CLN, they are represented as IEEE single-precision floating point numbers. +This corresponds closely to the C/C++ type @samp{float}. + +@item +Double floats, type @code{cl_DF}. +They have 1 sign bit, 11 exponent bits (including the exponent's sign), +and 53 mantissa bits (including the ``hidden'' bit). +In CLN, they are represented as IEEE double-precision floating point numbers. +This corresponds closely to the C/C++ type @samp{double}. + +@item +Long floats, type @code{cl_LF}. +They have 1 sign bit, 32 exponent bits (including the exponent's sign), +and n mantissa bits (including the ``hidden'' bit), where n >= 64. +The precision of a long float is unlimited, but once created, a long float +has a fixed precision. (No ``lazy recomputation''.) +@end itemize + +Of course, computations with long floats are more expensive than those +with smaller floating-point formats. + +CLN does not implement features like NaNs, denormalized numbers and +gradual underflow. If the exponent range of some floating-point type +is too limited for your application, choose another floating-point type +with larger exponent range. + +As a user of CLN, you can forget about the differences between the +four floating-point types and just declare all your floating-point +variables as being of type @code{cl_F}. This has the advantage that +when you change the precision of some computation (say, from @code{cl_DF} +to @code{cl_LF}), you don't have to change the code, only the precision +of the initial values. Also, many transcendental functions have been +declared as returning a @code{cl_F} when the argument is a @code{cl_F}, +but such declarations are missing for the types @code{cl_SF}, @code{cl_FF}, +@code{cl_DF}, @code{cl_LF}. (Such declarations would be wrong if +the floating point contagion rule happened to change in the future.) + + +@node Complex numbers, Conversions, Floating-point numbers, Ordinary number types +@section Complex numbers + +Complex numbers, as implemented by the class @code{cl_N}, have a real +part and an imaginary part, both real numbers. A complex number whose +imaginary part is the exact number @code{0} is automatically converted +to a real number. + +Complex numbers can arise from real numbers alone, for example +through application of @code{sqrt} or transcendental functions. + + +@node Conversions, , Complex numbers, Ordinary number types +@section Conversions + +Conversions from any class to any its superclasses (``base classes'' in +C++ terminology) is done automatically. + +Conversions from the C built-in types @samp{long} and @samp{unsigned long} +are provided for the classes @code{cl_I}, @code{cl_RA}, @code{cl_R}, +@code{cl_N} and @code{cl_number}. + +Conversions from the C built-in types @samp{int} and @samp{unsigned int} +are provided for the classes @code{cl_I}, @code{cl_RA}, @code{cl_R}, +@code{cl_N} and @code{cl_number}. However, these conversions emphasize +efficiency. Their range is therefore limited: + +@itemize @minus +@item +The conversion from @samp{int} works only if the argument is < 2^29 and > -2^29. +@item +The conversion from @samp{unsigned int} works only if the argument is < 2^29. +@end itemize + +In a declaration like @samp{cl_I x = 10;} the C++ compiler is able to +do the conversion of @code{10} from @samp{int} to @samp{cl_I} at compile time +already. On the other hand, code like @samp{cl_I x = 1000000000;} is +in error. +So, if you want to be sure that an @samp{int} whose magnitude is not guaranteed +to be < 2^29 is correctly converted to a @samp{cl_I}, first convert it to a +@samp{long}. Similarly, if a large @samp{unsigned int} is to be converted to a +@samp{cl_I}, first convert it to an @samp{unsigned long}. + +Conversions from the C built-in type @samp{float} are provided for the classes +@code{cl_FF}, @code{cl_F}, @code{cl_R}, @code{cl_N} and @code{cl_number}. + +Conversions from the C built-in type @samp{double} are provided for the classes +@code{cl_DF}, @code{cl_F}, @code{cl_R}, @code{cl_N} and @code{cl_number}. + +Conversions from @samp{const char *} are provided for the classes +@code{cl_I}, @code{cl_RA}, +@code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF}, @code{cl_F}, +@code{cl_R}, @code{cl_N}. +The easiest way to specify a value which is outside of the range of the +C++ built-in types is therefore to specify it as a string, like this: +@example + cl_I order_of_rubiks_cube_group = "43252003274489856000"; +@end example +Note that this conversion is done at runtime, not at compile-time. + +Conversions from @code{cl_I} to the C built-in types @samp{int}, +@samp{unsigned int}, @samp{long}, @samp{unsigned long} are provided through +the functions + +@table @code +@item int cl_I_to_int (const cl_I& x) +@itemx unsigned int cl_I_to_uint (const cl_I& x) +@itemx long cl_I_to_long (const cl_I& x) +@itemx unsigned long cl_I_to_ulong (const cl_I& x) +Returns @code{x} as element of the C type @var{ctype}. If @code{x} is not +representable in the range of @var{ctype}, a runtime error occurs. +@end table + +Conversions from the classes @code{cl_I}, @code{cl_RA}, +@code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF}, @code{cl_F} and +@code{cl_R} +to the C built-in types @samp{float} and @samp{double} are provided through +the functions + +@table @code +@item float cl_float_approx (const @var{type}& x) +@itemx double cl_double_approx (const @var{type}& x) +Returns an approximation of @code{x} of C type @var{ctype}. +If @code{abs(x)} is too close to 0 (underflow), 0 is returned. +If @code{abs(x)} is too large (overflow), an IEEE infinity is returned. +@end table + +Conversions from any class to any of its subclasses (``derived classes'' in +C++ terminology) are not provided. Instead, you can assert and check +that a value belongs to a certain subclass, and return it as element of that +class, using the @samp{As} and @samp{The} macros. +@code{As(@var{type})(@var{value})} checks that @var{value} belongs to +@var{type} and returns it as such. +@code{The(@var{type})(@var{value})} assumes that @var{value} belongs to +@var{type} and returns it as such. It is your responsibility to ensure +that this assumption is valid. +Example: + +@example +@group + cl_I x = @dots{}; + if (!(x >= 0)) abort(); + cl_I ten_x = The(cl_I)(expt(10,x)); // If x >= 0, 10^x is an integer. + // In general, it would be a rational number. +@end group +@end example + + +@node Functions on numbers, Input/Output, Ordinary number types, Top +@chapter Functions on numbers + +Each of the number classes declares its mathematical operations in the +corresponding include file. For example, if your code operates with +objects of type @code{cl_I}, it should @code{#include }. + + +@menu +* Constructing numbers:: +* Elementary functions:: +* Elementary rational functions:: +* Elementary complex functions:: +* Comparisons:: +* Rounding functions:: +* Roots:: +* Transcendental functions:: +* Functions on integers:: +* Functions on floating-point numbers:: +* Conversion functions:: +* Random number generators:: +* Obfuscating operators:: +@end menu + +@node Constructing numbers, Elementary functions, Functions on numbers, Functions on numbers +@section Constructing numbers + +Here is how to create number objects ``from nothing''. + + +@menu +* Constructing integers:: +* Constructing rational numbers:: +* Constructing floating-point numbers:: +* Constructing complex numbers:: +@end menu + +@node Constructing integers, Constructing rational numbers, Constructing numbers, Constructing numbers +@subsection Constructing integers + +@code{cl_I} objects are most easily constructed from C integers and from +strings. See @ref{Conversions}. + + +@node Constructing rational numbers, Constructing floating-point numbers, Constructing integers, Constructing numbers +@subsection Constructing rational numbers + +@code{cl_RA} objects can be constructed from strings. The syntax +for rational numbers is described in @ref{Internal and printed representation}. +Another standard way to produce a rational number is through application +of @samp{operator /} or @samp{recip} on integers. + + +@node Constructing floating-point numbers, Constructing complex numbers, Constructing rational numbers, Constructing numbers +@subsection Constructing floating-point numbers + +@code{cl_F} objects with low precision are most easily constructed from +C @samp{float} and @samp{double}. See @ref{Conversions}. + +To construct a @code{cl_F} with high precision, you can use the conversion +from @samp{const char *}, but you have to specify the desired precision +within the string. (See @ref{Internal and printed representation}.) +Example: +@example + cl_F e = "0.271828182845904523536028747135266249775724709369996e+1_40"; +@end example +will set @samp{e} to the given value, with a precision of 40 decimal digits. + +The programmatic way to construct a @code{cl_F} with high precision is +through the @code{cl_float} conversion function, see +@ref{Conversion to floating-point numbers}. For example, to compute +@code{e} to 40 decimal places, first construct 1.0 to 40 decimal places +and then apply the exponential function: +@example + cl_float_format_t precision = cl_float_format(40); + cl_F e = exp(cl_float(1,precision)); +@end example + + +@node Constructing complex numbers, , Constructing floating-point numbers, Constructing numbers +@subsection Constructing complex numbers + +Non-real @code{cl_N} objects are normally constructed through the function +@example + cl_N complex (const cl_R& realpart, const cl_R& imagpart) +@end example +See @ref{Elementary complex functions}. + + +@node Elementary functions, Elementary rational functions, Constructing numbers, Functions on numbers +@section Elementary functions + +Each of the classes @code{cl_N}, @code{cl_R}, @code{cl_RA}, @code{cl_I}, +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines the following operations: + +@table @code +@item @var{type} operator + (const @var{type}&, const @var{type}&) +Addition. + +@item @var{type} operator - (const @var{type}&, const @var{type}&) +Subtraction. + +@item @var{type} operator - (const @var{type}&) +Returns the negative of the argument. + +@item @var{type} plus1 (const @var{type}& x) +Returns @code{x + 1}. + +@item @var{type} minus1 (const @var{type}& x) +Returns @code{x - 1}. + +@item @var{type} operator * (const @var{type}&, const @var{type}&) +Multiplication. + +@item @var{type} square (const @var{type}& x) +Returns @code{x * x}. +@end table + +Each of the classes @code{cl_N}, @code{cl_R}, @code{cl_RA}, +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines the following operations: + +@table @code +@item @var{type} operator / (const @var{type}&, const @var{type}&) +Division. + +@item @var{type} recip (const @var{type}&) +Returns the reciprocal of the argument. +@end table + +The class @code{cl_I} doesn't define a @samp{/} operation because +in the C/C++ language this operator, applied to integral types, +denotes the @samp{floor} or @samp{truncate} operation (which one of these, +is implementation dependent). (@xref{Rounding functions}) +Instead, @code{cl_I} defines an ``exact quotient'' function: + +@table @code +@item cl_I exquo (const cl_I& x, const cl_I& y) +Checks that @code{y} divides @code{x}, and returns the quotient @code{x}/@code{y}. +@end table + +The following exponentiation functions are defined: + +@table @code +@item cl_I expt_pos (const cl_I& x, const cl_I& y) +@itemx cl_RA expt_pos (const cl_RA& x, const cl_I& y) +@code{y} must be > 0. Returns @code{x^y}. + +@item cl_RA expt (const cl_RA& x, const cl_I& y) +@itemx cl_R expt (const cl_R& x, const cl_I& y) +@itemx cl_N expt (const cl_N& x, const cl_I& y) +Returns @code{x^y}. +@end table + +Each of the classes @code{cl_R}, @code{cl_RA}, @code{cl_I}, +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines the following operation: + +@table @code +@item @var{type} abs (const @var{type}& x) +Returns the absolute value of @code{x}. +This is @code{x} if @code{x >= 0}, and @code{-x} if @code{x <= 0}. +@end table + +The class @code{cl_N} implements this as follows: + +@table @code +@item cl_R abs (const cl_N x) +Returns the absolute value of @code{x}. +@end table + +Each of the classes @code{cl_N}, @code{cl_R}, @code{cl_RA}, @code{cl_I}, +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines the following operation: + +@table @code +@item @var{type} signum (const @var{type}& x) +Returns the sign of @code{x}, in the same number format as @code{x}. +This is defined as @code{x / abs(x)} if @code{x} is non-zero, and +@code{x} if @code{x} is zero. If @code{x} is real, the value is either +0 or 1 or -1. +@end table + + +@node Elementary rational functions, Elementary complex functions, Elementary functions, Functions on numbers +@section Elementary rational functions + +Each of the classes @code{cl_RA}, @code{cl_I} defines the following operations: + +@table @code +@item cl_I numerator (const @var{type}& x) +Returns the numerator of @code{x}. + +@item cl_I denominator (const @var{type}& x) +Returns the denominator of @code{x}. +@end table + +The numerator and denominator of a rational number are normalized in such +a way that they have no factor in common and the denominator is positive. + + +@node Elementary complex functions, Comparisons, Elementary rational functions, Functions on numbers +@section Elementary complex functions + +The class @code{cl_N} defines the following operation: + +@table @code +@item cl_N complex (const cl_R& a, const cl_R& b) +Returns the complex number @code{a+bi}, that is, the complex number with +real part @code{a} and imaginary part @code{b}. +@end table + +Each of the classes @code{cl_N}, @code{cl_R} defines the following operations: + +@table @code +@item cl_R realpart (const @var{type}& x) +Returns the real part of @code{x}. + +@item cl_R imagpart (const @var{type}& x) +Returns the imaginary part of @code{x}. + +@item @var{type} conjugate (const @var{type}& x) +Returns the complex conjugate of @code{x}. +@end table + +We have the relations + +@itemize @asis +@item +@code{x = complex(realpart(x), imagpart(x))} +@item +@code{conjugate(x) = complex(realpart(x), -imagpart(x))} +@end itemize + + +@node Comparisons, Rounding functions, Elementary complex functions, Functions on numbers +@section Comparisons + +Each of the classes @code{cl_N}, @code{cl_R}, @code{cl_RA}, @code{cl_I}, +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines the following operations: + +@table @code +@item bool operator == (const @var{type}&, const @var{type}&) +@itemx bool operator != (const @var{type}&, const @var{type}&) +Comparison, as in C and C++. + +@item uint32 cl_equal_hashcode (const @var{type}&) +Returns a 32-bit hash code that is the same for any two numbers which are +the same according to @code{==}. This hash code depends on the number's value, +not its type or precision. + +@item cl_boolean zerop (const @var{type}& x) +Compare against zero: @code{x == 0} +@end table + +Each of the classes @code{cl_R}, @code{cl_RA}, @code{cl_I}, +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines the following operations: + +@table @code +@item cl_signean cl_compare (const @var{type}& x, const @var{type}& y) +Compares @code{x} and @code{y}. Returns +1 if @code{x}>@code{y}, +-1 if @code{x}<@code{y}, 0 if @code{x}=@code{y}. + +@item bool operator <= (const @var{type}&, const @var{type}&) +@itemx bool operator < (const @var{type}&, const @var{type}&) +@itemx bool operator >= (const @var{type}&, const @var{type}&) +@itemx bool operator > (const @var{type}&, const @var{type}&) +Comparison, as in C and C++. + +@item cl_boolean minusp (const @var{type}& x) +Compare against zero: @code{x < 0} + +@item cl_boolean plusp (const @var{type}& x) +Compare against zero: @code{x > 0} + +@item @var{type} max (const @var{type}& x, const @var{type}& y) +Return the maximum of @code{x} and @code{y}. + +@item @var{type} min (const @var{type}& x, const @var{type}& y) +Return the minimum of @code{x} and @code{y}. +@end table + +When a floating point number and a rational number are compared, the float +is first converted to a rational number using the function @code{rational}. +Since a floating point number actually represents an interval of real numbers, +the result might be surprising. +For example, @code{(cl_F)(cl_R)"1/3" == (cl_R)"1/3"} returns false because +there is no floating point number whose value is exactly @code{1/3}. + + +@node Rounding functions, Roots, Comparisons, Functions on numbers +@section Rounding functions + +When a real number is to be converted to an integer, there is no ``best'' +rounding. The desired rounding function depends on the application. +The Common Lisp and ISO Lisp standards offer four rounding functions: + +@table @code +@item floor(x) +This is the largest integer <=@code{x}. + +@item ceiling(x) +This is the smallest integer >=@code{x}. + +@item truncate(x) +Among the integers between 0 and @code{x} (inclusive) the one nearest to @code{x}. + +@item round(x) +The integer nearest to @code{x}. If @code{x} is exactly halfway between two +integers, choose the even one. +@end table + +These functions have different advantages: + +@code{floor} and @code{ceiling} are translation invariant: +@code{floor(x+n) = floor(x) + n} and @code{ceiling(x+n) = ceiling(x) + n} +for every @code{x} and every integer @code{n}. + +On the other hand, @code{truncate} and @code{round} are symmetric: +@code{truncate(-x) = -truncate(x)} and @code{round(-x) = -round(x)}, +and furthermore @code{round} is unbiased: on the ``average'', it rounds +down exactly as often as it rounds up. + +The functions are related like this: + +@itemize @asis +@item +@code{ceiling(m/n) = floor((m+n-1)/n) = floor((m-1)/n)+1} +for rational numbers @code{m/n} (@code{m}, @code{n} integers, @code{n}>0), and +@item +@code{truncate(x) = sign(x) * floor(abs(x))} +@end itemize + +Each of the classes @code{cl_R}, @code{cl_RA}, +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines the following operations: + +@table @code +@item cl_I floor1 (const @var{type}& x) +Returns @code{floor(x)}. +@item cl_I ceiling1 (const @var{type}& x) +Returns @code{ceiling(x)}. +@item cl_I truncate1 (const @var{type}& x) +Returns @code{truncate(x)}. +@item cl_I round1 (const @var{type}& x) +Returns @code{round(x)}. +@end table + +Each of the classes @code{cl_R}, @code{cl_RA}, @code{cl_I}, +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines the following operations: + +@table @code +@item cl_I floor1 (const @var{type}& x, const @var{type}& y) +Returns @code{floor(x/y)}. +@item cl_I ceiling1 (const @var{type}& x, const @var{type}& y) +Returns @code{ceiling(x/y)}. +@item cl_I truncate1 (const @var{type}& x, const @var{type}& y) +Returns @code{truncate(x/y)}. +@item cl_I round1 (const @var{type}& x, const @var{type}& y) +Returns @code{round(x/y)}. +@end table + +These functions are called @samp{floor1}, @dots{} here instead of +@samp{floor}, @dots{}, because on some systems, system dependent include +files define @samp{floor} and @samp{ceiling} as macros. + +In many cases, one needs both the quotient and the remainder of a division. +It is more efficient to compute both at the same time than to perform +two divisions, one for quotient and the next one for the remainder. +The following functions therefore return a structure containing both +the quotient and the remainder. The suffix @samp{2} indicates the number +of ``return values''. The remainder is defined as follows: + +@itemize @bullet +@item +for the computation of @code{quotient = floor(x)}, +@code{remainder = x - quotient}, +@item +for the computation of @code{quotient = floor(x,y)}, +@code{remainder = x - quotient*y}, +@end itemize + +and similarly for the other three operations. + +Each of the classes @code{cl_R}, @code{cl_RA}, +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines the following operations: + +@table @code +@item struct @var{type}_div_t @{ cl_I quotient; @var{type} remainder; @}; +@itemx @var{type}_div_t floor2 (const @var{type}& x) +@itemx @var{type}_div_t ceiling2 (const @var{type}& x) +@itemx @var{type}_div_t truncate2 (const @var{type}& x) +@itemx @var{type}_div_t round2 (const @var{type}& x) +@end table + +Each of the classes @code{cl_R}, @code{cl_RA}, @code{cl_I}, +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines the following operations: + +@table @code +@item struct @var{type}_div_t @{ cl_I quotient; @var{type} remainder; @}; +@itemx @var{type}_div_t floor2 (const @var{type}& x, const @var{type}& y) +@itemx @var{type}_div_t ceiling2 (const @var{type}& x, const @var{type}& y) +@itemx @var{type}_div_t truncate2 (const @var{type}& x, const @var{type}& y) +@itemx @var{type}_div_t round2 (const @var{type}& x, const @var{type}& y) +@end table + +Sometimes, one wants the quotient as a floating-point number (of the +same format as the argument, if the argument is a float) instead of as +an integer. The prefix @samp{f} indicates this. + +Each of the classes +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines the following operations: + +@table @code +@item @var{type} ffloor (const @var{type}& x) +@itemx @var{type} fceiling (const @var{type}& x) +@itemx @var{type} ftruncate (const @var{type}& x) +@itemx @var{type} fround (const @var{type}& x) +@end table + +and similarly for class @code{cl_R}, but with return type @code{cl_F}. + +The class @code{cl_R} defines the following operations: + +@table @code +@item cl_F ffloor (const @var{type}& x, const @var{type}& y) +@itemx cl_F fceiling (const @var{type}& x, const @var{type}& y) +@itemx cl_F ftruncate (const @var{type}& x, const @var{type}& y) +@itemx cl_F fround (const @var{type}& x, const @var{type}& y) +@end table + +These functions also exist in versions which return both the quotient +and the remainder. The suffix @samp{2} indicates this. + +Each of the classes +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines the following operations: + +@table @code +@item struct @var{type}_fdiv_t @{ @var{type} quotient; @var{type} remainder; @}; +@itemx @var{type}_fdiv_t ffloor2 (const @var{type}& x) +@itemx @var{type}_fdiv_t fceiling2 (const @var{type}& x) +@itemx @var{type}_fdiv_t ftruncate2 (const @var{type}& x) +@itemx @var{type}_fdiv_t fround2 (const @var{type}& x) +@end table +and similarly for class @code{cl_R}, but with quotient type @code{cl_F}. + +The class @code{cl_R} defines the following operations: + +@table @code +@item struct @var{type}_fdiv_t @{ cl_F quotient; cl_R remainder; @}; +@itemx @var{type}_fdiv_t ffloor2 (const @var{type}& x, const @var{type}& y) +@itemx @var{type}_fdiv_t fceiling2 (const @var{type}& x, const @var{type}& y) +@itemx @var{type}_fdiv_t ftruncate2 (const @var{type}& x, const @var{type}& y) +@itemx @var{type}_fdiv_t fround2 (const @var{type}& x, const @var{type}& y) +@end table + +Other applications need only the remainder of a division. +The remainder of @samp{floor} and @samp{ffloor} is called @samp{mod} +(abbreviation of ``modulo''). The remainder @samp{truncate} and +@samp{ftruncate} is called @samp{rem} (abbreviation of ``remainder''). + +@itemize @bullet +@item +@code{mod(x,y) = floor2(x,y).remainder = x - floor(x/y)*y} +@item +@code{rem(x,y) = truncate2(x,y).remainder = x - truncate(x/y)*y} +@end itemize + +If @code{x} and @code{y} are both >= 0, @code{mod(x,y) = rem(x,y) >= 0}. +In general, @code{mod(x,y)} has the sign of @code{y} or is zero, +and @code{rem(x,y)} has the sign of @code{x} or is zero. + +The classes @code{cl_R}, @code{cl_I} define the following operations: + +@table @code +@item @var{type} mod (const @var{type}& x, const @var{type}& y) +@itemx @var{type} rem (const @var{type}& x, const @var{type}& y) +@end table + + +@node Roots, Transcendental functions, Rounding functions, Functions on numbers +@section Roots + +Each of the classes @code{cl_R}, +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines the following operation: + +@table @code +@item @var{type} sqrt (const @var{type}& x) +@code{x} must be >= 0. This function returns the square root of @code{x}, +normalized to be >= 0. If @code{x} is the square of a rational number, +@code{sqrt(x)} will be a rational number, else it will return a +floating-point approximation. +@end table + +The classes @code{cl_RA}, @code{cl_I} define the following operation: + +@table @code +@item cl_boolean sqrtp (const @var{type}& x, @var{type}* root) +This tests whether @code{x} is a perfect square. If so, it returns true +and the exact square root in @code{*root}, else it returns false. +@end table + +Furthermore, for integers, similarly: + +@table @code +@item cl_boolean isqrt (const @var{type}& x, @var{type}* root) +@code{x} should be >= 0. This function sets @code{*root} to +@code{floor(sqrt(x))} and returns the same value as @code{sqrtp}: +the boolean value @code{(expt(*root,2) == x)}. +@end table + +For @code{n}th roots, the classes @code{cl_RA}, @code{cl_I} +define the following operation: + +@table @code +@item cl_boolean rootp (const @var{type}& x, const cl_I& n, @var{type}* root) +@code{x} must be >= 0. @code{n} must be > 0. +This tests whether @code{x} is an @code{n}th power of a rational number. +If so, it returns true and the exact root in @code{*root}, else it returns +false. +@end table + +The only square root function which accepts negative numbers is the one +for class @code{cl_N}: + +@table @code +@item cl_N sqrt (const cl_N& z) +Returns the square root of @code{z}, as defined by the formula +@code{sqrt(z) = exp(log(z)/2)}. Conversion to a floating-point type +or to a complex number are done if necessary. The range of the result is the +right half plane @code{realpart(sqrt(z)) >= 0} +including the positive imaginary axis and 0, but excluding +the negative imaginary axis. +The result is an exact number only if @code{z} is an exact number. +@end table + + +@node Transcendental functions, Functions on integers, Roots, Functions on numbers +@section Transcendental functions + + +The transcendental functions return an exact result if the argument +is exact and the result is exact as well. Otherwise they must return +inexact numbers even if the argument is exact. +For example, @code{cos(0) = 1} returns the rational number @code{1}. + + +@menu +* Exponential and logarithmic functions:: +* Trigonometric functions:: +* Hyperbolic functions:: +* Euler gamma:: +* Riemann zeta:: +@end menu + +@node Exponential and logarithmic functions, Trigonometric functions, Transcendental functions, Transcendental functions +@subsection Exponential and logarithmic functions + +@table @code +@item cl_R exp (const cl_R& x) +@itemx cl_N exp (const cl_N& x) +Returns the exponential function of @code{x}. This is @code{e^x} where +@code{e} is the base of the natural logarithms. The range of the result +is the entire complex plane excluding 0. + +@item cl_R ln (const cl_R& x) +@code{x} must be > 0. Returns the (natural) logarithm of x. + +@item cl_N log (const cl_N& x) +Returns the (natural) logarithm of x. If @code{x} is real and positive, +this is @code{ln(x)}. In general, @code{log(x) = log(abs(x)) + i*phase(x)}. +The range of the result is the strip in the complex plane +@code{-pi < imagpart(log(x)) <= pi}. + +@item cl_R phase (const cl_N& x) +Returns the angle part of @code{x} in its polar representation as a +complex number. That is, @code{phase(x) = atan(realpart(x),imagpart(x))}. +This is also the imaginary part of @code{log(x)}. +The range of the result is the interval @code{-pi < phase(x) <= pi}. +The result will be an exact number only if @code{zerop(x)} or +if @code{x} is real and positive. + +@item cl_R log (const cl_R& a, const cl_R& b) +@code{a} and @code{b} must be > 0. Returns the logarithm of @code{a} with +respect to base @code{b}. @code{log(a,b) = ln(a)/ln(b)}. +The result can be exact only if @code{a = 1} or if @code{a} and @code{b} +are both rational. + +@item cl_N log (const cl_N& a, const cl_N& b) +Returns the logarithm of @code{a} with respect to base @code{b}. +@code{log(a,b) = log(a)/log(b)}. + +@item cl_N expt (const cl_N& x, const cl_N& y) +Exponentiation: Returns @code{x^y = exp(y*log(x))}. +@end table + +The constant e = exp(1) = 2.71828@dots{} is returned by the following functions: + +@table @code +@item cl_F cl_exp1 (cl_float_format_t f) +Returns e as a float of format @code{f}. + +@item cl_F cl_exp1 (const cl_F& y) +Returns e in the float format of @code{y}. + +@item cl_F cl_exp1 (void) +Returns e as a float of format @code{cl_default_float_format}. +@end table + + +@node Trigonometric functions, Hyperbolic functions, Exponential and logarithmic functions, Transcendental functions +@subsection Trigonometric functions + +@table @code +@item cl_R sin (const cl_R& x) +Returns @code{sin(x)}. The range of the result is the interval +@code{-1 <= sin(x) <= 1}. + +@item cl_N sin (const cl_N& z) +Returns @code{sin(z)}. The range of the result is the entire complex plane. + +@item cl_R cos (const cl_R& x) +Returns @code{cos(x)}. The range of the result is the interval +@code{-1 <= cos(x) <= 1}. + +@item cl_N cos (const cl_N& x) +Returns @code{cos(z)}. The range of the result is the entire complex plane. + +@item struct cl_cos_sin_t @{ cl_R cos; cl_R sin; @}; +@itemx cl_cos_sin_t cl_cos_sin (const cl_R& x) +Returns both @code{sin(x)} and @code{cos(x)}. This is more efficient than +computing them separately. The relation @code{cos^2 + sin^2 = 1} will +hold only approximately. + +@item cl_R tan (const cl_R& x) +@itemx cl_N tan (const cl_N& x) +Returns @code{tan(x) = sin(x)/cos(x)}. + +@item cl_N cis (const cl_R& x) +@itemx cl_N cis (const cl_N& x) +Returns @code{exp(i*x)}. The name @samp{cis} means ``cos + i sin'', because +@code{e^(i*x) = cos(x) + i*sin(x)}. + +@item cl_N asin (const cl_N& z) +Returns @code{arcsin(z)}. This is defined as +@code{arcsin(z) = log(iz+sqrt(1-z^2))/i} and satisfies +@code{arcsin(-z) = -arcsin(z)}. +The range of the result is the strip in the complex domain +@code{-pi/2 <= realpart(arcsin(z)) <= pi/2}, excluding the numbers +with @code{realpart = -pi/2} and @code{imagpart < 0} and the numbers +with @code{realpart = pi/2} and @code{imagpart > 0}. +@ignore +Proof: This follows from arcsin(z) = arsinh(iz)/i and the corresponding +results for arsinh. +@end ignore + +@item cl_N acos (const cl_N& z) +Returns @code{arccos(z)}. This is defined as +@code{arccos(z) = pi/2 - arcsin(z) = log(z+i*sqrt(1-z^2))/i} +@ignore + Kahan's formula: + @code{arccos(z) = 2*log(sqrt((1+z)/2)+i*sqrt((1-z)/2))/i} +@end ignore +and satisfies @code{arccos(-z) = pi - arccos(z)}. +The range of the result is the strip in the complex domain +@code{0 <= realpart(arcsin(z)) <= pi}, excluding the numbers +with @code{realpart = 0} and @code{imagpart < 0} and the numbers +with @code{realpart = pi} and @code{imagpart > 0}. +@ignore +Proof: This follows from the results about arcsin. +@end ignore + +@item cl_R atan (const cl_R& x, const cl_R& y) +Returns the angle of the polar representation of the complex number +@code{x+iy}. This is @code{atan(y/x)} if @code{x>0}. The range of +the result is the interval @code{-pi < atan(x,y) <= pi}. The result will +be an exact number only if @code{x > 0} and @code{y} is the exact @code{0}. +WARNING: In Common Lisp, this function is called as @code{(atan y x)}, +with reversed order of arguments. + +@item cl_R atan (const cl_R& x) +Returns @code{arctan(x)}. This is the same as @code{atan(1,x)}. The range +of the result is the interval @code{-pi/2 < atan(x) < pi/2}. The result +will be an exact number only if @code{x} is the exact @code{0}. + +@item cl_N atan (const cl_N& z) +Returns @code{arctan(z)}. This is defined as +@code{arctan(z) = (log(1+iz)-log(1-iz)) / 2i} and satisfies +@code{arctan(-z) = -arctan(z)}. The range of the result is +the strip in the complex domain +@code{-pi/2 <= realpart(arctan(z)) <= pi/2}, excluding the numbers +with @code{realpart = -pi/2} and @code{imagpart >= 0} and the numbers +with @code{realpart = pi/2} and @code{imagpart <= 0}. +@ignore +Proof: arctan(z) = artanh(iz)/i, we know the range of the artanh function. +@end ignore + +@end table + +The constant pi = 3.14@dots{} is returned by the following functions: + +@table @code +@item cl_F cl_pi (cl_float_format_t f) +Returns pi as a float of format @code{f}. + +@item cl_F cl_pi (const cl_F& y) +Returns pi in the float format of @code{y}. + +@item cl_F cl_pi (void) +Returns pi as a float of format @code{cl_default_float_format}. +@end table + + +@node Hyperbolic functions, Euler gamma, Trigonometric functions, Transcendental functions +@subsection Hyperbolic functions + +@table @code +@item cl_R sinh (const cl_R& x) +Returns @code{sinh(x)}. + +@item cl_N sinh (const cl_N& z) +Returns @code{sinh(z)}. The range of the result is the entire complex plane. + +@item cl_R cosh (const cl_R& x) +Returns @code{cosh(x)}. The range of the result is the interval +@code{cosh(x) >= 1}. + +@item cl_N cosh (const cl_N& z) +Returns @code{cosh(z)}. The range of the result is the entire complex plane. + +@item struct cl_cosh_sinh_t @{ cl_R cosh; cl_R sinh; @}; +@itemx cl_cosh_sinh_t cl_cosh_sinh (const cl_R& x) +Returns both @code{sinh(x)} and @code{cosh(x)}. This is more efficient than +computing them separately. The relation @code{cosh^2 - sinh^2 = 1} will +hold only approximately. + +@item cl_R tanh (const cl_R& x) +@itemx cl_N tanh (const cl_N& x) +Returns @code{tanh(x) = sinh(x)/cosh(x)}. + +@item cl_N asinh (const cl_N& z) +Returns @code{arsinh(z)}. This is defined as +@code{arsinh(z) = log(z+sqrt(1+z^2))} and satisfies +@code{arsinh(-z) = -arsinh(z)}. +@ignore +Proof: Knowing the range of log, we know -pi < imagpart(arsinh(z)) <= pi. +Actually, z+sqrt(1+z^2) can never be real and <0, so +-pi < imagpart(arsinh(z)) < pi. +We have (z+sqrt(1+z^2))*(-z+sqrt(1+(-z)^2)) = (1+z^2)-z^2 = 1, hence the +logs of both factors sum up to 0 mod 2*pi*i, hence to 0. +@end ignore +The range of the result is the strip in the complex domain +@code{-pi/2 <= imagpart(arsinh(z)) <= pi/2}, excluding the numbers +with @code{imagpart = -pi/2} and @code{realpart > 0} and the numbers +with @code{imagpart = pi/2} and @code{realpart < 0}. +@ignore +Proof: Write z = x+iy. Because of arsinh(-z) = -arsinh(z), we may assume +that z is in Range(sqrt), that is, x>=0 and, if x=0, then y>=0. +If x > 0, then Re(z+sqrt(1+z^2)) = x + Re(sqrt(1+z^2)) >= x > 0, +so -pi/2 < imagpart(log(z+sqrt(1+z^2))) < pi/2. +If x = 0 and y >= 0, arsinh(z) = log(i*y+sqrt(1-y^2)). + If y <= 1, the realpart is 0 and the imagpart is >= 0 and <= pi/2. + If y >= 1, the imagpart is pi/2 and the realpart is + log(y+sqrt(y^2-1)) >= log(y) >= 0. +@end ignore +@ignore +Moreover, if z is in Range(sqrt), +log(sqrt(1+z^2)+z) = 2 artanh(z/(1+sqrt(1+z^2))) +(for a proof, see file src/cl_C_asinh.cc). +@end ignore + +@item cl_N acosh (const cl_N& z) +Returns @code{arcosh(z)}. This is defined as +@code{arcosh(z) = 2*log(sqrt((z+1)/2)+sqrt((z-1)/2))}. +The range of the result is the half-strip in the complex domain +@code{-pi < imagpart(arcosh(z)) <= pi, realpart(arcosh(z)) >= 0}, +excluding the numbers with @code{realpart = 0} and @code{-pi < imagpart < 0}. +@ignore +Proof: sqrt((z+1)/2) and sqrt((z-1)/2)) lie in Range(sqrt), hence does +their sum, hence its log has an imagpart <= pi/2 and > -pi/2. +If z is in Range(sqrt), we have + sqrt(z+1)*sqrt(z-1) = sqrt(z^2-1) + ==> (sqrt((z+1)/2)+sqrt((z-1)/2))^2 = (z+1)/2 + sqrt(z^2-1) + (z-1)/2 + = z + sqrt(z^2-1) + ==> arcosh(z) = log(z+sqrt(z^2-1)) mod 2*pi*i + and since the imagpart of both expressions is > -pi, <= pi + ==> arcosh(z) = log(z+sqrt(z^2-1)) + To prove that the realpart of this is >= 0, write z = x+iy with x>=0, + z^2-1 = u+iv with u = x^2-y^2-1, v = 2xy, + sqrt(z^2-1) = p+iq with p = sqrt((sqrt(u^2+v^2)+u)/2) >= 0, + q = sqrt((sqrt(u^2+v^2)-u)/2) * sign(v), + then |z+sqrt(z^2-1)|^2 = |x+iy + p+iq|^2 + = (x+p)^2 + (y+q)^2 + = x^2 + 2xp + p^2 + y^2 + 2yq + q^2 + >= x^2 + p^2 + y^2 + q^2 (since x>=0, p>=0, yq>=0) + = x^2 + y^2 + sqrt(u^2+v^2) + >= x^2 + y^2 + |u| + >= x^2 + y^2 - u + = 1 + 2*y^2 + >= 1 + hence realpart(log(z+sqrt(z^2-1))) = log(|z+sqrt(z^2-1)|) >= 0. + Equality holds only if y = 0 and u <= 0, i.e. 0 <= x < 1. + In this case arcosh(z) = log(x+i*sqrt(1-x^2)) has imagpart >=0. +Otherwise, -z is in Range(sqrt). + If y != 0, sqrt((z+1)/2) = i^sign(y) * sqrt((-z-1)/2), + sqrt((z-1)/2) = i^sign(y) * sqrt((-z+1)/2), + hence arcosh(z) = sign(y)*pi/2*i + arcosh(-z), + and this has realpart > 0. + If y = 0 and -1<=x<=0, we still have sqrt(z+1)*sqrt(z-1) = sqrt(z^2-1), + ==> arcosh(z) = log(z+sqrt(z^2-1)) = log(x+i*sqrt(1-x^2)) + has realpart = 0 and imagpart > 0. + If y = 0 and x<=-1, however, sqrt(z+1)*sqrt(z-1) = - sqrt(z^2-1), + ==> arcosh(z) = log(z-sqrt(z^2-1)) = pi*i + arcosh(-z). + This has realpart >= 0 and imagpart = pi. +@end ignore + +@item cl_N atanh (const cl_N& z) +Returns @code{artanh(z)}. This is defined as +@code{artanh(z) = (log(1+z)-log(1-z)) / 2} and satisfies +@code{artanh(-z) = -artanh(z)}. The range of the result is +the strip in the complex domain +@code{-pi/2 <= imagpart(artanh(z)) <= pi/2}, excluding the numbers +with @code{imagpart = -pi/2} and @code{realpart <= 0} and the numbers +with @code{imagpart = pi/2} and @code{realpart >= 0}. +@ignore +Proof: Write z = x+iy. Examine + imagpart(artanh(z)) = (atan(1+x,y) - atan(1-x,-y))/2. + Case 1: y = 0. + x > 1 ==> imagpart = -pi/2, realpart = 1/2 log((x+1)/(x-1)) > 0, + x < -1 ==> imagpart = pi/2, realpart = 1/2 log((-x-1)/(-x+1)) < 0, + |x| < 1 ==> imagpart = 0 + Case 2: y > 0. + imagpart(artanh(z)) + = (atan(1+x,y) - atan(1-x,-y))/2 + = ((pi/2 - atan((1+x)/y)) - (-pi/2 - atan((1-x)/-y)))/2 + = (pi - atan((1+x)/y) - atan((1-x)/y))/2 + > (pi - pi/2 - pi/2 )/2 = 0 + and (1+x)/y > (1-x)/y + ==> atan((1+x)/y) > atan((-1+x)/y) = - atan((1-x)/y) + ==> imagpart < pi/2. + Hence 0 < imagpart < pi/2. + Case 3: y < 0. + By artanh(z) = -artanh(-z) and case 2, -pi/2 < imagpart < 0. +@end ignore +@end table + + +@node Euler gamma, Riemann zeta, Hyperbolic functions, Transcendental functions +@subsection Euler gamma + +Euler's constant C = 0.577@dots{} is returned by the following functions: + +@table @code +@item cl_F cl_eulerconst (cl_float_format_t f) +Returns Euler's constant as a float of format @code{f}. + +@item cl_F cl_eulerconst (const cl_F& y) +Returns Euler's constant in the float format of @code{y}. + +@item cl_F cl_eulerconst (void) +Returns Euler's constant as a float of format @code{cl_default_float_format}. +@end table + +Catalan's constant G = 0.915@dots{} is returned by the following functions: + +@table @code +@item cl_F cl_catalanconst (cl_float_format_t f) +Returns Catalan's constant as a float of format @code{f}. + +@item cl_F cl_catalanconst (const cl_F& y) +Returns Catalan's constant in the float format of @code{y}. + +@item cl_F cl_catalanconst (void) +Returns Catalan's constant as a float of format @code{cl_default_float_format}. +@end table + + +@node Riemann zeta, , Euler gamma, Transcendental functions +@subsection Riemann zeta + +Riemann's zeta function at an integral point @code{s>1} is returned by the +following functions: + +@table @code +@item cl_F cl_zeta (int s, cl_float_format_t f) +Returns Riemann's zeta function at @code{s} as a float of format @code{f}. + +@item cl_F cl_zeta (int s, const cl_F& y) +Returns Riemann's zeta function at @code{s} in the float format of @code{y}. + +@item cl_F cl_zeta (int s) +Returns Riemann's zeta function at @code{s} as a float of format +@code{cl_default_float_format}. +@end table + + +@node Functions on integers, Functions on floating-point numbers, Transcendental functions, Functions on numbers +@section Functions on integers + +@menu +* Logical functions:: +* Number theoretic functions:: +* Combinatorial functions:: +@end menu + +@node Logical functions, Number theoretic functions, Functions on integers, Functions on integers +@subsection Logical functions + +Integers, when viewed as in two's complement notation, can be thought as +infinite bit strings where the bits' values eventually are constant. +For example, +@example + 17 = ......00010001 + -6 = ......11111010 +@end example + +The logical operations view integers as such bit strings and operate +on each of the bit positions in parallel. + +@table @code +@item cl_I lognot (const cl_I& x) +@itemx cl_I operator ~ (const cl_I& x) +Logical not, like @code{~x} in C. This is the same as @code{-1-x}. + +@item cl_I logand (const cl_I& x, const cl_I& y) +@itemx cl_I operator & (const cl_I& x, const cl_I& y) +Logical and, like @code{x & y} in C. + +@item cl_I logior (const cl_I& x, const cl_I& y) +@itemx cl_I operator | (const cl_I& x, const cl_I& y) +Logical (inclusive) or, like @code{x | y} in C. + +@item cl_I logxor (const cl_I& x, const cl_I& y) +@itemx cl_I operator ^ (const cl_I& x, const cl_I& y) +Exclusive or, like @code{x ^ y} in C. + +@item cl_I logeqv (const cl_I& x, const cl_I& y) +Bitwise equivalence, like @code{~(x ^ y)} in C. + +@item cl_I lognand (const cl_I& x, const cl_I& y) +Bitwise not and, like @code{~(x & y)} in C. + +@item cl_I lognor (const cl_I& x, const cl_I& y) +Bitwise not or, like @code{~(x | y)} in C. + +@item cl_I logandc1 (const cl_I& x, const cl_I& y) +Logical and, complementing the first argument, like @code{~x & y} in C. + +@item cl_I logandc2 (const cl_I& x, const cl_I& y) +Logical and, complementing the second argument, like @code{x & ~y} in C. + +@item cl_I logorc1 (const cl_I& x, const cl_I& y) +Logical or, complementing the first argument, like @code{~x | y} in C. + +@item cl_I logorc2 (const cl_I& x, const cl_I& y) +Logical or, complementing the second argument, like @code{x | ~y} in C. +@end table + +These operations are all available though the function +@table @code +@item cl_I boole (cl_boole op, const cl_I& x, const cl_I& y) +@end table +where @code{op} must have one of the 16 values (each one stands for a function +which combines two bits into one bit): @code{boole_clr}, @code{boole_set}, +@code{boole_1}, @code{boole_2}, @code{boole_c1}, @code{boole_c2}, +@code{boole_and}, @code{boole_ior}, @code{boole_xor}, @code{boole_eqv}, +@code{boole_nand}, @code{boole_nor}, @code{boole_andc1}, @code{boole_andc2}, +@code{boole_orc1}, @code{boole_orc2}. + +Other functions that view integers as bit strings: + +@table @code +@item cl_boolean logtest (const cl_I& x, const cl_I& y) +Returns true if some bit is set in both @code{x} and @code{y}, i.e. if +@code{logand(x,y) != 0}. + +@item cl_boolean logbitp (const cl_I& n, const cl_I& x) +Returns true if the @code{n}th bit (from the right) of @code{x} is set. +Bit 0 is the least significant bit. + +@item uintL logcount (const cl_I& x) +Returns the number of one bits in @code{x}, if @code{x} >= 0, or +the number of zero bits in @code{x}, if @code{x} < 0. +@end table + +The following functions operate on intervals of bits in integers. +The type +@example +struct cl_byte @{ uintL size; uintL position; @}; +@end example +represents the bit interval containing the bits +@code{position}@dots{}@code{position+size-1} of an integer. +The constructor @code{cl_byte(size,position)} constructs a @code{cl_byte}. + +@table @code +@item cl_I ldb (const cl_I& n, const cl_byte& b) +extracts the bits of @code{n} described by the bit interval @code{b} +and returns them as a nonnegative integer with @code{b.size} bits. + +@item cl_boolean ldb_test (const cl_I& n, const cl_byte& b) +Returns true if some bit described by the bit interval @code{b} is set in +@code{n}. + +@item cl_I dpb (const cl_I& newbyte, const cl_I& n, const cl_byte& b) +Returns @code{n}, with the bits described by the bit interval @code{b} +replaced by @code{newbyte}. Only the lowest @code{b.size} bits of +@code{newbyte} are relevant. +@end table + +The functions @code{ldb} and @code{dpb} implicitly shift. The following +functions are their counterparts without shifting: + +@table @code +@item cl_I mask_field (const cl_I& n, const cl_byte& b) +returns an integer with the bits described by the bit interval @code{b} +copied from the corresponding bits in @code{n}, the other bits zero. + +@item cl_I deposit_field (const cl_I& newbyte, const cl_I& n, const cl_byte& b) +returns an integer where the bits described by the bit interval @code{b} +come from @code{newbyte} and the other bits come from @code{n}. +@end table + +The following relations hold: + +@itemize @asis +@item +@code{ldb (n, b) = mask_field(n, b) >> b.position}, +@item +@code{dpb (newbyte, n, b) = deposit_field (newbyte << b.position, n, b)}, +@item +@code{deposit_field(newbyte,n,b) = n ^ mask_field(n,b) ^ mask_field(new_byte,b)}. +@end itemize + +The following operations on integers as bit strings are efficient shortcuts +for common arithmetic operations: + +@table @code +@item cl_boolean oddp (const cl_I& x) +Returns true if the least significant bit of @code{x} is 1. Equivalent to +@code{mod(x,2) != 0}. + +@item cl_boolean evenp (const cl_I& x) +Returns true if the least significant bit of @code{x} is 0. Equivalent to +@code{mod(x,2) == 0}. + +@item cl_I operator << (const cl_I& x, const cl_I& n) +Shifts @code{x} by @code{n} bits to the left. @code{n} should be >=0. +Equivalent to @code{x * expt(2,n)}. + +@item cl_I operator >> (const cl_I& x, const cl_I& n) +Shifts @code{x} by @code{n} bits to the right. @code{n} should be >=0. +Bits shifted out to the right are thrown away. +Equivalent to @code{floor(x / expt(2,n))}. + +@item cl_I ash (const cl_I& x, const cl_I& y) +Shifts @code{x} by @code{y} bits to the left (if @code{y}>=0) or +by @code{-y} bits to the right (if @code{y}<=0). In other words, this +returns @code{floor(x * expt(2,y))}. + +@item uintL integer_length (const cl_I& x) +Returns the number of bits (excluding the sign bit) needed to represent @code{x} +in two's complement notation. This is the smallest n >= 0 such that +-2^n <= x < 2^n. If x > 0, this is the unique n > 0 such that +2^(n-1) <= x < 2^n. + +@item uintL ord2 (const cl_I& x) +@code{x} must be non-zero. This function returns the number of 0 bits at the +right of @code{x} in two's complement notation. This is the largest n >= 0 +such that 2^n divides @code{x}. + +@item uintL power2p (const cl_I& x) +@code{x} must be > 0. This function checks whether @code{x} is a power of 2. +If @code{x} = 2^(n-1), it returns n. Else it returns 0. +(See also the function @code{logp}.) +@end table + + +@node Number theoretic functions, Combinatorial functions, Logical functions, Functions on integers +@subsection Number theoretic functions + +@table @code +@item uint32 gcd (uint32 a, uint32 b) +@itemx cl_I gcd (const cl_I& a, const cl_I& b) +This function returns the greatest common divisor of @code{a} and @code{b}, +normalized to be >= 0. + +@item cl_I xgcd (const cl_I& a, const cl_I& b, cl_I* u, cl_I* v) +This function (``extended gcd'') returns the greatest common divisor @code{g} of +@code{a} and @code{b} and at the same time the representation of @code{g} +as an integral linear combination of @code{a} and @code{b}: +@code{u} and @code{v} with @code{u*a+v*b = g}, @code{g} >= 0. +@code{u} and @code{v} will be normalized to be of smallest possible absolute +value, in the following sense: If @code{a} and @code{b} are non-zero, and +@code{abs(a) != abs(b)}, @code{u} and @code{v} will satisfy the inequalities +@code{abs(u) <= abs(b)/(2*g)}, @code{abs(v) <= abs(a)/(2*g)}. + +@item cl_I lcm (const cl_I& a, const cl_I& b) +This function returns the least common multiple of @code{a} and @code{b}, +normalized to be >= 0. + +@item cl_boolean logp (const cl_I& a, const cl_I& b, cl_RA* l) +@itemx cl_boolean logp (const cl_RA& a, const cl_RA& b, cl_RA* l) +@code{a} must be > 0. @code{b} must be >0 and != 1. If log(a,b) is +rational number, this function returns true and sets *l = log(a,b), else +it returns false. +@end table + + +@node Combinatorial functions, , Number theoretic functions, Functions on integers +@subsection Combinatorial functions + +@table @code +@item cl_I factorial (uintL n) +@code{n} must be a small integer >= 0. This function returns the factorial +@code{n}! = @code{1*2*@dots{}*n}. + +@item cl_I doublefactorial (uintL n) +@code{n} must be a small integer >= 0. This function returns the +doublefactorial @code{n}!! = @code{1*3*@dots{}*n} or +@code{n}!! = @code{2*4*@dots{}*n}, respectively. + +@item cl_I binomial (uintL n, uintL k) +@code{n} and @code{k} must be small integers >= 0. This function returns the +binomial coefficient +@tex +${n \choose k} = {n! \over n! (n-k)!}$ +@end tex +@ifinfo +(@code{n} choose @code{k}) = @code{n}! / @code{k}! @code{(n-k)}! +@end ifinfo +for 0 <= k <= n, 0 else. +@end table + + +@node Functions on floating-point numbers, Conversion functions, Functions on integers, Functions on numbers +@section Functions on floating-point numbers + +Recall that a floating-point number consists of a sign @code{s}, an +exponent @code{e} and a mantissa @code{m}. The value of the number is +@code{(-1)^s * 2^e * m}. + +Each of the classes +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines the following operations. + +@table @code +@item @var{type} scale_float (const @var{type}& x, sintL delta) +@itemx @var{type} scale_float (const @var{type}& x, const cl_I& delta) +Returns @code{x*2^delta}. This is more efficient than an explicit multiplication +because it copies @code{x} and modifies the exponent. +@end table + +The following functions provide an abstract interface to the underlying +representation of floating-point numbers. + +@table @code +@item sintL float_exponent (const @var{type}& x) +Returns the exponent @code{e} of @code{x}. +For @code{x = 0.0}, this is 0. For @code{x} non-zero, this is the unique +integer with @code{2^(e-1) <= abs(x) < 2^e}. + +@item sintL float_radix (const @var{type}& x) +Returns the base of the floating-point representation. This is always @code{2}. + +@item @var{type} float_sign (const @var{type}& x) +Returns the sign @code{s} of @code{x} as a float. The value is 1 for +@code{x} >= 0, -1 for @code{x} < 0. + +@item uintL float_digits (const @var{type}& x) +Returns the number of mantissa bits in the floating-point representation +of @code{x}, including the hidden bit. The value only depends on the type +of @code{x}, not on its value. + +@item uintL float_precision (const @var{type}& x) +Returns the number of significant mantissa bits in the floating-point +representation of @code{x}. Since denormalized numbers are not supported, +this is the same as @code{float_digits(x)} if @code{x} is non-zero, and +0 if @code{x} = 0. +@end table + +The complete internal representation of a float is encoded in the type +@code{cl_decoded_float} (or @code{cl_decoded_sfloat}, @code{cl_decoded_ffloat}, +@code{cl_decoded_dfloat}, @code{cl_decoded_lfloat}, respectively), defined by +@example +struct cl_decoded_@var{type}float @{ + @var{type} mantissa; cl_I exponent; @var{type} sign; +@}; +@end example + +and returned by the function + +@table @code +@item cl_decoded_@var{type}float decode_float (const @var{type}& x) +For @code{x} non-zero, this returns @code{(-1)^s}, @code{e}, @code{m} with +@code{x = (-1)^s * 2^e * m} and @code{0.5 <= m < 1.0}. For @code{x} = 0, +it returns @code{(-1)^s}=1, @code{e}=0, @code{m}=0. +@code{e} is the same as returned by the function @code{float_exponent}. +@end table + +A complete decoding in terms of integers is provided as type +@example +struct cl_idecoded_float @{ + cl_I mantissa; cl_I exponent; cl_I sign; +@}; +@end example +by the following function: + +@table @code +@item cl_idecoded_float integer_decode_float (const @var{type}& x) +For @code{x} non-zero, this returns @code{(-1)^s}, @code{e}, @code{m} with +@code{x = (-1)^s * 2^e * m} and @code{m} an integer with @code{float_digits(x)} +bits. For @code{x} = 0, it returns @code{(-1)^s}=1, @code{e}=0, @code{m}=0. +WARNING: The exponent @code{e} is not the same as the one returned by +the functions @code{decode_float} and @code{float_exponent}. +@end table + +Some other function, implemented only for class @code{cl_F}: + +@table @code +@item cl_F float_sign (const cl_F& x, const cl_F& y) +This returns a floating point number whose precision and absolute value +is that of @code{y} and whose sign is that of @code{x}. If @code{x} is +zero, it is treated as positive. Same for @code{y}. +@end table + + +@node Conversion functions, Random number generators, Functions on floating-point numbers, Functions on numbers +@section Conversion functions + +@menu +* Conversion to floating-point numbers:: +* Conversion to rational numbers:: +@end menu + +@node Conversion to floating-point numbers, Conversion to rational numbers, Conversion functions, Conversion functions +@subsection Conversion to floating-point numbers + +The type @code{cl_float_format_t} describes a floating-point format. + +@table @code +@item cl_float_format_t cl_float_format (uintL n) +Returns the smallest float format which guarantees at least @code{n} +decimal digits in the mantissa (after the decimal point). + +@item cl_float_format_t cl_float_format (const cl_F& x) +Returns the floating point format of @code{x}. + +@item cl_float_format_t cl_default_float_format +Global variable: the default float format used when converting rational numbers +to floats. +@end table + +To convert a real number to a float, each of the types +@code{cl_R}, @code{cl_F}, @code{cl_I}, @code{cl_RA}, +@code{int}, @code{unsigned int}, @code{float}, @code{double} +defines the following operations: + +@table @code +@item cl_F cl_float (const @var{type}&x, cl_float_format_t f) +Returns @code{x} as a float of format @code{f}. +@item cl_F cl_float (const @var{type}&x, const cl_F& y) +Returns @code{x} in the float format of @code{y}. +@item cl_F cl_float (const @var{type}&x) +Returns @code{x} as a float of format @code{cl_default_float_format} if +it is an exact number, or @code{x} itself if it is already a float. +@end table + +Of course, converting a number to a float can lose precision. + +Every floating-point format has some characteristic numbers: + +@table @code +@item cl_F most_positive_float (cl_float_format_t f) +Returns the largest (most positive) floating point number in float format @code{f}. + +@item cl_F most_negative_float (cl_float_format_t f) +Returns the smallest (most negative) floating point number in float format @code{f}. + +@item cl_F least_positive_float (cl_float_format_t f) +Returns the least positive floating point number (i.e. > 0 but closest to 0) +in float format @code{f}. + +@item cl_F least_negative_float (cl_float_format_t f) +Returns the least negative floating point number (i.e. < 0 but closest to 0) +in float format @code{f}. + +@item cl_F float_epsilon (cl_float_format_t f) +Returns the smallest floating point number e > 0 such that @code{1+e != 1}. + +@item cl_F float_negative_epsilon (cl_float_format_t f) +Returns the smallest floating point number e > 0 such that @code{1-e != 1}. +@end table + + +@node Conversion to rational numbers, , Conversion to floating-point numbers, Conversion functions +@subsection Conversion to rational numbers + +Each of the classes @code{cl_R}, @code{cl_RA}, @code{cl_F} +defines the following operation: + +@table @code +@item cl_RA rational (const @var{type}& x) +Returns the value of @code{x} as an exact number. If @code{x} is already +an exact number, this is @code{x}. If @code{x} is a floating-point number, +the value is a rational number whose denominator is a power of 2. +@end table + +In order to convert back, say, @code{(cl_F)(cl_R)"1/3"} to @code{1/3}, there is +the function + +@table @code +@item cl_RA rationalize (const cl_R& x) +If @code{x} is a floating-point number, it actually represents an interval +of real numbers, and this function returns the rational number with +smallest denominator (and smallest numerator, in magnitude) +which lies in this interval. +If @code{x} is already an exact number, this function returns @code{x}. +@end table + +If @code{x} is any float, one has + +@itemize @asis +@item +@code{cl_float(rational(x),x) = x} +@item +@code{cl_float(rationalize(x),x) = x} +@end itemize + + +@node Random number generators, Obfuscating operators, Conversion functions, Functions on numbers +@section Random number generators + + +A random generator is a machine which produces (pseudo-)random numbers. +The include file @code{} defines a class @code{cl_random_state} +which contains the state of a random generator. If you make a copy +of the random number generator, the original one and the copy will produce +the same sequence of random numbers. + +The following functions return (pseudo-)random numbers in different formats. +Calling one of these modifies the state of the random number generator in +a complicated but deterministic way. + +The global variable +@example +cl_random_state cl_default_random_state +@end example +contains a default random number generator. It is used when the functions +below are called without @code{cl_random_state} argument. + +@table @code +@item uint32 random32 (cl_random_state& randomstate) +@itemx uint32 random32 () +Returns a random unsigned 32-bit number. All bits are equally random. + +@item cl_I random_I (cl_random_state& randomstate, const cl_I& n) +@itemx cl_I random_I (const cl_I& n) +@code{n} must be an integer > 0. This function returns a random integer @code{x} +in the range @code{0 <= x < n}. + +@item cl_F random_F (cl_random_state& randomstate, const cl_F& n) +@itemx cl_F random_F (const cl_F& n) +@code{n} must be a float > 0. This function returns a random floating-point +number of the same format as @code{n} in the range @code{0 <= x < n}. + +@item cl_R random_R (cl_random_state& randomstate, const cl_R& n) +@itemx cl_R random_R (const cl_R& n) +Behaves like @code{random_I} if @code{n} is an integer and like @code{random_F} +if @code{n} is a float. +@end table + + +@node Obfuscating operators, , Random number generators, Functions on numbers +@section Obfuscating operators + +The modifying C/C++ operators @code{+=}, @code{-=}, @code{*=}, @code{/=}, +@code{&=}, @code{|=}, @code{^=}, @code{<<=}, @code{>>=} +are not available by default because their +use tends to make programs unreadable. It is trivial to get away without +them. However, if you feel that you absolutely need these operators +to get happy, then add +@example +#define WANT_OBFUSCATING_OPERATORS +@end example +to the beginning of your source files, before the inclusion of any CLN +include files. This flag will enable the following operators: + +For the classes @code{cl_N}, @code{cl_R}, @code{cl_RA}, +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF}: + +@table @code +@item @var{type}& operator += (@var{type}&, const @var{type}&) +@itemx @var{type}& operator -= (@var{type}&, const @var{type}&) +@itemx @var{type}& operator *= (@var{type}&, const @var{type}&) +@itemx @var{type}& operator /= (@var{type}&, const @var{type}&) +@end table + +For the class @code{cl_I}: + +@table @code +@item @var{type}& operator += (@var{type}&, const @var{type}&) +@itemx @var{type}& operator -= (@var{type}&, const @var{type}&) +@itemx @var{type}& operator *= (@var{type}&, const @var{type}&) +@itemx @var{type}& operator &= (@var{type}&, const @var{type}&) +@itemx @var{type}& operator |= (@var{type}&, const @var{type}&) +@itemx @var{type}& operator ^= (@var{type}&, const @var{type}&) +@itemx @var{type}& operator <<= (@var{type}&, const @var{type}&) +@itemx @var{type}& operator >>= (@var{type}&, const @var{type}&) +@end table + +For the classes @code{cl_N}, @code{cl_R}, @code{cl_RA}, @code{cl_I}, +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF}: + +@table @code +@item @var{type}& operator ++ (@var{type}& x) +The prefix operator @code{++x}. + +@item void operator ++ (@var{type}& x, int) +The postfix operator @code{x++}. + +@item @var{type}& operator -- (@var{type}& x) +The prefix operator @code{--x}. + +@item void operator -- (@var{type}& x, int) +The postfix operator @code{x--}. +@end table + +Note that by using these obfuscating operators, you wouldn't gain efficiency: +In CLN @samp{x += y;} is exactly the same as @samp{x = x+y;}, not more +efficient. + + +@node Input/Output, Rings, Functions on numbers, Top +@chapter Input/Output + +@menu +* Internal and printed representation:: +* Input functions:: +* Output functions:: +@end menu + +@node Internal and printed representation, Input functions, Input/Output, Input/Output +@section Internal and printed representation + +All computations deal with the internal representations of the numbers. + +Every number has an external representation as a sequence of ASCII characters. +Several external representations may denote the same number, for example, +"20.0" and "20.000". + +Converting an internal to an external representation is called ``printing'', +converting an external to an internal representation is called ``reading''. +In CLN, is it always true that conversion of an internal to an external +representation and then back to an internal representation will yield the +same internal representation. Symbolically: @code{read(print(x)) == x}. +This is called ``print-read consistency''. + +Different types of numbers have different external representations (case +is insignificant): + +@table @asis +@item Integers +External representation: @var{sign}@{@var{digit}@}+. The reader also accepts the +Common Lisp syntaxes @var{sign}@{@var{digit}@}+@code{.} with a trailing dot +for decimal integers +and the @code{#@var{n}R}, @code{#b}, @code{#o}, @code{#x} prefixes. + +@item Rational numbers +External representation: @var{sign}@{@var{digit}@}+@code{/}@{@var{digit}@}+. +The @code{#@var{n}R}, @code{#b}, @code{#o}, @code{#x} prefixes are allowed +here as well. + +@item Floating-point numbers +External representation: @var{sign}@{@var{digit}@}*@var{exponent} or +@var{sign}@{@var{digit}@}*@code{.}@{@var{digit}@}*@var{exponent} or +@var{sign}@{@var{digit}@}*@code{.}@{@var{digit}@}+. A precision specifier +of the form _@var{prec} may be appended. There must be at least +one digit in the non-exponent part. The exponent has the syntax +@var{expmarker} @var{expsign} @{@var{digit}@}+. +The exponent marker is + +@itemize @asis +@item +@samp{s} for short-floats, +@item +@samp{f} for single-floats, +@item +@samp{d} for double-floats, +@item +@samp{L} for long-floats, +@end itemize + +or @samp{e}, which denotes a default float format. The precision specifying +suffix has the syntax _@var{prec} where @var{prec} denotes the number of +valid mantissa digits (in decimal, excluding leading zeroes), cf. also +function @samp{cl_float_format}. + +@item Complex numbers +External representation: +@itemize @asis +@item +In algebraic notation: @code{@var{realpart}+@var{imagpart}i}. Of course, +if @var{imagpart} is negative, its printed representation begins with +a @samp{-}, and the @samp{+} between @var{realpart} and @var{imagpart} +may be omitted. Note that this notation cannot be used when the @var{imagpart} +is rational and the rational number's base is >18, because the @samp{i} +is then read as a digit. +@item +In Common Lisp notation: @code{#C(@var{realpart} @var{imagpart})}. +@end itemize +@end table + + +@node Input functions, Output functions, Internal and printed representation, Input/Output +@section Input functions + +Including @code{} defines a type @code{cl_istream}, which is +the type of the first argument to all input functions. Unless you build +and use CLN with the macro CL_IO_STDIO being defined, @code{cl_istream} +is the same as @code{istream&}. + +The variable +@itemize @asis +@item +@code{cl_istream cl_stdin} +@end itemize +contains the standard input stream. + +These are the simple input functions: + +@table @code +@item int freadchar (cl_istream stream) +Reads a character from @code{stream}. Returns @code{cl_EOF} (not a @samp{char}!) +if the end of stream was encountered or an error occurred. + +@item int funreadchar (cl_istream stream, int c) +Puts back @code{c} onto @code{stream}. @code{c} must be the result of the +last @code{freadchar} operation on @code{stream}. +@end table + +Each of the classes @code{cl_N}, @code{cl_R}, @code{cl_RA}, @code{cl_I}, +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines, in @code{}, the following input function: + +@table @code +@item cl_istream operator>> (cl_istream stream, @var{type}& result) +Reads a number from @code{stream} and stores it in the @code{result}. +@end table + +The most flexible input functions, defined in @code{}, +are the following: + +@table @code +@item cl_N read_complex (cl_istream stream, const cl_read_flags& flags) +@itemx cl_R read_real (cl_istream stream, const cl_read_flags& flags) +@itemx cl_F read_float (cl_istream stream, const cl_read_flags& flags) +@itemx cl_RA read_rational (cl_istream stream, const cl_read_flags& flags) +@itemx cl_I read_integer (cl_istream stream, const cl_read_flags& flags) +Reads a number from @code{stream}. The @code{flags} are parameters which +affect the input syntax. Whitespace before the number is silently skipped. + +@item cl_N read_complex (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse) +@itemx cl_R read_real (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse) +@itemx cl_F read_float (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse) +@itemx cl_RA read_rational (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse) +@itemx cl_I read_integer (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse) +Reads a number from a string in memory. The @code{flags} are parameters which +affect the input syntax. The string starts at @code{string} and ends at +@code{string_limit} (exclusive limit). @code{string_limit} may also be +@code{NULL}, denoting the entire string, i.e. equivalent to +@code{string_limit = string + strlen(string)}. If @code{end_of_parse} is +@code{NULL}, the string in memory must contain exactly one number and nothing +more, else a fatal error will be signalled. If @code{end_of_parse} +is not @code{NULL}, @code{*end_of_parse} will be assigned a pointer past +the last parsed character (i.e. @code{string_limit} if nothing came after +the number). Whitespace is not allowed. +@end table + +The structure @code{cl_read_flags} contains the following fields: + +@table @code +@item cl_read_syntax_t syntax +The possible results of the read operation. Possible values are +@code{syntax_number}, @code{syntax_real}, @code{syntax_rational}, +@code{syntax_integer}, @code{syntax_float}, @code{syntax_sfloat}, +@code{syntax_ffloat}, @code{syntax_dfloat}, @code{syntax_lfloat}. + +@item cl_read_lsyntax_t lsyntax +Specifies the language-dependent syntax variant for the read operation. +Possible values are + +@table @code +@item lsyntax_standard +accept standard algebraic notation only, no complex numbers, +@item lsyntax_algebraic +accept the algebraic notation @code{@var{x}+@var{y}i} for complex numbers, +@item lsyntax_commonlisp +accept the @code{#b}, @code{#o}, @code{#x} syntaxes for binary, octal, +hexadecimal numbers, +@code{#@var{base}R} for rational numbers in a given base, +@code{#c(@var{realpart} @var{imagpart})} for complex numbers, +@item lsyntax_all +accept all of these extensions. +@end table + +@item unsigned int rational_base +The base in which rational numbers are read. + +@item cl_float_format_t float_flags.default_float_format +The float format used when reading floats with exponent marker @samp{e}. + +@item cl_float_format_t float_flags.default_lfloat_format +The float format used when reading floats with exponent marker @samp{l}. + +@item cl_boolean float_flags.mantissa_dependent_float_format +When this flag is true, floats specified with more digits than corresponding +to the exponent marker they contain, but without @var{_nnn} suffix, will get a +precision corresponding to their number of significant digits. +@end table + + +@node Output functions, , Input functions, Input/Output +@section Output functions + +Including @code{} defines a type @code{cl_ostream}, which is +the type of the first argument to all output functions. Unless you build +and use CLN with the macro CL_IO_STDIO being defined, @code{cl_ostream} +is the same as @code{ostream&}. + +The variable +@itemize @asis +@item +@code{cl_ostream cl_stdout} +@end itemize +contains the standard output stream. + +The variable +@itemize @asis +@item +@code{cl_ostream cl_stderr} +@end itemize +contains the standard error output stream. + +These are the simple output functions: + +@table @code +@item void fprintchar (cl_ostream stream, char c) +Prints the character @code{x} literally on the @code{stream}. + +@item void fprint (cl_ostream stream, const char * string) +Prints the @code{string} literally on the @code{stream}. + +@item void fprintdecimal (cl_ostream stream, int x) +@itemx void fprintdecimal (cl_ostream stream, const cl_I& x) +Prints the integer @code{x} in decimal on the @code{stream}. + +@item void fprintbinary (cl_ostream stream, const cl_I& x) +Prints the integer @code{x} in binary (base 2, without prefix) +on the @code{stream}. + +@item void fprintoctal (cl_ostream stream, const cl_I& x) +Prints the integer @code{x} in octal (base 8, without prefix) +on the @code{stream}. + +@item void fprinthexadecimal (cl_ostream stream, const cl_I& x) +Prints the integer @code{x} in hexadecimal (base 16, without prefix) +on the @code{stream}. +@end table + +Each of the classes @code{cl_N}, @code{cl_R}, @code{cl_RA}, @code{cl_I}, +@code{cl_F}, @code{cl_SF}, @code{cl_FF}, @code{cl_DF}, @code{cl_LF} +defines, in @code{}, the following output functions: + +@table @code +@item void fprint (cl_ostream stream, const @var{type}& x) +@itemx cl_ostream operator<< (cl_ostream stream, const @var{type}& x) +Prints the number @code{x} on the @code{stream}. The output may depend +on the global printer settings in the variable @code{cl_default_print_flags}. +The @code{ostream} flags and settings (flags, width and locale) are +ignored. +@end table + +The most flexible output function, defined in @code{}, +are the following: +@example +void print_complex (cl_ostream stream, const cl_print_flags& flags, + const cl_N& z); +void print_real (cl_ostream stream, const cl_print_flags& flags, + const cl_R& z); +void print_float (cl_ostream stream, const cl_print_flags& flags, + const cl_F& z); +void print_rational (cl_ostream stream, const cl_print_flags& flags, + const cl_RA& z); +void print_integer (cl_ostream stream, const cl_print_flags& flags, + const cl_I& z); +@end example +Prints the number @code{x} on the @code{stream}. The @code{flags} are +parameters which affect the output. + +The structure type @code{cl_print_flags} contains the following fields: + +@table @code +@item unsigned int rational_base +The base in which rational numbers are printed. Default is @code{10}. + +@item cl_boolean rational_readably +If this flag is true, rational numbers are printed with radix specifiers in +Common Lisp syntax (@code{#@var{n}R} or @code{#b} or @code{#o} or @code{#x} +prefixes, trailing dot). Default is false. + +@item cl_boolean float_readably +If this flag is true, type specific exponent markers have precedence over 'E'. +Default is false. + +@item cl_float_format_t default_float_format +Floating point numbers of this format will be printed using the 'E' exponent +marker. Default is @code{cl_float_format_ffloat}. + +@item cl_boolean complex_readably +If this flag is true, complex numbers will be printed using the Common Lisp +syntax @code{#C(@var{realpart} @var{imagpart})}. Default is false. + +@item cl_string univpoly_varname +Univariate polynomials with no explicit indeterminate name will be printed +using this variable name. Default is @code{"x"}. +@end table + +The global variable @code{cl_default_print_flags} contains the default values, +used by the function @code{fprint}, + + +@node Rings, Modular integers, Input/Output, Top +@chapter Rings + +CLN has a class of abstract rings. + +@example + Ring + cl_ring + +@end example + +Rings can be compared for equality: + +@table @code +@item bool operator== (const cl_ring&, const cl_ring&) +@itemx bool operator!= (const cl_ring&, const cl_ring&) +These compare two rings for equality. +@end table + +Given a ring @code{R}, the following members can be used. + +@table @code +@item void R->fprint (cl_ostream stream, const cl_ring_element& x) +@itemx cl_boolean R->equal (const cl_ring_element& x, const cl_ring_element& y) +@itemx cl_ring_element R->zero () +@itemx cl_boolean R->zerop (const cl_ring_element& x) +@itemx cl_ring_element R->plus (const cl_ring_element& x, const cl_ring_element& y) +@itemx cl_ring_element R->minus (const cl_ring_element& x, const cl_ring_element& y) +@itemx cl_ring_element R->uminus (const cl_ring_element& x) +@itemx cl_ring_element R->one () +@itemx cl_ring_element R->canonhom (const cl_I& x) +@itemx cl_ring_element R->mul (const cl_ring_element& x, const cl_ring_element& y) +@itemx cl_ring_element R->square (const cl_ring_element& x) +@itemx cl_ring_element R->expt_pos (const cl_ring_element& x, const cl_I& y) +@end table + +The following rings are built-in. + +@table @code +@item cl_null_ring cl_0_ring +The null ring, containing only zero. + +@item cl_complex_ring cl_C_ring +The ring of complex numbers. This corresponds to the type @code{cl_N}. + +@item cl_real_ring cl_R_ring +The ring of real numbers. This corresponds to the type @code{cl_R}. + +@item cl_rational_ring cl_RA_ring +The ring of rational numbers. This corresponds to the type @code{cl_RA}. + +@item cl_integer_ring cl_I_ring +The ring of integers. This corresponds to the type @code{cl_I}. +@end table + +Type tests can be performed for any of @code{cl_C_ring}, @code{cl_R_ring}, +@code{cl_RA_ring}, @code{cl_I_ring}: + +@table @code +@item cl_boolean instanceof (const cl_number& x, const cl_number_ring& R) +Tests whether the given number is an element of the number ring R. +@end table + + +@node Modular integers, Symbolic data types, Rings, Top +@chapter Modular integers + +@menu +* Modular integer rings:: +* Functions on modular integers:: +@end menu + +@node Modular integer rings, Functions on modular integers, Modular integers, Modular integers +@section Modular integer rings + +CLN implements modular integers, i.e. integers modulo a fixed integer N. +The modulus is explicitly part of every modular integer. CLN doesn't +allow you to (accidentally) mix elements of different modular rings, +e.g. @code{(3 mod 4) + (2 mod 5)} will result in a runtime error. +(Ideally one would imagine a generic data type @code{cl_MI(N)}, but C++ +doesn't have generic types. So one has to live with runtime checks.) + +The class of modular integer rings is + +@example + Ring + cl_ring + + | + | + Modular integer ring + cl_modint_ring + +@end example + +and the class of all modular integers (elements of modular integer rings) is + +@example + Modular integer + cl_MI + +@end example + +Modular integer rings are constructed using the function + +@table @code +@item cl_modint_ring cl_find_modint_ring (const cl_I& N) +This function returns the modular ring @samp{Z/NZ}. It takes care +of finding out about special cases of @code{N}, like powers of two +and odd numbers for which Montgomery multiplication will be a win, +and precomputes any necessary auxiliary data for computing modulo @code{N}. +There is a cache table of rings, indexed by @code{N} (or, more precisely, +by @code{abs(N)}). This ensures that the precomputation costs are reduced +to a minimum. +@end table + +Modular integer rings can be compared for equality: + +@table @code +@item bool operator== (const cl_modint_ring&, const cl_modint_ring&) +@itemx bool operator!= (const cl_modint_ring&, const cl_modint_ring&) +These compare two modular integer rings for equality. Two different calls +to @code{cl_find_modint_ring} with the same argument necessarily return the +same ring because it is memoized in the cache table. +@end table + +@node Functions on modular integers, , Modular integer rings, Modular integers +@section Functions on modular integers + +Given a modular integer ring @code{R}, the following members can be used. + +@table @code +@item cl_I R->modulus +This is the ring's modulus, normalized to be nonnegative: @code{abs(N)}. + +@item cl_MI R->zero() +This returns @code{0 mod N}. + +@item cl_MI R->one() +This returns @code{1 mod N}. + +@item cl_MI R->canonhom (const cl_I& x) +This returns @code{x mod N}. + +@item cl_I R->retract (const cl_MI& x) +This is a partial inverse function to @code{R->canonhom}. It returns the +standard representative (@code{>=0}, @code{random(cl_random_state& randomstate) +@itemx cl_MI R->random() +This returns a random integer modulo @code{N}. +@end table + +The following operations are defined on modular integers. + +@table @code +@item cl_modint_ring x.ring () +Returns the ring to which the modular integer @code{x} belongs. + +@item cl_MI operator+ (const cl_MI&, const cl_MI&) +Returns the sum of two modular integers. One of the arguments may also be +a plain integer. + +@item cl_MI operator- (const cl_MI&, const cl_MI&) +Returns the difference of two modular integers. One of the arguments may also be +a plain integer. + +@item cl_MI operator- (const cl_MI&) +Returns the negative of a modular integer. + +@item cl_MI operator* (const cl_MI&, const cl_MI&) +Returns the product of two modular integers. One of the arguments may also be +a plain integer. + +@item cl_MI square (const cl_MI&) +Returns the square of a modular integer. + +@item cl_MI recip (const cl_MI& x) +Returns the reciprocal @code{x^-1} of a modular integer @code{x}. @code{x} +must be coprime to the modulus, otherwise an error message is issued. + +@item cl_MI div (const cl_MI& x, const cl_MI& y) +Returns the quotient @code{x*y^-1} of two modular integers @code{x}, @code{y}. +@code{y} must be coprime to the modulus, otherwise an error message is issued. + +@item cl_MI expt_pos (const cl_MI& x, const cl_I& y) +@code{y} must be > 0. Returns @code{x^y}. + +@item cl_MI expt (const cl_MI& x, const cl_I& y) +Returns @code{x^y}. If @code{y} is negative, @code{x} must be coprime to the +modulus, else an error message is issued. + +@item cl_MI operator<< (const cl_MI& x, const cl_I& y) +Returns @code{x*2^y}. + +@item cl_MI operator>> (const cl_MI& x, const cl_I& y) +Returns @code{x*2^-y}. When @code{y} is positive, the modulus must be odd, +or an error message is issued. + +@item bool operator== (const cl_MI&, const cl_MI&) +@itemx bool operator!= (const cl_MI&, const cl_MI&) +Compares two modular integers, belonging to the same modular integer ring, +for equality. + +@item cl_boolean zerop (const cl_MI& x) +Returns true if @code{x} is @code{0 mod N}. +@end table + +The following output functions are defined (see also the chapter on +input/output). + +@table @code +@item void fprint (cl_ostream stream, const cl_MI& x) +@itemx cl_ostream operator<< (cl_ostream stream, const cl_MI& x) +Prints the modular integer @code{x} on the @code{stream}. The output may depend +on the global printer settings in the variable @code{cl_default_print_flags}. +@end table + + +@node Symbolic data types, Univariate polynomials, Modular integers, Top +@chapter Symbolic data types + +CLN implements two symbolic (non-numeric) data types: strings and symbols. + +@menu +* Strings:: +* Symbols:: +@end menu + +@node Strings, Symbols, Symbolic data types, Symbolic data types +@section Strings + +The class + +@example + String + cl_string + +@end example + +implements immutable strings. + +Strings are constructed through the following constructors: + +@table @code +@item cl_string (const char * s) +Returns an immutable copy of the (zero-terminated) C string @code{s}. + +@item cl_string (const char * ptr, unsigned long len) +Returns an immutable copy of the @code{len} characters at +@code{ptr[0]}, @dots{}, @code{ptr[len-1]}. NUL characters are allowed. +@end table + +The following functions are available on strings: + +@table @code +@item operator = +Assignment from @code{cl_string} and @code{const char *}. + +@item s.length() +@itemx strlen(s) +Returns the length of the string @code{s}. + +@item s[i] +Returns the @code{i}th character of the string @code{s}. +@code{i} must be in the range @code{0 <= i < s.length()}. + +@item bool equal (const cl_string& s1, const cl_string& s2) +Compares two strings for equality. One of the arguments may also be a +plain @code{const char *}. +@end table + +@node Symbols, , Strings, Symbolic data types +@section Symbols + +Symbols are uniquified strings: all symbols with the same name are shared. +This means that comparison of two symbols is fast (effectively just a pointer +comparison), whereas comparison of two strings must in the worst case walk +both strings until their end. +Symbols are used, for example, as tags for properties, as names of variables +in polynomial rings, etc. + +Symbols are constructed through the following constructor: + +@table @code +@item cl_symbol (const cl_string& s) +Looks up or creates a new symbol with a given name. +@end table + +The following operations are available on symbols: + +@table @code +@item cl_string (const cl_symbol& sym) +Conversion to @code{cl_string}: Returns the string which names the symbol +@code{sym}. + +@item bool equal (const cl_symbol& sym1, const cl_symbol& sym2) +Compares two symbols for equality. This is very fast. +@end table + + +@node Univariate polynomials, Internals, Symbolic data types, Top +@chapter Univariate polynomials + +@menu +* Univariate polynomial rings:: +* Functions on univariate polynomials:: +* Special polynomials:: +@end menu + +@node Univariate polynomial rings, Functions on univariate polynomials, Univariate polynomials, Univariate polynomials +@section Univariate polynomial rings + +CLN implements univariate polynomials (polynomials in one variable) over an +arbitrary ring. The indeterminate variable may be either unnamed (and will be +printed according to @code{cl_default_print_flags.univpoly_varname}, which +defaults to @samp{x}) or carry a given name. The base ring and the +indeterminate are explicitly part of every polynomial. CLN doesn't allow you to +(accidentally) mix elements of different polynomial rings, e.g. +@code{(a^2+1) * (b^3-1)} will result in a runtime error. (Ideally this should +return a multivariate polynomial, but they are not yet implemented in CLN.) + +The classes of univariate polynomial rings are + +@example + Ring + cl_ring + + | + | + Univariate polynomial ring + cl_univpoly_ring + + | + +----------------+-------------------+ + | | | + Complex polynomial ring | Modular integer polynomial ring + cl_univpoly_complex_ring | cl_univpoly_modint_ring + | + | + +----------------+ + | | + Real polynomial ring | + cl_univpoly_real_ring | + | + | + +----------------+ + | | + Rational polynomial ring | + cl_univpoly_rational_ring | + | + | + +----------------+ + | + Integer polynomial ring + cl_univpoly_integer_ring + +@end example + +and the corresponding classes of univariate polynomials are + +@example + Univariate polynomial + cl_UP + + | + +----------------+-------------------+ + | | | + Complex polynomial | Modular integer polynomial + cl_UP_N | cl_UP_MI + | + | + +----------------+ + | | + Real polynomial | + cl_UP_R | + | + | + +----------------+ + | | + Rational polynomial | + cl_UP_RA | + | + | + +----------------+ + | + Integer polynomial + cl_UP_I + +@end example + +Univariate polynomial rings are constructed using the functions + +@table @code +@item cl_univpoly_ring cl_find_univpoly_ring (const cl_ring& R) +@itemx cl_univpoly_ring cl_find_univpoly_ring (const cl_ring& R, const cl_symbol& varname) +This function returns the polynomial ring @samp{R[X]}, unnamed or named. +@code{R} may be an arbitrary ring. This function takes care of finding out +about special cases of @code{R}, such as the rings of complex numbers, +real numbers, rational numbers, integers, or modular integer rings. +There is a cache table of rings, indexed by @code{R} and @code{varname}. +This ensures that two calls of this function with the same arguments will +return the same polynomial ring. + +@item cl_univpoly_complex_ring cl_find_univpoly_ring (const cl_complex_ring& R) +@itemx cl_univpoly_complex_ring cl_find_univpoly_ring (const cl_complex_ring& R, const cl_symbol& varname) +@itemx cl_univpoly_real_ring cl_find_univpoly_ring (const cl_real_ring& R) +@itemx cl_univpoly_real_ring cl_find_univpoly_ring (const cl_real_ring& R, const cl_symbol& varname) +@itemx cl_univpoly_rational_ring cl_find_univpoly_ring (const cl_rational_ring& R) +@itemx cl_univpoly_rational_ring cl_find_univpoly_ring (const cl_rational_ring& R, const cl_symbol& varname) +@itemx cl_univpoly_integer_ring cl_find_univpoly_ring (const cl_integer_ring& R) +@itemx cl_univpoly_integer_ring cl_find_univpoly_ring (const cl_integer_ring& R, const cl_symbol& varname) +@itemx cl_univpoly_modint_ring cl_find_univpoly_ring (const cl_modint_ring& R) +@itemx cl_univpoly_modint_ring cl_find_univpoly_ring (const cl_modint_ring& R, const cl_symbol& varname) +These functions are equivalent to the general @code{cl_find_univpoly_ring}, +only the return type is more specific, according to the base ring's type. +@end table + +@node Functions on univariate polynomials, Special polynomials, Univariate polynomial rings, Univariate polynomials +@section Functions on univariate polynomials + +Given a univariate polynomial ring @code{R}, the following members can be used. + +@table @code +@item cl_ring R->basering() +This returns the base ring, as passed to @samp{cl_find_univpoly_ring}. + +@item cl_UP R->zero() +This returns @code{0 in R}, a polynomial of degree -1. + +@item cl_UP R->one() +This returns @code{1 in R}, a polynomial of degree <= 0. + +@item cl_UP R->canonhom (const cl_I& x) +This returns @code{x in R}, a polynomial of degree <= 0. + +@item cl_UP R->monomial (const cl_ring_element& x, uintL e) +This returns a sparse polynomial: @code{x * X^e}, where @code{X} is the +indeterminate. + +@item cl_UP R->create (sintL degree) +Creates a new polynomial with a given degree. The zero polynomial has degree +@code{-1}. After creating the polynomial, you should put in the coefficients, +using the @code{set_coeff} member function, and then call the @code{finalize} +member function. +@end table + +The following are the only destructive operations on univariate polynomials. + +@table @code +@item void set_coeff (cl_UP& x, uintL index, const cl_ring_element& y) +This changes the coefficient of @code{X^index} in @code{x} to be @code{y}. +After changing a polynomial and before applying any "normal" operation on it, +you should call its @code{finalize} member function. + +@item void finalize (cl_UP& x) +This function marks the endpoint of destructive modifications of a polynomial. +It normalizes the internal representation so that subsequent computations have +less overhead. Doing normal computations on unnormalized polynomials may +produce wrong results or crash the program. +@end table + +The following operations are defined on univariate polynomials. + +@table @code +@item cl_univpoly_ring x.ring () +Returns the ring to which the univariate polynomial @code{x} belongs. + +@item cl_UP operator+ (const cl_UP&, const cl_UP&) +Returns the sum of two univariate polynomials. + +@item cl_UP operator- (const cl_UP&, const cl_UP&) +Returns the difference of two univariate polynomials. + +@item cl_UP operator- (const cl_UP&) +Returns the negative of a univariate polynomial. + +@item cl_UP operator* (const cl_UP&, const cl_UP&) +Returns the product of two univariate polynomials. One of the arguments may +also be a plain integer or an element of the base ring. + +@item cl_UP square (const cl_UP&) +Returns the square of a univariate polynomial. + +@item cl_UP expt_pos (const cl_UP& x, const cl_I& y) +@code{y} must be > 0. Returns @code{x^y}. + +@item bool operator== (const cl_UP&, const cl_UP&) +@itemx bool operator!= (const cl_UP&, const cl_UP&) +Compares two univariate polynomials, belonging to the same univariate +polynomial ring, for equality. + +@item cl_boolean zerop (const cl_UP& x) +Returns true if @code{x} is @code{0 in R}. + +@item sintL degree (const cl_UP& x) +Returns the degree of the polynomial. The zero polynomial has degree @code{-1}. + +@item cl_ring_element coeff (const cl_UP& x, uintL index) +Returns the coefficient of @code{X^index} in the polynomial @code{x}. + +@item cl_ring_element x (const cl_ring_element& y) +Evaluation: If @code{x} is a polynomial and @code{y} belongs to the base ring, +then @samp{x(y)} returns the value of the substitution of @code{y} into +@code{x}. + +@item cl_UP deriv (const cl_UP& x) +Returns the derivative of the polynomial @code{x} with respect to the +indeterminate @code{X}. +@end table + +The following output functions are defined (see also the chapter on +input/output). + +@table @code +@item void fprint (cl_ostream stream, const cl_UP& x) +@itemx cl_ostream operator<< (cl_ostream stream, const cl_UP& x) +Prints the univariate polynomial @code{x} on the @code{stream}. The output may +depend on the global printer settings in the variable +@code{cl_default_print_flags}. +@end table + +@node Special polynomials, , Functions on univariate polynomials, Univariate polynomials +@section Special polynomials + +The following functions return special polynomials. + +@table @code +@item cl_UP_I cl_tschebychev (sintL n) +Returns the n-th Tchebychev polynomial (n >= 0). + +@item cl_UP_I cl_hermite (sintL n) +Returns the n-th Hermite polynomial (n >= 0). + +@item cl_UP_RA cl_legendre (sintL n) +Returns the n-th Legendre polynomial (n >= 0). + +@item cl_UP_I cl_laguerre (sintL n) +Returns the n-th Laguerre polynomial (n >= 0). +@end table + +Information how to derive the differential equation satisfied by each +of these polynomials from their definition can be found in the +@code{doc/polynomial/} directory. + + +@node Internals, Using the library, Univariate polynomials, Top +@chapter Internals + +@menu +* Why C++ ?:: +* Memory efficiency:: +* Speed efficiency:: +* Garbage collection:: +@end menu + +@node Why C++ ?, Memory efficiency, Internals, Internals +@section Why C++ ? + +Using C++ as an implementation language provides + +@itemize @bullet +@item +Efficiency: It compiles to machine code. + +@item +Portability: It runs on all platforms supporting a C++ compiler. Because +of the availability of GNU C++, this includes all currently used 32-bit and +64-bit platforms, independently of the quality of the vendor's C++ compiler. + +@item +Type safety: The C++ compilers knows about the number types and complains if, +for example, you try to assign a float to an integer variable. However, +a drawback is that C++ doesn't know about generic types, hence a restriction +like that @code{operation+ (const cl_MI&, const cl_MI&)} requires that both +arguments belong to the same modular ring cannot be expressed as a compile-time +information. + +@item +Algebraic syntax: The elementary operations @code{+}, @code{-}, @code{*}, +@code{=}, @code{==}, ... can be used in infix notation, which is more +convenient than Lisp notation @samp{(+ x y)} or C notation @samp{add(x,y,&z)}. +@end itemize + +With these language features, there is no need for two separate languages, +one for the implementation of the library and one in which the library's users +can program. This means that a prototype implementation of an algorithm +can be integrated into the library immediately after it has been tested and +debugged. No need to rewrite it in a low-level language after having prototyped +in a high-level language. + + +@node Memory efficiency, Speed efficiency, Why C++ ?, Internals +@section Memory efficiency + +In order to save memory allocations, CLN implements: + +@itemize @bullet +@item +Object sharing: An operation like @code{x+0} returns @code{x} without copying +it. +@item +Garbage collection: A reference counting mechanism makes sure that any +number object's storage is freed immediately when the last reference to the +object is gone. +@item +Small integers are represented as immediate values instead of pointers +to heap allocated storage. This means that integers @code{> -2^29}, +@code{< 2^29} don't consume heap memory, unless they were explicitly allocated +on the heap. +@end itemize + + +@node Speed efficiency, Garbage collection, Memory efficiency, Internals +@section Speed efficiency + +Speed efficiency is obtained by the combination of the following tricks +and algorithms: + +@itemize @bullet +@item +Small integers, being represented as immediate values, don't require +memory access, just a couple of instructions for each elementary operation. +@item +The kernel of CLN has been written in assembly language for some CPUs +(@code{i386}, @code{m68k}, @code{sparc}, @code{mips}, @code{arm}). +@item +On all CPUs, CLN uses the superefficient low-level routines from GNU +GMP version 2. +@item +For large numbers, CLN uses, instead of the standard @code{O(N^2)} +algorithm, the Karatsuba multiplication, which is an +@iftex +@tex +$O(N^{1.6})$ +@end tex +@end iftex +@ifinfo +@code{O(N^1.6)} +@end ifinfo +algorithm. +@item +For very large numbers (more than 12000 decimal digits), CLN uses +@iftex +Sch{@"o}nhage-Strassen +@end iftex +@ifinfo +Schönhage-Strassen +@end ifinfo +multiplication, which is an asymptotically +optimal multiplication algorithm. +@item +These fast multiplication algorithms also give improvements in the speed +of division and radix conversion. +@end itemize + + +@node Garbage collection, , Speed efficiency, Internals +@section Garbage collection + +All the number classes are reference count classes: They only contain a pointer +to an object in the heap. Upon construction, assignment and destruction of +number objects, only the objects' reference count are manipulated. + +Memory occupied by number objects are automatically reclaimed as soon as +their reference count drops to zero. + +For number rings, another strategy is implemented: There is a cache of, +for example, the modular integer rings. A modular integer ring is destroyed +only if its reference count dropped to zero and the cache is about to be +resized. The effect of this strategy is that recently used rings remain +cached, whereas undue memory consumption through cached rings is avoided. + + +@node Using the library, Customizing, Internals, Top +@chapter Using the library + +For the following discussion, we will assume that you have installed +the CLN source in @code{$CLN_DIR} and built it in @code{$CLN_TARGETDIR}. +For example, for me it's @code{CLN_DIR="$HOME/cln"} and +@code{CLN_TARGETDIR="$HOME/cln/linuxelf"}. You might define these as +environment variables, or directly substitute the appropriate values. + + +@menu +* Compiler options:: +* Include files:: +* An Example:: +* Debugging support:: +@end menu + +@node Compiler options, Include files, Using the library, Using the library +@section Compiler options + +Until you have installed CLN in a public place, the following options are +needed: + +When you compile CLN application code, add the flags +@example + -I$CLN_DIR/include -I$CLN_TARGETDIR/include +@end example +to the C++ compiler's command line (@code{make} variable CFLAGS or CXXFLAGS). +When you link CLN application code to form an executable, add the flags +@example + $CLN_TARGETDIR/src/libcln.a +@end example +to the C/C++ compiler's command line (@code{make} variable LIBS). + +If you did a @code{make install}, the include files are installed in a +public directory (normally @code{/usr/local/include}), hence you don't +need special flags for compiling. The library has been installed to a +public directory as well (normally @code{/usr/local/lib}), hence when +linking a CLN application it is sufficient to give the flag @code{-lcln}. + + +@node Include files, An Example, Compiler options, Using the library +@section Include files + +Here is a summary of the include files and their contents. + +@table @code +@item +General definitions, reference counting, garbage collection. +@item +The class cl_number. +@item +Functions for class cl_N, the complex numbers. +@item +Functions for class cl_R, the real numbers. +@item +Functions for class cl_F, the floats. +@item +Functions for class cl_SF, the short-floats. +@item +Functions for class cl_FF, the single-floats. +@item +Functions for class cl_DF, the double-floats. +@item +Functions for class cl_LF, the long-floats. +@item +Functions for class cl_RA, the rational numbers. +@item +Functions for class cl_I, the integers. +@item +Input/Output. +@item +Input/Output for class cl_N, the complex numbers. +@item +Input/Output for class cl_R, the real numbers. +@item +Input/Output for class cl_F, the floats. +@item +Input/Output for class cl_SF, the short-floats. +@item +Input/Output for class cl_FF, the single-floats. +@item +Input/Output for class cl_DF, the double-floats. +@item +Input/Output for class cl_LF, the long-floats. +@item +Input/Output for class cl_RA, the rational numbers. +@item +Input/Output for class cl_I, the integers. +@item +Flags for customizing input operations. +@item +Flags for customizing output operations. +@item +@code{cl_malloc_hook}, @code{cl_free_hook}. +@item +@code{cl_abort}. +@item +Conditions/exceptions. +@item +Strings. +@item +Symbols. +@item +Property lists. +@item +General rings. +@item +The null ring. +@item +The ring of complex numbers. +@item +The ring of real numbers. +@item +The ring of rational numbers. +@item +The ring of integers. +@item +Number threory functions. +@item +Modular integers. +@item +Vectors. +@item +General vectors. +@item +General vectors over cl_number. +@item +General vectors over cl_N. +@item +General vectors over cl_R. +@item +General vectors over cl_RA. +@item +General vectors over cl_I. +@item +General vectors of modular integers. +@item +Simple vectors. +@item +Simple vectors over cl_number. +@item +Simple vectors over cl_N. +@item +Simple vectors over cl_R. +@item +Simple vectors over cl_RA. +@item +Simple vectors over cl_I. +@item +Simple vectors of general ring elements. +@item +Univariate polynomials. +@item +Univariate polynomials over the integers. +@item +Univariate polynomials over the rational numbers. +@item +Univariate polynomials over the real numbers. +@item +Univariate polynomials over the complex numbers. +@item +Univariate polynomials over modular integer rings. +@item +Timing facilities. +@item +Includes all of the above. +@end table + + +@node An Example, Debugging support, Include files, Using the library +@section An Example + +A function which computes the nth Fibonacci number can be written as follows. + +@example +#include +#include + +// Returns F_n, computed as the nearest integer to +// ((1+sqrt(5))/2)^n/sqrt(5). Assume n>=0. +const cl_I fibonacci (int n) +@{ + // Need a precision of ((1+sqrt(5))/2)^-n. + cl_float_format_t prec = cl_float_format((int)(0.208987641*n+5)); + cl_R sqrt5 = sqrt(cl_float(5,prec)); + cl_R phi = (1+sqrt5)/2; + return round1( expt(phi,n)/sqrt5 ); +@} +@end example + +Let's explain what is going on in detail. + +The include file @code{} is necessary because the type +@code{cl_I} is used in the function, and the include file @code{} +is needed for the type @code{cl_R} and the floating point number functions. +The order of the include files does not matter. + +Then comes the function declaration. The argument is an @code{int}, the +result an integer. The return type is defined as @samp{const cl_I}, not +simply @samp{cl_I}, because that allows the compiler to detect typos like +@samp{fibonacci(n) = 100}. It would be possible to declare the return +type as @code{const cl_R} (real number) or even @code{const cl_N} (complex +number). We use the most specialized possible return type because functions +which call @samp{fibonacci} will be able to profit from the compiler's type +analysis: Adding two integers is slightly more efficient than adding the +same objects declared as complex numbers, because it needs less type +dispatch. Also, when linking to CLN as a non-shared library, this minimizes +the size of the resulting executable program. + +The result will be computed as expt(phi,n)/sqrt(5), rounded to the nearest +integer. In order to get a correct result, the absolute error should be less +than 1/2, i.e. the relative error should be less than sqrt(5)/(2*expt(phi,n)). +To this end, the first line computes a floating point precision for sqrt(5) +and phi. + +Then sqrt(5) is computed by first converting the integer 5 to a floating point +number and than taking the square root. The converse, first taking the square +root of 5, and then converting to the desired precision, would not work in +CLN: The square root would be computed to a default precision (normally +single-float precision), and the following conversion could not help about +the lacking accuracy. This is because CLN is not a symbolic computer algebra +system and does not represent sqrt(5) in a non-numeric way. + +The type @code{cl_R} for sqrt5 and, in the following line, phi is the only +possible choice. You cannot write @code{cl_F} because the C++ compiler can +only infer that @code{cl_float(5,prec)} is a real number. You cannot write +@code{cl_N} because a @samp{round1} does not exist for general complex +numbers. + +When the function returns, all the local variables in the function are +automatically reclaimed (garbage collected). Only the result survives and +gets passed to the caller. + + +@node Debugging support, , An Example, Using the library +@section Debugging support + +When debugging a CLN application with GNU @code{gdb}, two facilities are +available from the library: + +@itemize @bullet +@item The library does type checks, range checks, consistency checks at +many places. When one of these fails, the function @code{cl_abort()} is +called. Its default implementation is to perform an @code{exit(1)}, so +you won't have a core dump. But for debugging, it is best to set a +breakpoint at this function: +@example +(gdb) break cl_abort +@end example +When this breakpoint is hit, look at the stack's backtrace: +@example +(gdb) where +@end example + +@item The debugger's normal @code{print} command doesn't know about +CLN's types and therefore prints mostly useless hexadecimal addresses. +CLN offers a function @code{cl_print}, callable from the debugger, +for printing number objects. In order to get this function, you have +to define the macro @samp{CL_DEBUG} and then include all the header files +for which you want @code{cl_print} debugging support. For example: +@example +#define CL_DEBUG +#include +@end example +Now, if you have in your program a variable @code{cl_string s}, and +inspect it under @code{gdb}, the output may look like this: +@example +(gdb) print s +$7 = @{ = @{ = @{pointer = 0x8055b60, heappointer = 0x8055b60, + word = 134568800@}@}, @} +(gdb) call cl_print(s) +(cl_string) "" +$8 = 134568800 +@end example +Note that the output of @code{cl_print} goes to the program's error output, +not to gdb's standard output. + +Note, however, that the above facility does not work with all CLN types, +only with number objects and similar. Therefore CLN offers a member function +@code{debug_print()} on all CLN types. The same macro @samp{CL_DEBUG} +is needed for this member function to be implemented. Under @code{gdb}, +you call it like this: +@example +(gdb) print s +$7 = @{ = @{ = @{pointer = 0x8055b60, heappointer = 0x8055b60, + word = 134568800@}@}, @} +(gdb) call s.debug_print() +(cl_string) "" +(gdb) define cprint +>call ($1).debug_print() +>end +(gdb) cprint s +(cl_string) "" +@end example +Unfortunately, this feature does not seem to work under all circumstances. +@end itemize + + +@node Customizing, Index, Using the library, Top +@chapter Customizing + +@menu +* Error handling:: +* Floating-point underflow:: +* Customizing I/O:: +* Customizing the memory allocator:: +@end menu + +@node Error handling, Floating-point underflow, Customizing, Customizing +@section Error handling + +When a fatal error occurs, an error message is output to the standard error +output stream, and the function @code{cl_abort} is called. The default +version of this function (provided in the library) terminates the application. +To catch such a fatal error, you need to define the function @code{cl_abort} +yourself, with the prototype +@example +#include +void cl_abort (void); +@end example +This function must not return control to its caller. + + +@node Floating-point underflow, Customizing I/O, Error handling, Customizing +@section Floating-point underflow + +Floating point underflow denotes the situation when a floating-point number +is to be created which is so close to @code{0} that its exponent is too +low to be represented internally. By default, this causes a fatal error. +If you set the global variable +@example +cl_boolean cl_inhibit_floating_point_underflow +@end example +to @code{cl_true}, the error will be inhibited, and a floating-point zero +will be generated instead. +The default value of @code{cl_inhibit_floating_point_underflow} is +@code{cl_false}. + + +@node Customizing I/O, Customizing the memory allocator, Floating-point underflow, Customizing +@section Customizing I/O + +The output of the function @code{fprint} may be customized by changing the +value of the global variable @code{cl_default_print_flags}. + + +@node Customizing the memory allocator, , Customizing I/O, Customizing +@section Customizing the memory allocator + +Every memory allocation of CLN is done through the function pointer +@code{cl_malloc_hook}. Freeing of this memory is done through the function +pointer @code{cl_free_hook}. The default versions of these functions, +provided in the library, call @code{malloc} and @code{free} and check +the @code{malloc} result against @code{NULL}. +If you want to provide another memory allocator, you need to define +the variables @code{cl_malloc_hook} and @code{cl_free_hook} yourself, +like this: +@example +#include +void* (*cl_malloc_hook) (size_t size) = @dots{}; +void (*cl_free_hook) (void* ptr) = @dots{}; +@end example +The @code{cl_malloc_hook} function must not return a @code{NULL} pointer. + +It is not possible to change the memory allocator at runtime, because +it is already called at program startup by the constructors of some +global variables. + + + + +@c Indices + +@node Index, , Customizing, Top +@unnumbered Index + +@printindex my + + +@c Table of contents +@contents + + +@bye diff --git a/doc/cln_1.html b/doc/cln_1.html new file mode 100644 index 0000000..6a1cb07 --- /dev/null +++ b/doc/cln_1.html @@ -0,0 +1,169 @@ + + + + +CLN, a Class Library for Numbers - 1. Introduction + + +Go to the first, previous, next, last section, table of contents. +


+ + +

1. Introduction

+ +

+CLN is a library for computations with all kinds of numbers. +It has a rich set of number classes: + + + +

    +
  • + +Integers (with unlimited precision), + +
  • + +Rational numbers, + +
  • + +Floating-point numbers: + + +
      +
    • + +Short float, +
    • + +Single float, +
    • + +Double float, +
    • + +Long float (with unlimited precision), +
    + +
  • + +Complex numbers, + +
  • + +Modular integers (integers modulo a fixed integer), + +
  • + +Univariate polynomials. +
+ +

+The subtypes of the complex numbers among these are exactly the +types of numbers known to the Common Lisp language. Therefore +CLN can be used for Common Lisp implementations, giving +`CLN' another meaning: it becomes an abbreviation of +"Common Lisp Numbers". + + +

+The CLN package implements + + + +

    +
  • + +Elementary functions (+, -, *, /, sqrt, +comparisons, ...), + +
  • + +Logical functions (logical and, or, not, ...), + +
  • + +Transcendental functions (exponential, logarithmic, trigonometric, hyperbolic +functions and their inverse functions). +
+ +

+CLN is a C++ library. Using C++ as an implementation language provides + + + +

    +
  • + +efficiency: it compiles to machine code, +
  • + +type safety: the C++ compiler knows about the number types and complains +if, for example, you try to assign a float to an integer variable. +
  • + +algebraic syntax: You can use the +, -, *, =, +==, ... operators as in C or C++. +
+ +

+CLN is memory efficient: + + + +

    +
  • + +Small integers and short floats are immediate, not heap allocated. +
  • + +Heap-allocated memory is reclaimed through an automatic, non-interruptive +garbage collection. +
+ +

+CLN is speed efficient: + + + +

    +
  • + +The kernel of CLN has been written in assembly language for some CPUs +(i386, m68k, sparc, mips, arm). +
  • + +On all CPUs, CLN uses the superefficient low-level routines from GNU +GMP version 2. +
  • + +It uses Karatsuba multiplication, which is significantly faster +for large numbers than the standard multiplication algorithm. +
  • + +For very large numbers (more than 12000 decimal digits), it uses +Schönhage-Strassen +multiplication, which is an asymptotically +optimal multiplication algorithm, for multiplication, division and +radix conversion. +
+ +

+CLN aims at being easily integrated into larger software packages: + + + +

    +
  • + +The garbage collection imposes no burden on the main application. +
  • + +The library provides hooks for memory allocation and exceptions. +
+ +


+Go to the first, previous, next, last section, table of contents. + + diff --git a/doc/cln_10.html b/doc/cln_10.html new file mode 100644 index 0000000..059d504 --- /dev/null +++ b/doc/cln_10.html @@ -0,0 +1,153 @@ + + + + +CLN, a Class Library for Numbers - 10. Internals + + +Go to the first, previous, next, last section, table of contents. +


+ + +

10. Internals

+ + + +

10.1 Why C++ ?

+ +

+Using C++ as an implementation language provides + + + +

    +
  • + +Efficiency: It compiles to machine code. + +
  • + +Portability: It runs on all platforms supporting a C++ compiler. Because +of the availability of GNU C++, this includes all currently used 32-bit and +64-bit platforms, independently of the quality of the vendor's C++ compiler. + +
  • + +Type safety: The C++ compilers knows about the number types and complains if, +for example, you try to assign a float to an integer variable. However, +a drawback is that C++ doesn't know about generic types, hence a restriction +like that operation+ (const cl_MI&, const cl_MI&) requires that both +arguments belong to the same modular ring cannot be expressed as a compile-time +information. + +
  • + +Algebraic syntax: The elementary operations +, -, *, +=, ==, ... can be used in infix notation, which is more +convenient than Lisp notation `(+ x y)' or C notation `add(x,y,&z)'. +
+ +

+With these language features, there is no need for two separate languages, +one for the implementation of the library and one in which the library's users +can program. This means that a prototype implementation of an algorithm +can be integrated into the library immediately after it has been tested and +debugged. No need to rewrite it in a low-level language after having prototyped +in a high-level language. + + + + +

10.2 Memory efficiency

+ +

+In order to save memory allocations, CLN implements: + + + +

    +
  • + +Object sharing: An operation like x+0 returns x without copying +it. +
  • + +Garbage collection: A reference counting mechanism makes sure that any +number object's storage is freed immediately when the last reference to the +object is gone. +
  • + +Small integers are represented as immediate values instead of pointers +to heap allocated storage. This means that integers > -2^29, +< 2^29 don't consume heap memory, unless they were explicitly allocated +on the heap. +
+ + + +

10.3 Speed efficiency

+ +

+Speed efficiency is obtained by the combination of the following tricks +and algorithms: + + + +

    +
  • + +Small integers, being represented as immediate values, don't require +memory access, just a couple of instructions for each elementary operation. +
  • + +The kernel of CLN has been written in assembly language for some CPUs +(i386, m68k, sparc, mips, arm). +
  • + +On all CPUs, CLN uses the superefficient low-level routines from GNU +GMP version 2. +
  • + +For large numbers, CLN uses, instead of the standard O(N^2) +algorithm, the Karatsuba multiplication, which is an +O(N^1.6) +algorithm. +
  • + +For very large numbers (more than 12000 decimal digits), CLN uses +Schönhage-Strassen +multiplication, which is an asymptotically +optimal multiplication algorithm. +
  • + +These fast multiplication algorithms also give improvements in the speed +of division and radix conversion. +
+ + + +

10.4 Garbage collection

+ +

+All the number classes are reference count classes: They only contain a pointer +to an object in the heap. Upon construction, assignment and destruction of +number objects, only the objects' reference count are manipulated. + + +

+Memory occupied by number objects are automatically reclaimed as soon as +their reference count drops to zero. + + +

+For number rings, another strategy is implemented: There is a cache of, +for example, the modular integer rings. A modular integer ring is destroyed +only if its reference count dropped to zero and the cache is about to be +resized. The effect of this strategy is that recently used rings remain +cached, whereas undue memory consumption through cached rings is avoided. + + +


+Go to the first, previous, next, last section, table of contents. + + diff --git a/doc/cln_11.html b/doc/cln_11.html new file mode 100644 index 0000000..61ab64b --- /dev/null +++ b/doc/cln_11.html @@ -0,0 +1,413 @@ + + + + +CLN, a Class Library for Numbers - 11. Using the library + + +Go to the first, previous, next, last section, table of contents. +


+ + +

11. Using the library

+ +

+For the following discussion, we will assume that you have installed +the CLN source in $CLN_DIR and built it in $CLN_TARGETDIR. +For example, for me it's CLN_DIR="$HOME/cln" and +CLN_TARGETDIR="$HOME/cln/linuxelf". You might define these as +environment variables, or directly substitute the appropriate values. + + + + +

11.1 Compiler options

+ +

+Until you have installed CLN in a public place, the following options are +needed: + + +

+When you compile CLN application code, add the flags + +

+   -I$CLN_DIR/include -I$CLN_TARGETDIR/include
+
+ +

+to the C++ compiler's command line (make variable CFLAGS or CXXFLAGS). +When you link CLN application code to form an executable, add the flags + +

+   $CLN_TARGETDIR/src/libcln.a
+
+ +

+to the C/C++ compiler's command line (make variable LIBS). + + +

+If you did a make install, the include files are installed in a +public directory (normally /usr/local/include), hence you don't +need special flags for compiling. The library has been installed to a +public directory as well (normally /usr/local/lib), hence when +linking a CLN application it is sufficient to give the flag -lcln. + + + + +

11.2 Include files

+ +

+Here is a summary of the include files and their contents. + + +

+ +
<cl_object.h> +
+General definitions, reference counting, garbage collection. +
<cl_number.h> +
+The class cl_number. +
<cl_complex.h> +
+Functions for class cl_N, the complex numbers. +
<cl_real.h> +
+Functions for class cl_R, the real numbers. +
<cl_float.h> +
+Functions for class cl_F, the floats. +
<cl_sfloat.h> +
+Functions for class cl_SF, the short-floats. +
<cl_ffloat.h> +
+Functions for class cl_FF, the single-floats. +
<cl_dfloat.h> +
+Functions for class cl_DF, the double-floats. +
<cl_lfloat.h> +
+Functions for class cl_LF, the long-floats. +
<cl_rational.h> +
+Functions for class cl_RA, the rational numbers. +
<cl_integer.h> +
+Functions for class cl_I, the integers. +
<cl_io.h> +
+Input/Output. +
<cl_complex_io.h> +
+Input/Output for class cl_N, the complex numbers. +
<cl_real_io.h> +
+Input/Output for class cl_R, the real numbers. +
<cl_float_io.h> +
+Input/Output for class cl_F, the floats. +
<cl_sfloat_io.h> +
+Input/Output for class cl_SF, the short-floats. +
<cl_ffloat_io.h> +
+Input/Output for class cl_FF, the single-floats. +
<cl_dfloat_io.h> +
+Input/Output for class cl_DF, the double-floats. +
<cl_lfloat_io.h> +
+Input/Output for class cl_LF, the long-floats. +
<cl_rational_io.h> +
+Input/Output for class cl_RA, the rational numbers. +
<cl_integer_io.h> +
+Input/Output for class cl_I, the integers. +
<cl_input.h> +
+Flags for customizing input operations. +
<cl_output.h> +
+Flags for customizing output operations. +
<cl_malloc.h> +
+cl_malloc_hook, cl_free_hook. +
<cl_abort.h> +
+cl_abort. +
<cl_condition.h> +
+Conditions/exceptions. +
<cl_string.h> +
+Strings. +
<cl_symbol.h> +
+Symbols. +
<cl_proplist.h> +
+Property lists. +
<cl_ring.h> +
+General rings. +
<cl_null_ring.h> +
+The null ring. +
<cl_complex_ring.h> +
+The ring of complex numbers. +
<cl_real_ring.h> +
+The ring of real numbers. +
<cl_rational_ring.h> +
+The ring of rational numbers. +
<cl_integer_ring.h> +
+The ring of integers. +
<cl_numtheory.h> +
+Number threory functions. +
<cl_modinteger.h> +
+Modular integers. +
<cl_V.h> +
+Vectors. +
<cl_GV.h> +
+General vectors. +
<cl_GV_number.h> +
+General vectors over cl_number. +
<cl_GV_complex.h> +
+General vectors over cl_N. +
<cl_GV_real.h> +
+General vectors over cl_R. +
<cl_GV_rational.h> +
+General vectors over cl_RA. +
<cl_GV_integer.h> +
+General vectors over cl_I. +
<cl_GV_modinteger.h> +
+General vectors of modular integers. +
<cl_SV.h> +
+Simple vectors. +
<cl_SV_number.h> +
+Simple vectors over cl_number. +
<cl_SV_complex.h> +
+Simple vectors over cl_N. +
<cl_SV_real.h> +
+Simple vectors over cl_R. +
<cl_SV_rational.h> +
+Simple vectors over cl_RA. +
<cl_SV_integer.h> +
+Simple vectors over cl_I. +
<cl_SV_ringelt.h> +
+Simple vectors of general ring elements. +
<cl_univpoly.h> +
+Univariate polynomials. +
<cl_univpoly_integer.h> +
+Univariate polynomials over the integers. +
<cl_univpoly_rational.h> +
+Univariate polynomials over the rational numbers. +
<cl_univpoly_real.h> +
+Univariate polynomials over the real numbers. +
<cl_univpoly_complex.h> +
+Univariate polynomials over the complex numbers. +
<cl_univpoly_modint.h> +
+Univariate polynomials over modular integer rings. +
<cl_timing.h> +
+Timing facilities. +
<cln.h> +
+Includes all of the above. +
+ + + +

11.3 An Example

+ +

+A function which computes the nth Fibonacci number can be written as follows. + + + +

+#include <cl_integer.h>
+#include <cl_real.h>
+
+// Returns F_n, computed as the nearest integer to
+// ((1+sqrt(5))/2)^n/sqrt(5). Assume n>=0.
+const cl_I fibonacci (int n)
+{
+        // Need a precision of ((1+sqrt(5))/2)^-n.
+        cl_float_format_t prec = cl_float_format((int)(0.208987641*n+5));
+        cl_R sqrt5 = sqrt(cl_float(5,prec));
+        cl_R phi = (1+sqrt5)/2;
+        return round1( expt(phi,n)/sqrt5 );
+}
+
+ +

+Let's explain what is going on in detail. + + +

+The include file <cl_integer.h> is necessary because the type +cl_I is used in the function, and the include file <cl_real.h> +is needed for the type cl_R and the floating point number functions. +The order of the include files does not matter. + + +

+Then comes the function declaration. The argument is an int, the +result an integer. The return type is defined as `const cl_I', not +simply `cl_I', because that allows the compiler to detect typos like +`fibonacci(n) = 100'. It would be possible to declare the return +type as const cl_R (real number) or even const cl_N (complex +number). We use the most specialized possible return type because functions +which call `fibonacci' will be able to profit from the compiler's type +analysis: Adding two integers is slightly more efficient than adding the +same objects declared as complex numbers, because it needs less type +dispatch. Also, when linking to CLN as a non-shared library, this minimizes +the size of the resulting executable program. + + +

+The result will be computed as expt(phi,n)/sqrt(5), rounded to the nearest +integer. In order to get a correct result, the absolute error should be less +than 1/2, i.e. the relative error should be less than sqrt(5)/(2*expt(phi,n)). +To this end, the first line computes a floating point precision for sqrt(5) +and phi. + + +

+Then sqrt(5) is computed by first converting the integer 5 to a floating point +number and than taking the square root. The converse, first taking the square +root of 5, and then converting to the desired precision, would not work in +CLN: The square root would be computed to a default precision (normally +single-float precision), and the following conversion could not help about +the lacking accuracy. This is because CLN is not a symbolic computer algebra +system and does not represent sqrt(5) in a non-numeric way. + + +

+The type cl_R for sqrt5 and, in the following line, phi is the only +possible choice. You cannot write cl_F because the C++ compiler can +only infer that cl_float(5,prec) is a real number. You cannot write +cl_N because a `round1' does not exist for general complex +numbers. + + +

+When the function returns, all the local variables in the function are +automatically reclaimed (garbage collected). Only the result survives and +gets passed to the caller. + + + + +

11.4 Debugging support

+ +

+When debugging a CLN application with GNU gdb, two facilities are +available from the library: + + + +

    +
  • The library does type checks, range checks, consistency checks at + +many places. When one of these fails, the function cl_abort() is +called. Its default implementation is to perform an exit(1), so +you won't have a core dump. But for debugging, it is best to set a +breakpoint at this function: + +
    +(gdb) break cl_abort
    +
    + +When this breakpoint is hit, look at the stack's backtrace: + +
    +(gdb) where
    +
    + +
  • The debugger's normal print command doesn't know about + +CLN's types and therefore prints mostly useless hexadecimal addresses. +CLN offers a function cl_print, callable from the debugger, +for printing number objects. In order to get this function, you have +to define the macro `CL_DEBUG' and then include all the header files +for which you want cl_print debugging support. For example: + +
    +#define CL_DEBUG
    +#include <cl_string.h>
    +
    + +Now, if you have in your program a variable cl_string s, and +inspect it under gdb, the output may look like this: + +
    +(gdb) print s
    +$7 = {<cl_gcpointer> = { = {pointer = 0x8055b60, heappointer = 0x8055b60,
    +  word = 134568800}}, }
    +(gdb) call cl_print(s)
    +(cl_string) ""
    +$8 = 134568800
    +
    + +Note that the output of cl_print goes to the program's error output, +not to gdb's standard output. + +Note, however, that the above facility does not work with all CLN types, +only with number objects and similar. Therefore CLN offers a member function +debug_print() on all CLN types. The same macro `CL_DEBUG' +is needed for this member function to be implemented. Under gdb, +you call it like this: + +
    +(gdb) print s
    +$7 = {<cl_gcpointer> = { = {pointer = 0x8055b60, heappointer = 0x8055b60,
    +  word = 134568800}}, }
    +(gdb) call s.debug_print()
    +(cl_string) ""
    +(gdb) define cprint
    +>call ($1).debug_print()
    +>end
    +(gdb) cprint s
    +(cl_string) ""
    +
    + +Unfortunately, this feature does not seem to work under all circumstances. +
+ +


+Go to the first, previous, next, last section, table of contents. + + diff --git a/doc/cln_12.html b/doc/cln_12.html new file mode 100644 index 0000000..0070b35 --- /dev/null +++ b/doc/cln_12.html @@ -0,0 +1,97 @@ + + + + +CLN, a Class Library for Numbers - 12. Customizing + + +Go to the first, previous, next, last section, table of contents. +


+ + +

12. Customizing

+ + + +

12.1 Error handling

+ +

+When a fatal error occurs, an error message is output to the standard error +output stream, and the function cl_abort is called. The default +version of this function (provided in the library) terminates the application. +To catch such a fatal error, you need to define the function cl_abort +yourself, with the prototype + +

+#include <cl_abort.h>
+void cl_abort (void);
+
+ +

+This function must not return control to its caller. + + + + +

12.2 Floating-point underflow

+ +

+Floating point underflow denotes the situation when a floating-point number +is to be created which is so close to 0 that its exponent is too +low to be represented internally. By default, this causes a fatal error. +If you set the global variable + +

+cl_boolean cl_inhibit_floating_point_underflow
+
+ +

+to cl_true, the error will be inhibited, and a floating-point zero +will be generated instead. +The default value of cl_inhibit_floating_point_underflow is +cl_false. + + + + +

12.3 Customizing I/O

+ +

+The output of the function fprint may be customized by changing the +value of the global variable cl_default_print_flags. + + + + +

12.4 Customizing the memory allocator

+ +

+Every memory allocation of CLN is done through the function pointer +cl_malloc_hook. Freeing of this memory is done through the function +pointer cl_free_hook. The default versions of these functions, +provided in the library, call malloc and free and check +the malloc result against NULL. +If you want to provide another memory allocator, you need to define +the variables cl_malloc_hook and cl_free_hook yourself, +like this: + +

+#include <cl_malloc.h>
+void* (*cl_malloc_hook) (size_t size) = ...;
+void (*cl_free_hook) (void* ptr)      = ...;
+
+ +

+The cl_malloc_hook function must not return a NULL pointer. + + +

+It is not possible to change the memory allocator at runtime, because +it is already called at program startup by the constructors of some +global variables. + + +


+Go to the first, previous, next, last section, table of contents. + + diff --git a/doc/cln_13.html b/doc/cln_13.html new file mode 100644 index 0000000..7186cd1 --- /dev/null +++ b/doc/cln_13.html @@ -0,0 +1,22 @@ + + + + +CLN, a Class Library for Numbers - Index + + +Go to the first, previous, next, last section, table of contents. +


+ + +

Index

+ +

+Jump to: +

+ + +


+Go to the first, previous, next, last section, table of contents. + + diff --git a/doc/cln_2.html b/doc/cln_2.html new file mode 100644 index 0000000..2a92f22 --- /dev/null +++ b/doc/cln_2.html @@ -0,0 +1,255 @@ + + + + +CLN, a Class Library for Numbers - 2. Installation + + +Go to the first, previous, next, last section, table of contents. +


+ + +

2. Installation

+ +

+This section describes how to install the CLN package on your system. + + + + +

2.1 Prerequisites

+ + + +

2.1.1 C++ compiler

+ +

+To build CLN, you need a C++ compiler. +Actually, you need GNU g++ 2.7.0 or newer. +On HPPA, you need GNU g++ 2.8.0 or newer. +I recommend GNU egcs 1.1 or newer. + + +

+The following C++ features are used: +classes, member functions, +overloading of functions and operators, +constructors and destructors, inline, const, +multiple inheritance, templates. + + +

+The following C++ features are not used: +new, delete, virtual inheritance, +exceptions. + + +

+CLN relies on semi-automatic ordering of initializations +of static and global variables, a feature which I could +implement for GNU g++ only. + + + + +

2.1.2 Make utility

+ +

+To build CLN, you also need to have GNU make installed. + + + + +

2.1.3 Sed utility

+ +

+To build CLN on HP-UX, you also need to have GNU sed installed. +This is because the libtool script, which creates the CLN library, relies +on sed, and the vendor's sed utility on these systems is too +limited. + + + + +

2.2 Building the library

+ +

+As with any autoconfiguring GNU software, installation is as easy as this: + + + +

+$ ./configure
+$ make
+$ make check
+
+ +

+If on your system, `make' is not GNU make, you have to use +`gmake' instead of `make' above. + + +

+The configure command checks out some features of your system and +C++ compiler and builds the Makefiles. The make command +builds the library. This step may take 4 hours on an average workstation. +The make check runs some test to check that no important subroutine +has been miscompiled. + + +

+The configure command accepts options. To get a summary of them, try + + + +

+$ ./configure --help
+
+ +

+Some of the options are explained in detail in the `INSTALL.generic' file. + + +

+You can specify the C compiler, the C++ compiler and their options through +the following environment variables when running configure: + + +

+ +
CC +
+Specifies the C compiler. + +
CFLAGS +
+Flags to be given to the C compiler when compiling programs (not when linking). + +
CXX +
+Specifies the C++ compiler. + +
CXXFLAGS +
+Flags to be given to the C++ compiler when compiling programs (not when linking). +
+ +

+Examples: + + + +

+$ CC="gcc" CFLAGS="-O" CXX="g++" CXXFLAGS="-O" ./configure
+$ CC="gcc -V 2.7.2" CFLAGS="-O -g" \
+  CXX="g++ -V 2.7.2" CXXFLAGS="-O -g" ./configure
+$ CC="gcc -V 2.8.1" CFLAGS="-O -fno-exceptions" \
+  CXX="g++ -V 2.8.1" CXXFLAGS="-O -fno-exceptions" ./configure
+$ CC="gcc -V egcs-2.91.60" CFLAGS="-O2 -fno-exceptions" \
+  CXX="g++ -V egcs-2.91.60" CFLAGS="-O2 -fno-exceptions" ./configure
+
+ +

+Note that for these environment variables to take effect, you have to set +them (assuming a Bourne-compatible shell) on the same line as the +configure command. If you made the settings in earlier shell +commands, you have to export the environment variables before +calling configure. In a csh shell, you have to use the +`setenv' command for setting each of the environment variables. + + +

+On Linux, g++ needs 15 MB to compile the tests. So you should better +have 17 MB swap space and 1 MB room in $TMPDIR. + + +

+If you use g++ version 2.7.x, don't add `-O2' to the CXXFLAGS, +because `g++ -O' generates better code for CLN than `g++ -O2'. + + +

+If you use g++ version 2.8.x or egcs-2.91.x (a.k.a. egcs-1.1) or +gcc-2.95.x, I recommend adding `-fno-exceptions' to the CXXFLAGS. +This will likely generate better code. + + +

+If you use g++ version egcs-2.91.x (egcs-1.1) or gcc-2.95.x on Sparc, +add either `-O' or `-O2 -fno-schedule-insns' to the CXXFLAGS. +With full `-O2', g++ miscompiles the division routines. Also, for +--enable-shared to work, you need egcs-1.1.2 or newer. + + +

+On MIPS (SGI Irix 6), pass option --without-gmp to configure. gmp does +not work when compiled in `n32' binary format on Irix. + + +

+By default, only a static library is built. You can build CLN as a shared +library too, by calling configure with the option `--enable-shared'. +To get it built as a shared library only, call configure with the options +`--enable-shared --disable-static'. + + +

+If you use g++ version egcs-2.91.x (egcs-1.1) on Sparc, you cannot +use `--enable-shared' because g++ would miscompile parts of the +library. + + + + +

2.3 Installing the library

+ +

+As with any autoconfiguring GNU software, installation is as easy as this: + + + +

+$ make install
+
+ +

+The `make install' command installs the library and the include files +into public places (`/usr/local/lib/' and `/usr/local/include/', +if you haven't specified a --prefix option to configure). +This step may require superuser privileges. + + +

+If you have already built the library and wish to install it, but didn't +specify --prefix=... at configure time, just re-run +configure, giving it the same options as the first time, plus +the --prefix=... option. + + + + +

2.4 Cleaning up

+ +

+You can remove system-dependent files generated by make through + + + +

+$ make clean
+
+ +

+You can remove all files generated by make, thus reverting to a +virgin distribution of CLN, through + + + +

+$ make distclean
+
+ +


+Go to the first, previous, next, last section, table of contents. + + diff --git a/doc/cln_3.html b/doc/cln_3.html new file mode 100644 index 0000000..9db9d05 --- /dev/null +++ b/doc/cln_3.html @@ -0,0 +1,364 @@ + + + + +CLN, a Class Library for Numbers - 3. Ordinary number types + + +Go to the first, previous, next, last section, table of contents. +


+ + +

3. Ordinary number types

+ +

+CLN implements the following class hierarchy: + + + +

+                        Number
+                       cl_number
+                     <cl_number.h>
+                          |
+                          |
+                 Real or complex number
+                        cl_N
+                     <cl_complex.h>
+                          |
+                          |
+                     Real number
+                        cl_R
+                      <cl_real.h>
+                          |
+      +-------------------+-------------------+
+      |                                       |
+Rational number                     Floating-point number
+    cl_RA                                   cl_F
+<cl_rational.h>                          <cl_float.h>
+      |                                       |
+      |                  +-------------+-------------+-------------+
+   Integer               |             |             |             |
+    cl_I            Short-Float   Single-Float  Double-Float   Long-Float
+ <cl_integer.h>        cl_SF         cl_FF         cl_DF         cl_LF
+                   <cl_sfloat.h> <cl_ffloat.h> <cl_dfloat.h> <cl_lfloat.h>
+
+ +

+The base class cl_number is an abstract base class. +It is not useful to declare a variable of this type except if you want +to completely disable compile-time type checking and use run-time type +checking instead. + + +

+The class cl_N comprises real and complex numbers. There is +no special class for complex numbers since complex numbers with imaginary +part 0 are automatically converted to real numbers. + + +

+The class cl_R comprises real numbers of different kinds. It is an +abstract class. + + +

+The class cl_RA comprises exact real numbers: rational numbers, including +integers. There is no special class for non-integral rational numbers +since rational numbers with denominator 1 are automatically converted +to integers. + + +

+The class cl_F implements floating-point approximations to real numbers. +It is an abstract class. + + + + +

3.1 Exact numbers

+ +

+Some numbers are represented as exact numbers: there is no loss of information +when such a number is converted from its mathematical value to its internal +representation. On exact numbers, the elementary operations (+, +-, *, /, comparisons, ...) compute the completely +correct result. + + +

+In CLN, the exact numbers are: + + + +

    +
  • + +rational numbers (including integers), +
  • + +complex numbers whose real and imaginary parts are both rational numbers. +
+ +

+Rational numbers are always normalized to the form +numerator/denominator where the numerator and denominator +are coprime integers and the denominator is positive. If the resulting +denominator is 1, the rational number is converted to an integer. + + +

+Small integers (typically in the range -2^30...2^30-1, +for 32-bit machines) are especially efficient, because they consume no heap +allocation. Otherwise the distinction between these immediate integers +(called "fixnums") and heap allocated integers (called "bignums") +is completely transparent. + + + + +

3.2 Floating-point numbers

+ +

+Not all real numbers can be represented exactly. (There is an easy mathematical +proof for this: Only a countable set of numbers can be stored exactly in +a computer, even if one assumes that it has unlimited storage. But there +are uncountably many real numbers.) So some approximation is needed. +CLN implements ordinary floating-point numbers, with mantissa and exponent. + + +

+The elementary operations (+, -, *, /, ...) +only return approximate results. For example, the value of the expression +(cl_F) 0.3 + (cl_F) 0.4 prints as `0.70000005', not as +`0.7'. Rounding errors like this one are inevitable when computing +with floating-point numbers. + + +

+Nevertheless, CLN rounds the floating-point results of the operations +, +-, *, /, sqrt according to the "round-to-even" +rule: It first computes the exact mathematical result and then returns the +floating-point number which is nearest to this. If two floating-point numbers +are equally distant from the ideal result, the one with a 0 in its least +significant mantissa bit is chosen. + + +

+Similarly, testing floating point numbers for equality `x == y' +is gambling with random errors. Better check for `abs(x - y) < epsilon' +for some well-chosen epsilon. + + +

+Floating point numbers come in four flavors: + + + +

    +
  • + +Short floats, type cl_SF. +They have 1 sign bit, 8 exponent bits (including the exponent's sign), +and 17 mantissa bits (including the "hidden" bit). +They don't consume heap allocation. + +
  • + +Single floats, type cl_FF. +They have 1 sign bit, 8 exponent bits (including the exponent's sign), +and 24 mantissa bits (including the "hidden" bit). +In CLN, they are represented as IEEE single-precision floating point numbers. +This corresponds closely to the C/C++ type `float'. + +
  • + +Double floats, type cl_DF. +They have 1 sign bit, 11 exponent bits (including the exponent's sign), +and 53 mantissa bits (including the "hidden" bit). +In CLN, they are represented as IEEE double-precision floating point numbers. +This corresponds closely to the C/C++ type `double'. + +
  • + +Long floats, type cl_LF. +They have 1 sign bit, 32 exponent bits (including the exponent's sign), +and n mantissa bits (including the "hidden" bit), where n >= 64. +The precision of a long float is unlimited, but once created, a long float +has a fixed precision. (No "lazy recomputation".) +
+ +

+Of course, computations with long floats are more expensive than those +with smaller floating-point formats. + + +

+CLN does not implement features like NaNs, denormalized numbers and +gradual underflow. If the exponent range of some floating-point type +is too limited for your application, choose another floating-point type +with larger exponent range. + + +

+As a user of CLN, you can forget about the differences between the +four floating-point types and just declare all your floating-point +variables as being of type cl_F. This has the advantage that +when you change the precision of some computation (say, from cl_DF +to cl_LF), you don't have to change the code, only the precision +of the initial values. Also, many transcendental functions have been +declared as returning a cl_F when the argument is a cl_F, +but such declarations are missing for the types cl_SF, cl_FF, +cl_DF, cl_LF. (Such declarations would be wrong if +the floating point contagion rule happened to change in the future.) + + + + +

3.3 Complex numbers

+ +

+Complex numbers, as implemented by the class cl_N, have a real +part and an imaginary part, both real numbers. A complex number whose +imaginary part is the exact number 0 is automatically converted +to a real number. + + +

+Complex numbers can arise from real numbers alone, for example +through application of sqrt or transcendental functions. + + + + +

3.4 Conversions

+ +

+Conversions from any class to any its superclasses ("base classes" in +C++ terminology) is done automatically. + + +

+Conversions from the C built-in types `long' and `unsigned long' +are provided for the classes cl_I, cl_RA, cl_R, +cl_N and cl_number. + + +

+Conversions from the C built-in types `int' and `unsigned int' +are provided for the classes cl_I, cl_RA, cl_R, +cl_N and cl_number. However, these conversions emphasize +efficiency. Their range is therefore limited: + + + +

    +
  • + +The conversion from `int' works only if the argument is < 2^29 and > -2^29. +
  • + +The conversion from `unsigned int' works only if the argument is < 2^29. +
+ +

+In a declaration like `cl_I x = 10;' the C++ compiler is able to +do the conversion of 10 from `int' to `cl_I' at compile time +already. On the other hand, code like `cl_I x = 1000000000;' is +in error. +So, if you want to be sure that an `int' whose magnitude is not guaranteed +to be < 2^29 is correctly converted to a `cl_I', first convert it to a +`long'. Similarly, if a large `unsigned int' is to be converted to a +`cl_I', first convert it to an `unsigned long'. + + +

+Conversions from the C built-in type `float' are provided for the classes +cl_FF, cl_F, cl_R, cl_N and cl_number. + + +

+Conversions from the C built-in type `double' are provided for the classes +cl_DF, cl_F, cl_R, cl_N and cl_number. + + +

+Conversions from `const char *' are provided for the classes +cl_I, cl_RA, +cl_SF, cl_FF, cl_DF, cl_LF, cl_F, +cl_R, cl_N. +The easiest way to specify a value which is outside of the range of the +C++ built-in types is therefore to specify it as a string, like this: + +

+   cl_I order_of_rubiks_cube_group = "43252003274489856000";
+
+ +

+Note that this conversion is done at runtime, not at compile-time. + + +

+Conversions from cl_I to the C built-in types `int', +`unsigned int', `long', `unsigned long' are provided through +the functions + + +

+ +
int cl_I_to_int (const cl_I& x) +
+
unsigned int cl_I_to_uint (const cl_I& x) +
+
long cl_I_to_long (const cl_I& x) +
+
unsigned long cl_I_to_ulong (const cl_I& x) +
+Returns x as element of the C type ctype. If x is not +representable in the range of ctype, a runtime error occurs. +
+ +

+Conversions from the classes cl_I, cl_RA, +cl_SF, cl_FF, cl_DF, cl_LF, cl_F and +cl_R +to the C built-in types `float' and `double' are provided through +the functions + + +

+ +
float cl_float_approx (const type& x) +
+
double cl_double_approx (const type& x) +
+Returns an approximation of x of C type ctype. +If abs(x) is too close to 0 (underflow), 0 is returned. +If abs(x) is too large (overflow), an IEEE infinity is returned. +
+ +

+Conversions from any class to any of its subclasses ("derived classes" in +C++ terminology) are not provided. Instead, you can assert and check +that a value belongs to a certain subclass, and return it as element of that +class, using the `As' and `The' macros. +As(type)(value) checks that value belongs to +type and returns it as such. +The(type)(value) assumes that value belongs to +type and returns it as such. It is your responsibility to ensure +that this assumption is valid. +Example: + + + +

+   cl_I x = ...;
+   if (!(x >= 0)) abort();
+   cl_I ten_x = The(cl_I)(expt(10,x)); // If x >= 0, 10^x is an integer.
+                // In general, it would be a rational number.
+
+ +


+Go to the first, previous, next, last section, table of contents. + + diff --git a/doc/cln_4.html b/doc/cln_4.html new file mode 100644 index 0000000..f9ac86e --- /dev/null +++ b/doc/cln_4.html @@ -0,0 +1,1804 @@ + + + + +CLN, a Class Library for Numbers - 4. Functions on numbers + + +Go to the first, previous, next, last section, table of contents. +


+ + +

4. Functions on numbers

+ +

+Each of the number classes declares its mathematical operations in the +corresponding include file. For example, if your code operates with +objects of type cl_I, it should #include <cl_integer.h>. + + + + +

4.1 Constructing numbers

+ +

+Here is how to create number objects "from nothing". + + + + +

4.1.1 Constructing integers

+ +

+cl_I objects are most easily constructed from C integers and from +strings. See section 3.4 Conversions. + + + + +

4.1.2 Constructing rational numbers

+ +

+cl_RA objects can be constructed from strings. The syntax +for rational numbers is described in section 5.1 Internal and printed representation. +Another standard way to produce a rational number is through application +of `operator /' or `recip' on integers. + + + + +

4.1.3 Constructing floating-point numbers

+ +

+cl_F objects with low precision are most easily constructed from +C `float' and `double'. See section 3.4 Conversions. + + +

+To construct a cl_F with high precision, you can use the conversion +from `const char *', but you have to specify the desired precision +within the string. (See section 5.1 Internal and printed representation.) +Example: + +

+   cl_F e = "0.271828182845904523536028747135266249775724709369996e+1_40";
+
+ +

+will set `e' to the given value, with a precision of 40 decimal digits. + + +

+The programmatic way to construct a cl_F with high precision is +through the cl_float conversion function, see +section 4.11.1 Conversion to floating-point numbers. For example, to compute +e to 40 decimal places, first construct 1.0 to 40 decimal places +and then apply the exponential function: + +

+   cl_float_format_t precision = cl_float_format(40);
+   cl_F e = exp(cl_float(1,precision));
+
+ + + +

4.1.4 Constructing complex numbers

+ +

+Non-real cl_N objects are normally constructed through the function + +

+   cl_N complex (const cl_R& realpart, const cl_R& imagpart)
+
+ +

+See section 4.4 Elementary complex functions. + + + + +

4.2 Elementary functions

+ +

+Each of the classes cl_N, cl_R, cl_RA, cl_I, +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines the following operations: + + +

+ +
type operator + (const type&, const type&) +
+Addition. + +
type operator - (const type&, const type&) +
+Subtraction. + +
type operator - (const type&) +
+Returns the negative of the argument. + +
type plus1 (const type& x) +
+Returns x + 1. + +
type minus1 (const type& x) +
+Returns x - 1. + +
type operator * (const type&, const type&) +
+Multiplication. + +
type square (const type& x) +
+Returns x * x. +
+ +

+Each of the classes cl_N, cl_R, cl_RA, +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines the following operations: + + +

+ +
type operator / (const type&, const type&) +
+Division. + +
type recip (const type&) +
+Returns the reciprocal of the argument. +
+ +

+The class cl_I doesn't define a `/' operation because +in the C/C++ language this operator, applied to integral types, +denotes the `floor' or `truncate' operation (which one of these, +is implementation dependent). (See section 4.6 Rounding functions) +Instead, cl_I defines an "exact quotient" function: + + +

+ +
cl_I exquo (const cl_I& x, const cl_I& y) +
+Checks that y divides x, and returns the quotient x/y. +
+ +

+The following exponentiation functions are defined: + + +

+ +
cl_I expt_pos (const cl_I& x, const cl_I& y) +
+
cl_RA expt_pos (const cl_RA& x, const cl_I& y) +
+y must be > 0. Returns x^y. + +
cl_RA expt (const cl_RA& x, const cl_I& y) +
+
cl_R expt (const cl_R& x, const cl_I& y) +
+
cl_N expt (const cl_N& x, const cl_I& y) +
+Returns x^y. +
+ +

+Each of the classes cl_R, cl_RA, cl_I, +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines the following operation: + + +

+ +
type abs (const type& x) +
+Returns the absolute value of x. +This is x if x >= 0, and -x if x <= 0. +
+ +

+The class cl_N implements this as follows: + + +

+ +
cl_R abs (const cl_N x) +
+Returns the absolute value of x. +
+ +

+Each of the classes cl_N, cl_R, cl_RA, cl_I, +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines the following operation: + + +

+ +
type signum (const type& x) +
+Returns the sign of x, in the same number format as x. +This is defined as x / abs(x) if x is non-zero, and +x if x is zero. If x is real, the value is either +0 or 1 or -1. +
+ + + +

4.3 Elementary rational functions

+ +

+Each of the classes cl_RA, cl_I defines the following operations: + + +

+ +
cl_I numerator (const type& x) +
+Returns the numerator of x. + +
cl_I denominator (const type& x) +
+Returns the denominator of x. +
+ +

+The numerator and denominator of a rational number are normalized in such +a way that they have no factor in common and the denominator is positive. + + + + +

4.4 Elementary complex functions

+ +

+The class cl_N defines the following operation: + + +

+ +
cl_N complex (const cl_R& a, const cl_R& b) +
+Returns the complex number a+bi, that is, the complex number with +real part a and imaginary part b. +
+ +

+Each of the classes cl_N, cl_R defines the following operations: + + +

+ +
cl_R realpart (const type& x) +
+Returns the real part of x. + +
cl_R imagpart (const type& x) +
+Returns the imaginary part of x. + +
type conjugate (const type& x) +
+Returns the complex conjugate of x. +
+ +

+We have the relations + + + +

    +
  • + +x = complex(realpart(x), imagpart(x)) +
  • + +conjugate(x) = complex(realpart(x), -imagpart(x)) +
+ + + +

4.5 Comparisons

+ +

+Each of the classes cl_N, cl_R, cl_RA, cl_I, +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines the following operations: + + +

+ +
bool operator == (const type&, const type&) +
+
bool operator != (const type&, const type&) +
+Comparison, as in C and C++. + +
uint32 cl_equal_hashcode (const type&) +
+Returns a 32-bit hash code that is the same for any two numbers which are +the same according to ==. This hash code depends on the number's value, +not its type or precision. + +
cl_boolean zerop (const type& x) +
+Compare against zero: x == 0 +
+ +

+Each of the classes cl_R, cl_RA, cl_I, +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines the following operations: + + +

+ +
cl_signean cl_compare (const type& x, const type& y) +
+Compares x and y. Returns +1 if x>y, +-1 if x<y, 0 if x=y. + +
bool operator <= (const type&, const type&) +
+
bool operator < (const type&, const type&) +
+
bool operator >= (const type&, const type&) +
+
bool operator > (const type&, const type&) +
+Comparison, as in C and C++. + +
cl_boolean minusp (const type& x) +
+Compare against zero: x < 0 + +
cl_boolean plusp (const type& x) +
+Compare against zero: x > 0 + +
type max (const type& x, const type& y) +
+Return the maximum of x and y. + +
type min (const type& x, const type& y) +
+Return the minimum of x and y. +
+ +

+When a floating point number and a rational number are compared, the float +is first converted to a rational number using the function rational. +Since a floating point number actually represents an interval of real numbers, +the result might be surprising. +For example, (cl_F)(cl_R)"1/3" == (cl_R)"1/3" returns false because +there is no floating point number whose value is exactly 1/3. + + + + +

4.6 Rounding functions

+ +

+When a real number is to be converted to an integer, there is no "best" +rounding. The desired rounding function depends on the application. +The Common Lisp and ISO Lisp standards offer four rounding functions: + + +

+ +
floor(x) +
+This is the largest integer <=x. + +
ceiling(x) +
+This is the smallest integer >=x. + +
truncate(x) +
+Among the integers between 0 and x (inclusive) the one nearest to x. + +
round(x) +
+The integer nearest to x. If x is exactly halfway between two +integers, choose the even one. +
+ +

+These functions have different advantages: + + +

+floor and ceiling are translation invariant: +floor(x+n) = floor(x) + n and ceiling(x+n) = ceiling(x) + n +for every x and every integer n. + + +

+On the other hand, truncate and round are symmetric: +truncate(-x) = -truncate(x) and round(-x) = -round(x), +and furthermore round is unbiased: on the "average", it rounds +down exactly as often as it rounds up. + + +

+The functions are related like this: + + + +

    +
  • + +ceiling(m/n) = floor((m+n-1)/n) = floor((m-1)/n)+1 +for rational numbers m/n (m, n integers, n>0), and +
  • + +truncate(x) = sign(x) * floor(abs(x)) +
+ +

+Each of the classes cl_R, cl_RA, +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines the following operations: + + +

+ +
cl_I floor1 (const type& x) +
+Returns floor(x). +
cl_I ceiling1 (const type& x) +
+Returns ceiling(x). +
cl_I truncate1 (const type& x) +
+Returns truncate(x). +
cl_I round1 (const type& x) +
+Returns round(x). +
+ +

+Each of the classes cl_R, cl_RA, cl_I, +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines the following operations: + + +

+ +
cl_I floor1 (const type& x, const type& y) +
+Returns floor(x/y). +
cl_I ceiling1 (const type& x, const type& y) +
+Returns ceiling(x/y). +
cl_I truncate1 (const type& x, const type& y) +
+Returns truncate(x/y). +
cl_I round1 (const type& x, const type& y) +
+Returns round(x/y). +
+ +

+These functions are called `floor1', ... here instead of +`floor', ..., because on some systems, system dependent include +files define `floor' and `ceiling' as macros. + + +

+In many cases, one needs both the quotient and the remainder of a division. +It is more efficient to compute both at the same time than to perform +two divisions, one for quotient and the next one for the remainder. +The following functions therefore return a structure containing both +the quotient and the remainder. The suffix `2' indicates the number +of "return values". The remainder is defined as follows: + + + +

    +
  • + +for the computation of quotient = floor(x), +remainder = x - quotient, +
  • + +for the computation of quotient = floor(x,y), +remainder = x - quotient*y, +
+ +

+and similarly for the other three operations. + + +

+Each of the classes cl_R, cl_RA, +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines the following operations: + + +

+ +
struct type_div_t { cl_I quotient; type remainder; }; +
+
type_div_t floor2 (const type& x) +
+
type_div_t ceiling2 (const type& x) +
+
type_div_t truncate2 (const type& x) +
+
type_div_t round2 (const type& x) +
+
+ +

+Each of the classes cl_R, cl_RA, cl_I, +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines the following operations: + + +

+ +
struct type_div_t { cl_I quotient; type remainder; }; +
+
type_div_t floor2 (const type& x, const type& y) +
+
type_div_t ceiling2 (const type& x, const type& y) +
+
type_div_t truncate2 (const type& x, const type& y) +
+
type_div_t round2 (const type& x, const type& y) +
+
+ +

+Sometimes, one wants the quotient as a floating-point number (of the +same format as the argument, if the argument is a float) instead of as +an integer. The prefix `f' indicates this. + + +

+Each of the classes +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines the following operations: + + +

+ +
type ffloor (const type& x) +
+
type fceiling (const type& x) +
+
type ftruncate (const type& x) +
+
type fround (const type& x) +
+
+ +

+and similarly for class cl_R, but with return type cl_F. + + +

+The class cl_R defines the following operations: + + +

+ +
cl_F ffloor (const type& x, const type& y) +
+
cl_F fceiling (const type& x, const type& y) +
+
cl_F ftruncate (const type& x, const type& y) +
+
cl_F fround (const type& x, const type& y) +
+
+ +

+These functions also exist in versions which return both the quotient +and the remainder. The suffix `2' indicates this. + + +

+Each of the classes +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines the following operations: + + +

+ +
struct type_fdiv_t { type quotient; type remainder; }; +
+
type_fdiv_t ffloor2 (const type& x) +
+
type_fdiv_t fceiling2 (const type& x) +
+
type_fdiv_t ftruncate2 (const type& x) +
+
type_fdiv_t fround2 (const type& x) +
+
+

+and similarly for class cl_R, but with quotient type cl_F. + + +

+The class cl_R defines the following operations: + + +

+ +
struct type_fdiv_t { cl_F quotient; cl_R remainder; }; +
+
type_fdiv_t ffloor2 (const type& x, const type& y) +
+
type_fdiv_t fceiling2 (const type& x, const type& y) +
+
type_fdiv_t ftruncate2 (const type& x, const type& y) +
+
type_fdiv_t fround2 (const type& x, const type& y) +
+
+ +

+Other applications need only the remainder of a division. +The remainder of `floor' and `ffloor' is called `mod' +(abbreviation of "modulo"). The remainder `truncate' and +`ftruncate' is called `rem' (abbreviation of "remainder"). + + + +

    +
  • + +mod(x,y) = floor2(x,y).remainder = x - floor(x/y)*y +
  • + +rem(x,y) = truncate2(x,y).remainder = x - truncate(x/y)*y +
+ +

+If x and y are both >= 0, mod(x,y) = rem(x,y) >= 0. +In general, mod(x,y) has the sign of y or is zero, +and rem(x,y) has the sign of x or is zero. + + +

+The classes cl_R, cl_I define the following operations: + + +

+ +
type mod (const type& x, const type& y) +
+
type rem (const type& x, const type& y) +
+
+ + + +

4.7 Roots

+ +

+Each of the classes cl_R, +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines the following operation: + + +

+ +
type sqrt (const type& x) +
+x must be >= 0. This function returns the square root of x, +normalized to be >= 0. If x is the square of a rational number, +sqrt(x) will be a rational number, else it will return a +floating-point approximation. +
+ +

+The classes cl_RA, cl_I define the following operation: + + +

+ +
cl_boolean sqrtp (const type& x, type* root) +
+This tests whether x is a perfect square. If so, it returns true +and the exact square root in *root, else it returns false. +
+ +

+Furthermore, for integers, similarly: + + +

+ +
cl_boolean isqrt (const type& x, type* root) +
+x should be >= 0. This function sets *root to +floor(sqrt(x)) and returns the same value as sqrtp: +the boolean value (expt(*root,2) == x). +
+ +

+For nth roots, the classes cl_RA, cl_I +define the following operation: + + +

+ +
cl_boolean rootp (const type& x, const cl_I& n, type* root) +
+x must be >= 0. n must be > 0. +This tests whether x is an nth power of a rational number. +If so, it returns true and the exact root in *root, else it returns +false. +
+ +

+The only square root function which accepts negative numbers is the one +for class cl_N: + + +

+ +
cl_N sqrt (const cl_N& z) +
+Returns the square root of z, as defined by the formula +sqrt(z) = exp(log(z)/2). Conversion to a floating-point type +or to a complex number are done if necessary. The range of the result is the +right half plane realpart(sqrt(z)) >= 0 +including the positive imaginary axis and 0, but excluding +the negative imaginary axis. +The result is an exact number only if z is an exact number. +
+ + + +

4.8 Transcendental functions

+ +

+The transcendental functions return an exact result if the argument +is exact and the result is exact as well. Otherwise they must return +inexact numbers even if the argument is exact. +For example, cos(0) = 1 returns the rational number 1. + + + + +

4.8.1 Exponential and logarithmic functions

+ +
+ +
cl_R exp (const cl_R& x) +
+
cl_N exp (const cl_N& x) +
+Returns the exponential function of x. This is e^x where +e is the base of the natural logarithms. The range of the result +is the entire complex plane excluding 0. + +
cl_R ln (const cl_R& x) +
+x must be > 0. Returns the (natural) logarithm of x. + +
cl_N log (const cl_N& x) +
+Returns the (natural) logarithm of x. If x is real and positive, +this is ln(x). In general, log(x) = log(abs(x)) + i*phase(x). +The range of the result is the strip in the complex plane +-pi < imagpart(log(x)) <= pi. + +
cl_R phase (const cl_N& x) +
+Returns the angle part of x in its polar representation as a +complex number. That is, phase(x) = atan(realpart(x),imagpart(x)). +This is also the imaginary part of log(x). +The range of the result is the interval -pi < phase(x) <= pi. +The result will be an exact number only if zerop(x) or +if x is real and positive. + +
cl_R log (const cl_R& a, const cl_R& b) +
+a and b must be > 0. Returns the logarithm of a with +respect to base b. log(a,b) = ln(a)/ln(b). +The result can be exact only if a = 1 or if a and b +are both rational. + +
cl_N log (const cl_N& a, const cl_N& b) +
+Returns the logarithm of a with respect to base b. +log(a,b) = log(a)/log(b). + +
cl_N expt (const cl_N& x, const cl_N& y) +
+Exponentiation: Returns x^y = exp(y*log(x)). +
+ +

+The constant e = exp(1) = 2.71828... is returned by the following functions: + + +

+ +
cl_F cl_exp1 (cl_float_format_t f) +
+Returns e as a float of format f. + +
cl_F cl_exp1 (const cl_F& y) +
+Returns e in the float format of y. + +
cl_F cl_exp1 (void) +
+Returns e as a float of format cl_default_float_format. +
+ + + +

4.8.2 Trigonometric functions

+ +
+ +
cl_R sin (const cl_R& x) +
+Returns sin(x). The range of the result is the interval +-1 <= sin(x) <= 1. + +
cl_N sin (const cl_N& z) +
+Returns sin(z). The range of the result is the entire complex plane. + +
cl_R cos (const cl_R& x) +
+Returns cos(x). The range of the result is the interval +-1 <= cos(x) <= 1. + +
cl_N cos (const cl_N& x) +
+Returns cos(z). The range of the result is the entire complex plane. + +
struct cl_cos_sin_t { cl_R cos; cl_R sin; }; +
+
cl_cos_sin_t cl_cos_sin (const cl_R& x) +
+Returns both sin(x) and cos(x). This is more efficient than +computing them separately. The relation cos^2 + sin^2 = 1 will +hold only approximately. + +
cl_R tan (const cl_R& x) +
+
cl_N tan (const cl_N& x) +
+Returns tan(x) = sin(x)/cos(x). + +
cl_N cis (const cl_R& x) +
+
cl_N cis (const cl_N& x) +
+Returns exp(i*x). The name `cis' means "cos + i sin", because +e^(i*x) = cos(x) + i*sin(x). + +
cl_N asin (const cl_N& z) +
+Returns arcsin(z). This is defined as +arcsin(z) = log(iz+sqrt(1-z^2))/i and satisfies +arcsin(-z) = -arcsin(z). +The range of the result is the strip in the complex domain +-pi/2 <= realpart(arcsin(z)) <= pi/2, excluding the numbers +with realpart = -pi/2 and imagpart < 0 and the numbers +with realpart = pi/2 and imagpart > 0. + +
cl_N acos (const cl_N& z) +
+Returns arccos(z). This is defined as +arccos(z) = pi/2 - arcsin(z) = log(z+i*sqrt(1-z^2))/i +and satisfies arccos(-z) = pi - arccos(z). +The range of the result is the strip in the complex domain +0 <= realpart(arcsin(z)) <= pi, excluding the numbers +with realpart = 0 and imagpart < 0 and the numbers +with realpart = pi and imagpart > 0. + +
cl_R atan (const cl_R& x, const cl_R& y) +
+Returns the angle of the polar representation of the complex number +x+iy. This is atan(y/x) if x>0. The range of +the result is the interval -pi < atan(x,y) <= pi. The result will +be an exact number only if x > 0 and y is the exact 0. +WARNING: In Common Lisp, this function is called as (atan y x), +with reversed order of arguments. + +
cl_R atan (const cl_R& x) +
+Returns arctan(x). This is the same as atan(1,x). The range +of the result is the interval -pi/2 < atan(x) < pi/2. The result +will be an exact number only if x is the exact 0. + +
cl_N atan (const cl_N& z) +
+Returns arctan(z). This is defined as +arctan(z) = (log(1+iz)-log(1-iz)) / 2i and satisfies +arctan(-z) = -arctan(z). The range of the result is +the strip in the complex domain +-pi/2 <= realpart(arctan(z)) <= pi/2, excluding the numbers +with realpart = -pi/2 and imagpart >= 0 and the numbers +with realpart = pi/2 and imagpart <= 0. + +
+ +

+The constant pi = 3.14... is returned by the following functions: + + +

+ +
cl_F cl_pi (cl_float_format_t f) +
+Returns pi as a float of format f. + +
cl_F cl_pi (const cl_F& y) +
+Returns pi in the float format of y. + +
cl_F cl_pi (void) +
+Returns pi as a float of format cl_default_float_format. +
+ + + +

4.8.3 Hyperbolic functions

+ +
+ +
cl_R sinh (const cl_R& x) +
+Returns sinh(x). + +
cl_N sinh (const cl_N& z) +
+Returns sinh(z). The range of the result is the entire complex plane. + +
cl_R cosh (const cl_R& x) +
+Returns cosh(x). The range of the result is the interval +cosh(x) >= 1. + +
cl_N cosh (const cl_N& z) +
+Returns cosh(z). The range of the result is the entire complex plane. + +
struct cl_cosh_sinh_t { cl_R cosh; cl_R sinh; }; +
+
cl_cosh_sinh_t cl_cosh_sinh (const cl_R& x) +
+Returns both sinh(x) and cosh(x). This is more efficient than +computing them separately. The relation cosh^2 - sinh^2 = 1 will +hold only approximately. + +
cl_R tanh (const cl_R& x) +
+
cl_N tanh (const cl_N& x) +
+Returns tanh(x) = sinh(x)/cosh(x). + +
cl_N asinh (const cl_N& z) +
+Returns arsinh(z). This is defined as +arsinh(z) = log(z+sqrt(1+z^2)) and satisfies +arsinh(-z) = -arsinh(z). +The range of the result is the strip in the complex domain +-pi/2 <= imagpart(arsinh(z)) <= pi/2, excluding the numbers +with imagpart = -pi/2 and realpart > 0 and the numbers +with imagpart = pi/2 and realpart < 0. + +
cl_N acosh (const cl_N& z) +
+Returns arcosh(z). This is defined as +arcosh(z) = 2*log(sqrt((z+1)/2)+sqrt((z-1)/2)). +The range of the result is the half-strip in the complex domain +-pi < imagpart(arcosh(z)) <= pi, realpart(arcosh(z)) >= 0, +excluding the numbers with realpart = 0 and -pi < imagpart < 0. + +
cl_N atanh (const cl_N& z) +
+Returns artanh(z). This is defined as +artanh(z) = (log(1+z)-log(1-z)) / 2 and satisfies +artanh(-z) = -artanh(z). The range of the result is +the strip in the complex domain +-pi/2 <= imagpart(artanh(z)) <= pi/2, excluding the numbers +with imagpart = -pi/2 and realpart <= 0 and the numbers +with imagpart = pi/2 and realpart >= 0. +
+ + + +

4.8.4 Euler gamma

+ +

+Euler's constant C = 0.577... is returned by the following functions: + + +

+ +
cl_F cl_eulerconst (cl_float_format_t f) +
+Returns Euler's constant as a float of format f. + +
cl_F cl_eulerconst (const cl_F& y) +
+Returns Euler's constant in the float format of y. + +
cl_F cl_eulerconst (void) +
+Returns Euler's constant as a float of format cl_default_float_format. +
+ +

+Catalan's constant G = 0.915... is returned by the following functions: + + +

+ +
cl_F cl_catalanconst (cl_float_format_t f) +
+Returns Catalan's constant as a float of format f. + +
cl_F cl_catalanconst (const cl_F& y) +
+Returns Catalan's constant in the float format of y. + +
cl_F cl_catalanconst (void) +
+Returns Catalan's constant as a float of format cl_default_float_format. +
+ + + +

4.8.5 Riemann zeta

+ +

+Riemann's zeta function at an integral point s>1 is returned by the +following functions: + + +

+ +
cl_F cl_zeta (int s, cl_float_format_t f) +
+Returns Riemann's zeta function at s as a float of format f. + +
cl_F cl_zeta (int s, const cl_F& y) +
+Returns Riemann's zeta function at s in the float format of y. + +
cl_F cl_zeta (int s) +
+Returns Riemann's zeta function at s as a float of format +cl_default_float_format. +
+ + + +

4.9 Functions on integers

+ + + +

4.9.1 Logical functions

+ +

+Integers, when viewed as in two's complement notation, can be thought as +infinite bit strings where the bits' values eventually are constant. +For example, + +

+    17 = ......00010001
+    -6 = ......11111010
+
+ +

+The logical operations view integers as such bit strings and operate +on each of the bit positions in parallel. + + +

+ +
cl_I lognot (const cl_I& x) +
+
cl_I operator ~ (const cl_I& x) +
+Logical not, like ~x in C. This is the same as -1-x. + +
cl_I logand (const cl_I& x, const cl_I& y) +
+
cl_I operator & (const cl_I& x, const cl_I& y) +
+Logical and, like x & y in C. + +
cl_I logior (const cl_I& x, const cl_I& y) +
+
cl_I operator | (const cl_I& x, const cl_I& y) +
+Logical (inclusive) or, like x | y in C. + +
cl_I logxor (const cl_I& x, const cl_I& y) +
+
cl_I operator ^ (const cl_I& x, const cl_I& y) +
+Exclusive or, like x ^ y in C. + +
cl_I logeqv (const cl_I& x, const cl_I& y) +
+Bitwise equivalence, like ~(x ^ y) in C. + +
cl_I lognand (const cl_I& x, const cl_I& y) +
+Bitwise not and, like ~(x & y) in C. + +
cl_I lognor (const cl_I& x, const cl_I& y) +
+Bitwise not or, like ~(x | y) in C. + +
cl_I logandc1 (const cl_I& x, const cl_I& y) +
+Logical and, complementing the first argument, like ~x & y in C. + +
cl_I logandc2 (const cl_I& x, const cl_I& y) +
+Logical and, complementing the second argument, like x & ~y in C. + +
cl_I logorc1 (const cl_I& x, const cl_I& y) +
+Logical or, complementing the first argument, like ~x | y in C. + +
cl_I logorc2 (const cl_I& x, const cl_I& y) +
+Logical or, complementing the second argument, like x | ~y in C. +
+ +

+These operations are all available though the function +

+ +
cl_I boole (cl_boole op, const cl_I& x, const cl_I& y) +
+
+

+where op must have one of the 16 values (each one stands for a function +which combines two bits into one bit): boole_clr, boole_set, +boole_1, boole_2, boole_c1, boole_c2, +boole_and, boole_ior, boole_xor, boole_eqv, +boole_nand, boole_nor, boole_andc1, boole_andc2, +boole_orc1, boole_orc2. + + +

+Other functions that view integers as bit strings: + + +

+ +
cl_boolean logtest (const cl_I& x, const cl_I& y) +
+Returns true if some bit is set in both x and y, i.e. if +logand(x,y) != 0. + +
cl_boolean logbitp (const cl_I& n, const cl_I& x) +
+Returns true if the nth bit (from the right) of x is set. +Bit 0 is the least significant bit. + +
uintL logcount (const cl_I& x) +
+Returns the number of one bits in x, if x >= 0, or +the number of zero bits in x, if x < 0. +
+ +

+The following functions operate on intervals of bits in integers. +The type + +

+struct cl_byte { uintL size; uintL position; };
+
+ +

+represents the bit interval containing the bits +position...position+size-1 of an integer. +The constructor cl_byte(size,position) constructs a cl_byte. + + +

+ +
cl_I ldb (const cl_I& n, const cl_byte& b) +
+extracts the bits of n described by the bit interval b +and returns them as a nonnegative integer with b.size bits. + +
cl_boolean ldb_test (const cl_I& n, const cl_byte& b) +
+Returns true if some bit described by the bit interval b is set in +n. + +
cl_I dpb (const cl_I& newbyte, const cl_I& n, const cl_byte& b) +
+Returns n, with the bits described by the bit interval b +replaced by newbyte. Only the lowest b.size bits of +newbyte are relevant. +
+ +

+The functions ldb and dpb implicitly shift. The following +functions are their counterparts without shifting: + + +

+ +
cl_I mask_field (const cl_I& n, const cl_byte& b) +
+returns an integer with the bits described by the bit interval b +copied from the corresponding bits in n, the other bits zero. + +
cl_I deposit_field (const cl_I& newbyte, const cl_I& n, const cl_byte& b) +
+returns an integer where the bits described by the bit interval b +come from newbyte and the other bits come from n. +
+ +

+The following relations hold: + + + +

    +
  • + +ldb (n, b) = mask_field(n, b) >> b.position, +
  • + +dpb (newbyte, n, b) = deposit_field (newbyte << b.position, n, b), +
  • + +deposit_field(newbyte,n,b) = n ^ mask_field(n,b) ^ mask_field(new_byte,b). +
+ +

+The following operations on integers as bit strings are efficient shortcuts +for common arithmetic operations: + + +

+ +
cl_boolean oddp (const cl_I& x) +
+Returns true if the least significant bit of x is 1. Equivalent to +mod(x,2) != 0. + +
cl_boolean evenp (const cl_I& x) +
+Returns true if the least significant bit of x is 0. Equivalent to +mod(x,2) == 0. + +
cl_I operator << (const cl_I& x, const cl_I& n) +
+Shifts x by n bits to the left. n should be >=0. +Equivalent to x * expt(2,n). + +
cl_I operator >> (const cl_I& x, const cl_I& n) +
+Shifts x by n bits to the right. n should be >=0. +Bits shifted out to the right are thrown away. +Equivalent to floor(x / expt(2,n)). + +
cl_I ash (const cl_I& x, const cl_I& y) +
+Shifts x by y bits to the left (if y>=0) or +by -y bits to the right (if y<=0). In other words, this +returns floor(x * expt(2,y)). + +
uintL integer_length (const cl_I& x) +
+Returns the number of bits (excluding the sign bit) needed to represent x +in two's complement notation. This is the smallest n >= 0 such that +-2^n <= x < 2^n. If x > 0, this is the unique n > 0 such that +2^(n-1) <= x < 2^n. + +
uintL ord2 (const cl_I& x) +
+x must be non-zero. This function returns the number of 0 bits at the +right of x in two's complement notation. This is the largest n >= 0 +such that 2^n divides x. + +
uintL power2p (const cl_I& x) +
+x must be > 0. This function checks whether x is a power of 2. +If x = 2^(n-1), it returns n. Else it returns 0. +(See also the function logp.) +
+ + + +

4.9.2 Number theoretic functions

+ +
+ +
uint32 gcd (uint32 a, uint32 b) +
+
cl_I gcd (const cl_I& a, const cl_I& b) +
+This function returns the greatest common divisor of a and b, +normalized to be >= 0. + +
cl_I xgcd (const cl_I& a, const cl_I& b, cl_I* u, cl_I* v) +
+This function ("extended gcd") returns the greatest common divisor g of +a and b and at the same time the representation of g +as an integral linear combination of a and b: +u and v with u*a+v*b = g, g >= 0. +u and v will be normalized to be of smallest possible absolute +value, in the following sense: If a and b are non-zero, and +abs(a) != abs(b), u and v will satisfy the inequalities +abs(u) <= abs(b)/(2*g), abs(v) <= abs(a)/(2*g). + +
cl_I lcm (const cl_I& a, const cl_I& b) +
+This function returns the least common multiple of a and b, +normalized to be >= 0. + +
cl_boolean logp (const cl_I& a, const cl_I& b, cl_RA* l) +
+
cl_boolean logp (const cl_RA& a, const cl_RA& b, cl_RA* l) +
+a must be > 0. b must be >0 and != 1. If log(a,b) is +rational number, this function returns true and sets *l = log(a,b), else +it returns false. +
+ + + +

4.9.3 Combinatorial functions

+ +
+ +
cl_I factorial (uintL n) +
+n must be a small integer >= 0. This function returns the factorial +n! = 1*2*...*n. + +
cl_I doublefactorial (uintL n) +
+n must be a small integer >= 0. This function returns the +doublefactorial n!! = 1*3*...*n or +n!! = 2*4*...*n, respectively. + +
cl_I binomial (uintL n, uintL k) +
+n and k must be small integers >= 0. This function returns the +binomial coefficient +(n choose k) = n! / k! (n-k)! +for 0 <= k <= n, 0 else. +
+ + + +

4.10 Functions on floating-point numbers

+ +

+Recall that a floating-point number consists of a sign s, an +exponent e and a mantissa m. The value of the number is +(-1)^s * 2^e * m. + + +

+Each of the classes +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines the following operations. + + +

+ +
type scale_float (const type& x, sintL delta) +
+
type scale_float (const type& x, const cl_I& delta) +
+Returns x*2^delta. This is more efficient than an explicit multiplication +because it copies x and modifies the exponent. +
+ +

+The following functions provide an abstract interface to the underlying +representation of floating-point numbers. + + +

+ +
sintL float_exponent (const type& x) +
+Returns the exponent e of x. +For x = 0.0, this is 0. For x non-zero, this is the unique +integer with 2^(e-1) <= abs(x) < 2^e. + +
sintL float_radix (const type& x) +
+Returns the base of the floating-point representation. This is always 2. + +
type float_sign (const type& x) +
+Returns the sign s of x as a float. The value is 1 for +x >= 0, -1 for x < 0. + +
uintL float_digits (const type& x) +
+Returns the number of mantissa bits in the floating-point representation +of x, including the hidden bit. The value only depends on the type +of x, not on its value. + +
uintL float_precision (const type& x) +
+Returns the number of significant mantissa bits in the floating-point +representation of x. Since denormalized numbers are not supported, +this is the same as float_digits(x) if x is non-zero, and +0 if x = 0. +
+ +

+The complete internal representation of a float is encoded in the type +cl_decoded_float (or cl_decoded_sfloat, cl_decoded_ffloat, +cl_decoded_dfloat, cl_decoded_lfloat, respectively), defined by + +

+struct cl_decoded_typefloat {
+        type mantissa; cl_I exponent; type sign;
+};
+
+ +

+and returned by the function + + +

+ +
cl_decoded_typefloat decode_float (const type& x) +
+For x non-zero, this returns (-1)^s, e, m with +x = (-1)^s * 2^e * m and 0.5 <= m < 1.0. For x = 0, +it returns (-1)^s=1, e=0, m=0. +e is the same as returned by the function float_exponent. +
+ +

+A complete decoding in terms of integers is provided as type + +

+struct cl_idecoded_float {
+        cl_I mantissa; cl_I exponent; cl_I sign;
+};
+
+ +

+by the following function: + + +

+ +
cl_idecoded_float integer_decode_float (const type& x) +
+For x non-zero, this returns (-1)^s, e, m with +x = (-1)^s * 2^e * m and m an integer with float_digits(x) +bits. For x = 0, it returns (-1)^s=1, e=0, m=0. +WARNING: The exponent e is not the same as the one returned by +the functions decode_float and float_exponent. +
+ +

+Some other function, implemented only for class cl_F: + + +

+ +
cl_F float_sign (const cl_F& x, const cl_F& y) +
+This returns a floating point number whose precision and absolute value +is that of y and whose sign is that of x. If x is +zero, it is treated as positive. Same for y. +
+ + + +

4.11 Conversion functions

+ + + +

4.11.1 Conversion to floating-point numbers

+ +

+The type cl_float_format_t describes a floating-point format. + + +

+ +
cl_float_format_t cl_float_format (uintL n) +
+Returns the smallest float format which guarantees at least n +decimal digits in the mantissa (after the decimal point). + +
cl_float_format_t cl_float_format (const cl_F& x) +
+Returns the floating point format of x. + +
cl_float_format_t cl_default_float_format +
+Global variable: the default float format used when converting rational numbers +to floats. +
+ +

+To convert a real number to a float, each of the types +cl_R, cl_F, cl_I, cl_RA, +int, unsigned int, float, double +defines the following operations: + + +

+ +
cl_F cl_float (const type&x, cl_float_format_t f) +
+Returns x as a float of format f. +
cl_F cl_float (const type&x, const cl_F& y) +
+Returns x in the float format of y. +
cl_F cl_float (const type&x) +
+Returns x as a float of format cl_default_float_format if +it is an exact number, or x itself if it is already a float. +
+ +

+Of course, converting a number to a float can lose precision. + + +

+Every floating-point format has some characteristic numbers: + + +

+ +
cl_F most_positive_float (cl_float_format_t f) +
+Returns the largest (most positive) floating point number in float format f. + +
cl_F most_negative_float (cl_float_format_t f) +
+Returns the smallest (most negative) floating point number in float format f. + +
cl_F least_positive_float (cl_float_format_t f) +
+Returns the least positive floating point number (i.e. > 0 but closest to 0) +in float format f. + +
cl_F least_negative_float (cl_float_format_t f) +
+Returns the least negative floating point number (i.e. < 0 but closest to 0) +in float format f. + +
cl_F float_epsilon (cl_float_format_t f) +
+Returns the smallest floating point number e > 0 such that 1+e != 1. + +
cl_F float_negative_epsilon (cl_float_format_t f) +
+Returns the smallest floating point number e > 0 such that 1-e != 1. +
+ + + +

4.11.2 Conversion to rational numbers

+ +

+Each of the classes cl_R, cl_RA, cl_F +defines the following operation: + + +

+ +
cl_RA rational (const type& x) +
+Returns the value of x as an exact number. If x is already +an exact number, this is x. If x is a floating-point number, +the value is a rational number whose denominator is a power of 2. +
+ +

+In order to convert back, say, (cl_F)(cl_R)"1/3" to 1/3, there is +the function + + +

+ +
cl_RA rationalize (const cl_R& x) +
+If x is a floating-point number, it actually represents an interval +of real numbers, and this function returns the rational number with +smallest denominator (and smallest numerator, in magnitude) +which lies in this interval. +If x is already an exact number, this function returns x. +
+ +

+If x is any float, one has + + + +

    +
  • + +cl_float(rational(x),x) = x +
  • + +cl_float(rationalize(x),x) = x +
+ + + +

4.12 Random number generators

+ +

+A random generator is a machine which produces (pseudo-)random numbers. +The include file <cl_random.h> defines a class cl_random_state +which contains the state of a random generator. If you make a copy +of the random number generator, the original one and the copy will produce +the same sequence of random numbers. + + +

+The following functions return (pseudo-)random numbers in different formats. +Calling one of these modifies the state of the random number generator in +a complicated but deterministic way. + + +

+The global variable + +

+cl_random_state cl_default_random_state
+
+ +

+contains a default random number generator. It is used when the functions +below are called without cl_random_state argument. + + +

+ +
uint32 random32 (cl_random_state& randomstate) +
+
uint32 random32 () +
+Returns a random unsigned 32-bit number. All bits are equally random. + +
cl_I random_I (cl_random_state& randomstate, const cl_I& n) +
+
cl_I random_I (const cl_I& n) +
+n must be an integer > 0. This function returns a random integer x +in the range 0 <= x < n. + +
cl_F random_F (cl_random_state& randomstate, const cl_F& n) +
+
cl_F random_F (const cl_F& n) +
+n must be a float > 0. This function returns a random floating-point +number of the same format as n in the range 0 <= x < n. + +
cl_R random_R (cl_random_state& randomstate, const cl_R& n) +
+
cl_R random_R (const cl_R& n) +
+Behaves like random_I if n is an integer and like random_F +if n is a float. +
+ + + +

4.13 Obfuscating operators

+ +

+The modifying C/C++ operators +=, -=, *=, /=, +&=, |=, ^=, <<=, >>= +are not available by default because their +use tends to make programs unreadable. It is trivial to get away without +them. However, if you feel that you absolutely need these operators +to get happy, then add + +

+#define WANT_OBFUSCATING_OPERATORS
+
+ +

+to the beginning of your source files, before the inclusion of any CLN +include files. This flag will enable the following operators: + + +

+For the classes cl_N, cl_R, cl_RA, +cl_F, cl_SF, cl_FF, cl_DF, cl_LF: + + +

+ +
type& operator += (type&, const type&) +
+
type& operator -= (type&, const type&) +
+
type& operator *= (type&, const type&) +
+
type& operator /= (type&, const type&) +
+
+ +

+For the class cl_I: + + +

+ +
type& operator += (type&, const type&) +
+
type& operator -= (type&, const type&) +
+
type& operator *= (type&, const type&) +
+
type& operator &= (type&, const type&) +
+
type& operator |= (type&, const type&) +
+
type& operator ^= (type&, const type&) +
+
type& operator <<= (type&, const type&) +
+
type& operator >>= (type&, const type&) +
+
+ +

+For the classes cl_N, cl_R, cl_RA, cl_I, +cl_F, cl_SF, cl_FF, cl_DF, cl_LF: + + +

+ +
type& operator ++ (type& x) +
+The prefix operator ++x. + +
void operator ++ (type& x, int) +
+The postfix operator x++. + +
type& operator -- (type& x) +
+The prefix operator --x. + +
void operator -- (type& x, int) +
+The postfix operator x--. +
+ +

+Note that by using these obfuscating operators, you wouldn't gain efficiency: +In CLN `x += y;' is exactly the same as `x = x+y;', not more +efficient. + + +


+Go to the first, previous, next, last section, table of contents. + + diff --git a/doc/cln_5.html b/doc/cln_5.html new file mode 100644 index 0000000..4df2aed --- /dev/null +++ b/doc/cln_5.html @@ -0,0 +1,418 @@ + + + + +CLN, a Class Library for Numbers - 5. Input/Output + + +Go to the first, previous, next, last section, table of contents. +


+ + +

5. Input/Output

+ + + +

5.1 Internal and printed representation

+ +

+All computations deal with the internal representations of the numbers. + + +

+Every number has an external representation as a sequence of ASCII characters. +Several external representations may denote the same number, for example, +"20.0" and "20.000". + + +

+Converting an internal to an external representation is called "printing", +converting an external to an internal representation is called "reading". +In CLN, is it always true that conversion of an internal to an external +representation and then back to an internal representation will yield the +same internal representation. Symbolically: read(print(x)) == x. +This is called "print-read consistency". + + +

+Different types of numbers have different external representations (case +is insignificant): + + +

+ +
Integers +
+External representation: sign{digit}+. The reader also accepts the +Common Lisp syntaxes sign{digit}+. with a trailing dot +for decimal integers +and the #nR, #b, #o, #x prefixes. + +
Rational numbers +
+External representation: sign{digit}+/{digit}+. +The #nR, #b, #o, #x prefixes are allowed +here as well. + +
Floating-point numbers +
+External representation: sign{digit}*exponent or +sign{digit}*.{digit}*exponent or +sign{digit}*.{digit}+. A precision specifier +of the form _prec may be appended. There must be at least +one digit in the non-exponent part. The exponent has the syntax +expmarker expsign {digit}+. +The exponent marker is + + +
    +
  • + +`s' for short-floats, +
  • + +`f' for single-floats, +
  • + +`d' for double-floats, +
  • + +`L' for long-floats, +
+ +or `e', which denotes a default float format. The precision specifying +suffix has the syntax _prec where prec denotes the number of +valid mantissa digits (in decimal, excluding leading zeroes), cf. also +function `cl_float_format'. + +
Complex numbers +
+External representation: + +
    +
  • + +In algebraic notation: realpart+imagparti. Of course, +if imagpart is negative, its printed representation begins with +a `-', and the `+' between realpart and imagpart +may be omitted. Note that this notation cannot be used when the imagpart +is rational and the rational number's base is >18, because the `i' +is then read as a digit. +
  • + +In Common Lisp notation: #C(realpart imagpart). +
+ +
+ + + +

5.2 Input functions

+ +

+Including <cl_io.h> defines a type cl_istream, which is +the type of the first argument to all input functions. Unless you build +and use CLN with the macro CL_IO_STDIO being defined, cl_istream +is the same as istream&. + + +

+The variable + +

    +
  • + +cl_istream cl_stdin +
+ +

+contains the standard input stream. + + +

+These are the simple input functions: + + +

+ +
int freadchar (cl_istream stream) +
+Reads a character from stream. Returns cl_EOF (not a `char'!) +if the end of stream was encountered or an error occurred. + +
int funreadchar (cl_istream stream, int c) +
+Puts back c onto stream. c must be the result of the +last freadchar operation on stream. +
+ +

+Each of the classes cl_N, cl_R, cl_RA, cl_I, +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines, in <cl_type_io.h>, the following input function: + + +

+ +
cl_istream operator>> (cl_istream stream, type& result) +
+Reads a number from stream and stores it in the result. +
+ +

+The most flexible input functions, defined in <cl_type_io.h>, +are the following: + + +

+ +
cl_N read_complex (cl_istream stream, const cl_read_flags& flags) +
+
cl_R read_real (cl_istream stream, const cl_read_flags& flags) +
+
cl_F read_float (cl_istream stream, const cl_read_flags& flags) +
+
cl_RA read_rational (cl_istream stream, const cl_read_flags& flags) +
+
cl_I read_integer (cl_istream stream, const cl_read_flags& flags) +
+Reads a number from stream. The flags are parameters which +affect the input syntax. Whitespace before the number is silently skipped. + +
cl_N read_complex (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse) +
+
cl_R read_real (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse) +
+
cl_F read_float (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse) +
+
cl_RA read_rational (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse) +
+
cl_I read_integer (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse) +
+Reads a number from a string in memory. The flags are parameters which +affect the input syntax. The string starts at string and ends at +string_limit (exclusive limit). string_limit may also be +NULL, denoting the entire string, i.e. equivalent to +string_limit = string + strlen(string). If end_of_parse is +NULL, the string in memory must contain exactly one number and nothing +more, else a fatal error will be signalled. If end_of_parse +is not NULL, *end_of_parse will be assigned a pointer past +the last parsed character (i.e. string_limit if nothing came after +the number). Whitespace is not allowed. +
+ +

+The structure cl_read_flags contains the following fields: + + +

+ +
cl_read_syntax_t syntax +
+The possible results of the read operation. Possible values are +syntax_number, syntax_real, syntax_rational, +syntax_integer, syntax_float, syntax_sfloat, +syntax_ffloat, syntax_dfloat, syntax_lfloat. + +
cl_read_lsyntax_t lsyntax +
+Specifies the language-dependent syntax variant for the read operation. +Possible values are + +
+ +
lsyntax_standard +
+accept standard algebraic notation only, no complex numbers, +
lsyntax_algebraic +
+accept the algebraic notation x+yi for complex numbers, +
lsyntax_commonlisp +
+accept the #b, #o, #x syntaxes for binary, octal, +hexadecimal numbers, +#baseR for rational numbers in a given base, +#c(realpart imagpart) for complex numbers, +
lsyntax_all +
+accept all of these extensions. +
+ +
unsigned int rational_base +
+The base in which rational numbers are read. + +
cl_float_format_t float_flags.default_float_format +
+The float format used when reading floats with exponent marker `e'. + +
cl_float_format_t float_flags.default_lfloat_format +
+The float format used when reading floats with exponent marker `l'. + +
cl_boolean float_flags.mantissa_dependent_float_format +
+When this flag is true, floats specified with more digits than corresponding +to the exponent marker they contain, but without _nnn suffix, will get a +precision corresponding to their number of significant digits. +
+ + + +

5.3 Output functions

+ +

+Including <cl_io.h> defines a type cl_ostream, which is +the type of the first argument to all output functions. Unless you build +and use CLN with the macro CL_IO_STDIO being defined, cl_ostream +is the same as ostream&. + + +

+The variable + +

    +
  • + +cl_ostream cl_stdout +
+ +

+contains the standard output stream. + + +

+The variable + +

    +
  • + +cl_ostream cl_stderr +
+ +

+contains the standard error output stream. + + +

+These are the simple output functions: + + +

+ +
void fprintchar (cl_ostream stream, char c) +
+Prints the character x literally on the stream. + +
void fprint (cl_ostream stream, const char * string) +
+Prints the string literally on the stream. + +
void fprintdecimal (cl_ostream stream, int x) +
+
void fprintdecimal (cl_ostream stream, const cl_I& x) +
+Prints the integer x in decimal on the stream. + +
void fprintbinary (cl_ostream stream, const cl_I& x) +
+Prints the integer x in binary (base 2, without prefix) +on the stream. + +
void fprintoctal (cl_ostream stream, const cl_I& x) +
+Prints the integer x in octal (base 8, without prefix) +on the stream. + +
void fprinthexadecimal (cl_ostream stream, const cl_I& x) +
+Prints the integer x in hexadecimal (base 16, without prefix) +on the stream. +
+ +

+Each of the classes cl_N, cl_R, cl_RA, cl_I, +cl_F, cl_SF, cl_FF, cl_DF, cl_LF +defines, in <cl_type_io.h>, the following output functions: + + +

+ +
void fprint (cl_ostream stream, const type& x) +
+
cl_ostream operator<< (cl_ostream stream, const type& x) +
+Prints the number x on the stream. The output may depend +on the global printer settings in the variable cl_default_print_flags. +The ostream flags and settings (flags, width and locale) are +ignored. +
+ +

+The most flexible output function, defined in <cl_type_io.h>, +are the following: + +

+void print_complex  (cl_ostream stream, const cl_print_flags& flags,
+                     const cl_N& z);
+void print_real     (cl_ostream stream, const cl_print_flags& flags,
+                     const cl_R& z);
+void print_float    (cl_ostream stream, const cl_print_flags& flags,
+                     const cl_F& z);
+void print_rational (cl_ostream stream, const cl_print_flags& flags,
+                     const cl_RA& z);
+void print_integer  (cl_ostream stream, const cl_print_flags& flags,
+                     const cl_I& z);
+
+ +

+Prints the number x on the stream. The flags are +parameters which affect the output. + + +

+The structure type cl_print_flags contains the following fields: + + +

+ +
unsigned int rational_base +
+The base in which rational numbers are printed. Default is 10. + +
cl_boolean rational_readably +
+If this flag is true, rational numbers are printed with radix specifiers in +Common Lisp syntax (#nR or #b or #o or #x +prefixes, trailing dot). Default is false. + +
cl_boolean float_readably +
+If this flag is true, type specific exponent markers have precedence over 'E'. +Default is false. + +
cl_float_format_t default_float_format +
+Floating point numbers of this format will be printed using the 'E' exponent +marker. Default is cl_float_format_ffloat. + +
cl_boolean complex_readably +
+If this flag is true, complex numbers will be printed using the Common Lisp +syntax #C(realpart imagpart). Default is false. + +
cl_string univpoly_varname +
+Univariate polynomials with no explicit indeterminate name will be printed +using this variable name. Default is "x". +
+ +

+The global variable cl_default_print_flags contains the default values, +used by the function fprint, + + +


+Go to the first, previous, next, last section, table of contents. + + diff --git a/doc/cln_6.html b/doc/cln_6.html new file mode 100644 index 0000000..4d9413f --- /dev/null +++ b/doc/cln_6.html @@ -0,0 +1,112 @@ + + + + +CLN, a Class Library for Numbers - 6. Rings + + +Go to the first, previous, next, last section, table of contents. +


+ + +

6. Rings

+ +

+CLN has a class of abstract rings. + + + +

+                         Ring
+                       cl_ring
+                      <cl_ring.h>
+
+ +

+Rings can be compared for equality: + + +

+ +
bool operator== (const cl_ring&, const cl_ring&) +
+
bool operator!= (const cl_ring&, const cl_ring&) +
+These compare two rings for equality. +
+ +

+Given a ring R, the following members can be used. + + +

+ +
void R->fprint (cl_ostream stream, const cl_ring_element& x) +
+
cl_boolean R->equal (const cl_ring_element& x, const cl_ring_element& y) +
+
cl_ring_element R->zero () +
+
cl_boolean R->zerop (const cl_ring_element& x) +
+
cl_ring_element R->plus (const cl_ring_element& x, const cl_ring_element& y) +
+
cl_ring_element R->minus (const cl_ring_element& x, const cl_ring_element& y) +
+
cl_ring_element R->uminus (const cl_ring_element& x) +
+
cl_ring_element R->one () +
+
cl_ring_element R->canonhom (const cl_I& x) +
+
cl_ring_element R->mul (const cl_ring_element& x, const cl_ring_element& y) +
+
cl_ring_element R->square (const cl_ring_element& x) +
+
cl_ring_element R->expt_pos (const cl_ring_element& x, const cl_I& y) +
+
+ +

+The following rings are built-in. + + +

+ +
cl_null_ring cl_0_ring +
+The null ring, containing only zero. + +
cl_complex_ring cl_C_ring +
+The ring of complex numbers. This corresponds to the type cl_N. + +
cl_real_ring cl_R_ring +
+The ring of real numbers. This corresponds to the type cl_R. + +
cl_rational_ring cl_RA_ring +
+The ring of rational numbers. This corresponds to the type cl_RA. + +
cl_integer_ring cl_I_ring +
+The ring of integers. This corresponds to the type cl_I. +
+ +

+Type tests can be performed for any of cl_C_ring, cl_R_ring, +cl_RA_ring, cl_I_ring: + + +

+ +
cl_boolean instanceof (const cl_number& x, const cl_number_ring& R) +
+Tests whether the given number is an element of the number ring R. +
+ +


+Go to the first, previous, next, last section, table of contents. + + diff --git a/doc/cln_7.html b/doc/cln_7.html new file mode 100644 index 0000000..e065b2b --- /dev/null +++ b/doc/cln_7.html @@ -0,0 +1,215 @@ + + + + +CLN, a Class Library for Numbers - 7. Modular integers + + +Go to the first, previous, next, last section, table of contents. +


+ + +

7. Modular integers

+ + + +

7.1 Modular integer rings

+ +

+CLN implements modular integers, i.e. integers modulo a fixed integer N. +The modulus is explicitly part of every modular integer. CLN doesn't +allow you to (accidentally) mix elements of different modular rings, +e.g. (3 mod 4) + (2 mod 5) will result in a runtime error. +(Ideally one would imagine a generic data type cl_MI(N), but C++ +doesn't have generic types. So one has to live with runtime checks.) + + +

+The class of modular integer rings is + + + +

+                         Ring
+                       cl_ring
+                      <cl_ring.h>
+                          |
+                          |
+                 Modular integer ring
+                    cl_modint_ring
+                   <cl_modinteger.h>
+
+ +

+and the class of all modular integers (elements of modular integer rings) is + + + +

+                    Modular integer
+                         cl_MI
+                   <cl_modinteger.h>
+
+ +

+Modular integer rings are constructed using the function + + +

+ +
cl_modint_ring cl_find_modint_ring (const cl_I& N) +
+This function returns the modular ring `Z/NZ'. It takes care +of finding out about special cases of N, like powers of two +and odd numbers for which Montgomery multiplication will be a win, +and precomputes any necessary auxiliary data for computing modulo N. +There is a cache table of rings, indexed by N (or, more precisely, +by abs(N)). This ensures that the precomputation costs are reduced +to a minimum. +
+ +

+Modular integer rings can be compared for equality: + + +

+ +
bool operator== (const cl_modint_ring&, const cl_modint_ring&) +
+
bool operator!= (const cl_modint_ring&, const cl_modint_ring&) +
+These compare two modular integer rings for equality. Two different calls +to cl_find_modint_ring with the same argument necessarily return the +same ring because it is memoized in the cache table. +
+ + + +

7.2 Functions on modular integers

+ +

+Given a modular integer ring R, the following members can be used. + + +

+ +
cl_I R->modulus +
+This is the ring's modulus, normalized to be nonnegative: abs(N). + +
cl_MI R->zero() +
+This returns 0 mod N. + +
cl_MI R->one() +
+This returns 1 mod N. + +
cl_MI R->canonhom (const cl_I& x) +
+This returns x mod N. + +
cl_I R->retract (const cl_MI& x) +
+This is a partial inverse function to R->canonhom. It returns the +standard representative (>=0, <N) of x. + +
cl_MI R->random(cl_random_state& randomstate) +
+
cl_MI R->random() +
+This returns a random integer modulo N. +
+ +

+The following operations are defined on modular integers. + + +

+ +
cl_modint_ring x.ring () +
+Returns the ring to which the modular integer x belongs. + +
cl_MI operator+ (const cl_MI&, const cl_MI&) +
+Returns the sum of two modular integers. One of the arguments may also be +a plain integer. + +
cl_MI operator- (const cl_MI&, const cl_MI&) +
+Returns the difference of two modular integers. One of the arguments may also be +a plain integer. + +
cl_MI operator- (const cl_MI&) +
+Returns the negative of a modular integer. + +
cl_MI operator* (const cl_MI&, const cl_MI&) +
+Returns the product of two modular integers. One of the arguments may also be +a plain integer. + +
cl_MI square (const cl_MI&) +
+Returns the square of a modular integer. + +
cl_MI recip (const cl_MI& x) +
+Returns the reciprocal x^-1 of a modular integer x. x +must be coprime to the modulus, otherwise an error message is issued. + +
cl_MI div (const cl_MI& x, const cl_MI& y) +
+Returns the quotient x*y^-1 of two modular integers x, y. +y must be coprime to the modulus, otherwise an error message is issued. + +
cl_MI expt_pos (const cl_MI& x, const cl_I& y) +
+y must be > 0. Returns x^y. + +
cl_MI expt (const cl_MI& x, const cl_I& y) +
+Returns x^y. If y is negative, x must be coprime to the +modulus, else an error message is issued. + +
cl_MI operator<< (const cl_MI& x, const cl_I& y) +
+Returns x*2^y. + +
cl_MI operator>> (const cl_MI& x, const cl_I& y) +
+Returns x*2^-y. When y is positive, the modulus must be odd, +or an error message is issued. + +
bool operator== (const cl_MI&, const cl_MI&) +
+
bool operator!= (const cl_MI&, const cl_MI&) +
+Compares two modular integers, belonging to the same modular integer ring, +for equality. + +
cl_boolean zerop (const cl_MI& x) +
+Returns true if x is 0 mod N. +
+ +

+The following output functions are defined (see also the chapter on +input/output). + + +

+ +
void fprint (cl_ostream stream, const cl_MI& x) +
+
cl_ostream operator<< (cl_ostream stream, const cl_MI& x) +
+Prints the modular integer x on the stream. The output may depend +on the global printer settings in the variable cl_default_print_flags. +
+ +


+Go to the first, previous, next, last section, table of contents. + + diff --git a/doc/cln_8.html b/doc/cln_8.html new file mode 100644 index 0000000..a0381f6 --- /dev/null +++ b/doc/cln_8.html @@ -0,0 +1,123 @@ + + + + +CLN, a Class Library for Numbers - 8. Symbolic data types + + +Go to the first, previous, next, last section, table of contents. +


+ + +

8. Symbolic data types

+ +

+CLN implements two symbolic (non-numeric) data types: strings and symbols. + + + + +

8.1 Strings

+ +

+The class + + + +

+                      String
+                     cl_string
+                    <cl_string.h>
+
+ +

+implements immutable strings. + + +

+Strings are constructed through the following constructors: + + +

+ +
cl_string (const char * s) +
+Returns an immutable copy of the (zero-terminated) C string s. + +
cl_string (const char * ptr, unsigned long len) +
+Returns an immutable copy of the len characters at +ptr[0], ..., ptr[len-1]. NUL characters are allowed. +
+ +

+The following functions are available on strings: + + +

+ +
operator = +
+Assignment from cl_string and const char *. + +
s.length() +
+
strlen(s) +
+Returns the length of the string s. + +
s[i] +
+Returns the ith character of the string s. +i must be in the range 0 <= i < s.length(). + +
bool equal (const cl_string& s1, const cl_string& s2) +
+Compares two strings for equality. One of the arguments may also be a +plain const char *. +
+ + + +

8.2 Symbols

+ +

+Symbols are uniquified strings: all symbols with the same name are shared. +This means that comparison of two symbols is fast (effectively just a pointer +comparison), whereas comparison of two strings must in the worst case walk +both strings until their end. +Symbols are used, for example, as tags for properties, as names of variables +in polynomial rings, etc. + + +

+Symbols are constructed through the following constructor: + + +

+ +
cl_symbol (const cl_string& s) +
+Looks up or creates a new symbol with a given name. +
+ +

+The following operations are available on symbols: + + +

+ +
cl_string (const cl_symbol& sym) +
+Conversion to cl_string: Returns the string which names the symbol +sym. + +
bool equal (const cl_symbol& sym1, const cl_symbol& sym2) +
+Compares two symbols for equality. This is very fast. +
+ +


+Go to the first, previous, next, last section, table of contents. + + diff --git a/doc/cln_9.html b/doc/cln_9.html new file mode 100644 index 0000000..be510a2 --- /dev/null +++ b/doc/cln_9.html @@ -0,0 +1,323 @@ + + + + +CLN, a Class Library for Numbers - 9. Univariate polynomials + + +Go to the first, previous, next, last section, table of contents. +


+ + +

9. Univariate polynomials

+ + + +

9.1 Univariate polynomial rings

+ +

+CLN implements univariate polynomials (polynomials in one variable) over an +arbitrary ring. The indeterminate variable may be either unnamed (and will be +printed according to cl_default_print_flags.univpoly_varname, which +defaults to `x') or carry a given name. The base ring and the +indeterminate are explicitly part of every polynomial. CLN doesn't allow you to +(accidentally) mix elements of different polynomial rings, e.g. +(a^2+1) * (b^3-1) will result in a runtime error. (Ideally this should +return a multivariate polynomial, but they are not yet implemented in CLN.) + + +

+The classes of univariate polynomial rings are + + + +

+                           Ring
+                         cl_ring
+                        <cl_ring.h>
+                            |
+                            |
+                 Univariate polynomial ring
+                      cl_univpoly_ring
+                      <cl_univpoly.h>
+                            |
+           +----------------+-------------------+
+           |                |                   |
+ Complex polynomial ring    |    Modular integer polynomial ring
+ cl_univpoly_complex_ring   |        cl_univpoly_modint_ring
+  <cl_univpoly_complex.h>   |        <cl_univpoly_modint.h>
+                            |
+           +----------------+
+           |                |
+   Real polynomial ring     |
+   cl_univpoly_real_ring    |
+    <cl_univpoly_real.h>    |
+                            |
+           +----------------+
+           |                |
+ Rational polynomial ring   |
+ cl_univpoly_rational_ring  |
+  <cl_univpoly_rational.h>  |
+                            |
+           +----------------+
+           |
+ Integer polynomial ring
+ cl_univpoly_integer_ring
+  <cl_univpoly_integer.h>
+
+ +

+and the corresponding classes of univariate polynomials are + + + +

+                   Univariate polynomial
+                          cl_UP
+                      <cl_univpoly.h>
+                            |
+           +----------------+-------------------+
+           |                |                   |
+   Complex polynomial       |      Modular integer polynomial
+        cl_UP_N             |                cl_UP_MI
+  <cl_univpoly_complex.h>   |        <cl_univpoly_modint.h>
+                            |
+           +----------------+
+           |                |
+     Real polynomial        |
+        cl_UP_R             |
+    <cl_univpoly_real.h>    |
+                            |
+           +----------------+
+           |                |
+   Rational polynomial      |
+        cl_UP_RA            |
+  <cl_univpoly_rational.h>  |
+                            |
+           +----------------+
+           |
+   Integer polynomial
+        cl_UP_I
+  <cl_univpoly_integer.h>
+
+ +

+Univariate polynomial rings are constructed using the functions + + +

+ +
cl_univpoly_ring cl_find_univpoly_ring (const cl_ring& R) +
+
cl_univpoly_ring cl_find_univpoly_ring (const cl_ring& R, const cl_symbol& varname) +
+This function returns the polynomial ring `R[X]', unnamed or named. +R may be an arbitrary ring. This function takes care of finding out +about special cases of R, such as the rings of complex numbers, +real numbers, rational numbers, integers, or modular integer rings. +There is a cache table of rings, indexed by R and varname. +This ensures that two calls of this function with the same arguments will +return the same polynomial ring. + +
cl_univpoly_complex_ring cl_find_univpoly_ring (const cl_complex_ring& R) +
+
cl_univpoly_complex_ring cl_find_univpoly_ring (const cl_complex_ring& R, const cl_symbol& varname) +
+
cl_univpoly_real_ring cl_find_univpoly_ring (const cl_real_ring& R) +
+
cl_univpoly_real_ring cl_find_univpoly_ring (const cl_real_ring& R, const cl_symbol& varname) +
+
cl_univpoly_rational_ring cl_find_univpoly_ring (const cl_rational_ring& R) +
+
cl_univpoly_rational_ring cl_find_univpoly_ring (const cl_rational_ring& R, const cl_symbol& varname) +
+
cl_univpoly_integer_ring cl_find_univpoly_ring (const cl_integer_ring& R) +
+
cl_univpoly_integer_ring cl_find_univpoly_ring (const cl_integer_ring& R, const cl_symbol& varname) +
+
cl_univpoly_modint_ring cl_find_univpoly_ring (const cl_modint_ring& R) +
+
cl_univpoly_modint_ring cl_find_univpoly_ring (const cl_modint_ring& R, const cl_symbol& varname) +
+These functions are equivalent to the general cl_find_univpoly_ring, +only the return type is more specific, according to the base ring's type. +
+ + + +

9.2 Functions on univariate polynomials

+ +

+Given a univariate polynomial ring R, the following members can be used. + + +

+ +
cl_ring R->basering() +
+This returns the base ring, as passed to `cl_find_univpoly_ring'. + +
cl_UP R->zero() +
+This returns 0 in R, a polynomial of degree -1. + +
cl_UP R->one() +
+This returns 1 in R, a polynomial of degree <= 0. + +
cl_UP R->canonhom (const cl_I& x) +
+This returns x in R, a polynomial of degree <= 0. + +
cl_UP R->monomial (const cl_ring_element& x, uintL e) +
+This returns a sparse polynomial: x * X^e, where X is the +indeterminate. + +
cl_UP R->create (sintL degree) +
+Creates a new polynomial with a given degree. The zero polynomial has degree +-1. After creating the polynomial, you should put in the coefficients, +using the set_coeff member function, and then call the finalize +member function. +
+ +

+The following are the only destructive operations on univariate polynomials. + + +

+ +
void set_coeff (cl_UP& x, uintL index, const cl_ring_element& y) +
+This changes the coefficient of X^index in x to be y. +After changing a polynomial and before applying any "normal" operation on it, +you should call its finalize member function. + +
void finalize (cl_UP& x) +
+This function marks the endpoint of destructive modifications of a polynomial. +It normalizes the internal representation so that subsequent computations have +less overhead. Doing normal computations on unnormalized polynomials may +produce wrong results or crash the program. +
+ +

+The following operations are defined on univariate polynomials. + + +

+ +
cl_univpoly_ring x.ring () +
+Returns the ring to which the univariate polynomial x belongs. + +
cl_UP operator+ (const cl_UP&, const cl_UP&) +
+Returns the sum of two univariate polynomials. + +
cl_UP operator- (const cl_UP&, const cl_UP&) +
+Returns the difference of two univariate polynomials. + +
cl_UP operator- (const cl_UP&) +
+Returns the negative of a univariate polynomial. + +
cl_UP operator* (const cl_UP&, const cl_UP&) +
+Returns the product of two univariate polynomials. One of the arguments may +also be a plain integer or an element of the base ring. + +
cl_UP square (const cl_UP&) +
+Returns the square of a univariate polynomial. + +
cl_UP expt_pos (const cl_UP& x, const cl_I& y) +
+y must be > 0. Returns x^y. + +
bool operator== (const cl_UP&, const cl_UP&) +
+
bool operator!= (const cl_UP&, const cl_UP&) +
+Compares two univariate polynomials, belonging to the same univariate +polynomial ring, for equality. + +
cl_boolean zerop (const cl_UP& x) +
+Returns true if x is 0 in R. + +
sintL degree (const cl_UP& x) +
+Returns the degree of the polynomial. The zero polynomial has degree -1. + +
cl_ring_element coeff (const cl_UP& x, uintL index) +
+Returns the coefficient of X^index in the polynomial x. + +
cl_ring_element x (const cl_ring_element& y) +
+Evaluation: If x is a polynomial and y belongs to the base ring, +then `x(y)' returns the value of the substitution of y into +x. + +
cl_UP deriv (const cl_UP& x) +
+Returns the derivative of the polynomial x with respect to the +indeterminate X. +
+ +

+The following output functions are defined (see also the chapter on +input/output). + + +

+ +
void fprint (cl_ostream stream, const cl_UP& x) +
+
cl_ostream operator<< (cl_ostream stream, const cl_UP& x) +
+Prints the univariate polynomial x on the stream. The output may +depend on the global printer settings in the variable +cl_default_print_flags. +
+ + + +

9.3 Special polynomials

+ +

+The following functions return special polynomials. + + +

+ +
cl_UP_I cl_tschebychev (sintL n) +
+Returns the n-th Tchebychev polynomial (n >= 0). + +
cl_UP_I cl_hermite (sintL n) +
+Returns the n-th Hermite polynomial (n >= 0). + +
cl_UP_RA cl_legendre (sintL n) +
+Returns the n-th Legendre polynomial (n >= 0). + +
cl_UP_I cl_laguerre (sintL n) +
+Returns the n-th Laguerre polynomial (n >= 0). +
+ +

+Information how to derive the differential equation satisfied by each +of these polynomials from their definition can be found in the +doc/polynomial/ directory. + + +


+Go to the first, previous, next, last section, table of contents. + + diff --git a/doc/cln_toc.html b/doc/cln_toc.html new file mode 100644 index 0000000..ecf7ce9 --- /dev/null +++ b/doc/cln_toc.html @@ -0,0 +1,121 @@ + + + + +CLN, a Class Library for Numbers - Table of Contents + + +

CLN, a Class Library for Numbers

+
by Bruno Haible
+

+


+

+


+This document was generated on 14 January 2000 using +texi2html 1.56k. + + diff --git a/doc/polynomial/Makefile.devel b/doc/polynomial/Makefile.devel new file mode 100644 index 0000000..f719d1b --- /dev/null +++ b/doc/polynomial/Makefile.devel @@ -0,0 +1,25 @@ +# This is the developer's makefile, not the user's makefile. +# Don't use it unless you know exactly what you do! + + +# Some important programs: +SHELL = /bin/sh +MAKE = make +RM = rm -f + +LATEX = latex +DVIPS = dvips -D600 + + +all : diag_rational.ps tchebychev.ps hermite.ps legendre.ps laguerre.ps + +# %.tex : %.lyx + +%.dvi : %.tex + $(LATEX) $< + $(RM) $(patsubst %.tex,%.aux,$<) + $(RM) $(patsubst %.tex,%.log,$<) + +%.ps : %.dvi + $(DVIPS) -o $@ $< + diff --git a/doc/polynomial/README b/doc/polynomial/README new file mode 100644 index 0000000..5343391 --- /dev/null +++ b/doc/polynomial/README @@ -0,0 +1,5 @@ +This directory contains some notes about the method used to compute various +orthogonal polynomials, in particular how to retrieve a recurrence relation +or closed formula for the coefficients directly from the definition of the +polynomials. + diff --git a/doc/polynomial/diag_rational.dvi b/doc/polynomial/diag_rational.dvi new file mode 100644 index 0000000000000000000000000000000000000000..6df1dc208c074e90b365464d75212e9c1b9aa918 GIT binary patch literal 13132 zcmdU033ycHxjvJbBtTdKNM$RlVgg~zOawzh5Q+-OVpvoZQ$5U_NhZt^W(f&Wx2soF zX2{9G>CxB@RI3PR>+O1kGY(d8Z=VORt%X*tvZ(cTFE^!QoL-VeC;fFSP)`6KW`U=odsU@>jC_X#pH>C&^_#_U$59H48}(EUF7nwZ*w@G zSkoj0Lz2HH9*;jb?q(q-S0+E`9=dk#%96~|LYF_}aB9n>NW%K=?(Pvk`$OXcnK!YI z-|KMd%jLou+qCuft&U5Is6>LHus0Z(=?O`aqOa;0bD1{NA5`5@pH!iU0k@*N6V@wM z%~P~WyIffP2KJ68$I|hEm+EwnZ2Qhit&RvU2_%yr_I%bYeDZj7gfIw%(>D&4+8mX8 z*T&Jfw>lMwB`xDOb`RGUh`WU%dKBL_Ff{vsBQD#f zKb)$qsi~=@W!{Ur&nkT>^~=mMw#Dox-4KmD_2d82MJ#&pMPti6kJCzd@;TS*ZL#F1 zCHKa%E91%HKOT*Bmu|V?>f#KAL`C&}M?4NLk9^oYYVwqd`G{H< zSmN@yBY&lhKZ)$*8+$LJ^O6JP!Lbw_JY;Qq+DU?dDlGGlYwOn0auAFoWLw&%*T!hC z8U_F2^6=;H=kMZK+4lNwt)U^FoEooVrn0^RT1;5S9TAm~7=a!|pW=xIT=Z*&Y`vt? zYnSY@t@}@rCMg7U<6EznZ6A$JJG*iS_=@vuWsq|k5!^Obs%fXnt>&wk$hS%Sk)dQs zu=!2iNK+SVR$r-=RrV18dseF~CrhkT94hQm)mJ78_Uuku6w?TqMC)bCuEQF$RQO9k z1>dSC>hq~?uh>Z9QG*^;_r#NvH$ETh6n=iw4UMw(7k9&ilkfL@9+QjD{&Dx$QcIsL z$tWMT6>hIS=!hqW2v*p+ZNh((opXymatpKQRA7HyB{Vzgn(-OitBt{2<8tw+Yik2> zdGvSR%o-avGBT)matdt$0chSZ`K+j1Jacfs8<7;rC;6p7$G%WR33`+~rqTsdfiYAl zo9rQbgt6R56ROt06qWYq^SMuu8pm&hPsHVc;dr`Hv&VNCxbsAPDA;km5cCkl>|*$$ zT`Kn!UKtAd6V}(rhLooJ_J!J8V0A(K6_&yFW8rH}#QU+Iqh3ngLuOYy(Ty0rD)D+9ZZVR|FOij(A;4B}X+YgKNRrm40Y1k^;LsVQrzaQorjgVO>5?`rmGeuvcv_2#%gnGy( zl+98o2wAjx!`RnuoI#QHAz+lU=zSC7$WaFlYsuixU~3P@AAfD&;HdosK@)4&m=J^) zSVv$Eg}oHs9=PFHpIF4)v>l6BsF~2XEjQE zVrRm3Gr&)2>5GCev4nNUbJ1`VHcRgV|2(i&XG6IX1qza)TYOR*)Gqqk!{qA7oHoG$ zf}sszB^ZF|c!K1bvNdqOR%Zl%TVl3WXJ}hrC=0*)ZYFY(lX%^dNaz>|vi+kGDW078 z>|2oKw=bEeH{JsUl^KHA?_`;SR!%!pI+pzC4~Js%pi##trPz9VvT&vUPC@WULg^>F zlO+R6VorUG;swqlry2dzZzlix)*XA7;P(j^tH}ZPZ$8+Z+T3yF?FXCp*I|PT9^4HJ zv@GhO^ES)E*0*XiM_8*IZE+btvquy?x{4jqan<(Cbb?$m@~2vP<_SwxmG0ggm+^o0 znZaW&WY5UfA-AxHpx6n>h&zSXOA9nat8J8D7vTF$zNYt+U$a2FrinuBt!p%0a<&)znV5=9Cg7In{X_i%{hsp2tP?p!xGiBL(#}g z)6IHYx>?odszdJyJBhth58*XhYP_tFps)ofZQDb?9PYUxKt*^m-dTA7JSLH|<7H4@+=SFRN z_EfUyFXzQNF8VsRxPj*{)yh?*yDH=d-Xj2e$*n@U2yC0Xtgp?|YKTpyzjU(#TBf8M z6PB@S*C|+_YBfY*?t*zNO+vXqG)$_hqFf#SC9^clw{aTE?@LW#W`FKO&6HosMTNdK zO(25QXa5b^fypS#>@u3qde%S4XoYOM=uMKi5m$hHW)T4J0SLofZ%}+v-66HaJ#ihen;RV(9G0yx7dV%Q|LEm1gVTzWD}(S+@f zmyiSY-kyw{V1|ir*sViJM@19bvN}4u_(RabXpAt7smEPk9ZxW|*{6>ecn zb96m0f$*qLBu-clOwbp0QJ`an1`sK4SS&FBG#S?z?DhAoYRKmM&i#&59fiFi^9O4H zLhB(v>OCN-=nDr;$T10^%F@gRR3p-I0(dJ0G6HVqtAAL#V*+YLdHDyo>P>VyOOG~p zAqr}&AgzJbW_?)wCqkoQR-c0h)Mrzo+(fSgRictYLdWaOFH7?F&!D_+#}&2h+~nLUOap3o>KfL4o|G?K^kLK|`NXAW^7{(@p)ry&!xu-(dL( z5Y0t7ku=oh%_&(o$0$``%PZsZpx+f}6gs&KDai5QS#FmHIjbROMPI?%AtYkelyA{_ z&ysu@iQjip3#72=ZfX)B5#gf#2eC36nafzu!R9)S`ocE#QLUyfruapKma&%Kl*Qaq zBhsPa&+ShZys{?Mjtc(pVZHvI)$!UGg-wmWKk_-ve1GiWr$JYFxw>AF)NA4Js#^*K z{oa6x7TXjS(sIm)B%^`#q6c?eMJ2X`DufrdCfH?#kt3^wb&Hjh$oh0B@gOL+Q$xaL z0S=>Ew?eiZI7QK1#?nfqj3Kj2M3$P7FC`DAe6gsHc!{pUZw-e^XjgryYfCnLUslcg-}1uI&^ItsiEtkw%C z9<9=7PEel{iH2>w1WefkAxS>p%ngB{vME3>mW9!{Tvydlk+7A$(qf-|L4^_wb>WS5 z7od`4iI3O-3Z4W5=j)k~Bm*tK&89&(fe+mYLl z0KzRkZv+`xqe6_c0Gm}7W07k&Q-IJO2BQphkSHQ#vIeZ=N6=cYN^XjqUY4q4&?`~6 z zRt}|bzLWsFq+{fEz&iW0B!)jsOelWyf3z7mnITP12lf0t4{0-G6#ZOknP*Z_4pOD- z-r;?#7^k^-%c#9BgXTiV-x$rKra1|P_=3XZ#tc)GEfZ72KA4-41*(0yc=a)DMocca zd2x>LMhbDf$TzV)-=^YYbCXU%e&JWNOQ-PNX3c1*qr*WtLMWaXrjJNly2zY(enUP=-efLN(iRmVhR&lG zGl5X&@iAv5^ScHh6@Q#oGIt#L*qd4dvd82YVIZYx-zvI=(~6`Hq$U64xpr?E(cUTC zcka8C!I>8#ox;6G2T^1v;`hAOp}TmWwomhhyuS3R={a<={>^{h&TExk&y9HPD1`v@ zveM;BvmQW&bC#m}30k!oW{&NE7Z6>@5sC71yQ`TSG9N&fhnqr1ugKm3CQVe2s#Hyd z4OJFh@QkSiI1y~L^v=$H(8``$(>sll-g+kWydad^)n7@E=%BG0I#F=6BqxQ)i8UOt z!zR8eJ`{suNb#WShkhGgCacenuskLqy)2ba-&^JBA5hH)7hH&z3vLBg#$hefAI3$| zPp(A0lq`PnMfSUw8Yyvk%-{9_4>!w}qMxS)R0;>uOy>DYB92k14Q8E!=G~Z^P>b6( zzJwqYLNoEo!%`c1mef~n5z!)`yC3Rg0=?1Drj``-sVENM1&Ymm@(}OB>6d6xd)sx7KsAXem+hP>m=l3LSfBrDmQEA~tcTqw@ z!66sU-=z*xSw9#!bD zpXC^4a>$w=0`o>b(3yE`aP=v?Fg}>t&@uaVX8NQuR#Q5+PcSL-)^0#u;C_SC7MIWc z)nnO?VC|v+>j;v&SgY<%3oIYV(>s8pe75z@)CST7;n<^Za~z`x%oLDM4h-3iH+qx7 z8b3}$mlTAJD9zCg5x5_uup5;H@Mx8UPM|MgU7lt+BlUs#-K#H%q%XLEQb%fuP%`NX zs$W_*4M;qkQ#R#fmq=-C3a=foi60XQk`bc4?Djt_0Tj@SG+NJ+$a{d{sNat)hMM3k zvG%ZA*F0inEeAyxdD@xsQ~VieIb!5xxZ6}UlCY|a3gz+3dgbjEDxwXt78)CT-$L&0e+?yLqr*PX@=b$L{UccdAHVlfrKR7lR5JGV{bHL#v zk2(-}pLRTxJ)vasGtBhNSerGkPT^&TH*GN=mnV#NqB)(g{{C3@>6$frlEV^D(V7oD z*Y7O_BL4k2uCCx#X&UiJe&T7OzKsd&*#=ZxNfx~LJO|DZD;61`V|gjX@D*-%-4$%h z;b1|Y@$yK21xqU? zArdl&A9vNO`UcrL{7_n835Y{M3et?=cXfMAK6mX&<2~Am8vQZ(vZl#whskhfY`A9C z3-l-UGn6JbwCu@ePjPx9tB287wec&3ffe7=4GFe>dWE@lOuq4?CHdFs-%GK!U-Fz= zUp-BFjQvjG@Whuh{C5h!nAY7(0G+~9U+m~50ocgF(Y-{_DIDATbiXp_6i)0ra=H*Y zErSjWF-gsE-f0>6+xPOZ&gvOrgssTRV7z{-ajmlLJH4!#V0i}ToT28l)*wes)g|crZ*0`PAPl1SV$vU{?-Ajq~3Hx9WY{_LUID znreey-wouE3EVQb940K~LoagIFT*H#e(CyuADbxJjO4{S`J#-2c9dP$%RPH}rd;~e zZM_^*9{p%#zkVrCd2HV4ZYeL)+jG29Ub%ZJ{h5PJuJ<1V*vQu$F35VJi9~s#EID6H zj?_PD?i!P~)Lw1EQgZqmfBygAmKpyaWUW3U|37EKO78z?P3JMC-mX7AcpdBZP`FSY`0GGl?rJ7pMQM4#Q5`O|BRbWK~}iv$}bDgf!wO{~AyB+}pyM%unu zhufVKCvsc$XmL2>Y*Ne^o?Evsc`Wrts%GQFnX6Dyq?t$Si~+}a2baPJp-zi zhkf=y#>s}f^a?{nRwfQw*+kQp3^B|yu~a_D%ETv$^S2ZH!tFrWlWhlh?KJ9pzrsya z&%W{)u&q(d z6c2czcQG@(A#r*!gQf;7lIBE3-%O*PV6#eISC{ScN!d#@-t=TeCA!cHQZPw1Ec$Ve z5%jskD&4}VsBzTXIhCAyBV3@iEMhl*SfTI&Q1#Mt#%adc=79;@fV*_whR*GT=Uf2V zO0C%oz?{}QJ!cp&N~X>`7I-k~rMP_P08t&5b4i0?Mr^{XwZRzV!O$8Xs6fxl<%_!6 zpdJG0K$xQ6~ZU%0aD9>Ye(hc9|8cU1i8Rg#AWC|z{t zJ9hn4^4a2>ODVgid(Ll!qJdzdaO;@GqIbPds*wkTpE9RTS<47_ESuPb<<>D_jKyKT z38opASX-Ee=lG;#$SdOMFs|>0JG;kr?cX{-cho$BQS(C=ds}=Mw37>ePy_o2d&4Gt z&b{uvD+1nD3A5*s_Jpl!7TQxw#gH!?iZ)^H{IY03QXF%t=Rji~ueO?x1F`{G8VO{+ z;IuoD3_da%1H_y?bQFoZ<@SVi(e2CZ%4K$Cu^5d+X-2ha+QoKdfn8bZ6GNChtdVV} zE=MToHL4~m?qC!g@#zdh1~T^IG5{$BHyye-x`CD1U|_izX=3zUW|zUi6IIo+?PftM zbIiHWK^M~R?shuo%yd@GqJch6B2-T#F0|u%*a(F&Fw{;>yo`hN9`Oi5V67N<@iM0cb)*|mSN+BzqEqr?!p+sy^h3=qj8!Yy#c)Msbx_5PZlpcSfp!6B;W9}K%&hlHAv7Yv>1z6= zrVGa{42D|53g&?jFU4q^T|Kl|3Zdf=V4|uAg<+DG=9n|PI=k&GLwD5140PGLW?bTR zK?6-b(pAyDCzk}2NUmJeNRUkofwN$!oi0~1a#1lU<>vz_A>aun#c3AC6bto2VX`Eb z1qq15rHF3HPvBNHt3ISiVS3Z!T_J5!ua80W3UwJK_}u7w6VbEnxm|2XW82>a z!G2Zlr$p$p9hUFIyN3z3{Em^|ZSxME=l`@p-p@be{ai)<4}s+Sm_@!1J>>r=O5RVM R Sun Feb 16 14:19:06 1997 +#LyX 0.10 (C) 1995 1996 Matthias Ettrich and the LyX Team +\lyxformat 2.10 +\textclass article +\begin_preamble +\catcode`@=11 % @ ist ab jetzt ein gewoehnlicher Buchstabe +\def\Res{\mathop{\operator@font Res}} +\def\ll{\langle\!\langle} +\def\gg{\rangle\!\rangle} +\catcode`@=12 % @ ist ab jetzt wieder ein Sonderzeichen + +\end_preamble +\language default +\inputencoding latin1 +\fontscheme default +\epsfig dvips +\papersize a4paper +\paperfontsize 12 +\baselinestretch 1.00 +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation indent +\quotes_language english +\quotes_times 2 +\paperorientation portrait +\papercolumns 0 +\papersides 1 +\paperpagestyle plain + +\layout LaTeX Title + +The diagonal of a rational function +\layout Description + +Theorem: +\layout Standard + +Let +\begin_inset Formula \( M \) +\end_inset + + be a torsion-free +\begin_inset Formula \( R \) +\end_inset + +-module, and +\begin_inset Formula \( d>0 \) +\end_inset + +. + Let +\begin_inset Formula +\[ +f=\sum _{n_{1},...,n_{d}}a_{n_{1},...,n_{d}}\, x_{1}^{n_{1}}\cdots x_{d}^{n_{d}}\in M[[x_{1},\ldots x_{d}]]\] + +\end_inset + +be a rational function, i. +e. + there are +\begin_inset Formula \( P\in M[x_{1},\ldots ,x_{d}] \) +\end_inset + + and +\begin_inset Formula \( Q\in R[x_{1},\ldots ,x_{d}] \) +\end_inset + + with +\begin_inset Formula \( Q(0,\ldots ,0)=1 \) +\end_inset + + and +\begin_inset Formula \( Q\cdot f=P \) +\end_inset + +. + Then the full diagonal of +\begin_inset Formula \( f \) +\end_inset + + +\begin_inset Formula +\[ +g=\sum ^{\infty }_{n=0}a_{n,\ldots ,n}\, x_{1}^{n}\] + +\end_inset + +is a D-finite element of +\begin_inset Formula \( M[[x_{1}]] \) +\end_inset + +, w. +r. +t. + +\begin_inset Formula \( R[x_{1}] \) +\end_inset + + and +\begin_inset Formula \( \{\partial _{x_{1}}\} \) +\end_inset + +. + +\layout Description + +Proof: +\layout Standard + +From the hypotheses, +\begin_inset Formula \( M[[x_{1},\ldots ,x_{d}]] \) +\end_inset + + is a torsion-free differential module over +\begin_inset Formula \( R[x_{1},\ldots ,x_{d}] \) +\end_inset + + w. +r. +t. + the derivatives +\begin_inset Formula \( \{\partial _{x_{1}},\ldots ,\partial _{x_{d}}\} \) +\end_inset + +, and +\begin_inset Formula \( f \) +\end_inset + + is a D-finite element of +\begin_inset Formula \( M[[x_{1},\ldots ,x_{d}]] \) +\end_inset + + over +\begin_inset Formula \( R[x_{1},\ldots ,x_{d}] \) +\end_inset + + w. +r. +t. + +\begin_inset Formula \( \{\partial _{x_{1}},\ldots ,\partial _{x_{d}}\} \) +\end_inset + +. + Now apply the general diagonal theorem ([1], section 2. +18) +\begin_inset Formula \( d-1 \) +\end_inset + + times. + +\layout Description + +Theorem: +\layout Standard + +Let +\begin_inset Formula \( R \) +\end_inset + + be an integral domain of characteristic 0 and +\begin_inset Formula \( M \) +\end_inset + + simultaneously a torsion-free +\begin_inset Formula \( R \) +\end_inset + +-module and a commutative +\begin_inset Formula \( R \) +\end_inset + +-algebra without zero divisors. + Let +\begin_inset Formula +\[ +f=\sum _{m,n\geq 0}a_{m,n}x^{m}y^{n}\in M[[x,y]]\] + +\end_inset + + be a rational function. + Then the diagonal of +\begin_inset Formula \( f \) +\end_inset + + +\begin_inset Formula +\[ +g=\sum ^{\infty }_{n=0}a_{n,n}\, x^{n}\] + +\end_inset + + is algebraic over +\begin_inset Formula \( R[x] \) +\end_inset + +. + +\layout Description + +Motivation +\protected_separator +of +\protected_separator +proof: +\layout Standard + +The usual proof ([2]) uses complex analysis and works only for +\begin_inset Formula \( R=M=C \) +\end_inset + +. + The idea is to compute +\begin_inset Formula +\[ +g(x^{2})=\frac{1}{2\pi i}\oint _{|z|=1}f(xz,\frac{x}{z})\frac{dz}{z}\] + +\end_inset + +This integral, whose integrand is a rational function in +\begin_inset Formula \( x \) +\end_inset + + and +\begin_inset Formula \( z \) +\end_inset + +, is calculated using the residue theorem. + Since +\begin_inset Formula \( f(x,y) \) +\end_inset + + is continuous at +\begin_inset Formula \( (0,0) \) +\end_inset + +, there is a +\begin_inset Formula \( \delta >0 \) +\end_inset + + such that +\begin_inset Formula \( f(x,y)\neq \infty \) +\end_inset + + for +\begin_inset Formula \( |x|<\delta \) +\end_inset + +, +\begin_inset Formula \( |y|<\delta \) +\end_inset + +. + It follows that for all +\begin_inset Formula \( \varepsilon >0 \) +\end_inset + + and +\begin_inset Formula \( |x|<\delta \varepsilon \) +\end_inset + + all the poles of +\begin_inset Formula \( f(xz,\frac{x}{z}) \) +\end_inset + + are contained in +\begin_inset Formula \( \{z:|z|<\varepsilon \}\cup \{z:|z|>\frac{1}{\varepsilon }\} \) +\end_inset + +. + Thus the poles of +\begin_inset Formula \( f(xz,\frac{x}{z}) \) +\end_inset + +, all algebraic functions of +\begin_inset Formula \( x \) +\end_inset + + -- let's call them +\begin_inset Formula \( \zeta _{1}(x),\ldots \zeta _{s}(x) \) +\end_inset + + --, can be divided up into those for which +\begin_inset Formula \( |\zeta _{i}(x)|=O(|x|) \) +\end_inset + + as +\begin_inset Formula \( x\rightarrow 0 \) +\end_inset + + and those for which +\begin_inset Formula \( \frac{1}{|\zeta _{i}(x)|}=O(|x|) \) +\end_inset + + as +\begin_inset Formula \( x\rightarrow 0 \) +\end_inset + +. + It follows from the residue theorem that for +\begin_inset Formula \( |x|<\delta \) +\end_inset + + +\begin_inset Formula +\[ +g(x^{2})=\sum _{\zeta =0\vee \zeta =O(|x|)}\Res _{z=\zeta }\, f(xz,\frac{x}{z})\] + +\end_inset + + This is algebraic over +\begin_inset Formula \( C(x) \) +\end_inset + +. + Hence +\begin_inset Formula \( g(x) \) +\end_inset + + is algebraic over +\begin_inset Formula \( C(x^{1/2}) \) +\end_inset + +, hence also algebraic over +\begin_inset Formula \( C(x) \) +\end_inset + +. + +\layout Description + +Proof: +\layout Standard + +Let +\begin_inset Formula +\[ +h(x,z):=f(xz,\frac{x}{z})=\sum ^{\infty }_{m,n=0}a_{m,n}x^{m+n}z^{m-n}\in M[[xz,xz^{-1}]]\] + +\end_inset + +Then +\begin_inset Formula \( g(x^{2}) \) +\end_inset + + is the coefficient of +\begin_inset Formula \( z^{0} \) +\end_inset + + in +\begin_inset Formula \( h(x,z) \) +\end_inset + +. + Let +\begin_inset Formula \( N(x,z):=z^{d}Q(xz,\frac{x}{z}) \) +\end_inset + + (with +\begin_inset Formula \( d:=\max (\deg _{y}P,\deg _{y}Q) \) +\end_inset + +) be +\begin_inset Quotes eld +\end_inset + +the denominator +\begin_inset Quotes erd +\end_inset + + of +\begin_inset Formula \( h(x,z) \) +\end_inset + +. + We have +\begin_inset Formula \( N(x,z)\in R[x,z] \) +\end_inset + + and +\begin_inset Formula \( N\neq 0 \) +\end_inset + + (because +\begin_inset Formula \( N(0,z)=z^{d} \) +\end_inset + +). + Let +\begin_inset Formula \( K \) +\end_inset + + be the quotient field of +\begin_inset Formula \( R \) +\end_inset + +. + Thus +\begin_inset Formula \( N(x,z)\in K[x][z]\setminus \{0\} \) +\end_inset + +. + +\layout Standard + +It is well-known (see [3], p. +64, or [4], chap. + IV, §2, prop. + 8, or [5], chap. + III, §1) that the splitting field of +\begin_inset Formula \( N(x,z) \) +\end_inset + + over +\begin_inset Formula \( K(x) \) +\end_inset + + can be embedded into a field +\begin_inset Formula \( L((x^{1/r})) \) +\end_inset + +, where +\begin_inset Formula \( r \) +\end_inset + + is a positive integer and +\begin_inset Formula \( L \) +\end_inset + + is a finite-algebraic extension field of +\begin_inset Formula \( K \) +\end_inset + +, i. +e. + a simple algebraic extension +\begin_inset Formula \( L=K(\alpha )=K\alpha ^{0}+\cdots +K\alpha ^{u-1} \) +\end_inset + +. + +\layout Standard + + +\begin_inset Formula \( \widetilde{M}:=(R\setminus \{0\})^{-1}\cdot M \) +\end_inset + + is a +\begin_inset Formula \( K \) +\end_inset + +-vector space and a commutative +\begin_inset Formula \( K \) +\end_inset + +-algebra without zero divisors. + +\begin_inset Formula \( \widehat{M}:=\widetilde{M}\alpha ^{0}+\cdots +\widetilde{M}\alpha ^{u-1} \) +\end_inset + + is an +\begin_inset Formula \( L \) +\end_inset + +-vector space and a commutative +\begin_inset Formula \( L \) +\end_inset + +-algebra without zero divisors. + +\layout Standard + + +\begin_inset Formula +\begin{eqnarray*} +\widehat{M}\ll x,z\gg & := & \widehat{M}[[x^{1/r}\cdot z,x^{1/r}\cdot z^{-1},x^{1/r}]][x^{-1/r}]\\ + & = & \left\{ \sum _{m,n}c_{m,n}x^{m/r}z^{n}:c_{m,n}\neq 0\Rightarrow |n|\leq m+O(1)\right\} +\end{eqnarray*} + +\end_inset + +is an +\begin_inset Formula \( L \) +\end_inset + +-algebra which contains +\begin_inset Formula \( \widehat{M}((x^{1/r})) \) +\end_inset + +. + +\layout Standard + +Since +\begin_inset Formula \( N(x,z) \) +\end_inset + + splits into linear factors in +\begin_inset Formula \( L((x^{1/r}))[z] \) +\end_inset + +, +\begin_inset Formula \( N(x,z)=l\prod ^{s}_{i=1}(z-\zeta _{i}(x))^{k_{i}} \) +\end_inset + +, there exists a partial fraction decomposition of +\begin_inset Formula \( h(x,z)=\frac{P(xz,\frac{x}{z})}{Q(xz,\frac{x}{z})}=\frac{z^{d}P(xz,\frac{x}{z})}{N(x,z)} \) +\end_inset + + in +\begin_inset Formula \( \widehat{M}\ll x,z\gg \) +\end_inset + +: +\layout Standard + + +\begin_inset Formula +\[ +h(x,z)=\sum ^{l}_{j=0}P_{j}(x)z^{j}+\sum ^{s}_{i=1}\sum ^{k_{i}}_{k=1}\frac{P_{i,k}(x)}{(z-\zeta _{i}(x))^{k}}\] + +\end_inset + +with +\begin_inset Formula \( P_{j}(x),P_{i,k}(x)\in \widehat{M}((x^{1/r})) \) +\end_inset + +. + +\layout Standard + +Recall that we are looking for the coefficient of +\begin_inset Formula \( z^{0} \) +\end_inset + + in +\begin_inset Formula \( h(x,z) \) +\end_inset + +. + We compute it separately for each summand. + +\layout Standard + +If +\begin_inset Formula \( \zeta _{i}(x)=ax^{m/r}+... \) +\end_inset + + with +\begin_inset Formula \( a\in L\setminus \{0\} \) +\end_inset + +, +\begin_inset Formula \( m>0 \) +\end_inset + +, or +\begin_inset Formula \( \zeta _{i}(x)=0 \) +\end_inset + +, we have +\layout Standard + + +\begin_inset Formula +\begin{eqnarray*} +\frac{1}{(z-\zeta _{i}(x))^{k}} & = & \frac{1}{z^{k}}\cdot \frac{1}{\left( 1-\frac{\zeta _{i}(x)}{z}\right) ^{k}}\\ + & = & \frac{1}{z^{k}}\cdot \sum ^{\infty }_{j=0}{k-1+j\choose k-1}\left( \frac{\zeta _{i}(x)}{z}\right) ^{j}\\ + & = & \sum ^{\infty }_{j=0}{k-1+j\choose k-1}\frac{\zeta _{i}(x)^{j}}{z^{k+j}} +\end{eqnarray*} + +\end_inset + +hence the coefficient of +\begin_inset Formula \( z^{0} \) +\end_inset + + in +\begin_inset Formula \( \frac{P_{i,k}(x)}{(z-\zeta _{i}(x))^{k}} \) +\end_inset + + is +\begin_inset Formula \( 0 \) +\end_inset + +. + +\layout Standard +\cursor 59 +If +\begin_inset Formula \( \zeta _{i}(x)=ax^{m/r}+... \) +\end_inset + + with +\begin_inset Formula \( a\in L\setminus \{0\} \) +\end_inset + +, +\begin_inset Formula \( m<0 \) +\end_inset + +, we have +\begin_inset Formula +\[ +\frac{1}{(z-\zeta _{i}(x))^{k}}=\frac{1}{(-\zeta _{i}(x))^{k}}\cdot \frac{1}{\left( 1-\frac{z}{\zeta _{i}(x)}\right) ^{k}}=\frac{1}{(-\zeta _{i}(x))^{k}}\cdot \sum _{j=0}^{\infty }{k-1+j\choose k-1}\left( \frac{z}{\zeta _{i}(x)}\right) ^{j}\] + +\end_inset + +hence the coefficient of +\begin_inset Formula \( z^{0} \) +\end_inset + + in +\begin_inset Formula \( \frac{P_{i,k}(x)}{(z-\zeta _{i}(x))^{k}} \) +\end_inset + + is +\begin_inset Formula \( \frac{P_{i,k}(x)}{(-\zeta _{i}(x))^{k}} \) +\end_inset + +. + +\layout Standard + +The case +\begin_inset Formula \( \zeta _{i}(x)=ax^{m/r}+... \) +\end_inset + + with +\begin_inset Formula \( a\in L\setminus \{0\} \) +\end_inset + +, +\begin_inset Formula \( m=0 \) +\end_inset + +, cannot occur, because it would imply +\begin_inset Formula \( 0=N(0,\zeta _{i}(0))=N(0,a)=a^{d}. \) +\end_inset + + +\layout Standard + +Altogether we have +\begin_inset Formula +\[ +g(x^{2})=[z^{0}]h(x,z)=P_{0}(x)+\sum _{\frac{1}{\zeta _{i}(x)}=o(x)}\sum ^{k_{i}}_{k=1}\frac{P_{i,k}(x)}{(-\zeta _{i}(x))^{k}}\in \widehat{M}((x^{1/r}))\] + +\end_inset + + +\layout Standard + +Since all +\begin_inset Formula \( \zeta _{i}(x) \) +\end_inset + +(in +\begin_inset Formula \( L((x^{1/r})) \) +\end_inset + +) and all +\begin_inset Formula \( P_{j}(x),P_{i,k}(x) \) +\end_inset + + (in +\begin_inset Formula \( \widehat{M}((x^{1/r})) \) +\end_inset + +) are algebraic over +\begin_inset Formula \( K(x) \) +\end_inset + +, the same holds also for +\begin_inset Formula \( g(x^{2}) \) +\end_inset + +. + Hence +\begin_inset Formula \( g(x) \) +\end_inset + + is algebraic over +\begin_inset Formula \( K(x^{1/2}) \) +\end_inset + +, hence also over +\begin_inset Formula \( K(x) \) +\end_inset + +. + After clearing denominators, we finally conclude that +\begin_inset Formula \( g(x) \) +\end_inset + + is algebraic over +\begin_inset Formula \( R[x] \) +\end_inset + +. + +\layout Bibliography + +[1] Bruno Haible: D-finite power series in several variables. + +\shape italic +Diploma thesis, University of Karlsruhe, June 1989. + +\shape default + Sections 2. +18 and 2. +20. + +\layout Bibliography + +[2] M. + L. + J. + Hautus, D. + A. + Klarner: The diagonal of a double power series. + +\shape italic +Duke Math. + J. + +\shape default + +\series bold +38 +\series default + (1971), 229-235. + +\layout Bibliography + +[3] C. + Chevalley: Introduction to the theory of algebraic functions of one variable. + +\shape italic +Mathematical Surveys VI. + American Mathematical Society. + +\layout Bibliography + +[4] Jean-Pierre Serre: Corps locaux. + +\shape italic +Hermann. + Paris +\shape default +1968. + +\layout Bibliography + +[5] Martin Eichler: Introduction to the theory of algebraic numbers and + functions. + +\shape italic + Academic Press. + New York, London +\shape default +1966. + diff --git a/doc/polynomial/diag_rational.ps b/doc/polynomial/diag_rational.ps new file mode 100644 index 0000000..8b5e6a0 --- /dev/null +++ b/doc/polynomial/diag_rational.ps @@ -0,0 +1,1315 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: diag_rational.dvi +%%Pages: 4 +%%PageOrder: Ascend +%%BoundingBox: 0 0 596 842 +%%DocumentPaperSizes: a4 +%%EndComments +%DVIPSCommandLine: dvips -Pljfour -o diag_rational.ps diag_rational.dvi +%DVIPSParameters: dpi=600, compressed, comments removed +%DVIPSSource: TeX output 1997.02.16:1419 +%%BeginProcSet: texc.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]/id ch-image N /rw ch-width 7 add 8 idiv string N /rc 0 N /gp 0 N +/cp 0 N{rc 0 ne{rc 1 sub /rc X rw}{G}ifelse}imagemask restore}B /G{{id +gp get /gp gp 1 add N dup 18 mod S 18 idiv pl S get exec}loop}B /adv{cp +add /cp X}B /chg{rw cp id gp 4 index getinterval putinterval dup gp add +/gp X adv}B /nd{/cp 0 N rw exit}B /lsh{rw cp 2 copy get dup 0 eq{pop 1}{ +dup 255 eq{pop 254}{dup dup add 255 and S 1 and or}ifelse}ifelse put 1 +adv}B /rsh{rw cp 2 copy get dup 0 eq{pop 128}{dup 255 eq{pop 127}{dup 2 +idiv S 128 and or}ifelse}ifelse put 1 adv}B /clr{rw cp 2 index string +putinterval adv}B /set{rw cp fillstr 0 4 index getinterval putinterval +adv}B /fillstr 18 string 0 1 17{2 copy 255 put pop}for N /pl[{adv 1 chg} +{adv 1 chg nd}{1 add chg}{1 add chg nd}{adv lsh}{adv lsh nd}{adv rsh}{ +adv rsh nd}{1 add adv}{/rc X nd}{1 add set}{1 add clr}{adv 2 chg}{adv 2 +chg nd}{pop nd}]dup{bind pop}forall N /D{/cc X dup type /stringtype ne{] +}if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +TeXDict begin 39158280 55380996 1000 600 600 (diag_rational.dvi) +@start /Fa 39 122 df<13F0EA03FC1207A2EA0FFEA4EA07FCEA03CCEA000C131C1318 +A2133813301370136013E0EA01C013801203EA0700120E5A5A5A5A5A0F1D7A891E>44 +D<120FEA3FC0127FA212FFA31380EA7F00123C0A0A76891E>46 D<16C01501A215031507 +ED0F80151F153F157F913801FF005C140F147F903807FCFEEB0FF0EB0700EB00015DA314 +035DA314075DA3140F5DA3141F5DA3143F5DA3147F92C7FCA35C5CA313015CA313035CA3 +13075CA2130FA2131F133FB612FCA25D224276C132>49 D56 DI65 D<91B712F818FF19C002 +01903980003FF06E90C7EA0FF84AED03FCF000FE4B157FA2F13F800203EE1FC05DF10FE0 +A214074B16F01907A2140F5D1AF8A2141F5DA2190F143F5D1AF0A2147F4B151FA302FF17 +E092C9123FA34918C04A167F1A80A2010317FF4A1700A24E5A13074A4B5A611807010F5F +4A4B5A181F61011F4C5A4A4BC7FC18FE4D5A013F4B5A4A4A5A4D5A017FED3FC005FFC8FC +4AEB03FE01FFEC1FF8B812E094C9FC16F845447AC34A>68 D<91B6D8803FB512E0A30201 +0180C7387FE0006E90C86C5A4A167FA24B5EA219FF14034B93C7FCA26014074B5DA21803 +140F4B5DA21807141F4B5DA2180F143F4B5DA2181F147F92B75AA3DAFF80C7123F92C85B +A2187F5B4A5EA218FF13034A93C8FCA25F13074A5DA21703130F4A5DA21707131F4A5DA2 +170F133F4A5DA2017F151FA24A5D496C4A7EB6D8803FB512E0A34B447AC348>72 +D<027FB512E091B6FCA20200EBE000ED7F8015FFA293C7FCA35C5DA314035DA314075DA3 +140F5DA3141F5DA3143F5DA3147F5DA314FF92C8FCA35B5CA313035CA313075CA3130F5C +A3131F5CA2133FA25CEBFFE0B612E0A25D2B447BC326>I<031FB512F05DA29239000FFC +005FA35FA2161FA25FA2163FA25FA2167FA25FA216FFA294C7FCA25DA25EA21503A25EA2 +1507A25EA2150FA25EA2151FA25EA2153FA25EA2157FA25EEA0F80D83FE013FF93C8FC12 +7FA24A5AEAFFC04A5A1300007C495A0070495A4A5A6C5C003C495A6C01FEC9FC380F81F8 +3803FFE0C690CAFC344679C333>I<91B66C90383FFFF8A302010180C7000F13006E90C8 +EA07FC4A17F01AC04B4B5A4FC7FC193C02035E4B5DF003E0F0078002074BC8FC4B141E60 +18F8020F4A5A4BEB03C04D5A4DC9FC021F141E4B137C17F04C5A023F495A4B487E161F16 +3F027F497EED80FFED81EF923883CFF89138FF8F8FED1E07033C7F157849EBF00303E07F +15C092380001FF495A5C707FA213074A6E7EA2173F010F825C171F84131F4A140F84A201 +3F6F7E5CA2017F6F7EA24A4A7E496C4A7FB66C90B512FC5E614D447AC34B>I<91B612F0 +A25F020101C0C7FC6E5B4A90C8FCA25DA314035DA314075DA3140F5DA3141F5DA3143F5D +A3147F5DA314FF92C9FCA35B5CA3010316104A1538A21878010716705C18F018E0010F15 +015C18C01703011F15074A1580170FA2013FED1F004A5C5F017F15FE16034A130F01FFEC +7FFCB8FCA25F35447AC33D>I<91B56C93387FFFC08298B5FC02014DEBC0006E614A5FA2 +03DF4C6CC7FC1A0E63912603CFE05D038F5F1A381A711407030FEEE1FCA2F101C3020FEE +0383020E60F107036F6C1507021E160E021C60191CF1380F143C023804705BA2F1E01F02 +78ED01C091267003F85EF003801A3F02F0ED070002E0030E5CA24E137F130102C04B91C8 +FC606201036D6C5B02805F4D5A943803800113070200DA07005BA2050E1303495D010E60 +6F6C5A1907011E5D011C4B5CA27048130F133C01384B5C017892C7FC191F01F85C486C02 +7E5DD807FE027C4A7EB500F00178013FB512C0A216705A447AC357>I<91B56C49B512E0 +A28202009239000FFC00F107F0706E5A4A5F15DF705D1907EC03CFDB8FF892C7FCA20387 +5D02077F0303150EA270141EEC0F01020E161C826F153C141E021C6E1338167F1978023C +800238013F1470A27113F00278131F02705E83040F130102F014F84A5E1607EFFC031301 +4A01035C17FE1807010314014A02FF90C8FCA2705B0107168F91C8138E177F18DE5B010E +ED3FDC18FCA2011E151F011C5EA2170F133C01386F5A1378A201F81503486C5EEA07FEB5 +00F01401A2604B447AC348>I<91B712F018FEF0FF800201903980007FE06E90C7EA1FF0 +4AED07F818034B15FCF001FE1403A24B15FFA21407A25DA2140FF003FE5DA2021F16FC18 +074B15F8180F023F16F0F01FE04B15C0F03F80027FED7F0018FE4BEB03FCEF0FF002FFEC +7FC092B6C7FC17F892CAFC5BA25CA21303A25CA21307A25CA2130FA25CA2131FA25CA213 +3FA25CA2137FA25C497EB67EA340447AC342>80 D83 D<001FB500F090383FFFFCA326003FF0C7000113806D48913800FE +00013F167C18785C187018F0017F5E5CA2170101FF5E91C8FCA21703485F5BA217070003 +94C7FC5BA25F0007160E5BA2171E120F49151CA2173C121F491538A21778123F491570A2 +17F0127F495DA2160100FF5E90C8FCA216035F16074893C8FC5E160E161E5E007E153800 +7F15785E6C4A5A6D495A001F4A5A6D49C9FC6C6C133E6C6C13F83903FC07F0C6B512C001 +3F90CAFCEB07F83E466DC348>85 DI<007FB54AB51280B65CA2000101E09139007FF0006C49ED3F +C04A93C7FC6D6C153E601878013F5E6E4A5A604D5A6D6C4AC8FC5F171E010F151C6E5C5F +010715F06E495A5F4C5A6D6C49C9FC5E161E0101141C6E5B5E16F06DEB81E05EED8380DA +7F87CAFC15CF15DEEC3FDC15F85DA26E5A5D143FA35D147FA392CBFC5CA35C1301A35C13 +03A3495AA3497E000FB512F8A341446DC348>89 D97 D99 DIII<14FE137FA3EB01FC13001301A25CA21303A25CA21307A25CA2130F +A25CA2131FA25C157F90393F83FFC091388F81F091381E00F802387F4948137C5C4A137E +A2495A91C7FCA25B484814FE5E5BA2000314015E5BA2000714035E5B1507000F5DA24913 +0F5E001F1678031F1370491480A2003F023F13F0EE00E090C7FC160148023E13C0160300 +7E1680EE070000FEEC1E0FED1F1E48EC0FF80038EC03E02D467AC432>104 +D<143C147E14FE1301A3EB00FC14701400AE137C48B4FC3803C780380703C0000F13E012 +0E121C13071238A21278EA700F14C0131F00F0138012E0EA003F1400A25B137EA213FE5B +12015BA212035B141E0007131C13E0A2000F133CEBC038A21478EB807014F014E0EB81C0 +EA0783EBC7803803FE00EA00F8174378C11E>I<14FE137FA3EB01FC13001301A25CA213 +03A25CA21307A25CA2130FA25CA2131FA25C167E013F49B4FC92380783C09138000E07ED +3C1F491370ED603F017E13E0EC01C09026FE03801380913907000E00D9FC0E90C7FC5C00 +015B5C495AEBF9C03803FB8001FFC9FCA214F03807F3FCEBF07F9038E01FC06E7E000F13 +0781EBC003A2001F150FA20180140EA2003F151E161C010013E0A2485DA2007E15781670 +00FE01015B15F1489038007F800038021FC7FC2A467AC42D>107 +DIIIII114 DI<1470EB01F8A313035CA313075CA3130F5CA3131F5CA2007FB512E0B6FC15 +C0D8003FC7FCA25B137EA313FE5BA312015BA312035BA312075BA3120F5BA2EC0780001F +140013805C140E003F131EEB001C143C14385C6C13F0495A6C485AEB8780D807FEC7FCEA +01F81B3F78BD20>I<137C48B414072603C780EB1F80380703C0000F7F000E153F121C01 +07150012385E1278D8700F147E5C011F14FE00F05B00E05DEA003FEC0001A2495C137E15 +0313FE495CA215071201495CA2030F13380003167849ECC070A3031F13F0EE80E0153F00 +011581037F13C06DEBEF8300000101148090397C03C787903A3E0F07C70090391FFE01FE +903903F000782D2D78AB34>I<017C143848B414FC3A03C78001FE380703C0000F13E012 +0E001C14000107147E1238163E1278D8700F141E5C131F00F049131C12E0EA003F91C712 +3C16385B137E167801FE14705BA216F0000115E05B150116C0A24848EB0380A2ED0700A2 +150E12015D6D5B000014786D5B90387C01E090383F0780D90FFFC7FCEB03F8272D78AB2D +>I<017CEE038048B4020EEB0FC02603C780013FEB1FE0380703C0000E7F5E001C037E13 +0F01071607123804FE130300785DEA700F4A1501011F130100F001804914C012E0EA003F +DA000314034C14805B137E0307140701FE1700495CA2030F5C0001170E495CA260A24848 +495A60A2601201033F5C7F4B6C485A000002F713036D9039E7E0078090267E01C349C7FC +903A1F0781F81E903A0FFF007FF8D901FCEB0FE03B2D78AB41>I<137C48B414072603C7 +80EB1F80380703C0000F7F000E153F001C1600130712385E0078157EEA700F5C011F14FE +00F0495B12E0EA003FEC00015E5B137E150301FE5C5BA2150700015D5BA2150F00035D5B +A2151F5EA2153F12014BC7FC6D5B00005BEB7C0390383E0F7EEB1FFEEB03F090C712FE5D +A214015D121F397F8003F0A24A5A4848485A5D48131F00F049C8FC0070137E007813F838 +3801F0381E07C06CB4C9FCEA01FC294078AB2F>121 D E /Fb 7 +116 df82 D<92380FFFF04AB67E020F15F0023F15FC91 +B77E01039039FE001FFF4901F8010113804901E0010713C04901804913E0017F90C7FC49 +484A13F0A2485B485B5A5C5A7113E0485B7113C048701380943800FE0095C7FC485BA4B5 +FCAE7EA280A27EA2806C18FCA26C6D150119F87E6C6D15036EED07F06C18E06C6D150F6D +6DEC1FC06D01E0EC7F806D6DECFF00010701FCEB03FE6D9039FFC03FFC010091B512F002 +3F5D020F1580020102FCC7FCDA000F13C03E437BC148>99 D<92380FFFC04AB512FC020F +ECFF80023F15E091B712F80103D9FE037F499039F0007FFF011F01C0011F7F49496D7F49 +90C76C7F49486E7F48498048844A804884485B727E5A5C48717EA35A5C721380A2B5FCA3 +91B9FCA41A0002C0CBFCA67EA380A27EA27E6E160FF11F806C183F6C7FF17F006C7F6C6D +16FE6C17016D6C4B5A6D6D4A5A6D01E04A5A6D6DEC3FE0010301FC49B45A6D9026FFC01F +90C7FC6D6C90B55A021F15F8020715E0020092C8FC030713F041437CC14A>101 +DI<902607FF +80EB1FFFB691B512F0040714FC041F14FF4C8193267FE07F7F922781FE001F7FC6DA83F8 +6D7F6DD987F07F6DD98FC0814C7F039FC78015BE03BC8003FC825DA25DA25DA45DB3B2B7 +D8F007B71280A651417BC05A>110 D114 +D<913A3FFF8007800107B5EAF81F011FECFE7F017F91B5FC48B8FC48EBE0014890C7121F +D80FFC1407D81FF0801600485A007F167F49153FA212FF171FA27F7F7F6D92C7FC13FF14 +E014FF6C14F8EDFFC06C15FC16FF6C16C06C16F06C826C826C826C82013F1680010F16C0 +1303D9007F15E0020315F0EC001F1500041F13F81607007C150100FC81177F6C163FA217 +1F7EA26D16F0A27F173F6D16E06D157F6D16C001FEEDFF806D0203130002C0EB0FFE02FC +EB7FFC01DFB65A010F5DD8FE0315C026F8007F49C7FC48010F13E035437BC140>I +E /Fc 5 107 df0 D<12E012F812FEEA3F80EA0FE0EA03F8EA00 +FEEB3F80EB0FE0EB03F8EB00FC143FEC0FC0EC07F0EC01FCEC007FED1FC0ED07F0ED01FC +ED007FEE1FC01607161FEE7F00ED01FCED07F0ED1FC0037FC7FCEC01FCEC07F0EC0FC002 +3FC8FC14FCEB03F8EB0FE0EB3F8001FEC9FCEA03F8EA0FE0EA3F80007ECAFC12F812E0CB +FCAD007FB71280B812C0A22A3B7AAB37>21 D49 +D<00E0150C161C6C153C007015380078157800381570003C15F0001C15E0A2001E140100 +0E15C0000F14036C15806D1307000315006D5B0001140E6D131E0000141C6D133C017013 +38A20178137801381370013C13F0011C5BEB1E01010E5BEB0F0301075B1487010390C7FC +14CFEB01CEA214FE6D5AA21478A2143026297CA72F>95 D<12E0B3B3B3AD034378B114> +106 D E /Fd 16 121 df<007FB912E0BA12F0A26C18E03C04789A4D>0 +D<121FEA3F80EA7FC0EAFFE0A5EA7FC0EA3F80EA1F000B0B789E1C>I<19E0F003F0180F +F03FE0F0FF80943803FE00EF0FF8EF3FE0EFFF80DC03FEC7FCEE0FF8EE3FE0EEFF80DB03 +FEC8FCED1FF8ED7FE0913801FF80DA07FEC9FCEC1FF0EC7FC04948CAFCEB07FCEB1FF0EB +7FC04848CBFCEA07FCEA1FF0EA7FC048CCFCA2EA7FC0EA1FF0EA07FCEA01FF38007FC0EB +1FF0EB07FCEB01FF9038007FC0EC1FF0EC07FC913801FF809138007FE0ED1FF8ED07FE92 +3800FF80EE3FE0EE0FF8EE03FE933800FF80EF3FE0EF0FF8EF03FE943800FF80F03FE0F0 +0FF01803F000E01900B0007FB912E0BA12F0A26C18E03C4E78BE4D>20 +D<1AF0A3861A78A21A7C1A3CA21A3E1A1E1A1F747EA2747E747E87747E747E1B7E87757E +F30FE0F303F8007FBC12FEBE1280A26CF3FE00CEEA03F8F30FE0F31F8051C7FC1B7E6350 +5A505A63505A505AA250C8FC1A1E1A3E1A3CA21A7C1A78A21AF862A359347BB264>33 +D<18034E7E85180385180185727E1978197C8585737E86737E737E007FBA7EBB7E866C85 +CDEA0FC0747EF203F8F200FEF37F80F31FE0F307FC983801FF80A2983807FC00F31FE0F3 +7F8009FEC7FCF203F8F207E0505A007FBBC8FCBB5A626C61CCEA03F04F5A4F5A624FC9FC +193E61197819F84E5A6118036118076172CAFC59387BB464>41 D<49B4EF3FC0010F01E0 +923803FFF8013F01FC030F13FE4901FF92383FE01F48B66C91397E0007C02603F80301E0 +D901F8EB01E02807E0007FF049486D7E01806D6CD907C0147048C76C6C494880001EDA07 +FE49C87E001C6E6C013E150C486E6D48150E71481506486E01E0160793387FF1F0006092 +263FF3E08193381FFBC000E004FF1780486F4915017090C9FC82707F8482717E844D7E6C +4B6D1503006004EF1700933803E7FE0070922607C7FF5DDC0F837F003004816D140E0038 +4BC6FC0018033E6D6C5C001C4B6D6C143C6C4BD91FFC5C6C4A486D6C5C6DD907E06D6C13 +036C6C49486D9038E00FE0D801F0013FC890B55A27007C03FE6F91C7FC90263FFFF8031F +5B010F01E0030313F8D901FECAEA7FC0592D7BAB64>49 D<92B6FC02071580143F91B712 +0001030180C8FCD907FCC9FCEB1FE0EB3F80017ECAFC5B485A485A485A5B485A121F90CB +FC123EA2123C127CA2127812F8A25AA2B9FC1880A2180000F0CBFCA27EA21278127CA212 +3C123EA27E7F120F6C7E7F6C7E6C7E6C7E137E6D7EEB1FE0EB07FC6DB47E010090B6FC02 +3F1580140702001500313A78B542>I<1706170F171FA2173EA2177CA217F8A2EE01F0A2 +EE03E0A2EE07C0A2EE0F80A2EE1F00A2163EA25EA25EA24B5AA24B5AA24B5AA24B5AA24B +C7FCA2153EA25DA25DA24A5AA24A5AA24A5AA24A5AA24AC8FCA2143EA25CA25CA2495AA2 +495AA2495AA2495AA249C9FCA2133EA25BA25BA2485AA2485AA2485AA2485AA248CAFCA2 +123EA25AA25AA25A1260305C72C600>54 D<0060170C00F0171EB3B3A66C173EA2007817 +3C007C177C007E17FC003E17F86CEE01F06D15036C6CED07E06C6CED0FC0D803F8ED3F80 +D801FEEDFF0026007FC0EB07FCD93FFCEB7FF8010FB612E001031580D9007F01FCC7FC02 +0713C0373D7BBA42>91 D102 D<12FEEAFFE0EA07F8EA00FEEB7F806D7E6D7E130F6D7EA26D7EB3AD6D +7EA26D7E806E7E6E7EEC0FE0EC03FC913800FFE0A2913803FC00EC0FE0EC3FC04A5A4AC7 +FC5C495AA2495AB3AD495AA2495A131F495A495A01FEC8FCEA07F8EAFFE048C9FC236479 +CA32>I<140C141E143EA2143C147CA214F8A214F01301A2EB03E0A214C01307A2EB0F80 +A214005BA2133EA2133C137CA2137813F8A2485AA25B1203A2485AA25B120FA248C7FCA2 +121E123EA25AA2127812F8A41278127CA27EA2121E121FA26C7EA212077FA26C7EA21201 +7FA26C7EA21378137CA2133C133EA27FA27F1480A2EB07C0A2130314E0A2EB01F0A21300 +14F8A2147CA2143C143EA2141E140C176476CA27>I<126012F07EA21278127CA27EA212 +1E121FA26C7EA212077FA26C7EA212017FA26C7EA21378137CA2133C133EA27FA27F1480 +A2EB07C0A2130314E0A2EB01F0A2130014F8A2147CA2143C143EA4143C147CA214F8A214 +F01301A2EB03E0A214C01307A2EB0F80A214005BA2133EA2133C137CA2137813F8A2485A +A25B1203A2485AA25B120FA248C7FCA2121E123EA25AA2127812F8A25A126017647BCA27 +>I<126012F0B3B3B3B3B3A81260046474CA1C>I<126012F07EA21278127CA2123C123EA2 +121E121FA26C7EA212077FA212037FA212017FA26C7EA21378137CA2133C133EA2131E13 +1FA26D7EA2130780A2130380A2130180A26D7EA21478147CA2143C143EA280A28081A214 +0781A2140381A26E7EA2140081A21578157CA2153C153EA281A2811680A2150716C0A215 +0316E0A2ED01F0A2150016F8A21678167CA2163C163EA2161E160C27647BCA32>110 +D120 D E /Fe 7 62 df<13031307130E131C1338137013F0EA +01E013C01203EA0780A2EA0F00A2121EA35AA45AA512F8A25AAB7EA21278A57EA47EA37E +A2EA0780A2EA03C0120113E0EA00F013701338131C130E1307130310437AB11B>40 +D<12C07E12707E7E7E120FEA0780120313C0EA01E0A2EA00F0A21378A3133CA4131EA513 +1FA2130FAB131FA2131EA5133CA41378A313F0A2EA01E0A2EA03C013801207EA0F00120E +5A5A5A5A5A10437CB11B>I43 +D48 D<130C133C137CEA03FC12FFEAFC7C1200B3B113FE387F +FFFEA2172C7AAB23>II61 +D E /Ff 7 123 df<13031306A3EB07FC14FE130FEB3CFCEB70005B485A485A48C7FC12 +065A121C121812385AA35AA77EA27E127E6C7EEA1FF86CB4FC6C1380C613C0EB0FE01301 +A21300A214C0EA01C13800FF80EB3E00172E7CA21C>16 D<127812FCA212FEA2127E1206 +A3120CA2121C121812301260124007107A8513>59 D100 D<1338137CA2137813701300A7EA0780EA1FC0EA38E01230EA60F0EAC1E0A3 +EA03C0A3EA0780A2EA0F0013041306EA1E0CA21318121CEA1E70EA0FE0EA07800F237DA1 +16>105 D<13F8EA0FF0A21200A2485AA4485AA43807801E147FEB81C3EB8387380F060F +495A1318EB700E4848C7FCA213FCEA1E7EEA3C0F80EB0781158039780F0300A21402EB07 +0600F0138CEB03F8386000F019247CA221>107 D<3801F01E3907FC7F80390E1CE1C038 +180F8100301383007013071260EC0380D8001EC7FCA45BA21580003014C0397878018012 +F8EC030038F0FC0638E19C1C387F0FF8381E03E01A177D9523>120 +D122 D E /Fg 3 50 df<130C1338137013E0EA01C0EA038013005A120EA25A +A25AA312781270A312F0AB1270A312781238A37EA27EA27E7E1380EA01C0EA00E0137013 +38130C0E317AA418>40 D<12C012707E7E7E7E7E1380EA01C0A2EA00E0A21370A3137813 +38A3133CAB1338A313781370A313E0A2EA01C0A2EA038013005A120E5A5A5A12C00E317C +A418>I<13E01201120712FF12F91201B3A7487EB512C0A212217AA01E>49 +D E /Fh 23 123 df<1460A5EC7FF0EC3FF814FF903803CFE0903807800049C7FC131E5B +5B5BA2485A485AA2485A48C8FCA25A121E123E123CA3127C1278A412F8A4127CA2127E12 +7F6C7E13E0EA1FFC6CB47E6C13F000017F38003FFCEB07FE1300143F80A280141EA2EB60 +1CEB7838EB1FF0EB07C01D3C7DAD1F>16 D34 +D<123C127E12FFA4127E123C08087A8714>58 D<123C127EB4FCA21380A2127F123D1201 +A312031300A25A1206120E5A5A5A126009157A8714>I<15C0140114031580A214071500 +A25C140EA2141E141CA2143C143814781470A214F05CA213015CA213035C130791C7FCA2 +5B130EA2131E131CA2133C1338A21378137013F05BA212015BA212035BA2120790C8FC5A +120EA2121E121CA2123C1238A212781270A212F05AA21A437CB123>61 +D78 DI<013FB6FC17E0903A00FE0007F0EE01FC4AEB007EA201 +0181A25C1880010316005F5CA2010715FEA24A5C4C5A010F4A5A4C5A4AEB1F8004FFC7FC +91B512F84914C00280C9FCA3133F91CAFCA35B137EA313FE5BA312015BA21203B512E0A2 +312D7DAC2D>II<151FEC03FFA2EC003FA2153E +A2157EA2157CA215FCA215F8A21401EB07E190381FF9F0EB7C1DEBF80FEA01F03903E007 +E0EA07C0120FEA1F8015C0EA3F00140F5A007E1480A2141F12FE481400A2EC3F02150614 +3E5AEC7E0E007CEBFE0C14FC0101131C393E07BE18391F0E1E38390FFC0FF03903F003C0 +202F7DAD24>100 D<1307EB0F80EB1FC0A2EB0F80EB070090C7FCA9EA01E0EA07F8EA0E +3CEA1C3E123812301270EA607EEAE07C12C013FC485A120012015B12035BA21207EBC040 +14C0120F13801381381F01801303EB0700EA0F06131EEA07F8EA01F0122E7EAC18>105 +D<15E0EC01F01403A3EC01C091C7FCA9147CEB03FE9038078F80EB0E07131C013813C013 +30EB700F0160138013E013C0EB801F13001500A25CA2143EA2147EA2147CA214FCA25CA2 +1301A25CA21303A25CA2130700385BEAFC0F5C49C7FCEAF83EEAF0F8EA7FF0EA1F801C3B +81AC1D>I<131FEA03FFA2EA003FA2133EA2137EA2137CA213FCA25BA2120115F89038F0 +03FCEC0F0E0003EB1C1EEC387EEBE07014E03807E1C09038E3803849C7FC13CEEA0FDC13 +F8A2EBFF80381F9FE0EB83F0EB01F81300481404150C123EA2007E141C1518007CEBF038 +ECF83000FC1470EC78E048EB3FC00070EB0F801F2F7DAD25>I<137CEA0FFCA21200A213 +F8A21201A213F0A21203A213E0A21207A213C0A2120FA21380A2121FA21300A25AA2123E +A2127EA2127CA2EAFC08131812F8A21338133012F01370EAF860EA78E0EA3FC0EA0F000E +2F7DAD15>I<27078007F0137E3C1FE01FFC03FF803C18F0781F0783E03B3878E00F1E01 +263079C001B87F26707F8013B00060010013F001FE14E000E015C0485A4914800081021F +130300015F491400A200034A13076049133E170F0007027EEC8080188149017C131F1801 +000F02FCEB3F03053E130049495C180E001F0101EC1E0C183C010049EB0FF0000E6D48EB +03E0391F7E9D3E>I<3907C007E0391FE03FF83918F8783E393879E01E39307B801F3870 +7F00126013FEEAE0FC12C05B00815C0001143E5BA20003147E157C5B15FC0007ECF80816 +18EBC00115F0000F1538913803E0300180147016E0001F010113C015E390C7EAFF00000E +143E251F7E9D2B>II<38 +07C01F390FF07FC0391CF8E0E0383879C138307B8738707F07EA607E13FC00E0EB038048 +48C7FCA2128112015BA21203A25BA21207A25BA2120FA25BA2121FA290C8FC120E1B1F7E +9D20>114 DI117 +D<013F137C9038FFC1FF3A01C1E383803A0380F703C0390700F60F000E13FE4813FC1218 +0038EC0700003049C7FCA2EA200100005BA313035CA301075B5D14C000385CD87C0F1306 +00FC140E011F130C011B131C39F03BE038D8707113F0393FE0FFC0260F803FC7FC221F7E +9D28>120 DI<011E1330EB3F809038FFC07048EBE0E0ECF1C03803C0FF9038803F80903800070048 +130EC75A5C5C5C495A495A49C7FC131E13385B491340484813C0485A38070001000EEB03 +80380FE007391FF81F0038387FFF486C5A38601FFC38E00FF038C003C01C1F7D9D21>I +E /Fi 11 103 df<151E153E157C15F8EC01F0EC03E01407EC0FC0EC1F8015005C147E5C +A2495A495AA2495AA2495AA2495AA249C7FCA2137EA213FE5B12015BA212035BA21207A2 +5B120FA35B121FA45B123FA548C8FCA912FEB3A8127FA96C7EA5121F7FA4120F7FA31207 +7FA21203A27F1201A27F12007F137EA27FA26D7EA26D7EA26D7EA26D7EA26D7E6D7EA214 +7E80801580EC0FC0EC07E01403EC01F0EC00F8157C153E151E1F94718232>16 +D<12F07E127C7E7E6C7E7F6C7E6C7E12017F6C7E137EA27F6D7EA26D7EA26D7EA26D7EA2 +6D7EA26D7EA280147E147F80A21580141FA215C0A2140F15E0A3140715F0A4140315F8A5 +EC01FCA9EC00FEB3A8EC01FCA9EC03F8A515F01407A415E0140FA315C0141FA21580A214 +3F1500A25C147E14FE5CA2495AA2495AA2495AA2495AA2495AA249C7FC137EA25B485A5B +1203485A485A5B48C8FC123E5A5A5A1F947D8232>I32 +D<12F07E127C7E123F7E6C7E6C7E6C7E7F12016C7E7F137E133E133F6D7E130F806D7EA2 +6D7E80130180130080147E147F8081141F81140F81140781A2140381140181A2140081A2 +157FA36F7EA382151FA282150FA3821507A382A21503A282A31501A282A31500A382A482 +A21780A7163F17C0AC161F17E0B3B3A217C0163FAC1780167FA71700A25EA45EA31501A3 +5EA21503A35EA21507A25EA3150F5EA3151F5EA2153F5EA34BC7FCA315FEA25D1401A25D +14035D1407A25D140F5D141F5D143F92C8FC5C147E14FE5C13015C13035C495AA2495A5C +131F49C9FC133E137E5B5B485A12035B485A485A48CAFC5A123E5A5A5A2BF87E8242>I< +EE03C0160F163F167F923801FF004B5A4B5AED0FF04B5A4B5A4B5A4BC7FC5C5D4A5A1407 +5D4A5AA2141F5DA24A5AA44A5AB3B3B3B214FF92C8FCA35B5CA2495AA25C13075C130F49 +5A5C133F495A49C9FC485A485A485A485AEA1FC0485AB4CAFC12FCA2B4FCEA3F806C7EEA +0FF06C7E6C7E6C7E6C7E6D7E6D7E131F806D7E130780130380A26D7EA2807FA381147FB3 +B3B3B26E7EA46E7EA281140FA26E7E8114036E7E81806F7E6F7E6F7E6F7EED07FC6F7E6F +7E9238007FC0163F160F16032AF8748243>40 D<12F012FCB4FC7FEA3FE06C7E6C7EEA03 +FC6C7E6C7E6D7E6D7E80131F6D7E8013076D7EA2801301A26D7EA46E7EB3B3B3B281143F +A381141FA26E7EA21407811403816E7E1400816F7E6F7E6F7E6F7E6F7E6F7EED00FE167F +EE3FC0160FA2163FEE7F0016FEED03FC4B5A4B5A4B5A4B5A4B5A4BC7FC5D14014A5A5D14 +075D140FA24A5AA2143F5DA3147F5DB3B3B3B24AC8FCA4495AA213035CA2495A130F5C49 +5A133F5C495A49C9FC485A485AEA0FF8485A485AEAFF8090CAFC12FC12F02AF8748243> +I73 +D81 D88 D<17C0EE07F8EE3FFF4BB512E0030F14FC +923A7FFE1FFF80912703FFF00313F0021F90C7EA3FFEDAFFF0913803FFC0010301809138 +007FF0D91FF8C9EA07FED9FF809338007FC0D807FCCBEA0FF8D83FC0F000FF00FCCDEA0F +C000E01A01521080BF53>99 D<912607FF80178091B500F8EE03C0010702FFEE0F809026 +3FFC1F01E0ED7E0001FFC7D87FFCEC03F0D803F091260FFF80EB3FC0D81F8002019026FE +0FFFC7FC007CC9003FB512F800F0040714C000409326007FF8C8FC520A80BD53>102 +D E /Fj 35 123 df11 +D<1578913807FFE0021F13FC91383C7FFEEC7007EC6003ECE0004A13381600A280A380A2 +80147CA2147E143E143F816E7EA26E7E81140781EC3FFC14FF903803E1FEEB07C190381F +00FF133E49EB7F805B0001143F485A484814C049131F120F485AA248C7FC150F5A127EA3 +00FEEC1F805AA316005A5DA2153E157E157CA26C5C127C4A5A6C495AA26C495A6C6C485A +6C6C48C7FC3803E07C3800FFF0EB1FC027487CC62B>14 D<1530A7ED33FF033F13C0ED7C +0092B5FCDA03C31300DA0780C7FC4AC8FC141C14785C495A5C495A130749C9FC131E131C +133C5B5BA2485AA2485AA2485AA248CAFCA25A121EA2123E123CA3127C1278A412F8A67E +A2127C127EA2127F6C7E7F6C7E13F8EA0FFE3807FFC06C13F86C13FF6C6C13E0011F7F01 +0313FC9038007FFEEC1FFF14039138007F80153F151FA2150FA393C7FCA20102131E1307 +6D6C5A903801E0789038007FE0EC1F802A597CC42B>16 D<010FB712E0013F16F05B48B8 +12E04817C02807E0060030C7FCEB800EEA0F00001E010C13705A0038011C13605A006001 +1813E000E013381240C7FC5C4B5AA214F014E01301150314C01303A3EB078082130FA2EB +1F00A34980133E137EA24980A2000114015BA26C48EB00E0342C7EAA37>25 +D34 +D<121EEA7F80A2EAFFC0A4EA7F80A2EA1E000A0A78891B>58 D<121EEA7F8012FF13C0A2 +13E0A3127FEA1E601200A413E013C0A312011380120313005A1206120E5A5A5A12600B1D +78891B>II<127012FCB4FCEA7FC0EA1FF0EA07FCEA +01FF38007FC0EB1FF0EB07FE903801FF809038007FE0EC1FF8EC03FE913800FF80ED3FE0 +ED0FF8ED03FF030013C0EE3FF0EE0FFCEE01FF9338007FC0EF1FF0EF07FCEF01FF943800 +7FC0F01FE0A2F07FC0943801FF00EF07FCEF1FF0EF7FC04C48C7FCEE0FFCEE3FF0EEFFC0 +030390C8FCED0FF8ED3FE0EDFF80DA03FEC9FCEC1FF8EC7FE0903801FF80D907FECAFCEB +1FF0EB7FC04848CBFCEA07FCEA1FF0EA7FC048CCFC12FC12703B3878B44C>62 +D64 +D<4CB46C1318043F01F013384BB512FC0307D9007E1378DB1FF090380F80F0DB7F80EB03 +C1DA01FEC7EA01C34A48EC00E7DA0FF0ED7FE04A48153F4A5A02FFC9121F494817C04948 +160F495A130F4A178049481607495A137F4948170091CAFC5A485A1906485AA2485A96C7 +FC121F5BA2123F5BA3127F5BA4485AA419C0A2180161127F180396C7FC6018066C6C160E +601818001F17386D5E000F5F6D4B5A6C6C4B5A00034CC8FC6C6C150E6C6C153C017F5DD9 +3FC0EB01E0D91FF0EB0FC0D907FE017FC9FC0101B512FCD9003F13E0020790CAFC45487C +C546>67 D<91B600E049B512C0A3020001E0C8383FF800DB7F80ED1FE003FF94C7FC1A3E +93C9127862F101C04A4C5A4B4BC8FC191C6102035E4B5DF003804EC9FC0207150E4B1438 +6060020F4A5A4B0107CAFC170E5F021F14784B13F84C7E1603023F130F4B487E163BEEE1 +FF91387FC1C1DB83807FED8700159CDAFFB86D7E5D03C06D7E5D4990C7FC4A6E7EA2717E +13034A811707A201076F7E5C717EA2130F4A6E7FA2727E131F5C727E133F854A82D9FFE0 +4B7EB600E0010FB512E05FA252447CC353>75 D<91B612F8A3020001E0C8FC6F5A4B5AA2 +93C9FCA35C5DA314035DA314075DA3140F5DA3141F5DA3143F5DA3147F5DA314FF92CAFC +A35B4A16C0A21801010317804A15031900A201075E4A1506180E181E010F161C4A153C18 +381878011F16F84A4A5A1703013F150F4D5A4A14FF01FF02075BB9FCA2603A447CC342> +I<91B500C0933803FFFE63630200F1FE00DB6FE0EE1BF803EF171F1B3703CFEF67F0A21B +CF0201EF018F038F60DB87F0ED030F1B1F020317060307040C5BA2F2183F020717300206 +616F6C15601B7F020E17C0020CDC018090C7FCA24F485A021C16060218606F6C5C1A0102 +381618023004305BA2F16003027016C00260606F6CEB01801A0702E0ED03004A03065CA2 +4E130F01015E4A60047F5B1A1F01035E91C74A5CA24D48133F494BC7FC010661EE3F861A +7F010E158C010C039892C8FCA205B05C011C15E001186001386E5A190101785D01FC92C7 +5BD803FFEF07FEB500F8011E0107B512FE161C160C5F447BC35E>I<91B500C0020FB512 +8082A2DA007F9239007FE00070ED1F8074C7FCDBEFF8150E15CF03C7160C70151C1401DB +83FE1518A2DB81FF1538140303001630831A704A6D7E02061760163F7114E0140E020C6D +6C5CA2706C1301141C021801075D83190302386D7E023094C8FC1601715B147002606DEB +8006A294387FC00E14E04A023F130C18E0191C0101ED1FF04A1618170FF0F838130391C8 +3807FC30A2943803FE705B01060301136018FF19E0010E81010C5F187FA2131C0118705A +1338181F137801FC70C9FCEA03FFB512F884180651447CC34E>II<91B7 +12FEF0FFE019F802009039C0000FFE6F48EB01FF03FF9138007F80F13FC093C8EA1FE0A2 +4AEE0FF0A25D1AF81403A25DA21407F11FF05DA2020FEE3FE0A24B16C0197F021F1780F1 +FF004B4A5A4E5A023F4B5A4E5A4BEC3FC006FFC7FC027FEC07FC92B612F018800380CAFC +14FFA292CBFCA25BA25CA21303A25CA21307A25CA2130FA25CA2131FA25CA2133FA25CEB +FFE0B612E0A345447CC33F>II<91B712F018 +FF19E002009039C0003FF86F48EB07FC03FFEC01FEF0007F93C8EA3F801AC0F11FE05C5D +1AF0A214035DA30207EE3FE05DA2F17FC0020F17804B15FF1A004E5A021F4B5A4B4A5AF0 +0FE04E5A023F037FC7FC4BEB03FCEF1FF092B612804A4AC8FC923980007F80EF0FC0EF07 +F002FF6E7E92C77F1701845B4A1400A2170113035CA2170313075CA24D5A130F5CA3011F +18185CA2013F4C13381A304A6F1370D9FFE0020314E0B600E0ED01C00501EB0380943900 +FE0F00CBEA3FFEF007F045467CC34A>I97 D99 DI102 D<157E913803FF8091390FC1E0E091391F0073F002 +7E13334A133F4948131F010315E04948130F495AA2494814C0133F4A131F137F91C71380 +5B163F5A491500A25E120349147EA216FEA2495CA21501A25EA21503150700015D150F00 +00141F6D133F017CEB77E090383E01E790381F078F903807FE0FD901F85B90C7FC151FA2 +5EA2153FA293C7FCA2001C147E007F14FE485C4A5A140348495AEC0FC000F8495A007C01 +FEC8FC381FFFF8000313C02C407EAB2F>I<14FE137FA3EB01FC13001301A25CA21303A2 +5CA21307A25CA2130FA25CA2131FA25CED3FC090393F81FFF0913887C0FC91380E007E02 +3C133ED97F70133F4A7F4A14805C13FF91C7FC5BA24848143F17005BA200035D167E5BA2 +000715FE5E5B1501000F5DA24913035E001F1607030713064914E0150F003FEDC00E170C +90C7141CEE80184816381730007E167017E000FE91380781C0EEC38048913801FF000038 +EC007C30467BC438>I<141E143F5C5CA3147E143891C7FCAE133EEBFF803801C3C03807 +81E0380601F0120E121CEA180312381230A2EA700700605BA2EAE00F00C05BEA001F5CA2 +133F91C7FCA25B137E13FE5BA212015BEC03800003140013F01207495A1406140E140CEB +C01C141814385C00035BEBE1C0C6B45A013EC7FC19437DC121>I<163C16FEA21501A316 +FCED00701600AE15FCEC03FF91380F0780021C13C091383803E0147014E014C01301EC80 +07130314005B0106130F130E010C14C090C7FC151FA21680A2153FA21600A25DA2157EA2 +15FEA25DA21401A25DA21403A25DA21407A25DA2140FA25DA2141F5DA2143F001C91C7FC +127F48137E5CA248485AEB03E038F807C038781F80D83FFEC8FCEA07F0275681C128>I< +14FE137FA3EB01FC13001301A25CA21303A25CA21307A25CA2130FA25CA2131FA25C163F +013FECFFC0923803C0E09138000703ED1E0F491338ED701F017E13E0EC01C001FE018013 +C00203EB07004948C8FC140E00015B5C495A5C3803FBC001FFC9FC8014F83807F1FE9038 +F03F809038E00FE06E7E000F130381EBC001A2001FED01C017801380A2003F1503170001 +0013F05E481506160E007E150C161C00FE01005BED787048EC3FE00038EC0F802B467BC4 +33>II<01F8D903FCEC7F80D803FED91FFF90 +3803FFE0D8071F903B7C0FC00F81F83E0E0F80E007E01C00FC001C9026C3C0030178137C +271807C700D9F0E0137E02CE902601F1C0133E003801DCDAFB80133F003001D892C7FCD9 +0FF814FF0070495C0060495CA200E04949485CD8C01F187E4A5C1200040715FE013F6091 +C75BA2040F14014960017E5D1903041F5D13FE494B130762043F160E0001060F130C4992 +C713C0191F4CED801C00031A1849027E1638F2003004FE167000071A60494A16E0F201C0 +030192380F0380000FF18700494AEC03FED80380D90070EC00F84F2D7DAB55>I<01F8EB +03FCD803FEEB1FFFD8071F90387C0FC03B0E0F80E007E03A0C07C3C003001CD9C7007F00 +1801CE1301003801DC80003013D8EB0FF800705B00605BA200E0491303D8C01F5D5C1200 +1607013F5D91C7FCA2160F495D137E161F5F13FE49143F94C7FC187000014B136049147E +16FE4C13E0000317C049150104F81380170300071700495D170EEE781C000FED7C3849EC +1FF0D80380EC07C0342D7DAB3A>I<01F8EB0FC0D803FEEB7FF0D8070FEBF038000E9038 +83C07C3A0C07C701FC001C13CE0018EBDC03003813D8003013F8D90FF013F800709038E0 +00E0006015005C12E0EAC01F5C1200A2133F91C8FCA35B137EA313FE5BA312015BA31203 +5BA312075BA3120F5BEA0380262D7DAB2C>114 D<02FCEB07E0903A03FF801FFC903A0F +07C0781E903A1C03E0E01F903A3801F1C07FD9700013804901FB13FF4848EBFF00495B00 +0316FE90C71438484A130012061401000E5C120CC7FC14035DA314075DA3140F5DA3021F +143817305D1770023F1460121E003F16E0267F807FEB01C0026F148000FF01EF1303D901 +CFEB070000FE903887C00E267C03835B3A3C0F01E0783A1FFC00FFE0D803F0EB3F80302D +7EAB37>120 D<133ED9FF8014E02603C3C0EB03F0380703E0380601F0000E1507001C16 +E0EA180312380030150F007016C0EA60075C161FD8E00F158000C05BEA001F4A133F1700 +133F91C7FC5E49147E137EA216FE01FE5C5BA215015E485AA215035EA200001407150F6D +5C017C131F153F6D13FF90391F03CFC0903807FF8F903801FC0F90C7121F5EA2153F93C7 +FCD807C05BD81FE0137E5DA24848485A4A5A01805B39380007C00018495A001C49C8FC6C +137C380781F83803FFE0C66CC9FC2C407DAB30>I<027CEB018049B41303490180130001 +0F6D5A49EBE00E6F5A90393F03F838903978007EF80170EB1FF00160EB01E001E05C4949 +5A90C748C7FC150E5D5D5D5D4A5A4A5A4AC8FC140E5C5C5C5CEB03C049C9FC130E49141C +4914185B49143848481430491470D8039014F048B4495A3A0FEFC007C0391E03F01FD81C +01B55A486C91C7FC485C00606D5A00E0EB3FF048EB0FC0292D7CAB2D>I +E /Fk 71 124 df<9239FFC001FC020F9038F80FFF913B3F803E3F03C0913BFC00077E07 +E0D903F890390FFC0FF0494890383FF81F4948EB7FF0495A494814E049C7FCF00FE04991 +393FC0038049021F90C7FCAFB912F0A3C648C7D81FC0C7FCB3B2486CEC3FF0007FD9FC0F +B512E0A33C467EC539>11 D<4AB4FC020F13E091387F80F8903901FC001C49487FD907E0 +130F4948137F011FECFF80495A49C7FCA25B49EC7F00163E93C7FCACEE3F80B8FCA3C648 +C7FC167F163FB3B0486CEC7FC0007FD9FC1FB5FCA330467EC536>I14 D<001EEB03C0397F800FF000FF131F01C013F8A201E013FCA3007F130F +391E6003CC0000EB000CA401E0131C491318A3000114384913300003147090C712604814 +E0000614C0000E130148EB038048EB070048130E0060130C1E1D7DC431>34 +D<121EEA7F8012FF13C0A213E0A3127FEA1E601200A413E013C0A312011380120313005A +1206120E5A5A5A12600B1D78C41B>39 D<140C141C1438147014E0EB01C01303EB0780EB +0F00A2131E5BA25B13F85B12015B1203A2485AA3485AA348C7FCA35AA2123EA2127EA412 +7CA312FCB3A2127CA3127EA4123EA2123FA27EA36C7EA36C7EA36C7EA212017F12007F13 +787FA27F7FA2EB0780EB03C01301EB00E014701438141C140C166476CA26>I<12C07E12 +707E7E7E120F6C7E6C7EA26C7E6C7EA21378137C133C133E131E131FA2EB0F80A3EB07C0 +A3EB03E0A314F0A21301A214F8A41300A314FCB3A214F8A31301A414F0A21303A214E0A3 +EB07C0A3EB0F80A3EB1F00A2131E133E133C137C13785BA2485A485AA2485A48C7FC120E +5A5A5A5A5A16647BCA26>I<16C04B7EB3AB007FBAFCBB1280A26C1900C8D801E0C9FCB3 +AB6F5A41407BB84C>43 D<121EEA7F8012FF13C0A213E0A3127FEA1E601200A413E013C0 +A312011380120313005A1206120E5A5A5A12600B1D78891B>II< +121EEA7F80A2EAFFC0A4EA7F80A2EA1E000A0A78891B>I<14FF010713E090381F81F890 +383E007C01FC133F4848EB1F8049130F4848EB07C04848EB03E0A2000F15F0491301001F +15F8A2003F15FCA390C8FC4815FEA54815FFB3A46C15FEA56D1301003F15FCA3001F15F8 +A26C6CEB03F0A36C6CEB07E0000315C06D130F6C6CEB1F806C6CEB3F00013E137C90381F +81F8903807FFE0010090C7FC28447CC131>48 D<143014F013011303131F13FFB5FC13E7 +13071200B3B3B0497E497E007FB6FCA3204278C131>II<49B4FC010F13E0013F13FC9038FE01FE3A01F0007F80D803C0EB3FC0 +48C7EA1FE0120EED0FF0EA0FE0486C14F8A215077F5BA26C48130FEA03C0C813F0A3ED1F +E0A2ED3FC01680ED7F0015FE4A5AEC03F0EC1FC0D90FFFC7FC15F090380001FCEC007FED +3F80ED1FC0ED0FE016F0ED07F816FC150316FEA2150116FFA3121EEA7F80487EA416FE49 +1303A2007EC713FC00701407003015F80038140F6C15F06CEC1FE06C6CEB3FC0D803E0EB +7F803A01FE01FE0039007FFFF8010F13E0010190C7FC28447CC131>II<0006 +15C0D807C0130701FCEB7F8090B612005D5D5D15E0158026063FFCC7FC90C9FCAE14FF01 +0713C090381F01F090383800FC01F0137ED807C07F49EB1F8016C090C7120F000615E0C8 +EA07F0A316F81503A216FCA5123E127F487EA416F890C712075A006015F0A20070140F00 +3015E00038EC1FC07E001EEC3F806CEC7F006C6C13FE6C6C485A3901F807F039007FFFE0 +011F90C7FCEB07F826447BC131>II<121CA2EA1F80 +90B712C0A3481680A217005E0038C8120C0030151C00705D0060153016705E5E4814014B +5A4BC7FCC81206150E5D151815385D156015E04A5AA24A5A140792C8FC5CA25C141E143E +A2147E147CA214FCA21301A3495AA41307A6130FAA6D5AEB01C02A457BC231>I<14FF01 +0713E0011F13F890387F00FE01FC133FD801F0EB1F804848EB0FC049EB07E00007EC03F0 +48481301A290C713F8481400A47FA26D130116F07F6C6CEB03E013FC6C6CEB07C09039FF +800F806C9038C01F006CEBF03EECF87839007FFEF090383FFFC07F01077F6D13F8497F90 +381E7FFFD97C1F1380496C13C02601E00313E048486C13F000079038007FF84848EB3FFC +48C7120F003EEC07FE150148140016FF167F48153FA2161FA56C151E007C153EA2007E15 +3C003E157C6C15F86DEB01F06C6CEB03E06C6CEB07C0D803F8EB1F80C6B4EBFF0090383F +FFFC010F13F00101138028447CC131>I<14FF010713E0011F13F890387F80FC9038FC00 +7E48487F4848EB1F804848EB0FC0000FEC07E0485AED03F0485A16F8007F140190C713FC +A25AA216FE1500A516FFA46C5CA36C7E5D121F7F000F5C6C6C1306150E6C6C5B6C6C5BD8 +007C5B90383F01E090390FFF80FE903801FE0090C8FC150116FCA4ED03F8A216F0D80F80 +1307486C14E0486C130F16C0ED1F80A249EB3F0049137E001EC75A001C495A000F495A39 +07E01FE06CB51280C649C7FCEB1FF028447CC131>I<121EEA7F80A2EAFFC0A4EA7F80A2 +EA1E00C7FCB3A5121EEA7F80A2EAFFC0A4EA7F80A2EA1E000A2B78AA1B>I<007FBAFCBB +1280A26C1900CEFCB0007FBAFCBB1280A26C190041187BA44C>61 +D<16C04B7EA34B7EA34B7EA34B7EA3ED19FEA3ED30FFA203707FED607FA203E07FEDC03F +A2020180ED801FA2DA03007F160FA20206801607A24A6D7EA34A6D7EA34A6D7EA2027081 +0260147FA202E08191B7FCA249820280C7121FA249C87F170FA20106821707A2496F7EA3 +496F7EA3496F7EA201788313F8486C83D80FFF03037FB500E0027FEBFFC0A342477DC649 +>65 DI< +DB0FFE146092B500C013E0020314F0913A0FFC01FC0191393FC0003E02FFC7EA0F83D903 +FCEC03C74948EC01E74948EC00FF4948157F4948153F4948151F49C9120F485A49160712 +0348481603A248481601A248481600A2123FA2491760127FA31900485AAE6C7EA21960A2 +123F7FA2001F18E07F000F18C0A26C6C160119806C6C160312016DEE07006C6C16066D6C +150E6D6C5D6D6C5D6D6C15786D6C5D6D6C4A5AD900FFEC0780DA3FC0011FC7FCDA0FFC13 +FC0203B512F0020014C0DB0FFEC8FC3B487BC546>II< +B912F8A3000101C0C7127F6C6C48EC07FC17011700187C183C181CA284A31806A4180704 +067FA395C7FCA4160EA2161E163E16FE91B5FCA3EC8000163E161E160EA21606A319C0A3 +F0018093C7FCA41803A21900A260A260A2181EA2183E187EEF01FE170748486C147FB95A +A33A447CC342>II72 DI<010FB512FEA3D9000313806E130080B3B3AB123F487E487E +A44A5A13801300006C495A00705C6C13076C5C6C495A6CEB1F802603E07FC7FC3800FFFC +EB1FE027467BC332>IIIII80 D82 D<49B41303010FEBE007013F13F8 +9039FE00FE0FD801F8131FD807E0EB079F49EB03DF48486DB4FC48C8FC4881003E81127E +82127C00FC81A282A37E82A27EA26C6C91C7FC7F7FEA3FF813FE381FFFE06C13FE6CEBFF +E06C14FC6C14FF6C15C0013F14F0010F80010180D9001F7F14019138001FFF0303138081 +6F13C0167F163F161F17E000C0150FA31607A37EA36C16C0160F7E17806C151F6C16006C +5D6D147ED8FBC05CD8F9F0495AD8F07C495A90393FC00FE0D8E00FB51280010149C7FC39 +C0003FF02B487BC536>I<003FB912F8A3903BF0001FF8001F01806D481303003EC71500 +48187C0078183CA20070181CA30060180CA5481806A5C81600B3B3A54B7EED7FFE49B77E +A33F447DC346>I86 +DI91 +D<01C01318000114384848137048C712E0000EEB01C0000C1480001C1303001814000038 +5B003013060070130E0060130CA300E0131C481318A400CFEB19E039FFC01FF801E013FC +A3007F130FA2003F130701C013F8390F0001E01E1D71C431>II97 DII<167FED3FFFA315018182B3EC7F80 +903803FFF090380FC07C90383F000E017E1307496D5AD803F87F48487F5B000F81485AA2 +485AA2127FA290C8FC5AAB7E7FA2123FA26C7EA2000F5D7F6C6C5B00035C6C6C9038077F +806C6C010E13C0013F011C13FE90380FC0F8903803FFE09026007F0013002F467DC436> +IIIIII107 +DII<3901FC01FE00FF90 +3807FFC091381E07F091383801F8000701707F0003EBE0002601FDC07F5C01FF147F91C7 +FCA25BA35BB3A8486CECFF80B5D8F83F13FEA32F2C7DAB36>II<3901FC03FC00FF90380FFF8091383C07E091387001F83A07FDE000 +FE00010180137F01FFEC3F8091C7EA1FC04915E049140F17F0160717F8160317FCA3EE01 +FEABEE03FCA3EE07F8A217F0160F6D15E0EE1FC06D143F17806EEB7E00D9FDC05B9039FC +F003F891383C0FE091381FFF80DA03FCC7FC91C9FCAE487EB512F8A32F3F7DAB36>I<91 +387F8003903903FFE00790380FE07890393F801C0F90387E000E496D5AD803F8EB039F00 +07EC01BF4914FF48487F121F5B003F81A2485AA348C8FCAB6C7EA3123F7F121F6D5C120F +6D5B12076C6C5B6C6C497E6C6C130E013F131C90380FC0F8903803FFE09038007F0091C7 +FCAEEEFF80033F13FEA32F3F7DAB33>I<3903F803F000FFEB1FFCEC3C3EEC707F0007EB +E0FF3803F9C000015B13FBEC007E153C01FF13005BA45BB3A748B4FCB512FEA3202C7DAB +26>I<90383FE0183901FFFC383907E01F78390F0003F8001E1301481300007C14781278 +00F81438A21518A27EA27E6C6C13006C7E13FC383FFFE06C13FC6C13FF6C14C06C14E0C6 +14F0011F13F81300EC0FFC140300C0EB01FE1400157E7E153EA27EA36C143C6C147C1578 +6C14F86CEB01F039F38003E039F1F00F8039E07FFE0038C00FF01F2E7DAC26>I<1306A5 +130EA4131EA3133E137EA213FE12011207001FB512F0B6FCA2C648C7FCB3A4150CAA017E +131C017F1318A26D133890381F8030ECC070903807E0E0903801FFC09038007F001E3E7E +BC26>IIIIII<003FB612E0A2 +9038C0003F90C713C0003CEC7F800038ECFF00A20030495A0070495AA24A5A0060495AA2 +4A5A4A5AA2C7485A4AC7FC5B5C495A13075C495A131F4A1360495A495AA249C712C0485A +A2485A485A1501485A48481303A24848EB07804848131F00FF14FF90B6FCA2232B7DAA2B +>II E /Fl 18 119 df51 D56 +D58 +D77 +D80 D<003FBA12E0A59026FE000FEB8003D87FE0933800 +3FF049171F90C71607A2007E1803007C1801A300781800A400F819F8481978A5C81700B3 +B3A20107B8FCA545437CC24E>84 D<903801FFE0011F13FE017F6D7E48B612E03A03FE00 +7FF84848EB1FFC6D6D7E486C6D7EA26F7FA36F7F6C5A6C5AEA00F090C7FCA40203B5FC91 +B6FC1307013F13F19038FFFC01000313E0000F1380381FFE00485A5B127F5B12FF5BA35D +A26D5B6C6C5B4B13F0D83FFE013EEBFFC03A1FFF80FC7F0007EBFFF86CECE01FC66CEB80 +07D90FFCC9FC322F7DAD36>97 D101 DI104 D<137C48B4FC4813804813C0A24813E0A56C +13C0A26C13806C1300EA007C90C7FCAAEB7FC0EA7FFFA512037EB3AFB6FCA518467CC520 +>I<90277F8007FEEC0FFCB590263FFFC090387FFF8092B5D8F001B512E002816E488091 +3D87F01FFC0FE03FF8913D8FC00FFE1F801FFC0003D99F009026FF3E007F6C019E6D013C +130F02BC5D02F86D496D7EA24A5D4A5DA34A5DB3A7B60081B60003B512FEA5572D7CAC5E +>109 D<90397F8007FEB590383FFF8092B512E0028114F8913987F03FFC91388F801F00 +0390399F000FFE6C139E14BC02F86D7E5CA25CA35CB3A7B60083B512FEA5372D7CAC3E> +II<90397FC00FF8B590B57E +02C314E002CF14F89139DFC03FFC9139FF001FFE000301FCEB07FF6C496D13804A15C04A +6D13E05C7013F0A2EF7FF8A4EF3FFCACEF7FF8A318F017FFA24C13E06E15C06E5B6E4913 +806E4913006E495A9139DFC07FFC02CFB512F002C314C002C091C7FCED1FF092C9FCADB6 +7EA536407DAC3E>I<90387F807FB53881FFE0028313F0028F13F8ED8FFC91389F1FFE00 +0313BE6C13BC14F8A214F0ED0FFC9138E007F8ED01E092C7FCA35CB3A5B612E0A5272D7D +AC2E>114 D116 D118 +D E end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: a4 +%%BeginPaperSize: a4 +a4 +%%EndPaperSize + +%%EndSetup +%%Page: 1 1 +1 0 bop 257 573 a Fl(Theorem:)404 801 y Fk(Let)32 b Fj(M)44 +b Fk(b)s(e)33 b(a)f(torsion-free)f Fj(R)q Fk(-mo)s(dule,)g(and)i +Fj(d)27 b(>)h Fk(0.)43 b(Let)920 1021 y Fj(f)38 b Fk(=)1177 +938 y Fi(X)1110 1112 y Fh(n)1153 1121 y Fg(1)1187 1112 +y Fh(;:::;n)1330 1124 y Ff(d)1381 1021 y Fj(a)1432 1036 +y Fh(n)1475 1045 y Fg(1)1509 1036 y Fh(;:::;n)1652 1048 +y Ff(d)1707 1021 y Fj(x)1762 980 y Fh(n)1805 989 y Fg(1)1762 +1046 y Fe(1)1861 1021 y Fd(\001)17 b(\001)g(\001)e Fj(x)2049 +975 y Fh(n)2092 987 y Ff(d)2049 1046 y Fh(d)2160 1021 +y Fd(2)28 b Fj(M)10 b Fk([[)p Fj(x)2467 1036 y Fe(1)2508 +1021 y Fj(;)17 b(:)g(:)g(:)f(x)2738 1036 y Fh(d)2779 +1021 y Fk(]])257 1316 y(b)s(e)26 b(a)g(rational)d(function,)k(i.e.)41 +b(there)27 b(are)e Fj(P)42 b Fd(2)28 b Fj(M)10 b Fk([)p +Fj(x)2167 1331 y Fe(1)2207 1316 y Fj(;)17 b(:)g(:)g(:)f(;)h(x)2481 +1331 y Fh(d)2522 1316 y Fk(])26 b(and)g Fj(Q)i Fd(2)g +Fj(R)q Fk([)p Fj(x)3114 1331 y Fe(1)3154 1316 y Fj(;)17 +b(:)g(:)g(:)f(;)h(x)3428 1331 y Fh(d)3468 1316 y Fk(])257 +1437 y(with)33 b Fj(Q)p Fk(\(0)p Fj(;)17 b(:)g(:)g(:)e(;)i +Fk(0\))27 b(=)h(1)k(and)h Fj(Q)22 b Fd(\001)g Fj(f)39 +b Fk(=)27 b Fj(P)14 b Fk(.)43 b(Then)34 b(the)f(full)d(diagonal)h(of)h +Fj(f)1532 1714 y(g)f Fk(=)1744 1606 y Fc(1)1720 1631 +y Fi(X)1713 1813 y Fh(n)p Fe(=0)1863 1714 y Fj(a)1914 +1729 y Fh(n;:::)n(;n)2118 1714 y Fj(x)2173 1673 y Fh(n)2173 +1739 y Fe(1)257 2004 y Fk(is)h(a)h(D-\014nite)e(elemen)m(t)h(of)h +Fj(M)10 b Fk([[)p Fj(x)1478 2019 y Fe(1)1518 2004 y Fk(]],)33 +b(w.r.t.)44 b Fj(R)q Fk([)p Fj(x)2060 2019 y Fe(1)2100 +2004 y Fk(])33 b(and)g Fd(f)p Fj(@)2451 2019 y Fh(x)2491 +2028 y Fg(1)2529 2004 y Fd(g)p Fk(.)257 2232 y Fl(Pro)s(of:)404 +2460 y Fk(F)-8 b(rom)30 b(the)j(h)m(yp)s(otheses,)i Fj(M)10 +b Fk([[)p Fj(x)1564 2475 y Fe(1)1605 2460 y Fj(;)17 b(:)g(:)g(:)e(;)i +(x)1878 2475 y Fh(d)1919 2460 y Fk(]])32 b(is)g(a)g(torsion-free)f +(di\013eren)m(tial)g(mo)s(dule)257 2581 y(o)m(v)m(er)43 +b Fj(R)q Fk([)p Fj(x)632 2596 y Fe(1)672 2581 y Fj(;)17 +b(:)g(:)g(:)f(;)h(x)946 2596 y Fh(d)986 2581 y Fk(])42 +b(w.r.t.)71 b(the)42 b(deriv)-5 b(ativ)m(es)42 b Fd(f)p +Fj(@)2126 2596 y Fh(x)2166 2605 y Fg(1)2204 2581 y Fj(;)17 +b(:)g(:)g(:)f(;)h(@)2474 2596 y Fh(x)2514 2608 y Ff(d)2554 +2581 y Fd(g)p Fk(,)44 b(and)e Fj(f)52 b Fk(is)41 b(a)g(D-\014nite)257 +2701 y(elemen)m(t)26 b(of)f Fj(M)10 b Fk([[)p Fj(x)928 +2716 y Fe(1)969 2701 y Fj(;)17 b(:)g(:)g(:)e(;)i(x)1242 +2716 y Fh(d)1283 2701 y Fk(]])26 b(o)m(v)m(er)g Fj(R)q +Fk([)p Fj(x)1721 2716 y Fe(1)1761 2701 y Fj(;)17 b(:)g(:)g(:)f(;)h(x) +2035 2716 y Fh(d)2076 2701 y Fk(])25 b(w.r.t.)42 b Fd(f)p +Fj(@)2498 2716 y Fh(x)2538 2725 y Fg(1)2576 2701 y Fj(;)17 +b(:)g(:)g(:)f(;)h(@)2846 2716 y Fh(x)2886 2728 y Ff(d)2927 +2701 y Fd(g)p Fk(.)40 b(No)m(w)26 b(apply)257 2821 y(the)33 +b(general)f(diagonal)f(theorem)h(\([1],)g(section)h(2.18\))f +Fj(d)22 b Fd(\000)g Fk(1)33 b(times.)257 3050 y Fl(Theorem:)404 +3278 y Fk(Let)g Fj(R)i Fk(b)s(e)e(an)g(in)m(tegral)f(domain)g(of)h(c)m +(haracteristic)g(0)g(and)g Fj(M)44 b Fk(sim)m(ultaneously)32 +b(a)257 3398 y(torsion-free)38 b Fj(R)q Fk(-mo)s(dule)g(and)h(a)f(comm) +m(utativ)m(e)g Fj(R)q Fk(-algebra)g(without)g(zero)i(divisors.)257 +3519 y(Let)1223 3639 y Fj(f)e Fk(=)1460 3556 y Fi(X)1413 +3739 y Fh(m;n)p Fc(\025)p Fe(0)1644 3639 y Fj(a)1695 +3654 y Fh(m;n)1825 3639 y Fj(x)1880 3598 y Fh(m)1947 +3639 y Fj(y)1999 3598 y Fh(n)2072 3639 y Fd(2)28 b Fj(M)10 +b Fk([[)p Fj(x;)17 b(y)t Fk(]])257 3891 y(b)s(e)33 b(a)f(rational)f +(function.)43 b(Then)33 b(the)g(diagonal)d(of)j Fj(f)1571 +4164 y(g)e Fk(=)1784 4056 y Fc(1)1759 4081 y Fi(X)1752 +4262 y Fh(n)p Fe(=0)1902 4164 y Fj(a)1953 4179 y Fh(n;n)2079 +4164 y Fj(x)2134 4122 y Fh(n)257 4453 y Fk(is)h(algebraic)f(o)m(v)m(er) +j Fj(R)q Fk([)p Fj(x)p Fk(].)257 4681 y Fl(Motiv)-6 b(ation)36 +b(of)i(pro)s(of:)404 4909 y Fk(The)30 b(usual)g(pro)s(of)f(\([2]\))g +(uses)j(complex)d(analysis)g(and)h(w)m(orks)h(only)e(for)h +Fj(R)e Fk(=)g Fj(M)38 b Fk(=)257 5030 y Fj(C)7 b Fk(.)44 +b(The)33 b(idea)f(is)g(to)h(compute)1256 5294 y Fj(g)t +Fk(\()p Fj(x)1400 5252 y Fe(2)1439 5294 y Fk(\))28 b(=)1664 +5226 y(1)p 1618 5270 141 4 v 1618 5362 a(2)p Fj(\031)t(i)1786 +5176 y Fi(I)1832 5365 y Fc(j)p Fh(z)s Fc(j)p Fe(=1)2018 +5294 y Fj(f)11 b Fk(\()p Fj(xz)t(;)2273 5226 y(x)p 2273 +5270 56 4 v 2276 5362 a(z)2338 5294 y Fk(\))2386 5226 +y Fj(dz)p 2386 5270 101 4 v 2412 5362 a(z)1852 5637 y +Fk(1)p eop +%%Page: 2 2 +2 1 bop 257 573 a Fk(This)30 b(in)m(tegral,)e(whose)i(in)m(tegrand)f +(is)g(a)g(rational)e(function)h(in)h Fj(x)g Fk(and)h +Fj(z)t Fk(,)g(is)f(calculated)257 693 y(using)41 b(the)g(residue)g +(theorem.)68 b(Since)41 b Fj(f)11 b Fk(\()p Fj(x;)17 +b(y)t Fk(\))39 b(is)h(con)m(tin)m(uous)i(at)e(\(0)p Fj(;)17 +b Fk(0\),)42 b(there)f(is)f(a)257 814 y Fj(\016)32 b(>)c +Fk(0)k(suc)m(h)i(that)e Fj(f)11 b Fk(\()p Fj(x;)17 b(y)t +Fk(\))26 b Fd(6)p Fk(=)i Fd(1)k Fk(for)g Fd(j)p Fj(x)p +Fd(j)27 b Fj(<)h(\016)t Fk(,)k Fd(j)p Fj(y)t Fd(j)26 +b Fj(<)i(\016)t Fk(.)43 b(It)33 b(follo)m(ws)e(that)h(for)g(all)f +Fj(")c(>)g Fk(0)257 934 y(and)g Fd(j)p Fj(x)p Fd(j)g +Fj(<)h(\016)t(")d Fk(all)g(the)h(p)s(oles)g(of)g Fj(f)11 +b Fk(\()p Fj(xz)t(;)1693 895 y Fh(x)p 1693 911 40 4 v +1695 968 a(z)1743 934 y Fk(\))26 b(are)g(con)m(tained)h(in)e +Fd(f)p Fj(z)32 b Fk(:)c Fd(j)p Fj(z)t Fd(j)g Fj(<)f(")p +Fd(g)9 b([)g(f)p Fj(z)33 b Fk(:)28 b Fd(j)p Fj(z)t Fd(j)f +Fj(>)267 1015 y Fe(1)p 267 1031 36 4 v 268 1089 a Fh(")313 +1054 y Fd(g)p Fk(.)49 b(Th)m(us)37 b(the)e(p)s(oles)f(of)h +Fj(f)11 b Fk(\()p Fj(xz)t(;)1477 1015 y Fh(x)p 1477 1031 +40 4 v 1479 1089 a(z)1527 1054 y Fk(\),)35 b(all)e(algebraic)g +(functions)i(of)f Fj(x)h Fk({)g(let's)f(call)f(them)257 +1175 y Fj(\020)300 1190 y Fe(1)339 1175 y Fk(\()p Fj(x)p +Fk(\))p Fj(;)17 b(:)g(:)g(:)g(\020)689 1190 y Fh(s)725 +1175 y Fk(\()p Fj(x)p Fk(\))36 b({,)g(can)h(b)s(e)f(divided)f(up)h(in)m +(to)f(those)i(for)e(whic)m(h)h Fd(j)p Fj(\020)2779 1190 +y Fh(i)2807 1175 y Fk(\()p Fj(x)p Fk(\))p Fd(j)d Fk(=)g +Fj(O)s Fk(\()p Fd(j)p Fj(x)p Fd(j)p Fk(\))i(as)257 1295 +y Fj(x)43 b Fd(!)e Fk(0)g(and)g(those)g(for)g(whic)m(h)1580 +1256 y Fe(1)p 1502 1272 192 4 v 1502 1329 a Fc(j)p Fh(\020)1553 +1339 y Ff(i)1579 1329 y Fe(\()p Fh(x)p Fe(\))p Fc(j)1745 +1295 y Fk(=)h Fj(O)s Fk(\()p Fd(j)p Fj(x)p Fd(j)p Fk(\))d(as)j +Fj(x)g Fd(!)f Fk(0.)69 b(It)40 b(follo)m(ws)g(from)g(the)257 +1429 y(residue)33 b(theorem)g(that)f(for)g Fd(j)p Fj(x)p +Fd(j)c Fj(<)f(\016)1193 1672 y(g)t Fk(\()p Fj(x)1337 +1631 y Fe(2)1376 1672 y Fk(\))g(=)1711 1589 y Fi(X)1545 +1777 y Fh(\020)5 b Fe(=0)p Fc(_)p Fh(\020)g Fe(=)p Fh(O)r +Fe(\()p Fc(j)p Fh(x)p Fc(j)p Fe(\))2014 1672 y Fk(Res)2028 +1732 y Fh(z)s Fe(=)p Fh(\020)2201 1672 y Fj(f)11 b Fk(\()p +Fj(xz)t(;)2457 1605 y(x)p 2457 1649 56 4 v 2460 1741 +a(z)2522 1672 y Fk(\))257 1996 y(This)32 b(is)e(algebraic)g(o)m(v)m(er) +i Fj(C)7 b Fk(\()p Fj(x)p Fk(\).)43 b(Hence)32 b Fj(g)t +Fk(\()p Fj(x)p Fk(\))f(is)f(algebraic)g(o)m(v)m(er)i +Fj(C)7 b Fk(\()p Fj(x)2856 1960 y Fe(1)p Fh(=)p Fe(2)2966 +1996 y Fk(\),)32 b(hence)g(also)257 2117 y(algebraic)f(o)m(v)m(er)j +Fj(C)7 b Fk(\()p Fj(x)p Fk(\).)257 2345 y Fl(Pro)s(of:)404 +2573 y Fk(Let)647 2826 y Fj(h)p Fk(\()p Fj(x;)17 b(z)t +Fk(\))29 b(:=)e Fj(f)11 b Fk(\()p Fj(xz)t(;)1342 2759 +y(x)p 1342 2803 V 1345 2894 a(z)1407 2826 y Fk(\))28 +b(=)1649 2718 y Fc(1)1624 2743 y Fi(X)1576 2924 y Fh(m;n)p +Fe(=0)1808 2826 y Fj(a)1859 2841 y Fh(m;n)1988 2826 y +Fj(x)2043 2785 y Fh(m)p Fe(+)p Fh(n)2208 2826 y Fj(z)2257 +2785 y Fh(m)p Fc(\000)p Fh(n)2450 2826 y Fd(2)g Fj(M)10 +b Fk([[)p Fj(xz)t(;)17 b(xz)2954 2785 y Fc(\000)p Fe(1)3051 +2826 y Fk(]])257 3136 y(Then)48 b Fj(g)t Fk(\()p Fj(x)670 +3099 y Fe(2)709 3136 y Fk(\))e(is)g(the)h(co)s(e\016cien)m(t)g(of)f +Fj(z)1730 3099 y Fe(0)1816 3136 y Fk(in)g Fj(h)p Fk(\()p +Fj(x;)17 b(z)t Fk(\).)85 b(Let)47 b Fj(N)10 b Fk(\()p +Fj(x;)17 b(z)t Fk(\))52 b(:=)f Fj(z)3092 3099 y Fh(d)3134 +3136 y Fj(Q)p Fk(\()p Fj(xz)t(;)3408 3096 y Fh(x)p 3408 +3112 40 4 v 3410 3170 a(z)3457 3136 y Fk(\))257 3256 +y(\(with)36 b Fj(d)e Fk(:=)h(max)o(\(deg)1111 3279 y +Fh(y)1169 3256 y Fj(P)s(;)17 b Fk(deg)1426 3279 y Fh(y)1484 +3256 y Fj(Q)p Fk(\)\))37 b(b)s(e)f(\\the)h(denominator")e(of)h +Fj(h)p Fk(\()p Fj(x;)17 b(z)t Fk(\).)56 b(W)-8 b(e)37 +b(ha)m(v)m(e)257 3376 y Fj(N)10 b Fk(\()p Fj(x;)17 b(z)t +Fk(\))31 b Fd(2)e Fj(R)q Fk([)p Fj(x;)17 b(z)t Fk(])34 +b(and)g Fj(N)39 b Fd(6)p Fk(=)29 b(0)k(\(b)s(ecause)i +Fj(N)10 b Fk(\(0)p Fj(;)17 b(z)t Fk(\))29 b(=)g Fj(z)2390 +3340 y Fh(d)2431 3376 y Fk(\).)46 b(Let)33 b Fj(K)41 +b Fk(b)s(e)33 b(the)h(quotien)m(t)257 3497 y(\014eld)f(of)f +Fj(R)q Fk(.)43 b(Th)m(us)34 b Fj(N)10 b Fk(\()p Fj(x;)17 +b(z)t Fk(\))29 b Fd(2)g Fj(K)7 b Fk([)p Fj(x)p Fk(][)p +Fj(z)t Fk(])23 b Fd(n)f(f)p Fk(0)p Fd(g)p Fk(.)404 3617 +y(It)34 b(is)g(w)m(ell-kno)m(wn)g(\(see)h([3],)g(p.64,)f(or)g([4],)h(c) +m(hap.)49 b(IV,)34 b Fd(x)p Fk(2,)h(prop.)48 b(8,)35 +b(or)f([5],)g(c)m(hap.)257 3737 y(I)s(I)s(I,)k Fd(x)p +Fk(1\))g(that)g(the)h(splitting)c(\014eld)j(of)g Fj(N)10 +b Fk(\()p Fj(x;)17 b(z)t Fk(\))39 b(o)m(v)m(er)g Fj(K)7 +b Fk(\()p Fj(x)p Fk(\))38 b(can)h(b)s(e)f(em)m(b)s(edded)h(in)m(to)257 +3858 y(a)46 b(\014eld)h Fj(L)p Fk(\(\()p Fj(x)775 3822 +y Fe(1)p Fh(=r)884 3858 y Fk(\)\),)j(where)d Fj(r)i Fk(is)d(a)g(p)s +(ositiv)m(e)g(in)m(teger)g(and)h Fj(L)g Fk(is)e(a)i(\014nite-algebraic) +257 3978 y(extension)39 b(\014eld)e(of)g Fj(K)7 b Fk(,)38 +b(i.e.)58 b(a)37 b(simple)f(algebraic)f(extension)k Fj(L)d +Fk(=)f Fj(K)7 b Fk(\()p Fj(\013)q Fk(\))36 b(=)g Fj(K)7 +b(\013)3355 3942 y Fe(0)3419 3978 y Fk(+)257 4099 y Fd(\001)17 +b(\001)g(\001)k Fk(+)h Fj(K)7 b(\013)647 4062 y Fh(u)p +Fc(\000)p Fe(1)782 4099 y Fk(.)423 4187 y Fi(f)404 4219 +y Fj(M)38 b Fk(:=)28 b(\()p Fj(R)22 b Fd(n)f(f)p Fk(0)p +Fd(g)p Fk(\))1059 4183 y Fc(\000)p Fe(1)1173 4219 y Fd(\001)g +Fj(M)43 b Fk(is)31 b(a)h Fj(K)7 b Fk(-v)m(ector)33 b(space)g(and)f(a)g +(comm)m(utativ)m(e)f Fj(K)7 b Fk(-algebra)257 4339 y(without)32 +b(zero)g(divisors.)1238 4307 y Fi(c)1219 4339 y Fj(M)38 +b Fk(:=)1501 4307 y Fi(f)1482 4339 y Fj(M)11 b(\013)1650 +4303 y Fe(0)1710 4339 y Fk(+)20 b Fd(\001)d(\001)g(\001)i +Fk(+)2059 4307 y Fi(f)2040 4339 y Fj(M)11 b(\013)2208 +4303 y Fh(u)p Fc(\000)p Fe(1)2374 4339 y Fk(is)32 b(an)g +Fj(L)p Fk(-v)m(ector)g(space)h(and)f(a)257 4460 y(comm)m(utativ)m(e)g +Fj(L)p Fk(-algebra)f(without)h(zero)h(divisors.)585 4768 +y Fi(c)566 4800 y Fj(M)11 b Fd(h)-17 b(h)p Fj(x;)17 b(z)t +Fd(i)-17 b(i)83 b Fk(:=)1229 4768 y Fi(c)1210 4800 y +Fj(M)11 b Fk([[)p Fj(x)1424 4759 y Fe(1)p Fh(=r)1556 +4800 y Fd(\001)21 b Fj(z)t(;)c(x)1753 4759 y Fe(1)p Fh(=r)1885 +4800 y Fd(\001)22 b Fj(z)1984 4759 y Fc(\000)p Fe(1)2079 +4800 y Fj(;)17 b(x)2178 4759 y Fe(1)p Fh(=r)2286 4800 +y Fk(]][)p Fj(x)2422 4759 y Fc(\000)p Fe(1)p Fh(=r)2587 +4800 y Fk(])1038 5008 y(=)1210 4862 y Fi(\()1280 4925 +y(X)1277 5099 y Fh(m;n)1419 5008 y Fj(c)1461 5023 y Fh(m;n)1590 +5008 y Fj(x)1645 4967 y Fh(m=r)1781 5008 y Fj(z)1830 +4967 y Fh(n)1905 5008 y Fk(:)28 b Fj(c)2002 5023 y Fh(m;n)2159 +5008 y Fd(6)p Fk(=)f(0)h Fd(\))f(j)p Fj(n)p Fd(j)g(\024)h +Fj(m)23 b Fk(+)f Fj(O)s Fk(\(1\))3121 4862 y Fi(\))257 +5323 y Fk(is)32 b(an)h Fj(L)p Fk(-algebra)e(whic)m(h)i(con)m(tains)1612 +5290 y Fi(c)1593 5323 y Fj(M)11 b Fk(\(\()p Fj(x)1829 +5287 y Fe(1)p Fh(=r)1938 5323 y Fk(\)\).)1852 5637 y(2)p +eop +%%Page: 3 3 +3 2 bop 404 573 a Fk(Since)24 b Fj(N)10 b Fk(\()p Fj(x;)17 +b(z)t Fk(\))25 b(splits)d(in)m(to)h(linear)g(factors)g(in)g +Fj(L)p Fk(\(\()p Fj(x)2295 537 y Fe(1)p Fh(=r)2404 573 +y Fk(\)\)[)p Fj(z)t Fk(],)k Fj(N)10 b Fk(\()p Fj(x;)17 +b(z)t Fk(\))29 b(=)e Fj(l)3129 506 y Fi(Q)3208 533 y +Fh(s)3208 597 y(i)p Fe(=1)3326 573 y Fk(\()p Fj(z)9 b +Fd(\000)257 712 y Fj(\020)300 727 y Fh(i)328 712 y Fk(\()p +Fj(x)p Fk(\)\))497 676 y Fh(k)534 686 y Ff(i)565 712 +y Fk(,)37 b(there)f(exists)h(a)f(partial)e(fraction)h(decomp)s(osition) +f(of)i Fj(h)p Fk(\()p Fj(x;)17 b(z)t Fk(\))34 b(=)3116 +656 y Fh(P)10 b Fe(\()p Fh(xz)s(;)3304 629 y Ff(x)p 3303 +641 35 4 v 3305 682 a(z)3348 656 y Fe(\))p 3116 689 261 +4 v 3116 746 a Fh(Q)p Fe(\()p Fh(xz)s(;)3305 719 y Ff(x)p +3304 731 35 4 v 3306 772 a(z)3348 746 y Fe(\))3419 712 +y Fk(=)267 839 y Fh(z)303 815 y Ff(d)339 839 y Fh(P)g +Fe(\()p Fh(xz)s(;)527 811 y Ff(x)p 526 823 V 528 865 +a(z)571 839 y Fe(\))p 267 871 331 4 v 326 929 a Fh(N)d +Fe(\()p Fh(x;z)s Fe(\))641 894 y Fk(in)773 862 y Fi(c)754 +894 y Fj(M)k Fd(h)-17 b(h)p Fj(x;)17 b(z)t Fd(i)-17 b(i)p +Fk(:)985 1208 y Fj(h)p Fk(\()p Fj(x;)17 b(z)t Fk(\))29 +b(=)1448 1100 y Fh(l)1399 1125 y Fi(X)1397 1308 y Fh(j)t +Fe(=0)1536 1208 y Fj(P)1599 1223 y Fh(j)1636 1208 y Fk(\()p +Fj(x)p Fk(\))p Fj(z)1816 1167 y Fh(j)1876 1208 y Fk(+)2017 +1100 y Fh(s)1974 1125 y Fi(X)1976 1308 y Fh(i)p Fe(=1)2143 +1098 y Fh(k)2180 1108 y Ff(i)2114 1125 y Fi(X)2110 1310 +y Fh(k)r Fe(=1)2371 1141 y Fj(P)2434 1156 y Fh(i;k)2520 +1141 y Fk(\()p Fj(x)p Fk(\))p 2265 1185 493 4 v 2265 +1277 a(\()p Fj(z)e Fd(\000)c Fj(\020)2518 1292 y Fh(i)2546 +1277 y Fk(\()p Fj(x)p Fk(\)\))2715 1248 y Fh(k)257 1521 +y Fk(with)33 b Fj(P)543 1536 y Fh(j)579 1521 y Fk(\()p +Fj(x)p Fk(\))p Fj(;)17 b(P)817 1536 y Fh(i;k)903 1521 +y Fk(\()p Fj(x)p Fk(\))28 b Fd(2)1175 1489 y Fi(c)1156 +1521 y Fj(M)11 b Fk(\(\()p Fj(x)1392 1485 y Fe(1)p Fh(=r)1501 +1521 y Fk(\)\).)404 1641 y(Recall)26 b(that)h(w)m(e)h(are)g(lo)s(oking) +d(for)i(the)h(co)s(e\016cien)m(t)g(of)f Fj(z)2443 1605 +y Fe(0)2511 1641 y Fk(in)g Fj(h)p Fk(\()p Fj(x;)17 b(z)t +Fk(\).)42 b(W)-8 b(e)28 b(compute)257 1762 y(it)k(separately)h(for)f +(eac)m(h)h(summand.)404 1882 y(If)f Fj(\020)544 1897 +y Fh(i)572 1882 y Fk(\()p Fj(x)p Fk(\))c(=)g Fj(ax)941 +1846 y Fh(m=r)1099 1882 y Fk(+)22 b Fj(:::)33 b Fk(with)f +Fj(a)c Fd(2)g Fj(L)22 b Fd(n)g(f)p Fk(0)p Fd(g)p Fk(,)32 +b Fj(m)c(>)g Fk(0,)k(or)h Fj(\020)2562 1897 y Fh(i)2589 +1882 y Fk(\()p Fj(x)p Fk(\))28 b(=)g(0,)k(w)m(e)i(ha)m(v)m(e)1097 +2165 y(1)p 875 2209 V 875 2300 a(\()p Fj(z)27 b Fd(\000)22 +b Fj(\020)1127 2315 y Fh(i)1155 2300 y Fk(\()p Fj(x)p +Fk(\)\))1324 2272 y Fh(k)1460 2232 y Fk(=)1651 2165 y(1)p +1629 2209 93 4 v 1629 2300 a Fj(z)1678 2272 y Fh(k)1753 +2232 y Fd(\001)2031 2165 y Fk(1)p 1813 2209 485 4 v 1813 +2242 a Fi(\020)1863 2338 y Fk(1)g Fd(\000)2043 2292 y +Fh(\020)2074 2302 y Ff(i)2101 2292 y Fe(\()p Fh(x)p Fe(\))p +2043 2315 152 4 v 2101 2373 a Fh(z)2205 2242 y Fi(\021)2255 +2265 y Fh(k)1460 2588 y Fk(=)1651 2521 y(1)p 1629 2565 +93 4 v 1629 2657 a Fj(z)1678 2628 y Fh(k)1753 2588 y +Fd(\001)1829 2480 y Fc(1)1804 2505 y Fi(X)1803 2688 y +Fh(j)t Fe(=0)1942 2442 y Fi( )2008 2521 y Fj(k)j Fd(\000)e +Fk(1)f(+)g Fj(j)2091 2657 y(k)j Fd(\000)e Fk(1)2399 2442 +y Fi(!)16 b( )2557 2521 y Fj(\020)2600 2536 y Fh(i)2628 +2521 y Fk(\()p Fj(x)p Fk(\))p 2557 2565 203 4 v 2633 +2657 a Fj(z)2769 2442 y Fi(!)2835 2465 y Fh(j)1460 2891 +y Fk(=)1645 2783 y Fc(1)1620 2808 y Fi(X)1619 2991 y +Fh(j)t Fe(=0)1758 2745 y Fi( )1824 2824 y Fj(k)25 b Fd(\000)e +Fk(1)f(+)g Fj(j)1907 2960 y(k)j Fd(\000)e Fk(1)2214 2745 +y Fi(!)2290 2824 y Fj(\020)2333 2839 y Fh(i)2361 2824 +y Fk(\()p Fj(x)p Fk(\))2492 2788 y Fh(j)p 2290 2868 239 +4 v 2320 2960 a Fj(z)2369 2931 y Fh(k)r Fe(+)p Fh(j)257 +3211 y Fk(hence)34 b(the)f(co)s(e\016cien)m(t)h(of)e +Fj(z)1312 3175 y Fe(0)1384 3211 y Fk(in)1567 3159 y Fh(P)1612 +3171 y Ff(i;k)1691 3159 y Fe(\()p Fh(x)p Fe(\))p 1508 +3187 336 4 v 1508 3245 a(\()p Fh(z)s Fc(\000)p Fh(\020)1657 +3255 y Ff(i)1683 3245 y Fe(\()p Fh(x)p Fe(\)\))1804 3226 +y Ff(k)1886 3211 y Fk(is)g(0.)404 3356 y(If)g Fj(\020)544 +3371 y Fh(i)572 3356 y Fk(\()p Fj(x)p Fk(\))c(=)g Fj(ax)941 +3320 y Fh(m=r)1099 3356 y Fk(+)22 b Fj(:::)33 b Fk(with)f +Fj(a)c Fd(2)g Fj(L)22 b Fd(n)g(f)p Fk(0)p Fd(g)p Fk(,)32 +b Fj(m)c(<)g Fk(0,)k(w)m(e)i(ha)m(v)m(e)489 3578 y(1)p +267 3622 493 4 v 267 3714 a(\()p Fj(z)27 b Fd(\000)c +Fj(\020)520 3729 y Fh(i)548 3714 y Fk(\()p Fj(x)p Fk(\)\))717 +3685 y Fh(k)797 3646 y Fk(=)1085 3578 y(1)p 911 3622 +399 4 v 911 3714 a(\()p Fd(\000)p Fj(\020)1069 3729 y +Fh(i)1097 3714 y Fk(\()p Fj(x)p Fk(\)\))1266 3685 y Fh(k)1319 +3646 y Fd(\001)1574 3578 y Fk(1)p 1357 3622 485 4 v 1357 +3656 a Fi(\020)1406 3752 y Fk(1)f Fd(\000)1645 3713 y +Fh(z)p 1586 3729 152 4 v 1586 3786 a(\020)1617 3796 y +Ff(i)1644 3786 y Fe(\()p Fh(x)p Fe(\))1748 3656 y Fi(\021)1798 +3678 y Fh(k)1878 3646 y Fk(=)2166 3578 y(1)p 1992 3622 +399 4 v 1992 3714 a(\()p Fd(\000)p Fj(\020)2150 3729 +y Fh(i)2178 3714 y Fk(\()p Fj(x)p Fk(\)\))2347 3685 y +Fh(k)2400 3646 y Fd(\001)2453 3538 y Fc(1)2429 3563 y +Fi(X)2428 3745 y Fh(j)t Fe(=0)2567 3500 y Fi( )2632 3578 +y Fj(k)k Fd(\000)c Fk(1)g(+)g Fj(j)2715 3714 y(k)k Fd(\000)c +Fk(1)3023 3500 y Fi(!)16 b( )3257 3578 y Fj(z)p 3181 +3622 203 4 v 3181 3714 a(\020)3224 3729 y Fh(i)3252 3714 +y Fk(\()p Fj(x)p Fk(\))3393 3500 y Fi(!)3459 3522 y Fh(j)257 +4002 y Fk(hence)34 b(the)f(co)s(e\016cien)m(t)h(of)e +Fj(z)1312 3965 y Fe(0)1384 4002 y Fk(in)1567 3950 y Fh(P)1612 +3962 y Ff(i;k)1691 3950 y Fe(\()p Fh(x)p Fe(\))p 1508 +3978 336 4 v 1508 4036 a(\()p Fh(z)s Fc(\000)p Fh(\020)1657 +4046 y Ff(i)1683 4036 y Fe(\()p Fh(x)p Fe(\)\))1804 4017 +y Ff(k)1886 4002 y Fk(is)2035 3950 y Fh(P)2080 3962 y +Ff(i;k)2159 3950 y Fe(\()p Fh(x)p Fe(\))p 1994 3978 300 +4 v 1994 4036 a(\()p Fc(\000)p Fh(\020)2107 4046 y Ff(i)2134 +4036 y Fe(\()p Fh(x)p Fe(\)\))2255 4017 y Ff(k)2304 4002 +y Fk(.)404 4147 y(The)43 b(case)h Fj(\020)874 4162 y +Fh(i)902 4147 y Fk(\()p Fj(x)p Fk(\))h(=)g Fj(ax)1305 +4111 y Fh(m=r)1471 4147 y Fk(+)29 b Fj(:::)43 b Fk(with)f +Fj(a)k Fd(2)f Fj(L)30 b Fd(n)e(f)p Fk(0)p Fd(g)p Fk(,)45 +b Fj(m)h Fk(=)f(0,)g(cannot)e(o)s(ccur,)257 4267 y(b)s(ecause)34 +b(it)e(w)m(ould)g(imply)f(0)d(=)f Fj(N)10 b Fk(\(0)p +Fj(;)17 b(\020)1716 4282 y Fh(i)1744 4267 y Fk(\(0\)\))27 +b(=)h Fj(N)10 b Fk(\(0)p Fj(;)17 b(a)p Fk(\))27 b(=)h +Fj(a)2528 4231 y Fh(d)2569 4267 y Fj(:)404 4388 y Fk(Altogether)k(w)m +(e)h(ha)m(v)m(e)514 4670 y Fj(g)t Fk(\()p Fj(x)658 4629 +y Fe(2)697 4670 y Fk(\))28 b(=)f([)p Fj(z)942 4629 y +Fe(0)982 4670 y Fk(])p Fj(h)p Fk(\()p Fj(x;)17 b(z)t +Fk(\))29 b(=)f Fj(P)1485 4685 y Fe(0)1524 4670 y Fk(\()p +Fj(x)p Fk(\))22 b(+)1886 4587 y Fi(X)1839 4757 y Fg(1)p +1785 4769 138 4 v 1785 4810 a Ff(\020)1813 4826 y(i)1840 +4810 y Fg(\()p Ff(x)p Fg(\))1933 4784 y Fe(=)p Fh(o)p +Fe(\()p Fh(x)p Fe(\))2166 4559 y Fh(k)2203 4569 y Ff(i)2138 +4587 y Fi(X)2133 4771 y Fh(k)r Fe(=1)2347 4602 y Fj(P)2410 +4617 y Fh(i;k)2496 4602 y Fk(\()p Fj(x)p Fk(\))p 2288 +4647 399 4 v 2288 4738 a(\()p Fd(\000)p Fj(\020)2446 +4753 y Fh(i)2475 4738 y Fk(\()p Fj(x)p Fk(\)\))2644 4709 +y Fh(k)2724 4670 y Fd(2)2837 4638 y Fi(c)2818 4670 y +Fj(M)11 b Fk(\(\()p Fj(x)3054 4629 y Fe(1)p Fh(=r)3163 +4670 y Fk(\)\))404 5027 y(Since)39 b(all)f Fj(\020)851 +5042 y Fh(i)878 5027 y Fk(\()p Fj(x)p Fk(\)\(in)h Fj(L)p +Fk(\(\()p Fj(x)1365 4991 y Fe(1)p Fh(=r)1475 5027 y Fk(\)\)\))g(and)g +(all)f Fj(P)2030 5042 y Fh(j)2066 5027 y Fk(\()p Fj(x)p +Fk(\))p Fj(;)17 b(P)2304 5042 y Fh(i;k)2390 5027 y Fk(\()p +Fj(x)p Fk(\))40 b(\(in)2739 4995 y Fi(c)2720 5027 y Fj(M)10 +b Fk(\(\()p Fj(x)2955 4991 y Fe(1)p Fh(=r)3064 5027 y +Fk(\)\)\))39 b(are)h(al-)257 5147 y(gebraic)h(o)m(v)m(er)i +Fj(K)7 b Fk(\()p Fj(x)p Fk(\),)44 b(the)e(same)f(holds)g(also)g(for)g +Fj(g)t Fk(\()p Fj(x)2313 5111 y Fe(2)2352 5147 y Fk(\).)70 +b(Hence)43 b Fj(g)t Fk(\()p Fj(x)p Fk(\))e(is)g(algebraic)257 +5268 y(o)m(v)m(er)35 b Fj(K)7 b Fk(\()p Fj(x)650 5232 +y Fe(1)p Fh(=)p Fe(2)761 5268 y Fk(\),)33 b(hence)i(also)e(o)m(v)m(er)h +Fj(K)7 b Fk(\()p Fj(x)p Fk(\).)47 b(After)34 b(clearing)e +(denominators,)h(w)m(e)h(\014nally)257 5388 y(conclude)f(that)g +Fj(g)t Fk(\()p Fj(x)p Fk(\))f(is)g(algebraic)f(o)m(v)m(er)i +Fj(R)q Fk([)p Fj(x)p Fk(].)1852 5637 y(3)p eop +%%Page: 4 4 +4 3 bop 257 573 a Fb(References)62 792 y Fk(1)146 b(Bruno)46 +b(Haible:)69 b(D-\014nite)45 b(p)s(o)m(w)m(er)i(series)g(in)e(sev)m +(eral)i(v)-5 b(ariables.)82 b Fa(Diploma)46 b(thesis,)501 +912 y(University)35 b(of)g(Karlsruhe,)f(June)h(1989.)44 +b Fk(Sections)33 b(2.18)f(and)h(2.20.)62 1116 y(2)146 +b(M.)28 b(L.)f(J.)h(Hautus,)h(D.)e(A.)g(Klarner:)40 b(The)28 +b(diagonal)d(of)i(a)g(double)g(p)s(o)m(w)m(er)h(series.)43 +b Fa(Duke)501 1236 y(Math.)i(J.)35 b Fl(38)j Fk(\(1971\),)31 +b(229-235.)62 1439 y(3)146 b(C.)37 b(Chev)-5 b(alley:)50 +b(In)m(tro)s(duction)35 b(to)h(the)g(theory)h(of)e(algebraic)f +(functions)i(of)g(one)g(v)-5 b(ari-)501 1560 y(able.)43 +b Fa(Mathematic)-5 b(al)35 b(Surveys)f(VI.)h(A)n(meric)-5 +b(an)34 b(Mathematic)-5 b(al)34 b(So)-5 b(ciety.)62 1763 +y Fk(4)146 b(Jean-Pierre)33 b(Serre:)44 b(Corps)33 b(lo)s(caux.)43 +b Fa(Hermann.)h(Paris)35 b Fk(1968.)62 1967 y(5)146 b(Martin)38 +b(Eic)m(hler:)55 b(In)m(tro)s(duction)38 b(to)g(the)g(theory)h(of)f +(algebraic)f(n)m(um)m(b)s(ers)i(and)f(func-)501 2087 +y(tions.)43 b Fa(A)-5 b(c)g(ademic)34 b(Pr)-5 b(ess.)45 +b(New)35 b(Y)-7 b(ork,)34 b(L)-5 b(ondon)34 b Fk(1966.)1852 +5637 y(4)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/polynomial/diag_rational.tex b/doc/polynomial/diag_rational.tex new file mode 100644 index 0000000..3288312 --- /dev/null +++ b/doc/polynomial/diag_rational.tex @@ -0,0 +1,269 @@ +%% This LaTeX-file was created by Sun Feb 16 14:19:08 1997 +%% LyX 0.10 (C) 1995 1996 by Matthias Ettrich and the LyX Team + +%% Don't edit this file unless you are sure what you are doing. +\documentclass[12pt,a4paper,oneside,onecolumn]{article} +\usepackage[]{fontenc} +\usepackage[latin1]{inputenc} +\usepackage[dvips]{epsfig} + +%% +%% BEGIN The lyx specific LaTeX commands. +%% + +\makeatletter +\def\LyX{L\kern-.1667em\lower.25em\hbox{Y}\kern-.125emX\spacefactor1000}% +\newcommand{\lyxtitle}[1] {\thispagestyle{empty} +\global\@topnum\z@ +\section*{\LARGE \centering \sffamily \bfseries \protect#1 } +} +\newcommand{\lyxline}[1]{ +{#1 \vspace{1ex} \hrule width \columnwidth \vspace{1ex}} +} +\newenvironment{lyxsectionbibliography} +{ +\section*{\refname} +\@mkboth{\uppercase{\refname}}{\uppercase{\refname}} +\begin{list}{}{ +\itemindent-\leftmargin +\labelsep 0pt +\renewcommand{\makelabel}{} +} +} +{\end{list}} +\newenvironment{lyxchapterbibliography} +{ +\chapter*{\bibname} +\@mkboth{\uppercase{\bibname}}{\uppercase{\bibname}} +\begin{list}{}{ +\itemindent-\leftmargin +\labelsep 0pt +\renewcommand{\makelabel}{} +} +} +{\end{list}} +\def\lxq{"} +\newenvironment{lyxcode} +{\list{}{ +\rightmargin\leftmargin +\raggedright +\itemsep 0pt +\parsep 0pt +\ttfamily +}% +\item[] +} +{\endlist} +\newcommand{\lyxlabel}[1]{#1 \hfill} +\newenvironment{lyxlist}[1] +{\begin{list}{} +{\settowidth{\labelwidth}{#1} +\setlength{\leftmargin}{\labelwidth} +\addtolength{\leftmargin}{\labelsep} +\renewcommand{\makelabel}{\lyxlabel}}} +{\end{list}} +\newcommand{\lyxletterstyle}{ +\setlength\parskip{0.7em} +\setlength\parindent{0pt} +} +\newcommand{\lyxaddress}[1]{ +\par {\raggedright #1 +\vspace{1.4em} +\noindent\par} +} +\newcommand{\lyxrightaddress}[1]{ +\par {\raggedleft \begin{tabular}{l}\ignorespaces +#1 +\end{tabular} +\vspace{1.4em} +\par} +} +\newcommand{\lyxformula}[1]{ +\begin{eqnarray*} +#1 +\end{eqnarray*} +} +\newcommand{\lyxnumberedformula}[1]{ +\begin{eqnarray} +#1 +\end{eqnarray} +} +\makeatother + +%% +%% END The lyx specific LaTeX commands. +%% + +\pagestyle{plain} +\setcounter{secnumdepth}{3} +\setcounter{tocdepth}{3} + +%% Begin LyX user specified preamble: +\catcode`@=11 % @ ist ab jetzt ein gewoehnlicher Buchstabe +\def\Res{\mathop{\operator@font Res}} +\def\ll{\langle\!\langle} +\def\gg{\rangle\!\rangle} +\catcode`@=12 % @ ist ab jetzt wieder ein Sonderzeichen + + +%% End LyX user specified preamble. +\begin{document} + + +\title{The diagonal of a rational function} + +\begin{description} + +\item [Theorem:]~ + +\end{description} + +Let \( M \) be a torsion-free \( R \)-module, and \( d>0 \). Let +\[ +f=\sum _{n_{1},...,n_{d}}a_{n_{1},...,n_{d}}\, x_{1}^{n_{1}}\cdots x_{d}^{n_{d}}\in M[[x_{1},\ldots x_{d}]]\] +be a rational function, +i.e. there are \( P\in M[x_{1},\ldots ,x_{d}] \) and \( Q\in R[x_{1},\ldots ,x_{d}] \) with \( Q(0,\ldots ,0)=1 \) and \( Q\cdot f=P \). Then the full diagonal of \( f \) +\[ +g=\sum ^{\infty }_{n=0}a_{n,\ldots ,n}\, x_{1}^{n}\] +is +a D-finite element of \( M[[x_{1}]] \), w.r.t. \( R[x_{1}] \) and \( \{\partial _{x_{1}}\} \). + +\begin{description} + +\item [Proof:]~ + +\end{description} + +From the hypotheses, \( M[[x_{1},\ldots ,x_{d}]] \) is a torsion-free differential module over + \( R[x_{1},\ldots ,x_{d}] \) w.r.t. the derivatives \( \{\partial _{x_{1}},\ldots ,\partial _{x_{d}}\} \), and \( f \) is a D-finite element of \( M[[x_{1},\ldots ,x_{d}]] \) over + \( R[x_{1},\ldots ,x_{d}] \) w.r.t. \( \{\partial _{x_{1}},\ldots ,\partial _{x_{d}}\} \). Now apply the general diagonal theorem ([1], section 2.18) + \( d-1 \) times. + +\begin{description} + +\item [Theorem:]~ + +\end{description} + +Let \( R \) be an integral domain of characteristic 0 and \( M \) simultaneously +a torsion-free \( R \)-module and a commutative \( R \)-algebra without zero divisors. +Let +\[ +f=\sum _{m,n\geq 0}a_{m,n}x^{m}y^{n}\in M[[x,y]]\] + be a rational function. Then the diagonal of \( f \) +\[ +g=\sum ^{\infty }_{n=0}a_{n,n}\, x^{n}\] + is algebraic +over \( R[x] \). + +\begin{description} + +\item [Motivation~of~proof:]~ + +\end{description} + +The usual proof ([2]) uses complex analysis and works only for \( R=M=C \). +The idea is to compute +\[ +g(x^{2})=\frac{1}{2\pi i}\oint _{|z|=1}f(xz,\frac{x}{z})\frac{dz}{z}\] +This integral, whose integrand is a rational +function in \( x \) and \( z \), is calculated using the residue theorem. Since + \( f(x,y) \) is continuous at \( (0,0) \), there is a \( \delta >0 \) such that \( f(x,y)\neq \infty \) for \( |x|<\delta \), \( |y|<\delta \). It follows +that for all \( \varepsilon >0 \) and \( |x|<\delta \varepsilon \) all the poles of \( f(xz,\frac{x}{z}) \) are contained in \( \{z:|z|<\varepsilon \}\cup \{z:|z|>\frac{1}{\varepsilon }\} \). Thus the +poles of \( f(xz,\frac{x}{z}) \), all algebraic functions of \( x \) -- let's call them \( \zeta _{1}(x),\ldots \zeta _{s}(x) \) --, +can be divided up into those for which \( |\zeta _{i}(x)|=O(|x|) \) as \( x\rightarrow 0 \) and those for which + \( \frac{1}{|\zeta _{i}(x)|}=O(|x|) \) as \( x\rightarrow 0 \). It follows from the residue theorem that for \( |x|<\delta \) +\[ +g(x^{2})=\sum _{\zeta =0\vee \zeta =O(|x|)}\Res _{z=\zeta }\, f(xz,\frac{x}{z})\] + This is algebraic +over \( C(x) \). Hence \( g(x) \) is algebraic over \( C(x^{1/2}) \), hence also algebraic over \( C(x) \). + +\begin{description} + +\item [Proof:]~ + +\end{description} + +Let +\[ +h(x,z):=f(xz,\frac{x}{z})=\sum ^{\infty }_{m,n=0}a_{m,n}x^{m+n}z^{m-n}\in M[[xz,xz^{-1}]]\] +Then \( g(x^{2}) \) is the coefficient of \( z^{0} \) in \( h(x,z) \). Let \( N(x,z):=z^{d}Q(xz,\frac{x}{z}) \) (with \( d:=\max (\deg _{y}P,\deg _{y}Q) \)) be ``the denominator'' +of \( h(x,z) \). We have \( N(x,z)\in R[x,z] \) and \( N\neq 0 \) (because \( N(0,z)=z^{d} \)). Let \( K \) be the quotient field of + \( R \). Thus \( N(x,z)\in K[x][z]\setminus \{0\} \). + +It is well-known (see [3], p.64, or [4], chap. IV, §2, prop. 8, or +[5], chap. III, §1) that the splitting field of \( N(x,z) \) over \( K(x) \) can be embedded +into a field \( L((x^{1/r})) \), where \( r \) is a positive integer and \( L \) is a finite-algebraic +extension field of \( K \), i.e. a simple algebraic extension \( L=K(\alpha )=K\alpha ^{0}+\cdots +K\alpha ^{u-1} \). + + \( \widetilde{M}:=(R\setminus \{0\})^{-1}\cdot M \) is a \( K \)-vector space and a commutative \( K \)-algebra without zero divisors. + \( \widehat{M}:=\widetilde{M}\alpha ^{0}+\cdots +\widetilde{M}\alpha ^{u-1} \) is an \( L \)-vector space and a commutative \( L \)-algebra without zero divisors. + + + +\begin{eqnarray*} +\widehat{M}\ll x,z\gg & := & \widehat{M}[[x^{1/r}\cdot z,x^{1/r}\cdot z^{-1},x^{1/r}]][x^{-1/r}]\\ + & = & \left\{ \sum _{m,n}c_{m,n}x^{m/r}z^{n}:c_{m,n}\neq 0\Rightarrow |n|\leq m+O(1)\right\} +\end{eqnarray*} +is an \( L \)-algebra which contains \( \widehat{M}((x^{1/r})) \). + +Since \( N(x,z) \) splits into linear factors in \( L((x^{1/r}))[z] \), \( N(x,z)=l\prod ^{s}_{i=1}(z-\zeta _{i}(x))^{k_{i}} \), there exists a partial +fraction decomposition of \( h(x,z)=\frac{P(xz,\frac{x}{z})}{Q(xz,\frac{x}{z})}=\frac{z^{d}P(xz,\frac{x}{z})}{N(x,z)} \) in \( \widehat{M}\ll x,z\gg \): + + +\[ +h(x,z)=\sum ^{l}_{j=0}P_{j}(x)z^{j}+\sum ^{s}_{i=1}\sum ^{k_{i}}_{k=1}\frac{P_{i,k}(x)}{(z-\zeta _{i}(x))^{k}}\] +with \( P_{j}(x),P_{i,k}(x)\in \widehat{M}((x^{1/r})) \). + +Recall that we are looking for the coefficient of \( z^{0} \) in \( h(x,z) \). We compute +it separately for each summand. + +If \( \zeta _{i}(x)=ax^{m/r}+... \) with \( a\in L\setminus \{0\} \), \( m>0 \), or \( \zeta _{i}(x)=0 \), we have + + +\begin{eqnarray*} +\frac{1}{(z-\zeta _{i}(x))^{k}} & = & \frac{1}{z^{k}}\cdot \frac{1}{\left( 1-\frac{\zeta _{i}(x)}{z}\right) ^{k}}\\ + & = & \frac{1}{z^{k}}\cdot \sum ^{\infty }_{j=0}{k-1+j\choose k-1}\left( \frac{\zeta _{i}(x)}{z}\right) ^{j}\\ + & = & \sum ^{\infty }_{j=0}{k-1+j\choose k-1}\frac{\zeta _{i}(x)^{j}}{z^{k+j}} +\end{eqnarray*} +hence the coefficient of \( z^{0} \) in \( \frac{P_{i,k}(x)}{(z-\zeta _{i}(x))^{k}} \) is \( 0 \). + +If \( \zeta _{i}(x)=ax^{m/r}+... \) with \( a\in L\setminus \{0\} \), \( m<0 \), we have +\[ +\frac{1}{(z-\zeta _{i}(x))^{k}}=\frac{1}{(-\zeta _{i}(x))^{k}}\cdot \frac{1}{\left( 1-\frac{z}{\zeta _{i}(x)}\right) ^{k}}=\frac{1}{(-\zeta _{i}(x))^{k}}\cdot \sum _{j=0}^{\infty }{k-1+j\choose k-1}\left( \frac{z}{\zeta _{i}(x)}\right) ^{j}\] +hence the coefficient of \( z^{0} \) in \( \frac{P_{i,k}(x)}{(z-\zeta _{i}(x))^{k}} \) is \( \frac{P_{i,k}(x)}{(-\zeta _{i}(x))^{k}} \). + +The case \( \zeta _{i}(x)=ax^{m/r}+... \) with \( a\in L\setminus \{0\} \), \( m=0 \), cannot occur, because it would imply \( 0=N(0,\zeta _{i}(0))=N(0,a)=a^{d}. \) + +Altogether we have +\[ +g(x^{2})=[z^{0}]h(x,z)=P_{0}(x)+\sum _{\frac{1}{\zeta _{i}(x)}=o(x)}\sum ^{k_{i}}_{k=1}\frac{P_{i,k}(x)}{(-\zeta _{i}(x))^{k}}\in \widehat{M}((x^{1/r}))\] + + +Since all \( \zeta _{i}(x) \)(in \( L((x^{1/r})) \)) and all \( P_{j}(x),P_{i,k}(x) \) (in \( \widehat{M}((x^{1/r})) \)) are algebraic over \( K(x) \), the same +holds also for \( g(x^{2}) \). Hence \( g(x) \) is algebraic over \( K(x^{1/2}) \), hence also over \( K(x) \). +After clearing denominators, we finally conclude that \( g(x) \) is algebraic +over \( R[x] \). + +\begin{lyxsectionbibliography} + +\item [1] Bruno Haible: D-finite power series in several variables. \em Diploma +thesis, University of Karlsruhe, June 1989. \em Sections 2.18 and +2.20. + +\item [2] M. L. J. Hautus, D. A. Klarner: The diagonal of a double power +series. \em Duke Math. J. \em \bfseries 38 \mdseries (1971), +229-235. + +\item [3] C. Chevalley: Introduction to the theory of algebraic functions +of one variable. \em Mathematical Surveys VI. American Mathematical +Society.\em + +\item [4] Jean-Pierre Serre: Corps locaux. \em Hermann. Paris \em 1968. + +\item [5] Martin Eichler: Introduction to the theory of algebraic numbers +and functions. \em Academic Press. New York, London \em 1966. + +\end{lyxsectionbibliography} + +\end{document} diff --git a/doc/polynomial/hermite.dvi b/doc/polynomial/hermite.dvi new file mode 100644 index 0000000000000000000000000000000000000000..2bfaf5b7a741a3aad3344a15906390a7eea749c1 GIT binary patch literal 4080 zcmb_feQXrh5#Rf=jn4ra3WNj^1Fd3%F?WYC_O-48iVO*9V*C|X2`y{;oxRcBuGzh_ z&rYQVQCce44eKYY16N&4_zZ}uiqvW^XYA0VBFI5%RZ+F76lfx~0$SQ$DjKNe&b+;k z1s!ev=t_sy?0dgAGryVN%)9G!>>Zt6{#6bh*PoxPY$sinQY<V*7;IjYq%)xWad79(YW3$5?cg!iU*A)D#`;5=h^SjRN@N#7UgFjDCMD_>F z_I@(vx_M?Bkt0Hs(1Am3niL)urHH_X6`HR2`HjA}a(jw;A`!tKNNrOM$IMK6;cp#F z16&D!;ST^KLc^q}>7Fw!W>qR~R#RRkw3n2Lq?bnfWhvIzuNhD7xv!3L2TrzRU|`31 zZpWCbqqT`vrN6XtRn1X$ZYe;+xyrELH^rI$YSp;!Jpy|YDPq0GRbzHtFkNnL=Ff0N zxEg+L@UH&dfTrnXE9$2ls;WERK4bhf^lF;B_tV%y4pB46B<}Z}tJG9gHSXT{K-CvK z>MGxU$RbhPTA4_Qo}MRDId|^AYUaO8jHxg{1NKHOIjwIHvmL z663Sbu5;y@zW$}#85`4!FK)l=wMR-BZkXmKEz{9VRWC0uVjC;q0ON_okH8-NDUM4o zy>#uxV|E6*Cho_1U0T2%Qpqa=830=Djb=XTD5 z*GxHNB|i(~R*>bB|?PJZswnVDH(tQ%p?h}>Q+3RF^A>y> zIBXZETHXE01k{08qq|mAbW_s9#}u{{^SoW3^K|k@&&$JMNu~;s1t@@CGMFG?X&^$x zL=;cL8p@p1FNJ#*q(KlV5E9|TmKYvBFAq_|2+E+yV6sB16hi1L{+%@dZW)h?U0p+m zAOQ*O;YF$lk%6!f8n!e~)n9Mio@xdHMmcS8v)P1PjB*o4K73HgY^r7aV{TT}iz21S z<71o)QrHz;WBe0X?t*0X{(2A7H5;=`!5&`{F#Vdo_>U*^3Rb#xF;lRVXfnD0YW1tP zn26c5Z~dm>49D$Bt6WOn z?qucCJAwx23%E`wTld^vvq^XDoUCHPc%jG=nM@Rz)HLgkiC>zvx@YUp+WQ4a&O1j1 zg@UdLgZf<8r+nB-V~N#FPnZ`X&}W&zXUm5PeJy4<3;=CW9+Xk+1Kk)5$x;NiS#V4y zYjk(j%}nk}5tu^=-!he+@qG0fV;OCnUN<*fqBI?8=G_7-w;_i+o;pY2%9 zn&Amv!xhuNTb;Mxv+YmzQ&&Ag~um|QAkjK-@lL7c}>-Q=I z01~CI(vDD}K-^`y{lVt>lwnIzJYO)0g7QnzzJwx-zr&!_!x{_ zAfPUEn;$519j#d@nfGEnc#)eOGUwAOIGw?;Fuisj%cssd=mDd~F@*4~A!YS%+eb8Q zEv;kGu>E%(Ok)s*>@+sY{ig3!o`l80KUg}@CWQw<0ND7<(|#!;VMmi<3f;)E#!1b3 zHhv8&Q4+z{mZ_%fV4_ed0sTm(sU6m+L8B6M#VAX}gV(!26wz_BI-7(!lF+iB| zV`dLgU{3E|4WgqLzfleiSHmD~kz=AX=Gnh&8!vQ+Nl-6QENl2&uQ7m&1x2>nAnz`51_vzp Sun Feb 16 00:38:14 1997 +#LyX 0.10 (C) 1995 1996 Matthias Ettrich and the LyX Team +\lyxformat 2.10 +\textclass article +\language default +\inputencoding latin1 +\fontscheme default +\epsfig dvips +\papersize a4paper +\paperfontsize 12 +\baselinestretch 1.00 +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation indent +\quotes_language english +\quotes_times 2 +\paperorientation portrait +\papercolumns 0 +\papersides 1 +\paperpagestyle plain + +\layout Standard + +The Hermite polynomials +\begin_inset Formula \( H_{n}(x) \) +\end_inset + + are defined through +\begin_inset Formula +\[ +H_{n}(x)=(-1)^{n}e^{x^{2}}\cdot \left( \frac{d}{dx}\right) ^{n}\left( e^{-x^{2}}\right) \] + +\end_inset + + +\layout Description + +Theorem: +\layout Standard + + +\begin_inset Formula \( H_{n}(x) \) +\end_inset + + satisfies the recurrence relation +\layout Standard + + +\begin_inset Formula +\[ +H_{0}(x)=1\] + +\end_inset + + +\layout Standard + + +\begin_inset Formula +\[ +H_{n+1}(x)=2x\cdot H_{n}(x)-2n\cdot H_{n-1}(x)\] + +\end_inset + + for +\begin_inset Formula \( n\geq 0 \) +\end_inset + + and the differential equation +\begin_inset Formula \( H_{n}^{''}(x)-2x\cdot H_{n}^{'}(x)+2n\cdot H_{n}(x)=0 \) +\end_inset + + for all +\begin_inset Formula \( n\geq 0 \) +\end_inset + +. + +\layout Description + +Proof: +\layout Standard + +Let +\begin_inset Formula \( F:=\sum ^{\infty }_{n=0}\frac{H_{n}(x)}{n!}z^{n} \) +\end_inset + + be the exponential generating function of the sequence of polynomials. + Then, because the Taylor series development theorem holds in formal power + series rings (see [1], section 2. +16), we can simplify +\begin_inset Formula +\begin{eqnarray*} +F & = & e^{x^{2}}\cdot \sum ^{\infty }_{n=0}\frac{1}{n!}\left( \frac{d}{dx}\right) ^{n}\left( e^{-x^{2}}\right) \cdot (-z)^{n}\\ + & = & e^{x^{2}}\cdot e^{-(x-z)^{2}}\\ + & = & e^{2xz-z^{2}} +\end{eqnarray*} + +\end_inset + +It follows that +\begin_inset Formula \( \frac{d}{dz}F=(2x-2z)\cdot F \) +\end_inset + +. + This is equivalent to the claimed recurrence. + +\layout Standard +\cursor 190 +Starting from this equation, we compute a linear relation for the partial + derivatives of +\begin_inset Formula \( F \) +\end_inset + +. + Write +\begin_inset Formula \( \partial _{x}=\frac{d}{dx} \) +\end_inset + + and +\begin_inset Formula \( \Delta _{z}=z\frac{d}{dz} \) +\end_inset + +. + One computes +\begin_inset Formula +\[ +F=1\cdot F\] + +\end_inset + + +\begin_inset Formula +\[ +\partial _{x}F=2z\cdot F\] + +\end_inset + + +\begin_inset Formula +\[ +\partial _{x}^{2}F=4z^{2}\cdot F\] + +\end_inset + + +\begin_inset Formula +\[ +\Delta _{z}F=(2xz-2z^{2})\cdot F\] + +\end_inset + + +\begin_inset Formula +\[ +\partial _{x}\Delta _{z}F=(2z+4xz^{2}-4z^{3})\cdot F\] + +\end_inset + + +\begin_inset Formula +\[ +\Delta _{z}^{2}F=\left( 2x\cdot z+(4x^{2}-4)\cdot z^{2}-8x\cdot z^{3}+4\cdot z^{4}\right) \cdot F\] + +\end_inset + + Solve a homogeneous +\begin_inset Formula \( 5\times 6 \) +\end_inset + + system of linear equations over +\begin_inset Formula \( Q(x) \) +\end_inset + + to get +\begin_inset Formula +\[ +(-2x)\cdot \partial _{x}F+\partial _{x}^{2}F+2\cdot \Delta _{z}F=0\] + +\end_inset + + This is equivalent to the claimed equation +\begin_inset Formula \( H_{n}^{''}(x)-2x\cdot H_{n}^{'}(x)+2n\cdot H_{n}(x)=0 \) +\end_inset + +. + +\layout Bibliography + +[1] Bruno Haible: D-finite power series in several variables. + +\shape italic +Diploma thesis, University of Karlsruhe, June 1989 +\shape default +. + Sections 2. +15 and 2. +22. + diff --git a/doc/polynomial/hermite.ps b/doc/polynomial/hermite.ps new file mode 100644 index 0000000..692688f --- /dev/null +++ b/doc/polynomial/hermite.ps @@ -0,0 +1,647 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: hermite.dvi +%%Pages: 2 +%%PageOrder: Ascend +%%BoundingBox: 0 0 596 842 +%%DocumentPaperSizes: a4 +%%EndComments +%DVIPSCommandLine: dvips -Pljfour -o hermite.ps hermite.dvi +%DVIPSParameters: dpi=600, compressed, comments removed +%DVIPSSource: TeX output 1997.02.16:1407 +%%BeginProcSet: texc.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]/id ch-image N /rw ch-width 7 add 8 idiv string N /rc 0 N /gp 0 N +/cp 0 N{rc 0 ne{rc 1 sub /rc X rw}{G}ifelse}imagemask restore}B /G{{id +gp get /gp gp 1 add N dup 18 mod S 18 idiv pl S get exec}loop}B /adv{cp +add /cp X}B /chg{rw cp id gp 4 index getinterval putinterval dup gp add +/gp X adv}B /nd{/cp 0 N rw exit}B /lsh{rw cp 2 copy get dup 0 eq{pop 1}{ +dup 255 eq{pop 254}{dup dup add 255 and S 1 and or}ifelse}ifelse put 1 +adv}B /rsh{rw cp 2 copy get dup 0 eq{pop 128}{dup 255 eq{pop 127}{dup 2 +idiv S 128 and or}ifelse}ifelse put 1 adv}B /clr{rw cp 2 index string +putinterval adv}B /set{rw cp fillstr 0 4 index getinterval putinterval +adv}B /fillstr 18 string 0 1 17{2 copy 255 put pop}for N /pl[{adv 1 chg} +{adv 1 chg nd}{1 add chg}{1 add chg nd}{adv lsh}{adv lsh nd}{adv rsh}{ +adv rsh nd}{1 add adv}{/rc X nd}{1 add set}{1 add clr}{adv 2 chg}{adv 2 +chg nd}{pop nd}]dup{bind pop}forall N /D{/cc X dup type /stringtype ne{] +}if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +TeXDict begin 39158280 55380996 1000 600 600 (hermite.dvi) +@start /Fa 24 122 df<13F0EA03FC1207A2EA0FFEA4EA07FCEA03CCEA000C131C1318 +A2133813301370136013E0EA01C013801203EA0700120E5A5A5A5A5A0F1D7A891E>44 +D<16C01501A215031507ED0F80151F153F157F913801FF005C140F147F903807FCFEEB0F +F0EB0700EB00015DA314035DA314075DA3140F5DA3141F5DA3143F5DA3147F92C7FCA35C +5CA313015CA313035CA313075CA2130FA2131F133FB612FCA25D224276C132>49 +D56 +DI<91B712F818FF19C00201903980003FF06E90C7EA0FF84AED03FCF000FE4B157FA2 +F13F800203EE1FC05DF10FE0A214074B16F01907A2140F5D1AF8A2141F5DA2190F143F5D +1AF0A2147F4B151FA302FF17E092C9123FA34918C04A167F1A80A2010317FF4A1700A24E +5A13074A4B5A611807010F5F4A4B5A181F61011F4C5A4A4BC7FC18FE4D5A013F4B5A4A4A +5A4D5A017FED3FC005FFC8FC4AEB03FE01FFEC1FF8B812E094C9FC16F845447AC34A>68 +D<031FB512F05DA29239000FFC005FA35FA2161FA25FA2163FA25FA2167FA25FA216FFA2 +94C7FCA25DA25EA21503A25EA21507A25EA2150FA25EA2151FA25EA2153FA25EA2157FA2 +5EEA0F80D83FE013FF93C8FC127FA24A5AEAFFC04A5A1300007C495A0070495A4A5A6C5C +003C495A6C01FEC9FC380F81F83803FFE0C690CAFC344679C333>74 +D<91B66C90383FFFF8A302010180C7000F13006E90C8EA07FC4A17F01AC04B4B5A4FC7FC +193C02035E4B5DF003E0F0078002074BC8FC4B141E6018F8020F4A5A4BEB03C04D5A4DC9 +FC021F141E4B137C17F04C5A023F495A4B487E161F163F027F497EED80FFED81EF923883 +CFF89138FF8F8FED1E07033C7F157849EBF00303E07F15C092380001FF495A5C707FA213 +074A6E7EA2173F010F825C171F84131F4A140F84A2013F6F7E5CA2017F6F7EA24A4A7E49 +6C4A7FB66C90B512FC5E614D447AC34B>I<001FB500F090383FFFFCA326003FF0C70001 +13806D48913800FE00013F167C18785C187018F0017F5E5CA2170101FF5E91C8FCA21703 +485F5BA21707000394C7FC5BA25F0007160E5BA2171E120F49151CA2173C121F491538A2 +1778123F491570A217F0127F495DA2160100FF5E90C8FCA216035F16074893C8FC5E160E +161E5E007E1538007F15785E6C4A5A6D495A001F4A5A6D49C9FC6C6C133E6C6C13F83903 +FC07F0C6B512C0013F90CAFCEB07F83E466DC348>85 D97 D101 DI<14FE137FA3EB01FC13001301A2 +5CA21303A25CA21307A25CA2130FA25CA2131FA25C157F90393F83FFC091388F81F09138 +1E00F802387F4948137C5C4A137EA2495A91C7FCA25B484814FE5E5BA2000314015E5BA2 +000714035E5B1507000F5DA249130F5E001F1678031F1370491480A2003F023F13F0EE00 +E090C7FC160148023E13C01603007E1680EE070000FEEC1E0FED1F1E48EC0FF80038EC03 +E02D467AC432>104 D<143C147E14FE1301A3EB00FC14701400AE137C48B4FC3803C780 +380703C0000F13E0120E121C13071238A21278EA700F14C0131F00F0138012E0EA003F14 +00A25B137EA213FE5B12015BA212035B141E0007131C13E0A2000F133CEBC038A21478EB +807014F014E0EB81C0EA0783EBC7803803FE00EA00F8174378C11E>I108 DIIII114 DI< +1470EB01F8A313035CA313075CA3130F5CA3131F5CA2007FB512E0B6FC15C0D8003FC7FC +A25B137EA313FE5BA312015BA312035BA312075BA3120F5BA2EC0780001F140013805C14 +0E003F131EEB001C143C14385C6C13F0495A6C485AEB8780D807FEC7FCEA01F81B3F78BD +20>I<137C48B414072603C780EB1F80380703C0000F7F000E153F121C0107150012385E +1278D8700F147E5C011F14FE00F05B00E05DEA003FEC0001A2495C137E150313FE495CA2 +15071201495CA2030F13380003167849ECC070A3031F13F0EE80E0153F00011581037F13 +C06DEBEF8300000101148090397C03C787903A3E0F07C70090391FFE01FE903903F00078 +2D2D78AB34>I<017C143848B414FC3A03C78001FE380703C0000F13E0120E001C140001 +07147E1238163E1278D8700F141E5C131F00F049131C12E0EA003F91C7123C16385B137E +167801FE14705BA216F0000115E05B150116C0A24848EB0380A2ED0700A2150E12015D6D +5B000014786D5B90387C01E090383F0780D90FFFC7FCEB03F8272D78AB2D>I<137C48B4 +14072603C780EB1F80380703C0000F7F000E153F001C1600130712385E0078157EEA700F +5C011F14FE00F0495B12E0EA003FEC00015E5B137E150301FE5C5BA2150700015D5BA215 +0F00035D5BA2151F5EA2153F12014BC7FC6D5B00005BEB7C0390383E0F7EEB1FFEEB03F0 +90C712FE5DA214015D121F397F8003F0A24A5A4848485A5D48131F00F049C8FC0070137E +007813F8383801F0381E07C06CB4C9FCEA01FC294078AB2F>121 +D E /Fb 7 116 df82 D<92380FFFF04AB67E020F15F0 +023F15FC91B77E01039039FE001FFF4901F8010113804901E0010713C04901804913E001 +7F90C7FC49484A13F0A2485B485B5A5C5A7113E0485B7113C048701380943800FE0095C7 +FC485BA4B5FCAE7EA280A27EA2806C18FCA26C6D150119F87E6C6D15036EED07F06C18E0 +6C6D150F6D6DEC1FC06D01E0EC7F806D6DECFF00010701FCEB03FE6D9039FFC03FFC0100 +91B512F0023F5D020F1580020102FCC7FCDA000F13C03E437BC148>99 +D<92380FFFC04AB512FC020FECFF80023F15E091B712F80103D9FE037F499039F0007FFF +011F01C0011F7F49496D7F4990C76C7F49486E7F48498048844A804884485B727E5A5C48 +717EA35A5C721380A2B5FCA391B9FCA41A0002C0CBFCA67EA380A27EA27E6E160FF11F80 +6C183F6C7FF17F006C7F6C6D16FE6C17016D6C4B5A6D6D4A5A6D01E04A5A6D6DEC3FE001 +0301FC49B45A6D9026FFC01F90C7FC6D6C90B55A021F15F8020715E0020092C8FC030713 +F041437CC14A>101 DI<902607FF80EB1FFFB691B512F0040714FC041F14FF4C8193267FE07F7F9227 +81FE001F7FC6DA83F86D7F6DD987F07F6DD98FC0814C7F039FC78015BE03BC8003FC825D +A25DA25DA45DB3B2B7D8F007B71280A651417BC05A>110 D114 D<913A3FFF8007800107B5EAF81F011FECFE7F017F91B5FC48B8FC48EB +E0014890C7121FD80FFC1407D81FF0801600485A007F167F49153FA212FF171FA27F7F7F +6D92C7FC13FF14E014FF6C14F8EDFFC06C15FC16FF6C16C06C16F06C826C826C826C8201 +3F1680010F16C01303D9007F15E0020315F0EC001F1500041F13F81607007C150100FC81 +177F6C163FA2171F7EA26D16F0A27F173F6D16E06D157F6D16C001FEEDFF806D02031300 +02C0EB0FFE02FCEB7FFC01DFB65A010F5DD8FE0315C026F8007F49C7FC48010F13E03543 +7BC140>I E /Fc 1 111 df<000F13FC381FC3FF3931C707803861EC0301F813C0EAC1F0 +A213E03903C00780A3EC0F00EA0780A2EC1E041506D80F00130C143C15181538001EEB1C +70EC1FE0000CEB07801F177D9526>110 D E /Fd 1 49 df48 +D E /Fe 10 62 df<123C127E12FFA7127EA9123CAA1218A41200A7123C127E12FFA412 +7E123C082F7AAE14>33 D<13031307130E131C1338137013F0EA01E013C01203EA0780A2 +EA0F00A2121EA35AA45AA512F8A25AAB7EA21278A57EA47EA37EA2EA0780A2EA03C01201 +13E0EA00F013701338131C130E1307130310437AB11B>40 D<12C07E12707E7E7E120FEA +0780120313C0EA01E0A2EA00F0A21378A3133CA4131EA5131FA2130FAB131FA2131EA513 +3CA41378A313F0A2EA01E0A2EA03C013801207EA0F00120E5A5A5A5A5A10437CB11B>I< +EC0380B3A4B812FCA3C7D80380C7FCB3A42E2F7CA737>43 D +48 D<130C133C137CEA03FC12FFEAFC7C1200B3B113FE387FFFFEA2172C7AAB23>III<140EA2141E143EA2147E14FEA2EB01BE1303143E +1306130E130C131813381330136013E013C0EA0180120313001206120E120C5A12381230 +5A12E0B612FCA2C7EA3E00A9147F90381FFFFCA21E2D7EAC23>I61 D E /Ff 9 115 df58 D80 +D<003FBA12E0A59026FE000FEB8003D87FE09338003FF049171F90C71607A2007E180300 +7C1801A300781800A400F819F8481978A5C81700B3B3A20107B8FCA545437CC24E>84 +D101 +DI104 D<90277F8007FEEC0FFCB590263FFFC090387FFF8092B5D8F001B512E002 +816E4880913D87F01FFC0FE03FF8913D8FC00FFE1F801FFC0003D99F009026FF3E007F6C +019E6D013C130F02BC5D02F86D496D7EA24A5D4A5DA34A5DB3A7B60081B60003B512FEA5 +572D7CAC5E>109 D111 +D<90387F807FB53881FFE0028313F0028F13F8ED8FFC91389F1FFE000313BE6C13BC14F8 +A214F0ED0FFC9138E007F8ED01E092C7FCA35CB3A5B612E0A5272D7DAC2E>114 +D E /Fg 2 50 df0 D49 +D E /Fh 6 89 df<151E153E157C15F8EC01F0EC03E01407EC0FC0EC1F8015005C147E5C +A2495A495AA2495AA2495AA2495AA249C7FCA2137EA213FE5B12015BA212035BA21207A2 +5B120FA35B121FA45B123FA548C8FCA912FEB3A8127FA96C7EA5121F7FA4120F7FA31207 +7FA21203A27F1201A27F12007F137EA27FA26D7EA26D7EA26D7EA26D7EA26D7E6D7EA214 +7E80801580EC0FC0EC07E01403EC01F0EC00F8157C153E151E1F94718232>16 +D<12F07E127C7E7E6C7E7F6C7E6C7E12017F6C7E137EA27F6D7EA26D7EA26D7EA26D7EA2 +6D7EA26D7EA280147E147F80A21580141FA215C0A2140F15E0A3140715F0A4140315F8A5 +EC01FCA9EC00FEB3A8EC01FCA9EC03F8A515F01407A415E0140FA315C0141FA21580A214 +3F1500A25C147E14FE5CA2495AA2495AA2495AA2495AA2495AA249C7FC137EA25B485A5B +1203485A485A5B48C8FC123E5A5A5A1F947D8232>I32 +D<12F07E127C7E123F7E6C7E6C7E6C7E7F12016C7E7F137E133E133F6D7E130F806D7EA2 +6D7E80130180130080147E147F8081141F81140F81140781A2140381140181A2140081A2 +157FA36F7EA382151FA282150FA3821507A382A21503A282A31501A282A31500A382A482 +A21780A7163F17C0AC161F17E0B3B3A217C0163FAC1780167FA71700A25EA45EA31501A3 +5EA21503A35EA21507A25EA3150F5EA3151F5EA2153F5EA34BC7FCA315FEA25D1401A25D +14035D1407A25D140F5D141F5D143F92C8FC5C147E14FE5C13015C13035C495AA2495A5C +131F49C9FC133E137E5B5B485A12035B485A485A48CAFC5A123E5A5A5A2BF87E8242>I< +BB12FC86A3D87FC0C9001F7FF0007F6C6C17076C6C050113806C6CEF007F1A1F6C6CF00F +C06C6C18076C6C1803F201E06C6D17006D6C1860013F19706E18306D7E6D6C18181B006D +7E6D7E6D7EA26D7F6E7E6E7EA26E7E6E7E6E7EA26E7E6E7E80826F7E6F7EA26F7E6F7E6F +5A5EA24B5A5E4BCBFC153E157E5D5D4A5A4A5A14075D4A5A4ACCFC143E147E147C5C4948 +181801031930495A4A18704948186049CC12E0491801017EF003C0017C180749180F4848 +F01F800003197F49EF01FF4848050713004848173F48CA000FB5FC48BA5AA25ABB5AA24D +537B7F58>80 D88 D E /Fi 1 51 df50 +D E /Fj 4 22 df<007FB912E0BA12F0A26C18E03C04789A4D>0 +D<121FEA3F80EA7FC0EAFFE0A5EA7FC0EA3F80EA1F000B0B789E1C>I<0060160600F816 +0F6C161F007E163F6C167E6C6C15FC6C6CEC01F86C6CEC03F06C6CEC07E06C6CEC0FC06C +6CEC1F80017EEC3F006D147E6D6C5B6D6C485A6D6C485A6D6C485A6D6C485A6D6C485ADA +7E3FC7FCEC3F7E6E5A6E5A6E5AA24A7E4A7EEC3F7EEC7E3F4A6C7E49486C7E49486C7E49 +486C7E49486C7E49486C7E49C7127E017E8049EC1F804848EC0FC04848EC07E04848EC03 +F04848EC01F84848EC00FC48C9127E007E163F48161F48160F00601606303072B04D>I< +127012FCB4FCEA7FC0EA1FF0EA07FCEA01FF38007FC0EB1FF0EB07FCEB01FF9038007FC0 +EC1FF0EC07FC913801FF809138007FE0ED1FF8ED07FE923800FF80EE3FE0EE0FF8EE03FE +933800FF80EF3FE0EF0FF8EF03FE943800FF80F03FE0F00FF0A2F03FE0F0FF80943803FE +00EF0FF8EF3FE0EFFF80DC03FEC7FCEE0FF8EE3FE0EEFF80DB03FEC8FCED1FF8ED7FE091 +3801FF80DA07FEC9FCEC1FF0EC7FC04948CAFCEB07FCEB1FF0EB7FC04848CBFCEA07FCEA +1FF0EA7FC048CCFC12FC1270CDFCB0007FB912E0BA12F0A26C18E03C4E78BE4D>21 +D E /Fk 5 123 df<90273FFFFC0FB5FCA2D900FEC7EA3F80A24A1500A201015D177E5C +A2010315FE5F5CA2010714015F5CA2010F14035F5C91B6FC5B9139C00007E05CA2013F14 +0F5F91C7FCA249141F5F137EA201FE143F94C7FC5BA200015D167E5BA2000315FEB539E0 +3FFFF8A2382D7CAC3A>72 D<151FEC03FFA2EC003FA2153EA2157EA2157CA215FCA215F8 +A21401EB07E190381FF9F0EB7C1DEBF80FEA01F03903E007E0EA07C0120FEA1F8015C0EA +3F00140F5A007E1480A2141F12FE481400A2EC3F021506143E5AEC7E0E007CEBFE0C14FC +0101131C393E07BE18391F0E1E38390FFC0FF03903F003C0202F7DAD24>100 +D<3907C007E0391FE03FF83918F8783E393879E01E39307B801F38707F00126013FEEAE0 +FC12C05B00815C0001143E5BA20003147E157C5B15FC0007ECF8081618EBC00115F0000F +1538913803E0300180147016E0001F010113C015E390C7EAFF00000E143E251F7E9D2B> +110 D<013F137C9038FFC1FF3A01C1E383803A0380F703C0390700F60F000E13FE4813FC +12180038EC0700003049C7FCA2EA200100005BA313035CA301075B5D14C000385CD87C0F +130600FC140E011F130C011B131C39F03BE038D8707113F0393FE0FFC0260F803FC7FC22 +1F7E9D28>120 D<011E1330EB3F809038FFC07048EBE0E0ECF1C03803C0FF9038803F80 +903800070048130EC75A5C5C5C495A495A49C7FC131E13385B491340484813C0485A3807 +0001000EEB0380380FE007391FF81F0038387FFF486C5A38601FFC38E00FF038C003C01C +1F7D9D21>122 D E /Fl 9 123 df64 D<91B912F8A3020001C0C7123F6F48EC07F003FF15031901 +93C9FCA21A705C5DA3020317605DA314075D18C01701020F4B13005DA21703021F92C8FC +4B5BA25F023F141E4B13FE92B5FCA24A5CED8000173CA202FF141892C7FCA21738491530 +5CA21770010315604A91C9FCA313075CA3130F5CA3131F5CA2133FA313FFB612F8A34544 +7CC33F>70 D<91B6D8E003B61280A3020001E0C70003EB8000DB7F806E48C7FC03FF1503 +A293C85BA219075C4B5EA2190F14034B5EA2191F14074B5EA2193F140F4B5EA2197F141F +4B5EA219FF143F92B8C8FCA3DA7FC0C712014B5DA2180314FF92C85BA218075B4A5EA218 +0F13034A5EA2181F13074A5EA2183F130F4A5EA2187F131F4A5EA2013F16FFA24A93C9FC +D9FFE002037FB6D8E003B67EA351447CC351>72 D81 D100 DI<01F8EB03FCD803FEEB1FFFD8071F90 +387C0FC03B0E0F80E007E03A0C07C3C003001CD9C7007F001801CE1301003801DC800030 +13D8EB0FF800705B00605BA200E0491303D8C01F5D5C12001607013F5D91C7FCA2160F49 +5D137E161F5F13FE49143F94C7FC187000014B136049147E16FE4C13E0000317C0491501 +04F81380170300071700495D170EEE781C000FED7C3849EC1FF0D80380EC07C0342D7DAB +3A>110 D<02FCEB07E0903A03FF801FFC903A0F07C0781E903A1C03E0E01F903A3801F1 +C07FD9700013804901FB13FF4848EBFF00495B000316FE90C71438484A13001206140100 +0E5C120CC7FC14035DA314075DA3140F5DA3021F143817305D1770023F1460121E003F16 +E0267F807FEB01C0026F148000FF01EF1303D901CFEB070000FE903887C00E267C03835B +3A3C0F01E0783A1FFC00FFE0D803F0EB3F80302D7EAB37>120 D<027CEB018049B41303 +4901801300010F6D5A49EBE00E6F5A90393F03F838903978007EF80170EB1FF00160EB01 +E001E05C49495A90C748C7FC150E5D5D5D5D4A5A4A5A4AC8FC140E5C5C5C5CEB03C049C9 +FC130E49141C4914185B49143848481430491470D8039014F048B4495A3A0FEFC007C039 +1E03F01FD81C01B55A486C91C7FC485C00606D5A00E0EB3FF048EB0FC0292D7CAB2D> +122 D E /Fm 53 122 df<1618163CA2167EA216FFA24B7FA24B6C7EA29238063FE0A24B +6C7EA24B6C7EA292383807FC153092387003FE15609238E001FF15C002016D7F5D02036E +7E92C7FC4A6E7E1406020E6E7E140C021C6E7E141802386E7E143002706E7E146002E06E +7E5C01016F7F5C0103707E91C9FC183F010683181F4983180F49831807498318034983A2 +49707EA24848701380A248CBEA7FC0A20006F03FE0A248F01FF0A2001FBA12F8A24819FC +A24819FEA2BCFC48477CC651>1 D<9239FFC001FC020F9038F80FFF913B3F803E3F03C0 +913BFC00077E07E0D903F890390FFC0FF0494890383FF81F4948EB7FF0495A494814E049 +C7FCF00FE04991393FC0038049021F90C7FCAFB912F0A3C648C7D81FC0C7FCB3B2486CEC +3FF0007FD9FC0FB512E0A33C467EC539>11 D<4AB4FC020F13E091387F80F8903901FC00 +1C49487FD907E0130F4948137F011FECFF80495A49C7FCA25B49EC7F00163E93C7FCACEE +3F80B8FCA3C648C7FC167F163FB3B0486CEC7FC0007FD9FC1FB5FCA330467EC536>I<12 +1EEA7F80EAFFC0A9EA7F80ACEA3F00AB121EAC120CA5C7FCAA121EEA7F80A2EAFFC0A4EA +7F80A2EA1E000A4778C61B>33 D<140C141C1438147014E0EB01C01303EB0780EB0F00A2 +131E5BA25B13F85B12015B1203A2485AA3485AA348C7FCA35AA2123EA2127EA4127CA312 +FCB3A2127CA3127EA4123EA2123FA27EA36C7EA36C7EA36C7EA212017F12007F13787FA2 +7F7FA2EB0780EB03C01301EB00E014701438141C140C166476CA26>40 +D<12C07E12707E7E7E120F6C7E6C7EA26C7E6C7EA21378137C133C133E131E131FA2EB0F +80A3EB07C0A3EB03E0A314F0A21301A214F8A41300A314FCB3A214F8A31301A414F0A213 +03A214E0A3EB07C0A3EB0F80A3EB1F00A2131E133E133C137C13785BA2485A485AA2485A +48C7FC120E5A5A5A5A5A16647BCA26>I<16C04B7EB3AB007FBAFCBB1280A26C1900C8D8 +01E0C9FCB3AB6F5A41407BB84C>43 D<121EEA7F8012FF13C0A213E0A3127FEA1E601200 +A413E013C0A312011380120313005A1206120E5A5A5A12600B1D78891B>II<121EEA7F80A2EAFFC0A4EA7F80A2EA1E000A0A78891B>I<14FF010713E090 +381F81F890383E007C01FC133F4848EB1F8049130F4848EB07C04848EB03E0A2000F15F0 +491301001F15F8A2003F15FCA390C8FC4815FEA54815FFB3A46C15FEA56D1301003F15FC +A3001F15F8A26C6CEB03F0A36C6CEB07E0000315C06D130F6C6CEB1F806C6CEB3F00013E +137C90381F81F8903807FFE0010090C7FC28447CC131>48 D<143014F013011303131F13 +FFB5FC13E713071200B3B3B0497E497E007FB6FCA3204278C131>II52 D<000615C0D807C0130701FCEB7F8090B612 +005D5D5D15E0158026063FFCC7FC90C9FCAE14FF010713C090381F01F090383800FC01F0 +137ED807C07F49EB1F8016C090C7120F000615E0C8EA07F0A316F81503A216FCA5123E12 +7F487EA416F890C712075A006015F0A20070140F003015E00038EC1FC07E001EEC3F806C +EC7F006C6C13FE6C6C485A3901F807F039007FFFE0011F90C7FCEB07F826447BC131>I< +EC07FCEC3FFF91B512C0903903FC03E0903907E000F0D91FC0133849C71258017EEB01FC +01FE1303491307485A485AA24848EB03F8000FEC01F092C7FC485AA3485AA3127FA29038 +007F80903801FFF090380780FC39FF0E003E49EB1F8049EB0FC049EB07E0136001E0EB03 +F04914F8150116FC5BED00FEA390C812FFA47EA57F123FA216FE121F15016D14FC120FED +03F86C7EED07F06C6C14E06C6CEB0FC06C6CEB1F80017EEB3F0090383F80FE90380FFFF8 +010313E00100138028447CC131>I<14FF010713E0011F13F890387F00FE01FC133FD801 +F0EB1F804848EB0FC049EB07E00007EC03F048481301A290C713F8481400A47FA26D1301 +16F07F6C6CEB03E013FC6C6CEB07C09039FF800F806C9038C01F006CEBF03EECF8783900 +7FFEF090383FFFC07F01077F6D13F8497F90381E7FFFD97C1F1380496C13C02601E00313 +E048486C13F000079038007FF84848EB3FFC48C7120F003EEC07FE150148140016FF167F +48153FA2161FA56C151E007C153EA2007E153C003E157C6C15F86DEB01F06C6CEB03E06C +6CEB07C0D803F8EB1F80C6B4EBFF0090383FFFFC010F13F00101138028447CC131>56 +D<121EEA7F80A2EAFFC0A4EA7F80A2EA1E00C7FCB3A5121EEA7F80A2EAFFC0A4EA7F80A2 +EA1E000A2B78AA1B>58 D<007FBAFCBB1280A26C1900CEFCB0007FBAFCBB1280A26C1900 +41187BA44C>61 D66 D68 D72 DI76 +D79 D<49B41303010FEBE007013F +13F89039FE00FE0FD801F8131FD807E0EB079F49EB03DF48486DB4FC48C8FC4881003E81 +127E82127C00FC81A282A37E82A27EA26C6C91C7FC7F7FEA3FF813FE381FFFE06C13FE6C +EBFFE06C14FC6C14FF6C15C0013F14F0010F80010180D9001F7F14019138001FFF030313 +80816F13C0167F163F161F17E000C0150FA31607A37EA36C16C0160F7E17806C151F6C16 +006C5D6D147ED8FBC05CD8F9F0495AD8F07C495A90393FC00FE0D8E00FB51280010149C7 +FC39C0003FF02B487BC536>83 D<003FB912F8A3903BF0001FF8001F01806D481303003E +C7150048187C0078183CA20070181CA30060180CA5481806A5C81600B3B3A54B7EED7FFE +49B77EA33F447DC346>I87 D91 D93 +D97 +DII<167FED3FFFA315018182B3EC7F80903803FFF090380FC07C +90383F000E017E1307496D5AD803F87F48487F5B000F81485AA2485AA2127FA290C8FC5A +AB7E7FA2123FA26C7EA2000F5D7F6C6C5B00035C6C6C9038077F806C6C010E13C0013F01 +1C13FE90380FC0F8903803FFE09026007F0013002F467DC436>III +III108 DI<3901FC01FE00FF903807FFC091381E07F091383801F8000701707F0003EB +E0002601FDC07F5C01FF147F91C7FCA25BA35BB3A8486CECFF80B5D8F83F13FEA32F2C7D +AB36>II<3901FC03FC00FF90380FFF8091 +383C07E091387001F83A07FDE000FE00010180137F01FFEC3F8091C7EA1FC04915E04914 +0F17F0160717F8160317FCA3EE01FEABEE03FCA3EE07F8A217F0160F6D15E0EE1FC06D14 +3F17806EEB7E00D9FDC05B9039FCF003F891383C0FE091381FFF80DA03FCC7FC91C9FCAE +487EB512F8A32F3F7DAB36>I<91387F8003903903FFE00790380FE07890393F801C0F90 +387E000E496D5AD803F8EB039F0007EC01BF4914FF48487F121F5B003F81A2485AA348C8 +FCAB6C7EA3123F7F121F6D5C120F6D5B12076C6C5B6C6C497E6C6C130E013F131C90380F +C0F8903803FFE09038007F0091C7FCAEEEFF80033F13FEA32F3F7DAB33>I<3903F803F0 +00FFEB1FFCEC3C3EEC707F0007EBE0FF3803F9C000015B13FBEC007E153C01FF13005BA4 +5BB3A748B4FCB512FEA3202C7DAB26>I<90383FE0183901FFFC383907E01F78390F0003 +F8001E1301481300007C1478127800F81438A21518A27EA27E6C6C13006C7E13FC383FFF +E06C13FC6C13FF6C14C06C14E0C614F0011F13F81300EC0FFC140300C0EB01FE1400157E +7E153EA27EA36C143C6C147C15786C14F86CEB01F039F38003E039F1F00F8039E07FFE00 +38C00FF01F2E7DAC26>I<1306A5130EA4131EA3133E137EA213FE12011207001FB512F0 +B6FCA2C648C7FCB3A4150CAA017E131C017F1318A26D133890381F8030ECC070903807E0 +E0903801FFC09038007F001E3E7EBC26>IIIII< +B539F001FFFCA3000790C7EA7FE06C48EC1F8000011600160E0000150C6D141C6D1418A2 +6E1338013F1430A26D6C5BA26E13E0010F5CA26D6C485AA2ECF803010391C7FCA2903801 +FC06A2ECFE0E0100130CA2EC7F18A215B8EC3FB0A2EC1FE0A36E5AA26E5AA36EC8FCA214 +06A35CA25CA2123C007E5BB4FC5CA25CEAFE01387C0380D87007C9FCEA3C1EEA0FFCEA03 +F02E3F7EAA33>I E end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: a4 +%%BeginPaperSize: a4 +a4 +%%EndPaperSize + +%%EndSetup +%%Page: 1 1 +1 0 bop 404 573 a Fm(The)33 b(Hermite)f(p)s(olynomials)d +Fl(H)1604 588 y Fk(n)1651 573 y Fm(\()p Fl(x)p Fm(\))k(are)g(de\014ned) +h(through)1159 801 y Fl(H)1240 816 y Fk(n)1287 801 y +Fm(\()p Fl(x)p Fm(\))28 b(=)g(\()p Fj(\000)p Fm(1\))1752 +760 y Fk(n)1799 801 y Fl(e)1844 760 y Fk(x)1884 737 y +Fi(2)1945 801 y Fj(\001)1994 655 y Fh( )2098 734 y Fl(d)p +2070 778 107 4 v 2070 870 a(dx)2186 655 y Fh(!)2252 678 +y Fk(n)2315 705 y Fh(\020)2365 801 y Fl(e)2410 760 y +Fg(\000)p Fk(x)2505 737 y Fi(2)2544 705 y Fh(\021)257 +1022 y Ff(Theorem:)404 1186 y Fl(H)485 1201 y Fk(n)531 +1186 y Fm(\()p Fl(x)p Fm(\))33 b(satis\014es)h(the)f(recurrence)h +(relation)1661 1375 y Fl(H)1742 1390 y Fe(0)1781 1375 +y Fm(\()p Fl(x)p Fm(\))28 b(=)f(1)1093 1607 y Fl(H)1174 +1622 y Fk(n)p Fe(+1)1311 1607 y Fm(\()p Fl(x)p Fm(\))h(=)g(2)p +Fl(x)22 b Fj(\001)g Fl(H)1831 1622 y Fk(n)1878 1607 y +Fm(\()p Fl(x)p Fm(\))g Fj(\000)h Fm(2)p Fl(n)f Fj(\001)g +Fl(H)2391 1622 y Fk(n)p Fg(\000)p Fe(1)2528 1607 y Fm(\()p +Fl(x)p Fm(\))257 1771 y(for)33 b Fl(n)c Fj(\025)h Fm(0)j(and)g(the)h +(di\013eren)m(tial)d(equation)i Fl(H)2018 1711 y Fd(00)2010 +1795 y Fk(n)2062 1771 y Fm(\()p Fl(x)p Fm(\))23 b Fj(\000)g +Fm(2)p Fl(x)g Fj(\001)g Fl(H)2583 1711 y Fd(0)2575 1795 +y Fk(n)2621 1771 y Fm(\()p Fl(x)p Fm(\))g(+)g(2)p Fl(n)f +Fj(\001)h Fl(H)3135 1786 y Fk(n)3182 1771 y Fm(\()p Fl(x)p +Fm(\))29 b(=)f(0)257 1891 y(for)k(all)f Fl(n)d Fj(\025)g +Fm(0.)257 2055 y Ff(Pro)s(of:)404 2219 y Fm(Let)34 b +Fl(F)44 b Fm(:=)821 2153 y Fh(P)908 2179 y Fg(1)908 2244 +y Fk(n)p Fe(=0)1072 2173 y Fk(H)1130 2181 y Fc(n)1172 +2173 y Fe(\()p Fk(x)p Fe(\))p 1072 2196 196 4 v 1138 +2254 a Fk(n)p Fe(!)1277 2219 y Fl(z)1326 2183 y Fk(n)1408 +2219 y Fm(b)s(e)34 b(the)h(exp)s(onen)m(tial)e(generating)h(function)g +(of)f(the)i(se-)257 2340 y(quence)27 b(of)c(p)s(olynomials.)38 +b(Then,)27 b(b)s(ecause)f(the)f(T)-8 b(a)m(ylor)23 b(series)i(dev)m +(elopmen)m(t)g(theorem)257 2460 y(holds)33 b(in)e(formal)g(p)s(o)m(w)m +(er)i(series)g(rings)f(\(see)i([1],)f(section)f(2.16\),)g(w)m(e)i(can)f +(simplify)1023 2688 y Fl(F)97 b Fm(=)83 b Fl(e)1387 2647 +y Fk(x)1427 2624 y Fi(2)1487 2688 y Fj(\001)1568 2580 +y Fg(1)1544 2605 y Fh(X)1537 2787 y Fk(n)p Fe(=0)1715 +2621 y Fm(1)p 1697 2665 86 4 v 1697 2757 a Fl(n)p Fm(!)1809 +2542 y Fh( )1912 2621 y Fl(d)p 1884 2665 107 4 v 1884 +2757 a(dx)2000 2542 y Fh(!)2066 2565 y Fk(n)2130 2592 +y Fh(\020)2179 2688 y Fl(e)2224 2647 y Fg(\000)p Fk(x)2319 +2624 y Fi(2)2358 2592 y Fh(\021)2430 2688 y Fj(\001)21 +b Fm(\()p Fj(\000)p Fl(z)t Fm(\))2681 2647 y Fk(n)1183 +2925 y Fm(=)83 b Fl(e)1387 2884 y Fk(x)1427 2860 y Fi(2)1487 +2925 y Fj(\001)22 b Fl(e)1582 2884 y Fg(\000)p Fe(\()p +Fk(x)p Fg(\000)p Fk(z)s Fe(\))1822 2860 y Fi(2)1183 3070 +y Fm(=)83 b Fl(e)1387 3029 y Fe(2)p Fk(xz)s Fg(\000)p +Fk(z)1589 3005 y Fi(2)257 3234 y Fm(It)33 b(follo)m(ws)f(that)923 +3195 y Fk(d)p 905 3211 72 4 v 905 3268 a(dz)987 3234 +y Fl(F)42 b Fm(=)27 b(\(2)p Fl(x)c Fj(\000)g Fm(2)p Fl(z)t +Fm(\))f Fj(\001)g Fl(F)14 b Fm(.)44 b(This)33 b(is)f(equiv)-5 +b(alen)m(t)33 b(to)f(the)h(claimed)e(recur-)257 3354 +y(rence.)404 3475 y(Starting)i(from)g(this)g(equation,)i(w)m(e)g +(compute)f(a)g(linear)f(relation)f(for)i(the)g(partial)257 +3595 y(deriv)-5 b(ativ)m(es)33 b(of)f Fl(F)14 b Fm(.)43 +b(W)-8 b(rite)32 b Fl(@)1323 3610 y Fk(x)1395 3595 y +Fm(=)1529 3556 y Fk(d)p 1509 3572 77 4 v 1509 3629 a(dx)1627 +3595 y Fm(and)h(\001)1898 3610 y Fk(z)1966 3595 y Fm(=)27 +b Fl(z)2147 3556 y Fk(d)p 2129 3572 72 4 v 2129 3629 +a(dz)2211 3595 y Fm(.)43 b(One)33 b(computes)1674 3759 +y Fl(F)41 b Fm(=)28 b(1)21 b Fj(\001)h Fl(F)1601 3966 +y(@)1652 3981 y Fk(x)1696 3966 y Fl(F)42 b Fm(=)27 b(2)p +Fl(z)g Fj(\001)22 b Fl(F)1581 4188 y(@)1637 4147 y Fe(2)1632 +4213 y Fk(x)1677 4188 y Fl(F)42 b Fm(=)27 b(4)p Fl(z)1983 +4147 y Fe(2)2045 4188 y Fj(\001)22 b Fl(F)1393 4420 y +Fm(\001)1474 4435 y Fk(z)1514 4420 y Fl(F)41 b Fm(=)28 +b(\(2)p Fl(xz)f Fj(\000)22 b Fm(2)p Fl(z)2133 4379 y +Fe(2)2173 4420 y Fm(\))g Fj(\001)g Fl(F)1216 4652 y(@)1267 +4667 y Fk(x)1311 4652 y Fm(\001)1392 4667 y Fk(z)1432 +4652 y Fl(F)42 b Fm(=)27 b(\(2)p Fl(z)g Fm(+)22 b(4)p +Fl(xz)2050 4611 y Fe(2)2112 4652 y Fj(\000)h Fm(4)p Fl(z)2310 +4611 y Fe(3)2350 4652 y Fm(\))f Fj(\001)g Fl(F)781 4884 +y Fm(\001)862 4843 y Fe(2)862 4909 y Fk(z)902 4884 y +Fl(F)41 b Fm(=)1110 4788 y Fh(\020)1159 4884 y Fm(2)p +Fl(x)23 b Fj(\001)e Fl(z)27 b Fm(+)22 b(\(4)p Fl(x)1647 +4843 y Fe(2)1709 4884 y Fj(\000)h Fm(4\))f Fj(\001)f +Fl(z)2016 4843 y Fe(2)2079 4884 y Fj(\000)h Fm(8)p Fl(x)h +Fj(\001)e Fl(z)2403 4843 y Fe(3)2466 4884 y Fm(+)h(4)g +Fj(\001)g Fl(z)2734 4843 y Fe(4)2774 4788 y Fh(\021)2845 +4884 y Fj(\001)g Fl(F)257 5061 y Fm(Solv)m(e)33 b(a)f(homogeneous)h(5) +22 b Fj(\002)h Fm(6)32 b(system)h(of)g(linear)d(equations)j(o)m(v)m(er) +h Fl(Q)p Fm(\()p Fl(x)p Fm(\))f(to)f(get)1170 5224 y(\()p +Fj(\000)p Fm(2)p Fl(x)p Fm(\))22 b Fj(\001)g Fl(@)1550 +5239 y Fk(x)1594 5224 y Fl(F)36 b Fm(+)22 b Fl(@)1847 +5183 y Fe(2)1842 5249 y Fk(x)1888 5224 y Fl(F)36 b Fm(+)22 +b(2)f Fj(\001)h Fm(\001)2286 5239 y Fk(z)2326 5224 y +Fl(F)42 b Fm(=)27 b(0)257 5388 y(This)f(is)e(equiv)-5 +b(alen)m(t)25 b(to)g(the)g(claimed)e(equation)i Fl(H)2121 +5329 y Fd(00)2113 5413 y Fk(n)2165 5388 y Fm(\()p Fl(x)p +Fm(\))7 b Fj(\000)g Fm(2)p Fl(x)g Fj(\001)g Fl(H)2622 +5329 y Fd(0)2614 5413 y Fk(n)2660 5388 y Fm(\()p Fl(x)p +Fm(\))g(+)g(2)p Fl(n)g Fj(\001)g Fl(H)3111 5403 y Fk(n)3157 +5388 y Fm(\()p Fl(x)p Fm(\))28 b(=)f(0.)1852 5637 y(1)p +eop +%%Page: 2 2 +2 1 bop 257 573 a Fb(References)62 792 y Fm(1)146 b(Bruno)46 +b(Haible:)69 b(D-\014nite)45 b(p)s(o)m(w)m(er)i(series)g(in)e(sev)m +(eral)i(v)-5 b(ariables.)82 b Fa(Diploma)46 b(thesis,)501 +912 y(University)35 b(of)g(Karlsruhe,)f(June)h(1989)p +Fm(.)43 b(Sections)33 b(2.15)f(and)h(2.22.)1852 5637 +y(2)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/polynomial/hermite.tex b/doc/polynomial/hermite.tex new file mode 100644 index 0000000..99e729c --- /dev/null +++ b/doc/polynomial/hermite.tex @@ -0,0 +1,176 @@ +%% This LaTeX-file was created by Sun Feb 16 14:05:55 1997 +%% LyX 0.10 (C) 1995 1996 by Matthias Ettrich and the LyX Team + +%% Don't edit this file unless you are sure what you are doing. +\documentclass[12pt,a4paper,oneside,onecolumn]{article} +\usepackage[]{fontenc} +\usepackage[latin1]{inputenc} +\usepackage[dvips]{epsfig} + +%% +%% BEGIN The lyx specific LaTeX commands. +%% + +\makeatletter +\def\LyX{L\kern-.1667em\lower.25em\hbox{Y}\kern-.125emX\spacefactor1000}% +\newcommand{\lyxtitle}[1] {\thispagestyle{empty} +\global\@topnum\z@ +\section*{\LARGE \centering \sffamily \bfseries \protect#1 } +} +\newcommand{\lyxline}[1]{ +{#1 \vspace{1ex} \hrule width \columnwidth \vspace{1ex}} +} +\newenvironment{lyxsectionbibliography} +{ +\section*{\refname} +\@mkboth{\uppercase{\refname}}{\uppercase{\refname}} +\begin{list}{}{ +\itemindent-\leftmargin +\labelsep 0pt +\renewcommand{\makelabel}{} +} +} +{\end{list}} +\newenvironment{lyxchapterbibliography} +{ +\chapter*{\bibname} +\@mkboth{\uppercase{\bibname}}{\uppercase{\bibname}} +\begin{list}{}{ +\itemindent-\leftmargin +\labelsep 0pt +\renewcommand{\makelabel}{} +} +} +{\end{list}} +\def\lxq{"} +\newenvironment{lyxcode} +{\list{}{ +\rightmargin\leftmargin +\raggedright +\itemsep 0pt +\parsep 0pt +\ttfamily +}% +\item[] +} +{\endlist} +\newcommand{\lyxlabel}[1]{#1 \hfill} +\newenvironment{lyxlist}[1] +{\begin{list}{} +{\settowidth{\labelwidth}{#1} +\setlength{\leftmargin}{\labelwidth} +\addtolength{\leftmargin}{\labelsep} +\renewcommand{\makelabel}{\lyxlabel}}} +{\end{list}} +\newcommand{\lyxletterstyle}{ +\setlength\parskip{0.7em} +\setlength\parindent{0pt} +} +\newcommand{\lyxaddress}[1]{ +\par {\raggedright #1 +\vspace{1.4em} +\noindent\par} +} +\newcommand{\lyxrightaddress}[1]{ +\par {\raggedleft \begin{tabular}{l}\ignorespaces +#1 +\end{tabular} +\vspace{1.4em} +\par} +} +\newcommand{\lyxformula}[1]{ +\begin{eqnarray*} +#1 +\end{eqnarray*} +} +\newcommand{\lyxnumberedformula}[1]{ +\begin{eqnarray} +#1 +\end{eqnarray} +} +\makeatother + +%% +%% END The lyx specific LaTeX commands. +%% + +\pagestyle{plain} +\setcounter{secnumdepth}{3} +\setcounter{tocdepth}{3} +\begin{document} + +The Hermite polynomials \( H_{n}(x) \) are defined through +\[ +H_{n}(x)=(-1)^{n}e^{x^{2}}\cdot \left( \frac{d}{dx}\right) ^{n}\left( e^{-x^{2}}\right) \] + + +\begin{description} + +\item [Theorem:]~ + +\end{description} + + \( H_{n}(x) \) satisfies the recurrence relation + + +\[ +H_{0}(x)=1\] + + + +\[ +H_{n+1}(x)=2x\cdot H_{n}(x)-2n\cdot H_{n-1}(x)\] + for \( n\geq 0 \) and the differential equation \( H_{n}^{''}(x)-2x\cdot H_{n}^{'}(x)+2n\cdot H_{n}(x)=0 \) for all \( n\geq 0 \). + +\begin{description} + +\item [Proof:]~ + +\end{description} + +Let \( F:=\sum ^{\infty }_{n=0}\frac{H_{n}(x)}{n!}z^{n} \) be the exponential generating function of the sequence of polynomials. +Then, because the Taylor series development theorem holds in formal +power series rings (see [1], section 2.16), we can simplify +\begin{eqnarray*} +F & = & e^{x^{2}}\cdot \sum ^{\infty }_{n=0}\frac{1}{n!}\left( \frac{d}{dx}\right) ^{n}\left( e^{-x^{2}}\right) \cdot (-z)^{n}\\ + & = & e^{x^{2}}\cdot e^{-(x-z)^{2}}\\ + & = & e^{2xz-z^{2}} +\end{eqnarray*} +It follows +that \( \frac{d}{dz}F=(2x-2z)\cdot F \). This is equivalent to the claimed recurrence. + +Starting from this equation, we compute a linear relation for the +partial derivatives of \( F \). Write \( \partial _{x}=\frac{d}{dx} \) and \( \Delta _{z}=z\frac{d}{dz} \). One computes +\[ +F=1\cdot F\] + +\[ +\partial _{x}F=2z\cdot F\] + +\[ +\partial _{x}^{2}F=4z^{2}\cdot F\] + +\[ +\Delta _{z}F=(2xz-2z^{2})\cdot F\] + +\[ +\partial _{x}\Delta _{z}F=(2z+4xz^{2}-4z^{3})\cdot F\] + +\[ +\Delta _{z}^{2}F=\left( 2x\cdot z+(4x^{2}-4)\cdot z^{2}-8x\cdot z^{3}+4\cdot z^{4}\right) \cdot F\] + Solve +a homogeneous \( 5\times 6 \) system of linear equations over \( Q(x) \) to get +\[ +(-2x)\cdot \partial _{x}F+\partial _{x}^{2}F+2\cdot \Delta _{z}F=0\] + This is +equivalent to the claimed equation \( H_{n}^{''}(x)-2x\cdot H_{n}^{'}(x)+2n\cdot H_{n}(x)=0 \). + +\begin{lyxsectionbibliography} + +\item [1] Bruno Haible: D-finite power series in several variables. \em Diploma +thesis, University of Karlsruhe, June 1989\em . Sections 2.15 and +2.22. + +\end{lyxsectionbibliography} + +\end{document} diff --git a/doc/polynomial/laguerre.dvi b/doc/polynomial/laguerre.dvi new file mode 100644 index 0000000000000000000000000000000000000000..9742c70a42f9c0b374de14ad12ec2bc61b88c153 GIT binary patch literal 7864 zcmcgx33wFc8J^ANf`nT{5HO%VBoOmtH-cPIM9P^~kV7p{+3e0Hqq{S4W^!z>)V3aY z%#c4*)`j>mP!742YPC9XL%>IoTEw#>s1*YA`~I2P*^rG|OS{jL7}@{$ zj`w@NfxLnkrtaesJW!2AQ zzU^}cKI=0cVi;xpsR+ZY&*12varjM2_2Y@&H|&^~$K=B?_><)iiyp7Bpqh=kk8G{* zRn@Yh$Z9oB^Hm`f;e{~g3rSj{-;;-{HYPV^`@><*GoQ6Me zVwfA>#;YW2>s+HS-e44IJ~%SK=JRYoldDCcwyIjyM~L?+&CJ@5AGeNy9WBWnQTM{@ z%C$JF=qK~mv^A(CC$TDV-iVRKYpD=D;T{k|ig-%fU5Y|7wr|xx3oc18CmyZs&)~P# z3bw&hx}!i<6h;5)@N)|3b5UtLppv}(ck5a6!uK#tkY)1sFVORH^OQh?3Lk|GezrFr zwqpeT&xl7_^<$%djp`I#pNs04BJpa>k}ffD_niHCsp?CS@p~8)I`93Pj3Usqk_7?C zMGTV|^vtV2TAymi$_9`38L++}vf+tv{k9=W4)v2`6~~U~BFQInQa&qzAz4ji{k7mO z-j9EV;2VKgbvMIo8oVP2#@&B-ob97Nw=KUhCn;nmczt|psY){UWSTBA4en9(-eZCr z6cV0OoD`sSj7M$hd&hy)g@xWY9|fx$V>FM}&S=!j?Jh03Db@SIF~Uyfby- z9;Vf!#>}%-xEZVz6vP(yfZO2)KtcOJ%_xoe_&^L4js>_p7W8e}DaruM7<+3iRXP@L zh%yPl0u|uoW-s{r)MXPB=ij>F(mW;`(PAP~ij3P^TB@pg&UIHS;M5ezX=Aj)F1jR- z+MBw`5*K#Fc`a2LTM^TmrRt{Mw?ovKDxvdyp%83Is#T(Hv4HW+Tv2FR#t1>gz!nMs zqk@&AnIC)3$dW8tG&?jJ&}^jmow2RhEL1ZK#O}e9}o;70a_C zxQVaQg0;LKL8=KsTx$7S0yiRt(L(S=4V>g~PYKBy|IRE~<4nW{IA4{(`$C$;iX23N zd5{J-uHGruYph5xM(B5{Uhw?e3K4JG7N3D8M-%FwpE;$F{M@-{wqA@I!m>x78vP3} z>J5O3yg&b3(b~e396M6hxa6AG4Ub9+_!QRYb?*ks8u74U8prdRyWNE`(V4Z7pESxR z=Yod9DjD)z?BT5rLff6We%Nw>Ck!m{*SQXH(k31|>d>T_(zpqvT z7aV#DiDdyfleNgVcBdE#38HQ509zMhLqbiME7&cPshD(d2}cDVy;NW2{~_28EImt-h6$%JR^n5BB6p|~RvXfjh)B4s( zh--vyXLuk$rp-Z$I;VCg{ddU-VJm^eBLGvQ$j+;s08P1ROk1RB)^en%g6WxEL5xxs zyxU1iE8RCU>)Mx4kZkrsa70wKnYsJcq8&2Tu>0) zWX8$$7#I*HkpZ&r7Kjg46Jih*B4s|A6~i1agoLVy78Hdr{l_IpSwNSMHz2bH8TVa5 z$h#BYLP|s?8>!X!FlJbB5^=9PS`GP4i(g0F{DVe00osbsGZsU7U2269WWuPs;*0nX zNoI7Mvw|*Jsuc=iF>!}}#s#$qNGH^4A?}tKt8ubciFe2#VsR7}blN|YFrO|0)vqDU z8|w^+M2Ky?#22b!D@7lYtj*k#B?d&j5EjImYR(_cy6t@kf20kI^f8JBh+wuss|opd zwy1>kIQjsvaJK72yH|s|T~ppO7B8k&oq7|=zmMif@hSN$v-hyinOA)gqE#AJb14BeUE%n>7FV0_3LB_wy| zUdXhr4g0_jb`)&(V!@I%^8=$O#@U)v+Z@^I7to%){hX;Y+9)mqhG7rXRk_=D8XT|c z!Gg!b+04@=oWN3E>r;aSbZP^p2JH&;l&6s-3~ZPEM~?i2Kb$Z4D^Kn}>AQ zCv9f-?=fJtnf=|&Kd2Z~l&LFLcJf|h?0YCi~} z2Do@~jectRt#}D>m6hqPhTBXh_6xCk)~QPs&t7J?x$N|eVU{c^8MfwQV+=4mu)dW6 zNzc^_;*C+nXba{HdJ_d|&jWYF;USg}X1-y8E!NJ&0BM?qG*nt4m)v;7 z&NSrOJsnn}nQMm{2EOTbY?Uth!KajG>p8iaWNlayPp-q*vDZbjr{p6Nff*MAYD^ST zG-prl08g3DxNIV|3C7pAIL&s@pr^(nF58Es932IAYM7)oB4Y7g8?^S-l)WgNaa*@| z2FLeY(y^c#Xe8MbL^u{oCoGAUYuFheXV%IzEl4I^W6d0ZS{lo%v(9$xhT(!$udy5w z;js=tEtxXyMU!!G)%OTea0OOdG9k3svYDruSiPoy#7gK^Kg4;;FP}^FXuSr@9`*fMmIOr|2Uhwq(g;Fd-JFC+5yNd z6%&r>$475!yICdkXK(z^yi3OxUBn^OwVJ~_PMl#-07D(Vlrq#zsMDa5I7=>t1)EdUuo8G)S!_y^5}R+^b_&dyX3pG zl3cH=ck7u)zfhj0Sq_f?A6;!i+HF&x&ga{A7IK`Aw=IXFVr(+lE=#mzg&(MMfD;X_5h0cU=`kA|KLP`yl{mIv8 z%uXd#kHS@^G3n%$^gnpifc8cMGJ>&k8<0V60b^A^jY+S#4~Ov}SN!~Ly^^;^H%emH zLf$k}Dho+>;Nm9$slShIM1OsCfqAS6K6H|*XCHcE16wK!(7E`ag%7gUsdtVxz{_<@f z?Mq(%=mOEa+;F^+`NAWq*A?1$H;OE6F`}%&U<#v|QJ_*O$cn-js1UzsRnrTx;V+}9 z5M^M2ZCAbOSO6i>0P|Yt#<~~DHaxcQPzTb&!7&H^Ysx>C!MN6nQ493Od?8eaT|L6y z2cxa9fYVE%R?;q~)j)=3jK%Myh$O@83z|MFitI@=goZf}fa27A`;Y~gfXb?V{-IWY z7rABjgM}&)-dL7ief7(Zr20`G3~pcxmgvWW%XajIfY^9H(2QM};L{31>?|C%WLEIh z0QQ&NgC_>-&a$S0j6v_~hiKoqxyg)`Qp-luxH>LC4O9tS5TSj4z9`9B(C3F{O0)Fc z0BFAFrL6z4uudr3;!$?Z*tf77cBSI_EmF0e23T3W5GuOPuLu8+hXR@=;nBr}gB z_KGj2uFYWQK8!oPkm*gB{z)(G%TwBy!t}42Y2RzoKD4HPnoT!`NThiKO#2#~{u%Xa Mh8Y&gc-#E^8@!ly2mk;8 literal 0 HcmV?d00001 diff --git a/doc/polynomial/laguerre.lyx b/doc/polynomial/laguerre.lyx new file mode 100644 index 0000000..a8fd94c --- /dev/null +++ b/doc/polynomial/laguerre.lyx @@ -0,0 +1,316 @@ +#This file was created by Sun Feb 16 14:05:04 1997 +#LyX 0.10 (C) 1995 1996 Matthias Ettrich and the LyX Team +\lyxformat 2.10 +\textclass article +\begin_preamble +\catcode`@=11 % @ ist ab jetzt ein gewoehnlicher Buchstabe +\def\ll{\langle\!\langle} +\def\gg{\rangle\!\rangle} +\catcode`@=12 % @ ist ab jetzt wieder ein Sonderzeichen + +\end_preamble +\language default +\inputencoding latin1 +\fontscheme default +\epsfig dvips +\papersize a4paper +\paperfontsize 12 +\baselinestretch 1.00 +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation indent +\quotes_language english +\quotes_times 2 +\paperorientation portrait +\papercolumns 0 +\papersides 1 +\paperpagestyle plain + +\layout Standard + +The Laguerre polynomials +\begin_inset Formula \( L_{n}(x) \) +\end_inset + + are defined through +\begin_inset Formula +\[ +L_{n}(x)=e^{x}\cdot \left( \frac{d}{dx}\right) ^{n}(x^{n}e^{-x})\] + +\end_inset + + +\layout Description + +Theorem: +\layout Standard + + +\begin_inset Formula \( L_{n}(x) \) +\end_inset + + satisfies the recurrence relation +\layout Standard + + +\begin_inset Formula +\[ +L_{0}(x)=1\] + +\end_inset + + +\layout Standard + + +\begin_inset Formula +\[ +L_{n+1}(x)=(2n+1-x)\cdot L_{n}(x)-n^{2}\cdot L_{n-1}(x)\] + +\end_inset + +for +\begin_inset Formula \( n\geq 0 \) +\end_inset + + and the differential equation +\begin_inset Formula \( x\cdot L_{n}^{''}(x)+(1-x)\cdot L_{n}^{'}(x)+n\cdot L_{n}(x)=0 \) +\end_inset + + for all +\begin_inset Formula \( n\geq 0 \) +\end_inset + +. + +\layout Description + +Proof: +\layout Standard + +Let +\begin_inset Formula \( F:=\sum ^{\infty }_{n=0}\frac{L_{n}(x)}{n!}\cdot z^{n} \) +\end_inset + + be the exponential generating function of the sequence of polynomials. + It is the diagonal series of the power series +\begin_inset Formula +\[ +G:=\sum _{m,n=0}^{\infty }\frac{1}{m!}\cdot e^{x}\cdot \left( \frac{d}{dx}\right) ^{m}(x^{n}e^{-x})\cdot y^{m}\cdot z^{n}\] + +\end_inset + +Because the Taylor series development theorem holds in formal power series + rings (see [1], section 2. +16), we can simplify +\begin_inset Formula +\begin{eqnarray*} +G & = & e^{x}\cdot \sum _{n=0}^{\infty }\left( \sum _{m=0}^{\infty }\frac{1}{m!}\cdot \left( \frac{d}{dx}\right) ^{m}(x^{n}e^{-x})\cdot y^{m}\right) \cdot z^{n}\\ + & = & e^{x}\cdot \sum _{n=0}^{\infty }(x+y)^{n}e^{-(x+y)}\cdot z^{n}\\ + & = & \frac{e^{-y}}{1-(x+y)z} +\end{eqnarray*} + +\end_inset + +We take over the terminology from the +\begin_inset Quotes eld +\end_inset + +diag_rational +\begin_inset Quotes erd +\end_inset + + paper; here +\begin_inset Formula \( R=Q[x] \) +\end_inset + + and +\begin_inset Formula \( M=Q[[x]] \) +\end_inset + + (or, if you like it better, +\begin_inset Formula \( M=H(C) \) +\end_inset + +, the algebra of functions holomorphic in the entire complex plane). + +\begin_inset Formula \( G\in M[[y,z]] \) +\end_inset + + is not rational; nevertheless we can proceed similarly to the +\begin_inset Quotes eld +\end_inset + +diag_series +\begin_inset Quotes erd +\end_inset + + paper. + +\begin_inset Formula \( F(z^{2}) \) +\end_inset + + is the coefficient of +\begin_inset Formula \( t^{0} \) +\end_inset + + in +\begin_inset Formula +\[ +G(zt,\frac{z}{t})=\frac{e^{-zt}}{1-z^{2}-\frac{xz}{t}}\in M[[zt,\frac{z}{t},z]]=M\ll z,t\gg \] + +\end_inset + +The denominator's only zero is +\begin_inset Formula \( t=\frac{xz}{1-z^{2}} \) +\end_inset + +. + We can write +\begin_inset Formula +\[ +e^{-zt}=e^{-\frac{xz^{2}}{1-z^{2}}}+\left( zt-\frac{xz^{2}}{1-z^{2}}\right) \cdot P(z,t)\] + +\end_inset + +with +\begin_inset Formula \( P(z,t)\in Q[[zt,\frac{xz^{2}}{1-z^{2}}]]\subset Q[[zt,x,z]]=M[[zt,z]]\subset M\ll z,t\gg \) +\end_inset + +. + This yields -- all computations being done in +\begin_inset Formula \( M\ll z,t\gg \) +\end_inset + + -- +\begin_inset Formula +\begin{eqnarray*} +G(zt,\frac{z}{t}) & = & \frac{e^{-\frac{xz^{2}}{1-z^{2}}}}{1-z^{2}-\frac{xz}{t}}+\frac{zt}{1-z^{2}}\cdot P(z,t)\\ + & = & \frac{1}{1-z^{2}}\cdot e^{-\frac{xz^{2}}{1-z^{2}}}\cdot \sum _{j=0}^{\infty }\left( \frac{x}{1-z^{2}}\frac{z}{t}\right) ^{j}+\frac{zt}{1-z^{2}}\cdot P(z,t) +\end{eqnarray*} + +\end_inset + +Here, the coefficient of +\begin_inset Formula \( t^{0} \) +\end_inset + + is +\begin_inset Formula +\[ +F(z^{2})=\frac{1}{1-z^{2}}\cdot e^{-\frac{xz^{2}}{1-z^{2}}}\] + +\end_inset + +hence +\begin_inset Formula +\[ +F(z)=\frac{1}{1-z}\cdot e^{-\frac{xz}{1-z}}\] + +\end_inset + + +\layout Standard + +It follows that +\begin_inset Formula \( (1-z)^{2}\cdot \frac{d}{dz}F-(1-x-z)\cdot F=0 \) +\end_inset + +. + This is equivalent to the claimed recurrence. + +\layout Standard + +Starting from the closed form for +\begin_inset Formula \( F \) +\end_inset + +, we compute a linear relation for the partial derivatives of +\begin_inset Formula \( F \) +\end_inset + +. + Write +\begin_inset Formula \( \partial _{x}=\frac{d}{dx} \) +\end_inset + + and +\begin_inset Formula \( \Delta _{z}=z\frac{d}{dz} \) +\end_inset + +. + One computes +\begin_inset Formula +\[ +F=1\cdot F\] + +\end_inset + + +\begin_inset Formula +\[ +\left( 1-z\right) \cdot \partial _{x}F=-z\cdot F\] + +\end_inset + + +\begin_inset Formula +\[ +\left( 1-z\right) ^{2}\cdot \partial _{x}^{2}F=z^{2}\cdot F\] + +\end_inset + + +\begin_inset Formula +\[ +\left( 1-z\right) ^{2}\cdot \Delta _{z}F=((1-x)z-z^{2})\cdot F\] + +\end_inset + + +\begin_inset Formula +\[ +\left( 1-z\right) ^{3}\cdot \partial _{x}\Delta _{z}F=(-z+xz^{2}+z^{3})\cdot F\] + +\end_inset + +Solve a homogeneous +\begin_inset Formula \( 4\times 5 \) +\end_inset + + system of linear equations over +\begin_inset Formula \( Q(x) \) +\end_inset + + to get +\begin_inset Formula +\[ +\left( 1-z\right) ^{3}\cdot \left( (1-x)\cdot \partial _{x}F+x\cdot \partial _{x}^{2}F+\Delta _{z}F\right) =0\] + +\end_inset + +Divide by the first factor to get +\begin_inset Formula +\[ +(1-x)\cdot \partial _{x}F+x\cdot \partial _{x}^{2}F+\Delta _{z}F=0\] + +\end_inset + +This is equivalent to the claimed equation +\begin_inset Formula \( x\cdot L_{n}^{''}(x)+(1-x)\cdot L_{n}^{'}(x)+n\cdot L_{n}(x)=0 \) +\end_inset + +. + +\layout Bibliography +\cursor 123 +[1] Bruno Haible: D-finite power series in several variables. + +\shape italic +Diploma thesis, University of Karlsruhe, June 1989 +\shape default +. + Sections 2. +15 and 2. +22. + diff --git a/doc/polynomial/laguerre.ps b/doc/polynomial/laguerre.ps new file mode 100644 index 0000000..609ed79 --- /dev/null +++ b/doc/polynomial/laguerre.ps @@ -0,0 +1,864 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: laguerre.dvi +%%Pages: 3 +%%PageOrder: Ascend +%%BoundingBox: 0 0 596 842 +%%DocumentPaperSizes: a4 +%%EndComments +%DVIPSCommandLine: dvips -Pljfour -o laguerre.ps laguerre.dvi +%DVIPSParameters: dpi=600, compressed, comments removed +%DVIPSSource: TeX output 1997.02.16:1408 +%%BeginProcSet: texc.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]/id ch-image N /rw ch-width 7 add 8 idiv string N /rc 0 N /gp 0 N +/cp 0 N{rc 0 ne{rc 1 sub /rc X rw}{G}ifelse}imagemask restore}B /G{{id +gp get /gp gp 1 add N dup 18 mod S 18 idiv pl S get exec}loop}B /adv{cp +add /cp X}B /chg{rw cp id gp 4 index getinterval putinterval dup gp add +/gp X adv}B /nd{/cp 0 N rw exit}B /lsh{rw cp 2 copy get dup 0 eq{pop 1}{ +dup 255 eq{pop 254}{dup dup add 255 and S 1 and or}ifelse}ifelse put 1 +adv}B /rsh{rw cp 2 copy get dup 0 eq{pop 128}{dup 255 eq{pop 127}{dup 2 +idiv S 128 and or}ifelse}ifelse put 1 adv}B /clr{rw cp 2 index string +putinterval adv}B /set{rw cp fillstr 0 4 index getinterval putinterval +adv}B /fillstr 18 string 0 1 17{2 copy 255 put pop}for N /pl[{adv 1 chg} +{adv 1 chg nd}{1 add chg}{1 add chg nd}{adv lsh}{adv lsh nd}{adv rsh}{ +adv rsh nd}{1 add adv}{/rc X nd}{1 add set}{1 add clr}{adv 2 chg}{adv 2 +chg nd}{pop nd}]dup{bind pop}forall N /D{/cc X dup type /stringtype ne{] +}if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +TeXDict begin 39158280 55380996 1000 600 600 (laguerre.dvi) +@start /Fa 24 122 df<13F0EA03FC1207A2EA0FFEA4EA07FCEA03CCEA000C131C1318 +A2133813301370136013E0EA01C013801203EA0700120E5A5A5A5A5A0F1D7A891E>44 +D<16C01501A215031507ED0F80151F153F157F913801FF005C140F147F903807FCFEEB0F +F0EB0700EB00015DA314035DA314075DA3140F5DA3141F5DA3143F5DA3147F92C7FCA35C +5CA313015CA313035CA313075CA2130FA2131F133FB612FCA25D224276C132>49 +D56 +DI<91B712F818FF19C00201903980003FF06E90C7EA0FF84AED03FCF000FE4B157FA2 +F13F800203EE1FC05DF10FE0A214074B16F01907A2140F5D1AF8A2141F5DA2190F143F5D +1AF0A2147F4B151FA302FF17E092C9123FA34918C04A167F1A80A2010317FF4A1700A24E +5A13074A4B5A611807010F5F4A4B5A181F61011F4C5A4A4BC7FC18FE4D5A013F4B5A4A4A +5A4D5A017FED3FC005FFC8FC4AEB03FE01FFEC1FF8B812E094C9FC16F845447AC34A>68 +D<031FB512F05DA29239000FFC005FA35FA2161FA25FA2163FA25FA2167FA25FA216FFA2 +94C7FCA25DA25EA21503A25EA21507A25EA2150FA25EA2151FA25EA2153FA25EA2157FA2 +5EEA0F80D83FE013FF93C8FC127FA24A5AEAFFC04A5A1300007C495A0070495A4A5A6C5C +003C495A6C01FEC9FC380F81F83803FFE0C690CAFC344679C333>74 +D<91B66C90383FFFF8A302010180C7000F13006E90C8EA07FC4A17F01AC04B4B5A4FC7FC +193C02035E4B5DF003E0F0078002074BC8FC4B141E6018F8020F4A5A4BEB03C04D5A4DC9 +FC021F141E4B137C17F04C5A023F495A4B487E161F163F027F497EED80FFED81EF923883 +CFF89138FF8F8FED1E07033C7F157849EBF00303E07F15C092380001FF495A5C707FA213 +074A6E7EA2173F010F825C171F84131F4A140F84A2013F6F7E5CA2017F6F7EA24A4A7E49 +6C4A7FB66C90B512FC5E614D447AC34B>I<001FB500F090383FFFFCA326003FF0C70001 +13806D48913800FE00013F167C18785C187018F0017F5E5CA2170101FF5E91C8FCA21703 +485F5BA21707000394C7FC5BA25F0007160E5BA2171E120F49151CA2173C121F491538A2 +1778123F491570A217F0127F495DA2160100FF5E90C8FCA216035F16074893C8FC5E160E +161E5E007E1538007F15785E6C4A5A6D495A001F4A5A6D49C9FC6C6C133E6C6C13F83903 +FC07F0C6B512C0013F90CAFCEB07F83E466DC348>85 D97 D101 DI<14FE137FA3EB01FC13001301A2 +5CA21303A25CA21307A25CA2130FA25CA2131FA25C157F90393F83FFC091388F81F09138 +1E00F802387F4948137C5C4A137EA2495A91C7FCA25B484814FE5E5BA2000314015E5BA2 +000714035E5B1507000F5DA249130F5E001F1678031F1370491480A2003F023F13F0EE00 +E090C7FC160148023E13C01603007E1680EE070000FEEC1E0FED1F1E48EC0FF80038EC03 +E02D467AC432>104 D<143C147E14FE1301A3EB00FC14701400AE137C48B4FC3803C780 +380703C0000F13E0120E121C13071238A21278EA700F14C0131F00F0138012E0EA003F14 +00A25B137EA213FE5B12015BA212035B141E0007131C13E0A2000F133CEBC038A21478EB +807014F014E0EB81C0EA0783EBC7803803FE00EA00F8174378C11E>I108 DIIII114 DI< +1470EB01F8A313035CA313075CA3130F5CA3131F5CA2007FB512E0B6FC15C0D8003FC7FC +A25B137EA313FE5BA312015BA312035BA312075BA3120F5BA2EC0780001F140013805C14 +0E003F131EEB001C143C14385C6C13F0495A6C485AEB8780D807FEC7FCEA01F81B3F78BD +20>I<137C48B414072603C780EB1F80380703C0000F7F000E153F121C0107150012385E +1278D8700F147E5C011F14FE00F05B00E05DEA003FEC0001A2495C137E150313FE495CA2 +15071201495CA2030F13380003167849ECC070A3031F13F0EE80E0153F00011581037F13 +C06DEBEF8300000101148090397C03C787903A3E0F07C70090391FFE01FE903903F00078 +2D2D78AB34>I<017C143848B414FC3A03C78001FE380703C0000F13E0120E001C140001 +07147E1238163E1278D8700F141E5C131F00F049131C12E0EA003F91C7123C16385B137E +167801FE14705BA216F0000115E05B150116C0A24848EB0380A2ED0700A2150E12015D6D +5B000014786D5B90387C01E090383F0780D90FFFC7FCEB03F8272D78AB2D>I<137C48B4 +14072603C780EB1F80380703C0000F7F000E153F001C1600130712385E0078157EEA700F +5C011F14FE00F0495B12E0EA003FEC00015E5B137E150301FE5C5BA2150700015D5BA215 +0F00035D5BA2151F5EA2153F12014BC7FC6D5B00005BEB7C0390383E0F7EEB1FFEEB03F0 +90C712FE5DA214015D121F397F8003F0A24A5A4848485A5D48131F00F049C8FC0070137E +007813F8383801F0381E07C06CB4C9FCEA01FC294078AB2F>121 +D E /Fb 7 116 df82 D<92380FFFF04AB67E020F15F0 +023F15FC91B77E01039039FE001FFF4901F8010113804901E0010713C04901804913E001 +7F90C7FC49484A13F0A2485B485B5A5C5A7113E0485B7113C048701380943800FE0095C7 +FC485BA4B5FCAE7EA280A27EA2806C18FCA26C6D150119F87E6C6D15036EED07F06C18E0 +6C6D150F6D6DEC1FC06D01E0EC7F806D6DECFF00010701FCEB03FE6D9039FFC03FFC0100 +91B512F0023F5D020F1580020102FCC7FCDA000F13C03E437BC148>99 +D<92380FFFC04AB512FC020FECFF80023F15E091B712F80103D9FE037F499039F0007FFF +011F01C0011F7F49496D7F4990C76C7F49486E7F48498048844A804884485B727E5A5C48 +717EA35A5C721380A2B5FCA391B9FCA41A0002C0CBFCA67EA380A27EA27E6E160FF11F80 +6C183F6C7FF17F006C7F6C6D16FE6C17016D6C4B5A6D6D4A5A6D01E04A5A6D6DEC3FE001 +0301FC49B45A6D9026FFC01F90C7FC6D6C90B55A021F15F8020715E0020092C8FC030713 +F041437CC14A>101 DI<902607FF80EB1FFFB691B512F0040714FC041F14FF4C8193267FE07F7F9227 +81FE001F7FC6DA83F86D7F6DD987F07F6DD98FC0814C7F039FC78015BE03BC8003FC825D +A25DA25DA45DB3B2B7D8F007B71280A651417BC05A>110 D114 D<913A3FFF8007800107B5EAF81F011FECFE7F017F91B5FC48B8FC48EB +E0014890C7121FD80FFC1407D81FF0801600485A007F167F49153FA212FF171FA27F7F7F +6D92C7FC13FF14E014FF6C14F8EDFFC06C15FC16FF6C16C06C16F06C826C826C826C8201 +3F1680010F16C01303D9007F15E0020315F0EC001F1500041F13F81607007C150100FC81 +177F6C163FA2171F7EA26D16F0A27F173F6D16E06D157F6D16C001FEEDFF806D02031300 +02C0EB0FFE02FCEB7FFC01DFB65A010F5DD8FE0315C026F8007F49C7FC48010F13E03543 +7BC140>I E /Fc 2 51 df<13E01201120712FF12F91201B3A7487EB512C0A212217AA0 +1E>49 DI E /Fd 3 123 +df<000F13FC381FC3FF3931C707803861EC0301F813C0EAC1F0A213E03903C00780A3EC +0F00EA0780A2EC1E041506D80F00130C143C15181538001EEB1C70EC1FE0000CEB07801F +177D9526>110 D<3801F01E3907FC7F80390E1CE1C038180F8100301383007013071260 +EC0380D8001EC7FCA45BA21580003014C0397878018012F8EC030038F0FC0638E19C1C38 +7F0FF8381E03E01A177D9523>120 D122 D E /Fe 2 +49 df0 D48 D +E /Ff 9 62 df<123C127E12FFA7127EA9123CAA1218A41200A7123C127E12FFA4127E12 +3C082F7AAE14>33 D<13031307130E131C1338137013F0EA01E013C01203EA0780A2EA0F +00A2121EA35AA45AA512F8A25AAB7EA21278A57EA47EA37EA2EA0780A2EA03C0120113E0 +EA00F013701338131C130E1307130310437AB11B>40 D<12C07E12707E7E7E120FEA0780 +120313C0EA01E0A2EA00F0A21378A3133CA4131EA5131FA2130FAB131FA2131EA5133CA4 +1378A313F0A2EA01E0A2EA03C013801207EA0F00120E5A5A5A5A5A10437CB11B>I43 D48 +D<130C133C137CEA03FC12FFEAFC7C1200B3B113FE387FFFFEA2172C7AAB23>III61 +D E /Fg 9 115 df58 D80 D<003FBA12E0A59026FE000FEB8003D87FE0 +9338003FF049171F90C71607A2007E1803007C1801A300781800A400F819F8481978A5C8 +1700B3B3A20107B8FCA545437CC24E>84 D101 DI104 D<90277F8007FEEC0FFCB590263F +FFC090387FFF8092B5D8F001B512E002816E4880913D87F01FFC0FE03FF8913D8FC00FFE +1F801FFC0003D99F009026FF3E007F6C019E6D013C130F02BC5D02F86D496D7EA24A5D4A +5DA34A5DB3A7B60081B60003B512FEA5572D7CAC5E>109 D111 D<90387F807FB53881FFE0028313F0028F13F8ED8F +FC91389F1FFE000313BE6C13BC14F8A214F0ED0FFC9138E007F8ED01E092C7FCA35CB3A5 +B612E0A5272D7DAC2E>114 D E /Fh 2 50 df0 +D49 D E /Fi 8 89 df<151E153E157C15F8EC01F0EC03E0 +1407EC0FC0EC1F8015005C147E5CA2495A495AA2495AA2495AA2495AA249C7FCA2137EA2 +13FE5B12015BA212035BA21207A25B120FA35B121FA45B123FA548C8FCA912FEB3A8127F +A96C7EA5121F7FA4120F7FA312077FA21203A27F1201A27F12007F137EA27FA26D7EA26D +7EA26D7EA26D7EA26D7E6D7EA2147E80801580EC0FC0EC07E01403EC01F0EC00F8157C15 +3E151E1F94718232>16 D<12F07E127C7E7E6C7E7F6C7E6C7E12017F6C7E137EA27F6D7E +A26D7EA26D7EA26D7EA26D7EA26D7EA280147E147F80A21580141FA215C0A2140F15E0A3 +140715F0A4140315F8A5EC01FCA9EC00FEB3A8EC01FCA9EC03F8A515F01407A415E0140F +A315C0141FA21580A2143F1500A25C147E14FE5CA2495AA2495AA2495AA2495AA2495AA2 +49C7FC137EA25B485A5B1203485A485A5B48C8FC123E5A5A5A1F947D8232>I<160F161F +163E167C16F8ED01F0ED03E0ED07C0150FED1F801600153E157E5D4A5A5D14034A5A5D14 +0F4A5AA24AC7FC143E147E5CA2495AA2495AA2495AA2130F5CA2495AA2133F91C8FCA25B +137E13FEA25B1201A25B1203A35B1207A35B120FA35BA2121FA45B123FA690C9FC5AAA12 +FEB3AC127FAA7E7FA6121F7FA4120FA27FA312077FA312037FA312017FA212007FA2137E +137F7FA280131FA26D7EA2801307A26D7EA26D7EA26D7EA2147E143E143F6E7EA26E7E14 +07816E7E1401816E7E157E153E811680ED0FC01507ED03E0ED01F0ED00F8167C163E161F +160F28C66E823D>I<12F07E127C7E7E6C7E6C7E6C7E7F6C7E1200137C137E7F6D7E130F +806D7E1303806D7EA26D7E147C147E80A26E7EA26E7EA26E7EA2811403A26E7EA2811400 +A281157E157FA2811680A2151F16C0A3150F16E0A3150716F0A31503A216F8A4150116FC +A6150016FEAA167FB3AC16FEAA16FC1501A616F81503A416F0A21507A316E0150FA316C0 +151FA31680153FA216005DA2157E15FE5DA214015DA24A5AA214075DA24A5AA24A5AA24A +C7FCA2147E147C14FC495AA2495A5C1307495A5C131F49C8FC137E137C5B1201485A5B48 +5A485A48C9FC123E5A5A5A28C67E823D>I32 D<12F07E127C7E123F7E6C +7E6C7E6C7E7F12016C7E7F137E133E133F6D7E130F806D7EA26D7E80130180130080147E +147F8081141F81140F81140781A2140381140181A2140081A2157FA36F7EA382151FA282 +150FA3821507A382A21503A282A31501A282A31500A382A482A21780A7163F17C0AC161F +17E0B3B3A217C0163FAC1780167FA71700A25EA45EA31501A35EA21503A35EA21507A25E +A3150F5EA3151F5EA2153F5EA34BC7FCA315FEA25D1401A25D14035D1407A25D140F5D14 +1F5D143F92C8FC5C147E14FE5C13015C13035C495AA2495A5C131F49C9FC133E137E5B5B +485A12035B485A485A48CAFC5A123E5A5A5A2BF87E8242>I80 +D88 +D E /Fj 8 106 df<007FB912E0BA12F0A26C18E03C04789A4D>0 +D<121FEA3F80EA7FC0EAFFE0A5EA7FC0EA3F80EA1F000B0B789E1C>I<0060160600F816 +0F6C161F007E163F6C167E6C6C15FC6C6CEC01F86C6CEC03F06C6CEC07E06C6CEC0FC06C +6CEC1F80017EEC3F006D147E6D6C5B6D6C485A6D6C485A6D6C485A6D6C485A6D6C485ADA +7E3FC7FCEC3F7E6E5A6E5A6E5AA24A7E4A7EEC3F7EEC7E3F4A6C7E49486C7E49486C7E49 +486C7E49486C7E49486C7E49C7127E017E8049EC1F804848EC0FC04848EC07E04848EC03 +F04848EC01F84848EC00FC48C9127E007E163F48161F48160F00601606303072B04D>I< +127012FCB4FCEA7FC0EA1FF0EA07FCEA01FF38007FC0EB1FF0EB07FCEB01FF9038007FC0 +EC1FF0EC07FC913801FF809138007FE0ED1FF8ED07FE923800FF80EE3FE0EE0FF8EE03FE +933800FF80EF3FE0EF0FF8EF03FE943800FF80F03FE0F00FF0A2F03FE0F0FF80943803FE +00EF0FF8EF3FE0EFFF80DC03FEC7FCEE0FF8EE3FE0EEFF80DB03FEC8FCED1FF8ED7FE091 +3801FF80DA07FEC9FCEC1FF0EC7FC04948CAFCEB07FCEB1FF0EB7FC04848CBFCEA07FCEA +1FF0EA7FC048CCFC12FC1270CDFCB0007FB912E0BA12F0A26C18E03C4E78BE4D>21 +D<037FB612E00207B712F0143F91B812E0010301C0C9FCD907FCCAFCEB0FE0EB3F8049CB +FC13FC485A485A485A5B485A121F90CCFC123EA2123C127CA2127812F8A25AA87EA21278 +127CA2123C123EA27E7F120F6C7E7F6C7E6C7E6C7E137E6D7EEB1FE0EB07FC6DB47E0100 +90B712E0023F16F01407020016E03C3A78B54D>26 D<92B6FC02071580143F91B7120001 +030180C8FCD907FCC9FCEB1FE0EB3F80017ECAFC5B485A485A485A5B485A121F90CBFC12 +3EA2123C127CA2127812F8A25AA2B9FC1880A2180000F0CBFCA27EA21278127CA2123C12 +3EA27E7F120F6C7E7F6C7E6C7E6C7E137E6D7EEB1FE0EB07FC6DB47E010090B6FC023F15 +80140702001500313A78B542>50 D<140C141E143EA2143C147CA214F8A214F01301A2EB +03E0A214C01307A2EB0F80A214005BA2133EA2133C137CA2137813F8A2485AA25B1203A2 +485AA25B120FA248C7FCA2121E123EA25AA2127812F8A41278127CA27EA2121E121FA26C +7EA212077FA26C7EA212017FA26C7EA21378137CA2133C133EA27FA27F1480A2EB07C0A2 +130314E0A2EB01F0A2130014F8A2147CA2143C143EA2141E140C176476CA27>104 +D<126012F07EA21278127CA27EA2121E121FA26C7EA212077FA26C7EA212017FA26C7EA2 +1378137CA2133C133EA27FA27F1480A2EB07C0A2130314E0A2EB01F0A2130014F8A2147C +A2143C143EA4143C147CA214F8A214F01301A2EB03E0A214C01307A2EB0F80A214005BA2 +133EA2133C137CA2137813F8A2485AA25B1203A2485AA25B120FA248C7FCA2121E123EA2 +5AA2127812F8A25A126017647BCA27>I E /Fk 10 123 df<123C127EB4FCA21380A212 +7F123D1201A312031300A25A1206120E5A5A5A126009157A8714>59 +D<90383FFFFEA2010090C8FC5C5CA21301A25CA21303A25CA21307A25CA2130FA25CA213 +1FA25CA2133FA291C7EA0180A24914031700017E5C160601FE140EA2495C163C12015E49 +EB01F84B5A0003141FB7FC5E292D7DAC30>76 D<151FEC03FFA2EC003FA2153EA2157EA2 +157CA215FCA215F8A21401EB07E190381FF9F0EB7C1DEBF80FEA01F03903E007E0EA07C0 +120FEA1F8015C0EA3F00140F5A007E1480A2141F12FE481400A2EC3F021506143E5AEC7E +0E007CEBFE0C14FC0101131C393E07BE18391F0E1E38390FFC0FF03903F003C0202F7DAD +24>100 D<15E0EC01F01403A3EC01C091C7FCA9147CEB03FE9038078F80EB0E07131C01 +3813C01330EB700F0160138013E013C0EB801F13001500A25CA2143EA2147EA2147CA214 +FCA25CA21301A25CA21303A25CA2130700385BEAFC0F5C49C7FCEAF83EEAF0F8EA7FF0EA +1F801C3B81AC1D>106 D<27078007F0137E3C1FE01FFC03FF803C18F0781F0783E03B38 +78E00F1E01263079C001B87F26707F8013B00060010013F001FE14E000E015C0485A4914 +800081021F130300015F491400A200034A13076049133E170F0007027EEC808018814901 +7C131F1801000F02FCEB3F03053E130049495C180E001F0101EC1E0C183C010049EB0FF0 +000E6D48EB03E0391F7E9D3E>109 D<3907C007E0391FE03FF83918F8783E393879E01E +39307B801F38707F00126013FEEAE0FC12C05B00815C0001143E5BA20003147E157C5B15 +FC0007ECF8081618EBC00115F0000F1538913803E0300180147016E0001F010113C015E3 +90C7EAFF00000E143E251F7E9D2B>I<130E131FA25BA2133EA2137EA2137CA213FCA2B5 +12F8A23801F800A25BA21203A25BA21207A25BA2120FA25BA2001F131014301300147014 +6014E0381E01C0EB0380381F0700EA0F0EEA07FCEA01F0152B7EA919>116 +D<013F137C9038FFC1FF3A01C1E383803A0380F703C0390700F60F000E13FE4813FC1218 +0038EC0700003049C7FCA2EA200100005BA313035CA301075B5D14C000385CD87C0F1306 +00FC140E011F130C011B131C39F03BE038D8707113F0393FE0FFC0260F803FC7FC221F7E +9D28>120 DI<011E1330EB3F809038FFC07048EBE0E0ECF1C03803C0FF9038803F80903800070048 +130EC75A5C5C5C495A495A49C7FC131E13385B491340484813C0485A38070001000EEB03 +80380FE007391FF81F0038387FFF486C5A38601FFC38E00FF038C003C01C1F7D9D21>I +E /Fl 19 123 df<121EEA7F8012FF13C0A213E0A3127FEA1E601200A413E013C0A31201 +1380120313005A1206120E5A5A5A12600B1D78891B>59 D64 D<4CB46C1318043F01F013384BB512 +FC0307D9007E1378DB1FF090380F80F0DB7F80EB03C1DA01FEC7EA01C34A48EC00E7DA0F +F0ED7FE04A48153F4A5A02FFC9121F494817C04948160F495A130F4A178049481607495A +137F4948170091CAFC5A485A1906485AA2485A96C7FC121F5BA2123F5BA3127F5BA4485A +A419C0A2180161127F180396C7FC6018066C6C160E601818001F17386D5E000F5F6D4B5A +6C6C4B5A00034CC8FC6C6C150E6C6C153C017F5DD93FC0EB01E0D91FF0EB0FC0D907FE01 +7FC9FC0101B512FCD9003F13E0020790CAFC45487CC546>67 D<91B912F8A3020001C0C7 +123F6F48EC07F003FF1503190193C9FCA21A705C5DA3020317605DA314075D18C0170102 +0F4B13005DA21703021F92C8FC4B5BA25F023F141E4B13FE92B5FCA24A5CED8000173CA2 +02FF141892C7FCA217384915305CA21770010315604A91C9FCA313075CA3130F5CA3131F +5CA2133FA313FFB612F8A345447CC33F>70 D<4CB46C1318043F01F013384BB512FC0307 +D9007E1378DB1FF090380F80F0DB7F80EB03C1DA01FEC7EA01C34A48EC00E7DA0FF0ED7F +E04A48153F4A5A02FFC9121F494817C04948160F495A130F4A178049481607495A137F49 +48170091CAFC5A485A1906485AA2485A96C7FC121F5BA2123F5BA3127F5BA4485A4CB612 +805EA293C7EBE000725AA3007F60A218FF96C7FCA26C7E5F606C7EA2000F16036D5E6C6C +15070003160F6C6C151F6C6CED3DF8D97F8014786D6CEB01E0D91FF0903807C078D907FE +90387F00700101B500FC1330D9003F01F090C8FC020790CAFC45487CC54D>I<91B6D8E0 +03B61280A3020001E0C70003EB8000DB7F806E48C7FC03FF1503A293C85BA219075C4B5E +A2190F14034B5EA2191F14074B5EA2193F140F4B5EA2197F141F4B5EA219FF143F92B8C8 +FCA3DA7FC0C712014B5DA2180314FF92C85BA218075B4A5EA2180F13034A5EA2181F1307 +4A5EA2183F130F4A5EA2187F131F4A5EA2013F16FFA24A93C9FCD9FFE002037FB6D8E003 +B67EA351447CC351>I<91B612F8A3020001E0C8FC6F5A4B5AA293C9FCA35C5DA314035D +A314075DA3140F5DA3141F5DA3143F5DA3147F5DA314FF92CAFCA35B4A16C0A218010103 +17804A15031900A201075E4A1506180E181E010F161C4A153C18381878011F16F84A4A5A +1703013F150F4D5A4A14FF01FF02075BB9FCA2603A447CC342>76 +D<91B500C0933803FFFE63630200F1FE00DB6FE0EE1BF803EF171F1B3703CFEF67F0A21B +CF0201EF018F038F60DB87F0ED030F1B1F020317060307040C5BA2F2183F020717300206 +616F6C15601B7F020E17C0020CDC018090C7FCA24F485A021C16060218606F6C5C1A0102 +381618023004305BA2F16003027016C00260606F6CEB01801A0702E0ED03004A03065CA2 +4E130F01015E4A60047F5B1A1F01035E91C74A5CA24D48133F494BC7FC010661EE3F861A +7F010E158C010C039892C8FCA205B05C011C15E001186001386E5A190101785D01FC92C7 +5BD803FFEF07FEB500F8011E0107B512FE161C160C5F447BC35E>I<91B712FEF0FFE019 +F802009039C0000FFE6F48EB01FF03FF9138007F80F13FC093C8EA1FE0A24AEE0FF0A25D +1AF81403A25DA21407F11FF05DA2020FEE3FE0A24B16C0197F021F1780F1FF004B4A5A4E +5A023F4B5A4E5A4BEC3FC006FFC7FC027FEC07FC92B612F018800380CAFC14FFA292CBFC +A25BA25CA21303A25CA21307A25CA2130FA25CA2131FA25CA2133FA25CEBFFE0B612E0A3 +45447CC33F>80 DI<91B712F018FF19E00200 +9039C0003FF86F48EB07FC03FFEC01FEF0007F93C8EA3F801AC0F11FE05C5D1AF0A21403 +5DA30207EE3FE05DA2F17FC0020F17804B15FF1A004E5A021F4B5A4B4A5AF00FE04E5A02 +3F037FC7FC4BEB03FCEF1FF092B612804A4AC8FC923980007F80EF0FC0EF07F002FF6E7E +92C77F1701845B4A1400A2170113035CA2170313075CA24D5A130F5CA3011F18185CA201 +3F4C13381A304A6F1370D9FFE0020314E0B600E0ED01C00501EB0380943900FE0F00CBEA +3FFEF007F045467CC34A>I100 DI<01F8D903FCEC7F +80D803FED91FFF903803FFE0D8071F903B7C0FC00F81F83E0E0F80E007E01C00FC001C90 +26C3C0030178137C271807C700D9F0E0137E02CE902601F1C0133E003801DCDAFB80133F +003001D892C7FCD90FF814FF0070495C0060495CA200E04949485CD8C01F187E4A5C1200 +040715FE013F6091C75BA2040F14014960017E5D1903041F5D13FE494B130762043F160E +0001060F130C4992C713C0191F4CED801C00031A1849027E1638F2003004FE167000071A +60494A16E0F201C0030192380F0380000FF18700494AEC03FED80380D90070EC00F84F2D +7DAB55>109 D<01F8EB03FCD803FEEB1FFFD8071F90387C0FC03B0E0F80E007E03A0C07 +C3C003001CD9C7007F001801CE1301003801DC80003013D8EB0FF800705B00605BA200E0 +491303D8C01F5D5C12001607013F5D91C7FCA2160F495D137E161F5F13FE49143F94C7FC +187000014B136049147E16FE4C13E0000317C049150104F81380170300071700495D170E +EE781C000FED7C3849EC1FF0D80380EC07C0342D7DAB3A>I<141C147EA314FE5CA31301 +5CA313035CA313075CA2007FB512FCB6FC15F839000FC000A2131F5CA3133F91C7FCA35B +137EA313FE5BA312015BA312035BA21570000714605B15E015C0000F130101C013801403 +EC070000071306140E5C6C6C5A000113F03800FFC0013FC7FC1E3F7EBD23>116 +D<02FCEB07E0903A03FF801FFC903A0F07C0781E903A1C03E0E01F903A3801F1C07FD970 +0013804901FB13FF4848EBFF00495B000316FE90C71438484A130012061401000E5C120C +C7FC14035DA314075DA3140F5DA3021F143817305D1770023F1460121E003F16E0267F80 +7FEB01C0026F148000FF01EF1303D901CFEB070000FE903887C00E267C03835B3A3C0F01 +E0783A1FFC00FFE0D803F0EB3F80302D7EAB37>120 D<133ED9FF8014E02603C3C0EB03 +F0380703E0380601F0000E1507001C16E0EA180312380030150F007016C0EA60075C161F +D8E00F158000C05BEA001F4A133F1700133F91C7FC5E49147E137EA216FE01FE5C5BA215 +015E485AA215035EA200001407150F6D5C017C131F153F6D13FF90391F03CFC0903807FF +8F903801FC0F90C7121F5EA2153F93C7FCD807C05BD81FE0137E5DA24848485A4A5A0180 +5B39380007C00018495A001C49C8FC6C137C380781F83803FFE0C66CC9FC2C407DAB30> +I<027CEB018049B413034901801300010F6D5A49EBE00E6F5A90393F03F838903978007E +F80170EB1FF00160EB01E001E05C49495A90C748C7FC150E5D5D5D5D4A5A4A5A4AC8FC14 +0E5C5C5C5CEB03C049C9FC130E49141C4914185B49143848481430491470D8039014F048 +B4495A3A0FEFC007C0391E03F01FD81C01B55A486C91C7FC485C00606D5A00E0EB3FF048 +EB0FC0292D7CAB2D>I E /Fm 61 124 df<1618163CA2167EA216FFA24B7FA24B6C7EA2 +9238063FE0A24B6C7EA24B6C7EA292383807FC153092387003FE15609238E001FF15C002 +016D7F5D02036E7E92C7FC4A6E7E1406020E6E7E140C021C6E7E141802386E7E14300270 +6E7E146002E06E7E5C01016F7F5C0103707E91C9FC183F010683181F4983180F49831807 +498318034983A249707EA24848701380A248CBEA7FC0A20006F03FE0A248F01FF0A2001F +BA12F8A24819FCA24819FEA2BCFC48477CC651>1 D<9239FFC001FC020F9038F80FFF91 +3B3F803E3F03C0913BFC00077E07E0D903F890390FFC0FF0494890383FF81F4948EB7FF0 +495A494814E049C7FCF00FE04991393FC0038049021F90C7FCAFB912F0A3C648C7D81FC0 +C7FCB3B2486CEC3FF0007FD9FC0FB512E0A33C467EC539>11 D<4AB4FC020F13E091387F +80F8903901FC001C49487FD907E0130F4948137F011FECFF80495A49C7FCA25B49EC7F00 +163E93C7FCACEE3F80B8FCA3C648C7FC167F163FB3B0486CEC7FC0007FD9FC1FB5FCA330 +467EC536>I14 D<121EEA7F80EAFFC0A9EA7F80ACEA +3F00AB121EAC120CA5C7FCAA121EEA7F80A2EAFFC0A4EA7F80A2EA1E000A4778C61B>33 +D<001EEB03C0397F800FF000FF131F01C013F8A201E013FCA3007F130F391E6003CC0000 +EB000CA401E0131C491318A3000114384913300003147090C712604814E0000614C0000E +130148EB038048EB070048130E0060130C1E1D7DC431>I<121EEA7F8012FF13C0A213E0 +A3127FEA1E601200A413E013C0A312011380120313005A1206120E5A5A5A12600B1D78C4 +1B>39 D<140C141C1438147014E0EB01C01303EB0780EB0F00A2131E5BA25B13F85B1201 +5B1203A2485AA3485AA348C7FCA35AA2123EA2127EA4127CA312FCB3A2127CA3127EA412 +3EA2123FA27EA36C7EA36C7EA36C7EA212017F12007F13787FA27F7FA2EB0780EB03C013 +01EB00E014701438141C140C166476CA26>I<12C07E12707E7E7E120F6C7E6C7EA26C7E +6C7EA21378137C133C133E131E131FA2EB0F80A3EB07C0A3EB03E0A314F0A21301A214F8 +A41300A314FCB3A214F8A31301A414F0A21303A214E0A3EB07C0A3EB0F80A3EB1F00A213 +1E133E133C137C13785BA2485A485AA2485A48C7FC120E5A5A5A5A5A16647BCA26>I<16 +C04B7EB3AB007FBAFCBB1280A26C1900C8D801E0C9FCB3AB6F5A41407BB84C>43 +D<121EEA7F8012FF13C0A213E0A3127FEA1E601200A413E013C0A312011380120313005A +1206120E5A5A5A12600B1D78891B>II<121EEA7F80A2EAFFC0A4 +EA7F80A2EA1E000A0A78891B>I<14FF010713E090381F81F890383E007C01FC133F4848 +EB1F8049130F4848EB07C04848EB03E0A2000F15F0491301001F15F8A2003F15FCA390C8 +FC4815FEA54815FFB3A46C15FEA56D1301003F15FCA3001F15F8A26C6CEB03F0A36C6CEB +07E0000315C06D130F6C6CEB1F806C6CEB3F00013E137C90381F81F8903807FFE0010090 +C7FC28447CC131>48 D<143014F013011303131F13FFB5FC13E713071200B3B3B0497E49 +7E007FB6FCA3204278C131>II<49B4 +FC010F13E0013F13FC9038FE01FE3A01F0007F80D803C0EB3FC048C7EA1FE0120EED0FF0 +EA0FE0486C14F8A215077F5BA26C48130FEA03C0C813F0A3ED1FE0A2ED3FC01680ED7F00 +15FE4A5AEC03F0EC1FC0D90FFFC7FC15F090380001FCEC007FED3F80ED1FC0ED0FE016F0 +ED07F816FC150316FEA2150116FFA3121EEA7F80487EA416FE491303A2007EC713FC0070 +1407003015F80038140F6C15F06CEC1FE06C6CEB3FC0D803E0EB7F803A01FE01FE003900 +7FFFF8010F13E0010190C7FC28447CC131>II<000615C0D807C0130701FCEB +7F8090B612005D5D5D15E0158026063FFCC7FC90C9FCAE14FF010713C090381F01F09038 +3800FC01F0137ED807C07F49EB1F8016C090C7120F000615E0C8EA07F0A316F81503A216 +FCA5123E127F487EA416F890C712075A006015F0A20070140F003015E00038EC1FC07E00 +1EEC3F806CEC7F006C6C13FE6C6C485A3901F807F039007FFFE0011F90C7FCEB07F82644 +7BC131>II<121EEA7F80A2EAFFC0A4EA7F80A2EA1E +00C7FCB3A5121EEA7F80A2EAFFC0A4EA7F80A2EA1E000A2B78AA1B>58 +D<121EEA7F80A2EAFFC0A4EA7F80A2EA1E00C7FCB3A5121E127FEAFF80A213C0A4127F12 +1E1200A512011380A3120313005A1206120E120C121C5A5A12600A3E78AA1B>I<007FBA +FCBB1280A26C1900CEFCB0007FBAFCBB1280A26C190041187BA44C>61 +D66 +D68 D72 D +I76 +D79 D<49B41303010FEBE007013F +13F89039FE00FE0FD801F8131FD807E0EB079F49EB03DF48486DB4FC48C8FC4881003E81 +127E82127C00FC81A282A37E82A27EA26C6C91C7FC7F7FEA3FF813FE381FFFE06C13FE6C +EBFFE06C14FC6C14FF6C15C0013F14F0010F80010180D9001F7F14019138001FFF030313 +80816F13C0167F163F161F17E000C0150FA31607A37EA36C16C0160F7E17806C151F6C16 +006C5D6D147ED8FBC05CD8F9F0495AD8F07C495A90393FC00FE0D8E00FB51280010149C7 +FC39C0003FF02B487BC536>83 D<003FB912F8A3903BF0001FF8001F01806D481303003E +C7150048187C0078183CA20070181CA30060180CA5481806A5C81600B3B3A54B7EED7FFE +49B77EA33F447DC346>I87 D91 D<01C01318000114384848137048C712E0000EEB01C0000C14 +80001C13030018140000385B003013060070130E0060130CA300E0131C481318A400CFEB +19E039FFC01FF801E013FCA3007F130FA2003F130701C013F8390F0001E01E1D71C431> +II97 DII<167FED +3FFFA315018182B3EC7F80903803FFF090380FC07C90383F000E017E1307496D5AD803F8 +7F48487F5B000F81485AA2485AA2127FA290C8FC5AAB7E7FA2123FA26C7EA2000F5D7F6C +6C5B00035C6C6C9038077F806C6C010E13C0013F011C13FE90380FC0F8903803FFE09026 +007F0013002F467DC436>IIIIII +107 DII<3901FC01FE00 +FF903807FFC091381E07F091383801F8000701707F0003EBE0002601FDC07F5C01FF147F +91C7FCA25BA35BB3A8486CECFF80B5D8F83F13FEA32F2C7DAB36>II<3901FC03FC00FF90380FFF8091383C07E091387001F83A07FD +E000FE00010180137F01FFEC3F8091C7EA1FC04915E049140F17F0160717F8160317FCA3 +EE01FEABEE03FCA3EE07F8A217F0160F6D15E0EE1FC06D143F17806EEB7E00D9FDC05B90 +39FCF003F891383C0FE091381FFF80DA03FCC7FC91C9FCAE487EB512F8A32F3F7DAB36> +I<91387F8003903903FFE00790380FE07890393F801C0F90387E000E496D5AD803F8EB03 +9F0007EC01BF4914FF48487F121F5B003F81A2485AA348C8FCAB6C7EA3123F7F121F6D5C +120F6D5B12076C6C5B6C6C497E6C6C130E013F131C90380FC0F8903803FFE09038007F00 +91C7FCAEEEFF80033F13FEA32F3F7DAB33>I<3903F803F000FFEB1FFCEC3C3EEC707F00 +07EBE0FF3803F9C000015B13FBEC007E153C01FF13005BA45BB3A748B4FCB512FEA3202C +7DAB26>I<90383FE0183901FFFC383907E01F78390F0003F8001E1301481300007C1478 +127800F81438A21518A27EA27E6C6C13006C7E13FC383FFFE06C13FC6C13FF6C14C06C14 +E0C614F0011F13F81300EC0FFC140300C0EB01FE1400157E7E153EA27EA36C143C6C147C +15786C14F86CEB01F039F38003E039F1F00F8039E07FFE0038C00FF01F2E7DAC26>I<13 +06A5130EA4131EA3133E137EA213FE12011207001FB512F0B6FCA2C648C7FCB3A4150CAA +017E131C017F1318A26D133890381F8030ECC070903807E0E0903801FFC09038007F001E +3E7EBC26>IIIIII<003FB612 +E0A29038C0003F90C713C0003CEC7F800038ECFF00A20030495A0070495AA24A5A006049 +5AA24A5A4A5AA2C7485A4AC7FC5B5C495A13075C495A131F4A1360495A495AA249C712C0 +485AA2485A485A1501485A48481303A24848EB07804848131F00FF14FF90B6FCA2232B7D +AA2B>II E end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: a4 +%%BeginPaperSize: a4 +a4 +%%EndPaperSize + +%%EndSetup +%%Page: 1 1 +1 0 bop 404 573 a Fm(The)33 b(Laguerre)g(p)s(olynomials)c +Fl(L)1620 588 y Fk(n)1668 573 y Fm(\()p Fl(x)p Fm(\))k(are)f(de\014ned) +i(through)1286 851 y Fl(L)1352 866 y Fk(n)1400 851 y +Fm(\()p Fl(x)p Fm(\))28 b(=)f Fl(e)1707 809 y Fk(x)1773 +851 y Fj(\001)1823 704 y Fi( )1926 783 y Fl(d)p 1899 +827 107 4 v 1899 919 a(dx)2015 704 y Fi(!)2081 727 y +Fk(n)2144 851 y Fm(\()p Fl(x)2237 809 y Fk(n)2285 851 +y Fl(e)2330 809 y Fh(\000)p Fk(x)2428 851 y Fm(\))257 +1128 y Fg(Theorem:)404 1348 y Fl(L)470 1363 y Fk(n)517 +1348 y Fm(\()p Fl(x)p Fm(\))33 b(satis\014es)g(the)g(recurrence)i +(relation)1668 1586 y Fl(L)1734 1601 y Ff(0)1774 1586 +y Fm(\()p Fl(x)p Fm(\))28 b(=)f(1)907 1917 y Fl(L)973 +1932 y Fk(n)p Ff(+1)1111 1917 y Fm(\()p Fl(x)p Fm(\))h(=)f(\(2)p +Fl(n)22 b Fm(+)h(1)e Fj(\000)i Fl(x)p Fm(\))g Fj(\001)e +Fl(L)2040 1932 y Fk(n)2088 1917 y Fm(\()p Fl(x)p Fm(\))h +Fj(\000)h Fl(n)2399 1876 y Ff(2)2461 1917 y Fj(\001)e +Fl(L)2576 1932 y Fk(n)p Fh(\000)p Ff(1)2714 1917 y Fm(\()p +Fl(x)p Fm(\))257 2130 y(for)k Fl(n)j Fj(\025)g Fm(0)e(and)g(the)g +(di\013eren)m(tial)d(equation)j Fl(x)8 b Fj(\001)g Fl(L)2046 +2070 y Fe(00)2046 2155 y Fk(n)2093 2130 y Fm(\()p Fl(x)p +Fm(\))g(+)g(\(1)g Fj(\000)g Fl(x)p Fm(\))g Fj(\001)g +Fl(L)2699 2070 y Fe(0)2699 2155 y Fk(n)2746 2130 y Fm(\()p +Fl(x)p Fm(\))g(+)g Fl(n)g Fj(\001)g Fl(L)3137 2145 y +Fk(n)3184 2130 y Fm(\()p Fl(x)p Fm(\))28 b(=)f(0)257 +2250 y(for)32 b(all)f Fl(n)d Fj(\025)g Fm(0.)257 2471 +y Fg(Pro)s(of:)404 2691 y Fm(Let)41 b Fl(F)55 b Fm(:=)850 +2625 y Fi(P)937 2651 y Fh(1)937 2716 y Fk(n)p Ff(=0)1101 +2645 y Fk(L)1149 2653 y Fd(n)1191 2645 y Ff(\()p Fk(x)p +Ff(\))p 1101 2668 186 4 v 1162 2726 a Fk(n)p Ff(!)1324 +2691 y Fj(\001)27 b Fl(z)1428 2655 y Fk(n)1517 2691 y +Fm(b)s(e)41 b(the)g(exp)s(onen)m(tial)f(generating)g(function)g(of)h +(the)257 2812 y(sequence)36 b(of)c(p)s(olynomials.)40 +b(It)33 b(is)f(the)h(diagonal)d(series)j(of)f(the)h(p)s(o)m(w)m(er)h +(series)950 3084 y Fl(G)27 b Fm(:=)1257 2976 y Fh(1)1232 +3001 y Fi(X)1185 3182 y Fk(m;n)p Ff(=0)1458 3016 y Fm(1)p +1426 3061 113 4 v 1426 3152 a Fl(m)p Fm(!)1571 3084 y +Fj(\001)22 b Fl(e)1666 3043 y Fk(x)1732 3084 y Fj(\001)1782 +2938 y Fi( )1885 3016 y Fl(d)p 1857 3061 107 4 v 1857 +3152 a(dx)1974 2938 y Fi(!)2039 2961 y Fk(m)2122 3084 +y Fm(\()p Fl(x)2215 3043 y Fk(n)2263 3084 y Fl(e)2308 +3043 y Fh(\000)p Fk(x)2407 3084 y Fm(\))g Fj(\001)g Fl(y)2569 +3043 y Fk(m)2657 3084 y Fj(\001)f Fl(z)2755 3043 y Fk(n)257 +3373 y Fm(Because)34 b(the)f(T)-8 b(a)m(ylor)31 b(series)i(dev)m +(elopmen)m(t)g(theorem)f(holds)f(in)h(formal)d(p)s(o)m(w)m(er)34 +b(series)257 3494 y(rings)e(\(see)i([1],)f(section)f(2.16\),)g(w)m(e)i +(can)f(simplify)798 3771 y Fl(G)83 b Fm(=)g Fl(e)1162 +3730 y Fk(x)1229 3771 y Fj(\001)1310 3664 y Fh(1)1285 +3688 y Fi(X)1278 3870 y Fk(n)p Ff(=0)1428 3625 y Fi( )1535 +3664 y Fh(1)1510 3688 y Fi(X)1494 3870 y Fk(m)p Ff(=0)1705 +3704 y Fm(1)p 1673 3748 113 4 v 1673 3840 a Fl(m)p Fm(!)1817 +3771 y Fj(\001)1867 3625 y Fi( )1971 3704 y Fl(d)p 1943 +3748 107 4 v 1943 3840 a(dx)2059 3625 y Fi(!)2125 3648 +y Fk(m)2208 3771 y Fm(\()p Fl(x)2301 3730 y Fk(n)2348 +3771 y Fl(e)2393 3730 y Fh(\000)p Fk(x)2492 3771 y Fm(\))22 +b Fj(\001)g Fl(y)2654 3730 y Fk(m)2720 3625 y Fi(!)2808 +3771 y Fj(\001)f Fl(z)2906 3730 y Fk(n)958 4056 y Fm(=)83 +b Fl(e)1162 4015 y Fk(x)1229 4056 y Fj(\001)1310 3948 +y Fh(1)1285 3973 y Fi(X)1278 4154 y Fk(n)p Ff(=0)1411 +4056 y Fm(\()p Fl(x)23 b Fm(+)f Fl(y)t Fm(\))1715 4015 +y Fk(n)1761 4056 y Fl(e)1806 4015 y Fh(\000)p Ff(\()p +Fk(x)p Ff(+)p Fk(y)r Ff(\))2074 4056 y Fj(\001)g Fl(z)2173 +4015 y Fk(n)958 4339 y Fm(=)1318 4272 y Fl(e)1363 4236 +y Fh(\000)p Fk(y)p 1127 4316 523 4 v 1127 4408 a Fm(1)g +Fj(\000)h Fm(\()p Fl(x)f Fm(+)g Fl(y)t Fm(\))p Fl(z)257 +4608 y Fm(W)-8 b(e)30 b(tak)m(e)f(o)m(v)m(er)h(the)g(terminology)c +(from)i(the)h(\\diag)p 2160 4608 30 4 v 34 w(rational")d(pap)s(er;)k +(here)g Fl(R)f Fm(=)e Fl(Q)p Fm([)p Fl(x)p Fm(])257 4729 +y(and)h Fl(M)38 b Fm(=)28 b Fl(Q)p Fm([[)p Fl(x)p Fm(]])g(\(or,)h(if)d +(y)m(ou)i(lik)m(e)f(it)f(b)s(etter,)j Fl(M)39 b Fm(=)27 +b Fl(H)8 b Fm(\()p Fl(C)f Fm(\),)28 b(the)g(algebra)e(of)h(functions) +257 4849 y(holomorphic)44 b(in)g(the)j(en)m(tire)e(complex)g(plane\).) +82 b Fl(G)50 b Fj(2)h Fl(M)10 b Fm([[)p Fl(y)t(;)17 b(z)t +Fm(]])46 b(is)f(not)h(rational;)257 4969 y(nev)m(ertheless)e(w)m(e)e +(can)f(pro)s(ceed)h(similarly)37 b(to)k(the)h(\\diag)p +2464 4969 V 33 w(series")g(pap)s(er.)69 b Fl(F)14 b Fm(\()p +Fl(z)3311 4933 y Ff(2)3351 4969 y Fm(\))41 b(is)257 5090 +y(the)33 b(co)s(e\016cien)m(t)h(of)e Fl(t)1027 5054 y +Ff(0)1099 5090 y Fm(in)830 5335 y Fl(G)p Fm(\()p Fl(z)t(t;)1084 +5268 y(z)p 1084 5312 50 4 v 1091 5404 a(t)1143 5335 y +Fm(\))c(=)1478 5268 y Fl(e)1523 5232 y Fh(\000)p Fk(z)s(t)p +1323 5312 477 4 v 1323 5404 a Fm(1)21 b Fj(\000)i Fl(z)1542 +5375 y Ff(2)1604 5404 y Fj(\000)1714 5364 y Fk(xz)p 1714 +5380 76 4 v 1739 5438 a(t)1837 5335 y Fj(2)28 b Fl(M)10 +b Fm([[)p Fl(z)t(t;)2229 5268 y(z)p 2229 5312 50 4 v +2236 5404 a(t)2288 5335 y(;)17 b(z)t Fm(]])29 b(=)e Fl(M)10 +b Fj(h)-17 b(h)p Fl(z)t(;)17 b(t)p Fj(i)-17 b(i)1852 +5637 y Fm(1)p eop +%%Page: 2 2 +2 1 bop 257 573 a Fm(The)34 b(denominator's)e(only)g(zero)h(is)f +Fl(t)c Fm(=)1830 534 y Fk(xz)p 1787 550 161 4 v 1787 +607 a Ff(1)p Fh(\000)p Fk(z)1913 588 y Fc(2)1957 573 +y Fm(.)44 b(W)-8 b(e)33 b(can)g(write)1048 829 y Fl(e)1093 +788 y Fh(\000)p Fk(z)s(t)1241 829 y Fm(=)28 b Fl(e)1390 +776 y Fh(\000)1477 749 y Fd(xz)1544 728 y Fc(2)p 1455 +761 145 4 v 1455 811 a(1)p Fe(\000)p Fd(z)1565 797 y +Fc(2)1636 829 y Fm(+)1734 683 y Fi( )1799 829 y Fl(z)t(t)c +Fj(\000)2074 761 y Fl(xz)2178 725 y Ff(2)p 2016 806 260 +4 v 2016 897 a Fm(1)e Fj(\000)h Fl(z)2236 868 y Ff(2)2286 +683 y Fi(!)2374 829 y Fj(\001)e Fl(P)14 b Fm(\()p Fl(z)t(;)j(t)p +Fm(\))257 1088 y(with)47 b Fl(P)14 b Fm(\()p Fl(z)t(;)j(t)p +Fm(\))52 b Fj(2)g Fl(Q)p Fm([[)p Fl(z)t(t;)1240 1049 +y Fk(xz)1316 1026 y Fc(2)p 1215 1065 161 4 v 1215 1123 +a Ff(1)p Fh(\000)p Fk(z)1341 1104 y Fc(2)1385 1088 y +Fm(]])h Fj(\032)f Fl(Q)p Fm([[)p Fl(z)t(t;)17 b(x;)g(z)t +Fm(]])54 b(=)e Fl(M)10 b Fm([[)p Fl(z)t(t;)17 b(z)t Fm(]])54 +b Fj(\032)f Fl(M)10 b Fj(h)-17 b(h)p Fl(z)t(;)17 b(t)p +Fj(i)-17 b(i)p Fm(.)87 b(This)257 1209 y(yields)33 b({)f(all)e +(computations)i(b)s(eing)g(done)h(in)f Fl(M)10 b Fj(h)-17 +b(h)p Fl(z)t(;)17 b(t)p Fj(i)-17 b(i)33 b Fm({)534 1499 +y Fl(G)p Fm(\()p Fl(z)t(t;)787 1432 y(z)p 787 1476 50 +4 v 794 1567 a(t)847 1499 y Fm(\))83 b(=)1241 1432 y +Fl(e)1286 1379 y Fh(\000)1372 1352 y Fd(xz)1439 1331 +y Fc(2)p 1351 1364 145 4 v 1351 1414 a(1)p Fe(\000)p +Fd(z)1461 1400 y Fc(2)p 1137 1476 477 4 v 1137 1567 a +Fm(1)22 b Fj(\000)g Fl(z)1356 1539 y Ff(2)1419 1567 y +Fj(\000)1528 1528 y Fk(xz)p 1528 1544 76 4 v 1553 1602 +a(t)1646 1499 y Fm(+)1841 1432 y Fl(z)t(t)p 1753 1476 +260 4 v 1753 1567 a Fm(1)g Fj(\000)h Fl(z)1973 1539 y +Ff(2)2045 1499 y Fj(\001)f Fl(P)14 b Fm(\()p Fl(z)t(;)j(t)p +Fm(\))968 1780 y(=)1242 1712 y(1)p 1137 1756 V 1137 1848 +a(1)22 b Fj(\000)g Fl(z)1356 1819 y Ff(2)1428 1780 y +Fj(\001)g Fl(e)1523 1727 y Fh(\000)1610 1700 y Fd(xz)1677 +1679 y Fc(2)p 1588 1712 145 4 v 1588 1762 a(1)p Fe(\000)p +Fd(z)1698 1748 y Fc(2)1769 1780 y Fj(\001)1845 1672 y +Fh(1)1820 1697 y Fi(X)1819 1879 y Fk(j)t Ff(=0)1958 1658 +y Fi(\022)2131 1712 y Fl(x)p 2029 1756 260 4 v 2029 1848 +a Fm(1)g Fj(\000)h Fl(z)2249 1819 y Ff(2)2309 1712 y +Fl(z)p 2309 1756 50 4 v 2316 1848 a(t)2369 1658 y Fi(\023)2430 +1681 y Fk(j)2488 1780 y Fm(+)2684 1712 y Fl(z)t(t)p 2596 +1756 260 4 v 2596 1848 a Fm(1)f Fj(\000)h Fl(z)2816 1819 +y Ff(2)2888 1780 y Fj(\001)f Fl(P)14 b Fm(\()p Fl(z)t(;)j(t)p +Fm(\))257 2044 y(Here,)34 b(the)f(co)s(e\016cien)m(t)g(of)f +Fl(t)1284 2008 y Ff(0)1356 2044 y Fm(is)1380 2262 y Fl(F)14 +b Fm(\()p Fl(z)1544 2220 y Ff(2)1583 2262 y Fm(\))28 +b(=)1868 2194 y(1)p 1763 2238 V 1763 2330 a(1)21 b Fj(\000)i +Fl(z)1982 2301 y Ff(2)2054 2262 y Fj(\001)f Fl(e)2149 +2209 y Fh(\000)2236 2182 y Fd(xz)2303 2161 y Fc(2)p 2214 +2194 145 4 v 2214 2244 a(1)p Fe(\000)p Fd(z)2324 2230 +y Fc(2)257 2473 y Fm(hence)1436 2613 y Fl(F)14 b Fm(\()p +Fl(z)t Fm(\))28 b(=)1866 2545 y(1)p 1780 2589 221 4 v +1780 2681 a(1)22 b Fj(\000)g Fl(z)2032 2613 y Fj(\001)g +Fl(e)2127 2569 y Fh(\000)2214 2542 y Fd(xz)p 2192 2554 +111 4 v 2192 2595 a Fc(1)p Fe(\000)p Fd(z)404 2818 y +Fm(It)33 b(follo)m(ws)f(that)h(\(1)22 b Fj(\000)h Fl(z)t +Fm(\))1339 2782 y Ff(2)1402 2818 y Fj(\001)1480 2779 +y Fk(d)p 1462 2795 72 4 v 1462 2853 a(dz)1544 2818 y +Fl(F)36 b Fj(\000)23 b Fm(\(1)g Fj(\000)g Fl(x)g Fj(\000)g +Fl(z)t Fm(\))g Fj(\001)f Fl(F)43 b Fm(=)28 b(0.)45 b(This)34 +b(is)f(equiv)-5 b(alen)m(t)33 b(to)257 2939 y(the)g(claimed)e +(recurrence.)404 3059 y(Starting)e(from)h(the)h(closed)g(form)e(for)i +Fl(F)14 b Fm(,)30 b(w)m(e)i(compute)f(a)g(linear)e(relation)g(for)h +(the)257 3180 y(partial)h(deriv)-5 b(ativ)m(es)32 b(of)g +Fl(F)14 b Fm(.)44 b(W)-8 b(rite)31 b Fl(@)1637 3195 y +Fk(x)1710 3180 y Fm(=)1843 3140 y Fk(d)p 1823 3156 77 +4 v 1823 3214 a(dx)1942 3180 y Fm(and)h(\001)2212 3195 +y Fk(z)2280 3180 y Fm(=)c Fl(z)2461 3140 y Fk(d)p 2443 +3156 72 4 v 2443 3214 a(dz)2525 3180 y Fm(.)44 b(One)33 +b(computes)1674 3357 y Fl(F)41 b Fm(=)28 b(1)21 b Fj(\001)h +Fl(F)1403 3591 y Fm(\(1)f Fj(\000)i Fl(z)t Fm(\))g Fj(\001)f +Fl(@)1822 3606 y Fk(x)1866 3591 y Fl(F)42 b Fm(=)27 b +Fj(\000)p Fl(z)g Fj(\001)22 b Fl(F)1401 3850 y Fm(\(1)g +Fj(\000)h Fl(z)t Fm(\))1698 3802 y Ff(2)1759 3850 y Fj(\001)f +Fl(@)1865 3809 y Ff(2)1860 3875 y Fk(x)1905 3850 y Fl(F)42 +b Fm(=)27 b Fl(z)2162 3809 y Ff(2)2225 3850 y Fj(\001)21 +b Fl(F)1114 4110 y Fm(\(1)h Fj(\000)h Fl(z)t Fm(\))1411 +4061 y Ff(2)1472 4110 y Fj(\001)f Fm(\001)1603 4125 y +Fk(z)1643 4110 y Fl(F)41 b Fm(=)28 b(\(\(1)22 b Fj(\000)g +Fl(x)p Fm(\))p Fl(z)28 b Fj(\000)22 b Fl(z)2411 4068 +y Ff(2)2452 4110 y Fm(\))g Fj(\001)f Fl(F)1047 4369 y +Fm(\(1)h Fj(\000)h Fl(z)t Fm(\))1344 4320 y Ff(3)1405 +4369 y Fj(\001)f Fl(@)1506 4384 y Fk(x)1550 4369 y Fm(\001)1631 +4384 y Fk(z)1671 4369 y Fl(F)42 b Fm(=)27 b(\()p Fj(\000)p +Fl(z)h Fm(+)22 b Fl(xz)2269 4328 y Ff(2)2331 4369 y Fm(+)g +Fl(z)2478 4328 y Ff(3)2519 4369 y Fm(\))g Fj(\001)f Fl(F)257 +4546 y Fm(Solv)m(e)33 b(a)f(homogeneous)h(4)22 b Fj(\002)h +Fm(5)32 b(system)h(of)g(linear)d(equations)j(o)m(v)m(er)h +Fl(Q)p Fm(\()p Fl(x)p Fm(\))f(to)f(get)891 4736 y(\(1)22 +b Fj(\000)g Fl(z)t Fm(\))1187 4687 y Ff(3)1248 4736 y +Fj(\001)1298 4639 y Fi(\020)1348 4736 y Fm(\(1)g Fj(\000)g +Fl(x)p Fm(\))h Fj(\001)f Fl(@)1773 4751 y Fk(x)1817 4736 +y Fl(F)36 b Fm(+)22 b Fl(x)g Fj(\001)g Fl(@)2197 4695 +y Ff(2)2192 4760 y Fk(x)2238 4736 y Fl(F)35 b Fm(+)22 +b(\001)2515 4751 y Fk(z)2556 4736 y Fl(F)2633 4639 y +Fi(\021)2710 4736 y Fm(=)27 b(0)257 4913 y(Divide)32 +b(b)m(y)h(the)g(\014rst)g(factor)f(to)g(get)1144 5090 +y(\(1)22 b Fj(\000)h Fl(x)p Fm(\))f Fj(\001)g Fl(@)1569 +5105 y Fk(x)1613 5090 y Fl(F)36 b Fm(+)22 b Fl(x)h Fj(\001)f +Fl(@)1994 5049 y Ff(2)1989 5115 y Fk(x)2034 5090 y Fl(F)36 +b Fm(+)22 b(\001)2312 5105 y Fk(z)2352 5090 y Fl(F)41 +b Fm(=)28 b(0)257 5268 y(This)c(is)e(equiv)-5 b(alen)m(t)23 +b(to)g(the)g(claimed)f(equation)g Fl(x)s Fj(\001)s Fl(L)2173 +5208 y Fe(00)2173 5292 y Fk(n)2220 5268 y Fm(\()p Fl(x)p +Fm(\))s(+)s(\(1)s Fj(\000)s Fl(x)p Fm(\))s Fj(\001)s +Fl(L)2796 5208 y Fe(0)2796 5292 y Fk(n)2843 5268 y Fm(\()p +Fl(x)p Fm(\))s(+)s Fl(n)s Fj(\001)s Fl(L)3214 5283 y +Fk(n)3260 5268 y Fm(\()p Fl(x)p Fm(\))28 b(=)257 5388 +y(0.)1852 5637 y(2)p eop +%%Page: 3 3 +3 2 bop 257 573 a Fb(References)62 792 y Fm(1)146 b(Bruno)46 +b(Haible:)69 b(D-\014nite)45 b(p)s(o)m(w)m(er)i(series)g(in)e(sev)m +(eral)i(v)-5 b(ariables.)82 b Fa(Diploma)46 b(thesis,)501 +912 y(University)35 b(of)g(Karlsruhe,)f(June)h(1989)p +Fm(.)43 b(Sections)33 b(2.15)f(and)h(2.22.)1852 5637 +y(3)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/polynomial/laguerre.tex b/doc/polynomial/laguerre.tex new file mode 100644 index 0000000..b06deb1 --- /dev/null +++ b/doc/polynomial/laguerre.tex @@ -0,0 +1,214 @@ +%% This LaTeX-file was created by Sun Feb 16 14:06:08 1997 +%% LyX 0.10 (C) 1995 1996 by Matthias Ettrich and the LyX Team + +%% Don't edit this file unless you are sure what you are doing. +\documentclass[12pt,a4paper,oneside,onecolumn]{article} +\usepackage[]{fontenc} +\usepackage[latin1]{inputenc} +\usepackage[dvips]{epsfig} + +%% +%% BEGIN The lyx specific LaTeX commands. +%% + +\makeatletter +\def\LyX{L\kern-.1667em\lower.25em\hbox{Y}\kern-.125emX\spacefactor1000}% +\newcommand{\lyxtitle}[1] {\thispagestyle{empty} +\global\@topnum\z@ +\section*{\LARGE \centering \sffamily \bfseries \protect#1 } +} +\newcommand{\lyxline}[1]{ +{#1 \vspace{1ex} \hrule width \columnwidth \vspace{1ex}} +} +\newenvironment{lyxsectionbibliography} +{ +\section*{\refname} +\@mkboth{\uppercase{\refname}}{\uppercase{\refname}} +\begin{list}{}{ +\itemindent-\leftmargin +\labelsep 0pt +\renewcommand{\makelabel}{} +} +} +{\end{list}} +\newenvironment{lyxchapterbibliography} +{ +\chapter*{\bibname} +\@mkboth{\uppercase{\bibname}}{\uppercase{\bibname}} +\begin{list}{}{ +\itemindent-\leftmargin +\labelsep 0pt +\renewcommand{\makelabel}{} +} +} +{\end{list}} +\def\lxq{"} +\newenvironment{lyxcode} +{\list{}{ +\rightmargin\leftmargin +\raggedright +\itemsep 0pt +\parsep 0pt +\ttfamily +}% +\item[] +} +{\endlist} +\newcommand{\lyxlabel}[1]{#1 \hfill} +\newenvironment{lyxlist}[1] +{\begin{list}{} +{\settowidth{\labelwidth}{#1} +\setlength{\leftmargin}{\labelwidth} +\addtolength{\leftmargin}{\labelsep} +\renewcommand{\makelabel}{\lyxlabel}}} +{\end{list}} +\newcommand{\lyxletterstyle}{ +\setlength\parskip{0.7em} +\setlength\parindent{0pt} +} +\newcommand{\lyxaddress}[1]{ +\par {\raggedright #1 +\vspace{1.4em} +\noindent\par} +} +\newcommand{\lyxrightaddress}[1]{ +\par {\raggedleft \begin{tabular}{l}\ignorespaces +#1 +\end{tabular} +\vspace{1.4em} +\par} +} +\newcommand{\lyxformula}[1]{ +\begin{eqnarray*} +#1 +\end{eqnarray*} +} +\newcommand{\lyxnumberedformula}[1]{ +\begin{eqnarray} +#1 +\end{eqnarray} +} +\makeatother + +%% +%% END The lyx specific LaTeX commands. +%% + +\pagestyle{plain} +\setcounter{secnumdepth}{3} +\setcounter{tocdepth}{3} + +%% Begin LyX user specified preamble: +\catcode`@=11 % @ ist ab jetzt ein gewoehnlicher Buchstabe +\def\ll{\langle\!\langle} +\def\gg{\rangle\!\rangle} +\catcode`@=12 % @ ist ab jetzt wieder ein Sonderzeichen + + +%% End LyX user specified preamble. +\begin{document} + +The Laguerre polynomials \( L_{n}(x) \) are defined through +\[ +L_{n}(x)=e^{x}\cdot \left( \frac{d}{dx}\right) ^{n}(x^{n}e^{-x})\] + + +\begin{description} + +\item [Theorem:]~ + +\end{description} + + \( L_{n}(x) \) satisfies the recurrence relation + + +\[ +L_{0}(x)=1\] + + + +\[ +L_{n+1}(x)=(2n+1-x)\cdot L_{n}(x)-n^{2}\cdot L_{n-1}(x)\] +for \( n\geq 0 \) and the differential equation \( x\cdot L_{n}^{''}(x)+(1-x)\cdot L_{n}^{'}(x)+n\cdot L_{n}(x)=0 \) for all \( n\geq 0 \). + +\begin{description} + +\item [Proof:]~ + +\end{description} + +Let \( F:=\sum ^{\infty }_{n=0}\frac{L_{n}(x)}{n!}\cdot z^{n} \) be the exponential generating function of the sequence of polynomials. +It is the diagonal series of the power series +\[ +G:=\sum _{m,n=0}^{\infty }\frac{1}{m!}\cdot e^{x}\cdot \left( \frac{d}{dx}\right) ^{m}(x^{n}e^{-x})\cdot y^{m}\cdot z^{n}\] +Because the Taylor series +development theorem holds in formal power series rings (see [1], section +2.16), we can simplify +\begin{eqnarray*} +G & = & e^{x}\cdot \sum _{n=0}^{\infty }\left( \sum _{m=0}^{\infty }\frac{1}{m!}\cdot \left( \frac{d}{dx}\right) ^{m}(x^{n}e^{-x})\cdot y^{m}\right) \cdot z^{n}\\ + & = & e^{x}\cdot \sum _{n=0}^{\infty }(x+y)^{n}e^{-(x+y)}\cdot z^{n}\\ + & = & \frac{e^{-y}}{1-(x+y)z} +\end{eqnarray*} +We take over the terminology from the ``diag\_rational'' +paper; here \( R=Q[x] \) and \( M=Q[[x]] \) (or, if you like it better, \( M=H(C) \), the algebra of +functions holomorphic in the entire complex plane). \( G\in M[[y,z]] \) is not rational; +nevertheless we can proceed similarly to the ``diag\_series'' paper. + \( F(z^{2}) \) is the coefficient of \( t^{0} \) in +\[ +G(zt,\frac{z}{t})=\frac{e^{-zt}}{1-z^{2}-\frac{xz}{t}}\in M[[zt,\frac{z}{t},z]]=M\ll z,t\gg \] +The denominator's only zero is \( t=\frac{xz}{1-z^{2}} \). We +can write +\[ +e^{-zt}=e^{-\frac{xz^{2}}{1-z^{2}}}+\left( zt-\frac{xz^{2}}{1-z^{2}}\right) \cdot P(z,t)\] +with \( P(z,t)\in Q[[zt,\frac{xz^{2}}{1-z^{2}}]]\subset Q[[zt,x,z]]=M[[zt,z]]\subset M\ll z,t\gg \). This yields -- all computations being done in \( M\ll z,t\gg \) +-- +\begin{eqnarray*} +G(zt,\frac{z}{t}) & = & \frac{e^{-\frac{xz^{2}}{1-z^{2}}}}{1-z^{2}-\frac{xz}{t}}+\frac{zt}{1-z^{2}}\cdot P(z,t)\\ + & = & \frac{1}{1-z^{2}}\cdot e^{-\frac{xz^{2}}{1-z^{2}}}\cdot \sum _{j=0}^{\infty }\left( \frac{x}{1-z^{2}}\frac{z}{t}\right) ^{j}+\frac{zt}{1-z^{2}}\cdot P(z,t) +\end{eqnarray*} +Here, the coefficient of \( t^{0} \) is +\[ +F(z^{2})=\frac{1}{1-z^{2}}\cdot e^{-\frac{xz^{2}}{1-z^{2}}}\] +hence +\[ +F(z)=\frac{1}{1-z}\cdot e^{-\frac{xz}{1-z}}\] + + +It follows that \( (1-z)^{2}\cdot \frac{d}{dz}F-(1-x-z)\cdot F=0 \). This is equivalent to the claimed recurrence. + +Starting from the closed form for \( F \), we compute a linear relation +for the partial derivatives of \( F \). Write \( \partial _{x}=\frac{d}{dx} \) and \( \Delta _{z}=z\frac{d}{dz} \). One computes +\[ +F=1\cdot F\] + +\[ +\left( 1-z\right) \cdot \partial _{x}F=-z\cdot F\] + +\[ +\left( 1-z\right) ^{2}\cdot \partial _{x}^{2}F=z^{2}\cdot F\] + +\[ +\left( 1-z\right) ^{2}\cdot \Delta _{z}F=((1-x)z-z^{2})\cdot F\] + +\[ +\left( 1-z\right) ^{3}\cdot \partial _{x}\Delta _{z}F=(-z+xz^{2}+z^{3})\cdot F\] +Solve +a homogeneous \( 4\times 5 \) system of linear equations over \( Q(x) \) to get +\[ +\left( 1-z\right) ^{3}\cdot \left( (1-x)\cdot \partial _{x}F+x\cdot \partial _{x}^{2}F+\Delta _{z}F\right) =0\] +Divide by +the first factor to get +\[ +(1-x)\cdot \partial _{x}F+x\cdot \partial _{x}^{2}F+\Delta _{z}F=0\] +This is equivalent to the claimed equation + \( x\cdot L_{n}^{''}(x)+(1-x)\cdot L_{n}^{'}(x)+n\cdot L_{n}(x)=0 \). + +\begin{lyxsectionbibliography} + +\item [1] Bruno Haible: D-finite power series in several variables. \em Diploma +thesis, University of Karlsruhe, June 1989\em . Sections 2.15 and +2.22. + +\end{lyxsectionbibliography} + +\end{document} diff --git a/doc/polynomial/legendre.dvi b/doc/polynomial/legendre.dvi new file mode 100644 index 0000000000000000000000000000000000000000..0db27789cd39db875763394de3ba6b93f95eb999 GIT binary patch literal 8888 zcmd5?4RjONl^$8LEi4-wW0F7s+dzvAj$+9`!H!arQlP|O2OL65NjpemTSd|+qcPat z^dxNB4cTM{o@P-6P8rVTcfWg|E)+QKOP-$I!obV<%WG>oxD7RYj~MR}YkW(Ve8Su4 z_xct!`xf{YJ_suuxa`lp#^ANT;4s5T`!Dq|%>IHf{WAl!G4xG#d8#GwqV< z7#SI@e8F+GpK-%(_yape!;6PvGATULuGM9FwR(kxEkj&sj0-7Zx4`#wb<66k>KCLW zv+Iiw8{5DWDeDR1ylrhjk|g!QE6+-#^xnljnYea*MJ>EF`T)apa?F$;v8u=Ik^GYS zhaC^Vvq~nW)ynW9GZ&s2t*V{Xu$RhP0wRIDi9TQButSna!LcLi|8{jg$7dS zy(hx&1z&DaSW(GZ+UA=mpAPjzc!iD02PWPNK?0}aBcV{rxo0dcgrl62iE9nSd90R= zg%o~sf)lpxIsq;fyRWcm3fwn5$vQ7SI_0Tbp7U5XfDlRaEk4bh@||W-`fIxf^+1tG z@oj5RAeqemsho+U1X?FAD2;T-DsZwg48P;4g2G=6Gm7T(%7awmj_z;*BY4~16A)jK zP;9QKbn}sr5*}}=3CW9ECmRIwD3@DI*_P%64j+yST!M?GMQ^=);M#RlAS}=@qgOxu zUu*W;6Jc|&&;K-}4=-@hW(W!p2eK@mrBS>D_%Bh)C8(zaF4!Z$X+cgAxCr&EtU4Ly zz_bmIL2CT_)su~FPBlXGpLXdsLQ4b`pR7)N@i91zE&Y$WOe}?QG+*)6E5i=U?6Fhx zeeyuXmq+Xm*7eJ{i6;Ft5K=xxIaOilQ~9Aw<#; zo9R&4gO-Fi5dlKd++96X!E~K3Rgk#}cgOTN=*Lt*-7LxBJ+QT7@Vn}z>zYTex@+)b z9;OJBSjUz`-=Z^(jgTqDYj2V;Wk_*hhc1+Y5#i73l(W;BoM$YcQRXXPK1-6~yFabX zmyeox0GLvbrnQ^FW+dGe5Sza`f@v4Ol-+flw40z5_zW~5<0=Od9mG10`1rbitd?)=V0Zzhbg#XKjXt>7_I;=9_ zC54O6e?~-g!+HdV!fY2GVPa-+e;Zrf>qmn5UlswDruFh|uv&W(ArE z^;O>*y9DU&Zbu!<7$^9BLU~;MJy>7^c-Zs&c1anEw&+S*z&y{*XiyGnVm4r&TKPt9 zIY5BRM2(6N_kKc`f2d?t$u@IeRViwVfd+kMZNuRVUwgeXr!GoR| z2kmZxHxc@0%crT)wVSyh+mnETeD>Rj@*P+RSirTu2n3m7=@7Ry%|-Zl6fp|X1o4L= zUIJka!Z8YNp=CUcm}Wd@_*DS+Q@E^4aGbKyx2XX>r?H?Q;izv=wo!l&vN0tQj>aS5 z&OW_jOXRcZ!_GZpWxF0m5JBx|X`sqBrMCevCMbccLcBX1Ot}v3Hn^9;5I}<<4>-g1D)9&#UD@4FEBrYrh_QJlfVtxf{!s- zxbhc3Te4L;$YZcf42E@MqjNH%PI-V>x{sZJ)Ya*_iKWKMt2T7@MyF{ z_6*2xf1M9$WTw|#ZQ7GkVG$t!tOJ&K(4er!(?DS}{b>zQ0A6Zs%Z)VoJM^|X0R>b< z%B7TY(2^J|$=0YTz^5{;lokaPNMEpmR*&akjKd$EU6XgBX`#QtYzK7tpX(vAA9}1b zqYLjiPs#qK+87J-i006nUZNeW@%09v3(k`(pr>qg>$yQRmD;hz9F{pXoa zm$j%9o?jqo)D}pojR4b?O(PE4-dRAE&h5|dJ6Wkm#|_)wu&-^RYvlt~EjJ#Wx&I}J zgt$P)L!8~OXaUrp>N7He!0eu~-lj{@g#*|r*k=GGPc5NmT)sbnPZs55huB+k-K5y~LoA`Ur19F_ze zL?y!J)I$d+3}hXg^g`a`8#2%-TgX?Pq=lR?4+}avxgV{BCR5ILIdOO+4Mj>V|W{n^VZ zoZe{}74Cx>pTZv^n2tezHTzGwXVA3TW%jT6&UtEotx+$8yFU4>PF#Mr2MoSNv z+9Prb3p_u@v4S;vr0d~GW3*?$G0G8w0ggF*rh{KP=rOkT4!}@|_BcWqw#_W1P&EX_ z*1d0u9;Uh>Uw;P;iE(Oy^n|*dx*_Q}omBqtHyTcu9r_jk>FyfFXju9!k2qh6;zo|l zRoRWkdBn3v)x7DpnBG)?wh8&bG~moIQ%yaBzPfOYzO7#0VLY>3R^c{e5DrN)dpg=^ zKUx8eq`JCEGf4o=l5F(pY>MKMgp}LtVUx@+18*DbGHVQ2U_V%|us8&QlPj4b{baHm z{7M^V7>vkOAM|99{oIeQ$MzW*UXuCwjc2oBz~l)!%EQy)6Ser)Kb62i&?t1(*oA5` ziIh3dLY9mY+BzvDIkc66IraN_m2Ju2N>P8HweOqnwRC=9PUQ#HImtX<^`E+$S~hN6 z-#=+r49JQ_+09nTR!AtdUoIat{6MyBUuuX%?&_cOK_vp6o;dwU%L~Kvex3CK6mc;8 z0HVyF5SGe{*ksafn?LA;+onSkOyu>^`EvOXMiE)FGHFWRansfhA^qO_i6#BuTY;=` zF@~)80qi3-GsD5ah0KE|tXX83oMPg*5h)Dm>vKbmwj+AiWu+BrmhCgp1Ph>$59lJT^w+d8JDg@`z~x-ZK~O_()S_kyIpRz?7QP4Oow4p=o8FM>BwxDLA1$U zK8ypB0at4bEo=0uP^$v--6;K?0J?KiC=eC6QTW#KrC5m{3Bug&0x zL^#oaF?hr0U%xFD-pUEkDfXpYO$#BfZ()T0^=l@zm-tS-J|HekX?;_;=LP-9vN4&!@wFe7chSwhf9+fUn literal 0 HcmV?d00001 diff --git a/doc/polynomial/legendre.lyx b/doc/polynomial/legendre.lyx new file mode 100644 index 0000000..624b1f3 --- /dev/null +++ b/doc/polynomial/legendre.lyx @@ -0,0 +1,361 @@ +#This file was created by Sun Feb 16 14:24:48 1997 +#LyX 0.10 (C) 1995 1996 Matthias Ettrich and the LyX Team +\lyxformat 2.10 +\textclass article +\begin_preamble +\catcode`@=11 % @ ist ab jetzt ein gewoehnlicher Buchstabe +\def\mod#1{\allowbreak \mkern8mu \mathop{\operator@font mod}\,\,{#1}} +\def\pmod#1{\allowbreak \mkern8mu \left({\mathop{\operator@font mod}\,\,{#1}}\right)} +\catcode`@=12 % @ ist ab jetzt wieder ein Sonderzeichen + +\end_preamble +\language default +\inputencoding latin1 +\fontscheme default +\epsfig dvips +\papersize a4paper +\paperfontsize 12 +\baselinestretch 1.00 +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation indent +\quotes_language english +\quotes_times 2 +\paperorientation portrait +\papercolumns 0 +\papersides 1 +\paperpagestyle plain + +\layout Standard +\cursor 47 +The Legendre polynomials +\begin_inset Formula \( P_{n}(x) \) +\end_inset + + are defined through +\begin_inset Formula +\[ +P_{n}(x)=\frac{1}{2^{n}n!}\cdot \left( \frac{d}{dx}\right) ^{n}(x^{2}-1)^{n}\] + +\end_inset + +(For a motivation of the +\begin_inset Formula \( 2^{n} \) +\end_inset + + in the denominator, look at +\begin_inset Formula \( P_{n}(x) \) +\end_inset + + modulo an odd prime +\begin_inset Formula \( p \) +\end_inset + +, and observe that +\begin_inset Formula \( P_{n}(x)\equiv P_{p-1-n}(x)\mod p \) +\end_inset + + for +\begin_inset Formula \( 0\leq n\leq p-1 \) +\end_inset + +. + This wouldn't hold if the +\begin_inset Formula \( 2^{n} \) +\end_inset + + factor in the denominator weren't present. +) +\layout Description + +Theorem: +\layout Standard + + +\begin_inset Formula \( P_{n}(x) \) +\end_inset + + satisfies the recurrence relation +\layout Standard + + +\begin_inset Formula +\[ +P_{0}(x)=1\] + +\end_inset + + +\layout Standard + + +\begin_inset Formula +\[ +(n+1)\cdot P_{n+1}(x)=(2n+1)x\cdot P_{n}(x)-n\cdot P_{n-1}(x)\] + +\end_inset + +for +\begin_inset Formula \( n\geq 0 \) +\end_inset + + and the differential equation +\begin_inset Formula \( (1-x^{2})\cdot P_{n}^{''}(x)-2x\cdot P_{n}^{'}(x)+(n^{2}+n)\cdot P_{n}(x)=0 \) +\end_inset + + for all +\begin_inset Formula \( n\geq 0 \) +\end_inset + +. + +\layout Description + +Proof: +\layout Standard + +Let +\begin_inset Formula \( F:=\sum ^{\infty }_{n=0}P_{n}(x)\cdot z^{n} \) +\end_inset + + be the generating function of the sequence of polynomials. + It is the diagonal series of the power series +\begin_inset Formula +\[ +G:=\sum _{m,n=0}^{\infty }\frac{1}{2^{n}m!}\cdot \left( \frac{d}{dx}\right) ^{m}(x^{2}-1)^{n}\cdot y^{m}\cdot z^{n}\] + +\end_inset + +Because the Taylor series development theorem holds in formal power series + rings (see [1], section 2. +16), we can simplify +\begin_inset Formula +\begin{eqnarray*} +G & = & \sum _{n=0}^{\infty }\frac{1}{2^{n}}\cdot \left( \sum _{m=0}^{\infty }\frac{1}{m!}\cdot \left( \frac{d}{dx}\right) ^{m}(x^{2}-1)^{n}\cdot y^{m}\right) \cdot z^{n}\\ + & = & \sum _{n=0}^{\infty }\frac{1}{2^{n}}\cdot \left( (x+y)^{2}-1\right) ^{n}\cdot z^{n}\\ + & = & \frac{1}{1-\frac{1}{2}\left( (x+y)^{2}-1\right) z} +\end{eqnarray*} + +\end_inset + +We take over the terminology from the +\begin_inset Quotes eld +\end_inset + +diag_rational +\begin_inset Quotes erd +\end_inset + + paper; here +\begin_inset Formula \( R=Q[x] \) +\end_inset + + and +\begin_inset Formula \( M=Q[[x]] \) +\end_inset + + (or, if you like it better, +\begin_inset Formula \( M=H(C) \) +\end_inset + +, the algebra of functions holomorphic in the entire complex plane). + +\begin_inset Formula \( G\in M[[y,z]] \) +\end_inset + + is rational; hence +\begin_inset Formula \( F \) +\end_inset + + is algebraic over +\begin_inset Formula \( R[z] \) +\end_inset + +. + Let's proceed exactly as in the +\begin_inset Quotes eld +\end_inset + +diag_series +\begin_inset Quotes erd +\end_inset + + paper. + +\begin_inset Formula \( F(z^{2}) \) +\end_inset + + is the coefficient of +\begin_inset Formula \( t^{0} \) +\end_inset + + in +\begin_inset Formula +\[ +G(zt,\frac{z}{t})=\frac{2t}{2t-\left( (x+zt)^{2}-1\right) z}=\frac{2t}{-z^{3}\cdot t^{2}+2(1-xz^{2})\cdot t+(z-x^{2}z)}\] + +\end_inset + +The splitting field of the denominator is +\begin_inset Formula \( L=Q(x)(z)(\alpha ) \) +\end_inset + + where +\begin_inset Formula +\[ +\alpha _{1/2}=\frac{1-xz^{2}\pm \sqrt{1-2xz^{2}+z^{4}}}{z^{3}}\] + +\end_inset + + +\begin_inset Formula +\[ +\alpha =\alpha _{1}=\frac{2}{z^{3}}-\frac{2x}{z}+\frac{1-x^{2}}{2}z+\cdots \in Q(x)[[z]][\frac{1}{z}]\] + +\end_inset + + +\begin_inset Formula +\[ +\alpha _{2}=\frac{x^{2}-1}{2}z+\cdots \in Q(x)[[z]][\frac{1}{z}]\] + +\end_inset + +The partial fraction decomposition of +\begin_inset Formula \( G(zt,\frac{z}{t}) \) +\end_inset + + reads +\begin_inset Formula +\[ +G(zt,\frac{z}{t})=-\frac{2}{z^{3}}\cdot \frac{1}{\alpha _{1}-\alpha _{2}}\cdot \left( \frac{\alpha _{1}}{t-\alpha _{1}}-\frac{\alpha _{2}}{t-\alpha _{2}}\right) \] + +\end_inset + +It follows that +\begin_inset Formula +\[ +F(z^{2})=-\frac{2}{z^{3}}\cdot \frac{1}{\alpha _{1}-\alpha _{2}}\cdot \left( \frac{\alpha _{1}}{0-\alpha _{1}}-0\right) =\frac{1}{\sqrt{1-2xz^{2}+z^{4}}}\] + +\end_inset + +hence +\begin_inset Formula +\[ +F(z)=\frac{1}{\sqrt{1-2xz+z^{2}}}\] + +\end_inset + + +\layout Standard + +It follows that +\begin_inset Formula \( (1-2xz+z^{2})\cdot \frac{d}{dz}F+(z-x)\cdot F=0 \) +\end_inset + +. + This is equivalent to the claimed recurrence. + +\layout Standard + +Starting from the closed form for +\begin_inset Formula \( F \) +\end_inset + +, we compute a linear relation for the partial derivatives of +\begin_inset Formula \( F \) +\end_inset + +. + Write +\begin_inset Formula \( \partial _{x}=\frac{d}{dx} \) +\end_inset + + and +\begin_inset Formula \( \Delta _{z}=z\frac{d}{dz} \) +\end_inset + +. + One computes +\begin_inset Formula +\[ +F=1\cdot F\] + +\end_inset + + +\begin_inset Formula +\[ +\left( 1-2xz+z^{2}\right) \cdot \partial _{x}F=z\cdot F\] + +\end_inset + + +\begin_inset Formula +\[ +\left( 1-2xz+z^{2}\right) ^{2}\cdot \partial _{x}^{2}F=3z^{2}\cdot F\] + +\end_inset + + +\begin_inset Formula +\[ +\left( 1-2xz+z^{2}\right) \cdot \Delta _{z}F=(xz-z^{2})\cdot F\] + +\end_inset + + +\begin_inset Formula +\[ +\left( 1-2xz+z^{2}\right) ^{2}\cdot \partial _{x}\Delta _{z}F=(z+xz^{2}-2z^{3})\cdot F\] + +\end_inset + + +\begin_inset Formula +\[ +\left( 1-2xz+z^{2}\right) ^{2}\cdot \Delta _{z}^{2}F=\left( xz+(x^{2}-2)z^{2}-xz^{3}+z^{4}\right) \cdot F\] + +\end_inset + +Solve a homogeneous +\begin_inset Formula \( 5\times 6 \) +\end_inset + + system of linear equations over +\begin_inset Formula \( Q(x) \) +\end_inset + + to get +\begin_inset Formula +\[ +\left( 1-2xz+z^{2}\right) ^{2}\cdot \left( (-2x)\cdot \partial _{x}F+(1-x^{2})\cdot \partial _{x}^{2}F+\Delta _{z}F+\Delta _{z}^{2}F\right) =0\] + +\end_inset + +Divide by the first factor to get +\begin_inset Formula +\[ +(-2x)\cdot \partial _{x}F+(1-x^{2})\cdot \partial _{x}^{2}F+\Delta _{z}F+\Delta _{z}^{2}F=0\] + +\end_inset + +This is equivalent to the claimed equation +\begin_inset Formula \( (1-x^{2})\cdot P_{n}^{''}(x)-2x\cdot P_{n}^{'}(x)+(n^{2}+n)\cdot P_{n}(x)=0 \) +\end_inset + +. + +\layout Bibliography + +[1] Bruno Haible: D-finite power series in several variables. + +\shape italic +Diploma thesis, University of Karlsruhe, June 1989 +\shape default +. + Sections 2. +14, 2. +15 and 2. +22. + diff --git a/doc/polynomial/legendre.ps b/doc/polynomial/legendre.ps new file mode 100644 index 0000000..13ad819 --- /dev/null +++ b/doc/polynomial/legendre.ps @@ -0,0 +1,889 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: legendre.dvi +%%Pages: 3 +%%PageOrder: Ascend +%%BoundingBox: 0 0 596 842 +%%DocumentPaperSizes: a4 +%%EndComments +%DVIPSCommandLine: dvips -Pljfour -o legendre.ps legendre.dvi +%DVIPSParameters: dpi=600, compressed, comments removed +%DVIPSSource: TeX output 1997.02.16:1425 +%%BeginProcSet: texc.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]/id ch-image N /rw ch-width 7 add 8 idiv string N /rc 0 N /gp 0 N +/cp 0 N{rc 0 ne{rc 1 sub /rc X rw}{G}ifelse}imagemask restore}B /G{{id +gp get /gp gp 1 add N dup 18 mod S 18 idiv pl S get exec}loop}B /adv{cp +add /cp X}B /chg{rw cp id gp 4 index getinterval putinterval dup gp add +/gp X adv}B /nd{/cp 0 N rw exit}B /lsh{rw cp 2 copy get dup 0 eq{pop 1}{ +dup 255 eq{pop 254}{dup dup add 255 and S 1 and or}ifelse}ifelse put 1 +adv}B /rsh{rw cp 2 copy get dup 0 eq{pop 128}{dup 255 eq{pop 127}{dup 2 +idiv S 128 and or}ifelse}ifelse put 1 adv}B /clr{rw cp 2 index string +putinterval adv}B /set{rw cp fillstr 0 4 index getinterval putinterval +adv}B /fillstr 18 string 0 1 17{2 copy 255 put pop}for N /pl[{adv 1 chg} +{adv 1 chg nd}{1 add chg}{1 add chg nd}{adv lsh}{adv lsh nd}{adv rsh}{ +adv rsh nd}{1 add adv}{/rc X nd}{1 add set}{1 add clr}{adv 2 chg}{adv 2 +chg nd}{pop nd}]dup{bind pop}forall N /D{/cc X dup type /stringtype ne{] +}if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +TeXDict begin 39158280 55380996 1000 600 600 (legendre.dvi) +@start /Fa 24 122 df<13F0EA03FC1207A2EA0FFEA4EA07FCEA03CCEA000C131C1318 +A2133813301370136013E0EA01C013801203EA0700120E5A5A5A5A5A0F1D7A891E>44 +D<16C01501A215031507ED0F80151F153F157F913801FF005C140F147F903807FCFEEB0F +F0EB0700EB00015DA314035DA314075DA3140F5DA3141F5DA3143F5DA3147F92C7FCA35C +5CA313015CA313035CA313075CA2130FA2131F133FB612FCA25D224276C132>49 +D56 +DI<91B712F818FF19C00201903980003FF06E90C7EA0FF84AED03FCF000FE4B157FA2 +F13F800203EE1FC05DF10FE0A214074B16F01907A2140F5D1AF8A2141F5DA2190F143F5D +1AF0A2147F4B151FA302FF17E092C9123FA34918C04A167F1A80A2010317FF4A1700A24E +5A13074A4B5A611807010F5F4A4B5A181F61011F4C5A4A4BC7FC18FE4D5A013F4B5A4A4A +5A4D5A017FED3FC005FFC8FC4AEB03FE01FFEC1FF8B812E094C9FC16F845447AC34A>68 +D<031FB512F05DA29239000FFC005FA35FA2161FA25FA2163FA25FA2167FA25FA216FFA2 +94C7FCA25DA25EA21503A25EA21507A25EA2150FA25EA2151FA25EA2153FA25EA2157FA2 +5EEA0F80D83FE013FF93C8FC127FA24A5AEAFFC04A5A1300007C495A0070495A4A5A6C5C +003C495A6C01FEC9FC380F81F83803FFE0C690CAFC344679C333>74 +D<91B66C90383FFFF8A302010180C7000F13006E90C8EA07FC4A17F01AC04B4B5A4FC7FC +193C02035E4B5DF003E0F0078002074BC8FC4B141E6018F8020F4A5A4BEB03C04D5A4DC9 +FC021F141E4B137C17F04C5A023F495A4B487E161F163F027F497EED80FFED81EF923883 +CFF89138FF8F8FED1E07033C7F157849EBF00303E07F15C092380001FF495A5C707FA213 +074A6E7EA2173F010F825C171F84131F4A140F84A2013F6F7E5CA2017F6F7EA24A4A7E49 +6C4A7FB66C90B512FC5E614D447AC34B>I<001FB500F090383FFFFCA326003FF0C70001 +13806D48913800FE00013F167C18785C187018F0017F5E5CA2170101FF5E91C8FCA21703 +485F5BA21707000394C7FC5BA25F0007160E5BA2171E120F49151CA2173C121F491538A2 +1778123F491570A217F0127F495DA2160100FF5E90C8FCA216035F16074893C8FC5E160E +161E5E007E1538007F15785E6C4A5A6D495A001F4A5A6D49C9FC6C6C133E6C6C13F83903 +FC07F0C6B512C0013F90CAFCEB07F83E466DC348>85 D97 D101 DI<14FE137FA3EB01FC13001301A2 +5CA21303A25CA21307A25CA2130FA25CA2131FA25C157F90393F83FFC091388F81F09138 +1E00F802387F4948137C5C4A137EA2495A91C7FCA25B484814FE5E5BA2000314015E5BA2 +000714035E5B1507000F5DA249130F5E001F1678031F1370491480A2003F023F13F0EE00 +E090C7FC160148023E13C01603007E1680EE070000FEEC1E0FED1F1E48EC0FF80038EC03 +E02D467AC432>104 D<143C147E14FE1301A3EB00FC14701400AE137C48B4FC3803C780 +380703C0000F13E0120E121C13071238A21278EA700F14C0131F00F0138012E0EA003F14 +00A25B137EA213FE5B12015BA212035B141E0007131C13E0A2000F133CEBC038A21478EB +807014F014E0EB81C0EA0783EBC7803803FE00EA00F8174378C11E>I108 DIIII114 DI< +1470EB01F8A313035CA313075CA3130F5CA3131F5CA2007FB512E0B6FC15C0D8003FC7FC +A25B137EA313FE5BA312015BA312035BA312075BA3120F5BA2EC0780001F140013805C14 +0E003F131EEB001C143C14385C6C13F0495A6C485AEB8780D807FEC7FCEA01F81B3F78BD +20>I<137C48B414072603C780EB1F80380703C0000F7F000E153F121C0107150012385E +1278D8700F147E5C011F14FE00F05B00E05DEA003FEC0001A2495C137E150313FE495CA2 +15071201495CA2030F13380003167849ECC070A3031F13F0EE80E0153F00011581037F13 +C06DEBEF8300000101148090397C03C787903A3E0F07C70090391FFE01FE903903F00078 +2D2D78AB34>I<017C143848B414FC3A03C78001FE380703C0000F13E0120E001C140001 +07147E1238163E1278D8700F141E5C131F00F049131C12E0EA003F91C7123C16385B137E +167801FE14705BA216F0000115E05B150116C0A24848EB0380A2ED0700A2150E12015D6D +5B000014786D5B90387C01E090383F0780D90FFFC7FCEB03F8272D78AB2D>I<137C48B4 +14072603C780EB1F80380703C0000F7F000E153F001C1600130712385E0078157EEA700F +5C011F14FE00F0495B12E0EA003FEC00015E5B137E150301FE5C5BA2150700015D5BA215 +0F00035D5BA2151F5EA2153F12014BC7FC6D5B00005BEB7C0390383E0F7EEB1FFEEB03F0 +90C712FE5DA214015D121F397F8003F0A24A5A4848485A5D48131F00F049C8FC0070137E +007813F8383801F0381E07C06CB4C9FCEA01FC294078AB2F>121 +D E /Fb 7 116 df82 D<92380FFFF04AB67E020F15F0 +023F15FC91B77E01039039FE001FFF4901F8010113804901E0010713C04901804913E001 +7F90C7FC49484A13F0A2485B485B5A5C5A7113E0485B7113C048701380943800FE0095C7 +FC485BA4B5FCAE7EA280A27EA2806C18FCA26C6D150119F87E6C6D15036EED07F06C18E0 +6C6D150F6D6DEC1FC06D01E0EC7F806D6DECFF00010701FCEB03FE6D9039FFC03FFC0100 +91B512F0023F5D020F1580020102FCC7FCDA000F13C03E437BC148>99 +D<92380FFFC04AB512FC020FECFF80023F15E091B712F80103D9FE037F499039F0007FFF +011F01C0011F7F49496D7F4990C76C7F49486E7F48498048844A804884485B727E5A5C48 +717EA35A5C721380A2B5FCA391B9FCA41A0002C0CBFCA67EA380A27EA27E6E160FF11F80 +6C183F6C7FF17F006C7F6C6D16FE6C17016D6C4B5A6D6D4A5A6D01E04A5A6D6DEC3FE001 +0301FC49B45A6D9026FFC01F90C7FC6D6C90B55A021F15F8020715E0020092C8FC030713 +F041437CC14A>101 DI<902607FF80EB1FFFB691B512F0040714FC041F14FF4C8193267FE07F7F9227 +81FE001F7FC6DA83F86D7F6DD987F07F6DD98FC0814C7F039FC78015BE03BC8003FC825D +A25DA25DA45DB3B2B7D8F007B71280A651417BC05A>110 D114 D<913A3FFF8007800107B5EAF81F011FECFE7F017F91B5FC48B8FC48EB +E0014890C7121FD80FFC1407D81FF0801600485A007F167F49153FA212FF171FA27F7F7F +6D92C7FC13FF14E014FF6C14F8EDFFC06C15FC16FF6C16C06C16F06C826C826C826C8201 +3F1680010F16C01303D9007F15E0020315F0EC001F1500041F13F81607007C150100FC81 +177F6C163FA2171F7EA26D16F0A27F173F6D16E06D157F6D16C001FEEDFF806D02031300 +02C0EB0FFE02FCEB7FFC01DFB65A010F5DD8FE0315C026F8007F49C7FC48010F13E03543 +7BC140>I E /Fc 1 49 df48 D E /Fd +9 115 df58 +D80 D<003FBA12E0A59026FE000FEB8003D87FE0933800 +3FF049171F90C71607A2007E1803007C1801A300781800A400F819F8481978A5C81700B3 +B3A20107B8FCA545437CC24E>84 D101 DI104 D<90277F8007FEEC0FFCB590263FFFC090 +387FFF8092B5D8F001B512E002816E4880913D87F01FFC0FE03FF8913D8FC00FFE1F801F +FC0003D99F009026FF3E007F6C019E6D013C130F02BC5D02F86D496D7EA24A5D4A5DA34A +5DB3A7B60081B60003B512FEA5572D7CAC5E>109 D111 D<90387F807FB53881FFE0028313F0028F13F8ED8FFC9138 +9F1FFE000313BE6C13BC14F8A214F0ED0FFC9138E007F8ED01E092C7FCA35CB3A5B612E0 +A5272D7DAC2E>114 D E /Fe 2 50 df0 +D49 D E /Ff 7 62 df43 D48 D<130C133C137CEA03FC12FFEA +FC7C1200B3B113FE387FFFFEA2172C7AAB23>III<140EA2141E143EA2147E14FEA2EB01BE1303143E1306130E130C1318133813301360 +13E013C0EA0180120313001206120E120C5A123812305A12E0B612FCA2C7EA3E00A9147F +90381FFFFCA21E2D7EAC23>I61 +D E /Fg 8 89 df<151E153E157C15F8EC01F0EC03E01407EC0FC0EC1F8015005C147E5C +A2495A495AA2495AA2495AA2495AA249C7FCA2137EA213FE5B12015BA212035BA21207A2 +5B120FA35B121FA45B123FA548C8FCA912FEB3A8127FA96C7EA5121F7FA4120F7FA31207 +7FA21203A27F1201A27F12007F137EA27FA26D7EA26D7EA26D7EA26D7EA26D7E6D7EA214 +7E80801580EC0FC0EC07E01403EC01F0EC00F8157C153E151E1F94718232>16 +D<12F07E127C7E7E6C7E7F6C7E6C7E12017F6C7E137EA27F6D7EA26D7EA26D7EA26D7EA2 +6D7EA26D7EA280147E147F80A21580141FA215C0A2140F15E0A3140715F0A4140315F8A5 +EC01FCA9EC00FEB3A8EC01FCA9EC03F8A515F01407A415E0140FA315C0141FA21580A214 +3F1500A25C147E14FE5CA2495AA2495AA2495AA2495AA2495AA249C7FC137EA25B485A5B +1203485A485A5B48C8FC123E5A5A5A1F947D8232>I<160F161F163E167C16F8ED01F0ED +03E0ED07C0150FED1F801600153E157E5D4A5A5D14034A5A5D140F4A5AA24AC7FC143E14 +7E5CA2495AA2495AA2495AA2130F5CA2495AA2133F91C8FCA25B137E13FEA25B1201A25B +1203A35B1207A35B120FA35BA2121FA45B123FA690C9FC5AAA12FEB3AC127FAA7E7FA612 +1F7FA4120FA27FA312077FA312037FA312017FA212007FA2137E137F7FA280131FA26D7E +A2801307A26D7EA26D7EA26D7EA2147E143E143F6E7EA26E7E1407816E7E1401816E7E15 +7E153E811680ED0FC01507ED03E0ED01F0ED00F8167C163E161F160F28C66E823D>I<12 +F07E127C7E7E6C7E6C7E6C7E7F6C7E1200137C137E7F6D7E130F806D7E1303806D7EA26D +7E147C147E80A26E7EA26E7EA26E7EA2811403A26E7EA2811400A281157E157FA2811680 +A2151F16C0A3150F16E0A3150716F0A31503A216F8A4150116FCA6150016FEAA167FB3AC +16FEAA16FC1501A616F81503A416F0A21507A316E0150FA316C0151FA31680153FA21600 +5DA2157E15FE5DA214015DA24A5AA214075DA24A5AA24A5AA24AC7FCA2147E147C14FC49 +5AA2495A5C1307495A5C131F49C8FC137E137C5B1201485A5B485A485A48C9FC123E5A5A +5A28C67E823D>I32 D<12F07E127C7E123F7E6C7E6C7E6C7E7F12016C7E +7F137E133E133F6D7E130F806D7EA26D7E80130180130080147E147F8081141F81140F81 +140781A2140381140181A2140081A2157FA36F7EA382151FA282150FA3821507A382A215 +03A282A31501A282A31500A382A482A21780A7163F17C0AC161F17E0B3B3A217C0163FAC +1780167FA71700A25EA45EA31501A35EA21503A35EA21507A25EA3150F5EA3151F5EA215 +3F5EA34BC7FCA315FEA25D1401A25D14035D1407A25D140F5D141F5D143F92C8FC5C147E +14FE5C13015C13035C495AA2495A5C131F49C9FC133E137E5B5B485A12035B485A485A48 +CAFC5A123E5A5A5A2BF87E8242>I80 D88 D E /Fh 9 113 +df<007FB912E0BA12F0A26C18E03C04789A4D>0 D<121FEA3F80EA7FC0EAFFE0A5EA7FC0 +EA3F80EA1F000B0B789E1C>I<0060160600F8160F6C161F007E163F6C167E6C6C15FC6C +6CEC01F86C6CEC03F06C6CEC07E06C6CEC0FC06C6CEC1F80017EEC3F006D147E6D6C5B6D +6C485A6D6C485A6D6C485A6D6C485A6D6C485ADA7E3FC7FCEC3F7E6E5A6E5A6E5AA24A7E +4A7EEC3F7EEC7E3F4A6C7E49486C7E49486C7E49486C7E49486C7E49486C7E49C7127E01 +7E8049EC1F804848EC0FC04848EC07E04848EC03F04848EC01F84848EC00FC48C9127E00 +7E163F48161F48160F00601606303072B04D>I<16C04B7EB3AC007FBA1280BB12C0A26C +1980C8D801E0C9FCB3A9007FBA1280BB12C0A26C198042427BC14D>6 +D<007FBA1280BB12C0A26C1980CEFCB0007FBA1280BB12C0A26C1980CEFCB0007FBA1280 +BB12C0A26C1980422C7BAE4D>17 D<19E0F003F0180FF03FE0F0FF80943803FE00EF0FF8 +EF3FE0EFFF80DC03FEC7FCEE0FF8EE3FE0EEFF80DB03FEC8FCED1FF8ED7FE0913801FF80 +DA07FEC9FCEC1FF0EC7FC04948CAFCEB07FCEB1FF0EB7FC04848CBFCEA07FCEA1FF0EA7F +C048CCFCA2EA7FC0EA1FF0EA07FCEA01FF38007FC0EB1FF0EB07FCEB01FF9038007FC0EC +1FF0EC07FC913801FF809138007FE0ED1FF8ED07FE923800FF80EE3FE0EE0FF8EE03FE93 +3800FF80EF3FE0EF0FF8EF03FE943800FF80F03FE0F00FF01803F000E01900B0007FB912 +E0BA12F0A26C18E03C4E78BE4D>20 D<127012FCB4FCEA7FC0EA1FF0EA07FCEA01FF3800 +7FC0EB1FF0EB07FCEB01FF9038007FC0EC1FF0EC07FC913801FF809138007FE0ED1FF8ED +07FE923800FF80EE3FE0EE0FF8EE03FE933800FF80EF3FE0EF0FF8EF03FE943800FF80F0 +3FE0F00FF0A2F03FE0F0FF80943803FE00EF0FF8EF3FE0EFFF80DC03FEC7FCEE0FF8EE3F +E0EEFF80DB03FEC8FCED1FF8ED7FE0913801FF80DA07FEC9FCEC1FF0EC7FC04948CAFCEB +07FCEB1FF0EB7FC04848CBFCEA07FCEA1FF0EA7FC048CCFC12FC1270CDFCB0007FB912E0 +BA12F0A26C18E03C4E78BE4D>I<92B6FC02071580143F91B7120001030180C8FCD907FC +C9FCEB1FE0EB3F80017ECAFC5B485A485A485A5B485A121F90CBFC123EA2123C127CA212 +7812F8A25AA2B9FC1880A2180000F0CBFCA27EA21278127CA2123C123EA27E7F120F6C7E +7F6C7E6C7E6C7E137E6D7EEB1FE0EB07FC6DB47E010090B6FC023F158014070200150031 +3A78B542>50 D<1B0C1B1E1B3EA21B7CA21BF8A2F201F0A2F203E0A2F207C0A2F20F80A2 +F21F00A21A3EA262A262A24F5AA2621903A24F5AA24F5AA24FC7FCA2193EA261A261A24E +5AA24E5AA24E5AA24E5AA2010C4CC8FC133C017C163EEA01FE00035F487E001E5F00387F +D8707F4B5A00E07FD8003F4B5A80011F4B5AA26E4A5A130F6E4AC9FC13076E143E13036E +5C13016E5C7F6F5B027F1301A26F485A143F6F485A141F6F485A140F6F48CAFC1407EDFC +3E14035E15FE02015B15FF6E5BA26F5AA26F5AA26F5AA26FCBFC150E4F647A8353>112 +D E /Fi 9 123 df<123C127EB4FCA21380A2127F123D1201A312031300A25A1206120E +5A5A5A126009157A8714>59 D<15C0140114031580A214071500A25C140EA2141E141CA2 +143C143814781470A214F05CA213015CA213035C130791C7FCA25B130EA2131E131CA213 +3C1338A21378137013F05BA212015BA212035BA2120790C8FC5A120EA2121E121CA2123C +1238A212781270A212F05AA21A437CB123>61 D<151FEC03FFA2EC003FA2153EA2157EA2 +157CA215FCA215F8A21401EB07E190381FF9F0EB7C1DEBF80FEA01F03903E007E0EA07C0 +120FEA1F8015C0EA3F00140F5A007E1480A2141F12FE481400A2EC3F021506143E5AEC7E +0E007CEBFE0C14FC0101131C393E07BE18391F0E1E38390FFC0FF03903F003C0202F7DAD +24>100 D<27078007F0137E3C1FE01FFC03FF803C18F0781F0783E03B3878E00F1E0126 +3079C001B87F26707F8013B00060010013F001FE14E000E015C0485A4914800081021F13 +0300015F491400A200034A13076049133E170F0007027EEC8080188149017C131F180100 +0F02FCEB3F03053E130049495C180E001F0101EC1E0C183C010049EB0FF0000E6D48EB03 +E0391F7E9D3E>109 D<3907C007E0391FE03FF83918F8783E393879E01E39307B801F38 +707F00126013FEEAE0FC12C05B00815C0001143E5BA20003147E157C5B15FC0007ECF808 +1618EBC00115F0000F1538913803E0300180147016E0001F010113C015E390C7EAFF0000 +0E143E251F7E9D2B>I<90387C01F89038FE07FE3901CF8E0F3A03879C0780D907B813C0 +000713F000069038E003E0EB0FC0000E1380120CA2D8081F130712001400A249130F16C0 +133EA2017EEB1F80A2017C14005D01FC133E5D15FC6D485A3901FF03E09038FB87C0D9F1 +FFC7FCEBF0FC000390C8FCA25BA21207A25BA2120FA2EAFFFCA2232B829D24>112 +D<130E131FA25BA2133EA2137EA2137CA213FCA2B512F8A23801F800A25BA21203A25BA2 +1207A25BA2120FA25BA2001F1310143013001470146014E0381E01C0EB0380381F0700EA +0F0EEA07FCEA01F0152B7EA919>116 D<013F137C9038FFC1FF3A01C1E383803A0380F7 +03C0390700F60F000E13FE4813FC12180038EC0700003049C7FCA2EA200100005BA31303 +5CA301075B5D14C000385CD87C0F130600FC140E011F130C011B131C39F03BE038D87071 +13F0393FE0FFC0260F803FC7FC221F7E9D28>120 D<011E1330EB3F809038FFC07048EB +E0E0ECF1C03803C0FF9038803F80903800070048130EC75A5C5C5C495A495A49C7FC131E +13385B491340484813C0485A38070001000EEB0380380FE007391FF81F0038387FFF486C +5A38601FFC38E00FF038C003C01C1F7D9D21>122 D E /Fj 20 123 +df11 +D<121EEA7F8012FF13C0A213E0A3127FEA1E601200A413E013C0A312011380120313005A +1206120E5A5A5A12600B1D78891B>59 D64 D<4CB46C1318043F01F013384BB512FC0307D9007E13 +78DB1FF090380F80F0DB7F80EB03C1DA01FEC7EA01C34A48EC00E7DA0FF0ED7FE04A4815 +3F4A5A02FFC9121F494817C04948160F495A130F4A178049481607495A137F4948170091 +CAFC5A485A1906485AA2485A96C7FC121F5BA2123F5BA3127F5BA4485AA419C0A2180161 +127F180396C7FC6018066C6C160E601818001F17386D5E000F5F6D4B5A6C6C4B5A00034C +C8FC6C6C150E6C6C153C017F5DD93FC0EB01E0D91FF0EB0FC0D907FE017FC9FC0101B512 +FCD9003F13E0020790CAFC45487CC546>67 D<91B912F8A3020001C0C7123F6F48EC07F0 +03FF1503190193C9FCA21A705C5DA3020317605DA314075D18C01701020F4B13005DA217 +03021F92C8FC4B5BA25F023F141E4B13FE92B5FCA24A5CED8000173CA202FF141892C7FC +A217384915305CA21770010315604A91C9FCA313075CA3130F5CA3131F5CA2133FA313FF +B612F8A345447CC33F>70 D<4CB46C1318043F01F013384BB512FC0307D9007E1378DB1F +F090380F80F0DB7F80EB03C1DA01FEC7EA01C34A48EC00E7DA0FF0ED7FE04A48153F4A5A +02FFC9121F494817C04948160F495A130F4A178049481607495A137F4948170091CAFC5A +485A1906485AA2485A96C7FC121F5BA2123F5BA3127F5BA4485A4CB612805EA293C7EBE0 +00725AA3007F60A218FF96C7FCA26C7E5F606C7EA2000F16036D5E6C6C15070003160F6C +6C151F6C6CED3DF8D97F8014786D6CEB01E0D91FF0903807C078D907FE90387F00700101 +B500FC1330D9003F01F090C8FC020790CAFC45487CC54D>I<91B6D8E003B61280A30200 +01E0C70003EB8000DB7F806E48C7FC03FF1503A293C85BA219075C4B5EA2190F14034B5E +A2191F14074B5EA2193F140F4B5EA2197F141F4B5EA219FF143F92B8C8FCA3DA7FC0C712 +014B5DA2180314FF92C85BA218075B4A5EA2180F13034A5EA2181F13074A5EA2183F130F +4A5EA2187F131F4A5EA2013F16FFA24A93C9FCD9FFE002037FB6D8E003B67EA351447CC3 +51>I<91B612F8A3020001E0C8FC6F5A4B5AA293C9FCA35C5DA314035DA314075DA3140F +5DA3141F5DA3143F5DA3147F5DA314FF92CAFCA35B4A16C0A21801010317804A15031900 +A201075E4A1506180E181E010F161C4A153C18381878011F16F84A4A5A1703013F150F4D +5A4A14FF01FF02075BB9FCA2603A447CC342>76 D<91B500C0933803FFFE63630200F1FE +00DB6FE0EE1BF803EF171F1B3703CFEF67F0A21BCF0201EF018F038F60DB87F0ED030F1B +1F020317060307040C5BA2F2183F020717300206616F6C15601B7F020E17C0020CDC0180 +90C7FCA24F485A021C16060218606F6C5C1A0102381618023004305BA2F16003027016C0 +0260606F6CEB01801A0702E0ED03004A03065CA24E130F01015E4A60047F5B1A1F01035E +91C74A5CA24D48133F494BC7FC010661EE3F861A7F010E158C010C039892C8FCA205B05C +011C15E001186001386E5A190101785D01FC92C75BD803FFEF07FEB500F8011E0107B512 +FE161C160C5F447BC35E>I<91B712FEF0FFE019F802009039C0000FFE6F48EB01FF03FF +9138007F80F13FC093C8EA1FE0A24AEE0FF0A25D1AF81403A25DA21407F11FF05DA2020F +EE3FE0A24B16C0197F021F1780F1FF004B4A5A4E5A023F4B5A4E5A4BEC3FC006FFC7FC02 +7FEC07FC92B612F018800380CAFC14FFA292CBFCA25BA25CA21303A25CA21307A25CA213 +0FA25CA2131FA25CA2133FA25CEBFFE0B612E0A345447CC33F>80 +DI<91B712F018FF19E002009039C0003FF86F +48EB07FC03FFEC01FEF0007F93C8EA3F801AC0F11FE05C5D1AF0A214035DA30207EE3FE0 +5DA2F17FC0020F17804B15FF1A004E5A021F4B5A4B4A5AF00FE04E5A023F037FC7FC4BEB +03FCEF1FF092B612804A4AC8FC923980007F80EF0FC0EF07F002FF6E7E92C77F1701845B +4A1400A2170113035CA2170313075CA24D5A130F5CA3011F18185CA2013F4C13381A304A +6F1370D9FFE0020314E0B600E0ED01C00501EB0380943900FE0F00CBEA3FFEF007F04546 +7CC34A>I100 D<01F8D903FCEC7F80D803FED91FFF903803FFE0 +D8071F903B7C0FC00F81F83E0E0F80E007E01C00FC001C9026C3C0030178137C271807C7 +00D9F0E0137E02CE902601F1C0133E003801DCDAFB80133F003001D892C7FCD90FF814FF +0070495C0060495CA200E04949485CD8C01F187E4A5C1200040715FE013F6091C75BA204 +0F14014960017E5D1903041F5D13FE494B130762043F160E0001060F130C4992C713C019 +1F4CED801C00031A1849027E1638F2003004FE167000071A60494A16E0F201C003019238 +0F0380000FF18700494AEC03FED80380D90070EC00F84F2D7DAB55>109 +D<01F8EB03FCD803FEEB1FFFD8071F90387C0FC03B0E0F80E007E03A0C07C3C003001CD9 +C7007F001801CE1301003801DC80003013D8EB0FF800705B00605BA200E0491303D8C01F +5D5C12001607013F5D91C7FCA2160F495D137E161F5F13FE49143F94C7FC187000014B13 +6049147E16FE4C13E0000317C049150104F81380170300071700495D170EEE781C000FED +7C3849EC1FF0D80380EC07C0342D7DAB3A>I112 D<141C147EA314FE5CA313015C +A313035CA313075CA2007FB512FCB6FC15F839000FC000A2131F5CA3133F91C7FCA35B13 +7EA313FE5BA312015BA312035BA21570000714605B15E015C0000F130101C013801403EC +070000071306140E5C6C6C5A000113F03800FFC0013FC7FC1E3F7EBD23>116 +D<02FCEB07E0903A03FF801FFC903A0F07C0781E903A1C03E0E01F903A3801F1C07FD970 +0013804901FB13FF4848EBFF00495B000316FE90C71438484A130012061401000E5C120C +C7FC14035DA314075DA3140F5DA3021F143817305D1770023F1460121E003F16E0267F80 +7FEB01C0026F148000FF01EF1303D901CFEB070000FE903887C00E267C03835B3A3C0F01 +E0783A1FFC00FFE0D803F0EB3F80302D7EAB37>120 D<133ED9FF8014E02603C3C0EB03 +F0380703E0380601F0000E1507001C16E0EA180312380030150F007016C0EA60075C161F +D8E00F158000C05BEA001F4A133F1700133F91C7FC5E49147E137EA216FE01FE5C5BA215 +015E485AA215035EA200001407150F6D5C017C131F153F6D13FF90391F03CFC0903807FF +8F903801FC0F90C7121F5EA2153F93C7FCD807C05BD81FE0137E5DA24848485A4A5A0180 +5B39380007C00018495A001C49C8FC6C137C380781F83803FFE0C66CC9FC2C407DAB30> +I<027CEB018049B413034901801300010F6D5A49EBE00E6F5A90393F03F838903978007E +F80170EB1FF00160EB01E001E05C49495A90C748C7FC150E5D5D5D5D4A5A4A5A4AC8FC14 +0E5C5C5C5CEB03C049C9FC130E49141C4914185B49143848481430491470D8039014F048 +B4495A3A0FEFC007C0391E03F01FD81C01B55A486C91C7FC485C00606D5A00E0EB3FF048 +EB0FC0292D7CAB2D>I E /Fk 60 122 df<1618163CA2167EA216FFA24B7FA24B6C7EA2 +9238063FE0A24B6C7EA24B6C7EA292383807FC153092387003FE15609238E001FF15C002 +016D7F5D02036E7E92C7FC4A6E7E1406020E6E7E140C021C6E7E141802386E7E14300270 +6E7E146002E06E7E5C01016F7F5C0103707E91C9FC183F010683181F4983180F49831807 +498318034983A249707EA24848701380A248CBEA7FC0A20006F03FE0A248F01FF0A2001F +BA12F8A24819FCA24819FEA2BCFC48477CC651>1 D<9239FFC001FC020F9038F80FFF91 +3B3F803E3F03C0913BFC00077E07E0D903F890390FFC0FF0494890383FF81F4948EB7FF0 +495A494814E049C7FCF00FE04991393FC0038049021F90C7FCAFB912F0A3C648C7D81FC0 +C7FCB3B2486CEC3FF0007FD9FC0FB512E0A33C467EC539>11 D<4AB4FC020F13E091387F +80F8903901FC001C49487FD907E0130F4948137F011FECFF80495A49C7FCA25B49EC7F00 +163E93C7FCACEE3F80B8FCA3C648C7FC167F163FB3B0486CEC7FC0007FD9FC1FB5FCA330 +467EC536>I14 D<121EEA7F80EAFFC0A9EA7F80ACEA +3F00AB121EAC120CA5C7FCAA121EEA7F80A2EAFFC0A4EA7F80A2EA1E000A4778C61B>33 +D<001EEB03C0397F800FF000FF131F01C013F8A201E013FCA3007F130F391E6003CC0000 +EB000CA401E0131C491318A3000114384913300003147090C712604814E0000614C0000E +130148EB038048EB070048130E0060130C1E1D7DC431>I<121EEA7F8012FF13C0A213E0 +A3127FEA1E601200A413E013C0A312011380120313005A1206120E5A5A5A12600B1D78C4 +1B>39 D<140C141C1438147014E0EB01C01303EB0780EB0F00A2131E5BA25B13F85B1201 +5B1203A2485AA3485AA348C7FCA35AA2123EA2127EA4127CA312FCB3A2127CA3127EA412 +3EA2123FA27EA36C7EA36C7EA36C7EA212017F12007F13787FA27F7FA2EB0780EB03C013 +01EB00E014701438141C140C166476CA26>I<12C07E12707E7E7E120F6C7E6C7EA26C7E +6C7EA21378137C133C133E131E131FA2EB0F80A3EB07C0A3EB03E0A314F0A21301A214F8 +A41300A314FCB3A214F8A31301A414F0A21303A214E0A3EB07C0A3EB0F80A3EB1F00A213 +1E133E133C137C13785BA2485A485AA2485A48C7FC120E5A5A5A5A5A16647BCA26>I<16 +C04B7EB3AB007FBAFCBB1280A26C1900C8D801E0C9FCB3AB6F5A41407BB84C>43 +D<121EEA7F8012FF13C0A213E0A3127FEA1E601200A413E013C0A312011380120313005A +1206120E5A5A5A12600B1D78891B>II<121EEA7F80A2EAFFC0A4 +EA7F80A2EA1E000A0A78891B>I<14FF010713E090381F81F890383E007C01FC133F4848 +EB1F8049130F4848EB07C04848EB03E0A2000F15F0491301001F15F8A2003F15FCA390C8 +FC4815FEA54815FFB3A46C15FEA56D1301003F15FCA3001F15F8A26C6CEB03F0A36C6CEB +07E0000315C06D130F6C6CEB1F806C6CEB3F00013E137C90381F81F8903807FFE0010090 +C7FC28447CC131>48 D<143014F013011303131F13FFB5FC13E713071200B3B3B0497E49 +7E007FB6FCA3204278C131>II<49B4 +FC010F13E0013F13FC9038FE01FE3A01F0007F80D803C0EB3FC048C7EA1FE0120EED0FF0 +EA0FE0486C14F8A215077F5BA26C48130FEA03C0C813F0A3ED1FE0A2ED3FC01680ED7F00 +15FE4A5AEC03F0EC1FC0D90FFFC7FC15F090380001FCEC007FED3F80ED1FC0ED0FE016F0 +ED07F816FC150316FEA2150116FFA3121EEA7F80487EA416FE491303A2007EC713FC0070 +1407003015F80038140F6C15F06CEC1FE06C6CEB3FC0D803E0EB7F803A01FE01FE003900 +7FFFF8010F13E0010190C7FC28447CC131>II<000615C0D807C0130701FCEB +7F8090B612005D5D5D15E0158026063FFCC7FC90C9FCAE14FF010713C090381F01F09038 +3800FC01F0137ED807C07F49EB1F8016C090C7120F000615E0C8EA07F0A316F81503A216 +FCA5123E127F487EA416F890C712075A006015F0A20070140F003015E00038EC1FC07E00 +1EEC3F806CEC7F006C6C13FE6C6C485A3901F807F039007FFFE0011F90C7FCEB07F82644 +7BC131>II<121EEA7F80A2EAFFC0A4EA7F80A2EA1E +00C7FCB3A5121EEA7F80A2EAFFC0A4EA7F80A2EA1E000A2B78AA1B>58 +D<121EEA7F80A2EAFFC0A4EA7F80A2EA1E00C7FCB3A5121E127FEAFF80A213C0A4127F12 +1E1200A512011380A3120313005A1206120E120C121C5A5A12600A3E78AA1B>I<007FBA +FCBB1280A26C1900CEFCB0007FBAFCBB1280A26C190041187BA44C>61 +D66 +D68 D70 +D72 DI76 D79 +D<49B41303010FEBE007013F13F89039FE00FE0FD801F8131FD807E0EB079F49EB03DF48 +486DB4FC48C8FC4881003E81127E82127C00FC81A282A37E82A27EA26C6C91C7FC7F7FEA +3FF813FE381FFFE06C13FE6CEBFFE06C14FC6C14FF6C15C0013F14F0010F80010180D900 +1F7F14019138001FFF03031380816F13C0167F163F161F17E000C0150FA31607A37EA36C +16C0160F7E17806C151F6C16006C5D6D147ED8FBC05CD8F9F0495AD8F07C495A90393FC0 +0FE0D8E00FB51280010149C7FC39C0003FF02B487BC536>83 D<003FB912F8A3903BF000 +1FF8001F01806D481303003EC7150048187C0078183CA20070181CA30060180CA5481806 +A5C81600B3B3A54B7EED7FFE49B77EA33F447DC346>I87 +D91 D<01C01318000114384848 +137048C712E0000EEB01C0000C1480001C13030018140000385B003013060070130E0060 +130CA300E0131C481318A400CFEB19E039FFC01FF801E013FCA3007F130FA2003F130701 +C013F8390F0001E01E1D71C431>II97 +DII<167FED3FFFA315018182B3EC7F80903803FFF090380FC07C +90383F000E017E1307496D5AD803F87F48487F5B000F81485AA2485AA2127FA290C8FC5A +AB7E7FA2123FA26C7EA2000F5D7F6C6C5B00035C6C6C9038077F806C6C010E13C0013F01 +1C13FE90380FC0F8903803FFE09026007F0013002F467DC436>III +III107 DII<3901FC01FE00FF903807FFC091381E07F091383801F8000701707F +0003EBE0002601FDC07F5C01FF147F91C7FCA25BA35BB3A8486CECFF80B5D8F83F13FEA3 +2F2C7DAB36>II<3901FC03FC00FF90380F +FF8091383C07E091387001F83A07FDE000FE00010180137F01FFEC3F8091C7EA1FC04915 +E049140F17F0160717F8160317FCA3EE01FEABEE03FCA3EE07F8A217F0160F6D15E0EE1F +C06D143F17806EEB7E00D9FDC05B9039FCF003F891383C0FE091381FFF80DA03FCC7FC91 +C9FCAE487EB512F8A32F3F7DAB36>I<91387F8003903903FFE00790380FE07890393F80 +1C0F90387E000E496D5AD803F8EB039F0007EC01BF4914FF48487F121F5B003F81A2485A +A348C8FCAB6C7EA3123F7F121F6D5C120F6D5B12076C6C5B6C6C497E6C6C130E013F131C +90380FC0F8903803FFE09038007F0091C7FCAEEEFF80033F13FEA32F3F7DAB33>I<3903 +F803F000FFEB1FFCEC3C3EEC707F0007EBE0FF3803F9C000015B13FBEC007E153C01FF13 +005BA45BB3A748B4FCB512FEA3202C7DAB26>I<90383FE0183901FFFC383907E01F7839 +0F0003F8001E1301481300007C1478127800F81438A21518A27EA27E6C6C13006C7E13FC +383FFFE06C13FC6C13FF6C14C06C14E0C614F0011F13F81300EC0FFC140300C0EB01FE14 +00157E7E153EA27EA36C143C6C147C15786C14F86CEB01F039F38003E039F1F00F8039E0 +7FFE0038C00FF01F2E7DAC26>I<1306A5130EA4131EA3133E137EA213FE12011207001F +B512F0B6FCA2C648C7FCB3A4150CAA017E131C017F1318A26D133890381F8030ECC07090 +3807E0E0903801FFC09038007F001E3E7EBC26>IIII< +B539F007FFFCA30003D9C00113C0C6496C1300017F14FC013F5C6E13E06D7E010F495A6D +6C485A02F890C7FC903803FC060101130E6E5A903800FF186E5AEC3FF05D141F140F6E7E +81140FEC0DFCEC19FEEC38FF4A7E9138603F8002C07F0101131F49486C7E02007F01066D +7E010E1303496D7E013C80017C80D801FC1580D80FFE4913C0B5D8800F13FFA3302B7FAA +33>II E end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: a4 +%%BeginPaperSize: a4 +a4 +%%EndPaperSize + +%%EndSetup +%%Page: 1 1 +1 0 bop 404 573 a Fk(The)33 b(Legendre)h(p)s(olynomials)29 +b Fj(P)1628 588 y Fi(n)1675 573 y Fk(\()p Fj(x)p Fk(\))k(are)g +(de\014ned)h(through)1199 856 y Fj(P)1262 871 y Fi(n)1309 +856 y Fk(\()p Fj(x)p Fk(\))28 b(=)1647 789 y(1)p 1581 +833 182 4 v 1581 924 a(2)1630 896 y Fi(n)1677 924 y Fj(n)p +Fk(!)1794 856 y Fh(\001)1844 710 y Fg( )1948 789 y Fj(d)p +1920 833 107 4 v 1920 924 a(dx)2036 710 y Fg(!)2102 733 +y Fi(n)2165 856 y Fk(\()p Fj(x)2258 815 y Ff(2)2320 856 +y Fh(\000)23 b Fk(1\))2507 815 y Fi(n)257 1137 y Fk(\(F)-8 +b(or)40 b(a)h(motiv)-5 b(ation)38 b(of)j(the)g(2)1412 +1101 y Fi(n)1500 1137 y Fk(in)f(the)h(denominator,)h(lo)s(ok)e(at)g +Fj(P)2815 1152 y Fi(n)2862 1137 y Fk(\()p Fj(x)p Fk(\))h(mo)s(dulo)e +(an)257 1258 y(o)s(dd)30 b(prime)f Fj(p)p Fk(,)h(and)g(observ)m(e)i +(that)e Fj(P)1631 1273 y Fi(n)1678 1258 y Fk(\()p Fj(x)p +Fk(\))e Fh(\021)g Fj(P)2005 1273 y Fi(p)p Fe(\000)p Ff(1)p +Fe(\000)p Fi(n)2232 1258 y Fk(\()p Fj(x)p Fk(\))62 b(mo)s(d)48 +b Fj(p)30 b Fk(for)g(0)d Fh(\024)h Fj(n)g Fh(\024)g Fj(p)17 +b Fh(\000)g Fk(1.)257 1378 y(This)33 b(w)m(ouldn't)g(hold)f(if)f(the)i +(2)1407 1342 y Fi(n)1486 1378 y Fk(factor)f(in)g(the)h(denominator)e(w) +m(eren't)j(presen)m(t.\))257 1605 y Fd(Theorem:)404 1832 +y Fj(P)467 1847 y Fi(n)514 1832 y Fk(\()p Fj(x)p Fk(\))e(satis\014es)i +(the)f(recurrence)h(relation)1669 2075 y Fj(P)1732 2090 +y Ff(0)1772 2075 y Fk(\()p Fj(x)p Fk(\))28 b(=)f(1)806 +2417 y(\()p Fj(n)22 b Fk(+)g(1\))g Fh(\001)g Fj(P)1244 +2432 y Fi(n)p Ff(+1)1381 2417 y Fk(\()p Fj(x)p Fk(\))28 +b(=)f(\(2)p Fj(n)22 b Fk(+)g(1\))p Fj(x)h Fh(\001)e Fj(P)2185 +2432 y Fi(n)2232 2417 y Fk(\()p Fj(x)p Fk(\))i Fh(\000)f +Fj(n)h Fh(\001)f Fj(P)2679 2432 y Fi(n)p Fe(\000)p Ff(1)2816 +2417 y Fk(\()p Fj(x)p Fk(\))257 2636 y(for)33 b Fj(n)d +Fh(\025)f Fk(0)k(and)h(the)g(di\013eren)m(tial)d(equation)i(\(1)23 +b Fh(\000)g Fj(x)2195 2600 y Ff(2)2235 2636 y Fk(\))g +Fh(\001)f Fj(P)2423 2576 y Fc(00)2409 2661 y Fi(n)2467 +2636 y Fk(\()p Fj(x)p Fk(\))h Fh(\000)g Fk(2)p Fj(x)g +Fh(\001)g Fj(P)2976 2576 y Fc(0)2962 2661 y Fi(n)3008 +2636 y Fk(\()p Fj(x)p Fk(\))g(+)g(\()p Fj(n)3357 2600 +y Ff(2)3419 2636 y Fk(+)257 2756 y Fj(n)p Fk(\))g Fh(\001)e +Fj(P)488 2771 y Fi(n)535 2756 y Fk(\()p Fj(x)p Fk(\))28 +b(=)g(0)k(for)g(all)f Fj(n)d Fh(\025)g Fk(0.)257 2983 +y Fd(Pro)s(of:)404 3210 y Fk(Let)38 b Fj(F)51 b Fk(:=)838 +3144 y Fg(P)926 3170 y Fe(1)926 3235 y Fi(n)p Ff(=0)1079 +3210 y Fj(P)1142 3225 y Fi(n)1189 3210 y Fk(\()p Fj(x)p +Fk(\))26 b Fh(\001)g Fj(z)1449 3174 y Fi(n)1535 3210 +y Fk(b)s(e)38 b(the)h(generating)e(function)h(of)f(the)i(sequence)i(of) +257 3330 y(p)s(olynomials.)g(It)32 b(is)h(the)g(diagonal)d(series)j(of) +f(the)h(p)s(o)m(w)m(er)h(series)949 3608 y Fj(G)28 b +Fk(:=)1257 3500 y Fe(1)1232 3525 y Fg(X)1184 3706 y Fi(m;n)p +Ff(=0)1506 3541 y Fk(1)p 1426 3585 209 4 v 1426 3677 +a(2)1475 3648 y Fi(n)1522 3677 y Fj(m)p Fk(!)1666 3608 +y Fh(\001)1716 3462 y Fg( )1820 3541 y Fj(d)p 1792 3585 +107 4 v 1792 3677 a(dx)1908 3462 y Fg(!)1974 3485 y Fi(m)2057 +3608 y Fk(\()p Fj(x)2150 3567 y Ff(2)2212 3608 y Fh(\000)22 +b Fk(1\))2398 3567 y Fi(n)2467 3608 y Fh(\001)g Fj(y)2569 +3567 y Fi(m)2657 3608 y Fh(\001)g Fj(z)2756 3567 y Fi(n)257 +3903 y Fk(Because)34 b(the)f(T)-8 b(a)m(ylor)31 b(series)i(dev)m +(elopmen)m(t)g(theorem)f(holds)f(in)h(formal)d(p)s(o)m(w)m(er)34 +b(series)257 4024 y(rings)e(\(see)i([1],)f(section)f(2.16\),)g(w)m(e)i +(can)f(simplify)752 4307 y Fj(G)83 b Fk(=)1102 4199 y +Fe(1)1078 4224 y Fg(X)1071 4405 y Fi(n)p Ff(=0)1254 4240 +y Fk(1)p 1231 4284 96 4 v 1231 4375 a(2)1280 4347 y Fi(n)1358 +4307 y Fh(\001)1408 4161 y Fg( )1515 4199 y Fe(1)1490 +4224 y Fg(X)1474 4405 y Fi(m)p Ff(=0)1685 4240 y Fk(1)p +1653 4284 113 4 v 1653 4375 a Fj(m)p Fk(!)1798 4307 y +Fh(\001)1847 4161 y Fg( )1951 4240 y Fj(d)p 1923 4284 +107 4 v 1923 4375 a(dx)2039 4161 y Fg(!)2105 4184 y Fi(m)2188 +4307 y Fk(\()p Fj(x)2281 4266 y Ff(2)2343 4307 y Fh(\000)23 +b Fk(1\))2530 4266 y Fi(n)2599 4307 y Fh(\001)e Fj(y)2700 +4266 y Fi(m)2766 4161 y Fg(!)2854 4307 y Fh(\001)h Fj(z)2953 +4266 y Fi(n)912 4592 y Fk(=)1102 4484 y Fe(1)1078 4509 +y Fg(X)1071 4690 y Fi(n)p Ff(=0)1254 4524 y Fk(1)p 1231 +4568 96 4 v 1231 4660 a(2)1280 4631 y Fi(n)1358 4592 +y Fh(\001)1408 4495 y Fg(\020)1458 4592 y Fk(\()p Fj(x)g +Fk(+)g Fj(y)t Fk(\))1761 4550 y Ff(2)1822 4592 y Fh(\000)h +Fk(1)1971 4495 y Fg(\021)2020 4518 y Fi(n)2089 4592 y +Fh(\001)f Fj(z)2188 4550 y Fi(n)912 4863 y Fk(=)1505 +4795 y(1)p 1081 4840 898 4 v 1081 4932 a(1)g Fh(\000)1261 +4892 y Ff(1)p 1261 4908 36 4 v 1261 4966 a(2)1323 4932 +y Fk(\(\()p Fj(x)h Fk(+)f Fj(y)t Fk(\))1665 4903 y Ff(2)1725 +4932 y Fh(\000)h Fk(1\))16 b Fj(z)257 5147 y Fk(W)-8 +b(e)30 b(tak)m(e)f(o)m(v)m(er)h(the)g(terminology)c(from)i(the)h +(\\diag)p 2160 5147 30 4 v 34 w(rational")d(pap)s(er;)k(here)g +Fj(R)f Fk(=)e Fj(Q)p Fk([)p Fj(x)p Fk(])257 5268 y(and)h +Fj(M)38 b Fk(=)28 b Fj(Q)p Fk([[)p Fj(x)p Fk(]])g(\(or,)h(if)d(y)m(ou)i +(lik)m(e)f(it)f(b)s(etter,)j Fj(M)39 b Fk(=)27 b Fj(H)8 +b Fk(\()p Fj(C)f Fk(\),)28 b(the)g(algebra)e(of)h(functions)257 +5388 y(holomorphic)37 b(in)h(the)h(en)m(tire)f(complex)g(plane\).)62 +b Fj(G)38 b Fh(2)g Fj(M)10 b Fk([[)p Fj(y)t(;)17 b(z)t +Fk(]])39 b(is)f(rational;)i(hence)1852 5637 y(1)p eop +%%Page: 2 2 +2 1 bop 257 573 a Fj(F)45 b Fk(is)30 b(algebraic)g(o)m(v)m(er)i +Fj(R)q Fk([)p Fj(z)t Fk(].)44 b(Let's)31 b(pro)s(ceed)h(exactly)f(as)g +(in)g(the)g(\\diag)p 2891 573 30 4 v 34 w(series")g(pap)s(er.)257 +693 y Fj(F)14 b Fk(\()p Fj(z)421 657 y Ff(2)461 693 y +Fk(\))33 b(is)f(the)h(co)s(e\016cien)m(t)g(of)f Fj(t)1399 +657 y Ff(0)1471 693 y Fk(in)356 958 y Fj(G)p Fk(\()p +Fj(z)t(t;)610 890 y(z)p 610 934 50 4 v 617 1026 a(t)669 +958 y Fk(\))c(=)1254 890 y(2)p Fj(t)p 848 934 895 4 v +848 1026 a Fk(2)p Fj(t)23 b Fh(\000)f Fk(\(\()p Fj(x)h +Fk(+)f Fj(z)t(t)p Fk(\))1428 997 y Ff(2)1490 1026 y Fh(\000)h +Fk(1\))16 b Fj(z)1780 958 y Fk(=)2598 890 y(2)p Fj(t)p +1894 934 1493 4 v 1894 1026 a Fh(\000)p Fj(z)2020 997 +y Ff(3)2083 1026 y Fh(\001)22 b Fj(t)2168 997 y Ff(2)2229 +1026 y Fk(+)g(2\(1)g Fh(\000)h Fj(xz)2689 997 y Ff(2)2729 +1026 y Fk(\))f Fh(\001)g Fj(t)h Fk(+)f(\()p Fj(z)k Fh(\000)d +Fj(x)3259 997 y Ff(2)3299 1026 y Fj(z)t Fk(\))257 1234 +y(The)34 b(splitting)c(\014eld)j(of)f(the)h(denominator)e(is)h +Fj(L)c Fk(=)f Fj(Q)p Fk(\()p Fj(x)p Fk(\)\()p Fj(z)t +Fk(\)\()p Fj(\013)q Fk(\))34 b(where)1168 1523 y Fj(\013)1230 +1539 y Ff(1)p Fi(=)p Ff(2)1368 1523 y Fk(=)1481 1456 +y(1)22 b Fh(\000)h Fj(xz)1756 1420 y Ff(2)1819 1456 y +Fh(\006)1918 1374 y(p)p 2001 1374 574 4 v 82 x Fk(1)f +Fh(\000)h Fk(2)p Fj(xz)2325 1427 y Ff(2)2387 1456 y Fk(+)f +Fj(z)2534 1427 y Ff(4)p 1481 1500 1094 4 v 1983 1592 +a Fj(z)2032 1563 y Ff(3)834 1946 y Fj(\013)28 b Fk(=)f +Fj(\013)1089 1961 y Ff(1)1157 1946 y Fk(=)1290 1878 y(2)p +1270 1922 90 4 v 1270 2014 a Fj(z)1319 1985 y Ff(3)1391 +1946 y Fh(\000)1501 1878 y Fk(2)p Fj(x)p 1501 1922 105 +4 v 1528 2014 a(z)1637 1946 y Fk(+)1745 1878 y(1)22 b +Fh(\000)h Fj(x)1971 1842 y Ff(2)p 1745 1922 266 4 v 1854 +2014 a Fk(2)2021 1946 y Fj(z)k Fk(+)22 b Fh(\001)17 b(\001)g(\001)25 +b(2)k Fj(Q)p Fk(\()p Fj(x)p Fk(\)[[)p Fj(z)t Fk(]][)2831 +1878 y(1)p 2831 1922 50 4 v 2831 2014 a Fj(z)2892 1946 +y Fk(])1168 2368 y Fj(\013)1230 2383 y Ff(2)1297 2368 +y Fk(=)1411 2300 y Fj(x)1466 2264 y Ff(2)1528 2300 y +Fh(\000)22 b Fk(1)p 1411 2345 266 4 v 1519 2436 a(2)1686 +2368 y Fj(z)27 b Fk(+)22 b Fh(\001)17 b(\001)g(\001)26 +b(2)i Fj(Q)p Fk(\()p Fj(x)p Fk(\)[[)p Fj(z)t Fk(]][)2496 +2300 y(1)p 2496 2345 50 4 v 2496 2436 a Fj(z)2557 2368 +y Fk(])257 2619 y(The)34 b(partial)c(fraction)i(decomp)s(osition)e(of)i +Fj(G)p Fk(\()p Fj(z)t(t;)2140 2580 y Fi(z)p 2140 2596 +36 4 v 2145 2653 a(t)2186 2619 y Fk(\))g(reads)897 2893 +y Fj(G)p Fk(\()p Fj(z)t(t;)1151 2825 y(z)p 1151 2869 +50 4 v 1158 2961 a(t)1210 2893 y Fk(\))c(=)g Fh(\000)1487 +2825 y Fk(2)p 1467 2869 90 4 v 1467 2961 a Fj(z)1516 +2932 y Ff(3)1588 2893 y Fh(\001)1786 2825 y Fk(1)p 1648 +2869 325 4 v 1648 2961 a Fj(\013)1710 2976 y Ff(1)1772 +2961 y Fh(\000)22 b Fj(\013)1933 2976 y Ff(2)2005 2893 +y Fh(\001)2055 2771 y Fg(\022)2204 2825 y Fj(\013)2266 +2840 y Ff(1)p 2126 2869 259 4 v 2126 2961 a Fj(t)g Fh(\000)h +Fj(\013)2345 2976 y Ff(1)2416 2893 y Fh(\000)2604 2825 +y Fj(\013)2666 2840 y Ff(2)p 2526 2869 V 2526 2961 a +Fj(t)f Fh(\000)h Fj(\013)2745 2976 y Ff(2)2794 2771 y +Fg(\023)257 3153 y Fk(It)33 b(follo)m(ws)e(that)656 3393 +y Fj(F)14 b Fk(\()p Fj(z)820 3351 y Ff(2)860 3393 y Fk(\))28 +b(=)f Fh(\000)1137 3325 y Fk(2)p 1116 3369 90 4 v 1116 +3461 a Fj(z)1165 3432 y Ff(3)1238 3393 y Fh(\001)1436 +3325 y Fk(1)p 1298 3369 325 4 v 1298 3461 a Fj(\013)1360 +3476 y Ff(1)1421 3461 y Fh(\000)c Fj(\013)1583 3476 y +Ff(2)1654 3393 y Fh(\001)1704 3271 y Fg(\022)1861 3325 +y Fj(\013)1923 3340 y Ff(1)p 1775 3369 273 4 v 1775 3461 +a Fk(0)f Fh(\000)h Fj(\013)2008 3476 y Ff(1)2079 3393 +y Fh(\000)g Fk(0)2228 3271 y Fg(\023)2317 3393 y Fk(=)2734 +3325 y(1)p 2430 3369 657 4 v 2430 3387 a Fh(p)p 2513 +3387 574 4 v 82 x Fk(1)f Fh(\000)h Fk(2)p Fj(xz)2837 +3440 y Ff(2)2899 3469 y Fk(+)f Fj(z)3046 3440 y Ff(4)257 +3660 y Fk(hence)1391 3800 y Fj(F)14 b Fk(\()p Fj(z)t +Fk(\))28 b(=)2019 3733 y(1)p 1735 3777 617 4 v 1735 3795 +a Fh(p)p 1818 3795 534 4 v 81 x Fk(1)22 b Fh(\000)g Fk(2)p +Fj(xz)27 b Fk(+)22 b Fj(z)2311 3847 y Ff(2)404 4038 y +Fk(It)34 b(follo)m(ws)f(that)h(\(1)23 b Fh(\000)g Fk(2)p +Fj(xz)28 b Fk(+)23 b Fj(z)1581 4002 y Ff(2)1622 4038 +y Fk(\))g Fh(\001)1761 3999 y Fi(d)p 1744 4015 72 4 v +1744 4072 a(dz)1825 4038 y Fj(F)37 b Fk(+)23 b(\()p Fj(z)28 +b Fh(\000)c Fj(x)p Fk(\))g Fh(\001)e Fj(F)44 b Fk(=)31 +b(0.)47 b(This)35 b(is)e(equiv)-5 b(alen)m(t)257 4158 +y(to)33 b(the)g(claimed)d(recurrence.)404 4279 y(Starting)f(from)h(the) +h(closed)g(form)e(for)i Fj(F)14 b Fk(,)30 b(w)m(e)i(compute)f(a)g +(linear)e(relation)g(for)h(the)257 4399 y(partial)h(deriv)-5 +b(ativ)m(es)32 b(of)g Fj(F)14 b Fk(.)44 b(W)-8 b(rite)31 +b Fj(@)1637 4414 y Fi(x)1710 4399 y Fk(=)1843 4360 y +Fi(d)p 1823 4376 77 4 v 1823 4433 a(dx)1942 4399 y Fk(and)h(\001)2212 +4414 y Fi(z)2280 4399 y Fk(=)c Fj(z)2461 4360 y Fi(d)p +2443 4376 72 4 v 2443 4433 a(dz)2525 4399 y Fk(.)44 b(One)33 +b(computes)1674 4619 y Fj(F)41 b Fk(=)28 b(1)21 b Fh(\001)h +Fj(F)1273 4842 y Fg(\020)1323 4939 y Fk(1)f Fh(\000)i +Fk(2)p Fj(xz)k Fk(+)22 b Fj(z)1816 4898 y Ff(2)1856 4842 +y Fg(\021)1928 4939 y Fh(\001)g Fj(@)2029 4954 y Fi(x)2073 +4939 y Fj(F)42 b Fk(=)27 b Fj(z)g Fh(\001)22 b Fj(F)1209 +5212 y Fg(\020)1258 5308 y Fk(1)g Fh(\000)h Fk(2)p Fj(xz)k +Fk(+)22 b Fj(z)1752 5267 y Ff(2)1792 5212 y Fg(\021)1842 +5235 y Ff(2)1903 5308 y Fh(\001)g Fj(@)2009 5267 y Ff(2)2004 +5333 y Fi(x)2049 5308 y Fj(F)42 b Fk(=)27 b(3)p Fj(z)2355 +5267 y Ff(2)2417 5308 y Fh(\001)22 b Fj(F)1852 5637 y +Fk(2)p eop +%%Page: 3 3 +3 2 bop 1089 697 a Fg(\020)1139 793 y Fk(1)21 b Fh(\000)i +Fk(2)p Fj(xz)k Fk(+)22 b Fj(z)1632 752 y Ff(2)1672 697 +y Fg(\021)1744 793 y Fh(\001)g Fk(\001)1875 808 y Fi(z)1915 +793 y Fj(F)41 b Fk(=)28 b(\()p Fj(xz)f Fh(\000)c Fj(z)2437 +752 y Ff(2)2477 793 y Fk(\))f Fh(\001)g Fj(F)893 1066 +y Fg(\020)942 1162 y Fk(1)g Fh(\000)h Fk(2)p Fj(xz)k +Fk(+)22 b Fj(z)1436 1121 y Ff(2)1476 1066 y Fg(\021)1526 +1089 y Ff(2)1587 1162 y Fh(\001)g Fj(@)1688 1177 y Fi(x)1732 +1162 y Fk(\001)1813 1177 y Fi(z)1853 1162 y Fj(F)42 b +Fk(=)27 b(\()p Fj(z)g Fk(+)22 b Fj(xz)2373 1121 y Ff(2)2436 +1162 y Fh(\000)h Fk(2)p Fj(z)2634 1121 y Ff(3)2673 1162 +y Fk(\))g Fh(\001)e Fj(F)650 1435 y Fg(\020)700 1532 +y Fk(1)g Fh(\000)i Fk(2)p Fj(xz)k Fk(+)22 b Fj(z)1193 +1491 y Ff(2)1233 1435 y Fg(\021)1283 1458 y Ff(2)1345 +1532 y Fh(\001)f Fk(\001)1475 1491 y Ff(2)1475 1556 y +Fi(z)1515 1532 y Fj(F)42 b Fk(=)1723 1435 y Fg(\020)1773 +1532 y Fj(xz)27 b Fk(+)22 b(\()p Fj(x)2091 1491 y Ff(2)2153 +1532 y Fh(\000)h Fk(2\))p Fj(z)2389 1491 y Ff(2)2451 +1532 y Fh(\000)f Fj(xz)2654 1491 y Ff(3)2717 1532 y Fk(+)g +Fj(z)2864 1491 y Ff(4)2904 1435 y Fg(\021)2976 1532 y +Fh(\001)g Fj(F)257 1764 y Fk(Solv)m(e)33 b(a)f(homogeneous)h(5)22 +b Fh(\002)h Fk(6)32 b(system)h(of)g(linear)d(equations)j(o)m(v)m(er)h +Fj(Q)p Fk(\()p Fj(x)p Fk(\))f(to)f(get)443 1917 y Fg(\020)492 +2013 y Fk(1)22 b Fh(\000)h Fk(2)p Fj(xz)k Fk(+)22 b Fj(z)986 +1972 y Ff(2)1026 1917 y Fg(\021)1076 1940 y Ff(2)1137 +2013 y Fh(\001)1187 1917 y Fg(\020)1237 2013 y Fk(\()p +Fh(\000)p Fk(2)p Fj(x)p Fk(\))g Fh(\001)g Fj(@)1617 2028 +y Fi(x)1661 2013 y Fj(F)36 b Fk(+)22 b(\(1)g Fh(\000)h +Fj(x)2122 1972 y Ff(2)2162 2013 y Fk(\))f Fh(\001)g Fj(@)2328 +1972 y Ff(2)2323 2038 y Fi(x)2368 2013 y Fj(F)36 b Fk(+)22 +b(\001)2646 2028 y Fi(z)2686 2013 y Fj(F)36 b Fk(+)22 +b(\001)2964 1972 y Ff(2)2964 2038 y Fi(z)3004 2013 y +Fj(F)3081 1917 y Fg(\021)3158 2013 y Fk(=)27 b(0)257 +2233 y(Divide)32 b(b)m(y)h(the)g(\014rst)g(factor)f(to)g(get)864 +2453 y(\()p Fh(\000)p Fk(2)p Fj(x)p Fk(\))23 b Fh(\001)f +Fj(@)1245 2468 y Fi(x)1289 2453 y Fj(F)36 b Fk(+)22 b(\(1)g +Fh(\000)h Fj(x)1750 2412 y Ff(2)1789 2453 y Fk(\))g Fh(\001)e +Fj(@)1955 2412 y Ff(2)1950 2478 y Fi(x)1996 2453 y Fj(F)36 +b Fk(+)22 b(\001)2274 2468 y Fi(z)2314 2453 y Fj(F)35 +b Fk(+)22 b(\001)2591 2412 y Ff(2)2591 2478 y Fi(z)2632 +2453 y Fj(F)41 b Fk(=)27 b(0)257 2673 y(This)h(is)f(equiv)-5 +b(alen)m(t)27 b(to)h(the)g(claimed)d(equation)j(\(1)12 +b Fh(\000)g Fj(x)2293 2637 y Ff(2)2332 2673 y Fk(\))g +Fh(\001)g Fj(P)2499 2614 y Fc(00)2485 2698 y Fi(n)2543 +2673 y Fk(\()p Fj(x)p Fk(\))g Fh(\000)g Fk(2)p Fj(x)g +Fh(\001)g Fj(P)3008 2614 y Fc(0)2994 2698 y Fi(n)3041 +2673 y Fk(\()p Fj(x)p Fk(\))g(+)g(\()p Fj(n)3368 2637 +y Ff(2)3419 2673 y Fk(+)257 2794 y Fj(n)p Fk(\))23 b +Fh(\001)e Fj(P)488 2809 y Fi(n)535 2794 y Fk(\()p Fj(x)p +Fk(\))28 b(=)g(0.)257 3126 y Fb(References)62 3345 y +Fk(1)146 b(Bruno)46 b(Haible:)69 b(D-\014nite)45 b(p)s(o)m(w)m(er)i +(series)g(in)e(sev)m(eral)i(v)-5 b(ariables.)82 b Fa(Diploma)46 +b(thesis,)501 3466 y(University)35 b(of)g(Karlsruhe,)f(June)h(1989)p +Fk(.)43 b(Sections)33 b(2.14,)f(2.15)g(and)h(2.22.)1852 +5637 y(3)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/polynomial/legendre.tex b/doc/polynomial/legendre.tex new file mode 100644 index 0000000..1bf6d78 --- /dev/null +++ b/doc/polynomial/legendre.tex @@ -0,0 +1,224 @@ +%% This LaTeX-file was created by Sun Feb 16 14:24:52 1997 +%% LyX 0.10 (C) 1995 1996 by Matthias Ettrich and the LyX Team + +%% Don't edit this file unless you are sure what you are doing. +\documentclass[12pt,a4paper,oneside,onecolumn]{article} +\usepackage[]{fontenc} +\usepackage[latin1]{inputenc} +\usepackage[dvips]{epsfig} + +%% +%% BEGIN The lyx specific LaTeX commands. +%% + +\makeatletter +\def\LyX{L\kern-.1667em\lower.25em\hbox{Y}\kern-.125emX\spacefactor1000}% +\newcommand{\lyxtitle}[1] {\thispagestyle{empty} +\global\@topnum\z@ +\section*{\LARGE \centering \sffamily \bfseries \protect#1 } +} +\newcommand{\lyxline}[1]{ +{#1 \vspace{1ex} \hrule width \columnwidth \vspace{1ex}} +} +\newenvironment{lyxsectionbibliography} +{ +\section*{\refname} +\@mkboth{\uppercase{\refname}}{\uppercase{\refname}} +\begin{list}{}{ +\itemindent-\leftmargin +\labelsep 0pt +\renewcommand{\makelabel}{} +} +} +{\end{list}} +\newenvironment{lyxchapterbibliography} +{ +\chapter*{\bibname} +\@mkboth{\uppercase{\bibname}}{\uppercase{\bibname}} +\begin{list}{}{ +\itemindent-\leftmargin +\labelsep 0pt +\renewcommand{\makelabel}{} +} +} +{\end{list}} +\def\lxq{"} +\newenvironment{lyxcode} +{\list{}{ +\rightmargin\leftmargin +\raggedright +\itemsep 0pt +\parsep 0pt +\ttfamily +}% +\item[] +} +{\endlist} +\newcommand{\lyxlabel}[1]{#1 \hfill} +\newenvironment{lyxlist}[1] +{\begin{list}{} +{\settowidth{\labelwidth}{#1} +\setlength{\leftmargin}{\labelwidth} +\addtolength{\leftmargin}{\labelsep} +\renewcommand{\makelabel}{\lyxlabel}}} +{\end{list}} +\newcommand{\lyxletterstyle}{ +\setlength\parskip{0.7em} +\setlength\parindent{0pt} +} +\newcommand{\lyxaddress}[1]{ +\par {\raggedright #1 +\vspace{1.4em} +\noindent\par} +} +\newcommand{\lyxrightaddress}[1]{ +\par {\raggedleft \begin{tabular}{l}\ignorespaces +#1 +\end{tabular} +\vspace{1.4em} +\par} +} +\newcommand{\lyxformula}[1]{ +\begin{eqnarray*} +#1 +\end{eqnarray*} +} +\newcommand{\lyxnumberedformula}[1]{ +\begin{eqnarray} +#1 +\end{eqnarray} +} +\makeatother + +%% +%% END The lyx specific LaTeX commands. +%% + +\pagestyle{plain} +\setcounter{secnumdepth}{3} +\setcounter{tocdepth}{3} + +%% Begin LyX user specified preamble: +\catcode`@=11 % @ ist ab jetzt ein gewoehnlicher Buchstabe +\def\mod#1{\allowbreak \mkern8mu \mathop{\operator@font mod}\,\,{#1}} +\def\pmod#1{\allowbreak \mkern8mu \left({\mathop{\operator@font mod}\,\,{#1}}\right)} +\catcode`@=12 % @ ist ab jetzt wieder ein Sonderzeichen + + +%% End LyX user specified preamble. +\begin{document} + +The Legendre polynomials \( P_{n}(x) \) are defined through +\[ +P_{n}(x)=\frac{1}{2^{n}n!}\cdot \left( \frac{d}{dx}\right) ^{n}(x^{2}-1)^{n}\] +(For a motivation +of the \( 2^{n} \) in the denominator, look at \( P_{n}(x) \) modulo an odd prime \( p \), and +observe that \( P_{n}(x)\equiv P_{p-1-n}(x)\mod p \) for \( 0\leq n\leq p-1 \). This wouldn't hold if the \( 2^{n} \) factor in the denominator +weren't present.) + +\begin{description} + +\item [Theorem:]~ + +\end{description} + + \( P_{n}(x) \) satisfies the recurrence relation + + +\[ +P_{0}(x)=1\] + + + +\[ +(n+1)\cdot P_{n+1}(x)=(2n+1)x\cdot P_{n}(x)-n\cdot P_{n-1}(x)\] +for \( n\geq 0 \) and the differential equation \( (1-x^{2})\cdot P_{n}^{''}(x)-2x\cdot P_{n}^{'}(x)+(n^{2}+n)\cdot P_{n}(x)=0 \) for all \( n\geq 0 \). + +\begin{description} + +\item [Proof:]~ + +\end{description} + +Let \( F:=\sum ^{\infty }_{n=0}P_{n}(x)\cdot z^{n} \) be the generating function of the sequence of polynomials. It +is the diagonal series of the power series +\[ +G:=\sum _{m,n=0}^{\infty }\frac{1}{2^{n}m!}\cdot \left( \frac{d}{dx}\right) ^{m}(x^{2}-1)^{n}\cdot y^{m}\cdot z^{n}\] +Because the Taylor series +development theorem holds in formal power series rings (see [1], section +2.16), we can simplify +\begin{eqnarray*} +G & = & \sum _{n=0}^{\infty }\frac{1}{2^{n}}\cdot \left( \sum _{m=0}^{\infty }\frac{1}{m!}\cdot \left( \frac{d}{dx}\right) ^{m}(x^{2}-1)^{n}\cdot y^{m}\right) \cdot z^{n}\\ + & = & \sum _{n=0}^{\infty }\frac{1}{2^{n}}\cdot \left( (x+y)^{2}-1\right) ^{n}\cdot z^{n}\\ + & = & \frac{1}{1-\frac{1}{2}\left( (x+y)^{2}-1\right) z} +\end{eqnarray*} +We take over the terminology from the ``diag\_rational'' +paper; here \( R=Q[x] \) and \( M=Q[[x]] \) (or, if you like it better, \( M=H(C) \), the algebra of +functions holomorphic in the entire complex plane). \( G\in M[[y,z]] \) is rational; +hence \( F \) is algebraic over \( R[z] \). Let's proceed exactly as in the ``diag\_series'' +paper. \( F(z^{2}) \) is the coefficient of \( t^{0} \) in +\[ +G(zt,\frac{z}{t})=\frac{2t}{2t-\left( (x+zt)^{2}-1\right) z}=\frac{2t}{-z^{3}\cdot t^{2}+2(1-xz^{2})\cdot t+(z-x^{2}z)}\] +The splitting field of the denominator +is \( L=Q(x)(z)(\alpha ) \) where +\[ +\alpha _{1/2}=\frac{1-xz^{2}\pm \sqrt{1-2xz^{2}+z^{4}}}{z^{3}}\] + +\[ +\alpha =\alpha _{1}=\frac{2}{z^{3}}-\frac{2x}{z}+\frac{1-x^{2}}{2}z+\cdots \in Q(x)[[z]][\frac{1}{z}]\] + +\[ +\alpha _{2}=\frac{x^{2}-1}{2}z+\cdots \in Q(x)[[z]][\frac{1}{z}]\] +The partial fraction decomposition of \( G(zt,\frac{z}{t}) \) reads +\[ +G(zt,\frac{z}{t})=-\frac{2}{z^{3}}\cdot \frac{1}{\alpha _{1}-\alpha _{2}}\cdot \left( \frac{\alpha _{1}}{t-\alpha _{1}}-\frac{\alpha _{2}}{t-\alpha _{2}}\right) \] +It follows +that +\[ +F(z^{2})=-\frac{2}{z^{3}}\cdot \frac{1}{\alpha _{1}-\alpha _{2}}\cdot \left( \frac{\alpha _{1}}{0-\alpha _{1}}-0\right) =\frac{1}{\sqrt{1-2xz^{2}+z^{4}}}\] +hence +\[ +F(z)=\frac{1}{\sqrt{1-2xz+z^{2}}}\] + + +It follows that \( (1-2xz+z^{2})\cdot \frac{d}{dz}F+(z-x)\cdot F=0 \). This is equivalent to the claimed recurrence. + +Starting from the closed form for \( F \), we compute a linear relation +for the partial derivatives of \( F \). Write \( \partial _{x}=\frac{d}{dx} \) and \( \Delta _{z}=z\frac{d}{dz} \). One computes +\[ +F=1\cdot F\] + +\[ +\left( 1-2xz+z^{2}\right) \cdot \partial _{x}F=z\cdot F\] + +\[ +\left( 1-2xz+z^{2}\right) ^{2}\cdot \partial _{x}^{2}F=3z^{2}\cdot F\] + +\[ +\left( 1-2xz+z^{2}\right) \cdot \Delta _{z}F=(xz-z^{2})\cdot F\] + +\[ +\left( 1-2xz+z^{2}\right) ^{2}\cdot \partial _{x}\Delta _{z}F=(z+xz^{2}-2z^{3})\cdot F\] + +\[ +\left( 1-2xz+z^{2}\right) ^{2}\cdot \Delta _{z}^{2}F=\left( xz+(x^{2}-2)z^{2}-xz^{3}+z^{4}\right) \cdot F\] +Solve +a homogeneous \( 5\times 6 \) system of linear equations over \( Q(x) \) to get +\[ +\left( 1-2xz+z^{2}\right) ^{2}\cdot \left( (-2x)\cdot \partial _{x}F+(1-x^{2})\cdot \partial _{x}^{2}F+\Delta _{z}F+\Delta _{z}^{2}F\right) =0\] +Divide by +the first factor to get +\[ +(-2x)\cdot \partial _{x}F+(1-x^{2})\cdot \partial _{x}^{2}F+\Delta _{z}F+\Delta _{z}^{2}F=0\] +This is equivalent to the claimed equation + \( (1-x^{2})\cdot P_{n}^{''}(x)-2x\cdot P_{n}^{'}(x)+(n^{2}+n)\cdot P_{n}(x)=0 \). + +\begin{lyxsectionbibliography} + +\item [1] Bruno Haible: D-finite power series in several variables. \em Diploma +thesis, University of Karlsruhe, June 1989\em . Sections 2.14, 2.15 +and 2.22. + +\end{lyxsectionbibliography} + +\end{document} diff --git a/doc/polynomial/tchebychev.dvi b/doc/polynomial/tchebychev.dvi new file mode 100644 index 0000000000000000000000000000000000000000..8a1b9761d218d41d56f01098888d40a59ae560d7 GIT binary patch literal 6372 zcmcIp3vd+m8Q**5;YA2&K#(E@9TO7LyGsZV%oG@hf;?1+G1~gr-0kI7?{?$vUPxkR z#8$^x-6fkX*M+pb(DDd@+Sjyo!^H%uwU5*~PNzEU*kH?4t9B}L*oaE$_x*SG9&ph@ zr#Iwv_uv2j`~SY*_kF+bW6J6HYXA6x)fBv3Z(X~nnQ2|b$EA+Aw8+0|)rwkQpw{2e z=&$!RJOwKpxa`wj=ixQzJVa6Q;JI#!8g#Pc*A#qLeaSQF8LdZd_floB4SsooF~J`& znj_4Bt6@vC7~FkSh%jwhcTkHkoq9*#c7>02b9{`YqoQ8Phjl5!=zdYsA7r^um7bpU zvp3qmo7t`?7>lv~K&n|zIwmI4vtM=04NxU;4t~K|F?QuBr>LHx+lO36w|P>+b;q_Q&95B3@-=ZEK3cNPdUV8p(Xv#Rau65wkDoMe zGRloq2b6*G$0l-j3#7Ud&f%f-)t_BlvzK6S1zZy_5WD@pF^6UyfDii>-F#9Tqq6Vk zAffCdcMkJ{3U^L%Xzy5sX83BA{qt)ZWtn`Oo_pdCTL*LDZtL;~PJsJ(fr&LLigI{< z?P}ua%;CyF2JVFGt-C}(P%L9a4dB&6td{|3`;H0{I9OvIiW7V_aE_e(=s;j3ps2;n z`(sqXdEm6+uhOhr!AD?_W8W{5=ax05=RCCU1}{~FcQ@TEb~haN`4lBtylt%v4u?%V z&DQ;^wNzKZZI0(Ykc$?VXNn_Bkn9z+j57V~L*f9I8Xb*ld0_6dkUVjl!1vux@nHn* zAVJL7%t#3jdtYk3TKtvAjm9Qf^_(0_PM!ZaO?~*o_-qQjYk8RI^81e5rhsKj56Nmd z_hGu?xlOuWOu4ZR;k{rq#0=1jm}Cxavj)f0PTqbdsJ85QwI3cHr=}i`Qq8|reP9gz3QI2#%NN3 z%6`Io>p9@MN#~3cRQFEGpY;TIzAX&6!y?Wl$BJeQ+6a*13bfYs!ni9cI zQQ2>2upO)vNx0noL3mf9xxEl(T98M#&Iqy$r%NK3A4u%b8SO!i*LT2{w4~vm5nAtr zAK(u3B_jZrV;Ze>&}N{91)8wH${Hai$j6A&MHZo|Rf}&O+|DQ5-+U{|NLs1`Vy|Za z;i^iwA2XWJWx5^TCDC^vzFpV5a~*s1O>nFqH^{Ou#9$rZXbIzr3u!5@>ee?HO_mX6 zGBm1X!17@z%)5VVu#%|tFap09&=74#UxbHdBBApp4&W3zBr3^;#iO#yZC{bg zlc_gekkzZNF0*N!vbo~9J!W!c&6X8OZ;4kn>?H`$g`_txLKw2~-nAwL$<{zSEG$62 z%!Z!HkI9CFQ4j%F4*V#2I(+Yu*$NVuJazs0YCuDsQ+-$VvBedGbB za!I)F?JbnFRQG%(8+4v6$I)BxBO7n-HEt4bs3(thu zWfnJM42PjfM-wh(lIfDnKh3=$cJ1vn$SXl8h7lU$ixF5+VuP9wf^=VFgcf1rILAW1 z1)2#~;v{m!tleba5Ezh2LnRaIMnj5P)c#Tyk9UTJSA+R*Wl-Mmw zOboY=vK&JT8O~qI>UAS|8b^uF+>=kQd`cv zl5-{`<7Bz7#uU99B~vR$qdfS12lfS!X)%}bQUuH_7#=w)n?!fssvMeH>uT@_Qc27W z?WPKX&F%#6v6j|i@qu2opPDRpf-ZO(8($}U{Wq_r(=@&X)MlU&%iOitYC>0RY?n}3 zaqS8B@z$^{?r4Gnbi|z+GXNjhsu-%xlzWH9=%~8l5~I_)84SAJpz4qbu~W{GrJouMMn6$6eMFiB=&UxpX-7mq_4nq_jX6kkUEDJCD2HcLMc6U) zQ(E1T%t3oNBIT~t3A6GR*4vEBg9>h&TtF3BX%$2S=uk3xptS}vL2znD1E#_0m4wD) z^9wT7Qu!!)+ZhQYOF#8Q%L22}#Cmo?+zz-mb9lw<4b@_+!88XFuzvcuA~ytLd>WQM zlul4Hnj_@Osy90EXSrE zr?~5cIL9YEz4JEEY+ICRR7=DYH!m|AG%~V)`Unm;)+M zpYSwv{#VQjq~{MD>s^yO1(jgv{KCy3eEArydcNNXrB`Id8uZjn_q}@u$96ITj0Cz9 z?z-hrYd6tCR21S7rbfFZ4rR^1YUL_W(_z-w&XBnZbTe-c!R$Q%9Z*PvUzX?T5)e>N ze?U<)m*h_Gapvwg05YYNau&8QT@b&*Gu?ti)q+FD!sF+Hv-iT&`a)B$bb)z#!T&la PJQ_VqQFD(uC&}wSjf%I- literal 0 HcmV?d00001 diff --git a/doc/polynomial/tchebychev.lyx b/doc/polynomial/tchebychev.lyx new file mode 100644 index 0000000..a5b0bfb --- /dev/null +++ b/doc/polynomial/tchebychev.lyx @@ -0,0 +1,333 @@ +#This file was created by Sun Feb 16 00:32:21 1997 +#LyX 0.10 (C) 1995 1996 Matthias Ettrich and the LyX Team +\lyxformat 2.10 +\textclass article +\language default +\inputencoding latin1 +\fontscheme default +\epsfig dvips +\papersize a4paper +\paperfontsize 12 +\baselinestretch 1.00 +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation indent +\quotes_language english +\quotes_times 2 +\paperorientation portrait +\papercolumns 1 +\papersides 1 +\paperpagestyle plain + +\layout Standard + +The Tschebychev polynomials (of the 1st kind) +\begin_inset Formula \( T_{n}(x) \) +\end_inset + + are defined through the recurrence relation +\layout Standard + + +\begin_inset Formula +\[ +T_{0}(x)=1\] + +\end_inset + + +\layout Standard + + +\begin_inset Formula +\[ +T_{1}(x)=x\] + +\end_inset + + +\layout Standard + + +\begin_inset Formula +\[ +T_{n+2}(x)=2x\cdot T_{n+1}(x)-T_{n}(x)\] + +\end_inset + + for +\begin_inset Formula \( n\geq 0 \) +\end_inset + +. + +\layout Description + +Theorem: +\layout Standard + + +\begin_inset Formula \( T_{n}(x) \) +\end_inset + + satisfies the differential equation +\begin_inset Formula \( (x^{2}-1)\cdot T_{n}^{''}(x)+x\cdot T_{n}^{'}(x)-n^{2}\cdot T_{n}(x)=0 \) +\end_inset + + for all +\begin_inset Formula \( n\geq 0 \) +\end_inset + +. + +\layout Description + +Proof: +\layout Standard + +Let +\begin_inset Formula \( F:=\sum ^{\infty }_{n=0}T_{n}(x)z^{n} \) +\end_inset + + be the generating function of the sequence of polynomials. + The recurrence is equivalent to the equation +\begin_inset Formula +\[ +(1-2x\cdot z+z^{2})\cdot F=1-x\cdot z\] + +\end_inset + + +\layout Description + +Proof +\protected_separator +1: +\layout Standard + + +\begin_inset Formula \( F \) +\end_inset + + is a rational function in +\begin_inset Formula \( z \) +\end_inset + +, +\begin_inset Formula \( F=\frac{1-xz}{1-2xz+z^{2}} \) +\end_inset + +. + From the theory of recursions with constant coefficients, we know that + we have to perform a partial fraction decomposition. + So let +\begin_inset Formula \( p(z)=z^{2}-2x\cdot z+1 \) +\end_inset + + be the denominator and +\begin_inset Formula \( \alpha =x+\sqrt{x^{2}-1} \) +\end_inset + + and +\begin_inset Formula \( \alpha ^{-1} \) +\end_inset + + its zeroes. + The partial fraction decomposition reads +\begin_inset Formula +\[ +F=\frac{1-xz}{1-2xz+z^{2}}=\frac{1}{2}\left( \frac{1}{1-\alpha z}+\frac{1}{1-\alpha ^{-1}z}\right) \] + +\end_inset + + hence +\begin_inset Formula \( T_{n}(x)=\frac{1}{2}(\alpha ^{n}+\alpha ^{-n}) \) +\end_inset + +. + Note that the field +\begin_inset Formula \( Q(x)(\alpha ) \) +\end_inset + +, being a finite dimensional extension field of +\begin_inset Formula \( Q(x) \) +\end_inset + + in characteristic 0, has a unique derivation extending +\begin_inset Formula \( \frac{d}{dx} \) +\end_inset + + on +\begin_inset Formula \( Q(x) \) +\end_inset + +. + We can therefore try to construct an annihilating differential operator + for +\begin_inset Formula \( T_{n}(x) \) +\end_inset + + by combination of annihilating differential operators for +\begin_inset Formula \( \alpha ^{n} \) +\end_inset + + and +\begin_inset Formula \( \alpha ^{-n} \) +\end_inset + +. + In fact, +\begin_inset Formula \( L_{1}:=(\alpha -x)\frac{d}{dx}-n \) +\end_inset + + satisfies +\begin_inset Formula \( L_{1}[\alpha ^{n}]=0 \) +\end_inset + +, and +\begin_inset Formula \( L_{2}:=(\alpha -x)\frac{d}{dx}+n \) +\end_inset + + satisfies +\begin_inset Formula \( L_{2}[\alpha ^{-n}]=0 \) +\end_inset + +. + A common multiple of +\begin_inset Formula \( L_{1} \) +\end_inset + + and +\begin_inset Formula \( L_{2} \) +\end_inset + + is easily found by solving an appropriate system of linear equations: +\layout Standard + + +\begin_inset Formula \( L=(x^{2}-1)\left( \frac{d}{dx}\right) ^{2}+x\frac{d}{dx}-n^{2}=\left( (\alpha -x)\frac{d}{dx}+n\right) \cdot L_{1}=\left( (\alpha -x)\frac{d}{dx}-n\right) \cdot L_{2} \) +\end_inset + + +\layout Standard + +It follows that both +\begin_inset Formula \( L[\alpha ^{n}]=0 \) +\end_inset + + and +\begin_inset Formula \( L[\alpha ^{-n}]=0 \) +\end_inset + +, hence +\begin_inset Formula \( L[T_{n}(x)]=0 \) +\end_inset + +. + +\layout Description + +Proof +\protected_separator +2: +\layout Standard + +Starting from the above equation, we compute a linear relation for the partial + derivatives of +\begin_inset Formula \( F \) +\end_inset + +. + Write +\begin_inset Formula \( \partial _{x}=\frac{d}{dx} \) +\end_inset + + and +\begin_inset Formula \( \Delta _{z}=z\frac{d}{dz} \) +\end_inset + +. + One computes +\layout Standard + + +\begin_inset Formula +\[ +\left( 1-2xz+z^{2}\right) \cdot F=1-xz\] + +\end_inset + + +\begin_inset Formula +\[ +\left( 1-2xz+z^{2}\right) ^{2}\cdot \partial _{x}F=z-z^{3}\] + +\end_inset + + +\begin_inset Formula +\[ +\left( 1-2xz+z^{2}\right) ^{3}\cdot \partial _{x}^{2}F=4z^{2}-4z^{4}\] + +\end_inset + + +\begin_inset Formula +\[ +\left( 1-2xz+z^{2}\right) ^{2}\cdot \Delta _{z}F=xz-2z^{2}+xz^{3}\] + +\end_inset + + +\begin_inset Formula +\[ +\left( 1-2xz+z^{2}\right) ^{3}\cdot \partial _{x}\Delta _{z}F=z+2xz^{2}-6z^{3}+2xz^{4}+z^{5}\] + +\end_inset + + +\begin_inset Formula +\[ +\left( 1-2xz+z^{2}\right) ^{3}\cdot \Delta _{z}^{2}F=xz+(2x^{2}-4)z^{2}-(2x^{2}-4)z^{4}-xz^{5}\] + +\end_inset + + +\layout Standard + +Solve a +\begin_inset Formula \( 6\times 6 \) +\end_inset + + system of linear equations over +\begin_inset Formula \( Q(x) \) +\end_inset + + to get +\begin_inset Formula +\[ +x\cdot \partial _{x}F+(x^{2}-1)\cdot \partial _{x}^{2}F-\Delta _{z}^{2}F=0\] + +\end_inset + + +\layout Standard + +This is equivalent to the claimed equation +\begin_inset Formula \( (x^{2}-1)\cdot T_{n}^{''}(x)+x\cdot T_{n}^{'}(x)-n^{2}\cdot T_{n}(x)=0 \) +\end_inset + +. + +\layout Bibliography +\cursor 137 +[1] Bruno Haible: D-finite power series in several variables. + +\shape italic +Diploma thesis, University of Karlsruhe, June 1989. + +\shape default + Sections 2. +12 and 2. +15. + diff --git a/doc/polynomial/tchebychev.ps b/doc/polynomial/tchebychev.ps new file mode 100644 index 0000000..d24e464 --- /dev/null +++ b/doc/polynomial/tchebychev.ps @@ -0,0 +1,726 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: tchebychev.dvi +%%Pages: 2 +%%PageOrder: Ascend +%%BoundingBox: 0 0 596 842 +%%DocumentPaperSizes: a4 +%%EndComments +%DVIPSCommandLine: dvips -Pljfour -o tchebychev.ps tchebychev.dvi +%DVIPSParameters: dpi=600, compressed, comments removed +%DVIPSSource: TeX output 1997.02.16:1406 +%%BeginProcSet: texc.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]/id ch-image N /rw ch-width 7 add 8 idiv string N /rc 0 N /gp 0 N +/cp 0 N{rc 0 ne{rc 1 sub /rc X rw}{G}ifelse}imagemask restore}B /G{{id +gp get /gp gp 1 add N dup 18 mod S 18 idiv pl S get exec}loop}B /adv{cp +add /cp X}B /chg{rw cp id gp 4 index getinterval putinterval dup gp add +/gp X adv}B /nd{/cp 0 N rw exit}B /lsh{rw cp 2 copy get dup 0 eq{pop 1}{ +dup 255 eq{pop 254}{dup dup add 255 and S 1 and or}ifelse}ifelse put 1 +adv}B /rsh{rw cp 2 copy get dup 0 eq{pop 128}{dup 255 eq{pop 127}{dup 2 +idiv S 128 and or}ifelse}ifelse put 1 adv}B /clr{rw cp 2 index string +putinterval adv}B /set{rw cp fillstr 0 4 index getinterval putinterval +adv}B /fillstr 18 string 0 1 17{2 copy 255 put pop}for N /pl[{adv 1 chg} +{adv 1 chg nd}{1 add chg}{1 add chg nd}{adv lsh}{adv lsh nd}{adv rsh}{ +adv rsh nd}{1 add adv}{/rc X nd}{1 add set}{1 add clr}{adv 2 chg}{adv 2 +chg nd}{pop nd}]dup{bind pop}forall N /D{/cc X dup type /stringtype ne{] +}if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +TeXDict begin 39158280 55380996 1000 600 600 (tchebychev.dvi) +@start /Fa 25 122 df<13F0EA03FC1207A2EA0FFEA4EA07FCEA03CCEA000C131C1318 +A2133813301370136013E0EA01C013801203EA0700120E5A5A5A5A5A0F1D7A891E>44 +D<120FEA3FC0127FA212FFA31380EA7F00123C0A0A76891E>46 D<16C01501A215031507 +ED0F80151F153F157F913801FF005C140F147F903807FCFEEB0FF0EB0700EB00015DA314 +035DA314075DA3140F5DA3141F5DA3143F5DA3147F92C7FCA35C5CA313015CA313035CA3 +13075CA2130FA2131F133FB612FCA25D224276C132>49 D56 DI<91B712F818FF19C00201903980 +003FF06E90C7EA0FF84AED03FCF000FE4B157FA2F13F800203EE1FC05DF10FE0A214074B +16F01907A2140F5D1AF8A2141F5DA2190F143F5D1AF0A2147F4B151FA302FF17E092C912 +3FA34918C04A167F1A80A2010317FF4A1700A24E5A13074A4B5A611807010F5F4A4B5A18 +1F61011F4C5A4A4BC7FC18FE4D5A013F4B5A4A4A5A4D5A017FED3FC005FFC8FC4AEB03FE +01FFEC1FF8B812E094C9FC16F845447AC34A>68 D<031FB512F05DA29239000FFC005FA3 +5FA2161FA25FA2163FA25FA2167FA25FA216FFA294C7FCA25DA25EA21503A25EA21507A2 +5EA2150FA25EA2151FA25EA2153FA25EA2157FA25EEA0F80D83FE013FF93C8FC127FA24A +5AEAFFC04A5A1300007C495A0070495A4A5A6C5C003C495A6C01FEC9FC380F81F83803FF +E0C690CAFC344679C333>74 D<91B66C90383FFFF8A302010180C7000F13006E90C8EA07 +FC4A17F01AC04B4B5A4FC7FC193C02035E4B5DF003E0F0078002074BC8FC4B141E6018F8 +020F4A5A4BEB03C04D5A4DC9FC021F141E4B137C17F04C5A023F495A4B487E161F163F02 +7F497EED80FFED81EF923883CFF89138FF8F8FED1E07033C7F157849EBF00303E07F15C0 +92380001FF495A5C707FA213074A6E7EA2173F010F825C171F84131F4A140F84A2013F6F +7E5CA2017F6F7EA24A4A7E496C4A7FB66C90B512FC5E614D447AC34B>I<001FB500F090 +383FFFFCA326003FF0C7000113806D48913800FE00013F167C18785C187018F0017F5E5C +A2170101FF5E91C8FCA21703485F5BA21707000394C7FC5BA25F0007160E5BA2171E120F +49151CA2173C121F491538A21778123F491570A217F0127F495DA2160100FF5E90C8FCA2 +16035F16074893C8FC5E160E161E5E007E1538007F15785E6C4A5A6D495A001F4A5A6D49 +C9FC6C6C133E6C6C13F83903FC07F0C6B512C0013F90CAFCEB07F83E466DC348>85 +D97 D101 +DI<14FE137FA3EB01FC13001301A25CA21303A25CA21307A25CA2130FA25CA2131F +A25C157F90393F83FFC091388F81F091381E00F802387F4948137C5C4A137EA2495A91C7 +FCA25B484814FE5E5BA2000314015E5BA2000714035E5B1507000F5DA249130F5E001F16 +78031F1370491480A2003F023F13F0EE00E090C7FC160148023E13C01603007E1680EE07 +0000FEEC1E0FED1F1E48EC0FF80038EC03E02D467AC432>104 D<143C147E14FE1301A3 +EB00FC14701400AE137C48B4FC3803C780380703C0000F13E0120E121C13071238A21278 +EA700F14C0131F00F0138012E0EA003F1400A25B137EA213FE5B12015BA212035B141E00 +07131C13E0A2000F133CEBC038A21478EB807014F014E0EB81C0EA0783EBC7803803FE00 +EA00F8174378C11E>I108 +DI< +D801F0EB0FE0D803FCEB7FF83A071E01F03E3A0E0F03C01F001ED987001380001C018E13 +0F003C139C003801B814C014F838781FF000705BA25C00F049131FD8E03F158091C7FC12 +00163F491500137EA25E01FE147E5B16FE5E12014913015E170F00030203130E4914F0A2 +0307131E0007EDE01C5B173CEEC038000F167849157017E0ED03C1001FEDE3C049903801 +FF000007C8127C302D78AB37>III114 +DI<1470EB01F8A313 +035CA313075CA3130F5CA3131F5CA2007FB512E0B6FC15C0D8003FC7FCA25B137EA313FE +5BA312015BA312035BA312075BA3120F5BA2EC0780001F140013805C140E003F131EEB00 +1C143C14385C6C13F0495A6C485AEB8780D807FEC7FCEA01F81B3F78BD20>I<137C48B4 +14072603C780EB1F80380703C0000F7F000E153F121C0107150012385E1278D8700F147E +5C011F14FE00F05B00E05DEA003FEC0001A2495C137E150313FE495CA215071201495CA2 +030F13380003167849ECC070A3031F13F0EE80E0153F00011581037F13C06DEBEF830000 +0101148090397C03C787903A3E0F07C70090391FFE01FE903903F000782D2D78AB34>I< +017C143848B414FC3A03C78001FE380703C0000F13E0120E001C14000107147E1238163E +1278D8700F141E5C131F00F049131C12E0EA003F91C7123C16385B137E167801FE14705B +A216F0000115E05B150116C0A24848EB0380A2ED0700A2150E12015D6D5B000014786D5B +90387C01E090383F0780D90FFFC7FCEB03F8272D78AB2D>I<137C48B414072603C780EB +1F80380703C0000F7F000E153F001C1600130712385E0078157EEA700F5C011F14FE00F0 +495B12E0EA003FEC00015E5B137E150301FE5C5BA2150700015D5BA2150F00035D5BA215 +1F5EA2153F12014BC7FC6D5B00005BEB7C0390383E0F7EEB1FFEEB03F090C712FE5DA214 +015D121F397F8003F0A24A5A4848485A5D48131F00F049C8FC0070137E007813F8383801 +F0381E07C06CB4C9FCEA01FC294078AB2F>121 D E /Fb 7 116 +df82 D<92380FFFF04AB67E020F15F0023F15FC91B77E +01039039FE001FFF4901F8010113804901E0010713C04901804913E0017F90C7FC49484A +13F0A2485B485B5A5C5A7113E0485B7113C048701380943800FE0095C7FC485BA4B5FCAE +7EA280A27EA2806C18FCA26C6D150119F87E6C6D15036EED07F06C18E06C6D150F6D6DEC +1FC06D01E0EC7F806D6DECFF00010701FCEB03FE6D9039FFC03FFC010091B512F0023F5D +020F1580020102FCC7FCDA000F13C03E437BC148>99 D<92380FFFC04AB512FC020FECFF +80023F15E091B712F80103D9FE037F499039F0007FFF011F01C0011F7F49496D7F4990C7 +6C7F49486E7F48498048844A804884485B727E5A5C48717EA35A5C721380A2B5FCA391B9 +FCA41A0002C0CBFCA67EA380A27EA27E6E160FF11F806C183F6C7FF17F006C7F6C6D16FE +6C17016D6C4B5A6D6D4A5A6D01E04A5A6D6DEC3FE0010301FC49B45A6D9026FFC01F90C7 +FC6D6C90B55A021F15F8020715E0020092C8FC030713F041437CC14A>101 +DI<902607FF +80EB1FFFB691B512F0040714FC041F14FF4C8193267FE07F7F922781FE001F7FC6DA83F8 +6D7F6DD987F07F6DD98FC0814C7F039FC78015BE03BC8003FC825DA25DA25DA45DB3B2B7 +D8F007B71280A651417BC05A>110 D114 +D<913A3FFF8007800107B5EAF81F011FECFE7F017F91B5FC48B8FC48EBE0014890C7121F +D80FFC1407D81FF0801600485A007F167F49153FA212FF171FA27F7F7F6D92C7FC13FF14 +E014FF6C14F8EDFFC06C15FC16FF6C16C06C16F06C826C826C826C82013F1680010F16C0 +1303D9007F15E0020315F0EC001F1500041F13F81607007C150100FC81177F6C163FA217 +1F7EA26D16F0A27F173F6D16E06D157F6D16C001FEEDFF806D0203130002C0EB0FFE02FC +EB7FFC01DFB65A010F5DD8FE0315C026F8007F49C7FC48010F13E035437BC140>I +E /Fc 1 51 df50 D E +/Fd 2 50 df0 D49 +D E /Fe 5 81 df<151E153E157C15F8EC01F0EC03E01407EC0FC0EC1F8015005C147E5C +A2495A495AA2495AA2495AA2495AA249C7FCA2137EA213FE5B12015BA212035BA21207A2 +5B120FA35B121FA45B123FA548C8FCA912FEB3A8127FA96C7EA5121F7FA4120F7FA31207 +7FA21203A27F1201A27F12007F137EA27FA26D7EA26D7EA26D7EA26D7EA26D7E6D7EA214 +7E80801580EC0FC0EC07E01403EC01F0EC00F8157C153E151E1F94718232>16 +D<12F07E127C7E7E6C7E7F6C7E6C7E12017F6C7E137EA27F6D7EA26D7EA26D7EA26D7EA2 +6D7EA26D7EA280147E147F80A21580141FA215C0A2140F15E0A3140715F0A4140315F8A5 +EC01FCA9EC00FEB3A8EC01FCA9EC03F8A515F01407A415E0140FA315C0141FA21580A214 +3F1500A25C147E14FE5CA2495AA2495AA2495AA2495AA2495AA249C7FC137EA25B485A5B +1203485A485A5B48C8FC123E5A5A5A1F947D8232>I<160F161F163E167C16F8ED01F0ED +03E0ED07C0150FED1F801600153E157E5D4A5A5D14034A5A5D140F4A5AA24AC7FC143E14 +7E5CA2495AA2495AA2495AA2130F5CA2495AA2133F91C8FCA25B137E13FEA25B1201A25B +1203A35B1207A35B120FA35BA2121FA45B123FA690C9FC5AAA12FEB3AC127FAA7E7FA612 +1F7FA4120FA27FA312077FA312037FA312017FA212007FA2137E137F7FA280131FA26D7E +A2801307A26D7EA26D7EA26D7EA2147E143E143F6E7EA26E7E1407816E7E1401816E7E15 +7E153E811680ED0FC01507ED03E0ED01F0ED00F8167C163E161F160F28C66E823D>I<12 +F07E127C7E7E6C7E6C7E6C7E7F6C7E1200137C137E7F6D7E130F806D7E1303806D7EA26D +7E147C147E80A26E7EA26E7EA26E7EA2811403A26E7EA2811400A281157E157FA2811680 +A2151F16C0A3150F16E0A3150716F0A31503A216F8A4150116FCA6150016FEAA167FB3AC +16FEAA16FC1501A616F81503A416F0A21507A316E0150FA316C0151FA31680153FA21600 +5DA2157E15FE5DA214015DA24A5AA214075DA24A5AA24A5AA24AC7FCA2147E147C14FC49 +5AA2495A5C1307495A5C131F49C8FC137E137C5B1201485A5B485A485A48C9FC123E5A5A +5A28C67E823D>I80 D E /Ff 1 49 df48 +D E /Fg 11 115 df49 DI58 D80 D<003FBA12E0A59026FE000FEB8003D87FE09338003FF049171F90C71607A2 +007E1803007C1801A300781800A400F819F8481978A5C81700B3B3A20107B8FCA545437C +C24E>84 D101 DI104 D<90277F8007FEEC0FFCB590263FFFC090387FFF8092B5D8F001B5 +12E002816E4880913D87F01FFC0FE03FF8913D8FC00FFE1F801FFC0003D99F009026FF3E +007F6C019E6D013C130F02BC5D02F86D496D7EA24A5D4A5DA34A5DB3A7B60081B60003B5 +12FEA5572D7CAC5E>109 D +111 D<90387F807FB53881FFE0028313F0028F13F8ED8FFC91389F1FFE000313BE6C13BC +14F8A214F0ED0FFC9138E007F8ED01E092C7FCA35CB3A5B612E0A5272D7DAC2E>114 +D E /Fh 5 113 df<007FB912E0BA12F0A26C18E03C04789A4D>0 +D<121FEA3F80EA7FC0EAFFE0A5EA7FC0EA3F80EA1F000B0B789E1C>I<0060160600F816 +0F6C161F007E163F6C167E6C6C15FC6C6CEC01F86C6CEC03F06C6CEC07E06C6CEC0FC06C +6CEC1F80017EEC3F006D147E6D6C5B6D6C485A6D6C485A6D6C485A6D6C485A6D6C485ADA +7E3FC7FCEC3F7E6E5A6E5A6E5AA24A7E4A7EEC3F7EEC7E3F4A6C7E49486C7E49486C7E49 +486C7E49486C7E49486C7E49C7127E017E8049EC1F804848EC0FC04848EC07E04848EC03 +F04848EC01F84848EC00FC48C9127E007E163F48161F48160F00601606303072B04D>I< +127012FCB4FCEA7FC0EA1FF0EA07FCEA01FF38007FC0EB1FF0EB07FCEB01FF9038007FC0 +EC1FF0EC07FC913801FF809138007FE0ED1FF8ED07FE923800FF80EE3FE0EE0FF8EE03FE +933800FF80EF3FE0EF0FF8EF03FE943800FF80F03FE0F00FF0A2F03FE0F0FF80943803FE +00EF0FF8EF3FE0EFFF80DC03FEC7FCEE0FF8EE3FE0EEFF80DB03FEC8FCED1FF8ED7FE091 +3801FF80DA07FEC9FCEC1FF0EC7FC04948CAFCEB07FCEB1FF0EB7FC04848CBFCEA07FCEA +1FF0EA7FC048CCFC12FC1270CDFCB0007FB912E0BA12F0A26C18E03C4E78BE4D>21 +D<1B0C1B1E1B3EA21B7CA21BF8A2F201F0A2F203E0A2F207C0A2F20F80A2F21F00A21A3E +A262A262A24F5AA2621903A24F5AA24F5AA24FC7FCA2193EA261A261A24E5AA24E5AA24E +5AA24E5AA2010C4CC8FC133C017C163EEA01FE00035F487E001E5F00387FD8707F4B5A00 +E07FD8003F4B5A80011F4B5AA26E4A5A130F6E4AC9FC13076E143E13036E5C13016E5C7F +6F5B027F1301A26F485A143F6F485A141F6F485A140F6F48CAFC1407EDFC3E14035E15FE +02015B15FF6E5BA26F5AA26F5AA26F5AA26FCBFC150E4F647A8353>112 +D E /Fi 8 62 df43 +D48 D<130C133C137CEA03FC12FFEAFC7C1200B3B113FE387F +FFFEA2172C7AAB23>III<140EA2141E143EA2 +147E14FEA2EB01BE1303143E1306130E130C131813381330136013E013C0EA0180120313 +001206120E120C5A123812305A12E0B612FCA2C7EA3E00A9147F90381FFFFCA21E2D7EAC +23>I<000CEB0180380FC01F90B512005C5C14F014C0D80C7EC7FC90C8FCA8EB1FC0EB7F +F8380DE07C380F801F01001380000E130F000CEB07C0C713E0A2140315F0A4127812FCA4 +48EB07E012E0006014C00070130F6C14806CEB1F006C133E380780F83801FFE038007F80 +1C2D7DAB23>I61 D E +/Fj 4 123 df<151FEC03FFA2EC003FA2153EA2157EA2157CA215FCA215F8A21401EB07 +E190381FF9F0EB7C1DEBF80FEA01F03903E007E0EA07C0120FEA1F8015C0EA3F00140F5A +007E1480A2141F12FE481400A2EC3F021506143E5AEC7E0E007CEBFE0C14FC0101131C39 +3E07BE18391F0E1E38390FFC0FF03903F003C0202F7DAD24>100 +D<3907C007E0391FE03FF83918F8783E393879E01E39307B801F38707F00126013FEEAE0 +FC12C05B00815C0001143E5BA20003147E157C5B15FC0007ECF8081618EBC00115F0000F +1538913803E0300180147016E0001F010113C015E390C7EAFF00000E143E251F7E9D2B> +110 D<013F137C9038FFC1FF3A01C1E383803A0380F703C0390700F60F000E13FE4813FC +12180038EC0700003049C7FCA2EA200100005BA313035CA301075B5D14C000385CD87C0F +130600FC140E011F130C011B131C39F03BE038D8707113F0393FE0FFC0260F803FC7FC22 +1F7E9D28>120 D<011E1330EB3F809038FFC07048EBE0E0ECF1C03803C0FF9038803F80 +903800070048130EC75A5C5C5C495A495A49C7FC131E13385B491340484813C0485A3807 +0001000EEB0380380FE007391FF81F0038387FFF486C5A38601FFC38E00FF038C003C01C +1F7D9D21>122 D E /Fk 10 123 df11 D64 D<91B912F8A3020001C0C7123F6F48EC07F003FF1503190193C9FCA21A705C5D +A3020317605DA314075D18C01701020F4B13005DA21703021F92C8FC4B5BA25F023F141E +4B13FE92B5FCA24A5CED8000173CA202FF141892C7FCA217384915305CA2177001031560 +4A91C9FCA313075CA3130F5CA3131F5CA2133FA313FFB612F8A345447CC33F>70 +D<91B612F8A3020001E0C8FC6F5A4B5AA293C9FCA35C5DA314035DA314075DA3140F5DA3 +141F5DA3143F5DA3147F5DA314FF92CAFCA35B4A16C0A21801010317804A15031900A201 +075E4A1506180E181E010F161C4A153C18381878011F16F84A4A5A1703013F150F4D5A4A +14FF01FF02075BB9FCA2603A447CC342>76 D +81 D<48BA12C05AA291C7D980001380D807F092C7121F4949150F0180170748C75B1903 +120E48020316005E12181238003014074C5C00701806126000E0140F485DA3C8001F92C7 +FC5EA3153F5EA3157F5EA315FF93CAFCA35C5DA314035DA314075DA3140F5DA3141F5DA3 +143F5DA2147FA214FF01037F001FB612FCA25E42447EC339>84 D<01F8EB03FCD803FEEB +1FFFD8071F90387C0FC03B0E0F80E007E03A0C07C3C003001CD9C7007F001801CE130100 +3801DC80003013D8EB0FF800705B00605BA200E0491303D8C01F5D5C12001607013F5D91 +C7FCA2160F495D137E161F5F13FE49143F94C7FC187000014B136049147E16FE4C13E000 +0317C049150104F81380170300071700495D170EEE781C000FED7C3849EC1FF0D80380EC +07C0342D7DAB3A>110 D112 D<02FCEB07E0903A03FF801FFC903A0F07C0781E90 +3A1C03E0E01F903A3801F1C07FD9700013804901FB13FF4848EBFF00495B000316FE90C7 +1438484A130012061401000E5C120CC7FC14035DA314075DA3140F5DA3021F143817305D +1770023F1460121E003F16E0267F807FEB01C0026F148000FF01EF1303D901CFEB070000 +FE903887C00E267C03835B3A3C0F01E0783A1FFC00FFE0D803F0EB3F80302D7EAB37> +120 D<027CEB018049B413034901801300010F6D5A49EBE00E6F5A90393F03F838903978 +007EF80170EB1FF00160EB01E001E05C49495A90C748C7FC150E5D5D5D5D4A5A4A5A4AC8 +FC140E5C5C5C5CEB03C049C9FC130E49141C4914185B49143848481430491470D8039014 +F048B4495A3A0FEFC007C0391E03F01FD81C01B55A486C91C7FC485C00606D5A00E0EB3F +F048EB0FC0292D7CAB2D>122 D E /Fl 57 123 df<1618163CA2167EA216FFA24B7FA2 +4B6C7EA29238063FE0A24B6C7EA24B6C7EA292383807FC153092387003FE15609238E001 +FF15C002016D7F5D02036E7E92C7FC4A6E7E1406020E6E7E140C021C6E7E141802386E7E +143002706E7E146002E06E7E5C01016F7F5C0103707E91C9FC183F010683181F4983180F +49831807498318034983A249707EA24848701380A248CBEA7FC0A20006F03FE0A248F01F +F0A2001FBA12F8A24819FCA24819FEA2BCFC48477CC651>1 D<9239FFC001FC020F9038 +F80FFF913B3F803E3F03C0913BFC00077E07E0D903F890390FFC0FF0494890383FF81F49 +48EB7FF0495A494814E049C7FCF00FE04991393FC0038049021F90C7FCAFB912F0A3C648 +C7D81FC0C7FCB3B2486CEC3FF0007FD9FC0FB512E0A33C467EC539>11 +D<4AB4FC020F13E091387F80F8903901FC001C49487FD907E0130F4948137F011FECFF80 +495A49C7FCA25B49EC7F00163E93C7FCACEE3F80B8FCA3C648C7FC167F163FB3B0486CEC +7FC0007FD9FC1FB5FCA330467EC536>I14 +D<140C141C1438147014E0EB01C01303EB0780EB0F00A2131E5BA25B13F85B12015B1203 +A2485AA3485AA348C7FCA35AA2123EA2127EA4127CA312FCB3A2127CA3127EA4123EA212 +3FA27EA36C7EA36C7EA36C7EA212017F12007F13787FA27F7FA2EB0780EB03C01301EB00 +E014701438141C140C166476CA26>40 D<12C07E12707E7E7E120F6C7E6C7EA26C7E6C7E +A21378137C133C133E131E131FA2EB0F80A3EB07C0A3EB03E0A314F0A21301A214F8A413 +00A314FCB3A214F8A31301A414F0A21303A214E0A3EB07C0A3EB0F80A3EB1F00A2131E13 +3E133C137C13785BA2485A485AA2485A48C7FC120E5A5A5A5A5A16647BCA26>I<16C04B +7EB3AB007FBAFCBB1280A26C1900C8D801E0C9FCB3AB6F5A41407BB84C>43 +D<121EEA7F8012FF13C0A213E0A3127FEA1E601200A413E013C0A312011380120313005A +1206120E5A5A5A12600B1D78891B>II<121EEA7F80A2EAFFC0A4 +EA7F80A2EA1E000A0A78891B>I<14FF010713E090381F81F890383E007C01FC133F4848 +EB1F8049130F4848EB07C04848EB03E0A2000F15F0491301001F15F8A2003F15FCA390C8 +FC4815FEA54815FFB3A46C15FEA56D1301003F15FCA3001F15F8A26C6CEB03F0A36C6CEB +07E0000315C06D130F6C6CEB1F806C6CEB3F00013E137C90381F81F8903807FFE0010090 +C7FC28447CC131>48 D<143014F013011303131F13FFB5FC13E713071200B3B3B0497E49 +7E007FB6FCA3204278C131>II52 D<000615C0D807C0130701FCEB7F8090B612005D5D5D15E0158026063FFCC7FC90 +C9FCAE14FF010713C090381F01F090383800FC01F0137ED807C07F49EB1F8016C090C712 +0F000615E0C8EA07F0A316F81503A216FCA5123E127F487EA416F890C712075A006015F0 +A20070140F003015E00038EC1FC07E001EEC3F806CEC7F006C6C13FE6C6C485A3901F807 +F039007FFFE0011F90C7FCEB07F826447BC131>II< +121EEA7F80A2EAFFC0A4EA7F80A2EA1E00C7FCB3A5121EEA7F80A2EAFFC0A4EA7F80A2EA +1E000A2B78AA1B>58 D<007FBAFCBB1280A26C1900CEFCB0007FBAFCBB1280A26C190041 +187BA44C>61 D<16C04B7EA34B7EA34B7EA34B7EA3ED19FEA3ED30FFA203707FED607FA2 +03E07FEDC03FA2020180ED801FA2DA03007F160FA20206801607A24A6D7EA34A6D7EA34A +6D7EA20270810260147FA202E08191B7FCA249820280C7121FA249C87F170FA201068217 +07A2496F7EA3496F7EA3496F7EA201788313F8486C83D80FFF03037FB500E0027FEBFFC0 +A342477DC649>65 DI68 D70 D72 +DI76 D78 DI<49B41303010FEB +E007013F13F89039FE00FE0FD801F8131FD807E0EB079F49EB03DF48486DB4FC48C8FC48 +81003E81127E82127C00FC81A282A37E82A27EA26C6C91C7FC7F7FEA3FF813FE381FFFE0 +6C13FE6CEBFFE06C14FC6C14FF6C15C0013F14F0010F80010180D9001F7F14019138001F +FF03031380816F13C0167F163F161F17E000C0150FA31607A37EA36C16C0160F7E17806C +151F6C16006C5D6D147ED8FBC05CD8F9F0495AD8F07C495A90393FC00FE0D8E00FB51280 +010149C7FC39C0003FF02B487BC536>83 D<003FB912F8A3903BF0001FF8001F01806D48 +1303003EC7150048187C0078183CA20070181CA30060180CA5481806A5C81600B3B3A54B +7EED7FFE49B77EA33F447DC346>I87 D91 D93 D +97 DII<167FED3FFFA315018182B3EC7F80903803FFF090380F +C07C90383F000E017E1307496D5AD803F87F48487F5B000F81485AA2485AA2127FA290C8 +FC5AAB7E7FA2123FA26C7EA2000F5D7F6C6C5B00035C6C6C9038077F806C6C010E13C001 +3F011C13FE90380FC0F8903803FFE09026007F0013002F467DC436>IIIIII107 DII<3901FC01FE00FF903807FFC091381E07F091383801F8000701 +707F0003EBE0002601FDC07F5C01FF147F91C7FCA25BA35BB3A8486CECFF80B5D8F83F13 +FEA32F2C7DAB36>II<3901FC03FC00FF90 +380FFF8091383C07E091387001F83A07FDE000FE00010180137F01FFEC3F8091C7EA1FC0 +4915E049140F17F0160717F8160317FCA3EE01FEABEE03FCA3EE07F8A217F0160F6D15E0 +EE1FC06D143F17806EEB7E00D9FDC05B9039FCF003F891383C0FE091381FFF80DA03FCC7 +FC91C9FCAE487EB512F8A32F3F7DAB36>I<91387F8003903903FFE00790380FE0789039 +3F801C0F90387E000E496D5AD803F8EB039F0007EC01BF4914FF48487F121F5B003F81A2 +485AA348C8FCAB6C7EA3123F7F121F6D5C120F6D5B12076C6C5B6C6C497E6C6C130E013F +131C90380FC0F8903803FFE09038007F0091C7FCAEEEFF80033F13FEA32F3F7DAB33>I< +3903F803F000FFEB1FFCEC3C3EEC707F0007EBE0FF3803F9C000015B13FBEC007E153C01 +FF13005BA45BB3A748B4FCB512FEA3202C7DAB26>I<90383FE0183901FFFC383907E01F +78390F0003F8001E1301481300007C1478127800F81438A21518A27EA27E6C6C13006C7E +13FC383FFFE06C13FC6C13FF6C14C06C14E0C614F0011F13F81300EC0FFC140300C0EB01 +FE1400157E7E153EA27EA36C143C6C147C15786C14F86CEB01F039F38003E039F1F00F80 +39E07FFE0038C00FF01F2E7DAC26>I<1306A5130EA4131EA3133E137EA213FE12011207 +001FB512F0B6FCA2C648C7FCB3A4150CAA017E131C017F1318A26D133890381F8030ECC0 +70903807E0E0903801FFC09038007F001E3E7EBC26>IIIIII<003FB612E0A29038C0003F90C713C0003CEC7F800038EC +FF00A20030495A0070495AA24A5A0060495AA24A5A4A5AA2C7485A4AC7FC5B5C495A1307 +5C495A131F4A1360495A495AA249C712C0485AA2485A485A1501485A48481303A24848EB +07804848131F00FF14FF90B6FCA2232B7DAA2B>I E end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: a4 +%%BeginPaperSize: a4 +a4 +%%EndPaperSize + +%%EndSetup +%%Page: 1 1 +1 0 bop 404 573 a Fl(The)27 b(Tsc)m(heb)m(yc)m(hev)32 +b(p)s(olynomials)23 b(\(of)k(the)g(1st)g(kind\))f Fk(T)2467 +588 y Fj(n)2514 573 y Fl(\()p Fk(x)p Fl(\))h(are)g(de\014ned)h(through) +257 693 y(the)33 b(recurrence)i(relation)1672 904 y Fk(T)1729 +919 y Fi(0)1769 904 y Fl(\()p Fk(x)p Fl(\))28 b(=)f(1)1669 +1229 y Fk(T)1726 1244 y Fi(1)1766 1229 y Fl(\()p Fk(x)p +Fl(\))h(=)f Fk(x)1218 1554 y(T)1275 1569 y Fj(n)p Fi(+2)1413 +1554 y Fl(\()p Fk(x)p Fl(\))h(=)f(2)p Fk(x)c Fh(\001)e +Fk(T)1908 1569 y Fj(n)p Fi(+1)2046 1554 y Fl(\()p Fk(x)p +Fl(\))h Fh(\000)h Fk(T)2356 1569 y Fj(n)2403 1554 y Fl(\()p +Fk(x)p Fl(\))257 1765 y(for)32 b Fk(n)c Fh(\025)g Fl(0.)257 +1982 y Fg(Theorem:)404 2200 y Fk(T)461 2215 y Fj(n)508 +2200 y Fl(\()p Fk(x)p Fl(\))33 b(satis\014es)g(the)g(di\013eren)m(tial) +d(equation)j(\()p Fk(x)2178 2163 y Fi(2)2239 2200 y Fh(\000)23 +b Fl(1\))f Fh(\001)f Fk(T)2568 2140 y Ff(00)2554 2224 +y Fj(n)2613 2200 y Fl(\()p Fk(x)p Fl(\))h(+)g Fk(x)g +Fh(\001)g Fk(T)3062 2140 y Ff(0)3048 2224 y Fj(n)3095 +2200 y Fl(\()p Fk(x)p Fl(\))g Fh(\000)h Fk(n)3406 2163 +y Fi(2)3468 2200 y Fh(\001)257 2320 y Fk(T)314 2335 y +Fj(n)362 2320 y Fl(\()p Fk(x)p Fl(\))k(=)h(0)k(for)g(all)f +Fk(n)d Fh(\025)g Fl(0.)257 2537 y Fg(Pro)s(of:)404 2755 +y Fl(Let)45 b Fk(F)62 b Fl(:=)868 2688 y Fe(P)956 2715 +y Fd(1)956 2779 y Fj(n)p Fi(=0)1110 2755 y Fk(T)1167 +2770 y Fj(n)1214 2755 y Fl(\()p Fk(x)p Fl(\))p Fk(z)1394 +2718 y Fj(n)1487 2755 y Fl(b)s(e)45 b(the)g(generating)g(function)f(of) +h(the)g(sequence)j(of)257 2875 y(p)s(olynomials.)41 b(The)33 +b(recurrence)i(is)d(equiv)-5 b(alen)m(t)32 b(to)g(the)h(equation)1222 +3085 y(\(1)22 b Fh(\000)g Fl(2)p Fk(x)h Fh(\001)e Fk(z)27 +b Fl(+)22 b Fk(z)1825 3044 y Fi(2)1865 3085 y Fl(\))g +Fh(\001)g Fk(F)42 b Fl(=)27 b(1)22 b Fh(\000)h Fk(x)f +Fh(\001)g Fk(z)257 3303 y Fg(Pro)s(of)38 b(1:)404 3520 +y Fk(F)j Fl(is)27 b(a)h(rational)d(function)i(in)g Fk(z)t +Fl(,)i Fk(F)42 b Fl(=)1925 3481 y Fi(1)p Fd(\000)p Fj(xz)p +1845 3497 326 4 v 1845 3555 a Fi(1)p Fd(\000)p Fi(2)p +Fj(xz)s Fi(+)p Fj(z)2137 3536 y Fc(2)2181 3520 y Fl(.)g(F)-8 +b(rom)26 b(the)i(theory)g(of)f(recursions)257 3641 y(with)e(constan)m +(t)h(co)s(e\016cien)m(ts,)i(w)m(e)e(kno)m(w)g(that)f(w)m(e)h(ha)m(v)m +(e)h(to)e(p)s(erform)f(a)g(partial)f(fraction)257 3761 +y(decomp)s(osition.)59 b(So)39 b(let)e Fk(p)p Fl(\()p +Fk(z)t Fl(\))h(=)g Fk(z)1618 3725 y Fi(2)1684 3761 y +Fh(\000)27 b Fl(2)p Fk(x)f Fh(\001)g Fk(z)31 b Fl(+)25 +b(1)39 b(b)s(e)f(the)h(denominator)e(and)h Fk(\013)g +Fl(=)257 3881 y Fk(x)23 b Fl(+)433 3800 y Fh(p)p 516 +3800 266 4 v 81 x Fk(x)571 3853 y Fi(2)633 3881 y Fh(\000)g +Fl(1)32 b(and)h Fk(\013)1067 3845 y Fd(\000)p Fi(1)1193 +3881 y Fl(its)f(zero)s(es.)45 b(The)33 b(partial)d(fraction)i(decomp)s +(osition)f(reads)916 4131 y Fk(F)41 b Fl(=)1263 4063 +y(1)22 b Fh(\000)g Fk(xz)p 1134 4107 534 4 v 1134 4199 +a Fl(1)g Fh(\000)g Fl(2)p Fk(xz)27 b Fl(+)22 b Fk(z)1627 +4170 y Fi(2)1705 4131 y Fl(=)1819 4063 y(1)p 1819 4107 +49 4 v 1819 4199 a(2)1894 4009 y Fe(\022)2082 4063 y +Fl(1)p 1965 4107 283 4 v 1965 4199 a(1)g Fh(\000)h Fk(\013)q(z)2280 +4131 y Fl(+)2553 4063 y(1)p 2388 4107 378 4 v 2388 4199 +a(1)f Fh(\000)h Fk(\013)2622 4170 y Fd(\000)p Fi(1)2716 +4199 y Fk(z)2776 4009 y Fe(\023)257 4388 y Fl(hence)38 +b Fk(T)589 4403 y Fj(n)636 4388 y Fl(\()p Fk(x)p Fl(\))d(=)922 +4348 y Fi(1)p 922 4364 36 4 v 922 4422 a(2)967 4388 y +Fl(\()p Fk(\013)1068 4351 y Fj(n)1139 4388 y Fl(+)25 +b Fk(\013)1303 4351 y Fd(\000)p Fj(n)1404 4388 y Fl(\).)55 +b(Note)36 b(that)g(the)h(\014eld)f Fk(Q)p Fl(\()p Fk(x)p +Fl(\)\()p Fk(\013)q Fl(\),)i(b)s(eing)d(a)h(\014nite)g(di-)257 +4508 y(mensional)28 b(extension)j(\014eld)e(of)g Fk(Q)p +Fl(\()p Fk(x)p Fl(\))h(in)f(c)m(haracteristic)g(0,)h(has)g(a)g(unique)g +(deriv)-5 b(ation)257 4628 y(extending)745 4589 y Fj(d)p +725 4605 77 4 v 725 4663 a(dx)854 4628 y Fl(on)44 b Fk(Q)p +Fl(\()p Fk(x)p Fl(\).)76 b(W)-8 b(e)43 b(can)h(therefore)g(try)f(to)g +(construct)i(an)e(annihilating)257 4749 y(di\013eren)m(tial)28 +b(op)s(erator)h(for)g Fk(T)1335 4764 y Fj(n)1382 4749 +y Fl(\()p Fk(x)p Fl(\))h(b)m(y)g(com)m(bination)e(of)h(annihilating)d +(di\013eren)m(tial)i(op-)257 4869 y(erators)i(for)e Fk(\013)788 +4833 y Fj(n)864 4869 y Fl(and)h Fk(\013)1113 4833 y Fd(\000)p +Fj(n)1215 4869 y Fl(.)42 b(In)29 b(fact,)h Fk(L)1685 +4884 y Fi(1)1753 4869 y Fl(:=)d(\()p Fk(\013)16 b Fh(\000)f +Fk(x)p Fl(\))2215 4830 y Fj(d)p 2194 4846 V 2194 4904 +a(dx)2296 4869 y Fh(\000)g Fk(n)30 b Fl(satis\014es)g +Fk(L)2898 4884 y Fi(1)2937 4869 y Fl([)p Fk(\013)3027 +4833 y Fj(n)3074 4869 y Fl(])e(=)f(0,)j(and)257 4990 +y Fk(L)323 5005 y Fi(2)391 4990 y Fl(:=)d(\()p Fk(\013)c +Fh(\000)e Fk(x)p Fl(\))866 4950 y Fj(d)p 845 4966 V 845 +5024 a(dx)953 4990 y Fl(+)g Fk(n)33 b Fl(satis\014es)g +Fk(L)1566 5005 y Fi(2)1606 4990 y Fl([)p Fk(\013)1696 +4953 y Fd(\000)p Fj(n)1797 4990 y Fl(])28 b(=)f(0.)44 +b(A)32 b(common)f(m)m(ultiple)e(of)j Fk(L)3128 5005 y +Fi(1)3200 4990 y Fl(and)g Fk(L)3455 5005 y Fi(2)257 5110 +y Fl(is)g(easily)g(found)h(b)m(y)g(solving)f(an)g(appropriate)g(system) +i(of)e(linear)f(equations:)404 5254 y Fk(L)d Fl(=)f(\()p +Fk(x)694 5218 y Fi(2)737 5254 y Fh(\000)s Fl(1\))921 +5157 y Fe(\020)1001 5215 y Fj(d)p 981 5230 V 981 5288 +a(dx)1067 5157 y Fe(\021)1117 5180 y Fi(2)1160 5254 y +Fl(+)s Fk(x)1324 5215 y Fj(d)p 1304 5230 V 1304 5288 +a(dx)1394 5254 y Fh(\000)s Fk(n)1532 5218 y Fi(2)1600 +5254 y Fl(=)1703 5157 y Fe(\020)1753 5254 y Fl(\()p Fk(\013)c +Fh(\000)f Fk(x)p Fl(\))2099 5215 y Fj(d)p 2078 5230 V +2078 5288 a(dx)2187 5254 y Fl(+)g Fk(n)2343 5157 y Fe(\021)2396 +5254 y Fh(\001)s Fk(L)2493 5269 y Fi(1)2561 5254 y Fl(=)2664 +5157 y Fe(\020)2714 5254 y Fl(\()p Fk(\013)g Fh(\000)h +Fk(x)p Fl(\))3059 5215 y Fj(d)p 3039 5230 V 3039 5288 +a(dx)3148 5254 y Fh(\000)f Fk(n)3305 5157 y Fe(\021)3358 +5254 y Fh(\001)s Fk(L)3455 5269 y Fi(2)404 5388 y Fl(It)32 +b(follo)m(ws)g(that)g(b)s(oth)g Fk(L)p Fl([)p Fk(\013)1427 +5352 y Fj(n)1474 5388 y Fl(])c(=)g(0)k(and)h Fk(L)p Fl([)p +Fk(\013)2060 5352 y Fd(\000)p Fj(n)2162 5388 y Fl(])27 +b(=)h(0,)k(hence)i Fk(L)p Fl([)p Fk(T)2849 5403 y Fj(n)2897 +5388 y Fl(\()p Fk(x)p Fl(\)])28 b(=)g(0.)1852 5637 y(1)p +eop +%%Page: 2 2 +2 1 bop 257 573 a Fg(Pro)s(of)38 b(2:)404 801 y Fl(Starting)g(from)g +(the)i(ab)s(o)m(v)m(e)h(equation,)g(w)m(e)f(compute)g(a)f(linear)f +(relation)g(for)h(the)257 922 y(partial)31 b(deriv)-5 +b(ativ)m(es)32 b(of)g Fk(F)14 b Fl(.)44 b(W)-8 b(rite)31 +b Fk(@)1637 937 y Fj(x)1710 922 y Fl(=)1843 882 y Fj(d)p +1823 898 77 4 v 1823 956 a(dx)1942 922 y Fl(and)h(\001)2212 +937 y Fj(z)2280 922 y Fl(=)c Fk(z)2461 882 y Fj(d)p 2443 +898 72 4 v 2443 956 a(dz)2525 922 y Fl(.)44 b(One)33 +b(computes)1282 1080 y Fe(\020)1332 1176 y Fl(1)21 b +Fh(\000)i Fl(2)p Fk(xz)k Fl(+)22 b Fk(z)1825 1135 y Fi(2)1865 +1080 y Fe(\021)1937 1176 y Fh(\001)g Fk(F)41 b Fl(=)28 +b(1)22 b Fh(\000)g Fk(xz)1222 1449 y Fe(\020)1272 1545 +y Fl(1)g Fh(\000)g Fl(2)p Fk(xz)27 b Fl(+)22 b Fk(z)1765 +1504 y Fi(2)1806 1449 y Fe(\021)1855 1472 y Fi(2)1917 +1545 y Fh(\001)f Fk(@)2017 1560 y Fj(x)2062 1545 y Fk(F)41 +b Fl(=)28 b Fk(z)f Fh(\000)22 b Fk(z)2490 1504 y Fi(3)1153 +1818 y Fe(\020)1203 1915 y Fl(1)g Fh(\000)g Fl(2)p Fk(xz)27 +b Fl(+)22 b Fk(z)1696 1874 y Fi(2)1737 1818 y Fe(\021)1786 +1841 y Fi(3)1848 1915 y Fh(\001)g Fk(@)1954 1874 y Fi(2)1949 +1939 y Fj(x)1994 1915 y Fk(F)41 b Fl(=)28 b(4)p Fk(z)2300 +1874 y Fi(2)2362 1915 y Fh(\000)23 b Fl(4)p Fk(z)2560 +1874 y Fi(4)1025 2188 y Fe(\020)1074 2284 y Fl(1)f Fh(\000)h +Fl(2)p Fk(xz)k Fl(+)22 b Fk(z)1568 2243 y Fi(2)1608 2188 +y Fe(\021)1658 2211 y Fi(2)1719 2284 y Fh(\001)g Fl(\001)1850 +2299 y Fj(z)1890 2284 y Fk(F)42 b Fl(=)27 b Fk(xz)g Fh(\000)c +Fl(2)p Fk(z)2423 2243 y Fi(2)2485 2284 y Fl(+)f Fk(xz)2687 +2243 y Fi(3)719 2557 y Fe(\020)769 2654 y Fl(1)f Fh(\000)i +Fl(2)p Fk(xz)k Fl(+)22 b Fk(z)1262 2613 y Fi(2)1302 2557 +y Fe(\021)1352 2580 y Fi(3)1414 2654 y Fh(\001)f Fk(@)1514 +2669 y Fj(x)1559 2654 y Fl(\001)1640 2669 y Fj(z)1680 +2654 y Fk(F)41 b Fl(=)28 b Fk(z)f Fl(+)22 b(2)p Fk(xz)2211 +2613 y Fi(2)2273 2654 y Fh(\000)h Fl(6)p Fk(z)2471 2613 +y Fi(3)2533 2654 y Fl(+)f(2)p Fk(xz)2784 2613 y Fi(4)2846 +2654 y Fl(+)g Fk(z)2993 2613 y Fi(5)554 2927 y Fe(\020)603 +3023 y Fl(1)g Fh(\000)h Fl(2)p Fk(xz)k Fl(+)22 b Fk(z)1097 +2982 y Fi(2)1137 2927 y Fe(\021)1187 2950 y Fi(3)1248 +3023 y Fh(\001)g Fl(\001)1379 2982 y Fi(2)1379 3048 y +Fj(z)1419 3023 y Fk(F)41 b Fl(=)28 b Fk(xz)f Fl(+)22 +b(\(2)p Fk(x)1994 2982 y Fi(2)2056 3023 y Fh(\000)h Fl(4\))p +Fk(z)2292 2982 y Fi(2)2354 3023 y Fh(\000)f Fl(\(2)p +Fk(x)2595 2982 y Fi(2)2657 3023 y Fh(\000)h Fl(4\))p +Fk(z)2893 2982 y Fi(4)2955 3023 y Fh(\000)f Fk(xz)3158 +2982 y Fi(5)404 3256 y Fl(Solv)m(e)32 b(a)h(6)22 b Fh(\002)g +Fl(6)33 b(system)g(of)f(linear)f(equations)i(o)m(v)m(er)h +Fk(Q)p Fl(\()p Fk(x)p Fl(\))f(to)f(get)1124 3476 y Fk(x)22 +b Fh(\001)g Fk(@)1302 3491 y Fj(x)1346 3476 y Fk(F)36 +b Fl(+)22 b(\()p Fk(x)1636 3434 y Fi(2)1698 3476 y Fh(\000)h +Fl(1\))f Fh(\001)f Fk(@)2012 3434 y Fi(2)2007 3500 y +Fj(x)2053 3476 y Fk(F)36 b Fh(\000)22 b Fl(\001)2332 +3434 y Fi(2)2332 3500 y Fj(z)2372 3476 y Fk(F)42 b Fl(=)27 +b(0)404 3696 y(This)34 b(is)g(equiv)-5 b(alen)m(t)34 +b(to)g(the)g(claimed)f(equation)h(\()p Fk(x)2336 3659 +y Fi(2)2399 3696 y Fh(\000)23 b Fl(1\))g Fh(\001)g Fk(T)2731 +3636 y Ff(00)2717 3720 y Fj(n)2776 3696 y Fl(\()p Fk(x)p +Fl(\))g(+)g Fk(x)h Fh(\001)f Fk(T)3230 3636 y Ff(0)3216 +3720 y Fj(n)3263 3696 y Fl(\()p Fk(x)p Fl(\))h Fh(\000)257 +3816 y Fk(n)315 3780 y Fi(2)377 3816 y Fh(\001)e Fk(T)484 +3831 y Fj(n)531 3816 y Fl(\()p Fk(x)p Fl(\))28 b(=)g(0.)257 +4149 y Fb(References)62 4368 y Fl(1)146 b(Bruno)46 b(Haible:)69 +b(D-\014nite)45 b(p)s(o)m(w)m(er)i(series)g(in)e(sev)m(eral)i(v)-5 +b(ariables.)82 b Fa(Diploma)46 b(thesis,)501 4488 y(University)35 +b(of)g(Karlsruhe,)f(June)h(1989.)44 b Fl(Sections)33 +b(2.12)f(and)h(2.15.)1852 5637 y(2)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/polynomial/tchebychev.tex b/doc/polynomial/tchebychev.tex new file mode 100644 index 0000000..8f9bbaf --- /dev/null +++ b/doc/polynomial/tchebychev.tex @@ -0,0 +1,208 @@ +%% This LaTeX-file was created by Sun Feb 16 14:05:43 1997 +%% LyX 0.10 (C) 1995 1996 by Matthias Ettrich and the LyX Team + +%% Don't edit this file unless you are sure what you are doing. +\documentclass[12pt,a4paper,oneside,onecolumn]{article} +\usepackage[]{fontenc} +\usepackage[latin1]{inputenc} +\usepackage[dvips]{epsfig} + +%% +%% BEGIN The lyx specific LaTeX commands. +%% + +\makeatletter +\def\LyX{L\kern-.1667em\lower.25em\hbox{Y}\kern-.125emX\spacefactor1000}% +\newcommand{\lyxtitle}[1] {\thispagestyle{empty} +\global\@topnum\z@ +\section*{\LARGE \centering \sffamily \bfseries \protect#1 } +} +\newcommand{\lyxline}[1]{ +{#1 \vspace{1ex} \hrule width \columnwidth \vspace{1ex}} +} +\newenvironment{lyxsectionbibliography} +{ +\section*{\refname} +\@mkboth{\uppercase{\refname}}{\uppercase{\refname}} +\begin{list}{}{ +\itemindent-\leftmargin +\labelsep 0pt +\renewcommand{\makelabel}{} +} +} +{\end{list}} +\newenvironment{lyxchapterbibliography} +{ +\chapter*{\bibname} +\@mkboth{\uppercase{\bibname}}{\uppercase{\bibname}} +\begin{list}{}{ +\itemindent-\leftmargin +\labelsep 0pt +\renewcommand{\makelabel}{} +} +} +{\end{list}} +\def\lxq{"} +\newenvironment{lyxcode} +{\list{}{ +\rightmargin\leftmargin +\raggedright +\itemsep 0pt +\parsep 0pt +\ttfamily +}% +\item[] +} +{\endlist} +\newcommand{\lyxlabel}[1]{#1 \hfill} +\newenvironment{lyxlist}[1] +{\begin{list}{} +{\settowidth{\labelwidth}{#1} +\setlength{\leftmargin}{\labelwidth} +\addtolength{\leftmargin}{\labelsep} +\renewcommand{\makelabel}{\lyxlabel}}} +{\end{list}} +\newcommand{\lyxletterstyle}{ +\setlength\parskip{0.7em} +\setlength\parindent{0pt} +} +\newcommand{\lyxaddress}[1]{ +\par {\raggedright #1 +\vspace{1.4em} +\noindent\par} +} +\newcommand{\lyxrightaddress}[1]{ +\par {\raggedleft \begin{tabular}{l}\ignorespaces +#1 +\end{tabular} +\vspace{1.4em} +\par} +} +\newcommand{\lyxformula}[1]{ +\begin{eqnarray*} +#1 +\end{eqnarray*} +} +\newcommand{\lyxnumberedformula}[1]{ +\begin{eqnarray} +#1 +\end{eqnarray} +} +\makeatother + +%% +%% END The lyx specific LaTeX commands. +%% + +\pagestyle{plain} +\setcounter{secnumdepth}{3} +\setcounter{tocdepth}{3} +\begin{document} + +The Tschebychev polynomials (of the 1st kind) \( T_{n}(x) \) are defined through +the recurrence relation + + +\[ +T_{0}(x)=1\] + + + +\[ +T_{1}(x)=x\] + + + +\[ +T_{n+2}(x)=2x\cdot T_{n+1}(x)-T_{n}(x)\] + for \( n\geq 0 \). + +\begin{description} + +\item [Theorem:]~ + +\end{description} + + \( T_{n}(x) \) satisfies the differential equation \( (x^{2}-1)\cdot T_{n}^{''}(x)+x\cdot T_{n}^{'}(x)-n^{2}\cdot T_{n}(x)=0 \) for all \( n\geq 0 \). + +\begin{description} + +\item [Proof:]~ + +\end{description} + +Let \( F:=\sum ^{\infty }_{n=0}T_{n}(x)z^{n} \) be the generating function of the sequence of polynomials. The +recurrence is equivalent to the equation +\[ +(1-2x\cdot z+z^{2})\cdot F=1-x\cdot z\] + + +\begin{description} + +\item [Proof~1:]~ + +\end{description} + + \( F \) is a rational function in \( z \), \( F=\frac{1-xz}{1-2xz+z^{2}} \). From the theory of recursions with +constant coefficients, we know that we have to perform a partial fraction +decomposition. So let \( p(z)=z^{2}-2x\cdot z+1 \) be the denominator and \( \alpha =x+\sqrt{x^{2}-1} \) and \( \alpha ^{-1} \) its zeroes. +The partial fraction decomposition reads +\[ +F=\frac{1-xz}{1-2xz+z^{2}}=\frac{1}{2}\left( \frac{1}{1-\alpha z}+\frac{1}{1-\alpha ^{-1}z}\right) \] + hence \( T_{n}(x)=\frac{1}{2}(\alpha ^{n}+\alpha ^{-n}) \). Note that the +field \( Q(x)(\alpha ) \), being a finite dimensional extension field of \( Q(x) \) in characteristic +0, has a unique derivation extending \( \frac{d}{dx} \) on \( Q(x) \). We can therefore try +to construct an annihilating differential operator for \( T_{n}(x) \) by combination +of annihilating differential operators for \( \alpha ^{n} \) and \( \alpha ^{-n} \). In fact, \( L_{1}:=(\alpha -x)\frac{d}{dx}-n \) satisfies + \( L_{1}[\alpha ^{n}]=0 \), and \( L_{2}:=(\alpha -x)\frac{d}{dx}+n \) satisfies \( L_{2}[\alpha ^{-n}]=0 \). A common multiple of \( L_{1} \) and \( L_{2} \) is easily found +by solving an appropriate system of linear equations: + + \( L=(x^{2}-1)\left( \frac{d}{dx}\right) ^{2}+x\frac{d}{dx}-n^{2}=\left( (\alpha -x)\frac{d}{dx}+n\right) \cdot L_{1}=\left( (\alpha -x)\frac{d}{dx}-n\right) \cdot L_{2} \) + +It follows that both \( L[\alpha ^{n}]=0 \) and \( L[\alpha ^{-n}]=0 \), hence \( L[T_{n}(x)]=0 \). + +\begin{description} + +\item [Proof~2:]~ + +\end{description} + +Starting from the above equation, we compute a linear relation for +the partial derivatives of \( F \). Write \( \partial _{x}=\frac{d}{dx} \) and \( \Delta _{z}=z\frac{d}{dz} \). One computes + + +\[ +\left( 1-2xz+z^{2}\right) \cdot F=1-xz\] + +\[ +\left( 1-2xz+z^{2}\right) ^{2}\cdot \partial _{x}F=z-z^{3}\] + +\[ +\left( 1-2xz+z^{2}\right) ^{3}\cdot \partial _{x}^{2}F=4z^{2}-4z^{4}\] + +\[ +\left( 1-2xz+z^{2}\right) ^{2}\cdot \Delta _{z}F=xz-2z^{2}+xz^{3}\] + +\[ +\left( 1-2xz+z^{2}\right) ^{3}\cdot \partial _{x}\Delta _{z}F=z+2xz^{2}-6z^{3}+2xz^{4}+z^{5}\] + +\[ +\left( 1-2xz+z^{2}\right) ^{3}\cdot \Delta _{z}^{2}F=xz+(2x^{2}-4)z^{2}-(2x^{2}-4)z^{4}-xz^{5}\] + + +Solve a \( 6\times 6 \) system of linear equations over \( Q(x) \) to get +\[ +x\cdot \partial _{x}F+(x^{2}-1)\cdot \partial _{x}^{2}F-\Delta _{z}^{2}F=0\] + + +This is equivalent to the claimed equation \( (x^{2}-1)\cdot T_{n}^{''}(x)+x\cdot T_{n}^{'}(x)-n^{2}\cdot T_{n}(x)=0 \). + +\begin{lyxsectionbibliography} + +\item [1] Bruno Haible: D-finite power series in several variables. \em Diploma +thesis, University of Karlsruhe, June 1989. \em Sections 2.12 and +2.15. + +\end{lyxsectionbibliography} + +\end{document} diff --git a/doc/ratseries/README b/doc/ratseries/README new file mode 100644 index 0000000..e2de2f2 --- /dev/null +++ b/doc/ratseries/README @@ -0,0 +1,15 @@ +This directory contains an explanation of the algorithms CLN uses for the +computation of transcendental functions. This stuff was presented at the +IMACS/ACA 1997 in Hawaii and is published in the ANTS III proceedings. + + paper/ An updated version of the paper. + slides/ The slides used in the IMACS/ACA talk. + +It is published as + + Bruno Haible, Thomas Papanikolaou: + Fast multiprecision evaluation of series of rational numbers. + In: Algorithmic Number Theory, Third International Symposium, ANTS-III, + J. P. Buhler ed., Lecture Notes in Computer Science 1423, + Springer Verlag (1998). + diff --git a/doc/ratseries/paper/Makefile.devel b/doc/ratseries/paper/Makefile.devel new file mode 100644 index 0000000..a3d5f2b --- /dev/null +++ b/doc/ratseries/paper/Makefile.devel @@ -0,0 +1,38 @@ +# How to use the Makefile +# +# LATEX, BIBTEX, DVIPS, RM, GZIP and UUENCODE are configuration +# variables which you can change to point to the appropriate +# location on your system. You do not need to change anything else. +# +LATEX=latex +BIBTEX=bibtex +DVIPS=dvips -D600 +RM=rm -f +GZIP=gzip +UUENCODE=uuencode + +# `make' creates binsplit.dvi and binsplit.ps +# +all: binsplit.dvi binsplit.ps + +# `make binsplit.dvi' creates binsplit.dvi +# +binsplit.dvi: binsplit.tex binsplit.bib + $(LATEX) binsplit.tex + $(BIBTEX) binsplit + $(LATEX) binsplit.tex + $(LATEX) binsplit.tex + +# `make binsplit.ps' creates binsplit.ps +# +binsplit.ps: binsplit.dvi + $(DVIPS) -o binsplit.ps binsplit.dvi + +# `make clean' removes all redundant files produced by LaTeX and BibTeX +# +clean: + -$(RM) *.aux *.log *.toc *.idx *.lof *.lot *.bbl *.blg + +# Do not type the quotes! +# +# End of Help diff --git a/doc/ratseries/paper/README b/doc/ratseries/paper/README new file mode 100644 index 0000000..6173744 --- /dev/null +++ b/doc/ratseries/paper/README @@ -0,0 +1,41 @@ +TITLE : "Fast multiprecision evaluation of series of rational numbers" +AUTHORS: Bruno Haible, Thomas Papanikolaou + +Contents +-------- + +This directory contains the following files: + +Makefile ......................... to use with `make'. See below. + +README ........................... this file + +acm.bst.orig ..................... Original ISSAC '97 BibTeX style + +acm.bst .......................... ISSAC '97 BibTeX style (modified to keep + long author names) + +acmconf.sty ...................... ISSAC '97 ACM Conference style + +binsplit.bib ..................... BibTeX bibliography + +binsplit.tex ..................... LaTeX source + +binsplit.ps ...................... PostScript source + + +How to use the Makefile +----------------------- + +LATEX, BIBTEX, DVIPS, RM, GZIP and UUENCODE are configuration +variables which you can change to point to the appropriate +location on your system. You do not need to change anything else. + + `make binsplit.dvi' creates binsplit.dvi + + `make binsplit.ps' creates binsplit.ps + + `make clean' removes all files produced by LaTeX and BibTeX + +Do not type the quotes! + diff --git a/doc/ratseries/paper/acm.bst b/doc/ratseries/paper/acm.bst new file mode 100644 index 0000000..79d9401 --- /dev/null +++ b/doc/ratseries/paper/acm.bst @@ -0,0 +1,1134 @@ +% ACM Transactions bibliography style (24-Jan-88 version) +% A lot like abbrv.bst, but names come out "Last, initials", and in \sc. +% Some dates are parenthesized. +% +% History +% 2/ 6/86 (HWT) Original version, by Howard Trickey. +% 3/ 5/86 (HWT) Put in pp. everywhere but articles, as per ACM style. +% 1/24/88 (OP&HWT) Updated for BibTeX version 0.99a, Oren Patashnik; +% corrected the abbreviations to "Mar." and "Sept."; +% THIS `acm' VERSION DOES NOT WORK WITH BIBTEX 0.98i. + +ENTRY + { address + author + booktitle + chapter + edition + editor + howpublished + institution + journal + key + month + note + number + organization + pages + publisher + school + series + title + type + volume + year + } + {} + { label } + +INTEGERS { output.state before.all mid.sentence after.sentence after.block } + +FUNCTION {init.state.consts} +{ #0 'before.all := + #1 'mid.sentence := + #2 'after.sentence := + #3 'after.block := +} + +STRINGS { s t } + +FUNCTION {output.nonnull} +{ 's := + output.state mid.sentence = + { ", " * write$ } + { output.state after.block = + { add.period$ write$ + newline$ + "\newblock " write$ + } + { output.state before.all = + 'write$ + { add.period$ " " * write$ } + if$ + } + if$ + mid.sentence 'output.state := + } + if$ + s +} + +FUNCTION {output} +{ duplicate$ empty$ + 'pop$ + 'output.nonnull + if$ +} + +FUNCTION {output.check} +{ 't := + duplicate$ empty$ + { pop$ "empty " t * " in " * cite$ * warning$ } + 'output.nonnull + if$ +} + +FUNCTION {output.bibitem} +{ newline$ + "\bibitem{" write$ + cite$ write$ + "}" write$ + newline$ + "" + before.all 'output.state := +} + +FUNCTION {fin.entry} +{ add.period$ + write$ + newline$ +} + +FUNCTION {new.block} +{ output.state before.all = + 'skip$ + { after.block 'output.state := } + if$ +} + +FUNCTION {new.sentence} +{ output.state after.block = + 'skip$ + { output.state before.all = + 'skip$ + { after.sentence 'output.state := } + if$ + } + if$ +} + +FUNCTION {not} +{ { #0 } + { #1 } + if$ +} + +FUNCTION {and} +{ 'skip$ + { pop$ #0 } + if$ +} + +FUNCTION {or} +{ { pop$ #1 } + 'skip$ + if$ +} + +FUNCTION {new.block.checka} +{ empty$ + 'skip$ + 'new.block + if$ +} + +FUNCTION {new.block.checkb} +{ empty$ + swap$ empty$ + and + 'skip$ + 'new.block + if$ +} + +FUNCTION {field.or.null} +{ duplicate$ empty$ + { pop$ "" } + 'skip$ + if$ +} + +FUNCTION {emphasize} +{ duplicate$ empty$ + { pop$ "" } + { "{\em " swap$ * "}" * } + if$ +} + +FUNCTION {emphasizeic} +{ duplicate$ empty$ + { pop$ "" } + { "{\em " swap$ * "\/}" * } + if$ +} + +FUNCTION {scapify} +{ duplicate$ empty$ + { pop$ "" } + { "{\sc " swap$ * "}" * } + if$ +} + +INTEGERS { nameptr namesleft numnames } + +FUNCTION {format.names} +{ 's := + #1 'nameptr := + s num.names$ 'numnames := + numnames 'namesleft := + { namesleft #0 > } + { s nameptr "{vv~}{ff }{ll}{, jj}" format.name$ 't := + nameptr #1 > + { namesleft #1 > + { ", " * t * } + { t "others" = + { ", et~al." * } + { ", and " * t * } + if$ + } + if$ + } + 't + if$ + nameptr #1 + 'nameptr := + namesleft #1 - 'namesleft := + } + while$ +} + +% For names inside entries (e.g., editors of an "In ..."); +% this is exactly ABBRV.BST's `format.names' function. +FUNCTION {format.innames} +{ 's := + #1 'nameptr := + s num.names$ 'numnames := + numnames 'namesleft := + { namesleft #0 > } + { s nameptr "{f.~}{vv~}{ll}{, jj}" format.name$ 't := + nameptr #1 > + { namesleft #1 > + { ", " * t * } + { numnames #2 > + { "," * } + 'skip$ + if$ + t "others" = + { " et~al." * } + { " and " * t * } + if$ + } + if$ + } + 't + if$ + nameptr #1 + 'nameptr := + namesleft #1 - 'namesleft := + } + while$ +} + +FUNCTION {format.authors} +{ author empty$ + { "" } + { author format.names scapify } + if$ +} + +FUNCTION {format.editors} +{ editor empty$ + { "" } + { editor format.names scapify + editor num.names$ #1 > + { ", Eds." * } + { ", Ed." * } + if$ + } + if$ +} + +FUNCTION {format.ineditors} +{ editor empty$ + { "" } + { editor format.innames + editor num.names$ #1 > + { ", Eds." * } + { ", Ed." * } + if$ + } + if$ +} + +FUNCTION {format.title} +{ title empty$ + { "" } + { title } + if$ +} + +FUNCTION {n.dashify} +{ 't := + "" + { t empty$ not } + { t #1 #1 substring$ "-" = + { t #1 #2 substring$ "--" = not + { "--" * + t #2 global.max$ substring$ 't := + } + { { t #1 #1 substring$ "-" = } + { "-" * + t #2 global.max$ substring$ 't := + } + while$ + } + if$ + } + { t #1 #1 substring$ * + t #2 global.max$ substring$ 't := + } + if$ + } + while$ +} + +FUNCTION {format.date} +{ year empty$ + { month empty$ + { "" } + { "there's a month but no year in " cite$ * warning$ + month + } + if$ + } + { month empty$ + 'year + { month " " * year * } + if$ + } + if$ +} + +FUNCTION {format.btitle} +{ title emphasize +} + +FUNCTION {tie.or.space.connect} +{ duplicate$ text.length$ #3 < + { "~" } + { " " } + if$ + swap$ * * +} + +FUNCTION {either.or.check} +{ empty$ + 'pop$ + { "can't use both " swap$ * " fields in " * cite$ * warning$ } + if$ +} + +FUNCTION {format.bvolume} +{ volume empty$ + { "" } + { "vol.~" volume * + series empty$ + 'skip$ + { " of " * series emphasize * } + if$ + "volume and number" number either.or.check + } + if$ +} + +FUNCTION {format.number.series} +{ volume empty$ + { number empty$ + { series field.or.null } + { output.state mid.sentence = + { "no.~" } + { "No.~" } + if$ + number * + series empty$ + { "there's a number but no series in " cite$ * warning$ } + { " in " * series * } + if$ + } + if$ + } + { "" } + if$ +} + +FUNCTION {format.edition} +{ edition empty$ + { "" } + { output.state mid.sentence = + { edition "l" change.case$ "~ed." * } + { edition "t" change.case$ "~ed." * } + if$ + } + if$ +} + +FUNCTION {format.pages} +{ pages empty$ + { "" } + { pages n.dashify } + if$ +} + +INTEGERS { multiresult } + +FUNCTION {multi.page.check} +{ 't := + #0 'multiresult := + { multiresult not + t empty$ not + and + } + { t #1 #1 substring$ + duplicate$ "-" = + swap$ duplicate$ "," = + swap$ "+" = + or or + { #1 'multiresult := } + { t #2 global.max$ substring$ 't := } + if$ + } + while$ + multiresult +} + +FUNCTION {format.pp.pages} +{ pages empty$ + { "" } + { pages multi.page.check + { "pp.~" pages n.dashify * } + { "p.~" pages * } + if$ + } + if$ +} + +FUNCTION {format.journal.vol.num.date} +{ journal empty$ + { "empty journal in " cite$ * warning$ + "" + } + { journal + volume empty$ + 'skip$ + { " " * volume * } + if$ + number empty$ + 'emphasizeic + { emphasize ", " * number * } + if$ + year empty$ + { "empty year in " cite$ * warning$ } + { " (" * format.date * ")" * } + if$ + } + if$ +} + +FUNCTION {format.chapter.pages} +{ chapter empty$ + 'format.pp.pages + { type empty$ + { "ch.~" chapter * } + { type "l" change.case$ chapter tie.or.space.connect } + if$ + pages empty$ + 'skip$ + { ", " * format.pp.pages * } + if$ + } + if$ +} + +FUNCTION {format.in.ed.booktitle} +{ booktitle empty$ + { "" } + { "In " booktitle emphasize * + editor empty$ + 'skip$ + { ", " * format.ineditors * } + if$ + } + if$ +} + +% The proceedings title (it's on the stack) gets an (address, date) appended +FUNCTION {format.proc.date} +{ duplicate$ empty$ + { pop$ "" } + { year empty$ + { "empty year in " cite$ * warning$ + address empty$ + 'emphasize + { emphasizeic + " (" * address * ")" * + } + if$ + } + { emphasizeic + " (" * + address empty$ + 'skip$ + { address * ", " * } + if$ + format.date * + ")" * + } + if$ + } + if$ +} + +FUNCTION {format.in.proc.date} +{ booktitle empty$ + { "" } + { "In " booktitle format.proc.date * } + if$ +} + +FUNCTION {empty.misc.check} +{ author empty$ title empty$ howpublished empty$ + month empty$ year empty$ note empty$ + and and and and and + key empty$ not and + { "all relevant fields are empty in " cite$ * warning$ } + 'skip$ + if$ +} + +FUNCTION {format.thesis.type} +{ type empty$ + 'skip$ + { pop$ + type "t" change.case$ + } + if$ +} + +FUNCTION {format.tr.number} +{ type empty$ + { "Tech. Rep." } + 'type + if$ + number empty$ + { "t" change.case$ } + { number tie.or.space.connect } + if$ +} + +FUNCTION {format.article.crossref} +{ key empty$ + { journal empty$ + { "need key or journal for " cite$ * " to crossref " * crossref * + warning$ + "" + } + { "In {\em " journal * "\/}" * } + if$ + } + { "In " key * } + if$ + " \cite{" * crossref * "}" * +} + +FUNCTION {format.crossref.editor} +{ editor #1 "{vv~}{ll}" format.name$ + editor num.names$ duplicate$ + #2 > + { pop$ " et~al." * } + { #2 < + 'skip$ + { editor #2 "{ff }{vv }{ll}{ jj}" format.name$ "others" = + { " et~al." * } + { " and " * editor #2 "{vv~}{ll}" format.name$ * } + if$ + } + if$ + } + if$ +} + +FUNCTION {format.book.crossref} +{ volume empty$ + { "empty volume in " cite$ * "'s crossref of " * crossref * warning$ + "In " + } + { "Vol.~" volume * + " of " * + } + if$ + editor empty$ + editor field.or.null author field.or.null = + or + { key empty$ + { series empty$ + { "need editor, key, or series for " cite$ * " to crossref " * + crossref * warning$ + "" * + } + { "{\em " * series * "\/}" * } + if$ + } + { key * } + if$ + } + { format.crossref.editor * } + if$ + " \cite{" * crossref * "}" * +} + +FUNCTION {format.incoll.inproc.crossref} +{ editor empty$ + editor field.or.null author field.or.null = + or + { key empty$ + { booktitle empty$ + { "need editor, key, or booktitle for " cite$ * " to crossref " * + crossref * warning$ + "" + } + { "In {\em " booktitle * "\/}" * } + if$ + } + { "In " key * } + if$ + } + { "In " format.crossref.editor * } + if$ + " \cite{" * crossref * "}" * +} + +FUNCTION {article} +{ output.bibitem + format.authors "author" output.check + new.block + format.title "title" output.check + new.block + crossref missing$ + { format.journal.vol.num.date output + format.pages output + } + { format.article.crossref output.nonnull + format.pp.pages output + } + if$ + new.block + note output + fin.entry +} + +FUNCTION {book} +{ output.bibitem + author empty$ + { format.editors "author and editor" output.check } + { format.authors output.nonnull + crossref missing$ + { "author and editor" editor either.or.check } + 'skip$ + if$ + } + if$ + new.block + format.btitle "title" output.check + format.edition output + crossref missing$ + { format.bvolume output + new.block + format.number.series output + new.sentence + publisher "publisher" output.check + address output + } + { new.block + format.book.crossref output.nonnull + } + if$ + format.date "year" output.check + new.block + note output + fin.entry +} + +FUNCTION {booklet} +{ output.bibitem + format.authors output + new.block + format.title "title" output.check + howpublished address new.block.checkb + howpublished output + address output + format.date output + new.block + note output + fin.entry +} + +FUNCTION {inbook} +{ output.bibitem + author empty$ + { format.editors "author and editor" output.check } + { format.authors output.nonnull + crossref missing$ + { "author and editor" editor either.or.check } + 'skip$ + if$ + } + if$ + new.block + format.btitle "title" output.check + format.edition output + crossref missing$ + { format.bvolume output + new.block + format.number.series output + new.sentence + publisher "publisher" output.check + address output + } + { new.block + format.book.crossref output.nonnull + } + if$ + format.date "year" output.check + format.chapter.pages "chapter and pages" output.check + new.block + note output + fin.entry +} + +FUNCTION {incollection} +{ output.bibitem + format.authors "author" output.check + new.block + format.title "title" output.check + new.block + crossref missing$ + { format.in.ed.booktitle "booktitle" output.check + format.edition output + format.bvolume output + format.number.series output + new.sentence + publisher "publisher" output.check + address output + format.date "year" output.check + } + { format.incoll.inproc.crossref output.nonnull } + if$ + format.chapter.pages output + new.block + note output + fin.entry +} + +FUNCTION {inproceedings} +{ output.bibitem + format.authors "author" output.check + new.block + format.title "title" output.check + new.block + crossref missing$ + { format.in.proc.date "booktitle" output.check + format.ineditors output + format.bvolume output + format.number.series output + organization output + publisher output + } + { format.incoll.inproc.crossref output.nonnull } + if$ + format.pp.pages output + new.block + note output + fin.entry +} + +FUNCTION {conference} { inproceedings } + +FUNCTION {manual} +{ output.bibitem + author empty$ + { organization scapify output } + { format.authors output.nonnull } + if$ + new.block + format.btitle "title" output.check + format.edition output + author empty$ + { address new.block.checka } + { organization address new.block.checkb + organization output + } + if$ + address output + format.date output + new.block + note output + fin.entry +} + +FUNCTION {mastersthesis} +{ output.bibitem + format.authors "author" output.check + new.block + format.title "title" output.check + new.block + "Master's thesis" format.thesis.type output.nonnull + school "school" output.check + address output + format.date "year" output.check + new.block + note output + fin.entry +} + +FUNCTION {misc} +{ output.bibitem + format.authors output + title howpublished new.block.checkb + format.title output + howpublished new.block.checka + howpublished output + format.date output + new.block + note output + fin.entry + empty.misc.check +} + +FUNCTION {phdthesis} +{ output.bibitem + format.authors "author" output.check + new.block + format.btitle "title" output.check + new.block + "PhD thesis" format.thesis.type output.nonnull + school "school" output.check + address output + format.date "year" output.check + new.block + note output + fin.entry +} + +FUNCTION {proceedings} +{ output.bibitem + editor empty$ + { organization scapify output } + { format.editors output.nonnull } + if$ + new.block + title format.proc.date "title" output.check + format.bvolume output + format.number.series output + editor empty$ + 'skip$ + { organization output } + if$ + publisher output + new.block + note output + fin.entry +} + +FUNCTION {techreport} +{ output.bibitem + format.authors "author" output.check + new.block + format.title "title" output.check + new.block + format.tr.number output.nonnull + institution "institution" output.check + address output + format.date "year" output.check + new.block + note output + fin.entry +} + +FUNCTION {unpublished} +{ output.bibitem + format.authors "author" output.check + new.block + format.title "title" output.check + new.block + note "note" output.check + format.date output + fin.entry +} + +FUNCTION {default.type} { misc } + +MACRO {jan} {"Jan."} + +MACRO {feb} {"Feb."} + +MACRO {mar} {"Mar."} + +MACRO {apr} {"Apr."} + +MACRO {may} {"May"} + +MACRO {jun} {"June"} + +MACRO {jul} {"July"} + +MACRO {aug} {"Aug."} + +MACRO {sep} {"Sept."} + +MACRO {oct} {"Oct."} + +MACRO {nov} {"Nov."} + +MACRO {dec} {"Dec."} + +MACRO {acmcs} {"ACM Comput. Surv."} + +MACRO {acta} {"Acta Inf."} + +MACRO {cacm} {"Commun. ACM"} + +MACRO {ibmjrd} {"IBM J. Res. Dev."} + +MACRO {ibmsj} {"IBM Syst.~J."} + +MACRO {ieeese} {"IEEE Trans. Softw. Eng."} + +MACRO {ieeetc} {"IEEE Trans. Comput."} + +MACRO {ieeetcad} + {"IEEE Trans. Comput.-Aided Design Integrated Circuits"} + +MACRO {ipl} {"Inf. Process. Lett."} + +MACRO {jacm} {"J.~ACM"} + +MACRO {jcss} {"J.~Comput. Syst. Sci."} + +MACRO {scp} {"Sci. Comput. Programming"} + +MACRO {sicomp} {"SIAM J. Comput."} + +MACRO {tocs} {"ACM Trans. Comput. Syst."} + +MACRO {tods} {"ACM Trans. Database Syst."} + +MACRO {tog} {"ACM Trans. Gr."} + +MACRO {toms} {"ACM Trans. Math. Softw."} + +MACRO {toois} {"ACM Trans. Office Inf. Syst."} + +MACRO {toplas} {"ACM Trans. Program. Lang. Syst."} + +MACRO {tcs} {"Theoretical Comput. Sci."} + +READ + +FUNCTION {sortify} +{ purify$ + "l" change.case$ +} + +INTEGERS { len } + +FUNCTION {chop.word} +{ 's := + 'len := + s #1 len substring$ = + { s len #1 + global.max$ substring$ } + 's + if$ +} + +FUNCTION {sort.format.names} +{ 's := + #1 'nameptr := + "" + s num.names$ 'numnames := + numnames 'namesleft := + { namesleft #0 > } + { nameptr #1 > + { " " * } + 'skip$ + if$ + s nameptr "{vv{ } }{ll{ }}{ f{ }}{ jj{ }}" format.name$ 't := + nameptr numnames = t "others" = and + { "et al" * } + { t sortify * } + if$ + nameptr #1 + 'nameptr := + namesleft #1 - 'namesleft := + } + while$ +} + +FUNCTION {sort.format.title} +{ 't := + "A " #2 + "An " #3 + "The " #4 t chop.word + chop.word + chop.word + sortify + #1 global.max$ substring$ +} + +FUNCTION {author.sort} +{ author empty$ + { key empty$ + { "to sort, need author or key in " cite$ * warning$ + "" + } + { key sortify } + if$ + } + { author sort.format.names } + if$ +} + +FUNCTION {author.editor.sort} +{ author empty$ + { editor empty$ + { key empty$ + { "to sort, need author, editor, or key in " cite$ * warning$ + "" + } + { key sortify } + if$ + } + { editor sort.format.names } + if$ + } + { author sort.format.names } + if$ +} + +FUNCTION {author.organization.sort} +{ author empty$ + { organization empty$ + { key empty$ + { "to sort, need author, organization, or key in " cite$ * warning$ + "" + } + { key sortify } + if$ + } + { "The " #4 organization chop.word sortify } + if$ + } + { author sort.format.names } + if$ +} + +FUNCTION {editor.organization.sort} +{ editor empty$ + { organization empty$ + { key empty$ + { "to sort, need editor, organization, or key in " cite$ * warning$ + "" + } + { key sortify } + if$ + } + { "The " #4 organization chop.word sortify } + if$ + } + { editor sort.format.names } + if$ +} + +FUNCTION {presort} +{ type$ "book" = + type$ "inbook" = + or + 'author.editor.sort + { type$ "proceedings" = + 'editor.organization.sort + { type$ "manual" = + 'author.organization.sort + 'author.sort + if$ + } + if$ + } + if$ + " " + * + year field.or.null sortify + * + " " + * + title field.or.null + sort.format.title + * + #1 entry.max$ substring$ + 'sort.key$ := +} + +ITERATE {presort} + +SORT + +STRINGS { longest.label } + +INTEGERS { number.label longest.label.width } + +FUNCTION {initialize.longest.label} +{ "" 'longest.label := + #1 'number.label := + #0 'longest.label.width := +} + +FUNCTION {longest.label.pass} +{ number.label int.to.str$ 'label := + number.label #1 + 'number.label := + label width$ longest.label.width > + { label 'longest.label := + label width$ 'longest.label.width := + } + 'skip$ + if$ +} + +EXECUTE {initialize.longest.label} + +ITERATE {longest.label.pass} + +FUNCTION {begin.bib} +{ preamble$ empty$ + 'skip$ + { preamble$ write$ newline$ } + if$ + "\begin{thebibliography}{" longest.label * "}" * write$ newline$ +} + +EXECUTE {begin.bib} + +EXECUTE {init.state.consts} + +ITERATE {call.type$} + +FUNCTION {end.bib} +{ newline$ + "\end{thebibliography}" write$ newline$ +} + +EXECUTE {end.bib} diff --git a/doc/ratseries/paper/acmconf.sty b/doc/ratseries/paper/acmconf.sty new file mode 100644 index 0000000..3b23c99 --- /dev/null +++ b/doc/ratseries/paper/acmconf.sty @@ -0,0 +1,713 @@ +% ACMCONF DOCUMENT STYLE - Updated 10 April 1995. +% +% This is a patched version of the 5 April 1993 release. No stylistic +% changes have been made; it should produce output identical to the 1993 +% release if that release worked properly on your system. A LaTeX2e patch +% has been added for systems having problems with the section header font. +% +% If you get an error message similar to +% +% ! Undefined control sequence. +% l.165 \font\ninsfb = cmssbx10\@ptscale +% +% then see the comments beginning on line 173 (look for "DIAGNOSTICS"). +%----------------------------------------------------------------------- +% Modification of Traub/Shivers version by Kevin Theobald, McGill +% University. New version has automatic copyright space, option +% for box around "to appear" entry, and style option to indent +% first paragraph after subheadings. Released 5 April 1993. +% +% To use: install in reachable directory (one contained in TEXINPUTS +% environment variable); use \documentstyle[]{acmconf} +%----------------------------------------------------------------------- +% adapted from ARTICLE document style by Ken Traub +% Hacked for [preprint] option by Olin Shivers 4/91 +% ARTICLE DOCUMENT STYLE -- Released 16 March 1988 +% for LaTeX version 2.09 +% Copyright (C) 1988 by Leslie Lamport + +%%% ACMCONF is a document style for producing two-column camera-ready pages for +%%% ACM conferences, according to ACM specifications. The main features of +%%% this style are: +%%% +%%% 1) Two columns. +%%% 2) Side and top margins of 4.5pc, bottom margin of 6pc, column gutter of +%%% 2pc, hence columns are 20pc wide and 55.5pc tall. (6pc = 1in, approx) +%%% 3) First page has title information, and an extra 6pc of space at the +%%% bottom of the first column for the ACM copyright notice. +%%% 4) Text is 9pt on 10pt baselines; titles (except main) are 9pt bold. +%%% +%%% This document style supports a [preprint] style option that allows +%%% you to run off a copy for a preprint -- with page numbers, "to +%%% appear" information, and so forth. This is documented below. +%%% +%%% This document style also supports a [secindent] style option which +%%% causes paragraphs following (sub)section heads to be indented like +%%% the others. (Added by KBT) +%%% +%%% There are a few restrictions you must observe: +%%% +%%% 1) You cannot change the font size; ACM wants you to use 9pt. +%%% 3) You must start your paper with the \maketitle command. Prior to the +%%% \maketitle you must have \title and \author commands. If you have a +%%% \date command it will be ignored; no date appears on the paper, since +%%% the proceedings will have a date on the front cover. +%%% 4) Marginal paragraphs, tables of contents, lists of figures and tables, +%%% and page headings are all forbidden. +%%% 5) The `figure' environment will produce a figure one column wide; if you +%%% want one that is two columns wide, use `figure*'. +%%% +%%% Page Headings: +%%% Normally, \pagestyle commands are ignored --- pages have no headings or +%%% numbers. ACM will number the pages for you when they are inserted into the +%%% proceedings (you should put page numbers on the BACK of each page, though, +%%% in case someone drops your paper on the floor). +%%% +%%% If the [preprint] option is present, then \pagestyle commands are obeyed, +%%% and the default is \pagestyle{plain}. All pages (including the first) +%%% are numbered. (This is useful if you want to make a reprint version +%%% of your paper, with page numbering identical to the conference +%%% proceedings. In such a case, you may need to insert the command +%%% \setcounter{page}{...} before \maketitle.) The [twoside] option is +%%% also useful when using headers. +%%% +%%% Copyright Space: +%%% This style automatically leaves 1" blank space at the bottom of page 1/ +%%% column 1. This space can optionally be filled with some text using the +%%% \toappear{...} command. If used, this command must be BEFORE the \maketitle +%%% command. If this command is defined AND [preprint] is on, then the +%%% space is filled with the {...} text (at the bottom); otherwise, it is +%%% blank. If you use \toappearbox{...} instead of \toappear{...} then a +%%% box will be drawn around the text (if [preprint] is on). +%%% +%%% A typical usage looks like this: +%%% \toappear{To appear in the Ninth AES Conference on Medievil Lithuanian +%%% Embalming Technique, June 1991, Alfaretta, Georgia.} +%%% This will be included in the preprint, and left out of the conference +%%% version. +%%% +%%% Acmconf defines two useful conditionals. +%%% - \ifacmconf{true-stuff}{false-stuff} +%%% expands to true-stuff. +%%% - \ifpreprint true-stuff \else else-stuff \fi +%%% expands to true-stuff if the [preprint] option is being used, +%%% otherwise it expands to else-stuff. +%%% \ifacmconf is a latex command; \ifpreprint is a real latex conditional. +%%% +%%% WARNING: +%%% Some dvi-ps converters heuristically allow chars to drift from their +%%% true positions a few pixels. This loses noticeably with the 9pt sans-serif +%%% bold font used for section headers. You turn this hackery off in our +%%% dvi-ps converters with the -e option: +%%% dvips -e 0 foo.dvi >foo.ps + +\typeout{Document Style `acmconf' <22 May 89>. Hacked 4/91 by} +\typeout{ shivers@cs.cmu.edu, 4/93 by theobald@cs.mcgill.ca} +\typeout{Bugs to theobald@cs.mcgill.ca} + +\newif\if@acmconf\@acmconftrue +\long\def\ifacmconf#1#2{\if@acmconf#1\else#2\fi} + +\newif\ifpreprint +\def\ds@preprint{\preprinttrue} +\def\ds@twoside{\@twosidetrue \@mparswitchtrue} +\def\ds@secindent{\def\@afterindentfalse{\@afterindenttrue}} + +\@namedef{ds@10pt}{\@latexerr{The `10pt' option is not allowed in the `acmconf' + document style.}\@eha} +\@namedef{ds@11pt}{\@latexerr{The `11pt' option is not allowed in the `acmconf' + document style.}\@eha} +\@namedef{ds@12pt}{\@latexerr{The `12pt' option is not allowed in the `acmconf' + document style.}\@eha} + +\@options + +\lineskip 1pt % \lineskip is 1pt for all font sizes. +\normallineskip 1pt +\def\baselinestretch{1} + +\def\@normalsize{\@setsize\normalsize{10pt}\ixpt\@ixpt +\abovedisplayskip 9pt plus2pt minus4.5pt% +\belowdisplayskip \abovedisplayskip +\abovedisplayshortskip \z@ plus3pt% +\belowdisplayshortskip 5.4pt plus3pt minus3pt% +\let\@listi\@listI} % Setting of \@listi added 9 Jun 87 + +\def\small{\@setsize\small{9pt}\viiipt\@viiipt +\abovedisplayskip 7.6pt plus 3pt minus 4pt% +\belowdisplayskip \abovedisplayskip +\abovedisplayshortskip \z@ plus2pt% +\belowdisplayshortskip 3.6pt plus2pt minus 2pt +\def\@listi{\leftmargin\leftmargini %% Added 22 Dec 87 +\topsep 4pt plus 2pt minus 2pt\parsep 2pt plus 1pt minus 1pt +\itemsep \parsep}} + +\def\footnotesize{\@setsize\footnotesize{8pt}\viipt\@viipt +\abovedisplayskip 6.4pt plus 2pt minus 4pt% +\belowdisplayskip \abovedisplayskip +\abovedisplayshortskip \z@ plus 1pt% +\belowdisplayshortskip 2.7pt plus 1pt minus 2pt +\def\@listi{\leftmargin\leftmargini %% Added 22 Dec 87 +\topsep 3pt plus 1pt minus 1pt\parsep 2pt plus 1pt minus 1pt +\itemsep \parsep}} + +\def\scriptsize{\@setsize\scriptsize{8pt}\viipt\@viipt} +\def\tiny{\@setsize\tiny{6pt}\vpt\@vpt} +\def\large{\@setsize\large{13.6pt}\xipt\@xipt} +\def\Large{\@setsize\Large{16pt}\xiipt\@xiipt} +\def\LARGE{\@setsize\LARGE{18pt}\xivpt\@xivpt} +\def\huge{\@setsize\huge{22pt}\xviipt\@xviipt} +\def\Huge{\@setsize\Huge{25pt}\xxpt\@xxpt} + +%%% Patch for LaTeX-2e (LaTeX 2.09 compatibility mode) +%%% The line \font\ninsfb = cmssbx10\@ptscale9 is replaced by +\expandafter\ifx\csname fontseries\endcsname\relax + \font\ninsfb = cmssbx10\@ptscale9 + \else + \def\ninsfb{\fontfamily{cmss}\fontseries{bx}\fontshape{n} + \fontsize{9}{\f@baselineskip}\selectfont} +\fi +%%% End patch for LaTeX-2e +\def\@acmtitlestyle{\normalsize\ninsfb} +%%% +%%% DIAGNOSTICS: +%%% The ten lines above (the patch and the \def\@acmtitlestyle command) will +%%% cause problems if your printer doesn't have the 9pt. bold sans-serif font. +%%% If this is a problem, try commenting out those lines and uncommenting one +%%% of the following alternatives. (It is best to try them in order until +%%% finding one that works; the earlier alternatives cause less change.) +%%% +%%% ALTERNATIVE 1: (works if your system has the same font in 10pt.) +%%% \font\tensfb = cmssbx10 +%%% \def\@acmtitlestyle{\normalsize\tensfb} +%%% ALTERNATIVE 2: +%%% \def\@acmtitlestyle{\normalsize\ninbf} +%%% ALTERNATIVE 3: +%%% \def\@acmtitlestyle{\normalsize\tenbf} + +\normalsize % Choose the normalsize font. + +\oddsidemargin 4.5pc +\evensidemargin 4.5pc +\advance\oddsidemargin by -1in % Correct for LaTeX gratuitousness +\advance\evensidemargin by -1in % Correct for LaTeX gratuitousness +\marginparwidth 0pt % Margin pars are not allowed. +\marginparsep 11pt % Horizontal space between outer margin and + % marginal note + + % Top of page: +\topmargin 4.5pc % Nominal distance from top of page to top of + % box containing running head. +\advance\topmargin by -1in % Correct for LaTeX gratuitousness +\headheight 0pt % Height of box containing running head. +\headsep 0pt % Space between running head and text. + % Bottom of page: +\footskip 30pt % Distance from baseline of box containing foot + % to baseline of last line of text. +\footheight 12pt % Height of box containing running foot. + +%% Must redefine the top margin so there's room for headers and +%% page numbers if you are using the preprint option. Footers +%% are OK as is. Olin. +\advance\topmargin by -37pt % Leave 37pt above text for headers +\headheight 12pt % Height of box containing running head. +\headsep 25pt % Space between running head and text. + +\textheight 666pt % 9 1/4 column height +\textwidth 42pc % Width of text line. + % For two-column mode: +\columnsep 2pc % Space between columns +\columnseprule 0pt % Width of rule between columns. +\hfuzz 1pt % Allow some variation in column width, otherwise it's + % too hard to typeset in narrow columns. + +\footnotesep 5.6pt % Height of strut placed at the beginning of every + % footnote = height of normal \footnotesize strut, + % so no extra space between footnotes. + +\skip\footins 8.1pt plus 4pt minus 2pt % Space between last line of text and + % top of first footnote. +\floatsep 11pt plus 2pt minus 2pt % Space between adjacent floats moved + % to top or bottom of text page. +\textfloatsep 18pt plus 2pt minus 4pt % Space between main text and floats + % at top or bottom of page. +\intextsep 11pt plus 2pt minus 2pt % Space between in-text figures and + % text. +\@maxsep 18pt % The maximum of \floatsep, + % \textfloatsep and \intextsep (minus + % the stretch and shrink). +\dblfloatsep 11pt plus 2pt minus 2pt % Same as \floatsep for double-column + % figures in two-column mode. +\dbltextfloatsep 18pt plus 2pt minus 4pt% \textfloatsep for double-column + % floats. +\@dblmaxsep 18pt % The maximum of \dblfloatsep and + % \dbltexfloatsep. +\@fptop 0pt plus 1fil % Stretch at top of float page/column. (Must be + % 0pt plus ...) +\@fpsep 8pt plus 2fil % Space between floats on float page/column. +\@fpbot 0pt plus 1fil % Stretch at bottom of float page/column. (Must be + % 0pt plus ... ) +\@dblfptop 0pt plus 1fil % Stretch at top of float page. (Must be 0pt plus ...) +\@dblfpsep 8pt plus 2fil % Space between floats on float page. +\@dblfpbot 0pt plus 1fil % Stretch at bottom of float page. (Must be + % 0pt plus ... ) +\marginparpush 5pt % Minimum vertical separation between two marginal + % notes. + +\parskip 0pt plus 1pt % Extra vertical space between paragraphs. +\parindent 13.5pt % Width of paragraph indentation. +%\topsep 8pt plus 2pt minus 4pt % Extra vertical space, in addition to + % \parskip, added above and below list and + % paragraphing environments. +\partopsep 2pt plus 1pt minus 1pt% Extra vertical space, in addition to + % \parskip and \topsep, added when user + % leaves blank line before environment. +%\itemsep 4pt plus 2pt minus 1pt % Extra vertical space, in addition to + % \parskip, added between list items. +% See \@listI for values of \topsep and \itemsep + +\@lowpenalty 51 % Produced by \nopagebreak[1] or \nolinebreak[1] +\@medpenalty 151 % Produced by \nopagebreak[2] or \nolinebreak[2] +\@highpenalty 301 % Produced by \nopagebreak[3] or \nolinebreak[3] + +\@beginparpenalty -\@lowpenalty % Before a list or paragraph environment. +\@endparpenalty -\@lowpenalty % After a list or paragraph environment. +\@itempenalty -\@lowpenalty % Between list items. + +% \clubpenalty % 'Club line' at bottom of page. +% \widowpenalty % 'Widow line' at top of page. +% \displaywidowpenalty % Math display widow line. +% \predisplaypenalty % Breaking before a math display. +% \postdisplaypenalty % Breaking after a math display. +% \interlinepenalty % Breaking at a line within a paragraph. +% \brokenpenalty % Breaking after a hyphenated line. + +\def\part{\par % New paragraph + \addvspace{4ex} % Adds vertical space above title. + \@afterindentfalse % Suppresses indent in first paragraph. Change + \secdef\@part\@spart}% to \@afterindenttrue to have indent. + +\def\@part[#1]#2{\ifnum \c@secnumdepth >\m@ne % IF secnumdepth > -1 + \refstepcounter{part} % THEN step part counter + \addcontentsline{toc}{part}{\thepart % add toc line + \hspace{1em}#1}\else % ELSE add unnumbered line + \addcontentsline{toc}{part}{#1}\fi % FI + { \parindent 0pt \raggedright + \ifnum \c@secnumdepth >\m@ne% IF secnumdepth > -1 + \Large \bf Part \thepart % THEN Print 'Part' and + \par \nobreak % number in \Large boldface. + \fi % FI + \huge \bf % Select \huge boldface. + #2\markboth{}{}\par } % Print title and set heading marks null. + \nobreak % TeX penalty to prevent page break. + \vskip 3ex % Space between title and text. + \@afterheading % Routine called after part and + } % section heading. + +\def\@spart#1{{\parindent 0pt \raggedright + \huge \bf + #1\par} % Title. + \nobreak % TeX penalty to prevent page break. + \vskip 3ex % Space between title and text. + \@afterheading % Routine called after part and + } % section heading. + +\def\section{\@startsection {section}{1}{\z@}{-3.5ex plus -1ex minus + -.2ex}{2.3ex plus .2ex}{\@acmtitlestyle}} +\def\subsection{\@startsection{subsection}{2}{\z@}{-3.25ex plus -1ex minus + -.2ex}{1.5ex plus .2ex}{\@acmtitlestyle}} +\def\subsubsection{\@startsection{subsubsection}{3}{\z@}{-3.25ex plus +-1ex minus -.2ex}{1.5ex plus .2ex}{\@acmtitlestyle}} +\def\paragraph{\@startsection + {paragraph}{4}{\z@}{3.25ex plus 1ex minus .2ex}{-1em}{\@acmtitlestyle}} +\def\subparagraph{\@startsection + {subparagraph}{4}{\parindent}{3.25ex plus 1ex minus + .2ex}{-1em}{\@acmtitlestyle}} + +\setcounter{secnumdepth}{3} + +\def\appendix{\par + \setcounter{section}{0} + \setcounter{subsection}{0} + \def\thesection{\Alph{section}}} + +\leftmargini 22.5pt +\leftmarginii 19.8pt % > \labelsep + width of '(m)' +\leftmarginiii 16.8pt % > \labelsep + width of 'vii.' +\leftmarginiv 15.3pt % > \labelsep + width of 'M.' +\leftmarginv 9pt +\leftmarginvi 9pt + +\leftmargin\leftmargini +\labelsep 4.5pt +\labelwidth\leftmargini\advance\labelwidth-\labelsep +% \parsep 4pt plus 2pt minus 1pt (Removed 9 Jun 87) + +% \@listI defines top level and \@listi values of +% \leftmargin, \topsep, \parsep, and \itemsep +% (Added 9 Jun 87) +\def\@listI{\leftmargin\leftmargini \parsep 3.6pt plus 2pt minus 1pt% +\topsep 7.2pt plus 2pt minus 4pt% +\itemsep 3.6pt plus 2pt minus 1pt} + +\let\@listi\@listI +\@listi + +\def\@listii{\leftmargin\leftmarginii + \labelwidth\leftmarginii\advance\labelwidth-\labelsep + \topsep 3.6pt plus 2pt minus 1pt + \parsep 1.8pt plus 0.9pt minus 0.9pt + \itemsep \parsep} + +\def\@listiii{\leftmargin\leftmarginiii + \labelwidth\leftmarginiii\advance\labelwidth-\labelsep + \topsep 1.8pt plus 0.9pt minus 0.9pt + \parsep \z@ \partopsep 1pt plus 0pt minus 1pt + \itemsep \topsep} + +\def\@listiv{\leftmargin\leftmarginiv + \labelwidth\leftmarginiv\advance\labelwidth-\labelsep} + +\def\@listv{\leftmargin\leftmarginv + \labelwidth\leftmarginv\advance\labelwidth-\labelsep} + +\def\@listvi{\leftmargin\leftmarginvi + \labelwidth\leftmarginvi\advance\labelwidth-\labelsep} + +\def\labelenumi{\theenumi.} +\def\theenumi{\arabic{enumi}} + +\def\labelenumii{(\theenumii)} +\def\theenumii{\alph{enumii}} +\def\p@enumii{\theenumi} + +\def\labelenumiii{\theenumiii.} +\def\theenumiii{\roman{enumiii}} +\def\p@enumiii{\theenumi(\theenumii)} + +\def\labelenumiv{\theenumiv.} +\def\theenumiv{\Alph{enumiv}} +\def\p@enumiv{\p@enumiii\theenumiii} + +\def\labelitemi{$\bullet$} +\def\labelitemii{\bf --} +\def\labelitemiii{$\ast$} +\def\labelitemiv{$\cdot$} + +\def\verse{\let\\=\@centercr + \list{}{\itemsep\z@ \itemindent -1.5em\listparindent \itemindent + \rightmargin\leftmargin\advance\leftmargin 1.5em}\item[]} +\let\endverse\endlist + +\def\quotation{\list{}{\listparindent 1.5em + \itemindent\listparindent + \rightmargin\leftmargin \parsep 0pt plus 1pt}\item[]} +\let\endquotation=\endlist + +\def\quote{\list{}{\rightmargin\leftmargin}\item[]} +\let\endquote=\endlist + +\def\descriptionlabel#1{\hspace\labelsep \bf #1} +\def\description{\list{}{\labelwidth\z@ \itemindent-\leftmargin + \let\makelabel\descriptionlabel}} + +\let\enddescription\endlist + +%\newdimen\descriptionmargin +%\descriptionmargin=3em + +\def\theequation{\arabic{equation}} + +% \jot = 3pt % Extra space added between lines of an eqnarray environment + +% The macro \@eqnnum defines how equation numbers are to appear in equations. +% +% \def\@eqnnum{(\theequation)} +% + +% Changed pagenum to 1, so margins work right in twoside option. +% It's not clear to me that this environment is useful for acmconf.sty +% anyway. -Olin +\def\titlepage{\@restonecolfalse\if@twocolumn\@restonecoltrue\onecolumn + \else \newpage \fi \thispagestyle{empty}\c@page\@ne} + +\def\endtitlepage{\if@restonecol\twocolumn \else \newpage \fi \c@page\@ne} + +\arraycolsep 4.5pt % Half the space between columns in an array environment. +\tabcolsep 5.4pt % Half the space between columns in a tabular environment. +\arrayrulewidth .4pt % Width of rules in array and tabular environment. +\doublerulesep 1.8pt % Space between adjacent rules in array or tabular env. + +\tabbingsep \labelsep % Space used by the \' command. (See LaTeX manual.) + +\skip\@mpfootins = \skip\footins + +\fboxsep = 2.7pt % Space left between box and text by \fbox and \framebox. +\fboxrule = .4pt % Width of rules in box made by \fbox and \framebox. + +\newcounter{part} +\newcounter {section} +\newcounter {subsection}[section] +\newcounter {subsubsection}[subsection] +\newcounter {paragraph}[subsubsection] +\newcounter {subparagraph}[paragraph] + +\def\thepart{\Roman{part}} % Roman numeral part numbers. +\def\thesection {\arabic{section}} +\def\thesubsection {\thesection.\arabic{subsection}} +\def\thesubsubsection {\thesubsection .\arabic{subsubsection}} +\def\theparagraph {\thesubsubsection.\arabic{paragraph}} +\def\thesubparagraph {\theparagraph.\arabic{subparagraph}} + +\def\@pnumwidth{1.55em} +\def\@tocrmarg {2.55em} +\def\@dotsep{4.5} +\setcounter{tocdepth}{3} + +\def\tableofcontents{\@latexerr{\tableofcontents: Tables of contents are not + allowed in the `acmconf' document style.}\@eha} + +\def\l@part#1#2{\addpenalty{\@secpenalty} + \addvspace{2.25em plus 1pt} % space above part line + \begingroup + \@tempdima 3em % width of box holding part number, used by + \parindent \z@ \rightskip \@pnumwidth %% \numberline + \parfillskip -\@pnumwidth + {\large \bf % set line in \large boldface + \leavevmode % TeX command to enter horizontal mode. + #1\hfil \hbox to\@pnumwidth{\hss #2}}\par + \nobreak % Never break after part entry + \endgroup} + +\def\l@section#1#2{\addpenalty{\@secpenalty} % good place for page break + \addvspace{1.0em plus 1pt} % space above toc entry + \@tempdima 1.5em % width of box holding section number + \begingroup + \parindent \z@ \rightskip \@pnumwidth + \parfillskip -\@pnumwidth + \bf % Boldface. + \leavevmode % TeX command to enter horizontal mode. + \advance\leftskip\@tempdima %% added 5 Feb 88 to conform to + \hskip -\leftskip %% 25 Jan 88 change to \numberline + #1\nobreak\hfil \nobreak\hbox to\@pnumwidth{\hss #2}\par + \endgroup} + + +\def\l@subsection{\@dottedtocline{2}{1.5em}{2.3em}} +\def\l@subsubsection{\@dottedtocline{3}{3.8em}{3.2em}} +\def\l@paragraph{\@dottedtocline{4}{7.0em}{4.1em}} +\def\l@subparagraph{\@dottedtocline{5}{10em}{5em}} + +\def\listoffigures{\@latexerr{\listoffigures: Lists of figures are not + allowed in the `acmconf' document style.}\@eha} + +\def\l@figure{\@dottedtocline{1}{1.5em}{2.3em}} + +\def\listoftables{\@latexerr{\listoftables: Lists of tables are not + allowed in the `acmconf' document style.}\@eha} +\let\l@table\l@figure + + +\def\thebibliography#1{\section*{References\@mkboth + {REFERENCES}{REFERENCES}}\list + {[\arabic{enumi}]}{\settowidth\labelwidth{[#1]}\leftmargin\labelwidth + \advance\leftmargin\labelsep + \usecounter{enumi}} + \def\newblock{\hskip .11em plus .33em minus .07em} + \sloppy\clubpenalty4000\widowpenalty4000 + \sfcode`\.=1000\relax} + +\let\endthebibliography=\endlist + +% \def\@biblabel#1{[#1]\hfill} % Produces the label for a \bibitem[...] + % command. +% \def\@cite#1{[#1]} % Produces the output of the \cite command. + +\newif\if@restonecol + +\def\theindex{\@restonecoltrue\if@twocolumn\@restonecolfalse\fi +\columnseprule \z@ +\columnsep 35pt\twocolumn[\section*{Index}] + \@mkboth{INDEX}{INDEX}\thispagestyle{empty}\parindent\z@ + \parskip\z@ plus .3pt\relax\let\item\@idxitem} + +\def\@idxitem{\par\hangindent 40pt} + +\def\subitem{\par\hangindent 40pt \hspace*{20pt}} + +\def\subsubitem{\par\hangindent 40pt \hspace*{30pt}} + +\def\endtheindex{\if@restonecol\onecolumn\else\clearpage\fi} + +\def\indexspace{\par \vskip 10pt plus 5pt minus 3pt\relax} + +\def\footnoterule{\kern-3\p@ + \hrule width .4\columnwidth + \kern 2.6\p@} % The \hrule has default height of .4pt . + +\long\def\@makefntext#1{\parindent 1em\noindent + \hbox to 1.8em{\hss$^{\@thefnmark}$}#1} + +\setcounter{topnumber}{2} +\def\topfraction{.7} +\setcounter{bottomnumber}{1} +\def\bottomfraction{.3} +\setcounter{totalnumber}{3} +\def\textfraction{.2} +\def\floatpagefraction{.5} +\setcounter{dbltopnumber}{2} +\def\dbltopfraction{.7} +\def\dblfloatpagefraction{.5} + +\long\def\@makecaption#1#2{ + \vskip 10pt + \setbox\@tempboxa\hbox{#1: #2} + \ifdim \wd\@tempboxa >\hsize % IF longer than one line: + #1: #2\par % THEN set as ordinary paragraph. + \else % ELSE center. + \hbox to\hsize{\hfil\box\@tempboxa\hfil} + \fi} + +\newcounter{figure} +\def\thefigure{\@arabic\c@figure} + +\def\fps@figure{tbp} +\def\ftype@figure{1} +\def\ext@figure{lof} +\def\fnum@figure{Figure \thefigure} +\def\figure{\@float{figure}} +\let\endfigure\end@float +\@namedef{figure*}{\@dblfloat{figure}} +\@namedef{endfigure*}{\end@dblfloat} + +\newcounter{table} +\def\thetable{\@arabic\c@table} + +\def\fps@table{tbp} +\def\ftype@table{2} +\def\ext@table{lot} +\def\fnum@table{Table \thetable} +\def\table{\@float{table}} +\let\endtable\end@float +\@namedef{table*}{\@dblfloat{table}} +\@namedef{endtable*}{\end@dblfloat} + +\def\maketitle{\par + \begingroup + \def\thefootnote{\fnsymbol{footnote}} + \def\@makefnmark{\hbox + to 0pt{$^{\@thefnmark}$\hss}} + \if@twocolumn + \twocolumn[\@maketitle] + \else \newpage + \global\@topnum\z@ % Prevents figures from going at top of page. +% \@maketitle \fi\thispagestyle{empty}\@thanks + \@maketitle \fi\@thanks + \endgroup + \setcounter{footnote}{0} + \let\maketitle\relax + \let\@maketitle\relax + \gdef\@thanks{}\gdef\@author{}\gdef\@title{}\let\thanks\relax + \@copyrightspace} + +\newbox\@acmtitlebox +\def\@maketitle{\newpage + \null + \setbox\@acmtitlebox\vbox{% + \vskip 2em % Vertical space above title. + \begin{center} + {\LARGE \@title \par} % Title set in \LARGE size. + \vskip 1.5em % Vertical space after title. + {\large % each author set in \large, in a + \lineskip .5em % tabular environment + \begin{tabular}[t]{c}\@author + \end{tabular}\par} + \vskip 1.5em % Vertical space after author. + \end{center}} + \dimen0=\ht\@acmtitlebox + \advance\dimen0 by -14.5pc\relax % Increased space for title box -- KBT + \unvbox\@acmtitlebox + \ifdim\dimen0<0.0pt\relax\vskip-\dimen0\fi} + +\def\abstract{\if@twocolumn +\section*{Abstract} +\else \small +\begin{center} +{\bf Abstract\vspace{-.5em}\vspace{0pt}} +\end{center} +\quotation +\fi} + +\def\endabstract{\if@twocolumn\else\endquotation\fi} + +%%% This section (written by KBT) handles the 1" box in the lower left +%%% corner of the left column of the first page by creating a picture, +%%% and inserting the predefined string at the bottom (with a negative +%%% displacement to offset the space allocated for a non-existent +%%% caption). +%%% +\def\ftype@copyrightbox{8} +\def\@copyrightspace{ +\@float{copyrightbox}[b] +\begin{center} +\setlength{\unitlength}{1pc} +\begin{picture}(20,2.8) +\ifpreprint \put(0,-0.95){\@toappear} \else \fi +\end{picture} +\end{center} +\end@float} + +\def\@toappear{} % Default setting blank - commands below change this. +\def\toappear#1{\def\@toappear{\parbox[b]{20pc}{#1}}} +\def\toappearbox#1{\def\@toappear{\raisebox{5pt}{\framebox[20pc]{\parbox[b]{19pc}{#1}}}}} + +\def\marginpar{\@latexerr{The \marginpar command is not allowed in the + `acmconf' document style.}\@eha} + +\mark{{}{}} % Initializes TeX's marks + +%% Headings are ignored unless the [preprint] option is in force. +\ifpreprint + \if@twoside + \def\ps@headings{ + \def\@oddfoot{} + \def\@evenfoot{} + \def\@evenhead{\rm\thepage\hfil \sl \leftmark} + \def\@oddhead{\hbox{}\sl \rightmark \hfil\rm\thepage} + \def\sectionmark##1{\markboth {\uppercase{\ifnum\c@secnumdepth>\z@ + \thesection \hskip 1em\relax \fi ##1}}{}} + \def\subsectionmark##1 + {\markright {\ifnum \c@secnumdepth >\@ne \thesubsection + \hskip 1em\relax \fi ##1}}} + + \else + \def\ps@headings{ + \def\@oddfoot{} + \def\@evenfoot{} + \def\@oddhead{\hbox{}\sl \rightmark \hfil \rm\thepage} + \def\sectionmark##1{\markright{\uppercase{\ifnum \c@secnumdepth >\z@ + \thesection\hskip 1em\relax \fi ##1}}}} + \fi + + \def\ps@myheadings{\def\@oddhead{\hbox{}\sl\rightmark \hfil\rm\thepage}% + \def \@evenhead{\rm \thepage\hfil\sl\leftmark\hbox{}}% + \def\@oddfoot{}% + \def\@evenfoot{}% + \def\sectionmark##1{}% + \def\subsectionmark##1{}} + +\else % preprint off -- all \pagestyle commands ==> \pagestyle{empty}. + \let\ps@plain\ps@empty + \let\ps@headings\ps@empty + \let\ps@myheadings\ps@empty +\fi + +\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} + +\ps@plain +\pagenumbering{arabic} % Arabic page numbers +\twocolumn % Double column. +\raggedbottom % Ragged bottom diff --git a/doc/ratseries/paper/binsplit.bib b/doc/ratseries/paper/binsplit.bib new file mode 100644 index 0000000..a3ae1ba --- /dev/null +++ b/doc/ratseries/paper/binsplit.bib @@ -0,0 +1,131 @@ + +@ARTICLE{71, + author = "Arnold Sch{\"o}nhage and Volker Strassen", + title = "Schnelle Multiplikation gro{\ss}er Zahlen", + journal = "Computing {\bf 7}", + year = 1971, + pages = "281--292"} + +@ARTICLE{76a, + author = "Richard P. Brent", + title = "The complexity of multiple-precision arithmetic", + journal = "Complexity of Computational Problem Solving", + editor = " R. P. Brent, R. S. Anderssen", + publisher = "University of Queensland Press", + year = "1976"} + +@ARTICLE{76b, + author = "Richard P. Brent", + title = "Fast multiple-precision evaluation of elementary functions", + journal = "Journal of the ACM {\bf 23}", + year = "1976", + pages = "242--251"} + +@ARTICLE{76c, + author = "Eugene Salamin", + title = "Computation of {$\pi$} using arithmetic-geometric mean", + journal = "Mathematics of Computation {\bf 30}", + year = "1976", + pages = "565--570"} + +@ARTICLE{80, + author = "Richard P. Brent and Edwin M. McMillan", + title = "Some new algorithms for high-precision computation of Euler's constant", + journal = "Mathematics of Computation {\bf 34}", + year = "1980", + pages = "305--312"} + +@BOOK{87, + author = "Jonathan M. Borwein and Peter B. Borwein", + title = "Pi and the AGM", + publisher = "Wiley", + year = "1987"} + +@ARTICLE{91, + author = "E. A. Karatsuba", + title = "Fast evaluation of transcendental functions", + journal = "Probl. Peredachi Inform. \bf{27}", + year = "1991", + pages = "76--99"} + +@ARTICLE{91b, + author = "E. A. Karatsuba", + title = "On fast computation of transcendental functions", + journal = "Soviet Math. Dokl. \bf{43}", + year = "1991", + pages = "693--694"} + +@ARTICLE{93, + author = "E. A. Karatsuba", + title = "Fast evaluation of $\zeta(3)$", + journal = "Probl. Peredachi Inform. \bf{29}", + year = "1993", + pages = "68--73"} + +@TECHREPORT{95, + author = "Thomas Papanikolaou and Ingrid Biehl and Johannes Buchmann", + title = "{\sf LiDIA}: a library for computational number theory", + institution = "Universit{\"a}t des Saarlandes", + type = "{SFB} 124 report", + year = "1995"} + +@UNPUBLISHED{95b, + author = "Henri Cohen and C. Batut and Dominique Bernardi and M. Olivier", + title = "{GP/PARI} calculator -- Version 1.39.03", + note = "Available via anonymous FTP from {\tt ftp://megrez.math.u-bordeaux.fr}", + year = "1995"} + +@ARTICLE{95c, + author = "E. A. Karatsuba", + title = "Fast calculation of the Riemann zeta function $\zeta(s)$ for integer values of the argument $s$", + journal = "Probl. Inform. Transm. \bf{31}", + year = "1995", + pages = "353--362"} + +@UNPUBLISHED{96a, + author = "Bruno Haible", + title = "{CLN}, a class library for numbers", + note = "Available via anonymous FTP from {\tt ftp://ftp.santafe.edu/pub/gnu/cln.tar.gz}", + year = "1996"} + +@UNPUBLISHED{96c, + author = "Theodor Amdeberhan and Doron Zeilberger", + title = "Acceleration of hypergeometric series via the WZ method", + note = "To appear in: Electronic Journal of Combinatorics, Wilf Festschrift Volume"} + +@UNPUBLISHED{96d, + author = "Simon Plouffe", + title = "{ISC}: Inverse Symbolic Calculator", + note = "Tables of records of computation, {\tt http://www.cecm.sfu.ca/projects/ISC/records2.html}"} + +@INPROCEEDINGS{96e, + author = "Richard P. Brent and Alf {van der Poorten} and Hermann {te Riele}", + title = "A comparative study of algorithms for computing continued fractions + of algebraic numbers", + booktitle = "H. Cohen (editor), Algorithmic Number Theory: Second International Symposium, ANTS-II", + publisher = "Springer Verlag", + pages = "37--49", + year = "1996"} + +@PhDTHESIS{97, + AUTHOR = "Thomas Papanikolaou", + TITLE = "Entwurf und Entwicklung einer objektorientierten Bibliothek + f{\"u}r algorithmische Zahlentheorie", + TYPE = "{PhD Thesis}", + INSTITUTION = "Universit{\"a}t des Saarlandes", + YEAR = "1997" +} + +@Manual{97b, + TITLE = "{\sf LiDIA 1.3} -- a library for computational number theory", + AUTHOR = "{\sf LiDIA}-Group", + ORGANIZATION = "Technische Universit{\"a}t Darmstadt", + NOTE = "Available via anonymous FTP from {\tt ftp://ftp.informatik.tu-darmstadt.de /pub/TI/systems/LiDIA} or via WWW from {\tt http://www.informatik.tu-darmstadt.de/TI/LiDIA}", + YEAR = "1997" +} + +@UNPUBLISHED{98, + author = "Thomas Papanikolaou", + title = "Homepage", + note = "{\tt http://www.math.u-bordeaux.fr/\~{}papanik}"} + diff --git a/doc/ratseries/paper/binsplit.dvi b/doc/ratseries/paper/binsplit.dvi new file mode 100644 index 0000000000000000000000000000000000000000..72fb2a4c4518e4d4185e82cb6fe8f824b930a855 GIT binary patch literal 59996 zcmeEv34B!5*>^H`lCXwdltplZM8c5C9uPHvEDFdHwTh^dWRi?bX2Q$_h`8HIT_)yo zWgJa)T+pg$-D?G0+Zhm-TD5Amt$S<5rApmU;rl<&Ip^Lx$po?O`+dLf`+a#|>CD`F z&pqck&w2LcD@XPv>z^1iEen6z2cyT=dVexL*cNGRi;Qu44ufQGI zblVU8?Zw}Xj$1ds6TR{KDOp)JIv&W%ir%=#fqxShUhq{^FTHr{uIis`THHS?zp*iE z0LIIyZwa|e-kYuOd8y13j>Mb~Oli5UYipZ7;%g0g>wRHgFkpCB>3b{Jc>Hai2z?DU z8ewn9=MB@R5dY@!8-aLROT4bLVWu|}?nq31cT!aRCEnY*&}x@Y-uJV*9M0>>3q(@QQ6&eK8vS=fq;Flk?`EIEO|#^pxA?d+IuCwgoZApfBXr zwGp*7B|qutxCu|!k7=(iis6?~o7ZUY8Yk;}r*86w8rlN%Z2s*FO3U4Ry*}6$3ez2a zk1^j@*ZJ6;!}M=&`iWO8Tnx5&VcTpPYpqdTR#IMS%<%>~AFGb|{Qh=hrnkYnhQ=K7 zkIUsvrKM%Xb>$NF|pmNca3{<<3h0{S{C*w5~<$N%pn1{!Te zpZbqCG+%{H$Q+3;BPY9rW% zpCjISqdDMP+2#$$8-t;EBQPo6VlWcU*KKqkL0 z;Pr$6wEAEG!>=;Dp(by@h|pz$az(oK#T;Lt-rv^X3p5$6w7onLZ%8+90vu_Po*7+h~!xxrsNS%oHCkqOq*pm)@;CYKu3u9Sdzn3hGCcc|Ieb=BzYCN}RY&agcP5LB z=6E}818r5X#TyCv>gh@IUc(askxwJ7pXuM|+NDbDrHr|;mC@m~9 zj%)LKLleVA#!OGdD60HRpo{-lFxA`I- zP#50cRu53n@Acbv-_?;AdDVBI3&5M5weAl6yQ?pn7l?#{owFMo+IZC+w~6Dhpa)*Z zob&EisBO{6ke8?;kdt=dIs#CbZfy31jk>rOnCF#K_U7071d#phG3^BxLna(1YG{P9 zO#!?*9a2Tg!S=3$Kq4z!JyX8i+C%!7Kh7C8%lYvt( z?88Vi_5t{005f>ue(xGz1UuVKRGcof#KpoShVakv)$yRhbqlk)wC7(?3*(&!HihG< z1&sRwtz%m1!|8@RAE|{=J!fDbNv9+>^zz5--=hYfo$-D0CF&Ns^xV1c*EVBB^PB~O zk(lG*a4-PU;GxL|L*5AH={G{&FlIeXcf9hL$Cx>3lHqGGhR2WHY5<1g_+uV9e>gQcU3b3LR#uEZ0vQfapYmBX<}sl= z@6}p^j(hTp`T;Uwl{$I zxP&Xsd@KIN5BS#;62EyuxRbxr?}fT^%4y9WK{VA+t$Z$l{|zz6`iFglDrEu`AUb!w zN?7Cp1Y10z6-<{2;mm_0U~!P{c;Ay;jRgU18-s0u203^gUe(@(lQttn6q=9cQXJJ5 zUmy;Q1jq>^`BZ*8^_{sA6^Wu3>CV3Q;{e9A*IvR_hHdW*gA^GxfNdaQiZ&7{15_j7F6|y?v&R6ih~o3WaR_6~tH1>aI?Nitj6D&s zUhq}GwVhdooLRH43GX9HXmVe$Ev$288zi9ywJ-AmF~{Cp_y_=i0Gy_MLyPhncnriP z9+$cS zdhU3~t|2RLI-S8?G;$wXllK81lahPY`$F{~U-$-K5EmrL zv7Si5m#=_yt&V&BIN@sEse^Q_X-^WfB(&`*ZSa~oN_ zm1w;_Tbue04tmV-d51Vav<+U6S&MNHvD)tKTsPVi2Df+3i3Clah5h-wgC>O=)<_w7 zebyJ7--(29Ka&+*yL*tpkVq1zHMWS!TueLnr+`&ESi}lGy`BakY2yHsya1@Qw&A^? z%@J>tmpB)XYY{Y%s8fDTGuH|a0AH0v7W9JHtDvx$6R07*)s@%cSwUoTdwnylq<#e< z9*@|1-MZ01Y!0zQ=aeF`m{1&q*~?pHqs3t%y$eCdrRVv+neBsY=x--=15BdrW-LjK zYkQ7%3=4uFOFdlG#nwnRHu|20)7 z@8B~lpPcyeMX6SkC)mk9er4*f;}&bYDNmjz#w&KDR&Ia_q}Yl5(UppGkQUC|gP|++ zyzj42bA^e)u|Q3$$e@YPEAeS1X;=Iu4w3mt9ZpH=4q7{I0ZX8xxihW~%>^e9y;IgT9>Rz{|`e{?no(ky6)0&*)TLrG@#StI% zdBlL}0Wg7Sh2Ore1UqKT}%dpARU%RBB`qCMtMLhUBvHRe>J<6x*EmZ6{wMlgS2 zkl-nSxppKDxUCLEVscB|#7oE|{r}ZMGKmcj_0$%;GkfAoyK*kox=zc=fs8``k*;5U zFXo~Bef-wpTLMRkyY4NqBi@8dH!JXW==frx*bkxX)N6k)FvVOiYznYCkWgdCLKA`U zfHivATj6d9Yy({8fzr|W;EJ;a1)T>CYF+_wiKK5OpBfF2FzX|Nj)Sg0ymKD-Ce$ks z(byPLC6q|c;<-X63t_^#^QSMR7U{XiOoYIwJHMQjX|Wwqear#pZ_B1NlfV|$3syXD zzY$xWTlMC)EZvb`m2?+&=nFpW#1!7TKeaf9F)_4t$kO46u}1&x+_a&mJ!>9Fac|Gj zuey?SI7Xq=3|(`srO88Z5~r%i8xC^zx4+?tQ@ocO-Jg-P;&|riRIRSPen)b8 z7mYomGxX5nrFzySIZ3c^?W1{(5bn$w=G^);)}OuhQ1u%yGIwiB>Zo|K9Fo!N7l2`f z%>#|I9n-E}-pfAbTzh%?;JMMO2)K10*apw*oUm<#u6Zw@@wErXVSH%p;23I91tHe2 zVvcv--ChT#A8OaNaqon|R3aofB&T92RWqAO91fCx7=Yx0qpp^=r3KpM=Wi#agxKP1 zXkgJ#4Q`uI?xn}Fl;>D>t@>4wf-c8}kIQM9Y9hTbAcSX##fxyXhYZ`|?}#}*crRHL zPc2qI81!vM+P7NuP0yKiUXqnIe=yL5<)~>zf-&vP3V;NwA?d;!lIBpgE+$-+`nKUQ zZNP`1q(>QID`~xXgZ2>hT6vG0vKorM%2~%DsL`B30=I-9G!(TaEsVs}#qTlxy-QpA z4J|>G1fchVLR)8>T0>cz~N4RxP6@5mP?VCIhZ7uaSl&7FW2kXOerVK1rj z;*cy7cudNL1?nzpxa z9MwQ_l)_GTM^~RyYRURkba%1PEY0&APfj<1Cx2}5tm)7P$6v(*1jZA=lOZ$+Qyomp zTK}7gYG{4SJ;neC*T%pgjADVN$*pln>9m!g)~ke<$HwUr-z^#dCH)^aZm9(e``tH* z>{})XVXFVFrHPzTH$`W3&bwqW$u|11+pbQ+s*>ox<^r*=LShyIayqkrdM1#S?T(!f z&TO~y_FB?Bg5%R{lb9XbCI!Nia85J){0N~xV~x&cr?AJ9dK2WLLUn-*0!fVyoN#*(h6n?b()mdnm9np5q9IF~eN9izbfENC%Nvqb;ECu|E*DBBGO7m`f=?YEDT5vOS6W;X8*`2J;( zU3^Vsf7K>1DgWFC#-wQH#1HtMe&5`>rJi7{4~r*p-m)JZDP>%DVa)N-Z&$;eW_SZ( zQe;_nCGdnu@|zs&593D&)&N4pfrtNDOz$XNJMxTVi85*|?9c~nJ^^epXUdovP`z8< zWfhWO-O7H=?gH^T$+}q_&m@@Z7()oeWEzr0oh0;_WA`dyIuQ<{G$EbM$>6?wU!esk zm7GX7TaaKS-up^wF&rz*-06R7b?3}eEsCtHJlKqwHt=+lGWW_;!19SQgFaY1h0s2) zN=vdKcHrp}^CZBbb}&h!n{o?2AsJ%N9QB*KBPN7I9g-LC+@QSO>S9R;d|Eg^1Q4Z+ z5T@4>IyUSvsozAhMb^W!N)F`)Z!4@(WQYQfIN(aiO(q68=RGbkXwc|$S=7$Tx|i?` z>}}rT7BY=#8Y_@V&;4S#cwor3Q6z15=!Z|N2R1oo)|%J^mAU`d7w{Zw2xu{9@R07a zNv+VG_urE&aL1f4j@~xh!1tUHchH9h;Dhc=UTy9iJx=f=66N*atjP5%4GoL=ZbEZZ z&n_)ZUjlweWIww@s;L{!O60^RLEcS1w;4#gXU^DNeNG(s`st=p!H&rC2UgIkAfk@A zw3R(7`eE7=3jBN&^Yexzabk8mXaiXKYJuV;ojb7o>ds*&)iy&JBqVGH5_aKUGU7vS zhbgf|;g|A^5*cOZXewebsUKZV7TTd-9Gi;3^rerRzYL5CpQLfO?CJQH24%;ca{jn< zovAqQqb(~s$L-xb-HpvT=A89(LchIxI{&yei)5huKCh=v#K76lu1tI};jB%AfvU-q zQVWQpT+$(bqSx)7{9#n@d(W-*Q=hlRloGZXOtm`6HcJ!Q*a(dJEXK&h~AUM9S zCLlQZ(xvtxqB=mxuNgvso-^t<^aY>smpJsu`|;}kbkS;k$$}0&$GcRmjlSlNX-%KZ zAbpFN=GZ~~)35MO(-e>S*TOO1&=V3x z_1@k}K5K%*&|&ZL37X-p_rR_|NCG}=AKNaMKtxRz(3Y`eku&K1Eg;8?|4OpRFWMlE zusFW`{_v>e27}jsOD1)Ao)V)jeuEbG+38O!fF(YkaK@&gjC+g>gKoJvg^~LYE4NT! z$oXxI0#N})f&lXwY~qRQ_&1suKVHO(-1>bF0SAA8^Z{QhACdd%yD(>ldL(3f2a zYJ*=0gS*Xe@H4eZ;CR2&56tiibBhEc96Rudg@p0|oq5HKFu<7seU9pR$9yXmp$~ub z1itOisaIG8raocLPW5b2zZya>khCYO>={ zG>&j`btDEIn-|rOd@+@R1zb;&od4ee-ag=#9))4eGcjW1cVd<^rJ0D??1jN0xlY_ZdLY>@U}SH~Sga-JcOgAqPGv)Nm};lY_JT1l29trcTVSp?Dy z?n`EAd?f)hF(hY)kPB;c$5*540VX_XtYAwUJr;9(bts(J6h8n?Lk4bx{Fn$YAXzya zK@5kqVHYUwq?oZ(H4&l{)21}qPO4<*MO|7sbWX+gStDG;-ZIjAS>4sOn@6+$gaJ~u z1|%ux*|#qBwfOuLv%^;VxDS3nTx~Iu@LS=~*L%a^AOgZJrxv5|-D^5)#K|{=J3p2Pu^M8?KZ@!d?Nri!fjAbb^T%jfAXjq?Y^?5M` za)2PvstHm?%C9>f-Ye9lZFO?N=CG;hE!*m`FzxN1v3G#@IrNZb=oi*%jFitvB8)>W zO6Vu#k**v|hyZz#-bcJw+O(|2q&KRhp|+ckd^I{jx0{BG_4!c4L4S@>0n+-XQwdl7^ZDU zVS;jq#T-+AO(8MLGs2NFz=VciydFxBuzJ(hB6y(`QXk?tin<()t;)Aj!KMW{>ar*V zR=$PUk-EiQ>?(1UDwp?h2>tNYBlg4b+snk(i7*j55~c+H()&Fm@Bx0vKJ*Yrp(sZ> zbTz{x-)@SKF|9nm4pw%YsiVFpr@3{m^xTEHWHmeNO!XU?ewi#Oir2Nl z=gzwm^ihl(4Q7taK6v>$H2}%z%Fd~NQ+7Tw3M9)37)>5u0O1vgIx>iyctiC9wuGwQ zH4w#F1q!#u5oxACRSRTv_HXUJh1e?@EygyCa69y;Acy0C9#MP%I~a-ZMVdW-K8Vl=WkQ$~n+D}_X|IIs0JJXVTz#Zz?1+;1 zLIHQAuH+nc1*CN2<6_!xt2wSCw1S>s zxUPJ+}&EKRv?A@wa$dgjIJS@Iz{+U=yhQjNY1YGnK^80WdM`jTaaI2y7v`2gL@_ zuYn-WFbF!(qpcOb7xJ)!_o8joa?x4#1YPz%~3k4cSATKXjZN{o?e^~*%977<0VS~ut z%=rruP=$CZ?Yr=Dm!8u)muCqrZDSvpkz}-+8X@NRqhGFE?DS-l@)`)vYz|&mIi>+& z9WbSk5CO*>T)3Uv-(A(IZ}SLljF$q7cb%CESLi%@yoO?s!{Mr(XU_M{npZQ~?J8r5 zS6H&x;+BNN`n<~#JB(mSve4}C)U~d}$IkVZCN0=9>fh(zHH;dsH0I$smQ z5RzdEzIyRZfGloFK=EKB`~K*yMmsTBUIOA{G%p1m00P3>U|^ada8@P)n1*Dy)<{G> z=>aRo2VBuIx?>f(-%gV9rK? z6a)(GVFh^7oU%IKMB>TMLNXvrLOgz^O^BJB&~10*D@ZO+n)?VjcBnF{?wB$q=6obZ z8+)eQMiPJ3dBJPz+R4RihL?y@=o!#s-VftQPmytC9sX;@e=DcaIW{9~bK0plK z1{3xARbbz=bli9*T`sWQqt-CN2r;r`SH67!u$68PxQhVNh!H3;udvF|9r6=!W|~O2 zXVhKGANIQP1-KBFQ@?^SKuWz5O|41e6>vYn?@a^XxiHL?_09B>fXGe zOC|^024a+n%hY*|qm5$Mp@m{wFmfFtGFOOAP_L$^+*6GyQ+Qz#3*;;07F9~4M>q8}}2evz?6g4rCi5#*1@G99b@&5km(`S?yF1X>{S7ho?Z0cQ)1 zDMm^6@h}N7M~b>o(^1$^Fdxy*0__7W6y4lJNFeb`tdX7<%gQ*w5-|WC#+k`D01TNR z-A!PBf;Q3YO$?duT7<1!;#$-bL*}~{^QFbMOAJL_CPB{NFP}y_$ZN# z22$SY_taYfY815<)B0=@h644BU^-?954j6Vfs_=I<_X}RAOQ@Z2ZNS!AU>*D;u^G} zq96-}2wsDhPly2Dm9HrvlSU}H<)!N;;n#)+NL9fA+wqKT8lt02@s~t5Ubm3HiDB=$ zSm~bH@*IR6lH7>d1wJEVhgc_sa8HQh*Xw+O9fy1f3%6Eej!MxI7K@ zy2nGw<=2vj*zwVO6d}V~sYqPF@YL5MycR$Pk2M8YK|sKUXn*Qhi(xRDuO!?VQClD= z10fFdAI|Zx-BD;kjKjEGkn8ZrPEKvVT%1{>AL-r6$>uKvCAy%HI_EqrqlXdR(b!zu z3=`n|=PANJNO6f2gmuTD-|rE|HwK2Y@=gdC1WS%#tM?OfQPzh<2_=1XXU?1ia8+7Xl{JdIqU`jL|QXzny| z(u4VF>^N%+mKjED4CxIN<`UC>g897Xkc4K)%q#q)I)^rM>=oN@N)v%sU!^4o(pFbZppsz zpZ%yAzrdMuYaOD%es|gffewB2@P8(<2fiS@K6$BQ5;;F9ir!0(v~^>o&rCl&zi!J> zn@hH|Y@X!aI@}x~?}VSy2<(nfBMgq`r;pG%{Lx+g@BMRe!0wL=x0nAqiGRrG?6L)d=IQ-9ic*2s|{rF9fuKPu-RVaYM!{%Gks$N3~FRqS`bl zuSaa&n7#yxUOkoP$QHus5CM2@%up$Ov;E0Sau>goprn|@%4nd zO-^RI6?{O$2&pHj?{F{EYC=an(Pw(bCMAEVO&V_K)HI%cAqffMyXj3{ZJ&se}A|9fnpfRATW{MF6 z2Qw3;70HYwD2G)lBWQ5UIqsg`w~SKeq>EYc0RchGHJ*p+L*R%jwFuh`5?Vb z2=R7Ax|ESSwFV(>mx%xX_7pldZr##`^={m1#UMHTD;dn4Q}0?uK-T-sI*VfC9-YAA zGyu>Q6M~LKhFODWdM6`lU`e^BTx2#|)}>}J1Gy-U*K(x3umHe>9mFsS_S1@>tAAWu zkXnOS0Fbp;ZuSQ-jVu0T`z7qdPxd?nT9}vId^}Nw| zytzZ)Q@w+Kh8eaWC`1&pLl{4g(DV6cm!A8*flb6ViIfe}M*)8!xQQJAPod;pxh!)Z zVp`?#;97tfxo?aD$bFO;YHl~P9-MD!^02)?jwBccPysepbJW5fxC+jXL$v$jBm-^K zSY50KIJ&d8kr}^*pQ$w#Vp6o+6YDWUkBlc4!E%y|NgPWv?%{Tmp)#A36E*!5IpJ@} zInkAK^fzhVia13L7Z*Z$l`+2j*)3ugoi7|Cf{I~P#tm(3-Jz3c#sh=eI%jLR7FeY_ zTec>FB3;hWLlJ9(K&oO`d?(*2edH{9N?8->TL_wtlQV(xxRm{p)8D(aT~i=_N`V#H zAMz{LM&k^@p(9>m2vYtRgmk(Fw_{xGKzuD?Q;xh%5f^rs4efUw+|r5ueX$cXaT$|D z22cv~8-Bw5J)H4H8>b|4zWG};YB}Q(Q+Vrrn-aeP#lW+3?YtwZyE+dyoxqsR@CPFU#M$&W0Hup0hcC!Ijx2vF>LO| z6n--Ju`L#{>GN1Q6PvAPZ&|a|TFr4EJeOvTk0xl6hhU+JF;9QPa8Azb=0IN4y8~J6 ziRI;|Iodtx8BP{C|9{|QQCe%aQ>C?zuui!k-8kkJrBtdK$=#5JTUgBi>XG_G=);sX z=D6(dNW@02e|&|}fC?HQ6O;%H^Ch|Ix;WjsAncVEW|F7l?%_J#9k51-0>$k4!cK~$(wtvJY&k>uRq1g@ zj(CoYJ3?M4Z8-;g44eMfRGWz0hB&63<%#dpVjjU-V$;95KGx#1rc`bN|H|X{)tg+Al`PiH6Pu1&8Tf>$0=OD z+XE0rh1{tRS+)VDa+37rUP4%S`d{E7hY#Ap1f!%RAV@B`X%+8!@NE2M0+GY{NM_9} zr5j2_C%}<#&a@n_82|fz-Gi|vetU>D{|+5r_XD0NOmpB!6>lZwO^S|XB@n>1$hz~aK%Jv?^HiJk7$W*J38p+$n4A+dMBpI2cegFies z9b1M(=5@msN-~@L_UHSgJcSEvd16PNwYq!Qk)%9Cc(9>XD4JgT_N2_@L|^mACsk}W zl)KEeMnohKi^W!55um9GH5TR-79CxsR5)hj97L1_kSTcZ_XGFMk69yUvqI7|$sFHe zN|eA>97^{M+p>@yyzT6mZ*eMT!fW)-pTlOto+I%|XjEZRo)^Z4d85^&% ziIgOQ$aOHr)iBi1y@Hz(jY1)b0BHYnxAB5NM~(L* z<#j5>PsUKJiYE~>0BT|iB#<|_w1Q0r*_M@Ri<6XrA%%zm>M1jiAvOK*c~SY^nS#os z7abJAszk%A=Nc48VLT9MR7Pkt3}PLl(dc`R$$&;C^AY%?PV+vw&*?rT_JqBM+R951 zt1(sx#{+V#mqMh4w+{L;Y;i`aU3a|Knw-ix5XEG(5&69U#v{LA(+*5NKveCPtG87k zy39?#)01Qdg!Bw^NgEg?oXoty96d=+Xr$Eqb7)4e9FV85Yc&P!S7qvw&+1k`Oy5ozbn2WjzR*4lju=*h5r>rkJ zz>FR%Ht9Z%(WmA~sKGdIAk=i;Ao7s1s)2jd6g*9?#!n8RY=4@nQ*4&si#V5Wv+*|V zj1HU6m6y#1O2jp5M_-jBqpfcMwgw!W!-gSY<5k&z()m@G`mj6YC}gGlHrrz~1vdaV zhM5En1rb3~k5vdn)v3Yp{LFSFu zgtK%_9Ge=)Jn%bslOdFd{4aMD;1HbCSszUTH|1_GrBsS8$JTRc+Nb~Ax_!_EMFpvL z%BC%pLbJdzE_nj$9ZA>9A*|e~faUWwK#e%XR?!>CE{`cw(ExGA2yax#pRlL;+q{wn z?T|D`O-*6`5Av~t$E*VCI{!Z-vs0gr#32XfrV*cV#luL)MxnP`Mlx>gtc5NP#S(Z< zdiFiDGteZ)OeGX6x&#$A<~-s(@}CQCW7jp!f+iXHnCWKV(3z=v-mMjqPr^p}r-#`H zFt~ge&jgz1@xO|m=GMzoj>xoJvZy)C4F5nlGJh(TNxjjJH4z6+hiV9XZ>V$Pk@g*Myg zlwsBa&o5_C4}R-zxj^S@WD3%q=a;Jm%JtZz1FhBBc_F8}V{OEkNlVxAbXu6^9RFh% z7R%oGf*_D$nGnFumE~Qul2*pUf=yvpsyzIVoBy^dkhrDJu~D_z#vhotq7XE8Koh-+z5nQ&9Q@0dXVGgFB1wqNHVM) z6dH|~6j1_0bKXJ%2c849q1ts3`NBbUpYjXIJ_yZzz^T^>3bhUAB=OY)#hY3osQ1gt zrq9AOIq5xjqR;#nqDi-4AE2eYnt{Hnc_fxbh0Rhgf3Jji)tFXAx7Z3(QhbCx0t|LV zKSGcr#BBz=sN@g01oNwUYW2cgLz%paz`|o;CgydEZMQ^NjD0{ixufFWKlyA%T9H1{~CqAU~gr3_9)v-e4f}8WY74Tk)3TZVlUHQlETrFwv_TMn5gDaxA5WXrMv)jumO1B5LGAgx zjDOj}KN8S?ifVlv-AO^-FrE{15jJfWqJ+mcrj37@p#{B#glN*+H~y3KA{|!*qKG#v z@j|@H`sMfnDQwe(s1R71j^%j&0jXm}jd`e4Fz~bA+3#nKs~B|w9@wYG<@j`}UE=~* zxlog0H#C&HUr8#ZOFMh6oV=jS^vVITEqLX1qz@2L8Mi#M`jsJ!= z>0bhx`9=3BX!3}1C}PR#JS#;E)byV2N|>;WfY>m%ADwe=L6nxzf4~qmDw$lLxrkLV zAl$A#gm5W*Djx^pLT_8VDvfxk6GpNJ>1r#JP_?+m3Y!}T7yp@*GhhGC>}}n(vzVjx zJ3NwIcmO?;mAp*qb016w3!MlD3$2Q3eURtFrk>Gr%HyL12xw^f8$_AYG_;At4WXei z&CZ~nNkEuKcjE3Z>FAEVti-bT{|866^7lKFE}|1Mg2uUj5j0gd^d3ROWdf8SW*zlj z454HCA+7oU8$#2pR|vA$`XnqX%6smrmVOf)3HVaSwEvMAuw8q^&%W{2-P!eKpY(^gsc}+Wd#`q zu>K#hOGr8lh7?tpbK@8`GL?x46^h3yz(2}^sp_*jTh142rbD{WyE+2bG-n`CjFJ`4 z&KU^O$sES~LDXns=CmOb!=Vo!00nQwgP|2+12s&kOdutOAdLYwyjCh$j$mVwp;WN} z$MLS7lHh*pA$oS}3u)drIW5RWG#OKjO_5IzGyBmZCI+!93#92B^{|Dcl<8&*@zCD5 zWo~=xb+Zw0Z7Z@}d7Se40*mZn9#q>UJ;+1Lx*((Zf~^)rcDXDUph<pwMYx6LQ3bnRs zaIfXqs}fRe0F-sGfJ-5lE0G(=zv*EP?W8d}bXw}poGb+b)FOS9q$1rXwKgN**ee%f&+yTf@{G}DDMin&* zqg%7HQPMc~kBj9kSy>N+Kw|P9rf4?4g~T8XVZDCAzs?lFY>v-Q!BYVD4-HJWU|`r@ zwLd*=4vhK2Khac7dS#ck_%c#lzZ@rwiOxR^1}`$(LWp$GIC~+8w6ujq@oUudIXc2v zMKM@0?e>kV0raHrKb{QVzL7{>3I@Tahr!RPt(%_;Gf9^Sv>$;P#1P~lpm50J)l*?e zf$0RD>aN=eI^v&G2U)>RSks8w41Fq?4&%neL6@AxJIyf*<4)a76(kOR{Rzvro^$}(x0Sv zW4?LIqIUEX0G_bh-ocU2NQ zoY@?2Ye2;Ks_+W5pNOKwhOnC;&~L~H76fGWGB_$3?KqW!9^7^Ei@|NH?PX5G;p&|y zb2g>Kv?QwLS8&yQ@?yMjfV;dSHgNDz`K7eOSdQKh2avEq11`exK=o!s+f)K9)Z8H4 zj%-|1%{NVDhHTKGYkN{WpEkwANqUMohh4B5?4QcQ!aEAJ%alneg0R=KMZFukXBvY> z9`M;b6%OhP!+8INLv^2^l!~G_6JkW~BaZ^jT#hqsYdxeAB?`8+urvozkPTu}hMDBn z*>oB-RAADMffgoVd)qEi)EA~$++rud^tlHOR!3Zx_KG=opFZ6H@)EYjH0K-SLnvn_ z34SGiD_xKuVcmWAcWHJvdYHoQ2qV%_RsHh(RjKL8k}}=7ZZ7DBdOKbfZ4~4%=k4V} z)4OY-2)`71tSJkVv_%{IW67L?WQ`vQz->*?g*Onph3t}nr2@k~;2{%$RQ3xqC z6j~m_ksk&6Wg@%3c{oiX#}3q;;)7>u+@nhV=aZ3!QDzQ36IUE%Y629~UY|}mWxV|$up?3@wfc@23!2C|Di9Zud}~zn0=ij&zG;=Myz+tl5?zqD?Yy_ z(KlSe{F&^5S>T@E?&^a7cf%=&>Iifs@fJ@zwD&3;SpT<8ViOXQm@=B-RJJ_YK3S^ zS5tFPVF2Vtl=c(`7%OR$Kt-p!S6;l|9xY_?r#n(BVAmgzE|1odcXIyob3DjvHv{_9 z?Fwf4NP_b8x;giL`K@Iv;4R52fE--Nv`1-W27ZBU>DgOF6>ttf5}XcKjHKZGAdfsW zlU9(_At=H4+Few6F>K)9WJ#QR53$9IPz-(MJaKv%s$+R1;9t87I~7ifDNyUCUvjrS zDh|bCOHjwO)#u7-GF~DtPQ`$c5R_VoJh!vB#w=#tnJXL=RQ8@+*#;sJ!^mo7Dh2JZ zXt@~MssoCu4|Sw+^4O_0UKS1z4+d3hV4uHI$sZ6c6#zyt_@X|k_IcYP)cmI^B%pni z-Yeh-hdZ=pWO0(*218k5wrT|XN3s*`ASa2Yj*20#`XCajrPSbM^ zycR-?j>oB2pgE@KRu|L$xDkf{G7*|O;b>C57)6jRB+5;zMvRQ7X|-5Sz&5Izisl_!xn>42tl=GLOk2I|r%%s5WI8%eu2(uIa>^NzuTS zy)u&}J~WpL1dP+X5s!gtBS;jnx;(;@t+>b%6zSuGqMH9`fAP!;h7d!lJ#@xtUY}oJ zB6ym_rgV@L?a+6D!KDgFban_zP|`u*pl_2X1C0i#%$1ATjUkiCaTK?schqk?&?xqj z%h8x^A{yB)JgOd@lBE2egzP$I#3?|wk>5005MklPlJ|c14Vm#W$*?RjOS-yWGAt)o zLyjaH4TRTpSzQqL{Hwl#C|X>ubXb*_%EZ-OQ4G}=l(e)2G9rt=O0o|>G(OSqwaKvk zOxj7$l0=UHO&I85tzk*m6o~sgzQ-mI_uH@pbR7vLeg13;#Hea~Luq1n)teZC{}N*< zl-W9yj;l71LPIKyFAQ!-1ge>IxP7=HT)Ot@8#7cbIYwJ6fXBIRJV{`@e?kmXD54S% zL@b{3-Sxtq)kETR?jB{9LrAKGY;xSSFbs8R(>}AAB=CHx6i6q2$#Ri76q(zhMs?1u zZHB8IW>(MurIRafA!4Ex@(XE+XbDkTvrVhu0XSHhvr>duOySYiaF<1VhCm|iHt+_ejAFW_AbT1sULY?41r1Dd}d4Pnb&WvR|u zfY?!Uc`zA4J*WQ=+Fef}{$%T5gu%Iop^aNw>N$%%wL~-5?iNo9o`otF5DZrsRR(M< zm@p`)$C&F~4WTV!ETXVZBru4e1~U??8n2pC=`M+B&Gjv!(kL`}g!+xRL6jeD0FtBO zGKw=o$Kest`IyZVK>RXe?jkimb0o)Gd##a#{fOMEY3wy5yFg+@xKT@7vJbhKO$KS~7Vfcfv1*n{An41BESAqJ9N)doEN)DNnmqgc?Rys^DIG9$bpC{IW zii)sb5|^XxqGC4SEVMLiQwtEX?d}>1m;^#ky#(G}b6T>mY0R;`pD?TPVYZdFGlzsc zAcmZZM$ymE?w6Uxkf=q3+)nCh7jxF^Hj6BPnU`QvqT8KG*r`4SgARwITftQ|l8G{c zhYGBbWnYNjVV|rM!!i&NGdA-%A81yEOb{UqV5}DVg|dKzN+DQ!AWdNa)Wh^5(Na3I zAT9-(Olj&kSqntF4$ZNr@(H@wpUV=Q5&5x~BwvzxDKhI@dyFmqM*P~Bo zs)|;1pypk>T3=)gia!G#r5+VS=@*0fJ`hEY?z+Xf!3xCRp%CHg8M`- zKH47p5i)bm#qZ{Bf#mWivJ5?}j+9}-c1L=jORx&ASwqdY_Tz8aTfIlzu%l^bE$m0= z0sZ6p=+S0@Jt2qLY@S|=gXH+lKYMGZC(VdZJ6HLFQ0-KDEb}A5iNb=Yk!6ND2vIs@ zddoeEmV%L;^Tg>o&46Y?;3WlFlx;cax9`HQfGn1ibPWN`|CUSp-)yv}7fkxvUIv|p zagVXWw$~Nv!;9{7Qh28SA$P-;`k)x0(`RUP8oXx;`|Y|^f00WJTa}hgALER z^RltPO;K4XLw7(Cr3+&?q+yxWsLbHzG-Hl+pYQifQI7jsA|Fh}%$j4QLXl+2DxOl7 z&7wrzLk6gw(74}|Y>DM{?-Iz7a#oYTwF`czNg%f|0YkDi2}Id*UAy{O7B4e)2&5N_ z6Fv|f0`(*IyFs9I$^XCC3~-bV*&k2=AUhHVx{Rp)MfIU3k-=8&qif>-08sR)pUv)0 zYi7Rx2Z5$4iiCtxA{8?){Mb6qBera}k&14&5*<4I{PF)g=+Lzvq_r_5eUoO}Yjel- zS$M))#(&=3apRX9MOPE4aZCx_ZV98475MR6)_Oo&J?ga$LU z>ITKAe$f3{78Q@`6Y>_>Z&W&GoclGNaK%uQLy zt48NwWoig{!X;&JRiCnw+BKej6OYb$YCVTO-EANGi2E)QG_aR(k6*VC{^nZUS@L_b zg4udBB1Sy_!W==JXHh^LUdqs7D&O*twi`glHkOr;% zSF&utEF3|rkq)stjyvjG_46(D6jGEH*8`yR`TFNp5YW(xvpEQ8OGAcR=}a8#sg{*g ztcmI-bLKZ`7p<_ri2_m36qUk~1g|y&oSyP0*5AGlFfiqPwyxQ0X16Zu)W z0;VVHd6)erIX#xM_QKRG2+<7slej>POYeKysbk)co;#oqB9Z%QEx-M!K@e$EynC~+9wd0hxEap?NKAq=&svn zbZxKtjYdE8uPE&0{JN4};C!b5FGz2ZDcxPNF{b3@rojTeF>|h5X7q7o0O6lp&f9=2tq1(+CmU@P!o9OzI-f@#}GW%nS$V_zC)SUAIRjEXXri)32pb~wl0t_H#dzIZ4HWE9{0-B7+&1TWEeK7u6!LY&V+_x zL!6X_?9Q)HkBYdh^?Jja6ffC2QJGhtJN5SDq_h=he!@aI+8B-uLaCkEFsLZ)9i8?5 zi`_~YGLqhkYGfRf;%L$3Q;cv~6t6RLZa#r|-jeZ#fx!$=>sH$ji0Nmu8`ckk$9} zptoO6Dt*QqB0ZZLrzD2Q7b^W^rb@j~-A?Zy^3#&MX2GS8lK)JCOe}&=2-d5eK*T= ztZy*Y!u{7?bE`1`$0q6}=X%dCfAWpwGEK`xUhUT9#)qE>=kkIkAz0 zc)EAijA=i=T&V9ktA^A905Dmin!K>}z?cc6Jz3>ps1=4K`Eq4mB2THbFxlF&>}Pi} zi4Fgwt;rlqkH-qS!2@;U&KaeCqw==kqq0+zYE4GL#4K`aznIKt8w064dm?NGOM`Ta z-1a!OouUR@y7tCXOOchOIKS1)tjn<&CRLPsx~fMzGq!_zAbkkLkX_739THK2-6fM= zo0!S{fd?w4wa*j&C##zoi8qM$Y(X=%3~kJ`GdQfU>dfBTnB~k}RMV(d20V^A`|U(W zGj>|a>@DukraGEQYb=c6bhyaTM)(9bo5+@s$3RYcS+{0pvF!eDv71SCGrM~aMu|DD zR!vOUG|HfZ^o6zcu&GM}yd0mSzKBTET++IkQGf#~51Ww;HeAlwVkl#r+4?4X{~$W& z!jB^llhAvq%@KLzQRO?*%n_s1_o&_GW|A3ws8TRq5)F0O;9VhC&Pwv70Du|03I(WO z5|x}~CzB|xsNLMx10#D{Bc1vNL|yNrl})LYN*2%P)!FD zRiDS9!(8F^3LB;D$`o~bQ54xI*fEoKZk9+g+;K7`RHIpDwm=tKKc4!A|58UDbmghX ze+{Cog}pP6`3hW;_$u0SP-7AEqUvn(pLORcGG-PTvx7mS^G58(eZoaozIDCq!eL2Q+M1yo<69~-69o6&-HAlFlq#Y!Q@{? zQ@uWCE0tWz+50_xMxx1yr)N2*>`gf9zKv4kH96>qAF@@&1nP%*AEk8K5!rc}Y!ss6 z1IJuzm4BM=;l5Y0)g=l|aIle862n%|fP42r@w&w};s&Lq$W@xwphjyNpU~b~5G^B!F|LV%=AT6|_Dg3ZyNC`JWCURzL{?KVn+? zfZ>T`AAr*6z12wVg0gi|qeSV1bYw^7TKvS3)m5B9Ar#|6^^0 z%0ZJSsrce|*vfNsR!OFV#89`4Uuz7+r2PAvfCP{UXKfmS%}tE<)bM5`Pef+Y(&tEh z5}{ty$q}}-TUMl+1<^(0l}=GijVVlS{xfM5Cg;`P?gxcA=*FKVshe(i0EeSdk=6c) zt7GpCju}#Cj1@c|D(phX5{!TjWA3u|QfnH!EDivJ4S@g!EeH>hNQore4lz-1NaS9v zX+)(@z6KNST_N*Qs*w^AK*$RjhH8Kg-EkiyHdTA%!-1*4MddHtl*=GULdg4 zrsZ4?9lMaBtLHv;I}=~Tlj$Gvs4c|1W=?rL@nz$)l-8OUd7*GjvrW=@+9)%Bhk6y# zxs$0q6u)Yth8!kq=Ot7)3YH>7t$G4p#0jcEOW0%qJ83DK`T~szs~W;{ZLzVYRRg}j zSyO~zT}E`p94{Or;?K?cyfUvCd6SMyhpXT&aXKhHQbwb3B4jMf zIi4k{tFkOG+S&}NloaT&X1RHSRYg_u`X&}z1_eSzGaUcpjP39Ym4|t@vH&)*J z7&-mKA#@kYTrB|vk{SQZ=pk@SM26-gqL`44pceA_L2fyH5#ggD`W0DTWL!nAR}k&T zVPq8%@;!1CK@;V%?cwCI31m1^89iJa+;5`gzn4Z}PQXgtlAblHPal8D8eX=1ZU2*Xu)U}}Iv9RN=po~UOgD{rE9pq_J zh(wOse%sZP$UF1Y`TV{J;Kx-xWY1pqx2%AdA>c(}J=wk!fkr-_HEO;@n$;|k3FoVa zgX(iY5h_nhFw~A{{Q%x5vlI)Fd1w}uF;G#atN&S_6h%=KhuSfrLCH&DC^x);BGrMS z^d$&HtU19C`VM)fAR;1_hFV!;?=X8h7q~`FD(+y!NK(1+``@2F zE}BTZIy^CM^It$X*x8YId(&m2%D}FbixRneQ4g;3+2=NDS&pA(K^LR?1A0zrS>n6B zduHkVqle#Q{){2@vDd%K4ZNX)gnbt%*O_MHj_na265xZUNs&czC!D@XLFSxY4D)Uvb;EL*so+JOb z1%n1>UT{fy1qRQ!V7IFpm1cUrIVu)hQCXhpA}_eK)a99s#@!Qj1_7K}C?a9OzvWx9GJ(>Nw%l3HZ7--7krC{T*z;a!WTJZ*3hP5z|gKXZUL!G!ED$L`U52iqjDm_Zn_q-KFFi4f5hC;nZm z1A+$aY=PX@l0vT40G@n~G`a`@2jVIu1Q;^p`yrD!K6@wyUMh_xVD>_EL2XRrqY0T1 zi>eW231pc$)V`C2&LBXGWa7b{QpQCRVxz}rHjg0~U>adc=68G`1yxfz4(m##)#G1)l9@vFI{r9G8TV-B}+Y-ysPg-CVJWJgdf(l$z@a{R z=TEv_U7vO3;9`rS+KILh8_}L3YwPL_No-RDn|PBEBh-GAI8OtM?CX8AH`$VqY^Zt=i{|X+b|0#B#Ko78WyUL+Njo3P{$3+Hhb#X;c z82kWa`@U475FsNblvcYSyZ0QHNiZ%}R#s$K2~*%oS1D*mFS9Lk6_;1{9CrU^OL&kO z5uizwRaf`iFrIEn6;QXhSB`~woB^5%5`Xy7jvtDm1pz60# z`8CRD@0W}>;G{(q$dMR!Y?dgL#8MSIGCJ(dwPXgUqaJq0N@e48tYqKTyGP%08OQN~I|g zd$~$U2)^aB58?Tt-{v{C`-O?sE$2rQ0gk){n zYraU>>u-eRymRzi2`_ANoJt49VbQiq`@kvCcC235#b>25Voo zcNs~-46~Lr*N|o_u=HI4(=!LAT-_=hYynbd2F`nG0Vj)bDGzuXA3h6PE|1LM*PZO* z$9C+P#Pv0xZPV%;56@+Nk#IO@$AcsuhhLBm7${sFzu2il(Zjla6mO?fT|4 zPzs+MoK!ez58hRav)D*_W;d9FF2kK-E>TpsMz_~@yUzxA$dj?AQoz+`a34E!P=LxR zH>9fMg#rEiDr|Rm(g4tr2ayl0RJH*Dt_1mSZL)$%+7?;6J_Ll40y|tN&H_tWBIm*^ zp&p&N7cmg8!g-5EsG;)`-+ddpw-hKurHi3jpLVA=mi@1pQtS5n;K?AGCXGgPs&<~q z#rcKF?!GV=w!|$|_!XWyaWdIklIQ~q9GoSN`?jM}8Ls1D?4=6`i$5+(lt;|vhyQN4 zVlK!j_e9}xm9k;YE32Us$DaKR>`2mCN*Hk!}S;@ zE^ri;92pATORmu~mm9}E=aPb#Iz#{ zeoPTHx?hz&vlXeLb4WvS0X1Y*d4I5m8ghnD$S@Ec9iAJNLR)(J4_8qWh2KyT>y@9= z5~+5Y9D?eq#kA~!(gwKCB5GXrSGi2h!fA3KvgSBj97KU&DeYN7txCr#^;D z50l^&CQx7a@8NhqLgU;va}{C14P&|ABnF1Uo`gw-WOSakqfWzt^|yE zcs`@6gmyr}hv=ks%%0K`>_nG#%r3DLRI8{|OkNgQq4>cdigUM+#z1ixb6vn=IS2{_ zQ@5I(MjfIaP;Z#pP*mWMAYcfJ%pr%`C>_BT>OvR+Rk#xpq!id7DKDdVsedTpa?nFu= zBNEyNuZ&akV9^vn-6_&sO50a=UI-*wM6m}~TF0@q&=cY|0YD3x}U-~iMEl1k}TaXh73+H9}|xqdoXc|;iF+O)!gYVwL<(?+2ANrLEbvS0JaNXUou#yXI;{9HtIr! zRqe7C&kEw@jys29DlLGoPq=DnazG7!9%w5lK)R<@Z3G&7v3^P9RRJ4h8}2&I{vXaf+37srde=r(OMb8!M8 zV}W^q0@cCMA& z9$M4V;H~q9uq~(&_vLh2FxnMd_w2JEF5Irb8;YY@0n*lFPY8@#qr_NJb#rf=4vgMM z&3c$DJxsbzISotXiJ9yM#Hi&!kr&aW{beMo1RFp#2sbDVx9N-H{2)GPoq&xy9>)!M zO2;151rVtd22WaMz=QGzV71KTPw}D5_v|i01{Brja?c@OW5hT)j=*{Zvvk}sGQJ~s++VR1FN8j7%B@9J)$Egck#tgLi+*?|@+RJsk4_HRPS>z=QoWU34bOou6 z+BvT6i+pNvxGRPp2{=4P4LT>xS%5p72R)C8c@?J|QR}X*suZ<8c+-}ZS`z`D5}L+x zJ{+(JufY~aFhc*}Vme$oS1c#2@q;RfXj{Nu2G;sTO>lyU86u(Q{QgSItnJbVOub+` z;3uAMkLCRSbv#c$n8DI&6^laD;{kCvE!6N~Y0yuGXI*>e4&>5RS60AEMRk_MR}41-ut_5G4*`-_1u>O z+ZTASG_Dp7Qgg(n^o=u~E-h2z&|<5K3t`(HQCnJEzP8j|Vqa)Q&xPjXzh*A9D`(9Y zH8?{sUzC=@j{)(;SQJFAE}ac;posED)te+~j5$BQR8dEuYM<*D)acImy|hFyG?|wX zb6z_<9BFGnLlzWw2je7(fH#AEAdsrRSx5v}0EQSqI^m?tl5nyDh9RuxGE4^2+$Ao( z-_NGa3+OpVy|8_*E0!})n;9gPvA_$wZt#I(06;n09-#*h znhD|{C{|mfC_XEQAVJ?sIJIWbtU?Vw6WNI%<)vDIuqXO`t9(Sv^}&Dsc+R3Ji-=Cv zESab0ovtgP0c;^}`Q2+lFr}-6KtW1IEa#0Qq@M_cWclD4Vc-%KqnOBhp!EY^+gpMN zx0_wNNY8maKxRJ$g&mEN)~Qpbw4jHS_Z$~cx!Kh=xemQ9yq>l-uEr2mtR~V}jSwx1 zx>WtI#;!iLi874e+O_+FF)*SaV1hAV0@t-&+Z`B`4U|EIK@oIQ@z#&EYp++^UdC*q ze-JQ!pgXF~w0!xM0RAIU6Co)22W|sDiN;_I2qF?8Cgfrw#;CvNz25bj0kO&c*qgie zp67X=@8^Brr$U8}41`Zf$!bfud4)(FSb@r2|LjDPdO>l@=X=FM2(7BJa5qfmLjR!* zE`8g<5{*^v4Lo6c=g}%G=sB`h6A-bfXRm<>(BZS_VJSuaGdpA5wEq)|oG(F-cZ2QV|B0bk9Q+G$llYNwPk`8xu_(5^76SgfV6q`Rjb3+a zHN2-jycWCzfiFAlzfHvpnq+tT3|ymerp-)Nd1EKtGer%*%ZeFj zzozq!6+^gdD-UE~2C@>C#fzhcW#;h#U9ZoZ_xeqH!w|0cHhP!nOFawkCqb4K+}f#5 zef2RT!&F!L2nwcHH+XU^kGMV=@1yTCi%*7OMArMdF%QRdSc(nP8dHkYhbO_@Fp-F4 zhcNH-6Z@HC8DXu&Qt>PTn26fYyY|6UoPv0h7t#2Tg(JA~%Q>`cnTQ^7Igx^rx^+vy zZvkFyZtJX46BCr3K`_#J&YiPKRjAHg&a%EEHDRVj5`0cs7&bn_huQXJ!iZ^)^<6GK zK+U>X&8{?gm_G)MJbA}?(n}jRZXBu7L$MswsDp!pH~4}Jv$EN+vbtJj%VP1`*2iQ? z%&IrvQ-j#Z9~IN2iNsVq@d{Q6Jx^r?1Z|(ccm>>>G|pt19CF+Oz(jrSdMYiZX`1Q} zTRg4uhaI`?H~4Vlt;MnBsobEFi54C6w%{~pf&Pt$5=n){U(AbuD~?+M9W&0#eFKpM zMFeo1VeF_Ycn3^HobClk6r#g(1T6RbGm5?wgE=2y4wlzu6ZMF(Bwme?qd>C&b-3@{ zv1P>Q@C35x3SMB0VWp1Q@pOXOuiJJ(@B5YVZDrBQ>x9Th41^FP) z185zYAG{A2#;^L+?P)_54!4J7!1wltC6W%qUN`wNIxfots?9&9O!F`F(j`pjB5Al;-Jmlc%D?i$sl_3>O>z;De#q_Tf#B z?)mp#?&%lhR7`{_@5j-CrjgTNh{A^9BhVQM=;9#EeikPiKm;AuAPdK_?FO}o+Gl=x z03}#DfuOe%V;K?LP%{H>>LQ3pVxW!4*R|E zC&yiAuGzBVlUa+22kjSaZy!Ea^UL9L+!U@}+w@u1uX41Ffq2vrlCs(M>*Pta4JYN% zL6$ygFrF2(^;Z&0SC~1KdYYhbv%6Ij9(reO6W5IG?346|Gj5MIZ`GB@hqy+~%g%w~ zYZ*Lw`tNqzL7RPKKs{s~%*6$5*8YRT$E}0eAwj#%cXjt% z>!5@uXUgwCKWYxv;_HGo^@-Q-Y~tvuEczq-hx}Sg%NHMiX&sc}er?L3rQ$wwklyxd zP4E8Ln&PN475k&NeOmpR$v-?|9hBle&3US@cO9cM(VE^4XpU|6Qjhr{jrlb0uY<}o WMjc8~IYUwe#JtLJ7hklUq2GUMN@MN- literal 0 HcmV?d00001 diff --git a/doc/ratseries/paper/binsplit.ps b/doc/ratseries/paper/binsplit.ps new file mode 100644 index 0000000..8ae3dce --- /dev/null +++ b/doc/ratseries/paper/binsplit.ps @@ -0,0 +1,3030 @@ +%!PS-Adobe-2.0 +%%Creator: dvips(k) 5.86 Copyright 1999 Radical Eye Software +%%Title: binsplit.dvi +%%Pages: 8 +%%PageOrder: Ascend +%%BoundingBox: 0 0 596 842 +%%DocumentPaperSizes: a4 +%%EndComments +%DVIPSWebPage: (www.radicaleye.com) +%DVIPSCommandLine: dvips -D600 -o binsplit.ps binsplit.dvi +%DVIPSParameters: dpi=600, compressed +%DVIPSSource: TeX output 1999.09.07:0959 +%%BeginProcSet: texc.pro +%! +/TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S +N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 +mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 +0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ +landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize +mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ +matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round +exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ +statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] +N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin +/FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array +/BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 +array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N +df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A +definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get +}B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} +B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr +1 add N}if}B/id 0 N/rw 0 N/rc 0 N/gp 0 N/cp 0 N/G 0 N/CharBuilder{save 3 +1 roll S A/base get 2 index get S/BitMaps get S get/Cd X pop/ctr 0 N Cdx +0 Cx Cy Ch sub Cx Cw add Cy setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx +sub Cy .1 sub]/id Ci N/rw Cw 7 add 8 idiv string N/rc 0 N/gp 0 N/cp 0 N{ +rc 0 ne{rc 1 sub/rc X rw}{G}ifelse}imagemask restore}B/G{{id gp get/gp +gp 1 add N A 18 mod S 18 idiv pl S get exec}loop}B/adv{cp add/cp X}B +/chg{rw cp id gp 4 index getinterval putinterval A gp add/gp X adv}B/nd{ +/cp 0 N rw exit}B/lsh{rw cp 2 copy get A 0 eq{pop 1}{A 255 eq{pop 254}{ +A A add 255 and S 1 and or}ifelse}ifelse put 1 adv}B/rsh{rw cp 2 copy +get A 0 eq{pop 128}{A 255 eq{pop 127}{A 2 idiv S 128 and or}ifelse} +ifelse put 1 adv}B/clr{rw cp 2 index string putinterval adv}B/set{rw cp +fillstr 0 4 index getinterval putinterval adv}B/fillstr 18 string 0 1 17 +{2 copy 255 put pop}for N/pl[{adv 1 chg}{adv 1 chg nd}{1 add chg}{1 add +chg nd}{adv lsh}{adv lsh nd}{adv rsh}{adv rsh nd}{1 add adv}{/rc X nd}{ +1 add set}{1 add clr}{adv 2 chg}{adv 2 chg nd}{pop nd}]A{bind pop} +forall N/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn +/BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put +}if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ +bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A +mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ +SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ +userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X +1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 +index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N +/p{show}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 N/Ry 0 N/V{}B/RV/v{ +/Ry X/Rx X V}B statusdict begin/product where{pop false[(Display)(NeXT) +(LaserWriter 16/600)]{A length product length le{A length product exch 0 +exch getinterval eq{pop true exit}if}{pop}ifelse}forall}{false}ifelse +end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{BDot}imagemask +grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat{BDot} +imagemask grestore}}ifelse B/QV{gsave newpath transform round exch round +exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 rlineto +fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B/M{S p +delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M}B/g{0 M} +B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p -3 w}B/n{ +p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{0 S +rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end + +%%EndProcSet +TeXDict begin 39158280 55380996 1000 600 600 (binsplit.dvi) +@start +%DVIPSBitmapFont: Fa cmcsc10 9 44 +/Fa 44 128 df<123C127EB4FCA21380A2127F123D1201A4EA0300A35A1206120E120C5A +12385A12200917788718>44 DI<123C127E12FFA4127E123C08 +08788718>I<156015F0A34A7EA34A7EA24A7E1406A2EC0EFFEC0C7FA202187F153FA24A +6C7EA202707FEC600FA202C07F1507A249486C7EA349486C7EA2498001061300A2010FB6 +FCA30118C7EA3F80A3496E7EA20170810160140FA2498116071201707E487ED80FF0EC0F +FCD8FFFE91B512F0A334367CB53D>65 DIIII +71 DII<013FB51280A39039001FF0006E5AB3B0121C127FEAFF80A44A5A130000 +7C495A12706C49C7FC6C13FC380F81F83803FFE0C66CC8FC21357CB22A>II77 D79 +DI82 D +I<007FB81280A3903A8003F8007FD87C00150F0078160700701603A20060160100E017C0 +A3481600A6C71600B3AB4A7E011FB6FCA332337CB23B>I86 D<003FB612FEA39039F80003FC13C090C7EA07F8003EEC +0FF0123C0038EC1FE00078EC3FC01270ED7F80EDFF00A20060495A4A5A14075DC7485A14 +1F5D4A5A147F5D4AC7FC5B5C495A13075C495A011F14065C495A137F5C49C7FC4848140E +A2485A485A161C485A4848143C167C484814FC48481303151FB7FCA327337BB232>90 +D<1418143CA3147EA214FFA39038019F80A201037F140FA201067F1407A2496C7EA2011C +7FEB1801A2496C7EA201707FEB7FFFA29038C0003FA20001158049131FA2000315C090C7 +120F486C14E0120F486CEB1FF0D8FFF090B5FCA228277EA62E>97 +DI<02FF13100107EBE03090391FC0787090397E001CF001F813074848 +130348481301485A000F1400485A167048C8FCA2481530127EA200FE1500A8127E163012 +7F7EA26C6C1460A26C7E000715C06C6CEB01806C6C13036C6CEB0700017E130E90381FC0 +78903807FFE00100138024287DA62C>IIII<02FF13100107EBE03090391FC0787090397E001CF001 +F813074848130348481301485A000F1400485A167048C8FCA2481530127EA200FE1500A6 +4AB5FCA2007E90380007F8ED03F0127F7EA26C7EA26C7E12076C7E6C6C1307EA00FC017E +130C90391FC03870903907FFF0100100EB800028287DA630>II< +B5FCA2EA0FF0EA07E0B3AEEA0FF0B5FCA210267DA517>I107 DIII<49B4FC010F13E090383F01F8 +90387C007C4848133FD803E0EB0F80000715C04848EB07E0491303001F15F048C7EA01F8 +A24815FCA2007E1400A200FE15FEA9007FEC01FCA36C15F86D1303001F15F06D1307000F +15E06C6CEB0FC06C6CEB1F806C6CEB3F006C6C137E90383F01F890380FFFE0010190C7FC +27287DA62F>II<49B4FC +010F13E090383F01F890387C007C4848133F4848EB1F804848EB0FC04848EB07E0491303 +001F15F0003F15F890C712014815FCA2007E1400A200FE15FEA9007E15FC007F1401A26C +15F8A23A1F807C03F014FE3A0FC1C307E03A07E3818FC03A03F301DF803A01FB00FF006C +B46C5A90383FC1F890390FFFF006130190C71278160EED7C1EED7FFE16FC153F16F8151F +ED0FF0ED07C027327DA62F>III<007FB612F8A2397E00FC0100 +78EC00780070153800601518A200E0151C48150CA5C71400B3A4497E90387FFFF8A22626 +7EA52C>III<3DFFFE +03FFF803FFC0A2290FF0007FC0001300496D48137C0007021F14387F00036E6C1330A26D +167000014A6C1360A26D496C13E0000002335CA26D903873F801017E01615CA26D9026E1 +FC03C7FC15C0A2903A1F81807E06A3903A0FC3003F0CA3D907E6EB1F98A3D903FCEB0FF0 +A36D486D5AA36D486D5AA302606D5A3A277FA53E>I<0038137038FE01FCA2EAFF03A2EA +FE01A238380070160877B229>127 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fb cmss9 9 12 +/Fb 12 106 df45 D<12FEA70707798615>I<13035B131F137F +EA07FFB5FCA313BFEAF83F1200B3B2007FB51280A519337AB226>49 +DIII65 D +68 D<12FEB3B3B0073479B315>73 D<12FEB3B3ABB612FEA51F3479B32A>76 +D97 D<12FEA71200AC127EB3AF07 +347BB313>105 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fc cmsy5 5 2 +/Fc 2 107 df0 D<12E0B3B3A50329799E13>106 +D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fd cmss8 7 10 +/Fd 10 106 df45 D<12F8A505057A8411>I<1318133813F8120F +12FFA312F01200B3A9B512F8A415277BA61F>49 D52 D65 D68 D<12FCB3B3A406287BA711>73 D<12FCB3B2B61280A419287B +A722>76 D97 D<12FCA61200A9127CB3A806297DA80E>105 +D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fe cmr7 7 41 +/Fe 41 122 df<1306130C13181330136013E0EA01C0EA0380A2EA07005A120E121EA212 +1C123CA35AA512F85AAB7E1278A57EA3121C121EA2120E120F7EEA0380A2EA01C0EA00E0 +136013301318130C13060F3B7AAB1A>40 D<12C012607E7E7E120E7EEA0380A2EA01C013 +E0120013F0A213701378A3133CA5133E131EAB133E133CA51378A3137013F0A213E01201 +13C0EA0380A2EA0700120E120C5A5A5A5A0F3B7DAB1A>I<1238127C12FE12FFA2127F12 +3B1203A31206A3120C121812381270122008127B8613>44 DI<12 +38127C12FEA3127C123807077B8613>I<13381378EA01F8121F12FE12E01200B3AB487E +B512F8A215267BA521>49 D<13FF000313E0380E03F0381800F848137C48137E00787F12 +FC6CEB1F80A4127CC7FC15005C143E147E147C5C495A495A5C495A010EC7FC5B5B903870 +018013E0EA0180390300030012065A001FB5FC5A485BB5FCA219267DA521>I<13FF0003 +13E0380F01F8381C007C0030137E003C133E007E133FA4123CC7123E147E147C5C495AEB +07E03801FF8091C7FC380001E06D7E147C80143F801580A21238127C12FEA21500485B00 +78133E00705B6C5B381F01F03807FFC0C690C7FC19277DA521>I<0018130C001F137CEB +FFF85C5C1480D819FCC7FC0018C8FCA7137F3819FFE0381F81F0381E0078001C7F001813 +3EC7FC80A21580A21230127C12FCA3150012F00060133E127000305B001C5B380F03E038 +03FFC0C648C7FC19277DA521>53 DI<137F3803FFE0380781F8380E007C48131E5A801278A3127C00 +7E131EEA3F80EBE03C6C6C5A380FFCF03807FFC06C5BC613E0487F38079FFC380F07FEEA +1E0348C67E48133FEC1F8048130FA21407A315001278140E6C5B6C5B380F80F03803FFE0 +C66CC7FC19277DA521>56 D61 +D<140EA2141FA34A7EA3EC6FC0A2ECEFE014C7A290380183F0A390380301F8A201067F14 +00A249137EA2011C137F01187FA24980013FB5FCA2903960000FC0A201E080491307A248 +486D7EA200038115011207D81FC0497ED8FFF890383FFFE0A22B2A7EA931>65 +D<91387FC002903903FFF80690390FE01E0E90383F0007017CEB019ED801F0EB00FE4848 +147E4848143E5B000F151E48C8FC48150E123EA2007E1506A2127C00FC1500A8127C007E +1506A2123EA2003F150C7E6C7E000715186D14386C6C14306C6C1460D8007CEB01C0013F +EB038090390FE01E00903803FFF89038007FC0272A7DA82F>67 D76 +D78 +D<007FB7FCA23A7E003F003F0078150F007081006081A200E01680481501A5C791C7FCB3 +A64A7E013FB5FCA229287EA72F>84 D87 D91 D93 +D<13FE3807FFC0380F03E0381C00F0003E1378003F137C143C143E121EC7FCA3EB3FFEEA +01FF3807F03EEA1FC0EA3F00127EA2481418A3147E127EECDF38393F838FF0390FFE0FE0 +3903F807C01D1C7E9A21>97 DIII<133F3801FFE03803E1F0380F80F8381F007C143E123E007E131E141F127C12FCA2 +B6FCA200FCC7FCA4127C127E1403123E6C1307380F800E3807C01C3803E0783800FFE0EB +3F80181C7E9A1E>II<90387E03E03901FF9FF03807C3 +FC380F00F048EBF800001E1378003E137CA6001E1378001F13F86C5BEBC3E0380DFF80D8 +1C7EC7FC90C8FCA3121E380FFFF014FC6C13FF001F1480393E001FC000781307EC03E048 +1301A40078EB03C0007C13076CEB0F80390FC07E003803FFF838007FC01C277E9921>I< +EA0F8012FFA2121F120FAAEB81FCEB8FFF90389C0F809038B007C013E09038C003E0A313 +80AF391FC007F039FFF83FFEA21F287EA725>I<120EEA3F80A5EA0E00C7FCA7EA078012 +FFA2121F120FB3121FEAFFF8A20D287EA713>I108 D<260F81FC137F3BFF8FFF03FFC0903A9C0F8703E03B1FB007 +CC01F0D80FE013D8903AC003F000F8A301805BAF486C486C487E3CFFF83FFE0FFF80A231 +1A7E9937>I<380F81FC38FF8FFF90389C0F80391FB007C0EA0FE09038C003E0A31380AF +391FC007F039FFF83FFEA21F1A7E9925>II<380F81FC38FF8FFF9038BC0FC0 +391FF007E0390FC003F0EB800115F8EC00FCA2157C157EA7157C15FCA2EC01F801C013F0 +EC03E09038F007C09038BC1F8090388FFF00EB83F80180C7FCA7487EEAFFF8A21F257E99 +25>I<380F07C038FF1FF0EB38F8EA1F71EA0F6113C1EBC0F014005BAF487EEAFFFCA215 +1A7E991A>114 D<3803F840380FFEC0EA3C07EA7803EA7001EAF000A37E6C1300EA7FC0 +13FC6CB4FC6C1380000713C0C613E0130738C003F0130113007EA26C13E0130100F813C0 +38EE078038C7FF00EA81FC141C7E9A1A>I<13C0A41201A312031207120F121FB512E0A2 +3807C000AC1430A73803E060A23801F0C03800FF80EB3F0014257FA31A>I<390F8003E0 +00FF133FA2001F1307000F1303B01407A20007130F9038C01BF03903E073FE3801FFE339 +007F83E01F1B7E9925>I<39FFF807FEA2390FE001F001C013E0000714C013E000031480 +EBF00300011400A23800F806A2EB7C0CA2EB7E1CEB3E18A26D5AA2EB0FE0A36D5AA26D5A +A21F1A7F9823>I<3BFFF8FFF07FE0A23B1FC01FC01F80000F90390F800E00A20007150C +EC1FC02603E01B5B15E0143B2601F0315B15F0D9F86013700000156015F89039FCC078E0 +017CEB7CC0137D90393F803D80153FEC001F6D91C7FCA2011E7F010E130EA22B1A7F982F +>I<39FFF807FEA2390FE001F001C013E0000714C0EA03E01580EBF003000114006D5A00 +00130613FCEB7C0CA26D5AA26D5AA214F06D5AA26D5AA26D5AA291C7FCA213061230EA78 +0EEAFC0C131C1318485AEA70E0EA3FC06CC8FC1F257F9823>121 +D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Ff cmmi5 5 5 +/Ff 5 121 df107 D<380F03F0383F87FC3833DC1EEA63F8EAC3F013E0EA03C0A248485A +A3EC7820D80F00136014F015C014F1001EEB7F80000CEB3E001B127D9125>110 +D<380F07E0383F8FF83833D81CEA63F038C3E03CEBC07C1203143838078000A448C7FCA4 +121E120C16127D911C>114 D<137E3801FF80EA0381380703C0380E0780EB0300EA0F80 +EA07F86CB4FC6C1380EA000FEA3003127812F8EB0700EAF00EEA7FFCEA1FF012127C911C +>I<3807E0F0381FF3F838383F1CEA703E38603C3C00C0137C12001438EB7800A2123800 +78130438F8F00CA200F013183861F870387F3FE0381E0F8016127C9121>120 +D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fg cmr5 5 7 +/Fg 7 121 df<1360EA01E0120F12FF12F11201B3A3387FFF80A2111C7B9B1C>49 +DIII97 +D<3AFE1FC03F8090397FF0FFE03A1EC0F981F03A1F803F0078EB003E001E133CAB3AFFC1 +FF83FFA228127D912F>109 D<38FFC1FFA2380F80F83807C0E03803E1C03801F3806CB4 +C7FC137E133C133E137FEBE7803801C3C0380381E048C67E001F7F39FF81FF80A219127E +911E>120 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fh cmbx9 9 33 +/Fh 33 122 df<1507ED0F80A2151F1600A25D153E157E157CA215FC5D14015DA214035D +14075DA2140F5D141F92C7FCA25C143E147E147CA214FC5C13015CA213035C13075CA213 +0F5C131F91C8FCA25B133E137E137CA213FC5B12015BA212035B12075BA2120F5B121F90 +C9FCA25A123E127E127CA212FC5AA21270214B7BB72C>47 DI<147814F8130313 +1FEA03FFB5FCA3EAFC1F1200B3B2007FB512FEA41F317AB02C>III<151F5D5DA25D5C5C5C5CA25C143D147D14F9EB01F114E1EB03 +C1EB0781130FEB1F01133E133C137813F01201EA03E0EA07C01380EA0F00121E123E5A5A +B712FEA4C700031300A80103B512FEA427317EB02C>I<123C123F90B612F8A44815F016 +E016C0168016005D007CC7127E00785C4A5A00F8495A48495A4A5A4A5AC7FC4AC7FC147E +14FE5C13015C1303A2495AA2130FA2131FA25C133FA4137FA96D5AA2010FC8FC25337BB1 +2C>55 D57 +D<120FEA3FC0EA7FE0EAFFF0A6EA7FE0EA3FC0EA0F00C7FCA9120FEA3FC0EA7FE0EAFFF0 +A6EA7FE0EA3FC0EA0F000C217AA019>I65 +D67 D73 D78 D80 D<003FB812F8A4D9F003EB801FD87F80ED +03FC01001501007E1600007C177CA20078173CA400F8173E48171EA4C71600B3A9011FB6 +12F0A437327DB13E>84 D97 D<903807FF80013F13F090B512FC3903FE01FE4848487EEA0FF8EA +1FF0EA3FE0A2007F6D5A496C5A153000FF91C7FCA9127F7FA2003FEC07807F6C6C130F00 +0FEC1F00D807FE133E3903FF80FCC6EBFFF8013F13E0010790C7FC21217DA027>99 +D<903803FF80013F13F090B512FC48EB03FE3907FC007F4848EB3F804848EB1FC05B003F +EC0FE0127F5B16F012FF150790B6FCA301C0C8FCA4127F7F123F16F06C7E000F14016C6C +EB03E0D803FEEB0FC03A01FF807F806C6CB51200011F13FC010313E024217EA029>101 +DI<16F890390FFC +07FE90387FFF9F48B6127F3907FC0FFC380FF003001F14FED9E001133E003FECFF1C1600 +A6001F5CEBF003000F5C3907FC0FF890B512E0486C1380D90FFCC7FC48C9FCA37F7F90B5 +12F015FE6CECFF8016E06C15F06C15F84815FC121F393F80001F48C7EA03FE4814014814 +00A46C14016C6CEB03FC6C6CEB07F86C6CEB0FF0D80FFCEB7FE00003B61280C6ECFE0001 +0F13E028327EA12C>III107 DI<2703F803FEEB03FE00FF903B1FFFC01FFFC0027FD9E07F7F913B +F81FF0F81FF0903CF9E00FF9E00FF8260FFBC0EBFBC06CB4486CB4486C7E02001400495C +A3495CB2B500E0B500E0B512E0A443217CA04A>I<3901F803FF00FF010F13C0023F13F0 +9138FC0FF89039F9E007FC380FFBC06CB4486C7E1400A25BA25BB2B539E07FFFF0A42C21 +7DA031>I<903803FF80011F13F090B512FE48EB01FF3A07FC007FC0D80FF0EB1FE0001F +15F049130F003F15F8491307007F15FCA300FF15FEA8007F15FCA26D130F003F15F8001F +15F06D131F6C6CEB3FE06C6CEB7FC03A01FF01FF006CEBFFFE013F13F80103138027217E +A02C>I<3901FC07FC00FF90387FFF8001FDB512E09039FFF01FF89138C007FC000F9038 +0003FE6C4880496D1380A26F13C0A3EE7FE0A9EEFFC0A34B1380A26D4913006D495A9138 +C00FFC9138F03FF801FDB512E0D9FC7F1380DA0FF8C7FC91C9FCABB512E0A42B307EA031 +>I<3901F81F8000FFEB7FF0ECFFF89038F9E3FC9038FBC7FE380FFF876C1307A213FEEC +03FCEC01F8EC0060491300B1B512F0A41F217EA024>114 D<9038FFE1C0000713FF5A38 +3F803F387E000F14075A14037EA26C6CC7FC13FCEBFFE06C13FC806CEBFF80000F14C06C +14E0C6FC010F13F0EB007F140F00F0130714037EA26C14E06C13076CEB0FC09038C01F80 +90B5120000F913FC38E03FE01C217DA023>I<133CA5137CA313FCA21201A21203120700 +1FB51280B6FCA3D807FCC7FCB0EC03C0A79038FE078012033901FF0F006C13FEEB3FFCEB +0FF01A2F7EAE22>I120 DI +E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fi cmti9 9 50 +/Fi 50 128 df14 D<130E131F133F137E13FCEA01F8EA03F0EA07E0EA0F +80EA1F00123E5A5A5A100E67B327>19 D39 D<1560EC01E0EC03C0EC07 +00140E5C143C5C5C495A495A13075C49C7FC5B131E5B137C137813F85B12015B12035B12 +07A25B120FA290C8FC5AA2121E123EA3123C127CA31278A212F8A35AAF12701278A21238 +A2123C121CA27EA27E6C7E12011B4A75B71F>I<14301438A28080A2140F801580A21403 +15C0A4140115E0A81403A415C0A31407A31580140FA315005CA3141E143EA2143C147CA2 +5CA25C13015C13035C13075C130F91C7FC131E133E133C5B5B485AA2485A485A48C8FC12 +1E5A12705A5A1B4A7EB71F>I44 DI< +121C127F12FFA412FE12380808778718>I<1370EA01FC1203A413F8EA00E01300B0121C +127F5AA45A12380E20779F18>58 D<161C163CA2167C16FCA21501821503A2ED077E150F +150E151CA21538A2157015F015E0EC01C0A2913803807F82EC0700A2140E141E141C5CA2 +5CA25C49B6FCA25B913880003F49C7EA1F80A2130E131E131C133C13385B13F05B120112 +03D80FF0EC3FC0D8FFFE903807FFFEA32F367BB539>65 D<0107B612C04915F017FC903A +003F8000FE177FEF3F8092C7121FA24A15C0A2147EA214FE18804A143FA20101ED7F0017 +7E4A5C16010103EC03F04C5A4AEB1FC091B6C7FC495C9139F0007F804AEB0FC0707E010F +6E7E834A1301A2011F81A25CA2133F5F91C71203A2494A5AA2017E4A5A4C5A01FE4A5A4C +C7FC49EB01FE0001EC07FC007FB612F0B712C04BC8FC32337BB236>II<0107B612C04915F017FC903A003F8001FEEE007FEF1F +8092C7EA0FC0EF07E05CEF03F0147E170102FE15F8A25CA21301A25CA2130317035CA213 +0718F04A1407A2130F18E04A140F18C0011F151F18805CEF3F00133F177E91C85AA2494A +5A4C5A017E4A5A4C5A01FE4A5A047EC7FC49495A0001EC0FF8007FB612E0B7C8FC15F835 +337BB23A>I<0107B712F05B18E0903A003F80001F1707170392C7FC17015C18C0147EA2 +14FEA24A130EA20101EC1E03041C13804A91C7FC163C13035E9138F001F891B5FC5B5EEC +E0011500130F5E5C1707011F01015BEEC00E0280141E92C7121C133F173C91C812381778 +495DA2017E14014C5A01FE14074C5A49141F00014AB45A007FB7FCB8FC94C7FC34337CB2 +34>I<92391FE001809238FFF8030207EBFE07913A1FF01F0F0091393F80079F9139FE00 +03DFD901F86DB4FCD907F05C49481300495A4948147E49C8127C137E13FE485A48481578 +A2485AA248481570A2485A94C7FC123F5BA3127F90CBFCA400FE91383FFFFCA25F923800 +3F8094C7FCA2007E5DA2167EA2007F15FE7E5E6C6C1301A26C6C495A6D13076C6CEB0F78 +6C6C133E3A00FF01FC3090387FFFF0011F01C0C8FCD903FEC9FC313775B43B>71 +D<0107B548B512C0495CA2903C003FC0000FF0004B5CA292C75BA24A141F60147EA202FE +143F95C7FC5CA201015D177E5CA2010315FE5F5C91B6FC5B5F9138E00001A2010F14035F +5CA2011F14075F5CA2013F140F5F91C7FCA249141F5F137EA201FE143F94C8FC5B00015D +3B7FFFF01FFFFCB55BA23A337BB239>I<010FB51280A216009038003FC05DA292C7FCA2 +5CA2147EA214FEA25CA21301A25CA21303A25CA21307A25CA2130FA25CA2131FA25CA213 +3FA291C8FCA25BA2137EA213FEA25B1201B512F8A25C21337BB21E>I<91381FFFFE5C16 +FC9138003F80A31600A25D157EA315FE5DA314015DA314035DA314075DA3140F5DA3141F +5DA3143F92C7FCA2121C007E5B00FE137EA214FE485BEAF80100E05B495A387007E03878 +0FC06C48C8FCEA1FFCEA07F0273579B228>I<902607FFC0ED7FFC4917FF81D9003F4B13 +00611803023BED077CA2027BED0EFC610273151C1838DAF1F01439F071F014E118E10101 +ED01C36102C1EC0383EF070301031607050E5BEC80F8171C0107ED380F6102001470A249 +EDE01FDC01C090C7FC130EEE0380011E017C5C933807003E011C140EA2013C4A137E187C +01385C5E017816FC6F485B1370ED3FC001F0EC80016000011500D807F81503277FFF803E +90B512C0B5EB3C01151C46337BB245>77 D<902607FF8090383FFFC0496D5BA2D9001F91 +3803F8004A6C6D5A6060EC3BF0027B140360EC71F8A202F11407DAF0FC91C7FC14E0A201 +01017E5B170E14C0810103151EEE801CEC801FA20107ECC03C030F1338140016E0490107 +13781770010E14F01503011E15F0705A011C1301A2013C14FD03005B133816FF0178147F +5F0170143FA213F070C8FC1201EA07F8267FFF807FB5140EA23A337BB239>I<0107B612 +C04915F883903A003F8001FEEE003FEF1F8092C713C0170F5C18E0147EA214FEEF1FC05C +A201011680173F4A1500177E010315FE5F4AEB03F8EE07E00107EC3FC091B6C7FC16F802 +E0C9FC130FA25CA2131FA25CA2133FA291CAFCA25BA2137EA213FEA25B1201387FFFF0B5 +FCA233337CB234>80 D<913901FC018091380FFF03023F13C791387E07EF903A01F801FF +0049487E4A7F495A4948133E131F91C7FC5B013E143CA3137E1638A293C7FC137FA26D7E +14E014FE90381FFFC06D13F86D7F01017F6D6C7E020F7F1400153F6F7E150FA4120EA200 +1E5D121CA2151F003C92C7FCA2003E143E5D127E007F5C6D485A9038C007E039F3F80FC0 +00F0B5C8FC38E03FFC38C00FF029377AB42B>83 D<0003B812C05A1880903AF800FC003F +260FC001141F0180150F01005B001EEE07001403121C003C4A5BA200380107140E127800 +705CA2020F141E00F0161CC74990C7FCA2141FA25DA2143FA292C9FCA25CA2147EA214FE +A25CA21301A25CA21303A25CA21307A25C497E001FB512F05AA2323374B237>I<49B612 +FC5BA292380001F8D907F8EB03F04A130702C0EB0FE04948EB1FC0EE3F8091C7EA7F0001 +1E147E16FE011C495A013C495A4B5A0138495A5E0178495A90C7123F4BC7FC15FE4A5A5D +4A5A14074A5A4A5A4A5A4AC8FC147E14FE4948130749485B4948130E495A4A131E131F49 +48131C49C7123C13FE48485C5B484814F800074A5A48481303484813074848EB1FE048C7 +12FF90B6FCB7FC5E2E337AB22F>90 D97 D<137EEA0FFE121F5B1200A35BA212 +01A25BA21203A25BA21207A2EBC3E0EBCFF8380FDC3EEBF81F497E01E01380EA1FC01380 +15C013005AA2123EA2007E131F1580127CA2143F00FC14005AA2147EA25CA2387801F85C +495A6C485A495A6C48C7FCEA0FFCEA03F01A3578B323>I<14FCEB07FF90381F07809038 +3E03C0EBFC013801F8033803F0073807E00F13C0120F391F80070091C7FC48C8FCA35A12 +7EA312FE5AA4007C14C0EC01E0A2EC03C06CEB0F80EC1F006C137C380F81F03803FFC0C6 +48C7FC1B2278A023>III<15 +1FED7FC0EDF0E0020113F0EC03E3A2EC07C316E0EDC1C091380FC0005DA4141F92C7FCA4 +5C143E90381FFFFEA3D9007EC7FC147CA414FC5CA513015CA413035CA413075CA3130FA2 +5CA3131F91C8FCA35B133E1238EA7E3CA2EAFE7812FC485AEA78E0EA3FC0000FC9FC2445 +82B418>I<143FECFF80903803E1E6903807C0FF90380F807FEB1F00133E017E133F4913 +3EA24848137EA24848137CA215FC12074913F8A21401A2D80FC013F0A21403120715E014 +07140F141F3903E03FC00001137FEBF0FF38007FCF90381F0F801300141FA21500A25C14 +3E1238007E137E5C00FE5B48485A387803E0387C0F80D81FFFC7FCEA07F820317CA023> +III<1538157C15FCA315701500AB143EECFF80 +903801E3C090380383E0EB0701130FEB0E03131C133C133814071378013013C01300140F +A21580A2141FA21500A25CA2143EA2147EA2147CA214FCA25CA21301A25CA213035C1238 +387E07C0A238FE0F804848C7FCEAF83EEA787CEA3FF0EA0F801E4283B118>II<133FEA07FF5A13FEEA +007EA3137CA213FCA213F8A21201A213F0A21203A213E0A21207A213C0A2120FA21380A2 +121FA21300A25AA2123EA2127EA2127C1318EAFC1C133CEAF838A21378137012F013F0EA +F8E01279EA3FC0EA0F00103579B314>I<2703C003F8137F3C0FF00FFE01FFC03C1E783C +1F07C1E03C1C7CF00F8F01F03B3C3DE0079E0026383FC001FC7FD97F805B007001005B5E +137ED8F0FC90380FC00100E05FD860F8148012000001021F130360491400A200034A1307 +6049013E130FF081800007027EEC83C0051F138049017C1403A2000F02FC1407053E1300 +49495CEF1E0E001F01015D183C010049EB0FF0000E6D48EB03E03A227AA03F>I<3903C0 +07F0390FF01FFC391E787C1E391C7CF01F393C3DE00F26383FC01380EB7F8000781300EA +707EA2D8F0FC131F00E01500EA60F8120000015C153E5BA20003147E157C4913FCEDF818 +0007153C0201133801C013F0A2000F1578EDE070018014F016E0001FECE1C015E390C7EA +FF00000E143E26227AA02B>I<14FCEB07FF90381F07C090383E03E09038FC01F0EA01F8 +3903F000F8485A5B120F484813FCA248C7FCA214014814F8127EA2140300FE14F05AA2EC +07E0A2007CEB0FC01580141FEC3F006C137E5C381F01F0380F83E03803FF80D800FCC7FC +1E2278A027>I<011E137C90387F81FF9039F3C387C09039E3EF03E03901E1FE01D9C1FC +13F0EBC3F8000313F0018314F814E0EA07871307000313C01200010F130316F01480A201 +1F130716E01400A249EB0FC0A2013EEB1F80A2017EEB3F00017F133E5D5D9038FF81F090 +38FDC3E09038F8FF80027EC7FC000190C8FCA25BA21203A25BA21207A25BB5FCA325307F +A027>I<3903C00FC0390FF03FF0391E78F078391C7DE03C393C3FC0FC00381380EB7F00 +007814F8D8707E13701500EAF0FC12E0EA60F812001201A25BA21203A25BA21207A25BA2 +120FA25BA2121FA290C8FC120E1E227AA020>114 DI<1303EB0F80A3131FA21400A25BA2133EA2137EA2137C387FFF +F8A2B5FC3800F800A21201A25BA21203A25BA21207A25BA2120FA25B1460001F13F014E0 +1300130114C01303001E1380EB07005BEA0F1EEA07F8EA01E015307AAE19>II<01F01338D803FC13FCEA0F1E120E121C123C0038147CEA783E0070143CA2 +137ED8F07C1338EA60FCC65A1578000114705BA215F0000314E05BA2EC01C0A2EBC00315 +8014071500EBE00EA26C6C5A3800F878EB7FE0EB1F801E227AA023>II<011F137C90387FC1FF3A01E1E787 +803A03C0F703C0903880FE0FEA07004813FC000E1580001E9038F80700001C91C7FC1301 +003C5B1218120013035CA31307A25C1506010F130F150E14800038141ED87C1F131C00FC +143C1538013F5B39F07FC0E03970F3C3C0393FE1FF80260F807EC7FC22227CA023>I<13 +F0D803FC1307D80F1E130F000E141F121C123C0038143FD8783E133E1270A2017E137ED8 +F07C137CEA60FCC65A15FC000114F85BA21401000314F013E0A2140315E0EA07C0A20003 +130715C0EBE00F141F0001133F9038F07F8038007FEFEB1F8FEB001F1500A25C003E133E +007E137E147C5C007C5BEA7001495A38380780D83C1FC7FCEA0FFCEA07F020317AA025> +I123 D<001E13F0387F01F81303EAFF07A338FE03F0383801C0 +15086CB227>127 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fj cmsy9 9 13 +/Fj 13 113 df<007FB712FCB812FEA26C16FC2F047A943C>0 D<123C127E12FFA4127E +123C08087A9615>I<130E131FA639700E01C000F8EB03E000FE130F00FF131F397F8E3F +C0391FEEFF003803FFF8C613E0EB3F80A2EBFFE0000313F8381FEEFF397F8E3FC039FF0E +1FE000FE130F00F813030070EB01C0D8001FC7FCA6130E1B207BA226>3 +D<15E081B3A4007FB812C0B912E0A26C17C0C800F0C8FCB3007FB812C0B912E0A26C17C0 +33327CB13C>6 D<171C177EEE01FEEE07FCEE1FF0EE7FC0923801FF00ED07FCED1FF0ED +7FC04A48C7FCEC07FCEC1FF0EC7FC04948C8FCEB07FCEB1FF0EB7FC04848C9FCEA07FCEA +1FF0EA7FC048CAFCA2EA7FC0EA1FF0EA07FCEA01FF38007FC0EB1FF0EB07FCEB01FF9038 +007FC0EC1FF0EC07FCEC01FF9138007FC0ED1FF0ED07FCED01FF9238007FC0EE1FF0EE07 +FCEE01FEEE007E171C1700AC007FB712FCB812FEA26C16FC2F3E7AB03C>20 +D<127012FCB4FCEA7FC0EA1FF0EA07FCEA01FF38007FC0EB1FF0EB07FCEB01FF9038007F +C0EC1FF0EC07FCEC01FF9138007FC0ED1FF0ED07FCED01FF9238007FC0EE1FF0EE07FCEE +01FEA2EE07FCEE1FF0EE7FC0923801FF00ED07FCED1FF0ED7FC04A48C7FCEC07FCEC1FF0 +EC7FC04948C8FCEB07FCEB1FF0EB7FC04848C9FCEA07FCEA1FF0EA7FC048CAFC12FC1270 +CBFCAC007FB712FCB812FEA26C16FC2F3E7AB03C>I<187018F0A2841878A2187C183C18 +3E84A2727E727E85727E727E727E197F007FBA12C0BB12F0A26C19C0CCEA7F0019FC4E5A +4E5A4E5A614E5A4EC7FCA2183E183C187C1878A218F860A2187044287CA64D>33 +D49 D<1630167816F8A2ED01F0A2ED03E0A2ED07C0A2ED0F80A2ED1F00A2153E +A25DA25DA24A5AA24A5AA24A5AA24A5AA24AC7FCA2143EA25CA25CA2495AA2495AA2495A +A2495AA249C8FCA2133EA25BA25BA2485AA2485AA2485AA2485AA248C9FCA2123EA25AA2 +5AA25A1260254675B500>54 D<126012F0B3B3B3AFB512E0A37E134A74B722>98 +D<14C0EB01E0B3B3B3AFB5FCA314C0134A7EB722>I<126012F0B3B3B3B31260044B78B7 +15>106 D<1930197819F8A2F001F0A2F003E0A2F007C0A2F00F80A2F01F00A2183EA260 +A260A24D5AA24D5AA24D5AA24D5AA24DC7FCA2173EA25FA25FA24C5A13C000014B5AEA07 +E0000F4B5AEA3FF000734B5AEAE3F800C14BC8FCEA01FC0000153E7F017E5C137F6D5CA2 +6E485A131F6E485A130F6E485A13076E485A13036E48C9FC1301153E14FC01005B14FEEC +7EF8147F6E5AA26E5AA26E5AA26E5A92CAFC3D4C7B8340>112 D +E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fk cmmi6 6 30 +/Fk 30 121 df11 D<90381FFFFC90B5FC5A4814F83907C07C00380F00 +3C001E131C48131E12381278A2485BA35C1470007013F0495A6C485AD81C0FC7FCEA0FFE +EA03F01E167E9424>27 D60 D<140C141C143C1438A21478147014F014E0130114C0A2130314 +8013071400A25B130E131E131CA2133C13381378137013F05BA212015B12035BA2120790 +C7FC5A120EA2121E121C123C123812781270A212F05AA216317CA420>I<90B6FC16E090 +3907C003F0ED00F8494813FC167C167EA249C7127C16FCA2ED01F8013EEB03F0ED07E0ED +1F8090393FFFFE005B90397C003F80ED07C0ED03E04914F01501A216F8484814F01503A2 +ED07E04848EB0FC0ED1F80ED3F00000714FEB612F815C027227CA12E>66 +D<90B6FC16E0903907C003F8ED00FC4948133E161E161FEE0F8049C7FCA317C0133EA449 +1580161FA21700495CA2163E5E485A5E4B5A4B5A4848495A4B5A033EC7FC0007EB01F8B6 +12E092C8FC2A227CA132>68 D78 +DI81 D<001FB612FCA29039003E00 +7C003C151C00385B12300070151812605C5AA3C648481300A4495AA4495AA4495AA449C8 +FCA35B381FFFFE5C26227DA124>84 D86 +D<131FEBFF8C3801E0DE3803807E3807007C48133C121E123E003C5B127CA3485BA21540 +1560903801E0C012781303393807E180391C1CF300380FF87F3807E03C1B177E9522>97 +DIII<140FEC3FC0EC71E014E3A2010113C0EC +E180ECE000495AA5495AA2EBFFFEA2EB0780A249C7FCA5131EA65BA55BA31370A2EA38F0 +EA78E012F8EAF9C0EA7180007FC8FC121E1B2F7CA31E>102 DI<1338137CA2137813701300A7EA0780EA1FC0EA38E01230EA60F0EAC1 +E0A3EA03C0A3EA0780A2EA0F0013041306EA1E0CA21318121CEA1E70EA0FE0EA07800F23 +7DA116>105 D<13F8EA0FF0A21200A2485AA4485AA43807801E147FEB81C3EB8387380F +060F495A1318EB700E4848C7FCA213FCEA1E7EEA3C0F80EB0781158039780F0300A21402 +EB070600F0138CEB03F8386000F019247CA221>107 DI<000F017E13FC3A1F81FF83FF3B31C383C707803A61EE03CC039026EC01F813 +C0D8C1F813F013F001E013E00003903903C0078013C0A2EE0F003907800780A2EE1E0417 +06270F000F00130C163C1718A2001E011EEB1C70EE1FE0000C010CEB07802F177D9536> +I<000F13FC381FC3FF3931C707803861EC0301F813C0EAC1F0A213E03903C00780A3EC0F +00EA0780A2EC1E041506D80F00130C143C15181538001EEB1C70EC1FE0000CEB07801F17 +7D9526>I<3801E01F3903F07FC0390639C1E0390C3F80F0EB3E00001814F8013C137815 +F8C65AA49038F001F0A3EC03E0D801E013C0EBF00715809038F80F003803DC3CEBCFF8EB +C7E001C0C7FC485AA448C8FCA2EA7FF012FF1D20809520>112 DI<380F01 +F0381FC7F83831CE1CEA61F8EBF03C00C1137C13E014383803C000A4485AA448C7FCA412 +1EA2120C16177D951D>II<133013785BA4485AA4485AB51280A23803C00048 +5AA448C7FCA4121EA25B1480383C03001306A25BEA1C38EA0FF0EA07C011217D9F18>I< +EA07C0380FE0033918F0078012300060EB0F0012C0A2EAC1E00001131EEA03C0A348485A +A215101518EC7830A214F8018113603903C3B8C03901FF1F803900FC0F001D177D9525> +I<3807800E380FE01FEA38F012300060130F12C01407EAC1E000011306EA03C0A3380780 +0CA214081418A21430146014C0EA03C13801FF00EA007E18177D951F>I<3801F01E3907 +FC7F80390E1CE1C038180F8100301383007013071260EC0380D8001EC7FCA45BA2158000 +3014C0397878018012F8EC030038F0FC0638E19C1C387F0FF8381E03E01A177D9523> +120 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fl cmex10 10 24 +/Fl 24 113 df<1430147014E0EB01C01303EB0780EB0F00A2131E5BA25B13F85B12015B +1203A2485AA3485AA3121F90C7FCA25AA3123EA2127EA6127C12FCB3A2127C127EA6123E +A2123FA37EA27F120FA36C7EA36C7EA212017F12007F13787FA27F7FA2EB0780EB03C013 +01EB00E0147014301462738226>0 D<12C07E12707E123C7E7EA26C7E6C7EA26C7E7F12 +007F1378137CA27FA37FA31480130FA214C0A31307A214E0A6130314F0B3A214E01307A6 +14C0A2130FA31480A2131F1400A3133EA35BA2137813F85B12015B485AA2485A48C7FCA2 +121E5A12385A5A5A14627C8226>III<12F0B3B3B3B3B3A4B512F8A4 +1562708227>I<1478B3B3B3B3B3A4B512F8A415627F8227>I<12F0B3B3B2043674811C> +12 D<151E153E157C15F8EC01F0EC03E01407EC0FC0EC1F8015005C147E5CA2495A495A +A2495AA2495AA2495AA249C7FCA2137EA213FE5B12015BA212035BA21207A25B120FA35B +121FA45B123FA548C8FCA912FEB3A8127FA96C7EA5121F7FA4120F7FA312077FA21203A2 +7F1201A27F12007F137EA27FA26D7EA26D7EA26D7EA26D7EA26D7E6D7EA2147E80801580 +EC0FC0EC07E01403EC01F0EC00F8157C153E151E1F94718232>16 +D<12F07E127C7E7E6C7E7F6C7E6C7E12017F6C7E137EA27F6D7EA26D7EA26D7EA26D7EA2 +6D7EA26D7EA280147E147F80A21580141FA215C0A2140F15E0A3140715F0A4140315F8A5 +EC01FCA9EC00FEB3A8EC01FCA9EC03F8A515F01407A415E0140FA315C0141FA21580A214 +3F1500A25C147E14FE5CA2495AA2495AA2495AA2495AA2495AA249C7FC137EA25B485A5B +1203485A485A5B48C8FC123E5A5A5A1F947D8232>I<160F161F163E167C16F8ED01F0ED +03E0ED07C0150FED1F801600153E157E5D4A5A5D14034A5A5D140F4A5AA24AC7FC143E14 +7E5CA2495AA2495AA2495AA2130F5CA2495AA2133F91C8FCA25B137E13FEA25B1201A25B +1203A35B1207A35B120FA35BA2121FA45B123FA690C9FC5AAA12FEB3AC127FAA7E7FA612 +1F7FA4120FA27FA312077FA312037FA312017FA212007FA2137E137F7FA280131FA26D7E +A2801307A26D7EA26D7EA26D7EA2147E143E143F6E7EA26E7E1407816E7E1401816E7E15 +7E153E811680ED0FC01507ED03E0ED01F0ED00F8167C163E161F160F28C66E823D>I<12 +F07E127C7E7E6C7E6C7E6C7E7F6C7E1200137C137E7F6D7E130F806D7E1303806D7EA26D +7E147C147E80A26E7EA26E7EA26E7EA2811403A26E7EA2811400A281157E157FA2811680 +A2151F16C0A3150F16E0A3150716F0A31503A216F8A4150116FCA6150016FEAA167FB3AC +16FEAA16FC1501A616F81503A416F0A21507A316E0150FA316C0151FA31680153FA21600 +5DA2157E15FE5DA214015DA24A5AA214075DA24A5AA24A5AA24AC7FCA2147E147C14FC49 +5AA2495A5C1307495A5C131F49C8FC137E137C5B1201485A5B485A485A48C9FC123E5A5A +5A28C67E823D>I32 D<12F07E127C7E123F7E6C7E6C7E6C7E7F12016C7E +7F137E133E133F6D7E130F806D7EA26D7E80130180130080147E147F8081141F81140F81 +140781A2140381140181A2140081A2157FA36F7EA382151FA282150FA3821507A382A215 +03A282A31501A282A31500A382A482A21780A7163F17C0AC161F17E0B3B3A217C0163FAC +1780167FA71700A25EA45EA31501A35EA21503A35EA21507A25EA3150F5EA3151F5EA215 +3F5EA34BC7FCA315FEA25D1401A25D14035D1407A25D140F5D141F5D143F92C8FC5C147E +14FE5C13015C13035C495AA2495A5C131F49C9FC133E137E5B5B485A12035B485A485A48 +CAFC5A123E5A5A5A2BF87E8242>I<177C17FCEE01F8A2EE03F0EE07E0EE0FC0A2EE1F80 +EE3F005E167E5E15015E15034B5A5E150F5E151F4B5AA24BC7FCA215FEA24A5AA24A5AA2 +4A5AA2140F5D141F5D143F5DA2147F92C8FC5CA25C13015C1303A25C1307A3495AA3495A +A3133F5CA3137F5CA313FF91C9FCA35A5BA31203A25BA31207A35BA3120FA45BA2121FA6 +5BA2123FA85BA2127FAE5B12FFB3A62E95688149>48 D<12F87E127EA27E6C7E6C7EA26C +7E6C7E7F12016C7E7F137E137F6D7E131F80130F806D7EA26D7EA26D7EA26D7EA2147FA2 +6E7EA281141F81140F811407A281140381A2140181140081A28182A36F7EA36F7EA38215 +0FA3821507A3821503A3821501A382A281A31780A3167FA317C0A4163FA217E0A6161FA2 +17F0A8160FA217F8AE160717FCB3A62E957E8149>I64 DI +80 D +88 DII108 DI<1B301B781BF8 +A2F201F0A2F203E0A2F207C0A2F20F80A2F21F00A21A3EA262A262A24F5AA24F5AA24F5A +A262190FA24FC7FCA2193EA261A261A24E5AA24E5AA24E5AA24E5AA24EC8FCA2183EA260 +131001305E13F800014C5A1203D80FFC4B5A121DD838FE4B5A12F0D8407F4B5A12004DC9 +FC6D7E173E6D7E5F6D7E5FA26D6C495AA26D6C495AA26D6C5C1607A26D6C495AA2027F49 +CAFCA291383F803EA25EEC1FC05EEC0FE0EDE1F0EC07F1EDF3E0A26EB45AA26E5BA26E90 +CBFCA25D157E157C15384D64788353>112 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fm cmsy6 6 8 +/Fm 8 113 df0 D<127812FCA4127806067A8F13>I20 D<12E012F812FEEA3F80EA0FE0EA03F8EA00FEEB3F80EB0FC0EB03F0 +EB00FC147FEC1FC0EC07F0EC01FCEC007FED1FC01507151FED7F00EC01FCEC07F0EC1FC0 +027FC7FC14FCEB03F0EB0FC0EB3F8001FEC8FCEA03F8EA0FE0EA3F80007EC9FC12F812E0 +CAFCA9007FB61280B712C0A2222F7AA230>I48 +D<01FEEC0FE02603FFC0EB3FF8000F01F0EBFE3E3B1F0FF801F0073C3C01FC07C003803B +3000FE0F00010070D93F1EEB00C00060EB1F9C00E0D90FF81460485C14076E7E6E7E8102 +0315E00060D9073F14C091390F1F80016C90261E0FE01380003890397C07F0073C1C01F0 +03FE1F003B0F8FE001FFFE3B03FF80007FF8C648C7EA0FE033177C953D>I<12E0B3B3AD +033179A413>106 D<170C171C173C1738177817F017E0160117C0160317801607EE0F00 +160E161E161C163C163816785E5E15015E15034B5AD8038091C7FC00075CD81FC0130E00 +3F141ED8F3E0131C0043143CD801F05B15706C6C13F05DEB7C015DEB3E034A5A011F90C8 +FC5CEB0F8E149EEB07DC14FC6D5A5C13015C13002E327C8232>112 +D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fn cmr6 6 18 +/Fn 18 121 df<127812FCA81278AB1230A61200A4123012FCA4123006247AA312>33 +D<130C1338137013E0EA01C0EA038013005A120EA25AA25AA312781270A312F0AB1270A3 +12781238A37EA27EA27E7E1380EA01C0EA00E013701338130C0E317AA418>40 +D<12C012707E7E7E7E7E1380EA01C0A2EA00E0A21370A313781338A3133CAB1338A31378 +1370A313E0A2EA01C0A2EA038013005A120E5A5A5A12C00E317CA418>I<1438B2B712FE +A3C70038C7FCB227277C9F2F>43 D<13FF000313C0380781E0380F00F0001E137848133C +A248131EA400F8131FAD0078131EA2007C133E003C133CA26C13786C13F0380781E03803 +FFC0C6130018227DA01E>48 D<13E01201120712FF12F91201B3A7487EB512C0A212217A +A01E>II<13FF000313C0380F03E0381C00F0 +14F8003E13FC147CA2001E13FC120CC712F8A2EB01F0EB03E0EB0FC03801FF00A2380003 +E0EB00F01478147C143E143F1230127812FCA2143E48137E0060137C003813F8381E03F0 +380FFFC00001130018227DA01E>I<14E01301A213031307A2130D131D13391331136113 +E113C1EA01811203EA07011206120C121C12181230127012E0B6FCA2380001E0A6EB03F0 +EB3FFFA218227DA11E>I<00101330381E01F0381FFFE014C01480EBFE00EA1BF00018C7 +FCA513FE381BFF80381F03C0381C01E0381800F014F8C71278A2147CA21230127812F8A2 +14784813F8006013F0387001E01238381E07803807FF00EA01F816227CA01E>II61 D97 D<3801F83F3907FEFF80381E07E3391C038300383801C000787FA500385B6C +485AEA1E07D83FFEC7FCEA31F80030C8FC1238A2383FFF806C13F06C7F487F3838007E48 +130E48130F80A36C5B0070130E003C133C001F13F83807FFE0C690C7FC19227D951E> +103 D<120FB4FCA2121F7EB3ABEAFFF0A20C237DA212>108 D<3A0F07F007F03AFF1FFC +1FFC9039703E703E3A1FC01EC01E6C486C487EA201001300AE3BFFF0FFF0FFF0A22C167D +9532>I<137E3803FFC0380781E0380F00F0001E137848133CA248131EA200F8131FA700 +78131E007C133E003C133C003E137C6C13F8380F81F03803FFC0C6130018187D961E> +111 D<397FE07FE0A2390FC03F000007133C3803E0386C6C5A6C6C5AEB7DC0EB3F806DC7 +FC7F497EEB3BC0EB71E0EBE0F03801C0783803807C00077F001F133F39FFC07FF0A21C15 +7E9420>120 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fo cmmi9 9 49 +/Fo 49 123 df<147F903803FFE090380FC0F890383F007C017C017E1360497F484815E0 +484890381F80C0120748481481EEC1804848130F003F15C390C7140016C74815C6007E15 +CE16DC16D816F8485D5E5E127CA3151F6C143F037713C06C903801E7E03A0F800783E13B +07C07E03E3803B01FFF801FF003A007F80007C2B227EA031>11 D<1418A214381430A214 +38EC1BFCEC1FFFEC3C0391B5FC903801E3FC903803C00049C7FC130E5B133C5B5B485AA2 +485A485AA248C8FCA2121EA25AA3127C1278A312F8A25AA37EA47E7E127EEA7F807FEA3F +F86CB4FC6C13E06C13F8000113FE6C6C7E010F138013019038003FC0141F140F1407A215 +80A29038200F001330EB3C1EEB0FF8EB03E020447DB322>16 D<013FB6128090B712C012 +03481680481600271F00C018C7FC001C1438EA38010070143000601380EAE00300001470 +A2EB0700A25B15F0130E131EA2013E7F133C137CA213FC497FA2000180A2485A157EA2D8 +01C013382A217E9F2C>25 D +39 D<123C127E12FFA4127E123C08087A8715>58 D<123C127EB4FCA21380A2127F123D +1201A412031300A25A1206120E120C121C5A5A126009177A8715>I<171C177EEE01FEEE +07FCEE1FF0EE7FC0923801FF00ED07FCED1FF0ED7FC04A48C7FCEC07FCEC1FF0EC7FC049 +48C8FCEB07FCEB1FF0EB7FC04848C9FCEA07FCEA1FF0EA7FC048CAFCA2EA7FC0EA1FF0EA +07FCEA01FF38007FC0EB1FF0EB07FCEB01FF9038007FC0EC1FF0EC07FCEC01FF9138007F +C0ED1FF0ED07FCED01FF9238007FC0EE1FF0EE07FCEE01FEEE007E171C2F2E7AA93C>I< +1530157815F8A215F01401A215E01403A215C01407A21580140FA215005CA2143EA2143C +147CA2147814F8A25C1301A25C1303A25C1307A2495AA291C7FC5BA2131E133EA2133C13 +7CA2137813F8A25B1201A25B1203A2485AA25B120FA290C8FC5AA2121E123EA2123C127C +A2127812F8A25A12601D4B7CB726>I<127012FCB4FCEA7FC0EA1FF0EA07FCEA01FF3800 +7FC0EB1FF0EB07FCEB01FF9038007FC0EC1FF0EC07FCEC01FF9138007FC0ED1FF0ED07FC +ED01FF9238007FC0EE1FF0EE07FCEE01FEA2EE07FCEE1FF0EE7FC0923801FF00ED07FCED +1FF0ED7FC04A48C7FCEC07FCEC1FF0EC7FC04948C8FCEB07FCEB1FF0EB7FC04848C9FCEA +07FCEA1FF0EA7FC048CAFC12FC12702F2E7AA93C>I<16035E5EA24C7EA2163F167FA216 +FFA2ED01BFED033F831506161F150C1518A215301570156015C083EC01800203130F1500 +1406A25C141C14184A80A2027FB5FC91B6FCA2903901800007A249C7FC1306835B16035B +5B1370136013E01201D807F04A7EB549B512F0A25B34367DB53A>65 +D<010FB612F017FEEFFF80903B003FC0003FE0EF0FF017074B14F81703027F15FCA292C7 +FCA25C18F84A140718F00101150F18E04AEC1FC0EF3F800103ED7F00EE01FE4AEB07F891 +B612E04915809139F8001FF04AEB03FCEE00FE010F157FA24AEC3F80A2011F16C0A25CA2 +133F18804A147FA2017FEDFF005F91C712014C5A494A5A4C5A49EC3FE00001913801FF80 +B748C7FC16F816C036337DB23A>II<010FB612F817FF18C0903B003FC0003FE0EF0FF0EF03F84B6D7E717E027F157F84 +92C81380A24A151F19C05CA21301A25CA21303183F5CA2130719804A157FA2130F19004A +5D60011F1501605C4D5A013F5E17074A4A5A60017F4B5A4DC7FC91C8127E4C5A494A5AEE +0FF049EC3FC000014AB4C8FCB712FC16F093C9FC3A337DB23F>I<010FB712FCA218F890 +3A003FC00007170018785D1838147F183092C8FCA25CA25C16060101020E1370040C1360 +4A1500A20103141C5E5C16F849B5FCA25EECF001010F130016605CA2011F14E05E5CA201 +3F91C8FCA25CA2137FA291CAFCA25BA25B487EB6FCA336337DB231>70 +DI<010F +B5D8C03FB5FCA39026003FE0C713804B1500A24B5CA2027F14016092C7FCA24A1403605C +A201011507605CA20103150F605C91B7FC5B6002F0C7121FA2010F153F605CA2011F157F +95C7FC5CA2013F5D5F5CA2017F14015F91C7FCA24914035F5B00011507B5D8FC03B512F0 +A340337DB240>I<90260FFFE092380FFFC06161D9003FEFE0004F5A19DFDA33F05EF001 +9F0273ED033F97C7FC02631506180C02E35EDAE1F8EC187E14C118300101EE60FE610281 +15C0EF018001031681DA80FC90380301F81400170649ED0C0361010615181730010E017E +140705605B010C15C0A2011C913801800F610118EC030016060138013F141F4C5C01305C +A201704A133F96C8FC01605C6F5A01E05E4C137E000192C7FCD807F016FEB5D8801E9038 +7FFFFC151C150C4A337CB24A>77 D<90260FFFE049B5FCA281D9001F9138000FE04A6CEC +07801900DA33FC1406A2DA71FE140E180C146081DAE07F141C701318ECC03F8201011638 +6F6C133014806F7E010316706F6C136014001503496E13E003015C0106801500010EECFF +0160010CEC7F81A2011CEC3FC395C7FC0118EC1FE3A20138EC0FF717F60130140717FE01 +7014035F01601401A213E0705A1201D807F01578B57E1730A240337DB23D>II<010FB612F017FE83903B +003FC0007FC0EF1FE0EF07F05DEF03F8147FA292C713FCA25CEF07F85CA2010116F0170F +4A15E0EF1FC00103ED3F80EF7F004A14FEEE03FC0107EC1FF091B612C04CC7FC02F0C9FC +130FA25CA2131FA25CA2133FA25CA2137FA291CAFCA25BA25B1201B512FCA336337DB231 +>II<010FB67E17F817FE903A003FC001FF933800 +3FC0EF1FE04B130FEF07F0147FA292C713F8A25CEF0FF05CA20101ED1FE018C04AEC3F80 +18000103157E4C5A4AEB07F0EE3FC049B500FEC7FC16F89138F0007E82010F6E7E707E5C +83131FA25CA2013F141FA25CA2017F143F5F91C7FC180649160E180C49161C00011718B5 +00FC011F133893380FE070040713E0C93803FFC09338007F0037357DB23A>I<03FF1318 +0207EBE038021FEBF87891397F00FCF802FCEB1FF0D901F0130F49481307494813034948 +14E0A249C71201A2013E15C0A3137E1780A2017F91C7FC8080EB3FF014FF15F06D13FE6D +6D7E6D806D80010080020F7F1400150F6F7E150315011500A2120CA2001C5D1218A21501 +00385D003C14035E4B5A007E4A5A007F141F6D49C7FCD87BE0137C39F9FC03F839F07FFF +E0D8E01F138026C003FEC8FC2D377CB42F>I<0003B812F05A18E0903AF0007F000FD80F +8049130390C71401000E5C48EE00C01401121800384A1301A2003001031580127000605C +A20207140300E01700C74990C7FCA2140FA25DA2141FA25DA2143FA25DA2147FA292C9FC +A25CA25CA21301A25CA21303A25C497E001FB512FEA334337FB22D>I<267FFFFE90380F +FFF8A3000190C8EA7F0049153C1738491530A217701203491560A217E01207495DA21601 +120F495DA21603121F4992C7FCA25E123F491406A2160E127F90C8120CA2161C5A481518 +A216381630481570166016E04B5A7E007E4A5A4BC8FC007F140E6C143C6C6C5B6C6C485A +3907F00FC06CB5C9FCC613FCEB1FE035357BB234>II97 +D<133FEA1FFFA25B1200A35BA21201A25BA21203A25BA21207A2EBE0F8EBE3FF390FEF07 +809038FC03C001F813E0EBF001D81FE013F013C0138015F8123FA21300A248130315F012 +7EA2140700FE14E05AA2EC0FC0A2EC1F80007C14005C147E003C137C003E5B381E01F038 +0F07C06CB4C7FCEA00FC1D357EB321>I<147F903803FFC090380FC0F090383F0038137C +4913F83801F0013803E0031207EA0FC090388001F0001F90C7FC123F90C8FCA25A127EA4 +5AA3127C150C151C15386C147015E06CEB03C0390F800F003807C07E3801FFF038007F80 +1E227EA021>II<14FE903807FF8090381F03C090387C01E03801F800485A485A485A485A +1401D83F0013C01403007EEB0F80ECFE00387FFFF8B5128000FCC8FCA45AA415186C1438 +007C147015E0003CEB01C0003EEB07806CEB1E00380F80FC3803FFE0C690C7FC1D227DA0 +24>IIIII +107 DIII<011F131F +90397FC07FE09039E3E1E0F09039C3E380783A01C1F7007CD981FE133CD983FC133E0003 +5BEB03F0163FEA0707120600025B1200010F147F167E5CA2011F14FE16FC5CA2013FEB01 +F8A291380003F016E0491307ED0FC002801380ED1F009038FFC03E9038FEE0F89038FC7F +E0EC1F80000190C8FCA25BA21203A25BA21207A25BB57EA3283083A027>112 +D<903801F803903807FE0790381F071F90387C03BF9038F801BED801F013FE0003130048 +5A4913FC120F485A1401D83F0013F8A3481303007E14F0A300FE13074814E0A3140F15C0 +127C141F143F003CEB7F80003E13FF381E01DF380F07BF3907FE3F00EA00F813005C147E +A314FE5CA21301A25C90387FFFE090B5FCA220307EA022>I<3903E003E0390FF81FF839 +1C7C3C1C0018EB703E39383EE0FE38303FC0EB7F800070EB00FCEA607E157000E01400EA +C0FEEA40FC1200A212015BA312035BA312075BA3120F5BA3121F5B0007C8FC1F227EA023 +>II< +EB0380EB0FC0A3131FA21480A2133FA21400A25BA2137E387FFFFEA2B5FC3800FC00A212 +01A25BA21203A25BA21207A25BA2120FA25B1408001F131C14181380143814701460EB00 +E0EB01C0380F8380EB8700EA07FEEA01F817307FAE1C>I<13F8D803FEEB01C0D8070FEB +03E0000EEB8007121C001813C00038140FEA301F0070018013C01260013F131F00E01300 +00401580C65A017E133F13FE491400A25D120149137E1602EDFE0716064913FCA2160E02 +01130C9039F803F81C1618000090380F7C38D97C1C137090393FF81FE0903907E0078028 +227EA02C>I<01F0130ED803FC131FD8071EEB3F80EA0E1F121C0038EB801F0030140F01 +3F130700701300006014035BD8E07E14001240EA00FE495B000114065BA2150E0003140C +5B151C15181538491330157015606D13E04A5A0001495A6D48C7FC3800FC1EEB3FF8EB07 +E021227EA025>I<90391F801F8090397FE07FE09039E0F0E0703A01C0F9C0F83903807D +833807007F000E1403000C15F0001C137E0018EC01C002FEC7FC00385B1210C7FC13015C +A31303A25C1640010714E016C0001C5B007E1401010F148000FE1403011FEB0700011B13 +0E39F839F01C397070F878393FE07FE0390F801F8025227EA02C>120 +D<13F0D803FCEB01C0D8071EEB03E0D80E1F1307121C003813800030140F013F14C00070 +1300126049131FD8E07E14801240EA00FE49133F000115005BA25D0003147E5BA215FE5D +5BA214015DEBF00314070001130F3900F83FF0EB3FFBEB0FC3EB00075DA20007130FD81F +805B003F495AA24AC7FCEB007E003E137C00385B381803F0381E07C0D807FFC8FCEA01F8 +23317EA026>I<903807800390381FE00790383FF00690387FF80E9038FFFC1C48EBFE78 +9038E03FF03803800190C712E0EC01C0C7EA0380EC0700140E143C14705C495A495A49C7 +FC130E133C0170130C49131C484813184848133848C71278D80EC013F0380FFE03391F3F +FFE0D8381F13C0486C1380D86007130038E003FE38C000F020227DA024>I +E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fp cmssbx10 9 45 +/Fp 45 122 df39 +D44 D +46 D49 DIII<000FB512F84880A65D01F8C8FCAAEB +FBFC90B57E15E08181819038FE0FFEEBF80701F07F13E080D80FC01480C7FCA81218A212 +3C4A1300127E127F486C5A9038E03FFE6CB5FC5D6C5C6C5C6C5C00031480C649C7FCEB1F +F021367DB329>II<007FB61280B712C0A66C15 +80C813005C4A5A4A5A4A5AA24A5A143F4A5A5D14FF5D5B4990C7FCA25B5C130F5CA2131F +5C133FA25C137FA35C13FFA55A5CA96C5B22357DB329>IIII65 D<91380FFF8091B512F8010714FF011F +15C0137F90B7FC5A48168048EBFC01489038E0003F0280130F4890C712074914034848EC +010093C7FC485AA25BA312FF5BAC7F127FA37FA26C7EA26C6C15C06D14016C6D130702E0 +130F6C01FCEB7FE06C90B6FC7E7E7F011F15800107ECFE00010014F8020F13802B367BB4 +35>67 D<007FB512F0B7FC16E016F88216FF17809026E0007F13C0150F030313E06F13F0 +81EE7FF8163FA2EE1FFCA3160F17FEAE17FCA2161FA217F8163F167F17F016FF030313E0 +150F037F13C090B7128017005E16F816E016806C02F8C7FC2F3479B33B>I<007FB612E0 +B712F0A616E001E0C8FCAE90B6FC1680A5160001E0C8FCAE90B612F016F8A76C15F02534 +79B330>I<913807FFC091B512FC010314FF010F15C0013F15F090B7FC5A5A4849C613E0 +4801E0131F4A13074890C71203491401003F1500491540491500127F5BA312FF5BA79238 +1FFFF8A57F127FED001FA27F123F7F7F121F7F6C13C0806C01FE137F6C90B6FC7E7E133F +010F15E0010315800100ECFC00020713802D367CB437>71 DII<007FB512E0B612FEEDFFC08216F882829038E0007FED0FFF81811780 +A281A45DA217005D4B5A157F90B65A5E5E16C093C7FC15F89038E01FFC140F816E7EA26E +7F80826E7FA26F7EA26F7E151F826F7EA26F7EA26F13806F13C0A26C486D13802A3479B3 +35>82 D<007FB712FEB9FCA66C16FEC7D81FFCC7FCB3B3A76E5A30347DB337>84 +D<001FB7FC481680A66C1600C8EA1FFE153F5E4B5A4B5A5C5E4A5B5C4A5B93C7FC4A5A14 +3F5D4A5A4A5A5B5D495B5B5D4990C8FC495A133F5C495A13FF485B5C485B5A5C4890C9FC +485A123F5B48B7FCB81280A66C160029347CB332>90 D97 DIIIII<90393FF801F048B5120F48ECBFF8000F14FF +5A9039F01FF0383A3FE00FF800A248486C7EA96C6C485AA26C6C485A90B5FC6C5C158000 +1D91C7FC381C3FF890C9FC121EA2121F90B512C06C14FC15FF16804815C04815E0387F80 +00ED3FF048C7121F150FA56D131F007F15E06D133F3A3FF801FFC090B6FC000F15006C5C +000114F8D8001F138025347EA229>III<127F487EB1EC07FC +EC0FFEEC3FFCEC7FF8ECFFF0018113E0018313C001871380018F1300EB9FFEEBBFFCEBFF +F05C5C80A2808080A2EBE7FEEBC3FF0181138015C01380EC7FE0EC3FF0EC1FF8A2EC0FFC +EC07FEEC03FFA26C487E20347BB328>107 D +IIIII<143C007F13FCEAFF831387138F +139FA213BF1480EBFE005B13F0A25BA25BB36C5A16237CA21C>114 +DIIII<397F +8003FE38FFC00713E0007FEB0FFC393FF01FF8D81FF813F0380FFC3F0007EB7FE09038FE +FFC06CB512806C14007E6D5A5C6D5A131F6D5A497E497E137F8090B5FC484813800003EB +7FC0EA07FCEC3FE0390FF81FF0D81FF013F8003FEB0FFCEBE007D87FC013FE00FFEB03FF +497E90C7FC20227EA125>120 D<007F147F486C13FF6D5A127F01E013FE003F130313F0 +15FC001F130713F8000F14F8EBFC0F120715F0EBFE1F120315E0EA01FF143F6C14C0A214 +BF017F1380A2EB3FFF15007FA26D5AA313075C1303A2495AA3495AA2495A12C038F07FC0 +B5FC5C91C7FC5B5B6C5AEA1FC020327EA125>I E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fq cmtt9 9 64 +/Fq 64 127 df<00101320007C13F838FE01FCAAEAFC00007C13F8A900381370161778AE +27>34 D<131FEB7FC0497E5A80EA03F1EBE1F8EA07E013C0A513C15C9039C3F1FF80D9E3 +E113C03803E7E3EBEFC101FF1480913881F800EC01F0EA01FEEBFC0301F85B00031307D8 +07FC5B120F381FFE0FD83FBE5BEB3F1FD87E1F90C7FC149F38FC0FBF14FE1307ECFC0201 +03EB0F80EB01F8A238FE03FC387E07FE397F1FFF9F6CB61200149F6CEB0FFE390FFC03FC +3903F000F822307EAE27>38 D40 +D<127012F812FE7E6C7E6C7EEA0FE06C7E12037F6C7E1200137EA27FA2EB1F80A3EB0FC0 +A4EB07E0ACEB0FC0A4EB1F80A3EB3F00A2137EA25B1201485A5B1207485AEA3FC0485A48 +C7FC5A12F81270133A7AB327>I<130F497EA60078EB81E000FEEB87F000FF138FEBDFBF +6CB512E06C14C0000F1400000313FCC613F0A2000313FC000F13FF003F14C04814E039FF +DFBFF0EB1F8F00FE13870078EB81E00000EB8000A66DC7FC1C207BA627>II<120FEA3FC013E0EA7F +F0A213F8A2123FA2120F120113F01203EA07E0121FEA7FC0EAFF8013005A12700D147389 +27>I<007FB512F8B612FCA46C14F81E067C9927>I<121EEA7F80A2EAFFC0A4EA7F80A2EA +1E000A0A728927>I<1538157C15FCA2140115F8140315F0140715E0140F15C0141F1580 +143F1500A25C147E14FE5C13015C13035C13075C130F5CA2131F5C133F91C7FC5B137E13 +FE5B12015B12035BA212075B120F5B121F5B123F90C8FC5A127E12FE5AA25A12781E3A7C +B327>II<130E131FA25B5BA25B5A5A127FB5FCA213BFEA7E3F12 +00B3AA003FB512805A15C01580A21A2F79AE27>IIII<121EEA7F80A2EAFFC0A4EA7F80A2EA +1E00C7FCAC121EEA7F80A2EAFFC0A4EA7F80A2EA1E000A20729F27>58 +D<120FEA3FC0A2EA7FE0A4EA3FC0A2EA0F00C7FCAC120FEA3F8013C0127F13E0A3123FA2 +120F120713C0120FA2EA3F80EA7F005A5A12F812700B2A739F27>I<007FB512FEB7FCA4 +003F14FEC9FCA6003FB512FEB7FCA46C14FE20127D9F27>61 D<127012FC7E6C7E7FEA7F +F0EA1FF86C7EEA03FF6C7F38007FE06D7E6D7EEB07FE6D7E010013C0EC7FE0EC3FF8EC0F +FC1407A2140FEC3FF8EC7FE0ECFFC001031300495AEB1FF8495A495A3801FF804890C7FC +EA0FFC485AEA7FF0EAFFC05B48C8FC5A12701E287CAA27>I64 DI<007FB5FCB612C08115F87E3907E003FCEC +00FE157E157F81A6157EA25D1403EC0FF890B55A15C015F081819038E000FE157FED3F80 +151FA2ED0FC0A6151F1680153FED7F004A5A007FB55AB65A5D15E06C1480222E7FAD27> +I<903803F80E90381FFE1F90383FFFBF90B6FC5A3803FE0F3807F803497E48487E485A49 +137FA248C7123FA25A127E151E150012FE5AAA7E127EA2151E007F143F7EA26C7E157F6D +137E6C6C13FE3907F001FCEBF8033903FE0FF86CB512F06C14E0013F13C06D1300EB03F8 +20307DAE27>I<387FFFFC14FFB612C06C80813907E00FF81407EC01FC6E7EA2157E157F +811680151FA316C0150FABED1F80A3153F1600A25D15FEA24A5A4A5A140F007FB55A5DB6 +5A6C91C7FC14FC222E7FAD27>I<007FB512E0B612F0A36C14E039001F8000B3B2007FB5 +12E0B612F0A36C14E01C2E7BAD27>73 D<387FFFC080B5FC7E5CD803F0C8FCB3AAED0780 +ED0FC0A7007FB6FCA2B7FC7E1680222E7FAD27>76 D<007FB5FCB612E081816C803907E0 +03FEEC00FF81ED3F80151F16C0150FA6151F1680153FED7F005DEC03FE90B55A5D5D5D92 +C7FC01E0C8FCADEA7FFEB5FCA36C5A222E7FAD27>80 DI<387FFFF0B512FE6E7E816C80 +3907E01FF014076E7E1401811400A514015D14034A5A141F90B55A5D5DA281EBE01F6E7E +14076E7EA816F0EDF1F8A4397FFE01FBB5EBFFF08016E06C48EB7FC0C8EA1F00252F7FAD +27>I<90387FC0E03901FFF1F0000713FF5A5AEA3FE0EB801F387F000F007E130712FE5A +1403A3EC01E06C90C7FC127E127FEA3FC013F86CB47E6C13F86C13FE6CEBFF80C614C001 +0F13E0010013F0140FEC07F81403140115FC1400127812FCA46CEB01F8A26C1303903880 +07F09038F01FE090B5FC15C0150000F85B38701FF81E307CAE27>I<007FB61280B712C0 +A439FC03F00FA60078EC0780000091C7FCB3AB90B512C04880A36C5C222E7EAD27>I<3A +7FFC03FFE06D5A00FF15F0007F15E0497E3A07E0007E00A46C6C5BA4EBF80100015CA46C +6C485AA490387E07E0A56D485AA4011F5B149FA3010F90C7FCA5EB07FEA46D5AA26D5A24 +2F7FAD27>86 D<387FFFF0B512F8A314F000FCC7FCB3B3ACB512F014F8A36C13F0153A71 +B327>91 D<387FFFF0B512F8A37EEA0001B3B3ACEA7FFFB5FCA36C13F0153A7EB327>93 +D<007FB512F8B612FCA46C14F81E067C7E27>95 D<3803FFC0000F13F04813FC4813FF81 +1380EC1FC0381F000F000480C71207A2EB0FFF137F0003B5FC120F5A383FFC07EA7FC013 +0012FE5AA46C130F007F131FEBC0FF6CB612806C15C07E000313F1C69038807F8022207C +9F27>97 DIIIII<153F90391FC0FF80D97FF313C048B612E05A4814 +EF390FF07F873A1FC01FC3C0EDC000EB800F48486C7EA66C6C485AEBC01FA2390FF07F80 +90B5C7FC5C485BEB7FF0EB1FC090C9FCA27F6CB5FC15E015F84814FE4880EB8001007EC7 +EA3F80007C140F00FC15C0481407A46C140F007C1580007F143F6C6CEB7F009038F807FF +6CB55A000714F86C5CC614C0D90FFCC7FC23337EA027>II<130F497E497EA46D5A6DC7FC90C8FCA7383FFF8048 +7FA37EEA000FB3A4007FB512F0B6FC15F815F07E1D2F7BAE27>I<143C147E14FFA4147E +143C1400A73801FFFE4813FFA37EC7123FB3B0147E1238007C13FE38FE01FC1303B512F8 +14F06C13E06C13803807FE0018407CAE27>II<387FFF80B57EA37EEA000FB3B2007FB512F8B612FCA3 +6C14F81E2E7CAD27>I<397F07C01F3AFF9FF07FC09039FFF9FFE091B57E7E3A0FFC7FF1 +F89038F03FC001E0138001C01300A3EB803EB03A7FF0FFC3FF486C01E3138001F913E701 +F813E36C4801C313002920819F27>I<387FE07F39FFF1FFC001F713F090B5FC6C800003 +13C1EC01FCEBFE005B5BA25BB03A7FFF83FFE0B500C713F0A36C018313E024207F9F27> +II<387FE0FFD8FFF313C090 +B512F0816C800003EB81FE49C67E49EB3F8049131F16C049130FA216E01507A6150F16C0 +7F151F6DEB3F80157F6DEBFF009038FF83FEECFFFC5D5D01F313C0D9F0FEC7FC91C8FCAC +387FFF80B57EA36C5B23317F9F27>I<90380FF03C90383FFE7E90B5FC000314FE5A380F +FC1F381FE007EBC003383F800148C7FC127EA200FE147E5AA67E007E14FEA2007F1301EA +3F80EBC003381FE007380FF81F6CB5FC7E6C147E38007FFCEB0FF090C7FCAC91381FFFF8 +A24A13FC6E13F8A226317E9F27>I<397FFC03FC39FFFE0FFF023F13804A13C0007F90B5 +FC39007FFE1F14F89138F00F809138E002004AC7FC5CA291C8FCA2137EAD007FB57EB67E +A36C5C22207E9F27>I<9038FFF3800007EBFFC0121F5A5AEB803F38FC000F5AA2EC0780 +6C90C7FCEA7F8013FC383FFFF06C13FC000713FF00011480D8000F13C09038003FE01407 +0078EB03F000FC1301A27E14036CEB07E0EBE01F90B512C01580150000FB13FC38707FF0 +1C207B9F27>I<133C137EA8007FB512F0B612F8A36C14F0D8007EC7FCAE1518157EA415 +FE6D13FC1483ECFFF86D13F06D13E0010313C0010013001F297EA827>I<397FE01FF848 +6C487EA3007F131F00031300B21401A21403EBFC0F6CB612E016F07EEB3FFE90390FF87F +E024207F9F27>I<3A7FFC0FFF80486C4813C0A36C486C13803A07C000F800EBE0010003 +5CA2EBF00300015CA2EBF80700005CA390387C0F80A36D48C7FCA3EB3F3FEB1F3EA214FE +6D5AA36D5AA26D5A22207E9F27>I<3A7FFE07FFE000FF15F06D5A497E007F15E03A0F80 +001F00A36D5B0007143EA414F0EBC1F83903E3FC7CA4EBE79EA200011478A301F713F8A2 +EBFF0F6C5CA3EBFE0790387C03E024207F9F27>I<393FFC1FFF486C5A168016006C487E +3901F807E06C6C485A4A5A017E90C7FC6D5AEB1F7E5C6D5A13076D5A5C80497E130F497E +143EEB3E3FEB7E1F90387C0F8001F87F00016D7E3803F0033A7FFE1FFF80A2B54813C06C +486C1380A222207E9F27>I<3A7FFC0FFF80486C4813C0A36C486C13803A07E000F80000 +0313015D13F00001130301F85B1200A26D485A137CA290387E0F80133EA2011F90C7FC5C +A2130F149E14BE130714FC1303A25C1301A25CA213035CA213075C1208EA3E0F007F5B13 +1FD87E7FC8FCEA7FFE6C5A5B6C5AEA07C022317E9F27>I<001FB512FE4814FFA4903800 +01FEEC03FCEC07F8EC0FF0001EEB1FE0C7EA3FC0EC7F80ECFF00495A495A495AEB1FE049 +5A495A49C7FC485A4848131E4848133F485A485A485A485AB7FCA46C14FE20207E9F27> +II125 D<3901F003803903FC07C0000F130F381FFE1F393FFF7F80397FBFFF +0038FE1FFE486C5A00F813F0387003E01A0A7AAD27>I E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fr cmr9 9 86 +/Fr 86 128 df0 D<91393FE00FE0903A01FFF83FF8903A07E01EF83C90 +3A1F800FF07E903A3F001FE0FE017E133F4914C0485A1738484890381F8000ACB812C0A3 +3B03F0001F8000B3A7486C497EB50083B5FCA32F357FB42D>11 DIII<137813FCA212011203EA07F813E0EA0FC0EA1F801300123C5A5A12 +400E0E71B326>19 D25 +D<123C127E12FFA8127EAB123E123CAB1218A61200A7123C127E12FFA4127E123C08367A +B515>33 D<003C13F0387E01F838FF03FCA2EB83FEA2EA7F81383D80F600011306A40003 +130EEB000CA248131C00061318000E1338000C1330001C13704813E0387001C000601380 +17177EB326>I<017C1503D803FEED078026078780140F260F01C0141F261E00E0EC3F00 +003E01F8147E003C017CEB01FE007C90397F8007FC913933FFFEF800789038307FF900F8 +9039380001F00218495A16075F4C5A161F4CC7FC163E5E023813FC007801305B007C4A5A +EC7003003C01605B003E9038E007C0001EEBC00FD80F015C270787801FC8FC3903FE003F +D8007C133E90C748131F03FCEBFF809239F801E1E0913A01F003C07002039038078030DB +E00F1338DA07C0EB0018020F49131C0380140C91381F001E4A013E130E023E15065C14FC +495A5C495A13075C4948150E011F021E130C91C7121F013E161C017E6E1318017CED8038 +49020713300001923803C07049913801E1E049913800FF806C48ED1F00373C7CB740>37 +D<123C127EB4FCA21380A2127F123D1201A412031300A25A1206120E120C121C5A5A1260 +09177AB315>39 D<14C01301EB0380EB0F00130E5B133C5B5BA2485A485AA212075B120F +90C7FC5AA2121E123EA3123C127CA55AB0127CA5123C123EA3121E121FA27E7F12077F12 +03A26C7E6C7EA213787F131C7F130FEB0380EB01C01300124A79B71E>I<12C07E127012 +3C121C7E120F6C7E6C7EA26C7E6C7EA27F1378137C133C133EA2131E131FA37F1480A5EB +07C0B0EB0F80A514005BA3131E133EA2133C137C137813F85BA2485A485AA2485A48C7FC +120E5A123C12705A5A124A7CB71E>I<156015F0B3A4007FB812C0B912E0A26C17C0C800 +F0C8FCB3A4156033327CAB3C>43 D<123C127EB4FCA21380A2127F123D1201A412031300 +A25A1206120E120C121C5A5A126009177A8715>II<123C127E12 +FFA4127E123C08087A8715>I<1530157815F8A215F01401A215E01403A215C01407A215 +80140FA215005CA2143EA2143C147CA2147814F8A25C1301A25C1303A25C1307A2495AA2 +91C7FC5BA2131E133EA2133C137CA2137813F8A25B1201A25B1203A2485AA25B120FA290 +C8FC5AA2121E123EA2123C127CA2127812F8A25A12601D4B7CB726>II<13075B5B137FEA07FFB5FC13BFEAF83F12 +00B3B3A2497E007FB51280A319327AB126>I +III<000C14C0380FC00F90B512 +8015005C5C14F014C0D80C18C7FC90C8FCA9EB0FC0EB7FF8EBF07C380FC03F9038001F80 +EC0FC0120E000CEB07E0A2C713F01403A215F8A41218127E12FEA315F0140712F8006014 +E01270EC0FC06C131F003C14806CEB7F00380F80FE3807FFF8000113E038003F801D347C +B126>I<14FE903807FF80011F13E090383F00F0017C13703901F801F8EBF003EA03E012 +07EA0FC0EC01F04848C7FCA248C8FCA35A127EEB07F0EB1FFC38FE381F9038700F809038 +E007C039FFC003E0018013F0EC01F8130015FC1400A24814FEA5127EA4127F6C14FCA26C +1301018013F8000F14F0EBC0030007EB07E03903E00FC03901F81F806CB51200EB3FFCEB +0FE01F347DB126>I<1230123C003FB6FCA34814FEA215FC0070C7123800601430157015 +E04814C01401EC0380C7EA07001406140E5C141814385CA25CA2495A1303A3495AA2130F +A3131F91C7FCA25BA55BA9131C20347CB126>III<123C127E12FFA4127E123C1200B0123C +127E12FFA4127E123C08207A9F15>I<123C127E12FFA4127E123C1200B0123C127E12FE +12FFA3127F123F1203A412071206A3120E120C121C1238123012701260082F7A9F15>I< +007FB812C0B912E0A26C17C0CCFCAC007FB812C0B912E0A26C17C033147C9C3C>61 +D<15E0A34A7EA24A7EA34A7EA3EC0DFE140CA2EC187FA34A6C7EA202707FEC601FA202E0 +7FECC00FA2D901807F1507A249486C7EA301066D7EA2010E80010FB5FCA249800118C77E +A24981163FA2496E7EA3496E7EA20001821607487ED81FF04A7ED8FFFE49B512E0A33336 +7DB53A>65 DIIIIIIII<017FB5FCA3 +9038003FE0EC1FC0B3B1127EB4FCA4EC3F805A0060140000705B6C13FE6C485A380F03F0 +3803FFC0C690C7FC20357DB227>IIIIIII82 D<90381FE00390387FFC0748B5FC3907F01FCF390F8003FF +48C7FC003E80814880A200788000F880A46C80A27E92C7FC127F13C0EA3FF013FF6C13F0 +6C13FF6C14C06C14F0C680013F7F01037F9038003FFF140302001380157F153FED1FC015 +0F12C0A21507A37EA26CEC0F80A26C15006C5C6C143E6C147E01C05B39F1FC03F800E0B5 +12E0011F138026C003FEC7FC22377CB42B>I<007FB712FEA390398007F001D87C00EC00 +3E0078161E0070160EA20060160600E01607A3481603A6C71500B3AB4A7E011FB512FCA3 +30337DB237>IIII<267FFFFC90B512C0A30001 +01E090381FF80026007F80EB0FC0013F6E5A6E91C7FC6D6C130E010F140C6E5B6D6C1338 +01035C6E13606D6C13E06D6C485A5EDA7F83C8FCEC3FC715C6EC1FECEC0FFC5D14076E7E +A26E7E815C6F7E9138063FC0140E4A6C7E9138180FF0EC380702707F91386003FCECC001 +0101804A6C7E49C77E4981010E6E7E010C6E7E131C496E7E01786E7E13FCD807FEEC1FFE +B56C90B512F8A335337EB23A>I<003FB612FCA39039F80007F813C090C7EA0FF0003EEC +1FE0123C0038EC3FC00078EC7F801270EDFF004A5AA20060495AA24A5A4A5AC7FC4A5A4A +5AA24A5A4AC7FCA2495A495AA2495A495AA24948130C495AA2495A49C7FCA24848141CA2 +485A485A1638485A4848147816F84848130148481307153FB7FCA326337CB22F>90 +DI<0003130C48131C000E13384813 +7000181360003813E0003013C0EA700100601380A2EAE00300C01300A400DE137800FF13 +FCEB83FEA2EA7F81A2383F00FC001E1378171774B326>II +97 DII<153FEC0FFFA3EC007F81AEEB07F0EB3FFCEBFC0F3901F003 +BF3907E001FF48487E48487F8148C7FCA25A127E12FEAA127E127FA27E6C6C5BA26C6C5B +6C6C4813803A03F007BFFC3900F81E3FEB3FFCD90FE0130026357DB32B>III<151F90391FC07F809039FFF8E3C03901F07FC73907E03F033A0FC01F +83809039800F8000001F80EB00074880A66C5CEB800F000F5CEBC01F6C6C48C7FCEBF07C +380EFFF8380C1FC0001CC9FCA3121EA2121F380FFFFEECFFC06C14F06C14FC4880381F00 +01003EEB007F4880ED1F8048140FA56C141F007C15006C143E6C5C390FC001F83903F007 +E0C6B51280D91FFCC7FC22337EA126>IIIIII<2703F01FE013FF00FF90267FF80313C0903BF1E07C0F +03E0903BF3803E1C01F02807F7003F387FD803FE1470496D486C7EA2495CA2495CB3486C +496C487EB53BC7FFFE3FFFF0A33C217EA041>I<3903F01FC000FFEB7FF09038F1E0FC90 +38F3807C3907F7007EEA03FE497FA25BA25BB3486CEB7F80B538C7FFFCA326217EA02B> +II<3903F03F8000FFEBFFE0 +9038F3C0F89038F7007ED807FE7F6C48EB1F804914C049130F16E0ED07F0A3ED03F8A915 +0716F0A216E0150F16C06D131F6DEB3F80160001FF13FC9038F381F89038F1FFE0D9F07F +C7FC91C8FCAA487EB512C0A325307EA02B>I<903807F00390383FFC07EBFC0F3901F803 +8F3807E001000F14DF48486CB4FC497F123F90C77E5AA25A5AA9127FA36C6C5B121F6D5B +000F5B3907E003BF3903F0073F3800F81EEB3FF8EB0FE090C7FCAAED7F8091380FFFFCA3 +26307DA029>I<3803E07C38FFE1FF9038E38F809038E71FC0EA07EEEA03ECA29038FC0F +8049C7FCA35BB2487EB512E0A31A217FA01E>II<1330A51370A313F0A21201A212031207381FFFFEB5FCA23803F000AF +1403A814073801F806A23800FC0EEB7E1CEB1FF8EB07E0182F7FAD1E>III +II<3A7FFF807FF8A33A07F8001FC00003EC0F800001EC070015066C6C5BA26D131C +017E1318A26D5BA2EC8070011F1360ECC0E0010F5BA2903807E180A214F3010390C7FC14 +FBEB01FEA26D5AA31478A21430A25CA214E05CA2495A1278D8FC03C8FCA21306130EEA70 +1CEA7838EA1FF0EA0FC025307F9F29>I<003FB512F0A2EB000F003C14E00038EB1FC000 +30EB3F800070137F1500006013FE495A13035CC6485A495AA2495A495A49C7FC153013FE +485A12035B48481370485A001F14604913E0485A387F000348130F90B5FCA21C207E9F22 +>II<001C1370387F01FC00FF13FEA4007F13FC381C0070170879 +B226>127 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fs cmr10 10.95 18 +/Fs 18 118 df66 D72 D80 +D<003FB91280A3903AF0007FE001018090393FC0003F48C7ED1FC0007E1707127C007817 +03A300701701A548EF00E0A5C81600B3B14B7E4B7E0107B612FEA33B3D7DBC42>84 +D97 D +I101 D104 DI107 DI<2701F801FE14FF00FF902707FFC00313E091 +3B1E07E00F03F0913B7803F03C01F80007903BE001F87000FC2603F9C06D487F00010180 +5C01FBD900FF147F91C75B13FF4992C7FCA2495CB3A6486C496CECFF80B5D8F87FD9FC3F +13FEA347287DA74C>I<3901F801FE00FF903807FFC091381E07E091387803F000079038 +E001F82603F9C07F0001138001FB6D7E91C7FC13FF5BA25BB3A6486C497EB5D8F87F13FC +A32E287DA733>I<14FF010713E090381F81F890387E007E01F8131F4848EB0F804848EB +07C04848EB03E0000F15F04848EB01F8A2003F15FCA248C812FEA44815FFA96C15FEA36C +6CEB01FCA3001F15F86C6CEB03F0A26C6CEB07E06C6CEB0FC06C6CEB1F80D8007EEB7E00 +90383F81FC90380FFFF0010090C7FC282A7EA82D>I<3901FC03FC00FF90381FFF809138 +7C0FE09039FDE003F03A07FFC001FC6C496C7E6C90C7127F49EC3F805BEE1FC017E0A2EE +0FF0A3EE07F8AAEE0FF0A4EE1FE0A2EE3FC06D1580EE7F007F6E13FE9138C001F89039FD +E007F09039FC780FC0DA3FFFC7FCEC07F891C9FCAD487EB512F8A32D3A7EA733>I<3901 +F807E000FFEB1FF8EC787CECE1FE3807F9C100031381EA01FB1401EC00FC01FF13304913 +00A35BB3A5487EB512FEA31F287EA724>114 D<90383FC0603901FFF8E03807C03F381F +000F003E1307003C1303127C0078130112F81400A27E7E7E6D1300EA7FF8EBFFC06C13F8 +6C13FE6C7F6C1480000114C0D8003F13E0010313F0EB001FEC0FF800E01303A214017E14 +00A27E15F07E14016C14E06CEB03C0903880078039F3E01F0038E0FFFC38C01FE01D2A7D +A824>I117 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Ft cmr12 14.4 17 +/Ft 17 119 df70 +D97 +DII101 D<157F913803FFE0020F13F0 +91383FC0F891387F01FC903901FE03FE903803FC0714F81307EB0FF0A290391FE003FCED +01F892C7FC495AB3B612FEA426003FC0C7FCB3B3A580EBFFF0007FEBFFF8A427547DD324 +>I<1378EA01FE487E487FA66C90C7FC6C5AEA007890C8FCB0EB7F80B5FCA41203C6FC13 +7FB3B3A43801FFE0B61280A419507CCF21>105 D108 D<01FFD907FEEC03FFB590261FFFC0010F13E0 +037F01F0013F13F8912701F80FFC9038FC07FE913D03C003FE01E001FF00039026070001 +9038038000C6010E6D6C48C76C7E6D48DA7F8E6E7E4A159CA24ADA3FF86E7E02605D14E0 +4A5DA34A5DB3AD2601FFE0DAFFF0EC7FF8B6D8C07F9026FFE03FB512F0A45C347CB363> +I<01FFEB07FCB590383FFF8092B512E0913901F00FF8913903C007FC000349C66C7EC601 +0E13016D486D7E5C143002706E7E146014E05CA35CB3AD2601FFE0903801FFE0B600C0B6 +12C0A43A347CB341>II<90397F8007FCB590387FFF8002 +81B512E0913987F00FF891398F8003FC000390399E0001FFC601BC6D7FD97FF86E7E4A6E +7E4A6E7E4A140F844A6E7EA2717EA3717EA4711380AB4D1300A44D5AA24D5AA2606E140F +4D5A6E5D6E4A5A6E4A5A02BC4AC7FC029E495A028FEB07FC913987E01FF00281B512C0DA +807F90C8FCED0FF892CAFCB13801FFE0B612C0A4394B7DB341>I<01FFEB1F80B5EB7FF0 +913801FFF8913803E1FC91380783FE0003EB0F07C6131EEB7F1C1438143091387003FC91 +386000F0160014E05CA45CB3AA8048487EB612F0A427347DB32E>114 +DIIII E +%EndDVIPSBitmapFont +end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%BeginPaperSize: a4 +a4 +%%EndPaperSize + +%%EndSetup +%%Page: 1 1 +1 0 bop 428 85 a Ft(F)-10 b(ast)39 b(m)m(ultiprecision)34 +b(ev)-7 b(aluation)36 b(of)j(series)f(of)g(rational)e(n)m(um)m(b)s(ers) +839 348 y Fs(Bruno)29 b(Haible)883 b(Thomas)30 b(P)m(apanik)m(olaou) +1007 461 y Fr(ILOG)1207 b(Lab)r(oratoire)28 b(A2X)823 +574 y(9,)e(rue)g(de)f(V)-6 b(erdun)859 b(351,)27 b(cours)f(de)g(la)g +(Lib)n(\023)-36 b(eration)675 687 y(F)26 b({)g(94253)h(Gen)n(tilly)f +(Cedex)740 b(F)26 b({)g(33405)h(T)-6 b(alence)27 b(Cedex)830 +799 y Fq(haible@ilog.fr)810 b(papanik@math.u-bordeaux.fr)-152 +1376 y Fp(Abstract)-152 1533 y Fr(W)-6 b(e)26 b(describ)r(e)g(t)n(w)n +(o)g(tec)n(hniques)f(for)h(fast)h(m)n(ultiple-precision)e(ev)l(al-)-152 +1616 y(uation)32 b(of)g(linearly)h(con)n(v)n(ergen)n(t)e(series,)j +(including)e(p)r(o)n(w)n(er)g(series)-152 1699 y(and)26 +b(Raman)n(ujan)f(series.)36 b(The)26 b(computation)f(time)g(for)i +Fo(N)34 b Fr(bits)26 b(is)-152 1782 y Fo(O)r Fr(\(\(log)16 +b Fo(N)8 b Fr(\))180 1750 y Fn(2)215 1782 y Fo(M)g Fr(\()p +Fo(N)g Fr(\)\),)20 b(where)e Fo(M)8 b Fr(\()p Fo(N)g +Fr(\))19 b(is)g(the)f(time)f(needed)h(to)g(m)n(ulti-)-152 +1865 y(ply)g(t)n(w)n(o)g Fo(N)8 b Fr(-bit)17 b(n)n(um)n(b)r(ers.)30 +b(Applications)19 b(include)e(fast)i(algorithms)-152 +1948 y(for)k(elemen)n(tary)f(functions,)h Fo(\031)s Fr(,)g(h)n(yp)r +(ergeometric)f(functions)g(at)h(ra-)-152 2031 y(tional)h(p)r(oin)n(ts,) +g Fo(\020)5 b Fr(\(3\),)23 b(Euler's,)i(Catalan's)g(and)d(Ap)n(\023)-36 +b(ery's)22 b(constan)n(t.)-152 2114 y(The)k(algorithms)h(are)f +(suitable)g(for)h(parallel)g(computation.)-152 2310 y +Fp(1)83 b(Intro)r(duction)-152 2467 y Fr(Multiple-precision)37 +b(ev)l(aluation)f(of)h(real)f(n)n(um)n(b)r(ers)e(has)i(b)r(ecome)-152 +2550 y(e\016cien)n(tly)c(p)r(ossible)h(since)f(Sc)n(h\177)-38 +b(onhage)32 b(and)f(Strassen)h([19)q(])g(ha)n(v)n(e)-152 +2633 y(sho)n(w)n(ed)26 b(that)g(the)f(bit)g(complexit)n(y)g(of)h(the)f +(m)n(ultiplication)h(of)g(t)n(w)n(o)-152 2716 y Fo(N)8 +b Fr(-bit)32 b(n)n(um)n(b)r(ers)e(is)i Fo(M)8 b Fr(\()p +Fo(N)g Fr(\))32 b(=)f Fo(O)r Fr(\()p Fo(N)43 b Fr(log)15 +b Fo(N)42 b Fr(log)15 b(log)g Fo(N)8 b Fr(\).)53 b(This)32 +b(is)-152 2799 y(not)23 b(only)f(a)h(theoretical)h(result;)g(a)f(C++)g +(implemen)n(tation)e([8)q(])i(can)-152 2882 y(exploit)38 +b(this)f(already)g(for)h Fo(N)49 b Fr(=)40 b(40000)e(bits.)69 +b(Algorithms)37 b(for)-152 2965 y(computing)17 b(elemen)n(tary)h +(functions)g(\(exp,)h(log,)i(sin,)f(cos,)h(tan,)f(asin,)-152 +3048 y(acos,)39 b(atan,)f(sinh,)f(cosh,)h(tanh,)f(arsinh,)g(arcosh,)i +(artanh\))34 b(ha)n(v)n(e)-152 3131 y(app)r(eared)22 +b(in)f([4)q(],)i(and)e(a)h(remark)l(able)f(algorithm)g(for)i +Fo(\031)h Fr(w)n(as)e(found)-152 3214 y(b)n(y)j(Bren)n(t)h(and)f +(Salamin)g([18)q(].)-40 3297 y(Ho)n(w)n(ev)n(er,)34 b(all)f(these)f +(algorithms)h(su\013er)f(from)g(the)f(fact)i(that)-152 +3380 y(calculated)24 b(results)g(are)g(not)f(reusable,)h(since)g(the)f +(computation)f(is)-152 3463 y(done)29 b(using)g(real)h(arithmetic)e +(\(using)h(exact)g(rational)h(arithmetic)-152 3546 y(w)n(ould)24 +b(b)r(e)g(extremely)f(ine\016cien)n(t\).)33 b(Therefore)26 +b(functions)e(or)g(con-)-152 3629 y(stan)n(ts)31 b(ha)n(v)n(e)f(to)h(b) +r(e)g(recomputed)e(from)h(the)h(scratc)n(h)g(ev)n(ery)e(time)-152 +3712 y(higher)d(precision)h(is)f(required.)-40 3795 y(In)f(this)g +(note,)g(w)n(e)h(presen)n(t)e(algorithms)i(for)g(fast)f(computation) +-152 3878 y(of)i(sums)e(of)h(the)f(form)400 4093 y Fo(S)g +Fr(=)583 3991 y Fm(1)553 4016 y Fl(X)556 4190 y Fk(n)p +Fn(=0)686 4093 y Fo(R)q Fr(\()p Fo(n)p Fr(\))p Fo(F)11 +b Fr(\(0\))h Fj(\001)h(\001)h(\001)f Fo(F)e Fr(\()p Fo(n)p +Fr(\))-152 4337 y(where)33 b Fo(R)q Fr(\()p Fo(n)p Fr(\))e(and)h +Fo(F)11 b Fr(\()p Fo(n)p Fr(\))32 b(are)g(rational)i(functions)e(in)g +Fo(n)h Fr(with)f(ra-)-152 4421 y(tional)24 b(co)r(e\016cien)n(ts,)h +(pro)n(vided)c(that)i(this)g(sum)e(is)i(linearly)h(con)n(v)n(er-)-152 +4504 y(gen)n(t,)d(i.e.)33 b(that)19 b(the)f Fo(n)p Fr(-th)g(term)g(is)i +Fo(O)r Fr(\()p Fo(c)982 4472 y Fm(\000)p Fk(n)1073 4504 +y Fr(\))f(with)g Fo(c)j(>)f Fr(1.)32 b(Examples)-152 +4587 y(include)19 b(elemen)n(tary)f(and)h(h)n(yp)r(ergeometric)g +(functions)g(at)g(rational)-152 4670 y(p)r(oin)n(ts)25 +b(in)f(the)g Fi(interior)h Fr(of)h(the)e(circle)h(of)g(con)n(v)n +(ergence,)h(as)f(w)n(ell)g(as)-152 4753 y Fo(\031)k Fr(and)c(Euler's,)i +(Catalan's)h(and)d(Ap)n(\023)-36 b(ery's)25 b(constan)n(ts.)2152 +1376 y(The)g(presen)n(ted)f(algorithms)h(are)g Fi(e)l(asy)j(to)f +(implement)d Fr(and)g Fi(ex-)2040 1459 y(tr)l(emely)32 +b(e\016cient)p Fr(,)e(since)g(they)e(tak)n(e)h(adv)l(an)n(tage)g(of)h +(pure)e(in)n(teger)2040 1542 y(arithmetic.)36 b(The)27 +b(calculated)g(results)g(are)g Fi(exact)p Fr(,)h(making)e +Fi(che)l(ck-)2040 1625 y(p)l(ointing)35 b Fr(and)g Fi(r)l(euse)h +Fr(of)g(computations)e(p)r(ossible.)63 b(Finally)-6 b(,)38 +b(the)2040 1708 y(computation)25 b(of)i(our)e(algorithms)i +Fi(c)l(an)h(b)l(e)g(e)l(asily)g(p)l(ar)l(al)t(lelise)l(d)p +Fr(.)2152 1791 y(After)38 b(publishing)f(the)g(presen)n(t)g(pap)r(er,)j +(w)n(e)e(w)n(ere)g(informed)2040 1874 y(that)17 b(the)g(results)g(of)h +(section)g(2)g(w)n(ere)f(already)h(published)f(b)n(y)f(E.)h(Karat-)2040 +1957 y(suba)26 b(in)f([9)q(,)h(10)q(,)g(11,)g(12)q(].)2040 +2153 y Fp(2)82 b(Evaluation)29 b(of)e(linea)n(rly)h(convergent)g +(series)2040 2310 y Fr(The)f(tec)n(hnique)e(presen)n(ted)g(here)i +(applies)g(to)f(all)h(linearly)g(con)n(v)n(er-)2040 2393 +y(gen)n(t)f(sums)e(of)j(the)e(form)2602 2622 y Fo(S)g +Fr(=)2785 2520 y Fm(1)2755 2545 y Fl(X)2758 2719 y Fk(n)p +Fn(=0)2898 2573 y Fo(a)p Fr(\()p Fo(n)p Fr(\))p 2898 +2605 147 4 v 2902 2672 a Fo(b)p Fr(\()p Fo(n)p Fr(\))3065 +2573 y Fo(p)p Fr(\(0\))12 b Fj(\001)h(\001)g(\001)g Fo(p)p +Fr(\()p Fo(n)p Fr(\))p 3065 2605 397 4 v 3067 2672 a +Fo(q)s Fr(\(0\))f Fj(\001)h(\001)g(\001)g Fo(q)s Fr(\()p +Fo(n)p Fr(\))2040 2867 y(where)25 b Fo(a)p Fr(\()p Fo(n)p +Fr(\),)g Fo(b)p Fr(\()p Fo(n)p Fr(\),)h Fo(p)p Fr(\()p +Fo(n)p Fr(\),)f Fo(q)s Fr(\()p Fo(n)p Fr(\))g(are)g(in)n(tegers)h(with) +f Fo(O)r Fr(\(log)15 b Fo(n)p Fr(\))25 b(bits.)2040 2950 +y(The)j(most)g(often)h(used)e(case)i(is)g(that)f Fo(a)p +Fr(\()p Fo(n)p Fr(\),)g Fo(b)p Fr(\()p Fo(n)p Fr(\),)h +Fo(p)p Fr(\()p Fo(n)p Fr(\),)g Fo(q)s Fr(\()p Fo(n)p +Fr(\))f(are)2040 3033 y(p)r(olynomials)e(in)g Fo(n)g +Fr(with)g(in)n(teger)g(co)r(e\016cien)n(ts.)2040 3192 +y Fh(Algorithm:)2152 3352 y Fr(Giv)n(en)g(t)n(w)n(o)g(index)f(b)r +(ounds)g Fo(n)3040 3360 y Fn(1)3101 3352 y Fr(and)h Fo(n)3297 +3360 y Fn(2)3332 3352 y Fr(,)g(consider)g(the)g(partial)2040 +3435 y(sum)2503 3623 y Fo(S)f Fr(=)2734 3546 y Fl(X)2656 +3720 y Fk(n)2694 3730 y Fg(1)2727 3720 y Fm(\024)p Fk(n)e Fr(1.)46 b(Hence)29 b(c)n(ho)r(osing)-152 +109 y Fo(n)-106 117 y Fn(max)32 109 y Fr(=)21 b Fo(N)193 +76 y Fn(log)12 b(2)p 193 92 121 4 v 194 135 a(log)g Fk(c)338 +109 y Fr(+)i Fo(O)r Fr(\(1\))25 b(will)g(ensure)g(that)f(the)g +(round-o\013)f(error)i(is)-152 218 y Fo(<)h Fr(2)-28 +187 y Fm(\000)p Fk(N)78 218 y Fr(.)44 b(By)28 b(our)h(assumption)f +(that)g Fo(a)p Fr(\()p Fo(n)p Fr(\),)i Fo(b)p Fr(\()p +Fo(n)p Fr(\),)f Fo(p)p Fr(\()p Fo(n)p Fr(\),)h Fo(q)s +Fr(\()p Fo(n)p Fr(\))e(are)-152 301 y(in)n(tegers)e(with)f +Fo(O)r Fr(\(log)15 b Fo(n)p Fr(\))25 b(bits,)h(the)e(in)n(tegers)i +Fo(P)11 b Fr(,)24 b Fo(Q)p Fr(,)h Fo(B)t Fr(,)g Fo(T)36 +b Fr(b)r(elong-)-152 384 y(ing)26 b(to)g(the)f(in)n(terv)l(al)g +Fo(n)525 392 y Fn(1)581 384 y Fj(\024)c Fo(n)h(<)f(n)857 +392 y Fn(2)917 384 y Fr(all)27 b(ha)n(v)n(e)d Fo(O)r +Fr(\(\()p Fo(n)1366 392 y Fn(2)1418 384 y Fj(\000)16 +b Fo(n)1540 392 y Fn(1)1575 384 y Fr(\))d(log)i Fo(n)1776 +392 y Fn(2)1811 384 y Fr(\))-152 467 y(bits.)-40 550 +y(The)29 b(algorithm's)g(recursion)g(depth)e(is)i Fo(d)c +Fr(=)1318 517 y Fn(log)12 b Fk(n)1446 525 y Fg(max)p +1318 533 236 4 v 1376 576 a Fn(log)f(2)1582 550 y Fr(+)19 +b Fo(O)r Fr(\(1\).)-152 650 y(A)n(t)36 b(recursion)i(depth)e +Fo(k)j Fr(\(1)h Fj(\024)g Fo(k)i Fj(\024)e Fo(d)p Fr(\),)f(in)n(tegers) +f(ha)n(ving)f(eac)n(h)-152 733 y Fo(O)r Fr(\()-52 701 +y Fk(n)-14 709 y Fg(max)p -51 716 146 4 v -12 762 a Fn(2)18 +748 y Ff(k)117 733 y Fr(log)15 b Fo(n)275 741 y Fn(max)392 +733 y Fr(\))25 b(bits)g(are)g(m)n(ultiplied.)33 b(Th)n(us,)26 +b(the)e(en)n(tire)h(com-)-152 816 y(putation)h(time)f +Fo(t)g Fr(is)157 1042 y Fo(t)75 b Fr(=)438 940 y Fk(d)394 +965 y Fl(X)399 1139 y Fk(k)q Fn(=1)527 1042 y Fr(2)565 +1006 y Fk(k)q Fm(\000)p Fn(1)682 1042 y Fo(O)755 952 +y Fl(\020)805 1042 y Fo(M)900 952 y Fl(\020)959 993 y +Fo(n)1005 1001 y Fn(max)p 959 1025 163 4 v 1003 1092 +a Fr(2)1041 1071 y Fk(k)1145 1042 y Fr(log)15 b Fo(n)1303 +1050 y Fn(max)1420 952 y Fl(\021)o(\021)260 1325 y Fr(=)438 +1224 y Fk(d)394 1249 y Fl(X)399 1423 y Fk(k)q Fn(=1)527 +1325 y Fo(O)g Fr(\()p Fo(M)21 b Fr(\()p Fo(n)801 1333 +y Fn(max)931 1325 y Fr(log)15 b Fo(n)1089 1333 y Fn(max)1206 +1325 y Fr(\))o(\))260 1521 y(=)74 b Fo(O)r Fr(\(log)16 +b Fo(n)643 1529 y Fn(max)760 1521 y Fo(M)8 b Fr(\()p +Fo(n)918 1529 y Fn(max)1047 1521 y Fr(log)15 b Fo(n)1205 +1529 y Fn(max)1322 1521 y Fr(\)\))-152 1671 y(Because)27 +b(of)g Fo(n)276 1679 y Fn(max)414 1671 y Fr(=)21 b Fo(O)r +Fr(\()627 1640 y Fk(N)p 595 1654 118 4 v 595 1696 a Fn(log)12 +b Fk(c)723 1671 y Fr(\))25 b(and)-122 1891 y Fo(M)-26 +1776 y Fl(\022)83 1842 y Fo(N)p 45 1874 146 4 v 45 1941 +a Fr(log)15 b Fo(c)213 1891 y Fr(log)372 1842 y Fo(N)p +335 1874 V 335 1941 a Fr(log)g Fo(c)490 1776 y Fl(\023)626 +1891 y Fr(=)74 b Fo(O)833 1776 y Fl(\022)958 1842 y Fr(1)p +904 1874 V 904 1941 a(log)15 b Fo(c)1060 1891 y(N)21 +b Fr(\(log)15 b Fo(N)8 b Fr(\))1383 1855 y Fn(2)1443 +1891 y Fr(log)15 b(log)g Fo(N)1736 1776 y Fl(\023)626 +2123 y Fr(=)74 b Fo(O)833 2008 y Fl(\022)958 2075 y Fr(1)p +904 2106 V 904 2174 a(log)15 b Fo(c)1072 2123 y Fr(log)g +Fo(N)22 b(M)8 b Fr(\()p Fo(N)g Fr(\))1478 2008 y Fl(\023)-152 +2323 y Fr(w)n(e)26 b(ha)n(v)n(e)356 2449 y Fo(t)21 b +Fr(=)g Fo(O)559 2334 y Fl(\022)684 2401 y Fr(1)p 630 +2432 V 630 2500 a(log)15 b Fo(c)785 2449 y Fr(\(log)g +Fo(N)8 b Fr(\))1026 2414 y Fn(2)1061 2449 y Fo(M)g Fr(\()p +Fo(N)g Fr(\))1272 2334 y Fl(\023)-152 2625 y Fr(Considering)27 +b Fo(c)f Fr(as)g(constan)n(t,)h(this)e(is)h(the)g(desired)g(result.) +-152 2766 y Fh(Chec)n(kp)r(oin)n(ting/P)n(arallelising:)-40 +2907 y Fr(A)f(c)n(hec)n(kp)r(oin)n(t)e(can)i(b)r(e)g(easily)h(done)e(b) +n(y)g(storing)h(the)g(\(in)n(teger\))-152 2990 y(v)l(alues)i(of)g +Fo(n)212 2998 y Fn(1)247 2990 y Fr(,)g Fo(n)341 2998 +y Fn(2)376 2990 y Fr(,)g Fo(P)11 b Fr(,)27 b Fo(Q)p Fr(,)f +Fo(B)k Fr(and)d Fo(T)11 b Fr(.)36 b(Similarly)-6 b(,)27 +b(if)g Fo(m)f Fr(pro)r(cessors)-152 3073 y(are)e(a)n(v)l(ailable,)i +(then)d(the)g(in)n(terv)l(al)g([0)p Fo(;)14 b(n)1028 +3081 y Fk(max)1156 3073 y Fr(])24 b(can)f(b)r(e)h(divided)f(in)n(to) +-152 3156 y Fo(m)d Fr(pieces)g(of)h(length)f Fo(l)j Fr(=)e +Fj(b)p Fo(n)670 3164 y Fk(max)797 3156 y Fo(=m)p Fj(c)p +Fr(.)33 b(After)20 b(eac)n(h)g(pro)r(cessor)h Fo(i)f +Fr(has)-152 3239 y(computed)d(the)h(sum)g(of)h(its)g(in)n(terv)l(al)f +([)p Fo(il)q(;)c Fr(\()p Fo(i)s Fr(+)s(1\))p Fo(l)q Fr(],)20 +b(the)e(partial)i(sums)-152 3322 y(are)35 b(com)n(bined)e(to)i(the)f +(\014nal)g(result)h(using)g(the)f(rules)h(describ)r(ed)-152 +3405 y(ab)r(o)n(v)n(e.)-152 3547 y Fh(Note:)-40 3688 +y Fr(F)-6 b(or)22 b(the)f(sp)r(ecial)i(case)f Fo(a)p +Fr(\()p Fo(n)p Fr(\))f(=)g Fo(b)p Fr(\()p Fo(n)p Fr(\))g(=)g(1,)i(the)e +(binary)g(splitting)-152 3771 y(algorithm)e(has)g(already)g(b)r(een)f +(do)r(cumen)n(ted)f(in)i([3)q(],)h(section)f(6,)i(and)-152 +3854 y([2)q(],)26 b(section)h(10.2.3.)-40 3937 y(Explicit)d +(computation)e(of)i Fo(P)11 b Fr(,)23 b Fo(Q)p Fr(,)h +Fo(B)t Fr(,)f Fo(T)34 b Fr(is)23 b(only)g(required)g(as)g(a)-152 +4020 y(recursion)28 b(base,)f(for)h Fo(n)537 4028 y Fn(2)590 +4020 y Fj(\000)17 b Fo(n)713 4028 y Fn(1)771 4020 y Fo(<)23 +b Fr(2,)k(but)f(a)n(v)n(oiding)h(recursions)h(for)-152 +4103 y Fo(n)-106 4111 y Fn(2)-54 4103 y Fj(\000)17 b +Fo(n)69 4111 y Fn(1)125 4103 y Fo(<)k Fr(5)26 b(gains)h(some)f(p)r +(ercen)n(t)f(of)h(execution)g(sp)r(eed.)-40 4186 y(The)34 +b(binary)f(splitting)i(algorithm)f(is)g(asymptotically)g(faster)-152 +4269 y(than)25 b(step-b)n(y-step)e(ev)l(aluation)i(of)h(the)f(sum)f({)h +(whic)n(h)g(has)g(binary)-152 4352 y(complexit)n(y)36 +b Fo(O)r Fr(\()p Fo(N)409 4320 y Fn(2)445 4352 y Fr(\))h({)g(b)r +(ecause)h(it)f(pushes)g(as)h(m)n(uc)n(h)d(m)n(ultipli-)-152 +4435 y(cation)d(w)n(ork)g(as)g(p)r(ossible)g(to)g(the)f(region)h(where) +g(m)n(ultiplication)-152 4518 y(b)r(ecomes)i(e\016cien)n(t.)59 +b(If)34 b(the)g(m)n(ultiplication)g(w)n(ere)g(implemen)n(ted)-152 +4601 y(as)28 b(an)g Fo(M)8 b Fr(\()p Fo(N)g Fr(\))24 +b(=)g Fo(O)r Fr(\()p Fo(N)531 4569 y Fn(2)566 4601 y +Fr(\))k(algorithm,)g(the)f(binary)g(splitting)h(algo-)-152 +4684 y(rithm)j(w)n(ould)i(pro)n(vide)e(no)h(sp)r(eedup)g(o)n(v)n(er)g +(step-b)n(y-step)e(ev)l(alua-)-152 4767 y(tion.)-152 +4909 y Fh(Implemen)n(tation:)-40 5050 y Fr(In)24 b(the)f(follo)n(wing)k +(w)n(e)e(presen)n(t)e(a)i(simpli\014ed)e(C++)h(implemen-)-152 +5133 y(tation)f(of)g(the)f(ab)r(o)n(v)n(e)g(algorithm)822 +5101 y Fn(1)857 5133 y Fr(.)33 b(The)22 b(initialisation)j(is)e(done)f +(b)n(y)p -152 5171 797 4 v -65 5220 a Fg(1)-33 5245 y +Fe(A)28 b(complete)d(implemen)n(tation)g(can)h(b)r(e)h(found)f(in)h +(CLN)h([8].)45 b(The)27 b(im-)-152 5311 y(plemen)n(tation)21 +b(of)j(the)e(binary-splitting)g(metho)r(d)g(will)h(b)r(e)g(also)g(a)n +(v)l(ailable)g(in)-152 5378 y Fd(LiDIA-1.4)2040 -69 y +Fr(a)29 b(structure)g Fq(abpq)p 2601 -69 24 4 v 29 w(series)i +Fr(con)n(taining)e(arra)n(ys)h Fq(a)p Fr(,)g Fq(b)p Fr(,)h +Fq(p)e Fr(and)g Fq(q)g Fr(of)2040 14 y(m)n(ultiprecision)f(in)n(tegers) +g(\()p Fq(bigint)p Fr(s\).)42 b(The)28 b(v)l(alues)f(of)i(the)e(arra)n +(ys)2040 97 y(at)i(the)e(index)h Fo(n)h Fr(corresp)r(ond)f(to)h(the)f +(v)l(alues)g(of)h(the)f(functions)h Fo(a)p Fr(,)2040 +180 y Fo(b)p Fr(,)23 b Fo(p)e Fr(and)g Fo(q)j Fr(at)e(the)f(in)n(teger) +h(p)r(oin)n(t)g Fo(n)p Fr(.)33 b(The)22 b(\(partial\))g(results)h(of)f +(the)2040 263 y(algorithm)k(are)g(stored)g(in)g(the)f +Fq(abpq)p 3132 263 V 29 w(series)p 3395 263 V 30 w(result)i +Fr(structure.)2040 413 y Fq(//)40 b(abpq_series)i(is)d(initialised)j +(by)e(user)2040 496 y(struct)h({)e(bigint)i(*a,)f(*b,)g(*p,)f(*q;)2315 +579 y(})g(abpq_series;)2040 745 y(//)h(abpq_series_result)j(holds)d +(the)g(partial)h(results)2040 828 y(struct)g({)e(bigint)i(P,)e(Q,)h(B,) +g(T;)2315 911 y(})f(abpq_series_result;)2040 1077 y(//)h(binary)g +(splitting)i(summation)f(for)f(abpq_series)2040 1160 +y(void)g(sum_abpq\(abpq_series_result)46 b(&)39 b(r,)2589 +1243 y(int)h(n1,)g(int)g(n2,)2589 1326 y(const)h(abpq_series)g(&)f +(arg\))2040 1409 y({)2119 1492 y(//)f(check)i(the)f(length)g(of)g(the)g +(summation)h(interval)2119 1575 y(switch)f(\(n2)g(-)g(n1\))2119 +1658 y({)2197 1741 y(case)g(0:)2275 1824 y(error_handler\("summation)45 +b(device",)2629 1907 y("sum_abpq::)c(n2-n1)g(should)f(be)g(>)f(0."\);) +2275 1990 y(break;)2197 2156 y(case)h(1:)g(//)g(the)f(result)i(at)f +(the)g(point)g(n1)2275 2239 y(r.P)g(=)g(arg.p[n1];)2275 +2322 y(r.Q)g(=)g(arg.q[n1];)2275 2405 y(r.B)g(=)g(arg.b[n1];)2275 +2488 y(r.T)g(=)g(arg.a[n1])h(*)f(arg.p[n1];)2275 2571 +y(break;)2197 2737 y(//)g(cases)g(2,)g(3,)f(4)h(left)g(out)g(for)g +(simplicity)2197 2904 y(default:)h(//)f(the)g(general)g(case)2275 +3070 y(//)g(the)g(left)g(and)g(the)g(right)g(partial)h(sum)2275 +3153 y(abpq_series_result)j(L,)39 b(R;)2275 3319 y(//)h(find)g(the)g +(middle)h(of)e(the)h(interval)2275 3402 y(int)g(nm)g(=)g(\(n1)f(+)h +(n2\))g(/)f(2;)2275 3568 y(//)h(sum)g(left)g(side)2275 +3651 y(sum_abpq\(L,)i(n1,)e(nm,)g(arg\);)2275 3817 y(//)g(sum)g(right)g +(side)2275 3900 y(sum_abpq\(R,)i(nm,)e(n2,)g(arg\);)2275 +4066 y(//)g(put)g(together)2275 4149 y(r.P)g(=)g(L.P)g(*)f(R.P;)2275 +4232 y(r.Q)h(=)g(L.Q)g(*)f(R.Q;)2275 4315 y(r.B)h(=)g(L.B)g(*)f(R.B;) +2275 4398 y(r.T)h(=)g(R.B)g(*)f(R.Q)h(*)g(L.T)f(+)h(L.B)g(*)f(L.P)h(*)g +(R.T;)2275 4481 y(break;)2119 4564 y(})2040 4647 y(})2152 +4796 y Fr(Note)30 b(that)f(the)g(m)n(ultiprecision)h(in)n(tegers)g +(could)g(b)r(e)f(replaced)2040 4879 y(here)c(b)n(y)g(in)n(teger)g(p)r +(olynomials,)h(or)g(b)n(y)e(an)n(y)h(other)g(ring)h(pro)n(viding)2040 +4962 y(the)d(op)r(erators)h(=)f(\(assignmen)n(t\),)g(+)g(\(addition\))g +(and)f Fj(\003)i Fr(\(m)n(ultipli-)2040 5045 y(cation\).)42 +b(F)-6 b(or)28 b(example,)g(one)g(could)h(regard)f(a)h(biv)l(ariate)f +(p)r(olyno-)2040 5129 y(mial)j(o)n(v)n(er)f(the)g(in)n(tegers)h(as)g(a) +g(series)h(o)n(v)n(er)e(the)g(second)h(v)l(ariable,)2040 +5212 y(with)j(p)r(olynomials)f(o)n(v)n(er)h(the)e(\014rst)i(v)l +(ariable)f(as)h(its)g(co)r(e\016cien)n(ts.)2040 5295 +y(This)25 b(w)n(ould)g(result)f(an)h(accelerated)h(algorithm)e(for)h +(summing)e(bi-)2040 5378 y(v)l(ariate)j(\(and)f(th)n(us)g(m)n(ultiv)l +(ariate\))g(p)r(olynomials.)p eop +%%Page: 3 3 +3 2 bop -152 -69 a Fp(2.1)83 b(Example:)36 b(The)28 b(facto)n(rial)-152 +63 y Fr(This)36 b(is)g(the)e(most)h(classical)j(example)c(of)i(the)e +(binary)h(splitting)-152 146 y(algorithm)26 b(and)g(w)n(as)g(probably)g +(kno)n(wn)f(long)h(b)r(efore)h([2].)-40 229 y(Computation)j(of)i(the)e +(factorial)i(is)f(b)r(est)f(done)h(using)f(the)g(bi-)-152 +312 y(nary)e(splitting)h(algorithm,)h(com)n(bined)d(with)i(a)g +(reduction)f(of)h(the)-152 395 y(ev)n(en)18 b(factors)h(in)n(to)f(o)r +(dd)g(factors)h(and)f(m)n(ultiplication)g(with)g(a)g(p)r(o)n(w)n(er) +-152 478 y(of)27 b(2,)f(according)h(to)f(the)f(form)n(ula)37 +752 y Fo(n)p Fr(!)d(=)f(2)245 716 y Fk(n)p Fm(\000)p +Fk(\033)367 726 y Fg(2)400 716 y Fn(\()p Fk(n)p Fn(\))507 +752 y Fj(\001)549 675 y Fl(Y)546 849 y Fk(k)q Fm(\025)p +Fn(1)671 587 y Fl(0)671 736 y(@)940 675 y(Y)767 831 y +Ff(n)p 753 840 65 4 v 753 884 a Fg(2)781 872 y Ff(k)828 +851 y Fk(<)p Fn(2)p Fk(m)p Fn(+1)p Fm(\024)1146 831 y +Ff(n)p 1096 840 138 4 v 1096 884 a Fg(2)1124 872 y Ff(k)q +Fc(\000)p Fg(1)1243 752 y Fr(\(2)p Fo(m)c Fr(+)g(1\))1541 +587 y Fl(1)1541 736 y(A)1614 604 y Fk(k)-152 1021 y Fr(and)26 +b(where)g(the)f(pro)r(ducts)341 1198 y Fo(P)11 b Fr(\()p +Fo(n)477 1206 y Fn(1)511 1198 y Fo(;)i(n)591 1206 y Fn(2)626 +1198 y Fr(\))21 b(=)851 1121 y Fl(Y)759 1296 y Fk(n)797 +1306 y Fg(1)829 1296 y Fk()f Fr(0.)61 b(Because)35 b(the)f(series)h(is)g(not)f(only)g +(lin-)-152 3000 y(early)g(con)n(v)n(ergen)n(t)e({)h(exp\()p +Fo(x)p Fr(\))f(is)h(an)g(en)n(tire)g(function)g({,)i +Fo(n)1631 3008 y Fn(max)1781 3000 y Fr(=)-152 3092 y +Fo(O)r Fr(\()107 3061 y Fk(N)p -51 3075 371 4 v -51 3125 +a Fn(log)12 b Fk(N)5 b Fn(+log)260 3105 y Fg(1)p 238 +3114 71 4 v 238 3148 a Fc(j)p Ff(x)p Fc(j)329 3092 y +Fr(\),)26 b(hence)f(the)h(bit)f(complexit)n(y)g(is)387 +3379 y Fo(O)460 3239 y Fl( )638 3330 y Fr(\(log)15 b +Fo(N)8 b Fr(\))879 3298 y Fn(2)p 536 3362 480 4 v 536 +3435 a Fr(log)15 b Fo(N)25 b Fr(+)17 b(log)954 3404 y +Fn(1)p 933 3418 73 4 v 933 3460 a Fm(j)p Fk(x)p Fm(j)1025 +3379 y Fo(M)8 b Fr(\()p Fo(N)g Fr(\))1236 3239 y Fl(!)-152 +3618 y Fr(Considering)27 b Fo(x)e Fr(as)i(constan)n(t,)f(this)g(is)g +Fo(O)r Fr(\(log)15 b Fo(N)26 b(M)8 b Fr(\()p Fo(N)g Fr(\)\).)-152 +3805 y Fp(2.2.2)82 b Fr(exp\()p Fo(x)p Fr(\))26 b Fp(fo)n(r)i(real)f +Fo(x)-152 3936 y Fr(This)j(can)e(b)r(e)h(computed)e(using)i(the)f +(addition)h(theorem)f(for)h(exp,)-152 4019 y(b)n(y)20 +b(a)i(tric)n(k)f(due)f(to)i(Bren)n(t)f([3])h(\(see)f(also)i([2)q(],)f +(section)g(10.2,)i(exercise)-152 4102 y(8\).)35 b(W)-6 +b(rite)568 4329 y Fo(x)21 b Fr(=)g Fo(x)758 4337 y Fn(0)809 +4329 y Fr(+)916 4227 y Fm(1)886 4252 y Fl(X)891 4427 +y Fk(k)q Fn(=0)1029 4281 y Fo(u)1073 4290 y Fk(k)p 1029 +4312 83 4 v 1032 4380 a Fo(v)1069 4389 y Fk(k)-152 4594 +y Fr(with)26 b Fo(x)67 4602 y Fn(0)127 4594 y Fr(in)n(teger,)g +Fo(v)439 4603 y Fk(k)499 4594 y Fr(=)21 b(2)618 4562 +y Fn(2)648 4541 y Ff(k)715 4594 y Fr(and)k Fj(j)p Fo(u)929 +4603 y Fk(k)968 4594 y Fj(j)d Fo(<)f Fr(2)1130 4562 y +Fn(2)1160 4541 y Ff(k)q Fc(\000)p Fg(1)1274 4594 y Fr(,)26 +b(and)f(compute)299 4783 y(exp\()p Fo(x)p Fr(\))20 b(=)h(exp\()p +Fo(x)814 4791 y Fn(0)848 4783 y Fr(\))c Fj(\001)936 4706 +y Fl(Y)933 4880 y Fk(k)q Fm(\025)p Fn(0)1058 4783 y Fr(exp)1188 +4693 y Fl(\020)1248 4734 y Fo(u)1292 4743 y Fk(k)p 1248 +4766 V 1251 4833 a Fo(v)1288 4842 y Fk(k)1340 4693 y +Fl(\021)-40 5028 y Fr(This)27 b(algorithm)f(has)g(bit)f(complexit)n(y) +-31 5272 y Fo(O)43 5132 y Fl( )109 5165 y Fk(O)r Fn(\(log)11 +b Fk(N)5 b Fn(\))168 5195 y Fl(X)173 5369 y Fk(k)q Fn(=0)409 +5223 y Fr(\(log)15 b Fo(N)8 b Fr(\))650 5191 y Fn(2)p +371 5255 352 4 v 371 5322 a Fr(log)15 b Fo(N)25 b Fr(+)17 +b(2)684 5301 y Fk(k)733 5272 y Fo(M)8 b Fr(\()p Fo(N)g +Fr(\))944 5132 y Fl(!)1031 5272 y Fr(=)21 b Fo(O)r Fr(\(\(log)15 +b Fo(N)8 b Fr(\))1443 5236 y Fn(2)1478 5272 y Fo(M)g +Fr(\()p Fo(N)g Fr(\)\))2040 -69 y Fp(2.2.3)110 b Fr(ln\()p +Fo(x)p Fr(\))26 b Fp(fo)n(r)h(rational)i Fo(x)2040 63 +y Fr(F)-6 b(or)28 b(rational)g Fj(j)p Fo(x)18 b Fj(\000)g +Fr(1)p Fj(j)25 b Fo(<)f Fr(1,)29 b(the)e(binary)g(splitting)h +(algorithm)f(can)2040 146 y(also)g(b)r(e)f(applied)g(directly)g(to)f +(the)h(p)r(o)n(w)n(er)g(series)h(for)g(ln\()p Fo(x)p +Fr(\).)34 b(W)-6 b(rite)2040 229 y Fo(x)q Fj(\000)q Fr(1)21 +b(=)2296 198 y Fk(u)p 2296 212 37 4 v 2298 254 a(v)2361 +229 y Fr(and)c(compute)g(the)g(series)i(with)f Fo(a)p +Fr(\()p Fo(n)p Fr(\))j(=)g(1,)f Fo(b)p Fr(\()p Fo(n)p +Fr(\))h(=)g Fo(n)q Fr(+)q(1,)2040 312 y Fo(q)s Fr(\()p +Fo(n)p Fr(\))g(=)h Fo(v)s Fr(,)j Fo(p)p Fr(\(0\))c(=)h +Fo(u)p Fr(,)k(and)f Fo(p)p Fr(\()p Fo(n)p Fr(\))c(=)g +Fj(\000)p Fo(u)k Fr(for)i Fo(n)22 b(>)f Fr(0.)2152 395 +y(This)27 b(algorithm)f(has)f(bit)h(complexit)n(y)e Fo(O)r +Fr(\(\(log)16 b Fo(N)8 b Fr(\))3656 363 y Fn(2)3691 395 +y Fo(M)g Fr(\()p Fo(N)g Fr(\)\).)2040 582 y Fp(2.2.4)82 +b Fr(ln\()p Fo(x)p Fr(\))27 b Fp(fo)n(r)g(real)h Fo(x)2040 +714 y Fr(This)e(can)g(b)r(e)g(computed)e(using)i(the)f(\\in)n(v)n +(erse")h(Bren)n(t)g(tric)n(k:)2152 797 y(Start)g(with)g +Fo(y)d Fr(:=)f(0.)2152 880 y(As)31 b(long)h(as)f Fo(x)f +Fj(6)p Fr(=)g(1)h(within)h(the)e(actual)i(precision,)h(c)n(ho)r(ose)f +Fo(k)2040 971 y Fr(maximal)23 b(with)h Fj(j)p Fo(x)14 +b Fj(\000)g Fr(1)p Fj(j)22 b Fo(<)f Fr(2)2878 939 y Fm(\000)p +Fk(k)2964 971 y Fr(.)34 b(Put)24 b Fo(z)g Fr(=)d(2)3347 +939 y Fm(\000)p Fn(2)p Fk(k)3477 906 y Fl(\002)3512 971 +y Fr(2)3550 939 y Fn(2)p Fk(k)3619 971 y Fr(\()p Fo(x)16 +b Fj(\000)h Fr(1\))3854 906 y Fl(\003)3889 971 y Fr(,)24 +b(i.e.)2040 1062 y(let)h Fo(z)j Fr(con)n(tain)d(the)f(\014rst)h +Fo(k)i Fr(signi\014can)n(t)e(bits)g(of)h Fo(x)15 b Fj(\000)g +Fr(1.)34 b Fo(z)28 b Fr(is)d(a)h(go)r(o)r(d)2040 1145 +y(appro)n(ximation)20 b(for)i(ln\()p Fo(x)p Fr(\).)32 +b(Set)20 b Fo(y)k Fr(:=)d Fo(y)10 b Fr(+)d Fo(z)22 b +Fr(and)f Fo(x)g Fr(:=)g Fo(x)7 b Fj(\001)g Fr(exp)o(\()p +Fj(\000)p Fo(z)s Fr(\).)2152 1228 y(Since)23 b Fo(x)11 +b Fj(\001)g Fr(exp\()p Fo(y)s Fr(\))22 b(is)h(an)g(in)n(v)l(arian)n(t)f +(of)i(the)e(algorithm,)i(the)f(\014nal)2040 1311 y Fo(y)28 +b Fr(is)e(the)g(desired)g(v)l(alue)f(ln\()p Fo(x)p Fr(\).)2152 +1394 y(This)i(algorithm)f(has)f(bit)h(complexit)n(y)2161 +1644 y Fo(O)2235 1504 y Fl( )2300 1538 y Fk(O)r Fn(\(log)11 +b Fk(N)5 b Fn(\))2360 1568 y Fl(X)2365 1742 y Fk(k)q +Fn(=0)2601 1595 y Fr(\(log)14 b Fo(N)8 b Fr(\))2841 1564 +y Fn(2)p 2563 1627 352 4 v 2563 1695 a Fr(log)15 b Fo(N)25 +b Fr(+)17 b(2)2876 1674 y Fk(k)2924 1644 y Fo(M)8 b Fr(\()p +Fo(N)g Fr(\))3135 1504 y Fl(!)3223 1644 y Fr(=)21 b Fo(O)r +Fr(\(\(log)15 b Fo(N)8 b Fr(\))3635 1608 y Fn(2)3670 +1644 y Fo(M)g Fr(\()p Fo(N)g Fr(\)\))2040 1919 y Fp(2.2.5)110 +b Fr(sin\()p Fo(x)p Fr(\))p Fp(,)26 b Fr(cos)q(\()p Fo(x)p +Fr(\))h Fp(fo)n(r)g(rational)h Fo(x)2040 2050 y Fr(These)35 +b(are)g(direct)g(applications)h(of)f(the)f(binary)g(splitting)i(algo-) +2040 2133 y(rithm:)63 b(F)-6 b(or)40 b(sin)q(\()p Fo(x)p +Fr(\),)j(put)d Fo(a)p Fr(\()p Fo(n)p Fr(\))45 b(=)h(1,)e +Fo(b)p Fr(\()p Fo(n)p Fr(\))i(=)f(1,)g Fo(p)p Fr(\(0\))h(=)f +Fo(u)p Fr(,)2040 2216 y Fo(q)s Fr(\(0\))h(=)f Fo(v)s +Fr(,)e(and)d Fo(p)p Fr(\()p Fo(n)p Fr(\))45 b(=)g Fj(\000)p +Fo(u)2993 2185 y Fn(2)3028 2216 y Fr(,)e Fo(q)s Fr(\()p +Fo(n)p Fr(\))j(=)f(\(2)p Fo(n)p Fr(\)\(2)p Fo(n)28 b +Fr(+)e(1\))p Fo(v)3866 2185 y Fn(2)3941 2216 y Fr(for)2040 +2299 y Fo(n)41 b(>)g Fr(0.)70 b(F)-6 b(or)37 b(cos)q(\()p +Fo(x)p Fr(\),)j(put)c Fo(a)p Fr(\()p Fo(n)p Fr(\))41 +b(=)g(1,)f Fo(b)p Fr(\()p Fo(n)p Fr(\))h(=)g(1,)g Fo(p)p +Fr(\(0\))f(=)h(1,)2040 2382 y Fo(q)s Fr(\(0\))22 b(=)f(1,)k(and)g +Fo(p)p Fr(\()p Fo(n)p Fr(\))c(=)g Fj(\000)p Fo(u)2862 +2351 y Fn(2)2897 2382 y Fr(,)k Fo(q)s Fr(\()p Fo(n)p +Fr(\))d(=)f(\(2)p Fo(n)16 b Fj(\000)g Fr(1\)\(2)p Fo(n)p +Fr(\))p Fo(v)3647 2351 y Fn(2)3707 2382 y Fr(for)26 b +Fo(n)c(>)f Fr(0.)2040 2465 y(Of)39 b(course,)j(when)c(b)r(oth)g(sin\()p +Fo(x)p Fr(\))g(and)g(cos)q(\()p Fo(x)p Fr(\))f(are)i(needed,)i(one)2040 +2548 y(should)25 b(only)g(compute)f(sin\()p Fo(x)p Fr(\))g(this)h(w)n +(a)n(y)-6 b(,)25 b(and)g(then)f(set)h(cos)q(\()p Fo(x)p +Fr(\))c(=)2040 2651 y Fj(\006)2100 2582 y Fl(p)p 2183 +2582 365 4 v 69 x Fr(1)c Fj(\000)g Fr(sin\()p Fo(x)p +Fr(\))2513 2630 y Fn(2)2547 2651 y Fr(.)35 b(This)26 +b(is)g(a)g(20\045)h(sp)r(eedup)e(at)h(least.)2152 2743 +y(The)18 b(bit)e(complexit)n(y)g(of)i(these)f(algorithms)h(is)g +Fo(O)r Fr(\(log)d Fo(N)8 b(M)g Fr(\()p Fo(N)g Fr(\)\).)2040 +2930 y Fp(2.2.6)110 b Fr(sin\()p Fo(x)p Fr(\))p Fp(,)26 +b Fr(cos)q(\()p Fo(x)p Fr(\))h Fp(fo)n(r)g(real)h Fo(x)2040 +3062 y Fr(T)-6 b(o)37 b(compute)f(cos\()p Fo(x)p Fr(\))24 +b(+)g Fo(i)13 b Fr(sin)q(\()p Fo(x)p Fr(\))38 b(=)i(exp)o(\()p +Fo(ix)p Fr(\))c(for)i(real)f Fo(x)p Fr(,)i(again)2040 +3145 y(the)30 b(addition)g(theorems)g(and)g(Bren)n(t's)h(tric)n(k)f +(can)g(b)r(e)g(used.)48 b(The)2040 3228 y(resulting)26 +b(algorithm)g(has)g(bit)g(complexit)n(y)e Fo(O)r Fr(\(\(log)16 +b Fo(N)8 b Fr(\))3685 3196 y Fn(2)3719 3228 y Fo(M)g +Fr(\()p Fo(N)g Fr(\)\).)2040 3415 y Fp(2.2.7)110 b Fr(arctan\()p +Fo(x)p Fr(\))27 b Fp(fo)n(r)g(rational)h Fo(x)2040 3547 +y Fr(F)-6 b(or)30 b(rational)g Fj(j)p Fo(x)p Fj(j)e Fo(<)f +Fr(1,)k(the)e(fastest)i(w)n(a)n(y)e(to)h(compute)e(arctan\()p +Fo(x)p Fr(\))2040 3630 y(with)19 b(bit)g(complexit)n(y)e +Fo(O)r Fr(\(\(log)e Fo(N)8 b Fr(\))3035 3598 y Fn(2)3070 +3630 y Fo(M)g Fr(\()p Fo(N)g Fr(\)\))19 b(is)h(to)e(apply)h(the)f +(binary)2040 3713 y(splitting)i(algorithm)f(directly)h(to)f(the)g(p)r +(o)n(w)n(er)g(series)i(for)f(arctan\()p Fo(x)p Fr(\).)2040 +3796 y(Put)37 b Fo(a)p Fr(\()p Fo(n)p Fr(\))k(=)f(1,)i +Fo(b)p Fr(\()p Fo(n)p Fr(\))e(=)h(2)p Fo(n)26 b Fr(+)e(1,)41 +b Fo(q)s Fr(\()p Fo(n)p Fr(\))g(=)g(1,)g Fo(p)p Fr(\(0\))f(=)h +Fo(x)c Fr(and)2040 3879 y Fo(p)p Fr(\()p Fo(n)p Fr(\))21 +b(=)g Fj(\000)p Fo(x)2391 3847 y Fn(2)2451 3879 y Fr(for)26 +b Fo(n)c(>)f Fr(0.)2040 4066 y Fp(2.2.8)110 b Fr(arctan\()p +Fo(x)p Fr(\))27 b Fp(fo)n(r)g(real)h Fo(x)2040 4197 y +Fr(This)22 b(again)g(can)f(b)r(e)g(computed)f(using)h(the)g(\\in)n(v)n +(erse")h(Bren)n(t)f(tric)n(k:)2152 4280 y(Start)g(out)g(with)g +Fo(z)k Fr(:=)2908 4250 y Fn(1)p 2819 4264 209 4 v 2819 +4273 a Fj(p)p 2883 4273 145 4 v 55 x Fn(1+)p Fk(x)2995 +4314 y Fg(2)3045 4280 y Fr(+)8 b Fo(i)3235 4250 y Fk(x)p +3149 4264 209 4 v 3149 4273 a Fj(p)p 3213 4273 145 4 +v 55 x Fn(1+)p Fk(x)3325 4314 y Fg(2)3388 4280 y Fr(and)21 +b Fo(')g Fr(:=)h(0.)33 b(During)2040 4409 y(the)26 b(algorithm)g +Fo(z)j Fr(will)e(b)r(e)f(a)h(complex)e(n)n(um)n(b)r(er)f(with)i +Fj(j)p Fo(z)s Fj(j)d Fr(=)f(1)k(and)2040 4492 y(Re\()p +Fo(z)s Fr(\))21 b Fo(>)g Fr(0.)2152 4575 y(As)j(long)h(as)g(Im)n(\()p +Fo(z)s Fr(\))c Fj(6)p Fr(=)g(0)k(within)f(the)g(actual)h(precision,)h +(c)n(ho)r(ose)2040 4671 y Fo(k)31 b Fr(maximal)c(with)i +Fj(j)13 b Fr(Im)n(\()p Fo(z)s Fr(\))p Fj(j)26 b Fo(<)g +Fr(2)3000 4639 y Fm(\000)p Fk(k)3087 4671 y Fr(.)42 b(Put)28 +b Fo(\013)f Fr(=)e(2)3502 4639 y Fm(\000)p Fn(2)p Fk(k)3632 +4605 y Fl(\002)3667 4671 y Fr(2)3705 4639 y Fn(2)p Fk(k)3786 +4671 y Fr(Im)o(\()p Fo(z)s Fr(\))3977 4605 y Fl(\003)4011 +4671 y Fr(,)2040 4766 y(i.e.)36 b(let)27 b Fo(\013)f +Fr(con)n(tain)g(the)g(\014rst)g Fo(k)i Fr(signi\014can)n(t)f(bits)f(of) +g(Im)o(\()p Fo(z)s Fr(\).)35 b Fo(\013)27 b Fr(is)f(a)2040 +4849 y(go)r(o)r(d)j(appro)n(ximation)e(for)h(arcsin)q(\(Im)o(\()p +Fo(z)s Fr(\)\).)39 b(Set)27 b Fo(')e Fr(:=)g Fo(')18 +b Fr(+)g Fo(\013)28 b Fr(and)2040 4932 y Fo(z)c Fr(:=)e +Fo(z)e Fj(\001)d Fr(exp\()p Fj(\000)p Fo(i\013)p Fr(\).)2152 +5015 y(Since)j Fo(z)10 b Fj(\001)c Fr(exp\()p Fo(i')p +Fr(\))20 b(is)h(an)f(in)n(v)l(arian)n(t)g(of)i(the)e(algorithm,)i(the)e +(\014nal)2040 5098 y Fo(')26 b Fr(is)g(the)f(desired)h(v)l(alue)g +(arcsin)3091 5067 y Fk(x)p 3004 5081 209 4 v 3004 5091 +a Fj(p)p 3068 5091 145 4 v 55 x Fn(1+)p Fk(x)3180 5132 +y Fg(2)3222 5098 y Fr(.)p eop +%%Page: 4 4 +4 3 bop -40 -69 a Fr(This)27 b(algorithm)f(has)g(bit)f(complexit)n(y) +-31 164 y Fo(O)43 24 y Fl( )109 57 y Fk(O)r Fn(\(log)11 +b Fk(N)5 b Fn(\))168 87 y Fl(X)173 262 y Fk(k)q Fn(=0)409 +115 y Fr(\(log)15 b Fo(N)8 b Fr(\))650 83 y Fn(2)p 371 +147 352 4 v 371 215 a Fr(log)15 b Fo(N)25 b Fr(+)17 b(2)684 +193 y Fk(k)733 164 y Fo(M)8 b Fr(\()p Fo(N)g Fr(\))944 +24 y Fl(!)1031 164 y Fr(=)21 b Fo(O)r Fr(\(\(log)15 b +Fo(N)8 b Fr(\))1443 128 y Fn(2)1478 164 y Fo(M)g Fr(\()p +Fo(N)g Fr(\)\))-152 436 y Fp(2.2.9)82 b Fr(sinh\()p Fo(x)p +Fr(\))p Fp(,)27 b Fr(cosh\()p Fo(x)p Fr(\))g Fp(fo)n(r)g(rational)h +(and)g(real)f Fo(x)-152 567 y Fr(These)f(can)e(b)r(e)h(computed)e(b)n +(y)g(similar)j(algorithms)f(as)g(sin\()p Fo(x)p Fr(\))f(and)-152 +650 y(cos)q(\()p Fo(x)p Fr(\))c(ab)r(o)n(v)n(e,)h(with)g(the)f(same)g +(asymptotic)f(bit)h(complexit)n(y)-6 b(.)32 b(The)-152 +733 y(standard)26 b(computation,)f(using)g(exp)o(\()p +Fo(x)p Fr(\))g(and)g(its)h(recipro)r(cal)h(\(cal-)-152 +816 y(culated)37 b(b)n(y)f(the)h(Newton)f(metho)r(d\))g(results)h(also) +i(to)e(the)f(same)-152 899 y(complexit)n(y)25 b(and)g(w)n(orks)h +(equally)g(w)n(ell)h(in)e(practice.)-40 982 y(The)20 +b(bit)f(complexit)n(y)e(of)j(these)f(algorithms)h(is)g +Fo(O)r Fr(\(log)15 b Fo(N)d(M)c Fr(\()p Fo(N)g Fr(\)\))-152 +1065 y(for)27 b(rational)g Fo(x)e Fr(and)g Fo(O)r Fr(\(\(log)16 +b Fo(N)8 b Fr(\))802 1034 y Fn(2)836 1065 y Fo(M)g Fr(\()p +Fo(N)g Fr(\)\))26 b(for)h(real)f Fo(x)p Fr(.)-152 1250 +y Fp(2.3)83 b(Example:)32 b(Hyp)r(ergeometric)19 b(functions)f(at)h +(rational)g(p)r(oints)-152 1381 y Fr(The)26 b(binary)e(splitting)i +(algorithm)f(is)h(w)n(ell)g(suited)f(for)g(the)g(ev)l(alua-)-152 +1464 y(tion)h(of)h(a)f(h)n(yp)r(ergeometric)f(series)140 +1676 y Fo(F)213 1561 y Fl(\022)311 1632 y Fo(a)352 1640 +y Fn(1)387 1632 y Fo(;)75 b(:)13 b(:)g(:)g(;)75 b(a)722 +1640 y Fk(r)315 1716 y Fo(b)348 1724 y Fn(1)383 1716 +y Fo(;)k(:)13 b(:)g(:)g(;)80 b(b)719 1724 y Fk(s)794 +1608 y Fl(\014)794 1657 y(\014)822 1676 y Fo(x)866 1561 +y Fl(\023)947 1676 y Fr(=)1058 1574 y Fm(1)1029 1599 +y Fl(X)1031 1774 y Fk(n)p Fn(=0)1171 1628 y Fo(a)p 1212 +1565 43 4 v -32 x Fk(n)1212 1641 y Fn(1)1267 1628 y Fj(\001)13 +b(\001)g(\001)h Fo(a)p 1411 1565 V -32 x Fk(n)1411 1641 +y(r)p 1171 1659 282 4 v 1179 1733 a Fo(b)p 1212 1676 +43 4 v -26 x Fk(n)1212 1752 y Fn(1)1267 1733 y Fj(\001)f(\001)g(\001)h +Fo(b)p 1403 1676 V -26 x Fk(n)1403 1742 y(s)1463 1676 +y Fo(x)1507 1640 y Fk(n)-152 1900 y Fr(with)30 b(rational)i(co)r +(e\016cien)n(ts)f Fo(a)752 1908 y Fn(1)786 1900 y Fr(,)g(...,)h +Fo(a)995 1908 y Fk(r)1030 1900 y Fr(,)f Fo(b)1115 1908 +y Fn(1)1150 1900 y Fr(,)g(...,)h Fo(b)1351 1908 y Fk(s)1414 +1900 y Fr(at)e(a)g(rational)-152 1983 y(p)r(oin)n(t)36 +b Fo(x)g Fr(in)g(the)f(in)n(terior)i(of)g(the)f(circle)h(of)g(con)n(v)n +(ergence.)66 b(Just)-152 2079 y(put)38 b Fo(a)p Fr(\()p +Fo(n)p Fr(\))k(=)g(1,)g Fo(b)p Fr(\()p Fo(n)p Fr(\))g(=)g(1,)g +Fo(p)p Fr(\(0\))g(=)g Fo(q)s Fr(\(0\))g(=)g(1,)g(and)1611 +2043 y Fk(p)p Fn(\()p Fk(n)p Fn(\))p 1611 2062 119 4 +v 1612 2104 a Fk(q)r Fn(\()p Fk(n)p Fn(\))1781 2079 y +Fr(=)-142 2162 y Fn(\()p Fk(a)-84 2172 y Fg(1)-52 2162 +y Fn(+)p Fk(n)p Fm(\000)p Fn(1\))p Fm(\001\001\001)p +Fn(\()p Fk(a)250 2170 y Ff(r)283 2162 y Fn(+)p Fk(n)p +Fm(\000)p Fn(1\))p Fk(x)p -142 2182 648 4 v -117 2224 +a Fn(\()p Fk(b)-66 2234 y Fg(1)-34 2224 y Fn(+)p Fk(n)p +Fm(\000)p Fn(1\))p Fm(\001\001\001)p Fn(\()p Fk(b)261 +2232 y Ff(s)294 2224 y Fn(+)p Fk(n)p Fm(\000)p Fn(1\))543 +2199 y Fr(for)28 b Fo(n)d(>)g Fr(0.)40 b(The)28 b(ev)l(aluation)g(can)g +(th)n(us)f(b)r(e)-152 2309 y(done)k(with)f(bit)h(complexit)n(y)e +Fo(O)r Fr(\(\(log)15 b Fo(N)8 b Fr(\))1067 2277 y Fn(2)1102 +2309 y Fo(M)g Fr(\()p Fo(N)g Fr(\)\))31 b(for)g Fo(r)g +Fr(=)e Fo(s)h Fr(and)-152 2392 y Fo(O)r Fr(\(log)16 b +Fo(N)25 b(M)8 b Fr(\()p Fo(N)g Fr(\)\))26 b(for)h Fo(r)c(<)e(s)p +Fr(.)-152 2576 y Fp(2.4)83 b(Example:)36 b Fo(\031)-152 +2707 y Fr(The)26 b(Raman)n(ujan)f(series)i(for)f Fo(\031)260 +2871 y Fr(1)p 256 2902 47 4 v 256 2970 a Fo(\031)334 +2919 y Fr(=)465 2871 y(12)p 425 2902 157 4 v 425 2971 +a Fo(C)485 2950 y Fn(3)p Fk(=)p Fn(2)634 2818 y Fm(1)605 +2842 y Fl(X)607 3017 y Fk(n)p Fn(=0)748 2870 y Fr(\()p +Fj(\000)p Fr(1\))906 2839 y Fk(n)948 2870 y Fr(\(6)p +Fo(n)p Fr(\)!\()p Fo(A)17 b Fr(+)g Fo(nB)t Fr(\))p 748 +2902 686 4 v 890 2970 a(\(3)p Fo(n)p Fr(\)!)p Fo(n)p +Fr(!)1122 2948 y Fn(3)1158 2970 y Fo(C)1218 2948 y Fn(3)p +Fk(n)-152 3143 y Fr(with)36 b Fo(A)h Fr(=)g(13591409,)k +Fo(B)g Fr(=)c(545140134,)k Fo(C)h Fr(=)37 b(640320)h(found)-152 +3226 y(b)n(y)i(the)h(Ch)n(udno)n(vsky's)623 3194 y Fn(2)699 +3226 y Fr(and)g(whic)n(h)g(is)h(used)e(b)n(y)h(the)f +Fb(LiDIA)-152 3309 y Fr([16)q(,)32 b(15)q(,)g(13)q(])g(and)f(the)h(P)n +(ari)g([7)q(])g(system)f(to)h(compute)e Fo(\031)s Fr(,)j(is)g(usu-)-152 +3392 y(ally)i(written)f(as)h(an)e(algorithm)i(of)f(bit)g(complexit)n(y) +f Fo(O)r Fr(\()p Fo(N)1638 3360 y Fn(2)1673 3392 y Fr(\).)59 +b(It)-152 3475 y(is,)34 b(ho)n(w)n(ev)n(er,)f(p)r(ossible)g(to)f(apply) +f(binary)g(splitting)h(to)f(the)h(sum.)-152 3558 y(Put)j +Fo(a)p Fr(\()p Fo(n)p Fr(\))h(=)g Fo(A)23 b Fr(+)g Fo(nB)t +Fr(,)38 b Fo(b)p Fr(\()p Fo(n)p Fr(\))e(=)g(1,)i Fo(p)p +Fr(\(0\))e(=)h(1,)g Fo(q)s Fr(\(0\))g(=)f(1,)i(and)-152 +3641 y Fo(p)p Fr(\()p Fo(n)p Fr(\))j(=)g Fj(\000)p Fr(\(6)p +Fo(n)26 b Fj(\000)e Fr(5\)\(2)p Fo(n)i Fj(\000)f Fr(1\)\(6)p +Fo(n)h Fj(\000)f Fr(1\),)41 b Fo(q)s Fr(\()p Fo(n)p Fr(\))g(=)h +Fo(n)1467 3609 y Fn(3)1501 3641 y Fo(C)1561 3609 y Fn(3)1596 +3641 y Fo(=)p Fr(24)d(for)-152 3724 y Fo(n)30 b(>)f Fr(0.)50 +b(This)31 b(reduces)g(the)f(complexit)n(y)f(to)i Fo(O)r +Fr(\(\(log)15 b Fo(N)8 b Fr(\))1543 3692 y Fn(2)1578 +3724 y Fo(M)g Fr(\()p Fo(N)g Fr(\)\).)-152 3807 y(Although)32 +b(this)g(is)h(theoretically)h(slo)n(w)n(er)f(than)f(Bren)n(t-Salamin's) +-152 3890 y(quadratically)41 b(con)n(v)n(ergen)n(t)f(iteration,)46 +b(whic)n(h)41 b(has)g(a)f(bit)h(com-)-152 3973 y(plexit)n(y)34 +b(of)h Fo(O)r Fr(\(log)15 b Fo(N)32 b(M)8 b Fr(\()p Fo(N)g +Fr(\)\),)37 b(in)d(practice)h(the)f(binary)g(splitted)-152 +4056 y(Raman)n(ujan)d(sum)g(is)i(three)f(times)f(faster)j(than)d(Bren)n +(t-Salamin,)-152 4139 y(at)g(least)g(in)f(the)g(range)h(from)f +Fo(N)37 b Fr(=)29 b(1000)i(bits)g(to)f Fo(N)37 b Fr(=)29 +b(1000000)-152 4222 y(bits.)-152 4407 y Fp(2.5)83 b(Example:)36 +b(Catalan's)28 b(constant)f Fo(G)-152 4538 y Fr(A)f(linearly)g(con)n(v) +n(ergen)n(t)f(sum)g(for)h(Catalan's)i(constan)n(t)521 +4750 y Fo(G)21 b Fr(:=)734 4648 y Fm(1)705 4673 y Fl(X)707 +4847 y Fk(n)p Fn(=0)903 4701 y Fr(\()p Fj(\000)p Fr(1\))1061 +4669 y Fk(n)p 847 4733 312 4 v 847 4801 a Fr(\(2)p Fo(n)d +Fr(+)f(1\))1124 4779 y Fn(2)-152 4978 y Fr(is)27 b(giv)n(en)e(in)h +([2],)h(p.)34 b(386:)140 5194 y Fo(G)21 b Fr(=)312 5145 +y(3)p 312 5177 39 4 v 312 5244 a(8)403 5092 y Fm(1)374 +5117 y Fl(X)376 5291 y Fk(n)p Fn(=0)725 5145 y Fr(1)p +516 5177 457 4 v 516 5190 a Fl(\000)554 5221 y Fn(2)p +Fk(n)570 5280 y(n)623 5190 y Fl(\001)661 5255 y Fr(\(2)p +Fo(n)d Fr(+)f(1\))938 5234 y Fn(2)999 5194 y Fr(+)1086 +5145 y Fo(\031)p 1086 5177 47 4 v 1090 5244 a Fr(8)1156 +5194 y(log)r(\(2)g(+)1417 5128 y Fj(p)p 1481 5128 39 +4 v 66 x Fr(3\))p -152 5304 797 4 v -65 5353 a Fg(2)-33 +5378 y Fe(A)23 b(sp)r(ecial)e(case)g(of)i([2)o(],)f(form)n(ula)g +(\(5.5.18\),)g(with)g(N=163.)2152 -69 y Fr(The)c(series)g(is)g(summed)c +(using)k(binary)e(splitting,)k(putting)d Fo(a)p Fr(\()p +Fo(n)p Fr(\))k(=)2040 14 y(1,)44 b Fo(b)p Fr(\()p Fo(n)p +Fr(\))h(=)f(2)p Fo(n)27 b Fr(+)g(1,)44 b Fo(p)p Fr(\(0\))g(=)g(1,)g +Fo(q)s Fr(\(0\))h(=)g(1,)f(and)39 b Fo(p)p Fr(\()p Fo(n)p +Fr(\))44 b(=)h Fo(n)p Fr(,)2040 97 y Fo(q)s Fr(\()p Fo(n)p +Fr(\))40 b(=)g(2\(2)p Fo(n)26 b Fr(+)e(1\))37 b(for)h +Fo(n)j(>)e Fr(0.)69 b(Th)n(us)37 b Fo(G)g Fr(can)g(b)r(e)g(computed) +2040 180 y(with)26 b(bit)f(complexit)n(y)g Fo(O)r Fr(\(\(log)15 +b Fo(N)8 b Fr(\))3056 149 y Fn(2)3091 180 y Fo(M)g Fr(\()p +Fo(N)g Fr(\)\).)2040 368 y Fp(2.6)82 b(Example:)37 b(The)27 +b(Gamma)h(function)f(at)h(rational)g(p)r(oints)2040 499 +y Fr(F)-6 b(or)31 b(ev)l(aluating)f(\000\()p Fo(s)p Fr(\))g(for)i +(rational)f Fo(s)p Fr(,)h(w)n(e)f(\014rst)f(reduce)g +Fo(s)g Fr(to)h(the)2040 582 y(range)38 b(1)i Fj(\024)g +Fo(s)g Fj(\024)g Fr(2)e(b)n(y)e(the)g(form)n(ula)h(\000\()p +Fo(s)25 b Fr(+)f(1\))40 b(=)g Fo(s)p Fr(\000\()p Fo(s)p +Fr(\).)68 b(T)-6 b(o)2040 665 y(compute)28 b(\000\()p +Fo(s)p Fr(\))g(with)h(a)g(precision)h(of)g Fo(N)37 b +Fr(bits,)30 b(c)n(ho)r(ose)g(a)f(p)r(ositiv)n(e)2040 +758 y(in)n(teger)22 b Fo(x)f Fr(with)h Fo(xe)2606 726 +y Fm(\000)p Fk(x)2713 758 y Fo(<)f Fr(2)2832 726 y Fm(\000)p +Fk(N)2939 758 y Fr(.)33 b(P)n(artial)23 b(in)n(tegration)f(lets)g(us)g +(write)2075 1036 y(\000\()p Fo(s)p Fr(\))74 b(=)2428 +925 y Fl(Z)2511 946 y Fm(1)2474 1114 y Fn(0)2589 1036 +y Fo(e)2625 1000 y Fm(\000)p Fk(t)2700 1036 y Fo(t)2728 +1000 y Fk(s)p Fm(\000)p Fn(1)2840 1036 y Fo(dt)2293 1278 +y Fr(=)h Fo(x)2472 1242 y Fk(s)2505 1278 y Fo(e)2541 +1242 y Fm(\000)p Fk(x)2687 1177 y Fm(1)2657 1202 y Fl(X)2659 +1376 y Fk(n)p Fn(=0)3064 1230 y Fo(x)3108 1198 y Fk(n)p +2800 1261 615 4 v 2800 1329 a Fo(s)p Fr(\()p Fo(s)16 +b Fr(+)h(1\))c Fj(\001)g(\001)g(\001)h Fr(\()p Fo(s)i +Fr(+)h Fo(n)p Fr(\))3441 1278 y(+)3518 1167 y Fl(Z)3601 +1188 y Fm(1)3564 1356 y Fk(x)3679 1278 y Fo(e)3715 1242 +y Fm(\000)p Fk(t)3791 1278 y Fo(t)3819 1242 y Fk(s)p +Fm(\000)p Fn(1)3930 1278 y Fo(dt)2040 1575 y Fr(The)36 +b(last)g(in)n(tegral)g(is)g Fo(<)h(xe)2916 1543 y Fm(\000)p +Fk(x)3039 1575 y Fo(<)g Fr(2)3174 1543 y Fm(\000)p Fk(N)3280 +1575 y Fr(.)63 b(The)36 b(series)g(is)g(ev)l(alu-)2040 +1658 y(ated)h(as)g(a)g(h)n(yp)r(ergeometric)g(function)g(\(see)g(ab)r +(o)n(v)n(e\);)42 b(the)37 b(n)n(um-)2040 1741 y(b)r(er)32 +b(of)h(terms)e(to)h(b)r(e)g(summed)d(up)i(is)i Fo(O)r +Fr(\()p Fo(N)8 b Fr(\),)34 b(since)f Fo(x)e Fr(=)h Fo(O)r +Fr(\()p Fo(N)8 b Fr(\).)2040 1824 y(Th)n(us)23 b(the)g(en)n(tire)g +(computation)g(can)g(b)r(e)g(done)g(with)h(bit)f(complex-)2040 +1907 y(it)n(y)i Fo(O)r Fr(\(\(log)16 b Fo(N)8 b Fr(\))2487 +1875 y Fn(2)2522 1907 y Fo(M)g Fr(\()p Fo(N)g Fr(\)\).)2040 +2067 y Fh(Note:)2152 2226 y Fr(This)27 b(result)e(is)i(already)f(men)n +(tioned)e(in)i([4)q(].)2152 2309 y(E.)e(Karatsuba)f([9)q(])g(extends)f +(this)h(result)g(to)h(\000\()p Fo(s)p Fr(\))e(for)i(algebraic)2040 +2392 y Fo(s)p Fr(.)2152 2475 y(F)-6 b(or)35 b(\000\()p +Fo(s)p Fr(\))g(there)f(is)i(no)f(c)n(hec)n(kp)r(oin)n(ting)f(p)r +(ossible)i(b)r(ecause)g(of)2040 2558 y(the)25 b(dep)r(endency)g(on)g +Fo(x)g Fr(in)h(the)f(binary)g(splitting.)2040 2746 y +Fp(2.7)82 b(Example:)37 b(The)27 b(Riemann)h(Zeta)g(value)g +Fo(\020)5 b Fr(\(3\))2040 2877 y(Recen)n(tly)-6 b(,)31 +b(Doron)g(Zeilb)r(erger's)i(metho)r(d)d(of)h(\\creativ)n(e)h(telescop-) +2040 2960 y(ing")d(has)g(b)r(een)f(applied)h(to)g(Riemann's)e(zeta)i +(function)g(at)g Fo(s)c Fr(=)h(3)2040 3043 y(\(see)g([1)q(]\),)g(whic)n +(h)g(is)g(also)h(kno)n(wn)e(as)h Fi(Ap)n(\023)-37 b(ery's)29 +b(c)l(onstant)p Fr(:)2324 3276 y Fo(\020)5 b Fr(\(3\))22 +b(=)2574 3228 y(1)p 2574 3259 39 4 v 2574 3327 a(2)2665 +3174 y Fm(1)2635 3199 y Fl(X)2637 3374 y Fk(n)p Fn(=1)2778 +3227 y Fr(\()p Fj(\000)p Fr(1\))2936 3195 y Fk(n)p Fm(\000)p +Fn(1)3056 3227 y Fr(\(205)p Fo(n)3246 3195 y Fn(2)3300 +3227 y Fj(\000)16 b Fr(160)p Fo(n)j Fr(+)e(32\))p 2778 +3259 961 4 v 3128 3349 a Fo(n)3174 3328 y Fn(5)3209 3284 +y Fl(\000)3247 3316 y Fn(2)p Fk(n)3262 3375 y(n)3316 +3284 y Fl(\001)3354 3301 y Fn(5)2152 3517 y Fr(This)22 +b(sum)e(consists)j(of)f(three)f(h)n(yp)r(ergeometric)g(series.)34 +b(Binary)2040 3600 y(splitting)k(can)g(also)h(b)r(e)f(applied)g +(directly)-6 b(,)40 b(b)n(y)d(putting)g Fo(a)p Fr(\()p +Fo(n)p Fr(\))k(=)2040 3683 y(205)p Fo(n)2200 3651 y Fn(2)2260 +3683 y Fr(+)23 b(250)p Fo(n)i Fr(+)e(77,)39 b Fo(b)p +Fr(\()p Fo(n)p Fr(\))e(=)g(1,)h Fo(p)p Fr(\(0\))f(=)h(1,)g +Fo(p)p Fr(\()p Fo(n)p Fr(\))f(=)g Fj(\000)p Fo(n)3871 +3651 y Fn(5)3941 3683 y Fr(for)2040 3766 y Fo(n)24 b(>)f +Fr(0,)28 b(and)e Fo(q)s Fr(\()p Fo(n)p Fr(\))e(=)f(32\(2)p +Fo(n)c Fr(+)f(1\))3035 3734 y Fn(5)3070 3766 y Fr(.)38 +b(Th)n(us)27 b(the)f(bit)h(complexit)n(y)f(of)2040 3849 +y(computing)f Fo(\020)5 b Fr(\(3\))26 b(is)g Fo(O)r Fr(\(\(log)15 +b Fo(N)8 b Fr(\))2991 3817 y Fn(2)3026 3849 y Fo(M)g +Fr(\()p Fo(N)g Fr(\)\).)2040 4008 y Fh(Note:)2152 4168 +y Fr(Using)18 b(this)g(the)g(authors)g(w)n(ere)h(able)f(to)h(establish) +g(a)f(new)g(record)2040 4251 y(in)29 b(the)f(calculation)i(of)f +Fo(\020)5 b Fr(\(3\))28 b(b)n(y)g(computing)f(1,000,000)32 +b(decimals)2040 4334 y([17)q(].)45 b(The)29 b(computation)g(to)r(ok)g +(8)g(hours)g(on)g(a)g(Hewlett)h(P)n(ac)n(k)l(ard)2040 +4417 y(9000/712)i(mac)n(hine.)41 b(After)29 b(distributing)f(on)g(a)h +(cluster)g(of)g(4)g(HP)2040 4500 y(9000/712)e(mac)n(hines)d(the)f(same) +h(computation)f(required)h(only)g(2.5)2040 4583 y(hours.)66 +b(The)37 b(half)g(hour)f(w)n(as)h(necessary)g(for)g(reading)g(the)f +(par-)2040 4666 y(tial)28 b(results)f(from)f(disk)h(and)f(for)h(recom)n +(bining)g(them.)36 b(Again,)27 b(w)n(e)2040 4749 y(ha)n(v)n(e)c(used)g +(binary-splitting)g(for)h(recom)n(bining:)32 b(the)23 +b(4)h(partial)g(re-)2040 4832 y(sult)36 b(pro)r(duced)e(2)i(results)g +(whic)n(h)g(w)n(ere)g(com)n(bined)e(to)i(the)f(\014nal)2040 +4915 y(1,000,000)29 b(decimals)d(v)l(alue)f(of)i Fo(\020)5 +b Fr(\(3\).)2152 4998 y(This)40 b(example)e(sho)n(ws)i(the)f(imp)r +(ortance)g(of)h(c)n(hec)n(kp)r(oin)n(ting.)2040 5081 +y(Ev)n(en)30 b(if)h(a)g(mac)n(hine)f(crashes)h(through)f(the)g +(calculation,)k(the)c(re-)2040 5164 y(sults)35 b(of)g(the)e(other)i +(mac)n(hines)e(are)i(still)g(usable.)61 b(Additionally)-6 +b(,)2040 5247 y(b)r(eing)27 b(able)h(to)f(parallelise)i(the)d +(computation)h(reduced)f(the)h(com-)2040 5330 y(puting)e(time)g +(dramatically)-6 b(.)p eop +%%Page: 5 5 +5 4 bop -152 -69 a Fp(3)83 b(Evaluation)28 b(of)g(linea)n(rly)g +(convergent)f(series)g(of)h(sums)-152 88 y Fr(The)23 +b(tec)n(hnique)f(presen)n(ted)g(in)h(the)f(previous)h(section)g(also)h +(applies)-152 171 y(to)i(all)h(linearly)f(con)n(v)n(ergen)n(t)f(sums)g +(of)i(the)e(form)31 400 y Fo(U)30 b Fr(=)223 298 y Fm(1)194 +323 y Fl(X)196 497 y Fk(n)p Fn(=0)336 351 y Fo(a)p Fr(\()p +Fo(n)p Fr(\))p 336 383 147 4 v 340 450 a Fo(b)p Fr(\()p +Fo(n)p Fr(\))506 285 y Fl(\022)580 351 y Fo(c)p Fr(\(0\))p +577 383 138 4 v 577 450 a Fo(d)p Fr(\(0\))742 400 y(+)17 +b Fj(\001)c(\001)g(\001)k Fr(+)1015 351 y Fo(c)p Fr(\()p +Fo(n)p Fr(\))p 1012 383 146 4 v 1012 450 a Fo(d)p Fr(\()p +Fo(n)p Fr(\))1168 285 y Fl(\023)1252 351 y Fo(p)p Fr(\(0\))12 +b Fj(\001)h(\001)h(\001)f Fo(p)p Fr(\()p Fo(n)p Fr(\))p +1252 383 397 4 v 1254 450 a Fo(q)s Fr(\(0\))f Fj(\001)h(\001)h(\001)f +Fo(q)s Fr(\()p Fo(n)p Fr(\))-152 644 y(where)35 b Fo(a)p +Fr(\()p Fo(n)p Fr(\),)i Fo(b)p Fr(\()p Fo(n)p Fr(\),)g +Fo(c)p Fr(\()p Fo(n)p Fr(\),)g Fo(d)p Fr(\()p Fo(n)p +Fr(\),)g Fo(p)p Fr(\()p Fo(n)p Fr(\),)f Fo(q)s Fr(\()p +Fo(n)p Fr(\))e(are)h(in)n(tegers)h(with)-152 727 y Fo(O)r +Fr(\(log)16 b Fo(n)p Fr(\))27 b(bits.)38 b(The)27 b(most)f(often)i +(used)e(case)i(is)f(again)h(that)f Fo(a)p Fr(\()p Fo(n)p +Fr(\),)-152 810 y Fo(b)p Fr(\()p Fo(n)p Fr(\),)22 b Fo(c)p +Fr(\()p Fo(n)p Fr(\),)f Fo(d)p Fr(\()p Fo(n)p Fr(\),)g +Fo(p)p Fr(\()p Fo(n)p Fr(\),)g Fo(q)s Fr(\()p Fo(n)p +Fr(\))f(are)h(p)r(olynomials)f(in)g Fo(n)g Fr(with)g(in)n(teger)-152 +893 y(co)r(e\016cien)n(ts.)-152 1052 y Fh(Algorithm:)-40 +1211 y Fr(Giv)n(en)29 b(t)n(w)n(o)g(index)g(b)r(ounds)f +Fo(n)861 1219 y Fn(1)896 1211 y Fr(and)h Fo(n)1095 1219 +y Fn(2)1130 1211 y Fr(,)h(consider)f(the)g(partial)-152 +1294 y(sums)311 1407 y Fo(S)c Fr(=)542 1330 y Fl(X)464 +1505 y Fk(n)502 1515 y Fg(1)535 1505 y Fm(\024)p Fk(n)f +(0."\);)2275 2050 y(break;)2197 2217 y(case)h(1:)g(//)g(the)f(result)i +(at)f(the)g(point)g(n1)2275 2300 y(r.P)g(=)g(arg.p[n1];)2275 +2383 y(r.Q)g(=)g(arg.q[n1];)2275 2466 y(r.B)g(=)g(arg.b[n1];)2275 +2549 y(r.T)g(=)g(arg.a[n1])h(*)f(arg.p[n1];)2275 2632 +y(r.D)g(=)g(arg.d[n1];)2275 2715 y(r.C)g(=)g(arg.c[n1];)2275 +2798 y(r.V)g(=)g(arg.a[n1])h(*)f(arg.c[n1])h(*)e(arg.p[n1];)2275 +2881 y(break;)2197 3047 y(//)h(cases)g(2,)g(3,)f(4)h(left)g(out)g(for)g +(simplicity)2197 3213 y(default:)h(//)f(general)h(case)2275 +3379 y(//)f(the)g(left)g(and)g(the)g(right)g(partial)h(sum)2275 +3462 y(abpqcd_series_result)j(L,)c(R;)2275 3628 y(//)g(find)g(the)g +(middle)h(of)e(the)h(interval)2275 3711 y(int)g(nm)g(=)g(\(n1)f(+)h +(n2\))g(/)f(2;)2275 3877 y(//)h(sum)g(left)g(side)2275 +3960 y(sum_abpqcd\(L,)j(n1,)d(nm,)f(arg\);)2275 4126 +y(//)h(sum)g(right)g(side)2275 4209 y(sum_abpqcd\(R,)j(nm,)d(n2,)f +(arg\);)2275 4375 y(//)h(put)g(together)2275 4458 y(r.P)g(=)g(L.P)g(*)f +(R.P;)2275 4541 y(r.Q)h(=)g(R.Q)g(*)f(L.Q;)2275 4624 +y(r.B)h(=)g(L.B)g(*)f(R.B;)2275 4707 y(bigint)i(tmp)f(=)f(L.B)h(*)g +(L.P)g(*)f(R.T;)2275 4790 y(r.T)h(=)g(R.B)g(*)f(R.Q)h(*)g(L.T)f(+)h +(tmp;)2275 4873 y(r.D)g(=)g(L.D)g(*)f(R.D;)2275 4956 +y(r.C)h(=)g(L.C)g(*)f(R.D)h(+)g(R.C)f(*)h(L.D;)2275 5039 +y(r.V)g(=)g(R.D)g(*)f(\(R.B)h(*)g(R.Q)g(*)f(L.V)h(+)g(L.C)f(*)h(tmp\)) +2511 5122 y(+)f(L.D)h(*)g(L.B)g(*)f(L.P)h(*)f(R.V;)2275 +5205 y(break;)2119 5288 y(})2040 5371 y(})p eop +%%Page: 6 6 +6 5 bop -152 -69 a Fp(3.1)83 b(Example:)36 b(Euler's)27 +b(constant)g Fo(C)-152 63 y Fh(Theorem:)-40 222 y Fr(Let)32 +b Fo(f)8 b Fr(\()p Fo(x)p Fr(\))32 b(=)376 162 y Fl(P)464 +182 y Fm(1)464 249 y Fk(n)p Fn(=0)612 191 y Fk(x)647 +171 y Ff(n)p 606 205 89 4 v 606 249 a Fk(n)p Fn(!)662 +235 y Fg(2)736 222 y Fr(and)g Fo(g)s Fr(\()p Fo(x)p Fr(\))e(=)1158 +162 y Fl(P)1245 182 y Fm(1)1245 249 y Fk(n)p Fn(=0)1377 +222 y Fo(H)1441 230 y Fk(n)1500 191 y(x)1535 171 y Ff(n)p +1493 205 V 1493 249 a Fk(n)p Fn(!)1549 235 y Fg(2)1592 +222 y Fr(.)53 b(Then)-152 331 y(for)27 b Fo(x)21 b Fj(!)g(1)p +Fr(,)264 295 y Fk(g)r Fn(\()p Fk(x)p Fn(\))p 262 314 +119 4 v 262 357 a Fk(f)6 b Fn(\()p Fk(x)p Fn(\))412 331 +y Fr(=)503 301 y Fn(1)p 503 315 31 4 v 503 357 a(2)556 +331 y Fr(log)15 b Fo(x)i Fr(+)g Fo(C)22 b Fr(+)17 b Fo(O)1033 +266 y Fl(\000)1071 331 y Fo(e)1107 299 y Fm(\000)p Fn(4)1185 +263 y Fm(p)p 1235 263 35 3 v 36 x Fk(x)1274 266 y Fl(\001)1312 +331 y Fr(.)-152 506 y Fh(Pro)r(of:)-40 665 y Fr(The)27 +b(Laplace)h(metho)r(d)e(for)h(asymptotic)g(ev)l(aluation)g(of)g(exp)r +(o-)-152 748 y(nen)n(tially)f(gro)n(wing)h(sums)e(and)g(in)n(tegrals)i +(yields)257 942 y Fo(f)8 b Fr(\()p Fo(x)p Fr(\))21 b(=)g +Fo(e)544 906 y Fn(2)574 870 y Fm(p)p 624 870 V 36 x Fk(x)663 +942 y Fo(x)707 906 y Fm(\000)765 887 y Fg(1)p 765 896 +29 4 v 765 927 a(4)872 894 y Fr(1)p 817 925 150 4 v 817 +995 a(2)855 941 y Fj(p)p 919 941 47 4 v 54 x Fo(\031)976 +942 y Fr(\(1)c(+)g Fo(O)r Fr(\()p Fo(x)1272 906 y Fm(\000)1330 +887 y Fg(1)p 1330 896 29 4 v 1330 927 a(4)1372 942 y +Fr(\)\))-152 1148 y(and)-42 1327 y Fo(g)s Fr(\()p Fo(x)p +Fr(\))i(=)i Fo(e)238 1291 y Fn(2)268 1255 y Fm(p)p 318 +1255 35 3 v 36 x Fk(x)357 1327 y Fo(x)401 1291 y Fm(\000)459 +1272 y Fg(1)p 459 1281 29 4 v 459 1313 a(4)566 1279 y +Fr(1)p 511 1310 150 4 v 511 1380 a(2)549 1326 y Fj(p)p +614 1326 47 4 v 614 1380 a Fo(\031)683 1237 y Fl(\020)742 +1279 y Fr(1)p 742 1310 39 4 v 742 1378 a(2)804 1327 y(log)15 +b Fo(x)h Fr(+)h Fo(C)22 b Fr(+)17 b Fo(O)r Fr(\(log)e +Fo(x)i Fj(\001)g Fo(x)1552 1291 y Fm(\000)1610 1272 y +Fg(1)p 1610 1281 29 4 v 1610 1313 a(4)1652 1327 y Fr(\))1682 +1237 y Fl(\021)-152 1555 y Fr(On)36 b(the)f(other)h(hand,)j +Fo(h)p Fr(\()p Fo(x)p Fr(\))f(:=)884 1518 y Fk(g)r Fn(\()p +Fk(x)p Fn(\))p 882 1538 119 4 v 882 1580 a Fk(f)6 b Fn(\()p +Fk(x)p Fn(\))1046 1555 y Fr(satis\014es)38 b(the)d(di\013eren)n(tial) +-152 1651 y(equation)53 1808 y Fo(xf)8 b Fr(\()p Fo(x)p +Fr(\))16 b Fj(\001)h Fo(h)344 1772 y Fm(00)385 1808 y +Fr(\()p Fo(x)p Fr(\))g(+)f(\(2)p Fo(xf)739 1772 y Fm(0)762 +1808 y Fr(\()p Fo(x)p Fr(\))g(+)h Fo(f)8 b Fr(\()p Fo(x)p +Fr(\)\))17 b Fj(\001)g Fo(h)1237 1772 y Fm(0)1260 1808 +y Fr(\()p Fo(x)p Fr(\))j(=)h Fo(f)1510 1772 y Fm(0)1533 +1808 y Fr(\()p Fo(x)p Fr(\))-152 1966 y(hence)-152 2161 +y Fo(h)p Fr(\()p Fo(x)p Fr(\))g(=)108 2113 y(1)p 108 +2144 39 4 v 108 2212 a(2)169 2161 y(log)15 b Fo(x)p Fr(+)p +Fo(C)5 b Fr(+)p Fo(c)538 2169 y Fn(2)585 2050 y Fl(Z)668 +2071 y Fm(1)631 2239 y Fk(x)834 2113 y Fr(1)p 756 2144 +196 4 v 756 2212 a Fo(tf)j Fr(\()p Fo(t)p Fr(\))917 2190 +y Fn(2)961 2161 y Fo(dt)21 b Fr(=)1141 2113 y(1)p 1141 +2144 39 4 v 1141 2212 a(2)1202 2161 y(log)15 b Fo(x)p +Fr(+)p Fo(C)5 b Fr(+)p Fo(O)r Fr(\()p Fo(e)1664 2125 +y Fm(\000)p Fn(4)1742 2089 y Fm(p)p 1792 2089 35 3 v +36 x Fk(x)1830 2161 y Fr(\))-152 2375 y Fh(Algorithm:)-40 +2535 y Fr(T)-6 b(o)26 b(compute)f Fo(C)31 b Fr(with)26 +b(a)g(precision)g(of)h Fo(N)34 b Fr(bits,)26 b(set)486 +2744 y Fo(x)21 b Fr(=)632 2654 y Fl(l)676 2744 y Fr(\()p +Fo(N)k Fr(+)17 b(2\))964 2696 y(log)e(2)p 964 2727 151 +4 v 1020 2795 a(4)1125 2654 y Fl(m)1168 2664 y Fn(2)-152 +2939 y Fr(and)36 b(ev)l(aluate)h(the)e(series)j(for)f +Fo(g)s Fr(\()p Fo(x)p Fr(\))d(and)i Fo(f)8 b Fr(\()p +Fo(x)p Fr(\))36 b(sim)n(ultaneously)-6 b(,)-152 3022 +y(using)27 b(the)g(binary-splitting)g(algorithm,)h(with)f +Fo(a)p Fr(\()p Fo(n)p Fr(\))c(=)g(1,)28 b Fo(b)p Fr(\()p +Fo(n)p Fr(\))23 b(=)-152 3105 y(1,)f Fo(c)p Fr(\()p Fo(n)p +Fr(\))g(=)f(1,)g Fo(d)p Fr(\()p Fo(n)p Fr(\))h(=)f Fo(n)5 +b Fr(+)g(1,)22 b Fo(p)p Fr(\()p Fo(n)p Fr(\))f(=)g Fo(x)p +Fr(,)g Fo(q)s Fr(\()p Fo(n)p Fr(\))g(=)h(\()p Fo(n)5 +b Fr(+)g(1\))1490 3073 y Fn(2)1525 3105 y Fr(.)33 b(Let)20 +b Fo(\013)h Fr(=)-152 3188 y(3)p Fo(:)p Fr(591121477)c +Fo(:)d(:)f(:)31 b Fr(b)r(e)f(the)h(solution)g(of)h(the)e(equation)h +Fj(\000)p Fo(\013)12 b Fr(log)j Fo(\013)21 b Fr(+)-152 +3271 y Fo(\013)f Fr(+)f(1)29 b(=)e(0.)46 b(Then)29 b +Fo(\013)508 3217 y Fj(p)p 573 3217 44 4 v 573 3271 a +Fo(x)19 b Fj(\000)795 3241 y Fn(1)p 725 3255 171 4 v +725 3297 a(4)11 b(log)h Fk(\013)919 3271 y Fr(log)1031 +3217 y Fj(p)p 1095 3217 44 4 v 54 x Fo(x)19 b Fr(+)g +Fo(O)r Fr(\(1\))30 b(terms)f(of)h(the)-152 3380 y(series)d(su\016ce)f +(for)h(the)e(relativ)n(e)h(error)g(to)g(b)r(e)g(b)r(ounded)e(b)n(y)h(2) +1653 3349 y Fm(\000)p Fk(N)1759 3380 y Fr(.)-152 3540 +y Fh(Complexit)n(y:)-40 3699 y Fr(The)18 b(bit)f(complexit)n(y)f(of)h +(this)h(algorithm)f(is)h Fo(O)r Fr(\(\(log)d Fo(N)8 b +Fr(\))1564 3667 y Fn(2)1599 3699 y Fo(M)g Fr(\()p Fo(N)g +Fr(\)\).)-152 3859 y Fh(Note:)-40 4018 y Fr(This)23 b(algorithm)f(w)n +(as)g(\014rst)g(men)n(tioned)e(in)i([5].)34 b(It)21 b(is)h(b)n(y)f(far) +h(the)-152 4101 y(fastest)27 b(kno)n(wn)e(algorithm)h(for)h(computing)e +(Euler's)h(constan)n(t.)-40 4184 y(F)-6 b(or)33 b(Euler's)g(constan)n +(t)g(there)f(is)h(no)g(c)n(hec)n(kp)r(oin)n(ting)f(p)r(ossible)-152 +4267 y(b)r(ecause)27 b(of)f(the)f(dep)r(endency)f(on)i +Fo(x)f Fr(in)h(the)f(binary)g(splitting.)-152 4463 y +Fp(4)83 b(Computational)27 b(results)-152 4620 y Fr(In)22 +b(this)g(section)g(w)n(e)h(presen)n(t)f(some)f(computational)h(results) +h(of)g(our)-152 4703 y(CLN)f(and)g Fb(LiDIA)g Fr(implemen)n(tation)f +(of)i(the)e(algorithms)i(presen)n(ted)-152 4786 y(in)j(this)g(note.)35 +b(W)-6 b(e)26 b(use)g(the)f(o\016cial)i(v)n(ersion)g(\(1.3\))f(and)g +(an)g(exp)r(er-)-152 4869 y(imen)n(tal)33 b(v)n(ersion)f(\(1.4a\))i(of) +g Fb(LiDIA)p Fr(.)e(W)-6 b(e)33 b(ha)n(v)n(e)f(tak)n(en)g(adv)l(an)n +(tage)-152 4952 y(of)26 b Fb(LiDIA)p Fr('s)g(abilit)n(y)f(to)h(replace) +g(its)g(k)n(ernel)f(\(m)n(ultiprecision)g(arith-)-152 +5035 y(metic)17 b(and)h(memory)e(managemen)n(t\))g([16)q(,)i(15)q(,)g +(13],)i(so)f(w)n(e)f(w)n(ere)g(able)-152 5118 y(to)26 +b(use)g(in)f(b)r(oth)h(cases)h(CLN's)f(fast)h(in)n(teger)f(arithmetic)f +(routines.)p 2040 -64 2022 4 v 2038 19 4 84 v 2085 -6 +a(D)p 2239 19 V 142 w(exp)o(\(1\))p 2545 19 V 90 w(log)r(\(2\))p +2848 19 V 106 w Fo(\031)p 3151 19 V 259 w(C)p 3454 19 +V 248 w(G)p 3757 19 V 243 w(\020)5 b Fr(\(3\))p 4060 +19 V 2040 23 2022 4 v 2040 38 V 2038 126 4 89 v 2085 +101 a(10)2161 70 y Fn(2)p 2239 126 V 2286 101 a Fr(0.0005)p +2545 126 V 94 w(0.0020)p 2848 126 V 92 w(0.0014)p 3151 +126 V 92 w(0.0309)p 3454 126 V 92 w(0.0179)p 3757 126 +V 92 w(0.0027)p 4060 126 V 2040 130 2022 4 v 2038 218 +4 89 v 2085 194 a(10)2161 162 y Fn(3)p 2239 218 V 2286 +194 a Fr(0.0069)p 2545 218 V 94 w(0.0474)p 2848 218 V +92 w(0.0141)p 3151 218 V 92 w(0.8110)p 3454 218 V 92 +w(0.3580)p 3757 218 V 92 w(0.0696)p 4060 218 V 2040 222 +2022 4 v 2038 311 4 89 v 2085 286 a(10)2161 254 y Fn(4)p +2239 311 V 2286 286 a Fr(0.2566)p 2545 311 V 94 w(1.9100)p +2848 311 V 92 w(0.6750)p 3151 311 V 92 w(33.190)p 3454 +311 V 92 w(13.370)p 3757 311 V 92 w(2.5600)p 4060 311 +V 2040 314 2022 4 v 2038 403 4 89 v 2085 378 a(10)2161 +346 y Fn(5)p 2239 403 V 2286 378 a Fr(5.5549)p 2545 403 +V 94 w(45.640)p 2848 403 V 92 w(17.430)p 3151 403 V 92 +w(784.93)p 3454 403 V 92 w(340.33)p 3757 403 V 92 w(72.970)p +4060 403 V 2040 406 2022 4 v 2040 549 a(Figure)35 b(1:)53 +b Fb(LiDIA-1.4a)34 b Fr(timings)h(of)g(computation)f(of)h(constan)n(ts) +2040 632 y(using)26 b(binary-splitting)2040 955 y Fp(4.1)82 +b(Timings)2040 1087 y Fr(The)29 b(table)g(in)g(Figure)g(1)g(sho)n(ws)h +(the)e(running)g(times)g(for)i(the)e(cal-)2040 1170 y(culation)37 +b(of)g(exp\(1\),)i(log)r(\(2\),)g Fo(\031)s Fr(,)g Fo(C)5 +b Fr(,)40 b Fo(G)c Fr(and)g Fo(\020)5 b Fr(\(3\))36 b(to)h(precision) +2040 1253 y(100,)g(1000,)g(10000)e(and)e(100000)j(decimal)d(digits.)58 +b(The)34 b(timings)2040 1336 y(are)29 b(giv)n(en)e(in)h(seconds)h(and)f +(they)f(denote)g(the)h Fi(r)l(e)l(al)h Fr(time)e(needed,)2040 +1419 y(i.e.)52 b(system)30 b(and)h(user)g(time.)50 b(The)31 +b(computation)g(w)n(as)h(done)f(on)2040 1502 y(an)26 +b(In)n(tel)f(P)n(en)n(tium)f(with)i(133Hz)h(and)e(32MB)i(of)g(RAM.)2152 +1585 y(The)20 b(second)f(table)h(\(Figure)g(2\))f(summarizes)g(the)f(p) +r(erformance)2040 1668 y(of)25 b Fo(exp)p Fr(\()p Fo(x)p +Fr(\))e(in)h(v)l(arious)h(Computer)f(Algebra)h(systems)3631 +1636 y Fn(3)3665 1668 y Fr(.)34 b(F)-6 b(or)25 b(a)f(fair)2040 +1751 y(comparison)h(of)h(the)f(algorithms,)h(b)r(oth)f(argumen)n(t)f +(and)h(precision)2040 1834 y(are)d(c)n(hosen)g(in)f(suc)n(h)g(a)h(w)n +(a)n(y)-6 b(,)22 b(that)g(system{sp)r(eci\014c)f(optimizations)2040 +1917 y(\(BCD)e(arithmetic)g(in)g(Maple,)i(FFT)f(m)n(ultiplication)f(in) +g(CLN,)g(sp)r(e-)2040 2000 y(cial)j(exact)f(argumen)n(t)f(handling)h +(in)g Fb(LiDIA)p Fr(\))f(do)h(not)g(w)n(ork.)33 b(W)-6 +b(e)21 b(use)2040 2096 y Fo(x)g Fr(=)g Fj(\000)2246 2034 +y(p)p 2310 2034 39 4 v 62 x Fr(2)j(and)f(precision)h(10)2913 +2064 y Fn(\()p Fk(i=)p Fn(3\))3050 2096 y Fr(,)h(with)e +Fo(i)h Fr(running)f(from)g(4)h(to)g(15.)p 2106 2282 1862 +4 v 2104 2365 4 84 v 2322 2340 a(D)p 2424 2365 V 90 w(Maple)p +2804 2365 V 173 w(P)n(ari)p 3222 2365 V 280 w Fb(LiDIA-1.3)p +3624 2365 V 89 w Fr(CLN)p 3965 2365 V 2106 2368 1862 +4 v 2106 2383 V 2104 2466 4 84 v 2304 2441 a(21)p 2424 +2466 V 91 w(0.00090)p 2804 2466 V 130 w(0.00047)p 3222 +2466 V 170 w(0.00191)p 3624 2466 V 152 w(0.00075)p 3965 +2466 V 2106 2469 1862 4 v 2104 2552 4 84 v 2304 2527 +a(46)p 2424 2552 V 91 w(0.00250)p 2804 2552 V 130 w(0.00065)p +3222 2552 V 170 w(0.00239)p 3624 2552 V 152 w(0.00109)p +3965 2552 V 2106 2556 1862 4 v 2104 2639 4 84 v 2266 +2614 a(100)p 2424 2639 V 91 w(0.01000)p 2804 2639 V 130 +w(0.00160)p 3222 2639 V 170 w(0.00389)p 3624 2639 V 152 +w(0.00239)p 3965 2639 V 2106 2642 1862 4 v 2104 2725 +4 84 v 2266 2700 a(215)p 2424 2725 V 91 w(0.03100)p 2804 +2725 V 130 w(0.00530)p 3222 2725 V 170 w(0.00750)p 3624 +2725 V 152 w(0.00690)p 3965 2725 V 2106 2728 1862 4 v +2104 2811 4 84 v 2266 2786 a(464)p 2424 2811 V 91 w(0.11000)p +2804 2811 V 130 w(0.02500)p 3222 2811 V 170 w(0.02050)p +3624 2811 V 152 w(0.02991)p 3965 2811 V 2106 2815 1862 +4 v 2104 2898 4 84 v 2227 2873 a(1000)p 2424 2898 V 92 +w(0.4000)p 2804 2898 V 168 w(0.2940)p 3222 2898 V 208 +w(0.0704)p 3624 2898 V 190 w(0.0861)p 3965 2898 V 2106 +2901 1862 4 v 2104 2984 4 84 v 2227 2959 a(2154)p 2424 +2984 V 92 w(1.7190)p 2804 2984 V 168 w(0.8980)p 3222 +2984 V 208 w(0.2990)p 3624 2984 V 190 w(0.2527)p 3965 +2984 V 2106 2987 1862 4 v 2104 3070 4 84 v 2227 3045 +a(4641)p 2424 3070 V 92 w(8.121)p 2804 3070 V 206 w(5.941)p +3222 3070 V 246 w(1.510)p 3624 3070 V 228 w(0.906)p 3965 +3070 V 2106 3074 1862 4 v 2104 3157 4 84 v 2189 3132 +a(10000)p 2424 3157 V 92 w(39.340)p 2804 3157 V 168 w(39.776)p +3222 3157 V 208 w(7.360)p 3624 3157 V 228 w(4.059)p 3965 +3157 V 2106 3160 1862 4 v 2104 3243 4 84 v 2189 3218 +a(21544)p 2424 3243 V 92 w(172.499)p 2804 3243 V 130 +w(280.207)p 3222 3243 V 170 w(39.900)p 3624 3243 V 190 +w(15.010)p 3965 3243 V 2106 3246 1862 4 v 2104 3329 4 +84 v 2189 3304 a(46415)p 2424 3329 V 92 w(868.841)p 2804 +3329 V 130 w(1972.184)p 3222 3329 V 132 w(129.000)p 3624 +3329 V 152 w(39.848)p 3965 3329 V 2106 3333 1862 4 v +2104 3416 4 84 v 2151 3391 a(100000)p 2424 3416 V 92 +w(4873.829)p 2804 3416 V 92 w(21369.197)p 3222 3416 V +94 w(437.000)p 3624 3416 V 152 w(106.990)p 3965 3416 +V 2106 3419 1862 4 v 2238 3579 a(Figure)i(2:)35 b(Timings)26 +b(of)g(computation)f(of)i(exp)o(\()p Fj(\000)3703 3517 +y(p)p 3767 3517 39 4 v 62 x Fr(2\))2152 3834 y(MapleV)39 +b(R3)g(is)g(the)f(slo)n(w)n(est)i(system)e(in)g(this)h(comparison.)2040 +3917 y(This)29 b(is)h(probably)e(due)g(to)h(the)f(BCD)i(arithmetic)e +(it)h(uses.)44 b(Ho)n(w-)2040 4000 y(ev)n(er,)37 b(Maple)e(seems)g(to)f +(ha)n(v)n(e)g(an)h(asymptotically)f(b)r(etter)h(algo-)2040 +4083 y(rithm)24 b(for)i Fo(exp)p Fr(\()p Fo(x)p Fr(\))c(for)k(n)n(um)n +(b)r(ers)d(ha)n(ving)i(more)f(than)h(10000)i(deci-)2040 +4166 y(mals.)33 b(In)21 b(this)h(range)h(it)f(outp)r(erforms)g(P)n +(ari-1.39.03,)k(whic)n(h)c(is)g(the)2040 4249 y(fastest)27 +b(system)e(in)g(the)h(0{200)h(decimals)f(range.)2152 +4332 y(The)18 b(comparison)f(indicating)h(the)f(strength)g(of)g +(binary-splitting)2040 4415 y(is)28 b(b)r(et)n(w)n(een)e +Fb(LiDIA-1.3)h Fr(and)g(CLN)g(itself.)40 b(Ha)n(ving)26 +b(the)h(same)f(k)n(er-)2040 4498 y(nel,)33 b(the)e(only)g(di\013erence) +g(is)h(here)f(that)g Fb(LiDIA-1.3)g Fr(uses)h(Bren)n(t's)2040 +4581 y Fo(O)r Fr(\()2130 4527 y Fj(p)p 2195 4527 47 4 +v 2195 4581 a Fo(nM)8 b Fr(\()p Fo(n)p Fr(\)\))23 b(for)g(exp)o(\()p +Fo(x)p Fr(\),)g(whereas)h(CLN)e(c)n(hanges)i(from)e(Bren)n(t's)2040 +4664 y(metho)r(d)j(to)g(a)h(binary-splitting)g(v)n(ersion)g(for)g +(large)h(n)n(um)n(b)r(ers.)2152 4747 y(As)g(exp)r(ected)f(in)g(the)g +(range)h(of)h(1000{100000)j(decimals)c(CLN)2040 4830 +y(outp)r(erforms)j Fb(LiDIA-1.3)g Fr(b)n(y)f(far.)49 +b(The)30 b(fact)h(that)f Fb(LiDIA-1.2.1)h Fr(is)2040 +4913 y(faster)d(in)f(the)f(range)h(of)h(200{1000)i(decimals)d(\(also)h +(in)e(some)h(trig.)2040 4996 y(functions\))18 b(is)f(probably)g(due)f +(to)i(a)f(b)r(etter)g(optimized)g Fo(O)r Fr(\()3708 4942 +y Fj(p)p 3772 4942 V 54 x Fo(n)q(M)8 b Fr(\()p Fo(n)p +Fr(\)\))2040 5079 y(metho)r(d)25 b(for)h(exp)o(\()p Fo(x)p +Fr(\).)p 2040 5124 797 4 v 2127 5173 a Fg(3)2159 5198 +y Fe(W)-5 b(e)15 b(do)h(not)g(list)g(the)g(timings)f(of)h +Fd(LiDIA-1.4a)g Fe(since)f(these)g(are)h(comparable)2040 +5264 y(to)23 b(those)e(of)h(CLN.)p eop +%%Page: 7 7 +7 6 bop -152 -69 a Fp(4.2)83 b(Distributed)27 b(computing)g(of)h +Fo(\020)5 b Fr(\(3\))-152 63 y(Using)22 b(the)f(metho)r(d)g(describ)r +(ed)g(in)h(2.7)h(the)e(authors)h(w)n(ere)g(the)f(\014rst)-152 +146 y(to)30 b(compute)f(1,000,000)k(decimals)c(of)i Fo(\020)5 +b Fr(\(3\))30 b([17)q(].)46 b(The)30 b(computa-)-152 +229 y(tion)d(to)r(ok)f(8)h(hours)f(on)g(a)g(Hewlett)h(P)n(ac)n(k)l(ard) +f(9000/712)j(mac)n(hine.)-152 312 y(After)g(distributing)g(on)g(a)g +(cluster)h(of)f(4)h(HP)e(9000/712)k(mac)n(hines)-152 +395 y(the)k(same)g(computation)f(required)g(only)h(2.5)h(hours.)66 +b(The)36 b(half)-152 478 y(hour)25 b(w)n(as)h(necessary)g(for)f +(reading)h(the)f(partial)h(results)f(from)g(disk)-152 +561 y(and)37 b(for)g(recom)n(bining)g(them.)66 b(Again,)41 +b(w)n(e)c(ha)n(v)n(e)f(used)h(binary-)-152 644 y(splitting)e(for)g +(recom)n(bining:)52 b(the)33 b(4)i(partial)g(result)g(pro)r(duced)e(2) +-152 727 y(results)25 b(whic)n(h)f(w)n(ere)h(com)n(bined)e(to)h(the)g +(\014nal)g(1,000,000)k(decimals)-152 810 y(v)l(alue)e(of)g +Fo(\020)5 b Fr(\(3\).)-40 893 y(This)40 b(example)e(sho)n(ws)i(the)f +(imp)r(ortance)g(of)h(c)n(hec)n(kp)r(oin)n(ting.)-152 +976 y(Ev)n(en)30 b(if)h(a)g(mac)n(hine)f(crashes)h(through)f(the)g +(calculation,)k(the)c(re-)-152 1059 y(sults)35 b(of)g(the)f(other)g +(mac)n(hines)f(are)i(still)g(usable.)61 b(Additionally)-6 +b(,)-152 1142 y(b)r(eing)27 b(able)h(to)f(parallelise)i(the)e +(computation)f(reduced)g(the)h(com-)-152 1225 y(puting)f(time)e +(dramatically)-6 b(.)-152 1413 y Fp(4.3)83 b(Euler's)26 +b(constant)h Fo(C)-152 1544 y Fr(W)-6 b(e)29 b(ha)n(v)n(e)g(implemen)n +(ted)e(a)j(v)n(ersion)f(of)h(Bren)n(t's)g(and)f(McMillan's)-152 +1627 y(algorithm)j([5)q(])f(and)g(a)h(v)n(ersion)f(accelerated)i(b)n(y) +d(binary-splitting)-152 1710 y(as)d(sho)n(wn)f(in)f(3.1.)-40 +1793 y(The)40 b(computation)e(of)i Fo(C)k Fr(w)n(as)c(done)e(t)n(wice)i +(on)f(a)g(SP)-6 b(AR)n(C-)-152 1876 y(Ultra)36 b(mac)n(hine)e(with)h +(167)h(MHz)f(and)g(256)h(MB)g(of)g(RAM.)f(The)-152 1959 +y(\014rst)23 b(computation)f(using)h(the)g(non-acellerated)g(v)n +(ersion)g(required)-152 2042 y(160)j(hours.)34 b(The)24 +b(result)h(of)g(this)g(computation)e(w)n(as)j(then)d(v)n(eri\014ed)-152 +2125 y(b)n(y)i(the)g(binary)g(splitting)i(v)n(ersion)f(in)f(\(only\))h +(14)g(hours.)-40 2208 y(The)h(\014rst)f(475006)j(partial)e(quotien)n +(ts)f(of)i(the)e(con)n(tin)n(ued)f(frac-)-152 2291 y(tion)d(of)g +Fo(C)k Fr(w)n(ere)c(computed)e(on)h(an)g(In)n(tel)g(P)n(en)n(tium)f +(with)h(133)i(MHz)-152 2374 y(and)k(32)h(MB)g(of)f(RAM)g(in)g(3)g +(hours)g(using)h(a)f(programm)f(b)n(y)g(H.)h(te)-152 +2457 y(Riele)33 b(based)g(on)g([6],)i(whic)n(h)e(w)n(as)h(translated)f +(to)g Fb(LiDIA)f Fr(for)h(e\016-)-152 2540 y(ciency)j(reasons.)64 +b(Computing)35 b(the)g(475006th)i(con)n(v)n(ergen)n(t)e(pro-)-152 +2623 y(duced)25 b(the)g(follo)n(wing)k(impro)n(v)n(ed)24 +b(theorem:)-73 2756 y(If)i Fo(C)31 b Fr(is)26 b(a)g(rational)h(n)n(um)n +(b)r(er,)d Fo(C)i Fr(=)21 b Fo(p=q)s Fr(,)26 b(then)f +Fj(j)p Fo(q)s Fj(j)d Fo(>)f Fr(10)1574 2724 y Fn(244663)-40 +2889 y Fr(Details)33 b(of)e(this)h(computation)e(\(including)h +(statistics)i(on)e(the)-152 2972 y(partial)c(quotien)n(ts\))e(can)h(b)r +(e)f(found)h(in)f([14)r(].)-152 3167 y Fp(5)83 b(Conclusions)-152 +3324 y Fr(Although)17 b(p)r(o)n(w)n(erful,)j(the)d(binary)g(splitting)h +(metho)r(d)e(has)i(not)f(b)r(een)-152 3407 y(widely)30 +b(used.)46 b(Esp)r(ecially)-6 b(,)32 b(no)e(information)g(existed)f(on) +h(the)f(ap-)-152 3490 y(plicabilit)n(y)e(of)f(this)g(metho)r(d.)-40 +3573 y(In)c(this)h(note)g(w)n(e)g(presen)n(ted)f(a)g(generic)i +(binary-splitting)e(sum-)-152 3656 y(mation)d(device)f(for)h(ev)l +(aluating)g(t)n(w)n(o)g(t)n(yp)r(es)g(of)g(linearly)g(con)n(v)n(ergen)n +(t)-152 3740 y(series.)35 b(F)-6 b(rom)22 b(this)i(w)n(e)f(deriv)n(ed)g +(simple)g(and)g(computationally)g(ef-)-152 3823 y(\014cien)n(t)g +(algorithms)g(for)h(the)e(ev)l(aluation)h(of)h(elemen)n(tary)d +(functions)-152 3906 y(and)32 b(constan)n(ts.)52 b(These)32 +b(algorithms)h(w)n(ork)e(with)h Fi(exact)h Fr(ob)t(jects,)-152 +3989 y(making)22 b(them)f(suitable)h(for)h(use)g(within)f(Computer)f +(Algebra)i(sys-)-152 4072 y(tems.)-40 4155 y(W)-6 b(e)36 +b(ha)n(v)n(e)g(sho)n(wn)h(that)f(the)g(practical)h(p)r(erformance)g(of) +g(our)-152 4238 y(algorithms)e(is)f(sup)r(erior)g(to)g(curren)n(t)f +(system)g(implemen)n(tations.)-152 4321 y(In)24 b(addition)g(to)g +(existing)h(metho)r(ds,)f(our)g(algorithms)h(pro)n(vide)e(the)-152 +4404 y(p)r(ossibilit)n(y)d(of)g(c)n(hec)n(kp)r(oin)n(ting)e(and)h +(parallelising.)34 b(These)20 b(features)-152 4487 y(can)33 +b(b)r(e)g(useful)g(for)h(h)n(uge)e(calculations,)37 b(suc)n(h)32 +b(as)h(those)g(done)g(in)-152 4570 y(analytic)27 b(n)n(um)n(b)r(er)c +(theory)i(researc)n(h.)-152 4765 y Fp(6)83 b(Thanks)-152 +4922 y Fr(The)22 b(authors)h(w)n(ould)f(lik)n(e)g(to)g(thank)f(J\177) +-38 b(org)23 b(Arndt,)f(for)h(p)r(oin)n(ting)f(us)-152 +5005 y(to)i(c)n(hapter)f(10)h(in)f([2)q(].)34 b(W)-6 +b(e)23 b(w)n(ould)h(also)g(lik)n(e)g(to)f(thank)g(Ric)n(hard)g(P)-6 +b(.)-152 5088 y(Bren)n(t)24 b(for)g(his)f(commen)n(ts)f(and)h(Hermann)f +(te)h(Riele)h(for)g(pro)n(viding)-152 5171 y(us)35 b(his)g(program)g +(for)g(the)g(con)n(tin)n(ued)f(fraction)i(computation)e(of)-152 +5254 y(Euler's)27 b(constan)n(t.)2040 -69 y Fp(References)2078 +88 y Fr([1])39 b Fa(Theodor)45 b(Amdeberhan,)j(and)c(Dor)n(on)j +(Zeilber)n(ger)p Fr(.)2197 171 y(Acceleration)56 b(of)g(h)n(yp)r +(ergeometric)f(series)h(via)f(the)g(WZ)2197 254 y(metho)r(d.)d(T)-6 +b(o)33 b(app)r(ear)g(in:)47 b(Electronic)33 b(Journal)g(of)g(Com)n(bi-) +2197 337 y(natorics,)27 b(Wilf)g(F)-6 b(estsc)n(hrift)26 +b(V)-6 b(olume.)2078 480 y([2])39 b Fa(Jona)-5 b(than)25 +b(M.)g(Bor)-7 b(wein,)25 b(and)g(Peter)f(B.)h(Bor)-7 +b(wein)p Fr(.)29 b Fi(Pi)2197 563 y(and)f(the)g(A)n(GM)p +Fr(.)35 b(Wiley)-6 b(,)26 b(1987.)2078 705 y([3])39 b +Fa(Richard)48 b(P.)h(Brent)p Fr(.)95 b(The)46 b(complexit)n(y)f(of)i(m) +n(ultiple-)2197 788 y(precision)i(arithmetic.)102 b Fi(Complexity)49 +b(of)f(Computational)2197 871 y(Pr)l(oblem)28 b(Solving)k +Fr(\(1976\).)2078 1013 y([4])39 b Fa(Richard)21 b(P.)i(Brent)p +Fr(.)h(F)-6 b(ast)20 b(m)n(ultiple-precision)g(ev)l(aluation)2197 +1096 y(of)f(elemen)n(tary)f(functions.)23 b Fi(Journal)e(of)g(the)h(A)n +(CM)e Fh(23)f Fr(\(1976\),)2197 1179 y(242{251.)2078 +1322 y([5])39 b Fa(Richard)51 b(P.)h(Brent,)57 b(and)51 +b(Ed)n(win)h(M.)f(McMillan)p Fr(.)2197 1405 y(Some)37 +b(new)h(algorithms)h(for)g(high-precision)f(computation)2197 +1488 y(of)c(Euler's)g(constan)n(t.)57 b Fi(Mathematics)36 +b(of)f(Computation)g Fh(34)2197 1571 y Fr(\(1980\),)27 +b(305{312.)2078 1713 y([6])39 b Fa(Richard)i(P.)h(Brent,)j(Alf)d(v)-7 +b(an)42 b(der)f(Poor)-5 b(ten,)46 b(and)2197 1796 y(Hermann)40 +b(te)h(Riele)p Fr(.)71 b(A)37 b(comparativ)n(e)h(study)f(of)j(algo-) +2197 1879 y(rithms)32 b(for)i(computing)e(con)n(tin)n(ued)g(fractions)j +(of)f(algebraic)2197 1962 y(n)n(um)n(b)r(ers.)86 b(In)43 +b Fi(H.)g(Cohen)i(\(e)l(ditor\),)k(A)n(lgorithmic)44 +b(Num-)2197 2045 y(b)l(er)21 b(The)l(ory:)33 b(Se)l(c)l(ond)22 +b(International)f(Symp)l(osium,)h(ANTS-II)2197 2128 y +Fr(\(1996\),)27 b(Springer)f(V)-6 b(erlag,)26 b(pp.)f(37{49.)2078 +2270 y([7])39 b Fa(Henri)47 b(Cohen,)53 b(C.)48 b(Ba)-5 +b(tut,)53 b(Dominique)48 b(Bernardi,)2197 2353 y(and)64 +b(M.)g(Olivier)p Fr(.)140 b(GP/P)-6 b(ARI)60 b(calculator)j({)f(V)-6 +b(er-)2197 2437 y(sion)49 b(1.39.03.)106 b(Av)l(ailable)49 +b(via)g(anon)n(ymous)e(FTP)j(from)2197 2520 y Fq +(ftp://megrez.math.u-bordeaux.)q(fr)p Fr(,)32 b(1995.)2078 +2662 y([8])39 b Fa(Br)n(uno)136 b(Haible)p Fr(.)349 b(CLN,)131 +b(a)h(class)g(li-)2197 2745 y(brary)21 b(for)h(n)n(um)n(b)r(ers.)k(Av)l +(ailable)c(via)f(anon)n(ymous)g(FTP)h(from)2197 2828 +y Fq(ftp://ftp.santafe.edu/pub/gnu)q(/cln.)q(tar.)q(gz)p +Fr(,)32 b(1996.)2078 2970 y([9])39 b Fa(E.)33 b(A.)g(Kara)-5 +b(tsuba)p Fr(.)49 b(F)-6 b(ast)30 b(ev)l(aluation)h(of)g(transcenden)n +(tal)2197 3053 y(functions.)k Fi(Pr)l(obl.)27 b(Per)l(e)l(dachi)i +(Inform.)e Fh(27)f Fr(\(1991\),)h(76{99.)2040 3195 y([10])39 +b Fa(E.)32 b(A.)g(Kara)-5 b(tsuba)p Fr(.)45 b(On)29 b(fast)h +(computation)f(of)h(transcen-)2197 3278 y(den)n(tal)i(functions.)54 +b Fi(Soviet)35 b(Math.)e(Dokl.)g Fh(43)g Fr(\(1991\),)i(693{)2197 +3362 y(694.)2040 3504 y([11])k Fa(E.)i(A.)g(Kara)-5 b(tsuba)p +Fr(.)71 b(F)-6 b(ast)39 b(ev)l(aluation)f(of)h Fo(\020)5 +b Fr(\(3\).)72 b Fi(Pr)l(obl.)2197 3587 y(Per)l(e)l(dachi)29 +b(Inform.)d Fh(29)g Fr(\(1993\),)i(68{73.)2040 3729 y([12])39 +b Fa(E.)e(A.)g(Kara)-5 b(tsuba)p Fr(.)59 b(F)-6 b(ast)35 +b(calculation)g(of)g(the)f(Riemann)2197 3812 y(zeta)25 +b(function)g Fo(\020)5 b Fr(\()p Fo(s)p Fr(\))24 b(for)i(in)n(teger)f +(v)l(alues)g(of)g(the)g(argumen)n(t)f Fo(s)p Fr(.)2197 +3895 y Fi(Pr)l(obl.)j(Inform.)g(T)-6 b(r)l(ansm.)28 b +Fh(31)e Fr(\(1995\),)h(353{362.)2040 4037 y([13])39 b +Fb(LiDIA)p Fa(-Gr)n(oup)p Fr(.)146 b Fb(LiDIA)63 b(1.3)g +Fi({)f(a)g(libr)l(ary)h(for)f(c)l(om-)2197 4120 y(putational)76 +b(numb)l(er)h(the)l(ory)p Fr(.)191 b(T)-6 b(ec)n(hnisc)n(he)78 +b(Univ)n(er-)2197 4204 y(sit\177)-38 b(at)54 b(Darmstadt,)61 +b(1997.)120 b(Av)l(ailable)54 b(via)g(anon)n(ymous)2197 +4287 y(FTP)i(from)e Fq(ftp://ftp.informatik.tu-dar)q(mstad)q(t.de)2197 +4370 y(/pub/TI/systems/LiDIA)117 b Fr(or)c(via)g(WWW)g(from)2197 +4453 y Fq(http://www.informatik.tu-darm)q(stadt)q(.de/)q(TI/Li)q(DIA)p +Fr(.)2040 4595 y([14])39 b Fa(Thomas)176 b(P)-7 b(ap)i(anik)n(ola)n(ou) +p Fr(.)469 b(Homepage.)2197 4678 y Fq(http://www.math.u-bordeaux.fr)q +(/~pap)q(anik)q Fr(.)2040 4820 y([15])39 b Fa(Thomas)45 +b(P)-7 b(ap)i(anik)n(ola)n(ou)p Fr(.)86 b Fi(Entwurf)43 +b(und)h(Entwicklung)2197 4903 y(einer)f(objektorientierten)i +(Bibliothek)e(f)q(\177)-40 b(ur)42 b(algorithmische)2197 +4986 y(Zahlenthe)l(orie)p Fr(.)36 b(PhD)25 b(Thesis,)i(1997.)2040 +5129 y([16])39 b Fa(Thomas)54 b(P)-7 b(ap)i(anik)n(ola)n(ou,)63 +b(Ingrid)53 b(Biehl,)60 b(and)54 b(Jo-)2197 5212 y(hannes)21 +b(Buchmann)p Fr(.)h Fb(LiDIA)p Fr(:)d(a)h(library)f(for)i +(computational)2197 5295 y(n)n(um)n(b)r(er)k(theory)-6 +b(.)39 b(SFB)28 b(124)g(rep)r(ort,)h(Univ)n(ersit\177)-38 +b(at)27 b(des)h(Saar-)2197 5378 y(landes,)e(1995.)p eop +%%Page: 8 8 +8 7 bop -152 -69 a Fr([17])39 b Fa(Simon)195 b(Plouffe)p +Fr(.)522 b(ISC:)190 b(In)n(v)n(erse)5 14 y(Sym)n(b)r(olic)21 +b(Calculator.)30 b(T)-6 b(ables)23 b(of)f(records)h(of)f(computation,)5 +97 y Fq(http://www.cecm.sfu.ca/proje)q(cts/I)q(SC/r)q(ecord)q(s2.h)q +(tml)p Fr(.)-152 240 y([18])39 b Fa(Eugene)23 b(Salamin)p +Fr(.)k(Computation)21 b(of)i Fo(\031)h Fr(using)d(arithmetic-)5 +323 y(geometric)50 b(mean.)104 b Fi(Mathematics)50 b(of)f(Computation)h +Fh(30)5 406 y Fr(\(1976\),)27 b(565{570.)-152 549 y([19])39 +b Fa(Arnold)83 b(Sch)511 543 y(\177)508 549 y(onha)n(ge,)96 +b(and)82 b(V)n(olker)h(Strassen)p Fr(.)5 632 y(Sc)n(hnelle)38 +b(Multiplik)l(ation)g(gro\031er)h(Zahlen.)71 b Fi(Computing)39 +b Fh(7)5 715 y Fr(\(1971\),)27 b(281{292.)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/ratseries/paper/binsplit.tex b/doc/ratseries/paper/binsplit.tex new file mode 100644 index 0000000..6092b11 --- /dev/null +++ b/doc/ratseries/paper/binsplit.tex @@ -0,0 +1,1130 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% +%%% Version 12, 1999-09-07, Bruno +%%% ----------------------------- +%%% +%%% * Habe neue Referenzen zu den Karatsuba-Arbeiten hinzugefügt, entnommen +%%% dem großartigen Paper CECM-98-118 (98_118-Borwein-Bradley-Crandall.dvi). +%%% * Habe in acm.bst, Funktion format.title, das change.case rausgenommen, +%%% das die Namen von Euler, Riemann u.a. in Kleinbuchstaben konvertiert +%%% hatte. +%%% +%%% Version 11, 1998-12-20, Bruno +%%% ----------------------------- +%%% +%%% * Habe Referenzen zu den Karatsuba-Arbeiten hinzugefügt. +%%% +%%% Version 10, 1998-03-10, Thomas & Bruno +%%% -------------------------------------- +%%% +%%% * Korrigiere die Formel für a(n) bei zeta(3). +%%% * Schönheitsfehler im Literaturverzeichnis. +%%% +%%% Version 9, 1998-03-06, Thomas & Bruno +%%% ------------------------------------- +%%% +%%% * Schreibe \frac{1}{|x|} statt \frac{1}{x}. +%%% +%%% Version 8, 1998-01-16b, Thomas +%%% ------------------------------ +%%% +%%% * Drei Literaturverweise für LiDIA statt nur einem. +%%% +%%% Version 7, 1998-01-16a, Bruno +%%% ----------------------------- +%%% +%%% * Adresse: Praefix F fuer Frankreich +%%% * Abstract: Erwaehne zeta(3) +%%% * Kleinere Korrekturen der O()-Abschaetzungen +%%% +%%% Version 6, 1998-01-14, Thomas +%%% ----------------------------- +%%% +%%% * habe meine Adresse ge"andert. +%%% +%%% * habe Resultat f"ur die Euler Konstante + Kettenbruch eingef"uhrt +%%% +%%% Version 5, 1997-12-11, Thomas +%%% ----------------------------- +%%% +%%% * Habe die Anzahl der Scritte bei der Euler Konstante von +%%% x = ceiling(N log(2)/4)^2 auf x = ceiling((N+2) log(2)/4)^2 +%%% hochgesetzt (Mail von Sofroniou) +%%% +%%% * Habe Kommentar eingef"ugt bzgl Checkpointing bei der Euler +%%% Konstante und Gamma(x) (Mail von Sofroniou) +%%% +%%% * Habe Section zu Geschwindigkeit von Maple gegen"uber Pari +%%% verbessert (mail von Laurent Bernardi). +%%% +%%% Version 4, 1997-01-09, Thomas +%%% ----------------------------- +%%% +%%% * Habe die Komplexitätsaussage für sinh, cosh ergänzt. +%%% * Habe die Versionen der getesteten CAS ergänzt. +%%% +%%% Version 3, 1997-01-07, Bruno +%%% ---------------------------- +%%% +%%% * Meine Firma schreibt sich mit vier Grossbuchstaben. +%%% * Apery schreibt sich m.W. mit einem Akzent. +%%% * Die Fehlermeldung meldet n2-n1>0, nicht n1-n2>0. +%%% * N -> \(N\) (zweimal) +%%% * Leerzeile entfernt nach Display-Formeln, bei denen der Absatz +%%% weitergeht. Hat den Effekt eines \noindent. +%%% * Im Abschnitt: arctan(x) for rational x: "another way" -> "the fastest way" +%%% * "[87]" -> "\cite{87}" +%%% * Das Cohen-Villegas-Zagier brauchen wir nun doch nicht zu zitieren. +%%% * Die "Note:" am Ende von Abschnitt ueber die Gamma-Funktion optisch +%%% verkleinert. +%%% * Die Formel fuer die hypergeometrische Funktionen optisch verschoenert. +%%% Andere Formeln ebenso. +%%% * Figure 2, erste Spalte rechtsbuendig. +%%% * "out performs" -> "outperforms" +%%% * "the streng" -> "the strength" +%%% * Hinweis auf die Parallelisierbarkeit im Abstract. +%%% * Bibtex-Style gehackt, damit nicht jeder zweite Autor auf seine +%%% Anfangsbuchstaben verkuerzt und alleinstehende Autoren ihres +%%% Vornamens beraubt werden. +%%% +%%% Version 2, 1997-01-06, Thomas +%%% ----------------------------- +%%% +%%% * geänderte Abschnitte sind auskommentiert mit %%%. Alle +%%% Änderungen sind als Vorschlag zu verstehen. Der Grund +%%% wird im folgenden angegeben. Falls Du mit einer Änderung +%%% einverstanden bist, kannst Du alle %%%-Zeilen löschen. +%%% +%%% * Lyx defines wurden entfernt. Grund: das ISSAC-acmconf.sty +%%% erlaubt keine fremde macros. Ãœbersetzung mit LaTeX geht. +%%% * habe Keyboardumlaute (ä,ü,ö,ß) in LaTeX umgeschrieben. +%%% Grund: damit die Submission in einem file geht. +%%% * Habe fontenc und psfig usepackage Befehle entfernt. +%%% Grund: fonts bestimmt acmconf.sty und keine Bilder vorhanden. +%%% * Habe bibliography mit BibTeX (binsplit.bib) und acm.bst +%%% erstellt. Grund: wird von ISSAC '97 verlangt. +%%% * Habe langen Formeln in einer eqnarray Umgebung gesteckt. +%%% Grund: acmconf.sty läuft im twocolumn-Modus. Lange Formeln +%%% haben die Ausgabe durcheinander gebracht. +%%% * Habe Reihenfolge bei der Beschreibung der elementare +%%% Funktionen geändert, sodaß zuerst die rationale und dann +%%% die reelle version beschrieben wird. Grund: Einheitlichkeit. +%%% * Habe sinh mit binary-splitting gegen sinh mit exp-Berechnung +%%% getestet. Sie sind ungefähr gleich gut auf meinen Pentium, +%%% mir machen "Wackler" beim cosh. cosh ist ab und zu, sowohl +%%% bei kleiner als auch bei große Präzision langsamer. Habe +%%% dies und dem Abschnitt sinh, cosh ausgefüllt. Grund: es hat +%%% gefehlt. +%%% * Habe artanh Abschnitt entfernt. Grund: ich habe in der +%%% Einleitung der elementaren Funktionen darauf verwiesen, daß +%%% man die Berechnung anderer Funktionen (wie artanh) auf die +%%% hier erwähnte zurückführen oder auf analoger Weise +%%% implementieren kann. Ich denke man braucht nicht alles explizit +%%% anzugeben. +%%% +%%% * Habe Dein Dankeschön an mich entfernt. +%%% * Habe Abschnitt über Konvergenzbeschleunigung entfernt. +%%% Grund: das geht in Dein MathComp paper. +%%% +%%% * Habe neue Formel für pi eingefügt. Grund: einfacher, +%%% effizienter und stimmt mit der angegebenen Referenz +%%% überein. +%%% * Habe die Berechnung der Apery Konstante angepasst. +%%% Grund: die hier angegebenen Formel wurde mit einer +%%% umgeformten Reihe berechnet. Wenn man dieses nicht +%%% kennt, wirkt es verwirrend. Keine Effizienz-steigerung. +%%% * Habe die Beschreibung für die erste version der Euler +%%% Konstante entfernt. Grund: wird von der zweiten version +%%% in jeder Hinsicht (Beweis, Effizienz) gedeckt. +%%% * Habe Abschnitte über Checkpointing und Parallelisierung +%%% eingefügt. Ein Beispiel über die Wirksamkeit habe ich +%%% bei der Apery Konstante angegeben. Grund: damit können wir +%%% das Paper auch bei PASCO '97 einreichen. +%%% +%%% * Habe Beispiel-C++-Implementierung für abpq Reihen eingefügt. +%%% Grund: zeigen wie einfach es ist wenn man die Formeln hat ;-) +%%% * Habe Beispiel-Implementierung für abpqcd Reihen eingefügt. +%%% Grund: dito +%%% * Habe Computational results und Conclusions Abschnitt eingefügt. +%%% * Habe die Namen der Konstanten (C, G, ...) and die entsprechenden +%%% Abschnitten eingefügt. Grund: diese Namen werden bei den +%%% Tabellen im Abschnitt Computational results benutzt. +%%% * Habe Verweis an LiDIA eingefügt. Grund: wird bei Computational +%%% results erw\"ahnt. +%%% +%%% Version 1, 1996-11-30, Bruno +%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Bruno Haible, Thomas Papanikolaou. %%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\documentstyle{acmconf} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Plain TeX macros +%\catcode`@=11 % @ ist ab jetzt ein gewoehnlicher Buchstabe +%\def\@Re{\qopname@{Re}} \def\re#1{{\@Re #1}} +%\def\@Im{\qopname@{Im}} \def\im#1{{\@Im #1}} +%\catcode`@=12 % @ ist ab jetzt wieder ein Sonderzeichen + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% LaTeX2e macros +\catcode`@=11 % @ ist ab jetzt ein gewoehnlicher Buchstabe +\def\re{\mathop{\operator@font Re}\nolimits} +\def\im{\mathop{\operator@font Im}\nolimits} +\def\artanh{\mathop{\operator@font artanh}\nolimits} +\catcode`@=12 % @ ist ab jetzt wieder ein Sonderzeichen + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{document} + +\title{Fast multiprecision evaluation of series of rational numbers} + +\author{ +\begin{tabular}{ccc} +{Bruno Haible} & \hspace*{2cm} & {Thomas Papanikolaou}\\ +{\normalsize ILOG} && {\normalsize Laboratoire A2X}\\ +{\normalsize 9, rue de Verdun} && {\normalsize 351, cours de la Lib\'eration}\\ +{\normalsize F -- 94253 Gentilly Cedex} && {\normalsize F -- 33405 Talence Cedex}\\ +{\normalsize {\tt haible@ilog.fr}} && {\normalsize {\tt papanik@math.u-bordeaux.fr}}\\ +\end{tabular} +} + +\maketitle + +\begin{abstract} + +We describe two techniques for fast multiple-precision evaluation of linearly +convergent series, including power series and Ramanujan series. The computation +time for \(N\) bits is \( O((\log N)^{2}M(N)) \), where \( M(N) \) is the time +needed to multiply two \(N\)-bit numbers. Applications include fast algorithms +for elementary functions, \(\pi\), hypergeometric functions at rational points, +$\zeta(3)$, Euler's, Catalan's and Ap{\'e}ry's constant. The algorithms are +suitable for parallel computation. + +\end{abstract} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Introduction} + +Multiple-precision evaluation of real numbers has become efficiently possible +since Sch\"onhage and Strassen \cite{71} have showed that the bit complexity of +the multiplication of two \(N\)-bit numbers is +\( M(N)=O(N\:\log N\:\log\log N) \). +This is not only a theoretical result; a C++ implementation \cite{96a} can +exploit this already for \( N=40000 \) bits. Algorithms for computing +elementary functions (exp, log, sin, cos, tan, asin, acos, atan, sinh, cosh, +tanh, arsinh, arcosh, artanh) have appeared in \cite{76b}, and a remarkable +algorithm for \( \pi \) was found by Brent and Salamin \cite{76c}. + +However, all these algorithms suffer from the fact that calculated results +are not reusable, since the computation is done using real arithmetic (using +exact rational arithmetic would be extremely inefficient). Therefore functions +or constants have to be recomputed from the scratch every time higher precision +is required. + +In this note, we present algorithms for fast computation of sums of the form + +\[S=\sum _{n=0}^{\infty }R(n)F(0)\cdots F(n)\] +where \( R(n) \) and \( F(n) \) are rational functions in \( n \) with rational +coefficients, provided that this sum is linearly convergent, i.e. that the +\( n \)-th term is \( O(c^{-n}) \) with \( c>1 \). Examples include elementary +and hypergeometric functions at rational points in the {\em interior} of the +circle of convergence, as well as \( \pi \) and Euler's, Catalan's and +Ap{\'e}ry's constants. + +The presented algorithms are {\em easy to implement} and {\em extremely +efficient}, since they take advantage of pure integer arithmetic. The +calculated results are {\em exact}, making {\em checkpointing} and +{\em reuse} of computations possible. Finally, +the computation of our algorithms {\em can be easily parallelised}. + +After publishing the present paper, we were informed that the results of +section 2 were already published by E.~Karatsuba in \cite{91,91b,93,95c}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Evaluation of linearly convergent series} + +The technique presented here applies to all linearly convergent sums of the +form + +\[ S=\sum ^{\infty }_{n=0} +\frac{a(n)}{b(n)}\frac{p(0)\cdots p(n)}{q(0)\cdots q(n)}\] +where \( a(n) \), \( b(n) \), \( p(n) \), \( q(n) \) are integers with +\( O(\log n) \) bits. The most often used case is that \( a(n) \), \( b(n) \), +\( p(n) \), \( q(n) \) are polynomials in \( n \) with integer coefficients. + +\begin{description} +\item [Algorithm:]~ +\end{description} + +Given two index bounds \( n_{1} \) and \( n_{2} \), consider the partial sum + +\[ +S=\sum _{n_{1}\leq n1 \). Hence choosing +\( n_{\max }=N\frac{\log 2}{\log c}+O(1) \) will ensure that the round-off +error is \( <2^{-N} \). By our assumption that \( a(n) \), \( b(n) \), +\( p(n) \), \( q(n) \) are integers with \( O(\log n) \) bits, the integers +\( P \), \( Q \), \( B \), \( T \) belonging to the interval +\( n_{1}\leq n 0."); + break; + + case 1: // the result at the point n1 + r.P = arg.p[n1]; + r.Q = arg.q[n1]; + r.B = arg.b[n1]; + r.T = arg.a[n1] * arg.p[n1]; + break; + + // cases 2, 3, 4 left out for simplicity + + default: // the general case + + // the left and the right partial sum + abpq_series_result L, R; + + // find the middle of the interval + int nm = (n1 + n2) / 2; + + // sum left side + sum_abpq(L, n1, nm, arg); + + // sum right side + sum_abpq(R, nm, n2, arg); + + // put together + r.P = L.P * R.P; + r.Q = L.Q * R.Q; + r.B = L.B * R.B; + r.T = R.B * R.Q * L.T + L.B * L.P * R.T; + break; + } +} +\end{verbatim} + +Note that the multiprecision integers could be replaced here by integer +polynomials, or by any other ring providing the operators \( = \) (assignment), +\( + \) (addition) and \( * \) (multiplication). For example, one could regard +a bivariate polynomial over the integers as a series over the second variable, +with polynomials over the first variable as its coefficients. This would result +an accelerated algorithm for summing bivariate (and thus multivariate) +polynomials. + +\subsection{Example: The factorial} + +This is the most classical example of the binary splitting algorithm and was +probably known long before \cite{87}. + +Computation of the factorial is best done using the binary splitting algorithm, +combined with a reduction of the even factors into odd factors and +multiplication with a power of 2, according to the formula + +\[ +n!=2^{n-\sigma _{2}(n)}\cdot \prod _{k\geq 1} +\left( \prod _{\frac{n}{2^{k}}<2m+1\leq \frac{n}{2^{k-1}}}(2m+1)\right) ^{k}\] +and where the products +\[ +P(n_{1},n_{2})=\prod _{n_{1}0 \). +Because the series is not only linearly convergent -- \( \exp (x) \) is an +entire function --, \( n_{\max }=O(\frac{N}{\log N + \log \frac{1}{|x|}}) \), +hence the bit complexity is +\[ O\left(\frac{(\log N)^2}{\log N + \log \frac{1}{|x|}} M(N)\right) \] +Considering \(x\) as constant, this is \( O(\log N\: M(N)) \). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\subsubsection{\( \exp (x) \) for real \( x \)} + +This can be computed using the addition theorem for exp, by a trick due to +Brent \cite{76a} (see also \cite{87}, section 10.2, exercise 8). Write + +\[ +x=x_{0}+\sum _{k=0}^{\infty }\frac{u_{k}}{v_{k}}\] +with \( x_{0} \) integer, \( v_{k}=2^{2^{k}} \) and +\( |u_{k}|<2^{2^{k-1}} \), and compute +\[ +\exp (x)= +\exp (x_{0})\cdot \prod _{k\geq 0}\exp \left( \frac{u_{k}}{v_{k}}\right) \] + +This algorithm has bit complexity +\[ O\left(\sum\limits_{k=0}^{O(\log N)} \frac{(\log N)^2}{\log N + 2^k} M(N)\right) + = O((\log N)^{2}M(N)) \] + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\subsubsection{ \( \ln (x) \) for rational \( x \)} + +For rational \( |x-1|<1 \), the binary splitting algorithm can also be applied +directly to the power series for \( \ln (x) \). Write \( x-1=\frac{u}{v} \) +and compute the series with \( a(n)=1 \), \( b(n)=n+1 \), \( q(n)=v \), +\( p(0)=u \), and \( p(n)=-u \) for \( n>0 \). + +This algorithm has bit complexity \( O((\log N)^{2}M(N)) \). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\subsubsection{\( \ln (x) \) for real \( x \)} + +This can be computed using the ``inverse'' Brent trick: + +Start with \( y:=0 \). + +As long as \( x\neq 1 \) within the actual precision, choose \( k \) +maximal with \( |x-1|<2^{-k} \). Put \( z=2^{-2k}\left[ 2^{2k}(x-1)\right] \), +i.e. let \( z \) contain the first \( k \) significant bits of \( x-1 \). +\( z \) is a good approximation for \( \ln (x) \). Set \( y:=y+z \) and +\( x:=x\cdot \exp (-z) \). + +Since \( x\cdot \exp (y) \) is an invariant of the algorithm, the final +\( y \) is the desired value \( \ln (x) \). + +This algorithm has bit complexity +\[ O\left(\sum\limits_{k=0}^{O(\log N)} \frac{(\log N)^2}{\log N + 2^k} M(N)\right) + = O((\log N)^{2}M(N)) \] + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\subsubsection{ \( \sin (x) \), \( \cos (x) \) for rational \( x \)} + +These are direct applications of the binary splitting algorithm: For +\( \sin (x) \), put \( a(n)=1 \), \( b(n)=1 \), \( p(0)=u \), +\( q(0)=v \), and \( p(n)=-u^{2} \), \( q(n)=(2n)(2n+1)v^{2} \) for +\( n>0 \). For \( \cos (x) \), put \( a(n)=1 \), \( b(n)=1 \), +\( p(0)=1 \), \( q(0)=1 \), and \( p(n)=-u^{2} \), \( q(n)=(2n-1)(2n)v^{2} \) +for \( n>0 \). Of course, when both \( \sin (x) \) and \( \cos (x) \) are +needed, one should only compute + \( \sin (x) \) this way, and then set +\( \cos (x)=\pm \sqrt{1-\sin (x)^{2}} \). This is a 20\% speedup at least. + +The bit complexity of these algorithms is \( O(\log N\: M(N)) \). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\subsubsection{ \( \sin (x) \), \( \cos (x) \) for real \( x \)} + +To compute \( \cos (x)+i\sin (x)=\exp (ix) \) for real \( x \), again the +addition theorems and Brent's trick +can be used. The resulting algorithm has bit complexity +\( O((\log N)^{2}M(N)) \). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\subsubsection{ \( \arctan (x) \) for rational \( x \)} + +For rational \( |x|<1 \), the fastest way to compute \( \arctan (x) \) with +bit complexity \( O((\log N)^{2}M(N)) \) is +to apply the binary splitting algorithm directly to the power series +for \( \arctan (x) \). Put \( a(n)=1 \), \( b(n)=2n+1 \), \( q(n)=1 \), +\( p(0)=x \) and \( p(n)=-x^{2} \) for \( n>0 \). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\subsubsection{ \( \arctan (x) \) for real \( x \)} + +This again can be computed using the ``inverse'' Brent trick: + +Start out with \( z:=\frac{1}{\sqrt{1+x^{2}}}+i\frac{x}{\sqrt{1+x^{2}}} \) +and \( \varphi :=0 \). During the algorithm \( z \) will be a complex number +with \( |z|=1 \) and \( \re (z)>0 \). + +As long as \( \im (z)\neq 0 \) within the actual precision, choose \( k \) +maximal with \( |\im (z)|<2^{-k} \). +Put \( \alpha =2^{-2k}\left[ 2^{2k}\im (z)\right] \), i.e. let \( \alpha \) +contain the first \( k \) significant bits of \( \im (z) \). \( \alpha \) +is a good approximation for \( \arcsin (\im (z)) \). Set +\( \varphi :=\varphi +\alpha \) and \( z:=z\cdot \exp (-i\alpha ) \). + +Since \( z\cdot \exp (i\varphi ) \) is an invariant of the algorithm, the +final \( \varphi \) is the desired +value \( \arcsin \frac{x}{\sqrt{1+x^{2}}} \). + +This algorithm has bit complexity +\[ O\left(\sum\limits_{k=0}^{O(\log N)} \frac{(\log N)^2}{\log N + 2^k} M(N)\right) + = O((\log N)^{2}M(N)) \] + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\subsubsection{\( \sinh (x) \), \( \cosh (x) \) for rational and real \( x \)} + +These can be computed by similar algorithms as \( \sin (x) \) and +\( \cos (x) \) above, with the same asymptotic bit complexity. The +standard computation, using \( \exp (x) \) and its reciprocal (calculated +by the Newton method) results also to the same complexity and works equally +well in practice. + +The bit complexity of these algorithms is \( O(\log N\: M(N)) \) for rational +\( x \) and \( O((\log N)^{2}M(N)) \) for real \( x \). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\subsection{Example: Hypergeometric functions at rational points} + +The binary splitting algorithm is well suited for the evaluation of a +hypergeometric series + +\[ +F\left( \begin{array}{ccc} +a_{1}, & \ldots , & a_{r}\\ +b_{1}, & \ldots , & b_{s} +\end{array} +\big| x\right) =\sum ^{\infty }_{n=0} +\frac{a_{1}^{\overline{n}}\cdots +a_{r}^{\overline{n}}}{b_{1}^{\overline{n}}\cdots b_{s}^{\overline{n}}}x^{n}\] +with rational coefficients \( a_{1} \), ..., \( a_{r} \), \( b_{1} \), +..., \( b_{s} \) at a rational point \( x \) in the interior of the circle of +convergence. Just put \( a(n)=1 \), \( b(n)=1 \), \( p(0)=q(0)=1 \), and +\( \frac{p(n)}{q(n)}=\frac{(a_{1}+n-1)\cdots +(a_{r}+n-1)x}{(b_{1}+n-1)\cdots (b_{s}+n-1)} \) for \( n>0 \). The evaluation +can thus be done with +bit complexity \( O((\log N)^{2}M(N)) \) for +\( r=s \) and \( O(\log N\: M(N)) \) for \( r0 \). This reduces the complexity to +\( O((\log N)^{2}M(N)) \). Although this is theoretically slower than +Brent-Salamin's quadratically convergent iteration, which has a bit +complexity of \( O(\log N\: M(N)) \), in practice the binary splitted +Ramanujan sum is three times faster than Brent-Salamin, at least in the +range from \( N=1000 \) bits to \( N=1000000 \) bits. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% \subsection{Example: Catalan's constant} + +\subsection{Example: Catalan's constant \( G \)} + +A linearly convergent sum for Catalan's constant +\[ +G:=\sum ^{\infty }_{n=0}\frac{(-1)^{n}}{(2n+1)^{2}}\] +is given in \cite{87}, p. 386: +\[ +G = \frac{3}{8}\sum ^{\infty }_{n=0}\frac{1}{{2n \choose n} (2n+1)^{2}} + +\frac{\pi }{8}\log (2+\sqrt{3}) +\] + +The series is summed using binary splitting, putting \( a(n)=1 \), +\( b(n)=2n+1 \), \( p(0)=1 \), \( q(0)=1 \), and +\( p(n)=n \), \( q(n)=2(2n+1) \) for \( n>0 \). Thus +\( G \) can be computed with bit complexity \( O((\log N)^{2}M(N)) \). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\subsection{Example: The Gamma function at rational points} + +For evaluating \( \Gamma (s) \) for rational \( s \), we first reduce \( s \) +to the range \( 1\leq s\leq 2 \) by the formula \( \Gamma (s+1)=s\Gamma (s) \). +To compute \( \Gamma (s) \) with a precision of \( N \) bits, choose a +positive integer \( x \) with \( xe^{-x}<2^{-N} \). Partial integration lets +us write + +\begin{eqnarray*} +\Gamma (s)&=& \int ^{\infty }_{0}e^{-t}t^{s-1}dt\\ + &=& x^{s}e^{-x}\:\sum ^{\infty }_{n=0} + \frac{x^{n}}{s(s+1)\cdots (s+n)} + +\int^{\infty }_{x}e^{-t}t^{s-1}dt\\ +\end{eqnarray*} +The last integral is \( 0 \), and \( q(n)=32(2n+1)^{5} \). +Thus the bit complexity of computing \( \zeta (3) \) is +\( O((\log N)^{2}M(N)) \). + +\begin{description} +\item [Note:]~ +\end{description} + +Using this the authors were able to establish a new record in the +calculation of \( \zeta (3) \) by computing 1,000,000 decimals \cite{96d}. +The computation took 8 hours on a Hewlett Packard 9000/712 machine. After +distributing on a cluster of 4 HP 9000/712 machines the same computation +required only 2.5 hours. The half hour was necessary for reading the partial +results from disk and for recombining them. Again, we have used binary-splitting +for recombining: the 4 partial result produced 2 results which were combined +to the final 1,000,000 decimals value of \( \zeta (3) \). + +This example shows the importance of checkpointing. Even if a machine crashes +through the calculation, the results of the other machines are still usable. +Additionally, being able to parallelise the computation reduced the computing +time dramatically. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Evaluation of linearly convergent series of sums} + +The technique presented in the previous section also applies to all linearly +convergent sums of the form + +\[ +U=\sum ^{\infty }_{n=0}\frac{a(n)}{b(n)}\left( \frac{c(0)}{d(0)}+\cdots ++\frac{c(n)}{d(n)}\right) \frac{p(0)\cdots p(n)}{q(0)\cdots q(n)}\] + where \( a(n) \), \( b(n) \), \( c(n) \), \( d(n) \), \( p(n) \), +\( q(n) \) are integers with \( O(\log n) \) bits. The most often +used case is again that \( a(n) \), \( b(n) \), \( c(n) \), \( d(n) \), +\( p(n) \), \( q(n) \) are polynomials in \( n \) with +integer coefficients. + +\begin{description} +\item [Algorithm:]~ +\end{description} + +Given two index bounds \( n_{1} \)and \( n_{2} \), consider the partial sums +\[ +S=\sum _{n_{1}\leq n 0."); + break; + + case 1: // the result at the point n1 + r.P = arg.p[n1]; + r.Q = arg.q[n1]; + r.B = arg.b[n1]; + r.T = arg.a[n1] * arg.p[n1]; + r.D = arg.d[n1]; + r.C = arg.c[n1]; + r.V = arg.a[n1] * arg.c[n1] * arg.p[n1]; + break; + + // cases 2, 3, 4 left out for simplicity + + default: // general case + + // the left and the right partial sum + abpqcd_series_result L, R; + + // find the middle of the interval + int nm = (n1 + n2) / 2; + + // sum left side + sum_abpqcd(L, n1, nm, arg); + + // sum right side + sum_abpqcd(R, nm, n2, arg); + + // put together + r.P = L.P * R.P; + r.Q = R.Q * L.Q; + r.B = L.B * R.B; + bigint tmp = L.B * L.P * R.T; + r.T = R.B * R.Q * L.T + tmp; + r.D = L.D * R.D; + r.C = L.C * R.D + R.C * L.D; + r.V = R.D * (R.B * R.Q * L.V + L.C * tmp) + + L.D * L.B * L.P * R.V; + break; + } +} +\end{verbatim} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\subsection{Example: Euler's constant \( C \) \label{eulergamma}} + +\begin{description} +\item [Theorem:]~ +\end{description} + +Let \( f(x)=\sum ^{\infty }_{n=0}\frac{x^{n}}{n!^{2}} \) and +\( g(x)=\sum ^{\infty }_{n=0}H_{n}\frac{x^{n}}{n!^{2}} \). Then for +\( x\rightarrow \infty \), +\( \frac{g(x)}{f(x)}=\frac{1}{2}\log x+C+O\left( e^{-4\sqrt{x}}\right) \). + +\begin{description} +\item [Proof:]~ +\end{description} + +The Laplace method for asymptotic evaluation of exponentially growing +sums and integrals yields +\[ +f(x)= +e^{2\sqrt{x}}x^{-\frac{1}{4}}\frac{1}{2\sqrt{\pi }}(1+O(x^{-\frac{1}{4}}))\] + and +\[ +g(x)=e^{2\sqrt{x}}x^{-\frac{1}{4}}\frac{1}{2\sqrt{\pi }} +\left(\frac{1}{2}\log x+C+O(\log x\cdot x^{-\frac{1}{4}})\right)\] +On the other hand, \( h(x):=\frac{g(x)}{f(x)} \) satisfies the +differential equation +\[ +xf(x)\cdot h''(x)+(2xf'(x)+f(x))\cdot h'(x)=f'(x)\] +hence +\[ +h(x)=\frac{1}{2}\log x+C+c_{2} +\int ^{\infty }_{x}\frac{1}{tf(t)^{2}}dt=\frac{1}{2}\log x+C+O(e^{-4\sqrt{x}})\] + + +\begin{description} +\item [Algorithm:]~ +\end{description} + +To compute \( C \) with a precision of \( N \) bits, set +\[ x=\left\lceil (N+2)\: \frac{\log 2}{4}\right\rceil ^{2} \] +and evaluate the series for \( g(x) \) and \( f(x) \) simultaneously, +using the binary-splitting algorithm, +with \( a(n)=1 \), \( b(n)=1 \), \( c(n)=1 \), \( d(n)=n+1 \), +\( p(n)=x \), \( q(n)=(n+1)^{2} \). Let \( \alpha =3.591121477\ldots \) +be the solution of the equation \( -\alpha \log \alpha +\alpha +1=0 \). Then + \( \alpha \sqrt{x}-\frac{1}{4\log \alpha }\log \sqrt{x}+O(1) \) +terms of the series suffice for the relative error to be bounded +by \( 2^{-N} \). + +\begin{description} +\item [Complexity:]~ +\end{description} + +The bit complexity of this algorithm is \( O((\log N)^{2}M(N)) \). + +\begin{description} +\item [Note:]~ +\end{description} + +This algorithm was first mentioned in \cite{80}. It is by far +the fastest known algorithm for computing Euler's constant. + +For Euler's constant there is no checkpointing possible because +of the dependency on \( x \) in the binary splitting. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Computational results} + +In this section we present some computational results of our CLN and +{\sf LiDIA} implementation of the algorithms presented in this note. We use +the official version (1.3) and an experimental version (1.4a) of {\sf LiDIA}. +We have taken advantage of {\sf LiDIA}'s ability to replace its kernel +(multiprecision arithmetic and memory management) \cite{95,97,97b}, so we were +able to use in both cases CLN's fast integer arithmetic routines. + +\subsection{Timings} + +The table in Figure \ref{Fig1} shows the running times for the calculation of +\( \exp(1) \), \( \log(2) \), \( \pi \), \( C \), \( G \) and \( \zeta(3) \) +to precision 100, 1000, 10000 and 100000 decimal digits. The timings are given +in seconds and they denote the {\em real} time needed, i.e. system and user +time. The computation was done on an Intel Pentium with 133Hz and 32MB of RAM. + +\begin{figure}[htb] +\begin{center} +\begin{tabular}{|l|l|l|l|l|l|l|} +\hline +D &\( \exp(1) \)&\( \log(2) \)&\( \pi \)&\( C \) &\( G \)&\( \zeta(3) \)\\ +\hline +\hline +\( 10^2 \) &0.0005 & 0.0020 &0.0014 & 0.0309 &0.0179 & 0.0027 \\ +\hline +\( 10^3 \) &0.0069 & 0.0474 &0.0141 & 0.8110 &0.3580 & 0.0696 \\ +\hline +\( 10^4 \) &0.2566 & 1.9100 &0.6750 & 33.190 &13.370 & 2.5600 \\ +\hline +\( 10^5 \) &5.5549 & 45.640 &17.430 & 784.93 &340.33 & 72.970 \\ +\hline +\end{tabular} +\caption{{\sf LiDIA-1.4a} timings of computation of constants using +binary-splitting}\label{Fig1} +\end{center} +\end{figure} + +The second table (Figure \ref{Fig2}) summarizes the performance of +\( exp(x) \) in various Computer Algebra systems\footnote{We do not list +the timings of {\sf LiDIA-1.4a} since these are comparable to those of CLN.}. +For a fair comparison of the algorithms, both argument and precision are +chosen in such a way, that system--specific optimizations (BCD arithmetic +in Maple, FFT multiplication in CLN, special exact argument handling in +{\sf LiDIA}) do not work. We use \( x = -\sqrt{2} \) and precision +\( 10^{(i/3)} \), with \( i \) running from \( 4 \) to \( 15 \). + +\begin{figure}[htb] +\begin{center} +\begin{tabular}{|r|l|l|l|l|} +\hline +D & Maple & Pari & {\sf LiDIA-1.3} & CLN \\ +\hline +\hline +21 & 0.00090 & 0.00047 & 0.00191 & 0.00075 \\ +\hline +46 & 0.00250 & 0.00065 & 0.00239 & 0.00109 \\ +\hline +100 & 0.01000 & 0.00160 & 0.00389 & 0.00239 \\ +\hline +215 & 0.03100 & 0.00530 & 0.00750 & 0.00690 \\ +\hline +464 & 0.11000 & 0.02500 & 0.02050 & 0.02991 \\ +\hline +1000 & 0.4000 & 0.2940 & 0.0704 & 0.0861 \\ +\hline +2154 & 1.7190 & 0.8980 & 0.2990 & 0.2527 \\ +\hline +4641 & 8.121 & 5.941 & 1.510 & 0.906 \\ +\hline +10000 & 39.340 & 39.776 & 7.360 & 4.059 \\ +\hline +21544 & 172.499 & 280.207 & 39.900 & 15.010 \\ +\hline +46415 & 868.841 & 1972.184& 129.000 & 39.848 \\ +\hline +100000 & 4873.829 & 21369.197& 437.000 & 106.990 \\ +\hline +\end{tabular} +\caption{Timings of computation of \( \exp(-\sqrt{2}) \)}\label{Fig2} +\end{center} +\end{figure} + +MapleV R3 is the slowest system in this comparison. This is probably due to +the BCD arithmetic it uses. However, Maple seems to have an asymptotically +better algorithm for \( exp (x) \) for numbers having more than 10000 decimals. +In this range it outperforms Pari-1.39.03, which is the fastest system in the +0--200 decimals range. + +The comparison indicating the strength of binary-splitting is between +{\sf LiDIA-1.3} and CLN itself. Having the same kernel, the only +difference is here that {\sf LiDIA-1.3} uses Brent's \( O(\sqrt{n}M(n)) \) +for \( \exp(x) \), whereas CLN changes from Brent's method to a +binary-splitting version for large numbers. + +As expected in the range of 1000--100000 decimals CLN outperforms +{\sf LiDIA-1.3} by far. The fact that {\sf LiDIA-1.2.1} is faster +in the range of 200--1000 decimals (also in some trig. functions) +is probably due to a better optimized \( O(\sqrt{n}M(n)) \) method +for \( \exp(x) \). + +\subsection {Distributed computing of \( \zeta (3) \)} + +Using the method described in \ref{zeta} the authors were the first to +compute 1,000,000 decimals of \( \zeta (3) \) \cite{96d}. +The computation took 8 hours on a Hewlett Packard 9000/712 machine. After +distributing on a cluster of 4 HP 9000/712 machines the same computation +required only 2.5 hours. The half hour was necessary for reading the partial +results from disk and for recombining them. Again, we have used binary-splitting +for recombining: the 4 partial result produced 2 results which were combined +to the final 1,000,000 decimals value of \( \zeta (3) \). + +This example shows the importance of checkpointing. Even if a machine crashes +through the calculation, the results of the other machines are still usable. +Additionally, being able to parallelise the computation reduced the computing +time dramatically. + +\subsection{Euler's constant \( C \)} + +We have implemented a version of Brent's and McMillan's algorithm \cite{80} and +a version accelerated by binary-splitting as shown in \ref{eulergamma}. + +The computation of \( C \) was done twice on a SPARC-Ultra machine +with 167 MHz and 256 MB of RAM. The first computation using the non-acellerated +version required 160 hours. The result of this computation was then verified +by the binary splitting version in (only) 14 hours. + +The first 475006 partial quotients of the continued fraction of \( C \) +were computed on an Intel Pentium with 133 MHz and 32 MB of RAM in 3 hours +using a programm by H. te Riele based on \cite{96e}, which was translated to +{\sf LiDIA} for efficiency reasons. Computing the 475006th +convergent produced the following improved theorem: + +\medskip + +\centerline{If \( C \) is a rational number, \(C=p/q\), then \( |q| > 10^{244663} \)} + +\medskip + +Details of this computation (including statistics on the partial +quotients) can be found in \cite{98}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Conclusions} + +Although powerful, the binary splitting method has not been widely used. +Especially, no information existed on the applicability of this method. + +In this note we presented a generic binary-splitting summation device for +evaluating two types of linearly convergent series. From this we derived simple +and computationally efficient algorithms for the evaluation of elementary +functions and constants. These algorithms work with {\em exact} +objects, making them suitable for use within Computer Algebra systems. + +We have shown that the practical performance of our algorithms is +superior to current system implementations. In addition to existing methods, +our algorithms provide the possibility of checkpointing and parallelising. +These features can be useful for huge calculations, such as those done in +analytic number theory research. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Thanks} + +The authors would like to thank J\"org Arndt, for pointing us to +chapter 10 in \cite{87}. We would also like to thank Richard P. Brent for +his comments and Hermann te Riele for providing us his program for the +continued fraction computation of Euler's constant. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\bibliography{binsplit} +\bibliographystyle{acm} + +\end{document} diff --git a/doc/ratseries/slides/Makefile.devel b/doc/ratseries/slides/Makefile.devel new file mode 100644 index 0000000..2c70d8e --- /dev/null +++ b/doc/ratseries/slides/Makefile.devel @@ -0,0 +1,52 @@ +TEX = tex +DVIPS = dvips -D600 +GNUPLOT = gnuplot + + +all : slide0.ps slide1.ps slide2.ps slide3.ps slide4.ps slide5.ps slide6.ps + +slide0.dvi : slide0.tex + $(TEX) slide0.tex + +slide1.dvi : slide1.tex + $(TEX) slide1.tex + +slide2.dvi : slide2.tex + $(TEX) slide2.tex + +slide3.dvi : slide3.tex + $(TEX) slide3.tex + +slide4.dvi : slide4.tex + $(TEX) slide4.tex + +slide5.dvi : slide5.tex + $(TEX) slide5.tex + +slide6.dvi : slide6.tex fig2.eps + $(TEX) slide6.tex + +fig2.eps : fig2.maple fig2.pari fig2.lidia fig2.cln gnuplot-command + $(GNUPLOT) < gnuplot-command > fig2.eps + +slide0.ps : slide0.dvi + $(DVIPS) -o $@ slide0.dvi + +slide1.ps : slide1.dvi + $(DVIPS) -o $@ slide1.dvi + +slide2.ps : slide2.dvi + $(DVIPS) -o $@ slide2.dvi + +slide3.ps : slide3.dvi + $(DVIPS) -o $@ slide3.dvi + +slide4.ps : slide4.dvi + $(DVIPS) -o $@ slide4.dvi + +slide5.ps : slide5.dvi + $(DVIPS) -o $@ slide5.dvi + +slide6.ps : slide6.dvi + $(DVIPS) -o $@ slide6.dvi + diff --git a/doc/ratseries/slides/epsf.tex b/doc/ratseries/slides/epsf.tex new file mode 100644 index 0000000..e239a4f --- /dev/null +++ b/doc/ratseries/slides/epsf.tex @@ -0,0 +1,138 @@ +% EPSF.TEX macro file: +% Written by Tomas Rokicki of Radical Eye Software, 29 Mar 1989. +% Revised by Don Knuth, 3 Jan 1990. +% +% TeX macros to include an Encapsulated PostScript graphic. +% Works by finding the bounding box comment, +% calculating the correct scale values, and inserting a vbox +% of the appropriate size at the current position in the TeX document. +% +% To use, simply say +% \input epsf % somewhere early on in your TeX file +% \epsfbox{filename.ps} % where you want to insert a vbox for a figure +% +% The effect will be to typeset the figure as a TeX box, at the +% point of your \epsfbox command. By default, the graphic will have its +% `natural' width (namely the width of its bounding box, as described +% in filename.ps). The TeX box will have depth zero. + +% You can enlarge or reduce the figure by saying +% \epsfxsize= \epsfille{filename.ps} +% instead. Then the width of the TeX box will be \epsfxsize, and its +% height will be scaled proportionately. +% (The \epsfbox macro resets \epsfxsize to zero after each use.) + +% If you want TeX to report the size of the figure (as a message +% on your terminal when it processes each figure), say `\epsfverbosetrue'. + +% +\newread\epsffilein % file to \read +\newif\ifepsffileok % continue looking for the bounding box? +\newif\ifepsfbbfound % success? +\newif\ifepsfverbose % report what you're making? +\newdimen\epsfxsize % horizontal size after scaling +\newdimen\epsfysize % vertical size after scaling +\newdimen\epsftsize % horizontal size before scaling +\newdimen\epsfrsize % vertical size before scaling +\newdimen\epsftmp % register for arithmetic manipulation +\newdimen\pspoints % conversion factor + +\pspoints=1truebp % Adobe points are `big' +\epsfxsize=0pt % Default value, means `use natural size' + +% +\def\epsfbox#1{% +% +% The first thing we need to do is to open the +% PostScript file, if possible. +% +\openin\epsffilein=#1 +\ifeof\epsffilein\errmessage{I couldn't open #1, will ignore it}\else +% +% Okay, we got it. Now we'll scan lines until we find one that doesn't +% start with %. We're looking for the bounding box comment. +% + {\epsffileoktrue \chardef\other=12 + \def\do##1{\catcode`##1=\other}\dospecials \catcode`\ =10 + \loop + \read\epsffilein to \epsffileline + \ifeof\epsffilein\epsffileokfalse\else +% +% We check to see if the first character is a % sign; +% if not, we stop reading (unless the line was entirely blank); +% if so, we look further and stop only if the line begins with +% `%%BoundingBox: '. +% + \expandafter\epsfaux\epsffileline. \\% + \fi + \ifepsffileok\repeat + \ifepsfbbfound\else + \ifepsfverbose\message{No bounding box comment in #1; using defaults}\fi + \global\def\epsfllx{72}% + \global\def\epsflly{72}% + \global\def\epsfurx{540}% + \global\def\epsfury{720}\fi + }\closein\epsffilein +% +% Now we have to calculate the scale and offset values to use. +% First we compute the natural sizes. +% + \epsfrsize=\epsfury\pspoints + \advance\epsfrsize by-\epsflly\pspoints + \epsftsize=\epsfurx\pspoints + \advance\epsftsize by-\epsfllx\pspoints +% +% If `epsfxsize' is 0, we default to the natural size of the picture. +% Otherwise we scale the graph to be \epsfxsize wide. +% + \ifnum\epsfxsize=0 \epsfxsize=\epsftsize \epsfysize=\epsfrsize +% +% We have a sticky problem here: TeX doesn't do floating point arithmetic! +% Our goal is to compute y = rx/t. The following loop does this reasonably +% fast, with an error of at most about 16 sp (about 1/4000 pt). +% + \else\epsftmp=\epsfrsize \divide\epsftmp\epsftsize + \epsfysize=\epsfxsize \multiply\epsfysize\epsftmp + \multiply\epsftmp\epsftsize \advance\epsfrsize-\epsftmp + \epsftmp=\epsfxsize + \loop \advance\epsfrsize\epsfrsize \divide\epsftmp 2 + \ifnum\epsftmp>0 + \ifnum\epsfrsize<\epsftsize\else + \advance\epsfrsize-\epsftsize \advance\epsfysize\epsftmp \fi + \repeat + \fi +% +% Finally, we make the vbox and stick in a \special that dvips can parse. +% + \ifepsfverbose\message{#1: width=\the\epsfxsize, height=\the\epsfysize}\fi + \epsftmp=10\epsfxsize \divide\epsftmp\pspoints + \vbox to\epsfysize{\vfil\hbox to\epsfxsize{% + \special{psfile=#1 llx=\epsfllx\space lly=\epsflly\space + urx=\epsfurx\space ury=\epsfury\space rwi=\number\epsftmp}% + \hfil}}% +\fi\epsfxsize=0pt}% + +% +% We still need to define the tricky \epsfaux macro. This requires +% a couple of magic constants for comparison purposes. +% +{\catcode`\%=12 \global\let\epsfpercent=%\global\def\epsfbblit{%BoundingBox:}}% +% +% So we're ready to check for `%BoundingBox:' and to grab the +% values if they are found. +% +\long\def\epsfaux#1#2 #3\\{\ifx#1\epsfpercent + \def\testit{#2}\ifx\testit\epsfbblit + \epsfgrab #3 . . . \\% + \epsffileokfalse + \global\epsfbbfoundtrue + \fi\else\ifx#1\par\else\epsffileokfalse\fi\fi}% +% +% Here we grab the values and stuff them in the appropriate definitions. +% +\def\epsfgrab#1 #2 #3 #4 #5\\{\global\def\epsfllx{#1}\global\def\epsflly{#2}% + \global\def\epsfurx{#3}\global\def\epsfury{#4}}% +% +% Finally, another definition for compatibility with older macros. +% +\let\epsffile=\epsfbox diff --git a/doc/ratseries/slides/fig2.cln b/doc/ratseries/slides/fig2.cln new file mode 100644 index 0000000..bc8873f --- /dev/null +++ b/doc/ratseries/slides/fig2.cln @@ -0,0 +1,13 @@ +# Figure 2's data w.r.t. CLN + 21 0.00075 + 46 0.00109 + 100 0.00239 + 215 0.00690 + 464 0.02991 + 1000 0.0861 + 2154 0.2527 + 4641 0.906 + 10000 4.059 + 21544 15.010 + 46415 39.848 +100000 106.990 diff --git a/doc/ratseries/slides/fig2.eps b/doc/ratseries/slides/fig2.eps new file mode 100644 index 0000000..5e5ea0f --- /dev/null +++ b/doc/ratseries/slides/fig2.eps @@ -0,0 +1,339 @@ +%!PS-Adobe-2.0 EPSF-2.0 +%%Creator: gnuplot +%%DocumentFonts: Helvetica +%%BoundingBox: 50 50 356 302 +%%EndComments +/gnudict 40 dict def +gnudict begin +/Color false def +/Solid false def +/gnulinewidth 5.000 def +/vshift -46 def +/dl {10 mul} def +/hpt 31.5 def +/vpt 31.5 def +/M {moveto} bind def +/L {lineto} bind def +/R {rmoveto} bind def +/V {rlineto} bind def +/vpt2 vpt 2 mul def +/hpt2 hpt 2 mul def +/Lshow { currentpoint stroke M + 0 vshift R show } def +/Rshow { currentpoint stroke M + dup stringwidth pop neg vshift R show } def +/Cshow { currentpoint stroke M + dup stringwidth pop -2 div vshift R show } def +/DL { Color {setrgbcolor Solid {pop []} if 0 setdash } + {pop pop pop Solid {pop []} if 0 setdash} ifelse } def +/BL { stroke gnulinewidth 2 mul setlinewidth } def +/AL { stroke gnulinewidth 2 div setlinewidth } def +/PL { stroke gnulinewidth setlinewidth } def +/LTb { BL [] 0 0 0 DL } def +/LTa { AL [1 dl 2 dl] 0 setdash 0 0 0 setrgbcolor } def +/LT0 { PL [] 0 1 0 DL } def +/LT1 { PL [4 dl 2 dl] 0 0 1 DL } def +/LT2 { PL [2 dl 3 dl] 1 0 0 DL } def +/LT3 { PL [1 dl 1.5 dl] 1 0 1 DL } def +/LT4 { PL [5 dl 2 dl 1 dl 2 dl] 0 1 1 DL } def +/LT5 { PL [4 dl 3 dl 1 dl 3 dl] 1 1 0 DL } def +/LT6 { PL [2 dl 2 dl 2 dl 4 dl] 0 0 0 DL } def +/LT7 { PL [2 dl 2 dl 2 dl 2 dl 2 dl 4 dl] 1 0.3 0 DL } def +/LT8 { PL [2 dl 2 dl 2 dl 2 dl 2 dl 2 dl 2 dl 4 dl] 0.5 0.5 0.5 DL } def +/P { stroke [] 0 setdash + currentlinewidth 2 div sub M + 0 currentlinewidth V stroke } def +/D { stroke [] 0 setdash 2 copy vpt add M + hpt neg vpt neg V hpt vpt neg V + hpt vpt V hpt neg vpt V closepath stroke + P } def +/A { stroke [] 0 setdash vpt sub M 0 vpt2 V + currentpoint stroke M + hpt neg vpt neg R hpt2 0 V stroke + } def +/B { stroke [] 0 setdash 2 copy exch hpt sub exch vpt add M + 0 vpt2 neg V hpt2 0 V 0 vpt2 V + hpt2 neg 0 V closepath stroke + P } def +/C { stroke [] 0 setdash exch hpt sub exch vpt add M + hpt2 vpt2 neg V currentpoint stroke M + hpt2 neg 0 R hpt2 vpt2 V stroke } def +/T { stroke [] 0 setdash 2 copy vpt 1.12 mul add M + hpt neg vpt -1.62 mul V + hpt 2 mul 0 V + hpt neg vpt 1.62 mul V closepath stroke + P } def +/S { 2 copy A C} def +end +%%EndProlog +gnudict begin +gsave +50 50 translate +0.050 0.050 scale +0 setgray +/Helvetica findfont 140 scalefont setfont +newpath +LTa +LTb +672 771 M +63 0 V +5154 0 R +-63 0 V +588 771 M +(0.001) Rshow +672 1191 M +63 0 V +5154 0 R +-63 0 V +-5238 0 R +(0.01) Rshow +672 1610 M +63 0 V +5154 0 R +-63 0 V +-5238 0 R +(0.1) Rshow +672 2030 M +63 0 V +5154 0 R +-63 0 V +-5238 0 R +(1) Rshow +672 2450 M +63 0 V +5154 0 R +-63 0 V +-5238 0 R +(10) Rshow +672 2870 M +63 0 V +5154 0 R +-63 0 V +-5238 0 R +(100) Rshow +672 3290 M +63 0 V +5154 0 R +-63 0 V +-5238 0 R +(1000) Rshow +672 3710 M +63 0 V +5154 0 R +-63 0 V +-5238 0 R +(10000) Rshow +672 351 M +0 63 V +0 4555 R +0 -63 V +672 211 M +(10) Cshow +1023 351 M +0 31 V +0 4587 R +0 -31 V +1486 351 M +0 31 V +0 4587 R +0 -31 V +1724 351 M +0 31 V +0 4587 R +0 -31 V +1837 351 M +0 63 V +0 4555 R +0 -63 V +0 -4695 R +(100) Cshow +2188 351 M +0 31 V +0 4587 R +0 -31 V +2652 351 M +0 31 V +0 4587 R +0 -31 V +2890 351 M +0 31 V +0 4587 R +0 -31 V +3003 351 M +0 63 V +0 4555 R +0 -63 V +0 -4695 R +(1000) Cshow +3353 351 M +0 31 V +0 4587 R +0 -31 V +3817 351 M +0 31 V +0 4587 R +0 -31 V +4055 351 M +0 31 V +0 4587 R +0 -31 V +4168 351 M +0 63 V +0 4555 R +0 -63 V +0 -4695 R +(10000) Cshow +4519 351 M +0 31 V +0 4587 R +0 -31 V +4982 351 M +0 31 V +0 4587 R +0 -31 V +5220 351 M +0 31 V +0 4587 R +0 -31 V +5333 351 M +0 63 V +0 4555 R +0 -63 V +0 -4695 R +(100000) Cshow +5684 351 M +0 31 V +0 4587 R +0 -31 V +672 351 M +5217 0 V +0 4618 V +-5217 0 V +672 351 L +3280 71 M +(N) Cshow +LT0 +5406 4766 M +(Maple) Rshow +5490 4766 M +252 0 V +1047 752 M +397 186 V +393 253 V +388 206 V +389 231 V +389 235 V +388 266 V +388 283 V +389 288 V +388 269 V +389 295 V +388 315 V +5574 4766 D +1047 752 D +1444 938 D +1837 1191 D +2225 1397 D +2614 1628 D +3003 1863 D +3391 2129 D +3779 2412 D +4168 2700 D +4556 2969 D +4945 3264 D +5333 3579 D +LT1 +5406 4626 M +(Pari) Rshow +5490 4626 M +252 0 V +1047 633 M +397 59 V +393 165 V +388 218 V +389 283 V +389 449 V +388 204 V +388 344 V +389 347 V +388 356 V +389 356 V +388 434 V +5574 4626 A +1047 633 A +1444 692 A +1837 857 A +2225 1075 A +2614 1358 A +3003 1807 A +3391 2011 A +3779 2355 A +4168 2702 A +4556 3058 A +4945 3414 A +5333 3848 A +LT2 +5406 4486 M +(LiDIA) Rshow +5490 4486 M +252 0 V +1047 889 M +397 41 V +393 88 V +388 120 V +389 184 V +389 224 V +388 264 V +388 295 V +389 289 V +388 308 V +389 214 V +388 223 V +5574 4486 B +1047 889 B +1444 930 B +1837 1018 B +2225 1138 B +2614 1322 B +3003 1546 B +3391 1810 B +3779 2105 B +4168 2394 B +4556 2702 B +4945 2916 B +5333 3139 B +LT3 +5406 4346 M +(CLN) Rshow +5490 4346 M +252 0 V +1047 718 M +397 69 V +393 143 V +388 193 V +389 267 V +389 193 V +388 196 V +388 233 V +389 274 V +388 238 V +389 178 V +388 180 V +5574 4346 C +1047 718 C +1444 787 C +1837 930 C +2225 1123 C +2614 1390 C +3003 1583 C +3391 1779 C +3779 2012 C +4168 2286 C +4556 2524 C +4945 2702 C +5333 2882 C +stroke +grestore +end +showpage +%%Trailer diff --git a/doc/ratseries/slides/fig2.lidia b/doc/ratseries/slides/fig2.lidia new file mode 100644 index 0000000..3237006 --- /dev/null +++ b/doc/ratseries/slides/fig2.lidia @@ -0,0 +1,13 @@ +# Figure 2's data w.r.t. LiDIA-1.2.1 + 21 0.00191 + 46 0.00239 + 100 0.00389 + 215 0.0075 + 464 0.0205 + 1000 0.0704 + 2154 0.299 + 4641 1.51 + 10000 7.36 + 21544 39.9 + 46415 129 +100000 437 diff --git a/doc/ratseries/slides/fig2.maple b/doc/ratseries/slides/fig2.maple new file mode 100644 index 0000000..047ff73 --- /dev/null +++ b/doc/ratseries/slides/fig2.maple @@ -0,0 +1,13 @@ +# Figure 2's data w.r.t. Maple + 21 0.0009 + 46 0.0025 + 100 0.0100 + 215 0.031 + 464 0.11 + 1000 0.40 + 2154 1.719 + 4641 8.121 + 10000 39.340 + 21544 172.499 + 46415 868.841 +100000 4873.829 diff --git a/doc/ratseries/slides/fig2.pari b/doc/ratseries/slides/fig2.pari new file mode 100644 index 0000000..b7ddc65 --- /dev/null +++ b/doc/ratseries/slides/fig2.pari @@ -0,0 +1,13 @@ +# Figure 2's data w.r.t. Pari + 21 0.00047 + 46 0.00065 + 100 0.0016 + 215 0.0053 + 464 0.025 + 1000 0.294 + 2154 0.898 + 4641 5.941 + 10000 39.776 + 21544 280.207 + 46415 1972.184 +100000 21369.197 diff --git a/doc/ratseries/slides/fig2log.cln b/doc/ratseries/slides/fig2log.cln new file mode 100644 index 0000000..f0fcb1d --- /dev/null +++ b/doc/ratseries/slides/fig2log.cln @@ -0,0 +1,13 @@ +# Figure 2's data w.r.t. CLN +1.32 -3.12 +1.66 -2.96 +2.00 -2.62 +2.33 -2.16 +2.67 -1.52 +3.00 -1.06 +3.33 -0.60 +3.67 -0.04 +4.00 0.61 +4.33 1.18 +4.67 1.60 +5.00 2.03 diff --git a/doc/ratseries/slides/fig2log.lidia b/doc/ratseries/slides/fig2log.lidia new file mode 100644 index 0000000..3d88bfe --- /dev/null +++ b/doc/ratseries/slides/fig2log.lidia @@ -0,0 +1,13 @@ +# Figure 2's data w.r.t. LiDIA-1.2.1 +1.32 -2.72 +1.66 -2.62 +2.00 -2.41 +2.33 -2.12 +2.67 -1.69 +3.00 -1.15 +3.33 -0.52 +3.67 0.18 +4.00 0.87 +4.33 1.60 +4.67 2.11 +5.00 2.64 diff --git a/doc/ratseries/slides/fig2log.maple b/doc/ratseries/slides/fig2log.maple new file mode 100644 index 0000000..ec60598 --- /dev/null +++ b/doc/ratseries/slides/fig2log.maple @@ -0,0 +1,14 @@ +# Figure 2's data w.r.t. Maple +1.32 -3.05 +1.66 -2.60 +2.00 -2.00 +2.33 -1.51 +2.67 -0.96 +3.00 -0.40 +3.33 0.24 +3.67 0.91 +4.00 1.59 +4.33 2.24 +4.67 2.94 +5.00 3.69 + diff --git a/doc/ratseries/slides/fig2log.pari b/doc/ratseries/slides/fig2log.pari new file mode 100644 index 0000000..1be3ac0 --- /dev/null +++ b/doc/ratseries/slides/fig2log.pari @@ -0,0 +1,13 @@ +# Figure 2's data w.r.t. Pari +1.32 -3.33 +1.66 -3.19 +2.00 -2.80 +2.33 -2.28 +2.67 -1.60 +3.00 -0.53 +3.33 -0.05 +3.67 0.77 +4.00 1.60 +4.33 2.45 +4.67 3.29 +5.00 4.33 diff --git a/doc/ratseries/slides/gnuplot-command b/doc/ratseries/slides/gnuplot-command new file mode 100644 index 0000000..18a063e --- /dev/null +++ b/doc/ratseries/slides/gnuplot-command @@ -0,0 +1,7 @@ +set term postscript eps +set size 0.85,1 +set logscale x 10 +set logscale y 10 +set ytics (0.001,0.01,0.1,1,10,100,1000,10000) +set xlabel "N" +plot [10:300000] [0.0001:10000000] 'fig2.maple' title 'Maple' with linespoints, 'fig2.pari' title 'Pari' with linespoints, 'fig2.lidia' title 'LiDIA' with linespoints, 'fig2.cln' title 'CLN' with linespoints diff --git a/doc/ratseries/slides/slide0.dvi b/doc/ratseries/slides/slide0.dvi new file mode 100644 index 0000000000000000000000000000000000000000..8dfbbb88a90fa47ad820c3ae1501b2d4b9e26bd2 GIT binary patch literal 460 zcmey)#MnIPfQ&T*5U?GPRtQOrP{=PWDJU&bFtoHZ*E2BJGc>a@GBz~n2C85LDI)~_ z13~ZnPYeuw3m7eK>hv!7_bxT8ccRw*s?SE3xaX-c2)eIh-~yV$nw*7$g%gbxl!XL1JEJ_T>DW z#Qf5}g}sv)+B~0rX1+OjK@bBw&@d2Y0UBt&&d78c)5a5Cr8$+8LE+ceH(!E*q2~us jUJE&(83S(WfC7hsiGdNT!>|SwHXDBeV49 DI<0003150601E0143E01FFEB07FE91B55A5E5E5E16804BC7FC15 +F815E0D9C7FEC8FC01C0C9FCADEC3FF09038C1FFFE01C76D7E9039DFE03FC09039FF000F +F001FC6D7E01F06D7E496D7E496D7E491580167FC913C0A217E0163FA317F0A3120CEA3F +80487E12FF7FA317E049147F5B6CC813C01278007CEDFF807E4B13006C4A5A6C6C495AD8 +07E0495AD803F8495A6CB4EBFFC06C90B55A013F49C7FC010F13F8010113802C457AC239 +>53 D<121E121F13E090B712FEA35A17FC17F817F017E0A2003EC8EA07C048ED0F801700 +00785D163E5E5E485D15014B5AC8485A5E150F4BC7FC153E153C157C5DA24A5A14035D14 +075D140FA24A5AA2143FA2147F92C8FCA25CA35BA25CA21303A51307AA6D5AA2EB00F02F +4679C339>55 D57 D<49B612FCA490C7383FFE006F5A150FB3B3A91206EA1F80487E487E48 +7EA34B5AA25B6C48495A495C003EC7127F5E6C6C495A260FE00390C7FC3903FC0FFC6CB5 +5A6C6C13C0D90FFEC8FC2E477AC43B>74 D108 D117 D121 D E /Fb 18 118 +df66 +D72 D80 D<001FBF12C0A54AC7000391C71203 +4801C06E49DA001F13E091C949150701FC1B0101F0F3007F491C3F491C1F491C0FA290CA +1807A2003E1D03A348F501F0A500781D00A8481E78A6CB1900B3B3B3B04D7FA205076D7E +057F14F8037FB912F8A56D757AF47A>84 D<913801FFF0021F13FF027F14C00103B612F0 +499038007FFCD91FF0EB0FFFD93FC001037F49C76C7F01FC6E6C7E496F7E486C8248B46C +6E7E6E140F6E8148707E80717FA4717F6C5BA26C5B6C6CC8FC90C9FCA7173F047FB5FC03 +0FB6FC92B7FC0207EBFE01023F13C09138FFFE00010313F0010F13C04990C7FCEB3FFCEB +FFF84813E0485B485BA24890C8FC485AA2485AF201E0485AA312FF5B5FA45FA26D5D007F +160E171E6C6C923A3C7FE003C07F001F0478EBF0076C6CDBF03F14806C6DD903E0EBF80F +6C01E0903B07C01FFE3F006C01F8903A1F800FFFFE6C01FFD9FF005C013FD9FFFE01035B +010F02F86D13E0010102E06D6CC7FCD9000F90CBFC4B4F79CC54>97 +D<143F0003B5FCB6FCA5C6FC131F7FA27FB3AFEF7FF80403B57E041F14F0047F14FC923A +01FFC03FFE923B03FC0007FF80DB07F001017FDB0FC09038007FF04BC86C7E033EED0FFC +4B6F7E4B6F7E4B834B814B6F7F874B707EA292CA6C7EA2871A1F87A2747EA31C80A386A2 +1CC0AE1C80A262A21C00A3505AA3631A3F631A7F6F5F505A814F5B6F4B5BDAFDF094C7FC +DAFCF84B5ADAF8784B5A037E4B5A4A6CED7FF06F6C4A5A9126E00FE001035BDB03F8010F +90C8FC4A6CB4EB7FFC6F90B55A4A013F14C090C8000F49C9FC040013E0527A7BF75E>I< +923807FF80037F13F00203B512FE020F6E7E91263FFE0313E0913A7FF0007FF0902601FF +C0EB1FF84990C76C7E49486E7E49486E7E49486E138049486E13C04948ED7FE013FF4AED +3FF0485B4818F8181F4890C9FC19FC4848160FA2001F18FEA248481607A319FF127FA25B +A212FF90BAFCA401F8CBFCA9127FA27FA3123FA36C7EA2190F6C7EA26C181F6C6D161E19 +3E6C6D163C6C187C6E16786D6C16F8013FEE01F06D6C16E06D6C15036D6CED0FC06D6C6C +EC1F806D6DEC3F006D01F014FEDA3FFCEB03F8913A0FFFC03FF06E90B512C0020092C7FC +033F13FC030313C0404F7BCC4B>101 D<143F0003B5FCB6FCA5C6FC131F7FA27FB3AFEF +3FFC4CB512C0040F14F04C14FC93397FC03FFE9339FE000FFFDB01F801037FDB03E06D7F +4B486D7F4BC8FC031E6F7EA24B6F7E5D157015F04B6F7EA25DA35DA492C9FCB3B3A7496D +4B7EA2017F01F04AB512C0B7D8F803B712E0A553787AF75E>104 +DI<143F0003B5 +FCB6FCA5C6FC131F7FA27FB3B10503B612F8A5DD007F14007213F07213C097C7FC19FC61 +19E0614EC8FC187E604D5A4D5A4D5A4D5A4D5A053EC9FC17FC4C5A4C5A4C5A4C5A161F4C +7E167F4C7E03037F5D4B7F92381F9FFEED3F1F92387E0FFF4B6C7F15F8DBE0037F4B6C7F +158092C77F4A6E7EA2717E717E8483717F8583717F8583727E85183F727E8584727F8686 +8486496C4B7F1AFE017F01E0021FEBFFC0B700F090B7FCA550787BF759>107 +D<143F0003B5FCB6FCA5C6FC131F7FA27FB3B3B3B3B3AB497FA2017F13F0B712F8A52578 +7BF72E>I<027EDA3FFCEEFFF02603FFFE49B500C0020713FFB5020F02F0023F14C04C02 +FC4A14F093277FC03FFE4948C67F9327FE000FFFD903F8EB3FFCDB01F8010390268007E0 +EB0FFEC6DA03E06D9026C00F806D7E011F49486D6D48C76C7F010F49C8143C031E6F6C48 +6E7F13074B6F6C486E7F4BEEF9E003705F03F016FB4B6FB4486F7E14FF4B94C9FCA34B5E +A492C95BB3B3A7496D4B6C4C7EA2017F01F04AB500C0020713FFB7D8F803B7D8E00FB712 +80A5814C7ACB8C>I<027EEC3FFC2603FFFE49B512C0B5020F14F04C14FC93397FC03FFE +9339FE000FFFDB01F801037FC6DA03E06D7F011F49486D7F010F49C8FC031E6F7E13074B +6F7E5D157015F04B6F7E14FF5DA35DA492C9FCB3B3A7496D4B7EA2017F01F04AB512C0B7 +D8F803B712E0A5534C7ACB5E>I<923801FFC0031F13FC92B67E020315E0020F9038007F +F8DA3FF8EB0FFEDA7FC0EB01FF4948486D13C04948C8EA3FE049486F7E49486F7E49486F +7E49486F7E017F8349486F7F4A8148854890CA6C7EA24848717EA2000F8549171F001F85 +A3003F85A249170F007F85A500FF1A80AD007F1A00A36D5F003F61A3001F61A26D173F00 +0F61A26C6C4D5AA26C6D4C5A6C616E5D6C616D6C4B90C7FC013F5F6D6C4B5A6E150FD907 +FCED1FF06D6C4B5A6D6C6CECFFC06D01E001035BDA3FF8D90FFEC8FC6EB4EB7FFC020790 +B512F002001580033F49C9FC030113C0494F7BCC54>I<023FEC7FF80003B50103B57EB6 +011F14F0047F14FC923A01FFC03FFE923B03FC0007FF80DB07F06D7FC6DA0FC0010013F0 +011F49C86C7E6D013E6F7E4B6F7E6D496F7E4B6F7F4B814B83737F4B6F7FA292CA6C7EA2 +871A3F871A1F87A3741380A57413C0AE501380A41C0062A2631A3FA2631A7F631AFF6F5F +4F5B814F5B6F4B5B6F4B90C7FC6F5E03784B5A037E4B5A6FEDFFF06F6C495BDB0FE00107 +5BDB03F8011F90C8FC6FB4EBFFFC6F90B55A043F14C0040F49C9FC040013E094CBFCB3A5 +497FA2017F13F0B712F8A5526D7BCB5E>I<027E49B4FC2603FFFE010F13C0B5023F13F0 +4C13F89338FF07FC923901F80FFE923803E01FC6913907C03FFF011FEB0F80010FEB1F00 +151E01075BA24BEB1FFEA24BEB0FFCEF03F04B90C7FC14FFA25DA35DA692C9FCB3B3A349 +7F81017F13F8B8FCA5384C7BCB42>114 D<913A0FFF8001C049B5EAF003010FECFE0701 +3FECFF0F90267FF80013DF2601FF80EB1FFF4848C71207D807F8140148488049157F4848 +153F4848151FA2007F160F90C9FCA2481607A317037FA27FA27F7FD87FFC92C7FC7F383F +FFC014F86CEBFF8015FC6CECFFE06C15FC6CEDFF806C16E06C6C816D15FC010F81010381 +01001680020F15C0DA007F14E01503DB003F13F0040713F816017013FC0070163F00F016 +1FEF0FFE7E17071703A27E1701A27EA36C17FCA26D150318F87F6D150718F06DED0FE06D +151F6DED3FC001BFED7F80D91F80903801FF0026FE0FE0EB07FE26FC07FEEB7FF86DB65A +48C615C048013F49C7FC48010313E0374F7BCC42>I<023F17FC0003B5ED0FFFB60203B5 +FCA5C6EE0003011FEE007F6D173FA26D171FB3B3A7193FA4197FA319FF7F606F15DF6D16 +03F0079F866D6DEC0F1F027F031E7F6F027C14E0DA3FF802F8ECFFE0DA1FFEEB03F0913A +07FFC01FE06E90B512C002001500033F01FCEDF800030101E00280C7FC534E7ACB5E> +117 D E /Fc 17 119 df[ +137 169 120 296 156 70 D<0407B57E0303B7FC033F16E04AB812FE020F717E023F18 +F091BA12FC49850107737E499126FE000F81490280010115F0706D6C80496E6E8049050F +80706E8090B66C6E818589486F6E81A274808986A28986896C5DA36D4A6F806D5CA26D5C +6D5C6D91C9FC010113FC9038003FE091CBFCA897B7FC060FB8FC0507B9FC94BAFC160F93 +BBFC1507153F92B812CF0207EEE00F021FEDFE00027F15E091B71280010303FCC7FC4915 +F04915C0495D017F4AC8FC5E90B65A485D485D485DA2485D4892C9FCA25A5D5A5DA3B6FC +5DA462A462816C61A297B7FC6C80616C6E4B5A0707826C6F4A48816C6F4A4815F0073F16 +FE6C6F9126FFF07FECFFFE6C03F84901E0826C6F010F01C017806D9126FF807F497E011F +92B612006D4D7F01034D7F01004D1303023F04E07F020704806D7E02004BC8000F150003 +0F02F003015CDB007F90CEFC717179EF79>97 D[ +125 173 124 299 138 I<943807FFFE94B612F8040FEDFF80047F16F00303B812FC030F +17FF033F18C04B844ABA12F80207854ADBC007804A4AC7FC4A02F849804A4A178091B600 +C05B494B4915C04992C7FC495C494D15E0495C5E5B5B5E90B6FC485DA2487215C05E5A73 +158048721500A24C6E5C48735B745B080F13E048070190C7FC97C9FCA293CDFC5AA6B7FC +B37EA5827EA47EA2827EF41FF8A26C6FEF3FFCA26C1B7F826C1CF81CFF6C815113F06D80 +6D4F13E0826D4F13C06D6E4C13806D6F5D6D6F4B1300714B5A6D6FEC01FF6D03FC4A5B6E +02FF020F5B021F03C0013F5B6EDBF803B55A6E92B75A0201616E4EC7FC033F5F030F17F0 +030317C0DB007F93C8FC040F15F8040015C0050701F8C9FC5E7178EF6E>I<943803FFFC +94B612F0040715FE043FEDFFC04BB812F0030717FC031F17FF037F18C04ABA7E4ADBC03F +14F8020F9126FE0007804A02F80101804A4A6D6C7F4A02C06E8091B6486E804992C86C80 +494A81497280494A84494A814972805E49737F5E90B68548864C19805A87481DC0A25E48 +7414E0A25AA21EF0A24892CA7EA35AA21EF8A4B7FCA393BBFCA61EF01EE093CEFCA77EA6 +7EA2827EA47EF51FE06C6FF03FF0F57FF8A27E7018FF7E5213F06C816D5013E0826D5013 +C06D6E5F704D13806D626D6E4D13006D6F93B5FC6D6F4B5B6D6F4B5B6E02F8030F5B6E6E +033F5B6E02FF92B55A6E03C001075C020303FC017F5C6E92B748C7FC6E6C60031F606F18 +E0030118806F6C4CC8FC040F16F0040116C0DC001F02FCC9FCDD007F1380657179EF74> +101 D[<96B5FC063F14E00503B612FC051F15FF94B812C0040383040F83043F8393B97E +4BDBF03F7F4BDB807F7F030F4A48B6FC4B02F816804B4A5A4B4A4815C018C092B6008016 +E04A4B5A4A5CA24A5CA25C5F5CA24A4A6D15C0A2731580A24A4A6D1500745B745B745B74 +5B0801138097C9FCB3A9003FBA12C0ACC76C02F0CBFCB3B3B3B3AEBB7EAB49C97E>91 +173 121 300 76 I[<4AB4FC020F13E0023F13F891B512FE49804981498149814981A249 +81A24981A390B77EA96D5DA36D5DA26D5DA26D5D6D5D6D5D6D92C8FC6D5C023F13F8020F +13E0020190C9FC91CBFCB3A5EE7FF0010FB6FC007FB7FCACEA000F13017FA280B3B3B3B3 +A9BA12E0AB49C81203>59 173 122 300 68 105 D[61 172 122 299 +68 108 D<922601FFC0DB7FFF953803FFF8013FB60307B500F8053FEBFFC0B8033FDAFF +804BB612FC4FB700E0030F15FF070704F8033F16C0071F04FE92B812F04F704A8396B96C +0107834E7249834E02006F49D9F807804E01F06D6E49D98003814E01C06D4C48487E4E90 +C76C6ED9FFF86D81DE3FFC714801E083D8001F4C486E4B49800101DCFFE0714890C8816D +4D6105C1496E6E48486F806E02C390C84C5A4E62DDC7FCDFBFE084DDCFF8F1FFC04E6205 +DF70864E97C9FC05FF8E4E614E61A395C95EA24D62A34D62A54D62B3B3B3A5BAD8FC03BA +D8E01FBAFCAB49C8000104F0C8000F0480C87EC86F7AEECF>I<922601FFC0ED7FFF013F +B60307B512F8B8033FECFF804FB712E0070716F8071F16FE4F8296B97E4E844E0200814E +01F06D804E01C07F4E90C76C80DE3FFC83D8001F4C48800101DCFFE0836D5F05C1496E80 +6E02C390C8FC60DDC7FC85EFCFF86005DF826005FF866060A395C9FCA25FA35FA55FB3B3 +B3A5BAD8FC03BA12E0AB49C8000104F0C8120F836F7AEE8A>I<943803FFFE057FEBFFF0 +0407B7FC043F16E04BB812FC030717FF031F18C0037F18F092BA7E0203DBC01F14FE4A91 +26FC0001804A02F06D6C80023F4A6E14E04A0280020F8091B6C86C80494A6F80494A6F80 +494A6F80A2494A7080494A70804988A2494A708090B686A2484B7080A24889A24889A248 +1E80A34892CA6C15C0A4481EE0A4481EF0A6B71BF8B16C1EF0A66C1EE0A46C6F4C15C0A4 +6C1E80A26C1E00A26C65705E6C65A26C65705E6D64705E6D646D6E93B65A6D646D6E4B92 +C7FC705D6D6E4B5C6D6F4A5C6D03E0023F5C023F6E4A14E06E02FE0103B65A6E9126FFC0 +1F5D6E92B8C8FC020119FC6E6C18F06F60030F1880030105FCC9FC6F6C16F0040F168004 +0003F8CAFC050349CBFC6D7179EF7C>II<4BB46C903807FF +80013FB6023F13FCB849B67E4E15E0060F15F84E15FE4E814E168095B812C00581D9FC0F +14E0DFF01F14F0058313C00587D9003F14F84E4914FCD8000FED8FFC01015E6DDB9FF090 +B612FEA26EECBFE0A26017FF60A295C7FC7414FCA34D6E14F87414F0A24D6E14E07414C0 +7414800800EBFE00F31FF04D92C8FCA95FB3B3B2BB7EAB49C97E5F6F7CEE6A>114 +D<4BB5EC0FC0037F02F8133F0207B7EBFFE0023F16C391BAFC13035B131F49EC00034901 +F0EB003F90B50080140F4849C812034849814A8148498248498285484982A248845C5A85 +A4B56C82A380A2806E705B14FE6E94C8FC15C015F015FE6CECFFE016FF17F8EFFFC06C17 +F818FF6C18E019F86C18FE856C19C06C856C851AFC6C856D847F010F856D856D8513006E +84021F841403DA007F83150F0300831607EE003F050181EF003F18077215801800D83FE0 +83007F181F486C83A2856D83A2857FA285A27F1C007FA280636E5EA26E6061806E606E4C +5B6E5E6E4C5B6F4B5B03E05D03F84AB55A03FE020F91C7FCDBFFE090B55A93B75A62023F +17E0496C5FD9F80794C8FCD9F00116F89026C0003F15E06C4801074AC9FC007EC86C13C0 +517178EF62>I[<923801FFE0AA5DA75DA45DA45DA35DA25DA392B5FCA25C5CA25C5C5CA2 +5C5C91B6FC13035B011F92B71280137F0007BBFCBCFCA9D8000103E0C9FCB3B3B2F27FF8 +B3A31AFF6D6F15F0A36E5E1BE0836E4C13C0836E5E7115806E6E4913006EED803F6E9238 +E07FFE6E92B55A806F5E6F5E6F5E03075E030193C7FCDB003F5C040714F0DC001F1380> +77 158 123 284 97 III E end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: a4 +%%BeginPaperSize: a4 +a4 +%%EndPaperSize + +%%EndSetup +%%Page: 1 1 +1 0 bop 613 563 a Fc(F)-21 b(ast)82 b(m)-7 b(ultiprecision)84 +b(ev)-14 b(aluation)690 1142 y(of)83 b(series)f(of)h(rational)f(n)-7 +b(um)g(b)7 b(ers)1751 2347 y Fb(Bruno)56 b(Haible)1425 +2864 y(Thomas)h(P)-5 b(apanik)g(olaou)1927 4069 y Fa(25)39 +b(July)f(1997)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/ratseries/slides/slide0.tex b/doc/ratseries/slides/slide0.tex new file mode 100644 index 0000000..fac9b0d --- /dev/null +++ b/doc/ratseries/slides/slide0.tex @@ -0,0 +1,26 @@ +\magnification=\magstep3 +\hsize=19truecm +\vsize=19truecm +\nopagenumbers +\parindent=0mm +\font\eins=cmb10 scaled \magstep 3 +\font\zwei=cmr12 +\font\mini=cmr7 +\hbox{} +\vfill + +\centerline{\eins Fast multiprecision evaluation} +\bigskip\bigskip +\centerline{\eins of series of rational numbers} +\bigskip\bigskip\bigskip\bigskip\bigskip\bigskip +\centerline{\zwei Bruno Haible} +\bigskip\bigskip +\centerline{\zwei Thomas Papanikolaou} +\bigskip\bigskip\bigskip\bigskip\bigskip\bigskip +\centerline{\mini 25 July 1997} + +\vfill +\hbox{} +\eject + +\end diff --git a/doc/ratseries/slides/slide1.dvi b/doc/ratseries/slides/slide1.dvi new file mode 100644 index 0000000000000000000000000000000000000000..48104538cf7ccba28f90d09193782164f22cdd49 GIT binary patch literal 1220 zcmbW1Pe>GT6vuy~?wV;<+QCf0mB`Xf<~M6QyZt)|=0T-}5;~RRFm8jhv)k?rx~GB= ziuw&ZE*Y3P1`*+cu@ESMAa$ryL5I*oBpIE$*al@6d%sy-hFS=GFf+`|d!P4xzu$c4 zX9;t2e5v6Sf^aV#YPu+0YKrPwOxK!lFvz#Fd^`4^dA*TD>4@Hg`mKz~r zmb|XZRj|_iI4TDMJs>k8^Uu}X-t(T%W6sBkB>%#L4Febl`*&IEUoYoserNTXLK6@m zjbe7O22zN%ar!VZJzt(>ut6_Y*+}(mgoY&KLX1^$^aBBuVVJF z7bLKnQKDg}f7_8&37vAW780yu*WMA5!9hP~5VL-Eu18HRtm)cSxYNaH%<%rAtm#4sm^MiojitI9 zqpGCdTUgU%L4l3!m({c;h2w%^7>_8G=kwIgxI`6ca2FFFaxBlXJBJ3KmJYcM_0rCL zVxO!if|~E(V{yI%jNB&S~>X7&VlsT{+oO4n0)Cqef3tGMDL0N52Ct`}MX|fuo8(xRd-CtmcR_A|!39Wdk icfl7-QPUQ;L{T#p|AdR$vAENVdVB++GFQnbJN^LXY^i+! literal 0 HcmV?d00001 diff --git a/doc/ratseries/slides/slide1.log b/doc/ratseries/slides/slide1.log new file mode 100644 index 0000000..05e37dd --- /dev/null +++ b/doc/ratseries/slides/slide1.log @@ -0,0 +1,6 @@ +This is TeX, Version 3.14159 (C version 6.1) (format=tex 96.5.7) 16 JUL 1997 23:21 +**slide1.tex +(slide1.tex +Hyphenation patterns for english, german, francais, loaded. +[1] ) +Output written on slide1.dvi (1 page, 1220 bytes). diff --git a/doc/ratseries/slides/slide1.ps b/doc/ratseries/slides/slide1.ps new file mode 100644 index 0000000..7a26289 --- /dev/null +++ b/doc/ratseries/slides/slide1.ps @@ -0,0 +1,425 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: slide1.dvi +%%Pages: 1 +%%PageOrder: Ascend +%%BoundingBox: 0 0 596 842 +%%DocumentPaperSizes: a4 +%%EndComments +%DVIPSCommandLine: dvips -Pljfour -o slide1.ps slide1.dvi +%DVIPSParameters: dpi=600, compressed, comments removed +%DVIPSSource: TeX output 1997.07.16:2321 +%%BeginProcSet: texc.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]/id ch-image N /rw ch-width 7 add 8 idiv string N /rc 0 N /gp 0 N +/cp 0 N{rc 0 ne{rc 1 sub /rc X rw}{G}ifelse}imagemask restore}B /G{{id +gp get /gp gp 1 add N dup 18 mod S 18 idiv pl S get exec}loop}B /adv{cp +add /cp X}B /chg{rw cp id gp 4 index getinterval putinterval dup gp add +/gp X adv}B /nd{/cp 0 N rw exit}B /lsh{rw cp 2 copy get dup 0 eq{pop 1}{ +dup 255 eq{pop 254}{dup dup add 255 and S 1 and or}ifelse}ifelse put 1 +adv}B /rsh{rw cp 2 copy get dup 0 eq{pop 128}{dup 255 eq{pop 127}{dup 2 +idiv S 128 and or}ifelse}ifelse put 1 adv}B /clr{rw cp 2 index string +putinterval adv}B /set{rw cp fillstr 0 4 index getinterval putinterval +adv}B /fillstr 18 string 0 1 17{2 copy 255 put pop}for N /pl[{adv 1 chg} +{adv 1 chg nd}{1 add chg}{1 add chg nd}{adv lsh}{adv lsh nd}{adv rsh}{ +adv rsh nd}{1 add adv}{/rc X nd}{1 add set}{1 add clr}{adv 2 chg}{adv 2 +chg nd}{pop nd}]dup{bind pop}forall N /D{/cc X dup type /stringtype ne{] +}if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +TeXDict begin 39158280 55380996 1728 600 600 (slide1.dvi) +@start /Fa 2 2 df<007FBC12FCBD12FEA46C1BFC570674A670>0 +DI E /Fb 2 20 df[<1AFC19011903F107F0190FF11FE0F13FC0F17F80F1FF004E5A4E5A +4E5A4E5A4E5A183F614E5A4EC7FC4D5A17034D5A604D5A171F4D5A604D5A17FF4C90C8FC +5F16034C5AA24C5A4C5AA24C5A167F5F4C5AA24B90C9FC5D5E15075E150F5E151F4B5AA2 +4B5AA24B5AA24A5BA34A90CAFCA24A5AA24A5AA2141F5DA2143F5D147F5DA214FF5DA25B +5D5BA292CBFC5BA3495AA35C131FA3495AA4495AA4495AA45A5CA35AA25CA35AA391CCFC +A35AA35BA3121FA55BA2123FA85B127FAD5B12FFB3B3A2127F7FAD123F7FA8121FA27FA5 +120FA37FA37EA380A37EA380A27EA3807EA46D7EA46D7EA46D7EA3130F80A36D7EA37F81 +A27F817FA281147FA281143F81141FA281140FA26E7EA26E7EA26E7FA36E7FA26F7EA26F +7EA26F7E150F82150782150382816F7FA2707E83163F707EA2707E707EA2707E16018370 +7F177F717E84717E170F717E84717E1701717E727E727E85181F727E727E727E727E727E +F17F80F13FC0F11FE0F10FF01907F103FC19011900>70 344 98 +133 106 18 D[<127C12FE127F6C7E7F6C7E6C7E6C7E6C7E6C7E6C7E6D7E6D7E6D7E8013 +0F6D7E6D7E6D7E806D7F147F6E7E816E7E140F6E7E816E7E1401816E7FA26F7E6F7EA26F +7E82150F6F7EA26F7E8281838183167F83707EA2707EA2707EA2707EA3707EA2707FA270 +7FA284177FA284173F84171FA284170FA284170784A28385A3717FA38385A3727EA4727E +A4727EA485180FA385A284A31A80A384A31AC0A384A31AE0A584A21AF0A8197F1AF8AD19 +3F1AFCB3B3A21AF8197FAD1AF019FFA81AE0A260A51AC0A360A31A80A360A31A00A360A2 +61A3181F61A44E5AA44E5AA44E5AA3615FA34D5BA396C7FC5FA260170F60A2171F60A217 +3F60177F60A217FF60A24C5BA24C90C8FCA24C5AA34C5AA24C5AA24C5AA24C5A5F16FF5F +5D94C9FC5D5E4B5AA24B5A151F5E4B5AA24B5A4B5AA24A90CAFC5D14034A5A5D4A5A141F +4A5A5D4A5A14FF4990CBFC5C495A495A495A131F5C495A495A49CCFC485A485A485A485A +485A485A5B48CDFC12FE127C>70 344 123 133 106 I E /Fc 2 +50 df33 D49 +D E /Fd 1 111 df<017EEC1FF048B46CEBFFFE48D9E0036D7E3C0787F00FE03FC03C0F +03F81F001FE0DAFC3C130F001E4A800101491307003CEBFDE049B44880007C5C127892C7 +FC4948140F00F05F5C00005B010F151F605CA2011F153F605C177F013F5EA24A14FF95C7 +FC017F4A147C4D13785C160301FF4B13F819F091C7140105F813E048EF03C0180749EE0F +80F01F00933801FC3E49913800FFFCEF3FF0D800F0ED0FC03E2D7BAB47>110 +D E /Fe 42 122 df43 DIII48 D<153C157C15FC14011407141F147FEB03FF137FB6FCA2149FEB +FC1F1380C7FCB3B3B3B34A7EA249B512C0007FB8FCA5305F74DE48>I<913807FF80027F +13F849B6FC010715C04915F090263FF80713FC90267FC0007F01FEC7EA3FFF4848020F7F +D803F06E7F48486E7F496E7F000F8348488090C96C7E5A003E707E127E007C83D87FE081 +7F487E6D17807F83A56C5AA26C485D6C5AD803801700CAFCA25F60A24D5AA26017FF604C +5BA24C5B4C5B95C7FC4C5A4C5A5F4C5A4C5A5F4C5A4B90C8FC4B5A4B5A4B5A5E4B5A4B5A +4BC9FC15FE4A5A4A5A4A5A4A5A4A5A4BEC07804AC8FC147E4AED0F00495A495AEB07C049 +5A49C95A013E161E133C49163E5B484816FE48B8FC5A485F5A5A5AB9FCA260A3395F79DE +48>I<913801FFE0021F13FE91B612C0010315F04901007FD91FF0EB1FFED93F806D7E01 +7EC700037F498248486E7F496E7F484882EA07FC01FF6F7E805A6E81A2173F805CA26C16 +7F5C6C90C8FC6C485EEA007890C9FC6017FFA2604C5BA2604C5B95C7FC4C5A4C5A4C5A4C +5AEE7FC04B485ADB7FFEC8FC91383FFFF016FEEEFFC091C713F0EE3FFCEE0FFE706C7E70 +7F707F707F717E84717EA284831980A219C083A219E0A2EA03C0EA0FF0487E487E487EB5 +FCA319C0A25FA24917806C5A494B13005B003EC95B003F167F6C6C5E6D4B5A6C6C4A5BD8 +07F85E6C6C4A5B6CB4020F5B6C01E0013F90C7FCD93FFEEBFFFE6DB612F801075D010115 +80D9003F49C8FC020313E03B627ADE48>II<01C016E0D801F0150301FE151FD9FFC0ECFF +C002FE011F5B91B7C7FC5FA25F17F05F5F94C8FC5E16F801F714C09026F07FFCC9FC91CB +FCB2EDFFE0020713FE023F6D7E9139FF807FE0903AF1FC001FF0D9F3E0EB07F8D9F7806D +7E01FFC76CB4FC5B496E7F496F7E4982496F7E120090C97F171F84A284A2717EA51980A4 +EA0780EA1FE0487E487E487EA41900A2495DA2495EEA7FC00078C9FC007C4C5AA26C5F17 +7F6C5F4D5A6C7E6C6C4A5B6D4A5B6C6C4A90C7FCD801FC4A5A6CB4EC3FFCD97FC0EBFFF8 +90263FF80713E06DB65A010792C8FC010114FC6D6C13E0020F90C9FC396279DE48>IIIII<007FBD12FCBE12FEA4003F1CFCD1FCB3A4003FBD12FCBE12FEA46C1CFC +5F2278B470>61 D66 D69 +D75 DI +I80 +D<912603FFC014E0023F01FC130191B6EA8003010315E0010FEDF007499038007FFCD93F +F8903807FE0FD97FE0903801FF1FD9FF809038007F9F4890C8EA1FFF4848814848150349 +81000F82485A187F4848163FA2007F171F5B180FA200FF1707A418037FA36D1601A27F12 +7F7F6D93C7FC7F6C7F8014F06C13FE6CEBFFE015FE6CECFFE06C15FEEEFFE06C16FC6C16 +FF6D826D16E0010F826D820101826D6C81020F8102001680030F15C01500040F14E01600 +053F13F0170F050313F8837113FC187FA2183F19FE0070171F12F0180FA31807A27EA46C +18FCA36C170F19F87EA26DEE1FF07F6DEE3FE0A201F8EE7FC06DEEFF806D17006D6C5CD9 +3FE0EC07FED91FF84A5A26FE07FFEC3FF8486C9039F801FFE0010090B65A48013F92C7FC +020F5C48010114F048D9000F13803F6878E450>83 D97 D<14F8EA07FFB5FCA51201 +EA007F133F131FB3A8EE3FF84BB57E030714E092391FE01FF892397F0003FE03FC6D7EDA +F9F09038007FC0DAFBE06E7EDAFFC06E7E4B6E7E92C86C7E4A8218034A824A6F1380A272 +13C01AE0A2197F1AF0A21AF8A2193FA31AFCAC1AF8A2197FA21AF0A3F1FFE0A21AC0601A +80804E13006E5E4E5A6E4B5ADAEF804A5ADAE7C05DDAC3E0EC7FC0DAC1F04A5ADA80F849 +90C7FCDA007EEB07FC92393FC03FF0011E010FB512C090C7000391C8FC9238007FF04666 +7CE350>II101 +D103 +D<14F8EA07FFB5FCA51201EA007F133F131FB3A8EE0FFE93387FFFC04BB512F0923907F8 +1FFC92390FC007FE92391F0001FF153C4B6D7F4B81DAF9E0147FDAFBC0815D14FF92C812 +3F855CA25CA45CB3B2496C4B7E90B5913801FFFEB748B612FEA547647BE350>I<131FEB +7FC0497E487FA2487FA56C5BA26C5B6D5A011FC7FC90C8FCB214F8EA03FF127FA51201EA +007F133F131FB3B3AB497EEBFFFEB612FEA51F617CE027>I<14F8EA07FFB5FCA51201EA +007F133F131FB3AA4CB612C0A5706CEBF800051F13804EC7FC18F818E0604D5A057EC8FC +5F4C5A4C5A4C5A4C5A4C5A043EC9FC16FC4B5A4B5A4B7E150F4B7E4B7E157F02F9B5FCDA +FBF37FDAFFE17F15C103807F4B6C7E5C02F86D7E4A6D7EA2707E707E8284707F707FA271 +7E717EA2717E717EA2717E85717F4D7F496C82D9FFFE4A13FEB600FE017FEBFFF8A54564 +7CE34C>107 D<14F8EA07FFB5FCA51201EA007F133F131FB3B3B3B3AB497E90B5FCB7FC +A520647CE327>IIII<02F8EB3FF8D807FF49B57EB5010714E092391FE01FF892397F00 +07FE03FCEB01FFDAF9F06D13C0C6D9FBE06E7E90263FFFC06E7E6D496E7E92C86C7E4A82 +18074A824A6F1380A27213C01AE084A21AF0197F1AF8A4193F1AFCACF17FF8A41AF019FF +A21AE0601AC0A24E1380804E13006E4B5A616E4B5A6F4A5A6F5DDAFBE0ECFFC0DAF9F049 +5BDAF8F84990C7FC037EEB0FFC92393FC07FF0030FB512C0030391C8FC9238007FF093CA +FCB3497E90B5FCB7FCA5465C7CBF50>I114 DI<143C +A7147CA514FCA31301A21303A21307A2130F131F133F137F13FF000390B612C0120FB8FC +A326000FFCC8FCB3AD17F0AE010714016E14E0A3010314036E14C07F6D90388007809138 +7FC00F91393FE01F0091381FF87E6EB45A02035B9138003FE02C5A7DD738>I<02F8ED01 +F0D807FFED0FFFB54AB5FCA50001ED0003D8007F1500013F167F011F163FB3B2187FA418 +FFA2130F5FA26E5C0107923807BFF8F03FFC6D6C020F13FF0101031E14FE6D6C147CDA7F +C013F891393FF807F0020FB512C00203028014C09128003FFC003EC7FC47427BBF50>I< +B6D8F01FB500FC017FB51280A5000349C7003F01800107EBFC00C601F8DA0FFEC7000113 +E06D484B6E5B013F0307705A9AC7FC6E6E6C153E131F1C3C6E6F157C010F1A785F6E7014 +F80107625F6E6F6C13016D62171F6F90261E3FE013036D62173E6D6D90263C1FF0495AA2 +177C6E6C9026780FF849C8FCA2EFF0076E6C6F131EA2933801E003DA1FF86F5BA2932603 +C001147CDA0FFC6F1378A24C486CEB80F8DA07FE5F160F03FF90C7EA7FC16E605E049EEC +3FE36E6016BE04FCEC1FF76E60A24CEC0FFF037F94C9FCA24C80033F5EA26F486E5AA36F +486E5AA24C140003075E61407DBD68>119 D +II E /Ff 2 111 df13 +D110 D E /Fg 12 118 df[<49B4FC011F13E0017F13F8 +90B512FE00038048818248814881A248815A8282B7FCA282A31780A417C0A27EA37E7EA2 +7E7EA27EC6ECFE7F6D13FC011F13F00101EB00FF90C8FC1780A45DA21700A25DA25E1507 +A25E150FA24B5AA24B5AA2157F5E15FF5E5C4A5B93C7FC5C4A5A141F5D4A5A4A5A14FF49 +5B495B495B5B4990C8FC495A495A495A5C6D5A5C6D5A011EC9FC>42 +87 113 299 69 39 D[147 +169 120 296 163 69 D<0407B57E0303B7FC033F16E04AB812FE020F717E023F18F091 +BA12FC49850107737E499126FE000F81490280010115F0706D6C80496E6E8049050F8070 +6E8090B66C6E818589486F6E81A274808986A28986896C5DA36D4A6F806D5CA26D5C6D5C +6D91C9FC010113FC9038003FE091CBFCA897B7FC060FB8FC0507B9FC94BAFC160F93BBFC +1507153F92B812CF0207EEE00F021FEDFE00027F15E091B71280010303FCC7FC4915F049 +15C0495D017F4AC8FC5E90B65A485D485D485DA2485D4892C9FCA25A5D5A5DA3B6FC5DA4 +62A462816C61A297B7FC6C80616C6E4B5A0707826C6F4A48816C6F4A4815F0073F16FE6C +6F9126FFF07FECFFFE6C03F84901E0826C6F010F01C017806D9126FF807F497E011F92B6 +12006D4D7F01034D7F01004D1303023F04E07F020704806D7E02004BC8000F1500030F02 +F003015CDB007F90CEFC717179EF79>97 D<943807FFFE94B612F8040FEDFF80047F16F0 +0303B812FC030F17FF033F18C04B844ABA12F80207854ADBC007804A4AC7FC4A02F84980 +4A4A178091B600C05B494B4915C04992C7FC495C494D15E0495C5E5B5B5E90B6FC485DA2 +487215C05E5A73158048721500A24C6E5C48735B745B080F13E048070190C7FC97C9FCA2 +93CDFC5AA6B7FCB37EA5827EA47EA2827EF41FF8A26C6FEF3FFCA26C1B7F826C1CF81CFF +6C815113F06D806D4F13E0826D4F13C06D6E4C13806D6F5D6D6F4B1300714B5A6D6FEC01 +FF6D03FC4A5B6E02FF020F5B021F03C0013F5B6EDBF803B55A6E92B75A0201616E4EC7FC +033F5F030F17F0030317C0DB007F93C8FC040F15F8040015C0050701F8C9FC5E7178EF6E +>99 D<943803FFFC94B612F0040715FE043FEDFFC04BB812F0030717FC031F17FF037F18 +C04ABA7E4ADBC03F14F8020F9126FE0007804A02F80101804A4A6D6C7F4A02C06E8091B6 +486E804992C86C80494A81497280494A84494A814972805E49737F5E90B68548864C1980 +5A87481DC0A25E487414E0A25AA21EF0A24892CA7EA35AA21EF8A4B7FCA393BBFCA61EF0 +1EE093CEFCA77EA67EA2827EA47EF51FE06C6FF03FF0F57FF8A27E7018FF7E5213F06C81 +6D5013E0826D5013C06D6E5F704D13806D626D6E4D13006D6F93B5FC6D6F4B5B6D6F4B5B +6E02F8030F5B6E6E033F5B6E02FF92B55A6E03C001075C020303FC017F5C6E92B748C7FC +6E6C60031F606F18E0030118806F6C4CC8FC040F16F0040116C0DC001F02FCC9FCDD007F +1380657179EF74>101 D[61 172 122 299 68 108 D<922601FFC0ED7FFF013FB60307B5 +12F8B8033FECFF804FB712E0070716F8071F16FE4F8296B97E4E844E0200814E01F06D80 +4E01C07F4E90C76C80DE3FFC83D8001F4C48800101DCFFE0836D5F05C1496E806E02C390 +C8FC60DDC7FC85EFCFF86005DF826005FF866060A395C9FCA25FA35FA55FB3B3B3A5BAD8 +FC03BA12E0AB49C8000104F0C8120F836F7AEE8A>110 D<943803FFFE057FEBFFF00407 +B7FC043F16E04BB812FC030717FF031F18C0037F18F092BA7E0203DBC01F14FE4A9126FC +0001804A02F06D6C80023F4A6E14E04A0280020F8091B6C86C80494A6F80494A6F80494A +6F80A2494A7080494A70804988A2494A708090B686A2484B7080A24889A24889A2481E80 +A34892CA6C15C0A4481EE0A4481EF0A6B71BF8B16C1EF0A66C1EE0A46C6F4C15C0A46C1E +80A26C1E00A26C65705E6C65A26C65705E6D64705E6D646D6E93B65A6D646D6E4B92C7FC +705D6D6E4B5C6D6F4A5C6D03E0023F5C023F6E4A14E06E02FE0103B65A6E9126FFC01F5D +6E92B8C8FC020119FC6E6C18F06F60030F1880030105FCC9FC6F6C16F0040F1680040003 +F8CAFC050349CBFC6D7179EF7C>I<4BB46C903807FF80013FB6023F13FCB849B67E4E15 +E0060F15F84E15FE4E814E168095B812C00581D9FC0F14E0DFF01F14F0058313C00587D9 +003F14F84E4914FCD8000FED8FFC01015E6DDB9FF090B612FEA26EECBFE0A26017FF60A2 +95C7FC7414FCA34D6E14F87414F0A24D6E14E07414C07414800800EBFE00F31FF04D92C8 +FCA95FB3B3B2BB7EAB49C97E5F6F7CEE6A>114 D<4BB5EC0FC0037F02F8133F0207B7EB +FFE0023F16C391BAFC13035B131F49EC00034901F0EB003F90B50080140F4849C8120348 +49814A8148498248498285484982A248845C5A85A4B56C82A380A2806E705B14FE6E94C8 +FC15C015F015FE6CECFFE016FF17F8EFFFC06C17F818FF6C18E019F86C18FE856C19C06C +856C851AFC6C856D847F010F856D856D8513006E84021F841403DA007F83150F03008316 +07EE003F050181EF003F18077215801800D83FE083007F181F486C83A2856D83A2857FA2 +85A27F1C007FA280636E5EA26E6061806E606E4C5B6E5E6E4C5B6F4B5B03E05D03F84AB5 +5A03FE020F91C7FCDBFFE090B55A93B75A62023F17E0496C5FD9F80794C8FCD9F00116F8 +9026C0003F15E06C4801074AC9FC007EC86C13C0517178EF62>I[<923801FFE0AA5DA75D +A45DA45DA35DA25DA392B5FCA25C5CA25C5C5CA25C5C91B6FC13035B011F92B71280137F +0007BBFCBCFCA9D8000103E0C9FCB3B3B2F27FF8B3A31AFF6D6F15F0A36E5E1BE0836E4C +13C0836E5E7115806E6E4913006EED803F6E9238E07FFE6E92B55A806F5E6F5E6F5E0307 +5E030193C7FCDB003F5C040714F0DC001F1380>77 158 123 284 +97 II E end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: a4 +%%BeginPaperSize: a4 +a4 +%%EndPaperSize + +%%EndSetup +%%Page: 1 1 +1 0 bop 1367 1305 a Fg(Euler's)82 b(constan)-7 b(t)1091 +1871 y Ff(\015)49 b Fe(=)89 b(lim)1365 1958 y Fd(n)p +Fc(!1)1689 1669 y Fb(\022)1811 1774 y Fe(1)p 1811 1838 +72 6 v 1811 1970 a(1)1932 1871 y(+)2093 1774 y(1)p 2093 +1838 V 2093 1970 a(2)2214 1871 y(+)31 b Fa(\001)24 b(\001)g(\001)31 +b Fe(+)2724 1774 y(1)p 2717 1838 87 6 v 2717 1970 a Ff(n)2852 +1871 y Fa(\000)h Fe(log)26 b Ff(n)3291 1669 y Fb(\023)0 +2466 y Fe(1962)95 b(Kn)l(uth)897 b(1271)533 b(Euler-MacLaurin)0 +2638 y(1963)95 b(Sw)l(eeney)773 b(3683)95 b(20)71 b(h)143 +b(exp)t(onen)l(tial)47 b(in)l(tegral)0 2810 y(1977)95 +b(Bren)l(t)875 b(20700)95 b(20)71 b(h)143 b(exp)t(onen)l(tial)47 +b(in)l(tegral)0 2983 y(1980)95 b(Bren)l(t,)46 b(McMillan)192 +b(30100)533 b(Bessel)47 b(in)l(tegral)0 3155 y(1997)95 +b(P)l(apanik)l(olaou)314 b(500000)94 b(160)47 b(h)95 +b(Bessel)47 b(in)l(tegral)0 3327 y(1997)95 b(P)l(apanik)l(olaou)242 +b(1000000)94 b(42)71 b(h)143 b(Bessel)47 b(in)l(tegral,)h(bin.)g +(splitting)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/ratseries/slides/slide1.tex b/doc/ratseries/slides/slide1.tex new file mode 100644 index 0000000..ee48fa8 --- /dev/null +++ b/doc/ratseries/slides/slide1.tex @@ -0,0 +1,30 @@ +\magnification=\magstep3 +\hsize=19truecm +\vsize=19truecm +\nopagenumbers +\parindent=0mm +\font\eins=cmb10 scaled \magstep 3 +\font\zwei=cmr12 +\font\mini=cmr7 +\def\frac#1#2{{{#1} \over {#2}}} +\hbox{} +\vfill + +\centerline{\eins Euler's constant} +\bigskip\bigskip +\centerline{$\displaystyle \gamma = \lim\limits_{n \to \infty} \left( \frac{1}{1} + \frac{1}{2} + \cdots + \frac{1}{n} - \log n \right)$} +\bigskip\bigskip +\halign{# & #\hfil & \hfil# & # & #\hfil\cr +1962 & Knuth & 1271 & & Euler-MacLaurin \cr +1963 & Sweeney & 3683 & 20 h & exponential integral \cr +1977 & Brent & 20700 & 20 h & exponential integral \cr +1980 & Brent, McMillan & 30100 & & Bessel integral \cr +1997 & Papanikolaou & 500000 & 160 h & Bessel integral \cr +1997 & Papanikolaou & 1000000 & 42 h & Bessel integral, bin.\ splitting \cr +} + +\vfill +\hbox{} +\eject + +\end diff --git a/doc/ratseries/slides/slide2.dvi b/doc/ratseries/slides/slide2.dvi new file mode 100644 index 0000000000000000000000000000000000000000..9c9fdc7ca36066a06e164fd912f5c4be182aeee3 GIT binary patch literal 1100 zcmah|T}TvB6u#rGYo?f*l%RntQM&{}*gMlPO z-OJtv4I-R<5zHZBKr#Zsis&VJ=povNhzufnvl0JLwlk})8w_-Yfjjqp=ljk*^PQCp zX86&3>1hOEnJ+18=R3=S5wR~KmT`4;&MMYf#ht3J=1$Z;00g7M{uc=dEdN1>#F*N+ z1IH4T%o?V`_2XLgr=0O4sK7Oi_5w?$SMYG`*Cw|wKr`P&TlsLrFA~{4OfmIFo@$ny zn5Qv`)X^5NAow^|ZKI~E6B@d>*fp3s1EzkCRT?mswV_Q+Ep0v8z834kJ(LBR`U{Bg zpz{?+<63JldcCOU|}^#?hg3 zs%INP(lU>Ixuy0gHr9^En5juE*IMp)l3rtYkYi^V2_8c85-U1(O9c{lRcgjRZmFES zqJ~DV#Z!dosUc}sA1-aJ9Ki!V@#dJRqhqIdhqO~9thS|K6^iPVx~>!!+ zHdC{|PwDpc`ou8sN}^BTiCh%=fGM{*tG2)oWES7aOFz5j@(HF{zn`g1W6Z%4P->PG zJDg5U+OR*^3;h{wPwoNCdbC(xUtO54hE~(_XV;VY1%%MciDhNG+<%yp#LeJ>*Kd_{ zI;u>xzBLimr%h?Zkzow5xtxg=_$)lzLpbN)_}OuK#cqY*~>$eaxk} lL!TJ52Qh}DV(eB!ryHBb(96biX5??fsar$HbSL8*#9z>*j(`9F literal 0 HcmV?d00001 diff --git a/doc/ratseries/slides/slide2.log b/doc/ratseries/slides/slide2.log new file mode 100644 index 0000000..17d886a --- /dev/null +++ b/doc/ratseries/slides/slide2.log @@ -0,0 +1,6 @@ +This is TeX, Version 3.14159 (C version 6.1) (format=tex 96.5.7) 16 JUL 1997 21:48 +**slide2.tex +(slide2.tex +Hyphenation patterns for english, german, francais, loaded. +[1] ) +Output written on slide2.dvi (1 page, 1100 bytes). diff --git a/doc/ratseries/slides/slide2.ps b/doc/ratseries/slides/slide2.ps new file mode 100644 index 0000000..5e498e4 --- /dev/null +++ b/doc/ratseries/slides/slide2.ps @@ -0,0 +1,408 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: slide2.dvi +%%Pages: 1 +%%PageOrder: Ascend +%%BoundingBox: 0 0 596 842 +%%DocumentPaperSizes: a4 +%%EndComments +%DVIPSCommandLine: dvips -Pljfour -o slide2.ps slide2.dvi +%DVIPSParameters: dpi=600, compressed, comments removed +%DVIPSSource: TeX output 1997.07.16:2148 +%%BeginProcSet: texc.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]/id ch-image N /rw ch-width 7 add 8 idiv string N /rc 0 N /gp 0 N +/cp 0 N{rc 0 ne{rc 1 sub /rc X rw}{G}ifelse}imagemask restore}B /G{{id +gp get /gp gp 1 add N dup 18 mod S 18 idiv pl S get exec}loop}B /adv{cp +add /cp X}B /chg{rw cp id gp 4 index getinterval putinterval dup gp add +/gp X adv}B /nd{/cp 0 N rw exit}B /lsh{rw cp 2 copy get dup 0 eq{pop 1}{ +dup 255 eq{pop 254}{dup dup add 255 and S 1 and or}ifelse}ifelse put 1 +adv}B /rsh{rw cp 2 copy get dup 0 eq{pop 128}{dup 255 eq{pop 127}{dup 2 +idiv S 128 and or}ifelse}ifelse put 1 adv}B /clr{rw cp 2 index string +putinterval adv}B /set{rw cp fillstr 0 4 index getinterval putinterval +adv}B /fillstr 18 string 0 1 17{2 copy 255 put pop}for N /pl[{adv 1 chg} +{adv 1 chg nd}{1 add chg}{1 add chg nd}{adv lsh}{adv lsh nd}{adv rsh}{ +adv rsh nd}{1 add adv}{/rc X nd}{1 add set}{1 add clr}{adv 2 chg}{adv 2 +chg nd}{pop nd}]dup{bind pop}forall N /D{/cc X dup type /stringtype ne{] +}if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +TeXDict begin 39158280 55380996 1728 600 600 (slide2.dvi) +@start /Fa 1 2 df1 D E /Fb 4 62 df48 +D50 +DI<007FBBFCBC1280A3 +6C1A00CFFCB3007FBBFCBC1280A36C1A00491D79A758>61 D E /Fc +2 111 df +99 D<017EEC1FF048B46CEBFFFE48D9E0036D7E3C0787F00FE03FC03C0F03F81F001FE0 +DAFC3C130F001E4A800101491307003CEBFDE049B44880007C5C127892C7FC4948140F00 +F05F5C00005B010F151F605CA2011F153F605C177F013F5EA24A14FF95C7FC017F4A147C +4D13785C160301FF4B13F819F091C7140105F813E048EF03C0180749EE0F80F01F009338 +01FC3E49913800FFFCEF3FF0D800F0ED0FC03E2D7BAB47>110 D +E /Fd 3 89 df[<18FC17011703EF07F8EF0FF0EF1FE0EF3FC0EF7F80EFFF004C5A4C5A +4C5AA24C5A4C5A4C5A4C5A16FF94C7FC4B5A15035E4B5A150F4B5A5E153F4B5AA24B5A93 +C8FC5C4A5AA24A5AA24A5AA24A5AA24A5AA2147F5D14FF5D5BA24990C9FCA25C1307A249 +5AA3495AA3495AA3495AA313FF5CA35A5CA25AA291CAFCA35AA25BA2120FA35BA2121FA5 +5BA2123FA65B127FAB5B12FFB3AF127F7FAB123F7FA6121FA27FA5120FA27FA31207A27F +A27EA380A27EA2807EA380137FA36D7EA36D7EA36D7EA36D7EA2130380A26D7FA27F8114 +7F81143FA26E7EA26E7EA26E7EA26E7EA26E7E80826F7EA26F7E151F826F7E15076F7E82 +15016F7E83167F707E707E707E707EA2707E707E707EEF7F80EF3FC0EF1FE0EF0FF0EF07 +F8EF03FC17011700>54 257 102 133 86 16 D[<127C12FE127F7F6C7E6C7E6C7E6C7E +6C7E6C7E6C7E6D7EA26D7E6D7E6D7E6D7E8013036D7E807F6E7E816E7E141F816E7EA26E +7E1403816E7EA26E7FA26F7EA26F7EA26F7EA282150F82150782A26F7EA28183A26F7FA3 +707EA3707EA3707EA383160FA3831607A283A282A31880A282A218C0A382A218E0A5177F +A218F0A6173F18F8AB171F18FCB3AF18F8173FAB18F0177FA618E0A217FFA518C0A25EA3 +1880A25EA21800A35EA25FA2160F5FA3161F5FA34C5AA34C5AA34C5AA34B5BA294C7FC5D +A24B5AA25E150F5E151F5EA24B5AA24B5AA24B5AA24A90C8FCA24A5A5D14074A5AA24A5A +5D143F4A5A5D4AC9FC5B5C495A13075C495A495A495A495AA249CAFC485A485A485A485A +485A485A485A90CBFC12FE127C>54 257 123 133 86 I<007FC5B512F8C5B67EA3A181 +A2A1816C02C0D0FC6C6EE3000F836C6EF6001F23006C6E0E0F816C6E2000A1011F806C6E +21076C6E0F00806C6F213FA1140F6D6E0F037F6D6E8D6D6E7B6C7EA1153F6D6EFA0FFE6D +6E2207A115036D6E7C7E6D6E7C7E6D6FFA3F80A26E6EFA1FC06E6E220F6E6E2207A1EE03 +E06E806E6EFA01F0A116006E6E23F86E6E23786E81A1173C6F6E22006F806F80A26F806F +80A26F806F806F81A2708070807080A270807080A2708070807081A2718071807180A271 +807180A2718071807181A2728072807280A272807280A2728072807281A2738073807380 +A273807380858873807381A2748074807480A27480868665745C745CA2755B7590D2FC75 +5A6464515A1B7F515A64505B5090D3FC505A1A0F505A505A63505A505A4F5B614F90D4FC +624F5A4F5A4F5A197F4F5A4E5B624E90D5FC4E5A4E5A181F4E5A614E5A4E5A4D5B5F4D90 +D6FC4D5A604D5A4D5A4D5A17FF4C5B604C90D7FC4C48233C4C482378161F4C4823F84C48 +23F04D22014C5A4B49FA03E04B90D612074BA113C04B48230F4C231F4B48FB3F804B4823 +7F4B4823FF03FF5913004A496A4A496A93D6EA1FFE4A48233F4A48FBFFFC4A486A023F23 +074A48101F5B4B227F4A4857B5FC49490F0F5C4990D5127F491003B65A4948213F49480E +0FB7FC4A0D07B85A49480C7FB9FC49C5B5FC90C5B65A5A5AA193C7FC5A48A15C5A5A48A1 +5CC5B6FCA26CA15CBEC9787FCF>88 D E /Fe 1 50 df49 D E /Ff 24 120 df40 D<126012F012787E123E7E6C7E6C7E6C7E6C7E7F +6C7E137E133E133F6D7E80130F6D7EA26D7E80130180130080A2147FA26E7EA281141FA2 +81140FA281A2140781A36E7EA4811401A581A280A61680B3A41600A65CA25DA514035DA4 +4A5AA35D140FA25DA2141F5DA2143F5DA24AC7FCA214FEA25C13015C13035C495AA2495A +131F5C49C8FC133E137E5B485A5B485A485A485A48C9FC123E123C5A5A1260219078EB38 +>I44 D46 D48 +D<007FBD12FCBE12FEA4003F1CFCD1FCB3A4003FBD12FCBE12FEA46C1CFC5F2278B470> +61 D97 D<14F8EA07FFB5FCA51201EA007F133F131FB3A8EE3FF84BB57E030714E0 +92391FE01FF892397F0003FE03FC6D7EDAF9F09038007FC0DAFBE06E7EDAFFC06E7E4B6E +7E92C86C7E4A8218034A824A6F1380A27213C01AE0A2197F1AF0A21AF8A2193FA31AFCAC +1AF8A2197FA21AF0A3F1FFE0A21AC0601A80804E13006E5E4E5A6E4B5ADAEF804A5ADAE7 +C05DDAC3E0EC7FC0DAC1F04A5ADA80F84990C7FCDA007EEB07FC92393FC03FF0011E010F +B512C090C7000391C8FC9238007FF046667CE350>IIII103 D<14F8EA07FFB5FCA51201EA007F133F131F +B3A8EE0FFE93387FFFC04BB512F0923907F81FFC92390FC007FE92391F0001FF153C4B6D +7F4B81DAF9E0147FDAFBC0815D14FF92C8123F855CA25CA45CB3B2496C4B7E90B5913801 +FFFEB748B612FEA547647BE350>I<131FEB7FC0497E487FA2487FA56C5BA26C5B6D5A01 +1FC7FC90C8FCB214F8EA03FF127FA51201EA007F133F131FB3B3AB497EEBFFFEB612FEA5 +1F617CE027>I<14F8EA07FFB5FCA51201EA007F133F131FB3B3B3B3AB497E90B5FCB7FC +A520647CE327>108 DIII<02F8EB3FF8D807FF49B57EB5010714E092391FE01FF89239 +7F0007FE03FCEB01FFDAF9F06D13C0C6D9FBE06E7E90263FFFC06E7E6D496E7E92C86C7E +4A8218074A824A6F1380A27213C01AE084A21AF0197F1AF8A4193F1AFCACF17FF8A41AF0 +19FFA21AE0601AC0A24E1380804E13006E4B5A616E4B5A6F4A5A6F5DDAFBE0ECFFC0DAF9 +F0495BDAF8F84990C7FC037EEB0FFC92393FC07FF0030FB512C0030391C8FC9238007FF0 +93CAFCB3497E90B5FCB7FCA5465C7CBF50>I114 DI< +143CA7147CA514FCA31301A21303A21307A2130F131F133F137F13FF000390B612C0120F +B8FCA326000FFCC8FCB3AD17F0AE010714016E14E0A3010314036E14C07F6D9038800780 +91387FC00F91393FE01F0091381FF87E6EB45A02035B9138003FE02C5A7DD738>I<02F8 +ED01F0D807FFED0FFFB54AB5FCA50001ED0003D8007F1500013F167F011F163FB3B2187F +A418FFA2130F5FA26E5C0107923807BFF8F03FFC6D6C020F13FF0101031E14FE6D6C147C +DA7FC013F891393FF807F0020FB512C00203028014C09128003FFC003EC7FC47427BBF50 +>I119 D E /Fg 9 114 +df<92B600C00707B512FE4A6F4F14FF685614FEA291C7003F51EBF000040F09F71380DD +BFF096B5C7FCF701EF053F963803CFFEA2041FF2079F69041EF20F1F1F1E93263E1FF819 +3F0D3C5B043C1A78A2047CF2F07FE401E05B1678716CEF03C004F81BFF54485B04F04F5A +A20301F21E010C3C5C4C6C7E1E780303505A6904C0F001E0F503C0030763716CDC078091 +C8FC1680F50F00030F071E5B68040060654B1B1F716D4B5C031E4E5AA2033E4E48133F68 +033C4E5A52C7FC037C6D6D177F0A1E5D037860A203F84E14FF525D5D726C495A02016351 +485D4B4D5AA202034EC75A091E5E4B6E7E6302074E5C9DC9FC4B5FA2020F4D485C50485D +92C8EA1FF8505A4A4DC8121F67021E171E62023E1B3F726C485E143C62027CDCFDE0157F +670278EEFFC002F85F7217FF010195C95B496C5E010763D91FFF5E48B500E0070F13F800 +7FDAFF804A027FB7FCB76C6D4891B87E4C99C8FC616190627AE18B>77 +D<92B600C04BB612FE4A6F4B15FFA27219FEA291C7001FDD0007140004076D040013F84C +F17FE072EF3F80057F96C7FC173F041F6D173EA293261E1FFF173CA2DC3E0F187C731678 +EE3C0785047C19F8716D5E16788304F86E1501664C6C7FA20301027F1603735E5E727E03 +031907726C5E5E84030770140F9BC8FC4C6D7FA2030F6E5E74141E93C7FC727F4B193E72 +163C031E82197F033E70147C1D78033C6F7EA2037C031F15F8745C1578737F03F8180173 +5D4B17C0A2020170EBE003654B811BF0020370140709F85B5DF27FFC0207190F083F91C9 +FC4B17FEA2020F716C5A1C1E92CA7E1C9E4A19BE7413FC141E86143E745B143CA2027C83 +640278187F14F8A20101735A497E0107191FEB1FFF48B500E0715A007FECFF80B77E4C16 +07641B0378627AE173>II<942601FFE01460051F01FC14F094B6EA800104039238E003E004 +0FEDF0074C9038007FF8DC7FF0903807FC0FDCFFC0903901FE1FC04B90C8EA7F3FDB07FE +ED3FFFDB0FF8814B486F13804B48814C814B5A4BC914004A835D4A4882020760A24A5AA2 +021F605DA3023F60A46381A2636F94C7FC81A28116C016F06E13FEEEFFE06E14FEEFFFE0 +6E15FCF0FFC06E16F06E826E16FE6F81031F826F821501DB003F81040381EE007F050780 +EF007F060F7F18031800197FA2193F737EA3190F01E060487EA25BA2120362A30007181F +62A262000F183F62197F62486C4DC8FC606D5F4E5A486C4C5A6D160F6D4C5A6E4B5A267F +DFC0EDFFC0D9CFF04A90C9FCD987FCEC07FE902603FF80EB1FFCD8FE019039F801FFF048 +6C6CB65A486D158048010F4ACAFC020114F048D9000F1380546878E458>83 +D97 DI< +D90FF0EC03FFD93FFC023F13E049B491B512F8903CFC3F8003FE07FC3D01F01FC007E001 +FED803E0903AE01F8000FFD9C00F49C76C7E0007DAF07C8101805C000FECF9F00100D9FB +E06E7E48ECFFC0001E5D4A90C8FC123E003C5C4B157F143F007C5C12785D027F16FF00F8 +6100705CC7FC02FF5D625DA2495E97C7FC5D60495FA292C8120F615B181F4A5EA2010F16 +3F4F133C5C187F011F4D137C06FF14784A5E1BF8013F4B15F0614A17011BE0017FEF0003 +1BC04A17071B8001FFF00F00715C4A173E725B624A92383F87F095381FFFC06DC900075B +013CDC01FEC7FC4E427DBF56>110 D +112 DI E /Fh 10 118 +df[217 +170 119 297 236 77 D[178 173 120 297 188 82 D<0407B57E0303B7FC033F16E04AB812FE020F717E023F +18F091BA12FC49850107737E499126FE000F81490280010115F0706D6C80496E6E804905 +0F80706E8090B66C6E818589486F6E81A274808986A28986896C5DA36D4A6F806D5CA26D +5C6D5C6D91C9FC010113FC9038003FE091CBFCA897B7FC060FB8FC0507B9FC94BAFC160F +93BBFC1507153F92B812CF0207EEE00F021FEDFE00027F15E091B71280010303FCC7FC49 +15F04915C0495D017F4AC8FC5E90B65A485D485D485DA2485D4892C9FCA25A5D5A5DA3B6 +FC5DA462A462816C61A297B7FC6C80616C6E4B5A0707826C6F4A48816C6F4A4815F0073F +16FE6C6F9126FFF07FECFFFE6C03F84901E0826C6F010F01C017806D9126FF807F497E01 +1F92B612006D4D7F01034D7F01004D1303023F04E07F020704806D7E02004BC8000F1500 +030F02F003015CDB007F90CEFC717179EF79>97 D<943803FFFC94B612F0040715FE043F +EDFFC04BB812F0030717FC031F17FF037F18C04ABA7E4ADBC03F14F8020F9126FE000780 +4A02F80101804A4A6D6C7F4A02C06E8091B6486E804992C86C80494A81497280494A8449 +4A814972805E49737F5E90B68548864C19805A87481DC0A25E487414E0A25AA21EF0A248 +92CA7EA35AA21EF8A4B7FCA393BBFCA61EF01EE093CEFCA77EA67EA2827EA47EF51FE06C +6FF03FF0F57FF8A27E7018FF7E5213F06C816D5013E0826D5013C06D6E5F704D13806D62 +6D6E4D13006D6F93B5FC6D6F4B5B6D6F4B5B6E02F8030F5B6E6E033F5B6E02FF92B55A6E +03C001075C020303FC017F5C6E92B748C7FC6E6C60031F606F18E0030118806F6C4CC8FC +040F16F0040116C0DC001F02FCC9FCDD007F1380657179EF74>101 +D[<4AB4FC020F13E0023F13F891B512FE49804981498149814981A24981A24981A390B7 +7EA96D5DA36D5DA26D5DA26D5D6D5D6D5D6D92C8FC6D5C023F13F8020F13E0020190C9FC +91CBFCB3A5EE7FF0010FB6FC007FB7FCACEA000F13017FA280B3B3B3B3A9BA12E0AB49C8 +1203>59 173 122 300 68 105 D[61 172 122 299 68 108 D<922601FFC0ED7FFF013F +B60307B512F8B8033FECFF804FB712E0070716F8071F16FE4F8296B97E4E844E0200814E +01F06D804E01C07F4E90C76C80DE3FFC83D8001F4C48800101DCFFE0836D5F05C1496E80 +6E02C390C8FC60DDC7FC85EFCFF86005DF826005FF866060A395C9FCA25FA35FA55FB3B3 +B3A5BAD8FC03BA12E0AB49C8000104F0C8120F836F7AEE8A>110 +D<4BB5EC0FC0037F02F8133F0207B7EBFFE0023F16C391BAFC13035B131F49EC00034901 +F0EB003F90B50080140F4849C812034849814A8148498248498285484982A248845C5A85 +A4B56C82A380A2806E705B14FE6E94C8FC15C015F015FE6CECFFE016FF17F8EFFFC06C17 +F818FF6C18E019F86C18FE856C19C06C856C851AFC6C856D847F010F856D856D8513006E +84021F841403DA007F83150F0300831607EE003F050181EF003F18077215801800D83FE0 +83007F181F486C83A2856D83A2857FA285A27F1C007FA280636E5EA26E6061806E606E4C +5B6E5E6E4C5B6F4B5B03E05D03F84AB55A03FE020F91C7FCDBFFE090B55A93B75A62023F +17E0496C5FD9F80794C8FCD9F00116F89026C0003F15E06C4801074AC9FC007EC86C13C0 +517178EF62>115 D[<923801FFE0AA5DA75DA45DA45DA35DA25DA392B5FCA25C5CA25C5C +5CA25C5C91B6FC13035B011F92B71280137F0007BBFCBCFCA9D8000103E0C9FCB3B3B2F2 +7FF8B3A31AFF6D6F15F0A36E5E1BE0836E4C13C0836E5E7115806E6E4913006EED803F6E +9238E07FFE6E92B55A806F5E6F5E6F5E03075E030193C7FCDB003F5C040714F0DC001F13 +80>77 158 123 284 97 II E end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: a4 +%%BeginPaperSize: a4 +a4 +%%EndPaperSize + +%%EndSetup +%%Page: 1 1 +1 0 bop 1569 1461 a Fh(Main)82 b(Result)1427 2057 y Fg(S)48 +b Ff(=)1765 1877 y Fe(1)1719 1921 y Fd(X)1714 2224 y +Fc(n)p Fb(=0)1972 1960 y Fg(a)p Ff(\()p Fg(n)p Ff(\))p +1972 2024 274 6 v 1979 2155 a Fg(b)p Ff(\()p Fg(n)p Ff(\))2304 +1960 y Fg(p)p Ff(\(0\))24 b Fa(\001)g(\001)g(\001)e Fg(p)p +Ff(\()p Fg(n)p Ff(\))p 2304 2024 741 6 v 2307 2155 a +Fg(q)5 b Ff(\(0\))24 b Fa(\001)g(\001)g(\001)e Fg(q)5 +b Ff(\()p Fg(n)p Ff(\))0 2533 y(with)48 b Fg(a)p Ff(\()p +Fg(n)p Ff(\),)f Fg(b)p Ff(\()p Fg(n)p Ff(\),)g Fg(p)p +Ff(\()p Fg(n)p Ff(\),)g Fg(q)5 b Ff(\()p Fg(n)p Ff(\))48 +b(small)g(in)l(tegers)87 b(=)39 b Fg(O)t Ff(\()p Fg(n)3060 +2481 y Fc(c)3119 2533 y Ff(\))0 2877 y(can)47 b(b)t(e)g(computed)e(to)i +Fg(N)64 b Ff(digits)48 b(in)h(time)717 3170 y Fg(O)855 +3011 y Fd(\020)940 3170 y Fg(M)16 b Ff(\()p Fg(N)g Ff(\))24 +b(\(log)h Fg(N)16 b Ff(\))1813 3098 y Fb(2)1877 3011 +y Fd(\021)2003 3170 y Ff(=)39 b Fg(O)2292 3011 y Fd(\020)2377 +3170 y Fg(N)h Ff(\(log)26 b Fg(N)16 b Ff(\))2984 3098 +y Fb(3)3096 3170 y Ff(log)26 b(log)h Fg(N)3646 3011 y +Fd(\021)3731 3170 y Ff(.)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/ratseries/slides/slide2.tex b/doc/ratseries/slides/slide2.tex new file mode 100644 index 0000000..d276eb6 --- /dev/null +++ b/doc/ratseries/slides/slide2.tex @@ -0,0 +1,28 @@ +\magnification=\magstep3 +\hsize=19truecm +\vsize=19truecm +\nopagenumbers +\parindent=0mm +\font\eins=cmb10 scaled \magstep 3 +\font\zwei=cmr12 +\font\mini=cmr7 +\def\frac#1#2{{{#1} \over {#2}}} +\hbox{} +\vfill + +\centerline{\eins Main Result} +\bigskip\bigskip +\centerline{$\displaystyle S = {\sum\limits_{n=0}^{\infty} \frac{a(n)}{b(n)} \, \frac{p(0) \cdots p(n)}{q(0) \cdots q(n)}}$} +\bigskip +with $a(n)$, $b(n)$, $p(n)$, $q(n)$ small integers ${} = O(n^c)$ +\bigskip +can be computed to $N$ digits in time +\medskip +\centerline{$O \left( {M(N) \, {(\log N)}^2} \right) += O \left( N \, {(\log N)}^3 \, \log \log N \right)$.} + +\vfill +\hbox{} +\eject + +\end diff --git a/doc/ratseries/slides/slide3.dvi b/doc/ratseries/slides/slide3.dvi new file mode 100644 index 0000000000000000000000000000000000000000..92b3090656124d70ec9fe0b4b7cb039a134e7f8d GIT binary patch literal 1700 zcmb7ET}TvB6uz@RW@>*{q$r^w(a#n$mThYFum(ODj}R8TKH)Ie55c4l{02ONv;Fb{j?obP=1oNvD= z6L)&}VQDRblk>2o%q{LK>*xx1c7@A?>T3ID-o9DbR#REY^8=8((NI%oyDuE}1&$D@ z0wJuRhA#&r=~OK}DDbjN^mYY9zT-o;-iy@S-0W#T(h>B9kNRtfRI+R(rp~xW$;lsY z+ci^}rkvSe@hyMBF> zP{e)*B?KZBTsV#~wf5&p-+F&3g+EzWp`O3kE%5jE5hCUHSuiy{DM|(sJG0;dAp}Fy zA3G{AEgqJbM_$JQGSGn^lI6tWvj`m)(ekCAq=oBV;Gy0+)~03XEBWLI>r~@#>E3A| zMJ+ucc|DGCH?AoKfjUb=cb-IZVqIX9b9h?=&)l?CAHjPJHZ znKK4h02%#1ikUIZ#oQFPk?RE@VCJCa`m5&_ZR?k(JGY7XR_}LRUq)MK-spZxO z`2?t*NUMr@OuIi$YwAw4&Z^=s0@cKlKlPotL7G1sW>>aqTSg`hYP#)Aaq6s?6Lg~P z;=w4Ud5F^#qNk`+&4RiCwnJTyyp=9$Zb_A^oaIBlpy&;^N66(u7>$aOEtwxCwQ>$j zNc9ME2@j)FgORKl(pqRt&o;S-(A+Aw##@WI2)P0kedbr$UBl81(zRGNeHY7aFx|jm zP@%=r6|}|nSY3@OPkn)l#B!fHQruX2k{J*eiKe(Xb7vuAz**iHXEQz0pJ%S5PljGZ zDne-RJ9yCsy?t|ylQz|IQ7+;Pz1G-Q3|-0i4{zv_#%^n5nnu=Z=<+|nY44fdWX>Oh CDurnP literal 0 HcmV?d00001 diff --git a/doc/ratseries/slides/slide3.log b/doc/ratseries/slides/slide3.log new file mode 100644 index 0000000..362349d --- /dev/null +++ b/doc/ratseries/slides/slide3.log @@ -0,0 +1,6 @@ +This is TeX, Version 3.14159 (C version 6.1) (format=tex 96.5.7) 16 JUL 1997 22:00 +**slide3.tex +(slide3.tex +Hyphenation patterns for english, german, francais, loaded. +[1] ) +Output written on slide3.dvi (1 page, 1700 bytes). diff --git a/doc/ratseries/slides/slide3.ps b/doc/ratseries/slides/slide3.ps new file mode 100644 index 0000000..7f39af2 --- /dev/null +++ b/doc/ratseries/slides/slide3.ps @@ -0,0 +1,478 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: slide3.dvi +%%Pages: 1 +%%PageOrder: Ascend +%%BoundingBox: 0 0 596 842 +%%DocumentPaperSizes: a4 +%%EndComments +%DVIPSCommandLine: dvips -Pljfour -o slide3.ps slide3.dvi +%DVIPSParameters: dpi=600, compressed, comments removed +%DVIPSSource: TeX output 1997.07.16:2200 +%%BeginProcSet: texc.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]/id ch-image N /rw ch-width 7 add 8 idiv string N /rc 0 N /gp 0 N +/cp 0 N{rc 0 ne{rc 1 sub /rc X rw}{G}ifelse}imagemask restore}B /G{{id +gp get /gp gp 1 add N dup 18 mod S 18 idiv pl S get exec}loop}B /adv{cp +add /cp X}B /chg{rw cp id gp 4 index getinterval putinterval dup gp add +/gp X adv}B /nd{/cp 0 N rw exit}B /lsh{rw cp 2 copy get dup 0 eq{pop 1}{ +dup 255 eq{pop 254}{dup dup add 255 and S 1 and or}ifelse}ifelse put 1 +adv}B /rsh{rw cp 2 copy get dup 0 eq{pop 128}{dup 255 eq{pop 127}{dup 2 +idiv S 128 and or}ifelse}ifelse put 1 adv}B /clr{rw cp 2 index string +putinterval adv}B /set{rw cp fillstr 0 4 index getinterval putinterval +adv}B /fillstr 18 string 0 1 17{2 copy 255 put pop}for N /pl[{adv 1 chg} +{adv 1 chg nd}{1 add chg}{1 add chg nd}{adv lsh}{adv lsh nd}{adv rsh}{ +adv rsh nd}{1 add adv}{/rc X nd}{1 add set}{1 add clr}{adv 2 chg}{adv 2 +chg nd}{pop nd}]dup{bind pop}forall N /D{/cc X dup type /stringtype ne{] +}if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +TeXDict begin 39158280 55380996 1728 600 600 (slide3.dvi) +@start /Fa 4 34 df<007FBC12FCBD12FEA46C1BFC570674A670>0 +DI<127812FE6C7E13E013F8EA7FFE380FFF80000313E0C613F8EB3FFE90380FFF800103 +13E0010013F8EC3FFF020F13C0020313F0020013FCED3FFF030F13C0030113F09238007F +FCEE1FFF040713C0040113F09338007FFCEF1FFF050713E0050113F89438007FFE95381F +FF80060713E0060113F89538003FFE96380FFF80070313E0070013F8F23FFE97380FFF80 +080313E0080013FCF33FFE1B0FA21B3FF3FFFC080313E0080F138097383FFE00F2FFF807 +0313E0070F1380DF3FFEC7FC953801FFF8060713E0061F1380DE7FFEC8FC943801FFF805 +0713E0051F90C9FCEF7FFC933801FFF0040713C0041F90CAFCEE7FFC923801FFF0030F13 +C0033F90CBFCEDFFFC020313F0020F13C0023F90CCFCECFFF8010313E0010F1380D93FFE +CDFCEBFFF8000313E0000F1380D83FFECEFCEA7FF8EAFFE0138048CFFC1278D0FCB3A400 +3FBC12F8481BFCBD12FEA36C1BFC577074DA70>21 D<1D1E1D3FA38A1D1FA38A1D0FA28A +1D078A1D038A1D018A777EA21E7F8B1E3F787E787E8B787E787E787E787EF77FC0797EF7 +1FF8797E79B4FC007FC112E0C212F821FCA221F86C20E0D200071300F70FFC555AF73FE0 +555A55C7FC545A545A545A545A67545A545A1E7F9CC8FC1EFEA2535A661D03661D07661D +0F66A21D1F66A31D3F9BC9FCA31D1E7E4C78C98F>33 D E /Fb 1 +89 df<007FC5B512F8C5B67EA3A181A2A1816C02C0D0FC6C6EE3000F836C6EF6001F2300 +6C6E0E0F816C6E2000A1011F806C6E21076C6E0F00806C6F213FA1140F6D6E0F037F6D6E +8D6D6E7B6C7EA1153F6D6EFA0FFE6D6E2207A115036D6E7C7E6D6E7C7E6D6FFA3F80A26E +6EFA1FC06E6E220F6E6E2207A1EE03E06E806E6EFA01F0A116006E6E23F86E6E23786E81 +A1173C6F6E22006F806F80A26F806F80A26F806F806F81A2708070807080A270807080A2 +708070807081A2718071807180A271807180A2718071807181A2728072807280A2728072 +80A2728072807281A2738073807380A273807380858873807381A2748074807480A27480 +868665745C745CA2755B7590D2FC755A6464515A1B7F515A64505B5090D3FC505A1A0F50 +5A505A63505A505A4F5B614F90D4FC624F5A4F5A4F5A197F4F5A4E5B624E90D5FC4E5A4E +5A181F4E5A614E5A4E5A4D5B5F4D90D6FC4D5A604D5A4D5A4D5A17FF4C5B604C90D7FC4C +48233C4C482378161F4C4823F84C4823F04D22014C5A4B49FA03E04B90D612074BA113C0 +4B48230F4C231F4B48FB3F804B48237F4B4823FF03FF5913004A496A4A496A93D6EA1FFE +4A48233F4A48FBFFFC4A486A023F23074A48101F5B4B227F4A4857B5FC49490F0F5C4990 +D5127F491003B65A4948213F49480E0FB7FC4A0D07B85A49480C7FB9FC49C5B5FC90C5B6 +5A5A5AA193C7FC5A48A15C5A5A48A15CC5B6FCA26CA15CBEC9787FCF>88 +D E /Fc 1 1 df<007FBA12E0BB12F0A36C19E04405759B5A>0 D +E /Fd 2 51 df49 DI +E /Fe 4 111 df<120FEA3FC0EA7FE0EAFFF0A313F8A3127F123FEA0F381200A4137813 +70A213F0A213E0120113C01203EA0780A2EA0F00121E5A123812300D20758B22>59 +D<027FB67E91B77EA26E5D9126007FFEC9FCED3FF0157FA25EA315FF5EA35C5EA35C93CA +FCA35C5DA3140F5DA3141F5DA3143F5DA3147F5DA2F1038002FF16075D190F1A005B4B5D +191E193E5B92C95AA2614916015C4E5A1807010F160F4A4B5A187F011F4B485A1707D97F +F8147F007FB95ABAFCA26C95C7FC414579C44F>76 D<027FB712C091B812FCF1FF806E17 +E09126007FF8C713F86F48EC1FFC037FED07FF070113804C6E13C0A2F27FE015FF4C16F0 +A35C5EA34AEFFFE093C9FC1BC0614A18804B4B13004F5A62020F4C5A4B4B5AF17FC04E48 +5A021FDB07FEC7FC4BECFFF892B712C04EC8FC4A819226F0000313C09438007FE0F01FF0 +027F6F7E4B81727EA202FF15035DA218075B5DA2180F5B92C8FCA24E5A5B5CA21B0E010F +191E5C1B3E011F193C1B7C017F040F1478007FB500FC17F0B66C913807FE01953903FF07 +E06C4A6EEBFF80CC6C1300F10FFC4F477AC456>82 D<017EEC1FF048B46CEBFFFE48D9E0 +036D7E3C0787F00FE03FC03C0F03F81F001FE0DAFC3C130F001E4A800101491307003CEB +FDE049B44880007C5C127892C7FC4948140F00F05F5C00005B010F151F605CA2011F153F +605C177F013F5EA24A14FF95C7FC017F4A147C4D13785C160301FF4B13F819F091C71401 +05F813E048EF03C0180749EE0F80F01F00933801FC3E49913800FFFCEF3FF0D800F0ED0F +C03E2D7BAB47>110 D E /Ff 5 92 df<12E07E127C7E7E6C7E6C7E6C7E6C7E7F6C7E13 +7C137E7F7F806D7EA26D7EA26D7EA2801301A280130080A2147E147FA4801580A5141F15 +C0B11580143FA515005CA4147E14FEA25C13015CA213035CA2495AA2495AA2495A91C7FC +5B137E137C13FC485A5B485A485A485A48C8FC123E5A12F05A1A6379CA2D>41 +D<141E143E147EEB01FE1307137FB5FCA213FB1383EA0003B3B3AF497E497F007FB612F8 +A4254375C239>49 DI<007FBBFCBC1280A36C1A00CFFCB3007FBBFCBC1280A36C1A00491D79A758>61 +D91 D E /Fg 11 +114 df<1C3C1CFE1B031B0F1B3FF3FFFC080313E0080F138097383FFE00F2FFF8070313 +E0070F1380DF3FFEC7FC953801FFF8060713E0061F1380DE7FFEC8FC943801FFF8050713 +E0051F90C9FCEF7FFC933801FFF0040713C0041F90CAFCEE7FFC923801FFF0030F13C003 +3F90CBFCEDFFFC020313F0020F13C0023F90CCFCECFFF8010313E0010F1380D93FFECDFC +EBFFF8000313E0000F1380D87FFECEFCEAFFF813E0A213F8EA7FFE380FFF80000313E0C6 +13F8EB3FFE90380FFF80010313E0010013F8EC3FFF020F13C0020313F0020013FCED3FFF +030F13C0030113F09238007FFCEE1FFF040713C0040113F09338007FFCEF1FFF050713E0 +050113F89438007FFE95381FFF80060713E0060113F89538003FFE96380FFF80070313E0 +070013F8F23FFE97380FFF80080313E0080013FCF33FFE1B0F1B031B001C3C575474CD70 +>60 D<92BA12C04A19FCF4FF801DE01DF891C7003F01C0C700017F040F90C96CB4FC0A1F +13807613C04D827613E0041F7113F0A24D7013F8A2163FF57FFC5FA2167FA25FA204FF18 +FF1EF85FA24B4E13F0A24D4C13E0A24B4E13C01E804D5E5213004B4E5A525A94CA485A51 +5B4B4D13C0090F5B4C4C48C7FCF37FF8031F933801FFE0080F13804C912603FFFCC8FC93 +B812E04B17FCF3FF8004F8C8000113E09738007FF8037FEF1FFC75B4FC4C707F757F15FF +757F4C84874A86A24C717EA25CA25EA25CA293CB12FFA25C654B5FA2021F62634B616302 +3F4E5B654B5F5190C7FC027F4E5A515A4B4C5B505B02FF4D5B081F5B4B4C5B49DEFFFEC8 +FC07075B010F057F13F0007FBB12C0BCC9FC1AF81AC007FCCAFC66627AE16D>66 +D<92BAFC4A19F81CFF1DC08991C7003F01E0C7000F13F8040F018002017F9838003FFE76 +7E95C9000713807613C01EE04C834D18F088A2043F19F85FA3167F5FA304FF5F5FA34B4E +13F05FA25213E05D4D18C0521380A24B4E13004D5F525A525A4B4E5A94CA5B09035B515B +4B4D90C7FC4CEE3FFCF3FFF8080713E0033F047F138093B800FCC8FC1BF04B94C9FC1AE0 +04F8CDFCA215FFA25EA25CA25EA25CA25EA25CA25EA25CA293CEFCA25CA25DA2143FA25D +A2147FA25DA214FFA25D5BA2010F13FC007FB77EB87E5FA365627AE15C>80 +DI<9426 +01FFE01460051F01FC14F094B6EA800104039238E003E0040FEDF0074C9038007FF8DC7F +F0903807FC0FDCFFC0903901FE1FC04B90C8EA7F3FDB07FEED3FFFDB0FF8814B486F1380 +4B48814C814B5A4BC914004A835D4A4882020760A24A5AA2021F605DA3023F60A46381A2 +636F94C7FC81A28116C016F06E13FEEEFFE06E14FEEFFFE06E15FCF0FFC06E16F06E826E +16FE6F81031F826F821501DB003F81040381EE007F050780EF007F060F7F18031800197F +A2193F737EA3190F01E060487EA25BA2120362A30007181F62A262000F183F62197F6248 +6C4DC8FC606D5F4E5A486C4C5A6D160F6D4C5A6E4B5A267FDFC0EDFFC0D9CFF04A90C9FC +D987FCEC07FE902603FF80EB1FFCD8FE019039F801FFF0486C6CB65A486D158048010F4A +CAFC020114F048D9000F1380546878E458>83 D<011FBD12801EC05BA21E80499026C000 +0101F8C77E02FCC74A140702F01901D9FFC04CEC007F91C8FC494B173F48481C00495F49 +8700035E5B0007605B4D171E485A96C9FC90C9FC485E001E1C3E4E163C123E003C163FA2 +007C5F1278057F177C00F81C7800704D1638CA95C7FC17FFA260A25EA260A25EA260A25E +A260A25EA295CCFCA25EA25FA2163FA25FA2167FA25FA216FFA25FA25DA25FA25DA25FA2 +5DA25FA25DA294CDFCA25DA25E153F4B7E0207B512E00003B912C0488461A362617DE054 +>I97 D +I110 D +112 DI E /Fh 29 122 +df40 +D<126012F012787E123E7E6C7E6C7E6C7E6C7E7F6C7E137E133E133F6D7E80130F6D7EA2 +6D7E80130180130080A2147FA26E7EA281141FA281140FA281A2140781A36E7EA4811401 +A581A280A61680B3A41600A65CA25DA514035DA44A5AA35D140FA25DA2141F5DA2143F5D +A24AC7FCA214FEA25C13015C13035C495AA2495A131F5C49C8FC133E137E5B485A5B485A +485A485A48C9FC123E123C5A5A1260219078EB38>I43 DI<153C157C15FC140114 +07141F147FEB03FF137FB6FCA2149FEBFC1F1380C7FCB3B3B3B34A7EA249B512C0007FB8 +FCA5305F74DE48>49 D52 D58 D<007FBD12FCBE12FEA4003F1CFCD1FCB3A4003FBD12FCBE12FE +A46C1CFC5F2278B470>61 D67 D82 D97 D99 +DII103 D<14F8EA07FFB5FCA51201EA00 +7F133F131FB3A8EE0FFE93387FFFC04BB512F0923907F81FFC92390FC007FE92391F0001 +FF153C4B6D7F4B81DAF9E0147FDAFBC0815D14FF92C8123F855CA25CA45CB3B2496C4B7E +90B5913801FFFEB748B612FEA547647BE350>I<131FEB7FC0497E487FA2487FA56C5BA2 +6C5B6D5A011FC7FC90C8FCB214F8EA03FF127FA51201EA007F133F131FB3B3AB497EEBFF +FEB612FEA51F617CE027>I<14F8EA07FFB5FCA51201EA007F133F131FB3B3B3B3AB497E +90B5FCB7FCA520647CE327>108 DIII<02F8EB3FF8D807FF49B57EB5010714E092391F +E01FF892397F0007FE03FCEB01FFDAF9F06D13C0C6D9FBE06E7E90263FFFC06E7E6D496E +7E92C86C7E4A8218074A824A6F1380A27213C01AE084A21AF0197F1AF8A4193F1AFCACF1 +7FF8A41AF019FFA21AE0601AC0A24E1380804E13006E4B5A616E4B5A6F4A5A6F5DDAFBE0 +ECFFC0DAF9F0495BDAF8F84990C7FC037EEB0FFC92393FC07FF0030FB512C0030391C8FC +9238007FF093CAFCB3497E90B5FCB7FCA5465C7CBF50>I114 DI<143CA7147CA514FCA31301A21303A21307A2130F131F133F137F13FF000390 +B612C0120FB8FCA326000FFCC8FCB3AD17F0AE010714016E14E0A3010314036E14C07F6D +903880078091387FC00F91393FE01F0091381FF87E6EB45A02035B9138003FE02C5A7DD7 +38>I<02F8ED01F0D807FFED0FFFB54AB5FCA50001ED0003D8007F1500013F167F011F16 +3FB3B2187FA418FFA2130F5FA26E5C0107923807BFF8F03FFC6D6C020F13FF0101031E14 +FE6D6C147CDA7FC013F891393FF807F0020FB512C00203028014C09128003FFC003EC7FC +47427BBF50>III121 D E /Fi 11 122 +df[153 +170 120 297 176 66 D[<94B5EE01F8041F02FC15034BB76C4A7E030F04F0140F033F04 +FE141F92B96C133F020306E0137F020F06F813FF4A725A4A725A91BB128749DBE00115CF +494AC7000F91B5FC4902F814014902E06E7E490280151F93C91207494916014949824B83 +90B548171F48864B834886484A83A287484A84A2488788A24891CC7EA288A25A88A288A2 +B6FC8188A3811D7FA281A2811D3F8181818170725A6C817095C8FC16F816FE707E6C16F8 +EFFF8018F8F0FF806C18F8F1FF806C19F8F2FF801BF06C1AFE757E6C1BE01CF86C876C1B +FF896D876D87896D876D876D876D876D886D88806E876E87800203876E876E7E031F8615 +07030086161F04011A80EE001F1701DD001F18C01801F0001F070117E0F1001F1A030800 +16F087871B0F87871FF88787EA3FE0007F87487E88A288A388A27FA288A36D1DF0A47FA2 +1FE07FA26E611FC080A26E1C806E61801F006E616E636E616F6203E095B5FC6F626F4D5C +03FE5F6F6C4C5C04E04C5C04F84C5C04FE167FDCFFC092B6C7FC05FE02035CDDFFF8013F +5C02C792B85A028362020062496D198049011F96C8FC49010718FC49010018F049023F17 +C049020794C9FC49DA007F15F86CC9000715C0007EDC001F01F8CAFC>109 +176 114 300 138 83 D<0407B57E0303B7FC033F16E04AB812FE020F717E023F18F091 +BA12FC49850107737E499126FE000F81490280010115F0706D6C80496E6E8049050F8070 +6E8090B66C6E818589486F6E81A274808986A28986896C5DA36D4A6F806D5CA26D5C6D5C +6D91C9FC010113FC9038003FE091CBFCA897B7FC060FB8FC0507B9FC94BAFC160F93BBFC +1507153F92B812CF0207EEE00F021FEDFE00027F15E091B71280010303FCC7FC4915F049 +15C0495D017F4AC8FC5E90B65A485D485D485DA2485D4892C9FCA25A5D5A5DA3B6FC5DA4 +62A462816C61A297B7FC6C80616C6E4B5A0707826C6F4A48816C6F4A4815F0073F16FE6C +6F9126FFF07FECFFFE6C03F84901E0826C6F010F01C017806D9126FF807F497E011F92B6 +12006D4D7F01034D7F01004D1303023F04E07F020704806D7E02004BC8000F1500030F02 +F003015CDB007F90CEFC717179EF79>97 D103 D[<4AB4FC020F13E0023F13 +F891B512FE49804981498149814981A24981A24981A390B77EA96D5DA36D5DA26D5DA26D +5D6D5D6D5D6D92C8FC6D5C023F13F8020F13E0020190C9FC91CBFCB3A5EE7FF0010FB6FC +007FB7FCACEA000F13017FA280B3B3B3B3A9BA12E0AB49C81203>59 +173 122 300 68 105 D[61 172 122 299 68 108 D<922601FFC0ED7FFF013FB60307B5 +12F8B8033FECFF804FB712E0070716F8071F16FE4F8296B97E4E844E0200814E01F06D80 +4E01C07F4E90C76C80DE3FFC83D8001F4C48800101DCFFE0836D5F05C1496E806E02C390 +C8FC60DDC7FC85EFCFF86005DF826005FF866060A395C9FCA25FA35FA55FB3B3B3A5BAD8 +FC03BA12E0AB49C8000104F0C8120F836F7AEE8A>110 D +112 D<4BB46C903807FF80013FB6023F13FCB849B67E4E15E0060F15F84E15FE4E814E16 +8095B812C00581D9FC0F14E0DFF01F14F0058313C00587D9003F14F84E4914FCD8000FED +8FFC01015E6DDB9FF090B612FEA26EECBFE0A26017FF60A295C7FC7414FCA34D6E14F874 +14F0A24D6E14E07414C07414800800EBFE00F31FF04D92C8FCA95FB3B3B2BB7EAB49C97E +5F6F7CEE6A>114 D[<923801FFE0AA5DA75DA45DA45DA35DA25DA392B5FCA25C5CA25C5C +5CA25C5C91B6FC13035B011F92B71280137F0007BBFCBCFCA9D8000103E0C9FCB3B3B2F2 +7FF8B3A31AFF6D6F15F0A36E5E1BE0836E4C13C0836E5E7115806E6E4913006EED803F6E +9238E07FFE6E92B55A806F5E6F5E6F5E03075E030193C7FCDB003F5C040714F0DC001F13 +80>77 158 123 284 97 116 D121 D E end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: a4 +%%BeginPaperSize: a4 +a4 +%%EndPaperSize + +%%EndSetup +%%Page: 1 1 +1 0 bop 1364 688 a Fi(Binary)83 b(Splitting)0 1205 y +Fh(Recursiv)l(e)47 b(algorithm:)1171 1593 y Fg(S)1259 +1619 y Ff([)p Fe(n)1362 1633 y Fd(1)1418 1619 y Fe(;n)1523 +1633 y Fd(2)1579 1619 y Ff(\))1671 1593 y Fh(=)1828 1412 +y Fe(n)1899 1426 y Fd(2)1955 1412 y Fc(\000)p Ff(1)1862 +1457 y Fb(X)1822 1758 y Fe(n)p Ff(=)p Fe(n)2052 1772 +y Fd(1)2149 1496 y Fg(a)p Fh(\()p Fg(n)p Fh(\))p 2149 +1560 274 6 v 2156 1691 a Fg(b)p Fh(\()p Fg(n)p Fh(\))2481 +1496 y Fg(p)p Fh(\()p Fg(n)2695 1517 y Ff(1)2760 1496 +y Fh(\))24 b Fa(\001)g(\001)g(\001)f Fg(p)p Fh(\()p Fg(n)p +Fh(\))p 2481 1560 820 6 v 2484 1691 a Fg(q)5 b Fh(\()p +Fg(n)2695 1713 y Ff(1)2760 1691 y Fh(\))24 b Fa(\001)g(\001)g(\001)f +Fg(q)5 b Fh(\()p Fg(n)p Fh(\))0 1995 y(Compute)45 b Fg(P)60 +b Fh(=)39 b Fg(p)p Fh(\()p Fg(n)1139 2016 y Ff(1)1203 +1995 y Fh(\))24 b Fa(\001)g(\001)g(\001)f Fg(p)p Fh(\()p +Fg(n)1688 2016 y Ff(2)1785 1995 y Fa(\000)31 b Fh(1\),)47 +b Fg(Q)41 b Fh(=)e Fg(q)5 b Fh(\()p Fg(n)2659 2016 y +Ff(1)2724 1995 y Fh(\))24 b Fa(\001)g(\001)g(\001)f Fg(q)5 +b Fh(\()p Fg(n)3206 2016 y Ff(2)3302 1995 y Fa(\000)31 +b Fh(1\),)0 2167 y Fg(B)47 b Fh(=)39 b Fg(b)p Fh(\()p +Fg(n)511 2188 y Ff(1)575 2167 y Fh(\))24 b Fa(\001)g(\001)g(\001)f +Fg(b)p Fh(\()p Fg(n)1050 2188 y Ff(2)1146 2167 y Fa(\000)31 +b Fh(1\))48 b(and)f Fg(T)67 b Fh(with)1735 2498 y Fg(S)1823 +2524 y Ff([)p Fe(n)1926 2538 y Fd(1)1982 2524 y Fe(;n)2087 +2538 y Fd(2)2143 2524 y Ff(\))2235 2498 y Fh(=)2518 2401 +y Fg(T)p 2403 2465 334 6 v 2403 2597 a(B)39 b Fa(\001)32 +b Fg(Q)143 2911 y(n)229 2932 y Ff(2)326 2911 y Fa(\000)f +Fg(n)555 2932 y Ff(1)660 2911 y Fg(<)39 b Fh(4)191 b +Fa(!)48 b Fh(directly)143 3169 y Fg(n)229 3190 y Ff(2)326 +3169 y Fa(\000)31 b Fg(n)555 3190 y Ff(1)660 3169 y Fa(\025)39 +b Fh(4)191 b Fa(!)48 b Fh(split)1859 3427 y Fg(P)59 b +Fh(=)40 b Fg(P)2254 3449 y Fe(L)2372 3427 y Fa(\001)31 +b Fg(P)2535 3449 y Fe(R)1837 3599 y Fg(Q)40 b Fh(=)f +Fg(Q)2254 3621 y Fe(L)2372 3599 y Fa(\001)32 b Fg(Q)2557 +3621 y Fe(R)1840 3771 y Fg(B)47 b Fh(=)39 b Fg(B)2256 +3793 y Fe(L)2374 3771 y Fa(\001)31 b Fg(B)2554 3793 y +Fe(R)1236 3943 y Fg(T)60 b Fh(=)39 b Fg(B)1640 3965 y +Fe(R)1766 3943 y Fa(\001)32 b Fg(Q)1951 3965 y Fe(R)2077 +3943 y Fa(\001)g Fg(T)2233 3965 y Fe(L)2351 3943 y Fh(+)f +Fg(B)2603 3965 y Fe(L)2721 3943 y Fa(\001)g Fg(P)2884 +3965 y Fe(L)3002 3943 y Fa(\001)h Fg(T)3158 3965 y Fe(R)p +eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/ratseries/slides/slide3.tex b/doc/ratseries/slides/slide3.tex new file mode 100644 index 0000000..f57efcf --- /dev/null +++ b/doc/ratseries/slides/slide3.tex @@ -0,0 +1,38 @@ +\magnification=\magstep3 +\hsize=19truecm +\vsize=19truecm +\nopagenumbers +\parindent=0mm +\font\eins=cmb10 scaled \magstep 3 +\font\zwei=cmr12 +\font\mini=cmr7 +\def\frac#1#2{{{#1} \over {#2}}} +\hbox{} +\vfill + +\centerline{\eins Binary Splitting} +\bigskip\bigskip +Recursive algorithm: +\medskip +\centerline{$\displaystyle S_{[n_1,n_2)} = {\sum\limits_{n=n_1}^{n_2-1} \frac{a(n)}{b(n)} \, \frac{p(n_1) \cdots p(n)}{q(n_1) \cdots q(n)}}$} +\medskip +Compute $P = {p(n_1) \cdots p(n_2-1)}$, $Q = {q(n_1) \cdots q(n_2-1)}$, +\vskip 0cm +$B = {b(n_1) \cdots b(n_2-1)}$ and $T$ with +\medskip +\centerline{$\displaystyle S_{[n_1,n_2)} = \frac{T}{B \cdot Q}$} +\bigskip +\quad $n_2 - n_1 < 4$ \quad $\rightarrow$ directly +\medskip +\quad $n_2 - n_1 \geq 4$ \quad $\rightarrow$ split +\medskip +\centerline{$P = P_L \cdot P_R$} +\centerline{$Q = Q_L \cdot Q_R$} +\centerline{$B = B_L \cdot B_R$} +\centerline{$T = B_R \cdot Q_R \cdot T_L + B_L \cdot P_L \cdot T_R$} + +\vfill +\hbox{} +\eject + +\end diff --git a/doc/ratseries/slides/slide4.dvi b/doc/ratseries/slides/slide4.dvi new file mode 100644 index 0000000000000000000000000000000000000000..de88ec6ed4bc311282bd00a29399ae42720731f8 GIT binary patch literal 1332 zcmah}TSyd97(U~=Yu-xTyp$Shl2>eIkycG3vG8Fb#T2c;beHu4?yR`GxDsR_T2kle zX=4K)I?_`$s0>JgAlVJ+p^_dd>7qnPg)cTzUa>QyxdUzZ!!T#gob#RU|IYXSzXO=A zo0AF00S(<`d{U*gCduw{wz`~2Tzsh@$5vHKy3j%MiJhN1i_O-|v0?*e z^nF6Q=oT`(0aI}WMGz9Ha|2@C*#>D}S@M@|5Jbty4<+R2FphJGgk8}LuwNmFauYCJ=RVsX_hoqH!ghFMLmEU1vLenbg5H_W#F!k+8Tbxwx zk=bGMt$b>r?fcWLn&f0wO+GSzRZ^}A;?VbLE%ru)585t?ZZDNf$nuEcnEFs2lu?f{ zi_gi@eBDF@!a+aoi&jY1K5veL;aqyi>i0+EtyB>mej$&kF{*<>;I*$r8&eEN-CJ@+ zze`pCA}PCc^N5f`-3tK8=-q%NP4@oMM7zUEtz1zx_5o!5@>`+`Mp~S&t%J;ftrT#+YAyett5UyhW(9yiOTa9RKPtZR>i_@% literal 0 HcmV?d00001 diff --git a/doc/ratseries/slides/slide4.log b/doc/ratseries/slides/slide4.log new file mode 100644 index 0000000..35810d7 --- /dev/null +++ b/doc/ratseries/slides/slide4.log @@ -0,0 +1,20 @@ +This is TeX, Version 3.14159 (C version 6.1) (format=tex 96.5.7) 16 JUL 1997 22:08 +**slide4.tex +(slide4.tex +Hyphenation patterns for english, german, francais, loaded. + +Underfull \hbox (badness 10000) in paragraph at lines 15--18 + + +\hbox(0.0+0.0)x312.84833 +.\glue(\rightskip) 0.0 + + +Underfull \hbox (badness 10000) in paragraph at lines 19--21 + + +\hbox(0.0+0.0)x312.84833 +.\glue(\rightskip) 0.0 + +[1] ) +Output written on slide4.dvi (1 page, 1332 bytes). diff --git a/doc/ratseries/slides/slide4.ps b/doc/ratseries/slides/slide4.ps new file mode 100644 index 0000000..d3d3fc7 --- /dev/null +++ b/doc/ratseries/slides/slide4.ps @@ -0,0 +1,450 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: slide4.dvi +%%Pages: 1 +%%PageOrder: Ascend +%%BoundingBox: 0 0 596 842 +%%DocumentPaperSizes: a4 +%%EndComments +%DVIPSCommandLine: dvips -Pljfour -o slide4.ps slide4.dvi +%DVIPSParameters: dpi=600, compressed, comments removed +%DVIPSSource: TeX output 1997.07.16:2208 +%%BeginProcSet: texc.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]/id ch-image N /rw ch-width 7 add 8 idiv string N /rc 0 N /gp 0 N +/cp 0 N{rc 0 ne{rc 1 sub /rc X rw}{G}ifelse}imagemask restore}B /G{{id +gp get /gp gp 1 add N dup 18 mod S 18 idiv pl S get exec}loop}B /adv{cp +add /cp X}B /chg{rw cp id gp 4 index getinterval putinterval dup gp add +/gp X adv}B /nd{/cp 0 N rw exit}B /lsh{rw cp 2 copy get dup 0 eq{pop 1}{ +dup 255 eq{pop 254}{dup dup add 255 and S 1 and or}ifelse}ifelse put 1 +adv}B /rsh{rw cp 2 copy get dup 0 eq{pop 128}{dup 255 eq{pop 127}{dup 2 +idiv S 128 and or}ifelse}ifelse put 1 adv}B /clr{rw cp 2 index string +putinterval adv}B /set{rw cp fillstr 0 4 index getinterval putinterval +adv}B /fillstr 18 string 0 1 17{2 copy 255 put pop}for N /pl[{adv 1 chg} +{adv 1 chg nd}{1 add chg}{1 add chg nd}{adv lsh}{adv lsh nd}{adv rsh}{ +adv rsh nd}{1 add adv}{/rc X nd}{1 add set}{1 add clr}{adv 2 chg}{adv 2 +chg nd}{pop nd}]dup{bind pop}forall N /D{/cc X dup type /stringtype ne{] +}if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +TeXDict begin 39158280 55380996 1728 600 600 (slide4.dvi) +@start /Fa 1 2 df1 D E /Fb 4 62 df48 +D50 +D<167CA216FC1501A215031507150FA2151F153FA2157B15F3140115E3EC03C3EC0783A2 +EC0F03141E143E143C147814F0130114E0EB03C0EB0780A2EB0F00131E133E133C5B5BA2 +485A485A12075B48C7FC121EA25A5A12F8B9FCA4C83807FC00ACED1FFF023FB6FCA43044 +7CC339>52 D<007FBBFCBC1280A36C1A00CFFCB3007FBBFCBC1280A36C1A00491D79A758 +>61 D E /Fc 2 121 df<017EEC1FF048B46CEBFFFE48D9E0036D7E3C0787F00FE03FC0 +3C0F03F81F001FE0DAFC3C130F001E4A800101491307003CEBFDE049B44880007C5C1278 +92C7FC4948140F00F05F5C00005B010F151F605CA2011F153F605C177F013F5EA24A14FF +95C7FC017F4A147C4D13785C160301FF4B13F819F091C7140105F813E048EF03C0180749 +EE0F80F01F00933801FC3E49913800FFFCEF3FF0D800F0ED0FC03E2D7BAB47>110 +D120 D E /Fd 7 89 df[<18FC17011703EF07F8EF0FF0EF1FE0EF3FC0EF7F80EFFF +004C5A4C5A4C5AA24C5A4C5A4C5A4C5A16FF94C7FC4B5A15035E4B5A150F4B5A5E153F4B +5AA24B5A93C8FC5C4A5AA24A5AA24A5AA24A5AA24A5AA2147F5D14FF5D5BA24990C9FCA2 +5C1307A2495AA3495AA3495AA3495AA313FF5CA35A5CA25AA291CAFCA35AA25BA2120FA3 +5BA2121FA55BA2123FA65B127FAB5B12FFB3AF127F7FAB123F7FA6121FA27FA5120FA27F +A31207A27FA27EA380A27EA2807EA380137FA36D7EA36D7EA36D7EA36D7EA2130380A26D +7FA27F81147F81143FA26E7EA26E7EA26E7EA26E7EA26E7E80826F7EA26F7E151F826F7E +15076F7E8215016F7E83167F707E707E707E707EA2707E707E707EEF7F80EF3FC0EF1FE0 +EF0FF0EF07F8EF03FC17011700>54 257 102 133 86 16 D[<127C12FE127F7F6C7E6C +7E6C7E6C7E6C7E6C7E6C7E6D7EA26D7E6D7E6D7E6D7E8013036D7E807F6E7E816E7E141F +816E7EA26E7E1403816E7EA26E7FA26F7EA26F7EA26F7EA282150F82150782A26F7EA281 +83A26F7FA3707EA3707EA3707EA383160FA3831607A283A282A31880A282A218C0A382A2 +18E0A5177FA218F0A6173F18F8AB171F18FCB3AF18F8173FAB18F0177FA618E0A217FFA5 +18C0A25EA31880A25EA21800A35EA25FA2160F5FA3161F5FA34C5AA34C5AA34C5AA34B5B +A294C7FC5DA24B5AA25E150F5E151F5EA24B5AA24B5AA24B5AA24A90C8FCA24A5A5D1407 +4A5AA24A5A5D143F4A5A5D4AC9FC5B5C495A13075C495A495A495A495AA249CAFC485A48 +5A485A485A485A485A485A90CBFC12FE127C>54 257 123 133 86 +I[<1AFC19011903F107F0190FF11FE0F13FC0F17F80F1FF004E5A4E5A4E5A4E5A4E5A18 +3F614E5A4EC7FC4D5A17034D5A604D5A171F4D5A604D5A17FF4C90C8FC5F16034C5AA24C +5A4C5AA24C5A167F5F4C5AA24B90C9FC5D5E15075E150F5E151F4B5AA24B5AA24B5AA24A +5BA34A90CAFCA24A5AA24A5AA2141F5DA2143F5D147F5DA214FF5DA25B5D5BA292CBFC5B +A3495AA35C131FA3495AA4495AA4495AA45A5CA35AA25CA35AA391CCFCA35AA35BA3121F +A55BA2123FA85B127FAD5B12FFB3B3A2127F7FAD123F7FA8121FA27FA5120FA37FA37EA3 +80A37EA380A27EA3807EA46D7EA46D7EA46D7EA3130F80A36D7EA37F81A27F817FA28114 +7FA281143F81141FA281140FA26E7EA26E7EA26E7FA36E7FA26F7EA26F7EA26F7E150F82 +150782150382816F7FA2707E83163F707EA2707E707EA2707E160183707F177F717E8471 +7E170F717E84717E1701717E727E727E85181F727E727E727E727E727EF17F80F13FC0F1 +1FE0F10FF01907F103FC19011900>70 344 98 133 106 I[<127C12FE127F6C7E7F6C7E +6C7E6C7E6C7E6C7E6C7E6D7E6D7E6D7E80130F6D7E6D7E6D7E806D7F147F6E7E816E7E14 +0F6E7E816E7E1401816E7FA26F7E6F7EA26F7E82150F6F7EA26F7E8281838183167F8370 +7EA2707EA2707EA2707EA3707EA2707FA2707FA284177FA284173F84171FA284170FA284 +170784A28385A3717FA38385A3727EA4727EA4727EA485180FA385A284A31A80A384A31A +C0A384A31AE0A584A21AF0A8197F1AF8AD193F1AFCB3B3A21AF8197FAD1AF019FFA81AE0 +A260A51AC0A360A31A80A360A31A00A360A261A3181F61A44E5AA44E5AA44E5AA3615FA3 +4D5BA396C7FC5FA260170F60A2171F60A2173F60177F60A217FF60A24C5BA24C90C8FCA2 +4C5AA34C5AA24C5AA24C5AA24C5A5F16FF5F5D94C9FC5D5E4B5AA24B5A151F5E4B5AA24B +5A4B5AA24A90CAFC5D14034A5A5D4A5A141F4A5A5D4A5A14FF4990CBFC5C495A495A495A +131F5C495A495A49CCFC485A485A485A485A485A485A5B48CDFC12FE127C>70 +344 123 133 106 I[ +45 344 92 133 84 24 D[45 344 126 133 84 I<007FC5B512F8C5B67EA3A181A2A1816C02C0D0FC6C6EE3 +000F836C6EF6001F23006C6E0E0F816C6E2000A1011F806C6E21076C6E0F00806C6F213F +A1140F6D6E0F037F6D6E8D6D6E7B6C7EA1153F6D6EFA0FFE6D6E2207A115036D6E7C7E6D +6E7C7E6D6FFA3F80A26E6EFA1FC06E6E220F6E6E2207A1EE03E06E806E6EFA01F0A11600 +6E6E23F86E6E23786E81A1173C6F6E22006F806F80A26F806F80A26F806F806F81A27080 +70807080A270807080A2708070807081A2718071807180A271807180A2718071807181A2 +728072807280A272807280A2728072807281A2738073807380A273807380858873807381 +A2748074807480A27480868665745C745CA2755B7590D2FC755A6464515A1B7F515A6450 +5B5090D3FC505A1A0F505A505A63505A505A4F5B614F90D4FC624F5A4F5A4F5A197F4F5A +4E5B624E90D5FC4E5A4E5A181F4E5A614E5A4E5A4D5B5F4D90D6FC4D5A604D5A4D5A4D5A +17FF4C5B604C90D7FC4C48233C4C482378161F4C4823F84C4823F04D22014C5A4B49FA03 +E04B90D612074BA113C04B48230F4C231F4B48FB3F804B48237F4B4823FF03FF5913004A +496A4A496A93D6EA1FFE4A48233F4A48FBFFFC4A486A023F23074A48101F5B4B227F4A48 +57B5FC49490F0F5C4990D5127F491003B65A4948213F49480E0FB7FC4A0D07B85A49480C +7FB9FC49C5B5FC90C5B65A5A5AA193C7FC5A48A15C5A5A48A15CC5B6FCA26CA15CBEC978 +7FCF>88 D E /Fe 3 113 df<007FBA12E0BB12F0A36C19E04405759B5A>0 +D49 D<1C0E1C1FA21C3F1C3E1C +7E1C7C1CFCF301F8A2F303F01CE01B071CC01B0F1C801B1F1C00631B7EA263631A01631A +03631A07631A0F631A1F50C7FCA21A7E1A7C1AFC6219016219036219074F5AA24F5A97C8 +FC61193E010E177E011E177C017F17FC495F00036D15014860001F6D1503D83E7F4C5A00 +7C7FD8F03F4C5A00E06D5ED8001F161F6E93C9FC010F5E6E153E0107167E6E157C010316 +FC6E4A5A7F6F495A6D5E6F1307027F5D6F130F6E6C5C171F6E6C91CAFC020F5C6F133E02 +07147E6F5B14036F485A6E5C16836E5C16C7037F5B16EF033F5B16FF6F90CBFCA26F5A5E +15075E15035E15015E586577845E>112 D E /Ff 8 121 df13 +D<92B600C04BB612FE4A6F4B15FFA27219FEA291C7001FDD0007140004076D040013F84C +F17FE072EF3F80057F96C7FC173F041F6D173EA293261E1FFF173CA2DC3E0F187C731678 +EE3C0785047C19F8716D5E16788304F86E1501664C6C7FA20301027F1603735E5E727E03 +031907726C5E5E84030770140F9BC8FC4C6D7FA2030F6E5E74141E93C7FC727F4B193E72 +163C031E82197F033E70147C1D78033C6F7EA2037C031F15F8745C1578737F03F8180173 +5D4B17C0A2020170EBE003654B811BF0020370140709F85B5DF27FFC0207190F083F91C9 +FC4B17FEA2020F716C5A1C1E92CA7E1C9E4A19BE7413FC141E86143E745B143CA2027C83 +640278187F14F8A20101735A497E0107191FEB1FFF48B500E0715A007FECFF80B77E4C16 +07641B0378627AE173>78 DI101 D<4EB4FC060713C0061F13F09538 +3F83F89538FF007C4D48133C943903FC01FEF0F8030507EB07FF050F5B4E5A171FF13FFE +173F18E01AFC057FEB1FF8F10FF0F107E04D48C7FCA54C5BA45EA295C8FCA45E5FA4160F +4AB712FCA25CA26E5E91C7D81FF8C8FCA5163F5FA4167F5FA416FF5FA45DA25FA45D94C9 +FCA45D5EA4150F5EA5151F5EA4153F5EA44B5AA45E15FFA35EA25CA293CAFCA25C5DEA07 +E0D80FF05BEA1FF8383FFC07007F5CA25D38FFF80F5D49485A13E06C48485A018090CBFC +383C007E003E5B381FC1F86CB45A000313C0C690CCFC488479E546>II110 +D<4AB4EC03FE020F01E090380FFFC0023F01F8013F13E091267F03FC90387E07F89126FC +00FE9038F800FCD903F090397F01F001D907C0913983C007FE4948D93FC7130F91C79038 +CF801F011E91381FEF004903FF133F017C5D1378495D000119FC494BEB1FF8000319F049 +023FEC07C000074C90C7FC5BA2167F000F5E6CC8FCC9FC16FF5FA35D5FA35D94C9FCA35D +5EA3150FF101E05EA2031F15031AC05ED807E01707486C013F1680486C170F003F190048 +6C017F5D191E484801FF5D197CDA01F75D01F001E74A5A9027E003C3FC495A277FC007C1 +4A5A9027800F81FE495A283E001F00FF013FC7FC261FC0FE90383F81FE260FFFF890381F +FFF8000349010713E026007FC0010190C8FC47427CBF52>120 D +E /Fg 22 118 df33 D40 D<126012F012787E123E7E6C7E6C7E6C7E6C7E7F6C7E137E +133E133F6D7E80130F6D7EA26D7E80130180130080A2147FA26E7EA281141FA281140FA2 +81A2140781A36E7EA4811401A581A280A61680B3A41600A65CA25DA514035DA44A5AA35D +140FA25DA2141F5DA2143F5DA24AC7FCA214FEA25C13015C13035C495AA2495A131F5C49 +C8FC133E137E5B485A5B485A485A485A48C9FC123E123C5A5A1260219078EB38>I43 +D46 D<153C157C15FC14011407141F147FEB03FF137FB6FCA2149FEBFC1F1380C7FCB3B3 +B3B34A7EA249B512C0007FB8FCA5305F74DE48>49 D<913807FF80027F13F849B6FC0107 +15C04915F090263FF80713FC90267FC0007F01FEC7EA3FFF4848020F7FD803F06E7F4848 +6E7F496E7F000F8348488090C96C7E5A003E707E127E007C83D87FE0817F487E6D17807F +83A56C5AA26C485D6C5AD803801700CAFCA25F60A24D5AA26017FF604C5BA24C5B4C5B95 +C7FC4C5A4C5A5F4C5A4C5A5F4C5A4B90C8FC4B5A4B5A4B5A5E4B5A4B5A4BC9FC15FE4A5A +4A5A4A5A4A5A4A5A4BEC07804AC8FC147E4AED0F00495A495AEB07C0495A49C95A013E16 +1E133C49163E5B484816FE48B8FC5A485F5A5A5AB9FCA260A3395F79DE48>I52 +D58 +D<007FBD12FCBE12FEA4003F1CFCD1FCB3A4003FBD12FCBE12FEA46C1CFC5F2278B470> +61 D67 D80 D<001FBD12C0A59126F0000349C77E4890C801F8020713E001F81900491A7F01C01A +1F491A0FA290C91707A2003E1B03A2003C1B01007C1CF0A400781B00A7481C78A5CA1800 +B3B3B3A24C7F4C7F041FEBFFC0021FB912C0A55D617BE068>84 D101 D103 D<14F8EA07FFB5FCA51201EA007F133F131FB3A8EE0FFE93387FFFC04BB512F0 +923907F81FFC92390FC007FE92391F0001FF153C4B6D7F4B81DAF9E0147FDAFBC0815D14 +FF92C8123F855CA25CA45CB3B2496C4B7E90B5913801FFFEB748B612FEA547647BE350> +I<14F8EA07FFB5FCA51201EA007F133F131FB3B3B3B3AB497E90B5FCB7FCA520647CE327 +>108 D110 +DI115 D<143CA7147CA514FCA31301A21303A21307A213 +0F131F133F137F13FF000390B612C0120FB8FCA326000FFCC8FCB3AD17F0AE010714016E +14E0A3010314036E14C07F6D903880078091387FC00F91393FE01F0091381FF87E6EB45A +02035B9138003FE02C5A7DD738>I<02F8ED01F0D807FFED0FFFB54AB5FCA50001ED0003 +D8007F1500013F167F011F163FB3B2187FA418FFA2130F5FA26E5C0107923807BFF8F03F +FC6D6C020F13FF0101031E14FE6D6C147CDA7FC013F891393FF807F0020FB512C0020302 +8014C09128003FFC003EC7FC47427BBF50>I E /Fh 16 118 df[<49B4FC011F13E0017F +13F890B512FE00038048818248814881A248815A8282B7FCA282A31780A417C0A27EA37E +7EA27E7EA27EC6ECFE7F6D13FC011F13F00101EB00FF90C8FC1780A45DA21700A25DA25E +1507A25E150FA24B5AA24B5AA2157F5E15FF5E5C4A5B93C7FC5C4A5A141F5D4A5A4A5A14 +FF495B495B495B5B4990C8FC495A495A495A5C6D5A5C6D5A011EC9FC>42 +87 113 299 69 39 D[<51B47E517F517F517FA2517FA2517FA3517FA398B6FCA35081A3 +5081A35081A35081A25081A35081A35081A397B8FCA34F83A34F83A34F83A24F83A34F83 +A21B3F4F83A2507E077F83A2507E07FF83A2507E4E85871AF04E85874E01E083A2874E49 +83A2507F4E85A297C77E4E85A24F80067F85A24F8006FF85884D4985A2884D4985A2884D +4985A24F804D87A24F814D87A296C97E4D87A24E82057F87894D4886A2894C4987A2894C +4987A24E824C89A24E824C90BD7EA34C89A34C89A24C89A393C0FC05FCCB120F4D844B8B +A24D844B8BA24D844B8BA24D844B8B8B5F4B8B8B4B90CD82A28B4B488AA24C8603FF8BA2 +4C864A8DA24C864A8DA24C86020F01F88B0103B600F085B900FE041FBCFCAB01F0C8007F +4FC91201>168 173 119 300 187 65 D[<982607FFFEEF01F80807B600F8160397B8EE +0FFC070F05E0151F077F05FC153F0603BA157F061F07C014FF067F07F05B0503BB00FC5B +050F745B053F9738FF801F94BD6C5A4C9426F0003F6E5A04074CC7000302F8B5FC041F04 +E0DA007F13FD4C93C9000F90B6FC4C03FC16034BB700E0824B0480707E4B93CB7E4B03FC +180F4B4B84037F03E08492B748844A4C844A93CD7E4E864A4B864A4B864A5D4A4B864A4B +866091B7874993CFFCA2494B885B4D885B4D885B494B88A2495D8E90B7FC5F8E5AA2484C +88A35A94D1FCA25AA348227F5EA35AFB3FF8A2A0C7FCA25A5EA7B7FCB3A47EA7827EA56C +FA1FF8A2FB3FFC827EA37EA2836C227FA2A112F86C82A26C22FFA2711EF07F6A6D81A112 +E06D6F647F715213C07F715213807F6D6F64A112006D70636E6F64585A6E6F1BFF6E6F50 +5B6E816E6F505B6E6F505B72505B6E70616E704F5B6F6F4F90C7FC031F03F84E485A6F6F +4E5B6F03FF606F04C0051F5B6F04F0057F5B6F6C03FC4CB512C07003FF04075C7004E003 +1F91C8FC040704FE92B55A0401DCFFF8011F5C7094B812F0053F63050F1B80050398C9FC +DD007F19FC061F19F0060319C0DE007F4DCAFC070F17F007001780080703F8CBFCE00007 +91CCFC>150 176 114 300 179 67 D[147 +169 120 296 163 69 D<0407B57E0303B7FC033F16E04AB812FE020F717E023F18F091 +BA12FC49850107737E499126FE000F81490280010115F0706D6C80496E6E8049050F8070 +6E8090B66C6E818589486F6E81A274808986A28986896C5DA36D4A6F806D5CA26D5C6D5C +6D91C9FC010113FC9038003FE091CBFCA897B7FC060FB8FC0507B9FC94BAFC160F93BBFC +1507153F92B812CF0207EEE00F021FEDFE00027F15E091B71280010303FCC7FC4915F049 +15C0495D017F4AC8FC5E90B65A485D485D485DA2485D4892C9FCA25A5D5A5DA3B6FC5DA4 +62A462816C61A297B7FC6C80616C6E4B5A0707826C6F4A48816C6F4A4815F0073F16FE6C +6F9126FFF07FECFFFE6C03F84901E0826C6F010F01C017806D9126FF807F497E011F92B6 +12006D4D7F01034D7F01004D1303023F04E07F020704806D7E02004BC8000F1500030F02 +F003015CDB007F90CEFC717179EF79>97 D<943807FFFE94B612F8040FEDFF80047F16F0 +0303B812FC030F17FF033F18C04B844ABA12F80207854ADBC007804A4AC7FC4A02F84980 +4A4A178091B600C05B494B4915C04992C7FC495C494D15E0495C5E5B5B5E90B6FC485DA2 +487215C05E5A73158048721500A24C6E5C48735B745B080F13E048070190C7FC97C9FCA2 +93CDFC5AA6B7FCB37EA5827EA47EA2827EF41FF8A26C6FEF3FFCA26C1B7F826C1CF81CFF +6C815113F06D806D4F13E0826D4F13C06D6E4C13806D6F5D6D6F4B1300714B5A6D6FEC01 +FF6D03FC4A5B6E02FF020F5B021F03C0013F5B6EDBF803B55A6E92B75A0201616E4EC7FC +033F5F030F17F0030317C0DB007F93C8FC040F15F8040015C0050701F8C9FC5E7178EF6E +>99 D<943803FFFC94B612F0040715FE043FEDFFC04BB812F0030717FC031F17FF037F18 +C04ABA7E4ADBC03F14F8020F9126FE0007804A02F80101804A4A6D6C7F4A02C06E8091B6 +486E804992C86C80494A81497280494A84494A814972805E49737F5E90B68548864C1980 +5A87481DC0A25E487414E0A25AA21EF0A24892CA7EA35AA21EF8A4B7FCA393BBFCA61EF0 +1EE093CEFCA77EA67EA2827EA47EF51FE06C6FF03FF0F57FF8A27E7018FF7E5213F06C81 +6D5013E0826D5013C06D6E5F704D13806D626D6E4D13006D6F93B5FC6D6F4B5B6D6F4B5B +6E02F8030F5B6E6E033F5B6E02FF92B55A6E03C001075C020303FC017F5C6E92B748C7FC +6E6C60031F606F18E0030118806F6C4CC8FC040F16F0040116C0DC001F02FCC9FCDD007F +1380657179EF74>101 D[<4AB4FC020F13E0023F13F891B512FE49804981498149814981 +A24981A24981A390B77EA96D5DA36D5DA26D5DA26D5D6D5D6D5D6D92C8FC6D5C023F13F8 +020F13E0020190C9FC91CBFCB3A5EE7FF0010FB6FC007FB7FCACEA000F13017FA280B3B3 +B3B3A9BA12E0AB49C81203>59 173 122 300 68 105 D[61 172 122 +299 68 108 D<922601FFC0ED7FFF013FB60307B512F8B8033FECFF804FB712E0070716 +F8071F16FE4F8296B97E4E844E0200814E01F06D804E01C07F4E90C76C80DE3FFC83D800 +1F4C48800101DCFFE0836D5F05C1496E806E02C390C8FC60DDC7FC85EFCFF86005DF8260 +05FF866060A395C9FCA25FA35FA55FB3B3B3A5BAD8FC03BA12E0AB49C8000104F0C8120F +836F7AEE8A>110 D<943803FFFE057FEBFFF00407B7FC043F16E04BB812FC030717FF03 +1F18C0037F18F092BA7E0203DBC01F14FE4A9126FC0001804A02F06D6C80023F4A6E14E0 +4A0280020F8091B6C86C80494A6F80494A6F80494A6F80A2494A7080494A70804988A249 +4A708090B686A2484B7080A24889A24889A2481E80A34892CA6C15C0A4481EE0A4481EF0 +A6B71BF8B16C1EF0A66C1EE0A46C6F4C15C0A46C1E80A26C1E00A26C65705E6C65A26C65 +705E6D64705E6D646D6E93B65A6D646D6E4B92C7FC705D6D6E4B5C6D6F4A5C6D03E0023F +5C023F6E4A14E06E02FE0103B65A6E9126FFC01F5D6E92B8C8FC020119FC6E6C18F06F60 +030F1880030105FCC9FC6F6C16F0040F1680040003F8CAFC050349CBFC6D7179EF7C>I< +DC7FF091381FFFC0011FB60203B512FEB8021FECFFE096B712FC060716FF061F17C0067F +17F095B912FC05F38405F7727E94B6D8C01F819626FC00078107E001018107806D81D800 +074CC86C8001004C6F8006F06F806E4B6F814E6F816095C96C814D864D824D867681A277 +80A28C892180A37715C0A321E089A321F0A58921F8B321F0A265A421E0A36521C0A32180 +65A221006568A29AB65AA2525D6883525D7162715E724B5D7296C7FC724B5C724B5C724B +5C7292B65A06FF02035D07C0495D07F0011F5D07FF90B648C8FC97B75A05F918F005F818 +C0063F94C9FC060F16FC060316E0060093CAFC071F14F0070049CBFC97CDFCB3B1BA12FC +AB49C812017D9F7CEE8A>I<4BB46C903807FF80013FB6023F13FCB849B67E4E15E0060F +15F84E15FE4E814E168095B812C00581D9FC0F14E0DFF01F14F0058313C00587D9003F14 +F84E4914FCD8000FED8FFC01015E6DDB9FF090B612FEA26EECBFE0A26017FF60A295C7FC +7414FCA34D6E14F87414F0A24D6E14E07414C07414800800EBFE00F31FF04D92C8FCA95F +B3B3B2BB7EAB49C97E5F6F7CEE6A>114 D<4BB5EC0FC0037F02F8133F0207B7EBFFE002 +3F16C391BAFC13035B131F49EC00034901F0EB003F90B50080140F4849C812034849814A +8148498248498285484982A248845C5A85A4B56C82A380A2806E705B14FE6E94C8FC15C0 +15F015FE6CECFFE016FF17F8EFFFC06C17F818FF6C18E019F86C18FE856C19C06C856C85 +1AFC6C856D847F010F856D856D8513006E84021F841403DA007F83150F0300831607EE00 +3F050181EF003F18077215801800D83FE083007F181F486C83A2856D83A2857FA285A27F +1C007FA280636E5EA26E6061806E606E4C5B6E5E6E4C5B6F4B5B03E05D03F84AB55A03FE +020F91C7FCDBFFE090B55A93B75A62023F17E0496C5FD9F80794C8FCD9F00116F89026C0 +003F15E06C4801074AC9FC007EC86C13C0517178EF62>I[<923801FFE0AA5DA75DA45DA4 +5DA35DA25DA392B5FCA25C5CA25C5C5CA25C5C91B6FC13035B011F92B71280137F0007BB +FCBCFCA9D8000103E0C9FCB3B3B2F27FF8B3A31AFF6D6F15F0A36E5E1BE0836E4C13C083 +6E5E7115806E6E4913006EED803F6E9238E07FFE6E92B55A806F5E6F5E6F5E03075E0301 +93C7FCDB003F5C040714F0DC001F1380>77 158 123 284 97 II +E end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: a4 +%%BeginPaperSize: a4 +a4 +%%EndPaperSize + +%%EndSetup +%%Page: 1 1 +1 0 bop 510 1014 a Fh(Application)84 b(to)f(Euler's)f(Constan)-7 +b(t)0 1657 y Fg(Put)334 b Ff(f)15 b Fg(\()p Ff(x)p Fg(\))40 +b(:=)1129 1478 y Fe(1)1083 1521 y Fd(X)1078 1825 y Fc(n)p +Fb(=0)1351 1560 y Ff(x)1433 1508 y Fc(n)p 1336 1624 191 +6 v 1336 1770 a Ff(n)p Fg(!)1462 1706 y Fb(2)520 2090 +y Ff(g)5 b Fg(\()p Ff(x)p Fg(\))40 b(:=)1069 1911 y Fe(1)1023 +1954 y Fd(X)1018 2258 y Fc(n)p Fb(=0)1258 1888 y Fd(\022)1381 +1993 y Fg(1)p 1381 2057 72 6 v 1381 2189 a(1)1502 2090 +y(+)32 b Fa(\001)24 b(\001)g(\001)31 b Fg(+)2013 1993 +y(1)p 2005 2057 87 6 v 2005 2189 a Ff(n)2109 1888 y Fd(\023)2271 +1993 y Ff(x)2353 1941 y Fc(n)p 2256 2057 191 6 v 2256 +2204 a Ff(n)p Fg(!)2381 2139 y Fb(2)0 2850 y Fg(Then)1411 +2753 y Ff(g)5 b Fg(\()p Ff(x)p Fg(\))p 1405 2817 280 +6 v 1405 2948 a Ff(f)15 b Fg(\()p Ff(x)p Fg(\))1741 2850 +y(=)1910 2753 y(1)p 1910 2817 72 6 v 1910 2948 a(2)2023 +2850 y(log)26 b Ff(x)32 b Fg(+)f Ff(\015)40 b Fg(+)32 +b Ff(O)2884 2691 y Fd(\020)2970 2850 y Ff(e)3037 2791 +y Fe(\000)p Fb(4)3184 2718 y Fe(p)p 3278 2718 66 5 v +73 x Fc(x)3350 2691 y Fd(\021)3435 2850 y Fg(.)0 3618 +y(Cho)t(ose)46 b Ff(x)40 b Fg(=)772 3416 y Fd(\030)873 +3521 y Ff(N)g Fg(log)26 b(2)p 873 3585 436 6 v 1055 3716 +a(4)1326 3416 y Fd(\031)1410 3446 y Fb(2)1474 3618 y +Fg(.)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/ratseries/slides/slide4.tex b/doc/ratseries/slides/slide4.tex new file mode 100644 index 0000000..79d0b8c --- /dev/null +++ b/doc/ratseries/slides/slide4.tex @@ -0,0 +1,28 @@ +\magnification=\magstep3 +\hsize=19truecm +\vsize=19truecm +\nopagenumbers +\parindent=0mm +\font\eins=cmb10 scaled \magstep 3 +\font\zwei=cmr12 +\font\mini=cmr7 +\def\frac#1#2{{{#1} \over {#2}}} +\hbox{} +\vfill + +\centerline{\eins Application to Euler's Constant} +\bigskip\bigskip +Put +\quad\quad{$\displaystyle f(x) := {\sum\limits_{n=0}^{\infty} \frac{x^n}{{n!}^2}}$}\hfill\break +\hphantom{Put}\quad\quad{$\displaystyle g(x) := {\sum\limits_{n=0}^{\infty} \left( \frac{1}{1} + \cdots + \frac{1}{n} \right) \frac{x^n}{{n!}^2}}$}\hfill\break +\bigskip\bigskip +Then +\hfill{$\displaystyle \frac{g(x)}{f(x)} = \frac{1}{2} \log x + \gamma + O \left( e^{-4 \sqrt{x}} \right) $.}\hfill\break +\bigskip\bigskip +Choose $\displaystyle {x = {\left\lceil \frac{N \log 2}{4} \right\rceil}^2}$. + +\vfill +\hbox{} +\eject + +\end diff --git a/doc/ratseries/slides/slide5.dvi b/doc/ratseries/slides/slide5.dvi new file mode 100644 index 0000000000000000000000000000000000000000..15891e8e964309bf26a6546d13433f6992d624a2 GIT binary patch literal 1116 zcmah|U1-x#6uw#44Y#rBL^sjF6q&80CE3t9r-M;sqJmYNh@zOKw{2X0y4<9;FYdt? zQ4UardS!SxmEPt#FD&1x38+X=Qw82*8P{dL zEEsbdb~5>z+4iY!T-tN(<>t4mlq57FvCRC5H4$t1&zu~?Nkvp-MG|=YKYs1?7J@$? z$&*a`+>tO&TkhB_Q4oWw`J{>1a#-;+qzPXrpRa5P0#3#bdZa6<{!8i@N95)G^|}UC z31KCUqahXYx{8D{B1UjbhcXWlZTZoX5Qbsw#El{~?v~aua6$$3#BLY1T!r2I%-n-qVfixS80 D E /Fb 1 111 df<017EEC1FF048B46CEBFFFE48D9E0 +036D7E3C0787F00FE03FC03C0F03F81F001FE0DAFC3C130F001E4A800101491307003CEB +FDE049B44880007C5C127892C7FC4948140F00F05F5C00005B010F151F605CA2011F153F +605C177F013F5EA24A14FF95C7FC017F4A147C4D13785C160301FF4B13F819F091C71401 +05F813E048EF03C0180749EE0F80F01F00933801FC3E49913800FFFCEF3FF0D800F0ED0F +C03E2D7BAB47>110 D E /Fc 2 82 df<94261FFFC0EC03800407B500FCEC07C0043FEC +FF804BB712E0030716FC033FD9FE0101FF130F92B526F0001FEBF01F4A02C0010390B5FC +02076DC8FC91260FFCFE153F91263FE1FC814A4848030713F79126FF03F0923803FC0749 +484848ED00FE902703F80FC0167FD907F0F03F8749484848EE1FC7D91FC090CAEA0FE749 +4848EF07F7DA003E1703017E017EEF01FF49017C83A2484801FC187F484849183FA22607 +E001191F01C05B000F1B0FEB80034B1807121F1300F4038048010796C7FC003E5CA2127E +127CA3140F5D12FC5AB07E127C811407A3127E123EA2123F6C8014031380120F81EBC001 +120713E0D803F07F02001A306C6C6D19786C6C017C19FC1C01017E017E18036D013EF007 +F8DA803FF00FF06D6C6C6CEF3FE0D90FE0F17FC06D6C6C6CEFFF806D6C6C6C04031300D9 +01FE6D4C5A6D6C6C6CEE1FFC91267FC1FCEE7FF86E6CB4923801FFE091270FFC7FC0020F +5B912707FF3FF0027F90C7FC020190B590381FFFFE6E92B612F8033F17E0030717800301 +04FCC8FCDB003F15F0040792C9FCDC001F13E05E687BE441>67 D<94381FFFE00407B67E +043F15F04BB712FE0307707E033FD9FC0014F092B500E0011F13FC4A028001077F020749 +C700016D7E91260FFDFC6E487F91263FE3F892387F1FF04A484892383F8FF89126FF0FE0 +92381FC3FCD901FE4992380FC1FE902703F81F80923807E07FD907F090C900036D7E4948 +48716C7E90261FC03E04016D7E90263F807E716C7EDA007C04001303017E747E4901FC71 +6C7E4B177C48481B7E2603F001067E7F4B173ED807E0F31F80D9C003063F130F000F4A71 +14C001801B07A2001F1DE0D90007F180034B170F481DF0003E1C01A2007E1DF8007C1C00 +A2020F854B1707A200FC1DFC481D7CB06C1DFC007C1DF8A26F170F020761A2007E1C0100 +3E1DF0A2003F1C036C1DE06F171FD98003F10007000F1DC0A201C01B0F00076E4D1480D9 +E001063E131FD803F0F33F006F177E2601F800067C137E6C6C636F17FC017E017C4D485A +6D505ADA807E0401130790261FC03E4D485A90260FE03F0403495A6D6C6C4D485AD903F8 +6D030749C7FC902701FE0FC092380FC1FED900FF6D92381FC3FC91267FC7F092383F8FF8 +6E6C6C4B485A91260FFDFC9238FEFFC06EB46C4AB55A02016D6C010749C8FC6E02E0011F +5B033F01FC90B512F0030790B7128003014CC9FCDB003F15F0701580DC0FDF91CAFC9439 +C0001F80707E04036E7E716D7E706C80716D7E706C6D7E057F6D7E716C137F716CEB3FC0 +716CEB1FF0716CEB0FFCDD03FC903A07FF8001E071B4010190B512F0719038C0007FDE7F +F0131FDE1FFE010714E0952707FFE0001480060190B6EAFE00726C15F0071F15C0070302 +FCC7FCDF003F1380667F7BE44F>81 D E /Fd 7 121 df<1602160783160F94C8FCA8EF +1FFF94B512E07014F093380FF00193383FC00093387FF007DB01FDB512E0922603F07F13 +C0923A07E03FFE004B48C8FC4BC9FC157E5D4A5A4A5A4A5A5D4A5A141F4ACAFC147E5CA2 +495A495A13075C495A131F5C133F49CBFC137E13FE5B12015B1203A2485AA2485AA3485A +A3123F5BA3127F90CCFCA35AA55AA37EA67FA37FA26C7E7F7F6C7E7F6C6C7E14E06C13F8 +14FF6C14E06C14FC6CECFF806C15F0013F14FC6D14FF010715C00101816D6C80020F8002 +0180EC003F03077F1500EE3FFF160F828282A282A25FA35F16015F1438023C495A021F49 +5A91390FC00FC0913907F83F800201B5C8FC9138007FFCED0FF03C8379E43F>16 +D<023FB912E049BA12F04919F8130F5B5B4919F090BB12E0481AC04890288003C0007CC8 +FC3907FC000701F04A1378485AD81F80010F14F848C7FC003E92C7FC484A5C127800F816 +0148143E5AC8FC037E1303157C6015FCA24B13071401A34A5AA20207140FA25D140FA214 +1F4B80A2143F5D147FA214FF92C77F5BA3494881A213074A81130FA2011F6F7E5C133F5C +836D485D4A6E5A6D486E5A4D407CBD52>25 D<127812FE6C7E13E013F8EA3FFE380FFF80 +000313E0C613F8EB3FFE90380FFF80010313E0010013F8EC3FFF020F13C0020313F00200 +13FCED3FFF030F13C0030113F09238007FFCEE1FFF040713C0040113F09338007FFCEF1F +FF050713E0050113F89438007FFE95381FFF80060713E0060113F89538003FFE96380FFF +80070313E0070013F8F23FFE97380FFF80080313E0080013FCF33FFE1B0FA21B3FF3FFFC +080313E0080F138097383FFE00F2FFF8070313E0070F1380DF3FFEC7FC953801FFF80607 +13E0061F1380DE7FFEC8FC943801FFF8050713E0051F90C9FCEF7FFC933801FFF0040713 +C0041F90CAFCEE7FFC923801FFF0030F13C0033F90CBFCEDFFFC020313F0020F13C0023F +90CCFCECFFF8010313E0010F1380D93FFECDFCEBFFF8000313E0000F1380D83FFECEFCEA +FFF813E0138048CFFC1278575474CD70>62 D<4EB4FC060713C0061F13F095383F83F895 +38FF007C4D48133C943903FC01FEF0F8030507EB07FF050F5B4E5A171FF13FFE173F18E0 +1AFC057FEB1FF8F10FF0F107E04D48C7FCA54C5BA45EA295C8FCA45E5FA4160F4AB712FC +A25CA26E5E91C7D81FF8C8FCA5163F5FA4167F5FA416FF5FA45DA25FA45D94C9FCA45D5E +A4150F5EA5151F5EA4153F5EA44B5AA45E15FFA35EA25CA293CAFCA25C5DEA07E0D80FF0 +5BEA1FF8383FFC07007F5CA25D38FFF80F5D49485A13E06C48485A018090CBFC383C007E +003E5B381FC1F86CB45A000313C0C690CCFC488479E546>102 D107 D110 D<4AB4EC03FE020F01E090 +380FFFC0023F01F8013F13E091267F03FC90387E07F89126FC00FE9038F800FCD903F090 +397F01F001D907C0913983C007FE4948D93FC7130F91C79038CF801F011E91381FEF0049 +03FF133F017C5D1378495D000119FC494BEB1FF8000319F049023FEC07C000074C90C7FC +5BA2167F000F5E6CC8FCC9FC16FF5FA35D5FA35D94C9FCA35D5EA3150FF101E05EA2031F +15031AC05ED807E01707486C013F1680486C170F003F1900486C017F5D191E484801FF5D +197CDA01F75D01F001E74A5A9027E003C3FC495A277FC007C14A5A9027800F81FE495A28 +3E001F00FF013FC7FC261FC0FE90383F81FE260FFFF890381FFFF8000349010713E02600 +7FC0010190C8FC47427CBF52>120 D E /Fe 43 122 df0 +D39 DI< +126012F012787E123E7E6C7E6C7E6C7E6C7E7F6C7E137E133E133F6D7E80130F6D7EA26D +7E80130180130080A2147FA26E7EA281141FA281140FA281A2140781A36E7EA4811401A5 +81A280A61680B3A41600A65CA25DA514035DA44A5AA35D140FA25DA2141F5DA2143F5DA2 +4AC7FCA214FEA25C13015C13035C495AA2495A131F5C49C8FC133E137E5B485A5B485A48 +5A485A48C9FC123E123C5A5A1260219078EB38>I44 DII< +153C157C15FC14011407141F147FEB03FF137FB6FCA2149FEBFC1F1380C7FCB3B3B3B34A +7EA249B512C0007FB8FCA5305F74DE48>49 D<007FBD12FCBE12FEA4003F1CFCD1FCB3A4 +003FBD12FCBE12FEA46C1CFC5F2278B470>61 D67 D72 +D<027FB712F0A5DA0001ECF000DB003F13C0705B82B3B3B3ACEA0FF0487E487E487EB5FC +A495C7FC5EA2495D127F49143F01F05DD83FC04A5A90C8FC6C4B5A6C6C5D6C6C495BD803 +F0495B6C6C4990C8FCD800FEEB1FFC90397FE07FF8011FB512E0010391C9FC9038007FF0 +3C657AE14A>74 D76 D80 D82 D86 D<000FBA12FEA503E0C813FC02FC +C84813F802F05D48018017F091C94813E05B01F84C13C0495E1A80494C1300495E61494C +5AA290C9485B5F61001E4C5B5F61003E4C5BA24D90C7FC003C5E604D5A5E60C9485B5E60 +4C5BA24C5B5E95C8FC4C5A16FF5F4B5BA24B5B5D5F4B5B5D5F4B90C9FCA24B5A15FF5E4A +5B5C5E4A49150FA24A5B5C5E4A90C9FC5C4B161F4A5A49181E5D495BA2495B49183E5D49 +5B5B92CA127E495AA2494817FE5A4A1601484916034818074A160F4849161FF13FFC4849 +16FF48170391C9121F48480303B5FCBBFCA5486278E158>90 DI93 D97 D99 DIIII< +14F8EA07FFB5FCA51201EA007F133F131FB3A8EE0FFE93387FFFC04BB512F0923907F81F +FC92390FC007FE92391F0001FF153C4B6D7F4B81DAF9E0147FDAFBC0815D14FF92C8123F +855CA25CA45CB3B2496C4B7E90B5913801FFFEB748B612FEA547647BE350>I<131FEB7F +C0497E487FA2487FA56C5BA26C5B6D5A011FC7FC90C8FCB214F8EA03FF127FA51201EA00 +7F133F131FB3B3AB497EEBFFFEB612FEA51F617CE027>I<153EEDFF804A13C04A13E0A2 +4A13F0A56E13E0A26E13C06E1380ED3E0092C7FCB2ED03F0EC1FFF0103B5FCA5EB000314 +00157F153FB3B3B3ACEA1FC0486C14E0487E486C137FA216C0A2EDFF80A24914006C4848 +5AD83FC05B90380003F86C6C485A390FF01FE00003B55AC691C7FCEB1FF8247F86E02C> +I<14F8EA07FFB5FCA51201EA007F133F131FB3AA4CB612C0A5706CEBF800051F13804EC7 +FC18F818E0604D5A057EC8FC5F4C5A4C5A4C5A4C5A4C5A043EC9FC16FC4B5A4B5A4B7E15 +0F4B7E4B7E157F02F9B5FCDAFBF37FDAFFE17F15C103807F4B6C7E5C02F86D7E4A6D7EA2 +707E707E8284707F707FA2717E717EA2717E717EA2717E85717F4D7F496C82D9FFFE4A13 +FEB600FE017FEBFFF8A545647CE34C>I<14F8EA07FFB5FCA51201EA007F133F131FB3B3 +B3B3AB497E90B5FCB7FCA520647CE327>I +III<02F8EB3FF8D807FF49B57EB5010714E0 +92391FE01FF892397F0007FE03FCEB01FFDAF9F06D13C0C6D9FBE06E7E90263FFFC06E7E +6D496E7E92C86C7E4A8218074A824A6F1380A27213C01AE084A21AF0197F1AF8A4193F1A +FCACF17FF8A41AF019FFA21AE0601AC0A24E1380804E13006E4B5A616E4B5A6F4A5A6F5D +DAFBE0ECFFC0DAF9F0495BDAF8F84990C7FC037EEB0FFC92393FC07FF0030FB512C00303 +91C8FC9238007FF093CAFCB3497E90B5FCB7FCA5465C7CBF50>IIII<143CA7147CA514FCA31301A21303A21307A2130F131F13 +3F137F13FF000390B612C0120FB8FCA326000FFCC8FCB3AD17F0AE010714016E14E0A301 +0314036E14C07F6D903880078091387FC00F91393FE01F0091381FF87E6EB45A02035B91 +38003FE02C5A7DD738>I<02F8ED01F0D807FFED0FFFB54AB5FCA50001ED0003D8007F15 +00013F167F011F163FB3B2187FA418FFA2130F5FA26E5C0107923807BFF8F03FFC6D6C02 +0F13FF0101031E14FE6D6C147CDA7FC013F891393FF807F0020FB512C00203028014C091 +28003FFC003EC7FC47427BBF50>IIIII E /Ff 2 51 df<913803FF80021F13F091B512FE01036E7E4981 +011F15F04981498190B77E48824817804817C0A24817E0A24817F04817F8A34817FCA3B9 +12FEAC6C17FCA36C17F8A36C17F06C17E0A26C17C0A26C17806C17006C5E6D5D6D5D6D5D +010715C06D5D01004AC7FC021F13F002031380373878BF48>15 D<0407B612FC93B712FE +1507153F92B8FC020317FC4A01FCC9FC021F1380DA3FFCCAFCECFFE04913804990CBFCEB +07FC495AEB1FE0495A495A49CCFC5B485A485AA2485A5B120F5B121F5B123F90CDFCA25A +127EA312FE5AA3BB12FC1AFEA41AFC00FCCDFCA37E127EA3127F7EA27F121F7F120F7F12 +077F6C7EA26C7E6C7E7F6D7E6D7E6D7EEB0FF86D7E6DB4FC6D7F6D13E0EC3FFC6EB47E02 +0713FC6E90B712FC020017FE153F15071500040715FC475474CD60>50 +D E /Fg 14 117 df[<51B47E517F517F517FA2517FA2517FA3517FA398B6FCA35081A3 +5081A35081A35081A25081A35081A35081A397B8FCA34F83A34F83A34F83A24F83A34F83 +A21B3F4F83A2507E077F83A2507E07FF83A2507E4E85871AF04E85874E01E083A2874E49 +83A2507F4E85A297C77E4E85A24F80067F85A24F8006FF85884D4985A2884D4985A2884D +4985A24F804D87A24F814D87A296C97E4D87A24E82057F87894D4886A2894C4987A2894C +4987A24E824C89A24E824C90BD7EA34C89A34C89A24C89A393C0FC05FCCB120F4D844B8B +A24D844B8BA24D844B8BA24D844B8B8B5F4B8B8B4B90CD82A28B4B488AA24C8603FF8BA2 +4C864A8DA24C864A8DA24C86020F01F88B0103B600F085B900FE041FBCFCAB01F0C8007F +4FC91201>168 173 119 300 187 65 D[<0807B5FC4FB612FC073FEDFFE00603B812FE +061FEFFFC0067F18F00503BA12FE050F737E053F1AE094BC12F80403DC800F15FE4C03F8 +C781041F03C0021F15C04C92C800078193B600FC030115F84B03F06F6C804B4B7080030F +4B706E7E4B92CA0007814B4A71814B4A718192B64871814A4B72804A8B4A4B72804A4B72 +814E844A8C4A92CC6C814A8C91B6487381A2494B7381498D4D85498D4D86498E4D86498E +498E4D86498EA390B7487481A2488FA294CE7E488FA3488FA24C8748A11280A348A112C0 +A548A112E04C87A448A112F0A8B721F8B3A56CA112F0A770636CA112E0A66CA112C0A370 +636CA11280A46CA112007162A26C6BA26C6B7162A26C6B71626D6AA26D6A71626D6A7197 +B7FC6D6AA26D6F4F93C7FCA26D6F4F5D6D6971616D696E6F4E5DA26E6F4E5D6E6F4E5D6E +6F4E5D6E9DC8FC6E6F95B65A6E6F4D5D6E6F4D5D6F6E4D5D6F6F4C5D6F6F4C5D6F03F004 +7F5D6F6F93B7C9FC6F03FE03035D03006F4B15F87003C0021F5D041F03F891B712C07092 +26FF800F5E040393B848CAFC04001BF87162050F1A8005034FCBFC050019F8061F18C006 +034DCCFCDE003F16E007034BCDFCDF000791CEFC>157 176 114 +300 186 79 D<0407B57E0303B7FC033F16E04AB812FE020F717E023F18F091BA12FC49 +850107737E499126FE000F81490280010115F0706D6C80496E6E8049050F80706E8090B6 +6C6E818589486F6E81A274808986A28986896C5DA36D4A6F806D5CA26D5C6D5C6D91C9FC +010113FC9038003FE091CBFCA897B7FC060FB8FC0507B9FC94BAFC160F93BBFC1507153F +92B812CF0207EEE00F021FEDFE00027F15E091B71280010303FCC7FC4915F04915C0495D +017F4AC8FC5E90B65A485D485D485DA2485D4892C9FCA25A5D5A5DA3B6FC5DA462A46281 +6C61A297B7FC6C80616C6E4B5A0707826C6F4A48816C6F4A4815F0073F16FE6C6F9126FF +F07FECFFFE6C03F84901E0826C6F010F01C017806D9126FF807F497E011F92B612006D4D +7F01034D7F01004D1303023F04E07F020704806D7E02004BC8000F1500030F02F003015C +DB007F90CEFC717179EF79>97 D<943807FFFE94B612F8040FEDFF80047F16F00303B812 +FC030F17FF033F18C04B844ABA12F80207854ADBC007804A4AC7FC4A02F849804A4A1780 +91B600C05B494B4915C04992C7FC495C494D15E0495C5E5B5B5E90B6FC485DA2487215C0 +5E5A73158048721500A24C6E5C48735B745B080F13E048070190C7FC97C9FCA293CDFC5A +A6B7FCB37EA5827EA47EA2827EF41FF8A26C6FEF3FFCA26C1B7F826C1CF81CFF6C815113 +F06D806D4F13E0826D4F13C06D6E4C13806D6F5D6D6F4B1300714B5A6D6FEC01FF6D03FC +4A5B6E02FF020F5B021F03C0013F5B6EDBF803B55A6E92B75A0201616E4EC7FC033F5F03 +0F17F0030317C0DB007F93C8FC040F15F8040015C0050701F8C9FC5E7178EF6E>99 +D<943803FFFC94B612F0040715FE043FEDFFC04BB812F0030717FC031F17FF037F18C04A +BA7E4ADBC03F14F8020F9126FE0007804A02F80101804A4A6D6C7F4A02C06E8091B6486E +804992C86C80494A81497280494A84494A814972805E49737F5E90B68548864C19805A87 +481DC0A25E487414E0A25AA21EF0A24892CA7EA35AA21EF8A4B7FCA393BBFCA61EF01EE0 +93CEFCA77EA67EA2827EA47EF51FE06C6FF03FF0F57FF8A27E7018FF7E5213F06C816D50 +13E0826D5013C06D6E5F704D13806D626D6E4D13006D6F93B5FC6D6F4B5B6D6F4B5B6E02 +F8030F5B6E6E033F5B6E02FF92B55A6E03C001075C020303FC017F5C6E92B748C7FC6E6C +60031F606F18E0030118806F6C4CC8FC040F16F0040116C0DC001F02FCC9FCDD007F1380 +657179EF74>101 D[131 172 122 299 138 104 D[<4AB4FC020F13E0023F13F891B512FE49804981 +498149814981A24981A24981A390B77EA96D5DA36D5DA26D5DA26D5D6D5D6D5D6D92C8FC +6D5C023F13F8020F13E0020190C9FC91CBFCB3A5EE7FF0010FB6FC007FB7FCACEA000F13 +017FA280B3B3B3B3A9BA12E0AB49C81203>59 173 122 300 68 +I[ +61 172 122 299 68 108 D<922601FFC0ED7FFF013FB60307B512F8B8033FECFF804FB7 +12E0070716F8071F16FE4F8296B97E4E844E0200814E01F06D804E01C07F4E90C76C80DE +3FFC83D8001F4C48800101DCFFE0836D5F05C1496E806E02C390C8FC60DDC7FC85EFCFF8 +6005DF826005FF866060A395C9FCA25FA35FA55FB3B3B3A5BAD8FC03BA12E0AB49C80001 +04F0C8120F836F7AEE8A>110 D<943803FFFE057FEBFFF00407B7FC043F16E04BB812FC +030717FF031F18C0037F18F092BA7E0203DBC01F14FE4A9126FC0001804A02F06D6C8002 +3F4A6E14E04A0280020F8091B6C86C80494A6F80494A6F80494A6F80A2494A7080494A70 +804988A2494A708090B686A2484B7080A24889A24889A2481E80A34892CA6C15C0A4481E +E0A4481EF0A6B71BF8B16C1EF0A66C1EE0A46C6F4C15C0A46C1E80A26C1E00A26C65705E +6C65A26C65705E6D64705E6D646D6E93B65A6D646D6E4B92C7FC705D6D6E4B5C6D6F4A5C +6D03E0023F5C023F6E4A14E06E02FE0103B65A6E9126FFC01F5D6E92B8C8FC020119FC6E +6C18F06F60030F1880030105FCC9FC6F6C16F0040F1680040003F8CAFC050349CBFC6D71 +79EF7C>II<4BB46C903807FF80013FB6023F13FCB849B67E +4E15E0060F15F84E15FE4E814E168095B812C00581D9FC0F14E0DFF01F14F0058313C005 +87D9003F14F84E4914FCD8000FED8FFC01015E6DDB9FF090B612FEA26EECBFE0A26017FF +60A295C7FC7414FCA34D6E14F87414F0A24D6E14E07414C07414800800EBFE00F31FF04D +92C8FCA95FB3B3B2BB7EAB49C97E5F6F7CEE6A>114 D<4BB5EC0FC0037F02F8133F0207 +B7EBFFE0023F16C391BAFC13035B131F49EC00034901F0EB003F90B50080140F4849C812 +034849814A8148498248498285484982A248845C5A85A4B56C82A380A2806E705B14FE6E +94C8FC15C015F015FE6CECFFE016FF17F8EFFFC06C17F818FF6C18E019F86C18FE856C19 +C06C856C851AFC6C856D847F010F856D856D8513006E84021F841403DA007F83150F0300 +831607EE003F050181EF003F18077215801800D83FE083007F181F486C83A2856D83A285 +7FA285A27F1C007FA280636E5EA26E6061806E606E4C5B6E5E6E4C5B6F4B5B03E05D03F8 +4AB55A03FE020F91C7FCDBFFE090B55A93B75A62023F17E0496C5FD9F80794C8FCD9F001 +16F89026C0003F15E06C4801074AC9FC007EC86C13C0517178EF62>I[<923801FFE0AA5D +A75DA45DA45DA35DA25DA392B5FCA25C5CA25C5C5CA25C5C91B6FC13035B011F92B71280 +137F0007BBFCBCFCA9D8000103E0C9FCB3B3B2F27FF8B3A31AFF6D6F15F0A36E5E1BE083 +6E4C13C0836E5E7115806E6E4913006EED803F6E9238E07FFE6E92B55A806F5E6F5E6F5E +03075E030193C7FCDB003F5C040714F0DC001F1380>77 158 123 +284 97 I E end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: a4 +%%BeginPaperSize: a4 +a4 +%%EndPaperSize + +%%EndSetup +%%Page: 1 1 +1 0 bop 967 1025 a Fg(Other)82 b(Applications)-143 1541 +y Ff(\017)71 b Fe(exp,)47 b(sin,)h(cos,)e(log,)i(arctan,)f(etc.)-143 +1799 y Ff(\017)71 b Fd(\031)53 b Fe(\(Ch)l(udno)l(vsky's)44 +b(form)l(ula,)i(a)i(Raman)l(ujan)c(t)l(yp)t(e)i(series\))-143 +2058 y Ff(\017)71 b Fe(h)l(yp)t(ergeometric)45 b(functions)i(at)g +Fd(x)40 b Ff(2)f Fc(Q)-143 2316 y Ff(\017)71 b Fe(h)l(yp)t(ergeometric) +60 b(and)i(holonomic)g(functions)g(at)g Fd(x)j Ff(2)g +Fc(C)102 b Fe([J.)62 b(v)-8 b(an)62 b(der)0 2488 y(Ho)t(ev)l(en])-143 +2746 y Ff(\017)71 b Fe(\000\()p Fd(x)p Fe(\))47 b(at)g +Fd(x)40 b Ff(2)g Fc(Q)-143 3004 y Ff(\017)71 b Fe(Large)g(terms)f(of)i +(P-recursiv)l(e)f(sequences,)76 b(i.e.)c Fd(f)2853 3026 +y Fb(n)3003 3004 y Fe(\()p Fd(n)h Fe(large\))f(where)0 +3177 y Fd(f)15 b Fe(\()p Fd(x)p Fe(\))40 b(=)471 3069 +y Fa(P)646 3177 y Fd(f)716 3198 y Fb(n)794 3177 y Fd(x)876 +3125 y Fb(n)1002 3177 y Fe(is)48 b(holonomic,)-143 3435 +y Ff(\017)71 b Fd(\020)11 b Fe(\()p Fd(k)5 b Fe(\),)45 +b Fd(k)f(>)39 b Fe(1)46 b(o)t(dd)g(\(using)g(Cohen-Villegas-Zagier)f +(con)l(v)l(ergence)f(accel-)0 3607 y(eration\))p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/ratseries/slides/slide5.tex b/doc/ratseries/slides/slide5.tex new file mode 100644 index 0000000..9556066 --- /dev/null +++ b/doc/ratseries/slides/slide5.tex @@ -0,0 +1,38 @@ +\input amssym.def +\input amssym +\magnification=\magstep3 +\hsize=17truecm +\vsize=19truecm +\nopagenumbers +\parindent=0mm +\font\eins=cmb10 scaled \magstep 3 +\font\zwei=cmr12 +\font\mini=cmr7 +\def\frac#1#2{{{#1} \over {#2}}} +\hbox{} +\vfill + +\centerline{\eins Other Applications} +\bigskip\bigskip +\item{$\bullet$} exp, sin, cos, log, arctan, etc. +\medskip +\item{$\bullet$} $\pi$ (Chudnovsky's formula, a Ramanujan type series) +\medskip +\item{$\bullet$} hypergeometric functions at $x \in {\Bbb Q}$ +\medskip +\item{$\bullet$} hypergeometric and holonomic functions at $x \in {\Bbb C}$ + [J.\ van der Hoeven] +\medskip +\item{$\bullet$} $\Gamma(x)$ at $x \in {\Bbb Q}$ +\medskip +\item{$\bullet$} Large terms of P-recursive sequences, i.e.\ $f_n$ ($n$ large) + where ${f(x) = \sum f_n x^n}$ is holonomic, +\medskip +\item{$\bullet$} $\zeta(k)$, $k > 1$ odd (using Cohen-Villegas-Zagier + convergence acceleration) + +\vfill +\hbox{} +\eject + +\end diff --git a/doc/ratseries/slides/slide6.dvi b/doc/ratseries/slides/slide6.dvi new file mode 100644 index 0000000000000000000000000000000000000000..5da6ce47a728f93d2339298ab9b83ed830da1b42 GIT binary patch literal 488 zcmey)#MnIPfQ&T*5U?GPRtQOrP{=PWDJU&bFtoHZ*E2BJGc>m{FfcUe2C85LDI)~_ z13~ZnPYeuw3m7eK>hv!7&$!jBcVcdy_Gjx$-1F2J1l`v$Z~;wWP0md+GG+Rqtw}zCNHFZ)gO_ioJqB-U5b=53G87-nf3tReOj7-5-A_rU-Fxw?~g literal 0 HcmV?d00001 diff --git a/doc/ratseries/slides/slide6.log b/doc/ratseries/slides/slide6.log new file mode 100644 index 0000000..4cd26a1 --- /dev/null +++ b/doc/ratseries/slides/slide6.log @@ -0,0 +1,19 @@ +This is TeX, Version 3.14159 (C version 6.1) (format=tex 96.5.7) 17 JUL 1997 00:10 +**slide6.tex +(slide6.tex +Hyphenation patterns for english, german, francais, loaded. +(/usr/lib/teTeX/texmf/tex/amstex/base/amssym.def +\msafam=\fam8 +\msbfam=\fam9 +\eufmfam=\fam10 +) +(/home/bruno/tex/macros/dissaux/amssym.tex) (epsf.tex +\epsffilein=\read0 +\epsfxsize=\dimen16 +\epsfysize=\dimen17 +\epsftsize=\dimen18 +\epsfrsize=\dimen19 +\epsftmp=\dimen20 +\pspoints=\dimen21 +) [1] ) +Output written on slide6.dvi (1 page, 488 bytes). diff --git a/doc/ratseries/slides/slide6.ps b/doc/ratseries/slides/slide6.ps new file mode 100644 index 0000000..a3d7fa3 --- /dev/null +++ b/doc/ratseries/slides/slide6.ps @@ -0,0 +1,574 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: slide6.dvi +%%Pages: 1 +%%PageOrder: Ascend +%%BoundingBox: 0 0 596 842 +%%DocumentPaperSizes: a4 +%%EndComments +%DVIPSCommandLine: dvips -Pljfour -o slide6.ps slide6.dvi +%DVIPSParameters: dpi=600, compressed, comments removed +%DVIPSSource: TeX output 1997.07.17:0010 +%%BeginProcSet: texc.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]/id ch-image N /rw ch-width 7 add 8 idiv string N /rc 0 N /gp 0 N +/cp 0 N{rc 0 ne{rc 1 sub /rc X rw}{G}ifelse}imagemask restore}B /G{{id +gp get /gp gp 1 add N dup 18 mod S 18 idiv pl S get exec}loop}B /adv{cp +add /cp X}B /chg{rw cp id gp 4 index getinterval putinterval dup gp add +/gp X adv}B /nd{/cp 0 N rw exit}B /lsh{rw cp 2 copy get dup 0 eq{pop 1}{ +dup 255 eq{pop 254}{dup dup add 255 and S 1 and or}ifelse}ifelse put 1 +adv}B /rsh{rw cp 2 copy get dup 0 eq{pop 128}{dup 255 eq{pop 127}{dup 2 +idiv S 128 and or}ifelse}ifelse put 1 adv}B /clr{rw cp 2 index string +putinterval adv}B /set{rw cp fillstr 0 4 index getinterval putinterval +adv}B /fillstr 18 string 0 1 17{2 copy 255 put pop}for N /pl[{adv 1 chg} +{adv 1 chg nd}{1 add chg}{1 add chg nd}{adv lsh}{adv lsh nd}{adv rsh}{ +adv rsh nd}{1 add adv}{/rc X nd}{1 add set}{1 add clr}{adv 2 chg}{adv 2 +chg nd}{pop nd}]dup{bind pop}forall N /D{/cc X dup type /stringtype ne{] +}if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +%%BeginProcSet: special.pro +TeXDict begin /SDict 200 dict N SDict begin /@SpecialDefaults{/hs 612 N +/vs 792 N /ho 0 N /vo 0 N /hsc 1 N /vsc 1 N /ang 0 N /CLIP 0 N /rwiSeen +false N /rhiSeen false N /letter{}N /note{}N /a4{}N /legal{}N}B +/@scaleunit 100 N /@hscale{@scaleunit div /hsc X}B /@vscale{@scaleunit +div /vsc X}B /@hsize{/hs X /CLIP 1 N}B /@vsize{/vs X /CLIP 1 N}B /@clip{ +/CLIP 2 N}B /@hoffset{/ho X}B /@voffset{/vo X}B /@angle{/ang X}B /@rwi{ +10 div /rwi X /rwiSeen true N}B /@rhi{10 div /rhi X /rhiSeen true N}B +/@llx{/llx X}B /@lly{/lly X}B /@urx{/urx X}B /@ury{/ury X}B /magscale +true def end /@MacSetUp{userdict /md known{userdict /md get type +/dicttype eq{userdict begin md length 10 add md maxlength ge{/md md dup +length 20 add dict copy def}if end md begin /letter{}N /note{}N /legal{} +N /od{txpose 1 0 mtx defaultmatrix dtransform S atan/pa X newpath +clippath mark{transform{itransform moveto}}{transform{itransform lineto} +}{6 -2 roll transform 6 -2 roll transform 6 -2 roll transform{ +itransform 6 2 roll itransform 6 2 roll itransform 6 2 roll curveto}}{{ +closepath}}pathforall newpath counttomark array astore /gc xdf pop ct 39 +0 put 10 fz 0 fs 2 F/|______Courier fnt invertflag{PaintBlack}if}N +/txpose{pxs pys scale ppr aload pop por{noflips{pop S neg S TR pop 1 -1 +scale}if xflip yflip and{pop S neg S TR 180 rotate 1 -1 scale ppr 3 get +ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg TR}if xflip yflip +not and{pop S neg S TR pop 180 rotate ppr 3 get ppr 1 get neg sub neg 0 +TR}if yflip xflip not and{ppr 1 get neg ppr 0 get neg TR}if}{noflips{TR +pop pop 270 rotate 1 -1 scale}if xflip yflip and{TR pop pop 90 rotate 1 +-1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg +TR}if xflip yflip not and{TR pop pop 90 rotate ppr 3 get ppr 1 get neg +sub neg 0 TR}if yflip xflip not and{TR pop pop 270 rotate ppr 2 get ppr +0 get neg sub neg 0 S TR}if}ifelse scaleby96{ppr aload pop 4 -1 roll add +2 div 3 1 roll add 2 div 2 copy TR .96 dup scale neg S neg S TR}if}N /cp +{pop pop showpage pm restore}N end}if}if}N /normalscale{Resolution 72 +div VResolution 72 div neg scale magscale{DVImag dup scale}if 0 setgray} +N /psfts{S 65781.76 div N}N /startTexFig{/psf$SavedState save N userdict +maxlength dict begin /magscale true def normalscale currentpoint TR +/psf$ury psfts /psf$urx psfts /psf$lly psfts /psf$llx psfts /psf$y psfts +/psf$x psfts currentpoint /psf$cy X /psf$cx X /psf$sx psf$x psf$urx +psf$llx sub div N /psf$sy psf$y psf$ury psf$lly sub div N psf$sx psf$sy +scale psf$cx psf$sx div psf$llx sub psf$cy psf$sy div psf$ury sub TR +/showpage{}N /erasepage{}N /copypage{}N /p 3 def @MacSetUp}N /doclip{ +psf$llx psf$lly psf$urx psf$ury currentpoint 6 2 roll newpath 4 copy 4 2 +roll moveto 6 -1 roll S lineto S lineto S lineto closepath clip newpath +moveto}N /endTexFig{end psf$SavedState restore}N /@beginspecial{SDict +begin /SpecialSave save N gsave normalscale currentpoint TR +@SpecialDefaults count /ocount X /dcount countdictstack N}N /@setspecial +{CLIP 1 eq{newpath 0 0 moveto hs 0 rlineto 0 vs rlineto hs neg 0 rlineto +closepath clip}if ho vo TR hsc vsc scale ang rotate rwiSeen{rwi urx llx +sub div rhiSeen{rhi ury lly sub div}{dup}ifelse scale llx neg lly neg TR +}{rhiSeen{rhi ury lly sub div dup scale llx neg lly neg TR}if}ifelse +CLIP 2 eq{newpath llx lly moveto urx lly lineto urx ury lineto llx ury +lineto closepath clip}if /showpage{}N /erasepage{}N /copypage{}N newpath +}N /@endspecial{count ocount sub{pop}repeat countdictstack dcount sub{ +end}repeat grestore SpecialSave restore end}N /@defspecial{SDict begin} +N /@fedspecial{end}B /li{lineto}B /rl{rlineto}B /rc{rcurveto}B /np{ +/SaveX currentpoint /SaveY X N 1 setlinecap newpath}N /st{stroke SaveX +SaveY moveto}N /fil{fill SaveX SaveY moveto}N /ellipse{/endangle X +/startangle X /yrad X /xrad X /savematrix matrix currentmatrix N TR xrad +yrad scale 0 0 1 startangle endangle arc savematrix setmatrix}N end +%%EndProcSet +TeXDict begin 39158280 55380996 1728 600 600 (slide6.dvi) +@start /Fa 2 113 df<007FBC12FCBD12FEA46C1BFC570674A670>0 +D<1F07F70F801F1FA21F3F2000671F7E1FFE671E01671E03671E07671E0F671E1F671E3F +9CC7FC661E7E1EFE661D01661D03661D07661D0F661D1F661D3F9BC8FCA2651D7E1DFE65 +1C01651C03651C07651C0F651C1F651C3F9AC9FC641C7E1CFE641B01641B03641B07641B +0F641B1F641B3F022096CAFC027060D901F0187E497E010719FED91FFC60013F1801496C +60D801FF1803486D60D807CF1807D81F0F6D5FD83E07180F007C6200F06E161F486C6100 +006E163F6D96CBFC6F5E6D187E6F16FE027F5F6F1501023F5F19036F5E021F16076F5E6E +160F705D6E161F705D6E163F7092CCFC6E5E197E826E16FE705C037F1401705C033F1403 +705C031F1407705C6F140F61EF801F6F5DEFC03F6F92CDFC715A6F147EEFF0FE6F5C17F9 +047F5B17FBEFFFF08260826082608295CEFC825FA2705AA216005F7190768578>112 +D E /Fb 2 18 df[<18FC17011703EF07F8EF0FF0EF1FE0EF3FC0EF7F80EFFF004C5A4C +5A4C5AA24C5A4C5A4C5A4C5A16FF94C7FC4B5A15035E4B5A150F4B5A5E153F4B5AA24B5A +93C8FC5C4A5AA24A5AA24A5AA24A5AA24A5AA2147F5D14FF5D5BA24990C9FCA25C1307A2 +495AA3495AA3495AA3495AA313FF5CA35A5CA25AA291CAFCA35AA25BA2120FA35BA2121F +A55BA2123FA65B127FAB5B12FFB3AF127F7FAB123F7FA6121FA27FA5120FA27FA31207A2 +7FA27EA380A27EA2807EA380137FA36D7EA36D7EA36D7EA36D7EA2130380A26D7FA27F81 +147F81143FA26E7EA26E7EA26E7EA26E7EA26E7E80826F7EA26F7E151F826F7E15076F7E +8215016F7E83167F707E707E707E707EA2707E707E707EEF7F80EF3FC0EF1FE0EF0FF0EF +07F8EF03FC17011700>54 257 102 133 86 16 D[<127C12FE127F7F6C7E6C7E6C7E6C +7E6C7E6C7E6C7E6D7EA26D7E6D7E6D7E6D7E8013036D7E807F6E7E816E7E141F816E7EA2 +6E7E1403816E7EA26E7FA26F7EA26F7EA26F7EA282150F82150782A26F7EA28183A26F7F +A3707EA3707EA3707EA383160FA3831607A283A282A31880A282A218C0A382A218E0A517 +7FA218F0A6173F18F8AB171F18FCB3AF18F8173FAB18F0177FA618E0A217FFA518C0A25E +A31880A25EA21800A35EA25FA2160F5FA3161F5FA34C5AA34C5AA34C5AA34B5BA294C7FC +5DA24B5AA25E150F5E151F5EA24B5AA24B5AA24B5AA24A90C8FCA24A5A5D14074A5AA24A +5A5D143F4A5A5D4AC9FC5B5C495A13075C495A495A495A495AA249CAFC485A485A485A48 +5A485A485A485A90CBFC12FE127C>54 257 123 133 86 I E /Fc +4 121 df<913807FF80027F13F849B6FC010715C04915F090263FF80713FC90267FC000 +7F01FEC7EA3FFF4848020F7FD803F06E7F48486E7F496E7F000F8348488090C96C7E5A00 +3E707E127E007C83D87FE0817F487E6D17807F83A56C5AA26C485D6C5AD803801700CAFC +A25F60A24D5AA26017FF604C5BA24C5B4C5B95C7FC4C5A4C5A5F4C5A4C5A5F4C5A4B90C8 +FC4B5A4B5A4B5A5E4B5A4B5A4BC9FC15FE4A5A4A5A4A5A4A5A4A5A4BEC07804AC8FC147E +4AED0F00495A495AEB07C0495A49C95A013E161E133C49163E5B484816FE48B8FC5A485F +5A5A5AB9FCA260A3395F79DE48>50 D101 +D<02F8EB3FF8D807FF49B57EB5010714E092391FE01FF892397F0007FE03FCEB01FFDAF9 +F06D13C0C6D9FBE06E7E90263FFFC06E7E6D496E7E92C86C7E4A8218074A824A6F1380A2 +7213C01AE084A21AF0197F1AF8A4193F1AFCACF17FF8A41AF019FFA21AE0601AC0A24E13 +80804E13006E4B5A616E4B5A6F4A5A6F5DDAFBE0ECFFC0DAF9F0495BDAF8F84990C7FC03 +7EEB0FFC92393FC07FF0030FB512C0030391C8FC9238007FF093CAFCB3497E90B5FCB7FC +A5465C7CBF50>112 D120 +D E /Fd 6 116 df[<0007C412F0A6488FA64CC7001F03FCC7123F04E01B0393C8F1007F +03F81D0F4B8903C01D01484A77804AC91B3F4A8B4A8B4A8BA24A8BA24A8BA24A8BA2488F +91CA1C7FA349213FA549211FA3007F8FA3498DA948487B1380A6CC99C8FCB3B3B3B3B3A5 +033FBE12FEAB06C0CA1201>153 167 119 294 172 84 D103 +D[<4AB4FC020F13E0023F13F891B512FE49804981498149814981A24981A24981A390B7 +7EA96D5DA36D5DA26D5DA26D5D6D5D6D5D6D92C8FC6D5C023F13F8020F13E0020190C9FC +91CBFCB3A5EE7FF0010FB6FC007FB7FCACEA000F13017FA280B3B3B3B3A9BA12E0AB49C8 +1203>59 173 122 300 68 105 D<922601FFC0DB7FFF953803FFF8013FB60307B500F8 +053FEBFFC0B8033FDAFF804BB612FC4FB700E0030F15FF070704F8033F16C0071F04FE92 +B812F04F704A8396B96C0107834E7249834E02006F49D9F807804E01F06D6E49D9800381 +4E01C06D4C48487E4E90C76C6ED9FFF86D81DE3FFC714801E083D8001F4C486E4B498001 +01DCFFE0714890C8816D4D6105C1496E6E48486F806E02C390C84C5A4E62DDC7FCDFBFE0 +84DDCFF8F1FFC04E6205DF70864E97C9FC05FF8E4E614E61A395C95EA24D62A34D62A54D +62B3B3B3A5BAD8FC03BAD8E01FBAFCAB49C8000104F0C8000F0480C87EC86F7AEECF> +109 D<922601FFC0ED7FFF013FB60307B512F8B8033FECFF804FB712E0070716F8071F16 +FE4F8296B97E4E844E0200814E01F06D804E01C07F4E90C76C80DE3FFC83D8001F4C4880 +0101DCFFE0836D5F05C1496E806E02C390C8FC60DDC7FC85EFCFF86005DF826005FF8660 +60A395C9FCA25FA35FA55FB3B3B3A5BAD8FC03BA12E0AB49C8000104F0C8120F836F7AEE +8A>I<4BB5EC0FC0037F02F8133F0207B7EBFFE0023F16C391BAFC13035B131F49EC0003 +4901F0EB003F90B50080140F4849C812034849814A8148498248498285484982A248845C +5A85A4B56C82A380A2806E705B14FE6E94C8FC15C015F015FE6CECFFE016FF17F8EFFFC0 +6C17F818FF6C18E019F86C18FE856C19C06C856C851AFC6C856D847F010F856D856D8513 +006E84021F841403DA007F83150F0300831607EE003F050181EF003F18077215801800D8 +3FE083007F181F486C83A2856D83A2857FA285A27F1C007FA280636E5EA26E6061806E60 +6E4C5B6E5E6E4C5B6F4B5B03E05D03F84AB55A03FE020F91C7FCDBFFE090B55A93B75A62 +023F17E0496C5FD9F80794C8FCD9F00116F89026C0003F15E06C4801074AC9FC007EC86C +13C0517178EF62>115 D E end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: a4 +%%BeginPaperSize: a4 +a4 +%%EndPaperSize + +%%EndSetup +%%Page: 1 1 +1 0 bop 1570 840 a Fd(Timings)1649 1240 y Fc(exp)1892 +1081 y Fb(\020)1978 1240 y Fa(\000)2090 1114 y(p)p 2209 +1114 72 6 v 2209 1240 a Fc(2)2281 1081 y Fb(\021)0 3792 +y @beginspecial 50 @llx 50 @lly 356 @urx 302 @ury 3060 +@rwi @setspecial +%%BeginDocument: fig2.eps +/gnudict 40 dict def +gnudict begin +/Color false def +/Solid false def +/gnulinewidth 5.000 def +/vshift -46 def +/dl {10 mul} def +/hpt 31.5 def +/vpt 31.5 def +/M {moveto} bind def +/L {lineto} bind def +/R {rmoveto} bind def +/V {rlineto} bind def +/vpt2 vpt 2 mul def +/hpt2 hpt 2 mul def +/Lshow { currentpoint stroke M + 0 vshift R show } def +/Rshow { currentpoint stroke M + dup stringwidth pop neg vshift R show } def +/Cshow { currentpoint stroke M + dup stringwidth pop -2 div vshift R show } def +/DL { Color {setrgbcolor Solid {pop []} if 0 setdash } + {pop pop pop Solid {pop []} if 0 setdash} ifelse } def +/BL { stroke gnulinewidth 2 mul setlinewidth } def +/AL { stroke gnulinewidth 2 div setlinewidth } def +/PL { stroke gnulinewidth setlinewidth } def +/LTb { BL [] 0 0 0 DL } def +/LTa { AL [1 dl 2 dl] 0 setdash 0 0 0 setrgbcolor } def +/LT0 { PL [] 0 1 0 DL } def +/LT1 { PL [4 dl 2 dl] 0 0 1 DL } def +/LT2 { PL [2 dl 3 dl] 1 0 0 DL } def +/LT3 { PL [1 dl 1.5 dl] 1 0 1 DL } def +/LT4 { PL [5 dl 2 dl 1 dl 2 dl] 0 1 1 DL } def +/LT5 { PL [4 dl 3 dl 1 dl 3 dl] 1 1 0 DL } def +/LT6 { PL [2 dl 2 dl 2 dl 4 dl] 0 0 0 DL } def +/LT7 { PL [2 dl 2 dl 2 dl 2 dl 2 dl 4 dl] 1 0.3 0 DL } def +/LT8 { PL [2 dl 2 dl 2 dl 2 dl 2 dl 2 dl 2 dl 4 dl] 0.5 0.5 0.5 DL } def +/P { stroke [] 0 setdash + currentlinewidth 2 div sub M + 0 currentlinewidth V stroke } def +/D { stroke [] 0 setdash 2 copy vpt add M + hpt neg vpt neg V hpt vpt neg V + hpt vpt V hpt neg vpt V closepath stroke + P } def +/A { stroke [] 0 setdash vpt sub M 0 vpt2 V + currentpoint stroke M + hpt neg vpt neg R hpt2 0 V stroke + } def +/B { stroke [] 0 setdash 2 copy exch hpt sub exch vpt add M + 0 vpt2 neg V hpt2 0 V 0 vpt2 V + hpt2 neg 0 V closepath stroke + P } def +/C { stroke [] 0 setdash exch hpt sub exch vpt add M + hpt2 vpt2 neg V currentpoint stroke M + hpt2 neg 0 R hpt2 vpt2 V stroke } def +/T { stroke [] 0 setdash 2 copy vpt 1.12 mul add M + hpt neg vpt -1.62 mul V + hpt 2 mul 0 V + hpt neg vpt 1.62 mul V closepath stroke + P } def +/S { 2 copy A C} def +end +gnudict begin +gsave +50 50 translate +0.050 0.050 scale +0 setgray +/Helvetica findfont 140 scalefont setfont +newpath +LTa +LTb +672 771 M +63 0 V +5154 0 R +-63 0 V +588 771 M +(0.001) Rshow +672 1191 M +63 0 V +5154 0 R +-63 0 V +-5238 0 R +(0.01) Rshow +672 1610 M +63 0 V +5154 0 R +-63 0 V +-5238 0 R +(0.1) Rshow +672 2030 M +63 0 V +5154 0 R +-63 0 V +-5238 0 R +(1) Rshow +672 2450 M +63 0 V +5154 0 R +-63 0 V +-5238 0 R +(10) Rshow +672 2870 M +63 0 V +5154 0 R +-63 0 V +-5238 0 R +(100) Rshow +672 3290 M +63 0 V +5154 0 R +-63 0 V +-5238 0 R +(1000) Rshow +672 3710 M +63 0 V +5154 0 R +-63 0 V +-5238 0 R +(10000) Rshow +672 351 M +0 63 V +0 4555 R +0 -63 V +672 211 M +(10) Cshow +1023 351 M +0 31 V +0 4587 R +0 -31 V +1486 351 M +0 31 V +0 4587 R +0 -31 V +1724 351 M +0 31 V +0 4587 R +0 -31 V +1837 351 M +0 63 V +0 4555 R +0 -63 V +0 -4695 R +(100) Cshow +2188 351 M +0 31 V +0 4587 R +0 -31 V +2652 351 M +0 31 V +0 4587 R +0 -31 V +2890 351 M +0 31 V +0 4587 R +0 -31 V +3003 351 M +0 63 V +0 4555 R +0 -63 V +0 -4695 R +(1000) Cshow +3353 351 M +0 31 V +0 4587 R +0 -31 V +3817 351 M +0 31 V +0 4587 R +0 -31 V +4055 351 M +0 31 V +0 4587 R +0 -31 V +4168 351 M +0 63 V +0 4555 R +0 -63 V +0 -4695 R +(10000) Cshow +4519 351 M +0 31 V +0 4587 R +0 -31 V +4982 351 M +0 31 V +0 4587 R +0 -31 V +5220 351 M +0 31 V +0 4587 R +0 -31 V +5333 351 M +0 63 V +0 4555 R +0 -63 V +0 -4695 R +(100000) Cshow +5684 351 M +0 31 V +0 4587 R +0 -31 V +672 351 M +5217 0 V +0 4618 V +-5217 0 V +672 351 L +3280 71 M +(N) Cshow +LT0 +5406 4766 M +(Maple) Rshow +5490 4766 M +252 0 V +1047 752 M +397 186 V +393 253 V +388 206 V +389 231 V +389 235 V +388 266 V +388 283 V +389 288 V +388 269 V +389 295 V +388 315 V +5574 4766 D +1047 752 D +1444 938 D +1837 1191 D +2225 1397 D +2614 1628 D +3003 1863 D +3391 2129 D +3779 2412 D +4168 2700 D +4556 2969 D +4945 3264 D +5333 3579 D +LT1 +5406 4626 M +(Pari) Rshow +5490 4626 M +252 0 V +1047 633 M +397 59 V +393 165 V +388 218 V +389 283 V +389 449 V +388 204 V +388 344 V +389 347 V +388 356 V +389 356 V +388 434 V +5574 4626 A +1047 633 A +1444 692 A +1837 857 A +2225 1075 A +2614 1358 A +3003 1807 A +3391 2011 A +3779 2355 A +4168 2702 A +4556 3058 A +4945 3414 A +5333 3848 A +LT2 +5406 4486 M +(LiDIA) Rshow +5490 4486 M +252 0 V +1047 889 M +397 41 V +393 88 V +388 120 V +389 184 V +389 224 V +388 264 V +388 295 V +389 289 V +388 308 V +389 214 V +388 223 V +5574 4486 B +1047 889 B +1444 930 B +1837 1018 B +2225 1138 B +2614 1322 B +3003 1546 B +3391 1810 B +3779 2105 B +4168 2394 B +4556 2702 B +4945 2916 B +5333 3139 B +LT3 +5406 4346 M +(CLN) Rshow +5490 4346 M +252 0 V +1047 718 M +397 69 V +393 143 V +388 193 V +389 267 V +389 193 V +388 196 V +388 233 V +389 274 V +388 238 V +389 178 V +388 180 V +5574 4346 C +1047 718 C +1444 787 C +1837 930 C +2225 1123 C +2614 1390 C +3003 1583 C +3391 1779 C +3779 2012 C +4168 2286 C +4556 2524 C +4945 2702 C +5333 2882 C +stroke +grestore +end +showpage +%%EndDocument + @endspecial eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/ratseries/slides/slide6.tex b/doc/ratseries/slides/slide6.tex new file mode 100644 index 0000000..456cf23 --- /dev/null +++ b/doc/ratseries/slides/slide6.tex @@ -0,0 +1,27 @@ +\input amssym.def +\input amssym +\magnification=\magstep3 +\input epsf +\hsize=17truecm +\vsize=19truecm +\nopagenumbers +\parindent=0mm +\font\eins=cmb10 scaled \magstep 3 +\font\zwei=cmr12 +\font\mini=cmr7 +\def\frac#1#2{{{#1} \over {#2}}} +\hbox{} +\vfill + +\centerline{\eins Timings} +\bigskip +\centerline{$\displaystyle \exp \left( -\sqrt{2} \right) $} +\bigskip\bigskip +\epsfbox{fig2.eps} + + +\vfill +\hbox{} +\eject + +\end diff --git a/doc/texinfo.tex b/doc/texinfo.tex new file mode 100644 index 0000000..75b7f23 --- /dev/null +++ b/doc/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: 1.1 $ +\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 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 . + % + \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 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 to achieve this: TeX expands \the only once, +% simply yielding the contents of the . +\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\}\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/examples/Makefile.in b/examples/Makefile.in new file mode 100644 index 0000000..62b7c97 --- /dev/null +++ b/examples/Makefile.in @@ -0,0 +1,111 @@ +# Makefile for cln/examples +# This is only needed while CLN has not been installed in a public place on +# your system (such as /usr/local/include and /usr/local/lib). Once CLN is +# installed, a simple C++ compiler command suffices. + +#### Start of system configuration section. #### + +# Directories used by "make": +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ + +# Programs used by "make": +# C compiler +CC = @CC@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +# C++ compiler +CXX = @CXX@ +CXXFLAGS = @CXXFLAGS@ +CXXCPP = @CXXCPP@ +INCLUDES = -I../include -I$(top_srcdir)/include -I$(srcdir) +CPPFLAGS += $(INCLUDES) +LIBTOOL = @LIBTOOL@ +LIBTOOL_LINK = $(LIBTOOL) --mode=link +MV = mv +LN = ln +RM = rm -f +@SET_MAKE@ + +#### End of system configuration section. #### + +SHELL = /bin/sh + +# Needed by $(LIBTOOL). +top_builddir = .. + +VPATH = $(srcdir) + +FILES_CC := $(notdir $(wildcard $(srcdir)/*.cc)) +FILES_CC := $(filter-out %.i.cc, $(FILES_CC)) + +FILES_I_CC := $(patsubst %.cc,%.i.cc,$(FILES_CC)) + +FILES_S := $(patsubst %.cc,%.s,$(FILES_CC)) + +FILES_O := $(patsubst %.cc,%.o,$(FILES_CC)) + +OBJECTS = $(FILES_O) + +LIBS = ../src/libcln.la -lm +LIBDEPS = ../src/libcln.la + +PROGRAMS = contfrac e fibonacci legendre lucaslehmer nextprime perfnum +MODULES_contfrac = contfrac +MODULES_e = e +MODULES_fibonacci = fibonacci +MODULES_legendre = legendre +MODULES_lucaslehmer = lucaslehmer +MODULES_nextprime = nextprime +MODULES_perfnum = perfnum + +all : contfrac e fibonacci legendre lucaslehmer nextprime perfnum + +%.s : %.c + $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -S $< -o $@ + +%.s : %.cc + $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -S $< -o $@ + +%.o : %.c + $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ + +%.o : %.cc + $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ + +%.i : %.c + $(CPP) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) $< > $@ + +%.i.cc : %.cc + $(CXXCPP) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) $< > $@ + +contfrac : $(patsubst %,%.o,$(MODULES_contfrac)) +e : $(patsubst %,%.o,$(MODULES_e)) +fibonacci : $(patsubst %,%.o,$(MODULES_fibonacci)) +legendre : $(patsubst %,%.o,$(MODULES_legendre)) +lucaslehmer : $(patsubst %,%.o,$(MODULES_lucaslehmer)) +nextprime : $(patsubst %,%.o,$(MODULES_nextprime)) +perfnum : $(patsubst %,%.o,$(MODULES_perfnum)) +$(PROGRAMS) : % : $(LIBDEPS) + $(LIBTOOL_LINK) $(CXX) $(CXXFLAGS) $(TARGET_ARCH) $(patsubst %,%.o,$(MODULES_$(*F))) $(LIBS) -o $@ + + +install : all + +installdirs : + +uninstall : + +check : all + +mostlyclean : clean + +clean : force + $(RM) *.s *.o *.a $(PROGRAMS) a.out core + +distclean : clean + $(RM) config.status config.log config.cache Makefile + +maintainer-clean : distclean + +force : diff --git a/examples/atan_recip.cc b/examples/atan_recip.cc new file mode 100644 index 0000000..2db8ffc --- /dev/null +++ b/examples/atan_recip.cc @@ -0,0 +1,273 @@ +// Computation of arctan(1/m) (m integer) to high precision. + +#include "cl_integer.h" +#include "cl_rational.h" +#include "cl_real.h" +#include "cl_lfloat.h" +#include "cl_LF.h" +#include "cl_LF_tran.h" +#include "cl_alloca.h" +#include +#include +#include "cl_timing.h" + +#undef floor +#include +#define floor cln_floor + + +// Method 1: atan(1/m) = sum(n=0..infty, (-1)^n/(2n+1) * 1/m^(2n+1)) +// Method 2: atan(1/m) = sum(n=0..infty, 4^n*n!^2/(2n+1)! * m/(m^2+1)^(n+1)) +// a. Using long floats. [N^2] +// b. Simulating long floats using integers. [N^2] +// c. Using integers, no binary splitting. [N^2] +// d. Using integers, with binary splitting. [FAST] +// Method 3: general built-in algorithm. [FAST] + + +// Method 1: atan(1/m) = sum(n=0..infty, (-1)^n/(2n+1) * 1/m^(2n+1)) + +const cl_LF atan_recip_1a (cl_I m, uintC len) +{ + var uintC actuallen = len + 1; + var cl_LF eps = scale_float(cl_I_to_LF(1,actuallen),-intDsize*(sintL)actuallen); + var cl_I m2 = m*m; + var cl_LF fterm = cl_I_to_LF(1,actuallen)/m; + var cl_LF fsum = fterm; + for (var uintL n = 1; fterm >= eps; n++) { + fterm = fterm/m2; + fterm = cl_LF_shortenwith(fterm,eps); + if ((n % 2) == 0) + fsum = fsum + LF_to_LF(fterm/(2*n+1),actuallen); + else + fsum = fsum - LF_to_LF(fterm/(2*n+1),actuallen); + } + return shorten(fsum,len); +} + +const cl_LF atan_recip_1b (cl_I m, uintC len) +{ + var uintC actuallen = len + 1; + var cl_I m2 = m*m; + var cl_I fterm = floor1((cl_I)1 << (intDsize*actuallen), m); + var cl_I fsum = fterm; + for (var uintL n = 1; fterm > 0; n++) { + fterm = floor1(fterm,m2); + if ((n % 2) == 0) + fsum = fsum + floor1(fterm,2*n+1); + else + fsum = fsum - floor1(fterm,2*n+1); + } + return scale_float(cl_I_to_LF(fsum,len),-intDsize*(sintL)actuallen); +} + +const cl_LF atan_recip_1c (cl_I m, uintC len) +{ + var uintC actuallen = len + 1; + var cl_I m2 = m*m; + var sintL N = (sintL)(0.69314718*intDsize/2*actuallen/log(cl_double_approx(m))) + 1; + var cl_I num = 0, den = 1; // "lazy rational number" + for (sintL n = N-1; n>=0; n--) { + // Multiply sum with 1/m^2: + den = den * m2; + // Add (-1)^n/(2n+1): + if ((n % 2) == 0) + num = num*(2*n+1) + den; + else + num = num*(2*n+1) - den; + den = den*(2*n+1); + } + den = den*m; + var cl_LF result = cl_I_to_LF(num,actuallen)/cl_I_to_LF(den,actuallen); + return shorten(result,len); +} + +const cl_LF atan_recip_1d (cl_I m, uintC len) +{ + var uintC actuallen = len + 1; + var cl_I m2 = m*m; + var uintL N = (uintL)(0.69314718*intDsize/2*actuallen/log(cl_double_approx(m))) + 1; + CL_ALLOCA_STACK; + var cl_I* bv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var cl_I* qv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var uintL n; + for (n = 0; n < N; n++) { + new (&bv[n]) cl_I ((n % 2) == 0 ? (cl_I)(2*n+1) : -(cl_I)(2*n+1)); + new (&qv[n]) cl_I (n==0 ? m : m2); + } + var cl_rational_series series; + series.av = NULL; series.bv = bv; + series.pv = NULL; series.qv = qv; series.qsv = NULL; + var cl_LF result = eval_rational_series(N,series,actuallen); + for (n = 0; n < N; n++) { + bv[n].~cl_I(); + qv[n].~cl_I(); + } + return shorten(result,len); +} + + +// Method 2: atan(1/m) = sum(n=0..infty, 4^n*n!^2/(2n+1)! * m/(m^2+1)^(n+1)) + +const cl_LF atan_recip_2a (cl_I m, uintC len) +{ + var uintC actuallen = len + 1; + var cl_LF eps = scale_float(cl_I_to_LF(1,actuallen),-intDsize*(sintL)actuallen); + var cl_I m2 = m*m+1; + var cl_LF fterm = cl_I_to_LF(m,actuallen)/m2; + var cl_LF fsum = fterm; + for (var uintL n = 1; fterm >= eps; n++) { + fterm = The(cl_LF)((2*n)*fterm)/((2*n+1)*m2); + fterm = cl_LF_shortenwith(fterm,eps); + fsum = fsum + LF_to_LF(fterm,actuallen); + } + return shorten(fsum,len); +} + +const cl_LF atan_recip_2b (cl_I m, uintC len) +{ + var uintC actuallen = len + 1; + var cl_I m2 = m*m+1; + var cl_I fterm = floor1((cl_I)m << (intDsize*actuallen), m2); + var cl_I fsum = fterm; + for (var uintL n = 1; fterm > 0; n++) { + fterm = floor1((2*n)*fterm,(2*n+1)*m2); + fsum = fsum + fterm; + } + return scale_float(cl_I_to_LF(fsum,len),-intDsize*(sintL)actuallen); +} + +const cl_LF atan_recip_2c (cl_I m, uintC len) +{ + var uintC actuallen = len + 1; + var cl_I m2 = m*m+1; + var uintL N = (uintL)(0.69314718*intDsize*actuallen/log(cl_double_approx(m2))) + 1; + var cl_I num = 0, den = 1; // "lazy rational number" + for (uintL n = N; n>0; n--) { + // Multiply sum with (2n)/(2n+1)(m^2+1): + num = num * (2*n); + den = den * ((2*n+1)*m2); + // Add 1: + num = num + den; + } + num = num*m; + den = den*m2; + var cl_LF result = cl_I_to_LF(num,actuallen)/cl_I_to_LF(den,actuallen); + return shorten(result,len); +} + +const cl_LF atan_recip_2d (cl_I m, uintC len) +{ + var uintC actuallen = len + 1; + var cl_I m2 = m*m+1; + var uintL N = (uintL)(0.69314718*intDsize*actuallen/log(cl_double_approx(m2))) + 1; + CL_ALLOCA_STACK; + var cl_I* pv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var cl_I* qv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var uintL n; + new (&pv[0]) cl_I (m); + new (&qv[0]) cl_I (m2); + for (n = 1; n < N; n++) { + new (&pv[n]) cl_I (2*n); + new (&qv[n]) cl_I ((2*n+1)*m2); + } + var cl_rational_series series; + series.av = NULL; series.bv = NULL; + series.pv = pv; series.qv = qv; series.qsv = NULL; + var cl_LF result = eval_rational_series(N,series,actuallen); + for (n = 0; n < N; n++) { + pv[n].~cl_I(); + qv[n].~cl_I(); + } + return shorten(result,len); +} + + +// Main program: Compute and display the timings. + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); + cl_I m = (cl_I)argv[1]; + uintL len = atoi(argv[2]); + cl_LF p; + ln(cl_I_to_LF(1000,len+10)); // fill cache + // Method 1. + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = atan_recip_1a(m,len); } + } + cout << p << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = atan_recip_1b(m,len); } + } + cout << p << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = atan_recip_1c(m,len); } + } + cout << p << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = atan_recip_1d(m,len); } + } + cout << p << endl; + // Method 2. + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = atan_recip_2a(m,len); } + } + cout << p << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = atan_recip_2b(m,len); } + } + cout << p << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = atan_recip_2c(m,len); } + } + cout << p << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = atan_recip_2d(m,len); } + } + cout << p << endl; + // Method 3. + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = The(cl_LF)(atan(cl_RA_to_LF(1/(cl_RA)m,len))); } + } + cout << p << endl; +} + + +// Timings of the above algorithms, on an i486 33 MHz, running Linux. +// m = 390112. (For Jörg Arndt's formula (4.15).) +// N 1a 1b 1c 1d 2a 2b 2c 2d 3 +// 10 0.0027 0.0018 0.0019 0.0019 0.0032 0.0022 0.0019 0.0019 0.0042 +// 25 0.0085 0.0061 0.0058 0.0061 0.0095 0.0069 0.0056 0.0061 0.028 +// 50 0.024 0.018 0.017 0.017 0.026 0.020 0.016 0.017 0.149 +// 100 0.075 0.061 0.057 0.054 0.079 0.065 0.052 0.052 0.71 +// 250 0.41 0.33 0.32 0.26 0.42 0.36 0.28 0.24 3.66 +// 500 1.57 1.31 1.22 0.88 1.57 1.36 1.10 0.83 13.7 +// 1000 6.08 5.14 4.56 2.76 6.12 5.36 4.06 2.58 45.5 +// 2500 36.5 32.2 25.8 10.2 38.4 33.6 22.2 9.1 191 +// 5000 +// 10000 +// asymp. N^2 N^2 N^2 FAST N^2 N^2 N^2 FAST FAST +// +// m = 319. (For Jörg Arndt's formula (4.7).) +// N 1a 1b 1c 1d 2a 2b 2c 2d 3 +// 1000 6.06 4.40 9.17 3.82 5.29 3.90 7.50 3.53 50.3 +// +// m = 18. (For Jörg Arndt's formula (4.4).) +// N 1a 1b 1c 1d 2a 2b 2c 2d 3 +// 1000 11.8 9.0 22.3 6.0 10.2 7.7 17.1 5.7 54.3 diff --git a/examples/atanh_recip.cc b/examples/atanh_recip.cc new file mode 100644 index 0000000..240b8b4 --- /dev/null +++ b/examples/atanh_recip.cc @@ -0,0 +1,281 @@ +// Computation of artanh(1/m) (m integer) to high precision. + +#include "cl_integer.h" +#include "cl_rational.h" +#include "cl_real.h" +#include "cl_complex.h" +#include "cl_lfloat.h" +#include "cl_LF.h" +#include "cl_LF_tran.h" +#include "cl_alloca.h" +#include +#include +#include "cl_timing.h" + +#undef floor +#include +#define floor cln_floor + + +// Method 1: atanh(1/m) = sum(n=0..infty, 1/(2n+1) * 1/m^(2n+1)) +// Method 2: atanh(1/m) = sum(n=0..infty, (-4)^n*n!^2/(2n+1)! * m/(m^2-1)^(n+1)) +// a. Using long floats. [N^2] +// b. Simulating long floats using integers. [N^2] +// c. Using integers, no binary splitting. [N^2] +// d. Using integers, with binary splitting. [FAST] +// Method 3: general built-in algorithm. [FAST] +// Method 4: atanh(x) = 1/2 ln((1+x)/(1-x)), +// using the general built-in algorithm [FAST] + + +// Method 1: atanh(1/m) = sum(n=0..infty, 1/(2n+1) * 1/m^(2n+1)) + +const cl_LF atanh_recip_1a (cl_I m, uintC len) +{ + var uintC actuallen = len + 1; + var cl_LF eps = scale_float(cl_I_to_LF(1,actuallen),-intDsize*(sintL)actuallen); + var cl_I m2 = m*m; + var cl_LF fterm = cl_I_to_LF(1,actuallen)/m; + var cl_LF fsum = fterm; + for (var uintL n = 1; fterm >= eps; n++) { + fterm = fterm/m2; + fterm = cl_LF_shortenwith(fterm,eps); + fsum = fsum + LF_to_LF(fterm/(2*n+1),actuallen); + } + return shorten(fsum,len); +} + +const cl_LF atanh_recip_1b (cl_I m, uintC len) +{ + var uintC actuallen = len + 1; + var cl_I m2 = m*m; + var cl_I fterm = floor1((cl_I)1 << (intDsize*actuallen), m); + var cl_I fsum = fterm; + for (var uintL n = 1; fterm > 0; n++) { + fterm = floor1(fterm,m2); + fsum = fsum + floor1(fterm,2*n+1); + } + return scale_float(cl_I_to_LF(fsum,len),-intDsize*(sintL)actuallen); +} + +const cl_LF atanh_recip_1c (cl_I m, uintC len) +{ + var uintC actuallen = len + 1; + var cl_I m2 = m*m; + var sintL N = (sintL)(0.69314718*intDsize/2*actuallen/log(cl_double_approx(m))) + 1; + var cl_I num = 0, den = 1; // "lazy rational number" + for (sintL n = N-1; n>=0; n--) { + // Multiply sum with 1/m^2: + den = den * m2; + // Add 1/(2n+1): + num = num*(2*n+1) + den; + den = den*(2*n+1); + } + den = den*m; + var cl_LF result = cl_I_to_LF(num,actuallen)/cl_I_to_LF(den,actuallen); + return shorten(result,len); +} + +const cl_LF atanh_recip_1d (cl_I m, uintC len) +{ + var uintC actuallen = len + 1; + var cl_I m2 = m*m; + var uintL N = (uintL)(0.69314718*intDsize/2*actuallen/log(cl_double_approx(m))) + 1; + CL_ALLOCA_STACK; + var cl_I* bv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var cl_I* qv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var uintL n; + for (n = 0; n < N; n++) { + new (&bv[n]) cl_I ((cl_I)(2*n+1)); + new (&qv[n]) cl_I (n==0 ? m : m2); + } + var cl_rational_series series; + series.av = NULL; series.bv = bv; + series.pv = NULL; series.qv = qv; series.qsv = NULL; + var cl_LF result = eval_rational_series(N,series,actuallen); + for (n = 0; n < N; n++) { + bv[n].~cl_I(); + qv[n].~cl_I(); + } + return shorten(result,len); +} + + +// Method 2: atanh(1/m) = sum(n=0..infty, (-4)^n*n!^2/(2n+1)! * m/(m^2-1)^(n+1)) + +const cl_LF atanh_recip_2a (cl_I m, uintC len) +{ + var uintC actuallen = len + 1; + var cl_LF eps = scale_float(cl_I_to_LF(1,actuallen),-intDsize*(sintL)actuallen); + var cl_I m2 = m*m-1; + var cl_LF fterm = cl_I_to_LF(m,actuallen)/m2; + var cl_LF fsum = fterm; + for (var uintL n = 1; fterm >= eps; n++) { + fterm = The(cl_LF)((2*n)*fterm)/((2*n+1)*m2); + fterm = cl_LF_shortenwith(fterm,eps); + if ((n % 2) == 0) + fsum = fsum + LF_to_LF(fterm,actuallen); + else + fsum = fsum - LF_to_LF(fterm,actuallen); + } + return shorten(fsum,len); +} + +const cl_LF atanh_recip_2b (cl_I m, uintC len) +{ + var uintC actuallen = len + 1; + var cl_I m2 = m*m-1; + var cl_I fterm = floor1((cl_I)m << (intDsize*actuallen), m2); + var cl_I fsum = fterm; + for (var uintL n = 1; fterm > 0; n++) { + fterm = floor1((2*n)*fterm,(2*n+1)*m2); + if ((n % 2) == 0) + fsum = fsum + fterm; + else + fsum = fsum - fterm; + } + return scale_float(cl_I_to_LF(fsum,len),-intDsize*(sintL)actuallen); +} + +const cl_LF atanh_recip_2c (cl_I m, uintC len) +{ + var uintC actuallen = len + 1; + var cl_I m2 = m*m-1; + var uintL N = (uintL)(0.69314718*intDsize*actuallen/log(cl_double_approx(m2))) + 1; + var cl_I num = 0, den = 1; // "lazy rational number" + for (uintL n = N; n>0; n--) { + // Multiply sum with -(2n)/(2n+1)(m^2+1): + num = num * (2*n); + den = - den * ((2*n+1)*m2); + // Add 1: + num = num + den; + } + num = num*m; + den = den*m2; + var cl_LF result = cl_I_to_LF(num,actuallen)/cl_I_to_LF(den,actuallen); + return shorten(result,len); +} + +const cl_LF atanh_recip_2d (cl_I m, uintC len) +{ + var uintC actuallen = len + 1; + var cl_I m2 = m*m-1; + var uintL N = (uintL)(0.69314718*intDsize*actuallen/log(cl_double_approx(m2))) + 1; + CL_ALLOCA_STACK; + var cl_I* pv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var cl_I* qv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var uintL n; + new (&pv[0]) cl_I (m); + new (&qv[0]) cl_I (m2); + for (n = 1; n < N; n++) { + new (&pv[n]) cl_I (-(cl_I)(2*n)); + new (&qv[n]) cl_I ((2*n+1)*m2); + } + var cl_rational_series series; + series.av = NULL; series.bv = NULL; + series.pv = pv; series.qv = qv; series.qsv = NULL; + var cl_LF result = eval_rational_series(N,series,actuallen); + for (n = 0; n < N; n++) { + pv[n].~cl_I(); + qv[n].~cl_I(); + } + return shorten(result,len); +} + + +// Main program: Compute and display the timings. + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); + cl_I m = (cl_I)argv[1]; + uintL len = atoi(argv[2]); + cl_LF p; + ln(cl_I_to_LF(1000,len+10)); // fill cache + // Method 1. + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = atanh_recip_1a(m,len); } + } + cout << p << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = atanh_recip_1b(m,len); } + } + cout << p << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = atanh_recip_1c(m,len); } + } + cout << p << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = atanh_recip_1d(m,len); } + } + cout << p << endl; + // Method 2. + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = atanh_recip_2a(m,len); } + } + cout << p << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = atanh_recip_2b(m,len); } + } + cout << p << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = atanh_recip_2c(m,len); } + } + cout << p << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = atanh_recip_2d(m,len); } + } + cout << p << endl; + // Method 3. + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = The(cl_LF)(atanh(cl_RA_to_LF(1/(cl_RA)m,len))); } + } + cout << p << endl; + // Method 4. + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = The(cl_LF)(scale_float(ln(cl_RA_to_LF((cl_RA)(m+1)/(cl_RA)(m-1),len)),-1)); } + } + cout << p << endl; +} + + +// Timings of the above algorithms, on an i486 33 MHz, running Linux. +// m = 3 -> 1/2 ln(2) +// N 1a 1b 1c 1d 2a 2b 2c 2d 3 +// 10 0.021 0.014 0.019 0.012 0.029 0.015 0.023 0.015 0.015 +// 25 0.060 0.041 0.073 0.041 0.082 0.046 0.086 0.051 0.066 +// 50 0.164 0.110 0.258 0.120 0.203 0.124 0.295 0.142 +// 100 0.49 0.35 1.05 0.37 0.60 0.35 1.19 0.42 +// 250 2.5 1.9 7.2 1.7 2.9 1.9 8.0 1.8 +// 500 10.1 7.2 33.4 5.5 10.7 7.3 36.5 5.9 +// 1000 38 30 145 16.1 39 29 158 16.8 +// 2500 231 188 976 53 237 186 1081 58 +// asymp. N^2 N^2 N^2 FAST N^2 N^2 N^2 FAST +// +// m = 9 -> 1/2 ln(5/4) +// N 1a 1b 1c 1d 2a 2b 2c 2d 3 4 +// 10 0.0106 0.0072 0.0084 0.0061 0.0139 0.0073 0.0098 0.0073 0.0140 0.0211 +// 25 0.031 0.021 0.029 0.019 0.039 0.022 0.031 0.022 0.063 0.081 +// 50 0.083 0.057 0.091 0.056 0.098 0.058 0.098 0.060 0.232 0.212 +// 100 0.25 0.17 0.32 0.16 0.28 0.17 0.34 0.17 0.60 0.59 +// 250 1.28 0.94 2.11 0.77 1.40 0.91 2.18 0.76 2.76 2.76 +// 500 5.1 3.6 9.4 2.5 5.2 3.4 9.3 2.4 10.4 9.7 +// 1000 19.1 14.7 42 7.8 18.5 13.6 42 7.4 31 30 +// 2500 116 93 279 29.6 113 86 278 30.0 129 125 +// asymp. N^2 N^2 N^2 FAST N^2 N^2 N^2 FAST FAST FAST diff --git a/examples/contfrac.cc b/examples/contfrac.cc new file mode 100644 index 0000000..f93f869 --- /dev/null +++ b/examples/contfrac.cc @@ -0,0 +1,45 @@ +// Print the continued fraction of a real number. + +// We work with real numbers and integers. +#include +#include + +// We do I/O. +#include +#include + +// Our private error handling: return to the main program. +#include +jmp_buf restartpoint; +void cl_abort (void) { longjmp(restartpoint,1); } + +int main (int argc, char* argv[]) +{ + for (int i = 1; i < argc; i++) { + const char * arg = argv[i]; + if (setjmp(restartpoint)) + continue; + // Convert argument to its internal representation: + cl_R x = arg; + // Check sign. + if (minusp(x)) { + fprint(cl_stdout, "-"); + x = -x; + } + fprint(cl_stdout, "["); + const char* separator = "; "; + for (;;) { + // Split x into integral and fractional part. + cl_R_div_t x_split = floor2(x); + fprint(cl_stdout, x_split.quotient); + x = x_split.remainder; + if (zerop(x)) + break; + fprint(cl_stdout, separator); + separator = ", "; + // Invert x. + x = recip(x); + } + fprint(cl_stdout, "]\n"); + } +} diff --git a/examples/e.cc b/examples/e.cc new file mode 100644 index 0000000..61a733c --- /dev/null +++ b/examples/e.cc @@ -0,0 +1,121 @@ +/* + * The following program was used to compute the first 100,000,000 decimal + * digits of e = exp(1), on December 18-20, 1998. + * Timings on a Sun UltraSparc-II (296 MHz), running Solaris 2.6, equipped + * with 512 MB RAM and 2 GB swap: + * + * 100 digits: + * computation of e: real time: 0.002 s, run time: 0.000 s + * conversion to decimal: real time: 0.003 s, run time: 0.000 s + * 1000 digits: + * computation of e: real time: 0.018 s, run time: 0.020 s + * conversion to decimal: real time: 0.028 s, run time: 0.020 s + * 10000 digits: + * computation of e: real time: 0.488 s, run time: 0.480 s + * conversion to decimal: real time: 1.059 s, run time: 1.060 s + * 100000 digits: + * computation of e: real time: 8.139 s, run time: 8.010 s + * conversion to decimal: real time: 16.593 s, run time: 16.540 s + * 1000000 digits: + * computation of e: real time: 122.383 s, run time: 121.020 s + * conversion to decimal: real time: 252.524 s, run time: 250.760 s + * 10000000 digits: + * computation of e: real time: 2152.061 s, run time: 2056.430 s + * conversion to decimal: real time: 3579.670 s, run time: 3388.990 s + * 100000000 digits: + * computation of e: real time: 40061.367 s, run time: 30449.630 s + * conversion to decimal: real time: 54507.003 s, run time: 40063.510 s + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void +sum_exp1 (uintL a, uintL b, cl_I & first, cl_I & second) +{ + switch (b - a) + { + case 1: + first = second = b; + break; + case 2: + { + cl_I s = (a + b) >> 1; + second = s * b; + first = second + b; + } + break; + default: + { + cl_I lp, lq, rp, rq, tmp; + uintL mid = (a + b) >> 1; + sum_exp1 (a, mid, lp, lq); + sum_exp1 (mid, b, rp, rq); + tmp = lp * rq; + first = tmp + rp; + second = lq * rq; + } + break; + } +} + +void +const_exp1 (cl_LF & result, uintL dec) +{ + uintL c = (uintL) (dec * log (10)); + uintL n = dec; + uintC actuallen = (uintC)(3.321928094 * dec / intDsize); + n = (uintL) ((n + c) / log ((double)n)); + n = (uintL) ((n + c) / log ((double)n)); + n = (uintL) ((n + c) / log ((double)n)); + + n += 2; + actuallen += 2; + + cout << "n = " << n << endl; + cout << "actuallen = " << actuallen << endl; + cl_I p, q; + sum_exp1 (0, n, p, q); + cout << "sum_exp1 ends ok" << endl; + extern cl_LF cl_I_to_LF(const cl_I&, uintC); + result = The(cl_LF)(cl_I_to_LF (p, actuallen) / cl_I_to_LF (q, actuallen)); + cout << "const_exp1 returns ok" << endl; +} + +int +main (int argc, char *argv[]) +{ + int digits = 100; + while (argc >= 3) { + if (!strcmp(argv[1],"-n")) { + digits = atoi(argv[2]); + argc -= 2; argv += 2; + continue; + } + break; + } + if (argc < 1) + exit(1); + + cl_LF c1; + long l = digits; + cout << "\nCalculating exp1 to " << l << " decimals" << endl; + { CL_TIMING; + const_exp1 (c1, l); + } + { CL_TIMING; + cout << "@" << endl; + cout << c1 << endl; + cout << "@" << endl; + } +} diff --git a/examples/fibonacci.cc b/examples/fibonacci.cc new file mode 100644 index 0000000..fb80ab6 --- /dev/null +++ b/examples/fibonacci.cc @@ -0,0 +1,143 @@ +// Compute and print the n-th Fibonacci number. + +// We work with integers and real numbers. +#include +#include + +// We do I/O. +#include +#include + +// We use the timing functions. +#include + +// Declare the exit() function. +#include + +// F_n is defined through the recurrence relation +// F_0 = 0, F_1 = 1, F_(n+2) = F_(n+1) + F_n. +// The following addition formula holds: +// F_(n+m) = F_(m-1) * F_n + F_m * F_(n+1) for m >= 1, n >= 0. +// (Proof: For fixed m, the LHS and the RHS satisfy the same recurrence +// w.r.t. n, and the initial values (n=0, n=1) agree. Hence all values agree.) +// Replace m by m+1: +// F_(n+m+1) = F_m * F_n + F_(m+1) * F_(n+1) for m >= 0, n >= 0 +// Now put in m = n, to get +// F_(2n) = (F_(n+1)-F_n) * F_n + F_n * F_(n+1) = F_n * (2*F_(n+1) - F_n) +// F_(2n+1) = F_n ^ 2 + F_(n+1) ^ 2 +// hence +// F_(2n+2) = F_(n+1) * (2*F_n + F_(n+1)) + +struct twofibs { + cl_I u; // F_n + cl_I v; // F_(n+1) + // Constructor. + twofibs (const cl_I& uu, const cl_I& vv) : u (uu), v (vv) {} +}; + +// Returns F_n and F_(n+1). Assume n>=0. +static const twofibs fibonacci2 (int n) +{ + if (n==0) + return twofibs(0,1); + int m = n/2; // floor(n/2) + twofibs Fm = fibonacci2(m); + // Since a squaring is cheaper than a multiplication, better use + // three squarings instead of one multiplication and two squarings. + cl_I u2 = square(Fm.u); + cl_I v2 = square(Fm.v); + if (n==2*m) { + // n = 2*m + cl_I uv2 = square(Fm.v - Fm.u); + return twofibs(v2 - uv2, u2 + v2); + } else { + // n = 2*m+1 + cl_I uv2 = square(Fm.u + Fm.v); + return twofibs(u2 + v2, uv2 - u2); + } +} + +// Returns just F_n. Assume n>=0. +const cl_I fibonacci (int n) +{ + if (n==0) + return 0; + int m = n/2; // floor(n/2) + twofibs Fm = fibonacci2(m); + if (n==2*m) { + // n = 2*m + // Here we don't use the squaring formula because + // one multiplication is cheaper than two squarings. + cl_I& u = Fm.u; + cl_I& v = Fm.v; + return u * ((v << 1) - u); + } else { + // n = 2*m+1 + cl_I u2 = square(Fm.u); + cl_I v2 = square(Fm.v); + return u2 + v2; + } +} + +// Returns just F_n, computed as the nearest integer to +// ((1+sqrt(5))/2)^n/sqrt(5). Assume n>=0. +const cl_I fibonacci_slow (int n) +{ + // Need a precision of ((1+sqrt(5))/2)^-n. + cl_float_format_t prec = cl_float_format((int)(0.208987641*n+5)); + cl_R sqrt5 = sqrt(cl_float(5,prec)); + cl_R phi = (1+sqrt5)/2; + return round1( expt(phi,n)/sqrt5 ); +} + +#ifndef TIMING + +int main (int argc, char* argv[]) +{ + if (argc != 2) { + fprint(cl_stderr, "Usage: fibonacci n\n"); + exit(1); + } + int n = atoi(argv[1]); + fprint(cl_stdout, "fib("); + fprintdecimal(cl_stdout, n); + fprint(cl_stdout, ") = "); + fprint(cl_stdout, fibonacci(n)); + fprint(cl_stdout, "\n"); +} + +#else // TIMING + +int main (int argc, char* argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc != 2) { + fprint(cl_stderr, "Usage: fibonacci n\n"); + exit(1); + } + int n = atoi(argv[1]); + { CL_TIMING; + fprint(cl_stdout, "fib("); + fprintdecimal(cl_stdout, n); + fprint(cl_stdout, ") = "); + for (int rep = repetitions-1; rep > 0; rep--) + fibonacci(n); + fprint(cl_stdout, fibonacci(n)); + fprint(cl_stdout, "\n"); + } + { CL_TIMING; + fprint(cl_stdout, "fib("); + fprintdecimal(cl_stdout, n); + fprint(cl_stdout, ") = "); + for (int rep = repetitions-1; rep > 0; rep--) + fibonacci_slow(n); + fprint(cl_stdout, fibonacci_slow(n)); + fprint(cl_stdout, "\n"); + } +} + +#endif diff --git a/examples/legendre.cc b/examples/legendre.cc new file mode 100644 index 0000000..6441043 --- /dev/null +++ b/examples/legendre.cc @@ -0,0 +1,72 @@ +// Compute the Legendre polynomials. + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Computes the n-th Legendre polynomial in R[x], using the formula +// P_n(x) = 1/(2^n n!) * (d/dx)^n (x^2-1)^n. (Assume n >= 0.) + +const cl_UP_RA legendre (const cl_rational_ring& R, int n) +{ + cl_univpoly_rational_ring PR = cl_find_univpoly_ring(R); + cl_UP_RA b = PR->create(2); + b.set_coeff(2,1); + b.set_coeff(1,0); + b.set_coeff(0,-1); + b.finalize(); // b is now x^2-1 + cl_UP_RA p = (n==0 ? PR->one() : expt_pos(b,n)); + for (int i = 0; i < n; i++) + p = deriv(p); + cl_RA factor = recip(factorial(n)*ash(1,n)); + for (int j = degree(p); j >= 0; j--) + p.set_coeff(j, coeff(p,j) * factor); + p.finalize(); + return p; +} + +const cl_UP_MI legendre (const cl_modint_ring& R, int n) +{ + cl_univpoly_modint_ring PR = cl_find_univpoly_ring(R); + cl_UP_MI b = PR->create(2); + b.set_coeff(2,R->canonhom(1)); + b.set_coeff(1,R->canonhom(0)); + b.set_coeff(0,R->canonhom(-1)); + b.finalize(); // b is now x^2-1 + cl_UP_MI p = (n==0 ? PR->one() : expt_pos(b,n)); + for (int i = 0; i < n; i++) + p = deriv(p); + cl_MI factor = recip(R->canonhom(factorial(n)*ash(1,n))); + for (int j = degree(p); j >= 0; j--) + p.set_coeff(j, coeff(p,j) * factor); + p.finalize(); + return p; +} + +int main (int argc, char* argv[]) +{ + if (!(argc == 2 || argc == 3)) { + fprint(cl_stderr, "Usage: legendre n [m]\n"); + exit(1); + } + int n = atoi(argv[1]); + if (!(n >= 0)) { + fprint(cl_stderr, "Usage: legendre n [m] with n >= 0\n"); + exit(1); + } + if (argc == 2) { + cl_UP p = legendre(cl_RA_ring,n); + fprint(cl_stdout, p); + } else { + cl_I m = argv[2]; + cl_UP p = legendre(cl_find_modint_ring(m),n); + fprint(cl_stdout, p); + } + fprint(cl_stdout, "\n"); +} diff --git a/examples/lucaslehmer.cc b/examples/lucaslehmer.cc new file mode 100644 index 0000000..4cf7f24 --- /dev/null +++ b/examples/lucaslehmer.cc @@ -0,0 +1,82 @@ +// Check whether a mersenne number is prime, +// using the Lucas-Lehmer test. +// [Donald Ervin Knuth: The Art of Computer Programming, Vol. II: +// Seminumerical Algorithms, second edition. Section 4.5.4, p. 391.] + +// We work with integers. +#include + +// Checks whether 2^q-1 is prime, q an odd prime. +bool mersenne_prime_p (int q) +{ + cl_I m = ((cl_I)1 << q) - 1; + int i; + cl_I L_i; + for (i = 0, L_i = 4; i < q-2; i++) + L_i = mod(L_i*L_i - 2, m); + return (L_i==0); +} + +// Same thing, but optimized. +bool mersenne_prime_p_opt (int q) +{ + cl_I m = ((cl_I)1 << q) - 1; + int i; + cl_I L_i; + for (i = 0, L_i = 4; i < q-2; i++) { + L_i = square(L_i) - 2; + L_i = ldb(L_i,cl_byte(q,q)) + ldb(L_i,cl_byte(q,0)); + if (L_i >= m) + L_i = L_i - m; + } + return (L_i==0); +} + +// Now we work with modular integers. +#include + +// Same thing, but using modular integers. +bool mersenne_prime_p_modint (int q) +{ + cl_I m = ((cl_I)1 << q) - 1; + cl_modint_ring R = cl_find_modint_ring(m); // Z/mZ + int i; + cl_MI L_i; + for (i = 0, L_i = R->canonhom(4); i < q-2; i++) + L_i = R->minus(R->square(L_i),R->canonhom(2)); + return R->equal(L_i,R->zero()); +} + +#include // we do I/O +#include // declares exit() +#include + +int main (int argc, char* argv[]) +{ + if (!(argc == 2)) { + fprint(cl_stderr, "Usage: lucaslehmer exponent\n"); + exit(1); + } + int q = atoi(argv[1]); + if (!(q >= 2 && ((q % 2)==1))) { + fprint(cl_stderr, "Usage: lucaslehmer q with q odd prime\n"); + exit(1); + } + bool isprime; + { CL_TIMING; isprime = mersenne_prime_p(q); } + { CL_TIMING; isprime = mersenne_prime_p_opt(q); } + { CL_TIMING; isprime = mersenne_prime_p_modint(q); } + fprint(cl_stdout, "2^"); + fprintdecimal(cl_stdout, q); + fprint(cl_stdout, "-1 is "); + if (isprime) + fprint(cl_stdout, "prime"); + else + fprint(cl_stdout, "composite"); + fprint(cl_stdout, "\n"); +} + +// Computing time on a i486, 33 MHz: +// 1279: 2.02 s +// 2281: 8.74 s +// 44497: 14957 s diff --git a/examples/nextprime.cc b/examples/nextprime.cc new file mode 100644 index 0000000..2559eed --- /dev/null +++ b/examples/nextprime.cc @@ -0,0 +1,25 @@ +// This program prints the smallest probable prime >= x, x being given on the +// command line. + +// We work with real numbers and integers. +#include +#include + +// We do I/O. +#include +#include + +// The function nextprobprime() is part of the number theory package. +#include + +int main (int argc, char* argv[]) +{ + if (argc != 2) { + fprint(cl_stderr, "Usage: nextprime x\n"); + exit(1); + } + cl_R x = (cl_R)argv[1]; + cl_I p = nextprobprime(x); + fprint(cl_stdout, p); + fprint(cl_stdout, "\n"); +} diff --git a/examples/perfnum.cc b/examples/perfnum.cc new file mode 100644 index 0000000..2d930e9 --- /dev/null +++ b/examples/perfnum.cc @@ -0,0 +1,11 @@ +// This program prints the largest now known perfect number. + +#include +#include + +int main () +{ + int p = 1398269; // previous one was 1257787 + cl_I x = (((cl_I)1 << p) - 1) << (p-1); + cout << x << endl; +} diff --git a/include/cl_GV.h b/include/cl_GV.h new file mode 100644 index 0000000..b4ce37a --- /dev/null +++ b/include/cl_GV.h @@ -0,0 +1,299 @@ +// General vectors. + +#ifndef _CL_GV_H +#define _CL_GV_H + +#include "cl_object.h" +#include "cl_V.h" +#include "cl_abort.h" +#include + + +// A vector is a structure having the following interface: +// v.length() returns the number of elements +// v[i] returns the i-th element (0<=i class cl_GV_inner; +template class cl_GV_index; +template class cl_GV_constindex; +template struct cl_GV_vectorops; + +template +class cl_GV_inner { +protected: + uintL len; // number of elements +public: + uintL length () const; // number of elements + cl_GV_vectorops* vectorops; // get/set element + const cl_GV_index operator[] (unsigned long index); + const cl_GV_constindex operator[] (unsigned long index) const; + const cl_GV_index operator[] (long index); + const cl_GV_constindex operator[] (long index) const; + const cl_GV_index operator[] (unsigned int index); + const cl_GV_constindex operator[] (unsigned int index) const; + const cl_GV_index operator[] (int index); + const cl_GV_constindex operator[] (int index) const; +public: /* ugh */ + // Constructor. + cl_GV_inner (uintL l, cl_GV_vectorops* ops) : len (l), vectorops (ops) {} +public: + // Destructor. + ~cl_GV_inner (); + // Ability to place an object at a given address. + void* operator new (size_t size, cl_GV_inner* ptr) { (void)size; return ptr; } +private: +// No default constructor, copy constructor, assignment operator, new. + cl_GV_inner (); + cl_GV_inner (const cl_GV_inner&); + cl_GV_inner& operator= (const cl_GV_inner&); + void* operator new (size_t size) + { (void)size; return (void*)1; } // SGI CC needs this definition +// Friend declarations. They are for the compiler. Just ignore them. + friend class cl_GV_index; + friend class cl_GV_constindex; +}; + +template +class cl_GV_index { + // This is the class of objects created by accessing a non-const vector + // through []. +public: + cl_GV_inner* vec; + uintL index; + operator T () const; + // Constructor: + cl_GV_index (cl_GV_inner* v, uintL i) : vec (v), index (i) {} + // Assignment operator. + void operator= (const T& x) const; +#if (defined(__sparc__) || defined(__sparc64__) || defined(__mips__) || defined(__mips64__)) && !defined(__GNUC__) // maybe an SGI CC and Sun CC bug? + void operator= (const cl_GV_index&) const; + void operator= (const cl_GV_constindex&) const; +#else +private: + // No assignment operator. + cl_GV_index& operator= (const cl_GV_index&); +#endif +private: +// No default constructor. + cl_GV_index (); +}; + +template +class cl_GV_constindex { + // This is the class of objects created by accessing a const vector + // through []. It lacks the assignment operator. +public: + const cl_GV_inner* vec; + uintL index; + operator T () const; + // Constructor: + cl_GV_constindex (const cl_GV_inner* v, uintL i) : vec (v), index (i) {} +private: +// No default constructor, assignment operator. + cl_GV_constindex (); + cl_GV_constindex& operator= (const cl_GV_constindex&); +}; + +template +struct cl_GV_vectorops { + const T (*element) (const cl_GV_inner* vec, uintL index); + void (*set_element) (cl_GV_inner* vec, uintL index, const T& x); + void (*do_delete) (cl_GV_inner* vec); + void (*copy_elements) (const cl_GV_inner* srcvec, uintL srcindex, cl_GV_inner* destvec, uintL destindex, uintL count); +}; + +// All member functions are inline. + +template +inline uintL cl_GV_inner::length () const +{ + return len; +} + +template +inline const cl_GV_index cl_GV_inner::operator[] (unsigned long index) +{ + return cl_GV_index(this,index); +} + +template +inline const cl_GV_constindex cl_GV_inner::operator[] (unsigned long index) const +{ + return cl_GV_constindex(this,index); +} + +template +inline const cl_GV_index cl_GV_inner::operator[] (long index) +{ + return operator[]((unsigned long)index); +} + +template +inline const cl_GV_constindex cl_GV_inner::operator[] (long index) const +{ + return operator[]((unsigned long)index); +} + +template +inline const cl_GV_index cl_GV_inner::operator[] (unsigned int index) +{ + return operator[]((unsigned long)index); +} + +template +inline const cl_GV_constindex cl_GV_inner::operator[] (unsigned int index) const +{ + return operator[]((unsigned long)index); +} + +template +inline const cl_GV_index cl_GV_inner::operator[] (int index) +{ + return operator[]((unsigned long)index); +} + +template +inline const cl_GV_constindex cl_GV_inner::operator[] (int index) const +{ + return operator[]((unsigned long)index); +} + +template +inline cl_GV_inner::~cl_GV_inner () +{ + vectorops->do_delete(this); +} + +template +inline cl_GV_index::operator T () const +{ + #ifndef CL_GV_NO_RANGECHECKS + if (!(index < vec->len)) cl_abort(); + #endif + return vec->vectorops->element(vec,index); +} + +template +inline void cl_GV_index::operator= (const T& x) const +{ + #ifndef CL_GV_NO_RANGECHECKS + if (!(index < vec->len)) cl_abort(); + #endif + vec->vectorops->set_element(vec,index,x); +} + +template +inline cl_GV_constindex::operator T () const +{ + #ifndef CL_GV_NO_RANGECHECKS + if (!(index < vec->len)) cl_abort(); + #endif + return vec->vectorops->element(vec,index); +} + +#if (defined(__sparc__) || defined(__mips__) || defined(__mips64__)) && !defined(__GNUC__) // maybe an SGI CC and Sun CC bug? handle "y[j] = x[i];" +template +inline void cl_GV_index::operator= (const cl_GV_index& x) const +{ operator= ((T) x); } +template +inline void cl_GV_index::operator= (const cl_GV_constindex& x) const +{ operator= ((T) x); } +#endif + + +// In memory, a vector looks like this: + +template +struct cl_heap_GV : cl_heap { + cl_GV_inner v; + // here room for the elements +}; + +// And a reference to a vector always looks like this: + +template +struct cl_GV : public BASE { +public: + // Length. + uintL length () const + { + return ((const cl_heap_GV *) pointer)->v.length(); + } + // Reference. Forbid modification of `const cl_GV&' arguments. + const cl_GV_constindex operator[] (unsigned long index) const + { + return ((const cl_heap_GV *) pointer)->v[index]; + } + const cl_GV_index operator[] (unsigned long index) + { + return ((cl_heap_GV *) pointer)->v[index]; + } + const cl_GV_constindex operator[] (long index) const + { return operator[]((unsigned long)index); } + const cl_GV_index operator[] (long index) + { return operator[]((unsigned long)index); } + const cl_GV_constindex operator[] (unsigned int index) const + { return operator[]((unsigned long)index); } + const cl_GV_index operator[] (unsigned int index) + { return operator[]((unsigned long)index); } + const cl_GV_constindex operator[] (int index) const + { return operator[]((unsigned long)index); } + const cl_GV_index operator[] (int index) + { return operator[]((unsigned long)index); } + // Copy constructor. + cl_GV (const cl_GV&); + // Assignment operator. + cl_GV& operator= (const cl_GV&); + // Copy a piece of a vector into another vector. + // (Both vectors must be of the same type. Overlapping not allowed.) + static void copy_elements (const cl_GV& src, uintL srcindex, cl_GV& dest, uintL destindex, uintL count) + { + const cl_heap_GV * hsrc = (const cl_heap_GV *) src.pointer; + cl_heap_GV * hdest = (cl_heap_GV *) dest.pointer; + if (!(hsrc->v.vectorops == hdest->v.vectorops)) + cl_abort(); + hsrc->v.vectorops->copy_elements(&hsrc->v,srcindex,&hdest->v,destindex,count); + } + // Private pointer manipulations. + operator cl_heap_GV* () const; + cl_GV (cl_heap_GV* p) : BASE ((cl_private_thing) p) {} + cl_GV (cl_private_thing p) : BASE (p) {} +protected: + // Forbid use of default constructor. + cl_GV (); +}; +#define CL_GV(T,BASE) cl_GV +// Define copy constructor. +template + _CL_DEFINE_COPY_CONSTRUCTOR2(CL_GV(T,BASE),cl_GV,BASE) +// Define assignment operator. +template + CL_DEFINE_ASSIGNMENT_OPERATOR(CL_GV(T,BASE),CL_GV(T,BASE)) +// Private pointer manipulations. Never throw away a `struct cl_heap_GV *'! +template +inline CL_GV(T,BASE)::operator cl_heap_GV* () const +{ + cl_heap_GV* hpointer = (cl_heap_GV*)pointer; + cl_inc_refcount(*this); + return hpointer; +} +#undef CL_GV + +// The "generic" general vector type. + +typedef cl_heap_GV cl_heap_GV_any; +typedef cl_GV cl_GV_any; + + +// Hack section. + +// Conversions to subtypes without checking: + #define The(type) *(const type *) & cl_identity +// This inline function is for type checking purposes only. + inline const cl_GV_any& cl_identity (const cl_GV_any& x) { return x; } + + +#endif /* _CL_GV_H */ diff --git a/include/cl_GV_complex.h b/include/cl_GV_complex.h new file mode 100644 index 0000000..8dc30b5 --- /dev/null +++ b/include/cl_GV_complex.h @@ -0,0 +1,54 @@ +// General vectors of complex numbers. + +#ifndef _CL_GV_COMPLEX_H +#define _CL_GV_COMPLEX_H + +#include "cl_number.h" +#include "cl_GV_number.h" +#include "cl_complex_class.h" +#include "cl_io.h" + +// A vector of complex numbers is just a normal vector of numbers. + +typedef cl_heap_GV cl_heap_GV_N; + +struct cl_GV_N : public cl_GV { +public: + // Constructors. + cl_GV_N (); + cl_GV_N (const cl_GV_N&); + explicit cl_GV_N (uintL len); + // Assignment operators. + cl_GV_N& operator= (const cl_GV_N&); + // Private pointer manipulations. + cl_GV_N (cl_heap_GV_N* p) : cl_GV (p) {} + cl_GV_N (cl_private_thing p) : cl_GV (p) {} +}; +inline cl_GV_N::cl_GV_N (const cl_GV_N& x) : cl_GV (as_cl_private_thing(x)) {} +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_GV_N,cl_GV_N) +inline cl_GV_N::cl_GV_N (uintL len) + : cl_GV ((cl_heap_GV_N*) cl_make_heap_GV_number(len)) {} +inline cl_GV_N::cl_GV_N () + : cl_GV ((cl_heap_GV_N*) (cl_heap_GV_number*) cl_null_GV_number) {} + +// Copy a vector. +inline const cl_GV_N copy (const cl_GV_N& vector) +{ + return The(cl_GV_N) (copy((const cl_GV_number&) vector)); +} + +// Output. +inline void fprint (cl_ostream stream, const cl_GV_N& x) +{ + extern cl_print_flags cl_default_print_flags; + extern void print_vector (cl_ostream stream, const cl_print_flags& flags, void (* fun) (cl_ostream, const cl_print_flags&, const cl_number&), const cl_GV_number& vector); + extern void print_complex (cl_ostream stream, const cl_print_flags& flags, const cl_N& z); + print_vector(stream, cl_default_print_flags, + (void (*) (cl_ostream, const cl_print_flags&, const cl_number&)) + (void (*) (cl_ostream, const cl_print_flags&, const cl_N&)) + &print_complex, + x); +} +CL_DEFINE_PRINT_OPERATOR(cl_GV_N) + +#endif /* _CL_GV_COMPLEX_H */ diff --git a/include/cl_GV_integer.h b/include/cl_GV_integer.h new file mode 100644 index 0000000..b6f6acf --- /dev/null +++ b/include/cl_GV_integer.h @@ -0,0 +1,84 @@ +// General vectors of integers. + +#ifndef _CL_GV_INTEGER_H +#define _CL_GV_INTEGER_H + +#include "cl_number.h" +#include "cl_GV_rational.h" +#include "cl_integer_class.h" +#include "cl_io.h" + +// A vector of integers is *not* just a normal vector of numbers (the vectorops +// support the maxbits() operation), but we treat can it like this nevertheless. + +#ifdef HAVE_TEMPLATE_NULL +template <> +#endif +struct cl_heap_GV : cl_heap { + cl_GV_inner v; + // here room for the elements + sintL maxbits () const; +}; +typedef cl_heap_GV cl_heap_GV_I; + +struct cl_GV_I : public cl_GV { +public: + // Constructors. + cl_GV_I (); + cl_GV_I (const cl_GV_I&); + // Create a vector of unconstrained integers. + explicit cl_GV_I (uintL len); + // Create a vector of m-bit integers (>=0, <2^m). + cl_GV_I (uintL len, sintL m); + // Assignment operators. + cl_GV_I& operator= (const cl_GV_I&); + // Number m of bits allowed per element (-1 if unconstrained). + sintL maxbits () const + { + return ((const cl_heap_GV_I *) pointer)->maxbits(); + } + // Private pointer manipulations. + cl_GV_I (cl_heap_GV_I* p) : cl_GV (p) {} + cl_GV_I (cl_private_thing p) : cl_GV (p) {} +}; +inline cl_GV_I::cl_GV_I (const cl_GV_I& x) : cl_GV (as_cl_private_thing(x)) {} +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_GV_I,cl_GV_I) +extern cl_heap_GV_I* cl_make_heap_GV_I (uintL len); +inline cl_GV_I::cl_GV_I (uintL len) + : cl_GV (cl_make_heap_GV_I(len)) {} +extern cl_heap_GV_I* cl_make_heap_GV_I (uintL len, sintL m); +inline cl_GV_I::cl_GV_I (uintL len, sintL m) + : cl_GV (cl_make_heap_GV_I(len,m)) {} + +// Private pointer manipulations. Never throw away a `struct cl_heap_GV_I *'! +extern const cl_GV_I cl_null_GV_I; +inline cl_GV_I::cl_GV_I () + : cl_GV ((cl_heap_GV_I*) cl_null_GV_I) {} +CL_REQUIRE(cl_GV_I) + +// Copy a vector. +extern const cl_GV_I copy (const cl_GV_I&); + +// Output. +inline void fprint (cl_ostream stream, const cl_GV_I& x) +{ + extern cl_print_flags cl_default_print_flags; + extern void print_vector (cl_ostream stream, const cl_print_flags& flags, void (* fun) (cl_ostream, const cl_print_flags&, const cl_number&), const cl_GV_number& vector); + extern void print_integer (cl_ostream stream, const cl_print_flags& flags, const cl_I& z); + print_vector(stream, cl_default_print_flags, + (void (*) (cl_ostream, const cl_print_flags&, const cl_number&)) + (void (*) (cl_ostream, const cl_print_flags&, const cl_I&)) + &print_integer, + x); +} +CL_DEFINE_PRINT_OPERATOR(cl_GV_I) + +// Debugging support. +#ifdef CL_DEBUG +extern int cl_GV_I_debug_module; +static void* const cl_GV_I_debug_dummy[] = { &cl_GV_I_debug_dummy, + &cl_GV_I_debug_module +}; +#endif + +#endif /* _CL_GV_INTEGER_H */ diff --git a/include/cl_GV_modinteger.h b/include/cl_GV_modinteger.h new file mode 100644 index 0000000..d37267e --- /dev/null +++ b/include/cl_GV_modinteger.h @@ -0,0 +1,50 @@ +// General vectors of modular integers. + +#ifndef _CL_GV_MODINTEGER_H +#define _CL_GV_MODINTEGER_H + +#include "cl_modinteger.h" +#include "cl_GV_integer.h" + +// A vector of modular integers (over the same modular integer ring) +// is just a normal vector of integers, with maxbits() operation. + +#ifdef HAVE_TEMPLATE_NULL +template <> +#endif +struct cl_heap_GV<_cl_MI> : cl_heap { + cl_GV_inner<_cl_MI> v; + // here room for the elements +}; +typedef cl_heap_GV<_cl_MI> cl_heap_GV_MI; + +struct cl_GV_MI : public cl_GV<_cl_MI,cl_GV_any> { +public: + // Constructors. + cl_GV_MI (); + cl_GV_MI (const cl_GV_MI&); + // Create a vector of modular integers. + cl_GV_MI (uintL len, cl_heap_modint_ring* R); + // Assignment operators. + cl_GV_MI& operator= (const cl_GV_MI&); + // Number m of bits allowed per element (-1 if unconstrained). + sintL maxbits () const + { + return ((const cl_heap_GV_I *) pointer)->maxbits(); + } +}; +inline cl_GV_MI::cl_GV_MI (const cl_GV_MI& x) : cl_GV<_cl_MI,cl_GV_any> (as_cl_private_thing(x)) {} +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_GV_MI,cl_GV_MI) +inline cl_GV_MI::cl_GV_MI () + : cl_GV<_cl_MI,cl_GV_any> ((cl_heap_GV_MI*) (cl_heap_GV_I*) cl_null_GV_I) {} +inline cl_GV_MI::cl_GV_MI (uintL len, cl_heap_modint_ring* R) + : cl_GV<_cl_MI,cl_GV_any> ((cl_heap_GV_MI*) cl_make_heap_GV_I(len,R->bits)) {} + +// Copy a vector. +inline const cl_GV_MI copy (const cl_GV_MI& vector) +{ + return The(cl_GV_MI) (copy((const cl_GV_I&) vector)); +} + + +#endif /* _CL_GV_MODINTEGER_H */ diff --git a/include/cl_GV_number.h b/include/cl_GV_number.h new file mode 100644 index 0000000..4b5bb18 --- /dev/null +++ b/include/cl_GV_number.h @@ -0,0 +1,46 @@ +// General vectors of numbers. + +#ifndef _CL_GV_NUMBER_H +#define _CL_GV_NUMBER_H + +#include "cl_number.h" +#include "cl_GV.h" + +typedef cl_heap_GV cl_heap_GV_number; + +struct cl_GV_number : public cl_GV { +public: + // Constructors. + cl_GV_number (); + cl_GV_number (const cl_GV_number&); + explicit cl_GV_number (uintL len); + // Assignment operators. + cl_GV_number& operator= (const cl_GV_number&); + // Private pointer manipulations. + cl_GV_number (cl_heap_GV_number* p) : cl_GV (p) {} + cl_GV_number (cl_private_thing p) : cl_GV (p) {} +}; +inline cl_GV_number::cl_GV_number (const cl_GV_number& x) : cl_GV (as_cl_private_thing(x)) {} +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_GV_number,cl_GV_number) +extern cl_heap_GV_number* cl_make_heap_GV_number (uintL len); +inline cl_GV_number::cl_GV_number (uintL len) + : cl_GV (cl_make_heap_GV_number(len)) {} + +// Private pointer manipulations. Never throw away a `struct cl_heap_GV_number *'! +extern const cl_GV_number cl_null_GV_number; +inline cl_GV_number::cl_GV_number () + : cl_GV ((cl_heap_GV_number*) cl_null_GV_number) {} +CL_REQUIRE(cl_GV_number) + +// Copy a vector. +extern const cl_GV_number copy (const cl_GV_number&); + +// Debugging support. +#ifdef CL_DEBUG +extern int cl_GV_number_debug_module; +static void* const cl_GV_number_debug_dummy[] = { &cl_GV_number_debug_dummy, + &cl_GV_number_debug_module +}; +#endif + +#endif /* _CL_GV_NUMBER_H */ diff --git a/include/cl_GV_rational.h b/include/cl_GV_rational.h new file mode 100644 index 0000000..8f4a4f5 --- /dev/null +++ b/include/cl_GV_rational.h @@ -0,0 +1,54 @@ +// General vectors of rational numbers. + +#ifndef _CL_GV_RATIONAL_H +#define _CL_GV_RATIONAL_H + +#include "cl_number.h" +#include "cl_GV_real.h" +#include "cl_rational_class.h" +#include "cl_io.h" + +// A vector of rational numbers is just a normal vector of real numbers. + +typedef cl_heap_GV cl_heap_GV_RA; + +struct cl_GV_RA : public cl_GV { +public: + // Constructors. + cl_GV_RA (); + cl_GV_RA (const cl_GV_RA&); + explicit cl_GV_RA (uintL len); + // Assignment operators. + cl_GV_RA& operator= (const cl_GV_RA&); + // Private pointer manipulations. + cl_GV_RA (cl_heap_GV_RA* p) : cl_GV (p) {} + cl_GV_RA (cl_private_thing p) : cl_GV (p) {} +}; +inline cl_GV_RA::cl_GV_RA (const cl_GV_RA& x) : cl_GV (as_cl_private_thing(x)) {} +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_GV_RA,cl_GV_RA) +inline cl_GV_RA::cl_GV_RA (uintL len) + : cl_GV ((cl_heap_GV_RA*) cl_make_heap_GV_number(len)) {} +inline cl_GV_RA::cl_GV_RA () + : cl_GV ((cl_heap_GV_RA*) (cl_heap_GV_number*) cl_null_GV_number) {} + +// Copy a vector. +inline const cl_GV_RA copy (const cl_GV_RA& vector) +{ + return The(cl_GV_RA) (copy((const cl_GV_R&) vector)); +} + +// Output. +inline void fprint (cl_ostream stream, const cl_GV_RA& x) +{ + extern cl_print_flags cl_default_print_flags; + extern void print_vector (cl_ostream stream, const cl_print_flags& flags, void (* fun) (cl_ostream, const cl_print_flags&, const cl_number&), const cl_GV_number& vector); + extern void print_rational (cl_ostream stream, const cl_print_flags& flags, const cl_RA& z); + print_vector(stream, cl_default_print_flags, + (void (*) (cl_ostream, const cl_print_flags&, const cl_number&)) + (void (*) (cl_ostream, const cl_print_flags&, const cl_RA&)) + &print_rational, + x); +} +CL_DEFINE_PRINT_OPERATOR(cl_GV_RA) + +#endif /* _CL_GV_RAATIONAL_H */ diff --git a/include/cl_GV_real.h b/include/cl_GV_real.h new file mode 100644 index 0000000..f4ff825 --- /dev/null +++ b/include/cl_GV_real.h @@ -0,0 +1,54 @@ +// General vectors of real numbers. + +#ifndef _CL_GV_REAL_H +#define _CL_GV_REAL_H + +#include "cl_number.h" +#include "cl_GV_complex.h" +#include "cl_real_class.h" +#include "cl_io.h" + +// A vector of real numbers is just a normal vector of numbers. + +typedef cl_heap_GV cl_heap_GV_R; + +struct cl_GV_R : public cl_GV { +public: + // Constructors. + cl_GV_R (); + cl_GV_R (const cl_GV_R&); + explicit cl_GV_R (uintL len); + // Assignment operators. + cl_GV_R& operator= (const cl_GV_R&); + // Private pointer manipulations. + cl_GV_R (cl_heap_GV_R* p) : cl_GV (p) {} + cl_GV_R (cl_private_thing p) : cl_GV (p) {} +}; +inline cl_GV_R::cl_GV_R (const cl_GV_R& x) : cl_GV (as_cl_private_thing(x)) {} +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_GV_R,cl_GV_R) +inline cl_GV_R::cl_GV_R (uintL len) + : cl_GV ((cl_heap_GV_R*) cl_make_heap_GV_number(len)) {} +inline cl_GV_R::cl_GV_R () + : cl_GV ((cl_heap_GV_R*) (cl_heap_GV_number*) cl_null_GV_number) {} + +// Copy a vector. +inline const cl_GV_R copy (const cl_GV_R& vector) +{ + return The(cl_GV_R) (copy((const cl_GV_N&) vector)); +} + +// Output. +inline void fprint (cl_ostream stream, const cl_GV_R& x) +{ + extern cl_print_flags cl_default_print_flags; + extern void print_vector (cl_ostream stream, const cl_print_flags& flags, void (* fun) (cl_ostream, const cl_print_flags&, const cl_number&), const cl_GV_number& vector); + extern void print_real (cl_ostream stream, const cl_print_flags& flags, const cl_R& z); + print_vector(stream, cl_default_print_flags, + (void (*) (cl_ostream, const cl_print_flags&, const cl_number&)) + (void (*) (cl_ostream, const cl_print_flags&, const cl_R&)) + &print_real, + x); +} +CL_DEFINE_PRINT_OPERATOR(cl_GV_R) + +#endif /* _CL_GV_REAL_H */ diff --git a/include/cl_SV.h b/include/cl_SV.h new file mode 100644 index 0000000..f02783b --- /dev/null +++ b/include/cl_SV.h @@ -0,0 +1,180 @@ +// Simple vectors. + +#ifndef _CL_SV_H +#define _CL_SV_H + +#include "cl_object.h" +#include "cl_V.h" +#include "cl_abort.h" +#include + + +// A simple vector has the same operations as a vector, but it can store +// _only_ cl_gcobject's. +// This class is here because the general vectors always need a function +// call for getting/setting the element of a vector. Our main application +// of the general vectors are the bit vectors, needed for implementing +// polynomials over modular integer rings. I don't want that polynomials +// over other rings (in particular cl_I) be penalized by the mere existence +// of polynomials over modular integer rings. + +// When the vectors were implemented like this: +// +// cl_GV --> cl_GV --> cl_GV --> cl_GV +// +// a bit/byte-vector (of integers with limited range) could actually be +// treated correctly by all the functions which manipulate vectors of cl_N. +// This is not crucial, however. Here, we'll have disjoint sets +// +// cl_SV --> cl_SV --> cl_SV --> cl_SV +// +// cl_GV +// +// i.e. the functions which manipulate a (simple!) vector of cl_N cannot +// deal with a bit/byte-vector. +// (This is the same issue as UPGRADED-ARRAY-ELEMENT-TYPE in Common Lisp.) + +template class cl_SV_inner; + +template +class cl_SV_inner { +protected: + uintL len; // number of elements +private: +// T data[]; // the elements + T * data() { return (T *) (this+1); } + const T * data() const { return (const T *) (this+1); } +public: + uintL length () const { return len; } // number of elements + const T & operator[] (unsigned long index) const + { + #ifndef CL_SV_NO_RANGECHECKS + if (!(index < length())) cl_abort(); + #endif + return data()[index]; + } + T & operator[] (unsigned long index) + { + #ifndef CL_SV_NO_RANGECHECKS + if (!(index < length())) cl_abort(); + #endif + return data()[index]; + } + // New ANSI C++ compilers also want the following. + const T & operator[] (unsigned int index) const + { return operator[]((unsigned long)index); } + T & operator[] (unsigned int index) + { return operator[]((unsigned long)index); } + const T & operator[] (long index) const + { return operator[]((unsigned long)index); } + T & operator[] (long index) + { return operator[]((unsigned long)index); } + const T & operator[] (int index) const + { return operator[]((unsigned long)index); } + T & operator[] (int index) + { return operator[]((unsigned long)index); } +public: /* ugh */ + // Constructor. + cl_SV_inner (uintL l) : len (l) {} +public: + // Destructor. + ~cl_SV_inner (); + // Ability to place an object at a given address. + void* operator new (size_t size, cl_SV_inner* ptr) { (void)size; return ptr; } +private: +// No default constructor, copy constructor, assignment operator, new. + cl_SV_inner (); + cl_SV_inner (const cl_SV_inner&); + cl_SV_inner& operator= (const cl_SV_inner&); + void* operator new (size_t size); +}; + +// All member functions are inline. + +template +inline cl_SV_inner::~cl_SV_inner () +{ + uintL i = len; + while (i > 0) { + i--; + data()[i].~T(); + } +} + + +// In memory, a simple vector looks like this: + +template +struct cl_heap_SV : cl_heap { + cl_SV_inner v; + // here room for the elements +}; + +template +struct cl_SV : public BASE { +public: + // Length. + uintL length () const + { + return ((const cl_heap_SV *) pointer)->v.length(); + } + // Reference. Forbid modification of `const cl_SV&' arguments. + const T & operator[] (unsigned long index) const + { + return ((const cl_heap_SV *) pointer)->v[index]; + } + T & operator[] (unsigned long index) + { + return ((cl_heap_SV *) pointer)->v[index]; + } + // New ANSI C++ compilers also want the following. + const T & operator[] (unsigned int index) const + { return operator[]((unsigned long)index); } + T & operator[] (unsigned int index) + { return operator[]((unsigned long)index); } + const T & operator[] (long index) const + { return operator[]((unsigned long)index); } + T & operator[] (long index) + { return operator[]((unsigned long)index); } + const T & operator[] (int index) const + { return operator[]((unsigned long)index); } + T & operator[] (int index) + { return operator[]((unsigned long)index); } + // Constructors. + cl_SV (const cl_SV&); + // Assignment operators. + cl_SV& operator= (const cl_SV&); + // Private pointer manipulations. + cl_SV (cl_heap_SV* p) : BASE ((cl_private_thing)p) {} + cl_SV (cl_private_thing p) : BASE (p) {} +protected: + // Forbid use of default constructor. + cl_SV (); +}; +#define CL_SV(T,BASE) cl_SV +// Define copy constructor. +template + _CL_DEFINE_COPY_CONSTRUCTOR2(CL_SV(T,BASE),cl_SV,BASE) +// Define assignment operator. +template + CL_DEFINE_ASSIGNMENT_OPERATOR(CL_SV(T,BASE),CL_SV(T,BASE)) +#undef CL_SV + +// The "generic" simple vector type. + +typedef cl_heap_SV cl_heap_SV_any; +typedef cl_SV cl_SV_any; + +// Copy a simple vector. +extern const cl_SV_any copy (const cl_SV_any&); + + +// Hack section. + +// Conversions to subtypes without checking: + #define The(type) *(const type *) & cl_identity +// This inline function is for type checking purposes only. + inline const cl_SV_any& cl_identity (const cl_SV_any& x) { return x; } + + +#endif /* _CL_SV_H */ diff --git a/include/cl_SV_complex.h b/include/cl_SV_complex.h new file mode 100644 index 0000000..61bdec7 --- /dev/null +++ b/include/cl_SV_complex.h @@ -0,0 +1,50 @@ +// Simple vectors of complex numbers. + +#ifndef _CL_SV_COMPLEX_H +#define _CL_SV_COMPLEX_H + +#include "cl_number.h" +#include "cl_SV_number.h" +#include "cl_complex_class.h" +#include "cl_io.h" + +// A vector of complex numbers is just a normal vector of numbers. + +typedef cl_heap_SV cl_heap_SV_N; + +struct cl_SV_N : public cl_SV { +public: + // Constructors. + cl_SV_N () : cl_SV ((cl_heap_SV_N*) (cl_heap_SV_number*) cl_null_SV_number) {}; + cl_SV_N (const cl_SV_N&); + explicit cl_SV_N (uintL len) : cl_SV ((cl_heap_SV_N*) cl_make_heap_SV_number(len)) {}; + // Assignment operators. + cl_SV_N& operator= (const cl_SV_N&); + // Private pointer manipulations. + cl_SV_N (cl_heap_SV_N* p) : cl_SV (p) {} + cl_SV_N (cl_private_thing p) : cl_SV (p) {} +}; +inline cl_SV_N::cl_SV_N (const cl_SV_N& x) : cl_SV (as_cl_private_thing(x)) {} +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_SV_N,cl_SV_N) + +// Copy a simple vector. +inline const cl_SV_N copy (const cl_SV_N& vector) +{ + return The(cl_SV_N) (copy((const cl_SV_number&) vector)); +} + +// Output. +inline void fprint (cl_ostream stream, const cl_SV_N& x) +{ + extern cl_print_flags cl_default_print_flags; + extern void print_vector (cl_ostream stream, const cl_print_flags& flags, void (* fun) (cl_ostream, const cl_print_flags&, const cl_number&), const cl_SV_number& vector); + extern void print_complex (cl_ostream stream, const cl_print_flags& flags, const cl_N& z); + print_vector(stream, cl_default_print_flags, + (void (*) (cl_ostream, const cl_print_flags&, const cl_number&)) + (void (*) (cl_ostream, const cl_print_flags&, const cl_N&)) + &print_complex, + x); +} +CL_DEFINE_PRINT_OPERATOR(cl_SV_N) + +#endif /* _CL_SV_COMPLEX_H */ diff --git a/include/cl_SV_integer.h b/include/cl_SV_integer.h new file mode 100644 index 0000000..29417c2 --- /dev/null +++ b/include/cl_SV_integer.h @@ -0,0 +1,47 @@ +// Simple vectors of integers. + +#ifndef _CL_SV_INTEGER_H +#define _CL_SV_INTEGER_H + +#include "cl_number.h" +#include "cl_SV_rational.h" +#include "cl_integer_class.h" +#include "cl_io.h" + +// A vector of integers is just a normal vector of rational numbers. + +typedef cl_heap_SV cl_heap_SV_I; + +struct cl_SV_I : public cl_SV { +public: + // Constructors. + cl_SV_I () : cl_SV ((cl_heap_SV_I*) (cl_heap_SV_number*) cl_null_SV_number) {}; + cl_SV_I (const cl_SV_I&); + explicit cl_SV_I (uintL len) : cl_SV ((cl_heap_SV_I*) cl_make_heap_SV_number(len)) {}; + // Assignment operators. + cl_SV_I& operator= (const cl_SV_I&); +}; +inline cl_SV_I::cl_SV_I (const cl_SV_I& x) : cl_SV (as_cl_private_thing(x)) {} +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_SV_I,cl_SV_I) + +// Copy a simple vector. +inline const cl_SV_I copy (const cl_SV_I& vector) +{ + return The(cl_SV_I) (copy((const cl_SV_RA&) vector)); +} + +// Output. +inline void fprint (cl_ostream stream, const cl_SV_I& x) +{ + extern cl_print_flags cl_default_print_flags; + extern void print_vector (cl_ostream stream, const cl_print_flags& flags, void (* fun) (cl_ostream, const cl_print_flags&, const cl_number&), const cl_SV_number& vector); + extern void print_integer (cl_ostream stream, const cl_print_flags& flags, const cl_I& z); + print_vector(stream, cl_default_print_flags, + (void (*) (cl_ostream, const cl_print_flags&, const cl_number&)) + (void (*) (cl_ostream, const cl_print_flags&, const cl_I&)) + &print_integer, + x); +} +CL_DEFINE_PRINT_OPERATOR(cl_SV_I) + +#endif /* _CL_SV_INTEGER_H */ diff --git a/include/cl_SV_number.h b/include/cl_SV_number.h new file mode 100644 index 0000000..fb1f344 --- /dev/null +++ b/include/cl_SV_number.h @@ -0,0 +1,58 @@ +// Simple vectors of numbers. + +#ifndef _CL_SV_NUMBER_H +#define _CL_SV_NUMBER_H + +#include "cl_number.h" +#include "cl_SV.h" +#include "cl_io.h" + +typedef cl_heap_SV cl_heap_SV_number; + +struct cl_SV_number : public cl_SV { +public: + // Constructors. + cl_SV_number (); + cl_SV_number (const cl_SV_number&); + explicit cl_SV_number (uintL len); + // Assignment operators. + cl_SV_number& operator= (const cl_SV_number&); + // Private pointer manipulations. + operator cl_heap_SV_number* () const; + cl_SV_number (cl_heap_SV_number* p) : cl_SV (p) {} + cl_SV_number (cl_private_thing p) : cl_SV (p) {} +}; +inline cl_SV_number::cl_SV_number (const cl_SV_number& x) : cl_SV (as_cl_private_thing(x)) {} +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_SV_number,cl_SV_number) +// Returns a new simple vector with uninitialized contents. +extern cl_heap_SV_number* cl_make_heap_SV_number_uninit (uintL len); +// Returns a new simple vector with all elements initialized to 0. +extern cl_heap_SV_number* cl_make_heap_SV_number (uintL len); +inline cl_SV_number::cl_SV_number (uintL len) + : cl_SV (cl_make_heap_SV_number(len)) {} + +// Private pointer manipulations. Never throw away a `struct cl_heap_SV_number *'! +inline cl_SV_number::operator cl_heap_SV_number* () const +{ + cl_heap_SV_number* hpointer = (cl_heap_SV_number*)pointer; + cl_inc_refcount(*this); + return hpointer; +} +extern const cl_SV_number cl_null_SV_number; +inline cl_SV_number::cl_SV_number () + : cl_SV ((cl_heap_SV_number*) cl_null_SV_number) {} +CL_REQUIRE(cl_SV_number) + +// Copy a simple vector. +inline const cl_SV_number copy (const cl_SV_number& vector) +{ return The(cl_SV_number) (copy((const cl_SV_any&) vector)); } + +// Debugging support. +#ifdef CL_DEBUG +extern int cl_SV_number_debug_module; +static void* const cl_SV_number_debug_dummy[] = { &cl_SV_number_debug_dummy, + &cl_SV_number_debug_module +}; +#endif + +#endif /* _CL_SV_NUMBER_H */ diff --git a/include/cl_SV_rational.h b/include/cl_SV_rational.h new file mode 100644 index 0000000..44e58af --- /dev/null +++ b/include/cl_SV_rational.h @@ -0,0 +1,50 @@ +// Simple vectors of rational numbers. + +#ifndef _CL_SV_RATIONAL_H +#define _CL_SV_RATIONAL_H + +#include "cl_number.h" +#include "cl_SV_real.h" +#include "cl_rational_class.h" +#include "cl_io.h" + +// A vector of rational numbers is just a normal vector of real numbers. + +typedef cl_heap_SV cl_heap_SV_RA; + +struct cl_SV_RA : public cl_SV { +public: + // Constructors. + cl_SV_RA () : cl_SV ((cl_heap_SV_RA*) (cl_heap_SV_number*) cl_null_SV_number) {}; + cl_SV_RA (const cl_SV_RA&); + explicit cl_SV_RA (uintL len) : cl_SV ((cl_heap_SV_RA*) cl_make_heap_SV_number(len)) {}; + // Assignment operators. + cl_SV_RA& operator= (const cl_SV_RA&); + // Private pointer manipulations. + cl_SV_RA (cl_heap_SV_RA* p) : cl_SV (p) {} + cl_SV_RA (cl_private_thing p) : cl_SV (p) {} +}; +inline cl_SV_RA::cl_SV_RA (const cl_SV_RA& x) : cl_SV (as_cl_private_thing(x)) {} +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_SV_RA,cl_SV_RA) + +// Copy a simple vector. +inline const cl_SV_RA copy (const cl_SV_RA& vector) +{ + return The(cl_SV_RA) (copy((const cl_SV_R&) vector)); +} + +// Output. +inline void fprint (cl_ostream stream, const cl_SV_RA& x) +{ + extern cl_print_flags cl_default_print_flags; + extern void print_vector (cl_ostream stream, const cl_print_flags& flags, void (* fun) (cl_ostream, const cl_print_flags&, const cl_number&), const cl_SV_number& vector); + extern void print_rational (cl_ostream stream, const cl_print_flags& flags, const cl_RA& z); + print_vector(stream, cl_default_print_flags, + (void (*) (cl_ostream, const cl_print_flags&, const cl_number&)) + (void (*) (cl_ostream, const cl_print_flags&, const cl_RA&)) + &print_rational, + x); +} +CL_DEFINE_PRINT_OPERATOR(cl_SV_RA) + +#endif /* _CL_SV_RAATIONAL_H */ diff --git a/include/cl_SV_real.h b/include/cl_SV_real.h new file mode 100644 index 0000000..12cf25d --- /dev/null +++ b/include/cl_SV_real.h @@ -0,0 +1,50 @@ +// Simple vectors of real numbers. + +#ifndef _CL_SV_REAL_H +#define _CL_SV_REAL_H + +#include "cl_number.h" +#include "cl_SV_complex.h" +#include "cl_real_class.h" +#include "cl_io.h" + +// A vector of real numbers is just a normal vector of numbers. + +typedef cl_heap_SV cl_heap_SV_R; + +struct cl_SV_R : public cl_SV { +public: + // Constructors. + cl_SV_R () : cl_SV ((cl_heap_SV_R*) (cl_heap_SV_number*) cl_null_SV_number) {}; + cl_SV_R (const cl_SV_R&); + explicit cl_SV_R (uintL len) : cl_SV ((cl_heap_SV_R*) cl_make_heap_SV_number(len)) {}; + // Assignment operators. + cl_SV_R& operator= (const cl_SV_R&); + // Private pointer manipulations. + cl_SV_R (cl_heap_SV_R* p) : cl_SV (p) {} + cl_SV_R (cl_private_thing p) : cl_SV (p) {} +}; +inline cl_SV_R::cl_SV_R (const cl_SV_R& x) : cl_SV (as_cl_private_thing(x)) {} +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_SV_R,cl_SV_R) + +// Copy a simple vector. +inline const cl_SV_R copy (const cl_SV_R& vector) +{ + return The(cl_SV_R) (copy((const cl_SV_N&) vector)); +} + +// Output. +inline void fprint (cl_ostream stream, const cl_SV_R& x) +{ + extern cl_print_flags cl_default_print_flags; + extern void print_vector (cl_ostream stream, const cl_print_flags& flags, void (* fun) (cl_ostream, const cl_print_flags&, const cl_number&), const cl_SV_number& vector); + extern void print_real (cl_ostream stream, const cl_print_flags& flags, const cl_R& z); + print_vector(stream, cl_default_print_flags, + (void (*) (cl_ostream, const cl_print_flags&, const cl_number&)) + (void (*) (cl_ostream, const cl_print_flags&, const cl_R&)) + &print_real, + x); +} +CL_DEFINE_PRINT_OPERATOR(cl_SV_R) + +#endif /* _CL_SV_REAL_H */ diff --git a/include/cl_SV_ringelt.h b/include/cl_SV_ringelt.h new file mode 100644 index 0000000..15a6957 --- /dev/null +++ b/include/cl_SV_ringelt.h @@ -0,0 +1,62 @@ +// Simple vectors of ring elements. + +#ifndef _CL_SV_RINGELT_H +#define _CL_SV_RINGELT_H + +#include "cl_ring.h" +#include "cl_SV.h" +#include "cl_io.h" + +typedef cl_heap_SV<_cl_ring_element> cl_heap_SV_ringelt; + +struct cl_SV_ringelt : public cl_SV<_cl_ring_element,cl_SV_any> { +public: + // Constructors. + cl_SV_ringelt (); + cl_SV_ringelt (const cl_SV_ringelt&); + explicit cl_SV_ringelt (uintL len); + // Assignment operators. + cl_SV_ringelt& operator= (const cl_SV_ringelt&); + // Private pointer manipulations. + operator cl_heap_SV_ringelt* () const; + cl_SV_ringelt (cl_heap_SV_ringelt* p) : cl_SV<_cl_ring_element,cl_SV_any> (p) {} + cl_SV_ringelt (cl_private_thing p) : cl_SV<_cl_ring_element,cl_SV_any> (p) {} +}; +inline cl_SV_ringelt::cl_SV_ringelt (const cl_SV_ringelt& x) : cl_SV<_cl_ring_element,cl_SV_any> (as_cl_private_thing(x)) {} +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_SV_ringelt,cl_SV_ringelt) +// Returns a new simple vector with uninitialized contents. +extern cl_heap_SV_ringelt* cl_make_heap_SV_ringelt_uninit (uintL len); +// Returns a new simple vector with all elements initialized to some value. +extern cl_heap_SV_ringelt* cl_make_heap_SV_ringelt (uintL len); +inline cl_SV_ringelt::cl_SV_ringelt (uintL len) + : cl_SV<_cl_ring_element,cl_SV_any> (cl_make_heap_SV_ringelt(len)) {} + +// Private pointer manipulations. +// Never throw away a `struct cl_heap_SV_ringelt *'! +inline cl_SV_ringelt::operator cl_heap_SV_ringelt* () const +{ + cl_heap_SV_ringelt* hpointer = (cl_heap_SV_ringelt*)pointer; + cl_inc_refcount(*this); + return hpointer; +} +extern const cl_SV_ringelt cl_null_SV_ringelt; +inline cl_SV_ringelt::cl_SV_ringelt () + : cl_SV<_cl_ring_element,cl_SV_any> ((cl_heap_SV_ringelt*) cl_null_SV_ringelt) {} +CL_REQUIRE(cl_SV_ringelt) + +// Copy a simple vector. +inline const cl_SV_ringelt copy (const cl_SV_ringelt& vector) +{ return The(cl_SV_ringelt) (copy((const cl_SV_any&) vector)); } + +// Output. +extern void fprint (cl_ostream stream, const cl_ring& R, const cl_SV_ringelt& x); + +// Debugging support. +#ifdef CL_DEBUG +extern int cl_SV_ringelt_debug_module; +static void* const cl_SV_ringelt_debug_dummy[] = { &cl_SV_ringelt_debug_dummy, + &cl_SV_ringelt_debug_module +}; +#endif + +#endif /* _CL_SV_RINGELT_H */ diff --git a/include/cl_V.h b/include/cl_V.h new file mode 100644 index 0000000..44dffcf --- /dev/null +++ b/include/cl_V.h @@ -0,0 +1,19 @@ +// Vectors. + +#ifndef _CL_V_H +#define _CL_V_H + +#include "cl_object.h" + +struct cl_V_any : public cl_gcpointer { + // Constructors. + cl_V_any () {} + cl_V_any (const cl_V_any&); + cl_V_any (cl_private_thing p) : cl_gcpointer (p) {} + // Assignment operators. + cl_V_any& operator= (const cl_V_any&); +}; +CL_DEFINE_COPY_CONSTRUCTOR2(cl_V_any,cl_gcpointer) +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_V_any,cl_V_any) + +#endif /* _CL_V_H */ diff --git a/include/cl_abort.h b/include/cl_abort.h new file mode 100644 index 0000000..189b3a1 --- /dev/null +++ b/include/cl_abort.h @@ -0,0 +1,12 @@ +// Abnormal program exit. + +#ifndef _CL_ABORT_H +#define _CL_ABORT_H + +#ifdef _CL_MACROS_H +nonreturning_function(extern, cl_abort, (void)); +#else +extern void cl_abort (void); +#endif + +#endif /* _CL_ABORT_H */ diff --git a/include/cl_complex.h b/include/cl_complex.h new file mode 100644 index 0000000..5cca361 --- /dev/null +++ b/include/cl_complex.h @@ -0,0 +1,157 @@ +// Public complex number operations. + +#ifndef _CL_COMPLEX_H +#define _CL_COMPLEX_H + +#include "cl_number.h" +#include "cl_complex_class.h" +#include "cl_real_class.h" +#include "cl_integer_class.h" + + +CL_DEFINE_AS_CONVERSION(cl_N) + + +// zerop(x) testet, ob (= x 0). +extern cl_boolean zerop (const cl_N& x); + + +// Liefert zu reellen Zahlen a und b die komplexe Zahl a+bi. +// complex(a,b) +extern const cl_N complex (const cl_R& a, const cl_R& b); + +// realpart(x) liefert den Realteil der Zahl x. +extern const cl_R realpart (const cl_N& x); + +// imagpart(x) liefert den Imaginärteil der Zahl x. +extern const cl_R imagpart (const cl_N& x); + +// conjugate(x) liefert die konjugiert komplexe Zahl zur Zahl x. +extern const cl_N conjugate (const cl_N& x); + + +// Liefert (- x), wo x eine Zahl ist. +extern const cl_N operator- (const cl_N& x); + +// Liefert (+ x y), wo x und y Zahlen sind. +extern const cl_N operator+ (const cl_N& x, const cl_N& y); + +// Liefert (- x y), wo x und y Zahlen sind. +extern const cl_N operator- (const cl_N& x, const cl_N& y); + +// Liefert (* x y), wo x und y Zahlen sind. +extern const cl_N operator* (const cl_N& x, const cl_N& y); + +// Liefert (* x x), wo x eine Zahl ist. +extern const cl_N square (const cl_N& x); + +// Liefert (/ x y), wo x und y Zahlen sind. +extern const cl_N operator/ (const cl_N& x, const cl_N& y); + +// Liefert (abs x), wo x eine Zahl ist. +extern const cl_R abs (const cl_N& x); + +// recip(x) liefert (/ x), wo x eine Zahl ist. +extern const cl_N recip (const cl_N& x); + +// (1+ x), wo x eine Zahl ist. +extern const cl_N plus1 (const cl_N& x); + +// (1- x), wo x eine Zahl ist. +extern const cl_N minus1 (const cl_N& x); + +// signum(x) liefert (signum x), wo x eine Zahl ist. +extern const cl_N signum (const cl_N& x); + +// sqrt(x) = (sqrt x) zieht die Wurzel aus einer Zahl x. +extern const cl_N sqrt (const cl_N& x); + +// cl_equal(x,y) vergleicht zwei Zahlen x und y auf Gleichheit. +extern cl_boolean cl_equal (const cl_N& x, const cl_N& y); +// cl_equal_hashcode(x) liefert einen cl_equal-invarianten Hashcode für x. +extern uint32 cl_equal_hashcode (const cl_N& x); + +inline bool operator== (const cl_N& x, const cl_N& y) + { return cl_equal(x,y); } +inline bool operator!= (const cl_N& x, const cl_N& y) + { return !cl_equal(x,y); } + +// phase(x) liefert (phase x), wo x eine Zahl ist. +// Ergebnis rational nur wenn (= x 0) oder wenn x reell und >0. +extern const cl_R phase (const cl_N& x); + +// exp(x) liefert (exp x), wo x eine Zahl ist. +extern const cl_N exp (const cl_N& x); + +// log(x) liefert (log x), wo x eine Zahl ist. +extern const cl_N log (const cl_N& x); + +// log(a,b) liefert (log a b), wo a und b Zahlen sind. +extern const cl_N log (const cl_N& a, const cl_N& b); + +// (expt x y), wo x eine Zahl und y ein Integer ist. +extern const cl_N expt (const cl_N& x, sintL y); +extern const cl_N expt (const cl_N& x, const cl_I& y); + +// (expt x y), wo x und y Zahlen sind. +extern const cl_N expt (const cl_N& x, const cl_N& y); + +// sin(x) liefert (sin x), wo x eine Zahl ist. +extern const cl_N sin (const cl_N& x); + +// cos(x) liefert (cos x), wo x eine Zahl ist. +extern const cl_N cos (const cl_N& x); + +// tan(x) liefert (tan x), wo x eine Zahl ist. +extern const cl_N tan (const cl_N& x); + +// cis(x) liefert (cis x), wo x eine Zahl ist. +extern const cl_N cis (const cl_R& x); +extern const cl_N cis (const cl_N& x); + +// sinh(x) liefert (sinh x), wo x eine Zahl ist. +extern const cl_N sinh (const cl_N& x); + +// cosh(x) liefert (cosh x), wo x eine Zahl ist. +extern const cl_N cosh (const cl_N& x); + +// tanh(x) liefert (tanh x), wo x eine Zahl ist. +extern const cl_N tanh (const cl_N& x); + +// atan(z) liefert den Arctan einer Zahl z. +extern const cl_N atan (const cl_N& z); + +// atanh(z) liefert den Artanh einer Zahl z. +extern const cl_N atanh (const cl_N& z); + +// asin(z) liefert den Arcsin einer Zahl z. +extern const cl_N asin (const cl_N& z); + +// asinh(z) liefert den Arsinh einer Zahl z. +extern const cl_N asinh (const cl_N& z); + +// acos(z) liefert den Arccos einer Zahl z. +extern const cl_N acos (const cl_N& z); + +// acosh(z) liefert den Arcosh einer Zahl z. +extern const cl_N acosh (const cl_N& z); + + +#ifdef WANT_OBFUSCATING_OPERATORS +// This could be optimized to use in-place operations. +inline cl_N& operator+= (cl_N& x, const cl_N& y) { return x = x + y; } +inline cl_N& operator++ /* prefix */ (cl_N& x) { return x = plus1(x); } +inline void operator++ /* postfix */ (cl_N& x, int dummy) { (void)dummy; x = plus1(x); } +inline cl_N& operator-= (cl_N& x, const cl_N& y) { return x = x - y; } +inline cl_N& operator-- /* prefix */ (cl_N& x) { return x = minus1(x); } +inline void operator-- /* postfix */ (cl_N& x, int dummy) { (void)dummy; x = minus1(x); } +inline cl_N& operator*= (cl_N& x, const cl_N& y) { return x = x * y; } +inline cl_N& operator/= (cl_N& x, const cl_N& y) { return x = x / y; } +#endif + + +// Runtime typing support. +extern cl_class cl_class_complex; + + +#endif /* _CL_COMPLEX_H */ diff --git a/include/cl_complex_class.h b/include/cl_complex_class.h new file mode 100644 index 0000000..44c5ae3 --- /dev/null +++ b/include/cl_complex_class.h @@ -0,0 +1,63 @@ +// Abstract class of complex numbers. + +#ifndef _CL_COMPLEX_CLASS_H +#define _CL_COMPLEX_CLASS_H + +#include "cl_number.h" + + +class cl_N : public cl_number { +public: +// Default constructor. + cl_N (); +// Copy constructor. + cl_N (const cl_N&); +// Converters. +// Assignment operators. + cl_N& operator= (const cl_N&); +// Constructors and assignment operators from C numeric types. + cl_N (const int); // |argument| must be < 2^29 + cl_N (const unsigned int); // argument must be < 2^29 + cl_N (const long); + cl_N (const unsigned long); + cl_N (const float); + cl_N (const double); + cl_N& operator= (const int); // |argument| must be < 2^29 + cl_N& operator= (const unsigned int); // argument must be < 2^29 + cl_N& operator= (const long); + cl_N& operator= (const unsigned long); + cl_N& operator= (const float); + cl_N& operator= (const double); +// Other constructors. + cl_N (const char *); +// Private constructor. + cl_N (cl_private_thing); + cl_N (struct cl_heap_complex *); +public: // Ability to place an object at a given address. + void* operator new (size_t size) { return cl_malloc_hook(size); } + void* operator new (size_t size, cl_N* ptr) { (void)size; return ptr; } + void operator delete (void* ptr) { cl_free_hook(ptr); } +private: +// Friend declarations. They are for the compiler. Just ignore them. +}; + +// Private constructors. +inline cl_N::cl_N (cl_private_thing ptr) : cl_number (ptr) {} +// The assignment operators: +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_N, cl_N) +// The default constructors. +inline cl_N::cl_N () + : cl_number ((cl_private_thing) cl_combine(cl_FN_tag,0)) {} +// The copy constructors. +CL_DEFINE_COPY_CONSTRUCTOR2(cl_N,cl_number) +// Constructors and assignment operators from C numeric types. +CL_DEFINE_INT_CONSTRUCTORS(cl_N) +CL_DEFINE_INT_ASSIGNMENT_OPERATORS(cl_N) +CL_DEFINE_LONG_CONSTRUCTORS(cl_N) +CL_DEFINE_LONG_ASSIGNMENT_OPERATORS(cl_N) +// Constructors and assignment operators from C numeric types. +CL_DEFINE_FLOAT_CONSTRUCTOR(cl_N) +CL_DEFINE_DOUBLE_CONSTRUCTOR(cl_N) + + +#endif /* _CL_COMPLEX_CLASS_H */ diff --git a/include/cl_complex_io.h b/include/cl_complex_io.h new file mode 100644 index 0000000..79b1d64 --- /dev/null +++ b/include/cl_complex_io.h @@ -0,0 +1,46 @@ +// I/O of complex numbers. + +#ifndef _CL_COMPLEX_IO_H +#define _CL_COMPLEX_IO_H + +#include "cl_number_io.h" +#include "cl_complex.h" + + +// Undocumented input functions + +extern const cl_N read_complex (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse); +extern const cl_N read_complex (cl_istream stream, const cl_read_flags& flags); + +// Documented input functions + +inline cl_istream operator>> (cl_istream stream, cl_N& result) +{ + extern cl_read_flags cl_N_read_flags; + result = read_complex(stream,cl_N_read_flags); + return stream; +} + + +// Undocumented output functions + + +// Documented output functions + +// Gibt eine komplexe Zahl aus. +// print_complex(stream,z); +// > z: komplexe Zahl +// > stream: Stream +extern void print_complex (cl_ostream stream, const cl_print_flags& flags, const cl_N& z); +extern void print_complex (cl_ostream stream, const cl_print_number_flags& flags, const cl_N& z); + +inline void fprint (cl_ostream stream, const cl_N& x) +{ + extern cl_print_flags cl_default_print_flags; + print_complex(stream,cl_default_print_flags,x); +} + +CL_DEFINE_PRINT_OPERATOR(cl_N) + + +#endif /* _CL_COMPLEX_IO_H */ diff --git a/include/cl_complex_ring.h b/include/cl_complex_ring.h new file mode 100644 index 0000000..ed8f4a1 --- /dev/null +++ b/include/cl_complex_ring.h @@ -0,0 +1,14 @@ +// Built-in complex number ring. + +#ifndef _CL_COMPLEX_RING_H +#define _CL_COMPLEX_RING_H + +#include "cl_ring.h" +#include "cl_complex_class.h" + +typedef cl_specialized_number_ring cl_complex_ring; +extern const cl_complex_ring cl_C_ring; // math. C +extern cl_class cl_class_complex_ring; +//CL_REQUIRE(cl_C_ring) + +#endif /* _CL_COMPLEX_RING_H */ diff --git a/include/cl_condition.h b/include/cl_condition.h new file mode 100644 index 0000000..ff17c89 --- /dev/null +++ b/include/cl_condition.h @@ -0,0 +1,40 @@ +// Conditions (a.k.a. exceptions) + +#ifndef _CL_CONDITION_H +#define _CL_CONDITION_H + +#include "cl_malloc.h" +#include "cl_io.h" + +struct cl_condition { + // Allocation. + void* operator new (size_t size) { return cl_malloc_hook(size); } + // Deallocation. + void operator delete (void* ptr) { cl_free_hook(ptr); } + // Name. + virtual const char * name () const = 0; + // Print. + virtual void print (cl_ostream) const = 0; + // Virtual destructor. + virtual ~cl_condition () + #if defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 8) // workaround gcc bug + {} + #else + = 0; + #endif +private: + virtual void dummy (); +}; +#define SUBCLASS_cl_condition() \ +public: \ + /* Allocation. */ \ + void* operator new (size_t size) { return cl_malloc_hook(size); } \ + /* Deallocation. */ \ + void operator delete (void* ptr) { cl_free_hook(ptr); } + +// Functions which want to raise a condition return a `cl_condition*'. +// The caller checks this value. NULL means no condition. The one who +// disposes the condition (handles it without resignalling it) should +// call `delete' on the condition pointer. + +#endif /* _CL_CONDITION_H */ diff --git a/include/cl_config.h.in b/include/cl_config.h.in new file mode 100644 index 0000000..de06402 --- /dev/null +++ b/include/cl_config.h.in @@ -0,0 +1,119 @@ +// Defines CPU and compiler dependent macros + +#ifndef _CL_CONFIG_H +#define _CL_CONFIG_H + +/* These definitions are adjusted by `configure' automatically. */ + +/* CPU */ +#ifndef __i386__ +#undef __i386__ +#endif +#ifndef __m68k__ +#undef __m68k__ +#endif +#ifndef __mips__ +#undef __mips__ +#endif +#ifndef __mips64__ +#undef __mips64__ +#endif +#ifndef __sparc__ +#undef __sparc__ +#endif +#ifndef __sparc64__ +#undef __sparc64__ +#endif +#ifndef __alpha__ +#undef __alpha__ +#endif +#ifndef __hppa__ +#undef __hppa__ +#endif +#ifndef __arm__ +#undef __arm__ +#endif +#ifndef __rs6000__ +#undef __rs6000__ +#endif +#ifndef __m88k__ +#undef __m88k__ +#endif +#ifndef __convex__ +#undef __convex__ +#endif + + +/* assembler syntax */ + +/* CL_AS_UNDERSCORE */ +/* Define if C symbols are prefixed by an underscore in assembly language. */ +#undef ASM_UNDERSCORE + + +/* compiler characteristics */ + +/* CL_BOOL */ +/* Define if your compiler understands the bool type. */ +#undef HAVE_BOOL +/* Define this as `int' if your compiler doesn't understand the bool type. */ +#undef bool + +/* CL_LONGLONG */ +/* Define if your compiler supports the `long long' type. */ +#undef HAVE_LONGLONG + +/* CL_LONGDOUBLE */ +/* Define if your compiler supports the `long double' type. */ +#undef HAVE_LONGDOUBLE + +/* CL_TEMPLATE_NULL */ +/* Define if your compiler supports the `template <>' syntax. */ +#undef HAVE_TEMPLATE_NULL + + +/* header files */ + +/* CL_UNISTD_H */ +/* Define if you have . */ +#undef HAVE_UNISTD_H + + +/* functions and declarations */ + +/* CL_ALLOCA */ +/* Define if you have and it should be used (not Ultrix). */ +#undef HAVE_ALLOCA_H +/* Define if you need to link with an external alloca.o when using alloca(). */ +#undef NO_ALLOCA + + +/* compiler characteristics */ + +/* CL_GLOBAL_CONSTRUCTORS */ +/* Define as the prefix of the name of a module's global constructor function, + cf. macro FILE_FUNCTION_FORMAT in gcc/tree.c. */ +#ifndef CL_GLOBAL_CONSTRUCTOR_PREFIX +#undef CL_GLOBAL_CONSTRUCTOR_PREFIX +#endif +/* Define as the prefix of the name of a module's global destructor function, + cf. macro FILE_FUNCTION_FORMAT in gcc/tree.c. */ +#ifndef CL_GLOBAL_DESTRUCTOR_PREFIX +#undef CL_GLOBAL_DESTRUCTOR_PREFIX +#endif +/* Define if a module's global constructor function and global destructor + function need to be exported in order to be accessible from other modules. */ +#undef CL_NEED_GLOBALIZE_CTORDTOR + +/* CL_CHAR_UNSIGNED */ +#ifndef __CHAR_UNSIGNED__ +#undef __CHAR_UNSIGNED__ +#endif + +/* CL_MACHINE */ +/* see cl_intparam.h */ +/* see cl_floatparam.h */ + + +#endif /* _CL_CONFIG_H */ + diff --git a/include/cl_dfloat.h b/include/cl_dfloat.h new file mode 100644 index 0000000..60821cf --- /dev/null +++ b/include/cl_dfloat.h @@ -0,0 +1,305 @@ +// Public double float operations. + +#ifndef _CL_DFLOAT_H +#define _CL_DFLOAT_H + +#include "cl_number.h" +#include "cl_dfloat_class.h" +#include "cl_integer_class.h" +#include "cl_float.h" + + +CL_DEFINE_AS_CONVERSION(cl_DF) + + +// Liefert zu einem Double-Float x : (- x), ein DF. +extern const cl_DF operator- (const cl_DF& x); + +// cl_compare(x,y) vergleicht zwei Double-Floats x und y. +// Ergebnis: 0 falls x=y, +1 falls x>y, -1 falls x= (const cl_DF& x, const cl_DF& y) + { return cl_compare(x,y)>=0; } +inline bool operator> (const cl_DF& x, const cl_DF& y) + { return cl_compare(x,y)>0; } + +// minusp(x) == (< x 0) +extern cl_boolean minusp (const cl_DF& x); + +// zerop(x) stellt fest, ob ein Double-Float x = 0.0 ist. +extern cl_boolean zerop (const cl_DF& x); + +// plusp(x) == (> x 0) +extern cl_boolean plusp (const cl_DF& x); + +// Liefert zu zwei Double-Float x und y : (+ x y), ein DF. +extern const cl_DF operator+ (const cl_DF& x, const cl_DF& y); + +// Liefert zu zwei Double-Float x und y : (- x y), ein DF. +extern const cl_DF operator- (const cl_DF& x, const cl_DF& y); + +// Liefert zu zwei Double-Float x und y : (* x y), ein DF. +extern const cl_DF operator* (const cl_DF& x, const cl_DF& y); + +// Liefert zu einem Double-Float x : (* x x), ein DF. +inline const cl_DF square (const cl_DF& x) { return x*x; } + +// Liefert zu zwei Double-Float x und y : (/ x y), ein DF. +extern const cl_DF operator/ (const cl_DF& x, const cl_DF& y); + +// Liefert zu einem Double-Float x>=0 : (sqrt x), ein DF. +extern const cl_DF sqrt (const cl_DF& x); + +// recip(x) liefert (/ x), wo x ein Double-Float ist. +extern const cl_DF recip (const cl_DF& x); + +// abs(x) liefert (abs x), wo x ein Double-Float ist. +extern const cl_DF abs (const cl_DF& x); + + +// (1+ x), wo x ein Double-Float ist. +inline const cl_DF plus1 (const cl_DF& x) +{ + extern const cl_DF cl_I_to_DF (const cl_I&); + return x + cl_I_to_DF(cl_I(1)); +} + +// (1- x), wo x ein Double-Float ist. +inline const cl_DF minus1 (const cl_DF& x) +{ + extern const cl_DF cl_I_to_DF (const cl_I&); + return x + cl_I_to_DF(cl_I(-1)); +} + + +// ffloor(x) liefert (ffloor x), wo x ein DF ist. +extern const cl_DF ffloor (const cl_DF& x); + +// fceiling(x) liefert (fceiling x), wo x ein DF ist. +extern const cl_DF fceiling (const cl_DF& x); + +// ftruncate(x) liefert (ftruncate x), wo x ein DF ist. +extern const cl_DF ftruncate (const cl_DF& x); + +// fround(x) liefert (fround x), wo x ein DF ist. +extern const cl_DF fround (const cl_DF& x); + + +// Return type for frounding operators. +// x / y --> (q,r) with x = y*q+r. +struct cl_DF_fdiv_t { + cl_DF quotient; + cl_DF remainder; +// Constructor. + cl_DF_fdiv_t () {} + cl_DF_fdiv_t (const cl_DF& q, const cl_DF& r) : quotient(q), remainder(r) {} +}; + +// ffloor2(x) liefert (ffloor x), wo x ein DF ist. +inline const cl_DF_fdiv_t ffloor2 (const cl_DF& x) + { cl_DF q = ffloor(x); return cl_DF_fdiv_t(q,x-q); } + +// fceiling2(x) liefert (fceiling x), wo x ein DF ist. +inline const cl_DF_fdiv_t fceiling2 (const cl_DF& x) + { cl_DF q = fceiling(x); return cl_DF_fdiv_t(q,x-q); } + +// ftruncate2(x) liefert (ftruncate x), wo x ein DF ist. +inline const cl_DF_fdiv_t ftruncate2 (const cl_DF& x) + { cl_DF q = ftruncate(x); return cl_DF_fdiv_t(q,x-q); } + +// fround2(x) liefert (fround x), wo x ein DF ist. +inline const cl_DF_fdiv_t fround2 (const cl_DF& x) + { cl_DF q = fround(x); return cl_DF_fdiv_t(q,x-q); } + + +// Return type for rounding operators. +// x / y --> (q,r) with x = y*q+r. +struct cl_DF_div_t { + cl_I quotient; + cl_DF remainder; +// Constructor. + cl_DF_div_t () {} + cl_DF_div_t (const cl_I& q, const cl_DF& r) : quotient(q), remainder(r) {} +}; + +// floor2(x) liefert (floor x), wo x ein DF ist. +inline const cl_DF_div_t floor2 (const cl_DF& x) +{ + extern const cl_I cl_DF_to_I (const cl_DF& x); + cl_DF q = ffloor(x); + return cl_DF_div_t(cl_DF_to_I(q),x-q); +} +inline const cl_I floor1 (const cl_DF& x) +{ + extern const cl_I cl_DF_to_I (const cl_DF& x); + return cl_DF_to_I(ffloor(x)); +} + +// ceiling2(x) liefert (ceiling x), wo x ein DF ist. +inline const cl_DF_div_t ceiling2 (const cl_DF& x) +{ + extern const cl_I cl_DF_to_I (const cl_DF& x); + cl_DF q = fceiling(x); + return cl_DF_div_t(cl_DF_to_I(q),x-q); +} +inline const cl_I ceiling1 (const cl_DF& x) +{ + extern const cl_I cl_DF_to_I (const cl_DF& x); + return cl_DF_to_I(fceiling(x)); +} + +// truncate2(x) liefert (truncate x), wo x ein DF ist. +inline const cl_DF_div_t truncate2 (const cl_DF& x) +{ + extern const cl_I cl_DF_to_I (const cl_DF& x); + cl_DF q = ftruncate(x); + return cl_DF_div_t(cl_DF_to_I(q),x-q); +} +inline const cl_I truncate1 (const cl_DF& x) +{ + extern const cl_I cl_DF_to_I (const cl_DF& x); + return cl_DF_to_I(ftruncate(x)); +} + +// round2(x) liefert (round x), wo x ein DF ist. +inline const cl_DF_div_t round2 (const cl_DF& x) +{ + extern const cl_I cl_DF_to_I (const cl_DF& x); + cl_DF q = fround(x); + return cl_DF_div_t(cl_DF_to_I(q),x-q); +} +inline const cl_I round1 (const cl_DF& x) +{ + extern const cl_I cl_DF_to_I (const cl_DF& x); + return cl_DF_to_I(fround(x)); +} + +// floor2(x,y) liefert (floor x y). +extern const cl_DF_div_t floor2 (const cl_DF& x, const cl_DF& y); +inline const cl_I floor1 (const cl_DF& x, const cl_DF& y) { return floor1(x/y); } + +// ceiling2(x,y) liefert (ceiling x y). +extern const cl_DF_div_t ceiling2 (const cl_DF& x, const cl_DF& y); +inline const cl_I ceiling1 (const cl_DF& x, const cl_DF& y) { return ceiling1(x/y); } + +// truncate2(x,y) liefert (truncate x y). +extern const cl_DF_div_t truncate2 (const cl_DF& x, const cl_DF& y); +inline const cl_I truncate1 (const cl_DF& x, const cl_DF& y) { return truncate1(x/y); } + +// round2(x,y) liefert (round x y). +extern const cl_DF_div_t round2 (const cl_DF& x, const cl_DF& y); +inline const cl_I round1 (const cl_DF& x, const cl_DF& y) { return round1(x/y); } + + +// Return type for decode_float: +struct cl_decoded_dfloat { + cl_DF mantissa; + cl_I exponent; + cl_DF sign; +// Constructor. + cl_decoded_dfloat () {} + cl_decoded_dfloat (const cl_DF& m, const cl_I& e, const cl_DF& s) : mantissa(m), exponent(e), sign(s) {} +}; + +// decode_float(x) liefert zu einem Float x: (decode-float x). +// x = 0.0 liefert (0.0, 0, 1.0). +// x = (-1)^s * 2^e * m liefert ((-1)^0 * 2^0 * m, e als Integer, (-1)^s). +extern const cl_decoded_dfloat decode_float (const cl_DF& x); + +// float_exponent(x) liefert zu einem Float x: +// den Exponenten von (decode-float x). +// x = 0.0 liefert 0. +// x = (-1)^s * 2^e * m liefert e. +extern sintL float_exponent (const cl_DF& x); + +// float_radix(x) liefert (float-radix x), wo x ein Float ist. +inline sintL float_radix (const cl_DF& x) +{ + (void)x; // unused x + return 2; +} + +// float_sign(x) liefert (float-sign x), wo x ein Float ist. +extern const cl_DF float_sign (const cl_DF& x); + +// float_digits(x) liefert (float-digits x), wo x ein Float ist. +// < ergebnis: ein uintL >0 +extern uintL float_digits (const cl_DF& x); + +// float_precision(x) liefert (float-precision x), wo x ein Float ist. +// < ergebnis: ein uintL >=0 +extern uintL float_precision (const cl_DF& x); + + +// integer_decode_float(x) liefert zu einem Float x: (integer-decode-float x). +// x = 0.0 liefert (0, 0, 1). +// x = (-1)^s * 2^e * m bei Float-Precision p liefert +// (Mantisse 2^p * m als Integer, e-p als Integer, (-1)^s als Fixnum). +extern const cl_idecoded_float integer_decode_float (const cl_DF& x); + + +// scale_float(x,delta) liefert x*2^delta, wo x ein DF ist. +extern const cl_DF scale_float (const cl_DF& x, sintL delta); +extern const cl_DF scale_float (const cl_DF& x, const cl_I& delta); + + +// max(x,y) liefert (max x y), wo x und y Floats sind. +extern const cl_DF max (const cl_DF& x, const cl_DF& y); + +// min(x,y) liefert (min x y), wo x und y Floats sind. +extern const cl_DF min (const cl_DF& x, const cl_DF& y); + +// signum(x) liefert (signum x), wo x ein Float ist. +extern const cl_DF signum (const cl_DF& x); + + +// Konversion zu einem C "float". +extern float cl_float_approx (const cl_DF& x); + +// Konversion zu einem C "double". +extern double cl_double_approx (const cl_DF& x); + + +#ifdef WANT_OBFUSCATING_OPERATORS +// This could be optimized to use in-place operations. +inline cl_DF& operator+= (cl_DF& x, const cl_DF& y) { return x = x + y; } +inline cl_DF& operator++ /* prefix */ (cl_DF& x) { return x = plus1(x); } +inline void operator++ /* postfix */ (cl_DF& x, int dummy) { (void)dummy; x = plus1(x); } +inline cl_DF& operator-= (cl_DF& x, const cl_DF& y) { return x = x - y; } +inline cl_DF& operator-- /* prefix */ (cl_DF& x) { return x = minus1(x); } +inline void operator-- /* postfix */ (cl_DF& x, int dummy) { (void)dummy; x = minus1(x); } +inline cl_DF& operator*= (cl_DF& x, const cl_DF& y) { return x = x * y; } +inline cl_DF& operator/= (cl_DF& x, const cl_DF& y) { return x = x / y; } +#endif + + +/* */ +CL_REQUIRE(cl_ieee) + + +// Runtime typing support. +extern cl_class cl_class_dfloat; + + +// Debugging support. +#ifdef CL_DEBUG +extern int cl_DF_debug_module; +static void* const cl_DF_debug_dummy[] = { &cl_DF_debug_dummy, + &cl_DF_debug_module +}; +#endif + + +#endif /* _CL_DFLOAT_H */ diff --git a/include/cl_dfloat_class.h b/include/cl_dfloat_class.h new file mode 100644 index 0000000..ba0c86d --- /dev/null +++ b/include/cl_dfloat_class.h @@ -0,0 +1,65 @@ +// Concrete class of double float numbers. + +#ifndef _CL_DFLOAT_CLASS_H +#define _CL_DFLOAT_CLASS_H + +#include "cl_number.h" +#include "cl_float_class.h" + + +class cl_DF : public cl_F { +public: +// Default constructor. + cl_DF (); +// Assignment operators. + cl_DF& operator= (const cl_DF&); +// Optimization of method pointer_p(). + cl_boolean pointer_p() const + { return cl_true; } +// Faster pointer_p() gives a faster copy constructor (but not destructor!!!). + cl_DF (const cl_DF& x); +// Constructors and assignment operators from C numeric types. + cl_DF (const double); + cl_DF& operator= (const double); +// Other constructors. + cl_DF (const char *); +// Private constructor. + cl_DF (cl_private_thing); + cl_DF (struct cl_heap_dfloat *); +// Private pointer manipulations. + operator struct cl_heap_dfloat * () const; +public: // Ability to place an object at a given address. + void* operator new (size_t size) { return cl_malloc_hook(size); } + void* operator new (size_t size, cl_DF* ptr) { (void)size; return ptr; } + void operator delete (void* ptr) { cl_free_hook(ptr); } +private: +// Friend declarations. They are for the compiler. Just ignore them. +}; + +// Private constructors. +inline cl_DF::cl_DF (cl_private_thing ptr) : cl_F (ptr) {} +// The assignment operators: +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_DF, cl_DF) +// The default constructors. +// Private pointer manipulations. Never throw away a `struct cl_heap_dfloat *'! +inline cl_DF::operator struct cl_heap_dfloat * () const +{ + struct cl_heap_dfloat * hpointer = (struct cl_heap_dfloat *) pointer; + cl_inc_refcount(*this); + return hpointer; +} +extern const cl_DF cl_DF_0; +inline cl_DF::cl_DF () + : cl_F ((cl_private_thing) (struct cl_heap_dfloat *) cl_DF_0) {} +CL_REQUIRE(cl_DF_globals) +#if 0 // see cl_DF.h +inline cl_DF::cl_DF (struct cl_heap_dfloat * ptr) + : cl_F ((cl_private_thing) ptr) {} +#endif +// The copy constructors. +CL_DEFINE_COPY_CONSTRUCTOR2(cl_DF,cl_F) +// Constructors and assignment operators from C numeric types. +CL_DEFINE_DOUBLE_CONSTRUCTOR(cl_DF) + + +#endif /* _CL_DFLOAT_CLASS_H */ diff --git a/include/cl_dfloat_io.h b/include/cl_dfloat_io.h new file mode 100644 index 0000000..783c671 --- /dev/null +++ b/include/cl_dfloat_io.h @@ -0,0 +1,27 @@ +// I/O of dfloats. + +#ifndef _CL_DFLOAT_IO_H +#define _CL_DFLOAT_IO_H + +#include "cl_number_io.h" +#include "cl_dfloat.h" + +inline cl_istream operator>> (cl_istream stream, cl_DF& result) +{ + extern cl_read_flags cl_DF_read_flags; + extern const cl_F read_float (cl_istream, const cl_read_flags&); + result = As(cl_DF)(read_float(stream,cl_DF_read_flags)); + return stream; +} + +// The following does strictly the same as the general `fprint' for floats. +// It is here only so that people don't need to include . +inline void fprint (cl_ostream stream, const cl_DF& x) +{ + extern void print_float (cl_ostream stream, const cl_print_flags& flags, const cl_F& z); + extern cl_print_flags cl_default_print_flags; + print_float(stream,cl_default_print_flags,x); +} +CL_DEFINE_PRINT_OPERATOR(cl_DF) + +#endif /* _CL_DFLOAT_IO_H */ diff --git a/include/cl_ffloat.h b/include/cl_ffloat.h new file mode 100644 index 0000000..bb85e05 --- /dev/null +++ b/include/cl_ffloat.h @@ -0,0 +1,310 @@ +// Public single float operations. + +#ifndef _CL_FFLOAT_H +#define _CL_FFLOAT_H + +#include "cl_number.h" +#include "cl_ffloat_class.h" +#include "cl_integer_class.h" +#include "cl_float.h" + + +CL_DEFINE_AS_CONVERSION(cl_FF) + + +// Liefert zu einem Single-Float x : (- x), ein FF. +extern const cl_FF operator- (const cl_FF& x); + +// cl_compare(x,y) vergleicht zwei Single-Floats x und y. +// Ergebnis: 0 falls x=y, +1 falls x>y, -1 falls x= (const cl_FF& x, const cl_FF& y) + { return cl_compare(x,y)>=0; } +inline bool operator> (const cl_FF& x, const cl_FF& y) + { return cl_compare(x,y)>0; } + +// minusp(x) == (< x 0) +extern cl_boolean minusp (const cl_FF& x); + +// zerop(x) stellt fest, ob ein Single-Float x = 0.0 ist. +extern cl_boolean zerop (const cl_FF& x); + +// plusp(x) == (> x 0) +extern cl_boolean plusp (const cl_FF& x); + +// Liefert zu zwei Single-Float x und y : (+ x y), ein FF. +extern const cl_FF operator+ (const cl_FF& x, const cl_FF& y); + +// Liefert zu zwei Single-Float x und y : (- x y), ein FF. +extern const cl_FF operator- (const cl_FF& x, const cl_FF& y); + +// Liefert zu zwei Single-Float x und y : (* x y), ein FF. +extern const cl_FF operator* (const cl_FF& x, const cl_FF& y); + +// Liefert zu einem Single-Float x : (* x x), ein FF. +inline const cl_FF square (const cl_FF& x) { return x*x; } + +// Liefert zu zwei Single-Float x und y : (/ x y), ein FF. +extern const cl_FF operator/ (const cl_FF& x, const cl_FF& y); + +// Liefert zu einem Single-Float x>=0 : (sqrt x), ein FF. +extern const cl_FF sqrt (const cl_FF& x); + +// recip(x) liefert (/ x), wo x ein Single-Float ist. +extern const cl_FF recip (const cl_FF& x); + +// abs(x) liefert (abs x), wo x ein Single-Float ist. +extern const cl_FF abs (const cl_FF& x); + + +// (1+ x), wo x ein Single-Float ist. +inline const cl_FF plus1 (const cl_FF& x) +{ + extern const cl_FF cl_I_to_FF (const cl_I&); + return x + cl_I_to_FF(cl_I(1)); +} + +// (1- x), wo x ein Single-Float ist. +inline const cl_FF minus1 (const cl_FF& x) +{ + extern const cl_FF cl_I_to_FF (const cl_I&); + return x + cl_I_to_FF(cl_I(-1)); +} + + +// ffloor(x) liefert (ffloor x), wo x ein FF ist. +extern const cl_FF ffloor (const cl_FF& x); + +// fceiling(x) liefert (fceiling x), wo x ein FF ist. +extern const cl_FF fceiling (const cl_FF& x); + +// ftruncate(x) liefert (ftruncate x), wo x ein FF ist. +extern const cl_FF ftruncate (const cl_FF& x); + +// fround(x) liefert (fround x), wo x ein FF ist. +extern const cl_FF fround (const cl_FF& x); + + +// Return type for frounding operators. +// x / y --> (q,r) with x = y*q+r. +struct cl_FF_fdiv_t { + cl_FF quotient; + cl_FF remainder; +// Constructor. + cl_FF_fdiv_t () {} + cl_FF_fdiv_t (const cl_FF& q, const cl_FF& r) : quotient(q), remainder(r) {} +}; + +// ffloor2(x) liefert (ffloor x), wo x ein FF ist. +inline const cl_FF_fdiv_t ffloor2 (const cl_FF& x) + { cl_FF q = ffloor(x); return cl_FF_fdiv_t(q,x-q); } + +// fceiling2(x) liefert (fceiling x), wo x ein FF ist. +inline const cl_FF_fdiv_t fceiling2 (const cl_FF& x) + { cl_FF q = fceiling(x); return cl_FF_fdiv_t(q,x-q); } + +// ftruncate2(x) liefert (ftruncate x), wo x ein FF ist. +inline const cl_FF_fdiv_t ftruncate2 (const cl_FF& x) + { cl_FF q = ftruncate(x); return cl_FF_fdiv_t(q,x-q); } + +// fround2(x) liefert (fround x), wo x ein FF ist. +inline const cl_FF_fdiv_t fround2 (const cl_FF& x) + { cl_FF q = fround(x); return cl_FF_fdiv_t(q,x-q); } + + +// Return type for rounding operators. +// x / y --> (q,r) with x = y*q+r. +struct cl_FF_div_t { + cl_I quotient; + cl_FF remainder; +// Constructor. + cl_FF_div_t () {} + cl_FF_div_t (const cl_I& q, const cl_FF& r) : quotient(q), remainder(r) {} +}; + +// floor2(x) liefert (floor x), wo x ein FF ist. +inline const cl_FF_div_t floor2 (const cl_FF& x) +{ + extern const cl_I cl_FF_to_I (const cl_FF& x); + cl_FF q = ffloor(x); + return cl_FF_div_t(cl_FF_to_I(q),x-q); +} +inline const cl_I floor1 (const cl_FF& x) +{ + extern const cl_I cl_FF_to_I (const cl_FF& x); + return cl_FF_to_I(ffloor(x)); +} + +// ceiling2(x) liefert (ceiling x), wo x ein FF ist. +inline const cl_FF_div_t ceiling2 (const cl_FF& x) +{ + extern const cl_I cl_FF_to_I (const cl_FF& x); + cl_FF q = fceiling(x); + return cl_FF_div_t(cl_FF_to_I(q),x-q); +} +inline const cl_I ceiling1 (const cl_FF& x) +{ + extern const cl_I cl_FF_to_I (const cl_FF& x); + return cl_FF_to_I(fceiling(x)); +} + +// truncate2(x) liefert (truncate x), wo x ein FF ist. +inline const cl_FF_div_t truncate2 (const cl_FF& x) +{ + extern const cl_I cl_FF_to_I (const cl_FF& x); + cl_FF q = ftruncate(x); + return cl_FF_div_t(cl_FF_to_I(q),x-q); +} +inline const cl_I truncate1 (const cl_FF& x) +{ + extern const cl_I cl_FF_to_I (const cl_FF& x); + return cl_FF_to_I(ftruncate(x)); +} + +// round2(x) liefert (round x), wo x ein FF ist. +inline const cl_FF_div_t round2 (const cl_FF& x) +{ + extern const cl_I cl_FF_to_I (const cl_FF& x); + cl_FF q = fround(x); + return cl_FF_div_t(cl_FF_to_I(q),x-q); +} +inline const cl_I round1 (const cl_FF& x) +{ + extern const cl_I cl_FF_to_I (const cl_FF& x); + return cl_FF_to_I(fround(x)); +} + +// floor2(x,y) liefert (floor x y). +extern const cl_FF_div_t floor2 (const cl_FF& x, const cl_FF& y); +inline const cl_I floor1 (const cl_FF& x, const cl_FF& y) { return floor1(x/y); } + +// ceiling2(x,y) liefert (ceiling x y). +extern const cl_FF_div_t ceiling2 (const cl_FF& x, const cl_FF& y); +inline const cl_I ceiling1 (const cl_FF& x, const cl_FF& y) { return ceiling1(x/y); } + +// truncate2(x,y) liefert (truncate x y). +extern const cl_FF_div_t truncate2 (const cl_FF& x, const cl_FF& y); +inline const cl_I truncate1 (const cl_FF& x, const cl_FF& y) { return truncate1(x/y); } + +// round2(x,y) liefert (round x y). +extern const cl_FF_div_t round2 (const cl_FF& x, const cl_FF& y); +inline const cl_I round1 (const cl_FF& x, const cl_FF& y) { return round1(x/y); } + + +// Return type for decode_float: +struct cl_decoded_ffloat { + cl_FF mantissa; + cl_I exponent; + cl_FF sign; +// Constructor. + cl_decoded_ffloat () {} + cl_decoded_ffloat (const cl_FF& m, const cl_I& e, const cl_FF& s) : mantissa(m), exponent(e), sign(s) {} +}; + +// decode_float(x) liefert zu einem Float x: (decode-float x). +// x = 0.0 liefert (0.0, 0, 1.0). +// x = (-1)^s * 2^e * m liefert ((-1)^0 * 2^0 * m, e als Integer, (-1)^s). +extern const cl_decoded_ffloat decode_float (const cl_FF& x); + +// float_exponent(x) liefert zu einem Float x: +// den Exponenten von (decode-float x). +// x = 0.0 liefert 0. +// x = (-1)^s * 2^e * m liefert e. +extern sintL float_exponent (const cl_FF& x); + +// float_radix(x) liefert (float-radix x), wo x ein Float ist. +inline sintL float_radix (const cl_FF& x) +{ + (void)x; // unused x + return 2; +} + +// float_sign(x) liefert (float-sign x), wo x ein Float ist. +extern const cl_FF float_sign (const cl_FF& x); + +// float_digits(x) liefert (float-digits x), wo x ein Float ist. +// < ergebnis: ein uintL >0 +extern uintL float_digits (const cl_FF& x); + +// float_precision(x) liefert (float-precision x), wo x ein Float ist. +// < ergebnis: ein uintL >=0 +extern uintL float_precision (const cl_FF& x); + + +// integer_decode_float(x) liefert zu einem Float x: (integer-decode-float x). +// x = 0.0 liefert (0, 0, 1). +// x = (-1)^s * 2^e * m bei Float-Precision p liefert +// (Mantisse 2^p * m als Integer, e-p als Integer, (-1)^s als Fixnum). +extern const cl_idecoded_float integer_decode_float (const cl_FF& x); + + +// scale_float(x,delta) liefert x*2^delta, wo x ein FF ist. +extern const cl_FF scale_float (const cl_FF& x, sintL delta); +extern const cl_FF scale_float (const cl_FF& x, const cl_I& delta); + + +// max(x,y) liefert (max x y), wo x und y Floats sind. +extern const cl_FF max (const cl_FF& x, const cl_FF& y); + +// min(x,y) liefert (min x y), wo x und y Floats sind. +extern const cl_FF min (const cl_FF& x, const cl_FF& y); + +// signum(x) liefert (signum x), wo x ein Float ist. +extern const cl_FF signum (const cl_FF& x); + + +// Konversion zu einem C "float". +extern float cl_float_approx (const cl_FF& x); + +// Konversion zu einem C "double". +extern double cl_double_approx (const cl_FF& x); + + +#ifdef WANT_OBFUSCATING_OPERATORS +// This could be optimized to use in-place operations. +inline cl_FF& operator+= (cl_FF& x, const cl_FF& y) { return x = x + y; } +inline cl_FF& operator++ /* prefix */ (cl_FF& x) { return x = plus1(x); } +inline void operator++ /* postfix */ (cl_FF& x, int dummy) { (void)dummy; x = plus1(x); } +inline cl_FF& operator-= (cl_FF& x, const cl_FF& y) { return x = x - y; } +inline cl_FF& operator-- /* prefix */ (cl_FF& x) { return x = minus1(x); } +inline void operator-- /* postfix */ (cl_FF& x, int dummy) { (void)dummy; x = minus1(x); } +inline cl_FF& operator*= (cl_FF& x, const cl_FF& y) { return x = x * y; } +inline cl_FF& operator/= (cl_FF& x, const cl_FF& y) { return x = x / y; } +#endif + + +CL_REQUIRE(cl_ieee) +/* */ + + +// Runtime typing support. +extern cl_class cl_class_ffloat; +#ifdef CL_WIDE_POINTERS +static const void* const cl_FF_classes_dummy[] = { &cl_FF_classes_dummy, + &cl_class_ffloat +}; +#endif + + +// Debugging support. +#ifdef CL_DEBUG +extern int cl_FF_debug_module; +static void* const cl_FF_debug_dummy[] = { &cl_FF_debug_dummy, + &cl_FF_debug_module +}; +#endif + + +#endif /* _CL_FFLOAT_H */ diff --git a/include/cl_ffloat_class.h b/include/cl_ffloat_class.h new file mode 100644 index 0000000..6183819 --- /dev/null +++ b/include/cl_ffloat_class.h @@ -0,0 +1,76 @@ +// Concrete class of single float numbers. + +#ifndef _CL_FFLOAT_CLASS_H +#define _CL_FFLOAT_CLASS_H + +#include "cl_number.h" +#include "cl_float_class.h" + + +class cl_FF : public cl_F { +public: +// Default constructor. + cl_FF (); +// Assignment operators. + cl_FF& operator= (const cl_FF&); +// Optimization of method pointer_p(). + cl_boolean pointer_p() const +#if defined(CL_WIDE_POINTERS) + { return cl_false; } +#else + { return cl_true; } +#endif +// Faster pointer_p() gives a faster copy constructor (but not destructor!!!). + cl_FF (const cl_FF& x); +// Constructors and assignment operators from C numeric types. + cl_FF (const float); + cl_FF& operator= (const float); +// Other constructors. + cl_FF (const char *); +// Private constructor. + cl_FF (cl_private_thing); +#if defined(CL_WIDE_POINTERS) + cl_FF (struct cl_heap_ffloat * /* NULL! */, cl_uint); +#else + cl_FF (struct cl_heap_ffloat *); +// Private pointer manipulations. + operator struct cl_heap_ffloat * () const; +#endif +public: // Ability to place an object at a given address. + void* operator new (size_t size) { return cl_malloc_hook(size); } + void* operator new (size_t size, cl_FF* ptr) { (void)size; return ptr; } + void operator delete (void* ptr) { cl_free_hook(ptr); } +}; + +// Private constructors. +inline cl_FF::cl_FF (cl_private_thing ptr) : cl_F (ptr) {} +// The assignment operators: +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_FF, cl_FF) +// The default constructors. +#if defined(CL_WIDE_POINTERS) +inline cl_FF::cl_FF () + : cl_F ((cl_private_thing) cl_combine(cl_FF_tag,0)) {} +#else +// Private pointer manipulations. Never throw away a `struct cl_heap_ffloat *'! +inline cl_FF::operator struct cl_heap_ffloat * () const +{ + struct cl_heap_ffloat * hpointer = (struct cl_heap_ffloat *) pointer; + cl_inc_refcount(*this); + return hpointer; +} +extern const cl_FF cl_FF_0; +inline cl_FF::cl_FF () + : cl_F ((cl_private_thing) (struct cl_heap_ffloat *) cl_FF_0) {} +CL_REQUIRE(cl_FF_globals) +#if 0 // see cl_FF.h +inline cl_FF::cl_FF (struct cl_heap_ffloat * ptr) + : cl_F ((cl_private_thing) ptr) {} +#endif +#endif +// The copy constructors. +CL_DEFINE_COPY_CONSTRUCTOR2(cl_FF,cl_F) +// Constructors and assignment operators from C numeric types. +CL_DEFINE_FLOAT_CONSTRUCTOR(cl_FF) + + +#endif /* _CL_FFLOAT_CLASS_H */ diff --git a/include/cl_ffloat_io.h b/include/cl_ffloat_io.h new file mode 100644 index 0000000..bf3a165 --- /dev/null +++ b/include/cl_ffloat_io.h @@ -0,0 +1,27 @@ +// I/O of ffloats. + +#ifndef _CL_FFLOAT_IO_H +#define _CL_FFLOAT_IO_H + +#include "cl_number_io.h" +#include "cl_ffloat.h" + +inline cl_istream operator>> (cl_istream stream, cl_FF& result) +{ + extern cl_read_flags cl_FF_read_flags; + extern const cl_F read_float (cl_istream, const cl_read_flags&); + result = As(cl_FF)(read_float(stream,cl_FF_read_flags)); + return stream; +} + +// The following does strictly the same as the general `fprint' for floats. +// It is here only so that people don't need to include . +inline void fprint (cl_ostream stream, const cl_FF& x) +{ + extern void print_float (cl_ostream stream, const cl_print_flags& flags, const cl_F& z); + extern cl_print_flags cl_default_print_flags; + print_float(stream,cl_default_print_flags,x); +} +CL_DEFINE_PRINT_OPERATOR(cl_FF) + +#endif /* _CL_FFLOAT_IO_H */ diff --git a/include/cl_float.h b/include/cl_float.h new file mode 100644 index 0000000..6cf0215 --- /dev/null +++ b/include/cl_float.h @@ -0,0 +1,655 @@ +// Public float operations. + +#ifndef _CL_FLOAT_H +#define _CL_FLOAT_H + +#include "cl_number.h" +#include "cl_float_class.h" +#include "cl_floatformat.h" +#include "cl_random.h" +#include "cl_integer_class.h" +#include "cl_sfloat_class.h" +#include "cl_ffloat_class.h" +#include "cl_dfloat_class.h" +#include "cl_lfloat_class.h" + + +CL_DEFINE_AS_CONVERSION(cl_F) + + +// Return type for integer_decode_float: +struct cl_idecoded_float { + cl_I mantissa; + cl_I exponent; + cl_I sign; +// Constructor. + cl_idecoded_float () {} + cl_idecoded_float (const cl_I& m, const cl_I& e, const cl_I& s) : mantissa(m), exponent(e), sign(s) {} +}; + + +// zerop(x) testet, ob (= x 0). +extern cl_boolean zerop (const cl_F& x); + +// minusp(x) testet, ob (< x 0). +extern cl_boolean minusp (const cl_F& x); + +// plusp(x) testet, ob (> x 0). +extern cl_boolean plusp (const cl_F& x); + + +// cl_F_to_SF(x) wandelt ein Float x in ein Short-Float um und rundet dabei. +extern const cl_SF cl_F_to_SF (const cl_F& x); + +// cl_F_to_FF(x) wandelt ein Float x in ein Single-Float um und rundet dabei. +extern const cl_FF cl_F_to_FF (const cl_F& x); + +// cl_F_to_DF(x) wandelt ein Float x in ein Double-Float um und rundet dabei. +extern const cl_DF cl_F_to_DF (const cl_F& x); + +// cl_F_to_LF(x,len) wandelt ein Float x in ein Long-Float mit len Digits um +// und rundet dabei. +// > uintC len: gewünschte Anzahl Digits, >=LF_minlen +extern const cl_LF cl_F_to_LF (const cl_F& x, uintC len); + + +// The default float format used when converting rational numbers to floats. +extern cl_float_format_t cl_default_float_format; + +// Returns the smallest float format which guarantees at least n decimal digits +// in the mantissa (after the decimal point). +extern cl_float_format_t cl_float_format (uintL n); + +// cl_float(x,y) wandelt ein Float x in das Float-Format des Floats y um +// und rundet dabei nötigenfalls. +// > x,y: Floats +// < ergebnis: (float x y) +extern const cl_F cl_float (const cl_F& x, const cl_F& y); + +// cl_float(x,f) wandelt ein Float x in das Float-Format f um +// und rundet dabei nötigenfalls. +// > x: ein Float +// > f: eine Float-Format-Spezifikation +// < ergebnis: (float x f) +extern const cl_F cl_float (const cl_F& x, cl_float_format_t f); + +// cl_float(x) wandelt eine reelle Zahl x in ein Float um +// und rundet dabei nötigenfalls. +// > x: eine reelle Zahl +// < ergebnis: (float x) +// Abhängig von cl_default_float_format. +inline const cl_F cl_float (const cl_F& x) { return x; } + +// cl_float(x,y) wandelt ein Integer x in das Float-Format des Floats y um +// und rundet dabei nötigenfalls. +// > x: ein Integer +// > y: ein Float +// < ergebnis: (float x y) +extern const cl_F cl_float (const cl_I& x, const cl_F& y); + +// cl_float(x,y) wandelt ein Integer x in das Float-Format f um +// und rundet dabei nötigenfalls. +// > x: ein Integer +// > f: eine Float-Format-Spezifikation +// < ergebnis: (float x f) +extern const cl_F cl_float (const cl_I& x, cl_float_format_t f); + +// cl_float(x) wandelt ein Integer x in ein Float um und rundet dabei. +// > x: ein Integer +// < ergebnis: (float x) +// Abhängig von cl_default_float_format. +extern const cl_F cl_float (const cl_I& x); + +// cl_float(x,y) wandelt eine rationale Zahl x in das Float-Format des +// Floats y um und rundet dabei nötigenfalls. +// > x: eine rationale Zahl +// > y: ein Float +// < ergebnis: (float x y) +extern const cl_F cl_float (const cl_RA& x, const cl_F& y); + +// cl_float(x,y) wandelt eine rationale Zahl x in das Float-Format f um +// und rundet dabei nötigenfalls. +// > x: eine rationale Zahl +// > f: eine Float-Format-Spezifikation +// < ergebnis: (float x f) +extern const cl_F cl_float (const cl_RA& x, cl_float_format_t f); + +// cl_float(x) wandelt eine rationale Zahl x in ein Float um und rundet dabei. +// > x: eine rationale Zahl +// < ergebnis: (float x) +// Abhängig von cl_default_float_format. +extern const cl_F cl_float (const cl_RA& x); + +// The C++ compilers are not clever enough to guess this: +inline const cl_F cl_float (int x, const cl_F& y) + { return cl_float(cl_I(x),y); } +inline const cl_F cl_float (unsigned int x, const cl_F& y) + { return cl_float(cl_I(x),y); } +inline const cl_F cl_float (int x, cl_float_format_t y) + { return cl_float(cl_I(x),y); } +inline const cl_F cl_float (unsigned int x, cl_float_format_t y) + { return cl_float(cl_I(x),y); } +inline const cl_F cl_float (int x) + { return cl_float(cl_I(x)); } +inline const cl_F cl_float (unsigned int x) + { return cl_float(cl_I(x)); } +// The C++ compilers could hardly guess the following: +inline const cl_F cl_float (float x, const cl_F& y) + { return cl_float(cl_FF(x),y); } +inline const cl_F cl_float (double x, const cl_F& y) + { return cl_float(cl_DF(x),y); } +inline const cl_F cl_float (float x, cl_float_format_t y) + { return cl_float(cl_FF(x),y); } +inline const cl_F cl_float (double x, cl_float_format_t y) + { return cl_float(cl_DF(x),y); } +inline const cl_F cl_float (float x) + { return cl_float(cl_FF(x)); } +inline const cl_F cl_float (double x) + { return cl_float(cl_DF(x)); } + + +// Liefert (- x), wo x ein Float ist. +extern const cl_F operator- (const cl_F& x); + +// Liefert (+ x y), wo x und y Floats sind. +extern const cl_F operator+ (const cl_F& x, const cl_F& y); +// The C++ compilers could hardly guess the following: +inline const cl_F operator+ (const cl_RA& x, const cl_F& y) + { return cl_float(x,y) + y; } +inline const cl_F operator+ (const cl_I& x, const cl_F& y) + { return cl_float(x,y) + y; } +inline const cl_F operator+ (const cl_F& x, const cl_RA& y) + { return x + cl_float(y,x); } +inline const cl_F operator+ (const cl_F& x, const cl_I& y) + { return x + cl_float(y,x); } +// Dem C++-Compiler muß man nun auch das Folgende sagen: +inline const cl_F operator+ (const int x, const cl_F& y) + { return cl_I(x) + y; } +inline const cl_F operator+ (const unsigned int x, const cl_F& y) + { return cl_I(x) + y; } +inline const cl_F operator+ (const long x, const cl_F& y) + { return cl_I(x) + y; } +inline const cl_F operator+ (const unsigned long x, const cl_F& y) + { return cl_I(x) + y; } +inline const cl_F operator+ (const cl_F& x, const int y) + { return x + cl_I(y); } +inline const cl_F operator+ (const cl_F& x, const unsigned int y) + { return x + cl_I(y); } +inline const cl_F operator+ (const cl_F& x, const long y) + { return x + cl_I(y); } +inline const cl_F operator+ (const cl_F& x, const unsigned long y) + { return x + cl_I(y); } + +// Liefert (- x y), wo x und y Floats sind. +extern const cl_F operator- (const cl_F& x, const cl_F& y); +// The C++ compilers could hardly guess the following: +inline const cl_F operator- (const cl_RA& x, const cl_F& y) + { return cl_float(x,y) - y; } +inline const cl_F operator- (const cl_I& x, const cl_F& y) + { return cl_float(x,y) - y; } +inline const cl_F operator- (const cl_F& x, const cl_RA& y) + { return x - cl_float(y,x); } +inline const cl_F operator- (const cl_F& x, const cl_I& y) + { return x - cl_float(y,x); } +// Dem C++-Compiler muß man nun auch das Folgende sagen: +inline const cl_F operator- (const int x, const cl_F& y) + { return cl_I(x) - y; } +inline const cl_F operator- (const unsigned int x, const cl_F& y) + { return cl_I(x) - y; } +inline const cl_F operator- (const long x, const cl_F& y) + { return cl_I(x) - y; } +inline const cl_F operator- (const unsigned long x, const cl_F& y) + { return cl_I(x) - y; } +inline const cl_F operator- (const cl_F& x, const int y) + { return x - cl_I(y); } +inline const cl_F operator- (const cl_F& x, const unsigned int y) + { return x - cl_I(y); } +inline const cl_F operator- (const cl_F& x, const long y) + { return x - cl_I(y); } +inline const cl_F operator- (const cl_F& x, const unsigned long y) + { return x - cl_I(y); } + +// Liefert (* x y), wo x und y Floats sind. +extern const cl_F operator* (const cl_F& x, const cl_F& y); +// Spezialfall x oder y Integer oder rationale Zahl. +inline const cl_R operator* (const cl_F& x, const cl_I& y) +{ + extern const cl_R cl_F_I_mul (const cl_F&, const cl_I&); + return cl_F_I_mul(x,y); +} +inline const cl_R operator* (const cl_I& x, const cl_F& y) +{ + extern const cl_R cl_F_I_mul (const cl_F&, const cl_I&); + return cl_F_I_mul(y,x); +} +inline const cl_R operator* (const cl_F& x, const cl_RA& y) +{ + extern const cl_R cl_F_RA_mul (const cl_F&, const cl_RA&); + return cl_F_RA_mul(x,y); +} +inline const cl_R operator* (const cl_RA& x, const cl_F& y) +{ + extern const cl_R cl_F_RA_mul (const cl_F&, const cl_RA&); + return cl_F_RA_mul(y,x); +} +// Dem C++-Compiler muß man nun auch das Folgende sagen: +inline const cl_R operator* (const int x, const cl_F& y) + { return cl_I(x) * y; } +inline const cl_R operator* (const unsigned int x, const cl_F& y) + { return cl_I(x) * y; } +inline const cl_R operator* (const long x, const cl_F& y) + { return cl_I(x) * y; } +inline const cl_R operator* (const unsigned long x, const cl_F& y) + { return cl_I(x) * y; } +inline const cl_R operator* (const cl_F& x, const int y) + { return x * cl_I(y); } +inline const cl_R operator* (const cl_F& x, const unsigned int y) + { return x * cl_I(y); } +inline const cl_R operator* (const cl_F& x, const long y) + { return x * cl_I(y); } +inline const cl_R operator* (const cl_F& x, const unsigned long y) + { return x * cl_I(y); } + +// Liefert (* x x), wo x ein Float ist. +extern const cl_F square (const cl_F& x); + +// Liefert (/ x y), wo x und y Floats sind. +extern const cl_F operator/ (const cl_F& x, const cl_F& y); +// Liefert (/ x y), wo x und y ein Float und eine rationale Zahl sind. +extern const cl_F operator/ (const cl_F& x, const cl_RA& y); +extern const cl_F operator/ (const cl_F& x, const cl_I& y); +extern const cl_R operator/ (const cl_RA& x, const cl_F& y); +extern const cl_R operator/ (const cl_I& x, const cl_F& y); +// The C++ compilers could hardly guess the following: +inline const cl_F operator/ (const cl_F& x, const int y) + { return x / cl_I(y); } +inline const cl_F operator/ (const cl_F& x, const unsigned int y) + { return x / cl_I(y); } +inline const cl_F operator/ (const cl_F& x, const long y) + { return x / cl_I(y); } +inline const cl_F operator/ (const cl_F& x, const unsigned long y) + { return x / cl_I(y); } +inline const cl_R operator/ (const int x, const cl_F& y) + { return cl_I(x) / y; } +inline const cl_R operator/ (const unsigned int x, const cl_F& y) + { return cl_I(x) / y; } +inline const cl_R operator/ (const long x, const cl_F& y) + { return cl_I(x) / y; } +inline const cl_R operator/ (const unsigned long x, const cl_F& y) + { return cl_I(x) / y; } + +// Liefert (abs x), wo x ein Float ist. +extern const cl_F abs (const cl_F& x); + +// Liefert zu einem Float x>=0 : (sqrt x), ein Float. +extern const cl_F sqrt (const cl_F& x); + +// recip(x) liefert (/ x), wo x ein Float ist. +extern const cl_F recip (const cl_F& x); + +// (1+ x), wo x ein Float ist. +inline const cl_F plus1 (const cl_F& x) // { return x + cl_I(1); } +{ + return x + cl_float(1,x); +} + +// (1- x), wo x ein Float ist. +inline const cl_F minus1 (const cl_F& x) // { return x + cl_I(-1); } +{ + return x + cl_float(-1,x); +} + +// cl_compare(x,y) vergleicht zwei Floats x und y. +// Ergebnis: 0 falls x=y, +1 falls x>y, -1 falls x= (const cl_F& x, const cl_F& y) + { return cl_compare(x,y)>=0; } +inline bool operator> (const cl_F& x, const cl_F& y) + { return cl_compare(x,y)>0; } + + +// ffloor(x) liefert (ffloor x), wo x ein Float ist. +extern const cl_F ffloor (const cl_F& x); + +// fceiling(x) liefert (fceiling x), wo x ein Float ist. +extern const cl_F fceiling (const cl_F& x); + +// ftruncate(x) liefert (ftruncate x), wo x ein Float ist. +extern const cl_F ftruncate (const cl_F& x); + +// fround(x) liefert (fround x), wo x ein Float ist. +extern const cl_F fround (const cl_F& x); + + +// Return type for frounding operators. +// x / y --> (q,r) with x = y*q+r. +struct cl_F_fdiv_t { + cl_F quotient; + cl_F remainder; +// Constructor. + cl_F_fdiv_t () {} + cl_F_fdiv_t (const cl_F& q, const cl_F& r) : quotient(q), remainder(r) {} +}; + +// ffloor2(x) liefert (ffloor x), wo x ein F ist. +extern const cl_F_fdiv_t ffloor2 (const cl_F& x); + +// fceiling2(x) liefert (fceiling x), wo x ein F ist. +extern const cl_F_fdiv_t fceiling2 (const cl_F& x); + +// ftruncate2(x) liefert (ftruncate x), wo x ein F ist. +extern const cl_F_fdiv_t ftruncate2 (const cl_F& x); + +// fround2(x) liefert (fround x), wo x ein F ist. +extern const cl_F_fdiv_t fround2 (const cl_F& x); + + +// Return type for rounding operators. +// x / y --> (q,r) with x = y*q+r. +struct cl_F_div_t { + cl_I quotient; + cl_F remainder; +// Constructor. + cl_F_div_t () {} + cl_F_div_t (const cl_I& q, const cl_F& r) : quotient(q), remainder(r) {} +}; + +// floor2(x) liefert (floor x), wo x ein F ist. +extern const cl_F_div_t floor2 (const cl_F& x); +extern const cl_I floor1 (const cl_F& x); + +// ceiling2(x) liefert (ceiling x), wo x ein F ist. +extern const cl_F_div_t ceiling2 (const cl_F& x); +extern const cl_I ceiling1 (const cl_F& x); + +// truncate2(x) liefert (truncate x), wo x ein F ist. +extern const cl_F_div_t truncate2 (const cl_F& x); +extern const cl_I truncate1 (const cl_F& x); + +// round2(x) liefert (round x), wo x ein F ist. +extern const cl_F_div_t round2 (const cl_F& x); +extern const cl_I round1 (const cl_F& x); + +// floor2(x,y) liefert (floor x y), wo x und y Floats sind. +extern const cl_F_div_t floor2 (const cl_F& x, const cl_F& y); +inline const cl_I floor1 (const cl_F& x, const cl_F& y) { return floor1(x/y); } + +// ceiling2(x,y) liefert (ceiling x y), wo x und y Floats sind. +extern const cl_F_div_t ceiling2 (const cl_F& x, const cl_F& y); +inline const cl_I ceiling1 (const cl_F& x, const cl_F& y) { return ceiling1(x/y); } + +// truncate2(x,y) liefert (truncate x y), wo x und y Floats sind. +extern const cl_F_div_t truncate2 (const cl_F& x, const cl_F& y); +inline const cl_I truncate1 (const cl_F& x, const cl_F& y) { return truncate1(x/y); } + +// round2(x,y) liefert (round x y), wo x und y Floats sind. +extern const cl_F_div_t round2 (const cl_F& x, const cl_F& y); +inline const cl_I round1 (const cl_F& x, const cl_F& y) { return round1(x/y); } + + +// Return type for decode_float: +struct cl_decoded_float { + cl_F mantissa; + cl_I exponent; + cl_F sign; +// Constructor. + cl_decoded_float () {} + cl_decoded_float (const cl_F& m, const cl_I& e, const cl_F& s) : mantissa(m), exponent(e), sign(s) {} +}; + +// decode_float(x) liefert zu einem Float x: (decode-float x). +// x = 0.0 liefert (0.0, 0, 1.0). +// x = (-1)^s * 2^e * m liefert ((-1)^0 * 2^0 * m, e als Integer, (-1)^s). +extern const cl_decoded_float decode_float (const cl_F& x); + +// float_exponent(x) liefert zu einem Float x: +// den Exponenten von (decode-float x). +// x = 0.0 liefert 0. +// x = (-1)^s * 2^e * m liefert e. +extern sintL float_exponent (const cl_F& x); + +// float_radix(x) liefert (float-radix x), wo x ein Float ist. +inline sintL float_radix (const cl_F& x) +{ + (void)x; // unused x + return 2; +} + +// float_sign(x) liefert (float-sign x), wo x ein Float ist. +extern const cl_F float_sign (const cl_F& x); + +// float_sign(x,y) liefert (float-sign x y), wo x und y Floats sind. +extern const cl_F float_sign (const cl_F& x, const cl_F& y); + +// float_digits(x) liefert (float-digits x), wo x ein Float ist. +// < ergebnis: ein uintL >0 +extern uintL float_digits (const cl_F& x); + +// float_precision(x) liefert (float-precision x), wo x ein Float ist. +// < ergebnis: ein uintL >=0 +extern uintL float_precision (const cl_F& x); + +// Returns the floating point format of a float. +inline cl_float_format_t cl_float_format (const cl_F& x) + { return (cl_float_format_t) float_digits(x); } + + +// integer_decode_float(x) liefert zu einem Float x: (integer-decode-float x). +// x = 0.0 liefert (0, 0, 1). +// x = (-1)^s * 2^e * m bei Float-Precision p liefert +// (Mantisse 2^p * m als Integer, e-p als Integer, (-1)^s als Fixnum). +extern const cl_idecoded_float integer_decode_float (const cl_F& x); + + +// rational(x) liefert (rational x), wo x ein Float ist. +extern const cl_RA rational (const cl_F& x); + + +// scale_float(x,delta) liefert x*2^delta, wo x ein Float ist. +extern const cl_F scale_float (const cl_F& x, sintL delta); +extern const cl_F scale_float (const cl_F& x, const cl_I& delta); + + +// max(x,y) liefert (max x y), wo x und y Floats sind. +extern const cl_F max (const cl_F& x, const cl_F& y); + +// min(x,y) liefert (min x y), wo x und y Floats sind. +extern const cl_F min (const cl_F& x, const cl_F& y); + +// signum(x) liefert (signum x), wo x ein Float ist. +extern const cl_F signum (const cl_F& x); + + +// Returns the largest (most positive) floating point number in float format f. +extern const cl_F most_positive_float (cl_float_format_t f); +//CL_REQUIRE(cl_F_mostpos) + +// Returns the smallest (most negative) floating point number in float format f. +extern const cl_F most_negative_float (cl_float_format_t f); +//CL_REQUIRE(cl_F_mostneg) + +// Returns the least positive floating point number (i.e. > 0 but closest to 0) +// in float format f. +extern const cl_F least_positive_float (cl_float_format_t f); +//CL_REQUIRE(cl_F_leastpos) + +// Returns the least negative floating point number (i.e. < 0 but closest to 0) +// in float format f. +extern const cl_F least_negative_float (cl_float_format_t f); +//CL_REQUIRE(cl_F_leastneg) + +// Returns the smallest floating point number e > 0 such that 1+e != 1. +extern const cl_F float_epsilon (cl_float_format_t f); +//CL_REQUIRE(cl_F_epspos) + +// Returns the smallest floating point number e > 0 such that 1-e != 1. +extern const cl_F float_negative_epsilon (cl_float_format_t f); +//CL_REQUIRE(cl_F_epsneg) + + +// Konversion zu einem C "float". +extern float cl_float_approx (const cl_F& x); + +// Konversion zu einem C "double". +extern double cl_double_approx (const cl_F& x); + + +// Transcendental functions + + +// cl_pi(y) liefert die Zahl pi im selben Float-Format wie y. +// > y: ein Float +extern const cl_F cl_pi (const cl_F& y); + +// cl_pi(y) liefert die Zahl pi im Float-Format f. +// > f: eine Float-Format-Spezifikation +extern const cl_F cl_pi (cl_float_format_t f); + +// cl_pi() liefert die Zahl pi im Default-Float-Format. +extern const cl_F cl_pi (void); + +//CL_REQUIRE(cl_F_pi_var) + + +// sin(x) liefert den Sinus (sin x) eines Float x. +extern const cl_F sin (const cl_F& x); + +// cos(x) liefert den Cosinus (cos x) eines Float x. +extern const cl_F cos (const cl_F& x); + +// Return type for cl_cos_sin(): +struct cl_cos_sin_t { + cl_R cos; + cl_R sin; +// Constructor: + cl_cos_sin_t (const cl_R& u, const cl_R& v) : cos (u), sin (v) {} +}; + +// cl_cos_sin(x) liefert ((cos x),(sin x)), beide Werte. +extern const cl_cos_sin_t cl_cos_sin (const cl_F& x); + +// tan(x) liefert den Tangens (tan x) eines Float x. +extern const cl_F tan (const cl_F& x); + + +// cl_exp1(y) liefert die Zahl e = exp(1) im selben Float-Format wie y. +// > y: ein Float +extern const cl_F cl_exp1 (const cl_F& y); + +// cl_exp1(y) liefert die Zahl e = exp(1) im Float-Format f. +// > f: eine Float-Format-Spezifikation +extern const cl_F cl_exp1 (cl_float_format_t f); + +// cl_exp1() liefert die Zahl e = exp(1) im Default-Float-Format. +extern const cl_F cl_exp1 (void); + +//CL_REQUIRE(cl_F_exp1_var) + + +// ln(x) liefert zu einem Float x>0 die Zahl ln(x). +extern const cl_F ln (const cl_F& x); +// Spezialfall: x Long-Float -> Ergebnis Long-Float +inline const cl_LF ln (const cl_LF& x) { return The(cl_LF)(ln(The(cl_F)(x))); } + +// exp(x) liefert zu einem Float x die Zahl exp(x). +extern const cl_F exp (const cl_F& x); + +// sinh(x) liefert zu einem Float x die Zahl sinh(x). +extern const cl_F sinh (const cl_F& x); + +// cosh(x) liefert zu einem Float x die Zahl cosh(x). +extern const cl_F cosh (const cl_F& x); + +// Return type for cl_cosh_sinh(): +struct cl_cosh_sinh_t { + cl_R cosh; + cl_R sinh; +// Constructor: + cl_cosh_sinh_t (const cl_R& u, const cl_R& v) : cosh (u), sinh (v) {} +}; + +// cl_cosh_sinh(x) liefert ((cosh x),(sinh x)), beide Werte. +extern const cl_cosh_sinh_t cl_cosh_sinh (const cl_F& x); + +// tanh(x) liefert zu einem Float x die Zahl tanh(x). +extern const cl_F tanh (const cl_F& x); + + +// cl_eulerconst(y) liefert die Eulersche Konstante +// im selben Float-Format wie y. +// > y: ein Float +extern const cl_F cl_eulerconst (const cl_F& y); + +// cl_eulerconst(y) liefert die Eulersche Konstante im Float-Format f. +// > f: eine Float-Format-Spezifikation +extern const cl_F cl_eulerconst (cl_float_format_t f); + +// cl_eulerconst() liefert die Eulersche Konstante im Default-Float-Format. +extern const cl_F cl_eulerconst (void); + +//CL_REQUIRE(cl_F_eulerconst_var) + + +// cl_catalanconst(y) liefert die Catalansche Konstante +// im selben Float-Format wie y. +// > y: ein Float +extern const cl_F cl_catalanconst (const cl_F& y); + +// cl_catalanconst(y) liefert die Catalansche Konstante im Float-Format f. +// > f: eine Float-Format-Spezifikation +extern const cl_F cl_catalanconst (cl_float_format_t f); + +// cl_catalanconst() liefert die Catalansche Konstante im Default-Float-Format. +extern const cl_F cl_catalanconst (void); + +//CL_REQUIRE(cl_F_catalanconst_var) + + +// zeta(s) returns the Riemann zeta function at s>1. +extern const cl_F cl_zeta (int s, const cl_F& y); +extern const cl_F cl_zeta (int s, cl_float_format_t f); +extern const cl_F cl_zeta (int s); + + +// random_F(randomstate,n) liefert zu einem Float n>0 ein zufälliges +// Float x mit 0 <= x < n. +// > randomstate: ein Random-State, wird verändert +extern const cl_F random_F (cl_random_state& randomstate, const cl_F& n); + +inline const cl_F random_F (const cl_F& n) + { return random_F(cl_default_random_state,n); } + + +#ifdef WANT_OBFUSCATING_OPERATORS +// This could be optimized to use in-place operations. +inline cl_F& operator+= (cl_F& x, const cl_F& y) { return x = x + y; } +inline cl_F& operator++ /* prefix */ (cl_F& x) { return x = plus1(x); } +inline void operator++ /* postfix */ (cl_F& x, int dummy) { (void)dummy; x = plus1(x); } +inline cl_F& operator-= (cl_F& x, const cl_F& y) { return x = x - y; } +inline cl_F& operator-- /* prefix */ (cl_F& x) { return x = minus1(x); } +inline void operator-- /* postfix */ (cl_F& x, int dummy) { (void)dummy; x = minus1(x); } +inline cl_F& operator*= (cl_F& x, const cl_F& y) { return x = x * y; } +inline cl_F& operator/= (cl_F& x, const cl_F& y) { return x = x / y; } +#endif + + +CL_REQUIRE(cl_ieee) + + +// If this is true, floating point underflow returns zero instead of an error. +extern cl_boolean cl_inhibit_floating_point_underflow; + + +#endif /* _CL_FLOAT_H */ diff --git a/include/cl_float_class.h b/include/cl_float_class.h new file mode 100644 index 0000000..c3b2302 --- /dev/null +++ b/include/cl_float_class.h @@ -0,0 +1,50 @@ +// Abstract class of floating-point numbers. + +#ifndef _CL_FLOAT_CLASS_H +#define _CL_FLOAT_CLASS_H + +#include "cl_number.h" +#include "cl_real_class.h" + + +class cl_F : public cl_R { +public: +// Default constructor. + cl_F (); +// Copy constructor. + cl_F (const cl_F&); +// Converters. +// Assignment operators. + cl_F& operator= (const cl_F&); +// Constructors and assignment operators from C numeric types. + cl_F (const float); + cl_F (const double); + cl_F& operator= (const float); + cl_F& operator= (const double); +// Other constructors. + cl_F (const char *); +// Private constructor. + cl_F (cl_private_thing); +public: // Ability to place an object at a given address. + void* operator new (size_t size) { return cl_malloc_hook(size); } + void* operator new (size_t size, cl_F* ptr) { (void)size; return ptr; } + void operator delete (void* ptr) { cl_free_hook(ptr); } +private: +// Friend declarations. They are for the compiler. Just ignore them. +}; + +// Private constructors. +inline cl_F::cl_F (cl_private_thing ptr) : cl_R (ptr) {} +// The assignment operators: +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_F, cl_F) +// The default constructors. +inline cl_F::cl_F () + : cl_R ((cl_private_thing) cl_combine(cl_SF_tag,0)) {} +// The copy constructors. +CL_DEFINE_COPY_CONSTRUCTOR2(cl_F,cl_R) +// Constructors and assignment operators from C numeric types. +CL_DEFINE_FLOAT_CONSTRUCTOR(cl_F) +CL_DEFINE_DOUBLE_CONSTRUCTOR(cl_F) + + +#endif /* _CL_FLOAT_CLASS_H */ diff --git a/include/cl_float_io.h b/include/cl_float_io.h new file mode 100644 index 0000000..b02d080 --- /dev/null +++ b/include/cl_float_io.h @@ -0,0 +1,79 @@ +// I/O of floats. + +#ifndef _CL_FLOAT_IO_H +#define _CL_FLOAT_IO_H + +#include "cl_number_io.h" +#include "cl_float.h" + + +// Undocumented input functions + +// Wandelt eine Zeichenkette mit Float-Syntax in ein Float um. +// read_float(base,sign,string,index1,index4,index2,index3) +// > base: Lesebasis (=10) +// > sign: Vorzeichen (/=0 falls negativ) +// > string: Simple-String (enthält Ziffern und evtl. Punkt und Exponentmarker) +// > index1: Index vom Mantissenanfang (excl. Vorzeichen) +// > index4: Index nach dem Mantissenende +// > index2: Index beim Ende der Characters +// > index3: Index nach dem Dezimalpunkt (=index4 falls keiner da) +// (also Mantisse mit index4-index1 Characters: Ziffern und max. 1 '.') +// (also index4-index3 Nachkommaziffern) +// (also bei index4> (cl_istream stream, cl_F& result) +{ + extern cl_read_flags cl_F_read_flags; + result = read_float(stream,cl_F_read_flags); + return stream; +} + + +// Undocumented output functions + + +// Documented output functions + +// Gibt ein Float aus. +// print_float(stream,z); +// > z: Float +// > stream: Stream +extern void print_float (cl_ostream stream, const cl_print_flags& flags, const cl_F& z); +extern void print_float (cl_ostream stream, const cl_print_number_flags& flags, const cl_F& z); +extern void print_float (cl_ostream stream, const cl_print_real_flags& flags, const cl_F& z); +extern void print_float (cl_ostream stream, const cl_print_float_flags& flags, const cl_F& z); + +// Gibt ein Float binär (sehr primitiv) aus. +// print_float_binary(stream,z); +// > z: Float +// > stream: Stream +extern void print_float_binary (cl_ostream stream, const cl_F& z); + +// The following does strictly the same as the general `fprint' for numbers. +// It is here only so that you don't need the complex printer +// in order to print a float. ("Treeshaking") + +inline void fprint (cl_ostream stream, const cl_F& x) +{ + extern cl_print_flags cl_default_print_flags; + print_float(stream,cl_default_print_flags,x); +} + +CL_DEFINE_PRINT_OPERATOR(cl_F) + + +#endif /* _CL_FLOAT_IO_H */ diff --git a/include/cl_floatformat.h b/include/cl_floatformat.h new file mode 100644 index 0000000..84bc185 --- /dev/null +++ b/include/cl_floatformat.h @@ -0,0 +1,16 @@ +// Floating point format specifiers. + +#ifndef _CL_FLOATFORMAT_H +#define _CL_FLOATFORMAT_H + +#include "cl_types.h" + +// Float format specifier type. (Float mantissa precision in bits.) +typedef enum cl_float_format_t { + cl_float_format_sfloat = 17, + cl_float_format_ffloat = 24, + cl_float_format_dfloat = 53, + cl_float_format_lfloat_min = ((53+intDsize-1)/intDsize)*intDsize // = round_up(53,intDsize) +}; + +#endif /* _CL_FLOATFORMAT_H */ diff --git a/include/cl_input.h b/include/cl_input.h new file mode 100644 index 0000000..a8709a4 --- /dev/null +++ b/include/cl_input.h @@ -0,0 +1,57 @@ +// Input functions. + +#ifndef _CL_INPUT_H +#define _CL_INPUT_H + +#include "cl_types.h" +#include "cl_floatformat.h" +#include "cl_io.h" + +struct cl_read_float_flags { + // The float format used when reading floats with exponent marker 'E'. + cl_float_format_t default_float_format; + // The float format used when reading floats with exponent marker 'L'. + cl_float_format_t default_lfloat_format; + // Flag whether floats specified with more digits than corresponding + // to the exponent marker they contain, but without _nnn suffix, will + // get a precision corresponding to their number of significant digits. + cl_boolean mantissa_dependent_float_format; +}; + +// Specifies the possible results of a read operation. +enum cl_read_syntax_t { + syntax_integer = 1 << 0, // -> cl_I + syntax_ratio = 1 << 1, // -> cl_RA + syntax_rational = syntax_integer | syntax_ratio, // -> cl_RA + syntax_sfloat = 1 << 2, // -> cl_SF + syntax_ffloat = 1 << 3, // -> cl_FF + syntax_dfloat = 1 << 4, // -> cl_DF + syntax_lfloat = 1 << 5, // -> cl_LF + syntax_float = syntax_sfloat | syntax_ffloat | syntax_dfloat | syntax_lfloat, + // -> cl_F + syntax_real = syntax_rational | syntax_float, // -> cl_R + syntax_complex = 1 << 6, // -> cl_N + syntax_number = syntax_real | syntax_complex, // -> cl_N + syntax_maybe_bad = 1 << 7 // avoid errors +}; + +// Specifies the syntax to be applied to a read operation. +enum cl_read_lsyntax_t { + // Standard algebraic notation. + lsyntax_standard = 0, + // Extended algebraic notation: x+yi + lsyntax_algebraic = 1 << 0, + // Common Lisp notation: #b, #o, #x, #r, #c + lsyntax_commonlisp = 1 << 1, + // All of them. + lsyntax_all = lsyntax_algebraic | lsyntax_commonlisp +}; + +struct cl_read_flags { + cl_read_syntax_t syntax; + cl_read_lsyntax_t lsyntax; + unsigned int rational_base; + cl_read_float_flags float_flags; +}; + +#endif /* _CL_INPUT_H */ diff --git a/include/cl_integer.h b/include/cl_integer.h new file mode 100644 index 0000000..d5e2597 --- /dev/null +++ b/include/cl_integer.h @@ -0,0 +1,602 @@ +// Public integer operations. + +#ifndef _CL_INTEGER_H +#define _CL_INTEGER_H + +#include "cl_number.h" +#include "cl_integer_class.h" +#include "cl_random.h" + + +CL_DEFINE_AS_CONVERSION(cl_I) + + +// Konversion Integer >=0, <2^32 nach uintL. +// Wandelt Integer >=0 in Unsigned Longword um. +// cl_I_to_UL(obj) +// > obj: Integer, sollte >=0, <2^32 sein +// < ergebnis: der Wert des Integer als 32-Bit-Zahl. + extern uint32 cl_I_to_UL (const cl_I& obj); + +// Konversion Integer >=-2^31, <2^31 nach sintL. +// Wandelt Integer in Signed Longword um. +// cl_I_to_L(obj) +// > obj: Integer, sollte >=-2^31, <2^31 sein +// < ergebnis: der Wert des Integer als 32-Bit-Zahl. + extern sint32 cl_I_to_L (const cl_I& obj); + +// Convert an integer to a C `int' or `unsigned int'. +#if (int_bitsize==32) + inline int cl_I_to_int (const cl_I& x) { return cl_I_to_L(x); } + inline unsigned int cl_I_to_uint (const cl_I& x) { return cl_I_to_UL(x); } +#endif + +// Convert an integer to a C `long' or `unsigned long'. +#if (long_bitsize==32) + inline long cl_I_to_long (const cl_I& x) { return cl_I_to_L(x); } + inline unsigned long cl_I_to_ulong (const cl_I& x) { return cl_I_to_UL(x); } +#elif (long_bitsize==64) + extern uint64 cl_I_to_UQ (const cl_I& obj); + extern sint64 cl_I_to_Q (const cl_I& obj); + inline long cl_I_to_long (const cl_I& x) { return cl_I_to_Q(x); } + inline unsigned long cl_I_to_ulong (const cl_I& x) { return cl_I_to_UQ(x); } +#endif + + +// Logische Operationen auf Integers: + +// (LOGIOR x y), wenn x, y Integers sind. +// Ergebnis Integer. +extern const cl_I logior (const cl_I& x, const cl_I& y); + +// (LOGXOR x y), wenn x, y Integers sind. +// Ergebnis Integer. +extern const cl_I logxor (const cl_I& x, const cl_I& y); + +// (LOGAND x y), wenn x, y Integers sind. +// Ergebnis Integer. +extern const cl_I logand (const cl_I& x, const cl_I& y); + +// (LOGEQV x y), wenn x, y Integers sind. +// Ergebnis Integer. +extern const cl_I logeqv (const cl_I& x, const cl_I& y); + +// (LOGNAND x y), wenn x, y Integers sind. +// Ergebnis Integer. +extern const cl_I lognand (const cl_I& x, const cl_I& y); + +// (LOGNOR x y), wenn x, y Integers sind. +// Ergebnis Integer. +extern const cl_I lognor (const cl_I& x, const cl_I& y); + +// (LOGANDC2 x y), wenn x, y Integers sind. +// Ergebnis Integer. +extern const cl_I logandc2 (const cl_I& x, const cl_I& y); + +// (LOGANDC1 x y), wenn x, y Integers sind. +// Ergebnis Integer. +inline const cl_I logandc1 (const cl_I& x, const cl_I& y) +{ + return logandc2(y,x); +} + +// (LOGORC2 x y), wenn x, y Integers sind. +// Ergebnis Integer. +extern const cl_I logorc2 (const cl_I& x, const cl_I& y); + +// (LOGORC1 x y), wenn x, y Integers sind. +// Ergebnis Integer. +inline const cl_I logorc1 (const cl_I& x, const cl_I& y) +{ + return logorc2(y,x); +} + +// (LOGNOT x), wenn x ein Integer sind. +// Ergebnis Integer. +extern const cl_I lognot (const cl_I& x); + +// Konstanten für BOOLE: +typedef enum { + boole_clr, + boole_set, + boole_1, + boole_2, + boole_c1, + boole_c2, + boole_and, + boole_ior, + boole_xor, + boole_eqv, + boole_nand, + boole_nor, + boole_andc1, + boole_andc2, + boole_orc1, + boole_orc2 +} cl_boole; + +// (BOOLE op x y), wenn x und y Integers und op ein Objekt sind. +// Ergebnis Integer. +extern const cl_I boole (cl_boole op, const cl_I& x, const cl_I& y); + +// Prüft, ob (LOGTEST x y), wo x und y Integers sind. +// (LOGTEST x y) = (NOT (ZEROP (LOGAND x y))). +// < ergebnis: /=0, falls ja; =0, falls nein. +extern cl_boolean logtest (const cl_I& x, const cl_I& y); + +// Prüft, ob (LOGBITP x y), wo x und y Integers sind. +// Ergebnis: /=0, wenn ja; =0, wenn nein. +extern cl_boolean logbitp (uintL x, const cl_I& y); +extern cl_boolean logbitp (const cl_I& x, const cl_I& y); + +// Prüft, ob (ODDP x), wo x ein Integer ist. +// Ergebnis: /=0, falls ja; =0, falls nein. +extern cl_boolean oddp (const cl_I& x); + +// Prüft, ob (EVENP x), wo x ein Integer ist. +// Ergebnis: /=0, falls ja; =0, falls nein. +inline cl_boolean evenp (const cl_I& x) + { return (cl_boolean) (!oddp(x)); } + +// (ASH x y), wo x und y Integers sind. Ergebnis Integer. +extern const cl_I ash (const cl_I& x, sintL y); +extern const cl_I ash (const cl_I& x, const cl_I& y); + +// (LOGCOUNT x), wo x ein Integer ist. Ergebnis uintL. +extern uintL logcount (const cl_I& x); + +// (INTEGER-LENGTH x), wo x ein Integer ist. Ergebnis uintL. +extern uintL integer_length (const cl_I& x); + +// (ORD2 x) = max{n>=0: 2^n | x }, wo x ein Integer /=0 ist. Ergebnis uintL. +extern uintL ord2 (const cl_I& x); + +// power2p(x) stellt fest, ob ein Integer x>0 eine Zweierpotenz ist. +// Ergebnis: n>0, wenn x=2^(n-1), 0 sonst. +extern uintL power2p (const cl_I& x); + +inline const cl_I operator| (const cl_I& x, const cl_I& y) + { return logior(x,y); } +inline const cl_I operator^ (const cl_I& x, const cl_I& y) + { return logxor(x,y); } +inline const cl_I operator& (const cl_I& x, const cl_I& y) + { return logand(x,y); } +inline const cl_I operator~ (const cl_I& x) + { return lognot(x); } +#ifdef WANT_OBFUSCATING_OPERATORS +// This could be optimized to use in-place operations. +inline cl_I& operator|= (cl_I& x, const cl_I& y) { return x = x | y; } +inline cl_I& operator^= (cl_I& x, const cl_I& y) { return x = x ^ y; } +inline cl_I& operator&= (cl_I& x, const cl_I& y) { return x = x & y; } +#endif + + +// Addition/Subtraktion von Integers + +// (1+ x), wo x ein Integer ist. Ergebnis Integer. +extern const cl_I plus1 (const cl_I& x); + +// (1- x), wo x ein Integer ist. Ergebnis Integer. +extern const cl_I minus1 (const cl_I& x); + +// (+ x y), wo x und y Integers sind. Ergebnis Integer. +extern const cl_I operator+ (const cl_I& x, const cl_I& y); +// Dem C++-Compiler muß man auch das Folgende sagen: +inline const cl_I operator+ (const int x, const cl_I& y) + { return cl_I(x) + y; } +inline const cl_I operator+ (const unsigned int x, const cl_I& y) + { return cl_I(x) + y; } +inline const cl_I operator+ (const long x, const cl_I& y) + { return cl_I(x) + y; } +inline const cl_I operator+ (const unsigned long x, const cl_I& y) + { return cl_I(x) + y; } +inline const cl_I operator+ (const cl_I& x, const int y) + { return x + cl_I(y); } +inline const cl_I operator+ (const cl_I& x, const unsigned int y) + { return x + cl_I(y); } +inline const cl_I operator+ (const cl_I& x, const long y) + { return x + cl_I(y); } +inline const cl_I operator+ (const cl_I& x, const unsigned long y) + { return x + cl_I(y); } + +// (- x), wenn x ein Integer ist. Ergebnis Integer. +extern const cl_I operator- (const cl_I& x); + +// (- x y), wo x und y Integers sind. Ergebnis Integer. +extern const cl_I operator- (const cl_I& x, const cl_I& y); +// Dem C++-Compiler muß man auch das Folgende sagen: +inline const cl_I operator- (const int x, const cl_I& y) + { return cl_I(x) - y; } +inline const cl_I operator- (const unsigned int x, const cl_I& y) + { return cl_I(x) - y; } +inline const cl_I operator- (const long x, const cl_I& y) + { return cl_I(x) - y; } +inline const cl_I operator- (const unsigned long x, const cl_I& y) + { return cl_I(x) - y; } +inline const cl_I operator- (const cl_I& x, const int y) + { return x - cl_I(y); } +inline const cl_I operator- (const cl_I& x, const unsigned int y) + { return x - cl_I(y); } +inline const cl_I operator- (const cl_I& x, const long y) + { return x - cl_I(y); } +inline const cl_I operator- (const cl_I& x, const unsigned long y) + { return x - cl_I(y); } + +// (abs x), wenn x ein Integer ist. Ergebnis Integer. +extern const cl_I abs (const cl_I& x); + +// Shifts. +inline const cl_I operator<< (const cl_I& x, sintL y) // assume 0 <= y < 2^31 + { return ash(x,y); } +inline const cl_I operator<< (const cl_I& x, const cl_I& y) // assume y >= 0 + { return ash(x,y); } +inline const cl_I operator>> (const cl_I& x, sintL y) // assume 0 <= y < 2^31 + { return ash(x,-y); } +inline const cl_I operator>> (const cl_I& x, const cl_I& y) // assume y >= 0 + { return ash(x,-y); } + + +// Vergleich von Integers + +// cl_equal(x,y) vergleicht zwei Integers x und y auf Gleichheit. +extern cl_boolean cl_equal (const cl_I& x, const cl_I& y); +// cl_equal_hashcode(x) liefert einen cl_equal-invarianten Hashcode für x. +extern uint32 cl_equal_hashcode (const cl_I& x); + +// cl_compare(x,y) vergleicht zwei Integers x und y. +// Ergebnis: 0 falls x=y, +1 falls x>y, -1 falls x= (const cl_I& x, const cl_I& y) + { return cl_compare(x,y)>=0; } +inline bool operator> (const cl_I& x, const cl_I& y) + { return cl_compare(x,y)>0; } + +// minusp(x) == (< x 0) +extern cl_boolean minusp (const cl_I& x); + +// plusp(x) == (> x 0) +extern cl_boolean plusp (const cl_I& x); + +// zerop(x) stellt fest, ob ein Integer = 0 ist. +extern cl_boolean zerop (const cl_I& x); + + +// BYTE-Operationen auf Integers + +struct cl_byte { + uintL size; + uintL position; +// Konstruktor: + cl_byte (unsigned int s, unsigned int p) : size (s), position (p) {} +}; + +// (LDB byte n), wo n ein Integer ist. +extern const cl_I ldb (const cl_I& n, const cl_byte& b); + +// ldb_test(n,byte) führt (LDB-TEST byte n) aus, wobei n ein Integer ist. +// Ergebnis: cl_false wenn nein (also alle fraglichen Bits =0), cl_true wenn ja. +extern cl_boolean ldb_test (const cl_I& n, const cl_byte& b); + +// (MASK-FIELD byte n), wo n ein Integer ist. +extern const cl_I mask_field (const cl_I& n, const cl_byte& b); + +// (DEPOSIT-FIELD newbyte byte n), wo n und newbyte Integers sind. +extern const cl_I deposit_field (const cl_I& newbyte, const cl_I& n, const cl_byte& b); + +// (DPB newbyte byte n), wo n und newbyte Integers sind. +extern const cl_I dpb (const cl_I& newbyte, const cl_I& n, const cl_byte& b); + + +// Multiplikation ganzer Zahlen + +// (* x y), wo x und y Integers sind. Ergebnis Integer. +extern const cl_I operator* (const cl_I& x, const cl_I& y); +// Dem C++-Compiler muß man auch das Folgende sagen: +inline const cl_I operator* (const int x, const cl_I& y) + { return cl_I(x) * y; } +inline const cl_I operator* (const unsigned int x, const cl_I& y) + { return cl_I(x) * y; } +inline const cl_I operator* (const long x, const cl_I& y) + { return cl_I(x) * y; } +inline const cl_I operator* (const unsigned long x, const cl_I& y) + { return cl_I(x) * y; } +inline const cl_I operator* (const cl_I& x, const int y) + { return x * cl_I(y); } +inline const cl_I operator* (const cl_I& x, const unsigned int y) + { return x * cl_I(y); } +inline const cl_I operator* (const cl_I& x, const long y) + { return x * cl_I(y); } +inline const cl_I operator* (const cl_I& x, const unsigned long y) + { return x * cl_I(y); } + +// (EXPT x 2), wo x Integer ist. +extern const cl_I square (const cl_I& x); + +// (EXPT x y), wo x Integer, y Integer >0 ist. +extern const cl_I expt_pos (const cl_I& x, uintL y); +extern const cl_I expt_pos (const cl_I& x, const cl_I& y); + +// Fakultät (! n), wo n Fixnum >=0 ist. Ergebnis Integer. +extern const cl_I factorial (uintL n); +//CL_REQUIRE(cl_I_factorial) + +// Double factorial (!! n), with n Fixnum >=0. Returns integer. +extern const cl_I doublefactorial (uintL n); + +// Binomialkoeffizient (n \choose k) = n! / k! (n-k)!, wo n,k >= 0 sind. +extern const cl_I binomial (uintL n, uintL k); + + +// Division ganzer Zahlen + +// Return type for division operators. +// x / y --> (q,r) with x = y*q+r. +struct cl_I_div_t { + cl_I quotient; + cl_I remainder; +// Constructor. + cl_I_div_t () {} + cl_I_div_t (const cl_I& q, const cl_I& r) : quotient(q), remainder(r) {} +}; + +// Dividiert zwei Integers x,y >=0 und liefert den Quotienten x/y >=0. +// Bei y=0 Error. Die Division muß aufgehen, sonst Error. +// exquopos(x,y) +// > x,y: Integers >=0 +// < ergebnis: Quotient x/y, ein Integer >=0 + extern const cl_I exquopos (const cl_I& x, const cl_I& y); + +// Dividiert zwei Integers x,y und liefert den Quotienten x/y. +// Bei y=0 Error. Die Division muß aufgehen, sonst Error. +// exquo(x,y) +// > x,y: Integers +// < ergebnis: Quotient x/y, ein Integer + extern const cl_I exquo (const cl_I& x, const cl_I& y); + +// mod(x,y) = (mod x y), wo x,y Integers sind. + extern const cl_I mod (const cl_I& x, const cl_I& y); + +// rem(x,y) = (rem x y), wo x,y Integers sind. + extern const cl_I rem (const cl_I& x, const cl_I& y); + +// Dividiert zwei Integers x,y und liefert Quotient und Rest +// (q,r) := (floor x y) +// floor2(x,y) +// > x,y: Integers +// < q,r: Quotient q, Rest r + extern const cl_I_div_t floor2 (const cl_I& x, const cl_I& y); + extern const cl_I floor1 (const cl_I& x, const cl_I& y); + +// Dividiert zwei Integers x,y und liefert Quotient und Rest +// (q,r) := (ceiling x y) +// ceiling2(x,y) +// > x,y: Integers +// < q,r: Quotient q, Rest r + extern const cl_I_div_t ceiling2 (const cl_I& x, const cl_I& y); + extern const cl_I ceiling1 (const cl_I& x, const cl_I& y); + +// Dividiert zwei Integers x,y und liefert Quotient und Rest +// (q,r) := (truncate x y) +// truncate2(x,y) +// > x,y: Integers +// < q,r: Quotient q, Rest r + extern const cl_I_div_t truncate2 (const cl_I& x, const cl_I& y); + extern const cl_I truncate1 (const cl_I& x, const cl_I& y); + +// Dividiert zwei Integers x,y und liefert Quotient und Rest +// (q,r) := (round x y) +// round2(x,y) +// > x,y: Integers +// < q,r: Quotient q, Rest r + extern const cl_I_div_t round2 (const cl_I& x, const cl_I& y); + extern const cl_I round1 (const cl_I& x, const cl_I& y); + + +// ggT und kgV von Integers + +// Liefert den ggT zweier Integers. +// gcd(a,b) +// > a,b: zwei Integers +// < ergebnis: (gcd a b), ein Integer >=0 + extern const cl_I gcd (const cl_I& a, const cl_I& b); + extern uint32 gcd (uint32 a, uint32 b); + +// Liefert den ggT zweier Integers samt Beifaktoren. +// g = xgcd(a,b,&u,&v) +// > a,b: zwei Integers +// < u, v, g: Integers mit u*a+v*b = g >= 0 + extern const cl_I xgcd (const cl_I& a, const cl_I& b, cl_I* u, cl_I* v); +// Im Fall A/=0, B/=0 genügt das Ergebnis (g,u,v) den Ungleichungen: +// Falls |A| = |B| : g = |A|, u = (signum A), v = 0. +// Falls |B| | |A|, |B| < |A| : g = |B|, u = 0, v = (signum B). +// Falls |A| | |B|, |A| < |B| : g = |A|, u = (signum A), v = 0. +// Sonst: |u| <= |B| / (2*g), |v| <= |A| / (2*g). +// In jedem Fall |u| <= |B|/g, |v| < |A|/g. +// (Beweis: Im Prinzip macht man ja mehrere Euklid-Schritte auf einmal. Im +// letzten Fall - oBdA |A| > |B| - braucht man mindestens zwei Euklid-Schritte, +// also gilt im Euklid-Tableau +// i |A| |B| Erg. +// -------------------------------------------- +// 0 1 0 |A| +// 1 0 1 |B| +// ... ... ... ... +// n-1 -(-1)^n*x[n-1] (-1)^n*y[n-1] z[n-1] +// n (-1)^n*x[n] -(-1)^n*y[n] z[n] +// n+1 -(-1)^n*x[n+1] (-1)^n*y[n+1] z[n+1] = 0 +// -------------------------------------------- +// g = z[n], |u|=x[n], |v|=y[n] +// n>=2, z[0] > ... > z[n-1] > z[n] = g, g | z[n-1], also z[n-1] >= 2*g. +// Da aber mit (-1)^i*x[i]*|A| - (-1)^i*y[i]*|B| = z[i] für i=0..n+1 +// und x[i]*y[i+1] - x[i+1]*y[i] = (-1)^i für i=0..n, +// x[i]*z[i+1] - x[i+1]*z[i] = (-1)^i*|B| für i=0..n, +// y[i]*z[i+1] - y[i+1]*z[i] = -(-1)^i*|A| für i=0..n +// auch |A| = y[i+1]*z[i] + y[i]*z[i+1], |B| = x[i+1]*z[i] + x[i]*z[i+1] +// für i=0..n (Cramersche Regel), folgt +// |A| = y[n]*z[n-1] + y[n-1]*z[n] >= y[n]*2*g + 0 = |v|*2*g, +// |B| = x[n]*z[n-1] + x[n-1]*z[n] >= x[n]*2*g + 0 = |u|*2*g.) + +// Liefert den kgV zweier Integers. +// lcm(a,b) +// > a,b: zwei Integers +// < ergebnis: (lcm a b), ein Integer >=0 + extern const cl_I lcm (const cl_I& a, const cl_I& b); + + +// Wurzel aus ganzen Zahlen + +// Zieht die Wurzel (ISQRT x) aus einem Integer. +// isqrt(x,&w) +// > x: Integer (sollte >=0 sein) +// < w: (isqrt x) +// < ergebnis: cl_true falls x Quadratzahl, cl_false sonst + extern cl_boolean isqrt (const cl_I& x, cl_I* w); +// Wenn das boolesche Ergebnis uninteressant ist: + inline const cl_I isqrt (const cl_I& x) { cl_I w; isqrt(x,&w); return w; } + +// Stellt fest, ob ein Integer >=0 eine Quadratzahl ist. +// sqrtp(x,&w) +// > x: ein Integer >=0 +// < w: Integer (sqrt x) falls x Quadratzahl +// < ergebnis: cl_true ..................., cl_false sonst + extern cl_boolean sqrtp (const cl_I& x, cl_I* w); + +// Stellt fest, ob ein Integer >=0 eine n-te Potenz ist. +// rootp(x,n,&w) +// > x: ein Integer >=0 +// > n: ein Integer >0 +// < w: Integer (expt x (/ n)) falls x eine n-te Potenz +// < ergebnis: cl_true ........................, cl_false sonst + extern cl_boolean rootp (const cl_I& x, uintL n, cl_I* w); + extern cl_boolean rootp (const cl_I& x, const cl_I& n, cl_I* w); + + +// max(x,y) liefert (max x y), wo x und y ganze Zahlen sind. +extern const cl_I max (const cl_I& x, const cl_I& y); + +// min(x,y) liefert (min x y), wo x und y ganze Zahlen sind. +extern const cl_I min (const cl_I& x, const cl_I& y); + +// signum(x) liefert (signum x), wo x eine ganze Zahl ist. +extern const cl_I signum (const cl_I& x); + + +// Multipliziert ein Integer mit 10 und addiert eine weitere Ziffer. +// mul_10_plus_x(y,x) +// > y: Integer Y (>=0) +// > x: Ziffernwert X (>=0,<10) +// < ergebnis: Integer Y*10+X (>=0) +extern const cl_I mul_10_plus_x (const cl_I& y, unsigned char x); + + +// 2-adische Inverse. +// cl_recip2adic(n,x) +// > n: >0 +// > x: Integer, ungerade +// < ergebnis: n-Bit-Zahl y == (x mod 2^n)^-1, d.h. y*x == 1 mod 2^n +extern const cl_I cl_recip2adic (uintL n, const cl_I& x); + +// 2-adische Division. +// cl_div2adic(n,x,y) +// > n: >0 +// > x: Integer +// > y: Integer, ungerade +// < ergebnis: n-Bit-Zahl z == (x mod 2^n)/(y mod 2^n), d.h. z*y == x mod 2^n +extern const cl_I cl_div2adic (uintL n, const cl_I& x, const cl_I& y); + + +// numerator(r) liefert den Zähler des Integer r. +inline const cl_I numerator (const cl_I& r) + { return r; } +// denominator(r) liefert den Nenner (> 0) des Integer r. +inline const cl_I denominator (const cl_I& r) + { (void)r; return 1; } + + +// Konversion zu einem C "float". +extern float cl_float_approx (const cl_I& x); + +// Konversion zu einem C "double". +extern double cl_double_approx (const cl_I& x); + + +// random_I(randomstate,n) liefert zu einem Integer n>0 ein zufälliges +// Integer x mit 0 <= x < n. +// > randomstate: ein Random-State, wird verändert +extern const cl_I random_I (cl_random_state& randomstate, const cl_I& n); + +inline const cl_I random_I (const cl_I& n) + { return random_I(cl_default_random_state,n); } + +// testrandom_I(randomstate) liefert ein zufälliges Integer zum Testen. +// > randomstate: ein Random-State, wird verändert +extern const cl_I testrandom_I (cl_random_state& randomstate); + +inline const cl_I testrandom_I () + { return testrandom_I(cl_default_random_state); } + + +#ifdef WANT_OBFUSCATING_OPERATORS +// This could be optimized to use in-place operations. +inline cl_I& operator+= (cl_I& x, const cl_I& y) { return x = x + y; } +inline cl_I& operator+= (cl_I& x, const int y) { return x = x + y; } +inline cl_I& operator+= (cl_I& x, const unsigned int y) { return x = x + y; } +inline cl_I& operator+= (cl_I& x, const long y) { return x = x + y; } +inline cl_I& operator+= (cl_I& x, const unsigned long y) { return x = x + y; } +inline cl_I& operator++ /* prefix */ (cl_I& x) { return x = plus1(x); } +inline void operator++ /* postfix */ (cl_I& x, int dummy) { (void)dummy; x = plus1(x); } +inline cl_I& operator-= (cl_I& x, const cl_I& y) { return x = x - y; } +inline cl_I& operator-= (cl_I& x, const int y) { return x = x - y; } +inline cl_I& operator-= (cl_I& x, const unsigned int y) { return x = x - y; } +inline cl_I& operator-= (cl_I& x, const long y) { return x = x - y; } +inline cl_I& operator-= (cl_I& x, const unsigned long y) { return x = x - y; } +inline cl_I& operator-- /* prefix */ (cl_I& x) { return x = minus1(x); } +inline void operator-- /* postfix */ (cl_I& x, int dummy) { (void)dummy; x = minus1(x); } +inline cl_I& operator*= (cl_I& x, const cl_I& y) { return x = x * y; } +inline cl_I& operator<<= (cl_I& x, sintL y) // assume 0 <= y < 2^31 + { return x = x << y; } +inline cl_I& operator<<= (cl_I& x, const cl_I& y) // assume y >= 0 + { return x = x << y; } +inline cl_I& operator>>= (cl_I& x, sintL y) // assume 0 <= y < 2^31 + { return x = x >> y; } +inline cl_I& operator>>= (cl_I& x, const cl_I& y) // assume y >= 0 + { return x = x >> y; } +#if 0 // Defining operator/ collides with the operator/ (cl_RA, cl_RA). +// operator/ should perform exquo(x,y), but people believe in the C semantics. +// And it would be wiser to use floor1 and mod instead of truncate1 and rem, +// but again, many C compilers implement / and % like this and people believe +// in it. +inline const cl_I operator/ (const cl_I& x, const cl_I& y) { return truncate1(x,y); } +inline const cl_I operator% (const cl_I& x, const cl_I& y) { return rem(x,y); } +inline cl_I& operator/= (cl_I& x, const cl_I& y) { return x = x / y; } +inline cl_I& operator%= (cl_I& x, const cl_I& y) { return x = x % y; } +#endif +#endif + + +// Runtime typing support. +extern cl_class cl_class_fixnum; +extern cl_class cl_class_bignum; +static const void* const cl_I_classes_dummy[] = { &cl_I_classes_dummy, + &cl_class_fixnum +}; + + +// Debugging support. +#ifdef CL_DEBUG +extern int cl_I_debug_module; +static void* const cl_I_debug_dummy[] = { &cl_I_debug_dummy, + &cl_I_debug_module +}; +#endif + + +#endif /* _CL_INTEGER_H */ diff --git a/include/cl_integer_class.h b/include/cl_integer_class.h new file mode 100644 index 0000000..3b463e5 --- /dev/null +++ b/include/cl_integer_class.h @@ -0,0 +1,55 @@ +// Abstract class of integers. + +#ifndef _CL_INTEGER_CLASS_H +#define _CL_INTEGER_CLASS_H + +#include "cl_number.h" +#include "cl_rational_class.h" + + +class cl_I : public cl_RA { +public: +// Default constructor. + cl_I (); +// Copy constructor. + cl_I (const cl_I&); +// Assignment operators. + cl_I& operator= (const cl_I&); +// Constructors and assignment operators from C numeric types. + cl_I (const int); // |argument| must be < 2^29 + cl_I (const unsigned int); // argument must be < 2^29 + cl_I (const long); + cl_I (const unsigned long); + cl_I& operator= (const int); // |argument| must be < 2^29 + cl_I& operator= (const unsigned int); // argument must be < 2^29 + cl_I& operator= (const long); + cl_I& operator= (const unsigned long); +// Other constructors. + cl_I (const char *); +// Private constructor. + cl_I (cl_private_thing); + cl_I (struct cl_fixnum * /* NULL! */, cl_uint); + cl_I (struct cl_heap_bignum *); +public: // Ability to place an object at a given address. + void* operator new (size_t size) { return cl_malloc_hook(size); } + void* operator new (size_t size, cl_I* ptr) { (void)size; return ptr; } + void operator delete (void* ptr) { cl_free_hook(ptr); } +}; + +// Private constructors. +inline cl_I::cl_I (cl_private_thing ptr) : cl_RA (ptr) {} +// The assignment operators: +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_I, cl_I) +// The default constructors. +inline cl_I::cl_I () + : cl_RA ((cl_private_thing) cl_combine(cl_FN_tag,0)) {} +// The copy constructors. +CL_DEFINE_COPY_CONSTRUCTOR2(cl_I,cl_RA) +// Constructors and assignment operators from C numeric types. +CL_DEFINE_INT_CONSTRUCTORS(cl_I) +CL_DEFINE_INT_ASSIGNMENT_OPERATORS(cl_I) +CL_DEFINE_LONG_CONSTRUCTORS(cl_I) +CL_DEFINE_LONG_ASSIGNMENT_OPERATORS(cl_I) + + +#endif /* _CL_INTEGER_CLASS_H */ diff --git a/include/cl_integer_io.h b/include/cl_integer_io.h new file mode 100644 index 0000000..ee13ae7 --- /dev/null +++ b/include/cl_integer_io.h @@ -0,0 +1,103 @@ +// I/O of integers. + +#ifndef _CL_INTEGER_IO_H +#define _CL_INTEGER_IO_H + +#include "cl_number_io.h" +#include "cl_integer_class.h" + + +// Undocumented input functions + +// Wandelt eine Zeichenkette mit Integer-Syntax in ein Integer um. +// Punkte werden überlesen. +// read_integer(base,sign,string,index1,index2) +// > base: Lesebasis (>=2, <=36) +// > sign: Vorzeichen (/=0 falls negativ) +// > string: Simple-String (enthält Ziffern mit Wert index1: Index der ersten Ziffer +// > index2: Index nach der letzten Ziffer +// (also index2-index1 Ziffern, incl. evtl. Dezimalpunkt am Schluß) +// < ergebnis: Integer +extern const cl_I read_integer (unsigned int base, + cl_signean sign, const char * string, uintL index1, uintL index2); + +// The following does strictly the same as the general read_complex. +// It is here only so that you don't need the rational, complex and float number +// readers in order to read an integer. ("Treeshaking") +extern const cl_I read_integer (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse); +extern const cl_I read_integer (cl_istream stream, const cl_read_flags& flags); + +// Documented input functions + +inline cl_istream operator>> (cl_istream stream, cl_I& result) +{ + extern cl_read_flags cl_I_read_flags; + result = read_integer(stream,cl_I_read_flags); + return stream; +} + + +// Undocumented output functions + +// Liefert zu einem Integer >=0 (write-to-string integer :base 10 :radix nil), +// also die Ziffernfolge als String. +// Mit cl_malloc_hook() alloziert, mit cl_free_hook() freizugeben. +extern char * cl_decimal_string (const cl_I& x); + +// Gibt ein Integer aus. +// print_integer(stream,base,z); +// > z: Integer +// > base: Basis (>=2, <=36) +// > stream: Stream +extern void print_integer (cl_ostream stream, unsigned int base, const cl_I& z); +// Dasselbe als String. Mit cl_malloc_hook() alloziert, mit cl_free_hook() freizugeben. +extern char * print_integer_to_string (unsigned int base, const cl_I& z); + + +// Documented output functions + +inline void fprintdecimal (cl_ostream stream, const cl_I& x) +{ + print_integer(stream,10,x); +} + +inline void fprintbinary (cl_ostream stream, const cl_I& x) +{ + print_integer(stream,2,x); +} + +inline void fprintoctal (cl_ostream stream, const cl_I& x) +{ + print_integer(stream,8,x); +} + +inline void fprinthexadecimal (cl_ostream stream, const cl_I& x) +{ + print_integer(stream,16,x); +} + +// Gibt eine Zahl aus. +// print_integer(stream,flags,z); +// > z: Zahl +// > stream: Stream +// > flags: Ausgabe-Parameter +extern void print_integer (cl_ostream stream, const cl_print_flags& flags, const cl_I& z); +extern void print_integer (cl_ostream stream, const cl_print_number_flags& flags, const cl_I& z); +extern void print_integer (cl_ostream stream, const cl_print_real_flags& flags, const cl_I& z); +extern void print_integer (cl_ostream stream, const cl_print_rational_flags& flags, const cl_I& z); + +// The following does strictly the same as the general `fprint' for numbers. +// It is here only so that you don't need the rational number printer +// in order to print an integer. ("Treeshaking") + +inline void fprint (cl_ostream stream, const cl_I& x) +{ + extern cl_print_flags cl_default_print_flags; + print_integer(stream,cl_default_print_flags,x); +} + +CL_DEFINE_PRINT_OPERATOR(cl_I) + + +#endif /* _CL_INTEGER_IO_H */ diff --git a/include/cl_integer_ring.h b/include/cl_integer_ring.h new file mode 100644 index 0000000..fe99e54 --- /dev/null +++ b/include/cl_integer_ring.h @@ -0,0 +1,14 @@ +// Built-in integer ring. + +#ifndef _CL_INTEGER_RING_H +#define _CL_INTEGER_RING_H + +#include "cl_ring.h" +#include "cl_integer_class.h" + +typedef cl_specialized_number_ring cl_integer_ring; +extern const cl_integer_ring cl_I_ring; // math. Z +extern cl_class cl_class_integer_ring; +//CL_REQUIRE(cl_I_ring) + +#endif /* _CL_INTEGER_RING_H */ diff --git a/include/cl_io.h b/include/cl_io.h new file mode 100644 index 0000000..67d9a18 --- /dev/null +++ b/include/cl_io.h @@ -0,0 +1,159 @@ +// I/O through or + +#ifndef _CL_IO_H +#define _CL_IO_H + +#include "cl_types.h" +#include "cl_modules.h" + +#if !defined(CL_IO_STDIO) && !defined(CL_IO_IOSTREAM) +// Prefer iostream based I/O - this is what people expect. +#define CL_IO_IOSTREAM +#endif + + +#if defined(CL_IO_STDIO) + +// I/O through + +#include + +#define cl_istream FILE * +#define cl_ostream FILE * +#define cl_stdin stdin +#define cl_stdout stdout +#define cl_stderr stderr +extern FILE* cl_debugout; + +// Elementary operations on cl_istream + +#define cl_EOF EOF + +inline int freadchar (cl_istream stream) +{ + // return fgetc(stream); + return getc(stream); +} + +inline int funreadchar (cl_istream stream, int c) +{ + return ungetc(c,stream); +} + +// Elementary operations on cl_ostream + +inline void fprintchar (cl_ostream stream, char c) +{ + // fputc(c,stream); + putc(c,stream); +} + +inline void fprint (cl_ostream stream, const char * string) +{ + // fprintf(stream,"%s",string); + fputs(string,stream); +} + +#endif + + +#if defined(CL_IO_IOSTREAM) + +// I/O through + +#ifdef floor + #undef floor + #include + #define floor cln_floor +#else + #include +#endif + +#define cl_istream istream& +#define cl_ostream ostream& +#define cl_stdin cin +#define cl_stdout cout +#define cl_stderr cerr +extern ostream* cl_debugout_stream; +#define cl_debugout (*cl_debugout_stream) + +// Elementary operations on cl_istream + +#define cl_EOF (-1) + +inline int freadchar (cl_istream stream) +{ + char c; + if (stream.get(c)) + return c; + else + // EOF or error + return cl_EOF; +} + +inline int funreadchar (cl_istream stream, int c) +{ + if (c != cl_EOF) + stream.putback((char)c); + return c; +} + +// Elementary operations on cl_ostream + +inline void fprintchar (cl_ostream stream, char c) +{ + stream.put(c); +} + +inline void fprint (cl_ostream stream, const char * string) +{ + stream << string; +} + +#endif + + +extern void fprintdecimal (cl_ostream stream, unsigned long x); +extern void fprintdecimal (cl_ostream stream, long x); + +inline void fprintdecimal (cl_ostream stream, unsigned int x) +{ + fprintdecimal(stream,(unsigned long)x); +} +inline void fprintdecimal (cl_ostream stream, int x) +{ + fprintdecimal(stream,(long)x); +} + +extern void fprinthexadecimal (cl_ostream stream, unsigned long x); +extern void fprinthexadecimal (cl_ostream stream, long x); + +inline void fprinthexadecimal (cl_ostream stream, unsigned int x) +{ + fprinthexadecimal(stream,(unsigned long)x); +} +inline void fprinthexadecimal (cl_ostream stream, int x) +{ + fprinthexadecimal(stream,(long)x); +} + + +class cl_print_flags; +class cl_print_number_flags; +class cl_print_real_flags; +class cl_print_rational_flags; +class cl_print_float_flags; +CL_REQUIRE(cl_prin_globals) + + +// Define the customary << and >> operators. + +#define CL_DEFINE_PRINT_OPERATOR(_class_) \ +inline cl_ostream operator<< (cl_ostream stream, const _class_& x) \ +{ \ + fprint(stream,x); \ + return stream; \ +} + + +#endif /* _CL_IO_H */ diff --git a/include/cl_lfloat.h b/include/cl_lfloat.h new file mode 100644 index 0000000..347c148 --- /dev/null +++ b/include/cl_lfloat.h @@ -0,0 +1,411 @@ +// Public long float operations. + +#ifndef _CL_LFLOAT_H +#define _CL_LFLOAT_H + +#include "cl_number.h" +#include "cl_lfloat_class.h" +#include "cl_integer_class.h" +#include "cl_float.h" + + +CL_DEFINE_AS_CONVERSION(cl_LF) + + +// Liefert zu einem Long-Float x : (- x), ein LF. +extern const cl_LF operator- (const cl_LF& x); + +// cl_compare(x,y) vergleicht zwei Long-Floats x und y. +// Ergebnis: 0 falls x=y, +1 falls x>y, -1 falls x= (const cl_LF& x, const cl_LF& y) + { return cl_compare(x,y)>=0; } +inline bool operator> (const cl_LF& x, const cl_LF& y) + { return cl_compare(x,y)>0; } + +// minusp(x) == (< x 0) +extern cl_boolean minusp (const cl_LF& x); + +// zerop(x) stellt fest, ob ein Long-Float x = 0.0 ist. +extern cl_boolean zerop (const cl_LF& x); + +// plusp(x) == (> x 0) +extern cl_boolean plusp (const cl_LF& x); + +// Liefert zu zwei Long-Float x und y : (+ x y), ein LF. +extern const cl_LF operator+ (const cl_LF& x, const cl_LF& y); + +// Liefert zu zwei Long-Float x und y : (- x y), ein LF. +extern const cl_LF operator- (const cl_LF& x, const cl_LF& y); + +// Liefert zu zwei Long-Float x und y : (* x y), ein LF. +extern const cl_LF operator* (const cl_LF& x, const cl_LF& y); +// Spezialfall x oder y Integer oder rationale Zahl. +inline const cl_R operator* (const cl_LF& x, const cl_I& y) +{ + extern const cl_R cl_LF_I_mul (const cl_LF&, const cl_I&); + return cl_LF_I_mul(x,y); +} +inline const cl_R operator* (const cl_I& x, const cl_LF& y) +{ + extern const cl_R cl_LF_I_mul (const cl_LF&, const cl_I&); + return cl_LF_I_mul(y,x); +} +inline const cl_R operator* (const cl_LF& x, const cl_RA& y) +{ + extern const cl_R cl_LF_RA_mul (const cl_LF&, const cl_RA&); + return cl_LF_RA_mul(x,y); +} +inline const cl_R operator* (const cl_RA& x, const cl_LF& y) +{ + extern const cl_R cl_LF_RA_mul (const cl_LF&, const cl_RA&); + return cl_LF_RA_mul(y,x); +} +// Dem C++-Compiler muß man auch das Folgende sagen (wg. `int * cl_LF' u.ä.): +inline const cl_R operator* (const int x, const cl_LF& y) + { return cl_I(x) * y; } +inline const cl_R operator* (const unsigned int x, const cl_LF& y) + { return cl_I(x) * y; } +inline const cl_R operator* (const long x, const cl_LF& y) + { return cl_I(x) * y; } +inline const cl_R operator* (const unsigned long x, const cl_LF& y) + { return cl_I(x) * y; } +inline const cl_R operator* (const cl_LF& x, const int y) + { return x * cl_I(y); } +inline const cl_R operator* (const cl_LF& x, const unsigned int y) + { return x * cl_I(y); } +inline const cl_R operator* (const cl_LF& x, const long y) + { return x * cl_I(y); } +inline const cl_R operator* (const cl_LF& x, const unsigned long y) + { return x * cl_I(y); } +// Spezialfall x = y. +// Liefert zu einem Long-Float x : (* x x), ein LF. +extern const cl_LF square (const cl_LF& x); + +// Liefert zu zwei Long-Float x und y : (/ x y), ein LF. +extern const cl_LF operator/ (const cl_LF& x, const cl_LF& y); +// Spezialfall x oder y Integer oder rationale Zahl. +inline const cl_LF operator/ (const cl_LF& x, const cl_I& y) +{ + extern const cl_LF cl_LF_I_div (const cl_LF& x, const cl_I& y); + return cl_LF_I_div(x,y); +} +inline const cl_R operator/ (const cl_I& x, const cl_LF& y) +{ + extern const cl_R cl_I_LF_div (const cl_I& x, const cl_LF& y); + return cl_I_LF_div(x,y); +} +inline const cl_LF operator/ (const cl_LF& x, const cl_RA& y) +{ + extern const cl_LF cl_LF_RA_div (const cl_LF& x, const cl_RA& y); + return cl_LF_RA_div(x,y); +} +inline const cl_R operator/ (const cl_RA& x, const cl_LF& y) +{ + extern const cl_R cl_RA_LF_div (const cl_RA& x, const cl_LF& y); + return cl_RA_LF_div(x,y); +} +// Dem C++-Compiler muß man nun auch das Folgende sagen: +inline const cl_LF operator/ (const cl_LF& x, const int y) + { return x / cl_I(y); } +inline const cl_LF operator/ (const cl_LF& x, const unsigned int y) + { return x / cl_I(y); } +inline const cl_LF operator/ (const cl_LF& x, const long y) + { return x / cl_I(y); } +inline const cl_LF operator/ (const cl_LF& x, const unsigned long y) + { return x / cl_I(y); } +inline const cl_R operator/ (const int x, const cl_LF& y) + { return cl_I(x) / y; } +inline const cl_R operator/ (const unsigned int x, const cl_LF& y) + { return cl_I(x) / y; } +inline const cl_R operator/ (const long x, const cl_LF& y) + { return cl_I(x) / y; } +inline const cl_R operator/ (const unsigned long x, const cl_LF& y) + { return cl_I(x) / y; } + +// Liefert zu einem Long-Float x>=0 : (sqrt x), ein LF. +extern const cl_LF sqrt (const cl_LF& x); + +// recip(x) liefert (/ x), wo x ein Long-Float ist. +extern const cl_LF recip (const cl_LF& x); + +// abs(x) liefert (abs x), wo x ein Long-Float ist. +extern const cl_LF abs (const cl_LF& x); + + +// (1+ x), wo x ein Long-Float ist. +extern const cl_LF plus1 (const cl_LF& x); + +// (1- x), wo x ein Long-Float ist. +extern const cl_LF minus1 (const cl_LF& x); + + +// ffloor(x) liefert (ffloor x), wo x ein LF ist. +extern const cl_LF ffloor (const cl_LF& x); + +// fceiling(x) liefert (fceiling x), wo x ein LF ist. +extern const cl_LF fceiling (const cl_LF& x); + +// ftruncate(x) liefert (ftruncate x), wo x ein LF ist. +extern const cl_LF ftruncate (const cl_LF& x); + +// fround(x) liefert (fround x), wo x ein LF ist. +extern const cl_LF fround (const cl_LF& x); + + +// Return type for frounding operators. +// x / y --> (q,r) with x = y*q+r. +struct cl_LF_fdiv_t { + cl_LF quotient; + cl_LF remainder; +// Constructor. + cl_LF_fdiv_t () {} + cl_LF_fdiv_t (const cl_LF& q, const cl_LF& r) : quotient(q), remainder(r) {} +}; + +// ffloor2(x) liefert (ffloor x), wo x ein LF ist. +inline const cl_LF_fdiv_t ffloor2 (const cl_LF& x) +{ + extern const cl_LF LF_LF_minus_LF (const cl_LF&, const cl_LF&); + cl_LF q = ffloor(x); + return cl_LF_fdiv_t(q,LF_LF_minus_LF(x,q)); +} + +// fceiling2(x) liefert (fceiling x), wo x ein LF ist. +inline const cl_LF_fdiv_t fceiling2 (const cl_LF& x) +{ + extern const cl_LF LF_LF_minus_LF (const cl_LF&, const cl_LF&); + cl_LF q = fceiling(x); + return cl_LF_fdiv_t(q,LF_LF_minus_LF(x,q)); +} + +// ftruncate2(x) liefert (ftruncate x), wo x ein LF ist. +inline const cl_LF_fdiv_t ftruncate2 (const cl_LF& x) +{ + extern const cl_LF LF_LF_minus_LF (const cl_LF&, const cl_LF&); + cl_LF q = ftruncate(x); + return cl_LF_fdiv_t(q,LF_LF_minus_LF(x,q)); +} + +// fround2(x) liefert (fround x), wo x ein LF ist. +inline const cl_LF_fdiv_t fround2 (const cl_LF& x) +{ + extern const cl_LF LF_LF_minus_LF (const cl_LF&, const cl_LF&); + cl_LF q = fround(x); + return cl_LF_fdiv_t(q,LF_LF_minus_LF(x,q)); +} + + +// Return type for rounding operators. +// x / y --> (q,r) with x = y*q+r. +struct cl_LF_div_t { + cl_I quotient; + cl_LF remainder; +// Constructor. + cl_LF_div_t () {} + cl_LF_div_t (const cl_I& q, const cl_LF& r) : quotient(q), remainder(r) {} +}; + +// floor2(x) liefert (floor x), wo x ein LF ist. +inline const cl_LF_div_t floor2 (const cl_LF& x) +{ + extern const cl_LF LF_LF_minus_LF (const cl_LF&, const cl_LF&); + extern const cl_I cl_LF_to_I (const cl_LF& x); + cl_LF q = ffloor(x); + return cl_LF_div_t(cl_LF_to_I(q),LF_LF_minus_LF(x,q)); +} +inline const cl_I floor1 (const cl_LF& x) +{ + extern const cl_I cl_LF_to_I (const cl_LF& x); + return cl_LF_to_I(ffloor(x)); +} + +// ceiling2(x) liefert (ceiling x), wo x ein LF ist. +inline const cl_LF_div_t ceiling2 (const cl_LF& x) +{ + extern const cl_LF LF_LF_minus_LF (const cl_LF&, const cl_LF&); + extern const cl_I cl_LF_to_I (const cl_LF& x); + cl_LF q = fceiling(x); + return cl_LF_div_t(cl_LF_to_I(q),LF_LF_minus_LF(x,q)); +} +inline const cl_I ceiling1 (const cl_LF& x) +{ + extern const cl_I cl_LF_to_I (const cl_LF& x); + return cl_LF_to_I(fceiling(x)); +} + +// truncate2(x) liefert (truncate x), wo x ein LF ist. +inline const cl_LF_div_t truncate2 (const cl_LF& x) +{ + extern const cl_LF LF_LF_minus_LF (const cl_LF&, const cl_LF&); + extern const cl_I cl_LF_to_I (const cl_LF& x); + cl_LF q = ftruncate(x); + return cl_LF_div_t(cl_LF_to_I(q),LF_LF_minus_LF(x,q)); +} +inline const cl_I truncate1 (const cl_LF& x) +{ + extern const cl_I cl_LF_to_I (const cl_LF& x); + return cl_LF_to_I(ftruncate(x)); +} + +// round2(x) liefert (round x), wo x ein LF ist. +inline const cl_LF_div_t round2 (const cl_LF& x) +{ + extern const cl_LF LF_LF_minus_LF (const cl_LF&, const cl_LF&); + extern const cl_I cl_LF_to_I (const cl_LF& x); + cl_LF q = fround(x); + return cl_LF_div_t(cl_LF_to_I(q),LF_LF_minus_LF(x,q)); +} +inline const cl_I round1 (const cl_LF& x) +{ + extern const cl_I cl_LF_to_I (const cl_LF& x); + return cl_LF_to_I(fround(x)); +} + +// floor2(x,y) liefert (floor x y). +extern const cl_LF_div_t floor2 (const cl_LF& x, const cl_LF& y); +inline const cl_I floor1 (const cl_LF& x, const cl_LF& y) { return floor1(x/y); } + +// ceiling2(x,y) liefert (ceiling x y). +extern const cl_LF_div_t ceiling2 (const cl_LF& x, const cl_LF& y); +inline const cl_I ceiling1 (const cl_LF& x, const cl_LF& y) { return ceiling1(x/y); } + +// truncate2(x,y) liefert (truncate x y). +extern const cl_LF_div_t truncate2 (const cl_LF& x, const cl_LF& y); +inline const cl_I truncate1 (const cl_LF& x, const cl_LF& y) { return truncate1(x/y); } + +// round2(x,y) liefert (round x y). +extern const cl_LF_div_t round2 (const cl_LF& x, const cl_LF& y); +inline const cl_I round1 (const cl_LF& x, const cl_LF& y) { return round1(x/y); } + + +// cl_float(x,y) returns a long float if y is a long float. +inline const cl_LF cl_float (const cl_F& x, const cl_LF& y) +{ + extern const cl_F cl_float (const cl_F& x, const cl_F& y); + return The(cl_LF)(cl_float(x,(const cl_F&)y)); +} +inline const cl_LF cl_float (const cl_I& x, const cl_LF& y) +{ + extern const cl_F cl_float (const cl_I& x, const cl_F& y); + return The(cl_LF)(cl_float(x,(const cl_F&)y)); +} +inline const cl_LF cl_float (const cl_RA& x, const cl_LF& y) +{ + extern const cl_F cl_float (const cl_RA& x, const cl_F& y); + return The(cl_LF)(cl_float(x,(const cl_F&)y)); +} +inline const cl_LF cl_float (int x, const cl_LF& y) + { return cl_float(cl_I(x),y); } +inline const cl_LF cl_float (unsigned int x, const cl_LF& y) + { return cl_float(cl_I(x),y); } + + +// Return type for decode_float: +struct cl_decoded_lfloat { + cl_LF mantissa; + cl_I exponent; + cl_LF sign; +// Constructor. + cl_decoded_lfloat () {} + cl_decoded_lfloat (const cl_LF& m, const cl_I& e, const cl_LF& s) : mantissa(m), exponent(e), sign(s) {} +}; + +// decode_float(x) liefert zu einem Float x: (decode-float x). +// x = 0.0 liefert (0.0, 0, 1.0). +// x = (-1)^s * 2^e * m liefert ((-1)^0 * 2^0 * m, e als Integer, (-1)^s). +extern const cl_decoded_lfloat decode_float (const cl_LF& x); + +// float_exponent(x) liefert zu einem Float x: +// den Exponenten von (decode-float x). +// x = 0.0 liefert 0. +// x = (-1)^s * 2^e * m liefert e. +extern sintL float_exponent (const cl_LF& x); + +// float_radix(x) liefert (float-radix x), wo x ein Float ist. +inline sintL float_radix (const cl_LF& x) +{ + (void)x; // unused x + return 2; +} + +// float_sign(x) liefert (float-sign x), wo x ein Float ist. +extern const cl_LF float_sign (const cl_LF& x); + +// float_digits(x) liefert (float-digits x), wo x ein Float ist. +// < ergebnis: ein uintL >0 +extern uintL float_digits (const cl_LF& x); + +// float_precision(x) liefert (float-precision x), wo x ein Float ist. +// < ergebnis: ein uintL >=0 +extern uintL float_precision (const cl_LF& x); + + +// integer_decode_float(x) liefert zu einem Float x: (integer-decode-float x). +// x = 0.0 liefert (0, 0, 1). +// x = (-1)^s * 2^e * m bei Float-Precision p liefert +// (Mantisse 2^p * m als Integer, e-p als Integer, (-1)^s als Fixnum). +extern const cl_idecoded_float integer_decode_float (const cl_LF& x); + + +// scale_float(x,delta) liefert x*2^delta, wo x ein LF ist. +extern const cl_LF scale_float (const cl_LF& x, sintL delta); +extern const cl_LF scale_float (const cl_LF& x, const cl_I& delta); + + +// max(x,y) liefert (max x y), wo x und y Floats sind. +extern const cl_LF max (const cl_LF& x, const cl_LF& y); + +// min(x,y) liefert (min x y), wo x und y Floats sind. +extern const cl_LF min (const cl_LF& x, const cl_LF& y); + +// signum(x) liefert (signum x), wo x ein Float ist. +extern const cl_LF signum (const cl_LF& x); + + +// Konversion zu einem C "float". +extern float cl_float_approx (const cl_LF& x); + +// Konversion zu einem C "double". +extern double cl_double_approx (const cl_LF& x); + + +#ifdef WANT_OBFUSCATING_OPERATORS +// This could be optimized to use in-place operations. +inline cl_LF& operator+= (cl_LF& x, const cl_LF& y) { return x = x + y; } +inline cl_LF& operator++ /* prefix */ (cl_LF& x) { return x = plus1(x); } +inline void operator++ /* postfix */ (cl_LF& x, int dummy) { (void)dummy; x = plus1(x); } +inline cl_LF& operator-= (cl_LF& x, const cl_LF& y) { return x = x - y; } +inline cl_LF& operator-- /* prefix */ (cl_LF& x) { return x = minus1(x); } +inline void operator-- /* postfix */ (cl_LF& x, int dummy) { (void)dummy; x = minus1(x); } +inline cl_LF& operator*= (cl_LF& x, const cl_LF& y) { return x = x * y; } +inline cl_LF& operator/= (cl_LF& x, const cl_LF& y) { return x = x / y; } +#endif + + +// Runtime typing support. +extern cl_class cl_class_lfloat; + + +// Debugging support. +#ifdef CL_DEBUG +extern int cl_LF_debug_module; +static void* const cl_LF_debug_dummy[] = { &cl_LF_debug_dummy, + &cl_LF_debug_module +}; +#endif + + +#endif /* _CL_LFLOAT_H */ diff --git a/include/cl_lfloat_class.h b/include/cl_lfloat_class.h new file mode 100644 index 0000000..1062652 --- /dev/null +++ b/include/cl_lfloat_class.h @@ -0,0 +1,64 @@ +// Concrete class of long float numbers. + +#ifndef _CL_LFLOAT_CLASS_H +#define _CL_LFLOAT_CLASS_H + +#include "cl_number.h" +#include "cl_float_class.h" + + +class cl_LF : public cl_F { +public: +// Default constructor. + cl_LF (); +// Assignment operators. + cl_LF& operator= (const cl_LF&); +// Optimization of method pointer_p(). + cl_boolean pointer_p() const + { return cl_true; } +// Faster pointer_p() gives a faster copy constructor (but not destructor!!!). + cl_LF (const cl_LF& x); +// Other constructors. + cl_LF (const char *); +// Private constructor. + cl_LF (cl_private_thing); + cl_LF (struct cl_heap_lfloat *); +// Private pointer manipulations. + operator struct cl_heap_lfloat * () const; +public: // Ability to place an object at a given address. + void* operator new (size_t size) { return cl_malloc_hook(size); } + void* operator new (size_t size, cl_LF* ptr) { (void)size; return ptr; } + void operator delete (void* ptr) { cl_free_hook(ptr); } +}; +// Define this if you want the elementary cl_LF operations (+, -, *, /, +// sqrt, cl_LF_I_mul) to return results which are always the correctly +// rounded exact results, i.e. results which are correct within 0.5 ulp. +// If you don't define this, results will be correct within 0.50001 ulp, +// but often the computation will be much faster. +/* #define CL_LF_PEDANTIC */ + +// Private constructors. +inline cl_LF::cl_LF (cl_private_thing ptr) : cl_F (ptr) {} +// The assignment operators: +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_LF, cl_LF) +// The default constructors. +// Private pointer manipulations. Never throw away a `struct cl_heap_lfloat *'! +inline cl_LF::operator struct cl_heap_lfloat * () const +{ + struct cl_heap_lfloat * hpointer = (struct cl_heap_lfloat *) pointer; + cl_inc_refcount(*this); + return hpointer; +} +extern const cl_LF cl_LF_0; +inline cl_LF::cl_LF () + : cl_F ((cl_private_thing) (struct cl_heap_lfloat *) cl_LF_0) {} +CL_REQUIRE(cl_LF_globals) +#if 0 // see cl_LF_impl.h +inline cl_LF::cl_LF (struct cl_heap_lfloat * ptr) + : cl_F ((cl_private_thing) ptr) {} +#endif +// The copy constructors. +CL_DEFINE_COPY_CONSTRUCTOR2(cl_LF,cl_F) + + +#endif /* _CL_LFLOAT_CLASS_H */ diff --git a/include/cl_lfloat_io.h b/include/cl_lfloat_io.h new file mode 100644 index 0000000..ff66c34 --- /dev/null +++ b/include/cl_lfloat_io.h @@ -0,0 +1,27 @@ +// I/O of lfloats. + +#ifndef _CL_LFLOAT_IO_H +#define _CL_LFLOAT_IO_H + +#include "cl_number_io.h" +#include "cl_lfloat.h" + +inline cl_istream operator>> (cl_istream stream, cl_LF& result) +{ + extern cl_read_flags cl_LF_read_flags; + extern const cl_F read_float (cl_istream, const cl_read_flags&); + result = As(cl_LF)(read_float(stream,cl_LF_read_flags)); + return stream; +} + +// The following does strictly the same as the general `fprint' for floats. +// It is here only so that people don't need to include . +inline void fprint (cl_ostream stream, const cl_LF& x) +{ + extern void print_float (cl_ostream stream, const cl_print_flags& flags, const cl_F& z); + extern cl_print_flags cl_default_print_flags; + print_float(stream,cl_default_print_flags,x); +} +CL_DEFINE_PRINT_OPERATOR(cl_LF) + +#endif /* _CL_LFLOAT_IO_H */ diff --git a/include/cl_malloc.h b/include/cl_malloc.h new file mode 100644 index 0000000..1528438 --- /dev/null +++ b/include/cl_malloc.h @@ -0,0 +1,13 @@ +// User modifiable memory allocator. + +#ifndef _CL_MALLOC_H +#define _CL_MALLOC_H + +#include + +// Function like malloc() which returns aligned memory of size (> 0) bytes. +extern void* (*cl_malloc_hook) (size_t size); +// Function like free() which makes available for reuse such memory. +extern void (*cl_free_hook) (void* ptr); + +#endif /* _CL_MALLOC_H */ diff --git a/include/cl_modinteger.h b/include/cl_modinteger.h new file mode 100644 index 0000000..06c9a85 --- /dev/null +++ b/include/cl_modinteger.h @@ -0,0 +1,470 @@ +// Modular integer operations. + +#ifndef _CL_MODINTEGER_H +#define _CL_MODINTEGER_H + +#include "cl_object.h" +#include "cl_ring.h" +#include "cl_integer.h" +#include "cl_random.h" +#include "cl_malloc.h" +#include "cl_io.h" +#include "cl_proplist.h" +#include "cl_condition.h" +#include "cl_abort.h" +#undef random // Linux defines random() as a macro! + + +// Representation of an element of a ring Z/mZ. + +// To protect against mixing elements of different modular rings, such as +// (3 mod 4) + (2 mod 5), every modular integer carries its ring in itself. + + +// Representation of a ring Z/mZ. + +class cl_heap_modint_ring; + +class cl_modint_ring : public cl_ring { +public: + // Default constructor. + cl_modint_ring (); + // Constructor. Takes a cl_heap_modint_ring*, increments its refcount. + cl_modint_ring (cl_heap_modint_ring* r); + // Copy constructor. + cl_modint_ring (const cl_modint_ring&); + // Assignment operator. + cl_modint_ring& operator= (const cl_modint_ring&); + // Automatic dereferencing. + cl_heap_modint_ring* operator-> () const + { return (cl_heap_modint_ring*)heappointer; } +}; + +// Z/0Z +extern const cl_modint_ring cl_modint0_ring; +// Default constructor. This avoids dealing with NULL pointers. +inline cl_modint_ring::cl_modint_ring () + : cl_ring (as_cl_private_thing(cl_modint0_ring)) {} +CL_REQUIRE(cl_MI) +// Copy constructor and assignment operator. +CL_DEFINE_COPY_CONSTRUCTOR2(cl_modint_ring,cl_ring) +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_modint_ring,cl_modint_ring) + +// Normal constructor for `cl_modint_ring'. +inline cl_modint_ring::cl_modint_ring (cl_heap_modint_ring* r) + : cl_ring ((cl_private_thing) (cl_inc_pointer_refcount((cl_heap*)r), r)) {} + +// Operations on modular integer rings. + +inline bool operator== (const cl_modint_ring& R1, const cl_modint_ring& R2) +{ return (R1.pointer == R2.pointer); } +inline bool operator!= (const cl_modint_ring& R1, const cl_modint_ring& R2) +{ return (R1.pointer != R2.pointer); } +inline bool operator== (const cl_modint_ring& R1, cl_heap_modint_ring* R2) +{ return (R1.pointer == R2); } +inline bool operator!= (const cl_modint_ring& R1, cl_heap_modint_ring* R2) +{ return (R1.pointer != R2); } + + +// Condition raised when a probable prime is discovered to be composite. +struct cl_composite_condition : public cl_condition { + SUBCLASS_cl_condition() + cl_I p; // the non-prime + cl_I factor; // a nontrivial factor, or 0 + // Constructors. + cl_composite_condition (const cl_I& _p) + : p (_p), factor (0) + { print(cl_stderr); } + cl_composite_condition (const cl_I& _p, const cl_I& _f) + : p (_p), factor (_f) + { print(cl_stderr); } + // Implement general condition methods. + const char * name () const; + void print (cl_ostream) const; + ~cl_composite_condition () {} +}; + + +// Representation of an element of a ring Z/mZ. + +class _cl_MI /* cf. _cl_ring_element */ { +public: + cl_I rep; // representative, integer >=0, 0 + const _cl_MI (* expt_pos) (cl_heap_modint_ring* R, const _cl_MI& x, const cl_I& y); + // x^-1 + const cl_MI_x (* recip) (cl_heap_modint_ring* R, const _cl_MI& x); + // x*y^-1 + const cl_MI_x (* div) (cl_heap_modint_ring* R, const _cl_MI& x, const _cl_MI& y); + // x^y, y Integer + const cl_MI_x (* expt) (cl_heap_modint_ring* R, const _cl_MI& x, const cl_I& y); + // x -> x mod m for x>=0 + const cl_I (* reduce_modulo) (cl_heap_modint_ring* R, const cl_I& x); + // some inverse of canonical homomorphism + const cl_I (* retract) (cl_heap_modint_ring* R, const _cl_MI& x); +}; +#if defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 8) // workaround two g++-2.7.0 bugs + #define cl_modint_setops _cl_modint_setops + #define cl_modint_addops _cl_modint_addops + #define cl_modint_mulops _cl_modint_mulops +#else + typedef const _cl_modint_setops cl_modint_setops; + typedef const _cl_modint_addops cl_modint_addops; + typedef const _cl_modint_mulops cl_modint_mulops; +#endif + +// Representation of the ring Z/mZ. + +// Currently rings are garbage collected only when they are not referenced +// any more and when the ring table gets full. + +// Modular integer rings are kept unique in memory. This way, ring equality +// can be checked very efficiently by a simple pointer comparison. + +class cl_heap_modint_ring /* cf. cl_heap_ring */ : public cl_heap { + SUBCLASS_cl_heap_ring() +private: + cl_property_list properties; +protected: + cl_modint_setops* setops; + cl_modint_addops* addops; + cl_modint_mulops* mulops; +public: + cl_I modulus; // m, normalized to be >= 0 +public: + // Low-level operations. + void _fprint (cl_ostream stream, const _cl_MI& x) + { setops->fprint(this,stream,x); } + cl_boolean _equal (const _cl_MI& x, const _cl_MI& y) + { return setops->equal(this,x,y); } + const _cl_MI _random (cl_random_state& randomstate) + { return setops->random(this,randomstate); } + const _cl_MI _zero () + { return addops->zero(this); } + cl_boolean _zerop (const _cl_MI& x) + { return addops->zerop(this,x); } + const _cl_MI _plus (const _cl_MI& x, const _cl_MI& y) + { return addops->plus(this,x,y); } + const _cl_MI _minus (const _cl_MI& x, const _cl_MI& y) + { return addops->minus(this,x,y); } + const _cl_MI _uminus (const _cl_MI& x) + { return addops->uminus(this,x); } + const _cl_MI _one () + { return mulops->one(this); } + const _cl_MI _canonhom (const cl_I& x) + { return mulops->canonhom(this,x); } + const _cl_MI _mul (const _cl_MI& x, const _cl_MI& y) + { return mulops->mul(this,x,y); } + const _cl_MI _square (const _cl_MI& x) + { return mulops->square(this,x); } + const _cl_MI _expt_pos (const _cl_MI& x, const cl_I& y) + { return mulops->expt_pos(this,x,y); } + const cl_MI_x _recip (const _cl_MI& x) + { return mulops->recip(this,x); } + const cl_MI_x _div (const _cl_MI& x, const _cl_MI& y) + { return mulops->div(this,x,y); } + const cl_MI_x _expt (const _cl_MI& x, const cl_I& y) + { return mulops->expt(this,x,y); } + const cl_I _reduce_modulo (const cl_I& x) + { return mulops->reduce_modulo(this,x); } + const cl_I _retract (const _cl_MI& x) + { return mulops->retract(this,x); } + // High-level operations. + void fprint (cl_ostream stream, const cl_MI& x) + { + if (!(x.ring() == this)) cl_abort(); + _fprint(stream,x); + } + cl_boolean equal (const cl_MI& x, const cl_MI& y) + { + if (!(x.ring() == this)) cl_abort(); + if (!(y.ring() == this)) cl_abort(); + return _equal(x,y); + } + const cl_MI random (cl_random_state& randomstate = cl_default_random_state) + { + return cl_MI(this,_random(randomstate)); + } + const cl_MI zero () + { + return cl_MI(this,_zero()); + } + cl_boolean zerop (const cl_MI& x) + { + if (!(x.ring() == this)) cl_abort(); + return _zerop(x); + } + const cl_MI plus (const cl_MI& x, const cl_MI& y) + { + if (!(x.ring() == this)) cl_abort(); + if (!(y.ring() == this)) cl_abort(); + return cl_MI(this,_plus(x,y)); + } + const cl_MI minus (const cl_MI& x, const cl_MI& y) + { + if (!(x.ring() == this)) cl_abort(); + if (!(y.ring() == this)) cl_abort(); + return cl_MI(this,_minus(x,y)); + } + const cl_MI uminus (const cl_MI& x) + { + if (!(x.ring() == this)) cl_abort(); + return cl_MI(this,_uminus(x)); + } + const cl_MI one () + { + return cl_MI(this,_one()); + } + const cl_MI canonhom (const cl_I& x) + { + return cl_MI(this,_canonhom(x)); + } + const cl_MI mul (const cl_MI& x, const cl_MI& y) + { + if (!(x.ring() == this)) cl_abort(); + if (!(y.ring() == this)) cl_abort(); + return cl_MI(this,_mul(x,y)); + } + const cl_MI square (const cl_MI& x) + { + if (!(x.ring() == this)) cl_abort(); + return cl_MI(this,_square(x)); + } + const cl_MI expt_pos (const cl_MI& x, const cl_I& y) + { + if (!(x.ring() == this)) cl_abort(); + return cl_MI(this,_expt_pos(x,y)); + } + const cl_MI_x recip (const cl_MI& x) + { + if (!(x.ring() == this)) cl_abort(); + return _recip(x); + } + const cl_MI_x div (const cl_MI& x, const cl_MI& y) + { + if (!(x.ring() == this)) cl_abort(); + if (!(y.ring() == this)) cl_abort(); + return _div(x,y); + } + const cl_MI_x expt (const cl_MI& x, const cl_I& y) + { + if (!(x.ring() == this)) cl_abort(); + return _expt(x,y); + } + const cl_I reduce_modulo (const cl_I& x) + { + return _reduce_modulo(x); + } + const cl_I retract (const cl_MI& x) + { + if (!(x.ring() == this)) cl_abort(); + return _retract(x); + } + // Miscellaneous. + sintL bits; // number of bits needed to represent a representative, or -1 + int log2_bits; // log_2(bits), or -1 + // Property operations. + cl_property* get_property (const cl_symbol& key) + { return properties.get_property(key); } + void add_property (cl_property* new_property) + { properties.add_property(new_property); } +// Constructor. + cl_heap_modint_ring (cl_I m, cl_modint_setops*, cl_modint_addops*, cl_modint_mulops*); +// This class is intented to be subclassable, hence needs a virtual destructor. + virtual ~cl_heap_modint_ring () {} +private: + virtual void dummy (); +}; +#define SUBCLASS_cl_heap_modint_ring() \ + SUBCLASS_cl_heap_ring() + +// Lookup or create a modular integer ring Z/mZ +extern const cl_modint_ring cl_find_modint_ring (const cl_I& m); +CL_REQUIRE(cl_MI) + +// Runtime typing support. +extern cl_class cl_class_modint_ring; + + +// Operations on modular integers. + +// Output. +inline void fprint (cl_ostream stream, const cl_MI& x) + { x.ring()->fprint(stream,x); } +CL_DEFINE_PRINT_OPERATOR(cl_MI) + +// Add. +inline const cl_MI operator+ (const cl_MI& x, const cl_MI& y) + { return x.ring()->plus(x,y); } +inline const cl_MI operator+ (const cl_MI& x, const cl_I& y) + { return x.ring()->plus(x,x.ring()->canonhom(y)); } +inline const cl_MI operator+ (const cl_I& x, const cl_MI& y) + { return y.ring()->plus(y.ring()->canonhom(x),y); } + +// Negate. +inline const cl_MI operator- (const cl_MI& x) + { return x.ring()->uminus(x); } + +// Subtract. +inline const cl_MI operator- (const cl_MI& x, const cl_MI& y) + { return x.ring()->minus(x,y); } +inline const cl_MI operator- (const cl_MI& x, const cl_I& y) + { return x.ring()->minus(x,x.ring()->canonhom(y)); } +inline const cl_MI operator- (const cl_I& x, const cl_MI& y) + { return y.ring()->minus(y.ring()->canonhom(x),y); } + +// Shifts. +extern const cl_MI operator<< (const cl_MI& x, sintL y); // assume 0 <= y < 2^31 +extern const cl_MI operator>> (const cl_MI& x, sintL y); // assume m odd, 0 <= y < 2^31 + +// Equality. +inline bool operator== (const cl_MI& x, const cl_MI& y) + { return x.ring()->equal(x,y); } +inline bool operator!= (const cl_MI& x, const cl_MI& y) + { return !x.ring()->equal(x,y); } +inline bool operator== (const cl_MI& x, const cl_I& y) + { return x.ring()->equal(x,x.ring()->canonhom(y)); } +inline bool operator!= (const cl_MI& x, const cl_I& y) + { return !x.ring()->equal(x,x.ring()->canonhom(y)); } +inline bool operator== (const cl_I& x, const cl_MI& y) + { return y.ring()->equal(y.ring()->canonhom(x),y); } +inline bool operator!= (const cl_I& x, const cl_MI& y) + { return !y.ring()->equal(y.ring()->canonhom(x),y); } + +// Compare against 0. +inline cl_boolean zerop (const cl_MI& x) + { return x.ring()->zerop(x); } + +// Multiply. +inline const cl_MI operator* (const cl_MI& x, const cl_MI& y) + { return x.ring()->mul(x,y); } + +// Squaring. +inline const cl_MI square (const cl_MI& x) + { return x.ring()->square(x); } + +// Exponentiation x^y, where y > 0. +inline const cl_MI expt_pos (const cl_MI& x, const cl_I& y) + { return x.ring()->expt_pos(x,y); } + +// Reciprocal. +inline const cl_MI recip (const cl_MI& x) + { return x.ring()->recip(x); } + +// Division. +inline const cl_MI div (const cl_MI& x, const cl_MI& y) + { return x.ring()->div(x,y); } +inline const cl_MI div (const cl_MI& x, const cl_I& y) + { return x.ring()->div(x,x.ring()->canonhom(y)); } +inline const cl_MI div (const cl_I& x, const cl_MI& y) + { return y.ring()->div(y.ring()->canonhom(x),y); } + +// Exponentiation x^y. +inline const cl_MI expt (const cl_MI& x, const cl_I& y) + { return x.ring()->expt(x,y); } + +// Scalar multiplication. +inline const cl_MI operator* (const cl_I& x, const cl_MI& y) + { return y.ring()->mul(y.ring()->canonhom(x),y); } +inline const cl_MI operator* (const cl_MI& x, const cl_I& y) + { return x.ring()->mul(x.ring()->canonhom(y),x); } + +// TODO: implement gcd, index (= gcd), unitp, sqrtp + + +// Debugging support. +#ifdef CL_DEBUG +extern int cl_MI_debug_module; +static void* const cl_MI_debug_dummy[] = { &cl_MI_debug_dummy, + &cl_MI_debug_module +}; +#endif + + +#endif /* _CL_MODINTEGER_H */ diff --git a/include/cl_modules.h b/include/cl_modules.h new file mode 100644 index 0000000..913e443 --- /dev/null +++ b/include/cl_modules.h @@ -0,0 +1,203 @@ +// Macros for correct module ordering. + +#ifndef _CL_MODULES_H +#define _CL_MODULES_H + +// The order of initialization of different compilation units is not +// specified in C++. AIX 4 has a linker which apparently does order +// the modules according to dependencies, so that low-level modules +// will be initialized earlier than the high-level modules which depend +// on them. I have a patch for GNU ld that does the same thing. +// +// But for now, I take a half-automatic approach to the correct module +// ordering problem: PROVIDE/REQUIRE, as in Common Lisp. +// +// CL_PROVIDE(module) must be the first code-generating entity in a module. +// Inline function definitions can precede it, but global variable/function/ +// class definitions may not precede it. +// Afterwards, any number of CL_REQUIRE(othermodule) is allowed. +// At the end of the module, there must be a corresponding +// CL_PROVIDE_END(module). (Sorry for this, it's really needed.) +// +// These macros work only with g++, and only in optimizing mode. But who +// wants to use CLN with other C++ compilers anyway... + +// How to apply these macros: +// 1. Find out about variables which need to be initialized. +// On Linux/ELF, you can use a command like +// $ nm -o libcln.a | grep -v ' [UTtRrW] ' | sort +1 +// A symbol of type "D" or "d" lies in the preinitialized DATA section, +// a symbol of type "B" or "b" lies in the uninitialized BSS section. +// All of them have to be checked. +// - Those which contain POD (= plain old data, i.e. scalar values or +// class instances without nontrivial constructors) are already fully +// initialized by the linker and can be discarded from these considerations. +// - Those which are static variables inside a function (you recognize +// them: g++ appends a dot and a number to their name) are initialized +// the first time the function is entered. They can be discarded from +// our considerations as well. +// 2. Find out which of these variables are publically exposed (to the user of +// the library) through the library's include files, either directly or +// through inline functions, or indirectly through normal function calls. +// These variables can be referenced from any user module U, hence any +// such module must CL_REQUIRE(M) the variable's definition module M. +// Since there is no CL_REQUIRE_IF_NEEDED(M) macro (which is equivalent +// to CL_REQUIRE(M) if the required module will be part of the executable +// but does nothing if M is not used), we must preventively put the +// CL_REQUIRE(M) into the header file. Hopefully M is either used anyway +// or does not bring in too much code into the executable. +// 3. Variables which are not publicly exposed but used internally by the +// library can be handled by adding a CL_REQUIRE in all the library's +// modules which directly or indirectly use the variable. +// 4. Variables and functions which can be reasonably assumed to not be +// accessed or executed during initialization need not be treated. +// For example, I/O to external streams, exception handling facilities, +// number theory stuff, etc. + +// OK, stop reading here, because it's getting obscene. + +#if defined(__GNUC__) && defined(__OPTIMIZE__) && !(defined(__hppa__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 8)) && !defined(NO_PROVIDE_REQUIRE) + #ifdef ASM_UNDERSCORE + #define ASM_UNDERSCORE_PREFIX "_" + #else + #define ASM_UNDERSCORE_PREFIX "" + #endif + // Globalize a label defined in the same translation unit. + // See macro ASM_GLOBALIZE_LABEL in the egcs sources. + #if defined(__i386__) || defined(__m68k__) || defined(__mips__) || defined(__mips64__) || defined(__alpha__) || defined(__rs6000__) + // Some m68k systems use "xdef" or "global" or ".global"... + #define CL_GLOBALIZE_LABEL(label) __asm__("\t.globl " label); + #endif + #if defined(__sparc__) || defined(__sparc64__) || defined(__arm__) + // Some arm systems use "EXPORT" or ".globl"... + #define CL_GLOBALIZE_LABEL(label) __asm__("\t.global " label); + #endif + #if defined(__hppa__) + #define CL_GLOBALIZE_LABEL(label) __asm__("\t.EXPORT " label ",ENTRY,PRIV_LEV=3"); + #endif + #if defined(__m88k__) + #define CL_GLOBALIZE_LABEL(label) __asm__("\tglobal " label); + #endif + #if defined(__convex__) + #define CL_GLOBALIZE_LABEL(label) __asm__(".globl " label); + #endif + #ifndef CL_GLOBALIZE_LABEL + #define CL_GLOBALIZE_LABEL(label) + #endif + #if defined(__rs6000__) || defined(_WIN32) + #define CL_GLOBALIZE_JUMP_LABEL(label) CL_GLOBALIZE_LABEL(#label) + #else + #define CL_GLOBALIZE_JUMP_LABEL(label) + #endif + #ifdef CL_NEED_GLOBALIZE_CTORDTOR + #define CL_GLOBALIZE_CTORDTOR_LABEL(label) CL_GLOBALIZE_LABEL(label) + #else + #define CL_GLOBALIZE_CTORDTOR_LABEL(label) + #endif + // Output a label inside a function. + // See macro ASM_OUTPUT_LABEL in the egcs sources. + #if defined(__hppa__) + #define CL_OUTPUT_LABEL(label) ASM_VOLATILE ("\n" label) + #else + #define CL_OUTPUT_LABEL(label) ASM_VOLATILE ("\n" label ":") + #endif + // ASM_VOLATILE(string) is for asms without arguments only!! + #if ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 91)) || (__GNUC__ >= 3) + // avoid warning caused by the volatile keyword + #define ASM_VOLATILE __asm__ + #else + // need volatile to avoid reordering + #define ASM_VOLATILE __asm__ __volatile__ + #endif + // CL_JUMP_TO(addr) jumps to an address, like goto *(void*)(addr), + // except that the latter inhibits inlining of the function containing it + // in gcc-2.95. For new CPUs, look for "jump" and "indirect_jump" in gcc's + // machine description. + #if defined(__i386__) + #define CL_JUMP_TO(addr) ASM_VOLATILE("jmp %*%0" : : "rm" ((void*)(addr))) + #endif + #if defined(__m68k__) + #define CL_JUMP_TO(addr) ASM_VOLATILE("jmp %0@" : : "a" ((void*)(addr))) + #endif + #if defined(__mips__) + #define CL_JUMP_TO(addr) ASM_VOLATILE("%*j %0" : : "d" ((void*)(addr))) + #endif + #if defined(__sparc__) || defined(__sparc64__) + #define CL_JUMP_TO(addr) ASM_VOLATILE("jmp %0\n\tnop" : : "r" ((void*)(addr))) + #endif + #if defined(__alpha__) + #define CL_JUMP_TO(addr) ASM_VOLATILE("jmp $31,(%0),0" : : "r" ((void*)(addr))) + #endif + #if defined(__hppa__) + //#define CL_JUMP_TO(addr) ASM_VOLATILE("bv,n 0(%0)" : : "r" ((void*)(addr))) + #define CL_JUMP_TO(addr) ASM_VOLATILE("b " #addr "\n\tnop") + #endif + #if defined(__arm__) + #define CL_JUMP_TO(addr) ASM_VOLATILE("mov pc,%0" : : "r" ((void*)(addr))) + #endif + #if defined(__rs6000__) || defined(__powerpc__) || defined(__ppc__) + //#define CL_JUMP_TO(addr) ASM_VOLATILE("mtctr %0\n\tbctr" : : "r" ((void*)(addr))) + #define CL_JUMP_TO(addr) ASM_VOLATILE("b " #addr) + #endif + #if defined(__m88k__) + #define CL_JUMP_TO(addr) ASM_VOLATILE("jmp %0" : : "r" ((void*)(addr))) + #endif + #if defined(__convex__) + #define CL_JUMP_TO(addr) ASM_VOLATILE("jmp (%0)" : : "r" ((void*)(addr))) + #endif + #define CL_PROVIDE(module) \ + extern "C" void cl_module__##module##__firstglobalfun () {} \ + extern "C" void cl_module__##module##__ctorend (void); \ + extern "C" void cl_module__##module##__dtorend (void); \ + CL_GLOBALIZE_JUMP_LABEL(cl_module__##module##__ctorend) \ + CL_GLOBALIZE_JUMP_LABEL(cl_module__##module##__dtorend) \ + CL_GLOBALIZE_CTORDTOR_LABEL( \ + ASM_UNDERSCORE_PREFIX CL_GLOBAL_CONSTRUCTOR_PREFIX \ + "cl_module__" #module "__firstglobalfun") \ + CL_GLOBALIZE_CTORDTOR_LABEL( \ + ASM_UNDERSCORE_PREFIX CL_GLOBAL_DESTRUCTOR_PREFIX \ + "cl_module__" #module "__firstglobalfun") \ + static int cl_module__##module##__counter; \ + struct cl_module__##module##__controller { \ + inline cl_module__##module##__controller () \ + { if (cl_module__##module##__counter++) \ + { CL_JUMP_TO(cl_module__##module##__ctorend); } \ + } \ + inline ~cl_module__##module##__controller () \ + { CL_OUTPUT_LABEL (ASM_UNDERSCORE_PREFIX "cl_module__" #module "__dtorend"); } \ + }; \ + static cl_module__##module##__controller cl_module__##module##__ctordummy; + #define CL_PROVIDE_END(module) \ + struct cl_module__##module##__destroyer { \ + inline cl_module__##module##__destroyer () \ + { CL_OUTPUT_LABEL (ASM_UNDERSCORE_PREFIX "cl_module__" #module "__ctorend"); } \ + inline ~cl_module__##module##__destroyer () \ + { if (--cl_module__##module##__counter) \ + { CL_JUMP_TO(cl_module__##module##__dtorend); } \ + } \ + }; \ + static cl_module__##module##__destroyer cl_module__##module##__dtordummy; + #define CL_REQUIRE(module) \ + extern "C" void cl_module__##module##__ctor (void) \ + __asm__ (ASM_UNDERSCORE_PREFIX CL_GLOBAL_CONSTRUCTOR_PREFIX \ + "cl_module__" #module "__firstglobalfun"); \ + extern "C" void cl_module__##module##__dtor (void) \ + __asm__ (ASM_UNDERSCORE_PREFIX CL_GLOBAL_DESTRUCTOR_PREFIX \ + "cl_module__" #module "__firstglobalfun"); \ + struct _CL_REQUIRE_CLASSNAME(module,__LINE__) { \ + inline _CL_REQUIRE_CLASSNAME(module,__LINE__) () \ + { cl_module__##module##__ctor (); } \ + inline ~_CL_REQUIRE_CLASSNAME(module,__LINE__) () \ + { cl_module__##module##__dtor (); } \ + }; \ + static _CL_REQUIRE_CLASSNAME(module,__LINE__) \ + _CL_REQUIRE_CLASSNAME(module##_requirer,__LINE__); + #define _CL_REQUIRE_CLASSNAME(module,line) __CL_REQUIRE_CLASSNAME(module,line) + #define __CL_REQUIRE_CLASSNAME(module,line) cl_module__##module##__##line +#else + #define CL_PROVIDE(module) + #define CL_PROVIDE_END(module) + #define CL_REQUIRE(module) +#endif + +#endif /* _CL_MODULES_H */ diff --git a/include/cl_null_ring.h b/include/cl_null_ring.h new file mode 100644 index 0000000..4a49171 --- /dev/null +++ b/include/cl_null_ring.h @@ -0,0 +1,12 @@ +// Built-in null ring. + +#ifndef _CL_NULL_RING_H +#define _CL_NULL_RING_H + +#include "cl_ring.h" + +class cl_null_ring : public cl_ring { public: cl_null_ring (); }; +extern const cl_null_ring cl_0_ring; // math. {0} +//CL_REQUIRE(cl_0_ring) + +#endif /* _CL_NULL_RING_H */ diff --git a/include/cl_number.h b/include/cl_number.h new file mode 100644 index 0000000..e46fbab --- /dev/null +++ b/include/cl_number.h @@ -0,0 +1,245 @@ +// Basic definitions of numbers + +#ifndef _CL_NUMBER_H +#define _CL_NUMBER_H + +#include "cl_object.h" +#include "cl_malloc.h" + +// Type hierachy: +// Number (N) = +// Real (R) = +// Float (F) = +// Short float (SF) +// Single float (FF) +// Double float (DF) +// Long float (LF) +// Rational (RA) = +// Integer (I) = +// Fixnum (FN) +// Bignum (BN) +// Ratio (RT) +// Complex (C) + + +// Constructors and assignment operators from C numeric types. + +#define CL_DEFINE_INT_CONSTRUCTOR(_class_,_type_) \ +inline _class_::_class_ (const _type_ wert) \ +{ \ + word = cl_combine(cl_FN_tag,wert); \ +} +#define CL_DEFINE_INT_CONSTRUCTORS(_class_) \ +CL_DEFINE_INT_CONSTRUCTOR(_class_, int) \ +CL_DEFINE_INT_CONSTRUCTOR(_class_, unsigned int) + +#define CL_DEFINE_INT_ASSIGNMENT_OPERATOR(_class_,_type_) \ +inline _class_& _class_::operator= (const _type_ wert) \ +{ \ + cl_dec_refcount(*this); \ + word = cl_combine(cl_FN_tag,wert); \ + return *this; \ +} +#define CL_DEFINE_INT_ASSIGNMENT_OPERATORS(_class_) \ +CL_DEFINE_INT_ASSIGNMENT_OPERATOR(_class_, int) \ +CL_DEFINE_INT_ASSIGNMENT_OPERATOR(_class_, unsigned int) + +#if (long_bitsize==32) +// `long' == `sintL', `unsigned long' == `uintL'. +#define CL_DEFINE_LONG_CONSTRUCTORS(_class_) \ +inline _class_::_class_ (const long wert) \ +{ \ + extern cl_private_thing cl_I_constructor_from_L (sint32 wert); \ + pointer = cl_I_constructor_from_L(wert); \ +} \ +inline _class_::_class_ (const unsigned long wert) \ +{ \ + extern cl_private_thing cl_I_constructor_from_UL (uint32 wert); \ + pointer = cl_I_constructor_from_UL(wert); \ +} +#elif (long_bitsize==64) +// `long' == `sintQ', `unsigned long' == `uintQ'. +#define CL_DEFINE_LONG_CONSTRUCTORS(_class_) \ +inline _class_::_class_ (const long wert) \ +{ \ + extern cl_private_thing cl_I_constructor_from_Q (sint64 wert); \ + pointer = cl_I_constructor_from_Q(wert); \ +} \ +inline _class_::_class_ (const unsigned long wert) \ +{ \ + extern cl_private_thing cl_I_constructor_from_UQ (uint64 wert); \ + pointer = cl_I_constructor_from_UQ(wert); \ +} +#endif + +#if (long_bitsize==32) +// `long' == `sintL', `unsigned long' == `uintL'. +#define CL_DEFINE_LONG_ASSIGNMENT_OPERATORS(_class_) \ +inline _class_& _class_::operator= (const long wert) \ +{ \ + extern cl_private_thing cl_I_constructor_from_L (sint32 wert); \ + cl_dec_refcount(*this); \ + pointer = cl_I_constructor_from_L(wert); \ + return *this; \ +} \ +inline _class_& _class_::operator= (const unsigned long wert) \ +{ \ + extern cl_private_thing cl_I_constructor_from_UL (uint32 wert); \ + cl_dec_refcount(*this); \ + pointer = cl_I_constructor_from_UL(wert); \ + return *this; \ +} +#elif (long_bitsize==64) +// `long' == `sintQ', `unsigned long' == `uintQ'. +#define CL_DEFINE_LONG_ASSIGNMENT_OPERATORS(_class_) \ +inline _class_& _class_::operator= (const long wert) \ +{ \ + extern cl_private_thing cl_I_constructor_from_Q (sint64 wert); \ + cl_dec_refcount(*this); \ + pointer = cl_I_constructor_from_Q(wert); \ + return *this; \ +} \ +inline _class_& _class_::operator= (const unsigned long wert) \ +{ \ + extern cl_private_thing cl_I_constructor_from_UQ (uint64 wert); \ + cl_dec_refcount(*this); \ + pointer = cl_I_constructor_from_UQ(wert); \ + return *this; \ +} +#endif + + +// Conversions to subtypes: +// As(cl_I)(x) returns x as a cl_I. It first checks that x is a cl_I +// and then returns it without change of representation. +#if 0 // no debug information + #define As(type) as_##type + #define CL_DEFINE_AS_CONVERSION(_class_) \ + extern const _class_& as_##_class_ (const cl_number& x); \ + inline const _class_& as_##_class_ (const _class_& x) { return x; } +#else // Line number information for ease of debugging. + #define As(type) as_##type cl_as_aux + #define cl_as_aux(expr) (expr,__FILE__,__LINE__) + #define CL_DEFINE_AS_CONVERSION(_class_) \ + extern const _class_& as_##_class_ (const cl_number& x, const char * filename, int line); \ + inline const _class_& as_##_class_ (const _class_& x, const char * filename, int line) { (void)filename; (void)line; return x; } +#endif + + +// Constructors and assignment operators from C numeric types. + +// from `float': +extern cl_private_thing cl_float_to_FF_pointer (const union ffloatjanus& val); + +#define CL_DEFINE_FLOAT_CONSTRUCTOR(_class_) \ +inline _class_ :: _class_ (const float x) \ +{ \ + pointer = cl_float_to_FF_pointer(*(const union ffloatjanus *)&x); \ +} \ +inline _class_& _class_::operator= (const float x) \ +{ \ + cl_dec_refcount(*this); \ + pointer = cl_float_to_FF_pointer(*(const union ffloatjanus *)&x); \ + return *this; \ +} + +// from `double': +extern struct cl_heap_dfloat * cl_double_to_DF_pointer (const union dfloatjanus& val); + +#define CL_DEFINE_DOUBLE_CONSTRUCTOR(_class_) \ +inline _class_::_class_ (const double x) \ +{ \ + pointer = cl_double_to_DF_pointer(*(const union dfloatjanus *)&x); \ +} \ +inline _class_& _class_::operator= (const double x) \ +{ \ + cl_dec_refcount(*this); \ + pointer = cl_double_to_DF_pointer(*(const union dfloatjanus *)&x); \ + return *this; \ +} + + +// Abstract class of all numbers. + +class cl_number : public cl_gcobject { +public: +// Default constructor. (Used for objects with no initializer.) + cl_number (); +// Copy constructor. (Used for function argument passing and function +// return value, and of course for objects with initializers of the same type.) + cl_number (const cl_number& x); +// Converters. (Used for function argument passing and function return values.) +// Assignment operators. (Used for assignments.) + cl_number& operator= (const cl_number&); +// Constructors and assignment operators from C numeric types. + cl_number (const int); // |argument| must be < 2^29 + cl_number (const unsigned int); // argument must be < 2^29 + cl_number (const long); + cl_number (const unsigned long); + cl_number (const float); + cl_number (const double); + cl_number& operator= (const int); // |argument| must be < 2^29 + cl_number& operator= (const unsigned int); // argument must be < 2^29 + cl_number& operator= (const long); + cl_number& operator= (const unsigned long); + cl_number& operator= (const float); + cl_number& operator= (const double); +// Other constructors. +// cl_number (const char *); +// Private pointer manipulations. + cl_number (cl_private_thing); + cl_private_thing _as_cl_private_thing () const; +}; + +// Private constructors. +inline cl_number::cl_number (cl_private_thing ptr) : cl_gcobject (ptr) {} +// The assignment operators: +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_number, cl_number) +// The default constructors. +inline cl_number::cl_number () + : cl_gcobject ((cl_private_thing) cl_combine(cl_FN_tag,0)) {} +// The copy constructors. +CL_DEFINE_COPY_CONSTRUCTOR2(cl_number,cl_gcobject) +// Constructors and assignment operators from C numeric types. +CL_DEFINE_INT_CONSTRUCTORS(cl_number) +CL_DEFINE_INT_ASSIGNMENT_OPERATORS(cl_number) +CL_DEFINE_LONG_CONSTRUCTORS(cl_number) +CL_DEFINE_LONG_ASSIGNMENT_OPERATORS(cl_number) +CL_DEFINE_FLOAT_CONSTRUCTOR(cl_number) +CL_DEFINE_DOUBLE_CONSTRUCTOR(cl_number) + + +// Conversion: +//inline cl_N& cl_as_N (const cl_number& x) +//{ return *(cl_N*)(&x); } + + +// Hack section. + +// Conversions to subtypes without checking: +// The(cl_I)(x) converts x to a cl_I, without change of representation! + #define The(type) *(const type *) & cl_identity +// This inline function is for type checking purposes only. + inline const cl_number& cl_identity (const cl_number& x) { return x; } + +// Mutable(type,x); +// x should be a variable `const type x' or `const type& x'. +// This macro introduces a new variable `type& x' whose value can be +// modified. Useful for modifying the argument of a function which takes +// a `const type &x'. +// Warning: To apply this to a function's formal parameter, a block { ... } +// must be inserted. + #define Mutable(type,x) \ + type __copied_##x = x; \ + type& x = __copied_##x; + +// DeclareType(type,x); +// x should be a variable of some subtype of `cl_number'. type should be +// a subtype of `cl_number'. A new variable of the given type is declared, +// with name x and which refers to x (by reference, with const attribute). + #define DeclareType(type,x) \ + const type& __tmp_##x = *(const type*) &x; \ + const type& x = __tmp_##x; + + +#endif /* _CL_NUMBER_H */ diff --git a/include/cl_number_io.h b/include/cl_number_io.h new file mode 100644 index 0000000..0758c2b --- /dev/null +++ b/include/cl_number_io.h @@ -0,0 +1,34 @@ +// I/O of numbers. + +#ifndef _CL_NUMBER_IO_H +#define _CL_NUMBER_IO_H + +#include "cl_io.h" +#include "cl_number.h" + +// Input. + +// Finish with bad syntax. +#ifdef _CL_MACROS_H +nonreturning_function(extern, read_number_bad_syntax, (const char * string, const char * string_limit)); +#else +extern void read_number_bad_syntax (const char * string, const char * string_limit); +#endif + +// Finish with junk after the number. +#ifdef _CL_MACROS_H +nonreturning_function(extern, read_number_junk, (const char * string_rest, const char * string, const char * string_limit)); +#else +extern void read_number_junk (const char * string_rest, const char * string, const char * string_limit); +#endif + +// Finish with EOF. +#ifdef _CL_MACROS_H +nonreturning_function(extern, read_number_eof, (void)); +#else +extern void read_number_eof (void); +#endif + +struct cl_read_flags; + +#endif /* _CL_NUMBER_IO_H */ diff --git a/include/cl_numtheory.h b/include/cl_numtheory.h new file mode 100644 index 0000000..f4533f2 --- /dev/null +++ b/include/cl_numtheory.h @@ -0,0 +1,86 @@ +// Number theoretic operations. + +#ifndef _CL_NUMTHEORY_H +#define _CL_NUMTHEORY_H + +#include "cl_number.h" +#include "cl_integer.h" +#include "cl_modinteger.h" +#include "cl_condition.h" + +// jacobi(a,b) returns the Jacobi symbol +// ( a ) +// ( --- ) +// ( b ) +// a, b must be integers, b > 0, b odd. The result is 0 iff gcd(a,b) > 1. + extern int jacobi (sint32 a, sint32 b); + extern int jacobi (const cl_I& a, const cl_I& b); + +// isprobprime(n), n integer > 0, +// returns true when n is probably prime. +// This is pretty quick, but no caching is done. + extern cl_boolean isprobprime (const cl_I& n); + +// nextprobprime(x) returns the smallest probable prime >= x. + extern const cl_I nextprobprime (const cl_R& x); + +#if 0 +// primitive_root(R) of R = Z/pZ, with p a probable prime, +// returns +// either a generator of (Z/pZ)^*, assuming p is prime, or +// a proof that p is not prime, maybe even a non-trivial factor of p. +struct primitive_root_t { + cl_composite_condition* condition; + cl_MI gen; + // Constructors. + primitive_root_t (cl_composite_condition* c) : condition (c) {} + primitive_root_t (const cl_MI& g) : condition (NULL), gen (g) {} +}; +extern const primitive_root_t primitive_root (const cl_modint_ring& R); +#endif + +// sqrt_mod_p(R,x) where x is an element of R = Z/pZ, with p a probable prime, +// returns +// either the square roots of x in R, assuming p is prime, or +// a proof that p is not prime, maybe even a non-trivial factor of p. +struct sqrt_mod_p_t { + cl_composite_condition* condition; + // If no condition: + int solutions; // 0,1,2 + cl_I factor; // zero or non-trivial factor of p + cl_MI solution[2]; // max. 2 solutions + // Constructors. + sqrt_mod_p_t () {} + sqrt_mod_p_t (cl_composite_condition* c) : condition (c) {} + sqrt_mod_p_t (int s) : condition (NULL), solutions (s) {} + sqrt_mod_p_t (int s, const cl_MI& x0) : condition (NULL), solutions (s) + { solution[0] = x0; } + sqrt_mod_p_t (int s, const cl_MI& x0, const cl_MI& x1) : condition (NULL), solutions (s) + { solution[0] = x0; solution[1] = x1; } +}; +extern const sqrt_mod_p_t sqrt_mod_p (const cl_modint_ring& R, const cl_MI& x); + +// cornacchia1(d,p) solves x^2 + d*y^2 = p. +// cornacchia4(d,p) solves x^2 + d*y^2 = 4*p. +// d is an integer > 0, p is a probable prime. +// It returns +// either a nonnegative solution (x,y), if it exists, assuming p is prime, or +// a proof that p is not prime, maybe even a non-trivial factor of p. +struct cornacchia_t { + cl_composite_condition* condition; + // If no condition: + int solutions; // 0,1 + // If solutions=1 and d > 4 (d > 64 for cornacchia4): + // All solutions are (x,y), (-x,y), (x,-y), (-x,-y). + cl_I solution_x; // x >= 0 + cl_I solution_y; // y >= 0 + // Constructors. + cornacchia_t () {} + cornacchia_t (cl_composite_condition* c) : condition (c) {} + cornacchia_t (int s) : condition (NULL), solutions (s) {} + cornacchia_t (int s, const cl_I& x, const cl_I& y) : condition (NULL), solutions (s), solution_x (x), solution_y (y) {} +}; +extern const cornacchia_t cornacchia1 (const cl_I& d, const cl_I& p); +extern const cornacchia_t cornacchia4 (const cl_I& d, const cl_I& p); + +#endif /* _CL_NUMTHEORY_H */ diff --git a/include/cl_object.h b/include/cl_object.h new file mode 100644 index 0000000..328c36c --- /dev/null +++ b/include/cl_object.h @@ -0,0 +1,562 @@ +// General object definitions: pointers, reference counting, garbage collection. + +#ifndef _CL_OBJECT_H +#define _CL_OBJECT_H + +#include "cl_types.h" +#include "cl_modules.h" +#include + +// We don't have to deal with circular structures, so normal reference counting +// is sufficient. Is also has the advantage of being mostly non-interrupting. + + +// An object is either a pointer to heap allocated data +// or immediate data. + +// It is possible to distinguish these because pointers are aligned. +// cl_uint_alignment is the guaranteed alignment of a `void*' or `long' +// in memory. Must be > 1. +#if defined(__m68k__) + #define cl_word_alignment 2 +#endif +#if defined(__i386__) || defined(__mips__) || defined(__sparc__) || defined(__hppa__) || defined(__arm__) || defined(__rs6000__) || defined(__m88k__) || defined(__convex__) + #define cl_word_alignment 4 +#endif +#if defined(__alpha__) || defined(__mips64__) || defined(__sparc64__) + #define cl_word_alignment 8 +#endif +#if !defined(cl_word_alignment) + #error "Define cl_word_alignment for your CPU!" +#endif + + +// Four basic classes are introduced: +// +// gcobject rcobject +// +// gcpointer rcpointer +// +// `gcobject' = garbage collectible object (pointer or immediate), +// `gcpointer' = garbage collectible pointer, +// `rcobject' = reference counted object (pointer or immediate), +// `rcpointer' = reference counted pointer. +// +// "garbage collectible" means that a reference count is maintained, and +// when the reference count drops to 0, the object is freed. This is useful +// for all kind of short- or long-lived objects. +// "reference counted" means that a reference count is maintained, which +// cannot drop to 0. This is useful for objects which are registered in a +// global cache table, in order to know which objects can be thrown away +// when the cache is cleaned. (If the cache were never cleaned, its objects +// would never be freed, and we could get away with normal C pointers.) +// +// It is permissible to treat a `rcobject' as a `gcobject', and a `rcpointer' +// as a `gcpointer', but this just increases the destructor and copy-constructor +// overhead. +// It is also permissible to treat a `gcpointer' as a `gcobject', and a +// `rcpointer' as a `rcobject', but this just increases the destructor and +// copy-constructor overhead. + + +// Immediate data is a word, as wide as a pointer. +typedef sintP cl_sint; +typedef uintP cl_uint; // This ought to be called `cl_word'. +#define cl_word_size intPsize +// NB: (cl_word_size==64) implies defined(HAVE_FAST_LONGLONG) +#if (cl_word_size==64) + #define CL_WIDE_POINTERS +#endif + +// Distinguish immediate data from pointers. +inline cl_boolean cl_pointer_p (cl_uint word) +{ + return (cl_boolean)((word & (cl_word_alignment-1)) == 0); +} +inline cl_boolean cl_immediate_p (cl_uint word) +{ + return (cl_boolean)((word & (cl_word_alignment-1)) != 0); +} + +// Immediate data: Fixnum, Short Float, maybe Single Float. +// They have type tags. +// |...............................|......| +// cl_value cl_tag + +// Number of bits reserved for tagging information: +#if (cl_word_alignment <= 4) + #define cl_tag_len 2 +#else + #define cl_tag_len 3 +#endif +#define cl_tag_shift 0 +#if (cl_word_size == 64) + #define cl_value_shift 32 +#else + #define cl_value_shift (cl_tag_len+cl_tag_shift) +#endif +#define cl_value_len (cl_word_size - cl_value_shift) +#define cl_tag_mask (((1UL << cl_tag_len) - 1) << cl_tag_shift) +#define cl_value_mask (((1UL << cl_value_len) - 1) << cl_value_shift) + +// Return the tag of a word. +inline cl_uint cl_tag (cl_uint word) +{ + return (word & cl_tag_mask) >> cl_tag_shift; +} + +// Return the value (unsigned) of a word. +inline cl_uint cl_value (cl_uint word) +{ + // This assumes cl_value_shift + cl_value_len == cl_word_size. + return word >> cl_value_shift; +} + +// Return a word, combining a value and a tag. +inline cl_uint cl_combine (cl_uint tag, cl_uint value) +{ + return (value << cl_value_shift) + (tag << cl_tag_shift); +} +inline cl_uint cl_combine (cl_uint tag, cl_sint value) +{ + // This assumes cl_value_shift + cl_value_len == cl_word_size. + return (value << cl_value_shift) + (tag << cl_tag_shift); +} +// Keep the compiler happy. +inline cl_uint cl_combine (cl_uint tag, unsigned int value) +{ return cl_combine(tag,(cl_uint)value); } +inline cl_uint cl_combine (cl_uint tag, int value) +{ return cl_combine(tag,(cl_sint)value); } + +// Definition of the tags. +#if !defined(CL_WIDE_POINTERS) + #if (cl_word_alignment == 2) + #define cl_FN_tag 1 + #define cl_SF_tag 3 // must satisfy the cl_immediate_p predicate! + #endif + #if (cl_word_alignment == 4) + #define cl_FN_tag 1 + #define cl_SF_tag 2 + #endif +#else // CL_WIDE_POINTERS + // Single Floats are immediate as well. + #define cl_FN_tag 1 + #define cl_SF_tag 2 + #define cl_FF_tag 3 +#endif + +// Corresponding classes. +extern const struct cl_class * cl_immediate_classes [1<refcount++; +} + +// Decrement the reference count of a garbage collected pointer. +inline void cl_gc_dec_pointer_refcount (cl_heap* pointer) +{ + if (--pointer->refcount == 0) + cl_free_heap_object(pointer); +} +// Decrement the reference count of a reference counted pointer. +inline void cl_rc_dec_pointer_refcount (cl_heap* pointer) +{ + --pointer->refcount; +} + +// Increment the reference count. +// This must be a macro, not an inline function, because pointer_p() and +// inc_pointer_refcount() are non-virtual member functions, so that the +// compiler can optimize it. +#define cl_inc_refcount(x) \ + if ((x).pointer_p()) \ + (x).inc_pointer_refcount(); \ + +// Decrement the reference count. +// This must be a macro, not an inline function, because pointer_p() and +// dec_pointer_refcount() are non-virtual member functions, so that the +// compiler can optimize it. +#define cl_dec_refcount(x) \ + if ((x).pointer_p()) \ + (x).dec_pointer_refcount(); \ + +// The declaration of a copy constructor. +// Restriction: The base class's default constructor must do nothing or +// initialize `pointer' to a constant expression. +#define CL_DEFINE_COPY_CONSTRUCTOR1(_class_) \ + _CL_DEFINE_COPY_CONSTRUCTOR1(_class_,_class_) +#define _CL_DEFINE_COPY_CONSTRUCTOR1(_class_,_classname_) \ +inline _class_::_classname_ (const _class_& x) \ +{ \ + cl_uint x_word = x.word; \ + cl_inc_refcount(x); \ + word = x_word; \ +} + +// The declaration of a copy constructor. +// Restriction: The base class must have the usual `cl_private_thing' +// constructor. Drawback: The base class must be known here. +#define CL_DEFINE_COPY_CONSTRUCTOR2(_class_,_baseclass_) \ + _CL_DEFINE_COPY_CONSTRUCTOR2(_class_,_class_,_baseclass_) +#define _CL_DEFINE_COPY_CONSTRUCTOR2(_class_,_classname_,_baseclass_) \ +inline _class_::_classname_ (const _class_& x) \ + : _baseclass_ (as_cl_private_thing(x)) {} + +// The declaration of an assignment operator. +#define CL_DEFINE_ASSIGNMENT_OPERATOR(dest_class,src_class) \ +inline dest_class& dest_class::operator= (const src_class& x) \ +{ \ + /* Be careful, we might be assigning x to itself. */ \ + cl_uint x_word = x.word; \ + cl_inc_refcount(x); \ + cl_dec_refcount(*this); \ + word = x_word; \ + return *this; \ +} + +// We have a small problem with destructors: The specialized destructor +// of a leaf class such as `cl_SF' should be more efficient than the +// general destructor for `cl_N'. Since (by C++ specs) destructing a cl_SF +// would run the destructors for cl_SF, cl_F, cl_R, cl_N (in that order), +// and in the last step the compiler does not know any more that the object +// actually is a cl_SF, there is no way to optimize the destructor! +// ("progn-reversed" method combination is evil.) +// And if we define "mirror"/"shadow" classes with no destructors (such +// that `cl_F' inherits from `cl_F_no_destructor' buts adds a destructor) +// then we need to add explicit conversion operators cl_SF -> cl_F -> cl_R ..., +// with the effect that calling an overloaded function like `as_cl_F' +// (which has two signatures `as_cl_F(cl_number)' and `as_cl_F(cl_F)') +// with a cl_SF argument gives an "call of overloaded function is ambiguous" +// error. +// There is no help: If we want overloaded functions to be callable in a way +// that makes sense, `cl_SF' has to be a subclass of `cl_F', and then the +// destructor of `cl_SF' will do at least as much computation as the `cl_F' +// destructor. Praise C++ ! :-(( +// (Even making `pointer_p()' a virtual function would not help.) + + +// This is obnoxious. +template struct cl_htentry1; + +// The four concrete classes of all objects. + +class cl_gcobject { +public: /* ugh */ + union { + void* pointer; + cl_heap* heappointer; + cl_uint word; + }; +public: +// Default constructor. (Used for objects with no initializer.) + cl_gcobject (); +// Destructor. (Used when a variable goes out of scope.) + ~cl_gcobject (); +// Copy constructor. + cl_gcobject (const cl_gcobject&); +// Assignment operator. + cl_gcobject& operator= (const cl_gcobject&); +// Distinguish immediate data from pointer. + cl_boolean pointer_p() const + { return cl_pointer_p(word); } +// Reference counting. + void inc_pointer_refcount () const + { cl_inc_pointer_refcount(heappointer); } + void dec_pointer_refcount () const + { cl_gc_dec_pointer_refcount(heappointer); } +// Return the type tag of an immediate number. + cl_uint nonpointer_tag () const + { return cl_tag(word); } +// Return the type tag of a heap-allocated number. + const cl_class * pointer_type () const + { return heappointer->type; } +// Private pointer manipulations. + cl_private_thing _as_cl_private_thing () const; +// Private constructor. + cl_gcobject (cl_private_thing p) + #if !(defined(__alpha__) && !defined(__GNUC__)) + : pointer (p) {} + #else + { pointer = p; } + #endif +// Debugging output. + void debug_print () const; +// Ability to place an object at a given address. + void* operator new (size_t size, cl_gcobject* ptr) { (void)size; return ptr; } + void* operator new (size_t size) { return ::operator new (size); } +}; +inline cl_gcobject::cl_gcobject () {} +inline cl_gcobject::~cl_gcobject () { cl_dec_refcount(*this); } +CL_DEFINE_COPY_CONSTRUCTOR1(cl_gcobject) +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_gcobject,cl_gcobject) + +class cl_gcpointer { +public: /* ugh */ + union { + void* pointer; + cl_heap* heappointer; + cl_uint word; + }; +public: +// Default constructor. (Used for objects with no initializer.) + cl_gcpointer (); +// Destructor. (Used when a variable goes out of scope.) + ~cl_gcpointer (); +// Copy constructor. + cl_gcpointer (const cl_gcpointer&); +// Assignment operator. + cl_gcpointer& operator= (const cl_gcpointer&); +// Distinguish immediate data from pointer. + cl_boolean pointer_p() const + { return cl_true; } +// Reference counting. + void inc_pointer_refcount () const + { cl_inc_pointer_refcount(heappointer); } + void dec_pointer_refcount () const + { cl_gc_dec_pointer_refcount(heappointer); } +// Return the type tag of an immediate number. + cl_uint nonpointer_tag () const + { return cl_tag(word); } +// Return the type tag of a heap-allocated number. + const cl_class * pointer_type () const + { return heappointer->type; } +// Private pointer manipulations. + cl_private_thing _as_cl_private_thing () const; +// Private constructor. + cl_gcpointer (cl_private_thing p) + #if !(defined(__alpha__) && !defined(__GNUC__)) + : pointer (p) {} + #else + { pointer = p; } + #endif +// Debugging output. + void debug_print () const; +// Ability to place an object at a given address. + void* operator new (size_t size, cl_gcpointer* ptr) { (void)size; return ptr; } + void* operator new (size_t size) { return ::operator new (size); } +}; +inline cl_gcpointer::cl_gcpointer () {} +inline cl_gcpointer::~cl_gcpointer () { cl_dec_refcount(*this); } +CL_DEFINE_COPY_CONSTRUCTOR1(cl_gcpointer) +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_gcpointer,cl_gcpointer) + +class cl_rcobject { +public: /* ugh */ + union { + void* pointer; + cl_heap* heappointer; + cl_uint word; + }; +public: +// Default constructor. (Used for objects with no initializer.) + cl_rcobject (); +// Destructor. (Used when a variable goes out of scope.) + ~cl_rcobject (); +// Copy constructor. + cl_rcobject (const cl_rcobject&); +// Assignment operator. + cl_rcobject& operator= (const cl_rcobject&); +// Distinguish immediate data from pointer. + cl_boolean pointer_p() const + { return cl_pointer_p(word); } +// Reference counting. + void inc_pointer_refcount () const + { cl_inc_pointer_refcount(heappointer); } + void dec_pointer_refcount () const + { cl_rc_dec_pointer_refcount(heappointer); } +// Return the type tag of an immediate number. + cl_uint nonpointer_tag () const + { return cl_tag(word); } +// Return the type tag of a heap-allocated number. + const cl_class * pointer_type () const + { return heappointer->type; } +// Private pointer manipulations. + cl_private_thing _as_cl_private_thing () const; +// Private constructor. + cl_rcobject (cl_private_thing p) + #if !(defined(__alpha__) && !defined(__GNUC__)) + : pointer (p) {} + #else + { pointer = p; } + #endif +// Debugging output. + void debug_print () const; +// Ability to place an object at a given address. + void* operator new (size_t size, cl_rcobject* ptr) { (void)size; return ptr; } + void* operator new (size_t size) { return ::operator new (size); } +}; +inline cl_rcobject::cl_rcobject () {} +inline cl_rcobject::~cl_rcobject () { cl_dec_refcount(*this); } +CL_DEFINE_COPY_CONSTRUCTOR1(cl_rcobject) +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_rcobject,cl_rcobject) + +class cl_rcpointer { +public: /* ugh */ + union { + void* pointer; + cl_heap* heappointer; + cl_uint word; + }; +public: +// Default constructor. (Used for objects with no initializer.) + cl_rcpointer (); +// Destructor. (Used when a variable goes out of scope.) + ~cl_rcpointer (); +// Copy constructor. + cl_rcpointer (const cl_rcpointer&); +// Assignment operator. + cl_rcpointer& operator= (const cl_rcpointer&); +// Distinguish immediate data from pointer. + cl_boolean pointer_p() const + { return cl_true; } +// Reference counting. + void inc_pointer_refcount () const + { cl_inc_pointer_refcount(heappointer); } + void dec_pointer_refcount () const + { cl_rc_dec_pointer_refcount(heappointer); } +// Return the type tag of an immediate number. + cl_uint nonpointer_tag () const + { return cl_tag(word); } +// Return the type tag of a heap-allocated number. + const cl_class * pointer_type () const + { return heappointer->type; } +// Private pointer manipulations. + cl_private_thing _as_cl_private_thing () const; +// Private constructor. + cl_rcpointer (cl_private_thing p) + #if !(defined(__alpha__) && !defined(__GNUC__)) + : pointer (p) {} + #else + { pointer = p; } + #endif +// Debugging output. + void debug_print () const; +// Ability to place an object at a given address. + void* operator new (size_t size, cl_rcpointer* ptr) { (void)size; return ptr; } + void* operator new (size_t size) { return ::operator new (size); } +}; +inline cl_rcpointer::cl_rcpointer () {} +inline cl_rcpointer::~cl_rcpointer () { cl_dec_refcount(*this); } +CL_DEFINE_COPY_CONSTRUCTOR1(cl_rcpointer) +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_rcpointer,cl_rcpointer) + +// Private pointer manipulations. + +inline cl_private_thing cl_gcobject::_as_cl_private_thing () const +{ + cl_private_thing p = (cl_private_thing) pointer; + cl_inc_refcount(*this); + return p; +} +inline cl_private_thing as_cl_private_thing (const cl_gcobject& x) +{ + return x._as_cl_private_thing(); +} + +inline cl_private_thing cl_gcpointer::_as_cl_private_thing () const +{ + cl_private_thing p = (cl_private_thing) pointer; + cl_inc_refcount(*this); + return p; +} +inline cl_private_thing as_cl_private_thing (const cl_gcpointer& x) +{ + return x._as_cl_private_thing(); +} + +inline cl_private_thing cl_rcobject::_as_cl_private_thing () const +{ + cl_private_thing p = (cl_private_thing) pointer; + cl_inc_refcount(*this); + return p; +} +inline cl_private_thing as_cl_private_thing (const cl_rcobject& x) +{ + return x._as_cl_private_thing(); +} + +inline cl_private_thing cl_rcpointer::_as_cl_private_thing () const +{ + cl_private_thing p = (cl_private_thing) pointer; + cl_inc_refcount(*this); + return p; +} +inline cl_private_thing as_cl_private_thing (const cl_rcpointer& x) +{ + return x._as_cl_private_thing(); +} + +// Note: When we define a function that returns a class object by value, +// we normally return it as const value. The declarations +// T func (...); (A) +// and +// const T func (...); (B) +// behave identically and generate identical code, except that the code +// func(...) = foo; +// compiles fine with (A) but is an error (and yields a warning) with (B). +// We want this warning. + +// Define a conversion operator from one object to another object of the +// same size. +#if (defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ <= 7)) // workaround g++ bug + #define CL_DEFINE_CONVERTER(target_class) \ + operator target_class () const \ + { \ + if (sizeof(*this) != sizeof(target_class)) cl_abort(); \ + return * (const target_class *) (void*) this; \ + } +#else + #define CL_DEFINE_CONVERTER(target_class) \ + operator const target_class & () const \ + { \ + if (sizeof(*this) != sizeof(target_class)) cl_abort(); \ + return * (const target_class *) (void*) this; \ + } +#endif + +#endif /* _CL_OBJECT_H */ diff --git a/include/cl_output.h b/include/cl_output.h new file mode 100644 index 0000000..3ad224b --- /dev/null +++ b/include/cl_output.h @@ -0,0 +1,70 @@ +// Output functions. + +#ifndef _CL_OUTPUT_H +#define _CL_OUTPUT_H + +#include "cl_types.h" +#include "cl_floatformat.h" +#include "cl_io.h" +#include "cl_string.h" + +struct cl_print_rational_flags { + // Base in which rational numbers are to be printed. + unsigned int rational_base; + // Flag whether to print radix specifiers in Common Lisp syntax for + // rational numbers (#nR or #b or #o or #x prefixes, trailing dot). + cl_boolean rational_readably; +// Constructor. + cl_print_rational_flags () : + rational_base (10), + rational_readably (cl_false) {} +}; + +struct cl_print_float_flags { + // Flag whether to prefer type specific exponent markers over 'E'. + cl_boolean float_readably; + // If !float_readably, the format which earns the 'E' exponent marker. + cl_float_format_t default_float_format; +// Constructor. + cl_print_float_flags () : + float_readably (cl_false), + default_float_format (cl_float_format_ffloat) {} +}; + +struct cl_print_real_flags : cl_print_rational_flags, cl_print_float_flags {}; + +struct cl_print_complex_flags { + // Flag whether to use the Common Lisp #C(realpart imagpart) syntax, + cl_boolean complex_readably; +// Constructor. + cl_print_complex_flags () : + complex_readably (cl_false) {} +}; + +struct cl_print_number_flags : cl_print_real_flags, cl_print_complex_flags {}; + +enum cl_print_vector_syntax_t { + vsyntax_algebraic, // [a, b, c] + vsyntax_pretty, // [a b c] + vsyntax_commonlisp // #(a b c) +}; + +struct cl_print_vector_flags { + cl_print_vector_syntax_t vector_syntax; +// Constructor. + cl_print_vector_flags () : + vector_syntax (vsyntax_pretty) {} +}; + +struct cl_print_univpoly_flags { + cl_string univpoly_varname; +// Constructor. + cl_print_univpoly_flags () : + univpoly_varname ("x") {} +}; + +struct cl_print_flags : cl_print_number_flags, cl_print_vector_flags, cl_print_univpoly_flags {}; + +extern cl_print_flags cl_default_print_flags; + +#endif /* _CL_OUTPUT_H */ diff --git a/include/cl_proplist.h b/include/cl_proplist.h new file mode 100644 index 0000000..15f3dde --- /dev/null +++ b/include/cl_proplist.h @@ -0,0 +1,51 @@ +// Property lists. + +#ifndef _CL_PROPLIST_H +#define _CL_PROPLIST_H + +#include "cl_symbol.h" +#include "cl_malloc.h" + +// The only extensible way to extend objects at runtime in an extensible +// and decentralized way (without having to modify the object's class) +// is to add a property table to every object. +// For the moment, only very few properties are planned, so lists should be +// enough. Since properties represent additional information about the object, +// there is no need for removing properties, so singly linked lists will be +// enough. + +// This is the base class for all properties. +struct cl_property { +private: + cl_property* next; +public: + cl_symbol key; + // Constructor. + cl_property (const cl_symbol& k) : next (NULL), key (k) {} + // Destructor. + virtual ~cl_property () {} + // Allocation and deallocation. + void* operator new (size_t size) { return cl_malloc_hook(size); } + void operator delete (void* ptr) { cl_free_hook(ptr); } +private: + virtual void dummy (); +// Friend declarations. They are for the compiler. Just ignore them. + friend class cl_property_list; +}; +#define SUBCLASS_cl_property() \ + void* operator new (size_t size) { return cl_malloc_hook(size); } \ + void operator delete (void* ptr) { cl_free_hook(ptr); } + +struct cl_property_list { +private: + cl_property* list; +public: + cl_property* get_property (const cl_symbol& key); + void add_property (cl_property* new_property); + // Constructor. + cl_property_list () : list (NULL) {} + // Destructor. + ~cl_property_list (); +}; + +#endif /* _CL_PROPLIST_H */ diff --git a/include/cl_random.h b/include/cl_random.h new file mode 100644 index 0000000..6ea7812 --- /dev/null +++ b/include/cl_random.h @@ -0,0 +1,43 @@ +// Public random number operations. + +#ifndef _CL_RANDOM_H +#define _CL_RANDOM_H + +#include "cl_types.h" +#include "cl_modules.h" + +class cl_random_state { +public: + struct { uint32 hi; uint32 lo; } seed; +// Constructor: + cl_random_state (); +}; + +// random32(randomstate) liefert eine neue Zufallszahl. +// > randomstate: ein Random-State, wird verändert +// < ergebnis: eine 32-Bit-Zufallszahl +extern uint32 random32 (cl_random_state& randomstate); + +#if defined(HAVE_FAST_LONGLONG) +// random64(randomstate) liefert eine neue Zufallszahl. +// > randomstate: ein Random-State, wird verändert +// < ergebnis: eine 64-Bit-Zufallszahl +inline uint64 random64 (cl_random_state& randomstate) +{ + return ((uint64)random32(randomstate) << 32) + | (uint64)random32(randomstate); +} +#endif + +// Ein globaler Zufallszahlengenerator. +extern cl_random_state cl_default_random_state; +CL_REQUIRE(cl_random_def) +// Das ist der Default-Generator. +inline uint32 random32 (void) + { return random32(cl_default_random_state); } +#if defined(HAVE_FAST_LONGLONG) +inline uint64 random64 (void) + { return random64(cl_default_random_state); } +#endif + +#endif /* _CL_RANDOM_H */ diff --git a/include/cl_rational.h b/include/cl_rational.h new file mode 100644 index 0000000..523a8b6 --- /dev/null +++ b/include/cl_rational.h @@ -0,0 +1,302 @@ +// Public rational number operations. + +#ifndef _CL_RATIONAL_H +#define _CL_RATIONAL_H + +#include "cl_number.h" +#include "cl_rational_class.h" +#include "cl_integer_class.h" + + +CL_DEFINE_AS_CONVERSION(cl_RA) + + +// numerator(r) liefert den Zähler der rationalen Zahl r. +extern const cl_I numerator (const cl_RA& r); + +// denominator(r) liefert den Nenner (> 0) der rationalen Zahl r. +extern const cl_I denominator (const cl_RA& r); + + +// Liefert (- r), wo r eine rationale Zahl ist. +extern const cl_RA operator- (const cl_RA& r); + +// (+ r s), wo r und s rationale Zahlen sind. +extern const cl_RA operator+ (const cl_RA& r, const cl_RA& s); +// Dem C++-Compiler muß man auch das Folgende sagen: +inline const cl_RA operator+ (const int x, const cl_RA& y) + { return cl_I(x) + y; } +inline const cl_RA operator+ (const unsigned int x, const cl_RA& y) + { return cl_I(x) + y; } +inline const cl_RA operator+ (const long x, const cl_RA& y) + { return cl_I(x) + y; } +inline const cl_RA operator+ (const unsigned long x, const cl_RA& y) + { return cl_I(x) + y; } +inline const cl_RA operator+ (const cl_RA& x, const int y) + { return x + cl_I(y); } +inline const cl_RA operator+ (const cl_RA& x, const unsigned int y) + { return x + cl_I(y); } +inline const cl_RA operator+ (const cl_RA& x, const long y) + { return x + cl_I(y); } +inline const cl_RA operator+ (const cl_RA& x, const unsigned long y) + { return x + cl_I(y); } + +// (- r s), wo r und s rationale Zahlen sind. +extern const cl_RA operator- (const cl_RA& r, const cl_RA& s); +// Dem C++-Compiler muß man auch das Folgende sagen: +inline const cl_RA operator- (const int x, const cl_RA& y) + { return cl_I(x) - y; } +inline const cl_RA operator- (const unsigned int x, const cl_RA& y) + { return cl_I(x) - y; } +inline const cl_RA operator- (const long x, const cl_RA& y) + { return cl_I(x) - y; } +inline const cl_RA operator- (const unsigned long x, const cl_RA& y) + { return cl_I(x) - y; } +inline const cl_RA operator- (const cl_RA& x, const int y) + { return x - cl_I(y); } +inline const cl_RA operator- (const cl_RA& x, const unsigned int y) + { return x - cl_I(y); } +inline const cl_RA operator- (const cl_RA& x, const long y) + { return x - cl_I(y); } +inline const cl_RA operator- (const cl_RA& x, const unsigned long y) + { return x - cl_I(y); } + +// (1+ r), wo r eine rationale Zahl ist. +extern const cl_RA plus1 (const cl_RA& r); + +// (1- r), wo r eine rationale Zahl ist. +extern const cl_RA minus1 (const cl_RA& r); + +// (abs r), wo r eine rationale Zahl ist. +extern const cl_RA abs (const cl_RA& r); + +// cl_equal(r,s) vergleicht zwei rationale Zahlen r und s auf Gleichheit. +extern cl_boolean cl_equal (const cl_RA& r, const cl_RA& s); +// cl_equal_hashcode(r) liefert einen cl_equal-invarianten Hashcode für r. +extern uint32 cl_equal_hashcode (const cl_RA& r); + +// cl_compare(r,s) vergleicht zwei rationale Zahlen r und s. +// Ergebnis: 0 falls r=s, +1 falls r>s, -1 falls r= (const cl_RA& x, const cl_RA& y) + { return cl_compare(x,y)>=0; } +inline bool operator> (const cl_RA& x, const cl_RA& y) + { return cl_compare(x,y)>0; } + +// minusp(x) == (< x 0) +extern cl_boolean minusp (const cl_RA& x); + +// zerop(x) stellt fest, ob eine rationale Zahl = 0 ist. +extern cl_boolean zerop (const cl_RA& x); + +// plusp(x) == (> x 0) +extern cl_boolean plusp (const cl_RA& x); + +// Kehrwert (/ r), wo r eine rationale Zahl ist. +extern const cl_RA recip (const cl_RA& r); + +// Liefert (* r s), wo r und s rationale Zahlen sind. +extern const cl_RA operator* (const cl_RA& r, const cl_RA& s); +// Dem C++-Compiler muß man auch das Folgende sagen: +inline const cl_RA operator* (const int x, const cl_RA& y) + { return cl_I(x) * y; } +inline const cl_RA operator* (const unsigned int x, const cl_RA& y) + { return cl_I(x) * y; } +inline const cl_RA operator* (const long x, const cl_RA& y) + { return cl_I(x) * y; } +inline const cl_RA operator* (const unsigned long x, const cl_RA& y) + { return cl_I(x) * y; } +inline const cl_RA operator* (const cl_RA& x, const int y) + { return x * cl_I(y); } +inline const cl_RA operator* (const cl_RA& x, const unsigned int y) + { return x * cl_I(y); } +inline const cl_RA operator* (const cl_RA& x, const long y) + { return x * cl_I(y); } +inline const cl_RA operator* (const cl_RA& x, const unsigned long y) + { return x * cl_I(y); } + +// Quadrat (* r r), wo r eine rationale Zahl ist. +extern const cl_RA square (const cl_RA& r); + +// Liefert (/ r s), wo r und s rationale Zahlen sind. +extern const cl_RA operator/ (const cl_RA& r, const cl_RA& s); +// Dem C++-Compiler muß man auch das Folgende sagen: +inline const cl_RA operator/ (const int x, const cl_RA& y) + { return cl_I(x) / y; } +inline const cl_RA operator/ (const unsigned int x, const cl_RA& y) + { return cl_I(x) / y; } +inline const cl_RA operator/ (const long x, const cl_RA& y) + { return cl_I(x) / y; } +inline const cl_RA operator/ (const unsigned long x, const cl_RA& y) + { return cl_I(x) / y; } +inline const cl_RA operator/ (const cl_RA& x, const int y) + { return x / cl_I(y); } +inline const cl_RA operator/ (const cl_RA& x, const unsigned int y) + { return x / cl_I(y); } +inline const cl_RA operator/ (const cl_RA& x, const long y) + { return x / cl_I(y); } +inline const cl_RA operator/ (const cl_RA& x, const unsigned long y) + { return x / cl_I(y); } + +// Return type for rounding operators. +// x / y --> (q,r) with x = y*q+r. +struct cl_RA_div_t { + cl_I quotient; + cl_RA remainder; +// Constructor. + cl_RA_div_t () {} + cl_RA_div_t (const cl_I& q, const cl_RA& r) : quotient(q), remainder(r) {} +}; + +// Liefert ganzzahligen und gebrochenen Anteil einer rationalen Zahl. +// (q,r) := (floor x) +// floor2(x) +// > x: rationale Zahl +// < q,r: Quotient q, ein Integer, Rest r, eine rationale Zahl + extern const cl_RA_div_t floor2 (const cl_RA& x); + extern const cl_I floor1 (const cl_RA& x); + +// Liefert ganzzahligen und gebrochenen Anteil einer rationalen Zahl. +// (q,r) := (ceiling x) +// ceiling2(x) +// > x: rationale Zahl +// < q,r: Quotient q, ein Integer, Rest r, eine rationale Zahl + extern const cl_RA_div_t ceiling2 (const cl_RA& x); + extern const cl_I ceiling1 (const cl_RA& x); + +// Liefert ganzzahligen und gebrochenen Anteil einer rationalen Zahl. +// (q,r) := (truncate x) +// truncate2(x) +// > x: rationale Zahl +// < q,r: Quotient q, ein Integer, Rest r, eine rationale Zahl + extern const cl_RA_div_t truncate2 (const cl_RA& x); + extern const cl_I truncate1 (const cl_RA& x); + +// Liefert ganzzahligen und gebrochenen Anteil einer rationalen Zahl. +// (q,r) := (round x) +// round2(x) +// > x: rationale Zahl +// < q,r: Quotient q, ein Integer, Rest r, eine rationale Zahl + extern const cl_RA_div_t round2 (const cl_RA& x); + extern const cl_I round1 (const cl_RA& x); + +// floor2(x,y) liefert (floor x y). +extern const cl_RA_div_t floor2 (const cl_RA& x, const cl_RA& y); +extern const cl_I floor1 (const cl_RA& x, const cl_RA& y); + +// ceiling2(x,y) liefert (ceiling x y). +extern const cl_RA_div_t ceiling2 (const cl_RA& x, const cl_RA& y); +extern const cl_I ceiling1 (const cl_RA& x, const cl_RA& y); + +// truncate2(x,y) liefert (truncate x y). +extern const cl_RA_div_t truncate2 (const cl_RA& x, const cl_RA& y); +extern const cl_I truncate1 (const cl_RA& x, const cl_RA& y); + +// round2(x,y) liefert (round x y). +extern const cl_RA_div_t round2 (const cl_RA& x, const cl_RA& y); +extern const cl_I round1 (const cl_RA& x, const cl_RA& y); + +// max(x,y) liefert (max x y), wo x und y rationale Zahlen sind. +extern const cl_RA max (const cl_RA& x, const cl_RA& y); + +// min(x,y) liefert (min x y), wo x und y rationale Zahlen sind. +extern const cl_RA min (const cl_RA& x, const cl_RA& y); + +// signum(x) liefert (signum x), wo x eine rationale Zahl ist. +extern const cl_RA signum (const cl_RA& x); + +// (expt x y), wo x eine rationale Zahl und y ein Integer >0 ist. +extern const cl_RA expt_pos (const cl_RA& x, uintL y); +extern const cl_RA expt_pos (const cl_RA& x, const cl_I& y); + +// (expt x y), wo x eine rationale Zahl und y ein Integer ist. +extern const cl_RA expt (const cl_RA& x, sintL y); +extern const cl_RA expt (const cl_RA& x, const cl_I& y); + +// Stellt fest, ob eine rationale Zahl >=0 das Quadrat einer rationalen Zahl +// ist. +// sqrtp(x,&w) +// > x: eine rationale Zahl >=0 +// < w: rationale Zahl (sqrt x) falls x Quadratzahl +// < ergebnis: cl_true ..................., cl_false sonst + extern cl_boolean sqrtp (const cl_RA& x, cl_RA* w); + +// Stellt fest, ob eine rationale Zahl >=0 die n-te Potenz einer rationalen Zahl +// ist. +// rootp(x,n,&w) +// > x: eine rationale Zahl >=0 +// > n: ein Integer >0 +// < w: exakte n-te Wurzel (expt x (/ n)) falls x eine n-te Potenz +// < ergebnis: cl_true ........................, cl_false sonst + extern cl_boolean rootp (const cl_RA& x, uintL n, cl_RA* w); + extern cl_boolean rootp (const cl_RA& x, const cl_I& n, cl_RA* w); + +// Liefert zu Integers a>0, b>1 den Logarithmus log(a,b), +// falls er eine rationale Zahl ist. +// logp(a,b,&l) +// > a: ein Integer >0 +// > b: ein Integer >1 +// < l: log(a,b) falls er eine exakte rationale Zahl ist +// < ergebnis: cl_true ......................................., cl_false sonst + extern cl_boolean logp (const cl_I& a, const cl_I& b, cl_RA* l); + +// Liefert zu rationalen Zahlen a>0, b>0 den Logarithmus log(a,b), +// falls er eine rationale Zahl ist. +// logp(a,b,&l) +// > a: eine rationale Zahl >0 +// > b: eine rationale Zahl >0, /=1 +// < l: log(a,b) falls er eine exakte rationale Zahl ist +// < ergebnis: cl_true ......................................., cl_false sonst + extern cl_boolean logp (const cl_RA& a, const cl_RA& b, cl_RA* l); + +// Konversion zu einem C "float". +extern float cl_float_approx (const cl_RA& x); + +// Konversion zu einem C "double". +extern double cl_double_approx (const cl_RA& x); + + +#ifdef WANT_OBFUSCATING_OPERATORS +// This could be optimized to use in-place operations. +inline cl_RA& operator+= (cl_RA& x, const cl_RA& y) { return x = x + y; } +inline cl_RA& operator+= (cl_RA& x, const int y) { return x = x + y; } +inline cl_RA& operator+= (cl_RA& x, const unsigned int y) { return x = x + y; } +inline cl_RA& operator+= (cl_RA& x, const long y) { return x = x + y; } +inline cl_RA& operator+= (cl_RA& x, const unsigned long y) { return x = x + y; } +inline cl_RA& operator++ /* prefix */ (cl_RA& x) { return x = plus1(x); } +inline void operator++ /* postfix */ (cl_RA& x, int dummy) { (void)dummy; x = plus1(x); } +inline cl_RA& operator-= (cl_RA& x, const cl_RA& y) { return x = x - y; } +inline cl_RA& operator-= (cl_RA& x, const int y) { return x = x - y; } +inline cl_RA& operator-= (cl_RA& x, const unsigned int y) { return x = x - y; } +inline cl_RA& operator-= (cl_RA& x, const long y) { return x = x - y; } +inline cl_RA& operator-= (cl_RA& x, const unsigned long y) { return x = x - y; } +inline cl_RA& operator-- /* prefix */ (cl_RA& x) { return x = minus1(x); } +inline void operator-- /* postfix */ (cl_RA& x, int dummy) { (void)dummy; x = minus1(x); } +inline cl_RA& operator*= (cl_RA& x, const cl_RA& y) { return x = x * y; } +inline cl_RA& operator/= (cl_RA& x, const cl_RA& y) { return x = x / y; } +#endif + + +// Runtime typing support. +extern cl_class cl_class_ratio; + + +// Debugging support. +#ifdef CL_DEBUG +extern int cl_RA_debug_module; +static void* const cl_RA_debug_dummy[] = { &cl_RA_debug_dummy, + &cl_RA_debug_module +}; +#endif + + +#endif /* _CL_RATIONAL_H */ diff --git a/include/cl_rational_class.h b/include/cl_rational_class.h new file mode 100644 index 0000000..13c0dc0 --- /dev/null +++ b/include/cl_rational_class.h @@ -0,0 +1,57 @@ +// Abstract class of rational numbers. + +#ifndef _CL_RATIONAL_CLASS_H +#define _CL_RATIONAL_CLASS_H + +#include "cl_number.h" +#include "cl_real_class.h" + + +class cl_RA : public cl_R { +public: +// Default constructor. + cl_RA (); +// Copy constructor. + cl_RA (const cl_RA&); +// Converters. +// Assignment operators. + cl_RA& operator= (const cl_RA&); +// Constructors and assignment operators from C numeric types. + cl_RA (const int); // |argument| must be < 2^29 + cl_RA (const unsigned int); // argument must be < 2^29 + cl_RA (const long); + cl_RA (const unsigned long); + cl_RA& operator= (const int); // |argument| must be < 2^29 + cl_RA& operator= (const unsigned int); // argument must be < 2^29 + cl_RA& operator= (const long); + cl_RA& operator= (const unsigned long); +// Other constructors. + cl_RA (const char *); +// Private constructor. + cl_RA (cl_private_thing); + cl_RA (struct cl_heap_ratio *); +public: // Ability to place an object at a given address. + void* operator new (size_t size) { return cl_malloc_hook(size); } + void* operator new (size_t size, cl_RA* ptr) { (void)size; return ptr; } + void operator delete (void* ptr) { cl_free_hook(ptr); } +private: +// Friend declarations. They are for the compiler. Just ignore them. +}; + +// Private constructors. +inline cl_RA::cl_RA (cl_private_thing ptr) : cl_R (ptr) {} +// The assignment operators: +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_RA, cl_RA) +// The default constructors. +inline cl_RA::cl_RA () + : cl_R ((cl_private_thing) cl_combine(cl_FN_tag,0)) {} +// The copy constructors. +CL_DEFINE_COPY_CONSTRUCTOR2(cl_RA,cl_R) +// Constructors and assignment operators from C numeric types. +CL_DEFINE_INT_CONSTRUCTORS(cl_RA) +CL_DEFINE_INT_ASSIGNMENT_OPERATORS(cl_RA) +CL_DEFINE_LONG_CONSTRUCTORS(cl_RA) +CL_DEFINE_LONG_ASSIGNMENT_OPERATORS(cl_RA) + + +#endif /* _CL_RATIONAL_CLASS_H */ diff --git a/include/cl_rational_io.h b/include/cl_rational_io.h new file mode 100644 index 0000000..3ab2721 --- /dev/null +++ b/include/cl_rational_io.h @@ -0,0 +1,76 @@ +// I/O of rational numbers. + +#ifndef _CL_RATIONAL_IO_H +#define _CL_RATIONAL_IO_H + +#include "cl_number_io.h" +#include "cl_rational.h" + + +// Undocumented input functions + +// Wandelt eine Zeichenkette mit Rational-Syntax in eine rationale Zahl um. +// read_rational(base,sign,string,index1,index3,index2) +// > base: Lesebasis (>=2, <=36) +// > sign: Vorzeichen (/=0 falls negativ) +// > string: Simple-String (enthält Ziffern mit Wert index1: Index der ersten Ziffer +// > index3: Index von '/' +// > index2: Index nach der letzten Ziffer +// (also index3-index1 Zähler-Ziffern, index2-index3-1 Nenner-Ziffern) +// < ergebnis: rationale Zahl +extern const cl_RA read_rational (unsigned int base, + cl_signean sign, const char * string, uintL index1, uintL index3, uintL index2); + +// The following does strictly the same as the general read_complex. +// It is here only so that you don't need the complex and float number +// readers in order to read an rational number. ("Treeshaking") +extern const cl_RA read_rational (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse); +extern const cl_RA read_rational (cl_istream stream, const cl_read_flags& flags); + +// Documented input functions + +inline cl_istream operator>> (cl_istream stream, cl_RA& result) +{ + extern cl_read_flags cl_RA_read_flags; + result = read_rational(stream,cl_RA_read_flags); + return stream; +} + + +// Undocumented output functions + +// Gibt eine rationale Zahl aus. +// print_rational(stream,base,z); +// > z: rationale Zahl +// > base: Basis (>=2, <=36) +// > stream: Stream +extern void print_rational (cl_ostream stream, unsigned int base, const cl_RA& z); + + +// Documented output functions + +// Gibt eine Zahl aus. +// print_rational(stream,flags,z); +// > z: Zahl +// > stream: Stream +// > flags: Ausgabe-Parameter +extern void print_rational (cl_ostream stream, const cl_print_flags& flags, const cl_RA& z); +extern void print_rational (cl_ostream stream, const cl_print_number_flags& flags, const cl_RA& z); +extern void print_rational (cl_ostream stream, const cl_print_real_flags& flags, const cl_RA& z); +extern void print_rational (cl_ostream stream, const cl_print_rational_flags& flags, const cl_RA& z); + +// The following does strictly the same as the general `fprint' for numbers. +// It is here only so that you don't need the complex and long-float number +// printers in order to print an integer. ("Treeshaking") + +inline void fprint (cl_ostream stream, const cl_RA& x) +{ + extern cl_print_flags cl_default_print_flags; + print_rational(stream,cl_default_print_flags,x); +} + +CL_DEFINE_PRINT_OPERATOR(cl_RA) + + +#endif /* _CL_RATIONAL_IO_H */ diff --git a/include/cl_rational_ring.h b/include/cl_rational_ring.h new file mode 100644 index 0000000..1f3e4c0 --- /dev/null +++ b/include/cl_rational_ring.h @@ -0,0 +1,14 @@ +// Built-in rational number ring. + +#ifndef _CL_RATIONAL_RING_H +#define _CL_RATIONAL_RING_H + +#include "cl_ring.h" +#include "cl_rational_class.h" + +typedef cl_specialized_number_ring cl_rational_ring; +extern const cl_rational_ring cl_RA_ring; // math. Q +extern cl_class cl_class_rational_ring; +//CL_REQUIRE(cl_RA_ring) + +#endif /* _CL_RATIONAL_RING_H */ diff --git a/include/cl_real.h b/include/cl_real.h new file mode 100644 index 0000000..74dd5f2 --- /dev/null +++ b/include/cl_real.h @@ -0,0 +1,519 @@ +// Public real number operations. + +#ifndef _CL_REAL_H +#define _CL_REAL_H + +#include "cl_number.h" +#include "cl_real_class.h" +#include "cl_rational_class.h" +#include "cl_integer_class.h" +#include "cl_float.h" +#include "cl_floatformat.h" +#include "cl_random.h" + + +CL_DEFINE_AS_CONVERSION(cl_R) + + +// zerop(x) testet, ob (= x 0). +extern cl_boolean zerop (const cl_R& x); + +// minusp(x) testet, ob (< x 0). +extern cl_boolean minusp (const cl_R& x); + +// plusp(x) testet, ob (> x 0). +extern cl_boolean plusp (const cl_R& x); + + +// R_to_SF(x) wandelt eine reelle Zahl x in ein Short-Float um. +// < ergebnis: (coerce x 'short-float) +extern const cl_SF cl_R_to_SF (const cl_R& x); + +// R_to_FF(x) wandelt eine reelle Zahl x in ein Single-Float um. +// < ergebnis: (coerce x 'single-float) +extern const cl_FF cl_R_to_FF (const cl_R& x); + +// R_to_DF(x) wandelt eine reelle Zahl x in ein Double-Float um. +// < ergebnis: (coerce x 'double-float) +extern const cl_DF cl_R_to_DF (const cl_R& x); + +// R_to_LF(x,len) wandelt eine reelle Zahl x in ein Long-Float mit len Digits um. +// > uintC len: gewünschte Anzahl Digits, >=LF_minlen +// < ergebnis: (coerce x `(long-float ,len)) +extern const cl_LF cl_R_to_LF (const cl_R& x, uintC len); + +// cl_float(x,y) wandelt eine reelle Zahl x in das Float-Format des +// Floats y um und rundet dabei nötigenfalls. +// > x: eine reelle Zahl +// > y: ein Float +// < ergebnis: (float x y) +extern const cl_F cl_float (const cl_R& x, const cl_F& y); + +// cl_float(x,f) wandelt eine reelle Zahl x in das Float-Format f um +// und rundet dabei nötigenfalls. +// > x: eine reelle Zahl +// > f: eine Float-Format-Spezifikation +// < ergebnis: (float x f) +extern const cl_F cl_float (const cl_R& x, cl_float_format_t f); + +// cl_float(x) wandelt eine reelle Zahl x in ein Float um +// und rundet dabei nötigenfalls. +// > x: eine reelle Zahl +// < ergebnis: (float x) +// Abhängig von cl_default_float_format. +extern const cl_F cl_float (const cl_R& x); + + +// Liefert (- x), wo x eine reelle Zahl ist. +extern const cl_R operator- (const cl_R& x); + +// Liefert (+ x y), wo x und y reelle Zahlen sind. +extern const cl_R operator+ (const cl_R& x, const cl_R& y); +// Spezialfall: x oder y Float -> Ergebnis Float +inline const cl_F operator+ (const cl_R& x, const cl_F& y) + { return The(cl_F)(x + The(cl_R)(y)); } +inline const cl_F operator+ (const cl_F& x, const cl_R& y) + { return The(cl_F)(The(cl_R)(x) + y); } +// Dem C++-Compiler muß man nun auch das Folgende sagen: +inline const cl_R operator+ (const int x, const cl_R& y) + { return cl_I(x) + y; } +inline const cl_R operator+ (const unsigned int x, const cl_R& y) + { return cl_I(x) + y; } +inline const cl_R operator+ (const long x, const cl_R& y) + { return cl_I(x) + y; } +inline const cl_R operator+ (const unsigned long x, const cl_R& y) + { return cl_I(x) + y; } +inline const cl_R operator+ (const cl_R& x, const int y) + { return x + cl_I(y); } +inline const cl_R operator+ (const cl_R& x, const unsigned int y) + { return x + cl_I(y); } +inline const cl_R operator+ (const cl_R& x, const long y) + { return x + cl_I(y); } +inline const cl_R operator+ (const cl_R& x, const unsigned long y) + { return x + cl_I(y); } + +// Liefert (- x y), wo x und y reelle Zahlen sind. +extern const cl_R operator- (const cl_R& x, const cl_R& y); +// Spezialfall: x oder y Float -> Ergebnis Float +inline const cl_F operator- (const cl_R& x, const cl_F& y) + { return The(cl_F)(x - The(cl_R)(y)); } +inline const cl_F operator- (const cl_F& x, const cl_R& y) + { return The(cl_F)(The(cl_R)(x) - y); } +// Dem C++-Compiler muß man nun auch das Folgende sagen: +inline const cl_R operator- (const int x, const cl_R& y) + { return cl_I(x) - y; } +inline const cl_R operator- (const unsigned int x, const cl_R& y) + { return cl_I(x) - y; } +inline const cl_R operator- (const long x, const cl_R& y) + { return cl_I(x) - y; } +inline const cl_R operator- (const unsigned long x, const cl_R& y) + { return cl_I(x) - y; } +inline const cl_R operator- (const cl_R& x, const int y) + { return x - cl_I(y); } +inline const cl_R operator- (const cl_R& x, const unsigned int y) + { return x - cl_I(y); } +inline const cl_R operator- (const cl_R& x, const long y) + { return x - cl_I(y); } +inline const cl_R operator- (const cl_R& x, const unsigned long y) + { return x - cl_I(y); } + +// Liefert (* x y), wo x und y reelle Zahlen sind. +extern const cl_R operator* (const cl_R& x, const cl_R& y); +// Dem C++-Compiler muß man auch das Folgende sagen (wg. `int * cl_F' u.ä.): +inline const cl_R operator* (const int x, const cl_R& y) + { return cl_I(x) * y; } +inline const cl_R operator* (const unsigned int x, const cl_R& y) + { return cl_I(x) * y; } +inline const cl_R operator* (const long x, const cl_R& y) + { return cl_I(x) * y; } +inline const cl_R operator* (const unsigned long x, const cl_R& y) + { return cl_I(x) * y; } +inline const cl_R operator* (const cl_R& x, const int y) + { return x * cl_I(y); } +inline const cl_R operator* (const cl_R& x, const unsigned int y) + { return x * cl_I(y); } +inline const cl_R operator* (const cl_R& x, const long y) + { return x * cl_I(y); } +inline const cl_R operator* (const cl_R& x, const unsigned long y) + { return x * cl_I(y); } + +// Liefert (* x x), wo x eine reelle Zahl ist. +extern const cl_R square (const cl_R& x); + +// Liefert (/ x y), wo x und y reelle Zahlen sind. +extern const cl_R operator/ (const cl_R& x, const cl_R& y); +// Spezialfall: x oder y Float -> Ergebnis Float +inline const cl_F operator/ (const cl_F& x, const cl_R& y) + { return The(cl_F)(The(cl_R)(x) / y); } +// Dem C++-Compiler muß man auch das Folgende sagen (wg. `int / cl_F' u.ä.): +inline const cl_R operator/ (const int x, const cl_R& y) + { return cl_I(x) / y; } +inline const cl_R operator/ (const unsigned int x, const cl_R& y) + { return cl_I(x) / y; } +inline const cl_R operator/ (const long x, const cl_R& y) + { return cl_I(x) / y; } +inline const cl_R operator/ (const unsigned long x, const cl_R& y) + { return cl_I(x) / y; } +inline const cl_R operator/ (const cl_R& x, const int y) + { return x / cl_I(y); } +inline const cl_R operator/ (const cl_R& x, const unsigned int y) + { return x / cl_I(y); } +inline const cl_R operator/ (const cl_R& x, const long y) + { return x / cl_I(y); } +inline const cl_R operator/ (const cl_R& x, const unsigned long y) + { return x / cl_I(y); } + +// Liefert (abs x), wo x eine reelle Zahl ist. +extern const cl_R abs (const cl_R& x); + +// recip(x) liefert (/ x), wo x eine reelle Zahl ist. +extern const cl_R recip (const cl_R& x); + +// (1+ x), wo x eine reelle Zahl ist. +extern const cl_R plus1 (const cl_R& x); + +// (1- x), wo x eine reelle Zahl ist. +extern const cl_R minus1 (const cl_R& x); + + +// Return type for rounding operators. +// x / y --> (q,r) with x = y*q+r. +struct cl_R_div_t { + cl_I quotient; + cl_R remainder; +// Constructor. + cl_R_div_t () {} + cl_R_div_t (const cl_I& q, const cl_R& r) : quotient(q), remainder(r) {} + cl_R_div_t (const struct cl_I_div_t &); + cl_R_div_t (const struct cl_RA_div_t &); + cl_R_div_t (const struct cl_F_div_t &); +}; + +// floor2(x) liefert (floor x), wo x eine reelle Zahl ist. +extern const cl_R_div_t floor2 (const cl_R& x); +extern const cl_I floor1 (const cl_R& x); + +// ceiling2(x) liefert (ceiling x), wo x eine reelle Zahl ist. +extern const cl_R_div_t ceiling2 (const cl_R& x); +extern const cl_I ceiling1 (const cl_R& x); + +// truncate2(x) liefert (truncate x), wo x eine reelle Zahl ist. +extern const cl_R_div_t truncate2 (const cl_R& x); +extern const cl_I truncate1 (const cl_R& x); + +// round2(x) liefert (round x), wo x eine reelle Zahl ist. +extern const cl_R_div_t round2 (const cl_R& x); +extern const cl_I round1 (const cl_R& x); + +// floor2(x,y) liefert (floor x y), wo x und y reelle Zahlen sind. +extern const cl_R_div_t floor2 (const cl_R& x, const cl_R& y); +extern const cl_I floor1 (const cl_R& x, const cl_R& y); + +// ceiling2(x,y) liefert (ceiling x y), wo x und y reelle Zahlen sind. +extern const cl_R_div_t ceiling2 (const cl_R& x, const cl_R& y); +extern const cl_I ceiling1 (const cl_R& x, const cl_R& y); + +// truncate2(x,y) liefert (truncate x y), wo x und y reelle Zahlen sind. +extern const cl_R_div_t truncate2 (const cl_R& x, const cl_R& y); +extern const cl_I truncate1 (const cl_R& x, const cl_R& y); + +// round2(x,y) liefert (round x y), wo x und y reelle Zahlen sind. +extern const cl_R_div_t round2 (const cl_R& x, const cl_R& y); +extern const cl_I round1 (const cl_R& x, const cl_R& y); + + +// Return type for frounding operators. +// x / y --> (q,r) with x = y*q+r. +struct cl_R_fdiv_t { + cl_F quotient; + cl_R remainder; +// Constructor. + cl_R_fdiv_t () {} + cl_R_fdiv_t (const cl_F& q, const cl_R& r) : quotient(q), remainder(r) {} + cl_R_fdiv_t (const struct cl_F_fdiv_t &); +}; + +// ffloor2(x) liefert (ffloor x), wo x eine reelle Zahl ist. +extern const cl_R_fdiv_t ffloor2 (const cl_R& x); +extern const cl_F ffloor (const cl_R& x); + +// fceiling2(x) liefert (fceiling x), wo x eine reelle Zahl ist. +extern const cl_R_fdiv_t fceiling2 (const cl_R& x); +extern const cl_F fceiling (const cl_R& x); + +// ftruncate2(x) liefert (ftruncate x), wo x eine reelle Zahl ist. +extern const cl_R_fdiv_t ftruncate2 (const cl_R& x); +extern const cl_F ftruncate (const cl_R& x); + +// fround2(x) liefert (fround x), wo x eine reelle Zahl ist. +extern const cl_R_fdiv_t fround2 (const cl_R& x); +extern const cl_F fround (const cl_R& x); + +// ffloor2(x,y) liefert (ffloor x y), wo x und y reelle Zahlen sind. +extern const cl_R_fdiv_t ffloor2 (const cl_R& x, const cl_R& y); +extern const cl_F ffloor (const cl_R& x, const cl_R& y); + +// fceiling2(x,y) liefert (fceiling x y), wo x und y reelle Zahlen sind. +extern const cl_R_fdiv_t fceiling2 (const cl_R& x, const cl_R& y); +extern const cl_F fceiling (const cl_R& x, const cl_R& y); + +// ftruncate2(x,y) liefert (ftruncate x y), wo x und y reelle Zahlen sind. +extern const cl_R_fdiv_t ftruncate2 (const cl_R& x, const cl_R& y); +extern const cl_F ftruncate (const cl_R& x, const cl_R& y); + +// fround2(x,y) liefert (fround x y), wo x und y reelle Zahlen sind. +extern const cl_R_fdiv_t fround2 (const cl_R& x, const cl_R& y); +extern const cl_F fround (const cl_R& x, const cl_R& y); + + +// mod(x,y) = (mod x y), wo x und y reelle Zahlen sind. +extern const cl_R mod (const cl_R& x, const cl_R& y); + +// rem(x,y) = (rem x y), wo x und y reelle Zahlen sind. +extern const cl_R rem (const cl_R& x, const cl_R& y); + + +// rational(x) liefert (rational x), wo x eine reelle Zahl ist. +extern const cl_RA rational (const cl_R& x); +// Spezialfall: +inline const cl_RA rational (const cl_RA& x) { return x; } + + +// cl_equal(x,y) vergleicht zwei reelle Zahlen x und y auf Gleichheit. +extern cl_boolean cl_equal (const cl_R& x, const cl_R& y); +// cl_equal_hashcode(x) liefert einen cl_equal-invarianten Hashcode für x. +extern uint32 cl_equal_hashcode (const cl_R& x); + +// cl_compare(x,y) vergleicht zwei reelle Zahlen x und y. +// Ergebnis: 0 falls x=y, +1 falls x>y, -1 falls x= (const cl_R& x, const cl_R& y) + { return cl_compare(x,y)>=0; } +inline bool operator> (const cl_R& x, const cl_R& y) + { return cl_compare(x,y)>0; } + +// max(x,y) liefert (max x y), wo x und y reelle Zahlen sind. +extern const cl_R max (const cl_R& x, const cl_R& y); + +// min(x,y) liefert (min x y), wo x und y reelle Zahlen sind. +extern const cl_R min (const cl_R& x, const cl_R& y); + +// signum(x) liefert (signum x), wo x eine reelle Zahl ist. +extern const cl_R signum (const cl_R& x); + +// sqrt(x) = (sqrt x) zieht die Wurzel aus einer reellen Zahl x >=0. +extern const cl_R sqrt (const cl_R& x); +// sqrt(x) = (sqrt x) zieht die Wurzel aus einer rationalen Zahl x >=0. +extern const cl_R sqrt (const cl_RA& x); + +// (expt x y), wo x eine reelle Zahl und y ein Integer ist. +extern const cl_R expt (const cl_R& x, sintL y); +extern const cl_R expt (const cl_R& x, const cl_I& y); + +// rationalize(x) liefert (rationalize x), wo x eine reelle Zahl ist. +extern const cl_RA rationalize (const cl_R& x); + + +// Konversion zu einem C "float". +extern float cl_float_approx (const cl_R& x); + +// Konversion zu einem C "double". +extern double cl_double_approx (const cl_R& x); + + +// Transcendental functions + + +// atan(x,y) liefert zu zwei reellen Zahlen x, y den Winkel von (x,y) +// in Polarkoordinaten. Ergebnis rational nur, wenn x>0 und y=0. +extern const cl_R atan (const cl_R& x, const cl_R& y); +// Spezialfall: y Float -> Ergebnis Float +inline const cl_F atan (const cl_R& x, const cl_F& y) + { return The(cl_F)(atan(x,The(cl_R)(y))); } +// Dem C++-Compiler muß man nun auch das Folgende sagen: +inline const cl_R atan (const cl_R& x, const int y) + { return atan(x,cl_I(y)); } +inline const cl_R atan (const cl_R& x, const unsigned int y) + { return atan(x,cl_I(y)); } +inline const cl_R atan (const cl_R& x, const long y) + { return atan(x,cl_I(y)); } +inline const cl_R atan (const cl_R& x, const unsigned long y) + { return atan(x,cl_I(y)); } + +// atan(x) liefert den Arctan einer reellen Zahl x. +// Ergebnis rational nur, wenn x=0. +extern const cl_R atan (const cl_R& x); +// Spezialfall: x Float -> Ergebnis Float +inline const cl_F atan (const cl_F& x) { return The(cl_F)(atan(The(cl_R)(x))); } +// Dem C++-Compiler muß man nun auch das Folgende sagen: +inline const cl_R atan (const int x) { return atan(cl_I(x)); } +inline const cl_R atan (const unsigned int x) { return atan(cl_I(x)); } +inline const cl_R atan (const long x) { return atan(cl_I(x)); } +inline const cl_R atan (const unsigned long x) { return atan(cl_I(x)); } + +// sin(x) liefert den Sinus (sin x) einer reellen Zahl x. +extern const cl_R sin (const cl_R& x); +// Dem C++-Compiler muß man nun auch das Folgende sagen: +inline const cl_R sin (const int x) { return sin(cl_I(x)); } +inline const cl_R sin (const unsigned int x) { return sin(cl_I(x)); } +inline const cl_R sin (const long x) { return sin(cl_I(x)); } +inline const cl_R sin (const unsigned long x) { return sin(cl_I(x)); } + +// cos(x) liefert den Cosinus (cos x) einer reellen Zahl x. +extern const cl_R cos (const cl_R& x); +// Dem C++-Compiler muß man nun auch das Folgende sagen: +inline const cl_R cos (const int x) { return cos(cl_I(x)); } +inline const cl_R cos (const unsigned int x) { return cos(cl_I(x)); } +inline const cl_R cos (const long x) { return cos(cl_I(x)); } +inline const cl_R cos (const unsigned long x) { return cos(cl_I(x)); } + +// cl_cos_sin(x) liefert ((cos x),(sin x)), beide Werte. +extern const cl_cos_sin_t cl_cos_sin (const cl_R& x); + +// tan(x) liefert den Tangens (tan x) einer reellen Zahl x. +extern const cl_R tan (const cl_R& x); +// Dem C++-Compiler muß man nun auch das Folgende sagen: +inline const cl_R tan (const int x) { return tan(cl_I(x)); } +inline const cl_R tan (const unsigned int x) { return tan(cl_I(x)); } +inline const cl_R tan (const long x) { return tan(cl_I(x)); } +inline const cl_R tan (const unsigned long x) { return tan(cl_I(x)); } + +// ln(x) liefert zu einer reellen Zahl x>0 die Zahl ln(x). +extern const cl_R ln (const cl_R& x); +// Dem C++-Compiler muß man nun auch das Folgende sagen: +inline const cl_R ln (const int x) { return ln(cl_I(x)); } +inline const cl_R ln (const unsigned int x) { return ln(cl_I(x)); } +inline const cl_R ln (const long x) { return ln(cl_I(x)); } +inline const cl_R ln (const unsigned long x) { return ln(cl_I(x)); } + +// log(a,b) liefert zu reellen Zahlen a>0, b>0 die Zahl +// log(a,b)=ln(a)/ln(b). +// Ergebnis rational nur, wenn a=1 oder a und b rational. +extern const cl_R log (const cl_R& a, const cl_R& b); + +// exp(x) liefert zu einer reellen Zahl x die Zahl exp(x). +extern const cl_R exp (const cl_R& x); +// Dem C++-Compiler muß man nun auch das Folgende sagen: +inline const cl_R exp (const int x) { return exp(cl_I(x)); } +inline const cl_R exp (const unsigned int x) { return exp(cl_I(x)); } +inline const cl_R exp (const long x) { return exp(cl_I(x)); } +inline const cl_R exp (const unsigned long x) { return exp(cl_I(x)); } + +// sinh(x) liefert zu einer reellen Zahl x die Zahl sinh(x). +extern const cl_R sinh (const cl_R& x); +// Dem C++-Compiler muß man nun auch das Folgende sagen: +inline const cl_R sinh (const int x) { return sinh(cl_I(x)); } +inline const cl_R sinh (const unsigned int x) { return sinh(cl_I(x)); } +inline const cl_R sinh (const long x) { return sinh(cl_I(x)); } +inline const cl_R sinh (const unsigned long x) { return sinh(cl_I(x)); } + +// cosh(x) liefert zu einer reellen Zahl x die Zahl cosh(x). +extern const cl_R cosh (const cl_R& x); +// Dem C++-Compiler muß man nun auch das Folgende sagen: +inline const cl_R cosh (const int x) { return cosh(cl_I(x)); } +inline const cl_R cosh (const unsigned int x) { return cosh(cl_I(x)); } +inline const cl_R cosh (const long x) { return cosh(cl_I(x)); } +inline const cl_R cosh (const unsigned long x) { return cosh(cl_I(x)); } + +// cl_cosh_sinh(x) liefert ((cosh x),(sinh x)), beide Werte. +extern const cl_cosh_sinh_t cl_cosh_sinh (const cl_R& x); + +// tanh(x) liefert zu einer reellen Zahl x die Zahl tanh(x). +extern const cl_R tanh (const cl_R& x); +// Dem C++-Compiler muß man nun auch das Folgende sagen: +inline const cl_R tanh (const int x) { return tanh(cl_I(x)); } +inline const cl_R tanh (const unsigned int x) { return tanh(cl_I(x)); } +inline const cl_R tanh (const long x) { return tanh(cl_I(x)); } +inline const cl_R tanh (const unsigned long x) { return tanh(cl_I(x)); } + + +// random_R(randomstate,n) liefert zu einer reellen Zahl n>0 eine Zufallszahl +// x mit 0 <= x < n. +extern const cl_R random_R (cl_random_state& randomstate, const cl_R& n); + +inline const cl_R random_R (const cl_R& n) + { return random_R(cl_default_random_state,n); } + + +#ifdef WANT_OBFUSCATING_OPERATORS +// This could be optimized to use in-place operations. +inline cl_R& operator+= (cl_R& x, const cl_R& y) { return x = x + y; } +inline cl_F& operator+= (cl_F& x, const cl_R& y) { return x = x + y; } +inline cl_F& operator+= (cl_F& x, const cl_RA& y) { return x = x + y; } +inline cl_F& operator+= (cl_F& x, const cl_I& y) { return x = x + y; } +inline cl_R& operator+= (cl_R& x, const int y) { return x = x + y; } +inline cl_R& operator+= (cl_R& x, const unsigned int y) { return x = x + y; } +inline cl_R& operator+= (cl_R& x, const long y) { return x = x + y; } +inline cl_R& operator+= (cl_R& x, const unsigned long y) { return x = x + y; } +inline cl_F& operator+= (cl_F& x, const int y) { return x = x + y; } +inline cl_F& operator+= (cl_F& x, const unsigned int y) { return x = x + y; } +inline cl_F& operator+= (cl_F& x, const long y) { return x = x + y; } +inline cl_F& operator+= (cl_F& x, const unsigned long y) { return x = x + y; } +inline cl_R& operator++ /* prefix */ (cl_R& x) { return x = plus1(x); } +inline void operator++ /* postfix */ (cl_R& x, int dummy) { (void)dummy; x = plus1(x); } +inline cl_R& operator-= (cl_R& x, const cl_R& y) { return x = x - y; } +inline cl_F& operator-= (cl_F& x, const cl_R& y) { return x = x - y; } +inline cl_F& operator-= (cl_F& x, const cl_RA& y) { return x = x - y; } +inline cl_F& operator-= (cl_F& x, const cl_I& y) { return x = x - y; } +inline cl_R& operator-= (cl_R& x, const int y) { return x = x - y; } +inline cl_R& operator-= (cl_R& x, const unsigned int y) { return x = x - y; } +inline cl_R& operator-= (cl_R& x, const long y) { return x = x - y; } +inline cl_R& operator-= (cl_R& x, const unsigned long y) { return x = x - y; } +inline cl_F& operator-= (cl_F& x, const int y) { return x = x - y; } +inline cl_F& operator-= (cl_F& x, const unsigned int y) { return x = x - y; } +inline cl_F& operator-= (cl_F& x, const long y) { return x = x - y; } +inline cl_F& operator-= (cl_F& x, const unsigned long y) { return x = x - y; } +inline cl_R& operator-- /* prefix */ (cl_R& x) { return x = minus1(x); } +inline void operator-- /* postfix */ (cl_R& x, int dummy) { (void)dummy; x = minus1(x); } +inline cl_R& operator*= (cl_R& x, const cl_R& y) { return x = x * y; } +inline cl_R& operator/= (cl_R& x, const cl_R& y) { return x = x / y; } +inline cl_F& operator/= (cl_F& x, const cl_R& y) { return x = x / y; } +inline cl_F& operator/= (cl_F& x, const cl_RA& y) { return x = x / y; } +inline cl_F& operator/= (cl_F& x, const cl_I& y) { return x = x / y; } +inline cl_R& operator/= (cl_R& x, const int y) { return x = x / y; } +inline cl_R& operator/= (cl_R& x, const unsigned int y) { return x = x / y; } +inline cl_R& operator/= (cl_R& x, const long y) { return x = x / y; } +inline cl_R& operator/= (cl_R& x, const unsigned long y) { return x = x / y; } +inline cl_F& operator/= (cl_F& x, const int y) { return x = x / y; } +inline cl_F& operator/= (cl_F& x, const unsigned int y) { return x = x / y; } +inline cl_F& operator/= (cl_F& x, const long y) { return x = x / y; } +inline cl_F& operator/= (cl_F& x, const unsigned long y) { return x = x / y; } +#endif + + +// Complex operations, trivial for reals + +inline const cl_R realpart (const cl_R& x) +{ + return x; +} +inline const cl_R imagpart (const cl_R& x) +{ + (void)x; // unused x + return 0; +} +inline const cl_R conjugate (const cl_R& x) +{ + return x; +} + + +// Debugging support. +#ifdef CL_DEBUG +extern int cl_R_debug_module; +static void* const cl_R_debug_dummy[] = { &cl_R_debug_dummy, + &cl_R_debug_module +}; +#endif + + +#endif /* _CL_REAL_H */ diff --git a/include/cl_real_class.h b/include/cl_real_class.h new file mode 100644 index 0000000..07274b5 --- /dev/null +++ b/include/cl_real_class.h @@ -0,0 +1,63 @@ +// Abstract class of real numbers. + +#ifndef _CL_REAL_CLASS_H +#define _CL_REAL_CLASS_H + +#include "cl_number.h" +#include "cl_complex_class.h" + + +class cl_R : public cl_N { +public: +// Default constructor. + cl_R (); +// Copy constructor. + cl_R (const cl_R&); +// Converters. +// Assignment operators. + cl_R& operator= (const cl_R&); +// Constructors and assignment operators from C numeric types. + cl_R (const int); // |argument| must be < 2^29 + cl_R (const unsigned int); // argument must be < 2^29 + cl_R (const long); + cl_R (const unsigned long); + cl_R (const float); + cl_R (const double); + cl_R& operator= (const int); // |argument| must be < 2^29 + cl_R& operator= (const unsigned int); // argument must be < 2^29 + cl_R& operator= (const long); + cl_R& operator= (const unsigned long); + cl_R& operator= (const float); + cl_R& operator= (const double); +// Other constructors. + cl_R (const char *); +// Private constructor. + cl_R (cl_private_thing); +public: // Ability to place an object at a given address. + void* operator new (size_t size) { return cl_malloc_hook(size); } + void* operator new (size_t size, cl_R* ptr) { (void)size; return ptr; } + void operator delete (void* ptr) { cl_free_hook(ptr); } +private: +// Friend declarations. They are for the compiler. Just ignore them. +}; + +// Private constructors. +inline cl_R::cl_R (cl_private_thing ptr) : cl_N (ptr) {} +// The assignment operators: +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_R, cl_R) +// The default constructors. +inline cl_R::cl_R () + : cl_N ((cl_private_thing) cl_combine(cl_FN_tag,0)) {} +// The copy constructors. +CL_DEFINE_COPY_CONSTRUCTOR2(cl_R,cl_N) +// Constructors and assignment operators from C numeric types. +CL_DEFINE_INT_CONSTRUCTORS(cl_R) +CL_DEFINE_INT_ASSIGNMENT_OPERATORS(cl_R) +CL_DEFINE_LONG_CONSTRUCTORS(cl_R) +CL_DEFINE_LONG_ASSIGNMENT_OPERATORS(cl_R) +CL_DEFINE_FLOAT_CONSTRUCTOR(cl_R) +CL_DEFINE_DOUBLE_CONSTRUCTOR(cl_R) + + + +#endif /* _CL_REAL_CLASS_H */ diff --git a/include/cl_real_io.h b/include/cl_real_io.h new file mode 100644 index 0000000..83e5634 --- /dev/null +++ b/include/cl_real_io.h @@ -0,0 +1,55 @@ +// I/O of real numbers. + +#ifndef _CL_REAL_IO_H +#define _CL_REAL_IO_H + +#include "cl_number_io.h" +#include "cl_real.h" + + +// Undocumented input functions + +// The following does strictly the same as the general read_complex. +// It is here only so that you don't need the complex number reader +// in order to read an rational number. ("Treeshaking") +extern const cl_R read_real (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse); +extern const cl_R read_real (cl_istream stream, const cl_read_flags& flags); + +// Documented input functions + +inline cl_istream operator>> (cl_istream stream, cl_R& result) +{ + extern cl_read_flags cl_R_read_flags; + result = read_real(stream,cl_R_read_flags); + return stream; +} + + +// Undocumented output functions + + +// Documented output functions + +// Gibt eine Zahl aus. +// print_real(stream,flags,z); +// > z: Zahl +// > stream: Stream +// > flags: Ausgabe-Parameter +extern void print_real (cl_ostream stream, const cl_print_flags& flags, const cl_R& z); +extern void print_real (cl_ostream stream, const cl_print_number_flags& flags, const cl_R& z); +extern void print_real (cl_ostream stream, const cl_print_real_flags& flags, const cl_R& z); + +// The following does strictly the same as the general `fprint' for numbers. +// It is here only so that you don't need the complex number printer +// in order to print an integer. ("Treeshaking") + +inline void fprint (cl_ostream stream, const cl_R& x) +{ + extern cl_print_flags cl_default_print_flags; + print_real(stream,cl_default_print_flags,x); +} + +CL_DEFINE_PRINT_OPERATOR(cl_R) + + +#endif /* _CL_REAL_IO_H */ diff --git a/include/cl_real_ring.h b/include/cl_real_ring.h new file mode 100644 index 0000000..09f611c --- /dev/null +++ b/include/cl_real_ring.h @@ -0,0 +1,14 @@ +// Built-in real number ring. + +#ifndef _CL_REAL_RING_H +#define _CL_REAL_RING_H + +#include "cl_ring.h" +#include "cl_real_class.h" + +typedef cl_specialized_number_ring cl_real_ring; +extern const cl_real_ring cl_R_ring; // math. R +extern cl_class cl_class_real_ring; +//CL_REQUIRE(cl_R_ring) + +#endif /* _CL_REAL_RING_H */ diff --git a/include/cl_ring.h b/include/cl_ring.h new file mode 100644 index 0000000..c57431e --- /dev/null +++ b/include/cl_ring.h @@ -0,0 +1,446 @@ +// Ring operations. + +#ifndef _CL_RING_H +#define _CL_RING_H + +#include "cl_object.h" +#include "cl_malloc.h" +#include "cl_proplist.h" +#include "cl_number.h" +#include "cl_io.h" +class cl_I; + +// This file defines the general layout of rings, ring elements, and +// operations available on ring elements. Any subclass of `cl_ring' +// must implement these operations, with the same memory layout. +// (Because generic packages like the polynomial rings access the base +// ring's operation vectors through inline functions defined in this file.) + +class cl_heap_ring; + +// Rings are reference counted, but not freed immediately when they aren't +// used any more. Hence they inherit from `cl_rcpointer'. + +// Vectors of function pointers are more efficient than virtual member +// functions. But it constrains us not to use multiple or virtual inheritance. +// +// Note! We are passing raw `cl_heap_ring*' pointers to the operations +// for efficiency (compared to passing `const cl_ring&', we save a memory +// access, and it is easier to cast to a `cl_heap_ring_specialized*'). +// These raw pointers are meant to be used downward (in the dynamic extent +// of the call) only. If you need to save them in a data structure, cast +// to `cl_ring'; this will correctly increment the reference count. +// (This technique is safe because the inline wrapper functions make sure +// that we have a `cl_ring' somewhere containing the pointer, so there +// is no danger of dangling pointers.) +// +// Note! Because the `cl_heap_ring*' -> `cl_ring' conversion increments +// the reference count, you have to use the `cl_private_thing' -> `cl_ring' +// conversion if the reference count is already incremented. + +class cl_ring : public cl_rcpointer { +public: + // Constructor. Takes a cl_heap_ring*, increments its refcount. + cl_ring (cl_heap_ring* r); + // Private constructor. Doesn't increment the refcount. + cl_ring (cl_private_thing); + // Copy constructor. + cl_ring (const cl_ring&); + // Assignment operator. + cl_ring& operator= (const cl_ring&); + // Default constructor. + cl_ring (); + // Automatic dereferencing. + cl_heap_ring* operator-> () const + { return (cl_heap_ring*)heappointer; } +}; +CL_DEFINE_COPY_CONSTRUCTOR2(cl_ring,cl_rcpointer) +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_ring,cl_ring) + +// Normal constructor for `cl_ring'. +inline cl_ring::cl_ring (cl_heap_ring* r) +{ cl_inc_pointer_refcount((cl_heap*)r); pointer = r; } +// Private constructor for `cl_ring'. +inline cl_ring::cl_ring (cl_private_thing p) +{ pointer = p; } + +inline bool operator== (const cl_ring& R1, const cl_ring& R2) +{ return (R1.pointer == R2.pointer); } +inline bool operator!= (const cl_ring& R1, const cl_ring& R2) +{ return (R1.pointer != R2.pointer); } +inline bool operator== (const cl_ring& R1, cl_heap_ring* R2) +{ return (R1.pointer == R2); } +inline bool operator!= (const cl_ring& R1, cl_heap_ring* R2) +{ return (R1.pointer != R2); } + +// Representation of an element of a ring. +// +// In order to support true polymorphism (without C++ templates), all +// ring elements share the same basic layout: +// cl_ring ring; // the ring +// cl_gcobject rep; // representation of the element +// The representation of the element depends on the ring, of course, +// but we constrain it to be a single pointer into the heap or an immediate +// value. +// +// Any arithmetic operation on a ring R (like +, -, *) must return a value +// with ring = R. This is +// a. necessary if the computation is to proceed correctly (e.g. in cl_RA, +// ((3/4)*4 mod 3) is 0, simplifying it to ((cl_I)4 mod (cl_I)3) = 1 +// wouldn't be correct), +// b. possible even if R is an extension ring of some ring R1 (e.g. cl_N +// being an extension ring of cl_R). Automatic retraction from R to R1 +// can be done through dynamic typing: An element of R which happens +// to lie in R1 is stored using the internal representation of R1, +// but with ring = R. Elements of R1 and R\R1 can be distinguished +// through rep's type. +// c. an advantage for the implementation of polynomials and other +// entities which contain many elements of the same ring. They need +// to store only the elements' representations, and a single pointer +// to the ring. +// +// The ring operations exist in two versions: +// - Low-level version, which only operates on the representation. +// - High-level version, which operates on full cl_ring_elements. +// We make this distinction for performance: Multiplication of polynomials +// over Z/nZ, operating on the high-level operations, spends 40% of its +// computing time with packing and unpacking of cl_ring_elements. +// The low-level versions have an underscore prepended and are unsafe. + +class _cl_ring_element { +public: + cl_gcobject rep; // representation of the element + // Default constructor. + _cl_ring_element (); +public: /* ugh */ + // Constructor. + _cl_ring_element (const cl_heap_ring* R, const cl_gcobject& r) : rep (as_cl_private_thing(r)) { (void)R; } + _cl_ring_element (const cl_ring& R, const cl_gcobject& r) : rep (as_cl_private_thing(r)) { (void)R; } +public: // Ability to place an object at a given address. + void* operator new (size_t size) { return cl_malloc_hook(size); } + void* operator new (size_t size, _cl_ring_element* ptr) { (void)size; return ptr; } + void operator delete (void* ptr) { cl_free_hook(ptr); } +}; + +class cl_ring_element : public _cl_ring_element { +protected: + cl_ring _ring; // ring +public: + const cl_ring& ring () const { return _ring; } + // Default constructor. + cl_ring_element (); +public: /* ugh */ + // Constructor. + cl_ring_element (const cl_ring& R, const cl_gcobject& r) : _cl_ring_element (R,r), _ring (R) {} + cl_ring_element (const cl_ring& R, const _cl_ring_element& r) : _cl_ring_element (r), _ring (R) {} +public: // Debugging output. + void debug_print () const; + // Ability to place an object at a given address. + void* operator new (size_t size) { return cl_malloc_hook(size); } + void* operator new (size_t size, cl_ring_element* ptr) { (void)size; return ptr; } + void operator delete (void* ptr) { cl_free_hook(ptr); } +}; + +// The ring operations are encoded as vectors of function pointers. You +// can add more operations to the end of each vector or add new vectors, +// but you must not reorder the operations nor reorder the vectors nor +// change the functions' signatures incompatibly. + +// There should ideally be a template class for each vector, but unfortunately +// you lose the ability to initialize the vector using "= { ... }" syntax +// when you subclass it. + +struct _cl_ring_setops { + // print + void (* fprint) (cl_heap_ring* R, cl_ostream stream, const _cl_ring_element& x); + // equality + cl_boolean (* equal) (cl_heap_ring* R, const _cl_ring_element& x, const _cl_ring_element& y); + // ... +}; +struct _cl_ring_addops { + // 0 + const _cl_ring_element (* zero) (cl_heap_ring* R); + cl_boolean (* zerop) (cl_heap_ring* R, const _cl_ring_element& x); + // x+y + const _cl_ring_element (* plus) (cl_heap_ring* R, const _cl_ring_element& x, const _cl_ring_element& y); + // x-y + const _cl_ring_element (* minus) (cl_heap_ring* R, const _cl_ring_element& x, const _cl_ring_element& y); + // -x + const _cl_ring_element (* uminus) (cl_heap_ring* R, const _cl_ring_element& x); + // ... +}; +struct _cl_ring_mulops { + // 1 + const _cl_ring_element (* one) (cl_heap_ring* R); + // canonical homomorphism + const _cl_ring_element (* canonhom) (cl_heap_ring* R, const cl_I& x); + // x*y + const _cl_ring_element (* mul) (cl_heap_ring* R, const _cl_ring_element& x, const _cl_ring_element& y); + // x^2 + const _cl_ring_element (* square) (cl_heap_ring* R, const _cl_ring_element& x); + // x^y, y Integer >0 + const _cl_ring_element (* expt_pos) (cl_heap_ring* R, const _cl_ring_element& x, const cl_I& y); + // ... +}; +#if defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 8) // workaround two g++-2.7.0 bugs + #define cl_ring_setops _cl_ring_setops + #define cl_ring_addops _cl_ring_addops + #define cl_ring_mulops _cl_ring_mulops +#else + typedef const _cl_ring_setops cl_ring_setops; + typedef const _cl_ring_addops cl_ring_addops; + typedef const _cl_ring_mulops cl_ring_mulops; +#endif + +// Representation of a ring in memory. + +class cl_heap_ring : public cl_heap { +public: + // Allocation. + void* operator new (size_t size) { return cl_malloc_hook(size); } + // Deallocation. + void operator delete (void* ptr) { cl_free_hook(ptr); } +private: + cl_property_list properties; +protected: + cl_ring_setops* setops; + cl_ring_addops* addops; + cl_ring_mulops* mulops; +public: + // More information comes here. + // ... +public: + // Low-level operations. + void _fprint (cl_ostream stream, const _cl_ring_element& x) + { setops->fprint(this,stream,x); } + cl_boolean _equal (const _cl_ring_element& x, const _cl_ring_element& y) + { return setops->equal(this,x,y); } + const _cl_ring_element _zero () + { return addops->zero(this); } + cl_boolean _zerop (const _cl_ring_element& x) + { return addops->zerop(this,x); } + const _cl_ring_element _plus (const _cl_ring_element& x, const _cl_ring_element& y) + { return addops->plus(this,x,y); } + const _cl_ring_element _minus (const _cl_ring_element& x, const _cl_ring_element& y) + { return addops->minus(this,x,y); } + const _cl_ring_element _uminus (const _cl_ring_element& x) + { return addops->uminus(this,x); } + const _cl_ring_element _one () + { return mulops->one(this); } + const _cl_ring_element _canonhom (const cl_I& x) + { return mulops->canonhom(this,x); } + const _cl_ring_element _mul (const _cl_ring_element& x, const _cl_ring_element& y) + { return mulops->mul(this,x,y); } + const _cl_ring_element _square (const _cl_ring_element& x) + { return mulops->square(this,x); } + const _cl_ring_element _expt_pos (const _cl_ring_element& x, const cl_I& y) + { return mulops->expt_pos(this,x,y); } + // High-level operations. + void fprint (cl_ostream stream, const cl_ring_element& x) + { + if (!(x.ring() == this)) cl_abort(); + _fprint(stream,x); + } + cl_boolean equal (const cl_ring_element& x, const cl_ring_element& y) + { + if (!(x.ring() == this)) cl_abort(); + if (!(y.ring() == this)) cl_abort(); + return _equal(x,y); + } + const cl_ring_element zero () + { + return cl_ring_element(this,_zero()); + } + cl_boolean zerop (const cl_ring_element& x) + { + if (!(x.ring() == this)) cl_abort(); + return _zerop(x); + } + const cl_ring_element plus (const cl_ring_element& x, const cl_ring_element& y) + { + if (!(x.ring() == this)) cl_abort(); + if (!(y.ring() == this)) cl_abort(); + return cl_ring_element(this,_plus(x,y)); + } + const cl_ring_element minus (const cl_ring_element& x, const cl_ring_element& y) + { + if (!(x.ring() == this)) cl_abort(); + if (!(y.ring() == this)) cl_abort(); + return cl_ring_element(this,_minus(x,y)); + } + const cl_ring_element uminus (const cl_ring_element& x) + { + if (!(x.ring() == this)) cl_abort(); + return cl_ring_element(this,_uminus(x)); + } + const cl_ring_element one () + { + return cl_ring_element(this,_one()); + } + const cl_ring_element canonhom (const cl_I& x) + { + return cl_ring_element(this,_canonhom(x)); + } + const cl_ring_element mul (const cl_ring_element& x, const cl_ring_element& y) + { + if (!(x.ring() == this)) cl_abort(); + if (!(y.ring() == this)) cl_abort(); + return cl_ring_element(this,_mul(x,y)); + } + const cl_ring_element square (const cl_ring_element& x) + { + if (!(x.ring() == this)) cl_abort(); + return cl_ring_element(this,_square(x)); + } + const cl_ring_element expt_pos (const cl_ring_element& x, const cl_I& y) + { + if (!(x.ring() == this)) cl_abort(); + return cl_ring_element(this,_expt_pos(x,y)); + } + // Property operations. + cl_property* get_property (const cl_symbol& key) + { return properties.get_property(key); } + void add_property (cl_property* new_property) + { properties.add_property(new_property); } +// Constructor. + cl_heap_ring (cl_ring_setops* setopv, cl_ring_addops* addopv, cl_ring_mulops* mulopv) + : setops (setopv), addops (addopv), mulops (mulopv) + { refcount = 0; } // will be incremented by the `cl_ring' constructor +}; +#define SUBCLASS_cl_heap_ring() \ +public: \ + /* Allocation. */ \ + void* operator new (size_t size) { return cl_malloc_hook(size); } \ + /* Deallocation. */ \ + void operator delete (void* ptr) { cl_free_hook(ptr); } + +// Operations on ring elements. + +// Output. +inline void fprint (cl_ostream stream, const cl_ring_element& x) + { x.ring()->fprint(stream,x); } +CL_DEFINE_PRINT_OPERATOR(cl_ring_element) + +// Add. +inline const cl_ring_element operator+ (const cl_ring_element& x, const cl_ring_element& y) + { return x.ring()->plus(x,y); } + +// Negate. +inline const cl_ring_element operator- (const cl_ring_element& x) + { return x.ring()->uminus(x); } + +// Subtract. +inline const cl_ring_element operator- (const cl_ring_element& x, const cl_ring_element& y) + { return x.ring()->minus(x,y); } + +// Equality. +inline bool operator== (const cl_ring_element& x, const cl_ring_element& y) + { return x.ring()->equal(x,y); } +inline bool operator!= (const cl_ring_element& x, const cl_ring_element& y) + { return !x.ring()->equal(x,y); } + +// Compare against 0. +inline cl_boolean zerop (const cl_ring_element& x) + { return x.ring()->zerop(x); } + +// Multiply. +inline const cl_ring_element operator* (const cl_ring_element& x, const cl_ring_element& y) + { return x.ring()->mul(x,y); } + +// Squaring. +inline const cl_ring_element square (const cl_ring_element& x) + { return x.ring()->square(x); } + +// Exponentiation x^y, where y > 0. +inline const cl_ring_element expt_pos (const cl_ring_element& x, const cl_I& y) + { return x.ring()->expt_pos(x,y); } + +// Scalar multiplication. +// [Is this operation worth being specially optimized for the case of +// polynomials?? Polynomials have a faster scalar multiplication. +// We should use it.??] +inline const cl_ring_element operator* (const cl_I& x, const cl_ring_element& y) + { return y.ring()->mul(y.ring()->canonhom(x),y); } +inline const cl_ring_element operator* (const cl_ring_element& x, const cl_I& y) + { return x.ring()->mul(x.ring()->canonhom(y),x); } + + +// Ring of uninitialized elements. +// Any operation results in a run-time error. + +extern const cl_ring cl_no_ring; +extern cl_class cl_class_no_ring; +CL_REQUIRE(cl_no_ring) + +inline cl_ring::cl_ring () + : cl_rcpointer (as_cl_private_thing(cl_no_ring)) {} +inline _cl_ring_element::_cl_ring_element () + : rep ((cl_private_thing) cl_combine(cl_FN_tag,0)) {} +inline cl_ring_element::cl_ring_element () + : _cl_ring_element (), _ring () {} + + +// Support for built-in number rings. +// Beware, they are not optimally efficient. + +template +struct cl_number_ring_ops { + cl_boolean (* contains) (const cl_number&); + cl_boolean (* equal) (const T&, const T&); + cl_boolean (* zerop) (const T&); + const T (* plus) (const T&, const T&); + const T (* minus) (const T&, const T&); + const T (* uminus) (const T&); + const T (* mul) (const T&, const T&); + const T (* square) (const T&); + const T (* expt_pos) (const T&, const cl_I&); +}; +class cl_heap_number_ring : public cl_heap_ring { +public: + cl_number_ring_ops* ops; + // Constructor. + cl_heap_number_ring (cl_ring_setops* setopv, cl_ring_addops* addopv, cl_ring_mulops* mulopv, cl_number_ring_ops* opv) + : cl_heap_ring (setopv,addopv,mulopv), ops (opv) {} +}; + +class cl_number_ring : public cl_ring { +public: + cl_number_ring (cl_heap_number_ring* r) + : cl_ring (r) {} +}; + +template +class cl_specialized_number_ring : public cl_number_ring { +public: + cl_specialized_number_ring (); +}; + +// Type test. +inline cl_boolean instanceof (const cl_number& x, const cl_number_ring& R) +{ + return ((cl_heap_number_ring*) R.heappointer)->ops->contains(x); +} + + +// Hack section. + +// Conversions to subtypes without checking: +// The2(cl_MI)(x) converts x to a cl_MI, without change of representation! + #define The(type) *(const type *) & cl_identity + #define The2(type) *(const type *) & cl_identity2 +// This inline function is for type checking purposes only. + inline const cl_ring& cl_identity (const cl_ring& r) { return r; } + inline const cl_ring_element& cl_identity2 (const cl_ring_element& x) { return x; } + inline const cl_gcobject& cl_identity (const _cl_ring_element& x) { return x.rep; } + + +// Debugging support. +#ifdef CL_DEBUG +extern int cl_ring_debug_module; +static void* const cl_ring_debug_dummy[] = { &cl_ring_debug_dummy, + &cl_ring_debug_module +}; +#endif + + +#endif /* _CL_RING_H */ diff --git a/include/cl_sfloat.h b/include/cl_sfloat.h new file mode 100644 index 0000000..868e439 --- /dev/null +++ b/include/cl_sfloat.h @@ -0,0 +1,304 @@ +// Public short float operations. + +#ifndef _CL_SFLOAT_H +#define _CL_SFLOAT_H + +#include "cl_number.h" +#include "cl_sfloat_class.h" +#include "cl_integer_class.h" +#include "cl_float.h" + + +CL_DEFINE_AS_CONVERSION(cl_SF) + + +// Liefert zu einem Short-Float x : (- x), ein SF. +extern const cl_SF operator- (const cl_SF& x); + +// cl_compare(x,y) vergleicht zwei Short-Floats x und y. +// Ergebnis: 0 falls x=y, +1 falls x>y, -1 falls x= (const cl_SF& x, const cl_SF& y) + { return cl_compare(x,y)>=0; } +inline bool operator> (const cl_SF& x, const cl_SF& y) + { return cl_compare(x,y)>0; } + +// minusp(x) == (< x 0) +extern cl_boolean minusp (const cl_SF& x); + +// zerop(x) stellt fest, ob ein Short-Float x = 0.0 ist. +extern cl_boolean zerop (const cl_SF& x); + +// plusp(x) == (> x 0) +extern cl_boolean plusp (const cl_SF& x); + +// Liefert zu zwei Short-Float x und y : (+ x y), ein SF. +extern const cl_SF operator+ (const cl_SF& x, const cl_SF& y); + +// Liefert zu zwei Short-Float x und y : (- x y), ein SF. +extern const cl_SF operator- (const cl_SF& x, const cl_SF& y); + +// Liefert zu zwei Short-Float x und y : (* x y), ein SF. +extern const cl_SF operator* (const cl_SF& x, const cl_SF& y); + +// Liefert zu einem Short-Float x : (* x x), ein SF. +inline const cl_SF square (const cl_SF& x) { return x*x; } + +// Liefert zu zwei Short-Float x und y : (/ x y), ein SF. +extern const cl_SF operator/ (const cl_SF& x, const cl_SF& y); + +// Liefert zu einem Short-Float x>=0 : (sqrt x), ein SF. +extern const cl_SF sqrt (const cl_SF& x); + +// recip(x) liefert (/ x), wo x ein Short-Float ist. +extern const cl_SF recip (const cl_SF& x); + +// abs(x) liefert (abs x), wo x ein Short-Float ist. +extern const cl_SF abs (const cl_SF& x); + + +// (1+ x), wo x ein Short-Float ist. +inline const cl_SF plus1 (const cl_SF& x) +{ + extern const cl_SF cl_I_to_SF (const cl_I&); + return x + cl_I_to_SF(cl_I(1)); +} + +// (1- x), wo x ein Short-Float ist. +inline const cl_SF minus1 (const cl_SF& x) +{ + extern const cl_SF cl_I_to_SF (const cl_I&); + return x + cl_I_to_SF(cl_I(-1)); +} + + +// ffloor(x) liefert (ffloor x), wo x ein SF ist. +extern const cl_SF ffloor (const cl_SF& x); + +// fceiling(x) liefert (fceiling x), wo x ein SF ist. +extern const cl_SF fceiling (const cl_SF& x); + +// ftruncate(x) liefert (ftruncate x), wo x ein SF ist. +extern const cl_SF ftruncate (const cl_SF& x); + +// fround(x) liefert (fround x), wo x ein SF ist. +extern const cl_SF fround (const cl_SF& x); + + +// Return type for frounding operators. +// x / y --> (q,r) with x = y*q+r. +struct cl_SF_fdiv_t { + cl_SF quotient; + cl_SF remainder; +// Constructor. + cl_SF_fdiv_t () {} + cl_SF_fdiv_t (const cl_SF& q, const cl_SF& r) : quotient(q), remainder(r) {} +}; + +// ffloor2(x) liefert (ffloor x), wo x ein SF ist. +inline const cl_SF_fdiv_t ffloor2 (const cl_SF& x) + { cl_SF q = ffloor(x); return cl_SF_fdiv_t(q,x-q); } + +// fceiling2(x) liefert (fceiling x), wo x ein SF ist. +inline const cl_SF_fdiv_t fceiling2 (const cl_SF& x) + { cl_SF q = fceiling(x); return cl_SF_fdiv_t(q,x-q); } + +// ftruncate2(x) liefert (ftruncate x), wo x ein SF ist. +inline const cl_SF_fdiv_t ftruncate2 (const cl_SF& x) + { cl_SF q = ftruncate(x); return cl_SF_fdiv_t(q,x-q); } + +// fround2(x) liefert (fround x), wo x ein SF ist. +inline const cl_SF_fdiv_t fround2 (const cl_SF& x) + { cl_SF q = fround(x); return cl_SF_fdiv_t(q,x-q); } + + +// Return type for rounding operators. +// x / y --> (q,r) with x = y*q+r. +struct cl_SF_div_t { + cl_I quotient; + cl_SF remainder; +// Constructor. + cl_SF_div_t () {} + cl_SF_div_t (const cl_I& q, const cl_SF& r) : quotient(q), remainder(r) {} +}; + +// floor2(x) liefert (floor x), wo x ein SF ist. +inline const cl_SF_div_t floor2 (const cl_SF& x) +{ + extern const cl_I cl_SF_to_I (const cl_SF& x); + cl_SF q = ffloor(x); + return cl_SF_div_t(cl_SF_to_I(q),x-q); +} +inline const cl_I floor1 (const cl_SF& x) +{ + extern const cl_I cl_SF_to_I (const cl_SF& x); + return cl_SF_to_I(ffloor(x)); +} + +// ceiling2(x) liefert (ceiling x), wo x ein SF ist. +inline const cl_SF_div_t ceiling2 (const cl_SF& x) +{ + extern const cl_I cl_SF_to_I (const cl_SF& x); + cl_SF q = fceiling(x); + return cl_SF_div_t(cl_SF_to_I(q),x-q); +} +inline const cl_I ceiling1 (const cl_SF& x) +{ + extern const cl_I cl_SF_to_I (const cl_SF& x); + return cl_SF_to_I(fceiling(x)); +} + +// truncate2(x) liefert (truncate x), wo x ein SF ist. +inline const cl_SF_div_t truncate2 (const cl_SF& x) +{ + extern const cl_I cl_SF_to_I (const cl_SF& x); + cl_SF q = ftruncate(x); + return cl_SF_div_t(cl_SF_to_I(q),x-q); +} +inline const cl_I truncate1 (const cl_SF& x) +{ + extern const cl_I cl_SF_to_I (const cl_SF& x); + return cl_SF_to_I(ftruncate(x)); +} + +// round2(x) liefert (round x), wo x ein SF ist. +inline const cl_SF_div_t round2 (const cl_SF& x) +{ + extern const cl_I cl_SF_to_I (const cl_SF& x); + cl_SF q = fround(x); + return cl_SF_div_t(cl_SF_to_I(q),x-q); +} +inline const cl_I round1 (const cl_SF& x) +{ + extern const cl_I cl_SF_to_I (const cl_SF& x); + return cl_SF_to_I(fround(x)); +} + +// floor2(x,y) liefert (floor x y). +extern const cl_SF_div_t floor2 (const cl_SF& x, const cl_SF& y); +inline const cl_I floor1 (const cl_SF& x, const cl_SF& y) { return floor1(x/y); } + +// ceiling2(x,y) liefert (ceiling x y). +extern const cl_SF_div_t ceiling2 (const cl_SF& x, const cl_SF& y); +inline const cl_I ceiling1 (const cl_SF& x, const cl_SF& y) { return ceiling1(x/y); } + +// truncate2(x,y) liefert (truncate x y). +extern const cl_SF_div_t truncate2 (const cl_SF& x, const cl_SF& y); +inline const cl_I truncate1 (const cl_SF& x, const cl_SF& y) { return truncate1(x/y); } + +// round2(x,y) liefert (round x y). +extern const cl_SF_div_t round2 (const cl_SF& x, const cl_SF& y); +inline const cl_I round1 (const cl_SF& x, const cl_SF& y) { return round1(x/y); } + + +// Return type for decode_float: +struct cl_decoded_sfloat { + cl_SF mantissa; + cl_I exponent; + cl_SF sign; +// Constructor. + cl_decoded_sfloat () {} + cl_decoded_sfloat (const cl_SF& m, const cl_I& e, const cl_SF& s) : mantissa(m), exponent(e), sign(s) {} +}; + +// decode_float(x) liefert zu einem Float x: (decode-float x). +// x = 0.0 liefert (0.0, 0, 1.0). +// x = (-1)^s * 2^e * m liefert ((-1)^0 * 2^0 * m, e als Integer, (-1)^s). +extern const cl_decoded_sfloat decode_float (const cl_SF& x); + +// float_exponent(x) liefert zu einem Float x: +// den Exponenten von (decode-float x). +// x = 0.0 liefert 0. +// x = (-1)^s * 2^e * m liefert e. +extern sintL float_exponent (const cl_SF& x); + +// float_radix(x) liefert (float-radix x), wo x ein Float ist. +inline sintL float_radix (const cl_SF& x) +{ + (void)x; // unused x + return 2; +} + +// float_sign(x) liefert (float-sign x), wo x ein Float ist. +extern const cl_SF float_sign (const cl_SF& x); + +// float_digits(x) liefert (float-digits x), wo x ein Float ist. +// < ergebnis: ein uintL >0 +extern uintL float_digits (const cl_SF& x); + +// float_precision(x) liefert (float-precision x), wo x ein Float ist. +// < ergebnis: ein uintL >=0 +extern uintL float_precision (const cl_SF& x); + + +// integer_decode_float(x) liefert zu einem Float x: (integer-decode-float x). +// x = 0.0 liefert (0, 0, 1). +// x = (-1)^s * 2^e * m bei Float-Precision p liefert +// (Mantisse 2^p * m als Integer, e-p als Integer, (-1)^s als Fixnum). +extern const cl_idecoded_float integer_decode_float (const cl_SF& x); + + +// scale_float(x,delta) liefert x*2^delta, wo x ein SF ist. +extern const cl_SF scale_float (const cl_SF& x, sintL delta); +extern const cl_SF scale_float (const cl_SF& x, const cl_I& delta); + + +// max(x,y) liefert (max x y), wo x und y Floats sind. +extern const cl_SF max (const cl_SF& x, const cl_SF& y); + +// min(x,y) liefert (min x y), wo x und y Floats sind. +extern const cl_SF min (const cl_SF& x, const cl_SF& y); + +// signum(x) liefert (signum x), wo x ein Float ist. +extern const cl_SF signum (const cl_SF& x); + + +// Konversion zu einem C "float". +extern float cl_float_approx (const cl_SF& x); + +// Konversion zu einem C "double". +extern double cl_double_approx (const cl_SF& x); + + +#ifdef WANT_OBFUSCATING_OPERATORS +// This could be optimized to use in-place operations. +inline cl_SF& operator+= (cl_SF& x, const cl_SF& y) { return x = x + y; } +inline cl_SF& operator++ /* prefix */ (cl_SF& x) { return x = plus1(x); } +inline void operator++ /* postfix */ (cl_SF& x, int dummy) { (void)dummy; x = plus1(x); } +inline cl_SF& operator-= (cl_SF& x, const cl_SF& y) { return x = x - y; } +inline cl_SF& operator-- /* prefix */ (cl_SF& x) { return x = minus1(x); } +inline void operator-- /* postfix */ (cl_SF& x, int dummy) { (void)dummy; x = minus1(x); } +inline cl_SF& operator*= (cl_SF& x, const cl_SF& y) { return x = x * y; } +inline cl_SF& operator/= (cl_SF& x, const cl_SF& y) { return x = x / y; } +#endif + + +// Runtime typing support. +extern cl_class cl_class_sfloat; +static const void* const cl_SF_classes_dummy[] = { &cl_SF_classes_dummy, + &cl_class_sfloat +}; + + +// Debugging support. +#ifdef CL_DEBUG +extern int cl_SF_debug_module; +static void* const cl_SF_debug_dummy[] = { &cl_SF_debug_dummy, + &cl_SF_debug_module +}; +#endif + + +#endif /* _CL_SFLOAT_H */ diff --git a/include/cl_sfloat_class.h b/include/cl_sfloat_class.h new file mode 100644 index 0000000..ffa2281 --- /dev/null +++ b/include/cl_sfloat_class.h @@ -0,0 +1,43 @@ +// Concrete class of short float numbers. + +#ifndef _CL_SFLOAT_CLASS_H +#define _CL_SFLOAT_CLASS_H + +#include "cl_number.h" +#include "cl_float_class.h" + + +class cl_SF : public cl_F { +public: +// Default constructor. + cl_SF (); +// Assignment operators. + cl_SF& operator= (const cl_SF&); +// Optimization of method pointer_p(). + cl_boolean pointer_p() const + { return cl_false; } +// Faster pointer_p() gives a faster copy constructor (but not destructor!!!). + cl_SF (const cl_SF& x); +// Other constructors. + cl_SF (const char *); +// Private constructor. + cl_SF (cl_private_thing); + cl_SF (struct cl_sfloat * /* NULL! */, cl_uint); +public: // Ability to place an object at a given address. + void* operator new (size_t size) { return cl_malloc_hook(size); } + void* operator new (size_t size, cl_SF* ptr) { (void)size; return ptr; } + void operator delete (void* ptr) { cl_free_hook(ptr); } +}; + +// Private constructors. +inline cl_SF::cl_SF (cl_private_thing ptr) : cl_F (ptr) {} +// The assignment operators: +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_SF, cl_SF) +// The default constructors. +inline cl_SF::cl_SF () + : cl_F ((cl_private_thing) cl_combine(cl_SF_tag,0)) {} +// The copy constructors. +CL_DEFINE_COPY_CONSTRUCTOR2(cl_SF,cl_F) + + +#endif /* _CL_SFLOAT_CLASS_H */ diff --git a/include/cl_sfloat_io.h b/include/cl_sfloat_io.h new file mode 100644 index 0000000..7b72cda --- /dev/null +++ b/include/cl_sfloat_io.h @@ -0,0 +1,27 @@ +// I/O of sfloats. + +#ifndef _CL_SFLOAT_IO_H +#define _CL_SFLOAT_IO_H + +#include "cl_number_io.h" +#include "cl_sfloat.h" + +inline cl_istream operator>> (cl_istream stream, cl_SF& result) +{ + extern cl_read_flags cl_SF_read_flags; + extern const cl_F read_float (cl_istream, const cl_read_flags&); + result = As(cl_SF)(read_float(stream,cl_SF_read_flags)); + return stream; +} + +// The following does strictly the same as the general `fprint' for floats. +// It is here only so that people don't need to include . +inline void fprint (cl_ostream stream, const cl_SF& x) +{ + extern void print_float (cl_ostream stream, const cl_print_flags& flags, const cl_F& z); + extern cl_print_flags cl_default_print_flags; + print_float(stream,cl_default_print_flags,x); +} +CL_DEFINE_PRINT_OPERATOR(cl_SF) + +#endif /* _CL_SFLOAT_IO_H */ diff --git a/include/cl_string.h b/include/cl_string.h new file mode 100644 index 0000000..ec177c5 --- /dev/null +++ b/include/cl_string.h @@ -0,0 +1,173 @@ +// Strings. + +#ifndef _CL_STRING_H +#define _CL_STRING_H + +#include "cl_object.h" +#include "cl_io.h" +#include "cl_abort.h" +#include + +// General, reference counted and garbage collected strings. +struct cl_heap_string : public cl_heap { +private: + unsigned long length; // length (in characters) + char data[1]; // the characters, plus a '\0' at the end + // Standard allocation disabled. + void* operator new (size_t size) { (void)size; cl_abort(); return (void*)1; } + // Standard deallocation disabled. + void operator delete (void* ptr) { (void)ptr; cl_abort(); } + // No default constructor. + cl_heap_string (); +private: +// Friend declarations. They are for the compiler. Just ignore them. + friend class cl_string; + friend cl_heap_string* cl_make_heap_string (unsigned long len); + friend cl_heap_string* cl_make_heap_string (const char * s); + friend cl_heap_string* cl_make_heap_string (const char * ptr, unsigned long len); + friend const cl_string operator+ (const cl_string& str1, const cl_string& str2); + friend const cl_string operator+ (const char* str1, const cl_string& str2); + friend const cl_string operator+ (const cl_string& str1, const char* str2); +}; + +struct cl_string : public cl_gcpointer { +public: + // Conversion to simple string. + // NOTE! The resulting pointer is valid only as long as the string + // is live, i.e. you must keep the string in a variable until you + // are done with the pointer to the characters. + const char * asciz () const + { + return &((cl_heap_string*)pointer)->data[0]; + } + // Return the length (number of characters). + unsigned long length () const + { + return ((cl_heap_string*)pointer)->length; + } + // Return a specific character. + char operator[] (unsigned long i) const + { + if (!(i < length())) cl_abort(); // Range check. + return ((cl_heap_string*)pointer)->data[i]; + } + // New ANSI C++ compilers also want the following. + char operator[] (unsigned int i) const + { return operator[]((unsigned long)i); } + char operator[] (long i) const + { return operator[]((unsigned long)i); } + char operator[] (int i) const + { return operator[]((unsigned long)i); } + // Constructors. + cl_string (); + cl_string (const cl_string&); + cl_string (const char * s); + cl_string (const char * ptr, unsigned long len); + // Assignment operators. + cl_string& operator= (const cl_string&); + cl_string& operator= (const char *); + // Private pointer manipulations. + operator cl_heap_string* () const; + cl_string (cl_heap_string* str) { pointer = str; } + cl_string (cl_private_thing p) : cl_gcpointer (p) {} +}; +CL_DEFINE_COPY_CONSTRUCTOR2(cl_string,cl_gcpointer) +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_string,cl_string) +inline cl_string::cl_string (const char * s) +{ + extern cl_heap_string* cl_make_heap_string (const char *); + pointer = cl_make_heap_string(s); +} +inline cl_string& cl_string::operator= (const char * s) +{ + extern cl_heap_string* cl_make_heap_string (const char *); + cl_heap_string* tmp = cl_make_heap_string(s); + cl_dec_refcount(*this); + pointer = tmp; + return *this; +} + +// Length. +inline unsigned long strlen (const cl_string& str) +{ + return str.length(); +} +// Conversion to `const char *'. +inline const char * asciz (const char * s) { return s; } +inline const char * asciz (const cl_string& s) { return s.asciz(); } + +// Comparison. +inline bool equal (const cl_string& str1, const cl_string& str2) +{ + return str1.length() == str2.length() + && !strcmp(str1.asciz(), str2.asciz()); +} +inline bool equal (const char * str1, const cl_string& str2) +{ + return !strcmp(str1, str2.asciz()); +} +inline bool equal (const cl_string& str1, const char * str2) +{ + return !strcmp(str1.asciz(), str2); +} + +// Private pointer manipulations. Never throw away a `struct cl_heap_string *'! +inline cl_string::operator cl_heap_string* () const +{ + cl_heap_string* hpointer = (cl_heap_string*)pointer; + cl_inc_refcount(*this); + return hpointer; +} +inline cl_string::cl_string () +{ + extern const cl_string cl_null_string; + pointer = (cl_heap_string*) cl_null_string; +} +CL_REQUIRE(cl_st_null) + +// Hash code. +extern unsigned long hashcode (const cl_string& str); + +// Output. +extern void fprint (cl_ostream stream, const cl_string& str); +CL_DEFINE_PRINT_OPERATOR(cl_string) + +// Input. + +#ifdef CL_IO_IOSTREAM + +// Reads a line. Up to delim. The delimiter character is not placed in the +// resulting string. The delimiter character is kept in the input stream. +// If EOF is encountered, the stream's eofbit is set. +extern const cl_string cl_fget (cl_istream stream, char delim = '\n'); + +// Reads a line. Up to delim. The delimiter character is not placed in the +// resulting string. The delimiter character is extracted from the input stream. +// If EOF is encountered, the stream's eofbit is set. +extern const cl_string cl_fgetline (cl_istream stream, char delim = '\n'); + +// Like above, but only up to n-1 characters. If n-1 characters were read +// before the delimiter character was seen, the stream's failbit is set. +extern const cl_string cl_fget (cl_istream stream, int n, char delim = '\n'); +extern const cl_string cl_fgetline (cl_istream stream, int n, char delim = '\n'); + +// Skips whitespace and then reads a non-whitespace string. +// If stream.width() is greater than 0, at most stream.width()-1 non-whitespace +// characters are read. When done, stream.width(0) is called. +// If EOF is encountered, the stream's eofbit is set. +extern cl_istream operator>> (cl_istream stream, cl_string& str); + +#endif + +// Runtime typing support. +extern cl_class cl_class_string; + +// Debugging support. +#ifdef CL_DEBUG +extern int cl_string_debug_module; +static void* const cl_string_debug_dummy[] = { &cl_string_debug_dummy, + &cl_string_debug_module +}; +#endif + +#endif /* _CL_STRING_H */ diff --git a/include/cl_symbol.h b/include/cl_symbol.h new file mode 100644 index 0000000..f4fd0a0 --- /dev/null +++ b/include/cl_symbol.h @@ -0,0 +1,50 @@ +// Symbols. + +#ifndef _CL_SYMBOL_H +#define _CL_SYMBOL_H + +#include "cl_string.h" + +// Symbols are just strings, uniquified through a global hash table. + +#if (defined(__alpha__) && !defined(__GNUC__)) +struct hashuniq; +#endif + +struct cl_symbol : public cl_rcpointer { +public: + // Conversion to string. + operator cl_string () const; + // Constructors. + cl_symbol (const cl_string&); // create or lookup a symbol from its name + cl_symbol (const cl_symbol&); + // Assignment operators. + cl_symbol& operator= (const cl_symbol&); + // Private pointer manipulations. + cl_symbol (cl_private_thing p) : cl_rcpointer (p) {} +public: /* ugh */ + // Create a new symbol given its name. + cl_symbol (struct hashuniq * null, const cl_string& s); +}; +CL_DEFINE_COPY_CONSTRUCTOR2(cl_symbol,cl_rcpointer) +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_symbol,cl_symbol) + +// A symbol points to a string, so to convert cl_symbol -> cl_string, we just +// take the pointer and put it into a cl_string. +inline cl_symbol::operator cl_string () const +{ + return cl_string(_as_cl_private_thing()); +} + +// Comparison. +inline bool equal (const cl_symbol& s1, const cl_symbol& s2) +{ + return (s1.pointer == s2.pointer); +} + +// Hash code. +extern unsigned long hashcode (const cl_symbol& s); + +CL_REQUIRE(cl_symbol) + +#endif /* _CL_SYMBOL_H */ diff --git a/include/cl_timing.h b/include/cl_timing.h new file mode 100644 index 0000000..6a7f72e --- /dev/null +++ b/include/cl_timing.h @@ -0,0 +1,74 @@ +// Timing tools. + +#ifndef _CL_TIMING_H +#define _CL_TIMING_H + +#include "cl_config.h" +#include "cl_intparam.h" +#include "cl_types.h" + +#include "cl_io.h" + +struct cl_timespec { + uintL tv_sec; // seconds since 1970-01-01 + sintL tv_nsec; // nanoseconds, >= 0, < 1000000000 + // Constructors. + cl_timespec () {} + cl_timespec (uintL sec, sintL nsec) + : tv_sec (sec), tv_nsec (nsec) {} +}; + +struct cl_time_duration { + uintL tv_sec; // seconds + uintL tv_nsec; // nanoseconds + // Constructors. + cl_time_duration () {} + cl_time_duration (uintL sec) + : tv_sec (sec), tv_nsec (0) {} + cl_time_duration (uintL sec, uintL nsec) + : tv_sec (sec), tv_nsec (nsec) {} +}; + +struct cl_time_consumption { + cl_time_duration realtime; // elapsed time + cl_time_duration usertime; // system's notion of user time/run time +}; + +extern const cl_time_duration operator- (const cl_timespec&, const cl_timespec&); +extern const cl_timespec operator+ (const cl_timespec&, const cl_time_duration&); +extern const cl_timespec operator- (const cl_timespec&, const cl_time_duration&); +extern const cl_time_duration operator+ (const cl_time_duration&, const cl_time_duration&); +extern const cl_time_duration operator- (const cl_time_duration&, const cl_time_duration&); + +extern const cl_timespec cl_current_time (); +extern const cl_time_consumption cl_current_time_consumption (); + +// Report a time consumption. +// (Should better be a virtual member function of `cl_time_consumption'). +extern void cl_timing_report (cl_ostream, const cl_time_consumption&); + +struct cl_timing { + // Constructor, starts the time interval. + cl_timing (cl_time_consumption& accumulator); + cl_timing (cl_ostream destination = cl_stderr); + cl_timing (const char *, cl_ostream destination = cl_stderr); + // Destructor, closes the time interval and does a report. + ~cl_timing (); +//private: + cl_time_consumption tmp; + void (*report_fn) (const cl_timing&); + void* report_destination; + const char * comment; +}; + +// Macro for timing. +// Usage: +// { CL_TIMING; computation(); } +// or { CL_TIMING(accumulator); computation(); } +// or { CL_TIMING(cl_stdout); computation(); } +// The timing interval starts immediately and ends at the closing brace. +#define CL_TIMING CL_TIMING1(__LINE__) +#define CL_TIMING1(line) CL_TIMING2(line) +#define CL_TIMING2(line) cl_timing cl_timing_dummy_##line + +#endif /* _CL_TIMING_H */ diff --git a/include/cl_types.h b/include/cl_types.h new file mode 100644 index 0000000..5e402e7 --- /dev/null +++ b/include/cl_types.h @@ -0,0 +1,151 @@ +// Basic type definitions + +#ifndef _CL_TYPES_H +#define _CL_TYPES_H + +// CPU and other +#include "cl_config.h" + +// char_bitsize, short_bitsize, long_bitsize, long_long_bitsize +#include "cl_intparam.h" + +// Elementary arithmetic types of given width: + // 8 bits + #if (char_bitsize==8) + typedef signed char sint8; + typedef unsigned char uint8; + #else + #error "No 8 bit integer type?" + #endif + // 16 bits + #if (short_bitsize==16) + typedef short sint16; + typedef unsigned short uint16; + #else + #error "No 16 bit integer type?" + #endif + // 32 bits + #if (long_bitsize==32) + typedef long sint32; + typedef unsigned long uint32; + #elif (int_bitsize==32) + typedef int sint32; + typedef unsigned int uint32; + #else + #error "No 32 bit integer type?" + #endif + // 64 bits + #if (long_bitsize==64) + typedef long sint64; + typedef unsigned long uint64; + #undef HAVE_LONGLONG + #define HAVE_LONGLONG + #elif defined(HAVE_LONGLONG) + #if defined(long_long_bitsize) && (long_long_bitsize==64) + typedef long long sint64; + typedef unsigned long long uint64; + #else // unusable type + #undef HAVE_LONGLONG + #endif + #endif + #if defined(HAVE_LONGLONG) && (defined(__alpha__) || defined(__mips64__) || defined(__sparc64__)) + // 64 bit registers in hardware + #define HAVE_FAST_LONGLONG + #endif +// Synonyms + #define intBsize 8 + typedef sint8 sintB; + typedef uint8 uintB; + #define intWsize 16 + typedef sint16 sintW; + typedef uint16 uintW; + #define intLsize 32 + typedef sint32 sintL; + typedef uint32 uintL; + #ifdef HAVE_LONGLONG + #define intQsize 64 + typedef sint64 sintQ; + typedef uint64 uintQ; + #endif + +// Boolean type. +#if 1 + typedef enum { cl_false = 0, cl_true = 1 } + cl_boolean; +#else + typedef bool cl_boolean; + #define cl_false 0 + #define cl_true 1 +#endif + +// Type for three values (0, +1, -1). + typedef int cl_signean; + #define signean_plus 1 + #define signean_null 0 + #define signean_minus -1 + +// Integer type used for counters. + #if (defined(HAVE_FAST_LONGLONG) && defined(__alpha__)) + #define intCsize long_bitsize + typedef long sintC; + typedef unsigned long uintC; + #else + #define intCsize int_bitsize + typedef int sintC; + typedef unsigned int uintC; + #endif + +// Integer type as large as a pointer. +// Assumption: sizeof(long) == sizeof(void*) + #define intPsize long_bitsize + typedef long sintP; + typedef unsigned long uintP; + +// Numbers in the heap are stored as "digit" sequences. +// A digit is an unsigned int with intDsize bits. +// intDsize should be 8 or 16 or 32 or 64. + #if (defined(HAVE_FAST_LONGLONG) && defined(__alpha__)) + #define intDsize 64 + #define intDDsize 128 // = 2*intDsize + #define log2_intDsize 6 // = log2(intDsize) + #else + #define intDsize 32 + #define intDDsize 64 // = 2*intDsize + #define log2_intDsize 5 // = log2(intDsize) + #endif + #if (intDsize==8) + typedef sint8 sintD; + typedef uint8 uintD; + #endif + #if (intDsize==16) + typedef sint16 sintD; + typedef uint16 uintD; + #endif + #if (intDsize==32) + typedef sint32 sintD; + typedef uint32 uintD; + #endif + #if (intDsize==64) + typedef sint64 sintD; + typedef uint64 uintD; + #endif +// HAVE_DD means that there are unsigned ints with 2*intDsize bits. + #if (intDDsize <= (defined(HAVE_FAST_LONGLONG) ? 64 : 32)) + #define HAVE_DD 1 + #if (intDDsize==16) + typedef sint16 sintDD; + typedef uint16 uintDD; + #endif + #if (intDDsize==32) + typedef sint32 sintDD; + typedef uint32 uintDD; + #endif + #if (intDDsize==64) + typedef sint64 sintDD; + typedef uint64 uintDD; + #endif + #else + #define HAVE_DD 0 + #endif + +#endif /* _CL_TYPES_H */ diff --git a/include/cl_univpoly.h b/include/cl_univpoly.h new file mode 100644 index 0000000..6010a57 --- /dev/null +++ b/include/cl_univpoly.h @@ -0,0 +1,713 @@ +// Univariate Polynomials. + +#ifndef _CL_UNIVPOLY_H +#define _CL_UNIVPOLY_H + +#include "cl_object.h" +#include "cl_ring.h" +#include "cl_malloc.h" +#include "cl_proplist.h" +#include "cl_symbol.h" +#include "cl_V.h" +#include "cl_io.h" + +// To protect against mixing elements of different polynomial rings, every +// polynomial carries its ring in itself. + +class cl_heap_univpoly_ring; + +class cl_univpoly_ring : public cl_ring { +public: + // Default constructor. + cl_univpoly_ring (); + // Constructor. Takes a cl_heap_univpoly_ring*, increments its refcount. + cl_univpoly_ring (cl_heap_univpoly_ring* r); + // Private constructor. Doesn't increment the refcount. + cl_univpoly_ring (cl_private_thing); + // Copy constructor. + cl_univpoly_ring (const cl_univpoly_ring&); + // Assignment operator. + cl_univpoly_ring& operator= (const cl_univpoly_ring&); + // Automatic dereferencing. + cl_heap_univpoly_ring* operator-> () const + { return (cl_heap_univpoly_ring*)heappointer; } +}; +// Copy constructor and assignment operator. +CL_DEFINE_COPY_CONSTRUCTOR2(cl_univpoly_ring,cl_ring) +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_univpoly_ring,cl_univpoly_ring) + +// Normal constructor for `cl_univpoly_ring'. +inline cl_univpoly_ring::cl_univpoly_ring (cl_heap_univpoly_ring* r) + : cl_ring ((cl_private_thing) (cl_inc_pointer_refcount((cl_heap*)r), r)) {} +// Private constructor for `cl_univpoly_ring'. +inline cl_univpoly_ring::cl_univpoly_ring (cl_private_thing p) + : cl_ring (p) {} + +// Operations on univariate polynomial rings. + +inline bool operator== (const cl_univpoly_ring& R1, const cl_univpoly_ring& R2) +{ return (R1.pointer == R2.pointer); } +inline bool operator!= (const cl_univpoly_ring& R1, const cl_univpoly_ring& R2) +{ return (R1.pointer != R2.pointer); } +inline bool operator== (const cl_univpoly_ring& R1, cl_heap_univpoly_ring* R2) +{ return (R1.pointer == R2); } +inline bool operator!= (const cl_univpoly_ring& R1, cl_heap_univpoly_ring* R2) +{ return (R1.pointer != R2); } + +// Representation of a univariate polynomial. + +class _cl_UP /* cf. _cl_ring_element */ { +public: + cl_gcpointer rep; // vector of coefficients, a cl_V_any + // Default constructor. + _cl_UP (); +public: /* ugh */ + // Constructor. + _cl_UP (const cl_heap_univpoly_ring* R, const cl_V_any& r) : rep (as_cl_private_thing(r)) { (void)R; } + _cl_UP (const cl_univpoly_ring& R, const cl_V_any& r) : rep (as_cl_private_thing(r)) { (void)R; } +public: + // Conversion. + CL_DEFINE_CONVERTER(_cl_ring_element) +public: // Ability to place an object at a given address. + void* operator new (size_t size) { return cl_malloc_hook(size); } + void* operator new (size_t size, _cl_UP* ptr) { (void)size; return ptr; } + void operator delete (void* ptr) { cl_free_hook(ptr); } +}; + +class cl_UP /* cf. cl_ring_element */ : public _cl_UP { +protected: + cl_univpoly_ring _ring; // polynomial ring (references the base ring) +public: + const cl_univpoly_ring& ring () const { return _ring; } +private: + // Default constructor. + cl_UP (); +public: /* ugh */ + // Constructor. + cl_UP (const cl_univpoly_ring& R, const cl_V_any& r) + : _cl_UP (R,r), _ring (R) {} + cl_UP (const cl_univpoly_ring& R, const _cl_UP& r) + : _cl_UP (r), _ring (R) {} +public: + // Conversion. + CL_DEFINE_CONVERTER(cl_ring_element) + // Destructive modification. + void set_coeff (uintL index, const cl_ring_element& y); + void finalize(); + // Evaluation. + const cl_ring_element operator() (const cl_ring_element& y) const; + // Debugging output. + void debug_print () const; +public: // Ability to place an object at a given address. + void* operator new (size_t size) { return cl_malloc_hook(size); } + void* operator new (size_t size, cl_UP* ptr) { (void)size; return ptr; } + void operator delete (void* ptr) { cl_free_hook(ptr); } +}; + + +// Ring operations. + +struct _cl_univpoly_setops /* cf. _cl_ring_setops */ { + // print + void (* fprint) (cl_heap_univpoly_ring* R, cl_ostream stream, const _cl_UP& x); + // equality + // (Be careful: This is not well-defined for polynomials with + // floating-point coefficients.) + cl_boolean (* equal) (cl_heap_univpoly_ring* R, const _cl_UP& x, const _cl_UP& y); +}; +struct _cl_univpoly_addops /* cf. _cl_ring_addops */ { + // 0 + const _cl_UP (* zero) (cl_heap_univpoly_ring* R); + cl_boolean (* zerop) (cl_heap_univpoly_ring* R, const _cl_UP& x); + // x+y + const _cl_UP (* plus) (cl_heap_univpoly_ring* R, const _cl_UP& x, const _cl_UP& y); + // x-y + const _cl_UP (* minus) (cl_heap_univpoly_ring* R, const _cl_UP& x, const _cl_UP& y); + // -x + const _cl_UP (* uminus) (cl_heap_univpoly_ring* R, const _cl_UP& x); +}; +struct _cl_univpoly_mulops /* cf. _cl_ring_mulops */ { + // 1 + const _cl_UP (* one) (cl_heap_univpoly_ring* R); + // canonical homomorphism + const _cl_UP (* canonhom) (cl_heap_univpoly_ring* R, const cl_I& x); + // x*y + const _cl_UP (* mul) (cl_heap_univpoly_ring* R, const _cl_UP& x, const _cl_UP& y); + // x^2 + const _cl_UP (* square) (cl_heap_univpoly_ring* R, const _cl_UP& x); + // x^y, y Integer >0 + const _cl_UP (* expt_pos) (cl_heap_univpoly_ring* R, const _cl_UP& x, const cl_I& y); +}; +struct _cl_univpoly_modulops { + // scalar multiplication x*y + const _cl_UP (* scalmul) (cl_heap_univpoly_ring* R, const cl_ring_element& x, const _cl_UP& y); +}; +struct _cl_univpoly_polyops { + // degree + sintL (* degree) (cl_heap_univpoly_ring* R, const _cl_UP& x); + // monomial + const _cl_UP (* monomial) (cl_heap_univpoly_ring* R, const cl_ring_element& x, uintL e); + // coefficient (0 if index>degree) + const cl_ring_element (* coeff) (cl_heap_univpoly_ring* R, const _cl_UP& x, uintL index); + // create new polynomial, bounded degree + const _cl_UP (* create) (cl_heap_univpoly_ring* R, sintL deg); + // set coefficient in new polynomial + void (* set_coeff) (cl_heap_univpoly_ring* R, _cl_UP& x, uintL index, const cl_ring_element& y); + // finalize polynomial + void (* finalize) (cl_heap_univpoly_ring* R, _cl_UP& x); + // evaluate, substitute an element of R + const cl_ring_element (* eval) (cl_heap_univpoly_ring* R, const _cl_UP& x, const cl_ring_element& y); +}; +#if defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 8) // workaround two g++-2.7.0 bugs + #define cl_univpoly_setops _cl_univpoly_setops + #define cl_univpoly_addops _cl_univpoly_addops + #define cl_univpoly_mulops _cl_univpoly_mulops + #define cl_univpoly_modulops _cl_univpoly_modulops + #define cl_univpoly_polyops _cl_univpoly_polyops +#else + typedef const _cl_univpoly_setops cl_univpoly_setops; + typedef const _cl_univpoly_addops cl_univpoly_addops; + typedef const _cl_univpoly_mulops cl_univpoly_mulops; + typedef const _cl_univpoly_modulops cl_univpoly_modulops; + typedef const _cl_univpoly_polyops cl_univpoly_polyops; +#endif + +// Representation of a univariate polynomial ring. + +class cl_heap_univpoly_ring /* cf. cl_heap_ring */ : public cl_heap { + SUBCLASS_cl_heap_ring() +private: + cl_property_list properties; +protected: + cl_univpoly_setops* setops; + cl_univpoly_addops* addops; + cl_univpoly_mulops* mulops; + cl_univpoly_modulops* modulops; + cl_univpoly_polyops* polyops; +protected: + cl_ring _basering; // the coefficients are elements of this ring +public: + const cl_ring& basering () const { return _basering; } +public: + // Low-level operations. + void _fprint (cl_ostream stream, const _cl_UP& x) + { setops->fprint(this,stream,x); } + cl_boolean _equal (const _cl_UP& x, const _cl_UP& y) + { return setops->equal(this,x,y); } + const _cl_UP _zero () + { return addops->zero(this); } + cl_boolean _zerop (const _cl_UP& x) + { return addops->zerop(this,x); } + const _cl_UP _plus (const _cl_UP& x, const _cl_UP& y) + { return addops->plus(this,x,y); } + const _cl_UP _minus (const _cl_UP& x, const _cl_UP& y) + { return addops->minus(this,x,y); } + const _cl_UP _uminus (const _cl_UP& x) + { return addops->uminus(this,x); } + const _cl_UP _one () + { return mulops->one(this); } + const _cl_UP _canonhom (const cl_I& x) + { return mulops->canonhom(this,x); } + const _cl_UP _mul (const _cl_UP& x, const _cl_UP& y) + { return mulops->mul(this,x,y); } + const _cl_UP _square (const _cl_UP& x) + { return mulops->square(this,x); } + const _cl_UP _expt_pos (const _cl_UP& x, const cl_I& y) + { return mulops->expt_pos(this,x,y); } + const _cl_UP _scalmul (const cl_ring_element& x, const _cl_UP& y) + { return modulops->scalmul(this,x,y); } + sintL _degree (const _cl_UP& x) + { return polyops->degree(this,x); } + const _cl_UP _monomial (const cl_ring_element& x, uintL e) + { return polyops->monomial(this,x,e); } + const cl_ring_element _coeff (const _cl_UP& x, uintL index) + { return polyops->coeff(this,x,index); } + const _cl_UP _create (sintL deg) + { return polyops->create(this,deg); } + void _set_coeff (_cl_UP& x, uintL index, const cl_ring_element& y) + { polyops->set_coeff(this,x,index,y); } + void _finalize (_cl_UP& x) + { polyops->finalize(this,x); } + const cl_ring_element _eval (const _cl_UP& x, const cl_ring_element& y) + { return polyops->eval(this,x,y); } + // High-level operations. + void fprint (cl_ostream stream, const cl_UP& x) + { + if (!(x.ring() == this)) cl_abort(); + _fprint(stream,x); + } + cl_boolean equal (const cl_UP& x, const cl_UP& y) + { + if (!(x.ring() == this)) cl_abort(); + if (!(y.ring() == this)) cl_abort(); + return _equal(x,y); + } + const cl_UP zero () + { + return cl_UP(this,_zero()); + } + cl_boolean zerop (const cl_UP& x) + { + if (!(x.ring() == this)) cl_abort(); + return _zerop(x); + } + const cl_UP plus (const cl_UP& x, const cl_UP& y) + { + if (!(x.ring() == this)) cl_abort(); + if (!(y.ring() == this)) cl_abort(); + return cl_UP(this,_plus(x,y)); + } + const cl_UP minus (const cl_UP& x, const cl_UP& y) + { + if (!(x.ring() == this)) cl_abort(); + if (!(y.ring() == this)) cl_abort(); + return cl_UP(this,_minus(x,y)); + } + const cl_UP uminus (const cl_UP& x) + { + if (!(x.ring() == this)) cl_abort(); + return cl_UP(this,_uminus(x)); + } + const cl_UP one () + { + return cl_UP(this,_one()); + } + const cl_UP canonhom (const cl_I& x) + { + return cl_UP(this,_canonhom(x)); + } + const cl_UP mul (const cl_UP& x, const cl_UP& y) + { + if (!(x.ring() == this)) cl_abort(); + if (!(y.ring() == this)) cl_abort(); + return cl_UP(this,_mul(x,y)); + } + const cl_UP square (const cl_UP& x) + { + if (!(x.ring() == this)) cl_abort(); + return cl_UP(this,_square(x)); + } + const cl_UP expt_pos (const cl_UP& x, const cl_I& y) + { + if (!(x.ring() == this)) cl_abort(); + return cl_UP(this,_expt_pos(x,y)); + } + const cl_UP scalmul (const cl_ring_element& x, const cl_UP& y) + { + if (!(y.ring() == this)) cl_abort(); + return cl_UP(this,_scalmul(x,y)); + } + sintL degree (const cl_UP& x) + { + if (!(x.ring() == this)) cl_abort(); + return _degree(x); + } + const cl_UP monomial (const cl_ring_element& x, uintL e) + { + return cl_UP(this,_monomial(x,e)); + } + const cl_ring_element coeff (const cl_UP& x, uintL index) + { + if (!(x.ring() == this)) cl_abort(); + return _coeff(x,index); + } + const cl_UP create (sintL deg) + { + return cl_UP(this,_create(deg)); + } + void set_coeff (cl_UP& x, uintL index, const cl_ring_element& y) + { + if (!(x.ring() == this)) cl_abort(); + _set_coeff(x,index,y); + } + void finalize (cl_UP& x) + { + if (!(x.ring() == this)) cl_abort(); + _finalize(x); + } + const cl_ring_element eval (const cl_UP& x, const cl_ring_element& y) + { + if (!(x.ring() == this)) cl_abort(); + return _eval(x,y); + } + // Property operations. + cl_property* get_property (const cl_symbol& key) + { return properties.get_property(key); } + void add_property (cl_property* new_property) + { properties.add_property(new_property); } +// Constructor. + cl_heap_univpoly_ring (const cl_ring& r, cl_univpoly_setops*, cl_univpoly_addops*, cl_univpoly_mulops*, cl_univpoly_modulops*, cl_univpoly_polyops*); +// This class is intented to be subclassable, hence needs a virtual destructor. + virtual ~cl_heap_univpoly_ring () {} +private: + virtual void dummy (); +}; +#define SUBCLASS_cl_heap_univpoly_ring() \ + SUBCLASS_cl_heap_ring() + + +// Lookup or create the "standard" univariate polynomial ring over a ring r. +extern const cl_univpoly_ring cl_find_univpoly_ring (const cl_ring& r); +//CL_REQUIRE(cl_UP_unnamed) + +// Lookup or create a univariate polynomial ring with a named variable over r. +extern const cl_univpoly_ring cl_find_univpoly_ring (const cl_ring& r, const cl_symbol& varname); +//CL_REQUIRE(cl_UP_named) + +CL_REQUIRE(cl_UP) + +// Runtime typing support. +extern cl_class cl_class_univpoly_ring; + + +// Operations on polynomials. + +// Output. +inline void fprint (cl_ostream stream, const cl_UP& x) + { x.ring()->fprint(stream,x); } +CL_DEFINE_PRINT_OPERATOR(cl_UP) + +// Add. +inline const cl_UP operator+ (const cl_UP& x, const cl_UP& y) + { return x.ring()->plus(x,y); } + +// Negate. +inline const cl_UP operator- (const cl_UP& x) + { return x.ring()->uminus(x); } + +// Subtract. +inline const cl_UP operator- (const cl_UP& x, const cl_UP& y) + { return x.ring()->minus(x,y); } + +// Equality. +inline bool operator== (const cl_UP& x, const cl_UP& y) + { return x.ring()->equal(x,y); } +inline bool operator!= (const cl_UP& x, const cl_UP& y) + { return !x.ring()->equal(x,y); } + +// Compare against 0. +inline cl_boolean zerop (const cl_UP& x) + { return x.ring()->zerop(x); } + +// Multiply. +inline const cl_UP operator* (const cl_UP& x, const cl_UP& y) + { return x.ring()->mul(x,y); } + +// Squaring. +inline const cl_UP square (const cl_UP& x) + { return x.ring()->square(x); } + +// Exponentiation x^y, where y > 0. +inline const cl_UP expt_pos (const cl_UP& x, const cl_I& y) + { return x.ring()->expt_pos(x,y); } + +// Scalar multiplication. +#if 0 // less efficient +inline const cl_UP operator* (const cl_I& x, const cl_UP& y) + { return y.ring()->mul(y.ring()->canonhom(x),y); } +inline const cl_UP operator* (const cl_UP& x, const cl_I& y) + { return x.ring()->mul(x.ring()->canonhom(y),x); } +#endif +inline const cl_UP operator* (const cl_I& x, const cl_UP& y) + { return y.ring()->scalmul(y.ring()->basering()->canonhom(x),y); } +inline const cl_UP operator* (const cl_UP& x, const cl_I& y) + { return x.ring()->scalmul(x.ring()->basering()->canonhom(y),x); } +inline const cl_UP operator* (const cl_ring_element& x, const cl_UP& y) + { return y.ring()->scalmul(x,y); } +inline const cl_UP operator* (const cl_UP& x, const cl_ring_element& y) + { return x.ring()->scalmul(y,x); } + +// Degree. +inline sintL degree (const cl_UP& x) + { return x.ring()->degree(x); } + +// Coefficient. +inline const cl_ring_element coeff (const cl_UP& x, uintL index) + { return x.ring()->coeff(x,index); } + +// Destructive modification. +inline void set_coeff (cl_UP& x, uintL index, const cl_ring_element& y) + { x.ring()->set_coeff(x,index,y); } +inline void finalize (cl_UP& x) + { x.ring()->finalize(x); } +inline void cl_UP::set_coeff (uintL index, const cl_ring_element& y) + { ring()->set_coeff(*this,index,y); } +inline void cl_UP::finalize () + { ring()->finalize(*this); } + +// Evaluation. (No extension of the base ring allowed here for now.) +inline const cl_ring_element cl_UP::operator() (const cl_ring_element& y) const +{ + return ring()->eval(*this,y); +} + +// Derivative. +extern const cl_UP deriv (const cl_UP& x); + + +// Ring of uninitialized elements. +// Any operation results in a run-time error. + +extern const cl_univpoly_ring cl_no_univpoly_ring; +extern cl_class cl_class_no_univpoly_ring; +CL_REQUIRE(cl_UP_no_ring) + +inline cl_univpoly_ring::cl_univpoly_ring () + : cl_ring (as_cl_private_thing(cl_no_univpoly_ring)) {} +inline _cl_UP::_cl_UP () + : rep ((cl_private_thing) cl_combine(cl_FN_tag,0)) {} +inline cl_UP::cl_UP () + : _cl_UP (), _ring () {} + + +// Debugging support. +#ifdef CL_DEBUG +extern int cl_UP_debug_module; +static void* const cl_UP_debug_dummy[] = { &cl_UP_debug_dummy, + &cl_UP_debug_module +}; +#endif + + +#endif /* _CL_UNIVPOLY_H */ + + +// Templates for univariate polynomials of complex/real/rational/integers. + +#ifdef notyet +// Unfortunately, this is not usable now, because of gcc-2.7 bugs: +// - A template inline function is not inline in the first function that +// uses it. +// - Argument matching bug: User-defined conversions are not tried (or +// tried with too low priority) for template functions w.r.t. normal +// functions. For example, a call expt_pos(cl_UP_specialized,int) +// is compiled as expt_pos(const cl_UP&, const cl_I&) instead of +// expt_pos(const cl_UP_specialized&, const cl_I&). +// It will, however, be usable when gcc-2.8 is released. + +#if defined(_CL_UNIVPOLY_COMPLEX_H) || defined(_CL_UNIVPOLY_REAL_H) || defined(_CL_UNIVPOLY_RATIONAL_H) || defined(_CL_UNIVPOLY_INTEGER_H) +#ifndef _CL_UNIVPOLY_AUX_H + +// Normal univariate polynomials with stricter static typing: +// `class T' instead of `cl_ring_element'. + +template class cl_univpoly_specialized_ring; +template class cl_UP_specialized; +template class cl_heap_univpoly_specialized_ring; + +template +class cl_univpoly_specialized_ring : public cl_univpoly_ring { +public: + // Default constructor. + cl_univpoly_specialized_ring () : cl_univpoly_ring () {} + // Copy constructor. + cl_univpoly_specialized_ring (const cl_univpoly_specialized_ring&); + // Assignment operator. + cl_univpoly_specialized_ring& operator= (const cl_univpoly_specialized_ring&); + // Automatic dereferencing. + cl_heap_univpoly_specialized_ring* operator-> () const + { return (cl_heap_univpoly_specialized_ring*)heappointer; } +}; +// Copy constructor and assignment operator. +template +_CL_DEFINE_COPY_CONSTRUCTOR2(cl_univpoly_specialized_ring,cl_univpoly_specialized_ring,cl_univpoly_ring) +template +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_univpoly_specialized_ring,cl_univpoly_specialized_ring) + +template +class cl_UP_specialized : public cl_UP { +public: + const cl_univpoly_specialized_ring& ring () const { return The(cl_univpoly_specialized_ring)(_ring); } + // Conversion. + CL_DEFINE_CONVERTER(cl_ring_element) + // Destructive modification. + void set_coeff (uintL index, const T& y); + void finalize(); + // Evaluation. + const T operator() (const T& y) const; +public: // Ability to place an object at a given address. + void* operator new (size_t size) { return cl_malloc_hook(size); } + void* operator new (size_t size, cl_UP_specialized* ptr) { (void)size; return ptr; } + void operator delete (void* ptr) { cl_free_hook(ptr); } +}; + +template +class cl_heap_univpoly_specialized_ring : public cl_heap_univpoly_ring { + SUBCLASS_cl_heap_univpoly_ring() + // High-level operations. + void fprint (cl_ostream stream, const cl_UP_specialized& x) + { + cl_heap_univpoly_ring::fprint(stream,x); + } + cl_boolean equal (const cl_UP_specialized& x, const cl_UP_specialized& y) + { + return cl_heap_univpoly_ring::equal(x,y); + } + const cl_UP_specialized zero () + { + return The2(cl_UP_specialized)(cl_heap_univpoly_ring::zero()); + } + cl_boolean zerop (const cl_UP_specialized& x) + { + return cl_heap_univpoly_ring::zerop(x); + } + const cl_UP_specialized plus (const cl_UP_specialized& x, const cl_UP_specialized& y) + { + return The2(cl_UP_specialized)(cl_heap_univpoly_ring::plus(x,y)); + } + const cl_UP_specialized minus (const cl_UP_specialized& x, const cl_UP_specialized& y) + { + return The2(cl_UP_specialized)(cl_heap_univpoly_ring::minus(x,y)); + } + const cl_UP_specialized uminus (const cl_UP_specialized& x) + { + return The2(cl_UP_specialized)(cl_heap_univpoly_ring::uminus(x)); + } + const cl_UP_specialized one () + { + return The2(cl_UP_specialized)(cl_heap_univpoly_ring::one()); + } + const cl_UP_specialized canonhom (const cl_I& x) + { + return The2(cl_UP_specialized)(cl_heap_univpoly_ring::canonhom(x)); + } + const cl_UP_specialized mul (const cl_UP_specialized& x, const cl_UP_specialized& y) + { + return The2(cl_UP_specialized)(cl_heap_univpoly_ring::mul(x,y)); + } + const cl_UP_specialized square (const cl_UP_specialized& x) + { + return The2(cl_UP_specialized)(cl_heap_univpoly_ring::square(x)); + } + const cl_UP_specialized expt_pos (const cl_UP_specialized& x, const cl_I& y) + { + return The2(cl_UP_specialized)(cl_heap_univpoly_ring::expt_pos(x,y)); + } + const cl_UP_specialized scalmul (const T& x, const cl_UP_specialized& y) + { + return The2(cl_UP_specialized)(cl_heap_univpoly_ring::scalmul(x,y)); + } + sintL degree (const cl_UP_specialized& x) + { + return cl_heap_univpoly_ring::degree(x); + } + const cl_UP_specialized monomial (const T& x, uintL e) + { + return The2(cl_UP_specialized)(cl_heap_univpoly_ring::monomial(cl_ring_element(cl_C_ring??,x),e)); + } + const T coeff (const cl_UP_specialized& x, uintL index) + { + return The(T)(cl_heap_univpoly_ring::coeff(x,index)); + } + const cl_UP_specialized create (sintL deg) + { + return The2(cl_UP_specialized)(cl_heap_univpoly_ring::create(deg)); + } + void set_coeff (cl_UP_specialized& x, uintL index, const T& y) + { + cl_heap_univpoly_ring::set_coeff(x,index,cl_ring_element(cl_C_ring??,y)); + } + void finalize (cl_UP_specialized& x) + { + cl_heap_univpoly_ring::finalize(x); + } + const T eval (const cl_UP_specialized& x, const T& y) + { + return The(T)(cl_heap_univpoly_ring::eval(x,cl_ring_element(cl_C_ring??,y))); + } +private: + // No need for any constructors. + cl_heap_univpoly_specialized_ring (); +}; + +// Lookup of polynomial rings. +template +inline const cl_univpoly_specialized_ring cl_find_univpoly_ring (const cl_specialized_number_ring& r) +{ return The(cl_univpoly_specialized_ring) (cl_find_univpoly_ring((const cl_ring&)r)); } +template +inline const cl_univpoly_specialized_ring cl_find_univpoly_ring (const cl_specialized_number_ring& r, const cl_symbol& varname) +{ return The(cl_univpoly_specialized_ring) (cl_find_univpoly_ring((const cl_ring&)r,varname)); } + +// Operations on polynomials. + +// Add. +template +inline const cl_UP_specialized operator+ (const cl_UP_specialized& x, const cl_UP_specialized& y) + { return x.ring()->plus(x,y); } + +// Negate. +template +inline const cl_UP_specialized operator- (const cl_UP_specialized& x) + { return x.ring()->uminus(x); } + +// Subtract. +template +inline const cl_UP_specialized operator- (const cl_UP_specialized& x, const cl_UP_specialized& y) + { return x.ring()->minus(x,y); } + +// Multiply. +template +inline const cl_UP_specialized operator* (const cl_UP_specialized& x, const cl_UP_specialized& y) + { return x.ring()->mul(x,y); } + +// Squaring. +template +inline const cl_UP_specialized square (const cl_UP_specialized& x) + { return x.ring()->square(x); } + +// Exponentiation x^y, where y > 0. +template +inline const cl_UP_specialized expt_pos (const cl_UP_specialized& x, const cl_I& y) + { return x.ring()->expt_pos(x,y); } + +// Scalar multiplication. +// Need more discrimination on T ?? +template +inline const cl_UP_specialized operator* (const cl_I& x, const cl_UP_specialized& y) + { return y.ring()->mul(y.ring()->canonhom(x),y); } +template +inline const cl_UP_specialized operator* (const cl_UP_specialized& x, const cl_I& y) + { return x.ring()->mul(x.ring()->canonhom(y),x); } +template +inline const cl_UP_specialized operator* (const T& x, const cl_UP_specialized& y) + { return y.ring()->scalmul(x,y); } +template +inline const cl_UP_specialized operator* (const cl_UP_specialized& x, const T& y) + { return x.ring()->scalmul(y,x); } + +// Coefficient. +template +inline const T coeff (const cl_UP_specialized& x, uintL index) + { return x.ring()->coeff(x,index); } + +// Destructive modification. +template +inline void set_coeff (cl_UP_specialized& x, uintL index, const T& y) + { x.ring()->set_coeff(x,index,y); } +template +inline void finalize (cl_UP_specialized& x) + { x.ring()->finalize(x); } +template +inline void cl_UP_specialized::set_coeff (uintL index, const T& y) + { ring()->set_coeff(*this,index,y); } +template +inline void cl_UP_specialized::finalize () + { ring()->finalize(*this); } + +// Evaluation. (No extension of the base ring allowed here for now.) +template +inline const T cl_UP_specialized::operator() (const T& y) const +{ + return ring()->eval(*this,y); +} + +// Derivative. +template +inline const cl_UP_specialized deriv (const cl_UP_specialized& x) + { return The(cl_UP_specialized)(deriv((const cl_UP&)x)); } + + +#endif /* _CL_UNIVPOLY_AUX_H */ +#endif + +#endif diff --git a/include/cl_univpoly_complex.h b/include/cl_univpoly_complex.h new file mode 100644 index 0000000..c87243e --- /dev/null +++ b/include/cl_univpoly_complex.h @@ -0,0 +1,222 @@ +// Univariate Polynomials over the complex numbers. + +#ifndef _CL_UNIVPOLY_COMPLEX_H +#define _CL_UNIVPOLY_COMPLEX_H + +#include "cl_ring.h" +#include "cl_univpoly.h" +#include "cl_number.h" +#include "cl_complex_class.h" +#include "cl_integer_class.h" +#include "cl_complex_ring.h" + +// Normal univariate polynomials with stricter static typing: +// `cl_N' instead of `cl_ring_element'. + +#ifdef notyet + +typedef cl_UP_specialized cl_UP_N; +typedef cl_univpoly_specialized_ring cl_univpoly_complex_ring; +//typedef cl_heap_univpoly_specialized_ring cl_heap_univpoly_complex_ring; + +#else + +class cl_heap_univpoly_complex_ring; + +class cl_univpoly_complex_ring : public cl_univpoly_ring { +public: + // Default constructor. + cl_univpoly_complex_ring () : cl_univpoly_ring () {} + // Copy constructor. + cl_univpoly_complex_ring (const cl_univpoly_complex_ring&); + // Assignment operator. + cl_univpoly_complex_ring& operator= (const cl_univpoly_complex_ring&); + // Automatic dereferencing. + cl_heap_univpoly_complex_ring* operator-> () const + { return (cl_heap_univpoly_complex_ring*)heappointer; } +}; +// Copy constructor and assignment operator. +CL_DEFINE_COPY_CONSTRUCTOR2(cl_univpoly_complex_ring,cl_univpoly_ring) +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_univpoly_complex_ring,cl_univpoly_complex_ring) + +class cl_UP_N : public cl_UP { +public: + const cl_univpoly_complex_ring& ring () const { return The(cl_univpoly_complex_ring)(_ring); } + // Conversion. + CL_DEFINE_CONVERTER(cl_ring_element) + // Destructive modification. + void set_coeff (uintL index, const cl_N& y); + void finalize(); + // Evaluation. + const cl_N operator() (const cl_N& y) const; +public: // Ability to place an object at a given address. + void* operator new (size_t size) { return cl_malloc_hook(size); } + void* operator new (size_t size, cl_UP_N* ptr) { (void)size; return ptr; } + void operator delete (void* ptr) { cl_free_hook(ptr); } +}; + +class cl_heap_univpoly_complex_ring : public cl_heap_univpoly_ring { + SUBCLASS_cl_heap_univpoly_ring() + // High-level operations. + void fprint (cl_ostream stream, const cl_UP_N& x) + { + cl_heap_univpoly_ring::fprint(stream,x); + } + cl_boolean equal (const cl_UP_N& x, const cl_UP_N& y) + { + return cl_heap_univpoly_ring::equal(x,y); + } + const cl_UP_N zero () + { + return The2(cl_UP_N)(cl_heap_univpoly_ring::zero()); + } + cl_boolean zerop (const cl_UP_N& x) + { + return cl_heap_univpoly_ring::zerop(x); + } + const cl_UP_N plus (const cl_UP_N& x, const cl_UP_N& y) + { + return The2(cl_UP_N)(cl_heap_univpoly_ring::plus(x,y)); + } + const cl_UP_N minus (const cl_UP_N& x, const cl_UP_N& y) + { + return The2(cl_UP_N)(cl_heap_univpoly_ring::minus(x,y)); + } + const cl_UP_N uminus (const cl_UP_N& x) + { + return The2(cl_UP_N)(cl_heap_univpoly_ring::uminus(x)); + } + const cl_UP_N one () + { + return The2(cl_UP_N)(cl_heap_univpoly_ring::one()); + } + const cl_UP_N canonhom (const cl_I& x) + { + return The2(cl_UP_N)(cl_heap_univpoly_ring::canonhom(x)); + } + const cl_UP_N mul (const cl_UP_N& x, const cl_UP_N& y) + { + return The2(cl_UP_N)(cl_heap_univpoly_ring::mul(x,y)); + } + const cl_UP_N square (const cl_UP_N& x) + { + return The2(cl_UP_N)(cl_heap_univpoly_ring::square(x)); + } + const cl_UP_N expt_pos (const cl_UP_N& x, const cl_I& y) + { + return The2(cl_UP_N)(cl_heap_univpoly_ring::expt_pos(x,y)); + } + const cl_UP_N scalmul (const cl_N& x, const cl_UP_N& y) + { + return The2(cl_UP_N)(cl_heap_univpoly_ring::scalmul(cl_ring_element(cl_C_ring,x),y)); + } + sintL degree (const cl_UP_N& x) + { + return cl_heap_univpoly_ring::degree(x); + } + const cl_UP_N monomial (const cl_N& x, uintL e) + { + return The2(cl_UP_N)(cl_heap_univpoly_ring::monomial(cl_ring_element(cl_C_ring,x),e)); + } + const cl_N coeff (const cl_UP_N& x, uintL index) + { + return The(cl_N)(cl_heap_univpoly_ring::coeff(x,index)); + } + const cl_UP_N create (sintL deg) + { + return The2(cl_UP_N)(cl_heap_univpoly_ring::create(deg)); + } + void set_coeff (cl_UP_N& x, uintL index, const cl_N& y) + { + cl_heap_univpoly_ring::set_coeff(x,index,cl_ring_element(cl_C_ring,y)); + } + void finalize (cl_UP_N& x) + { + cl_heap_univpoly_ring::finalize(x); + } + const cl_N eval (const cl_UP_N& x, const cl_N& y) + { + return The(cl_N)(cl_heap_univpoly_ring::eval(x,cl_ring_element(cl_C_ring,y))); + } +private: + // No need for any constructors. + cl_heap_univpoly_complex_ring (); +}; + +// Lookup of polynomial rings. +inline const cl_univpoly_complex_ring cl_find_univpoly_ring (const cl_complex_ring& r) +{ return The(cl_univpoly_complex_ring) (cl_find_univpoly_ring((const cl_ring&)r)); } +inline const cl_univpoly_complex_ring cl_find_univpoly_ring (const cl_complex_ring& r, const cl_symbol& varname) +{ return The(cl_univpoly_complex_ring) (cl_find_univpoly_ring((const cl_ring&)r,varname)); } + +// Operations on polynomials. + +// Add. +inline const cl_UP_N operator+ (const cl_UP_N& x, const cl_UP_N& y) + { return x.ring()->plus(x,y); } + +// Negate. +inline const cl_UP_N operator- (const cl_UP_N& x) + { return x.ring()->uminus(x); } + +// Subtract. +inline const cl_UP_N operator- (const cl_UP_N& x, const cl_UP_N& y) + { return x.ring()->minus(x,y); } + +// Multiply. +inline const cl_UP_N operator* (const cl_UP_N& x, const cl_UP_N& y) + { return x.ring()->mul(x,y); } + +// Squaring. +inline const cl_UP_N square (const cl_UP_N& x) + { return x.ring()->square(x); } + +// Exponentiation x^y, where y > 0. +inline const cl_UP_N expt_pos (const cl_UP_N& x, const cl_I& y) + { return x.ring()->expt_pos(x,y); } + +// Scalar multiplication. +#if 0 // less efficient +inline const cl_UP_N operator* (const cl_I& x, const cl_UP_N& y) + { return y.ring()->mul(y.ring()->canonhom(x),y); } +inline const cl_UP_N operator* (const cl_UP_N& x, const cl_I& y) + { return x.ring()->mul(x.ring()->canonhom(y),x); } +#endif +inline const cl_UP_N operator* (const cl_I& x, const cl_UP_N& y) + { return y.ring()->scalmul(x,y); } +inline const cl_UP_N operator* (const cl_UP_N& x, const cl_I& y) + { return x.ring()->scalmul(y,x); } +inline const cl_UP_N operator* (const cl_N& x, const cl_UP_N& y) + { return y.ring()->scalmul(x,y); } +inline const cl_UP_N operator* (const cl_UP_N& x, const cl_N& y) + { return x.ring()->scalmul(y,x); } + +// Coefficient. +inline const cl_N coeff (const cl_UP_N& x, uintL index) + { return x.ring()->coeff(x,index); } + +// Destructive modification. +inline void set_coeff (cl_UP_N& x, uintL index, const cl_N& y) + { x.ring()->set_coeff(x,index,y); } +inline void finalize (cl_UP_N& x) + { x.ring()->finalize(x); } +inline void cl_UP_N::set_coeff (uintL index, const cl_N& y) + { ring()->set_coeff(*this,index,y); } +inline void cl_UP_N::finalize () + { ring()->finalize(*this); } + +// Evaluation. (No extension of the base ring allowed here for now.) +inline const cl_N cl_UP_N::operator() (const cl_N& y) const +{ + return ring()->eval(*this,y); +} + +// Derivative. +inline const cl_UP_N deriv (const cl_UP_N& x) + { return The2(cl_UP_N)(deriv((const cl_UP&)x)); } + +#endif + +CL_REQUIRE(cl_C_ring) + +#endif /* _CL_UNIVPOLY_COMPLEX_H */ diff --git a/include/cl_univpoly_integer.h b/include/cl_univpoly_integer.h new file mode 100644 index 0000000..96cea07 --- /dev/null +++ b/include/cl_univpoly_integer.h @@ -0,0 +1,227 @@ +// Univariate Polynomials over the integer numbers. + +#ifndef _CL_UNIVPOLY_INTEGER_H +#define _CL_UNIVPOLY_INTEGER_H + +#include "cl_ring.h" +#include "cl_univpoly.h" +#include "cl_number.h" +#include "cl_integer_class.h" +#include "cl_integer_ring.h" + +// Normal univariate polynomials with stricter static typing: +// `cl_I' instead of `cl_ring_element'. + +#ifdef notyet + +typedef cl_UP_specialized cl_UP_I; +typedef cl_univpoly_specialized_ring cl_univpoly_integer_ring; +//typedef cl_heap_univpoly_specialized_ring cl_heap_univpoly_integer_ring; + +#else + +class cl_heap_univpoly_integer_ring; + +class cl_univpoly_integer_ring : public cl_univpoly_ring { +public: + // Default constructor. + cl_univpoly_integer_ring () : cl_univpoly_ring () {} + // Copy constructor. + cl_univpoly_integer_ring (const cl_univpoly_integer_ring&); + // Assignment operator. + cl_univpoly_integer_ring& operator= (const cl_univpoly_integer_ring&); + // Automatic dereferencing. + cl_heap_univpoly_integer_ring* operator-> () const + { return (cl_heap_univpoly_integer_ring*)heappointer; } +}; +// Copy constructor and assignment operator. +CL_DEFINE_COPY_CONSTRUCTOR2(cl_univpoly_integer_ring,cl_univpoly_ring) +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_univpoly_integer_ring,cl_univpoly_integer_ring) + +class cl_UP_I : public cl_UP { +public: + const cl_univpoly_integer_ring& ring () const { return The(cl_univpoly_integer_ring)(_ring); } + // Conversion. + CL_DEFINE_CONVERTER(cl_ring_element) + // Destructive modification. + void set_coeff (uintL index, const cl_I& y); + void finalize(); + // Evaluation. + const cl_I operator() (const cl_I& y) const; +public: // Ability to place an object at a given address. + void* operator new (size_t size) { return cl_malloc_hook(size); } + void* operator new (size_t size, cl_UP_I* ptr) { (void)size; return ptr; } + void operator delete (void* ptr) { cl_free_hook(ptr); } +}; + +class cl_heap_univpoly_integer_ring : public cl_heap_univpoly_ring { + SUBCLASS_cl_heap_univpoly_ring() + // High-level operations. + void fprint (cl_ostream stream, const cl_UP_I& x) + { + cl_heap_univpoly_ring::fprint(stream,x); + } + cl_boolean equal (const cl_UP_I& x, const cl_UP_I& y) + { + return cl_heap_univpoly_ring::equal(x,y); + } + const cl_UP_I zero () + { + return The2(cl_UP_I)(cl_heap_univpoly_ring::zero()); + } + cl_boolean zerop (const cl_UP_I& x) + { + return cl_heap_univpoly_ring::zerop(x); + } + const cl_UP_I plus (const cl_UP_I& x, const cl_UP_I& y) + { + return The2(cl_UP_I)(cl_heap_univpoly_ring::plus(x,y)); + } + const cl_UP_I minus (const cl_UP_I& x, const cl_UP_I& y) + { + return The2(cl_UP_I)(cl_heap_univpoly_ring::minus(x,y)); + } + const cl_UP_I uminus (const cl_UP_I& x) + { + return The2(cl_UP_I)(cl_heap_univpoly_ring::uminus(x)); + } + const cl_UP_I one () + { + return The2(cl_UP_I)(cl_heap_univpoly_ring::one()); + } + const cl_UP_I canonhom (const cl_I& x) + { + return The2(cl_UP_I)(cl_heap_univpoly_ring::canonhom(x)); + } + const cl_UP_I mul (const cl_UP_I& x, const cl_UP_I& y) + { + return The2(cl_UP_I)(cl_heap_univpoly_ring::mul(x,y)); + } + const cl_UP_I square (const cl_UP_I& x) + { + return The2(cl_UP_I)(cl_heap_univpoly_ring::square(x)); + } + const cl_UP_I expt_pos (const cl_UP_I& x, const cl_I& y) + { + return The2(cl_UP_I)(cl_heap_univpoly_ring::expt_pos(x,y)); + } + const cl_UP_I scalmul (const cl_I& x, const cl_UP_I& y) + { + return The2(cl_UP_I)(cl_heap_univpoly_ring::scalmul(cl_ring_element(cl_I_ring,x),y)); + } + sintL degree (const cl_UP_I& x) + { + return cl_heap_univpoly_ring::degree(x); + } + const cl_UP_I monomial (const cl_I& x, uintL e) + { + return The2(cl_UP_I)(cl_heap_univpoly_ring::monomial(cl_ring_element(cl_I_ring,x),e)); + } + const cl_I coeff (const cl_UP_I& x, uintL index) + { + return The(cl_I)(cl_heap_univpoly_ring::coeff(x,index)); + } + const cl_UP_I create (sintL deg) + { + return The2(cl_UP_I)(cl_heap_univpoly_ring::create(deg)); + } + void set_coeff (cl_UP_I& x, uintL index, const cl_I& y) + { + cl_heap_univpoly_ring::set_coeff(x,index,cl_ring_element(cl_I_ring,y)); + } + void finalize (cl_UP_I& x) + { + cl_heap_univpoly_ring::finalize(x); + } + const cl_I eval (const cl_UP_I& x, const cl_I& y) + { + return The(cl_I)(cl_heap_univpoly_ring::eval(x,cl_ring_element(cl_I_ring,y))); + } +private: + // No need for any constructors. + cl_heap_univpoly_integer_ring (); +}; + +// Lookup of polynomial rings. +inline const cl_univpoly_integer_ring cl_find_univpoly_ring (const cl_integer_ring& r) +{ return The(cl_univpoly_integer_ring) (cl_find_univpoly_ring((const cl_ring&)r)); } +inline const cl_univpoly_integer_ring cl_find_univpoly_ring (const cl_integer_ring& r, const cl_symbol& varname) +{ return The(cl_univpoly_integer_ring) (cl_find_univpoly_ring((const cl_ring&)r,varname)); } + +// Operations on polynomials. + +// Add. +inline const cl_UP_I operator+ (const cl_UP_I& x, const cl_UP_I& y) + { return x.ring()->plus(x,y); } + +// Negate. +inline const cl_UP_I operator- (const cl_UP_I& x) + { return x.ring()->uminus(x); } + +// Subtract. +inline const cl_UP_I operator- (const cl_UP_I& x, const cl_UP_I& y) + { return x.ring()->minus(x,y); } + +// Multiply. +inline const cl_UP_I operator* (const cl_UP_I& x, const cl_UP_I& y) + { return x.ring()->mul(x,y); } + +// Squaring. +inline const cl_UP_I square (const cl_UP_I& x) + { return x.ring()->square(x); } + +// Exponentiation x^y, where y > 0. +inline const cl_UP_I expt_pos (const cl_UP_I& x, const cl_I& y) + { return x.ring()->expt_pos(x,y); } + +// Scalar multiplication. +#if 0 // less efficient +inline const cl_UP_I operator* (const cl_I& x, const cl_UP_I& y) + { return y.ring()->mul(y.ring()->canonhom(x),y); } +inline const cl_UP_I operator* (const cl_UP_I& x, const cl_I& y) + { return x.ring()->mul(x.ring()->canonhom(y),x); } +#endif +inline const cl_UP_I operator* (const cl_I& x, const cl_UP_I& y) + { return y.ring()->scalmul(x,y); } +inline const cl_UP_I operator* (const cl_UP_I& x, const cl_I& y) + { return x.ring()->scalmul(y,x); } + +// Coefficient. +inline const cl_I coeff (const cl_UP_I& x, uintL index) + { return x.ring()->coeff(x,index); } + +// Destructive modification. +inline void set_coeff (cl_UP_I& x, uintL index, const cl_I& y) + { x.ring()->set_coeff(x,index,y); } +inline void finalize (cl_UP_I& x) + { x.ring()->finalize(x); } +inline void cl_UP_I::set_coeff (uintL index, const cl_I& y) + { ring()->set_coeff(*this,index,y); } +inline void cl_UP_I::finalize () + { ring()->finalize(*this); } + +// Evaluation. (No extension of the base ring allowed here for now.) +inline const cl_I cl_UP_I::operator() (const cl_I& y) const +{ + return ring()->eval(*this,y); +} + +// Derivative. +inline const cl_UP_I deriv (const cl_UP_I& x) + { return The2(cl_UP_I)(deriv((const cl_UP&)x)); } + +#endif + +CL_REQUIRE(cl_I_ring) + + +// Returns the n-th Tchebychev polynomial (n >= 0). +extern const cl_UP_I cl_tschebychev (sintL n); + +// Returns the n-th Hermite polynomial (n >= 0). +extern const cl_UP_I cl_hermite (sintL n); + +// Returns the n-th Laguerre polynomial (n >= 0). +extern const cl_UP_I cl_laguerre (sintL n); + +#endif /* _CL_UNIVPOLY_INTEGER_H */ diff --git a/include/cl_univpoly_modint.h b/include/cl_univpoly_modint.h new file mode 100644 index 0000000..5b008ed --- /dev/null +++ b/include/cl_univpoly_modint.h @@ -0,0 +1,209 @@ +// Univariate Polynomials over modular integers. + +#ifndef _CL_UNIVPOLY_MODINT_H +#define _CL_UNIVPOLY_MoDINT_H + +#include "cl_ring.h" +#include "cl_univpoly.h" +#include "cl_modinteger.h" +#include "cl_integer_class.h" + +// Normal univariate polynomials with stricter static typing: +// `cl_MI' instead of `cl_ring_element'. + +class cl_heap_univpoly_modint_ring; + +class cl_univpoly_modint_ring : public cl_univpoly_ring { +public: + // Default constructor. + cl_univpoly_modint_ring () : cl_univpoly_ring () {} + // Copy constructor. + cl_univpoly_modint_ring (const cl_univpoly_modint_ring&); + // Assignment operator. + cl_univpoly_modint_ring& operator= (const cl_univpoly_modint_ring&); + // Automatic dereferencing. + cl_heap_univpoly_modint_ring* operator-> () const + { return (cl_heap_univpoly_modint_ring*)heappointer; } +}; +// Copy constructor and assignment operator. +CL_DEFINE_COPY_CONSTRUCTOR2(cl_univpoly_modint_ring,cl_univpoly_ring) +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_univpoly_modint_ring,cl_univpoly_modint_ring) + +class cl_UP_MI : public cl_UP { +public: + const cl_univpoly_modint_ring& ring () const { return The(cl_univpoly_modint_ring)(_ring); } + // Conversion. + CL_DEFINE_CONVERTER(cl_ring_element) + // Destructive modification. + void set_coeff (uintL index, const cl_MI& y); + void finalize(); + // Evaluation. + const cl_MI operator() (const cl_MI& y) const; +public: // Ability to place an object at a given address. + void* operator new (size_t size) { return cl_malloc_hook(size); } + void* operator new (size_t size, cl_UP_MI* ptr) { (void)size; return ptr; } + void operator delete (void* ptr) { cl_free_hook(ptr); } +}; + +class cl_heap_univpoly_modint_ring : public cl_heap_univpoly_ring { + SUBCLASS_cl_heap_univpoly_ring() + const cl_modint_ring& basering () const { return The(cl_modint_ring)(_basering); } + // High-level operations. + void fprint (cl_ostream stream, const cl_UP_MI& x) + { + cl_heap_univpoly_ring::fprint(stream,x); + } + cl_boolean equal (const cl_UP_MI& x, const cl_UP_MI& y) + { + return cl_heap_univpoly_ring::equal(x,y); + } + const cl_UP_MI zero () + { + return The2(cl_UP_MI)(cl_heap_univpoly_ring::zero()); + } + cl_boolean zerop (const cl_UP_MI& x) + { + return cl_heap_univpoly_ring::zerop(x); + } + const cl_UP_MI plus (const cl_UP_MI& x, const cl_UP_MI& y) + { + return The2(cl_UP_MI)(cl_heap_univpoly_ring::plus(x,y)); + } + const cl_UP_MI minus (const cl_UP_MI& x, const cl_UP_MI& y) + { + return The2(cl_UP_MI)(cl_heap_univpoly_ring::minus(x,y)); + } + const cl_UP_MI uminus (const cl_UP_MI& x) + { + return The2(cl_UP_MI)(cl_heap_univpoly_ring::uminus(x)); + } + const cl_UP_MI one () + { + return The2(cl_UP_MI)(cl_heap_univpoly_ring::one()); + } + const cl_UP_MI canonhom (const cl_I& x) + { + return The2(cl_UP_MI)(cl_heap_univpoly_ring::canonhom(x)); + } + const cl_UP_MI mul (const cl_UP_MI& x, const cl_UP_MI& y) + { + return The2(cl_UP_MI)(cl_heap_univpoly_ring::mul(x,y)); + } + const cl_UP_MI square (const cl_UP_MI& x) + { + return The2(cl_UP_MI)(cl_heap_univpoly_ring::square(x)); + } + const cl_UP_MI expt_pos (const cl_UP_MI& x, const cl_I& y) + { + return The2(cl_UP_MI)(cl_heap_univpoly_ring::expt_pos(x,y)); + } + const cl_UP_MI scalmul (const cl_MI& x, const cl_UP_MI& y) + { + return The2(cl_UP_MI)(cl_heap_univpoly_ring::scalmul(x,y)); + } + sintL degree (const cl_UP_MI& x) + { + return cl_heap_univpoly_ring::degree(x); + } + const cl_UP_MI monomial (const cl_MI& x, uintL e) + { + return The2(cl_UP_MI)(cl_heap_univpoly_ring::monomial(x,e)); + } + const cl_MI coeff (const cl_UP_MI& x, uintL index) + { + return The2(cl_MI)(cl_heap_univpoly_ring::coeff(x,index)); + } + const cl_UP_MI create (sintL deg) + { + return The2(cl_UP_MI)(cl_heap_univpoly_ring::create(deg)); + } + void set_coeff (cl_UP_MI& x, uintL index, const cl_MI& y) + { + cl_heap_univpoly_ring::set_coeff(x,index,y); + } + void finalize (cl_UP_MI& x) + { + cl_heap_univpoly_ring::finalize(x); + } + const cl_MI eval (const cl_UP_MI& x, const cl_MI& y) + { + return The2(cl_MI)(cl_heap_univpoly_ring::eval(x,y)); + } +private: + // No need for any constructors. + cl_heap_univpoly_modint_ring (); +}; + +// Lookup of polynomial rings. +inline const cl_univpoly_modint_ring cl_find_univpoly_ring (const cl_modint_ring& r) +{ return The(cl_univpoly_modint_ring) (cl_find_univpoly_ring((const cl_ring&)r)); } +inline const cl_univpoly_modint_ring cl_find_univpoly_ring (const cl_modint_ring& r, const cl_symbol& varname) +{ return The(cl_univpoly_modint_ring) (cl_find_univpoly_ring((const cl_ring&)r,varname)); } + +// Operations on polynomials. + +// Add. +inline const cl_UP_MI operator+ (const cl_UP_MI& x, const cl_UP_MI& y) + { return x.ring()->plus(x,y); } + +// Negate. +inline const cl_UP_MI operator- (const cl_UP_MI& x) + { return x.ring()->uminus(x); } + +// Subtract. +inline const cl_UP_MI operator- (const cl_UP_MI& x, const cl_UP_MI& y) + { return x.ring()->minus(x,y); } + +// Multiply. +inline const cl_UP_MI operator* (const cl_UP_MI& x, const cl_UP_MI& y) + { return x.ring()->mul(x,y); } + +// Squaring. +inline const cl_UP_MI square (const cl_UP_MI& x) + { return x.ring()->square(x); } + +// Exponentiation x^y, where y > 0. +inline const cl_UP_MI expt_pos (const cl_UP_MI& x, const cl_I& y) + { return x.ring()->expt_pos(x,y); } + +// Scalar multiplication. +#if 0 // less efficient +inline const cl_UP_MI operator* (const cl_I& x, const cl_UP_MI& y) + { return y.ring()->mul(y.ring()->canonhom(x),y); } +inline const cl_UP_MI operator* (const cl_UP_MI& x, const cl_I& y) + { return x.ring()->mul(x.ring()->canonhom(y),x); } +#endif +inline const cl_UP_MI operator* (const cl_I& x, const cl_UP_MI& y) + { return y.ring()->scalmul(y.ring()->basering()->canonhom(x),y); } +inline const cl_UP_MI operator* (const cl_UP_MI& x, const cl_I& y) + { return x.ring()->scalmul(x.ring()->basering()->canonhom(y),x); } +inline const cl_UP_MI operator* (const cl_MI& x, const cl_UP_MI& y) + { return y.ring()->scalmul(x,y); } +inline const cl_UP_MI operator* (const cl_UP_MI& x, const cl_MI& y) + { return x.ring()->scalmul(y,x); } + +// Coefficient. +inline const cl_MI coeff (const cl_UP_MI& x, uintL index) + { return x.ring()->coeff(x,index); } + +// Destructive modification. +inline void set_coeff (cl_UP_MI& x, uintL index, const cl_MI& y) + { x.ring()->set_coeff(x,index,y); } +inline void finalize (cl_UP_MI& x) + { x.ring()->finalize(x); } +inline void cl_UP_MI::set_coeff (uintL index, const cl_MI& y) + { ring()->set_coeff(*this,index,y); } +inline void cl_UP_MI::finalize () + { ring()->finalize(*this); } + +// Evaluation. (No extension of the base ring allowed here for now.) +inline const cl_MI cl_UP_MI::operator() (const cl_MI& y) const +{ + return ring()->eval(*this,y); +} + +// Derivative. +inline const cl_UP_MI deriv (const cl_UP_MI& x) + { return The2(cl_UP_MI)(deriv((const cl_UP&)x)); } + +#endif /* _CL_UNIVPOLY_MODINT_H */ diff --git a/include/cl_univpoly_rational.h b/include/cl_univpoly_rational.h new file mode 100644 index 0000000..9a87e04 --- /dev/null +++ b/include/cl_univpoly_rational.h @@ -0,0 +1,226 @@ +// Univariate Polynomials over the rational numbers. + +#ifndef _CL_UNIVPOLY_RATIONAL_H +#define _CL_UNIVPOLY_RATIONAL_H + +#include "cl_ring.h" +#include "cl_univpoly.h" +#include "cl_number.h" +#include "cl_rational_class.h" +#include "cl_integer_class.h" +#include "cl_rational_ring.h" + +// Normal univariate polynomials with stricter static typing: +// `cl_RA' instead of `cl_ring_element'. + +#ifdef notyet + +typedef cl_UP_specialized cl_UP_RA; +typedef cl_univpoly_specialized_ring cl_univpoly_rational_ring; +//typedef cl_heap_univpoly_specialized_ring cl_heap_univpoly_rational_ring; + +#else + +class cl_heap_univpoly_rational_ring; + +class cl_univpoly_rational_ring : public cl_univpoly_ring { +public: + // Default constructor. + cl_univpoly_rational_ring () : cl_univpoly_ring () {} + // Copy constructor. + cl_univpoly_rational_ring (const cl_univpoly_rational_ring&); + // Assignment operator. + cl_univpoly_rational_ring& operator= (const cl_univpoly_rational_ring&); + // Automatic dereferencing. + cl_heap_univpoly_rational_ring* operator-> () const + { return (cl_heap_univpoly_rational_ring*)heappointer; } +}; +// Copy constructor and assignment operator. +CL_DEFINE_COPY_CONSTRUCTOR2(cl_univpoly_rational_ring,cl_univpoly_ring) +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_univpoly_rational_ring,cl_univpoly_rational_ring) + +class cl_UP_RA : public cl_UP { +public: + const cl_univpoly_rational_ring& ring () const { return The(cl_univpoly_rational_ring)(_ring); } + // Conversion. + CL_DEFINE_CONVERTER(cl_ring_element) + // Destructive modification. + void set_coeff (uintL index, const cl_RA& y); + void finalize(); + // Evaluation. + const cl_RA operator() (const cl_RA& y) const; +public: // Ability to place an object at a given address. + void* operator new (size_t size) { return cl_malloc_hook(size); } + void* operator new (size_t size, cl_UP_RA* ptr) { (void)size; return ptr; } + void operator delete (void* ptr) { cl_free_hook(ptr); } +}; + +class cl_heap_univpoly_rational_ring : public cl_heap_univpoly_ring { + SUBCLASS_cl_heap_univpoly_ring() + // High-level operations. + void fprint (cl_ostream stream, const cl_UP_RA& x) + { + cl_heap_univpoly_ring::fprint(stream,x); + } + cl_boolean equal (const cl_UP_RA& x, const cl_UP_RA& y) + { + return cl_heap_univpoly_ring::equal(x,y); + } + const cl_UP_RA zero () + { + return The2(cl_UP_RA)(cl_heap_univpoly_ring::zero()); + } + cl_boolean zerop (const cl_UP_RA& x) + { + return cl_heap_univpoly_ring::zerop(x); + } + const cl_UP_RA plus (const cl_UP_RA& x, const cl_UP_RA& y) + { + return The2(cl_UP_RA)(cl_heap_univpoly_ring::plus(x,y)); + } + const cl_UP_RA minus (const cl_UP_RA& x, const cl_UP_RA& y) + { + return The2(cl_UP_RA)(cl_heap_univpoly_ring::minus(x,y)); + } + const cl_UP_RA uminus (const cl_UP_RA& x) + { + return The2(cl_UP_RA)(cl_heap_univpoly_ring::uminus(x)); + } + const cl_UP_RA one () + { + return The2(cl_UP_RA)(cl_heap_univpoly_ring::one()); + } + const cl_UP_RA canonhom (const cl_I& x) + { + return The2(cl_UP_RA)(cl_heap_univpoly_ring::canonhom(x)); + } + const cl_UP_RA mul (const cl_UP_RA& x, const cl_UP_RA& y) + { + return The2(cl_UP_RA)(cl_heap_univpoly_ring::mul(x,y)); + } + const cl_UP_RA square (const cl_UP_RA& x) + { + return The2(cl_UP_RA)(cl_heap_univpoly_ring::square(x)); + } + const cl_UP_RA expt_pos (const cl_UP_RA& x, const cl_I& y) + { + return The2(cl_UP_RA)(cl_heap_univpoly_ring::expt_pos(x,y)); + } + const cl_UP_RA scalmul (const cl_RA& x, const cl_UP_RA& y) + { + return The2(cl_UP_RA)(cl_heap_univpoly_ring::scalmul(cl_ring_element(cl_RA_ring,x),y)); + } + sintL degree (const cl_UP_RA& x) + { + return cl_heap_univpoly_ring::degree(x); + } + const cl_UP_RA monomial (const cl_RA& x, uintL e) + { + return The2(cl_UP_RA)(cl_heap_univpoly_ring::monomial(cl_ring_element(cl_RA_ring,x),e)); + } + const cl_RA coeff (const cl_UP_RA& x, uintL index) + { + return The(cl_RA)(cl_heap_univpoly_ring::coeff(x,index)); + } + const cl_UP_RA create (sintL deg) + { + return The2(cl_UP_RA)(cl_heap_univpoly_ring::create(deg)); + } + void set_coeff (cl_UP_RA& x, uintL index, const cl_RA& y) + { + cl_heap_univpoly_ring::set_coeff(x,index,cl_ring_element(cl_RA_ring,y)); + } + void finalize (cl_UP_RA& x) + { + cl_heap_univpoly_ring::finalize(x); + } + const cl_RA eval (const cl_UP_RA& x, const cl_RA& y) + { + return The(cl_RA)(cl_heap_univpoly_ring::eval(x,cl_ring_element(cl_RA_ring,y))); + } +private: + // No need for any constructors. + cl_heap_univpoly_rational_ring (); +}; + +// Lookup of polynomial rings. +inline const cl_univpoly_rational_ring cl_find_univpoly_ring (const cl_rational_ring& r) +{ return The(cl_univpoly_rational_ring) (cl_find_univpoly_ring((const cl_ring&)r)); } +inline const cl_univpoly_rational_ring cl_find_univpoly_ring (const cl_rational_ring& r, const cl_symbol& varname) +{ return The(cl_univpoly_rational_ring) (cl_find_univpoly_ring((const cl_ring&)r,varname)); } + +// Operations on polynomials. + +// Add. +inline const cl_UP_RA operator+ (const cl_UP_RA& x, const cl_UP_RA& y) + { return x.ring()->plus(x,y); } + +// Negate. +inline const cl_UP_RA operator- (const cl_UP_RA& x) + { return x.ring()->uminus(x); } + +// Subtract. +inline const cl_UP_RA operator- (const cl_UP_RA& x, const cl_UP_RA& y) + { return x.ring()->minus(x,y); } + +// Multiply. +inline const cl_UP_RA operator* (const cl_UP_RA& x, const cl_UP_RA& y) + { return x.ring()->mul(x,y); } + +// Squaring. +inline const cl_UP_RA square (const cl_UP_RA& x) + { return x.ring()->square(x); } + +// Exponentiation x^y, where y > 0. +inline const cl_UP_RA expt_pos (const cl_UP_RA& x, const cl_I& y) + { return x.ring()->expt_pos(x,y); } + +// Scalar multiplication. +#if 0 // less efficient +inline const cl_UP_RA operator* (const cl_I& x, const cl_UP_RA& y) + { return y.ring()->mul(y.ring()->canonhom(x),y); } +inline const cl_UP_RA operator* (const cl_UP_RA& x, const cl_I& y) + { return x.ring()->mul(x.ring()->canonhom(y),x); } +#endif +inline const cl_UP_RA operator* (const cl_I& x, const cl_UP_RA& y) + { return y.ring()->scalmul(x,y); } +inline const cl_UP_RA operator* (const cl_UP_RA& x, const cl_I& y) + { return x.ring()->scalmul(y,x); } +inline const cl_UP_RA operator* (const cl_RA& x, const cl_UP_RA& y) + { return y.ring()->scalmul(x,y); } +inline const cl_UP_RA operator* (const cl_UP_RA& x, const cl_RA& y) + { return x.ring()->scalmul(y,x); } + +// Coefficient. +inline const cl_RA coeff (const cl_UP_RA& x, uintL index) + { return x.ring()->coeff(x,index); } + +// Destructive modification. +inline void set_coeff (cl_UP_RA& x, uintL index, const cl_RA& y) + { x.ring()->set_coeff(x,index,y); } +inline void finalize (cl_UP_RA& x) + { x.ring()->finalize(x); } +inline void cl_UP_RA::set_coeff (uintL index, const cl_RA& y) + { ring()->set_coeff(*this,index,y); } +inline void cl_UP_RA::finalize () + { ring()->finalize(*this); } + +// Evaluation. (No extension of the base ring allowed here for now.) +inline const cl_RA cl_UP_RA::operator() (const cl_RA& y) const +{ + return ring()->eval(*this,y); +} + +// Derivative. +inline const cl_UP_RA deriv (const cl_UP_RA& x) + { return The2(cl_UP_RA)(deriv((const cl_UP&)x)); } + +#endif + +CL_REQUIRE(cl_RA_ring) + + +// Returns the n-th Legendre polynomial (n >= 0). +extern const cl_UP_RA cl_legendre (sintL n); + +#endif /* _CL_UNIVPOLY_RATIONAL_H */ diff --git a/include/cl_univpoly_real.h b/include/cl_univpoly_real.h new file mode 100644 index 0000000..c04736b --- /dev/null +++ b/include/cl_univpoly_real.h @@ -0,0 +1,222 @@ +// Univariate Polynomials over the real numbers. + +#ifndef _CL_UNIVPOLY_REAL_H +#define _CL_UNIVPOLY_REAL_H + +#include "cl_ring.h" +#include "cl_univpoly.h" +#include "cl_number.h" +#include "cl_real_class.h" +#include "cl_integer_class.h" +#include "cl_real_ring.h" + +// Normal univariate polynomials with stricter static typing: +// `cl_R' instead of `cl_ring_element'. + +#ifdef notyet + +typedef cl_UP_specialized cl_UP_R; +typedef cl_univpoly_specialized_ring cl_univpoly_real_ring; +//typedef cl_heap_univpoly_specialized_ring cl_heap_univpoly_real_ring; + +#else + +class cl_heap_univpoly_real_ring; + +class cl_univpoly_real_ring : public cl_univpoly_ring { +public: + // Default constructor. + cl_univpoly_real_ring () : cl_univpoly_ring () {} + // Copy constructor. + cl_univpoly_real_ring (const cl_univpoly_real_ring&); + // Assignment operator. + cl_univpoly_real_ring& operator= (const cl_univpoly_real_ring&); + // Automatic dereferencing. + cl_heap_univpoly_real_ring* operator-> () const + { return (cl_heap_univpoly_real_ring*)heappointer; } +}; +// Copy constructor and assignment operator. +CL_DEFINE_COPY_CONSTRUCTOR2(cl_univpoly_real_ring,cl_univpoly_ring) +CL_DEFINE_ASSIGNMENT_OPERATOR(cl_univpoly_real_ring,cl_univpoly_real_ring) + +class cl_UP_R : public cl_UP { +public: + const cl_univpoly_real_ring& ring () const { return The(cl_univpoly_real_ring)(_ring); } + // Conversion. + CL_DEFINE_CONVERTER(cl_ring_element) + // Destructive modification. + void set_coeff (uintL index, const cl_R& y); + void finalize(); + // Evaluation. + const cl_R operator() (const cl_R& y) const; +public: // Ability to place an object at a given address. + void* operator new (size_t size) { return cl_malloc_hook(size); } + void* operator new (size_t size, cl_UP_R* ptr) { (void)size; return ptr; } + void operator delete (void* ptr) { cl_free_hook(ptr); } +}; + +class cl_heap_univpoly_real_ring : public cl_heap_univpoly_ring { + SUBCLASS_cl_heap_univpoly_ring() + // High-level operations. + void fprint (cl_ostream stream, const cl_UP_R& x) + { + cl_heap_univpoly_ring::fprint(stream,x); + } + cl_boolean equal (const cl_UP_R& x, const cl_UP_R& y) + { + return cl_heap_univpoly_ring::equal(x,y); + } + const cl_UP_R zero () + { + return The2(cl_UP_R)(cl_heap_univpoly_ring::zero()); + } + cl_boolean zerop (const cl_UP_R& x) + { + return cl_heap_univpoly_ring::zerop(x); + } + const cl_UP_R plus (const cl_UP_R& x, const cl_UP_R& y) + { + return The2(cl_UP_R)(cl_heap_univpoly_ring::plus(x,y)); + } + const cl_UP_R minus (const cl_UP_R& x, const cl_UP_R& y) + { + return The2(cl_UP_R)(cl_heap_univpoly_ring::minus(x,y)); + } + const cl_UP_R uminus (const cl_UP_R& x) + { + return The2(cl_UP_R)(cl_heap_univpoly_ring::uminus(x)); + } + const cl_UP_R one () + { + return The2(cl_UP_R)(cl_heap_univpoly_ring::one()); + } + const cl_UP_R canonhom (const cl_I& x) + { + return The2(cl_UP_R)(cl_heap_univpoly_ring::canonhom(x)); + } + const cl_UP_R mul (const cl_UP_R& x, const cl_UP_R& y) + { + return The2(cl_UP_R)(cl_heap_univpoly_ring::mul(x,y)); + } + const cl_UP_R square (const cl_UP_R& x) + { + return The2(cl_UP_R)(cl_heap_univpoly_ring::square(x)); + } + const cl_UP_R expt_pos (const cl_UP_R& x, const cl_I& y) + { + return The2(cl_UP_R)(cl_heap_univpoly_ring::expt_pos(x,y)); + } + const cl_UP_R scalmul (const cl_R& x, const cl_UP_R& y) + { + return The2(cl_UP_R)(cl_heap_univpoly_ring::scalmul(cl_ring_element(cl_R_ring,x),y)); + } + sintL degree (const cl_UP_R& x) + { + return cl_heap_univpoly_ring::degree(x); + } + const cl_UP_R monomial (const cl_R& x, uintL e) + { + return The2(cl_UP_R)(cl_heap_univpoly_ring::monomial(cl_ring_element(cl_R_ring,x),e)); + } + const cl_R coeff (const cl_UP_R& x, uintL index) + { + return The(cl_R)(cl_heap_univpoly_ring::coeff(x,index)); + } + const cl_UP_R create (sintL deg) + { + return The2(cl_UP_R)(cl_heap_univpoly_ring::create(deg)); + } + void set_coeff (cl_UP_R& x, uintL index, const cl_R& y) + { + cl_heap_univpoly_ring::set_coeff(x,index,cl_ring_element(cl_R_ring,y)); + } + void finalize (cl_UP_R& x) + { + cl_heap_univpoly_ring::finalize(x); + } + const cl_R eval (const cl_UP_R& x, const cl_R& y) + { + return The(cl_R)(cl_heap_univpoly_ring::eval(x,cl_ring_element(cl_R_ring,y))); + } +private: + // No need for any constructors. + cl_heap_univpoly_real_ring (); +}; + +// Lookup of polynomial rings. +inline const cl_univpoly_real_ring cl_find_univpoly_ring (const cl_real_ring& r) +{ return The(cl_univpoly_real_ring) (cl_find_univpoly_ring((const cl_ring&)r)); } +inline const cl_univpoly_real_ring cl_find_univpoly_ring (const cl_real_ring& r, const cl_symbol& varname) +{ return The(cl_univpoly_real_ring) (cl_find_univpoly_ring((const cl_ring&)r,varname)); } + +// Operations on polynomials. + +// Add. +inline const cl_UP_R operator+ (const cl_UP_R& x, const cl_UP_R& y) + { return x.ring()->plus(x,y); } + +// Negate. +inline const cl_UP_R operator- (const cl_UP_R& x) + { return x.ring()->uminus(x); } + +// Subtract. +inline const cl_UP_R operator- (const cl_UP_R& x, const cl_UP_R& y) + { return x.ring()->minus(x,y); } + +// Multiply. +inline const cl_UP_R operator* (const cl_UP_R& x, const cl_UP_R& y) + { return x.ring()->mul(x,y); } + +// Squaring. +inline const cl_UP_R square (const cl_UP_R& x) + { return x.ring()->square(x); } + +// Exponentiation x^y, where y > 0. +inline const cl_UP_R expt_pos (const cl_UP_R& x, const cl_I& y) + { return x.ring()->expt_pos(x,y); } + +// Scalar multiplication. +#if 0 // less efficient +inline const cl_UP_R operator* (const cl_I& x, const cl_UP_R& y) + { return y.ring()->mul(y.ring()->canonhom(x),y); } +inline const cl_UP_R operator* (const cl_UP_R& x, const cl_I& y) + { return x.ring()->mul(x.ring()->canonhom(y),x); } +#endif +inline const cl_UP_R operator* (const cl_I& x, const cl_UP_R& y) + { return y.ring()->scalmul(x,y); } +inline const cl_UP_R operator* (const cl_UP_R& x, const cl_I& y) + { return x.ring()->scalmul(y,x); } +inline const cl_UP_R operator* (const cl_R& x, const cl_UP_R& y) + { return y.ring()->scalmul(x,y); } +inline const cl_UP_R operator* (const cl_UP_R& x, const cl_R& y) + { return x.ring()->scalmul(y,x); } + +// Coefficient. +inline const cl_R coeff (const cl_UP_R& x, uintL index) + { return x.ring()->coeff(x,index); } + +// Destructive modification. +inline void set_coeff (cl_UP_R& x, uintL index, const cl_R& y) + { x.ring()->set_coeff(x,index,y); } +inline void finalize (cl_UP_R& x) + { x.ring()->finalize(x); } +inline void cl_UP_R::set_coeff (uintL index, const cl_R& y) + { ring()->set_coeff(*this,index,y); } +inline void cl_UP_R::finalize () + { ring()->finalize(*this); } + +// Evaluation. (No extension of the base ring allowed here for now.) +inline const cl_R cl_UP_R::operator() (const cl_R& y) const +{ + return ring()->eval(*this,y); +} + +// Derivative. +inline const cl_UP_R deriv (const cl_UP_R& x) + { return The2(cl_UP_R)(deriv((const cl_UP&)x)); } + +#endif + +CL_REQUIRE(cl_R_ring) + +#endif /* _CL_UNIVPOLY_REAL_H */ diff --git a/include/cln.h b/include/cln.h new file mode 100644 index 0000000..d12ff38 --- /dev/null +++ b/include/cln.h @@ -0,0 +1,141 @@ +// CLN exported types and functions + +#ifndef _CLN_H +#define _CLN_H + +// Automatically generated by configure +//#include "cl_config.h" // included by "cl_types.h" below +//#include "cl_intparam.h" // included by "cl_types.h" below +//#include "cl_floatparam.h" // not needed by any public header file + +// ============================== base ============================== + +// Basic types and definitions. +#include "cl_types.h" +#include "cl_modules.h" +#include "cl_object.h" + +// Miscellaneous. +#include "cl_random.h" +#include "cl_malloc.h" +#include "cl_abort.h" +#include "cl_floatformat.h" +#include "cl_io.h" +#include "cl_condition.h" + +// Symbolic facilities. +#include "cl_string.h" +#include "cl_symbol.h" +#include "cl_proplist.h" + +// Miscellaneous. +#include "cl_input.h" +#include "cl_output.h" + +// Abstract number classes. +#include "cl_number.h" +#include "cl_number_io.h" +#include "cl_complex_class.h" +#include "cl_real_class.h" +#include "cl_rational_class.h" + +// Rings. +#include "cl_ring.h" + +// ============================== integer ============================== + +// Integers. +#include "cl_integer_class.h" +#include "cl_integer.h" +#include "cl_integer_io.h" +#include "cl_integer_ring.h" +#include "cl_null_ring.h" + +// ============================== rational ============================== + +// Rational numbers. +#include "cl_rational.h" +#include "cl_rational_io.h" +#include "cl_rational_ring.h" + +// ============================== float ============================== + +// Floating-point numbers. +#include "cl_float_class.h" +#include "cl_sfloat_class.h" +#include "cl_ffloat_class.h" +#include "cl_dfloat_class.h" +#include "cl_lfloat_class.h" +#include "cl_float.h" +#include "cl_float_io.h" +#include "cl_sfloat.h" +#include "cl_sfloat_io.h" +#include "cl_ffloat.h" +#include "cl_ffloat_io.h" +#include "cl_dfloat.h" +#include "cl_dfloat_io.h" +#include "cl_lfloat.h" +#include "cl_lfloat_io.h" + +// ============================== real ============================== + +// Real numbers. +#include "cl_real.h" +#include "cl_real_io.h" +#include "cl_real_ring.h" + +// ============================== complex ============================== + +// Complex numbers. +#include "cl_complex.h" +#include "cl_complex_io.h" +#include "cl_complex_ring.h" + +// ============================== modinteger ============================== + +// Modular integers. +#include "cl_modinteger.h" + +// ============================== numtheory ============================== + +// Rings for number theory. +#include "cl_numtheory.h" + +// ============================== vector ============================== + +// Vectors. +#include "cl_V.h" +#include "cl_GV.h" +#include "cl_GV_number.h" +#include "cl_GV_complex.h" +#include "cl_GV_real.h" +#include "cl_GV_rational.h" +#include "cl_GV_integer.h" +#include "cl_GV_modinteger.h" +#include "cl_SV.h" +#include "cl_SV_number.h" +#include "cl_SV_complex.h" +#include "cl_SV_real.h" +#include "cl_SV_rational.h" +#include "cl_SV_integer.h" +#include "cl_SV_ringelt.h" + +// ============================== polynomial ============================== + +// Polynomials. +#include "cl_univpoly.h" +#include "cl_univpoly_complex.h" +#include "cl_univpoly_real.h" +#include "cl_univpoly_rational.h" +#include "cl_univpoly_integer.h" +#include "cl_univpoly_modint.h" + +// ============================== modpolynomial ============================== + +// ============================== timing ============================== + +// Environmental facilities. +#include "cl_timing.h" + +#endif /* _CLN_H */ + diff --git a/lidia-interface/LiDIA-patch1 b/lidia-interface/LiDIA-patch1 new file mode 100644 index 0000000..5665cab --- /dev/null +++ b/lidia-interface/LiDIA-patch1 @@ -0,0 +1,321 @@ +diff -r -c3 LiDIA-1.3.orig/Readme LiDIA-1.3/Readme +*** LiDIA-1.3.orig/Readme Wed Feb 5 21:51:10 1997 +--- LiDIA-1.3/Readme Sun Jan 25 00:44:29 1998 +*************** +*** 157,164 **** + o mpqs: large prime variant for quadratic sieve in the class + rational_factorization. + +! o You can now choose gmp as the integer arithmetic of the kernel. +! This LiDIA - release contains gmp version 2.0.2. + + + +--- 157,164 ---- + o mpqs: large prime variant for quadratic sieve in the class + rational_factorization. + +! o You can now choose gmp or cln as the integer arithmetic of the kernel. +! This LiDIA release contains gmp version 2.0.2 and cln version 1997-09-06. + + + +diff -r -c3 LiDIA-1.3.orig/config/CONFIG.in LiDIA-1.3/config/CONFIG.in +*** LiDIA-1.3.orig/config/CONFIG.in Wed Feb 5 12:02:16 1997 +--- LiDIA-1.3/config/CONFIG.in Sat Jan 24 18:42:57 1998 +*************** +*** 42,48 **** + # + # The Kernel And The Interface To Be compiled + # +! # Possible Integer Interfaces Are: libI, lip, gmp + # + # Possible Memory Managers Are: malloc, dentzer, boehm, + # default (no manager) +--- 42,48 ---- + # + # The Kernel And The Interface To Be compiled + # +! # Possible Integer Interfaces Are: libI, lip, gmp, cln + # + # Possible Memory Managers Are: malloc, dentzer, boehm, + # default (no manager) +*************** +*** 149,155 **** + LIDIA_INSTALL_DAT = ${LIDIA_INSTALL_DIR}/lib + + # +! # OS/2 Compatability Section + # + + CXX-off = +--- 149,155 ---- + LIDIA_INSTALL_DAT = ${LIDIA_INSTALL_DIR}/lib + + # +! # OS/2 Compatibility Section + # + + CXX-off = +*************** +*** 166,171 **** +--- 166,172 ---- + # Make Command Macros + # + # AR -- the archiver command ++ # ARX -- the archiver extract command + # RM -- command used to remove files + # RMR -- command used to remove directories + # CP -- command used to copy files +*************** +*** 178,183 **** +--- 179,185 ---- + # + + AR = @AR@ ++ ARX = ar x + RM = @RM@ + RMR = @RMR@ + CP = @CP@ +diff -r -c3 LiDIA-1.3.orig/config/CONFIG.os2 LiDIA-1.3/config/CONFIG.os2 +*** LiDIA-1.3.orig/config/CONFIG.os2 Tue Jan 21 14:55:44 1997 +--- LiDIA-1.3/config/CONFIG.os2 Sat Jan 24 18:43:28 1998 +*************** +*** 137,142 **** +--- 137,143 ---- + # Make Command Macros + # + # AR -- the archiver command ++ # ARX -- the archiver extract command + # RM -- command used to remove files + # RMR -- command used to remove directories + # CP -- command used to copy files +*************** +*** 147,152 **** +--- 148,154 ---- + # TOUCH -- command used to create an empry file + # + AR = ar ru ++ ARX = ar x + RM = del /N + RMR = del /N + CP = xcopy +diff -r -c3 LiDIA-1.3.orig/config/bin/integer-sh LiDIA-1.3/config/bin/integer-sh +*** LiDIA-1.3.orig/config/bin/integer-sh Tue Oct 22 22:25:57 1996 +--- LiDIA-1.3/config/bin/integer-sh Sun Jan 25 00:47:13 1998 +*************** +*** 7,15 **** + + echo " " + echo "You will now be asked for the integer arithmetic that " +! echo "will be used in the kernel of LiDIA (gmp, libI, lip)." + echo " " + echo "gmp - written by Torbjorn Granlund" + echo "libI - written by Ralf Dentzer" + echo "lip - written by Arjen Lenstra" + echo " " +--- 7,16 ---- + + echo " " + echo "You will now be asked for the integer arithmetic that " +! echo "will be used in the kernel of LiDIA (gmp, cln, libI, lip)." + echo " " + echo "gmp - written by Torbjorn Granlund" ++ echo "cln - written by Bruno Haible (based on gmp)" + echo "libI - written by Ralf Dentzer" + echo "lip - written by Arjen Lenstra" + echo " " +*************** +*** 23,35 **** + do + echo -n "integer arithmetic ? [$INTEGERS] : " + read ANSWER +! if test "$ANSWER" = "gmp" -o "$ANSWER" = "lip" -o "$ANSWER" = "libI" ; then + INTEGERS=$ANSWER + SUCCESS=y + elif test "$ANSWER" = "" ; then + SUCCESS=y + else +! echo "Please choose gmp, libI, or lip." + INTEGERS="libI" + fi + done +--- 24,36 ---- + do + echo -n "integer arithmetic ? [$INTEGERS] : " + read ANSWER +! if test "$ANSWER" = "gmp" -o "$ANSWER" = "cln" -o "$ANSWER" = "lip" -o "$ANSWER" = "libI" ; then + INTEGERS=$ANSWER + SUCCESS=y + elif test "$ANSWER" = "" ; then + SUCCESS=y + else +! echo "Please choose gmp, cln, libI, or lip." + INTEGERS="libI" + fi + done +diff -r -c3 LiDIA-1.3.orig/doc/manual/FIG/lidia_model.fig LiDIA-1.3/doc/manual/FIG/lidia_model.fig +*** LiDIA-1.3.orig/doc/manual/FIG/lidia_model.fig Tue Feb 27 11:57:01 1996 +--- LiDIA-1.3/doc/manual/FIG/lidia_model.fig Sun Jan 25 00:48:58 1998 +*************** +*** 55,61 **** + 4 0 -1 0 0 2 16 0.0000000 4 225 2085 1200 2850 parameterized classes\001 + 4 0 -1 0 0 2 16 0.0000000 4 225 1365 1200 4035 simple classes\001 + 4 0 -1 0 0 2 16 0.0000000 4 165 930 1200 5220 interfaces\001 +! 4 2 -1 0 0 12 12 0.0000000 4 180 2100 9000 6375 (libI, lip, gmp, mm)\001 + 4 2 -1 0 0 12 12 0.0000000 4 180 1365 9000 5175 (bigint, gmm)\001 + 4 2 -1 0 0 12 12 0.0000000 4 180 2940 9000 3975 (bigrational, bigfloat, ...)\001 + 4 2 -1 0 0 12 12 0.0000000 4 180 3675 9000 2775 (vector, matrix, power series, ...)\001 +--- 55,61 ---- + 4 0 -1 0 0 2 16 0.0000000 4 225 2085 1200 2850 parameterized classes\001 + 4 0 -1 0 0 2 16 0.0000000 4 225 1365 1200 4035 simple classes\001 + 4 0 -1 0 0 2 16 0.0000000 4 165 930 1200 5220 interfaces\001 +! 4 2 -1 0 0 12 12 0.0000000 4 180 2100 9000 6375 (libI, lip, gmp, cln, mm)\001 + 4 2 -1 0 0 12 12 0.0000000 4 180 1365 9000 5175 (bigint, gmm)\001 + 4 2 -1 0 0 12 12 0.0000000 4 180 2940 9000 3975 (bigrational, bigfloat, ...)\001 + 4 2 -1 0 0 12 12 0.0000000 4 180 3675 9000 2775 (vector, matrix, power series, ...)\001 +diff -r -c3 LiDIA-1.3.orig/doc/manual/bibliography.tex LiDIA-1.3/doc/manual/bibliography.tex +*** LiDIA-1.3.orig/doc/manual/bibliography.tex Fri Jan 24 13:22:31 1997 +--- LiDIA-1.3/doc/manual/bibliography.tex Sun Jan 25 00:55:48 1998 +*************** +*** 151,156 **** +--- 151,159 ---- + \IT{A rigorous subexponential algorithm for computation of class groups}, + Tech. report, IBM Research Report, San Jose, CA, 1989. + ++ \bibitem{haible} B. Haible: ++ \IT{CLN, a Class Library for Numbers}, 1997. ++ + \bibitem{HLConF} G.H. Hardy and J.E. Littlewood: + \IT{\em Partitio numerorum {III}: On the expression of a number as a sum of + primes}, Acta Math. {\bf 44} (1923), 1--70. +diff -r -c3 LiDIA-1.3.orig/doc/manual/installing.tex LiDIA-1.3/doc/manual/installing.tex +*** LiDIA-1.3.orig/doc/manual/installing.tex Wed Feb 5 17:33:40 1997 +--- LiDIA-1.3/doc/manual/installing.tex Sun Jan 25 00:58:30 1998 +*************** +*** 309,316 **** + of the kernel. + \item BIGINT\\ + This is used to decide which integer arithmetic is to be compiled with +! {\LiDIA}. At the moment we support three possibilities: \TT{gmp}, \TT{libI}, +! and \TT{lip}. We suggest that you use the \TT{gmp} with the GNU g++ + compiler and \TT{libI} otherwise. Use \TT{lip}, if you have chosen + \TT{libI} during the configuration process and TARGET has been set + to c by configure. In this case, no \TT{libI} assembler code is +--- 309,316 ---- + of the kernel. + \item BIGINT\\ + This is used to decide which integer arithmetic is to be compiled with +! {\LiDIA}. At the moment we support four possibilities: \TT{gmp}, \TT{cln}, +! TT{libI}, and \TT{lip}. We suggest that you use the \TT{gmp} with the GNU g++ + compiler and \TT{libI} otherwise. Use \TT{lip}, if you have chosen + \TT{libI} during the configuration process and TARGET has been set + to c by configure. In this case, no \TT{libI} assembler code is +diff -r -c3 LiDIA-1.3.orig/doc/manual/overview.tex LiDIA-1.3/doc/manual/overview.tex +*** LiDIA-1.3.orig/doc/manual/overview.tex Wed Jan 29 19:32:32 1997 +--- LiDIA-1.3/doc/manual/overview.tex Sun Jan 25 00:57:36 1998 +*************** +*** 19,24 **** +--- 19,25 ---- + \newcommand{\libi}{{\bf libI}} + \newcommand{\gmp}{{\bf GNU gmp}} + \newcommand{\lip}{{\bf lip}} ++ \newcommand{\cln}{{\bf cln}} + \newcommand{\bigint}{{\bf bigint}} + + +*************** +*** 70,76 **** + It is a serious problem to decide which multiprecision integer package + and which memory manager should be used in \LiDIA. There are + competing multiprecision integer packages, for example the +! \gmp\ package \cite{gnump}, the \libi\ package \cite{dentzer} and + the \lip\ package \cite{lenstra}. Some of those packages are more + efficient on one architecture and some on others. Also, new + architectures lead very fast to new multiprecision packages. We decided +--- 71,78 ---- + It is a serious problem to decide which multiprecision integer package + and which memory manager should be used in \LiDIA. There are + competing multiprecision integer packages, for example the +! \gmp\ package \cite{gnump}, the \cln\ package \cite{haible}, +! the \libi\ package \cite{dentzer} and + the \lip\ package \cite{lenstra}. Some of those packages are more + efficient on one architecture and some on others. Also, new + architectures lead very fast to new multiprecision packages. We decided +*************** +*** 112,120 **** + whole functionality of the interface can be used in the kernel. + Currently, we support the multiprecision integer packages + \libi\ \cite{dentzer}, Arjen Lenstra's \Index{lip} package \cite{lenstra} +! (available by anonymous ftp via \TT{flash.bellcore.com:/pub/lenstra}) and GNU's + \IndexSUBTT{GNU}{gmp} arithmetic \cite{gnump} (available by anonymous +! ftp via \TT{prep.ai.mit.edu}). + + The second \LiDIA\ level is the \BF{interface} through which {\CPP} + applications on higher levels have access to the kernel. By that +--- 114,123 ---- + whole functionality of the interface can be used in the kernel. + Currently, we support the multiprecision integer packages + \libi\ \cite{dentzer}, Arjen Lenstra's \Index{lip} package \cite{lenstra} +! (available by anonymous ftp via \TT{flash.bellcore.com:/pub/lenstra}), GNU's + \IndexSUBTT{GNU}{gmp} arithmetic \cite{gnump} (available by anonymous +! ftp via \TT{prep.ai.mit.edu}), and CLN (available by anonymous ftp from +! \TT{ma2s2.mathematik.uni-karlsruhe.de:/pub/gnu}). + + The second \LiDIA\ level is the \BF{interface} through which {\CPP} + applications on higher levels have access to the kernel. By that +diff -r -c3 LiDIA-1.3.orig/include/LiDIA/bigint.h LiDIA-1.3/include/LiDIA/bigint.h +*** LiDIA-1.3.orig/include/LiDIA/bigint.h Tue Oct 29 17:47:17 1996 +--- LiDIA-1.3/include/LiDIA/bigint.h Sat Jan 24 20:29:16 1998 +*************** +*** 51,56 **** +--- 51,57 ---- + bigint(long l); + bigint(unsigned long ul); + bigint(const bigint & a); ++ bigint(const integer_type_name & II) : I (II) {} // cln needs this + ~bigint(); + + /** +Only in LiDIA-1.3/src/interfaces/integers: cln +diff -r -c3 LiDIA-1.3.orig/src/interfaces/integers/gmp/bigint.c LiDIA-1.3/src/interfaces/integers/gmp/bigint.c +*** LiDIA-1.3.orig/src/interfaces/integers/gmp/bigint.c Fri Jan 10 18:19:00 1997 +--- LiDIA-1.3/src/interfaces/integers/gmp/bigint.c Sat Jan 24 17:41:29 1998 +*************** +*** 610,616 **** + + void invert(bigint & a, const bigint & b) + { +! if ((a.I._mp_size == 1 || a.I._mp_size == -1) && a.I._mp_d[0] == 1) + mpz_set(&a.I, &b.I); + else + lidia_error_handler("bigint", "invert::inverting of a non-unit."); +--- 610,616 ---- + + void invert(bigint & a, const bigint & b) + { +! if ((b.I._mp_size == 1 || b.I._mp_size == -1) && b.I._mp_d[0] == 1) + mpz_set(&a.I, &b.I); + else + lidia_error_handler("bigint", "invert::inverting of a non-unit."); +Only in LiDIA-1.3/src/kernel/integers: cln +diff -r -c3 LiDIA-1.3.orig/src/simple_classes/factorization/mpqs.c LiDIA-1.3/src/simple_classes/factorization/mpqs.c +*** LiDIA-1.3.orig/src/simple_classes/factorization/mpqs.c Tue Jan 28 14:00:36 1997 +--- LiDIA-1.3/src/simple_classes/factorization/mpqs.c Sat Jan 24 17:45:17 1998 +*************** +*** 17,23 **** + //extern "C" int system(char*); + #endif + +! #if !defined(__GNUG__) + #include + #else + #define SIGHUP 1 /* hangup */ +--- 17,23 ---- + //extern "C" int system(char*); + #endif + +! #if defined(__linux__) || !defined(__GNUG__) + #include + #else + #define SIGHUP 1 /* hangup */ diff --git a/lidia-interface/LiDIA-patch2 b/lidia-interface/LiDIA-patch2 new file mode 100644 index 0000000..31ea28c --- /dev/null +++ b/lidia-interface/LiDIA-patch2 @@ -0,0 +1,27 @@ +diff -r -c3 LiDIA-1.3/config/CONFIG LiDIA/config/CONFIG +*** LiDIA-1.3/config/CONFIG Mon Apr 15 15:00:47 1996 +--- LiDIA/config/CONFIG Sun Nov 17 18:43:41 1996 +*************** +*** 49,57 **** + # default (no manager) + # + +! BIGINT = libI +! GMM = default + + + # + # The Compiler/Assembler/Linker Settings +--- 49,60 ---- + # default (no manager) + # + +! BIGINT = cln +! GMM = default + ++ CLN_DIR = /home/bruno/cln ++ CLN_TARGETDIR = /home/bruno/cln/linuxelf ++ CLN_INCLUDES = -I$(CLN_TARGETDIR)/include -I$(CLN_DIR)/include -I$(CLN_DIR)/src/base -I$(CLN_DIR)/src/float -I$(CLN_DIR)/src/float/dfloat -I$(CLN_DIR)/src/io + + # + # The Compiler/Assembler/Linker Settings diff --git a/lidia-interface/README b/lidia-interface/README new file mode 100644 index 0000000..702053d --- /dev/null +++ b/lidia-interface/README @@ -0,0 +1,57 @@ +This directory contains an interface to the LiDIA library, version 1.3.1. +It is already contained in LiDIA-1.3.1 and LiDIA-1.4a1, and is reproduced +here only as a sample for the use of CLN. + +LiDIA is available from + ftp://ftp.informatik.th-darmstadt.de/pub/TI/systems/LiDIA +(The LiDIA group has also a nice Web page.) + +LiDIA has an abstract interface to the underlying long integer implementation. +Using CLN instead of the default libI, lip or gmp has the following +advantages: + + - Maximum speed on all CPUs, since CLN is based on the highly + optimized gmp-2.0.2. + + - Very large integers profit from CLN's Schönhage-Strassen FFT multiplication + (asymptotic bit complexity: O(N log N log log N)). + + - Copying integers is fast: no copying is actually involved, only a + reference count is manipulated. + + - Small integers (absolute value < 2^29) are represented immediately, + thus no memory allocation/deallocation is involved when dealing with + small integers. + +CLN does all this automatically. + +INSTALLATION +------------ + +1. Build CLN. + +2. Apply the first patch to LiDIA: + $ cd .../LiDIA + $ patch -p1 < .../cln/lidia-interface/LiDIA-patch1 + +3. Configure LiDIA as described in its manual. + +4. Apply the second patch to LiDIA: + $ cd .../LiDIA + $ patch -p1 < .../cln/lidia-interface/LiDIA-patch2 + You may have to do this by hand, if the patch fails. + +5. Make two symbolic links + $ ln -s .../cln/lidia-interface/interfaces/integers/cln \ + .../LiDIA/src/interfaces/integers/cln + $ ln -s .../cln/BUILDDIR/src .../LiDIA/src/kernel/integers/cln + where .../cln/BUILDDIR is the directory in which you have built + cln (i.e. there is a file .../cln/BUILDDIR/src/libcln.a). + +6. Modify the definitions of the variables CLN_DIR and CLN_TARGETDIR in + the file .../LiDIA/config/CONFIG : + CLN_DIR must point to .../cln, + CLN_TARGETDIR must point to .../cln/BUILDDIR. + +7. Build LiDIA as described in its manual. + diff --git a/lidia-interface/TAR-FILE-LIST b/lidia-interface/TAR-FILE-LIST new file mode 100644 index 0000000..9411232 --- /dev/null +++ b/lidia-interface/TAR-FILE-LIST @@ -0,0 +1,236 @@ +cln/COPYING +cln/INSTALL +cln/INSTALL.generic +cln/Makefile.in +cln/README +cln/configure +cln/autoconf/config.guess +cln/autoconf/config.sub +cln/autoconf/floatparam.c +cln/autoconf/intparam.c +cln/autoconf/ltconfig +cln/autoconf/ltmain.sh +cln/benchmarks/Makefile.in +cln/doc/Makefile.in +cln/examples/Makefile.in +cln/gmp/ +cln/include/cl_abort.h +cln/include/cl_complex_class.h +cln/include/cl_config.h.in +cln/include/cl_dfloat.h +cln/include/cl_dfloat_class.h +cln/include/cl_ffloat.h +cln/include/cl_ffloat_class.h +cln/include/cl_float.h +cln/include/cl_floatformat.h +cln/include/cl_float_class.h +cln/include/cl_input.h +cln/include/cl_integer.h +cln/include/cl_integer_class.h +cln/include/cl_integer_io.h +cln/include/cl_io.h +cln/include/cl_lfloat.h +cln/include/cl_lfloat_class.h +cln/include/cl_malloc.h +cln/include/cl_modules.h +cln/include/cl_number.h +cln/include/cl_number_io.h +cln/include/cl_object.h +cln/include/cl_output.h +cln/include/cl_random.h +cln/include/cl_rational_class.h +cln/include/cl_real_class.h +cln/include/cl_sfloat_class.h +cln/include/cl_string.h +cln/include/cl_types.h +cln/src/Makefile.in +cln/src/Makeflags +cln/src/base/Makeflags +cln/src/base/cl_N.h +cln/src/base/cl_N_err_d0.cc +cln/src/base/cl_alloca.cc +cln/src/base/cl_alloca.h +cln/src/base/cl_base_config.h.in +cln/src/base/cl_free.cc +cln/src/base/cl_gmpconfig.h.in +cln/src/base/cl_low.h +cln/src/base/cl_macros.h +cln/src/base/cl_malloc.cc +cln/src/base/cl_notreached.cc +cln/src/base/cl_offsetof.h +cln/src/base/cl_sysdep.h +cln/src/base/cl_xmacros.h +cln/src/base/digit/Makeflags +cln/src/base/digit/cl_D.h +cln/src/base/digitseq/Makeflags +cln/src/base/digitseq/cl_DS.h +cln/src/base/digitseq/cl_DS_div.cc +cln/src/base/digitseq/cl_DS_endian.h +cln/src/base/digitseq/cl_DS_mul.cc +cln/src/base/digitseq/cl_DS_mul_fftm.h +cln/src/base/digitseq/cl_DS_mul_kara.h +cln/src/base/digitseq/cl_DS_mul_kara_sqr.h +cln/src/base/digitseq/cl_DS_random.cc +cln/src/base/digitseq/cl_DS_recip.cc +cln/src/base/digitseq/cl_DS_recipsqrt.cc +cln/src/base/digitseq/cl_DS_sqrt.cc +cln/src/base/digitseq/cl_asm.h +cln/src/base/digitseq/cl_asm_.cc +cln/src/base/digitseq/cl_asm_arm.h +cln/src/base/digitseq/cl_asm_arm_.cc +cln/src/base/digitseq/cl_asm_hppa.h +cln/src/base/digitseq/cl_asm_hppa_.cc +cln/src/base/digitseq/cl_asm_i386.h +cln/src/base/digitseq/cl_asm_i386_.cc +cln/src/base/digitseq/cl_asm_m68k.h +cln/src/base/digitseq/cl_asm_m68k_.cc +cln/src/base/digitseq/cl_asm_mips.h +cln/src/base/digitseq/cl_asm_mips_.cc +cln/src/base/digitseq/cl_asm_sparc.h +cln/src/base/digitseq/cl_asm_sparc_.cc +cln/src/base/digitseq/cl_asm_sparc64.h +cln/src/base/digitseq/cl_asm_sparc64_.cc +cln/src/base/input/Makeflags +cln/src/base/input/cl_read_err_bad.cc +cln/src/base/input/cl_read_err_junk.cc +cln/src/base/low/Makeflags +cln/src/base/low/cl_low_div.cc +cln/src/base/low/cl_low_mul.cc +cln/src/base/output/Makeflags +cln/src/base/output/cl_output_dec.cc +cln/src/base/output/cl_prin_globals.cc +cln/src/base/random/Makeflags +cln/src/base/random/cl_UL_random.cc +cln/src/base/random/cl_random_def.cc +cln/src/base/random/cl_random_from.cc +cln/src/base/random/cl_random_impl.h +cln/src/base/string/Makeflags +cln/src/base/string/cl_spushstring.h +cln/src/base/string/cl_spushstring_push.cc +cln/src/base/string/cl_sstring.cc +cln/src/base/string/cl_sstring.h +cln/src/base/string/cl_st_c2.cc +cln/src/base/string/cl_st_make1.cc +cln/src/base/string/cl_st_make2.cc +cln/src/base/string/cl_st_null.cc +cln/src/base/string/misc/Makeflags +cln/src/base/string/misc/cl_st_class.cc +cln/src/integer/Makeflags +cln/src/integer/cl_I.h +cln/src/integer/algebraic/Makeflags +cln/src/integer/algebraic/cl_I_sqrt.cc +cln/src/integer/bitwise/Makeflags +cln/src/integer/bitwise/cl_I_ash.cc +cln/src/integer/bitwise/cl_I_ash.h +cln/src/integer/bitwise/cl_I_ash_I.cc +cln/src/integer/bitwise/cl_I_asherr.cc +cln/src/integer/bitwise/cl_I_byte.h +cln/src/integer/bitwise/cl_I_fullbyte.cc +cln/src/integer/bitwise/cl_I_ilength.cc +cln/src/integer/bitwise/cl_I_ldb.cc +cln/src/integer/bitwise/cl_I_ldbx.cc +cln/src/integer/bitwise/cl_I_log.h +cln/src/integer/bitwise/cl_I_log_aux.cc +cln/src/integer/bitwise/cl_I_logand.cc +cln/src/integer/bitwise/cl_I_logbitp.cc +cln/src/integer/bitwise/cl_I_logior.cc +cln/src/integer/bitwise/cl_I_lognot.cc +cln/src/integer/bitwise/cl_I_logxor.cc +cln/src/integer/conv/Makeflags +cln/src/integer/conv/cl_I_digits_need.cc +cln/src/integer/conv/cl_I_from_DS.cc +cln/src/integer/conv/cl_I_from_L.cc +cln/src/integer/conv/cl_I_from_L2.cc +cln/src/integer/conv/cl_I_from_NDS.cc +cln/src/integer/conv/cl_I_from_NUDS.cc +cln/src/integer/conv/cl_I_from_Q.cc +cln/src/integer/conv/cl_I_from_UDS.cc +cln/src/integer/conv/cl_I_from_UL.cc +cln/src/integer/conv/cl_I_from_UQ.cc +cln/src/integer/conv/cl_I_from_digits.cc +cln/src/integer/conv/cl_I_to_L.cc +cln/src/integer/conv/cl_I_to_Q.cc +cln/src/integer/conv/cl_I_to_UL.cc +cln/src/integer/conv/cl_I_to_UQ.cc +cln/src/integer/conv/cl_I_to_digits.cc +cln/src/integer/division/Makeflags +cln/src/integer/division/cl_I_floor2.cc +cln/src/integer/division/cl_I_rem.cc +cln/src/integer/division/cl_I_trunc1.cc +cln/src/integer/division/cl_I_trunc2.cc +cln/src/integer/elem/Makeflags +cln/src/integer/elem/cl_I_compare.cc +cln/src/integer/elem/cl_I_div.cc +cln/src/integer/elem/cl_I_equal.cc +cln/src/integer/elem/cl_I_minus.cc +cln/src/integer/elem/cl_I_minus1.cc +cln/src/integer/elem/cl_I_minusp.cc +cln/src/integer/elem/cl_I_mul.cc +cln/src/integer/elem/cl_I_plus.cc +cln/src/integer/elem/cl_I_plus1.cc +cln/src/integer/elem/cl_I_square.cc +cln/src/integer/elem/cl_I_uminus.cc +cln/src/integer/elem/cl_I_zerop.cc +cln/src/integer/gcd/Makeflags +cln/src/integer/gcd/cl_I_gcd.cc +cln/src/integer/gcd/cl_I_gcd_aux.cc +cln/src/integer/gcd/cl_I_gcd_aux2.cc +cln/src/integer/gcd/cl_I_xgcd.cc +cln/src/integer/gcd/cl_low_gcd.cc +cln/src/integer/input/Makeflags +cln/src/integer/input/cl_I_from_string.cc +cln/src/integer/input/cl_I_read.cc +cln/src/integer/input/cl_I_readparsed.cc +cln/src/integer/misc/Makeflags +cln/src/integer/misc/cl_BN_class.cc +cln/src/integer/misc/cl_I_abs.cc +cln/src/integer/misc/cl_I_exptpos_I.cc +cln/src/integer/misc/cl_I_oddp.cc +cln/src/integer/output/Makeflags +cln/src/integer/output/cl_I_aprint.cc +cln/src/integer/output/cl_I_bprint.cc +cln/src/integer/output/cl_I_cprint.cc +cln/src/integer/output/cl_I_decstring.cc +cln/src/integer/output/cl_I_dprint.cc +cln/src/integer/output/cl_I_print.cc +cln/src/integer/output/cl_I_print_string.cc +cln/src/integer/random/Makeflags +cln/src/integer/random/cl_I_random.cc +cln/src/float/Makeflags +cln/src/float/cl_F.h +cln/src/float/cl_float_config.h.in +cln/src/float/base/Makeflags +cln/src/float/base/cl_F_err_nan.cc +cln/src/float/base/cl_F_err_ov.cc +cln/src/float/base/cl_F_err_un.cc +cln/src/float/base/cl_F_globals.cc +cln/src/float/base/cl_ieee.cc +cln/src/float/base/cl_ieee.h +cln/src/float/ffloat/Makeflags +cln/src/float/ffloat/cl_FF.h +cln/src/float/ffloat/elem/Makeflags +cln/src/float/ffloat/elem/cl_FF_globals.cc +cln/src/float/ffloat/misc/Makeflags +cln/src/float/ffloat/misc/cl_FF_class.cc +cln/src/float/dfloat/Makeflags +cln/src/float/dfloat/cl_DF.h +cln/src/float/dfloat/conv/Makeflags +cln/src/float/dfloat/conv/cl_DF_from_double.cc +cln/src/float/dfloat/conv/cl_I_to_double.cc +cln/src/float/dfloat/elem/Makeflags +cln/src/float/dfloat/elem/cl_DF_fround.cc +cln/src/float/dfloat/elem/cl_DF_globals.cc +cln/src/float/dfloat/elem/cl_DF_to_I.cc +cln/src/float/dfloat/misc/Makeflags +cln/src/float/dfloat/misc/cl_DF_class.cc +cln/src/float/lfloat/Makeflags +cln/src/float/lfloat/cl_LF.h +cln/src/float/lfloat/cl_LF_impl.h +cln/src/float/lfloat/elem/Makeflags +cln/src/float/lfloat/elem/cl_LF_globals.cc +cln/src/float/lfloat/misc/Makeflags +cln/src/float/lfloat/misc/cl_LF_class.cc +cln/src/timing/Makeflags +cln/src/timing/cl_t_config.h.in +cln/tests/.gdbinit +cln/tests/Makefile.in diff --git a/lidia-interface/bigint.o.i386-linux b/lidia-interface/bigint.o.i386-linux new file mode 100644 index 0000000000000000000000000000000000000000..ddd204b821b8c32375cb5a18c68d20cc748d0e6c GIT binary patch literal 27412 zcmeHPeSB2anLhatqDF~`3W^XcA`}S;1qG{a_?W0av5tf!ZZ!^*WReU{G9fbqSj);f zu**1&rCqnH?zW|^{ng#t%C6ety6Z+{!M19%bXBUNsoFYi(i&^j)Y4|3=ic|sJ#%OB zfnvLVcz?gibD#6R=RN1V=lh%sw|G`p<>lom{p6_vecvDA)hldjdi9^ZyBZ>a{$NNs&X+D1fedHxsQJ2r6-n@eAQMYs5}>w8jO`rn8jJ2@Sv zaCe>&!Ln!7XOZp8?cJ09zB}80Xs>Dc9b?GHil0mVLGt^4@-s?$72SRLyYs}M+CQk@ zF3*wb1D+$t!NXqkjWyCri|DcJHn{_RcgXVNM!UZ_{>xSVvHUwqem`)1=E{$h7vyNBg8^mC1mm(-$5Ia5RZk#`>FY*Ub&kX2)e z8Cj!pdbrf{M^=4&DE5y@mPeS+IbRynn!Omv7}?Y9kNqo|rO&Zx4E?P6Sf656_3j|mtaM;EZrab%GM8~ ziiUIm@;;=?p4-1!zU&uY!XN4REj~1HW1&6#b9m76YsP$mmCYo((&Ix#n=%(H9A+}@ zO*$%jC1cu~c~tgF|1|dOwQ+rMjjO$%oZR*Qo+Q|0jX!fo; z#`gX&Fjg6lE`Q%S#`fypmpz#;lChHQ?`)Zj)tgeSGx0}nV=xPIGbu~a^!%II0P0e` zZ)oR?IhFP&hU}ijR$))4#(uomn!if64`*_jz+W@N|j8MGDygJ?y1^=f5HF9>R_ z?O4^QIdkWhONfl=JB2CA$*$dzobh0^_V?6pv`aD!4my3}=-SJcV{C81`?iM>%v!rO!UCwm#eyU8)sWSKP zS@ZW*N3PK;pZC%1WTS7MzuD~#KCsujAKA}&Kl0)EN3U;dN|K%_UJU+nwrWjNqjyH< z;OMI2WM1~%a8+?)8v7(~<+p*fEh29BiD8 zb@m@<2PZ3!I16q|7%fD+yzMVUr;L1RojGP~-SV!AmL_MI2Q$VZG%>SpGP2paD`Wn& zj*sm-vh;q@I#0JVZ|@I!Gom1S6oDs#eCO>8F2*%g4X0OD#%UII%VrW8f;Z zuR3P1%QI*k6%LxVGutfB^0RhduVwjbN~XWw_(1-8<0$?0hKkOA_W-+R^n%e{^~>9! zgheX+u>@0Q-(SHW+lOPgFs>yH^Slz5Fy?L+H$gbs9k@NZ%agxWBi~6+XoEhj|>V`tz7=HJw)Cag5C4Olv^jwP3tA)+e|nnI(;|IO~IN<4**aWY9w`2GH zZy>~pn$gveM2H#P?0lUAx&|Az(SycR}KvT015E;Log627o+dR=xY zEZ@BJ46S6X;77kd$v!Wds=r@&iSt~d+SDum3lbX~j^X{;!^6Y1_7@Gmhr6m% z4?z~+S9-WU#j5!SWaF@B;6+agB}HTogmHv*1ztq3-lIG1gCAlHvAtqFucw6cuFLiS zzjXB+$ywRX5y3cbJ>+KC8BdJ<_93h2huC+;ttrut5{{JVVF zo1gvB{=yk5@lvv8FnRj6gVE{R-ie;^?p`YgCnE=ZMHXJQv+z<(zNcMo#YgYdqq%*% zaghBKCkCnCzHE;JAODHf^z5c#3`B{6u7KXUVjr6ok>!(;HL32Q1JcF1S zSum_f`p&^I^@?}nLwOsg#@{QAo?4ymWPMjk{Ym@U3-$PW!?B*eMe+BR-7+iwUip?2 z;_uCm9v6RaL2UA*NB4ToLxsL#!&HgO#-kY5ycm_VzcD6ky;Maj(dh^Dn1=co(8m(F zzhL5KI&+576=p3A2fb2#PNnPqT?^mSJznu#Vt;MxHhk4)XH#22mCL;4zF%(rTPU~Q zg+F$K;Rlswd$K}D|C2Evj;@+cLn-z|KB#q7UQt$F0StEpI{ndb=fxLabWyOqDX_UT z7%6QJwD_aJje#=N5NrvyM;U2^N5{YP(wy-P`--T3MLYe{+Asn)Po`)MYDI zUQ{~wvQO2_D-EqqNdfB-X` z_BcuDhiUP-7(c#al(n8-=zUoegp}IBY8B8dN2pb)tuI3FW${^Z25$fcZe(* zu?|1eUjKT#T(rmXX?qQLH|_oP2=;<5dxM6(6AXJCqiIjq+fLY90j?jW&*u*O%={gJ zy{QPJycj>7zdd-TJ^dVny(O9ewd@qU>pG)&;$p1!_#%(iBO2~kcV4K}u9KBw{8RB` zy37OfX4+d?rPP&11#5dy%XrN2LiOgbDa`yAd$ez+Kwg-h8|`?eHOeQbGsGYzdC;%4 z(DnnlADrdW@>}uFR5ZUA?<}L{Pvf1R@M}JZch;TecuhYAuG|$U*1Yo+ST$#IT6UfS zb+S5>hVjtHlab17aK6tH&ZVG!7=9&qB~Z(2!8;7z;L_g;z6EkM<9J5>JMq2~zte<&7w@|b-i>$tFn>P=?=j@PcpotMZ}DD&2BYmy z#Cs)v+WvIBuQPZB-nZhX^{eo{8^24C7V}q!cl|K^5cmLo+TJaAFF}LU{O`ca!L_|_ zgRe8>kArVD_;cX9z;$}R0`CQ1h_smgAHem)^iP4T1kF;*&jqgpuZN8KtHAX`{WUHg z1m6XH4h7WT2Hp*x5dKY<{(rjoL2xfRSV;5-86RAizW}!M!}N~_?}eOWBGa1%J^+4$ z@MYj$OhlSjf$s*tM&z~NB^dB$3%?P((%`p%cYvQS@}1zj4E{Cn9)mvs&cX2>(cecd z5A*vQ7gxxuekea3d^h52|1SjZ1+RvT<*Rb(*ML`InAt7z^)C5mzy~1bdV%q82QN9% zDbF_;A6(1#fUh&;PlN9?Zv!tyLOT5~yX4;i z?|?jxys$j~<&yuz#a|`IWd3#0=dsUjaBaT`ZB0Kc-&y379eJ5cz8u_Z$k)2$E#SK# z=X#6zyM=NrBsBjA@O1{iAH3V(2f#})m}vc%!MB3nCHCH+9D~E7!iT|o!L|MwX#16? zJA5JdE`whN&c>koR}J_&gEvwx5B(7Z?}mI6-dUbFcqJBQntzdUaOzV2HSivA-JW)X z>xVjzftR2$uf;p{Uj**}*Yn{!jBoJM(AUb(bmWV{cN+W}@BxEw0QaJEZxs7q0M`%G z|CaC-cs~an_xs>I(0>@5`8f!_bGlM@3;!*6`PoW6BK%bJ)dBGNn4_t`5L`dBzY4q* z|E9qsavyj{sgwVkzvgUhpds%<@dcSfd}tF9qKPc{AQAuLLidt5lP4KloN~-M%(}cZ1(1@>{|6 zLwk3Fd*>4z>fc2ECinn2<5E8lW0igwHl2Jv4j%!OF97cVzgc*d zOaFTC0myZIZgRKZt$}ty*`)zpo{+=d?)lv zCH{1b%{>bpdzXOghf%9syvD`bTzspG-{a!7T2;BUE?DfcwJMj^61P^Tzr88k=4%Qx8#({PV&(H)Ag9Xd zw;&U^0&Z%@nOcmeU%uu}#9i(4RfU`g#%oPzgeWzP18Lg!nw5)b+zd#kUzW}aRGK^C z1!}5RCXb!jT}) z@eM76>eKzq(7?ukX)WB;@+A8o#Tk5i{!0Vjl!qHblIKwZQ)4N$5s+-4mSGRqc}Hi zF`KOlH8nU1tXav{-f$BdH}DD{@^5vfbOCS@KDxP1e^YRCy5qrmU~>mM3K}9BwIr@< z2!#uWV$pzaqdycw@r`hYSoLBGBUYogt0f)74z%jU6{f8QmETs<0q}ih0EP@#2(KV~ zP2pGrnk9UJL9Zjs4vGO9?ysn5Y7T|{(e-}xdxg;|){gE0!4kw;RmHf7fp}M#p{^v1 zs)}K7=?L8f|N9m><@ZN0Jm|^}DV+NUn*uJKj!-O8;b^fpG`9NfTxxe9ES4)U(uzA5 zE3T=TGZaP7Qp^z+LNm|O%L?@Q{Ak*eW)P#RK{<9C)EdhT-jpeJTGE|tVBt(I&p3{Y+@PTH=BGQ?}=`FtJr$YdIqAl+YmzRXBg2F$6#4#>9CmO1G8 zd`%l&`N7=T-sq18jMiWqvsPhLLw`xsRru3>t$D(L+#!4scYOvV%5DP+BRS zGqgG_)XO!mZCeEVEXDA!6S2aMIAUW$d)JFYNmfMyfsFE4tCv8tA6?ETTd_zKlY_EJ z@H5V`DxI##>@`aTS2AWyy%01EIMbnOYRH(fjK!0`qoXs7b)jCzsLgKO$Od~AB4u&% z6Vwvhf428j1Umq(n6rluF+x)l=kF! zAy(6tzHVWrhq;rF`kF)jmWZ<7xm4s{4rx0vD_H%8u68Lbl>Btvej3wSiag3rOk%p&5zdJ(Zysb$1jO06bBuTJJfgx*8K4-=vH8zS`h z@0_SNG2hmkOaz}tgx(4w?j(Z3Hwx#s5|r;D;=uQi;E>3t71;7QM8v;bc&lJS@Jk{; zKwO0LbRzOQM1fvM@K)+BEnDeiSX0KMA*4ruv74F z1iJF5$$rdU`X(Df)5hWPM##f{t&SZe#TuE`Q^m0QtO1@N!);YCgCY! zL?ME$zmyn5d4+ES=Alg{1aD_JF0j8sgg+i4ZdU3kBGUVr;3>HKVZ74?&jK>ud?Mmq zN<_X_6A{0Ki1;@PeqQhiA}$Dfg-@Lfz6JM8MCi8?Z$bYO{tyx6KPWsUcpC0@=!Zo_ z`b98C+@RDKh2Jaq3^AhAZ-p1(E{O4#5aFLS!dnIJ0J6My34Vp)DDQWPDDPe(%K0)8 zcHR~|9y0O@Amd*k_(_H%{*^@hZXm*6AtLO2j)-{Q6nt3lDZ#gi@Y`fu&QWi!U=0!e z>lD62@F61ncu;ss@RTzUUWae|h_JIta0Bskm~VvNBlse*PO0AspET8ucRdmMHwpi| z;1k3-O1(z>f>K8$d^WygV0o7lk#3#f4kGIJo5CLvOc7DP$Kmpq`ezAVPDK3%gx@T9 zFA??o-@;!IEIJF}F{REW!pa1Zfrv=ibYr6wT`aUl`Em4X4m4M5iO zM!}mIz6sxe3IAuo?@IWiMAYRo#LY;Dh+om!Hcl5@4y4^G!7CXKyVnsBznutwewGM3 z|3rkHhXj8hcv$eX8IYqKO9X3(&<_g!qu}$zuVS7ReiFuV>UoHW9}wIw;dcq{7yKO& z`71%*XlDTt@mC7g3GN`?jCvRTh+vAi1@%75j(3*e<-}W%zVMp`?;)a{Jtq7)!Mt-2 zj&?hPi1Zf=`iW?_eaj{_23@-aL99Kq{|&g-<=tmX{NepAEzZ zFwY2oLU^z6LBR{>+Im+L5wB734&o*7hwxX4%drk5uE2U1n70S-^YBBw8AQlu6Cs}m zr2G<*-#|p$3=`4DHjDhP$^RYWo`gS2guR1;uK;PMj~se4K5ok|CBoj-MA*9)NIgF} z^x7pnL4>_83*HN)-oKJV@5d58MEpQVL#6f;5%1T;CzX1K_!P!zVBXX4e;N4y;F~t$LG(}J zGl&Pwdlvmd!t)o}dJBoqVO%9bze>XEiHFb*h)DN#BGSD_@H;@J_lV%j4F9Q8uahIc zzb1bk`zMi4DYwI?3C;j=JX}mXjC~aGCG-cumBg2^E+F!qBm{Mws;H|`8V!q5nKJsB#koz`rui#q2YXz?tTqoEh*eVzj +#include +#include +#include +#include +#include +#include + +/* + * The bit operations assume a sign/magnitude representation. (The doc + * seems to indicate this, and this is supported by the fact that libI, + * lip, gmp all work on sign/magnitude representation. Thomas Papanikolaou + * says the contrary, but I think he's not right about this detail.) HB + */ +#define BITOPS_ASSUME_ABS + +/** +** constructors and destructor; we could leave out some of these +**/ + +bigint::bigint() +: I () {} + +bigint::bigint(int i) +: I ((long)i) {} + +bigint::bigint(long l) +: I (l) {} + +bigint::bigint(unsigned long ul) +: I (ul) {} + +bigint::bigint(const cl_I & a) +: I (a) {} + +bigint::bigint(const bigint & a) +: I (a.I) {} + +bigint::~bigint() +{} + +/** +** inline member functions +**/ + +int bigint::bit(unsigned int i) const +{ +#ifdef BITOPS_ASSUME_ABS + if (minusp(I)) + return (int)logbitp(i,-I); + else +#endif + return (int)logbitp(i,I); +} + +lidia_size_t bigint::length() const +{ +#ifdef BITOPS_ASSUME_ABS + if (minusp(I)) + return (integer_length(-I)+intDsize-1)/intDsize; + else +#endif + return (integer_length(I)+intDsize-1)/intDsize; +} + +lidia_size_t bigint::bit_length() const +{ +#ifdef BITOPS_ASSUME_ABS + if (minusp(I)) + return integer_length(-I); + else +#endif + return integer_length(I); +} + +int bigint::sign() const +{ + if (minusp(I)) + return -1; + else if (zerop(I)) + return 0; + else + return 1; +} + +bool bigint::is_positive() const +{ if (!minusp(I)) + if (!zerop(I)) + return (bool)1; + return (bool)0; +} + +bool bigint::is_negative() const +{ return (bool)minusp(I); } + +bool bigint::is_even() const +{ return (bool)evenp(I); } + +bool bigint::is_odd() const +{ return (bool)oddp(I); } + +bool bigint::is_zero() const +{ return (bool)zerop(I); } + +bool bigint::is_gt_zero() const +{ if (!minusp(I)) + if (!zerop(I)) + return (bool)1; + return (bool)0; +} + +bool bigint::is_ge_zero() const +{ return (bool)!minusp(I); } + +bool bigint::is_lt_zero() const +{ return (bool)minusp(I); } + +bool bigint::is_le_zero() const +{ if (!minusp(I)) + if (!zerop(I)) + return (bool)0; + return (bool)1; +} + +bool bigint::is_one() const +{ return (bool)(I == 1); } + + +bool is_odd (const bigint & a) +{ return (bool)oddp(a.I); } + +bool is_even (const bigint & a) +{ return (bool)evenp(a.I); } + +bool is_positive (const bigint & a) +{ + if (!minusp(a.I)) + if (!zerop(a.I)) + return (bool)1; + return (bool)0; +} + +bool is_negative (const bigint & a) +{ return (bool)minusp(a.I); } + +bool is_zero (const bigint & a) +{ return (bool)zerop(a.I); } + +bool is_one (const bigint & a) +{ return (bool)(a.I == 1); } + + + +bool bigint::intify(int & i) const +{ + if (integer_length(I) >= int_bitsize) + return (bool)1; + i = cl_I_to_L(I); + return (bool)0; +} + +bool bigint::longify(long & i) const +{ + if (integer_length(I) >= long_bitsize) + return (bool)1; + i = cl_I_to_long(I); + return (bool)0; +} + +int bigint::abs_compare(const bigint & a) const +{ + return (int)cl_compare(::abs(I),::abs(a.I)); +} + +int bigint::compare(const bigint & a) const +{ + return (int)cl_compare(I,a.I); +} + +unsigned long bigint::most_significant_digit() const +{ + if (zerop(I)) return 0; + cl_I aI = ::abs(I); + return cl_I_to_UL(ldb(aI,cl_byte(intDsize,((integer_length(aI)-1)/intDsize)*intDsize))); +} + +unsigned long bigint::least_significant_digit() const +{ + cl_I aI = ::abs(I); + return cl_I_to_UL(ldb(aI,cl_byte(intDsize,0))); +} + +const double bigint::radix() +{ return ldexp(1.0,intDsize); } + +const int bigint::bits_per_digit() +{ return intDsize; } + +void bigint::absolute_value() +{ if (minusp(I)) { I = -I; } } + +void bigint::abs() +{ if (minusp(I)) { I = -I; } } + +void bigint::negate() +{ I = -I; } + +void bigint::assign_zero() +{ I = 0; } + +void bigint::assign_one() +{ I = 1; } + +void bigint::assign(int i) +{ I = (long)i; } + +void bigint::assign(long i) +{ I = i; } + +void bigint::assign(unsigned long ui) +{ I = ui; } + +void bigint::assign(double d) +{ I = round1((cl_DF)d); } + +void bigint::assign(const bigint & a) +{ I = a.I; } + +void bigint::multiply_by_2() +{ I = ash(I,1); } + +void bigint::divide_by_2() +{ if (minusp(I)) { I = ash(plus1(I),-1); } else { I = ash(I,-1); } } + +/** +** Type checking +**/ + +bool is_char(const bigint & a) +{ if (integer_length(a.I) < char_bitsize) + return (bool)1; + return (bool)0; +} + +bool is_uchar(const bigint & a) +{ if (!minusp(a.I)) + if (integer_length(a.I) <= char_bitsize) + return (bool)1; + return (bool)0; +} + +bool is_short(const bigint & a) +{ if (integer_length(a.I) < short_bitsize) + return (bool)1; + return (bool)0; +} + +bool is_ushort(const bigint & a) +{ if (!minusp(a.I)) + if (integer_length(a.I) <= short_bitsize) + return (bool)1; + return (bool)0; +} + +bool is_int(const bigint & a) +{ if (integer_length(a.I) < int_bitsize) + return (bool)1; + return (bool)0; +} + +bool is_uint(const bigint & a) +{ if (!minusp(a.I)) + if (integer_length(a.I) <= int_bitsize) + return (bool)1; + return (bool)0; +} + +bool is_long(const bigint & a) +{ if (integer_length(a.I) < long_bitsize) + return (bool)1; + return (bool)0; +} + +bool is_ulong(const bigint & a) +{ if (!minusp(a.I)) + if (integer_length(a.I) <= long_bitsize) + return (bool)1; + return (bool)0; +} + +/** +** assignments +**/ + + +int bigint::operator = (int i) +{ I = (long)i; return i; } + +long bigint::operator = (long l) +{ I = l; return l; } + +unsigned long bigint::operator = (unsigned long ul) +{ I = ul; return ul; } + +double bigint::operator = (double d) +{ I = round1((cl_DF)d); return d; } + +bigint & bigint::operator = (const bigint & a) +{ I = a.I; return *this; } + +/** +** comparisons +**/ + +bool operator == (const bigint & a, const bigint & b) +{ return (bool)(a.I == b.I); } + +bool operator != (const bigint & a, const bigint & b) +{ return (bool)(a.I != b.I); } + +bool operator > (const bigint & a, const bigint & b) +{ return (bool)(a.I > b.I); } + +bool operator >= (const bigint & a, const bigint & b) +{ return (bool)(a.I >= b.I); } + +bool operator < (const bigint & a, const bigint & b) +{ return (bool)(a.I < b.I); } + +bool operator <= (const bigint & a, const bigint & b) +{ return (bool)(a.I <= b.I); } + +/** +** operator overloading +**/ + +bigint operator - (const bigint & a) +{ return bigint(-a.I); } + +bigint operator + (const bigint & a, const bigint & b) +{ return bigint(a.I + b.I); } + +bigint operator - (const bigint & a, const bigint & b) +{ return bigint(a.I - b.I); } + +bigint operator * (const bigint & a, const bigint & b) +{ return bigint(a.I * b.I); } + +bigint operator / (const bigint & a, const bigint & b) +{ return bigint(truncate1(a.I,b.I)); } + +bigint operator % (const bigint & a, const bigint & b) +{ return bigint(rem(a.I,b.I)); } + +bigint operator << (const bigint & a, long ui) +{ + if (ui < 0) + lidia_error_handler("bigint", "operator<<::index is negative."); + return bigint(ash(a.I,(cl_I)ui)); +} + +bigint operator >> (const bigint & a, long ui) +{ + if (ui < 0) + lidia_error_handler("bigint", "operator>>::index is negative."); + return bigint(ash(a.I,-(cl_I)ui)); +} + +bigint operator & (const bigint & a, const bigint & b) +{ return bigint(logand(a.I,b.I)); } + +bigint operator | (const bigint & a, const bigint & b) +{ return bigint(logior(a.I,b.I)); } + +bigint operator ^ (const bigint & a, const bigint & b) +{ return bigint(logxor(a.I,b.I)); } + +bigint & bigint::operator += (const bigint & a) +{ I = I + a.I; return *this; } + +bigint & bigint::operator -= (const bigint & a) +{ I = I - a.I; return *this; } + +bigint & bigint::operator *= (const bigint & a) +{ I = I * a.I; return *this; } + +bigint & bigint::operator /= (const bigint & a) +{ I = truncate1(I,a.I); return *this; } + +bigint & bigint::operator %= (const bigint & a) +{ I = rem(I,a.I); return *this; } + +bigint & bigint::operator <<= (long ui) +{ + if (ui < 0) + lidia_error_handler("bigint", "operator<<=::index is negative."); + I = ash(I,(cl_I)ui); + return *this; +} + +bigint & bigint::operator >>= (long ui) +{ + if (ui < 0) + lidia_error_handler("bigint", "operator>>=::index is negative."); + I = ash(I,-(cl_I)ui); + return *this; +} + +bigint & bigint::operator &= (const bigint & a) +{ I = logand(I,a.I); return *this; } + +bigint & bigint::operator |= (const bigint & a) +{ I = logior(I,a.I); return *this; } + +bigint & bigint::operator ^= (const bigint & a) +{ I = logxor(I,a.I); return *this; } + +bigint & bigint::operator++ () +{ I = plus1(I); return *this; } + +bigint & bigint::operator-- () +{ I = minus1(I); return *this; } + +bigint bigint::operator++ (int) +{ bigint a = *this; I = plus1(I); return a; } + +bigint bigint::operator-- (int) +{ bigint a = *this; I = minus1(I); return a; } + +int bigint::operator ! () const +{ return (int)zerop(I); } + +bigint bigint::operator ~ () const +{ return bigint(lognot(I)); } + +/** +** Procedural versions +**/ + +void negate(bigint & a, const bigint & b) +{ a.I = -b.I; } + +void add(bigint & c, const bigint & a, const bigint & b) +{ c.I = a.I + b.I; } + +void subtract(bigint & c, const bigint & a, const bigint & b) +{ c.I = a.I - b.I; } + +void multiply(bigint & c, const bigint & a, const bigint & b) +{ c.I = a.I * b.I; } + +void divide(bigint & c, const bigint & a, const bigint & b) +{ c.I = truncate1(a.I,b.I); } + +void remainder(bigint & c, const bigint & a, const bigint & b) +{ c.I = rem(a.I,b.I); } + +void div_rem(bigint & q, bigint & r, const bigint & a, const bigint & b) +{ + cl_I_div_t q_r = truncate2(a.I,b.I); + q.I = q_r.quotient; + r.I = q_r.remainder; +} + +void invert(bigint & a, const bigint & b) +{ + if ((b.I == 1) || (b.I == -1)) + a.I = b.I; + else + lidia_error_handler("bigint", "invert::inverting of a non-unit."); +} + +void shift_left(bigint & c, const bigint & a, long ui) +{ + if (ui < 0) + lidia_error_handler("bigint", "shift_left()::index is negative."); + c.I = ash(a.I,(cl_I)ui); +} + +void shift_right(bigint & c, const bigint & a, long ui) +{ + if (ui < 0) + lidia_error_handler("bigint", "shift_right()::index is negative."); + c.I = ash(a.I,-(cl_I)ui); +} + +void power(bigint & c, const bigint & a, const bigint & b) +{ + if ((a.I == 1) || (a.I == -1)) + { + if (b.is_odd()) + c.I = a.I; + else + c.assign_one(); + } + else if (b.is_negative()) + c.assign_zero(); + else if (b.is_zero()) + c.assign_one(); + else + c.I = expt_pos(a.I,b.I); +} + +void power(bigint & c, const bigint & a, long i) +{ + if ((a.I == 1) || (a.I == -1)) + { + if (i&1) + c.I = a.I; + else + c.assign_one(); + } + else if (i < 0) + c.assign_zero(); + else if (i == 0) + c.assign_one(); + else + c.I = expt_pos(a.I,(cl_I)i); +} + +void and(bigint & c, const bigint & a, const bigint & b) +{ c.I = logand(a.I,b.I); } + +void or(bigint & c, const bigint & a, const bigint & b) +{ c.I = logior(a.I,b.I); } + +void xor(bigint & c, const bigint & a, const bigint & b) +{ c.I = logxor(a.I,b.I); } + +void not(bigint & b, const bigint & a) +{ b.I = lognot(a.I); } + +void inc(bigint & c) +{ c.I = plus1(c.I); } + +void dec(bigint & c) +{ c.I = minus1(c.I); } + +void add(bigint & c, const bigint & a, long i) +{ c.I = a.I + i; } + +void subtract(bigint & c, const bigint & a, long i) +{ c.I = a.I - i; } + +void multiply(bigint & c, const bigint & a, long i) +{ c.I = a.I * i; } + +void divide(bigint & c, const bigint & a, long i) +{ c.I = truncate1(a.I,i); } + +void remainder(long &r, const bigint & a, long i) +{ + r = cl_I_to_long(rem(a.I,i)); +} + +long remainder(const bigint & a, long i) +{ + return cl_I_to_long(rem(a.I,i)); +} + +void div_rem(bigint & q, long &r, const bigint & a, long i) +{ + cl_I_div_t q_r = truncate2(a.I,i); + q.I = q_r.quotient; + r = cl_I_to_long(q_r.remainder); +} + +/** +** gcd's +**/ + +bigint gcd(const bigint & a, const bigint & b) +{ return bigint(gcd(a.I,b.I)); } + +bigint bgcd(const bigint & a, const bigint & b) +{ return bigint(gcd(a.I,b.I)); } + +bigint dgcd(const bigint & a, const bigint & b) +{ return bigint(gcd(a.I,b.I)); } + +bigint xgcd(bigint & u, bigint & v, const bigint & a, const bigint & b) +{ +#if 0 + // In the case abs(a) == abs(b), LiDIA wants to have u=0, abs(v)=1. + // But CLN returns abs(u)=1, v=0. Therefore we swap the arguments. + return bigint(xgcd(b.I,a.I,&v.I,&u.I)); +#else + // I think the above special case is unimportant, and it's more important + // to be consistent with xgcd_left and xgcd_right below. + return bigint(xgcd(a.I,b.I,&u.I,&v.I)); +#endif +} + +bigint xgcd_left(bigint & u, const bigint & a, const bigint & b) +{ cl_I v; return bigint(xgcd(a.I,b.I,&u.I,&v)); } + +bigint xgcd_right(bigint & v, const bigint & a, const bigint & b) +{ cl_I u; return bigint(xgcd(a.I,b.I,&u,&v.I)); } + +/** +** functions +**/ + +bigint abs(const bigint & a) +{ return bigint(abs(a.I)); } + +void seed(const bigint & a) +{ + cl_default_random_state.seed.lo = cl_I_to_UL(ldb(a.I,cl_byte(32,0))); + cl_default_random_state.seed.hi = cl_I_to_UL(ldb(a.I,cl_byte(32,32))); +} + +void bigint::randomize(const bigint & a) +{ + if (minusp(a.I)) + *this = bigint(-random_I(-a.I)); + else + *this = bigint(random_I(a.I)); +} + +bigint randomize(const bigint & a) +{ + if (minusp(a.I)) + return bigint(-random_I(-a.I)); + else + return bigint(random_I(a.I)); +} + +double dbl(const bigint & a) +{ return cl_double_approx(a.I); } + +xdouble xdbl(const bigint & a) +{ + double d1 = dbl(a); + bigint a1; a1.assign(d1); + double d2 = dbl(a - a1); + return (xdouble)d1 + (xdouble)d2; +} + +void sqrt(bigint & a, const bigint & b) +{ a.I = isqrt(b.I); } + +void square(bigint & a, const bigint & b) +{ a.I = square(b.I); } + +void swap(bigint & a, bigint & b) +{ + void* tmp = a.I.pointer; + a.I.pointer = b.I.pointer; + b.I.pointer = tmp; +} + +/** +** input / output +**/ + +istream & operator >> (istream & in, bigint & a) +{ + a.scan (in); + return (in); +} + +ostream & operator << (ostream & out, const bigint & a) +{ out << a.I; return out; } + +int string_to_bigint(const char *s, bigint & a) +{ + int n = strlen(s); + char c[n+1]; + for (int i = 0; i < n; i++) + switch (s[i]) + { + case '+': case '-': case '.': + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': + case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': + case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': + case 'V': case 'W': case 'X': case 'Y': case 'Z': + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': + case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': + case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': + case 'v': case 'w': case 'x': case 'y': case 'z': + c[i] = s[i]; break; + default: + c[i] = '\0'; goto eos; + } + c[n] = '\0'; +eos: + n = strlen(c); + if (n == 0) return -1; + a = (bigint)(cl_I)c; return n; +} + +int bigint_to_string(const bigint & a, char *s) +{ + char* r = print_integer_to_string(10,a.I); + strcpy(s,r); + cl_free_hook(r); + return strlen(s); +} + +/** +** using fread/fwrite +**/ + +void bigint::read_from_file(FILE * fp) +{ + scan_from_file(fp); + int c = getc(fp); if (c != EOF && c != '\n') { ungetc(c,fp); } +} + +void bigint::write_to_file(FILE * fp) +{ + print_to_file(fp); + putc('\n',fp); +} + +/** +** using fscanf/fprintf +**/ + +void bigint::scan_from_file(FILE * fp) +{ + cl_spushstring buffer; + int c; + while ((c = getc(fp)) != EOF) + if (!(c=='\n' || c=='\t' || c==' ')) + { ungetc(c,fp); break; } + while ((c = getc(fp)) != EOF) { + switch (c) + { case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case '+': case '-': + buffer.push((char)c); break; + default: + ungetc(c,fp); goto end; + } + } +end: + char* s = buffer.contents(); + if (s[0] != '\0') + I = (cl_I)s; + cl_free_hook(s); +} + +void bigint::print_to_file(FILE * fp) +{ + char* s = print_integer_to_string(10,I); + fprintf(fp,"%s",s); + cl_free_hook(s); +} + +/** +** Error handler +**/ + +void cl_abort (void) +{ + lidia_error_handler("cln", "cl_abort() called"); +} + diff --git a/lidia-interface/src/interfaces/integers/cln/bigint_def.h b/lidia-interface/src/interfaces/integers/cln/bigint_def.h new file mode 100644 index 0000000..7d8df91 --- /dev/null +++ b/lidia-interface/src/interfaces/integers/cln/bigint_def.h @@ -0,0 +1,40 @@ +// +// LiDIA - a library for computational number theory +// Copyright (c) 1996 by the LiDIA Group +// +// File : bigint_def.h +// Author : Bruno Haible (HB) +// Last change : HB, 1996-11-17, initial version +// HB, 1998-01-24, change #include to #include "cl_*" +// because the files are in $(LIDIA_HOME)/include/LiDIA, +// and the only -I option is -I$(LIDIA_HOME)/include . +// + +#ifndef LIDIA_BIGINT_DEF_H +#define LIDIA_BIGINT_DEF_H + +/** +** The next include MUST remain in this file in THIS position. +**/ + +#include + +/** +** include here the include file of the C multiple precision integers +** and define integer_type_name to be the integer type we have. Define +** base_digit to +** +** For example write something like +** +** #include "integer_include_file.h" +** #define integer_type_name your_integer_type_name +** +**/ + +#include +#include + +#define integer_type_name cl_I +#define base_digit uintD + +#endif diff --git a/lidia-interface/src/interfaces/integers/cln/makefile b/lidia-interface/src/interfaces/integers/cln/makefile new file mode 100644 index 0000000..20c250c --- /dev/null +++ b/lidia-interface/src/interfaces/integers/cln/makefile @@ -0,0 +1,69 @@ +###################################################################### +# +# Name ................... LiDIA/src/interfaces/integers/cln/makefile +# +# Architecture : unix +# Compiler : gcc, g++ +# Flags : -g -O2 +# Program Flags: +# Author : Thomas Papanikolaou & Bruno Haible +# Release : 1.0 +# Last Change : 1998-01-24 +# Copyright : by the University of Saarland and Bruno Haible, 1996 +# + +# +# include the configuration file +# + +include ../../../../config/CONFIG + +# +# Object +# + +OBJ=bigint.o + +# +# Rules +# + +all: copyh $(libp)LiDIA.a + +appl: bigint_appl$(EXE) + +# +# Dependencies +# + +copyh: + $(CP) bigint_def.h $(LIDIA_HOME)$(DIRSEP)include$(DIRSEP)LiDIA + +bigint.o: bigint.c $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)bigint.h + $(CXX) -c $(CXXFLAGS) -I$(LIDIA_INC) -I$(LIDIA_HOME)$(DIRSEP)src$(DIRSEP)kernel$(DIRSEP)integers$(DIRSEP)cln$(DIRSEP)cln$(DIRSEP)include -I$(LIDIA_HOME)$(DIRSEP)src$(DIRSEP)kernel$(DIRSEP)integers$(DIRSEP)cln $*.c -o $(objp)$*.o + $(NOOMV) $*.o $(objp)$*.o + $(TOUCH) $*.o + +$(libp)LiDIA.a: $(OBJ) + -$(AR) $(LIDIA_LIB)$(DIRSEP)$(libp)LiDIA.a $(objp)*.o + +ranlib: + $(RANLIB) $(LIDIA_LIB)$(DIRSEP)$(libp)LiDIA.a + +bigint_appl$(EXE): bigint_appl.c + $(CXX) $(CXXFLAGS) bigint_appl.c $(CXX-off) -I$(LIDIA_INC) -L$(LIDIA_LIB) -o bigint_appl$(EXE) $(LIB) + -$(MV) bigint_appl$(EXE) $(LIDIA_BIN) + +# +# Clean +# + +clean: + -$(RM) *.o + +veryclean: clean + -$(RM) bigint_appl$(EXE) + +# +# End Of Makefile +# diff --git a/lidia-interface/src/kernel/integers/cln/README b/lidia-interface/src/kernel/integers/cln/README new file mode 100644 index 0000000..3c6799f --- /dev/null +++ b/lidia-interface/src/kernel/integers/cln/README @@ -0,0 +1,17 @@ +LiDIA has an abstract interface to the underlying long integer implementation. +Using CLN instead of the default libI, lip or gmp has the following +advantages: + + - Maximum speed on all CPUs, since CLN is based on the highly + optimized gmp-2.0.2. + + - Very large integers profit from CLN's Schönhage-Strassen FFT multiplication + (asymptotic bit complexity: O(N log N log log N)). + + - Copying integers is fast: no copying is actually involved, only a + reference count is manipulated. + + - Small integers (absolute value < 2^29) are represented immediately, + thus no memory allocation/deallocation is involved when dealing with + small integers. + diff --git a/lidia-interface/src/kernel/integers/cln/cln/README.LiDIA b/lidia-interface/src/kernel/integers/cln/cln/README.LiDIA new file mode 100644 index 0000000..3b1756e --- /dev/null +++ b/lidia-interface/src/kernel/integers/cln/cln/README.LiDIA @@ -0,0 +1,6 @@ +This directory contains a special version of CLN, trimmed down for LiDIA. +It was prepared from CLN version 1.0, found on ftp://ftp.santafe.edu/pub/gnu/, +by + 1. removing many unnecessary files (including many source files, the test + suite and the documentation), + 2. adding the file README.LiDIA diff --git a/lidia-interface/src/kernel/integers/cln/makefile b/lidia-interface/src/kernel/integers/cln/makefile new file mode 100755 index 0000000..4d4462e --- /dev/null +++ b/lidia-interface/src/kernel/integers/cln/makefile @@ -0,0 +1,178 @@ +###################################################################### +# +# Name ............................... LiDIA/src/kernel/cln/makefile +# +# Architecture : unix +# Compiler : gcc, g++ +# Flags : -g -O2 -fno-exceptions +# Program Flags: +# Author : Markus Maurer, Bruno Haible +# Release : 1.0 +# Last Change : 1998-12-13 +# Copyright : by the University of Saarland and Bruno Haible, 1998 +# + +# +# include the configuration file +# + +include ../../../../config/CONFIG + +# +# Dependencies +# + + +default: library + +c: library + +sparc: library + +sparc7: library + +sparc8: library + +mips: library + +i386: library + +i486: library + +i586: library + +i686: library + +hppa1.1: library + + + + +# +# library and application files +# + +library: cln$(DIRSEP)include$(DIRSEP)cl_config.h cln$(DIRSEP)include$(DIRSEP)cl_intparam.h + cd cln$(DIRSEP)gmp $(SEP) $(MAKE) mpn/libmpn.la mp_clz_tab.lo + cd cln$(DIRSEP)src $(SEP) $(MAKE) + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_abort.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_complex_class.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_config.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_dfloat.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_dfloat_class.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_ffloat.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_ffloat_class.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_float.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_float_class.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_floatformat.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_floatparam.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_input.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_integer.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_integer_class.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_integer_io.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_intparam.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_io.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_lfloat.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_lfloat_class.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_malloc.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_modules.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_number.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_number_io.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_object.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_output.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_random.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_rational_class.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_real_class.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_sfloat_class.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_string.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_types.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)src$(DIRSEP)base$(DIRSEP)cl_spushstring.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)src$(DIRSEP)base$(DIRSEP)cl_sstring.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)gmp$(DIRSEP)gmp.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)gmp$(DIRSEP)gmp-impl.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)gmp$(DIRSEP)longlong.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)gmp$(DIRSEP)mpn$(DIRSEP)gmp-mparam.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + $(SHELL) cln$(DIRSEP)libtool --mode=install cp cln$(DIRSEP)src$(DIRSEP)libcln.la `pwd`$(DIRSEP)libcln.la + $(ARX) libcln.a + $(AR) $(LIDIA_LIB)$(DIRSEP)$(libp)LiDIA.a *.o + $(RM) *.o + $(RM) libcln.a + $(TOUCH) library + + +ranlib: + $(RANLIB) $(LIDIA_LIB)$(DIRSEP)$(libp)LiDIA.a + +appl: +# cd cln $(SEP) $(MAKE) check + + + +# +# Configuration command +# + + +configure: + cd cln $(SEP) CC="$(CC)" CFLAGS="$(CFLAGS) -fno-exceptions" CXX="$(CXX)" CXXFLAGS="$(CXXFLAGS) -fno-exceptions" .$(DIRSEP)configure --target=$(LIDIA_ARCH) + + + +# +# Installation commands +# + +install: installh + +installh: + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_abort.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_complex_class.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_config.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_dfloat.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_dfloat_class.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_ffloat.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_ffloat_class.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_float.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_float_class.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_floatformat.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_floatparam.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_input.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_integer.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_integer_class.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_integer_io.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_intparam.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_io.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_lfloat.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_lfloat_class.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_malloc.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_modules.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_number.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_number_io.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_object.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_output.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_random.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_rational_class.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_real_class.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_sfloat_class.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_string.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)include$(DIRSEP)cl_types.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)src$(DIRSEP)base$(DIRSEP)cl_spushstring.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)src$(DIRSEP)base$(DIRSEP)cl_sstring.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)gmp$(DIRSEP)gmp.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)gmp$(DIRSEP)gmp-impl.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)gmp$(DIRSEP)longlong.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + -$(CP) cln$(DIRSEP)gmp$(DIRSEP)mpn$(DIRSEP)gmp-mparam.h $(LIDIA_INC)$(DIRSEP)LiDIA$(DIRSEP)kernel + + +# +# Clean +# + +clean: + -cd cln $(SEP) make clean + -$(RM) library + + +veryclean: clean + + diff --git a/src/Makefile.devel b/src/Makefile.devel new file mode 100644 index 0000000..6f1e057 --- /dev/null +++ b/src/Makefile.devel @@ -0,0 +1,16 @@ +# This is the developer's makefile, not the user's makefile. +# Don't use it unless you know exactly what you do! + + +# Some important programs: +SHELL = /bin/sh +MAKE = make + + +SUBMAKEFILES := $(shell find . -name Makefile.devel) + +all : force + for file in $(SUBMAKEFILES); do dir=`dirname $$file`; if test "$$dir" != "."; then (cd $$dir; $(MAKE) -f Makefile.devel) ; fi ; done + + +force : diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 0000000..9079d66 --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,240 @@ +# Makefile for cln/src + +#### Start of system configuration section. #### + +# Directories used by "make": +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ + +# Directories used by "make install": +prefix = @prefix@ +local_prefix = /usr/local +exec_prefix = @exec_prefix@ +datadir = @datadir@ +libdir = @libdir@ +includedir = @includedir@ +mandir = @mandir@ + +# Programs used by "make": +# C compiler +CC = @CC@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +# C++ compiler +CXX = @CXX@ +CXXFLAGS = @CXXFLAGS@ +CXXCPP = @CXXCPP@ +INCLUDES = -I../include -I$(top_srcdir)/include +GMP_INCLUDES = @GMP_INCLUDES@ +CPPFLAGS += $(INCLUDES) +LIBTOOL = @LIBTOOL@ +LIBTOOL_COMPILE = $(LIBTOOL) --mode=compile +LIBTOOL_LINK = $(LIBTOOL) --mode=link +LIBTOOL_INSTALL = $(LIBTOOL) --mode=install +LIBTOOL_UNINSTALL = $(LIBTOOL) --mode=uninstall +AR = ar +AR_FLAGS = rc +RANLIB = @RANLIB@ +MV = mv +LN = ln +RM = rm -f +@SET_MAKE@ + +# Programs used by "make install": +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ + +#### End of system configuration section. #### + +SHELL = /bin/sh + +# Needed by $(LIBTOOL). +top_builddir = .. + +# When this Makefile is called with SUBDIR=some_subdirectory, it builds +# only the object files belonging to sources in that subdirectory. The +# final library is built only if SUBDIR=. +SUBDIR = . + +# Define the search path for sources. +# The ":" below keeps config.status from removing this line. +VPATH = $(srcdir)/$(SUBDIR) # : + +# Add subdirectory specific flags. +include $(srcdir)/$(SUBDIR)/Makeflags +CPPFLAGS += $(SUBDIR_INCLUDES) + +# Need to know the system name. +SYSTEM := $(shell uname -s) + +FILES_CC := $(notdir $(wildcard $(srcdir)/$(SUBDIR)/*.cc)) +FILES_CC := $(filter-out %.i.cc, $(FILES_CC)) +ASMFILES_CC := $(patsubst cl_asm_@host_cpu@_%.cc,cl_asm_%.cc, $(filter cl_asm_@host_cpu@_%.cc, $(FILES_CC))) +FILES_CC := $(filter-out cl_asm_%.cc, $(FILES_CC)) + +FILES_I_CC := $(patsubst %.cc,%.i.cc,$(FILES_CC)) + +FILES_S := $(patsubst %.cc,%.s,$(FILES_CC)) + +FILES_LO := $(patsubst %.cc,%.lo,$(FILES_CC)) + +ASMFILES_S := $(patsubst %.cc,%.s,$(ASMFILES_CC)) + +ASMFILES_LO := $(patsubst %.cc,%.lo,$(ASMFILES_CC)) + +OBJECTS_LO = $(FILES_LO) $(ASMFILES_LO) + +SUBDIRS := $(patsubst $(srcdir)/%/.,%,$(wildcard $(srcdir)/$(SUBDIR)/*/.)) +# Avoid certain subdirectories: +# private/ and old/ don't contain valid sources, +# CVS/ and RCS/ are created when people put the sources under version control, +# ii_files/ is created during "make" by SGI C++. +SUBDIRS := $(filter-out old ./old private ./private CVS %/CVS RCS %/RCS ii_files ./ii_files,$(SUBDIRS)) + +SUBDIRS_TARGET := $(patsubst %,%.target,$(SUBDIRS)) +SUBDIRS_DIRDEP := $(patsubst %,%.dirdep,$(SUBDIRS)) + +ifeq ($(SUBDIR),.) +ALLFILES_CC := $(notdir $(wildcard $(srcdir)/*.cc) $(foreach subdir,$(SUBDIRS), $(wildcard $(srcdir)/$(subdir)/*.cc) $(wildcard $(srcdir)/$(subdir)/*/*.cc) $(wildcard $(srcdir)/$(subdir)/*/*/*.cc))) +ALLFILES_CC := $(filter-out %.i.cc, $(ALLFILES_CC)) +ALLASMFILES_CC := $(patsubst cl_asm_@host_cpu@_%.cc,cl_asm_%.cc, $(filter cl_asm_@host_cpu@_%.cc, $(ALLFILES_CC))) +ALLFILES_CC := $(filter-out cl_asm_%.cc, $(ALLFILES_CC)) +ALLFILES_LO := $(patsubst %.cc,%.lo,$(ALLFILES_CC)) +ALLASMFILES_LO := $(patsubst %.cc,%.lo,$(ALLASMFILES_CC)) +ALLOBJECTS_LO = $(ALLFILES_LO) $(ALLASMFILES_LO) + +all : $(OBJECTS_LO) $(SUBDIRS_TARGET) libcln.la +else +all : $(OBJECTS_LO) $(SUBDIRS_TARGET) +endif + +alls : $(FILES_S) $(ASMFILES_S) + +allo : $(FILES_LO) $(ASMFILES_LO) + +ASMFLAGS := +ifeq (@AS_UNDERSCORE@,true) +ASMFLAGS += -DUNDERSCORE +endif + +# Rules for normal compilation. + +%.lo : %.c + $(LIBTOOL_COMPILE) $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< + +%.lo : %.cc + $(LIBTOOL_COMPILE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< + +# Rules for normal compilation, only needed for debugging. + +%.s : %.c + $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -S $< -o $@ + +%.s : %.cc + $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -S $< -o $@ + +# Rules for preprocessing. + +%.i : %.c + $(CPP) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) $< > $@ + +%.i.cc : %.cc + $(CXXCPP) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) $< > $@ + +# Rules for assembly language files, + +ifneq ($(ASMFILES_LO),) + +ifneq ($(filter @host_cpu@,sparc sparc64),) +$(ASMFILES_S) : %.s : %.cc + $(CXXCPP) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) $(ASMFLAGS) $< | grep -v '^#' | grep -v '^ *#line' | sed -e 's/\([.%]\) /\1/g' -e 's/ , /,/g' -e 's/ :/:/g' -e 's/\$$/#/g' > $@ +else +ifeq (@host_cpu@,m68k) +$(ASMFILES_S) : %.s : %.cc +ifeq (@AS_UNDERSCORE@,true) + $(CXXCPP) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -P $(ASMFLAGS) $< | sed -e 's/\\#/#/g' -e 's/\$$//g' > $@ +else + $(CXXCPP) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -P $(ASMFLAGS) $< | sed -e 's/\\#/#/g' -e 's/\$$/%/g' > $@ +endif +else +ifeq (@host_cpu@,hppa) +$(ASMFILES_S) : %.s : %.cc + -$(CXXCPP) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -P $(ASMFLAGS) $< > $@ +else +$(ASMFILES_S) : %.s : %.cc + $(CXXCPP) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -P $(ASMFLAGS) $< > $@ +endif +endif +endif + +ifeq (@host_cpu@,hppa) +# Only the native as groks the .SHORTDATA statements +$(ASMFILES_LO) : %.lo : %.s + $(LIBTOOL_COMPILE) $(CC) $(CFLAGS) $(TARGET_ARCH) -c $< \ + || COMPILER_PATH=/usr/ccs/bin $(LIBTOOL_COMPILE) $(CC) $(CFLAGS) $(TARGET_ARCH) -c $< \ + || COMPILER_PATH=/bin $(LIBTOOL_COMPILE) $(CC) $(CFLAGS) $(TARGET_ARCH) -c $< +else +$(ASMFILES_LO) : %.lo : %.s + $(LIBTOOL_COMPILE) $(CC) $(CFLAGS) $(TARGET_ARCH) -c $< +endif + +endif + + +# Recurse into subdirectories +$(SUBDIRS_TARGET) : %.target : %.dirdep + $(MAKE) SUBDIR=$* + +$(SUBDIRS_DIRDEP) : %.dirdep : + + +ifeq ($(SUBDIR),.) + +../gmp/mpn/libmpn.la : $(LIBTOOL) + cd ../gmp && $(MAKE) mpn/libmpn.la mp_clz_tab.lo + + +libcln.la : $(LIBTOOL) $(ALLOBJECTS_LO) @GMP_OBJDEPS@ + $(LIBTOOL_LINK) $(CC) -o libcln.la -rpath $(libdir) $(ALLOBJECTS_LO) @GMP_OBJS@ + +install : all force + if [ ! -d $(libdir) ] ; then mkdir $(libdir) ; fi + $(LIBTOOL_INSTALL) $(INSTALL_DATA) libcln.la $(libdir)/libcln.la + if [ ! -d $(includedir) ] ; then mkdir $(includedir) ; fi + $(INSTALL_DATA) $(top_srcdir)/include/*.h $(includedir) + $(INSTALL_DATA) ../include/*.h $(includedir) +# if [ ! -d $(mandir) ] ; then mkdir $(mandir) ; fi +# if [ ! -d $(mandir)/man3 ] ; then mkdir $(mandir)/man3 ; fi +# if [ ! -d $(datadir) ] ; then mkdir $(datadir) ; fi +# if [ ! -d $(datadir)/html ] ; then mkdir $(datadir)/html ; fi + +installdirs : force + if [ ! -d $(libdir) ] ; then mkdir $(libdir) ; fi + if [ ! -d $(includedir) ] ; then mkdir $(includedir) ; fi +# if [ ! -d $(mandir) ] ; then mkdir $(mandir) ; fi +# if [ ! -d $(mandir)/man3 ] ; then mkdir $(mandir)/man3 ; fi +# if [ ! -d $(datadir) ] ; then mkdir $(datadir) ; fi +# if [ ! -d $(datadir)/html ] ; then mkdir $(datadir)/html ; fi + +uninstall : force + $(LIBTOOL_UNINSTALL) $(RM) $(libdir)/libcln.la + $(RM) $(addprefix $(includedir)/, $(notdir $(wildcard $(top_srcdir)/include/*.h))) + $(RM) $(addprefix $(includedir)/, $(notdir $(wildcard ../include/*.h))) + +check : all + +mostlyclean : clean + +clean : force + $(RM) *.s *.o *.lo *.a *.la core + $(RM) -r .libs _libs + +distclean : clean + $(RM) config.status config.log config.cache Makefile + +maintainer-clean : distclean + +endif + +force : diff --git a/src/Makeflags b/src/Makeflags new file mode 100644 index 0000000..4b0afee --- /dev/null +++ b/src/Makeflags @@ -0,0 +1,3 @@ +# This file contains additional flags for the main Makefile. + +SUBDIR_INCLUDES = diff --git a/src/Makerules.devel b/src/Makerules.devel new file mode 100644 index 0000000..2d68ac0 --- /dev/null +++ b/src/Makerules.devel @@ -0,0 +1,10 @@ +# Common rules for the developer's makefiles. + + +# Some important programs: +SHELL = /bin/sh +MAKE = make + +# Other programs: +DIGIT_HEADER = $(SRCDIR)/base/digitseq/digit_header + diff --git a/src/TUNING b/src/TUNING new file mode 100644 index 0000000..98da294 --- /dev/null +++ b/src/TUNING @@ -0,0 +1,50 @@ +Tips for performance tuning on a specific architecture: + +1. Choose the optimal limb size (intDsize). This is fundamental. On 32-bit + platforms intDsize=32 is best. On 64-bit platforms intDsize=64 may be + better, especially if there is a 64x64-bit multiplication in hardware. + +2. Tune GMP. + +3. The break-even points between several algorithms for the same task + have to be determined experimentally. + + multiplication: + cl_DS_mul.cc karatsuba_threshold + cl_DS_mul.cc function cl_fftm_suitable + division: + cl_DS_div.cc function cl_recip_suitable + 2-adic reciprocal: + cl_2DS_recip.cc recip2adic_threshold + 2-adic division: + cl_2DS_div.cc function cl_recip_suitable + square root: + cl_DS_sqrt.cc function cl_recipsqrt_suitable + cl_LF_sqrt.cc "if (len > ...)" + gcd: + cl_I_gcd.cc cl_gcd_double_threshold + binary->decimal conversion: + cl_I_to_digits.cc cl_digits_div_threshold + pi: + cl_LF_pi.cc best of 4 algorithms + exp, log: + cl_F_expx.cc factor limit_slope of isqrt(d) + cl_R_exp.cc inside function exp + cl_R_ln.cc inside function ln + eulerconst: + cl_LF_eulerconst.cc function compute_eulerconst + sin, cos, sinh, cosh: + cl_F_sinx.cc factor limit_slope of isqrt(d) + cl_R_sin.cc inside function sin + cl_R_cos.cc inside function cos + cl_R_cossin.cc inside function cl_cos_sin + cl_F_sinhx.cc factor limit_slope of isqrt(d) + cl_R_sinh.cc inside function sinh + cl_R_cosh.cc inside function cosh + cl_R_coshsinh.cc inside function cl_cosh_sinh + cl_F_atanx.cc factor limit_slope of isqrt(d) + cl_F_atanx.cc inside function atanx + cl_F_atanhx.cc factor limit_slope of isqrt(d) + cl_F_atanhx.cc inside function atanhx + + diff --git a/src/base/Makeflags b/src/base/Makeflags new file mode 100644 index 0000000..2aab5c6 --- /dev/null +++ b/src/base/Makeflags @@ -0,0 +1,3 @@ +# This file contains additional flags for the main Makefile. + +SUBDIR_INCLUDES = -I$(srcdir)/base diff --git a/src/base/cl_N.h b/src/base/cl_N.h new file mode 100644 index 0000000..7969961 --- /dev/null +++ b/src/base/cl_N.h @@ -0,0 +1,21 @@ +// cl_N internals + +#ifndef _CL_N_H +#define _CL_N_H + +#include "cl_number.h" +#include "cl_macros.h" + +nonreturning_function(extern, cl_error_division_by_0, (void)); +nonreturning_function(extern, cl_as_error, (const cl_number& obj, const char * typestring, const char * filename, int line)); + +// For the equal-invariant hashcode, we take a mixture of exponent, length +// and the most significant 32 bits. To ensure that equal(x,y) implies +// equal_hashcode(x) == equal_hashcode(y) we must make sure that +// equal_hashcode(rational(x)) == equal_hashcode(x) and +// equal_hashcode(0.0) = 0 (important because of equal(complex(x,0.0),x)). + #define equal_hashcode_low(msd,exp,sign) \ + (((((uint32)(msd) << 7) | ((uint32)(msd) >> 25)) ^ ((sint32)(sign) << 30)) + (uintL)(exp)) + #define equal_hashcode_one equal_hashcode_low(bit(31),1,0) + +#endif /* _CL_N_H */ diff --git a/src/base/cl_N_err_d0.cc b/src/base/cl_N_err_d0.cc new file mode 100644 index 0000000..7da2194 --- /dev/null +++ b/src/base/cl_N_err_d0.cc @@ -0,0 +1,19 @@ +// cl_error_division_by_0(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_N.h" + + +// Implementation. + +#include "cl_io.h" +#include "cl_abort.h" + +void cl_error_division_by_0 (void) +{ + fprint(cl_stderr, "Division by zero.\n"); + cl_abort(); +} diff --git a/src/base/cl_abort.cc b/src/base/cl_abort.cc new file mode 100644 index 0000000..d2c6129 --- /dev/null +++ b/src/base/cl_abort.cc @@ -0,0 +1,17 @@ +// cl_abort(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_abort.h" + + +// Implementation. + +#include + +void cl_abort (void) +{ + exit(1); +} diff --git a/src/base/cl_alloca.cc b/src/base/cl_alloca.cc new file mode 100644 index 0000000..2166f9f --- /dev/null +++ b/src/base/cl_alloca.cc @@ -0,0 +1,30 @@ +// cl_alloc_alloca_header(), cl_free_alloca_header(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_alloca.h" + + +// Implementation. + +#include "cl_malloc.h" +#include "cl_offsetof.h" + +cl_alloca_header* cl_alloc_alloca_header (size_t size) +{ + var cl_alloca_header* pointer = + (cl_alloca_header*)cl_malloc_hook(size+offsetofa(cl_alloca_header,usable_memory)); + pointer->next = NULL; + return pointer; +} + +void cl_free_alloca_header (cl_alloca_header* pointer) +{ + do { + cl_alloca_header* next = pointer->next; + cl_free_hook(pointer); + pointer = next; + } while (pointer != NULL); +} diff --git a/src/base/cl_alloca.h b/src/base/cl_alloca.h new file mode 100644 index 0000000..6ed5a45 --- /dev/null +++ b/src/base/cl_alloca.h @@ -0,0 +1,84 @@ +// cl_alloca(). + +#ifndef _CL_ALLOCA_H +#define _CL_ALLOCA_H + +#include "cl_macros.h" +#include + +// Allocating temporary data of arbitrary size. +// We prefer to allocate it on the stack instead of via malloc(), because +// that's fully inlinable and causes less cache misses. But the global stack +// size of applications is limited (typically 8 MB on Unix, 1 MB on Windows), +// and we don't want users of CLN to need to change these limits. Therefore +// we use stack allocation only for amounts < 64KB, and malloc() for larger +// blocks. +// Usage: +// {CL_ALLOCA_STACK; +// ... +// ... = cl_alloca(...); +// ... +// ... = cl_small_alloca(...); +// ... +// ... = cl_alloca(...); +// ... +// } +// CL_ALLOCA_STACK declares that use of cl_alloca() and cl_small_alloca() is +// possible. Then cl_alloca() and cl_small_alloca() can be used an arbitrary +// number of times to get room. +// The allocated room's extent ends at the end of the { ... } block. +// In every C function CL_ALLOCA_STACK should only called once. +// Because of a gcc bug, functions using these macros shouldn't be declared +// inline. +// cl_alloca(size) fetches a block of size bytes. +// cl_small_alloca(size) fetches a block of size bytes, with size < 65536. +// CL_SMALL_ALLOCA_STACK is similar to CL_ALLOCA_STACK, but allows only +// the use of cl_small_alloca(), not cl_alloca(). + +// CL_ALLOCA_STACK creates a variable containing a linked list of pointers +// to be freed when the block is exited. + +struct cl_alloca_header { + cl_alloca_header* next; + long usable_memory[1]; // "long" guarantees alignment +}; + +extern cl_alloca_header* cl_alloc_alloca_header (size_t size); +extern void cl_free_alloca_header (cl_alloca_header* pointer); + +class cl_alloca_stack { + cl_alloca_header* pointer; +public: + cl_alloca_stack () { pointer = NULL; } + ~cl_alloca_stack () { if (pointer) cl_free_alloca_header(pointer); } + void* push (cl_alloca_header* p) { p->next = pointer; pointer = p; return &p->usable_memory; } +}; + +#define CL_ALLOCA_STACK \ + cl_alloca_stack _alloca_stack + +#define CL_ALLOCA_MAX 65536 + +#if defined(__GNUC__) && !defined(__riscos) && !defined(__convex__) + #define cl_alloca(size) ((size) >= CL_ALLOCA_MAX ? _alloca_stack.push(cl_alloc_alloca_header(size)) : __builtin_alloca(size)) + #define cl_small_alloca(size) __builtin_alloca(size) + #define CL_SMALL_ALLOCA_STACK +#elif !defined(NO_ALLOCA) && !defined(__sparc__) && !defined(__sparc64__) + #define cl_alloca(size) ((size) >= CL_ALLOCA_MAX ? _alloca_stack.push(cl_alloc_alloca_header(size)) : alloca(size)) + #define cl_small_alloca(size) alloca(size) + #define CL_SMALL_ALLOCA_STACK +#else + #define cl_alloca(size) _alloca_stack.push(cl_alloc_alloca_header(size)) + #define cl_small_alloca(size) _alloca_stack.push(cl_alloc_alloca_header(size)) + #define CL_SMALL_ALLOCA_STACK CL_ALLOCA_STACK +#endif + +// cl_alloc_array(type,size) +// cl_small_alloc_array(type,size) +// allocate an array with dynamic extent. + #define cl_alloc_array(arrayeltype,arraysize) \ + (arrayeltype*)cl_alloca((arraysize)*sizeof(arrayeltype)) + #define cl_small_alloc_array(arrayeltype,arraysize) \ + (arrayeltype*)cl_small_alloca((arraysize)*sizeof(arrayeltype)) + +#endif /* _CL_ALLOCA_H */ diff --git a/src/base/cl_as_err.cc b/src/base/cl_as_err.cc new file mode 100644 index 0000000..a06b684 --- /dev/null +++ b/src/base/cl_as_err.cc @@ -0,0 +1,34 @@ +// cl_as_error(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_N.h" + + +// Implementation. + +#include "cl_io.h" +#include "cl_abort.h" + +void cl_as_error (const cl_number& obj, const char * typestring, const char * filename, int line) +{ + fprint(cl_stderr, "Type assertion failed: in file "); + fprint(cl_stderr, filename); + fprint(cl_stderr, ", line "); + fprintdecimal(cl_stderr, line); + fprint(cl_stderr, ", not "); + fprint(cl_stderr, typestring); + fprint(cl_stderr, ": "); +#if 0 // This brings in a dependency from the complex and float printer and all the float stuff. + fprint(cl_stderr, obj); +#else + fprint(cl_stderr, "@0x"); + fprinthexadecimal(cl_stderr, (unsigned long)(void*)&obj); + fprint(cl_stderr, ": 0x"); + fprinthexadecimal(cl_stderr, (unsigned long)obj.word); +#endif + fprint(cl_stderr, "\n"); + cl_abort(); +} diff --git a/src/base/cl_base_config.h.in b/src/base/cl_base_config.h.in new file mode 100644 index 0000000..a5759e7 --- /dev/null +++ b/src/base/cl_base_config.h.in @@ -0,0 +1,30 @@ +// Defines OS dependent macros + +#ifndef _CL_BASE_CONFIG_H +#define _CL_BASE_CONFIG_H + +/* These definitions are adjusted by `configure' automatically. */ + + +/* functions and declarations */ + +/* CL_GETTIMEOFDAY */ +/* Define if you have the gettimeofday() function. */ +#undef HAVE_GETTIMEOFDAY +/* Define if the declaration of gettimeofday() needs dots. */ +#undef GETTIMEOFDAY_DOTS +/* Define as the type of `tzp' in gettimeofday() declaration. */ +#undef GETTIMEOFDAY_TZP_T + +/* CL_FTIME */ +/* Define if you have the ftime() function. */ +#undef HAVE_FTIME + +/* CL_TIMES_CLOCK */ +/* Define if you have the times() function and it returns the real time, + but don't have the gettimeofday() or ftime() function. */ +#undef HAVE_TIMES_CLOCK + + +#endif /* _CL_BASE_CONFIG_H */ + diff --git a/src/base/cl_condition.cc b/src/base/cl_condition.cc new file mode 100644 index 0000000..ac6e3bf --- /dev/null +++ b/src/base/cl_condition.cc @@ -0,0 +1,18 @@ +// Conditions. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_condition.h" + + +// Implementation. + +// This tells the compiler to put the `cl_condition' vtable into this file. +void cl_condition::dummy () {} + +// The destructor must be defined although it is virtual and abstract. +#if !(defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 8)) +cl_condition::~cl_condition () {} +#endif diff --git a/src/base/cl_debug.cc b/src/base/cl_debug.cc new file mode 100644 index 0000000..373c494 --- /dev/null +++ b/src/base/cl_debug.cc @@ -0,0 +1,78 @@ +// Debugging support for dynamic typing. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_object.h" + + +// Implementation. + +#include "cl_io.h" +#include "cl_abort.h" + +// The default printer function. +void cl_dprint_unknown (cl_heap* pointer) +{ + fprint(cl_debugout, ""); +} + +static void cl_dprint_unknown_immediate (cl_heap* pointer) +{ + fprint(cl_debugout, ""); +} + +// Print an object. This function is callable from the debugger. +extern "C" void* cl_print (cl_uint word); +void* cl_print (cl_uint word) +{ + var cl_heap* pointer = (cl_heap*)word; + if (cl_pointer_p(word)) { + var const cl_class* type = pointer->type; + if (type->dprint) + type->dprint(pointer); + else + cl_dprint_unknown(pointer); + } else { + var const cl_class* type = cl_immediate_classes[cl_tag(word)]; + if (type && type->dprint) + type->dprint(pointer); + else + cl_dprint_unknown_immediate(pointer); + } + #ifdef CL_IO_IOSTREAM + cl_debugout << endl; // newline and flush output + #else + fprint(cl_debugout, "\n"); + #endif + return pointer; +} + +void cl_gcobject::debug_print () const +{ + cl_print(word); +} + +void cl_gcpointer::debug_print () const +{ + cl_print(word); +} + +void cl_rcobject::debug_print () const +{ + cl_print(word); +} + +void cl_rcpointer::debug_print () const +{ + cl_print(word); +} diff --git a/src/base/cl_debugout.cc b/src/base/cl_debugout.cc new file mode 100644 index 0000000..ad5a5c2 --- /dev/null +++ b/src/base/cl_debugout.cc @@ -0,0 +1,27 @@ +// Debugging stream. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_io.h" + + +// Implementation. + +// Just assume that the debugger runs on /dev/tty, independently of +// cl_stdin, cl_stdout, cl_stderr. + +#if defined(CL_IO_STDIO) + +FILE* cl_debugout = fopen("/dev/tty","a"); + +#endif + +#if defined(CL_IO_IOSTREAM) + +#include + +ostream* cl_debugout_stream = new ofstream ("/dev/tty"); + +#endif diff --git a/src/base/cl_free.cc b/src/base/cl_free.cc new file mode 100644 index 0000000..a7d49c4 --- /dev/null +++ b/src/base/cl_free.cc @@ -0,0 +1,51 @@ +// cl_free_heap_object(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_object.h" + + +// Implementation. + +#include "cl_malloc.h" + +void cl_free_heap_object (cl_heap* pointer) +{ + // This is invoked when pointer->refcount gets decremented to 0. + var const cl_class* type = pointer->type; + if (type->destruct) + type->destruct(pointer); + cl_free_hook(pointer); +} + + +// The best place to put the free software license is cl_free.o. + +// NB about #ident: To see the strings in the .comment section of an ELF +// executable, use "strings < executable", not "strings executable". +// Better put the license into the data section: it is more portable (some +// C++ compilers may not understand #ident), is not lost in object formats +// like a.out, and is taken into account by "intelligent" strings commands. + +static const char * copyright_notice[] = { + " \n" + "Copyright (c) Bruno Haible 1988-1999 \n" + " \n" + "This program is free software; you can redistribute it and/or modify\n" + "it under the terms of the GNU General Public License as published by\n" + "the Free Software Foundation; either version 2, or (at your option) \n" + "any later version. \n" + " \n" + "This program is distributed in the hope that it will be useful, but \n" + "WITHOUT ANY WARRANTY; without even the implied warranty of \n" + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU \n" + "General Public License for more details. \n" + " \n" + "You should have received a copy of the GNU General Public License \n" + "along with this program; if not, write to the Free Software \n" + "Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n" + " ", + (const char *) ©right_notice +}; diff --git a/src/base/cl_gmpconfig.h.in b/src/base/cl_gmpconfig.h.in new file mode 100644 index 0000000..f10e6b1 --- /dev/null +++ b/src/base/cl_gmpconfig.h.in @@ -0,0 +1,16 @@ +// Defines configuration dependent macros + +#ifndef _CL_GMPCONFIG_H +#define _CL_GMPCONFIG_H + +/* These definitions are adjusted by `configure' automatically. */ + + +/* interfacing to GNU gmp */ + +/* Define if you wish to use the fast GNU gmp low-level functions. */ +#undef CL_USE_GMP + + +#endif /* _CL_GMPCONFIG_H */ + diff --git a/src/base/cl_immclasses.cc b/src/base/cl_immclasses.cc new file mode 100644 index 0000000..091b649 --- /dev/null +++ b/src/base/cl_immclasses.cc @@ -0,0 +1,13 @@ +// cl_immediate_classes. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_object.h" + + +// Implementation. + +const struct cl_class * cl_immediate_classes [1< +class cl_abstract_iterator { +public: + virtual bool endp () = 0; + virtual T& next () = 0; +}; + + +#endif /* _CL_ITERATOR_H */ diff --git a/src/base/cl_low.h b/src/base/cl_low.h new file mode 100644 index 0000000..2ab26f4 --- /dev/null +++ b/src/base/cl_low.h @@ -0,0 +1,1314 @@ +// Low-level arithmetic: operations on 16-bit and 32-bit words + +#ifndef _CL_LOW_H +#define _CL_LOW_H + + +// Determines the sign of a 16-bit number. +// sign_of(wert) +// > wert: eine 16-Bit-Zahl +// < sint16 ergebnis: 0 falls wert>=0, -1 falls wert<0. +inline sint16 sign_of (sint16 wert) +{ +#if defined(__sparc64__) + return (sint64)wert >> 63; +#elif defined(__sparc__) || defined(__arm__) + return (sint32)wert >> 31; +#else + return (wert >= 0 ? 0 : -1); +#endif +} + +// Determines the sign of a 32-bit number. +// sign_of(wert) +// > wert: eine 32-Bit-Zahl +// < sint32 ergebnis: 0 falls wert>=0, -1 falls wert<0. +inline sint32 sign_of (sint32 wert) +{ +#if defined(__sparc64__) + return (sint64)wert >> 63; +#elif defined(__sparc__) || defined(__arm__) + return wert >> 31; +#else + return (wert >= 0 ? 0 : -1); +#endif +} + +#ifdef HAVE_FAST_LONGLONG + +// Determines the sign of a 64-bit number. +// sign_of(wert) +// > wert: eine 64-Bit-Zahl +// < sint64 ergebnis: 0 falls wert>=0, -1 falls wert<0. +inline sint64 sign_of (sint64 wert) +{ + return wert >> 63; +} + +#endif /* HAVE_FAST_LONGLONG */ + + +// High-Word einer 32-Bit-Zahl bestimmen +// high16(wert) +inline uint16 high16 (uint32 wert) +{ + return wert >> 16; +} + +// Low-Word einer 32-Bit-Zahl bestimmen +// low16(wert) +inline uint16 low16 (uint32 wert) +{ + return (uint16)wert; +} + +// Eine 32-Bit-Zahl aus ihrem High-Word und ihrem Low-Word bestimmen: +// highlow32(uint16 high, uint16 low) +inline uint32 highlow32 (uint16 high, uint16 low) +{ + return ((uint32)high << 16) | (uint32)low; +} + +// Eine 32-Bit-Zahl aus ihrem High-Word und ihrem Low-Word 0 bestimmen: +// highlow32_0(uint16 high) +inline uint32 highlow32_0 (uint16 high) +{ + return (uint32)high << 16; +} + +#ifdef HAVE_FAST_LONGLONG + +// High-Word einer 64-Bit-Zahl bestimmen +// high32(wert) +inline uint32 high32 (uint64 wert) +{ + return wert >> 32; +} + +// Low-Word einer 64-Bit-Zahl bestimmen +// low32(wert) +inline uint32 low32 (uint64 wert) +{ + return (uint32)wert; +} + +// Eine 64-Bit-Zahl aus ihrem High-Word und ihrem Low-Word bestimmen: +// highlow64(uint32 high, uint32 low) +inline uint64 highlow64 (uint32 high, uint32 low) +{ + return ((uint64)high << 32) | (uint64)low; +} + +// Eine 64-Bit-Zahl aus ihrem High-Word und ihrem Low-Word 0 bestimmen: +// highlow64_0(uint32 high) +inline uint64 highlow64_0 (uint32 high) +{ + return (uint64)high << 32; +} + +#endif /* HAVE_FAST_LONGLONG */ + + +// Multipliziert zwei 16-Bit-Zahlen miteinander und liefert eine 32-Bit-Zahl: +// mulu16(arg1,arg2) +// > arg1, arg2 : zwei 16-Bit-Zahlen +// < ergebnis: eine 32-Bit-Zahl +#if defined(__GNUC__) && defined(__sparc__) && !defined(__sparc64__) && defined(FAST_DOUBLE) +// Ist das schneller als mulu16_ ?? +inline uint32 mulu16 (uint16 arg1, uint16 arg2) +{ + union { double f; uint32 i[2]; } __fi; + __fi.f = (double)(sint32)arg1 * (double)(sint32)arg2 + + (double)(4503599627370496.0L); // + 2^52, zum Normalisieren + return __fi.i[1]; // untere 32 Bit herausholen (benutzt CL_CPU_BIG_ENDIAN_P !) +} +#elif defined(__GNUC__) && defined(__sparc64__) && !defined(NO_ASM) +inline uint32 mulu16 (uint16 arg1, uint16 arg2) +{ + register uint64 _prod; + __asm__("umul %1,%2,%0" + : "=r" (_prod) + : "r" (arg1), "r" (arg2) + ); + return _prod; +} +#elif defined(__GNUC__) && defined(__i386__) && !defined(NO_ASM) +inline uint32 mulu16 (uint16 arg1, uint16 arg2) +{ + register uint16 _hi; + register uint16 _lo; + __asm__("mulw %2" + : "=d" /* %dx */ (_hi), "=a" /* %ax */ (_lo) + : "rm" (arg1), "1" /* %eax */ (arg2) + ); + return highlow32(_hi,_lo); +} +#elif defined(__sparc__) || defined(__sparc64__) + extern "C" uint32 mulu16_ (uint16 arg1, uint16 arg2); + #define mulu16 mulu16_ // extern in Assembler +#else +inline uint32 mulu16 (uint16 arg1, uint16 arg2) +{ + return arg1 * arg2; +} +#endif + +// Multipliziert zwei 24-Bit-Zahlen zusammen und liefert eine 48-Bit-Zahl. +// mulu24(arg1,arg2,hi=,lo=); +// > arg1, arg2 : zwei 24-Bit-Zahlen +// < 2^32*hi+lo : eine 48-Bit-Zahl +#if defined(__sparc__) && !defined(__sparc64__) && defined(FAST_DOUBLE) + #define mulu24(x,y,hi_zuweisung,lo_zuweisung) \ + { var uint32 _x = (x); \ + var uint32 _y = (y); \ + var union { double f; uint32 i[2]; uint16 s[4]; } __fi; \ + __fi.f = (double)(sint32)(_x)*(double)(sint32)(_y) \ + + (double)(4503599627370496.0L); /* + 2^52, zum Normalisieren */\ + hi_zuweisung __fi.s[1]; /* mittlere 16 Bit herausholen, (benutzt CL_CPU_BIG_ENDIAN_P !) */\ + lo_zuweisung __fi.i[1]; /* untere 32 Bit herausholen (benutzt CL_CPU_BIG_ENDIAN_P !) */\ + } +#else + #define mulu24 mulu32 +#endif + +// Multipliziert zwei 32-Bit-Zahlen miteinander und liefert eine 32-Bit-Zahl: +// mulu32_unchecked(arg1,arg2) +// > arg1, arg2 : zwei 32-Bit-Zahlen +// < ergebnis : eine 32-Bit-Zahl +// Es wird vorausgesetzt, daß arg1*arg2 < 2^32. +#if defined(__GNUC__) && defined(__sparc64__) && !defined(NO_ASM) +inline uint32 mulu32_unchecked (uint32 arg1, uint32 arg2) +{ + register uint64 _prod; + __asm__("umul %1,%2,%0" + : "=r" (_prod) + : "r" (arg1), "r" (arg2) + ); + return _prod; +} +#elif defined(__sparc__) + extern "C" uint32 mulu32_unchecked (uint32 x, uint32 y); // extern in Assembler +#else + // Wir können dafür auch die Bibliotheksroutine des C-Compilers nehmen: + inline uint32 mulu32_unchecked (uint32 arg1, uint32 arg2) + { + return arg1 * arg2; + } +#endif + +// Multipliziert zwei 32-Bit-Zahlen miteinander und liefert eine 64-Bit-Zahl: +// mulu32(arg1,arg2,hi=,lo=); +// > arg1, arg2 : zwei 32-Bit-Zahlen +// < 2^32*hi+lo : eine 64-Bit-Zahl + extern "C" uint32 mulu32_ (uint32 arg1, uint32 arg2); // -> Low-Teil + extern "C" uint32 mulu32_high; // -> High-Teil +#if defined(__GNUC__) && defined(__m68k__) && !defined(NO_ASM) + #define mulu32(x,y,hi_zuweisung,lo_zuweisung) \ + ({ var uint32 _x = (x); \ + var uint32 _y = (y); \ + var uint32 _hi; \ + var uint32 _lo; \ + __asm__("mulul %3,%0:%1" : "=d" (_hi), "=d"(_lo) : "1" (_x), "dm" (_y) ); \ + hi_zuweisung _hi; \ + lo_zuweisung _lo; \ + }) +#elif defined(__GNUC__) && defined(__m68k__) + #define mulu32(x,y,hi_zuweisung,lo_zuweisung) \ + ({ var uint32 _x = (x); \ + var uint32 _y = (y); \ + var uint16 _x1 = high16(_x); \ + var uint16 _x0 = low16(_x); \ + var uint16 _y1 = high16(_y); \ + var uint16 _y0 = low16(_y); \ + var uint32 _hi = mulu16(_x1,_y1); /* obere Portion */ \ + var uint32 _lo = mulu16(_x0,_y0); /* untere Portion */ \ + {var uint32 _mid = mulu16(_x0,_y1); /* 1. mittlere Portion */ \ + _hi += high16(_mid); _mid = highlow32_0(low16(_mid)); \ + _lo += _mid; if (_lo < _mid) { _hi += 1; } /* 64-Bit-Addition */\ + } \ + {var uint32 _mid = mulu16(_x1,_y0); /* 2. mittlere Portion */ \ + _hi += high16(_mid); _mid = highlow32_0(low16(_mid)); \ + _lo += _mid; if (_lo < _mid) { _hi += 1; } /* 64-Bit-Addition */\ + } \ + hi_zuweisung _hi; \ + lo_zuweisung _lo; \ + }) +#elif defined(__GNUC__) && defined(__sparc64__) && !defined(NO_ASM) + #define mulu32(x,y,hi_zuweisung,lo_zuweisung) \ + ({ var register uint64 _hi; \ + var register uint64 _lo; \ + __asm__("umul %2,%3,%1\n\trd %y,%0" \ + : "=r" (_hi), "=r" (_lo) \ + : "r" ((uint32)(x)), "r" ((uint32)(y)) \ + ); \ + hi_zuweisung (uint32)_hi; lo_zuweisung (uint32)_lo; \ + }) +#elif defined(__GNUC__) && defined(__sparc__) + #define mulu32(x,y,hi_zuweisung,lo_zuweisung) \ + ({ lo_zuweisung mulu32_(x,y); /* extern in Assembler */ \ + {var register uint32 _hi __asm__("%g1"); \ + hi_zuweisung _hi; \ + }}) +#elif defined(__GNUC__) && defined(__arm__) && 0 // see comment cl_asm_arm.cc + #define mulu32(x,y,hi_zuweisung,lo_zuweisung) \ + ({ lo_zuweisung mulu32_(x,y); /* extern in Assembler */ \ + {var register uint32 _hi __asm__("%r1"/*"%a2"*/); \ + hi_zuweisung _hi; \ + }}) +#elif defined(__GNUC__) && defined(__i386__) && !defined(NO_ASM) + #define mulu32(x,y,hi_zuweisung,lo_zuweisung) \ + ({ var register uint32 _hi; \ + var register uint32 _lo; \ + __asm__("mull %2" \ + : "=d" /* %edx */ (_hi), "=a" /* %eax */ (_lo) \ + : "g" ((uint32)(x)), "1" /* %eax */ ((uint32)(y)) \ + ); \ + hi_zuweisung _hi; lo_zuweisung _lo; \ + }) +#elif defined(__GNUC__) && defined(__mips__) && !defined(NO_ASM) + #define mulu32(x,y,hi_zuweisung,lo_zuweisung) \ + ({ var register uint32 _hi; \ + var register uint32 _lo; \ + __asm__("multu %3,%2 ; mfhi %0 ; mflo %1" \ + : "=r" (_hi), "=r" (_lo) \ + : "r" ((uint32)(x)), "r" ((uint32)(y)) \ + ); \ + hi_zuweisung _hi; lo_zuweisung _lo; \ + }) +#elif defined(__GNUC__) && defined(HAVE_LONGLONG) && !defined(__arm__) + #define mulu32(x,y,hi_zuweisung,lo_zuweisung) \ + ({ var register uint64 _prod = (uint64)(uint32)(x) * (uint64)(uint32)(y); \ + hi_zuweisung (uint32)(_prod>>32); \ + lo_zuweisung (uint32)(_prod); \ + }) +#elif defined(WATCOM) && defined(__i386__) && !defined(NO_ASM) + #define mulu32(x,y,hi_zuweisung,lo_zuweisung) \ + { var register uint32 _hi; \ + var register uint32 _lo; \ + _lo = mulu32_(x,y), _hi = mulu32_high_(); \ + hi_zuweisung _hi; lo_zuweisung _lo; \ + } + extern "C" uint32 mulu32_high_ (void); + #pragma aux mulu32_ = 0xF7 0xE2 /* mull %edx */ parm [eax] [edx] value [eax] modify [eax edx]; + #pragma aux mulu32_high_ = /* */ value [edx] modify []; +#else + #define mulu32(x,y,hi_zuweisung,lo_zuweisung) \ + { lo_zuweisung mulu32_(x,y); hi_zuweisung mulu32_high; } + #if defined(__m68k__) || defined(__sparc__) || defined(__sparc64__) || defined(__arm__) || (defined(__i386__) && !defined(WATCOM) && !defined(MICROSOFT)) || defined(__mips__) || defined(__hppa__) + // mulu32_ extern in Assembler + #if defined(__sparc__) || defined(__sparc64__) + extern "C" uint32 _get_g1 (void); + #define mulu32_high (_get_g1()) // Rückgabe im Register %g1 + #elif !defined(__hppa__) + #define NEED_VAR_mulu32_high + #endif + #else + #define NEED_FUNCTION_mulu32_ + #endif +#endif + +#ifdef HAVE_FAST_LONGLONG + +// Multipliziert zwei 32-Bit-Zahlen miteinander und liefert eine 64-Bit-Zahl: +// mulu32_w(arg1,arg2) +// > arg1, arg2 : zwei 32-Bit-Zahlen +// < result : eine 64-Bit-Zahl +#if defined(__GNUC__) + #define mulu32_w(x,y) ((uint64)(uint32)(x) * (uint64)(uint32)(y)) +#else + extern "C" uint64 mulu32_w (uint32 arg1, uint32 arg2); + #define NEED_FUNCTION_mulu32_w +#endif + +// Multipliziert zwei 64-Bit-Zahlen miteinander und liefert eine 128-Bit-Zahl: +// mulu64(arg1,arg2,hi=,lo=); +// > arg1, arg2 : zwei 64-Bit-Zahlen +// < 2^64*hi+lo : eine 128-Bit-Zahl + extern "C" uint64 mulu64_ (uint64 arg1, uint64 arg2); // -> Low-Teil + extern "C" uint64 mulu64_high; // -> High-Teil +#if defined(__GNUC__) && defined(__alpha__) && !defined(NO_ASM) + #define mulu64(x,y,hi_zuweisung,lo_zuweisung) \ + ({ var register uint64 _x = (x); \ + var register uint64 _y = (y); \ + var register uint64 _hi; \ + var register uint64 _lo; \ + __asm__("mulq %1,%2,%0" \ + : "=r" (_lo) \ + : "r" (_x), "r" (_y) \ + ); \ + __asm__("umulh %1,%2,%0" \ + : "=r" (_hi) \ + : "r" (_x), "r" (_y) \ + ); \ + hi_zuweisung _hi; \ + lo_zuweisung _lo; \ + }) +#elif defined(__GNUC__) && defined(__sparc64__) + #define mulu64(x,y,hi_zuweisung,lo_zuweisung) \ + ({ lo_zuweisung mulu64_(x,y); /* extern in Assembler */ \ + {var register uint64 _hi __asm__("%g2"); \ + hi_zuweisung _hi; \ + }}) +#else + #define mulu64(x,y,hi_zuweisung,lo_zuweisung) \ + { lo_zuweisung mulu64_(x,y); hi_zuweisung mulu64_high; } + #if defined(__sparc64__) + // mulu64_ extern in Assembler + #if defined(__sparc64__) + extern "C" uint64 _get_g2 (void); + #define mulu64_high (_get_g2()) // Rückgabe im Register %g2 + #else + #define NEED_VAR_mulu64_high + #endif + #else + #define NEED_FUNCTION_mulu64_ + #endif +#endif + +#endif /* HAVE_FAST_LONGLONG */ + + +// Dividiert eine 16-Bit-Zahl durch eine 16-Bit-Zahl und +// liefert einen 16-Bit-Quotienten und einen 16-Bit-Rest. +// divu_1616_1616(x,y,q=,r=); +// > uint16 x: Zähler +// > uint16 y: Nenner +// < uint16 q: floor(x/y) +// < uint16 r: x mod y +// < x = q*y+r + #define divu_1616_1616(x,y,q_zuweisung,r_zuweisung) \ + { var uint16 __x = (x); \ + var uint16 __y = (y); \ + q_zuweisung floor(__x,__y); \ + r_zuweisung (__x % __y); \ + } + +// Dividiert eine 32-Bit-Zahl durch eine 16-Bit-Zahl und +// liefert einen 16-Bit-Quotienten und einen 16-Bit-Rest. +// divu_3216_1616(x,y,q=,r=); +// > uint32 x: Zähler +// > uint16 y: Nenner +// > Es sei bekannt, daß 0 <= x < 2^16*y . +// < uint16 q: floor(x/y) +// < uint16 r: x mod y +// < x = q*y+r +#if defined(__sparc__) + extern "C" uint32 divu_3216_1616_ (uint32 x, uint16 y); // -> Quotient q, Rest r +#else + extern "C" uint16 divu_3216_1616_ (uint32 x, uint16 y); // -> Quotient q + extern "C" uint16 divu_16_rest; // -> Rest r +#endif +#if defined(__GNUC__) && defined(__sparc64__) && !defined(NO_ASM) + #define divu_3216_1616(x,y,q_zuweisung,r_zuweisung) \ + ({var uint32 __x = (x); \ + var uint16 __y = (y); \ + var uint64 __q; \ + var uint64 __r; \ + __asm__ __volatile__ ( \ + "wr %%g0,%%g0,%%y\n\t" \ + "udiv %2,%3,%0\n\t" \ + "umul %0,%3,%1" \ + "sub %2,%1,%1" \ + : "=&r" (__q), "=&r" (__r) \ + : "r" (__x), "r" (__y)); \ + q_zuweisung (uint16)__q; \ + r_zuweisung (uint16)__r; \ + }) +#elif defined(__GNUC__) && (defined(__sparc__) || defined(__sparc64__)) + #define divu_3216_1616(x,y,q_zuweisung,r_zuweisung) \ + ({ var uint32 __qr = divu_3216_1616_(x,y); /* extern in Assembler */\ + q_zuweisung low16(__qr); \ + r_zuweisung high16(__qr); \ + }) +#elif defined(__GNUC__) && defined(__m68k__) && !defined(NO_ASM) + #define divu_3216_1616(x,y,q_zuweisung,r_zuweisung) \ + ({var uint32 __x = (x); \ + var uint16 __y = (y); \ + var uint32 __qr; \ + __asm__ __volatile__ (" \ + divu %2,%0 \ + " : "=d" (__qr) : "0" (__x), "dm" (__y)); \ + q_zuweisung low16(__qr); \ + r_zuweisung high16(__qr); \ + }) +#elif defined(__GNUC__) && defined(__i386__) && !defined(NO_ASM) + #define divu_3216_1616(x,y,q_zuweisung,r_zuweisung) \ + ({var uint32 __x = (x); \ + var uint16 __y = (y); \ + var uint16 __q; \ + var uint16 __r; \ + __asm__("divw %4" \ + : "=a" /* %ax */ (__q), "=d" /* %dx */ (__r) \ + : "1" /* %dx */ ((uint16)(high16(__x))), "0" /* %ax */ ((uint16)(low16(__x))), "rm" (__y) \ + ); \ + q_zuweisung __q; \ + r_zuweisung __r; \ + }) +#elif defined(__GNUC__) && defined(__arm__) && 0 // see comment cl_asm_arm.cc + #define divu_3216_1616(x,y,q_zuweisung,r_zuweisung) \ + { var uint32 _q = divu_3216_1616_(x,y); /* extern in Assembler */ \ + var register uint32 _r __asm__("%r1"/*"%a2"*/); \ + q_zuweisung _q; r_zuweisung _r; \ + } +#elif defined(__GNUC__) && !defined(__arm__) + #define divu_3216_1616(x,y,q_zuweisung,r_zuweisung) \ + ({var uint32 __x = (x); \ + var uint16 __y = (y); \ + var uint16 __q = floor(__x,__y); \ + q_zuweisung __q; \ + r_zuweisung (__x - __q * __y); \ + }) +#elif defined(__sparc__) || defined(__sparc64__) + #define divu_3216_1616(x,y,q_zuweisung,r_zuweisung) \ + { var uint32 __qr = divu_3216_1616_(x,y); /* extern in Assembler */ \ + q_zuweisung low16(__qr); \ + r_zuweisung high16(__qr); \ + } +#elif defined(__arm__) + #define divu_3216_1616(x,y,q_zuweisung,r_zuweisung) \ + { q_zuweisung divu_3216_1616_(x,y); /* extern in Assembler */ \ + r_zuweisung divu_16_rest; \ + } + #define NEED_VAR_divu_16_rest +#else + #define divu_3216_1616(x,y,q_zuweisung,r_zuweisung) \ + { q_zuweisung divu_3216_1616_(x,y); r_zuweisung divu_16_rest; } + #define NEED_FUNCTION_divu_3216_1616_ +#endif + +// Dividiert eine 32-Bit-Zahl durch eine 16-Bit-Zahl und +// liefert einen 32-Bit-Quotienten und einen 16-Bit-Rest. +// divu_3216_3216(x,y,q=,r=); +// > uint32 x: Zähler +// > uint16 y: Nenner +// Es sei bekannt, daß y>0. +// < uint32 q: floor(x/y) +// < uint16 r: x mod y +// < x = q*y+r + extern "C" uint32 divu_3216_3216_ (uint32 x, uint16 y); // -> Quotient q + extern "C" uint16 divu_16_rest; // -> Rest r +#if defined(__GNUC__) && defined(__sparc64__) && !defined(NO_ASM) + #define divu_3216_3216(x,y,q_zuweisung,r_zuweisung) \ + ({var uint32 __x = (x); \ + var uint16 __y = (y); \ + var uint64 __q; \ + var uint64 __r; \ + __asm__ __volatile__ ( \ + "wr %%g0,%%g0,%%y\n\t" \ + "udiv %2,%3,%0\n\t" \ + "umul %0,%3,%1" \ + "sub %2,%1,%1" \ + : "=&r" (__q), "=&r" (__r) \ + : "r" (__x), "r" (__y)); \ + q_zuweisung (uint32)__q; \ + r_zuweisung (uint16)__r; \ + }) +#elif defined(__sparc__) || defined(__sparc64__) || defined(__i386__) + #define divu_3216_3216 divu_3232_3232 +#else + // Methode: (beta = 2^16) + // x = x1*beta+x0 schreiben. + // Division mit Rest: x1 = q1*y + r1, wobei 0 <= x1 < beta <= beta*y. + // Also 0 <= q1 < beta, 0 <= r1 < y. + // Division mit Rest: (r1*beta+x0) = q0*y + r0, wobei 0 <= r1*beta+x0 < beta*y. + // Also 0 <= q0 < beta, 0 <= r0 < y + // und x = x1*beta+x0 = (q1*beta+q0)*y + r0. + // Setze q := q1*beta+q0 und r := r0. + #define divu_3216_3216(x,y,q_zuweisung,r_zuweisung) \ + { var uint32 _x = (x); \ + var uint16 _y = (y); \ + var uint16 _q1; \ + var uint16 _q0; \ + var uint16 _r1; \ + divu_3216_1616(high16(_x),_y, _q1 = , _r1 = ); \ + divu_3216_1616(highlow32(_r1,low16(_x)),_y, _q0 = , r_zuweisung); \ + q_zuweisung highlow32(_q1,_q0); \ + } +#endif + +// Dividiert eine 32-Bit-Zahl durch eine 32-Bit-Zahl und +// liefert einen 32-Bit-Quotienten und einen 32-Bit-Rest. +// divu_3232_3232(x,y,q=,r=); +// > uint32 x: Zähler +// > uint32 y: Nenner +// Es sei bekannt, daß y>0. +// < uint32 q: floor(x/y) +// < uint32 r: x mod y +// < x = q*y+r + extern "C" uint32 divu_3232_3232_ (uint32 x, uint32 y); // -> Quotient q + extern "C" uint32 divu_32_rest; // -> Rest r +#if defined(__GNUC__) && defined(__sparc64__) && !defined(NO_ASM) + #define divu_3232_3232(x,y,q_zuweisung,r_zuweisung) \ + ({var uint32 __x = (x); \ + var uint32 __y = (y); \ + var uint64 __q; \ + var uint64 __r; \ + __asm__ __volatile__ ( \ + "wr %%g0,%%g0,%%y\n\t" \ + "udiv %2,%3,%0\n\t" \ + "umul %0,%3,%1" \ + "sub %2,%1,%1" \ + : "=&r" (__q), "=&r" (__r) \ + : "r" (__x), "r" (__y)); \ + q_zuweisung (uint32)__q; \ + r_zuweisung (uint32)__r; \ + }) +#elif defined(__sparc__) || defined(__sparc64__) || defined(__i386__) + #define divu_3232_3232(x,y,q_zuweisung,r_zuweisung) \ + divu_6432_3232(0,x,y,q_zuweisung,r_zuweisung) + #define divu_3232_3232_(x,y) divu_6432_3232_(0,x,y) +#else + // Methode: (beta = 2^n = 2^16, n = 16) + // Falls y < beta, handelt es sich um eine 32-durch-16-Bit-Division. + // Falls y >= beta: + // Quotient q = floor(x/y) < beta (da 0 <= x < beta^2, y >= beta). + // y habe genau n+k Bits (1 <= k <= n), d.h. 2^(n+k-1) <= y < 2^(n+k). + // Schreibe x = 2^k*x1 + x0 mit x1 := floor(x/2^k) + // und y = 2^k*y1 + y0 mit y1 := floor(y/2^k) + // und bilde den Näherungs-Quotienten floor(x1/y1) + // oder (noch besser) floor(x1/(y1+1)). + // Wegen 0 <= x1 < 2^(2n) und 0 < 2^(n-1) <= y1 < 2^n + // und x1/(y1+1) <= x/y < x1/(y1+1) + 2 + // (denn x1/(y1+1) = (x1*2^k)/((y1+1)*2^k) <= (x1*2^k)/y <= x/y + // und x/y - x1/(y1+1) = (x+x*y1-x1*y)/(y*(y1+1)) + // = (x+x0*y1-x1*y0)/(y*(y1+1)) <= (x+x0*y1)/(y*(y1+1)) + // <= x/(y*(y1+1)) + x0/y + // <= 2^(2n)/(2^(n+k-1)*(2^(n-1)+1)) + 2^k/2^(n+k-1) + // = 2^(n-k+1)/(2^(n-1)+1) + 2^(1-n) <= 2^n/(2^(n-1)+1) + 2^(1-n) < 2 ) + // gilt floor(x1/(y1+1)) <= floor(x/y) <= floor(x1/(y1+1)) + 2 . + // Man bildet also q:=floor(x1/(y1+1)) (ein Shift um n Bit oder + // eine (2n)-durch-n-Bit-Division, mit Ergebnis q <= floor(x/y) < beta) + // und x-q*y und muß hiervon noch höchstens 2 mal y abziehen und q + // incrementieren, um den Quotienten q = floor(x/y) und den Rest + // x-floor(x/y)*y der Division zu bekommen. + #define divu_3232_3232(x,y,q_zuweisung,r_zuweisung) \ + { var uint32 _x = (x); \ + var uint32 _y = (y); \ + if (_y <= (uint32)(bit(16)-1)) \ + { var uint16 _q1; \ + var uint16 _q0; \ + var uint16 _r1; \ + divu_3216_1616(high16(_x),_y, _q1 = , _r1 = ); \ + divu_3216_1616(highlow32(_r1,low16(_x)),_y, _q0 = , r_zuweisung); \ + q_zuweisung highlow32(_q1,_q0); \ + } \ + else \ + { var uint32 _x1 = _x; /* x1 := x */ \ + var uint32 _y1 = _y; /* y1 := y */ \ + var uint16 _q; \ + do { _x1 = floor(_x1,2); _y1 = floor(_y1,2); } /* k erhöhen */\ + until (_y1 <= (uint32)(bit(16)-1)); /* bis y1 < beta */ \ + { var uint16 _y2 = low16(_y1)+1; /* y1+1 bilden */ \ + if (_y2==0) \ + { _q = high16(_x1); } /* y1+1=beta -> ein Shift */ \ + else \ + { divu_3216_1616(_x1,_y2,_q=,); } /* Division von x1 durch y1+1 */\ + } \ + /* _q = q = floor(x1/(y1+1)) */ \ + /* x-q*y bilden (eine 16-mal-32-Bit-Multiplikation ohne Ãœberlauf): */\ + _x -= highlow32_0(mulu16(_q,high16(_y))); /* q * high16(y) * beta */\ + /* gefahrlos, da q*high16(y) <= q*y/beta <= x/beta < beta */ \ + _x -= mulu16(_q,low16(_y)); /* q * low16(y) */ \ + /* gefahrlos, da q*high16(y)*beta + q*low16(y) = q*y <= x */ \ + /* Noch höchstens 2 mal y abziehen: */ \ + if (_x >= _y) \ + { _q += 1; _x -= _y; \ + if (_x >= _y) \ + { _q += 1; _x -= _y; } \ + } \ + r_zuweisung _x; \ + q_zuweisung (uint32)(_q); \ + } } + #define NEED_FUNCTION_divu_3232_3232_ +#endif + +// Dividiert eine 64-Bit-Zahl durch eine 32-Bit-Zahl und +// liefert einen 32-Bit-Quotienten und einen 32-Bit-Rest. +// divu_6432_3232(xhi,xlo,y,q=,r=); +// > uint32 xhi,xlo: x = 2^32*xhi+xlo = Zähler +// > uint32 y: Nenner +// > Es sei bekannt, daß 0 <= x < 2^32*y . +// < uint32 q: floor(x/y) +// < uint32 r: x mod y +// < x = q*y+r + extern "C" uint32 divu_6432_3232_ (uint32 xhi, uint32 xlo, uint32 y); // -> Quotient q + extern "C" uint32 divu_32_rest; // -> Rest r +#if defined(__GNUC__) && defined(__m68k__) && !defined(NO_ASM) + #define divu_6432_3232(xhi,xlo,y,q_zuweisung,r_zuweisung) \ + ({var uint32 __xhi = (xhi); \ + var uint32 __xlo = (xlo); \ + var uint32 __y = (y); \ + var uint32 __q; \ + var uint32 __r; \ + __asm__ __volatile__ (" \ + divul %4,%1:%0 \ + " : "=d" (__q), "=d" (__r) : "1" (__xhi), "0" (__xlo), "dm" (__y)); \ + q_zuweisung __q; \ + r_zuweisung __r; \ + }) + #define divu_6432_3232_(xhi,xlo,y) \ + ({var uint32 ___q; divu_6432_3232(xhi,xlo,y,___q=,); ___q; }) +#elif defined(__GNUC__) && defined(__sparc64__) && !defined(NO_ASM) + #define divu_6432_3232(xhi,xlo,y,q_zuweisung,r_zuweisung) \ + ({var uint32 __xhi = (xhi); \ + var uint32 __xlo = (xlo); \ + var uint32 __y = (y); \ + var uint64 __q; \ + var uint64 __r; \ + __asm__ __volatile__ ( \ + "wr %2,%%g0,%%y\n\t" \ + "udiv %3,%4,%0\n\t" \ + "umul %0,%4,%1" \ + "sub %3,%1,%1" \ + : "=&r" (__q), "=&r" (__r) \ + : "r" (__xhi), "r" (__xlo), "r" (__y)); \ + q_zuweisung (uint32)__q; \ + r_zuweisung (uint32)__r; \ + }) +#elif defined(__GNUC__) && (defined(__sparc__) || defined(__sparc64__)) + #define divu_6432_3232(xhi,xlo,y,q_zuweisung,r_zuweisung) \ + ({ var uint32 _q = divu_6432_3232_(xhi,xlo,y); /* extern in Assembler */\ + var register uint32 _r __asm__("%g1"); \ + q_zuweisung _q; r_zuweisung _r; \ + }) +#elif defined(__GNUC__) && defined(__arm__) && 0 // see comment cl_asm_arm.cc + #define divu_6432_3232(xhi,xlo,y,q_zuweisung,r_zuweisung) \ + ({ var uint32 _q = divu_6432_3232_(xhi,xlo,y); /* extern in Assembler */\ + var register uint32 _r __asm__("%r1"/*"%a2"*/); \ + q_zuweisung _q; r_zuweisung _r; \ + }) +#elif defined(__GNUC__) && defined(__i386__) && !defined(NO_ASM) + #define divu_6432_3232(xhi,xlo,y,q_zuweisung,r_zuweisung) \ + ({var uint32 __xhi = (xhi); \ + var uint32 __xlo = (xlo); \ + var uint32 __y = (y); \ + var uint32 __q; \ + var uint32 __r; \ + __asm__ __volatile__ ( \ + "divl %4" \ + : "=a" /* %eax */ (__q), "=d" /* %edx */ (__r) \ + : "1" /* %edx */ (__xhi), "0" /* %eax */ (__xlo), "rm" (__y) \ + ); \ + q_zuweisung __q; \ + r_zuweisung __r; \ + }) + #define divu_6432_3232_(xhi,xlo,y) \ + ({var uint32 ___q; divu_6432_3232(xhi,xlo,y,___q=,); ___q; }) +#elif defined(__GNUC__) && defined(HAVE_LONGLONG) && !defined(__arm__) + #define divu_6432_3232(xhi,xlo,y,q_zuweisung,r_zuweisung) \ + ({var uint32 __xhi = (xhi); \ + var uint32 __xlo = (xlo); \ + var uint64 __x = ((uint64)__xhi << 32) | (uint64)__xlo; \ + var uint32 __y = (y); \ + var uint32 __q = floor(__x,(uint64)__y); \ + q_zuweisung __q; r_zuweisung __xlo - __q * __y; \ + }) + #define divu_6432_3232_(xhi,xlo,y) \ + ({var uint32 ___q; divu_6432_3232(xhi,xlo,y,___q=,); ___q; }) +#elif defined(WATCOM) && defined(__i386__) && !defined(NO_ASM) + #define divu_6432_3232(xhi,xlo,y,q_zuweisung,r_zuweisung) \ + { var uint32 __xhi = (xhi); \ + var uint32 __xlo = (xlo); \ + var uint32 __y = (y); \ + var uint32 __q; \ + var uint32 __r; \ + __q = divu_6432_3232_(__xhi,__xlo,__y); __r = divu_6432_3232_rest(); \ + q_zuweisung __q; \ + r_zuweisung __r; \ + } + extern "C" uint32 divu_6432_3232_rest (void); + #pragma aux divu_6432_3232_ = 0xF7 0xF1 /* divl %ecx */ parm [edx] [eax] [ecx] value [eax] modify [eax edx]; + #pragma aux divu_6432_3232_rest = /* */ value [edx] modify []; +#else + #define divu_6432_3232(xhi,xlo,y,q_zuweisung,r_zuweisung) \ + { q_zuweisung divu_6432_3232_(xhi,xlo,y); r_zuweisung divu_32_rest; } + #if defined(__m68k__) || defined(__sparc__) || defined(__sparc64__) || defined(__arm__) || (defined(__i386__) && !defined(WATCOM) && !defined(MICROSOFT)) || defined(__hppa__) + // divu_6432_3232_ extern in Assembler + #if defined(__sparc__) || defined(__sparc64__) + extern "C" uint32 _get_g1 (void); + #define divu_32_rest (_get_g1()) // Rückgabe im Register %g1 + #else + #define NEED_VAR_divu_32_rest + #endif + #else + #define NEED_FUNCTION_divu_6432_3232_ + #endif +#endif + +#ifdef HAVE_FAST_LONGLONG + +// Dividiert eine 64-Bit-Zahl durch eine 32-Bit-Zahl und +// liefert einen 32-Bit-Quotienten und einen 32-Bit-Rest. +// divu_6432_3232_w(x,y,q=,r=); +// > uint64 x: Zähler +// > uint32 y: Nenner +// > Es sei bekannt, daß 0 <= x < 2^32*y . +// < uint32 q: floor(x/y) +// < uint32 r: x mod y +// < x = q*y+r +#if defined(__GNUC__) + #define divu_6432_3232_w(x,y,q_zuweisung,r_zuweisung) \ + ({var uint64 __x = (x); \ + var uint32 __y = (y); \ + var uint32 __q = floor(__x,(uint64)__y); \ + q_zuweisung __q; r_zuweisung (uint32)__x - __q * __y; \ + }) +#else + #define divu_6432_3232_w(x,y,q_zuweisung,r_zuweisung) \ + { var uint64 __x = (x); \ + divu_6432_3232(high32(__x),low32(__x),(y),q_zuweisung,r_zuweisung); \ + } +#endif + +// Dividiert eine 64-Bit-Zahl durch eine 64-Bit-Zahl und +// liefert einen 64-Bit-Quotienten und einen 64-Bit-Rest. +// divu_6464_6464(x,y,q=,r=); +// > uint64 x: Zähler +// > uint64 y: Nenner +// Es sei bekannt, daß y>0. +// < uint64 q: floor(x/y) +// < uint64 r: x mod y +// < x = q*y+r +#if defined(__alpha__) || 1 + #define divu_6464_6464(x,y,q_zuweisung,r_zuweisung) \ + { var uint64 __x = (x); \ + var uint64 __y = (y); \ + q_zuweisung (__x / __y); \ + r_zuweisung (__x % __y); \ + } +#endif + +// Dividiert eine 128-Bit-Zahl durch eine 64-Bit-Zahl und +// liefert einen 64-Bit-Quotienten und einen 64-Bit-Rest. +// divu_12864_6464(xhi,xlo,y,q=,r=); +// > uint64 xhi,xlo: x = 2^64*xhi+xlo = Zähler +// > uint64 y: Nenner +// > Es sei bekannt, daß 0 <= x < 2^64*y . +// < uint64 q: floor(x/y) +// < uint64 r: x mod y +// < x = q*y+r + extern "C" uint64 divu_12864_6464_ (uint64 xhi, uint64 xlo, uint64 y); // -> Quotient q + extern "C" uint64 divu_64_rest; // -> Rest r + #define divu_12864_6464(xhi,xlo,y,q_zuweisung,r_zuweisung) \ + { q_zuweisung divu_12864_6464_(xhi,xlo,y); r_zuweisung divu_64_rest; } + #define NEED_FUNCTION_divu_12864_6464_ + +#endif /* HAVE_FAST_LONGLONG */ + + +// Zieht die Ganzzahl-Wurzel aus einer 32-Bit-Zahl und +// liefert eine 16-Bit-Wurzel und einen Rest. +// isqrt_32_16(x,y=,sqrtp=); +// > uint32 x: Radikand, >= 2^30, < 2^32 +// < uint16 y: floor(sqrt(x)), >= 2^15, < 2^16 +// < boolean sqrtp: /=0, falls x=y^2 + // Methode: + // y := 2^16 als Anfangswert, + // y := floor((y + floor(x/y))/2) als nächster Wert, + // solange z := floor(x/y) < y, setze y := floor((y+z)/2). + // y ist fertig; x=y^2 genau dann, wenn z=y und die letzte Division aufging. + // (Beweis: + // 1. Die Folge der y ist streng monoton fallend. + // 2. Stets gilt y >= floor(sqrt(x)) (denn für alle y>0 ist + // y + x/y >= 2*sqrt(x) und daher floor((y + floor(x/y))/2) = + // floor(y/2 + x/(2*y)) >= floor(sqrt(x)) ). + // 3. Am Schluß gilt x >= y^2. + // ) + #define isqrt_32_16(x,y_zuweisung,sqrtp_zuweisung) \ + { var uint32 _x = (x); \ + var uint16 _x1 = high16(_x); \ + var uint16 _y = floor(_x1,2) | bit(16-1); \ + loop \ + { var uint16 _z; \ + var uint16 _r; \ + if (_x1 >= _y) /* Division _x/_y ergäbe Ãœberlauf -> _z > _y */\ + { unused (sqrtp_zuweisung FALSE); break; } \ + divu_3216_1616(_x,_y, _z=,_r=); /* Dividiere _x/_y */ \ + if (_z >= _y) \ + { unused (sqrtp_zuweisung (_z == _y) && (_r == 0)); break; } \ + _y = floor((uint16)(_z+_y),2) | bit(16-1); /* _y muß >= 2^15 bleiben */\ + } \ + y_zuweisung _y; \ + } + +// Zieht die Ganzzahl-Wurzel aus einer 64-Bit-Zahl und +// liefert eine 32-Bit-Wurzel und einen Rest. +// isqrt_64_32(xhi,xlo,y=,sqrtp=); +// > uint32 xhi,xlo: Radikand x = 2^32*xhi+xlo, >= 2^62, < 2^64 +// < uint32 y: floor(sqrt(x)), >= 2^31, < 2^32 +// < boolean sqrtp: /=0, falls x=y^2 +#if defined(__sparc__) || defined(__sparc64__) || defined(__m68k__) || defined(__hppa__) + // Methode: + // y := 2^32 als Anfangswert, + // y := floor((y + floor(x/y))/2) als nächster Wert, + // solange z := floor(x/y) < y, setze y := floor((y+z)/2). + // y ist fertig; x=y^2 genau dann, wenn z=y und die letzte Division aufging. + // (Beweis: + // 1. Die Folge der y ist streng monoton fallend. + // 2. Stets gilt y >= floor(sqrt(x)) (denn für alle y>0 ist + // y + x/y >= 2*sqrt(x) und daher floor((y + floor(x/y))/2) = + // floor(y/2 + x/(2*y)) >= floor(sqrt(x)) ). + // 3. Am Schluß gilt x >= y^2. + // ) + #define isqrt_64_32(xhi,xlo,y_zuweisung,sqrtp_zuweisung) \ + { var uint32 _xhi = (xhi); \ + var uint32 _xlo = (xlo); \ + var uint32 _y = floor(_xhi,2) | bit(32-1); \ + loop \ + { var uint32 _z; \ + var uint32 _rest; \ + if (_xhi >= _y) /* Division _x/_y ergäbe Ãœberlauf -> _z > _y */\ + { sqrtp_zuweisung FALSE; break; } \ + divu_6432_3232(_xhi,_xlo,_y, _z=,_rest=); /* Dividiere _x/_y */\ + if (_z >= _y) \ + { sqrtp_zuweisung (_z == _y) && (_rest == 0); break; } \ + _y = floor(_z+_y,2) | bit(32-1); /* _y muß >= 2^31 bleiben */ \ + } \ + y_zuweisung _y; \ + } +#else + // Methode: + // Wie bei UDS_sqrt mit n=2. + // y = 2^16*yhi + ylo ansetzen. + // Dann muß + // yhi = floor(y/2^16) = floor(floor(sqrt(x))/2^16) + // = floor(sqrt(x)/2^16) = floor(sqrt(x/2^32)) = isqrt(xhi) + // sein. Es folgt yhi >= 2^15. + // Danach sucht man das größte ylo >=0 mit + // x - 2^32*yhi^2 >= 2*2^16*yhi*ylo + ylo^2. + // Dazu setzen wir xhi*2^32+xlo := x - 2^32*yhi^2 + // (also xhi := xhi - yhi^2, das ist >=0, <=2*yhi). + // Die Schätzung für die zweite Ziffer + // ylo' := min(2^16-1,floor((xhi*2^32+xlo)/(2*2^16*yhi))) + // erfüllt ylo'-1 <= ylo <= ylo', ist also um höchstens 1 zu groß. + // (Beweis: Rechte Ungleichung klar, da ylo < 2^16 und + // xhi*2^32+xlo >= 2*2^16*yhi*ylo + ylo^2 >= 2*2^16*yhi*ylo + // ==> (xhi*2^32+xlo)/(2*2^16*yhi) >= ylo gelten muß. + // Linke Ungleichung: Falls floor(...)>=2^16, ist + // xhi*2^32+xlo >= 2*2^16*2^16*yhi >= 2*2^16*yhi*(2^16-1) + 2^32 + // >= 2*2^16*yhi*(2^16-1) + (2^16-1)^2 + // und xhi*2^32+xlo < 2*2^16*2^16*yhi + (2^16)^2, also + // ylo = 2^16-1 = ylo'. + // Sonst ist ylo' = floor((xhi*2^32+xlo)/(2*2^16*yhi)), also + // xhi*2^32+xlo >= 2*2^16*yhi*ylo' >= 2*2^16*yhi*(ylo'-1) + 2^32 + // >= 2*2^16*yhi*(ylo'-1) + (ylo'-1)^2, + // also ylo >= ylo'-1 nach Definition von ylo.) + #define isqrt_64_32(xhi,xlo,y_zuweisung,sqrtp_zuweisung) \ + { var uint32 _xhi = (xhi); \ + var uint32 _xlo = (xlo); \ + var uint16 _yhi; \ + var uint16 _ylo; \ + /* erste Ziffer berechnen: */ \ + isqrt_32_16(_xhi,_yhi=,); /* yhi := isqrt(xhi) */ \ + _xhi -= mulu16(_yhi,_yhi); /* jetzt 0 <= xhi <= 2*yhi */ \ + /* x = 2^32*yhi^2 + 2^32*xhi + xlo */ \ + /* Schätzung für die zweite Ziffer berechnen: */ \ + /* ylo := min(2^16-1,floor((xhi*2^32+xlo)/(2*2^16*yhi))) bilden: */\ + {var uint32 _z = (_xhi << 15) | (_xlo >> 17); /* < 2^15*(2*yhi+1) */\ + var uint32 _r = highlow32_0(_yhi); \ + if (_z >= _r) \ + { _ylo = bit(16)-1; _r = _z - _r + (uint32)_yhi; } \ + else \ + { divu_3216_1616(_z,_yhi, _ylo=,_r=); } \ + /* x = 2^32*yhi^2 + 2*2^16*yhi*ylo + 2^17*r + (xlo mod 2^17), */ \ + /* 0 <= r < yhi + 2^15 */ \ + _xlo = (_r << 17) | (_xlo & (bit(17)-1)); \ + /* x = 2^32*yhi^2 + 2*2^16*yhi*ylo + 2^32*floor(r/2^15) + xlo */ \ + _z = mulu16(_ylo,_ylo); /* z = ylo^2 */ \ + /* Versuche vom Rest 2^32*floor(r/2^15) + xlo z zu subtrahieren. */\ + /* Falls Rest >= z (d.h. r>=2^15 oder xlo>=z), ist ylo fertig, */ \ + /* und es gilt x=y^2 genau dann, wenn r<2^15 und xlo=z. */ \ + /* Sonst (d.h. r<2^15 und xlo= 2^32 > z, also x>y^2. */\ + if (_r < bit(15)) \ + { if (_xlo < _z) \ + { _ylo -= 1; sqrtp_zuweisung FALSE; } \ + else \ + { sqrtp_zuweisung (_xlo == _z); } \ + } \ + else \ + { sqrtp_zuweisung FALSE; } \ + y_zuweisung highlow32(_yhi,_ylo); \ + }} +#endif + +#ifdef HAVE_FAST_LONGLONG + +// Zieht die Ganzzahl-Wurzel aus einer 128-Bit-Zahl und +// liefert eine 64-Bit-Wurzel und einen Rest. +// isqrt_128_64(xhi,xlo,y=,sqrtp=); +// > uint64 xhi,xlo: Radikand x = 2^64*xhi+xlo, >= 2^126, < 2^128 +// < uint64 y: floor(sqrt(x)), >= 2^63, < 2^64 +// < boolean sqrtp: /=0, falls x=y^2 + // Methode: + // Wie bei UDS_sqrt mit n=2. + // y = 2^32*yhi + ylo ansetzen. + // Dann muß + // yhi = floor(y/2^32) = floor(floor(sqrt(x))/2^32) + // = floor(sqrt(x)/2^32) = floor(sqrt(x/2^64)) = isqrt(xhi) + // sein. Es folgt yhi >= 2^31. + // Danach sucht man das größte ylo >=0 mit + // x - 2^64*yhi^2 >= 2*2^32*yhi*ylo + ylo^2. + // Dazu setzen wir xhi*2^64+xlo := x - 2^64*yhi^2 + // (also xhi := xhi - yhi^2, das ist >=0, <=2*yhi). + // Die Schätzung für die zweite Ziffer + // ylo' := min(2^32-1,floor((xhi*2^64+xlo)/(2*2^32*yhi))) + // erfüllt ylo'-1 <= ylo <= ylo', ist also um höchstens 1 zu groß. + // (Beweis: Rechte Ungleichung klar, da ylo < 2^32 und + // xhi*2^64+xlo >= 2*2^32*yhi*ylo + ylo^2 >= 2*2^32*yhi*ylo + // ==> (xhi*2^64+xlo)/(2*2^32*yhi) >= ylo gelten muß. + // Linke Ungleichung: Falls floor(...)>=2^32, ist + // xhi*2^64+xlo >= 2*2^32*2^32*yhi >= 2*2^32*yhi*(2^32-1) + 2^64 + // >= 2*2^32*yhi*(2^32-1) + (2^32-1)^2 + // und xhi*2^64+xlo < 2*2^32*2^32*yhi + (2^32)^2, also + // ylo = 2^32-1 = ylo'. + // Sonst ist ylo' = floor((xhi*2^64+xlo)/(2*2^32*yhi)), also + // xhi*2^64+xlo >= 2*2^32*yhi*ylo' >= 2*2^32*yhi*(ylo'-1) + 2^64 + // >= 2*2^32*yhi*(ylo'-1) + (ylo'-1)^2, + // also ylo >= ylo'-1 nach Definition von ylo.) + #define isqrt_128_64(x_hi,x_lo,y_zuweisung,sqrtp_zuweisung) \ + { var uint64 xhi = (x_hi); \ + var uint64 xlo = (x_lo); \ + var uint32 yhi; \ + var uint32 ylo; \ + /* erste Ziffer berechnen: */ \ + isqrt_64_32(high32(xhi),low32(xhi),yhi=,); /* yhi := isqrt(xhi) */\ + xhi -= mulu32_w(yhi,yhi); /* jetzt 0 <= xhi <= 2*yhi */ \ + /* x = 2^64*yhi^2 + 2^64*xhi + xlo */ \ + /* Schätzung für die zweite Ziffer berechnen: */ \ + /* ylo := min(2^32-1,floor((xhi*2^64+xlo)/(2*2^32*yhi))) bilden: */\ + {var uint64 z = (xhi << 31) | (xlo >> 33); /* < 2^31*(2*yhi+1) */ \ + var uint64 r = highlow64_0(yhi); \ + if (z >= r) \ + { ylo = bit(32)-1; r = z - r + (uint64)yhi; } \ + else \ + { divu_6432_3232_w(z,yhi, ylo=,r=); } \ + /* x = 2^64*yhi^2 + 2*2^32*yhi*ylo + 2^33*r + (xlo mod 2^33), */ \ + /* 0 <= r < yhi + 2^31 */ \ + xlo = (r << 33) | (xlo & (bit(33)-1)); \ + /* x = 2^64*yhi^2 + 2*2^32*yhi*ylo + 2^64*floor(r/2^31) + xlo */ \ + z = mulu32_w(ylo,ylo); /* z = ylo^2 */ \ + /* Versuche vom Rest 2^64*floor(r/2^31) + xlo z zu subtrahieren. */\ + /* Falls Rest >= z (d.h. r>=2^31 oder xlo>=z), ist ylo fertig, */ \ + /* und es gilt x=y^2 genau dann, wenn r<2^31 und xlo=z. */ \ + /* Sonst (d.h. r<2^31 und xlo= 2^64 > z, also x>y^2. */\ + if (r < bit(31)) \ + { if (xlo < z) \ + { ylo -= 1; sqrtp_zuweisung FALSE; } \ + else \ + { sqrtp_zuweisung (xlo == z); } \ + } \ + else \ + { sqrtp_zuweisung FALSE; } \ + y_zuweisung highlow64(yhi,ylo); \ + }} + +#endif /* HAVE_FAST_LONGLONG */ + +// Zieht die Ganzzahl-Wurzel aus einer 32-Bit-Zahl und +// liefert eine 16-Bit-Wurzel. +// isqrt(x) +// > uintL x : Radikand, >=0, <2^32 +// < uintL ergebnis : Wurzel, >=0, <2^16 + extern uintL isqrt (uintL x); + +// Zieht die Ganzzahl-Wurzel aus einer 64-Bit-Zahl und +// liefert eine 32-Bit-Wurzel. +// isqrt(x1,x0) +// > uintL2 x = x1*2^32+x0 : Radikand, >=0, <2^64 +// < uintL ergebnis : Wurzel, >=0, <2^32 + extern uintL isqrt (uintL x1, uintL x0); + + +// Bits einer 8-Bit-Zahl zählen: +// integerlength8(digit,size=); +// setzt size auf die höchste in digit vorkommende Bitnummer. +// > digit: ein uint8 >0 +// < size: >0, <=8, mit 2^(size-1) <= digit < 2^size +#if defined(__GNUC__) && defined(__m68k__) && !defined(NO_ASM) + #define integerlength8(digit,size_zuweisung) \ + { var uintL zero_counter; /* zählt die führenden Nullbits in digit */\ + __asm__("bfffo %1{#0:#8},%0" : "=d" (zero_counter) : "dm" ((uint8)(digit)) ); \ + size_zuweisung (8-zero_counter); \ + } +#elif defined(__sparc__) && !defined(__sparc64__) + #define integerlength8(digit,size_zuweisung) \ + integerlength32((uint32)(digit),size_zuweisung) // siehe unten +#elif defined(__GNUC__) && defined(__i386__) && !defined(NO_ASM) + #define integerlength8(digit,size_zuweisung) \ + integerlength16((uint16)(digit),size_zuweisung) +#else + #define integerlength8(digit,size_zuweisung) \ + { var uintC bitsize = 1; \ + var uintL x8 = (uint8)(digit); \ + /* x8 hat höchstens 8 Bits. */\ + if (x8 >= bit(4)) { x8 = x8>>4; bitsize += 4; } \ + /* x8 hat höchstens 4 Bits. */\ + if (x8 >= bit(2)) { x8 = x8>>2; bitsize += 2; } \ + /* x8 hat höchstens 2 Bits. */\ + if (x8 >= bit(1)) { /* x8 = x8>>1; */ bitsize += 1; } \ + /* x8 hat höchstens 1 Bit. Dieses Bit muß gesetzt sein. */\ + size_zuweisung bitsize; \ + } +#endif + +// Bits einer 16-Bit-Zahl zählen: +// integerlength16(digit,size=); +// setzt size auf die höchste in digit vorkommende Bitnummer. +// > digit: ein uint16 >0 +// < size: >0, <=16, mit 2^(size-1) <= digit < 2^size +#if defined(__GNUC__) && defined(__m68k__) && !defined(NO_ASM) + #define integerlength16(digit,size_zuweisung) \ + { var uintL zero_counter; /* zählt die führenden Nullbits in digit */\ + __asm__("bfffo %1{#0:#16},%0" : "=d" (zero_counter) : "dm" ((uint16)(digit)) ); \ + size_zuweisung (16-zero_counter); \ + } +#elif defined(__sparc__) && !defined(__sparc64__) + #define integerlength16(digit,size_zuweisung) \ + integerlength32((uint32)(digit),size_zuweisung) // siehe unten +#elif defined(__GNUC__) && defined(__i386__) && !defined(NO_ASM) + #define integerlength16(digit,size_zuweisung) \ + { var uintW one_position; /* Position der führenden 1 */\ + __asm__("bsrw %1,%0" : "=r" (one_position) : "r" ((uint16)(digit)) ); \ + size_zuweisung (1+one_position); \ + } +// Die weiteren kommen von gcc/longlong.h : +#elif defined(__GNUC__) && defined(__ibm032__) && !defined(NO_ASM) // RT/ROMP + #define integerlength16(digit,size_zuweisung) \ + { var uintL zero_counter; /* zählt die führenden Nullbits in digit */\ + __asm__("clz %0,%1" : "=r" (zero_counter) : "r" ((uint32)(digit)) ); \ + size_zuweisung (16-zero_counter); \ + } +#else + #define integerlength16(digit,size_zuweisung) \ + { var uintC bitsize = 1; \ + var uintWL x16 = (uint16)(digit); \ + /* x16 hat höchstens 16 Bits. */\ + if (x16 >= bit(8)) { x16 = x16>>8; bitsize += 8; } \ + /* x16 hat höchstens 8 Bits. */\ + if (x16 >= bit(4)) { x16 = x16>>4; bitsize += 4; } \ + /* x16 hat höchstens 4 Bits. */\ + if (x16 >= bit(2)) { x16 = x16>>2; bitsize += 2; } \ + /* x16 hat höchstens 2 Bits. */\ + if (x16 >= bit(1)) { /* x16 = x16>>1; */ bitsize += 1; } \ + /* x16 hat höchstens 1 Bit. Dieses Bit muß gesetzt sein. */\ + size_zuweisung bitsize; \ + } +#endif + +// Bits einer 32-Bit-Zahl zählen: +// integerlength32(digit,size=); +// setzt size auf die höchste in digit vorkommende Bitnummer. +// > digit: ein uint32 >0 +// < size: >0, <=32, mit 2^(size-1) <= digit < 2^size +#if defined(__GNUC__) && defined(__m68k__) && !defined(NO_ASM) + #define integerlength32(digit,size_zuweisung) \ + { var uintL zero_counter; /* zählt die führenden Nullbits in digit */\ + __asm__("bfffo %1{#0:#32},%0" : "=d" (zero_counter) : "dm" ((uint32)(digit)) ); \ + size_zuweisung (32-zero_counter); \ + } +#elif defined(__sparc__) && !defined(__sparc64__) && defined(FAST_DOUBLE) + #define integerlength32(digit,size_zuweisung) \ + {var union { double f; uint32 i[2]; } __fi; \ + const int df_mant_len = 52; /* mantissa bits (excl. hidden bit) */\ + const int df_exp_mid = 1022; /* exponent bias */ \ + /* Bilde 2^52 + digit: */\ + __fi.i[0] = (uint32)(df_mant_len+1+df_exp_mid) << (df_mant_len-32); /* Vorzeichen 0, Exponent 53 */\ + __fi.i[1] = (digit); /* untere 32 Bits setzen (benutzt CL_CPU_BIG_ENDIAN_P !) */\ + /* subtrahiere 2^52: */\ + __fi.f = __fi.f - (double)(4503599627370496.0L); \ + /* Hole davon den Exponenten: */\ + size_zuweisung ((__fi.i[0] >> (df_mant_len-32)) - df_exp_mid); \ + } +#elif defined(__GNUC__) && defined(__i386__) && !defined(NO_ASM) + #define integerlength32(digit,size_zuweisung) \ + { var uintL one_position; /* Position der führenden 1 */\ + __asm__("bsrl %1,%0" : "=r" (one_position) : "rm" ((uint32)(digit)) ); \ + size_zuweisung (1+one_position); \ + } +#elif defined(__hppa__) && !defined(NO_ASM) + #define integerlength32(digit,size_zuweisung) \ + size_zuweisung length32(digit); + extern "C" uintL length32 (uintL digit); // extern in Assembler +// Die weiteren kommen von gcc/longlong.h : +#elif defined(__GNUC__) && (defined(__a29k__) || defined(___AM29K__)) && !defined(NO_ASM) + #define integerlength32(digit,size_zuweisung) \ + { var uintL zero_counter; /* zählt die führenden Nullbits in digit */\ + __asm__("clz %0,%1" : "=r" (zero_counter) : "r" ((uint32)(digit)) ); \ + size_zuweisung (32-zero_counter); \ + } +#elif defined(__GNUC__) && defined(__gmicro__) && !defined(NO_ASM) + #define integerlength32(digit,size_zuweisung) \ + { var uintL zero_counter; /* zählt die führenden Nullbits in digit */\ + __asm__("bsch/1 %1,%0" : "=g" (zero_counter) : "g" ((uint32)(digit)) ); \ + size_zuweisung (32-zero_counter); \ + } +#elif defined(__GNUC__) && defined(__rs6000__) && !defined(NO_ASM) + #ifdef _AIX + // old assembler syntax + #define integerlength32(digit,size_zuweisung) \ + { var uintL zero_counter; /* zählt die führenden Nullbits in digit */\ + __asm__("cntlz %0,%1" : "=r" (zero_counter) : "r" ((uint32)(digit)) ); \ + size_zuweisung (32-zero_counter); \ + } + #else + // new assembler syntax + #define integerlength32(digit,size_zuweisung) \ + { var uintL zero_counter; /* zählt die führenden Nullbits in digit */\ + __asm__("cntlzw %0,%1" : "=r" (zero_counter) : "r" ((uint32)(digit)) ); \ + size_zuweisung (32-zero_counter); \ + } + #endif +#elif defined(__GNUC__) && defined(__m88k__) && !defined(NO_ASM) + #define integerlength32(digit,size_zuweisung) \ + { var uintL one_position; /* Position der führenden 1 */\ + __asm__("ff1 %0,%1" : "=r" (one_position) : "r" ((uint32)(digit)) ); \ + size_zuweisung (1+one_position); \ + } +#elif defined(__GNUC__) && defined(__ibm032__) && !defined(NO_ASM) // RT/ROMP + #define integerlength32(digit,size_zuweisung) \ + { var uintL x32 = (uint32)(digit); \ + if (x32 >= bit(16)) \ + { integerlength16(x32>>16,size_zuweisung 16 + ); } \ + else \ + { integerlength16(x32,size_zuweisung); } \ + } +#else + #define integerlength32(digit,size_zuweisung) \ + { var uintC bitsize = 1; \ + var uintL x32 = (uint32)(digit); \ + /* x32 hat höchstens 32 Bits. */\ + if (x32 >= bit(16)) { x32 = x32>>16; bitsize += 16; } \ + /* x32 hat höchstens 16 Bits. */\ + if (x32 >= bit(8)) { x32 = x32>>8; bitsize += 8; } \ + /* x32 hat höchstens 8 Bits. */\ + if (x32 >= bit(4)) { x32 = x32>>4; bitsize += 4; } \ + /* x32 hat höchstens 4 Bits. */\ + if (x32 >= bit(2)) { x32 = x32>>2; bitsize += 2; } \ + /* x32 hat höchstens 2 Bits. */\ + if (x32 >= bit(1)) { /* x32 = x32>>1; */ bitsize += 1; } \ + /* x32 hat höchstens 1 Bit. Dieses Bit muß gesetzt sein. */\ + size_zuweisung bitsize; \ + } +#endif + +// Bits einer 64-Bit-Zahl zählen: +// integerlength64(digit,size=); +// setzt size auf die höchste in digit vorkommende Bitnummer. +// > digit: ein uint64 >0 +// < size: >0, <=64, mit 2^(size-1) <= digit < 2^size + #define integerlength64(digit,size_zuweisung) \ + { var uintC bitsize = 1; \ + var uint64 x64 = (uint64)(digit); \ + /* x64 hat höchstens 64 Bits. */\ + if (x64 >= bit(32)) { x64 = x64>>32; bitsize += 32; } \ + /* x64 hat höchstens 32 Bits. */\ + if (x64 >= bit(16)) { x64 = x64>>16; bitsize += 16; } \ + /* x64 hat höchstens 16 Bits. */\ + if (x64 >= bit(8)) { x64 = x64>>8; bitsize += 8; } \ + /* x64 hat höchstens 8 Bits. */\ + if (x64 >= bit(4)) { x64 = x64>>4; bitsize += 4; } \ + /* x64 hat höchstens 4 Bits. */\ + if (x64 >= bit(2)) { x64 = x64>>2; bitsize += 2; } \ + /* x64 hat höchstens 2 Bits. */\ + if (x64 >= bit(1)) { /* x64 = x64>>1; */ bitsize += 1; } \ + /* x64 hat höchstens 1 Bit. Dieses Bit muß gesetzt sein. */\ + size_zuweisung bitsize; \ + } + +// Hintere Nullbits eines 32-Bit-Wortes zählen: +// ord2_32(digit,count=); +// setzt size auf die kleinste in digit vorkommende Bitnummer. +// > digit: ein uint32 >0 +// < count: >=0, <32, mit 2^count | digit, digit/2^count ungerade + #if defined(__GNUC__) && defined(__i386__) && !defined(NO_ASM) + #define ord2_32(digit,count_zuweisung) \ + { var uintL one_position; /* Position der letzten 1 */\ + __asm__("bsfl %1,%0" : "=r" (one_position) : "rm" ((uint32)(digit)) ); \ + count_zuweisung one_position; \ + } + #define FAST_ORD2 + #elif defined(__sparc__) && !defined(__sparc64__) + #define ord2_32(digit,count_zuweisung) \ + { var uint32 n = (digit); \ + n = n | -n; \ + n = (n<<4) + n; \ + n = (n<<6) + n; \ + n = n - (n<<16); /* or n = n ^ (n<<16); or n = n &~ (n<<16); */ \ + /* static const char ord2_tab [64] = {-1,0,1,12,2,6,-1,13,3,-1,7,-1,-1,-1,-1,14,10,4,-1,-1,8,-1,-1,25,-1,-1,-1,-1,-1,21,27,15,31,11,5,-1,-1,-1,-1,-1,9,-1,-1,24,-1,-1,20,26,30,-1,-1,-1,-1,23,-1,19,29,-1,22,18,28,17,16,-1}; */ \ + /* count_zuweisung ord2_tab[n>>26]; */ \ + count_zuweisung "\377\000\001\014\002\006\377\015\003\377\007\377\377\377\377\016\012\004\377\377\010\377\377\031\377\377\377\377\377\025\033\017\037\013\005\377\377\377\377\377\011\377\377\030\377\377\024\032\036\377\377\377\377\027\377\023\035\377\026\022\034\021\020"[n>>26]; \ + } + #define FAST_ORD2 + #else + // Sei n = ord2(x). Dann ist logxor(x,x-1) = 2^n + (2^n-1) = 2^(n+1)-1. + // Also (ord2 x) = (1- (integer-length (logxor x (1- x)))) . + #define ord2_32(digit,count_zuweisung) \ + { var uint32 _digit = digit ^ (digit - 1); \ + integerlength32(_digit,count_zuweisung -1 + ) \ + } + #endif + + +// Bits eines Wortes zählen. +// logcount_NN(); +// > xNN: ein uintNN +// < xNN: Anzahl der darin gesetzten Bits + // Bits von x8 zählen: (Input x8, Output x8) + #define logcount_8() \ + ( /* x8 besteht aus 8 1-Bit-Zählern (0,1). */\ + x8 = (x8 & 0x55U) + ((x8 & 0xAAU) >> 1), \ + /* x8 besteht aus 4 2-Bit-Zählern (0,1,2). */\ + x8 = (x8 & 0x33U) + ((x8 & 0xCCU) >> 2), \ + /* x8 besteht aus 2 4-Bit-Zählern (0,1,2,3,4). */\ + x8 = (x8 & 0x0FU) + (x8 >> 4) \ + /* x8 besteht aus 1 8-Bit-Zähler (0,...,8). */\ + ) + // Bits von x16 zählen: (Input x16, Output x16) + #define logcount_16() \ + ( /* x16 besteht aus 16 1-Bit-Zählern (0,1). */\ + x16 = (x16 & 0x5555U) + ((x16 & 0xAAAAU) >> 1), \ + /* x16 besteht aus 8 2-Bit-Zählern (0,1,2). */\ + x16 = (x16 & 0x3333U) + ((x16 & 0xCCCCU) >> 2), \ + /* x16 besteht aus 4 4-Bit-Zählern (0,1,2,3,4). */\ + x16 = (x16 & 0x0F0FU) + ((x16 & 0xF0F0U) >> 4), \ + /* x16 besteht aus 2 8-Bit-Zählern (0,...,8). */\ + x16 = (x16 & 0x00FFU) + (x16 >> 8) \ + /* x16 besteht aus 1 16-Bit-Zähler (0,...,16). */\ + ) + // Bits von x32 zählen: (Input x32, Output x32) + #define logcount_32() \ + ( /* x32 besteht aus 32 1-Bit-Zählern (0,1). */\ + x32 = (x32 & 0x55555555UL) + ((x32 & 0xAAAAAAAAUL) >> 1), \ + /* x32 besteht aus 16 2-Bit-Zählern (0,1,2). */\ + x32 = (x32 & 0x33333333UL) + ((x32 & 0xCCCCCCCCUL) >> 2), \ + /* x32 besteht aus 8 4-Bit-Zählern (0,1,2,3,4). */\ + x32 = high16(x32)+low16(x32), \ + /* x32 besteht aus 4 4-Bit-Zählern (0,...,8). */\ + x32 = (x32 & 0x0F0FU) + ((x32 & 0xF0F0U) >> 4), \ + /* x32 besteht aus 2 8-Bit-Zählern (0,...,16). */\ + x32 = (x32 & 0x00FFU) + (x32 >> 8) \ + /* x32 besteht aus 1 16-Bit-Zähler (0,...,32). */\ + ) + // Bits von x64 zählen: (Input x64, Output x64) + #define logcount_64() \ + ( /* x64 besteht aus 64 1-Bit-Zählern (0,1). */\ + x64 = (x64 & 0x5555555555555555UL) + ((x64 & 0xAAAAAAAAAAAAAAAAUL) >> 1),\ + /* x64 besteht aus 32 2-Bit-Zählern (0,1,2). */\ + x64 = (x64 & 0x3333333333333333UL) + ((x64 & 0xCCCCCCCCCCCCCCCCUL) >> 2),\ + /* x64 besteht aus 16 4-Bit-Zählern (0,1,2,3,4). */\ + x64 = (uint32)(x64 + (x64 >> 32)), \ + /* x64 besteht aus 8 4-Bit-Zählern (0,...,8). */\ + x64 = (x64 & 0x0F0F0F0FUL) + ((x64 & 0xF0F0F0F0UL) >> 4), \ + /* x64 besteht aus 4 8-Bit-Zählern (0,...,16). */\ + x64 = (x64 & 0x00FF00FFU) + ((x64 & 0xFF00FF00U) >> 8), \ + /* x64 besteht aus 2 16-Bit-Zählern (0,...,32). */\ + x64 = (x64 & 0x0000FFFFU) + (x64 >> 16) \ + /* x64 besteht aus 1 16-Bit-Zähler (0,...,64). */\ + ) + + +#endif /* _CL_LOW_H */ diff --git a/src/base/cl_macros.h b/src/base/cl_macros.h new file mode 100644 index 0000000..d4a1959 --- /dev/null +++ b/src/base/cl_macros.h @@ -0,0 +1,251 @@ +// CLN internal macros + +#ifndef _CL_MACROS_H +#define _CL_MACROS_H + +// Concatenation of macroexpanded tokens. +// Example: +// #undef x +// #define y 16 +// CONCAT(x,y) ==> 'x16' (not 'xy' !) + #define CONCAT_(xxx,yyy) xxx##yyy + #define CONCAT3_(aaa,bbb,ccc) aaa##bbb##ccc + #define CONCAT4_(aaa,bbb,ccc,ddd) aaa##bbb##ccc##ddd + #define CONCAT5_(aaa,bbb,ccc,ddd,eee) aaa##bbb##ccc##ddd##eee + #define CONCAT6_(aaa,bbb,ccc,ddd,eee,fff) aaa##bbb##ccc##ddd##eee##fff + #define CONCAT7_(aaa,bbb,ccc,ddd,eee,fff,ggg) aaa##bbb##ccc##ddd##eee##fff##ggg + #define CONCAT(xxx,yyy) CONCAT_(xxx,yyy) + #define CONCAT3(aaa,bbb,ccc) CONCAT3_(aaa,bbb,ccc) + #define CONCAT4(aaa,bbb,ccc,ddd) CONCAT4_(aaa,bbb,ccc,ddd) + #define CONCAT5(aaa,bbb,ccc,ddd,eee) CONCAT5_(aaa,bbb,ccc,ddd,eee) + #define CONCAT6(aaa,bbb,ccc,ddd,eee,fff) CONCAT6_(aaa,bbb,ccc,ddd,eee,fff) + #define CONCAT7(aaa,bbb,ccc,ddd,eee,fff,ggg) CONCAT7_(aaa,bbb,ccc,ddd,eee,fff,ggg) + +// Convert tokens to strings. +// STRING(token) ==> "token" + #define STRING(token) #token + #define STRINGIFY(token) STRING(token) + +// Declare functions that don't return. +// nonreturning_function(extern,exit,(void)); == extern void exit (void); + #ifdef __GNUC__ + #if (__GNUC__ >= 3) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 90)) + #define nonreturning_function(storclass,funname,arguments) \ + storclass void funname arguments __attribute__((__noreturn__)) + #else + #define nonreturning_function(storclass,funname,arguments) \ + typedef void CONCAT3(funname,_function_,__LINE__) arguments; \ + storclass __volatile__ CONCAT3(funname,_function_,__LINE__) funname + #endif + #else + #define nonreturning_function(storclass,funname,arguments) \ + storclass void funname arguments + #endif + +// Declaration of variables. + #define var + +// `if' with more than one clause: +// if (cond1) ... {elif (condi) ...} [else ...] + #define elif else if + +// Endless loop, leave with break; or return...; + #define loop while (1) + +// Reversed end condition. +// Allows until (expression) statement +// and do statement until (expression); + #define until(expression) while(!(expression)) + +// Boolean values. + #define FALSE 0 + #define TRUE 1 + +// Ignore a value (instead of assigning it to a variable). +// unused ... + #if defined(__GNUC__) || defined(__KCC) // avoid a gcc warning "statement with no effect" + #define unused (void) + #else + #define unused + #endif + +// Denotes a point where control flow can never arrive. +// NOTREACHED + #define NOTREACHED cl_notreached_abort(__FILE__,__LINE__); + nonreturning_function(extern,cl_notreached_abort, (const char* filename, int lineno)); + +// Check an arithmetic expression. +// ASSERT(expr) + #define ASSERT(expr) { if (!(expr)) { NOTREACHED } } + +// alloca() + #if defined(__GNUC__) && !defined(__riscos) && !defined(__convex__) + #undef alloca + #define alloca __builtin_alloca + #elif defined(_MSC_VER) + #include + #define alloca _alloca + #elif defined(HAVE_ALLOCA_H) || defined(__riscos) + #include + #ifndef alloca // Sometimes `alloca' is defined as a macro... + #if defined(__osf__) + extern "C" char* alloca (int size); + #else + extern "C" void* alloca (int size); + #endif + #endif + #elif defined(_AIX) + #pragma alloca // AIX requires this to be the first thing in the file. + #elif defined(WATCOM) + #include // defines `alloca' as a macro + #elif !defined(NO_ALLOCA) + extern "C" void* alloca (int size); + #endif + +// NULL pointer. + #undef NULL + #define NULL 0 + +// Bit number n (0<=n<32) + #define bit(n) (1L<<(n)) +// Bit number n (0=12) && ((sint32)((uint32)(x) << (31-(n))) < 0) ) \ + ) + #endif + #endif +// minus bit number n (0<=n<32) + #define minus_bit(n) (-1L<<(n)) +// minus bit number n (0=long_bitsize. + #define bitc(n) (1UL << (((n) >= 0 && (n) < long_bitsize) ? (n) : 0)) + +// floor(a,b) for a>=0, b>0 returns floor(a/b). +// b should be a constant expression. + #define floor(a_from_floor,b_from_floor) ((a_from_floor) / (b_from_floor)) +// Save the macro in case we need to include . + #define cln_floor(a_from_floor,b_from_floor) ((a_from_floor) / (b_from_floor)) + +// ceiling(a,b) for a>=0, b>0 returns ceiling(a/b) = floor((a+b-1)/b). +// b should be a constant expression. + #define ceiling(a_from_ceiling,b_from_ceiling) \ + (((a_from_ceiling) + (b_from_ceiling) - 1) / (b_from_ceiling)) + +// round_down(a,b) decreases a>=0 such that it becomes divisible by b>0. +// b should be a constant expression. + #define round_down(a_from_round,b_from_round) \ + (floor(a_from_round,b_from_round)*(b_from_round)) + +// round_up(a,b) increases a>=0 such that it becomes divisible by b>0. +// b should be a constant expression. + #define round_up(a_from_round,b_from_round) \ + (ceiling(a_from_round,b_from_round)*(b_from_round)) + +// We never call malloc(0), so no need to handle it. + #define __MALLOC_0_RETURNS_NULL + +// Loop which executes a statement a given number of times. +// dotimesC(countvar,count,statement); +// countvar must be of type `uintC'. It is modified! + #define dotimesC(countvar_from_dotimesC,count_from_dotimesC,statement_from_dotimesC) \ + { countvar_from_dotimesC = (count_from_dotimesC); \ + until (countvar_from_dotimesC==0) \ + {statement_from_dotimesC; countvar_from_dotimesC--; } \ + } + #define dotimespC(countvar_from_dotimespC,count_from_dotimespC,statement_from_dotimespC) \ + { countvar_from_dotimespC = (count_from_dotimespC); \ + do {statement_from_dotimespC} until (--countvar_from_dotimespC==0); \ + } + +// doconsttimes(count,statement); +// führt statement count mal aus (count mal der Code!), +// wobei count eine constant-expression >=0, <=8 ist. + #define doconsttimes(count_from_doconsttimes,statement_from_doconsttimes) \ + { if (0 < (count_from_doconsttimes)) { statement_from_doconsttimes; } \ + if (1 < (count_from_doconsttimes)) { statement_from_doconsttimes; } \ + if (2 < (count_from_doconsttimes)) { statement_from_doconsttimes; } \ + if (3 < (count_from_doconsttimes)) { statement_from_doconsttimes; } \ + if (4 < (count_from_doconsttimes)) { statement_from_doconsttimes; } \ + if (5 < (count_from_doconsttimes)) { statement_from_doconsttimes; } \ + if (6 < (count_from_doconsttimes)) { statement_from_doconsttimes; } \ + if (7 < (count_from_doconsttimes)) { statement_from_doconsttimes; } \ + } + +// DOCONSTTIMES(count,macroname); +// ruft count mal den Macro macroname auf (count mal der Code!), +// wobei count eine constant-expression >=0, <=8 ist. +// Dabei bekommt macroname der Reihe nach die Werte 0,...,count-1 übergeben. + #define DOCONSTTIMES(count_from_DOCONSTTIMES,macroname_from_DOCONSTTIMES) \ + { if (0 < (count_from_DOCONSTTIMES)) { macroname_from_DOCONSTTIMES((0 < (count_from_DOCONSTTIMES) ? 0 : 0)); } \ + if (1 < (count_from_DOCONSTTIMES)) { macroname_from_DOCONSTTIMES((1 < (count_from_DOCONSTTIMES) ? 1 : 0)); } \ + if (2 < (count_from_DOCONSTTIMES)) { macroname_from_DOCONSTTIMES((2 < (count_from_DOCONSTTIMES) ? 2 : 0)); } \ + if (3 < (count_from_DOCONSTTIMES)) { macroname_from_DOCONSTTIMES((3 < (count_from_DOCONSTTIMES) ? 3 : 0)); } \ + if (4 < (count_from_DOCONSTTIMES)) { macroname_from_DOCONSTTIMES((4 < (count_from_DOCONSTTIMES) ? 4 : 0)); } \ + if (5 < (count_from_DOCONSTTIMES)) { macroname_from_DOCONSTTIMES((5 < (count_from_DOCONSTTIMES) ? 5 : 0)); } \ + if (6 < (count_from_DOCONSTTIMES)) { macroname_from_DOCONSTTIMES((6 < (count_from_DOCONSTTIMES) ? 6 : 0)); } \ + if (7 < (count_from_DOCONSTTIMES)) { macroname_from_DOCONSTTIMES((7 < (count_from_DOCONSTTIMES) ? 7 : 0)); } \ + } + +// AT_INITIALIZATION(id) { ... } +// executes the given code at initialization time of the file. +// The id is something unique. + #define AT_INITIALIZATION(id) \ + class CONCAT3(INIT_CLASS_,id,__LINE__) { \ + public: CONCAT3(INIT_CLASS_,id,__LINE__) (void); \ + } CONCAT4(INIT_CLASS_,id,__LINE__,_DUMMY); \ + inline CONCAT3(INIT_CLASS_,id,__LINE__)::CONCAT3(INIT_CLASS_,id,__LINE__) (void) + +// AT_DESTRUCTION(id) { ... } +// executes the given code at destruction time of the file. +// The id is something unique. + #define AT_DESTRUCTION(id) \ + class CONCAT3(DESTR_CLASS_,id,__LINE__) { \ + public: ~CONCAT3(DESTR_CLASS_,id,__LINE__) (void); \ + } CONCAT4(DESTR_CLASS_,id,__LINE__,_DUMMY); \ + CONCAT3(DESTR_CLASS_,id,__LINE__)::~CONCAT3(DESTR_CLASS_,id,__LINE__) (void) + +// Inside a class definition: +// Overload `new' so that a class object can be allocated anywhere. +#if !((defined(__rs6000__) || defined(__alpha__)) && !defined(__GNUC__)) +#define ALLOCATE_ANYWHERE(classname) \ + /* Ability to place an object at a given address. */ \ +public: \ + void* operator new (size_t size) { return cl_malloc_hook(size); } \ + void* operator new (size_t size, classname* ptr) { unused size; return ptr; } \ + void operator delete (void* ptr) { cl_free_hook(ptr); } +#else +// For some compilers, work around template problem with "classname". +#define ALLOCATE_ANYWHERE(classname) \ + /* Ability to place an object at a given address. */ \ +public: \ + void* operator new (size_t size) { return cl_malloc_hook(size); } \ + void* operator new (size_t size, void* ptr) { unused size; return ptr; } \ + void operator delete (void* ptr) { cl_free_hook(ptr); } +#endif + +// init1(type, object) (value); +// initializes `object' with `value', by calling `type''s constructor. +// (The identifiers `init' and `Init' are already in use by , +// it's a shame!) +#define init1(type,lvalue) (void) new (&(lvalue)) type + +// MAYBE_INLINE normally expands to nothing. +// Useful for including the implementation of some file inline into another. + #define MAYBE_INLINE + #define MAYBE_INLINE2 + +#endif /* _CL_MACROS_H */ diff --git a/src/base/cl_malloc.cc b/src/base/cl_malloc.cc new file mode 100644 index 0000000..aa7b821 --- /dev/null +++ b/src/base/cl_malloc.cc @@ -0,0 +1,35 @@ +// cl_malloc_hook, cl_free_hook. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_malloc.h" + + +// Implementation. + +#include +#include "cl_io.h" +#include "cl_abort.h" + +#ifndef malloc + extern "C" void* malloc (size_t size); +#endif +#ifndef free + extern "C" void free (void* ptr); +#endif + +// Just like malloc() but never return NULL pointers. +static void* xmalloc (size_t size) +{ + void* ptr = malloc(size); + if (ptr) + return ptr; + fprint(cl_stderr, "Out of virtual memory.\n"); + cl_abort(); +} + +void* (*cl_malloc_hook) (size_t size) = xmalloc; +void (*cl_free_hook) (void* ptr) = free; + diff --git a/src/base/cl_notreached.cc b/src/base/cl_notreached.cc new file mode 100644 index 0000000..d6ec6bc --- /dev/null +++ b/src/base/cl_notreached.cc @@ -0,0 +1,24 @@ +// cl_notreached_abort(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_macros.h" + + +// Implementation. + +#include "cl_io.h" +#include "cl_abort.h" + +void cl_notreached_abort (const char* filename, int lineno) +{ + fprint(cl_stderr, "Internal error: statement in file "); + fprint(cl_stderr, filename); + fprint(cl_stderr, ", line "); + fprintdecimal(cl_stderr, lineno); + fprint(cl_stderr, " has been reached!!\n"); + fprint(cl_stderr, "Please send the authors of the program a description how you produced this error!\n"); + cl_abort(); +} diff --git a/src/base/cl_offsetof.h b/src/base/cl_offsetof.h new file mode 100644 index 0000000..3192334 --- /dev/null +++ b/src/base/cl_offsetof.h @@ -0,0 +1,14 @@ +// offsetof() and friends + +#ifndef _CL_OFFSETOF_H +#define _CL_OFFSETOF_H + +#undef offsetof +#if defined(__GNUG__) + #define offsetof(type,ident) ((long)&(((type*)1)->ident)-1) +#else + #define offsetof(type,ident) ((long)&(((type*)0)->ident)) +#endif +#define offsetofa(type,ident) offsetof(type,ident[0]) + +#endif /* _CL_OFFSETOF_H */ diff --git a/src/base/cl_sysdep.h b/src/base/cl_sysdep.h new file mode 100644 index 0000000..ca11aaa --- /dev/null +++ b/src/base/cl_sysdep.h @@ -0,0 +1,64 @@ +// System dependent definitions + +#ifndef _CL_SYSDEP_H +#define _CL_SYSDEP_H + +// CPU and other +#include "cl_config.h" + +// char_bitsize, short_bitsize, long_bitsize, long_long_bitsize +#include "cl_intparam.h" + +// The CPU's endianness +#if defined(short_little_endian) || defined(int_little_endian) || defined(long_little_endian) + // Z80, VAX, I80X86, DECALPHA, MIPSEL, ...: + // Low byte at low address, high byte at high address + #if defined(CL_CPU_BIG_ENDIAN_P) + #error "Bogus CL_CPU_BIG_ENDIAN_P!" + #endif + #define CL_CPU_BIG_ENDIAN_P 0 +#endif +#if defined(short_big_endian) || defined(int_big_endian) || defined(long_big_endian) + // MC680X0, SPARC, HPPA, MIPSEB, M88000, RS6000, ...: + // High byte at low address, low byte at high address + #if defined(CL_CPU_BIG_ENDIAN_P) + #error "Bogus CL_CPU_BIG_ENDIAN_P!" + #endif + #define CL_CPU_BIG_ENDIAN_P 1 +#endif +#if !defined(CL_CPU_BIG_ENDIAN_P) + #error "Bogus CL_CPU_BIG_ENDIAN_P!" +#endif + +// Auswahl der Floating-Point-Fähigkeiten: +// FAST_DOUBLE sollte definiert werden, wenn ein Floating-Point-Coprozessor +// vorhanden ist, dessen `double'-Typ IEEE-Floating-Points mit 64 Bits sind. +// FAST_FLOAT sollte definiert werden, wenn ein Floating-Point-Coprozessor +// vorhanden ist, dessen `float'-Typ IEEE-Floating-Points mit 32 Bits sind, +// und der C++-Compiler auch `float'- und nicht `double'-Operationen generiert. +#if defined(__sparc__) || defined(__sparc64__) || defined(__hppa__) || defined(__m88k__) || defined(__rs6000__) + #define FAST_DOUBLE + #define FAST_FLOAT +#endif +#if defined(__i386__) && (defined(linux) || defined(__linux__) || defined(NeXT)) + // Linux hat einen funktionierenden Floating-Point-Coprozessor-Emulator. + // NeXTstep läuft sowieso nur mit Floating-Point-Coprozessor. + // Aber auf Intel-Pentium-Prozessoren ist die FPU fehlerhaft. + #define FAST_DOUBLE + #define FAST_FLOAT +#endif +#if defined(__arm__) + // Bei Integers ist der Prozessor Little-Endian, bei Double-Floats Big-Endian! + #undef FAST_DOUBLE +#endif + +// Macros for internal use. +#include "cl_macros.h" + +// Elementary types. +#include "cl_types.h" + +// Dependencies among modules. +#include "cl_modules.h" + +#endif /* _CL_SYSDEP_H */ diff --git a/src/base/cl_xmacros.h b/src/base/cl_xmacros.h new file mode 100644 index 0000000..971e656 --- /dev/null +++ b/src/base/cl_xmacros.h @@ -0,0 +1,13 @@ +// CLN internal macros extra +// This file must be included after other system include files. + +#ifndef _CL_XMACROS_H +#define _CL_XMACROS_H + +// Swap the contents of two variables: swap(int, x1, x2); + #define swap(swap_type,swap_var1,swap_var2) \ + { var swap_type swap_temp; \ + swap_temp = swap_var1; swap_var1 = swap_var2; swap_var2 = swap_temp; \ + } + +#endif /* _CL_XMACROS_H */ diff --git a/src/base/digit/Makeflags b/src/base/digit/Makeflags new file mode 100644 index 0000000..c329293 --- /dev/null +++ b/src/base/digit/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/base/Makeflags +SUBDIR_INCLUDES += diff --git a/src/base/digit/cl_2D.h b/src/base/digit/cl_2D.h new file mode 100644 index 0000000..87db39e --- /dev/null +++ b/src/base/digit/cl_2D.h @@ -0,0 +1,40 @@ +// Digit level 2-adic arithmetic + +#ifndef _CL_2D_H +#define _CL_2D_H + +#include "cl_types.h" +#include "cl_D.h" + +// Multipliziert zwei Zahlen mod 2^intDsize. +// mul2adic(a,b) +// > uintD a,b: Zahlen mod 2^intDsize +// < ergebnis: Zahl c mod 2^intDsize mit c == a*b mod 2^intDsize + extern uintD mul2adic (uintD a, uintD b); +#if HAVE_DD + inline uintD mul2adic (uintD a, uintD b) + { + return lowD(muluD(a,b)); + } +#else + inline uintD mul2adic (uintD a, uintD b) + { + muluD(a,b, ,return); + } +#endif + +// Potenziert eine Zahl mod 2^intDsize. +// expt_pos(x,y) +// > uintD x: Zahl mod 2^intDsize +// > uintL y: Exponent >0 +// < uintD ergebnis: x^y mod 2^intDsize + extern uintD expt_pos (uintD x, uintL y); + +// Dividiert zwei Zahlen mod 2^intDsize. +// div2adic(a,b) +// > uintD a: Zahl mod 2^intDsize +// > uintD b: ungerade Zahl mod 2^intDsize +// < ergebnis: Zahl c mod 2^intDsize mit b*c == a mod 2^intDsize + extern uintD div2adic (uintD a, uintD b); + +#endif /* _CL_2D_H */ diff --git a/src/base/digit/cl_2D_div.cc b/src/base/digit/cl_2D_div.cc new file mode 100644 index 0000000..36c22e5 --- /dev/null +++ b/src/base/digit/cl_2D_div.cc @@ -0,0 +1,44 @@ +// div2adic(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_2D.h" + + +// Implementation. + +uintD div2adic (uintD a, uintD b) +{ +// Methode: +// Konstruiere c Bit für Bit. +// c := 0, d := a. +// Für j=0,...,intDsize: +// [Hier b*c == a mod 2^j und d = (a-b*c)/2^j.] j=intDsize -> fertig. +// Falls d ungerade, setze c:=c+2^j und d:=(d-b)/2, sonst d:=d/2. +// Ergebnis c. + ASSERT(!((b % 2) ==0)) +#if 1 + {var uintD c = 0; + var uintD bit_j = 1; // 2^j + loop // Verwende a als Variable d + { if (a & bit(0)) { c = c+bit_j; a = a-b; } + a = a>>1; + bit_j = bit_j << 1; + if (bit_j == 0) break; // j=intDsize -> fertig + } + return c; + } +#else + {var uintD bit_j = 1; // 2^j + var uintD b_j = b-1; // (b-1)*2^j + loop // Verwende a als Variable d*2^j+c + { if (a & bit_j) { a = a - b_j; } + b_j = b_j << 1; bit_j = bit_j << 1; + if (bit_j == 0) break; // j=intDsize -> fertig + } + return a; + } +#endif +} diff --git a/src/base/digit/cl_2D_exptpos.cc b/src/base/digit/cl_2D_exptpos.cc new file mode 100644 index 0000000..1cf16af --- /dev/null +++ b/src/base/digit/cl_2D_exptpos.cc @@ -0,0 +1,36 @@ +// expt_pos(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_2D.h" + + +// Implementation. + +uintD expt_pos (uintD a, uintL b) +{ +// Methode: +// a:=x, b:=y, c:=1. [a^b*c bleibt invariant, = x^y.] +// Solange b>1, +// falls b ungerade, setze c:=a*c, +// setze b:=floor(b/2), +// setze a:=a*a. +// Wenn b=1, setze c:=a*c. +// Liefere c. +// Oder optimiert: +// a:=x, b:=y. +// Solange b gerade, setze a:=a*a, b:=b/2. [a^b bleibt invariant, = x^y.] +// c:=a. +// Solange b:=floor(b/2) >0 ist, +// setze a:=a*a, und falls b ungerade, setze c:=a*c. +// Liefere c. + while ((b & bit(0)) == 0) { a = mul2adic(a,a); b = b>>1; } + var uintD c = a; + until ((b = b>>1) == 0) + { a = mul2adic(a,a); + if (b & bit(0)) { c = mul2adic(a,c); } + } + return c; +} diff --git a/src/base/digit/cl_D.h b/src/base/digit/cl_D.h new file mode 100644 index 0000000..dc01288 --- /dev/null +++ b/src/base/digit/cl_D.h @@ -0,0 +1,223 @@ +// Digit level arithmetic + +#ifndef _CL_D_H +#define _CL_D_H + +#include "cl_types.h" +#include "cl_low.h" + +// Aus cl_types.h importiere: +// intDsize Anzahl Bits in einem Digit +// uintD, sintD Integer-Typen für ein Digit +// log2_intDsize log2(intDsize) +// HAVE_DD Flag, das anzeigt, ob ein Integertyp für Doppel-Digits da ist +// intDDsize Anzahl Bits in einem Doppel-Digit +// uintDD,sintDD Integer-Typen für ein Doppel-Digit + +#ifdef HAVE_FAST_LONGLONG + #if !((64%intDsize)==0) + #error "intDsize should be a divisor of 64!" + #endif +#else + #if !((32%intDsize)==0) + #error "intDsize should be a divisor of 32!" + #endif +#endif + + +// Vorzeichen eines Digit bestimmen +// sign_of_sintD(wert) +// > wert: ein Digit +// < sintD ergebnis: 0 falls wert>=0, -1 falls wert<0. +inline sint32 sign_of_sintD (sintD wert) +{ + return sign_of(wert); +} + +#if HAVE_DD + +// High-Digit eines Doppel-Digit bestimmen +// highD(wert) + #if (!(intDsize==16)) + #define highD(x) ((uintD)((uintDD)(x)>>intDsize)) + #else + #define highD high16 + #endif + +// Low-Digit eines Doppel-Digit bestimmen +// lowD(wert) + #define lowD(x) ((uintD)(uintDD)(x)) + +// Ein Doppel-Digit aus ihrem High-Digit und ihrem Low-Digit bestimmen: +// highlowDD(uintD high, uintD low) + #if (!(intDsize==16)) + #define highlowDD(x,y) (((uintDD)(uintD)(x)< 0. + #if (intDsize==8) || (intDsize==16) || (intDsize==64) + #define floorD(arg1,arg2) (floor((uintD)(arg1),(uintD)(arg2))) + #endif + #if (intDsize==32) + #define floorD divu_3232_3232_ + #endif + +// Ganzzahl-Wurzel eines Doppel-Digits berechnen. +// isqrtD(xhi,xlo,y=,sqrtp=); +// > uintD xhi,xlo: Radikand x = 2^intDsize*xhi+xlo, +// >= 2^(2*intDsize-2), < 2^(2*intDsize) +// < uintD y: floor(sqrt(x)), >= 2^(intDsize-1), < 2^intDsize +// < boolean sqrtp: /=0, falls x=y^2 +#if (intDsize==8) + #define isqrtD(xhi,xlo,y_zuweisung,sqrtp_zuweisung) \ + { var uint32 _z; \ + isqrt_32_16((((uint32)xhi<<8) | (uint32)xlo) << 16, _z=,sqrtp_zuweisung); \ + y_zuweisung (_z >> 8); \ + } +#endif +#if (intDsize==16) + #define isqrtD(xhi,xlo,y_zuweisung,sqrtp_zuweisung) \ + isqrt_32_16(highlow32(xhi,xlo),y_zuweisung,sqrtp_zuweisung) +#endif +#if (intDsize==32) + #define isqrtD isqrt_64_32 +#endif +#if (intDsize==64) + #define isqrtD isqrt_128_64 +#endif + +// Bits eines Digit zählen: +// integerlengthD(digit,size=); +// setzt size auf die höchste in digit vorkommende Bitnummer. +// > digit: ein uintD >0 +// < size: >0, <=intDsize, mit 2^(size-1) <= digit < 2^size +#if (intDsize==8) + #define integerlengthD integerlength8 +#endif +#if (intDsize==16) + #define integerlengthD integerlength16 +#endif +#if (intDsize==32) + #define integerlengthD integerlength32 +#endif +#if (intDsize==64) + #define integerlengthD integerlength64 +#endif + +// Hintere Nullbits eines Digits zählen: +// ord2_D(digit,count=); +// setzt size auf die kleinste in digit vorkommende Bitnummer. +// > digit: ein uintD >0 +// < count: >=0, x: ein uintD +// < ergebnis: Anzahl der darin gesetzten Bits +#if (intDsize==8) + inline uint8 logcountD (uint8 x8) { logcount_8(); return x8; } +#endif +#if (intDsize==16) + inline uint16 logcountD (uint16 x16) { logcount_16(); return x16; } +#endif +#if (intDsize==32) + inline uint32 logcountD (uint32 x32) { logcount_32(); return x32; } +#endif +#if (intDsize==64) + inline uint64 logcountD (uint64 x64) { logcount_64(); return x64; } +#endif + +#endif /* _CL_D_H */ diff --git a/src/base/digitseq/Makeflags b/src/base/digitseq/Makeflags new file mode 100644 index 0000000..2e55239 --- /dev/null +++ b/src/base/digitseq/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/base/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/base/digit -I$(srcdir)/base/random -Ibase $(GMP_INCLUDES) diff --git a/src/base/digitseq/cl_2DS.h b/src/base/digitseq/cl_2DS.h new file mode 100644 index 0000000..2ea4c76 --- /dev/null +++ b/src/base/digitseq/cl_2DS.h @@ -0,0 +1,27 @@ +// Digit sequence 2-adic arithmetic + +#ifndef _CL_2DS_H +#define _CL_2DS_H + +// div2adic(a_len,a_LSDptr,b_len,b_LSDptr,dest_LSDptr); +// dividiert die UDS a_LSDptr[-a_len..-1] mod 2^(intDsize*b_len) +// durch die ungerade UDS b_LSDptr[-b_len..-1] mod 2^(intDsize*b_len) +// (a_len >= b_len > 0) und liefert +// den Quotienten q als UDS dest_LSDptr[-b_len..-1] mod 2^(intDsize*b_len) und +// den "Rest" (a-b*q)/2^(intDsize*b_len) als UDS dest_LSDptr[-a_len..-b_len-1]. +// Falls a_len > b_len, wird b implizit als durch Nullen fortgesetzt angenommen. + extern void div2adic (uintC a_len, const uintD* a_LSDptr, uintC b_len, const uintD* b_LSDptr, uintD* dest_LSDptr); + +// div2adic(len,a_LSDptr,b_LSDptr,dest_LSDptr); +// dividiert die UDS a_LSDptr[-len..-1] mod 2^(intDsize*len) +// durch die ungerade UDS b_LSDptr[-len..-1] mod 2^(intDsize*len) (len>0) und +// liefert den Quotienten als UDS dest_LSDptr[-len..-1] mod 2^(intDsize*len). + inline void div2adic (uintC len, const uintD* a_LSDptr, const uintD* b_LSDptr, uintD* dest_LSDptr) + { div2adic(len,a_LSDptr,len,b_LSDptr,dest_LSDptr); } + +// recip2adic(len,a_LSDptr,dest_LSDptr); +// bildet den Kehrwert der ungeraden UDS a_LSDptr[-len..-1] mod 2^(intDsize*len) +// (len>0) und liefert sie als UDS dest_LSDptr[-len..-1] mod 2^(intDsize*len). + extern void recip2adic (uintC len, const uintD* a_LSDptr, uintD* dest_LSDptr); + +#endif /* _CL_2DS_H */ diff --git a/src/base/digitseq/cl_2DS_div.cc b/src/base/digitseq/cl_2DS_div.cc new file mode 100644 index 0000000..186e467 --- /dev/null +++ b/src/base/digitseq/cl_2DS_div.cc @@ -0,0 +1,113 @@ +// div2adic(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_2DS.h" + + +// Implementation. + +#include "cl_2D.h" +#include "cl_DS.h" +#include "cl_abort.h" + +// Timings on a i486 33 MHz running Linux: +// Divide N digits by N digits Divide 2*N digits by N digits +// N standard Newton N standard Newton +// 10 0.00015 0.00054 10 0.00023 0.00054 +// 25 0.00065 0.00256 25 0.00116 0.00256 +// 50 0.0024 0.0083 50 0.0044 0.0082 +// 100 0.0089 0.027 100 0.0172 0.027 +// 250 0.054 0.130 250 0.107 0.130 +// 500 0.22 0.42 500 0.425 0.42 +// 1000 0.86 1.30 1000 1.72 1.30 +// 2500 5.6 4.1 2500 11.0 4.1 +// 5000 22.3 9.4 5000 44.7 9.3 +// 10000 91.2 20.6 10000 182 20.5 +// -----> Newton faster for N >= 2070 -----> Newton faster for N >= 500 +// +// 1.0*N / N : Newton for N >= 2070 or 1790 >= N >= 1460 +// 1.1*N / N : Newton for N >= 1880 or 1790 >= N >= 1320 +// 1.2*N / N : Newton for N >= 1250 +// 1.3*N / N : Newton for N >= 1010 +// 1.4*N / N : Newton for N >= 940 +// 1.5*N / N : Newton for N >= 750 +// 1.6*N / N : Newton for N >= 625 +// 1.7*N / N : Newton for N >= 550 +// 1.8*N / N : Newton for N >= 500 +// 1.9*N / N : Newton for N >= 500 +// 2.0*N / N : Newton for N >= 500 +// +// Break-even-point. When in doubt, prefer to choose the standard algorithm. + static inline cl_boolean cl_recip_suitable (uintL m, uintL n) // n <= m + { if (n < 500) + return cl_false; + else // when n >= 2100/(m/n)^2, i.e. (m/46)^2 > n + { var uintL mq = floor(m,46); + if ((mq >= bit(16)) || ((uintL)(mq*mq) > n)) + return cl_true; + else + return cl_false; + } + } + +void div2adic (uintC a_len, const uintD* a_LSDptr, uintC b_len, const uintD* b_LSDptr, uintD* dest_LSDptr) +{ + var uintC lendiff = a_len - b_len; + if (cl_recip_suitable(a_len,b_len)) + { // Division using reciprocal (Newton-Hensel algorithm). + CL_ALLOCA_STACK; + // Bestimme Kehrwert c von b mod 2^(intDsize*b_len). + var uintD* c_LSDptr; + num_stack_alloc(b_len,,c_LSDptr=); + recip2adic(b_len,b_LSDptr,c_LSDptr); + // Bestimme q := a * c mod 2^(intDsize*b_len). + var uintD* q_LSDptr; + num_stack_alloc(2*b_len,,q_LSDptr=); + cl_UDS_mul(a_LSDptr,b_len,c_LSDptr,b_len,q_LSDptr); + // Zur Bestimmung des Restes wieder mit b multiplizieren: + var uintD* p_LSDptr; + num_stack_alloc(2*b_len,,p_LSDptr=); + cl_UDS_mul(q_LSDptr,b_len,b_LSDptr,b_len,p_LSDptr); + // Ãœberprüfen, daß p == a mod 2^(intDsize*b_len): + if (compare_loop_msp(a_LSDptr lspop b_len,p_LSDptr lspop b_len,b_len)) + cl_abort(); + // Quotient q und "Rest" (a-b*q)/2^(intDsize*b_len) ablegen: + copy_loop_lsp(q_LSDptr,dest_LSDptr,b_len); + if (lendiff <= b_len) + { sub_loop_lsp(a_LSDptr lspop b_len,p_LSDptr lspop b_len,dest_LSDptr lspop b_len,lendiff); } + else + { var uintD carry = sub_loop_lsp(a_LSDptr lspop b_len,p_LSDptr lspop b_len,dest_LSDptr lspop b_len,b_len); + copy_loop_lsp(a_LSDptr lspop 2*b_len,dest_LSDptr lspop 2*b_len,lendiff-b_len); + if (carry) { dec_loop_lsp(dest_LSDptr lspop 2*b_len,lendiff-b_len); } + } + } + else + { // Standard division. + var uintD b0inv = div2adic(1,lspref(b_LSDptr,0)); // b' + copy_loop_lsp(a_LSDptr,dest_LSDptr,a_len); // d := a + do { var uintD digit = lspref(dest_LSDptr,0); // nächstes d[j] + digit = mul2adic(b0inv,digit); + // digit = nächstes c[j] + if (a_len <= b_len) + { mulusub_loop_lsp(digit,b_LSDptr,dest_LSDptr,a_len); } // d := d - b * c[j] * beta^j + else + // a_len > b_len, b wird als durch Nullen fortgesetzt gedacht. + { var uintD carry = mulusub_loop_lsp(digit,b_LSDptr,dest_LSDptr,b_len); + if (lspref(dest_LSDptr,b_len) >= carry) + { lspref(dest_LSDptr,b_len) -= carry; } + else + { lspref(dest_LSDptr,b_len) -= carry; + dec_loop_lsp(dest_LSDptr lspop (b_len+1),a_len-(b_len+1)); + } } + // Nun ist lspref(dest_LSDptr,0) = 0. + lspref(dest_LSDptr,0) = digit; // c[j] ablegen + lsshrink(dest_LSDptr); a_len--; // nächstes j + } + until (a_len==lendiff); + } +} +// Bit complexity (N = max(a_len,b_len)): O(M(N)). + diff --git a/src/base/digitseq/cl_2DS_recip.cc b/src/base/digitseq/cl_2DS_recip.cc new file mode 100644 index 0000000..73a9ef3 --- /dev/null +++ b/src/base/digitseq/cl_2DS_recip.cc @@ -0,0 +1,61 @@ +// recip2adic(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_2DS.h" + + +// Implementation. + +#include "cl_2D.h" +#include "cl_DS.h" + +// Break-even point of the Newton iteration vs. standard div2adic. +const unsigned int recip2adic_threshold = 380; + +void recip2adic (uintC len, const uintD* a_LSDptr, uintD* dest_LSDptr) +{ + // Method: + // If len < threshold, use regular 2-adic division. + // Else [Newton iteration] set n := ceiling(len/2), + // compute recursively b := recip2adic(a mod 2^(intDsize*n)), + // return 2*b-a*b^2 mod 2^(intDsize*2*n). + CL_ALLOCA_STACK; + var uintL k = 0; // number of Newton steps + var uintL n = len; + while (n >= recip2adic_threshold) { + n = ceiling(n,2); + k++; + } + // Nonrecursive step. + var uintD* one_LSDptr; + num_stack_alloc(n,,one_LSDptr=); + lspref(one_LSDptr,0) = 1; + clear_loop_lsp(one_LSDptr lspop 1,n-1); + div2adic(n,one_LSDptr,a_LSDptr,dest_LSDptr); + // Newton iteration. + if (k > 0) { + var uintD* b2_LSDptr; + var uintD* prod_LSDptr; + num_stack_alloc(len+1,,b2_LSDptr=); + num_stack_alloc(2*(uintL)len,,prod_LSDptr=); + do { + // n = ceiling(len/2^k) + // Compute n2 = ceiling(len/2^(k-1)), + // then n = ceiling(n2/2). + k--; + var uintL n2 = ((len-1)>>k)+1; // = 2*n or = 2*n-1 + // Set b := 2*b-a*b^2 mod 2^(intDsize*n2) + cl_UDS_mul_square(dest_LSDptr,n,b2_LSDptr); // b^2 + cl_UDS_mul(b2_LSDptr,n2,a_LSDptr,n2,prod_LSDptr); // a*b^2 + clear_loop_lsp(dest_LSDptr lspop n,n2-n); + shift1left_loop_lsp(dest_LSDptr,n+1); // (n+1 instead of n2 is ok) + subfrom_loop_lsp(prod_LSDptr,dest_LSDptr,n2); + n = n2; + } while (k > 0); + } +} +// Bit complexity (N := len): O(M(N)). + diff --git a/src/base/digitseq/cl_DS.h b/src/base/digitseq/cl_DS.h new file mode 100644 index 0000000..7f5e9d1 --- /dev/null +++ b/src/base/digitseq/cl_DS.h @@ -0,0 +1,2653 @@ +// Digit sequence arithmetic + +#ifndef _CL_DS_H +#define _CL_DS_H + +#include "cl_types.h" +#include "cl_gmpconfig.h" +#include "cl_D.h" +#include "cl_DS_endian.h" +#include "cl_alloca.h" + +// Digit Sequence (DS) +// a memory range with n digits (n an uintC), +// between two pointers MSDptr and LSDptr. +#if CL_DS_BIG_ENDIAN_P +// MSDptr LSDptr = MSDptr+n +// | MSD ............. LSD | +// [short: MSDptr/n/LSDptr ] +// In C: uintD* MSDptr, uintC len, MSDptr[0] ... MSDptr[len-1] are the digits. +#else +// LSDptr MSDptr = LSDptr+n +// | LSD ............. MSD | +// In C: uintD* LSDptr, uintC len, LSDptr[0] ... LSDptr[len-1] are the digits. +#endif +// If n = 0, this represents the number 0. +// If n > 0, the most significant bit (i.e. bit (intDsize-1) of +// MSDptr[CL_DS_BIG_ENDIAN_P?0:-1]) is the sign bit. If the sign +// bit were repeated infinitely often, one would get an +// "infinite bit sequence". +// +// A Normalised Digit Sequence (NDS) is one for which the MSD is necessary, +// i.e. n = 0 or (n > 0 and the most significant intDsize+1 bits are not +// all the same). + +// Unsigned Digit Sequence (UDS) +// like DS, but without sign. +// +// Normalized Unsigned Digit Sequence (NUDS): +// an UDS for which the MSD is necessary, i.e. n = 0 or +// (n > 0 and the most significant intDsize bits are not all zero). + +// For the construction of constant DS, using "digit_header": +#define D1(byte0) (uintD)(byte0) +#define D2(byte0,byte1) (((uintD)(byte0)<<8)|(uintD)(byte1)) +#define D4(byte0,byte1,byte2,byte3) (((uintD)(byte0)<<24)|((uintD)(byte1)<<16)|((uintD)(byte2)<<8)|((uintD)(byte3))) +#define D8(byte0,byte1,byte2,byte3,byte4,byte5,byte6,byte7) (((uintD)(byte0)<<56)|((uintD)(byte1)<<48)|((uintD)(byte2)<<40)|((uintD)(byte3)<<32)|((uintD)(byte4)<<24)|((uintD)(byte5)<<16)|((uintD)(byte6)<<8)|((uintD)(byte7))) + +struct DS { + uintD* MSDptr; + unsigned int len; + uintD* LSDptr; +}; + +// Endianness independent access of digit sequences: +// mspref(MSDptr,i) access a most significant digit +// lspref(LSDptr,i) access a least significant digit +// msshrink(MSDptr) shrinks the DS by throwing away the MSD +// msprefnext(MSDptr) combines mspref(MSDptr,0) and msshrink(MSDptr) +// lsshrink(LSDptr) shrinks the DS by throwing away the LSD +// lsprefnext(LSDptr) combines lspref(LSDptr,0) and lsshrink(LSDptr) +// mspop pointer operator corresponding to msshrink, arg is widened to an uintP +// lspop pointer operator corresponding to lsshrink, arg is widened to an uintP +#if CL_DS_BIG_ENDIAN_P + #define mspref(p,i) (p)[i] + #define lspref(p,i) (p)[-(uintP)(i)-1] + #define msshrink(p) (p)++ + #define msprefnext(p) (*(p)++) + #define lsshrink(p) (p)-- + #define lsprefnext(p) (*--(p)) + #define mspop + + #define lspop - +#else + #define mspref(p,i) (p)[-(uintP)(i)-1] + #define lspref(p,i) (p)[i] + #define msshrink(p) (p)-- + #define msprefnext(p) (*--(p)) + #define lsshrink(p) (p)++ + #define lsprefnext(p) (*(p)++) + #define mspop - + #define lspop + +#endif + +// Endianness independent macros for turning an array into a digit sequence. +// arrayMSDptr(array,length) returns the MSDptr of array[0..length-1] +// arrayLSDptr(array,length) returns the LSDptr of array[0..length-1] +#if CL_DS_BIG_ENDIAN_P + #define arrayMSDptr(array,length) &(array)[0] + #define arrayLSDptr(array,length) &(array)[length] +#else + #define arrayMSDptr(array,length) &(array)[length] + #define arrayLSDptr(array,length) &(array)[0] +#endif +#define arrayLSref(array,length,i) lspref(arrayLSDptr(array,length),i) + + +// These functions on digit sequences are either inline C++ functions +// or external assembler functions (see files cl_asm_*). + + +// See which functions are defined as external functions. +#include "cl_asm.h" + + +// Declare the external functions. + +extern "C" { + +#ifdef COPY_LOOPS + +extern uintD* copy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count); + +extern uintD* copy_loop_down (const uintD* sourceptr, uintD* destptr, uintC count); + +#endif + +#ifdef FILL_LOOPS + +extern uintD* fill_loop_up (uintD* destptr, uintC count, uintD filler); + +extern uintD* fill_loop_down (uintD* destptr, uintC count, uintD filler); + +#endif + +#ifdef CLEAR_LOOPS + +extern uintD* clear_loop_up (uintD* destptr, uintC count); + +extern uintD* clear_loop_down (uintD* destptr, uintC count); + +#endif + +#ifdef TEST_LOOPS + +extern cl_boolean test_loop_up (const uintD* ptr, uintC count); + +extern cl_boolean test_loop_down (const uintD* ptr, uintC count); + +#endif + +#if CL_DS_BIG_ENDIAN_P + +#ifdef LOG_LOOPS + +extern void or_loop_up (uintD* xptr, const uintD* yptr, uintC count); + +extern void xor_loop_up (uintD* xptr, const uintD* yptr, uintC count); + +extern void and_loop_up (uintD* xptr, const uintD* yptr, uintC count); + +extern void eqv_loop_up (uintD* xptr, const uintD* yptr, uintC count); + +extern void nand_loop_up (uintD* xptr, const uintD* yptr, uintC count); + +extern void nor_loop_up (uintD* xptr, const uintD* yptr, uintC count); + +extern void andc2_loop_up (uintD* xptr, const uintD* yptr, uintC count); + +extern void orc2_loop_up (uintD* xptr, const uintD* yptr, uintC count); + +extern void not_loop_up (uintD* xptr, uintC count); + +#endif + +#ifdef TEST_LOOPS + +extern cl_boolean and_test_loop_up (const uintD* xptr, const uintD* yptr, uintC count); + +extern cl_signean compare_loop_up (const uintD* xptr, const uintD* yptr, uintC count); + +#endif + +#ifdef ADDSUB_LOOPS + +extern uintD add_loop_down (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count); + +extern uintD addto_loop_down (const uintD* sourceptr, uintD* destptr, uintC count); + +extern uintD inc_loop_down (uintD* ptr, uintC count); + +extern uintD sub_loop_down (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count); + +extern uintD subx_loop_down (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count, uintD carry); + +extern uintD subfrom_loop_down (const uintD* sourceptr, uintD* destptr, uintC count); + +extern uintD dec_loop_down (uintD* ptr, uintC count); + +extern uintD neg_loop_down (uintD* ptr, uintC count); + +#endif + +#ifdef SHIFT_LOOPS + +extern uintD shift1left_loop_down (uintD* ptr, uintC count); + +extern uintD shiftleft_loop_down (uintD* ptr, uintC count, uintC i, uintD carry); + +extern uintD shiftleftcopy_loop_down (const uintD* sourceptr, uintD* destptr, uintC count, uintC i); + +extern uintD shift1right_loop_up (uintD* ptr, uintC count, uintD carry); + +extern uintD shiftright_loop_up (uintD* ptr, uintC count, uintC i); + +extern uintD shiftrightsigned_loop_up (uintD* ptr, uintC count, uintC i); + +extern uintD shiftrightcopy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry); + +#endif + +#ifdef MUL_LOOPS + +extern uintD mulusmall_loop_down (uintD digit, uintD* ptr, uintC len, uintD newdigit); + +extern void mulu_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len); + +extern uintD muluadd_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len); + +extern uintD mulusub_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len); + +#endif + +#ifdef DIV_LOOPS + +extern uintD divu_loop_up (uintD digit, uintD* ptr, uintC len); + +extern uintD divucopy_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len); + +#endif + +#else // !CL_DS_BIG_ENDIAN_P + +#ifdef LOG_LOOPS + +extern void or_loop_down (uintD* xptr, const uintD* yptr, uintC count); + +extern void xor_loop_down (uintD* xptr, const uintD* yptr, uintC count); + +extern void and_loop_down (uintD* xptr, const uintD* yptr, uintC count); + +extern void eqv_loop_down (uintD* xptr, const uintD* yptr, uintC count); + +extern void nand_loop_down (uintD* xptr, const uintD* yptr, uintC count); + +extern void nor_loop_down (uintD* xptr, const uintD* yptr, uintC count); + +extern void andc2_loop_down (uintD* xptr, const uintD* yptr, uintC count); + +extern void orc2_loop_down (uintD* xptr, const uintD* yptr, uintC count); + +extern void not_loop_down (uintD* xptr, uintC count); + +#endif + +#ifdef TEST_LOOPS + +extern cl_boolean and_test_loop_down (const uintD* xptr, const uintD* yptr, uintC count); + +extern cl_signean compare_loop_down (const uintD* xptr, const uintD* yptr, uintC count); + +#endif + +#ifdef ADDSUB_LOOPS + +extern uintD add_loop_up (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count); + +extern uintD addto_loop_up (const uintD* sourceptr, uintD* destptr, uintC count); + +extern uintD inc_loop_up (uintD* ptr, uintC count); + +extern uintD sub_loop_up (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count); + +extern uintD subx_loop_up (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count, uintD carry); + +extern uintD subfrom_loop_up (const uintD* sourceptr, uintD* destptr, uintC count); + +extern uintD dec_loop_up (uintD* ptr, uintC count); + +extern uintD neg_loop_up (uintD* ptr, uintC count); + +#endif + +#ifdef SHIFT_LOOPS + +extern uintD shift1left_loop_up (uintD* ptr, uintC count); + +extern uintD shiftleft_loop_up (uintD* ptr, uintC count, uintC i, uintD carry); + +extern uintD shiftleftcopy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count, uintC i); + +extern uintD shift1right_loop_down (uintD* ptr, uintC count, uintD carry); + +extern uintD shiftright_loop_down (uintD* ptr, uintC count, uintC i); + +extern uintD shiftrightsigned_loop_down (uintD* ptr, uintC count, uintC i); + +extern uintD shiftrightcopy_loop_down (const uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry); + +#endif + +#ifdef MUL_LOOPS + +extern uintD mulusmall_loop_up (uintD digit, uintD* ptr, uintC len, uintD newdigit); + +extern void mulu_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len); + +extern uintD muluadd_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len); + +extern uintD mulusub_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len); + +#endif + +#ifdef DIV_LOOPS + +extern uintD divu_loop_down (uintD digit, uintD* ptr, uintC len); + +extern uintD divucopy_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len); + +#endif + +#endif // !CL_DS_BIG_ENDIAN_P + +// Independently of CL_DS_BIG_ENDIAN_P: + +#ifdef TEST_LOOPS + +extern cl_signean compare_loop_up (const uintD* xptr, const uintD* yptr, uintC count); + +#endif + +#ifdef LOG_LOOPS + +extern void xor_loop_up (uintD* xptr, const uintD* yptr, uintC count); + +#endif + +#ifdef SHIFT_LOOPS + +extern uintD shiftleftcopy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count, uintC i); + +extern void shiftxor_loop_up (uintD* xptr, const uintD* yptr, uintC count, uintC i); + +#endif + +} // "C" extern. + + +#if defined(CL_USE_GMP) + +// Supersede the functions by wrappers around calls to gmp mpn, +// for those functions where gmp is believed to be faster. + +#include + +#if 0 // not worth it, since gmp's mpn_cmp is not optimized +inline cl_signean compare_loop_down (const uintD* xptr, const uintD* yptr, uintC count) +{ + return mpn_cmp(xptr-count,yptr-count,count); +} +#endif + +inline uintD add_loop_up (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count) +{ + if (count == 0) + return 0; + return mpn_add_n(destptr,sourceptr1,sourceptr2,count); +} + +inline uintD addto_loop_up (const uintD* sourceptr, uintD* destptr, uintC count) +{ + if (count == 0) + return 0; + return mpn_add_n(destptr,destptr,sourceptr,count); +} + +inline uintD inc_loop_up (uintD* ptr, uintC count) +{ + if (count == 0) + return 1; + return mpn_add_1(ptr,ptr,count,1); +} + +inline uintD sub_loop_up (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count) +{ + if (count == 0) + return 0; + return mpn_sub_n(destptr,sourceptr1,sourceptr2,count); +} + +inline uintD subx_loop_up (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count, uintD carry) +{ + if (count == 0) + return carry; + var uintD res_carry = mpn_sub_n(destptr,sourceptr1,sourceptr2,count); + if (carry) + res_carry |= mpn_sub_1(destptr,destptr,count,1); + return res_carry; +} + +inline uintD subfrom_loop_up (const uintD* sourceptr, uintD* destptr, uintC count) +{ + if (count == 0) + return 0; + return mpn_sub_n(destptr,destptr,sourceptr,count); +} + +inline uintD dec_loop_up (uintD* ptr, uintC count) +{ + if (count == 0) + return (uintD)(-1); + return -mpn_sub_1(ptr,ptr,count,1); +} + +#if !defined(ADDSUB_LOOPS) +// No equivalent for this in gmp. But we need this function, so write it in C. +inline uintD neg_loop_up (uintD* ptr, uintC count) +{ + // erstes Digit /=0 suchen: + until (count==0) { if (!(*ptr == 0)) goto L1; ptr++; count--; } + return 0; + L1: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys + *ptr = - *ptr; count--; // 1 Digit negieren + dotimesC(count,count, { ptr++; *ptr = ~ *ptr; } ); // alle anderen Digits invertieren + return (uintD)(-1); +} +#endif + +#define ADDSUB_LOOPS + +inline uintD shift1left_loop_up (uintD* ptr, uintC count) +{ + if (count == 0) + return 0; + return mpn_lshift(ptr,ptr,count,1); +} + +inline uintD shiftleft_loop_up (uintD* ptr, uintC count, uintC i, uintD carry) +{ + if (count == 0) + return carry; + var uintD res_carry = mpn_lshift(ptr,ptr,count,i); + ptr[0] |= carry; + return res_carry; +} + +inline uintD shiftleftcopy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count, uintC i) +{ + if (count == 0) + return 0; + return mpn_lshift(destptr,sourceptr,count,i); +} + +inline uintD shift1right_loop_down (uintD* ptr, uintC count, uintD carry) +{ + if (count == 0) + return carry; + var uintD res_carry = mpn_rshift(ptr-count,ptr-count,count,1); + if (carry) + ptr[-1] |= bit(intDsize-1); + return res_carry; +} + +inline uintD shiftright_loop_down (uintD* ptr, uintC count, uintC i) +{ + if (count == 0) + return 0; + return mpn_rshift(ptr-count,ptr-count,count,i); +} + +inline uintD shiftrightsigned_loop_down (uintD* ptr, uintC count, uintC i) +{ + var uintD carry = ((sintD)ptr[-1] >> (intDsize-1)) << (intDsize-i); + var uintD res_carry = mpn_rshift(ptr-count,ptr-count,count,i); + ptr[-1] |= carry; + return res_carry; +} + +inline uintD shiftrightcopy_loop_down (const uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry) +{ + carry = carry << (intDsize-i); + if (count == 0) + return carry; + var uintD res_carry = mpn_rshift(destptr-count,sourceptr-count,count,i); + destptr[-1] |= carry; + return res_carry; +} + +#define SHIFT_LOOPS + +inline uintD mulusmall_loop_up (uintD digit, uintD* ptr, uintC len, uintD newdigit) +{ + if (len == 0) + return newdigit; + var uintD res_carry = mpn_mul_1(ptr,ptr,len,digit); + res_carry += mpn_add_1(ptr,ptr,len,newdigit); + return res_carry; +} + +inline void mulu_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len) +{ + destptr[len] = (len==0 ? 0 : mpn_mul_1(destptr,sourceptr,len,digit)); +} + +inline uintD muluadd_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len) +{ + if (len == 0) + return 0; + return mpn_addmul_1(destptr,sourceptr,len,digit); +} + +inline uintD mulusub_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len) +{ + if (len == 0) + return 0; + return mpn_submul_1(destptr,sourceptr,len,digit); +} + +#define MUL_LOOPS + +#endif // defined(CL_USE_GMP) + + +// Define the missing functions as inline functions. + +#ifndef COPY_LOOPS + +// Kopierschleife: +// destptr = copy_loop_up(sourceptr,destptr,count); +// kopiert count (uintC>=0) Digits aufwärts von sourceptr nach destptr +// und liefert das neue destptr. + inline uintD* copy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count) + { dotimesC(count,count, { *destptr++ = *sourceptr++; } ); + return destptr; + } + +// Kopierschleife: +// destptr = copy_loop_down(sourceptr,destptr,count); +// kopiert count (uintC>=0) Digits abwärts von sourceptr nach destptr +// und liefert das neue destptr. + inline uintD* copy_loop_down (const uintD* sourceptr, uintD* destptr, uintC count) + { dotimesC(count,count, { *--destptr = *--sourceptr; } ); + return destptr; + } + +#endif + +#ifndef FILL_LOOPS + +// Füllschleife: +// destptr = fill_loop_up(destptr,count,filler); +// kopiert count (uintC>=0) mal das Digit filler aufwärts nach destptr +// und liefert das neue destptr. + inline uintD* fill_loop_up (uintD* destptr, uintC count, uintD filler) + { dotimesC(count,count, { *destptr++ = filler; } ); + return destptr; + } + +// Füllschleife: +// destptr = fill_loop_down(destptr,count,filler); +// kopiert count (uintC>=0) mal das Digit filler abwärts nach destptr +// und liefert das neue destptr. + inline uintD* fill_loop_down (uintD* destptr, uintC count, uintD filler) + { dotimesC(count,count, { *--destptr = filler; } ); + return destptr; + } + +#endif + +#ifndef CLEAR_LOOPS + +// Lösch-Schleife: +// destptr = clear_loop_up(destptr,count); +// löscht count (uintC>=0) Digits aufwärts ab destptr +// und liefert das neue destptr. + inline uintD* clear_loop_up (uintD* destptr, uintC count) + { dotimesC(count,count, { *destptr++ = 0; } ); + return destptr; + } + +// Lösch-Schleife: +// destptr = clear_loop_down(destptr,count); +// löscht count (uintC>=0) Digits abwärts ab destptr +// und liefert das neue destptr. + inline uintD* clear_loop_down (uintD* destptr, uintC count) + { dotimesC(count,count, { *--destptr = 0; } ); + return destptr; + } + +#endif + +#ifndef TEST_LOOPS + +// Test-Schleife: +// test_loop_up(ptr,count) +// testet count (uintC>=0) Digits aufwärts ab ptr, ob darunter eines /=0 ist. +// Ergebnis /=0, falls ja. + inline cl_boolean test_loop_up (const uintD* ptr, uintC count) + { dotimesC(count,count, { if (*ptr++) return cl_true; } ); + return cl_false; + } + +// Test-Schleife: +// test_loop_down(ptr,count) +// testet count (uintC>=0) Digits abwärts ab ptr, ob darunter eines /=0 ist. +// Ergebnis /=0, falls ja. + inline cl_boolean test_loop_down (const uintD* ptr, uintC count) + { dotimesC(count,count, { if (*--ptr) return cl_true; } ); + return cl_false; + } + +#endif + +#if CL_DS_BIG_ENDIAN_P + +#ifndef LOG_LOOPS + +// OR-Schleife: +// or_loop_up(xptr,yptr,count); +// verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr +// mit Ziel ab xptr durch OR. + inline void or_loop_up (uintD* xptr, const uintD* yptr, uintC count) + { dotimesC(count,count, { *xptr++ |= *yptr++; } ); } + +// XOR-Schleife: +// xor_loop_up(xptr,yptr,count); +// verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr +// mit Ziel ab xptr durch XOR. + inline void xor_loop_up (uintD* xptr, const uintD* yptr, uintC count) + { dotimesC(count,count, { *xptr++ ^= *yptr++; } ); } + +// AND-Schleife: +// and_loop_up(xptr,yptr,count); +// verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr +// mit Ziel ab xptr durch AND. + inline void and_loop_up (uintD* xptr, const uintD* yptr, uintC count) + { dotimesC(count,count, { *xptr++ &= *yptr++; } ); } + +// EQV-Schleife: +// eqv_loop_up(xptr,yptr,count); +// verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr +// mit Ziel ab xptr durch EQV (NOT XOR). + inline void eqv_loop_up (uintD* xptr, const uintD* yptr, uintC count) + { dotimesC(count,count, + {var uintD temp = ~ (*xptr ^ *yptr++); *xptr++ = temp; } + ); + } + +// NAND-Schleife: +// nand_loop_up(xptr,yptr,count); +// verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr +// mit Ziel ab xptr durch NAND (NOT AND). + inline void nand_loop_up (uintD* xptr, const uintD* yptr, uintC count) + { dotimesC(count,count, + {var uintD temp = ~ (*xptr & *yptr++); *xptr++ = temp; } + ); + } + +// NOR-Schleife: +// nor_loop_up(xptr,yptr,count); +// verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr +// mit Ziel ab xptr durch NOR (NOT OR). + inline void nor_loop_up (uintD* xptr, const uintD* yptr, uintC count) + { dotimesC(count,count, + {var uintD temp = ~ (*xptr | *yptr++); *xptr++ = temp; } + ); + } + +// ANDC2-Schleife: +// andc2_loop_up(xptr,yptr,count); +// verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr +// mit Ziel ab xptr durch ANDC2 (AND NOT). + inline void andc2_loop_up (uintD* xptr, const uintD* yptr, uintC count) + { dotimesC(count,count, { *xptr++ &= ~(*yptr++); } ); } + +// ORC2-Schleife: +// orc2_loop_up(xptr,yptr,count); +// verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr +// mit Ziel ab xptr durch ORC2 (OR NOT). + inline void orc2_loop_up (uintD* xptr, const uintD* yptr, uintC count) + { dotimesC(count,count, { *xptr++ |= ~(*yptr++); } ); } + +// NOT-Schleife: +// not_loop_up(xptr,count); +// verknüpft count (uintC>0) Digits aufwärts ab xptr mit Ziel ab xptr +// durch NOT. + inline void not_loop_up (uintD* xptr, uintC count) + { dotimespC(count,count, + {var uintD temp = ~ (*xptr); *xptr++ = temp; } + ); + } + +#endif + +#ifndef TEST_LOOPS + +// AND-Test-Schleife: +// and_test_loop_up(xptr,yptr,count); +// verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr durch AND +// und testet, ob sich dabei ein Digit /=0 ergibt. Ergebnis cl_true, falls ja. + inline cl_boolean and_test_loop_up (const uintD* xptr, const uintD* yptr, uintC count) + { dotimesC(count,count, { if (*xptr++ & *yptr++) return cl_true; } ); + return cl_false; + } + +// Vergleichsschleife: +// result = compare_loop_up(xptr,yptr,count); +// vergleicht nacheinander xptr[0] mit yptr[0], xptr[1] mit yptr[1], usw., +// insgesamt count Digits, und liefert 0 falls alle gleich sind, +// +1 falls zuerst ein xptr[i]>yptr[i] ist, +// -1 falls zuerst ein xptr[i] *--yptr ? signean_plus : signean_minus); + }); + return signean_null; // alle Digits gleich + } + +#endif + +#ifndef ADDSUB_LOOPS + +// Additionsschleife: +// übertrag = add_loop_down(sourceptr1,sourceptr2,destptr,count); +// addiert count (uintC>=0) Digits abwärts von sourceptr1, von sourceptr2 +// abwärts nach destptr und liefert den Ãœbertrag (0 oder /=0, was 1 bedeutet). + inline uintD add_loop_down (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count) + { var uintD source1; + var uintD source2; + if (!(count==0)) + do { source1 = *--sourceptr1; + source2 = *--sourceptr2; + *--destptr = source1 + source2; + if (source1 > (uintD)(~source2)) goto carry_1; + carry_0: + count--; + } + until (count==0); + return 0; + do { source1 = *--sourceptr1; + source2 = *--sourceptr2; + *--destptr = source1 + source2 + 1; + if (source1 < (uintD)(~source2)) goto carry_0; + carry_1: + count--; + } + until (count==0); + return 1; + } + +// Additionsschleife: +// übertrag = addto_loop_down(sourceptr,destptr,count); +// addiert count (uintC>=0) Digits abwärts von sourceptr, von destptr +// abwärts nach destptr und liefert den Ãœbertrag (0 oder /=0, was 1 bedeutet). + inline uintD addto_loop_down (const uintD* sourceptr, uintD* destptr, uintC count) + { var uintD source1; + var uintD source2; + if (!(count==0)) + do { source1 = *--sourceptr; + source2 = *--destptr; + *destptr = source1 + source2; + if (source1 > (uintD)(~source2)) goto carry_1; + carry_0: + count--; + } + until (count==0); + return 0; + do { source1 = *--sourceptr; + source2 = *--destptr; + *destptr = source1 + source2 + 1; + if (source1 < (uintD)(~source2)) goto carry_0; + carry_1: + count--; + } + until (count==0); + return 1; + } + +// Incrementierschleife: +// übertrag = inc_loop_down(ptr,count); +// incrementiert count (uintC>=0) Digits abwärts von ptr, so lange bis kein +// Ãœbertrag mehr auftritt und liefert den Ãœbertrag (0 oder /=0, was 1 bedeutet). + inline uintD inc_loop_down (uintD* ptr, uintC count) + { dotimesC(count,count, + { if (!( ++(*--ptr) == 0 )) return 0; } // kein weiterer Ãœbertrag + ); + return 1; // weiterer Ãœbertrag + } + +// Subtraktionsschleife: +// übertrag = sub_loop_down(sourceptr1,sourceptr2,destptr,count); +// subtrahiert count (uintC>=0) Digits abwärts von sourceptr1, von sourceptr2 +// abwärts nach destptr und liefert den Ãœbertrag (0 oder /=0, was -1 bedeutet). + inline uintD sub_loop_down (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count) + { var uintD source1; + var uintD source2; + if (!(count==0)) + do { source1 = *--sourceptr1; + source2 = *--sourceptr2; + *--destptr = source1 - source2; + if (source1 < source2) goto carry_1; + carry_0: + count--; + } + until (count==0); + return 0; + do { source1 = *--sourceptr1; + source2 = *--sourceptr2; + *--destptr = source1 - source2 - 1; + if (source1 > source2) goto carry_0; + carry_1: + count--; + } + until (count==0); + return (uintD)(-1); + } + +// Subtraktionsschleife: +// übertrag = subx_loop_down(sourceptr1,sourceptr2,destptr,count,carry); +// subtrahiert count (uintC>=0) Digits abwärts von sourceptr1 und addiert +// einen Carry (0 oder -1), von sourceptr2 abwärts nach destptr und +// liefert den Ãœbertrag (0 oder /=0, was -1 bedeutet). + inline uintD subx_loop_down (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count, uintD carry) + { var uintD source1; + var uintD source2; + if (carry==0) + { if (!(count==0)) + do { source1 = *--sourceptr1; + source2 = *--sourceptr2; + *--destptr = source1 - source2; + if (source1 < source2) goto carry_1; + carry_0: + count--; + } + until (count==0); + return 0; + } + else + { if (!(count==0)) + do { source1 = *--sourceptr1; + source2 = *--sourceptr2; + *--destptr = source1 - source2 - 1; + if (source1 > source2) goto carry_0; + carry_1: + count--; + } + until (count==0); + return (uintD)(-1); + } } + +// Subtraktionsschleife: +// übertrag = subfrom_loop_down(sourceptr,destptr,count); +// subtrahiert count (uintC>=0) Digits abwärts von sourceptr, von destptr +// abwärts nach destptr (dest := dest - source) +// und liefert den Ãœbertrag (0 oder /=0, was -1 bedeutet). + inline uintD subfrom_loop_down (const uintD* sourceptr, uintD* destptr, uintC count) + { var uintD source1; + var uintD source2; + if (!(count==0)) + do { source1 = *--destptr; + source2 = *--sourceptr; + *destptr = source1 - source2; + if (source1 < source2) goto carry_1; + carry_0: + count--; + } + until (count==0); + return 0; + do { source1 = *--destptr; + source2 = *--sourceptr; + *destptr = source1 - source2 - 1; + if (source1 > source2) goto carry_0; + carry_1: + count--; + } + until (count==0); + return (uintD)(-1); + } + +// Decrementierschleife: +// übertrag = dec_loop_down(ptr,count); +// decrementiert count (uintC>=0) Digits abwärts von ptr, so lange bis kein +// Ãœbertrag mehr auftritt und liefert den Ãœbertrag (0 oder -1). + inline uintD dec_loop_down (uintD* ptr, uintC count) + { dotimesC(count,count, + { if (!( (*--ptr)-- == 0 )) return 0; } // kein weiterer Ãœbertrag + ); + return (uintD)(-1); // weiterer Ãœbertrag + } + +// Negierschleife: +// übertrag = neg_loop_down(ptr,count); +// negiert count (uintC>=0) Digits abwärts von ptr, +// und liefert den Ãœbertrag (0 oder -1). + inline uintD neg_loop_down (uintD* ptr, uintC count) + { // erstes Digit /=0 suchen: + until (count==0) { if (!(*--ptr == 0)) goto L1; count--; } + return 0; + L1: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys + *ptr = - *ptr; count--; // 1 Digit negieren + dotimesC(count,count, { --ptr; *ptr = ~ *ptr; } ); // alle anderen Digits invertieren + return (uintD)(-1); + } + +#endif + +#ifndef SHIFT_LOOPS + +// Schiebeschleife um 1 Bit nach links: +// übertrag = shift1left_loop_down(ptr,count); +// schiebt count (uintC>=0) Digits abwärts von ptr um 1 Bit nach links, +// und liefert den Ãœbertrag (0 oder /=0, was 1 bedeutet). + #if HAVE_DD + inline uintD shift1left_loop_down (uintD* ptr, uintC count) + { var uintDD accu = 0; + dotimesC(count,count, + { accu = ((uintDD)(*--ptr)<<1)+accu; *ptr = lowD(accu); + accu = (uintDD)(highD(accu)); + }); + return (uintD)accu; + } + #else + inline uintD shift1left_loop_down (uintD* ptr, uintC count) + { var uintD carry = 0; + dotimesC(count,count, + { var uintD accu = *--ptr; + *ptr = (accu<<1) | carry; + carry = accu>>(intDsize-1); + }); + return carry; + } + #endif + +// Schiebeschleife um i Bits nach links: +// übertrag = shiftleft_loop_down(ptr,count,i,übertrag_init); +// schiebt count (uintC>=0) Digits abwärts von ptr um i Bits (0=0, <2^i). + #if HAVE_DD + inline uintD shiftleft_loop_down (uintD* ptr, uintC count, uintC i, uintD carry) + { var uintDD accu = (uintDD)carry; + dotimesC(count,count, + { accu = ((uintDD)(*--ptr)<>j; + }); + return carry; + } + #endif + +// Schiebe- und Kopierschleife um i Bits nach links: +// übertrag = shiftleftcopy_loop_down(sourceptr,destptr,count,i); +// kopiert count (uintC>=0) Digits abwärts von sourceptr nach destptr +// und schiebt sie dabei um i Bits (0=0, <2^i). + #if HAVE_DD + inline uintD shiftleftcopy_loop_down (const uintD* sourceptr, uintD* destptr, uintC count, uintC i) + { var uintDD accu = 0; + dotimesC(count,count, + { accu = ((uintDD)(*--sourceptr)<>j; + }); + return carry; + } + #endif + +// Schiebeschleife um 1 Bit nach rechts: +// übertrag = shift1right_loop_up(ptr,count,übertrag_init); +// schiebt count (uintC>=0) Digits aufwärts von ptr um 1 Bit nach rechts, +// wobei links das Bit übertrag_init (sollte =0 oder =-1 sein) hineingeschoben +// wird, und liefert den Ãœbertrag (0 oder /=0, was 1 bedeutet). + #if HAVE_DD + inline uintD shift1right_loop_up (uintD* ptr, uintC count, uintD carry) + { var uintDD accu = (sintDD)(sintD)carry & ((uintDD)1 << (2*intDsize-1)); // 0 oder bit(2*intDsize-1) + dotimesC(count,count, + { accu = (highlowDD_0(*ptr)>>1)+accu; *ptr++ = highD(accu); + accu = highlowDD_0(lowD(accu)); + }); + return highD(accu); + } + #else + inline uintD shift1right_loop_up (uintD* ptr, uintC count, uintD carry) + { carry = carry << (intDsize-1); // carry zu einem einzigen Bit machen + dotimesC(count,count, + { var uintD accu = *ptr; + *ptr++ = (accu >> 1) | carry; + carry = accu << (intDsize-1); + }); + return carry; + } + #endif + +// Schiebeschleife um i Bits nach rechts: +// übertrag = shiftright_loop_up(ptr,count,i); +// schiebt count (uintC>=0) Digits aufwärts von ptr um i Bits (0>i)+accu; *ptr++ = highD(accu); + }); + return lowD(accu); + } + #else + inline uintD shiftright_loop_up (uintD* ptr, uintC count, uintC i) + { var uintC j = intDsize-i; + var uintD carry = 0; + dotimesC(count,count, + { var uintD accu = *ptr; + *ptr++ = (accu >> i) | carry; + carry = accu << j; + }); + return carry; + } + #endif + +// Schiebeschleife um i Bits nach rechts: +// übertrag = shiftrightsigned_loop_up(ptr,count,i); +// schiebt count (uintC>0) Digits aufwärts von ptr um i Bits (0>i; + dotimespC(count,count, + { // Die oberen i Bits von (uintD)accu bilden hier den Ãœbertrag. + accu = highlowDD_0(lowD(accu)); + // Die oberen i Bits von (uintDD)accu bilden hier den Ãœbertrag. + accu = (highlowDD_0(*ptr)>>i)+accu; *ptr++ = highD(accu); + }); + return lowD(accu); + } + #else + inline uintD shiftrightsigned_loop_up (uintD* ptr, uintC count, uintC i) + { var uintC j = intDsize-i; + var uintD carry; + { var uintD accu = *ptr; + *ptr++ = (sintD)accu >> i; + carry = accu << j; + count--; + } + dotimesC(count,count, + { var uintD accu = *ptr; + *ptr++ = (accu >> i) | carry; + carry = accu << j; + }); + return carry; + } + #endif + +// Schiebe- und Kopier-Schleife um i Bits nach rechts: +// übertrag = shiftrightcopy_loop_up(sourceptr,destptr,count,i,carry); +// kopiert count (uintC>=0) Digits aufwärts von sourceptr nach destptr +// und schiebt sie dabei um i Bits (0>i; + dotimesC(count,count, + { // Die oberen i Bits von (uintD)accu bilden hier den Ãœbertrag. + accu = highlowDD_0(lowD(accu)); + // Die oberen i Bits von (uintDD)accu bilden hier den Ãœbertrag. + accu = (highlowDD_0(*sourceptr++)>>i)+accu; *destptr++ = highD(accu); + }); + return lowD(accu); + } + #else + inline uintD shiftrightcopy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry) + { var uintC j = intDsize-i; + carry = carry << j; + dotimesC(count,count, + { var uintD accu = *sourceptr++; + *destptr++ = (accu >> i) | carry; + carry = accu << j; + }); + return carry; + } + #endif + +#endif + +#ifndef MUL_LOOPS + +// Multiplikations-Einfachschleife: +// Multipliziert eine UDS mit einem kleinen Digit und addiert ein kleines Digit. +// mulusmall_loop_down(digit,ptr,len,newdigit) +// multipliziert die UDS ptr[-len..-1] mit digit (>=2, <=36), +// addiert dabei newdigit (>=0, =0, 0) +// mit dem einzelnen digit +// und legt das Ergebnis in der UDS destptr[-len-1..-1] ab. + #if HAVE_DD + inline void mulu_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len) + { var uintDD carry = 0; + dotimespC(len,len, + { // Hier ist carry=digit=0 oder 0 <= carry < digit. + carry = carry + muluD(digit,*--sourceptr); + // Hier ist carry=digit=0 oder 0 <= carry < 2^intDsize*digit. + *--destptr = lowD(carry); + carry = (uintDD)highD(carry); // carry := floor(carry/2^intDsize) < digit + }); + *--destptr = lowD(carry); + } + #else + inline void mulu_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len) + { var uintD carry = 0; + dotimespC(len,len, + { // Hier ist carry=digit=0 oder 0 <= carry < digit. + var uintD hi; + var uintD lo; + muluD(digit,*--sourceptr,hi=,lo=); + // Hier ist 0 <= 2^intDsize*hi + lo + carry < 2^intDsize*digit oder hi=lo=carry=digit=0. + lo += carry; if (lo < carry) { hi += 1; } + *--destptr = lo; + carry = hi; + }); + *--destptr = carry; + } + #endif + +// Multiplikations-Einfachschleife mit Akkumulation: +// Multipliziert eine UDS mit einem Digit und addiert das Ergebnis zu einer +// zweiten UDS auf. +// muluadd_loop_down(digit,sourceptr,destptr,len); +// multipliziert die UDS sourceptr[-len..-1] (len>0) +// mit dem einzelnen digit, legt das Ergebnis in der UDS destptr[-len..-1] +// ab und liefert den weiteren Ãœbertrag. + #if HAVE_DD + inline uintD muluadd_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len) + { var uintDD carry = 0; + if (!(digit==0)) + { dotimespC(len,len, + { // Hier ist 0 <= carry <= digit. + carry = carry + muluD(digit,*--sourceptr) + (uintDD)*--destptr; + // Hier ist 0 <= carry <= 2^intDsize*digit + 2^intDsize-1. + *destptr = lowD(carry); + carry = (uintDD)highD(carry); // carry := floor(carry/2^intDsize) <= digit + }); + } + return lowD(carry); + } + #else + inline uintD muluadd_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len) + { var uintD carry = 0; + if (!(digit==0)) + { dotimespC(len,len, + { // Hier ist 0 <= carry <= digit. + var uintD hi; + var uintD lo; + muluD(digit,*--sourceptr,hi=,lo=); + // Hier ist 0 <= 2^intDsize*hi + lo + carry + *--destptr <= 2^intDsize*digit+2^intDsize-1. + lo += carry; if (lo < carry) { hi += 1; } + carry = *--destptr; + lo += carry; if (lo < carry) { hi += 1; } + *destptr = lo; + carry = hi; + }); + } + return carry; + } + #endif + +// Multiplikations-Einfachschleife mit Diminution: +// Multipliziert eine UDS mit einem Digit und subtrahiert das Ergebnis von +// einer zweiten UDS. +// mulusub_loop_down(digit,sourceptr,destptr,len); +// multipliziert die UDS sourceptr[-len..-1] (len>0) mit dem einzelnen +// digit, subtrahiert das Ergebnis von der UDS destptr[-len..-1] und liefert +// den weiteren Ãœbertrag (>=0, evtl. von destptr[-len-1] zu subtrahieren). + #if HAVE_DD + inline uintD mulusub_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len) + { var uintDD carry = 0; + if (!(digit==0)) + { dotimespC(len,len, + { // Hier ist 0 <= carry <= digit. + carry = carry + muluD(digit,*--sourceptr) + (uintD)(~(*--destptr)); + // Hier ist 0 <= carry <= 2^intDsize*digit + 2^intDsize-1. + *destptr = ~lowD(carry); + carry = (uintDD)highD(carry); // carry := floor(carry/2^intDsize) <= digit + // Hier ist 0 <= carry <= digit. + }); + return lowD(carry); + } + else + return 0; // nichts zu subtrahieren -> kein Ãœbertrag + } + #else + inline uintD mulusub_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len) + { var uintD carry = 0; + if (!(digit==0)) + { dotimespC(len,len, + { // Hier ist 0 <= carry <= digit. + var uintD hi; + var uintD lo; + muluD(digit,*--sourceptr,hi=,lo=); + // Hier ist 0 <= 2^intDsize*hi + lo + carry + ~(*--destptr) <= 2^intDsize*digit+2^intDsize-1. + lo += carry; if (lo < carry) { hi += 1; } + carry = *--destptr; + *destptr = carry - lo; if (carry < lo) { hi += 1; } + carry = hi; + }); + return carry; + } + else + return 0; // nichts zu subtrahieren -> kein Ãœbertrag + } + #endif + +#endif + +#ifndef DIV_LOOPS + +// Divisions-Einfachschleife: +// Dividiert eine UDS durch ein Digit. +// divu_loop_up(digit,ptr,len) +// dividiert die UDS ptr[0..len-1] durch digit, +// legt das Ergebnis in derselben UDS ab, und liefert den Rest (>=0, =0, =0) Digits abwärts ab xptr und ab yptr +// mit Ziel ab xptr durch OR. + inline void or_loop_down (uintD* xptr, const uintD* yptr, uintC count) + { dotimesC(count,count, { *--xptr |= *--yptr; } ); } + +// XOR-Schleife: +// xor_loop_down(xptr,yptr,count); +// verknüpft count (uintC>=0) Digits abwärts ab xptr und ab yptr +// mit Ziel ab xptr durch XOR. + inline void xor_loop_down (uintD* xptr, const uintD* yptr, uintC count) + { dotimesC(count,count, { *--xptr ^= *--yptr; } ); } + +// AND-Schleife: +// and_loop_down(xptr,yptr,count); +// verknüpft count (uintC>=0) Digits abwärts ab xptr und ab yptr +// mit Ziel ab xptr durch AND. + inline void and_loop_down (uintD* xptr, const uintD* yptr, uintC count) + { dotimesC(count,count, { *--xptr &= *--yptr; } ); } + +// EQV-Schleife: +// eqv_loop_down(xptr,yptr,count); +// verknüpft count (uintC>=0) Digits abwärts ab xptr und ab yptr +// mit Ziel ab xptr durch EQV (NOT XOR). + inline void eqv_loop_down (uintD* xptr, const uintD* yptr, uintC count) + { dotimesC(count,count, + {var uintD temp = ~ (*--xptr ^ *--yptr); *xptr = temp; } + ); + } + +// NAND-Schleife: +// nand_loop_down(xptr,yptr,count); +// verknüpft count (uintC>=0) Digits abwärts ab xptr und ab yptr +// mit Ziel ab xptr durch NAND (NOT AND). + inline void nand_loop_down (uintD* xptr, const uintD* yptr, uintC count) + { dotimesC(count,count, + {var uintD temp = ~ (*--xptr & *--yptr); *xptr = temp; } + ); + } + +// NOR-Schleife: +// nor_loop_down(xptr,yptr,count); +// verknüpft count (uintC>=0) Digits abwärts ab xptr und ab yptr +// mit Ziel ab xptr durch NOR (NOT OR). + inline void nor_loop_down (uintD* xptr, const uintD* yptr, uintC count) + { dotimesC(count,count, + {var uintD temp = ~ (*--xptr | *--yptr); *xptr = temp; } + ); + } + +// ANDC2-Schleife: +// andc2_loop_down(xptr,yptr,count); +// verknüpft count (uintC>=0) Digits abwärts ab xptr und ab yptr +// mit Ziel ab xptr durch ANDC2 (AND NOT). + inline void andc2_loop_down (uintD* xptr, const uintD* yptr, uintC count) + { dotimesC(count,count, { *--xptr &= ~(*--yptr); } ); } + +// ORC2-Schleife: +// orc2_loop_down(xptr,yptr,count); +// verknüpft count (uintC>=0) Digits abwärts ab xptr und ab yptr +// mit Ziel ab xptr durch ORC2 (OR NOT). + inline void orc2_loop_down (uintD* xptr, const uintD* yptr, uintC count) + { dotimesC(count,count, { *--xptr |= ~(*--yptr); } ); } + +// NOT-Schleife: +// not_loop_down(xptr,count); +// verknüpft count (uintC>0) Digits abwärts ab xptr mit Ziel ab xptr +// durch NOT. + inline void not_loop_down (uintD* xptr, uintC count) + { dotimespC(count,count, + {var uintD temp = ~ (*--xptr); *xptr = temp; } + ); + } + +#endif + +#ifndef TEST_LOOPS + +// AND-Test-Schleife: +// and_test_loop_down(xptr,yptr,count); +// verknüpft count (uintC>=0) Digits abwärts ab xptr und ab yptr durch AND +// und testet, ob sich dabei ein Digit /=0 ergibt. Ergebnis cl_true, falls ja. + inline cl_boolean and_test_loop_down (const uintD* xptr, const uintD* yptr, uintC count) + { dotimesC(count,count, { if (*--xptr & *--yptr) return cl_true; } ); + return cl_false; + } + +// Vergleichsschleife: +// result = compare_loop_down(xptr,yptr,count); +// vergleicht nacheinander xptr[-1] mit yptr[-1], xptr[-2] mit yptr[-2], usw., +// insgesamt count Digits, und liefert 0 falls alle gleich sind, +// +1 falls zuerst ein xptr[i]>yptr[i] ist, +// -1 falls zuerst ein xptr[i] *yptr ? signean_plus : signean_minus); + }); + return signean_null; // alle Digits gleich + } + +#endif + +#ifndef ADDSUB_LOOPS + +// Additionsschleife: +// übertrag = add_loop_up(sourceptr1,sourceptr2,destptr,count); +// addiert count (uintC>=0) Digits aufwärts von sourceptr1, von sourceptr2 +// aufwärts nach destptr und liefert den Ãœbertrag (0 oder /=0, was 1 bedeutet). + inline uintD add_loop_up (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count) + { var uintD source1; + var uintD source2; + if (!(count==0)) + do { source1 = *sourceptr1++; + source2 = *sourceptr2++; + *destptr++ = source1 + source2; + if (source1 > (uintD)(~source2)) goto carry_1; + carry_0: + count--; + } + until (count==0); + return 0; + do { source1 = *sourceptr1++; + source2 = *sourceptr2++; + *destptr++ = source1 + source2 + 1; + if (source1 < (uintD)(~source2)) goto carry_0; + carry_1: + count--; + } + until (count==0); + return 1; + } + +// Additionsschleife: +// übertrag = addto_loop_up(sourceptr,destptr,count); +// addiert count (uintC>=0) Digits aufwärts von sourceptr, von destptr +// aufwärts nach destptr und liefert den Ãœbertrag (0 oder /=0, was 1 bedeutet). + inline uintD addto_loop_up (const uintD* sourceptr, uintD* destptr, uintC count) + { var uintD source1; + var uintD source2; + if (!(count==0)) + do { source1 = *sourceptr++; + source2 = *destptr; + *destptr++ = source1 + source2; + if (source1 > (uintD)(~source2)) goto carry_1; + carry_0: + count--; + } + until (count==0); + return 0; + do { source1 = *sourceptr++; + source2 = *destptr; + *destptr++ = source1 + source2 + 1; + if (source1 < (uintD)(~source2)) goto carry_0; + carry_1: + count--; + } + until (count==0); + return 1; + } + +// Incrementierschleife: +// übertrag = inc_loop_up(ptr,count); +// incrementiert count (uintC>=0) Digits aufwärts von ptr, so lange bis kein +// Ãœbertrag mehr auftritt und liefert den Ãœbertrag (0 oder /=0, was 1 bedeutet). + inline uintD inc_loop_up (uintD* ptr, uintC count) + { dotimesC(count,count, + { if (!( ++(*ptr++) == 0 )) return 0; } // kein weiterer Ãœbertrag + ); + return 1; // weiterer Ãœbertrag + } + +// Subtraktionsschleife: +// übertrag = sub_loop_up(sourceptr1,sourceptr2,destptr,count); +// subtrahiert count (uintC>=0) Digits aufwärts von sourceptr1, von sourceptr2 +// aufwärts nach destptr und liefert den Ãœbertrag (0 oder /=0, was -1 bedeutet). + inline uintD sub_loop_up (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count) + { var uintD source1; + var uintD source2; + if (!(count==0)) + do { source1 = *sourceptr1++; + source2 = *sourceptr2++; + *destptr++ = source1 - source2; + if (source1 < source2) goto carry_1; + carry_0: + count--; + } + until (count==0); + return 0; + do { source1 = *sourceptr1++; + source2 = *sourceptr2++; + *destptr++ = source1 - source2 - 1; + if (source1 > source2) goto carry_0; + carry_1: + count--; + } + until (count==0); + return (uintD)(-1); + } + +// Subtraktionsschleife: +// übertrag = subx_loop_up(sourceptr1,sourceptr2,destptr,count,carry); +// subtrahiert count (uintC>=0) Digits aufwärts von sourceptr1 und addiert +// einen Carry (0 oder -1), von sourceptr2 aufwärts nach destptr und +// liefert den Ãœbertrag (0 oder /=0, was -1 bedeutet). + inline uintD subx_loop_up (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count, uintD carry) + { var uintD source1; + var uintD source2; + if (carry==0) + { if (!(count==0)) + do { source1 = *sourceptr1++; + source2 = *sourceptr2++; + *destptr++ = source1 - source2; + if (source1 < source2) goto carry_1; + carry_0: + count--; + } + until (count==0); + return 0; + } + else + { if (!(count==0)) + do { source1 = *sourceptr1++; + source2 = *sourceptr2++; + *destptr++ = source1 - source2 - 1; + if (source1 > source2) goto carry_0; + carry_1: + count--; + } + until (count==0); + return (uintD)(-1); + } } + +// Subtraktionsschleife: +// übertrag = subfrom_loop_up(sourceptr,destptr,count); +// subtrahiert count (uintC>=0) Digits aufwärts von sourceptr, von destptr +// aufwärts nach destptr (dest := dest - source) +// und liefert den Ãœbertrag (0 oder /=0, was -1 bedeutet). + inline uintD subfrom_loop_up (const uintD* sourceptr, uintD* destptr, uintC count) + { var uintD source1; + var uintD source2; + if (!(count==0)) + do { source1 = *destptr; + source2 = *sourceptr++; + *destptr++ = source1 - source2; + if (source1 < source2) goto carry_1; + carry_0: + count--; + } + until (count==0); + return 0; + do { source1 = *destptr; + source2 = *sourceptr++; + *destptr++ = source1 - source2 - 1; + if (source1 > source2) goto carry_0; + carry_1: + count--; + } + until (count==0); + return (uintD)(-1); + } + +// Decrementierschleife: +// übertrag = dec_loop_up(ptr,count); +// decrementiert count (uintC>=0) Digits aufwärts von ptr, so lange bis kein +// Ãœbertrag mehr auftritt und liefert den Ãœbertrag (0 oder -1). + inline uintD dec_loop_up (uintD* ptr, uintC count) + { dotimesC(count,count, + { if (!( (*ptr++)-- == 0 )) return 0; } // kein weiterer Ãœbertrag + ); + return (uintD)(-1); // weiterer Ãœbertrag + } + +// Negierschleife: +// übertrag = neg_loop_up(ptr,count); +// negiert count (uintC>=0) Digits aufwärts von ptr, +// und liefert den Ãœbertrag (0 oder -1). + inline uintD neg_loop_up (uintD* ptr, uintC count) + { // erstes Digit /=0 suchen: + until (count==0) { if (!(*ptr == 0)) goto L1; ptr++; count--; } + return 0; + L1: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys + *ptr = - *ptr; count--; // 1 Digit negieren + dotimesC(count,count, { ptr++; *ptr = ~ *ptr; } ); // alle anderen Digits invertieren + return (uintD)(-1); + } + +#endif + +#ifndef SHIFT_LOOPS + +// Schiebeschleife um 1 Bit nach links: +// übertrag = shift1left_loop_up(ptr,count); +// schiebt count (uintC>=0) Digits aufwärts von ptr um 1 Bit nach links, +// und liefert den Ãœbertrag (0 oder /=0, was 1 bedeutet). + #if HAVE_DD + inline uintD shift1left_loop_up (uintD* ptr, uintC count) + { var uintDD accu = 0; + dotimesC(count,count, + { accu = ((uintDD)(*ptr)<<1)+accu; *ptr++ = lowD(accu); + accu = (uintDD)(highD(accu)); + }); + return (uintD)accu; + } + #else + inline uintD shift1left_loop_up (uintD* ptr, uintC count) + { var uintD carry = 0; + dotimesC(count,count, + { var uintD accu = *ptr; + *ptr++ = (accu<<1) | carry; + carry = accu>>(intDsize-1); + }); + return carry; + } + #endif + +// Schiebeschleife um i Bits nach links: +// übertrag = shiftleft_loop_up(ptr,count,i,übertrag_init); +// schiebt count (uintC>=0) Digits aufwärts von ptr um i Bits (0=0, <2^i). + #if HAVE_DD + inline uintD shiftleft_loop_up (uintD* ptr, uintC count, uintC i, uintD carry) + { var uintDD accu = (uintDD)carry; + dotimesC(count,count, + { accu = ((uintDD)(*ptr)<>j; + }); + return carry; + } + #endif + +// Schiebe- und Kopierschleife um i Bits nach links: +// übertrag = shiftleftcopy_loop_up(sourceptr,destptr,count,i); +// kopiert count (uintC>=0) Digits aufwärts von sourceptr nach destptr +// und schiebt sie dabei um i Bits (0=0, <2^i). + #if HAVE_DD + inline uintD shiftleftcopy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count, uintC i) + { var uintDD accu = 0; + dotimesC(count,count, + { accu = ((uintDD)(*sourceptr++)<>j; + }); + return carry; + } + #endif + +// Schiebeschleife um 1 Bit nach rechts: +// übertrag = shift1right_loop_down(ptr,count,übertrag_init); +// schiebt count (uintC>=0) Digits abwärts von ptr um 1 Bit nach rechts, +// wobei links das Bit übertrag_init (sollte =0 oder =-1 sein) hineingeschoben +// wird, und liefert den Ãœbertrag (0 oder /=0, was 1 bedeutet). + #if HAVE_DD + inline uintD shift1right_loop_down (uintD* ptr, uintC count, uintD carry) + { var uintDD accu = (sintDD)(sintD)carry & ((uintDD)1 << (2*intDsize-1)); // 0 oder bit(2*intDsize-1) + dotimesC(count,count, + { accu = (highlowDD_0(*--ptr)>>1)+accu; *ptr = highD(accu); + accu = highlowDD_0(lowD(accu)); + }); + return highD(accu); + } + #else + inline uintD shift1right_loop_down (uintD* ptr, uintC count, uintD carry) + { carry = carry << (intDsize-1); // carry zu einem einzigen Bit machen + dotimesC(count,count, + { var uintD accu = *--ptr; + *ptr = (accu >> 1) | carry; + carry = accu << (intDsize-1); + }); + return carry; + } + #endif + +// Schiebeschleife um i Bits nach rechts: +// übertrag = shiftright_loop_down(ptr,count,i); +// schiebt count (uintC>=0) Digits abwärts von ptr um i Bits (0>i)+accu; *ptr = highD(accu); + }); + return lowD(accu); + } + #else + inline uintD shiftright_loop_down (uintD* ptr, uintC count, uintC i) + { var uintC j = intDsize-i; + var uintD carry = 0; + dotimesC(count,count, + { var uintD accu = *--ptr; + *ptr = (accu >> i) | carry; + carry = accu << j; + }); + return carry; + } + #endif + +// Schiebeschleife um i Bits nach rechts: +// übertrag = shiftrightsigned_loop_down(ptr,count,i); +// schiebt count (uintC>0) Digits abwärts von ptr um i Bits (0>i; + dotimespC(count,count, + { // Die oberen i Bits von (uintD)accu bilden hier den Ãœbertrag. + accu = highlowDD_0(lowD(accu)); + // Die oberen i Bits von (uintDD)accu bilden hier den Ãœbertrag. + accu = (highlowDD_0(*--ptr)>>i)+accu; *ptr = highD(accu); + }); + return lowD(accu); + } + #else + inline uintD shiftrightsigned_loop_down (uintD* ptr, uintC count, uintC i) + { var uintC j = intDsize-i; + var uintD carry; + { var uintD accu = *--ptr; + *ptr = (sintD)accu >> i; + carry = accu << j; + count--; + } + dotimesC(count,count, + { var uintD accu = *--ptr; + *ptr = (accu >> i) | carry; + carry = accu << j; + }); + return carry; + } + #endif + +// Schiebe- und Kopier-Schleife um i Bits nach rechts: +// übertrag = shiftrightcopy_loop_down(sourceptr,destptr,count,i,carry); +// kopiert count (uintC>=0) Digits abwärts von sourceptr nach destptr +// und schiebt sie dabei um i Bits (0>i; + dotimesC(count,count, + { // Die oberen i Bits von (uintD)accu bilden hier den Ãœbertrag. + accu = highlowDD_0(lowD(accu)); + // Die oberen i Bits von (uintDD)accu bilden hier den Ãœbertrag. + accu = (highlowDD_0(*--sourceptr)>>i)+accu; *--destptr = highD(accu); + }); + return lowD(accu); + } + #else + inline uintD shiftrightcopy_loop_down (const uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry) + { var uintC j = intDsize-i; + carry = carry << j; + dotimesC(count,count, + { var uintD accu = *--sourceptr; + *--destptr = (accu >> i) | carry; + carry = accu << j; + }); + return carry; + } + #endif + +#endif + +#ifndef MUL_LOOPS + +// Multiplikations-Einfachschleife: +// Multipliziert eine UDS mit einem kleinen Digit und addiert ein kleines Digit. +// mulusmall_loop_up(digit,ptr,len,newdigit) +// multipliziert die UDS ptr[0..len-1] mit digit (>=2, <=36), +// addiert dabei newdigit (>=0, =0, 0) +// mit dem einzelnen digit +// und legt das Ergebnis in der UDS destptr[0..len] ab. + #if HAVE_DD + inline void mulu_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len) + { var uintDD carry = 0; + dotimespC(len,len, + { // Hier ist carry=digit=0 oder 0 <= carry < digit. + carry = carry + muluD(digit,*sourceptr++); + // Hier ist carry=digit=0 oder 0 <= carry < 2^intDsize*digit. + *destptr++ = lowD(carry); + carry = (uintDD)highD(carry); // carry := floor(carry/2^intDsize) < digit + }); + *destptr++ = lowD(carry); + } + #else + inline void mulu_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len) + { var uintD carry = 0; + dotimespC(len,len, + { // Hier ist carry=digit=0 oder 0 <= carry < digit. + var uintD hi; + var uintD lo; + muluD(digit,*sourceptr++,hi=,lo=); + // Hier ist 0 <= 2^intDsize*hi + lo + carry < 2^intDsize*digit oder hi=lo=carry=digit=0. + lo += carry; if (lo < carry) { hi += 1; } + *destptr++ = lo; + carry = hi; + }); + *destptr++ = carry; + } + #endif + +// Multiplikations-Einfachschleife mit Akkumulation: +// Multipliziert eine UDS mit einem Digit und addiert das Ergebnis zu einer +// zweiten UDS auf. +// muluadd_loop_up(digit,sourceptr,destptr,len); +// multipliziert die UDS sourceptr[0..len-1] (len>0) +// mit dem einzelnen digit, legt das Ergebnis in der UDS destptr[0..len-1] +// ab und liefert den weiteren Ãœbertrag. + #if HAVE_DD + inline uintD muluadd_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len) + { var uintDD carry = 0; + if (!(digit==0)) + { dotimespC(len,len, + { // Hier ist 0 <= carry <= digit. + carry = carry + muluD(digit,*sourceptr++) + (uintDD)*destptr; + // Hier ist 0 <= carry <= 2^intDsize*digit + 2^intDsize-1. + *destptr++ = lowD(carry); + carry = (uintDD)highD(carry); // carry := floor(carry/2^intDsize) <= digit + }); + } + return lowD(carry); + } + #else + inline uintD muluadd_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len) + { var uintD carry = 0; + if (!(digit==0)) + { dotimespC(len,len, + { // Hier ist 0 <= carry <= digit. + var uintD hi; + var uintD lo; + muluD(digit,*sourceptr++,hi=,lo=); + // Hier ist 0 <= 2^intDsize*hi + lo + carry + *destptr <= 2^intDsize*digit+2^intDsize-1. + lo += carry; if (lo < carry) { hi += 1; } + carry = *destptr; + lo += carry; if (lo < carry) { hi += 1; } + *destptr++ = lo; + carry = hi; + }); + } + return carry; + } + #endif + +// Multiplikations-Einfachschleife mit Diminution: +// Multipliziert eine UDS mit einem Digit und subtrahiert das Ergebnis von +// einer zweiten UDS. +// mulusub_loop_up(digit,sourceptr,destptr,len); +// multipliziert die UDS sourceptr[0..len-1] (len>0) mit dem einzelnen +// digit, subtrahiert das Ergebnis von der UDS destptr[0..len-1] und liefert +// den weiteren Ãœbertrag (>=0, evtl. von destptr[len] zu subtrahieren). + #if HAVE_DD + inline uintD mulusub_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len) + { var uintDD carry = 0; + if (!(digit==0)) + { dotimespC(len,len, + { // Hier ist 0 <= carry <= digit. + carry = carry + muluD(digit,*sourceptr++) + (uintD)(~(*destptr)); + // Hier ist 0 <= carry <= 2^intDsize*digit + 2^intDsize-1. + *destptr++ = ~lowD(carry); + carry = (uintDD)highD(carry); // carry := floor(carry/2^intDsize) <= digit + // Hier ist 0 <= carry <= digit. + }); + return lowD(carry); + } + else + return 0; // nichts zu subtrahieren -> kein Ãœbertrag + } + #else + inline uintD mulusub_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len) + { var uintD carry = 0; + if (!(digit==0)) + { dotimespC(len,len, + { // Hier ist 0 <= carry <= digit. + var uintD hi; + var uintD lo; + muluD(digit,*sourceptr++,hi=,lo=); + // Hier ist 0 <= 2^intDsize*hi + lo + carry + ~(*destptr) <= 2^intDsize*digit+2^intDsize-1. + lo += carry; if (lo < carry) { hi += 1; } + carry = *destptr; + *destptr++ = carry - lo; if (carry < lo) { hi += 1; } + carry = hi; + }); + return carry; + } + else + return 0; // nichts zu subtrahieren -> kein Ãœbertrag + } + #endif + +#endif + +#ifndef DIV_LOOPS + +// Divisions-Einfachschleife: +// Dividiert eine UDS durch ein Digit. +// divu_loop_down(digit,ptr,len) +// dividiert die UDS ptr[-len..-1] durch digit, +// legt das Ergebnis in derselben UDS ab, und liefert den Rest (>=0, =0, yptr[i] ist, +// -1 falls zuerst ein xptr[i] *--yptr ? signean_plus : signean_minus); + }); + return signean_null; // alle Digits gleich + } + +#endif + +#if !defined(LOG_LOOPS) && !CL_DS_BIG_ENDIAN_P + +// XOR-Schleife: +// xor_loop_up(xptr,yptr,count); +// verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr +// mit Ziel ab xptr durch XOR. + inline void xor_loop_up (uintD* xptr, const uintD* yptr, uintC count) + { dotimesC(count,count, { *xptr++ ^= *yptr++; } ); } + +#endif + +#if !defined(SHIFT_LOOPS) && CL_DS_BIG_ENDIAN_P + +// Schiebe- und Kopierschleife um i Bits nach links: +// übertrag = shiftleftcopy_loop_up(sourceptr,destptr,count,i); +// kopiert count (uintC>=0) Digits aufwärts von sourceptr nach destptr +// und schiebt sie dabei um i Bits (0=0, <2^i). + #if HAVE_DD + inline uintD shiftleftcopy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count, uintC i) + { var uintDD accu = 0; + dotimesC(count,count, + { accu = ((uintDD)(*sourceptr++)<>j; + }); + return carry; + } + #endif + +#endif + +#if !defined(SHIFT_LOOPS) + +// Schiebe- und XOR-Schleife: +// shiftxor_loop_up(xptr,yptr,count,i); +// verknüpft count+1 Digits aufwärts ab xptr mit count Digits aufwärts ab yptr, +// um i Bits verschoben, durch XOR. (count uintC>=0, 0 0) + { var uintD carry = xptr[0]; + dotimespC(count,count, + { var uintDD accu = highlowDD(xptr[1],carry); + accu = ((uintDD)(*yptr++)< 0) + { var uintC j = intDsize-i; + var uintD carry = *xptr; + dotimespC(count,count, + { var uintD accu = *yptr++; + *xptr++ = (accu<>j) ^ *xptr; + }); + *xptr = carry; + } } + #endif + +#endif + + +// Endianness independent names for these functions. +#if CL_DS_BIG_ENDIAN_P + #define copy_loop_msp copy_loop_up + #define copy_loop_lsp copy_loop_down + #define fill_loop_msp fill_loop_up + #define fill_loop_lsp fill_loop_down + #define clear_loop_msp clear_loop_up + #define clear_loop_lsp clear_loop_down + #define test_loop_msp test_loop_up + #define or_loop_msp or_loop_up + #define xor_loop_msp xor_loop_up + #define and_loop_msp and_loop_up + #define eqv_loop_msp eqv_loop_up + #define nand_loop_msp nand_loop_up + #define nor_loop_msp nor_loop_up + #define andc2_loop_msp andc2_loop_up + #define orc2_loop_msp orc2_loop_up + #define not_loop_msp not_loop_up + #define and_test_loop_msp and_test_loop_up + #define compare_loop_msp compare_loop_up + #define add_loop_lsp add_loop_down + #define addto_loop_lsp addto_loop_down + #define inc_loop_lsp inc_loop_down + #define sub_loop_lsp sub_loop_down + #define subx_loop_lsp subx_loop_down + #define subfrom_loop_lsp subfrom_loop_down + #define dec_loop_lsp dec_loop_down + #define neg_loop_lsp neg_loop_down + #define shift1left_loop_lsp shift1left_loop_down + #define shiftleft_loop_lsp shiftleft_loop_down + #define shiftleftcopy_loop_lsp shiftleftcopy_loop_down + #define shift1right_loop_msp shift1right_loop_up + #define shiftright_loop_msp shiftright_loop_up + #define shiftrightsigned_loop_msp shiftrightsigned_loop_up + #define shiftrightcopy_loop_msp shiftrightcopy_loop_up + #define mulusmall_loop_lsp mulusmall_loop_down + #define mulu_loop_lsp mulu_loop_down + #define muluadd_loop_lsp muluadd_loop_down + #define mulusub_loop_lsp mulusub_loop_down + #define divu_loop_msp divu_loop_up + #define divucopy_loop_msp divucopy_loop_up +#else + #define copy_loop_msp copy_loop_down + #define copy_loop_lsp copy_loop_up + #define fill_loop_msp fill_loop_down + #define fill_loop_lsp fill_loop_up + #define clear_loop_msp clear_loop_down + #define clear_loop_lsp clear_loop_up + #define test_loop_msp test_loop_down + #define or_loop_msp or_loop_down + #define xor_loop_msp xor_loop_down + #define and_loop_msp and_loop_down + #define eqv_loop_msp eqv_loop_down + #define nand_loop_msp nand_loop_down + #define nor_loop_msp nor_loop_down + #define andc2_loop_msp andc2_loop_down + #define orc2_loop_msp orc2_loop_down + #define not_loop_msp not_loop_down + #define and_test_loop_msp and_test_loop_down + #define compare_loop_msp compare_loop_down + #define add_loop_lsp add_loop_up + #define addto_loop_lsp addto_loop_up + #define inc_loop_lsp inc_loop_up + #define sub_loop_lsp sub_loop_up + #define subx_loop_lsp subx_loop_up + #define subfrom_loop_lsp subfrom_loop_up + #define dec_loop_lsp dec_loop_up + #define neg_loop_lsp neg_loop_up + #define shift1left_loop_lsp shift1left_loop_up + #define shiftleft_loop_lsp shiftleft_loop_up + #define shiftleftcopy_loop_lsp shiftleftcopy_loop_up + #define shift1right_loop_msp shift1right_loop_down + #define shiftright_loop_msp shiftright_loop_down + #define shiftrightsigned_loop_msp shiftrightsigned_loop_down + #define shiftrightcopy_loop_msp shiftrightcopy_loop_down + #define mulusmall_loop_lsp mulusmall_loop_up + #define mulu_loop_lsp mulu_loop_up + #define muluadd_loop_lsp muluadd_loop_up + #define mulusub_loop_lsp mulusub_loop_up + #define divu_loop_msp divu_loop_down + #define divucopy_loop_msp divucopy_loop_down +#endif + +// Endianness independent loops where the direction doesn't matter. +#if CL_DS_BIG_ENDIAN_P + #define DS_clear_loop(MSDptr,len,LSDptr) (void)clear_loop_up(MSDptr,len) + #define DS_test_loop(MSDptr,len,LSDptr) test_loop_up(MSDptr,len) +#else + #define DS_clear_loop(MSDptr,len,LSDptr) (void)clear_loop_up(LSDptr,len) + #define DS_test_loop(MSDptr,len,LSDptr) test_loop_up(LSDptr,len) +#endif + + +// Umwandlungsroutinen Digit-Sequence-Teil <--> Longword: + +// get_32_Dptr(ptr) +// holt die nächsten 32 Bits aus den 32/intDsize Digits ab ptr. +// set_32_Dptr(ptr,wert); +// speichert den Wert wert (32 Bits) in die 32/intDsize Digits ab ptr. +// get_max32_Dptr(count,ptr) +// holt die nächsten count Bits aus den ceiling(count/intDsize) Digits ab ptr. +// set_max32_Dptr(count,ptr,wert) +// speichert wert (count Bits) in die ceiling(count/intDsize) Digits ab ptr. +// Jeweils ptr eine Variable vom Typ uintD*, +// wert eine Variable vom Typ uint32, +// count eine Variable oder constant-expression mit Wert >=0, <=32. + #if (intDsize==32) + inline uint32 get_32_Dptr (const uintD* ptr) + { + return mspref(ptr,0); + } + inline void set_32_Dptr (uintD* ptr, uint32 wert) + { + mspref(ptr,0) = wert; + } + inline uint32 get_max32_Dptr (uintC count, const uintD* ptr) + { + return count==0 ? 0 : + mspref(ptr,0); + } + inline void set_max32_Dptr (uintC count, uintD* ptr, uint32 wert) + { + if (count==0) return; + mspref(ptr,0) = wert; return; + } + #endif + #if (intDsize==16) + inline uint32 get_32_Dptr (const uintD* ptr) + { + return ((uint32)mspref(ptr,0)<<16) | (uint32)mspref(ptr,1); + } + inline void set_32_Dptr (uintD* ptr, uint32 wert) + { + mspref(ptr,0) = (uintD)(wert>>16); mspref(ptr,1) = (uintD)wert; + } + inline uint32 get_max32_Dptr (uintC count, const uintD* ptr) + { + return count==0 ? 0 : + count<=16 ? mspref(ptr,0) : + ((uint32)mspref(ptr,0)<<16) | (uint32)mspref(ptr,1); + } + inline void set_max32_Dptr (uintC count, uintD* ptr, uint32 wert) + { + if (count==0) return; + if (count<=16) { mspref(ptr,0) = (uintD)wert; return; } + mspref(ptr,0) = (uintD)(wert>>16); mspref(ptr,1) = (uintD)wert; return; + } + #endif + #if (intDsize==8) + inline uint32 get_32_Dptr (const uintD* ptr) + { + return ((((((uint32)mspref(ptr,0) <<8) | (uint32)mspref(ptr,1)) <<8) | (uint32)mspref(ptr,2)) <<8) | (uint32)mspref(ptr,3); + } + inline void set_32_Dptr (uintD* ptr, uint32 wert) + { + mspref(ptr,0) = (uintD)(wert>>24); mspref(ptr,1) = (uintD)(wert>>16); mspref(ptr,2) = (uintD)(wert>>8); mspref(ptr,3) = (uintD)wert; + } + inline uint32 get_max32_Dptr (uintC count, const uintD* ptr) + { + return count==0 ? 0 : + count<=8 ? mspref(ptr,0) : + count<=16 ? ((uint32)mspref(ptr,0)<<8) | (uint32)mspref(ptr,1) : + count<=24 ? ((((uint32)mspref(ptr,0)<<8) | (uint32)mspref(ptr,1))<<8) | (uint32)mspref(ptr,2) : + ((((((uint32)mspref(ptr,0)<<8) | (uint32)mspref(ptr,1))<<8) | (uint32)mspref(ptr,2))<<8) | (uint32)mspref(ptr,3); + } + inline void set_max32_Dptr (uintC count, uintD* ptr, uint32 wert) + { + if (count==0) return; + if (count<=8) { mspref(ptr,0) = (uintD)wert; return; } + if (count<=16) { mspref(ptr,0) = (uintD)(wert>>8); mspref(ptr,1) = (uintD)wert; return; } + if (count<=24) { mspref(ptr,0) = (uintD)(wert>>16); mspref(ptr,1) = (uintD)(wert>>8); mspref(ptr,2) = (uintD)wert; return; } + mspref(ptr,0) = (uintD)(wert>>24); mspref(ptr,1) = (uintD)(wert>>16); mspref(ptr,2) = (uintD)(wert>>8); mspref(ptr,3) = (uintD)wert; return; + } + #endif + +#if (cl_word_size==64) +// get_64_Dptr(ptr) +// holt die nächsten 64 Bits aus den 64/intDsize Digits ab ptr. +// set_64_Dptr(ptr,wert); +// speichert den Wert wert (64 Bits) in die 64/intDsize Digits ab ptr. +// get_max64_Dptr(count,ptr) +// holt die nächsten count Bits aus den ceiling(count/intDsize) Digits ab ptr. +// set_max64_Dptr(count,ptr,wert) +// speichert wert (count Bits) in die ceiling(count/intDsize) Digits ab ptr. +// Jeweils ptr eine Variable vom Typ uintD*, +// wert eine Variable vom Typ uint64, +// count eine Variable oder constant-expression mit Wert >=0, <=64. + #if (intDsize==64) + inline uint64 get_64_Dptr (const uintD* ptr) + { + return mspref(ptr,0); + } + inline void set_64_Dptr (uintD* ptr, uint64 wert) + { + mspref(ptr,0) = wert; + } + inline uint64 get_max64_Dptr (uintC count, const uintD* ptr) + { + return count==0 ? 0 : mspref(ptr,0); + } + inline void set_max64_Dptr (uintC count, uintD* ptr, uint64 wert) + { + if (count==0) return; + mspref(ptr,0) = wert; return; + } + #else // (intDsize<=32) + inline uint64 get_64_Dptr (const uintD* ptr) + { + return ((uint64)get_32_Dptr(ptr) << 32) | (uint64)get_32_Dptr(ptr mspop 32/intDsize); + } + inline void set_64_Dptr (uintD* ptr, uint64 wert) + { + set_32_Dptr(ptr,(uint32)(wert>>32)); + set_32_Dptr(ptr mspop 32/intDsize,(uint32)wert); + } + inline uint64 get_max64_Dptr (uintC count, const uintD* ptr) + { + return count==0 ? 0 : + count<=32 ? (uint64)get_max32_Dptr(count,ptr) : + ((uint64)get_max32_Dptr(count-32,ptr) << 32) | (uint64)get_32_Dptr(ptr mspop ceiling(count-32,intDsize)); + } + inline void set_max64_Dptr (uintC count, uintD* ptr, uint64 wert) + { + if (count==0) return; + if (count<=32) { set_max32_Dptr(count,ptr,(uint32)wert); return; } + set_max32_Dptr(count-32,ptr,(uint32)(wert>>32)); + set_32_Dptr(ptr mspop ceiling(count-32,intDsize),(uint32)wert); return; + } + #endif +#endif + +// get_uint1D_Dptr(ptr) holt 1 Digit (unsigned) ab ptr +// get_uint2D_Dptr(ptr) holt 2 Digits (unsigned) ab ptr +// get_uint3D_Dptr(ptr) holt 3 Digits (unsigned) ab ptr +// get_uint4D_Dptr(ptr) holt 4 Digits (unsigned) ab ptr +// get_sint1D_Dptr(ptr) holt 1 Digit (signed) ab ptr +// get_sint2D_Dptr(ptr) holt 2 Digits (signed) ab ptr +// get_sint3D_Dptr(ptr) holt 3 Digits (signed) ab ptr +// get_sint4D_Dptr(ptr) holt 4 Digits (signed) ab ptr +// Jeweils ptr eine Variable vom Typ uintD*. +// NB: Bei intDsize==64 sind diese Funktionen nur sehr bedingt tauglich. + inline uint32 get_uint1D_Dptr (const uintD* ptr) + { + return lspref(ptr,0); + } + inline sint32 get_sint1D_Dptr (const uintD* ptr) + { + return (sint32)(sintD)lspref(ptr,0); + } + #if (intDsize < 32) + inline uint32 get_uint2D_Dptr (const uintD* ptr) + { + return ((uint32)lspref(ptr,1) << intDsize) | (uint32)lspref(ptr,0); + } + inline sint32 get_sint2D_Dptr (const uintD* ptr) + { + return ((uint32)(sint32)(sintD)lspref(ptr,1) << intDsize) | (uint32)lspref(ptr,0); + } + #else + #define get_uint2D_Dptr(ptr) get_uint1D_Dptr(ptr) + #define get_sint2D_Dptr(ptr) (sint32)get_uint2D_Dptr(ptr) + #endif + #if (intDsize < 16) + inline uint32 get_uint3D_Dptr (const uintD* ptr) + { + return ((((uint32)lspref(ptr,2) << intDsize) | (uint32)lspref(ptr,1)) << intDsize) | (uint32)lspref(ptr,0); + } + inline sint32 get_sint3D_Dptr (const uintD* ptr) + { + return ((((uint32)(sint32)(sintD)lspref(ptr,2) << intDsize) | (uint32)lspref(ptr,1)) << intDsize) | (uint32)lspref(ptr,0); + } + inline uint32 get_uint4D_Dptr (const uintD* ptr) + { + return ((((((uint32)lspref(ptr,3) << intDsize) | (uint32)lspref(ptr,2)) << intDsize) | (uint32)lspref(ptr,1)) << intDsize) | (uint32)lspref(ptr,0); + } + inline sint32 get_sint4D_Dptr (const uintD* ptr) + { + return ((((((uint32)(sint32)(sintD)lspref(ptr,3) << intDsize) | (uint32)lspref(ptr,2)) << intDsize) | (uint32)lspref(ptr,1)) << intDsize) | (uint32)lspref(ptr,0); + } + #else + #define get_uint3D_Dptr(ptr) get_uint2D_Dptr(ptr) + #define get_sint3D_Dptr(ptr) (sint32)get_uint3D_Dptr(ptr) + #define get_uint4D_Dptr(ptr) get_uint2D_Dptr(ptr) + #define get_sint4D_Dptr(ptr) (sint32)get_uint4D_Dptr(ptr) + #endif + + +// NUM_STACK ist eine Art Zahlen-Stack-Pointer. +// Verwendung: +// {CL_ALLOCA_STACK; +// ... +// num_stack_alloc(...); +// ... +// num_stack_array(...); +// ... +// } +// CL_ALLOCA_STACK rettet den aktuellen Wert von NUM_STACK. +// Dann darf beliebig oft mit num_stack_alloc/num_stack_array Platz auf dem +// Zahlen-Stack belegt werden. +// Beim Ende des Blocks wird NUM_STACK wieder auf den vorigen Wert gesetzt, +// und der Platz gilt als wieder freigegeben. +// In jeder C-Funktion sollte CL_ALLOCA_STACK nur einmal aufgerufen werden. +// Wegen eines GCC-Bugs sollten Funktionen, die diese Macros benutzen, +// nicht inline deklariert sein. + +// num_stack_array(need, low_addr = , high_addr = ); +// num_stack_small_array(need, low_addr = , high_addr = ); +// belegt need Digits auf dem Zahlen-Stack und legt die untere Grenze des +// allozierten Bereichs in low_addr und die obere Grenze in high_addr ab. +// Jedes von beiden ist optional. + +// num_stack_alloc(need, MSDptr = , LSDptr = ); +// num_stack_small_alloc(need, MSDptr = , LSDptr = ); +// belegt need Digits auf dem Zahlen-Stack und legt den MSDptr und den +// LSDptr ab. Jedes von beiden ist optional. + +// num_stack_alloc_1(need, MSDptr = , LSDptr = ); +// num_stack_small_alloc_1(need, MSDptr = , LSDptr = ); +// wie num_stack_alloc, nur daß unterhalb von MSDptr noch ein Digit Platz +// zusätzlich belegt wird. + +#define num_stack_array(need,low_zuweisung,high_zuweisung) \ + {var uintL __need = (uintL)(need); \ + var uintD* __array = cl_alloc_array(uintD,__need); \ + unused (low_zuweisung &__array[0]); unused (high_zuweisung &__array[__need]); \ + } +#define num_stack_small_array(need,low_zuweisung,high_zuweisung) \ + {var uintL __need = (uintL)(need); \ + var uintD* __array = cl_small_alloc_array(uintD,__need); \ + unused (low_zuweisung &__array[0]); unused (high_zuweisung &__array[__need]); \ + } +#if CL_DS_BIG_ENDIAN_P + #define num_stack_alloc(need,MSDptr_zuweisung,LSDptr_zuweisung) \ + num_stack_array(need,MSDptr_zuweisung,LSDptr_zuweisung) + #define num_stack_small_alloc(need,MSDptr_zuweisung,LSDptr_zuweisung) \ + num_stack_small_array(need,MSDptr_zuweisung,LSDptr_zuweisung) + #define num_stack_alloc_1(need,MSDptr_zuweisung,LSDptr_zuweisung) \ + num_stack_array((uintL)(need)+1,MSDptr_zuweisung 1 + ,LSDptr_zuweisung) + #define num_stack_small_alloc_1(need,MSDptr_zuweisung,LSDptr_zuweisung) \ + num_stack_small_array((uintL)(need)+1,MSDptr_zuweisung 1 + ,LSDptr_zuweisung) +#else + #define num_stack_alloc(need,MSDptr_zuweisung,LSDptr_zuweisung) \ + num_stack_array(need,LSDptr_zuweisung,MSDptr_zuweisung) + #define num_stack_small_alloc(need,MSDptr_zuweisung,LSDptr_zuweisung) \ + num_stack_small_array(need,LSDptr_zuweisung,MSDptr_zuweisung) + #define num_stack_alloc_1(need,MSDptr_zuweisung,LSDptr_zuweisung) \ + num_stack_array((uintL)(need)+1,LSDptr_zuweisung,MSDptr_zuweisung -1 + ) + #define num_stack_small_alloc_1(need,MSDptr_zuweisung,LSDptr_zuweisung) \ + num_stack_small_array((uintL)(need)+1,LSDptr_zuweisung,MSDptr_zuweisung -1 + ) +#endif + + +// Macro: In der DS MSDptr/len/LSDptr wird eine 1 unterhalb des Pointers ptr +// addiert. Unterhalb von MSDptr muß 1 Digit Platz sein. +// Dabei ist ptr - MSDptr = count und 0 < count <= len . +// Eventuell wird MSDptr erniedrigt und len erhöht. + #define DS_1_plus(ptr,count) \ + {var uintD* ptr_from_DS_1_plus = (ptr); \ + var uintC count_from_DS_1_plus = (count); \ + loop { if (--count_from_DS_1_plus==0) /* Zähler erniedrigen */\ + { /* Beim Most Significant Digit angelangt */\ + lsprefnext(ptr_from_DS_1_plus) += 1; \ + /* jetzt ist ptr_from_DS_1_plus = MSDptr */\ + if (mspref(ptr_from_DS_1_plus,0) == (uintD)bit(intDsize-1)) \ + { /* 7FFF + 1 muß zu 00008000 werden: */\ + lsprefnext(MSDptr) = 0; \ + len++; \ + } \ + break; \ + } \ + if (!((lsprefnext(ptr_from_DS_1_plus) += 1) == 0)) /* weiterincrementieren */\ + break; /* kein weiterer Ãœbertrag -> Schleife abbrechen */\ + } } + +// Macro: In der DS MSDptr/len/LSDptr wird eine 1 unterhalb des Pointers ptr +// subtrahiert. Unterhalb von MSDptr muß 1 Digit Platz sein. +// Dabei ist ptr - MSDptr = count und 0 < count <= len . +// Eventuell wird MSDptr erniedrigt und len erhöht. + #define DS_minus1_plus(ptr,count) \ + {var uintD* ptr_from_DS_minus1_plus = (ptr); \ + var uintC count_from_DS_minus1_plus = (count); \ + loop { if (--count_from_DS_minus1_plus==0) /* Zähler erniedrigen */\ + { /* Beim Most Significant Digit angelangt */\ + lsprefnext(ptr_from_DS_minus1_plus) -= 1; \ + /* jetzt ist ptr_from_DS_minus1_plus = MSDptr */\ + if (mspref(ptr_from_DS_minus1_plus,0) == (uintD)bit(intDsize-1)-1) \ + { /* 8000 - 1 muß zu FFFF7FFF werden: */\ + lsprefnext(MSDptr) = (uintD)(-1); \ + len++; \ + } \ + break; \ + } \ + if (!((sintD)(lsprefnext(ptr_from_DS_minus1_plus) -= 1) == -1)) /* weiterdecrementieren */\ + break; /* kein weiterer Ãœbertrag -> Schleife abbrechen */\ + } } + + +// Multiplikations-Doppelschleife: +// Multipliziert zwei UDS und legt das Ergebnis in einer dritten UDS ab. +// cl_UDS_mul(sourceptr1,len1,sourceptr2,len2,destptr); +// multipliziert die UDS sourceptr1[-len1..-1] (len1>0) +// mit der UDS sourceptr2[-len1..-1] (len2>0) +// und legt das Ergebnis in der UDS destptr[-len..-1] (len=len1+len2) ab. +// Unterhalb von destptr werden len Digits Platz benötigt. +extern void cl_UDS_mul (const uintD* sourceptr1, uintC len1, + const uintD* sourceptr2, uintC len2, + uintD* destptr); +// Spezialfall sourceptr1 == sourceptr2 && len1 == len2. +extern void cl_UDS_mul_square (const uintD* sourceptr, uintC len, + uintD* destptr); + +// Multipliziert zwei Unsigned-Digit-sequences. +// UDS_UDS_mul_UDS(len1,LSDptr1, len2,LSDptr2, MSDptr=,len=,LSDptr=); +// multipliziert die UDS ../len1/LSDptr1 und ../len2/LSDptr2. +// Dabei sollte len1>0 und len2>0 sein. +// Ergebnis ist die UDS MSDptr/len/LSDptr, mit len=len1+len2, im Stack. +// Dabei wird num_stack erniedrigt. + #define UDS_UDS_mul_UDS(len1,LSDptr1,len2,LSDptr2, MSDptr_zuweisung,len_zuweisung,LSDptr_zuweisung) \ + var uintL CONCAT(len_from_UDSmul_,__LINE__) = (uintL)(len1) + (uintL)(len2); \ + var uintD* CONCAT(LSDptr_from_UDSmul_,__LINE__); \ + unused (len_zuweisung CONCAT(len_from_UDSmul_,__LINE__)); \ + num_stack_alloc(CONCAT(len_from_UDSmul_,__LINE__),MSDptr_zuweisung,LSDptr_zuweisung CONCAT(LSDptr_from_UDSmul_,__LINE__) =); \ + cl_UDS_mul((LSDptr1),(len1),(LSDptr2),(len2),CONCAT(LSDptr_from_UDSmul_,__LINE__)); + +// Multipliziert zwei Digit-sequences. +// DS_DS_mul_DS(MSDptr1,len1,LSDptr1, MSDptr2,len2,LSDptr2, MSDptr=,len=,LSDptr=); +// multipliziert die DS MSDptr1/len1/LSDptr1 und MSDptr2/len2/LSDptr2. +// Dabei sollte len1>0 und len2>0 sein, und beide DS sollten /= 0 sein. +// Alles sollten Variablen sein! +// Ergebnis ist die DS MSDptr/len/LSDptr, mit len=len1+len2, im Stack. +// Dabei wird num_stack erniedrigt. + // Methode: + // Erst unsigned multiplizieren. Dann bis zu zwei Subtraktionen. + // Sei b=2^intDsize, k=len1, l=len2, n=DS1, m=DS2. + // Gesucht ist n * m. + // Wir errechnen erst das unsigned-product p (mod b^(k+l)). + // n>0, m>0: p = n*m, n*m = p + // n<0, m>0: p = (n+b^k)*m, n*m + b^(k+l) = p - b^k * m (mod b^(k+l)). + // n>0, m<0: p = n*(m+b^l), n*m + b^(k+l) = p - b^l * n (mod b^(k+l)). + // n<0, m<0: p = (n+b^k)*(m+b^l), + // n*m = p - b^k * (m+b^l) - b^l * (n+b^k) (mod b^(k+l)). + #define DS_DS_mul_DS(MSDptr1,len1,LSDptr1,MSDptr2,len2,LSDptr2, MSDptr_zuweisung,len_zuweisung,LSDptr_zuweisung) \ + var uintD* MSDptr0; \ + var uintD* LSDptr0; \ + var uintL len_from_DSmal = (uintL)(len1) + (uintL)(len2); \ + unused (len_zuweisung len_from_DSmal); \ + num_stack_alloc(len_from_DSmal,MSDptr_zuweisung MSDptr0 =,LSDptr_zuweisung LSDptr0 =); \ + var uintD MSD1_from_DSmal = mspref(MSDptr1,0); \ + var uintD MSD2_from_DSmal = mspref(MSDptr2,0); \ + var uintL len1_from_DSmal = (len1); \ + var uintL len2_from_DSmal = (len2); \ + if (MSD1_from_DSmal==0) { msprefnext(MSDptr0) = 0; len1_from_DSmal--; } \ + if (MSD2_from_DSmal==0) { msprefnext(MSDptr0) = 0; len2_from_DSmal--; } \ + cl_UDS_mul((LSDptr1),len1_from_DSmal,(LSDptr2),len2_from_DSmal,LSDptr0); \ + if ((sintD)MSD1_from_DSmal < 0) /* n<0 ? */\ + /* muß m bzw. m+b^l subtrahieren, um k Digits verschoben: */\ + { subfrom_loop_lsp(LSDptr2,LSDptr0 lspop len1,len2); } \ + if ((sintD)MSD2_from_DSmal < 0) /* m<0 ? */\ + /* muß n bzw. n+b^k subtrahieren, um l Digits verschoben: */\ + { subfrom_loop_lsp(LSDptr1,LSDptr0 lspop len2,len1); } + + +// Dividiert zwei Unsigned Digit sequences durcheinander. +// UDS_divide(a_MSDptr,a_len,a_LSDptr, b_MSDptr,b_len,b_LSDptr, &q,&r); +// Die UDS a = a_MSDptr/a_len/a_LSDptr (a>=0) wird durch +// die UDS b = b_MSDptr/b_len/b_LSDptr (b>=0) dividiert: +// a = q * b + r mit 0 <= r < b. Bei b=0 Error. +// q der Quotient, r der Rest. +// q = q_MSDptr/q_len/q_LSDptr, r = r_MSDptr/r_len/r_LSDptr beides +// Normalized Unsigned Digit sequences. +// Vorsicht: q_LSDptr <= r_MSDptr, +// Vorzeichenerweiterung von r kann q zerstören! +// Vorzeichenerweiterung von q ist erlaubt. +// a und b werden nicht modifiziert. +// num_stack wird erniedrigt. + #define UDS_divide(a_MSDptr,a_len,a_LSDptr,b_MSDptr,b_len,b_LSDptr,q_,r_) \ + /* Platz fürs Ergebnis machen. Brauche maximal a_len+1 Digits. */\ + var uintC _a_len = (a_len); \ + var uintD* roomptr; num_stack_alloc_1(_a_len+1,roomptr=,); \ + cl_UDS_divide(a_MSDptr,_a_len,a_LSDptr,b_MSDptr,b_len,b_LSDptr,roomptr,q_,r_); + extern void cl_UDS_divide (const uintD* a_MSDptr, uintC a_len, const uintD* a_LSDptr, + const uintD* b_MSDptr, uintC b_len, const uintD* b_LSDptr, + uintD* roomptr, DS* q_, DS* r_); + + +// Bildet zu einer Unsigned Digit sequence a die Wurzel +// (genauer: Gaußklammer aus Wurzel aus a). +// UDS_sqrt(a_MSDptr,a_len,a_LSDptr, &b, squarep=) +// > a_MSDptr/a_len/a_LSDptr: eine UDS +// < NUDS b: Gaußklammer der Wurzel aus a +// < squarep: cl_true falls a = b^2, cl_false falls b^2 < a < (b+1)^2. +// a wird nicht modifiziert. +// Vorzeichenerweiterung von b ist erlaubt. +// num_stack wird erniedrigt. + #define UDS_sqrt(a_MSDptr,a_len,a_LSDptr,b_,squarep_zuweisung) \ + { /* ceiling(a_len,2) Digits Platz fürs Ergebnis machen: */\ + var uintC _a_len = (a_len); \ + num_stack_alloc_1(ceiling(_a_len,2),(b_)->MSDptr=,); \ + squarep_zuweisung cl_UDS_sqrt(a_MSDptr,_a_len,a_LSDptr,b_); \ + } + extern cl_boolean cl_UDS_sqrt (const uintD* a_MSDptr, uintC a_len, const uintD* a_LSDptr, DS* b_); + + +// Auxiliary function for approximately computing 1/x +// using Newton iteration. + extern void cl_UDS_recip (const uintD* a_MSDptr, uintC a_len, + uintD* b_MSDptr, uintC b_len); + +// Auxiliary function for approximately computing 1/sqrt(x) +// using Newton iteration. + extern void cl_UDS_recipsqrt (const uintD* a_MSDptr, uintC a_len, + uintD* b_MSDptr, uintC b_len); + + +#endif /* _CL_DS_H */ diff --git a/src/base/digitseq/cl_DS_div.cc b/src/base/digitseq/cl_DS_div.cc new file mode 100644 index 0000000..de88316 --- /dev/null +++ b/src/base/digitseq/cl_DS_div.cc @@ -0,0 +1,376 @@ +// cl_UDS_divide(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_DS.h" + + +// Implementation. + +#include "cl_N.h" +#include "cl_abort.h" + +// We observe the following timings: +// Time for dividing 2*N digits by N digits, on a i486 33 MHz running Linux: +// N standard Newton +// 10 0.0003 0.0012 +// 25 0.0013 0.0044 +// 50 0.0047 0.0125 +// 100 0.017 0.037 +// 250 0.108 0.146 +// 500 0.43 0.44 +// 1000 1.72 1.32 +// 2500 11.2 4.1 +// 5000 44.3 9.5 +// 10000 187 20.6 +// -----> Newton faster for N >= 550. +// Time for dividing 3*N digits by N digits, on a i486 33 MHz running Linux: +// N standard Newton +// 10 0.0006 0.0025 +// 25 0.0026 0.0103 +// 50 0.0092 0.030 +// 100 0.035 0.089 +// 250 0.215 0.362 +// 500 0.85 1.10 +// 1000 3.44 3.21 +// 2500 23.3 7.9 +// 5000 89.0 15.6 +// 10000 362 33.1 +// -----> Newton faster for N >= 740. +// Time for dividing m digits by n digits: +// n = 2,3,5,10,25,50,100,250: Newton never faster. +// n = 400: Newton faster for m >= 440, m < 600 +// n = 500: Newton faster for m >= 530, m < 900 +// n = 600: Newton faster for m >= 630, m < 1250 +// n = 700: Newton faster for m >= 730, m < 1530 +// n = 800: Newton faster for m >= 825, m < 2600 or m >= 5300 +// n = 900: Newton faster for m >= 925, m < 2700 or m >= 3400 +// n = 1000: Newton faster for m >= 1020 +// n = 1500: Newton faster for m >= 1520 +// n = 2000: Newton faster for m >= 2020 +// n = 2500: Newton faster for m >= 2520 +// n = 5000: Newton faster for m >= 5020 +// Break-even-point. When in doubt, prefer to choose the standard algorithm. + static inline cl_boolean cl_recip_suitable (uintL m, uintL n) // m > n + { if (n < 500) + return cl_false; + else + if (n < 1000) + return (cl_boolean)((m >= n+30) && (m < 3*n-600)); + else + return (cl_boolean)(m >= n+20); + } + +// Dividiert zwei Unsigned Digit sequences durcheinander. +// UDS_divide(a_MSDptr,a_len,a_LSDptr, b_MSDptr,b_len,b_LSDptr, &q,&r); +// Die UDS a = a_MSDptr/a_len/a_LSDptr (a>=0) wird durch +// die UDS b = b_MSDptr/b_len/b_LSDptr (b>=0) dividiert: +// a = q * b + r mit 0 <= r < b. Bei b=0 Error. +// q der Quotient, r der Rest. +// q = q_MSDptr/q_len/q_LSDptr, r = r_MSDptr/r_len/r_LSDptr beides +// Normalized Unsigned Digit sequences. +// Vorsicht: q_LSDptr <= r_MSDptr, +// Vorzeichenerweiterung von r kann q zerstören! +// Vorzeichenerweiterung von q ist erlaubt. +// a und b werden nicht modifiziert. +// +// Methode: +// erst a und b normalisieren: a=[a[m-1],...,a[0]], b=[b[n-1],...,b[0]] +// mit m>=0 und n>0 (Stellensystem der Basis beta=2^intDsize). +// Falls m=n=1, Single-Precision-Division: +// r:=0, j:=m, +// while j>0 do +// {Hier (q[m-1]*beta^(m-1)+...+q[j]*beta^j) * b[0] + r*beta^j = +// = a[m-1]*beta^(m-1)+...+a[j]*beta^j und 0<=r=n>1, Multiple-Precision-Division: +// Es gilt a/b < beta^(m-n+1). +// s:=intDsize-1-(Nummer des höchsten Bits in b[n-1]), 0<=s=beta/2. +// Für j=m-n,...,0: {Hier 0 <= r < b*beta^(j+1).} +// Berechne q* : +// q* := floor((r[j+n]*beta+r[j+n-1])/b[n-1]). +// Bei Ãœberlauf (q* >= beta) setze q* := beta-1. +// Berechne c2 := ((r[j+n]*beta+r[j+n-1]) - q* * b[n-1])*beta + r[j+n-2] +// und c3 := b[n-2] * q*. +// {Es ist 0 <= c2 < 2*beta^2, sogar 0 <= c2 < beta^2 falls kein +// Ãœberlauf aufgetreten war. Ferner 0 <= c3 < beta^2. +// Bei Ãœberlauf und r[j+n]*beta+r[j+n-1] - q* * b[n-1] >= beta, +// das heißt c2 >= beta^2, kann man die nächste Abfrage überspringen.} +// Solange c3 > c2, {hier 0 <= c2 < c3 < beta^2} setze +// q* := q* - 1, c2 := c2 + b[n-1]*beta, c3 := c3 - b[n-2]. +// Falls q* > 0: +// Setze r := r - b * q* * beta^j, im einzelnen: +// [r[n+j],...,r[j]] := [r[n+j],...,r[j]] - q* * [b[n-1],...,b[0]]. +// also: u:=0, for i:=0 to n-1 do +// u := u + q* * b[i], +// r[j+i]:=r[j+i]-(u mod beta) (+ beta, falls Carry), +// u:=u div beta (+ 1, falls bei der Subtraktion Carry) +// r[n+j]:=r[n+j]-u. +// {Da stets u = (q* * [b[i-1],...,b[0]] div beta^i) + 1 +// < q* + 1 <= beta, läuft der Ãœbertrag u nicht über.} +// Tritt dabei ein negativer Ãœbertrag auf, so setze q* := q* - 1 +// und [r[n+j],...,r[j]] := [r[n+j],...,r[j]] + [0,b[n-1],...,b[0]]. +// Setze q[j] := q*. +// Normalisiere [q[m-n],..,q[0]] und erhalte den Quotienten q, +// Schiebe [r[n-1],...,r[0]] um s Bits nach rechts, normalisiere und +// erhalte den Rest r. +// Dabei kann q[j] auf dem Platz von r[n+j] liegen. + void cl_UDS_divide (const uintD* a_MSDptr, uintC a_len, const uintD* a_LSDptr, + const uintD* b_MSDptr, uintC b_len, const uintD* b_LSDptr, + uintD* roomptr, // ab roomptr kommen a_len+1 freie Digits + DS* q_, DS* r_) + { // a normalisieren (a_MSDptr erhöhen, a_len erniedrigen): + while ((a_len>0) && (mspref(a_MSDptr,0)==0)) { msshrink(a_MSDptr); a_len--; } + // b normalisieren (b_MSDptr erhöhen, b_len erniedrigen): + loop + { if (b_len==0) { cl_error_division_by_0(); } + if (mspref(b_MSDptr,0)==0) { msshrink(b_MSDptr); b_len--; } + else break; + } + // jetzt m=a_len >=0 und n=b_len >0. + if (a_len < b_len) + // mMSDptr = r_MSDptr; q_->len = 0; q_->LSDptr = r_MSDptr; // q = 0, eine NUDS + r_->MSDptr = r_MSDptr; r_->len = a_len; r_->LSDptr = r_LSDptr; // r = Kopie von a, eine NUDS + return; + } + elif (b_len==1) + // n=1: Single-Precision-Division + { // beta^(m-1) <= a < beta^m ==> beta^(m-2) <= a/b < beta^m + var uintD* q_MSDptr = roomptr; + var uintD* q_LSDptr = q_MSDptr mspop a_len; + var uintD* r_MSDptr = q_LSDptr; + var uintD* r_LSDptr = r_MSDptr mspop 1; + // Speicheraufbau: q_MSDptr/a_len/q_LSDptr r_MSDptr/1/r_LSDptr + // | q | | r | + {var uintD rest = divucopy_loop_msp(mspref(b_MSDptr,0),a_MSDptr,q_MSDptr,a_len); // Division durch b[0] + var uintC r_len; + if (!(rest==0)) + { mspref(r_MSDptr,0) = rest; r_len=1; } // Rest als r ablegen + else + { r_MSDptr = r_LSDptr; r_len=0; } // Rest auf 0 normalisieren + if (mspref(q_MSDptr,0)==0) + { msshrink(q_MSDptr); a_len--; } // q normalisieren + q_->MSDptr = q_MSDptr; q_->len = a_len; q_->LSDptr = q_LSDptr; // q ablegen + r_->MSDptr = r_MSDptr; r_->len = r_len; r_->LSDptr = r_LSDptr; // r ablegen + return; + }} + else + // n>1: Multiple-Precision-Division + { // beta^(m-1) <= a < beta^m, beta^(n-1) <= b < beta^n ==> + // beta^(m-n-1) <= a/b < beta^(m-n+1). + var uintL s; + CL_ALLOCA_STACK; + // s bestimmen: + { var uintD msd = mspref(b_MSDptr,0); // b[n-1] + #if 0 + s = 0; + while ((sintD)msd >= 0) { msd = msd<<1; s++; } + #else // ein wenig effizienter, Abfrage auf s=0 vorwegnehmen + if ((sintD)msd < 0) + { s = 0; goto shift_ok; } + else + { integerlengthD(msd, s = intDsize - ); goto shift; } + #endif + } + // 0 <= s < intDsize. + // Kopiere b und schiebe es dabei um s Bits nach links: + if (!(s==0)) + shift: + { var uintD* new_b_MSDptr; + var uintD* new_b_LSDptr; + num_stack_alloc(b_len,new_b_MSDptr=,new_b_LSDptr=); + shiftleftcopy_loop_lsp(b_LSDptr,new_b_LSDptr,b_len,s); + b_MSDptr = new_b_MSDptr; b_LSDptr = new_b_LSDptr; + } + shift_ok: + // Wieder b = b_MSDptr/b_len/b_LSDptr. + // Kopiere a und schiebe es dabei um s Bits nach links, erhalte r: + {var uintD* r_MSDptr = roomptr; + var uintD* r_LSDptr = roomptr mspop (a_len+1); + // Speicheraufbau: r_MSDptr/ a_len+1 /r_LSDptr + // | r | + // später: q_MSDptr/a_len-b_len+1/r_MSDptr/b_len/r_LSDptr + // | q | r | + if (s==0) + { copy_loop_lsp(a_LSDptr,r_LSDptr,a_len); mspref(r_MSDptr,0) = 0; } + else + { mspref(r_MSDptr,0) = shiftleftcopy_loop_lsp(a_LSDptr,r_LSDptr,a_len,s); } + // Nun r = r_MSDptr/a_len+1/r_LSDptr. + var uintC j = a_len-b_len; // m-n + var uintD* q_MSDptr = r_MSDptr; + var uintC q_len = j+1; // q wird m-n+1 Digits haben + if (cl_recip_suitable(a_len,b_len)) + { // Bestimme Kehrwert c von b. + var uintD* c_MSDptr; + var uintD* c_LSDptr; + num_stack_alloc(j+3,c_MSDptr=,c_LSDptr=); + cl_UDS_recip(b_MSDptr,b_len,c_MSDptr,j+1); + // c hat j+3 Digits, | beta^(m+2)/b - c | < beta. + // Mit a' = floor(a/beta^n) multiplizieren, liefert d': + var uintD* d_MSDptr; + UDS_UDS_mul_UDS(j+1,r_MSDptr mspop (j+1), j+3,c_MSDptr mspop (j+3), + d_MSDptr=,,); + // d' has 2*j+4 digits, d := floor(d'/beta^(j+2)) has j+2 digits. + // | beta^(m+2)/b - c | < beta ==> (since a < beta^(m+1)) + // | beta^(m+2)*a/b - a*c | < beta^(m+2), + // 0 <= a - a'*beta^n < beta^n ==> (since c <= 2*beta^(j+2)) + // 0 <= a*c - a'*c*beta^n < 2*beta^(m+2) ==> + // -beta^(m+2) < beta^(m+2)*a/b - a'*c*beta^n < 3*beta^(m+2) ==> + // -1 < a/b - a'*c*beta^(-j-2) < 3 ==> + // -1 < a/b - d'*beta^(-j-2) < 3, + // -1 < d'*beta^(-j-2) - d <= 0 ==> + // -2 < a/b - d < 3 ==> + // -2 <= q - d < 3 ==> |q-d| <= 2. + var uintD* d_LSDptr = d_MSDptr mspop (j+2); + // Zur Bestimmung des Restes wieder mit b multiplizieren: + var uintD* p_MSDptr; + var uintD* p_LSDptr; + UDS_UDS_mul_UDS(j+2,d_LSDptr, b_len,b_LSDptr, p_MSDptr=,,p_LSDptr=); + // d ist um höchstens 2 zu groß, muß also evtl. zweimal um 1 + // decrementieren, bis das Produkt <= a wird. + if ((mspref(p_MSDptr,0) > 0) || (compare_loop_msp(p_MSDptr mspop 1,r_MSDptr,a_len+1) > 0)) + { dec_loop_lsp(d_LSDptr,j+2); + if (subfrom_loop_lsp(b_LSDptr,p_LSDptr,b_len)) + dec_loop_lsp(p_LSDptr lspop b_len,j+2); + if ((mspref(p_MSDptr,0) > 0) || (compare_loop_msp(p_MSDptr mspop 1,r_MSDptr,a_len+1) > 0)) + { dec_loop_lsp(d_LSDptr,j+2); + if (subfrom_loop_lsp(b_LSDptr,p_LSDptr,b_len)) + dec_loop_lsp(p_LSDptr lspop b_len,j+2); + if ((mspref(p_MSDptr,0) > 0) || (compare_loop_msp(p_MSDptr mspop 1,r_MSDptr,a_len+1) > 0)) + cl_abort(); + } } + // Rest bestimmen: + subfrom_loop_lsp(p_LSDptr,r_LSDptr,a_len+1); + if (test_loop_msp(r_MSDptr,j)) cl_abort(); + r_MSDptr = r_LSDptr lspop b_len; // = r_MSDptr mspop (j+1); + // d ist um höchstens 2 zu klein, muß also evtl. zweimal um 1 + // incrementieren, bis der Rest < b wird. + if ((lspref(r_MSDptr,0) > 0) || (compare_loop_msp(r_MSDptr,b_MSDptr,b_len) >= 0)) + { inc_loop_lsp(d_LSDptr,j+2); + if (subfrom_loop_lsp(b_LSDptr,r_LSDptr,b_len)) + lspref(r_LSDptr,b_len) -= 1; + if ((lspref(r_MSDptr,0) > 0) || (compare_loop_msp(r_MSDptr,b_MSDptr,b_len) >= 0)) + { inc_loop_lsp(d_LSDptr,j+2); + if (subfrom_loop_lsp(b_LSDptr,r_LSDptr,b_len)) + lspref(r_LSDptr,b_len) -= 1; + if ((lspref(r_MSDptr,0) > 0) || (compare_loop_msp(r_MSDptr,b_MSDptr,b_len) >= 0)) + cl_abort(); + } } + // r ist fertig, q := d. + if (mspref(d_MSDptr,0) > 0) cl_abort(); + q_len = j+1; copy_loop_msp(d_MSDptr mspop 1,q_MSDptr,q_len); + } + else + { var uintD* r_ptr = r_LSDptr lspop j; // Pointer oberhalb von r[j] + j = j+1; + var uintD b_msd = mspref(b_MSDptr,0); // b[n-1] + var uintD b_2msd = mspref(b_MSDptr,1); // b[n-2] + #if HAVE_DD + var uintDD b_msdd = highlowDD(b_msd,b_2msd); // b[n-1]*beta+b[n-2] + #endif + // Divisions-Schleife: (wird m-n+1 mal durchlaufen) + // j = Herabzähler, b_MSDptr/b_len/b_LSDptr = [b[n-1],...,b[0]], b_len=n, + // r_MSDptr = Pointer auf r[n+j] = Pointer auf q[j], + // r_ptr = Pointer oberhalb von r[j]. + do { var uintD q_stern; + var uintD c1; + if (mspref(r_MSDptr,0) < b_msd) // r[j+n] < b[n-1] ? + { // Dividiere r[j+n]*beta+r[j+n-1] durch b[n-1], ohne Ãœberlauf: + #if HAVE_DD + divuD(highlowDD(mspref(r_MSDptr,0),mspref(r_MSDptr,1)),b_msd, q_stern=,c1=); + #else + divuD(mspref(r_MSDptr,0),mspref(r_MSDptr,1),b_msd, q_stern=,c1=); + #endif + } + else + { // Ãœberlauf, also r[j+n]*beta+r[j+n-1] >= beta*b[n-1] + q_stern = bitm(intDsize)-1; // q* = beta-1 + // Teste ob r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] >= beta + // <==> r[j+n]*beta+r[j+n-1] + b[n-1] >= beta*b[n-1]+beta + // <==> b[n-1] < floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta) {<= beta !} ist. + // Wenn ja, direkt zur Subtraktionschleife. + // (Andernfalls ist r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] < beta + // <==> floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta) = b[n-1] ). + if ((mspref(r_MSDptr,0) > b_msd) || ((c1 = mspref(r_MSDptr,1)+b_msd) < b_msd)) + // r[j+n] >= b[n-1]+1 oder + // r[j+n] = b[n-1] und Addition r[j+n-1]+b[n-1] gibt Carry ? + { goto subtract; } // ja -> direkt in die Subtraktion + } + // q_stern = q*, + // c1 = (r[j+n]*beta+r[j+n-1]) - q* * b[n-1] (>=0, 0, um b[n-1]*beta+b[n-2] erniedrigen. + // Dies kann wegen b[n-1]*beta+b[n-2] >= beta^2/2 + // höchstens zwei mal auftreten. + if (c3 > c2) + { q_stern = q_stern-1; // q* := q* - 1 + if (c3-c2 > b_msdd) + { q_stern = q_stern-1; } // q* := q* - 1 + } } + #else + // Wie oben, nur mit zweigeteilten c2=[c2hi|c2lo] und c3=[c3hi|c3lo]: + #define c2hi c1 + { var uintD c2lo = mspref(r_MSDptr,2); // c2hi*beta+c2lo = c1*beta+r[j+n-2] + var uintD c3hi; + var uintD c3lo; + muluD(b_2msd,q_stern, c3hi=,c3lo=); // c3hi*beta+c3lo = b[n-2] * q* + if ((c3hi > c2hi) || ((c3hi == c2hi) && (c3lo > c2lo))) + { q_stern = q_stern-1; // q* := q* - 1 + c3hi -= c2hi; if (c3lo < c2lo) { c3hi--; }; c3lo -= c2lo; // c3 := c3-c2 + if ((c3hi > b_msd) || ((c3hi == b_msd) && (c3lo > b_2msd))) + { q_stern = q_stern-1; } // q* := q* - 1 + } } + #undef c2hi + #endif + if (!(q_stern==0)) + subtract: + { // Subtraktionsschleife: r := r - b * q* * beta^j + var uintD carry = mulusub_loop_lsp(q_stern,b_LSDptr,r_ptr,b_len); + // Noch r_ptr[-b_len-1] -= carry, d.h. r_MSDptr[0] -= carry + // durchführen und danach r_MSDptr[0] vergessen: + if (carry > mspref(r_MSDptr,0)) + // Subtraktion ergab Ãœbertrag + { q_stern = q_stern-1; // q* := q* - 1 + addto_loop_lsp(b_LSDptr,r_ptr,b_len); // Additionsschleife + // r[n+j] samt Carry kann vergessen werden... + } } + // Berechnung von q* ist fertig. + msprefnext(r_MSDptr) = q_stern; // als q[j] ablegen + r_ptr = r_ptr mspop 1; + } + until (--j == 0); + } + // Nun ist q = [q[m-n],..,q[0]] = q_MSDptr/q_len/r_MSDptr + // und r = [r[n-1],...,r[0]] = r_MSDptr/b_len/r_LSDptr. + // q normalisieren und ablegen: + if (mspref(q_MSDptr,0)==0) + { msshrink(q_MSDptr); q_len--; } + q_->MSDptr = q_MSDptr; q_->len = q_len; q_->LSDptr = r_MSDptr; + // Schiebe [r[n-1],...,r[0]] um s Bits nach rechts: + if (!(s==0)) + { shiftright_loop_msp(r_MSDptr,b_len,s); } + // r normalisieren und ablegen: + while ((b_len>0) && (mspref(r_MSDptr,0)==0)) + { msshrink(r_MSDptr); b_len--; } + r_->MSDptr = r_MSDptr; r_->len = b_len; r_->LSDptr = r_LSDptr; + return; + }} + } +// Bit complexity (N = a_len): O(M(N)). + diff --git a/src/base/digitseq/cl_DS_endian.h b/src/base/digitseq/cl_DS_endian.h new file mode 100644 index 0000000..0951ef2 --- /dev/null +++ b/src/base/digitseq/cl_DS_endian.h @@ -0,0 +1,21 @@ +// Digit sequence endianness + +#ifndef _CL_DS_ENDIAN_H +#define _CL_DS_ENDIAN_H + +#include "cl_gmpconfig.h" + +// Set this to 1 for big-endian digit ordering in memory, +// set this to 0 for little-endian digit ordering in memory. +// We now support both. +#ifdef CL_USE_GMP + // Use of gmp requires CL_DS_BIG_ENDIAN_P = 0. + #define CL_DS_BIG_ENDIAN_P 0 +#else + // In general, the digit ordering has nearly no effect on speed. + // We have used the big-endian ordering for a long time, so let's use + // the little-endian ordering now for at least the same time :-) + #define CL_DS_BIG_ENDIAN_P 0 +#endif + +#endif /* _CL_DS_ENDIAN_H */ diff --git a/src/base/digitseq/cl_DS_mul.cc b/src/base/digitseq/cl_DS_mul.cc new file mode 100644 index 0000000..285c642 --- /dev/null +++ b/src/base/digitseq/cl_DS_mul.cc @@ -0,0 +1,473 @@ +// cl_UDS_mul(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_DS.h" + + +// Implementation. + +#include "cl_low.h" +#include "cl_malloc.h" +#include "cl_abort.h" + +// Multiplikations-Doppelschleife: +// Multipliziert zwei UDS und legt das Ergebnis in einer dritten UDS ab. +// cl_UDS_mul(sourceptr1,len1,sourceptr2,len2,destptr); +// multipliziert die UDS sourceptr1[-len1..-1] (len1>0) +// mit der UDS sourceptr2[-len1..-1] (len2>0) +// und legt das Ergebnis in der UDS destptr[-len..-1] (len=len1+len2) ab. +// Unterhalb von destptr werden len Digits Platz benötigt. + void cl_UDS_mul (const uintD* sourceptr1, uintC len1, + const uintD* sourceptr2, uintC len2, + uintD* destptr); +// Spezialfall sourceptr1 == sourceptr2 && len1 == len2. + void cl_UDS_mul_square (const uintD* sourceptr, uintC len, + uintD* destptr); + +// Multiplikation nach Schulmethode: + static inline void mulu_2loop (const uintD* sourceptr1, uintC len1, + const uintD* sourceptr2, uintC len2, + uintD* destptr) + { // Es ist 2 <= len1 <= len2. + // Erster Schleifendurchlauf: + mulu_loop_lsp(lsprefnext(sourceptr1),sourceptr2,destptr,len2); + lsshrink(destptr); + var uintD* destptr2 = destptr lspop len2; + // äußere Schleife läuft über source1 : + dotimespC(len1,len1-1, + { // innere Schleife läuft über source2 : + var uintD carry = + muluadd_loop_lsp(lsprefnext(sourceptr1),sourceptr2,destptr,len2); + lsprefnext(destptr2) = carry; // UDS um das Carry-Digit verlängern + lsshrink(destptr); + }); + } + static inline void mulu_2loop_square (const uintD* sourceptr, uintC len, + uintD* destptr) + { // Es ist 2 <= len. + // Gemischte Produkte: + #if 0 + // 2*( x[1] * x[0..0] * b^1 + // + x[2] * x[1..0] * b^2 + // + ... + // + x[n-1] * x[n-2..0]*b^(n-1)) + { var const uintD* sourceptr1 = sourceptr lspop 1; + var uintD* destptr1 = destptr; + lsprefnext(destptr1) = 0; + var uintD* destptr2 = destptr1; + var uintC count; + for (count = 1; count < len; count++) + { // sourceptr1 = sourceptr lspop count, destptr1 = destptr lspop count, + // destptr2 = destptr lspop (2*count-1). + lsprefnext(destptr2) = 0; + var uintD carry = + muluadd_loop_lsp(lsprefnext(sourceptr1),sourceptr,destptr1,count); + lsprefnext(destptr2) = carry; + destptr1 = destptr1 lspop 1; + } + { var uintD carry = shift1left_loop_lsp(destptr lspop 1,2*len-2); + lspref(destptr2,0) = (carry==0 ? 0 : 1); + } } + #else + // 2*( x[n-1..1] * x[0] * b^1 + // + x[n-1..2] * x[1] * b^3 + // + ... + // + x[n-1..n-1] * x[n-2] * b^(2*n-3)) + { var const uintD* sourceptr1 = sourceptr; + var uintD* destptr2 = destptr; + lsprefnext(destptr2) = 0; + var uintC count = len-1; + { var uintD digit = lsprefnext(sourceptr1); + mulu_loop_lsp(digit,sourceptr1,destptr2,count); + } + var uintD* destptr1 = destptr lspop (len+1); + while (--count > 0) + { destptr2 = destptr2 lspop 2; + var uintD digit = lsprefnext(sourceptr1); + var uintD carry = muluadd_loop_lsp(digit,sourceptr1,destptr2,count); + lsprefnext(destptr1) = carry; + } + { var uintD carry = shift1left_loop_lsp(destptr lspop 1,2*len-2); + lspref(destptr1,0) = (carry==0 ? 0 : 1); + } } + #endif + // Quadrate: + len = 2*len; + do { len -= 2; + var uintD digit = lsprefnext(sourceptr); + #if HAVE_DD + var uintDD prod = muluD(digit,digit); + var uintDD accu = highlowDD(lspref(destptr,1),lspref(destptr,0)); + accu += prod; + lspref(destptr,0) = lowD(accu); lspref(destptr,1) = highD(accu); + destptr = destptr lspop 2; + if (accu < prod) { inc_loop_lsp(destptr,len); } + #else + var uintD hi; + var uintD lo; + muluD(digit,digit, hi=,lo=); + var uintD tmp; + tmp = lspref(destptr,0) + lo; lspref(destptr,0) = tmp; + if (tmp < lo) hi++; + tmp = lspref(destptr,1) + hi; lspref(destptr,1) = tmp; + destptr = destptr lspop 2; + if (tmp < hi) { inc_loop_lsp(destptr,len); } + #endif + } while (len > 0); + } + +// Karatsuba-Multiplikation: O(n^(log 3 / log 2)) + static void mulu_karatsuba (const uintD* sourceptr1, uintC len1, + const uintD* sourceptr2, uintC len2, + uintD* destptr); + static void mulu_karatsuba_square (const uintD* sourceptr, uintC len, + uintD* destptr); +#include "cl_DS_mul_kara.h" + // karatsuba_threshold = Länge, ab der die Karatsuba-Multiplikation bevorzugt + // wird. Der Break-Even-Point bestimmt sich aus Zeitmessungen. + // Als Test dient (progn (time (! 5000)) nil), das viele kleine und einige + // ganz große Multiplikationen durchführt. Miß die Runtime. + // Unter Linux mit einem 80486: Auf einer Sparc 2: + // threshold time in 0.01 sec. + // 5 125 127 + // 6 116 117 + // 7 107 110 + // 8 101 103 + // 9 99 102 + // 10 98 100 + // 11 97 100 + // 12 96 99 + // 13 97 99 + // 14 97 100 + // 15 97 99 + // 16 98 100 + // 17 98 100 + // 18 98 100 + // 19 98 101 + // 20 99 102 + // 25 103 105 + // 30 109 111 + // 40 115 118 + // 50 122 125 + // 70 132 134 + // 100 151 152 + // 150 164 167 + // 250 183 187 + // 500 203 205 + // 1000 203 205 + // (clisp)(cln) + // Das Optimum scheint bei karatsuba_threshold = 12 zu liegen. + // Da das Optimum aber vom Verhältnis + // Zeit für uintD-Multiplikation / Zeit für uintD-Addition + // abhängt und die gemessenen Zeiten auf eine Unterschreitung des Optimums + // empfindlicher reagieren als auf eine Ãœberschreitung des Optimums, + // sind wir vorsichtig und wählen einen Wert etwas über dem Optimum: + const unsigned int cl_karatsuba_threshold = 16; + +#if 0 // Lohnt sich nicht + +// FFT-Multiplikation nach Nussbaumer: O(n log n log log n) +#include "cl_DS_mul_nuss.h" + // nuss_threshold = Länge, ab der die Nussbaumer-Multiplikation bevorzugt + // wird. Der Break-Even-Point bestimmt sich aus Zeitmessungen. + // Multiplikation zweier N-Wort-Zahlen unter Linux mit einem 80486: + // N kara nuss nuss-asm (time in sec.) + // 1000 0.36 1.05 0.70 + // 5000 4.69 10.0 6.71 + // 25000 61.6 62.7 40.2 + // 32500 91.8 62.7 40.3 + // 35000 102.7 124.7 80.4 + // 50000 185 132 85.2 + int cl_nuss_threshold = 1000000; + +// FFT-Multiplikation in Z/pZ: O(n log n log log n) +#include "cl_DS_mul_fftp.h" + // fftp_threshold = Länge, ab der die FFT-Multiplikation mod p bevorzugt + // wird. Der Break-Even-Point bestimmt sich aus Zeitmessungen. + // Multiplikation zweier N-Wort-Zahlen unter Linux mit einem 80486: + // N kara fftp (time in sec.) + // 1000 0.36 1.57 + // 5000 4.66 14.86 + // 25000 61.1 75.0 + // 32500 90.8 75.5 + // 35000 101.6 150.1 + // 50000 183 160 + int cl_fftp_threshold = 1000000; + +// FFT-Multiplikation in Z/pZ: O(n log n log log n) +// für drei verschiedene Primzahlen p1,p2,p3 < 2^32. +#include "cl_DS_mul_fftp3.h" + // fftp3_threshold = Länge, ab der die FFT-Multiplikation mod p_i bevorzugt + // wird. Der Break-Even-Point bestimmt sich aus Zeitmessungen. + // Multiplikation zweier N-Wort-Zahlen unter Linux mit einem 80486: + // N kara fftp3 fftp (time in sec.) + // 1000 0.36 0.59 1.57 + // 5000 4.66 5.44 14.89 + // 10000 13.98 11.91 32.43 + // 25000 61.1 27.4 75.4 + // 32500 90.5 28.1 75.5 + // 35000 101.4 54.8 150.4 + // 50000 183 58.9 161.6 + int cl_fftp3_threshold = 1000000; + +// FFT-Multiplikation in Z/pZ: O(n log n log log n) +// für drei verschiedene Primzahlen p1,p2,p3 < 2^32, +// mit Montgomery-Multiplikation. +#include "cl_DS_mul_fftp3m.h" + // fftp3_threshold = Länge, ab der die FFT-Multiplikation mod p_i bevorzugt + // wird. Der Break-Even-Point bestimmt sich aus Zeitmessungen. + // Multiplikation zweier N-Wort-Zahlen unter + // Linux mit einem 80486, 33 MHz, mit Benutzung der GMP-Low-Level-Funktionen: + // N kara fftm fftp3m fftp3 fftp (time in sec.) + // 1000 0.35 0.49 0.54 0.59 1.58 + // 2500 1.48 0.97 2.34 2.52 6.99 + // 5000 4.43 2.19 5.08 5.48 15.16 + // 10000 13.33 4.68 10.93 11.82 32.94 + // 25000 58.5 12.0 25.3 27.4 77.0 + // 32500 86.0 25.0 26.1 28.0 77.3 + // 35000 96.5 25.0 50.8 54.9 152.8 + // 50000 176 25.2 54.2 58.5 163.4 + // und auf einer SPARC 20 mit 75 MHz, ohne GMP-Low-Level-Funktionen: + // N kara fftm fftp3m fftp3 fftp (time in sec.) + // 1000 0.076 0.096 0.113 0.233 0.415 + // 2500 0.32 0.21 0.48 1.03 1.82 + // 5000 0.97 0.51 1.03 2.22 3.96 + // 10000 2.99 1.03 2.23 4.72 8.59 + // 25000 13.22 2.73 4.99 10.78 19.73 + // 32500 19.3 5.7 5.2 10.9 19.7 + // 35000 21.5 5.9 10.0 21.7 39.4 + // 50000 39.5 6.0 11.3 23.1 42.7 + int cl_fftp3m_threshold = 1000000; + +#endif + +// FFT-Multiplikation in Z/pZ: O(n^1.29) +#include "cl_DS_mul_fftm.h" + // fftm_threshold = Länge, ab der die FFT-Multiplikation mod m bevorzugt + // wird. Der Break-Even-Point bestimmt sich aus Zeitmessungen. + // Multiplikation zweier N-Wort-Zahlen unter + // Linux mit einem 80486: Solaris, Sparc 10/20: + // N kara fftm (time in sec.) kara fftm + // 1000 0.36 0.54 0.08 0.10 + // 5000 4.66 2.48 1.01 0.51 + // 25000 61.1 13.22 13.23 2.73 + // 32500 91.0 27.5 20.0 5.8 + // 35000 102.1 27.5 21.5 5.6 + // 50000 183 27.6 40.7 5.6 + // Multiplikation zweier N-Wort-Zahlen unter + // Linux mit einem 80486: Solaris, Sparc 10/20: + // N kara fftm (time in sec.) kara fftm + // 1000 0.36 0.54 0.08 0.10 + // 1260 0.52 0.50 0.11 0.10 + // 1590 0.79 0.51 0.16 0.10 + // 2000 1.09 1.07 0.23 0.21 + // 2520 1.57 1.08 0.33 0.21 + // 3180 2.32 1.08 0.50 0.21 + // 4000 3.29 2.22 0.70 0.41 + // 5040 4.74 2.44 0.99 0.50 + // N1 N2 kara fftm (time in sec.) kara fftm + // 1250 1250 0.51 0.50 0.11 0.10 + // 1250 1580 0.70 0.50 0.15 0.10 + // 1250 2000 0.89 0.51 0.18 0.10 + // 1250 2250 0.99 0.51 0.21 0.10 + // 1250 2500 1.08 1.03 <--- 0.22 0.21 + // 1250 2800 1.20 1.07 0.26 0.21 + // 1250 3100 1.35 1.07 0.28 0.21 + // Es gibt also noch Werte von (len1,len2) mit 1250 <= len1 <= len2, bei + // denen "kara" schneller ist als "fftm", aber nicht viele und dort auch + // nur um 5%. Darum wählen wir ab hier die FFT-Multiplikation. + const unsigned int cl_fftm_threshold = 1250; // muß stets >= 6 sein (sonst Endlosrekursion!) + // This is the threshold for multiplication of equally sized factors. + // When the lengths differ much, the threshold varies: + // len2 = 3000 len1 >= 800 + // len2 = 3500 len1 >= 700 + // len2 = 4000 len1 >= 580 + // len2 = 4500 len1 >= 430 + // len2 = 5000 len1 >= 370 + // len2 = 5500 len1 >= 320 + // len2 = 6000 len1 >= 500 + // len2 = 7000 len1 >= 370 + // len2 = 8000 len1 >= 330 + // len2 = 9000 len1 >= 420 + // len2 =10000 len1 >= 370 + // len2 =11000 len1 >= 330 + // len2 =12000 len1 >= 330 + // len2 =13000 len1 >= 350 + // Let's choose the following condition: + const unsigned int cl_fftm_threshold1 = 330; + const unsigned int cl_fftm_threshold2 = 2*cl_fftm_threshold; + // len1 > cl_fftm_threshold1 && len2 > cl_fftm_threshold2 + // && len1 >= cl_fftm_threshold1 + cl_fftm_threshold/(len2-cl_fftm_threshold1)*(cl_fftm_threshold-cl_fftm_threshold1). + static inline cl_boolean cl_fftm_suitable (uintL len1, uintL len2) + { if (len1 >= cl_fftm_threshold) + return cl_true; + if (len1 > cl_fftm_threshold1) + if (len2 > cl_fftm_threshold2) + { var uint32 hi; + var uint32 lo; + mulu32(len1-cl_fftm_threshold1,len2-cl_fftm_threshold1, hi=,lo=); + if (hi > 0 || lo >= cl_fftm_threshold*(cl_fftm_threshold-cl_fftm_threshold1)) + return cl_true; + } + return cl_false; + } + +#if 0 // Lohnt sich nicht + +// FFT-Multiplikation über den komplexen Zahlen. +#include "cl_DS_mul_fftc.h" + // Multiplikation zweier N-Wort-Zahlen unter + // Linux mit einem i486 33 MHz + // N kara/fftm fftc fftclong + // 1000 0.35 1.52 0.94 + // 2500 0.98 7.6/8.4 4.7 + // 5000 2.2 18.2 10.2 + // 10000 4.7 34 22 + // Multiplikation zweier N-Wort-Zahlen unter + // Linux mit einem i586 90/100 MHz + // N kara/fftm fftc fftclong + // 1000 0.03 0.20 0.16 + // 2500 0.16 1.6 0.92 + // 5000 0.3 2.6 2.2 + // 10000 0.7 7.1 4.8 + // 25000 1.6 (50MB) 20.7(22MB) + // Multiplikation zweier N-Wort-Zahlen unter + // Solaris, Sparc 20, 75 MHz + // N kara/fftm fftc + // 1000 0.07 0.14 + // 2500 0.21 0.76 + // 5000 0.44 1.75 + // 10000 0.88 4.95 + // 25000 2.3 (15MB) + +// FFT-Multiplikation über den komplexen Zahlen, Symmetrie ausnutzend. +#include "cl_DS_mul_fftcs.h" + // Multiplikation zweier N-Wort-Zahlen unter + // Linux mit einem i486 33 MHz + // N kara/fftm fftcs fftcslong + // 1000 0.34 0.71 0.43 + // 2500 0.98 3.4 2.1 + // 5000 2.2 8.0 4.7 + // 10000 4.7 16.1 10.4 + // Multiplikation zweier N-Wort-Zahlen unter + // Solaris, Sparc 20, 75 MHz + // N kara/fftm fftcs + // 300 0.010 0.012 + // 400 0.018 0.027 + // 500 0.023 0.027 + // 600 0.031 0.027 + // 700 0.031 0.027 + // 800 0.051 0.058 + // 900 0.064 0.059 + // 1000 0.069 0.059 + // 1250 0.088 0.13 + // 1500 0.088 0.13 + // 1750 0.088 0.13 + // 2000 0.19 0.13 + // 2500 0.19 0.29 + // 3000 0.19 0.33 + // 3500 0.20 0.31 + // 4000 0.37 0.70 + // 4500 0.38 0.70 + // 5000 0.43 0.69 + // 6000 0.43 0.69 + // 7000 0.43 1.62 + // 8000 0.88 1.60 + // 9000 0.88 1.6 + // 10000 0.90 1.55 + // 12000 0.89 4.7 + // 14000 0.90 5.2 + // 16000 1.43 5.2 + +#endif + +#if 0 // Keine gute Fehlerabschätzung + +// FFT-Multiplikation über den komplexen Zahlen, mit reellen Zahlen rechnend. +#include "cl_DS_mul_fftr.h" + // Multiplikation zweier N-Wort-Zahlen unter + // Linux mit einem i486 33 MHz + // N kara/fftm fftr fftrlong + // 1000 0.34 0.64 0.40 + // 2500 0.98 3.5 2.0 + // 5000 2.2 7.2/7.7 4.6 + // 10000 4.7 16.6 10.0 + +#endif + +// int cl_mul_algo = 0; + void cl_UDS_mul (const uintD* sourceptr1, uintC len1, + const uintD* sourceptr2, uintC len2, + uintD* destptr) + { // len1<=len2 erzwingen: + if (len1>len2) + {{var const uintD* temp; + temp = sourceptr1; sourceptr1 = sourceptr2; sourceptr2 = temp; + } + {var uintC temp; + temp = len1; len1 = len2; len2 = temp; + }} + if (len1==1) + // nur eine Einfachschleife + { mulu_loop_lsp(lsprefnext(sourceptr1),sourceptr2,destptr,len2); } + else + { +// if (cl_mul_algo > 0) +// mulu_fftcs(sourceptr1,len1,sourceptr2,len2,destptr); +// else +// if (cl_mul_algo > 0) +// mulu_nussbaumer(sourceptr1,len1,sourceptr2,len2,destptr); +// else + if (len1 < cl_karatsuba_threshold) + // Multiplikation nach Schulmethode + mulu_2loop(sourceptr1,len1,sourceptr2,len2,destptr); + else // len1 groß + if (!cl_fftm_suitable(len1,len2)) + // Karatsuba-Multiplikation + // (ausgelagert, um die eigentliche Multiplikationsfunktion nicht + // durch zu viele Registervariablen zu belasten): + mulu_karatsuba(sourceptr1,len1,sourceptr2,len2,destptr); + else + //mulu_fft_modp(sourceptr1,len1,sourceptr2,len2,destptr); + //mulu_nussbaumer(sourceptr1,len1,sourceptr2,len2,destptr); + //mulu_fft_modp3(sourceptr1,len1,sourceptr2,len2,destptr); + mulu_fft_modm(sourceptr1,len1,sourceptr2,len2,destptr); + #ifdef DEBUG_MUL_XXX + { // Check the correctness of an other multiplication algorithm: + CL_ALLOCA_STACK; + var uintD tmpprod_xxx = cl_alloc_array(uintD,len1+len2); + mulu_xxx(sourceptr1,len1,sourceptr2,len2,arrayLSDptr(tmpprod_xxx,len1+len2)); + if (compare_loop_msp(destptr lspop (len1+len2),arrayMSDptr(tmpprod_xxx,len1+len2),len1+len2)) + cl_abort(); + } + #endif + } + } + +// Special support for squaring. +// Squaring takes approximately 69% of the time of a normal multiplication. + #include "cl_DS_mul_kara_sqr.h" // defines mulu_karatsuba_square() + void cl_UDS_mul_square (const uintD* sourceptr, uintC len, + uintD* destptr) + { if (len==1) + { var uintD digit = lspref(sourceptr,0); + #if HAVE_DD + var uintDD prod = muluD(digit,digit); + lspref(destptr,0) = lowD(prod); lspref(destptr,1) = highD(prod); + #else + muluD(digit,digit, lspref(destptr,1)=,lspref(destptr,0)=); + #endif + } + else + { if (len < cl_karatsuba_threshold) + mulu_2loop_square(sourceptr,len,destptr); + else + if (!(len >= cl_fftm_threshold)) + mulu_karatsuba_square(sourceptr,len,destptr); + else + mulu_fft_modm(sourceptr,len,sourceptr,len,destptr); + } + } diff --git a/src/base/digitseq/cl_DS_mul_fftc.h b/src/base/digitseq/cl_DS_mul_fftc.h new file mode 100644 index 0000000..f3528a6 --- /dev/null +++ b/src/base/digitseq/cl_DS_mul_fftc.h @@ -0,0 +1,1106 @@ +// Fast integer multiplication using FFT over the complex numbers. +// [Donald Ervin Knuth: The Art of Computer Programming, Vol. II: +// Seminumerical Algorithms, second edition. Section 4.3.3, p. 290-294.] +// Bruno Haible 6.5.1996, 24.-25.8.1996 + +// FFT in the complex domain has the drawback that it needs careful round-off +// error analysis. But for CPUs with good floating-point performance it might +// nevertheless be better than FFT mod Z/mZ. + +// It is important to have precise round-off error estimates. Although +// (by laws of statistics) in the average the actual round-off error makes up +// only half of the bits provided for round-off protection, we cannot rely +// on this average behaviour, but have to produce correct results. +// +// Knuth's formula (42), p. 294, says: +// If we want to multiply l-bit words using an FFT(2^k), our floating point +// numbers shall have m >= 2(k+l) + k + log_2 k + 3.5 mantissa bits. +// +// Here is a more careful analysis, using absolute error estimates. +// +// 1. We assume floating point numbers with radix 2, with the properties: +// (i) Multiplication with 2^n and 2^-n is exact. +// (ii) Negation x -> -x is exact. +// (iii) Addition: When adding x and y, with |x| <= 2^a, |y| <= 2^a, +// the result |x+y| <= 2^(a+1) has an error <= e*2^(a+1-m). +// (iv) Multiplication: When multiplying x and y, with |x| <= 2^a, +// |y| <= 2^b, the result |x*y| <= 2^(a+b) has an error <= e*2^(a+b-m). +// Here e = 1 for a truncating arithmetic, but e = 1/2 for a rounding +// arithmetic like IEEE single and double floats. +// 2. Let's introduce some notation: err(x) means |x'-x| where x is the +// exact mathematical value and x' is its representation in the machine. +// 3. From 1. we get for real numbers x,y: +// (i) err(2^n*x) = 2^n * err(x), +// (ii) err(-x) = err(x), +// (iii) |x| <= 2^a, |y| <= 2^a, then +// err(x+y) <= err(x) + err(y) + e*2^(a+1-m), +// [or .... ............... + e*2^(a-m) if |x+y| <= 2^a]. +// (iv) |x| <= 2^a, |y| <= 2^b, then +// err(x*y) <= 2^a * err(y) + 2^b * err(x) + e*2^(a+b-m). +// 4. Our complex arithmetic will be based on the formulas: +// (i) 2^n*(x+iy) = (2^n*x)+i(2^n*y) +// (ii) -(x+iy) = (-x)+i(-y) +// (iii) (x+iy)+(u+iv) = (x+u)+i(y+v) +// (iv) (x+iy)*(u+iv) = (x*u-y*v)+i(x*v+y*u) +// The notation err(z) means |z'-z|, as above, with |.| being the usual +// absolute value on complex numbers (_not_ the L^1 norm). +// 5. From 3. and 4. we get for complex numbers x,y: +// (i) err(2^n*x) = 2^n * err(x), +// (ii) err(-x) = err(x), +// (iii) |x| <= 2^a, |y| <= 2^a, then +// err(x+y) <= err(x) + err(y) + e*2^(a+3/2-m), +// (iv) |x| <= 2^a, |y| <= 2^b, then +// err(x*y) <= 2^a * err(y) + 2^b * err(x) + 3*e*2^(a+b+1/2-m). +// 6. We start out with precomputed roots of unity: +// |exp(2 pi i/2^n)| <= 1, +// err(exp(2 pi i/2^n)) <= e*2^(1/2-m), (even err(..)=0 for n=0,1,2), +// and compute exp(2 pi i * j/2^k) according to the binary digits of j. +// This way, each root of unity will be a product of at most k precomputed +// roots. If (j mod 2^(k-2)) has n bits, then exp(2 pi i * j/2^k) will +// be computed using n factors, i.e. n-1 complex multiplications, and by +// 5.iv. we'll have +// err(exp(2 pi i * j/2^k)) <= n*e*2^(1/2-m) + max(n-1,0)*3*e*2^(1/2-m) +// = max(4*n-3,0)*e*2^(1/2-m). +// Hence the maximum roots-of-unity error is (set n=k-2) +// err(w^j) <= (4*k-11)*e*2^(1/2-m), +// and the average roots-of-unity error is (set n=(k-2)/2) +// < 2*(k-2)*e*2^(1/2-m). +// 7. Now we start the FFT. +// Before the first step, x_i are integral, |x_i| < 2^l and err(x_i) = 0. +// After the first butterfly, which replaces (x(i1),x(i2)) by +// (x(i1) + x(i2), x(i1) - x(i2)), we have |x_i| < 2^(l+1) and err(x_i) = 0. +// Then, for each of the remaining k-1 steps, a butterfly replaces +// (x(i1),x(i2)) by (x(i1) + w^exp*x(i2), x(i1) - w^exp*x(i2)). Thus, +// after n steps we have |x_i| < 2^(l+n) and err(x_i) <= E_i where +// E_0 = 0, +// E_1 = 0, +// E_(n+1) = (E_n + 2^(l+n)*(4*k-11)*e*2^(1/2-m) + 3*e*2^(l+n+1/2-m)) +// + E_n + e*2^(l+n+3/2-m) +// = 2*E_n + (4*k-6)*e*2^(l+n+1/2-m) +// hence E_n = (2^n-2)*(4*k-6)*e*2^(l+1/2-m). +// Setting n = k, we have proved that after the FFT ends, we have +// |x_i| < 2^(l+k) and err(x_i) <= (4*k-6)*e*2^(l+k+1/2-m). +// 8. The same error analysis holds for the y_i and their FFT. After we +// multiply z_i := x_i * y_i, we have +// |z_i| < 2^(2*l+2*k) and err(z_i) <= (8*k-9)*e*2^(2*l+2*k+1/2-m). +// 9. Then an inverse FFT on z_i is done, which is the same as an FFT +// followed by a permutation and a division by 2^k. After n steps of +// the FFT, we have |z_i| < 2^(2*l+2*k+n) and err(z_i) <= E_i where +// E_0 = (8*k-9)*e*2^(2*l+2*k+1/2-m), +// E_(n+1) = (E_n + 2^(2*l+2*k+n)*(4*k-11)*e*2^(1/2-m) +// + 3*e*2^(2*l+2*k+n+1/2-m)) +// + E_n + e*2^(2*l+2*k+n+3/2-m) +// = 2*E_n + (4*k-6)*e*2^(2*l+2*k+n+1/2-m) +// hence E_n = 2^n*(8*k-9)*e*2^(2*l+2*k+1/2-m) +// + (2^n-1)*(4*k-6)*e*2^(2*l+2*k+1/2-m). +// So, after the FFT, we have (set n=k) |z_i| < 2^(2*l+3*k) and +// err(z_i) <= (12*k-15)*e*2^(2*l+3*k+1/2-m). +// Permutation doesn't change the estimates. After division by 2^k, we get +// |z_i| < 2^(2*l+2*k) and +// err(z_i) <= (12*k-15)*e*2^(2*l+2*k+1/2-m). +// 10. When converting the z_i back to integers, we know that z_i should be +// real, integral, and |z_i| < 2^(2*l+k). We can only guarantee that we +// can find the integral z_i from the floating-point computation if +// (12*k-15)*e*2^(2*l+2*k+1/2-m) < 1/2. +// 11. Assuming e = 1/2 and m = 53 (typical values for IEEE double arithmetic), +// we get the constraint 2*l < m - 1/2 - 2*k - log_2(12*k-15). +// k = 2 l <= 22 +// k = 3 l <= 21 +// k = 4 l <= 19 +// k = 5 l <= 18 +// k = 6 l <= 17 +// k = 7 l <= 16 +// k = 8 l <= 15 +// k = 9 l <= 13 +// k = 10 l <= 12 +// k = 11 l <= 11 +// k = 12 l <= 10 +// k = 13 l <= 9 +// k = 14 l <= 8 +// k = 15 l <= 7 +// k = 16 l <= 6 +// k = 17 l <= 5 +// k = 18 l <= 4 +// k = 19 l <= 3 +// k = 20 l <= 2 +// Assuming e = 1/2 and m = 64 ("long double" arithmetic on i387/i486/i586), +// we get the constraint 2*l < m - 1/2 - 2*k - log_2(12*k-15). +// k = 2 l <= 28 +// k = 3 l <= 26 +// k = 4 l <= 25 +// k = 5 l <= 24 +// k = 6 l <= 22 +// k = 7 l <= 21 +// k = 8 l <= 20 +// k = 9 l <= 19 +// k = 10 l <= 18 +// k = 11 l <= 17 +// k = 12 l <= 16 +// k = 13 l <= 15 +// k = 14 l <= 14 +// k = 15 l <= 13 +// k = 16 l <= 12 +// k = 17 l <= 10 +// k = 18 l <= 9 +// k = 19 l <= 8 +// k = 20 l <= 7 +// k = 21 l <= 6 +// k = 22 l <= 5 +// k = 23 l <= 4 +// k = 24 l <= 3 +// k = 25 l <= 2 + + +#if !(intDsize==32) +#error "complex fft implemented only for intDsize==32" +#endif + + +#include "cl_floatparam.h" +#include "cl_io.h" +#include "cl_abort.h" + +#if defined(HAVE_LONGDOUBLE) && (long_double_mant_bits > double_mant_bits) && (defined(__i386__) || defined(__m68k__) || (defined(__sparc__) && 0)) +// Only these CPUs have fast "long double"s in hardware. +// On SPARC, "long double"s are emulated in software and don't work. +typedef long double fftc_real; +#define fftc_real_mant_bits long_double_mant_bits +#define fftc_real_rounds long_double_rounds +#else +typedef double fftc_real; +#define fftc_real_mant_bits double_mant_bits +#define fftc_real_rounds double_rounds +#endif + +typedef struct fftc_complex + { + fftc_real re; + fftc_real im; + } + fftc_complex; + +static const fftc_complex fftc_roots_of_1 [32+1] = + // roots_of_1[n] is a (2^n)th root of unity in C. + // Also roots_of_1[n-1] = roots_of_1[n]^2. + // For simplicity we choose roots_of_1[n] = exp(2 pi i/2^n). + { + #if (fftc_real_mant_bits == double_mant_bits) + // These values have 64 bit precision. + { 1.0, 0.0 }, + { -1.0, 0.0 }, + { 0.0, 1.0 }, + { 0.7071067811865475244, 0.7071067811865475244 }, + { 0.9238795325112867561, 0.38268343236508977172 }, + { 0.9807852804032304491, 0.19509032201612826784 }, + { 0.99518472667219688623, 0.098017140329560601996 }, + { 0.9987954562051723927, 0.049067674327418014254 }, + { 0.9996988186962042201, 0.024541228522912288032 }, + { 0.99992470183914454094, 0.0122715382857199260795 }, + { 0.99998117528260114264, 0.0061358846491544753597 }, + { 0.9999952938095761715, 0.00306795676296597627 }, + { 0.99999882345170190993, 0.0015339801862847656123 }, + { 0.99999970586288221914, 7.6699031874270452695e-4 }, + { 0.99999992646571785114, 3.8349518757139558907e-4 }, + { 0.9999999816164292938, 1.9174759731070330744e-4 }, + { 0.9999999954041073129, 9.5873799095977345874e-5 }, + { 0.99999999885102682754, 4.793689960306688455e-5 }, + { 0.99999999971275670683, 2.3968449808418218729e-5 }, + { 0.9999999999281891767, 1.1984224905069706422e-5 }, + { 0.99999999998204729416, 5.9921124526424278428e-6 }, + { 0.99999999999551182357, 2.9960562263346607504e-6 }, + { 0.99999999999887795586, 1.4980281131690112288e-6 }, + { 0.999999999999719489, 7.4901405658471572114e-7 }, + { 0.99999999999992987223, 3.7450702829238412391e-7 }, + { 0.99999999999998246807, 1.8725351414619534487e-7 }, + { 0.999999999999995617, 9.36267570730980828e-8 }, + { 0.99999999999999890425, 4.6813378536549092695e-8 }, + { 0.9999999999999997261, 2.340668926827455276e-8 }, + { 0.99999999999999993153, 1.1703344634137277181e-8 }, + { 0.99999999999999998287, 5.8516723170686386908e-9 }, + { 0.9999999999999999957, 2.925836158534319358e-9 }, + { 0.9999999999999999989, 1.4629180792671596806e-9 } + #else (fftc_real_mant_bits > double_mant_bits) + // These values have 128 bit precision. + { 1.0L, 0.0L }, + { -1.0L, 0.0L }, + { 0.0L, 1.0L }, + { 0.707106781186547524400844362104849039284L, 0.707106781186547524400844362104849039284L }, + { 0.923879532511286756128183189396788286823L, 0.38268343236508977172845998403039886676L }, + { 0.980785280403230449126182236134239036975L, 0.195090322016128267848284868477022240928L }, + { 0.995184726672196886244836953109479921574L, 0.098017140329560601994195563888641845861L }, + { 0.998795456205172392714771604759100694444L, 0.0490676743274180142549549769426826583147L }, + { 0.99969881869620422011576564966617219685L, 0.0245412285229122880317345294592829250654L }, + { 0.99992470183914454092164649119638322435L, 0.01227153828571992607940826195100321214037L }, + { 0.999981175282601142656990437728567716173L, 0.00613588464915447535964023459037258091705L }, + { 0.999995293809576171511580125700119899554L, 0.00306795676296597627014536549091984251894L }, + { 0.99999882345170190992902571017152601905L, 0.001533980186284765612303697150264079079954L }, + { 0.999999705862882219160228217738765677117L, 7.66990318742704526938568357948576643142e-4L }, + { 0.99999992646571785114473148070738785695L, 3.83495187571395589072461681181381263396e-4L }, + { 0.999999981616429293808346915402909714504L, 1.91747597310703307439909561989000933469e-4L }, + { 0.99999999540410731289097193313960614896L, 9.58737990959773458705172109764763511872e-5L }, + { 0.9999999988510268275626733077945541084L, 4.79368996030668845490039904946588727468e-5L }, + { 0.99999999971275670684941397221864177609L, 2.39684498084182187291865771650218200947e-5L }, + { 0.999999999928189176709775095883850490262L, 1.198422490506970642152156159698898480473e-5L }, + { 0.99999999998204729417728262414778410738L, 5.99211245264242784287971180889086172999e-6L }, + { 0.99999999999551182354431058417299732444L, 2.99605622633466075045481280835705981183e-6L }, + { 0.999999999998877955886077016551752536504L, 1.49802811316901122885427884615536112069e-6L }, + { 0.999999999999719488971519214794719584451L, 7.49014056584715721130498566730655637157e-7L }, + { 0.99999999999992987224287980123972873676L, 3.74507028292384123903169179084633177398e-7L }, + { 0.99999999999998246806071995015624773673L, 1.8725351414619534486882457659356361712e-7L }, + { 0.999999999999995617015179987529456656217L, 9.3626757073098082799067286680885620193e-8L }, + { 0.999999999999998904253794996881763834182L, 4.68133785365490926951155181385400969594e-8L }, + { 0.99999999999999972606344874922040343793L, 2.34066892682745527595054934190348440379e-8L }, + { 0.999999999999999931515862187305098514444L, 1.170334463413727718124621350323810379807e-8L }, + { 0.999999999999999982878965546826274482047L, 5.8516723170686386908097901008341396944e-9L }, + { 0.999999999999999995719741386706568611352L, 2.92583615853431935792823046906895590202e-9L }, + { 0.999999999999999998929935346676642152265L, 1.46291807926715968052953216186596371037e-9L } + #endif + }; + +// Define this for (cheap) consistency checks. +//#define DEBUG_FFTC + +// Define the algorithm of the backward FFT: +// Either FORWARD (a normal FFT followed by a permutation) +// or RECIPROOT (an FFT with reciprocal root of unity) +// or CLEVER (an FFT with reciprocal root of unity but clever computation +// of the reciprocals). +// Drawback of FORWARD: the permutation pass. +// Drawback of RECIPROOT: need all the powers of the root, not only half of them. +#define FORWARD 42 +#define RECIPROOT 43 +#define CLEVER 44 +#define FFTC_BACKWARD CLEVER + +static fftc_real fftc_pow2_table[64] = // table of powers of 2 + { + 1.0, + 2.0, + 4.0, + 8.0, + 16.0, + 32.0, + 64.0, + 128.0, + 256.0, + 512.0, + 1024.0, + 2048.0, + 4096.0, + 8192.0, + 16384.0, + 32768.0, + 65536.0, + 131072.0, + 262144.0, + 524288.0, + 1048576.0, + 2097152.0, + 4194304.0, + 8388608.0, + 16777216.0, + 33554432.0, + 67108864.0, + 134217728.0, + 268435456.0, + 536870912.0, + 1073741824.0, + 2147483648.0, + 4294967296.0, + 8589934592.0, + 17179869184.0, + 34359738368.0, + 68719476736.0, + 137438953472.0, + 274877906944.0, + 549755813888.0, + 1099511627776.0, + 2199023255552.0, + 4398046511104.0, + 8796093022208.0, + 17592186044416.0, + 35184372088832.0, + 70368744177664.0, + 140737488355328.0, + 281474976710656.0, + 562949953421312.0, + 1125899906842624.0, + 2251799813685248.0, + 4503599627370496.0, + 9007199254740992.0, + 18014398509481984.0, + 36028797018963968.0, + 72057594037927936.0, + 144115188075855872.0, + 288230376151711744.0, + 576460752303423488.0, + 1152921504606846976.0, + 2305843009213693952.0, + 4611686018427387904.0, + 9223372036854775808.0 + }; + +// For a constant expression n (0 <= n < 128), returns 2^n of type fftc_real. +#define fftc_pow2(n) \ + (((n) & 64 ? (fftc_real)18446744073709551616.0 : (fftc_real)1.0) \ + * ((n) & 32 ? (fftc_real)4294967296.0 : (fftc_real)1.0) \ + * ((n) & 16 ? (fftc_real)65536.0 : (fftc_real)1.0) \ + * ((n) & 8 ? (fftc_real)256.0 : (fftc_real)1.0) \ + * ((n) & 4 ? (fftc_real)16.0 : (fftc_real)1.0) \ + * ((n) & 2 ? (fftc_real)4.0 : (fftc_real)1.0) \ + * ((n) & 1 ? (fftc_real)2.0 : (fftc_real)1.0) \ + ) + +// r := a + b +static inline void add (const fftc_complex& a, const fftc_complex& b, fftc_complex& r) +{ + r.re = a.re + b.re; + r.im = a.im + b.im; +} + +// r := a - b +static inline void sub (const fftc_complex& a, const fftc_complex& b, fftc_complex& r) +{ + r.re = a.re - b.re; + r.im = a.im - b.im; +} + +// r := a * b +static inline void mul (fftc_real a, const fftc_complex& b, fftc_complex& r) +{ + r.re = a * b.re; + r.im = a * b.im; +} + +// r := a * b +static inline void mul (const fftc_complex& a, const fftc_complex& b, fftc_complex& r) +{ + var fftc_real r_re = a.re * b.re - a.im * b.im; + var fftc_real r_im = a.re * b.im + a.im * b.re; + r.re = r_re; + r.im = r_im; +} + +#ifndef _BIT_REVERSE +#define _BIT_REVERSE +// Reverse an n-bit number x. n>0. +static uintL bit_reverse (uintL n, uintL x) +{ + var uintL y = 0; + do { + y <<= 1; + y |= (x & 1); + x >>= 1; + } while (!(--n == 0)); + return y; +} +#endif + +// Compute a complex convolution using FFT: z[0..N-1] := x[0..N-1] * y[0..N-1]. +static void fftc_convolution (const uintL n, const uintL N, // N = 2^n + fftc_complex * x, // N numbers + fftc_complex * y, // N numbers + fftc_complex * z // N numbers result + ) +{ + CL_ALLOCA_STACK; + #if (FFTC_BACKWARD == RECIPROOT) || defined(DEBUG_FFTC) + var fftc_complex* const w = cl_alloc_array(fftc_complex,N); + #else + var fftc_complex* const w = cl_alloc_array(fftc_complex,(N>>1)+1); + #endif + var uintL i; + // Initialize w[i] to w^i, w a primitive N-th root of unity. + w[0] = fftc_roots_of_1[0]; + #if (FFTC_BACKWARD == RECIPROOT) || defined(DEBUG_FFTC) + { + var int j; + for (j = n-1; j>=0; j--) { + var fftc_complex r_j = fftc_roots_of_1[n-j]; + w[1<=0; j--) { + var fftc_complex r_j = fftc_roots_of_1[n-j]; + w[1<>1; i += (2<=3 ? 4*n-11 : 0); + epsilon = epsilon / fftc_pow2(fftc_real_mant_bits); + if (fftc_real_rounds == rounds_to_nearest) + epsilon = 0.5*epsilon; + epsilon = 1.414*epsilon; + // epsilon = (4*k-11)*e*2^(1/2-m). + var fftc_real part; + var fftc_complex& w_N = w[N>>1]; + part = w_N.re - (fftc_real)(-1.0); + if (part > epsilon || part < -epsilon) + cl_abort(); + part = w_N.im; + if (part > epsilon || part < -epsilon) + cl_abort(); + } + { + var fftc_complex w_N; + mul(w[N-1],fftc_roots_of_1[n], w_N); + // Since there was one more multiplication, + // we have to replace n by (n+1) in the epsilon above. + var fftc_real epsilon; + epsilon = (fftc_real)(4*n-7); + epsilon = epsilon / fftc_pow2(fftc_real_mant_bits); + if (fftc_real_rounds == rounds_to_nearest) + epsilon = 0.5*epsilon; + epsilon = 1.414*epsilon; + // epsilon = (4*k-7)*e*2^(1/2-m). + var fftc_real part; + part = w_N.re - (fftc_real)1.0; + if (part > epsilon || part < -epsilon) + cl_abort(); + part = w_N.im; + if (part > epsilon || part < -epsilon) + cl_abort(); + } + #endif + var bool squaring = (x == y); + // Do an FFT of length N on x. + { + var sintL l; + /* l = n-1 */ { + var const uintL tmax = N>>1; // tmax = 2^(n-1) + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = t; + var uintL i2 = i1 + tmax; + // Butterfly: replace (x(i1),x(i2)) by + // (x(i1) + x(i2), x(i1) - x(i2)). + var fftc_complex tmp; + tmp = x[i2]; + sub(x[i1],tmp, x[i2]); + add(x[i1],tmp, x[i1]); + } + } + for (l = n-2; l>=0; l--) { + var const uintL smax = (uintL)1 << (n-1-l); + var const uintL tmax = (uintL)1 << l; + for (var uintL s = 0; s < smax; s++) { + var uintL exp = bit_reverse(n-1-l,s) << l; + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = (s << (l+1)) + t; + var uintL i2 = i1 + tmax; + // Butterfly: replace (x(i1),x(i2)) by + // (x(i1) + w^exp*x(i2), x(i1) - w^exp*x(i2)). + var fftc_complex tmp; + mul(x[i2],w[exp], tmp); + sub(x[i1],tmp, x[i2]); + add(x[i1],tmp, x[i1]); + } + } + } + } + // Do an FFT of length N on y. + if (!squaring) { + var sintL l; + /* l = n-1 */ { + var uintL const tmax = N>>1; // tmax = 2^(n-1) + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = t; + var uintL i2 = i1 + tmax; + // Butterfly: replace (y(i1),y(i2)) by + // (y(i1) + y(i2), y(i1) - y(i2)). + var fftc_complex tmp; + tmp = y[i2]; + sub(y[i1],tmp, y[i2]); + add(y[i1],tmp, y[i1]); + } + } + for (l = n-2; l>=0; l--) { + var const uintL smax = (uintL)1 << (n-1-l); + var const uintL tmax = (uintL)1 << l; + for (var uintL s = 0; s < smax; s++) { + var uintL exp = bit_reverse(n-1-l,s) << l; + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = (s << (l+1)) + t; + var uintL i2 = i1 + tmax; + // Butterfly: replace (y(i1),y(i2)) by + // (y(i1) + w^exp*y(i2), y(i1) - w^exp*y(i2)). + var fftc_complex tmp; + mul(y[i2],w[exp], tmp); + sub(y[i1],tmp, y[i2]); + add(y[i1],tmp, y[i1]); + } + } + } + } + // Multiply the transformed vectors into z. + for (i = 0; i < N; i++) + mul(x[i],y[i], z[i]); + // Undo an FFT of length N on z. + { + var uintL l; + for (l = 0; l < n-1; l++) { + var const uintL smax = (uintL)1 << (n-1-l); + var const uintL tmax = (uintL)1 << l; + #if FFTC_BACKWARD != CLEVER + for (var uintL s = 0; s < smax; s++) { + var uintL exp = bit_reverse(n-1-l,s) << l; + #if FFTC_BACKWARD == RECIPROOT + if (exp > 0) + exp = N - exp; // negate exp (use w^-1 instead of w) + #endif + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = (s << (l+1)) + t; + var uintL i2 = i1 + tmax; + // Inverse Butterfly: replace (z(i1),z(i2)) by + // ((z(i1)+z(i2))/2, (z(i1)-z(i2))/(2*w^exp)). + // Do the division by 2 later. + var fftc_complex sum; + var fftc_complex diff; + add(z[i1],z[i2], sum); + sub(z[i1],z[i2], diff); + z[i1] = sum; + mul(diff,w[exp], z[i2]); + } + } + #else // FFTC_BACKWARD == CLEVER: clever handling of negative exponents + /* s = 0, exp = 0 */ { + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = t; + var uintL i2 = i1 + tmax; + // Inverse Butterfly: replace (z(i1),z(i2)) by + // ((z(i1)+z(i2))/2, (z(i1)-z(i2))/(2*w^exp)), + // with exp <-- 0. + // Do the division by 2 later. + var fftc_complex sum; + var fftc_complex diff; + add(z[i1],z[i2], sum); + sub(z[i1],z[i2], diff); + z[i1] = sum; + z[i2] = diff; + } + } + for (var uintL s = 1; s < smax; s++) { + var uintL exp = bit_reverse(n-1-l,s) << l; + exp = (N>>1) - exp; // negate exp (use w^-1 instead of w) + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = (s << (l+1)) + t; + var uintL i2 = i1 + tmax; + // Inverse Butterfly: replace (z(i1),z(i2)) by + // ((z(i1)+z(i2))/2, (z(i1)-z(i2))/(2*w^exp)), + // with exp <-- (N/2 - exp). + // Do the division by 2 later. + var fftc_complex sum; + var fftc_complex diff; + add(z[i1],z[i2], sum); + sub(z[i2],z[i1], diff); // note that w^(N/2) = -1 + z[i1] = sum; + mul(diff,w[exp], z[i2]); + } + } + #endif + } + /* l = n-1 */ { + var const fftc_real pow2 = (fftc_real)1 / (fftc_real)N; + var const uintL tmax = N>>1; // tmax = 2^(n-1) + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = t; + var uintL i2 = i1 + tmax; + // Inverse Butterfly: replace (z(i1),z(i2)) by + // ((z(i1)+z(i2))/2, (z(i1)-z(i2))/2). + // Do all the divisions by 2 now. + var fftc_complex sum; + var fftc_complex diff; + add(z[i1],z[i2], sum); + sub(z[i1],z[i2], diff); + mul(pow2,sum, z[i1]); + mul(pow2,diff, z[i2]); + } + } + } + #if FFTC_BACKWARD == FORWARD + // Swap z[i] and z[N-i] for 0 < i < N/2. + for (i = (N>>1)-1; i > 0; i--) { + var fftc_complex tmp = z[i]; + z[i] = z[N-i]; + z[N-i] = tmp; + } + #endif +} + +// For a given k >= 2, the maximum l is determined by +// 2*l < m - 1/2 - 2*k - log_2(12*k-15) - (1 if e=1.0, 0 if e=0.5). +// This is a decreasing function of k. +#define max_l(k) \ + (int)((fftc_real_mant_bits \ + - 2*(k) \ + - ((k)<=2 ? 4 : (k)<=3 ? 5 : (k)<=5 ? 6 : (k)<=8 ? 7 : (k)<=16 ? 8 : (k)<=31 ? 9 : 10) \ + - (fftc_real_rounds == rounds_to_nearest ? 0 : 1)) \ + / 2) +static int max_l_table[32+1] = + { 0, 0, max_l(2), max_l(3), max_l(4), max_l(5), max_l(6), + max_l(7), max_l(8), max_l(9), max_l(10), max_l(11), max_l(12), max_l(13), + max_l(14), max_l(15), max_l(16), max_l(17), max_l(18), max_l(19), max_l(20), + max_l(21), max_l(22), max_l(23), max_l(24), max_l(25), max_l(26), max_l(27), + max_l(28), max_l(29), max_l(30), max_l(31), max_l(32) + }; + +// Split len uintD's below sourceptr into chunks of l bits, thus filling +// N complex numbers at x. +static void fill_factor (uintL N, fftc_complex* x, uintL l, + const uintD* sourceptr, uintL len) +{ + var uintL i; + if (max_l(2) > intDsize && l > intDsize) { + // l > intDsize + if (max_l(2) > 64 && l > 64) { + fprint(cl_stderr, "FFT problem: l > 64 not supported by pow2_table\n"); + cl_abort(); + } + var fftc_real carry = 0; + var sintL carrybits = 0; // number of bits in carry (>=0, 0) { + var uintD digit = lsprefnext(sourceptr); + if (carrybits+intDsize >= l) { + x[i].re = carry + (fftc_real)(digit & bitm(l-carrybits)) * fftc_pow2_table[carrybits]; + x[i].im = (fftc_real)0; + i++; + carry = (l-carrybits == intDsize ? (fftc_real)0 : (fftc_real)(digit >> (l-carrybits))); + carrybits = carrybits+intDsize-l; + } else { + carry = carry + (fftc_real)digit * fftc_pow2_table[carrybits]; + carrybits = carrybits+intDsize; + } + len--; + } + if (carrybits > 0) { + x[i].re = carry; + x[i].im = (fftc_real)0; + i++; + } + if (i > N) + cl_abort(); + } else if (max_l(2) >= intDsize && l == intDsize) { + // l = intDsize + if (len > N) + cl_abort(); + for (i = 0; i < len; i++) { + var uintD digit = lsprefnext(sourceptr); + x[i].re = (fftc_real)digit; + x[i].im = (fftc_real)0; + } + } else { + // l < intDsize + var const uintD l_mask = bit(l)-1; + var uintD carry = 0; + var sintL carrybits = 0; // number of bits in carry (>=0, = l) { + x[i].re = (fftc_real)(carry & l_mask); + x[i].im = (fftc_real)0; + carry >>= l; + carrybits -= l; + } else { + if (len == 0) + break; + len--; + var uintD digit = lsprefnext(sourceptr); + x[i].re = (fftc_real)((carry | (digit << carrybits)) & l_mask); + x[i].im = (fftc_real)0; + carry = digit >> (l-carrybits); + carrybits = intDsize - (l-carrybits); + } + } + while (carrybits > 0) { + if (!(i < N)) + cl_abort(); + x[i].re = (fftc_real)(carry & l_mask); + x[i].im = (fftc_real)0; + carry >>= l; + carrybits -= l; + i++; + } + if (len > 0) + cl_abort(); + } + for ( ; i < N; i++) { + x[i].re = (fftc_real)0; + x[i].im = (fftc_real)0; + } +} + +// Given a not too large floating point number, round it to the nearest integer. +static inline fftc_real fftc_fround (fftc_real x) +{ + return + #if (fftc_real_rounds == rounds_to_nearest) + (x + (fftc_pow2(fftc_real_mant_bits-1)+fftc_pow2(fftc_real_mant_bits-2))) + - (fftc_pow2(fftc_real_mant_bits-1)+fftc_pow2(fftc_real_mant_bits-2)); + #elif (fftc_real_rounds == rounds_to_infinity) + (fftc_pow2(fftc_real_mant_bits-1)+fftc_pow2(fftc_real_mant_bits-2)) + - ((fftc_pow2(fftc_real_mant_bits-1)+fftc_pow2(fftc_real_mant_bits-2)) + - (x + (fftc_real)0.5)); + #else // rounds_to_zero, rounds_to_minus_infinity + ((x + (fftc_real)0.5) + + (fftc_pow2(fftc_real_mant_bits-1)+fftc_pow2(fftc_real_mant_bits-2))) + - (fftc_pow2(fftc_real_mant_bits-1)+fftc_pow2(fftc_real_mant_bits-2)); + #endif +} + +// Given a not too large floating point number, round it down. +static inline fftc_real fftc_ffloor (fftc_real x) +{ + #if (fftc_real_rounds == rounds_to_nearest) + var fftc_real y = + (x + (fftc_pow2(fftc_real_mant_bits-1)+fftc_pow2(fftc_real_mant_bits-2))) + - (fftc_pow2(fftc_real_mant_bits-1)+fftc_pow2(fftc_real_mant_bits-2)); + if (y <= x) + return y; + else + return y - (fftc_real)1.0; + #elif (fftc_real_rounds == rounds_to_infinity) + return + (fftc_pow2(fftc_real_mant_bits-1)+fftc_pow2(fftc_real_mant_bits-2)) + - ((fftc_pow2(fftc_real_mant_bits-1)+fftc_pow2(fftc_real_mant_bits-2)) + - x); + #else // rounds_to_zero, rounds_to_minus_infinity + return + (x + (fftc_pow2(fftc_real_mant_bits-1)+fftc_pow2(fftc_real_mant_bits-2))) + - (fftc_pow2(fftc_real_mant_bits-1)+fftc_pow2(fftc_real_mant_bits-2)); + #endif +} + +// Combine the N complex numbers at z into uintD's below destptr. +// The z[i] are known to be approximately integers >= 0, < N*2^(2*l). +// Assumes room for floor(N*l/intDsize)+(1+ceiling((n+2*l)/intDsize)) uintD's +// below destptr. Fills len digits and returns (destptr lspop len). +static uintD* unfill_product (uintL n, uintL N, // N = 2^n + const fftc_complex * z, uintL l, + uintD* destptr) +{ + var uintL i; + if (n + 2*l <= intDsize) { + // 2-digit carry is sufficient, l < intDsize + var uintD carry0 = 0; + var uintD carry1 = 0; + var uintL shift = 0; // shift next digit before adding it to the carry, >=0, 0) { + carry1 += digit >> (intDsize-shift); + digit = digit << shift; + } + if ((carry0 += digit) < digit) + carry1 += 1; + shift += l; + if (shift >= intDsize) { + lsprefnext(destptr) = carry0; + carry0 = carry1; + carry1 = 0; + shift -= intDsize; + } + } + lsprefnext(destptr) = carry0; + lsprefnext(destptr) = carry1; + } else if (n + 2*l <= 2*intDsize) { + // 3-digit carry is sufficient, l < intDsize + #if HAVE_DD + var uintDD carry0 = 0; + var uintD carry1 = 0; + var uintL shift = 0; // shift next digit before adding it to the carry, >=0, 0) { + carry1 += (uintD)(digit >> (2*intDsize-shift)); + digit = digit << shift; + } + if ((carry0 += digit) < digit) + carry1 += 1; + shift += l; + if (shift >= intDsize) { + lsprefnext(destptr) = lowD(carry0); + carry0 = highlowDD(carry1,highD(carry0)); + carry1 = 0; + shift -= intDsize; + } + } + lsprefnext(destptr) = lowD(carry0); + lsprefnext(destptr) = highD(carry0); + lsprefnext(destptr) = carry1; + #else + var uintD carry0 = 0; + var uintD carry1 = 0; + var uintD carry2 = 0; + var uintL shift = 0; // shift next digit before adding it to the carry, >=0, 0) { + carry2 += digit1 >> (intDsize-shift); + digit1 = (digit1 << shift) | (digit0 >> (intDsize-shift)); + digit0 = digit0 << shift; + } + if ((carry0 += digit0) < digit0) + if ((carry1 += 1) == 0) + carry2 += 1; + if ((carry1 += digit1) < digit1) + carry2 += 1; + shift += l; + if (shift >= intDsize) { + lsprefnext(destptr) = carry0; + carry0 = carry1; + carry1 = carry2; + carry2 = 0; + shift -= intDsize; + } + } + lsprefnext(destptr) = carry0; + lsprefnext(destptr) = carry1; + lsprefnext(destptr) = carry2; + #endif + } else { + // 1-digit+1-float carry is sufficient + var uintD carry0 = 0; + var fftc_real carry1 = 0; + var uintL shift = 0; // shift next digit before adding it to the carry, >=0, = (fftc_real)0 + && z[i].re > digit - (fftc_real)0.5 + && z[i].re < digit + (fftc_real)0.5)) + cl_abort(); + #endif + if (shift > 0) + digit = digit * fftc_pow2_table[shift]; + var fftc_real digit1 = fftc_ffloor(digit*((fftc_real)1.0/fftc_pow2(intDsize))); + var uintD digit0 = (uintD)(digit - digit1*fftc_pow2(intDsize)); + carry1 += digit1; + if ((carry0 += digit0) < digit0) + carry1 += (fftc_real)1.0; + shift += l; + while (shift >= intDsize) { + lsprefnext(destptr) = carry0; + var fftc_real tmp = fftc_ffloor(carry1*((fftc_real)1.0/fftc_pow2(intDsize))); + carry0 = (uintD)(carry1 - tmp*fftc_pow2(intDsize)); + carry1 = tmp; + shift -= intDsize; + } + } + if (carry0 > 0 || carry1 > (fftc_real)0.0) { + lsprefnext(destptr) = carry0; + while (carry1 > (fftc_real)0.0) { + var fftc_real tmp = fftc_ffloor(carry1*((fftc_real)1.0/fftc_pow2(intDsize))); + lsprefnext(destptr) = (uintD)(carry1 - tmp*fftc_pow2(intDsize)); + carry1 = tmp; + } + } + } + return destptr; +} + +static inline void mulu_fftcomplex_nocheck (const uintD* sourceptr1, uintC len1, + const uintD* sourceptr2, uintC len2, + uintD* destptr) +// Es ist 2 <= len1 <= len2. +{ + // We have to find parameters l and k such that + // ceiling(len1*intDsize/l) + ceiling(len2*intDsize/l) - 1 <= 2^k, + // and (12*k-15)*e*2^(2*l+2*k+1/2-m) < 1/2. + // Try primarily to minimize k. Minimizing l buys you nothing. + var uintL k; + // Computing k: If len1 and len2 differ much, we'll split source2 - + // hence for the moment just substitute len1 for len2. + // + // First approximation of k: A necessary condition for + // 2*ceiling(len1*intDsize/l) - 1 <= 2^k + // is 2*len1*intDsize/l_max - 1 <= 2^k. + { + var const int l = max_l(2); + var uintL lhs = 2*ceiling((uintL)len1*intDsize,l) - 1; // >=1 + if (lhs < 3) + k = 2; + else + integerlength32(lhs-1, k=); // k>=2 + } + // Try whether this k is ok or whether we have to increase k. + for ( ; ; k++) { + if (k >= sizeof(max_l_table)/sizeof(max_l_table[0]) + || max_l_table[k] <= 0) { + fprint(cl_stderr, "FFT problem: numbers too big, floating point precision not sufficient\n"); + cl_abort(); + } + if (2*ceiling((uintL)len1*intDsize,max_l_table[k])-1 <= ((uintL)1 << k)) + break; + } + // We could try to reduce l, keeping the same k. But why should we? + // Calculate the number of pieces in which source2 will have to be + // split. Each of the pieces must satisfy + // ceiling(len1*intDsize/l) + ceiling(len2*intDsize/l) - 1 <= 2^k, + var uintL len2p; + // Try once with k, once with k+1. Compare them. + { + var uintL remaining_k = ((uintL)1 << k) + 1 - ceiling((uintL)len1*intDsize,max_l_table[k]); + var uintL max_piecelen_k = floor(remaining_k*max_l_table[k],intDsize); + var uintL numpieces_k = ceiling(len2,max_piecelen_k); + var uintL remaining_k1 = ((uintL)1 << (k+1)) + 1 - ceiling((uintL)len1*intDsize,max_l_table[k+1]); + var uintL max_piecelen_k1 = floor(remaining_k1*max_l_table[k+1],intDsize); + var uintL numpieces_k1 = ceiling(len2,max_piecelen_k1); + if (numpieces_k <= 2*numpieces_k1) { + // keep k + len2p = max_piecelen_k; + } else { + // choose k+1 + k = k+1; + len2p = max_piecelen_k1; + } + } + var const uintL l = max_l_table[k]; + var const uintL n = k; + var const uintL N = (uintL)1 << n; + CL_ALLOCA_STACK; + var fftc_complex* const x = cl_alloc_array(fftc_complex,N); + var fftc_complex* const y = cl_alloc_array(fftc_complex,N); + #ifdef DEBUG_FFTC + var fftc_complex* const z = cl_alloc_array(fftc_complex,N); + #else + var fftc_complex* const z = x; // put z in place of x - saves memory + #endif + var uintD* const tmpprod1 = cl_alloc_array(uintD,len1+1); + var uintL tmpprod_len = floor(l< len2) + len2p = len2; + if (len2p == 1) { + // cheap case + var uintD* tmpptr = arrayLSDptr(tmpprod1,len1+1); + mulu_loop_lsp(lspref(sourceptr2,0),sourceptr1,tmpptr,len1); + if (addto_loop_lsp(tmpptr,destptr,len1+1)) + if (inc_loop_lsp(destptr lspop (len1+1),destlen-(len1+1))) + cl_abort(); + } else { + var bool squaring = ((sourceptr1 == sourceptr2) && (len1 == len2p)); + // Fill factor x. + fill_factor(N,x,l,sourceptr1,len1); + // Fill factor y. + if (!squaring) + fill_factor(N,y,l,sourceptr2,len2p); + // Multiply. + if (!squaring) + fftc_convolution(n,N, &x[0], &y[0], &z[0]); + else + fftc_convolution(n,N, &x[0], &x[0], &z[0]); + #ifdef DEBUG_FFTC + // Check result. + { + var fftc_real re_lo_limit = (fftc_real)(-0.5); + var fftc_real re_hi_limit = (fftc_real)N * fftc_pow2_table[l] * fftc_pow2_table[l] + (fftc_real)0.5; + var fftc_real im_lo_limit = (fftc_real)(-0.5); + var fftc_real im_hi_limit = (fftc_real)0.5; + for (var uintL i = 0; i < N; i++) { + if (!(z[i].im > im_lo_limit + && z[i].im < im_hi_limit)) + cl_abort(); + if (!(z[i].re > re_lo_limit + && z[i].re < re_hi_limit)) + cl_abort(); + } + } + #endif + var uintD* tmpLSDptr = arrayLSDptr(tmpprod,tmpprod_len); + var uintD* tmpMSDptr = unfill_product(n,N,z,l,tmpLSDptr); + var uintL tmplen = + #if CL_DS_BIG_ENDIAN_P + tmpLSDptr - tmpMSDptr; + #else + tmpMSDptr - tmpLSDptr; + #endif + if (tmplen > tmpprod_len) + cl_abort(); + // Add result to destptr[-destlen..-1]: + if (tmplen > destlen) { + if (test_loop_msp(tmpMSDptr,tmplen-destlen)) + cl_abort(); + tmplen = destlen; + } + if (addto_loop_lsp(tmpLSDptr,destptr,tmplen)) + if (inc_loop_lsp(destptr lspop tmplen,destlen-tmplen)) + cl_abort(); + } + // Decrement len2. + destptr = destptr lspop len2p; + destlen -= len2p; + sourceptr2 = sourceptr2 lspop len2p; + len2 -= len2p; + } while (len2 > 0); +} + +#ifndef _CHECKSUM +#define _CHECKSUM + +// Compute a checksum: number mod (2^intDsize-1). +static uintD compute_checksum (const uintD* sourceptr, uintC len) +{ + var uintD tmp = ~(uintD)0; // -1-(sum mod 2^intDsize-1), always >0 + do { + var uintD digit = lsprefnext(sourceptr); + if (digit < tmp) + tmp -= digit; // subtract digit + else + tmp -= digit+1; // subtract digit-(2^intDsize-1) + } while (--len > 0); + return ~tmp; +} + +// Multiply two checksums modulo (2^intDsize-1). +static inline uintD multiply_checksum (uintD checksum1, uintD checksum2) +{ + var uintD checksum; + var uintD cksum_hi; + #if HAVE_DD + var uintDD cksum = muluD(checksum1,checksum2); + cksum_hi = highD(cksum); checksum = lowD(cksum); + #else + muluD(checksum1,checksum2, cksum_hi =, checksum =); + #endif + if ((checksum += cksum_hi) + 1 <= cksum_hi) + checksum += 1; + return checksum; +} + +#endif // _CHECKSUM + +static void mulu_fftcomplex (const uintD* sourceptr1, uintC len1, + const uintD* sourceptr2, uintC len2, + uintD* destptr) +{ + // Compute checksums of the arguments and multiply them. + var uintD checksum1 = compute_checksum(sourceptr1,len1); + var uintD checksum2 = compute_checksum(sourceptr2,len2); + var uintD checksum = multiply_checksum(checksum1,checksum2); + mulu_fftcomplex_nocheck(sourceptr1,len1,sourceptr2,len2,destptr); + if (!(checksum == compute_checksum(destptr,len1+len2))) { + fprint(cl_stderr, "FFT problem: checksum error\n"); + cl_abort(); + } +} diff --git a/src/base/digitseq/cl_DS_mul_fftcs.h b/src/base/digitseq/cl_DS_mul_fftcs.h new file mode 100644 index 0000000..3b49b94 --- /dev/null +++ b/src/base/digitseq/cl_DS_mul_fftcs.h @@ -0,0 +1,1155 @@ +// Fast integer multiplication using FFT over the complex numbers, +// exploiting symmetry. +// [Donald Ervin Knuth: The Art of Computer Programming, Vol. II: +// Seminumerical Algorithms, second edition. Section 4.3.3, p. 290-294.] +// Bruno Haible 6.5.1996, 24.-25.8.1996, 31.8.1996 + +// FFT in the complex domain has the drawback that it needs careful round-off +// error analysis. But for CPUs with good floating-point performance it might +// nevertheless be better than FFT mod Z/mZ. + +// The usual FFT(2^n) computes the values of a polynomial p(z) mod (z^(2^n)-1) +// at the (2^n)-th roots of unity. For our purposes, we start out with +// polynomials with real coefficients. So the values at z_j = exp(2 pi i j/N) +// and z_-j = exp(- 2 pi i j/N) will be complex conjugates of each other, +// which means that there exists a polynomial r(z) of degree <= 1 with real +// coefficients such that p(z_j) = r(z_j) and p(z_-j) = r(z_-j). This +// implies that r(z) is the remainder of p(z) divided by +// (z - z_j) (z - z_-j) = (z^2 - 2 cos(2 pi j/N) z + 1). +// +// Based on this insight, we replace the usual n FFT steps +// for m = n...0: +// (z^(2^n)-1) = prod(j=0..2^(n-m)-1, (z^(2^m) - exp(2 pi j/2^(n-m)))) +// by +// for m = n...1: +// (z^(2^n)-1) = (z^(2^m)-1) * prod(j=1..2^(n-m)-1, factor_m[j](z)) +// where +// factor_m[j](z) = prod(k mod 2^n with k == j or k == -j mod 2^(n-m+1), +// (z - exp(2 pi i k/N)) ) +// = prod(k=0..2^(m-1)-1, +// (z - exp(2 pi i (j+2^(n-m+1)k)/N)) +// (z - exp(- 2 pi i (j+2^(n-m+1)k)/N)) ) +// = (z^(2^(m-1)) - exp(2 pi i j 2^(m-1)/N)) +// (z^(2^(m-1)) - exp(- 2 pi i j 2^(m-1)/N)) +// = (z^(2^(m-1)) - exp(2 pi i j/2^(n-m+1))) +// (z^(2^(m-1)) - exp(- 2 pi i j/2^(n-m+1))) +// = (z^(2^m) - 2 cos(2 pi j/2^(n-m+1)) z^(2^(m-1)) + 1). +// The factors and the input are real polynomials, hence all intermediate +// and final remainders will be real as well. +// +// However, instead of storing +// p(z) mod (z^(2^m) - 2 cos(2 pi j/2^(n-m+1)) z^(2^(m-1)) + 1), +// we compute and store +// realpart and imagpart of p(z) mod (z^(2^(m-1)) - exp(2 pi i j 2^(m-1)/N)). +// This way, the round-off error estimates are better because we don't have +// to multiply with numbers > 1, and because during the final reverse FFT, we +// don't have to divide by numbers around 2^(-n). +// +// The usual FFT algorithm +// Input: polynomial p in x[0..2^n-1]. +// for l = n-1..0: // step m=l+1 -> m=l +// for s in {0,..,2^(n-1-l)-1}: +// exp := bit_reverse(n-1-l,s)*2^l, +// // chinese remainder algorithm for (z^(2^(l+1)) - w^(2*exp)) = +// // = (z^(2^l) - w^exp) * (z^(2^l) - w^(exp+2^(n-1))). +// for t in {0,..,2^l-1}: +// i1 := s*2^(l+1) + t, i2 := s*2^(l+1) + 2^l + t, +// replace (x[i1],x[i2]) by (x[i1] + w^exp*x[i2], x[i1] - w^exp*x[i2]) +// Invariant: +// for m = n..0: +// for j in {0..2^(n-m)-1}: +// p(z) mod (z^(2^m) - exp(2 pi i j/2^(n-m))) +// in x[bit_reverse(n-m,j)*2^m .. bit_reverse(n-m,j)*2^m+2^m-1]. +// Output: p(z_j) in x[bit_reverse(n,j)]. +// is thus replaced by the algorithm +// Input: polynomial p in x[0..2^n-1]. +// for l = n-1..1: // step m=l+1 -> m=l +// for s in {0}: +// // chinese remainder algorithm for +// // (z^(2^(l+1)) - 1) = (z^(2^l) - 1) * (z^(2^l) + 1). +// for t in {0,..,2^l-1}: +// i1 := t, i2 := 2^l + t, +// replace (x[i1],x[i2]) by (x[i1] + x[i2], x[i1] - x[i2]) +// // chinese remainder algorithm for +// // (z^(2^l) + 1) = (z^(2^(l-1)) - i) * (z^(2^(l-1)) + i). +// // Nothing to do because of +// // a[0]z^0+...+a[2^l-1]z^(2^l-1) mod (z^(2^(l-1)) - i) +// // = (a[0]z^0+...+a[2^(l-1)-1]z^(2^(l-1)-1)) +// // + i*(a[2^(l-1)]z^0+...+a[2^l-1]z^(2^(l-1)-1)) +// // and because of the way we store the real parts and imaginary parts. +// for s in {1,..,2^(n-1-l)-1}: +// exp := shuffle(n-1-l,s)*2^(l-1), +// // chinese remainder algorithm for +// // (z^(2^l) - w^(2*exp)) +// // = (z^(2^(l-1)) - w^exp) * conj(z^(2^(l-1)) - w^(2^(n-1)-exp)). +// for t in {0,..,2^(l-1)-1}: +// i1 := s*2^(l+1) + t, i2 := s*2^(l+1) + 2^(l-1) + t, +// i3 := s*2^(l+1) + 2^l + t, i4 := s*2^(l+1) + 2^l + 2^(l-1) + t, +// replace (x[i1],x[i2],x[i3],x[i4]) by +// (x[i1] + x[i2]*Re(w^exp) - x[i4]*Im(w^exp), +// x[i3] + x[i4]*Re(w^exp) + x[i2]*Im(w^exp), +// x[i1] - x[i2]*Re(w^exp) + x[i4]*Im(w^exp), +// -x[i3] + x[i4]*Re(w^exp) + x[i2]*Im(w^exp)) +// Invariant: +// for m = n..1: +// p(z) mod (z^(2^m) - 1) in x[0..2^m-1], +// for j in {1,..,2^(n-m)-1}: +// p(z) mod (z^(2^(m-1)) - exp(2 pi i j/2^(n-m+1))) +// in x[invshuffle(n-m,j)*2^m + (0 .. 2^(m-1)-1)] (realpart) +// and x[invshuffle(n-m,j)*2^m+2^(m-1) + (0 .. 2^(m-1)-1)] (imagpart). +// Output: p(z) mod (z^2 - 1) in x[0],x[1], +// p(z) mod (z - exp(2 pi i j/2^n)) (0 < j < 2^(n-1)) +// = x[2*invshuffle(n-1,j)] + i*x[2*invshuffle(n-1,j)+1], +// p(z) mod (z - exp(- 2 pi i j/2^n)) (0 < j < 2^(n-1)) +// = x[2*invshuffle(n-1,j)] - i*x[2*invshuffle(n-1,j)+1]. +// +// The shuffle function is defined like this: +// shuffle(n,j) defined for n >= 0, 0 < j < 2^n, yields 0 < shuffle(n,j) < 2^n. +// Definition by splitting off the least significant bit: +// n = 0: void. +// n > 0: shuffle(n,1) = 2^(n-1), +// n > 0, 0 < j < 2^(n-1): shuffle(n,2*j) = shuffle(n-1,j), +// n > 0, 0 < j < 2^(n-1): shuffle(n,2*j+1) = 2^n - shuffle(n-1,j). +// Its inverse function is defined like this: +// invshuffle(n,j) defined for n >= 0, 0 < j < 2^n, 0 < invshuffle(n,j) < 2^n. +// Definition by splitting off the most significant bit: +// n = 0: void. +// n > 0, 0 < j < 2^(n-1): invshuffle(n,j) = invshuffle(n-1,j)*2, +// n > 0, j = 2^(n-1): invshuffle(n,j) = 1, +// n > 0, 2^(n-1) < j < 2^n: invshuffle(n,j) = invshuffle(n-1,2^n-j)*2+1. +// Note that shuffle(n,.) and invshuffle(n,.) are _not_ the same permutation +// for n>=4. + +// It is important to have precise round-off error estimates. Although +// (by laws of statistics) in the average the actual round-off error makes up +// only half of the bits provided for round-off protection, we cannot rely +// on this average behaviour, but have to produce correct results. +// +// Knuth's formula (42), p. 294, says: +// If we want to multiply l-bit words using an FFT(2^k), our floating point +// numbers shall have m >= 2(k+l) + k + log_2 k + 3.5 mantissa bits. +// +// Here is a more careful analysis, using absolute error estimates. +// +// 1. We assume floating point numbers with radix 2, with the properties: +// (i) Multiplication with 2^n and 2^-n is exact. +// (ii) Negation x -> -x is exact. +// (iii) Addition: When adding x and y, with |x| <= 2^a, |y| <= 2^a, +// the result |x+y| <= 2^(a+1) has an error <= e*2^(a+1-m). +// (iv) Multiplication: When multiplying x and y, with |x| <= 2^a, +// |y| <= 2^b, the result |x*y| <= 2^(a+b) has an error <= e*2^(a+b-m). +// Here e = 1 for a truncating arithmetic, but e = 1/2 for a rounding +// arithmetic like IEEE single and double floats. +// 2. Let's introduce some notation: err(x) means |x'-x| where x is the +// exact mathematical value and x' is its representation in the machine. +// 3. From 1. we get for real numbers x,y: +// (i) err(2^n*x) = 2^n * err(x), +// (ii) err(-x) = err(x), +// (iii) |x| <= 2^a, |y| <= 2^a, then +// err(x+y) <= err(x) + err(y) + e*2^(a+1-m), +// [or .... ............... + e*2^(a-m) if |x+y| <= 2^a]. +// (iv) |x| <= 2^a, |y| <= 2^b, then +// err(x*y) <= 2^a * err(y) + 2^b * err(x) + e*2^(a+b-m). +// 4. Our complex arithmetic will be based on the formulas: +// (i) 2^n*(x+iy) = (2^n*x)+i(2^n*y) +// (ii) -(x+iy) = (-x)+i(-y) +// (iii) (x+iy)+(u+iv) = (x+u)+i(y+v) +// (iv) (x+iy)*(u+iv) = (x*u-y*v)+i(x*v+y*u) +// The notation err(z) means |z'-z|, as above, with |.| being the usual +// absolute value on complex numbers (_not_ the L^1 norm). +// 5. From 3. and 4. we get for complex numbers x,y: +// (i) err(2^n*x) = 2^n * err(x), +// (ii) err(-x) = err(x), +// (iii) |x| <= 2^a, |y| <= 2^a, then +// err(x+y) <= err(x) + err(y) + e*2^(a+3/2-m), +// (iv) |x| <= 2^a, |y| <= 2^b, then +// err(x*y) <= 2^a * err(y) + 2^b * err(x) + 3*e*2^(a+b+1/2-m). +// 6. We start out with precomputed roots of unity: +// |exp(2 pi i/2^n)| <= 1, +// err(exp(2 pi i/2^n)) <= e*2^(1/2-m), (even err(..)=0 for n=0,1,2), +// and compute exp(2 pi i * j/2^k) according to the binary digits of j. +// This way, each root of unity will be a product of at most k precomputed +// roots. If (j mod 2^(k-2)) has n bits, then exp(2 pi i * j/2^k) will +// be computed using n factors, i.e. n-1 complex multiplications, and by +// 5.iv. we'll have +// err(exp(2 pi i * j/2^k)) <= n*e*2^(1/2-m) + max(n-1,0)*3*e*2^(1/2-m) +// = max(4*n-3,0)*e*2^(1/2-m). +// Hence the maximum roots-of-unity error is (set n=k-2) +// err(w^j) <= (4*k-11)*e*2^(1/2-m), +// and the average roots-of-unity error is (set n=(k-2)/2) +// < 2*(k-2)*e*2^(1/2-m). +// 7. Now we start the FFT. +// Before the first step, x_i are integral, |x_i| < 2^l and err(x_i) = 0. +// After the first butterfly, which replaces (x(i1),x(i2)) by +// (x(i1) + x(i2), x(i1) - x(i2)), we have |x_i| < 2^(l+1) and err(x_i) = 0. +// Then, for each of the remaining k-1 steps, a butterfly replaces +// (x(i1),x(i2)) by (x(i1) + w^exp*x(i2), x(i1) - w^exp*x(i2)). Thus, +// after n steps we have |x_i| < 2^(l+n) and err(x_i) <= E_i where +// E_0 = 0, +// E_1 = 0, +// E_(n+1) = (E_n + 2^(l+n)*(4*k-11)*e*2^(1/2-m) + 3*e*2^(l+n+1/2-m)) +// + E_n + e*2^(l+n+3/2-m) +// = 2*E_n + (4*k-6)*e*2^(l+n+1/2-m) +// hence E_n = (2^n-2)*(4*k-6)*e*2^(l+1/2-m). +// Setting n = k, we have proved that after the FFT ends, we have +// |x_i| < 2^(l+k) and err(x_i) <= (4*k-6)*e*2^(l+k+1/2-m). +// 8. The same error analysis holds for the y_i and their FFT. After we +// multiply z_i := x_i * y_i, we have +// |z_i| < 2^(2*l+2*k) and err(z_i) <= (8*k-9)*e*2^(2*l+2*k+1/2-m). +// 9. Then an inverse FFT on z_i is done, which is the same as an FFT +// followed by a permutation and a division by 2^k. After n steps of +// the FFT, we have |z_i| < 2^(2*l+2*k+n) and err(z_i) <= E_i where +// E_0 = (8*k-9)*e*2^(2*l+2*k+1/2-m), +// E_(n+1) = (E_n + 2^(2*l+2*k+n)*(4*k-11)*e*2^(1/2-m) +// + 3*e*2^(2*l+2*k+n+1/2-m)) +// + E_n + e*2^(2*l+2*k+n+3/2-m) +// = 2*E_n + (4*k-6)*e*2^(2*l+2*k+n+1/2-m) +// hence E_n = 2^n*(8*k-9)*e*2^(2*l+2*k+1/2-m) +// + (2^n-1)*(4*k-6)*e*2^(2*l+2*k+1/2-m). +// So, after the FFT, we have (set n=k) |z_i| < 2^(2*l+3*k) and +// err(z_i) <= (12*k-15)*e*2^(2*l+3*k+1/2-m). +// Permutation doesn't change the estimates. After division by 2^k, we get +// |z_i| < 2^(2*l+2*k) and +// err(z_i) <= (12*k-15)*e*2^(2*l+2*k+1/2-m). +// 10. When converting the z_i back to integers, we know that z_i should be +// real, integral, and |z_i| < 2^(2*l+k). We can only guarantee that we +// can find the integral z_i from the floating-point computation if +// (12*k-15)*e*2^(2*l+2*k+1/2-m) < 1/2. +// 11. Assuming e = 1/2 and m = 53 (typical values for IEEE double arithmetic), +// we get the constraint 2*l < m - 1/2 - 2*k - log_2(12*k-15). +// k = 2 l <= 22 +// k = 3 l <= 21 +// k = 4 l <= 19 +// k = 5 l <= 18 +// k = 6 l <= 17 +// k = 7 l <= 16 +// k = 8 l <= 15 +// k = 9 l <= 13 +// k = 10 l <= 12 +// k = 11 l <= 11 +// k = 12 l <= 10 +// k = 13 l <= 9 +// k = 14 l <= 8 +// k = 15 l <= 7 +// k = 16 l <= 6 +// k = 17 l <= 5 +// k = 18 l <= 4 +// k = 19 l <= 3 +// k = 20 l <= 2 +// Assuming e = 1/2 and m = 64 ("long double" arithmetic on i387/i486/i586), +// we get the constraint 2*l < m - 1/2 - 2*k - log_2(12*k-15). +// k = 2 l <= 28 +// k = 3 l <= 26 +// k = 4 l <= 25 +// k = 5 l <= 24 +// k = 6 l <= 22 +// k = 7 l <= 21 +// k = 8 l <= 20 +// k = 9 l <= 19 +// k = 10 l <= 18 +// k = 11 l <= 17 +// k = 12 l <= 16 +// k = 13 l <= 15 +// k = 14 l <= 14 +// k = 15 l <= 13 +// k = 16 l <= 12 +// k = 17 l <= 10 +// k = 18 l <= 9 +// k = 19 l <= 8 +// k = 20 l <= 7 +// k = 21 l <= 6 +// k = 22 l <= 5 +// k = 23 l <= 4 +// k = 24 l <= 3 +// k = 25 l <= 2 + + +#if !(intDsize==32) +#error "complex symmetric fft implemented only for intDsize==32" +#endif + + +#include "cl_floatparam.h" +#include "cl_io.h" +#include "cl_abort.h" + +#if defined(HAVE_LONGDOUBLE) && (long_double_mant_bits > double_mant_bits) && (defined(__i386__) || defined(__m68k__) || (defined(__sparc__) && 0)) +// Only these CPUs have fast "long double"s in hardware. +// On SPARC, "long double"s are emulated in software and don't work. +typedef long double fftcs_real; +#define fftcs_real_mant_bits long_double_mant_bits +#define fftcs_real_rounds long_double_rounds +#else +typedef double fftcs_real; +#define fftcs_real_mant_bits double_mant_bits +#define fftcs_real_rounds double_rounds +#endif + +typedef struct fftcs_complex { + fftcs_real re; + fftcs_real im; +} fftcs_complex; + +static const fftcs_complex fftcs_roots_of_1 [32+1] = + // roots_of_1[n] is a (2^n)th root of unity in C. + // Also roots_of_1[n-1] = roots_of_1[n]^2. + // For simplicity we choose roots_of_1[n] = exp(2 pi i/2^n). + { + #if (fftcs_real_mant_bits == double_mant_bits) + // These values have 64 bit precision. + { 1.0, 0.0 }, + { -1.0, 0.0 }, + { 0.0, 1.0 }, + { 0.7071067811865475244, 0.7071067811865475244 }, + { 0.9238795325112867561, 0.38268343236508977172 }, + { 0.9807852804032304491, 0.19509032201612826784 }, + { 0.99518472667219688623, 0.098017140329560601996 }, + { 0.9987954562051723927, 0.049067674327418014254 }, + { 0.9996988186962042201, 0.024541228522912288032 }, + { 0.99992470183914454094, 0.0122715382857199260795 }, + { 0.99998117528260114264, 0.0061358846491544753597 }, + { 0.9999952938095761715, 0.00306795676296597627 }, + { 0.99999882345170190993, 0.0015339801862847656123 }, + { 0.99999970586288221914, 7.6699031874270452695e-4 }, + { 0.99999992646571785114, 3.8349518757139558907e-4 }, + { 0.9999999816164292938, 1.9174759731070330744e-4 }, + { 0.9999999954041073129, 9.5873799095977345874e-5 }, + { 0.99999999885102682754, 4.793689960306688455e-5 }, + { 0.99999999971275670683, 2.3968449808418218729e-5 }, + { 0.9999999999281891767, 1.1984224905069706422e-5 }, + { 0.99999999998204729416, 5.9921124526424278428e-6 }, + { 0.99999999999551182357, 2.9960562263346607504e-6 }, + { 0.99999999999887795586, 1.4980281131690112288e-6 }, + { 0.999999999999719489, 7.4901405658471572114e-7 }, + { 0.99999999999992987223, 3.7450702829238412391e-7 }, + { 0.99999999999998246807, 1.8725351414619534487e-7 }, + { 0.999999999999995617, 9.36267570730980828e-8 }, + { 0.99999999999999890425, 4.6813378536549092695e-8 }, + { 0.9999999999999997261, 2.340668926827455276e-8 }, + { 0.99999999999999993153, 1.1703344634137277181e-8 }, + { 0.99999999999999998287, 5.8516723170686386908e-9 }, + { 0.9999999999999999957, 2.925836158534319358e-9 }, + { 0.9999999999999999989, 1.4629180792671596806e-9 } + #else (fftcs_real_mant_bits > double_mant_bits) + // These values have 128 bit precision. + { 1.0L, 0.0L }, + { -1.0L, 0.0L }, + { 0.0L, 1.0L }, + { 0.707106781186547524400844362104849039284L, 0.707106781186547524400844362104849039284L }, + { 0.923879532511286756128183189396788286823L, 0.38268343236508977172845998403039886676L }, + { 0.980785280403230449126182236134239036975L, 0.195090322016128267848284868477022240928L }, + { 0.995184726672196886244836953109479921574L, 0.098017140329560601994195563888641845861L }, + { 0.998795456205172392714771604759100694444L, 0.0490676743274180142549549769426826583147L }, + { 0.99969881869620422011576564966617219685L, 0.0245412285229122880317345294592829250654L }, + { 0.99992470183914454092164649119638322435L, 0.01227153828571992607940826195100321214037L }, + { 0.999981175282601142656990437728567716173L, 0.00613588464915447535964023459037258091705L }, + { 0.999995293809576171511580125700119899554L, 0.00306795676296597627014536549091984251894L }, + { 0.99999882345170190992902571017152601905L, 0.001533980186284765612303697150264079079954L }, + { 0.999999705862882219160228217738765677117L, 7.66990318742704526938568357948576643142e-4L }, + { 0.99999992646571785114473148070738785695L, 3.83495187571395589072461681181381263396e-4L }, + { 0.999999981616429293808346915402909714504L, 1.91747597310703307439909561989000933469e-4L }, + { 0.99999999540410731289097193313960614896L, 9.58737990959773458705172109764763511872e-5L }, + { 0.9999999988510268275626733077945541084L, 4.79368996030668845490039904946588727468e-5L }, + { 0.99999999971275670684941397221864177609L, 2.39684498084182187291865771650218200947e-5L }, + { 0.999999999928189176709775095883850490262L, 1.198422490506970642152156159698898480473e-5L }, + { 0.99999999998204729417728262414778410738L, 5.99211245264242784287971180889086172999e-6L }, + { 0.99999999999551182354431058417299732444L, 2.99605622633466075045481280835705981183e-6L }, + { 0.999999999998877955886077016551752536504L, 1.49802811316901122885427884615536112069e-6L }, + { 0.999999999999719488971519214794719584451L, 7.49014056584715721130498566730655637157e-7L }, + { 0.99999999999992987224287980123972873676L, 3.74507028292384123903169179084633177398e-7L }, + { 0.99999999999998246806071995015624773673L, 1.8725351414619534486882457659356361712e-7L }, + { 0.999999999999995617015179987529456656217L, 9.3626757073098082799067286680885620193e-8L }, + { 0.999999999999998904253794996881763834182L, 4.68133785365490926951155181385400969594e-8L }, + { 0.99999999999999972606344874922040343793L, 2.34066892682745527595054934190348440379e-8L }, + { 0.999999999999999931515862187305098514444L, 1.170334463413727718124621350323810379807e-8L }, + { 0.999999999999999982878965546826274482047L, 5.8516723170686386908097901008341396944e-9L }, + { 0.999999999999999995719741386706568611352L, 2.92583615853431935792823046906895590202e-9L }, + { 0.999999999999999998929935346676642152265L, 1.46291807926715968052953216186596371037e-9L } + #endif + }; + +// Define this for (cheap) consistency checks. +#define DEBUG_FFTCS + +static fftcs_real fftcs_pow2_table[64] = // table of powers of 2 + { + 1.0, + 2.0, + 4.0, + 8.0, + 16.0, + 32.0, + 64.0, + 128.0, + 256.0, + 512.0, + 1024.0, + 2048.0, + 4096.0, + 8192.0, + 16384.0, + 32768.0, + 65536.0, + 131072.0, + 262144.0, + 524288.0, + 1048576.0, + 2097152.0, + 4194304.0, + 8388608.0, + 16777216.0, + 33554432.0, + 67108864.0, + 134217728.0, + 268435456.0, + 536870912.0, + 1073741824.0, + 2147483648.0, + 4294967296.0, + 8589934592.0, + 17179869184.0, + 34359738368.0, + 68719476736.0, + 137438953472.0, + 274877906944.0, + 549755813888.0, + 1099511627776.0, + 2199023255552.0, + 4398046511104.0, + 8796093022208.0, + 17592186044416.0, + 35184372088832.0, + 70368744177664.0, + 140737488355328.0, + 281474976710656.0, + 562949953421312.0, + 1125899906842624.0, + 2251799813685248.0, + 4503599627370496.0, + 9007199254740992.0, + 18014398509481984.0, + 36028797018963968.0, + 72057594037927936.0, + 144115188075855872.0, + 288230376151711744.0, + 576460752303423488.0, + 1152921504606846976.0, + 2305843009213693952.0, + 4611686018427387904.0, + 9223372036854775808.0 + }; + +// For a constant expression n (0 <= n < 128), returns 2^n of type fftcs_real. +#define fftcs_pow2(n) \ + (((n) & 64 ? (fftcs_real)18446744073709551616.0 : (fftcs_real)1.0) \ + * ((n) & 32 ? (fftcs_real)4294967296.0 : (fftcs_real)1.0) \ + * ((n) & 16 ? (fftcs_real)65536.0 : (fftcs_real)1.0) \ + * ((n) & 8 ? (fftcs_real)256.0 : (fftcs_real)1.0) \ + * ((n) & 4 ? (fftcs_real)16.0 : (fftcs_real)1.0) \ + * ((n) & 2 ? (fftcs_real)4.0 : (fftcs_real)1.0) \ + * ((n) & 1 ? (fftcs_real)2.0 : (fftcs_real)1.0) \ + ) + +// r := a * b +static inline void mul (const fftcs_complex& a, const fftcs_complex& b, fftcs_complex& r) +{ + var fftcs_real r_re = a.re * b.re - a.im * b.im; + var fftcs_real r_im = a.re * b.im + a.im * b.re; + r.re = r_re; + r.im = r_im; +} + +static uintL shuffle (uintL n, uintL x) +{ + var uintL y = 0; + var sintL v = 1; + // Invariant: y + v*shuffle(n,x). + do { + if (x & 1) + if (x == 1) + return y + (v << (n-1)); + else { + y = y + (v << n); + v = -v; + } + x >>= 1; + } while (!(--n == 0)); + cl_abort(); +} + +#if 0 // unused +static uintL invshuffle (uintL n, uintL x) +{ + var uintL y = 0; + var uintL v = 1; + // Invariant: y + v*invshuffle(n,x). + do { + if (x == ((uintL)1 << (n-1))) + return y + v; + else if (x > ((uintL)1 << (n-1))) { + x = ((uintL)1 << n) - x; + y = y+v; + } + v <<= 1; + } while (!(--n == 0)); + cl_abort(); +} +#endif + +// Compute a real convolution using FFT: z[0..N-1] := x[0..N-1] * y[0..N-1]. +static void fftcs_convolution (const uintL n, const uintL N, // N = 2^n + fftcs_real * x, // N numbers + fftcs_real * y, // N numbers + fftcs_real * z // N numbers result + ) +{ + CL_ALLOCA_STACK; + var fftcs_complex* const w = cl_alloc_array(fftcs_complex,N>>2); + var uintL i; + // Initialize w[i] to w^i, w a primitive N-th root of unity. + w[0] = fftcs_roots_of_1[0]; + { + var int j; + for (j = n-3; j>=0; j--) { + var fftcs_complex r_j = fftcs_roots_of_1[n-j]; + w[1<>2; i += (2< 0; l--) { + /* s = 0 */ { + var const uintL tmax = (uintL)1 << l; + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = t; + var uintL i2 = i1 + tmax; + // replace (x[i1],x[i2]) by + // (x[i1] + x[i2], x[i1] - x[i2]) + var fftcs_real tmp; + tmp = x[i2]; + x[i2] = x[i1] - tmp; + x[i1] = x[i1] + tmp; + } + } + var const uintL smax = (uintL)1 << (n-1-l); + var const uintL tmax = (uintL)1 << (l-1); + for (var uintL s = 1; s < smax; s++) { + var uintL exp = shuffle(n-1-l,s) << (l-1); + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = (s << (l+1)) + t; + var uintL i2 = i1 + tmax; + var uintL i3 = i2 + tmax; + var uintL i4 = i3 + tmax; + // replace (x[i1],x[i2],x[i3],x[i4]) by + // (x[i1] + x[i2]*Re(w^exp) - x[i4]*Im(w^exp), + // x[i3] + x[i4]*Re(w^exp) + x[i2]*Im(w^exp), + // x[i1] - x[i2]*Re(w^exp) + x[i4]*Im(w^exp), + // -x[i3] + x[i4]*Re(w^exp) + x[i2]*Im(w^exp)) + var fftcs_real diff; + var fftcs_real sum; + var fftcs_real tmp1; + var fftcs_real tmp3; + diff = x[i2] * w[exp].re - x[i4] * w[exp].im; + sum = x[i4] * w[exp].re + x[i2] * w[exp].im; + tmp1 = x[i1]; + tmp3 = x[i3]; + x[i1] = tmp1 + diff; + x[i2] = tmp3 + sum; + x[i3] = tmp1 - diff; + x[i4] = sum - tmp3; + } + } + } + /* l = 0 */ { + // replace (x[0],x[1]) by (x[0]+x[1], x[0]-x[1]) + var fftcs_real tmp; + tmp = x[1]; + x[1] = x[0] - tmp; + x[0] = x[0] + tmp; + } + } + // Do an FFT of length N on y. + if (!squaring) { + var uintL l; + for (l = n-1; l > 0; l--) { + /* s = 0 */ { + var const uintL tmax = (uintL)1 << l; + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = t; + var uintL i2 = i1 + tmax; + // replace (y[i1],y[i2]) by + // (y[i1] + y[i2], y[i1] - y[i2]) + var fftcs_real tmp; + tmp = y[i2]; + y[i2] = y[i1] - tmp; + y[i1] = y[i1] + tmp; + } + } + var const uintL smax = (uintL)1 << (n-1-l); + var const uintL tmax = (uintL)1 << (l-1); + for (var uintL s = 1; s < smax; s++) { + var uintL exp = shuffle(n-1-l,s) << (l-1); + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = (s << (l+1)) + t; + var uintL i2 = i1 + tmax; + var uintL i3 = i2 + tmax; + var uintL i4 = i3 + tmax; + // replace (y[i1],y[i2],y[i3],y[i4]) by + // (y[i1] + y[i2]*Re(w^exp) - y[i4]*Im(w^exp), + // y[i3] + y[i4]*Re(w^exp) + y[i2]*Im(w^exp), + // y[i1] - y[i2]*Re(w^exp) + y[i4]*Im(w^exp), + // -y[i3] + y[i4]*Re(w^exp) + y[i2]*Im(w^exp)) + var fftcs_real diff; + var fftcs_real sum; + var fftcs_real tmp1; + var fftcs_real tmp3; + diff = y[i2] * w[exp].re - y[i4] * w[exp].im; + sum = y[i4] * w[exp].re + y[i2] * w[exp].im; + tmp1 = y[i1]; + tmp3 = y[i3]; + y[i1] = tmp1 + diff; + y[i2] = tmp3 + sum; + y[i3] = tmp1 - diff; + y[i4] = sum - tmp3; + } + } + } + /* l = 0 */ { + // replace (y[0],y[1]) by (y[0]+y[1], y[0]-y[1]) + var fftcs_real tmp; + tmp = y[1]; + y[1] = y[0] - tmp; + y[0] = y[0] + tmp; + } + } + // Multiply the transformed vectors into z. + { + // Multiplication mod (z-1). + z[0] = x[0] * y[0]; + // Multiplication mod (z+1). + z[1] = x[1] * y[1]; + for (i = 2; i < N; i += 2) + // Multiplication mod (z - exp(2 pi i j/2^n)), j = shuffle(n-1,i/2). + mul(*(fftcs_complex*)&x[i],*(fftcs_complex*)&y[i], *(fftcs_complex*)&z[i]); + } + // Undo an FFT of length N on z. + { + var uintL l; + /* l = 0 */ { + // replace (z[0],z[1]) by ((z[0]+z[1])/2, (z[0]-z[1])/2) + var fftcs_real tmp; + tmp = z[1]; + z[1] = (z[0] - tmp) * (fftcs_real)0.5; + z[0] = (z[0] + tmp) * (fftcs_real)0.5; + } + for (l = 1; l < n; l++) { + /* s = 0 */ { + var const uintL tmax = (uintL)1 << l; + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = t; + var uintL i2 = i1 + tmax; + // replace (z[i1],z[i2]) by + // ((z[i1]+z[i2])/2, (z[i1]-z[i2])/2) + // Do the division by 2 later. + var fftcs_real tmp; + tmp = z[i2]; + z[i2] = z[i1] - tmp; + z[i1] = z[i1] + tmp; + } + } + var const uintL smax = (uintL)1 << (n-1-l); + var const uintL tmax = (uintL)1 << (l-1); + for (var uintL s = 1; s < smax; s++) { + var uintL exp = shuffle(n-1-l,s) << (l-1); + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = (s << (l+1)) + t; + var uintL i2 = i1 + tmax; + var uintL i3 = i2 + tmax; + var uintL i4 = i3 + tmax; + // replace (z[i1],z[i2],z[i3],z[i4]) by + // ((z[i1]+z[i3])/2, + // (z[i1]-z[i3])/2*Re(w^exp)+(z[i2]+z[i4])/2*Im(w^exp), + // (z[i2]-z[i4])/2, + // (z[i2]+z[i4])/2*Re(w^exp)-(z[i1]-z[i3])/2*Im(w^exp)) + // Do the division by 2 later. + var fftcs_real diff13; + var fftcs_real sum24; + var fftcs_real tmp1; + var fftcs_real tmp3; + diff13 = z[i1] - z[i3]; + sum24 = z[i2] + z[i4]; + tmp1 = z[i1] + z[i3]; + tmp3 = z[i2] - z[i4]; + z[i1] = tmp1; + z[i2] = diff13 * w[exp].re + sum24 * w[exp].im; + z[i3] = tmp3; + z[i4] = sum24 * w[exp].re - diff13 * w[exp].im; + } + } + } + // Do all divisions by 2 now. + { + var fftcs_real f = (fftcs_real)2.0 / (fftcs_real)N; // 2^-(n-1) + for (i = 0; i < N; i++) + z[i] = z[i]*f; + } + } +} + +// For a given k >= 2, the maximum l is determined by +// 2*l < m - 1/2 - 2*k - log_2(12*k-15) - (1 if e=1.0, 0 if e=0.5). +// This is a decreasing function of k. +#define max_l(k) \ + (int)((fftcs_real_mant_bits \ + - 2*(k) \ + - ((k)<=2 ? 4 : (k)<=3 ? 5 : (k)<=5 ? 6 : (k)<=8 ? 7 : (k)<=16 ? 8 : (k)<=31 ? 9 : 10) \ + - (fftcs_real_rounds == rounds_to_nearest ? 0 : 1)) \ + / 2) +static int max_l_table[32+1] = + { 0, 0, max_l(2), max_l(3), max_l(4), max_l(5), max_l(6), + max_l(7), max_l(8), max_l(9), max_l(10), max_l(11), max_l(12), max_l(13), + max_l(14), max_l(15), max_l(16), max_l(17), max_l(18), max_l(19), max_l(20), + max_l(21), max_l(22), max_l(23), max_l(24), max_l(25), max_l(26), max_l(27), + max_l(28), max_l(29), max_l(30), max_l(31), max_l(32) + }; + +// Split len uintD's below sourceptr into chunks of l bits, thus filling +// N real numbers at x. +static void fill_factor (uintL N, fftcs_real* x, uintL l, + const uintD* sourceptr, uintL len) +{ + var uintL i; + if (max_l(2) > intDsize && l > intDsize) { + // l > intDsize + if (max_l(2) > 64 && l > 64) { + fprint(cl_stderr, "FFT problem: l > 64 not supported by pow2_table\n"); + cl_abort(); + } + var fftcs_real carry = 0; + var sintL carrybits = 0; // number of bits in carry (>=0, 0) { + var uintD digit = lsprefnext(sourceptr); + if (carrybits+intDsize >= l) { + x[i] = carry + (fftcs_real)(digit & bitm(l-carrybits)) * fftcs_pow2_table[carrybits]; + i++; + carry = (l-carrybits == intDsize ? (fftcs_real)0 : (fftcs_real)(digit >> (l-carrybits))); + carrybits = carrybits+intDsize-l; + } else { + carry = carry + (fftcs_real)digit * fftcs_pow2_table[carrybits]; + carrybits = carrybits+intDsize; + } + len--; + } + if (carrybits > 0) { + x[i] = carry; + i++; + } + if (i > N) + cl_abort(); + } else if (max_l(2) >= intDsize && l == intDsize) { + // l = intDsize + if (len > N) + cl_abort(); + for (i = 0; i < len; i++) { + var uintD digit = lsprefnext(sourceptr); + x[i] = (fftcs_real)digit; + } + } else { + // l < intDsize + var const uintD l_mask = bit(l)-1; + var uintD carry = 0; + var sintL carrybits = 0; // number of bits in carry (>=0, = l) { + x[i] = (fftcs_real)(carry & l_mask); + carry >>= l; + carrybits -= l; + } else { + if (len == 0) + break; + len--; + var uintD digit = lsprefnext(sourceptr); + x[i] = (fftcs_real)((carry | (digit << carrybits)) & l_mask); + carry = digit >> (l-carrybits); + carrybits = intDsize - (l-carrybits); + } + } + while (carrybits > 0) { + if (!(i < N)) + cl_abort(); + x[i] = (fftcs_real)(carry & l_mask); + carry >>= l; + carrybits -= l; + i++; + } + if (len > 0) + cl_abort(); + } + for ( ; i < N; i++) + x[i] = (fftcs_real)0; +} + +// Given a not too large floating point number, round it to the nearest integer. +static inline fftcs_real fftcs_fround (fftcs_real x) +{ + return + #if (fftcs_real_rounds == rounds_to_nearest) + (x + (fftcs_pow2(fftcs_real_mant_bits-1)+fftcs_pow2(fftcs_real_mant_bits-2))) + - (fftcs_pow2(fftcs_real_mant_bits-1)+fftcs_pow2(fftcs_real_mant_bits-2)); + #elif (fftcs_real_rounds == rounds_to_infinity) + (fftcs_pow2(fftcs_real_mant_bits-1)+fftcs_pow2(fftcs_real_mant_bits-2)) + - ((fftcs_pow2(fftcs_real_mant_bits-1)+fftcs_pow2(fftcs_real_mant_bits-2)) + - (x + (fftcs_real)0.5)); + #else // rounds_to_zero, rounds_to_minus_infinity + ((x + (fftcs_real)0.5) + + (fftcs_pow2(fftcs_real_mant_bits-1)+fftcs_pow2(fftcs_real_mant_bits-2))) + - (fftcs_pow2(fftcs_real_mant_bits-1)+fftcs_pow2(fftcs_real_mant_bits-2)); + #endif +} + +// Given a not too large floating point number, round it down. +static inline fftcs_real fftcs_ffloor (fftcs_real x) +{ + #if (fftcs_real_rounds == rounds_to_nearest) + var fftcs_real y = + (x + (fftcs_pow2(fftcs_real_mant_bits-1)+fftcs_pow2(fftcs_real_mant_bits-2))) + - (fftcs_pow2(fftcs_real_mant_bits-1)+fftcs_pow2(fftcs_real_mant_bits-2)); + if (y <= x) + return y; + else + return y - (fftcs_real)1.0; + #elif (fftcs_real_rounds == rounds_to_infinity) + return + (fftcs_pow2(fftcs_real_mant_bits-1)+fftcs_pow2(fftcs_real_mant_bits-2)) + - ((fftcs_pow2(fftcs_real_mant_bits-1)+fftcs_pow2(fftcs_real_mant_bits-2)) + - x); + #else // rounds_to_zero, rounds_to_minus_infinity + return + (x + (fftcs_pow2(fftcs_real_mant_bits-1)+fftcs_pow2(fftcs_real_mant_bits-2))) + - (fftcs_pow2(fftcs_real_mant_bits-1)+fftcs_pow2(fftcs_real_mant_bits-2)); + #endif +} + +// Combine the N real numbers at z into uintD's below destptr. +// The z[i] are known to be approximately integers >= 0, < N*2^(2*l). +// Assumes room for floor(N*l/intDsize)+(1+ceiling((n+2*l)/intDsize)) uintD's +// below destptr. Fills len digits and returns (destptr lspop len). +static uintD* unfill_product (uintL n, uintL N, // N = 2^n + const fftcs_real * z, uintL l, + uintD* destptr) +{ + var uintL i; + if (n + 2*l <= intDsize) { + // 2-digit carry is sufficient, l < intDsize + var uintD carry0 = 0; + var uintD carry1 = 0; + var uintL shift = 0; // shift next digit before adding it to the carry, >=0, 0) { + carry1 += digit >> (intDsize-shift); + digit = digit << shift; + } + if ((carry0 += digit) < digit) + carry1 += 1; + shift += l; + if (shift >= intDsize) { + lsprefnext(destptr) = carry0; + carry0 = carry1; + carry1 = 0; + shift -= intDsize; + } + } + lsprefnext(destptr) = carry0; + lsprefnext(destptr) = carry1; + } else if (n + 2*l <= 2*intDsize) { + // 3-digit carry is sufficient, l < intDsize + #if HAVE_DD + var uintDD carry0 = 0; + var uintD carry1 = 0; + var uintL shift = 0; // shift next digit before adding it to the carry, >=0, 0) { + carry1 += (uintD)(digit >> (2*intDsize-shift)); + digit = digit << shift; + } + if ((carry0 += digit) < digit) + carry1 += 1; + shift += l; + if (shift >= intDsize) { + lsprefnext(destptr) = lowD(carry0); + carry0 = highlowDD(carry1,highD(carry0)); + carry1 = 0; + shift -= intDsize; + } + } + lsprefnext(destptr) = lowD(carry0); + lsprefnext(destptr) = highD(carry0); + lsprefnext(destptr) = carry1; + #else + var uintD carry0 = 0; + var uintD carry1 = 0; + var uintD carry2 = 0; + var uintL shift = 0; // shift next digit before adding it to the carry, >=0, 0) { + carry2 += digit1 >> (intDsize-shift); + digit1 = (digit1 << shift) | (digit0 >> (intDsize-shift)); + digit0 = digit0 << shift; + } + if ((carry0 += digit0) < digit0) + if ((carry1 += 1) == 0) + carry2 += 1; + if ((carry1 += digit1) < digit1) + carry2 += 1; + shift += l; + if (shift >= intDsize) { + lsprefnext(destptr) = carry0; + carry0 = carry1; + carry1 = carry2; + carry2 = 0; + shift -= intDsize; + } + } + lsprefnext(destptr) = carry0; + lsprefnext(destptr) = carry1; + lsprefnext(destptr) = carry2; + #endif + } else { + // 1-digit+1-float carry is sufficient + var uintD carry0 = 0; + var fftcs_real carry1 = 0; + var uintL shift = 0; // shift next digit before adding it to the carry, >=0, = (fftcs_real)0 + && z[i] > digit - (fftcs_real)0.5 + && z[i] < digit + (fftcs_real)0.5)) + cl_abort(); + #endif + if (shift > 0) + digit = digit * fftcs_pow2_table[shift]; + var fftcs_real digit1 = fftcs_ffloor(digit*((fftcs_real)1.0/fftcs_pow2(intDsize))); + var uintD digit0 = (uintD)(digit - digit1*fftcs_pow2(intDsize)); + carry1 += digit1; + if ((carry0 += digit0) < digit0) + carry1 += (fftcs_real)1.0; + shift += l; + while (shift >= intDsize) { + lsprefnext(destptr) = carry0; + var fftcs_real tmp = fftcs_ffloor(carry1*((fftcs_real)1.0/fftcs_pow2(intDsize))); + carry0 = (uintD)(carry1 - tmp*fftcs_pow2(intDsize)); + carry1 = tmp; + shift -= intDsize; + } + } + if (carry0 > 0 || carry1 > (fftcs_real)0.0) { + lsprefnext(destptr) = carry0; + while (carry1 > (fftcs_real)0.0) { + var fftcs_real tmp = fftcs_ffloor(carry1*((fftcs_real)1.0/fftcs_pow2(intDsize))); + lsprefnext(destptr) = (uintD)(carry1 - tmp*fftcs_pow2(intDsize)); + carry1 = tmp; + } + } + } + return destptr; +} + +static inline void mulu_fftcs_nocheck (const uintD* sourceptr1, uintC len1, + const uintD* sourceptr2, uintC len2, + uintD* destptr) +// Es ist 2 <= len1 <= len2. +{ + // We have to find parameters l and k such that + // ceiling(len1*intDsize/l) + ceiling(len2*intDsize/l) - 1 <= 2^k, + // and (12*k-15)*e*2^(2*l+2*k+1/2-m) < 1/2. + // Try primarily to minimize k. Minimizing l buys you nothing. + var uintL k; + // Computing k: If len1 and len2 differ much, we'll split source2 - + // hence for the moment just substitute len1 for len2. + // + // First approximation of k: A necessary condition for + // 2*ceiling(len1*intDsize/l) - 1 <= 2^k + // is 2*len1*intDsize/l_max - 1 <= 2^k. + { + var const int l = max_l(2); + var uintL lhs = 2*ceiling((uintL)len1*intDsize,l) - 1; // >=1 + if (lhs < 3) + k = 2; + else + integerlength32(lhs-1, k=); // k>=2 + } + // Try whether this k is ok or whether we have to increase k. + for ( ; ; k++) { + if (k >= sizeof(max_l_table)/sizeof(max_l_table[0]) + || max_l_table[k] <= 0) { + fprint(cl_stderr, "FFT problem: numbers too big, floating point precision not sufficient\n"); + cl_abort(); + } + if (2*ceiling((uintL)len1*intDsize,max_l_table[k])-1 <= ((uintL)1 << k)) + break; + } + // We could try to reduce l, keeping the same k. But why should we? + // Calculate the number of pieces in which source2 will have to be + // split. Each of the pieces must satisfy + // ceiling(len1*intDsize/l) + ceiling(len2*intDsize/l) - 1 <= 2^k, + var uintL len2p; + // Try once with k, once with k+1. Compare them. + { + var uintL remaining_k = ((uintL)1 << k) + 1 - ceiling((uintL)len1*intDsize,max_l_table[k]); + var uintL max_piecelen_k = floor(remaining_k*max_l_table[k],intDsize); + var uintL numpieces_k = ceiling(len2,max_piecelen_k); + var uintL remaining_k1 = ((uintL)1 << (k+1)) + 1 - ceiling((uintL)len1*intDsize,max_l_table[k+1]); + var uintL max_piecelen_k1 = floor(remaining_k1*max_l_table[k+1],intDsize); + var uintL numpieces_k1 = ceiling(len2,max_piecelen_k1); + if (numpieces_k <= 2*numpieces_k1) { + // keep k + len2p = max_piecelen_k; + } else { + // choose k+1 + k = k+1; + len2p = max_piecelen_k1; + } + } + var const uintL l = max_l_table[k]; + var const uintL n = k; + var const uintL N = (uintL)1 << n; + CL_ALLOCA_STACK; + var fftcs_real* const x = cl_alloc_array(fftcs_real,N); + var fftcs_real* const y = cl_alloc_array(fftcs_real,N); + #ifdef DEBUG_FFTCS + var fftcs_real* const z = cl_alloc_array(fftcs_real,N); + #else + var fftcs_real* const z = x; // put z in place of x - saves memory + #endif + var uintD* const tmpprod1 = cl_alloc_array(uintD,len1+1); + var uintL tmpprod_len = floor(l< len2) + len2p = len2; + if (len2p == 1) { + // cheap case + var uintD* tmpptr = arrayLSDptr(tmpprod1,len1+1); + mulu_loop_lsp(lspref(sourceptr2,0),sourceptr1,tmpptr,len1); + if (addto_loop_lsp(tmpptr,destptr,len1+1)) + if (inc_loop_lsp(destptr lspop (len1+1),destlen-(len1+1))) + cl_abort(); + } else { + var bool squaring = ((sourceptr1 == sourceptr2) && (len1 == len2p)); + // Fill factor x. + fill_factor(N,x,l,sourceptr1,len1); + // Fill factor y. + if (!squaring) + fill_factor(N,y,l,sourceptr2,len2p); + // Multiply. + if (!squaring) + fftcs_convolution(n,N, &x[0], &y[0], &z[0]); + else + fftcs_convolution(n,N, &x[0], &x[0], &z[0]); + #ifdef DEBUG_FFTCS + // Check result. + { + var fftcs_real re_lo_limit = (fftcs_real)(-0.5); + var fftcs_real re_hi_limit = (fftcs_real)N * fftcs_pow2_table[l] * fftcs_pow2_table[l] + (fftcs_real)0.5; + for (var uintL i = 0; i < N; i++) + if (!(z[i] > re_lo_limit + && z[i] < re_hi_limit)) + cl_abort(); + } + #endif + var uintD* tmpLSDptr = arrayLSDptr(tmpprod,tmpprod_len); + var uintD* tmpMSDptr = unfill_product(n,N,z,l,tmpLSDptr); + var uintL tmplen = + #if CL_DS_BIG_ENDIAN_P + tmpLSDptr - tmpMSDptr; + #else + tmpMSDptr - tmpLSDptr; + #endif + if (tmplen > tmpprod_len) + cl_abort(); + // Add result to destptr[-destlen..-1]: + if (tmplen > destlen) { + if (test_loop_msp(tmpMSDptr,tmplen-destlen)) + cl_abort(); + tmplen = destlen; + } + if (addto_loop_lsp(tmpLSDptr,destptr,tmplen)) + if (inc_loop_lsp(destptr lspop tmplen,destlen-tmplen)) + cl_abort(); + } + // Decrement len2. + destptr = destptr lspop len2p; + destlen -= len2p; + sourceptr2 = sourceptr2 lspop len2p; + len2 -= len2p; + } while (len2 > 0); +} + +#ifndef _CHECKSUM +#define _CHECKSUM + +// Compute a checksum: number mod (2^intDsize-1). +static uintD compute_checksum (const uintD* sourceptr, uintC len) +{ + var uintD tmp = ~(uintD)0; // -1-(sum mod 2^intDsize-1), always >0 + do { + var uintD digit = lsprefnext(sourceptr); + if (digit < tmp) + tmp -= digit; // subtract digit + else + tmp -= digit+1; // subtract digit-(2^intDsize-1) + } while (--len > 0); + return ~tmp; +} + +// Multiply two checksums modulo (2^intDsize-1). +static inline uintD multiply_checksum (uintD checksum1, uintD checksum2) +{ + var uintD checksum; + var uintD cksum_hi; + #if HAVE_DD + var uintDD cksum = muluD(checksum1,checksum2); + cksum_hi = highD(cksum); checksum = lowD(cksum); + #else + muluD(checksum1,checksum2, cksum_hi =, checksum =); + #endif + if ((checksum += cksum_hi) + 1 <= cksum_hi) + checksum += 1; + return checksum; +} + +#endif // _CHECKSUM + +static void mulu_fftcs (const uintD* sourceptr1, uintC len1, + const uintD* sourceptr2, uintC len2, + uintD* destptr) +{ + // Compute checksums of the arguments and multiply them. + var uintD checksum1 = compute_checksum(sourceptr1,len1); + var uintD checksum2 = compute_checksum(sourceptr2,len2); + var uintD checksum = multiply_checksum(checksum1,checksum2); + mulu_fftcs_nocheck(sourceptr1,len1,sourceptr2,len2,destptr); + if (!(checksum == compute_checksum(destptr,len1+len2))) { + fprint(cl_stderr, "FFT problem: checksum error\n"); + cl_abort(); + } +} diff --git a/src/base/digitseq/cl_DS_mul_fftm.h b/src/base/digitseq/cl_DS_mul_fftm.h new file mode 100644 index 0000000..04714f1 --- /dev/null +++ b/src/base/digitseq/cl_DS_mul_fftm.h @@ -0,0 +1,654 @@ +// Fast integer multiplication using FFT in a modular ring. +// Bruno Haible 14.5.,16.5.1996 + +// FFT in the complex domain has the drawback that it needs careful round-off +// error analysis. So here we choose another field of characteristic 0: Q_p. +// Since Q_p contains exactly the (p-1)th roots of unity, we choose +// p == 1 mod N and have the Nth roots of unity (N = 2^n) in Q_p and +// even in Z_p. Actually, we compute in Z/(p^m Z). + +// All operations the FFT algorithm needs is addition, subtraction, +// multiplication, multiplication by the Nth root and unity and division +// by N. Hence we can use the domain Z/(p^m Z) even if p is not a prime! + +// We use the Schönhage-Strassen choice of the modulus: p = 2^R+1. This +// has two big advantages: Multiplication and division by 2 (which is a +// (2R)th root of unity) or a power of 2 is just a shift and an subtraction. +// And multiplication mod p is just a normal multiplication, followed by +// a subtraction. +// In order to exploit the (2R)th root of unity for FFT, we choose R = 2^r, +// and do an FFT of size M with M = 2^m and M | 2R. + +// Say we want to compute the product of two integers with N1 and N2 bits, +// respectively. We choose N >= N1+N2 and K, R, M with +// ceiling(N1/K)+ceiling(N2/K)-1 <= M (i.e. roughly N <= K*M), +// 2*K+ceiling(log2(M)) <= R, +// R = 2^r, M = 2^m, M | 2R. +// We then split each of the factors in M K-bit chunks each, and do +// an FFT mod p = 2^R+1. We then recover the convolution of the chunks +// from the FFT product (the first inequality ensures that this is possible). +// The second inequality ensures that we have no overflow, i.e. the +// convolution result is valid in Z, not only in Z/pZ. + +// The computation time (bit complexity) will be proportional to +// Mul(N) = O(M log(M) * O(2R)) + M * Mul(R+1). +// Hence we try to choose R as small as possible. +// Roughly, R >= 2*K, R >= M/2, hence R^2 >= K*M >= N. + +// For example, when N1 = N2 = 1000000: +// Choosing R = 1024, M = 2048, K = 506, ceiling(N1/K) = ceiling(N2/K) = 1977, +// M >= 3953, doesn't work. +// Choosing R = 2048, M = 4096, K = 1018, ceiling(N1/K) = ceiling(N2/K) = 983, +// M >= 1965, works. +// Actually, we will also want intDsize | K, so that splitting into chunks +// and putting together the result can be done without shifts. So +// choose R = 2048, M = 4096, K = 992, ceiling(N1/K) = ceiling(N2/K) = 1009. +// We see that M = 2048 suffices. + +// In contrast to Nussbaumer multiplication, here we can use the standard +// Karatsuba algorithm for multiplication mod p = 2^R+1. We don't have to +// recurse until N=1. + + +// Define this for (cheap) consistency checks. +//#define DEBUG_FFTM + + +// Operations modulo p = 2^R+1, each chunk represented as chlen words +// (chlen = floor(R/intDsize)+1). + +static inline void assign (const uintL R, const uintL chlen, + const uintD* a, uintD* r) +{ + unused R; + copy_loop_lsp(a,r,chlen); +} + +// r := (a + b) mod p +static void addm (const uintL R, const uintL chlen, + const uintD* a, const uintD* b, uintD* r) +{ + unused R; + // r := a+b. + add_loop_lsp(a,b, r, chlen); +#if 0 + if (lspref(r,chlen-1) < ((uintD)1 << (R % intDsize))) + return; + if (lspref(r,chlen-1) == ((uintD)1 << (R % intDsize))) + if (!DS_test_loop(r lspop (chlen-1),chlen-1,r)) + return; + // r >= p, so subtract r := r-p. + lspref(r,chlen-1) -= ((uintD)1 << (R % intDsize)); + dec_loop_lsp(r,chlen); +#else + if (lspref(r,chlen-1) < 1) + return; + if (lspref(r,chlen-1) == 1) + if (!DS_test_loop(r lspop (chlen-1),chlen-1,r)) + return; + // r >= p, so subtract r := r-p. + lspref(r,chlen-1) -= 1; + dec_loop_lsp(r,chlen); +#endif +} + +// r := (a - b) mod p +static void subm (const uintL R, const uintL chlen, + const uintD* a, const uintD* b, uintD* r) +{ + unused R; + // r := a-b. + sub_loop_lsp(a,b, r, chlen); +#if 0 + if ((sintD)lspref(r,chlen-1) >= 0) + return; + // r < 0, so add r := r+p. + lspref(r,chlen-1) += ((uintD)1 << (R % intDsize)); + inc_loop_lsp(r,chlen); +#else + if ((sintD)lspref(r,chlen-1) >= 0) + return; + // r < 0, so add r := r+p. + lspref(r,chlen-1) += 1; + inc_loop_lsp(r,chlen); +#endif +} + +// r := (a << s) mod p (0 <= s < R). +// Assume that a and r don't overlap. +static void shiftleftm (const uintL R, const uintL chlen, + const uintD* a, uintL s, uintD* r) +{ + // Write a = 2^(R-s)*b + c, then + // a << s = 2^R*b + (c << s) = (c << s) - b. +#if 0 + if (chlen == 1) { + // R < intDsize. + var uintD b = lspref(a,0) >> (R-s); + var uintD c = lspref(a,0) & (((uintD)1 << (R-s)) - 1); + c = c << s; + c -= b; + if ((sintD)c < 0) + c += ((uintD)1 << R) + 1; + lspref(r,0) = c; + return; + } +#endif + // Here R >= intDsize, hence intDsize | R. + if ((s % intDsize) == 0) { + var uintP lenb = s/intDsize; + var uintP lenc = (R-s)/intDsize; + // chlen = 1 + lenb + lenc. + lspref(r,lenb+lenc) = 0; + copy_loop_lsp(a,r lspop lenb,lenc); + copy_loop_lsp(a lspop lenc,r,lenb); + if ((lspref(a,lenb+lenc) > 0) || neg_loop_lsp(r,lenb)) // -b gives carry? + if (dec_loop_lsp(r lspop lenb,lenc)) + // add p = 2^R+1 to compensate with carry + inc_loop_lsp(r,chlen); + } else { + var uintP lenb = floor(s,intDsize); + var uintP lenc = floor(R-s,intDsize)+1; + // chlen = 1 + lenb + lenc. + s = s % intDsize; + lspref(r,lenb+lenc) = 0; + var uintD b0 = shiftleftcopy_loop_lsp(a,r lspop lenb,lenc,s); + var uintD bov; + if (lenb == 0) + bov = b0; + else { + bov = shiftleftcopy_loop_lsp(a lspop lenc,r,lenb,s); + lspref(r,0) |= b0; + } + bov |= lspref(a,lenb+lenc) << s; + if (neg_loop_lsp(r,lenb)) + bov++; + if (lspref(r,lenb) >= bov) + lspref(r,lenb) -= bov; + else { + lspref(r,lenb) -= bov; + if (dec_loop_lsp(r lspop (lenb+1),lenc-1)) + // add p = 2^R+1 to compensate with carry + inc_loop_lsp(r,chlen); + } + } +} + +// r := (a * b) mod p +static void mulm (const uintL R, const uintL chlen, + const uintD* a, const uintD* b, uintD* r) +{ + unused R; + // The leading digits are very likely to be 0. + var uintP a_len = chlen; + if (lspref(a,a_len-1) == 0) + do { + a_len--; + } while ((a_len > 0) && (lspref(a,a_len-1) == 0)); + if (a_len == 0) { + clear_loop_lsp(r,chlen); + return; + } + var uintP b_len = chlen; + if (lspref(b,b_len-1) == 0) + do { + b_len--; + } while ((b_len > 0) && (lspref(b,b_len-1) == 0)); + if (b_len == 0) { + clear_loop_lsp(r,chlen); + return; + } + CL_SMALL_ALLOCA_STACK; + var uintD* tmp = cl_small_alloc_array(uintD,2*chlen); + cl_UDS_mul(a,a_len, b,b_len, arrayLSDptr(tmp,2*chlen)); + DS_clear_loop(arrayMSDptr(tmp,2*chlen),2*chlen-(a_len+b_len),arrayLSDptr(tmp,2*chlen) lspop (a_len+b_len)); + // To divide c (0 <= c < p^2) by p = 2^R+1, + // we set q := floor(c/2^R) and r := c - q*p = (c mod 2^R) - q. + // If this becomes negative, set r := r + p (at most twice). + // (This works because floor(c/p) <= q <= floor(c/p)+2.) + // (Actually, here, 0 <= c <= (p-1)^2, hence + // floor(c/p) <= q <= floor(c/p)+1, so we have + // to set r := r + p at most once!) +#if 0 + if (chlen == 1) { + // R < intDsize. + var uintD r0 = (arrayLSref(tmp,2,0) & (((uintD)1 << R) - 1)) + - ((arrayLSref(tmp,2,1) << (intDsize-R)) | (arrayLSref(tmp,2,0) >> R)); + if ((sintD)r0 < 0) + r0 += ((uintD)1 << R) + 1; + lspref(r,0) = r0; + return; + } +#endif + // Here R >= intDsize, hence intDsize | R. + // R/intDsize = chlen-1. + // arrayLSref(tmp,2*chlen,2*chlen-1) = 0, arrayLSref(tmp,2*chlen,2*chlen-2) <= 1. + lspref(r,chlen-1) = 0; + if (sub_loop_lsp(arrayLSDptr(tmp,2*chlen),arrayLSDptr(tmp,2*chlen) lspop (chlen-1),r,chlen-1) || arrayLSref(tmp,2*chlen,2*chlen-2)) + // add p = 2^R+1 to compensate with carry + inc_loop_lsp(r,chlen); +} + +// b := (a / 2) mod p +static void shiftm (const uintL R, const uintL chlen, + const uintD* a, uintD* b) +{ + unused R; + shiftrightcopy_loop_msp(a lspop chlen,b lspop chlen,chlen,1,0); + if (lspref(a,0) & 1) { + // ((a + p) >> 1) = (a >> 1) + (p>>1) + 1. +#if 0 + if (chlen == 1) + // R < intDsize. + lspref(b,0) |= ((uintD)1 << (R-1)); + else +#endif + // intDsize | R. + lspref(b,chlen-2) |= ((uintD)1 << (intDsize-1)); + inc_loop_lsp(b,chlen); + } +} + + +#ifndef _BIT_REVERSE +#define _BIT_REVERSE +// Reverse an n-bit number x. n>0. +static uintL bit_reverse (uintL n, uintL x) +{ + var uintL y = 0; + do { + y <<= 1; + y |= (x & 1); + x >>= 1; + } while (!(--n == 0)); + return y; +} +#endif + +static void mulu_fftm (const uintL r, const uintL R, // R = 2^r + const uintL m, const uintL M, // M = 2^m + const uintL k, // K = intDsize*k + const uintD* sourceptr1, uintC len1, + const uintD* sourceptr2, uintC len2, + uintD* destptr) +// Assume: +// ceiling(len1/k)+ceiling(len2/k)-1 <= M, +// 2*K+m <= R, +// R = 2^r, M = 2^m, M | 2R. +// m > 0. +{ + var const uintL chlen = floor(R,intDsize)+1; // chunk length (in words) + CL_ALLOCA_STACK; + var uintD* const arrX = cl_alloc_array(uintD,chlen<= k) { + copy_loop_lsp(sptr,ptr,k); + clear_loop_lsp(ptr lspop k,chlen-k); + sptr = sptr lspop k; + slen -= k; + } else { + copy_loop_lsp(sptr,ptr,slen); + clear_loop_lsp(ptr lspop slen,chlen-slen); + i++; + break; + } + } + // X(i) := ... := X(M-1) := 0 + clear_loop_up(&arrX[chlen*i],chlen*(M-i)); + } + if (!squaring) { + var const uintD* sptr = sourceptr2; + var uintL slen = len2; + for (i = 0; i < M; i++) { + var uintD* ptr = Y(i); + if (slen >= k) { + copy_loop_lsp(sptr,ptr,k); + clear_loop_lsp(ptr lspop k,chlen-k); + sptr = sptr lspop k; + slen -= k; + } else { + copy_loop_lsp(sptr,ptr,slen); + clear_loop_lsp(ptr lspop slen,chlen-slen); + i++; + break; + } + } + // Y(i) := ... := Y(M-1) := 0 + clear_loop_up(&arrY[chlen*i],chlen*(M-i)); + } + // Do an FFT of length M on X. w = 2^(2R/M) = 2^(2^(r+1-m)). + { + var sintL l; + /* l = m-1 */ { + var const uintL tmax = M>>1; // tmax = 2^(m-1) + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = t; + var uintL i2 = i1 + tmax; + // Butterfly: replace (X(i1),X(i2)) by + // (X(i1) + X(i2), X(i1) - X(i2)). + assign(R,chlen, X(i2), tmp); + subm(R,chlen, X(i1),tmp, X(i2)); + addm(R,chlen, X(i1),tmp, X(i1)); + } + } + for (l = m-2; l>=0; l--) { + var const uintL smax = (uintL)1 << (m-1-l); + var const uintL tmax = (uintL)1 << l; + for (var uintL s = 0; s < smax; s++) { + // w^exp = 2^(exp << (r+1-m)). + var uintL exp = bit_reverse(m-1-l,s) << (r-(m-1-l)); + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = (s << (l+1)) + t; + var uintL i2 = i1 + tmax; + // Butterfly: replace (X(i1),X(i2)) by + // (X(i1) + w^exp*X(i2), X(i1) - w^exp*X(i2)). + shiftleftm(R,chlen, X(i2),exp, tmp); + subm(R,chlen, X(i1),tmp, X(i2)); + addm(R,chlen, X(i1),tmp, X(i1)); + } + } + } + } + // Do an FFT of length M on Y. w = 2^(2R/M) = 2^(2^(r+1-m)). + if (!squaring) { + var sintL l; + /* l = m-1 */ { + var const uintL tmax = M>>1; // tmax = 2^(m-1) + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = t; + var uintL i2 = i1 + tmax; + // Butterfly: replace (Y(i1),Y(i2)) by + // (Y(i1) + Y(i2), Y(i1) - Y(i2)). + assign(R,chlen, Y(i2), tmp); + subm(R,chlen, Y(i1),tmp, Y(i2)); + addm(R,chlen, Y(i1),tmp, Y(i1)); + } + } + for (l = m-2; l>=0; l--) { + var const uintL smax = (uintL)1 << (m-1-l); + var const uintL tmax = (uintL)1 << l; + for (var uintL s = 0; s < smax; s++) { + // w^exp = 2^(exp << (r+1-m)). + var uintL exp = bit_reverse(m-1-l,s) << (r-(m-1-l)); + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = (s << (l+1)) + t; + var uintL i2 = i1 + tmax; + // Butterfly: replace (Y(i1),Y(i2)) by + // (Y(i1) + w^exp*Y(i2), Y(i1) - w^exp*Y(i2)). + shiftleftm(R,chlen, Y(i2),exp, tmp); + subm(R,chlen, Y(i1),tmp, Y(i2)); + addm(R,chlen, Y(i1),tmp, Y(i1)); + } + } + } + } + // Multiply the transformed vectors into Z. + if (!squaring) { + for (i = 0; i < M; i++) + mulm(R,chlen, X(i),Y(i),Z(i)); + } else { + for (i = 0; i < M; i++) + mulm(R,chlen, X(i),X(i),Z(i)); + } + // Undo an FFT of length M on Z. w = 2^(2R/M) = 2^(2^(r+1-m)). + { + var uintL l; + for (l = 0; l < m-1; l++) { + var const uintL smax = (uintL)1 << (m-1-l); + var const uintL tmax = (uintL)1 << l; + /* s = 0, exp = 0 */ { + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = t; + var uintL i2 = i1 + tmax; + // Inverse Butterfly: replace (Z(i1),Z(i2)) by + // ((Z(i1)+Z(i2))/2, (Z(i1)-Z(i2))/(2*w^exp)), + // with exp <-- 0. + addm(R,chlen, Z(i1),Z(i2), sum); + subm(R,chlen, Z(i1),Z(i2), diff); + shiftm(R,chlen, sum, Z(i1)); + shiftm(R,chlen, diff, Z(i2)); + } + } + for (var uintL s = 1; s < smax; s++) { + // w^exp = 2^(exp << (r+1-m)). + var uintL exp = bit_reverse(m-1-l,s) << (r-(m-1-l)); + exp = R - exp; // negate exp (use w^-1 instead of w) + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = (s << (l+1)) + t; + var uintL i2 = i1 + tmax; + // Inverse Butterfly: replace (Z(i1),Z(i2)) by + // ((Z(i1)+Z(i2))/2, (Z(i1)-Z(i2))/(2*w^exp)), + // with exp <-- (M/2 - exp). + addm(R,chlen, Z(i1),Z(i2), sum); + subm(R,chlen, Z(i2),Z(i1), diff); // note that w^(M/2) = 2^R = -1 + shiftm(R,chlen, sum, Z(i1)); + shiftleftm(R,chlen, diff,exp-1, Z(i2)); + } + } + } + /* l = m-1 */ { + var const uintL tmax = M>>1; // tmax = 2^(m-1) + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = t; + var uintL i2 = i1 + tmax; + // Inverse Butterfly: replace (Z(i1),Z(i2)) by + // ((Z(i1)+Z(i2))/2, (Z(i1)-Z(i2))/2). + addm(R,chlen, Z(i1),Z(i2), sum); + subm(R,chlen, Z(i1),Z(i2), diff); + shiftm(R,chlen, sum, Z(i1)); + shiftm(R,chlen, diff, Z(i2)); + } + } + } + var uintC zchlen = 2*k + ceiling(m,intDsize); + #ifdef DEBUG_FFTM + // Check that every Z(i) has at most 2*K+m bits. + { + var uintC zerodigits = chlen - zchlen; + for (i = 0; i < M; i++) + if (DS_test_loop(Z(i) lspop chlen,zerodigits,Z(i) lspop zchlen)) + cl_abort(); + } + #endif + // Put together result. + var uintC destlen = len1+len2; + clear_loop_lsp(destptr,destlen); + for (i = 0; i < M; i++, destptr = destptr lspop k, destlen -= k) { + if (zchlen <= destlen) { + if (addto_loop_lsp(Z(i),destptr,zchlen)) + if (inc_loop_lsp(destptr lspop zchlen,destlen-zchlen)) + cl_abort(); + } else { + #ifdef DEBUG_FFTM + if (DS_test_loop(Z(i) lspop zchlen,zchlen-destlen,Z(i) lspop destlen)) + cl_abort(); + #endif + if (addto_loop_lsp(Z(i),destptr,destlen)) + cl_abort(); + } + if (destlen <= k) { + i++; + break; + } + } + #ifdef DEBUG_FFTM + // Check that Z(i)..Z(M-1) are all zero. + if (test_loop_up(&arrZ[chlen*i],chlen*(M-i))) + cl_abort(); + #endif + #undef diff + #undef sum + #undef tmp + #undef Z + #undef Y + #undef X +} + +// The running time of mulu_fftm() is roughly +// O(M log(M) * O(2R)) + M * R^(1+c), where c = log3/log2 - 1 = 0.585... +// Try to minimize this given the constraints +// ceiling(len1/k)+ceiling(len2/k)-1 <= M, +// K = intDsize*k, 2*K+m <= R, +// R = 2^r, M = 2^m, M | 2R. +// m > 0. +// Necessary conditions: +// len1+len2 <= k*(M+1), intDsize*(len1+len2) <= K*(M+1) <= (R-1)/2 * (2*R+1) < R^2. +// 2*intDsize+1 <= R, log2_intDsize+1 < r. +// So we start with len1 <= len2, +// r := max(log2_intDsize+2,ceiling(ceiling(log2(intDsize*2*len1))/2)), R := 2^r. +// try +// kmax := floor((R-(r+1))/(2*intDsize)), Kmax := intDsize*kmax, +// m := max(1,ceiling(log2(2*ceiling(len1/kmax)-1))), M := 2^m, +// if m > r+1 retry with r <- r+1. +// [Now we are sure that we can at least multiply len1 and len1 digits using these +// values of r and m, symbolically (r,m) OKFOR (len1,len1).] +// [Normally, we will have m=r+1 or m=r.] +// For (len1,len2), we might want to split the second integer into pieces. +// If (r,m) OKFOR (len1,len2) +// If (r-1,m) OKFOR (len1,ceiling(len2/2)) +// then use (r-1,m) and two pieces +// else use (r,m) and one piece +// else +// q1 := number of pieces len2 needs to be splitted into to be OKFOR (r,m), +// If m= log2_intDsize+2, R >= 4*intDsize, so chlen >= 5. +// To avoid infinite recursion, mulu_fft_modm() must only be called with len1 > 5. + +static bool okfor (uintL r, uintL m, uintC len1, uintC len2) +{ + var uintL R = (uintL)1 << r; + var uintL M = (uintL)1 << m; + var uintL k = floor(R-m,2*intDsize); + return (ceiling(len1,k)+ceiling(len2,k) <= M+1); +} + +static uintL numpieces (uintL r, uintL m, uintC len1, uintC len2) +{ + var uintL R = (uintL)1 << r; + var uintL M = (uintL)1 << m; + var uintL k = floor(R-m,2*intDsize); + var uintL piecelen2 = (M+1-ceiling(len1,k))*k; + #ifdef DEBUG_FFTM + if ((sintL)piecelen2 <= 0) + cl_abort(); + #endif + return ceiling(len2,piecelen2); +} + +static void mulu_fft_modm (const uintD* sourceptr1, uintC len1, + const uintD* sourceptr2, uintC len2, + uintD* destptr) + // Called only with 6 <= len1 <= len2. + { + var uint32 n; + integerlength32(len1-1, n=); // 2^(n-1) < len1 <= 2^n + var uintL r; + var uintL m; + r = ceiling(log2_intDsize+1+n,2); + if (r < log2_intDsize+2) + r = log2_intDsize+2; + retry: { + var uintL k = floor(((uintL)1 << r) - (r+1), 2*intDsize); + var uintL M = 2*ceiling(len1,k)-1; + integerlength32(M, m=); + if (m == 0) + m = 1; + if (m > r+1) { + r++; + goto retry; + } + } + #ifdef DEBUG_FFTM + if (!(m > 0 && m <= r+1 && okfor(r,m,len1,len1))) + cl_abort(); + #endif + if (okfor(r,m,len1,len2)) { + if ((m <= r) && (r > log2_intDsize+2) && okfor(r-1,m,len1,ceiling(len2,2))) + if (!(sourceptr1 == sourceptr2 && len1 == len2)) // when squaring, keep one piece + r--; + } else { + var uintL q1 = numpieces(r,m,len1,len2); + if (m <= r) { + var uintL q2 = numpieces(r,m+1,len1,len2); + if (2*q2 <= q1) + m++; + } else { + var uintL q2 = numpieces(r+1,m,len1,len2); + if (3*q2 <= q1) + r++; + } + } + var uintL R = (uintL)1 << r; + var uintL M = (uintL)1 << m; + var uintL k = floor(R-m,2*intDsize); + var uintL piecelen2 = (M+1-ceiling(len1,k))*k; + if (piecelen2 >= len2) { + // One piece only. + mulu_fftm(r,R, m,M, k, sourceptr1,len1, sourceptr2,len2, destptr); + return; + } + CL_ALLOCA_STACK; + var uintD* tmpptr; + num_stack_alloc(len1+piecelen2,,tmpptr=); + var uintL destlen = len1+len2; + clear_loop_lsp(destptr,destlen); + do { + var uintL len2p; // length of a piece of source2 + len2p = piecelen2; + if (len2p > len2) + len2p = len2; + // len2p = min(piecelen2,len2). + var uintL destlenp = len1 + len2p; + // destlenp = min(len1+piecelen2,destlen). + // Use tmpptr[-destlenp..-1]. + if (len2p == 1) { + // cheap case + mulu_loop_lsp(lspref(sourceptr2,0),sourceptr1,tmpptr,len1); + } else if (2*len2p < piecelen2) { + // semi-cheap case + cl_UDS_mul(sourceptr1,len1, sourceptr2,len2p, tmpptr); + } else { + mulu_fftm(r,R, m,M, k, sourceptr1,len1, sourceptr2,len2p, tmpptr); + } + if (addto_loop_lsp(tmpptr,destptr,destlenp)) + if (inc_loop_lsp(destptr lspop destlenp,destlen-destlenp)) + cl_abort(); + // Decrement len2. + destptr = destptr lspop len2p; + destlen -= len2p; + sourceptr2 = sourceptr2 lspop len2p; + len2 -= len2p; + } while (len2 > 0); +} diff --git a/src/base/digitseq/cl_DS_mul_fftp.h b/src/base/digitseq/cl_DS_mul_fftp.h new file mode 100644 index 0000000..5cf41b6 --- /dev/null +++ b/src/base/digitseq/cl_DS_mul_fftp.h @@ -0,0 +1,823 @@ +// Fast integer multiplication using FFT in a modular ring. +// Bruno Haible 5.5.1996 + +// FFT in the complex domain has the drawback that it needs careful round-off +// error analysis. So here we choose another field of characteristic 0: Q_p. +// Since Q_p contains exactly the (p-1)th roots of unity, we choose +// p == 1 mod N and have the Nth roots of unity (N = 2^n) in Q_p and +// even in Z_p. Actually, we compute in Z/(p^m Z). + +// All operations the FFT algorithm needs is addition, subtraction, +// multiplication, multiplication by the Nth root of unity and division +// by N. Hence we can use the domain Z/(p^m Z) even if p is not a prime! + +// We want to compute the convolution of N 32-bit words. The resulting +// words are < (2^32)^2 * N. If is safe to compute in Z/pZ with p = 2^94 + 1 +// or p = 7*2^92 + 1. We choose p < 2^95 so that we can easily represent every +// element of Z/pZ as three 32-bit words. + +#if !(intDsize==32) +#error "fft mod p implemented only for intDsize==32" +#endif + +#if 0 +typedef union { + #if CL_DS_BIG_ENDIAN_P + struct { uint32 w2; uint32 w1; uint32 w0; }; + #else + struct { uint32 w0; uint32 w1; uint32 w2; }; + #endif + uintD _w[3]; +} fftp_word; +#else +// typedef struct { uint32 w2; uint32 w1; uint32 w0; } fftp_word; +// typedef struct { uint32 w0; uint32 w1; uint32 w2; } fftp_word; +typedef struct { uintD _w[3]; } fftp_word; +#endif +#if CL_DS_BIG_ENDIAN_P + #define w2 _w[0] + #define w1 _w[1] + #define w0 _w[2] + #define W3(W2,W1,W0) { W2, W1, W0 } +#else + #define w0 _w[0] + #define w1 _w[1] + #define w2 _w[2] + #define W3(W2,W1,W0) { W0, W1, W2 } +#endif + +#if 0 +// p = 19807040628566084398385987585 = 5 * 3761 * 7484047069 * 140737471578113 +static const fftp_word p = W3( 1L<<30, 0, 1 ); // p = 2^94 + 1 +#define FFT_P_94 +static const fftp_word fftp_roots_of_1 [24+1] = + // roots_of_1[n] is a (2^n)th root of unity in Z/pZ. + // (Also roots_of_1[n-1] = roots_of_1[n]^2, but we don't need this.) + // (To build this table, you need to compute roots of unity modulo the + // factors of p and combine them using the Chinese Remainder Theorem. + // Or ask me for "quadmod.lsp".) + { + W3( 0x00000000, 0x00000000, 0x00000001 ), // 1 + W3( 0x0000003F, 0xFFFFFFFF, 0xFF800000 ), // 1180591620717402914816 + W3( 0x20000040, 0x00004000, 0x00000001 ), // 9903521494874733285348474881 + W3( 0x3688E9A7, 0xDD78E2A9, 0x1E75974D ), // 16877707849775746711303853901 + W3( 0x286E6589, 0x5E86C1E0, 0x42710379 ), // 12512861726041464545960067961 + W3( 0x00D79325, 0x1A884885, 0xEA46D6C5 ), // 260613923531515619478787781 + W3( 0x1950B480, 0xC387CEE5, 0xA69C443F ), // 7834691712342412468047070271 + W3( 0x19DC9D08, 0x11CADC6A, 0x5BA8B123 ), // 8003830486242687653832601891 + W3( 0x21D6D905, 0xB8BAC7C3, 0xC3841613 ), // 10472740308573592285123712531 + W3( 0x27D73986, 0x6AF6BD27, 0x7A6D7909 ), // 12330106088710388189231937801 + W3( 0x20D4698B, 0x0039D457, 0xA092AECF ), // 10160311000635748689099534031 + W3( 0x049BD1C4, 0xA94F001A, 0xFA76E358 ), // 1426314143682376031341568856 + W3( 0x26DD7228, 0x09400257, 0x9BB49CB9 ), // 12028142067661291067236719801 + W3( 0x12DAA9AD, 0xAF9435A9, 0xD50FF483 ), // 5835077289334326375656453251 + W3( 0x0B7CDA03, 0x9418702E, 0x7CD934CA ), // 3555271451571910239441204426 + W3( 0x2D272FCF, 0xB8644522, 0x68EAD40B ), // 13974199331913037576372147211 + W3( 0x00EDA06E, 0x0114DA26, 0xE8D84BA9 ), // 287273027105701319912475561 + W3( 0x2219C2C4, 0xFD3145C6, 0xDD019359 ), // 10553633252320053510122083161 + W3( 0x1764F007, 0x4F5D5FD4, 0xDAB10AFC ), // 7240181310654329198595869436 + W3( 0x01AA13EE, 0x2D1CD906, 0x11D5B1EB ), // 515096517694807745704079851 + W3( 0x27038944, 0x5A37BAAD, 0x5CECA64C ), // 12074190385578921562318087756 + W3( 0x2459CF22, 0xF625FD38, 0xADB48511 ), // 11250032926302238120667809041 + W3( 0x25B6C6A8, 0xD684063F, 0x7ABAD1EF ), // 11671908005633729316324561391 + W3( 0x1C1A2BC6, 0x12B253F1, 0x0D1BBCB7 ), // 8697219061868963805380983991 + W3( 0x198F3FE2, 0x5EE9919F, 0x535E80D5 } // 7910303322630257758732976341 + }; +// Sadly, this p doesn't work because we don't find a (2^n)th root of unity w +// such that w^(2^(n-1)) = -1 mod p. However, our algorithm below assumes +// that w^(2^(n-1)) = -1... +#else +// p = 34662321099990647697175478273, a prime +static const fftp_word p = W3( 7L<<28, 0, 1 ); // p = 7 * 2^92 + 1 +#define FFT_P_92 +static const fftp_word fftp_roots_of_1 [92+1] = + // roots_of_1[n] is a (2^n)th root of unity in Z/pZ. + // (Also roots_of_1[n-1] = roots_of_1[n]^2, but we don't need this.) + { + W3( 0x00000000, 0x00000000, 0x00000001 ), // 1 + W3( 0x70000000, 0x00000000, 0x00000000 ), // 34662321099990647697175478272 + W3( 0x064AF70F, 0x997E62CE, 0x77953100 ), // 1947537281862369253065568512 + W3( 0x261B8E96, 0xC3AD4296, 0xDA1BFA93 ), // 11793744727492885369350519443 + W3( 0x096EA949, 0x6EDCAF05, 0x47C92A4F ), // 2919146363086089454841571919 + W3( 0x366A8C3F, 0x7BF1436D, 0x2333BE9E ), // 16840998969615256469762195102 + W3( 0x27569FA8, 0xAE1775F1, 0xB21956A0 ), // 12174636971387721414084220576 + W3( 0x16CABB8B, 0xBAA59813, 0x62FCBCD9 ), // 7053758891710792545762852057 + W3( 0x1AE130A3, 0xF909B101, 0xB6BA30CF ), // 8318848263123793919933558991 + W3( 0x32AE8FEE, 0x6B1A656B, 0xED02BF24 ), // 15685283280129931240441823012 + W3( 0x2D1EE047, 0x5AEDC882, 0x8E96BCCC ), // 13964152342912072497719852236 + W3( 0x222A18FD, 0x3BF40635, 0xBFDEA8AD ), // 10573383226491471052459124909 + W3( 0x10534EE6, 0xED5A55D4, 0x06AE2155 ), // 5052473604609413010647032149 + W3( 0x02F3BFA3, 0x2D816786, 0xE6C27B3C ), // 913643975905572976593107772 + W3( 0x0B0CD0A5, 0x9A1FF4F7, 0x2624A5E1 ), // 3419827524917244902802499041 + W3( 0x257A492F, 0x156C141C, 0xFC5D75F4 ), // 11598779914676604137587439092 + W3( 0x061FB92A, 0xB1A1F41A, 0x7006920F ), // 1895261184698485907279745551 + W3( 0x2A4E1471, 0xDDB96073, 0xD8DDBB71 ), // 13092763174215078887900953457 + W3( 0x213B469E, 0xD72A84CA, 0xAAA477F2 ), // 10284665443205365583657072626 + W3( 0x1D7EF67C, 0x3DC2DA37, 0x4C86E9DC ), // 9128553932091860654576036316 + W3( 0x0CB7AA67, 0x2E087ED8, 0x2675D6E3 ), // 3935858248479385987820410595 + W3( 0x00BD7B24, 0x68388052, 0x57FFFB10 ), // 229068502577238003716979472 + W3( 0x1E1724A6, 0xBA587C3D, 0x0C12825B ), // 9312528669272006966417457755 + W3( 0x20595EF0, 0xC89DA33B, 0x3CB5583B ), // 10011563056352601486430394427 + W3( 0x15E730B2, 0x6D34E9EB, 0x71CCE555 ), // 6778677035560020292206912853 + W3( 0x015EFDBB, 0xC0A80C3B, 0xE4B1E017 ), // 424322259008787317821399063 + W3( 0x1B81FC63, 0x0C694944, 0x8EB481BF ), // 8513238559382277026756198847 + W3( 0x1AF53421, 0x5DCAA1A4, 0xD0C15A03 ), // 8343043259718611508685527555 + W3( 0x2F2B6B58, 0xBB60E464, 0x37A7DE2E ), // 14598286201875835624993840686 + W3( 0x27B4AB13, 0x54617640, 0xE86E757A ), // 12288329911800070034603013498 + W3( 0x041A31D2, 0xF0AC8E3C, 0x8AA4FD27 ), // 1269607397711669380834983207 + W3( 0x1A52F484, 0x39AC5917, 0x34E3F1F7 ), // 8146896869111203814625767927 + W3( 0x048FC120, 0x50F6ECBF, 0x268D86A8 ), // 1411728444351387120148776616 + W3( 0x27A2C427, 0x001F1239, 0x93380047 ), // 12266687669072434694473646151 + W3( 0x2E7E8DFB, 0x2411A754, 0xE12A9B1D ), // 14389305591459206001391737629 + W3( 0x29F14702, 0x40B3E1E2, 0xF7D71A8D ), // 12980571854778363745245010573 + W3( 0x3158DCE7, 0x8B8FEB32, 0x1DE35D24 ), // 15272194145252623177165790500 + W3( 0x12484C07, 0x437ED373, 0x9E45F602 ), // 5658131869639928287764805122 + W3( 0x1AEAE06E, 0xB905C908, 0x4389BF5F ), // 8330558749711089231534341983 + W3( 0x27BC0045, 0x43024FEB, 0xEC880258 ), // 12297194714773858676269122136 + W3( 0x2EFE1CBC, 0x0D2FAA94, 0xB4EA69A6 ), // 14543513305163560781242591654 + W3( 0x0B0D3D8B, 0xD779F105, 0x920367FA ), // 3420341787669373425792804858 + W3( 0x2D4D7BA9, 0x0970D8CF, 0x8CE6D7EC ), // 14020496699328277892009744364 + W3( 0x00DC5971, 0x0209470E, 0x713F2B27 ), // 266386055561000736260041511 + W3( 0x27E54E26, 0x53BA0137, 0xDD6740B3 ), // 12347128447319282384829366451 + W3( 0x2143A889, 0x8F2B57F5, 0xFB8181C1 ), // 10294799249108063706647986625 + W3( 0x1125419F, 0x5C4E0608, 0xE0AC0396 ), // 5306285315793562029414679446 + W3( 0x15B61D90, 0x63A27BB0, 0x26402B32 ), // 6719349317556695539371748146 + W3( 0x03B582FC, 0x419EF656, 0xB06BBC35 ), // 1147889163765050226454019125 + W3( 0x08FF62E1, 0xA3BB1145, 0xDA998F77 ), // 2784623116803271439773437815 + W3( 0x101978AF, 0xF93CBFA1, 0xB788B5A3 ), // 4982553232749484200897852835 + W3( 0x061334DE, 0x8FE5C6E9, 0x2B2309D6 ), // 1880129318103954373583505878 + W3( 0x343C6E7C, 0x8019BB43, 0xD954E744 ), // 16166277816826816936484857668 + W3( 0x06506A03, 0x0E6DE333, 0xF8011494 ), // 1954124751724394051182597268 + W3( 0x34892A42, 0x6502DAA3, 0x8FDA6971 ), // 16259042912153157504364865905 + W3( 0x0EF2C4BD, 0xF42D9711, 0xC32CEA49 ), // 4626279273705729025744104009 + W3( 0x24511305, 0x4F1EAE2C, 0x62FB10F4 ), // 11239473167855288013010178292 + W3( 0x14E5A052, 0xF1748A9C, 0xDD536730 ), // 6467301317787608309692589872 + W3( 0x0621D0A7, 0x0A5188AF, 0x7316C352 ), // 1897789944553576071437927250 + W3( 0x234498F0, 0xDF078E95, 0x6FEED50B ), // 10914904542475816633386325259 + W3( 0x029E4925, 0x948D6D57, 0xD4DF93A6 ), // 810325725128913871737688998 + W3( 0x11BB3805, 0x0589D746, 0x852F3E2F ), // 5487578840386649632552205871 + W3( 0x1D4370CA, 0xA4441B85, 0xC9606FE0 ), // 9056595957858187419376971744 + W3( 0x1C536F7D, 0x77D44926, 0x8DDB8932 ), // 8766447615182890705620797746 + W3( 0x3498CE71, 0xB726A4D3, 0xF4F3C813 ), // 16277952140466335672647796755 + W3( 0x1E4A297E, 0xAC13196E, 0xFACD8102 ), // 9374206759006667727054930178 + W3( 0x0E7C2CCC, 0xC940C98B, 0x0BC0CA49 ), // 4482908500893894680116251209 + W3( 0x124CF912, 0xD84438FD, 0x9C03585F ), // 5663784755954194195257972831 + W3( 0x06180FF8, 0xD447BEBE, 0xDB8821E7 ), // 1885999704184999223512015335 + W3( 0x1ED2EB11, 0x0687EC7C, 0xBE3436C8 ), // 9539534786948152514714023624 + W3( 0x30EBB35C, 0x59616A3C, 0x502CBB52 ), // 15140225046175435352009653074 + W3( 0x33E24883, 0xEDA36D60, 0xA25C8E5F ), // 16057295180155395438855097951 + W3( 0x0D879ED9, 0x076BAB06, 0x9BE12AA2 ), // 4187260250707927256570866338 + W3( 0x1A1B6C9C, 0x0966383B, 0x54123A87 ), // 8079764146434082816365050503 + W3( 0x31BD863A, 0xA2A6505C, 0xD759E6CF ), // 15393886339893077529104869071 + W3( 0x3209AF0A, 0x5E5055A1, 0x480AF03F ), // 15485957428841754012708171839 + W3( 0x1A4CC03C, 0xC8AA650B, 0x7F4DBCE9 ), // 8139396433274519652257348841 + W3( 0x3596471F, 0xB99D2EA3, 0xA3433E0C ), // 16584380266717730797139475980 + W3( 0x28E87642, 0x98E21FCE, 0xDE1B53EA ), // 12660429650750886812340409322 + W3( 0x20161DB9, 0xCDC199E9, 0x0A6BEDF2 ), // 9930257058416521571476434418 + W3( 0x1D0DC095, 0x2C40D22B, 0x088549BA ), // 8991690766592354745340742074 + W3( 0x2FCC953C, 0xA8B62408, 0x50FC4C29 ), // 14793121080372138443684989993 + W3( 0x0F854B39, 0xF659B4B5, 0xD2B0A6AC ), // 4803417528030967235217499820 + W3( 0x30E087D4, 0x02F3BBAB, 0xBA503373 ), // 15126721285415891216108630899 + W3( 0x0DAF660C, 0x26B99C42, 0x98B8BE05 ), // 4235349051642660841298902533 + W3( 0x0ED6AE0E, 0xCD02982A, 0xD233F0D9 ), // 4592322227691334993146278105 + W3( 0x3415EB9B, 0x4B61C19F, 0xB21F1255 ), // 16119720573722492095181034069 + W3( 0x1015A729, 0x20A1FAA2, 0x0D094529 ), // 4977936993224010619482096937 + W3( 0x1D2E3AD2, 0x7093579F, 0x1C93C97B ), // 9030953651705465548198627707 + W3( 0x130EAA8F, 0x859C980F, 0xD9E7E8ED ), // 5897945597894388791627999469 + W3( 0x2B7CA1C8, 0xFC34C5B5, 0x9C0B1C0C ), // 13458526232475976507763399692 + W3( 0x22367055, 0xA53B526A, 0x7505EABE ), // 10588302813110450634719881918 + W3( 0x344FEF55, 0x0B77067F, 0x38999E77 ) // 16189855864848287589134343799 + }; +#endif + +// Define this if you want the external loops instead of inline operations. +#define FFTP_EXTERNAL_LOOPS + +// Define this for (cheap) consistency checks. +//#define DEBUG_FFTP + +// Define this for extensive consistency checks. +//#define DEBUG_FFTP_OPERATIONS + +// Define the algorithm of the backward FFT: +// Either FORWARD (a normal FFT followed by a permutation) +// or RECIPROOT (an FFT with reciprocal root of unity) +// or CLEVER (an FFT with reciprocal root of unity but clever computation +// of the reciprocals). +// Drawback of FORWARD: the permutation pass. +// Drawback of RECIPROOT: need all the powers of the root, not only half of them. +#define FORWARD 42 +#define RECIPROOT 43 +#define CLEVER 44 +#define FFTP_BACKWARD CLEVER + +// r := a + b +static inline void add (const fftp_word& a, const fftp_word& b, fftp_word& r) +{ +#ifdef FFTP_EXTERNAL_LOOPS + add_loop_lsp(arrayLSDptr(a._w,3),arrayLSDptr(b._w,3),arrayLSDptr(r._w,3),3); +#else + var uint32 tmp; + + tmp = a.w0 + b.w0; + if (tmp >= a.w0) { + // no carry + r.w0 = tmp; + tmp = a.w1 + b.w1; + if (tmp >= a.w1) goto no_carry_1; else goto carry_1; + } else { + // carry + r.w0 = tmp; + tmp = a.w1 + b.w1 + 1; + if (tmp > a.w1) goto no_carry_1; else goto carry_1; + } + if (1) { + no_carry_1: // no carry + r.w1 = tmp; + tmp = a.w2 + b.w2; + } else { + carry_1: // carry + r.w1 = tmp; + tmp = a.w2 + b.w2 + 1; + } + r.w2 = tmp; +#endif +} + +// r := a - b +static inline void sub (const fftp_word& a, const fftp_word& b, fftp_word& r) +{ +#ifdef FFTP_EXTERNAL_LOOPS + sub_loop_lsp(arrayLSDptr(a._w,3),arrayLSDptr(b._w,3),arrayLSDptr(r._w,3),3); +#else + var uint32 tmp; + + tmp = a.w0 - b.w0; + if (tmp <= a.w0) { + // no carry + r.w0 = tmp; + tmp = a.w1 - b.w1; + if (tmp <= a.w1) goto no_carry_1; else goto carry_1; + } else { + // carry + r.w0 = tmp; + tmp = a.w1 - b.w1 - 1; + if (tmp < a.w1) goto no_carry_1; else goto carry_1; + } + if (1) { + no_carry_1: // no carry + r.w1 = tmp; + tmp = a.w2 - b.w2; + } else { + carry_1: // carry + r.w1 = tmp; + tmp = a.w2 - b.w2 - 1; + } + r.w2 = tmp; +#endif +} + +// b := a >> 1 +static inline void shift (const fftp_word& a, fftp_word& b) +{ +#ifdef FFTP_EXTERNAL_LOOPS + #ifdef DEBUG_FFTP + if (shiftrightcopy_loop_msp(arrayMSDptr(a._w,3),arrayMSDptr(b._w,3),3,1,0)) + cl_abort(); + #else + shiftrightcopy_loop_msp(arrayMSDptr(a._w,3),arrayMSDptr(b._w,3),3,1,0); + #endif +#else + var uint32 tmp, carry; + + tmp = a.w2; + b.w2 = a.w2 >> 1; + carry = tmp << 31; + tmp = a.w1; + b.w1 = (tmp >> 1) | carry; + carry = tmp << 31; + tmp = a.w0; + b.w0 = (tmp >> 1) | carry; + #ifdef DEBUG_FFTP + carry = tmp << 31; + if (carry) + cl_abort(); + #endif +#endif +} + +#ifdef DEBUG_FFTP_OPERATIONS +#define check_fftp_word(x) if (compare_loop_msp(arrayMSDptr((x)._w,3),arrayMSDptr(p._w,3),3) >= 0) cl_abort() +#else +#define check_fftp_word(x) +#endif + +// r := (a + b) mod p +static inline void addp (const fftp_word& a, const fftp_word& b, fftp_word& r) +{ + check_fftp_word(a); check_fftp_word(b); +#ifdef FFTP_EXTERNAL_LOOPS + add(a,b, r); + if (compare_loop_msp(arrayMSDptr(r._w,3),arrayMSDptr(p._w,3),3) >= 0) + sub(r,p, r); +#else + add(a,b, r); + if ((r.w2 > p.w2) + || ((r.w2 == p.w2) + && ((r.w1 > p.w1) + || ((r.w1 == p.w1) + && (r.w0 >= p.w0))))) + sub(r,p, r); +#endif + check_fftp_word(r); +} + +// r := (a - b) mod p +static inline void subp (const fftp_word& a, const fftp_word& b, fftp_word& r) +{ + check_fftp_word(a); check_fftp_word(b); + sub(a,b, r); + if ((sint32)r.w2 < 0) + add(r,p, r); + check_fftp_word(r); +} + +// r := (a * b) mod p +static void mulp (const fftp_word& a, const fftp_word& b, fftp_word& r) +{ + check_fftp_word(a); check_fftp_word(b); +#if defined(FFT_P_94) + var uintD c[6]; + var uintD* const cLSDptr = arrayLSDptr(c,6); + // Multiply the two words, using the standard method. + mulu_2loop(arrayLSDptr(a._w,3),3, arrayLSDptr(b._w,3),3, cLSDptr); + // c[0..5] now contains the product. + // Divide by p. + // To divide c (0 <= c < p^2) by p = 2^n+1, + // we set q := floor(c/2^n) and r := c - q*p = (c mod 2^n) - q. + // If this becomes negative, set r := r + p (at most twice). + // (This works because floor(c/p) <= q <= floor(c/p)+2.) + // (Actually, here, 0 <= c <= (p-1)^2, hence + // floor(c/p) <= q <= floor(c/p)+1, so we have + // to set r := r + p at most once!) + // n = 94 = 3*32-2 = 2*32+30. + shiftleft_loop_lsp(cLSDptr lspop 3,3,2,lspref(cLSDptr,2)>>30); + lspref(cLSDptr,2) &= bit(30)-1; + // c[0..2] now contains q, c[3..5] contains (c mod 2^n). + #if 0 + if (compare_loop_msp(cLSDptr lspop 6,arrayMSDptr(p._w,3),3) >= 0) // q >= p ? + subfrom_loop_lsp(arrayLSDptr(p._w,3),cLSDptr lspop 3,3); // q -= p; + #endif + if (subfrom_loop_lsp(cLSDptr lspop 3,cLSDptr,3)) // (c mod 2^n) - q + addto_loop_lsp(arrayLSDptr(p._w,3),cLSDptr,3); + r.w2 = lspref(cLSDptr,2); r.w1 = lspref(cLSDptr,1); r.w0 = lspref(cLSDptr,0); +#elif defined(FFT_P_92) + var uintD c[7]; + var uintD* const cLSDptr = arrayLSDptr(c,7); + // Multiply the two words, using the standard method. + mulu_2loop(arrayLSDptr(a._w,3),3, arrayLSDptr(b._w,3),3, cLSDptr); + // c[1..6] now contains the product. + // Divide by p. + // To divide c (0 <= c < p^2) by p = 7*2^n+1, + // we set q := floor(floor(c/2^n)/7) and + // r := c - q*p = (floor(c/2^n) mod 7)*2^n + (c mod 2^n) - q. + // If this becomes negative, set r := r + p. + // (As above, since 0 <= c <= (p-1)^2, we have + // floor(c/p) <= q <= floor(c/p)+1, so we have + // to set r := r + p at most once!) + // n = 92 = 3*32-4 = 2*32+28. + lspref(cLSDptr,6) = shiftleft_loop_lsp(cLSDptr lspop 3,3,4,lspref(cLSDptr,2)>>28); + lspref(cLSDptr,2) &= bit(28)-1; + // c[0..3] now contains floor(c/2^n), c[4..6] contains (c mod 2^n). + var uintD remainder = divu_loop_msp(7,cLSDptr lspop 7,4); + lspref(cLSDptr,2) |= remainder << 28; + // c[0..3] now contains q, c[4..6] contains (c mod 7*2^n). + #ifdef DEBUG_FFTP + if (lspref(cLSDptr,6) > 0) + cl_abort(); + #endif + #if 0 + if (compare_loop_msp(cLSDptr lspop 6,arrayMSDptr(p._w,3),3) >= 0) // q >= p ? + subfrom_loop_lsp(arrayLSDptr(p._w,3),cLSDptr lspop 3,3); // q -= p; + #endif + if (subfrom_loop_lsp(cLSDptr lspop 3,cLSDptr,3)) // (c mod 2^n) - q + addto_loop_lsp(arrayLSDptr(p._w,3),cLSDptr,3); + r.w2 = lspref(cLSDptr,2); r.w1 = lspref(cLSDptr,1); r.w0 = lspref(cLSDptr,0); +#else +#error "mulp not implemented for this prime" +#endif + if ((sint32)r.w2 < 0) + cl_abort(); + check_fftp_word(r); +} +#ifdef DEBUG_FFTP_OPERATIONS +static void mulp_doublecheck (const fftp_word& a, const fftp_word& b, fftp_word& r) +{ + fftp_word zero, ma, mb, or; + subp(a,a, zero); + subp(zero,a, ma); + subp(zero,b, mb); + mulp(ma,mb, or); + mulp(a,b, r); + if (compare_loop_msp(arrayMSDptr(r._w,3),arrayMSDptr(or._w,3),3)) + cl_abort(); +} +#define mulp mulp_doublecheck +#endif /* DEBUG_FFTP_OPERATIONS */ + +// b := (a / 2) mod p +static inline void shiftp (const fftp_word& a, fftp_word& b) +{ + check_fftp_word(a); + if (a.w0 & 1) { + var fftp_word a_even; + add(a,p, a_even); + shift(a_even, b); + } else + shift(a, b); + check_fftp_word(b); +} + +#ifndef _BIT_REVERSE +#define _BIT_REVERSE +// Reverse an n-bit number x. n>0. +static uintL bit_reverse (uintL n, uintL x) +{ + var uintL y = 0; + do { + y <<= 1; + y |= (x & 1); + x >>= 1; + } while (!(--n == 0)); + return y; +} +#endif + +// Compute an convolution mod p using FFT: z[0..N-1] := x[0..N-1] * y[0..N-1]. +static void fftp_convolution (const uintL n, const uintL N, // N = 2^n + fftp_word * x, // N words + fftp_word * y, // N words + fftp_word * z // N words result + ) +{ + CL_ALLOCA_STACK; + #if (FFTP_BACKWARD == RECIPROOT) || defined(DEBUG_FFTP) + var fftp_word* const w = cl_alloc_array(fftp_word,N); + #else + var fftp_word* const w = cl_alloc_array(fftp_word,(N>>1)+1); + #endif + var uintL i; + // Initialize w[i] to w^i, w a primitive N-th root of unity. + w[0] = fftp_roots_of_1[0]; + w[1] = fftp_roots_of_1[n]; + #if (FFTP_BACKWARD == RECIPROOT) || defined(DEBUG_FFTP) + for (i = 2; i < N; i++) + mulp(w[i-1],fftp_roots_of_1[n], w[i]); + #else // need only half of the roots + for (i = 2; i < N>>1; i++) + mulp(w[i-1],fftp_roots_of_1[n], w[i]); + #endif + #ifdef DEBUG_FFTP + // Check that w is really a primitive N-th root of unity. + { + var fftp_word w_N; + mulp(w[N-1],fftp_roots_of_1[n], w_N); + if (!(w_N.w2 == 0 && w_N.w1 == 0 && w_N.w0 == 1)) + cl_abort(); + w_N = w[N>>1]; + if (!(w_N.w2 == p.w2 && w_N.w1 == p.w1 && w_N.w0 == p.w0 - 1)) + cl_abort(); + } + #endif + var bool squaring = (x == y); + // Do an FFT of length N on x. + { + var sintL l; + /* l = n-1 */ { + var const uintL tmax = N>>1; // tmax = 2^(n-1) + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = t; + var uintL i2 = i1 + tmax; + // Butterfly: replace (x(i1),x(i2)) by + // (x(i1) + x(i2), x(i1) - x(i2)). + var fftp_word tmp; + tmp = x[i2]; + subp(x[i1],tmp, x[i2]); + addp(x[i1],tmp, x[i1]); + } + } + for (l = n-2; l>=0; l--) { + var const uintL smax = (uintL)1 << (n-1-l); + var const uintL tmax = (uintL)1 << l; + for (var uintL s = 0; s < smax; s++) { + var uintL exp = bit_reverse(n-1-l,s) << l; + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = (s << (l+1)) + t; + var uintL i2 = i1 + tmax; + // Butterfly: replace (x(i1),x(i2)) by + // (x(i1) + w^exp*x(i2), x(i1) - w^exp*x(i2)). + var fftp_word tmp; + mulp(x[i2],w[exp], tmp); + subp(x[i1],tmp, x[i2]); + addp(x[i1],tmp, x[i1]); + } + } + } + } + // Do an FFT of length N on y. + if (!squaring) { + var sintL l; + /* l = n-1 */ { + var uintL const tmax = N>>1; // tmax = 2^(n-1) + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = t; + var uintL i2 = i1 + tmax; + // Butterfly: replace (y(i1),y(i2)) by + // (y(i1) + y(i2), y(i1) - y(i2)). + var fftp_word tmp; + tmp = y[i2]; + subp(y[i1],tmp, y[i2]); + addp(y[i1],tmp, y[i1]); + } + } + for (l = n-2; l>=0; l--) { + var const uintL smax = (uintL)1 << (n-1-l); + var const uintL tmax = (uintL)1 << l; + for (var uintL s = 0; s < smax; s++) { + var uintL exp = bit_reverse(n-1-l,s) << l; + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = (s << (l+1)) + t; + var uintL i2 = i1 + tmax; + // Butterfly: replace (y(i1),y(i2)) by + // (y(i1) + w^exp*y(i2), y(i1) - w^exp*y(i2)). + var fftp_word tmp; + mulp(y[i2],w[exp], tmp); + subp(y[i1],tmp, y[i2]); + addp(y[i1],tmp, y[i1]); + } + } + } + } + // Multiply the transformed vectors into z. + for (i = 0; i < N; i++) + mulp(x[i],y[i], z[i]); + // Undo an FFT of length N on z. + { + var uintL l; + for (l = 0; l < n-1; l++) { + var const uintL smax = (uintL)1 << (n-1-l); + var const uintL tmax = (uintL)1 << l; + #if FFTP_BACKWARD != CLEVER + for (var uintL s = 0; s < smax; s++) { + var uintL exp = bit_reverse(n-1-l,s) << l; + #if FFTP_BACKWARD == RECIPROOT + if (exp > 0) + exp = N - exp; // negate exp (use w^-1 instead of w) + #endif + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = (s << (l+1)) + t; + var uintL i2 = i1 + tmax; + // Inverse Butterfly: replace (z(i1),z(i2)) by + // ((z(i1)+z(i2))/2, (z(i1)-z(i2))/(2*w^exp)). + var fftp_word sum; + var fftp_word diff; + addp(z[i1],z[i2], sum); + subp(z[i1],z[i2], diff); + shiftp(sum, z[i1]); + mulp(diff,w[exp], diff); shiftp(diff, z[i2]); + } + } + #else // FFTP_BACKWARD == CLEVER: clever handling of negative exponents + /* s = 0, exp = 0 */ { + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = t; + var uintL i2 = i1 + tmax; + // Inverse Butterfly: replace (z(i1),z(i2)) by + // ((z(i1)+z(i2))/2, (z(i1)-z(i2))/(2*w^exp)), + // with exp <-- 0. + var fftp_word sum; + var fftp_word diff; + addp(z[i1],z[i2], sum); + subp(z[i1],z[i2], diff); + shiftp(sum, z[i1]); + shiftp(diff, z[i2]); + } + } + for (var uintL s = 1; s < smax; s++) { + var uintL exp = bit_reverse(n-1-l,s) << l; + exp = (N>>1) - exp; // negate exp (use w^-1 instead of w) + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = (s << (l+1)) + t; + var uintL i2 = i1 + tmax; + // Inverse Butterfly: replace (z(i1),z(i2)) by + // ((z(i1)+z(i2))/2, (z(i1)-z(i2))/(2*w^exp)), + // with exp <-- (N/2 - exp). + var fftp_word sum; + var fftp_word diff; + addp(z[i1],z[i2], sum); + subp(z[i2],z[i1], diff); // note that w^(N/2) = -1 + shiftp(sum, z[i1]); + mulp(diff,w[exp], diff); shiftp(diff, z[i2]); + } + } + #endif + } + /* l = n-1 */ { + var const uintL tmax = N>>1; // tmax = 2^(n-1) + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = t; + var uintL i2 = i1 + tmax; + // Inverse Butterfly: replace (z(i1),z(i2)) by + // ((z(i1)+z(i2))/2, (z(i1)-z(i2))/2). + var fftp_word sum; + var fftp_word diff; + addp(z[i1],z[i2], sum); + subp(z[i1],z[i2], diff); + shiftp(sum, z[i1]); + shiftp(diff, z[i2]); + } + } + } + #if FFTP_BACKWARD == FORWARD + // Swap z[i] and z[N-i] for 0 < i < N/2. + for (i = (N>>1)-1; i > 0; i--) { + var fftp_word tmp = z[i]; + z[i] = z[N-i]; + z[N-i] = tmp; + } + #endif +} + +static void mulu_fft_modp (const uintD* sourceptr1, uintC len1, + const uintD* sourceptr2, uintC len2, + uintD* destptr) +// Es ist 2 <= len1 <= len2. +{ + // Methode: + // source1 ist ein Stück der Länge N1, source2 ein oder mehrere Stücke + // der Länge N2, mit N1+N2 <= N, wobei N Zweierpotenz ist. + // sum(i=0..N-1, x_i b^i) * sum(i=0..N-1, y_i b^i) wird errechnet, + // indem man die beiden Polynome + // sum(i=0..N-1, x_i T^i), sum(i=0..N-1, y_i T^i) + // multipliziert, und zwar durch Fourier-Transformation (s.o.). + var uint32 n; + integerlength32(len1-1, n=); // 2^(n-1) < len1 <= 2^n + var uintL len = (uintL)1 << n; // kleinste Zweierpotenz >= len1 + // Wählt man N = len, so hat man ceiling(len2/(len-len1+1)) * FFT(len). + // Wählt man N = 2*len, so hat man ceiling(len2/(2*len-len1+1)) * FFT(2*len). + // Wir wählen das billigere von beiden: + // Bei ceiling(len2/(len-len1+1)) <= 2 * ceiling(len2/(2*len-len1+1)) + // nimmt man N = len, bei ....... > ........ dagegen N = 2*len. + // (Wahl von N = 4*len oder mehr bringt nur in Extremfällen etwas.) + if (len2 > 2 * (len-len1+1) * (len2 <= (2*len-len1+1) ? 1 : ceiling(len2,(2*len-len1+1)))) { + n = n+1; + len = len << 1; + } + var const uintL N = len; // N = 2^n + CL_ALLOCA_STACK; + var fftp_word* const x = cl_alloc_array(fftp_word,N); + var fftp_word* const y = cl_alloc_array(fftp_word,N); + #ifdef DEBUG_FFTP + var fftp_word* const z = cl_alloc_array(fftp_word,N); + #else + var fftp_word* const z = x; // put z in place of x - saves memory + #endif + var uintD* const tmpprod = cl_alloc_array(uintD,len1+1); + var uintP i; + var uintL destlen = len1+len2; + clear_loop_lsp(destptr,destlen); + do { + var uintL len2p; // length of a piece of source2 + len2p = N - len1 + 1; + if (len2p > len2) + len2p = len2; + // len2p = min(N-len1+1,len2). + if (len2p == 1) { + // cheap case + var uintD* tmpptr = arrayLSDptr(tmpprod,len1+1); + mulu_loop_lsp(lspref(sourceptr2,0),sourceptr1,tmpptr,len1); + if (addto_loop_lsp(tmpptr,destptr,len1+1)) + if (inc_loop_lsp(destptr lspop (len1+1),destlen-(len1+1))) + cl_abort(); + } else { + var uintL destlenp = len1 + len2p - 1; + // destlenp = min(N,destlen-1). + var bool squaring = ((sourceptr1 == sourceptr2) && (len1 == len2p)); + // Fill factor x. + { + for (i = 0; i < len1; i++) { + x[i].w0 = lspref(sourceptr1,i); + x[i].w1 = 0; + x[i].w2 = 0; + } + for (i = len1; i < N; i++) { + x[i].w0 = 0; + x[i].w1 = 0; + x[i].w2 = 0; + } + } + // Fill factor y. + if (!squaring) { + for (i = 0; i < len2p; i++) { + y[i].w0 = lspref(sourceptr2,i); + y[i].w1 = 0; + y[i].w2 = 0; + } + for (i = len2p; i < N; i++) { + y[i].w0 = 0; + y[i].w1 = 0; + y[i].w2 = 0; + } + } + // Multiply. + if (!squaring) + fftp_convolution(n,N, &x[0], &y[0], &z[0]); + else + fftp_convolution(n,N, &x[0], &x[0], &z[0]); + #ifdef DEBUG_FFTP + // Check result. + for (i = 0; i < N; i++) + if (!(z[i].w2 < N)) + cl_abort(); + #endif + // Add result to destptr[-destlen..-1]: + { + var uintD* ptr = destptr; + // ac2|ac1|ac0 are an accumulator. + var uint32 ac0 = 0; + var uint32 ac1 = 0; + var uint32 ac2 = 0; + var uint32 tmp; + for (i = 0; i < destlenp; i++) { + // Add z[i] to the accumulator. + tmp = z[i].w0; + if ((ac0 += tmp) < tmp) { + if (++ac1 == 0) + ++ac2; + } + tmp = z[i].w1; + if ((ac1 += tmp) < tmp) + ++ac2; + tmp = z[i].w2; + ac2 += tmp; + // Add the accumulator's least significant word to destptr: + tmp = lspref(ptr,0); + if ((ac0 += tmp) < tmp) { + if (++ac1 == 0) + ++ac2; + } + lspref(ptr,0) = ac0; + lsshrink(ptr); + ac0 = ac1; + ac1 = ac2; + ac2 = 0; + } + // ac2 = 0. + if (ac1 > 0) { + if (!((i += 2) <= destlen)) + cl_abort(); + tmp = lspref(ptr,0); + if ((ac0 += tmp) < tmp) + ++ac1; + lspref(ptr,0) = ac0; + lsshrink(ptr); + tmp = lspref(ptr,0); + ac1 += tmp; + lspref(ptr,0) = ac1; + lsshrink(ptr); + if (ac1 < tmp) + if (inc_loop_lsp(ptr,destlen-i)) + cl_abort(); + } else if (ac0 > 0) { + if (!((i += 1) <= destlen)) + cl_abort(); + tmp = lspref(ptr,0); + ac0 += tmp; + lspref(ptr,0) = ac0; + lsshrink(ptr); + if (ac0 < tmp) + if (inc_loop_lsp(ptr,destlen-i)) + cl_abort(); + } + } + #ifdef DEBUG_FFTP + // If destlenp < N, check that the remaining z[i] are 0. + for (i = destlenp; i < N; i++) + if (z[i].w2 > 0 || z[i].w1 > 0 || z[i].w0 > 0) + cl_abort(); + #endif + } + // Decrement len2. + destptr = destptr lspop len2p; + destlen -= len2p; + sourceptr2 = sourceptr2 lspop len2p; + len2 -= len2p; + } while (len2 > 0); +} + +#undef FFT_P_94 +#undef FFT_P_92 +#undef w0 +#undef w1 +#undef w2 +#undef W3 diff --git a/src/base/digitseq/cl_DS_mul_fftp3.h b/src/base/digitseq/cl_DS_mul_fftp3.h new file mode 100644 index 0000000..619cc3d --- /dev/null +++ b/src/base/digitseq/cl_DS_mul_fftp3.h @@ -0,0 +1,672 @@ +// Fast integer multiplication using FFT in a modular ring. +// Bruno Haible 5.5.1996, 30.6.1996 + +// FFT in the complex domain has the drawback that it needs careful round-off +// error analysis. So here we choose another field of characteristic 0: Q_p. +// Since Q_p contains exactly the (p-1)th roots of unity, we choose +// p == 1 mod N and have the Nth roots of unity (N = 2^n) in Q_p and +// even in Z_p. Actually, we compute in Z/(p^m Z). + +// All operations the FFT algorithm needs is addition, subtraction, +// multiplication, multiplication by the Nth root of unity and division +// by N. Hence we can use the domain Z/(p^m Z) even if p is not a prime! + +// We want to compute the convolution of N 32-bit words. The resulting +// words are < (2^32)^2 * N. To avoid computing with numbers greater than +// 32 bits, we compute in Z/pZ for three different primes p in parallel, +// i.e. we compute in the ring (Z / p1 Z) x (Z / p2 Z) x (Z / p3 Z). We choose +// p1 = 3*2^30+1, p2 = 13*2^28+1, p3 = 29*2^27+1 (or 15*2^27+1 or 17*2^27+1). +// Because of p1*p2*p3 >= (2^32)^2 * N, the chinese remainder theorem will +// faithfully combine 3 32-bit words to a word < (2^32)^2 * N. + +#if !(intDsize==32) +#error "fft mod p implemented only for intDsize==32" +#endif + +static const uint32 p1 = 1+(3<<30); // = 3221225473 +static const uint32 p2 = 1+(13<<28); // = 3489660929 +static const uint32 p3 = 1+(29<<27); // = 3892314113 + +typedef struct { + uint32 w1; // remainder mod p1 + uint32 w2; // remainder mod p2 + uint32 w3; // remainder mod p3 +} fftp3_word; + +static const fftp3_word fftp3_roots_of_1 [27+1] = + // roots_of_1[n] is a (2^n)th root of unity in our ring. + // (Also roots_of_1[n-1] = roots_of_1[n]^2, but we don't need this.) + { + { 1, 1, 1 }, + { 3221225472, 3489660928, 3892314112 }, + { 1013946479, 1647819299, 800380159 }, + { 1031213943, 1728043888, 1502037594 }, + { 694614138, 156262243, 1093602721 }, + { 347220834, 408915340, 491290336 }, + { 680684264, 452506952, 846570852 }, + { 1109768284, 1230864251, 390870396 }, + { 602134989, 11914870, 1791906422 }, + { 1080308101, 336213294, 158126993 }, + { 381653707, 1548648704, 1432108380 }, + { 902453688, 429650884, 798472051 }, + { 1559299664, 775532293, 1877725713 }, + { 254499731, 727160889, 1192318337 }, + { 1376063215, 1557302953, 1642774092 }, + { 1284040478, 937059094, 1876917422 }, + { 336664489, 1411926644, 682311165 }, + { 894491787, 534027329, 473693773 }, + { 795860341, 1178663675, 1313928891 }, + { 23880336, 1707047452, 93147496 }, + { 790585193, 892284267, 1647947905 }, + { 877386874, 1729337527, 1233672227 }, + { 1510644826, 333000282, 296593948 }, + { 353060343, 901807544, 659274384 }, + { 716717815, 1281544649, 1457308949 }, + { 1020271667, 1713714919, 627726344 }, + { 139914905, 950720020, 1119863241 }, + { 709308748, 675675166, 538726428 } + }; + +// Define this for (cheap) consistency checks. +//#define DEBUG_FFTP3 + +// Define this for extensive consistency checks. +//#define DEBUG_FFTP3_OPERATIONS + +// Define the algorithm of the backward FFT: +// Either FORWARD (a normal FFT followed by a permutation) +// or RECIPROOT (an FFT with reciprocal root of unity) +// or CLEVER (an FFT with reciprocal root of unity but clever computation +// of the reciprocals). +// Drawback of FORWARD: the permutation pass. +// Drawback of RECIPROOT: need all the powers of the root, not only half of them. +#define FORWARD 42 +#define RECIPROOT 43 +#define CLEVER 44 +#define FFTP3_BACKWARD CLEVER + +#ifdef DEBUG_FFTP3_OPERATIONS +#define check_fftp3_word(x) if ((x.w1 >= p1) || (x.w2 >= p2) || (x.w3 >= p3)) cl_abort() +#else +#define check_fftp3_word(x) +#endif + +// r := 0 mod p +static inline void zerop3 (fftp3_word& r) +{ + r.w1 = 0; + r.w2 = 0; + r.w3 = 0; +} + +// r := x mod p +static inline void setp3 (uint32 x, fftp3_word& r) +{ + if (p1 >= ((uint32)1 << 31)) + r.w1 = (x >= p1 ? x - p1 : x); + else + divu_3232_3232(x,p1, ,r.w1=); + if (p2 >= ((uint32)1 << 31)) + r.w2 = (x >= p2 ? x - p2 : x); + else + divu_3232_3232(x,p2, ,r.w2=); + if (p3 >= ((uint32)1 << 31)) + r.w3 = (x >= p3 ? x - p3 : x); + else + divu_3232_3232(x,p3, ,r.w3=); +} + +// Chinese remainder theorem: +// (Z / p1 Z) x (Z / p2 Z) x (Z / p3 Z) == Z / p1*p2*p3 Z = Z / P Z. +// Return r as an integer >= 0, < p1*p2*p3, as 3-digit-sequence res. +static void combinep3 (const fftp3_word& r, uintD* resLSDptr) +{ + check_fftp3_word(r); + // Compute e1 * r.w1 + e2 * r.w2 + e3 * r.w3 where the idempotents are + // found as: xgcd(pi,p/pi) = 1 = ui*pi + vi*P/pi, ei = 1 - ui*pi. + // e1 = 35002755423056150739595925972 + // e2 = 14584479687667766215746868453 + // e3 = 37919651490985126265126719818 + // Since e1+e2+e3 > 2*P, we prefer to compute with the negated + // idempotents, their sum is < P: + // -e1 = 8750687877798370870638831149 + // -e2 = 29168963613186755394487888668 + // -e3 = 5833791809869395345108037303 + // We will have 0 <= -e1 * r.w1 + -e2 * r.w2 + -e3 * r.w3 < + // < -e1 * p1 + -e2 * p2 + -e3 * p3 < 2^32 * p1*p2*p3 < 2^128. + // The sum of the products fits in 4 digits, we divide by p1*p2*p3 + // as a 3-digit sequence and finally negate the remainder. + #if CL_DS_BIG_ENDIAN_P + var const uintD p123 [3] = { 0x8D600002, 0x06800002, 0x78000001 }; + var const uintD e1 [3] = { 0x1C46663C, 0x647FFF9D, 0x7E66662D }; + var const uintD e2 [3] = { 0x5E40004D, 0xEDAAAB66, 0xEAAAAB1C }; + var const uintD e3 [3] = { 0x12D99977, 0xB45554FE, 0x0EEEEEB7 }; + #else + var const uintD p123 [3] = { 0x78000001, 0x06800002, 0x8D600002 }; + var const uintD e1 [3] = { 0x7E66662D, 0x647FFF9D, 0x1C46663C }; + var const uintD e2 [3] = { 0xEAAAAB1C, 0xEDAAAB66, 0x5E40004D }; + var const uintD e3 [3] = { 0x0EEEEEB7, 0xB45554FE, 0x12D99977 }; + #endif + var uintD sum [4]; + var uintD* const sumLSDptr = arrayLSDptr(sum,4); + mulu_loop_lsp(r.w1,arrayLSDptr(e1,3), sumLSDptr,3); + lspref(sumLSDptr,3) += muluadd_loop_lsp(r.w2,arrayLSDptr(e2,3), sumLSDptr,3); + lspref(sumLSDptr,3) += muluadd_loop_lsp(r.w3,arrayLSDptr(e3,3), sumLSDptr,3); + #if 0 + {CL_ALLOCA_STACK; + var DS q; + var DS r; + UDS_divide(arrayMSDptr(sum,4),4,arrayLSDptr(sum,4), + arrayMSDptr(p123,3),3,arrayLSDptr(p123,3), + &q,&r + ); + ASSERT(q.len <= 1) + ASSERT(r.len <= 3) + copy_loop_lsp(r.LSDptr,arrayLSDptr(sum,4),r.len); + DS_clear_loop(arrayMSDptr(sum,4) mspop 1,3-r.len,arrayLSDptr(sum,4) lspop r.len); + } + #else + // Division wie UDS_divide mit a_len=4, b_len=3. + { + var uintD q_stern; + var uintD c1; + #if HAVE_DD + divuD(highlowDD(lspref(sumLSDptr,3),lspref(sumLSDptr,2)),lspref(arrayLSDptr(p123,3),2), q_stern=,c1=); + { var uintDD c2 = highlowDD(c1,lspref(sumLSDptr,1)); + var uintDD c3 = muluD(lspref(arrayLSDptr(p123,3),1),q_stern); + if (c3 > c2) + { q_stern = q_stern-1; + if (c3-c2 > highlowDD(lspref(arrayLSDptr(p123,3),2),lspref(arrayLSDptr(p123,3),1))) + { q_stern = q_stern-1; } + } } + #else + divuD(lspref(sumLSDptr,3),lspref(sumLSDptr,2),lspref(arrayLSDptr(p123,3),2), q_stern=,c1=); + { var uintD c2lo = lspref(sumLSDptr,1); + var uintD c3hi; + var uintD c3lo; + muluD(lspref(arrayLSDptr(p123,3),1),q_stern, c3hi=,c3lo=); + if ((c3hi > c1) || ((c3hi == c1) && (c3lo > c2lo))) + { q_stern = q_stern-1; + c3hi -= c1; if (c3lo < c2lo) { c3hi--; }; c3lo -= c2lo; + if ((c3hi > lspref(arrayLSDptr(p123,3),2)) || ((c3hi == lspref(arrayLSDptr(p123,3),2)) && (c3lo > lspref(arrayLSDptr(p123,3),1)))) + { q_stern = q_stern-1; } + } } + #endif + if (!(q_stern==0)) + { var uintD carry = mulusub_loop_lsp(q_stern,arrayLSDptr(p123,3),sumLSDptr,3); + if (carry > lspref(sumLSDptr,3)) + { q_stern = q_stern-1; + addto_loop_lsp(arrayLSDptr(p123,3),sumLSDptr,3); + } } + } + #endif + if (lspref(sumLSDptr,0)==0 && lspref(sumLSDptr,1)==0 && lspref(sumLSDptr,2)==0) { + clear_loop_lsp(resLSDptr,3); + } else { + sub_loop_lsp(arrayLSDptr(p123,3),sumLSDptr,resLSDptr,3); + } +} + +// r := (a + b) mod p +static inline void addp3 (const fftp3_word& a, const fftp3_word& b, fftp3_word& r) +{ + var uint32 x; + + check_fftp3_word(a); check_fftp3_word(b); + // Add single 32-bit words mod pi. + if (((x = (a.w1 + b.w1)) < b.w1) || (x >= p1)) + x -= p1; + r.w1 = x; + if (((x = (a.w2 + b.w2)) < b.w2) || (x >= p2)) + x -= p2; + r.w2 = x; + if (((x = (a.w3 + b.w3)) < b.w3) || (x >= p3)) + x -= p3; + r.w3 = x; + check_fftp3_word(r); +} + +// r := (a - b) mod p +static inline void subp3 (const fftp3_word& a, const fftp3_word& b, fftp3_word& r) +{ + check_fftp3_word(a); check_fftp3_word(b); + // Subtract single 32-bit words mod pi. + r.w1 = (a.w1 < b.w1 ? a.w1-b.w1+p1 : a.w1-b.w1); + r.w2 = (a.w2 < b.w2 ? a.w2-b.w2+p2 : a.w2-b.w2); + r.w3 = (a.w3 < b.w3 ? a.w3-b.w3+p3 : a.w3-b.w3); + check_fftp3_word(r); +} + +// r := (a * b) mod p +static void mulp3 (const fftp3_word& a, const fftp3_word& b, fftp3_word& res) +{ + check_fftp3_word(a); check_fftp3_word(b); + // To divide c (0 <= c < p^2) by p = m*2^n+1, + // we set q := floor(floor(c/2^n)/m) and + // r := c - q*p = (floor(c/2^n) mod m)*2^n + (c mod 2^n) - q. + // If this becomes negative, set r := r + p (at most twice). + // (This works because floor(c/p) <= q <= floor(c/p)+2.) + // (Actually, here, 0 <= c <= (p-1)^2, hence + // floor(c/p) <= q <= floor(c/p)+1, so we have + // to set r := r + p at most once!) + #if 1 + #define mul_mod_p(aw,bw,result_zuweisung,p,n,m) \ + { \ + var uint32 hi; \ + var uint32 lo; \ + mulu32(aw,bw, hi=,lo=); \ + divu_6432_3232(hi,lo,p, ,result_zuweisung); \ + } + #else + #define mul_mod_p(aw,bw,result_zuweisung,p,n,m) \ + { \ + var uint32 hi; \ + var uint32 lo; \ + mulu32(aw,bw, hi=,lo=); \ + var uint32 q; \ + var uint32 r; \ + divu_6432_3232(hi>>n,(hi<<(32-n))|(lo>>n), m, q=,r=); \ + r = (r << n) | (lo & (((uint32)1<= q) { r = r-q; } else { r = r-q+p; } \ + result_zuweisung r; \ + } + #endif + // p1 = 3*2^30+1, n = 30, m = 3 + mul_mod_p(a.w1,b.w1,res.w1=,p1,30,3); + // p2 = 13*2^28+1, n = 28, m = 13 + mul_mod_p(a.w2,b.w2,res.w2=,p2,28,13); + // p3 = 29*2^27+1, n = 27, m = 29 + mul_mod_p(a.w3,b.w3,res.w3=,p3,27,29); + #undef mul_mod_p + check_fftp3_word(res); +} +#ifdef DEBUG_FFTP3_OPERATIONS +static void mulp3_doublecheck (const fftp3_word& a, const fftp3_word& b, fftp3_word& r) +{ + fftp3_word zero, ma, mb, or; + zerop3(zero); + subp3(zero,a, ma); + subp3(zero,b, mb); + mulp3(ma,mb, or); + mulp3(a,b, r); + if (!((r.w1 == or.w1) && (r.w2 == or.w2) && (r.w3 == or.w3))) + cl_abort(); +} +#define mulp3 mulp3_doublecheck +#endif /* DEBUG_FFTP3_OPERATIONS */ + +// b := (a / 2) mod p +static inline void shiftp3 (const fftp3_word& a, fftp3_word& b) +{ + check_fftp3_word(a); + b.w1 = (a.w1 & 1 ? (a.w1 >> 1) + (p1 >> 1) + 1 : (a.w1 >> 1)); + b.w2 = (a.w2 & 1 ? (a.w2 >> 1) + (p2 >> 1) + 1 : (a.w2 >> 1)); + b.w3 = (a.w3 & 1 ? (a.w3 >> 1) + (p3 >> 1) + 1 : (a.w3 >> 1)); + check_fftp3_word(b); +} + +#ifndef _BIT_REVERSE +#define _BIT_REVERSE +// Reverse an n-bit number x. n>0. +static uintL bit_reverse (uintL n, uintL x) +{ + var uintL y = 0; + do { + y <<= 1; + y |= (x & 1); + x >>= 1; + } while (!(--n == 0)); + return y; +} +#endif + +// Compute an convolution mod p using FFT: z[0..N-1] := x[0..N-1] * y[0..N-1]. +static void fftp3_convolution (const uintL n, const uintL N, // N = 2^n + fftp3_word * x, // N words + fftp3_word * y, // N words + fftp3_word * z // N words result + ) +{ + CL_ALLOCA_STACK; + #if (FFTP3_BACKWARD == RECIPROOT) || defined(DEBUG_FFTP3) + var fftp3_word* const w = cl_alloc_array(fftp3_word,N); + #else + var fftp3_word* const w = cl_alloc_array(fftp3_word,(N>>1)+1); + #endif + var uintL i; + // Initialize w[i] to w^i, w a primitive N-th root of unity. + w[0] = fftp3_roots_of_1[0]; + w[1] = fftp3_roots_of_1[n]; + #if (FFTP3_BACKWARD == RECIPROOT) || defined(DEBUG_FFTP3) + for (i = 2; i < N; i++) + mulp3(w[i-1],fftp3_roots_of_1[n], w[i]); + #else // need only half of the roots + for (i = 2; i < N>>1; i++) + mulp3(w[i-1],fftp3_roots_of_1[n], w[i]); + #endif + #ifdef DEBUG_FFTP3 + // Check that w is really a primitive N-th root of unity. + { + var fftp3_word w_N; + mulp3(w[N-1],fftp3_roots_of_1[n], w_N); + if (!(w_N.w1 == 1 && w_N.w2 == 1 && w_N.w3 == 1)) + cl_abort(); + w_N = w[N>>1]; + if (!(w_N.w1 == p1-1 && w_N.w2 == p2-1 && w_N.w3 == p3-1)) + cl_abort(); + } + #endif + var bool squaring = (x == y); + // Do an FFT of length N on x. + { + var sintL l; + /* l = n-1 */ { + var const uintL tmax = N>>1; // tmax = 2^(n-1) + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = t; + var uintL i2 = i1 + tmax; + // Butterfly: replace (x(i1),x(i2)) by + // (x(i1) + x(i2), x(i1) - x(i2)). + var fftp3_word tmp; + tmp = x[i2]; + subp3(x[i1],tmp, x[i2]); + addp3(x[i1],tmp, x[i1]); + } + } + for (l = n-2; l>=0; l--) { + var const uintL smax = (uintL)1 << (n-1-l); + var const uintL tmax = (uintL)1 << l; + for (var uintL s = 0; s < smax; s++) { + var uintL exp = bit_reverse(n-1-l,s) << l; + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = (s << (l+1)) + t; + var uintL i2 = i1 + tmax; + // Butterfly: replace (x(i1),x(i2)) by + // (x(i1) + w^exp*x(i2), x(i1) - w^exp*x(i2)). + var fftp3_word tmp; + mulp3(x[i2],w[exp], tmp); + subp3(x[i1],tmp, x[i2]); + addp3(x[i1],tmp, x[i1]); + } + } + } + } + // Do an FFT of length N on y. + if (!squaring) { + var sintL l; + /* l = n-1 */ { + var uintL const tmax = N>>1; // tmax = 2^(n-1) + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = t; + var uintL i2 = i1 + tmax; + // Butterfly: replace (y(i1),y(i2)) by + // (y(i1) + y(i2), y(i1) - y(i2)). + var fftp3_word tmp; + tmp = y[i2]; + subp3(y[i1],tmp, y[i2]); + addp3(y[i1],tmp, y[i1]); + } + } + for (l = n-2; l>=0; l--) { + var const uintL smax = (uintL)1 << (n-1-l); + var const uintL tmax = (uintL)1 << l; + for (var uintL s = 0; s < smax; s++) { + var uintL exp = bit_reverse(n-1-l,s) << l; + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = (s << (l+1)) + t; + var uintL i2 = i1 + tmax; + // Butterfly: replace (y(i1),y(i2)) by + // (y(i1) + w^exp*y(i2), y(i1) - w^exp*y(i2)). + var fftp3_word tmp; + mulp3(y[i2],w[exp], tmp); + subp3(y[i1],tmp, y[i2]); + addp3(y[i1],tmp, y[i1]); + } + } + } + } + // Multiply the transformed vectors into z. + for (i = 0; i < N; i++) + mulp3(x[i],y[i], z[i]); + // Undo an FFT of length N on z. + { + var uintL l; + for (l = 0; l < n-1; l++) { + var const uintL smax = (uintL)1 << (n-1-l); + var const uintL tmax = (uintL)1 << l; + #if FFTP3_BACKWARD != CLEVER + for (var uintL s = 0; s < smax; s++) { + var uintL exp = bit_reverse(n-1-l,s) << l; + #if FFTP3_BACKWARD == RECIPROOT + if (exp > 0) + exp = N - exp; // negate exp (use w^-1 instead of w) + #endif + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = (s << (l+1)) + t; + var uintL i2 = i1 + tmax; + // Inverse Butterfly: replace (z(i1),z(i2)) by + // ((z(i1)+z(i2))/2, (z(i1)-z(i2))/(2*w^exp)). + var fftp3_word sum; + var fftp3_word diff; + addp3(z[i1],z[i2], sum); + subp3(z[i1],z[i2], diff); + shiftp3(sum, z[i1]); + mulp3(diff,w[exp], diff); shiftp3(diff, z[i2]); + } + } + #else // FFTP3_BACKWARD == CLEVER: clever handling of negative exponents + /* s = 0, exp = 0 */ { + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = t; + var uintL i2 = i1 + tmax; + // Inverse Butterfly: replace (z(i1),z(i2)) by + // ((z(i1)+z(i2))/2, (z(i1)-z(i2))/(2*w^exp)), + // with exp <-- 0. + var fftp3_word sum; + var fftp3_word diff; + addp3(z[i1],z[i2], sum); + subp3(z[i1],z[i2], diff); + shiftp3(sum, z[i1]); + shiftp3(diff, z[i2]); + } + } + for (var uintL s = 1; s < smax; s++) { + var uintL exp = bit_reverse(n-1-l,s) << l; + exp = (N>>1) - exp; // negate exp (use w^-1 instead of w) + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = (s << (l+1)) + t; + var uintL i2 = i1 + tmax; + // Inverse Butterfly: replace (z(i1),z(i2)) by + // ((z(i1)+z(i2))/2, (z(i1)-z(i2))/(2*w^exp)), + // with exp <-- (N/2 - exp). + var fftp3_word sum; + var fftp3_word diff; + addp3(z[i1],z[i2], sum); + subp3(z[i2],z[i1], diff); // note that w^(N/2) = -1 + shiftp3(sum, z[i1]); + mulp3(diff,w[exp], diff); shiftp3(diff, z[i2]); + } + } + #endif + } + /* l = n-1 */ { + var const uintL tmax = N>>1; // tmax = 2^(n-1) + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = t; + var uintL i2 = i1 + tmax; + // Inverse Butterfly: replace (z(i1),z(i2)) by + // ((z(i1)+z(i2))/2, (z(i1)-z(i2))/2). + var fftp3_word sum; + var fftp3_word diff; + addp3(z[i1],z[i2], sum); + subp3(z[i1],z[i2], diff); + shiftp3(sum, z[i1]); + shiftp3(diff, z[i2]); + } + } + } + #if FFTP3_BACKWARD == FORWARD + // Swap z[i] and z[N-i] for 0 < i < N/2. + for (i = (N>>1)-1; i > 0; i--) { + var fftp3_word tmp = z[i]; + z[i] = z[N-i]; + z[N-i] = tmp; + } + #endif +} + +static void mulu_fft_modp3 (const uintD* sourceptr1, uintC len1, + const uintD* sourceptr2, uintC len2, + uintD* destptr) +// Es ist 2 <= len1 <= len2. +{ + // Methode: + // source1 ist ein Stück der Länge N1, source2 ein oder mehrere Stücke + // der Länge N2, mit N1+N2 <= N, wobei N Zweierpotenz ist. + // sum(i=0..N-1, x_i b^i) * sum(i=0..N-1, y_i b^i) wird errechnet, + // indem man die beiden Polynome + // sum(i=0..N-1, x_i T^i), sum(i=0..N-1, y_i T^i) + // multipliziert, und zwar durch Fourier-Transformation (s.o.). + var uint32 n; + integerlength32(len1-1, n=); // 2^(n-1) < len1 <= 2^n + var uintL len = (uintL)1 << n; // kleinste Zweierpotenz >= len1 + // Wählt man N = len, so hat man ceiling(len2/(len-len1+1)) * FFT(len). + // Wählt man N = 2*len, so hat man ceiling(len2/(2*len-len1+1)) * FFT(2*len). + // Wir wählen das billigere von beiden: + // Bei ceiling(len2/(len-len1+1)) <= 2 * ceiling(len2/(2*len-len1+1)) + // nimmt man N = len, bei ....... > ........ dagegen N = 2*len. + // (Wahl von N = 4*len oder mehr bringt nur in Extremfällen etwas.) + if (len2 > 2 * (len-len1+1) * (len2 <= (2*len-len1+1) ? 1 : ceiling(len2,(2*len-len1+1)))) { + n = n+1; + len = len << 1; + } + var const uintL N = len; // N = 2^n + CL_ALLOCA_STACK; + var fftp3_word* const x = cl_alloc_array(fftp3_word,N); + var fftp3_word* const y = cl_alloc_array(fftp3_word,N); + #ifdef DEBUG_FFTP3 + var fftp3_word* const z = cl_alloc_array(fftp3_word,N); + #else + var fftp3_word* const z = x; // put z in place of x - saves memory + #endif + var uintD* const tmpprod = cl_alloc_array(uintD,len1+1); + var uintP i; + var uintL destlen = len1+len2; + clear_loop_lsp(destptr,destlen); + do { + var uintL len2p; // length of a piece of source2 + len2p = N - len1 + 1; + if (len2p > len2) + len2p = len2; + // len2p = min(N-len1+1,len2). + if (len2p == 1) { + // cheap case + var uintD* tmpptr = arrayLSDptr(tmpprod,len1+1); + mulu_loop_lsp(lspref(sourceptr2,0),sourceptr1,tmpptr,len1); + if (addto_loop_lsp(tmpptr,destptr,len1+1)) + if (inc_loop_lsp(destptr lspop (len1+1),destlen-(len1+1))) + cl_abort(); + } else { + var uintL destlenp = len1 + len2p - 1; + // destlenp = min(N,destlen-1). + var bool squaring = ((sourceptr1 == sourceptr2) && (len1 == len2p)); + // Fill factor x. + { + for (i = 0; i < len1; i++) + setp3(lspref(sourceptr1,i), x[i]); + for (i = len1; i < N; i++) + zerop3(x[i]); + } + // Fill factor y. + if (!squaring) { + for (i = 0; i < len2p; i++) + setp3(lspref(sourceptr2,i), y[i]); + for (i = len2p; i < N; i++) + zerop3(y[i]); + } + // Multiply. + if (!squaring) + fftp3_convolution(n,N, &x[0], &y[0], &z[0]); + else + fftp3_convolution(n,N, &x[0], &x[0], &z[0]); + // Add result to destptr[-destlen..-1]: + { + var uintD* ptr = destptr; + // ac2|ac1|ac0 are an accumulator. + var uint32 ac0 = 0; + var uint32 ac1 = 0; + var uint32 ac2 = 0; + var uint32 tmp; + for (i = 0; i < destlenp; i++) { + // Convert z[i] to a 3-digit number. + var uintD z_i[3]; + combinep3(z[i],arrayLSDptr(z_i,3)); + #ifdef DEBUG_FFTP3 + if (!(arrayLSref(z_i,3,2) < N)) + cl_abort(); + #endif + // Add z[i] to the accumulator. + tmp = arrayLSref(z_i,3,0); + if ((ac0 += tmp) < tmp) { + if (++ac1 == 0) + ++ac2; + } + tmp = arrayLSref(z_i,3,1); + if ((ac1 += tmp) < tmp) + ++ac2; + tmp = arrayLSref(z_i,3,2); + ac2 += tmp; + // Add the accumulator's least significant word to destptr: + tmp = lspref(ptr,0); + if ((ac0 += tmp) < tmp) { + if (++ac1 == 0) + ++ac2; + } + lspref(ptr,0) = ac0; + lsshrink(ptr); + ac0 = ac1; + ac1 = ac2; + ac2 = 0; + } + // ac2 = 0. + if (ac1 > 0) { + if (!((i += 2) <= destlen)) + cl_abort(); + tmp = lspref(ptr,0); + if ((ac0 += tmp) < tmp) + ++ac1; + lspref(ptr,0) = ac0; + lsshrink(ptr); + tmp = lspref(ptr,0); + ac1 += tmp; + lspref(ptr,0) = ac1; + lsshrink(ptr); + if (ac1 < tmp) + if (inc_loop_lsp(ptr,destlen-i)) + cl_abort(); + } else if (ac0 > 0) { + if (!((i += 1) <= destlen)) + cl_abort(); + tmp = lspref(ptr,0); + ac0 += tmp; + lspref(ptr,0) = ac0; + lsshrink(ptr); + if (ac0 < tmp) + if (inc_loop_lsp(ptr,destlen-i)) + cl_abort(); + } + } + #ifdef DEBUG_FFTP3 + // If destlenp < N, check that the remaining z[i] are 0. + for (i = destlenp; i < N; i++) + if (z[i].w1 > 0 || z[i].w2 > 0 || z[i].w3 > 0) + cl_abort(); + #endif + } + // Decrement len2. + destptr = destptr lspop len2p; + destlen -= len2p; + sourceptr2 = sourceptr2 lspop len2p; + len2 -= len2p; + } while (len2 > 0); +} diff --git a/src/base/digitseq/cl_DS_mul_fftp3m.h b/src/base/digitseq/cl_DS_mul_fftp3m.h new file mode 100644 index 0000000..14a277c --- /dev/null +++ b/src/base/digitseq/cl_DS_mul_fftp3m.h @@ -0,0 +1,858 @@ +// Fast integer multiplication using FFT in a modular ring. +// Bruno Haible 5.5.1996, 30.6.1996, 20.8.1996 + +// FFT in the complex domain has the drawback that it needs careful round-off +// error analysis. So here we choose another field of characteristic 0: Q_p. +// Since Q_p contains exactly the (p-1)th roots of unity, we choose +// p == 1 mod N and have the Nth roots of unity (N = 2^n) in Q_p and +// even in Z_p. Actually, we compute in Z/(p^m Z). + +// All operations the FFT algorithm needs is addition, subtraction, +// multiplication, multiplication by the Nth root of unity and division +// by N. Hence we can use the domain Z/(p^m Z) even if p is not a prime! + +// We want to compute the convolution of N 32-bit words. The resulting +// words are < (2^32)^2 * N. To avoid computing with numbers greater than +// 32 bits, we compute in Z/pZ for three different primes p in parallel, +// i.e. we compute in the ring (Z / p1 Z) x (Z / p2 Z) x (Z / p3 Z). We choose +// p1 = 3*2^30+1, p2 = 15*2^27+1, p3 = 7*2^26+1. +// Because of p1*p2*p3 >= 2^91 >= (2^32)^2 * N, the chinese remainder theorem +// will faithfully combine 3 32-bit words to a word < (2^32)^2 * N. + +// Furthermore we use Montgomery's modular multiplication trick +// [Peter L. Montgomery: Modular multiplication without trial division, +// Mathematics of Computation 44 (1985), 519-521.] +// +// Assume we want to compute modulo M, M odd. V and N will be chosen +// so that V*N==1 mod M and that (a,b) --> a*b*V mod M can be more easily +// computed than (a,b) --> a*b mod M. Then, we have a ring isomorphism +// (Z/MZ, +, * mod M) \isomorph (Z/MZ, +, (a,b) --> a*b*V mod M) +// x mod M --------> x*N mod M +// It is thus preferrable to use x*N mod M as a "representation" of x mod M, +// especially for computations which involve at least several multiplications. +// +// The precise algorithm to compute a*b*V mod M, given a and b, and the choice +// of N and V depend on M and on the hardware. The general idea is this: +// Choose N = 2^n, so that division by N is easy. Recall that V == N^-1 mod M. +// 1. Given a and b as m-bit numbers (M <= 2^m), compute a*b in full +// precision. +// 2. Write a*b = c*N+d, i.e. split it into components c and d. +// 3. Now a*b*V = c*N*V+d*V == c+d*V mod M. +// 4. Instead of computing d*V mod M +// a. by full multiplication and then division mod M, or +// b. by left shifts: repeated application of +// x := 2*x+(0 or 1); if (x >= M) { x := x-M; } +// we compute +// c. by right shifts (recall that d*V == d*2^-n mod M): repeated application +// of if (x odd) { x := (x+M)/2; } else { x := x/2; } +// Usually one will choose N = 2^m, so that c and d have both m bits. +// Several variations are possible: In step 4 one can implement the right +// shifts in hardware. Or (for example when N = 2^160 and working on a +// 32-bit machine) one can do 32 shift steps at the same time: +// Choose M' == M^-1 mod 2^32 and compute n/32 times +// x := (x - ((x mod 2^32) * M' mod 2^32) * M) / 2^32. +// +// Here, we deal with moduli M = p_i = j*2^k+1. These form of primes comes +// in because we need 2^n-th roots of unity mod M. But is also comes handy +// for Montgomery multiplication: Instead of choosing N = 2^32 (which makes +// up for very easy splitting in step 1) and V = j^2*2^(2*k-32), we better +// choose N = 2^k and V = -j. The algorithm now goes like this (recall that +// M is an m-bit number and j is an (m-k)-bit number): +// 1. Compute a*b in full precision, as a 2*m <= 64 bit number. +// 2. Split a*b = c*N+d, with c an (2m-k)-bit number and d an k-bit number. +// 3. a*b*V == c+d*V mod M. +// 4. Compute c mod M by splitting off the leading (m-k+1) bits of c and +// using table lookup; the remainder (c mod 2^(m-1)) is already reduced +// mod M. +// Compute d*|V| the standard way; |V| has only few bits. d*|V| is +// already reduced mod M, because d*|V| < j*2^k < M. + +// In order to get best performance, we carefully choose the primes so that +// a. the table of size 2^(m-k+1) doesn't get too large, +// b. multiplication by V is easy. +// Here is a list of the interesting primes < 2^32: +// +// U*M+V*N = 1 +// prime bits N=2^n V U 2m<=n+32 ? +// M m n +// +// 3*2^30+1 32 30 -3 1 n (*) +// +// 13*2^28+1 32 28 -13 1 n +// +// 15*2^27+1 31 27 -15 1 n (*) +// 17*2^27+1 32 27 -17 1 n +// 29*2^27+1 32 27 -29 1 n +// +// 7*2^26+1 29 26 -7 1 y (*) +// 27*2^26+1 31 26 -27 1 n +// 37*2^26+1 32 26 -37 1 n +// 43*2^26+1 32 26 -43 1 n +// +// 5*2^25+1 28 25 -5 1 y +// 33*2^25+1 31 25 -33 1 n +// 51*2^25+1 31 25 -51 1 n +// 63*2^25+1 31 25 -63 1 n +// 81*2^25+1 32 25 -81 1 n +// 125*2^25+1 32 25 -125 1 n +// +// 45*2^24+1 30 24 -45 1 n +// 73*2^24+1 31 24 -73 1 n +// 127*2^24+1 31 24 -127 1 n +// 151*2^24+1 32 24 -151 1 n +// 157*2^24+1 32 24 -157 1 n +// 171*2^24+1 32 24 -171 1 n +// 193*2^24+1 32 24 -193 1 n +// 235*2^24+1 32 24 -235 1 n +// 243*2^24+1 32 24 -243 1 n +// +// 45*2^23+1 29 23 -45 1 n +// ... +// +// The inequality 2m<=n+32 would mean that c fits in a 32-bit word, but that's +// actually irrelevant because we can fetch the most significant bits of c +// before actually computing c. +// We choose the primes marked with an asterisk. + + +#if !(intDsize==32) +#error "fft mod p implemented only for intDsize==32" +#endif + +// Avoid clash with fftp3 +#define p1 fftp3m_p1 +#define p2 fftp3m_p2 +#define p3 fftp3m_p3 +#define n1 fftp3m_n1 +#define n2 fftp3m_n2 +#define n3 fftp3m_n3 + +static const uint32 p1 = 1+(3<<30); // = 3221225473 +static const uint32 p2 = 1+(15<<27); // = 2013265921 +static const uint32 p3 = 1+(7<<26); // = 469762049 +static const uint32 n1 = 30; // Montgomery: represent x mod p1 as x*2^n1 mod p1 +static const uint32 n2 = 27; // Montgomery: represent x mod p2 as x*2^n2 mod p2 +static const uint32 n3 = 26; // Montgomery: represent x mod p3 as x*2^n3 mod p3 + +typedef struct { + uint32 w1; // remainder mod p1 + uint32 w2; // remainder mod p2 + uint32 w3; // remainder mod p3 +} fftp3m_word; + +static const fftp3m_word fftp3m_roots_of_1 [26+1] = + // roots_of_1[n] is a (2^n)th root of unity in our ring. + // (Also roots_of_1[n-1] = roots_of_1[n]^2, but we don't need this.) + { + #if 0 // in standard representation + { 1, 1, 1 }, + { 3221225472, 2013265920, 469762048 }, + { 1013946479, 284861408, 19610091 }, + { 1031213943, 211723194, 26623616 }, + { 694614138, 78945800, 111570435 }, + { 347220834, 772607190, 135956445 }, + { 680684264, 288289890, 181505383 }, + { 1109768284, 112574482, 145518049 }, + { 602134989, 928726468, 109721424 }, + { 1080308101, 875419223, 2847903 }, + { 381653707, 510575142, 110273149 }, + { 902453688, 193023072, 65701394 }, + { 1559299664, 313561437, 181642641 }, + { 254499731, 121307056, 82315502 }, + { 1376063215, 20899142, 142137197 }, + { 1284040478, 956809618, 207661045 }, + { 336664489, 317295870, 194405005 }, + { 894491787, 785393806, 2821902 }, + { 795860341, 738526384, 230963948 }, + { 23880336, 956561758, 59211404 }, + { 790585193, 352904935, 95374542 }, + { 877386874, 836313293, 153165757 }, + { 1510644826, 971592443, 74027009 }, + { 353060343, 692611595, 24417505 }, + { 716717815, 791167605, 26032760 }, + { 1020271667, 751686895, 150976424 }, + { 139914905, 477826617, 71902965 } + #else // in Montgomery representation + { 1073741824, 134217728, 67108864 }, + { 2147483649, 1879048193, 402653185 }, + { 1809501489, 1054751064, 265634015 }, + { 2877487492, 1193844673, 331740947 }, + { 2989687427, 665825587, 252496823 }, + { 3105485195, 1961758775, 114795379 }, + { 1920588894, 1994046595, 175397252 }, + { 703819063, 932019131, 314756028 }, + { 3020513810, 1682915367, 51434375 }, + { 713639124, 1015380543, 133810885 }, + { 946523922, 1576574394, 454008742 }, + { 2920407577, 1597744532, 191940679 }, + { 1627717094, 1589708641, 309595372 }, + { 2062650405, 126130591, 189567235 }, + { 615054086, 267042180, 382347871 }, + { 1719470156, 1681043157, 238769593 }, + { 961520328, 1992112863, 240663313 }, + { 2923061544, 81858141, 402250056 }, + { 808455044, 487635820, 302549471 }, + { 3213265361, 1681059681, 461303277 }, + { 1883955251, 1318650285, 254810522 }, + { 781279533, 1017987605, 179445770 }, + { 570193549, 1008968995, 459186762 }, + { 3103538692, 624914534, 466273834 }, + { 834835886, 1960521414, 331825355 }, + { 1807393093, 1292064821, 246867396 }, + { 2100845347, 1578757629, 56837012 } + #endif + }; + +// Define this for (cheap) consistency checks. +//#define DEBUG_FFTP3M + +// Define this for extensive consistency checks. +//#define DEBUG_FFTP3M_OPERATIONS + +// Define the algorithm of the backward FFT: +// Either FORWARD (a normal FFT followed by a permutation) +// or RECIPROOT (an FFT with reciprocal root of unity) +// or CLEVER (an FFT with reciprocal root of unity but clever computation +// of the reciprocals). +// Drawback of FORWARD: the permutation pass. +// Drawback of RECIPROOT: need all the powers of the root, not only half of them. +#define FORWARD 42 +#define RECIPROOT 43 +#define CLEVER 44 +#define FFTP3M_BACKWARD CLEVER + +#ifdef DEBUG_FFTP3M_OPERATIONS +#define check_fftp3m_word(x) if ((x.w1 >= p1) || (x.w2 >= p2) || (x.w3 >= p3)) cl_abort() +#else +#define check_fftp3m_word(x) +#endif + +// r := 0 mod p +static inline void zerop3m (fftp3m_word& r) +{ + r.w1 = 0; + r.w2 = 0; + r.w3 = 0; +} + +// r := x mod p +static inline void setp3m (uint32 x, fftp3m_word& r) +{ + var uint32 hi; + var uint32 lo; + hi = x >> (32-n1); lo = x << n1; divu_6432_3232(hi,lo,p1, ,r.w1=); + hi = x >> (32-n2); lo = x << n2; divu_6432_3232(hi,lo,p2, ,r.w2=); + hi = x >> (32-n3); lo = x << n3; divu_6432_3232(hi,lo,p3, ,r.w3=); +} + +// Chinese remainder theorem: +// (Z / p1 Z) x (Z / p2 Z) x (Z / p3 Z) == Z / p1*p2*p3 Z = Z / P Z. +// Return r as an integer >= 0, < p1*p2*p3, as 3-digit-sequence res. +// This routine also does the "de-Montgomerizing". +static void combinep3m (const fftp3m_word& r, uintD* resLSDptr) +{ + check_fftp3m_word(r); + // Compute e1 * v1 * r.w1 + e2 * v2 * r.w2 + e3 * v3 * r.w3 where + // vi == 2^-ni mod pi, and the idempotents ei are found as: + // xgcd(pi,p/pi) = 1 = ui*pi + vi*P/pi, ei = 1 - ui*pi. + // e1 = 1709008312966733882383995583 + // e2 = 2781580629833601225216537109 + // e3 = 1602397205945693664242711343 + // e1*v1 = 965961209845827124691257285 + // e2*v2 = 927193593718183024654651603 + // e3*v3 = 969191855872201893987508667 + // We will have 0 <= e1*v1 * r.w1 + e2*v2 * r.w2 + e3*v3 * r.w3 < + // < e1*v1 * p1 + e2*v2 * p2 + e3*v3 * p3 < 3 * 2^32 * p1*p2*p3 < 2^128. + // The sum of the products fits in 4 digits, we divide by p1*p2*p3 + // as a 3-digit sequence, thus getting the remainder. + #if 0 + #if CL_DS_BIG_ENDIAN_P + var const uintD p123 [3] = { 0x09D80000, 0x7C200001, 0x54000001 }; + var const uintD e1v1 [3] = { 0x031F063E, 0x1CD1F37E, 0x20E0C7C5 }; + var const uintD e2v2 [3] = { 0x02FEF4E1, 0x6E62C875, 0x788590D3 }; + var const uintD e3v3 [3] = { 0x0321B25B, 0xC8DB371B, 0xF0E861BB }; + #else + var const uintD p123 [3] = { 0x54000001, 0x7C200001, 0x09D80000 }; + var const uintD e1v1 [3] = { 0x20E0C7C5, 0x1CD1F37E, 0x031F063E }; + var const uintD e2v2 [3] = { 0x788590D3, 0x6E62C875, 0x02FEF4E1 }; + var const uintD e3v3 [3] = { 0xF0E861BB, 0xC8DB371B, 0x0321B25B }; + #endif + #else + // The final division step requires a shift left by 4 bits in order + // to normalize p1*p2*p3. We combine this shift left with the + // multiplications. Note that since e1v1 + e2v2 + e3v3 < p1*p2*p3, + // there is no risk of overflow. + #if CL_DS_BIG_ENDIAN_P + var const uintD p123 [3] = { 0x9D800007, 0xC2000015, 0x40000010 }; + var const uintD e1v1 [3] = { 0x31F063E1, 0xCD1F37E2, 0x0E0C7C50 }; + var const uintD e2v2 [3] = { 0x2FEF4E16, 0xE62C8757, 0x88590D30 }; + var const uintD e3v3 [3] = { 0x321B25BC, 0x8DB371BF, 0x0E861BB0 }; + #else + var const uintD p123 [3] = { 0x40000010, 0xC2000015, 0x9D800007 }; + var const uintD e1v1 [3] = { 0x0E0C7C50, 0xCD1F37E2, 0x31F063E1 }; + var const uintD e2v2 [3] = { 0x88590D30, 0xE62C8757, 0x2FEF4E16 }; + var const uintD e3v3 [3] = { 0x0E861BB0, 0x8DB371BF, 0x321B25BC }; + #endif + #endif + var uintD sum [4]; + var uintD* const sumLSDptr = arrayLSDptr(sum,4); + mulu_loop_lsp(r.w1,arrayLSDptr(e1v1,3), sumLSDptr,3); + lspref(sumLSDptr,3) += muluadd_loop_lsp(r.w2,arrayLSDptr(e2v2,3), sumLSDptr,3); + lspref(sumLSDptr,3) += muluadd_loop_lsp(r.w3,arrayLSDptr(e3v3,3), sumLSDptr,3); + #if 0 + {CL_ALLOCA_STACK; + var DS q; + var DS r; + UDS_divide(arrayMSDptr(sum,4),4,arrayLSDptr(sum,4), + arrayMSDptr(p123,3),3,arrayLSDptr(p123,3), + &q,&r + ); + ASSERT(q.len <= 1) + ASSERT(r.len <= 3) + copy_loop_lsp(r.LSDptr,arrayLSDptr(sum,4),r.len); + DS_clear_loop(arrayMSDptr(sum,4) mspop 1,3-r.len,arrayLSDptr(sum,4) lspop r.len); + } + #else + // Division wie UDS_divide mit a_len=4, b_len=3. + { + var uintD q_stern; + var uintD c1; + #if HAVE_DD + divuD(highlowDD(lspref(sumLSDptr,3),lspref(sumLSDptr,2)),lspref(arrayLSDptr(p123,3),2), q_stern=,c1=); + { var uintDD c2 = highlowDD(c1,lspref(sumLSDptr,1)); + var uintDD c3 = muluD(lspref(arrayLSDptr(p123,3),1),q_stern); + if (c3 > c2) + { q_stern = q_stern-1; + if (c3-c2 > highlowDD(lspref(arrayLSDptr(p123,3),2),lspref(arrayLSDptr(p123,3),1))) + { q_stern = q_stern-1; } + } } + #else + divuD(lspref(sumLSDptr,3),lspref(sumLSDptr,2),lspref(arrayLSDptr(p123,3),2), q_stern=,c1=); + { var uintD c2lo = lspref(sumLSDptr,1); + var uintD c3hi; + var uintD c3lo; + muluD(lspref(arrayLSDptr(p123,3),1),q_stern, c3hi=,c3lo=); + if ((c3hi > c1) || ((c3hi == c1) && (c3lo > c2lo))) + { q_stern = q_stern-1; + c3hi -= c1; if (c3lo < c2lo) { c3hi--; }; c3lo -= c2lo; + if ((c3hi > lspref(arrayLSDptr(p123,3),2)) || ((c3hi == lspref(arrayLSDptr(p123,3),2)) && (c3lo > lspref(arrayLSDptr(p123,3),1)))) + { q_stern = q_stern-1; } + } } + #endif + if (!(q_stern==0)) + { var uintD carry = mulusub_loop_lsp(q_stern,arrayLSDptr(p123,3),sumLSDptr,3); + if (carry > lspref(sumLSDptr,3)) + { q_stern = q_stern-1; + addto_loop_lsp(arrayLSDptr(p123,3),sumLSDptr,3); + } } + } + #endif + #ifdef DEBUG_FFTP3M_OPERATIONS + if (compare_loop_msp(sumLSDptr lspop 3,arrayMSDptr(p123,3),3) >= 0) + cl_abort(); + #endif + // Renormalize the division's remainder: shift right by 4 bits. + shiftrightcopy_loop_msp(sumLSDptr lspop 3,resLSDptr lspop 3,3,4,0); +} + +// r := (a + b) mod p +static inline void addp3m (const fftp3m_word& a, const fftp3m_word& b, fftp3m_word& r) +{ + var uint32 x; + + check_fftp3m_word(a); check_fftp3m_word(b); + // Add single 32-bit words mod pi. + if (((x = (a.w1 + b.w1)) < b.w1) || (x >= p1)) + x -= p1; + r.w1 = x; + if ((x = (a.w2 + b.w2)) >= p2) // x doesn't overflow since p2 <= 2^31 + x -= p2; + r.w2 = x; + if ((x = (a.w3 + b.w3)) >= p3) // x doesn't overflow since p3 <= 2^31 + x -= p3; + r.w3 = x; + check_fftp3m_word(r); +} + +// r := (a - b) mod p +static inline void subp3m (const fftp3m_word& a, const fftp3m_word& b, fftp3m_word& r) +{ + check_fftp3m_word(a); check_fftp3m_word(b); + // Subtract single 32-bit words mod pi. + r.w1 = (a.w1 < b.w1 ? a.w1-b.w1+p1 : a.w1-b.w1); + r.w2 = (a.w2 < b.w2 ? a.w2-b.w2+p2 : a.w2-b.w2); + r.w3 = (a.w3 < b.w3 ? a.w3-b.w3+p3 : a.w3-b.w3); + check_fftp3m_word(r); +} + +// r := (a * b) mod p +static void mulp3m (const fftp3m_word& a, const fftp3m_word& b, fftp3m_word& res) +{ + check_fftp3m_word(a); check_fftp3m_word(b); + // Multiplication à la Montgomery: + #define mul_mod_p(aw,bw,result_zuweisung,p,m,n,j,js,table) \ + { /* table[i] == i*2^(m-1) mod p for 0 <= i < 2^(m-n+1) */\ + var uint32 hi; \ + var uint32 lo; \ + mulu32(aw,bw, hi=,lo=); \ + /* hi has 2m-32 bits */ \ + var const int l = (m-1)-(32-n); \ + var uint32 r = table[hi>>l]; \ + hi = ((hi << (32-l)) >> (n-l)) | (lo >> n); \ + /* hi = c mod 2^(m-1), has m-1 bits */ \ + lo = lo & (bit(n)-1); \ + /* lo = d, has n bits */ \ + lo = (lo << js) - lo; \ + /* lo = d*|V|, has m bits */ \ + /* Finally compute (r + hi - lo) mod p. */ \ + if (m < 32) { \ + r += hi; \ + if (r >= p) \ + { r = r - p; } \ + } else { \ + if (((r += hi) < hi) || (r >= p)) \ + { r = r - p; } \ + } \ + r = (r < lo ? r-lo+p : r-lo); \ + /* ifdef DEBUG_FFTP3M_OPERATIONS * \ + var uint32 tmp; \ + mulu32(aw,bw, hi=,lo=); \ + divu_6432_3232(hi,lo,p, ,tmp=); \ + mulu32(tmp,j, hi=, lo=); \ + divu_6432_3232(hi,lo,p, ,tmp=); \ + if (tmp != 0) { tmp = p-tmp; } \ + if (tmp != r) \ + cl_abort(); \ + * endif DEBUG_FFTP3M_OPERATIONS */ \ + result_zuweisung r; \ + } + // p1 = 3*2^30+1, n1 = 30, j1 = 3 = 2^2-1 + static uint32 table1 [8] = + { 0, 2147483648, 1073741823, 3221225471, + 2147483646, 1073741821, 3221225469, 2147483644 + }; + mul_mod_p(a.w1,b.w1,res.w1=,p1,32,30,3,2,table1); + // p2 = 15*2^27+1, n2 = 27, j2 = 15 = 2^4-1 + static uint32 table2 [32] = + { 0, 1073741824, 134217727, 1207959551, + 268435454, 1342177278, 402653181, 1476395005, + 536870908, 1610612732, 671088635, 1744830459, + 805306362, 1879048186, 939524089, 2013265913, + 1073741816, 134217719, 1207959543, 268435446, + 1342177270, 402653173, 1476394997, 536870900, + 1610612724, 671088627, 1744830451, 805306354, + 1879048178, 939524081, 2013265905, 1073741808 + }; + mul_mod_p(a.w2,b.w2,res.w2=,p2,31,27,15,4,table2); + // p3 = 7*2^26+1, n3 = 26, j3 = 7 = 2^3-1 + static uint32 table3 [16] = + { 0, 268435456, 67108863, 335544319, + 134217726, 402653182, 201326589, 469762045, + 268435452, 67108859, 335544315, 134217722, + 402653178, 201326585, 469762041, 268435448 + }; + mul_mod_p(a.w3,b.w3,res.w3=,p3,29,26,7,3,table3); + #undef mul_mod_p + check_fftp3m_word(res); +} +#ifdef DEBUG_FFTP3M_OPERATIONS +static void mulp3m_doublecheck (const fftp3m_word& a, const fftp3m_word& b, fftp3m_word& r) +{ + fftp3m_word zero, ma, mb, or; + zerop3m(zero); + subp3m(zero,a, ma); + subp3m(zero,b, mb); + mulp3m(ma,mb, or); + mulp3m(a,b, r); + if (!((r.w1 == or.w1) && (r.w2 == or.w2) && (r.w3 == or.w3))) + cl_abort(); +} +#define mulp3m mulp3m_doublecheck +#endif /* DEBUG_FFTP3M_OPERATIONS */ + +// b := (a / 2) mod p +static inline void shiftp3m (const fftp3m_word& a, fftp3m_word& b) +{ + check_fftp3m_word(a); + b.w1 = (a.w1 & 1 ? (a.w1 >> 1) + (p1 >> 1) + 1 : (a.w1 >> 1)); + b.w2 = (a.w2 & 1 ? (a.w2 >> 1) + (p2 >> 1) + 1 : (a.w2 >> 1)); + b.w3 = (a.w3 & 1 ? (a.w3 >> 1) + (p3 >> 1) + 1 : (a.w3 >> 1)); + check_fftp3m_word(b); +} + +#ifndef _BIT_REVERSE +#define _BIT_REVERSE +// Reverse an n-bit number x. n>0. +static uintL bit_reverse (uintL n, uintL x) +{ + var uintL y = 0; + do { + y <<= 1; + y |= (x & 1); + x >>= 1; + } while (!(--n == 0)); + return y; +} +#endif + +// Compute an convolution mod p using FFT: z[0..N-1] := x[0..N-1] * y[0..N-1]. +static void fftp3m_convolution (const uintL n, const uintL N, // N = 2^n + fftp3m_word * x, // N words + fftp3m_word * y, // N words + fftp3m_word * z // N words result + ) +{ + CL_ALLOCA_STACK; + #if (FFTP3M_BACKWARD == RECIPROOT) || defined(DEBUG_FFTP3M) + var fftp3m_word* const w = cl_alloc_array(fftp3m_word,N); + #else + var fftp3m_word* const w = cl_alloc_array(fftp3m_word,(N>>1)+1); + #endif + var uintL i; + // Initialize w[i] to w^i, w a primitive N-th root of unity. + w[0] = fftp3m_roots_of_1[0]; + w[1] = fftp3m_roots_of_1[n]; + #if (FFTP3M_BACKWARD == RECIPROOT) || defined(DEBUG_FFTP3M) + for (i = 2; i < N; i++) + mulp3m(w[i-1],fftp3m_roots_of_1[n], w[i]); + #else // need only half of the roots + for (i = 2; i < N>>1; i++) + mulp3m(w[i-1],fftp3m_roots_of_1[n], w[i]); + #endif + #ifdef DEBUG_FFTP3M + // Check that w is really a primitive N-th root of unity. + { + var fftp3m_word w_N; + mulp3m(w[N-1],fftp3m_roots_of_1[n], w_N); + if (!( w_N.w1 == (uint32)1<>1]; + if (!( w_N.w1 == p1-((uint32)1<>1; // tmax = 2^(n-1) + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = t; + var uintL i2 = i1 + tmax; + // Butterfly: replace (x(i1),x(i2)) by + // (x(i1) + x(i2), x(i1) - x(i2)). + var fftp3m_word tmp; + tmp = x[i2]; + subp3m(x[i1],tmp, x[i2]); + addp3m(x[i1],tmp, x[i1]); + } + } + for (l = n-2; l>=0; l--) { + var const uintL smax = (uintL)1 << (n-1-l); + var const uintL tmax = (uintL)1 << l; + for (var uintL s = 0; s < smax; s++) { + var uintL exp = bit_reverse(n-1-l,s) << l; + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = (s << (l+1)) + t; + var uintL i2 = i1 + tmax; + // Butterfly: replace (x(i1),x(i2)) by + // (x(i1) + w^exp*x(i2), x(i1) - w^exp*x(i2)). + var fftp3m_word tmp; + mulp3m(x[i2],w[exp], tmp); + subp3m(x[i1],tmp, x[i2]); + addp3m(x[i1],tmp, x[i1]); + } + } + } + } + // Do an FFT of length N on y. + if (!squaring) { + var sintL l; + /* l = n-1 */ { + var uintL const tmax = N>>1; // tmax = 2^(n-1) + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = t; + var uintL i2 = i1 + tmax; + // Butterfly: replace (y(i1),y(i2)) by + // (y(i1) + y(i2), y(i1) - y(i2)). + var fftp3m_word tmp; + tmp = y[i2]; + subp3m(y[i1],tmp, y[i2]); + addp3m(y[i1],tmp, y[i1]); + } + } + for (l = n-2; l>=0; l--) { + var const uintL smax = (uintL)1 << (n-1-l); + var const uintL tmax = (uintL)1 << l; + for (var uintL s = 0; s < smax; s++) { + var uintL exp = bit_reverse(n-1-l,s) << l; + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = (s << (l+1)) + t; + var uintL i2 = i1 + tmax; + // Butterfly: replace (y(i1),y(i2)) by + // (y(i1) + w^exp*y(i2), y(i1) - w^exp*y(i2)). + var fftp3m_word tmp; + mulp3m(y[i2],w[exp], tmp); + subp3m(y[i1],tmp, y[i2]); + addp3m(y[i1],tmp, y[i1]); + } + } + } + } + // Multiply the transformed vectors into z. + for (i = 0; i < N; i++) + mulp3m(x[i],y[i], z[i]); + // Undo an FFT of length N on z. + { + var uintL l; + for (l = 0; l < n-1; l++) { + var const uintL smax = (uintL)1 << (n-1-l); + var const uintL tmax = (uintL)1 << l; + #if FFTP3M_BACKWARD != CLEVER + for (var uintL s = 0; s < smax; s++) { + var uintL exp = bit_reverse(n-1-l,s) << l; + #if FFTP3M_BACKWARD == RECIPROOT + if (exp > 0) + exp = N - exp; // negate exp (use w^-1 instead of w) + #endif + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = (s << (l+1)) + t; + var uintL i2 = i1 + tmax; + // Inverse Butterfly: replace (z(i1),z(i2)) by + // ((z(i1)+z(i2))/2, (z(i1)-z(i2))/(2*w^exp)). + var fftp3m_word sum; + var fftp3m_word diff; + addp3m(z[i1],z[i2], sum); + subp3m(z[i1],z[i2], diff); + shiftp3m(sum, z[i1]); + mulp3m(diff,w[exp], diff); shiftp3m(diff, z[i2]); + } + } + #else // FFTP3M_BACKWARD == CLEVER: clever handling of negative exponents + /* s = 0, exp = 0 */ { + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = t; + var uintL i2 = i1 + tmax; + // Inverse Butterfly: replace (z(i1),z(i2)) by + // ((z(i1)+z(i2))/2, (z(i1)-z(i2))/(2*w^exp)), + // with exp <-- 0. + var fftp3m_word sum; + var fftp3m_word diff; + addp3m(z[i1],z[i2], sum); + subp3m(z[i1],z[i2], diff); + shiftp3m(sum, z[i1]); + shiftp3m(diff, z[i2]); + } + } + for (var uintL s = 1; s < smax; s++) { + var uintL exp = bit_reverse(n-1-l,s) << l; + exp = (N>>1) - exp; // negate exp (use w^-1 instead of w) + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = (s << (l+1)) + t; + var uintL i2 = i1 + tmax; + // Inverse Butterfly: replace (z(i1),z(i2)) by + // ((z(i1)+z(i2))/2, (z(i1)-z(i2))/(2*w^exp)), + // with exp <-- (N/2 - exp). + var fftp3m_word sum; + var fftp3m_word diff; + addp3m(z[i1],z[i2], sum); + subp3m(z[i2],z[i1], diff); // note that w^(N/2) = -1 + shiftp3m(sum, z[i1]); + mulp3m(diff,w[exp], diff); shiftp3m(diff, z[i2]); + } + } + #endif + } + /* l = n-1 */ { + var const uintL tmax = N>>1; // tmax = 2^(n-1) + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = t; + var uintL i2 = i1 + tmax; + // Inverse Butterfly: replace (z(i1),z(i2)) by + // ((z(i1)+z(i2))/2, (z(i1)-z(i2))/2). + var fftp3m_word sum; + var fftp3m_word diff; + addp3m(z[i1],z[i2], sum); + subp3m(z[i1],z[i2], diff); + shiftp3m(sum, z[i1]); + shiftp3m(diff, z[i2]); + } + } + } + #if FFTP3M_BACKWARD == FORWARD + // Swap z[i] and z[N-i] for 0 < i < N/2. + for (i = (N>>1)-1; i > 0; i--) { + var fftp3m_word tmp = z[i]; + z[i] = z[N-i]; + z[N-i] = tmp; + } + #endif +} + +static void mulu_fft_modp3m (const uintD* sourceptr1, uintC len1, + const uintD* sourceptr2, uintC len2, + uintD* destptr) +// Es ist 2 <= len1 <= len2. +{ + // Methode: + // source1 ist ein Stück der Länge N1, source2 ein oder mehrere Stücke + // der Länge N2, mit N1+N2 <= N, wobei N Zweierpotenz ist. + // sum(i=0..N-1, x_i b^i) * sum(i=0..N-1, y_i b^i) wird errechnet, + // indem man die beiden Polynome + // sum(i=0..N-1, x_i T^i), sum(i=0..N-1, y_i T^i) + // multipliziert, und zwar durch Fourier-Transformation (s.o.). + var uint32 n; + integerlength32(len1-1, n=); // 2^(n-1) < len1 <= 2^n + var uintL len = (uintL)1 << n; // kleinste Zweierpotenz >= len1 + // Wählt man N = len, so hat man ceiling(len2/(len-len1+1)) * FFT(len). + // Wählt man N = 2*len, so hat man ceiling(len2/(2*len-len1+1)) * FFT(2*len). + // Wir wählen das billigere von beiden: + // Bei ceiling(len2/(len-len1+1)) <= 2 * ceiling(len2/(2*len-len1+1)) + // nimmt man N = len, bei ....... > ........ dagegen N = 2*len. + // (Wahl von N = 4*len oder mehr bringt nur in Extremfällen etwas.) + if (len2 > 2 * (len-len1+1) * (len2 <= (2*len-len1+1) ? 1 : ceiling(len2,(2*len-len1+1)))) { + n = n+1; + len = len << 1; + } + var const uintL N = len; // N = 2^n + CL_ALLOCA_STACK; + var fftp3m_word* const x = cl_alloc_array(fftp3m_word,N); + var fftp3m_word* const y = cl_alloc_array(fftp3m_word,N); + #ifdef DEBUG_FFTP3M + var fftp3m_word* const z = cl_alloc_array(fftp3m_word,N); + #else + var fftp3m_word* const z = x; // put z in place of x - saves memory + #endif + var uintD* const tmpprod = cl_alloc_array(uintD,len1+1); + var uintP i; + var uintL destlen = len1+len2; + clear_loop_lsp(destptr,destlen); + do { + var uintL len2p; // length of a piece of source2 + len2p = N - len1 + 1; + if (len2p > len2) + len2p = len2; + // len2p = min(N-len1+1,len2). + if (len2p == 1) { + // cheap case + var uintD* tmpptr = arrayLSDptr(tmpprod,len1+1); + mulu_loop_lsp(lspref(sourceptr2,0),sourceptr1,tmpptr,len1); + if (addto_loop_lsp(tmpptr,destptr,len1+1)) + if (inc_loop_lsp(destptr lspop (len1+1),destlen-(len1+1))) + cl_abort(); + } else { + var uintL destlenp = len1 + len2p - 1; + // destlenp = min(N,destlen-1). + var bool squaring = ((sourceptr1 == sourceptr2) && (len1 == len2p)); + // Fill factor x. + { + for (i = 0; i < len1; i++) + setp3m(lspref(sourceptr1,i), x[i]); + for (i = len1; i < N; i++) + zerop3m(x[i]); + } + // Fill factor y. + if (!squaring) { + for (i = 0; i < len2p; i++) + setp3m(lspref(sourceptr2,i), y[i]); + for (i = len2p; i < N; i++) + zerop3m(y[i]); + } + // Multiply. + if (!squaring) + fftp3m_convolution(n,N, &x[0], &y[0], &z[0]); + else + fftp3m_convolution(n,N, &x[0], &x[0], &z[0]); + // Add result to destptr[-destlen..-1]: + { + var uintD* ptr = destptr; + // ac2|ac1|ac0 are an accumulator. + var uint32 ac0 = 0; + var uint32 ac1 = 0; + var uint32 ac2 = 0; + var uint32 tmp; + for (i = 0; i < destlenp; i++) { + // Convert z[i] to a 3-digit number. + var uintD z_i[3]; + combinep3m(z[i],arrayLSDptr(z_i,3)); + #ifdef DEBUG_FFTP3M + if (!(arrayLSref(z_i,3,2) < N)) + cl_abort(); + #endif + // Add z[i] to the accumulator. + tmp = arrayLSref(z_i,3,0); + if ((ac0 += tmp) < tmp) { + if (++ac1 == 0) + ++ac2; + } + tmp = arrayLSref(z_i,3,1); + if ((ac1 += tmp) < tmp) + ++ac2; + tmp = arrayLSref(z_i,3,2); + ac2 += tmp; + // Add the accumulator's least significant word to destptr: + tmp = lspref(ptr,0); + if ((ac0 += tmp) < tmp) { + if (++ac1 == 0) + ++ac2; + } + lspref(ptr,0) = ac0; + lsshrink(ptr); + ac0 = ac1; + ac1 = ac2; + ac2 = 0; + } + // ac2 = 0. + if (ac1 > 0) { + if (!((i += 2) <= destlen)) + cl_abort(); + tmp = lspref(ptr,0); + if ((ac0 += tmp) < tmp) + ++ac1; + lspref(ptr,0) = ac0; + lsshrink(ptr); + tmp = lspref(ptr,0); + ac1 += tmp; + lspref(ptr,0) = ac1; + lsshrink(ptr); + if (ac1 < tmp) + if (inc_loop_lsp(ptr,destlen-i)) + cl_abort(); + } else if (ac0 > 0) { + if (!((i += 1) <= destlen)) + cl_abort(); + tmp = lspref(ptr,0); + ac0 += tmp; + lspref(ptr,0) = ac0; + lsshrink(ptr); + if (ac0 < tmp) + if (inc_loop_lsp(ptr,destlen-i)) + cl_abort(); + } + } + #ifdef DEBUG_FFTP3M + // If destlenp < N, check that the remaining z[i] are 0. + for (i = destlenp; i < N; i++) + if (z[i].w1 > 0 || z[i].w2 > 0 || z[i].w3 > 0) + cl_abort(); + #endif + } + // Decrement len2. + destptr = destptr lspop len2p; + destlen -= len2p; + sourceptr2 = sourceptr2 lspop len2p; + len2 -= len2p; + } while (len2 > 0); +} + +#undef n3 +#undef n2 +#undef n1 +#undef p3 +#undef p2 +#undef p1 diff --git a/src/base/digitseq/cl_DS_mul_fftr.h b/src/base/digitseq/cl_DS_mul_fftr.h new file mode 100644 index 0000000..cc1f865 --- /dev/null +++ b/src/base/digitseq/cl_DS_mul_fftr.h @@ -0,0 +1,1142 @@ +// Fast integer multiplication using FFT over the complex numbers, modified +// to work with real numbers only in the implementation. +// [Donald Ervin Knuth: The Art of Computer Programming, Vol. II: +// Seminumerical Algorithms, second edition. Section 4.3.3, p. 290-294.] +// Bruno Haible 6.5.1996, 24.-25.8.1996, 27.-30.8.1996 + +// FFT in the complex domain has the drawback that it needs careful round-off +// error analysis. But for CPUs with good floating-point performance it might +// nevertheless be better than FFT mod Z/mZ. + +// The usual FFT(2^n) computes the values of a polynomial p(z) mod (z^(2^n)-1) +// at the (2^n)-th roots of unity. For our purposes, we start out with +// polynomials with real coefficients. So the values at z_j = exp(2 pi i j/N) +// and z_-j = exp(- 2 pi i j/N) will be complex conjugates of each other, +// which means that there exists a polynomial r(z) of degree <= 1 with real +// coefficients such that p(z_j) = r(z_j) and p(z_-j) = r(z_-j). This +// implies that r(z) is the remainder of p(z) divided by +// (z - z_j) (z - z_-j) = (z^2 - 2 cos(2 pi j/N) z + 1). +// +// Based on this insight, we replace the usual n FFT steps +// for m = n...0: +// (z^(2^n)-1) = prod(j=0..2^(n-m)-1, (z^(2^m) - exp(2 pi j/2^(n-m)))) +// by +// for m = n...1: +// (z^(2^n)-1) = (z^(2^m)-1) * prod(j=1..2^(n-m)-1, factor_m[j](z)) +// where +// factor_m[j](z) = prod(k mod 2^n with k == j or k == -j mod 2^(n-m+1), +// (z - exp(2 pi i k/N)) ) +// = prod(k=0..2^(m-1)-1, +// (z - exp(2 pi i (j+2^(n-m+1)k)/N)) +// (z - exp(- 2 pi i (j+2^(n-m+1)k)/N)) ) +// = (z^(2^(m-1)) - exp(2 pi i j 2^(m-1)/N)) +// (z^(2^(m-1)) - exp(- 2 pi i j 2^(m-1)/N)) +// = (z^(2^(m-1)) - exp(2 pi i j/2^(n-m+1))) +// (z^(2^(m-1)) - exp(- 2 pi i j/2^(n-m+1))) +// = (z^(2^m) - 2 cos(2 pi j/2^(n-m+1)) z^(2^(m-1)) + 1). +// The factors and the input are real polynomials, hence all intermediate +// and final remainders will be real as well. +// +// The usual FFT algorithm +// Input: polynomial p in x[0..2^n-1]. +// for l = n-1..0: // step m=l+1 -> m=l +// for s in {0,..,2^(n-1-l)-1}: +// exp := bit_reverse(n-1-l,s)*2^l, +// // chinese remainder algorithm for (z^(2^(l+1)) - w^(2*exp)) = +// // = (z^(2^l) - w^exp) * (z^(2^l) - w^(exp+2^(n-1))). +// for t in {0,..,2^l-1}: +// i1 := s*2^(l+1) + t, i2 := s*2^(l+1) + 2^l + t, +// replace (x[i1],x[i2]) by (x[i1] + w^exp*x[i2], x[i1] - w^exp*x[i2]) +// Invariant: +// for m = n..0: +// for j in {0..2^(n-m)-1}: +// p(z) mod (z^(2^m) - exp(2 pi i j/2^(n-m))) +// in x[bit_reverse(n-m,j)*2^m .. bit_reverse(n-m,j)*2^m+2^m-1]. +// Output: p(z_j) in x[bit_reverse(n,j)]. +// is thus replaced by the algorithm +// Input: polynomial p in x[0..2^n-1]. +// for l = n-1..1: // step m=l+1 -> m=l +// for s in {0}: +// // chinese remainder algorithm for (z^(2^(l+1)) - 1) = +// // = (z^(2^l) - 1) * (z^(2^l) + 1). +// for t in {0,..,2^l-1}: +// i1 := t, i2 := 2^l + t, +// replace (x[i1],x[i2]) by (x[i1] + x[i2], x[i1] - x[i2]) +// for s in {1,..,2^(n-1-l)-1}: +// exp := shuffle(n-1-l,s)*2^(l-1), +// // chinese remainder algorithm for +// // (z^(2^(l+1)) - 2 cos(2 pi 2*exp/N) z^(2^l) + 1) = +// // = (z^(2^l) - 2 cos(2 pi exp/N) z^(2^(l-1)) + 1) +// // * (z^(2^l) - 2 cos(2 pi (2^(n-1)-exp)/N) z^(2^(l-1)) + 1) +// gam := 2 cos(2 pi exp/N), +// for t in {0,..,2^(l-1)-1}: +// i1 := s*2^(l+1) + t, i2 := s*2^(l+1) + 2^(l-1) + t, +// i3 := s*2^(l+1) + 2^l + t, i4 := s*2^(l+1) + 2^l + 2^(l-1) + t, +// replace (x[i1],x[i2],x[i3],x[i4]) by +// (x[i1]-x[i3] - x[i4]*gam, x[i3]*gam + x[i2]+x[i4]*(gam^2-1), +// x[i1]-x[i3] + x[i4]*gam, - x[i3]*gam + x[i2]+x[i4]*(gam^2-1)) +// Invariant: +// for m = n..1: +// p(z) mod (z^(2^m) - 1) in x[0..2^m-1], +// for j in {1,..,2^(n-m)-1}: +// p(z) mod (z^(2^m) - 2 cos(2 pi j/2^(n-m+1)) z^(2^(m-1)) + 1) +// in x[invshuffle(n-m,j)*2^m .. invshuffle(n-m,j)*2^m+2^m-1]. +// Output: p(z) mod (z^2 - 1) in x[0],x[1], +// p(z) mod (z^2 - 2 cos(2 pi j/2^n) z + 1) (0 < j < 2^(n-1)) +// in x[2*invshuffle(n-1,j)],x[2*invshuffle(n-1,j)+1]. +// +// The shuffle function is defined like this: +// shuffle(n,j) defined for n >= 0, 0 < j < 2^n, yields 0 < shuffle(n,j) < 2^n. +// Definition by splitting off the least significant bit: +// n = 0: void. +// n > 0: shuffle(n,1) = 2^(n-1), +// n > 0, 0 < j < 2^(n-1): shuffle(n,2*j) = shuffle(n-1,j), +// n > 0, 0 < j < 2^(n-1): shuffle(n,2*j+1) = 2^n - shuffle(n-1,j). +// Its inverse function is defined like this: +// invshuffle(n,j) defined for n >= 0, 0 < j < 2^n, 0 < invshuffle(n,j) < 2^n. +// Definition by splitting off the most significant bit: +// n = 0: void. +// n > 0, 0 < j < 2^(n-1): invshuffle(n,j) = invshuffle(n-1,j)*2, +// n > 0, j = 2^(n-1): invshuffle(n,j) = 1, +// n > 0, 2^(n-1) < j < 2^n: invshuffle(n,j) = invshuffle(n-1,2^n-j)*2+1. +// Note that shuffle(n,.) and invshuffle(n,.) are _not_ the same permutation +// for n>=4. + +// It is important to have precise round-off error estimates. Although +// (by laws of statistics) in the average the actual round-off error makes up +// only half of the bits provided for round-off protection, we cannot rely +// on this average behaviour, but have to produce correct results. +// +// Knuth's formula (42), p. 294, says: +// If we want to multiply l-bit words using an FFT(2^k), our floating point +// numbers shall have m >= 2(k+l) + k + log_2 k + 3.5 mantissa bits. +// +// Here is a more careful analysis, using absolute error estimates. +// +// 1. We assume floating point numbers with radix 2, with the properties: +// (i) Multiplication with 2^n and 2^-n is exact. +// (ii) Negation x -> -x is exact. +// (iii) Addition: When adding x and y, with |x| <= 2^a, |y| <= 2^a, +// the result |x+y| <= 2^(a+1) has an error <= e*2^(a+1-m). +// (iv) Multiplication: When multiplying x and y, with |x| <= 2^a, +// |y| <= 2^b, the result |x*y| <= 2^(a+b) has an error <= e*2^(a+b-m). +// (v) Division: When dividing x by y, with |x| <= 2^a, +// 2^b <= |y| <= 2^(b+1), the result |x/y| <= 2^(a-b) has an error +// <= e*2^(a-b-m). +// Here e = 1 for a truncating arithmetic, but e = 1/2 for a rounding +// arithmetic like IEEE single and double floats. +// 2. Let's introduce some notation: err(x) means |x'-x| where x is the +// exact mathematical value and x' is its representation in the machine. +// 3. From 1. we get for real numbers x,y: +// (i) err(2^n*x) = 2^n * err(x), +// (ii) err(-x) = err(x), +// (iii) |x| <= 2^a, |y| <= 2^a, then +// err(x+y) <= err(x) + err(y) + e*2^(a+1-m), +// [or .... ............... + e*2^(a-m) if |x+y| <= 2^a]. +// (iv) |x| <= 2^a, |y| <= 2^b, then +// err(x*y) <= 2^a * err(y) + 2^b * err(x) + e*2^(a+b-m). +// (v) |x| <= 2^a, 2^b <= |y| <= 2^(b+1), then +// err(x/y) <= 2^(-b) * err(x) + 2^(a-2b) * err(y) + e*2^(a-b-m). +// 4. Our complex arithmetic will be based on the formulas: +// (i) 2^n*(x+iy) = (2^n*x)+i(2^n*y) +// (ii) -(x+iy) = (-x)+i(-y) +// (iii) (x+iy)+(u+iv) = (x+u)+i(y+v) +// (iv) (x+iy)*(u+iv) = (x*u-y*v)+i(x*v+y*u) +// The notation err(z) means |z'-z|, as above, with |.| being the usual +// absolute value on complex numbers (_not_ the L^1 norm). +// 5. From 3. and 4. we get for complex numbers x,y: +// (i) err(2^n*x) = 2^n * err(x), +// (ii) err(-x) = err(x), +// (iii) |x| <= 2^a, |y| <= 2^a, then +// err(x+y) <= err(x) + err(y) + e*2^(a+3/2-m), +// (iv) |x| <= 2^a, |y| <= 2^b, then +// err(x*y) <= 2^a * err(y) + 2^b * err(x) + 3*e*2^(a+b+1/2-m). +// 6. We start out with precomputed roots of unity: +// |exp(2 pi i/2^n)| <= 1, +// err(exp(2 pi i/2^n)) <= e*2^(1/2-m), (even err(..)=0 for n=0,1,2), +// and compute exp(2 pi i * j/2^k) according to the binary digits of j. +// This way, each root of unity will be a product of at most k precomputed +// roots. If (j mod 2^(k-2)) has n bits, then exp(2 pi i * j/2^k) will +// be computed using n factors, i.e. n-1 complex multiplications, and by +// 5.iv. we'll have +// err(exp(2 pi i * j/2^k)) <= n*e*2^(1/2-m) + max(n-1,0)*3*e*2^(1/2-m) +// = max(4*n-3,0)*e*2^(1/2-m). +// Hence the maximum roots-of-unity error is (set n=k-2) +// err(w^j) <= (4*k-11)*e*2^(1/2-m), +// and the average roots-of-unity error is (set n=(k-2)/2) +// < 2*(k-2)*e*2^(1/2-m). +// 7. We use precomputed values of gam = 2*cos(2*pi*j/2^k) (0 < j < 2^(k-2)), +// 12*2^-k <= |gam| <= 2, +// err(gam) <= (4*k-11)*e*2^(3/2-m), +// and +// err(gam-1) <= (4*k-11)*e*2^(3/2-m), +// err(gam+1) <= (4*k-9)*e*2^(3/2-m), +// err(gam^2-1) <= (20*k-51)*e*2^(3/2-m), +// err(1/gam) <= (4*k-10)*e*(2*k-9/2-m). +// 8. Now we start the FFT. +// Before the first step, x_i are integral, |x_i| < 2^l and err(x_i) = 0. +// After the first butterfly, which replaces (x(i1),x(i2)) by +// (x(i1) + x(i2), x(i1) - x(i2)), we have |x_i| < 2^(l+1) and err(x_i) = 0. +// Then, for each of the remaining k-2 steps, a butterfly replaces +// (x[i1],x[i2],x[i3],x[i4]) by +// (x[i1]-x[i3] - x[i4]*gam, x[i3]*gam + x[i2]+x[i4]*(gam^2-1), +// x[i1]-x[i3] + x[i4]*gam, - x[i3]*gam + x[i2]+x[i4]*(gam^2-1)). +// Thus, after n steps we have |x_i| < 2^(l+3n) and err(x_i) <= E_i where +// E_0 = 0, +// E_1 = 0, +// E_(n+1) = ... +// +// This is just too complicated. We use fftc's round-off error estimates. +// As a consequence, sometimes the algorithm bails out, saying +// "FFT problem: checksum error"!!! + + +#if !(intDsize==32) +#error "real fft implemented only for intDsize==32" +#endif + + +#include "cl_floatparam.h" +#include "cl_io.h" +#include "cl_abort.h" + +#if defined(HAVE_LONGDOUBLE) && (long_double_mant_bits > double_mant_bits) && (defined(__i386__) || defined(__m68k__) || (defined(__sparc__) && 0)) +// Only these CPUs have fast "long double"s in hardware. +// On SPARC, "long double"s are emulated in software and don't work. +typedef long double fftr_real; +#define fftr_real_mant_bits long_double_mant_bits +#define fftr_real_rounds long_double_rounds +#else +typedef double fftr_real; +#define fftr_real_mant_bits double_mant_bits +#define fftr_real_rounds double_rounds +#endif + +// We need complex numbers for precomputing the roots of unity. +typedef struct fftr_complex { + fftr_real re; + fftr_real im; +} fftr_complex; + +// For every integer exp, we need to precompute gam = 2 cos(2 pi exp/N). +typedef union { + fftr_complex c; // exp(2 pi i exp/N) + struct { + fftr_real d; // gam = 2 cos(2 pi exp/N) + fftr_real e; // gam^2-1 + fftr_real f; // 1/gam + } gam; +} fftr_cosinus; + +static const fftr_complex fftr_roots_of_1 [32+1] = + // roots_of_1[n] is a (2^n)th root of unity in C. + // Also roots_of_1[n-1] = roots_of_1[n]^2. + // For simplicity we choose roots_of_1[n] = exp(2 pi i/2^n). + { + #if (fftr_real_mant_bits == double_mant_bits) + // These values have 64 bit precision. + { 1.0, 0.0 }, + { -1.0, 0.0 }, + { 0.0, 1.0 }, + { 0.7071067811865475244, 0.7071067811865475244 }, + { 0.9238795325112867561, 0.38268343236508977172 }, + { 0.9807852804032304491, 0.19509032201612826784 }, + { 0.99518472667219688623, 0.098017140329560601996 }, + { 0.9987954562051723927, 0.049067674327418014254 }, + { 0.9996988186962042201, 0.024541228522912288032 }, + { 0.99992470183914454094, 0.0122715382857199260795 }, + { 0.99998117528260114264, 0.0061358846491544753597 }, + { 0.9999952938095761715, 0.00306795676296597627 }, + { 0.99999882345170190993, 0.0015339801862847656123 }, + { 0.99999970586288221914, 7.6699031874270452695e-4 }, + { 0.99999992646571785114, 3.8349518757139558907e-4 }, + { 0.9999999816164292938, 1.9174759731070330744e-4 }, + { 0.9999999954041073129, 9.5873799095977345874e-5 }, + { 0.99999999885102682754, 4.793689960306688455e-5 }, + { 0.99999999971275670683, 2.3968449808418218729e-5 }, + { 0.9999999999281891767, 1.1984224905069706422e-5 }, + { 0.99999999998204729416, 5.9921124526424278428e-6 }, + { 0.99999999999551182357, 2.9960562263346607504e-6 }, + { 0.99999999999887795586, 1.4980281131690112288e-6 }, + { 0.999999999999719489, 7.4901405658471572114e-7 }, + { 0.99999999999992987223, 3.7450702829238412391e-7 }, + { 0.99999999999998246807, 1.8725351414619534487e-7 }, + { 0.999999999999995617, 9.36267570730980828e-8 }, + { 0.99999999999999890425, 4.6813378536549092695e-8 }, + { 0.9999999999999997261, 2.340668926827455276e-8 }, + { 0.99999999999999993153, 1.1703344634137277181e-8 }, + { 0.99999999999999998287, 5.8516723170686386908e-9 }, + { 0.9999999999999999957, 2.925836158534319358e-9 }, + { 0.9999999999999999989, 1.4629180792671596806e-9 } + #else (fftr_real_mant_bits > double_mant_bits) + // These values have 128 bit precision. + { 1.0L, 0.0L }, + { -1.0L, 0.0L }, + { 0.0L, 1.0L }, + { 0.707106781186547524400844362104849039284L, 0.707106781186547524400844362104849039284L }, + { 0.923879532511286756128183189396788286823L, 0.38268343236508977172845998403039886676L }, + { 0.980785280403230449126182236134239036975L, 0.195090322016128267848284868477022240928L }, + { 0.995184726672196886244836953109479921574L, 0.098017140329560601994195563888641845861L }, + { 0.998795456205172392714771604759100694444L, 0.0490676743274180142549549769426826583147L }, + { 0.99969881869620422011576564966617219685L, 0.0245412285229122880317345294592829250654L }, + { 0.99992470183914454092164649119638322435L, 0.01227153828571992607940826195100321214037L }, + { 0.999981175282601142656990437728567716173L, 0.00613588464915447535964023459037258091705L }, + { 0.999995293809576171511580125700119899554L, 0.00306795676296597627014536549091984251894L }, + { 0.99999882345170190992902571017152601905L, 0.001533980186284765612303697150264079079954L }, + { 0.999999705862882219160228217738765677117L, 7.66990318742704526938568357948576643142e-4L }, + { 0.99999992646571785114473148070738785695L, 3.83495187571395589072461681181381263396e-4L }, + { 0.999999981616429293808346915402909714504L, 1.91747597310703307439909561989000933469e-4L }, + { 0.99999999540410731289097193313960614896L, 9.58737990959773458705172109764763511872e-5L }, + { 0.9999999988510268275626733077945541084L, 4.79368996030668845490039904946588727468e-5L }, + { 0.99999999971275670684941397221864177609L, 2.39684498084182187291865771650218200947e-5L }, + { 0.999999999928189176709775095883850490262L, 1.198422490506970642152156159698898480473e-5L }, + { 0.99999999998204729417728262414778410738L, 5.99211245264242784287971180889086172999e-6L }, + { 0.99999999999551182354431058417299732444L, 2.99605622633466075045481280835705981183e-6L }, + { 0.999999999998877955886077016551752536504L, 1.49802811316901122885427884615536112069e-6L }, + { 0.999999999999719488971519214794719584451L, 7.49014056584715721130498566730655637157e-7L }, + { 0.99999999999992987224287980123972873676L, 3.74507028292384123903169179084633177398e-7L }, + { 0.99999999999998246806071995015624773673L, 1.8725351414619534486882457659356361712e-7L }, + { 0.999999999999995617015179987529456656217L, 9.3626757073098082799067286680885620193e-8L }, + { 0.999999999999998904253794996881763834182L, 4.68133785365490926951155181385400969594e-8L }, + { 0.99999999999999972606344874922040343793L, 2.34066892682745527595054934190348440379e-8L }, + { 0.999999999999999931515862187305098514444L, 1.170334463413727718124621350323810379807e-8L }, + { 0.999999999999999982878965546826274482047L, 5.8516723170686386908097901008341396944e-9L }, + { 0.999999999999999995719741386706568611352L, 2.92583615853431935792823046906895590202e-9L }, + { 0.999999999999999998929935346676642152265L, 1.46291807926715968052953216186596371037e-9L } + #endif + }; + +// Define this for (cheap) consistency checks. +#define DEBUG_FFTR + +static fftr_real fftr_pow2_table[64] = // table of powers of 2 + { + 1.0, + 2.0, + 4.0, + 8.0, + 16.0, + 32.0, + 64.0, + 128.0, + 256.0, + 512.0, + 1024.0, + 2048.0, + 4096.0, + 8192.0, + 16384.0, + 32768.0, + 65536.0, + 131072.0, + 262144.0, + 524288.0, + 1048576.0, + 2097152.0, + 4194304.0, + 8388608.0, + 16777216.0, + 33554432.0, + 67108864.0, + 134217728.0, + 268435456.0, + 536870912.0, + 1073741824.0, + 2147483648.0, + 4294967296.0, + 8589934592.0, + 17179869184.0, + 34359738368.0, + 68719476736.0, + 137438953472.0, + 274877906944.0, + 549755813888.0, + 1099511627776.0, + 2199023255552.0, + 4398046511104.0, + 8796093022208.0, + 17592186044416.0, + 35184372088832.0, + 70368744177664.0, + 140737488355328.0, + 281474976710656.0, + 562949953421312.0, + 1125899906842624.0, + 2251799813685248.0, + 4503599627370496.0, + 9007199254740992.0, + 18014398509481984.0, + 36028797018963968.0, + 72057594037927936.0, + 144115188075855872.0, + 288230376151711744.0, + 576460752303423488.0, + 1152921504606846976.0, + 2305843009213693952.0, + 4611686018427387904.0, + 9223372036854775808.0 + }; + +// For a constant expression n (0 <= n < 128), returns 2^n of type fftr_real. +#define fftr_pow2(n) \ + (((n) & 64 ? (fftr_real)18446744073709551616.0 : (fftr_real)1.0) \ + * ((n) & 32 ? (fftr_real)4294967296.0 : (fftr_real)1.0) \ + * ((n) & 16 ? (fftr_real)65536.0 : (fftr_real)1.0) \ + * ((n) & 8 ? (fftr_real)256.0 : (fftr_real)1.0) \ + * ((n) & 4 ? (fftr_real)16.0 : (fftr_real)1.0) \ + * ((n) & 2 ? (fftr_real)4.0 : (fftr_real)1.0) \ + * ((n) & 1 ? (fftr_real)2.0 : (fftr_real)1.0) \ + ) + +// r := a * b +static inline void mul (const fftr_complex& a, const fftr_complex& b, fftr_complex& r) +{ + var fftr_real r_re = a.re * b.re - a.im * b.im; + var fftr_real r_im = a.re * b.im + a.im * b.re; + r.re = r_re; + r.im = r_im; +} + +static uintL shuffle (uintL n, uintL x) +{ + var uintL y = 0; + var sintL v = 1; + // Invariant: y + v*shuffle(n,x). + do { + if (x & 1) + if (x == 1) + return y + (v << (n-1)); + else { + y = y + (v << n); + v = -v; + } + x >>= 1; + } while (!(--n == 0)); + cl_abort(); +} + +#if 0 // unused +static uintL invshuffle (uintL n, uintL x) +{ + var uintL y = 0; + var uintL v = 1; + // Invariant: y + v*invshuffle(n,x). + do { + if (x == ((uintL)1 << (n-1))) + return y + v; + else if (x > ((uintL)1 << (n-1))) { + x = ((uintL)1 << n) - x; + y = y+v; + } + v <<= 1; + } while (!(--n == 0)); + cl_abort(); +} +#endif + +// Compute a real convolution using FFT: z[0..N-1] := x[0..N-1] * y[0..N-1]. +static void fftr_convolution (const uintL n, const uintL N, // N = 2^n + fftr_real * x, // N numbers + fftr_real * y, // N numbers + fftr_real * z // N numbers result + ) +{ + CL_ALLOCA_STACK; + var fftr_cosinus* const w = cl_alloc_array(fftr_cosinus,N>>2); + var uintL i; + // Initialize w[exp].c to exp(2 pi i exp/N). + w[0].c = fftr_roots_of_1[0]; + { + var int j; + for (j = n-3; j>=0; j--) { + var fftr_complex r_j = fftr_roots_of_1[n-j]; + w[1<>2; i += (2<>2; i++) { + var fftr_real gam = w[i].c.re * (fftr_real)2.0; + w[i].gam.d = gam; + w[i].gam.e = (gam - (fftr_real)1.0) * (gam + (fftr_real)1.0); + w[i].gam.f = (fftr_real)1.0 / gam; + } + var bool squaring = (x == y); + // Do an FFT of length N on x. + { + var uintL l; + for (l = n-1; l > 0; l--) { + /* s = 0 */ { + var const uintL tmax = (uintL)1 << l; + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = t; + var uintL i2 = i1 + tmax; + // replace (x[i1],x[i2]) by + // (x[i1] + x[i2], x[i1] - x[i2]) + var fftr_real tmp; + tmp = x[i2]; + x[i2] = x[i1] - tmp; + x[i1] = x[i1] + tmp; + } + } + var const uintL smax = (uintL)1 << (n-1-l); + var const uintL tmax = (uintL)1 << (l-1); + for (var uintL s = 1; s < smax; s++) { + var uintL exp = shuffle(n-1-l,s) << (l-1); + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = (s << (l+1)) + t; + var uintL i2 = i1 + tmax; + var uintL i3 = i2 + tmax; + var uintL i4 = i3 + tmax; + // replace (x[i1],x[i2],x[i3],x[i4]) by + // (x[i1]-x[i3] - x[i4]*gam, + // x[i3]*gam + x[i2]+x[i4]*(gam^2-1), + // x[i1]-x[i3] + x[i4]*gam, + // - x[i3]*gam + x[i2]+x[i4]*(gam^2-1)) + var fftr_real sum13; + var fftr_real sum24; + var fftr_real tmp3; + var fftr_real tmp4; + sum13 = x[i1] - x[i3]; + tmp3 = x[i3]*w[exp].gam.d; + tmp4 = x[i4]*w[exp].gam.d; + sum24 = x[i2]+x[i4]*w[exp].gam.e; + x[i1] = sum13 - tmp4; + x[i3] = sum13 + tmp4; + x[i2] = sum24 + tmp3; + x[i4] = sum24 - tmp3; + } + } + } + /* l = 0 */ { + // replace (x[0],x[1]) by (x[0]+x[1], x[0]-x[1]) + var fftr_real tmp; + tmp = x[1]; + x[1] = x[0] - tmp; + x[0] = x[0] + tmp; + } + } + // Do an FFT of length N on y. + if (!squaring) { + var uintL l; + for (l = n-1; l > 0; l--) { + /* s = 0 */ { + var const uintL tmax = (uintL)1 << l; + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = t; + var uintL i2 = i1 + tmax; + // replace (y[i1],y[i2]) by + // (y[i1] + y[i2], y[i1] - y[i2]) + var fftr_real tmp; + tmp = y[i2]; + y[i2] = y[i1] - tmp; + y[i1] = y[i1] + tmp; + } + } + var const uintL smax = (uintL)1 << (n-1-l); + var const uintL tmax = (uintL)1 << (l-1); + for (var uintL s = 1; s < smax; s++) { + var uintL exp = shuffle(n-1-l,s) << (l-1); + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = (s << (l+1)) + t; + var uintL i2 = i1 + tmax; + var uintL i3 = i2 + tmax; + var uintL i4 = i3 + tmax; + // replace (y[i1],y[i2],y[i3],y[i4]) by + // (y[i1]-y[i3] - y[i4]*gam, + // y[i3]*gam + y[i2]+y[i4]*(gam^2-1), + // y[i1]-y[i3] + y[i4]*gam, + // - y[i3]*gam + y[i2]+y[i4]*(gam^2-1)) + var fftr_real sum13; + var fftr_real sum24; + var fftr_real tmp3; + var fftr_real tmp4; + sum13 = y[i1] - y[i3]; + tmp3 = y[i3]*w[exp].gam.d; + tmp4 = y[i4]*w[exp].gam.d; + sum24 = y[i2]+y[i4]*w[exp].gam.e; + y[i1] = sum13 - tmp4; + y[i3] = sum13 + tmp4; + y[i2] = sum24 + tmp3; + y[i4] = sum24 - tmp3; + } + } + } + /* l = 0 */ { + // replace (y[0],y[1]) by (y[0]+y[1], y[0]-y[1]) + var fftr_real tmp; + tmp = y[1]; + y[1] = y[0] - tmp; + y[0] = y[0] + tmp; + } + } + // Multiply the transformed vectors into z. + { + // Multiplication mod (z-1). + z[0] = x[0] * y[0]; + // Multiplication mod (z+1). + z[1] = x[1] * y[1]; + #if 0 // This needs w[1..2^(n-1)-1]. + var const uintL smax = (uintL)1 << (n-1); + for (var uintL s = 1; s < smax; s++) { + // Multiplication mod (z^2 - 2 cos(2 pi j/2^n) z + 1) + // with j = shuffle(n-1,s). + var uintL exp = shuffle(n-1,s); + var fftr_real tmp0 = x[2*s] * y[2*s]; + var fftr_real tmp1 = x[2*s] * y[2*s+1] + x[2*s+1] * y[2*s]; + var fftr_real tmp2 = x[2*s+1] * y[2*s+1]; + z[2*s] = tmp0 - tmp2; + z[2*s+1] = tmp1 + tmp2*w[exp].gam.d; + } + #else // This only needs w[1..2^(n-2)-1]. + // Multiplication mod (z^2+1). + /* s = 1 */ { + var fftr_real tmp0 = x[2] * y[2]; + var fftr_real tmp1 = x[2] * y[3] + x[3] * y[2]; + var fftr_real tmp2 = x[3] * y[3]; + z[2] = tmp0 - tmp2; + z[3] = tmp1; + } + var const uintL smax = (uintL)1 << (n-2); + for (var uintL s = 1; s < smax; s++) { + var uintL exp = shuffle(n-2,s); + // Multiplication mod (z^2 - 2 cos(2 pi j/2^n) z + 1) + // with j = shuffle(n-1,2*s) = shuffle(n-2,s). + var fftr_real gam = w[exp].gam.d; + { + var fftr_real tmp0 = x[4*s] * y[4*s]; + var fftr_real tmp1 = x[4*s] * y[4*s+1] + x[4*s+1] * y[4*s]; + var fftr_real tmp2 = x[4*s+1] * y[4*s+1]; + z[4*s] = tmp0 - tmp2; + z[4*s+1] = tmp1 + tmp2 * gam; + } + // Multiplication mod (z^2 - 2 cos(2 pi j/2^n) z + 1) + // with j = shuffle(n-1,2*s+1) = 2^(n-1) - shuffle(n-2,s). + { + var fftr_real tmp0 = x[4*s+2] * y[4*s+2]; + var fftr_real tmp1 = x[4*s+2] * y[4*s+3] + x[4*s+3] * y[4*s+2]; + var fftr_real tmp2 = x[4*s+3] * y[4*s+3]; + z[4*s+2] = tmp0 - tmp2; + z[4*s+3] = tmp1 - tmp2 * gam; + } + } + #endif + } + // Undo an FFT of length N on z. + { + var uintL l; + /* l = 0 */ { + // replace (z[0],z[1]) by ((z[0]+z[1])/2, (z[0]-z[1])/2) + var fftr_real tmp; + tmp = z[1]; + z[1] = (z[0] - tmp) * (fftr_real)0.5; + z[0] = (z[0] + tmp) * (fftr_real)0.5; + } + for (l = 1; l < n; l++) { + /* s = 0 */ { + var const uintL tmax = (uintL)1 << l; + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = t; + var uintL i2 = i1 + tmax; + // replace (z[i1],z[i2]) by + // ((z[i1]+z[i2])/2, (z[i1]-z[i2])/2) + // Do the division by 2 later. + var fftr_real tmp; + tmp = z[i2]; + z[i2] = z[i1] - tmp; + z[i1] = z[i1] + tmp; + } + } + var const uintL smax = (uintL)1 << (n-1-l); + var const uintL tmax = (uintL)1 << (l-1); + for (var uintL s = 1; s < smax; s++) { + var uintL exp = shuffle(n-1-l,s) << (l-1); + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = (s << (l+1)) + t; + var uintL i2 = i1 + tmax; + var uintL i3 = i2 + tmax; + var uintL i4 = i3 + tmax; + // replace (z[i1],z[i2],z[i3],z[i4]) by + // ((z[i1]+z[i3]+(z[i2]-z[i4])/gam)/2, + // (z[i2]+z[i4]-(z[i3]-z[i1])/gam*(gam^2-1))/2, + // (z[i2]-z[i4])/(gam*2), + // (z[i3]-z[i1])/(gam*2)) + // Do the division by 2 later. + var fftr_real sum13; + var fftr_real sum24; + var fftr_real tmp3; + var fftr_real tmp4; + sum13 = z[i1] + z[i3]; + sum24 = z[i2] + z[i4]; + tmp4 = (z[i3] - z[i1]) * w[exp].gam.f; + tmp3 = (z[i2] - z[i4]) * w[exp].gam.f; + z[i1] = sum13 + tmp3; + z[i2] = sum24 - tmp4*w[exp].gam.e; + z[i3] = tmp3; + z[i4] = tmp4; + } + } + } + // Do all divisions by 2 now. + { + var fftr_real f = (fftr_real)2.0 / (fftr_real)N; // 2^-(n-1) + for (i = 0; i < N; i++) + z[i] = z[i]*f; + } + } +} + +// For a given k >= 2, the maximum l is determined by +// 2*l < m - 1/2 - 2*k - log_2(12*k-15) - (1 if e=1.0, 0 if e=0.5). +// This is a decreasing function of k. +#define max_l(k) \ + (int)((fftr_real_mant_bits \ + - 2*(k) \ + - ((k)<=2 ? 4 : (k)<=3 ? 5 : (k)<=5 ? 6 : (k)<=8 ? 7 : (k)<=16 ? 8 : (k)<=31 ? 9 : 10) \ + - (fftr_real_rounds == rounds_to_nearest ? 0 : 1)) \ + / 2) +static int max_l_table[32+1] = + { 0, 0, max_l(2), max_l(3), max_l(4), max_l(5), max_l(6), + max_l(7), max_l(8), max_l(9), max_l(10), max_l(11), max_l(12), max_l(13), + max_l(14), max_l(15), max_l(16), max_l(17), max_l(18), max_l(19), max_l(20), + max_l(21), max_l(22), max_l(23), max_l(24), max_l(25), max_l(26), max_l(27), + max_l(28), max_l(29), max_l(30), max_l(31), max_l(32) + }; + +// Split len uintD's below sourceptr into chunks of l bits, thus filling +// N real numbers at x. +static void fill_factor (uintL N, fftr_real* x, uintL l, + const uintD* sourceptr, uintL len) +{ + var uintL i; + if (max_l(2) > intDsize && l > intDsize) { + // l > intDsize + if (max_l(2) > 64 && l > 64) { + fprint(cl_stderr, "FFT problem: l > 64 not supported by pow2_table\n"); + cl_abort(); + } + var fftr_real carry = 0; + var sintL carrybits = 0; // number of bits in carry (>=0, 0) { + var uintD digit = lsprefnext(sourceptr); + if (carrybits+intDsize >= l) { + x[i] = carry + (fftr_real)(digit & bitm(l-carrybits)) * fftr_pow2_table[carrybits]; + i++; + carry = (l-carrybits == intDsize ? (fftr_real)0 : (fftr_real)(digit >> (l-carrybits))); + carrybits = carrybits+intDsize-l; + } else { + carry = carry + (fftr_real)digit * fftr_pow2_table[carrybits]; + carrybits = carrybits+intDsize; + } + len--; + } + if (carrybits > 0) { + x[i] = carry; + i++; + } + if (i > N) + cl_abort(); + } else if (max_l(2) >= intDsize && l == intDsize) { + // l = intDsize + if (len > N) + cl_abort(); + for (i = 0; i < len; i++) { + var uintD digit = lsprefnext(sourceptr); + x[i] = (fftr_real)digit; + } + } else { + // l < intDsize + var const uintD l_mask = bit(l)-1; + var uintD carry = 0; + var sintL carrybits = 0; // number of bits in carry (>=0, = l) { + x[i] = (fftr_real)(carry & l_mask); + carry >>= l; + carrybits -= l; + } else { + if (len == 0) + break; + len--; + var uintD digit = lsprefnext(sourceptr); + x[i] = (fftr_real)((carry | (digit << carrybits)) & l_mask); + carry = digit >> (l-carrybits); + carrybits = intDsize - (l-carrybits); + } + } + while (carrybits > 0) { + if (!(i < N)) + cl_abort(); + x[i] = (fftr_real)(carry & l_mask); + carry >>= l; + carrybits -= l; + i++; + } + if (len > 0) + cl_abort(); + } + for ( ; i < N; i++) + x[i] = (fftr_real)0; +} + +// Given a not too large floating point number, round it to the nearest integer. +static inline fftr_real fftr_fround (fftr_real x) +{ + return + #if (fftr_real_rounds == rounds_to_nearest) + (x + (fftr_pow2(fftr_real_mant_bits-1)+fftr_pow2(fftr_real_mant_bits-2))) + - (fftr_pow2(fftr_real_mant_bits-1)+fftr_pow2(fftr_real_mant_bits-2)); + #elif (fftr_real_rounds == rounds_to_infinity) + (fftr_pow2(fftr_real_mant_bits-1)+fftr_pow2(fftr_real_mant_bits-2)) + - ((fftr_pow2(fftr_real_mant_bits-1)+fftr_pow2(fftr_real_mant_bits-2)) + - (x + (fftr_real)0.5)); + #else // rounds_to_zero, rounds_to_minus_infinity + ((x + (fftr_real)0.5) + + (fftr_pow2(fftr_real_mant_bits-1)+fftr_pow2(fftr_real_mant_bits-2))) + - (fftr_pow2(fftr_real_mant_bits-1)+fftr_pow2(fftr_real_mant_bits-2)); + #endif +} + +// Given a not too large floating point number, round it down. +static inline fftr_real fftr_ffloor (fftr_real x) +{ + #if (fftr_real_rounds == rounds_to_nearest) + var fftr_real y = + (x + (fftr_pow2(fftr_real_mant_bits-1)+fftr_pow2(fftr_real_mant_bits-2))) + - (fftr_pow2(fftr_real_mant_bits-1)+fftr_pow2(fftr_real_mant_bits-2)); + if (y <= x) + return y; + else + return y - (fftr_real)1.0; + #elif (fftr_real_rounds == rounds_to_infinity) + return + (fftr_pow2(fftr_real_mant_bits-1)+fftr_pow2(fftr_real_mant_bits-2)) + - ((fftr_pow2(fftr_real_mant_bits-1)+fftr_pow2(fftr_real_mant_bits-2)) + - x); + #else // rounds_to_zero, rounds_to_minus_infinity + return + (x + (fftr_pow2(fftr_real_mant_bits-1)+fftr_pow2(fftr_real_mant_bits-2))) + - (fftr_pow2(fftr_real_mant_bits-1)+fftr_pow2(fftr_real_mant_bits-2)); + #endif +} + +// Combine the N real numbers at z into uintD's below destptr. +// The z[i] are known to be approximately integers >= 0, < N*2^(2*l). +// Assumes room for floor(N*l/intDsize)+(1+ceiling((n+2*l)/intDsize)) uintD's +// below destptr. Fills len digits and returns (destptr lspop len). +static uintD* unfill_product (uintL n, uintL N, // N = 2^n + const fftr_real * z, uintL l, + uintD* destptr) +{ + var uintL i; + if (n + 2*l <= intDsize) { + // 2-digit carry is sufficient, l < intDsize + var uintD carry0 = 0; + var uintD carry1 = 0; + var uintL shift = 0; // shift next digit before adding it to the carry, >=0, 0) { + carry1 += digit >> (intDsize-shift); + digit = digit << shift; + } + if ((carry0 += digit) < digit) + carry1 += 1; + shift += l; + if (shift >= intDsize) { + lsprefnext(destptr) = carry0; + carry0 = carry1; + carry1 = 0; + shift -= intDsize; + } + } + lsprefnext(destptr) = carry0; + lsprefnext(destptr) = carry1; + } else if (n + 2*l <= 2*intDsize) { + // 3-digit carry is sufficient, l < intDsize + #if HAVE_DD + var uintDD carry0 = 0; + var uintD carry1 = 0; + var uintL shift = 0; // shift next digit before adding it to the carry, >=0, 0) { + carry1 += (uintD)(digit >> (2*intDsize-shift)); + digit = digit << shift; + } + if ((carry0 += digit) < digit) + carry1 += 1; + shift += l; + if (shift >= intDsize) { + lsprefnext(destptr) = lowD(carry0); + carry0 = highlowDD(carry1,highD(carry0)); + carry1 = 0; + shift -= intDsize; + } + } + lsprefnext(destptr) = lowD(carry0); + lsprefnext(destptr) = highD(carry0); + lsprefnext(destptr) = carry1; + #else + var uintD carry0 = 0; + var uintD carry1 = 0; + var uintD carry2 = 0; + var uintL shift = 0; // shift next digit before adding it to the carry, >=0, 0) { + carry2 += digit1 >> (intDsize-shift); + digit1 = (digit1 << shift) | (digit0 >> (intDsize-shift)); + digit0 = digit0 << shift; + } + if ((carry0 += digit0) < digit0) + if ((carry1 += 1) == 0) + carry2 += 1; + if ((carry1 += digit1) < digit1) + carry2 += 1; + shift += l; + if (shift >= intDsize) { + lsprefnext(destptr) = carry0; + carry0 = carry1; + carry1 = carry2; + carry2 = 0; + shift -= intDsize; + } + } + lsprefnext(destptr) = carry0; + lsprefnext(destptr) = carry1; + lsprefnext(destptr) = carry2; + #endif + } else { + // 1-digit+1-float carry is sufficient + var uintD carry0 = 0; + var fftr_real carry1 = 0; + var uintL shift = 0; // shift next digit before adding it to the carry, >=0, = (fftr_real)0 + && z[i] > digit - (fftr_real)0.5 + && z[i] < digit + (fftr_real)0.5)) + cl_abort(); + #endif + if (shift > 0) + digit = digit * fftr_pow2_table[shift]; + var fftr_real digit1 = fftr_ffloor(digit*((fftr_real)1.0/fftr_pow2(intDsize))); + var uintD digit0 = (uintD)(digit - digit1*fftr_pow2(intDsize)); + carry1 += digit1; + if ((carry0 += digit0) < digit0) + carry1 += (fftr_real)1.0; + shift += l; + while (shift >= intDsize) { + lsprefnext(destptr) = carry0; + var fftr_real tmp = fftr_ffloor(carry1*((fftr_real)1.0/fftr_pow2(intDsize))); + carry0 = (uintD)(carry1 - tmp*fftr_pow2(intDsize)); + carry1 = tmp; + shift -= intDsize; + } + } + if (carry0 > 0 || carry1 > (fftr_real)0.0) { + lsprefnext(destptr) = carry0; + while (carry1 > (fftr_real)0.0) { + var fftr_real tmp = fftr_ffloor(carry1*((fftr_real)1.0/fftr_pow2(intDsize))); + lsprefnext(destptr) = (uintD)(carry1 - tmp*fftr_pow2(intDsize)); + carry1 = tmp; + } + } + } + return destptr; +} + +static inline void mulu_fftr_nocheck (const uintD* sourceptr1, uintC len1, + const uintD* sourceptr2, uintC len2, + uintD* destptr) +// Es ist 2 <= len1 <= len2. +{ + // We have to find parameters l and k such that + // ceiling(len1*intDsize/l) + ceiling(len2*intDsize/l) - 1 <= 2^k, + // and (12*k-15)*e*2^(2*l+2*k+1/2-m) < 1/2. + // Try primarily to minimize k. Minimizing l buys you nothing. + var uintL k; + // Computing k: If len1 and len2 differ much, we'll split source2 - + // hence for the moment just substitute len1 for len2. + // + // First approximation of k: A necessary condition for + // 2*ceiling(len1*intDsize/l) - 1 <= 2^k + // is 2*len1*intDsize/l_max - 1 <= 2^k. + { + var const int l = max_l(2); + var uintL lhs = 2*ceiling((uintL)len1*intDsize,l) - 1; // >=1 + if (lhs < 3) + k = 2; + else + integerlength32(lhs-1, k=); // k>=2 + } + // Try whether this k is ok or whether we have to increase k. + for ( ; ; k++) { + if (k >= sizeof(max_l_table)/sizeof(max_l_table[0]) + || max_l_table[k] <= 0) { + fprint(cl_stderr, "FFT problem: numbers too big, floating point precision not sufficient\n"); + cl_abort(); + } + if (2*ceiling((uintL)len1*intDsize,max_l_table[k])-1 <= ((uintL)1 << k)) + break; + } + // We could try to reduce l, keeping the same k. But why should we? + // Calculate the number of pieces in which source2 will have to be + // split. Each of the pieces must satisfy + // ceiling(len1*intDsize/l) + ceiling(len2*intDsize/l) - 1 <= 2^k, + var uintL len2p; + // Try once with k, once with k+1. Compare them. + { + var uintL remaining_k = ((uintL)1 << k) + 1 - ceiling((uintL)len1*intDsize,max_l_table[k]); + var uintL max_piecelen_k = floor(remaining_k*max_l_table[k],intDsize); + var uintL numpieces_k = ceiling(len2,max_piecelen_k); + var uintL remaining_k1 = ((uintL)1 << (k+1)) + 1 - ceiling((uintL)len1*intDsize,max_l_table[k+1]); + var uintL max_piecelen_k1 = floor(remaining_k1*max_l_table[k+1],intDsize); + var uintL numpieces_k1 = ceiling(len2,max_piecelen_k1); + if (numpieces_k <= 2*numpieces_k1) { + // keep k + len2p = max_piecelen_k; + } else { + // choose k+1 + k = k+1; + len2p = max_piecelen_k1; + } + } + var const uintL l = max_l_table[k]; + var const uintL n = k; + var const uintL N = (uintL)1 << n; + CL_ALLOCA_STACK; + var fftr_real* const x = cl_alloc_array(fftr_real,N); + var fftr_real* const y = cl_alloc_array(fftr_real,N); + #ifdef DEBUG_FFTR + var fftr_real* const z = cl_alloc_array(fftr_real,N); + #else + var fftr_real* const z = x; // put z in place of x - saves memory + #endif + var uintD* const tmpprod1 = cl_alloc_array(uintD,len1+1); + var uintL tmpprod_len = floor(l< len2) + len2p = len2; + if (len2p == 1) { + // cheap case + var uintD* tmpptr = arrayLSDptr(tmpprod1,len1+1); + mulu_loop_lsp(lspref(sourceptr2,0),sourceptr1,tmpptr,len1); + if (addto_loop_lsp(tmpptr,destptr,len1+1)) + if (inc_loop_lsp(destptr lspop (len1+1),destlen-(len1+1))) + cl_abort(); + } else { + var bool squaring = ((sourceptr1 == sourceptr2) && (len1 == len2p)); + // Fill factor x. + fill_factor(N,x,l,sourceptr1,len1); + // Fill factor y. + if (!squaring) + fill_factor(N,y,l,sourceptr2,len2p); + // Multiply. + if (!squaring) + fftr_convolution(n,N, &x[0], &y[0], &z[0]); + else + fftr_convolution(n,N, &x[0], &x[0], &z[0]); + #ifdef DEBUG_FFTR + // Check result. + { + var fftr_real re_lo_limit = (fftr_real)(-0.5); + var fftr_real re_hi_limit = (fftr_real)N * fftr_pow2_table[l] * fftr_pow2_table[l] + (fftr_real)0.5; + for (var uintL i = 0; i < N; i++) + if (!(z[i] > re_lo_limit + && z[i] < re_hi_limit)) + cl_abort(); + } + #endif + var uintD* tmpLSDptr = arrayLSDptr(tmpprod,tmpprod_len); + var uintD* tmpMSDptr = unfill_product(n,N,z,l,tmpLSDptr); + var uintL tmplen = + #if CL_DS_BIG_ENDIAN_P + tmpLSDptr - tmpMSDptr; + #else + tmpMSDptr - tmpLSDptr; + #endif + if (tmplen > tmpprod_len) + cl_abort(); + // Add result to destptr[-destlen..-1]: + if (tmplen > destlen) { + if (test_loop_msp(tmpMSDptr,tmplen-destlen)) + cl_abort(); + tmplen = destlen; + } + if (addto_loop_lsp(tmpLSDptr,destptr,tmplen)) + if (inc_loop_lsp(destptr lspop tmplen,destlen-tmplen)) + cl_abort(); + } + // Decrement len2. + destptr = destptr lspop len2p; + destlen -= len2p; + sourceptr2 = sourceptr2 lspop len2p; + len2 -= len2p; + } while (len2 > 0); +} + +#ifndef _CHECKSUM +#define _CHECKSUM + +// Compute a checksum: number mod (2^intDsize-1). +static uintD compute_checksum (const uintD* sourceptr, uintC len) +{ + var uintD tmp = ~(uintD)0; // -1-(sum mod 2^intDsize-1), always >0 + do { + var uintD digit = lsprefnext(sourceptr); + if (digit < tmp) + tmp -= digit; // subtract digit + else + tmp -= digit+1; // subtract digit-(2^intDsize-1) + } while (--len > 0); + return ~tmp; +} + +// Multiply two checksums modulo (2^intDsize-1). +static inline uintD multiply_checksum (uintD checksum1, uintD checksum2) +{ + var uintD checksum; + var uintD cksum_hi; + #if HAVE_DD + var uintDD cksum = muluD(checksum1,checksum2); + cksum_hi = highD(cksum); checksum = lowD(cksum); + #else + muluD(checksum1,checksum2, cksum_hi =, checksum =); + #endif + if ((checksum += cksum_hi) + 1 <= cksum_hi) + checksum += 1; + return checksum; +} + +#endif // _CHECKSUM + +static void mulu_fftr (const uintD* sourceptr1, uintC len1, + const uintD* sourceptr2, uintC len2, + uintD* destptr) +{ + // Compute checksums of the arguments and multiply them. + var uintD checksum1 = compute_checksum(sourceptr1,len1); + var uintD checksum2 = compute_checksum(sourceptr2,len2); + var uintD checksum = multiply_checksum(checksum1,checksum2); + mulu_fftr_nocheck(sourceptr1,len1,sourceptr2,len2,destptr); + if (!(checksum == compute_checksum(destptr,len1+len2))) { + fprint(cl_stderr, "FFT problem: checksum error\n"); + cl_abort(); + } +} diff --git a/src/base/digitseq/cl_DS_mul_kara.h b/src/base/digitseq/cl_DS_mul_kara.h new file mode 100644 index 0000000..fba0a1b --- /dev/null +++ b/src/base/digitseq/cl_DS_mul_kara.h @@ -0,0 +1,260 @@ + + static void mulu_karatsuba (const uintD* sourceptr1, uintC len1, + const uintD* sourceptr2, uintC len2, + uintD* destptr) + // Karatsuba-Multiplikation + // Prinzip: (x1*b^k+x0) * (y1*b^k+y0) + // = x1*y1 * b^2k + ((x1+x0)*(y1+y0)-x1*y1-x0*y0) * b^k + x0*y0 + // Methode 1 (Collins/Loos, Degel): + // source2 wird in floor(len2/len1) einzelne UDS mit je einer + // Länge len3 (len1 <= len3 < 2*len1) unterteilt, + // jeweils k=floor(len3/2). + // Methode 2 (Haible): + // source2 wird in ceiling(len2/len1) einzelne UDS mit je einer + // Länge len3 (0 < len3 <= len1) unterteilt, jeweils k=floor(len1/2). + // Aufwand für die hinteren Einzelteile: + // bei beiden Methoden jeweils 3*len1^2. + // Aufwand für das vorderste Teil (alles, falls len1 <= len2 < 2*len1) + // mit r = len1, s = (len2 mod len1) + len1 (>= len1, < 2*len1): + // bei Methode 1: + // | : | r + // | : | s + // (r-s/2)*s/2 + s/2*s/2 + s/2*s/2 = r*s/2 + s^2/4 . + // bei Methode 2: + // | : | r + // | | : | s + // (s-r)*r + r/2*r/2 + r/2*r/2 + r/2*r/2 = r*s - r^2/4 . + // Wegen (r*s/2 + s^2/4) - (r*s - r^2/4) = (r-s)^2/4 >= 0 + // ist Methode 2 günstiger. + // Denkfehler! Dies gilt - wenn überhaupt - nur knapp oberhalb des + // Break-Even-Points. + // Im allgemeinen ist der Multiplikationsaufwand für zwei Zahlen der + // Längen u bzw. v nämlich gegeben durch min(u,v)^c * max(u,v), + // wobei c = log3/log2 - 1 = 0.585... + // Dadurch wird der Aufwand in Abhängigkeit des Parameters t = k, + // r/2 <= t <= s/2 (der einzig sinnvolle Bereich), zu + // (r-t)^c*(s-t) + t^c*(s-t) + t^(1+c). + // Dessen Optimum liegt (im Bereich r <= s <= 2*r) + // - im klassischen Fall c=1 tatsächlich stets bei t=r/2 [Methode 2], + // - im Karatsuba-Fall c=0.6 aber offenbar bei t=s/2 [Methode 1] + // oder ganz knapp darunter. + // Auch erweist sich Methode 1 im Experiment als effizienter. + // Daher implementieren wir Methode 1 : + { // Es ist 2 <= len1 <= len2. + // Spezialfall Quadrieren abfangen (häufig genug, daß sich das lohnt): + if (sourceptr1 == sourceptr2) + if (len1 == len2) + { mulu_karatsuba_square(sourceptr1,len1,destptr); return; } + var cl_boolean first_part = cl_true; // Flag, ob jetzt das erste Teilprodukt berechnet wird + if (len2 >= 2*len1) + { CL_SMALL_ALLOCA_STACK; + // Teilprodukte von jeweils len1 mal len1 Digits bilden: + var uintC k_lo = floor(len1,2); // Länge der Low-Teile: floor(len1/2) >0 + var uintC k_hi = len1 - k_lo; // Länge der High-Teile: ceiling(len1/2) >0 + // Es gilt k_lo <= k_hi <= len1, k_lo + k_hi = len1. + // Summe x1+x0 berechnen: + var uintD* sum1_MSDptr; + var uintC sum1_len = k_hi; // = max(k_lo,k_hi) + var uintD* sum1_LSDptr; + num_stack_small_alloc_1(sum1_len,sum1_MSDptr=,sum1_LSDptr=); + {var uintD carry = // Hauptteile von x1 und x0 addieren: + add_loop_lsp(sourceptr1 lspop k_lo,sourceptr1,sum1_LSDptr,k_lo); + if (!(k_lo==k_hi)) + // noch k_hi-k_lo = 1 Digits abzulegen + { mspref(sum1_MSDptr,0) = lspref(sourceptr1,len1-1); // = lspref(sourceptr1,2*k_lo) + if (!(carry==0)) { if (++(mspref(sum1_MSDptr,0)) == 0) carry=1; else carry=0; } + } + if (carry) { lsprefnext(sum1_MSDptr) = 1; sum1_len++; } + } + { // Platz für Summe y1+y0 belegen: + var uintC sum2_maxlen = k_hi+1; + var uintD* sum2_LSDptr; + num_stack_small_alloc(sum2_maxlen,,sum2_LSDptr=); + // Platz für Produkte x0*y0, x1*y1 belegen: + { var uintD* prod_MSDptr; + var uintD* prod_LSDptr; + var uintD* prodhi_LSDptr; + num_stack_small_alloc(2*(uintL)len1,prod_MSDptr=,prod_LSDptr=); + prodhi_LSDptr = prod_LSDptr lspop 2*k_lo; + // prod_MSDptr/2*len1/prod_LSDptr wird zuerst die beiden + // Produkte x1*y1 in prod_MSDptr/2*k_hi/prodhi_LSDptr + // und x0*y0 in prodhi_LSDptr/2*k_lo/prod_LSDptr, + // dann das Produkt (b^k*x1+x0)*(b^k*y1+y0) enthalten. + // Platz fürs Produkt (x1+x0)*(y1+y0) belegen: + {var uintD* prodmid_MSDptr; + var uintD* prodmid_LSDptr; + num_stack_small_alloc(sum1_len+sum2_maxlen,prodmid_MSDptr=,prodmid_LSDptr=); + // Schleife über die hinteren Einzelteile: + do { // Produkt x0*y0 berechnen: + cl_UDS_mul(sourceptr1,k_lo,sourceptr2,k_lo,prod_LSDptr); + // Produkt x1*y1 berechnen: + cl_UDS_mul(sourceptr1 lspop k_lo,k_hi,sourceptr2 lspop k_lo,k_hi,prodhi_LSDptr); + // Summe y1+y0 berechnen: + {var uintC sum2_len = k_hi; // = max(k_lo,k_hi) + var uintD* sum2_MSDptr = sum2_LSDptr lspop sum2_len; + {var uintD carry = // Hauptteile von y1 und y0 addieren: + add_loop_lsp(sourceptr2 lspop k_lo,sourceptr2,sum2_LSDptr,k_lo); + if (!(k_lo==k_hi)) + // noch k_hi-k_lo = 1 Digits abzulegen + { mspref(sum2_MSDptr,0) = lspref(sourceptr2,len1-1); // = lspref(sourceptr2,2*k_lo) + if (!(carry==0)) { if (++(mspref(sum2_MSDptr,0)) == 0) carry=1; else carry=0; } + } + if (carry) { lsprefnext(sum2_MSDptr) = 1; sum2_len++; } + } + // Produkt (x1+x0)*(y1+y0) berechnen: + cl_UDS_mul(sum1_LSDptr,sum1_len,sum2_LSDptr,sum2_len,prodmid_LSDptr); + // Das Produkt beansprucht 2*k_hi + (0 oder 1) <= sum1_len + sum2_len Digits. + {var uintC prodmid_len = sum1_len+sum2_len; + // Davon x1*y1 abziehen: + {var uintD carry = + subfrom_loop_lsp(prodhi_LSDptr,prodmid_LSDptr,2*k_hi); + // Falls Carry: Produkt beansprucht 2*k_hi+1 Digits. + // Carry um maximal 1 Digit weitertragen: + if (!(carry==0)) { lspref(prodmid_LSDptr,2*k_hi) -= 1; } + } + // Und x0*y0 abziehen: + {var uintD carry = + subfrom_loop_lsp(prod_LSDptr,prodmid_LSDptr,2*k_lo); + // Carry um maximal prodmid_len-2*k_lo Digits weitertragen: + if (!(carry==0)) + { dec_loop_lsp(prodmid_LSDptr lspop 2*k_lo,prodmid_len-2*k_lo); } + } + // prodmid_LSDptr[-prodmid_len..-1] enthält nun x0*y1+x1*y0. + // Dies wird zu prod = x1*y1*b^(2*k) + x0*y0 addiert: + {var uintD carry = + addto_loop_lsp(prodmid_LSDptr,prod_LSDptr lspop k_lo,prodmid_len); + // (Benutze dabei k_lo+prodmid_len <= k_lo+2*(k_hi+1) = 2*len1-k_lo+2 <= 2*len1 .) + if (!(carry==0)) + { inc_loop_lsp(prod_LSDptr lspop (k_lo+prodmid_len),2*len1-(k_lo+prodmid_len)); } + }}} + // Das Teilprodukt zum Gesamtprodukt addieren: + if (first_part) + { copy_loop_lsp(prod_LSDptr,destptr,2*len1); + destptr = destptr lspop len1; + first_part = cl_false; + } + else + { var uintD carry = + addto_loop_lsp(prod_LSDptr,destptr,len1); + destptr = destptr lspop len1; + copy_loop_lsp(prod_LSDptr lspop len1,destptr,len1); + if (!(carry==0)) { inc_loop_lsp(destptr,len1); } + } + sourceptr2 = sourceptr2 lspop len1; len2 -= len1; + } + while (len2 >= 2*len1); + }}} + } + // Nun ist len1 <= len2 < 2*len1. + // letztes Teilprodukt von len1 mal len2 Digits bilden: + {CL_SMALL_ALLOCA_STACK; + var uintD* prod_MSDptr; + var uintC prod_len = len1+len2; + var uintD* prod_LSDptr; + num_stack_small_alloc((uintL)prod_len,prod_MSDptr=,prod_LSDptr=); + { var uintC k_hi = floor(len2,2); // Länge der High-Teile: floor(len2/2) >0 + var uintC k_lo = len2 - k_hi; // Länge der Low-Teile: ceiling(len2/2) >0 + // Es gilt k_hi <= k_lo <= len1 <= len2, k_lo + k_hi = len2. + var uintC x1_len = len1-k_lo; // <= len2-k_lo = k_hi <= k_lo + // Summe x1+x0 berechnen: + var uintD* sum1_MSDptr; + var uintC sum1_len = k_lo; // = max(k_lo,k_hi) + var uintD* sum1_LSDptr; + num_stack_small_alloc_1(sum1_len,sum1_MSDptr=,sum1_LSDptr=); + {var uintD carry = // x1 und unteren Teil von x0 addieren: + add_loop_lsp(sourceptr1 lspop k_lo,sourceptr1,sum1_LSDptr,x1_len); + // und den oberen Teil von x0 dazu: + copy_loop_lsp(sourceptr1 lspop x1_len,sum1_LSDptr lspop x1_len,k_lo-x1_len); + if (!(carry==0)) + { carry = inc_loop_lsp(sum1_LSDptr lspop x1_len,k_lo-x1_len); + if (carry) { lsprefnext(sum1_MSDptr) = 1; sum1_len++; } + } + } + {// Summe y1+y0 berechnen: + var uintD* sum2_MSDptr; + var uintC sum2_len = k_lo; // = max(k_lo,k_hi) + var uintD* sum2_LSDptr; + num_stack_small_alloc_1(sum2_len,sum2_MSDptr=,sum2_LSDptr=); + {var uintD carry = // Hauptteile von y1 und y0 addieren: + add_loop_lsp(sourceptr2 lspop k_lo,sourceptr2,sum2_LSDptr,k_hi); + if (!(k_lo==k_hi)) + // noch k_lo-k_hi = 1 Digits abzulegen + { mspref(sum2_MSDptr,0) = lspref(sourceptr2,k_lo-1); // = lspref(sourceptr2,k_hi) + if (!(carry==0)) { if (++(mspref(sum2_MSDptr,0)) == 0) carry=1; else carry=0; } + } + if (carry) { lsprefnext(sum2_MSDptr) = 1; sum2_len++; } + } + // Platz für Produkte x0*y0, x1*y1: + { var uintC prodhi_len = x1_len+k_hi; + var uintD* prodhi_LSDptr = prod_LSDptr lspop 2*k_lo; + // prod_MSDptr/len1+len2/prod_LSDptr wird zuerst die beiden + // Produkte x1*y1 in prod_MSDptr/x1_len+k_hi/prodhi_LSDptr + // und x0*y0 in prodhi_LSDptr/2*k_lo/prod_LSDptr, + // dann das Produkt (b^k*x1+x0)*(b^k*y1+y0) enthalten. + // Platz fürs Produkt (x1+x0)*(y1+y0) belegen: + {var uintD* prodmid_MSDptr; + var uintC prodmid_len = sum1_len+sum2_len; + var uintD* prodmid_LSDptr; + num_stack_small_alloc(prodmid_len,prodmid_MSDptr=,prodmid_LSDptr=); + // Produkt (x1+x0)*(y1+y0) berechnen: + cl_UDS_mul(sum1_LSDptr,sum1_len,sum2_LSDptr,sum2_len,prodmid_LSDptr); + // Das Produkt beansprucht 2*k_lo + (0 oder 1) <= sum1_len + sum2_len = prodmid_len Digits. + // Produkt x0*y0 berechnen: + cl_UDS_mul(sourceptr1,k_lo,sourceptr2,k_lo,prod_LSDptr); + // Produkt x1*y1 berechnen: + if (!(x1_len==0)) + { cl_UDS_mul(sourceptr1 lspop k_lo,x1_len,sourceptr2 lspop k_lo,k_hi,prodhi_LSDptr); + // Und x1*y1 abziehen: + {var uintD carry = + subfrom_loop_lsp(prodhi_LSDptr,prodmid_LSDptr,prodhi_len); + // Carry um maximal prodmid_len-prodhi_len Digits weitertragen: + if (!(carry==0)) + { dec_loop_lsp(prodmid_LSDptr lspop prodhi_len,prodmid_len-prodhi_len); } + }} + else + // Produkt x1*y1=0, nichts abzuziehen + { clear_loop_lsp(prodhi_LSDptr,prodhi_len); } + // Und x0*y0 abziehen: + {var uintD carry = + subfrom_loop_lsp(prod_LSDptr,prodmid_LSDptr,2*k_lo); + // Falls Carry: Produkt beansprucht 2*k_lo+1 Digits. + // Carry um maximal 1 Digit weitertragen: + if (!(carry==0)) { lspref(prodmid_LSDptr,2*k_lo) -= 1; } + } + // prodmid_LSDptr[-prodmid_len..-1] enthält nun x0*y1+x1*y0. + // Dies ist < b^k_lo * b^k_hi + b^x1_len * b^k_lo + // = b^len2 + b^len1 <= 2 * b^len2, + // paßt also in len2+1 Digits. + // Im Fall x1_len=0 ist es sogar < b^k_lo * b^k_hi = b^len2, + // es paßt also in len2 Digits. + // prodmid_len, wenn möglich, um maximal 2 verkleinern: + // (benutzt prodmid_len >= 2*k_lo >= len2 >= 2) + if (mspref(prodmid_MSDptr,0)==0) + { prodmid_len--; + if (mspref(prodmid_MSDptr,1)==0) { prodmid_len--; } + } + // Nun ist k_lo+prodmid_len <= len1+len2 . + // (Denn es war prodmid_len = sum1_len+sum2_len <= 2*(k_lo+1) + // <= len2+3, und nach 2-maliger Verkleinerung jedenfalls + // prodmid_len <= len2+1. Im Falle k_lo < len1 also + // k_lo + prodmid_len <= (len1-1)+(len2+1) = len1+len2. + // Im Falle k_lo = len1 aber ist x1_len=0, sum1_len = k_lo, also + // war prodmid_len = sum1_len+sum2_len <= 2*k_lo+1 <= len2+2, + // nach 2-maliger Verkleinerung jedenfalls prodmid_len <= len2.) + // prodmid*b^k = (x0*y1+x1*y0)*b^k zu prod = x1*y1*b^(2*k) + x0*y0 addieren: + {var uintD carry = + addto_loop_lsp(prodmid_LSDptr,prod_LSDptr lspop k_lo,prodmid_len); + if (!(carry==0)) + { inc_loop_lsp(prod_LSDptr lspop (k_lo+prodmid_len),prod_len-(k_lo+prodmid_len)); } + }}}}} + // Das Teilprodukt zum Gesamtprodukt addieren: + if (first_part) + { copy_loop_lsp(prod_LSDptr,destptr,prod_len); } + else + { var uintD carry = + addto_loop_lsp(prod_LSDptr,destptr,len1); + destptr = destptr lspop len1; + copy_loop_lsp(prod_LSDptr lspop len1,destptr,len2); + if (!(carry==0)) { inc_loop_lsp(destptr,len2); } + } + }} diff --git a/src/base/digitseq/cl_DS_mul_kara_sqr.h b/src/base/digitseq/cl_DS_mul_kara_sqr.h new file mode 100644 index 0000000..1e834f5 --- /dev/null +++ b/src/base/digitseq/cl_DS_mul_kara_sqr.h @@ -0,0 +1,82 @@ + + // Eine vereinfachte Version von mulu_karatsuba für den Fall + // sourceptr1 == sourceptr2 && len1 == len2. + // Weniger Variablen, eine Additionsschleife weniger, eine Kopierschleife + // weniger, und bei rekursiven Aufrufen ist wieder + // sourceptr1 == sourceptr2 && len1 == len2. + static void mulu_karatsuba_square (const uintD* sourceptr, uintC len, + uintD* destptr) + { // Es ist 2 <= len. + CL_SMALL_ALLOCA_STACK; + var uintC prod_len = 2*len; + var uintD* prod_LSDptr = destptr; + var uintC k_hi = floor(len,2); // Länge der High-Teile: floor(len/2) >0 + var uintC k_lo = len - k_hi; // Länge der Low-Teile: ceiling(len/2) >0 + // Es gilt k_hi <= k_lo <= len, k_lo + k_hi = len. + // Summe x1+x0 berechnen: + var uintD* sum_MSDptr; + var uintC sum_len = k_lo; // = max(k_lo,k_hi) + var uintD* sum_LSDptr; + num_stack_small_alloc_1(sum_len,sum_MSDptr=,sum_LSDptr=); + {var uintD carry = // Hauptteile von x1 und x0 addieren: + add_loop_lsp(sourceptr lspop k_lo,sourceptr,sum_LSDptr,k_hi); + if (!(k_lo==k_hi)) + // noch k_lo-k_hi = 1 Digits abzulegen + { mspref(sum_MSDptr,0) = lspref(sourceptr,k_lo-1); // = lspref(sourceptr,k_hi) + if (!(carry==0)) { if (++(mspref(sum_MSDptr,0)) == 0) carry=1; else carry=0; } + } + if (carry) { lsprefnext(sum_MSDptr) = 1; sum_len++; } + } + // Platz für Produkte x0*x0, x1*x1: + { var uintC prodhi_len = 2*k_hi; + var uintD* prodhi_LSDptr = prod_LSDptr lspop 2*k_lo; + // prod_MSDptr/2*len/prod_LSDptr wird zuerst die beiden + // Produkte x1*x1 in prod_MSDptr/2*k_hi/prodhi_LSDptr + // und x0*x0 in prodhi_LSDptr/2*k_lo/prod_LSDptr, + // dann das Produkt (b^k*x1+x0)*(b^k*x1+x0) enthalten. + // Platz fürs Produkt (x1+x0)*(x1+x0) belegen: + {var uintD* prodmid_MSDptr; + var uintC prodmid_len = 2*sum_len; + var uintD* prodmid_LSDptr; + num_stack_small_alloc(prodmid_len,prodmid_MSDptr=,prodmid_LSDptr=); + // Produkt (x1+x0)*(x1+x0) berechnen: + cl_UDS_mul_square(sum_LSDptr,sum_len,prodmid_LSDptr); + // Das Produkt beansprucht 2*k_lo + (0 oder 1) <= 2*sum_len = prodmid_len Digits. + // Produkt x0*x0 berechnen: + cl_UDS_mul_square(sourceptr,k_lo,prod_LSDptr); + // Produkt x1*x1 berechnen: + cl_UDS_mul_square(sourceptr lspop k_lo,k_hi,prodhi_LSDptr); + // Und x1*x1 abziehen: + {var uintD carry = + subfrom_loop_lsp(prodhi_LSDptr,prodmid_LSDptr,prodhi_len); + // Carry um maximal prodmid_len-prodhi_len Digits weitertragen: + if (!(carry==0)) + { dec_loop_lsp(prodmid_LSDptr lspop prodhi_len,prodmid_len-prodhi_len); } + } + // Und x0*x0 abziehen: + {var uintD carry = + subfrom_loop_lsp(prod_LSDptr,prodmid_LSDptr,2*k_lo); + // Falls Carry: Produkt beansprucht 2*k_lo+1 Digits. + // Carry um maximal 1 Digit weitertragen: + if (!(carry==0)) { lspref(prodmid_LSDptr,2*k_lo) -= 1; } + } + // prodmid_LSDptr[-prodmid_len..-1] enthält nun 2*x0*x1. + // Dies ist < 2 * b^k_lo * b^k_hi = 2 * b^len, + // paßt also in len+1 Digits. + // prodmid_len, wenn möglich, um maximal 2 verkleinern: + // (benutzt prodmid_len >= 2*k_lo >= len >= 2) + if (mspref(prodmid_MSDptr,0)==0) + { prodmid_len--; + if (mspref(prodmid_MSDptr,1)==0) { prodmid_len--; } + } + // Nun ist k_lo+prodmid_len <= 2*len . + // (Denn es war prodmid_len = 2*sum_len <= 2*(k_lo+1) + // <= len+3, und nach 2-maliger Verkleinerung jedenfalls + // prodmid_len <= len+1. Wegen k_lo < len also + // k_lo + prodmid_len <= (len-1)+(len+1) = 2*len.) + // prodmid*b^k = 2*x0*x1*b^k zu prod = x1*x1*b^(2*k) + x0*x0 addieren: + {var uintD carry = + addto_loop_lsp(prodmid_LSDptr,prod_LSDptr lspop k_lo,prodmid_len); + if (!(carry==0)) + { inc_loop_lsp(prod_LSDptr lspop (k_lo+prodmid_len),prod_len-(k_lo+prodmid_len)); } + } }}} diff --git a/src/base/digitseq/cl_DS_mul_nuss.h b/src/base/digitseq/cl_DS_mul_nuss.h new file mode 100644 index 0000000..33b06a1 --- /dev/null +++ b/src/base/digitseq/cl_DS_mul_nuss.h @@ -0,0 +1,1511 @@ +// Fast integer multiplication using Nussbaumer's FFT based algorithm. +// [Donald Ervin Knuth: The Art of Computer Programming, Vol. II: +// Seminumerical Algorithms, second edition. +// Section 4.6.4, exercise 59, p. 503, 652-654.] +// [Henri Jean Nussbaumer, IEEE Trans. ASSP-28 (1980), 205-215.] +// Bruno Haible 4.-5.5.1996 + +// This algorithm has the benefit of working on entire words, not single bits, +// and involving no non-integer numbers. (The root of unity is chosen in +// an appropriate polynomial ring.) + +// If at the beginning all words x_i, y_i are >= 0 and < M, then +// the intermediate X_{i,j}, Y_{i,j} are < M * N in absolute value +// (where N = number of words), hence the |Z_{i,j}| < M^2 * N^2. +// We therefore reserve 2 32-bit words for every X_{i,j} and 4 32-bit words +// for every Z_{i,j}. + +#if !(intDsize==32) +#error "nussbaumer implemented only for intDsize==32" +#endif + +// Define this if you want the external loops instead of inline operations. +//#define NUSS_IN_EXTERNAL_LOOPS +#define NUSS_OUT_EXTERNAL_LOOPS + +// Define this if you want inline operations which access the stack directly. +// This looks like better code, but is in effect 3% slower. No idea why. +//#define NUSS_ASM_DIRECT + +// Define this for (cheap) consistency checks. +//#define DEBUG_NUSS + +// Define this for extensive consistency checks. +//#define DEBUG_NUSS_OPERATIONS + +#if (intDsize==32) + +//typedef struct { sint32 iw1; uint32 iw0; } nuss_inword; +//typedef struct { uint32 iw0; sint32 iw1; } nuss_inword; +typedef struct { uintD _iw[2]; } nuss_inword; +#if CL_DS_BIG_ENDIAN_P + #define iw1 _iw[0] + #define iw0 _iw[1] +#else + #define iw0 _iw[0] + #define iw1 _iw[1] +#endif + +//typedef struct { sint32 ow3; uint32 ow2; uint32 ow1; uint32 ow0; } nuss_outword; +//typedef struct { uint32 ow0; uint32 ow1; uint32 ow2; sint32 ow3; } nuss_outword; +typedef struct { uintD _ow[4]; } nuss_outword; +#if CL_DS_BIG_ENDIAN_P + #define ow3 _ow[0] + #define ow2 _ow[1] + #define ow1 _ow[2] + #define ow0 _ow[3] +#else + #define ow0 _ow[0] + #define ow1 _ow[1] + #define ow2 _ow[2] + #define ow3 _ow[3] +#endif + +// r := a + b +static inline void add (const nuss_inword& a, const nuss_inword& b, nuss_inword& r) +{ +#if defined(__GNUC__) && defined(__i386__) + var uintD dummy; + #ifdef NUSS_ASM_DIRECT + __asm__ __volatile__ ( + "movl %1,%0" "\n\t" + "addl %2,%0" "\n\t" + "movl %0,%3" + : "=&q" (dummy) + : "m" (a.iw0), "m" (b.iw0), "m" (r.iw0) + : "cc" + ); + __asm__ __volatile__ ( + "movl %1,%0" "\n\t" + "adcl %2,%0" "\n\t" + "movl %0,%3" + : "=&q" (dummy) + : "m" (a.iw1), "m" (b.iw1), "m" (r.iw1) + : "cc" + ); + #else + #if CL_DS_BIG_ENDIAN_P + __asm__ __volatile__ ( + "movl 4(%1),%0" "\n\t" + "addl 4(%2),%0" "\n\t" + "movl %0,4(%3)" "\n\t" + "movl (%1),%0" "\n\t" + "adcl (%2),%0" "\n\t" + "movl %0,(%3)" + : "=&q" (dummy) + : "r" (&a), "r" (&b), "r" (&r) + : "cc" + ); + #else + __asm__ __volatile__ ( + "movl (%1),%0" "\n\t" + "addl (%2),%0" "\n\t" + "movl %0,(%3)" "\n\t" + "movl 4(%1),%0" "\n\t" + "adcl 4(%2),%0" "\n\t" + "movl %0,4(%3)" + : "=&q" (dummy) + : "r" (&a), "r" (&b), "r" (&r) + : "cc" + ); + #endif + #endif +#elif defined(NUSS_IN_EXTERNAL_LOOPS) + add_loop_lsp(arrayLSDptr(a._iw,2),arrayLSDptr(b._iw,2),arrayLSDptr(r._iw,2),2); +#else + var uint32 tmp; + + tmp = a.iw0 + b.iw0; + if (tmp >= a.iw0) { + // no carry + r.iw0 = tmp; + r.iw1 = a.iw1 + b.iw1; + } else { + // carry + r.iw0 = tmp; + r.iw1 = a.iw1 + b.iw1 + 1; + } +#endif +} + +// r := a - b +static inline void sub (const nuss_inword& a, const nuss_inword& b, nuss_inword& r) +{ +#if defined(__GNUC__) && defined(__i386__) + var uintD dummy; + #ifdef NUSS_ASM_DIRECT + __asm__ __volatile__ ( + "movl %1,%0" "\n\t" + "subl %2,%0" "\n\t" + "movl %0,%3" + : "=&q" (dummy) + : "m" (a.iw0), "m" (b.iw0), "m" (r.iw0) + : "cc" + ); + __asm__ __volatile__ ( + "movl %1,%0" "\n\t" + "sbbl %2,%0" "\n\t" + "movl %0,%3" + : "=&q" (dummy) + : "m" (a.iw1), "m" (b.iw1), "m" (r.iw1) + : "cc" + ); + #else + #if CL_DS_BIG_ENDIAN_P + __asm__ __volatile__ ( + "movl 4(%1),%0" "\n\t" + "subl 4(%2),%0" "\n\t" + "movl %0,4(%3)" "\n\t" + "movl (%1),%0" "\n\t" + "sbbl (%2),%0" "\n\t" + "movl %0,(%3)" + : "=&q" (dummy) + : "r" (&a), "r" (&b), "r" (&r) + : "cc" + ); + #else + __asm__ __volatile__ ( + "movl (%1),%0" "\n\t" + "subl (%2),%0" "\n\t" + "movl %0,(%3)" "\n\t" + "movl 4(%1),%0" "\n\t" + "sbbl 4(%2),%0" "\n\t" + "movl %0,4(%3)" + : "=&q" (dummy) + : "r" (&a), "r" (&b), "r" (&r) + : "cc" + ); + #endif + #endif +#elif defined(NUSS_IN_EXTERNAL_LOOPS) + sub_loop_lsp(arrayLSDptr(a._iw,2),arrayLSDptr(b._iw,2),arrayLSDptr(r._iw,2),2); +#else + var uint32 tmp; + + tmp = a.iw0 - b.iw0; + if (tmp <= a.iw0) { + // no carry + r.iw0 = tmp; + r.iw1 = a.iw1 - b.iw1; + } else { + // carry + r.iw0 = tmp; + r.iw1 = a.iw1 - b.iw1 - 1; + } +#endif +} + +// r := a * b +static void mul (const nuss_inword& a, const nuss_inword& b, nuss_outword& r) +{ +#ifdef NUSS_IN_EXTERNAL_LOOPS + mulu_2loop(arrayLSDptr(a._iw,2),2, arrayLSDptr(b._iw,2),2, arrayLSDptr(r._ow,4)); + if ((sintD)mspref(arrayMSDptr(a._iw,2),0) < 0) + subfrom_loop_lsp(arrayLSDptr(b._iw,2),arrayLSDptr(r._ow,4) lspop 2,2); + if ((sintD)mspref(arrayMSDptr(b._iw,2),0) < 0) + subfrom_loop_lsp(arrayLSDptr(a._iw,2),arrayLSDptr(r._ow,4) lspop 2,2); +#else + if (a.iw1 == 0) { + // a small positive + if (b.iw1 == 0) { + // a, b small positive + mulu32(a.iw0, b.iw0, r.ow1 =, r.ow0 =); + r.ow3 = 0; r.ow2 = 0; + return; + } + else if (b.iw1 == -(uint32)1 && b.iw0 != 0) { + // b small negative + var uint32 hi, lo; + mulu32(a.iw0, -b.iw0, hi=, lo=); + r.ow0 = -lo; + if (lo) { + r.ow1 = ~hi; + } else if (hi) { + r.ow1 = -hi; + } else /* a.iw0 == 0 */ { + r.ow3 = 0; r.ow2 = 0; r.ow1 = 0; + return; + } + r.ow3 = -(uint32)1; r.ow2 = -(uint32)1; + return; + } + var uint32 hi1, lo1, hi0; + mulu32(a.iw0, b.iw0, hi0 =, r.ow0 =); + mulu32(a.iw0, b.iw1, hi1 =, lo1 =); + if ((lo1 += hi0) < hi0) + hi1++; + // hi1|lo1|r.ow0 = a.iw0 * b(unsigned). + r.ow1 = lo1; + if ((sint32)b.iw1 >= 0) { + r.ow2 = hi1; + r.ow3 = 0; + } else { + // b was negative -> subtract a * 2^64 + if (a.iw0) { + r.ow2 = hi1 - a.iw0; + r.ow3 = -(uint32)1; + } else /* a.iw0 == 0 */ { + r.ow3 = 0; r.ow2 = 0; + } + } + return; + } + else if (a.iw1 == -(uint32)1 && a.iw0 != 0) { + // a small negative + if (b.iw1 == 0) { + // b small positive + var uint32 hi, lo; + mulu32(-a.iw0, b.iw0, hi=, lo=); + r.ow0 = -lo; + if (lo) { + r.ow1 = ~hi; + } else if (hi) { + r.ow1 = -hi; + } else /* b.iw0 == 0 */ { + r.ow3 = 0; r.ow2 = 0; r.ow1 = 0; + return; + } + r.ow3 = -(uint32)1; r.ow2 = -(uint32)1; + return; + } + else if (b.iw1 == -(uint32)1 && b.iw0 != 0) { + // a, b small negative + mulu32(-a.iw0, -b.iw0, r.ow1 =, r.ow0 =); + r.ow3 = 0; r.ow2 = 0; + return; + } + var uint32 hi1, lo1, hi0, lo0; + mulu32(-a.iw0, b.iw0, hi0 =, lo0 =); + mulu32(-a.iw0, b.iw1, hi1 =, lo1 =); + if ((lo1 += hi0) < hi0) + hi1++; + // hi1|lo1|lo0 = -a * b(unsigned). + if (lo0) { + lo0 = -lo0; + lo1 = ~lo1; + hi1 = ~hi1; + } else if (lo1) { + lo1 = -lo1; + hi1 = ~hi1; + } else + hi1 = -hi1; + // hi1|lo1|lo0 = a * b(unsigned). + r.ow0 = lo0; + r.ow1 = lo1; + if ((sint32)b.iw1 >= 0) { + r.ow2 = hi1; + r.ow3 = -(uint32)1; + } else { + // b was negative -> subtract a * 2^64 + r.ow2 = hi1 - a.iw0; + r.ow3 = 0; + } + return; + } + else if (b.iw1 == 0) { + // b small positive + var uint32 hi1, lo1, hi0; + mulu32(b.iw0, a.iw0, hi0 =, r.ow0 =); + mulu32(b.iw0, a.iw1, hi1 =, lo1 =); + if ((lo1 += hi0) < hi0) + hi1++; + // hi1|lo1|r.ow0 = a(unsigned) * b.iw0. + r.ow1 = lo1; + if ((sint32)a.iw1 >= 0) { + r.ow2 = hi1; + r.ow3 = 0; + } else { + // a was negative -> subtract b * 2^64 + if (b.iw0) { + r.ow2 = hi1 - b.iw0; + r.ow3 = -(uint32)1; + } else /* b.iw0 == 0 */ { + r.ow3 = 0; r.ow2 = 0; + } + } + return; + } + else if (b.iw1 == -(uint32)1 && b.iw0 != 0) { + // b small negative + var uint32 hi1, lo1, hi0, lo0; + mulu32(-b.iw0, a.iw0, hi0 =, lo0 =); + mulu32(-b.iw0, a.iw1, hi1 =, lo1 =); + if ((lo1 += hi0) < hi0) + hi1++; + // hi1|lo1|lo0 = a(unsigned) * -b. + if (lo0) { + lo0 = -lo0; + lo1 = ~lo1; + hi1 = ~hi1; + } else if (lo1) { + lo1 = -lo1; + hi1 = ~hi1; + } else + hi1 = -hi1; + // hi1|lo1|lo0 = a(unsigned) * b. + r.ow0 = lo0; + r.ow1 = lo1; + if ((sint32)a.iw1 >= 0) { + r.ow2 = hi1; + r.ow3 = -(uint32)1; + } else { + // a was negative -> subtract b * 2^64 + r.ow2 = hi1 - b.iw0; + r.ow3 = 0; + } + return; + } + // This is the main and most frequent case (65% to 80%). + var uint32 w3, w2, w1, hi, lo; + mulu32(a.iw0, b.iw0, w1=, r.ow0=); + mulu32(a.iw1, b.iw1, w3=, w2=); + mulu32(a.iw0, b.iw1, hi=, lo=); + if ((w1 += lo) < lo) + hi++; + if ((w2 += hi) < hi) + w3++; + mulu32(a.iw1, b.iw0, hi=, lo=); + if ((w1 += lo) < lo) + hi++; + if ((w2 += hi) < hi) + w3++; + // w3|w2|w1|r.ow0 = a(unsigned) * b(unsigned). + r.ow1 = w1; + if ((sint32)a.iw1 < 0) { + // a was negative -> subtract b * 2^64 + if (w2 >= b.iw0) { + w2 -= b.iw0; + w3 -= b.iw1; + } else { + // carry + w2 -= b.iw0; + w3 = w3 - b.iw1 - 1; + } + } + if ((sint32)b.iw1 < 0) { + // b was negative -> subtract a * 2^64 + if (w2 >= a.iw0) { + w2 -= a.iw0; + w3 -= a.iw1; + } else { + // carry + w2 -= a.iw0; + w3 = w3 - a.iw1 - 1; + } + } + r.ow2 = w2; + r.ow3 = w3; + return; +#endif +} +#ifdef DEBUG_NUSS_OPERATIONS +static void mul_doublecheck (const nuss_inword& a, const nuss_inword& b, nuss_outword& r) +{ + nuss_outword or; + mulu_2loop(arrayLSDptr(a._iw,2),2, arrayLSDptr(b._iw,2),2, arrayLSDptr(or._ow,4)); + if ((sintD)mspref(arrayMSDptr(a._iw,2),0) < 0) + subfrom_loop_lsp(arrayLSDptr(b._iw,2),arrayLSDptr(or._ow,4) lspop 2,2); + if ((sintD)mspref(arrayMSDptr(b._iw,2),0) < 0) + subfrom_loop_lsp(arrayLSDptr(a._iw,2),arrayLSDptr(or._ow,4) lspop 2,2); + mul(a,b, r); + if (compare_loop_msp(arrayMSDptr(r._ow,4),arrayMSDptr(or._ow,4),4)) + cl_abort(); +} +#define mul mul_doublecheck +#endif + +// r := 0 +static inline void zero (nuss_outword& r) +{ + r.ow0 = 0; + r.ow1 = 0; + r.ow2 = 0; + r.ow3 = 0; +} + +// r := a + b +static inline void add (const nuss_outword& a, const nuss_outword& b, nuss_outword& r) +{ +#if defined(__GNUC__) && defined(__i386__) + var uintD dummy; + #ifdef NUSS_ASM_DIRECT + __asm__ __volatile__ ( + "movl %1,%0" "\n\t" + "addl %2,%0" "\n\t" + "movl %0,%3" + : "=&q" (dummy) + : "m" (a.ow0), "m" (b.ow0), "m" (r.ow0) + : "cc" + ); + __asm__ __volatile__ ( + "movl %1,%0" "\n\t" + "adcl %2,%0" "\n\t" + "movl %0,%3" + : "=&q" (dummy) + : "m" (a.ow1), "m" (b.ow1), "m" (r.ow1) + : "cc" + ); + __asm__ __volatile__ ( + "movl %1,%0" "\n\t" + "adcl %2,%0" "\n\t" + "movl %0,%3" + : "=&q" (dummy) + : "m" (a.ow2), "m" (b.ow2), "m" (r.ow2) + : "cc" + ); + __asm__ __volatile__ ( + "movl %1,%0" "\n\t" + "adcl %2,%0" "\n\t" + "movl %0,%3" + : "=&q" (dummy) + : "m" (a.ow3), "m" (b.ow3), "m" (r.ow3) + : "cc" + ); + #else + #if CL_DS_BIG_ENDIAN_P + __asm__ __volatile__ ( + "movl 12(%1),%0" "\n\t" + "addl 12(%2),%0" "\n\t" + "movl %0,12(%3)" "\n\t" + "movl 8(%1),%0" "\n\t" + "adcl 8(%2),%0" "\n\t" + "movl %0,8(%3)" "\n\t" + "movl 4(%1),%0" "\n\t" + "adcl 4(%2),%0" "\n\t" + "movl %0,4(%3)" "\n\t" + "movl (%1),%0" "\n\t" + "adcl (%2),%0" "\n\t" + "movl %0,(%3)" + : "=&q" (dummy) + : "r" (&a), "r" (&b), "r" (&r) + : "cc" + ); + #else + __asm__ __volatile__ ( + "movl (%1),%0" "\n\t" + "addl (%2),%0" "\n\t" + "movl %0,(%3)" "\n\t" + "movl 4(%1),%0" "\n\t" + "adcl 4(%2),%0" "\n\t" + "movl %0,4(%3)" "\n\t" + "movl 8(%1),%0" "\n\t" + "adcl 8(%2),%0" "\n\t" + "movl %0,8(%3)" "\n\t" + "movl 12(%1),%0" "\n\t" + "adcl 12(%2),%0" "\n\t" + "movl %0,12(%3)" + : "=&q" (dummy) + : "r" (&a), "r" (&b), "r" (&r) + : "cc" + ); + #endif + #endif +#elif defined(NUSS_OUT_EXTERNAL_LOOPS) + add_loop_lsp(arrayLSDptr(a._ow,4),arrayLSDptr(b._ow,4),arrayLSDptr(r._ow,4),4); +#else + var uint32 tmp; + + tmp = a.ow0 + b.ow0; + if (tmp >= a.ow0) { + // no carry + r.ow0 = tmp; + tmp = a.ow1 + b.ow1; + if (tmp >= a.ow1) goto no_carry_1; else goto carry_1; + } else { + // carry + r.ow0 = tmp; + tmp = a.ow1 + b.ow1 + 1; + if (tmp > a.ow1) goto no_carry_1; else goto carry_1; + } + if (1) { + no_carry_1: // no carry + r.ow1 = tmp; + tmp = a.ow2 + b.ow2; + if (tmp >= a.ow2) goto no_carry_2; else goto carry_2; + } else { + carry_1: // carry + r.ow1 = tmp; + tmp = a.ow2 + b.ow2 + 1; + if (tmp > a.ow2) goto no_carry_2; else goto carry_2; + } + if (1) { + no_carry_2: // no carry + r.ow2 = tmp; + tmp = a.ow3 + b.ow3; + } else { + carry_2: // carry + r.ow2 = tmp; + tmp = a.ow3 + b.ow3 + 1; + } + r.ow3 = tmp; +#endif +} + +// r := a - b +static inline void sub (const nuss_outword& a, const nuss_outword& b, nuss_outword& r) +{ +#if defined(__GNUC__) && defined(__i386__) + var uintD dummy; + #ifdef NUSS_ASM_DIRECT + __asm__ __volatile__ ( + "movl %1,%0" "\n\t" + "subl %2,%0" "\n\t" + "movl %0,%3" + : "=&q" (dummy) + : "m" (a.ow0), "m" (b.ow0), "m" (r.ow0) + : "cc" + ); + __asm__ __volatile__ ( + "movl %1,%0" "\n\t" + "sbbl %2,%0" "\n\t" + "movl %0,%3" + : "=&q" (dummy) + : "m" (a.ow1), "m" (b.ow1), "m" (r.ow1) + : "cc" + ); + __asm__ __volatile__ ( + "movl %1,%0" "\n\t" + "sbbl %2,%0" "\n\t" + "movl %0,%3" + : "=&q" (dummy) + : "m" (a.ow2), "m" (b.ow2), "m" (r.ow2) + : "cc" + ); + __asm__ __volatile__ ( + "movl %1,%0" "\n\t" + "sbbl %2,%0" "\n\t" + "movl %0,%3" + : "=&q" (dummy) + : "m" (a.ow3), "m" (b.ow3), "m" (r.ow3) + : "cc" + ); + #else + #if CL_DS_BIG_ENDIAN_P + __asm__ __volatile__ ( + "movl 12(%1),%0" "\n\t" + "subl 12(%2),%0" "\n\t" + "movl %0,12(%3)" "\n\t" + "movl 8(%1),%0" "\n\t" + "sbbl 8(%2),%0" "\n\t" + "movl %0,8(%3)" "\n\t" + "movl 4(%1),%0" "\n\t" + "sbbl 4(%2),%0" "\n\t" + "movl %0,4(%3)" "\n\t" + "movl (%1),%0" "\n\t" + "sbbl (%2),%0" "\n\t" + "movl %0,(%3)" + : "=&q" (dummy) + : "r" (&a), "r" (&b), "r" (&r) + : "cc" + ); + #else + __asm__ __volatile__ ( + "movl (%1),%0" "\n\t" + "subl (%2),%0" "\n\t" + "movl %0,(%3)" "\n\t" + "movl 4(%1),%0" "\n\t" + "sbbl 4(%2),%0" "\n\t" + "movl %0,4(%3)" "\n\t" + "movl 8(%1),%0" "\n\t" + "sbbl 8(%2),%0" "\n\t" + "movl %0,8(%3)" "\n\t" + "movl 12(%1),%0" "\n\t" + "sbbl 12(%2),%0" "\n\t" + "movl %0,12(%3)" + : "=&q" (dummy) + : "r" (&a), "r" (&b), "r" (&r) + : "cc" + ); + #endif + #endif +#elif defined(NUSS_OUT_EXTERNAL_LOOPS) + sub_loop_lsp(arrayLSDptr(a._ow,4),arrayLSDptr(b._ow,4),arrayLSDptr(r._ow,4),4); +#else + var uint32 tmp; + + tmp = a.ow0 - b.ow0; + if (tmp <= a.ow0) { + // no carry + r.ow0 = tmp; + tmp = a.ow1 - b.ow1; + if (tmp <= a.ow1) goto no_carry_1; else goto carry_1; + } else { + // carry + r.ow0 = tmp; + tmp = a.ow1 - b.ow1 - 1; + if (tmp < a.ow1) goto no_carry_1; else goto carry_1; + } + if (1) { + no_carry_1: // no carry + r.ow1 = tmp; + tmp = a.ow2 - b.ow2; + if (tmp <= a.ow2) goto no_carry_2; else goto carry_2; + } else { + carry_1: // carry + r.ow1 = tmp; + tmp = a.ow2 - b.ow2 - 1; + if (tmp < a.ow2) goto no_carry_2; else goto carry_2; + } + if (1) { + no_carry_2: // no carry + r.ow2 = tmp; + tmp = a.ow3 - b.ow3; + } else { + carry_2: // carry + r.ow2 = tmp; + tmp = a.ow3 - b.ow3 - 1; + } + r.ow3 = tmp; +#endif +} + +// b := a >> 1 +static inline void shift (const nuss_outword& a, nuss_outword& b) +{ +#if defined(__GNUC__) && defined(__i386__) && !defined(DEBUG_NUSS) + var uintD dummy; + #ifdef NUSS_ASM_DIRECT + __asm__ __volatile__ ( + "movl %1,%0" "\n\t" + "sarl $1,%0" "\n\t" + "movl %0,%2" + : "=&q" (dummy) + : "m" (a.ow3), "m" (b.ow3) + : "cc" + ); + __asm__ __volatile__ ( + "movl %1,%0" "\n\t" + "rcrl $1,%0" "\n\t" + "movl %0,%2" + : "=&q" (dummy) + : "m" (a.ow2), "m" (b.ow2) + : "cc" + ); + __asm__ __volatile__ ( + "movl %1,%0" "\n\t" + "rcrl $1,%0" "\n\t" + "movl %0,%2" + : "=&q" (dummy) + : "m" (a.ow1), "m" (b.ow1) + : "cc" + ); + __asm__ __volatile__ ( + "movl %1,%0" "\n\t" + "rcrl $1,%0" "\n\t" + "movl %0,%2" + : "=&q" (dummy) + : "m" (a.ow0), "m" (b.ow0) + : "cc" + ); + #else + #if CL_DS_BIG_ENDIAN_P + __asm__ __volatile__ ( + "movl (%1),%0" "\n\t" + "sarl $1,%0" "\n\t" + "movl %0,(%2)" "\n\t" + "movl 4(%1),%0" "\n\t" + "rcrl $1,%0" "\n\t" + "movl %0,4(%2)" "\n\t" + "movl 8(%1),%0" "\n\t" + "rcrl $1,%0" "\n\t" + "movl %0,8(%2)" "\n\t" + "movl 12(%1),%0" "\n\t" + "rcrl $1,%0" "\n\t" + "movl %0,12(%2)" + : "=&q" (dummy) + : "r" (&a), "r" (&b) + : "cc" + ); + #else + __asm__ __volatile__ ( + "movl 12(%1),%0" "\n\t" + "sarl $1,%0" "\n\t" + "movl %0,12(%2)" "\n\t" + "movl 8(%1),%0" "\n\t" + "rcrl $1,%0" "\n\t" + "movl %0,8(%2)" "\n\t" + "movl 4(%1),%0" "\n\t" + "rcrl $1,%0" "\n\t" + "movl %0,4(%2)" "\n\t" + "movl (%1),%0" "\n\t" + "rcrl $1,%0" "\n\t" + "movl %0,(%2)" + : "=&q" (dummy) + : "r" (&a), "r" (&b) + : "cc" + ); + #endif + #endif +#elif defined(NUSS_OUT_EXTERNAL_LOOPS) + #ifdef DEBUG_NUSS + if (shiftrightcopy_loop_msp(arrayMSDptr(a._ow,4),arrayMSDptr(b._ow,4),4,1,mspref(arrayMSDptr(a._ow,4),0)>>31)) + cl_abort(); + #else + shiftrightcopy_loop_msp(arrayMSDptr(a._ow,4),arrayMSDptr(b._ow,4),4,1,mspref(arrayMSDptr(a._ow,4),0)>>31); + #endif +#else + var uint32 tmp, carry; + + tmp = a.ow3; + b.ow3 = (sint32)tmp >> 1; + carry = tmp << 31; + tmp = a.ow2; + b.ow2 = (tmp >> 1) | carry; + carry = tmp << 31; + tmp = a.ow1; + b.ow1 = (tmp >> 1) | carry; + carry = tmp << 31; + tmp = a.ow0; + b.ow0 = (tmp >> 1) | carry; + #ifdef DEBUG_NUSS + carry = tmp << 31; + if (carry) + cl_abort(); + #endif +#endif +} + +#endif // (intDsize==32) + +#if (intDsize==64) + +//typedef struct { sint64 iw1; uint64 iw0; } nuss_inword; +//typedef struct { uint64 iw0; sint64 iw1; } nuss_inword; +typedef struct { uintD _iw[2]; } nuss_inword; +#if CL_DS_BIG_ENDIAN_P + #define iw1 _iw[0] + #define iw0 _iw[1] +#else + #define iw0 _iw[0] + #define iw1 _iw[1] +#endif + +//typedef struct { sint64 ow2; uint64 ow1; uint64 ow0; } nuss_outword; +//typedef struct { uint64 ow0; uint64 ow1; sint64 ow2; } nuss_outword; +typedef struct { uintD _ow[3]; } nuss_outword; +#if CL_DS_BIG_ENDIAN_P + #define ow2 _ow[0] + #define ow1 _ow[1] + #define ow0 _ow[2] +#else + #define ow0 _ow[0] + #define ow1 _ow[1] + #define ow2 _ow[2] +#endif + +// r := a + b +static inline void add (const nuss_inword& a, const nuss_inword& b, nuss_inword& r) +{ +#ifdef NUSS_IN_EXTERNAL_LOOPS + add_loop_lsp(arrayLSDptr(a._iw,2),arrayLSDptr(b._iw,2),arrayLSDptr(r._iw,2),2); +#else + var uint64 tmp; + + tmp = a.iw0 + b.iw0; + if (tmp >= a.iw0) { + // no carry + r.iw0 = tmp; + r.iw1 = a.iw1 + b.iw1; + } else { + // carry + r.iw0 = tmp; + r.iw1 = a.iw1 + b.iw1 + 1; + } +#endif +} + +// r := a - b +static inline void sub (const nuss_inword& a, const nuss_inword& b, nuss_inword& r) +{ +#ifdef NUSS_IN_EXTERNAL_LOOPS + sub_loop_lsp(arrayLSDptr(a._iw,2),arrayLSDptr(b._iw,2),arrayLSDptr(r._iw,2),2); +#else + var uint64 tmp; + + tmp = a.iw0 - b.iw0; + if (tmp <= a.iw0) { + // no carry + r.iw0 = tmp; + r.iw1 = a.iw1 - b.iw1; + } else { + // carry + r.iw0 = tmp; + r.iw1 = a.iw1 - b.iw1 - 1; + } +#endif +} + +// r := 0 +static inline void zero (nuss_outword& r) +{ + r.ow0 = 0; + r.ow1 = 0; + r.ow2 = 0; +} + +// r := a + b +static inline void add (const nuss_outword& a, const nuss_outword& b, nuss_outword& r) +{ +#ifdef NUSS_OUT_EXTERNAL_LOOPS + add_loop_lsp(arrayLSDptr(a._ow,3),arrayLSDptr(b._ow,3),arrayLSDptr(r._ow,3),3); +#else + var uint64 tmp; + + tmp = a.ow0 + b.ow0; + if (tmp >= a.ow0) { + // no carry + r.ow0 = tmp; + tmp = a.ow1 + b.ow1; + if (tmp >= a.ow1) goto no_carry_1; else goto carry_1; + } else { + // carry + r.ow0 = tmp; + tmp = a.ow1 + b.ow1 + 1; + if (tmp > a.ow1) goto no_carry_1; else goto carry_1; + } + if (1) { + no_carry_1: // no carry + r.ow1 = tmp; + tmp = a.ow2 + b.ow2; + } else { + carry_1: // carry + r.ow1 = tmp; + tmp = a.ow2 + b.ow2 + 1; + } + r.ow2 = tmp; +#endif +} + +// r := a - b +static inline void sub (const nuss_outword& a, const nuss_outword& b, nuss_outword& r) +{ +#ifdef NUSS_OUT_EXTERNAL_LOOPS + sub_loop_lsp(arrayLSDptr(a._ow,3),arrayLSDptr(b._ow,3),arrayLSDptr(r._ow,3),3); +#else + var uint64 tmp; + + tmp = a.ow0 - b.ow0; + if (tmp <= a.ow0) { + // no carry + r.ow0 = tmp; + tmp = a.ow1 - b.ow1; + if (tmp <= a.ow1) goto no_carry_1; else goto carry_1; + } else { + // carry + r.ow0 = tmp; + tmp = a.ow1 - b.ow1 - 1; + if (tmp < a.ow1) goto no_carry_1; else goto carry_1; + } + if (1) { + no_carry_1: // no carry + r.ow1 = tmp; + tmp = a.ow2 - b.ow2; + } else { + carry_1: // carry + r.ow1 = tmp; + tmp = a.ow2 - b.ow2 - 1; + } + r.ow2 = tmp; +#endif +} + +// b := a >> 1 +static inline void shift (const nuss_outword& a, nuss_outword& b) +{ +#ifdef NUSS_OUT_EXTERNAL_LOOPS + #ifdef DEBUG_NUSS + if (shiftrightcopy_loop_msp(arrayMSDptr(a._ow,3),arrayMSDptr(b._ow,3),3,1,mspref(arrayMSDptr(a._ow,3),0)>>63)) + cl_abort(); + #else + shiftrightcopy_loop_msp(arrayMSDptr(a._ow,3),arrayMSDptr(b._ow,3),3,1,mspref(arrayMSDptr(a._ow,3),0)>>63); + #endif +#else + var uint64 tmp, carry; + + tmp = a.ow2; + b.ow2 = (sint64)tmp >> 1; + carry = tmp << 63; + tmp = a.ow1; + b.ow1 = (tmp >> 1) | carry; + carry = tmp << 63; + tmp = a.ow0; + b.ow0 = (tmp >> 1) | carry; + #ifdef DEBUG_NUSS + carry = tmp << 63; + if (carry) + cl_abort(); + #endif +#endif +} + +#endif // (intDsize==64) + +// This is a recursive implementation. +// TODO: Write a non-recursive one. + +#ifndef _BIT_REVERSE +#define _BIT_REVERSE +// Reverse an n-bit number x. n>0. +static uintL bit_reverse (uintL n, uintL x) +{ + var uintL y = 0; + do { + y <<= 1; + y |= (x & 1); + x >>= 1; + } while (!(--n == 0)); + return y; +} +#endif + +// Threshold for recursion base in mulu_nuss_negacyclic(). +// Time of a multiplication with len1=len2=10000 on Linux i486: +// normal asm-optimized +// threshold1 = 1: 40.1 sec 25.5 sec +// threshold1 = 2: 28.6 sec 18.3 sec +// threshold1 = 3: 25.6 sec 16.6 sec +// threshold1 = 4: 25.7 sec 17.6 sec +// threshold1 = 5: 26.1 sec 18.0 sec +const uintL cl_nuss_threshold1 = 3; + +// Threshold for recursion base in mulu_nuss_cyclic(). +const uintL cl_nuss_threshold2 = 1; + +// Computes z[k] := sum(i+j==k mod N, x[i]*y[j]*(-1)^((i+j-k)/N)) +// for all k=0..N-1. +static void mulu_nuss_negacyclic (const uintL n, const uintL N, // N = 2^n + const nuss_inword * x, // N words + const nuss_inword * y, // N words + nuss_outword * z // N words result + ) +{ + #if 0 // always n > 0 + if (n == 0) { + // z[0] := x0 y0 + mul(x[0],y[0], z[0]); + return; + } + #endif + if (n <= cl_nuss_threshold1) { + if (n == 1) { + // z[0] := x0 (y0 + y1) - (x0 + x1) y1 + // z[1] := x0 (y0 + y1) + (x1 - x0) y0 + var nuss_inword x_sum; + var nuss_inword y_sum; + var nuss_outword first, second; + add(x[0],x[1], x_sum); + add(y[0],y[1], y_sum); + mul(x[0],y_sum, first); + mul(x_sum,y[1], second); sub(first,second, z[0]); + sub(x[1],x[0], x_sum); + mul(x_sum,y[0], second); add(first,second, z[1]); + return; + } + // 1 < n <= cl_nuss_threshold1. + #if 0 // straightforward, but slow + var uintL k; + for (k = 0; k < N; k++) { + var uintL i; + var nuss_outword accu; + mul(x[0],y[k], accu); + for (i = 1; i <= k; i++) { + var nuss_outword temp; + mul(x[i],y[k-i], temp); + add(accu,temp, accu); + } + for (i = k+1; i < N; i++) { + var nuss_outword temp; + mul(x[i],y[N-i+k], temp); + sub(accu,temp, accu); + } + z[k] = accu; + } + #else + var const uintL M = (uintL)1 << (n-1); // M = N/2 + var uintL i, j, k; + for (k = 0; k < N; k++) + zero(z[k]); + for (i = 0; i < M; i++) { + var uintL iM = i+M; + for (j = 0; j < M-i; j++) { + var uintL jM = j+M; + // z[i+j] += x[i] (y[j] + y[j+M]) - (x[i] + x[i+M]) y[j+M] + // z[i+j+M] += x[i] (y[j] + y[j+M]) + (x[i+M] - x[i]) y[j] + var nuss_inword x_sum; + var nuss_inword y_sum; + var nuss_outword first, second, temp; + add(x[i],x[iM], x_sum); + add(y[j],y[jM], y_sum); + mul(x[i],y_sum, first); + mul(x_sum,y[jM], second); sub(first,second, temp); add(z[i+j],temp, z[i+j]); + sub(x[iM],x[i], x_sum); + mul(x_sum,y[j], second); add(first,second, temp); add(z[i+j+M],temp, z[i+j+M]); + } + for (j = M-i; j < M; j++) { + var uintL jM = j+M; + // z[i+j] += x[i] (y[j] + y[j+M]) - (x[i] + x[i+M]) y[j+M] + // z[i+j-M] -= x[i] (y[j] + y[j+M]) + (x[i+M] - x[i]) y[j] + var nuss_inword x_sum; + var nuss_inword y_sum; + var nuss_outword first, second, temp; + add(x[i],x[iM], x_sum); + add(y[j],y[jM], y_sum); + mul(x[i],y_sum, first); + mul(x_sum,y[jM], second); sub(first,second, temp); add(z[i+j],temp, z[i+j]); + sub(x[iM],x[i], x_sum); + mul(x_sum,y[j], second); add(first,second, temp); sub(z[i+j-M],temp, z[i+j-M]); + } + } + #endif + return; + } + // Recursive FFT. + var const uintL m = n >> 1; // floor(n/2) + var const uintL r = n - m; // ceiling(n/2) + var const uintL M = (uintL)1 << m; // M = 2^m + var const uintL R = (uintL)1 << r; // R = 2^r + CL_ALLOCA_STACK; + var nuss_inword* const auX = cl_alloc_array(nuss_inword,2*N); + var nuss_inword* const auY = cl_alloc_array(nuss_inword,2*N); + var nuss_outword* const auZ = cl_alloc_array(nuss_outword,2*N); + #define X(i,j) auX[((i)<=0; l--) { + var const uintL smax = (uintL)1 << (m-l); + var const uintL tmax = (uintL)1 << l; + for (var uintL s = 0; s < smax; s++) { + var uintL exp = bit_reverse(m-l,s) << (l + r-m); + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = (s << (l+1)) + t; + var uintL i2 = i1 + tmax; + // Butterfly: replace (X(i1),X(i2)) by + // (X(i1) + w^exp*X(i2), X(i1) - w^exp*X(i2)). + for (j = 0; j < exp; j++) { + // note that w^R = -1 + sub(X(i1,j),X(i2,j-exp+R), tmp1[j]); + add(X(i1,j),X(i2,j-exp+R), tmp2[j]); + } + for (j = exp; j < R; j++) { + add(X(i1,j),X(i2,j-exp), tmp1[j]); + sub(X(i1,j),X(i2,j-exp), tmp2[j]); + } + for (j = 0; j < R; j++) { + X(i1,j) = tmp1[j]; + X(i2,j) = tmp2[j]; + } + } + } + } + } + // Do an FFT of length 2*M on Y. + if (!squaring) { + var sintL l; + // Level l = m: + for (i = 0; i < M; i++) + for (j = 0; j < R; j++) + Y(i+M,j) = Y(i,j); + // Level l = m-1..0: + for (l = m-1; l>=0; l--) { + var const uintL smax = (uintL)1 << (m-l); + var const uintL tmax = (uintL)1 << l; + for (var uintL s = 0; s < smax; s++) { + var uintL exp = bit_reverse(m-l,s) << (l + r-m); + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = (s << (l+1)) + t; + var uintL i2 = i1 + tmax; + // Butterfly: replace (Y(i1),Y(i2)) by + // (Y(i1) + w^exp*Y(i2), Y(i1) - w^exp*Y(i2)). + for (j = 0; j < exp; j++) { + // note that w^R = -1 + sub(Y(i1,j),Y(i2,j-exp+R), tmp1[j]); + add(Y(i1,j),Y(i2,j-exp+R), tmp2[j]); + } + for (j = exp; j < R; j++) { + add(Y(i1,j),Y(i2,j-exp), tmp1[j]); + sub(Y(i1,j),Y(i2,j-exp), tmp2[j]); + } + for (j = 0; j < R; j++) { + Y(i1,j) = tmp1[j]; + Y(i2,j) = tmp2[j]; + } + } + } + } + } + // Recursively compute the negacyclic product X(i)*Y(i) for all i. + if (!squaring) { + for (i = 0; i < 2*M; i++) + mulu_nuss_negacyclic(r,R, &X(i,0), &Y(i,0), &Z(i,0)); + } else { + for (i = 0; i < 2*M; i++) + mulu_nuss_negacyclic(r,R, &X(i,0), &X(i,0), &Z(i,0)); + } + // Undo an FFT of length 2*M on Z. + { + var uintL l; + // Level l = 0..m-1: + for (l = 0; l < m; l++) { + var const uintL smax = (uintL)1 << (m-l); + var const uintL tmax = (uintL)1 << l; + for (var uintL s = 0; s < smax; s++) { + var uintL exp = bit_reverse(m-l,s) << (l + r-m); + for (var uintL t = 0; t < tmax; t++) { + var uintL i1 = (s << (l+1)) + t; + var uintL i2 = i1 + tmax; + // Inverse Butterfly: replace (Z(i1),Z(i2)) by + // ((Z(i1)+Z(i2))/2, (Z(i1)-Z(i2))/(2*w^exp)). + for (j = 0; j < exp; j++) + // note that w^R = -1 + sub(Z(i2,j),Z(i1,j), tmpZ[j-exp+R]); + for (j = exp; j < R; j++) + sub(Z(i1,j),Z(i2,j), tmpZ[j-exp]); + for (j = 0; j < R; j++) { + var nuss_outword sum; + add(Z(i1,j),Z(i2,j), sum); + shift(sum, Z(i1,j)); + shift(tmpZ[j], Z(i2,j)); + } + } + } + } + // Level l=m: + for (i = 0; i < M; i++) { + var uintL i1 = i; + var uintL i2 = i1 + M; + // Inverse Butterfly: replace (Z(i1),Z(i2)) by + // ((Z(i1)+Z(i2))/2, (Z(i1)-Z(i2))/2). + for (j = 0; j < R; j++) { + var nuss_outword sum; + var nuss_outword diff; + add(Z(i1,j),Z(i2,j), sum); + sub(Z(i1,j),Z(i2,j), diff); + shift(sum, Z(i1,j)); + shift(diff, Z(i2,j)); + } + } + } + // Reduce to length M. + for (i = 0; i < M; i++) { + sub(Z(i,0),Z(i+M,R-1), z[i]); + for (j = 1; j < R; j++) + add(Z(i,j),Z(i+M,j-1), z[(j< 0 + if (n == 0) { + // z[0] := x0 y0 + mul(x[0],y[0], z[0]); + return; + } + #endif + if (n == 1) { + // z[0] := ((x0 + x1) (y0 + y1) + (x0 - x1) (y0 - y1)) / 2 + // z[1] := ((x0 + x1) (y0 + y1) - (x0 - x1) (y0 - y1)) / 2 + var nuss_inword x_sum; + var nuss_inword y_sum; + var nuss_inword x_diff; + var nuss_inword y_diff; + var nuss_outword first, second; + add(x[0],x[1], x_sum); + add(y[0],y[1], y_sum); + sub(x[0],x[1], x_diff); + sub(y[0],y[1], y_diff); + mul(x_sum,y_sum, first); + mul(x_diff,y_diff, second); + add(first,second, z[0]); shift(z[0], z[0]); + sub(first,second, z[1]); shift(z[1], z[1]); + return; + } + #if 0 // useless code because cl_nuss_threshold2 == 1 + if (n <= cl_nuss_threshold2) { + #if 0 // straightforward, but slow + var uintL k; + for (k = 0; k < N; k++) { + var uintL i; + var nuss_outword accu; + mul(x[0],y[k], accu); + for (i = 1; i <= k; i++) { + var nuss_outword temp; + mul(x[i],y[k-i], temp); + add(accu,temp, accu); + } + for (i = k+1; i < N; i++) { + var nuss_outword temp; + mul(x[i],y[N-i+k], temp); + add(accu,temp, accu); + } + z[k] = accu; + } + #else + var const uintL M = (uintL)1 << (n-1); // M = N/2 + var uintL i, j, k; + for (k = 0; k < N; k++) + zero(z[k]); + for (i = 0; i < M; i++) { + var uintL iM = i+M; + for (j = 0; j < M; j++) { + var uintL jM = j+M; + // z[i+j] += ((x[i] + x[i+M]) (y[j] + y[j+M]) + (x[i] - x[i+M]) (y[j] - y[j+M])) / 2 + // z[i+j+M] += ((x[i] + x[i+M]) (y[j] + y[j+M]) - (x[i] - x[i+M]) (y[j] - y[j+M])) / 2 + var nuss_inword x_sum; + var nuss_inword y_sum; + var nuss_inword x_diff; + var nuss_inword y_diff; + var nuss_outword first, second, temp; + add(x[i],x[iM], x_sum); + add(y[j],y[jM], y_sum); + sub(x[i],x[iM], x_diff); + sub(y[j],y[jM], y_diff); + mul(x_sum,y_sum, first); + mul(x_diff,y_diff, second); + add(first,second, temp); add(z[i+j],temp, z[i+j]); + var uintL ijM = (i+j+M) & (N-1); + sub(first,second, temp); add(z[ijM],temp, z[ijM]); + } + } + for (k = 0; k < N; k++) + shift(z[k], z[k]); + #endif + return; + } + #endif + var const uintL m = n-1; + var const uintL M = (uintL)1 << m; // M = 2^m = N/2 + var uintL i; + // Chinese remainder theorem: u^N-1 = (u^M-1)*(u^M+1) + for (i = 0; i < M; i++) { + // Butterfly: replace (x(i),x(i+M)) + // by (x(i)+x(i+M),x(i)-x(i+M)). + var nuss_inword tmp; + sub(x[i],x[i+M], tmp); + add(x[i],x[i+M], x[i]); + x[i+M] = tmp; + } + if (!(x == y)) // squaring? + for (i = 0; i < M; i++) { + // Butterfly: replace (y(i),y(i+M)) + // by (y(i)+y(i+M),y(i)-y(i+M)). + var nuss_inword tmp; + sub(y[i],y[i+M], tmp); + add(y[i],y[i+M], y[i]); + y[i+M] = tmp; + } + // Recurse. + mulu_nuss_cyclic(m,M, &x[0], &y[0], &z[0]); + mulu_nuss_negacyclic(m,M, &x[M], &y[M], &z[M]); + for (i = 0; i < M; i++) { + // Inverse Butterfly: replace (z(i),z(i+M)) + // by ((z(i)+z(i+M))/2,(z(i)-z(i+M))/2). + var nuss_outword sum; + var nuss_outword diff; + add(z[i],z[i+M], sum); + sub(z[i],z[i+M], diff); + shift(sum, z[i]); + shift(diff, z[i+M]); + } +} + +static void mulu_nussbaumer (const uintD* sourceptr1, uintC len1, + const uintD* sourceptr2, uintC len2, + uintD* destptr) +// Es ist 2 <= len1 <= len2. +{ + // Methode: + // source1 ist ein Stück der Länge N1, source2 ein oder mehrere Stücke + // der Länge N2, mit N1+N2 <= N, wobei N Zweierpotenz ist. + // sum(i=0..N-1, x_i b^i) * sum(i=0..N-1, y_i b^i) wird errechnet, + // indem man die beiden Polynome + // sum(i=0..N-1, x_i T^i), sum(i=0..N-1, y_i T^i) + // multipliziert, und zwar durch Fourier-Transformation (s.o.). + var uint32 n; + integerlength32(len1-1, n=); // 2^(n-1) < len1 <= 2^n + var uintL len = (uintL)1 << n; // kleinste Zweierpotenz >= len1 + // Wählt man N = len, so hat man ceiling(len2/(len-len1+1)) * FFT(len). + // Wählt man N = 2*len, so hat man ceiling(len2/(2*len-len1+1)) * FFT(2*len). + // Wir wählen das billigere von beiden: + // Bei ceiling(len2/(len-len1+1)) <= 2 * ceiling(len2/(2*len-len1+1)) + // nimmt man N = len, bei ....... > ........ dagegen N = 2*len. + // (Wahl von N = 4*len oder mehr bringt nur in Extremfällen etwas.) + if (len2 > 2 * (len-len1+1) * (len2 <= (2*len-len1+1) ? 1 : ceiling(len2,(2*len-len1+1)))) { + n = n+1; + len = len << 1; + } + var const uintL N = len; // N = 2^n + CL_ALLOCA_STACK; + var nuss_inword* const x = cl_alloc_array(nuss_inword,N); + var nuss_inword* const y = cl_alloc_array(nuss_inword,N); + var nuss_outword* const z = cl_alloc_array(nuss_outword,N); + var uintD* const tmpprod = cl_alloc_array(uintD,len1+1); + var uintP i; + var uintL destlen = len1+len2; + clear_loop_lsp(destptr,destlen); + do { + var uintL len2p; // length of a piece of source2 + len2p = N - len1 + 1; + if (len2p > len2) + len2p = len2; + // len2p = min(N-len1+1,len2). + if (len2p == 1) { + // cheap case + var uintD* tmpptr = arrayLSDptr(tmpprod,len1+1); + mulu_loop_lsp(lspref(sourceptr2,0),sourceptr1,tmpptr,len1); + if (addto_loop_lsp(tmpptr,destptr,len1+1)) + if (inc_loop_lsp(destptr lspop (len1+1),destlen-(len1+1))) + cl_abort(); + } else { + var uintL destlenp = len1 + len2p - 1; + // destlenp = min(N,destlen-1). + var bool squaring = ((sourceptr1 == sourceptr2) && (len1 == len2p)); + // Fill factor x. + { + for (i = 0; i < len1; i++) { + x[i].iw0 = lspref(sourceptr1,i); + x[i].iw1 = 0; + } + for (i = len1; i < N; i++) { + x[i].iw0 = 0; + x[i].iw1 = 0; + } + } + // Fill factor y. + if (!squaring) { + for (i = 0; i < len2p; i++) { + y[i].iw0 = lspref(sourceptr2,i); + y[i].iw1 = 0; + } + for (i = len2p; i < N; i++) { + y[i].iw0 = 0; + y[i].iw1 = 0; + } + } + // Multiply. + if (!squaring) + mulu_nuss_cyclic(n,N, &x[0], &y[0], &z[0]); + else + mulu_nuss_cyclic(n,N, &x[0], &x[0], &z[0]); + #ifdef DEBUG_NUSS + // Check result. + for (i = 0; i < N; i++) + if (!(z[i].ow3 == 0)) + cl_abort(); + #endif + // Add result to destptr[-destlen..-1]: + { + var uintD* ptr = destptr; + // ac2|ac1|ac0 are an accumulator. + var uint32 ac0 = 0; + var uint32 ac1 = 0; + var uint32 ac2 = 0; + var uint32 tmp; + for (i = 0; i < destlenp; i++) { + // Add z[i] to the accumulator. + tmp = z[i].ow0; + if ((ac0 += tmp) < tmp) { + if (++ac1 == 0) + ++ac2; + } + tmp = z[i].ow1; + if ((ac1 += tmp) < tmp) + ++ac2; + tmp = z[i].ow2; + ac2 += tmp; + // Add the accumulator's least significant word to destptr: + tmp = lspref(ptr,0); + if ((ac0 += tmp) < tmp) { + if (++ac1 == 0) + ++ac2; + } + lspref(ptr,0) = ac0; + lsshrink(ptr); + ac0 = ac1; + ac1 = ac2; + ac2 = 0; + } + // ac2 = 0. + if (ac1 > 0) { + if (!((i += 2) <= destlen)) + cl_abort(); + tmp = lspref(ptr,0); + if ((ac0 += tmp) < tmp) + ++ac1; + lspref(ptr,0) = ac0; + lsshrink(ptr); + tmp = lspref(ptr,0); + ac1 += tmp; + lspref(ptr,0) = ac1; + lsshrink(ptr); + if (ac1 < tmp) + if (inc_loop_lsp(ptr,destlen-i)) + cl_abort(); + } else if (ac0 > 0) { + if (!((i += 1) <= destlen)) + cl_abort(); + tmp = lspref(ptr,0); + ac0 += tmp; + lspref(ptr,0) = ac0; + lsshrink(ptr); + if (ac0 < tmp) + if (inc_loop_lsp(ptr,destlen-i)) + cl_abort(); + } + } + #ifdef DEBUG_NUSS + // If destlenp < N, check that the remaining z[i] are 0. + for (i = destlenp; i < N; i++) + if (z[i].ow2 > 0 || z[i].ow1 > 0 || z[i].ow0 > 0) + cl_abort(); + #endif + } + // Decrement len2. + destptr = destptr lspop len2p; + destlen -= len2p; + sourceptr2 = sourceptr2 lspop len2p; + len2 -= len2p; + } while (len2 > 0); +} + +#undef iw0 +#undef iw1 +#undef ow0 +#undef ow1 +#undef ow2 +#undef ow3 diff --git a/src/base/digitseq/cl_DS_random.cc b/src/base/digitseq/cl_DS_random.cc new file mode 100644 index 0000000..33c7260 --- /dev/null +++ b/src/base/digitseq/cl_DS_random.cc @@ -0,0 +1,33 @@ +// Digit sequence level random number generator. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_random_impl.h" + + +// Implementation. + +#include "cl_random.h" +#include "cl_DS.h" +#include "cl_low.h" + +void random_UDS (cl_random_state& randomstate, uintD* ptr, uintC len) +{ + var uintC count; + #if (intDsize==64) + dotimesC(count,len, + { mspref(ptr,0) = random64(randomstate); ptr = ptr mspop 1; }); + #else // (intDsize<=32) + dotimesC(count,floor(len,32/intDsize), + { var uint32 next = random32(randomstate); // weitere 32/intDsize Digits besorgen + set_32_Dptr(ptr,next); ptr = ptr mspop 32/intDsize; + }); + len = len % (32/intDsize); // Anzahl noch fehlender Digits + if (len>0) + { var uint32 next = random32(randomstate); // weitere 32/intDsize Digits besorgen + set_max32_Dptr(intDsize*len,ptr,next); + } + #endif +} diff --git a/src/base/digitseq/cl_DS_recip.cc b/src/base/digitseq/cl_DS_recip.cc new file mode 100644 index 0000000..c82e4d9 --- /dev/null +++ b/src/base/digitseq/cl_DS_recip.cc @@ -0,0 +1,160 @@ +// cl_UDS_recip(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_DS.h" + + +// Implementation. + +#include "cl_abort.h" + +// Compute the reciprocal value of a digit sequence. +// Input: UDS a_MSDptr/a_len/.. of length a_len, +// with 1/2*beta^a_len <= a < beta^a_len. +// Output: UDS b_MSDptr/b_len+2/.. of length b_len+1 (b_len>1), plus 1 more bit +// in the last limb, such that +// beta^b_len <= b <= 2*beta^b_len and +// | beta^(a_len+b_len)/a - b | < 1. +// If a_len > b_len, only the most significant b_len limbs + 3 bits of a +// are used. + extern void cl_UDS_recip (const uintD* a_MSDptr, uintC a_len, + uintD* b_MSDptr, uintC b_len); +// Method: +// Using Newton/Heron iteration. +// Write x = a/beta^a_len and y = b/beta^b_len. +// So we start out with 1/2 <= x < 1 and search an y with 1 <= y <= 2 +// and | 1/x - y | < beta^(-b_len). +// For n = 1,2,...,b_len we compute approximations y with 1 <= yn <= 2 +// and | 1/x - yn | < beta^(-n). The first n limbs of x, plus the +// next 3 bits (of the (n+1)st limb) enter the computation of yn. Apart +// from that, yn remains valid for any x which shares the same n+1 +// most significant limbs. +// Step n = 1: +// Write x = x1/beta + x2/beta^2 + xr with 0 <= xr < 1/(8*beta). +// Divide (beta^2-beta*x1-x2) by x1, gives beta^2-x1*beta-x2 = q*x1+r. +// If this division overflows, i.e. q >= beta, then x1 = beta/2, x2 = 0, +// and we just return y1 = 2. +// Else set qd := ceiling(max(q*x2/beta - r, 0) / (x1+1)) and return +// y1 = (beta+q-qd)/beta. +// Rationale: Obviously 0 <= qd <= q and 0 <= qd <= 2. We have +// beta^2 - beta*(beta+q-qd)*x +// <= beta^2 - (beta+q-qd)*(x1 + x2/beta) +// = beta^2 - beta*x1 - x2 - q*(x1 + x2/beta) + qd*(x1 + x2/beta) +// = q*x1 + r - q*(x1 + x2/beta) + qd*(x1 + x2/beta) +// = r - q*x2/beta + qd*(x1 + x2/beta) +// if qd=0: <= r <= x1-1 < x1 +// if qd>0: < r - q*x2/beta + qd*(x1+1) <= x1 +// hence always < x1 <= beta*x, hence +// 1 - x*y1 <= x/beta, hence 1/x - y1 <= 1/beta. +// And on the other hand +// beta^2 - beta*(beta+q-qd)*x +// = beta^2 - (beta+q-qd)*(x1 + x2/beta) - beta*(beta+q-qd)*xr +// where the third term is +// <= 2*beta^2*xr < beta/4 <= x1/2 <= beta*x/2. +// Hence +// beta^2 - beta*(beta+q-qd)*x > +// > beta^2 - (beta+q-qd)*(x1 + x2/beta) - beta*x/2 +// = r - q*x2/beta + qd*(x1 + x2/beta) - beta*x/2 +// >= - qd - beta*x/2 > - beta*x, hence +// 1 - x*y1 >= -x/beta, hence 1/x - y1 >= -1/beta. +// Step n -> m with n < m <= 2*n: +// Write x = xm + xr with 0 <= xr < 1/(8*beta^m). +// Set ym' = 2*yn - xm*yn*yn, +// ym = ym' rounded up to be a multiple of 1/(2*beta^m). +// Rationale: +// 1/x - ym <= 1/x - ym' = 1/x - 2*yn + (x-xr)*yn*yn +// <= 1/x - 2*yn + x*yn*yn = x * (1/x - yn)^2 < x*beta^(-2n) +// < beta^(-2n) <= beta^(-m), and +// 1/x - ym' = 1/x - 2*yn + (x-xr)*yn*yn +// > 1/x - 2*yn + x*yn*yn - 1/(2*beta^m) +// = x * (1/x - yn)^2 - 1/(2*beta^m) >= - 1/(2*beta^m), hence +// 1/x - ym > 1/x - ym' - 1/(2*beta^m) >= -1/beta^m. +// Since it is needed to compute ym as a multiple of 1/(2*beta^m), +// not only as a multiple of 1/beta^m, we compute with zn = 2*yn. +// The iteration now reads zm = round_up(2*zn - xm*zn*zn/2). +// Choice of n: +// So that the computation is minimal, e.g. in the case b_len=10: +// 1 -> 2 -> 3 -> 5 -> 10 and not 1 -> 2 -> 4 -> 8 -> 10. + void cl_UDS_recip (const uintD* a_MSDptr, uintC a_len, + uintD* b_MSDptr, uintC b_len) + { + var uintC y_len = b_len+1; + var uintC x_len = (a_len <= b_len ? a_len+1 : y_len); + var uintD* x_MSDptr; + var uintD* y_MSDptr; + var uintD* y2_MSDptr; + var uintD* y3_MSDptr; + CL_ALLOCA_STACK; + num_stack_alloc(x_len,x_MSDptr=,); + num_stack_alloc(y_len,y_MSDptr=,); + num_stack_alloc(2*y_len,y2_MSDptr=,); + num_stack_alloc(x_len+2*y_len,y3_MSDptr=,); + // Prepare x/2 at x_MSDptr by shifting a right by 1 bit. + if (a_len <= b_len) + { mspref(x_MSDptr,a_len) = + shiftrightcopy_loop_msp(a_MSDptr,x_MSDptr,a_len,1,0); + } + else + { mspref(x_MSDptr,b_len) = + shiftrightcopy_loop_msp(a_MSDptr,x_MSDptr,b_len,1,0) + | ((mspref(a_MSDptr,b_len) & -bit(intDsize-3)) >> 1); + } + // Step n = 1. + { var uintD x1 = mspref(a_MSDptr,0); + var uintD x2 = (a_len > 1 ? (mspref(a_MSDptr,1) & -bit(intDsize-3)) : 0); + if ((x1 == (uintD)bit(intDsize-1)) && (x2 == 0)) + { mspref(y_MSDptr,0) = 4; mspref(y_MSDptr,1) = 0; } + else + { var uintD q; + var uintD r; + var uintD chi; + var uintD clo; + #if HAVE_DD + divuD((uintDD)(-highlowDD(x1,x2)),x1, q=,r=); + var uintDD c = muluD(q,x2); + chi = highD(c); clo = lowD(c); + #else + divuD((uintD)(-x1 - (x2>0 ? 1 : 0)),(uintD)(-x2),x1, q=,r=); + muluD(q,x2,chi=,clo=); + #endif + if (clo > 0) + chi++; + // qd := ceiling(max(chi-r,0)/(x1+1)) + if (chi > r) + { chi -= r; + if (chi > x1) + { q--; } + q--; + } + mspref(y_MSDptr,0) = 2 + (q>>(intDsize-1)); + mspref(y_MSDptr,1) = q<<1; + } + } + // Other steps. + var int k; + integerlength32((uint32)b_len-1,k=); + // 2^(k-1) < b_len <= 2^k, so we need k steps. + var uintC n = 1; + for (; k>0; k--) + { // n = ceiling(b_len/2^k) limbs of y have already been computed. + var uintC m = ((b_len-1)>>(k-1))+1; // = ceiling(b_len/2^(k-1)) + // Compute zm := 2*zn - round_down(xm/2*zn*zn). + cl_UDS_mul_square(y_MSDptr mspop (n+1),n+1,y2_MSDptr mspop 2*(n+1)); + var uintC xm_len = (m < x_len ? m+1 : x_len); + cl_UDS_mul(x_MSDptr mspop xm_len,xm_len, + y2_MSDptr mspop 2*(n+1),2*n+1, + y3_MSDptr mspop (xm_len+2*n+1)); + // Round down by just taking the first m+1 limbs at y3_MSDptr. + shift1left_loop_lsp(y_MSDptr mspop (n+1),n+1); + clear_loop_msp(y_MSDptr mspop (n+1),m-n); + subfrom_loop_lsp(y3_MSDptr mspop (m+1),y_MSDptr mspop (m+1),m+1); + n = m; + } + // All n = b_len limbs of y have been computed. Divide by 2. + mspref(b_MSDptr,b_len+1) = + shiftrightcopy_loop_msp(y_MSDptr,b_MSDptr,b_len+1,1,0); + } +// Bit complexity (N := b_len): O(M(N)). diff --git a/src/base/digitseq/cl_DS_recipsqrt.cc b/src/base/digitseq/cl_DS_recipsqrt.cc new file mode 100644 index 0000000..ba5d4ca --- /dev/null +++ b/src/base/digitseq/cl_DS_recipsqrt.cc @@ -0,0 +1,164 @@ +// cl_UDS_recipsqrt(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_DS.h" + + +// Implementation. + +#include "cl_low.h" +#include "cl_abort.h" + +// Compute the reciprocal square root of a digit sequence. +// Input: UDS a_MSDptr/a_len/.. of length a_len, +// with 1/4 <= a < 1. +// [i.e. 1/4*beta^a_len <= a < beta^a_len] +// Output: UDS b_MSDptr/b_len+2/.. of length b_len+1 (b_len>1), plus 1 more bit +// in the last limb) such that +// 1 <= b <= 2 [i.e. beta^b_len <= b <= 2*beta^b_len] +// and | 1/sqrt(a) - b | < 1/2*beta^(-b_len). +// If a_len > b_len, only the most significant b_len+1 limbs of a are used. + extern void cl_UDS_recipsqrt (const uintD* a_MSDptr, uintC a_len, + uintD* b_MSDptr, uintC b_len); +// Method: +// Using Newton iteration for computation of x^-1/2. +// The Newton iteration for f(y) = x-1/y^2 reads: +// y --> y - (x-1/y^2)/(2/y^3) = y + y*(1-x*y^2)/2 =: g(y). +// We have T^3-3*T+2 = (T-1)^2*(T+2), hence +// 1/sqrt(x) - g(y) = 1/(2*sqrt(x)) * (sqrt(x)*y-1)^2 * (sqrt(x)*y+2). +// Hence g(y) <= 1/sqrt(x). +// If we choose 0 < y_0 <= 1/sqrt(x), then set y_(n+1) := g(y_n), we will +// always have 0 < y_n <= 1/sqrt(x). +// Since +// 1/sqrt(x) - g(y) = sqrt(x)*(sqrt(x)*y+2)/2 * (1/sqrt(x) - y)^2, +// which is >= 0 and < 3/2 * (1/sqrt(x) - y)^2, we have a quadratically +// convergent iteration. +// For n = 1,2,...,b_len we compute approximations y with 1 <= yn <= 2 +// and | 1/sqrt(x) - yn | < 1/2*beta^(-n). +// Step n=1: +// Compute the isqrt of the leading two digits of x, yields one digit. +// Compute its reciprocal, then do one iteration as below (n=0 -> m=1). +// Step n -> m with n < m <= 2*n: +// Write x = xm + xr with 0 <= xr < beta^-(m+1). +// Set ym' = yn + (yn*(1-xm*yn*yn))/2, round down to a multiple ym +// of beta^-(m+1). +// (Actually, compute yn*yn, round up to a multiple of beta^-(m+1), [1] +// multiply with xm, round up to a multiple of beta^-(m+1), [2] +// subtract from 1, no rounding needed, [2] +// multiply with yn, round down to a multiple of beta^-(m+1), [5] +// divide by 2, round down to a multiple of beta^-(m+1), [3] +// add to yn, no rounding needed. [Max rounding error: ^]) +// The exact value ym' (no rounding) would satisfy +// 0 <= 1/sqrt(xm) - ym' < 3/2 * (1/sqrt(xm) - yn)^2 +// < 3/8 * beta^(-2*n) by hypothesis, +// <= 3/8 * beta^-m. +// The rounding errors all go into the same direction, so +// 0 <= ym' - ym < 3 * beta^-(m+1) < 1/4 * beta^-m. +// Combine both inequalities: +// 0 <= 1/sqrt(xm) - ym < 1/2 * beta^-m. +// Neglecting xr can introduce a small error in the opposite direction: +// 0 <= 1/sqrt(xm) - 1/sqrt(x) = (sqrt(x) - sqrt(xm))/(sqrt(x)*sqrt(xm)) +// = xr / (sqrt(x)*sqrt(xm)*(sqrt(x)+sqrt(xm))) +// <= 4*xr < 4*beta^-(m+1) < 1/2*beta^-m. +// Combine both inequalities: +// | 1/sqrt(x) - ym | < 1/2 * beta^-m. +// (Actually, choosing the opposite rounding direction wouldn't hurt either.) +// Choice of n: +// So that the computation is minimal, e.g. in the case b_len=10: +// 1 -> 2 -> 3 -> 5 -> 10 and not 1 -> 2 -> 4 -> 8 -> 10. + void cl_UDS_recipsqrt (const uintD* a_MSDptr, uintC a_len, + uintD* b_MSDptr, uintC b_len) + { + var uintC y_len = b_len+2; + var uintC x_len = (a_len <= b_len ? a_len : b_len+1); + var const uintD* const x_MSDptr = a_MSDptr; + var uintD* y_MSDptr; + var uintD* y2_MSDptr; + var uintD* y3_MSDptr; + var uintD* y4_MSDptr; + CL_ALLOCA_STACK; + num_stack_alloc(y_len,y_MSDptr=,); + num_stack_alloc(2*y_len,y2_MSDptr=,); + num_stack_alloc(2*y_len,y3_MSDptr=,); + num_stack_alloc(2*y_len,y4_MSDptr=,); + // Step n = 1. + { var uintD x1 = mspref(x_MSDptr,0); + var uintD x2 = (a_len > 1 ? mspref(x_MSDptr,1) : 0); + var uintD y0; + var uintD y1; + var bool sqrtp; + isqrtD(x1,x2, y1=,sqrtp=); + // 2^31 <= y1 < 2^32. + y0 = 1; + if (!sqrtp) // want to compute 1/sqrt(x) rounded down + if (++y1 == 0) + goto step1_done; // 1/1.0000 = 1.0000 + // Set y0|y1 := 2^(2*intDsize)/y1 + // = 2^intDsize + (2^(2*intDsize)-2^intDsize*y1)/y1. + if ((uintD)(-y1) >= y1) { + y0 = 2; y1 = 0; + } else { + #if HAVE_DD + divuD(highlowDD_0((uintD)(-y1)),y1, y1=,); + #else + divuD((uintD)(-y1),0,y1, y1=,); + #endif + } + step1_done: + mspref(y_MSDptr,0) = y0; + mspref(y_MSDptr,1) = y1; + } + // Other steps. + var int k; + integerlength32((uint32)b_len-1,k=); + // 2^(k-1) < b_len <= 2^k, so we need k steps, plus one + // one more step at the beginning (because step 1 was not complete). + var uintC n = 0; + for (; k>=0; k--) + { var uintC m = ((b_len-1)>>k)+1; // = ceiling(b_len/2^k) + // Compute ym := yn + (yn*(1-xm*yn*yn))/2, rounded. + // Storage: at y_MSDptr: (1 + n+1) limbs, yn. + // at y2_MSDptr: (2 + 2*n+2) limbs, yn^2. + // at y3_MSDptr: (1 + m+1) limbs, xm*yn*yn, 1-xm*yn*yn. + // at y4_MSDptr: (2-n + m+n+2) limbs, yn*(1-xm*yn*yn). + clear_loop_msp(y_MSDptr mspop (n+2),m-n); + cl_UDS_mul_square(y_MSDptr mspop (n+2),n+2, + y2_MSDptr mspop 2*(n+2)); + var uintC xm_len = (m < x_len ? m+1 : x_len); + var uintC y2_len = m+2; // = (m+1 <= 2*n+2 ? m+2 : 2*n+3); + cl_UDS_mul(x_MSDptr mspop xm_len,xm_len, + y2_MSDptr mspop (y2_len+1),y2_len, + y3_MSDptr mspop (xm_len+y2_len)); + if (mspref(y3_MSDptr,0)==0) + // xm*yn*yn < 1 + { neg_loop_lsp(y3_MSDptr mspop (m+2),m+2); + mspref(y3_MSDptr,0) += 1; + if (test_loop_msp(y3_MSDptr,n)) cl_abort(); // check 0 <= y3 < beta^-(n-1) + cl_UDS_mul(y_MSDptr mspop (n+2),n+2, + y3_MSDptr mspop (m+2),m+2-n, + y4_MSDptr mspop (m+4)); + shift1right_loop_msp(y4_MSDptr,m+3-n,0); + if (addto_loop_lsp(y4_MSDptr mspop (m+3-n),y_MSDptr mspop (m+2),m+3-n)) + if ((n<1) || inc_loop_lsp(y_MSDptr mspop (n-1),n-1)) cl_abort(); + } + else + // xm*yn*yn >= 1 (this can happen since xm >= xn) + { mspref(y3_MSDptr,0) -= 1; + if (test_loop_msp(y3_MSDptr,n)) cl_abort(); // check 0 >= y3 > -beta^-(n-1) + cl_UDS_mul(y_MSDptr mspop (n+2),n+2, + y3_MSDptr mspop (m+2),m+2-n, + y4_MSDptr mspop (m+4)); + shift1right_loop_msp(y4_MSDptr,m+3-n,0); + if (subfrom_loop_lsp(y4_MSDptr mspop (m+3-n),y_MSDptr mspop (m+2),m+3-n)) + if ((n<1) || dec_loop_lsp(y_MSDptr mspop (n-1),n-1)) cl_abort(); + } + n = m; + // n = ceiling(b_len/2^k) limbs of y have now been computed. + } + copy_loop_msp(y_MSDptr,b_MSDptr,b_len+2); +} +// Bit complexity (N := b_len): O(M(N)). + diff --git a/src/base/digitseq/cl_DS_sqrt.cc b/src/base/digitseq/cl_DS_sqrt.cc new file mode 100644 index 0000000..b265907 --- /dev/null +++ b/src/base/digitseq/cl_DS_sqrt.cc @@ -0,0 +1,356 @@ +// cl_UDS_sqrt(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_DS.h" + + +// Implementation. + +#include "cl_low.h" +#include "cl_abort.h" + +// We observe the following timings: +// Time for square root of a_len = 2*N by b_len = N digits, +// on a i486 33 MHz running Linux: +// N standard Newton +// 10 0.00022 0.00132 +// 25 0.00082 0.0047 +// 50 0.0026 0.0130 +// 100 0.0095 0.038 +// 250 0.057 0.154 +// 500 0.22 0.46 +// 1000 0.90 1.39 +// 2500 6.0 4.6 +// 5000 24.1 10.7 +// 10000 98 23.2 +// -----> Newton faster for 1570 <= N <= 1790 and for N >= 2100. +// When in doubt, prefer to choose the standard algorithm. + static inline cl_boolean cl_recipsqrt_suitable (uintL n) + { return (cl_boolean)(n >= 2100); } + +// Workaround gcc-2.7.0 bug on i386. +#if defined(__GNUC__) + #if (__GNUC__ == 2) + #if (__GNUC_MINOR__ == 7) + #define workaround_gcc_bug() *&b_stern = *&b_stern; + #endif + #endif +#endif +#ifndef workaround_gcc_bug + #define workaround_gcc_bug() +#endif + +// Bildet zu einer Unsigned Digit sequence a die Wurzel +// (genauer: Gaußklammer aus Wurzel aus a). +// squarep = cl_UDS_sqrt(a_MSDptr,a_len,a_LSDptr, &b); +// > a_MSDptr/a_len/a_LSDptr: eine UDS +// < NUDS b: Gaußklammer der Wurzel aus a +// < squarep: cl_true falls a = b^2, cl_false falls b^2 < a < (b+1)^2. +// Methode: +// erst A normalisieren. A=0 --> B=0, fertig. +// Wähle n so, daß beta^(2n-2) <= A < beta^(2n). +// Wähle s (0<=s<16) so, daß beta^(2n)/4 <= A*2^(2s) < beta^(2n). +// Setze A:=A*2^(2s) und kopiere dabei A. Suche B=floor(sqrt(A)). +// Mache Platz für B=[0,b[n-1],...,b[0]], (mit einem Nulldigit Platz davor, +// da dort nicht B, sondern 2*B abgespeichert werden wird). +// Auf den Plätzen [a[2n-1],...,a[2n-2j]] wird die Differenz +// [a[2n-1],...,a[2n-2j]] - [b[n-1],...,b[n-j]] ^ 2 abgespeichert. +// Bestimme b[n-1] = floor(sqrt(a[2n-1]*beta+a[2n-2])) mit Heron/Newton: +// {x:=beta als vorheriger Anfangswert, dann:} +// x := floor((beta+a[2n-1])/2) +// wiederhole: d:=floor((a[2n-1]*beta+a[2n-2])/x). +// Falls d=beta/4 ist b[n-1]>=beta/2.} +// Erniedrige [a[2n-1],a[2n-2]] um b[n-1]^2. +// Für j=1,...,n: +// {Hier [b[n-1],...,b[n-j]] = floor(sqrt(altes [a[2n-1],...,a[2n-2j]])), +// in [a[2n-1],...,a[2n-2j]] steht jetzt der Rest +// [a[2n-1],...,a[2n-2j]] - [b[n-1],...,b[n-j]]^2, er ist >=0 und +// und <= 2 * [b[n-1],...,b[n-j]], belegt daher höchstens j Digits und 1 Bit. +// Daher sind nur [a[2n-j],...,a[2n-2j]] von Belang.} +// Für j= 0). +// Im einzelnen: +// b* := min(beta-1,floor([a[2n-j],a[2n-j-1],a[2n-j-2]]/(2*b[n-1]))), +// [a[2n-j],...,a[2n-2j-1]] wie angegeben erniedigen. +// Solange die Differenz <0 ist, setze b* := b* - 1 und +// erhöhe [a[2n-j],...,a[2n-2j-1]] um 2 * [b[n-1],...,b[n-j]]. +// Erniedrige [a[2n-j],...,a[2n-2j-2]] um b* ^ 2. +// Tritt dabei ein negativer Carry auf, +// so setze b* := b* - 1, +// setze b[n-j-1] := b* (im Speicher um 1 Bit nach links verschoben), +// erhöhe [a[2n-j],...,a[2n-2j-2]] um 2*[b[n-1],...,b[n-j-1]]+1. +// Sonst setze b[n-j-1] := b* (im Speicher um 1 Bit nach links verschoben). +// Nächstes j. +// Für j=n: +// Falls [a[n],...,a[0]] = [0,...,0], ist die Wurzel exakt, sonst nicht. +// Ergebnis ist [b[n-1],...,b[0]] * 2^(-s), schiebe also im Speicher +// [b[n],...,b[0]] um s+1 Bits nach rechts. +// Das Ergebnis ist eine NUDS der Länge n. +cl_boolean cl_UDS_sqrt (const uintD* a_MSDptr, uintC a_len, const uintD* a_LSDptr, DS* b_) +{ + // A normalisieren: + while ((a_len>0) && (mspref(a_MSDptr,0)==0)) { msshrink(a_MSDptr); a_len--; } + if (a_len==0) // A=0 -> B := NUDS 0 + { b_->LSDptr = b_->MSDptr; b_->len = 0; return cl_true; } + CL_ALLOCA_STACK; + // n und s bestimmen: + var uintC n = ceiling(a_len,2); // a_len = 2n oder 2n-1, n>0. + var uintL s; + { var uintD msd = mspref(a_MSDptr,0); // a[2n] bzw. a[2n-1] + #if 0 + s = 0; + while /* ((msd & (bit(intDsize-1)|bit(intDsize-2))) ==0) */ + (((sintD)msd >= 0) && ((sintD)(msd<<1) >= 0)) + { msd = msd<<2; s++; } + #else + integerlengthD(msd, s = intDsize - ); s = s>>1; + #endif + } + // Noch ist s nur modulo intDsize/2 bestimmt. + // A um 2s Bits nach links verschoben kopieren: + var uintD* new_a_MSDptr; + { var uintD* new_a_LSDptr; + num_stack_alloc(2*(uintL)n,new_a_MSDptr=,new_a_LSDptr=); // 2n Digits Platz belegen + {var uintL shiftcount = 2*s; + if (!((a_len & bit(0)) ==0)) // a_len ungerade? + { s += intDsize/2; lsprefnext(new_a_LSDptr) = 0; } // ja -> ein Nulldigit einschieben + if (shiftcount==0) + { copy_loop_lsp(a_LSDptr,new_a_LSDptr,a_len); } + else + { shiftleftcopy_loop_lsp(a_LSDptr,new_a_LSDptr,a_len,shiftcount); } + }} + #define a_MSDptr new_a_MSDptr + // Nun ist A = a_MSDptr/2n/.. + if (cl_recipsqrt_suitable(n)) + { // C := 1/sqrt(A) und dann D := A*C näherungsweise errechnen. + // D evtl. korrigieren, liefert B. + var uintD* c_MSDptr; + var uintD* c_LSDptr; + var uintD* d_MSDptr; + var uintD* d_LSDptr; + var uintD* d2_MSDptr; + num_stack_alloc(n+2, c_MSDptr=,c_LSDptr=); + num_stack_alloc(2*n+3, d_MSDptr=,d_LSDptr=); + num_stack_alloc(2*n, d2_MSDptr=,); + // 1/4 <= a < 1. + cl_UDS_recipsqrt(a_MSDptr,2*n,c_MSDptr,n); + // 1 <= c <= 2, | 1/sqrt(a) - c | < 1/2*beta^-n. + cl_UDS_mul(a_MSDptr mspop (n+1),n+1,c_LSDptr,n+2,d_LSDptr); + // 1/4 <= d < 2, | sqrt(a) - d | < beta^-n. + if (mspref(d_MSDptr,0) > 0) + { dec_loop_lsp(d_MSDptr mspop (n+1),n+1); + if (mspref(d_MSDptr,0) > 0) cl_abort(); + } + // D is our guess for B. Square to see how much we have to correct. + cl_UDS_mul_square(d_MSDptr mspop (1+n),n,d2_MSDptr mspop 2*n); + // Store D. + b_->LSDptr = copy_loop_msp(d_MSDptr mspop 1,b_->MSDptr,n); + b_->len = n; + // Store 2*D in place of D. + if (shift1left_loop_lsp(d_MSDptr mspop (1+n),n)) + mspref(d_MSDptr,0) = 1; + // Compare D^2 against A. + if (subfrom_loop_lsp(d2_MSDptr mspop 2*n,a_MSDptr mspop 2*n,2*n)) + // guessed too high, decrement D + { dec_loop_lsp(b_->LSDptr,n); + dec_loop_lsp(d_MSDptr mspop (1+n),1+n); // store 2*D+1 + if (!addto_loop_lsp(d_MSDptr mspop (1+n),a_MSDptr mspop 2*n,1+n)) + cl_abort(); + if (!inc_loop_lsp(a_MSDptr mspop (n-1),n-1)) + cl_abort(); + } + else if (test_loop_msp(a_MSDptr,n-1)) + // guessed way too low + cl_abort(); + else if (compare_loop_msp(a_MSDptr mspop (n-1),d_MSDptr,1+n) > 0) + // guessed too low, increment D + { inc_loop_lsp(b_->LSDptr,n); + mspref(d_MSDptr,n) |= bit(0); // store 2*D-1 + subfrom_loop_lsp(d_MSDptr mspop (1+n),a_MSDptr mspop 2*n,1+n); + inc_loop_lsp(d_MSDptr mspop (1+n),1+n); // store 2*D + if (compare_loop_msp(a_MSDptr mspop (n-1),d_MSDptr,1+n) > 0) + cl_abort(); + } + else + // guessed ok + {} + // Schiebe b um s Bits nach rechts: + if (s > 0) + shiftright_loop_msp(b_->MSDptr,n,s); + // Teste, ob alle a[n],...,a[0]=0 sind: + if (test_loop_msp(a_MSDptr mspop (n-1),n+1)) + return cl_false; + else + return cl_true; // ja -> Wurzel exakt + } + // Platz für B belegen: + { var uintD* b_MSDptr = b_->MSDptr mspop -1; // ab hier n+1 Digits Platz + var uintD b_msd; + // B = [0,b[n-1],...,b[0]] = b_MSDptr/n+1/.. + // Bestimmung von b[n-1]: + { var uintD a_msd = mspref(a_MSDptr,0); // a[2n-1] + var uintD a_2msd = mspref(a_MSDptr,1); // a[2n-2] + #if HAVE_DD + var uintDD a_msdd = highlowDD(a_msd,a_2msd); // a[2n-1]*beta+a[2n-2] + #endif + // Anfangswert: x := floor((beta + a[2n-1])/2) + var uintD x = floor(a_msd,2) | bit(intDsize-1); + loop // Heron-Iterationsschleife + { var uintD d; + // Dividiere d := floor((a[2n-1]*beta+a[2n-2])/x) : + if (a_msd>=x) break; // Ãœberlauf -> d>=beta -> fertig + #if HAVE_DD + divuD(a_msdd,x, d=,); + #else + divuD(a_msd,a_2msd,x, d=,); + #endif + if (d >= x) break; // d>=x -> fertig + // Nächste Iteration: x := floor((x+d)/2) + // (Da die Folge der x bekanntlich monoton fallend ist + // und bei b[n-1] >= beta/2 endet, muß x >= beta/2 werden, + // d.h. x+d>=beta.) + #if HAVE_DD + x = (uintD)(floor((uintDD)x + (uintDD)d, 2)); + #else + x = floor((uintD)(x+d),2) | bit(intDsize-1); + #endif + } + // x = b[n-1] fertig berechnet. + b_msd = x; + // Quadrieren und von [a[2n-1],a[2n-2]] abziehen: + #if HAVE_DD + a_msdd -= muluD(x,x); + mspref(a_MSDptr,0) = highD(a_msdd); mspref(a_MSDptr,1) = lowD(a_msdd); + #else + {var uintD x2hi; + var uintD x2lo; + muluD(x,x, x2hi=,x2lo=); + mspref(a_MSDptr,0) = a_msd - x2hi; + if (a_2msd < x2lo) { mspref(a_MSDptr,0) -= 1; } + mspref(a_MSDptr,1) = a_2msd - x2lo; + } + #endif + mspref(b_MSDptr,0) = 1; mspref(b_MSDptr,1) = x<<1; // b[n-1] ablegen + } + {var uintC j = 0; + var uintD* a_mptr = a_MSDptr mspop 0; + var uintD* a_lptr = a_MSDptr mspop 2; + var uintD* b_ptr = b_MSDptr mspop 2; + // Wurzel-Hauptschleife + until (++j == n) // j=1,...,n + { // b_MSDptr = Pointer auf b[n], b_ptr = Pointer hinter b[n-j]. + // a_mptr = Pointer auf a[2n-j], a_lptr = Pointer hinter a[2n-2j]. + // Bestimme b* : + var uintD b_stern; + { var uintD a_1d = mspref(a_mptr,0); // a[2n-j], =0 oder =1 + var uintD a_2d = mspref(a_mptr,1); // a[2n-j-1] + var uintD a_3d = mspref(a_mptr,2); // a[2n-j-2] + // a[2n-j]*beta^2+a[2n-j-1]*beta+a[2n-j-2] durch 2 dividieren, + // dann durch b_msd = b[n-1] dividieren: + #if HAVE_DD + var uintDD a_123dd = highlowDD(a_2d,a_3d); + a_123dd = a_123dd>>1; if (!(a_1d==0)) { a_123dd |= bit(2*intDsize-1); } + if (highD(a_123dd) >= b_msd) + { b_stern = bitm(intDsize)-1; } // bei Ãœberlauf: beta-1 + else + { divuD(a_123dd,b_msd, b_stern=,); } + #else + a_3d = a_3d>>1; if (!((a_2d & bit(0)) ==0)) { a_3d |= bit(intDsize-1); } + a_2d = a_2d>>1; if (!(a_1d==0)) { a_2d |= bit(intDsize-1); } + if (a_2d >= b_msd) + { b_stern = bitm(intDsize)-1; } // bei Ãœberlauf: beta-1 + else + { divuD(a_2d,a_3d,b_msd, b_stern=,); } + #endif + } + // b_stern = b* in der ersten Schätzung. + a_lptr = a_lptr mspop 1; // Pointer hinter a[2n-2j-1] + // Subtraktion [a[2n-j],...,a[2n-2j-1]] -= b* * [b[n],b[n-1],...,b[n-j]] : + { var uintD carry = mulusub_loop_lsp(b_stern,b_ptr,a_lptr,j+1); + if (mspref(a_mptr,0) >= carry) + { mspref(a_mptr,0) -= carry; } + else + { mspref(a_mptr,0) -= carry; // a[2n-j] wird <0 + // negativer Ãœbertrag -> b* nach unten korrigieren: + loop + { b_stern = b_stern-1; // b* := b* - 1 + // erhöhe [a[2n-j],...,a[2n-2j-1]] um [b[n],...,b[n-j]]: + if (!(( addto_loop_lsp(b_ptr,a_lptr,j+1) ==0))) + if ((mspref(a_mptr,0) += 1) ==0) // Ãœbertrag zu a[2n-j] + break; // macht a[2n-j] wieder >=0 -> Subtraktionsergebnis >=0 + } } } + // b_stern = b* in der zweiten Schätzung. + a_mptr = a_mptr mspop 1; // Pointer auf a[2n-j-1] + a_lptr = a_lptr mspop 1; // Pointer hinter a[2n-2j-2] + // Ziehe b* ^ 2 von [a[2n-j],...,a[2n-2j-2]] ab: + #if HAVE_DD + { var uintDD b_stern_2 = muluD(b_stern,b_stern); + var uintDD a_12dd = highlowDD(lspref(a_lptr,1),lspref(a_lptr,0)); // a[2n-2j-1]*beta+a[2n-2j-2] + var uintDD a_12dd_new = a_12dd - b_stern_2; + lspref(a_lptr,1) = highD(a_12dd_new); lspref(a_lptr,0) = lowD(a_12dd_new); + if (a_12dd >= b_stern_2) goto b_stern_ok; + } + #else + { var uintD b_stern_2_hi; + var uintD b_stern_2_lo; + muluD(b_stern,b_stern, b_stern_2_hi=,b_stern_2_lo=); + {var uintD a_1d = lspref(a_lptr,1); // a[2n-2j-1] + var uintD a_2d = lspref(a_lptr,0); // a[2n-2j-2] + var uintD a_1d_new = a_1d - b_stern_2_hi; + var uintD a_2d_new = a_2d - b_stern_2_lo; + if (a_2d < b_stern_2_lo) { a_1d_new -= 1; } + lspref(a_lptr,1) = a_1d_new; lspref(a_lptr,0) = a_2d_new; + if ((a_1d > b_stern_2_hi) + || ((a_1d == b_stern_2_hi) && (a_2d >= b_stern_2_lo)) + ) + goto b_stern_ok; + }} + #endif + if (TRUE) + { // muß noch [a[2n-j],...,a[2n-2j]] um 1 erniedrigen: + if ( dec_loop_lsp(a_lptr lspop 2,j+1) ==0) goto b_stern_ok; + // Subtraktion von b*^2 lieferte negativen Carry + b_stern = b_stern-1; // b* := b* - 1 + workaround_gcc_bug(); + // erhöhe [a[2n-j-1],...,a[2n-2j-2]] um [b[n],...,b[n-j],0] + 2 * b* + 1 + if ((sintD)b_stern < 0) { mspref(b_ptr,-1) |= bit(0); } // höchstes Bit von b* in b[n-j] ablegen + mspref(b_ptr,0) = (uintD)(b_stern<<1)+1; // niedrige Bits von b* und eine 1 als b[n-j-1] ablegen + addto_loop_lsp(b_ptr mspop 1,a_lptr,j+2); + // (a[2n-j] wird nicht mehr gebraucht.) + mspref(b_ptr,0) -= 1; // niedrige Bits von b* in b[n-j-1] ablegen + b_ptr = b_ptr mspop 1; + } + else + b_stern_ok: + { // b* als b[n-j-1] ablegen: + if ((sintD)b_stern < 0) { mspref(b_ptr,-1) |= bit(0); } // höchstes Bit von b* in b[n-j] ablegen + mspref(b_ptr,0) = (uintD)(b_stern<<1); // niedrige Bits von b* als b[n-j-1] ablegen + b_ptr = b_ptr mspop 1; + } + } + // b_MSDptr = Pointer auf b[n], b_ptr = Pointer hinter b[0]. + // a_mptr = Pointer auf a[n]. + // Schiebe [b[n],...,b[0]] um s+1 Bits nach rechts: + if (s == intDsize-1) + { lsshrink(b_ptr); } + else + { shiftright_loop_msp(b_MSDptr,n+1,s+1); msshrink(b_MSDptr); } + // b = b_MSDptr/n/b_ptr ist fertig, eine NUDS. + b_->MSDptr = b_MSDptr; b_->len = n; b_->LSDptr = b_ptr; + // Teste, ob alle a[n],...,a[0]=0 sind: + if (test_loop_msp(a_mptr,n+1)) + { return cl_false; } + else + { return cl_true; } // ja -> Wurzel exakt + }} +} +// Bit complexity (N := a_len): O(M(N)). + diff --git a/src/base/digitseq/cl_DS_trandom.cc b/src/base/digitseq/cl_DS_trandom.cc new file mode 100644 index 0000000..706db37 --- /dev/null +++ b/src/base/digitseq/cl_DS_trandom.cc @@ -0,0 +1,45 @@ +// Digit sequence level random number generator. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_random_impl.h" + + +// Implementation. + +#include "cl_random.h" +#include "cl_DS.h" +#include "cl_low.h" + +void testrandom_UDS (cl_random_state& randomstate, uintD* MSDptr, uintC len) +{ + // Idea from Torbjörn Granlund, see his "random2.c" file in gmp 2.0. + var uintD* ptr = MSDptr mspop len; + DS_clear_loop(MSDptr,len,ptr); + var uintL bit_pos = 0; + var uint32 ran = 0; + var uintC ran_bits = 0; + while (bit_pos < intDsize*(uintL)len) + { if (ran_bits < log2_intDsize+1) + { ran = random32(randomstate); ran_bits = 32; } + var uintL n_bits = (ran >> 1) % intDsize + 1; // number of bits + if (ran & 1) + { // put in a bit string of n_bits bits at position bit_pos. + if (bit_pos + n_bits > intDsize*(uintL)len) + { n_bits = intDsize*(uintL)len - bit_pos; } + if (bit_pos / intDsize == (bit_pos + n_bits - 1) / intDsize) + { // need to modify one digit + lspref(ptr,bit_pos/intDsize) |= (((uintD)1 << n_bits) - 1) << (bit_pos%intDsize); + } + else + { // need to modify two adjacent digits + lspref(ptr,bit_pos/intDsize) |= ((uintD)(-1) << (bit_pos%intDsize)); + lspref(ptr,bit_pos/intDsize+1) |= (((uintD)1 << ((bit_pos+n_bits)%intDsize)) - 1); + } + } + bit_pos = bit_pos + n_bits; + ran = ran >> (log2_intDsize+1); ran_bits -= log2_intDsize+1; + } +} diff --git a/src/base/digitseq/cl_asm.h b/src/base/digitseq/cl_asm.h new file mode 100644 index 0000000..8079878 --- /dev/null +++ b/src/base/digitseq/cl_asm.h @@ -0,0 +1,33 @@ +// Includes the CPU specific cl_asm_*.h file. + +#include "cl_config.h" +#include "cl_DS_endian.h" + +#ifdef __m68k__ + #include "cl_asm_m68k.h" +#endif + +#if defined(__sparc__) && !defined(__sparc64__) + #include "cl_asm_sparc.h" +#endif + +#if defined(__sparc64__) + #include "cl_asm_sparc64.h" +#endif + +#ifdef __i386__ + #include "cl_asm_i386.h" +#endif + +#ifdef __mips__ + #include "cl_asm_mips.h" +#endif + +#ifdef __hppa__ + #include "cl_asm_hppa.h" +#endif + +#ifdef __arm__ + #include "cl_asm_arm.h" +#endif + diff --git a/src/base/digitseq/cl_asm_.cc b/src/base/digitseq/cl_asm_.cc new file mode 100644 index 0000000..6a5e631 --- /dev/null +++ b/src/base/digitseq/cl_asm_.cc @@ -0,0 +1,33 @@ +// Includes the CPU specific cl_asm_*.cc file. + +#include "cl_config.h" +#include "cl_DS_endian.h" + +#ifdef __m68k__ + #include "cl_asm_m68k_.cc" +#endif + +#if defined(__sparc__) && !defined(__sparc64__) + #include "cl_asm_sparc_.cc" +#endif + +#if defined(__sparc64__) + #include "cl_asm_sparc64_.cc" +#endif + +#ifdef __i386__ + #include "cl_asm_i386_.cc" +#endif + +#ifdef __mips__ + #include "cl_asm_mips_.cc" +#endif + +#ifdef __hppa__ + #include "cl_asm_hppa_.cc" +#endif + +#ifdef __arm__ + #include "cl_asm_arm_.cc" +#endif + diff --git a/src/base/digitseq/cl_asm_arm.h b/src/base/digitseq/cl_asm_arm.h new file mode 100644 index 0000000..fc7583a --- /dev/null +++ b/src/base/digitseq/cl_asm_arm.h @@ -0,0 +1,10 @@ +// List the contents of cl_asm_arm.cc. + +#define COPY_LOOPS +#define FILL_LOOPS +#define CLEAR_LOOPS +#define LOG_LOOPS +#define TEST_LOOPS +#define ADDSUB_LOOPS +#define SHIFT_LOOPS +#define MUL_LOOPS diff --git a/src/base/digitseq/cl_asm_arm_.cc b/src/base/digitseq/cl_asm_arm_.cc new file mode 100644 index 0000000..bec5c01 --- /dev/null +++ b/src/base/digitseq/cl_asm_arm_.cc @@ -0,0 +1,3600 @@ +// ariarm.d (c) Copyright 1994, 1997 P.J.Burwood +// little-endian modifications (c) Copyright 1996 B. Haible +// external routines for arilev1.d +// Processor: ARM in APCS mode +// Assembler-Syntax: ObjAsm under RISC OS, GAS otherwise +// Assumptions: intCsize=32, intDsize=32. +// Parameter passing conventions: APCS means that registers a1-a4 and ip +// do not have to be preserved across function calls. +// Note: A sequence of up to 4 conditional instructions is used in preference +// to a branch. + + +#ifdef __riscos + +// ObjAsm syntax + +a1 RN 0 +a2 RN 1 +a3 RN 2 +a4 RN 3 +v1 RN 4 +v2 RN 5 +v3 RN 6 +v4 RN 7 +v5 RN 8 +v6 RN 9 +sl RN 10 +fp RN 11 +ip RN 12 +sp RN 13 +lr RN 14 +pc RN 15 + +f0 FN 0 +f1 FN 1 +f2 FN 2 +f3 FN 3 +f4 FN 4 +f5 FN 5 +f6 FN 6 +f7 FN 7 + +#define C(x) _##x +#define EXPORT(x) EXPORT x +#define DECLARE_FUNCTION(x) +#define GLABEL(x) _##x +#define LABEL(x) _##x + + AREA |C$$code|,CODE,READONLY + +#else + +// GAS syntax + +a1 .req r0 +a2 .req r1 +a3 .req r2 +a4 .req r3 +v1 .req r4 +v2 .req r5 +v3 .req r6 +v4 .req r7 +v5 .req r8 +v6 .req r9 +rfp .req r9 +sl .req r10 +fp .req r11 +ip .req r12 +sp .req r13 +lr .req r14 +pc .req r15 + +#define C(x) _##x +#define EXPORT(x) .global _##x +#if defined(__NetBSD__) +#define DECLARE_FUNCTION(x) .type _##x,%function +#else +#define DECLARE_FUNCTION(x) +#endif +#define GLABEL(x) _##x##: +#define LABEL(x) x##: +#define RRX rrx +#define END + +#endif + + +#if defined(__arm7m__) || defined(__arm8__) || defined(__arm9__) || defined(__strongarm__) + // ARM7M and later have 32x32 -> 64 multiplies which execute in 2-4 clocks. + #define HAVE_umull +#endif + + +#if defined(__GNUC__) && 0 + // With GNU C, we would like to pass the second return value in a2, don't + // need a global variable. Unfortunately, the current Acorn gcc crashes if + // we declare an appropriate local register variable with __asm__. + // It would be possible to declare the functions as returning a 64-bit + // result, but given the quality of gcc code dealing with 64-bit entities + // and the subtleties of 64-bit returns values (passed in register or in + // memory?) we now let it be. +#else + // Use three global variables. + #define MULU32_HIGH + #define DIVU_16_REST + #define DIVU_32_REST +#endif + +#ifdef __riscos + +#ifdef MULU32_HIGH +ptr_mulu32_high + IMPORT mulu32_high + DCD mulu32_high +#endif +#ifdef DIVU_16_REST +ptr_divu_16_rest + IMPORT divu_16_rest + DCD divu_16_rest +#endif +#ifdef DIVU_32_REST +ptr_divu_32_rest + IMPORT divu_32_rest + DCD divu_32_rest +#endif + +#else + +#ifdef MULU32_HIGH +ptr_mulu32_high: + .word _mulu32_high + .align 0 +#endif +#ifdef DIVU_16_REST +ptr_divu_16_rest: + .word _divu_16_rest + .align 0 +#endif +#ifdef DIVU_32_REST +ptr_divu_32_rest: + .word _divu_32_rest + .align 0 +#endif + +#endif + + +// extern uint32 mulu32_ (uint32 x, uint32 y); +// entry +// a1 = x +// a2 = y +// exit +// a1 = low32(x*y) +// a2 = high32(x*y) +// mulu32_high = high32(x*y) +// a3,a4,ip destroyed + EXPORT(mulu32_) + DECLARE_FUNCTION(mulu32_) +GLABEL(mulu32_) +#ifdef HAVE_umull + MOV a3,a2 + UMULL a1,a2,a3,a1 +#else + MOV ip,a1,LSR #16 // temp := top half of x + MOV a3,a2,LSR #16 // hi := top half of y + BIC a1,a1,ip,LSL #16 // x := bottom half of x + BIC a2,a2,a3,LSL #16 // y := bottom half of y + MUL a4,a1,a2 // low section of result + MUL a2,ip,a2 // ) middle sections + MUL a1,a3,a1 // ) of result + MUL a3,ip,a3 // high section of result + ADDS a2,a2,a1 // add middle sections + // (can't use mla as we need carry) + ADDCS a3,a3,#&10000 // carry from above add + ADDS a1,a4,a2,LSL #16 // x is now bottom 32 bits of result + ADC a2,a3,a2,LSR #16 // hi is top 32 bits +#endif +#ifdef MULU32_HIGH + LDR a3,[pc,#ptr_mulu32_high-.-8] + STR a2,[a3,#0] +#endif + MOVS pc,lr + +// extern uint16 divu_3216_1616_ (uint32 x, uint16 y); +// entry +// a1 = x +// a2 = y +// exit +// a1 = q = floor(x/y) +// a2 = r = x-q*y +// divu_16_rest = r = x-q*y +// a3 destroyed + EXPORT(divu_3216_1616_) + DECLARE_FUNCTION(divu_3216_1616_) +GLABEL(divu_3216_1616_) + // see cl_low_div.cc for algorithm + // in that notation: a1 = r, a2 = -s. + MOV a2,a2,LSL#15 // multiply divisor by 2^15 + RSB a2,a2,#0 // negate divisor + ADDS a1,a2,a1 // dividend = dividend + -divisor/2 + SUBCC a1,a1,a2 // dividend = dividend - -divisor/2 + ADCS a1,a2,a1,LSL#1 // dividend = dividend*2 + -divisor + // and shift quotient + SUBCC a1,a1,a2 // do this another 14 times + ADCS a1,a2,a1,LSL#1 + SUBCC a1,a1,a2 + ADCS a1,a2,a1,LSL#1 + SUBCC a1,a1,a2 + ADCS a1,a2,a1,LSL#1 + SUBCC a1,a1,a2 + ADCS a1,a2,a1,LSL#1 + SUBCC a1,a1,a2 + ADCS a1,a2,a1,LSL#1 + SUBCC a1,a1,a2 + ADCS a1,a2,a1,LSL#1 + SUBCC a1,a1,a2 + ADCS a1,a2,a1,LSL#1 + SUBCC a1,a1,a2 + ADCS a1,a2,a1,LSL#1 + SUBCC a1,a1,a2 + ADCS a1,a2,a1,LSL#1 + SUBCC a1,a1,a2 + ADCS a1,a2,a1,LSL#1 + SUBCC a1,a1,a2 + ADCS a1,a2,a1,LSL#1 + SUBCC a1,a1,a2 + ADCS a1,a2,a1,LSL#1 + SUBCC a1,a1,a2 + ADCS a1,a2,a1,LSL#1 + SUBCC a1,a1,a2 + ADCS a1,a2,a1,LSL#1 + SUBCC a1,a1,a2 // do the last conditional subtraction + MOV a2,a1,LSR#15 // move remainder into a2 and shift + ADC a1,a1,a1 // move last bit of quotient in + MOV a1,a1,LSL#16 // AND out top 16 bits by shifting up + MOV a1,a1,LSR#16 // and back down again +#ifdef DIVU_16_REST + LDR a3,[pc,#ptr_divu_16_rest-.-8] // save rest so can be picked up later + STR a2,[a3,#0] // the result is 16 bits +#endif + MOVS pc, lr + +// extern uint32 divu_6432_3232_ (uint32 xhi, uint32 xlo, uint32 y); // -> Quotient q +// extern uint32 divu_32_rest; // -> Rest r +// see cl_low_div.cc for algorithm +// entry +// a1 = xhi (dividend) +// a2 = xlo (dividend) +// a3 = y (divisor) +// exit +// a1 = 32 bit quotient +// a2 = 32 bit remainder +// a3, a4 destroyed + EXPORT(divu_6432_3232_) + DECLARE_FUNCTION(divu_6432_3232_) +GLABEL(divu_6432_3232_) + STMFD sp!, {v1,v2,v3,v4,v5,v6,lr} + MOV v2, a2 // = xlo + MOV v1, a3 // = y + CMP a3,#&10000 // y <= (uint32)(bit(16)-1) + BCS divu_6432_3232_l1 + MOV a2, v2, LSR #16 + ORR a1, a2, a1, ASL #16 // = highlow32(low16(xhi),high16(xlo)) + MOV a2, v1 + BL C(divu_3216_1616_) + MOV v3, a1 // = q1 + MOV a1, v2, ASL #16 + MOV a1, a1, LSR #16 + ORR a1, a1, a2, ASL #16 // = highlow32(r1,low16(xlo)) + MOV a2, v1 + BL C(divu_3216_1616_) + ORR a1, a1, v3, ASL #16 // = highlow32(q1,q0) +#ifdef DIVU_32_REST + LDR a4,[pc,#ptr_divu_32_rest-.-8] + STR a2,[a4,#0] // divu_32_rest = remainder +#endif + LDMFD sp!, {v1,v2,v3,v4,v5,v6,pc}^ + +LABEL(divu_6432_3232_l1) + MOV v3, #0 // s = 0 + MOVS a4, v1, LSR #16 // while ((sint32)y >= 0) + ADDEQ v3, v3, #16 // { y = y<<1; s++; } + MOVEQ v1, v1, ASL #16 + MOVS a4, v1, LSR #24 + ADDEQ v3, v3, #8 + MOVEQ v1, v1, ASL #8 + MOVS a4, v1, LSR #28 + ADDEQ v3, v3, #4 + MOVEQ v1, v1, ASL #4 + MOVS a4, v1, LSR #30 + ADDEQ v3, v3, #2 + MOVEQ v1, v1, ASL #2 + MOVS a4, v1, LSR #31 + ADDEQ v3, v3, #1 + MOVEQ v1, v1, ASL #1 + + CMPS v3, #0 + MOVNE a2, a1, ASL v3 // if (!(s==0)) + RSBNE a1, v3, #32 // { xhi = (xhi << s) + ORRNE a1, a2, v2, LSR a1 // | (xlo >> (32-s)); + MOVNE v2, v2, ASL v3 // xlo = xlo << s; } + ADD a2, v1, #&10000 // y1_1 = high16(y)+1 + MOVS v5, a2, LSR #16 // if (y1_1 = 0) + MOVEQ v4, a1, ASL #16 // r16 = low16(xhi) * 2^16 + MOVEQ a1, a1, LSR #16 // q1 = high16(xhi) + MOVNE a2, v5 + BLNE C(divu_3216_1616_) // divu_3216_1616(xhi,y1_1, q1=,r16=) + MOVNE v4, a2, ASL #16 // r16 = r16 * 2^16 + ORR v4, v4, v2, LSR #16 // r = highlow32(r16,high16(xlo)) + MOV a4, v1, ASL #16 // tmp = mulu16(low16(y),q1) + MOV a4, a4, LSR #16 + MUL a3, a4, a1 + RSB a3, a3, a1, ASL #16 // r2 = highlow32_0(q1) - tmp + MOV v6, a1 // = q1 + ADDS a1, v4, a3 // r += r2 + ADDCS v6, v6, #1 // if ( r < r2 ) { q1 += 1 + SUBCS a1, a1, v1 // r -= y } + CMP a1, v1 // if (r >= y) + ADDCS v6, v6, #1 // { q1 += 1 + SUBCS a1, a1, v1 // r -= y } + CMP v5, #0 // if (y1_1 = 0) + MOVEQ v4, a1, ASL #16 // { r16 = low16(r) * 2^16 + MOVEQ a1, a1, LSR #16 // q0 = high16(r) } + MOVNE a2, v5 + BLNE C(divu_3216_1616_) // divu_3216_1616(r,y1_1, q0=,r16=) + MOVNE v4, a2, ASL #16 // r16 = r16 * 2^16 + MOV v2, v2, ASL #16 + ORR v4, v4, v2, LSR #16 // r = highlow32(r16,low16(xlo)) + MOV a4, v1, ASL #16 // tmp = mulu16(low16(y),q0) + MOV a4, a4, LSR #16 + MUL a3, a4, a1 + RSB a3, a3, a1, ASL #16 // r2 = highlow32_0(q0) - tmp + ADDS v4, v4, a3 // r += r2 + ADDCS a1, a1, #1 // if ( r < r2 ) { q0 += 1 + SUBCS v4, v4, v1 // r -= y } + CMP v4, v1 // if (r >= y) + ADDCS a1, a1, #1 // { q0 += 1 + SUBCS v4, v4, v1 // r -= y } + MOV a2, v4, LSR v3 // remainder = r >> s + ORR a1, a1, v6, ASL #16 // return highlow32(q1,q0) +#ifdef DIVU_32_REST + LDR a3,[pc,#ptr_divu_32_rest-.-8] + STR a2,[a3,#0] // divu_32_rest = remainder +#endif + LDMFD sp!, {v1,v2,v3,v4,v5,v6,pc}^ + +// extern uintD* copy_loop_up (uintD* sourceptr, uintD* destptr, uintC count); +// entry +// a1 = source pointer +// a2 = destination pointer +// a3 = count of words to store +// exit +// a1 = address of last word stored + 1 +// a2 - a4, ip destroyed + EXPORT(copy_loop_up) // word aligned copy loop up + DECLARE_FUNCTION(copy_loop_up) +GLABEL(copy_loop_up) + ANDS a4,a3,#3 // multiple of 4 words ? + BEQ copy_loop_up_l1 // yup, so branch + CMP a4,#2 // copy the first 1-3 words + LDR a4,[a1],#4 // to align the total to a multiple + STR a4,[a2],#4 // of 4 words + LDRGE a4,[a1],#4 + STRGE a4,[a2],#4 + LDRGT a4,[a1],#4 + STRGT a4,[a2],#4 +LABEL(copy_loop_up_l1) + BICS a4,a3,#3 // set counter to multiple of 4 + MOVEQ a1,a2 // return addr of last word stored + MOVEQS pc,lr // if zero then we're done + STMFD sp!,{v1,lr} // save work regs +LABEL(copy_loop_up_l2) + LDMIA a1!,{a3,v1,ip,lr} // copy 4 words in one go + STMIA a2!,{a3,v1,ip,lr} + SUBS a4,a4,#8 // decrement counter by 8 + LDMGEIA a1!,{a3,v1,ip,lr} // if count still positive then copy + STMGEIA a2!,{a3,v1,ip,lr} // 4 more words + BGT copy_loop_up_l2 // and loop + MOV a1,a2 // return addr of last word stored + LDMFD sp!,{v1,pc}^ // restore work regs and return + +// extern uintD* copy_loop_down (uintD* sourceptr, uintD* destptr, uintC count); +// entry +// a1 = source pointer +// a2 = destination pointer +// a3 = count of words to store +// exit +// a1 = address of last word stored +// a2 - a4, ip destroyed + EXPORT(copy_loop_down) // word aligned copy loop down + DECLARE_FUNCTION(copy_loop_down) +GLABEL(copy_loop_down) + ANDS a4,a3,#3 // multiple of 4 words ? + BEQ copy_loop_down_l1 // yup, so branch + CMP a4,#2 // copy the first 1-3 words + LDR a4,[a1,#-4]! // to align the total to a multiple + STR a4,[a2,#-4]! // of 4 words + LDRGE a4,[a1,#-4]! + STRGE a4,[a2,#-4]! + LDRGT a4,[a1,#-4]! + STRGT a4,[a2,#-4]! +LABEL(copy_loop_down_l1) + BICS a4,a3,#3 // set counter to multiple of 4 + MOVEQ a1,a2 // return addr of last word stored + MOVEQS pc,lr // if zero then we're done + STMFD sp!,{v1,lr} // save work regs +LABEL(copy_loop_down_l2) + LDMDB a1!,{a3,v1,ip,lr} // copy 4 words in one go + STMDB a2!,{a3,v1,ip,lr} + SUBS a4,a4,#8 // decrement counter by 8 + LDMGEDB a1!,{a3,v1,ip,lr} // if count still positive then copy + STMGEDB a2!,{a3,v1,ip,lr} // 4 more words + BGT copy_loop_down_l2 // and loop + MOV a1,a2 // return addr of last word stored + LDMFD sp!,{v1,pc}^ // restore work regs and return + +// extern uintD* clear_loop_up (uintD* destptr, uintC count); +// entry +// a1 = destination pointer +// a2 = count of words to store +// exit +// a1 = address of last word stored + 1 +// a2 - a4, ip destroyed + EXPORT(clear_loop_up) // word aligned clear loop up + DECLARE_FUNCTION(clear_loop_up) +GLABEL(clear_loop_up) + MOV a3,#0 // set filler to 0 + // and drop into fill_loop_up + +// extern uintD* fill_loop_up (uintD* destptr, uintC count, uintD filler); +// entry +// a1 = destination pointer +// a2 = count of words to store +// a3 = word to store +// exit +// a1 = address of last word stored + 1 +// a2 - a4, ip destroyed + EXPORT(fill_loop_up) // word aligned fill loop up + DECLARE_FUNCTION(fill_loop_up) +GLABEL(fill_loop_up) + ANDS a4,a2,#3 // multiple of 4 words ? + BEQ fill_loop_up_l1 // yup, so branch + CMP a4,#2 // store the first 1-3 words + STR a3,[a1],#4 // to align the total to a multiple + STRGE a3,[a1],#4 // of 4 words + STRGT a3,[a1],#4 +LABEL(fill_loop_up_l1) + BICS a4,a2,#3 // set counter to multiple of 4 + MOVEQS pc,lr // if zero then we're done + STMFD sp!,{v1,lr} // save work regs + MOV v1,a3 // copy filler to three other + MOV ip,a3 // registers + MOV lr,a3 +LABEL(fill_loop_up_l2) + STMIA a1!,{a3,v1,ip,lr} // store 4 fillers in one go + SUBS a4,a4,#8 // decrement counter by 8 + STMGEIA a1!,{a3,v1,ip,lr} // if count still positive then store 4 + BGT fill_loop_up_l2 // more and loop + LDMFD sp!,{v1,pc}^ // restore work regs and return + + +// extern uintD* clear_loop_down (uintD* destptr, uintC count); +// entry +// a1 = destination pointer +// a2 = count of words to store +// exit +// a1 = address of last word stored + 1 +// a2 - a4, ip destroyed + EXPORT(clear_loop_down) // word aligned clear loop down + DECLARE_FUNCTION(clear_loop_down) +GLABEL(clear_loop_down) + MOV a3,#0 // set filler to 0 + // and drop into fill_loop_down + +// extern uintD* fill_loop_down (uintD* destptr, uintC count, uintD filler); +// entry +// a1 = destination pointer +// a2 = count of words to store +// a3 = word to store +// exit +// a1 = address of last word stored +// a2 - a4, ip destroyed + EXPORT(fill_loop_down) // word aligned fill loop down + DECLARE_FUNCTION(fill_loop_down) +GLABEL(fill_loop_down) + ANDS a4,a2,#3 // multiple of 4 words ? + BEQ fill_loop_down_l1 // yup, so branch + CMP a4,#2 // store the first 1-3 words + STR a3,[a1,#-4]! // to align the total to a multiple + STRGE a3,[a1,#-4]! // of 4 words + STRGT a3,[a1,#-4]! +LABEL(fill_loop_down_l1) + BICS a4,a2,#3 // set counter to multiple of 4 + MOVEQS pc,lr // if zero then we're done + STMFD sp!,{v1,lr} // save work regs + MOV v1,a3 // copy filler to three other + MOV ip,a3 // registers + MOV lr,a3 +LABEL(fill_loop_down_l2) + STMDB a1!,{a3,v1,ip,lr} // store 4 fillers in one go + SUBS a4,a4,#8 // decrement counter by 8 + STMGEDB a1!,{a3,v1,ip,lr} // if count still positive then store 4 + BGT fill_loop_down_l2 // more and loop + LDMFD sp!,{v1,pc}^ // restore work regs and return + +// extern void test_loop_up (uintD* xptr, uintC count); +// entry +// a1 = xptr +// a2 = count of words to be TESTed +// exit +// a1 = TRUE if any words are non-zero else FALSE +// a2 - a4, ip destroyed + EXPORT(test_loop_up) // word aligned test loop up + DECLARE_FUNCTION(test_loop_up) +GLABEL(test_loop_up) + MOV ip,a1 // move xptr to ip + MOV a1,#1 // set result to TRUE + ANDS a3,a2,#3 // multiple of 4 words ? + BEQ test_loop_up_l1 // yup, so branch + LDR a4,[ip],#4 // TEST the first 1-3 words + TEQ a4,#0 // align the total to a multiple of 4 + MOVNES pc,lr // return TRUE if AND_TEST ok + CMP a3,#2 + BLT test_loop_up_l1 // need to branch 'cos PSR set + LDRGE a4,[ip],#4 // when checking against zero + TEQGE a4,#0 + MOVNES pc,lr + CMP a3,#2 + BLE test_loop_up_l1 // need to branch 'cos PSR set + LDRGT a4,[ip],#4 // when checking against zero + TEQGT a4,#0 + MOVNES pc,lr +LABEL(test_loop_up_l1) + BICS a4,a2,#3 // set counter to multiple of 4 + MOVEQ a1,#0 // return FALSE + MOVEQS pc,lr // if zero then we're done + STMFD sp!,{v1,lr} // save work regs +LABEL(test_loop_up_l2) + LDMIA ip!,{a2,a3,v1,lr} // load 4 words in one go + TEQ a2,#0 // TEST the four words + TEQEQ a3,#0 + TEQEQ v1,#0 + TEQEQ lr,#0 + LDMNEFD sp!,{v1,pc}^ + SUBS a4,a4,#4 // decrement counter by 4 + BGT test_loop_up_l2 // if count still positive then loop + MOV a1,#0 + LDMFD sp!,{v1,pc}^ // restore work regs and return + +// extern void test_loop_down (uintD* xptr, uintC count); +// entry +// a1 = xptr +// a2 = count of words to be TESTed +// exit +// a1 = TRUE if any words are non-zero else FALSE +// a2 - a4, ip destroyed + EXPORT(test_loop_down) // word aligned test loop down + DECLARE_FUNCTION(test_loop_down) +GLABEL(test_loop_down) + MOV ip,a1 // move xptr to ip + MOV a1,#1 // set result to TRUE + ANDS a3,a2,#3 // multiple of 4 words ? + BEQ test_loop_down_l1 // yup, so branch + LDR a4,[ip,#-4]! // TEST the first 1-3 words + TEQ a4,#0 // align the total to a multiple of 4 + MOVNES pc,lr // return TRUE if AND_TEST ok + CMP a3,#2 + BLT test_loop_down_l1 // need to branch 'cos PSR set + LDRGE a4,[ip,#-4]! // when checking against zero + TEQGE a4,#0 + MOVNES pc,lr + CMP a3,#2 + BLE test_loop_down_l1 // need to branch 'cos PSR set + LDRGT a4,[ip,#-4]! // when checking against zero + TEQGT a4,#0 + MOVNES pc,lr +LABEL(test_loop_down_l1) + BICS a4,a2,#3 // set counter to multiple of 4 + MOVEQ a1,#0 // return FALSE + MOVEQS pc,lr // if zero then we're done + STMFD sp!,{v1,lr} // save work regs +LABEL(test_loop_down_l2) + LDMDB ip!,{a2,a3,v1,lr} // load 4 words in one go + TEQ a2,#0 // TEST the four words + TEQEQ a3,#0 + TEQEQ v1,#0 + TEQEQ lr,#0 + LDMNEFD sp!,{v1,pc}^ + SUBS a4,a4,#4 // decrement counter by 4 + BGT test_loop_down_l2 // if count still positive then loop + MOV a1,#0 + LDMFD sp!,{v1,pc}^ // restore work regs and return + +#if CL_DS_BIG_ENDIAN_P + +// extern void or_loop_up (uintD* xptr, uintD* yptr, uintC count); +// entry +// a1 = xptr +// a2 = yptr +// a3 = count of words to be ORed +// exit +// xptr |= yptr for count words +// a1 - a4, ip destroyed + EXPORT(or_loop_up) // word aligned or loop up + DECLARE_FUNCTION(or_loop_up) +GLABEL(or_loop_up) + ANDS a4,a3,#3 // multiple of 4 words ? + BEQ or_loop_up_l1 // yup, so branch + CMP a4,#2 // OR the first 1-3 words + LDR a4,[a2],#4 // to align the total to a multiple + LDR ip,[a1] // of 4 words + ORR ip,ip,a4 + STR ip,[a1],#4 + BLT or_loop_up_l1 // better to branch than skip instrs. + LDRGE a4,[a2],#4 + LDRGE ip,[a1] + ORRGE ip,ip,a4 + STRGE ip,[a1],#4 + LDRGT a4,[a2],#4 + LDRGT ip,[a1] + ORRGT ip,ip,a4 + STRGT ip,[a1],#4 +LABEL(or_loop_up_l1) + BICS a4,a3,#3 // set counter to multiple of 4 + MOVEQS pc,lr // if zero then we're done + STMFD sp!,{v1-v5,lr} // save work regs +LABEL(or_loop_up_l2) + LDMIA a2!,{a3,v1,v2,ip} // load 4 words in one go + LDMIA a1,{v3,v4,v5,lr} // load target words + ORR v3,v3,a3 // OR the four words + ORR v4,v4,v1 + ORR v5,v5,v2 + ORR lr,lr,ip + STMIA a1!,{v3,v4,v5,lr} // store 4 results + SUBS a4,a4,#4 // decrement counter by 4 + BGT or_loop_up_l2 // if count still positive then loop + LDMFD sp!,{v1-v5,pc}^ // restore work regs and return + +#endif + +// extern void xor_loop_up (uintD* xptr, uintD* yptr, uintC count); +// entry +// a1 = xptr +// a2 = yptr +// a3 = count of words to be XORed +// exit +// xptr ^= yptr for count words +// a1 - a4, ip destroyed + EXPORT(xor_loop_up) // word aligned xor loop up + DECLARE_FUNCTION(xor_loop_up) +GLABEL(xor_loop_up) + ANDS a4,a3,#3 // multiple of 4 words ? + BEQ xor_loop_up_l1 // yup, so branch + CMP a4,#2 // XOR the first 1-3 words + LDR a4,[a2],#4 // to align the total to a multiple + LDR ip,[a1] // of 4 words + EOR ip,ip,a4 + STR ip,[a1],#4 + BLT xor_loop_up_l1 // better to branch than skip instrs. + LDRGE a4,[a2],#4 + LDRGE ip,[a1] + EORGE ip,ip,a4 + STRGE ip,[a1],#4 + LDRGT a4,[a2],#4 + LDRGT ip,[a1] + EORGT ip,ip,a4 + STRGT ip,[a1],#4 +LABEL(xor_loop_up_l1) + BICS a4,a3,#3 // set counter to multiple of 4 + MOVEQS pc,lr // if zero then we're done + STMFD sp!,{v1-v5,lr} // save work regs +LABEL(xor_loop_up_l2) + LDMIA a2!,{a3,v1,v2,ip} // load 4 words in one go + LDMIA a1,{v3,v4,v5,lr} // load target words + EOR v3,v3,a3 // XOR the four words + EOR v4,v4,v1 + EOR v5,v5,v2 + EOR lr,lr,ip + STMIA a1!,{v3,v4,v5,lr} // store 4 results + SUBS a4,a4,#4 // decrement counter by 4 + BGT xor_loop_up_l2 // if count still positive then loop + LDMFD sp!,{v1-v5,pc}^ // restore work regs and return + +#if CL_DS_BIG_ENDIAN_P + +// extern void and_loop_up (uintD* xptr, uintD* yptr, uintC count); +// entry +// a1 = xptr +// a2 = yptr +// a3 = count of words to be ANDed +// exit +// xptr &= yptr for count words +// a1 - a4, ip destroyed + EXPORT(and_loop_up) // word aligned and loop up + DECLARE_FUNCTION(and_loop_up) +GLABEL(and_loop_up) + ANDS a4,a3,#3 // multiple of 4 words ? + BEQ and_loop_up_l1 // yup, so branch + CMP a4,#2 // AND the first 1-3 words + LDR a4,[a2],#4 // to align the total to a multiple + LDR ip,[a1] // of 4 words + AND ip,ip,a4 + STR ip,[a1],#4 + BLT and_loop_up_l1 // better to branch than skip instrs. + LDRGE a4,[a2],#4 + LDRGE ip,[a1] + ANDGE ip,ip,a4 + STRGE ip,[a1],#4 + LDRGT a4,[a2],#4 + LDRGT ip,[a1] + ANDGT ip,ip,a4 + STRGT ip,[a1],#4 +LABEL(and_loop_up_l1) + BICS a4,a3,#3 // set counter to multiple of 4 + MOVEQS pc,lr // if zero then we're done + STMFD sp!,{v1-v5,lr} // save work regs +LABEL(and_loop_up_l2) + LDMIA a2!,{a3,v1,v2,ip} // load 4 words in one go + LDMIA a1,{v3,v4,v5,lr} // load target words + AND v3,v3,a3 // AND the four words + AND v4,v4,v1 + AND v5,v5,v2 + AND lr,lr,ip + STMIA a1!,{v3,v4,v5,lr} // store 4 results + SUBS a4,a4,#4 // decrement counter by 4 + BGT and_loop_up_l2 // if count still positive then loop + LDMFD sp!,{v1-v5,pc}^ // restore work regs and return + +// extern void eqv_loop_up (uintD* xptr, uintD* yptr, uintC count); +// entry +// a1 = xptr +// a2 = yptr +// a3 = count of words to be XORed +// exit +// xptr = ~(xptr ^ yptr) for count words +// a1 - a4, ip destroyed + EXPORT(eqv_loop_up) // word aligned eqv loop up + DECLARE_FUNCTION(eqv_loop_up) +GLABEL(eqv_loop_up) + ANDS a4,a3,#3 // multiple of 4 words ? + BEQ eqv_loop_up_l1 // yup, so branch + CMP a4,#2 // EQV the first 1-3 words + LDR a4,[a2],#4 // to align the total to a multiple + LDR ip,[a1] // of 4 words + EOR ip,ip,a4 + MVN ip,ip + STR ip,[a1],#4 + BLT eqv_loop_up_l1 // better to branch than skip instrs. + LDRGE a4,[a2],#4 + LDRGE ip,[a1] + EORGE ip,ip,a4 + MVNGE ip,ip + STRGE ip,[a1],#4 + BLE eqv_loop_up_l1 // better to branch than skip instrs. + LDRGT a4,[a2],#4 + LDRGT ip,[a1] + EORGT ip,ip,a4 + MVNGT ip,ip + STRGT ip,[a1],#4 +LABEL(eqv_loop_up_l1) + BICS a4,a3,#3 // set counter to multiple of 4 + MOVEQS pc,lr // if zero then we're done + STMFD sp!,{v1-v5,lr} // save work regs +LABEL(eqv_loop_up_l2) + LDMIA a2!,{a3,v1,v2,ip} // load 4 words in one go + LDMIA a1,{v3,v4,v5,lr} // load target words + EOR v3,v3,a3 // EVQ the four words + MVN v3,v3 + EOR v4,v4,v1 + MVN v4,v4 + EOR v5,v5,v2 + MVN v5,v5 + EOR lr,lr,ip + MVN lr,lr + STMIA a1!,{v3,v4,v5,lr} // store 4 results + SUBS a4,a4,#4 // decrement counter by 4 + BGT eqv_loop_up_l2 // if count still positive then loop + LDMFD sp!,{v1-v5,pc}^ // restore work regs and return + +// extern void nand_loop_up (uintD* xptr, uintD* yptr, uintC count); +// entry +// a1 = xptr +// a2 = yptr +// a3 = count of words to be NANDed +// exit +// xptr = ~(xptr & yptr) for count words +// a1 - a4, ip destroyed + EXPORT(nand_loop_up) // word aligned nand loop up + DECLARE_FUNCTION(nand_loop_up) +GLABEL(nand_loop_up) + ANDS a4,a3,#3 // multiple of 4 words ? + BEQ nand_loop_up_l1 // yup, so branch + CMP a4,#2 // NAND the first 1-3 words + LDR a4,[a2],#4 // to align the total to a multiple + LDR ip,[a1] // of 4 words + AND ip,ip,a4 + MVN ip,ip + STR ip,[a1],#4 + BLT nand_loop_up_l1 // better to branch than skip instrs. + LDRGE a4,[a2],#4 + LDRGE ip,[a1] + ANDGE ip,ip,a4 + MVNGE ip,ip + STRGE ip,[a1],#4 + BLE nand_loop_up_l1 // better to branch than skip instrs. + LDRGT a4,[a2],#4 + LDRGT ip,[a1] + ANDGT ip,ip,a4 + MVNGT ip,ip + STRGT ip,[a1],#4 +LABEL(nand_loop_up_l1) + BICS a4,a3,#3 // set counter to multiple of 4 + MOVEQS pc,lr // if zero then we're done + STMFD sp!,{v1-v5,lr} // save work regs +LABEL(nand_loop_up_l2) + LDMIA a2!,{a3,v1,v2,ip} // load 4 words in one go + LDMIA a1,{v3,v4,v5,lr} // load target words + AND v3,v3,a3 // NAND the four words + MVN v3,v3 + AND v4,v4,v1 + MVN v4,v4 + AND v5,v5,v2 + MVN v5,v5 + AND lr,lr,ip + MVN lr,lr + STMIA a1!,{v3,v4,v5,lr} // store 4 results + SUBS a4,a4,#4 // decrement counter by 4 + BGT nand_loop_up_l2 // if count still positive then loop + LDMFD sp!,{v1-v5,pc}^ // restore work regs and return + +// extern void nor_loop_up (uintD* xptr, uintD* yptr, uintC count); +// entry +// a1 = xptr +// a2 = yptr +// a3 = count of words to be NORed +// exit +// xptr = ~(xptr | yptr) for count words +// a1 - a4, ip destroyed + EXPORT(nor_loop_up) // word aligned nor loop up + DECLARE_FUNCTION(nor_loop_up) +GLABEL(nor_loop_up) + ANDS a4,a3,#3 // multiple of 4 words ? + BEQ nor_loop_up_l1 // yup, so branch + CMP a4,#2 // NOR the first 1-3 words + LDR a4,[a2],#4 // to align the total to a multiple + LDR ip,[a1] // of 4 words + ORR ip,ip,a4 + MVN ip,ip + STR ip,[a1],#4 + BLT nor_loop_up_l1 // better to branch than skip instrs. + LDRGE a4,[a2],#4 + LDRGE ip,[a1] + ORRGE ip,ip,a4 + MVNGE ip,ip + STRGE ip,[a1],#4 + BLE nor_loop_up_l1 // better to branch than skip instrs. + LDRGT a4,[a2],#4 + LDRGT ip,[a1] + ORRGT ip,ip,a4 + MVNGT ip,ip + STRGT ip,[a1],#4 +LABEL(nor_loop_up_l1) + BICS a4,a3,#3 // set counter to multiple of 4 + MOVEQS pc,lr // if zero then we're done + STMFD sp!,{v1-v5,lr} // save work regs +LABEL(nor_loop_up_l2) + LDMIA a2!,{a3,v1,v2,ip} // load 4 words in one go + LDMIA a1,{v3,v4,v5,lr} // load target words + ORR v3,v3,a3 // NOR the four words + MVN v3,v3 + ORR v4,v4,v1 + MVN v4,v4 + ORR v5,v5,v2 + MVN v5,v5 + ORR lr,lr,ip + MVN lr,lr + STMIA a1!,{v3,v4,v5,lr} // store 4 results + SUBS a4,a4,#4 // decrement counter by 4 + BGT nor_loop_up_l2 // if count still positive then loop + LDMFD sp!,{v1-v5,pc}^ // restore work regs and return + +// extern void andc2_loop_up (uintD* xptr, uintD* yptr, uintC count); +// entry +// a1 = xptr +// a2 = yptr +// a3 = count of words to be ANDC2ed +// exit +// xptr = xptr & ~yptr for count words +// a1 - a4, ip destroyed + EXPORT(andc2_loop_up) // word aligned andc2 loop up + DECLARE_FUNCTION(andc2_loop_up) +GLABEL(andc2_loop_up) + ANDS a4,a3,#3 // multiple of 4 words ? + BEQ andc2_loop_up_l1 // yup, so branch + CMP a4,#2 // ANDC2 the first 1-3 words + LDR a4,[a2],#4 // to align the total to a multiple + LDR ip,[a1] // of 4 words + BIC ip,ip,a4 + STR ip,[a1],#4 + BLT andc2_loop_up_l1 // better to branch than skip instrs. + LDRGE a4,[a2],#4 + LDRGE ip,[a1] + BICGE ip,ip,a4 + STRGE ip,[a1],#4 + LDRGT a4,[a2],#4 + LDRGT ip,[a1] + BICGT ip,ip,a4 + STRGT ip,[a1],#4 +LABEL(andc2_loop_up_l1) + BICS a4,a3,#3 // set counter to multiple of 4 + MOVEQS pc,lr // if zero then we're done + STMFD sp!,{v1-v5,lr} // save work regs +LABEL(andc2_loop_up_l2) + LDMIA a2!,{a3,v1,v2,ip} // load 4 words in one go + LDMIA a1,{v3,v4,v5,lr} // load target words + BIC v3,v3,a3 // ANDC2 the four words + BIC v4,v4,v1 + BIC v5,v5,v2 + BIC lr,lr,ip + STMIA a1!,{v3,v4,v5,lr} // store 4 results + SUBS a4,a4,#4 // decrement counter by 4 + BGT andc2_loop_up_l2 // if count still positive then loop + LDMFD sp!,{v1-v5,pc}^ // restore work regs and return + +// extern void orc2_loop_up (uintD* xptr, uintD* yptr, uintC count); +// entry +// a1 = xptr +// a2 = yptr +// a3 = count of words to be XORed +// exit +// xptr = xptr | ~yptr for count words +// a1 - a4, ip destroyed + EXPORT(orc2_loop_up) // word aligned orc2 loop up + DECLARE_FUNCTION(orc2_loop_up) +GLABEL(orc2_loop_up) + ANDS a4,a3,#3 // multiple of 4 words ? + BEQ orc2_loop_up_l1 // yup, so branch + CMP a4,#2 // ORC2 the first 1-3 words + LDR a4,[a2],#4 // to align the total to a multiple + LDR ip,[a1] // of 4 words + MVN a4,a4 + ORR ip,ip,a4 + STR ip,[a1],#4 + BLT orc2_loop_up_l1 // better to branch than skip instrs. + LDRGE a4,[a2],#4 + LDRGE ip,[a1] + MVNGE a4,a4 + ORRGE ip,ip,a4 + STRGE ip,[a1],#4 + BLE orc2_loop_up_l1 // better to branch than skip instrs. + LDRGT a4,[a2],#4 + LDRGT ip,[a1] + MVNGT a4,a4 + ORRGT ip,ip,a4 + STRGT ip,[a1],#4 +LABEL(orc2_loop_up_l1) + BICS a4,a3,#3 // set counter to multiple of 4 + MOVEQS pc,lr // if zero then we're done + STMFD sp!,{v1-v5,lr} // save work regs +LABEL(orc2_loop_up_l2) + LDMIA a2!,{a3,v1,v2,ip} // load 4 words in one go + LDMIA a1,{v3,v4,v5,lr} // load target words + MVN a3,a3 // ORC2 the four words + ORR v3,v3,a3 + MVN v1,v1 + ORR v4,v4,v1 + MVN v2,v2 + ORR v5,v5,v2 + MVN ip,ip + ORR lr,lr,ip + STMIA a1!,{v3,v4,v5,lr} // store 4 results + SUBS a4,a4,#4 // decrement counter by 4 + BGT orc2_loop_up_l2 // if count still positive then loop + LDMFD sp!,{v1-v5,pc}^ // restore work regs and return + +// extern void not_loop_up (uintD* xptr, uintC count); +// entry +// a1 = xptr +// a2 = count of words to be NOTed +// exit +// xptr = ~xptr for count words +// a1 - a4, ip destroyed + EXPORT(not_loop_up) // word aligned not loop up + DECLARE_FUNCTION(not_loop_up) +GLABEL(not_loop_up) + ANDS a3,a2,#3 // multiple of 4 words ? + BEQ not_loop_up_l1 // yup, so branch + CMP a3,#2 // NOT the first 1-3 words + LDR a3,[a1] // to align the total to a multiple + MVN a3,a3 // of 4 words + STR a3,[a1],#4 + BLT not_loop_up_l1 // better to branch than skip instrs. + LDRGE a3,[a1] + MVNGE a3,a3 + STRGE a3,[a1],#4 + LDRGT a3,[a1] + MVNGT a3,a3 + STRGT a3,[a1],#4 +LABEL(not_loop_up_l1) + BICS a4,a2,#3 // set counter to multiple of 4 + MOVEQS pc,lr // if zero then we're done + STMFD sp!,{lr} // save work regs +LABEL(not_loop_up_l2) + LDMIA a1,{a2,a3,ip,lr} // load 4 words in one go,NO writeback + MVN a2,a2 // NOT the four words + MVN a3,a3 + MVN ip,ip + MVN lr,lr + STMIA a1!,{a2,a3,ip,lr} // store 4 results + SUBS a4,a4,#4 // decrement counter by 4 + BGT not_loop_up_l2 // if count still positive then loop + LDMFD sp!,{pc}^ // restore work regs and return + +// extern void and_test_loop_up (uintD* xptr, uintD* yptr, uintC count); +// entry +// a1 = xptr +// a2 = yptr +// a3 = count of words to be AND_TESTed +// exit +// a1 = TRUE if any words ANDed together are non-zero else FALSE +// a2 - a4, ip destroyed + EXPORT(and_test_loop_up) // word aligned and_test loop up + DECLARE_FUNCTION(and_test_loop_up) +GLABEL(and_test_loop_up) + ANDS a4,a3,#3 // multiple of 4 words ? + BEQ and_test_loop_up_l1 // yup, so branch + CMP a4,#2 + LDR a4,[a2],#4 // AND_TEST the first 1-3 words + LDR ip,[a1],#4 // to align the total to a multiple + TST ip,a4 // of 4 words + MOVNE a1,#1 // return TRUE if AND_TEST ok + MOVNES pc,lr + BCC and_test_loop_up_l1 // better to branch than skip instrs. + LDRGE a4,[a2],#4 + LDRGE ip,[a1],#4 + TSTGE ip,a4 + MOVNE a1,#1 + MOVNES pc,lr + ANDS a4,a3,#3 + CMP a4,#2 + BLE and_test_loop_up_l1 // better to branch than skip instrs. + LDRGT a4,[a2],#4 + LDRGT ip,[a1],#4 + TSTGT ip,a4 + MOVNE a1,#1 + MOVNES pc,lr +LABEL(and_test_loop_up_l1) + BICS a4,a3,#3 // set counter to multiple of 4 + MOVEQ a1,#0 // return FALSE + MOVEQS pc,lr // if zero then we're done + STMFD sp!,{v1-v6,lr} // save work regs + MOV v6,a1 // move xptr to v6 + MOV a1,#1 // set result to TRUE +LABEL(and_test_loop_up_l2) + LDMIA a2!,{a3,v1,v2,ip} // load 4 words in one go + LDMIA v6!,{v3,v4,v5,lr} // load target words + TST v3,a3 // AND_TEST the four words + TSTEQ v4,v1 + TSTEQ v5,v2 + TSTEQ lr,ip + LDMNEFD sp!,{v1-v6,pc}^ + SUBS a4,a4,#4 // decrement counter by 4 + BGT and_test_loop_up_l2 // if count still positive then loop + MOV a1,#0 + LDMFD sp!,{v1-v6,pc}^ // restore work regs and return + +#endif + +// extern void compare_loop_up (uintD* xptr, uintD* yptr, uintC count); +// entry +// a1 = xptr +// a2 = yptr +// a3 = count of words to be COMPAREd +// exit +// a1 = +1 if first non-equal word in xptr[] and yptr[] +// xptr[i] > yptr[i] +// -1 if xptr[i] < yptr[i] +// 0 otherwise +// a2 - a4, ip destroyed + EXPORT(compare_loop_up) // word aligned compare loop up + DECLARE_FUNCTION(compare_loop_up) +GLABEL(compare_loop_up) + ANDS a4,a3,#3 // multiple of 4 words ? + BEQ compare_loop_up_l1 // yup, so branch + LDR a4,[a2],#4 // COMPARE the first 1-3 words + LDR ip,[a1],#4 // to align the total to a multiple + CMP ip,a4 // of 4 words + MVNLO a1,#0 // x < y -> -1 + MOVHI a1,#1 // x > y -> +1 + MOVNES pc,lr // and return result if not equal + ANDS a4,a3,#3 + CMP a4,#2 + BLT compare_loop_up_l1 // need to branch 'cos PSR used + LDR a4,[a2],#4 + LDR ip,[a1],#4 + CMP ip,a4 + MVNLO a1,#0 + MOVHI a1,#1 + MOVNES pc,lr + ANDS a4,a3,#3 + CMP a4,#2 + BLE compare_loop_up_l1 // need to branch 'cos PSR used + LDR a4,[a2],#4 + LDR ip,[a1],#4 + CMP ip,a4 + MVNLO a1,#0 + MOVHI a1,#1 + MOVNES pc,lr +LABEL(compare_loop_up_l1) + BICS a4,a3,#3 // set counter to multiple of 4 + MOVEQ a1,#0 // xptr[] == yptr[] -> 0 + MOVEQS pc,lr // if zero then we're done + STMFD sp!,{v1-v6,lr} // save work regs + MOV v6,a1 // move xptr to v6 + MOV a1,#1 // set result to +1 +LABEL(compare_loop_up_l2) + LDMIA a2!,{a3,v1,v2,ip} // load 4 words in one go + LDMIA v6!,{v3,v4,v5,lr} // load test words + CMP v3,a3 // COMPARE the four words + CMPEQ v4,v1 + CMPEQ v5,v2 + CMPEQ lr,ip + MVNLO a1,#0 // x < y -> -1 (a1 already holds +1) + LDMNEFD sp!,{v1-v6,pc}^ + SUBS a4,a4,#4 // decrement counter by 4 + BGT compare_loop_up_l2 // if count still positive then loop + MOV a1,#0 + LDMFD sp!,{v1-v6,pc}^ // restore work regs and return + +#if CL_DS_BIG_ENDIAN_P + +// extern uintD addto_loop_down (uintD* sourceptr, uintD* destptr, uintC count); +// entry +// a1 = sourceptr +// a2 = destptr +// a3 = count of words to be added +// exit +// destptr[] = sourceptr[] + destptr[] +// a1 = last carry +// a2 - a4, ip destroyed + EXPORT(addto_loop_down) // word aligned addto loop down + DECLARE_FUNCTION(addto_loop_down) +GLABEL(addto_loop_down) + MOV a4,a3 // set regs for a call + MOV a3,a2 // to add_loop_down + // and drop into add_loop_down + +// extern uintD add_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count); +// entry +// a1 = sourceptr1 +// a2 = sourceptr2 +// a3 = destptr +// a4 = count of words to be added +// exit +// destptr[] = sourceptr1[] + sourceptr2[] +// a1 = last carry +// a2 - a4, ip destroyed + EXPORT(add_loop_down) // word aligned add loop down + DECLARE_FUNCTION(add_loop_down) +GLABEL(add_loop_down) + ANDS ip,a4,#3 // multiple of 4 words ? + BEQ add_loop_down_l1 // yup, so branch + STMFD sp!,{v6,lr} + LDR v6,[a2,#-4]! // add the first 1-3 words + LDR lr,[a1,#-4]! // to align the total to a multiple + ADDS lr,lr,v6 // of 4 words + STR lr,[a3,#-4]! + TEQ ip,#1 + BEQ add_loop_down_l0 // need to branch 'cos PSR used + LDR v6,[a2,#-4]! + LDR lr,[a1,#-4]! + ADCS lr,lr,v6 + STR lr,[a3,#-4]! + TEQ ip,#2 + BEQ add_loop_down_l0 // need to branch 'cos PSR used + LDR v6,[a2,#-4]! + LDR lr,[a1,#-4]! + ADCS lr,lr,v6 + STR lr,[a3,#-4]! +LABEL(add_loop_down_l0) // at least one add has happened + BICS a4,a4,#3 // set counter to multiple of 4 + BNE add_loop_down_l3 // branch if more adds to do + ADCEQ a1,a4,a4 // set result to Carry (a4 is 0) + LDMEQFD sp!,{v6,pc}^ // and return +LABEL(add_loop_down_l1) + BICS a4,a4,#3 // set counter to multiple of 4 + MOVEQ a1,#0 // no adds, so C = 0 + MOVEQS pc,lr // if zero then we're done + CMN a4,#0 // clear carry bit + STMFD sp!,{v6,lr} +LABEL(add_loop_down_l3) + STMFD sp!,{v1-v5} // save work regs +LABEL(add_loop_down_l2) + LDMDB a2!,{v1,v2,v3,ip} // load 4 words in one go + LDMDB a1!,{v4,v5,v6,lr} // and from source2 + ADCS lr,lr,ip // add the four words with carry + ADCS v6,v6,v3 + ADCS v5,v5,v2 + ADCS v4,v4,v1 + STMDB a3!,{v4,v5,v6,lr} // store 4 results + SUB a4,a4,#4 // decrement counter by 4, preserve C + TEQ a4,#0 // are we done ? + BNE add_loop_down_l2 // if count non-zero then loop + ADC a1,a4,a4 // set result to Carry (a4 is 0) + LDMFD sp!,{v1-v6,pc}^ // restore work regs and return + +// extern uintD inc_loop_down (uintD* ptr, uintC count); +// entry +// a1 = ptr +// a2 = count of words to be INCed +// exit +// a1 = 0 if any words are non-zero after increment else 1 +// stop incrementing when first word becomes non-zero +// a2 - a4, ip destroyed + EXPORT(inc_loop_down) // word aligned inc loop down + DECLARE_FUNCTION(inc_loop_down) +GLABEL(inc_loop_down) + ANDS a3,a2,#1 // multiple of 2 words ? + BEQ inc_loop_down_l1 // yup, so branch + LDR a4,[a1,#-4]! // INC the first word + ADDS a4,a4,#1 // align the total to a multiple of 2 + STR a4,[a1] + MOVNE a1,#0 // set result to 0 + MOVNES pc,lr // return 0 if non-zero result +LABEL(inc_loop_down_l1) + BICS a4,a2,#1 // set counter to multiple of 2 + MOVEQ a1,#1 // return 1 + MOVEQS pc,lr // if zero then we're done + MOV ip,a1 // move ptr to ip + MOV a1,#0 // set result to 0 + ANDS a3,a4,#3 + BEQ inc_loop_down_l3 + LDMDB ip,{a2,a3} // load 2 words in one go + ADDS a3,a3,#1 // INC the two words + ADDEQS a2,a2,#1 // stopping when first word non-zero + STMDB ip!,{a2,a3} // store 2 results + MOVNES pc,lr // return 0 if any result non-zero + SUBS a4,a4,#2 // decrement counter by 2 + MOVEQ a1,#1 // if finished loop then + MOVEQS pc,lr // return 1 +LABEL(inc_loop_down_l3) // now a multiple of 4 words + STMFD sp!,{v1,lr} // save work regs +LABEL(inc_loop_down_l2) + LDMDB ip,{a2,a3,v1,lr} // load 4 words in one go + ADDS lr,lr,#1 // INC the four words + ADDEQS v1,v1,#1 // stopping when first word non-zero + ADDEQS a3,a3,#1 + ADDEQS a2,a2,#1 + STMDB ip!,{a2,a3,v1,lr} // store 4 results + LDMNEFD sp!,{v1,pc}^ // return 0 if any result non-zero + SUBS a4,a4,#4 // decrement counter by 4 + BGT inc_loop_down_l2 // if count still positive then loop + MOV a1,#1 + LDMFD sp!,{v1,pc}^ // restore work regs and return 1 + +// extern uintD sub_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count); +// entry +// a1 = sourceptr1 +// a2 = sourceptr2 +// a3 = destptr +// a4 = count of words to be subtracted +// exit +// destptr[] = sourceptr1[] - sourceptr2[] +// a1 = last carry +// a2 - a4, ip destroyed + EXPORT(sub_loop_down) // word aligned sub loop down +LABEL(sub_loop_down) + ANDS ip,a4,#3 // multiple of 4 words ? + BEQ sub_loop_down_l1 // yup, so branch + STMFD sp!,{v6,lr} + LDR v6,[a2,#-4]! // subtract the first 1-3 words + LDR lr,[a1,#-4]! // to align the total to a multiple + SUBS lr,lr,v6 // of 4 words + STR lr,[a3,#-4]! + TEQ ip,#1 + BNE sub_loop_down_l0 // branch if more than one subtract +LABEL(sub_loop_down_l4) // drop through for better instr. timings + BICS a4,a4,#3 // set counter to multiple of 4 + SBCEQ a1,a4,a4 // set result to Carry (a4 is 0) + LDMEQFD sp!,{v6,pc}^ // and return + STMFD sp!,{v1-v5} // save work regs + B sub_loop_down_l2 // branch if more subtracts to do +LABEL(sub_loop_down_l0) + LDR v6,[a2,#-4]! + LDR lr,[a1,#-4]! + SBCS lr,lr,v6 + STR lr,[a3,#-4]! + TEQ ip,#2 + BEQ sub_loop_down_l4 // need to branch 'cos PSR used + LDR v6,[a2,#-4]! + LDR lr,[a1,#-4]! + SBCS lr,lr,v6 + STR lr,[a3,#-4]! + B sub_loop_down_l4 +LABEL(sub_loop_down_l1) + BICS a4,a4,#3 // set counter to multiple of 4 + MOVEQ a1,#0 // no subtracts, so C = 0 + MOVEQS pc,lr // if zero then we're done + CMP a4,#0 // set carry bit, since a4 > 0 + STMFD sp!,{v1-v6,lr} // save work regs +LABEL(sub_loop_down_l2) + LDMDB a2!,{v1,v2,v3,ip} // load 4 words in one go + LDMDB a1!,{v4,v5,v6,lr} // and from source2 + SBCS lr,lr,ip // subtract the four words with carry + SBCS v6,v6,v3 + SBCS v5,v5,v2 + SBCS v4,v4,v1 + STMDB a3!,{v4,v5,v6,lr} // store 4 results + SUB a4,a4,#4 // decrement counter by 4, preserve C + TEQ a4,#0 // are we done ? + BNE sub_loop_down_l2 // if count non-zero then loop + SBC a1,a4,a4 // set result to Carry (a4 is 0) + LDMFD sp!,{v1-v6,pc}^ // restore work regs and return + +// extern uintD subx_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry); +// entry +// a1 = sourceptr1 +// a2 = sourceptr2 +// a3 = destptr +// a4 = count of words to be subtracted +// [sp] = carry +// exit +// destptr[] = sourceptr1[] - sourceptr2[] +// a1 = last carry +// a2 - a4, ip destroyed + EXPORT(subx_loop_down) // word aligned xsub loop down +LABEL(subx_loop_down) + LDR ip,[sp] // get starting value of carry +LABEL(subx_loop_down_lsub) + RSBS ip,ip,#0 // set carry in PSR + ANDS ip,a4,#3 // multiple of 4 words ? + BEQ subx_loop_down_l1 // yup, so branch + STMFD sp!,{v6,lr} + LDR v6,[a2,#-4]! // subtract the first 1-3 words + LDR lr,[a1,#-4]! // to align the total to a multiple + SBCS lr,lr,v6 // of 4 words + STR lr,[a3,#-4]! + TEQ ip,#1 + BNE subx_loop_down_l0 // branch if more than one subtract +LABEL(subx_loop_down_l4) // drop through for better instr. timings + BICS a4,a4,#3 // set counter to multiple of 4 + SBCEQ a1,a4,a4 // set result to Carry (a4 is 0) + LDMEQFD sp!,{v6,pc}^ // and return + STMFD sp!,{v1-v5} // save work regs + B subx_loop_down_l2 // branch if more subtracts to do +LABEL(subx_loop_down_l0) + LDR v6,[a2,#-4]! + LDR lr,[a1,#-4]! + SBCS lr,lr,v6 + STR lr,[a3,#-4]! + TEQ ip,#2 + BEQ subx_loop_down_l4 // need to branch 'cos PSR used + LDR v6,[a2,#-4]! + LDR lr,[a1,#-4]! + SBCS lr,lr,v6 + STR lr,[a3,#-4]! + B subx_loop_down_l4 +LABEL(subx_loop_down_l1) + BICS a4,a4,#3 // set counter to multiple of 4 + SBCEQ a1,a4,a4 // set result to Carry (a4 is 0) + MOVEQS pc,lr // if zero then we're done + STMFD sp!,{v1-v6,lr} // save work regs +LABEL(subx_loop_down_l2) + LDMDB a2!,{v1,v2,v3,ip} // load 4 words in one go + LDMDB a1!,{v4,v5,v6,lr} // and from source2 + SBCS lr,lr,ip // subtract the four words with carry + SBCS v6,v6,v3 + SBCS v5,v5,v2 + SBCS v4,v4,v1 + STMDB a3!,{v4,v5,v6,lr} // store 4 results + SUB a4,a4,#4 // decrement counter by 4, preserve C + TEQ a4,#0 // are we done ? + BNE subx_loop_down_l2 // if count non-zero then loop + SBC a1,a4,a4 // set result to Carry (a4 is 0) + LDMFD sp!,{v1-v6,pc}^ // restore work regs and return + +// extern uintD subfrom_loop_down (uintD* sourceptr, uintD* destptr, uintC count); +// entry +// a1 = sourceptr +// a2 = destptr +// a3 = count of words to be subtracted +// exit +// destptr[] = destptr[] - sourceptr[] +// a1 = last carry +// a2 - a4, ip destroyed + EXPORT(subfrom_loop_down) // word aligned subfrom loop down + DECLARE_FUNCTION(subfrom_loop_down) +GLABEL(subfrom_loop_down) + ANDS ip,a3,#3 // multiple of 4 words ? + BEQ subfrom_loop_down_l1 // yup, so branch + STMFD sp!,{lr} + LDR a4,[a1,#-4]! // subtract the first 1-3 words + LDR lr,[a2,#-4]! // to align the total to a multiple + SUBS lr,lr,a4 // of 4 words + STR lr,[a2] + TEQ ip,#1 + BNE subfrom_loop_down_l0 // branch if more than one subtract +LABEL(subfrom_loop_down_l4) // drop through for better instr. timings + BICS a4,a3,#3 // set counter to multiple of 4 + SBCEQ a1,a4,a4 // set result to Carry (a4 is 0) + LDMEQFD sp!,{pc}^ // and return + STMFD sp!,{v1-v5} // save work regs + B subfrom_loop_down_l2 // branch if more subtracts to do +LABEL(subfrom_loop_down_l0) + LDR a4,[a1,#-4]! + LDR lr,[a2,#-4]! + SBCS lr,lr,a4 + STR lr,[a2] + TEQ ip,#2 + BEQ subfrom_loop_down_l4 // need to branch 'cos PSR used + LDR a4,[a1,#-4]! + LDR lr,[a2,#-4]! + SBCS lr,lr,a4 + STR lr,[a2] + B subfrom_loop_down_l4 +LABEL(subfrom_loop_down_l1) + BICS a4,a3,#3 // set counter to multiple of 4 + MOVEQ a1,#0 // no subtracts, so C = 0 + MOVEQS pc,lr // if zero then we're done + CMP a4,#0 // set carry bit, since a4 > 0 + STMFD sp!,{v1-v5,lr} // save work regs +LABEL(subfrom_loop_down_l2) + LDMDB a1!,{a3,v1,v2,ip} // load 4 words in one go + LDMDB a2,{v3,v4,v5,lr} // and from destptr + SBCS lr,lr,ip // subtract the four words with carry + SBCS v5,v5,v2 + SBCS v4,v4,v1 + SBCS v3,v3,a3 + STMDB a2!,{v3,v4,v5,lr} // store 4 results + SUB a4,a4,#4 // decrement counter by 4, preserve C + TEQ a4,#0 // are we done ? + BNE subfrom_loop_down_l2 // if count non-zero then loop + SBC a1,a4,a4 // set result to Carry (a4 is 0) + LDMFD sp!,{v1-v5,pc}^ // restore work regs and return + +// extern uintD dec_loop_down (uintD* ptr, uintC count); +// entry +// a1 = ptr +// a2 = count of words to be DECed +// exit +// a1 = 0 if any words are non-zero before decrement else -1 +// stop decrementing when first word is non-zero +// a2 - a4, ip destroyed + EXPORT(dec_loop_down) // word aligned dec loop down + DECLARE_FUNCTION(dec_loop_down) +GLABEL(dec_loop_down) + ANDS a3,a2,#1 // multiple of 2 words ? + BEQ dec_loop_down_l1 // yup, so branch + LDR a4,[a1,#-4]! // DEC the first word + SUBS a4,a4,#1 // align the total to a multiple of 2 + STR a4,[a1] + MOVCS a1,#0 // set result to 0 + MOVCSS pc,lr // return 0 if non-zero result +LABEL(dec_loop_down_l1) + BICS a4,a2,#1 // set counter to multiple of 2 + MVNEQ a1,#0 // return -1 + MOVEQS pc,lr // if zero then we're done + MOV ip,a1 // move ptr to ip + MOV a1,#0 // set result to 0 + ANDS a3,a4,#3 + BEQ dec_loop_down_l3 + LDMDB ip,{a2,a3} // load 2 words in one go + SUBS a3,a3,#1 // DEC the two words + SUBCCS a2,a2,#1 // stopping when first word non-zero + STMDB ip!,{a2,a3} // store 2 results + MOVCSS pc,lr // return 0 if any result non-zero + SUBS a4,a4,#2 // decrement counter by 2 + MVNEQ a1,#0 // if finished loop then + MOVEQS pc,lr // return -1 +LABEL(dec_loop_down_l3) // now a multiple of 4 words + STMFD sp!,{v1,lr} // save work regs +LABEL(dec_loop_down_l2) + LDMDB ip,{a2,a3,v1,lr} // load 4 words in one go + SUBS lr,lr,#1 // DEC the four words + SUBCCS v1,v1,#1 // stopping when first word non-zero + SUBCCS a3,a3,#1 + SUBCCS a2,a2,#1 + STMDB ip!,{a2,a3,v1,lr} // store 4 results + LDMCSFD sp!,{v1,pc}^ // return 0 if any carry + SUBS a4,a4,#4 // decrement counter by 4 + BGT dec_loop_down_l2 // if count still positive then loop + MVN a1,#0 + LDMFD sp!,{v1,pc}^ // restore work regs and return -1 + +// extern void neg_loop_down (uintD* ptr, uintC count); +// entry +// a1 = ptr +// a2 = count of words. The long integer is to be NEGated +// exit +// ptr[] = -ptr[] for count words +// a1 = last carry +// a2 - a4, ip destroyed + EXPORT(neg_loop_down) // word aligned neg loop down + DECLARE_FUNCTION(neg_loop_down) +GLABEL(neg_loop_down) + CMPS a2,#0 // count = 0 ? + MOVEQ a1,#0 // yup, so return 0 + MOVEQS pc,lr +LABEL(neg_loop_down_l1) // skip all the zero words first + LDR a3,[a1,#-4]! // compare words against zero + CMPS a3,#0 // downwards in memory + BNE neg_loop_down_l2 // non-zero, so negate rest of words + SUBS a2,a2,#1 // reduce count of words + BNE neg_loop_down_l1 // more ?, so loop + MOV a1,#0 // return 0 + MOVS pc,lr +LABEL(neg_loop_down_l2) + RSB a3,a3,#0 // first non-zero word = -word + STR a3,[a1] + SUBS a2,a2,#1 + MVNEQ a1,#0 // done ? -> return -1 + MOVEQS pc,lr + // now NOT rest of the words + ANDS a3,a2,#3 // multiple of 4 words ? + BEQ neg_loop_down_l3 // yup, so branch + CMP a3,#2 // NOT the first 1-3 words + LDR a3,[a1,#-4]! // to align the total to a multiple + MVN a3,a3 // of 4 words + STR a3,[a1] + BLT neg_loop_down_l3 // better to branch than skip instrs. + LDRGE a3,[a1,#-4]! + MVNGE a3,a3 + STRGE a3,[a1] + LDRGT a3,[a1,#-4]! + MVNGT a3,a3 + STRGT a3,[a1] +LABEL(neg_loop_down_l3) + BICS a4,a2,#3 // set counter to multiple of 4 + MVNEQ a1,#0 // set result to -1 + MOVEQS pc,lr // if zero then we're done + STMFD sp!,{lr} // save work regs +LABEL(neg_loop_down_l4) + LDMDB a1,{a2,a3,ip,lr} // load 4 words in one go,NO writeback + MVN a2,a2 // NOT the four words + MVN a3,a3 + MVN ip,ip + MVN lr,lr + STMDB a1!,{a2,a3,ip,lr} // store 4 results + SUBS a4,a4,#4 // decrement counter by 4 + BGT neg_loop_down_l4 // if count still positive then loop + MVN a1,#0 // set result to -1 + LDMFD sp!,{pc}^ // restore work regs and return -1 + +// extern uintD shift1left_loop_down (uintD* ptr, uintC count); +// entry +// a1 = ptr +// a2 = count of words to be shifted left +// exit +// a1 = carry out from last shift left +// a2 - a4, ip destroyed + EXPORT(shift1left_loop_down) // word aligned shift1left loop down + DECLARE_FUNCTION(shift1left_loop_down) +GLABEL(shift1left_loop_down) + CMN a1,#0 // clear carry bit, since a1 > 0 + ANDS a3,a2,#1 // multiple of 2 words ? + BEQ shift1left_loop_down_l1 // yup, so branch + LDR a4,[a1,#-4]! // shift left the first word + ADDS a4,a4,a4 + STR a4,[a1] +LABEL(shift1left_loop_down_l1) + BICS a4,a2,#1 // set counter to multiple of 2 + ADCEQ a1,a4,a4 // if zero set result to C (a4 is 0) + MOVEQS pc,lr // and return + ANDS a3,a4,#3 // multiple of 4 words ? + BEQ shift1left_loop_down_l3 // yup, so branch + LDMDB a1,{a2,a3} // load 2 words in one go + ADCS a3,a3,a3 // shift left the two words + ADCS a2,a2,a2 + STMDB a1!,{a2,a3} // store 2 results + BICS a4,a4,#2 // decrement counter by 2 + ADCEQ a1,a4,a4 // set result to Carry (a4 is 0) + MOVEQS pc,lr // and return +LABEL(shift1left_loop_down_l3) // now a multiple of 4 words + STMFD sp!,{lr} // save work regs +LABEL(shift1left_loop_down_l2) + LDMDB a1,{a2,a3,ip,lr} // load 4 words in one go + ADCS lr,lr,lr // shift left the four words + ADCS ip,ip,ip + ADCS a3,a3,a3 + ADCS a2,a2,a2 + STMDB a1!,{a2,a3,ip,lr} // store 4 results + SUB a4,a4,#4 // decrement counter by 4 + TEQ a4,#0 // are we done ? + BNE shift1left_loop_down_l2 // if count non-zero then loop + ADC a1,a4,a4 // set result to Carry (a4 is 0) + LDMFD sp!,{pc}^ // restore work regs and return 1 + +// extern uintD shiftleft_loop_down (uintD* ptr, uintC count, uintC i, uintD carry); +// entry +// a1 = ptr +// a2 = count of words to be shifted left +// a3 = size of left shift +// a4 = value to ORR in for first shift +// exit +// a1 = shift out from last shift left +// a2 - a4, ip destroyed + EXPORT(shiftleft_loop_down) // word aligned shiftleft loop down + DECLARE_FUNCTION(shiftleft_loop_down) +GLABEL(shiftleft_loop_down) + STMFD sp!,{v6,lr} + RSB v6,a3,#32 // size of complementary right shift + ANDS ip,a2,#3 // multiple of 4 words ? + BEQ shiftleft_loop_down_l1 // yup, so branch + LDR lr,[a1,#-4]! // shiftleft the first 1-3 words + ORR a4,a4,lr,ASL a3 // to align the total to a multiple + STR a4,[a1,#0] // of 4 words + MOV a4,lr,LSR v6 + CMP ip,#2 + BLT shiftleft_loop_down_l1 // better to branch than skip instrs. + LDRGE lr,[a1,#-4]! + ORRGE a4,a4,lr,ASL a3 + STRGE a4,[a1,#0] + MOVGE a4,lr,LSR v6 + LDRGT lr,[a1,#-4]! + ORRGT a4,a4,lr,ASL a3 + STRGT a4,[a1,#0] + MOVGT a4,lr,LSR v6 +LABEL(shiftleft_loop_down_l1) + BICS ip,a2,#3 // set counter to multiple of 4 + MOVEQ a1,a4 // if zero then we're done + LDMEQFD sp!,{v6,pc}^ // so return last shift out + STMFD sp!,{v1-v3} // save work regs +LABEL(shiftleft_loop_down_l2) + LDMDB a1,{a2,v1,v2,v3} // load 4 words in one go + ORR lr,a4,v3,ASL a3 // shiftleft the four words + MOV a4,v3,LSR v6 // keep carry in a4 + ORR v3,a4,v2,ASL a3 // and store results up a register + MOV a4,v2,LSR v6 // to regs v1-v3,lr + ORR v2,a4,v1,ASL a3 + MOV a4,v1,LSR v6 + ORR v1,a4,a2,ASL a3 + MOV a4,a2,LSR v6 + STMDB a1!,{v1,v2,v3,lr} // store 4 results + SUBS ip,ip,#4 // decrement counter by 4 + BGT shiftleft_loop_down_l2 // if count still positive then loop + MOV a1,a4 // result = last shift out + LDMFD sp!,{v1-v3,v6,pc}^ // restore work regs and return + +// extern uintD shiftleftcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i); +// entry +// a1 = sourceptr +// a2 = destptr +// a3 = count of words to be shifted left +// a4 = size of left shift +// exit +// a1 = shift out from last shift left +// a2 - a4, ip destroyed + EXPORT(shiftleftcopy_loop_down) // word aligned shiftleftcopy loop down + DECLARE_FUNCTION(shiftleftcopy_loop_down) +GLABEL(shiftleftcopy_loop_down) + STMFD sp!,{v5,v6,lr} + MOV v5,#0 // initial shift carry + RSB v6,a4,#32 // size of complementary right shift + ANDS ip,a3,#3 // multiple of 4 words ? + BEQ shiftleftcopy_loop_down_l1 // yup, so branch + LDR lr,[a1,#-4]! // shiftleft the first 1-3 words + ORR v5,v5,lr,ASL a4 // to align the total to a multiple + STR v5,[a2,#-4]! // of 4 words + MOV v5,lr,LSR v6 + CMP ip,#2 + BLT shiftleftcopy_loop_down_l1 // better to branch than skip instrs. + LDRGE lr,[a1,#-4]! + ORRGE v5,v5,lr,ASL a4 + STRGE v5,[a2,#-4]! + MOVGE v5,lr,LSR v6 + LDRGT lr,[a1,#-4]! + ORRGT v5,v5,lr,ASL a4 + STRGT v5,[a2,#-4]! + MOVGT v5,lr,LSR v6 +LABEL(shiftleftcopy_loop_down_l1) + BICS ip,a3,#3 // set counter to multiple of 4 + MOVEQ a1,v5 // if zero then we're done + LDMEQFD sp!,{v5,v6,pc}^ // so return last shift out + STMFD sp!,{v1-v3} // save work regs +LABEL(shiftleftcopy_loop_down_l2) + LDMDB a1!,{a3,v1,v2,v3} // load 4 words in one go + ORR lr,v5,v3,ASL a4 // shiftleft the four words + MOV v5,v3,LSR v6 // keep carry in v5 + ORR v3,v5,v2,ASL a4 // and store results up a register + MOV v5,v2,LSR v6 // to regs v1-v3,lr + ORR v2,v5,v1,ASL a4 + MOV v5,v1,LSR v6 + ORR v1,v5,a3,ASL a4 + MOV v5,a3,LSR v6 + STMDB a2!,{v1,v2,v3,lr} // store 4 results + SUBS ip,ip,#4 // decrement counter by 4 + BGT shiftleftcopy_loop_down_l2 // if count still positive then loop + MOV a1,v5 // result = last shift out + LDMFD sp!,{v1-v3,v5,v6,pc}^ // restore work regs and return + +// extern uintD shift1right_loop_up (uintD* ptr, uintC count, uintD carry); +// entry +// a1 = ptr +// a2 = count of words to be shifted right +// a3 = carry +// exit +// a1 = carry out from last shift right +// a2 - a4, ip destroyed + EXPORT(shift1right_loop_up) // word aligned shift1right loop up + DECLARE_FUNCTION(shift1right_loop_up) +GLABEL(shift1right_loop_up) + MOVS a3,a3,LSR #1 // set carry + ANDS a3,a2,#1 // multiple of 2 words ? + BEQ shift1right_loop_up_l1 // yup, so branch + LDR a4,[a1] // shift right the first word + MOVS a4,a4,RRX + STR a4,[a1],#4 +LABEL(shift1right_loop_up_l1) + BICS a4,a2,#1 // set counter to multiple of 2 + MOVEQ a1,a4,RRX // if zero set result to C (a4 is 0) + MOVEQS pc,lr // and return + ANDS a3,a4,#3 // multiple of 4 words ? + BEQ shift1right_loop_up_l3 // yup, so branch + LDMIA a1,{a2,a3} // load 2 words in one go + MOVS a2,a2,RRX // shift right the two words + MOVS a3,a3,RRX + STMIA a1!,{a2,a3} // store 2 results + BICS a4,a4,#2 // decrement counter by 2 + ADCEQ a1,a4,a4 // set result to Carry (a4 is 0) + MOVEQS pc,lr // and return +LABEL(shift1right_loop_up_l3) // now a multiple of 4 words + STMFD sp!,{lr} // save work regs +LABEL(shift1right_loop_up_l2) + LDMIA a1,{a2,a3,ip,lr} // load 4 words in one go + MOVS a2,a2,RRX // shift right the four words + MOVS a3,a3,RRX + MOVS ip,ip,RRX + MOVS lr,lr,RRX + STMIA a1!,{a2,a3,ip,lr} // store 4 results + SUB a4,a4,#4 // decrement counter by 4 + TEQ a4,#0 // are we done ? + BNE shift1right_loop_up_l2 // if count non-zero then loop + MOV a1,a4,RRX // set result to Carry (a4 is 0) + LDMFD sp!,{pc}^ // restore work regs and return 1 + +// extern uintD shiftright_loop_up (uintD* ptr, uintC count, uintC i); +// entry +// a1 = ptr +// a2 = count of words to be shifted right +// a3 = size of right shift +// exit +// a1 = shift out from last shift right +// a2 - a4, ip destroyed + EXPORT(shiftright_loop_up) // word aligned shiftright loop up + DECLARE_FUNCTION(shiftright_loop_up) +GLABEL(shiftright_loop_up) + STMFD sp!,{v6,lr} + MOV a4,#0 // initial shift carry + RSB v6,a3,#32 // size of complementary left shift +LABEL(shiftright_loop_up_l0) + ANDS ip,a2,#3 // multiple of 4 words ? + BEQ shiftright_loop_up_l1 // yup, so branch + LDR lr,[a1] // shiftright the first 1-3 words + ORR a4,a4,lr,LSR a3 // to align the total to a multiple + STR a4,[a1],#4 // of 4 words + MOV a4,lr,ASL v6 + CMP ip,#2 + BLT shiftright_loop_up_l1 // better to branch than skip instrs. + LDRGE lr,[a1] + ORRGE a4,a4,lr,LSR a3 + STRGE a4,[a1],#4 + MOVGE a4,lr,ASL v6 + LDRGT lr,[a1] + ORRGT a4,a4,lr,LSR a3 + STRGT a4,[a1],#4 + MOVGT a4,lr,ASL v6 +LABEL(shiftright_loop_up_l1) + BICS ip,a2,#3 // set counter to multiple of 4 + MOVEQ a1,a4 // if zero then we're done + LDMEQFD sp!,{v6,pc}^ // so return last shift out + STMFD sp!,{v1-v3} // save work regs +LABEL(shiftright_loop_up_l2) + LDMIA a1,{v1,v2,v3,lr} // load 4 words in one go + ORR a2,a4,v1,LSR a3 // shiftright the four words + MOV a4,v1,ASL v6 // keep carry in a4 + ORR v1,a4,v2,LSR a3 // and store results down a register + MOV a4,v2,ASL v6 // to regs a2,v1-v3 + ORR v2,a4,v3,LSR a3 + MOV a4,v3,ASL v6 + ORR v3,a4,lr,LSR a3 + MOV a4,lr,ASL v6 + STMIA a1!,{a2,v1,v2,v3} // store 4 results + SUBS ip,ip,#4 // decrement counter by 4 + BGT shiftright_loop_up_l2 // if count still positive then loop + MOV a1,a4 // result = last shift out + LDMFD sp!,{v1-v3,v6,pc}^ // restore work regs and return + +// extern uintD shiftrightsigned_loop_up (uintD* ptr, uintC count, uintC i); +// entry +// a1 = ptr +// a2 = count of words to be shifted right signed +// a3 = size of right shift +// exit +// a1 = shift out from last shift right +// a2 - a4, ip destroyed + EXPORT(shiftrightsigned_loop_up)// word aligned shiftrightsigned loop up + DECLARE_FUNCTION(shiftrightsigned_loop_up) +GLABEL(shiftrightsigned_loop_up) + STMFD sp!,{v6,lr} + RSB v6,a3,#32 // size of complementary left shift + LDR lr,[a1] // setup carry for first shift. + MOV a4,lr,ASR #31 // this is the sign extended bits + AND a4,a4,a4,LSL v6 // 31->(32-i) of the first word + B shiftright_loop_up_l0 // use right shift code now + +// extern uintD shiftrightcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry); +// entry +// a1 = sourceptr +// a2 = destptr +// a3 = count of words to be shifted right +// a4 = size of right shift +// [sp] = carry for first shift +// exit +// a1 = shift out from last shift right +// a2 - a4, ip destroyed + EXPORT(shiftrightcopy_loop_up) // word aligned shiftrightcopy loop up + DECLARE_FUNCTION(shiftrightcopy_loop_up) +GLABEL(shiftrightcopy_loop_up) + STMFD sp!,{v5,v6,lr} + LDR v5,[sp,#12] // initial shift carry + RSB v6,a4,#32 // size of complementary left shift + MOV v5,v5,ASL v6 +LABEL(shiftrightcopy_loop_up_l0) + ANDS ip,a3,#3 // multiple of 4 words ? + BEQ shiftrightcopy_loop_up_l1 // yup, so branch + LDR lr,[a1],#4 // shiftright the first 1-3 words + ORR v5,v5,lr,LSR a4 // to align the total to a multiple + STR v5,[a2],#4 // of 4 words + MOV v5,lr,ASL v6 + CMP ip,#2 + BLT shiftrightcopy_loop_up_l1 // better to branch than skip instrs. + LDRGE lr,[a1],#4 + ORRGE v5,v5,lr,LSR a4 + STRGE v5,[a2],#4 + MOVGE v5,lr,ASL v6 + LDRGT lr,[a1],#4 + ORRGT v5,v5,lr,LSR a4 + STRGT v5,[a2],#4 + MOVGT v5,lr,ASL v6 +LABEL(shiftrightcopy_loop_up_l1) + BICS ip,a3,#3 // set counter to multiple of 4 + MOVEQ a1,v5 // if zero then we're done + LDMEQFD sp!,{v5,v6,pc}^ // so return last shift out + STMFD sp!,{v1-v3} // save work regs +LABEL(shiftrightcopy_loop_up_l2) + LDMIA a1!,{v1,v2,v3,lr} // load 4 words in one go + ORR a3,v5,v1,LSR a4 // shiftright the four words + MOV v5,v1,ASL v6 // keep carry in v5 + ORR v1,v5,v2,LSR a4 // and store results down a register + MOV v5,v2,ASL v6 // to regs a2,v1-v3 + ORR v2,v5,v3,LSR a4 + MOV v5,v3,ASL v6 + ORR v3,v5,lr,LSR a4 + MOV v5,lr,ASL v6 + STMIA a2!,{a3,v1,v2,v3} // store 4 results + SUBS ip,ip,#4 // decrement counter by 4 + BGT shiftrightcopy_loop_up_l2 // if count still positive then loop + MOV a1,v5 // result = last shift out + LDMFD sp!,{v1-v3,v5,v6,pc}^ // restore work regs and return + +#ifndef HAVE_umull +// mulu32_64_vregs +// entry +// a1 = x +// ip = y +// exit +// v1 = low32(x*y) +// ip = high32(x*y) +// v2,v3,v4 destroyed +LABEL(mulu32_64_vregs) + MOV v1,a1,LSR #16 // temp := top half of x + MOV v2,ip,LSR #16 // hi := top half of y + BIC v3,a1,v1,LSL #16 // x := bottom half of x + BIC ip,ip,v2,LSL #16 // y := bottom half of y + MUL v4,v3,ip // low section of result + MUL ip,v1,ip // ) middle sections + MUL v3,v2,v3 // ) of result + MUL v2,v1,v2 // high section of result + ADDS ip,ip,v3 // add middle sections + // (can't use mla as we need carry) + ADDCS v2,v2,#&10000 // carry from above add + ADDS v1,v4,ip,LSL #16 // x is now bottom 32 bits of result + ADC ip,v2,ip,LSR #16 // hi is top 32 bits + MOVS pc,lr +#endif + +// extern uintD mulusmall_loop_down (uintD digit, uintD* ptr, uintC len, uintD newdigit); +// entry +// a1 = digit +// a2 = ptr +// a3 = count of words to be multiplied down +// a4 = new digit = carry +// exit +// a1 = final carry of multiply +// a2 - a4, ip destroyed + EXPORT(mulusmall_loop_down) + DECLARE_FUNCTION(mulusmall_loop_down) +GLABEL(mulusmall_loop_down) + CMP a3,#0 + MOVEQ a1,a4 + MOVEQS pc,lr +#ifdef HAVE_umull + STMFD sp!,{v1,lr} +LABEL(mulusmall_loop_down_l1) + LDR ip,[a2,#-4]! + UMULL v1,ip,a1,ip // muluD(digit,*--ptr,hi=,lo=) + ADDS v1,v1,a4 // lo += carry + ADC a4,ip,#0 // if (lo yptr[i] +// -1 if xptr[i] < yptr[i] +// 0 otherwise +// a2 - a4, ip destroyed + EXPORT(compare_loop_down) // word aligned compare loop down + DECLARE_FUNCTION(compare_loop_down) +GLABEL(compare_loop_down) + ANDS a4,a3,#3 // multiple of 4 words ? + BEQ compare_loop_down_l1 // yup, so branch + LDR a4,[a2,#-4]! // COMPARE the first 1-3 words + LDR ip,[a1,#-4]! // to align the total to a multiple + CMP ip,a4 // of 4 words + MVNLO a1,#0 // x < y -> -1 + MOVHI a1,#1 // x > y -> +1 + MOVNES pc,lr // and return result if not equal + ANDS a4,a3,#3 + CMP a4,#2 + BLT compare_loop_down_l1 // need to branch 'cos PSR used + LDR a4,[a2,#-4]! + LDR ip,[a1,#-4]! + CMP ip,a4 + MVNLO a1,#0 + MOVHI a1,#1 + MOVNES pc,lr + ANDS a4,a3,#3 + CMP a4,#2 + BLE compare_loop_down_l1 // need to branch 'cos PSR used + LDR a4,[a2,#-4]! + LDR ip,[a1,#-4]! + CMP ip,a4 + MVNLO a1,#0 + MOVHI a1,#1 + MOVNES pc,lr +LABEL(compare_loop_down_l1) + BICS a4,a3,#3 // set counter to multiple of 4 + MOVEQ a1,#0 // xptr[] == yptr[] -> 0 + MOVEQS pc,lr // if zero then we're done + STMFD sp!,{v1-v6,lr} // save work regs + MOV v6,a1 // move xptr to v6 + MOV a1,#1 // set result to +1 +LABEL(compare_loop_down_l2) + LDMDB a2!,{a3,v1,v2,ip} // load 4 words in one go + LDMDB v6!,{v3,v4,v5,lr} // load test words + CMP lr,ip // COMPARE the four words + CMPEQ v5,v2 + CMPEQ v4,v1 + CMPEQ v3,a3 + MVNLO a1,#0 // x < y -> -1 (a1 already holds +1) + LDMNEFD sp!,{v1-v6,pc}^ + SUBS a4,a4,#4 // decrement counter by 4 + BGT compare_loop_down_l2 // if count still positive then loop + MOV a1,#0 + LDMFD sp!,{v1-v6,pc}^ // restore work regs and return + +// extern uintD addto_loop_up (uintD* sourceptr, uintD* destptr, uintC count); +// entry +// a1 = sourceptr +// a2 = destptr +// a3 = count of words to be added +// exit +// destptr[] = sourceptr[] + destptr[] +// a1 = last carry +// a2 - a4, ip destroyed + EXPORT(addto_loop_up) // word aligned addto loop up + DECLARE_FUNCTION(addto_loop_up) +GLABEL(addto_loop_up) + MOV a4,a3 // set regs for a call + MOV a3,a2 // to add_loop_up + // and drop into add_loop_up + +// extern uintD add_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count); +// entry +// a1 = sourceptr1 +// a2 = sourceptr2 +// a3 = destptr +// a4 = count of words to be added +// exit +// destptr[] = sourceptr1[] + sourceptr2[] +// a1 = last carry +// a2 - a4, ip destroyed + EXPORT(add_loop_up) // word aligned add loop up + DECLARE_FUNCTION(add_loop_up) +GLABEL(add_loop_up) + ANDS ip,a4,#3 // multiple of 4 words ? + BEQ add_loop_up_l1 // yup, so branch + STMFD sp!,{v6,lr} + LDR v6,[a2],#4 // add the first 1-3 words + LDR lr,[a1],#4 // to align the total to a multiple + ADDS lr,lr,v6 // of 4 words + STR lr,[a3],#4 + TEQ ip,#1 + BEQ add_loop_up_l0 // need to branch 'cos PSR used + LDR v6,[a2],#4 + LDR lr,[a1],#4 + ADCS lr,lr,v6 + STR lr,[a3],#4 + TEQ ip,#2 + BEQ add_loop_up_l0 // need to branch 'cos PSR used + LDR v6,[a2],#4 + LDR lr,[a1],#4 + ADCS lr,lr,v6 + STR lr,[a3],#4 +LABEL(add_loop_up_l0) // at least one add has happened + BICS a4,a4,#3 // set counter to multiple of 4 + BNE add_loop_up_l3 // branch if more adds to do + ADCEQ a1,a4,a4 // set result to Carry (a4 is 0) + LDMEQFD sp!,{v6,pc}^ // and return +LABEL(add_loop_up_l1) + BICS a4,a4,#3 // set counter to multiple of 4 + MOVEQ a1,#0 // no adds, so C = 0 + MOVEQS pc,lr // if zero then we're done + CMN a4,#0 // clear carry bit + STMFD sp!,{v6,lr} +LABEL(add_loop_up_l3) + STMFD sp!,{v1-v5} // save work regs +LABEL(add_loop_up_l2) + LDMIA a2!,{v1,v2,v3,ip} // load 4 words in one go + LDMIA a1!,{v4,v5,v6,lr} // and from source2 + ADCS v4,v4,v1 // add the four words with carry + ADCS v5,v5,v2 + ADCS v6,v6,v3 + ADCS lr,lr,ip + STMIA a3!,{v4,v5,v6,lr} // store 4 results + SUB a4,a4,#4 // decrement counter by 4, preserve C + TEQ a4,#0 // are we done ? + BNE add_loop_up_l2 // if count non-zero then loop + ADC a1,a4,a4 // set result to Carry (a4 is 0) + LDMFD sp!,{v1-v6,pc}^ // restore work regs and return + +// extern uintD inc_loop_up (uintD* ptr, uintC count); +// entry +// a1 = ptr +// a2 = count of words to be INCed +// exit +// a1 = 0 if any words are non-zero after increment else 1 +// stop incrementing when first word becomes non-zero +// a2 - a4, ip destroyed + EXPORT(inc_loop_up) // word aligned inc loop up + DECLARE_FUNCTION(inc_loop_up) +GLABEL(inc_loop_up) + ANDS a3,a2,#1 // multiple of 2 words ? + BEQ inc_loop_up_l1 // yup, so branch + LDR a4,[a1] // INC the first word + ADDS a4,a4,#1 // align the total to a multiple of 2 + STR a4,[a1],#4 + MOVNE a1,#0 // set result to 0 + MOVNES pc,lr // return 0 if non-zero result +LABEL(inc_loop_up_l1) + BICS a4,a2,#1 // set counter to multiple of 2 + MOVEQ a1,#1 // return 1 + MOVEQS pc,lr // if zero then we're done + MOV ip,a1 // move ptr to ip + MOV a1,#0 // set result to 0 + ANDS a3,a4,#3 + BEQ inc_loop_up_l3 + LDMIA ip,{a2,a3} // load 2 words in one go + ADDS a2,a2,#1 // INC the two words + ADDEQS a3,a3,#1 // stopping when first word non-zero + STMIA ip!,{a2,a3} // store 2 results + MOVNES pc,lr // return 0 if any result non-zero + SUBS a4,a4,#2 // decrement counter by 2 + MOVEQ a1,#1 // if finished loop then + MOVEQS pc,lr // return 1 +LABEL(inc_loop_up_l3) // now a multiple of 4 words + STMFD sp!,{v1,lr} // save work regs +LABEL(inc_loop_up_l2) + LDMIA ip,{a2,a3,v1,lr} // load 4 words in one go + ADDS a2,a2,#1 // INC the four words + ADDEQS a3,a3,#1 // stopping when first word non-zero + ADDEQS v1,v1,#1 + ADDEQS lr,lr,#1 + STMIA ip!,{a2,a3,v1,lr} // store 4 results + LDMNEFD sp!,{v1,pc}^ // return 0 if any result non-zero + SUBS a4,a4,#4 // decrement counter by 4 + BGT inc_loop_up_l2 // if count still positive then loop + MOV a1,#1 + LDMFD sp!,{v1,pc}^ // restore work regs and return 1 + +// extern uintD sub_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count); +// entry +// a1 = sourceptr1 +// a2 = sourceptr2 +// a3 = destptr +// a4 = count of words to be subtracted +// exit +// destptr[] = sourceptr1[] - sourceptr2[] +// a1 = last carry +// a2 - a4, ip destroyed + EXPORT(sub_loop_up) // word aligned sub loop up + DECLARE_FUNCTION(sub_loop_up) +GLABEL(sub_loop_up) + ANDS ip,a4,#3 // multiple of 4 words ? + BEQ sub_loop_up_l1 // yup, so branch + STMFD sp!,{v6,lr} + LDR v6,[a2],#4 // subtract the first 1-3 words + LDR lr,[a1],#4 // to align the total to a multiple + SUBS lr,lr,v6 // of 4 words + STR lr,[a3],#4 + TEQ ip,#1 + BNE sub_loop_up_l0 // branch if more than one subtract +LABEL(sub_loop_up_l4) // drop through for better instr. timings + BICS a4,a4,#3 // set counter to multiple of 4 + SBCEQ a1,a4,a4 // set result to Carry (a4 is 0) + LDMEQFD sp!,{v6,pc}^ // and return + STMFD sp!,{v1-v5} // save work regs + B sub_loop_up_l2 // branch if more subtracts to do +LABEL(sub_loop_up_l0) + LDR v6,[a2],#4 + LDR lr,[a1],#4 + SBCS lr,lr,v6 + STR lr,[a3],#4 + TEQ ip,#2 + BEQ sub_loop_up_l4 // need to branch 'cos PSR used + LDR v6,[a2],#4 + LDR lr,[a1],#4 + SBCS lr,lr,v6 + STR lr,[a3],#4 + B sub_loop_up_l4 +LABEL(sub_loop_up_l1) + BICS a4,a4,#3 // set counter to multiple of 4 + MOVEQ a1,#0 // no subtracts, so C = 0 + MOVEQS pc,lr // if zero then we're done + CMP a4,#0 // set carry bit, since a4 > 0 + STMFD sp!,{v1-v6,lr} // save work regs +LABEL(sub_loop_up_l2) + LDMIA a2!,{v1,v2,v3,ip} // load 4 words in one go + LDMIA a1!,{v4,v5,v6,lr} // and from source2 + SBCS v4,v4,v1 // subtract the four words with carry + SBCS v5,v5,v2 + SBCS v6,v6,v3 + SBCS lr,lr,ip + STMIA a3!,{v4,v5,v6,lr} // store 4 results + SUB a4,a4,#4 // decrement counter by 4, preserve C + TEQ a4,#0 // are we done ? + BNE sub_loop_up_l2 // if count non-zero then loop + SBC a1,a4,a4 // set result to Carry (a4 is 0) + LDMFD sp!,{v1-v6,pc}^ // restore work regs and return + +// extern uintD subx_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry); +// entry +// a1 = sourceptr1 +// a2 = sourceptr2 +// a3 = destptr +// a4 = count of words to be subtracted +// [sp] = carry +// exit +// destptr[] = sourceptr1[] - sourceptr2[] +// a1 = last carry +// a2 - a4, ip destroyed + EXPORT(subx_loop_up) // word aligned xsub loop up + DECLARE_FUNCTION(subx_loop_up) +GLABEL(subx_loop_up) + LDR ip,[sp] // get starting value of carry +LABEL(subx_loop_up_lsub) + RSBS ip,ip,#0 // set carry in PSR + ANDS ip,a4,#3 // multiple of 4 words ? + BEQ subx_loop_up_l1 // yup, so branch + STMFD sp!,{v6,lr} + LDR v6,[a2],#4 // subtract the first 1-3 words + LDR lr,[a1],#4 // to align the total to a multiple + SBCS lr,lr,v6 // of 4 words + STR lr,[a3],#4 + TEQ ip,#1 + BNE subx_loop_up_l0 // branch if more than one subtract +LABEL(subx_loop_up_l4) // drop through for better instr. timings + BICS a4,a4,#3 // set counter to multiple of 4 + SBCEQ a1,a4,a4 // set result to Carry (a4 is 0) + LDMEQFD sp!,{v6,pc}^ // and return + STMFD sp!,{v1-v5} // save work regs + B subx_loop_up_l2 // branch if more subtracts to do +LABEL(subx_loop_up_l0) + LDR v6,[a2],#4 + LDR lr,[a1],#4 + SBCS lr,lr,v6 + STR lr,[a3],#4 + TEQ ip,#2 + BEQ subx_loop_up_l4 // need to branch 'cos PSR used + LDR v6,[a2],#4 + LDR lr,[a1],#4 + SBCS lr,lr,v6 + STR lr,[a3],#4 + B subx_loop_up_l4 +LABEL(subx_loop_up_l1) + BICS a4,a4,#3 // set counter to multiple of 4 + SBCEQ a1,a4,a4 // set result to Carry (a4 is 0) + MOVEQS pc,lr // if zero then we're done + STMFD sp!,{v1-v6,lr} // save work regs +LABEL(subx_loop_up_l2) + LDMIA a2!,{v1,v2,v3,ip} // load 4 words in one go + LDMIA a1!,{v4,v5,v6,lr} // and from source2 + SBCS v4,v4,v1 // subtract the four words with carry + SBCS v5,v5,v2 + SBCS v6,v6,v3 + SBCS lr,lr,ip + STMIA a3!,{v4,v5,v6,lr} // store 4 results + SUB a4,a4,#4 // decrement counter by 4, preserve C + TEQ a4,#0 // are we done ? + BNE subx_loop_up_l2 // if count non-zero then loop + SBC a1,a4,a4 // set result to Carry (a4 is 0) + LDMFD sp!,{v1-v6,pc}^ // restore work regs and return + +// extern uintD subfrom_loop_up (uintD* sourceptr, uintD* destptr, uintC count); +// entry +// a1 = sourceptr +// a2 = destptr +// a3 = count of words to be subtracted +// exit +// destptr[] = destptr[] - sourceptr[] +// a1 = last carry +// a2 - a4, ip destroyed + EXPORT(subfrom_loop_up) // word aligned subfrom loop up + DECLARE_FUNCTION(subfrom_loop_up) +GLABEL(subfrom_loop_up) + ANDS ip,a3,#3 // multiple of 4 words ? + BEQ subfrom_loop_up_l1 // yup, so branch + STMFD sp!,{lr} + LDR a4,[a1],#4 // subtract the first 1-3 words + LDR lr,[a2] // to align the total to a multiple + SUBS lr,lr,a4 // of 4 words + STR lr,[a2],#4 + TEQ ip,#1 + BNE subfrom_loop_up_l0 // branch if more than one subtract +LABEL(subfrom_loop_up_l4) // drop through for better instr. timings + BICS a4,a3,#3 // set counter to multiple of 4 + SBCEQ a1,a4,a4 // set result to Carry (a4 is 0) + LDMEQFD sp!,{pc}^ // and return + STMFD sp!,{v1-v5} // save work regs + B subfrom_loop_up_l2 // branch if more subtracts to do +LABEL(subfrom_loop_up_l0) + LDR a4,[a1],#4 + LDR lr,[a2] + SBCS lr,lr,a4 + STR lr,[a2],#4 + TEQ ip,#2 + BEQ subfrom_loop_up_l4 // need to branch 'cos PSR used + LDR a4,[a1],#4 + LDR lr,[a2] + SBCS lr,lr,a4 + STR lr,[a2],#4 + B subfrom_loop_up_l4 +LABEL(subfrom_loop_up_l1) + BICS a4,a3,#3 // set counter to multiple of 4 + MOVEQ a1,#0 // no subtracts, so C = 0 + MOVEQS pc,lr // if zero then we're done + CMP a4,#0 // set carry bit, since a4 > 0 + STMFD sp!,{v1-v5,lr} // save work regs +LABEL(subfrom_loop_up_l2) + LDMIA a1!,{a3,v1,v2,ip} // load 4 words in one go + LDMIA a2,{v3,v4,v5,lr} // and from destptr + SBCS v3,v3,a3 // subtract the four words with carry + SBCS v4,v4,v1 + SBCS v5,v5,v2 + SBCS lr,lr,ip + STMIA a2!,{v3,v4,v5,lr} // store 4 results + SUB a4,a4,#4 // decrement counter by 4, preserve C + TEQ a4,#0 // are we done ? + BNE subfrom_loop_up_l2 // if count non-zero then loop + SBC a1,a4,a4 // set result to Carry (a4 is 0) + LDMFD sp!,{v1-v5,pc}^ // restore work regs and return + +// extern uintD dec_loop_up (uintD* ptr, uintC count); +// entry +// a1 = ptr +// a2 = count of words to be DECed +// exit +// a1 = 0 if any words are non-zero before decrement else -1 +// stop decrementing when first word is non-zero +// a2 - a4, ip destroyed + EXPORT(dec_loop_up) // word aligned dec loop up + DECLARE_FUNCTION(dec_loop_up) +GLABEL(dec_loop_up) + ANDS a3,a2,#1 // multiple of 2 words ? + BEQ dec_loop_up_l1 // yup, so branch + LDR a4,[a1] // DEC the first word + SUBS a4,a4,#1 // align the total to a multiple of 2 + STR a4,[a1],#4 + MOVCS a1,#0 // set result to 0 + MOVCSS pc,lr // return 0 if non-zero result +LABEL(dec_loop_up_l1) + BICS a4,a2,#1 // set counter to multiple of 2 + MVNEQ a1,#0 // return -1 + MOVEQS pc,lr // if zero then we're done + MOV ip,a1 // move ptr to ip + MOV a1,#0 // set result to 0 + ANDS a3,a4,#3 + BEQ dec_loop_up_l3 + LDMIA ip,{a2,a3} // load 2 words in one go + SUBS a2,a2,#1 // DEC the two words + SUBCCS a3,a3,#1 // stopping when first word non-zero + STMIA ip!,{a2,a3} // store 2 results + MOVCSS pc,lr // return 0 if any result non-zero + SUBS a4,a4,#2 // decrement counter by 2 + MVNEQ a1,#0 // if finished loop then + MOVEQS pc,lr // return -1 +LABEL(dec_loop_up_l3) // now a multiple of 4 words + STMFD sp!,{v1,lr} // save work regs +LABEL(dec_loop_up_l2) + LDMIA ip,{a2,a3,v1,lr} // load 4 words in one go + SUBS a2,a2,#1 // DEC the four words + SUBCCS a3,a3,#1 // stopping when first word non-zero + SUBCCS v1,v1,#1 + SUBCCS lr,lr,#1 + STMIA ip!,{a2,a3,v1,lr} // store 4 results + LDMCSFD sp!,{v1,pc}^ // return 0 if any carry + SUBS a4,a4,#4 // decrement counter by 4 + BGT dec_loop_up_l2 // if count still positive then loop + MVN a1,#0 + LDMFD sp!,{v1,pc}^ // restore work regs and return -1 + +// extern void neg_loop_up (uintD* ptr, uintC count); +// entry +// a1 = ptr +// a2 = count of words. The long integer is to be NEGated +// exit +// ptr[] = -ptr[] for count words +// a1 = last carry +// a2 - a4, ip destroyed + EXPORT(neg_loop_up) // word aligned neg loop up + DECLARE_FUNCTION(neg_loop_up) +GLABEL(neg_loop_up) + CMPS a2,#0 // count = 0 ? + MOVEQ a1,#0 // yup, so return 0 + MOVEQS pc,lr +LABEL(neg_loop_up_l1) // skip all the zero words first + LDR a3,[a1],#4 // compare words against zero + CMPS a3,#0 // upwards in memory + BNE neg_loop_up_l2 // non-zero, so negate rest of words + SUBS a2,a2,#1 // reduce count of words + BNE neg_loop_up_l1 // more ?, so loop + MOV a1,#0 // return 0 + MOVS pc,lr +LABEL(neg_loop_up_l2) + RSB a3,a3,#0 // first non-zero word = -word + STR a3,[a1,#-4] + SUBS a2,a2,#1 + MVNEQ a1,#0 // done ? -> return -1 + MOVEQS pc,lr + // now NOT rest of the words + ANDS a3,a2,#3 // multiple of 4 words ? + BEQ neg_loop_up_l3 // yup, so branch + CMP a3,#2 // NOT the first 1-3 words + LDR a3,[a1] // to align the total to a multiple + MVN a3,a3 // of 4 words + STR a3,[a1],#4 + BLT neg_loop_up_l3 // better to branch than skip instrs. + LDRGE a3,[a1] + MVNGE a3,a3 + STRGE a3,[a1],#4 + LDRGT a3,[a1] + MVNGT a3,a3 + STRGT a3,[a1],#4 +LABEL(neg_loop_up_l3) + BICS a4,a2,#3 // set counter to multiple of 4 + MVNEQ a1,#0 // set result to -1 + MOVEQS pc,lr // if zero then we're done + STMFD sp!,{lr} // save work regs +LABEL(neg_loop_up_l4) + LDMIA a1,{a2,a3,ip,lr} // load 4 words in one go,NO writeback + MVN a2,a2 // NOT the four words + MVN a3,a3 + MVN ip,ip + MVN lr,lr + STMIA a1!,{a2,a3,ip,lr} // store 4 results + SUBS a4,a4,#4 // decrement counter by 4 + BGT neg_loop_up_l4 // if count still positive then loop + MVN a1,#0 // set result to -1 + LDMFD sp!,{pc}^ // restore work regs and return -1 + +// extern uintD shift1left_loop_up (uintD* ptr, uintC count); +// entry +// a1 = ptr +// a2 = count of words to be shifted left +// exit +// a1 = carry out from last shift left +// a2 - a4, ip destroyed + EXPORT(shift1left_loop_up) // word aligned shift1left loop up + DECLARE_FUNCTION(shift1left_loop_up) +GLABEL(shift1left_loop_up) + CMN a1,#0 // clear carry bit, since a1 > 0 + ANDS a3,a2,#1 // multiple of 2 words ? + BEQ shift1left_loop_up_l1 // yup, so branch + LDR a4,[a1] // shift left the first word + ADDS a4,a4,a4 + STR a4,[a1],#4 +LABEL(shift1left_loop_up_l1) + BICS a4,a2,#1 // set counter to multiple of 2 + ADCEQ a1,a4,a4 // if zero set result to C (a4 is 0) + MOVEQS pc,lr // and return + ANDS a3,a4,#3 // multiple of 4 words ? + BEQ shift1left_loop_up_l3 // yup, so branch + LDMIA a1,{a2,a3} // load 2 words in one go + ADCS a2,a2,a2 // shift left the two words + ADCS a3,a3,a3 + STMIA a1!,{a2,a3} // store 2 results + BICS a4,a4,#2 // decrement counter by 2 + ADCEQ a1,a4,a4 // set result to Carry (a4 is 0) + MOVEQS pc,lr // and return +LABEL(shift1left_loop_up_l3) // now a multiple of 4 words + STMFD sp!,{lr} // save work regs +LABEL(shift1left_loop_up_l2) + LDMIA a1,{a2,a3,ip,lr} // load 4 words in one go + ADCS a2,a2,a2 // shift left the four words + ADCS a3,a3,a3 + ADCS ip,ip,ip + ADCS lr,lr,lr + STMIA a1!,{a2,a3,ip,lr} // store 4 results + SUB a4,a4,#4 // decrement counter by 4 + TEQ a4,#0 // are we done ? + BNE shift1left_loop_up_l2 // if count non-zero then loop + ADC a1,a4,a4 // set result to Carry (a4 is 0) + LDMFD sp!,{pc}^ // restore work regs and return 1 + +// extern uintD shiftleft_loop_up (uintD* ptr, uintC count, uintC i, uintD carry); +// entry +// a1 = ptr +// a2 = count of words to be shifted left +// a3 = size of left shift +// a4 = value to ORR in for first shift +// exit +// a1 = shift out from last shift left +// a2 - a4, ip destroyed + EXPORT(shiftleft_loop_up) // word aligned shiftleft loop up + DECLARE_FUNCTION(shiftleft_loop_up) +GLABEL(shiftleft_loop_up) + STMFD sp!,{v6,lr} + RSB v6,a3,#32 // size of complementary right shift + ANDS ip,a2,#3 // multiple of 4 words ? + BEQ shiftleft_loop_up_l1 // yup, so branch + LDR lr,[a1] // shiftleft the first 1-3 words + ORR a4,a4,lr,ASL a3 // to align the total to a multiple + STR a4,[a1],#4 // of 4 words + MOV a4,lr,LSR v6 + CMP ip,#2 + BLT shiftleft_loop_up_l1 // better to branch than skip instrs. + LDRGE lr,[a1] + ORRGE a4,a4,lr,ASL a3 + STRGE a4,[a1],#4 + MOVGE a4,lr,LSR v6 + LDRGT lr,[a1] + ORRGT a4,a4,lr,ASL a3 + STRGT a4,[a1],#4 + MOVGT a4,lr,LSR v6 +LABEL(shiftleft_loop_up_l1) + BICS ip,a2,#3 // set counter to multiple of 4 + MOVEQ a1,a4 // if zero then we're done + LDMEQFD sp!,{v6,pc}^ // so return last shift out + STMFD sp!,{v1-v3} // save work regs +LABEL(shiftleft_loop_up_l2) + LDMIA a1,{v1,v2,v3,lr} // load 4 words in one go + ORR a2,a4,v1,ASL a3 // shiftleft the four words + MOV a4,v1,LSR v6 // keep carry in a4 + ORR v1,a4,v2,ASL a3 // and store results down a register + MOV a4,v2,LSR v6 // to regs a2,v1-v3 + ORR v2,a4,v3,ASL a3 + MOV a4,v3,LSR v6 + ORR v3,a4,lr,ASL a3 + MOV a4,lr,LSR v6 + STMIA a1!,{a2,v1,v2,v3} // store 4 results + SUBS ip,ip,#4 // decrement counter by 4 + BGT shiftleft_loop_up_l2 // if count still positive then loop + MOV a1,a4 // result = last shift out + LDMFD sp!,{v1-v3,v6,pc}^ // restore work regs and return + +#endif + +// extern uintD shiftleftcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i); +// entry +// a1 = sourceptr +// a2 = destptr +// a3 = count of words to be shifted left +// a4 = size of left shift +// exit +// a1 = shift out from last shift left +// a2 - a4, ip destroyed + EXPORT(shiftleftcopy_loop_up) // word aligned shiftleftcopy loop up + DECLARE_FUNCTION(shiftleftcopy_loop_up) +GLABEL(shiftleftcopy_loop_up) + STMFD sp!,{v5,v6,lr} + MOV v5,#0 // initial shift carry + RSB v6,a4,#32 // size of complementary right shift + ANDS ip,a3,#3 // multiple of 4 words ? + BEQ shiftleftcopy_loop_up_l1 // yup, so branch + LDR lr,[a1],#4 // shiftleft the first 1-3 words + ORR v5,v5,lr,ASL a4 // to align the total to a multiple + STR v5,[a2],#4 // of 4 words + MOV v5,lr,LSR v6 + CMP ip,#2 + BLT shiftleftcopy_loop_up_l1 // better to branch than skip instrs. + LDRGE lr,[a1],#4 + ORRGE v5,v5,lr,ASL a4 + STRGE v5,[a2],#4 + MOVGE v5,lr,LSR v6 + LDRGT lr,[a1],#4 + ORRGT v5,v5,lr,ASL a4 + STRGT v5,[a2],#4 + MOVGT v5,lr,LSR v6 +LABEL(shiftleftcopy_loop_up_l1) + BICS ip,a3,#3 // set counter to multiple of 4 + MOVEQ a1,v5 // if zero then we're done + LDMEQFD sp!,{v5,v6,pc}^ // so return last shift out + STMFD sp!,{v1-v3} // save work regs +LABEL(shiftleftcopy_loop_up_l2) + LDMIA a1!,{v1,v2,v3,lr} // load 4 words in one go + ORR a3,v5,v1,ASL a4 // shiftleft the four words + MOV v5,v1,LSR v6 // keep carry in v5 + ORR v1,v5,v2,ASL a4 // and store results down a register + MOV v5,v2,LSR v6 // to regs a3,v1-v3 + ORR v2,v5,v3,ASL a4 + MOV v5,v3,LSR v6 + ORR v3,v5,lr,ASL a4 + MOV v5,lr,LSR v6 + STMIA a2!,{a3,v1,v2,v3} // store 4 results + SUBS ip,ip,#4 // decrement counter by 4 + BGT shiftleftcopy_loop_up_l2 // if count still positive then loop + MOV a1,v5 // result = last shift out + LDMFD sp!,{v1-v3,v5,v6,pc}^ // restore work regs and return + +#if !CL_DS_BIG_ENDIAN_P + +// extern uintD shift1right_loop_down (uintD* ptr, uintC count, uintD carry); +// entry +// a1 = ptr +// a2 = count of words to be shifted right +// a3 = carry +// exit +// a1 = carry out from last shift right +// a2 - a4, ip destroyed + EXPORT(shift1right_loop_down) // word aligned shift1right loop down + DECLARE_FUNCTION(shift1right_loop_down) +GLABEL(shift1right_loop_down) + MOVS a3,a3,LSR #1 // set carry + ANDS a3,a2,#1 // multiple of 2 words ? + BEQ shift1right_loop_down_l1 // yup, so branch + LDR a4,[a1,#-4]! // shift right the first word + MOVS a4,a4,RRX + STR a4,[a1] +LABEL(shift1right_loop_down_l1) + BICS a4,a2,#1 // set counter to multiple of 2 + MOVEQ a1,a4,RRX // if zero set result to C (a4 is 0) + MOVEQS pc,lr // and return + ANDS a3,a4,#3 // multiple of 4 words ? + BEQ shift1right_loop_down_l3 // yup, so branch + LDMDB a1,{a2,a3} // load 2 words in one go + MOVS a3,a3,RRX // shift right the two words + MOVS a2,a2,RRX + STMDB a1!,{a2,a3} // store 2 results + BICS a4,a4,#2 // decrement counter by 2 + ADCEQ a1,a4,a4 // set result to Carry (a4 is 0) + MOVEQS pc,lr // and return +LABEL(shift1right_loop_down_l3) // now a multiple of 4 words + STMFD sp!,{lr} // save work regs +LABEL(shift1right_loop_down_l2) + LDMDB a1,{a2,a3,ip,lr} // load 4 words in one go + MOVS lr,lr,RRX // shift right the four words + MOVS ip,ip,RRX + MOVS a3,a3,RRX + MOVS a2,a2,RRX + STMDB a1!,{a2,a3,ip,lr} // store 4 results + SUB a4,a4,#4 // decrement counter by 4 + TEQ a4,#0 // are we done ? + BNE shift1right_loop_down_l2 // if count non-zero then loop + MOV a1,a4,RRX // set result to Carry (a4 is 0) + LDMFD sp!,{pc}^ // restore work regs and return 1 + +// extern uintD shiftright_loop_down (uintD* ptr, uintC count, uintC i); +// entry +// a1 = ptr +// a2 = count of words to be shifted right +// a3 = size of right shift +// exit +// a1 = shift out from last shift right +// a2 - a4, ip destroyed + EXPORT(shiftright_loop_down) // word aligned shiftright loop down + DECLARE_FUNCTION(shiftright_loop_down) +GLABEL(shiftright_loop_down) + STMFD sp!,{v6,lr} + MOV a4,#0 // initial shift carry + RSB v6,a3,#32 // size of complementary left shift +LABEL(shiftright_loop_down_l0) + ANDS ip,a2,#3 // multiple of 4 words ? + BEQ shiftright_loop_down_l1 // yup, so branch + LDR lr,[a1,#-4]! // shiftright the first 1-3 words + ORR a4,a4,lr,LSR a3 // to align the total to a multiple + STR a4,[a1] // of 4 words + MOV a4,lr,ASL v6 + CMP ip,#2 + BLT shiftright_loop_down_l1 // better to branch than skip instrs. + LDRGE lr,[a1,#-4]! + ORRGE a4,a4,lr,LSR a3 + STRGE a4,[a1] + MOVGE a4,lr,ASL v6 + LDRGT lr,[a1,#-4]! + ORRGT a4,a4,lr,LSR a3 + STRGT a4,[a1] + MOVGT a4,lr,ASL v6 +LABEL(shiftright_loop_down_l1) + BICS ip,a2,#3 // set counter to multiple of 4 + MOVEQ a1,a4 // if zero then we're done + LDMEQFD sp!,{v6,pc}^ // so return last shift out + STMFD sp!,{v1-v3} // save work regs +LABEL(shiftright_loop_down_l2) + LDMDB a1,{a2,v1,v2,v3} // load 4 words in one go + ORR lr,a4,v3,LSR a3 // shiftright the four words + MOV a4,v3,ASL v6 // keep carry in a4 + ORR v3,a4,v2,LSR a3 // and store results up a register + MOV a4,v2,ASL v6 // to regs v1-v3,lr + ORR v2,a4,v1,LSR a3 + MOV a4,v1,ASL v6 + ORR v1,a4,a2,LSR a3 + MOV a4,a2,ASL v6 + STMDB a1!,{v1,v2,v3,lr} // store 4 results + SUBS ip,ip,#4 // decrement counter by 4 + BGT shiftright_loop_down_l2 // if count still positive then loop + MOV a1,a4 // result = last shift out + LDMFD sp!,{v1-v3,v6,pc}^ // restore work regs and return + +// extern uintD shiftrightsigned_loop_down (uintD* ptr, uintC count, uintC i); +// entry +// a1 = ptr +// a2 = count of words to be shifted right signed +// a3 = size of right shift +// exit +// a1 = shift out from last shift right +// a2 - a4, ip destroyed + EXPORT(shiftrightsigned_loop_down)// word aligned shiftrightsigned loop down + DECLARE_FUNCTION(shiftrightsigned_loop_down) +GLABEL(shiftrightsigned_loop_down) + STMFD sp!,{v6,lr} + RSB v6,a3,#32 // size of complementary left shift + LDR lr,[a1,#-4] // setup carry for first shift. + MOV a4,lr,ASR #31 // this is the sign extended bits + AND a4,a4,a4,LSL v6 // 31->(32-i) of the first word + B shiftright_loop_down_l0 // use right shift code now + +// extern uintD shiftrightcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry); +// entry +// a1 = sourceptr +// a2 = destptr +// a3 = count of words to be shifted right +// a4 = size of right shift +// [sp] = carry for first shift +// exit +// a1 = shift out from last shift right +// a2 - a4, ip destroyed + EXPORT(shiftrightcopy_loop_down)// word aligned shiftrightcopy loop down + DECLARE_FUNCTION(shiftrightcopy_loop_down) +GLABEL(shiftrightcopy_loop_down) + STMFD sp!,{v5,v6,lr} + LDR v5,[sp,#12] // initial shift carry + RSB v6,a4,#32 // size of complementary left shift + MOV v5,v5,ASL v6 +LABEL(shiftrightcopy_loop_down_l0) + ANDS ip,a3,#3 // multiple of 4 words ? + BEQ shiftrightcopy_loop_down_l1 // yup, so branch + LDR lr,[a1,#-4]! // shiftright the first 1-3 words + ORR v5,v5,lr,LSR a4 // to align the total to a multiple + STR v5,[a2,#-4]! // of 4 words + MOV v5,lr,ASL v6 + CMP ip,#2 + BLT shiftrightcopy_loop_down_l1 // better to branch than skip instrs. + LDRGE lr,[a1,#-4]! + ORRGE v5,v5,lr,LSR a4 + STRGE v5,[a2,#-4]! + MOVGE v5,lr,ASL v6 + LDRGT lr,[a1,#-4]! + ORRGT v5,v5,lr,LSR a4 + STRGT v5,[a2,#-4]! + MOVGT v5,lr,ASL v6 +LABEL(shiftrightcopy_loop_down_l1) + BICS ip,a3,#3 // set counter to multiple of 4 + MOVEQ a1,v5 // if zero then we're done + LDMEQFD sp!,{v5,v6,pc}^ // so return last shift out + STMFD sp!,{v1-v3} // save work regs +LABEL(shiftrightcopy_loop_down_l2) + LDMDB a1!,{a3,v1,v2,v3} // load 4 words in one go + ORR lr,v5,v3,LSR a4 // shiftright the four words + MOV v5,v3,ASL v6 // keep carry in v5 + ORR v3,v5,v2,LSR a4 // and store results up a register + MOV v5,v2,ASL v6 // to regs v1-v3,lr + ORR v2,v5,v1,LSR a4 + MOV v5,v1,ASL v6 + ORR v1,v5,a3,LSR a4 + MOV v5,a3,ASL v6 + STMDB a2!,{v1,v2,v3,lr} // store 4 results + SUBS ip,ip,#4 // decrement counter by 4 + BGT shiftrightcopy_loop_down_l2 // if count still positive then loop + MOV a1,v5 // result = last shift out + LDMFD sp!,{v1-v3,v5,v6,pc}^ // restore work regs and return + +#ifndef HAVE_umull +// mulu32_64_vregs +// entry +// a1 = x +// ip = y +// exit +// v1 = low32(x*y) +// ip = high32(x*y) +// v2,v3,v4 destroyed +LABEL(mulu32_64_vregs) + MOV v1,a1,LSR #16 // temp := top half of x + MOV v2,ip,LSR #16 // hi := top half of y + BIC v3,a1,v1,LSL #16 // x := bottom half of x + BIC ip,ip,v2,LSL #16 // y := bottom half of y + MUL v4,v3,ip // low section of result + MUL ip,v1,ip // ) middle sections + MUL v3,v2,v3 // ) of result + MUL v2,v1,v2 // high section of result + ADDS ip,ip,v3 // add middle sections + // (can't use mla as we need carry) + ADDCS v2,v2,#&10000 // carry from above add + ADDS v1,v4,ip,LSL #16 // x is now bottom 32 bits of result + ADC ip,v2,ip,LSR #16 // hi is top 32 bits + MOVS pc,lr +#endif + +// extern uintD mulusmall_loop_up (uintD digit, uintD* ptr, uintC len, uintD newdigit); +// entry +// a1 = digit +// a2 = ptr +// a3 = count of words to be multiplied up +// a4 = new digit = carry +// exit +// a1 = final carry of multiply +// a2 - a4, ip destroyed + EXPORT(mulusmall_loop_up) + DECLARE_FUNCTION(mulusmall_loop_up) +GLABEL(mulusmall_loop_up) + CMP a3,#0 + MOVEQ a1,a4 + MOVEQS pc,lr +#ifdef HAVE_umull + STMFD sp!,{v1,lr} +LABEL(mulusmall_loop_up_l1) + LDR ip,[a2] + UMULL v1,ip,a1,ip // muluD(digit,*--ptr,hi=,lo=) + ADDS v1,v1,a4 // lo += carry + ADC a4,ip,#0 // if (lo=1, <=32) des Arguments /=0. +length32 .PROC + .CALLINFO + .ENTER // Input in %arg0, Output in %ret0 + // y = 1; + LDI 1,%ret0 + // if (x & (bit(31-15)*(bit(16)-1)) == 0) + EXTRU,<> %arg0,15,16,%r0 + SHD,TR %arg0,%r0,16,%arg0 // x = x<<(32-16); else + ADDI 16,%ret0,%ret0 // y = y+16; + // if (x & (bit(31-7)*(bit(8)-1)) == 0) + EXTRU,<> %arg0,7,8,%r0 + SHD,TR %arg0,%r0,24,%arg0 // x = x<<(32-24); else + ADDI 8,%ret0,%ret0 // y = y+8; + // if (x & (bit(31-3)*(bit(4)-1)) == 0) + EXTRU,<> %arg0,3,4,%r0 + SHD,TR %arg0,%r0,28,%arg0 // x = x<<(32-28); else + ADDI 4,%ret0,%ret0 // y = y+4; + // if (x & (bit(31-1)*(bit(2)-1)) == 0) + EXTRU,<> %arg0,1,2,%r0 + SHD,TR %arg0,%r0,30,%arg0 // x = x<<(32-30); else + ADDI 2,%ret0,%ret0 // y = y+2; + // if (x & (bit(31-0)*(bit(1)-1)) != 0) + EXTRU,= %arg0,0,1,%r0 + ADDI 1,%ret0,%ret0 // y = y+1; + .LEAVE + .PROCEND + + +#ifndef __GNUC__ /* mit GNU-C machen wir mulu32() als Macro, der inline multipliziert */ + + .SHORTDATA + .EXPORT mulu32_high + .ALIGN 8 +mulu32_high .WORD // 8 Byte Platz + .WORD + + .CODE + .EXPORT mulu32_ +// extern struct { uint32 lo; uint32 hi; } mulu32_ (uint32 arg1, uint32 arg2); +// 2^32*hi+lo := arg1*arg2. +mulu32_ .PROC + .CALLINFO + .ENTER // Input in %arg0,%arg1, Output in %ret0,mulu32_high + LDIL L'mulu32_high-$global$,%r1 + LDO R'mulu32_high-$global$(%r1),%r1 + // %r1 = &x + STW %arg0,0(%r1) // x abspeichern + FLDWS 0(%r1),%fr4 // und in den Coprozessor laden + STW %arg1,0(%r1) // y abspeichern + FLDWS 0(%r1),%fr5 // und in den Coprozessor laden + XMPYU %fr4,%fr5,%fr6 // beides multiplizieren + FSTDS %fr6,0(%r1) // Ergebnis (64 Bit) abspeichern + LDWS 4(%r1),%ret0 // low 32 Bit als Ergebnis + .LEAVE + .PROCEND + +#endif + + + .END diff --git a/src/base/digitseq/cl_asm_i386.h b/src/base/digitseq/cl_asm_i386.h new file mode 100644 index 0000000..3164928 --- /dev/null +++ b/src/base/digitseq/cl_asm_i386.h @@ -0,0 +1,11 @@ +// List the contents of cl_asm_i386.cc. + +#define COPY_LOOPS +#define FILL_LOOPS +#define CLEAR_LOOPS +#define LOG_LOOPS +#define TEST_LOOPS +#define ADDSUB_LOOPS +#define SHIFT_LOOPS +#define MUL_LOOPS +#define DIV_LOOPS diff --git a/src/base/digitseq/cl_asm_i386_.cc b/src/base/digitseq/cl_asm_i386_.cc new file mode 100644 index 0000000..4c8a59b --- /dev/null +++ b/src/base/digitseq/cl_asm_i386_.cc @@ -0,0 +1,2070 @@ +// Externe Routinen zu ARILEV1.D +// Prozessor: 80386 im native mode +// Assembler-Syntax: GNU oder SUN, Moves von links nach rechts +// Compiler: GNU-C oder SUN-C +// Parameter-Ãœbergabe: auf dem Stack 4(%esp),8(%esp),... +// Register: %eax,%edx,%ecx dürfen stets verändert werden, alles andere retten. +// Ergebnis-Ãœbergabe: in %eax +// Einstellungen: intCsize=32, intDsize=32. + +// Bruno Haible 14.8.1992 +// Zum Teil abgeschrieben von Bernhard Degels "v-i386.s" + + #ifdef ASM_UNDERSCORE + #if defined(__STDC__) || defined (__cplusplus) + #define C(entrypoint) _##entrypoint + #else + #define C(entrypoint) _/**/entrypoint + #endif + #else + #define C(entrypoint) entrypoint + #endif + #ifdef ASM_UNDERSCORE + #if defined(__STDC__) || defined (__cplusplus) + #define L(label) L##label + #else + #define L(label) L/**/label + #endif + #else + #if defined(__STDC__) || defined (__cplusplus) + #define L(label) .L##label + #else + #define L(label) .L/**/label + #endif + #endif + #if defined(ASM_UNDERSCORE) || defined(COHERENT) /* defined(__EMX__) || defined(__GO32__) || defined(linux) || defined(__386BSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(COHERENT) || ... */ + // GNU-Assembler oder MWC-Assembler + #define repz repe + #define shcl %cl, + #else /* defined(sun) || ... */ + // SUN-Assembler oder Consensys-Assembler + #define jecxz orl %ecx,%ecx ; jz + #define shcl + #endif + #if defined(__EMX__) + // Direction-Flag ist defaultmäßig gelöscht + #define dir0start + #define dir0end + #define dir1start std + #define dir1end cld + #elif 1 + // Wir gehen auf Nummer sicher. + #define dir0start cld + #define dir0end + #define dir1start std + #define dir1end cld + #else + // Direction-Flag darf nach Belieben modifiziert werden + #define dir0start cld + #define dir0end + #define dir1start std + #define dir1end + #endif + // Alignment. Note that some assemblers need ".align 3,0x90" whereas other + // assemblers don't like this syntax. So we put in the "nop"s by hand. + #if defined(ASM_UNDERSCORE) && !(defined(__CYGWIN32__) || defined(__MINGW32__)) + // BSD syntax assembler + #define ALIGN .align 3 + #else + // ELF syntax assembler + #define ALIGN .align 8 + #endif + // When this file is compiled into a shared library, ELF linkers need to + // know which symbols are functions. + #if defined(__svr4__) || defined(__ELF__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__ROSE__) || defined(_SEQUENT_) || defined(DGUX) || defined(_SCO_COFF) || defined(_SCO_ELF) + #define DECLARE_FUNCTION(name) .type C(name),@function + #else + #define DECLARE_FUNCTION(name) + #endif + + .text + + .globl C(copy_loop_up) + .globl C(copy_loop_down) + .globl C(fill_loop_up) + .globl C(fill_loop_down) + .globl C(clear_loop_up) + .globl C(clear_loop_down) + .globl C(test_loop_up) + .globl C(test_loop_down) + .globl C(xor_loop_up) + .globl C(compare_loop_up) + .globl C(shiftleftcopy_loop_up) + .globl C(shiftxor_loop_up) +#if CL_DS_BIG_ENDIAN_P + .globl C(or_loop_up) + .globl C(and_loop_up) + .globl C(eqv_loop_up) + .globl C(nand_loop_up) + .globl C(nor_loop_up) + .globl C(andc2_loop_up) + .globl C(orc2_loop_up) + .globl C(not_loop_up) + .globl C(and_test_loop_up) + .globl C(add_loop_down) + .globl C(addto_loop_down) + .globl C(inc_loop_down) + .globl C(sub_loop_down) + .globl C(subx_loop_down) + .globl C(subfrom_loop_down) + .globl C(dec_loop_down) + .globl C(neg_loop_down) + .globl C(shift1left_loop_down) + .globl C(shiftleft_loop_down) + .globl C(shiftleftcopy_loop_down) + .globl C(shift1right_loop_up) + .globl C(shiftright_loop_up) + .globl C(shiftrightsigned_loop_up) + .globl C(shiftrightcopy_loop_up) + .globl C(mulusmall_loop_down) + .globl C(mulu_loop_down) + .globl C(muluadd_loop_down) + .globl C(mulusub_loop_down) + .globl C(divu_loop_up) + .globl C(divucopy_loop_up) +#else + .globl C(or_loop_down) + .globl C(xor_loop_down) + .globl C(and_loop_down) + .globl C(eqv_loop_down) + .globl C(nand_loop_down) + .globl C(nor_loop_down) + .globl C(andc2_loop_down) + .globl C(orc2_loop_down) + .globl C(not_loop_down) + .globl C(and_test_loop_down) + .globl C(compare_loop_down) + .globl C(add_loop_up) + .globl C(addto_loop_up) + .globl C(inc_loop_up) + .globl C(sub_loop_up) + .globl C(subx_loop_up) + .globl C(subfrom_loop_up) + .globl C(dec_loop_up) + .globl C(neg_loop_up) + .globl C(shift1left_loop_up) + .globl C(shiftleft_loop_up) + .globl C(shift1right_loop_down) + .globl C(shiftright_loop_down) + .globl C(shiftrightsigned_loop_down) + .globl C(shiftrightcopy_loop_down) + .globl C(mulusmall_loop_up) + .globl C(mulu_loop_up) + .globl C(muluadd_loop_up) + .globl C(mulusub_loop_up) + .globl C(divu_loop_down) + .globl C(divucopy_loop_down) +#endif + +#ifndef __GNUC__ /* mit GNU-C machen wir mulu32() als Macro, der inline multipliziert */ + +// extern struct { uint32 lo; uint32 hi; } mulu32_ (uint32 arg1, uint32 arg2); +// 2^32*hi+lo := arg1*arg2. + .globl C(mulu32_) + ALIGN + DECLARE_FUNCTION(mulu32_) +C(mulu32_:) + movl 4(%esp),%eax // arg1 + mull 8(%esp) // %edx|%eax := arg1 * arg2 + movl %edx,C(mulu32_high) // %edx = hi abspeichern + ret // %eax = lo als Ergebnis + +#endif + +#ifndef __GNUC__ /* mit GNU-C machen wir divu_6432_3232() als Macro, der inline dividiert */ + +// extern struct { uint32 q; uint32 r; } divu_6432_3232_ (uint32 xhi, uint32 xlo, uint32 y); +// x = 2^32*xhi+xlo = q*y+r schreiben. Sei bekannt, daß 0 <= x < 2^32*y . + .globl C(divu_6432_3232_) + ALIGN + DECLARE_FUNCTION(divu_6432_3232_) +C(divu_6432_3232_:) + movl 4(%esp),%edx + movl 8(%esp),%eax + divl 12(%esp) // x = %edx|%eax durch dividieren + movl %edx,C(divu_32_rest) // Rest %edx = r abspeichern + ret // Quotient %eax = q als Ergebnis + +#endif + +// extern uintD* copy_loop_up (uintD* sourceptr, uintD* destptr, uintC count); + ALIGN + DECLARE_FUNCTION(copy_loop_up) +C(copy_loop_up:) + movl %edi,%edx // %edi retten + movl %esi,%eax // %esi retten + movl 4(%esp),%esi // %esi = sourceptr + movl 8(%esp),%edi // %edi = destptr + movl 12(%esp),%ecx // %ecx = count + dir0start + rep + movsl // %ecx mal aufwärts (%edi) := (%esi) + dir0end + movl %eax,%esi // %esi zurück + movl %edi,%eax // %edi als Ergebnis + movl %edx,%edi // %edi zurück + ret + +// extern uintD* copy_loop_down (uintD* sourceptr, uintD* destptr, uintC count); + ALIGN + DECLARE_FUNCTION(copy_loop_down) +C(copy_loop_down:) + movl %edi,%edx // %edi retten + movl %esi,%eax // %esi retten + movl 4(%esp),%esi // %esi = sourceptr + movl 8(%esp),%edi // %edi = destptr + movl 12(%esp),%ecx // %ecx = count + leal -4(%esi),%esi + leal -4(%edi),%edi + dir1start + rep + movsl // %ecx mal abwärts (%edi) := (%esi) + dir1end + movl %eax,%esi // %esi zurück + leal 4(%edi),%eax // %edi als Ergebnis + movl %edx,%edi // %edi zurück + ret + +// extern uintD* fill_loop_up (uintD* destptr, uintC count, uintD filler); + ALIGN + DECLARE_FUNCTION(fill_loop_up) +C(fill_loop_up:) + movl %edi,%edx // %edi retten + movl 4(%esp),%edi // %edi = destptr + movl 8(%esp),%ecx // %ecx = count + movl 12(%esp),%eax // %eax = filler + dir0start + rep + stosl // %ecx mal aufwärts (%edi) := %eax + dir0end + movl %edi,%eax // %edi als Ergebnis + movl %edx,%edi // %edi zurück + ret + +// extern uintD* fill_loop_down (uintD* destptr, uintC count, uintD filler); + ALIGN + DECLARE_FUNCTION(fill_loop_down) +C(fill_loop_down:) + movl %edi,%edx // %edi retten + movl 4(%esp),%edi // %edi = destptr + movl 8(%esp),%ecx // %ecx = count + movl 12(%esp),%eax // %eax = filler + leal -4(%edi),%edi + dir1start + rep + stosl // %ecx mal abwärts (%edi) := %eax + dir1end + leal 4(%edi),%eax // %edi als Ergebnis + movl %edx,%edi // %edi zurück + ret + +// extern uintD* clear_loop_up (uintD* destptr, uintC count); + ALIGN + DECLARE_FUNCTION(clear_loop_up) +C(clear_loop_up:) + movl %edi,%edx // %edi retten + movl 4(%esp),%edi // %edi = destptr + movl 8(%esp),%ecx // %ecx = count + xorl %eax,%eax // %eax = 0 + dir0start + rep + stosl // %ecx mal aufwärts (%edi) := %eax + dir0end + movl %edi,%eax // %edi als Ergebnis + movl %edx,%edi // %edi zurück + ret + +// extern uintD* clear_loop_down (uintD* destptr, uintC count); + ALIGN + DECLARE_FUNCTION(clear_loop_down) +C(clear_loop_down:) + movl %edi,%edx // %edi retten + movl 4(%esp),%edi // %edi = destptr + movl 8(%esp),%ecx // %ecx = count + leal -4(%edi),%edi + xorl %eax,%eax // %eax = 0 + dir1start + rep + stosl // %ecx mal abwärts (%edi) := %eax + dir1end + leal 4(%edi),%eax // %edi als Ergebnis + movl %edx,%edi // %edi zurück + ret + +// extern boolean test_loop_up (uintD* ptr, uintC count); + ALIGN + DECLARE_FUNCTION(test_loop_up) +C(test_loop_up:) + movl %edi,%edx // %edi retten + movl 4(%esp),%edi // %edi = ptr + movl 8(%esp),%ecx // %ecx = count + xorl %eax,%eax // %eax = 0 + dir0start + repz // Falls %ecx > 0: + scasl // %ecx mal aufwärts (%edi) testen + // und weiterschleifen, falls Z, d.h. (%edi)=0. + dir0end + // Noch ist %eax = 0. + jz L(tlu1) // alles =0 -> Ergebnis 0 + incl %eax // Ergebnis 1 +L(tlu1:) movl %edx,%edi // %edi zurück + ret + +// extern boolean test_loop_down (uintD* ptr, uintC count); + ALIGN + DECLARE_FUNCTION(test_loop_down) +C(test_loop_down:) + movl %edi,%edx // %edi retten + movl 4(%esp),%edi // %edi = ptr + movl 8(%esp),%ecx // %ecx = count + xorl %eax,%eax // %eax = 0 + leal -4(%edi),%edi + dir1start + repz // Falls %ecx > 0: + scasl // %ecx mal aufwärts (%edi) testen + // und weiterschleifen, falls Z, d.h. (%edi)=0. + dir1end + // Noch ist %eax = 0. + jz L(tld1) // alles =0 -> Ergebnis 0 + incl %eax // Ergebnis 1 +L(tld1:) movl %edx,%edi // %edi zurück + ret + +#if CL_DS_BIG_ENDIAN_P + +// extern void or_loop_up (uintD* xptr, uintD* yptr, uintC count); + ALIGN + DECLARE_FUNCTION(or_loop_up) +C(or_loop_up:) + pushl %esi // %esi retten + movl 8(%esp),%edx // %edx = xptr + movl 12(%esp),%esi // %esi = yptr + movl 16(%esp),%ecx // %ecx = count + subl %edx,%esi + jecxz L(olu2) // %ecx = 0 ? +L(olu1:) movl (%edx,%esi),%eax // *yptr + orl %eax,(%edx) // *xptr |= ... + leal 4(%edx),%edx // xptr++, yptr++ + decl %ecx + jnz L(olu1) +L(olu2:) popl %esi // %esi zurück + ret + +#endif + +// extern void xor_loop_up (uintD* xptr, uintD* yptr, uintC count); + ALIGN + DECLARE_FUNCTION(xor_loop_up) +C(xor_loop_up:) + pushl %esi // %esi retten + movl 8(%esp),%edx // %edx = xptr + movl 12(%esp),%esi // %esi = yptr + movl 16(%esp),%ecx // %ecx = count + subl %edx,%esi + jecxz L(xlu2) // %ecx = 0 ? +L(xlu1:) movl (%edx,%esi),%eax // *yptr + xorl %eax,(%edx) // *xptr ^= ... + leal 4(%edx),%edx // xptr++, yptr++ + decl %ecx + jnz L(xlu1) +L(xlu2:) popl %esi // %esi zurück + ret + +#if CL_DS_BIG_ENDIAN_P + +// extern void and_loop_up (uintD* xptr, uintD* yptr, uintC count); + ALIGN + DECLARE_FUNCTION(and_loop_up) +C(and_loop_up:) + pushl %esi // %esi retten + movl 8(%esp),%edx // %edx = xptr + movl 12(%esp),%esi // %esi = yptr + movl 16(%esp),%ecx // %ecx = count + subl %edx,%esi + jecxz L(alu2) // %ecx = 0 ? +L(alu1:) movl (%edx,%esi),%eax // *yptr + andl %eax,(%edx) // *xptr &= ... + leal 4(%edx),%edx // xptr++, yptr++ + decl %ecx + jnz L(alu1) +L(alu2:) popl %esi // %esi zurück + ret + +// extern void eqv_loop_up (uintD* xptr, uintD* yptr, uintC count); + ALIGN + DECLARE_FUNCTION(eqv_loop_up) +C(eqv_loop_up:) + pushl %esi // %esi retten + movl 8(%esp),%edx // %edx = xptr + movl 12(%esp),%esi // %esi = yptr + movl 16(%esp),%ecx // %ecx = count + subl %edx,%esi + jecxz L(elu2) // %ecx = 0 ? +L(elu1:) movl (%edx),%eax // *xptr + xorl (%edx,%esi),%eax // ^ *yptr + notl %eax // ~(...) + movl %eax,(%edx) // =: *xptr + leal 4(%edx),%edx // xptr++, yptr++ + decl %ecx + jnz L(elu1) +L(elu2:) popl %esi // %esi zurück + ret + +// extern void nand_loop_up (uintD* xptr, uintD* yptr, uintC count); + ALIGN + DECLARE_FUNCTION(nand_loop_up) +C(nand_loop_up:) + pushl %esi // %esi retten + movl 8(%esp),%edx // %edx = xptr + movl 12(%esp),%esi // %esi = yptr + movl 16(%esp),%ecx // %ecx = count + subl %edx,%esi + jecxz L(nalu2) // %ecx = 0 ? +L(nalu1:) movl (%edx),%eax // *xptr + andl (%edx,%esi),%eax // & *yptr + notl %eax // ~(...) + movl %eax,(%edx) // =: *xptr + leal 4(%edx),%edx // xptr++, yptr++ + decl %ecx + jnz L(nalu1) +L(nalu2:) popl %esi // %esi zurück + ret + +// extern void nor_loop_up (uintD* xptr, uintD* yptr, uintC count); + ALIGN + DECLARE_FUNCTION(nor_loop_up) +C(nor_loop_up:) + pushl %esi // %esi retten + movl 8(%esp),%edx // %edx = xptr + movl 12(%esp),%esi // %esi = yptr + movl 16(%esp),%ecx // %ecx = count + subl %edx,%esi + jecxz L(nolu2) // %ecx = 0 ? +L(nolu1:) movl (%edx),%eax // *xptr + orl (%edx,%esi),%eax // | *yptr + notl %eax // ~(...) + movl %eax,(%edx) // =: *xptr + leal 4(%edx),%edx // xptr++, yptr++ + decl %ecx + jnz L(nolu1) +L(nolu2:) popl %esi // %esi zurück + ret + +// extern void andc2_loop_up (uintD* xptr, uintD* yptr, uintC count); + ALIGN + DECLARE_FUNCTION(andc2_loop_up) +C(andc2_loop_up:) + pushl %esi // %esi retten + movl 8(%esp),%edx // %edx = xptr + movl 12(%esp),%esi // %esi = yptr + movl 16(%esp),%ecx // %ecx = count + subl %edx,%esi + jecxz L(aclu2) // %ecx = 0 ? +L(aclu1:) movl (%edx,%esi),%eax // *yptr + notl %eax // ~ *yptr + andl %eax,(%edx) // *xptr &= ... + leal 4(%edx),%edx // xptr++, yptr++ + decl %ecx + jnz L(aclu1) +L(aclu2:) popl %esi // %esi zurück + ret + +// extern void orc2_loop_up (uintD* xptr, uintD* yptr, uintC count); + ALIGN + DECLARE_FUNCTION(orc2_loop_up) +C(orc2_loop_up:) + pushl %esi // %esi retten + movl 8(%esp),%edx // %edx = xptr + movl 12(%esp),%esi // %esi = yptr + movl 16(%esp),%ecx // %ecx = count + subl %edx,%esi + jecxz L(oclu2) // %ecx = 0 ? +L(oclu1:) movl (%edx,%esi),%eax // *yptr + notl %eax // ~ *yptr + orl %eax,(%edx) // *xptr |= ... + leal 4(%edx),%edx // xptr++, yptr++ + decl %ecx + jnz L(oclu1) +L(oclu2:) popl %esi // %esi zurück + ret + +// extern void not_loop_up (uintD* xptr, uintC count); + ALIGN + DECLARE_FUNCTION(not_loop_up) +C(not_loop_up:) + movl 4(%esp),%edx // %edx = xptr + movl 8(%esp),%ecx // %ecx = count + jecxz L(nlu2) // %ecx = 0 ? + nop ; nop ; nop ; nop ; nop ; nop +L(nlu1:) notl (%edx) // ~= *xptr + leal 4(%edx),%edx // xptr++ + decl %ecx + jnz L(nlu1) +L(nlu2:) ret + +// extern boolean and_test_loop_up (uintD* xptr, uintD* yptr, uintC count); + ALIGN + DECLARE_FUNCTION(and_test_loop_up) +C(and_test_loop_up:) + pushl %esi // %esi retten + movl 8(%esp),%edx // %edx = xptr + movl 12(%esp),%esi // %esi = yptr + movl 16(%esp),%ecx // %ecx = count + jecxz L(atlu2) // %ecx = 0 ? + subl %edx,%esi +L(atlu1:) movl (%edx,%esi),%eax // *yptr + andl (%edx),%eax // *xptr & ... + jnz L(atlu3) + leal 4(%edx),%edx // xptr++, yptr++ + decl %ecx + jnz L(atlu1) +L(atlu2:) xorl %eax,%eax // Ergebnis 0 + popl %esi // %esi zurück + ret +L(atlu3:) movl $1,%eax // Ergebnis 1 (nicht irgendwas /=0 !) + popl %esi // %esi zurück + ret + +#endif + +// extern cl_signean compare_loop_up (uintD* xptr, uintD* yptr, uintC count); + ALIGN + DECLARE_FUNCTION(compare_loop_up) +C(compare_loop_up:) + movl %esi,%edx // %esi retten + movl %edi,%eax // %edi retten + movl 4(%esp),%esi // %esi = xptr + movl 8(%esp),%edi // %edi = yptr + movl 12(%esp),%ecx // %ecx = count + dir0start + repz // Falls %ecx > 0: + cmpsl // %ecx mal aufwärts (%edi) und (%esi) vergleichen + // und weiterschleifen, falls Z, d.h. (%edi)=(%esi). + dir0end + // Flags -> Ergebnis: + // Z,NC -> bis zum Schluß (%esi)-(%edi) = 0 -> x=y -> Ergebnis 0 + // NZ,C -> schließlich (%esi)-(%edi) < 0 -> x Ergebnis -1 + // NZ,NC -> schließlich (%esi)-(%edi) > 0 -> x>y -> Ergebnis +1 + movl %eax,%edi // %edi zurück + movl %edx,%esi // %esi zurück + jbe L(cmlu1) // "be" = Z oder C + movl $1,%eax // Ergebnis +1 + ret +L(cmlu1:) sbbl %eax,%eax // Ergebnis -1 (falls C) oder 0 (falls NC) + ret + +#if CL_DS_BIG_ENDIAN_P + +// extern uintD add_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count); + ALIGN + DECLARE_FUNCTION(add_loop_down) +C(add_loop_down:) + pushl %esi // %esi retten + pushl %edi // %edi retten + movl 12(%esp),%edx // %edx = sourceptr1 + movl 16(%esp),%esi // %esi = sourceptr2 + movl 20(%esp),%edi // %edi = destptr + movl 24(%esp),%ecx // %ecx = count + subl %edi,%edx + subl %edi,%esi + orl %ecx,%ecx // %ecx = 0 ?, Carry löschen + jz L(ald2) +L(ald1:) leal -4(%edi),%edi // sourceptr1--, sourceptr2--, destptr-- + movl (%edx,%edi),%eax // *sourceptr1 + adcl (%esi,%edi),%eax // + *sourceptr2 + carry + movl %eax,(%edi) // =: *destptr, neuen Carry behalten + decl %ecx + jnz L(ald1) +L(ald2:) sbbl %eax,%eax // Ergebnis := - Carry + popl %edi // %edi zurück + popl %esi // %esi zurück + ret + +// extern uintD addto_loop_down (uintD* sourceptr, uintD* destptr, uintC count); + ALIGN + DECLARE_FUNCTION(addto_loop_down) +C(addto_loop_down:) + pushl %edi // %edi retten + movl 8(%esp),%edx // %edx = sourceptr + movl 12(%esp),%edi // %edi = destptr + movl 16(%esp),%ecx // %ecx = count + subl %edi,%edx + orl %ecx,%ecx // %ecx = 0 ?, Carry löschen + jz L(atld2) +L(atld1:) leal -4(%edi),%edi // sourceptr--, destptr-- + movl (%edx,%edi),%eax // *sourceptr + adcl %eax,(%edi) // + *destptr + carry =: *destptr, neuer Carry + decl %ecx + jnz L(atld1) +L(atld2:) sbbl %eax,%eax // Ergebnis := - Carry + popl %edi // %edi zurück + ret + +// extern uintD inc_loop_down (uintD* ptr, uintC count); + ALIGN + DECLARE_FUNCTION(inc_loop_down) +C(inc_loop_down:) + movl 4(%esp),%edx // %edx = ptr + movl 8(%esp),%ecx // %ecx = count + jecxz L(ild2) // %ecx = 0 ? +L(ild1:) leal -4(%edx),%edx + addl $1,(%edx) // (*ptr)++ + jnc L(ild3) // kein Carry -> fertig + decl %ecx + jnz L(ild1) +L(ild2:) movl $1,%eax // Ergebnis := 1 + ret +L(ild3:) xorl %eax,%eax // Ergebnis := 0 + ret + +// extern uintD sub_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count); + ALIGN + DECLARE_FUNCTION(sub_loop_down) +C(sub_loop_down:) + pushl %esi // %esi retten + pushl %edi // %edi retten + movl 12(%esp),%edx // %edx = sourceptr1 + movl 16(%esp),%esi // %esi = sourceptr2 + movl 20(%esp),%edi // %edi = destptr + movl 24(%esp),%ecx // %ecx = count + subl %edi,%edx + subl %edi,%esi + orl %ecx,%ecx // %ecx = 0 ?, Carry löschen + jz L(sld2) +L(sld1:) leal -4(%edi),%edi // sourceptr1--, sourceptr2--, destptr-- + movl (%edx,%edi),%eax // *sourceptr1 + sbbl (%esi,%edi),%eax // - *sourceptr2 - carry + movl %eax,(%edi) // =: *destptr, neuen Carry behalten + decl %ecx + jnz L(sld1) +L(sld2:) sbbl %eax,%eax // Ergebnis := - Carry + popl %edi // %edi zurück + popl %esi // %esi zurück + ret + +// extern uintD subx_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry); + ALIGN + DECLARE_FUNCTION(subx_loop_down) +C(subx_loop_down:) + pushl %esi // %esi retten + pushl %edi // %edi retten + movl 12(%esp),%edx // %edx = sourceptr1 + movl 16(%esp),%esi // %esi = sourceptr2 + movl 20(%esp),%edi // %edi = destptr + movl 24(%esp),%ecx // %ecx = count + jecxz L(sxld2) // %ecx = 0 ? + subl %edi,%edx + subl %edi,%esi + movl 28(%esp),%eax // carry, 0 oder -1 + addl %eax,%eax // Bit 31 davon in den Carry + nop ; nop +L(sxld1:) leal -4(%edi),%edi // sourceptr1--, sourceptr2--, destptr-- + movl (%edx,%edi),%eax // *sourceptr1 + sbbl (%esi,%edi),%eax // - *sourceptr2 - carry + movl %eax,(%edi) // =: *destptr, neuen Carry behalten + decl %ecx + jnz L(sxld1) + sbbl %eax,%eax // Ergebnis := - Carry + popl %edi // %edi zurück + popl %esi // %esi zurück + ret +L(sxld2:) movl 28(%esp),%eax // Ergebnis := carry + popl %edi // %edi zurück + popl %esi // %esi zurück + ret + +// extern uintD subfrom_loop_down (uintD* sourceptr, uintD* destptr, uintC count); + ALIGN + DECLARE_FUNCTION(subfrom_loop_down) +C(subfrom_loop_down:) + pushl %edi // %edi retten + movl 8(%esp),%edx // %edx = sourceptr + movl 12(%esp),%edi // %edi = destptr + movl 16(%esp),%ecx // %ecx = count + subl %edi,%edx + orl %ecx,%ecx // %ecx = 0 ?, Carry löschen + jz L(sfld2) +L(sfld1:) leal -4(%edi),%edi // sourceptr--, destptr-- + movl (%edx,%edi),%eax // *sourceptr + sbbl %eax,(%edi) // *destptr - *sourceptr - carry =: *destptr, neuer Carry + decl %ecx + jnz L(sfld1) +L(sfld2:) sbbl %eax,%eax // Ergebnis := - Carry + popl %edi // %edi zurück + ret + +// extern uintD dec_loop_down (uintD* ptr, uintC count); + ALIGN + DECLARE_FUNCTION(dec_loop_down) +C(dec_loop_down:) + movl 4(%esp),%edx // %edx = ptr + movl 8(%esp),%ecx // %ecx = count + jecxz L(dld2) // %ecx = 0 ? +L(dld1:) leal -4(%edx),%edx + subl $1,(%edx) // (*ptr)-- + jnc L(dld3) // kein Carry -> fertig + decl %ecx + jnz L(dld1) +L(dld2:) movl $-1,%eax // Ergebnis := -1 + ret +L(dld3:) xorl %eax,%eax // Ergebnis := 0 + ret + +// extern uintD neg_loop_down (uintD* ptr, uintC count); + ALIGN + DECLARE_FUNCTION(neg_loop_down) +C(neg_loop_down:) + movl 4(%esp),%edx // %edx = ptr + movl 8(%esp),%ecx // %ecx = count + // erstes Digit /=0 suchen: + jecxz L(nld2) // %ecx = 0 ? +L(nld1:) leal -4(%edx),%edx + negl (%edx) + jnz L(nld3) + decl %ecx + jnz L(nld1) +L(nld2:) xorl %eax,%eax // Ergebnis := 0 + ret + nop ; nop ; nop ; nop ; nop ; nop +L(nld3:) // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys + // alle anderen Digits invertieren: + decl %ecx + jz L(nld5) +L(nld4:) leal -4(%edx),%edx + notl (%edx) + decl %ecx + jnz L(nld4) +L(nld5:) movl $-1,%eax // Ergebnis := -1 + ret + +// extern uintD shift1left_loop_down (uintD* ptr, uintC count); + ALIGN + DECLARE_FUNCTION(shift1left_loop_down) +C(shift1left_loop_down:) + movl 4(%esp),%edx // %edx = ptr + movl 8(%esp),%ecx // %ecx = count + orl %ecx,%ecx // %ecx = 0 ?, Carry löschen + jz L(s1lld2) + nop ; nop ; nop ; nop +L(s1lld1:) leal -4(%edx),%edx // ptr-- + rcll $1,(%edx) // *ptr und Carry um 1 Bit links rotieren + decl %ecx + jnz L(s1lld1) +L(s1lld2:) sbbl %eax,%eax // Ergebnis := - Carry + ret + +// extern uintD shiftleft_loop_down (uintD* ptr, uintC count, uintC i, uintD carry); + ALIGN + DECLARE_FUNCTION(shiftleft_loop_down) +C(shiftleft_loop_down:) + pushl %edi // %edi retten + pushl %ebx // %ebx retten + movl 12(%esp),%edi // %edi = ptr + movl 16(%esp),%edx // %edx = count + movb 20(%esp),%cl // %cl = i + orl %edx,%edx // count = 0 ? + jz L(slld4) + // erstes Digit shiften: + leal -4(%edi),%edi + movl (%edi),%eax // Digit in %eax halten + movl %eax,%ebx // und in %ebx rechnen: + shll %cl,%ebx // um i Bits links shiften + orl 24(%esp),%ebx // und die unteren i Bits eintragen + movl %ebx,(%edi) // und wieder ablegen + // Letztes Digit in %eax. + decl %edx + jz L(slld2) + nop ; nop ; nop ; nop +L(slld1:) // weiteres Digit shiften: + leal -4(%edi),%edi + movl (%edi),%ebx + shldl shcl %eax,(%edi) // (%edi) um %cl=i Bits links shiften, %eax von rechts reinshiften + // Letztes Digit in %ebx. + decl %edx + jz L(slld3) + // weiteres Digit shiften: + leal -4(%edi),%edi + movl (%edi),%eax + shldl shcl %ebx,(%edi) // (%edi) um %cl=i Bits links shiften, %ebx von rechts reinshiften + // Letztes Digit in %eax. + decl %edx + jnz L(slld1) +L(slld2:) movl %eax,%ebx +L(slld3:) xorl %eax,%eax // %eax := 0 + shldl shcl %ebx,%eax // %eax := höchste %cl=i Bits von %ebx + popl %ebx // %ebx zurück + popl %edi // %edi zurück + ret +L(slld4:) movl 24(%esp),%eax // %eax := carry + popl %ebx // %ebx zurück + popl %edi // %edi zurück + ret + +// extern uintD shiftleftcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i); + ALIGN + DECLARE_FUNCTION(shiftleftcopy_loop_down) +C(shiftleftcopy_loop_down:) + pushl %esi // %esi retten + pushl %edi // %edi retten + pushl %ebx // %ebx retten + movl 16(%esp),%esi // %esi = sourceptr + movl 20(%esp),%edi // %edi = destptr + movl 24(%esp),%edx // count + movb 28(%esp),%cl // i + orl %edx,%edx // count = 0 ? + jz L(slcld4) + subl %edi,%esi + // erstes Digit shiften: + leal -4(%edi),%edi // sourceptr--, destptr-- + movl (%edi,%esi),%ebx // *sourceptr in %ebx halten + movl %ebx,%eax // und in %eax rechnen: + shll %cl,%eax // um i Bits links shiften, rechts Nullen rein + movl %eax,(%edi) // und als *destptr ablegen + // Letztes Digit in %ebx. + negb %cl // 32-i + decl %edx + jz L(slcld2) +L(slcld1:) // weiteres Digit shiften: + leal -4(%edi),%edi // sourceptr--, destptr-- + movl (%edi,%esi),%eax // nächstes Digit nach %eax + shrdl shcl %eax,%ebx // %ebx um %cl=32-i Bits rechts shiften, %eax von links reinshiften + movl %ebx,(%edi) // %ebx als *destptr ablegen + // Letztes Digit in %eax. + decl %edx + jz L(slcld3) + // weiteres Digit shiften: + leal -4(%edi),%edi // sourceptr--, destptr-- + movl (%edi,%esi),%ebx // nächstes Digit nach %ebx + shrdl shcl %ebx,%eax // %eax um %cl=32-i Bits rechts shiften, %ebx von links reinshiften + movl %eax,(%edi) // %eax als *destptr ablegen + // Letztes Digit in %ebx. + decl %edx + jnz L(slcld1) +L(slcld2:) movl %ebx,%eax +L(slcld3:) shrl %cl,%eax // %eax um 32-i Bits nach rechts shiften + popl %ebx // %ebx zurück + popl %edi // %edi zurück + popl %esi // %esi zurück + ret +L(slcld4:) xorl %eax,%eax // %eax := 0 + popl %ebx // %ebx zurück + popl %edi // %edi zurück + popl %esi // %esi zurück + ret + +// extern uintD shift1right_loop_up (uintD* ptr, uintC count, uintD carry); + ALIGN + DECLARE_FUNCTION(shift1right_loop_up) +C(shift1right_loop_up:) + movl 4(%esp),%edx // %edx = ptr + movl 8(%esp),%ecx // %ecx = count + movl 12(%esp),%eax // %eax = carry (0 oder -1) + jecxz L(s1rld3) // %ecx = 0 ? + addl %eax,%eax // Carry := Bit 31 von carry +L(s1rld1:) rcrl $1,(%edx) // *ptr und Carry um 1 Bit rechts rotieren + leal 4(%edx),%edx // ptr++ + decl %ecx + jnz L(s1rld1) +L(s1rld2:) sbbl %eax,%eax // Ergebnis := - Carry +L(s1rld3:) ret + +// extern uintD shiftright_loop_up (uintD* ptr, uintC count, uintC i); + ALIGN + DECLARE_FUNCTION(shiftright_loop_up) +C(shiftright_loop_up:) + pushl %edi // %edi retten + pushl %ebx // %ebx retten + movl 12(%esp),%edi // %edi = ptr + movl 16(%esp),%edx // %edx = count + movb 20(%esp),%cl // %cl = i + orl %edx,%edx // count = 0 ? + jz L(srlu4) + // erstes Digit shiften: + movl (%edi),%eax // Digit in %eax halten + movl %eax,%ebx // und in %ebx rechnen: + shrl %cl,%ebx // um i Bits rechts shiften + movl %ebx,(%edi) // und wieder ablegen + // Letztes Digit in %eax. + decl %edx + jz L(srlu2) + nop ; nop ; nop +L(srlu1:) // weiteres Digit shiften: + leal 4(%edi),%edi + movl (%edi),%ebx + shrdl shcl %eax,(%edi) // (%edi) um %cl=i Bits rechts shiften, %eax von links reinshiften + // Letztes Digit in %ebx. + decl %edx + jz L(srlu3) + // weiteres Digit shiften: + leal 4(%edi),%edi + movl (%edi),%eax + shrdl shcl %ebx,(%edi) // (%edi) um %cl=i Bits rechts shiften, %ebx von links reinshiften + // Letztes Digit in %eax. + decl %edx + jnz L(srlu1) +L(srlu2:) movl %eax,%ebx +L(srlu3:) xorl %eax,%eax // %eax := 0 + shrdl shcl %ebx,%eax // %eax := niedrigste %cl=i Bits von %ebx, als Bits 31..32-i + popl %ebx // %ebx zurück + popl %edi // %edi zurück + ret +L(srlu4:) xorl %eax,%eax // %eax := 0 + popl %ebx // %ebx zurück + popl %edi // %edi zurück + ret + +// extern uintD shiftrightsigned_loop_up (uintD* ptr, uintC count, uintC i); + ALIGN + DECLARE_FUNCTION(shiftrightsigned_loop_up) +C(shiftrightsigned_loop_up:) + pushl %edi // %edi retten + pushl %ebx // %ebx retten + movl 12(%esp),%edi // %edi = ptr + movl 16(%esp),%edx // %edx = count + movb 20(%esp),%cl // %cl = i + // erstes Digit shiften: + movl (%edi),%eax // Digit in %eax halten + movl %eax,%ebx // und in %ebx rechnen: + sarl %cl,%ebx // um i Bits rechts shiften, Vorzeichen vervielfachen + movl %ebx,(%edi) // und wieder ablegen + // Letztes Digit in %eax. + decl %edx + jz L(srslu2) +L(srslu1:) // weiteres Digit shiften: + leal 4(%edi),%edi + movl (%edi),%ebx + shrdl shcl %eax,(%edi) // (%edi) um %cl=i Bits rechts shiften, %eax von links reinshiften + // Letztes Digit in %ebx. + decl %edx + jz L(srslu3) + // weiteres Digit shiften: + leal 4(%edi),%edi + movl (%edi),%eax + shrdl shcl %ebx,(%edi) // (%edi) um %cl=i Bits rechts shiften, %ebx von links reinshiften + // Letztes Digit in %eax. + decl %edx + jnz L(srslu1) +L(srslu2:) movl %eax,%ebx +L(srslu3:) xorl %eax,%eax // %eax := 0 + shrdl shcl %ebx,%eax // %eax := niedrigste %cl=i Bits von %ebx, als Bits 31..32-i + popl %ebx // %ebx zurück + popl %edi // %edi zurück + ret + +// extern uintD shiftrightcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry); + ALIGN + DECLARE_FUNCTION(shiftrightcopy_loop_up) +C(shiftrightcopy_loop_up:) + pushl %esi // %esi retten + pushl %edi // %edi retten + pushl %ebx // %ebx retten + movl 16(%esp),%esi // %esi = sourceptr + movl 20(%esp),%edi // %edi = destptr + movl 24(%esp),%edx // count + movb 28(%esp),%cl // i + negb %cl // 32-i + movl 32(%esp),%eax // %eax = carry + orl %edx,%edx // count = 0 ? + jz L(srcld3) + subl %edi,%esi + // erstes Digit shiften: + movl (%edi,%esi),%ebx // *sourceptr in %ebx halten + shldl shcl %ebx,%eax // carry um %cl=32-i Bits links shiften, dabei *sourceptr rein + movl %eax,(%edi) // und als *destptr ablegen + // Letztes Digit in %ebx. + decl %edx + jz L(srcld2) +L(srcld1:) // weiteres Digit shiften: + leal 4(%edi),%edi // sourceptr++, destptr++ + movl (%edi,%esi),%eax // nächstes Digit nach %eax + shldl shcl %eax,%ebx // %ebx um %cl=32-i Bits links shiften, %eax von rechts reinshiften + movl %ebx,(%edi) // %ebx als *destptr ablegen + // Letztes Digit in %eax. + decl %edx + jz L(srcld3) + // weiteres Digit shiften: + leal 4(%edi),%edi // sourceptr++, destptr++ + movl (%edi,%esi),%ebx // nächstes Digit nach %ebx + shldl shcl %ebx,%eax // %eax um %cl=32-i Bits links shiften, %ebx von rechts reinshiften + movl %eax,(%edi) // %eax als *destptr ablegen + // Letztes Digit in %ebx. + decl %edx + jnz L(srcld1) +L(srcld2:) movl %ebx,%eax +L(srcld3:) shll %cl,%eax // %eax um 32-i Bits nach links shiften + popl %ebx // %ebx zurück + popl %edi // %edi zurück + popl %esi // %esi zurück + ret + +// extern uintD mulusmall_loop_down (uintD digit, uintD* ptr, uintC len, uintD newdigit); + ALIGN + DECLARE_FUNCTION(mulusmall_loop_down) +C(mulusmall_loop_down:) + pushl %ebp // %ebp retten + pushl %edi // %edi retten + pushl %ebx // %ebx retten + movl 16(%esp),%ebx // %ebx = digit + movl 20(%esp),%edi // %edi = ptr + movl 24(%esp),%ecx // %ecx = len + movl 28(%esp),%ebp // %ebp = carry := newdigit + movl %ecx,%eax + negl %eax // %eax = -len + jz L(msld2) + leal -4(%edi,%eax,4),%edi // %edi = &ptr[-1-len] + nop ; nop ; nop +L(msld1:) movl (%edi,%ecx,4),%eax // *ptr + mull %ebx // %edx|%eax := digit * *ptr + addl %ebp,%eax // carry und Low-Teil des Produktes addieren + movl $0,%ebp + adcl %edx,%ebp // Ãœbertrag zum High-Teil %edx dazu, gibt neuen carry + movl %eax,(%edi,%ecx,4) // Low-Teil als *ptr ablegen + decl %ecx // count--, ptr-- + jnz L(msld1) +L(msld2:) movl %ebp,%eax // Ergebnis := letzter Ãœbertrag + popl %ebx // %ebx zurück + popl %edi // %edi zurück + popl %ebp // %ebp zurück + ret + +// extern void mulu_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); + ALIGN + DECLARE_FUNCTION(mulu_loop_down) +C(mulu_loop_down:) + pushl %ebp // %ebp retten + pushl %edi // %edi retten + pushl %esi // %esi retten + pushl %ebx // %ebx retten + movl 20(%esp),%ebx // %ebx = digit + movl 24(%esp),%esi // %esi = sourceptr + movl 28(%esp),%edi // %edi = destptr + movl 32(%esp),%ecx // %ecx = len + movl %ecx,%eax + notl %eax // %eax = -1-len + leal (%esi,%eax,4),%esi // %esi = &sourceptr[-1-len] + leal (%edi,%eax,4),%edi // %edi = &destptr[-1-len] + xorl %ebp,%ebp // %epb = carry := 0 +L(muld1:) movl (%esi,%ecx,4),%eax // *sourceptr + mull %ebx // %edx|%eax := digit * *sourceptr + addl %ebp,%eax // carry und Low-Teil des Produktes addieren + movl $0,%ebp + adcl %edx,%ebp // Ãœbertrag zum High-Teil %edx dazu, gibt neuen carry + movl %eax,(%edi,%ecx,4) // Low-Teil als *destptr ablegen + decl %ecx // count--, sourceptr--, destptr-- + jnz L(muld1) + movl %ebp,(%edi) // letzten Ãœbertrag ablegen + popl %ebx // %ebx zurück + popl %esi // %esi zurück + popl %edi // %edi zurück + popl %ebp // %ebp zurück + ret + +// extern uintD muluadd_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); + ALIGN + DECLARE_FUNCTION(muluadd_loop_down) +C(muluadd_loop_down:) + pushl %ebp // %ebp retten + pushl %edi // %edi retten + pushl %esi // %esi retten + pushl %ebx // %ebx retten + movl 20(%esp),%ebx // %ebx = digit + movl 24(%esp),%esi // %esi = sourceptr + movl 28(%esp),%edi // %edi = destptr + movl 32(%esp),%ecx // %ecx = len + movl %ecx,%eax + notl %eax // %eax = -1-len + leal (%esi,%eax,4),%esi // %esi = &sourceptr[-1-len] + leal (%edi,%eax,4),%edi // %edi = &destptr[-1-len] + xorl %ebp,%ebp // %epb = carry := 0 +L(muald1:) movl (%esi,%ecx,4),%eax // *sourceptr + mull %ebx // %edx|%eax := digit * *sourceptr + addl %ebp,%eax // carry und Low-Teil des Produktes addieren + movl $0,%ebp + adcl %ebp,%edx // Ãœbertrag zum High-Teil %edx dazu + addl %eax,(%edi,%ecx,4) // Low-Teil zu *destptr addieren + adcl %edx,%ebp // zweiten Ãœbertrag zu %edx addieren, gibt neuen carry + decl %ecx // count--, sourceptr--, destptr-- + jnz L(muald1) + movl %ebp,%eax // Ergebnis := letzter Ãœbertrag + popl %ebx // %ebx zurück + popl %esi // %esi zurück + popl %edi // %edi zurück + popl %ebp // %ebp zurück + ret + +// extern uintD mulusub_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); + ALIGN + DECLARE_FUNCTION(mulusub_loop_down) +C(mulusub_loop_down:) + pushl %ebp // %ebp retten + pushl %edi // %edi retten + pushl %esi // %esi retten + pushl %ebx // %ebx retten + movl 20(%esp),%ebx // %ebx = digit + movl 24(%esp),%esi // %esi = sourceptr + movl 28(%esp),%edi // %edi = destptr + movl 32(%esp),%ecx // %ecx = len + movl %ecx,%eax + notl %eax // %eax = -1-len + leal (%esi,%eax,4),%esi // %esi = &sourceptr[-1-len] + leal (%edi,%eax,4),%edi // %edi = &destptr[-1-len] + xorl %ebp,%ebp // %epb = carry := 0 +L(musld1:) movl (%esi,%ecx,4),%eax // *sourceptr + mull %ebx // %edx|%eax := digit * *sourceptr + addl %ebp,%eax // carry und Low-Teil des Produktes addieren + movl $0,%ebp + adcl %ebp,%edx // Ãœbertrag zum High-Teil %edx dazu + subl %eax,(%edi,%ecx,4) // Low-Teil von *destptr subtrahieren + adcl %edx,%ebp // zweiten Ãœbertrag zu %edx addieren, gibt neuen carry + decl %ecx // count--, sourceptr--, destptr-- + jnz L(musld1) + movl %ebp,%eax // Ergebnis := letzter Ãœbertrag + popl %ebx // %ebx zurück + popl %esi // %esi zurück + popl %edi // %edi zurück + popl %ebp // %ebp zurück + ret + +// extern uintD divu_loop_up (uintD digit, uintD* ptr, uintC len); + ALIGN + DECLARE_FUNCTION(divu_loop_up) +C(divu_loop_up:) + pushl %edi // %edi retten + pushl %ebx // %ebx retten + movl 12(%esp),%ebx // %ebx = digit + movl 16(%esp),%edi // %edi = ptr + movl 20(%esp),%ecx // %ecx = len + xorl %edx,%edx // %edx = Rest := 0 + jecxz L(dlu2) // %ecx = 0 ? +L(dlu1:) movl (%edi),%eax // nächstes Digit *ptr + divl %ebx // Division von %edx|%eax durch %ebx + movl %eax,(%edi) // Quotient %eax ablegen, Rest in %edx behalten + leal 4(%edi),%edi // ptr++ + decl %ecx + jnz L(dlu1) +L(dlu2:) movl %edx,%eax // Ergebnis := letzter Rest + popl %ebx // %ebx zurück + popl %edi // %edi zurück + ret + +// extern uintD divucopy_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); + ALIGN + DECLARE_FUNCTION(divucopy_loop_up) +C(divucopy_loop_up:) + pushl %edi // %edi retten + pushl %esi // %esi retten + pushl %ebx // %ebx retten + movl 16(%esp),%ebx // %ebx = digit + movl 20(%esp),%esi // %esi = sourceptr + movl 24(%esp),%edi // %edi = destptr + movl 28(%esp),%ecx // %ecx = len + xorl %edx,%edx // %edx = Rest := 0 + jecxz L(dclu2) // %ecx = 0 ? + subl %edi,%esi +L(dclu1:) movl (%esi,%edi),%eax // nächstes Digit *ptr + divl %ebx // Division von %edx|%eax durch %ebx + movl %eax,(%edi) // Quotient %eax ablegen, Rest in %edx behalten + leal 4(%edi),%edi // sourceptr++, destptr++ + decl %ecx + jnz L(dclu1) +L(dclu2:) movl %edx,%eax // Ergebnis := letzter Rest + popl %ebx // %ebx zurück + popl %esi // %esi zurück + popl %edi // %edi zurück + ret + +#endif + +#if !CL_DS_BIG_ENDIAN_P + +// extern void or_loop_down (uintD* xptr, uintD* yptr, uintC count); + ALIGN + DECLARE_FUNCTION(or_loop_down) +C(or_loop_down:) + pushl %esi // %esi retten + movl 8(%esp),%edx // %edx = xptr + movl 12(%esp),%esi // %esi = yptr + movl 16(%esp),%ecx // %ecx = count + subl %edx,%esi + jecxz L(old2) // %ecx = 0 ? +L(old1:) leal -4(%edx),%edx // xptr--, yptr-- + movl (%edx,%esi),%eax // *yptr + orl %eax,(%edx) // *xptr |= ... + decl %ecx + jnz L(old1) +L(old2:) popl %esi // %esi zurück + ret + +// extern void xor_loop_down (uintD* xptr, uintD* yptr, uintC count); + ALIGN + DECLARE_FUNCTION(xor_loop_down) +C(xor_loop_down:) + pushl %esi // %esi retten + movl 8(%esp),%edx // %edx = xptr + movl 12(%esp),%esi // %esi = yptr + movl 16(%esp),%ecx // %ecx = count + subl %edx,%esi + jecxz L(xld2) // %ecx = 0 ? +L(xld1:) leal -4(%edx),%edx // xptr--, yptr-- + movl (%edx,%esi),%eax // *yptr + xorl %eax,(%edx) // *xptr ^= ... + decl %ecx + jnz L(xld1) +L(xld2:) popl %esi // %esi zurück + ret + +// extern void and_loop_down (uintD* xptr, uintD* yptr, uintC count); + ALIGN + DECLARE_FUNCTION(and_loop_down) +C(and_loop_down:) + pushl %esi // %esi retten + movl 8(%esp),%edx // %edx = xptr + movl 12(%esp),%esi // %esi = yptr + movl 16(%esp),%ecx // %ecx = count + subl %edx,%esi + jecxz L(ald2) // %ecx = 0 ? +L(ald1:) leal -4(%edx),%edx // xptr--, yptr-- + movl (%edx,%esi),%eax // *yptr + andl %eax,(%edx) // *xptr &= ... + decl %ecx + jnz L(ald1) +L(ald2:) popl %esi // %esi zurück + ret + +// extern void eqv_loop_down (uintD* xptr, uintD* yptr, uintC count); + ALIGN + DECLARE_FUNCTION(eqv_loop_down) +C(eqv_loop_down:) + pushl %esi // %esi retten + movl 8(%esp),%edx // %edx = xptr + movl 12(%esp),%esi // %esi = yptr + movl 16(%esp),%ecx // %ecx = count + subl %edx,%esi + jecxz L(eld2) // %ecx = 0 ? +L(eld1:) leal -4(%edx),%edx // xptr--, yptr-- + movl (%edx),%eax // *xptr + xorl (%edx,%esi),%eax // ^ *yptr + notl %eax // ~(...) + movl %eax,(%edx) // =: *xptr + decl %ecx + jnz L(eld1) +L(eld2:) popl %esi // %esi zurück + ret + +// extern void nand_loop_down (uintD* xptr, uintD* yptr, uintC count); + ALIGN + DECLARE_FUNCTION(nand_loop_down) +C(nand_loop_down:) + pushl %esi // %esi retten + movl 8(%esp),%edx // %edx = xptr + movl 12(%esp),%esi // %esi = yptr + movl 16(%esp),%ecx // %ecx = count + subl %edx,%esi + jecxz L(nald2) // %ecx = 0 ? +L(nald1:) leal -4(%edx),%edx // xptr--, yptr-- + movl (%edx),%eax // *xptr + andl (%edx,%esi),%eax // & *yptr + notl %eax // ~(...) + movl %eax,(%edx) // =: *xptr + decl %ecx + jnz L(nald1) +L(nald2:) popl %esi // %esi zurück + ret + +// extern void nor_loop_down (uintD* xptr, uintD* yptr, uintC count); + ALIGN + DECLARE_FUNCTION(nor_loop_down) +C(nor_loop_down:) + pushl %esi // %esi retten + movl 8(%esp),%edx // %edx = xptr + movl 12(%esp),%esi // %esi = yptr + movl 16(%esp),%ecx // %ecx = count + subl %edx,%esi + jecxz L(nold2) // %ecx = 0 ? +L(nold1:) leal -4(%edx),%edx // xptr--, yptr-- + movl (%edx),%eax // *xptr + orl (%edx,%esi),%eax // | *yptr + notl %eax // ~(...) + movl %eax,(%edx) // =: *xptr + decl %ecx + jnz L(nold1) +L(nold2:) popl %esi // %esi zurück + ret + +// extern void andc2_loop_down (uintD* xptr, uintD* yptr, uintC count); + ALIGN + DECLARE_FUNCTION(andc2_loop_down) +C(andc2_loop_down:) + pushl %esi // %esi retten + movl 8(%esp),%edx // %edx = xptr + movl 12(%esp),%esi // %esi = yptr + movl 16(%esp),%ecx // %ecx = count + subl %edx,%esi + jecxz L(acld2) // %ecx = 0 ? +L(acld1:) leal -4(%edx),%edx // xptr--, yptr-- + movl (%edx,%esi),%eax // *yptr + notl %eax // ~ *yptr + andl %eax,(%edx) // *xptr &= ... + decl %ecx + jnz L(acld1) +L(acld2:) popl %esi // %esi zurück + ret + +// extern void orc2_loop_down (uintD* xptr, uintD* yptr, uintC count); + ALIGN + DECLARE_FUNCTION(orc2_loop_down) +C(orc2_loop_down:) + pushl %esi // %esi retten + movl 8(%esp),%edx // %edx = xptr + movl 12(%esp),%esi // %esi = yptr + movl 16(%esp),%ecx // %ecx = count + subl %edx,%esi + jecxz L(ocld2) // %ecx = 0 ? +L(ocld1:) leal -4(%edx),%edx // xptr--, yptr-- + movl (%edx,%esi),%eax // *yptr + notl %eax // ~ *yptr + orl %eax,(%edx) // *xptr |= ... + decl %ecx + jnz L(ocld1) +L(ocld2:) popl %esi // %esi zurück + ret + +// extern void not_loop_down (uintD* xptr, uintC count); + ALIGN + DECLARE_FUNCTION(not_loop_down) +C(not_loop_down:) + movl 4(%esp),%edx // %edx = xptr + movl 8(%esp),%ecx // %ecx = count + jecxz L(nld2) // %ecx = 0 ? + nop ; nop ; nop ; nop ; nop ; nop +L(nld1:) leal -4(%edx),%edx // xptr-- + notl (%edx) // ~= *xptr + decl %ecx + jnz L(nld1) +L(nld2:) ret + +// extern boolean and_test_loop_down (uintD* xptr, uintD* yptr, uintC count); + ALIGN + DECLARE_FUNCTION(and_test_loop_down) +C(and_test_loop_down:) + pushl %esi // %esi retten + movl 8(%esp),%edx // %edx = xptr + movl 12(%esp),%esi // %esi = yptr + movl 16(%esp),%ecx // %ecx = count + jecxz L(atld2) // %ecx = 0 ? + subl %edx,%esi +L(atld1:) leal -4(%edx),%edx // xptr--, yptr-- + movl (%edx,%esi),%eax // *yptr + andl (%edx),%eax // *xptr & ... + jnz L(atld3) + decl %ecx + jnz L(atld1) +L(atld2:) xorl %eax,%eax // Ergebnis 0 + popl %esi // %esi zurück + ret +L(atld3:) movl $1,%eax // Ergebnis 1 (nicht irgendwas /=0 !) + popl %esi // %esi zurück + ret + +// extern cl_signean compare_loop_down (uintD* xptr, uintD* yptr, uintC count); + ALIGN + DECLARE_FUNCTION(compare_loop_down) +C(compare_loop_down:) + movl %esi,%edx // %esi retten + movl %edi,%eax // %edi retten + movl 4(%esp),%esi // %esi = xptr + movl 8(%esp),%edi // %edi = yptr + movl 12(%esp),%ecx // %ecx = count + leal -4(%esi),%esi + leal -4(%edi),%edi + dir1start + repz // Falls %ecx > 0: + cmpsl // %ecx mal aufwärts (%edi) und (%esi) vergleichen + // und weiterschleifen, falls Z, d.h. (%edi)=(%esi). + dir1end + // Flags -> Ergebnis: + // Z,NC -> bis zum Schluß (%esi)-(%edi) = 0 -> x=y -> Ergebnis 0 + // NZ,C -> schließlich (%esi)-(%edi) < 0 -> x Ergebnis -1 + // NZ,NC -> schließlich (%esi)-(%edi) > 0 -> x>y -> Ergebnis +1 + movl %eax,%edi // %edi zurück + movl %edx,%esi // %esi zurück + jbe L(cmld1) // "be" = Z oder C + movl $1,%eax // Ergebnis +1 + ret +L(cmld1:) sbbl %eax,%eax // Ergebnis -1 (falls C) oder 0 (falls NC) + ret + +// extern uintD add_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count); + ALIGN + DECLARE_FUNCTION(add_loop_up) +C(add_loop_up:) + pushl %esi // %esi retten + pushl %edi // %edi retten + movl 12(%esp),%edx // %edx = sourceptr1 + movl 16(%esp),%esi // %esi = sourceptr2 + movl 20(%esp),%edi // %edi = destptr + movl 24(%esp),%ecx // %ecx = count + subl %edi,%edx + subl %edi,%esi + orl %ecx,%ecx // %ecx = 0 ?, Carry löschen + jz L(alu2) +L(alu1:) movl (%edx,%edi),%eax // *sourceptr1 + adcl (%esi,%edi),%eax // + *sourceptr2 + carry + movl %eax,(%edi) // =: *destptr, neuen Carry behalten + leal 4(%edi),%edi // sourceptr1++, sourceptr2++, destptr++ + decl %ecx + jnz L(alu1) +L(alu2:) sbbl %eax,%eax // Ergebnis := - Carry + popl %edi // %edi zurück + popl %esi // %esi zurück + ret + +// extern uintD addto_loop_up (uintD* sourceptr, uintD* destptr, uintC count); + ALIGN + DECLARE_FUNCTION(addto_loop_up) +C(addto_loop_up:) + pushl %edi // %edi retten + movl 8(%esp),%edx // %edx = sourceptr + movl 12(%esp),%edi // %edi = destptr + movl 16(%esp),%ecx // %ecx = count + subl %edi,%edx + orl %ecx,%ecx // %ecx = 0 ?, Carry löschen + jz L(atlu2) +L(atlu1:) movl (%edx,%edi),%eax // *sourceptr + adcl %eax,(%edi) // + *destptr + carry =: *destptr, neuer Carry + leal 4(%edi),%edi // sourceptr++, destptr++ + decl %ecx + jnz L(atlu1) +L(atlu2:) sbbl %eax,%eax // Ergebnis := - Carry + popl %edi // %edi zurück + ret + +// extern uintD inc_loop_up (uintD* ptr, uintC count); + ALIGN + DECLARE_FUNCTION(inc_loop_up) +C(inc_loop_up:) + movl 4(%esp),%edx // %edx = ptr + movl 8(%esp),%ecx // %ecx = count + jecxz L(ilu2) // %ecx = 0 ? +L(ilu1:) addl $1,(%edx) // (*ptr)++ + jnc L(ilu3) // kein Carry -> fertig + leal 4(%edx),%edx + decl %ecx + jnz L(ilu1) +L(ilu2:) movl $1,%eax // Ergebnis := 1 + ret +L(ilu3:) xorl %eax,%eax // Ergebnis := 0 + ret + +// extern uintD sub_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count); + ALIGN + DECLARE_FUNCTION(sub_loop_up) +C(sub_loop_up:) + pushl %esi // %esi retten + pushl %edi // %edi retten + movl 12(%esp),%edx // %edx = sourceptr1 + movl 16(%esp),%esi // %esi = sourceptr2 + movl 20(%esp),%edi // %edi = destptr + movl 24(%esp),%ecx // %ecx = count + subl %edi,%edx + subl %edi,%esi + orl %ecx,%ecx // %ecx = 0 ?, Carry löschen + jz L(slu2) +L(slu1:) movl (%edx,%edi),%eax // *sourceptr1 + sbbl (%esi,%edi),%eax // - *sourceptr2 - carry + movl %eax,(%edi) // =: *destptr, neuen Carry behalten + leal 4(%edi),%edi // sourceptr1++, sourceptr2++, destptr++ + decl %ecx + jnz L(slu1) +L(slu2:) sbbl %eax,%eax // Ergebnis := - Carry + popl %edi // %edi zurück + popl %esi // %esi zurück + ret + +// extern uintD subx_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry); + ALIGN + DECLARE_FUNCTION(subx_loop_up) +C(subx_loop_up:) + pushl %esi // %esi retten + pushl %edi // %edi retten + movl 12(%esp),%edx // %edx = sourceptr1 + movl 16(%esp),%esi // %esi = sourceptr2 + movl 20(%esp),%edi // %edi = destptr + movl 24(%esp),%ecx // %ecx = count + jecxz L(sxlu2) // %ecx = 0 ? + subl %edi,%edx + subl %edi,%esi + movl 28(%esp),%eax // carry, 0 oder -1 + addl %eax,%eax // Bit 31 davon in den Carry + nop ; nop +L(sxlu1:) movl (%edx,%edi),%eax // *sourceptr1 + sbbl (%esi,%edi),%eax // - *sourceptr2 - carry + movl %eax,(%edi) // =: *destptr, neuen Carry behalten + leal 4(%edi),%edi // sourceptr1++, sourceptr2++, destptr++ + decl %ecx + jnz L(sxlu1) + sbbl %eax,%eax // Ergebnis := - Carry + popl %edi // %edi zurück + popl %esi // %esi zurück + ret +L(sxlu2:) movl 28(%esp),%eax // Ergebnis := carry + popl %edi // %edi zurück + popl %esi // %esi zurück + ret + +// extern uintD subfrom_loop_up (uintD* sourceptr, uintD* destptr, uintC count); + ALIGN + DECLARE_FUNCTION(subfrom_loop_up) +C(subfrom_loop_up:) + pushl %edi // %edi retten + movl 8(%esp),%edx // %edx = sourceptr + movl 12(%esp),%edi // %edi = destptr + movl 16(%esp),%ecx // %ecx = count + subl %edi,%edx + orl %ecx,%ecx // %ecx = 0 ?, Carry löschen + jz L(sflu2) +L(sflu1:) movl (%edx,%edi),%eax // *sourceptr + sbbl %eax,(%edi) // *destptr - *sourceptr - carry =: *destptr, neuer Carry + leal 4(%edi),%edi // sourceptr++, destptr++ + decl %ecx + jnz L(sflu1) +L(sflu2:) sbbl %eax,%eax // Ergebnis := - Carry + popl %edi // %edi zurück + ret + +// extern uintD dec_loop_up (uintD* ptr, uintC count); + ALIGN + DECLARE_FUNCTION(dec_loop_up) +C(dec_loop_up:) + movl 4(%esp),%edx // %edx = ptr + movl 8(%esp),%ecx // %ecx = count + jecxz L(dlu2) // %ecx = 0 ? +L(dlu1:) subl $1,(%edx) // (*ptr)-- + jnc L(dlu3) // kein Carry -> fertig + leal 4(%edx),%edx + decl %ecx + jnz L(dlu1) +L(dlu2:) movl $-1,%eax // Ergebnis := -1 + ret +L(dlu3:) xorl %eax,%eax // Ergebnis := 0 + ret + +// extern uintD neg_loop_up (uintD* ptr, uintC count); + ALIGN + DECLARE_FUNCTION(neg_loop_up) +C(neg_loop_up:) + movl 4(%esp),%edx // %edx = ptr + movl 8(%esp),%ecx // %ecx = count + // erstes Digit /=0 suchen: + jecxz L(nlu2) // %ecx = 0 ? +L(nlu1:) negl (%edx) + jnz L(nlu3) + leal 4(%edx),%edx + decl %ecx + jnz L(nlu1) +L(nlu2:) xorl %eax,%eax // Ergebnis := 0 + ret + nop ; nop ; nop ; nop ; nop ; nop +L(nlu3:) // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys + // alle anderen Digits invertieren: + decl %ecx + jz L(nlu5) +L(nlu4:) leal 4(%edx),%edx + notl (%edx) + decl %ecx + jnz L(nlu4) +L(nlu5:) movl $-1,%eax // Ergebnis := -1 + ret + +// extern uintD shift1left_loop_up (uintD* ptr, uintC count); + ALIGN + DECLARE_FUNCTION(shift1left_loop_up) +C(shift1left_loop_up:) + movl 4(%esp),%edx // %edx = ptr + movl 8(%esp),%ecx // %ecx = count + orl %ecx,%ecx // %ecx = 0 ?, Carry löschen + jz L(s1llu2) + nop ; nop ; nop ; nop +L(s1llu1:) rcll $1,(%edx) // *ptr und Carry um 1 Bit links rotieren + leal 4(%edx),%edx // ptr++ + decl %ecx + jnz L(s1llu1) +L(s1llu2:) sbbl %eax,%eax // Ergebnis := - Carry + ret + +// extern uintD shiftleft_loop_up (uintD* ptr, uintC count, uintC i, uintD carry); + ALIGN + DECLARE_FUNCTION(shiftleft_loop_up) +C(shiftleft_loop_up:) + pushl %edi // %edi retten + pushl %ebx // %ebx retten + movl 12(%esp),%edi // %edi = ptr + movl 16(%esp),%edx // %edx = count + movb 20(%esp),%cl // %cl = i + orl %edx,%edx // count = 0 ? + jz L(sllu4) + // erstes Digit shiften: + movl (%edi),%eax // Digit in %eax halten + movl %eax,%ebx // und in %ebx rechnen: + shll %cl,%ebx // um i Bits links shiften + orl 24(%esp),%ebx // und die unteren i Bits eintragen + movl %ebx,(%edi) // und wieder ablegen + leal 4(%edi),%edi + // Letztes Digit in %eax. + decl %edx + jz L(sllu2) + nop ; nop ; nop ; nop +L(sllu1:) // weiteres Digit shiften: + movl (%edi),%ebx + shldl shcl %eax,(%edi) // (%edi) um %cl=i Bits links shiften, %eax von rechts reinshiften + leal 4(%edi),%edi + // Letztes Digit in %ebx. + decl %edx + jz L(sllu3) + // weiteres Digit shiften: + movl (%edi),%eax + shldl shcl %ebx,(%edi) // (%edi) um %cl=i Bits links shiften, %ebx von rechts reinshiften + leal 4(%edi),%edi + // Letztes Digit in %eax. + decl %edx + jnz L(sllu1) +L(sllu2:) movl %eax,%ebx +L(sllu3:) xorl %eax,%eax // %eax := 0 + shldl shcl %ebx,%eax // %eax := höchste %cl=i Bits von %ebx + popl %ebx // %ebx zurück + popl %edi // %edi zurück + ret +L(sllu4:) movl 24(%esp),%eax // %eax := carry + popl %ebx // %ebx zurück + popl %edi // %edi zurück + ret + +#endif + +// extern uintD shiftleftcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i); + ALIGN + DECLARE_FUNCTION(shiftleftcopy_loop_up) +C(shiftleftcopy_loop_up:) + pushl %esi // %esi retten + pushl %edi // %edi retten + pushl %ebx // %ebx retten + movl 16(%esp),%esi // %esi = sourceptr + movl 20(%esp),%edi // %edi = destptr + movl 24(%esp),%edx // count + movb 28(%esp),%cl // i + orl %edx,%edx // count = 0 ? + jz L(slclu4) + subl %edi,%esi + // erstes Digit shiften: + movl (%edi,%esi),%ebx // *sourceptr in %ebx halten + movl %ebx,%eax // und in %eax rechnen: + shll %cl,%eax // um i Bits links shiften, rechts Nullen rein + movl %eax,(%edi) // und als *destptr ablegen + leal 4(%edi),%edi // sourceptr++, destptr++ + // Letztes Digit in %ebx. + negb %cl // 32-i + decl %edx + jz L(slclu2) +L(slclu1:) // weiteres Digit shiften: + movl (%edi,%esi),%eax // nächstes Digit nach %eax + shrdl shcl %eax,%ebx // %ebx um %cl=32-i Bits rechts shiften, %eax von links reinshiften + movl %ebx,(%edi) // %ebx als *destptr ablegen + leal 4(%edi),%edi // sourceptr++, destptr++ + // Letztes Digit in %eax. + decl %edx + jz L(slclu3) + // weiteres Digit shiften: + movl (%edi,%esi),%ebx // nächstes Digit nach %ebx + shrdl shcl %ebx,%eax // %eax um %cl=32-i Bits rechts shiften, %ebx von links reinshiften + movl %eax,(%edi) // %eax als *destptr ablegen + leal 4(%edi),%edi // sourceptr++, destptr++ + // Letztes Digit in %ebx. + decl %edx + jnz L(slclu1) +L(slclu2:) movl %ebx,%eax +L(slclu3:) shrl %cl,%eax // %eax um 32-i Bits nach rechts shiften + popl %ebx // %ebx zurück + popl %edi // %edi zurück + popl %esi // %esi zurück + ret +L(slclu4:) xorl %eax,%eax // %eax := 0 + popl %ebx // %ebx zurück + popl %edi // %edi zurück + popl %esi // %esi zurück + ret + +#if !CL_DS_BIG_ENDIAN_P + +// extern uintD shift1right_loop_down (uintD* ptr, uintC count, uintD carry); + ALIGN + DECLARE_FUNCTION(shift1right_loop_down) +C(shift1right_loop_down:) + movl 4(%esp),%edx // %edx = ptr + movl 8(%esp),%ecx // %ecx = count + movl 12(%esp),%eax // %eax = carry (0 oder -1) + jecxz L(s1rlu3) // %ecx = 0 ? + addl %eax,%eax // Carry := Bit 31 von carry +L(s1rlu1:) leal -4(%edx),%edx // ptr-- + rcrl $1,(%edx) // *ptr und Carry um 1 Bit rechts rotieren + decl %ecx + jnz L(s1rlu1) +L(s1rlu2:) sbbl %eax,%eax // Ergebnis := - Carry +L(s1rlu3:) ret + +// extern uintD shiftright_loop_down (uintD* ptr, uintC count, uintC i); + ALIGN + DECLARE_FUNCTION(shiftright_loop_down) +C(shiftright_loop_down:) + pushl %edi // %edi retten + pushl %ebx // %ebx retten + movl 12(%esp),%edi // %edi = ptr + movl 16(%esp),%edx // %edx = count + movb 20(%esp),%cl // %cl = i + orl %edx,%edx // count = 0 ? + jz L(srld4) + // erstes Digit shiften: + leal -4(%edi),%edi + movl (%edi),%eax // Digit in %eax halten + movl %eax,%ebx // und in %ebx rechnen: + shrl %cl,%ebx // um i Bits rechts shiften + movl %ebx,(%edi) // und wieder ablegen + // Letztes Digit in %eax. + decl %edx + jz L(srld2) +L(srld1:) // weiteres Digit shiften: + leal -4(%edi),%edi + movl (%edi),%ebx + shrdl shcl %eax,(%edi) // (%edi) um %cl=i Bits rechts shiften, %eax von links reinshiften + // Letztes Digit in %ebx. + decl %edx + jz L(srld3) + // weiteres Digit shiften: + leal -4(%edi),%edi + movl (%edi),%eax + shrdl shcl %ebx,(%edi) // (%edi) um %cl=i Bits rechts shiften, %ebx von links reinshiften + // Letztes Digit in %eax. + decl %edx + jnz L(srld1) +L(srld2:) movl %eax,%ebx +L(srld3:) xorl %eax,%eax // %eax := 0 + shrdl shcl %ebx,%eax // %eax := niedrigste %cl=i Bits von %ebx, als Bits 31..32-i + popl %ebx // %ebx zurück + popl %edi // %edi zurück + ret +L(srld4:) xorl %eax,%eax // %eax := 0 + popl %ebx // %ebx zurück + popl %edi // %edi zurück + ret + +// extern uintD shiftrightsigned_loop_down (uintD* ptr, uintC count, uintC i); + ALIGN + DECLARE_FUNCTION(shiftrightsigned_loop_down) +C(shiftrightsigned_loop_down:) + pushl %edi // %edi retten + pushl %ebx // %ebx retten + movl 12(%esp),%edi // %edi = ptr + movl 16(%esp),%edx // %edx = count + movb 20(%esp),%cl // %cl = i + // erstes Digit shiften: + leal -4(%edi),%edi + movl (%edi),%eax // Digit in %eax halten + movl %eax,%ebx // und in %ebx rechnen: + sarl %cl,%ebx // um i Bits rechts shiften, Vorzeichen vervielfachen + movl %ebx,(%edi) // und wieder ablegen + // Letztes Digit in %eax. + decl %edx + jz L(srsld2) + nop ; nop ; nop ; nop +L(srsld1:) // weiteres Digit shiften: + leal -4(%edi),%edi + movl (%edi),%ebx + shrdl shcl %eax,(%edi) // (%edi) um %cl=i Bits rechts shiften, %eax von links reinshiften + // Letztes Digit in %ebx. + decl %edx + jz L(srsld3) + // weiteres Digit shiften: + leal -4(%edi),%edi + movl (%edi),%eax + shrdl shcl %ebx,(%edi) // (%edi) um %cl=i Bits rechts shiften, %ebx von links reinshiften + // Letztes Digit in %eax. + decl %edx + jnz L(srsld1) +L(srsld2:) movl %eax,%ebx +L(srsld3:) xorl %eax,%eax // %eax := 0 + shrdl shcl %ebx,%eax // %eax := niedrigste %cl=i Bits von %ebx, als Bits 31..32-i + popl %ebx // %ebx zurück + popl %edi // %edi zurück + ret + +// extern uintD shiftrightcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry); + ALIGN + DECLARE_FUNCTION(shiftrightcopy_loop_down) +C(shiftrightcopy_loop_down:) + pushl %esi // %esi retten + pushl %edi // %edi retten + pushl %ebx // %ebx retten + movl 16(%esp),%esi // %esi = sourceptr + movl 20(%esp),%edi // %edi = destptr + movl 24(%esp),%edx // count + movb 28(%esp),%cl // i + negb %cl // 32-i + movl 32(%esp),%eax // %eax = carry + orl %edx,%edx // count = 0 ? + jz L(srclu3) + subl %edi,%esi + // erstes Digit shiften: + leal -4(%edi),%edi // sourceptr--, destptr-- + movl (%edi,%esi),%ebx // *sourceptr in %ebx halten + shldl shcl %ebx,%eax // carry um %cl=32-i Bits links shiften, dabei *sourceptr rein + movl %eax,(%edi) // und als *destptr ablegen + // Letztes Digit in %ebx. + decl %edx + jz L(srclu2) + nop ; nop ; nop +L(srclu1:) // weiteres Digit shiften: + leal -4(%edi),%edi // sourceptr--, destptr-- + movl (%edi,%esi),%eax // nächstes Digit nach %eax + shldl shcl %eax,%ebx // %ebx um %cl=32-i Bits links shiften, %eax von rechts reinshiften + movl %ebx,(%edi) // %ebx als *destptr ablegen + // Letztes Digit in %eax. + decl %edx + jz L(srclu3) + // weiteres Digit shiften: + leal -4(%edi),%edi // sourceptr--, destptr-- + movl (%edi,%esi),%ebx // nächstes Digit nach %ebx + shldl shcl %ebx,%eax // %eax um %cl=32-i Bits links shiften, %ebx von rechts reinshiften + movl %eax,(%edi) // %eax als *destptr ablegen + // Letztes Digit in %ebx. + decl %edx + jnz L(srclu1) +L(srclu2:) movl %ebx,%eax +L(srclu3:) shll %cl,%eax // %eax um 32-i Bits nach links shiften + popl %ebx // %ebx zurück + popl %edi // %edi zurück + popl %esi // %esi zurück + ret + +// extern uintD mulusmall_loop_up (uintD digit, uintD* ptr, uintC len, uintD newdigit); + ALIGN + DECLARE_FUNCTION(mulusmall_loop_up) +C(mulusmall_loop_up:) + pushl %ebp // %ebp retten + pushl %edi // %edi retten + pushl %ebx // %ebx retten + movl 16(%esp),%ebx // %ebx = digit + movl 20(%esp),%edi // %edi = ptr + movl 24(%esp),%ecx // %ecx = len + movl 28(%esp),%ebp // %ebp = carry := newdigit + leal (%edi,%ecx,4),%edi // %edi = &ptr[len] + negl %ecx // %ecx = -count + jz L(mslu2) +L(mslu1:) movl (%edi,%ecx,4),%eax // *ptr + mull %ebx // %edx|%eax := digit * *ptr + addl %ebp,%eax // carry und Low-Teil des Produktes addieren + movl $0,%ebp + adcl %edx,%ebp // Ãœbertrag zum High-Teil %edx dazu, gibt neuen carry + movl %eax,(%edi,%ecx,4) // Low-Teil als *ptr ablegen + incl %ecx // count--, ptr++ + jnz L(mslu1) +L(mslu2:) movl %ebp,%eax // Ergebnis := letzter Ãœbertrag + popl %ebx // %ebx zurück + popl %edi // %edi zurück + popl %ebp // %ebp zurück + ret + +// extern void mulu_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); + ALIGN + DECLARE_FUNCTION(mulu_loop_up) +C(mulu_loop_up:) + pushl %ebp // %ebp retten + pushl %edi // %edi retten + pushl %esi // %esi retten + pushl %ebx // %ebx retten + movl 20(%esp),%ebx // %ebx = digit + movl 24(%esp),%esi // %esi = sourceptr + movl 28(%esp),%edi // %edi = destptr + movl 32(%esp),%ecx // %ecx = len + leal (%esi,%ecx,4),%esi // %esi = &sourceptr[len] + leal (%edi,%ecx,4),%edi // %edi = &destptr[len] + negl %ecx // %ecx = -count + xorl %ebp,%ebp // %epb = carry := 0 + nop ; nop +L(mulu1:) movl (%esi,%ecx,4),%eax // *sourceptr + mull %ebx // %edx|%eax := digit * *sourceptr + addl %ebp,%eax // carry und Low-Teil des Produktes addieren + movl $0,%ebp + adcl %edx,%ebp // Ãœbertrag zum High-Teil %edx dazu, gibt neuen carry + movl %eax,(%edi,%ecx,4) // Low-Teil als *destptr ablegen + incl %ecx // count--, sourceptr++, destptr++ + jnz L(mulu1) + movl %ebp,(%edi) // letzten Ãœbertrag ablegen + popl %ebx // %ebx zurück + popl %esi // %esi zurück + popl %edi // %edi zurück + popl %ebp // %ebp zurück + ret + +// extern uintD muluadd_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); + ALIGN + DECLARE_FUNCTION(muluadd_loop_up) +C(muluadd_loop_up:) + pushl %ebp // %ebp retten + pushl %edi // %edi retten + pushl %esi // %esi retten + pushl %ebx // %ebx retten + movl 20(%esp),%ebx // %ebx = digit + movl 24(%esp),%esi // %esi = sourceptr + movl 28(%esp),%edi // %edi = destptr + movl 32(%esp),%ecx // %ecx = len + leal (%esi,%ecx,4),%esi // %esi = &sourceptr[len] + leal (%edi,%ecx,4),%edi // %edi = &destptr[len] + negl %ecx // %ecx = -count + xorl %ebp,%ebp // %epb = carry := 0 + nop ; nop +L(mualu1:) movl (%esi,%ecx,4),%eax // *sourceptr + mull %ebx // %edx|%eax := digit * *sourceptr + addl %ebp,%eax // carry und Low-Teil des Produktes addieren + movl $0,%ebp + adcl %ebp,%edx // Ãœbertrag zum High-Teil %edx dazu + addl %eax,(%edi,%ecx,4) // Low-Teil zu *destptr addieren + adcl %edx,%ebp // zweiten Ãœbertrag zu %edx addieren, gibt neuen carry + incl %ecx // count--, sourceptr++, destptr++ + jnz L(mualu1) + movl %ebp,%eax // Ergebnis := letzter Ãœbertrag + popl %ebx // %ebx zurück + popl %esi // %esi zurück + popl %edi // %edi zurück + popl %ebp // %ebp zurück + ret + +// extern uintD mulusub_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); + ALIGN + DECLARE_FUNCTION(mulusub_loop_up) +C(mulusub_loop_up:) + pushl %ebp // %ebp retten + pushl %edi // %edi retten + pushl %esi // %esi retten + pushl %ebx // %ebx retten + movl 20(%esp),%ebx // %ebx = digit + movl 24(%esp),%esi // %esi = sourceptr + movl 28(%esp),%edi // %edi = destptr + movl 32(%esp),%ecx // %ecx = len + leal (%esi,%ecx,4),%esi // %esi = &sourceptr[len] + leal (%edi,%ecx,4),%edi // %edi = &destptr[len] + negl %ecx // %ecx = -count + xorl %ebp,%ebp // %epb = carry := 0 + nop ; nop +L(muslu1:) movl (%esi,%ecx,4),%eax // *sourceptr + mull %ebx // %edx|%eax := digit * *sourceptr + addl %ebp,%eax // carry und Low-Teil des Produktes addieren + movl $0,%ebp + adcl %ebp,%edx // Ãœbertrag zum High-Teil %edx dazu + subl %eax,(%edi,%ecx,4) // Low-Teil von *destptr subtrahieren + adcl %edx,%ebp // zweiten Ãœbertrag zu %edx addieren, gibt neuen carry + incl %ecx // count--, sourceptr++, destptr++ + jnz L(muslu1) + movl %ebp,%eax // Ergebnis := letzter Ãœbertrag + popl %ebx // %ebx zurück + popl %esi // %esi zurück + popl %edi // %edi zurück + popl %ebp // %ebp zurück + ret + +// extern uintD divu_loop_down (uintD digit, uintD* ptr, uintC len); + ALIGN + DECLARE_FUNCTION(divu_loop_down) +C(divu_loop_down:) + pushl %edi // %edi retten + pushl %ebx // %ebx retten + movl 12(%esp),%ebx // %ebx = digit + movl 16(%esp),%edi // %edi = ptr + movl 20(%esp),%ecx // %ecx = len + xorl %edx,%edx // %edx = Rest := 0 + jecxz L(dld2) // %ecx = 0 ? +L(dld1:) leal -4(%edi),%edi // ptr-- + movl (%edi),%eax // nächstes Digit *ptr + divl %ebx // Division von %edx|%eax durch %ebx + movl %eax,(%edi) // Quotient %eax ablegen, Rest in %edx behalten + decl %ecx + jnz L(dld1) +L(dld2:) movl %edx,%eax // Ergebnis := letzter Rest + popl %ebx // %ebx zurück + popl %edi // %edi zurück + ret + +// extern uintD divucopy_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); + ALIGN + DECLARE_FUNCTION(divucopy_loop_down) +C(divucopy_loop_down:) + pushl %edi // %edi retten + pushl %esi // %esi retten + pushl %ebx // %ebx retten + movl 16(%esp),%ebx // %ebx = digit + movl 20(%esp),%esi // %esi = sourceptr + movl 24(%esp),%edi // %edi = destptr + movl 28(%esp),%ecx // %ecx = len + xorl %edx,%edx // %edx = Rest := 0 + jecxz L(dcld2) // %ecx = 0 ? + subl %edi,%esi +L(dcld1:) leal -4(%edi),%edi // sourceptr--, destptr-- + movl (%esi,%edi),%eax // nächstes Digit *ptr + divl %ebx // Division von %edx|%eax durch %ebx + movl %eax,(%edi) // Quotient %eax ablegen, Rest in %edx behalten + decl %ecx + jnz L(dcld1) +L(dcld2:) movl %edx,%eax // Ergebnis := letzter Rest + popl %ebx // %ebx zurück + popl %esi // %esi zurück + popl %edi // %edi zurück + ret + +#endif + +// extern void shiftxor_loop_up (uintD* xptr, const uintD* yptr, uintC count, uintC i); + ALIGN + DECLARE_FUNCTION(shiftxor_loop_up) +C(shiftxor_loop_up:) + pushl %esi // %esi retten + pushl %edi // %edi retten + pushl %ebx // %ebx retten + movl 16(%esp),%esi // %esi = xptr + movl 20(%esp),%edi // %edi = yptr + movl 24(%esp),%edx // count + movb 28(%esp),%cl // i + orl %edx,%edx // count = 0 ? + jz L(shxlu4) + subl %esi,%edi + // erstes Digit shiften: + movl (%esi,%edi),%ebx // *yptr in %ebx halten + movl %ebx,%eax // und in %eax rechnen: + shll %cl,%eax // um i Bits links shiften, rechts Nullen rein + xorl %eax,(%esi) // und mit *xptr verknüpfen und ablegen + leal 4(%esi),%esi // sourceptr++, destptr++ + // Letztes Digit in %ebx. + negb %cl // 32-i + decl %edx + jz L(shxlu2) +L(shxlu1:) // weiteres Digit shiften: + movl (%esi,%edi),%eax // nächstes Digit nach %eax + shrdl shcl %eax,%ebx // %ebx um %cl=32-i Bits rechts shiften, %eax von links reinshiften + xorl %ebx,(%esi) // %ebx mit *xptr verknüpfen und ablegen + leal 4(%esi),%esi // xptr++, yptr++ + // Letztes Digit in %eax. + decl %edx + jz L(shxlu3) + // weiteres Digit shiften: + movl (%esi,%edi),%ebx // nächstes Digit nach %ebx + shrdl shcl %ebx,%eax // %eax um %cl=32-i Bits rechts shiften, %ebx von links reinshiften + xorl %eax,(%esi) // %eax mit *xptr verknüpfen und ablegen + leal 4(%esi),%esi // xptr++, yptr++ + // Letztes Digit in %ebx. + decl %edx + jnz L(shxlu1) +L(shxlu2:) movl %ebx,%eax +L(shxlu3:) shrl %cl,%eax // %eax um 32-i Bits nach rechts shiften + xorl %eax,(%esi) // und mit *xptr verknüpfen und ablegen +L(shxlu4:) popl %ebx // %ebx zurück + popl %edi // %edi zurück + popl %esi // %esi zurück + ret + diff --git a/src/base/digitseq/cl_asm_m68k.h b/src/base/digitseq/cl_asm_m68k.h new file mode 100644 index 0000000..39e9cb6 --- /dev/null +++ b/src/base/digitseq/cl_asm_m68k.h @@ -0,0 +1,11 @@ +// List the contents of cl_asm_m68k.cc. + +#define COPY_LOOPS +#define FILL_LOOPS +#define CLEAR_LOOPS +#define LOG_LOOPS +#define TEST_LOOPS +#define ADDSUB_LOOPS +#define SHIFT_LOOPS +#define MUL_LOOPS +#define DIV_LOOPS diff --git a/src/base/digitseq/cl_asm_m68k_.cc b/src/base/digitseq/cl_asm_m68k_.cc new file mode 100644 index 0000000..50a0a9b --- /dev/null +++ b/src/base/digitseq/cl_asm_m68k_.cc @@ -0,0 +1,1707 @@ +// Externe Routinen zu ARILEV1.D +// Prozessor: 680x0 mit x>=2 +// Assembler-Syntax: meist "$" streichen, auf A/UX "$" durch "%" ersetzen +// Compiler: CC oder GNU-C auf SUN3 oder AMIGA oder A/UX +// Parameter-Ãœbergabe: +// auf dem Stack: sp@(4), sp@(8), ... (.W-Größen belegen 4 Byte!), +// Rückgabewert in d0. +// Register a0-a1,d0-d1 frei verwendbar, +// Register a2-a4,d2-d7 müssen gerettet werden. +// Einstellungen: intCsize=16, intDsize=32. + + #ifdef ASM_UNDERSCORE + #if defined(__STDC__) || defined (__cplusplus) + #define C(entrypoint) _##entrypoint + #else + #define C(entrypoint) _/**/entrypoint + #endif + #else + #define C(entrypoint) entrypoint + #endif + + // Befehl, der das X- und das C-Bit löscht (und evtl. d1 modifiziert): + #if defined(sun) + // SUN-Assembler + #define clrx subw $d1,$d1 + #else + // GNU-Assembler + #if defined(__STDC__) || defined (__cplusplus) + // Some preprocessors keep the backslash in place, some don't. + // In any case, we will filter it out later. + #define clrx andb \#0x0e,$ccr + #else + #define clrx andb #0x0e,$ccr + #endif + #endif + + // When this file is compiled into a shared library, ELF linkers need to + // know which symbols are functions. + #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__ELF__) || defined(__svr4__) + #define DECLARE_FUNCTION(name) .type C(name),@function + #else + #define DECLARE_FUNCTION(name) + #endif + + .text + + .globl C(copy_loop_up),C(copy_loop_down),C(fill_loop_up),C(fill_loop_down) + .globl C(clear_loop_up),C(clear_loop_down) + .globl C(test_loop_up),C(test_loop_down) + .globl C(xor_loop_up),C(compare_loop_up),C(shiftleftcopy_loop_up),C(shiftxor_loop_up) +#if CL_DS_BIG_ENDIAN_P + .globl C(or_loop_up),C(and_loop_up),C(eqv_loop_up) + .globl C(nand_loop_up),C(nor_loop_up),C(andc2_loop_up),C(orc2_loop_up) + .globl C(not_loop_up) + .globl C(and_test_loop_up) + .globl C(add_loop_down),C(addto_loop_down),C(inc_loop_down) + .globl C(sub_loop_down),C(subx_loop_down),C(subfrom_loop_down),C(dec_loop_down) + .globl C(neg_loop_down) + .globl C(shift1left_loop_down),C(shiftleft_loop_down),C(shiftleftcopy_loop_down) + .globl C(shift1right_loop_up),C(shiftright_loop_up),C(shiftrightsigned_loop_up),C(shiftrightcopy_loop_up) + .globl C(mulusmall_loop_down),C(mulu_loop_down),C(muluadd_loop_down),C(mulusub_loop_down) + .globl C(divu_loop_up),C(divucopy_loop_up) +#else + .globl C(or_loop_down),C(xor_loop_down),C(and_loop_down),C(eqv_loop_down) + .globl C(nand_loop_down),C(nor_loop_down),C(andc2_loop_down),C(orc2_loop_down) + .globl C(not_loop_down) + .globl C(and_test_loop_down),C(compare_loop_down) + .globl C(add_loop_up),C(addto_loop_up),C(inc_loop_up) + .globl C(sub_loop_up),C(subx_loop_up),C(subfrom_loop_up),C(dec_loop_up) + .globl C(neg_loop_up) + .globl C(shift1left_loop_up),C(shiftleft_loop_up) + .globl C(shift1right_loop_down),C(shiftright_loop_down),C(shiftrightsigned_loop_down),C(shiftrightcopy_loop_down) + .globl C(mulusmall_loop_up),C(mulu_loop_up),C(muluadd_loop_up),C(mulusub_loop_up) + .globl C(divu_loop_down),C(divucopy_loop_down) +#endif + +#ifndef __GNUC__ /* mit GNU-C machen wir mulu32() als Macro, der inline multipliziert */ + .globl C(mulu32_) +| extern struct { uint32 lo; uint32 hi; } mulu32_ (uint32 arg1, uint32 arg2); +| 2^32*hi+lo := arg1*arg2. + DECLARE_FUNCTION(mulu32_) +C(mulu32_:) | Input in d0,d1, Output in d0,mulu32_high + movel $sp@(4),$d0 + movel $sp@(8),$d1 + mulul $d1,$d1:$d0 + movel $d1,(C(mulu32_high)) | Adressierung?? Deklaration?? + rts +#endif + +#ifndef __GNUC__ /* mit GNU-C machen wir divu_6432_3232() als Macro, der inline dividiert */ + .globl C(divu_6432_3232_) +| extern struct { uint32 q; uint32 r; } divu_6432_3232_ (uint32 xhi, uint32 xlo, uint32 y); +| x = 2^32*xhi+xlo = q*y+r schreiben. Sei bekannt, daß 0 <= x < 2^32*y . + DECLARE_FUNCTION(divu_6432_3232_) +C(divu_6432_3232_:) | Input in d1,d0,d2, Output in d0,divu_32_rest + movel $sp@(4),$d1 + movel $sp@(8),$d0 + divul $sp@(12),$d1:$d0 | x = d1|d0 durch y dividieren + movel $d1,(C(divu_32_rest)) | Rest ablegen | Adressierung?? Deklaration?? + rts +#endif + +| extern uintD* copy_loop_up (uintD* sourceptr, uintD* destptr, uintC count); + DECLARE_FUNCTION(copy_loop_up) +C(copy_loop_up:) | Input in a0,a1,d0.W, Output in d0 + movel $sp@(4),$a0 + movel $sp@(8),$a1 + movew $sp@(12+2),$d0 + bras 2f + 1: movel $a0@+,$a1@+ + 2: dbra $d0,1b + movel $a1,$d0 + rts + +| extern uintD* copy_loop_down (uintD* sourceptr, uintD* destptr, uintC count); + DECLARE_FUNCTION(copy_loop_down) +C(copy_loop_down:) | Input in a0,a1,d0.W, Output in d0 + movel $sp@(4),$a0 + movel $sp@(8),$a1 + movew $sp@(12+2),$d0 + bras 2f + 1: movel $a0@-,$a1@- + 2: dbra $d0,1b + movel $a1,$d0 + rts + +| extern uintD* fill_loop_up (uintD* destptr, uintC count, uintD filler); + DECLARE_FUNCTION(fill_loop_up) +C(fill_loop_up:) | Input in a0,d0.W,d1, Output in d0 + movel $sp@(4),$a0 + movew $sp@(8+2),$d0 + movel $sp@(12),$d1 + bras 2f + 1: movel $d1,$a0@+ + 2: dbra $d0,1b + movel $a0,$d0 + rts + +| extern uintD* fill_loop_down (uintD* destptr, uintC count, uintD filler); + DECLARE_FUNCTION(fill_loop_down) +C(fill_loop_down:) | Input in a0,d0.W,d1, Output in d0 + movel $sp@(4),$a0 + movew $sp@(8+2),$d0 + movel $sp@(12),$d1 + bras 2f + 1: movel $d1,$a0@- + 2: dbra $d0,1b + movel $a0,$d0 + rts + +| extern uintD* clear_loop_up (uintD* destptr, uintC count); + DECLARE_FUNCTION(clear_loop_up) +C(clear_loop_up:) | Input in a0,d0.W, Output in d0 + movel $sp@(4),$a0 + movew $sp@(8+2),$d0 + bras 2f + 1: clrl $a0@+ + 2: dbra $d0,1b + movel $a0,$d0 + rts + +| extern uintD* clear_loop_down (uintD* destptr, uintC count); + DECLARE_FUNCTION(clear_loop_down) +C(clear_loop_down:) | Input in a0,d0.W, Output in d0 + movel $sp@(4),$a0 + movew $sp@(8+2),$d0 + bras 2f + 1: clrl $a0@- + 2: dbra $d0,1b + movel $a0,$d0 + rts + +| extern boolean test_loop_up (uintD* ptr, uintC count); + DECLARE_FUNCTION(test_loop_up) +C(test_loop_up:) | Input in a0,d0.W, Output in d0.W=d0.L + movel $sp@(4),$a0 + movew $sp@(8+2),$d0 + bras 2f + 1: tstl $a0@+ + bnes 3f + 2: dbra $d0,1b + clrl $d0 + rts + 3: moveq #1,$d0 + rts + +| extern boolean test_loop_down (uintD* ptr, uintC count); + DECLARE_FUNCTION(test_loop_down) +C(test_loop_down:) | Input in a0,d0.W, Output in d0.W=d0.L + movel $sp@(4),$a0 + movew $sp@(8+2),$d0 + bras 2f + 1: tstl $a0@- + bnes 3f + 2: dbra $d0,1b + clrl $d0 + rts + 3: moveq #1,$d0 + rts + +#if CL_DS_BIG_ENDIAN_P + +| extern void or_loop_up (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(or_loop_up) +C(or_loop_up:) | Input in a0,a1,d0.W, verändert d1 + movel $sp@(4),$a0 + movel $sp@(8),$a1 + movew $sp@(12+2),$d0 + bras 2f + 1: movel $a1@+,$d1 + orl $d1,$a0@+ + 2: dbra $d0,1b + rts + +#endif + +| extern void xor_loop_up (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(xor_loop_up) +C(xor_loop_up:) | Input in a0,a1,d0.W, verändert d1 + movel $sp@(4),$a0 + movel $sp@(8),$a1 + movew $sp@(12+2),$d0 + bras 2f + 1: movel $a1@+,$d1 + eorl $d1,$a0@+ + 2: dbra $d0,1b + rts + +#if CL_DS_BIG_ENDIAN_P + +| extern void and_loop_up (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(and_loop_up) +C(and_loop_up:) | Input in a0,a1,d0.W, verändert d1 + movel $sp@(4),$a0 + movel $sp@(8),$a1 + movew $sp@(12+2),$d0 + bras 2f + 1: movel $a1@+,$d1 + andl $d1,$a0@+ + 2: dbra $d0,1b + rts + +| extern void eqv_loop_up (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(eqv_loop_up) +C(eqv_loop_up:) | Input in a0,a1,d0.W, verändert d1 + movel $sp@(4),$a0 + movel $sp@(8),$a1 + movew $sp@(12+2),$d0 + bras 2f + 1: movel $a1@+,$d1 + eorl $d1,$a0@ + notl $a0@+ + 2: dbra $d0,1b + rts + +| extern void nand_loop_up (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(nand_loop_up) +C(nand_loop_up:) | Input in a0,a1,d0.W, verändert d1 + movel $sp@(4),$a0 + movel $sp@(8),$a1 + movew $sp@(12+2),$d0 + bras 2f + 1: movel $a1@+,$d1 + andl $d1,$a0@ + notl $a0@+ + 2: dbra $d0,1b + rts + +| extern void nor_loop_up (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(nor_loop_up) +C(nor_loop_up:) | Input in a0,a1,d0.W, verändert d1 + movel $sp@(4),$a0 + movel $sp@(8),$a1 + movew $sp@(12+2),$d0 + bras 2f + 1: movel $a1@+,$d1 + orl $d1,$a0@ + notl $a0@+ + 2: dbra $d0,1b + rts + +| extern void andc2_loop_up (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(andc2_loop_up) +C(andc2_loop_up:) | Input in a0,a1,d0.W, verändert d1 + movel $sp@(4),$a0 + movel $sp@(8),$a1 + movew $sp@(12+2),$d0 + bras 2f + 1: movel $a1@+,$d1 + notl $d1 + andl $d1,$a0@+ + 2: dbra $d0,1b + rts + +| extern void orc2_loop_up (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(orc2_loop_up) +C(orc2_loop_up:) | Input in a0,a1,d0.W, verändert d1 + movel $sp@(4),$a0 + movel $sp@(8),$a1 + movew $sp@(12+2),$d0 + bras 2f + 1: movel $a1@+,$d1 + notl $d1 + orl $d1,$a0@+ + 2: dbra $d0,1b + rts + +| extern void not_loop_up (uintD* xptr, uintC count); + DECLARE_FUNCTION(not_loop_up) +C(not_loop_up:) | Input in a0,d0.W + movel $sp@(4),$a0 + movew $sp@(8+2),$d0 + bras 2f + 1: notl $a0@+ + 2: dbra $d0,1b + rts + +| extern boolean and_test_loop_up (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(and_test_loop_up) +C(and_test_loop_up:) | Input in a0,a1,d0.W, verändert d1, Output in d0.W=d0.L + movel $sp@(4),$a0 + movel $sp@(8),$a1 + movew $sp@(12+2),$d0 + bras 2f + 1: movel $a0@+,$d1 + andl $a1@+,$d1 + bnes 3f + 2: dbra $d0,1b + clrl $d0 + rts + 3: moveq #1,$d0 + rts + +#endif + +| extern cl_signean compare_loop_up (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(compare_loop_up) +C(compare_loop_up:) | Input in a0,a1,d0.W, Output in d0.W=d0.L + movel $sp@(4),$a0 + movel $sp@(8),$a1 + movew $sp@(12+2),$d0 + bras 2f + 1: cmpml $a1@+,$a0@+ + bnes 3f + 2: dbra $d0,1b + clrl $d0 + rts + 3: bcss 4f + moveq #1,$d0 + rts + 4: moveq #-1,$d0 + rts + +#if CL_DS_BIG_ENDIAN_P + +| extern uintD add_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count); + DECLARE_FUNCTION(add_loop_down) +C(add_loop_down:) | Input in a0,a1,a2,d0.W, verändert d1,d2, Output in d0 + moveml $a2/$d2,$sp@- + movel $sp@(8+4),$a0 + movel $sp@(8+8),$a1 + movel $sp@(8+12),$a2 + movew $sp@(8+16+2),$d0 + clrx | X-Bit löschen + bras 2f + 1: movel $a0@-,$d1 + movel $a1@-,$d2 + addxl $d2,$d1 + movel $d1,$a2@- + 2: dbra $d0,1b + subxl $d0,$d0 | -1 falls X gesetzt, 0 falls X gelöscht + moveml $sp@+,$a2/$d2 + rts + +| extern uintD addto_loop_down (uintD* sourceptr, uintD* destptr, uintC count); + DECLARE_FUNCTION(addto_loop_down) +C(addto_loop_down:) | Input in a0,a1,d0.W, Output in d0 + movel $sp@(4),$a0 + movel $sp@(8),$a1 + movew $sp@(12+2),$d0 + clrx | X-Bit löschen + bras 2f + 1: addxl $a0@-,$a1@- + 2: dbra $d0,1b + subxl $d0,$d0 | -1 falls X gesetzt, 0 falls X gelöscht + rts + +| extern uintD inc_loop_down (uintD* ptr, uintC count); + DECLARE_FUNCTION(inc_loop_down) +C(inc_loop_down:) | Input in a0,d0.W, Output in d0 + movel $sp@(4),$a0 + movew $sp@(8+2),$d0 + dbra $d0,1f | simuliere gesetzten Carry + moveq #-1,$d0 | d0.L=-1 für Ãœbertrag + rts + 1: addql #1,$a0@- + dbcc $d0,1b + subxl $d0,$d0 | kein Carry -> d0.L=0, sonst d0.L=-1 für Ãœbertrag + rts + +| extern uintD sub_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count); + DECLARE_FUNCTION(sub_loop_down) +C(sub_loop_down:) | Input in a0,a1,a2,d0.W, verändert d1,d2, Output in d0 + moveml $a2/$d2,$sp@- + movel $sp@(8+4),$a0 + movel $sp@(8+8),$a1 + movel $sp@(8+12),$a2 + movew $sp@(8+16+2),$d0 + clrx | X-Bit löschen + bras 2f + 1: movel $a0@-,$d1 + movel $a1@-,$d2 + subxl $d2,$d1 + movel $d1,$a2@- + 2: dbra $d0,1b + subxl $d0,$d0 | -1 falls X gesetzt, 0 falls X gelöscht + moveml $sp@+,$a2/$d2 + rts + +| extern uintD subx_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry); + DECLARE_FUNCTION(subx_loop_down) +C(subx_loop_down:) | Input in a0,a1,a2,d0.W,d1, verändert d2, Output in d0 + moveml $a2/$d2,$sp@- + movel $sp@(8+4),$a0 + movel $sp@(8+8),$a1 + movel $sp@(8+12),$a2 + movew $sp@(8+16+2),$d0 + movel $sp@(8+20),$d1 + roxrl #1,$d1 | X-Bit initialisieren + bras 2f + 1: movel $a0@-,$d1 + movel $a1@-,$d2 + subxl $d2,$d1 + movel $d1,$a2@- + 2: dbra $d0,1b + subxl $d0,$d0 | -1 falls X gesetzt, 0 falls X gelöscht + moveml $sp@+,$a2/$d2 + rts + +| extern uintD subfrom_loop_down (uintD* sourceptr, uintD* destptr, uintC count); + DECLARE_FUNCTION(subfrom_loop_down) +C(subfrom_loop_down:) | Input in a0,a1,d0.W, Output in d0 + movel $sp@(4),$a0 + movel $sp@(8),$a1 + movew $sp@(12+2),$d0 + clrx | X-Bit löschen + bras 2f + 1: subxl $a0@-,$a1@- + 2: dbra $d0,1b + subxl $d0,$d0 | -1 falls X gesetzt, 0 falls X gelöscht + rts + +| extern uintD dec_loop_down (uintD* ptr, uintC count); + DECLARE_FUNCTION(dec_loop_down) +C(dec_loop_down:) | Input in a0,d0.W, Output in d0 + movel $sp@(4),$a0 + movew $sp@(8+2),$d0 + dbra $d0,1f | simuliere gesetzten Carry + moveq #-1,$d0 | d0.L=-1 als Ãœbertrag + rts + 1: subql #1,$a0@- + dbcc $d0,1b | kein Carry -> Schleife abbrechen + subxl $d0,$d0 | kein Carry -> d0.L=0, sonst d0.L=-1 als Ãœbertrag + rts + +| extern uintD neg_loop_down (uintD* ptr, uintC count); + DECLARE_FUNCTION(neg_loop_down) +C(neg_loop_down:) | Input in a0,d0.W, Output in d0 + movel $sp@(4),$a0 + movew $sp@(8+2),$d0 + clrx | X-Bit löschen + bras 2f + 1: negxl $a0@- + 2: dbra $d0,1b + subxl $d0,$d0 | -1 falls X gesetzt, 0 falls X gelöscht + rts + +| extern uintD shift1left_loop_down (uintD* ptr, uintC count); + DECLARE_FUNCTION(shift1left_loop_down) +C(shift1left_loop_down:) | Input in a0,d0.W, Output in d0.L + movel $sp@(4),$a0 + movew $sp@(8+2),$d0 + clrx | X-Bit löschen + bras 2f + 1: roxlw $a0@- | Digit a0@- um 1 Bit links schieben, X-Bit als Buffer + roxlw $a0@- + 2: dbra $d0,1b + subxl $d0,$d0 | -1 falls X gesetzt, 0 falls X gelöscht + rts + +| extern uintD shiftleft_loop_down (uintD* ptr, uintC count, uintC i, uintD carry); + DECLARE_FUNCTION(shiftleft_loop_down) +C(shiftleft_loop_down:) | Input in a0,d0.W,d1.W,d2, Output in d0 +#if 1 + moveml $d2-$d5,$sp@- + movel $sp@(16+4),$a0 + movew $sp@(16+8+2),$d0 + movew $sp@(16+12+2),$d1 + movel $sp@(16+16),$d2 + moveq #32,$d5 + subw $d1,$d5 + | a0 = ptr, d0.W = count, d1.W = i, d5.W = 32-i, + | d2.L = Schiebe-Ãœbertrag (i Bits), d3.L = Schiebe-Akku + bras 2f + 1: movel $a0@-,$d3 | d3.L = neues Digit + movel $d3,$d4 + lsll $d1,$d4 | um i Bits nach links schieben + orl $d2,$d4 | mit vorigem Ãœbertrag kombinieren + movel $d4,$a0@ | 32 Bits ablegen + movel $d3,$d2 + lsrl $d5,$d2 | neuen Ãœbertrag bilden + 2: dbra $d0,1b | Schleife d0.W mal durchlaufen + movel $d2,$d0 + moveml $sp@+,$d2-$d5 + rts +#else + moveml $d2-$d5,$sp@- + movel $sp@(16+4),$a0 + movew $sp@(16+8+2),$d0 + movew $sp@(16+12+2),$d1 + movel $sp@(16+16),$d2 + moveq #1,$d5 + lsll $d1,$d5 + subql #1,$d5 + | a0 = ptr, d0.W = count, d1.W = i, d5.L = 2^i-1 + | d2.L = Schiebe-Ãœbertrag (i Bits), d3.L = Schiebe-Akku + bras 2f + 1: movel $a0@-,$d3 | d3.L = neues Digit + roll $d1,$d3 | um i Bits links rotieren + movel $d3,$d4 + andl $d5,$d3 | untere i Bits in d3 + eorl $d3,$d4 | obere 32-i Bits in d4 + orl $d2,$d4 | mit vorigem übertrag kombinieren + movel $d4,$a0@ | 32 Bits ablegen + movel $d3,$d2 | neuer Ãœbertrag + 2: dbra $d0,1b | Schleife d0.W mal durchlaufen + movel $d2,$d0 + moveml $sp@+,$d2-$d5 + rts +#endif + +| extern uintD shiftleftcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i); + DECLARE_FUNCTION(shiftleftcopy_loop_down) +C(shiftleftcopy_loop_down:) | Input in a0,a1,d0.W,d1.W, Output in d0 +#if 1 + moveml $d2-$d5,$sp@- + movel $sp@(16+4),$a0 + movel $sp@(16+8),$a1 + movew $sp@(16+12+2),$d0 + movew $sp@(16+16+2),$d1 + moveq #32,$d5 + subw $d1,$d5 + clrl $d2 + | a0 = sourceptr, a1 = destptr, d0.W = count, d1.W = i, d5.W = 32-i, + | d2.L = Schiebe-Ãœbertrag (i Bits), d3.L = Schiebe-Akku + bras 2f + 1: movel $a0@-,$d3 | d3.L = neues Digit + movel $d3,$d4 + lsll $d1,$d4 | um i Bits nach links schieben + orl $d2,$d4 | mit vorigem Ãœbertrag kombinieren + movel $d4,$a1@- | 32 Bits ablegen + movel $d3,$d2 + lsrl $d5,$d2 | neuen Ãœbertrag bilden + 2: dbra $d0,1b | Schleife d0.W mal durchlaufen + movel $d2,$d0 + moveml $sp@+,$d2-$d5 + rts +#else + moveml $d2-$d5,$sp@- + movel $sp@(16+4),$a0 + movel $sp@(16+8),$a1 + movew $sp@(16+12+2),$d0 + movew $sp@(16+16+2),$d1 + moveq #1,$d5 + lsll $d1,$d5 + subql #1,$d5 + | a0 = sourceptr, a1 = destptr, d0.W = count, d1.W = i, d5.L = 2^i-1 + | d2.L = Schiebe-Ãœbertrag (i Bits), d3.L = Schiebe-Akku + bras 2f + 1: movel $a0@-,$d3 | d3.L = neues Digit + roll $d1,$d3 | um i Bits links rotieren + movel $d3,$d4 + andl $d5,$d3 | untere i Bits in d3 + eorl $d3,$d4 | obere 32-i Bits in d4 + orl $d2,$d4 | mit vorigem übertrag kombinieren + movel $d4,$a1@- | 32 Bits ablegen + movel $d3,$d2 | neuer Ãœbertrag + 2: dbra $d0,1b | Schleife d0.W mal durchlaufen + movel $d2,$d0 + moveml $sp@+,$d2-$d5 + rts +#endif + +| extern uintD shift1right_loop_up (uintD* ptr, uintC count, uintD carry); + DECLARE_FUNCTION(shift1right_loop_up) +C(shift1right_loop_up:) | Input in a0,d0.W,d1, Output in d0 + movel $sp@(4),$a0 + movew $sp@(8+2),$d0 + movel $sp@(12),$d1 + roxrl #1,$d1 | X-Bit löschen oder setzen, je nach d1 + bras 2f + 1: roxrw $a0@+ | Digit a0@+ um 1 Bit rechts schieben, X-Bit als Buffer + roxrw $a0@+ + 2: dbra $d0,1b + subxl $d0,$d0 | -1 falls X gesetzt, 0 falls X gelöscht + rts + +| extern uintD shiftright_loop_up (uintD* ptr, uintC count, uintC i); + DECLARE_FUNCTION(shiftright_loop_up) +C(shiftright_loop_up:) | Input in a0,d0.W,d1.W, Output in d0 +#if 1 + moveml $d2-$d5,$sp@- + movel $sp@(16+4),$a0 + movew $sp@(16+8+2),$d0 + movew $sp@(16+12+2),$d1 + moveq #32,$d5 + subw $d1,$d5 + | a0 = ptr, d0.W = count, d1.W = i, d5.W = 32-i, + | d2.L = Schiebe-Ãœbertrag (i Bits), d3.L = Schiebe-Akku + clrl $d2 + bras 2f + 1: | a0 = Aufwärtszähler Adresse, d0.W = Herabzähler, d1.W = i, d5.W = 32-i, + | d2.L = Schiebe-Ãœbertrag (obere i Bits, restliche 32-i Bits sind 0) + | d3.L = Schiebe-Akku + movel $a0@,$d3 | neue Daten + movel $d3,$d4 + lsrl $d1,$d3 | um i Bits rechts schieben + orl $d2,$d3 | und mit vorigem Ãœbertrag kombinieren + movel $d3,$a0@+ | ablegen + lsll $d5,$d4 | um (32-i) Bits links geschoben + movel $d4,$d2 | liefert neuen Ãœbertrag + 2: dbra $d0,1b | Schleife d0.W mal durchlaufen + movel $d2,$d0 + moveml $sp@+,$d2-$d5 + rts +#else + moveml $d2-$d5,$sp@- + movel $sp@(16+4),$a0 + movew $sp@(16+8+2),$d0 + movew $sp@(16+12+2),$d1 + moveq #-1,$d5 + lsrl $d1,$d5 + | a0 = ptr, d0.W = count, d1.W = i, d5.L = 2^(32-i)-1, + | d2.L = Schiebe-Ãœbertrag (i Bits), d3.L = Schiebe-Akku + clrl $d2 + bras 2f + 1: | a0 = Aufwärtszähler Adresse, d0.W = Herabzähler, d1.W = i, d5.L = 2^(32-i)-1, + | d2.L = Schiebe-Ãœbertrag (obere i Bits, restliche 32-i Bits sind 0) + | d3.L = Schiebe-Akku + movel $a0@,$d3 | neue Daten + rorl $d1,$d3 | um i Bits rechts rotieren + movel $d3,$d4 + andl $d5,$d3 | untere 32-i Bits + eorl $d3,$d4 | obere i Bits + orl $d2,$d3 | und mit vorigem Ãœbertrag kombinieren + movel $d4,$d2 | neuer Ãœbertrag + movel $d3,$a0@+ | ablegen + 2: dbra $d0,1b | Schleife d0.W mal durchlaufen + movel $d2,$d0 + moveml $sp@+,$d2-$d5 + rts +#endif + +| extern uintD shiftrightsigned_loop_up (uintD* ptr, uintC count, uintC i); + DECLARE_FUNCTION(shiftrightsigned_loop_up) +C(shiftrightsigned_loop_up:) | Input in a0,d0.W,d1.W, Output in d0 +#if 1 + moveml $d2-$d5,$sp@- + movel $sp@(16+4),$a0 + movew $sp@(16+8+2),$d0 + movew $sp@(16+12+2),$d1 + moveq #32,$d5 + subw $d1,$d5 + | a0 = ptr, d0.W = count, d1.W = i, d5.W = 32-i, + | d2.L = Schiebe-Ãœbertrag (i Bits), d3.L = Schiebe-Akku + subqw #1,$d0 + movel $a0@,$d3 | erstes Digit + movel $d3,$d4 + asrl $d1,$d3 | um i Bits rechts schieben + bras 2f + 1: | a0 = Aufwärtszähler Adresse, d0.W = Herabzähler, d1.W = i, d5.W = 32-i, + | d2.L = Schiebe-Ãœbertrag (obere i Bits, restliche 32-i Bits sind 0) + | d3.L = Schiebe-Akku + movel $a0@,$d3 | neue Daten + movel $d3,$d4 + lsrl $d1,$d3 | um i Bits rechts schieben + orl $d2,$d3 | und mit vorigem Ãœbertrag kombinieren + 2: movel $d3,$a0@+ | ablegen + lsll $d5,$d4 | um (32-i) Bits links geschoben + movel $d4,$d2 | liefert neuen Ãœbertrag + dbra $d0,1b | Schleife d0.W mal durchlaufen + movel $d2,$d0 + moveml $sp@+,$d2-$d5 + rts +#else + moveml $d2-$d5,$sp@- + movel $sp@(16+4),$a0 + movew $sp@(16+8+2),$d0 + movew $sp@(16+12+2),$d1 + moveq #-1,$d5 + lsrl $d1,$d5 + | a0 = ptr, d0.W = count, d1.W = i, d5.L = 2^(32-i)-1, + | d2.L = Schiebe-Ãœbertrag (i Bits), d3.L = Schiebe-Akku + subqw #1,$d0 + movel $a0@,$d3 | erstes Digit + movel $d3,$d4 + rorl $d1,$d4 | um i Bits rechts rotieren + movel $d5,$d2 + notl $d2 + andl $d4,$d2 | obere 32-i Bits + asrl $d1,$d3 | erstes Digit um i Bits rechts shiften + bras 2f + 1: | a0 = Aufwärtszähler Adresse, d0.W = Herabzähler, d1.W = i, d5.L = 2^(32-i)-1, + | d2.L = Schiebe-Ãœbertrag (obere i Bits, restliche 32-i Bits sind 0) + | d3.L = Schiebe-Akku + movel $a0@,$d3 | neue Daten + rorl $d1,$d3 | um i Bits rechts rotieren + movel $d3,$d4 + andl $d5,$d3 | untere 32-i Bits + eorl $d3,$d4 | obere i Bits + orl $d2,$d3 | und mit vorigem Ãœbertrag kombinieren + movel $d4,$d2 | neuer Ãœbertrag + 2: movel $d3,$a0@+ | ablegen + dbra $d0,1b | Schleife d0.W mal durchlaufen + movel $d2,$d0 + moveml $sp@+,$d2-$d5 + rts +#endif + +| extern uintD shiftrightcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry); + DECLARE_FUNCTION(shiftrightcopy_loop_up) +C(shiftrightcopy_loop_up:) | Input in a0,a1,d0.W,d1.W,d2, Output in d0 +#if 1 + moveml $d2-$d5,$sp@- + movel $sp@(16+4),$a0 + movel $sp@(16+8),$a1 + movew $sp@(16+12+2),$d0 + movew $sp@(16+16+2),$d1 + movel $sp@(16+20),$d2 + moveq #32,$d5 + subw $d1,$d5 + | a0 = ptr, d0.W = count, d1.W = i, d5.W = 32-i + | d2.L = Schiebe-Ãœbertrag (i Bits), d3.L = Schiebe-Akku + bras 2f + 1: | a0,a1 = Aufwärtszähler Adresse, d0.W = Herabzähler, d1.W = i, d5.W = 32-i + | d2.L = Schiebe-Ãœbertrag (obere i Bits, restliche 32-i Bits sind 0) + | d3.L = Schiebe-Akku + movel $a0@+,$d3 | neue Daten + movel $d3,$d4 + lsrl $d1,$d3 | um i Bits rechts schieben + orl $d2,$d3 | und mit vorigem Ãœbertrag kombinieren + movel $d3,$a1@+ | ablegen + movel $d4,$d2 + 2: lsll $d5,$d2 | um (32-i) Bits links geschoben, gibt neuen Ãœbertrag + dbra $d0,1b | Schleife d0.W mal durchlaufen + movel $d2,$d0 + moveml $sp@+,$d2-$d5 + rts +#else + moveml $d2-$d5,$sp@- + movel $sp@(16+4),$a0 + movel $sp@(16+8),$a1 + movew $sp@(16+12+2),$d0 + movew $sp@(16+16+2),$d1 + movel $sp@(16+20),$d2 + moveq #-1,$d5 + lsrl $d1,$d5 + rorl $d1,$d2 + | a0 = ptr, d0.W = count, d1.W = i, d5.L = 2^(32-i)-1 + | d2.L = Schiebe-Ãœbertrag (i Bits), d3.L = Schiebe-Akku + bras 2f + 1: | a0,a1 = Aufwärtszähler Adresse, d0.W = Herabzähler, d1.W = i, d5.L = 2^(32-i)-1 + | d2.L = Schiebe-Ãœbertrag (obere i Bits, restliche 32-i Bits sind 0) + | d3.L = Schiebe-Akku + movel $a0@+,$d3 | neue Daten + rorl $d1,$d3 | um i Bits rechts rotieren + movel $d3,$d4 + andl $d5,$d3 | untere 32-i Bits + eorl $d3,$d4 | obere i Bits + orl $d2,$d3 | und mit vorigem Ãœbertrag kombinieren + movel $d4,$d2 | neuer Ãœbertrag + movel $d3,$a1@+ | ablegen + 2: dbra $d0,1b | Schleife d0.W mal durchlaufen + movel $d2,$d0 + moveml $sp@+,$d2-$d5 + rts +#endif + +| extern uintD mulusmall_loop_down (uintD digit, uintD* ptr, uintC len, uintD newdigit); + DECLARE_FUNCTION(mulusmall_loop_down) +C(mulusmall_loop_down:) | Input in d0,a0,d1.W,d2, Output in d0 + moveml $d2-$d4,$sp@- + movel $sp@(12+4),$d0 + movel $sp@(12+8),$a0 + movew $sp@(12+12+2),$d1 + movel $sp@(12+16),$d2 + addw #0,$d1 | X-Bit löschen + bras 2f + 1: movel $a0@-,$d3 | nächstes Digit + mulul $d0,$d4:$d3 | mit digit multiplizieren + addxl $d2,$d3 | und bisherigen Carry und X-Bit addieren + movel $d3,$a0@ | Low-Digit ablegen + movel $d4,$d2 | High-Digit gibt neuen Carry + 2: dbra $d1,1b + clrl $d0 + addxl $d2,$d0 | letzter Carry (incl. X-Bit) + moveml $sp@+,$d2-$d4 + rts + +| extern void mulu_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); + DECLARE_FUNCTION(mulu_loop_down) +C(mulu_loop_down:) | Input in d0,a0,a1,d1.W +#if 1 + moveml $d2-$d4,$sp@- + movel $sp@(12+4),$d0 + movel $sp@(12+8),$a0 + movel $sp@(12+12),$a1 + movew $sp@(12+16+2),$d1 + subl $d2,$d2 | carry := 0, X-Bit löschen + bras 2f + 1: movel $a0@-,$d3 | nächstes Digit + mulul $d0,$d4:$d3 | mit digit multiplizieren + addxl $d2,$d3 | und bisherigen Carry und X-Bit addieren + movel $d3,$a1@- | Low-Digit ablegen + movel $d4,$d2 | High-Digit gibt neuen Carry + 2: dbra $d1,1b + clrl $d3 + addxl $d3,$d2 | letztes X-Bit verarbeiten + movel $d2,$a1@- | letzten Carry ablegen + moveml $sp@+,$d2-$d4 + rts +#else + moveml $d2-$d5,$sp@- + movel $sp@(16+4),$d0 + movel $sp@(16+8),$a0 + movel $sp@(16+12),$a1 + movew $sp@(16+16+2),$d1 + clrl $d5 | 0 + clrl $d2 | carry + bras 2f + 1: movel $a0@-,$d3 | nächstes Digit + mulul $d0,$d4:$d3 | mit digit multiplizieren + addl $d2,$d3 | und bisherigen Carry addieren + addxl $d5,$d4 + movel $d3,$a1@- | Low-Digit ablegen + movel $d4,$d2 | High-Digit gibt neuen Carry + 2: dbra $d1,1b + movel $d2,$a1@- | letzten Carry ablegen + moveml $sp@+,$d2-$d5 + rts +#endif + +| extern uintD muluadd_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); + DECLARE_FUNCTION(muluadd_loop_down) +C(muluadd_loop_down:) | Input in d0,a0,a1,d1.W, Output in d0 + moveml $d2-$d5,$sp@- + movel $sp@(16+4),$d0 + movel $sp@(16+8),$a0 + movel $sp@(16+12),$a1 + movew $sp@(16+16+2),$d1 + clrl $d5 | 0 + subl $d2,$d2 | carry := 0, X-Bit löschen + bras 2f + 1: movel $a0@-,$d3 | nächstes Digit + mulul $d0,$d4:$d3 | mit digit multiplizieren + addxl $d2,$d3 | und bisherigen Carry und X-Bit addieren + addxl $d5,$d4 + addl $d3,$a1@- | Low-Digit zum dest-Digit addieren, X als Ãœbertrag + movel $d4,$d2 | High-Digit gibt neuen Carry + 2: dbra $d1,1b + addxl $d5,$d2 | letztes X-Bit addieren + movel $d2,$d0 | letzten Carry als Ergebnis + moveml $sp@+,$d2-$d5 + rts + +| extern uintD mulusub_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); + DECLARE_FUNCTION(mulusub_loop_down) +C(mulusub_loop_down:) | Input in d0,a0,a1,d1.W, Output in d0 + moveml $d2-$d5,$sp@- + movel $sp@(16+4),$d0 + movel $sp@(16+8),$a0 + movel $sp@(16+12),$a1 + movew $sp@(16+16+2),$d1 + clrl $d5 | 0 + subl $d2,$d2 | carry := 0, X-Bit löschen + bras 2f + 1: movel $a0@-,$d3 | nächstes Digit + mulul $d0,$d4:$d3 | mit digit multiplizieren + addxl $d2,$d3 | und bisherigen Carry und X-Bit addieren + addxl $d5,$d4 + subl $d3,$a1@- | Low-Digit vom dest-Digit subtrahieren, X als Ãœbertrag + movel $d4,$d2 | High-Digit gibt neuen Carry + 2: dbra $d1,1b + clrl $d0 + addxl $d2,$d0 | letzter Carry und letztes X-Bit + moveml $sp@+,$d2-$d5 + rts + +| extern uintD divu_loop_up (uintD digit, uintD* ptr, uintC len); + DECLARE_FUNCTION(divu_loop_up) +C(divu_loop_up:) | Input in d0,a0,d1.W, Output in d0 + moveml $d2-$d3,$sp@- + movel $sp@(8+4),$d0 + movel $sp@(8+8),$a0 + movew $sp@(8+12+2),$d1 + clrl $d2 | Rest := 0 + bras 2f + 1: movel $a0@,$d3 | nächst-niedriges Digit + divul $d0,$d2:$d3 | mit Rest kombinieren und durch digit dividieren + movel $d3,$a0@+ | Quotient ablegen, Rest in d2 + 2: dbra $d1,1b + movel $d2,$d0 | Rest + moveml $sp@+,$d2-$d3 + rts + +| extern uintD divucopy_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); + DECLARE_FUNCTION(divucopy_loop_up) +C(divucopy_loop_up:) | Input in d0,a0,a1,d1.W, Output in d0 + moveml $d2-$d3,$sp@- + movel $sp@(8+4),$d0 + movel $sp@(8+8),$a0 + movel $sp@(8+12),$a1 + movew $sp@(8+16+2),$d1 + clrl $d2 | Rest := 0 + bras 2f + 1: movel $a0@+,$d3 | nächst-niedriges Digit + divul $d0,$d2:$d3 | mit Rest kombinieren und durch digit dividieren + movel $d3,$a1@+ | Quotient ablegen, Rest in d2 + 2: dbra $d1,1b + movel $d2,$d0 | Rest + moveml $sp@+,$d2-$d3 + rts + +#endif + +#if !CL_DS_BIG_ENDIAN_P + +| extern void or_loop_down (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(or_loop_down) +C(or_loop_down:) | Input in a0,a1,d0.W, verändert d1 + movel $sp@(4),$a0 + movel $sp@(8),$a1 + movew $sp@(12+2),$d0 + bras 2f + 1: movel $a1@-,$d1 + orl $d1,$a0@- + 2: dbra $d0,1b + rts + +| extern void xor_loop_down (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(xor_loop_down) +C(xor_loop_down:) | Input in a0,a1,d0.W, verändert d1 + movel $sp@(4),$a0 + movel $sp@(8),$a1 + movew $sp@(12+2),$d0 + bras 2f + 1: movel $a1@-,$d1 + eorl $d1,$a0@- + 2: dbra $d0,1b + rts + +| extern void and_loop_down (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(and_loop_down) +C(and_loop_down:) | Input in a0,a1,d0.W, verändert d1 + movel $sp@(4),$a0 + movel $sp@(8),$a1 + movew $sp@(12+2),$d0 + bras 2f + 1: movel $a1@-,$d1 + andl $d1,$a0@- + 2: dbra $d0,1b + rts + +| extern void eqv_loop_down (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(eqv_loop_down) +C(eqv_loop_down:) | Input in a0,a1,d0.W, verändert d1 + movel $sp@(4),$a0 + movel $sp@(8),$a1 + movew $sp@(12+2),$d0 + bras 2f + 1: movel $a1@-,$d1 + eorl $d1,$a0@- + notl $a0@ + 2: dbra $d0,1b + rts + +| extern void nand_loop_down (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(nand_loop_down) +C(nand_loop_down:) | Input in a0,a1,d0.W, verändert d1 + movel $sp@(4),$a0 + movel $sp@(8),$a1 + movew $sp@(12+2),$d0 + bras 2f + 1: movel $a1@-,$d1 + andl $d1,$a0@- + notl $a0@ + 2: dbra $d0,1b + rts + +| extern void nor_loop_down (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(nor_loop_down) +C(nor_loop_down:) | Input in a0,a1,d0.W, verändert d1 + movel $sp@(4),$a0 + movel $sp@(8),$a1 + movew $sp@(12+2),$d0 + bras 2f + 1: movel $a1@-,$d1 + orl $d1,$a0@- + notl $a0@ + 2: dbra $d0,1b + rts + +| extern void andc2_loop_down (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(andc2_loop_down) +C(andc2_loop_down:) | Input in a0,a1,d0.W, verändert d1 + movel $sp@(4),$a0 + movel $sp@(8),$a1 + movew $sp@(12+2),$d0 + bras 2f + 1: movel $a1@-,$d1 + notl $d1 + andl $d1,$a0@- + 2: dbra $d0,1b + rts + +| extern void orc2_loop_down (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(orc2_loop_down) +C(orc2_loop_down:) | Input in a0,a1,d0.W, verändert d1 + movel $sp@(4),$a0 + movel $sp@(8),$a1 + movew $sp@(12+2),$d0 + bras 2f + 1: movel $a1@-,$d1 + notl $d1 + orl $d1,$a0@- + 2: dbra $d0,1b + rts + +| extern void not_loop_down (uintD* xptr, uintC count); + DECLARE_FUNCTION(not_loop_down) +C(not_loop_down:) | Input in a0,d0.W + movel $sp@(4),$a0 + movew $sp@(8+2),$d0 + bras 2f + 1: notl $a0@- + 2: dbra $d0,1b + rts + +| extern boolean and_test_loop_down (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(and_test_loop_down) +C(and_test_loop_down:) | Input in a0,a1,d0.W, verändert d1, Output in d0.W=d0.L + movel $sp@(4),$a0 + movel $sp@(8),$a1 + movew $sp@(12+2),$d0 + bras 2f + 1: movel $a0@-,$d1 + andl $a1@-,$d1 + bnes 3f + 2: dbra $d0,1b + clrl $d0 + rts + 3: moveq #1,$d0 + rts + +| extern cl_signean compare_loop_down (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(compare_loop_down) +C(compare_loop_down:) | Input in a0,a1,d0.W, verändert d1,d2, Output in d0.W=d0.L + movel $d2,$sp@- + movel $sp@(4+4),$a0 + movel $sp@(4+8),$a1 + movew $sp@(4+12+2),$d0 + bras 2f + 1: movel $a0@-,$d1 + movel $a1@-,$d2 + cmpl $d2,$d1 + bnes 3f + 2: dbra $d0,1b + clrl $d0 + movel $sp@+,$d2 + rts + 3: bcss 4f + moveq #1,$d0 + movel $sp@+,$d2 + rts + 4: moveq #-1,$d0 + movel $sp@+,$d2 + rts + +| extern uintD add_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count); + DECLARE_FUNCTION(add_loop_up) +C(add_loop_up:) | Input in a0,a1,a2,d0.W, verändert d1,d2, Output in d0 + moveml $a2/$d2,$sp@- + movel $sp@(8+4),$a0 + movel $sp@(8+8),$a1 + movel $sp@(8+12),$a2 + movew $sp@(8+16+2),$d0 + clrx | X-Bit löschen + bras 2f + 1: movel $a0@+,$d1 + movel $a1@+,$d2 + addxl $d2,$d1 + movel $d1,$a2@+ + 2: dbra $d0,1b + subxl $d0,$d0 | -1 falls X gesetzt, 0 falls X gelöscht + moveml $sp@+,$a2/$d2 + rts + +| extern uintD addto_loop_up (uintD* sourceptr, uintD* destptr, uintC count); + DECLARE_FUNCTION(addto_loop_up) +C(addto_loop_up:) | Input in a0,a1,d0.W, verändert d1,d2, Output in d0 + movel $d2,$sp@- + movel $sp@(4+4),$a0 + movel $sp@(4+8),$a1 + movew $sp@(4+12+2),$d0 + clrx | X-Bit löschen + bras 2f + 1: movel $a0@+,$d1 + movel $a1@,$d2 + addxl $d1,$d2 + movel $d2,$a1@+ + 2: dbra $d0,1b + subxl $d0,$d0 | -1 falls X gesetzt, 0 falls X gelöscht + movel $sp@+,$d2 + rts + +| extern uintD inc_loop_up (uintD* ptr, uintC count); + DECLARE_FUNCTION(inc_loop_up) +C(inc_loop_up:) | Input in a0,d0.W, Output in d0 + movel $sp@(4),$a0 + movew $sp@(8+2),$d0 + dbra $d0,1f | simuliere gesetzten Carry + moveq #-1,$d0 | d0.L=-1 für Ãœbertrag + rts + 1: addql #1,$a0@+ + dbcc $d0,1b + subxl $d0,$d0 | kein Carry -> d0.L=0, sonst d0.L=-1 für Ãœbertrag + rts + +| extern uintD sub_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count); + DECLARE_FUNCTION(sub_loop_up) +C(sub_loop_up:) | Input in a0,a1,a2,d0.W, verändert d1,d2, Output in d0 + moveml $a2/$d2,$sp@- + movel $sp@(8+4),$a0 + movel $sp@(8+8),$a1 + movel $sp@(8+12),$a2 + movew $sp@(8+16+2),$d0 + clrx | X-Bit löschen + bras 2f + 1: movel $a0@+,$d1 + movel $a1@+,$d2 + subxl $d2,$d1 + movel $d1,$a2@+ + 2: dbra $d0,1b + subxl $d0,$d0 | -1 falls X gesetzt, 0 falls X gelöscht + moveml $sp@+,$a2/$d2 + rts + +| extern uintD subx_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry); + DECLARE_FUNCTION(subx_loop_up) +C(subx_loop_up:) | Input in a0,a1,a2,d0.W,d1, verändert d2, Output in d0 + moveml $a2/$d2,$sp@- + movel $sp@(8+4),$a0 + movel $sp@(8+8),$a1 + movel $sp@(8+12),$a2 + movew $sp@(8+16+2),$d0 + movel $sp@(8+20),$d1 + roxrl #1,$d1 | X-Bit initialisieren + bras 2f + 1: movel $a0@+,$d1 + movel $a1@+,$d2 + subxl $d2,$d1 + movel $d1,$a2@+ + 2: dbra $d0,1b + subxl $d0,$d0 | -1 falls X gesetzt, 0 falls X gelöscht + moveml $sp@+,$a2/$d2 + rts + +| extern uintD subfrom_loop_up (uintD* sourceptr, uintD* destptr, uintC count); + DECLARE_FUNCTION(subfrom_loop_up) +C(subfrom_loop_up:) | Input in a0,a1,d0.W, Output in d0 + movel $sp@(4),$a0 + movel $sp@(8),$a1 + movew $sp@(12+2),$d0 + clrx | X-Bit löschen + bras 2f + 1: movel $a0@+,$d1 + movel $a1@,$d2 + subxl $d1,$d2 + movel $d2,$a1@+ + 2: dbra $d0,1b + subxl $d0,$d0 | -1 falls X gesetzt, 0 falls X gelöscht + rts + +| extern uintD dec_loop_up (uintD* ptr, uintC count); + DECLARE_FUNCTION(dec_loop_up) +C(dec_loop_up:) | Input in a0,d0.W, Output in d0 + movel $sp@(4),$a0 + movew $sp@(8+2),$d0 + dbra $d0,1f | simuliere gesetzten Carry + moveq #-1,$d0 | d0.L=-1 als Ãœbertrag + rts + 1: subql #1,$a0@+ + dbcc $d0,1b | kein Carry -> Schleife abbrechen + subxl $d0,$d0 | kein Carry -> d0.L=0, sonst d0.L=-1 als Ãœbertrag + rts + +| extern uintD neg_loop_up (uintD* ptr, uintC count); + DECLARE_FUNCTION(neg_loop_up) +C(neg_loop_up:) | Input in a0,d0.W, Output in d0 + movel $sp@(4),$a0 + movew $sp@(8+2),$d0 + clrx | X-Bit löschen + bras 2f + 1: negxl $a0@+ + 2: dbra $d0,1b + subxl $d0,$d0 | -1 falls X gesetzt, 0 falls X gelöscht + rts + +| extern uintD shift1left_loop_up (uintD* ptr, uintC count); + DECLARE_FUNCTION(shift1left_loop_up) +C(shift1left_loop_up:) | Input in a0,d0.W, verändert d1, Output in d0.L + movel $sp@(4),$a0 + movew $sp@(8+2),$d0 + clrx | X-Bit löschen + bras 2f + 1: movel $a0@,$d1 + roxll #1,$d1 + movel $d1,$a0@+ + 2: dbra $d0,1b + subxl $d0,$d0 | -1 falls X gesetzt, 0 falls X gelöscht + rts + +| extern uintD shiftleft_loop_up (uintD* ptr, uintC count, uintC i, uintD carry); + DECLARE_FUNCTION(shiftleft_loop_up) +C(shiftleft_loop_up:) | Input in a0,d0.W,d1.W,d2, Output in d0 +#if 1 + moveml $d2-$d5,$sp@- + movel $sp@(16+4),$a0 + movew $sp@(16+8+2),$d0 + movew $sp@(16+12+2),$d1 + movel $sp@(16+16),$d2 + moveq #32,$d5 + subw $d1,$d5 + | a0 = ptr, d0.W = count, d1.W = i, d5.W = 32-i, + | d2.L = Schiebe-Ãœbertrag (i Bits), d3.L = Schiebe-Akku + bras 2f + 1: movel $a0@,$d3 | d3.L = neues Digit + movel $d3,$d4 + lsll $d1,$d4 | um i Bits nach links schieben + orl $d2,$d4 | mit vorigem Ãœbertrag kombinieren + movel $d4,$a0@+ | 32 Bits ablegen + movel $d3,$d2 + lsrl $d5,$d2 | neuen Ãœbertrag bilden + 2: dbra $d0,1b | Schleife d0.W mal durchlaufen + movel $d2,$d0 + moveml $sp@+,$d2-$d5 + rts +#else + moveml $d2-$d5,$sp@- + movel $sp@(16+4),$a0 + movew $sp@(16+8+2),$d0 + movew $sp@(16+12+2),$d1 + movel $sp@(16+16),$d2 + moveq #1,$d5 + lsll $d1,$d5 + subql #1,$d5 + | a0 = ptr, d0.W = count, d1.W = i, d5.L = 2^i-1 + | d2.L = Schiebe-Ãœbertrag (i Bits), d3.L = Schiebe-Akku + bras 2f + 1: movel $a0@,$d3 | d3.L = neues Digit + roll $d1,$d3 | um i Bits links rotieren + movel $d3,$d4 + andl $d5,$d3 | untere i Bits in d3 + eorl $d3,$d4 | obere 32-i Bits in d4 + orl $d2,$d4 | mit vorigem übertrag kombinieren + movel $d4,$a0@+ | 32 Bits ablegen + movel $d3,$d2 | neuer Ãœbertrag + 2: dbra $d0,1b | Schleife d0.W mal durchlaufen + movel $d2,$d0 + moveml $sp@+,$d2-$d5 + rts +#endif + +#endif + +| extern uintD shiftleftcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i); + DECLARE_FUNCTION(shiftleftcopy_loop_up) +C(shiftleftcopy_loop_up:) | Input in a0,a1,d0.W,d1.W, Output in d0 +#if 1 + moveml $d2-$d5,$sp@- + movel $sp@(16+4),$a0 + movel $sp@(16+8),$a1 + movew $sp@(16+12+2),$d0 + movew $sp@(16+16+2),$d1 + moveq #32,$d5 + subw $d1,$d5 + clrl $d2 + | a0 = sourceptr, a1 = destptr, d0.W = count, d1.W = i, d5.W = 32-i, + | d2.L = Schiebe-Ãœbertrag (i Bits), d3.L = Schiebe-Akku + bras 2f + 1: movel $a0@+,$d3 | d3.L = neues Digit + movel $d3,$d4 + lsll $d1,$d4 | um i Bits nach links schieben + orl $d2,$d4 | mit vorigem Ãœbertrag kombinieren + movel $d4,$a1@+ | 32 Bits ablegen + movel $d3,$d2 + lsrl $d5,$d2 | neuen Ãœbertrag bilden + 2: dbra $d0,1b | Schleife d0.W mal durchlaufen + movel $d2,$d0 + moveml $sp@+,$d2-$d5 + rts +#else + moveml $d2-$d5,$sp@- + movel $sp@(16+4),$a0 + movel $sp@(16+8),$a1 + movew $sp@(16+12+2),$d0 + movew $sp@(16+16+2),$d1 + moveq #1,$d5 + lsll $d1,$d5 + subql #1,$d5 + | a0 = sourceptr, a1 = destptr, d0.W = count, d1.W = i, d5.L = 2^i-1 + | d2.L = Schiebe-Ãœbertrag (i Bits), d3.L = Schiebe-Akku + bras 2f + 1: movel $a0@+,$d3 | d3.L = neues Digit + roll $d1,$d3 | um i Bits links rotieren + movel $d3,$d4 + andl $d5,$d3 | untere i Bits in d3 + eorl $d3,$d4 | obere 32-i Bits in d4 + orl $d2,$d4 | mit vorigem übertrag kombinieren + movel $d4,$a1@+ | 32 Bits ablegen + movel $d3,$d2 | neuer Ãœbertrag + 2: dbra $d0,1b | Schleife d0.W mal durchlaufen + movel $d2,$d0 + moveml $sp@+,$d2-$d5 + rts +#endif + +#if !CL_DS_BIG_ENDIAN_P + +| extern uintD shift1right_loop_down (uintD* ptr, uintC count, uintD carry); + DECLARE_FUNCTION(shift1right_loop_down) +C(shift1right_loop_down:) | Input in a0,d0.W,d1, Output in d0 + movel $sp@(4),$a0 + movew $sp@(8+2),$d0 + movel $sp@(12),$d1 + roxrl #1,$d1 | X-Bit löschen oder setzen, je nach d1 + bras 2f + 1: movel $a0@-,$d1 + roxrl #1,$d1 + movel $d1,$a0@ + 2: dbra $d0,1b + subxl $d0,$d0 | -1 falls X gesetzt, 0 falls X gelöscht + rts + +| extern uintD shiftright_loop_down (uintD* ptr, uintC count, uintC i); + DECLARE_FUNCTION(shiftright_loop_down) +C(shiftright_loop_down:) | Input in a0,d0.W,d1.W, Output in d0 +#if 1 + moveml $d2-$d5,$sp@- + movel $sp@(16+4),$a0 + movew $sp@(16+8+2),$d0 + movew $sp@(16+12+2),$d1 + moveq #32,$d5 + subw $d1,$d5 + | a0 = ptr, d0.W = count, d1.W = i, d5.W = 32-i, + | d2.L = Schiebe-Ãœbertrag (i Bits), d3.L = Schiebe-Akku + clrl $d2 + bras 2f + 1: | a0 = Aufwärtszähler Adresse, d0.W = Herabzähler, d1.W = i, d5.W = 32-i, + | d2.L = Schiebe-Ãœbertrag (obere i Bits, restliche 32-i Bits sind 0) + | d3.L = Schiebe-Akku + movel $a0@-,$d3 | neue Daten + movel $d3,$d4 + lsrl $d1,$d3 | um i Bits rechts schieben + orl $d2,$d3 | und mit vorigem Ãœbertrag kombinieren + movel $d3,$a0@ | ablegen + lsll $d5,$d4 | um (32-i) Bits links geschoben + movel $d4,$d2 | liefert neuen Ãœbertrag + 2: dbra $d0,1b | Schleife d0.W mal durchlaufen + movel $d2,$d0 + moveml $sp@+,$d2-$d5 + rts +#else + moveml $d2-$d5,$sp@- + movel $sp@(16+4),$a0 + movew $sp@(16+8+2),$d0 + movew $sp@(16+12+2),$d1 + moveq #-1,$d5 + lsrl $d1,$d5 + | a0 = ptr, d0.W = count, d1.W = i, d5.L = 2^(32-i)-1, + | d2.L = Schiebe-Ãœbertrag (i Bits), d3.L = Schiebe-Akku + clrl $d2 + bras 2f + 1: | a0 = Aufwärtszähler Adresse, d0.W = Herabzähler, d1.W = i, d5.L = 2^(32-i)-1, + | d2.L = Schiebe-Ãœbertrag (obere i Bits, restliche 32-i Bits sind 0) + | d3.L = Schiebe-Akku + movel $a0@-,$d3 | neue Daten + rorl $d1,$d3 | um i Bits rechts rotieren + movel $d3,$d4 + andl $d5,$d3 | untere 32-i Bits + eorl $d3,$d4 | obere i Bits + orl $d2,$d3 | und mit vorigem Ãœbertrag kombinieren + movel $d4,$d2 | neuer Ãœbertrag + movel $d3,$a0@ | ablegen + 2: dbra $d0,1b | Schleife d0.W mal durchlaufen + movel $d2,$d0 + moveml $sp@+,$d2-$d5 + rts +#endif + +| extern uintD shiftrightsigned_loop_down (uintD* ptr, uintC count, uintC i); + DECLARE_FUNCTION(shiftrightsigned_loop_down) +C(shiftrightsigned_loop_down:) | Input in a0,d0.W,d1.W, Output in d0 +#if 1 + moveml $d2-$d5,$sp@- + movel $sp@(16+4),$a0 + movew $sp@(16+8+2),$d0 + movew $sp@(16+12+2),$d1 + moveq #32,$d5 + subw $d1,$d5 + | a0 = ptr, d0.W = count, d1.W = i, d5.W = 32-i, + | d2.L = Schiebe-Ãœbertrag (i Bits), d3.L = Schiebe-Akku + subqw #1,$d0 + movel $a0@-,$d3 | erstes Digit + movel $d3,$d4 + asrl $d1,$d3 | um i Bits rechts schieben + bras 2f + 1: | a0 = Aufwärtszähler Adresse, d0.W = Herabzähler, d1.W = i, d5.W = 32-i, + | d2.L = Schiebe-Ãœbertrag (obere i Bits, restliche 32-i Bits sind 0) + | d3.L = Schiebe-Akku + movel $a0@-,$d3 | neue Daten + movel $d3,$d4 + lsrl $d1,$d3 | um i Bits rechts schieben + orl $d2,$d3 | und mit vorigem Ãœbertrag kombinieren + 2: movel $d3,$a0@ | ablegen + lsll $d5,$d4 | um (32-i) Bits links geschoben + movel $d4,$d2 | liefert neuen Ãœbertrag + dbra $d0,1b | Schleife d0.W mal durchlaufen + movel $d2,$d0 + moveml $sp@+,$d2-$d5 + rts +#else + moveml $d2-$d5,$sp@- + movel $sp@(16+4),$a0 + movew $sp@(16+8+2),$d0 + movew $sp@(16+12+2),$d1 + moveq #-1,$d5 + lsrl $d1,$d5 + | a0 = ptr, d0.W = count, d1.W = i, d5.L = 2^(32-i)-1, + | d2.L = Schiebe-Ãœbertrag (i Bits), d3.L = Schiebe-Akku + subqw #1,$d0 + movel $a0@-,$d3 | erstes Digit + movel $d3,$d4 + rorl $d1,$d4 | um i Bits rechts rotieren + movel $d5,$d2 + notl $d2 + andl $d4,$d2 | obere 32-i Bits + asrl $d1,$d3 | erstes Digit um i Bits rechts shiften + bras 2f + 1: | a0 = Aufwärtszähler Adresse, d0.W = Herabzähler, d1.W = i, d5.L = 2^(32-i)-1, + | d2.L = Schiebe-Übertrag (obere i Bits, restliche 32-i Bits sind 0) + | d3.L = Schiebe-Akku + movel $a0@-,$d3 | neue Daten + rorl $d1,$d3 | um i Bits rechts rotieren + movel $d3,$d4 + andl $d5,$d3 | untere 32-i Bits + eorl $d3,$d4 | obere i Bits + orl $d2,$d3 | und mit vorigem Übertrag kombinieren + movel $d4,$d2 | neuer Übertrag + 2: movel $d3,$a0@ | ablegen + dbra $d0,1b | Schleife d0.W mal durchlaufen + movel $d2,$d0 + moveml $sp@+,$d2-$d5 + rts +#endif + +| extern uintD shiftrightcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry); + DECLARE_FUNCTION(shiftrightcopy_loop_down) +C(shiftrightcopy_loop_down:) | Input in a0,a1,d0.W,d1.W,d2, Output in d0 +#if 1 + moveml $d2-$d5,$sp@- + movel $sp@(16+4),$a0 + movel $sp@(16+8),$a1 + movew $sp@(16+12+2),$d0 + movew $sp@(16+16+2),$d1 + movel $sp@(16+20),$d2 + moveq #32,$d5 + subw $d1,$d5 + | a0 = ptr, d0.W = count, d1.W = i, d5.W = 32-i + | d2.L = Schiebe-Übertrag (i Bits), d3.L = Schiebe-Akku + bras 2f + 1: | a0,a1 = Aufwärtszähler Adresse, d0.W = Herabzähler, d1.W = i, d5.W = 32-i + | d2.L = Schiebe-Übertrag (obere i Bits, restliche 32-i Bits sind 0) + | d3.L = Schiebe-Akku + movel $a0@-,$d3 | neue Daten + movel $d3,$d4 + lsrl $d1,$d3 | um i Bits rechts schieben + orl $d2,$d3 | und mit vorigem Übertrag kombinieren + movel $d3,$a1@- | ablegen + movel $d4,$d2 + 2: lsll $d5,$d2 | um (32-i) Bits links geschoben, gibt neuen Übertrag + dbra $d0,1b | Schleife d0.W mal durchlaufen + movel $d2,$d0 + moveml $sp@+,$d2-$d5 + rts +#else + moveml $d2-$d5,$sp@- + movel $sp@(16+4),$a0 + movel $sp@(16+8),$a1 + movew $sp@(16+12+2),$d0 + movew $sp@(16+16+2),$d1 + movel $sp@(16+20),$d2 + moveq #-1,$d5 + lsrl $d1,$d5 + rorl $d1,$d2 + | a0 = ptr, d0.W = count, d1.W = i, d5.L = 2^(32-i)-1 + | d2.L = Schiebe-Übertrag (i Bits), d3.L = Schiebe-Akku + bras 2f + 1: | a0,a1 = Aufwärtszähler Adresse, d0.W = Herabzähler, d1.W = i, d5.L = 2^(32-i)-1 + | d2.L = Schiebe-Übertrag (obere i Bits, restliche 32-i Bits sind 0) + | d3.L = Schiebe-Akku + movel $a0@-,$d3 | neue Daten + rorl $d1,$d3 | um i Bits rechts rotieren + movel $d3,$d4 + andl $d5,$d3 | untere 32-i Bits + eorl $d3,$d4 | obere i Bits + orl $d2,$d3 | und mit vorigem Übertrag kombinieren + movel $d4,$d2 | neuer Übertrag + movel $d3,$a1@- | ablegen + 2: dbra $d0,1b | Schleife d0.W mal durchlaufen + movel $d2,$d0 + moveml $sp@+,$d2-$d5 + rts +#endif + +| extern uintD mulusmall_loop_up (uintD digit, uintD* ptr, uintC len, uintD newdigit); + DECLARE_FUNCTION(mulusmall_loop_up) +C(mulusmall_loop_up:) | Input in d0,a0,d1.W,d2, Output in d0 + moveml $d2-$d4,$sp@- + movel $sp@(12+4),$d0 + movel $sp@(12+8),$a0 + movew $sp@(12+12+2),$d1 + movel $sp@(12+16),$d2 + addw #0,$d1 | X-Bit löschen + bras 2f + 1: movel $a0@,$d3 | nächstes Digit + mulul $d0,$d4:$d3 | mit digit multiplizieren + addxl $d2,$d3 | und bisherigen Carry und X-Bit addieren + movel $d3,$a0@+ | Low-Digit ablegen + movel $d4,$d2 | High-Digit gibt neuen Carry + 2: dbra $d1,1b + clrl $d0 + addxl $d2,$d0 | letzter Carry (incl. X-Bit) + moveml $sp@+,$d2-$d4 + rts + +| extern void mulu_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); + DECLARE_FUNCTION(mulu_loop_up) +C(mulu_loop_up:) | Input in d0,a0,a1,d1.W +#if 1 + moveml $d2-$d4,$sp@- + movel $sp@(12+4),$d0 + movel $sp@(12+8),$a0 + movel $sp@(12+12),$a1 + movew $sp@(12+16+2),$d1 + subl $d2,$d2 | carry := 0, X-Bit löschen + bras 2f + 1: movel $a0@+,$d3 | nächstes Digit + mulul $d0,$d4:$d3 | mit digit multiplizieren + addxl $d2,$d3 | und bisherigen Carry und X-Bit addieren + movel $d3,$a1@+ | Low-Digit ablegen + movel $d4,$d2 | High-Digit gibt neuen Carry + 2: dbra $d1,1b + clrl $d3 + addxl $d3,$d2 | letztes X-Bit verarbeiten + movel $d2,$a1@+ | letzten Carry ablegen + moveml $sp@+,$d2-$d4 + rts +#else + moveml $d2-$d5,$sp@- + movel $sp@(16+4),$d0 + movel $sp@(16+8),$a0 + movel $sp@(16+12),$a1 + movew $sp@(16+16+2),$d1 + clrl $d5 | 0 + clrl $d2 | carry + bras 2f + 1: movel $a0@+,$d3 | nächstes Digit + mulul $d0,$d4:$d3 | mit digit multiplizieren + addl $d2,$d3 | und bisherigen Carry addieren + addxl $d5,$d4 + movel $d3,$a1@+ | Low-Digit ablegen + movel $d4,$d2 | High-Digit gibt neuen Carry + 2: dbra $d1,1b + movel $d2,$a1@+ | letzten Carry ablegen + moveml $sp@+,$d2-$d5 + rts +#endif + +| extern uintD muluadd_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); + DECLARE_FUNCTION(muluadd_loop_up) +C(muluadd_loop_up:) | Input in d0,a0,a1,d1.W, Output in d0 + moveml $d2-$d5,$sp@- + movel $sp@(16+4),$d0 + movel $sp@(16+8),$a0 + movel $sp@(16+12),$a1 + movew $sp@(16+16+2),$d1 + clrl $d5 | 0 + subl $d2,$d2 | carry := 0, X-Bit löschen + bras 2f + 1: movel $a0@+,$d3 | nächstes Digit + mulul $d0,$d4:$d3 | mit digit multiplizieren + addxl $d2,$d3 | und bisherigen Carry und X-Bit addieren + addxl $d5,$d4 + addl $d3,$a1@+ | Low-Digit zum dest-Digit addieren, X als Übertrag + movel $d4,$d2 | High-Digit gibt neuen Carry + 2: dbra $d1,1b + addxl $d5,$d2 | letztes X-Bit addieren + movel $d2,$d0 | letzten Carry als Ergebnis + moveml $sp@+,$d2-$d5 + rts + +| extern uintD mulusub_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); + DECLARE_FUNCTION(mulusub_loop_up) +C(mulusub_loop_up:) | Input in d0,a0,a1,d1.W, Output in d0 + moveml $d2-$d5,$sp@- + movel $sp@(16+4),$d0 + movel $sp@(16+8),$a0 + movel $sp@(16+12),$a1 + movew $sp@(16+16+2),$d1 + clrl $d5 | 0 + subl $d2,$d2 | carry := 0, X-Bit löschen + bras 2f + 1: movel $a0@+,$d3 | nächstes Digit + mulul $d0,$d4:$d3 | mit digit multiplizieren + addxl $d2,$d3 | und bisherigen Carry und X-Bit addieren + addxl $d5,$d4 + subl $d3,$a1@+ | Low-Digit vom dest-Digit subtrahieren, X als Übertrag + movel $d4,$d2 | High-Digit gibt neuen Carry + 2: dbra $d1,1b + clrl $d0 + addxl $d2,$d0 | letzter Carry und letztes X-Bit + moveml $sp@+,$d2-$d5 + rts + +| extern uintD divu_loop_down (uintD digit, uintD* ptr, uintC len); + DECLARE_FUNCTION(divu_loop_down) +C(divu_loop_down:) | Input in d0,a0,d1.W, Output in d0 + moveml $d2-$d3,$sp@- + movel $sp@(8+4),$d0 + movel $sp@(8+8),$a0 + movew $sp@(8+12+2),$d1 + clrl $d2 | Rest := 0 + bras 2f + 1: movel $a0@-,$d3 | nächst-niedriges Digit + divul $d0,$d2:$d3 | mit Rest kombinieren und durch digit dividieren + movel $d3,$a0@ | Quotient ablegen, Rest in d2 + 2: dbra $d1,1b + movel $d2,$d0 | Rest + moveml $sp@+,$d2-$d3 + rts + +| extern uintD divucopy_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); + DECLARE_FUNCTION(divucopy_loop_down) +C(divucopy_loop_down:) | Input in d0,a0,a1,d1.W, Output in d0 + moveml $d2-$d3,$sp@- + movel $sp@(8+4),$d0 + movel $sp@(8+8),$a0 + movel $sp@(8+12),$a1 + movew $sp@(8+16+2),$d1 + clrl $d2 | Rest := 0 + bras 2f + 1: movel $a0@-,$d3 | nächst-niedriges Digit + divul $d0,$d2:$d3 | mit Rest kombinieren und durch digit dividieren + movel $d3,$a1@- | Quotient ablegen, Rest in d2 + 2: dbra $d1,1b + movel $d2,$d0 | Rest + moveml $sp@+,$d2-$d3 + rts + +#endif + +| extern void shiftxor_loop_up (uintD* xptr, const uintD* yptr, uintC count, uintC i); + DECLARE_FUNCTION(shiftxor_loop_up) +C(shiftxor_loop_up:) | Input in a0,a1,d0.W,d1.W + moveml $d2-$d5,$sp@- + movel $sp@(16+4),$a0 + movel $sp@(16+8),$a1 + movew $sp@(16+12+2),$d0 + movew $sp@(16+16+2),$d1 + moveq #32,$d5 + subw $d1,$d5 + clrl $d2 + | a0 = xptr, a1 = yptr, d0.W = count, d1.W = i, d5.W = 32-i, + | d2.L = Schiebe-Übertrag (i Bits), d3.L = Schiebe-Akku + bras 2f + 1: movel $a1@+,$d3 | d3.L = neues Digit + movel $d3,$d4 + lsll $d1,$d4 | um i Bits nach links schieben + orl $d2,$d4 | mit vorigem Übertrag kombinieren + eorl $d4,$a0@+ | 32 Bits ablegen + movel $d3,$d2 + lsrl $d5,$d2 | neuen Übertrag bilden + 2: dbra $d0,1b | Schleife d0.W mal durchlaufen + eorl $d2,$a0@ + moveml $sp@+,$d2-$d5 + rts diff --git a/src/base/digitseq/cl_asm_mips.h b/src/base/digitseq/cl_asm_mips.h new file mode 100644 index 0000000..0e7f84d --- /dev/null +++ b/src/base/digitseq/cl_asm_mips.h @@ -0,0 +1,8 @@ +// List the contents of cl_asm_mips.cc. + +#define COPY_LOOPS +#define FILL_LOOPS +#define CLEAR_LOOPS +#define LOG_LOOPS +#define TEST_LOOPS +#define ADDSUB_LOOPS diff --git a/src/base/digitseq/cl_asm_mips_.cc b/src/base/digitseq/cl_asm_mips_.cc new file mode 100644 index 0000000..a057c22 --- /dev/null +++ b/src/base/digitseq/cl_asm_mips_.cc @@ -0,0 +1,1140 @@ +// Externe Routinen zu ARILEV1.D +// Prozessor: MIPS +// Endianness: irrelevant +// Compiler: GNU-C oder ... +// Parameter-Übergabe: in Registern $4,$5,$6,$7, und auf dem Stack 16($sp),... +// Rückgabewert: in Register $2 +// Einstellungen: intCsize=32, intDsize=32. +// Besonderheiten: Nach jedem Ladebefehl ein Wartetakt nötig, bevor der +// geholte Wert benutzt werden darf. + +// When this file is compiled into a shared library, ELF linkers need to +// know which symbols are functions. +#if defined(__GNU__) || defined(__NetBSD__) + #define DECLARE_FUNCTION(name) .type name,@function +#else + #define DECLARE_FUNCTION(name) +#endif + + .text + + .globl copy_loop_up + .globl copy_loop_down + .globl fill_loop_up + .globl fill_loop_down + .globl clear_loop_up + .globl clear_loop_down + .globl test_loop_up + .globl test_loop_down + .globl xor_loop_up + .globl compare_loop_up +#if CL_DS_BIG_ENDIAN_P + .globl or_loop_up + .globl and_loop_up + .globl eqv_loop_up + .globl nand_loop_up + .globl nor_loop_up + .globl andc2_loop_up + .globl orc2_loop_up + .globl not_loop_up + .globl and_test_loop_up + .globl add_loop_down + .globl addto_loop_down + .globl inc_loop_down + .globl sub_loop_down + .globl subx_loop_down + .globl subfrom_loop_down + .globl dec_loop_down + .globl neg_loop_down +#else + .globl or_loop_down + .globl xor_loop_down + .globl and_loop_down + .globl eqv_loop_down + .globl nand_loop_down + .globl nor_loop_down + .globl andc2_loop_down + .globl orc2_loop_down + .globl not_loop_down + .globl and_test_loop_down + .globl compare_loop_down + .globl add_loop_up + .globl addto_loop_up + .globl inc_loop_up + .globl sub_loop_up + .globl subx_loop_up + .globl subfrom_loop_up + .globl dec_loop_up + .globl neg_loop_up +#endif + +#ifndef __GNUC__ /* mit GNU-C machen wir mulu32() als Macro, der inline multipliziert */ + +// extern struct { uint32 lo; uint32 hi; } mulu32_ (uint32 arg1, uint32 arg2); +// 2^32*hi+lo := arg1*arg2. + .globl mulu32_ + .align 2 + DECLARE_FUNCTION(mulu32_) + .ent mulu32_ // Input in $4,$5, Output in $2,mulu32_high +mulu32_: + multu $5,$4 // arg1 * arg2 + mfhi $6 // hi + mflo $2 // lo + sw $6,mulu32_high // hi abspeichern // Adressierung?? Deklaration?? + j $31 // return + .end mulu32_ + +#endif + +// extern uintD* copy_loop_up (uintD* sourceptr, uintD* destptr, uintC count); + .align 2 + DECLARE_FUNCTION(copy_loop_up) + .ent copy_loop_up // Input in $4,$5,$6, Output in $2 +colu1: lw $12,($4) // d = *sourceptr + addu $4,4 // sourceptr++ + sw $12,($5) // *destptr = d + addu $5,4 // destptr++ + subu $6,1 // count-- +copy_loop_up: + bnez $6,colu1 // until (count==0) + move $2,$5 // destptr + j $31 // return + .end copy_loop_up + +// extern uintD* copy_loop_down (uintD* sourceptr, uintD* destptr, uintC count); + .align 2 + DECLARE_FUNCTION(copy_loop_down) + .ent copy_loop_down // Input in $4,$5,$6, Output in $2 +cold1: subu $4,4 // sourceptr-- + lw $12,($4) // d = *sourceptr + subu $5,4 // destptr-- + sw $12,($5) // *destptr = d + subu $6,1 // count-- +copy_loop_down: + bnez $6,cold1 // until (count==0) + move $2,$5 // destptr + j $31 // return + .end copy_loop_down + +// extern uintD* fill_loop_up (uintD* destptr, uintC count, uintD filler); + .align 2 + DECLARE_FUNCTION(fill_loop_up) + .ent fill_loop_up // Input in $4,$5,$6, Output in $2 +flu1: sw $6,($4) // *destptr = filler + addu $4,4 // destptr++ + subu $5,1 // count-- +fill_loop_up: + bnez $5,flu1 // until (count==0) + move $2,$4 // destptr + j $31 // return + .end fill_loop_up + +// extern uintD* fill_loop_down (uintD* destptr, uintC count, uintD filler); + .align 2 + DECLARE_FUNCTION(fill_loop_down) + .ent fill_loop_down // Input in $4,$5,$6, Output in $2 +fld1: subu $4,4 // destptr-- + sw $6,($4) // *destptr = filler + subu $5,1 // count-- +fill_loop_down: + bnez $5,fld1 // until (count==0) + move $2,$4 // destptr + j $31 // return + .end fill_loop_down + +// extern uintD* clear_loop_up (uintD* destptr, uintC count); + .align 2 + DECLARE_FUNCTION(clear_loop_up) + .ent clear_loop_up // Input in $4,$5, Output in $2 +cllu1: sw $0,($4) // *destptr = 0 + addu $4,4 // destptr++ + subu $5,1 // count-- +clear_loop_up: + bnez $5,cllu1 // until (count==0) + move $2,$4 // destptr + j $31 // return + .end clear_loop_up + +// extern uintD* clear_loop_down (uintD* destptr, uintC count); + .align 2 + DECLARE_FUNCTION(clear_loop_down) + .ent clear_loop_down // Input in $4,$5, Output in $2 +clld1: subu $4,4 // destptr-- + sw $0,($4) // *destptr = 0 + subu $5,1 // count-- +clear_loop_down: + bnez $5,clld1 // until (count==0) + move $2,$4 // destptr + j $31 // return + .end clear_loop_down + +// extern boolean test_loop_up (uintD* ptr, uintC count); + .align 2 + DECLARE_FUNCTION(test_loop_up) + .ent test_loop_up // Input in $4,$5 +tlu1: lw $12,($4) // x = *ptr + addu $4,4 // ptr++ + bnez $12,tlu3 + subu $5,1 // count-- +test_loop_up: + bnez $5,tlu1 // until (count==0) + move $2,$0 // 0 + j $31 // return +tlu3: li $2,1 // 1 + j $31 // return + .end test_loop_up + +// extern boolean test_loop_down (uintD* ptr, uintC count); + .align 2 + DECLARE_FUNCTION(test_loop_down) + .ent test_loop_down // Input in $4,$5 +tld1: subu $4,4 // ptr-- + lw $12,($4) // x = *ptr + subu $5,1 // count-- + bnez $12,tld3 +test_loop_down: + bnez $5,tld1 // until (count==0) + move $2,$0 // 0 + j $31 // return +tld3: li $2,1 // 1 + j $31 // return + .end test_loop_down + +#if CL_DS_BIG_ENDIAN_P + +// extern void or_loop_up (uintD* xptr, uintD* yptr, uintC count); + .align 2 + DECLARE_FUNCTION(or_loop_up) + .ent or_loop_up // Input in $4,$5,$6 +olu1: lw $12,($4) // x = *xptr + lw $13,($5) // y = *yptr + addu $5,4 // yptr++ + or $12,$13 // x |= y + sw $12,($4) // *xptr = x + addu $4,4 // xptr++ + subu $6,1 // count-- +or_loop_up: + bnez $6,olu1 // until (count==0) + j $31 // return + .end or_loop_up + +#endif + +// extern void xor_loop_up (uintD* xptr, uintD* yptr, uintC count); + .align 2 + DECLARE_FUNCTION(xor_loop_up) + .ent xor_loop_up // Input in $4,$5,$6 +xlu1: lw $12,($4) // x = *xptr + lw $13,($5) // y = *yptr + addu $5,4 // yptr++ + xor $12,$13 // x ^= y + sw $12,($4) // *xptr = x + addu $4,4 // xptr++ + subu $6,1 // count-- +xor_loop_up: + bnez $6,xlu1 // until (count==0) + j $31 // return + .end xor_loop_up + +#if CL_DS_BIG_ENDIAN_P + +// extern void and_loop_up (uintD* xptr, uintD* yptr, uintC count); + .align 2 + DECLARE_FUNCTION(and_loop_up) + .ent and_loop_up // Input in $4,$5,$6 +alu1: lw $12,($4) // x = *xptr + lw $13,($5) // y = *yptr + addu $5,4 // yptr++ + and $12,$13 // x &= y + sw $12,($4) // *xptr = x + addu $4,4 // xptr++ + subu $6,1 // count-- +and_loop_up: + bnez $6,alu1 // until (count==0) + j $31 // return + .end and_loop_up + +// extern void eqv_loop_up (uintD* xptr, uintD* yptr, uintC count); + .align 2 + DECLARE_FUNCTION(eqv_loop_up) + .ent eqv_loop_up // Input in $4,$5,$6 +nxlu1: lw $12,($4) // x = *xptr + lw $13,($5) // y = *yptr + addu $5,4 // yptr++ + xor $12,$13 // x ^= y + nor $12,$0 // x = ~x + sw $12,($4) // *xptr = x + addu $4,4 // xptr++ + subu $6,1 // count-- +eqv_loop_up: + bnez $6,nxlu1 // until (count==0) + j $31 // return + .end eqv_loop_up + +// extern void nand_loop_up (uintD* xptr, uintD* yptr, uintC count); + .align 2 + DECLARE_FUNCTION(nand_loop_up) + .ent nand_loop_up // Input in $4,$5,$6 +nalu1: lw $12,($4) // x = *xptr + lw $13,($5) // y = *yptr + addu $5,4 // yptr++ + and $12,$13 // x &= y // Gibt es 'nand $12,$13' ?? + nor $12,$0 // x = ~x + sw $12,($4) // *xptr = x + addu $4,4 // xptr++ + subu $6,1 // count-- +nand_loop_up: + bnez $6,nalu1 // until (count==0) + j $31 // return + .end nand_loop_up + +// extern void nor_loop_up (uintD* xptr, uintD* yptr, uintC count); + .align 2 + DECLARE_FUNCTION(nor_loop_up) + .ent nor_loop_up // Input in $4,$5,$6 +nolu1: lw $12,($4) // x = *xptr + lw $13,($5) // y = *yptr + addu $5,4 // yptr++ + nor $12,$13 // x = ~(x|y) + sw $12,($4) // *xptr = x + addu $4,4 // xptr++ + subu $6,1 // count-- +nor_loop_up: + bnez $6,nolu1 // until (count==0) + j $31 // return + .end nor_loop_up + +// extern void andc2_loop_up (uintD* xptr, uintD* yptr, uintC count); + .align 2 + DECLARE_FUNCTION(andc2_loop_up) + .ent andc2_loop_up // Input in $4,$5,$6 +aclu1: lw $12,($4) // x = *xptr + lw $13,($5) // y = *yptr + addu $5,4 // yptr++ + nor $13,$0 // y = ~y + and $12,$13 // x &= y + sw $12,($4) // *xptr = x + addu $4,4 // xptr++ + subu $6,1 // count-- +andc2_loop_up: + bnez $6,aclu1 // until (count==0) + j $31 // return + .end andc2_loop_up + +// extern void orc2_loop_up (uintD* xptr, uintD* yptr, uintC count); + .align 2 + DECLARE_FUNCTION(orc2_loop_up) + .ent orc2_loop_up // Input in $4,$5,$6 +oclu1: lw $12,($4) // x = *xptr + lw $13,($5) // y = *yptr + addu $5,4 // yptr++ + nor $13,$0 // y = ~y + or $12,$13 // x |= y + sw $12,($4) // *xptr = x + addu $4,4 // xptr++ + subu $6,1 // count-- +orc2_loop_up: + bnez $6,oclu1 // until (count==0) + j $31 // return + .end orc2_loop_up + +// extern void not_loop_up (uintD* xptr, uintC count); + .align 2 + DECLARE_FUNCTION(not_loop_up) + .ent not_loop_up // Input in $4,$5 +nlu1: lw $12,($4) // x = *xptr + subu $5,1 // count-- + nor $12,$0 // x = ~x + sw $12,($4) // *xptr = x + addu $4,4 // xptr++ +not_loop_up: + bnez $5,nlu1 // until (count==0) + j $31 // return + .end not_loop_up + +// extern boolean and_test_loop_up (uintD* xptr, uintD* yptr, uintC count); + .align 2 + DECLARE_FUNCTION(and_test_loop_up) + .ent and_test_loop_up // Input in $4,$5,$6 +atlu1: lw $12,($4) // x = *xptr + lw $13,($5) // y = *yptr + addu $5,4 // yptr++ + and $12,$13 // x &= y + bnez $12,atlu3 // if (x) ... + addu $4,4 // xptr++ + subu $6,1 // count-- +and_test_loop_up: + bnez $6,atlu1 // until (count==0) + move $2,$0 // 0 + j $31 // return +atlu3: li $2,1 // 1 + j $31 // return + .end and_test_loop_up + +#endif + +// extern cl_signean compare_loop_up (uintD* xptr, uintD* yptr, uintC count); + .align 2 + DECLARE_FUNCTION(compare_loop_up) + .ent compare_loop_up // Input in $4,$5,$6 +cmlu1: lw $12,($4) // x = *xptr + lw $13,($5) // y = *yptr + addu $5,4 // yptr++ + bne $12,$13,cmlu3 // if (!(x==y)) ... + addu $4,4 // xptr++ + subu $6,1 // count-- +compare_loop_up: + bnez $6,cmlu1 // until (count==0) + move $2,$0 // 0 + j $31 // return +cmlu3: bltu $12,$13,cmlu4 // if (x source2) [also kein Carry] ... +ald4: subu $7,1 // count-- + bnez $7,ald3 // until (count==0) + li $2,1 // 1 + j $31 // return + .end add_loop_down + +// extern uintD addto_loop_down (uintD* sourceptr, uintD* destptr, uintC count); + .align 2 + DECLARE_FUNCTION(addto_loop_down) + .ent addto_loop_down // Input in $4,$5,$6, Output in $2 +atld1: // kein Carry + subu $4,4 // sourceptr-- + subu $5,4 // destptr-- + lw $12,($4) // source1 = *sourceptr + lw $13,($5) // source2 = *destptr + subu $6,1 // count-- + addu $12,$13 // dest = source1 + source2 + sw $12,($5) // *destptr = dest + bltu $12,$13,atld4 // if (dest < source2) [also Carry] ... +addto_loop_down: +atld2: bnez $6,atld1 // until (count==0) + move $2,$0 // 0 + j $31 // return +atld3: // Hier Carry + subu $4,4 // sourceptr-- + subu $5,4 // destptr-- + lw $12,($4) // source1 = *sourceptr + lw $13,($5) // source2 = *destptr + subu $6,1 // count-- + addu $12,$13 // dest = source1 + source2 + addu $12,1 // + 1 + sw $12,($5) // *destptr = dest + bgtu $12,$13,atld2 // if (dest > source2) [also kein Carry] ... +atld4: bnez $6,atld3 // until (count==0) + li $2,1 // 1 + j $31 // return + .end addto_loop_down + +// extern uintD inc_loop_down (uintD* ptr, uintC count); + .align 2 + DECLARE_FUNCTION(inc_loop_down) + .ent inc_loop_down // Input in $4,$5, Output in $2 +ild1: subu $4,4 // ptr-- + lw $12,($4) // x = *ptr + subu $5,1 // count-- + addu $12,1 // x++; + sw $12,($4) // *ptr = x + bnez $12,ild3 // if (!(x==0)) ... +inc_loop_down: + bnez $5,ild1 // until (count==0) + li $2,1 // 1 + j $31 // return +ild3: move $2,$0 // 0 + j $31 // return + .end inc_loop_down + +// extern uintD sub_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count); + .align 2 + DECLARE_FUNCTION(sub_loop_down) + .ent sub_loop_down // Input in $4,$5,$6,$7, Output in $2 +sld1: // kein Carry + subu $4,4 // sourceptr1-- + subu $5,4 // sourceptr2-- + lw $12,($4) // source1 = *sourceptr1 + lw $13,($5) // source2 = *sourceptr2 + subu $6,4 // destptr-- + bltu $12,$13,sld2 // if (source1 < source2) [also Carry] ... + subu $12,$13 // dest = source1 - source2 + sw $12,($6) // *destptr = dest + subu $7,1 // count-- +sub_loop_down: + bnez $7,sld1 // until (count==0) + move $2,$0 // 0 + j $31 // return +sld2: subu $12,$13 // dest = source1 - source2 + sw $12,($6) // *destptr = dest + subu $7,1 // count-- + bnez $7,sld3 // until (count==0) + li $2,-1 // -1 + j $31 // return +sld3: // Hier Carry + subu $4,4 // sourceptr1-- + subu $5,4 // sourceptr2-- + lw $12,($4) // source1 = *sourceptr1 + lw $13,($5) // source2 = *sourceptr2 + subu $6,4 // destptr-- + bgtu $12,$13,sld4 // if (source1 > source2) [also kein Carry] ... + subu $12,$13 // dest = source1 - source2 + subu $12,1 // - 1 + sw $12,($6) // *destptr = dest + subu $7,1 // count-- + bnez $7,sld3 // until (count==0) + li $2,-1 // -1 + j $31 // return +sld4: subu $12,$13 // dest = source1 - source2 + subu $12,1 // - 1 + sw $12,($6) // *destptr = dest + subu $7,1 // count-- + bnez $7,sld1 // until (count==0) + move $2,$0 // 0 + j $31 // return + .end sub_loop_down + +// extern uintD subx_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry); + .align 2 + DECLARE_FUNCTION(subx_loop_down) + .ent subx_loop_down // Input in $4,$5,$6,$7, Output in $2 +subx_loop_down: + lw $12,16($sp) // carry + bnez $12,sxld5 // !(carry==0) ? + b sxld2 +sxld1: // kein Carry + subu $4,4 // sourceptr1-- + subu $5,4 // sourceptr2-- + lw $12,($4) // source1 = *sourceptr1 + lw $13,($5) // source2 = *sourceptr2 + subu $6,4 // destptr-- + bltu $12,$13,sxld3 // if (source1 < source2) [also Carry] ... + subu $12,$13 // dest = source1 - source2 + sw $12,($6) // *destptr = dest + subu $7,1 // count-- +sxld2: bnez $7,sxld1 // until (count==0) + move $2,$0 // 0 + j $31 // return +sxld3: subu $12,$13 // dest = source1 - source2 + sw $12,($6) // *destptr = dest + subu $7,1 // count-- + bnez $7,sxld4 // until (count==0) + li $2,-1 // -1 + j $31 // return +sxld4: // Hier Carry + subu $4,4 // sourceptr1-- + subu $5,4 // sourceptr2-- + lw $12,($4) // source1 = *sourceptr1 + lw $13,($5) // source2 = *sourceptr2 + subu $6,4 // destptr-- + bgtu $12,$13,sxld6 // if (source1 > source2) [also kein Carry] ... + subu $12,$13 // dest = source1 - source2 + subu $12,1 // - 1 + sw $12,($6) // *destptr = dest + subu $7,1 // count-- +sxld5: bnez $7,sxld4 // until (count==0) + li $2,-1 // -1 + j $31 // return +sxld6: subu $12,$13 // dest = source1 - source2 + subu $12,1 // - 1 + sw $12,($6) // *destptr = dest + subu $7,1 // count-- + bnez $7,sxld1 // until (count==0) + move $2,$0 // 0 + j $31 // return + .end subx_loop_down + +// extern uintD subfrom_loop_down (uintD* sourceptr, uintD* destptr, uintC count); + .align 2 + DECLARE_FUNCTION(subfrom_loop_down) + .ent subfrom_loop_down // Input in $4,$5,$6,$7, Output in $2 +sfld1: // kein Carry + subu $4,4 // sourceptr-- + subu $5,4 // destptr-- + lw $12,($5) // source1 = *destptr + lw $13,($4) // source2 = *sourceptr + subu $6,1 // count-- + bltu $12,$13,sfld2 // if (source1 < source2) [also Carry] ... + subu $12,$13 // dest = source1 - source2 + sw $12,($5) // *destptr = dest +subfrom_loop_down: + bnez $6,sfld1 // until (count==0) + move $2,$0 // 0 + j $31 // return +sfld2: subu $12,$13 // dest = source1 - source2 + sw $12,($5) // *destptr = dest + bnez $6,sfld3 // until (count==0) + li $2,-1 // -1 + j $31 // return +sfld3: // Hier Carry + subu $4,4 // sourceptr-- + subu $5,4 // destptr-- + lw $12,($5) // source1 = *destptr + lw $13,($4) // source2 = *sourceptr + subu $6,1 // count-- + bgtu $12,$13,sfld4 // if (source1 > source2) [also kein Carry] ... + subu $12,$13 // dest = source1 - source2 + subu $12,1 // - 1 + sw $12,($5) // *destptr = dest + bnez $6,sfld3 // until (count==0) + li $2,-1 // -1 + j $31 // return +sfld4: subu $12,$13 // dest = source1 - source2 + subu $12,1 // - 1 + sw $12,($5) // *destptr = dest + bnez $6,sfld1 // until (count==0) + move $2,$0 // 0 + j $31 // return + .end subfrom_loop_down + +// extern uintD dec_loop_down (uintD* ptr, uintC count); + .align 2 + DECLARE_FUNCTION(dec_loop_down) + .ent dec_loop_down // Input in $4,$5, Output in $2 +dld1: subu $4,4 // ptr-- + lw $12,($4) // x = *ptr + subu $5,1 // count-- + bnez $12,dld3 // if (!(x==0)) ... + subu $12,1 // x--; + sw $12,($4) // *ptr = x +dec_loop_down: + bnez $5,dld1 // until (count==0) + li $2,-1 // -1 + j $31 // return +dld3: subu $12,1 // x--; + sw $12,($4) // *ptr = x + move $2,$0 // 0 + j $31 // return + .end dec_loop_down + +// extern uintD neg_loop_down (uintD* ptr, uintC count); + .align 2 + DECLARE_FUNCTION(neg_loop_down) + .ent neg_loop_down // Input in $4,$5, Output in $2 + // erstes Digit /=0 suchen: +nld1: subu $4,4 // ptr-- + lw $12,($4) // x = *ptr + subu $5,1 // count-- + bnez $12,nld3 // if (!(x==0)) ... +neg_loop_down: + bnez $5,nld1 // until (count==0) + move $2,$0 // 0 + j $31 // return +nld3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys + // 1 Digit negieren: + subu $12,$0,$12 // x = -x + sw $12,($4) // *ptr = x + // alle anderen Digits invertieren: + b nld5 +nld4: subu $4,4 // xptr-- + lw $12,($4) // x = *xptr + subu $5,1 // count-- + nor $12,$0 // x = ~x + sw $12,($4) // *xptr = x +nld5: bnez $5,nld4 // until (count==0) + li $2,-1 // -1 + j $31 // return + .end neg_loop_down + +#endif + +#if !CL_DS_BIG_ENDIAN_P + +// extern void or_loop_down (uintD* xptr, uintD* yptr, uintC count); + .align 2 + DECLARE_FUNCTION(or_loop_down) + .ent or_loop_down // Input in $4,$5,$6 +old1: subu $4,4 // xptr-- + subu $5,4 // yptr-- + lw $12,($4) // x = *xptr + lw $13,($5) // y = *yptr + subu $6,1 // count-- + or $12,$13 // x |= y + sw $12,($4) // *xptr = x +or_loop_down: + bnez $6,old1 // until (count==0) + j $31 // return + .end or_loop_down + +// extern void xor_loop_down (uintD* xptr, uintD* yptr, uintC count); + .align 2 + DECLARE_FUNCTION(xor_loop_down) + .ent xor_loop_down // Input in $4,$5,$6 +xld1: subu $4,4 // xptr-- + subu $5,4 // yptr-- + lw $12,($4) // x = *xptr + lw $13,($5) // y = *yptr + subu $6,1 // count-- + xor $12,$13 // x ^= y + sw $12,($4) // *xptr = x +xor_loop_down: + bnez $6,xld1 // until (count==0) + j $31 // return + .end xor_loop_down + +// extern void and_loop_down (uintD* xptr, uintD* yptr, uintC count); + .align 2 + DECLARE_FUNCTION(and_loop_down) + .ent and_loop_down // Input in $4,$5,$6 +ald1: subu $4,4 // xptr-- + subu $5,4 // yptr-- + lw $12,($4) // x = *xptr + lw $13,($5) // y = *yptr + subu $6,1 // count-- + and $12,$13 // x &= y + sw $12,($4) // *xptr = x +and_loop_down: + bnez $6,ald1 // until (count==0) + j $31 // return + .end and_loop_down + +// extern void eqv_loop_down (uintD* xptr, uintD* yptr, uintC count); + .align 2 + DECLARE_FUNCTION(eqv_loop_down) + .ent eqv_loop_down // Input in $4,$5,$6 +nxld1: subu $4,4 // xptr-- + subu $5,4 // yptr-- + lw $12,($4) // x = *xptr + lw $13,($5) // y = *yptr + subu $6,1 // count-- + xor $12,$13 // x ^= y + nor $12,$0 // x = ~x + sw $12,($4) // *xptr = x +eqv_loop_down: + bnez $6,nxld1 // until (count==0) + j $31 // return + .end eqv_loop_down + +// extern void nand_loop_down (uintD* xptr, uintD* yptr, uintC count); + .align 2 + DECLARE_FUNCTION(nand_loop_down) + .ent nand_loop_down // Input in $4,$5,$6 +nald1: subu $4,4 // xptr-- + subu $5,4 // yptr-- + lw $12,($4) // x = *xptr + lw $13,($5) // y = *yptr + subu $6,1 // count-- + and $12,$13 // x &= y // Gibt es 'nand $12,$13' ?? + nor $12,$0 // x = ~x + sw $12,($4) // *xptr = x +nand_loop_down: + bnez $6,nald1 // until (count==0) + j $31 // return + .end nand_loop_down + +// extern void nor_loop_down (uintD* xptr, uintD* yptr, uintC count); + .align 2 + DECLARE_FUNCTION(nor_loop_down) + .ent nor_loop_down // Input in $4,$5,$6 +nold1: subu $4,4 // xptr-- + subu $5,4 // yptr-- + lw $12,($4) // x = *xptr + lw $13,($5) // y = *yptr + subu $6,1 // count-- + nor $12,$13 // x = ~(x|y) + sw $12,($4) // *xptr = x +nor_loop_down: + bnez $6,nold1 // until (count==0) + j $31 // return + .end nor_loop_down + +// extern void andc2_loop_down (uintD* xptr, uintD* yptr, uintC count); + .align 2 + DECLARE_FUNCTION(andc2_loop_down) + .ent andc2_loop_down // Input in $4,$5,$6 +acld1: subu $4,4 // xptr-- + subu $5,4 // yptr-- + lw $12,($4) // x = *xptr + lw $13,($5) // y = *yptr + subu $6,1 // count-- + nor $13,$0 // y = ~y + and $12,$13 // x &= y + sw $12,($4) // *xptr = x +andc2_loop_down: + bnez $6,acld1 // until (count==0) + j $31 // return + .end andc2_loop_down + +// extern void orc2_loop_down (uintD* xptr, uintD* yptr, uintC count); + .align 2 + DECLARE_FUNCTION(orc2_loop_down) + .ent orc2_loop_down // Input in $4,$5,$6 +ocld1: subu $4,4 // xptr-- + subu $5,4 // yptr-- + lw $12,($4) // x = *xptr + lw $13,($5) // y = *yptr + subu $6,1 // count-- + nor $13,$0 // y = ~y + or $12,$13 // x |= y + sw $12,($4) // *xptr = x +orc2_loop_down: + bnez $6,ocld1 // until (count==0) + j $31 // return + .end orc2_loop_down + +// extern void not_loop_down (uintD* xptr, uintC count); + .align 2 + DECLARE_FUNCTION(not_loop_down) + .ent not_loop_down // Input in $4,$5 +nld1: subu $4,4 // xptr-- + lw $12,($4) // x = *xptr + subu $5,1 // count-- + nor $12,$0 // x = ~x + sw $12,($4) // *xptr = x +not_loop_down: + bnez $5,nld1 // until (count==0) + j $31 // return + .end not_loop_down + +// extern boolean and_test_loop_down (uintD* xptr, uintD* yptr, uintC count); + .align 2 + DECLARE_FUNCTION(and_test_loop_down) + .ent and_test_loop_down // Input in $4,$5,$6 +atld1: subu $4,4 // xptr-- + subu $5,4 // yptr-- + lw $12,($4) // x = *xptr + lw $13,($5) // y = *yptr + and $12,$13 // x &= y + bnez $12,atld3 // if (x) ... + subu $6,1 // count-- +and_test_loop_down: + bnez $6,atld1 // until (count==0) + move $2,$0 // 0 + j $31 // return +atld3: li $2,1 // 1 + j $31 // return + .end and_test_loop_down + +// extern cl_signean compare_loop_down (uintD* xptr, uintD* yptr, uintC count); + .align 2 + DECLARE_FUNCTION(compare_loop_down) + .ent compare_loop_down // Input in $4,$5,$6 +cmld1: subu $4,4 // xptr-- + subu $5,4 // yptr-- + lw $12,($4) // x = *xptr + lw $13,($5) // y = *yptr + subu $6,1 // count-- + bne $12,$13,cmld3 // if (!(x==y)) ... +compare_loop_down: + bnez $6,cmld1 // until (count==0) + move $2,$0 // 0 + j $31 // return +cmld3: bltu $12,$13,cmld4 // if (x source2) [also kein Carry] ... +alu4: subu $7,1 // count-- + bnez $7,alu3 // until (count==0) + li $2,1 // 1 + j $31 // return + .end add_loop_up + +// extern uintD addto_loop_up (uintD* sourceptr, uintD* destptr, uintC count); + .align 2 + DECLARE_FUNCTION(addto_loop_up) + .ent addto_loop_up // Input in $4,$5,$6, Output in $2 +atlu1: // kein Carry + lw $12,($4) // source1 = *sourceptr + lw $13,($5) // source2 = *destptr + addu $4,4 // sourceptr++ + subu $6,1 // count-- + addu $12,$13 // dest = source1 + source2 + sw $12,($5) // *destptr = dest + addu $5,4 // destptr++ + bltu $12,$13,atlu4 // if (dest < source2) [also Carry] ... +addto_loop_up: +atlu2: bnez $6,atlu1 // until (count==0) + move $2,$0 // 0 + j $31 // return +atlu3: // Hier Carry + lw $12,($4) // source1 = *sourceptr + lw $13,($5) // source2 = *destptr + addu $4,4 // sourceptr++ + subu $6,1 // count-- + addu $12,$13 // dest = source1 + source2 + addu $12,1 // + 1 + sw $12,($5) // *destptr = dest + addu $5,4 // destptr++ + bgtu $12,$13,atlu2 // if (dest > source2) [also kein Carry] ... +atlu4: bnez $6,atlu3 // until (count==0) + li $2,1 // 1 + j $31 // return + .end addto_loop_up + +// extern uintD inc_loop_up (uintD* ptr, uintC count); + .align 2 + DECLARE_FUNCTION(inc_loop_up) + .ent inc_loop_up // Input in $4,$5, Output in $2 +ilu1: lw $12,($4) // x = *ptr + subu $5,1 // count-- + addu $12,1 // x++; + sw $12,($4) // *ptr = x + addu $4,4 // ptr++ + bnez $12,ilu3 // if (!(x==0)) ... +inc_loop_up: + bnez $5,ilu1 // until (count==0) + li $2,1 // 1 + j $31 // return +ilu3: move $2,$0 // 0 + j $31 // return + .end inc_loop_up + +// extern uintD sub_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count); + .align 2 + DECLARE_FUNCTION(sub_loop_up) + .ent sub_loop_up // Input in $4,$5,$6,$7, Output in $2 +slu1: // kein Carry + lw $12,($4) // source1 = *sourceptr1 + lw $13,($5) // source2 = *sourceptr2 + addu $4,4 // sourceptr1++ + addu $5,4 // sourceptr2++ + subu $7,1 // count-- + bltu $12,$13,slu2 // if (source1 < source2) [also Carry] ... + subu $12,$13 // dest = source1 - source2 + sw $12,($6) // *destptr = dest + addu $6,4 // destptr++ +sub_loop_up: + bnez $7,slu1 // until (count==0) + move $2,$0 // 0 + j $31 // return +slu2: subu $12,$13 // dest = source1 - source2 + sw $12,($6) // *destptr = dest + addu $6,4 // destptr++ + bnez $7,slu3 // until (count==0) + li $2,-1 // -1 + j $31 // return +slu3: // Hier Carry + lw $12,($4) // source1 = *sourceptr1 + lw $13,($5) // source2 = *sourceptr2 + addu $4,4 // sourceptr1++ + addu $5,4 // sourceptr2++ + subu $7,1 // count-- + bgtu $12,$13,slu4 // if (source1 > source2) [also kein Carry] ... + subu $12,$13 // dest = source1 - source2 + subu $12,1 // - 1 + sw $12,($6) // *destptr = dest + addu $6,4 // destptr++ + bnez $7,slu3 // until (count==0) + li $2,-1 // -1 + j $31 // return +slu4: subu $12,$13 // dest = source1 - source2 + subu $12,1 // - 1 + sw $12,($6) // *destptr = dest + addu $6,4 // destptr++ + bnez $7,slu1 // until (count==0) + move $2,$0 // 0 + j $31 // return + .end sub_loop_up + +// extern uintD subx_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry); + .align 2 + DECLARE_FUNCTION(subx_loop_up) + .ent subx_loop_up // Input in $4,$5,$6,$7, Output in $2 +subx_loop_up: + lw $12,16($sp) // carry + bnez $12,sxlu5 // !(carry==0) ? + b sxlu2 +sxlu1: // kein Carry + lw $12,($4) // source1 = *sourceptr1 + lw $13,($5) // source2 = *sourceptr2 + addu $4,4 // sourceptr1++ + addu $5,4 // sourceptr2++ + subu $7,1 // count-- + bltu $12,$13,sxlu3 // if (source1 < source2) [also Carry] ... + subu $12,$13 // dest = source1 - source2 + sw $12,($6) // *destptr = dest + addu $6,4 // destptr++ +sxlu2: bnez $7,sxlu1 // until (count==0) + move $2,$0 // 0 + j $31 // return +sxlu3: subu $12,$13 // dest = source1 - source2 + sw $12,($6) // *destptr = dest + addu $6,4 // destptr++ + bnez $7,sxlu4 // until (count==0) + li $2,-1 // -1 + j $31 // return +sxlu4: // Hier Carry + lw $12,($4) // source1 = *sourceptr1 + lw $13,($5) // source2 = *sourceptr2 + addu $4,4 // sourceptr1++ + addu $5,4 // sourceptr2++ + subu $7,1 // count-- + bgtu $12,$13,sxlu6 // if (source1 > source2) [also kein Carry] ... + subu $12,$13 // dest = source1 - source2 + subu $12,1 // - 1 + sw $12,($6) // *destptr = dest + addu $6,4 // destptr++ +sxlu5: bnez $7,sxlu4 // until (count==0) + li $2,-1 // -1 + j $31 // return +sxlu6: subu $12,$13 // dest = source1 - source2 + subu $12,1 // - 1 + sw $12,($6) // *destptr = dest + addu $6,4 // destptr++ + bnez $7,sxlu1 // until (count==0) + move $2,$0 // 0 + j $31 // return + .end subx_loop_up + +// extern uintD subfrom_loop_up (uintD* sourceptr, uintD* destptr, uintC count); + .align 2 + DECLARE_FUNCTION(subfrom_loop_up) + .ent subfrom_loop_up // Input in $4,$5,$6,$7, Output in $2 +sflu1: // kein Carry + lw $12,($5) // source1 = *destptr + lw $13,($4) // source2 = *sourceptr + addu $4,4 // sourceptr++ + subu $6,1 // count-- + bltu $12,$13,sflu2 // if (source1 < source2) [also Carry] ... + subu $12,$13 // dest = source1 - source2 + sw $12,($5) // *destptr = dest + addu $5,4 // destptr++ +subfrom_loop_up: + bnez $6,sflu1 // until (count==0) + move $2,$0 // 0 + j $31 // return +sflu2: subu $12,$13 // dest = source1 - source2 + sw $12,($5) // *destptr = dest + addu $5,4 // destptr++ + bnez $6,sflu3 // until (count==0) + li $2,-1 // -1 + j $31 // return +sflu3: // Hier Carry + lw $12,($5) // source1 = *destptr + lw $13,($4) // source2 = *sourceptr + addu $4,4 // sourceptr++ + subu $6,1 // count-- + bgtu $12,$13,sflu4 // if (source1 > source2) [also kein Carry] ... + subu $12,$13 // dest = source1 - source2 + subu $12,1 // - 1 + sw $12,($5) // *destptr = dest + addu $5,4 // destptr++ + bnez $6,sflu3 // until (count==0) + li $2,-1 // -1 + j $31 // return +sflu4: subu $12,$13 // dest = source1 - source2 + subu $12,1 // - 1 + sw $12,($5) // *destptr = dest + addu $5,4 // destptr++ + bnez $6,sflu1 // until (count==0) + move $2,$0 // 0 + j $31 // return + .end subfrom_loop_up + +// extern uintD dec_loop_up (uintD* ptr, uintC count); + .align 2 + DECLARE_FUNCTION(dec_loop_up) + .ent dec_loop_up // Input in $4,$5, Output in $2 +dlu1: lw $12,($4) // x = *ptr + subu $5,1 // count-- + bnez $12,dlu3 // if (!(x==0)) ... + subu $12,1 // x--; + sw $12,($4) // *ptr = x + addu $4,4 // ptr++ +dec_loop_up: + bnez $5,dlu1 // until (count==0) + li $2,-1 // -1 + j $31 // return +dlu3: subu $12,1 // x--; + sw $12,($4) // *ptr = x + move $2,$0 // 0 + j $31 // return + .end dec_loop_up + +// extern uintD neg_loop_up (uintD* ptr, uintC count); + .align 2 + DECLARE_FUNCTION(neg_loop_up) + .ent neg_loop_up // Input in $4,$5, Output in $2 + // erstes Digit /=0 suchen: +nlu1: lw $12,($4) // x = *ptr + subu $5,1 // count-- + bnez $12,nlu3 // if (!(x==0)) ... + addu $4,4 // ptr++ +neg_loop_up: + bnez $5,nlu1 // until (count==0) + move $2,$0 // 0 + j $31 // return +nlu3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys + // 1 Digit negieren: + subu $12,$0,$12 // x = -x + sw $12,($4) // *ptr = x + // alle anderen Digits invertieren: + b nlu5 +nlu4: lw $12,($4) // x = *xptr + subu $5,1 // count-- + nor $12,$0 // x = ~x + sw $12,($4) // *xptr = x +nlu5: addu $4,4 // xptr++ + bnez $5,nlu4 // until (count==0) + li $2,-1 // -1 + j $31 // return + .end neg_loop_up + +#endif + diff --git a/src/base/digitseq/cl_asm_sparc.h b/src/base/digitseq/cl_asm_sparc.h new file mode 100644 index 0000000..35e1acc --- /dev/null +++ b/src/base/digitseq/cl_asm_sparc.h @@ -0,0 +1,11 @@ +// List the contents of cl_asm_sparc.cc. + +#define COPY_LOOPS +#define FILL_LOOPS +#define CLEAR_LOOPS +#define LOG_LOOPS +#define TEST_LOOPS +#define ADDSUB_LOOPS +#define SHIFT_LOOPS +#define MUL_LOOPS +#define DIV_LOOPS diff --git a/src/base/digitseq/cl_asm_sparc64.h b/src/base/digitseq/cl_asm_sparc64.h new file mode 100644 index 0000000..3580996 --- /dev/null +++ b/src/base/digitseq/cl_asm_sparc64.h @@ -0,0 +1,10 @@ +// List the contents of cl_asm_sparc64.cc. + +#define COPY_LOOPS +#define FILL_LOOPS +#define CLEAR_LOOPS +#define LOG_LOOPS +#define TEST_LOOPS +#define ADDSUB_LOOPS +#define SHIFT_LOOPS +#define MUL_LOOPS diff --git a/src/base/digitseq/cl_asm_sparc64_.cc b/src/base/digitseq/cl_asm_sparc64_.cc new file mode 100644 index 0000000..e4acced --- /dev/null +++ b/src/base/digitseq/cl_asm_sparc64_.cc @@ -0,0 +1,2556 @@ +// Externe Routinen zu ARILEV1.D +// Prozessor: SPARC 64-bit +// Compiler: GNU-C oder ... +// Parameter-Übergabe: in Registern %o0-%o5. +// Parameter-Übergabe: in Registern %o0-%o5. +// Argumente vom Typ uint8, uint16, uint32 sind bereits vom Aufrufer zu +// uint64 umgewandelt worden (zero-extend, "srl reg,0,reg"). +// Argumente vom Typ sint8, sint16, sint32 sind bereits vom Aufrufer zu +// sint64 umgewandelt worden (sign-extend, "sra reg,0,reg"). +// Ergebnisse vom Typ uint8, uint16, uint32 müssen vor Rückgabe zu uint64 +// umgewandelt werden (zero-extend, "srl reg,0,reg"). +// Ergebnisse vom Typ sint8, sint16, sint32 müssen vor Rückgabe zu sint64 +// umgewandelt werden (sign-extend, "sra reg,0,reg"). +// Einstellungen: intCsize=32, intDsize=32. + +#ifdef ASM_UNDERSCORE + #define C(entrypoint) _##entrypoint +#else + #define C(entrypoint) entrypoint +#endif + +// When this file is compiled into a shared library, ELF linkers need to +// know which symbols are functions. +#if defined(__NetBSD__) || defined(__OpenBSD__) + #define DECLARE_FUNCTION(name) .type C(name),@function +#elif defined(__svr4__) || defined(__ELF__) + // Some preprocessors keep the backslash in place, some don't. + // Some complain about the # being not in front of an ANSI C macro. + // Therefore we use a dollar, which will be sed-converted to # later. + #define DECLARE_FUNCTION(name) .type C(name),$function +#else + #define DECLARE_FUNCTION(name) +#endif + + // Indikatoren für Anweisungen (Instruktionen) in Delay-Slots + // (diese werden VOR der vorigen Instruktion ausgeführt): + #define _ // Instruktion, die stets ausgeführt wird + #define __ // Instruktion, die nur im Sprung-Fall ausgeführt wird + // Abkürzungen für Anweisungen: + #define ret jmp %i7+8 // return from subroutine + #define retl jmp %o7+8 // return from leaf subroutine (no save/restore) + + .seg "text" + + .global C(mulu16_),C(mulu32_),C(mulu32_unchecked),C(mulu64_) + .global C(divu_6432_3232_),C(divu_3216_1616_) + .global C(copy_loop_up),C(copy_loop_down),C(fill_loop_up),C(fill_loop_down) + .global C(clear_loop_up),C(clear_loop_down) + .global C(test_loop_up),C(test_loop_down) + .global C(xor_loop_up),C(compare_loop_up),C(shiftleftcopy_loop_up),C(shiftxor_loop_up) +#if CL_DS_BIG_ENDIAN_P + .global C(or_loop_up),C(and_loop_up),C(eqv_loop_up) + .global C(nand_loop_up),C(nor_loop_up),C(andc2_loop_up),C(orc2_loop_up) + .global C(not_loop_up) + .global C(and_test_loop_up) + .global C(add_loop_down),C(addto_loop_down),C(inc_loop_down) + .global C(sub_loop_down),C(subx_loop_down),C(subfrom_loop_down),C(dec_loop_down) + .global C(neg_loop_down) + .global C(shift1left_loop_down),C(shiftleft_loop_down),C(shiftleftcopy_loop_down) + .global C(shift1right_loop_up),C(shiftright_loop_up),C(shiftrightsigned_loop_up),C(shiftrightcopy_loop_up) + .global C(mulusmall_loop_down),C(mulu_loop_down),C(muluadd_loop_down),C(mulusub_loop_down) +#else + .global C(or_loop_down),C(xor_loop_down),C(and_loop_down),C(eqv_loop_down) + .global C(nand_loop_down),C(nor_loop_down),C(andc2_loop_down),C(orc2_loop_down) + .global C(not_loop_down) + .global C(and_test_loop_down),C(compare_loop_down) + .global C(add_loop_up),C(addto_loop_up),C(inc_loop_up) + .global C(sub_loop_up),C(subx_loop_up),C(subfrom_loop_up),C(dec_loop_up) + .global C(neg_loop_up) + .global C(shift1left_loop_up),C(shiftleft_loop_up) + .global C(shift1right_loop_down),C(shiftright_loop_down),C(shiftrightsigned_loop_down),C(shiftrightcopy_loop_down) + .global C(mulusmall_loop_up),C(mulu_loop_up),C(muluadd_loop_up),C(mulusub_loop_up) +#endif + +#define LOOP_TYPE 1 // 1: Standard-Schleifen + // 2: Schleifen ohne Pointer, nur mit Zähler +#define STANDARD_LOOPS (LOOP_TYPE==1) +#define COUNTER_LOOPS (LOOP_TYPE==2) + +// extern uint32 mulu16_ (uint16 arg1, uint16 arg2); +// ergebnis := arg1*arg2. + DECLARE_FUNCTION(mulu16_) +C(mulu16_:) // Input in %o0,%o1, Output in %o0 + umul %o0,%o1,%o2 + retl + _ srl %o2,0,%o0 + +// extern struct { uint32 lo; uint32 hi; } mulu32_ (uint32 arg1, uint32 arg2); +// 2^32*hi+lo := arg1*arg2. + DECLARE_FUNCTION(mulu32_) +C(mulu32_:) // Input in %o0,%o1, Output in %o0,%g1 + umul %o0,%o1,%o2 + rd %y,%g1 + retl + _ srl %o2,0,%o0 + +// extern uint32 mulu32_unchecked (uint32 x, uint32 y); +// ergebnis := arg1*arg2 < 2^32. + DECLARE_FUNCTION(mulu32_unchecked) +C(mulu32_unchecked:) // Input in %o0,%o1, Output in %o0 + umul %o0,%o1,%o2 + retl + _ srl %o2,0,%o0 + +// extern struct { uint64 lo; uint64 hi; } mulu64_ (uint64 arg1, uint64 arg2); +// 2^64*hi+lo := arg1*arg2. + DECLARE_FUNCTION(mulu64_) +C(mulu64_:) // Input in %o0,%o1, Output in %o0,%g2 + srlx %o0,32,%o2 // %o2 = high32(arg1) + srl %o0,0,%o0 // %o0 = low32(arg1) + srlx %o1,32,%o3 // %o3 = high32(arg2) + srl %o1,0,%o1 // %o1 = low32(arg2) + mulx %o2,%o3,%g2 // high part + mulx %o2,%o1,%o2 // first mid part + mulx %o0,%o3,%o3 // second mid part + addcc %o2,%o3,%o2 // sum of mid parts + mov 0,%o3 + movcs %xcc,1,%o3 // carry from sum of mid parts + sllx %o3,32,%o3 + add %g2,%o3,%g2 // add to high part + srlx %o2,32,%o3 + add %g2,%o3,%g2 // add high32(midparts) to high part + mulx %o0,%o1,%o0 // low part + sllx %o2,32,%o2 + addcc %o0,%o2,%o0 // add low32(midparts)*2^32 to low part + add %g2,1,%o3 + retl + _ movcs %xcc,%o3,%g2 // add carry to high part + +// extern struct { uint32 q; uint32 r; } divu_6432_3232_ (uint32 xhi, uint32 xlo, uint32 y); +// x = 2^32*xhi+xlo = q*y+r schreiben. Sei bekannt, daß 0 <= x < 2^32*y . + DECLARE_FUNCTION(divu_6432_3232_) +C(divu_6432_3232_:) // Input in %o0,%o1,%o2, Output in %o0,%g1 + wr %o0,%g0,%y + udiv %o1,%o2,%o0 // x durch y dividieren, %o0 := q + umul %o0,%o2,%g1 // %g1 := (q*y) mod 2^32 + sub %o1,%g1,%g1 // %g1 := (xlo-q*y) mod 2^32 = r + retl + _ srl %o0,0,%o0 + +// extern struct { uint16 q; uint16 r; } divu_3216_1616_ (uint32 x, uint16 y); +// x = q*y+r schreiben. Sei bekannt, daß 0 <= x < 2^16*y . + DECLARE_FUNCTION(divu_3216_1616_) +C(divu_3216_1616_:) // Input in %o0,%o1, Output in %o0 (Rest und Quotient). + wr %g0,%g0,%y + udiv %o0,%o1,%o2 // dividieren, Quotient nach %o2 +#if 0 // Who says that %y has some meaningful contents after `udiv' ?? + rd %y,%g1 // Rest aus %y +#else + umul %o2,%o1,%g1 // %g1 := (q*y) mod 2^32 + sub %o0,%g1,%g1 // %g1 := (x-q*y) mod 2^32 = r +#endif + sll %g1,16,%g1 // in die oberen 16 Bit schieben + or %o2,%g1,%o0 + retl + _ srl %o0,0,%o0 + +#if !defined(__GNUC__) + .global C(_get_g1) +// extern uint32 _get_g1 (void); + DECLARE_FUNCTION(_get_g1) +C(_get_g1:) + retl + _ srl %g1,0,%o0 +#endif + +#if !defined(__GNUC__) + .global C(_get_g2) +// extern uint64 _get_g2 (void); + DECLARE_FUNCTION(_get_g2) +C(_get_g2:) + retl + _ mov %g2,%o0 +#endif + +// extern uintD* copy_loop_up (uintD* sourceptr, uintD* destptr, uintC count); + DECLARE_FUNCTION(copy_loop_up) +C(copy_loop_up:) // Input in %o0,%o1,%o2, Output in %o0 +#if STANDARD_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ nop +1: ldx [%o0],%o3 + add %o0,8,%o0 + stx %o3,[%o1] + subcc %o2,1,%o2 + bne,pt %xcc,1b + _ add %o1,8,%o1 +2: retl + _ mov %o1,%o0 +#endif +#if COUNTER_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sub %o1,8,%o1 + sub %g0,%o2,%o2 // %o2 = -count + sllx %o2,3,%o2 // %o2 = -8*count + sub %o0,%o2,%o0 // %o0 = &sourceptr[count] + sub %o1,%o2,%o1 // %o1 = &destptr[count-1] +1: ldx [%o0+%o2],%o3 // nächstes Digit holen + addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen + bne,pt %xcc,1b + _ stx %o3,[%o1+%o2] // Digit ablegen +2: retl + _ add %o1,8,%o0 +#endif + +// extern uintD* copy_loop_down (uintD* sourceptr, uintD* destptr, uintC count); + DECLARE_FUNCTION(copy_loop_down) +C(copy_loop_down:) // Input in %o0,%o1,%o2, Output in %o0 +#if STANDARD_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sub %o0,8,%o0 +1: ldx [%o0],%o3 + sub %o1,8,%o1 + stx %o3,[%o1] + subcc %o2,1,%o2 + bne,pt %xcc,1b + _ sub %o0,8,%o0 +2: retl + _ mov %o1,%o0 +#endif +#if COUNTER_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sub %o0,8,%o0 + sllx %o2,3,%o2 // %o2 = 8*count + sub %o0,%o2,%o0 // %o0 = &sourceptr[-count-1] + sub %o1,%o2,%o1 // %o1 = &destptr[-count] +1: ldx [%o0+%o2],%o3 // nächstes Digit holen + subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen + bne,pt %xcc,1b + _ stx %o3,[%o1+%o2] // Digit ablegen +2: retl + _ mov %o1,%o0 +#endif + +// extern uintD* fill_loop_up (uintD* destptr, uintC count, uintD filler); + DECLARE_FUNCTION(fill_loop_up) +C(fill_loop_up:) // Input in %o0,%o1,%o2, Output in %o0 +#if STANDARD_LOOPS +// srl %o1,0,%o1 // zero-extend %o1 = count + brz,pn %o1,2f + _ nop +1: stx %o2,[%o0] + subcc %o1,1,%o1 + bne,pt %xcc,1b + _ add %o0,8,%o0 +2: retl + _ nop +#endif +#if COUNTER_LOOPS +// srl %o1,0,%o1 // zero-extend %o1 = count + brz,pn %o1,2f + _ sub %o0,8,%o0 + sub %g0,%o1,%o1 // %o1 = -count + sllx %o1,3,%o1 // %o1 = -8*count + sub %o0,%o1,%o0 // %o0 = &destptr[count-1] +1: addcc %o1,8,%o1 // Zähler "erniedrigen", Pointer erhöhen + bne,pt %xcc,1b + _ stx %o2,[%o0+%o1] // Digit ablegen +2: retl + _ add %o0,8,%o0 +#endif + +// extern uintD* fill_loop_down (uintD* destptr, uintC count, uintD filler); + DECLARE_FUNCTION(fill_loop_down) +C(fill_loop_down:) // Input in %o0,%o1,%o2, Output in %o0 +#if STANDARD_LOOPS +// srl %o1,0,%o1 // zero-extend %o1 = count + brz,pn %o1,2f + _ sub %o0,8,%o0 +1: stx %o2,[%o0] + subcc %o1,1,%o1 + bne,pt %xcc,1b + _ sub %o0,8,%o0 +2: retl + _ add %o0,8,%o0 +#endif +#if COUNTER_LOOPS +// srl %o1,0,%o1 // zero-extend %o1 = count + brz,pn %o1,2f + _ sllx %o1,3,%o1 // %o1 = 8*count + sub %o0,%o1,%o0 // %o0 = &destptr[-count] +1: subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen + bne,pt %xcc,1b + _ stx %o2,[%o0+%o1] // Digit ablegen +2: retl + _ nop +#endif + +// extern uintD* clear_loop_up (uintD* destptr, uintC count); + DECLARE_FUNCTION(clear_loop_up) +C(clear_loop_up:) // Input in %o0,%o1, Output in %o0 +#if STANDARD_LOOPS +// srl %o1,0,%o1 // zero-extend %o1 = count + brz,pn %o1,2f + _ nop +1: stx %g0,[%o0] + subcc %o1,1,%o1 + bne,pt %xcc,1b + _ add %o0,8,%o0 +2: retl + _ nop +#endif +#if COUNTER_LOOPS +// srl %o1,0,%o1 // zero-extend %o1 = count + brz,pn %o1,2f + _ sub %o0,8,%o0 + sub %g0,%o1,%o1 // %o1 = -count + sllx %o1,3,%o1 // %o1 = -8*count + sub %o0,%o1,%o0 // %o0 = &destptr[count-1] +1: addcc %o1,8,%o1 // Zähler "erniedrigen", Pointer erhöhen + bne,pt %xcc,1b + _ stx %g0,[%o0+%o1] // Digit 0 ablegen +2: retl + _ add %o0,8,%o0 +#endif + +// extern uintD* clear_loop_down (uintD* destptr, uintC count); + DECLARE_FUNCTION(clear_loop_down) +C(clear_loop_down:) // Input in %o0,%o1, Output in %o0 +#if STANDARD_LOOPS +// srl %o1,0,%o1 // zero-extend %o1 = count + brz,pn %o1,2f + _ sub %o0,8,%o0 +1: stx %g0,[%o0] + subcc %o1,1,%o1 + bne,pt %xcc,1b + _ sub %o0,8,%o0 +2: retl + _ add %o0,8,%o0 +#endif +#if COUNTER_LOOPS +// srl %o1,0,%o1 // zero-extend %o1 = count + brz,pn %o1,2f + _ sllx %o1,3,%o1 // %o1 = 8*count + sub %o0,%o1,%o0 // %o0 = &destptr[-count] +1: subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen + bne,pt %xcc,1b + _ stx %g0,[%o0+%o1] // Digit 0 ablegen +2: retl + _ nop +#endif + +// extern boolean test_loop_up (uintD* ptr, uintC count); + DECLARE_FUNCTION(test_loop_up) +C(test_loop_up:) // Input in %o0,%o1, Output in %o0 +#if STANDARD_LOOPS +// srl %o1,0,%o1 // zero-extend %o1 = count + brz,pn %o1,2f + _ nop + ldx [%o0],%o2 +1: add %o0,8,%o0 + brnz,pn %o2,3f + _ subcc %o1,1,%o1 + bne,a,pt %xcc,1b + __ ldx [%o0],%o2 +2: retl + _ mov 0,%o0 +3: retl + _ mov 1,%o0 +#endif +#if COUNTER_LOOPS +// srl %o1,0,%o1 // zero-extend %o1 = count + brz,pn %o1,2f + _ sub %g0,%o1,%o1 // %o1 = -count + sllx %o1,3,%o1 // %o1 = -8*count + sub %o0,%o1,%o0 // %o0 = &ptr[count] + ldx [%o0+%o1],%o2 // nächstes Digit holen +1: brnz,pn %o2,3f // testen + _ addcc %o1,8,%o1 // Zähler "erniedrigen", Pointer erhöhen + bne,a,pt %xcc,1b + __ ldx [%o0+%o1],%o2 // nächstes Digit holen +2: retl + _ mov 0,%o0 +3: retl + _ mov 1,%o0 +#endif + +// extern boolean test_loop_down (uintD* ptr, uintC count); + DECLARE_FUNCTION(test_loop_down) +C(test_loop_down:) // Input in %o0,%o1, Output in %o0 +#if STANDARD_LOOPS +// srl %o1,0,%o1 // zero-extend %o1 = count + brz,pn %o1,2f + _ sub %o0,8,%o0 + ldx [%o0],%o2 +1: sub %o0,8,%o0 + brnz,pn %o2,3f + _ subcc %o1,1,%o1 + bne,a,pt %xcc,1b + __ ldx [%o0],%o2 +2: retl + _ mov 0,%o0 +3: retl + _ mov 1,%o0 +#endif +#if COUNTER_LOOPS +// srl %o1,0,%o1 // zero-extend %o1 = count + brz,pn %o1,2f + _ sllx %o1,3,%o1 // %o1 = 8*count + sub %o0,%o1,%o0 // %o0 = &ptr[-count] + sub %o1,8,%o1 + ldx [%o0+%o1],%o2 // nächstes Digit holen +1: brnz,pn %o2,3f // testen + _ subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen + bcc,a,pt %xcc,1b + __ ldx [%o0+%o1],%o2 // nächstes Digit holen +2: retl + _ mov 0,%o0 +3: retl + _ mov 1,%o0 +#endif + +#if CL_DS_BIG_ENDIAN_P + +// extern void or_loop_up (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(or_loop_up) +C(or_loop_up:) // Input in %o0,%o1,%o2 +#if STANDARD_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr +1: ldx [%o0],%o3 // *xptr + ldx [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + or %o3,%o4,%o3 // verknüpfen + stx %o3,[%o0] // =: *xptr + bne,pt %xcc,1b + _ add %o0,8,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sub %o0,8,%o0 + sub %g0,%o2,%o2 // %o2 = -count + sllx %o2,3,%o2 // %o2 = -8*count + sub %o0,%o2,%o0 // %o0 = &xptr[count-1] + sub %o1,%o2,%o1 // %o1 = &yptr[count] +1: ldx [%o1+%o2],%o3 // nächstes Digit holen + addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen + ldx [%o0+%o2],%o4 // noch ein Digit holen + or %o4,%o3,%o3 // beide verknüpfen + bne,pt %xcc,1b + _ stx %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +#endif + +// extern void xor_loop_up (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(xor_loop_up) +C(xor_loop_up:) // Input in %o0,%o1,%o2 +#if STANDARD_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr +1: ldx [%o0],%o3 // *xptr + ldx [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + xor %o3,%o4,%o3 // verknüpfen + stx %o3,[%o0] // =: *xptr + bne,pt %xcc,1b + _ add %o0,8,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sub %o0,8,%o0 + sub %g0,%o2,%o2 // %o2 = -count + sllx %o2,3,%o2 // %o2 = -8*count + sub %o0,%o2,%o0 // %o0 = &xptr[count-1] + sub %o1,%o2,%o1 // %o1 = &yptr[count] +1: ldx [%o1+%o2],%o3 // nächstes Digit holen + addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen + ldx [%o0+%o2],%o4 // noch ein Digit holen + xor %o4,%o3,%o3 // beide verknüpfen + bne,pt %xcc,1b + _ stx %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +#if CL_DS_BIG_ENDIAN_P + +// extern void and_loop_up (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(and_loop_up) +C(and_loop_up:) // Input in %o0,%o1,%o2 +#if STANDARD_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr +1: ldx [%o0],%o3 // *xptr + ldx [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + and %o3,%o4,%o3 // verknüpfen + stx %o3,[%o0] // =: *xptr + bne,pt %xcc,1b + _ add %o0,8,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sub %o0,8,%o0 + sub %g0,%o2,%o2 // %o2 = -count + sllx %o2,3,%o2 // %o2 = -8*count + sub %o0,%o2,%o0 // %o0 = &xptr[count-1] + sub %o1,%o2,%o1 // %o1 = &yptr[count] +1: ldx [%o1+%o2],%o3 // nächstes Digit holen + addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen + ldx [%o0+%o2],%o4 // noch ein Digit holen + and %o4,%o3,%o3 // beide verknüpfen + bne,pt %xcc,1b + _ stx %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +// extern void eqv_loop_up (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(eqv_loop_up) +C(eqv_loop_up:) // Input in %o0,%o1,%o2 +#if STANDARD_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr +1: ldx [%o0],%o3 // *xptr + ldx [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + xnor %o3,%o4,%o3 // verknüpfen + stx %o3,[%o0] // =: *xptr + bne,pt %xcc,1b + _ add %o0,8,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sub %o0,8,%o0 + sub %g0,%o2,%o2 // %o2 = -count + sllx %o2,3,%o2 // %o2 = -8*count + sub %o0,%o2,%o0 // %o0 = &xptr[count-1] + sub %o1,%o2,%o1 // %o1 = &yptr[count] +1: ldx [%o1+%o2],%o3 // nächstes Digit holen + addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen + ldx [%o0+%o2],%o4 // noch ein Digit holen + xnor %o4,%o3,%o3 // beide verknüpfen + bne,pt %xcc,1b + _ stx %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +// extern void nand_loop_up (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(nand_loop_up) +C(nand_loop_up:) // Input in %o0,%o1,%o2 +#if STANDARD_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr +1: ldx [%o0],%o3 // *xptr + ldx [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + and %o3,%o4,%o3 // verknüpfen + xnor %g0,%o3,%o3 + stx %o3,[%o0] // =: *xptr + bne,pt %xcc,1b + _ add %o0,8,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sub %o0,8,%o0 + sub %g0,%o2,%o2 // %o2 = -count + sllx %o2,3,%o2 // %o2 = -8*count + sub %o0,%o2,%o0 // %o0 = &xptr[count-1] + sub %o1,%o2,%o1 // %o1 = &yptr[count] +1: ldx [%o1+%o2],%o3 // nächstes Digit holen + addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen + ldx [%o0+%o2],%o4 // noch ein Digit holen + and %o4,%o3,%o3 // beide verknüpfen + xnor %g0,%o3,%o3 + bne,pt %xcc,1b + _ stx %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +// extern void nor_loop_up (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(nor_loop_up) +C(nor_loop_up:) // Input in %o0,%o1,%o2 +#if STANDARD_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr +1: ldx [%o0],%o3 // *xptr + ldx [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + or %o3,%o4,%o3 // verknüpfen + xnor %g0,%o3,%o3 + stx %o3,[%o0] // =: *xptr + bne,pt %xcc,1b + _ add %o0,8,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sub %o0,8,%o0 + sub %g0,%o2,%o2 // %o2 = -count + sllx %o2,3,%o2 // %o2 = -8*count + sub %o0,%o2,%o0 // %o0 = &xptr[count-1] + sub %o1,%o2,%o1 // %o1 = &yptr[count] +1: ldx [%o1+%o2],%o3 // nächstes Digit holen + addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen + ldx [%o0+%o2],%o4 // noch ein Digit holen + or %o4,%o3,%o3 // beide verknüpfen + xnor %g0,%o3,%o3 + bne,pt %xcc,1b + _ stx %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +// extern void andc2_loop_up (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(andc2_loop_up) +C(andc2_loop_up:) // Input in %o0,%o1,%o2 +#if STANDARD_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr +1: ldx [%o0],%o3 // *xptr + ldx [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + andn %o3,%o4,%o3 // verknüpfen + stx %o3,[%o0] // =: *xptr + bne,pt %xcc,1b + _ add %o0,8,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sub %o0,8,%o0 + sub %g0,%o2,%o2 // %o2 = -count + sllx %o2,3,%o2 // %o2 = -8*count + sub %o0,%o2,%o0 // %o0 = &xptr[count-1] + sub %o1,%o2,%o1 // %o1 = &yptr[count] +1: ldx [%o1+%o2],%o3 // nächstes Digit holen + addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen + ldx [%o0+%o2],%o4 // noch ein Digit holen + andn %o4,%o3,%o3 // beide verknüpfen + bne,pt %xcc,1b + _ stx %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +// extern void orc2_loop_up (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(orc2_loop_up) +C(orc2_loop_up:) // Input in %o0,%o1,%o2 +#if STANDARD_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr +1: ldx [%o0],%o3 // *xptr + ldx [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + orn %o3,%o4,%o3 // verknüpfen + stx %o3,[%o0] // =: *xptr + bne,pt %xcc,1b + _ add %o0,8,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sub %o0,8,%o0 + sub %g0,%o2,%o2 // %o2 = -count + sllx %o2,3,%o2 // %o2 = -8*count + sub %o0,%o2,%o0 // %o0 = &xptr[count-1] + sub %o1,%o2,%o1 // %o1 = &yptr[count] +1: ldx [%o1+%o2],%o3 // nächstes Digit holen + addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen + ldx [%o0+%o2],%o4 // noch ein Digit holen + orn %o4,%o3,%o3 // beide verknüpfen + bne,pt %xcc,1b + _ stx %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +// extern void not_loop_up (uintD* xptr, uintC count); + DECLARE_FUNCTION(not_loop_up) +C(not_loop_up:) // Input in %o0,%o1 +#if STANDARD_LOOPS +// srl %o1,0,%o1 // zero-extend %o1 = count + brz,pn %o1,2f + _ nop +1: ldx [%o0],%o2 + subcc %o1,1,%o1 + xnor %g0,%o2,%o2 + stx %o2,[%o0] + bne,pt %xcc,1b + _ add %o0,8,%o0 +2: retl + _ nop +#endif +#if COUNTER_LOOPS +// srl %o1,0,%o1 // zero-extend %o1 = count + brz,pn %o1,2f + _ sub %o0,8,%o0 + sub %g0,%o1,%o1 // %o1 = -count + sllx %o1,3,%o1 // %o1 = -8*count + sub %o0,%o1,%o0 // %o0 = &destptr[count-1] +1: addcc %o1,8,%o1 // Zähler "erniedrigen", Pointer erhöhen + ldx [%o0+%o1],%o2 // nächstes Digit holen + xnor %g0,%o2,%o2 + bne,pt %xcc,1b + _ stx %o2,[%o0+%o1] // Digit ablegen +2: retl + _ nop +#endif + +// extern boolean and_test_loop_up (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(and_test_loop_up) +C(and_test_loop_up:) // Input in %o0,%o1,%o2, Output in %o0 +#if STANDARD_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ nop +1: ldx [%o0],%o3 + ldx [%o1],%o4 + add %o0,8,%o0 + andcc %o3,%o4,%g0 + bne,pn %xcc,3f + _ subcc %o2,1,%o2 + bne,pt %xcc,1b + _ add %o1,8,%o1 +2: retl + _ mov 0,%o0 +3: retl + _ mov 1,%o0 +#endif +#if COUNTER_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sub %g0,%o2,%o2 // %o2 = -count + sllx %o2,3,%o2 // %o2 = -8*count + sub %o0,%o2,%o0 // %o0 = &xptr[count] + sub %o1,%o2,%o1 // %o1 = &yptr[count] + ldx [%o0+%o2],%o3 // nächstes Digit holen +1: ldx [%o1+%o2],%o4 // noch ein Digit holen + andcc %o3,%o4,%g0 // beide verknüpfen + bne,pn %xcc,3f + _ addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen + bne,a,pt %xcc,1b + __ ldx [%o0+%o2],%o3 // nächstes Digit holen +2: retl + _ mov 0,%o0 +3: retl + _ mov 1,%o0 +#endif + +#endif + +// extern cl_signean compare_loop_up (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(compare_loop_up) +C(compare_loop_up:) // Input in %o0,%o1,%o2, Output in %o0 +#if STANDARD_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ nop + ldx [%o0],%o3 +1: ldx [%o1],%o4 + add %o0,8,%o0 + subcc %o3,%o4,%g0 + bne,pn %xcc,3f + _ add %o1,8,%o1 + subcc %o2,1,%o2 + bne,a,pt %xcc,1b + __ ldx [%o0],%o3 +2: retl + _ mov 0,%o0 +3: mov 1,%o0 + movlu %xcc,-1,%o0 + retl + _ sra %o0,0,%o0 // sign-extend %o0 +#endif +#if COUNTER_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sub %g0,%o2,%o2 // %o2 = -count + sllx %o2,3,%o2 // %o2 = -8*count + sub %o0,%o2,%o0 // %o0 = &xptr[count] + sub %o1,%o2,%o1 // %o1 = &yptr[count] + ldx [%o0+%o2],%o3 // nächstes Digit holen +1: ldx [%o1+%o2],%o4 // noch ein Digit holen + subcc %o3,%o4,%g0 // vergleichen + bne,pn %xcc,3f + _ addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen + bne,a,pt %xcc,1b + __ ldx [%o0+%o2],%o3 // nächstes Digit holen +2: retl + _ mov 0,%o0 +3: subcc %o3,%o4,%g0 // nochmals vergleichen + mov 1,%o0 + movlu %xcc,-1,%o0 + retl + _ sra %o0,0,%o0 // sign-extend %o0 +#endif + +#if CL_DS_BIG_ENDIAN_P + +// extern uintD add_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count); + DECLARE_FUNCTION(add_loop_down) +C(add_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0 +#if STANDARD_LOOPS +// srl %o3,0,%o3 // zero-extend %o3 = count + brz,pn %o3,2f + _ mov %g0,%g1 // Carry := 0 + sub %o0,8,%o0 +1: ldx [%o0],%o4 // source1-digit + sub %o1,8,%o1 + ldx [%o1],%o5 // source2-digit + addcc %o4,%g1,%o4 + movcc %xcc,0,%g1 // %g1|%o4 := %o4 + alter Carry %g1 + addcc %o4,%o5,%o4 + movcs %xcc,1,%g1 // %g1|%o4 := %o4 + alter Carry %g1 + %o5 + sub %o2,8,%o2 + stx %o4,[%o2] // Digit ablegen + subcc %o3,1,%o3 + bne,pt %xcc,1b + _ sub %o0,8,%o0 +2: retl + _ mov %g1,%o0 +#endif +#if COUNTER_LOOPS +// srl %o3,0,%o3 // zero-extend %o3 = count + brz,pn %o3,2f + _ mov %g0,%g1 // Carry := 0 + sub %o0,8,%o0 + sub %o1,8,%o1 + sllx %o3,3,%o3 // %o3 = 8*count + sub %o0,%o3,%o0 // %o0 = &sourceptr1[-count-1] + sub %o1,%o3,%o1 // %o1 = &sourceptr2[-count-1] + sub %o2,%o3,%o2 // %o2 = &destptr[-count] +1: ldx [%o0+%o3],%o4 // source1-digit + ldx [%o1+%o3],%o5 // source2-digit + addcc %o4,%g1,%o4 + movcc %xcc,0,%g1 // %g1|%o4 := %o4 + alter Carry %g1 + addcc %o4,%o5,%o4 + movcs %xcc,1,%g1 // %g1|%o4 := %o4 + alter Carry %g1 + %o5 + subcc %o3,8,%o3 + bne,pt %xcc,1b + _ stx %o4,[%o2+%o3] // Digit ablegen +2: retl + _ mov %g1,%o0 +#endif + +// extern uintD addto_loop_down (uintD* sourceptr, uintD* destptr, uintC count); + DECLARE_FUNCTION(addto_loop_down) +C(addto_loop_down:) // Input in %o0,%o1,%o2, Output in %o0 +#if STANDARD_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ mov %g0,%o5 // Carry := 0 + sub %o0,8,%o0 +1: ldx [%o0],%o3 // source-digit + sub %o1,8,%o1 + ldx [%o1],%o4 // dest-digit + addcc %o3,%o5,%o3 + movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5 + addcc %o3,%o4,%o4 + movcs %xcc,1,%o5 // %o5|%o4 := %o3 + alter Carry %o5 + %o4 + stx %o4,[%o1] // Digit ablegen + subcc %o2,1,%o2 + bne,pt %xcc,1b + _ sub %o0,8,%o0 +2: retl + _ mov %o5,%o0 +#endif +#if COUNTER_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ mov %g0,%o5 // Carry := 0 + sub %o0,8,%o0 + sub %o1,8,%o1 + sllx %o2,3,%o2 // %o2 = 8*count + sub %o0,%o2,%o0 // %o0 = &sourceptr[-count-1] + sub %o1,%o2,%o1 // %o1 = &destptr[-count-1] + ldx [%o0+%o2],%o3 // source-digit +1: ldx [%o1+%o2],%o4 // dest-digit + addcc %o3,%o5,%o3 + movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5 + addcc %o3,%o4,%o4 + movcs %xcc,1,%o5 // %o5|%o4 := %o3 + alter Carry %o5 + %o4 + stx %o4,[%o1+%o2] // Digit ablegen + subcc %o2,8,%o2 + bne,a,pt %xcc,1b + __ ldx [%o0+%o2],%o3 // source-digit +2: retl + _ mov %o5,%o0 +#endif + +// extern uintD inc_loop_down (uintD* ptr, uintC count); + DECLARE_FUNCTION(inc_loop_down) +C(inc_loop_down:) // Input in %o0,%o1, Output in %o0 +#if STANDARD_LOOPS +// srl %o1,0,%o1 // zero-extend %o1 = count + brz,pn %o1,2f + _ sub %o0,8,%o0 +1: ldx [%o0],%o2 + addcc %o2,1,%o2 + bne,pn %xcc,3f + _ stx %o2,[%o0] + subcc %o1,1,%o1 + bne,pt %xcc,1b + _ sub %o0,8,%o0 +2: retl + _ mov 1,%o0 +3: retl + _ mov 0,%o0 +#endif +#if COUNTER_LOOPS +// srl %o1,0,%o1 // zero-extend %o1 = count + brz,pn %o1,2f + _ sub %o0,8,%o0 + sllx %o1,3,%o1 // %o1 = 8*count + sub %o0,%o1,%o0 // %o0 = &ptr[-count-1] + ldx [%o0+%o1],%o2 // digit holen +1: addcc %o2,1,%o2 // incrementieren + bne,pn %xcc,3f + _ stx %o2,[%o0+%o1] // ablegen + subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen + bne,a,pt %xcc,1b + __ ldx [%o0+%o1],%o2 +2: retl + _ mov 1,%o0 +3: retl + _ mov 0,%o0 +#endif + +// extern uintD sub_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count); + DECLARE_FUNCTION(sub_loop_down) +C(sub_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0 +#if STANDARD_LOOPS +// srl %o3,0,%o3 // zero-extend %o3 = count + brz,pn %o3,2f + _ mov %g0,%g1 // Carry := 0 + sub %o1,8,%o1 +1: ldx [%o1],%o5 // source2-digit + sub %o0,8,%o0 + ldx [%o0],%o4 // source1-digit + addcc %o5,%g1,%o5 + movcc %xcc,0,%g1 // %g1|%o5 := %o5 + alter Carry %g1 + subcc %o4,%o5,%o4 + movcs %xcc,1,%g1 // %o4-2^64*%g1 := %o4 - %o5 - alter Carry %g1 + sub %o2,8,%o2 + stx %o4,[%o2] // Digit ablegen + subcc %o3,1,%o3 + bne,pt %xcc,1b + _ sub %o1,8,%o1 +2: retl + _ mov %g1,%o0 +#endif +#if COUNTER_LOOPS +// srl %o3,0,%o3 // zero-extend %o3 = count + brz,pn %o3,2f + _ mov %g0,%g1 // Carry := 0 + sub %o0,8,%o0 + sub %o1,8,%o1 + sllx %o3,3,%o3 // %o3 = 8*count + sub %o0,%o3,%o0 // %o0 = &sourceptr1[-count-1] + sub %o1,%o3,%o1 // %o1 = &sourceptr2[-count-1] + sub %o2,%o3,%o2 // %o2 = &destptr[-count] +1: ldx [%o0+%o3],%o4 // source1-digit + ldx [%o1+%o3],%o5 // source2-digit + addcc %o5,%g1,%o5 + movcc %xcc,0,%g1 // %g1|%o5 := %o5 + alter Carry %g1 + subcc %o4,%o5,%o4 + movcs %xcc,1,%g1 // %o4-2^64*%g1 := %o4 - %o5 - alter Carry %g1 + subcc %o3,8,%o3 + bne,pt %xcc,1b + _ stx %o4,[%o2+%o3] // Digit ablegen +2: retl + _ mov %g1,%o0 +#endif + +// extern uintD subx_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry); + DECLARE_FUNCTION(subx_loop_down) +C(subx_loop_down:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1, Output in %o0 +#if STANDARD_LOOPS +// srl %o3,0,%o3 // zero-extend %o3 = count + brz,pn %o3,2f + _ mov %o4,%g1 // Carry (0 oder -1) + sub %o1,8,%o1 +1: ldx [%o1],%o5 // source2-digit + sub %o0,8,%o0 + ldx [%o0],%o4 // source1-digit + subcc %o5,%g1,%o5 + movcc %xcc,0,%g1 // %o5-2^64*%g1 := %o5 - alter Carry %g1 + subcc %o4,%o5,%o4 + movcs %xcc,-1,%g1 // %o4+2^64*%g1 := %o4 - %o5 + alter Carry %g1 + sub %o2,8,%o2 + stx %o4,[%o2] // Digit ablegen + subcc %o3,1,%o3 + bne,pt %xcc,1b + _ sub %o1,8,%o1 +2: retl + _ mov %g1,%o0 +#endif +#if COUNTER_LOOPS +// srl %o3,0,%o3 // zero-extend %o3 = count + brz,pn %o3,2f + _ mov %o4,%g1 // Carry (0 oder -1) + sub %o0,8,%o0 + sub %o1,8,%o1 + sllx %o3,3,%o3 // %o3 = 8*count + sub %o0,%o3,%o0 // %o0 = &sourceptr1[-count-1] + sub %o1,%o3,%o1 // %o1 = &sourceptr2[-count-1] + sub %o2,%o3,%o2 // %o2 = &destptr[-count] +1: ldx [%o1+%o3],%o5 // source2-digit + ldx [%o0+%o3],%o4 // source1-digit + subcc %o5,%g1,%o5 + movcc %xcc,0,%g1 // %o5-2^64*%g1 := %o5 - alter Carry %g1 + subcc %o4,%o5,%o4 + movcs %xcc,-1,%g1 // %o4+2^64*%g1 := %o4 - %o5 + alter Carry %g1 + subcc %o3,8,%o3 + bne,pt %xcc,1b + _ stx %o4,[%o2+%o3] // Digit ablegen +2: retl + _ mov %g1,%o0 +#endif + +// extern uintD subfrom_loop_down (uintD* sourceptr, uintD* destptr, uintC count); + DECLARE_FUNCTION(subfrom_loop_down) +C(subfrom_loop_down:) // Input in %o0,%o1,%o2, Output in %o0 +#if STANDARD_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ mov %g0,%o5 // Carry := 0 + sub %o0,8,%o0 +1: ldx [%o0],%o3 // source-digit + sub %o1,8,%o1 + ldx [%o1],%o4 // dest-digit + addcc %o3,%o5,%o3 + movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5 + subcc %o4,%o3,%o4 + movcs %xcc,1,%o5 // %o4-2^64*%o5 := %o4 - %o3 - alter Carry %o5 + stx %o4,[%o1] // Digit ablegen + subcc %o2,1,%o2 + bne,pt %xcc,1b + _ sub %o0,8,%o0 +2: retl + _ mov %o5,%o0 +#endif +#if COUNTER_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ mov %g0,%o5 // Carry := 0 + sub %o0,8,%o0 + sub %o1,8,%o1 + sllx %o2,3,%o2 // %o2 = 8*count + sub %o0,%o2,%o0 // %o0 = &sourceptr[-count-1] + sub %o1,%o2,%o1 // %o1 = &destptr[-count-1] + ldx [%o0+%o2],%o3 // source-digit +1: ldx [%o1+%o2],%o4 // dest-digit + addcc %o3,%o5,%o3 + movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5 + subcc %o4,%o3,%o4 + movcs %xcc,1,%o5 // %o4-2^64*%o5 := %o4 - %o3 - alter Carry %o5 + stx %o4,[%o1+%o2] // Digit ablegen + subcc %o2,8,%o2 + bne,a,pt %xcc,1b + __ ldx [%o0+%o2],%o3 // source-digit +2: retl + _ mov %o5,%o0 +#endif + +// extern uintD dec_loop_down (uintD* ptr, uintC count); + DECLARE_FUNCTION(dec_loop_down) +C(dec_loop_down:) // Input in %o0,%o1, Output in %o0 +#if STANDARD_LOOPS +// srl %o1,0,%o1 // zero-extend %o1 = count + brz,pn %o1,2f + _ sub %o0,8,%o0 +1: ldx [%o0],%o2 + subcc %o2,1,%o2 + bcc,pn %xcc,3f + _ stx %o2,[%o0] + subcc %o1,1,%o1 + bne,pt %xcc,1b + _ sub %o0,8,%o0 +2: retl + _ mov -1,%o0 +3: retl + _ mov 0,%o0 +#endif +#if COUNTER_LOOPS +// srl %o1,0,%o1 // zero-extend %o1 = count + brz,pn %o1,2f + _ sub %o0,8,%o0 + sllx %o1,3,%o1 // %o1 = 8*count + sub %o0,%o1,%o0 // %o0 = &ptr[-count-1] + ldx [%o0+%o1],%o2 // digit holen +1: subcc %o2,1,%o2 // decrementieren + bcc,pn %xcc,3f + _ stx %o2,[%o0+%o1] // ablegen + subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen + bne,a,pt %xcc,1b + __ ldx [%o0+%o1],%o2 +2: retl + _ mov -1,%o0 +3: retl + _ mov 0,%o0 +#endif + +// extern uintD neg_loop_down (uintD* ptr, uintC count); + DECLARE_FUNCTION(neg_loop_down) +C(neg_loop_down:) // Input in %o0,%o1, Output in %o0 +#if STANDARD_LOOPS +// srl %o1,0,%o1 // zero-extend %o1 = count + // erstes Digit /=0 suchen: + brz,pn %o1,2f + _ sub %o0,8,%o0 +1: ldx [%o0],%o2 + subcc %g0,%o2,%o2 + bne,pn %xcc,3f + _ subcc %o1,1,%o1 + bne,pt %xcc,1b + _ sub %o0,8,%o0 +2: retl + _ mov 0,%o0 +3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys + stx %o2,[%o0] // 1 Digit negieren + // alle anderen Digits invertieren: + be,pn %xcc,5f + _ sub %o0,8,%o0 +4: ldx [%o0],%o2 + subcc %o1,1,%o1 + xnor %g0,%o2,%o2 + stx %o2,[%o0] + bne,pt %xcc,4b + _ sub %o0,8,%o0 +5: retl + _ mov -1,%o0 +#endif +#if COUNTER_LOOPS +// srl %o1,0,%o1 // zero-extend %o1 = count + // erstes Digit /=0 suchen: + brz,pn %o1,2f + _ sub %o0,8,%o0 + sllx %o1,3,%o1 // %o1 = 8*count + sub %o0,%o1,%o0 // %o0 = &ptr[-count-1] + ldx [%o0+%o1],%o2 // digit holen +1: subcc %g0,%o2,%o2 // negieren, testen + bne,pn %xcc,3f + _ subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen + bne,a,pt %xcc,1b + __ ldx [%o0+%o1],%o2 +2: retl + _ mov 0,%o0 +3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys + // alle anderen Digits invertieren: + add %o1,8,%o1 + stx %o2,[%o0+%o1] // ablegen + subcc %o1,8,%o1 + be,pn %xcc,5f + _ nop + ldx [%o0+%o1],%o2 +4: xnor %g0,%o2,%o2 + stx %o2,[%o0+%o1] + subcc %o1,8,%o1 + bne,a,pt %xcc,4b + __ ldx [%o0+%o1],%o2 +5: retl + _ mov -1,%o0 +#endif + +// extern uintD shift1left_loop_down (uintD* ptr, uintC count); + DECLARE_FUNCTION(shift1left_loop_down) +C(shift1left_loop_down:) // Input in %o0,%o1, Output in %o0 +// srl %o1,0,%o1 // zero-extend %o1 = count + brz,pn %o1,2f + _ mov 0,%o3 // Carry := 0 + sub %o0,8,%o0 +1: ldx [%o0],%o2 // Digit + addcc %o2,%o2,%o4 // shiften + add %o4,%o3,%o4 // und carry + srlx %o2,63,%o3 // neues Carry + stx %o4,[%o0] // Digit ablegen + subcc %o1,1,%o1 + bne,pt %xcc,1b + _ sub %o0,8,%o0 +2: retl + _ mov %o3,%o0 + +// extern uintD shiftleft_loop_down (uintD* ptr, uintC count, uintC i, uintD carry); + DECLARE_FUNCTION(shiftleft_loop_down) +C(shiftleft_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0 +// srl %o1,0,%o1 // zero-extend %o1 = count + brz,pn %o1,2f + _ sub %g0,%o2,%g1 // 64-i (mod 64) + sub %o0,8,%o0 +1: ldx [%o0],%o4 // Digit + subcc %o1,1,%o1 + sllx %o4,%o2,%o5 // dessen niedere (64-i) Bits + or %o3,%o5,%o5 // mit dem alten Carry kombinieren + stx %o5,[%o0] // Digit ablegen + srlx %o4,%g1,%o3 // dessen höchste i Bits liefern den neuen Carry + bne,pt %xcc,1b + _ sub %o0,8,%o0 +2: retl + _ mov %o3,%o0 + +// extern uintD shiftleftcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i); + DECLARE_FUNCTION(shiftleftcopy_loop_down) +C(shiftleftcopy_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1,%g2, Output in %o0 +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ mov 0,%o4 // Carry := 0 + sub %g0,%o3,%g1 // 64-i (mod 64) + sub %o0,8,%o0 +1: ldx [%o0],%o5 // Digit + subcc %o2,1,%o2 + sllx %o5,%o3,%g2 // dessen niedere (64-i) Bits + or %o4,%g2,%g2 // mit dem alten Carry kombinieren + sub %o1,8,%o1 + stx %g2,[%o1] // Digit ablegen + srlx %o5,%g1,%o4 // dessen höchste i Bits liefern den neuen Carry + bne,pt %xcc,1b + _ sub %o0,8,%o0 +2: retl + _ mov %o4,%o0 + +// extern uintD shift1right_loop_up (uintD* ptr, uintC count, uintD carry); + DECLARE_FUNCTION(shift1right_loop_up) +C(shift1right_loop_up:) // Input in %o0,%o1,%o2, Output in %o0 +// srl %o1,0,%o1 // zero-extend %o1 = count + brz,pn %o1,2f + _ sllx %o2,63,%o2 // Carry +1: ldx [%o0],%o3 // Digit + subcc %o1,1,%o1 + srlx %o3,1,%o4 // shiften + or %o2,%o4,%o4 // und mit altem Carry kombinieren + stx %o4,[%o0] // und ablegen + sllx %o3,63,%o2 // neuer Carry + bne,pt %xcc,1b + _ add %o0,8,%o0 +2: retl + _ mov %o2,%o0 + +// extern uintD shiftright_loop_up (uintD* ptr, uintC count, uintC i); + DECLARE_FUNCTION(shiftright_loop_up) +C(shiftright_loop_up:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0 +// srl %o1,0,%o1 // zero-extend %o1 = count + sub %g0,%o2,%g1 // 64-i (mod 64) + brz,pn %o1,2f + _ or %g0,%g0,%o3 // Carry := 0 +1: ldx [%o0],%o4 // Digit + subcc %o1,1,%o1 + srlx %o4,%o2,%o5 // shiften + or %o3,%o5,%o5 // und mit altem Carry kombinieren + stx %o5,[%o0] // und ablegen + sllx %o4,%g1,%o3 // neuer Carry + bne,pt %xcc,1b + _ add %o0,8,%o0 +2: retl + _ mov %o3,%o0 + +// extern uintD shiftrightsigned_loop_up (uintD* ptr, uintC count, uintC i); + DECLARE_FUNCTION(shiftrightsigned_loop_up) +C(shiftrightsigned_loop_up:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0 +// srl %o1,0,%o1 // zero-extend %o1 = count + ldx [%o0],%o4 // erstes Digit + sub %g0,%o2,%g1 // 64-i (mod 64) + srax %o4,%o2,%o5 // shiften + stx %o5,[%o0] // und ablegen + sllx %o4,%g1,%o3 // neuer Carry + subcc %o1,1,%o1 + be,pn %xcc,2f + _ add %o0,8,%o0 +1: ldx [%o0],%o4 // Digit + subcc %o1,1,%o1 + srlx %o4,%o2,%o5 // shiften + or %o3,%o5,%o5 // und mit altem Carry kombinieren + stx %o5,[%o0] // und ablegen + sllx %o4,%g1,%o3 // neuer Carry + bne,pt %xcc,1b + _ add %o0,8,%o0 +2: retl + _ mov %o3,%o0 + +// extern uintD shiftrightcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry); + DECLARE_FUNCTION(shiftrightcopy_loop_up) +C(shiftrightcopy_loop_up:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1,%g2, Output in %o0 +// srl %o2,0,%o2 // zero-extend %o2 = count + sub %g0,%o3,%g1 // 64-i (mod 64) + brz,pn %o2,2f + _ sllx %o4,%g1,%g2 // erster Carry +1: ldx [%o0],%o4 // Digit + add %o0,8,%o0 + srlx %o4,%o3,%o5 // shiften + or %g2,%o5,%o5 // und mit altem Carry kombinieren + stx %o5,[%o1] // und ablegen + sllx %o4,%g1,%g2 // neuer Carry + subcc %o2,1,%o2 + bne,pt %xcc,1b + _ add %o1,8,%o1 +2: retl + _ mov %g2,%o0 + +// extern uintD mulusmall_loop_down (uintD digit, uintD* ptr, uintC len, uintD newdigit); + DECLARE_FUNCTION(mulusmall_loop_down) +C(mulusmall_loop_down:) // Input in %o0,%o1,%o2,%o3, Output in %o0, verändert %g1 +// srl %o2,0,%o2 // zero-extend %o2 = len + brz,pn %o2,2f + _ sub %o1,8,%o1 +1: // nächstes Digit [%o1] mit der 6-Bit-Zahl %o0 multiplizieren + // und kleinen Carry %o3 dazu: + ldx [%o1],%o4 + sub %o2,1,%o2 + srlx %o4,32,%o5 // high32(x) + srl %o4,0,%o4 // low32(x) + mulx %o4,%o0,%o4 // low32(x)*digit + mulx %o5,%o0,%o5 // high32(x)*digit + sllx %o5,32,%g1 // low32(high32(x)*digit)*2^32 + add %g1,%o3,%g1 // plus carry + addcc %o4,%g1,%o4 // plus low32(x)*digit + srlx %o5,32,%o3 // high32(high32(x)*digit) + add %o3,1,%g1 + movcs %xcc,%g1,%o3 // neuer Carry + stx %o4,[%o1] // neues Digit ablegen + brnz,pt %o2,1b + _ sub %o1,8,%o1 +2: retl + _ mov %o3,%o0 + +// extern void mulu_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); + DECLARE_FUNCTION(mulu_loop_down) +C(mulu_loop_down:) // Input in %i0,%i1,%i2,%i3 + save %sp,-192,%sp + mov 0,%l0 // Carry + srlx %i0,32,%l1 // %l1 = high32(digit) + srl %i0,0,%l2 // %l2 = low32(digit) + mov 1,%l3 + sllx %l3,32,%l3 // %l3 = 2^32 + sub %i1,%i2,%i1 // %i1 = sourceptr - destptr +1: sub %i2,8,%i2 + ldx [%i1+%i2],%o0 // nächstes Digit + subcc %i3,1,%i3 + // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0 + srlx %o0,32,%o1 + srl %o0,0,%o2 + mulx %l1,%o1,%o3 // high part + mulx %l1,%o2,%o4 // first mid part + mulx %l2,%o1,%o1 // second mid part + mulx %l2,%o2,%o2 // low part + srlx %o2,32,%o5 // low part's upper half + add %o4,%o5,%o4 // add to one of the mid parts, no carry + addcc %o4,%o1,%o4 // add other mid part + add %o3,%l3,%o5 + movcs %xcc,%o5,%o3 // if carry, add 2^32 to the high part + srlx %o4,32,%o5 + sllx %o4,32,%o4 + srl %o2,0,%o2 + add %o2,%o4,%o0 // combine low32(midparts) and low32(lowpart) + addcc %o0,%l0,%o0 // alten Carry addieren + add %o3,%o5,%l0 // add high32(midparts) to high part + add %l0,1,%o5 + movcs %xcc,%o5,%l0 // neuer Carry + // Multiplikation fertig + brnz,pt %i3,1b + _ stx %o0,[%i2] // Low-Digit ablegen + stx %l0,[%i2-8] // letzten Carry ablegen + ret + _ restore + +// extern uintD muluadd_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); + DECLARE_FUNCTION(muluadd_loop_down) +C(muluadd_loop_down:) // Input in %i0,%i1,%i2,%i3, Output in %i0 + save %sp,-192,%sp + mov 0,%l0 // Carry + srlx %i0,32,%l1 // %l1 = high32(digit) + srl %i0,0,%l2 // %l2 = low32(digit) + mov 1,%l3 + sllx %l3,32,%l3 // %l3 = 2^32 + sub %i1,%i2,%i1 // %i1 = sourceptr - destptr +1: sub %i2,8,%i2 + ldx [%i1+%i2],%o0 // nächstes Digit + ldx [%i2],%i4 // *destptr + subcc %i3,1,%i3 + // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0 + srlx %o0,32,%o1 + srl %o0,0,%o2 + mulx %l1,%o1,%o3 // high part + mulx %l1,%o2,%o4 // first mid part + mulx %l2,%o1,%o1 // second mid part + mulx %l2,%o2,%o2 // low part + srlx %o2,32,%o5 // low part's upper half + add %o4,%o5,%o4 // add to one of the mid parts, no carry + addcc %o4,%o1,%o4 // add other mid part + add %o3,%l3,%o5 + movcs %xcc,%o5,%o3 // if carry, add 2^32 to the high part + srlx %o4,32,%o5 + sllx %o4,32,%o4 + srl %o2,0,%o2 + add %o2,%o4,%o0 // combine low32(midparts) and low32(lowpart) + addcc %o0,%l0,%o0 // alten Carry addieren + add %o3,%o5,%l0 // add high32(midparts) to high part + add %l0,1,%o5 + movcs %xcc,%o5,%l0 // neuer Carry + // Multiplikation fertig + addcc %i4,%o0,%o0 // alten *destptr addieren + add %l0,1,%o2 + movcs %xcc,%o2,%l0 // neuer Carry + brnz,pt %i3,1b + _ stx %o0,[%i2] // Low-Digit ablegen + mov %l0,%i0 // letzter Carry + ret + _ restore + +// extern uintD mulusub_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); + DECLARE_FUNCTION(mulusub_loop_down) +C(mulusub_loop_down:) // Input in %i0,%i1,%i2,%i3, Output in %i0 + save %sp,-192,%sp + mov 0,%l0 // Carry + srlx %i0,32,%l1 // %l1 = high32(digit) + srl %i0,0,%l2 // %l2 = low32(digit) + mov 1,%l3 + sllx %l3,32,%l3 // %l3 = 2^32 + sub %i1,%i2,%i1 // %i1 = sourceptr - destptr +1: sub %i2,8,%i2 + ldx [%i1+%i2],%o0 // nächstes Digit + ldx [%i2],%i4 // *destptr + subcc %i3,1,%i3 + // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0 + srlx %o0,32,%o1 + srl %o0,0,%o2 + mulx %l1,%o1,%o3 // high part + mulx %l1,%o2,%o4 // first mid part + mulx %l2,%o1,%o1 // second mid part + mulx %l2,%o2,%o2 // low part + srlx %o2,32,%o5 // low part's upper half + add %o4,%o5,%o4 // add to one of the mid parts, no carry + addcc %o4,%o1,%o4 // add other mid part + add %o3,%l3,%o5 + movcs %xcc,%o5,%o3 // if carry, add 2^32 to the high part + srlx %o4,32,%o5 + sllx %o4,32,%o4 + srl %o2,0,%o2 + add %o2,%o4,%o0 // combine low32(midparts) and low32(lowpart) + addcc %o0,%l0,%o0 // alten Carry addieren + add %o3,%o5,%l0 // add high32(midparts) to high part + add %l0,1,%o5 + movcs %xcc,%o5,%l0 // neuer Carry + // Multiplikation fertig + subcc %i4,%o0,%o0 // vom alten *destptr subtrahieren + add %l0,1,%o2 + movcs %xcc,%o2,%l0 // neuer Carry + brnz,pt %i3,1b + _ stx %o0,[%i2] // Low-Digit ablegen + mov %l0,%i0 // letzter Carry + ret + _ restore + +#endif + +#if !CL_DS_BIG_ENDIAN_P + +// extern void or_loop_down (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(or_loop_down) +C(or_loop_down:) // Input in %o0,%o1,%o2 +#if STANDARD_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr + sub %o0,8,%o0 +1: ldx [%o0],%o3 // *xptr + ldx [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + or %o3,%o4,%o3 // verknüpfen + stx %o3,[%o0] // =: *xptr + bne,pt %xcc,1b + _ sub %o0,8,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sllx %o2,3,%o2 // %o2 = 8*count + sub %o0,%o2,%o0 // %o0 = &xptr[-count] + sub %o1,%o2,%o1 // %o1 = &yptr[-count] +1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen + ldx [%o1+%o2],%o3 // nächstes Digit holen + ldx [%o0+%o2],%o4 // noch ein Digit holen + or %o4,%o3,%o3 // beide verknüpfen + bne,pt %xcc,1b + _ stx %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +// extern void xor_loop_down (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(xor_loop_down) +C(xor_loop_down:) // Input in %o0,%o1,%o2 +#if STANDARD_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr + sub %o0,8,%o0 +1: ldx [%o0],%o3 // *xptr + ldx [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + xor %o3,%o4,%o3 // verknüpfen + stx %o3,[%o0] // =: *xptr + bne,pt %xcc,1b + _ sub %o0,8,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sllx %o2,3,%o2 // %o2 = 8*count + sub %o0,%o2,%o0 // %o0 = &xptr[-count] + sub %o1,%o2,%o1 // %o1 = &yptr[-count] +1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen + ldx [%o1+%o2],%o3 // nächstes Digit holen + ldx [%o0+%o2],%o4 // noch ein Digit holen + xor %o4,%o3,%o3 // beide verknüpfen + bne,pt %xcc,1b + _ stx %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +// extern void and_loop_down (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(and_loop_down) +C(and_loop_down:) // Input in %o0,%o1,%o2 +#if STANDARD_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr + sub %o0,8,%o0 +1: ldx [%o0],%o3 // *xptr + ldx [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + and %o3,%o4,%o3 // verknüpfen + stx %o3,[%o0] // =: *xptr + bne,pt %xcc,1b + _ sub %o0,8,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sllx %o2,3,%o2 // %o2 = 8*count + sub %o0,%o2,%o0 // %o0 = &xptr[-count] + sub %o1,%o2,%o1 // %o1 = &yptr[-count] +1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen + ldx [%o1+%o2],%o3 // nächstes Digit holen + ldx [%o0+%o2],%o4 // noch ein Digit holen + and %o4,%o3,%o3 // beide verknüpfen + bne,pt %xcc,1b + _ stx %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +// extern void eqv_loop_down (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(eqv_loop_down) +C(eqv_loop_down:) // Input in %o0,%o1,%o2 +#if STANDARD_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr + sub %o0,8,%o0 +1: ldx [%o0],%o3 // *xptr + ldx [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + xnor %o3,%o4,%o3 // verknüpfen + stx %o3,[%o0] // =: *xptr + bne,pt %xcc,1b + _ sub %o0,8,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sllx %o2,3,%o2 // %o2 = 8*count + sub %o0,%o2,%o0 // %o0 = &xptr[-count] + sub %o1,%o2,%o1 // %o1 = &yptr[-count] +1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen + ldx [%o1+%o2],%o3 // nächstes Digit holen + ldx [%o0+%o2],%o4 // noch ein Digit holen + xnor %o4,%o3,%o3 // beide verknüpfen + bne,pt %xcc,1b + _ stx %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +// extern void nand_loop_down (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(nand_loop_down) +C(nand_loop_down:) // Input in %o0,%o1,%o2 +#if STANDARD_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr + sub %o0,8,%o0 +1: ldx [%o0],%o3 // *xptr + ldx [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + and %o3,%o4,%o3 // verknüpfen + xnor %g0,%o3,%o3 + stx %o3,[%o0] // =: *xptr + bne,pt %xcc,1b + _ sub %o0,8,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sllx %o2,3,%o2 // %o2 = 8*count + sub %o0,%o2,%o0 // %o0 = &xptr[-count] + sub %o1,%o2,%o1 // %o1 = &yptr[-count] +1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen + ldx [%o1+%o2],%o3 // nächstes Digit holen + ldx [%o0+%o2],%o4 // noch ein Digit holen + and %o4,%o3,%o3 // beide verknüpfen + xnor %g0,%o3,%o3 + bne,pt %xcc,1b + _ stx %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +// extern void nor_loop_down (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(nor_loop_down) +C(nor_loop_down:) // Input in %o0,%o1,%o2 +#if STANDARD_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr + sub %o0,8,%o0 +1: ldx [%o0],%o3 // *xptr + ldx [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + or %o3,%o4,%o3 // verknüpfen + xnor %g0,%o3,%o3 + stx %o3,[%o0] // =: *xptr + bne,pt %xcc,1b + _ sub %o0,8,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sllx %o2,3,%o2 // %o2 = 8*count + sub %o0,%o2,%o0 // %o0 = &xptr[-count] + sub %o1,%o2,%o1 // %o1 = &yptr[-count] +1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen + ldx [%o1+%o2],%o3 // nächstes Digit holen + ldx [%o0+%o2],%o4 // noch ein Digit holen + or %o4,%o3,%o3 // beide verknüpfen + xnor %g0,%o3,%o3 + bne,pt %xcc,1b + _ stx %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +// extern void andc2_loop_down (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(andc2_loop_down) +C(andc2_loop_down:) // Input in %o0,%o1,%o2 +#if STANDARD_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr + sub %o0,8,%o0 +1: ldx [%o0],%o3 // *xptr + ldx [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + andn %o3,%o4,%o3 // verknüpfen + stx %o3,[%o0] // =: *xptr + bne,pt %xcc,1b + _ sub %o0,8,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sllx %o2,3,%o2 // %o2 = 8*count + sub %o0,%o2,%o0 // %o0 = &xptr[-count] + sub %o1,%o2,%o1 // %o1 = &yptr[-count] +1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen + ldx [%o1+%o2],%o3 // nächstes Digit holen + ldx [%o0+%o2],%o4 // noch ein Digit holen + andn %o4,%o3,%o3 // beide verknüpfen + bne,pt %xcc,1b + _ stx %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +// extern void orc2_loop_down (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(orc2_loop_down) +C(orc2_loop_down:) // Input in %o0,%o1,%o2 +#if STANDARD_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr + sub %o0,8,%o0 +1: ldx [%o0],%o3 // *xptr + ldx [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + orn %o3,%o4,%o3 // verknüpfen + stx %o3,[%o0] // =: *xptr + bne,pt %xcc,1b + _ sub %o0,8,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sllx %o2,3,%o2 // %o2 = 8*count + sub %o0,%o2,%o0 // %o0 = &xptr[-count] + sub %o1,%o2,%o1 // %o1 = &yptr[-count] +1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen + ldx [%o1+%o2],%o3 // nächstes Digit holen + ldx [%o0+%o2],%o4 // noch ein Digit holen + orn %o4,%o3,%o3 // beide verknüpfen + bne,pt %xcc,1b + _ stx %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +// extern void not_loop_down (uintD* xptr, uintC count); + DECLARE_FUNCTION(not_loop_down) +C(not_loop_down:) // Input in %o0,%o1 +#if STANDARD_LOOPS +// srl %o1,0,%o1 // zero-extend %o1 = count + brz,pn %o1,2f + _ sub %o0,8,%o0 +1: ldx [%o0],%o2 + subcc %o1,1,%o1 + xnor %g0,%o2,%o2 + stx %o2,[%o0] + bne,pt %xcc,1b + _ sub %o0,8,%o0 +2: retl + _ nop +#endif +#if COUNTER_LOOPS +// srl %o1,0,%o1 // zero-extend %o1 = count + brz,pn %o1,2f + _ sllx %o1,3,%o1 // %o1 = 8*count + sub %o0,%o1,%o0 // %o0 = &destptr[-count] +1: subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen + ldx [%o0+%o1],%o2 // nächstes Digit holen + xnor %g0,%o2,%o2 + bne,pt %xcc,1b + _ stx %o2,[%o0+%o1] // Digit ablegen +2: retl + _ nop +#endif + +// extern boolean and_test_loop_down (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(and_test_loop_down) +C(and_test_loop_down:) // Input in %o0,%o1,%o2, Output in %o0 +#if STANDARD_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,4f + _ sub %o0,8,%o0 +1: ldx [%o0],%o3 + sub %o1,8,%o1 + ldx [%o1],%o4 + subcc %o2,1,%o2 + be,pn %xcc,3f + _ andcc %o3,%o4,%g0 + be,pt %xcc,1b + _ sub %o0,8,%o0 +2: retl + _ mov 1,%o0 +3: bne 2b + _ nop +4: retl + _ mov 0,%o0 +#endif +#if COUNTER_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + sllx %o2,3,%o2 // %o2 = 8*count + sub %o0,%o2,%o0 // %o0 = &xptr[-count] + sub %o1,%o2,%o1 // %o1 = &yptr[-count] + subcc %o2,8,%o2 + bcs,pn %xcc,2f + _ nop + ldx [%o0+%o2],%o3 // nächstes Digit holen +1: ldx [%o1+%o2],%o4 // noch ein Digit holen + andcc %o3,%o4,%g0 // beide verknüpfen + bne,pn %xcc,3f + _ subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen + bcc,a,pt %xcc,1b + __ ldx [%o0+%o2],%o3 // nächstes Digit holen +2: retl + _ mov 0,%o0 +3: retl + _ mov 1,%o0 +#endif + +// extern cl_signean compare_loop_down (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(compare_loop_down) +C(compare_loop_down:) // Input in %o0,%o1,%o2, Output in %o0 +#if STANDARD_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ nop +1: ldx [%o0-8],%o3 + ldx [%o1-8],%o4 + subcc %o3,%o4,%g0 + bne,pn %xcc,3f + _ sub %o0,8,%o0 + subcc %o2,1,%o2 + bne,pn %xcc,1b + _ sub %o1,8,%o1 +2: retl + _ mov 0,%o0 +3: mov 1,%o0 + movlu %xcc,-1,%o0 + retl + _ sra %o0,0,%o0 // sign-extend %o0 +#endif +#if COUNTER_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + sllx %o2,3,%o2 // %o2 = 8*count + sub %o0,%o2,%o0 // %o0 = &xptr[-count] + sub %o1,%o2,%o1 // %o1 = &yptr[-count] + subcc %o2,8,%o2 + bcs,pn %xcc,4f + _ nop + ldx [%o0+%o2],%o3 // nächstes Digit holen +1: ldx [%o1+%o2],%o4 // noch ein Digit holen + subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen + bcs,pn %xcc,3f + _ subcc %o3,%o4,%g0 // vergleichen + be,a,pt %xcc,1b + __ ldx [%o0+%o2],%o3 // nächstes Digit holen +2: mov 1,%o0 + movlu %xcc,-1,%o0 + retl + _ sra %o0,0,%o0 // sign-extend %o0 +3: bne 2b + _ nop +4: retl + _ mov 0,%o0 +#endif + +// extern uintD add_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count); + DECLARE_FUNCTION(add_loop_up) +C(add_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0 +#if STANDARD_LOOPS +// srl %o3,0,%o3 // zero-extend %o3 = count + brz,pn %o3,2f + _ mov %g0,%g1 // Carry := 0 +1: ldx [%o0],%o4 // source1-digit + add %o0,8,%o0 + ldx [%o1],%o5 // source2-digit + add %o1,8,%o1 + addcc %o4,%g1,%o4 + movcc %xcc,0,%g1 // %g1|%o4 := %o4 + alter Carry %g1 + addcc %o4,%o5,%o4 + movcs %xcc,1,%g1 // %g1|%o4 := %o4 + alter Carry %g1 + %o5 + stx %o4,[%o2] // Digit ablegen + subcc %o3,1,%o3 + bne,pt %xcc,1b + _ add %o2,8,%o2 +2: retl + _ mov %g1,%o0 +#endif +#if COUNTER_LOOPS +// srl %o3,0,%o3 // zero-extend %o3 = count + brz,pn %o3,2f + _ mov %g0,%g1 // Carry := 0 + sub %g0,%o3,%o3 // %o3 = -count + sllx %o3,3,%o3 // %o3 = -8*count + sub %o2,8,%o2 + sub %o0,%o3,%o0 // %o0 = &sourceptr1[count] + sub %o1,%o3,%o1 // %o1 = &sourceptr2[count] + sub %o2,%o3,%o2 // %o2 = &destptr[count-1] +1: ldx [%o0+%o3],%o4 // source1-digit + ldx [%o1+%o3],%o5 // source2-digit + addcc %o4,%g1,%o4 + movcc %xcc,0,%g1 // %g1|%o4 := %o4 + alter Carry %g1 + addcc %o4,%o5,%o4 + movcs %xcc,1,%g1 // %g1|%o4 := %o4 + alter Carry %g1 + %o5 + addcc %o3,8,%o3 // Zähler erniedrigen, Pointer erhöhen + bne,pt %xcc,1b + _ stx %o4,[%o2+%o3] // Digit ablegen +2: retl + _ mov %g1,%o0 +#endif + +// extern uintD addto_loop_up (uintD* sourceptr, uintD* destptr, uintC count); + DECLARE_FUNCTION(addto_loop_up) +C(addto_loop_up:) // Input in %o0,%o1,%o2, Output in %o0 +#if STANDARD_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ mov %g0,%o5 // Carry := 0 +1: ldx [%o0],%o3 // source-digit + add %o0,8,%o0 + ldx [%o1],%o4 // dest-digit + addcc %o3,%o5,%o3 + movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5 + addcc %o3,%o4,%o4 + movcs %xcc,1,%o5 // %o5|%o4 := %o3 + alter Carry %o5 + %o4 + stx %o4,[%o1] // Digit ablegen + subcc %o2,1,%o2 + bne,pt %xcc,1b + _ add %o1,8,%o1 +2: retl + _ mov %o5,%o0 +#endif +#if COUNTER_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ mov %g0,%o5 // Carry := 0 + sub %g0,%o2,%o2 // %o2 = -count + sllx %o2,3,%o2 // %o2 = -8*count + sub %o0,%o2,%o0 // %o0 = &sourceptr[count] + sub %o1,%o2,%o1 // %o1 = &destptr[count] + ldx [%o0+%o2],%o3 // source-digit +1: ldx [%o1+%o2],%o4 // dest-digit + addcc %o3,%o5,%o3 + movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5 + addcc %o3,%o4,%o4 + movcs %xcc,1,%o5 // %o5|%o4 := %o3 + alter Carry %o5 + %o4 + stx %o4,[%o1+%o2] // Digit ablegen + addcc %o2,8,%o2 // Zähler erniedrigen, Pointer erhöhen + bne,a,pt %xcc,1b + __ ldx [%o0+%o2],%o3 // source-digit +2: retl + _ mov %o5,%o0 +#endif + +// extern uintD inc_loop_up (uintD* ptr, uintC count); + DECLARE_FUNCTION(inc_loop_up) +C(inc_loop_up:) // Input in %o0,%o1, Output in %o0 +#if STANDARD_LOOPS +// srl %o1,0,%o1 // zero-extend %o1 = count + brz,pn %o1,2f + _ nop + ldx [%o0],%o2 +1: add %o0,8,%o0 + addcc %o2,1,%o2 + bne,pn %xcc,3f + _ stx %o2,[%o0-8] + subcc %o1,1,%o1 + bne,a,pt %xcc,1b + __ ldx [%o0],%o2 +2: retl + _ mov 1,%o0 +3: retl + _ mov 0,%o0 +#endif +#if COUNTER_LOOPS +// srl %o1,0,%o1 // zero-extend %o1 = count + brz,pn %o1,2f + _ sub %g0,%o1,%o1 // %o1 = -count + sllx %o1,3,%o1 // %o1 = -8*count + sub %o0,%o1,%o0 // %o0 = &ptr[count] + ldx [%o0+%o1],%o2 // digit holen +1: addcc %o2,1,%o2 // incrementieren + bne,pn %xcc,3f + _ stx %o2,[%o0+%o1] // ablegen + addcc %o1,8,%o1 // Zähler erniedrigen, Pointer erhöhen + bne,a,pt %xcc,1b + __ ldx [%o0+%o1],%o2 +2: retl + _ mov 1,%o0 +3: retl + _ mov 0,%o0 +#endif + +// extern uintD sub_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count); + DECLARE_FUNCTION(sub_loop_up) +C(sub_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0 +#if STANDARD_LOOPS +// srl %o3,0,%o3 // zero-extend %o3 = count + brz,pn %o3,2f + _ mov %g0,%g1 // Carry := 0 +1: ldx [%o0],%o4 // source1-digit + add %o0,8,%o0 + ldx [%o1],%o5 // source2-digit + add %o1,8,%o1 + addcc %o5,%g1,%o5 + movcc %xcc,0,%g1 // %g1|%o5 := %o5 + alter Carry %g1 + subcc %o4,%o5,%o4 + movcs %xcc,1,%g1 // %o4-2^64*%g1 := %o4 - %o5 - alter Carry %g1 + stx %o4,[%o2] // Digit ablegen + subcc %o3,1,%o3 + bne,pt %xcc,1b + _ add %o2,8,%o2 +2: retl + _ mov %g1,%o0 +#endif +#if COUNTER_LOOPS +// srl %o3,0,%o3 // zero-extend %o3 = count + brz,pn %o3,2f + _ mov %g0,%g1 // Carry := 0 + sub %g0,%o3,%o3 // %o3 = -count + sllx %o3,3,%o3 // %o3 = -8*count + sub %o2,8,%o2 + sub %o0,%o3,%o0 // %o0 = &sourceptr1[count] + sub %o1,%o3,%o1 // %o1 = &sourceptr2[count] + sub %o2,%o3,%o2 // %o2 = &destptr[count-1] +1: ldx [%o1+%o3],%o5 // source2-digit + ldx [%o0+%o3],%o4 // source1-digit + addcc %o5,%g1,%o5 + movcc %xcc,0,%g1 // %g1|%o5 := %o5 + alter Carry %g1 + subcc %o4,%o5,%o4 + movcs %xcc,1,%g1 // %o4-2^64*%g1 := %o4 - %o5 - alter Carry %g1 + addcc %o3,8,%o3 + bne,pt %xcc,1b + _ stx %o4,[%o2+%o3] // Digit ablegen +2: retl + _ mov %g1,%o0 +#endif + +// extern uintD subx_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry); + DECLARE_FUNCTION(subx_loop_up) +C(subx_loop_up:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1, Output in %o0 +#if STANDARD_LOOPS +// srl %o3,0,%o3 // zero-extend %o3 = count + brz,pn %o3,2f + _ mov %o4,%g1 // Carry (0 oder -1) +1: ldx [%o0],%o4 // source1-digit + add %o0,8,%o0 + ldx [%o1],%o5 // source2-digit + add %o1,8,%o1 + subcc %o5,%g1,%o5 + movcc %xcc,0,%g1 // %o5-2^64*%g1 := %o5 - alter Carry %g1 + subcc %o4,%o5,%o4 + movcs %xcc,-1,%g1 // %o4+2^64*%g1 := %o4 - %o5 + alter Carry %g1 + stx %o4,[%o2] // Digit ablegen + subcc %o3,1,%o3 + bne,pt %xcc,1b + _ add %o2,8,%o2 +2: retl + _ mov %g1,%o0 +#endif +#if COUNTER_LOOPS +// srl %o3,0,%o3 // zero-extend %o3 = count + brz,pn %o3,2f + _ mov %o4,%g1 // Carry (0 oder -1) + sub %g0,%o3,%o3 // %o3 = -count + sllx %o3,3,%o3 // %o3 = -8*count + sub %o2,8,%o2 + sub %o0,%o3,%o0 // %o0 = &sourceptr1[count] + sub %o1,%o3,%o1 // %o1 = &sourceptr2[count] + sub %o2,%o3,%o2 // %o2 = &destptr[count-1] +1: ldx [%o1+%o3],%o5 // source2-digit + ldx [%o0+%o3],%o4 // source1-digit + subcc %o5,%g1,%o5 + movcc %xcc,0,%g1 // %o5-2^64*%g1 := %o5 - alter Carry %g1 + subcc %o4,%o5,%o4 + movcs %xcc,-1,%g1 // %o4+2^64*%g1 := %o4 - %o5 + alter Carry %g1 + addcc %o3,8,%o3 + bne,pt %xcc,1b + _ stx %o4,[%o2+%o3] // Digit ablegen +2: retl + _ mov %g1,%o0 +#endif + +// extern uintD subfrom_loop_up (uintD* sourceptr, uintD* destptr, uintC count); + DECLARE_FUNCTION(subfrom_loop_up) +C(subfrom_loop_up:) // Input in %o0,%o1,%o2, Output in %o0 +#if STANDARD_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ mov %g0,%o5 // Carry := 0 +1: ldx [%o0],%o3 // source-digit + add %o0,8,%o0 + ldx [%o1],%o4 // dest-digit + addcc %o3,%o5,%o3 + movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5 + subcc %o4,%o3,%o4 + movcs %xcc,1,%o5 // %o4-2^64*%o5 := %o4 - %o3 - alter Carry %o5 + stx %o4,[%o1] // Digit ablegen + subcc %o2,1,%o2 + bne,pt %xcc,1b + _ add %o1,8,%o1 +2: retl + _ mov %o5,%o0 +#endif +#if COUNTER_LOOPS +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ mov %g0,%o5 // Carry := 0 + sub %g0,%o2,%o2 // %o2 = -count + sllx %o2,3,%o2 // %o2 = -8*count + sub %o0,%o2,%o0 // %o0 = &sourceptr[count] + sub %o1,%o2,%o1 // %o1 = &destptr[count] + ldx [%o0+%o2],%o3 // source-digit +1: ldx [%o1+%o2],%o4 // dest-digit + addcc %o3,%o5,%o3 + movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5 + subcc %o4,%o3,%o4 + movcs %xcc,1,%o5 // %o4-2^64*%o5 := %o4 - %o3 - alter Carry %o5 + stx %o4,[%o1+%o2] // Digit ablegen + addcc %o2,8,%o2 + bne,a,pt %xcc,1b + __ ldx [%o0+%o2],%o3 // source-digit +2: retl + _ mov %o5,%o0 +#endif + +// extern uintD dec_loop_up (uintD* ptr, uintC count); + DECLARE_FUNCTION(dec_loop_up) +C(dec_loop_up:) // Input in %o0,%o1, Output in %o0 +#if STANDARD_LOOPS +// srl %o1,0,%o1 // zero-extend %o1 = count + brz,pn %o1,2f + _ nop + ldx [%o0],%o2 +1: add %o0,8,%o0 + subcc %o2,1,%o2 + bcc,pn %xcc,3f + _ stx %o2,[%o0-8] + subcc %o1,1,%o1 + bne,a,pt %xcc,1b + __ ldx [%o0],%o2 +2: retl + _ mov -1,%o0 +3: retl + _ mov 0,%o0 +#endif +#if COUNTER_LOOPS +// srl %o1,0,%o1 // zero-extend %o1 = count + brz,pn %o1,2f + _ sub %g0,%o1,%o1 // %o1 = -count + sllx %o1,3,%o1 // %o1 = -8*count + sub %o0,%o1,%o0 // %o0 = &ptr[count] + ldx [%o0+%o1],%o2 // digit holen +1: subcc %o2,1,%o2 // decrementieren + bcc,pn %xcc,3f + _ stx %o2,[%o0+%o1] // ablegen + addcc %o1,8,%o1 // Zähler erniedrigen, Pointer erhöhen + bne,a,pt %xcc,1b + __ ldx [%o0+%o1],%o2 +2: retl + _ mov -1,%o0 +3: retl + _ mov 0,%o0 +#endif + +// extern uintD neg_loop_up (uintD* ptr, uintC count); + DECLARE_FUNCTION(neg_loop_up) +C(neg_loop_up:) // Input in %o0,%o1, Output in %o0 +#if STANDARD_LOOPS +// srl %o1,0,%o1 // zero-extend %o1 = count + // erstes Digit /=0 suchen: + brz,pn %o1,2f + _ add %o0,8,%o0 +1: ldx [%o0-8],%o2 + subcc %g0,%o2,%o2 + bne,pn %xcc,3f + _ subcc %o1,1,%o1 + bne,pt %xcc,1b + _ add %o0,8,%o0 +2: retl + _ mov 0,%o0 +3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys + // 1 Digit negieren, alle anderen Digits invertieren: + be,pn %xcc,5f + _ stx %o2,[%o0-8] +4: ldx [%o0],%o2 + subcc %o1,1,%o1 + xnor %g0,%o2,%o2 + stx %o2,[%o0] + bne,pt %xcc,4b + _ add %o0,8,%o0 +5: retl + _ mov -1,%o0 +#endif +#if COUNTER_LOOPS +// srl %o1,0,%o1 // zero-extend %o1 = count + // erstes Digit /=0 suchen: + brz,pn %o1,2f + _ sub %g0,%o1,%o1 // %o1 = -count + sllx %o1,3,%o1 // %o1 = -8*count + sub %o0,%o1,%o0 // %o0 = &ptr[count] + ldx [%o0+%o1],%o2 // digit holen +1: subcc %g0,%o2,%o2 // negieren, testen + bne,pn %xcc,3f + _ addcc %o1,8,%o1 // Zähler erniedrigen, Pointer erhöhen + bne,a,pt %xcc,1b + __ ldx [%o0+%o1],%o2 +2: retl + _ mov 0,%o0 +3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys + // alle anderen Digits invertieren: + sub %o1,8,%o1 + stx %o2,[%o0+%o1] // ablegen + addcc %o1,8,%o1 + be,pn %xcc,5f + _ nop + ldx [%o0+%o1],%o2 +4: xnor %g0,%o2,%o2 + stx %o2,[%o0+%o1] + addcc %o1,8,%o1 + bne,a,pt %xcc,4b + __ ldx [%o0+%o1],%o2 +5: retl + _ mov -1,%o0 +#endif + +// extern uintD shift1left_loop_up (uintD* ptr, uintC count); + DECLARE_FUNCTION(shift1left_loop_up) +C(shift1left_loop_up:) // Input in %o0,%o1, Output in %o0 +// srl %o1,0,%o1 // zero-extend %o1 = count + brz,pn %o1,2f + _ mov 0,%o3 // Carry := 0 +1: ldx [%o0],%o2 // Digit + addcc %o2,%o2,%o4 // shiften + add %o4,%o3,%o4 // und carry + srlx %o2,63,%o3 // neues Carry + stx %o4,[%o0] // Digit ablegen + subcc %o1,1,%o1 + bne,pt %xcc,1b + _ add %o0,8,%o0 +2: retl + _ mov %o3,%o0 + +// extern uintD shiftleft_loop_up (uintD* ptr, uintC count, uintC i, uintD carry); + DECLARE_FUNCTION(shiftleft_loop_up) +C(shiftleft_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0 +// srl %o1,0,%o1 // zero-extend %o1 = count + brz,pn %o1,2f + _ sub %g0,%o2,%g1 // 64-i (mod 64) +1: ldx [%o0],%o4 // Digit + subcc %o1,1,%o1 + sllx %o4,%o2,%o5 // dessen niedere (64-i) Bits + or %o3,%o5,%o5 // mit dem alten Carry kombinieren + stx %o5,[%o0] // Digit ablegen + srlx %o4,%g1,%o3 // dessen höchste i Bits liefern den neuen Carry + bne,pt %xcc,1b + _ add %o0,8,%o0 +2: retl + _ mov %o3,%o0 + +#endif + +// extern uintD shiftleftcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i); + DECLARE_FUNCTION(shiftleftcopy_loop_up) +C(shiftleftcopy_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1,%g2, Output in %o0 +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ mov 0,%o4 // Carry := 0 + sub %g0,%o3,%g1 // 64-i (mod 64) +1: ldx [%o0],%o5 // Digit + subcc %o2,1,%o2 + sllx %o5,%o3,%g2 // dessen niedere (64-i) Bits + or %o4,%g2,%g2 // mit dem alten Carry kombinieren + stx %g2,[%o1] // Digit ablegen + add %o1,8,%o1 + srlx %o5,%g1,%o4 // dessen höchste i Bits liefern den neuen Carry + bne,pt %xcc,1b + _ add %o0,8,%o0 +2: retl + _ mov %o4,%o0 + +#if !CL_DS_BIG_ENDIAN_P + +// extern uintD shift1right_loop_down (uintD* ptr, uintC count, uintD carry); + DECLARE_FUNCTION(shift1right_loop_down) +C(shift1right_loop_down:) // Input in %o0,%o1,%o2, Output in %o0 +// srl %o1,0,%o1 // zero-extend %o1 = count + brz,pn %o1,2f + _ sllx %o2,63,%o2 // Carry + sub %o0,8,%o0 +1: ldx [%o0],%o3 // Digit + subcc %o1,1,%o1 + srlx %o3,1,%o4 // shiften + or %o2,%o4,%o4 // und mit altem Carry kombinieren + stx %o4,[%o0] // und ablegen + sllx %o3,63,%o2 // neuer Carry + bne,pt %xcc,1b + _ sub %o0,8,%o0 +2: retl + _ mov %o2,%o0 + +// extern uintD shiftright_loop_down (uintD* ptr, uintC count, uintC i); + DECLARE_FUNCTION(shiftright_loop_down) +C(shiftright_loop_down:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0 +// srl %o1,0,%o1 // zero-extend %o1 = count + sub %g0,%o2,%g1 // 64-i (mod 64) + brz,pn %o1,2f + _ or %g0,%g0,%o3 // Carry := 0 + sub %o0,8,%o0 +1: ldx [%o0],%o4 // Digit + subcc %o1,1,%o1 + srlx %o4,%o2,%o5 // shiften + or %o3,%o5,%o5 // und mit altem Carry kombinieren + stx %o5,[%o0] // und ablegen + sllx %o4,%g1,%o3 // neuer Carry + bne,pt %xcc,1b + _ sub %o0,8,%o0 +2: retl + _ mov %o3,%o0 + +// extern uintD shiftrightsigned_loop_down (uintD* ptr, uintC count, uintC i); + DECLARE_FUNCTION(shiftrightsigned_loop_down) +C(shiftrightsigned_loop_down:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0 +// srl %o1,0,%o1 // zero-extend %o1 = count + ldx [%o0-8],%o4 // erstes Digit + sub %g0,%o2,%g1 // 64-i (mod 64) + srax %o4,%o2,%o5 // shiften + stx %o5,[%o0-8] // und ablegen + sllx %o4,%g1,%o3 // neuer Carry + subcc %o1,1,%o1 + be,pn %xcc,2f + _ sub %o0,16,%o0 +1: ldx [%o0],%o4 // Digit + subcc %o1,1,%o1 + srlx %o4,%o2,%o5 // shiften + or %o3,%o5,%o5 // und mit altem Carry kombinieren + stx %o5,[%o0] // und ablegen + sllx %o4,%g1,%o3 // neuer Carry + bne,pt %xcc,1b + _ sub %o0,8,%o0 +2: retl + _ mov %o3,%o0 + +// extern uintD shiftrightcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry); + DECLARE_FUNCTION(shiftrightcopy_loop_down) +C(shiftrightcopy_loop_down:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1,%g2, Output in %o0 +// srl %o2,0,%o2 // zero-extend %o2 = count + sub %g0,%o3,%g1 // 64-i (mod 64) + brz,pn %o2,2f + _ sllx %o4,%g1,%g2 // erster Carry + sub %o0,8,%o0 +1: ldx [%o0],%o4 // Digit + sub %o1,8,%o1 + srlx %o4,%o3,%o5 // shiften + or %g2,%o5,%o5 // und mit altem Carry kombinieren + stx %o5,[%o1] // und ablegen + sllx %o4,%g1,%g2 // neuer Carry + subcc %o2,1,%o2 + bne,pt %xcc,1b + _ sub %o0,8,%o0 +2: retl + _ mov %g2,%o0 + +// extern uintD mulusmall_loop_up (uintD digit, uintD* ptr, uintC len, uintD newdigit); + DECLARE_FUNCTION(mulusmall_loop_up) +C(mulusmall_loop_up:) // Input in %o0,%o1,%o2,%o3, Output in %o0, verändert %g1 +// srl %o2,0,%o2 // zero-extend %o2 = len + brz,pn %o2,2f + _ nop +1: // nächstes Digit [%o1] mit der 6-Bit-Zahl %o0 multiplizieren + // und kleinen Carry %o3 dazu: + ldx [%o1],%o4 + sub %o2,1,%o2 + srlx %o4,32,%o5 // high32(x) + srl %o4,0,%o4 // low32(x) + mulx %o4,%o0,%o4 // low32(x)*digit + mulx %o5,%o0,%o5 // high32(x)*digit + sllx %o5,32,%g1 // low32(high32(x)*digit)*2^32 + add %g1,%o3,%g1 // plus carry + addcc %o4,%g1,%o4 // plus low32(x)*digit + srlx %o5,32,%o3 // high32(high32(x)*digit) + add %o3,1,%g1 + movcs %xcc,%g1,%o3 // neuer Carry + stx %o4,[%o1] // neues Digit ablegen + brnz,pt %o2,1b + _ add %o1,8,%o1 +2: retl + _ mov %o3,%o0 + +// extern void mulu_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); + DECLARE_FUNCTION(mulu_loop_up) +C(mulu_loop_up:) // Input in %i0,%i1,%i2,%i3 + save %sp,-192,%sp + mov 0,%l0 // Carry + srlx %i0,32,%l1 // %l1 = high32(digit) + srl %i0,0,%l2 // %l2 = low32(digit) + mov 1,%l3 + sllx %l3,32,%l3 // %l3 = 2^32 + sub %i1,%i2,%i1 // %i1 = sourceptr - destptr +1: ldx [%i1+%i2],%o0 // nächstes Digit + subcc %i3,1,%i3 + // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0 + srlx %o0,32,%o1 + srl %o0,0,%o2 + mulx %l1,%o1,%o3 // high part + mulx %l1,%o2,%o4 // first mid part + mulx %l2,%o1,%o1 // second mid part + mulx %l2,%o2,%o2 // low part + srlx %o2,32,%o5 // low part's upper half + add %o4,%o5,%o4 // add to one of the mid parts, no carry + addcc %o4,%o1,%o4 // add other mid part + add %o3,%l3,%o5 + movcs %xcc,%o5,%o3 // if carry, add 2^32 to the high part + srlx %o4,32,%o5 + sllx %o4,32,%o4 + srl %o2,0,%o2 + add %o2,%o4,%o0 // combine low32(midparts) and low32(lowpart) + addcc %o0,%l0,%o0 // alten Carry addieren + add %o3,%o5,%l0 // add high32(midparts) to high part + add %l0,1,%o5 + movcs %xcc,%o5,%l0 // neuer Carry + // Multiplikation fertig + stx %o0,[%i2] // Low-Digit ablegen + brnz,pt %i3,1b + _ add %i2,8,%i2 + stx %l0,[%i2] // letzten Carry ablegen + ret + _ restore + +// extern uintD muluadd_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); + DECLARE_FUNCTION(muluadd_loop_up) +C(muluadd_loop_up:) // Input in %i0,%i1,%i2,%i3, Output in %i0 + save %sp,-192,%sp + mov 0,%l0 // Carry + srlx %i0,32,%l1 // %l1 = high32(digit) + srl %i0,0,%l2 // %l2 = low32(digit) + mov 1,%l3 + sllx %l3,32,%l3 // %l3 = 2^32 + sub %i1,%i2,%i1 // %i1 = sourceptr - destptr +1: ldx [%i1+%i2],%o0 // nächstes Digit + ldx [%i2],%i4 // *destptr + subcc %i3,1,%i3 + // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0 + srlx %o0,32,%o1 + srl %o0,0,%o2 + mulx %l1,%o1,%o3 // high part + mulx %l1,%o2,%o4 // first mid part + mulx %l2,%o1,%o1 // second mid part + mulx %l2,%o2,%o2 // low part + srlx %o2,32,%o5 // low part's upper half + add %o4,%o5,%o4 // add to one of the mid parts, no carry + addcc %o4,%o1,%o4 // add other mid part + add %o3,%l3,%o5 + movcs %xcc,%o5,%o3 // if carry, add 2^32 to the high part + srlx %o4,32,%o5 + sllx %o4,32,%o4 + srl %o2,0,%o2 + add %o2,%o4,%o0 // combine low32(midparts) and low32(lowpart) + addcc %o0,%l0,%o0 // alten Carry addieren + add %o3,%o5,%l0 // add high32(midparts) to high part + add %l0,1,%o5 + movcs %xcc,%o5,%l0 // neuer Carry + // Multiplikation fertig + addcc %i4,%o0,%o0 // alten *destptr addieren + add %l0,1,%o2 + movcs %xcc,%o2,%l0 // neuer Carry + stx %o0,[%i2] // Low-Digit ablegen + brnz,pt %i3,1b + _ add %i2,8,%i2 + mov %l0,%i0 // letzter Carry + ret + _ restore + +// extern uintD mulusub_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); + DECLARE_FUNCTION(mulusub_loop_up) +C(mulusub_loop_up:) // Input in %i0,%i1,%i2,%i3, Output in %i0 + save %sp,-192,%sp + mov 0,%l0 // Carry + srlx %i0,32,%l1 // %l1 = high32(digit) + srl %i0,0,%l2 // %l2 = low32(digit) + mov 1,%l3 + sllx %l3,32,%l3 // %l3 = 2^32 + sub %i1,%i2,%i1 // %i1 = sourceptr - destptr +1: ldx [%i1+%i2],%o0 // nächstes Digit + ldx [%i2],%i4 // *destptr + subcc %i3,1,%i3 + // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0 + srlx %o0,32,%o1 + srl %o0,0,%o2 + mulx %l1,%o1,%o3 // high part + mulx %l1,%o2,%o4 // first mid part + mulx %l2,%o1,%o1 // second mid part + mulx %l2,%o2,%o2 // low part + srlx %o2,32,%o5 // low part's upper half + add %o4,%o5,%o4 // add to one of the mid parts, no carry + addcc %o4,%o1,%o4 // add other mid part + add %o3,%l3,%o5 + movcs %xcc,%o5,%o3 // if carry, add 2^32 to the high part + srlx %o4,32,%o5 + sllx %o4,32,%o4 + srl %o2,0,%o2 + add %o2,%o4,%o0 // combine low32(midparts) and low32(lowpart) + addcc %o0,%l0,%o0 // alten Carry addieren + add %o3,%o5,%l0 // add high32(midparts) to high part + add %l0,1,%o5 + movcs %xcc,%o5,%l0 // neuer Carry + // Multiplikation fertig + subcc %i4,%o0,%o0 // vom alten *destptr subtrahieren + add %l0,1,%o2 + movcs %xcc,%o2,%l0 // neuer Carry + stx %o0,[%i2] // Low-Digit ablegen + brnz,pt %i3,1b + _ add %i2,8,%i2 + mov %l0,%i0 // letzter Carry + ret + _ restore + +#endif + +// extern void shiftxor_loop_up (uintD* xptr, const uintD* yptr, uintC count, uintC i); + DECLARE_FUNCTION(shiftxor_loop_up) +C(shiftxor_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1,%g2 +// srl %o2,0,%o2 // zero-extend %o2 = count + brz,pn %o2,2f + _ sub %g0,%o3,%g1 // 64-i (mod 64) + sub %o1,%o0,%o1 + ldx [%o0],%o4 // *xptr holen +1: ldx [%o0+%o1],%o5 // *yptr holen + subcc %o2,1,%o2 + sllx %o5,%o3,%g2 // dessen niedere (64-i) Bits + xor %o4,%g2,%o4 // mit dem modifizierten *xptr kombinieren + stx %o4,[%o0] // und ablegen + add %o0,8,%o0 + srlx %o5,%g1,%g2 // höchste i Bits von *yptr + ldx [%o0],%o4 // schon mal mit dem nächsten *xptr + bne,pt %xcc,1b + _ xor %o4,%g2,%o4 // verknüpfen + stx %o4,[%o0] // und ablegen +2: retl + _ nop + diff --git a/src/base/digitseq/cl_asm_sparc_.cc b/src/base/digitseq/cl_asm_sparc_.cc new file mode 100644 index 0000000..aac70ae --- /dev/null +++ b/src/base/digitseq/cl_asm_sparc_.cc @@ -0,0 +1,4229 @@ +// Externe Routinen zu ARILEV1.D +// Prozessor: SPARC +// Compiler: GNU-C oder SUN-C +// Parameter-Übergabe: in Registern %o0-%o5. +// Einstellungen: intCsize=32, intDsize=32. + +#if defined(sparc_v8) || defined(__sparc_v8) || defined(__sparc_v8__) + #define sparcv8 +#endif + +#ifdef ASM_UNDERSCORE /* SunOS 4 */ + #if defined(__STDC__) || defined (__cplusplus) + #define C(entrypoint) _##entrypoint + #else + #define C(entrypoint) _/**/entrypoint + #endif +#else /* SunOS 5 = Solaris 2 */ + #define C(entrypoint) entrypoint +#endif + +// When this file is compiled into a shared library, ELF linkers need to +// know which symbols are functions. +#if defined(__NetBSD__) || defined(__OpenBSD__) + #define DECLARE_FUNCTION(name) .type C(name),@function +#elif defined(__svr4__) || defined(__ELF__) + // Some preprocessors keep the backslash in place, some don't. + // Some complain about the # being not in front of an ANSI C macro. + // Therefore we use a dollar, which will be sed-converted to # later. + #define DECLARE_FUNCTION(name) .type C(name),$function +#else + #define DECLARE_FUNCTION(name) +#endif + + // Indikatoren für Anweisungen (Instruktionen) in Delay-Slots + // (diese werden VOR der vorigen Instruktion ausgeführt): + #define _ // Instruktion, die stets ausgeführt wird + #define __ // Instruktion, die nur im Sprung-Fall ausgeführt wird + // Abkürzungen für Anweisungen: + #define ret jmp %i7+8 // return from subroutine + #define retl jmp %o7+8 // return from leaf subroutine (no save/restore) + + .seg "text" + + .global C(mulu16_),C(mulu32_),C(mulu32_unchecked) + .global C(divu_6432_3232_),C(divu_3216_1616_) + .global C(copy_loop_up),C(copy_loop_down),C(fill_loop_up),C(fill_loop_down) + .global C(clear_loop_up),C(clear_loop_down) + .global C(test_loop_up),C(test_loop_down) + .global C(xor_loop_up),C(compare_loop_up),C(shiftleftcopy_loop_up),C(shiftxor_loop_up) +#if CL_DS_BIG_ENDIAN_P + .global C(or_loop_up),C(and_loop_up),C(eqv_loop_up) + .global C(nand_loop_up),C(nor_loop_up),C(andc2_loop_up),C(orc2_loop_up) + .global C(not_loop_up) + .global C(and_test_loop_up) + .global C(add_loop_down),C(addto_loop_down),C(inc_loop_down) + .global C(sub_loop_down),C(subx_loop_down),C(subfrom_loop_down),C(dec_loop_down) + .global C(neg_loop_down) + .global C(shift1left_loop_down),C(shiftleft_loop_down),C(shiftleftcopy_loop_down) + .global C(shift1right_loop_up),C(shiftright_loop_up),C(shiftrightsigned_loop_up),C(shiftrightcopy_loop_up) + .global C(mulusmall_loop_down),C(mulu_loop_down),C(muluadd_loop_down),C(mulusub_loop_down) + .global C(divu_loop_up),C(divucopy_loop_up) +#else + .global C(or_loop_down),C(xor_loop_down),C(and_loop_down),C(eqv_loop_down) + .global C(nand_loop_down),C(nor_loop_down),C(andc2_loop_down),C(orc2_loop_down) + .global C(not_loop_down) + .global C(and_test_loop_down),C(compare_loop_down) + .global C(add_loop_up),C(addto_loop_up),C(inc_loop_up) + .global C(sub_loop_up),C(subx_loop_up),C(subfrom_loop_up),C(dec_loop_up) + .global C(neg_loop_up) + .global C(shift1left_loop_up),C(shiftleft_loop_up) + .global C(shift1right_loop_down),C(shiftright_loop_down),C(shiftrightsigned_loop_down),C(shiftrightcopy_loop_down) + .global C(mulusmall_loop_up),C(mulu_loop_up),C(muluadd_loop_up),C(mulusub_loop_up) + .global C(divu_loop_down),C(divucopy_loop_down) +#endif + +#define LOOP_TYPE 1 // 1: Standard-Schleifen + // 2: Schleifen ohne Pointer, nur mit Zähler + // 3: entrollte Schleifen +#define SLOW_LOOPS 0 +#define STANDARD_LOOPS (LOOP_TYPE==1) +#define COUNTER_LOOPS (LOOP_TYPE==2) +#define UNROLLED_LOOPS (LOOP_TYPE==3) +#define MULU32_INLINE 1 // 1: mulu32-Aufrufe inline in die Schleifen + +// extern uint32 mulu16_ (uint16 arg1, uint16 arg2); +// ergebnis := arg1*arg2. + DECLARE_FUNCTION(mulu16_) +C(mulu16_:) // Input in %o0,%o1, Output in %o0 +#ifdef sparcv8 + umul %o0,%o1,%o0 + retl + _ nop +#else + mov %o1,%y + nop // Wartetakt, nötig z.B. für SUN SPARCstation IPC + andcc %g0,%g0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + // Die 17 unteren Bits von %o2 und die 15 oberen Bits von %y + // ergeben das Resultat. (Die anderen Bits sind Null.) + rd %y,%o0 + srl %o0,17,%o0 + sll %o2,15,%o2 + retl + _ or %o2,%o0,%o0 +#endif + +// extern struct { uint32 lo; uint32 hi; } mulu32_ (uint32 arg1, uint32 arg2); +// 2^32*hi+lo := arg1*arg2. + DECLARE_FUNCTION(mulu32_) +C(mulu32_:) // Input in %o0,%o1, Output in %o0,%g1 +#ifdef sparcv8 + umul %o0,%o1,%o0 + retl + _ rd %y,%g1 +#else + mov %o1,%y + sra %o0,31,%o3 // Wartetakt, nötig z.B. für SUN SPARCstation IPC + andcc %g0,%g0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%g0,%o2 + and %o3,%o1,%o3 // %o3 = (0 falls %o0>=0, %o1 falls %o0<0) + add %o2,%o3,%g1 // hi + retl + _ rd %y,%o0 // lo +#endif + +// extern uint32 mulu32_unchecked (uint32 x, uint32 y); +// ergebnis := arg1*arg2 < 2^32. + DECLARE_FUNCTION(mulu32_unchecked) +C(mulu32_unchecked:) // Input in %o0,%o1, Output in %o0 +#ifdef sparcv8 + umul %o0,%o1,%o0 + retl + _ nop +#else + subcc %o0,%o1,%g0 + bcc,a 1f + __ mov %o1,%y + // arg1 < arg2, also kann man arg1 < 2^16 annehmen. + mov %o0,%y + nop // Wartetakt, nötig z.B. für SUN SPARCstation IPC + andcc %g0,%g0,%o2 + mulscc %o2,%o1,%o2 + mulscc %o2,%o1,%o2 + mulscc %o2,%o1,%o2 + mulscc %o2,%o1,%o2 + mulscc %o2,%o1,%o2 + mulscc %o2,%o1,%o2 + mulscc %o2,%o1,%o2 + mulscc %o2,%o1,%o2 + mulscc %o2,%o1,%o2 + mulscc %o2,%o1,%o2 + mulscc %o2,%o1,%o2 + mulscc %o2,%o1,%o2 + mulscc %o2,%o1,%o2 + mulscc %o2,%o1,%o2 + mulscc %o2,%o1,%o2 + mulscc %o2,%o1,%o2 + // Die 17 unteren Bits von %o2 und die 15 oberen Bits von %y + // ergeben das Resultat. (Die anderen Bits sind Null.) + rd %y,%o0 + srl %o0,17,%o0 + sll %o2,15,%o2 + retl + _ or %o2,%o0,%o0 +1: // arg1 >= arg2, also kann man arg2 < 2^16 annehmen. + nop // Wartetakt, nötig z.B. für SUN SPARCstation IPC + andcc %g0,%g0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + mulscc %o2,%o0,%o2 + // Die 17 unteren Bits von %o2 und die 15 oberen Bits von %y + // ergeben das Resultat. + rd %y,%o0 + srl %o0,17,%o0 + sll %o2,15,%o2 + retl + _ or %o2,%o0,%o0 +#endif + +// extern struct { uint32 q; uint32 r; } divu_6432_3232_ (uint32 xhi, uint32 xlo, uint32 y); +// x = 2^32*xhi+xlo = q*y+r schreiben. Sei bekannt, daß 0 <= x < 2^32*y . + DECLARE_FUNCTION(divu_6432_3232_) +C(divu_6432_3232_:) // Input in %o0,%o1,%o2, Output in %o0,%g1 +#if defined(sparcv8) + // Problem: Is udiv worth using (gmp-2.0.2 doesn't use it) ?? + wr %o0,%g0,%y + nop // wait 1 | Necessary for certain sparcv8 + nop // wait 2 | processors such as Ross Hypersparc, + nop // wait 3 | but not for most of the others. + udiv %o1,%o2,%o0 // x durch y dividieren, %o0 := q + umul %o0,%o2,%g1 // %g1 := (q*y) mod 2^32 + retl + _ sub %o1,%g1,%g1 // %g1 := (xlo-q*y) mod 2^32 = r +#else + // %o0 = xhi, %o1 = xlo, %o2 = y +// Divisions-Einzelschritte: +// %o0|%o1 wird jeweils um 1 Bit nach links geschoben, +// dafür wird rechts in %o1 ein Ergebnisbit (negiert!) reingeschoben. +// Je nachdem wird mit %o3|%o1 statt %o0|%o1 weitergemacht (spart 1 'mov'). +// Deswegen muß man den Code doppelt vorsehen: einmal mit %o0, einmal mit %o3. +#define SA0(label) /* Vergleichsschritt mit %o0 */\ + subcc %o0,%o2,%o3; \ + bcc label; \ + _ addxcc %o1,%o1,%o1 +#define SA1(label) /* Vergleichsschritt mit %o3 */\ + subcc %o3,%o2,%o0; \ + bcc label; \ + _ addxcc %o1,%o1,%o1 +#define SB0() /* Additionsschritt mit %o0 */\ + addx %o0,%o0,%o0 +#define SB1() /* Additionsschritt mit %o3 */\ + addx %o3,%o3,%o3 +// Los geht's: + addcc %o2,%o2,%g0 // y = %o2 < 2^31 ? + bcc Lsmalldiv // ja -> "kleine" Division + _ andcc %o2,1,%g0 // y = %o2 gerade ? + be Levendiv // ja -> Division durch gerade Zahl + _ srl %o2,1,%o2 + // Division durch ungerade Zahl: + // floor(x / (2*y'-1)) = floor(floor(x/2) / y') + (0 oder 1 oder 2) + // da 0 <= x/(2*y'-1) - x/(2*y') = x/(2*y'-1) / (2*y') = x/y / (2*y') + // < 2^32 / (2*y') < 2^32/y <= 2 . + add %o2,1,%o2 // %o2 = ceiling(y/2) = y' + // Man spart im Vergleich zu Lsmalldiv + // zu Beginn eine Verdoppelung von %o0|%o1 : addcc %o1,%o1,%o1; SB0() + // dafür am Schluß mehr zu tun... + SA0(Lb01) // Bit 31 des Quotienten bestimmen +La01: SB0(); SA0(Lb02) // Bit 30 des Quotienten bestimmen +La02: SB0(); SA0(Lb03) // Bit 29 des Quotienten bestimmen +La03: SB0(); SA0(Lb04) // Bit 28 des Quotienten bestimmen +La04: SB0(); SA0(Lb05) // Bit 27 des Quotienten bestimmen +La05: SB0(); SA0(Lb06) // Bit 26 des Quotienten bestimmen +La06: SB0(); SA0(Lb07) // Bit 25 des Quotienten bestimmen +La07: SB0(); SA0(Lb08) // Bit 24 des Quotienten bestimmen +La08: SB0(); SA0(Lb09) // Bit 23 des Quotienten bestimmen +La09: SB0(); SA0(Lb10) // Bit 22 des Quotienten bestimmen +La10: SB0(); SA0(Lb11) // Bit 21 des Quotienten bestimmen +La11: SB0(); SA0(Lb12) // Bit 20 des Quotienten bestimmen +La12: SB0(); SA0(Lb13) // Bit 19 des Quotienten bestimmen +La13: SB0(); SA0(Lb14) // Bit 18 des Quotienten bestimmen +La14: SB0(); SA0(Lb15) // Bit 17 des Quotienten bestimmen +La15: SB0(); SA0(Lb16) // Bit 16 des Quotienten bestimmen +La16: SB0(); SA0(Lb17) // Bit 15 des Quotienten bestimmen +La17: SB0(); SA0(Lb18) // Bit 14 des Quotienten bestimmen +La18: SB0(); SA0(Lb19) // Bit 13 des Quotienten bestimmen +La19: SB0(); SA0(Lb20) // Bit 12 des Quotienten bestimmen +La20: SB0(); SA0(Lb21) // Bit 11 des Quotienten bestimmen +La21: SB0(); SA0(Lb22) // Bit 10 des Quotienten bestimmen +La22: SB0(); SA0(Lb23) // Bit 9 des Quotienten bestimmen +La23: SB0(); SA0(Lb24) // Bit 8 des Quotienten bestimmen +La24: SB0(); SA0(Lb25) // Bit 7 des Quotienten bestimmen +La25: SB0(); SA0(Lb26) // Bit 6 des Quotienten bestimmen +La26: SB0(); SA0(Lb27) // Bit 5 des Quotienten bestimmen +La27: SB0(); SA0(Lb28) // Bit 4 des Quotienten bestimmen +La28: SB0(); SA0(Lb29) // Bit 3 des Quotienten bestimmen +La29: SB0(); SA0(Lb30) // Bit 2 des Quotienten bestimmen +La30: SB0(); SA0(Lb31) // Bit 1 des Quotienten bestimmen +La31: SB0(); SA0(Lb32) // Bit 0 des Quotienten bestimmen +La32: SB0() // %o0 = x mod (2*y') + xor %o1,-1,%o1 // %o1 = floor( floor(x/2) / y') = floor(x/(2*y')) + add %o2,%o2,%o2 + sub %o2,1,%o2 // wieder %o2 = 2*y'-1 = y + // Quotient und Rest umrechnen: + // x = %o1 * 2*y' + %o0 = %o1 * (2*y'-1) + (%o0+%o1) + // Also Quotient = %o1, Rest = %o0+%o1. + // Noch maximal 2 mal: Quotient += 1, Rest -= y. + addcc %o1,%o0,%o0 // Rest mod y bestimmen + bcc 1f // Additions-Überlauf -> Quotient erhöhen + _ subcc %o0,%o2,%o3 + subcc %o3,%o2,%o0 // muß der Quotient nochmals erhöht werden? + bcs 2f + _ mov %o3,%g1 + // Quotient 2 mal erhöhen, Rest %o0 + mov %o0,%g1 + retl + _ add %o1,2,%o0 +1: // kein Additions-Überlauf. + // Wegen y>=2^31 muß der Quotient noch höchstens 1 mal erhöht werden: + bcs 3f // %o0 < %o2 -> Rest %o0 und Quotient %o1 OK + _ mov %o3,%g1 +2: // Quotient %o1 erhöhen, Rest = %o0-%o2 = %o3 + retl + _ add %o1,1,%o0 +3: // Quotient %o1 und Rest %o0 OK + mov %o0,%g1 + retl + _ mov %o1,%o0 +// Parallelschiene zu La01..La32: +Lb01: SB1(); SA1(La02) +Lb02: SB1(); SA1(La03) +Lb03: SB1(); SA1(La04) +Lb04: SB1(); SA1(La05) +Lb05: SB1(); SA1(La06) +Lb06: SB1(); SA1(La07) +Lb07: SB1(); SA1(La08) +Lb08: SB1(); SA1(La09) +Lb09: SB1(); SA1(La10) +Lb10: SB1(); SA1(La11) +Lb11: SB1(); SA1(La12) +Lb12: SB1(); SA1(La13) +Lb13: SB1(); SA1(La14) +Lb14: SB1(); SA1(La15) +Lb15: SB1(); SA1(La16) +Lb16: SB1(); SA1(La17) +Lb17: SB1(); SA1(La18) +Lb18: SB1(); SA1(La19) +Lb19: SB1(); SA1(La20) +Lb20: SB1(); SA1(La21) +Lb21: SB1(); SA1(La22) +Lb22: SB1(); SA1(La23) +Lb23: SB1(); SA1(La24) +Lb24: SB1(); SA1(La25) +Lb25: SB1(); SA1(La26) +Lb26: SB1(); SA1(La27) +Lb27: SB1(); SA1(La28) +Lb28: SB1(); SA1(La29) +Lb29: SB1(); SA1(La30) +Lb30: SB1(); SA1(La31) +Lb31: SB1(); SA1(La32) +Lb32: SB1() // %o3 = x mod (2*y') + xor %o1,-1,%o1 // %o1 = floor( floor(x/2) / y') = floor(x/(2*y')) + add %o2,%o2,%o2 + sub %o2,1,%o2 // wieder %o2 = 2*y'-1 = y + // Quotient und Rest umrechnen: + // x = %o1 * 2*y' + %o3 = %o1 * (2*y'-1) + (%o3+%o1) + // Also Quotient = %o1, Rest = %o3+%o1. + // Noch maximal 2 mal: Quotient += 1, Rest -= y. + addcc %o1,%o3,%o3 // Rest mod y bestimmen + bcc 1f // Additions-Überlauf -> Quotient erhöhen + _ subcc %o3,%o2,%o0 + subcc %o0,%o2,%o3 // muß der Quotient nochmals erhöht werden? + bcs 2f + _ mov %o0,%g1 + // Quotient 2 mal erhöhen, Rest %o3 + mov %o3,%g1 + retl + _ add %o1,2,%o0 +1: // kein Additions-Überlauf. + // Wegen y>=2^31 muß der Quotient noch höchstens 1 mal erhöht werden: + bcs 3f // %o3 < %o2 -> Rest %o3 und Quotient %o1 OK + _ mov %o0,%g1 +2: // Quotient %o1 erhöhen, Rest = %o3-%o2 = %o0 + retl + _ add %o1,1,%o0 +3: // Quotient %o1 und Rest %o3 OK + mov %o3,%g1 + retl + _ mov %o1,%o0 +Lsmalldiv: // Division durch y < 2^31 + addcc %o1,%o1,%o1 +Lc00: SB0(); SA0(Ld01) // Bit 31 des Quotienten bestimmen +Lc01: SB0(); SA0(Ld02) // Bit 30 des Quotienten bestimmen +Lc02: SB0(); SA0(Ld03) // Bit 29 des Quotienten bestimmen +Lc03: SB0(); SA0(Ld04) // Bit 28 des Quotienten bestimmen +Lc04: SB0(); SA0(Ld05) // Bit 27 des Quotienten bestimmen +Lc05: SB0(); SA0(Ld06) // Bit 26 des Quotienten bestimmen +Lc06: SB0(); SA0(Ld07) // Bit 25 des Quotienten bestimmen +Lc07: SB0(); SA0(Ld08) // Bit 24 des Quotienten bestimmen +Lc08: SB0(); SA0(Ld09) // Bit 23 des Quotienten bestimmen +Lc09: SB0(); SA0(Ld10) // Bit 22 des Quotienten bestimmen +Lc10: SB0(); SA0(Ld11) // Bit 21 des Quotienten bestimmen +Lc11: SB0(); SA0(Ld12) // Bit 20 des Quotienten bestimmen +Lc12: SB0(); SA0(Ld13) // Bit 19 des Quotienten bestimmen +Lc13: SB0(); SA0(Ld14) // Bit 18 des Quotienten bestimmen +Lc14: SB0(); SA0(Ld15) // Bit 17 des Quotienten bestimmen +Lc15: SB0(); SA0(Ld16) // Bit 16 des Quotienten bestimmen +Lc16: SB0(); SA0(Ld17) // Bit 15 des Quotienten bestimmen +Lc17: SB0(); SA0(Ld18) // Bit 14 des Quotienten bestimmen +Lc18: SB0(); SA0(Ld19) // Bit 13 des Quotienten bestimmen +Lc19: SB0(); SA0(Ld20) // Bit 12 des Quotienten bestimmen +Lc20: SB0(); SA0(Ld21) // Bit 11 des Quotienten bestimmen +Lc21: SB0(); SA0(Ld22) // Bit 10 des Quotienten bestimmen +Lc22: SB0(); SA0(Ld23) // Bit 9 des Quotienten bestimmen +Lc23: SB0(); SA0(Ld24) // Bit 8 des Quotienten bestimmen +Lc24: SB0(); SA0(Ld25) // Bit 7 des Quotienten bestimmen +Lc25: SB0(); SA0(Ld26) // Bit 6 des Quotienten bestimmen +Lc26: SB0(); SA0(Ld27) // Bit 5 des Quotienten bestimmen +Lc27: SB0(); SA0(Ld28) // Bit 4 des Quotienten bestimmen +Lc28: SB0(); SA0(Ld29) // Bit 3 des Quotienten bestimmen +Lc29: SB0(); SA0(Ld30) // Bit 2 des Quotienten bestimmen +Lc30: SB0(); SA0(Ld31) // Bit 1 des Quotienten bestimmen +Lc31: SB0(); SA0(Ld32) // Bit 0 des Quotienten bestimmen +Lc32: mov %o0,%g1 // Rest aus %o0 in %g1 abspeichern + retl + _ xor %o1,-1,%o0 // Quotient nach %o0 +// Parallelschiene zu Lc01..Lc32: +Ld01: SB1(); SA1(Lc02) +Ld02: SB1(); SA1(Lc03) +Ld03: SB1(); SA1(Lc04) +Ld04: SB1(); SA1(Lc05) +Ld05: SB1(); SA1(Lc06) +Ld06: SB1(); SA1(Lc07) +Ld07: SB1(); SA1(Lc08) +Ld08: SB1(); SA1(Lc09) +Ld09: SB1(); SA1(Lc10) +Ld10: SB1(); SA1(Lc11) +Ld11: SB1(); SA1(Lc12) +Ld12: SB1(); SA1(Lc13) +Ld13: SB1(); SA1(Lc14) +Ld14: SB1(); SA1(Lc15) +Ld15: SB1(); SA1(Lc16) +Ld16: SB1(); SA1(Lc17) +Ld17: SB1(); SA1(Lc18) +Ld18: SB1(); SA1(Lc19) +Ld19: SB1(); SA1(Lc20) +Ld20: SB1(); SA1(Lc21) +Ld21: SB1(); SA1(Lc22) +Ld22: SB1(); SA1(Lc23) +Ld23: SB1(); SA1(Lc24) +Ld24: SB1(); SA1(Lc25) +Ld25: SB1(); SA1(Lc26) +Ld26: SB1(); SA1(Lc27) +Ld27: SB1(); SA1(Lc28) +Ld28: SB1(); SA1(Lc29) +Ld29: SB1(); SA1(Lc30) +Ld30: SB1(); SA1(Lc31) +Ld31: SB1(); SA1(Lc32) +Ld32: mov %o3,%g1 // Rest aus %o3 in %g1 abspeichern + retl + _ xor %o1,-1,%o0 // Quotient nach %o0 +Levendiv: // Division durch gerades y. + // x/2 durch y/2 dividieren, Quotient OK, Rest evtl. mit 2 multiplizieren. + // Es ist schon %o2 = y/2. + // Man spart im Vergleich zu Lsmalldiv + // zu Beginn eine Verdoppelung von %o0|%o1 : addcc %o1,%o1,%o1; SB0() + // dafür am Schluß Bit 0 von x zum Rest dazuschieben. + SA0(Lf01) // Bit 31 des Quotienten bestimmen +Le01: SB0(); SA0(Lf02) // Bit 30 des Quotienten bestimmen +Le02: SB0(); SA0(Lf03) // Bit 29 des Quotienten bestimmen +Le03: SB0(); SA0(Lf04) // Bit 28 des Quotienten bestimmen +Le04: SB0(); SA0(Lf05) // Bit 27 des Quotienten bestimmen +Le05: SB0(); SA0(Lf06) // Bit 26 des Quotienten bestimmen +Le06: SB0(); SA0(Lf07) // Bit 25 des Quotienten bestimmen +Le07: SB0(); SA0(Lf08) // Bit 24 des Quotienten bestimmen +Le08: SB0(); SA0(Lf09) // Bit 23 des Quotienten bestimmen +Le09: SB0(); SA0(Lf10) // Bit 22 des Quotienten bestimmen +Le10: SB0(); SA0(Lf11) // Bit 21 des Quotienten bestimmen +Le11: SB0(); SA0(Lf12) // Bit 20 des Quotienten bestimmen +Le12: SB0(); SA0(Lf13) // Bit 19 des Quotienten bestimmen +Le13: SB0(); SA0(Lf14) // Bit 18 des Quotienten bestimmen +Le14: SB0(); SA0(Lf15) // Bit 17 des Quotienten bestimmen +Le15: SB0(); SA0(Lf16) // Bit 16 des Quotienten bestimmen +Le16: SB0(); SA0(Lf17) // Bit 15 des Quotienten bestimmen +Le17: SB0(); SA0(Lf18) // Bit 14 des Quotienten bestimmen +Le18: SB0(); SA0(Lf19) // Bit 13 des Quotienten bestimmen +Le19: SB0(); SA0(Lf20) // Bit 12 des Quotienten bestimmen +Le20: SB0(); SA0(Lf21) // Bit 11 des Quotienten bestimmen +Le21: SB0(); SA0(Lf22) // Bit 10 des Quotienten bestimmen +Le22: SB0(); SA0(Lf23) // Bit 9 des Quotienten bestimmen +Le23: SB0(); SA0(Lf24) // Bit 8 des Quotienten bestimmen +Le24: SB0(); SA0(Lf25) // Bit 7 des Quotienten bestimmen +Le25: SB0(); SA0(Lf26) // Bit 6 des Quotienten bestimmen +Le26: SB0(); SA0(Lf27) // Bit 5 des Quotienten bestimmen +Le27: SB0(); SA0(Lf28) // Bit 4 des Quotienten bestimmen +Le28: SB0(); SA0(Lf29) // Bit 3 des Quotienten bestimmen +Le29: SB0(); SA0(Lf30) // Bit 2 des Quotienten bestimmen +Le30: SB0(); SA0(Lf31) // Bit 1 des Quotienten bestimmen +Le31: SB0(); SA0(Lf32) // Bit 0 des Quotienten bestimmen +Le32: SB0() // Bit 0 des Restes bestimmen + mov %o0,%g1 // Rest aus %o0 in %g1 abspeichern + retl + _ xor %o1,-1,%o0 // Quotient nach %o0 +// Parallelschiene zu Le01..Le32: +Lf01: SB1(); SA1(Le02) +Lf02: SB1(); SA1(Le03) +Lf03: SB1(); SA1(Le04) +Lf04: SB1(); SA1(Le05) +Lf05: SB1(); SA1(Le06) +Lf06: SB1(); SA1(Le07) +Lf07: SB1(); SA1(Le08) +Lf08: SB1(); SA1(Le09) +Lf09: SB1(); SA1(Le10) +Lf10: SB1(); SA1(Le11) +Lf11: SB1(); SA1(Le12) +Lf12: SB1(); SA1(Le13) +Lf13: SB1(); SA1(Le14) +Lf14: SB1(); SA1(Le15) +Lf15: SB1(); SA1(Le16) +Lf16: SB1(); SA1(Le17) +Lf17: SB1(); SA1(Le18) +Lf18: SB1(); SA1(Le19) +Lf19: SB1(); SA1(Le20) +Lf20: SB1(); SA1(Le21) +Lf21: SB1(); SA1(Le22) +Lf22: SB1(); SA1(Le23) +Lf23: SB1(); SA1(Le24) +Lf24: SB1(); SA1(Le25) +Lf25: SB1(); SA1(Le26) +Lf26: SB1(); SA1(Le27) +Lf27: SB1(); SA1(Le28) +Lf28: SB1(); SA1(Le29) +Lf29: SB1(); SA1(Le30) +Lf30: SB1(); SA1(Le31) +Lf31: SB1(); SA1(Le32) +Lf32: SB1() + mov %o3,%g1 // Rest aus %o0 in %g1 abspeichern + retl + _ xor %o1,-1,%o0 // Quotient nach %o0 +#endif + +// extern struct { uint16 q; uint16 r; } divu_3216_1616_ (uint32 x, uint16 y); +// x = q*y+r schreiben. Sei bekannt, daß 0 <= x < 2^16*y . + DECLARE_FUNCTION(divu_3216_1616_) +C(divu_3216_1616_:) // Input in %o0,%o1, Output in %o0 (Rest und Quotient). +#if defined(sparcv8) + // Problem: Is udiv worth using (gmp-2.0.2 doesn't use it) ?? + wr %g0,%g0,%y + nop // wait 1 + nop // wait 2 + nop // wait 3 + udiv %o0,%o1,%o0 // dividieren, Quotient nach %o0 + rd %y,%o1 // Rest aus %y + sll %o1,16,%o1 // in die oberen 16 Bit schieben + retl + _ or %o0,%o1,%o0 +#else + // %o0 = x, %o1 = y +// Divisions-Einzelschritte: +// %o0 wird jeweils um 1 Bit nach links geschoben, +// dafür wird rechts in %o1 ein Ergebnisbit (negiert!) reingeschoben. +// Dann wird auf >= 2^15*y verglichen (nicht auf >= 2^16*y, weil man dann das +// links herausgeschobene Bit mit vergleichen müßte!) + sll %o1,16,%o1 + srl %o1,1,%o1 // 2^15*y + sub %g0,%o1,%o2 // zum Addieren statt Subtrahieren: -2^15*y + // SC0(label) subtrahiert y, schiebt Carry-Bit rechts in %o0 rein + // (1 falls Subtraktion aufging, 0 sonst). + // Ging die Subtraktion nicht auf, so müßte man noch 2*y addieren. + // Das faßt man mit der nächsten Operation zusammen, indem man - statt + // y zu subtrahieren - y addiert: + // SC1(label) addiert y, schiebt Carry-Bit rechts in %o0 rein + // (1 falls Subtraktion aufgegangen wäre, man also wieder im + // "positiven Bereich" landet, 0 sonst). +#define SC0(label) \ + addcc %o0,%o2,%o0; \ + bcc label; \ + _ addx %o0,%o0,%o0 +#define SC1(label) \ + addcc %o0,%o1,%o0; \ + bcs label; \ + _ addx %o0,%o0,%o0 + SC0(Lh01) // Bit 15 des Quotienten bestimmen +Lg01: SC0(Lh02) // Bit 14 des Quotienten bestimmen +Lg02: SC0(Lh03) // Bit 13 des Quotienten bestimmen +Lg03: SC0(Lh04) // Bit 12 des Quotienten bestimmen +Lg04: SC0(Lh05) // Bit 11 des Quotienten bestimmen +Lg05: SC0(Lh06) // Bit 10 des Quotienten bestimmen +Lg06: SC0(Lh07) // Bit 9 des Quotienten bestimmen +Lg07: SC0(Lh08) // Bit 8 des Quotienten bestimmen +Lg08: SC0(Lh09) // Bit 7 des Quotienten bestimmen +Lg09: SC0(Lh10) // Bit 6 des Quotienten bestimmen +Lg10: SC0(Lh11) // Bit 5 des Quotienten bestimmen +Lg11: SC0(Lh12) // Bit 4 des Quotienten bestimmen +Lg12: SC0(Lh13) // Bit 3 des Quotienten bestimmen +Lg13: SC0(Lh14) // Bit 2 des Quotienten bestimmen +Lg14: SC0(Lh15) // Bit 1 des Quotienten bestimmen +Lg15: SC0(Lh16) // Bit 0 des Quotienten bestimmen +Lg16: // Die oberen 16 Bit von %o0 sind der Rest, + // die unteren 16 Bit von %o0 sind der Quotient. + retl + _ nop +Lh01: SC1(Lg02) // Bit 14 des Quotienten bestimmen +Lh02: SC1(Lg03) // Bit 13 des Quotienten bestimmen +Lh03: SC1(Lg04) // Bit 12 des Quotienten bestimmen +Lh04: SC1(Lg05) // Bit 11 des Quotienten bestimmen +Lh05: SC1(Lg06) // Bit 10 des Quotienten bestimmen +Lh06: SC1(Lg07) // Bit 9 des Quotienten bestimmen +Lh07: SC1(Lg08) // Bit 8 des Quotienten bestimmen +Lh08: SC1(Lg09) // Bit 7 des Quotienten bestimmen +Lh09: SC1(Lg10) // Bit 6 des Quotienten bestimmen +Lh10: SC1(Lg11) // Bit 5 des Quotienten bestimmen +Lh11: SC1(Lg12) // Bit 4 des Quotienten bestimmen +Lh12: SC1(Lg13) // Bit 3 des Quotienten bestimmen +Lh13: SC1(Lg14) // Bit 2 des Quotienten bestimmen +Lh14: SC1(Lg15) // Bit 1 des Quotienten bestimmen +Lh15: SC1(Lg16) // Bit 0 des Quotienten bestimmen +Lh16: // Noch 2*y addieren: + add %o0,%o1,%o0 + retl + _ add %o0,%o1,%o0 +#endif + +#if !defined(__GNUC__) + .global C(_get_g1) +// extern uint32 _get_g1 (void); + DECLARE_FUNCTION(_get_g1) +C(_get_g1:) + retl + _ mov %g1,%o0 +#endif + +// extern uintD* copy_loop_up (uintD* sourceptr, uintD* destptr, uintC count); + DECLARE_FUNCTION(copy_loop_up) +C(copy_loop_up:) // Input in %o0,%o1,%o2, Output in %o0 +#if STANDARD_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ nop +1: ld [%o0],%o3 + add %o0,4,%o0 + st %o3,[%o1] + subcc %o2,1,%o2 + bne 1b + _ add %o1,4,%o1 +2: retl + _ mov %o1,%o0 +#endif +#if COUNTER_LOOPS + subcc %g0,%o2,%o2 // %o2 = -count + be 2f + _ sub %o1,4,%o1 + sll %o2,2,%o2 // %o2 = -4*count + sub %o0,%o2,%o0 // %o0 = &sourceptr[count] + sub %o1,%o2,%o1 // %o1 = &destptr[count-1] +1: ld [%o0+%o2],%o3 // nächstes Digit holen + addcc %o2,4,%o2 // Zähler "erniedrigen", Pointer erhöhen + bne 1b + _ st %o3,[%o1+%o2] // Digit ablegen +2: retl + _ add %o1,4,%o0 +#endif + +// extern uintD* copy_loop_down (uintD* sourceptr, uintD* destptr, uintC count); + DECLARE_FUNCTION(copy_loop_down) +C(copy_loop_down:) // Input in %o0,%o1,%o2, Output in %o0 +#if STANDARD_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sub %o0,4,%o0 +1: ld [%o0],%o3 + sub %o1,4,%o1 + st %o3,[%o1] + subcc %o2,1,%o2 + bne 1b + _ sub %o0,4,%o0 +2: retl + _ mov %o1,%o0 +#endif +#if COUNTER_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sub %o0,4,%o0 + sll %o2,2,%o2 // %o2 = 4*count + sub %o0,%o2,%o0 // %o0 = &sourceptr[-count-1] + sub %o1,%o2,%o1 // %o1 = &destptr[-count] +1: ld [%o0+%o2],%o3 // nächstes Digit holen + subcc %o2,4,%o2 // Zähler erniedrigen, Pointer erniedrigen + bne 1b + _ st %o3,[%o1+%o2] // Digit ablegen +2: retl + _ mov %o1,%o0 +#endif + +// extern uintD* fill_loop_up (uintD* destptr, uintC count, uintD filler); + DECLARE_FUNCTION(fill_loop_up) +C(fill_loop_up:) // Input in %o0,%o1,%o2, Output in %o0 +#if STANDARD_LOOPS + andcc %o1,%o1,%g0 + be 2f + _ nop +1: st %o2,[%o0] + subcc %o1,1,%o1 + bne 1b + _ add %o0,4,%o0 +2: retl + _ nop +#endif +#if COUNTER_LOOPS + subcc %g0,%o1,%o1 // %o1 = -count + be 2f + _ sub %o0,4,%o0 + sll %o1,2,%o1 // %o1 = -4*count + sub %o0,%o1,%o0 // %o0 = &destptr[count-1] +1: addcc %o1,4,%o1 // Zähler "erniedrigen", Pointer erhöhen + bne 1b + _ st %o2,[%o0+%o1] // Digit ablegen +2: retl + _ add %o0,4,%o0 +#endif + +// extern uintD* fill_loop_down (uintD* destptr, uintC count, uintD filler); + DECLARE_FUNCTION(fill_loop_down) +C(fill_loop_down:) // Input in %o0,%o1,%o2, Output in %o0 +#if STANDARD_LOOPS + andcc %o1,%o1,%g0 + be 2f + _ sub %o0,4,%o0 +1: st %o2,[%o0] + subcc %o1,1,%o1 + bne 1b + _ sub %o0,4,%o0 +2: retl + _ add %o0,4,%o0 +#endif +#if COUNTER_LOOPS + andcc %o1,%o1,%g0 + be 2f + _ sll %o1,2,%o1 // %o1 = 4*count + sub %o0,%o1,%o0 // %o0 = &destptr[-count] +1: subcc %o1,4,%o1 // Zähler erniedrigen, Pointer erniedrigen + bne 1b + _ st %o2,[%o0+%o1] // Digit ablegen +2: retl + _ nop +#endif + +// extern uintD* clear_loop_up (uintD* destptr, uintC count); + DECLARE_FUNCTION(clear_loop_up) +C(clear_loop_up:) // Input in %o0,%o1, Output in %o0 +#if STANDARD_LOOPS + andcc %o1,%o1,%g0 + be 2f + _ nop +1: st %g0,[%o0] + subcc %o1,1,%o1 + bne 1b + _ add %o0,4,%o0 +2: retl + _ nop +#endif +#if COUNTER_LOOPS + subcc %g0,%o1,%o1 // %o1 = -count + be 2f + _ sub %o0,4,%o0 + sll %o1,2,%o1 // %o1 = -4*count + sub %o0,%o1,%o0 // %o0 = &destptr[count-1] +1: addcc %o1,4,%o1 // Zähler "erniedrigen", Pointer erhöhen + bne 1b + _ st %g0,[%o0+%o1] // Digit 0 ablegen +2: retl + _ add %o0,4,%o0 +#endif + +// extern uintD* clear_loop_down (uintD* destptr, uintC count); + DECLARE_FUNCTION(clear_loop_down) +C(clear_loop_down:) // Input in %o0,%o1, Output in %o0 +#if STANDARD_LOOPS + andcc %o1,%o1,%g0 + be 2f + _ sub %o0,4,%o0 +1: st %g0,[%o0] + subcc %o1,1,%o1 + bne 1b + _ sub %o0,4,%o0 +2: retl + _ add %o0,4,%o0 +#endif +#if COUNTER_LOOPS + andcc %o1,%o1,%g0 + be 2f + _ sll %o1,2,%o1 // %o1 = 4*count + sub %o0,%o1,%o0 // %o0 = &destptr[-count] +1: subcc %o1,4,%o1 // Zähler erniedrigen, Pointer erniedrigen + bne 1b + _ st %g0,[%o0+%o1] // Digit 0 ablegen +2: retl + _ nop +#endif + +// extern boolean test_loop_up (uintD* ptr, uintC count); + DECLARE_FUNCTION(test_loop_up) +C(test_loop_up:) // Input in %o0,%o1, Output in %o0 +#if STANDARD_LOOPS + andcc %o1,%o1,%g0 + be 2f + _ nop + ld [%o0],%o2 +1: add %o0,4,%o0 + andcc %o2,%o2,%g0 + bne 3f + _ subcc %o1,1,%o1 + bne,a 1b + __ ld [%o0],%o2 +2: retl + _ mov 0,%o0 +3: retl + _ mov 1,%o0 +#endif +#if COUNTER_LOOPS + subcc %g0,%o1,%o1 // %o1 = -count + be 2f + _ sll %o1,2,%o1 // %o1 = -4*count + sub %o0,%o1,%o0 // %o0 = &ptr[count] + ld [%o0+%o1],%o2 // nächstes Digit holen +1: andcc %o2,%o2,%g0 // testen + bne 3f + _ addcc %o1,4,%o1 // Zähler "erniedrigen", Pointer erhöhen + bne,a 1b + __ ld [%o0+%o1],%o2 // nächstes Digit holen +2: retl + _ mov 0,%o0 +3: retl + _ mov 1,%o0 +#endif + +// extern boolean test_loop_down (uintD* ptr, uintC count); + DECLARE_FUNCTION(test_loop_down) +C(test_loop_down:) // Input in %o0,%o1, Output in %o0 +#if STANDARD_LOOPS + andcc %o1,%o1,%g0 + be 2f + _ sub %o0,4,%o0 + ld [%o0],%o2 +1: sub %o0,4,%o0 + andcc %o2,%o2,%g0 + bne 3f + _ subcc %o1,1,%o1 + bne,a 1b + __ ld [%o0],%o2 +2: retl + _ mov 0,%o0 +3: retl + _ mov 1,%o0 +#endif +#if COUNTER_LOOPS + sll %o1,2,%o1 // %o1 = 4*count + sub %o0,%o1,%o0 // %o0 = &ptr[-count] + subcc %o1,4,%o1 + bcs 4f + _ nop + ld [%o0+%o1],%o2 // nächstes Digit holen +1: subcc %o1,4,%o1 // Zähler erniedrigen, Pointer erniedrigen + bcs 3f + _ andcc %o2,%o2,%g0 // testen + be,a 1b + __ ld [%o0+%o1],%o2 // nächstes Digit holen +2: retl + _ mov 1,%o0 +3: bne 2b + _ nop +4: retl + _ mov 0,%o0 +#endif + +#if CL_DS_BIG_ENDIAN_P + +// extern void or_loop_up (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(or_loop_up) +C(or_loop_up:) // Input in %o0,%o1,%o2 +#if SLOW_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ nop +1: ld [%o0],%o3 + ld [%o1],%o4 + add %o1,4,%o1 + or %o3,%o4,%o3 + st %o3,[%o0] + subcc %o2,1,%o2 + bne 1b + _ add %o0,4,%o0 +2: retl + _ nop +#endif +#if STANDARD_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr +1: ld [%o0],%o3 // *xptr + ld [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + or %o3,%o4,%o3 // verknüpfen + st %o3,[%o0] // =: *xptr + bne 1b + _ add %o0,4,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS + subcc %g0,%o2,%o2 // %o2 = -count + be 2f + _ sub %o0,4,%o0 + sll %o2,2,%o2 // %o2 = -4*count + sub %o0,%o2,%o0 // %o0 = &xptr[count-1] + sub %o1,%o2,%o1 // %o1 = &yptr[count] +1: ld [%o1+%o2],%o3 // nächstes Digit holen + addcc %o2,4,%o2 // Zähler "erniedrigen", Pointer erhöhen + ld [%o0+%o2],%o4 // noch ein Digit holen + or %o4,%o3,%o3 // beide verknüpfen + bne 1b + _ st %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +#endif + +// extern void xor_loop_up (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(xor_loop_up) +C(xor_loop_up:) // Input in %o0,%o1,%o2 +#if SLOW_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ nop +1: ld [%o0],%o3 + ld [%o1],%o4 + add %o1,4,%o1 + xor %o3,%o4,%o3 + st %o3,[%o0] + subcc %o2,1,%o2 + bne 1b + _ add %o0,4,%o0 +2: retl + _ nop +#endif +#if STANDARD_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr +1: ld [%o0],%o3 // *xptr + ld [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + xor %o3,%o4,%o3 // verknüpfen + st %o3,[%o0] // =: *xptr + bne 1b + _ add %o0,4,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS + subcc %g0,%o2,%o2 // %o2 = -count + be 2f + _ sub %o0,4,%o0 + sll %o2,2,%o2 // %o2 = -4*count + sub %o0,%o2,%o0 // %o0 = &xptr[count-1] + sub %o1,%o2,%o1 // %o1 = &yptr[count] +1: ld [%o1+%o2],%o3 // nächstes Digit holen + addcc %o2,4,%o2 // Zähler "erniedrigen", Pointer erhöhen + ld [%o0+%o2],%o4 // noch ein Digit holen + xor %o4,%o3,%o3 // beide verknüpfen + bne 1b + _ st %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +#if CL_DS_BIG_ENDIAN_P + +// extern void and_loop_up (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(and_loop_up) +C(and_loop_up:) // Input in %o0,%o1,%o2 +#if SLOW_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ nop +1: ld [%o0],%o3 + ld [%o1],%o4 + add %o1,4,%o1 + and %o3,%o4,%o3 + st %o3,[%o0] + subcc %o2,1,%o2 + bne 1b + _ add %o0,4,%o0 +2: retl + _ nop +#endif +#if STANDARD_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr +1: ld [%o0],%o3 // *xptr + ld [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + and %o3,%o4,%o3 // verknüpfen + st %o3,[%o0] // =: *xptr + bne 1b + _ add %o0,4,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS + subcc %g0,%o2,%o2 // %o2 = -count + be 2f + _ sub %o0,4,%o0 + sll %o2,2,%o2 // %o2 = -4*count + sub %o0,%o2,%o0 // %o0 = &xptr[count-1] + sub %o1,%o2,%o1 // %o1 = &yptr[count] +1: ld [%o1+%o2],%o3 // nächstes Digit holen + addcc %o2,4,%o2 // Zähler "erniedrigen", Pointer erhöhen + ld [%o0+%o2],%o4 // noch ein Digit holen + and %o4,%o3,%o3 // beide verknüpfen + bne 1b + _ st %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +// extern void eqv_loop_up (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(eqv_loop_up) +C(eqv_loop_up:) // Input in %o0,%o1,%o2 +#if SLOW_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ nop +1: ld [%o0],%o3 + ld [%o1],%o4 + add %o1,4,%o1 + xnor %o3,%o4,%o3 + st %o3,[%o0] + subcc %o2,1,%o2 + bne 1b + _ add %o0,4,%o0 +2: retl + _ nop +#endif +#if STANDARD_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr +1: ld [%o0],%o3 // *xptr + ld [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + xnor %o3,%o4,%o3 // verknüpfen + st %o3,[%o0] // =: *xptr + bne 1b + _ add %o0,4,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS + subcc %g0,%o2,%o2 // %o2 = -count + be 2f + _ sub %o0,4,%o0 + sll %o2,2,%o2 // %o2 = -4*count + sub %o0,%o2,%o0 // %o0 = &xptr[count-1] + sub %o1,%o2,%o1 // %o1 = &yptr[count] +1: ld [%o1+%o2],%o3 // nächstes Digit holen + addcc %o2,4,%o2 // Zähler "erniedrigen", Pointer erhöhen + ld [%o0+%o2],%o4 // noch ein Digit holen + xnor %o4,%o3,%o3 // beide verknüpfen + bne 1b + _ st %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +// extern void nand_loop_up (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(nand_loop_up) +C(nand_loop_up:) // Input in %o0,%o1,%o2 +#if SLOW_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ nop +1: ld [%o0],%o3 + ld [%o1],%o4 + add %o1,4,%o1 + and %o3,%o4,%o3 + xor %o3,-1,%o3 + st %o3,[%o0] + subcc %o2,1,%o2 + bne 1b + _ add %o0,4,%o0 +2: retl + _ nop +#endif +#if STANDARD_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr +1: ld [%o0],%o3 // *xptr + ld [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + and %o3,%o4,%o3 // verknüpfen + xor %o3,-1,%o3 + st %o3,[%o0] // =: *xptr + bne 1b + _ add %o0,4,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS + subcc %g0,%o2,%o2 // %o2 = -count + be 2f + _ sub %o0,4,%o0 + sll %o2,2,%o2 // %o2 = -4*count + sub %o0,%o2,%o0 // %o0 = &xptr[count-1] + sub %o1,%o2,%o1 // %o1 = &yptr[count] +1: ld [%o1+%o2],%o3 // nächstes Digit holen + addcc %o2,4,%o2 // Zähler "erniedrigen", Pointer erhöhen + ld [%o0+%o2],%o4 // noch ein Digit holen + and %o4,%o3,%o3 // beide verknüpfen + xor %o3,-1,%o3 + bne 1b + _ st %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +// extern void nor_loop_up (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(nor_loop_up) +C(nor_loop_up:) // Input in %o0,%o1,%o2 +#if SLOW_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ nop +1: ld [%o0],%o3 + ld [%o1],%o4 + add %o1,4,%o1 + or %o3,%o4,%o3 + xor %o3,-1,%o3 + st %o3,[%o0] + subcc %o2,1,%o2 + bne 1b + _ add %o0,4,%o0 +2: retl + _ nop +#endif +#if STANDARD_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr +1: ld [%o0],%o3 // *xptr + ld [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + or %o3,%o4,%o3 // verknüpfen + xor %o3,-1,%o3 + st %o3,[%o0] // =: *xptr + bne 1b + _ add %o0,4,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS + subcc %g0,%o2,%o2 // %o2 = -count + be 2f + _ sub %o0,4,%o0 + sll %o2,2,%o2 // %o2 = -4*count + sub %o0,%o2,%o0 // %o0 = &xptr[count-1] + sub %o1,%o2,%o1 // %o1 = &yptr[count] +1: ld [%o1+%o2],%o3 // nächstes Digit holen + addcc %o2,4,%o2 // Zähler "erniedrigen", Pointer erhöhen + ld [%o0+%o2],%o4 // noch ein Digit holen + or %o4,%o3,%o3 // beide verknüpfen + xor %o3,-1,%o3 + bne 1b + _ st %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +// extern void andc2_loop_up (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(andc2_loop_up) +C(andc2_loop_up:) // Input in %o0,%o1,%o2 +#if SLOW_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ nop +1: ld [%o0],%o3 + ld [%o1],%o4 + add %o1,4,%o1 + andn %o3,%o4,%o3 + st %o3,[%o0] + subcc %o2,1,%o2 + bne 1b + _ add %o0,4,%o0 +2: retl + _ nop +#endif +#if STANDARD_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr +1: ld [%o0],%o3 // *xptr + ld [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + andn %o3,%o4,%o3 // verknüpfen + st %o3,[%o0] // =: *xptr + bne 1b + _ add %o0,4,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS + subcc %g0,%o2,%o2 // %o2 = -count + be 2f + _ sub %o0,4,%o0 + sll %o2,2,%o2 // %o2 = -4*count + sub %o0,%o2,%o0 // %o0 = &xptr[count-1] + sub %o1,%o2,%o1 // %o1 = &yptr[count] +1: ld [%o1+%o2],%o3 // nächstes Digit holen + addcc %o2,4,%o2 // Zähler "erniedrigen", Pointer erhöhen + ld [%o0+%o2],%o4 // noch ein Digit holen + andn %o4,%o3,%o3 // beide verknüpfen + bne 1b + _ st %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +// extern void orc2_loop_up (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(orc2_loop_up) +C(orc2_loop_up:) // Input in %o0,%o1,%o2 +#if SLOW_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ nop +1: ld [%o0],%o3 + ld [%o1],%o4 + add %o1,4,%o1 + orn %o3,%o4,%o3 + st %o3,[%o0] + subcc %o2,1,%o2 + bne 1b + _ add %o0,4,%o0 +2: retl + _ nop +#endif +#if STANDARD_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr +1: ld [%o0],%o3 // *xptr + ld [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + orn %o3,%o4,%o3 // verknüpfen + st %o3,[%o0] // =: *xptr + bne 1b + _ add %o0,4,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS + subcc %g0,%o2,%o2 // %o2 = -count + be 2f + _ sub %o0,4,%o0 + sll %o2,2,%o2 // %o2 = -4*count + sub %o0,%o2,%o0 // %o0 = &xptr[count-1] + sub %o1,%o2,%o1 // %o1 = &yptr[count] +1: ld [%o1+%o2],%o3 // nächstes Digit holen + addcc %o2,4,%o2 // Zähler "erniedrigen", Pointer erhöhen + ld [%o0+%o2],%o4 // noch ein Digit holen + orn %o4,%o3,%o3 // beide verknüpfen + bne 1b + _ st %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +// extern void not_loop_up (uintD* xptr, uintC count); + DECLARE_FUNCTION(not_loop_up) +C(not_loop_up:) // Input in %o0,%o1 +#if STANDARD_LOOPS + andcc %o1,%o1,%g0 + be 2f + _ nop +1: ld [%o0],%o2 + subcc %o1,1,%o1 + xor %o2,-1,%o2 + st %o2,[%o0] + bne 1b + _ add %o0,4,%o0 +2: retl + _ nop +#endif +#if COUNTER_LOOPS + subcc %g0,%o1,%o1 // %o1 = -count + be 2f + _ sub %o0,4,%o0 + sll %o1,2,%o1 // %o1 = -4*count + sub %o0,%o1,%o0 // %o0 = &destptr[count-1] +1: addcc %o1,4,%o1 // Zähler "erniedrigen", Pointer erhöhen + ld [%o0+%o1],%o2 // nächstes Digit holen + xor %o2,-1,%o2 + bne 1b + _ st %o2,[%o0+%o1] // Digit ablegen +2: retl + _ nop +#endif + +// extern boolean and_test_loop_up (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(and_test_loop_up) +C(and_test_loop_up:) // Input in %o0,%o1,%o2, Output in %o0 +#if STANDARD_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ nop +1: ld [%o0],%o3 + ld [%o1],%o4 + add %o0,4,%o0 + andcc %o3,%o4,%g0 + bne 3f + _ subcc %o2,1,%o2 + bne 1b + _ add %o1,4,%o1 +2: retl + _ mov 0,%o0 +3: retl + _ mov 1,%o0 +#endif +#if COUNTER_LOOPS + subcc %g0,%o2,%o2 // %o2 = -count + be 2f + _ sll %o2,2,%o2 // %o2 = -4*count + sub %o0,%o2,%o0 // %o0 = &xptr[count] + sub %o1,%o2,%o1 // %o1 = &yptr[count] + ld [%o0+%o2],%o3 // nächstes Digit holen +1: ld [%o1+%o2],%o4 // noch ein Digit holen + andcc %o3,%o4,%g0 // beide verknüpfen + bne 3f + _ addcc %o2,4,%o2 // Zähler "erniedrigen", Pointer erhöhen + bne,a 1b + __ ld [%o0+%o2],%o3 // nächstes Digit holen +2: retl + _ mov 0,%o0 +3: retl + _ mov 1,%o0 +#endif + +#endif + +// extern cl_signean compare_loop_up (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(compare_loop_up) +C(compare_loop_up:) // Input in %o0,%o1,%o2, Output in %o0 +#if STANDARD_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ nop + ld [%o0],%o3 +1: ld [%o1],%o4 + add %o0,4,%o0 + subcc %o3,%o4,%g0 + bne 3f + _ add %o1,4,%o1 + subcc %o2,1,%o2 + bne,a 1b + __ ld [%o0],%o3 +2: retl + _ mov 0,%o0 +3: blu 4f + _ nop + retl + _ mov 1,%o0 +4: retl + _ mov -1,%o0 +#endif +#if COUNTER_LOOPS + subcc %g0,%o2,%o2 // %o2 = -count + be 2f + _ sll %o2,2,%o2 // %o2 = -4*count + sub %o0,%o2,%o0 // %o0 = &xptr[count] + sub %o1,%o2,%o1 // %o1 = &yptr[count] + ld [%o0+%o2],%o3 // nächstes Digit holen +1: ld [%o1+%o2],%o4 // noch ein Digit holen + subcc %o3,%o4,%g0 // vergleichen + bne 3f + _ addcc %o2,4,%o2 // Zähler "erniedrigen", Pointer erhöhen + bne,a 1b + __ ld [%o0+%o2],%o3 // nächstes Digit holen +2: retl + _ mov 0,%o0 +3: subcc %o3,%o4,%g0 // nochmals vergleichen + blu 4f + _ nop + retl + _ mov 1,%o0 +4: retl + _ mov -1,%o0 +#endif + +#if CL_DS_BIG_ENDIAN_P + +// extern uintD add_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count); + DECLARE_FUNCTION(add_loop_down) +C(add_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0 +#if STANDARD_LOOPS + andcc %o3,%o3,%g0 + be 2f + _ mov %g0,%g1 // Carry := 0 + sub %o0,4,%o0 +1: ld [%o0],%o4 // source1-digit + sub %o1,4,%o1 + ld [%o1],%o5 // source2-digit + subcc %g0,%g1,%g0 // carry + addxcc %o4,%o5,%o4 // addieren + addx %g0,%g0,%g1 // neuer Carry + sub %o2,4,%o2 + st %o4,[%o2] // Digit ablegen + subcc %o3,1,%o3 + bne 1b + _ sub %o0,4,%o0 +2: retl + _ mov %g1,%o0 +#endif +#if COUNTER_LOOPS + andcc %o3,%o3,%g0 + be 2f + _ mov %g0,%g1 // Carry := 0 + sub %o0,4,%o0 + sub %o1,4,%o1 + sll %o3,2,%o3 // %o3 = 4*count + sub %o0,%o3,%o0 // %o0 = &sourceptr1[-count-1] + sub %o1,%o3,%o1 // %o1 = &sourceptr2[-count-1] + sub %o2,%o3,%o2 // %o2 = &destptr[-count] +1: ld [%o0+%o3],%o4 // source1-digit + ld [%o1+%o3],%o5 // source2-digit + subcc %g0,%g1,%g0 // carry + addxcc %o4,%o5,%o4 // addieren + addx %g0,%g0,%g1 // neuer Carry + subcc %o3,4,%o3 + bne 1b + _ st %o4,[%o2+%o3] // Digit ablegen +2: retl + _ mov %g1,%o0 +#endif +#if UNROLLED_LOOPS + and %o3,7,%o4 // count mod 8 + sll %o4,2,%o5 + sub %o0,%o5,%o0 // %o0 = &sourceptr1[-(count mod 8)] + sub %o1,%o5,%o1 // %o1 = &sourceptr2[-(count mod 8)] + sub %o2,%o5,%o2 // %o2 = &destptr[-(count mod 8)] + sll %o4,4,%o4 +#ifdef PIC + mov %o7,%g2 // save return address + call 0f // put address of label 0 into %o7 + _ add %o7,144,%o5 +0: +#else + set _add_loop_down+176,%o5 +#endif + sub %o5,%o4,%o5 + jmp %o5 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8)) + _ subcc %g0,%g0,%g0 // carry löschen +1: subcc %g0,%g1,%g0 // carry + ld [%o0+28],%o4 // source1-digit + ld [%o1+28],%o5 // source2-digit + addxcc %o5,%o4,%o5 // addieren + st %o5,[%o2+28] // Digit ablegen + ld [%o0+24],%o4 // source1-digit + ld [%o1+24],%o5 // source2-digit + addxcc %o5,%o4,%o5 // addieren + st %o5,[%o2+24] // Digit ablegen + ld [%o0+20],%o4 // source1-digit + ld [%o1+20],%o5 // source2-digit + addxcc %o5,%o4,%o5 // addieren + st %o5,[%o2+20] // Digit ablegen + ld [%o0+16],%o4 // source1-digit + ld [%o1+16],%o5 // source2-digit + addxcc %o5,%o4,%o5 // addieren + st %o5,[%o2+16] // Digit ablegen + ld [%o0+12],%o4 // source1-digit + ld [%o1+12],%o5 // source2-digit + addxcc %o5,%o4,%o5 // addieren + st %o5,[%o2+12] // Digit ablegen + ld [%o0+8],%o4 // source1-digit + ld [%o1+8],%o5 // source2-digit + addxcc %o5,%o4,%o5 // addieren + st %o5,[%o2+8] // Digit ablegen + ld [%o0+4],%o4 // source1-digit + ld [%o1+4],%o5 // source2-digit + addxcc %o5,%o4,%o5 // addieren + st %o5,[%o2+4] // Digit ablegen + ld [%o0],%o4 // source1-digit + ld [%o1],%o5 // source2-digit + addxcc %o5,%o4,%o5 // addieren + st %o5,[%o2] // Digit ablegen + addx %g0,%g0,%g1 // neuer Carry + sub %o0,32,%o0 + sub %o1,32,%o1 + subcc %o3,8,%o3 // noch mindestens 8 Digits abzuarbeiten? + bcc 1b + _ sub %o2,32,%o2 +#ifdef PIC + jmp %g2+8 +#else + retl +#endif + _ mov %g1,%o0 +#endif + +// extern uintD addto_loop_down (uintD* sourceptr, uintD* destptr, uintC count); + DECLARE_FUNCTION(addto_loop_down) +C(addto_loop_down:) // Input in %o0,%o1,%o2, Output in %o0 +#if STANDARD_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ mov %g0,%o5 // Carry := 0 + sub %o0,4,%o0 +1: ld [%o0],%o3 // source-digit + sub %o1,4,%o1 + ld [%o1],%o4 // dest-digit + subcc %g0,%o5,%g0 // carry + addxcc %o4,%o3,%o4 // addieren + addx %g0,%g0,%o5 // neuer Carry + st %o4,[%o1] // Digit ablegen + subcc %o2,1,%o2 + bne 1b + _ sub %o0,4,%o0 +2: retl + _ mov %o5,%o0 +#endif +#if COUNTER_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ mov %g0,%o5 // Carry := 0 + sub %o0,4,%o0 + sub %o1,4,%o1 + sll %o2,2,%o2 // %o2 = 4*count + sub %o0,%o2,%o0 // %o0 = &sourceptr[-count-1] + sub %o1,%o2,%o1 // %o1 = &destptr[-count-1] + ld [%o0+%o2],%o3 // source-digit +1: ld [%o1+%o2],%o4 // dest-digit + subcc %g0,%o5,%g0 // carry + addxcc %o4,%o3,%o4 // addieren + addx %g0,%g0,%o5 // neuer Carry + st %o4,[%o1+%o2] // Digit ablegen + subcc %o2,4,%o2 + bne,a 1b + __ ld [%o0+%o2],%o3 // source-digit +2: retl + _ mov %o5,%o0 +#endif +#if UNROLLED_LOOPS + and %o2,7,%o3 // count mod 8 + sll %o3,2,%o4 + sub %o0,%o4,%o0 // %o0 = &sourceptr[-(count mod 8)] + sub %o1,%o4,%o1 // %o1 = &destptr[-(count mod 8)] + sll %o3,4,%o3 +#ifdef PIC + mov %o7,%g2 // save return address + call 0f // put address of label 0 into %o7 + _ add %o7,144,%o4 +0: +#else + set _addto_loop_down+172,%o4 +#endif + sub %o4,%o3,%o4 + jmp %o4 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8)) + _ subcc %g0,%g0,%g0 // carry löschen +1: subcc %g0,%o5,%g0 // carry + ld [%o0+28],%o3 // source-digit + ld [%o1+28],%o4 // dest-digit + addxcc %o4,%o3,%o4 // addieren + st %o4,[%o1+28] // Digit ablegen + ld [%o0+24],%o3 // source-digit + ld [%o1+24],%o4 // dest-digit + addxcc %o4,%o3,%o4 // addieren + st %o4,[%o1+24] // Digit ablegen + ld [%o0+20],%o3 // source-digit + ld [%o1+20],%o4 // dest-digit + addxcc %o4,%o3,%o4 // addieren + st %o4,[%o1+20] // Digit ablegen + ld [%o0+16],%o3 // source-digit + ld [%o1+16],%o4 // dest-digit + addxcc %o4,%o3,%o4 // addieren + st %o4,[%o1+16] // Digit ablegen + ld [%o0+12],%o3 // source-digit + ld [%o1+12],%o4 // dest-digit + addxcc %o4,%o3,%o4 // addieren + st %o4,[%o1+12] // Digit ablegen + ld [%o0+8],%o3 // source-digit + ld [%o1+8],%o4 // dest-digit + addxcc %o4,%o3,%o4 // addieren + st %o4,[%o1+8] // Digit ablegen + ld [%o0+4],%o3 // source-digit + ld [%o1+4],%o4 // dest-digit + addxcc %o4,%o3,%o4 // addieren + st %o4,[%o1+4] // Digit ablegen + ld [%o0],%o3 // source-digit + ld [%o1],%o4 // dest-digit + addxcc %o4,%o3,%o4 // addieren + st %o4,[%o1] // Digit ablegen + addx %g0,%g0,%o5 // neuer Carry + sub %o0,32,%o0 + subcc %o2,8,%o2 // noch mindestens 8 Digits abzuarbeiten? + bcc 1b + _ sub %o1,32,%o1 +#ifdef PIC + jmp %g2+8 +#else + retl +#endif + _ mov %o5,%o0 +#endif + +// extern uintD inc_loop_down (uintD* ptr, uintC count); + DECLARE_FUNCTION(inc_loop_down) +C(inc_loop_down:) // Input in %o0,%o1, Output in %o0 +#if STANDARD_LOOPS + andcc %o1,%o1,%g0 + be 2f + _ sub %o0,4,%o0 +1: ld [%o0],%o2 + addcc %o2,1,%o2 + bne 3f + _ st %o2,[%o0] + subcc %o1,1,%o1 + bne 1b + _ sub %o0,4,%o0 +2: retl + _ mov 1,%o0 +3: retl + _ mov 0,%o0 +#endif +#if COUNTER_LOOPS + andcc %o1,%o1,%g0 + be 2f + _ sub %o0,4,%o0 + sll %o1,2,%o1 // %o1 = 4*count + sub %o0,%o1,%o0 // %o0 = &ptr[-count-1] + ld [%o0+%o1],%o2 // digit holen +1: addcc %o2,1,%o2 // incrementieren + bne 3f + _ st %o2,[%o0+%o1] // ablegen + subcc %o1,4,%o1 // Zähler erniedrigen, Pointer erniedrigen + bne,a 1b + __ ld [%o0+%o1],%o2 +2: retl + _ mov 1,%o0 +3: retl + _ mov 0,%o0 +#endif + +// extern uintD sub_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count); + DECLARE_FUNCTION(sub_loop_down) +C(sub_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0 +#if STANDARD_LOOPS + andcc %o3,%o3,%g0 + be 2f + _ mov %g0,%g1 // Carry := 0 + sub %o0,4,%o0 +1: ld [%o0],%o4 // source1-digit + sub %o1,4,%o1 + ld [%o1],%o5 // source2-digit + subcc %g0,%g1,%g0 // carry + subxcc %o4,%o5,%o4 // subtrahieren + addx %g0,%g0,%g1 // neuer Carry + sub %o2,4,%o2 + st %o4,[%o2] // Digit ablegen + subcc %o3,1,%o3 + bne 1b + _ sub %o0,4,%o0 +2: retl + _ mov %g1,%o0 +#endif +#if COUNTER_LOOPS + andcc %o3,%o3,%g0 + be 2f + _ mov %g0,%g1 // Carry := 0 + sub %o0,4,%o0 + sub %o1,4,%o1 + sll %o3,2,%o3 // %o3 = 4*count + sub %o0,%o3,%o0 // %o0 = &sourceptr1[-count-1] + sub %o1,%o3,%o1 // %o1 = &sourceptr2[-count-1] + sub %o2,%o3,%o2 // %o2 = &destptr[-count] +1: ld [%o0+%o3],%o4 // source1-digit + ld [%o1+%o3],%o5 // source2-digit + subcc %g0,%g1,%g0 // carry + subxcc %o4,%o5,%o4 // subtrahieren + addx %g0,%g0,%g1 // neuer Carry + subcc %o3,4,%o3 + bne 1b + _ st %o4,[%o2+%o3] // Digit ablegen +2: retl + _ mov %g1,%o0 +#endif +#if UNROLLED_LOOPS + and %o3,7,%o4 // count mod 8 + sll %o4,2,%o5 + sub %o0,%o5,%o0 // %o0 = &sourceptr1[-(count mod 8)] + sub %o1,%o5,%o1 // %o1 = &sourceptr2[-(count mod 8)] + sub %o2,%o5,%o2 // %o2 = &destptr[-(count mod 8)] + sll %o4,4,%o4 +#ifdef PIC + mov %o7,%g2 // save return address + call 0f // put address of label 0 into %o7 + _ add %o7,144,%o5 +0: +#else + set _sub_loop_down+176,%o5 +#endif + sub %o5,%o4,%o5 + jmp %o5 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8)) + _ subcc %g0,%g0,%g0 // carry löschen +1: subcc %g0,%g1,%g0 // carry + ld [%o0+28],%o4 // source1-digit + ld [%o1+28],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2+28] // Digit ablegen + ld [%o0+24],%o4 // source1-digit + ld [%o1+24],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2+24] // Digit ablegen + ld [%o0+20],%o4 // source1-digit + ld [%o1+20],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2+20] // Digit ablegen + ld [%o0+16],%o4 // source1-digit + ld [%o1+16],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2+16] // Digit ablegen + ld [%o0+12],%o4 // source1-digit + ld [%o1+12],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2+12] // Digit ablegen + ld [%o0+8],%o4 // source1-digit + ld [%o1+8],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2+8] // Digit ablegen + ld [%o0+4],%o4 // source1-digit + ld [%o1+4],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2+4] // Digit ablegen + ld [%o0],%o4 // source1-digit + ld [%o1],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2] // Digit ablegen + addx %g0,%g0,%g1 // neuer Carry + sub %o0,32,%o0 + sub %o1,32,%o1 + subcc %o3,8,%o3 // noch mindestens 8 Digits abzuarbeiten? + bcc 1b + _ sub %o2,32,%o2 +#ifdef PIC + jmp %g2+8 +#else + retl +#endif + _ mov %g1,%o0 +#endif + +// extern uintD subx_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry); + DECLARE_FUNCTION(subx_loop_down) +C(subx_loop_down:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1, Output in %o0 +#if STANDARD_LOOPS + andcc %o3,%o3,%g0 + be 2f + _ mov %o4,%g1 // Carry + sub %o0,4,%o0 +1: ld [%o0],%o4 // source1-digit + sub %o1,4,%o1 + ld [%o1],%o5 // source2-digit + subcc %g0,%g1,%g0 // carry + subxcc %o4,%o5,%o4 // subtrahieren + addx %g0,%g0,%g1 // neuer Carry + sub %o2,4,%o2 + st %o4,[%o2] // Digit ablegen + subcc %o3,1,%o3 + bne 1b + _ sub %o0,4,%o0 +2: retl + _ mov %g1,%o0 +#endif +#if COUNTER_LOOPS + andcc %o3,%o3,%g0 + be 2f + _ mov %o4,%g1 // Carry + sub %o0,4,%o0 + sub %o1,4,%o1 + sll %o3,2,%o3 // %o3 = 4*count + sub %o0,%o3,%o0 // %o0 = &sourceptr1[-count-1] + sub %o1,%o3,%o1 // %o1 = &sourceptr2[-count-1] + sub %o2,%o3,%o2 // %o2 = &destptr[-count] +1: ld [%o0+%o3],%o4 // source1-digit + ld [%o1+%o3],%o5 // source2-digit + subcc %g0,%g1,%g0 // carry + subxcc %o4,%o5,%o4 // subtrahieren + addx %g0,%g0,%g1 // neuer Carry + subcc %o3,4,%o3 + bne 1b + _ st %o4,[%o2+%o3] // Digit ablegen +2: retl + _ mov %g1,%o0 +#endif +#if UNROLLED_LOOPS + and %o3,7,%o5 // count mod 8 + sll %o5,2,%g1 + sub %o0,%g1,%o0 // %o0 = &sourceptr1[-(count mod 8)] + sub %o1,%g1,%o1 // %o1 = &sourceptr2[-(count mod 8)] + sub %o2,%g1,%o2 // %o2 = &destptr[-(count mod 8)] + sll %o5,4,%o5 +#ifdef PIC + mov %o7,%g2 // save return address + call 0f // put address of label 0 into %o7 + _ add %o7,144,%g1 +0: +#else + set _subx_loop_down+176,%g1 +#endif + sub %g1,%o5,%g1 + jmp %g1 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8)) + _ subcc %g0,%o4,%g0 // carry initialisieren +1: subcc %g0,%g1,%g0 // carry + ld [%o0+28],%o4 // source1-digit + ld [%o1+28],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2+28] // Digit ablegen + ld [%o0+24],%o4 // source1-digit + ld [%o1+24],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2+24] // Digit ablegen + ld [%o0+20],%o4 // source1-digit + ld [%o1+20],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2+20] // Digit ablegen + ld [%o0+16],%o4 // source1-digit + ld [%o1+16],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2+16] // Digit ablegen + ld [%o0+12],%o4 // source1-digit + ld [%o1+12],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2+12] // Digit ablegen + ld [%o0+8],%o4 // source1-digit + ld [%o1+8],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2+8] // Digit ablegen + ld [%o0+4],%o4 // source1-digit + ld [%o1+4],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2+4] // Digit ablegen + ld [%o0],%o4 // source1-digit + ld [%o1],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2] // Digit ablegen + addx %g0,%g0,%g1 // neuer Carry + sub %o0,32,%o0 + sub %o1,32,%o1 + subcc %o3,8,%o3 // noch mindestens 8 Digits abzuarbeiten? + bcc 1b + _ sub %o2,32,%o2 +#ifdef PIC + jmp %g2+8 +#else + retl +#endif + _ mov %g1,%o0 +#endif + +// extern uintD subfrom_loop_down (uintD* sourceptr, uintD* destptr, uintC count); + DECLARE_FUNCTION(subfrom_loop_down) +C(subfrom_loop_down:) // Input in %o0,%o1,%o2, Output in %o0 +#if STANDARD_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ mov %g0,%o5 // Carry := 0 + sub %o0,4,%o0 +1: ld [%o0],%o3 // source-digit + sub %o1,4,%o1 + ld [%o1],%o4 // dest-digit + subcc %g0,%o5,%g0 // carry + subxcc %o4,%o3,%o4 // subtrahieren + addx %g0,%g0,%o5 // neuer Carry + st %o4,[%o1] // Digit ablegen + subcc %o2,1,%o2 + bne 1b + _ sub %o0,4,%o0 +2: retl + _ mov %o5,%o0 +#endif +#if COUNTER_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ mov %g0,%o5 // Carry := 0 + sub %o0,4,%o0 + sub %o1,4,%o1 + sll %o2,2,%o2 // %o2 = 4*count + sub %o0,%o2,%o0 // %o0 = &sourceptr[-count-1] + sub %o1,%o2,%o1 // %o1 = &destptr[-count-1] + ld [%o0+%o2],%o3 // source-digit +1: ld [%o1+%o2],%o4 // dest-digit + subcc %g0,%o5,%g0 // carry + subxcc %o4,%o3,%o4 // subtrahieren + addx %g0,%g0,%o5 // neuer Carry + st %o4,[%o1+%o2] // Digit ablegen + subcc %o2,4,%o2 + bne,a 1b + __ ld [%o0+%o2],%o3 // source-digit +2: retl + _ mov %o5,%o0 +#endif +#if UNROLLED_LOOPS + and %o2,7,%o3 // count mod 8 + sll %o3,2,%o4 + sub %o0,%o4,%o0 // %o0 = &sourceptr[-(count mod 8)] + sub %o1,%o4,%o1 // %o1 = &destptr[-(count mod 8)] + sll %o3,4,%o3 +#ifdef PIC + mov %o7,%g2 // save return address + call 0f // put address of label 0 into %o7 + _ add %o7,144,%o4 +0: +#else + set _subfrom_loop_down+172,%o4 +#endif + sub %o4,%o3,%o4 + jmp %o4 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8)) + _ subcc %g0,%g0,%g0 // carry löschen +1: subcc %g0,%o5,%g0 // carry + ld [%o0+28],%o3 // source-digit + ld [%o1+28],%o4 // dest-digit + subxcc %o4,%o3,%o4 // subtrahieren + st %o4,[%o1+28] // Digit ablegen + ld [%o0+24],%o3 // source-digit + ld [%o1+24],%o4 // dest-digit + subxcc %o4,%o3,%o4 // subtrahieren + st %o4,[%o1+24] // Digit ablegen + ld [%o0+20],%o3 // source-digit + ld [%o1+20],%o4 // dest-digit + subxcc %o4,%o3,%o4 // subtrahieren + st %o4,[%o1+20] // Digit ablegen + ld [%o0+16],%o3 // source-digit + ld [%o1+16],%o4 // dest-digit + subxcc %o4,%o3,%o4 // subtrahieren + st %o4,[%o1+16] // Digit ablegen + ld [%o0+12],%o3 // source-digit + ld [%o1+12],%o4 // dest-digit + subxcc %o4,%o3,%o4 // subtrahieren + st %o4,[%o1+12] // Digit ablegen + ld [%o0+8],%o3 // source-digit + ld [%o1+8],%o4 // dest-digit + subxcc %o4,%o3,%o4 // subtrahieren + st %o4,[%o1+8] // Digit ablegen + ld [%o0+4],%o3 // source-digit + ld [%o1+4],%o4 // dest-digit + subxcc %o4,%o3,%o4 // subtrahieren + st %o4,[%o1+4] // Digit ablegen + ld [%o0],%o3 // source-digit + ld [%o1],%o4 // dest-digit + subxcc %o4,%o3,%o4 // subtrahieren + st %o4,[%o1] // Digit ablegen + addx %g0,%g0,%o5 // neuer Carry + sub %o0,32,%o0 + subcc %o2,8,%o2 // noch mindestens 8 Digits abzuarbeiten? + bcc 1b + _ sub %o1,32,%o1 +#ifdef PIC + jmp %g2+8 +#else + retl +#endif + _ mov %o5,%o0 +#endif + +// extern uintD dec_loop_down (uintD* ptr, uintC count); + DECLARE_FUNCTION(dec_loop_down) +C(dec_loop_down:) // Input in %o0,%o1, Output in %o0 +#if STANDARD_LOOPS + andcc %o1,%o1,%g0 + be 2f + _ sub %o0,4,%o0 +1: ld [%o0],%o2 + subcc %o2,1,%o2 + bcc 3f + _ st %o2,[%o0] + subcc %o1,1,%o1 + bne 1b + _ sub %o0,4,%o0 +2: retl + _ mov -1,%o0 +3: retl + _ mov 0,%o0 +#endif +#if COUNTER_LOOPS + andcc %o1,%o1,%g0 + be 2f + _ sub %o0,4,%o0 + sll %o1,2,%o1 // %o1 = 4*count + sub %o0,%o1,%o0 // %o0 = &ptr[-count-1] + ld [%o0+%o1],%o2 // digit holen +1: subcc %o2,1,%o2 // decrementieren + bcc 3f + _ st %o2,[%o0+%o1] // ablegen + subcc %o1,4,%o1 // Zähler erniedrigen, Pointer erniedrigen + bne,a 1b + __ ld [%o0+%o1],%o2 +2: retl + _ mov -1,%o0 +3: retl + _ mov 0,%o0 +#endif + +// extern uintD neg_loop_down (uintD* ptr, uintC count); + DECLARE_FUNCTION(neg_loop_down) +C(neg_loop_down:) // Input in %o0,%o1, Output in %o0 +#if STANDARD_LOOPS + // erstes Digit /=0 suchen: + andcc %o1,%o1,%g0 + be 2f + _ sub %o0,4,%o0 +1: ld [%o0],%o2 + subcc %g0,%o2,%o2 + bne 3f + _ subcc %o1,1,%o1 + bne 1b + _ sub %o0,4,%o0 +2: retl + _ mov 0,%o0 +3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys + st %o2,[%o0] // 1 Digit negieren + // alle anderen Digits invertieren: + be 5f + _ sub %o0,4,%o0 +4: ld [%o0],%o2 + subcc %o1,1,%o1 + xor %o2,-1,%o2 + st %o2,[%o0] + bne 4b + _ sub %o0,4,%o0 +5: retl + _ mov -1,%o0 +#endif +#if COUNTER_LOOPS + // erstes Digit /=0 suchen: + andcc %o1,%o1,%g0 + be 2f + _ sub %o0,4,%o0 + sll %o1,2,%o1 // %o1 = 4*count + sub %o0,%o1,%o0 // %o0 = &ptr[-count-1] + ld [%o0+%o1],%o2 // digit holen +1: subcc %g0,%o2,%o2 // negieren, testen + bne 3f + _ subcc %o1,4,%o1 // Zähler erniedrigen, Pointer erniedrigen + bne,a 1b + __ ld [%o0+%o1],%o2 +2: retl + _ mov 0,%o0 +3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys + // alle anderen Digits invertieren: + add %o1,4,%o1 + st %o2,[%o0+%o1] // ablegen + subcc %o1,4,%o1 + be 5f + _ nop + ld [%o0+%o1],%o2 +4: xor %o2,-1,%o2 + st %o2,[%o0+%o1] + subcc %o1,4,%o1 + bne,a 4b + __ ld [%o0+%o1],%o2 +5: retl + _ mov -1,%o0 +#endif + +// extern uintD shift1left_loop_down (uintD* ptr, uintC count); + DECLARE_FUNCTION(shift1left_loop_down) +C(shift1left_loop_down:) // Input in %o0,%o1, Output in %o0 + andcc %o1,%o1,%g0 + be 2f + _ mov 0,%o3 // Carry := 0 + sub %o0,4,%o0 +1: ld [%o0],%o2 // Digit + subcc %g0,%o3,%g0 // carry + addxcc %o2,%o2,%o2 // shiften + addx %g0,%g0,%o3 // neues Carry + st %o2,[%o0] // Digit ablegen + subcc %o1,1,%o1 + bne 1b + _ sub %o0,4,%o0 +2: retl + _ mov %o3,%o0 + +// extern uintD shiftleft_loop_down (uintD* ptr, uintC count, uintC i, uintD carry); + DECLARE_FUNCTION(shiftleft_loop_down) +C(shiftleft_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0 + andcc %o1,%o1,%g0 + be 2f + _ sub %g0,%o2,%g1 // 32-i (mod 32) + sub %o0,4,%o0 +1: ld [%o0],%o4 // Digit + subcc %o1,1,%o1 + sll %o4,%o2,%o5 // dessen niedere (32-i) Bits + or %o3,%o5,%o5 // mit dem alten Carry kombinieren + st %o5,[%o0] // Digit ablegen + srl %o4,%g1,%o3 // dessen höchste i Bits liefern den neuen Carry + bne 1b + _ sub %o0,4,%o0 +2: retl + _ mov %o3,%o0 + +// extern uintD shiftleftcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i); + DECLARE_FUNCTION(shiftleftcopy_loop_down) +C(shiftleftcopy_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1,%g2, Output in %o0 + andcc %o2,%o2,%g0 + be 2f + _ mov 0,%o4 // Carry := 0 + sub %g0,%o3,%g1 // 32-i (mod 32) + sub %o0,4,%o0 +1: ld [%o0],%o5 // Digit + subcc %o2,1,%o2 + sll %o5,%o3,%g2 // dessen niedere (32-i) Bits + or %o4,%g2,%g2 // mit dem alten Carry kombinieren + sub %o1,4,%o1 + st %g2,[%o1] // Digit ablegen + srl %o5,%g1,%o4 // dessen höchste i Bits liefern den neuen Carry + bne 1b + _ sub %o0,4,%o0 +2: retl + _ mov %o4,%o0 + +// extern uintD shift1right_loop_up (uintD* ptr, uintC count, uintD carry); + DECLARE_FUNCTION(shift1right_loop_up) +C(shift1right_loop_up:) // Input in %o0,%o1,%o2, Output in %o0 + andcc %o1,%o1,%g0 + be 2f + _ sll %o2,31,%o2 // Carry +1: ld [%o0],%o3 // Digit + subcc %o1,1,%o1 + srl %o3,1,%o4 // shiften + or %o2,%o4,%o4 // und mit altem Carry kombinieren + st %o4,[%o0] // und ablegen + sll %o3,31,%o2 // neuer Carry + bne 1b + _ add %o0,4,%o0 +2: retl + _ mov %o2,%o0 + +// extern uintD shiftright_loop_up (uintD* ptr, uintC count, uintC i); + DECLARE_FUNCTION(shiftright_loop_up) +C(shiftright_loop_up:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0 + sub %g0,%o2,%g1 // 32-i (mod 32) + andcc %o1,%o1,%g0 + be 2f + _ or %g0,%g0,%o3 // Carry := 0 +1: ld [%o0],%o4 // Digit + subcc %o1,1,%o1 + srl %o4,%o2,%o5 // shiften + or %o3,%o5,%o5 // und mit altem Carry kombinieren + st %o5,[%o0] // und ablegen + sll %o4,%g1,%o3 // neuer Carry + bne 1b + _ add %o0,4,%o0 +2: retl + _ mov %o3,%o0 + +// extern uintD shiftrightsigned_loop_up (uintD* ptr, uintC count, uintC i); + DECLARE_FUNCTION(shiftrightsigned_loop_up) +C(shiftrightsigned_loop_up:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0 + ld [%o0],%o4 // erstes Digit + sub %g0,%o2,%g1 // 32-i (mod 32) + sra %o4,%o2,%o5 // shiften + st %o5,[%o0] // und ablegen + sll %o4,%g1,%o3 // neuer Carry + subcc %o1,1,%o1 + be 2f + _ add %o0,4,%o0 +1: ld [%o0],%o4 // Digit + subcc %o1,1,%o1 + srl %o4,%o2,%o5 // shiften + or %o3,%o5,%o5 // und mit altem Carry kombinieren + st %o5,[%o0] // und ablegen + sll %o4,%g1,%o3 // neuer Carry + bne 1b + _ add %o0,4,%o0 +2: retl + _ mov %o3,%o0 + +// extern uintD shiftrightcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry); + DECLARE_FUNCTION(shiftrightcopy_loop_up) +C(shiftrightcopy_loop_up:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1,%g2, Output in %o0 + sub %g0,%o3,%g1 // 32-i (mod 32) + andcc %o2,%o2,%g0 + be 2f + _ sll %o4,%g1,%g2 // erster Carry +1: ld [%o0],%o4 // Digit + add %o0,4,%o0 + srl %o4,%o3,%o5 // shiften + or %g2,%o5,%o5 // und mit altem Carry kombinieren + st %o5,[%o1] // und ablegen + sll %o4,%g1,%g2 // neuer Carry + subcc %o2,1,%o2 + bne 1b + _ add %o1,4,%o1 +2: retl + _ mov %g2,%o0 + +// extern uintD mulusmall_loop_down (uintD digit, uintD* ptr, uintC len, uintD newdigit); + DECLARE_FUNCTION(mulusmall_loop_down) +C(mulusmall_loop_down:) // Input in %o0,%o1,%o2,%o3, Output in %o0 + andcc %o2,%o2,%g0 + be 3f + _ sub %o1,4,%o1 +1: // nächstes Digit [%o1] mit der 6-Bit-Zahl %o0 multiplizieren + // und kleinen Carry %o3 dazu: + mov %o0,%y + ld [%o1],%o4 // Wartetakt! + addcc %o3,%o3,%o5 + mulscc %o5,%o4,%o5 + mulscc %o5,%o4,%o5 + mulscc %o5,%o4,%o5 + mulscc %o5,%o4,%o5 + mulscc %o5,%o4,%o5 + mulscc %o5,%o4,%o5 + mulscc %o5,%g0,%o5 + // Die 26 unteren Bits von %o5 und die 6 oberen Bits von %y + // ergeben das Resultat. (Die anderen Bits sind Null.) + tst %o4 // Korrektur, falls %o4 negativ war + bge 2f + _ sra %o5,26,%o3 // 6 obere Bits von %o5 -> neuer Carry + add %o3,%o0,%o3 // (falls %o4 negativ war, noch + %o0) +2: rd %y,%o4 + srl %o4,26,%o4 // 6 obere Bits von %y + sll %o5,6,%o5 // 26 untere Bits von %o5 + or %o5,%o4,%o4 // neues Digit + st %o4,[%o1] // ablegen + subcc %o2,1,%o2 + bne 1b + _ sub %o1,4,%o1 +3: retl + _ mov %o3,%o0 + +// extern void mulu_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); +#if !MULU32_INLINE + DECLARE_FUNCTION(mulu_loop_down) +C(mulu_loop_down:) // Input in %i0,%i1,%i2,%i3 + save %sp,-96,%sp + mov 0,%l0 // Carry +1: sub %i1,4,%i1 + ld [%i1],%o1 // nächstes Digit + call _mulu32_ // mit digit multiplizieren + _ mov %i0,%o0 + addcc %l0,%o0,%o0 // und bisherigen Carry addieren + addx %g0,%g1,%l0 // High-Digit gibt neuen Carry + sub %i2,4,%i2 + subcc %i3,1,%i3 + bne 1b + _ st %o0,[%i2] // Low-Digit ablegen + st %l0,[%i2-4] // letzten Carry ablegen + ret + _ restore +#else + DECLARE_FUNCTION(mulu_loop_down) +C(mulu_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1 + mov 0,%o4 // Carry +1: ld [%o1-4],%g1 // nächstes Digit + // mit digit multiplizieren: %o0 * %g1 -> %o5|%g1 +#ifdef sparcv8 + sub %o1,4,%o1 + umul %g1,%o0,%g1 + rd %y,%o5 +#else + mov %g1,%y + sub %o1,4,%o1 // Wartetakt! + andcc %g0,%g0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%g0,%o5 + tst %o0 + bl,a 2f + __ add %o5,%g1,%o5 +2: rd %y,%g1 +#endif + addcc %o4,%g1,%g1 // und bisherigen Carry addieren + addx %g0,%o5,%o4 // High-Digit gibt neuen Carry + sub %o2,4,%o2 + subcc %o3,1,%o3 + bne 1b + _ st %g1,[%o2] // Low-Digit ablegen + retl + _ st %o4,[%o2-4] // letzten Carry ablegen +#endif + +// extern uintD muluadd_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); + DECLARE_FUNCTION(muluadd_loop_down) +C(muluadd_loop_down:) // Input in %i0,%i1,%i2,%i3, Output in %i0 +#if !MULU32_INLINE + save %sp,-96,%sp + mov 0,%l0 // Carry +1: sub %i1,4,%i1 + ld [%i1],%o1 // nächstes source-Digit + call _mulu32_ // mit digit multiplizieren + _ mov %i0,%o0 + sub %i2,4,%i2 + ld [%i2],%o1 // nächstes dest-digit + addcc %l0,%o0,%o0 // und bisherigen Carry addieren + addx %g0,%g1,%l0 // High-Digit gibt neuen Carry + addcc %o1,%o0,%o0 // addieren + addx %g0,%l0,%l0 + subcc %i3,1,%i3 + bne 1b + _ st %o0,[%i2] // Low-Digit ablegen + mov %l0,%i0 // letzter Carry + ret + _ restore +#else + save %sp,-96,%sp + mov 0,%l0 // Carry +#ifndef sparcv8 + sra %i0,31,%l1 // 0 falls %i0>=0, -1 falls %i0<0 +#endif +1: ld [%i1-4],%o1 // nächstes source-Digit + sub %i1,4,%i1 + // mit digit multiplizieren: %i0 * %o1 -> %o2|%o0 +#ifdef sparcv8 + umul %i0,%o1,%o0 + rd %y,%o2 +#else + mov %o1,%y + and %o1,%l1,%o3 // Wartetakt! + andcc %g0,%g0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%g0,%o2 + add %o2,%o3,%o2 // %o3 = (0 falls %i0>=0, %o1 falls %i0<0) + rd %y,%o0 +#endif + sub %i2,4,%i2 + ld [%i2],%o1 // nächstes dest-digit + addcc %l0,%o0,%o0 // und bisherigen Carry addieren + addx %g0,%o2,%l0 // High-Digit gibt neuen Carry + addcc %o1,%o0,%o0 // addieren + addx %g0,%l0,%l0 + subcc %i3,1,%i3 + bne 1b + _ st %o0,[%i2] // Low-Digit ablegen + mov %l0,%i0 // letzter Carry + ret + _ restore +#endif + +// extern uintD mulusub_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); + DECLARE_FUNCTION(mulusub_loop_down) +C(mulusub_loop_down:) // Input in %i0,%i1,%i2,%i3, Output in %i0 +#if !MULU32_INLINE + save %sp,-96,%sp + mov 0,%l0 // Carry +1: sub %i1,4,%i1 + ld [%i1],%o1 // nächstes source-Digit + call _mulu32_ // mit digit multiplizieren + _ mov %i0,%o0 + sub %i2,4,%i2 + ld [%i2],%o1 // nächstes dest-digit + addcc %l0,%o0,%o0 // und bisherigen Carry addieren + addx %g0,%g1,%l0 // High-Digit gibt neuen Carry + subcc %o1,%o0,%o1 // davon das Low-Digit subtrahieren + addx %g0,%l0,%l0 + subcc %i3,1,%i3 + bne 1b + _ st %o1,[%i2] // dest-Digit ablegen + mov %l0,%i0 // letzter Carry + ret + _ restore +#else + save %sp,-96,%sp + mov 0,%l0 // Carry +#ifndef sparcv8 + sra %i0,31,%l1 // 0 falls %i0>=0, -1 falls %i0<0 +#endif +1: ld [%i1-4],%o1 // nächstes source-Digit + sub %i1,4,%i1 + // mit digit multiplizieren: %i0 * %o1 -> %o2|%o0 +#ifdef sparcv8 + umul %i0,%o1,%o0 + rd %y,%o2 +#else + mov %o1,%y + and %o1,%l1,%o3 // Wartetakt! + andcc %g0,%g0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%g0,%o2 + add %o2,%o3,%o2 // %o3 = (0 falls %i0>=0, %o1 falls %i0<0) + rd %y,%o0 +#endif + sub %i2,4,%i2 + ld [%i2],%o1 // nächstes dest-digit + addcc %l0,%o0,%o0 // und bisherigen Carry addieren + addx %g0,%o2,%l0 // High-Digit gibt neuen Carry + subcc %o1,%o0,%o1 // davon das Low-Digit subtrahieren + addx %g0,%l0,%l0 + subcc %i3,1,%i3 + bne 1b + _ st %o1,[%i2] // dest-Digit ablegen + mov %l0,%i0 // letzter Carry + ret + _ restore +#endif + +// extern uintD divu_loop_up (uintD digit, uintD* ptr, uintC len); + DECLARE_FUNCTION(divu_loop_up) +C(divu_loop_up:) // Input in %i0,%i1,%i2, Output in %i0 + save %sp,-96,%sp + andcc %i2,%i2,%g0 + be 2f + _ mov 0,%g1 // Rest +1: mov %g1,%o0 // Rest als High-Digit + ld [%i1],%o1 // nächstes Digit als Low-Digit + call C(divu_6432_3232_) // zusammen durch digit dividieren + _ mov %i0,%o2 + st %o0,[%i1] // Quotient ablegen, Rest in %g1 + subcc %i2,1,%i2 + bne 1b + _ add %i1,4,%i1 +2: mov %g1,%i0 // Rest als Ergebnis + ret + _ restore + +// extern uintD divucopy_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); + DECLARE_FUNCTION(divucopy_loop_up) +C(divucopy_loop_up:) // Input in %i0,%i1,%i2,%i3, Output in %i0 + save %sp,-96,%sp + andcc %i3,%i3,%g0 + be 2f + _ mov 0,%g1 // Rest +1: mov %g1,%o0 // Rest als High-Digit + ld [%i1],%o1 // nächstes Digit als Low-Digit + call C(divu_6432_3232_) // zusammen durch digit dividieren + _ mov %i0,%o2 + st %o0,[%i2] // Quotient ablegen, Rest in %g1 + add %i1,4,%i1 + subcc %i3,1,%i3 + bne 1b + _ add %i2,4,%i2 +2: mov %g1,%i0 // Rest als Ergebnis + ret + _ restore + +#endif + +#if !CL_DS_BIG_ENDIAN_P + +// extern void or_loop_down (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(or_loop_down) +C(or_loop_down:) // Input in %o0,%o1,%o2 +#if SLOW_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sub %o0,4,%o0 +1: ld [%o0],%o3 + sub %o1,4,%o1 + ld [%o1],%o4 + subcc %o2,1,%o2 + or %o3,%o4,%o3 + st %o3,[%o0] + bne 1b + _ sub %o0,4,%o0 +2: retl + _ nop +#endif +#if STANDARD_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr + sub %o0,4,%o0 +1: ld [%o0],%o3 // *xptr + ld [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + or %o3,%o4,%o3 // verknüpfen + st %o3,[%o0] // =: *xptr + bne 1b + _ sub %o0,4,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sll %o2,2,%o2 // %o2 = 4*count + sub %o0,%o2,%o0 // %o0 = &xptr[-count] + sub %o1,%o2,%o1 // %o1 = &yptr[-count] +1: subcc %o2,4,%o2 // Zähler erniedrigen, Pointer erniedrigen + ld [%o1+%o2],%o3 // nächstes Digit holen + ld [%o0+%o2],%o4 // noch ein Digit holen + or %o4,%o3,%o3 // beide verknüpfen + bne 1b + _ st %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +// extern void xor_loop_down (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(xor_loop_down) +C(xor_loop_down:) // Input in %o0,%o1,%o2 +#if SLOW_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sub %o0,4,%o0 +1: ld [%o0],%o3 + sub %o1,4,%o1 + ld [%o1],%o4 + subcc %o2,1,%o2 + xor %o3,%o4,%o3 + st %o3,[%o0] + bne 1b + _ sub %o0,4,%o0 +2: retl + _ nop +#endif +#if STANDARD_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr + sub %o0,4,%o0 +1: ld [%o0],%o3 // *xptr + ld [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + xor %o3,%o4,%o3 // verknüpfen + st %o3,[%o0] // =: *xptr + bne 1b + _ sub %o0,4,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sll %o2,2,%o2 // %o2 = 4*count + sub %o0,%o2,%o0 // %o0 = &xptr[-count] + sub %o1,%o2,%o1 // %o1 = &yptr[-count] +1: subcc %o2,4,%o2 // Zähler erniedrigen, Pointer erniedrigen + ld [%o1+%o2],%o3 // nächstes Digit holen + ld [%o0+%o2],%o4 // noch ein Digit holen + xor %o4,%o3,%o3 // beide verknüpfen + bne 1b + _ st %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +// extern void and_loop_down (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(and_loop_down) +C(and_loop_down:) // Input in %o0,%o1,%o2 +#if SLOW_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sub %o0,4,%o0 +1: ld [%o0],%o3 + sub %o1,4,%o1 + ld [%o1],%o4 + subcc %o2,1,%o2 + and %o3,%o4,%o3 + st %o3,[%o0] + bne 1b + _ sub %o0,4,%o0 +2: retl + _ nop +#endif +#if STANDARD_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr + sub %o0,4,%o0 +1: ld [%o0],%o3 // *xptr + ld [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + and %o3,%o4,%o3 // verknüpfen + st %o3,[%o0] // =: *xptr + bne 1b + _ sub %o0,4,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sll %o2,2,%o2 // %o2 = 4*count + sub %o0,%o2,%o0 // %o0 = &xptr[-count] + sub %o1,%o2,%o1 // %o1 = &yptr[-count] +1: subcc %o2,4,%o2 // Zähler erniedrigen, Pointer erniedrigen + ld [%o1+%o2],%o3 // nächstes Digit holen + ld [%o0+%o2],%o4 // noch ein Digit holen + and %o4,%o3,%o3 // beide verknüpfen + bne 1b + _ st %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +// extern void eqv_loop_down (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(eqv_loop_down) +C(eqv_loop_down:) // Input in %o0,%o1,%o2 +#if SLOW_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sub %o0,4,%o0 +1: ld [%o0],%o3 + sub %o1,4,%o1 + ld [%o1],%o4 + subcc %o2,1,%o2 + xnor %o3,%o4,%o3 + st %o3,[%o0] + bne 1b + _ sub %o0,4,%o0 +2: retl + _ nop +#endif +#if STANDARD_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr + sub %o0,4,%o0 +1: ld [%o0],%o3 // *xptr + ld [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + xnor %o3,%o4,%o3 // verknüpfen + st %o3,[%o0] // =: *xptr + bne 1b + _ sub %o0,4,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sll %o2,2,%o2 // %o2 = 4*count + sub %o0,%o2,%o0 // %o0 = &xptr[-count] + sub %o1,%o2,%o1 // %o1 = &yptr[-count] +1: subcc %o2,4,%o2 // Zähler erniedrigen, Pointer erniedrigen + ld [%o1+%o2],%o3 // nächstes Digit holen + ld [%o0+%o2],%o4 // noch ein Digit holen + xnor %o4,%o3,%o3 // beide verknüpfen + bne 1b + _ st %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +// extern void nand_loop_down (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(nand_loop_down) +C(nand_loop_down:) // Input in %o0,%o1,%o2 +#if SLOW_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sub %o0,4,%o0 +1: ld [%o0],%o3 + sub %o1,4,%o1 + ld [%o1],%o4 + subcc %o2,1,%o2 + and %o3,%o4,%o3 + xor %o3,-1,%o3 + st %o3,[%o0] + bne 1b + _ sub %o0,4,%o0 +2: retl + _ nop +#endif +#if STANDARD_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr + sub %o0,4,%o0 +1: ld [%o0],%o3 // *xptr + ld [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + and %o3,%o4,%o3 // verknüpfen + xor %o3,-1,%o3 + st %o3,[%o0] // =: *xptr + bne 1b + _ sub %o0,4,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sll %o2,2,%o2 // %o2 = 4*count + sub %o0,%o2,%o0 // %o0 = &xptr[-count] + sub %o1,%o2,%o1 // %o1 = &yptr[-count] +1: subcc %o2,4,%o2 // Zähler erniedrigen, Pointer erniedrigen + ld [%o1+%o2],%o3 // nächstes Digit holen + ld [%o0+%o2],%o4 // noch ein Digit holen + and %o4,%o3,%o3 // beide verknüpfen + xor %o3,-1,%o3 + bne 1b + _ st %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +// extern void nor_loop_down (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(nor_loop_down) +C(nor_loop_down:) // Input in %o0,%o1,%o2 +#if SLOW_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sub %o0,4,%o0 +1: ld [%o0],%o3 + sub %o1,4,%o1 + ld [%o1],%o4 + subcc %o2,1,%o2 + or %o3,%o4,%o3 + xor %o3,-1,%o3 + st %o3,[%o0] + bne 1b + _ sub %o0,4,%o0 +2: retl + _ nop +#endif +#if STANDARD_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr + sub %o0,4,%o0 +1: ld [%o0],%o3 // *xptr + ld [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + or %o3,%o4,%o3 // verknüpfen + xor %o3,-1,%o3 + st %o3,[%o0] // =: *xptr + bne 1b + _ sub %o0,4,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sll %o2,2,%o2 // %o2 = 4*count + sub %o0,%o2,%o0 // %o0 = &xptr[-count] + sub %o1,%o2,%o1 // %o1 = &yptr[-count] +1: subcc %o2,4,%o2 // Zähler erniedrigen, Pointer erniedrigen + ld [%o1+%o2],%o3 // nächstes Digit holen + ld [%o0+%o2],%o4 // noch ein Digit holen + or %o4,%o3,%o3 // beide verknüpfen + xor %o3,-1,%o3 + bne 1b + _ st %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +// extern void andc2_loop_down (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(andc2_loop_down) +C(andc2_loop_down:) // Input in %o0,%o1,%o2 +#if SLOW_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sub %o0,4,%o0 +1: ld [%o0],%o3 + sub %o1,4,%o1 + ld [%o1],%o4 + subcc %o2,1,%o2 + andn %o3,%o4,%o3 + st %o3,[%o0] + bne 1b + _ sub %o0,4,%o0 +2: retl + _ nop +#endif +#if STANDARD_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr + sub %o0,4,%o0 +1: ld [%o0],%o3 // *xptr + ld [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + andn %o3,%o4,%o3 // verknüpfen + st %o3,[%o0] // =: *xptr + bne 1b + _ sub %o0,4,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sll %o2,2,%o2 // %o2 = 4*count + sub %o0,%o2,%o0 // %o0 = &xptr[-count] + sub %o1,%o2,%o1 // %o1 = &yptr[-count] +1: subcc %o2,4,%o2 // Zähler erniedrigen, Pointer erniedrigen + ld [%o1+%o2],%o3 // nächstes Digit holen + ld [%o0+%o2],%o4 // noch ein Digit holen + andn %o4,%o3,%o3 // beide verknüpfen + bne 1b + _ st %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +// extern void orc2_loop_down (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(orc2_loop_down) +C(orc2_loop_down:) // Input in %o0,%o1,%o2 +#if SLOW_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sub %o0,4,%o0 +1: ld [%o0],%o3 + sub %o1,4,%o1 + ld [%o1],%o4 + subcc %o2,1,%o2 + orn %o3,%o4,%o3 + st %o3,[%o0] + bne 1b + _ sub %o0,4,%o0 +2: retl + _ nop +#endif +#if STANDARD_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sub %o1,%o0,%o1 // %o1 = yptr-xptr + sub %o0,4,%o0 +1: ld [%o0],%o3 // *xptr + ld [%o0+%o1],%o4 // *yptr + subcc %o2,1,%o2 + orn %o3,%o4,%o3 // verknüpfen + st %o3,[%o0] // =: *xptr + bne 1b + _ sub %o0,4,%o0 // xptr++, yptr++ +2: retl + _ nop +#endif +#if COUNTER_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ sll %o2,2,%o2 // %o2 = 4*count + sub %o0,%o2,%o0 // %o0 = &xptr[-count] + sub %o1,%o2,%o1 // %o1 = &yptr[-count] +1: subcc %o2,4,%o2 // Zähler erniedrigen, Pointer erniedrigen + ld [%o1+%o2],%o3 // nächstes Digit holen + ld [%o0+%o2],%o4 // noch ein Digit holen + orn %o4,%o3,%o3 // beide verknüpfen + bne 1b + _ st %o3,[%o1+%o2] // Digit ablegen +2: retl + _ nop +#endif + +// extern void not_loop_down (uintD* xptr, uintC count); + DECLARE_FUNCTION(not_loop_down) +C(not_loop_down:) // Input in %o0,%o1 +#if STANDARD_LOOPS + andcc %o1,%o1,%g0 + be 2f + _ sub %o0,4,%o0 +1: ld [%o0],%o2 + subcc %o1,1,%o1 + xor %o2,-1,%o2 + st %o2,[%o0] + bne 1b + _ sub %o0,4,%o0 +2: retl + _ nop +#endif +#if COUNTER_LOOPS + andcc %o1,%o1,%g0 + be 2f + _ sll %o1,2,%o1 // %o1 = 4*count + sub %o0,%o1,%o0 // %o0 = &destptr[-count] +1: subcc %o1,4,%o1 // Zähler erniedrigen, Pointer erniedrigen + ld [%o0+%o1],%o2 // nächstes Digit holen + xor %o2,-1,%o2 + bne 1b + _ st %o2,[%o0+%o1] // Digit ablegen +2: retl + _ nop +#endif + +// extern boolean and_test_loop_down (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(and_test_loop_down) +C(and_test_loop_down:) // Input in %o0,%o1,%o2, Output in %o0 +#if STANDARD_LOOPS + andcc %o2,%o2,%g0 + be 4f + _ sub %o0,4,%o0 +1: ld [%o0],%o3 + sub %o1,4,%o1 + ld [%o1],%o4 + subcc %o2,1,%o2 + be 3f + _ andcc %o3,%o4,%g0 + be 1b + _ sub %o0,4,%o0 +2: retl + _ mov 1,%o0 +3: bne 2b + _ nop +4: retl + _ mov 0,%o0 +#endif +#if COUNTER_LOOPS + sll %o2,2,%o2 // %o2 = 4*count + sub %o0,%o2,%o0 // %o0 = &xptr[-count] + sub %o1,%o2,%o1 // %o1 = &yptr[-count] + subcc %o2,4,%o2 + bcs 2f + _ nop + ld [%o0+%o2],%o3 // nächstes Digit holen +1: ld [%o1+%o2],%o4 // noch ein Digit holen + andcc %o3,%o4,%g0 // beide verknüpfen + bne 3f + _ subcc %o2,4,%o2 // Zähler erniedrigen, Pointer erniedrigen + bcc,a 1b + __ ld [%o0+%o2],%o3 // nächstes Digit holen +2: retl + _ mov 0,%o0 +3: retl + _ mov 1,%o0 +#endif + +// extern cl_signean compare_loop_down (uintD* xptr, uintD* yptr, uintC count); + DECLARE_FUNCTION(compare_loop_down) +C(compare_loop_down:) // Input in %o0,%o1,%o2, Output in %o0 +#if STANDARD_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ nop +1: ld [%o0-4],%o3 + ld [%o1-4],%o4 + subcc %o3,%o4,%g0 + bne 3f + _ sub %o0,4,%o0 + subcc %o2,1,%o2 + bne 1b + _ sub %o1,4,%o1 +2: retl + _ mov 0,%o0 +3: blu 4f + _ nop + retl + _ mov 1,%o0 +4: retl + _ mov -1,%o0 +#endif +#if COUNTER_LOOPS + sll %o2,2,%o2 // %o2 = 4*count + sub %o0,%o2,%o0 // %o0 = &xptr[-count] + sub %o1,%o2,%o1 // %o1 = &yptr[-count] + subcc %o2,4,%o2 + bcs 5f + _ nop + ld [%o0+%o2],%o3 // nächstes Digit holen +1: ld [%o1+%o2],%o4 // noch ein Digit holen + subcc %o2,4,%o2 // Zähler erniedrigen, Pointer erniedrigen + bcs 4f + _ subcc %o3,%o4,%g0 // vergleichen + be,a 1b + __ ld [%o0+%o2],%o3 // nächstes Digit holen +2: blu 3f + _ nop + retl + _ mov 1,%o0 +3: retl + _ mov -1,%o0 +4: bne 2b + _ nop +5: retl + _ mov 0,%o0 +#endif + +// extern uintD add_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count); + DECLARE_FUNCTION(add_loop_up) +C(add_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0 +#if STANDARD_LOOPS + andcc %o3,%o3,%g0 + be 2f + _ subcc %g0,%g0,%g0 // Carry := 0 +1: ld [%o0],%o4 // source1-digit + add %o0,4,%o0 + ld [%o1],%o5 // source2-digit + add %o1,4,%o1 + addxcc %o4,%o5,%o4 // addieren + addx %g0,%g0,%g1 // neuer Carry + st %o4,[%o2] // Digit ablegen + add %o2,4,%o2 + subcc %o3,1,%o3 + bne 1b + _ subcc %g0,%g1,%g0 // carry +2: retl + _ addx %g0,%g0,%o0 +#endif +#if COUNTER_LOOPS + subcc %g0,%o3,%o3 // %o3 = -count + be 2f + _ mov %g0,%g1 // Carry := 0 + sll %o3,2,%o3 // %o3 = -4*count + sub %o2,4,%o2 + sub %o0,%o3,%o0 // %o0 = &sourceptr1[count] + sub %o1,%o3,%o1 // %o1 = &sourceptr2[count] + sub %o2,%o3,%o2 // %o2 = &destptr[count-1] +1: ld [%o0+%o3],%o4 // source1-digit + ld [%o1+%o3],%o5 // source2-digit + subcc %g0,%g1,%g0 // carry + addxcc %o4,%o5,%o4 // addieren + addx %g0,%g0,%g1 // neuer Carry + addcc %o3,4,%o3 // Zähler erniedrigen, Pointer erhöhen + bne 1b + _ st %o4,[%o2+%o3] // Digit ablegen +2: retl + _ mov %g1,%o0 +#endif +#if UNROLLED_LOOPS + and %o3,7,%o4 // count mod 8 + sll %o4,2,%o5 + add %o0,%o5,%o0 // %o0 = &sourceptr1[count mod 8] + add %o1,%o5,%o1 // %o1 = &sourceptr2[count mod 8] + add %o2,%o5,%o2 // %o2 = &destptr[count mod 8] + sll %o4,4,%o4 +#ifdef PIC + mov %o7,%g2 // save return address + call 0f // put address of label 0 into %o7 + _ add %o7,144,%o5 +0: +#else + set _add_loop_up+176,%o5 +#endif + sub %o5,%o4,%o5 + jmp %o5 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8)) + _ subcc %g0,%g0,%g0 // carry löschen +1: subcc %g0,%g1,%g0 // carry + ld [%o0-32],%o4 // source1-digit + ld [%o1-32],%o5 // source2-digit + addxcc %o5,%o4,%o5 // addieren + st %o5,[%o2-32] // Digit ablegen + ld [%o0-28],%o4 // source1-digit + ld [%o1-28],%o5 // source2-digit + addxcc %o5,%o4,%o5 // addieren + st %o5,[%o2-28] // Digit ablegen + ld [%o0-24],%o4 // source1-digit + ld [%o1-24],%o5 // source2-digit + addxcc %o5,%o4,%o5 // addieren + st %o5,[%o2-24] // Digit ablegen + ld [%o0-20],%o4 // source1-digit + ld [%o1-20],%o5 // source2-digit + addxcc %o5,%o4,%o5 // addieren + st %o5,[%o2-20] // Digit ablegen + ld [%o0-16],%o4 // source1-digit + ld [%o1-16],%o5 // source2-digit + addxcc %o5,%o4,%o5 // addieren + st %o5,[%o2-16] // Digit ablegen + ld [%o0-12],%o4 // source1-digit + ld [%o1-12],%o5 // source2-digit + addxcc %o5,%o4,%o5 // addieren + st %o5,[%o2-12] // Digit ablegen + ld [%o0-8],%o4 // source1-digit + ld [%o1-8],%o5 // source2-digit + addxcc %o5,%o4,%o5 // addieren + st %o5,[%o2-8] // Digit ablegen + ld [%o0-4],%o4 // source1-digit + ld [%o1-4],%o5 // source2-digit + addxcc %o5,%o4,%o5 // addieren + st %o5,[%o2-4] // Digit ablegen + addx %g0,%g0,%g1 // neuer Carry + add %o0,32,%o0 + add %o1,32,%o1 + subcc %o3,8,%o3 // noch mindestens 8 Digits abzuarbeiten? + bcc 1b + _ add %o2,32,%o2 +#ifdef PIC + jmp %g2+8 +#else + retl +#endif + _ mov %g1,%o0 +#endif + +// extern uintD addto_loop_up (uintD* sourceptr, uintD* destptr, uintC count); + DECLARE_FUNCTION(addto_loop_up) +C(addto_loop_up:) // Input in %o0,%o1,%o2, Output in %o0 +#if STANDARD_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ mov %g0,%o5 // Carry := 0 +1: ld [%o0],%o3 // source-digit + add %o0,4,%o0 + ld [%o1],%o4 // dest-digit + subcc %g0,%o5,%g0 // carry + addxcc %o4,%o3,%o4 // addieren + addx %g0,%g0,%o5 // neuer Carry + st %o4,[%o1] // Digit ablegen + subcc %o2,1,%o2 + bne 1b + _ add %o1,4,%o1 +2: retl + _ mov %o5,%o0 +#endif +#if COUNTER_LOOPS + subcc %g0,%o2,%o2 // %o2 = -count + be 2f + _ mov %g0,%o5 // Carry := 0 + sll %o2,2,%o2 // %o2 = -4*count + sub %o0,%o2,%o0 // %o0 = &sourceptr[count] + sub %o1,%o2,%o1 // %o1 = &destptr[count] + ld [%o0+%o2],%o3 // source-digit +1: ld [%o1+%o2],%o4 // dest-digit + subcc %g0,%o5,%g0 // carry + addxcc %o4,%o3,%o4 // addieren + addx %g0,%g0,%o5 // neuer Carry + st %o4,[%o1+%o2] // Digit ablegen + addcc %o2,4,%o2 // Zähler erniedrigen, Pointer erhöhen + bne,a 1b + __ ld [%o0+%o2],%o3 // source-digit +2: retl + _ mov %o5,%o0 +#endif +#if UNROLLED_LOOPS + and %o2,7,%o3 // count mod 8 + sll %o3,2,%o4 + add %o0,%o4,%o0 // %o0 = &sourceptr[count mod 8] + add %o1,%o4,%o1 // %o1 = &destptr[count mod 8] + sll %o3,4,%o3 +#ifdef PIC + mov %o7,%g2 // save return address + call 0f // put address of label 0 into %o7 + _ add %o7,144,%o4 +0: +#else + set _addto_loop_up+172,%o4 +#endif + sub %o4,%o3,%o4 + jmp %o4 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8)) + _ subcc %g0,%g0,%g0 // carry löschen +1: subcc %g0,%o5,%g0 // carry + ld [%o0-32],%o3 // source-digit + ld [%o1-32],%o4 // dest-digit + addxcc %o4,%o3,%o4 // addieren + st %o4,[%o1-32] // Digit ablegen + ld [%o0-28],%o3 // source-digit + ld [%o1-28],%o4 // dest-digit + addxcc %o4,%o3,%o4 // addieren + st %o4,[%o1-28] // Digit ablegen + ld [%o0-24],%o3 // source-digit + ld [%o1-24],%o4 // dest-digit + addxcc %o4,%o3,%o4 // addieren + st %o4,[%o1-24] // Digit ablegen + ld [%o0-20],%o3 // source-digit + ld [%o1-20],%o4 // dest-digit + addxcc %o4,%o3,%o4 // addieren + st %o4,[%o1-20] // Digit ablegen + ld [%o0-16],%o3 // source-digit + ld [%o1-16],%o4 // dest-digit + addxcc %o4,%o3,%o4 // addieren + st %o4,[%o1-16] // Digit ablegen + ld [%o0-12],%o3 // source-digit + ld [%o1-12],%o4 // dest-digit + addxcc %o4,%o3,%o4 // addieren + st %o4,[%o1-12] // Digit ablegen + ld [%o0-8],%o3 // source-digit + ld [%o1-8],%o4 // dest-digit + addxcc %o4,%o3,%o4 // addieren + st %o4,[%o1-8] // Digit ablegen + ld [%o0-4],%o3 // source-digit + ld [%o1-4],%o4 // dest-digit + addxcc %o4,%o3,%o4 // addieren + st %o4,[%o1-4] // Digit ablegen + addx %g0,%g0,%o5 // neuer Carry + add %o0,32,%o0 + subcc %o2,8,%o2 // noch mindestens 8 Digits abzuarbeiten? + bcc 1b + _ add %o1,32,%o1 +#ifdef PIC + jmp %g2+8 +#else + retl +#endif + _ mov %o5,%o0 +#endif + +// extern uintD inc_loop_up (uintD* ptr, uintC count); + DECLARE_FUNCTION(inc_loop_up) +C(inc_loop_up:) // Input in %o0,%o1, Output in %o0 +#if STANDARD_LOOPS + andcc %o1,%o1,%g0 + be 2f + _ nop + ld [%o0],%o2 +1: add %o0,4,%o0 + addcc %o2,1,%o2 + bne 3f + _ st %o2,[%o0-4] + subcc %o1,1,%o1 + bne,a 1b + __ ld [%o0],%o2 +2: retl + _ mov 1,%o0 +3: retl + _ mov 0,%o0 +#endif +#if COUNTER_LOOPS + subcc %g0,%o1,%o1 // %o1 = -count + be 2f + _ sll %o1,2,%o1 // %o1 = -4*count + sub %o0,%o1,%o0 // %o0 = &ptr[count] + ld [%o0+%o1],%o2 // digit holen +1: addcc %o2,1,%o2 // incrementieren + bne 3f + _ st %o2,[%o0+%o1] // ablegen + addcc %o1,4,%o1 // Zähler erniedrigen, Pointer erhöhen + bne,a 1b + __ ld [%o0+%o1],%o2 +2: retl + _ mov 1,%o0 +3: retl + _ mov 0,%o0 +#endif + +// extern uintD sub_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count); + DECLARE_FUNCTION(sub_loop_up) +C(sub_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0 +#if STANDARD_LOOPS + andcc %o3,%o3,%g0 + be 2f + _ subcc %g0,%g0,%g0 // Carry := 0 +1: ld [%o0],%o4 // source1-digit + add %o0,4,%o0 + ld [%o1],%o5 // source2-digit + add %o1,4,%o1 + subxcc %o4,%o5,%o4 // subtrahieren + addx %g0,%g0,%g1 // neuer Carry + st %o4,[%o2] // Digit ablegen + add %o2,4,%o2 + subcc %o3,1,%o3 + bne 1b + _ subcc %g0,%g1,%g0 // carry +2: retl + _ addx %g0,%g0,%o0 +#endif +#if COUNTER_LOOPS + subcc %g0,%o3,%o3 // %o3 = -count + be 2f + _ mov %g0,%g1 // Carry := 0 + sll %o3,2,%o3 // %o3 = -4*count + sub %o2,4,%o2 + sub %o0,%o3,%o0 // %o0 = &sourceptr1[count] + sub %o1,%o3,%o1 // %o1 = &sourceptr2[count] + sub %o2,%o3,%o2 // %o2 = &destptr[count-1] +1: ld [%o0+%o3],%o4 // source1-digit + ld [%o1+%o3],%o5 // source2-digit + subcc %g0,%g1,%g0 // carry + subxcc %o4,%o5,%o4 // subtrahieren + addx %g0,%g0,%g1 // neuer Carry + addcc %o3,4,%o3 + bne 1b + _ st %o4,[%o2+%o3] // Digit ablegen +2: retl + _ mov %g1,%o0 +#endif +#if UNROLLED_LOOPS + and %o3,7,%o4 // count mod 8 + sll %o4,2,%o5 + add %o0,%o5,%o0 // %o0 = &sourceptr1[count mod 8] + add %o1,%o5,%o1 // %o1 = &sourceptr2[count mod 8] + add %o2,%o5,%o2 // %o2 = &destptr[count mod 8] + sll %o4,4,%o4 +#ifdef PIC + mov %o7,%g2 // save return address + call 0f // put address of label 0 into %o7 + _ add %o7,144,%o5 +0: +#else + set _sub_loop_up+176,%o5 +#endif + sub %o5,%o4,%o5 + jmp %o5 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8)) + _ subcc %g0,%g0,%g0 // carry löschen +1: subcc %g0,%g1,%g0 // carry + ld [%o0-32],%o4 // source1-digit + ld [%o1-32],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2-32] // Digit ablegen + ld [%o0-28],%o4 // source1-digit + ld [%o1-28],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2-28] // Digit ablegen + ld [%o0-24],%o4 // source1-digit + ld [%o1-24],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2-24] // Digit ablegen + ld [%o0-20],%o4 // source1-digit + ld [%o1-20],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2-20] // Digit ablegen + ld [%o0-16],%o4 // source1-digit + ld [%o1-16],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2-16] // Digit ablegen + ld [%o0-12],%o4 // source1-digit + ld [%o1-12],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2-12] // Digit ablegen + ld [%o0-8],%o4 // source1-digit + ld [%o1-8],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2-8] // Digit ablegen + ld [%o0-4],%o4 // source1-digit + ld [%o1-4],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2-4] // Digit ablegen + addx %g0,%g0,%g1 // neuer Carry + add %o0,32,%o0 + add %o1,32,%o1 + subcc %o3,8,%o3 // noch mindestens 8 Digits abzuarbeiten? + bcc 1b + _ add %o2,32,%o2 +#ifdef PIC + jmp %g2+8 +#else + retl +#endif + _ mov %g1,%o0 +#endif + +// extern uintD subx_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry); + DECLARE_FUNCTION(subx_loop_up) +C(subx_loop_up:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1, Output in %o0 +#if STANDARD_LOOPS + andcc %o3,%o3,%g0 + be 2f + _ subcc %g0,%o4,%g0 // Carry +1: ld [%o0],%o4 // source1-digit + add %o0,4,%o0 + ld [%o1],%o5 // source2-digit + add %o1,4,%o1 + subxcc %o4,%o5,%o4 // subtrahieren + addx %g0,%g0,%g1 // neuer Carry + st %o4,[%o2] // Digit ablegen + add %o2,4,%o2 + subcc %o3,1,%o3 + bne 1b + _ subcc %g0,%g1,%g0 // carry +2: retl + _ addx %g0,%g0,%o0 +#endif +#if COUNTER_LOOPS + subcc %g0,%o3,%o3 // %o3 = -count + be 2f + _ mov %o4,%g1 // Carry + sll %o3,2,%o3 // %o3 = -4*count + sub %o2,4,%o2 + sub %o0,%o3,%o0 // %o0 = &sourceptr1[count] + sub %o1,%o3,%o1 // %o1 = &sourceptr2[count] + sub %o2,%o3,%o2 // %o2 = &destptr[count-1] +1: ld [%o0+%o3],%o4 // source1-digit + ld [%o1+%o3],%o5 // source2-digit + subcc %g0,%g1,%g0 // carry + subxcc %o4,%o5,%o4 // subtrahieren + addx %g0,%g0,%g1 // neuer Carry + addcc %o3,4,%o3 + bne 1b + _ st %o4,[%o2+%o3] // Digit ablegen +2: retl + _ mov %g1,%o0 +#endif +#if UNROLLED_LOOPS + and %o3,7,%o5 // count mod 8 + sll %o5,2,%g1 + add %o0,%g1,%o0 // %o0 = &sourceptr1[count mod 8] + add %o1,%g1,%o1 // %o1 = &sourceptr2[count mod 8] + add %o2,%g1,%o2 // %o2 = &destptr[count mod 8] + sll %o5,4,%o5 +#ifdef PIC + mov %o7,%g2 // save return address + call 0f // put address of label 0 into %o7 + _ add %o7,144,%g1 +0: +#else + set _subx_loop_up+176,%g1 +#endif + sub %g1,%o5,%g1 + jmp %g1 // Sprung nach _subx_loop_up+4*(12+4*8-4*(count mod 8)) + _ subcc %g0,%o4,%g0 // carry initialisieren +1: subcc %g0,%g1,%g0 // carry + ld [%o0-32],%o4 // source1-digit + ld [%o1-32],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2-32] // Digit ablegen + ld [%o0-28],%o4 // source1-digit + ld [%o1-28],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2-28] // Digit ablegen + ld [%o0-24],%o4 // source1-digit + ld [%o1-24],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2-24] // Digit ablegen + ld [%o0-20],%o4 // source1-digit + ld [%o1-20],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2-20] // Digit ablegen + ld [%o0-16],%o4 // source1-digit + ld [%o1-16],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2-16] // Digit ablegen + ld [%o0-12],%o4 // source1-digit + ld [%o1-12],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2-12] // Digit ablegen + ld [%o0-8],%o4 // source1-digit + ld [%o1-8],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2-8] // Digit ablegen + ld [%o0-4],%o4 // source1-digit + ld [%o1-4],%o5 // source2-digit + subxcc %o4,%o5,%o4 // subtrahieren + st %o4,[%o2-4] // Digit ablegen + addx %g0,%g0,%g1 // neuer Carry + add %o0,32,%o0 + add %o1,32,%o1 + subcc %o3,8,%o3 // noch mindestens 8 Digits abzuarbeiten? + bcc 1b + _ add %o2,32,%o2 +#ifdef PIC + jmp %g2+8 +#else + retl +#endif + _ mov %g1,%o0 +#endif + +// extern uintD subfrom_loop_up (uintD* sourceptr, uintD* destptr, uintC count); + DECLARE_FUNCTION(subfrom_loop_up) +C(subfrom_loop_up:) // Input in %o0,%o1,%o2, Output in %o0 +#if STANDARD_LOOPS + andcc %o2,%o2,%g0 + be 2f + _ mov %g0,%o5 // Carry := 0 +1: ld [%o0],%o3 // source-digit + add %o0,4,%o0 + ld [%o1],%o4 // dest-digit + subcc %g0,%o5,%g0 // carry + subxcc %o4,%o3,%o4 // subtrahieren + addx %g0,%g0,%o5 // neuer Carry + st %o4,[%o1] // Digit ablegen + subcc %o2,1,%o2 + bne 1b + _ add %o1,4,%o1 +2: retl + _ mov %o5,%o0 +#endif +#if COUNTER_LOOPS + subcc %g0,%o2,%o2 // %o2 = -count + be 2f + _ mov %g0,%o5 // Carry := 0 + sll %o2,2,%o2 // %o2 = -4*count + sub %o0,%o2,%o0 // %o0 = &sourceptr[count] + sub %o1,%o2,%o1 // %o1 = &destptr[count] + ld [%o0+%o2],%o3 // source-digit +1: ld [%o1+%o2],%o4 // dest-digit + subcc %g0,%o5,%g0 // carry + subxcc %o4,%o3,%o4 // subtrahieren + addx %g0,%g0,%o5 // neuer Carry + st %o4,[%o1+%o2] // Digit ablegen + addcc %o2,4,%o2 + bne,a 1b + __ ld [%o0+%o2],%o3 // source-digit +2: retl + _ mov %o5,%o0 +#endif +#if UNROLLED_LOOPS + and %o2,7,%o3 // count mod 8 + sll %o3,2,%o4 + add %o0,%o4,%o0 // %o0 = &sourceptr[count mod 8] + add %o1,%o4,%o1 // %o1 = &destptr[count mod 8] + sll %o3,4,%o3 +#ifdef PIC + mov %o7,%g2 // save return address + call 0f // put address of label 0 into %o7 + _ add %o7,144,%o4 +0: +#else + set _subfrom_loop_up+172,%o4 +#endif + sub %o4,%o3,%o4 + jmp %o4 // Sprung nach _subfrom_loop_up+4*(11+4*8-4*(count mod 8)) + _ subcc %g0,%g0,%g0 // carry löschen +1: subcc %g0,%o5,%g0 // carry + ld [%o0-32],%o3 // source-digit + ld [%o1-32],%o4 // dest-digit + subxcc %o4,%o3,%o4 // subtrahieren + st %o4,[%o1-32] // Digit ablegen + ld [%o0-28],%o3 // source-digit + ld [%o1-28],%o4 // dest-digit + subxcc %o4,%o3,%o4 // subtrahieren + st %o4,[%o1-28] // Digit ablegen + ld [%o0-24],%o3 // source-digit + ld [%o1-24],%o4 // dest-digit + subxcc %o4,%o3,%o4 // subtrahieren + st %o4,[%o1-24] // Digit ablegen + ld [%o0-20],%o3 // source-digit + ld [%o1-20],%o4 // dest-digit + subxcc %o4,%o3,%o4 // subtrahieren + st %o4,[%o1-20] // Digit ablegen + ld [%o0-16],%o3 // source-digit + ld [%o1-16],%o4 // dest-digit + subxcc %o4,%o3,%o4 // subtrahieren + st %o4,[%o1-16] // Digit ablegen + ld [%o0-12],%o3 // source-digit + ld [%o1-12],%o4 // dest-digit + subxcc %o4,%o3,%o4 // subtrahieren + st %o4,[%o1-12] // Digit ablegen + ld [%o0-8],%o3 // source-digit + ld [%o1-8],%o4 // dest-digit + subxcc %o4,%o3,%o4 // subtrahieren + st %o4,[%o1-8] // Digit ablegen + ld [%o0-4],%o3 // source-digit + ld [%o1-4],%o4 // dest-digit + subxcc %o4,%o3,%o4 // subtrahieren + st %o4,[%o1-4] // Digit ablegen + addx %g0,%g0,%o5 // neuer Carry + add %o0,32,%o0 + subcc %o2,8,%o2 // noch mindestens 8 Digits abzuarbeiten? + bcc 1b + _ add %o1,32,%o1 +#ifdef PIC + jmp %g2+8 +#else + retl +#endif + _ mov %o5,%o0 +#endif + +// extern uintD dec_loop_up (uintD* ptr, uintC count); + DECLARE_FUNCTION(dec_loop_up) +C(dec_loop_up:) // Input in %o0,%o1, Output in %o0 +#if STANDARD_LOOPS + andcc %o1,%o1,%g0 + be 2f + _ nop + ld [%o0],%o2 +1: add %o0,4,%o0 + subcc %o2,1,%o2 + bcc 3f + _ st %o2,[%o0-4] + subcc %o1,1,%o1 + bne,a 1b + __ ld [%o0],%o2 +2: retl + _ mov -1,%o0 +3: retl + _ mov 0,%o0 +#endif +#if COUNTER_LOOPS + subcc %g0,%o1,%o1 // %o1 = -count + be 2f + _ sll %o1,2,%o1 // %o1 = -4*count + sub %o0,%o1,%o0 // %o0 = &ptr[count] + ld [%o0+%o1],%o2 // digit holen +1: subcc %o2,1,%o2 // decrementieren + bcc 3f + _ st %o2,[%o0+%o1] // ablegen + addcc %o1,4,%o1 // Zähler erniedrigen, Pointer erhöhen + bne,a 1b + __ ld [%o0+%o1],%o2 +2: retl + _ mov -1,%o0 +3: retl + _ mov 0,%o0 +#endif + +// extern uintD neg_loop_up (uintD* ptr, uintC count); + DECLARE_FUNCTION(neg_loop_up) +C(neg_loop_up:) // Input in %o0,%o1, Output in %o0 +#if STANDARD_LOOPS + // erstes Digit /=0 suchen: + andcc %o1,%o1,%g0 + be 2f + _ add %o0,4,%o0 +1: ld [%o0-4],%o2 + subcc %g0,%o2,%o2 + bne 3f + _ subcc %o1,1,%o1 + bne 1b + _ add %o0,4,%o0 +2: retl + _ mov 0,%o0 +3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys + // 1 Digit negieren, alle anderen Digits invertieren: + be 5f + _ st %o2,[%o0-4] +4: ld [%o0],%o2 + subcc %o1,1,%o1 + xor %o2,-1,%o2 + st %o2,[%o0] + bne 4b + _ add %o0,4,%o0 +5: retl + _ mov -1,%o0 +#endif +#if COUNTER_LOOPS + // erstes Digit /=0 suchen: + subcc %g0,%o1,%o1 // %o1 = -count + be 2f + _ sll %o1,2,%o1 // %o1 = -4*count + sub %o0,%o1,%o0 // %o0 = &ptr[count] + ld [%o0+%o1],%o2 // digit holen +1: subcc %g0,%o2,%o2 // negieren, testen + bne 3f + _ addcc %o1,4,%o1 // Zähler erniedrigen, Pointer erhöhen + bne,a 1b + __ ld [%o0+%o1],%o2 +2: retl + _ mov 0,%o0 +3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys + // alle anderen Digits invertieren: + sub %o1,4,%o1 + st %o2,[%o0+%o1] // ablegen + addcc %o1,4,%o1 + be 5f + _ nop + ld [%o0+%o1],%o2 +4: xor %o2,-1,%o2 + st %o2,[%o0+%o1] + addcc %o1,4,%o1 + bne,a 4b + __ ld [%o0+%o1],%o2 +5: retl + _ mov -1,%o0 +#endif + +// extern uintD shift1left_loop_up (uintD* ptr, uintC count); + DECLARE_FUNCTION(shift1left_loop_up) +C(shift1left_loop_up:) // Input in %o0,%o1, Output in %o0 + andcc %o1,%o1,%g0 + be 2f + _ mov 0,%o3 // Carry := 0 +1: ld [%o0],%o2 // Digit + subcc %g0,%o3,%g0 // carry + addxcc %o2,%o2,%o2 // shiften + addx %g0,%g0,%o3 // neues Carry + st %o2,[%o0] // Digit ablegen + subcc %o1,1,%o1 + bne 1b + _ add %o0,4,%o0 +2: retl + _ mov %o3,%o0 + +// extern uintD shiftleft_loop_up (uintD* ptr, uintC count, uintC i, uintD carry); + DECLARE_FUNCTION(shiftleft_loop_up) +C(shiftleft_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0 + andcc %o1,%o1,%g0 + be 2f + _ sub %g0,%o2,%g1 // 32-i (mod 32) +1: ld [%o0],%o4 // Digit + subcc %o1,1,%o1 + sll %o4,%o2,%o5 // dessen niedere (32-i) Bits + or %o3,%o5,%o5 // mit dem alten Carry kombinieren + st %o5,[%o0] // Digit ablegen + srl %o4,%g1,%o3 // dessen höchste i Bits liefern den neuen Carry + bne 1b + _ add %o0,4,%o0 +2: retl + _ mov %o3,%o0 + +#endif + +// extern uintD shiftleftcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i); + DECLARE_FUNCTION(shiftleftcopy_loop_up) +C(shiftleftcopy_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1,%g2, Output in %o0 + andcc %o2,%o2,%g0 + be 2f + _ mov 0,%o4 // Carry := 0 + sub %g0,%o3,%g1 // 32-i (mod 32) +1: ld [%o0],%o5 // Digit + subcc %o2,1,%o2 + sll %o5,%o3,%g2 // dessen niedere (32-i) Bits + or %o4,%g2,%g2 // mit dem alten Carry kombinieren + st %g2,[%o1] // Digit ablegen + add %o1,4,%o1 + srl %o5,%g1,%o4 // dessen höchste i Bits liefern den neuen Carry + bne 1b + _ add %o0,4,%o0 +2: retl + _ mov %o4,%o0 + +#if !CL_DS_BIG_ENDIAN_P + +// extern uintD shift1right_loop_down (uintD* ptr, uintC count, uintD carry); + DECLARE_FUNCTION(shift1right_loop_down) +C(shift1right_loop_down:) // Input in %o0,%o1,%o2, Output in %o0 + andcc %o1,%o1,%g0 + be 2f + _ sll %o2,31,%o2 // Carry + sub %o0,4,%o0 +1: ld [%o0],%o3 // Digit + subcc %o1,1,%o1 + srl %o3,1,%o4 // shiften + or %o2,%o4,%o4 // und mit altem Carry kombinieren + st %o4,[%o0] // und ablegen + sll %o3,31,%o2 // neuer Carry + bne 1b + _ sub %o0,4,%o0 +2: retl + _ mov %o2,%o0 + +// extern uintD shiftright_loop_down (uintD* ptr, uintC count, uintC i); + DECLARE_FUNCTION(shiftright_loop_down) +C(shiftright_loop_down:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0 + sub %g0,%o2,%g1 // 32-i (mod 32) + andcc %o1,%o1,%g0 + be 2f + _ or %g0,%g0,%o3 // Carry := 0 + sub %o0,4,%o0 +1: ld [%o0],%o4 // Digit + subcc %o1,1,%o1 + srl %o4,%o2,%o5 // shiften + or %o3,%o5,%o5 // und mit altem Carry kombinieren + st %o5,[%o0] // und ablegen + sll %o4,%g1,%o3 // neuer Carry + bne 1b + _ sub %o0,4,%o0 +2: retl + _ mov %o3,%o0 + +// extern uintD shiftrightsigned_loop_down (uintD* ptr, uintC count, uintC i); + DECLARE_FUNCTION(shiftrightsigned_loop_down) +C(shiftrightsigned_loop_down:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0 + ld [%o0-4],%o4 // erstes Digit + sub %g0,%o2,%g1 // 32-i (mod 32) + sra %o4,%o2,%o5 // shiften + st %o5,[%o0-4] // und ablegen + sll %o4,%g1,%o3 // neuer Carry + subcc %o1,1,%o1 + be 2f + _ sub %o0,8,%o0 +1: ld [%o0],%o4 // Digit + subcc %o1,1,%o1 + srl %o4,%o2,%o5 // shiften + or %o3,%o5,%o5 // und mit altem Carry kombinieren + st %o5,[%o0] // und ablegen + sll %o4,%g1,%o3 // neuer Carry + bne 1b + _ sub %o0,4,%o0 +2: retl + _ mov %o3,%o0 + +// extern uintD shiftrightcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry); + DECLARE_FUNCTION(shiftrightcopy_loop_down) +C(shiftrightcopy_loop_down:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1,%g2, Output in %o0 + sub %g0,%o3,%g1 // 32-i (mod 32) + andcc %o2,%o2,%g0 + be 2f + _ sll %o4,%g1,%g2 // erster Carry + sub %o0,4,%o0 +1: ld [%o0],%o4 // Digit + sub %o1,4,%o1 + srl %o4,%o3,%o5 // shiften + or %g2,%o5,%o5 // und mit altem Carry kombinieren + st %o5,[%o1] // und ablegen + sll %o4,%g1,%g2 // neuer Carry + subcc %o2,1,%o2 + bne 1b + _ sub %o0,4,%o0 +2: retl + _ mov %g2,%o0 + +// extern uintD mulusmall_loop_up (uintD digit, uintD* ptr, uintC len, uintD newdigit); + DECLARE_FUNCTION(mulusmall_loop_up) +C(mulusmall_loop_up:) // Input in %o0,%o1,%o2,%o3, Output in %o0 + andcc %o2,%o2,%g0 + be 3f + _ nop +1: // nächstes Digit [%o1] mit der 6-Bit-Zahl %o0 multiplizieren + // und kleinen Carry %o3 dazu: + mov %o0,%y + ld [%o1],%o4 // Wartetakt! + addcc %o3,%o3,%o5 + mulscc %o5,%o4,%o5 + mulscc %o5,%o4,%o5 + mulscc %o5,%o4,%o5 + mulscc %o5,%o4,%o5 + mulscc %o5,%o4,%o5 + mulscc %o5,%o4,%o5 + mulscc %o5,%g0,%o5 + // Die 26 unteren Bits von %o5 und die 6 oberen Bits von %y + // ergeben das Resultat. (Die anderen Bits sind Null.) + tst %o4 // Korrektur, falls %o4 negativ war + bge 2f + _ sra %o5,26,%o3 // 6 obere Bits von %o5 -> neuer Carry + add %o3,%o0,%o3 // (falls %o4 negativ war, noch + %o0) +2: rd %y,%o4 + srl %o4,26,%o4 // 6 obere Bits von %y + sll %o5,6,%o5 // 26 untere Bits von %o5 + or %o5,%o4,%o4 // neues Digit + st %o4,[%o1] // ablegen + subcc %o2,1,%o2 + bne 1b + _ add %o1,4,%o1 +3: retl + _ mov %o3,%o0 + +// extern void mulu_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); +#if !MULU32_INLINE + DECLARE_FUNCTION(mulu_loop_up) +C(mulu_loop_up:) // Input in %i0,%i1,%i2,%i3 + save %sp,-96,%sp + mov 0,%l0 // Carry +1: ld [%i1],%o1 // nächstes Digit + add %i1,4,%i1 + call _mulu32_ // mit digit multiplizieren + _ mov %i0,%o0 + addcc %l0,%o0,%o0 // und bisherigen Carry addieren + addx %g0,%g1,%l0 // High-Digit gibt neuen Carry + st %o0,[%i2] // Low-Digit ablegen + subcc %i3,1,%i3 + bne 1b + _ add %i2,4,%i2 + st %l0,[%i2] // letzten Carry ablegen + ret + _ restore +#else + DECLARE_FUNCTION(mulu_loop_up) +C(mulu_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1 + mov 0,%o4 // Carry +1: ld [%o1],%g1 // nächstes Digit + // mit digit multiplizieren: %o0 * %g1 -> %o5|%g1 +#ifdef sparcv8 + add %o1,4,%o1 + umul %g1,%o0,%g1 + rd %y,%o5 +#else + mov %g1,%y + add %o1,4,%o1 // Wartetakt! + andcc %g0,%g0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%o0,%o5 + mulscc %o5,%g0,%o5 + tst %o0 + bl,a 2f + __ add %o5,%g1,%o5 +2: rd %y,%g1 +#endif + addcc %o4,%g1,%g1 // und bisherigen Carry addieren + addx %g0,%o5,%o4 // High-Digit gibt neuen Carry + st %g1,[%o2] // Low-Digit ablegen + subcc %o3,1,%o3 + bne 1b + _ add %o2,4,%o2 + retl + _ st %o4,[%o2] // letzten Carry ablegen +#endif + +// extern uintD muluadd_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); + DECLARE_FUNCTION(muluadd_loop_up) +C(muluadd_loop_up:) // Input in %i0,%i1,%i2,%i3, Output in %i0 +#if !MULU32_INLINE + save %sp,-96,%sp + mov 0,%l0 // Carry +1: ld [%i1],%o1 // nächstes source-Digit + add %i1,4,%i1 + call _mulu32_ // mit digit multiplizieren + _ mov %i0,%o0 + ld [%i2],%o1 // nächstes dest-digit + addcc %l0,%o0,%o0 // und bisherigen Carry addieren + addx %g0,%g1,%l0 // High-Digit gibt neuen Carry + addcc %o1,%o0,%o0 // addieren + addx %g0,%l0,%l0 + st %o0,[%i2] // Low-Digit ablegen + subcc %i3,1,%i3 + bne 1b + _ add %i2,4,%i2 + mov %l0,%i0 // letzter Carry + ret + _ restore +#else + save %sp,-96,%sp + mov 0,%l0 // Carry +#ifndef sparcv8 + sra %i0,31,%l1 // 0 falls %i0>=0, -1 falls %i0<0 +#endif +1: ld [%i1],%o1 // nächstes source-Digit + add %i1,4,%i1 + // mit digit multiplizieren: %i0 * %o1 -> %o2|%o0 +#ifdef sparcv8 + umul %i0,%o1,%o0 + rd %y,%o2 +#else + mov %o1,%y + and %o1,%l1,%o3 // Wartetakt! + andcc %g0,%g0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%g0,%o2 + add %o2,%o3,%o2 // %o3 = (0 falls %i0>=0, %o1 falls %i0<0) + rd %y,%o0 +#endif + ld [%i2],%o1 // nächstes dest-digit + addcc %l0,%o0,%o0 // und bisherigen Carry addieren + addx %g0,%o2,%l0 // High-Digit gibt neuen Carry + addcc %o1,%o0,%o0 // addieren + addx %g0,%l0,%l0 + st %o0,[%i2] // Low-Digit ablegen + subcc %i3,1,%i3 + bne 1b + _ add %i2,4,%i2 + mov %l0,%i0 // letzter Carry + ret + _ restore +#endif + +// extern uintD mulusub_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); + DECLARE_FUNCTION(mulusub_loop_up) +C(mulusub_loop_up:) // Input in %i0,%i1,%i2,%i3, Output in %i0 +#if !MULU32_INLINE + save %sp,-96,%sp + mov 0,%l0 // Carry +1: ld [%i1],%o1 // nächstes source-Digit + add %i1,4,%i1 + call _mulu32_ // mit digit multiplizieren + _ mov %i0,%o0 + ld [%i2],%o1 // nächstes dest-digit + addcc %l0,%o0,%o0 // und bisherigen Carry addieren + addx %g0,%g1,%l0 // High-Digit gibt neuen Carry + subcc %o1,%o0,%o1 // davon das Low-Digit subtrahieren + addx %g0,%l0,%l0 + st %o1,[%i2] // dest-Digit ablegen + subcc %i3,1,%i3 + bne 1b + _ add %i2,4,%i2 + mov %l0,%i0 // letzter Carry + ret + _ restore +#else + save %sp,-96,%sp + mov 0,%l0 // Carry +#ifndef sparcv8 + sra %i0,31,%l1 // 0 falls %i0>=0, -1 falls %i0<0 +#endif +1: ld [%i1],%o1 // nächstes source-Digit + add %i1,4,%i1 + // mit digit multiplizieren: %i0 * %o1 -> %o2|%o0 +#ifdef sparcv8 + umul %i0,%o1,%o0 + rd %y,%o2 +#else + mov %o1,%y + and %o1,%l1,%o3 // Wartetakt! + andcc %g0,%g0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%i0,%o2 + mulscc %o2,%g0,%o2 + add %o2,%o3,%o2 // %o3 = (0 falls %i0>=0, %o1 falls %i0<0) + rd %y,%o0 +#endif + ld [%i2],%o1 // nächstes dest-digit + addcc %l0,%o0,%o0 // und bisherigen Carry addieren + addx %g0,%o2,%l0 // High-Digit gibt neuen Carry + subcc %o1,%o0,%o1 // davon das Low-Digit subtrahieren + addx %g0,%l0,%l0 + st %o1,[%i2] // dest-Digit ablegen + subcc %i3,1,%i3 + bne 1b + _ add %i2,4,%i2 + mov %l0,%i0 // letzter Carry + ret + _ restore +#endif + +// extern uintD divu_loop_down (uintD digit, uintD* ptr, uintC len); + DECLARE_FUNCTION(divu_loop_down) +C(divu_loop_down:) // Input in %i0,%i1,%i2, Output in %i0 + save %sp,-96,%sp + andcc %i2,%i2,%g0 + be 2f + _ mov 0,%g1 // Rest +1: mov %g1,%o0 // Rest als High-Digit + ld [%i1-4],%o1 // nächstes Digit als Low-Digit + call C(divu_6432_3232_) // zusammen durch digit dividieren + _ mov %i0,%o2 + st %o0,[%i1-4] // Quotient ablegen, Rest in %g1 + subcc %i2,1,%i2 + bne 1b + _ sub %i1,4,%i1 +2: mov %g1,%i0 // Rest als Ergebnis + ret + _ restore + +// extern uintD divucopy_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); + DECLARE_FUNCTION(divucopy_loop_down) +C(divucopy_loop_down:) // Input in %i0,%i1,%i2,%i3, Output in %i0 + save %sp,-96,%sp + andcc %i3,%i3,%g0 + be 2f + _ mov 0,%g1 // Rest +1: mov %g1,%o0 // Rest als High-Digit + ld [%i1-4],%o1 // nächstes Digit als Low-Digit + call C(divu_6432_3232_) // zusammen durch digit dividieren + _ mov %i0,%o2 + sub %i2,4,%i2 + st %o0,[%i2] // Quotient ablegen, Rest in %g1 + subcc %i3,1,%i3 + bne 1b + _ sub %i1,4,%i1 +2: mov %g1,%i0 // Rest als Ergebnis + ret + _ restore + +#endif + +// extern void shiftxor_loop_up (uintD* xptr, const uintD* yptr, uintC count, uintC i); + DECLARE_FUNCTION(shiftxor_loop_up) +C(shiftxor_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1,%g2 + andcc %o2,%o2,%g0 + be 2f + _ sub %g0,%o3,%g1 // 32-i (mod 32) + sub %o1,%o0,%o1 + ld [%o0],%o4 // *xptr holen +1: ld [%o0+%o1],%o5 // *yptr holen + subcc %o2,1,%o2 + sll %o5,%o3,%g2 // dessen niedere (32-i) Bits + xor %o4,%g2,%o4 // mit dem modifizierten *xptr kombinieren + st %o4,[%o0] // und ablegen + add %o0,4,%o0 + srl %o5,%g1,%g2 // höchste i Bits von *yptr + ld [%o0],%o4 // schon mal mit dem nächsten *xptr + bne 1b + _ xor %o4,%g2,%o4 // verknüpfen + st %o4,[%o0] // und ablegen +2: retl + _ nop + diff --git a/src/base/digitseq/digit_header b/src/base/digitseq/digit_header new file mode 100755 index 0000000..6a21012 --- /dev/null +++ b/src/base/digitseq/digit_header @@ -0,0 +1,57 @@ +#!/bin/sh +# Usage: digit_header < pi.h.in > pi.h +# converts a file containing the digits of pi (in hex) to +# a header file suitable for inclusion. + +bytes='' +while true; do + IFS='@' read line || break + bytes="$bytes "`echo "$line" | sed -e 's,//.*$,,' -e 's,[{};], ,g' -e 's,D(, ,g' -e 's/[,)]/ /g' -e 's,0x, ,g'` +done +bytes=`echo "$bytes" | sed -e 's, *, ,g'` + +blocks1=`echo " $bytes" | sed -e 's/ \([0-9A-Za-z]\+\)/ D1(0x\1),/g'` +blocks2=`echo " $bytes" | sed -e 's/ \([0-9A-Za-z]\+\) \([0-9A-Za-z]\+\)/ D2(0x\1,0x\2),/g'` +blocks4=`echo " $bytes" | sed -e 's/ \([0-9A-Za-z]\+\) \([0-9A-Za-z]\+\) \([0-9A-Za-z]\+\) \([0-9A-Za-z]\+\)/ D4(0x\1,0x\2,0x\3,0x\4),/g'` +blocks8=`echo " $bytes" | sed -e 's/ \([0-9A-Za-z]\+\) \([0-9A-Za-z]\+\) \([0-9A-Za-z]\+\) \([0-9A-Za-z]\+\) \([0-9A-Za-z]\+\) \([0-9A-Za-z]\+\) \([0-9A-Za-z]\+\) \([0-9A-Za-z]\+\)/ D8(0x\1,0x\2,0x\3,0x\4,0x\5,0x\6,0x\7,0x\8),/g'` + +reverse () { + eval "l=\$$1" + r=''; for word in $l; do r="$word $r"; done + eval "$2=\$r" +} + +reverse blocks1 revblocks1 +reverse blocks2 revblocks2 +reverse blocks4 revblocks4 +reverse blocks8 revblocks8 + +echo "{" +echo "#if CL_DS_BIG_ENDIAN_P" +echo " #if (intDsize==8)" +echo " "`echo "$blocks1" | sed -e 's/, *$//'` +echo " #endif" +echo " #if (intDsize==16)" +echo " "`echo "$blocks2" | sed -e 's/, *$//'` +echo " #endif" +echo " #if (intDsize==32)" +echo " "`echo "$blocks4" | sed -e 's/, *$//'` +echo " #endif" +echo " #if (intDsize==64)" +echo " "`echo "$blocks8" | sed -e 's/, *$//'` +echo " #endif" +echo "#else" +echo " #if (intDsize==8)" +echo " "`echo "$revblocks1" | sed -e 's/, *$//'` +echo " #endif" +echo " #if (intDsize==16)" +echo " "`echo "$revblocks2" | sed -e 's/, *$//'` +echo " #endif" +echo " #if (intDsize==32)" +echo " "`echo "$revblocks4" | sed -e 's/, *$//'` +echo " #endif" +echo " #if (intDsize==64)" +echo " "`echo "$revblocks8" | sed -e 's/, *$//'` +echo " #endif" +echo "#endif" +echo "} ;" diff --git a/src/base/hash/Makeflags b/src/base/hash/Makeflags new file mode 100644 index 0000000..c329293 --- /dev/null +++ b/src/base/hash/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/base/Makeflags +SUBDIR_INCLUDES += diff --git a/src/base/hash/cl_hash.h b/src/base/hash/cl_hash.h new file mode 100644 index 0000000..2e92ffd --- /dev/null +++ b/src/base/hash/cl_hash.h @@ -0,0 +1,190 @@ +// General hashtables + +#ifndef _CL_HASH_H +#define _CL_HASH_H + +#include "cl_object.h" +#include "cl_malloc.h" +#include "cl_abort.h" +#include "cl_iterator.h" + +const long htentry_last = 0; // means that there is no next entry + +// These forward declarations are needed for Sun CC 3.0.1 and 4.0.1. +template struct _cl_hashtable_iterator; + +template +struct cl_heap_hashtable : public cl_heap { +protected: + typedef struct htxentry { + long next; // > 0: pseudo-list continues at next-1 + // == 0: end of pseudo-list + // == -1: end of pseudo-free-list + // < -1: part of pseudo-free-list, continues at -next-2 + htentry entry; // if next >= 0 + } htxentry; + long _modulus; // size of the primary entry table, > 0 + long _size; // maximum number of entries + long _count; // current number of entries + long _freelist; // start of pseudo-free-list + long * _slots; // vector of length _modulus + htxentry * _entries; // vector of length _size + void* _total_vector; + cl_boolean (*_garcol_fun) (cl_heap*); // Function to make room in the table. + // Putting some intelligent function here turns + // a normal hash table into a "weak" hash table. +public: + // Allocation. + void* operator new (size_t size) { return cl_malloc_hook(size); } + // Deallocation. + void operator delete (void* ptr) { cl_free_hook(ptr); } + // Constructor: build a new, empty table. + cl_heap_hashtable (long initial_size = 5) : cl_heap (), + _size (initial_size), _count (0), _garcol_fun (no_garcol) + { + _modulus = compute_modulus(_size); + _total_vector = cl_malloc_hook(_modulus*sizeof(long) + _size*sizeof(htxentry)); + _slots = (long*) ((char*)_total_vector + 0); + _entries = (htxentry *) ((char*)_total_vector + _modulus*sizeof(long)); + for (var long hi = _modulus-1; hi >= 0; hi--) + _slots[hi] = 0; + var long free_list_head = -1; + for (var long i = _size-1; i >= 0; i--) { + _entries[i].next = free_list_head; + free_list_head = -2-i; + } + _freelist = free_list_head; + } + // Destructor. + ~cl_heap_hashtable () + { + for (long i = 0; i < _size; i++) + if (_entries[i].next >= 0) + _entries[i].~htxentry(); + cl_free_hook(_total_vector); + } + // Count number of entries. + long num_entries () + { + #if 0 + var long n = 0; + for (long i = 0; i < _size; i++) + if (_entries[i].next >= 0) + n++; + return n; + #else + /* We already have an up-to-date count. */ + return _count; + #endif + } + // Iterator. + _cl_hashtable_iterator iterator (); +protected: + // Compute the modulus, given the maximum number of entries. + static long compute_modulus (long size) + { + // It should be somewhat greater than size, since we want to + // avoid collisions. + // With N = size and M = modulus := k*size, the probability for a + // * primary slot to be empty is + // (1-1/M)^N == exp(-N/M) == exp(-1/k). + // * primary slot to carry a pseudo-list of length 1 is + // N 1/M (1-1/M)^(N-1) == exp(-N/M)*N/M == exp(-1/k)*1/k. + // * primary slot to carry a pseudo-list of length >1 (collision) is + // 1 - (1-1/M)^N - N 1/M (1-1/M)^(N-1) + // == 1 - exp(-N/M)*(1 + N/M) == 1 - (exp(-1/k)*(1+1/k)). + // Sample values: + // = 0 = 1 > 1 + // k = 1.0 0.37 0.37 0.26 + // k = 1.5 0.51 0.34 0.14 + // k = 2.0 0.61 0.30 0.09 + // I think k = 1.0 is reasonable. + // Furthermore, we make sure that M is not divisible by 2, 3, 5. + // Because in some applications, the hash codes are divisible + // by 2 or 3, and if the modulus were divisible by this number, + // only every second or every third primary slot would be filled, + // resulting in many collisions. + var long m = 1*size; + // Make sure m is not divisible by 2. + if ((m % 2) == 0) + m++; + // Make sure m is not divisible by 3. + if ((m % 3) == 0) + m += 2; + // Make sure m is not divisible by 5. + if ((m % 5) == 0) { + m += 2; + if ((m % 3) == 0) + m += 2; + } + return m; + } + // Return the index of a free entry. Assumes the free list is non-empty. + long get_free_index () + { + // Check whether there is some in the free list. + if (_freelist < -1) { + var long index = -2-_freelist; + _freelist = _entries[index].next; + return index; + } + #if !(defined(__hppa__) && !defined(__GNUC__)) // workaround HP CC problem + cl_abort(); + #endif + return -1; // dummy + } + // Put a free index into the free list. + void put_free_index (long index) + { + _entries[index].next = _freelist; + _freelist = -2-index; + } +private: + // Default function to make room in a hash table. + static cl_boolean no_garcol (cl_heap* ht) { unused ht; return cl_false; } +}; + +template +struct _cl_hashtable_iterator + #if !(defined(__mips__) && !defined(__GNUC__)) // workaround SGI CC bug + : cl_abstract_iterator + #endif +{ +private: + cl_heap_hashtable::htxentry * _entries; + long _index; +public: + _cl_hashtable_iterator () : _entries (0), _index (-1) {} +public: /* ugh */ + _cl_hashtable_iterator (cl_heap_hashtable::htxentry * e, long i) + : _entries (e), _index (i) + { + do { _index--; } + while (_index >= 0 && _entries[_index].next < 0); + } +public: + bool endp () { return (_index < 0); } + htentry& next () + { + if (_index < 0) + cl_abort(); + var long old_index = _index; + do { _index--; } + while (_index >= 0 && _entries[_index].next < 0); + return _entries[old_index].entry; + } +}; + +template +inline _cl_hashtable_iterator cl_heap_hashtable::iterator () +{ +#if defined(__GNUC__) + return _cl_hashtable_iterator::_cl_hashtable_iterator(_entries,_size); +#else // workaround most C++ compilers' bug + typedef _cl_hashtable_iterator _cl_hashtable_iterator_type; + return _cl_hashtable_iterator_type(_entries,_size); +#endif +} + + +#endif /* _CL_HASH_H */ diff --git a/src/base/hash/cl_hash1.h b/src/base/hash/cl_hash1.h new file mode 100644 index 0000000..5494b00 --- /dev/null +++ b/src/base/hash/cl_hash1.h @@ -0,0 +1,163 @@ +// Hash tables with 1 key and a value + +#ifndef _CL_HASH1_H +#define _CL_HASH1_H + +#include "cl_hash.h" +#include "cl_iterator.h" + +// Requirements: +// - function bool equal (key1_type,key1_type); +// - function unsigned long hashcode (key1_type); + +#if (defined(__alpha__) && !defined(__GNUC__)) +template struct cl_htentry1; +#endif + +template +struct cl_htentry1 { + ALLOCATE_ANYWHERE(cl_htentry1) + key1_type key; + value_type val; + const value_type& htvalue () { return val; } + cl_htentry1 (const key1_type& k, const value_type& v) + : key (k), val (v) {} +#if (defined(__rs6000__) && !defined(__GNUC__)) + cl_htentry1 () {} +#endif +}; + +template +struct cl_heap_hashtable_1 : public cl_heap_hashtable > { + // Allocation. + void* operator new (size_t size) { return cl_malloc_hook(size); } + // Deallocation. + void operator delete (void* ptr) { cl_free_hook(ptr); } +public: + // Lookup (htref alias gethash). + // Returns a pointer which you should immediately dereference + // if it is not NULL. + value_type* get (const key1_type& key) + { + var long index = _slots[hashcode(key) % _modulus] - 1; + while (index >= 0) { + if (!(index < _size)) + cl_abort(); + if (equal(key,_entries[index].entry.key)) + return &_entries[index].entry.val; + index = _entries[index].next - 1; + } + return NULL; + } + // Store (htset alias puthash). + void put (const key1_type& key, const value_type& val) + { + var unsigned long hcode = hashcode(key); + // Search whether it is already there. + { + var long index = _slots[hcode % _modulus] - 1; + while (index >= 0) { + if (!(index < _size)) + cl_abort(); + if (equal(key,_entries[index].entry.key)) { + _entries[index].entry.val = val; + return; + } + index = _entries[index].next - 1; + } + } + // Put it into the table. + prepare_store(); + var long hindex = hcode % _modulus; // _modulus may have changed! + var long index = get_free_index(); + new (&_entries[index].entry) cl_htentry1 (key,val); + _entries[index].next = _slots[hindex]; + _slots[hindex] = 1+index; + _count++; + } + // Remove (htrem alias remhash). + void remove (const key1_type& key) + { + var long* _index = &_slots[hashcode(key) % _modulus]; + while (*_index > 0) { + var long index = *_index - 1; + if (!(index < _size)) + cl_abort(); + if (equal(key,_entries[index].entry.key)) { + // Remove _entries[index].entry + *_index = _entries[index].next; + _entries[index].~htxentry(); + // The entry is now free. + put_free_index(index); + // That's it. + _count--; + return; + } + _index = &_entries[index].next; + } + } + // Iterate through the table. + // No stuff should be inserted into the table during the iteration, + // or you may find yourself iterating over an entry vector which has + // already been freed! + // ?? +private: + // Prepare a store operation: make sure that the free list is non-empty. + // This may change the table's size! + void prepare_store () + { + #if !(defined(__sparc__) && !defined(__GNUC__)) + if (_freelist < -1) + return; + // Can we make room? + if (_garcol_fun(this)) + if (_freelist < -1) + return; + // No! Have to grow the hash table. + grow(); + #else + // workaround Sun C++ 4.1 inline function compiler bug + if (_freelist >= -1) { + if (!_garcol_fun(this) || (_freelist >= -1)) + grow(); + } + #endif + } + void grow () + { + var long new_size = _size + (_size >> 1) + 1; // _size*1.5 + var long new_modulus = compute_modulus(new_size); + var void* new_total_vector = cl_malloc_hook(new_modulus*sizeof(long) + new_size*sizeof(htxentry)); + var long* new_slots = (long*) ((char*)new_total_vector + 0); + var htxentry* new_entries = (htxentry *) ((char*)new_total_vector + new_modulus*sizeof(long)); + for (var long hi = new_modulus-1; hi >= 0; hi--) + new_slots[hi] = 0; + var long free_list_head = -1; + for (var long i = new_size-1; i >= 0; i--) { + new_entries[i].next = free_list_head; + free_list_head = -2-i; + } + var htxentry* old_entries = _entries; + for (var long old_index = 0; old_index < _size; old_index++) + if (old_entries[old_index].next >= 0) { + var key1_type& key = old_entries[old_index].entry.key; + var value_type& val = old_entries[old_index].entry.val; + var long hindex = hashcode(key) % new_modulus; + var long index = -2-free_list_head; + free_list_head = new_entries[index].next; + new (&new_entries[index].entry) cl_htentry1 (key,val); + new_entries[index].next = new_slots[hindex]; + new_slots[hindex] = 1+index; + old_entries[old_index].~htxentry(); + } + cl_free_hook(_total_vector); + _modulus = new_modulus; + _size = new_size; + _freelist = free_list_head; + _slots = new_slots; + _entries = new_entries; + _total_vector = new_total_vector; + } +}; + +#endif /* _CL_HASH1_H */ diff --git a/src/base/hash/cl_hash1weak.h b/src/base/hash/cl_hash1weak.h new file mode 100644 index 0000000..0719ec4 --- /dev/null +++ b/src/base/hash/cl_hash1weak.h @@ -0,0 +1,93 @@ +// Weak hash tables with 1 key and a value + +#ifndef _CL_HASH1WEAK_H +#define _CL_HASH1WEAK_H + +#include "cl_hash1.h" + +// This is a hash table in which an entry can be removed when a user-defined +// condition is fulfilled (e.g. the value is not referenced any more). +// We don't remove unused entries immediately, only when the hash table +// wants to grow. This way the hash table also serves as a cache. + +// Requirements: +// - same as for hash1, +// - key1_type must be a subclass of cl_gc[object|pointer], +// - value_type must be a subclass of cl_[gc|rc][object|pointer], +// - function maygc_htentry(const cl_htentry1&); +// must be filled in at runtime. + +template +struct cl_heap_weak_hashtable_1 : public cl_heap_hashtable_1 { + // Allocation. + void* operator new (size_t size) { return cl_malloc_hook(size); } + // Deallocation. + void operator delete (void* ptr) { cl_free_hook(ptr); } +public: + // Function which tells when an unused entry may be garbage collected. + cl_boolean (* const _maygc_htentry) (const cl_htentry1&); + // Constructor. + cl_heap_weak_hashtable_1 (cl_boolean (*maygc_htentry) (const cl_htentry1&)) + : cl_heap_hashtable_1 (), + _maygc_htentry (maygc_htentry) + { + _garcol_fun = garcol; + } +private: + // Garbage collection. + // Before growing the table, we check whether we can remove unused + // entries. + static cl_boolean garcol (cl_heap* _ht) + { + var cl_heap_weak_hashtable_1* ht = (cl_heap_weak_hashtable_1*)_ht; + // Now ht->_garcol_fun = garcol. + // It is not worth doing a garbage collection if the table + // is small, say, has fewer than 100 entries. + if (ht->_count < 100) + return cl_false; + // Do a garbage collection. + var long removed = 0; + for (long i = 0; i < ht->_size; i++) + if (ht->_entries[i].next >= 0) { + var cl_htentry1& entry = ht->_entries[i].entry; + if (ht->_maygc_htentry(entry)) { + // This is hairy. We remove the entry and + // free the value after its refcount has + // dropped to zero. But in order to protect + // against too early destruction + // we have to temporarily increase the refcount. + if (entry.val.pointer_p()) + entry.val.inc_pointer_refcount(); + ht->remove(entry.key); + if (entry.val.pointer_p()) { + var cl_heap* p = entry.val.heappointer; + if (!(--p->refcount == 0)) cl_abort(); + cl_free_heap_object(p); + } + removed++; + } + } + if (removed == 0) + // Unsuccessful. Let the table grow immediately. + return cl_false; + else if (2*removed < ht->_count) { + // Table shrank by less than a factor of 1/1.5. + // Don't expand the table now, but expand it next time. + ht->_garcol_fun = garcol_nexttime; + return cl_true; + } else { + // Table shrank much. Don't expand the table now, + // and try a GC next time. + return cl_true; + } + } + static cl_boolean garcol_nexttime (cl_heap* _ht) + { + var cl_heap_weak_hashtable_1* ht = (cl_heap_weak_hashtable_1*)_ht; + // Now ht->_garcol_fun = garcol_nexttime. + ht->_garcol_fun = garcol; + return cl_false; + } +}; + +#endif /* _CL_HASH1WEAK_H */ diff --git a/src/base/hash/cl_hash2.h b/src/base/hash/cl_hash2.h new file mode 100644 index 0000000..10985b5 --- /dev/null +++ b/src/base/hash/cl_hash2.h @@ -0,0 +1,165 @@ +// Hash tables with 2 keys and a value + +#ifndef _CL_HASH2_H +#define _CL_HASH2_H + +#include "cl_hash.h" +#include "cl_iterator.h" + +// Requirements: +// - function bool equal (key1_type,key1_type); +// - function bool equal (key2_type,key2_type); +// - function unsigned long hashcode (key1_type,key2_type); + +template +struct cl_htentry2 { + ALLOCATE_ANYWHERE(cl_htentry2) + key1_type key1; + key2_type key2; + value_type val; + const value_type& htvalue () { return val; } + cl_htentry2 (const key1_type& k1, const key2_type& k2, const value_type& v) + : key1 (k1), key2 (k2), val (v) {} +#if (defined(__rs6000__) && !defined(__GNUC__)) + cl_htentry2 () {} +#endif +}; + +template +struct cl_heap_hashtable_2 : public cl_heap_hashtable > { + // Allocation. + void* operator new (size_t size) { return cl_malloc_hook(size); } + // Deallocation. + void operator delete (void* ptr) { cl_free_hook(ptr); } +public: + // Lookup (htref alias gethash). + // Returns a pointer which you should immediately dereference + // if it is not NULL. + value_type* get (const key1_type& key1, const key2_type& key2) + { + var long index = _slots[hashcode(key1,key2) % _modulus] - 1; + while (index >= 0) { + if (!(index < _size)) + cl_abort(); + if (equal(key1,_entries[index].entry.key1) + && equal(key2,_entries[index].entry.key2)) + return &_entries[index].entry.val; + index = _entries[index].next - 1; + } + return NULL; + } + // Store (htset alias puthash). + void put (const key1_type& key1, const key2_type& key2, const value_type& val) + { + var unsigned long hcode = hashcode(key1,key2); + // Search whether it is already there. + { + var long index = _slots[hcode % _modulus] - 1; + while (index >= 0) { + if (!(index < _size)) + cl_abort(); + if (equal(key1,_entries[index].entry.key1) + && equal(key2,_entries[index].entry.key2)) { + _entries[index].entry.val = val; + return; + } + index = _entries[index].next - 1; + } + } + // Put it into the table. + prepare_store(); + var long hindex = hcode % _modulus; // _modulus may have changed! + var long index = get_free_index(); + new (&_entries[index].entry) cl_htentry2 (key1,key2,val); + _entries[index].next = _slots[hindex]; + _slots[hindex] = 1+index; + _count++; + } + // Remove (htrem alias remhash). + void remove (const key1_type& key1, const key2_type& key2) + { + var long* _index = &_slots[hashcode(key1,key2) % _modulus]; + while (*_index > 0) { + var long index = *_index - 1; + if (!(index < _size)) + cl_abort(); + if (equal(key1,_entries[index].entry.key1) + && equal(key2,_entries[index].entry.key2)) { + // Remove _entries[index].entry + *_index = _entries[index].next; + _entries[index].~htxentry(); + // The entry is now free. + put_free_index(index); + // That's it. + _count--; + return; + } + _index = &_entries[index].next; + } + } + // Iterate through the table. + // No stuff should be inserted into the table during the iteration, + // or you may find yourself iterating over an entry vector which has + // already been freed! + // ?? +private: + // Prepare a store operation: make sure that the free list is non-empty. + // This may change the table's size! + void prepare_store () + { + #if !(defined(__sparc__) && !defined(__GNUC__)) + if (_freelist < -1) + return; + // Can we make room? + if (_garcol_fun(this)) + if (_freelist < -1) + return; + // No! Have to grow the hash table. + grow(); + #else + // workaround Sun C++ 4.1 inline function compiler bug + if (_freelist >= -1) { + if (!_garcol_fun(this) || (_freelist >= -1)) + grow(); + } + #endif + } + void grow () + { + var long new_size = _size + (_size >> 1) + 1; // _size*1.5 + var long new_modulus = compute_modulus(new_size); + var void* new_total_vector = cl_malloc_hook(new_modulus*sizeof(long) + new_size*sizeof(htxentry)); + var long* new_slots = (long*) ((char*)new_total_vector + 0); + var htxentry* new_entries = (htxentry *) ((char*)new_total_vector + new_modulus*sizeof(long)); + for (var long hi = new_modulus-1; hi >= 0; hi--) + new_slots[hi] = 0; + var long free_list_head = -1; + for (var long i = new_size-1; i >= 0; i--) { + new_entries[i].next = free_list_head; + free_list_head = -2-i; + } + var htxentry* old_entries = _entries; + for (var long old_index = 0; old_index < _size; old_index++) + if (old_entries[old_index].next >= 0) { + var key1_type& key1 = old_entries[old_index].entry.key1; + var key2_type& key2 = old_entries[old_index].entry.key2; + var value_type& val = old_entries[old_index].entry.val; + var long hindex = hashcode(key1,key2) % new_modulus; + var long index = -2-free_list_head; + free_list_head = new_entries[index].next; + new (&new_entries[index].entry) cl_htentry2 (key1,key2,val); + new_entries[index].next = new_slots[hindex]; + new_slots[hindex] = 1+index; + old_entries[old_index].~htxentry(); + } + cl_free_hook(_total_vector); + _modulus = new_modulus; + _size = new_size; + _freelist = free_list_head; + _slots = new_slots; + _entries = new_entries; + _total_vector = new_total_vector; + } +}; + +#endif /* _CL_HASH2_H */ diff --git a/src/base/hash/cl_hash2weak.h b/src/base/hash/cl_hash2weak.h new file mode 100644 index 0000000..e8ec0fe --- /dev/null +++ b/src/base/hash/cl_hash2weak.h @@ -0,0 +1,93 @@ +// Weak hash tables with 2 keys and a value + +#ifndef _CL_HASH2WEAK_H +#define _CL_HASH2WEAK_H + +#include "cl_hash2.h" + +// This is a hash table in which an entry can be removed when a user-defined +// condition is fulfilled (e.g. the value is not referenced any more). +// We don't remove unused entries immediately, only when the hash table +// wants to grow. This way the hash table also serves as a cache. + +// Requirements: +// - same as for hash2, +// - key1_type and key2_type must be subclasses of cl_gc[object|pointer], +// - value_type must be a subclass of cl_[gc|rc][object|pointer], +// - function maygc_htentry(const cl_htentry2&); +// must be filled in at runtime. + +template +struct cl_heap_weak_hashtable_2 : public cl_heap_hashtable_2 { + // Allocation. + void* operator new (size_t size) { return cl_malloc_hook(size); } + // Deallocation. + void operator delete (void* ptr) { cl_free_hook(ptr); } +public: + // Function which tells when an unused entry may be garbage collected. + cl_boolean (* const _maygc_htentry) (const cl_htentry2&); + // Constructor. + cl_heap_weak_hashtable_2 (cl_boolean (*maygc_htentry) (const cl_htentry2&)) + : cl_heap_hashtable_2 (), + _maygc_htentry (maygc_htentry) + { + _garcol_fun = garcol; + } +private: + // Garbage collection. + // Before growing the table, we check whether we can remove unused + // entries. + static cl_boolean garcol (cl_heap* _ht) + { + var cl_heap_weak_hashtable_2* ht = (cl_heap_weak_hashtable_2*)_ht; + // Now ht->_garcol_fun = garcol. + // It is not worth doing a garbage collection if the table + // is small, say, has fewer than 100 entries. + if (ht->_count < 100) + return cl_false; + // Do a garbage collection. + var long removed = 0; + for (long i = 0; i < ht->_size; i++) + if (ht->_entries[i].next >= 0) { + var cl_htentry2& entry = ht->_entries[i].entry; + if (ht->_maygc_htentry(entry)) { + // This is hairy. We remove the entry and + // free the value after its refcount has + // dropped to zero. But in order to protect + // against too early destruction + // we have to temporarily increase the refcount. + if (entry.val.pointer_p()) + entry.val.inc_pointer_refcount(); + ht->remove(entry.key1,entry.key2); + if (entry.val.pointer_p()) { + var cl_heap* p = entry.val.heappointer; + if (!(--p->refcount == 0)) cl_abort(); + cl_free_heap_object(p); + } + removed++; + } + } + if (removed == 0) + // Unsuccessful. Let the table grow immediately. + return cl_false; + else if (2*removed < ht->_count) { + // Table shrank by less than a factor of 1/1.5. + // Don't expand the table now, but expand it next time. + ht->_garcol_fun = garcol_nexttime; + return cl_true; + } else { + // Table shrank much. Don't expand the table now, + // and try a GC next time. + return cl_true; + } + } + static cl_boolean garcol_nexttime (cl_heap* _ht) + { + var cl_heap_weak_hashtable_2* ht = (cl_heap_weak_hashtable_2*)_ht; + // Now ht->_garcol_fun = garcol_nexttime. + ht->_garcol_fun = garcol; + return cl_false; + } +}; + +#endif /* _CL_HASH2WEAK_H */ diff --git a/src/base/hash/cl_hashset.h b/src/base/hash/cl_hashset.h new file mode 100644 index 0000000..b5d28f3 --- /dev/null +++ b/src/base/hash/cl_hashset.h @@ -0,0 +1,149 @@ +// Hash sets (hash tables with 1 key and no value) + +#ifndef _CL_HASHSET_H +#define _CL_HASHSET_H + +#include "cl_hash.h" +#include "cl_iterator.h" + +// Requirements: +// - function bool equal (key1_type,key1_type); +// - function unsigned long hashcode (key1_type); + +template +struct cl_htsetentry { + ALLOCATE_ANYWHERE(cl_htsetentry) + key1_type key; + cl_htsetentry (const key1_type& k) + : key (k) {} +}; + +template +struct cl_heap_hashtable_set : public cl_heap_hashtable > { + // Allocation. + void* operator new (size_t size) { return cl_malloc_hook(size); } + // Deallocation. + void operator delete (void* ptr) { cl_free_hook(ptr); } +public: + // Lookup (htref alias gethash). + bool get (const key1_type& key) + { + var long index = _slots[hashcode(key) % _modulus] - 1; + while (index >= 0) { + if (!(index < _size)) + cl_abort(); + if (equal(key,_entries[index].entry.key)) + return true; + index = _entries[index].next - 1; + } + return false; + } + // Store (htset alias puthash). + void put (const key1_type& key) + { + var unsigned long hcode = hashcode(key); + // Search whether it is already there. + { + var long index = _slots[hcode % _modulus] - 1; + while (index >= 0) { + if (!(index < _size)) + cl_abort(); + if (equal(key,_entries[index].entry.key)) + return; + index = _entries[index].next - 1; + } + } + // Put it into the table. + prepare_store(); + var long hindex = hcode % _modulus; // _modulus may have changed! + var long index = get_free_index(); + new (&_entries[index].entry) cl_htsetentry (key); + _entries[index].next = _slots[hindex]; + _slots[hindex] = 1+index; + _count++; + } + // Remove (htrem alias remhash). + void remove (const key1_type& key) + { + var long* _index = &_slots[hashcode(key) % _modulus]; + while (*_index > 0) { + var long index = *_index - 1; + if (!(index < _size)) + cl_abort(); + if (equal(key,_entries[index].entry.key)) { + // Remove _entries[index].entry + *_index = _entries[index].next; + _entries[index].~htxentry(); + // The entry is now free. + put_free_index(index); + // That's it. + _count--; + return; + } + _index = &_entries[index].next; + } + } + // Iterate through the table. + // No stuff should be inserted into the table during the iteration, + // or you may find yourself iterating over an entry vector which has + // already been freed! + // ?? +private: + // Prepare a store operation: make sure that the free list is non-empty. + // This may change the table's size! + void prepare_store () + { + #if !(defined(__sparc__) && !defined(__GNUC__)) + if (_freelist < -1) + return; + // Can we make room? + if (_garcol_fun(this)) + if (_freelist < -1) + return; + // No! Have to grow the hash table. + grow(); + #else + // workaround Sun C++ 4.1 inline function compiler bug + if (_freelist >= -1) { + if (!_garcol_fun(this) || (_freelist >= -1)) + grow(); + } + #endif + } + void grow () + { + var long new_size = _size + (_size >> 1) + 1; // _size*1.5 + var long new_modulus = compute_modulus(new_size); + var void* new_total_vector = cl_malloc_hook(new_modulus*sizeof(long) + new_size*sizeof(htxentry)); + var long* new_slots = (long*) ((char*)new_total_vector + 0); + var htxentry* new_entries = (htxentry *) ((char*)new_total_vector + new_modulus*sizeof(long)); + for (var long hi = new_modulus-1; hi >= 0; hi--) + new_slots[hi] = 0; + var long free_list_head = -1; + for (var long i = new_size-1; i >= 0; i--) { + new_entries[i].next = free_list_head; + free_list_head = -2-i; + } + var htxentry* old_entries = _entries; + for (var long old_index = 0; old_index < _size; old_index++) + if (old_entries[old_index].next >= 0) { + var key1_type& key = old_entries[old_index].entry.key; + var long hindex = hashcode(key) % new_modulus; + var long index = -2-free_list_head; + free_list_head = new_entries[index].next; + new (&new_entries[index].entry) cl_htsetentry (key); + new_entries[index].next = new_slots[hindex]; + new_slots[hindex] = 1+index; + old_entries[old_index].~htxentry(); + } + cl_free_hook(_total_vector); + _modulus = new_modulus; + _size = new_size; + _freelist = free_list_head; + _slots = new_slots; + _entries = new_entries; + _total_vector = new_total_vector; + } +}; + +#endif /* _CL_HASHSET_H */ diff --git a/src/base/hash/cl_hashuniq.h b/src/base/hash/cl_hashuniq.h new file mode 100644 index 0000000..3ca6754 --- /dev/null +++ b/src/base/hash/cl_hashuniq.h @@ -0,0 +1,160 @@ +// Hash tables for making objects unique + +#ifndef _CL_HASHUNIQ_H +#define _CL_HASHUNIQ_H + +#include "cl_hash.h" +#include "cl_iterator.h" + +// In such a hash table an entry's key is determined by its value +// and not stored explicitly. + +// Requirements: +// - function bool equal (key1_type,key1_type); +// - function unsigned long hashcode (key1_type); +// - function key1_type hashkey (value_type); +// - constructor value_type::value_type (struct hashuniq *, key1_type); + +template +struct cl_htuniqentry { + ALLOCATE_ANYWHERE(cl_htuniqentry) + value_type val; + const value_type& htvalue () { return val; } + cl_htuniqentry (const value_type& v) + : val (v) {} +#if (defined(__rs6000__) && !defined(__GNUC__)) + cl_htuniqentry () {} +#endif +}; + +template +struct cl_heap_hashtable_uniq : public cl_heap_hashtable > { + // Allocation. + void* operator new (size_t size) { return cl_malloc_hook(size); } + // Deallocation. + void operator delete (void* ptr) { cl_free_hook(ptr); } +public: + // Lookup (htref alias gethash). + // Returns a pointer which you should immediately dereference + // if it is not NULL. + value_type * get (const key1_type& key) + { + var long index = _slots[hashcode(key) % _modulus] - 1; + while (index >= 0) { + if (!(index < _size)) + cl_abort(); + if (equal(key,hashkey(_entries[index].entry.val))) + return &_entries[index].entry.val; + index = _entries[index].next - 1; + } + return NULL; + } + // Store (htset alias puthash). + void put (const key1_type& key) + { + var unsigned long hcode = hashcode(key); + // Search whether it is already there. + { + var long index = _slots[hcode % _modulus] - 1; + while (index >= 0) { + if (!(index < _size)) + cl_abort(); + if (equal(key,hashkey(_entries[index].entry.val))) + return; + index = _entries[index].next - 1; + } + } + // Put it into the table. + prepare_store(); + var long hindex = hcode % _modulus; // _modulus may have changed! + var long index = get_free_index(); + new (&_entries[index].entry) cl_htuniqentry (value_type((struct hashuniq *)0, key)); + _entries[index].next = _slots[hindex]; + _slots[hindex] = 1+index; + _count++; + } + // Remove (htrem alias remhash). + void remove (const key1_type& key) + { + var long* _index = &_slots[hashcode(key) % _modulus]; + while (*_index > 0) { + var long index = *_index - 1; + if (!(index < _size)) + cl_abort(); + if (equal(key,hashkey(_entries[index].entry.val))) { + // Remove _entries[index].entry + *_index = _entries[index].next; + _entries[index].~htxentry(); + // The entry is now free. + put_free_index(index); + // That's it. + _count--; + return; + } + _index = &_entries[index].next; + } + } + // Iterate through the table. + // No stuff should be inserted into the table during the iteration, + // or you may find yourself iterating over an entry vector which has + // already been freed! + // ?? +private: + // Prepare a store operation: make sure that the free list is non-empty. + // This may change the table's size! + void prepare_store () + { + #if !(defined(__sparc__) && !defined(__GNUC__)) + if (_freelist < -1) + return; + // Can we make room? + if (_garcol_fun(this)) + if (_freelist < -1) + return; + // No! Have to grow the hash table. + grow(); + #else + // workaround Sun C++ 4.1 inline function compiler bug + if (_freelist >= -1) { + if (!_garcol_fun(this) || (_freelist >= -1)) + grow(); + } + #endif + } + void grow () + { + var long new_size = _size + (_size >> 1) + 1; // _size*1.5 + var long new_modulus = compute_modulus(new_size); + var void* new_total_vector = cl_malloc_hook(new_modulus*sizeof(long) + new_size*sizeof(htxentry)); + var long* new_slots = (long*) ((char*)new_total_vector + 0); + var htxentry* new_entries = (htxentry *) ((char*)new_total_vector + new_modulus*sizeof(long)); + for (var long hi = new_modulus-1; hi >= 0; hi--) + new_slots[hi] = 0; + var long free_list_head = -1; + for (var long i = new_size-1; i >= 0; i--) { + new_entries[i].next = free_list_head; + free_list_head = -2-i; + } + var htxentry* old_entries = _entries; + for (var long old_index = 0; old_index < _size; old_index++) + if (old_entries[old_index].next >= 0) { + var value_type& val = old_entries[old_index].entry.val; + var long hindex = hashcode(hashkey(val)) % new_modulus; + var long index = -2-free_list_head; + free_list_head = new_entries[index].next; + new (&new_entries[index].entry) cl_htuniqentry (val); + new_entries[index].next = new_slots[hindex]; + new_slots[hindex] = 1+index; + old_entries[old_index].~htxentry(); + } + cl_free_hook(_total_vector); + _modulus = new_modulus; + _size = new_size; + _freelist = free_list_head; + _slots = new_slots; + _entries = new_entries; + _total_vector = new_total_vector; + } +}; + +#endif /* _CL_HASHUNIQ_H */ diff --git a/src/base/hash/cl_hashuniqweak.h b/src/base/hash/cl_hashuniqweak.h new file mode 100644 index 0000000..932574c --- /dev/null +++ b/src/base/hash/cl_hashuniqweak.h @@ -0,0 +1,93 @@ +// Weak hash tables for making objects unique + +#ifndef _CL_HASHUNIQWEAK_H +#define _CL_HASHUNIQWEAK_H + +#include "cl_hashuniq.h" + +// This is a hashuniq table in which an entry can be removed when the +// value is not referenced any more. +// Best example: string -> symbol uniquification. When a symbol is not +// referenced any more (except from the hash table itself), the (string,symbol) +// pair may be removed from the hash table. +// We don't remove unused entries immediately, only when the hash table +// wants to grow. This way the hash table also serves as a cache. + +// Requirements: +// - same as for hashuniq, +// - value_type must be a subclass of cl_[gc|rc][object|pointer]. +// Note that since the reference counts are compared against 1, it doesn't +// make sense to have more than one weak hash table for the same value_type. + +template +struct cl_heap_weak_hashtable_uniq : public cl_heap_hashtable_uniq { + // Allocation. + void* operator new (size_t size) { return cl_malloc_hook(size); } + // Deallocation. + void operator delete (void* ptr) { cl_free_hook(ptr); } +public: + // Constructor. + cl_heap_weak_hashtable_uniq () + : cl_heap_hashtable_uniq () + { + _garcol_fun = garcol; + } +private: + // Garbage collection. + // Before growing the table, we check whether we can remove unused + // entries. + static cl_boolean garcol (cl_heap* _ht) + { + var cl_heap_weak_hashtable_uniq* ht = (cl_heap_weak_hashtable_uniq*)_ht; + // Now ht->_garcol_fun = garcol. + // It is not worth doing a garbage collection if the table + // is small, say, has fewer than 100 entries. + if (ht->_count < 100) + return cl_false; + // Do a garbage collection. + var long removed = 0; + for (long i = 0; i < ht->_size; i++) + if (ht->_entries[i].next >= 0) { + var value_type& v = ht->_entries[i].entry.val; + if (!v.pointer_p() || (v.heappointer->refcount == 1)) { + // This is hairy. We remove the entry and + // free the value after its refcount has + // dropped to zero. But in order to protect + // against too early destruction (depending on + // how the C++ compiler optimizes hashkey()) + // we have to temporarily increase the refcount. + if (v.pointer_p()) + v.inc_pointer_refcount(); + ht->remove(hashkey(v)); + if (v.pointer_p()) { + var cl_heap* p = v.heappointer; + if (!(--p->refcount == 0)) cl_abort(); + cl_free_heap_object(p); + } + removed++; + } + } + if (removed == 0) + // Unsuccessful. Let the table grow immediately. + return cl_false; + else if (2*removed < ht->_count) { + // Table shrank by less than a factor of 1/1.5. + // Don't expand the table now, but expand it next time. + ht->_garcol_fun = garcol_nexttime; + return cl_true; + } else { + // Table shrank much. Don't expand the table now, + // and try a GC next time. + return cl_true; + } + } + static cl_boolean garcol_nexttime (cl_heap* _ht) + { + var cl_heap_weak_hashtable_uniq* ht = (cl_heap_weak_hashtable_uniq*)_ht; + // Now ht->_garcol_fun = garcol_nexttime. + ht->_garcol_fun = garcol; + return cl_false; + } +}; + +#endif /* _CL_HASHUNIQWEAK_H */ diff --git a/src/base/hash/cl_rcpointer2_hashweak_rcpointer.cc b/src/base/hash/cl_rcpointer2_hashweak_rcpointer.cc new file mode 100644 index 0000000..660cbd1 --- /dev/null +++ b/src/base/hash/cl_rcpointer2_hashweak_rcpointer.cc @@ -0,0 +1,47 @@ +// class cl_wht_from_rcpointer2_to_rcpointer. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rcpointer2_hashweak_rcpointer.h" + + +// Implementation. + +#include "cl_hash2weak.h" + +static void cl_weak_hashtable_from_rcpointer2_to_rcpointer_destructor (cl_heap* pointer) +{ +#if (defined(__mips__) || defined(__mips64__)) && !defined(__GNUC__) // workaround SGI CC bug + (*(cl_heap_weak_hashtable_from_rcpointer2_to_rcpointer*)pointer).~cl_heap_weak_hashtable_2(); +#else + (*(cl_heap_weak_hashtable_from_rcpointer2_to_rcpointer*)pointer).~cl_heap_weak_hashtable_from_rcpointer2_to_rcpointer(); +#endif +} + +cl_class cl_class_weak_hashtable_from_rcpointer2_to_rcpointer = { + cl_weak_hashtable_from_rcpointer2_to_rcpointer_destructor, + 0 +}; + +// These are not inline, because they tend to duplicate a lot of template code. + +cl_wht_from_rcpointer2_to_rcpointer::cl_wht_from_rcpointer2_to_rcpointer (cl_boolean (*maygc_htentry) (const cl_htentry_from_rcpointer2_to_rcpointer&)) +{ + var cl_heap_weak_hashtable_from_rcpointer2_to_rcpointer* ht = new cl_heap_weak_hashtable_from_rcpointer2_to_rcpointer (maygc_htentry); + ht->refcount = 1; + ht->type = &cl_class_weak_hashtable_from_rcpointer2_to_rcpointer; + pointer = ht; +} + +cl_rcpointer * cl_wht_from_rcpointer2_to_rcpointer::get (const cl_rcpointer& x, const cl_rcpointer& y) const +{ + return ((cl_heap_weak_hashtable_from_rcpointer2_to_rcpointer*)pointer)->get(x,y); +} + +void cl_wht_from_rcpointer2_to_rcpointer::put (const cl_rcpointer& x, const cl_rcpointer& y, const cl_rcpointer& z) const +{ + ((cl_heap_weak_hashtable_from_rcpointer2_to_rcpointer*)pointer)->put(x,y,z); +} + diff --git a/src/base/hash/cl_rcpointer2_hashweak_rcpointer.h b/src/base/hash/cl_rcpointer2_hashweak_rcpointer.h new file mode 100644 index 0000000..5514efa --- /dev/null +++ b/src/base/hash/cl_rcpointer2_hashweak_rcpointer.h @@ -0,0 +1,44 @@ +// cl_rcpointer hash tables + +#ifndef _CL_RCPOINTER2_HASHWEAK_RCPOINTER_H +#define _CL_RCPOINTER2_HASHWEAK_RCPOINTER_H + +#include "cl_object.h" + +#include "cl_hash2weak.h" + +// Equality. +static inline bool equal (const cl_rcpointer& x, const cl_rcpointer& y) +{ return (x.pointer == y.pointer); } + +// Hash code. Luckily objects don't move around in memory. +inline unsigned long hashcode (const cl_rcpointer& x1, const cl_rcpointer& x2) +{ + var unsigned long hashcode1 = (unsigned long)x1.pointer; + var unsigned long hashcode2 = (unsigned long)x2.pointer; + hashcode2 = (hashcode2 << 5) | (hashcode2 >> (long_bitsize-5)); // rotate + return hashcode1 ^ hashcode2; +} + +typedef cl_htentry2 cl_htentry_from_rcpointer2_to_rcpointer; + +typedef cl_heap_weak_hashtable_2 cl_heap_weak_hashtable_from_rcpointer2_to_rcpointer; + +typedef _cl_hashtable_iterator cl_hashtable_from_rcpointer2_to_rcpointer_iterator; + +struct cl_wht_from_rcpointer2_to_rcpointer : public cl_rcpointer { + // Constructors. + cl_wht_from_rcpointer2_to_rcpointer (cl_boolean (*maygc_htentry) (const cl_htentry_from_rcpointer2_to_rcpointer&)); + cl_wht_from_rcpointer2_to_rcpointer (const cl_wht_from_rcpointer2_to_rcpointer&); + // Assignment operators. + cl_wht_from_rcpointer2_to_rcpointer& operator= (const cl_wht_from_rcpointer2_to_rcpointer&); + // Iterator. + cl_hashtable_from_rcpointer2_to_rcpointer_iterator iterator () const + { return ((cl_heap_weak_hashtable_from_rcpointer2_to_rcpointer*)pointer)->iterator(); } + // Lookup. + cl_rcpointer * get (const cl_rcpointer& x, const cl_rcpointer& y) const; + // Store. + void put (const cl_rcpointer& x, const cl_rcpointer& y, const cl_rcpointer& z) const; +}; + +#endif /* _CL_RCPOINTER2_HASHWEAK_RCPOINTER_H */ diff --git a/src/base/hash/cl_rcpointer_hashweak_rcpointer.cc b/src/base/hash/cl_rcpointer_hashweak_rcpointer.cc new file mode 100644 index 0000000..8967994 --- /dev/null +++ b/src/base/hash/cl_rcpointer_hashweak_rcpointer.cc @@ -0,0 +1,47 @@ +// class cl_wht_from_rcpointer_to_rcpointer. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rcpointer_hashweak_rcpointer.h" + + +// Implementation. + +#include "cl_hash1weak.h" + +static void cl_weak_hashtable_from_rcpointer_to_rcpointer_destructor (cl_heap* pointer) +{ +#if (defined(__mips__) || defined(__mips64__)) && !defined(__GNUC__) // workaround SGI CC bug + (*(cl_heap_weak_hashtable_from_rcpointer_to_rcpointer*)pointer).~cl_heap_weak_hashtable_1(); +#else + (*(cl_heap_weak_hashtable_from_rcpointer_to_rcpointer*)pointer).~cl_heap_weak_hashtable_from_rcpointer_to_rcpointer(); +#endif +} + +cl_class cl_class_weak_hashtable_from_rcpointer_to_rcpointer = { + cl_weak_hashtable_from_rcpointer_to_rcpointer_destructor, + 0 +}; + +// These are not inline, because they tend to duplicate a lot of template code. + +cl_wht_from_rcpointer_to_rcpointer::cl_wht_from_rcpointer_to_rcpointer (cl_boolean (*maygc_htentry) (const cl_htentry_from_rcpointer_to_rcpointer&)) +{ + var cl_heap_weak_hashtable_from_rcpointer_to_rcpointer* ht = new cl_heap_weak_hashtable_from_rcpointer_to_rcpointer (maygc_htentry); + ht->refcount = 1; + ht->type = &cl_class_weak_hashtable_from_rcpointer_to_rcpointer; + pointer = ht; +} + +cl_rcpointer * cl_wht_from_rcpointer_to_rcpointer::get (const cl_rcpointer& x) const +{ + return ((cl_heap_weak_hashtable_from_rcpointer_to_rcpointer*)pointer)->get(x); +} + +void cl_wht_from_rcpointer_to_rcpointer::put (const cl_rcpointer& x, const cl_rcpointer& y) const +{ + ((cl_heap_weak_hashtable_from_rcpointer_to_rcpointer*)pointer)->put(x,y); +} + diff --git a/src/base/hash/cl_rcpointer_hashweak_rcpointer.h b/src/base/hash/cl_rcpointer_hashweak_rcpointer.h new file mode 100644 index 0000000..96e5413 --- /dev/null +++ b/src/base/hash/cl_rcpointer_hashweak_rcpointer.h @@ -0,0 +1,39 @@ +// cl_rcpointer hash tables + +#ifndef _CL_RCPOINTER_HASHWEAK_RCPOINTER_H +#define _CL_RCPOINTER_HASHWEAK_RCPOINTER_H + +#include "cl_object.h" + +#include "cl_hash1weak.h" + +// Equality. +static inline bool equal (const cl_rcpointer& x, const cl_rcpointer& y) +{ return (x.pointer == y.pointer); } + +// Hash code. Luckily objects don't move around in memory. +inline unsigned long hashcode (const cl_rcpointer& x) +{ return (unsigned long)x.pointer; } + +typedef cl_htentry1 cl_htentry_from_rcpointer_to_rcpointer; + +typedef cl_heap_weak_hashtable_1 cl_heap_weak_hashtable_from_rcpointer_to_rcpointer; + +typedef _cl_hashtable_iterator cl_hashtable_from_rcpointer_to_rcpointer_iterator; + +struct cl_wht_from_rcpointer_to_rcpointer : public cl_rcpointer { + // Constructors. + cl_wht_from_rcpointer_to_rcpointer (cl_boolean (*maygc_htentry) (const cl_htentry_from_rcpointer_to_rcpointer&)); + cl_wht_from_rcpointer_to_rcpointer (const cl_wht_from_rcpointer_to_rcpointer&); + // Assignment operators. + cl_wht_from_rcpointer_to_rcpointer& operator= (const cl_wht_from_rcpointer_to_rcpointer&); + // Iterator. + cl_hashtable_from_rcpointer_to_rcpointer_iterator iterator () const + { return ((cl_heap_weak_hashtable_from_rcpointer_to_rcpointer*)pointer)->iterator(); } + // Lookup. + cl_rcpointer * get (const cl_rcpointer& x) const; + // Store. + void put (const cl_rcpointer& x, const cl_rcpointer& y) const; +}; + +#endif /* _CL_RCPOINTER_HASHWEAK_RCPOINTER_H */ diff --git a/src/base/input/Makeflags b/src/base/input/Makeflags new file mode 100644 index 0000000..c329293 --- /dev/null +++ b/src/base/input/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/base/Makeflags +SUBDIR_INCLUDES += diff --git a/src/base/input/cl_read_err_bad.cc b/src/base/input/cl_read_err_bad.cc new file mode 100644 index 0000000..1880a35 --- /dev/null +++ b/src/base/input/cl_read_err_bad.cc @@ -0,0 +1,22 @@ +// read_number_bad_syntax(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_number_io.h" + + +// Implementation. + +#include "cl_io.h" +#include "cl_abort.h" + +void read_number_bad_syntax (const char * string, const char * string_limit) +{ + fprint(cl_stderr, "Illegal number syntax: \""); + for (const char * ptr = string; ptr != string_limit; ptr++) + fprintchar(cl_stderr, *ptr); + fprint(cl_stderr, "\"\n"); + cl_abort(); +} diff --git a/src/base/input/cl_read_err_eof.cc b/src/base/input/cl_read_err_eof.cc new file mode 100644 index 0000000..f6bd100 --- /dev/null +++ b/src/base/input/cl_read_err_eof.cc @@ -0,0 +1,19 @@ +// read_number_eof(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_number_io.h" + + +// Implementation. + +#include "cl_io.h" +#include "cl_abort.h" + +void read_number_eof (void) +{ + fprint(cl_stderr, "read_number: end of stream encountered\n"); + cl_abort(); +} diff --git a/src/base/input/cl_read_err_junk.cc b/src/base/input/cl_read_err_junk.cc new file mode 100644 index 0000000..3cc5fc9 --- /dev/null +++ b/src/base/input/cl_read_err_junk.cc @@ -0,0 +1,27 @@ +// read_number_junk(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_number_io.h" + + +// Implementation. + +#include "cl_io.h" +#include "cl_abort.h" + +void read_number_junk (const char * string_rest, const char * string, const char * string_limit) +{ + fprint(cl_stderr, "Junk after number: "); + { for (const char * ptr = string; ptr != string_rest; ptr++) + fprintchar(cl_stderr, *ptr); + } + fprint(cl_stderr, "\""); + { for (const char * ptr = string_rest; ptr != string_limit; ptr++) + fprintchar(cl_stderr, *ptr); + } + fprint(cl_stderr, "\"\n"); + cl_abort(); +} diff --git a/src/base/low/Makeflags b/src/base/low/Makeflags new file mode 100644 index 0000000..c329293 --- /dev/null +++ b/src/base/low/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/base/Makeflags +SUBDIR_INCLUDES += diff --git a/src/base/low/cl_low_div.cc b/src/base/low/cl_low_div.cc new file mode 100644 index 0000000..13641f9 --- /dev/null +++ b/src/base/low/cl_low_div.cc @@ -0,0 +1,306 @@ +// Low level: division. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_low.h" + + +// Implementation. + +#ifdef NEED_VAR_divu_16_rest +uint16 divu_16_rest; +#endif + +#ifdef NEED_FUNCTION_divu_3216_1616_ +uint16 divu_16_rest; +#if 1 +// Most processors have a good 32 by 32 bit division, use that. +uint16 divu_3216_1616_ (uint32 x, uint16 y) +{ + var uint16 q = floor(x,(uint32)y); + divu_16_rest = x - (uint32)q * (uint32)y; + return q; +} +#else +// On processors without a hardware division, we have to produce the quotient's +// bits individually. Basically the algorithm is like this: +// q := 0; r := x; +// if (r >= 2^15*y) { r -= 2^15*y; q |= 2^15; } +// if (r >= 2^14*y) { r -= 2^14*y; q |= 2^14; } +// ... +// if (r >= 2^0*y) { r -= 2^0*y; q |= 2^0; } +// We don't want to shift 2^k*y to the right. Instead, we shift r to the left: +// q := 0; r := x; +// if (r >= 2^15*y) { r -= 2^15*y; q |= 2^15; } +// if (2*r >= 2^15*y) { 2*r -= 2^15*y; q |= 2^14; } +// ... +// if (2^15*r >= 2^15*y) { 2^15*r -= 2^15*y; q |= 2^0; } +// In other terms: +// q := 0; r := x; s := 2^15*y; +// if (r >= s) { r -= s; q |= 2^15; } +// r := 2*r; +// if (r >= s) { r -= s; q |= 2^14; } +// r := 2*r; +// ... +// r := 2*r; +// if (r >= s) { r -= s; q |= 2^0; } +// r := r >> 15; +// Now, we combine r and q into a single register. The bits of q won't disturb +// the "r >= s" comparisons because up to the last comparisons only max 15 +// bits have accumulated, and s is a multiple of 2^15. +// We can thus shift r and q with a single instruction. +// q := 0; r := x; s := 2^15*y; +// if (r >= s) { r -= s; r := 2*r+1; } else r := 2*r; +// if (r >= s) { r -= s; r := 2*r+1; } else r := 2*r; +// ... +// if (r >= s) { r -= s; r := 2*r+1; } else r := 2*r; +// q := r & (2^16-1); r := r >> 16; +// Up to now, this is pretty standard. +// On most hardware the comparison "r >= s" already implies doing a subtraction +// r - s. It is wasteful to do the subtraction twice. Better do it once and +// test the carry afterwards: +// q := 0; r := x; s := 2^15*y; +// r -= s; if (no subcarry) { r := 2*r+1; } else { r := 2*r+2*s; } +// r -= s; if (no subcarry) { r := 2*r+1; } else { r := 2*r+2*s; } +// ... +// r -= s; if (no subcarry) { r := 2*r+1; } else { r := 2*r+2*s; } +// q := r & (2^16-1); r := r >> 16; +// In the case of carry we can combine the "+2*s" with the next "-s" operation. +// So this becomes "r := 2*r+s". But note about the carries: the case +// "(2*r+2*s)-s gives no subcarry" is equivalent to "2*r+s gives an addcarry". +// On most processors, subcarry and addcarry are the same bit. So we turn +// the subcarry into an addcarry by writing "r += -s" instead of "r -= s" +// (or vice versa: writing "2*r-(-s)" instead of "2*r+s"). +// q := 0; r := x; s := 2^15*y; +// r += -s; +// if (addcarry) { r := 2*r+1; r += -s; } else { r := 2*r+s; } +// if (addcarry) { r := 2*r+1; r += -s; } else { r := 2*r+s; } +// ... +// if (addcarry) { r := 2*r+1; } else { r := 2*r+2*s; } +// q := r & (2^16-1); r := r >> 16; +// This algorithm is implemented in cl_asm_arm.cc and (in slightly modified +// form) in cl_asm_sparc.cc. +#endif +#endif + +#ifdef NEED_FUNCTION_divu_3232_3232_ +// Dies dient nur noch als Hilfsfunktion für floorD(). +// Die Rückgabe des Restes in divu_32_rest ist also hier nicht nötig. +uint32 divu_3232_3232_(uint32 x, uint32 y) +{ + var uint32 q; + divu_3232_3232(x,y,q=,); + return q; +} +#endif + +#ifdef NEED_VAR_divu_32_rest +uint32 divu_32_rest; +#endif + +#ifdef NEED_FUNCTION_divu_6432_3232_ +uint32 divu_32_rest; +uint32 divu_6432_3232_(uint32 xhi, uint32 xlo, uint32 y) +// Methode: +// Wie UDS_divide mit intDsize=16, a_len=4, b_len=2. +{ + if (y <= (uint32)(bit(16)-1)) + // 48-durch-16-Bit-Division, + // aufgebaut aus zwei 32-durch-16-Bit-Divisionen: + { var uint16 q1; + var uint16 q0; + var uint16 r1; + divu_3216_1616(highlow32(low16(xhi),high16(xlo)),y, q1=,r1=); + divu_3216_1616(highlow32(r1,low16(xlo)),y, q0=,divu_32_rest=); + return highlow32(q1,q0); + } + // y>=2^16 + {// y shiften: + var uintL s = 0; + while ((sint32)y >= 0) { y = y<<1; s++; } + // x entsprechend shiften: + if (!(s==0)) + { xhi = (xhi << s) | (xlo >> (32-s)); xlo = xlo << s; } + // 64-durch-32-Bit-Division, + // aufgebaut aus zwei 48-durch-32-Bit-Divisionen. + // Methode für eine 48-durch-32-Bit-Division x/y mit 0 <= x < 2^16*y : + // (beta = 2^n = 2^16, n = 16) + // Wir wissen beta^2/2 <= y < beta^2, Quotient q = floor(x/y) < beta. + // Schreibe x = beta*x1 + x0 mit x1 := floor(x/beta) + // und y = beta*y1 + y0 mit y1 := floor(y/beta) + // und bilde den Näherungs-Quotienten floor(x1/y1) + // oder (noch besser) floor(x1/(y1+1)). + // Wegen 0 <= x1 < 2^(2n) und 0 < 2^(n-1) <= y1 < 2^n + // und x1/(y1+1) <= x/y < x1/(y1+1) + 2 + // (denn x1/(y1+1) = (x1*beta)/((y1+1)*beta) <= (x1*beta)/y <= x/y + // und x/y - x1/(y1+1) = (x+x*y1-x1*y)/(y*(y1+1)) + // = (x+x0*y1-x1*y0)/(y*(y1+1)) <= (x+x0*y1)/(y*(y1+1)) + // <= x/(y*(y1+1)) + x0/y = (x/y)/(y1+1) + x0/y + // <= 2^n/(2^(n-1)+1) + 2^n/2^(2n-1) = 2^n/(2^(n-1)+1) + 2^(1-n) < 2 ) + // gilt floor(x1/(y1+1)) <= floor(x/y) <= floor(x1/(y1+1)) + 2 . + // Man bildet also q:=floor(x1/(y1+1)) (ein Shift um n Bit oder + // eine (2n)-durch-n-Bit-Division, mit Ergebnis q <= floor(x/y) < beta) + // und x-q*y und muß hiervon noch höchstens 2 mal y abziehen und q + // incrementieren, um den Quotienten q = floor(x/y) und den Rest + // x-floor(x/y)*y der Division zu bekommen. + { var uint16 y1_1 = high16(y)+1; // y1+1 + var uint16 q1; + var uint16 q0; + var uint32 r; + // 2^16*xhi+high16(xlo) durch y dividieren: + {var uint16 r16; + var uint32 r2; + if (y1_1==0) + { q1 = high16(xhi); r16 = low16(xhi); } + else + { divu_3216_1616(xhi,y1_1, q1=,r16=); } + // q1 = floor(xhi/(y1+1)), r16 = xhi - (y1+1)*q1 (>=0, <=y1) + // Bilde r := (2^16*xhi+high16(xlo)) - y*q1 + // = 2^16*(xhi-y1*q1) + high16(xlo) - y0*q1 + // = 2^16*r16 + 2^16*q1 + high16(xlo) - y0*q1 (>=0) + // Dies ist < 2^16*y1 + 2^32 <= y + 2^32 <= 3*y, kann überlaufen! + r = highlow32(r16,high16(xlo)); // 2^16*r16 + high16(xlo) < 2^32 + r2 = highlow32_0(q1) - mulu16(low16(y),q1); // 2^16*q1 - y0*q1 < 2^32 + // 0 <= r+r2 < 3*y. Bei der Addition auf Carry testen! + // Carry -> jedenfalls y <= r+r2 < y + 2^32 <= 3*y. + // kein Carry -> jedenfalls 0 <= r+r2 < 2^32 <= 2*y. + if ((r += r2) < r2) // addieren, r >= 2^32 ? + { q1 += 1; r -= y; } + // jetzt noch 0 <= r < 2^32 <= 2*y + if (r >= y) + { q1 += 1; r -= y; } + }// Quotient q1, Rest r fertig. + // 2^16*r+low16(xlo) durch y dividieren: + {var uint16 r16; + var uint32 r2; + if (y1_1==0) + { q0 = high16(r); r16 = low16(r); } + else + { divu_3216_1616(r,y1_1, q0=,r16=); } + // q0 = floor(r/(y1+1)), r16 = r - (y1+1)*q0 (>=0, <=y1) + // Bilde r := (2^16*r+low16(xlo)) - y*q0 + // = 2^16*(r-y1*q0) + low16(xlo) - y0*q0 + // = 2^16*r16 + 2^16*q0 + low16(xlo) - y0*q0 (>=0) + // Dies ist < 2^16*y1 + 2^32 <= y + 2^32 <= 3*y, kann überlaufen! + r = highlow32(r16,low16(xlo)); // 2^16*r16 + low16(xlo) < 2^32 + r2 = highlow32_0(q0) - mulu16(low16(y),q0); // 2^16*q0 - y0*q0 < 2^32 + // 0 <= r+r2 < 3*y. Bei der Addition auf Carry testen! + // Carry -> jedenfalls y <= r+r2 < y + 2^32 <= 3*y. + // kein Carry -> jedenfalls 0 <= r+r2 < 2^32 <= 2*y. + if ((r += r2) < r2) // addieren, r >= 2^32 ? + { q0 += 1; r -= y; } + // jetzt noch 0 <= r < 2^32 <= 2*y + if (r >= y) + { q0 += 1; r -= y; } + }// Quotient q0, Rest r fertig. + divu_32_rest = r >> s; // Rest + return highlow32(q1,q0); // Quotient +} } } +#endif + +#ifdef NEED_VAR_divu_64_rest +uint64 divu_64_rest; +#endif + +#ifdef NEED_FUNCTION_divu_12864_6464_ +uint64 divu_64_rest; +uint64 divu_12864_6464_(uint64 xhi, uint64 xlo, uint64 y) +// Methode: +// Wie UDS_divide mit intDsize=32, a_len=4, b_len=2. +{ + if (y <= (uint64)(bit(32)-1)) + // 96-durch-32-Bit-Division, + // aufgebaut aus zwei 64-durch-32-Bit-Divisionen: + { var uint32 q1; + var uint32 q0; + var uint32 r1; + divu_6432_3232(low32(xhi),high32(xlo),y, q1=,r1=); + divu_6432_3232(r1,low32(xlo),y, q0=,divu_64_rest=); + return highlow64(q1,q0); + } + // y>=2^32 + {// y shiften: + var uintL s = 0; + while ((sint64)y >= 0) { y = y<<1; s++; } + // x entsprechend shiften: + if (!(s==0)) + { xhi = (xhi << s) | (xlo >> (64-s)); xlo = xlo << s; } + // 128-durch-64-Bit-Division, + // aufgebaut aus zwei 96-durch-64-Bit-Divisionen. + // Methode für eine 96-durch-64-Bit-Division x/y mit 0 <= x < 2^32*y : + // (beta = 2^n = 2^32, n = 32) + // Wir wissen beta^2/2 <= y < beta^2, Quotient q = floor(x/y) < beta. + // Schreibe x = beta*x1 + x0 mit x1 := floor(x/beta) + // und y = beta*y1 + y0 mit y1 := floor(y/beta) + // und bilde den Näherungs-Quotienten floor(x1/y1) + // oder (noch besser) floor(x1/(y1+1)). + // Wegen 0 <= x1 < 2^(2n) und 0 < 2^(n-1) <= y1 < 2^n + // und x1/(y1+1) <= x/y < x1/(y1+1) + 2 + // (denn x1/(y1+1) = (x1*beta)/((y1+1)*beta) <= (x1*beta)/y <= x/y + // und x/y - x1/(y1+1) = (x+x*y1-x1*y)/(y*(y1+1)) + // = (x+x0*y1-x1*y0)/(y*(y1+1)) <= (x+x0*y1)/(y*(y1+1)) + // <= x/(y*(y1+1)) + x0/y = (x/y)/(y1+1) + x0/y + // <= 2^n/(2^(n-1)+1) + 2^n/2^(2n-1) = 2^n/(2^(n-1)+1) + 2^(1-n) < 2 ) + // gilt floor(x1/(y1+1)) <= floor(x/y) <= floor(x1/(y1+1)) + 2 . + // Man bildet also q:=floor(x1/(y1+1)) (ein Shift um n Bit oder + // eine (2n)-durch-n-Bit-Division, mit Ergebnis q <= floor(x/y) < beta) + // und x-q*y und muß hiervon noch höchstens 2 mal y abziehen und q + // incrementieren, um den Quotienten q = floor(x/y) und den Rest + // x-floor(x/y)*y der Division zu bekommen. + { var uint32 y1_1 = high32(y)+1; // y1+1 + var uint32 q1; + var uint32 q0; + var uint64 r; + // 2^32*xhi+high32(xlo) durch y dividieren: + {var uint32 r32; + var uint64 r2; + if (y1_1==0) + { q1 = high32(xhi); r32 = low32(xhi); } + else + { divu_6432_3232_w(xhi,y1_1, q1=,r32=); } + // q1 = floor(xhi/(y1+1)), r32 = xhi - (y1+1)*q1 (>=0, <=y1) + // Bilde r := (2^32*xhi+high32(xlo)) - y*q1 + // = 2^32*(xhi-y1*q1) + high32(xlo) - y0*q1 + // = 2^32*r32 + 2^32*q1 + high32(xlo) - y0*q1 (>=0) + // Dies ist < 2^32*y1 + 2^64 <= y + 2^64 <= 3*y, kann überlaufen! + r = highlow64(r32,high32(xlo)); // 2^32*r32 + high32(xlo) < 2^64 + r2 = highlow64_0(q1) - mulu32_w(low32(y),q1); // 2^32*q1 - y0*q1 < 2^64 + // 0 <= r+r2 < 3*y. Bei der Addition auf Carry testen! + // Carry -> jedenfalls y <= r+r2 < y + 2^64 <= 3*y. + // kein Carry -> jedenfalls 0 <= r+r2 < 2^64 <= 2*y. + if ((r += r2) < r2) // addieren, r >= 2^64 ? + { q1 += 1; r -= y; } + // jetzt noch 0 <= r < 2^64 <= 2*y + if (r >= y) + { q1 += 1; r -= y; } + }// Quotient q1, Rest r fertig. + // 2^32*r+low32(xlo) durch y dividieren: + {var uint32 r32; + var uint64 r2; + if (y1_1==0) + { q0 = high32(r); r32 = low32(r); } + else + { divu_6432_3232_w(r,y1_1, q0=,r32=); } + // q0 = floor(r/(y1+1)), r32 = r - (y1+1)*q0 (>=0, <=y1) + // Bilde r := (2^32*r+low32(xlo)) - y*q0 + // = 2^32*(r-y1*q0) + low32(xlo) - y0*q0 + // = 2^32*r32 + 2^32*q0 + low32(xlo) - y0*q0 (>=0) + // Dies ist < 2^32*y1 + 2^64 <= y + 2^64 <= 3*y, kann überlaufen! + r = highlow64(r32,low32(xlo)); // 2^32*r32 + low32(xlo) < 2^64 + r2 = highlow64_0(q0) - mulu32_w(low32(y),q0); // 2^32*q0 - y0*q0 < 2^64 + // 0 <= r+r2 < 3*y. Bei der Addition auf Carry testen! + // Carry -> jedenfalls y <= r+r2 < y + 2^64 <= 3*y. + // kein Carry -> jedenfalls 0 <= r+r2 < 2^64 <= 2*y. + if ((r += r2) < r2) // addieren, r >= 2^64 ? + { q0 += 1; r -= y; } + // jetzt noch 0 <= r < 2^64 <= 2*y + if (r >= y) + { q0 += 1; r -= y; } + }// Quotient q0, Rest r fertig. + divu_64_rest = r >> s; // Rest + return highlow64(q1,q0); // Quotient +} } } +#endif + diff --git a/src/base/low/cl_low_isqrt.cc b/src/base/low/cl_low_isqrt.cc new file mode 100644 index 0000000..a5714e5 --- /dev/null +++ b/src/base/low/cl_low_isqrt.cc @@ -0,0 +1,60 @@ +// isqrt(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_low.h" + + +// Implementation. + +// Zieht die Ganzzahl-Wurzel aus einer 32-Bit-Zahl und +// liefert eine 16-Bit-Wurzel. +// isqrt(x) +// > uintL x : Radikand, >=0, <2^32 +// < uintL ergebnis : Wurzel, >=0, <2^16 +uintL isqrt (uintL x) +{ + // Methode: + // x=0 -> y=0, fertig. + // y := 2^k als Anfangswert, wobei k>0, k<=16 mit 2^(2k-2) <= x < 2^(2k) sei. + // y := floor((y + floor(x/y))/2) als nächster Wert, + // solange z := floor(x/y) < y, setze y := floor((y+z)/2). + // y ist fertig. + // (Beweis: + // 1. Die Folge der y ist streng monoton fallend. + // 2. Stets gilt y >= floor(sqrt(x)) (denn für alle y>0 ist + // y + x/y >= 2*sqrt(x) und daher floor((y + floor(x/y))/2) = + // floor(y/2 + x/(2*y)) >= floor(sqrt(x)) ). + // 3. Am Schluß gilt x >= y^2. + // ) + if (x==0) return 0; // x=0 -> y=0 + { var uintC k2; integerlength32(x,k2=); // 2^(k2-1) <= x < 2^k2 + {var uintC k1 = floor(k2-1,2); // k1 = k-1, k wie oben + if (k1 < 16-1) + // k < 16 + { var uintL y = (x >> (k1+2)) | bit(k1); // stets 2^(k-1) <= y < 2^k + loop + { var uintL z; + divu_3216_1616(x,y, z=,); // Dividiere x/y (geht, da x/y < 2^(2k)/2^(k-1) = 2^(k+1) <= 2^16) + if (z >= y) break; + y = floor(z+y,2); // geht, da z+y < 2*y < 2^(k+1) <= 2^16 + } + return y; + } + else + // k = 16, Vorsicht! + { var uintL x1 = high16(x); + var uintL y = (x >> (16+1)) | bit(16-1); // stets 2^(k-1) <= y < 2^k + loop + { var uintL z; + if (x1 >= y) break; // Division x/y ergäbe Überlauf -> z > y + divu_3216_1616(x,y, z=,); // Dividiere x/y + if (z >= y) break; + y = floor(z+y,2); + } + return y; + } + }} +} diff --git a/src/base/low/cl_low_isqrt2.cc b/src/base/low/cl_low_isqrt2.cc new file mode 100644 index 0000000..396cfac --- /dev/null +++ b/src/base/low/cl_low_isqrt2.cc @@ -0,0 +1,59 @@ +// isqrt(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_low.h" + + +// Implementation. + +// Zieht die Ganzzahl-Wurzel aus einer 64-Bit-Zahl und +// liefert eine 32-Bit-Wurzel. +// isqrt(x1,x0) +// > uintL2 x = x1*2^32+x0 : Radikand, >=0, <2^64 +// < uintL ergebnis : Wurzel, >=0, <2^32 +uintL isqrt (uintL x1, uintL x0) +{ + // Methode: + // x=0 -> y=0, fertig. + // y := 2^k als Anfangswert, wobei k>0, k<=32 mit 2^(2k-2) <= x < 2^(2k) sei. + // y := floor((y + floor(x/y))/2) als nächster Wert, + // solange z := floor(x/y) < y, setze y := floor((y+z)/2). + // y ist fertig. + // (Beweis: + // 1. Die Folge der y ist streng monoton fallend. + // 2. Stets gilt y >= floor(sqrt(x)) (denn für alle y>0 ist + // y + x/y >= 2*sqrt(x) und daher floor((y + floor(x/y))/2) = + // floor(y/2 + x/(2*y)) >= floor(sqrt(x)) ). + // 3. Am Schluß gilt x >= y^2. + // ) + if (x1==0) { return isqrt(x0); } // x klein? + { var uintC k2; integerlength32(x1,k2=); // 2^(k2+32-1) <= x < 2^(k2+32) + {var uintC k = ceiling(k2+32,2); // k wie oben + if (k < 32) + // k < 32 + { var uintL y = ((x1 << (32-k)) | (x0 >> k) | bit(k)) >> 1; // stets 2^(k-1) <= y < 2^k + loop + { var uintL z; + divu_6432_3232(x1,x0,y, z=,); // Dividiere x/y (geht, da x/y < 2^(2k)/2^(k-1) = 2^(k+1) <= 2^32) + if (z >= y) break; + y = floor(z+y,2); // geht, da z+y < 2*y < 2^(k+1) <= 2^32 + } + return y; + } + else + // k = 32, Vorsicht! + { var uintL y = (x1 >> 1) | bit(32-1); // stets 2^(k-1) <= y < 2^k + loop + { var uintL z; + if (x1 >= y) break; // Division x/y ergäbe Überlauf -> z > y + divu_6432_3232(x1,x0,y, z=,); // Dividiere x/y + if (z >= y) break; + y = floor(z+y,2) | bit(32-1); // y muß >= 2^(k-1) bleiben + } + return y; + } + }} +} diff --git a/src/base/low/cl_low_mul.cc b/src/base/low/cl_low_mul.cc new file mode 100644 index 0000000..eacd99f --- /dev/null +++ b/src/base/low/cl_low_mul.cc @@ -0,0 +1,71 @@ +// Low level: multiplication. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_low.h" + + +// Implementation. + +#ifdef NEED_VAR_mulu32_high +uint32 mulu32_high; +#endif + +#ifdef NEED_FUNCTION_mulu32_ +uint32 mulu32_high; +uint32 mulu32_ (uint32 x, uint32 y) +{ + var uint16 x1 = high16(x); + var uint16 x0 = low16(x); + var uint16 y1 = high16(y); + var uint16 y0 = low16(y); + var uint32 hi = mulu16(x1,y1); // obere Portion + var uint32 lo = mulu16(x0,y0); // untere Portion + {var uint32 mid = mulu16(x0,y1); // 1. mittlere Portion + hi += high16(mid); mid = highlow32_0(low16(mid)); + lo += mid; if (lo < mid) { hi += 1; } // 64-Bit-Addition + } + {var uint32 mid = mulu16(x1,y0); // 2. mittlere Portion + hi += high16(mid); mid = highlow32_0(low16(mid)); + lo += mid; if (lo < mid) { hi += 1; } // 64-Bit-Addition + } + mulu32_high = hi; return lo; +} +#endif + +#ifdef NEED_FUNCTION_mulu32_w +uint64 mulu32_w (uint32 arg1, uint32 arg2) +{ + var uint32 lo = mulu32_(arg1,arg2); + var uint32 hi = mulu32_high; + return highlow64(hi,lo); +} +#endif + +#ifdef NEED_VAR_mulu64_high +uint64 mulu64_high; +#endif + +#ifdef NEED_FUNCTION_mulu64_ +uint64 mulu64_high; +uint64 mulu64_ (uint64 x, uint64 y) +{ + var uint32 x1 = high32(x); + var uint32 x0 = low32(x); + var uint32 y1 = high32(y); + var uint32 y0 = low32(y); + var uint64 hi = mulu32_w(x1,y1); // obere Portion + var uint64 lo = mulu32_w(x0,y0); // untere Portion + {var uint64 mid = mulu32_w(x0,y1); // 1. mittlere Portion + hi += high32(mid); mid = highlow64_0(low32(mid)); + lo += mid; if (lo < mid) { hi += 1; } // 128-Bit-Addition + } + {var uint64 mid = mulu32_w(x1,y0); // 2. mittlere Portion + hi += high32(mid); mid = highlow64_0(low32(mid)); + lo += mid; if (lo < mid) { hi += 1; } // 128-Bit-Addition + } + mulu64_high = hi; return lo; +} +#endif diff --git a/src/base/output/Makeflags b/src/base/output/Makeflags new file mode 100644 index 0000000..c329293 --- /dev/null +++ b/src/base/output/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/base/Makeflags +SUBDIR_INCLUDES += diff --git a/src/base/output/cl_output_dec.cc b/src/base/output/cl_output_dec.cc new file mode 100644 index 0000000..3465bf1 --- /dev/null +++ b/src/base/output/cl_output_dec.cc @@ -0,0 +1,57 @@ +// fprintdecimal(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_io.h" + + +// Implementation. + +#if defined(CL_IO_STDIO) + +void fprintdecimal (cl_ostream stream, unsigned long x) +{ + fprintf(stream,"%lu",x); +} + +void fprintdecimal (cl_ostream stream, long x) +{ + fprintf(stream,"%ld",x); +} + +#endif + +#if defined(CL_IO_IOSTREAM) + +// We don't use `stream << x' or `stream << dec << x', because an ostream +// carries so many attributes, and we don't want to modifies these attributes. + +void fprintdecimal (cl_ostream stream, unsigned long x) +{ + #define bufsize 20 + var char buf[bufsize+1]; + var char* bufptr = &buf[bufsize]; + *bufptr = '\0'; + do { + unsigned long q = x / 10; + unsigned long r = x % 10; + *--bufptr = '0'+r; + x = q; + } while (x > 0); + fprint(stream,bufptr); + #undef bufsize +} + +void fprintdecimal (cl_ostream stream, long x) +{ + if (x >= 0) + fprintdecimal(stream,(unsigned long)x); + else { + fprintchar(stream,'-'); + fprintdecimal(stream,(unsigned long)(-1-x)+1); + } +} + +#endif diff --git a/src/base/output/cl_output_hex.cc b/src/base/output/cl_output_hex.cc new file mode 100644 index 0000000..7098b31 --- /dev/null +++ b/src/base/output/cl_output_hex.cc @@ -0,0 +1,49 @@ +// fprinthexadecimal(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_io.h" + + +// Implementation. + +#if defined(CL_IO_STDIO) + +void fprinthexadecimal (cl_ostream stream, unsigned long x) +{ + fprintf(stream,"%lX",x); +} + +#endif + +#if defined(CL_IO_IOSTREAM) + +void fprinthexadecimal (cl_ostream stream, unsigned long x) +{ + #define bufsize 16 + var char buf[bufsize+1]; + var char* bufptr = &buf[bufsize]; + *bufptr = '\0'; + do { + unsigned long q = x / 16; + unsigned long r = x % 16; + *--bufptr = (r<10 ? '0'+r : 'A'-10+r); + x = q; + } while (x > 0); + fprint(stream,bufptr); + #undef bufsize +} + +#endif + +void fprinthexadecimal (cl_ostream stream, long x) +{ + if (x >= 0) + fprintdecimal(stream,(unsigned long)x); + else { + fprintchar(stream,'-'); + fprintdecimal(stream,(unsigned long)(-1-x)+1); + } +} diff --git a/src/base/output/cl_prin_globals.cc b/src/base/output/cl_prin_globals.cc new file mode 100644 index 0000000..8a25148 --- /dev/null +++ b/src/base/output/cl_prin_globals.cc @@ -0,0 +1,28 @@ +// Global variables in CLN + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_prin_globals) + +// Specification. +#include "cl_output.h" + + +// Implementation. + +cl_print_flags cl_default_print_flags; +#if 0 // The default constructors already do this. +AT_INITIALIZATION(cl_default_print_flags) +{ + cl_default_print_flags.rational_base = 10; + cl_default_print_flags.rational_readably = cl_false; + cl_default_print_flags.float_readably = cl_false; + cl_default_print_flags.default_float_format = cl_float_format_ffloat; + cl_default_print_flags.complex_readably = cl_false; + cl_default_print_flags.vector_syntax = vsyntax_pretty; + cl_default_print_flags.univpoly_varname = "x"; +} +#endif + +CL_PROVIDE_END(cl_prin_globals) diff --git a/src/base/proplist/Makeflags b/src/base/proplist/Makeflags new file mode 100644 index 0000000..c329293 --- /dev/null +++ b/src/base/proplist/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/base/Makeflags +SUBDIR_INCLUDES += diff --git a/src/base/proplist/cl_pl_add.cc b/src/base/proplist/cl_pl_add.cc new file mode 100644 index 0000000..3240b98 --- /dev/null +++ b/src/base/proplist/cl_pl_add.cc @@ -0,0 +1,23 @@ +// class cl_property_list. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_proplist.h" + + +// Implementation. + +#include "cl_abort.h" + +// This tells the compiler to put the `cl_property' vtable into this file. +void cl_property::dummy () {} + +void cl_property_list::add_property (cl_property* new_property) +{ + if (new_property->next) + cl_abort(); + new_property->next = list; + list = new_property; +} diff --git a/src/base/proplist/cl_pl_d.cc b/src/base/proplist/cl_pl_d.cc new file mode 100644 index 0000000..10cd5d9 --- /dev/null +++ b/src/base/proplist/cl_pl_d.cc @@ -0,0 +1,19 @@ +// class cl_property_list. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_proplist.h" + + +// Implementation. + +cl_property_list::~cl_property_list () +{ + while (list) { + var cl_property* l = list; + list = l->next; + delete l; + } +} diff --git a/src/base/proplist/cl_pl_get.cc b/src/base/proplist/cl_pl_get.cc new file mode 100644 index 0000000..673d2b9 --- /dev/null +++ b/src/base/proplist/cl_pl_get.cc @@ -0,0 +1,19 @@ +// class cl_property_list. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_proplist.h" + + +// Implementation. + +cl_property* cl_property_list::get_property (const cl_symbol& key) +{ + var cl_property* l; + for (l = list; l; l = l->next) + if (equal(l->key,key)) + break; + return l; +} diff --git a/src/base/random/Makeflags b/src/base/random/Makeflags new file mode 100644 index 0000000..7b9d182 --- /dev/null +++ b/src/base/random/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/base/Makeflags +SUBDIR_INCLUDES += -Ibase diff --git a/src/base/random/cl_UL_random.cc b/src/base/random/cl_UL_random.cc new file mode 100644 index 0000000..fbb34be --- /dev/null +++ b/src/base/random/cl_UL_random.cc @@ -0,0 +1,56 @@ +// Word level random number generator. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_random.h" + + +// Implementation. + +#include "cl_low.h" + +// Zufallszahlengenerator nach [Knuth: The Art of Computer Programming, Vol. II, +// Seminumerical Algorithms, 3.3.4., Table 1, Line 30], nach C. Haynes: +// X eine 64-Bit-Zahl. Iteration X := (a*X+c) mod m +// mit m=2^64, a=6364136223846793005, c=1. + +uint32 random32 (cl_random_state& randomstate) +{ +#ifdef HAVE_FAST_LONGLONG + // Multiplikator a=6364136223846793005 = 0x5851F42D4C957F2D : + var uint64 seed = highlow64(randomstate.seed.hi,randomstate.seed.lo); + var const uint64 a = 0x5851F42D4C957F2DUL; + var uint64 newseed; + // multiplizieren, brauche nur letzte 64 Bit: + mulu64(seed,a, , newseed =); + // c addieren: + newseed += 1; + // seed neu füllen: + randomstate.seed.hi = high32(newseed); + randomstate.seed.lo = low32(newseed); + // mittlere 32 Bits als Ergebnis: + return (uint32)(newseed >> 16); + +#else + // Multiplikator a=6364136223846793005 = 0x5851F42D4C957F2D : + var uint32 seed_hi = randomstate.seed.hi; + var uint32 seed_lo = randomstate.seed.lo; + var const uint32 a_hi = 0x5851F42D; + var const uint32 a_lo = 0x4C957F2D; + var uint32 newseed_hi; + var uint32 newseed_lo; + // multiplizieren, brauche nur letzte 64 Bit: + mulu32(seed_lo,a_lo, newseed_hi =, newseed_lo =); + mulu32(seed_lo,a_hi, , newseed_hi +=); + mulu32(seed_hi,a_lo, , newseed_hi +=); + // c addieren: + newseed_lo += 1; if (newseed_lo==0) { newseed_hi += 1; } // um 1 erhöhen + // seed neu füllen: + randomstate.seed.hi = newseed_hi; + randomstate.seed.lo = newseed_lo; + // mittlere 32 Bits als Ergebnis: + return highlow32(low16(newseed_hi),high16(newseed_lo)); +#endif +} diff --git a/src/base/random/cl_random_def.cc b/src/base/random/cl_random_def.cc new file mode 100644 index 0000000..a1e3357 --- /dev/null +++ b/src/base/random/cl_random_def.cc @@ -0,0 +1,16 @@ +// cl_default_random_state. + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_random_def) + +// Specification. +#include "cl_random.h" + + +// Implementation. + +cl_random_state cl_default_random_state; + +CL_PROVIDE_END(cl_random_def) diff --git a/src/base/random/cl_random_from.cc b/src/base/random/cl_random_from.cc new file mode 100644 index 0000000..8ed6392 --- /dev/null +++ b/src/base/random/cl_random_from.cc @@ -0,0 +1,101 @@ +// cl_random_state constructor. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_random.h" + + +// Implementation. + +#include "cl_base_config.h" +#include "cl_low.h" + +#if defined(unix) || defined(__unix) || defined(_AIX) || defined(sinix) || (defined(_WIN32) && defined(__GNUC__)) + +#include +#include // declares getpid() +#include // declares rand() + +#if defined(HAVE_GETTIMEOFDAY) + +#include +#ifdef GETTIMEOFDAY_DOTS + extern "C" int gettimeofday (struct timeval * tp, ...); +#else + extern "C" int gettimeofday (struct timeval * tp, GETTIMEOFDAY_TZP_T tzp); +#endif + +inline uint32 get_seed (void) +{ + var struct timeval tv; + gettimeofday(&tv,0); + return highlow32(tv.tv_sec,tv.tv_usec); // 16+16 zufällige Bits +} + +#elif defined(HAVE_FTIME) + +#include +#ifdef _WIN32 + extern "C" void ftime (struct timeb * tp); +#else + extern "C" int ftime (struct timeb * tp); +#endif + +inline uint32 get_seed (void) +{ + var struct timeb tb; + ftime(&tb); + return (tb.time << 10) | tb.millitm; // 22+10 zufällige Bits +} + +#elif defined(HAVE_TIMES_CLOCK) + +#include +#ifndef CLK_TCK +#include +#endif +#include +extern "C" clock_t times (struct tms * buffer); + +inline uint32 get_seed (void) +{ + var struct tms tmsbuf; + var uint32 seed_lo = times(&tmsbuf); + return seed_lo + tmsbuf.tms_utime + tmsbuf.tms_stime; +} + +#endif + +#endif + +// Counter, to avoid that two random-states created immediately one after +// the other contain the same seed. +static uint32 counter = 0; + +cl_random_state::cl_random_state () +{ + var uint32 seed_hi; + var uint32 seed_lo; +#if defined(unix) || defined(__unix) || defined(_AIX) || defined(sinix) || (defined(_WIN32) && defined(__GNUC__)) + seed_lo = get_seed(); + seed_hi = (rand() // zufällige 31 Bit (bei UNIX_BSD) bzw. 16 Bit (bei UNIX_SYSV) + << 8) ^ (uintL)(getpid()); // ca. 8 Bit von der Process ID +#elif defined(__atarist) + seed_lo = highlow32(GEMDOS_GetDate(),GEMDOS_GetTime()); // 16+16 zufällige Bits + seed_hi = XBIOS_Random(); // 24 Bit zufällig vom XBIOS, vorne 8 Nullbits +#elif defined(amiga) || defined(AMIGA) + seed_lo = get_real_time(); // Uhrzeit + seed_hi = FindTask(NULL); // Pointer auf eigene Task +#elif defined(__MSDOS__) || defined(__EMX__) || defined(__riscos) + // Keine Zufallszahlen, keine PID, nichts Zufälliges da. + seed_lo = get_real_time(); // Uhrzeit, 100 Hz + seed_hi = time(NULL); +#else +#error "Must implement cl_random_state constructor!" +#endif + seed_hi ^= counter++ << 5; + seed.hi = seed_hi; + seed.lo = seed_lo; +} diff --git a/src/base/random/cl_random_impl.h b/src/base/random/cl_random_impl.h new file mode 100644 index 0000000..92e8ff0 --- /dev/null +++ b/src/base/random/cl_random_impl.h @@ -0,0 +1,22 @@ +// cl_random implementation + +#ifndef _CL_RANDOM_IMPL_H +#define _CL_RANDOM_IMPL_H + +#include "cl_random.h" + +// random_UDS(randomstate,MSDptr,len) füllt die UDS MSDptr/len/.. +// mit len Zufallsdigits. +// > randomstate: ein Random-State, wird verändert +// > MSDptr/len/..: wo die Zufallsdigits abgelegt werden sollen +// > len: gewünschte Anzahl von Zufallsdigits +extern void random_UDS (cl_random_state& randomstate, uintD* MSDptr, uintC len); + +// testrandom_UDS(randomstate,MSDptr,len) füllt die UDS MSDptr/len/.. +// mit len Zufallsdigits, mit relativ langen Blöcken von Nullen und Einsen. +// > randomstate: ein Random-State, wird verändert +// > MSDptr/len/..: wo die Zufallsdigits abgelegt werden sollen +// > len: gewünschte Anzahl von Zufallsdigits +extern void testrandom_UDS (cl_random_state& randomstate, uintD* MSDptr, uintC len); + +#endif /* _CL_RANDOM_IMPL_H */ diff --git a/src/base/ring/Makeflags b/src/base/ring/Makeflags new file mode 100644 index 0000000..c329293 --- /dev/null +++ b/src/base/ring/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/base/Makeflags +SUBDIR_INCLUDES += diff --git a/src/base/ring/cl_no_ring.cc b/src/base/ring/cl_no_ring.cc new file mode 100644 index 0000000..d0fe485 --- /dev/null +++ b/src/base/ring/cl_no_ring.cc @@ -0,0 +1,147 @@ +// Dummy ring. + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_no_ring) + +// Specification. +#include "cl_ring.h" + + +// Implementation. + +#include "cl_io.h" +#include "cl_abort.h" + +nonreturning_function(static, uninitialized_ring, (void)); +static void uninitialized_ring () +{ + fprint(cl_stderr, "Uninitialized ring operation called\n"); + cl_abort(); +} + +nonreturning_function(static, uninitialized_error, (const _cl_ring_element&)); +static void uninitialized_error (const _cl_ring_element& obj) +{ + fprint(cl_stderr, "Uninitialized ring element @0x"); + fprinthexadecimal(cl_stderr, (unsigned long)(void*)&obj); + fprint(cl_stderr, ": 0x"); + fprinthexadecimal(cl_stderr, (unsigned long)obj.rep.word); + fprint(cl_stderr, "\n"); + cl_abort(); +} + +#if (defined(__sparc__) && !defined(__GNUC__)) + // avoid Sun C++ 4.1 compiler bug + #define RETDUMMY return *(_cl_ring_element*)R +#else + #define RETDUMMY return *(_cl_ring_element*)0 +#endif + +static const _cl_ring_element dummy_op0 (cl_heap_ring* R) +{ + unused R; + uninitialized_ring(); RETDUMMY; +} + +static const _cl_ring_element dummy_op1 (cl_heap_ring* R, const _cl_ring_element& x) +{ + unused R; + uninitialized_error(x); RETDUMMY; +} + +static const _cl_ring_element dummy_op2 (cl_heap_ring* R, const _cl_ring_element& x, const _cl_ring_element& y) +{ + unused R; + uninitialized_error(x); uninitialized_error(y); RETDUMMY; +} + +static void dummy_fprint (cl_heap_ring* R, cl_ostream stream, const _cl_ring_element& x) +{ + unused R; + unused stream; + uninitialized_error(x); +} +static cl_boolean dummy_equal (cl_heap_ring* R, const _cl_ring_element& x, const _cl_ring_element& y) +{ + unused R; + uninitialized_error(x); uninitialized_error(y); return cl_false; +} + +#define dummy_zero dummy_op0 +static cl_boolean dummy_zerop (cl_heap_ring* R, const _cl_ring_element& x) +{ + unused R; + uninitialized_error(x); return cl_false; +} +#define dummy_plus dummy_op2 +#define dummy_minus dummy_op2 +#define dummy_uminus dummy_op1 + +#define dummy_one dummy_op0 +static const _cl_ring_element dummy_canonhom (cl_heap_ring* R, const cl_I& x) +{ + unused R; + (void)&x; // unused x; + uninitialized_ring(); RETDUMMY; +} +#define dummy_mul dummy_op2 +#define dummy_square dummy_op1 +static const _cl_ring_element dummy_expt_pos (cl_heap_ring* R, const _cl_ring_element& x, const cl_I& y) +{ + unused R; + (void)&y; // unused y; + uninitialized_error(x); RETDUMMY; +} + +static cl_ring_setops dummy_setops = { + dummy_fprint, + dummy_equal +}; +static cl_ring_addops dummy_addops = { + dummy_zero, + dummy_zerop, + dummy_plus, + dummy_minus, + dummy_uminus +}; +static cl_ring_mulops dummy_mulops = { + dummy_one, + dummy_canonhom, + dummy_mul, + dummy_square, + dummy_expt_pos +}; + +class cl_heap_no_ring : public cl_heap_ring { + SUBCLASS_cl_heap_ring() +public: + // Constructor. + cl_heap_no_ring () + : cl_heap_ring (&dummy_setops,&dummy_addops,&dummy_mulops) + { type = &cl_class_no_ring; } + // Destructor. + ~cl_heap_no_ring () {} +}; + +static void cl_no_ring_destructor (cl_heap* pointer) +{ + (*(cl_heap_no_ring*)pointer).~cl_heap_no_ring(); +} + +static void cl_no_ring_dprint (cl_heap* pointer) +{ + unused pointer; + fprint(cl_debugout, "(cl_ring) cl_no_ring"); +} + +cl_class cl_class_no_ring = { + cl_no_ring_destructor, + 0, + cl_no_ring_dprint +}; + +const cl_ring cl_no_ring = cl_ring (new cl_heap_no_ring()); + +CL_PROVIDE_END(cl_no_ring) diff --git a/src/base/ring/cl_ring_debug.cc b/src/base/ring/cl_ring_debug.cc new file mode 100644 index 0000000..cab9b4c --- /dev/null +++ b/src/base/ring/cl_ring_debug.cc @@ -0,0 +1,25 @@ +// cl_ring debugging support. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ring.h" + + +// Implementation. + +#include "cl_io.h" + +void cl_ring_element::debug_print () const +{ + fprint(cl_debugout, *this); + #ifdef CL_IO_IOSTREAM + cl_debugout << endl; // newline and flush output + #else + fprint(cl_debugout, "\n"); + #endif +} + +// This dummy links in this module when requires it. +int cl_ring_debug_module; diff --git a/src/base/string/Makeflags b/src/base/string/Makeflags new file mode 100644 index 0000000..c329293 --- /dev/null +++ b/src/base/string/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/base/Makeflags +SUBDIR_INCLUDES += diff --git a/src/base/string/cl_spushstring.h b/src/base/string/cl_spushstring.h new file mode 100644 index 0000000..5f2787b --- /dev/null +++ b/src/base/string/cl_spushstring.h @@ -0,0 +1,61 @@ +// Extendable strings. + +#ifndef _CL_SPUSHSTRING_H +#define _CL_SPUSHSTRING_H + +#include "cl_object.h" +#include "cl_malloc.h" +#include "cl_sstring.h" +#include "cl_abort.h" + +class cl_spushstring { +protected: + char * buffer; + uintL alloc; // allocated size of buffer + uintL index; // index into buffer, 0 <= index <= alloc +public: +// Constructor. When constructed, the string is empty. + cl_spushstring (); +// Destructor. + ~cl_spushstring (); +// Forget the contents. + void reset (); +// Add a character at the end. + void push (char); +// Adds several characters at the end at once. + void append (const char * ptr, uintL len); +// Get the contents as a string. Free it using cl_free_hook() when done. + char* contents (); +// Look at the contents. + uintL length () const; + char operator[] (uintL i) const; +}; +inline cl_spushstring::cl_spushstring () +{ + alloc = 20; // Must be > 0. + buffer = (char *) cl_malloc_hook(alloc); + index = 0; +} +inline cl_spushstring::~cl_spushstring () +{ + cl_free_hook(buffer); +} +inline void cl_spushstring::reset () +{ + index = 0; +} +inline char* cl_spushstring::contents () +{ + return cl_sstring(buffer,index); +} +inline uintL cl_spushstring::length () const +{ + return index; +} +inline char cl_spushstring::operator[] (uintL i) const +{ + if (!(i < index)) cl_abort(); + return buffer[i]; +} + +#endif /* _CL_SPUSHSTRING_H */ diff --git a/src/base/string/cl_spushstring_append.cc b/src/base/string/cl_spushstring_append.cc new file mode 100644 index 0000000..245d7a2 --- /dev/null +++ b/src/base/string/cl_spushstring_append.cc @@ -0,0 +1,28 @@ +// class cl_spushstring. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_spushstring.h" + + +// Implementation. + +#include // declares memcpy() + +void cl_spushstring::append (const char * ptr, uintL len) +{ + if (index + len > alloc) { + var uintL newalloc = index+2*len; + if (newalloc < 2*alloc) { newalloc = 2*alloc; } + var char* newbuffer = (char *) cl_malloc_hook(newalloc); + memcpy(newbuffer,buffer,alloc); + cl_free_hook(buffer); + buffer = newbuffer; + alloc = newalloc; + } + // Now index+len <= alloc. + for (uintL count = len; count > 0; count--) + buffer[index++] = *ptr++; +} diff --git a/src/base/string/cl_spushstring_push.cc b/src/base/string/cl_spushstring_push.cc new file mode 100644 index 0000000..29cb91f --- /dev/null +++ b/src/base/string/cl_spushstring_push.cc @@ -0,0 +1,26 @@ +// class cl_spushstring. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_spushstring.h" + + +// Implementation. + +#include // declares memcpy() + +void cl_spushstring::push (char c) +{ + if (index >= alloc) { + var uintL newalloc = 2*alloc; + var char* newbuffer = (char *) cl_malloc_hook(newalloc); + memcpy(newbuffer,buffer,alloc); + cl_free_hook(buffer); + buffer = newbuffer; + alloc = newalloc; + } + // Now index < alloc. + buffer[index++] = c; +} diff --git a/src/base/string/cl_sstring.cc b/src/base/string/cl_sstring.cc new file mode 100644 index 0000000..3e67af0 --- /dev/null +++ b/src/base/string/cl_sstring.cc @@ -0,0 +1,26 @@ +// cl_sstring(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sstring.h" + + +// Implementation. + +#include "cl_malloc.h" + +char * cl_sstring (const char * ptr, uintL len) +{ + var char * string = (char *) cl_malloc_hook(len+1); + { + var const char* ptr1 = ptr; + var char* ptr2 = string; + var uintL count; + for (count = len; count > 0; count--) + *ptr2++ = *ptr1++; + *ptr2++ = '\0'; + } + return string; +} diff --git a/src/base/string/cl_sstring.h b/src/base/string/cl_sstring.h new file mode 100644 index 0000000..433bb9e --- /dev/null +++ b/src/base/string/cl_sstring.h @@ -0,0 +1,10 @@ +// Simple strings. + +#ifndef _CL_SSTRING_H +#define _CL_SSTRING_H + +// Liefert einen String. +// Mit cl_malloc_hook() alloziert, mit cl_free_hook() freizugeben. +extern char * cl_sstring (const char * ptr, uintL len); + +#endif /* _CL_SSTRING_H */ diff --git a/src/base/string/cl_st_c2.cc b/src/base/string/cl_st_c2.cc new file mode 100644 index 0000000..163e66b --- /dev/null +++ b/src/base/string/cl_st_c2.cc @@ -0,0 +1,17 @@ +// constructor cl_string (const char * s). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_string.h" + + +// Implementation. + +extern cl_heap_string* cl_make_heap_string (const char * ptr, unsigned long len); + +cl_string::cl_string (const char * ptr, unsigned long len) +{ + pointer = cl_make_heap_string(ptr,len); +} diff --git a/src/base/string/cl_st_concat1.cc b/src/base/string/cl_st_concat1.cc new file mode 100644 index 0000000..56ea069 --- /dev/null +++ b/src/base/string/cl_st_concat1.cc @@ -0,0 +1,34 @@ +// cl_string concatenation. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_string.h" + + +// Implementation. + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_st_make0.cc" + +const cl_string operator+ (const cl_string& str1, const cl_string& str2) +{ + unsigned long len1 = strlen(str1); + unsigned long len2 = strlen(str2); + var cl_heap_string* str = cl_make_heap_string(len1+len2); + var char * ptr = &str->data[0]; + { + var const char * ptr1 = asciz(str1); + for (var unsigned long count = len1; count > 0; count--) + *ptr++ = *ptr1++; + } + { + var const char * ptr2 = asciz(str2); + for (var unsigned long count = len2; count > 0; count--) + *ptr++ = *ptr2++; + } + *ptr++ = '\0'; + return str; +} diff --git a/src/base/string/cl_st_concat2.cc b/src/base/string/cl_st_concat2.cc new file mode 100644 index 0000000..3a16604 --- /dev/null +++ b/src/base/string/cl_st_concat2.cc @@ -0,0 +1,34 @@ +// cl_string concatenation. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_string.h" + + +// Implementation. + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_st_make0.cc" + +const cl_string operator+ (const char* str1, const cl_string& str2) +{ + unsigned long len1 = strlen(str1); + unsigned long len2 = strlen(str2); + var cl_heap_string* str = cl_make_heap_string(len1+len2); + var char * ptr = &str->data[0]; + { + var const char * ptr1 = asciz(str1); + for (var unsigned long count = len1; count > 0; count--) + *ptr++ = *ptr1++; + } + { + var const char * ptr2 = asciz(str2); + for (var unsigned long count = len2; count > 0; count--) + *ptr++ = *ptr2++; + } + *ptr++ = '\0'; + return str; +} diff --git a/src/base/string/cl_st_concat3.cc b/src/base/string/cl_st_concat3.cc new file mode 100644 index 0000000..c2ce3b4 --- /dev/null +++ b/src/base/string/cl_st_concat3.cc @@ -0,0 +1,34 @@ +// cl_string concatenation. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_string.h" + + +// Implementation. + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_st_make0.cc" + +const cl_string operator+ (const cl_string& str1, const char* str2) +{ + unsigned long len1 = strlen(str1); + unsigned long len2 = strlen(str2); + var cl_heap_string* str = cl_make_heap_string(len1+len2); + var char * ptr = &str->data[0]; + { + var const char * ptr1 = asciz(str1); + for (var unsigned long count = len1; count > 0; count--) + *ptr++ = *ptr1++; + } + { + var const char * ptr2 = asciz(str2); + for (var unsigned long count = len2; count > 0; count--) + *ptr++ = *ptr2++; + } + *ptr++ = '\0'; + return str; +} diff --git a/src/base/string/cl_st_debug.cc b/src/base/string/cl_st_debug.cc new file mode 100644 index 0000000..5d37a60 --- /dev/null +++ b/src/base/string/cl_st_debug.cc @@ -0,0 +1,49 @@ +// cl_string debugging support. + +// General includes. +#include "cl_sysdep.h" + +// Specification. + + +// Implementation. + +#include "cl_string.h" +#include "cl_io.h" +#include + +static void dprint (cl_heap* pointer) +{ + var const cl_string& obj = *(const cl_string*)&pointer; + fprint(cl_debugout, "(cl_string) \""); + var unsigned long l = obj.length(); + for (var unsigned long i = 0; i < l; i++) { + var unsigned char c = obj[i]; + if (c >= 0x20) { + if (c == '"' || c == '\\') + fprintchar(cl_debugout, '\\'); + fprintchar(cl_debugout, c); + } else + switch (c) { + case '\n': fprint(cl_debugout, "\\n"); break; + case '\t': fprint(cl_debugout, "\\t"); break; + case '\b': fprint(cl_debugout, "\\b"); break; + case '\r': fprint(cl_debugout, "\\r"); break; + case '\f': fprint(cl_debugout, "\\f"); break; + case '\v': fprint(cl_debugout, "\\v"); break; + default: + static const char hexdigits[] = "0123456789abcdef"; + fprintchar(cl_debugout, '\\'); + fprintchar(cl_debugout, 'x'); + fprintchar(cl_debugout, hexdigits[(c>>4)&0x0f]); + fprintchar(cl_debugout, hexdigits[c&0x0f]); + break; + } + } + fprint(cl_debugout, "\""); +} +AT_INITIALIZATION(dprint_string) +{ cl_register_type_printer(cl_class_string,dprint); } + +// This dummy links in this module when requires it. +int cl_string_debug_module; diff --git a/src/base/string/cl_st_hashcode.cc b/src/base/string/cl_st_hashcode.cc new file mode 100644 index 0000000..61b23e1 --- /dev/null +++ b/src/base/string/cl_st_hashcode.cc @@ -0,0 +1,27 @@ +// cl_string hashcode(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_string.h" + + +// Implementation. + +unsigned long hashcode (const cl_string& str) +{ + var unsigned long code = 0x61284AF3; + // We walk through all characters. It may take some time for very + // long strings, but it's better than completely ignoring some characters. + var long len = str.length(); + var const char * ptr = str.asciz(); + for (; len > 0; len--) { + var unsigned char c = *ptr++; + code = (code << 5) | (code >> 27); // rotate left 5 bits + code += (long)c << 16; + code ^= (long)c; + code &= 0xFFFFFFFF; + } + return code; +} diff --git a/src/base/string/cl_st_make0.cc b/src/base/string/cl_st_make0.cc new file mode 100644 index 0000000..e0cd132 --- /dev/null +++ b/src/base/string/cl_st_make0.cc @@ -0,0 +1,23 @@ +// cl_make_heap_string(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_string.h" + + +// Implementation. + +#include "cl_malloc.h" +#include "cl_offsetof.h" + +MAYBE_INLINE +cl_heap_string* cl_make_heap_string (unsigned long len) +{ + var cl_heap_string* str = (cl_heap_string*) cl_malloc_hook(offsetofa(cl_heap_string,data)+sizeof(char)*(len+1)); + str->refcount = 1; + str->type = &cl_class_string; + str->length = len; + return str; /* Have to fill data[0..len] yourself. */ +} diff --git a/src/base/string/cl_st_make1.cc b/src/base/string/cl_st_make1.cc new file mode 100644 index 0000000..919aba3 --- /dev/null +++ b/src/base/string/cl_st_make1.cc @@ -0,0 +1,31 @@ +// cl_make_heap_string(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_string.h" + + +// Implementation. + +#include "cl_malloc.h" +#include "cl_offsetof.h" + +cl_heap_string* cl_make_heap_string (const char * s) +{ + var unsigned long len = strlen(s); + var cl_heap_string* str = (cl_heap_string*) cl_malloc_hook(offsetofa(cl_heap_string,data)+sizeof(char)*(len+1)); + str->refcount = 1; + str->type = &cl_class_string; + str->length = len; + { + var const char* ptr1 = s; + var char* ptr2 = &str->data[0]; + var uintL count; + for (count = len; count > 0; count--) + *ptr2++ = *ptr1++; + *ptr2++ = '\0'; + } + return str; +} diff --git a/src/base/string/cl_st_make2.cc b/src/base/string/cl_st_make2.cc new file mode 100644 index 0000000..dfcdea0 --- /dev/null +++ b/src/base/string/cl_st_make2.cc @@ -0,0 +1,30 @@ +// cl_make_heap_string(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_string.h" + + +// Implementation. + +#include "cl_malloc.h" +#include "cl_offsetof.h" + +cl_heap_string* cl_make_heap_string (const char * ptr, unsigned long len) +{ + var cl_heap_string* str = (cl_heap_string*) cl_malloc_hook(offsetofa(cl_heap_string,data)+sizeof(char)*(len+1)); + str->refcount = 1; + str->type = &cl_class_string; + str->length = len; + { + var const char* ptr1 = ptr; + var char* ptr2 = &str->data[0]; + var uintL count; + for (count = len; count > 0; count--) + *ptr2++ = *ptr1++; + *ptr2++ = '\0'; + } + return str; +} diff --git a/src/base/string/cl_st_null.cc b/src/base/string/cl_st_null.cc new file mode 100644 index 0000000..852ed64 --- /dev/null +++ b/src/base/string/cl_st_null.cc @@ -0,0 +1,17 @@ +// cl_null_string. + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_st_null) + +// Specification. +#include "cl_string.h" +extern const cl_string cl_null_string; + + +// Implementation. + +const cl_string cl_null_string = cl_string(NULL,0); + +CL_PROVIDE_END(cl_st_null) diff --git a/src/base/string/input/Makeflags b/src/base/string/input/Makeflags new file mode 100644 index 0000000..c1c9b6f --- /dev/null +++ b/src/base/string/input/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/base/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/base/string diff --git a/src/base/string/input/cl_st_get1.cc b/src/base/string/input/cl_st_get1.cc new file mode 100644 index 0000000..697a72f --- /dev/null +++ b/src/base/string/input/cl_st_get1.cc @@ -0,0 +1,39 @@ +// cl_fget(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_string.h" + + +// Implementation. + +#ifdef CL_IO_IOSTREAM + +#include "cl_io.h" +#include "cl_spushstring.h" + +#if ((defined(__sparc__) || defined(__rs6000__) || defined(__mips__)) && !defined(__GNUC__)) +// Sun C++ doesn't have istream::unget(). + #define unget() putback(c) +#endif + +const cl_string cl_fget (cl_istream stream, char delim) +{ + var cl_spushstring buffer; + // Handling of eofp is tricky: EOF is reached when (!stream.good()) || (stream.get()==EOF). + while (stream.good()) { + var int c = stream.get(); + if (c==EOF) + break; // ios::eofbit already set + if (c==delim) { + stream.unget(); + break; + } + buffer.push(c); + } + return buffer.contents(); +} + +#endif diff --git a/src/base/string/input/cl_st_get2.cc b/src/base/string/input/cl_st_get2.cc new file mode 100644 index 0000000..79d92c0 --- /dev/null +++ b/src/base/string/input/cl_st_get2.cc @@ -0,0 +1,49 @@ +// cl_fget(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_string.h" + + +// Implementation. + +#ifdef CL_IO_IOSTREAM + +#include "cl_io.h" +#include "cl_spushstring.h" + +#if ((defined(__sparc__) || defined(__rs6000__) || defined(__mips__)) && !defined(__GNUC__)) +// Sun C++ doesn't have istream::unget() and istream::set(). + #define unget() putback(c) + #define set(x) setf(x) +#endif + +const cl_string cl_fget (cl_istream stream, int n, char delim) +{ + var cl_spushstring buffer; + // Handling of eofp is tricky: EOF is reached when (!stream.good()) || (stream.get()==EOF). + while (stream.good()) { + var int c = stream.get(); + if (c==EOF) + break; // ios::eofbit already set + if (c==delim) { + stream.unget(); + break; + } + if (--n <= 0) { + stream.unget(); + #if defined(__GNUG__) && (__GNUC_MINOR__ < 8) + stream.set(ios::failbit); + #else // new ANSI C++ + stream.setstate(ios::failbit); + #endif + break; + } + buffer.push(c); + } + return buffer.contents(); +} + +#endif diff --git a/src/base/string/input/cl_st_getline1.cc b/src/base/string/input/cl_st_getline1.cc new file mode 100644 index 0000000..e3435c6 --- /dev/null +++ b/src/base/string/input/cl_st_getline1.cc @@ -0,0 +1,32 @@ +// cl_fgetline(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_string.h" + + +// Implementation. + +#ifdef CL_IO_IOSTREAM + +#include "cl_io.h" +#include "cl_spushstring.h" + +const cl_string cl_fgetline (cl_istream stream, char delim) +{ + var cl_spushstring buffer; + // Handling of eofp is tricky: EOF is reached when (!stream.good()) || (stream.get()==EOF). + while (stream.good()) { + var int c = stream.get(); + if (c==EOF) + break; // ios::eofbit already set + if (c==delim) + break; + buffer.push(c); + } + return buffer.contents(); +} + +#endif diff --git a/src/base/string/input/cl_st_getline2.cc b/src/base/string/input/cl_st_getline2.cc new file mode 100644 index 0000000..53397ae --- /dev/null +++ b/src/base/string/input/cl_st_getline2.cc @@ -0,0 +1,47 @@ +// cl_fgetline(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_string.h" + + +// Implementation. + +#ifdef CL_IO_IOSTREAM + +#include "cl_io.h" +#include "cl_spushstring.h" + +#if ((defined(__sparc__) || defined(__rs6000__) || defined(__mips__)) && !defined(__GNUC__)) +// Sun C++ doesn't have istream::unget() and istream::set(). + #define unget() putback(c) + #define set(x) setf(x) +#endif + +const cl_string cl_fgetline (cl_istream stream, int n, char delim) +{ + var cl_spushstring buffer; + // Handling of eofp is tricky: EOF is reached when (!stream.good()) || (stream.get()==EOF). + while (stream.good()) { + var int c = stream.get(); + if (c==EOF) + break; // ios::eofbit already set + if (c==delim) + break; + if (--n <= 0) { + stream.unget(); + #if defined(__GNUG__) && (__GNUC_MINOR__ < 8) + stream.set(ios::failbit); + #else // new ANSI C++ + stream.setstate(ios::failbit); + #endif + break; + } + buffer.push(c); + } + return buffer.contents(); +} + +#endif diff --git a/src/base/string/input/cl_st_gettoken.cc b/src/base/string/input/cl_st_gettoken.cc new file mode 100644 index 0000000..5213991 --- /dev/null +++ b/src/base/string/input/cl_st_gettoken.cc @@ -0,0 +1,65 @@ +// operator>>. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_string.h" + + +// Implementation. + +#ifdef CL_IO_IOSTREAM + +#include "cl_io.h" +#include "cl_spushstring.h" +#include + +#if ((defined(__sparc__) || defined(__rs6000__) || defined(__mips__)) && !defined(__GNUC__)) +// Sun C++ doesn't have istream::unget(). + #define unget() putback(c) +#endif + +cl_istream operator>> (cl_istream stream, cl_string& str) +{ + var cl_spushstring buffer; + var int n = stream.width(); + // Handling of eofp is tricky: EOF is reached when (!stream.good()) || (stream.get()==EOF). + int c; + // Skip whitespace. + while (stream.good()) { + c = stream.get(); + if (c==EOF) + break; + if (!isspace(c)) { + if (--n == 0) { + // stream.width()==1, means no characters. + stream.unget(); + break; + } + // If stream.width()==0, n gets negative and never 0. + goto nonws; + } + } + goto done; + // Read non-whitespace. + while (stream.good()) { + c = stream.get(); + if (c==EOF) + break; + if (isspace(c)) { + stream.unget(); + break; + } + nonws: + buffer.push(c); + if (--n == 0) + break; + } + done: + str = buffer.contents(); + stream.width(0); + return stream; +} + +#endif diff --git a/src/base/string/misc/Makeflags b/src/base/string/misc/Makeflags new file mode 100644 index 0000000..c329293 --- /dev/null +++ b/src/base/string/misc/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/base/Makeflags +SUBDIR_INCLUDES += diff --git a/src/base/string/misc/cl_st_class.cc b/src/base/string/misc/cl_st_class.cc new file mode 100644 index 0000000..b3bd01e --- /dev/null +++ b/src/base/string/misc/cl_st_class.cc @@ -0,0 +1,15 @@ +// cl_class_string. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_string.h" + + +// Implementation. + +cl_class cl_class_string = { + NULL, // empty destructor + 0 +}; diff --git a/src/base/string/output/Makeflags b/src/base/string/output/Makeflags new file mode 100644 index 0000000..c329293 --- /dev/null +++ b/src/base/string/output/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/base/Makeflags +SUBDIR_INCLUDES += diff --git a/src/base/string/output/cl_st_print.cc b/src/base/string/output/cl_st_print.cc new file mode 100644 index 0000000..8bbbf66 --- /dev/null +++ b/src/base/string/output/cl_st_print.cc @@ -0,0 +1,27 @@ +// fprint(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_string.h" + + +// Implementation. + +#include "cl_io.h" + +void fprint (cl_ostream stream, const cl_string& str) +{ +#if defined(CL_IO_STDIO) + var const char * ptr = str.asciz(); + var unsigned long i = str.length(); + while (i > 0) { + fprintchar(stream,*ptr); + ptr++; i--; + } +#endif +#if defined(CL_IO_IOSTREAM) + stream.write(str.asciz(),str.length()); +#endif +} diff --git a/src/base/symbol/Makeflags b/src/base/symbol/Makeflags new file mode 100644 index 0000000..49dde1c --- /dev/null +++ b/src/base/symbol/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/base/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/base/hash diff --git a/src/base/symbol/cl_sy_hashcode.cc b/src/base/symbol/cl_sy_hashcode.cc new file mode 100644 index 0000000..82579ec --- /dev/null +++ b/src/base/symbol/cl_sy_hashcode.cc @@ -0,0 +1,24 @@ +// cl_symbol hashcode(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_symbol.h" + + +// Implementation. + +#include "cl_offsetof.h" + +#define declare_alignof(where,type) \ + struct CONCAT(aligndummy,__LINE__) { char slot1; type slot2; }; \ + const unsigned long where = offsetof(CONCAT(aligndummy,__LINE__), slot2); + +unsigned long hashcode (const cl_symbol& s) +{ + // Strings don't move in memory, so we can just take the address. + declare_alignof(string_alignment,cl_heap_string); + return (unsigned long)(s.pointer) + / (string_alignment & -string_alignment); // divide by power of 2 +} diff --git a/src/base/symbol/cl_symbol.cc b/src/base/symbol/cl_symbol.cc new file mode 100644 index 0000000..dd007cd --- /dev/null +++ b/src/base/symbol/cl_symbol.cc @@ -0,0 +1,100 @@ +// class cl_symbol. + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_symbol) + +// Specification. +#include "cl_symbol.h" + + +// Implementation. + +#include "cl_hashuniqweak.h" + +inline const cl_string hashkey (const cl_symbol& sym) +{ + return (cl_string)sym; +} + +// A symbol points to a string, so to convert cl_string -> cl_symbol, we just +// take the pointer and put it into a cl_symbol. +inline cl_symbol::cl_symbol (struct hashuniq * null, const cl_string& s) + : cl_rcpointer (as_cl_private_thing(s)) { unused null; } + +typedef cl_htuniqentry cl_htentry_from_string_to_symbol; + +typedef cl_heap_weak_hashtable_uniq cl_heap_hashtable_from_string_to_symbol; + +typedef _cl_hashtable_iterator cl_hashtable_from_string_to_symbol_iterator; + +static void cl_hashtable_from_string_to_symbol_destructor (cl_heap* pointer) +{ +#if (defined(__mips__) || defined(__mips64__)) && !defined(__GNUC__) // workaround SGI CC bug + (*(cl_heap_hashtable_from_string_to_symbol*)pointer).~cl_heap_weak_hashtable_uniq(); +#else + (*(cl_heap_hashtable_from_string_to_symbol*)pointer).~cl_heap_hashtable_from_string_to_symbol(); +#endif +} + +cl_class cl_class_hashtable_from_string_to_symbol = { + cl_hashtable_from_string_to_symbol_destructor, + 0 +}; + +struct cl_ht_from_string_to_symbol : public cl_gcpointer { + // Constructors. + cl_ht_from_string_to_symbol (); + cl_ht_from_string_to_symbol (const cl_ht_from_string_to_symbol&); + // Assignment operators. + cl_ht_from_string_to_symbol& operator= (const cl_ht_from_string_to_symbol&); + // Iterator. + cl_hashtable_from_string_to_symbol_iterator iterator () const + { return ((cl_heap_hashtable_from_string_to_symbol*)pointer)->iterator(); } + // Lookup. + cl_symbol * get (const cl_string& s) const; + // Store. + void put (const cl_string& s) const; +}; + +// These are not inline, because they tend to duplicate a lot of template code. + +cl_ht_from_string_to_symbol::cl_ht_from_string_to_symbol () +{ + var cl_heap_hashtable_from_string_to_symbol* ht = new cl_heap_hashtable_from_string_to_symbol (); + ht->refcount = 1; + ht->type = &cl_class_hashtable_from_string_to_symbol; + pointer = ht; +} + +cl_symbol * cl_ht_from_string_to_symbol::get (const cl_string& s) const +{ + return ((cl_heap_hashtable_from_string_to_symbol*)pointer)->get(s); +} + +void cl_ht_from_string_to_symbol::put (const cl_string& s) const +{ + ((cl_heap_hashtable_from_string_to_symbol*)pointer)->put(s); +} + +// The global symbol table. +static cl_ht_from_string_to_symbol symbol_table; + +// Create or lookup a symbol from its name. +cl_symbol::cl_symbol (const cl_string& s) +{ + var cl_symbol * sym_in_table; + sym_in_table = symbol_table.get(s); + if (!sym_in_table) { + symbol_table.put(s); + sym_in_table = symbol_table.get(s); + if (!sym_in_table) + cl_abort(); + } + var cl_heap* p = sym_in_table->heappointer; + cl_inc_pointer_refcount(p); + pointer = p; +} + +CL_PROVIDE_END(cl_symbol) diff --git a/src/complex/Makeflags b/src/complex/Makeflags new file mode 100644 index 0000000..b536845 --- /dev/null +++ b/src/complex/Makeflags @@ -0,0 +1,3 @@ +# This file contains additional flags for the main Makefile. + +SUBDIR_INCLUDES = -I$(srcdir)/complex -I$(srcdir)/base diff --git a/src/complex/algebraic/Makeflags b/src/complex/algebraic/Makeflags new file mode 100644 index 0000000..efc1040 --- /dev/null +++ b/src/complex/algebraic/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/complex/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/real -I$(srcdir)/float/sfloat/elem -I$(srcdir)/float/sfloat -I$(srcdir)/float/ffloat/elem -I$(srcdir)/float/ffloat -I$(srcdir)/float/dfloat/elem -I$(srcdir)/float/dfloat -I$(srcdir)/float/lfloat/elem -I$(srcdir)/float/lfloat -I$(srcdir)/float -I$(srcdir)/rational -I$(srcdir)/integer -I$(srcdir)/base/digitseq -I$(srcdir)/base/digit -Ibase $(GMP_INCLUDES) diff --git a/src/complex/algebraic/cl_C_abs.cc b/src/complex/algebraic/cl_C_abs.cc new file mode 100644 index 0000000..03d2786 --- /dev/null +++ b/src/complex/algebraic/cl_C_abs.cc @@ -0,0 +1,31 @@ +// abs(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_C_abs_aux.cc" + +const cl_R abs (const cl_N& x) +{ +// Methode: +// Falls x reell: klar +// Falls x=a+bi: sqrt(a^2+b^2) + if (realp(x)) { + DeclareType(cl_R,x); + return abs(x); + } else { + DeclareType(cl_C,x); + return abs(x); + } +} diff --git a/src/complex/algebraic/cl_C_abs_aux.cc b/src/complex/algebraic/cl_C_abs_aux.cc new file mode 100644 index 0000000..98ba466 --- /dev/null +++ b/src/complex/algebraic/cl_C_abs_aux.cc @@ -0,0 +1,20 @@ +// abs(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_C.h" + + +// Implementation. + +#include "cl_real.h" + +MAYBE_INLINE +const cl_R abs (const cl_C& x) +{ + var const cl_R& a = realpart(x); + var const cl_R& b = imagpart(x); + return cl_hypot(a,b); +} diff --git a/src/complex/algebraic/cl_C_signum.cc b/src/complex/algebraic/cl_C_signum.cc new file mode 100644 index 0000000..0dcbed0 --- /dev/null +++ b/src/complex/algebraic/cl_C_signum.cc @@ -0,0 +1,34 @@ +// signum(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_C_abs_aux.cc" + +const cl_N signum (const cl_N& x) +{ +// Methode: +// x reell -> klar. +// x komplex -> falls (zerop x), x als Ergebnis, sonst (/ x (abs x)). + if (realp(x)) { + DeclareType(cl_R,x); + return signum(x); + } else { + DeclareType(cl_C,x); + if (zerop(x)) + return x; + else + return x / abs(x); + } +} diff --git a/src/complex/algebraic/cl_C_sqrt.cc b/src/complex/algebraic/cl_C_sqrt.cc new file mode 100644 index 0000000..4617382 --- /dev/null +++ b/src/complex/algebraic/cl_C_sqrt.cc @@ -0,0 +1,49 @@ +// sqrt(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" + +const cl_N sqrt (const cl_N& x) +{ +// Methode: +// x reell -> Für x>=0 klar, für x<0: sqrt(-x)*i. +// x=a+bi -> +// Bestimme r=abs(x)=sqrt(a*a+b*b). +// Falls a>=0: Setze c:=sqrt((r+a)/2), d:=(b/(2*c) falls c>0, c falls c=0). +// Falls a<0: Setze d:=sqrt((r-a)/2)*(1 falls b>=0, -1 falls b<0), c:=b/(2*d). +// Damit ist c>=0, 2*c*d=b, c*c=(r+a)/2, d*d=(r-a)/2, c*c-d*d=a, c*c+d*d=r, +// also c+di die gesuchte Wurzel. + if (realp(x)) { + DeclareType(cl_R,x); + if (!minusp(x)) + return sqrt(x); + else + return complex_C(0,sqrt(-x)); + } else { + DeclareType(cl_C,x); + var const cl_R& a = realpart(x); + var const cl_R& b = imagpart(x); + var cl_R r = cl_hypot(a,b); // r = (abs x) + if (!minusp(a)) { + // a>=0 + var cl_R c = sqrt((r+a)/2); + var cl_R d = (!zerop(c) ? b/(2*c) : c); + return complex_C(c,d); + } else { + var cl_R d = sqrt((r-a)/2); + if (minusp(b)) + d = -d; + var cl_R c = b/(2*d); + return complex_C(c,d); + } + } +} diff --git a/src/complex/algebraic/cl_DF_hypot.cc b/src/complex/algebraic/cl_DF_hypot.cc new file mode 100644 index 0000000..364aa34 --- /dev/null +++ b/src/complex/algebraic/cl_DF_hypot.cc @@ -0,0 +1,57 @@ +// cl_hypot(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_C.h" + + +// Implementation. + +#include "cl_dfloat.h" +#include "cl_DF.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_DF_minusp.cc" + +const cl_DF cl_hypot (const cl_DF& a, const cl_DF& b) +{ +// a=0.0 -> liefere abs(b). +// b=0.0 -> liefere abs(a). +// e:=max(exponent(a),exponent(b)). +// a':=a/2^e bzw. 0.0 bei Underflowmöglichkeit (beim Skalieren a':=a/2^e +// oder beim Quadrieren a'*a': 2*(e-exponent(a))>exp_mid-exp_low-1 +// d.h. exponent(b)-exponent(a)>floor((exp_mid-exp_low-1)/2) ). +// b':=b/2^e bzw. 0.0 bei Underflowmöglichkeit (beim Skalieren b':=b/2^e +// oder beim Quadrieren b'*b': 2*(e-exponent(b))>exp_mid-exp_low-1 +// d.h. exponent(a)-exponent(b)>floor((exp_mid-exp_low-1)/2) ). +// c':=a'*a'+b'*b', c':=sqrt(c'), liefere 2^e*c'. + var sintL a_exp; + var sintL b_exp; + { + // Exponenten von a holen: + var uintL uexp = DF_uexp(TheDfloat(a)->dfloat_value_semhi); + if (uexp == 0) + // a=0.0 -> liefere (abs b) : + return (minusp(b) ? -b : b); + a_exp = (sintL)(uexp - DF_exp_mid); + } + { + // Exponenten von b holen: + var uintL uexp = DF_uexp(TheDfloat(b)->dfloat_value_semhi); + if (uexp == 0) + // b=0.0 -> liefere (abs a) : + return (minusp(a) ? -a : a); + b_exp = (sintL)(uexp - DF_exp_mid); + } + // Nun a_exp = float_exponent(a), b_exp = float_exponent(b). + var sintL e = (a_exp > b_exp ? a_exp : b_exp); // Maximum der Exponenten + // a und b durch 2^e dividieren: + var cl_DF na = (b_exp-a_exp > floor(DF_exp_mid-DF_exp_low-1,2) ? cl_DF_0 : scale_float(a,-e)); + var cl_DF nb = (a_exp-b_exp > floor(DF_exp_mid-DF_exp_low-1,2) ? cl_DF_0 : scale_float(b,-e)); + // c' := a'*a'+b'*b' berechnen: + var cl_DF nc = square(na) + square(nb); + return scale_float(sqrt(nc),e); // c' := sqrt(c'), 2^e*c' +} diff --git a/src/complex/algebraic/cl_FF_hypot.cc b/src/complex/algebraic/cl_FF_hypot.cc new file mode 100644 index 0000000..5f3f9bf --- /dev/null +++ b/src/complex/algebraic/cl_FF_hypot.cc @@ -0,0 +1,57 @@ +// cl_hypot(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_C.h" + + +// Implementation. + +#include "cl_ffloat.h" +#include "cl_FF.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_FF_minusp.cc" + +const cl_FF cl_hypot (const cl_FF& a, const cl_FF& b) +{ +// a=0.0 -> liefere abs(b). +// b=0.0 -> liefere abs(a). +// e:=max(exponent(a),exponent(b)). +// a':=a/2^e bzw. 0.0 bei Underflowmöglichkeit (beim Skalieren a':=a/2^e +// oder beim Quadrieren a'*a': 2*(e-exponent(a))>exp_mid-exp_low-1 +// d.h. exponent(b)-exponent(a)>floor((exp_mid-exp_low-1)/2) ). +// b':=b/2^e bzw. 0.0 bei Underflowmöglichkeit (beim Skalieren b':=b/2^e +// oder beim Quadrieren b'*b': 2*(e-exponent(b))>exp_mid-exp_low-1 +// d.h. exponent(a)-exponent(b)>floor((exp_mid-exp_low-1)/2) ). +// c':=a'*a'+b'*b', c':=sqrt(c'), liefere 2^e*c'. + var sintL a_exp; + var sintL b_exp; + { + // Exponenten von a holen: + var uintL uexp = FF_uexp(cl_ffloat_value(a)); + if (uexp == 0) + // a=0.0 -> liefere (abs b) : + return (minusp(b) ? -b : b); + a_exp = (sintL)(uexp - FF_exp_mid); + } + { + // Exponenten von b holen: + var uintL uexp = FF_uexp(cl_ffloat_value(b)); + if (uexp == 0) + // b=0.0 -> liefere (abs a) : + return (minusp(a) ? -a : a); + b_exp = (sintL)(uexp - FF_exp_mid); + } + // Nun a_exp = float_exponent(a), b_exp = float_exponent(b). + var sintL e = (a_exp > b_exp ? a_exp : b_exp); // Maximum der Exponenten + // a und b durch 2^e dividieren: + var cl_FF na = (b_exp-a_exp > floor(FF_exp_mid-FF_exp_low-1,2) ? cl_FF_0 : scale_float(a,-e)); + var cl_FF nb = (a_exp-b_exp > floor(FF_exp_mid-FF_exp_low-1,2) ? cl_FF_0 : scale_float(b,-e)); + // c' := a'*a'+b'*b' berechnen: + var cl_FF nc = square(na) + square(nb); + return scale_float(sqrt(nc),e); // c' := sqrt(c'), 2^e*c' +} diff --git a/src/complex/algebraic/cl_LF_hypot.cc b/src/complex/algebraic/cl_LF_hypot.cc new file mode 100644 index 0000000..5455b3e --- /dev/null +++ b/src/complex/algebraic/cl_LF_hypot.cc @@ -0,0 +1,73 @@ +// cl_hypot(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_C.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_LF.h" +#include "cl_LF_impl.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_LF_minusp.cc" + +ALL_cl_LF_OPERATIONS_SAME_PRECISION() + +const cl_LF cl_hypot (const cl_LF& a, const cl_LF& b) +{ +// Zuerst a und b auf gleiche Länge bringen: den längeren runden. +// a=0.0 -> liefere abs(b). +// b=0.0 -> liefere abs(a). +// e:=max(exponent(a),exponent(b)). +// a':=a/2^e bzw. 0.0 bei Underflowmöglichkeit (beim Skalieren a':=a/2^e +// oder beim Quadrieren a'*a': 2*(e-exponent(a))>exp_mid-exp_low-1 +// d.h. exponent(b)-exponent(a)>floor((exp_mid-exp_low-1)/2) ). +// b':=b/2^e bzw. 0.0 bei Underflowmöglichkeit (beim Skalieren b':=b/2^e +// oder beim Quadrieren b'*b': 2*(e-exponent(b))>exp_mid-exp_low-1 +// d.h. exponent(a)-exponent(b)>floor((exp_mid-exp_low-1)/2) ). +// c':=a'*a'+b'*b', c':=sqrt(c'), liefere 2^e*c'. + { Mutable(cl_LF,a); + Mutable(cl_LF,b); + { + var uintC a_len = TheLfloat(a)->len; + var uintC b_len = TheLfloat(b)->len; + if (!(a_len == b_len)) { + if (a_len < b_len) + b = shorten(b,a_len); + else + a = shorten(a,b_len); + } + } + var sintL a_exp; + var sintL b_exp; + { + // Exponenten von a holen: + var uintL uexp = TheLfloat(a)->expo; + if (uexp == 0) + // a=0.0 -> liefere (abs b) : + return (minusp(b) ? -b : b); + a_exp = (sintL)(uexp - LF_exp_mid); + } + { + // Exponenten von b holen: + var uintL uexp = TheLfloat(b)->expo; + if (uexp == 0) + // b=0.0 -> liefere (abs a) : + return (minusp(a) ? -a : a); + b_exp = (sintL)(uexp - LF_exp_mid); + } + // Nun a_exp = float_exponent(a), b_exp = float_exponent(b). + var sintL e = (a_exp > b_exp ? a_exp : b_exp); // Maximum der Exponenten + // a und b durch 2^e dividieren: + var cl_LF na = ((b_exp > a_exp) && ((uintL)(b_exp-a_exp) > (uintL)floor(LF_exp_mid-LF_exp_low-1,2)) ? encode_LF0(TheLfloat(a)->len) : scale_float(a,-e)); + var cl_LF nb = ((a_exp > b_exp) && ((uintL)(a_exp-b_exp) > (uintL)floor(LF_exp_mid-LF_exp_low-1,2)) ? encode_LF0(TheLfloat(b)->len) : scale_float(b,-e)); + // c' := a'*a'+b'*b' berechnen: + var cl_LF nc = square(na) + square(nb); + return scale_float(sqrt(nc),e); // c' := sqrt(c'), 2^e*c' +}} diff --git a/src/complex/algebraic/cl_R_hypot.cc b/src/complex/algebraic/cl_R_hypot.cc new file mode 100644 index 0000000..aeea356 --- /dev/null +++ b/src/complex/algebraic/cl_R_hypot.cc @@ -0,0 +1,88 @@ +// cl_hypot(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_C.h" + + +// Implementation. + +#include "cl_real.h" +#include "cl_R.h" +#include "cl_rational.h" +#include "cl_RA.h" +#include "cl_F.h" +#include "cl_SF.h" +#include "cl_FF.h" +#include "cl_DF.h" +#include "cl_LF.h" + +const cl_R cl_hypot (const cl_R& a, const cl_R& b) +{ +// Methode: +// Falls a=0: (abs b). +// Falls b=0: (abs a). +// Falls a und b beide rational sind: +// c:=a*a+b*b, liefere (sqrt c). +// Falls a oder b Floats sind: +// Falls einer von beiden rational ist, runde ihn zum selben Float-Typ +// wie der andere und führe das UP durch. +// Falls beide Floats sind, erweitere auf den genaueren, führe das UP +// durch und runde wieder auf den ungenaueren. +// Das Ergebnis ist ein Float >=0. +// UP: [a,b Floats vom selben Typ] +// a=0.0 -> liefere abs(b). +// b=0.0 -> liefere abs(a). +// e:=max(exponent(a),exponent(b)). +// a':=a/2^e bzw. 0.0 bei Underflowmöglichkeit (beim Skalieren a':=a/2^e +// oder beim Quadrieren a'*a': 2*(e-exponent(a))>exp_mid-exp_low-1 +// d.h. exponent(b)-exponent(a)>floor((exp_mid-exp_low-1)/2) ). +// b':=b/2^e bzw. 0.0 bei Underflowmöglichkeit (beim Skalieren b':=b/2^e +// oder beim Quadrieren b'*b': 2*(e-exponent(b))>exp_mid-exp_low-1 +// d.h. exponent(a)-exponent(b)>floor((exp_mid-exp_low-1)/2) ). +// c':=a'*a'+b'*b', c':=sqrt(c'), liefere 2^e*c'. + + if (rationalp(a)) { + DeclareType(cl_RA,a); + if (eq(a,0)) // a=0 -> (abs b) + return abs(b); + if (rationalp(b)) { + DeclareType(cl_RA,b); + // a,b beide rational + return sqrt(square(a)+square(b)); + } else { + DeclareType(cl_F,b); + // a rational, b Float + floatcase(b + , return cl_hypot(cl_RA_to_SF(a),b); + , return cl_hypot(cl_RA_to_FF(a),b); + , return cl_hypot(cl_RA_to_DF(a),b); + , return cl_hypot(cl_RA_to_LF(a,TheLfloat(b)->len),b); + ); + } + } else { + DeclareType(cl_F,a); + if (rationalp(b)) { + DeclareType(cl_RA,b); + // a Float, b rational + if (eq(b,0)) // b=0 -> (abs a) + return abs(a); + floatcase(a + , return cl_hypot(a,cl_RA_to_SF(b)); + , return cl_hypot(a,cl_RA_to_FF(b)); + , return cl_hypot(a,cl_RA_to_DF(b)); + , return cl_hypot(a,cl_RA_to_LF(b,TheLfloat(a)->len)); + ); + } else { + DeclareType(cl_F,b); + // a,b Floats + #ifndef CL_LF_PEDANTIC + GEN_F_OP2(a,b, cl_hypot, 1, 1, return); + #else + GEN_F_OP2(a,b, cl_hypot, 1, 0, return); + #endif + } + } +} diff --git a/src/complex/algebraic/cl_SF_hypot.cc b/src/complex/algebraic/cl_SF_hypot.cc new file mode 100644 index 0000000..b74ab4b --- /dev/null +++ b/src/complex/algebraic/cl_SF_hypot.cc @@ -0,0 +1,57 @@ +// cl_hypot(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_C.h" + + +// Implementation. + +#include "cl_sfloat.h" +#include "cl_SF.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_SF_minusp.cc" + +const cl_SF cl_hypot (const cl_SF& a, const cl_SF& b) +{ +// a=0.0 -> liefere abs(b). +// b=0.0 -> liefere abs(a). +// e:=max(exponent(a),exponent(b)). +// a':=a/2^e bzw. 0.0 bei Underflowmöglichkeit (beim Skalieren a':=a/2^e +// oder beim Quadrieren a'*a': 2*(e-exponent(a))>exp_mid-exp_low-1 +// d.h. exponent(b)-exponent(a)>floor((exp_mid-exp_low-1)/2) ). +// b':=b/2^e bzw. 0.0 bei Underflowmöglichkeit (beim Skalieren b':=b/2^e +// oder beim Quadrieren b'*b': 2*(e-exponent(b))>exp_mid-exp_low-1 +// d.h. exponent(a)-exponent(b)>floor((exp_mid-exp_low-1)/2) ). +// c':=a'*a'+b'*b', c':=sqrt(c'), liefere 2^e*c'. + var sintL a_exp; + var sintL b_exp; + { + // Exponenten von a holen: + var uintL uexp = SF_uexp(a); + if (uexp == 0) + // a=0.0 -> liefere (abs b) : + return (minusp(b) ? -b : b); + a_exp = (sintL)(uexp - SF_exp_mid); + } + { + // Exponenten von b holen: + var uintL uexp = SF_uexp(b); + if (uexp == 0) + // b=0.0 -> liefere (abs a) : + return (minusp(a) ? -a : a); + b_exp = (sintL)(uexp - SF_exp_mid); + } + // Nun a_exp = float_exponent(a), b_exp = float_exponent(b). + var sintL e = (a_exp > b_exp ? a_exp : b_exp); // Maximum der Exponenten + // a und b durch 2^e dividieren: + var cl_SF na = (b_exp-a_exp > floor(SF_exp_mid-SF_exp_low-1,2) ? SF_0 : scale_float(a,-e)); + var cl_SF nb = (a_exp-b_exp > floor(SF_exp_mid-SF_exp_low-1,2) ? SF_0 : scale_float(b,-e)); + // c' := a'*a'+b'*b' berechnen: + var cl_SF nc = square(na) + square(nb); + return scale_float(sqrt(nc),e); // c' := sqrt(c'), 2^e*c' +} diff --git a/src/complex/cl_C.h b/src/complex/cl_C.h new file mode 100644 index 0000000..f3c22be --- /dev/null +++ b/src/complex/cl_C.h @@ -0,0 +1,190 @@ +// cl_C internals + +#ifndef _CL_C_H +#define _CL_C_H + +#include "cl_number.h" +#include "cl_complex.h" +#include "cl_sfloat_class.h" +#include "cl_ffloat_class.h" +#include "cl_dfloat_class.h" +#include "cl_lfloat_class.h" +#include "cl_macros.h" +#include "cl_malloc.h" + +struct cl_heap_complex : cl_heap { + cl_R realpart; + cl_R imagpart; +}; + +inline cl_heap_complex* TheComplex (cl_heap_complex* p) + { return p; } +inline cl_heap_complex* TheComplex (const cl_number& obj) + { return (cl_heap_complex*)(obj.pointer); } + +inline cl_heap_complex* allocate_complex (const cl_R& real, const cl_R& imag) +{ + cl_heap_complex* p = (cl_heap_complex*) cl_malloc_hook(sizeof(cl_heap_complex)); + p->refcount = 1; + p->type = &cl_class_complex; + p->realpart.pointer = real.pointer; cl_inc_refcount(real); + p->imagpart.pointer = imag.pointer; cl_inc_refcount(imag); + return p; +} + +// Private constructor. +// ptr should be the result of some allocate_complex() call. +inline cl_N::cl_N (cl_heap_complex* ptr) + : cl_number ((cl_private_thing) ptr) {} + +// Both work, but the first definition results in less compiler-generated +// temporaries. +#if 1 + #define Complex cl_heap_complex* +#else + #define Complex cl_N +#endif + +// Type tests +inline cl_boolean realp (const cl_N& x) +{ + if (x.pointer_p()) + if (x.heappointer->type == &cl_class_complex) + return cl_false; + return cl_true; +} +inline cl_boolean complexp (const cl_N& x) +{ + if (x.pointer_p()) + if (x.heappointer->type == &cl_class_complex) + return cl_true; + return cl_false; +} + +// Comparison with a fixnum. +inline cl_boolean eq (const cl_N& x, sint32 y) +{ + return (cl_boolean)(x.word == cl_combine(cl_FN_tag,y)); +} + +inline cl_boolean exact_zerop (const cl_N& x) +{ + return eq(x,0); +} + + +// A complex (cl_C) is a number which is not a real number (cl_R). + +// typedef +class cl_C : public cl_N { +public: +}; + +inline cl_boolean realp (const cl_C& x) + { unused x; return cl_false; } +inline cl_boolean complexp (const cl_C& x) + { unused x; return cl_true; } + + +// Liefert zu reellen Zahlen a und b /= Fixnum 0 die komplexe Zahl a+bi. +// complex_C(a,b) +extern const cl_N complex_C (const cl_R& a, const cl_R& b); + +// realpart(x) liefert den Realteil der Zahl x. +// imagpart(x) liefert den Imaginärteil der Zahl x. +inline const cl_R& realpart (const cl_C& x) +{ + return TheComplex(x)->realpart; +} +inline const cl_R& imagpart (const cl_C& x) +{ + return TheComplex(x)->imagpart; +} + + +// Primitive forms of complex numbers with restricted part type. + +// typedef +struct cl_C_SF { + cl_SF realpart; + cl_SF imagpart; + cl_C_SF (const cl_SF& re, const cl_SF& im) : realpart(re), imagpart(im) {} +}; +inline const cl_N complex_C (const cl_C_SF& c) + { return complex_C(c.realpart,c.imagpart); } + +// typedef +struct cl_C_FF { + cl_FF realpart; + cl_FF imagpart; + cl_C_FF (const cl_FF& re, const cl_FF& im) : realpart(re), imagpart(im) {} +}; +inline const cl_N complex_C (const cl_C_FF& c) + { return complex_C(c.realpart,c.imagpart); } + +// typedef +struct cl_C_DF { + cl_DF realpart; + cl_DF imagpart; + cl_C_DF (const cl_DF& re, const cl_DF& im) : realpart(re), imagpart(im) {} +}; +inline const cl_N complex_C (const cl_C_DF& c) + { return complex_C(c.realpart,c.imagpart); } + +// typedef +struct cl_C_LF { + cl_LF realpart; + cl_LF imagpart; + cl_C_LF (const cl_LF& re, const cl_LF& im) : realpart(re), imagpart(im) {} +}; +inline const cl_N complex_C (const cl_C_LF& c) + { return complex_C(c.realpart,c.imagpart); } + +// cl_C_recip(a,b) liefert 1/(a+bi), wo a und b Short-Floats sind. +extern const cl_C_SF cl_C_recip (const cl_SF& a, const cl_SF& b); + +// cl_C_recip(a,b) liefert 1/(a+bi), wo a und b Single-Floats sind. +extern const cl_C_FF cl_C_recip (const cl_FF& a, const cl_FF& b); + +// cl_C_recip(a,b) liefert 1/(a+bi), wo a und b Double-Floats sind. +extern const cl_C_DF cl_C_recip (const cl_DF& a, const cl_DF& b); + +// cl_C_recip(a,b) liefert 1/(a+bi), wo a und b gleichlange Long-Floats sind. +extern const cl_C_LF cl_C_recip (const cl_LF& a, const cl_LF& b); + + +// cl_C_hypot(a,b) liefert abs(a+bi), wo a und b Short-Floats sind. +extern const cl_SF cl_hypot (const cl_SF& a, const cl_SF& b); + +// cl_C_hypot(a,b) liefert abs(a+bi), wo a und b Single-Floats sind. +extern const cl_FF cl_hypot (const cl_FF& a, const cl_FF& b); + +// cl_C_hypot(a,b) liefert abs(a+bi), wo a und b Double-Floats sind. +extern const cl_DF cl_hypot (const cl_DF& a, const cl_DF& b); + +// cl_C_hypot(a,b) liefert abs(a+bi), wo a und b gleichlange Long-Floats sind. +extern const cl_LF cl_hypot (const cl_LF& a, const cl_LF& b); + +// cl_C_hypot(a,b) liefert abs(a+bi), wo a und b reelle Zahlen sind. +extern const cl_R cl_hypot (const cl_R& a, const cl_R& b); + +// Liefert (abs x), wo x eine nicht-reelle Zahl ist. +extern const cl_R abs (const cl_C& x); + + +// typedef +struct cl_C_R { + cl_R realpart; + cl_R imagpart; + cl_C_R () : realpart(0), imagpart(0) {} + cl_C_R (const cl_R& re, const cl_R& im) : realpart(re), imagpart(im) {} +}; + +// Hilfsfunktion für atanh und atan: u+iv := artanh(x+iy). Liefert cl_C_R(u,v). +extern const cl_C_R atanh (const cl_R& x, const cl_R& y); + +// Hilfsfunktion für asinh und asin: u+iv := arsinh(x+iy). Liefert cl_C_R(u,v). +extern const cl_C_R asinh (const cl_R& x, const cl_R& y); + + +#endif /* _CL_C_H */ diff --git a/src/complex/elem/Makeflags b/src/complex/elem/Makeflags new file mode 100644 index 0000000..6530f93 --- /dev/null +++ b/src/complex/elem/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/complex/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/real diff --git a/src/complex/elem/cl_C_equal.cc b/src/complex/elem/cl_C_equal.cc new file mode 100644 index 0000000..e3315e9 --- /dev/null +++ b/src/complex/elem/cl_C_equal.cc @@ -0,0 +1,53 @@ +// cl_equal(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" + +cl_boolean cl_equal (const cl_N& x, const cl_N& y) +{ +// Methode: +// Falls beide reell, klar. +// Falls x reell, y komplex: (= x (realpart y)) und (zerop (imagpart y)). +// Falls x komplex, y reell: analog +// Falls beide komplex: Realteile und Imaginärteile jeweils gleich? + if (realp(x)) { + DeclareType(cl_R,x); + if (realp(y)) { + DeclareType(cl_R,y); + // x,y beide reell + return cl_equal(x,y); + } else { + DeclareType(cl_C,y); + // x reell, y komplex + if (!zerop(imagpart(y))) + return cl_false; + return cl_equal(x,realpart(y)); + } + } else { + DeclareType(cl_C,x); + if (realp(y)) { + DeclareType(cl_R,y); + // x komplex, y reell + if (!zerop(imagpart(x))) + return cl_false; + return cl_equal(realpart(x),y); + } else { + DeclareType(cl_C,y); + // x,y beide komplex + if (!cl_equal(realpart(x),realpart(y))) + return cl_false; + if (!cl_equal(imagpart(x),imagpart(y))) + return cl_false; + return cl_true; + } + } +} diff --git a/src/complex/elem/cl_C_from_R_R_complex.cc b/src/complex/elem/cl_C_from_R_R_complex.cc new file mode 100644 index 0000000..57ed3a6 --- /dev/null +++ b/src/complex/elem/cl_C_from_R_R_complex.cc @@ -0,0 +1,15 @@ +// complex_C(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_C.h" + + +// Implementation. + +const cl_N complex_C (const cl_R& a, const cl_R& b) +{ + return allocate_complex(a,b); +} diff --git a/src/complex/elem/cl_C_from_R_R_complex1.cc b/src/complex/elem/cl_C_from_R_R_complex1.cc new file mode 100644 index 0000000..a365f18 --- /dev/null +++ b/src/complex/elem/cl_C_from_R_R_complex1.cc @@ -0,0 +1,22 @@ +// complex(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_C.h" + + +// Implementation. + +#include "cl_R.h" + +const cl_N complex (const cl_R& a, const cl_R& b) +{ +// Methode: +// Falls b=0, nur a. sonst komplexe Zahl erzeugen. + if (eq(b,0)) + return a; + else + return allocate_complex(a,b); +} diff --git a/src/complex/elem/cl_C_imagpart.cc b/src/complex/elem/cl_C_imagpart.cc new file mode 100644 index 0000000..37eb61f --- /dev/null +++ b/src/complex/elem/cl_C_imagpart.cc @@ -0,0 +1,22 @@ +// imagpart(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" + +const cl_R imagpart (const cl_N& x) +{ + if (realp(x)) + return 0; + else { + DeclareType(cl_C,x); + return imagpart(x); + } +} diff --git a/src/complex/elem/cl_C_minus.cc b/src/complex/elem/cl_C_minus.cc new file mode 100644 index 0000000..79514de --- /dev/null +++ b/src/complex/elem/cl_C_minus.cc @@ -0,0 +1,54 @@ +// binary operator - + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" + +const cl_N operator- (const cl_N& x, const cl_N& y) +{ +// Methode: +// x,y beide reell -> klar. +// x=a, y=b+ci -> (a-b)+(-c)i +// x=a+bi, y=c -> (a-c)+bi +// x=a+bi, y=c+di -> (a-c)+(b-d)i + if (realp(x)) { + DeclareType(cl_R,x); + if (realp(y)) { + DeclareType(cl_R,y); + return x-y; + } else { + DeclareType(cl_C,y); + // x=a, y=b+ci + var const cl_R& a = x; + var const cl_R& b = realpart(y); + var const cl_R& c = imagpart(y); + return complex_C(a-b,-c); + } + } else { + DeclareType(cl_C,x); + if (realp(y)) { + DeclareType(cl_R,y); + // x=a+bi, y=c + var const cl_R& a = realpart(x); + var const cl_R& b = imagpart(x); + var const cl_R& c = y; + return complex_C(a-c,b); + } else { + DeclareType(cl_C,y); + // x=a+bi, y=c+di + var const cl_R& a = realpart(x); + var const cl_R& b = imagpart(x); + var const cl_R& c = realpart(y); + var const cl_R& d = imagpart(y); + return complex(a-c,b-d); + } + } +} diff --git a/src/complex/elem/cl_C_minus1.cc b/src/complex/elem/cl_C_minus1.cc new file mode 100644 index 0000000..7469dbd --- /dev/null +++ b/src/complex/elem/cl_C_minus1.cc @@ -0,0 +1,29 @@ +// minus1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" + +const cl_N minus1 (const cl_N& x) +{ +// Methode: +// x reell -> klar. +// x=a+bi -> (a-1)+bi + if (realp(x)) { + DeclareType(cl_R,x); + return minus1(x); + } else { + DeclareType(cl_C,x); + var const cl_R& a = realpart(x); + var const cl_R& b = imagpart(x); + return complex_C(minus1(a),b); + } +} diff --git a/src/complex/elem/cl_C_mul.cc b/src/complex/elem/cl_C_mul.cc new file mode 100644 index 0000000..d75d158 --- /dev/null +++ b/src/complex/elem/cl_C_mul.cc @@ -0,0 +1,54 @@ +// binary operator * + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" + +const cl_N operator* (const cl_N& x, const cl_N& y) +{ +// Methode: +// x,y beide reell -> klar. +// x=a, y=b+ci -> (a*b)+(a*c)i +// x=a+bi, y=c -> (a*c)+(b*c)i +// x=a+bi, y=c+di -> (a*c-b*d)+(a*d+b*c)i + if (realp(x)) { + DeclareType(cl_R,x); + if (realp(y)) { + DeclareType(cl_R,y); + return x*y; + } else { + DeclareType(cl_C,y); + // x=a, y=b+ci + var const cl_R& a = x; + var const cl_R& b = realpart(y); + var const cl_R& c = imagpart(y); + return complex(a*b,a*c); + } + } else { + DeclareType(cl_C,x); + if (realp(y)) { + DeclareType(cl_R,y); + // x=a+bi, y=c + var const cl_R& a = realpart(x); + var const cl_R& b = imagpart(x); + var const cl_R& c = y; + return complex(a*c,b*c); + } else { + DeclareType(cl_C,y); + // x=a+bi, y=c+di + var const cl_R& a = realpart(x); + var const cl_R& b = imagpart(x); + var const cl_R& c = realpart(y); + var const cl_R& d = imagpart(y); + return complex(a*c-b*d,a*d+b*c); + } + } +} diff --git a/src/complex/elem/cl_C_plus.cc b/src/complex/elem/cl_C_plus.cc new file mode 100644 index 0000000..2a042bb --- /dev/null +++ b/src/complex/elem/cl_C_plus.cc @@ -0,0 +1,54 @@ +// binary operator + + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" + +const cl_N operator+ (const cl_N& x, const cl_N& y) +{ +// Methode: +// x,y beide reell -> klar. +// x=a, y=b+ci -> (a+b)+ci +// x=a+bi, y=c -> (a+c)+bi +// x=a+bi, y=c+di -> (a+c)+(b+d)i + if (realp(x)) { + DeclareType(cl_R,x); + if (realp(y)) { + DeclareType(cl_R,y); + return x+y; + } else { + DeclareType(cl_C,y); + // x=a, y=b+ci + var const cl_R& a = x; + var const cl_R& b = realpart(y); + var const cl_R& c = imagpart(y); + return complex_C(a+b,c); + } + } else { + DeclareType(cl_C,x); + if (realp(y)) { + DeclareType(cl_R,y); + // x=a+bi, y=c + var const cl_R& a = realpart(x); + var const cl_R& b = imagpart(x); + var const cl_R& c = y; + return complex_C(a+c,b); + } else { + DeclareType(cl_C,y); + // x=a+bi, y=c+di + var const cl_R& a = realpart(x); + var const cl_R& b = imagpart(x); + var const cl_R& c = realpart(y); + var const cl_R& d = imagpart(y); + return complex(a+c,b+d); + } + } +} diff --git a/src/complex/elem/cl_C_plus1.cc b/src/complex/elem/cl_C_plus1.cc new file mode 100644 index 0000000..6e1515e --- /dev/null +++ b/src/complex/elem/cl_C_plus1.cc @@ -0,0 +1,29 @@ +// plus1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" + +const cl_N plus1 (const cl_N& x) +{ +// Methode: +// x reell -> klar. +// x=a+bi -> (a+1)+bi + if (realp(x)) { + DeclareType(cl_R,x); + return plus1(x); + } else { + DeclareType(cl_C,x); + var const cl_R& a = realpart(x); + var const cl_R& b = imagpart(x); + return complex_C(plus1(a),b); + } +} diff --git a/src/complex/elem/cl_C_realpart.cc b/src/complex/elem/cl_C_realpart.cc new file mode 100644 index 0000000..da59cc4 --- /dev/null +++ b/src/complex/elem/cl_C_realpart.cc @@ -0,0 +1,23 @@ +// realpart(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" + +const cl_R realpart (const cl_N& x) +{ + if (realp(x)) { + DeclareType(cl_R,x); + return x; + } else { + DeclareType(cl_C,x); + return realpart(x); + } +} diff --git a/src/complex/elem/cl_C_square.cc b/src/complex/elem/cl_C_square.cc new file mode 100644 index 0000000..b9fac76 --- /dev/null +++ b/src/complex/elem/cl_C_square.cc @@ -0,0 +1,29 @@ +// square(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" + +const cl_N square (const cl_N& x) +{ +// Methode: +// x reell -> klar. +// x=a+bi -> (a^2-b^2)+(2*a*b)i + if (realp(x)) { + DeclareType(cl_R,x); + return square(x); + } else { + DeclareType(cl_C,x); + var const cl_R& a = realpart(x); + var const cl_R& b = imagpart(x); + return complex_C(square(a)-square(b),2*a*b); + } +} diff --git a/src/complex/elem/cl_C_uminus.cc b/src/complex/elem/cl_C_uminus.cc new file mode 100644 index 0000000..417b171 --- /dev/null +++ b/src/complex/elem/cl_C_uminus.cc @@ -0,0 +1,29 @@ +// unary operator - + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" + +const cl_N operator- (const cl_N& x) +{ +// Methode: +// x reell -> klar. +// x=a+bi -> (-a) + (-b) i + if (realp(x)) { + DeclareType(cl_R,x); + return -x; + } else { + DeclareType(cl_C,x); + var const cl_R& a = realpart(x); + var const cl_R& b = imagpart(x); + return complex_C(-a,-b); + } +} diff --git a/src/complex/elem/cl_C_zerop.cc b/src/complex/elem/cl_C_zerop.cc new file mode 100644 index 0000000..cbb916a --- /dev/null +++ b/src/complex/elem/cl_C_zerop.cc @@ -0,0 +1,30 @@ +// zerop(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" + +cl_boolean zerop (const cl_N& x) +{ + if (realp(x)) { + DeclareType(cl_R,x); + return zerop(x); + } else { + DeclareType(cl_C,x); + // x komplex, teste ob Real- und Imaginärteil beide = 0 sind. + var const cl_R& a = realpart(x); + var const cl_R& b = imagpart(x); + if (zerop(a)) + if (zerop(b)) + return cl_true; + return cl_false; + } +} diff --git a/src/complex/elem/division/Makeflags b/src/complex/elem/division/Makeflags new file mode 100644 index 0000000..4b1e364 --- /dev/null +++ b/src/complex/elem/division/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/complex/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/real -I$(srcdir)/float/sfloat -I$(srcdir)/float/ffloat -I$(srcdir)/float/dfloat -I$(srcdir)/float/lfloat -I$(srcdir)/float -I$(srcdir)/rational -I$(srcdir)/integer -I$(srcdir)/base/digitseq -I$(srcdir)/base/digit -Ibase $(GMP_INCLUDES) diff --git a/src/complex/elem/division/cl_C_DF_recip.cc b/src/complex/elem/division/cl_C_DF_recip.cc new file mode 100644 index 0000000..c214fef --- /dev/null +++ b/src/complex/elem/division/cl_C_DF_recip.cc @@ -0,0 +1,55 @@ +// cl_C_recip(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_C.h" + + +// Implementation. + +#include "cl_dfloat.h" +#include "cl_DF.h" + +const cl_C_DF cl_C_recip (const cl_DF& a, const cl_DF& b) +{ +// a=0.0 -> liefere die Komponenten a=0.0 und -1/b. +// b=0.0 -> liefere die Komponenten 1/a und b=0.0. +// e:=max(exponent(a),exponent(b)). +// a':=a/2^e bzw. 0.0 bei Underflowmöglichkeit (beim Skalieren a':=a/2^e +// oder beim Quadrieren a'*a': 2*(e-exponent(a))>exp_mid-exp_low-1 +// d.h. exponent(b)-exponent(a)>floor((exp_mid-exp_low-1)/2) ). +// b':=b/2^e bzw. 0.0 bei Underflowmöglichkeit (beim Skalieren b':=b/2^e +// oder beim Quadrieren b'*b': 2*(e-exponent(b))>exp_mid-exp_low-1 +// d.h. exponent(a)-exponent(b)>floor((exp_mid-exp_low-1)/2) ). +// c':=a'*a'+b'*b', +// liefere die beiden Komponenten 2^(-e)*a'/c' und -2^(-e)*b'/c'. + var sintL a_exp; + var sintL b_exp; + { + // Exponenten von a holen: + var uintL uexp = DF_uexp(TheDfloat(a)->dfloat_value_semhi); + if (uexp == 0) + // a=0.0 -> liefere (complex a (- (/ b))) : + return cl_C_DF(a,-recip(b)); + a_exp = (sintL)(uexp - DF_exp_mid); + } + { + // Exponenten von b holen: + var uintL uexp = DF_uexp(TheDfloat(b)->dfloat_value_semhi); + if (uexp == 0) + // b=0.0 -> liefere (complex (/ a) b) : + return cl_C_DF(recip(a),b); + b_exp = (sintL)(uexp - DF_exp_mid); + } + // Nun a_exp = float_exponent(a), b_exp = float_exponent(b). + var sintL e = (a_exp > b_exp ? a_exp : b_exp); // Maximum der Exponenten + // a und b durch 2^e dividieren: + var cl_DF na = (b_exp-a_exp > floor(DF_exp_mid-DF_exp_low-1,2) ? cl_DF_0 : scale_float(a,-e)); + var cl_DF nb = (a_exp-b_exp > floor(DF_exp_mid-DF_exp_low-1,2) ? cl_DF_0 : scale_float(b,-e)); + // c' := a'*a'+b'*b' berechnen: + var cl_DF nc = square(na) + square(nb); + // 2^(-e)*a'/c' + i * -2^(-e)*b'/c' + return cl_C_DF(scale_float(na/nc,-e), scale_float(-(nb/nc),-e)); +} diff --git a/src/complex/elem/division/cl_C_FF_recip.cc b/src/complex/elem/division/cl_C_FF_recip.cc new file mode 100644 index 0000000..0fe21cc --- /dev/null +++ b/src/complex/elem/division/cl_C_FF_recip.cc @@ -0,0 +1,55 @@ +// cl_C_recip(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_C.h" + + +// Implementation. + +#include "cl_ffloat.h" +#include "cl_FF.h" + +const cl_C_FF cl_C_recip (const cl_FF& a, const cl_FF& b) +{ +// a=0.0 -> liefere die Komponenten a=0.0 und -1/b. +// b=0.0 -> liefere die Komponenten 1/a und b=0.0. +// e:=max(exponent(a),exponent(b)). +// a':=a/2^e bzw. 0.0 bei Underflowmöglichkeit (beim Skalieren a':=a/2^e +// oder beim Quadrieren a'*a': 2*(e-exponent(a))>exp_mid-exp_low-1 +// d.h. exponent(b)-exponent(a)>floor((exp_mid-exp_low-1)/2) ). +// b':=b/2^e bzw. 0.0 bei Underflowmöglichkeit (beim Skalieren b':=b/2^e +// oder beim Quadrieren b'*b': 2*(e-exponent(b))>exp_mid-exp_low-1 +// d.h. exponent(a)-exponent(b)>floor((exp_mid-exp_low-1)/2) ). +// c':=a'*a'+b'*b', +// liefere die beiden Komponenten 2^(-e)*a'/c' und -2^(-e)*b'/c'. + var sintL a_exp; + var sintL b_exp; + { + // Exponenten von a holen: + var uintL uexp = FF_uexp(cl_ffloat_value(a)); + if (uexp == 0) + // a=0.0 -> liefere (complex a (- (/ b))) : + return cl_C_FF(a,-recip(b)); + a_exp = (sintL)(uexp - FF_exp_mid); + } + { + // Exponenten von b holen: + var uintL uexp = FF_uexp(cl_ffloat_value(b)); + if (uexp == 0) + // b=0.0 -> liefere (complex (/ a) b) : + return cl_C_FF(recip(a),b); + b_exp = (sintL)(uexp - FF_exp_mid); + } + // Nun a_exp = float_exponent(a), b_exp = float_exponent(b). + var sintL e = (a_exp > b_exp ? a_exp : b_exp); // Maximum der Exponenten + // a und b durch 2^e dividieren: + var cl_FF na = (b_exp-a_exp > floor(FF_exp_mid-FF_exp_low-1,2) ? cl_FF_0 : scale_float(a,-e)); + var cl_FF nb = (a_exp-b_exp > floor(FF_exp_mid-FF_exp_low-1,2) ? cl_FF_0 : scale_float(b,-e)); + // c' := a'*a'+b'*b' berechnen: + var cl_FF nc = square(na) + square(nb); + // 2^(-e)*a'/c' + i * -2^(-e)*b'/c' + return cl_C_FF(scale_float(na/nc,-e), scale_float(-(nb/nc),-e)); +} diff --git a/src/complex/elem/division/cl_C_LF_recip.cc b/src/complex/elem/division/cl_C_LF_recip.cc new file mode 100644 index 0000000..ed81c64 --- /dev/null +++ b/src/complex/elem/division/cl_C_LF_recip.cc @@ -0,0 +1,71 @@ +// cl_C_recip(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_C.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_LF.h" +#include "cl_LF_impl.h" + +ALL_cl_LF_OPERATIONS_SAME_PRECISION() + +const cl_C_LF cl_C_recip (const cl_LF& a, const cl_LF& b) +{ +// Zuerst a und b auf gleiche Länge bringen: den längeren runden. +// a=0.0 -> liefere die Komponenten a=0.0 und -1/b. +// b=0.0 -> liefere die Komponenten 1/a und b=0.0. +// e:=max(exponent(a),exponent(b)). +// a':=a/2^e bzw. 0.0 bei Underflowmöglichkeit (beim Skalieren a':=a/2^e +// oder beim Quadrieren a'*a': 2*(e-exponent(a))>exp_mid-exp_low-1 +// d.h. exponent(b)-exponent(a)>floor((exp_mid-exp_low-1)/2) ). +// b':=b/2^e bzw. 0.0 bei Underflowmöglichkeit (beim Skalieren b':=b/2^e +// oder beim Quadrieren b'*b': 2*(e-exponent(b))>exp_mid-exp_low-1 +// d.h. exponent(a)-exponent(b)>floor((exp_mid-exp_low-1)/2) ). +// c':=a'*a'+b'*b', +// liefere die beiden Komponenten 2^(-e)*a'/c' und -2^(-e)*b'/c'. + { Mutable(cl_LF,a); + Mutable(cl_LF,b); + { + var uintC a_len = TheLfloat(a)->len; + var uintC b_len = TheLfloat(b)->len; + if (!(a_len == b_len)) { + if (a_len < b_len) + b = shorten(b,a_len); + else + a = shorten(a,b_len); + } + } + var sintL a_exp; + var sintL b_exp; + { + // Exponenten von a holen: + var uintL uexp = TheLfloat(a)->expo; + if (uexp == 0) + // a=0.0 -> liefere (complex a (- (/ b))) : + return cl_C_LF(a,-recip(b)); + a_exp = (sintL)(uexp - LF_exp_mid); + } + { + // Exponenten von b holen: + var uintL uexp = TheLfloat(b)->expo; + if (uexp == 0) + // b=0.0 -> liefere (complex (/ a) b) : + return cl_C_LF(recip(a),b); + b_exp = (sintL)(uexp - LF_exp_mid); + } + // Nun a_exp = float_exponent(a), b_exp = float_exponent(b). + var sintL e = (a_exp > b_exp ? a_exp : b_exp); // Maximum der Exponenten + // a und b durch 2^e dividieren: + var cl_LF na = ((b_exp > a_exp) && ((uintL)(b_exp-a_exp) > (uintL)floor(LF_exp_mid-LF_exp_low-1,2)) ? encode_LF0(TheLfloat(a)->len) : scale_float(a,-e)); + var cl_LF nb = ((a_exp > b_exp) && ((uintL)(a_exp-b_exp) > (uintL)floor(LF_exp_mid-LF_exp_low-1,2)) ? encode_LF0(TheLfloat(b)->len) : scale_float(b,-e)); + // c' := a'*a'+b'*b' berechnen: + var cl_LF nc = square(na) + square(nb); + // 2^(-e)*a'/c' + i * -2^(-e)*b'/c' + return cl_C_LF(scale_float(na/nc,-e), scale_float(-(nb/nc),-e)); +}} diff --git a/src/complex/elem/division/cl_C_SF_recip.cc b/src/complex/elem/division/cl_C_SF_recip.cc new file mode 100644 index 0000000..b1fed61 --- /dev/null +++ b/src/complex/elem/division/cl_C_SF_recip.cc @@ -0,0 +1,55 @@ +// cl_C_recip(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_C.h" + + +// Implementation. + +#include "cl_sfloat.h" +#include "cl_SF.h" + +const cl_C_SF cl_C_recip (const cl_SF& a, const cl_SF& b) +{ +// a=0.0 -> liefere die Komponenten a=0.0 und -1/b. +// b=0.0 -> liefere die Komponenten 1/a und b=0.0. +// e:=max(exponent(a),exponent(b)). +// a':=a/2^e bzw. 0.0 bei Underflowmöglichkeit (beim Skalieren a':=a/2^e +// oder beim Quadrieren a'*a': 2*(e-exponent(a))>exp_mid-exp_low-1 +// d.h. exponent(b)-exponent(a)>floor((exp_mid-exp_low-1)/2) ). +// b':=b/2^e bzw. 0.0 bei Underflowmöglichkeit (beim Skalieren b':=b/2^e +// oder beim Quadrieren b'*b': 2*(e-exponent(b))>exp_mid-exp_low-1 +// d.h. exponent(a)-exponent(b)>floor((exp_mid-exp_low-1)/2) ). +// c':=a'*a'+b'*b', +// liefere die beiden Komponenten 2^(-e)*a'/c' und -2^(-e)*b'/c'. + var sintL a_exp; + var sintL b_exp; + { + // Exponenten von a holen: + var uintL uexp = SF_uexp(a); + if (uexp == 0) + // a=0.0 -> liefere (complex a (- (/ b))) : + return cl_C_SF(a,-recip(b)); + a_exp = (sintL)(uexp - SF_exp_mid); + } + { + // Exponenten von b holen: + var uintL uexp = SF_uexp(b); + if (uexp == 0) + // b=0.0 -> liefere (complex (/ a) b) : + return cl_C_SF(recip(a),b); + b_exp = (sintL)(uexp - SF_exp_mid); + } + // Nun a_exp = float_exponent(a), b_exp = float_exponent(b). + var sintL e = (a_exp > b_exp ? a_exp : b_exp); // Maximum der Exponenten + // a und b durch 2^e dividieren: + var cl_SF na = (b_exp-a_exp > floor(SF_exp_mid-SF_exp_low-1,2) ? SF_0 : scale_float(a,-e)); + var cl_SF nb = (a_exp-b_exp > floor(SF_exp_mid-SF_exp_low-1,2) ? SF_0 : scale_float(b,-e)); + // c' := a'*a'+b'*b' berechnen: + var cl_SF nc = square(na) + square(nb); + // 2^(-e)*a'/c' + i * -2^(-e)*b'/c' + return cl_C_SF(scale_float(na/nc,-e), scale_float(-(nb/nc),-e)); +} diff --git a/src/complex/elem/division/cl_C_div.cc b/src/complex/elem/division/cl_C_div.cc new file mode 100644 index 0000000..9976ca6 --- /dev/null +++ b/src/complex/elem/division/cl_C_div.cc @@ -0,0 +1,40 @@ +// binary operator / + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" + +const cl_N operator/ (const cl_N& x, const cl_N& y) +{ +// Methode: +// x,y beide reell -> klar. +// x=a+bi, y=c reell -> (a/c)+(b/c)i +// y komplex -> (* x (/ y)) + if (realp(y)) { + DeclareType(cl_R,y); + if (realp(x)) { + DeclareType(cl_R,x); + // x,y beide reell + return x/y; + } else { + DeclareType(cl_C,x); + // x komplex: x=a+bi, y=c + var const cl_R& a = realpart(x); + var const cl_R& b = imagpart(x); + var const cl_R& c = y; + return complex(a/c,b/c); + } + } else { + DeclareType(cl_C,y); + // y komplex + return x * recip(y); + } +} diff --git a/src/complex/elem/division/cl_C_recip.cc b/src/complex/elem/division/cl_C_recip.cc new file mode 100644 index 0000000..128714c --- /dev/null +++ b/src/complex/elem/division/cl_C_recip.cc @@ -0,0 +1,111 @@ +// recip(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" +#include "cl_R.h" +#include "cl_rational.h" +#include "cl_RA.h" +#include "cl_F.h" +#include "cl_SF.h" +#include "cl_FF.h" +#include "cl_DF.h" +#include "cl_LF.h" + +ALL_cl_LF_OPERATIONS_SAME_PRECISION() + +// for GEN_F_OP2: +#define NOMAP2(F,EXPR) \ + cl_C_##F _tmp = EXPR; \ + return complex_C(_tmp.realpart,_tmp.imagpart); +#define MAP2(F,FN,EXPR) \ + cl_C_##F _tmp = EXPR; \ + return complex_C(FN(_tmp.realpart),FN(_tmp.imagpart)) + +const cl_N recip (const cl_N& x) +{ +// Methode: +// Falls x reell, klar. +// Falls x=a+bi: +// Falls a=0: 0+(-1/b)i. +// Falls a und b beide rational sind: +// c:=a*a+b*b, c:=1/c, liefere a*c+(-b*c)i. +// Falls a oder b Floats sind: +// Falls einer von beiden rational ist, runde ihn zum selben Float-Typ +// wie der andere und führe das UP durch. +// Falls beide Floats sind, erweitere auf den genaueren, führe das UP +// durch und runde wieder auf den ungenaueren. +// Das Ergebnis ist eine komplexe Zahl, da beide Komponenten Floats sind. +// UP: [a,b Floats vom selben Typ] +// a=0.0 -> liefere die Komponenten a=0.0 und -1/b. +// b=0.0 -> liefere die Komponenten 1/a und b=0.0. +// e:=max(exponent(a),exponent(b)). +// a':=a/2^e bzw. 0.0 bei Underflowmöglichkeit (beim Skalieren a':=a/2^e +// oder beim Quadrieren a'*a': 2*(e-exponent(a))>exp_mid-exp_low-1 +// d.h. exponent(b)-exponent(a)>floor((exp_mid-exp_low-1)/2) ). +// b':=b/2^e bzw. 0.0 bei Underflowmöglichkeit (beim Skalieren b':=b/2^e +// oder beim Quadrieren b'*b': 2*(e-exponent(b))>exp_mid-exp_low-1 +// d.h. exponent(a)-exponent(b)>floor((exp_mid-exp_low-1)/2) ). +// c':=a'*a'+b'*b', +// liefere die beiden Komponenten 2^(-e)*a'/c' und -2^(-e)*b'/c'. + + if (realp(x)) { + DeclareType(cl_R,x); + return recip(x); + } else + { + DeclareType(cl_C,x); + var const cl_R& a = realpart(x); + var const cl_R& b = imagpart(x); + // x = a+bi + if (rationalp(a)) { + DeclareType(cl_RA,a); + if (eq(a,0)) + // (complex 0 (- (/ b))) + return complex_C(0,-recip(b)); + if (rationalp(b)) { + DeclareType(cl_RA,b); + // a,b beide rational + var cl_RA c = recip(square(a)+square(b)); + return complex_C(a*c,-b*c); + } else { + DeclareType(cl_F,b); + // a rational, b Float + floatcase(b + , return complex_C(cl_C_recip(cl_RA_to_SF(a),b)); + , return complex_C(cl_C_recip(cl_RA_to_FF(a),b)); + , return complex_C(cl_C_recip(cl_RA_to_DF(a),b)); + , return complex_C(cl_C_recip(cl_RA_to_LF(a,TheLfloat(b)->len),b)); + ); + } + } else { + DeclareType(cl_F,a); + if (rationalp(b)) { + DeclareType(cl_RA,b); + // a Float, b rational + floatcase(a + , return complex_C(cl_C_recip(a,cl_RA_to_SF(b))); + , return complex_C(cl_C_recip(a,cl_RA_to_FF(b))); + , return complex_C(cl_C_recip(a,cl_RA_to_DF(b))); + , return complex_C(cl_C_recip(a,cl_RA_to_LF(b,TheLfloat(a)->len))); + ); + } else { + DeclareType(cl_F,b); + // a,b Floats + #ifndef CL_LF_PEDANTIC + GEN_F_OP2(a,b,cl_C_recip,2,1,); // uses NOMAP2, MAP2. + #else + GEN_F_OP2(a,b,cl_C_recip,2,0,); // uses NOMAP2, MAP2. + #endif + } + } + } +} diff --git a/src/complex/input/Makeflags b/src/complex/input/Makeflags new file mode 100644 index 0000000..699fadf --- /dev/null +++ b/src/complex/input/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/complex/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/float -I$(srcdir)/integer -I$(srcdir)/base/string -I$(srcdir)/base/digitseq -I$(srcdir)/base/digit -Ibase $(GMP_INCLUDES) diff --git a/src/complex/input/cl_N_from_string.cc b/src/complex/input/cl_N_from_string.cc new file mode 100644 index 0000000..5e406ea --- /dev/null +++ b/src/complex/input/cl_N_from_string.cc @@ -0,0 +1,26 @@ +// cl_N (const char *) constructor. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex_class.h" + + +// Implementation. + +#include "cl_input.h" +#include "cl_complex_io.h" + +cl_read_flags cl_N_read_flags = { + syntax_number, + lsyntax_all, + 10, + { cl_float_format_ffloat, cl_float_format_lfloat_min, cl_true } +}; + +cl_N::cl_N (const char * string) +{ + pointer = as_cl_private_thing( + read_complex(cl_N_read_flags,string,NULL,NULL)); +} diff --git a/src/complex/input/cl_N_read.cc b/src/complex/input/cl_N_read.cc new file mode 100644 index 0000000..21c8396 --- /dev/null +++ b/src/complex/input/cl_N_read.cc @@ -0,0 +1,339 @@ +// read_complex(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex_io.h" + + +// Implementation. + +#include +#include "cl_input.h" +#include "cl_real_io.h" +#include "cl_float_io.h" +#include "cl_rational_io.h" +#include "cl_integer_io.h" +#include "cl_integer.h" +#include "cl_I.h" +#include "cl_F.h" +#include "cl_C.h" +#include "cl_abort.h" + +#undef floor +#include +#define floor cln_floor + +// Step forward over all digits, to the end of string or to the next non-digit. +static const char * skip_digits (const char * ptr, const char * string_limit, unsigned int base) +{ + for ( ; ptr != string_limit; ptr++) { + var char ch = *ptr; + if ((ch >= '0') && (ch <= '9')) + if (ch < '0' + (int)base) + continue; + else + break; + else { + if (base <= 10) + break; + if (((ch >= 'A') && (ch < 'A'-10+(int)base)) + || ((ch >= 'a') && (ch < 'a'-10+(int)base)) + ) + continue; + else + break; + } + } + return ptr; +} + +// Finish reading the "+yi" part of "x+yi" when "x" has already been read. +static const cl_N read_complex_number_rest (const cl_read_flags& flags, const char * string_rest, const char * string, const char * string_limit, const char * * end_of_parse, const cl_R& x); + +#define at_end_of_parse(ptr) \ + if (end_of_parse) \ + { *end_of_parse = (ptr); } \ + else \ + { if ((ptr) != string_limit) { read_number_junk((ptr),string,string_limit); } } + +const cl_N read_complex (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse) +{ + // If no string_limit is given, it defaults to the end of the string. + if (!string_limit) + string_limit = string + strlen(string); + if (flags.syntax & syntax_rational) { + // Check for rational number syntax. + var unsigned int rational_base = flags.rational_base; + var const char * ptr = string; + if (flags.lsyntax & lsyntax_commonlisp) { + if (ptr == string_limit) goto not_rational_syntax; + if (*ptr == '#') { + // Check for #b, #o, #x, #nR syntax. + ptr++; + if (ptr == string_limit) goto not_rational_syntax; + switch (*ptr) { + case 'b': case 'B': + rational_base = 2; break; + case 'o': case 'O': + rational_base = 8; break; + case 'x': case 'X': + rational_base = 16; break; + default: + var const char * base_end_ptr = + skip_digits(ptr,string_limit,10); + if (base_end_ptr == ptr) goto not_rational_syntax; + if (base_end_ptr == string_limit) goto not_rational_syntax; + if (!((*base_end_ptr == 'r') || (*base_end_ptr == 'R'))) + goto not_rational_syntax; + var cl_I base = read_integer(10,0,ptr,0,base_end_ptr-ptr); + if (!((base >= 2) && (base <= 36))) { + fprint(cl_stderr, "Base must be an integer in the range from 2 to 36, not "); + fprint(cl_stderr, base); + fprint(cl_stderr, "\n"); + cl_abort(); + } + rational_base = FN_to_UL(base); ptr = base_end_ptr; + break; + } + ptr++; + } + } + var const char * ptr_after_prefix = ptr; + var cl_signean sign = 0; + if (ptr == string_limit) goto not_rational_syntax; + switch (*ptr) { + case '-': sign = ~sign; + case '+': ptr++; + default: break; + } + var const char * ptr_after_sign = ptr; + if (flags.syntax & syntax_integer) { + // Check for integer syntax: {'+'|'-'|} {digit}+ {'.'|} + // Allow final dot only in Common Lisp syntax if there was no # prefix. + if ((flags.lsyntax & lsyntax_commonlisp) && (ptr_after_prefix == string)) { + ptr = skip_digits(ptr_after_sign,string_limit,10); + if (ptr != ptr_after_sign) + if (ptr != string_limit) + if (*ptr == '.') { + ptr++; + if ((ptr == string_limit) || !(((*ptr >= '0') && (*ptr <= '9')) || ((*ptr >= 'A') && (*ptr <= 'Z') && (*ptr != 'I')) || ((*ptr >= 'a') && (*ptr <= 'z') && (*ptr != 'i')) || (*ptr == '.') || (*ptr == '_') || (*ptr == '/'))) + return read_complex_number_rest(flags,ptr,string,string_limit,end_of_parse, + read_integer(10,sign,ptr_after_sign,0,ptr-ptr_after_sign)); + } + } + ptr = skip_digits(ptr_after_sign,string_limit,rational_base); + if ((ptr == string_limit) || !(((*ptr >= '0') && (*ptr <= '9')) || ((*ptr >= 'A') && (*ptr <= 'Z') && (*ptr != 'I')) || ((*ptr >= 'a') && (*ptr <= 'z') && (*ptr != 'i')) || (*ptr == '.') || (*ptr == '_') || (*ptr == '/'))) + return read_complex_number_rest(flags,ptr,string,string_limit,end_of_parse, + read_integer(rational_base,sign,ptr_after_sign,0,ptr-ptr_after_sign)); + } + if (flags.syntax & syntax_ratio) { + // Check for ratio syntax: {'+'|'-'|} {digit}+ '/' {digit}+ + ptr = skip_digits(ptr_after_sign,string_limit,rational_base); + if (ptr != ptr_after_sign) + if (ptr != string_limit) + if (*ptr == '/') { + var const char * ptr_at_slash = ptr; + ptr = skip_digits(ptr_at_slash+1,string_limit,rational_base); + if (ptr != ptr_at_slash+1) + if ((ptr == string_limit) || !(((*ptr >= '0') && (*ptr <= '9')) || ((*ptr >= 'A') && (*ptr <= 'Z') && (*ptr != 'I')) || ((*ptr >= 'a') && (*ptr <= 'z') && (*ptr != 'i')) || (*ptr == '.') || (*ptr == '_') || (*ptr == '/'))) + return read_complex_number_rest(flags,ptr,string,string_limit,end_of_parse, + read_rational(rational_base,sign,ptr_after_sign,0,ptr_at_slash-ptr_after_sign,ptr-ptr_after_sign)); + } + } + } +not_rational_syntax: + if (flags.syntax & syntax_float) { + // Check for floating-point number syntax: + // {'+'|'-'|} {digit}+ {'.' {digit}* | } expo {'+'|'-'|} {digit}+ + // {'+'|'-'|} {digit}* '.' {digit}+ expo {'+'|'-'|} {digit}+ + // {'+'|'-'|} {digit}* '.' {digit}+ + var const char * ptr = string; + var const unsigned int float_base = 10; + var cl_signean sign = 0; + if (ptr == string_limit) goto not_float_syntax; + switch (*ptr) { + case '-': sign = ~sign; + case '+': ptr++; + default: break; + } + var const char * ptr_after_sign = ptr; + var const char * ptr_after_intpart = skip_digits(ptr_after_sign,string_limit,float_base); + var cl_boolean have_dot = cl_false; + var const char * ptr_before_fracpart = ptr_after_intpart; + var const char * ptr_after_fracpart = ptr_after_intpart; + ptr = ptr_after_intpart; + if (ptr != string_limit) + if (*ptr == '.') { + have_dot = cl_true; + ptr_before_fracpart = ptr+1; + ptr_after_fracpart = skip_digits(ptr_before_fracpart,string_limit,float_base); + } + ptr = ptr_after_fracpart; + var char exponent_marker; + var cl_boolean have_exponent; + var const char * ptr_in_exponent = ptr; + var const char * ptr_after_exponent = ptr; + if ((ptr == string_limit) || !(((*ptr >= '0') && (*ptr <= '9')) || ((*ptr >= 'A') && (*ptr <= 'Z') && (*ptr != 'I')) || ((*ptr >= 'a') && (*ptr <= 'z') && (*ptr != 'i')) || (*ptr == '.') || (*ptr == '/'))) { + // No exponent. + have_exponent = cl_false; + // Must have at least one fractional part digit. + if (ptr_after_fracpart == ptr_before_fracpart) goto not_float_syntax; + exponent_marker = 'E'; + } else { + have_exponent = cl_true; + // Must have at least one digit. + if (ptr_after_sign == ptr_after_intpart) + if (ptr_after_fracpart == ptr_before_fracpart) + goto not_float_syntax; + exponent_marker = ((*ptr >= 'a') && (*ptr <= 'z') ? *ptr - 'a' + 'A' : *ptr); + switch (exponent_marker) { + case 'E': + case 'S': case 'F': case 'D': case 'L': + break; + default: + goto not_float_syntax; + } + } + if (have_exponent) { + ptr++; + if (ptr == string_limit) goto not_float_syntax; + switch (*ptr) { + case '-': + case '+': ptr++; + default: break; + } + ptr_in_exponent = ptr; + ptr_after_exponent = skip_digits(ptr_in_exponent,string_limit,10); + if (ptr_after_exponent == ptr_in_exponent) goto not_float_syntax; + } + ptr = ptr_after_exponent; + var const char * ptr_after_prec = ptr; + var cl_float_format_t prec; + if ((ptr != string_limit) && (*ptr == '_')) { + ptr++; + ptr_after_prec = skip_digits(ptr,string_limit,10); + if (ptr_after_prec == ptr) goto not_float_syntax; + var cl_I prec1 = digits_to_I(ptr,ptr_after_prec-ptr,10); + var uintL prec2 = cl_I_to_UL(prec1); + prec = (float_base==10 ? cl_float_format(prec2) + : (cl_float_format_t)((uintL)((1+prec2)*log((double)float_base)*1.442695041)+1) + ); + } else { + switch (exponent_marker) { + case 'S': prec = cl_float_format_sfloat; break; + case 'F': prec = cl_float_format_ffloat; break; + case 'D': prec = cl_float_format_dfloat; break; + case 'L': prec = flags.float_flags.default_lfloat_format; break; + case 'E': prec = flags.float_flags.default_float_format; break; + default: NOTREACHED + } + if (flags.float_flags.mantissa_dependent_float_format) { + // Count the number of significant digits. + ptr = ptr_after_sign; + while (ptr < ptr_after_fracpart && (*ptr == '0' || *ptr == '.')) ptr++; + var uintL num_significant_digits = + (ptr_after_fracpart - ptr) - (ptr_before_fracpart > ptr ? 1 : 0); + var uintL prec2 = (num_significant_digits>=2 ? num_significant_digits-2 : 0); + var cl_float_format_t precx = + (float_base==10 ? cl_float_format(prec2) + : (cl_float_format_t)((uintL)((1+prec2)*log((double)float_base)*1.442695041)+1) + ); + if ((uintL)precx > (uintL)prec) + prec = precx; + } + } + floatformatcase(prec + , if (!(flags.syntax & syntax_sfloat)) goto not_float_syntax; + , if (!(flags.syntax & syntax_ffloat)) goto not_float_syntax; + , if (!(flags.syntax & syntax_dfloat)) goto not_float_syntax; + , unused len; + if (!(flags.syntax & syntax_lfloat)) goto not_float_syntax; + ); + return read_complex_number_rest(flags,ptr_after_prec,string,string_limit,end_of_parse, + read_float(float_base,prec,sign,ptr_after_sign,0,ptr_after_fracpart-ptr_after_sign,ptr_after_exponent-ptr_after_sign,ptr_before_fracpart-ptr_after_sign)); + } +not_float_syntax: + if ((flags.syntax & syntax_complex) && (flags.lsyntax & lsyntax_commonlisp)) { + // Check for complex number syntax: + // '#' {'C'|'c'} '(' realpart {' '}+ imagpart ')' + var const char * ptr = string; + if (ptr == string_limit) goto not_complex_syntax; + if (!(*ptr == '#')) goto not_complex_syntax; + ptr++; + if (ptr == string_limit) goto not_complex_syntax; + if (!((*ptr == 'C') || (*ptr == 'c'))) goto not_complex_syntax; + ptr++; + // Modified flags for parsing the realpart and imagpart: + var cl_read_flags flags_for_parts = flags; + flags_for_parts.syntax = (cl_read_syntax_t)((flags_for_parts.syntax & ~syntax_complex) | syntax_maybe_bad); + var const char * end_of_part; + if (ptr == string_limit) goto not_complex_syntax; + if (!(*ptr == '(')) goto not_complex_syntax; + ptr++; + var cl_R realpart = read_real(flags_for_parts,ptr,string_limit,&end_of_part); + if (end_of_part == ptr) goto not_complex_syntax; + ptr = end_of_part; + if (ptr == string_limit) goto not_complex_syntax; + if (!(*ptr == ' ')) goto not_complex_syntax; + ptr++; + while ((ptr != string_limit) && (*ptr == ' ')) { ptr++; } + var cl_R imagpart = read_real(flags_for_parts,ptr,string_limit,&end_of_part); + if (end_of_part == ptr) goto not_complex_syntax; + ptr = end_of_part; + if (ptr == string_limit) goto not_complex_syntax; + if (!(*ptr == ')')) goto not_complex_syntax; + ptr++; + at_end_of_parse(ptr); + return complex(realpart,imagpart); + } +not_complex_syntax: +bad_syntax: + if (flags.syntax & syntax_maybe_bad) { + ASSERT(end_of_parse); + *end_of_parse = string; + return 0; // dummy return + } + read_number_bad_syntax(string,string_limit); +} + +static const cl_N read_complex_number_rest (const cl_read_flags& flags, const char * string_rest, const char * string, const char * string_limit, const char * * end_of_parse, const cl_R& x) +{ + unused string; + if ((flags.syntax & syntax_complex) && (flags.lsyntax & lsyntax_algebraic)) { + // Finish reading the "+yi" part of "x+yi". + // We allow "y" to begin with a '-'. + // We also allow the '+' to be replaced by '-', but in this case + // "y" may not begin with a '-'. + // We also allow the syntax "xi" (implicit realpart = 0). + var const char * ptr = string_rest; + if (ptr == string_limit) goto not_complex_syntax; + if ((*ptr == 'i') || (*ptr == 'I')) { + ptr++; + at_end_of_parse(ptr); + return complex(0,x); + } + switch (*ptr) { + case '+': ptr++; + case '-': break; + default: goto not_complex_syntax; + } + // Modified flags for parsing the imagpart: + var cl_read_flags flags_for_part = flags; + flags_for_part.syntax = (cl_read_syntax_t)((flags_for_part.syntax & ~syntax_complex) | syntax_maybe_bad); + var const char * end_of_part; + var const cl_R& realpart = x; + var cl_R imagpart = read_real(flags_for_part,ptr,string_limit,&end_of_part); + if (end_of_part == ptr) goto not_complex_syntax; + ptr = end_of_part; + if (ptr == string_limit) goto not_complex_syntax; + if (!((*ptr == 'i') || (*ptr == 'I'))) goto not_complex_syntax; + ptr++; + at_end_of_parse(ptr); + return complex(realpart,imagpart); + } +not_complex_syntax: + at_end_of_parse(string_rest); + return x; +} diff --git a/src/complex/input/cl_N_read_stream.cc b/src/complex/input/cl_N_read_stream.cc new file mode 100644 index 0000000..3fa7462 --- /dev/null +++ b/src/complex/input/cl_N_read_stream.cc @@ -0,0 +1,114 @@ +// read_complex(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex_io.h" + + +// Implementation. + +#include "cl_io.h" +#include "cl_spushstring.h" +#include "cl_input.h" + +// We read an entire token (or even more, if it begins with #C) into a +// buffer and then call read_complex() on the buffer. + +class pushstring_hack : public cl_spushstring { +public: + char* start_pointer (void) { return buffer; } + char* end_pointer (void) { return buffer+index; } +}; + +static cl_boolean number_char_p (char c) +{ + if ((c >= '0') && (c <= '9')) + return cl_true; + if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'))) + return cl_true; + switch (c) { + case '+': case '-': case '.': case '/': + return cl_true; + default: + return cl_false; + } +} + +const cl_N read_complex (cl_istream stream, const cl_read_flags& flags) +{ + // One pre-allocated buffer. This reduces the allocation/free cost. + static pushstring_hack buffer; + + var int c; + // Skip whitespace at the beginning. + loop { + c = freadchar(stream); + if (c == cl_EOF) goto eof; + if ((c == ' ') || (c == '\t') || (c == '\n')) + continue; + else + break; + } + // Found first non-whitespace character. + // Numbers cannot cross lines. We can treat EOF and '\n' the same way. + buffer.reset(); + if (c == '#') { + if (!(flags.lsyntax & lsyntax_commonlisp)) + goto syntax1; + buffer.push(c); + // Read some digits, then a letter, then a list or token. + loop { + c = freadchar(stream); + if (c == cl_EOF) goto eof; + buffer.push(c); + if ((c >= '0') && (c <= '9')) + continue; + else + break; + } + if (!(((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')))) + goto syntax1; + buffer.push(c); + c = freadchar(stream); + if (c == cl_EOF) goto eof; + if (c == '(') { + var uintL paren_level = 0; + loop { + buffer.push(c); + if (c == '(') paren_level++; + else if (c == ')') paren_level--; + if (paren_level == 0) goto done; + c = freadchar(stream); + if ((c == cl_EOF) || (c == '\n')) goto syntax; + } + } + } + // Read a number token. + if (!number_char_p(c)) + goto syntax1; + loop { + buffer.push(c); + c = freadchar(stream); + if (c == cl_EOF) + break; + if (!number_char_p(c)) { + funreadchar(stream,c); + break; + } + } +done: + // Parse the number. + return read_complex(flags, + buffer.start_pointer(), buffer.end_pointer(), + NULL + ); + + // Handle syntax error. +syntax1: buffer.push(c); +syntax: read_number_bad_syntax(buffer.start_pointer(),buffer.end_pointer()); + + // Handle premature EOF. +eof: read_number_eof(); +} diff --git a/src/complex/misc/Makeflags b/src/complex/misc/Makeflags new file mode 100644 index 0000000..d1e7c47 --- /dev/null +++ b/src/complex/misc/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/complex/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/integer -I$(srcdir)/base/digitseq -I$(srcdir)/base/digit -Ibase $(GMP_INCLUDES) diff --git a/src/complex/misc/cl_C_class.cc b/src/complex/misc/cl_C_class.cc new file mode 100644 index 0000000..db4290c --- /dev/null +++ b/src/complex/misc/cl_C_class.cc @@ -0,0 +1,22 @@ +// cl_class_complex. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" + +static void complex_destructor (cl_heap* pointer) +{ + (*(cl_heap_complex*)pointer).~cl_heap_complex(); +} + +cl_class cl_class_complex = { + complex_destructor, + cl_class_flags_subclass_complex +}; diff --git a/src/complex/misc/cl_C_conjugate.cc b/src/complex/misc/cl_C_conjugate.cc new file mode 100644 index 0000000..1a6e8e1 --- /dev/null +++ b/src/complex/misc/cl_C_conjugate.cc @@ -0,0 +1,26 @@ +// conjugate(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" + +const cl_N conjugate (const cl_N& x) +{ + if (realp(x)) + return x; + else { + DeclareType(cl_C,x); + var const cl_R& a = realpart(x); + var const cl_R& b = imagpart(x); + // Vorzeichenwechsel beim Imaginärteil + return complex_C(a,-b); + } +} diff --git a/src/complex/misc/cl_C_debug.cc b/src/complex/misc/cl_C_debug.cc new file mode 100644 index 0000000..80aca20 --- /dev/null +++ b/src/complex/misc/cl_C_debug.cc @@ -0,0 +1,30 @@ +// cl_C debugging support. + +// General includes. +#include "cl_sysdep.h" + +// Specification. + + +// Implementation. + +#include "cl_complex.h" +#include "cl_io.h" +#include "cl_complex_io.h" + +static void dprint (cl_heap* pointer) +{ + var const cl_N& obj = *(const cl_N*)&pointer; + fprint(cl_debugout, "(cl_N) "); + fprint(cl_debugout, obj); +} +AT_INITIALIZATION(dprint_N) +{ cl_register_type_printer(cl_class_complex,dprint); } + +// This dummy links in this module when requires it. +int cl_C_debug_module; + +extern int cl_R_debug_module; +static void* dummy[] = { &dummy, + &cl_R_debug_module +}; diff --git a/src/complex/misc/cl_C_eqhashcode.cc b/src/complex/misc/cl_C_eqhashcode.cc new file mode 100644 index 0000000..9e29510 --- /dev/null +++ b/src/complex/misc/cl_C_eqhashcode.cc @@ -0,0 +1,31 @@ +// cl_N equal_hashcode(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_N.h" +#include "cl_C.h" +#include "cl_real.h" + +uint32 cl_equal_hashcode (const cl_N& x) +{ + if (realp(x)) { + DeclareType(cl_R,x); + return cl_equal_hashcode(x); + } else { + DeclareType(cl_C,x); + var const cl_R& a = realpart(x); + var const cl_R& b = imagpart(x); + var uint32 code1 = cl_equal_hashcode(a); + var uint32 code2 = cl_equal_hashcode(b); + // Wichtig beim Kombinieren, wegen "complex canonicalization": + // Ist imagpart=0.0, so ist der Hashcode = cl_equal_hashcode(a). + return code1 ^ ((code2 << 5) | (code2 >> 27)); + } +} diff --git a/src/complex/misc/cl_C_expt.cc b/src/complex/misc/cl_C_expt.cc new file mode 100644 index 0000000..609e6be --- /dev/null +++ b/src/complex/misc/cl_C_expt.cc @@ -0,0 +1,52 @@ +// expt(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" + +// Methode: +// Für y>0: +// a:=x, b:=y. +// Solange b gerade, setze a:=a*a, b:=b/2. [a^b bleibt invariant, = x^y.] +// c:=a. +// Solange b:=floor(b/2) >0 ist, +// setze a:=a*a, und falls b ungerade, setze c:=a*c. +// Ergebnis c. +// Für y=0: Ergebnis 1. +// Für y<0: (/ (expt x (- y))). + +// Assume y>0. +inline const cl_N expt_pos (const cl_N& x, uintL y) +{ + var cl_N a = x; + var uintL b = y; + while (!(b % 2)) { a = square(a); b = b >> 1; } + var cl_N c = a; + until (b == 1) + { b = b >> 1; + a = square(a); + if (b % 2) { c = a * c; } + } + return c; +} + +const cl_N expt (const cl_N& x, sintL y) +{ + if (realp(x)) { + DeclareType(cl_R,x); + // x reell -> schnellere Routine + return expt(x,y); + } + if (y==0) { return 1; } // y=0 -> Ergebnis 1 + var uintL abs_y = (y<0 ? (uintL)(-y) : y); // Betrag von y nehmen + var cl_N z = expt_pos(x,abs_y); // (expt x (abs y)) + return (y<0 ? recip(z) : z); // evtl. noch Kehrwert nehmen +} diff --git a/src/complex/misc/cl_C_expt_I.cc b/src/complex/misc/cl_C_expt_I.cc new file mode 100644 index 0000000..35b35f8 --- /dev/null +++ b/src/complex/misc/cl_C_expt_I.cc @@ -0,0 +1,54 @@ +// expt(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" +#include "cl_I.h" + +// Methode: +// Für y>0: +// a:=x, b:=y. +// Solange b gerade, setze a:=a*a, b:=b/2. [a^b bleibt invariant, = x^y.] +// c:=a. +// Solange b:=floor(b/2) >0 ist, +// setze a:=a*a, und falls b ungerade, setze c:=a*c. +// Ergebnis c. +// Für y=0: Ergebnis 1. +// Für y<0: (/ (expt x (- y))). + +// Assume y>0. +inline const cl_N expt_pos (const cl_N& x, const cl_I& y) +{ + var cl_N a = x; + var cl_I b = y; + while (!oddp(b)) { a = square(a); b = b >> 1; } + var cl_N c = a; + until (eq(b,1)) + { b = b >> 1; + a = square(a); + if (oddp(b)) { c = a * c; } + } + return c; +} + +const cl_N expt (const cl_N& x, const cl_I& y) +{ + if (realp(x)) { + DeclareType(cl_R,x); + // x reell -> schnellere Routine + return expt(x,y); + } + if (eq(y,0)) { return 1; } // y=0 -> Ergebnis 1 + var cl_boolean y_negative = minusp(y); + var cl_I abs_y = (y_negative ? -y : y); // Betrag von y nehmen + var cl_N z = expt_pos(x,abs_y); // (expt x (abs y)) + return (y_negative ? recip(z) : z); // evtl. noch Kehrwert nehmen +} diff --git a/src/complex/misc/cl_N_as.cc b/src/complex/misc/cl_N_as.cc new file mode 100644 index 0000000..85cb6e6 --- /dev/null +++ b/src/complex/misc/cl_N_as.cc @@ -0,0 +1,42 @@ +// as_cl_N(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_N.h" + +// Cf. cl_N_p in cl_C_ring.cc. +// But here, for better inlining in g++, it is preferrable to finish every +// alternative with either "return cl_true;" or "return cl_false;". + +inline cl_boolean cl_N_p (const cl_number& x) +{ + if (!x.pointer_p()) + switch (x.nonpointer_tag()) { + case cl_FN_tag: + case cl_SF_tag: + #if defined(CL_WIDE_POINTERS) + case cl_FF_tag: + #endif + return cl_true; + } + else + if (x.pointer_type()->flags & cl_class_flags_subclass_complex) + return cl_true; + return cl_false; +} + +const cl_N& as_cl_N (const cl_number& x, const char * filename, int line) +{ + if (cl_N_p(x)) { + DeclareType(cl_N,x); + return x; + } else + cl_as_error(x,"a number",filename,line); +} diff --git a/src/complex/output/Makeflags b/src/complex/output/Makeflags new file mode 100644 index 0000000..56d7a89 --- /dev/null +++ b/src/complex/output/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/complex/Makeflags +SUBDIR_INCLUDES += diff --git a/src/complex/output/cl_N_aprint.cc b/src/complex/output/cl_N_aprint.cc new file mode 100644 index 0000000..a138561 --- /dev/null +++ b/src/complex/output/cl_N_aprint.cc @@ -0,0 +1,17 @@ +// print_complex(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex_io.h" + + +// Implementation. + +#include "cl_output.h" + +void print_complex (cl_ostream stream, const cl_print_flags& flags, const cl_N& z) +{ + print_complex(stream,(const cl_print_number_flags&)flags,z); +} diff --git a/src/complex/output/cl_N_bprint.cc b/src/complex/output/cl_N_bprint.cc new file mode 100644 index 0000000..695cc17 --- /dev/null +++ b/src/complex/output/cl_N_bprint.cc @@ -0,0 +1,60 @@ +// print_complex(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex_io.h" + + +// Implementation. + +#include "cl_output.h" +#include "cl_complex.h" +#include "cl_C.h" +#include "cl_real_io.h" + +void print_complex (cl_ostream stream, const cl_print_number_flags& flags, const cl_N& z) +{ + if (realp(z)) { + DeclareType(cl_R,z); + print_real(stream,flags,z); + } else { + DeclareType(cl_C,z); + var cl_R re = realpart(z); + var cl_R im = imagpart(z); + if (flags.complex_readably) { + // Common Lisp #C(re im) syntax + fprintchar(stream,'#'); + fprintchar(stream,'C'); + fprintchar(stream,'('); + print_real(stream,flags,re); + fprintchar(stream,' '); + print_real(stream,flags,im); + fprintchar(stream,')'); + } else { + // Standard mathematical notation: re + im i + if (!eq(im,0)) { + if (!eq(re,0)) { + // Example: 3-7i + print_real(stream,flags,re); + if (minusp(im)) { + fprintchar(stream,'-'); + print_real(stream,flags,-im); + } else { + fprintchar(stream,'+'); + print_real(stream,flags,im); + } + fprintchar(stream,'i'); + } else { + // Example: 6i + print_real(stream,flags,im); + fprintchar(stream,'i'); + } + } else { + // Example: 8 + print_real(stream,flags,re); + } + } + } +} diff --git a/src/complex/ring/Makeflags b/src/complex/ring/Makeflags new file mode 100644 index 0000000..56d7a89 --- /dev/null +++ b/src/complex/ring/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/complex/Makeflags +SUBDIR_INCLUDES += diff --git a/src/complex/ring/cl_C_ring.cc b/src/complex/ring/cl_C_ring.cc new file mode 100644 index 0000000..49cfcc3 --- /dev/null +++ b/src/complex/ring/cl_C_ring.cc @@ -0,0 +1,159 @@ +// Ring of complex numbers. + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_C_ring) + +// Specification. +#include "cl_complex_ring.h" + + +// Implementation. + +#include "cl_complex.h" +#include "cl_complex_io.h" +#include "cl_C.h" + +static void N_fprint (cl_heap_ring* R, cl_ostream stream, const _cl_ring_element& x) +{ + unused R; + fprint(stream,The(cl_N)(x)); +} + +static cl_boolean N_equal (cl_heap_ring* R, const _cl_ring_element& x, const _cl_ring_element& y) +{ + unused R; + return cl_equal(The(cl_N)(x),The(cl_N)(y)); +} + +static const _cl_ring_element N_zero (cl_heap_ring* R) +{ + return _cl_ring_element(R, (cl_N)0); +} + +static cl_boolean N_zerop (cl_heap_ring* R, const _cl_ring_element& x) +{ + unused R; + // Here we return true only if x is the *exact* zero. Because we + // don't want the degree of polynomials to depend on rounding errors. + // For all ring theoretic purposes, we treat 0.0, 0+0.0i etc. as if + // they were zero divisors. + return exact_zerop(The(cl_N)(x)); +} + +static const _cl_ring_element N_plus (cl_heap_ring* R, const _cl_ring_element& x, const _cl_ring_element& y) +{ + return _cl_ring_element(R, The(cl_N)(x) + The(cl_N)(y)); +} + +static const _cl_ring_element N_minus (cl_heap_ring* R, const _cl_ring_element& x, const _cl_ring_element& y) +{ + return _cl_ring_element(R, The(cl_N)(x) - The(cl_N)(y)); +} + +static const _cl_ring_element N_uminus (cl_heap_ring* R, const _cl_ring_element& x) +{ + return _cl_ring_element(R, - The(cl_N)(x)); +} + +static const _cl_ring_element N_one (cl_heap_ring* R) +{ + return _cl_ring_element(R, (cl_N)1); +} + +static const _cl_ring_element N_canonhom (cl_heap_ring* R, const cl_I& x) +{ + return _cl_ring_element(R, (cl_N)x); +} + +static const _cl_ring_element N_mul (cl_heap_ring* R, const _cl_ring_element& x, const _cl_ring_element& y) +{ + return _cl_ring_element(R, The(cl_N)(x) * The(cl_N)(y)); +} + +static const _cl_ring_element N_square (cl_heap_ring* R, const _cl_ring_element& x) +{ + return _cl_ring_element(R, square(The(cl_N)(x))); +} + +static const _cl_ring_element N_expt_pos (cl_heap_ring* R, const _cl_ring_element& x, const cl_I& y) +{ + return _cl_ring_element(R, expt(The(cl_N)(x),y)); +} + +static cl_boolean cl_N_p (const cl_number& x) +{ + return (cl_boolean) + (!x.pointer_p() + || (x.pointer_type()->flags & cl_class_flags_subclass_complex) != 0 + ); +} + +static cl_ring_setops N_setops = { + N_fprint, + N_equal +}; +static cl_ring_addops N_addops = { + N_zero, + N_zerop, + N_plus, + N_minus, + N_uminus +}; +static cl_ring_mulops N_mulops = { + N_one, + N_canonhom, + N_mul, + N_square, + N_expt_pos +}; + +static cl_number_ring_ops N_ops = { + cl_N_p, + cl_equal, + exact_zerop, + operator+, + operator-, + operator-, + operator*, + square, + expt +}; + +class cl_heap_complex_ring : public cl_heap_number_ring { + SUBCLASS_cl_heap_ring() +public: + // Constructor. + cl_heap_complex_ring () + : cl_heap_number_ring (&N_setops,&N_addops,&N_mulops, + (cl_number_ring_ops*) &N_ops) + { type = &cl_class_complex_ring; } + // Destructor. + ~cl_heap_complex_ring () {} +}; + +static void cl_complex_ring_destructor (cl_heap* pointer) +{ + (*(cl_heap_complex_ring*)pointer).~cl_heap_complex_ring(); +} + +static void cl_complex_ring_dprint (cl_heap* pointer) +{ + unused pointer; + fprint(cl_debugout, "(cl_complex_ring) cl_C_ring"); +} + +cl_class cl_class_complex_ring = { + cl_complex_ring_destructor, + cl_class_flags_number_ring, + cl_complex_ring_dprint +}; + +// Constructor. +inline cl_complex_ring::cl_specialized_number_ring () + : cl_number_ring (new cl_heap_complex_ring()) {} + +const cl_complex_ring cl_C_ring; + +CL_PROVIDE_END(cl_C_ring) diff --git a/src/complex/transcendental/Makeflags b/src/complex/transcendental/Makeflags new file mode 100644 index 0000000..a8e32dc --- /dev/null +++ b/src/complex/transcendental/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/complex/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/real/conv -I$(srcdir)/real -I$(srcdir)/float/transcendental -I$(srcdir)/rational -I$(srcdir)/integer -I$(srcdir)/base/digitseq -I$(srcdir)/base/digit -Ibase $(GMP_INCLUDES) diff --git a/src/complex/transcendental/cl_C_acos.cc b/src/complex/transcendental/cl_C_acos.cc new file mode 100644 index 0000000..ee82b57 --- /dev/null +++ b/src/complex/transcendental/cl_C_acos.cc @@ -0,0 +1,94 @@ +// acos(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" +#include "cl_R.h" +#include "cl_rational.h" +#include "cl_RA.h" +#include "cl_float.h" + +inline const cl_F cl_pi (const cl_R& v) +{ + if (rationalp(v)) + return cl_pi(); + else { + DeclareType(cl_F,v); + return cl_pi(v); + } +} + +const cl_N acos (const cl_N& z) +{ +// Methode: +// Wert und Branch Cuts nach der Formel CLTL2, S. 312: +// arccos(z) = log(z+i*sqrt(1-z^2))/i = pi/2 - arcsin(z) +// Sei z=x+iy. +// Falls y=0: +// Falls x rational: +// Bei x=1: Ergebnis 0. +// Bei x=1/2: Ergebnis pi/3. +// Bei x=0: Ergebnis pi/2. +// Bei x=-1/2: Ergebnis 2pi/3. +// Bei x=-1: Ergebnis pi. +// Sonst x in Float umwandeln. +// Falls x>1: Ergebnis i ln(x+sqrt(x^2-1)). +// Sonst errechne u+iv = arsinh(-y+ix) wie oben, Ergebnis (pi/2-v)+iu. + + cl_C_R u_v; + if (realp(z)) { + DeclareType(cl_R,z); + // y=0 + var const cl_R& x = z; + var cl_F xf; + if (rationalp(x)) { + DeclareType(cl_RA,x); + // x rational + if (integerp(x)) { + DeclareType(cl_I,x); + // x Integer + if (eq(x,0)) // x=0 -> Ergebnis pi/2 + return scale_float(cl_pi(),-1); + if (eq(x,1)) // x=1 -> Ergebnis 0 + return 0; + if (eq(x,-1)) // x=-1 -> Ergebnis pi + return cl_pi(); + xf = cl_float(x); + } else { + DeclareType(cl_RT,x); + // x Ratio + if (eq(denominator(x),2)) { // Nenner = 2 ? + if (eq(numerator(x),1)) // x=1/2 -> Ergebnis pi/3 + return cl_pi()/3; + if (eq(numerator(x),-1)) // x=-1/2 -> Ergebnis 2pi/3 + return scale_float(cl_pi(),1)/3; + } + xf = cl_float(x); + } + } else { + DeclareType(cl_F,x); + xf = x; + } + // x Float + { var cl_F& x = xf; + if (cl_I(1) < x) + // x>1 + return complex_C(0,ln(x+sqrt(square(x)-1))); + u_v = asinh(0,x); + }} else { + DeclareType(cl_C,z); + u_v = asinh(-imagpart(z),realpart(z)); + } + var cl_R& u = u_v.realpart; + var cl_R& v = u_v.imagpart; + var cl_F pi = cl_pi(v); // pi im Float-Format von v + return complex(scale_float(pi,-1)-v,u); // (pi/2-v)+iu +} diff --git a/src/complex/transcendental/cl_C_acosh.cc b/src/complex/transcendental/cl_C_acosh.cc new file mode 100644 index 0000000..7b613bc --- /dev/null +++ b/src/complex/transcendental/cl_C_acosh.cc @@ -0,0 +1,87 @@ +// acosh(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" +#include "cl_R.h" +#include "cl_rational.h" +#include "cl_RA.h" +#include "cl_float.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_F_from_R_def.cc" + +const cl_N acosh (const cl_N& z) +{ +// Methode: +// Wert und Branch Cuts nach der Formel CLTL2, S. 314: +// arcosh(z) = 2 log(sqrt((z+1)/2)+sqrt((z-1)/2)) +// Sei z=x+iy. +// Falls y=0: +// Falls x rational: +// Bei x=1: Ergebnis 0. +// Bei x=1/2: Ergebnis pi/3 i. +// Bei x=0: Ergebnis pi/2 i. +// Bei x=-1/2: Ergebnis 2pi/3 i. +// Bei x=-1: Ergebnis pi i. +// Falls x<-1: +// x in Float umwandeln, Ergebnis log(sqrt(x^2-1)-x) + i pi. +// Sonst nach (!) mit u = sqrt((z+1)/2) und v = sqrt((z-1)/2) : +// arcosh(z) = 4 artanh(v/(u+1)) = 4 artanh(sqrt((z-1)/2)/(1+sqrt((z+1)/2))) + +// Um für zwei Zahlen u,v mit u^2-v^2=1 und u,v beide in Bild(sqrt) +// (d.h. Realteil>0.0 oder Realteil=0.0 und Imaginärteil>=0.0) +// log(u+v) zu berechnen: +// log(u+v) = 2 artanh(v/(u+1)) (!) +// (Beweis: 2 artanh(v/(u+1)) = log(1+(v/(u+1))) - log(1-(v/(u+1))) +// = log((1+u+v)/(u+1)) - log((1+u-v)/(u+1)) == log((1+u+v)/(1+u-v)) +// = log(u+v) mod 2 pi i, und beider Imaginärteil ist > -pi und <= pi.) + + cl_C_R u_v; + if (realp(z)) { + DeclareType(cl_R,z); + // y=0 + var const cl_R& x = z; + if (rationalp(x)) { + DeclareType(cl_RA,x); + // x rational + if (integerp(x)) { + DeclareType(cl_I,x); + // x Integer + if (eq(x,0)) // x=0 -> Ergebnis pi/2 i + return complex_C(0,scale_float(cl_pi(),-1)); + if (eq(x,1)) // x=1 -> Ergebnis 0 + return 0; + if (eq(x,-1)) // x=-1 -> Ergebnis pi i + return complex_C(0,cl_pi()); + } else { + DeclareType(cl_RT,x); + // x Ratio + if (eq(denominator(x),2)) { // Nenner = 2 ? + if (eq(numerator(x),1)) // x=1/2 -> Ergebnis pi/3 i + return complex_C(0,cl_pi()/3); + if (eq(numerator(x),-1)) // x=-1/2 -> Ergebnis 2pi/3 i + return complex_C(0,scale_float(cl_pi(),1)/3); + } + } + } + if (x < cl_I(-1)) { + // x < -1 + var cl_F xf = cl_float(x); + var cl_F& x = xf; + // x Float <= -1 + // log(sqrt(x^2-1)-x), ein Float >=0, Imaginärteil pi + return complex_C(ln(sqrt(square(x)-1)-x),cl_pi()); + } + } + return 4 * atanh( sqrt(minus1(z)/2) / plus1(sqrt(plus1(z)/2)) ); +} diff --git a/src/complex/transcendental/cl_C_asin.cc b/src/complex/transcendental/cl_C_asin.cc new file mode 100644 index 0000000..8a4894f --- /dev/null +++ b/src/complex/transcendental/cl_C_asin.cc @@ -0,0 +1,39 @@ +// asin(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" + +// Methode: +// Wert und Branch Cuts nach der Formel CLTL2, S. 311: +// arcsin(z) = log(iz+sqrt(1-z^2))/i +// Sei z=x+iy, errechne u+iv = arsinh(-y+ix) wie oben, Ergebnis v-iu. +// Real- und Imaginärteil des Ergebnisses sind Floats, außer wenn z reell oder +// rein imaginär ist. + +inline const cl_C_R _asin (const cl_N& z) +{ + if (realp(z)) { + DeclareType(cl_R,z); + return asinh(0,z); + } else { + DeclareType(cl_C,z); + return asinh(-imagpart(z),realpart(z)); + } +} + +const cl_N asin (const cl_N& z) +{ + var cl_C_R u_v = _asin(z); + var cl_R& u = u_v.realpart; + var cl_R& v = u_v.imagpart; + return complex(v,-u); // v-iu +} diff --git a/src/complex/transcendental/cl_C_asinh.cc b/src/complex/transcendental/cl_C_asinh.cc new file mode 100644 index 0000000..816391c --- /dev/null +++ b/src/complex/transcendental/cl_C_asinh.cc @@ -0,0 +1,80 @@ +// asinh(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" + +// Methode: +// Wert und Branch Cuts nach der Formel CLTL2, S. 313: +// arsinh(z) = log(z+sqrt(1+z^2)) +// z=x+iy, Ergebnis u+iv. +// Falls x=0 und y=0: u=0, v=0. +// Falls x=0: arsinh(iy) = i arcsin(y). +// y rational -> +// Bei y=1: u = 0, v = pi/2. +// Bei y=1/2: u = 0, v = pi/6. +// Bei y=0: u = 0, v = 0. +// Bei y=-1/2: u = 0, v = -pi/6. +// Bei y=-1: u = 0, v = -pi/2. +// Sonst y in Float umwandeln. +// e := Exponent aus (decode-float y), d := (float-digits y) +// Bei y=0.0 oder e<=-d/2 liefere u = 0, v = y +// (denn bei e<=-d/2 ist y^2/3 < y^2/2 < 2^(-d)/2 = 2^(-d-1), also +// 1 <= asin(y)/y < 1+y^2/3 < 1+2^(-d-1) < 1+2^(-d), +// also ist asin(y)/y, auf d Bits gerundet, gleich 1.0). +// Berechne 1-y^2. +// Bei y>1 liefere u = ln(y+sqrt(y^2-1)), v = pi/2. +// Bei y<-1 liefere u = -ln(|y|+sqrt(|y|^2-1)), v = -pi/2. +// Bei |y|<=1 liefere u = 0, v = atan(X=sqrt(1-y^2),Y=y). +// Falls y=0: +// x rational -> x in Float umwandeln. +// |x|<1/2: u = atanh(x/sqrt(1+x^2)), +// x>=1/2: u = ln(x+sqrt(1+x^2)), +// x<=-1/2: u = -ln(-x+sqrt(1+x^2)). +// v = 0. +// Sonst: +// z in Bild(sqrt) -> log(sqrt(1+z^2)+z) = (!) = 2 artanh(z/(1+sqrt(1+z^2))). +// z nicht in Bild(sqrt) -> +// arsinh(z) = -arsinh(-z). +// (Denn arsinh(z)+arsinh(-z) == log((z+sqrt(1+z^2))(-z+sqrt(1+z^2))) +// = log((1+z^2)-z^2) = log(1) = 0 mod 2 pi i, und links ist +// der Imaginärteil betragsmäßig <=pi.) +// Also arsinh(z) = -arsinh(-z) = - 2 artanh(-z/(1+sqrt(1+z^2))) +// = (wegen -artanh(-w) = artanh(w)) = 2 artanh(z/(1+sqrt(1+z^2))). +// Real- und Imaginärteil des Ergebnisses sind Floats, außer wenn z reell oder +// rein imaginär ist. + +// Um für zwei Zahlen u,v mit u^2-v^2=1 und u,v beide in Bild(sqrt) +// (d.h. Realteil>0.0 oder Realteil=0.0 und Imaginärteil>=0.0) +// log(u+v) zu berechnen: +// log(u+v) = 2 artanh(v/(u+1)) (!) +// (Beweis: 2 artanh(v/(u+1)) = log(1+(v/(u+1))) - log(1-(v/(u+1))) +// = log((1+u+v)/(u+1)) - log((1+u-v)/(u+1)) == log((1+u+v)/(1+u-v)) +// = log(u+v) mod 2 pi i, und beider Imaginärteil ist > -pi und <= pi.) + +inline const cl_C_R _asinh (const cl_N& z) +{ + if (realp(z)) { + DeclareType(cl_R,z); + return asinh(z,0); + } else { + DeclareType(cl_C,z); + return asinh(realpart(z),imagpart(z)); + } +} + +const cl_N asinh (const cl_N& z) +{ + var cl_C_R u_v = _asinh(z); + var cl_R& u = u_v.realpart; + var cl_R& v = u_v.imagpart; + return complex(u,v); +} diff --git a/src/complex/transcendental/cl_C_asinh_aux.cc b/src/complex/transcendental/cl_C_asinh_aux.cc new file mode 100644 index 0000000..f68147d --- /dev/null +++ b/src/complex/transcendental/cl_C_asinh_aux.cc @@ -0,0 +1,172 @@ +// asinh(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_C.h" + + +// Implementation. + +#include "cl_real.h" +#include "cl_F_tran.h" +#include "cl_R.h" +#include "cl_rational.h" +#include "cl_RA.h" +#include "cl_float.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_F_from_R_def.cc" + +// Hilfsfunktion für asinh und asin: u+iv := arsinh(x+iy). Liefert cl_C_R(u,v). + +const cl_C_R asinh (const cl_R& x, const cl_R& y) +{ +// Methode: +// Wert und Branch Cuts nach der Formel CLTL2, S. 313: +// arsinh(z) = log(z+sqrt(1+z^2)) +// z=x+iy, Ergebnis u+iv. +// Falls x=0 und y=0: u=0, v=0. +// Falls x=0: arsinh(iy) = i arcsin(y). +// y rational -> +// Bei y=1: u = 0, v = pi/2. +// Bei y=1/2: u = 0, v = pi/6. +// Bei y=0: u = 0, v = 0. +// Bei y=-1/2: u = 0, v = -pi/6. +// Bei y=-1: u = 0, v = -pi/2. +// Sonst y in Float umwandeln. +// e := Exponent aus (decode-float y), d := (float-digits y) +// Bei y=0.0 oder e<=-d/2 liefere u = 0, v = y +// (denn bei e<=-d/2 ist y^2/3 < y^2/2 < 2^(-d)/2 = 2^(-d-1), also +// 1 <= asin(y)/y < 1+y^2/3 < 1+2^(-d-1) < 1+2^(-d), +// also ist asin(y)/y, auf d Bits gerundet, gleich 1.0). +// Berechne 1-y^2. +// Bei y>1 liefere u = ln(y+sqrt(y^2-1)), v = pi/2. +// Bei y<-1 liefere u = -ln(|y|+sqrt(|y|^2-1)), v = -pi/2. +// Bei |y|<=1 liefere u = 0, v = atan(X=sqrt(1-y^2),Y=y). +// Falls y=0: +// x rational -> x in Float umwandeln. +// |x|<1/2: u = atanh(x/sqrt(1+x^2)), +// x>=1/2: u = ln(x+sqrt(1+x^2)), +// x<=-1/2: u = -ln(-x+sqrt(1+x^2)). +// v = 0. +// Sonst: +// z in Bild(sqrt) -> log(sqrt(1+z^2)+z) = (!) = 2 artanh(z/(1+sqrt(1+z^2))). +// z nicht in Bild(sqrt) -> +// arsinh(z) = -arsinh(-z). +// (Denn arsinh(z)+arsinh(-z) == log((z+sqrt(1+z^2))(-z+sqrt(1+z^2))) +// = log((1+z^2)-z^2) = log(1) = 0 mod 2 pi i, und links ist +// der Imaginärteil betragsmäßig <=pi.) +// Also arsinh(z) = -arsinh(-z) = - 2 artanh(-z/(1+sqrt(1+z^2))) +// = (wegen -artanh(-w) = artanh(w)) = 2 artanh(z/(1+sqrt(1+z^2))). +// Real- und Imaginärteil des Ergebnisses sind Floats, außer wenn z reell oder +// rein imaginär ist. + +// Um für zwei Zahlen u,v mit u^2-v^2=1 und u,v beide in Bild(sqrt) +// (d.h. Realteil>0.0 oder Realteil=0.0 und Imaginärteil>=0.0) +// log(u+v) zu berechnen: +// log(u+v) = 2 artanh(v/(u+1)) (!) +// (Beweis: 2 artanh(v/(u+1)) = log(1+(v/(u+1))) - log(1-(v/(u+1))) +// = log((1+u+v)/(u+1)) - log((1+u-v)/(u+1)) == log((1+u+v)/(1+u-v)) +// = log(u+v) mod 2 pi i, und beider Imaginärteil ist > -pi und <= pi.) + + if (eq(x,0)) { + // x=0 + var cl_F yf; + if (rationalp(y)) { + DeclareType(cl_RA,y); + // y rational + if (eq(y,0)) // x=0, y=0 -> u=0, v=0 + return cl_C_R(0,0); + if (integerp(y)) { + DeclareType(cl_I,y); + // y Integer + if (eq(y,1)) // x=0, y=1 -> v = pi/2 + return cl_C_R(0,scale_float(cl_pi(),-1)); + if (eq(y,-1)) // x=0, y=-1 -> v = -pi/2 + return cl_C_R(0,-scale_float(cl_pi(),-1)); + yf = cl_float(y); // y in Float umwandeln + } else { + DeclareType(cl_RT,y); + // y Ratio + if (eq(denominator(y),2)) { // Nenner = 2 ? + if (eq(numerator(y),1)) // x=0, y=1/2 -> v = pi/6 + return cl_C_R(0,cl_pi()/6); + if (eq(numerator(y),-1)) // x=0, y=-1/2 -> v = -pi/6 + return cl_C_R(0,-(cl_pi()/6)); + } + yf = cl_float(y); // y in Float umwandeln + } + } else { + DeclareType(cl_F,y); + yf = y; + } + // y Float + var cl_F& y = yf; + if (zerop(y)) // y=0.0 -> arcsin(y) = y als Ergebnis + return cl_C_R(0,y); + if (float_exponent(y) <= (-(sintL)float_digits(y))>>1) + // e <= -d/2 <==> e <= -ceiling(d/2) + return cl_C_R(0,y); + var cl_F temp = 1-square(y); + if (!minusp(temp)) + // 1-y*y>=0, also |y|<=1 + // v = atan(X=sqrt(1-y*y),Y=y) + return cl_C_R(0,atan(sqrt(temp),y)); + else { + // 1-y*y<0, also |y|>1 + temp = sqrt(-temp); // sqrt(y*y-1) + if (minusp(y)) + temp = temp - y; + else + temp = temp + y; + // temp = sqrt(y^2-1)+|y|, ein Float >1 + var cl_F u = ln(temp); // ln(|y|+sqrt(y^2-1)), ein Float >0 + var cl_F v = scale_float(cl_pi(),-1); // (scale-float pi -1) = pi/2 + if (!minusp(y)) + return cl_C_R(u,v); // y>1 -> v = pi/2 + else + return cl_C_R(-u,-v); // y<-1 -> v = -pi/2, u = -ln(...) + } + } + if (eq(y,0)) { + // y=0 + var cl_F xf = cl_float(x); // x in Float umwandeln + var cl_F& x = xf; + // x Float + if (zerop(x)) + return cl_C_R(x,0); // x=0.0 -> u=x, v=0. + var cl_F temp = sqrt(1+square(x)); // sqrt(1+x^2) + if (float_exponent(x) < 0) // Exponent e (von x/=0) <0 ? + // |x|<1/2 + return cl_C_R(atanhx(x/temp),0); + else + // |x|>=1/2 + if (!minusp(x)) + // x>=1 + return cl_C_R(ln(temp+x),0); // u = ln(x+sqrt(1+x^2)) + else + // x<=-1 + return cl_C_R(-ln(temp-x),0); // u = -ln(-x+sqrt(1+x^2)) + } + var cl_N z = complex_C(x,y); // z=x+iy + var cl_N w = z/(1+sqrt(1+square(z))); // z/(1+sqrt(1+z^2)) + // Da z=x+iy weder reell noch rein imaginär ist, ist auch + // w := z/(1+sqrt(1+z^2)) weder reell noch rein imaginär. + // (Beweis: Sollte sqrt(1+z^2) rationalen Real- und Imaginärteil haben, + // so auch z, also auch w, und die Formel z = 2w/(1-w^2) zeigt, daß dann + // z reell oder rein imaginär sein müßte. Also hat sqrt(1+z^2) ein + // Float als Real- oder Imaginärteil, das Betragsquadrat des Nenners + // ist also ein Float, und da Real- und Imaginärteil von z /=0 sind, + // sind Real- und Imaginärteil von w Floats.) + // Daher hat dann atanh(...) Floats als Realteil u und Imaginärteil v. + { DeclareType(cl_C,w); + cl_C_R u_v = atanh(realpart(w),imagpart(w)); + var cl_R& u = u_v.realpart; + var cl_R& v = u_v.imagpart; + { DeclareType(cl_F,u); + DeclareType(cl_F,v); + return cl_C_R(scale_float(u,1),scale_float(v,1)); // u:=2*u, v:=2*v +}}} diff --git a/src/complex/transcendental/cl_C_atan.cc b/src/complex/transcendental/cl_C_atan.cc new file mode 100644 index 0000000..98b9a21 --- /dev/null +++ b/src/complex/transcendental/cl_C_atan.cc @@ -0,0 +1,39 @@ +// atan(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" + +// Methode: +// Wert und Branch Cuts nach der Formel CLTL2, S. 307/312/313: +// arctan(z) = (log(1+iz)-log(1-iz)) / 2i +// Sei z=x+iy, errechne u+iv = artanh(-y+ix) wie oben, Ergebnis v-iu. +// Real- und Imaginärteil des Ergebnisses sind Floats, außer wenn z reell oder +// rein imaginär ist. + +inline const cl_C_R _atan (const cl_N& z) +{ + if (realp(z)) { + DeclareType(cl_R,z); + return atanh(0,z); + } else { + DeclareType(cl_C,z); + return atanh(-imagpart(z),realpart(z)); + } +} + +const cl_N atan (const cl_N& z) +{ + var cl_C_R u_v = _atan(z); + var cl_R& u = u_v.realpart; + var cl_R& v = u_v.imagpart; + return complex(v,-u); // v-iu +} diff --git a/src/complex/transcendental/cl_C_atanh.cc b/src/complex/transcendental/cl_C_atanh.cc new file mode 100644 index 0000000..299445b --- /dev/null +++ b/src/complex/transcendental/cl_C_atanh.cc @@ -0,0 +1,60 @@ +// atanh(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" + +// Methode: +// Wert und Branch Cuts nach der Formel CLTL2, S. 315: +// artanh(z) = (log(1+z)-log(1-z)) / 2 +// Sei z=x+iy, Ergebnis u+iv. +// Falls x=0 und y=0: u=0, v=0. +// Falls x=0: u = 0, v = atan(X=1,Y=y). +// Falls y=0: +// x rational -> x in Float umwandeln. +// |x|<1/2: u = atanh(x), v = 0. +// |x|>=1/2: (1+x)/(1-x) errechnen, +// =0 -> Error, +// >0 (also |x|<1) -> u = 1/2 log((1+x)/(1-x)), v = 0. +// <0 (also |x|>1) -> u = 1/2 log(-(1+x)/(1-x)), +// v = (-pi/2 für x>1, pi/2 für x<-1). +// Sonst: +// 1+x und 1-x errechnen. +// x und y in Floats umwandeln. +// |4x| und 1+x^2+y^2 errechnen, +// |4x| < 1+x^2+y^2 -> u = 1/2 atanh(2x/(1+x^2+y^2)), +// |4x| >= 1+x^2+y^2 -> u = 1/4 ln ((1+x^2+y^2)+2x)/((1+x^2+y^2)-2x) +// oder besser (an der Singularität: |x|-1,|y| klein): +// u = 1/4 ln ((1+x)^2+y^2)/((1-x)^2+y^2). +// v = 1/2 atan(X=(1-x)(1+x)-y^2,Y=2y) * (-1 falls Y=0.0 und X<0.0 und x>=0.0, +// 1 sonst) +// Ergebnis ist reell nur, wenn z reell. +// Real- und Imaginärteil des Ergebnisses sind Floats, außer wenn z reell oder +// rein imaginär ist. + +inline const cl_C_R _atanh (const cl_N& z) +{ + if (realp(z)) { + DeclareType(cl_R,z); + return atanh(z,0); + } else { + DeclareType(cl_C,z); + return atanh(realpart(z),imagpart(z)); + } +} + +const cl_N atanh (const cl_N& z) +{ + var cl_C_R u_v = _atanh(z); + var cl_R& u = u_v.realpart; + var cl_R& v = u_v.imagpart; + return complex(u,v); +} diff --git a/src/complex/transcendental/cl_C_atanh_aux.cc b/src/complex/transcendental/cl_C_atanh_aux.cc new file mode 100644 index 0000000..c3dc545 --- /dev/null +++ b/src/complex/transcendental/cl_C_atanh_aux.cc @@ -0,0 +1,127 @@ +// atanh(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_C.h" + + +// Implementation. + +#include "cl_N.h" +#include "cl_real.h" +#include "cl_F_tran.h" +#include "cl_R.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_F_from_R_def.cc" + +// Hilfsfunktion für atanh und atan: u+iv := artanh(x+iy). Liefert cl_C_R(u,v). + +const cl_C_R atanh (const cl_R& x, const cl_R& y) +{ +// Methode: +// Wert und Branch Cuts nach der Formel CLTL2, S. 315: +// artanh(z) = (log(1+z)-log(1-z)) / 2 +// Sei z=x+iy, Ergebnis u+iv. +// Falls x=0 und y=0: u=0, v=0. +// Falls x=0: u = 0, v = atan(X=1,Y=y). +// Falls y=0: +// x rational -> x in Float umwandeln. +// |x|<1/2: u = atanh(x), v = 0. +// |x|>=1/2: (1+x)/(1-x) errechnen, +// =0 -> Error, +// >0 (also |x|<1) -> u = 1/2 log((1+x)/(1-x)), v = 0. +// <0 (also |x|>1) -> u = 1/2 log(-(1+x)/(1-x)), +// v = (-pi/2 für x>1, pi/2 für x<-1). +// Sonst: +// 1+x und 1-x errechnen. +// x und y in Floats umwandeln. +// |4x| und 1+x^2+y^2 errechnen, +// |4x| < 1+x^2+y^2 -> u = 1/2 atanh(2x/(1+x^2+y^2)), +// |4x| >= 1+x^2+y^2 -> u = 1/4 ln ((1+x^2+y^2)+2x)/((1+x^2+y^2)-2x) +// oder besser (an der Singularität: |x|-1,|y| klein): +// u = 1/4 ln ((1+x)^2+y^2)/((1-x)^2+y^2). +// v = 1/2 atan(X=(1-x)(1+x)-y^2,Y=2y) * (-1 falls Y=0.0 und X<0.0 und x>=0.0, +// 1 sonst) +// Ergebnis ist reell nur, wenn z reell. +// Real- und Imaginärteil des Ergebnisses sind Floats, außer wenn z reell oder +// rein imaginär ist. + + if (eq(x,0)) + // x=0 -> u=0, v=atan(X=1,Y=y) (Fall y=0 ist inbegriffen) + return cl_C_R(0, atan(1,y)); + if (eq(y,0)) { + var cl_F xf = cl_float(x); // (float x) + var cl_F& x = xf; + // x Float + if (zerop(x)) + // x=0.0 -> x als Ergebnis + return cl_C_R(x, 0); + if (float_exponent(x) < 0) + // Exponent e<0, also |x|<1/2 + return cl_C_R(atanhx(x), 0); + // e>=0, also |x|>=1/2 + var cl_F xx_den = 1 - x; + var cl_F xx = (1 + x) / xx_den; // (1+x)/(1-x) + var cl_R v; + if (!minusp(xx)) { + if (zerop(xx)) + { cl_error_division_by_0(); } + v = 0; + } else { + // (1+x)/(1-x) < 0 -> Betrag nehmen, Imaginärteil berechnen: + xx = - xx; + v = scale_float(cl_pi(),-1); // (scale-float pi -1) = pi/2 + if (minusp(xx_den)) + // 1-x<0 -> dann -pi/2 + v = -v; + } + // ln bilden, durch 2 + return cl_C_R(scale_float(ln(xx),-1), v); + } + var cl_R _1_plus_x = 1+x; + var cl_R _1_minus_x = 1-x; + // x und y in Floats umwandeln: (Diese Fallunterscheidung ist + // symmetrisch in x und y, auch wenn's nicht so aussieht.) + var cl_F xf; + var cl_F yf; + if (rationalp(x)) { + DeclareType(cl_RA,x); + yf = cl_float(y); + xf = cl_float(x,yf); + } else { + DeclareType(cl_F,x); + xf = x; + yf = cl_somefloat(y,xf); + } + var cl_F yf_2 = square(yf); + var cl_F u; + { + var cl_F temp1 = abs(scale_float(xf,2)); // |4x| + var cl_F temp2 = 1 + (square(xf) + yf_2); // 1+x^2+y^2 + if (temp1 < temp2) // |4x| < 1+x^2+y^2 ? + // u = 1/2 atanh(2x/(1+x^2+y^2)) + u = scale_float(atanhx(scale_float(xf,1)/temp2),-1); + else { + // u = 1/4 ln ((1+x)^2+y^2)/((1-x)^2+y^2) + var cl_F num = _1_plus_x*_1_plus_x + yf_2; // (1+x)^2+y^2, ein Float >=0 + var cl_F den = _1_minus_x*_1_minus_x + yf_2; // (1-x)^2+y^2, ein Float >=0 + if (zerop(den)) + { cl_error_division_by_0(); } + u = scale_float(ln(num/den),-2); + } + } + var cl_F v; + { + var cl_F X = _1_plus_x*_1_minus_x-yf_2; + var cl_F Y = scale_float(yf,1); + v = atan(X,Y); // atan(X=(1-x)(1+x)-y^2,Y=2y), ein Float + if (minusp(X) && !minusp(x) && zerop(Y)) + v = -v; + v = scale_float(v,-1); // 1/2 * atan(...) * +-1 + } + return cl_C_R(u,v); +} diff --git a/src/complex/transcendental/cl_C_cis.cc b/src/complex/transcendental/cl_C_cis.cc new file mode 100644 index 0000000..0753a27 --- /dev/null +++ b/src/complex/transcendental/cl_C_cis.cc @@ -0,0 +1,34 @@ +// cis(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" + +const cl_N cis (const cl_N& x) +{ +// Methode: +// x reell -> (complex (cos x) (sin x)) +// x = a+bi -> (complex (* (exp (- b)) (cos a)) (* (exp (- b)) (sin a))) + if (realp(x)) { + DeclareType(cl_R,x); + var cl_cos_sin_t trig = cl_cos_sin(x); + return complex(trig.cos, trig.sin); + } else { + DeclareType(cl_C,x); + // x=a+bi + var const cl_R& a = realpart(x); + var const cl_R& b = imagpart(x); + var cl_cos_sin_t trig_a = cl_cos_sin(a); // cos(a), sin(a) errechnen + var cl_R exp_minusb = exp(-b); // (exp (- b)) + return complex(exp_minusb*trig_a.cos, // (* (exp (- b)) (cos a)) + exp_minusb*trig_a.sin); // (* (exp (- b)) (sin a)) + } +} diff --git a/src/complex/transcendental/cl_C_cos.cc b/src/complex/transcendental/cl_C_cos.cc new file mode 100644 index 0000000..af0842f --- /dev/null +++ b/src/complex/transcendental/cl_C_cos.cc @@ -0,0 +1,34 @@ +// cos(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" + +const cl_N cos (const cl_N& x) +{ +// Methode: +// x reell -> klar +// x = a+bi -> (complex (* (cos a) (cosh b)) (- (* (sin a) (sinh b)))) + if (realp(x)) { + DeclareType(cl_R,x); + return cos(x); + } else { + DeclareType(cl_C,x); + // x=a+bi + var const cl_R& a = realpart(x); + var const cl_R& b = imagpart(x); + var cl_cosh_sinh_t hyp_b = cl_cosh_sinh(b); // cosh(b), sinh(b) errechnen + var cl_cos_sin_t trig_a = cl_cos_sin(a); // cos(a), sin(a) errechnen + return complex(trig_a.cos * hyp_b.cosh, // cos(a)*cosh(b) + - (trig_a.sin * hyp_b.sinh) // -sin(a)*sinh(b) + ); + } +} diff --git a/src/complex/transcendental/cl_C_cosh.cc b/src/complex/transcendental/cl_C_cosh.cc new file mode 100644 index 0000000..f8a1ec2 --- /dev/null +++ b/src/complex/transcendental/cl_C_cosh.cc @@ -0,0 +1,34 @@ +// cosh(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" + +const cl_N cosh (const cl_N& x) +{ +// Methode: +// x reell -> klar +// x = a+bi -> (complex (* (cosh a) (cos b)) (* (sinh a) (sin b))) + if (realp(x)) { + DeclareType(cl_R,x); + return cosh(x); + } else { + DeclareType(cl_C,x); + // x=a+bi + var const cl_R& a = realpart(x); + var const cl_R& b = imagpart(x); + var cl_cos_sin_t trig_b = cl_cos_sin(b); // cos(b), sin(b) errechnen + var cl_cosh_sinh_t hyp_a = cl_cosh_sinh(a); // cosh(a), sinh(a) errechnen + return complex(hyp_a.cosh * trig_b.cos, // cosh(a)*cos(b) + hyp_a.sinh * trig_b.sin // sinh(a)*sin(b) + ); + } +} diff --git a/src/complex/transcendental/cl_C_exp.cc b/src/complex/transcendental/cl_C_exp.cc new file mode 100644 index 0000000..4b3b96d --- /dev/null +++ b/src/complex/transcendental/cl_C_exp.cc @@ -0,0 +1,34 @@ +// exp(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" + +const cl_N exp (const cl_N& x) +{ +// Methode: +// x reell -> klar. +// x = a+bi -> (exp a) mit (cos b) + i (sin b) multiplizieren: +// (complex (* (exp a) (cos b)) (* (exp a) (sin b))) + if (realp(x)) { + DeclareType(cl_R,x); + return exp(x); + } else { + DeclareType(cl_C,x); + // x=a+bi + var const cl_R& a = realpart(x); + var const cl_R& b = imagpart(x); + var cl_cos_sin_t unitvec = cl_cos_sin(b); // (cos b), (sin b) + // Da b nicht = Fixnum 0 ist, ist auch sin(b) nicht = Fixnum 0. + var cl_R exp_a = exp(a); // (exp a) + return complex_C(exp_a * unitvec.cos, exp_a * unitvec.sin); + } +} diff --git a/src/complex/transcendental/cl_C_expt_C.cc b/src/complex/transcendental/cl_C_expt_C.cc new file mode 100644 index 0000000..7709e88 --- /dev/null +++ b/src/complex/transcendental/cl_C_expt_C.cc @@ -0,0 +1,218 @@ +// expt(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" +#include "cl_R.h" +#include "cl_rational.h" +#include "cl_RA.h" +#include "cl_I.h" +#include "cl_N.h" + +// Methode: +// Falls y rational: +// Falls y Integer: +// Falls y=0: Ergebnis 1, +// [Nach CLTL folgendermaßen: +// x reell: +// x rational -> Fixnum 1 +// x Float -> (float 1 x) +// x komplex: +// x komplex rational -> Fixnum 1 +// sonst: #C(1.0 0.0) im Float-Format des Real- bzw. Imaginärteils von x +// ] +// Falls x rational oder komplex rational oder |y| klein: +// x^|y| durch wiederholtes Quadrieren und Multiplizieren und evtl. +// Kehrwert-Bilden ermitteln. +// Sonst wie bei 'y Float'. +// Falls y Ratio m/n: +// Es gilt (expt x m/n) = (expt (expt x 1/n) m). +// Falls x in Q(i) liegt (also rational oder komplex rational ist): +// Sollte x^(m/n) in Q(i) liegen, so auch eine n-te Wurzel x^(1/n) +// (und bei n=2 oder n=4 damit auch alle n-ten Wurzeln x^(1/n) ). +// Falls x rational >=0: n-te Wurzel aus x nehmen. Ist sie rational, +// deren m-te Potenz als Ergebnis. +// Falls x rational <=0 oder komplex rational und n Zweierpotenz: +// n-te Wurzel aus x nehmen (mehrfaches sqrt). Ist sie rational oder +// komplex rational, deren m-te Potenz als Ergebnis. +// [Beliebige n betrachten!??] +// Falls n Zweierpotenz und |m|,n klein: n-te Wurzel aus x nehmen +// (mehrfaches sqrt), davon die m-te Potenz durch wiederholtes +// Quadrieren und Multiplizieren und evtl. Kehrwert-Bilden. +// Sonst wie bei 'y Float'. +// Falls y Float oder komplex: +// Falls (zerop x): +// Falls Realteil von y >0 : +// liefere 0.0 falls x und y reell, #C(0.0 0.0) sonst. +// Sonst Error. +// Falls y=0.0: +// liefere 1.0 falls x und y reell, #C(1.0 0.0) sonst. +// Sonst: (exp (* (log x) y)) +// Das Ergebnis liegt in Q(i), falls x in Q(i) liegt und 4y ein Integer ist.?? +// Genauigkeit erhöhen, log2(|y|) Bits mehr?? +// Bei x oder y rational und der andere Long-Float: bitte kein Single-Float!?? + +// Liefert x^0. +inline const cl_N expt_0 (const cl_N& x) +{ +#ifdef STRICT_CLTL + // y=0 -> 1 im Format von x. + if (realp(x)) { + DeclareType(cl_R,x); + if (rationalp(x)) { + DeclareType(cl_RA,x); + return 1; + } else { + DeclareType(cl_F,x); + return cl_float(1,x); + } + } else { + DeclareType(cl_C,x); + var cl_R f = contagion(realpart(x),imagpart(x)); + if (rationalp(f)) { + DeclareType(cl_RA,f); + return 1; + } else { + DeclareType(cl_F,f); + // #C(1.0 0.0) + return complex_C(cl_float(1,f),cl_float(0,f)); + } + } +#else + // Exponent exakt 0 -> Ergebnis exakt 1 + unused x; + return 1; +#endif +} + +inline const cl_R contagion (const cl_N& x) +{ + if (realp(x)) { + DeclareType(cl_R,x); + return x; + } else { + DeclareType(cl_C,x); + return contagion(realpart(x),imagpart(x)); + } +} + +const cl_N expt (const cl_N& x, const cl_N& y) +{ + if (realp(y)) { + DeclareType(cl_R,y); + if (rationalp(y)) { + DeclareType(cl_RA,y); + // y rational + if (integerp(y)) { + DeclareType(cl_I,y); + // y Integer + if (eq(y,0)) + return expt_0(x); // Liefere 1 + if (fixnump(y)) // |y| klein ? + return expt(x,y); // exakt ausrechnen + if (realp(x)) { + DeclareType(cl_R,x); + if (rationalp(x)) { + DeclareType(cl_RA,x); + return expt(x,y); // exakt ausrechnen + } + } else { + DeclareType(cl_C,x); + if (rationalp(realpart(x)) && rationalp(imagpart(x))) + return expt(x,y); // exakt ausrechnen + } + // x nicht exakt und |y| groß + } else { + DeclareType(cl_RT,y); + // y Ratio + var const cl_I& m = numerator(y); + var const cl_I& n = denominator(y); + if (realp(x)) { + DeclareType(cl_R,x); + if (rationalp(x)) { + DeclareType(cl_RA,x); + if (minusp(x)) + goto complex_rational; + // x rational >=0 + var cl_RA w; + if (rootp(x,n,&w)) // Wurzel rational? + return expt(w,m); + } + } else { + DeclareType(cl_C,x); + if (rationalp(realpart(x)) && rationalp(imagpart(x))) + goto complex_rational; + } + if (cl_false) { + complex_rational: + // x in Q(i) + var uintL k = power2p(n); + if (k) { + // n Zweierpotenz = 2^(k-1). n>1, also k>1 + Mutable(cl_N,x); + k--; + do { x = sqrt(x); } + while (--k > 0); + return expt(x,m); + } + } + if (fixnump(m) && fixnump(n)) { // |m| und n klein? + var uintL _n = FN_to_UL(n); + if ((_n & (_n-1)) == 0) { // n Zweierpotenz? + Mutable(cl_N,x); + until ((_n = _n >> 1) == 0) + { x = sqrt(x); } + return expt(x,m); + } + } + } + } + } + // allgemeiner Fall (z.B. y Float oder komplex): + if (zerop(x)) { // x=0.0 ? + if (!plusp(realpart(y))) // Realteil von y <=0 ? + { cl_error_division_by_0(); } + if (realp(x) && realp(y)) { + DeclareType(cl_R,x); + DeclareType(cl_R,y); + var cl_R f = contagion(x,y); + // ein Float, da sonst x = Fixnum 0 gewesen wäre + { DeclareType(cl_F,f); + return cl_float(0,f); // 0.0 + } + } else { + var cl_R f = contagion(contagion(x),contagion(y)); + // ein Float, da sonst x = Fixnum 0 gewesen wäre + { DeclareType(cl_F,f); + var cl_F f0 = cl_float(0,f); + return complex_C(f0,f0); // #C(0.0 0.0) + } + } + } + if (zerop(y)) { // y=0.0 ? + if (realp(x) && realp(y)) { + DeclareType(cl_R,x); + DeclareType(cl_R,y); + var cl_R f = contagion(x,y); + // ein Float, da sonst y = Fixnum 0 gewesen wäre + { DeclareType(cl_F,f); + return cl_float(1,f); + } + } else { + var cl_R f = contagion(contagion(x),contagion(y)); + // ein Float, da sonst y = Fixnum 0 gewesen wäre + { DeclareType(cl_F,f); + return complex_C(cl_float(1,f),cl_float(0,f)); + } + } + } + return exp(log(x)*y); +} diff --git a/src/complex/transcendental/cl_C_log.cc b/src/complex/transcendental/cl_C_log.cc new file mode 100644 index 0000000..9863f63 --- /dev/null +++ b/src/complex/transcendental/cl_C_log.cc @@ -0,0 +1,24 @@ +// log(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" +#include "cl_N.h" + +const cl_N log (const cl_N& x) +{ +// Methode: +// (complex (log (abs x)) (phase x)) + var cl_R r = abs(x); + if (zerop(r)) // (abs x) = 0 -> Error + { cl_error_division_by_0(); } + return complex(ln(r),phase(x)); +} diff --git a/src/complex/transcendental/cl_C_log2.cc b/src/complex/transcendental/cl_C_log2.cc new file mode 100644 index 0000000..75efeda --- /dev/null +++ b/src/complex/transcendental/cl_C_log2.cc @@ -0,0 +1,96 @@ +// log(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" +#include "cl_R.h" +#include "cl_N.h" + +const cl_N log (const cl_N& a, const cl_N& b) +{ +// Methode: +// (log a b) = +// falls b reell, >0: +// (complex (/ (log (abs a)) (log b)) (/ (phase a) (log b))), genauer: +// falls a reell, >0: bekannt +// falls (= a 0): Error +// sonst: (phase a) errechnen, ein Float. +// b (falls rational) ins selbe Float-Format umwandeln, +// Imaginärteil := (/ (phase a) (log dieses_b)). +// Falls a rational: (log (abs a) b). +// Falls a komplex mit rationalem Real- und Imaginärteil, +// Betragsquadrat (expt (abs a) 2) exakt ausrechnen als +// (+ (expt (realpart a) 2) (expt (imagpart a) 2)). +// Setze Realteil := (/ (log Betragsquadrat b) 2). +// [Eventuell wird hierbei (log b) ein zweites Mal ausgerechnet, +// aber dies sowieso nur in Single-Precision.] +// Sonst bilde (abs a), ein Float, und (log (abs a)), ein Float, +// wandle b (falls rational) ins selbe Float-Format um, +// setze Realteil := (/ (log (abs a)) (log dieses_b)). +// sonst: (/ (log a) (log b)) + if (realp(b)) { + DeclareType(cl_R,b); + if (plusp(b)) { + // b ist reell und >0 + if (realp(a)) { + DeclareType(cl_R,a); + if (plusp(a)) + // a und b sind beide reell und >0 + return log(a,b); + } + // b ist reell und >0, a aber nicht. + + // Imaginärteil (/ (phase a) (log b)) errechnen: + var cl_F im; + { + var cl_R angle = phase(a); + if (eq(angle,0)) // = Fixnum 0 <==> (= a 0) -> Error + { cl_error_division_by_0(); } + { DeclareType(cl_F,angle); + var cl_F bf = cl_somefloat(b,angle); // (float b) + im = angle / ln(bf); + }} + + // Realteil (/ (log (abs a)) (log b)) errechnen: + var cl_R re; + if (realp(a)) { + DeclareType(cl_R,a); + if (rationalp(a)) { + // a rational -> (log (abs a) b) errechnen: + re = log(abs(a),b); // NB: (abs a) > 0 + goto re_ok; + } + } else { + DeclareType(cl_C,a); + if (rationalp(realpart(a)) && rationalp(imagpart(a))) { + // a komplex mit rationalem Real- und Imaginärteil a1,a2 + var const cl_R& a1 = realpart(a); + var const cl_R& a2 = imagpart(a); + re = log(square(a1)+square(a2),b) / 2; + goto re_ok; + } + } + // Keine Chance für rationalen Realteil. + { + var cl_F abs_a = The(cl_F)(abs(a)); + var cl_F log_abs_a = ln(abs_a); + var cl_F bf = cl_somefloat(b,log_abs_a); // (float b) + re = log_abs_a / ln(bf); + } + re_ok: + + return complex_C(re,im); + } + } + + // normaler komplexer Fall + return log(a) / log(b); +} diff --git a/src/complex/transcendental/cl_C_phase.cc b/src/complex/transcendental/cl_C_phase.cc new file mode 100644 index 0000000..b403b3e --- /dev/null +++ b/src/complex/transcendental/cl_C_phase.cc @@ -0,0 +1,30 @@ +// phase(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" + +const cl_R phase (const cl_N& x) +{ +// Methode: +// (= x 0) -> willkürliches Ergebnis 0 +// x reell -> Winkel von (x,0) in Polarkoordinaten +// x komplex -> Winkel von ((realpart x),(imagpart x)) in Polarkoordinaten + if (zerop(x)) + return 0; + if (realp(x)) { + DeclareType(cl_R,x); + return atan(x,0); + } else { + DeclareType(cl_C,x); + return atan(realpart(x),imagpart(x)); + } +} diff --git a/src/complex/transcendental/cl_C_sin.cc b/src/complex/transcendental/cl_C_sin.cc new file mode 100644 index 0000000..2d5935c --- /dev/null +++ b/src/complex/transcendental/cl_C_sin.cc @@ -0,0 +1,36 @@ +// sin(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" + +const cl_N sin (const cl_N& x) +{ +// Methode: +// x reell -> klar +// x = a+bi -> (complex (* (sin a) (cosh b)) (* (cos a) (sinh b))) + if (realp(x)) { + DeclareType(cl_R,x); + return sin(x); + } else { + DeclareType(cl_C,x); + // x=a+bi + var const cl_R& a = realpart(x); + var const cl_R& b = imagpart(x); + var cl_cosh_sinh_t hyp_b = cl_cosh_sinh(b); // cosh(b), sinh(b) errechnen + var cl_cos_sin_t trig_a = cl_cos_sin(a); // cos(a), sin(a) errechnen + // Da b nicht = Fixnum 0 ist, ist auch sinh(b) nicht = Fixnum 0. + // cos(a) /= Fixnum 0. + return complex_C(trig_a.sin * hyp_b.cosh, // sin(a)*cosh(b) + trig_a.cos * hyp_b.sinh // cos(a)*sinh(b), nicht Fixnum 0 + ); + } +} diff --git a/src/complex/transcendental/cl_C_sinh.cc b/src/complex/transcendental/cl_C_sinh.cc new file mode 100644 index 0000000..b7ba4b9 --- /dev/null +++ b/src/complex/transcendental/cl_C_sinh.cc @@ -0,0 +1,36 @@ +// sinh(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" + +const cl_N sinh (const cl_N& x) +{ +// Methode: +// x reell -> klar +// x = a+bi -> (complex (* (sinh a) (cos b)) (* (cosh a) (sin b))) + if (realp(x)) { + DeclareType(cl_R,x); + return sinh(x); + } else { + DeclareType(cl_C,x); + // x=a+bi + var const cl_R& a = realpart(x); + var const cl_R& b = imagpart(x); + var cl_cosh_sinh_t hyp_a = cl_cosh_sinh(a); // cosh(a), sinh(a) errechnen + var cl_cos_sin_t trig_b = cl_cos_sin(b); // cos(b), sin(b) errechnen + // Da b nicht = Fixnum 0 ist, ist auch sin(b) nicht = Fixnum 0. + // cosh(a) /= Fixnum 0. + return complex_C(hyp_a.sinh * trig_b.cos, // sinh(a)*cos(b) + hyp_a.cosh * trig_b.sin // cosh(a)*sin(b), nicht Fixnum 0 + ); + } +} diff --git a/src/complex/transcendental/cl_C_tan.cc b/src/complex/transcendental/cl_C_tan.cc new file mode 100644 index 0000000..412f3b4 --- /dev/null +++ b/src/complex/transcendental/cl_C_tan.cc @@ -0,0 +1,40 @@ +// tan(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" + +const cl_N tan (const cl_N& x) +{ +// Methode: +// x reell -> (/ (sin x) (cos x)) +// x = a+bi -> (/ (complex (* (sin a) (cosh b)) (* (cos a) (sinh b))) +// (complex (* (cos a) (cosh b)) (- (* (sin a) (sinh b)))) ) + if (realp(x)) { + DeclareType(cl_R,x); + var cl_cos_sin_t trig = cl_cos_sin(x); + return trig.sin / trig.cos; + } else { + DeclareType(cl_C,x); + // x=a+bi + var const cl_R& a = realpart(x); + var const cl_R& b = imagpart(x); + var cl_cosh_sinh_t hyp_b = cl_cosh_sinh(b); // cosh(b), sinh(b) errechnen + var cl_cos_sin_t trig_a = cl_cos_sin(a); // cos(a), sin(a) errechnen + return + complex_C(trig_a.sin * hyp_b.cosh, // sin(a)*cosh(b) + trig_a.cos * hyp_b.sinh // cos(a)*sinh(b), nicht Fixnum 0 + ) + / complex(trig_a.cos * hyp_b.cosh, // cos(a)*cosh(b) + - (trig_a.sin * hyp_b.sinh) // -sin(a)*sinh(b) + ); + } +} diff --git a/src/complex/transcendental/cl_C_tanh.cc b/src/complex/transcendental/cl_C_tanh.cc new file mode 100644 index 0000000..96e8699 --- /dev/null +++ b/src/complex/transcendental/cl_C_tanh.cc @@ -0,0 +1,40 @@ +// tanh(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" + +const cl_N tanh (const cl_N& x) +{ +// Methode: +// x reell -> (/ (sinh x) (cosh x)) +// x = a+bi -> (/ (complex (* (sinh a) (cos b)) (* (cosh a) (sin b))) +// (complex (* (cosh a) (cos b)) (* (sinh a) (sin b))) ) + if (realp(x)) { + DeclareType(cl_R,x); + var cl_cosh_sinh_t hyp = cl_cosh_sinh(x); + return hyp.sinh / hyp.cosh; + } else { + DeclareType(cl_C,x); + // x=a+bi + var const cl_R& a = realpart(x); + var const cl_R& b = imagpart(x); + var cl_cos_sin_t trig_b = cl_cos_sin(b); // cos(b), sin(b) errechnen + var cl_cosh_sinh_t hyp_a = cl_cosh_sinh(a); // cosh(a), sinh(a) errechnen + return + complex_C(hyp_a.sinh * trig_b.cos, // sinh(a)*cos(b) + hyp_a.cosh * trig_b.sin // cosh(a)*sin(b), nicht Fixnum 0 + ) + / complex(hyp_a.cosh * trig_b.cos, // cosh(a)*cos(b) + hyp_a.sinh * trig_b.sin // sinh(a)*sin(b) + ); + } +} diff --git a/src/complex/transcendental/cl_R_cis.cc b/src/complex/transcendental/cl_R_cis.cc new file mode 100644 index 0000000..b0b0ea3 --- /dev/null +++ b/src/complex/transcendental/cl_R_cis.cc @@ -0,0 +1,21 @@ +// cis(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_complex.h" + + +// Implementation. + +#include "cl_C.h" +#include "cl_real.h" + +const cl_N cis (const cl_R& x) +{ +// Methode: +// (complex (cos x) (sin x)) + var cl_cos_sin_t trig = cl_cos_sin(x); + return complex(trig.cos, trig.sin); +} diff --git a/src/float/Makeflags b/src/float/Makeflags new file mode 100644 index 0000000..6f69c43 --- /dev/null +++ b/src/float/Makeflags @@ -0,0 +1,3 @@ +# This file contains additional flags for the main Makefile. + +SUBDIR_INCLUDES = -I$(srcdir)/float/sfloat -I$(srcdir)/float/ffloat -I$(srcdir)/float/dfloat -I$(srcdir)/float/lfloat -I$(srcdir)/float -I$(srcdir)/base/digitseq -I$(srcdir)/base/digit -Ibase -I$(srcdir)/base $(GMP_INCLUDES) diff --git a/src/float/algebraic/Makeflags b/src/float/algebraic/Makeflags new file mode 100644 index 0000000..546ddeb --- /dev/null +++ b/src/float/algebraic/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/Makeflags +SUBDIR_INCLUDES += diff --git a/src/float/algebraic/cl_F_sqrt.cc b/src/float/algebraic/cl_F_sqrt.cc new file mode 100644 index 0000000..902fded --- /dev/null +++ b/src/float/algebraic/cl_F_sqrt.cc @@ -0,0 +1,19 @@ +// sqrt(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" + +const cl_F sqrt (const cl_F& x) +GEN_F_OP1(x, sqrt, return) diff --git a/src/float/base/Makeflags b/src/float/base/Makeflags new file mode 100644 index 0000000..f1679ce --- /dev/null +++ b/src/float/base/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/Makeflags +SUBDIR_INCLUDES += -Ifloat diff --git a/src/float/base/cl_F_err_nan.cc b/src/float/base/cl_F_err_nan.cc new file mode 100644 index 0000000..04ed6b2 --- /dev/null +++ b/src/float/base/cl_F_err_nan.cc @@ -0,0 +1,19 @@ +// cl_error_floating_point_overflow(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F.h" + + +// Implementation. + +#include "cl_io.h" +#include "cl_abort.h" + +void cl_error_floating_point_nan (void) +{ + fprint(cl_stderr, "floating point NaN occurred.\n"); + cl_abort(); +} diff --git a/src/float/base/cl_F_err_ov.cc b/src/float/base/cl_F_err_ov.cc new file mode 100644 index 0000000..b0527d3 --- /dev/null +++ b/src/float/base/cl_F_err_ov.cc @@ -0,0 +1,19 @@ +// cl_error_floating_point_overflow(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F.h" + + +// Implementation. + +#include "cl_io.h" +#include "cl_abort.h" + +void cl_error_floating_point_overflow (void) +{ + fprint(cl_stderr, "Floating point overflow.\n"); + cl_abort(); +} diff --git a/src/float/base/cl_F_err_un.cc b/src/float/base/cl_F_err_un.cc new file mode 100644 index 0000000..5bf72b3 --- /dev/null +++ b/src/float/base/cl_F_err_un.cc @@ -0,0 +1,19 @@ +// cl_error_floating_point_underflow(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F.h" + + +// Implementation. + +#include "cl_io.h" +#include "cl_abort.h" + +void cl_error_floating_point_underflow (void) +{ + fprint(cl_stderr, "Floating point underflow.\n"); + cl_abort(); +} diff --git a/src/float/base/cl_F_globals.cc b/src/float/base/cl_F_globals.cc new file mode 100644 index 0000000..1de4db7 --- /dev/null +++ b/src/float/base/cl_F_globals.cc @@ -0,0 +1,15 @@ +// Global variables in CLN + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +cl_boolean cl_inhibit_floating_point_underflow = cl_false; + +cl_float_format_t cl_default_float_format = cl_float_format_ffloat; + diff --git a/src/float/base/cl_ieee.cc b/src/float/base/cl_ieee.cc new file mode 100644 index 0000000..fb4ca49 --- /dev/null +++ b/src/float/base/cl_ieee.cc @@ -0,0 +1,52 @@ +// System dependent IEEE floating-point coprocessor initialization. + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_ieee) + +// Specification. +#include "cl_ieee.h" + + +// Implementation. + +#include "cl_FF.h" +#include "cl_DF.h" +#include "cl_float_config.h" + +#if (defined(linux) || defined(__linux)) && (defined(FAST_FLOAT) || defined(FAST_DOUBLE)) + +// Damit Division durch 0.0 ein NaN und kein SIGFPE liefert: +// Entweder mit -lieee linken, +// oder libc-linux/sysdeps/linux/{i386,m68k}/ieee.c kopieren: + +#include + +#if 0 // Leider gibt das einen Error, wenn man zusätzlich mit -lieee linkt. + #if defined(HAVE_FPU_CONTROL_T) + fpu_control_t __fpu_control = _FPU_IEEE; + #else + unsigned short __fpu_control = _FPU_IEEE; + #endif +#else +AT_INITIALIZATION(ieee) +{ + #if defined(HAVE_FPU_CONTROL_T) + extern fpu_control_t __fpu_control; + __fpu_control = _FPU_IEEE; + #elif defined(HAVE_SETFPUCW) + __setfpucw(_FPU_IEEE); + #else + extern unsigned short __fpu_control; + __fpu_control = _FPU_IEEE; + #endif +} +#endif + +#endif + +// This dummy links in this module whenever some module needs IEEE floats. +int cl_ieee_module; + +CL_PROVIDE_END(cl_ieee) diff --git a/src/float/base/cl_ieee.h b/src/float/base/cl_ieee.h new file mode 100644 index 0000000..11b5b36 --- /dev/null +++ b/src/float/base/cl_ieee.h @@ -0,0 +1,17 @@ +// IEEE floating-point + +#ifndef _CL_IEEE_H +#define _CL_IEEE_H + +// To make sure that cl_ieee.cc is linked in. +// NEED_IEEE_FLOATS() +#if (defined(linux) || defined(__linux)) // only needed on Linux + #define NEED_IEEE_FLOATS() \ + CL_REQUIRE(cl_ieee) \ + static void* const CONCAT(cl_ieee_dummy_,__LINE__) = &cl_ieee_module; +#else + #define NEED_IEEE_FLOATS() +#endif +extern int cl_ieee_module; + +#endif /* _CL_IEEE_H */ diff --git a/src/float/cl_F.h b/src/float/cl_F.h new file mode 100644 index 0000000..f11107d --- /dev/null +++ b/src/float/cl_F.h @@ -0,0 +1,281 @@ +// cl_F internals + +#ifndef _CL_F_H +#define _CL_F_H + +#include "cl_number.h" +#include "cl_macros.h" +#include "cl_float.h" + + +nonreturning_function(extern, cl_error_floating_point_overflow, (void)); +nonreturning_function(extern, cl_error_floating_point_underflow, (void)); + +#define underflow_allowed() (! cl_inhibit_floating_point_underflow) + + +// For all floating-point formats: +// Sign s, Exponent e, Mantissa mk-1,...,m0 +// represents the number (-1)^s * 2^(e-_EXP_MID) * [0 . 1 mk-1 ... m0] +// e=0 represents the number 0, always with sign s=0 (and mantissa =0). +// _exp_low and _exp_high are (inclusive) bounds for e. +// Bits for Sign s Exponent e Mantissa m (= k) +// SF 1 8 16 +// FF 1 8 23 +// DF 1 11 52 +// LF 1 32 intDsize*n >= 53 + + +// Konversionen ohne Rundung: + +// cl_SF_to_FF(x) wandelt ein Short-Float x in ein Single-Float um. +extern const cl_FF cl_SF_to_FF (const cl_SF& x); + +// cl_SF_to_DF(x) wandelt ein Short-Float x in ein Double-Float um. +extern const cl_DF cl_SF_to_DF (const cl_SF& x); + +// cl_SF_to_LF(x,len) wandelt ein Short-Float x in ein Long-Float mit len Digits um. +// > uintC len: gewünschte Anzahl Digits, >=LF_minlen +extern const cl_LF cl_SF_to_LF (const cl_SF& x, uintC len); + +// cl_FF_to_DF(x) wandelt ein Single-Float x in ein Double-Float um. +extern const cl_DF cl_FF_to_DF (const cl_FF& x); + +// cl_FF_to_LF(x,len) wandelt ein Single-Float x in ein Long-Float mit len Digits um. +// > uintC len: gewünschte Anzahl Digits, >=LF_minlen +extern const cl_LF cl_FF_to_LF (const cl_FF& x, uintC len); + +// cl_DF_to_LF(x,len) wandelt ein Double-Float x in ein Long-Float mit len Digits um. +// > uintC len: gewünschte Anzahl Digits, >=LF_minlen +extern const cl_LF cl_DF_to_LF (const cl_DF& x, uintC len); + + +// Konversionen mit Rundung: + +// cl_FF_to_SF(x) wandelt ein Single-Float x in ein Short-Float um. +extern const cl_SF cl_FF_to_SF (const cl_FF& x); + +// cl_DF_to_SF(x) wandelt ein Double-Float x in ein Short-Float um. +extern const cl_SF cl_DF_to_SF (const cl_DF& x); + +// cl_LF_to_SF(x) wandelt ein Long-Float x in ein Short-Float um. +extern const cl_SF cl_LF_to_SF (const cl_LF& x); + +// cl_DF_to_FF(x) wandelt ein Double-Float x in ein Single-Float um. +extern const cl_FF cl_DF_to_FF (const cl_DF& x); + +// cl_LF_to_FF(x) wandelt ein Long-Float x in ein Single-Float um. +extern const cl_FF cl_LF_to_FF (const cl_LF& x); + +// cl_LF_to_DF(x) wandelt ein Long-Float x in ein Double-Float um. +extern const cl_DF cl_LF_to_DF (const cl_LF& x); + + +// Fehlermeldung wegen NaN +nonreturning_function(extern, cl_error_floating_point_nan, (void)); + + +// Runtime typing support. +extern cl_class cl_class_ffloat; +extern cl_class cl_class_dfloat; +extern cl_class cl_class_lfloat; + +// Type test. +inline cl_boolean longfloatp (const cl_F& x) +{ + if (x.pointer_p()) + if (x.pointer_type() == &cl_class_lfloat) + return cl_true; + return cl_false; +} + +// Macro: verteilt je nach Float-Typ eines Floats x auf 4 Statements. +// floattypecase(x, SF_statement,FF_statement,DF_statement,LF_statement); +// x sollte eine Variable sein. +#ifdef CL_WIDE_POINTERS + #define floattypecase(x, SF_statement,FF_statement,DF_statement,LF_statement) \ + if (!(x).pointer_p()) \ + switch ((x).nonpointer_tag()) \ + { case cl_SF_tag: { SF_statement } break; \ + case cl_FF_tag: { FF_statement } break; \ + default: NOTREACHED \ + } \ + else { \ + if ((x).pointer_type() == &cl_class_dfloat) { DF_statement } \ + else if ((x).pointer_type() == &cl_class_lfloat) { LF_statement } \ + else NOTREACHED \ + } +#else + #define floattypecase(x, SF_statement,FF_statement,DF_statement,LF_statement) \ + if (!(x).pointer_p()) \ + switch ((x).nonpointer_tag()) \ + { case cl_SF_tag: { SF_statement } break; \ + default: NOTREACHED \ + } \ + else { \ + if ((x).pointer_type() == &cl_class_ffloat) { FF_statement } \ + else if ((x).pointer_type() == &cl_class_dfloat) { DF_statement } \ + else if ((x).pointer_type() == &cl_class_lfloat) { LF_statement } \ + else NOTREACHED \ + } +#endif + +// Macro: verteilt je nach Float-Typ eines Floats x auf 4 Statements, +// die x vom jeweiligen Float-Typ benutzen dürfen. +// floatcase(x, SF_statement,FF_statement,DF_statement,LF_statement); +// x sollte eine Variable sein. + #define floatcase(x, SF_statement,FF_statement,DF_statement,LF_statement) \ + floattypecase(x \ + , var cl_SF& __tmp = *(cl_SF*)&x; var cl_SF& x = __tmp; SF_statement \ + , var cl_FF& __tmp = *(cl_FF*)&x; var cl_FF& x = __tmp; FF_statement \ + , var cl_DF& __tmp = *(cl_DF*)&x; var cl_DF& x = __tmp; DF_statement \ + , var cl_LF& __tmp = *(cl_LF*)&x; var cl_LF& x = __tmp; LF_statement \ + ) + + +// GEN_F_OP1(arg1,F_OP,ergebnis_zuweisung) +// generates the body of a float operation with one argument. +// LF_OP is executed once the argument has been converted to its exact +// float type. +#define GEN_F_OP1(arg1,F_OP,ergebnis_zuweisung) \ +{ \ + floatcase(arg1 \ + , /* SF */ ergebnis_zuweisung F_OP(arg1); \ + , /* FF */ ergebnis_zuweisung F_OP(arg1); \ + , /* DF */ ergebnis_zuweisung F_OP(arg1); \ + , /* LF */ ergebnis_zuweisung F_OP(arg1); \ + ); \ +} + + +// GEN_F_OP2(arg1,arg2,F_OP,r,s,ergebnis_zuweisung) +// generates the body of a float operation with two arguments. +// F_OP is executed once both arguments have been converted to the same +// float format (the longer one of arg1 and arg2). The r results are then +// converted the shorter of the two float formats. (r = 0,1,2.) +// s = 0,1. s=0 means the LF operation needs two long-floats of the same size. +// s=1 means they may be of different sizes. +#define GEN_F_OP2(arg1,arg2,F_OP,r,s,ergebnis_zuweisung) \ +{ \ + floatcase(arg1 \ + , /* arg1 SF */ \ + floatcase(arg2 \ + , /* arg2 SF */ \ + ergebnis_zuweisung CONCAT(NOMAP,r)(SF, \ + F_OP(arg1,arg2) ); \ + , /* arg2 FF */ \ + ergebnis_zuweisung CONCAT(MAP,r)(FF,cl_FF_to_SF,\ + F_OP(cl_SF_to_FF(arg1),arg2) ); \ + , /* arg2 DF */ \ + ergebnis_zuweisung CONCAT(MAP,r)(DF,cl_DF_to_SF,\ + F_OP(cl_SF_to_DF(arg1),arg2) ); \ + , /* arg2 LF */ \ + ergebnis_zuweisung CONCAT(MAP,r)(LF,cl_LF_to_SF,\ + F_OP(cl_SF_to_LF(arg1,CONCAT(LFlen,s)(arg2)),arg2) ); \ + ); \ + , /* arg1 FF */ \ + floatcase(arg2 \ + , /* arg2 SF */ \ + ergebnis_zuweisung CONCAT(MAP,r)(FF,cl_FF_to_SF,\ + F_OP(arg1,cl_SF_to_FF(arg2)) ); \ + , /* arg2 FF */ \ + ergebnis_zuweisung CONCAT(NOMAP,r)(FF, \ + F_OP(arg1,arg2) ); \ + , /* arg2 DF */ \ + ergebnis_zuweisung CONCAT(MAP,r)(DF,cl_DF_to_FF,\ + F_OP(cl_FF_to_DF(arg1),arg2) ); \ + , /* arg2 LF */ \ + ergebnis_zuweisung CONCAT(MAP,r)(LF,cl_LF_to_FF,\ + F_OP(cl_FF_to_LF(arg1,CONCAT(LFlen,s)(arg2)),arg2) ); \ + ); \ + , /* arg1 DF */ \ + floatcase(arg2 \ + , /* arg2 SF */ \ + ergebnis_zuweisung CONCAT(MAP,r)(DF,cl_DF_to_SF,\ + F_OP(arg1,cl_SF_to_DF(arg2)) ); \ + , /* arg2 FF */ \ + ergebnis_zuweisung CONCAT(MAP,r)(DF,cl_DF_to_FF,\ + F_OP(arg1,cl_FF_to_DF(arg2)) ); \ + , /* arg2 DF */ \ + ergebnis_zuweisung CONCAT(NOMAP,r)(DF, \ + F_OP(arg1,arg2) ); \ + , /* arg2 LF */ \ + ergebnis_zuweisung CONCAT(MAP,r)(LF,cl_LF_to_DF,\ + F_OP(cl_DF_to_LF(arg1,CONCAT(LFlen,s)(arg2)),arg2) ); \ + ); \ + , /* arg1 LF */ \ + floatcase(arg2 \ + , /* arg2 SF */ \ + ergebnis_zuweisung CONCAT(MAP,r)(LF,cl_LF_to_SF,\ + F_OP(arg1,cl_SF_to_LF(arg2,CONCAT(LFlen,s)(arg1))) ); \ + , /* arg2 FF */ \ + ergebnis_zuweisung CONCAT(MAP,r)(LF,cl_LF_to_FF,\ + F_OP(arg1,cl_FF_to_LF(arg2,CONCAT(LFlen,s)(arg1))) ); \ + , /* arg2 DF */ \ + ergebnis_zuweisung CONCAT(MAP,r)(LF,cl_LF_to_DF,\ + F_OP(arg1,cl_DF_to_LF(arg2,CONCAT(LFlen,s)(arg1))) ); \ + , /* arg2 LF */ \ + GEN_LF_OP2_AUX(arg1,arg2,F_OP,r,s,ergebnis_zuweisung) \ + ); \ + ); \ +} +#define GEN_LF_OP2_AUX(arg1,arg2,F_OP,r,s,ergebnis_zuweisung) \ + CONCAT(GEN_LF_OP2_AUX,s)(arg1,arg2,F_OP,r,ergebnis_zuweisung) +#define GEN_LF_OP2_AUX0(arg1,arg2,F_OP,r,ergebnis_zuweisung) \ + var uintC len1 = TheLfloat(arg1)->len; \ + var uintC len2 = TheLfloat(arg2)->len; \ + if (len1 == len2) /* gleich -> direkt ausführen */ \ + { ergebnis_zuweisung CONCAT(NOMAP,r) (LF, F_OP(arg1,arg2)); } \ + elif (len1 > len2) /* -> arg2 auf die Länge von arg1 bringen */ \ + { ergebnis_zuweisung CONCAT(MAP,r) (LF, LF_shorten_len2, \ + F_OP(arg1,extend(arg2,len1)) ); \ + } \ + else /* (len1 < len2) -> arg1 auf die Länge von arg2 bringen */ \ + { ergebnis_zuweisung CONCAT(MAP,r) (LF, LF_shorten_len1, \ + F_OP(extend(arg1,len2),arg2) ); \ + } +#define LF_shorten_len1(arg) shorten(arg,len1) +#define LF_shorten_len2(arg) shorten(arg,len2) +#define GEN_LF_OP2_AUX1(arg1,arg2,F_OP,r,ergebnis_zuweisung) \ + ergebnis_zuweisung CONCAT(NOMAP,r) (LF, F_OP(arg1,arg2)); + +#define NOMAP0(F,EXPR) EXPR +#define NOMAP1(F,EXPR) EXPR +#define MAP0(F,FN,EXPR) EXPR +#define MAP1(F,FN,EXPR) FN(EXPR) + +#define LFlen0(arg) TheLfloat(arg)->len +#define LFlen1(arg) LF_minlen + + +// cl_F_extendsqrt(x) erweitert die Genauigkeit eines Floats x um eine Stufe +// SF -> FF -> DF -> LF(4) -> LF(5) -> LF(6) -> ... +// Ein Float mit d Mantissenbits wird so zu einem Float mit +// mindestens d+sqrt(d)+2 Mantissenbits. +extern const cl_F cl_F_extendsqrt (const cl_F& x); + +// cl_F_extendsqrtx(x) erweitert die Genauigkeit eines Floats x um eine Stufe +// SF -> FF -> DF -> LF(4) -> LF(5) -> LF(6) -> ... +// Ein Float mit d Mantissenbits und l Exponentenbits wird so zu einem Float +// mit mindestens d+sqrt(d)+2+(l-1) Mantissenbits. +extern const cl_F cl_F_extendsqrtx (const cl_F& x); + +// cl_F_shortenrelative(x,y) tries to reduce the size of x, such that one +// wouldn't notice it when adding x to y. y must be /= 0. More precisely, +// this returns a float approximation of x, such that 1 ulp(x) < 1 ulp(y). +extern const cl_F cl_F_shortenrelative (const cl_F& x, const cl_F& y); + + +// Macro: dispatches according to a cl_float_format_t value. +// floatformatcase(value, SF_statement,FF_statement,DF_statement,LF_statement) +// LF_statement darf auf `len' zugreifen, die zu `value' korrespondierende +// Mantissenlänge (gemessen in Digits). + #define floatformatcase(value, SF_statement,FF_statement,DF_statement,LF_statement) \ + { if ((value) <= cl_float_format_sfloat) { SF_statement } \ + elif ((value) <= cl_float_format_ffloat) { FF_statement } \ + elif ((value) <= cl_float_format_dfloat) { DF_statement } \ + else { var uintL len = ceiling((uintL)(value),intDsize); LF_statement } \ + } + + +#endif /* _CL_F_H */ diff --git a/src/float/cl_float_config.h.in b/src/float/cl_float_config.h.in new file mode 100644 index 0000000..bc62a1e --- /dev/null +++ b/src/float/cl_float_config.h.in @@ -0,0 +1,20 @@ +// Defines OS dependent macros + +#ifndef _CL_FLOAT_CONFIG_H +#define _CL_FLOAT_CONFIG_H + +/* These definitions are adjusted by `configure' automatically. */ + + +/* functions and declarations */ + +/* CL_FPU_CONTROL */ +/* Define if you have and it defines the fpu_control_t type. */ +#undef HAVE_FPU_CONTROL_T +/* Define if you have and it declares the __setfpucw() + function. */ +#undef HAVE_SETFPUCW + + +#endif /* _CL_FLOAT_CONFIG_H */ + diff --git a/src/float/conv/Makeflags b/src/float/conv/Makeflags new file mode 100644 index 0000000..546ddeb --- /dev/null +++ b/src/float/conv/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/Makeflags +SUBDIR_INCLUDES += diff --git a/src/float/conv/cl_DF_to_FF.cc b/src/float/conv/cl_DF_to_FF.cc new file mode 100644 index 0000000..36c1aea --- /dev/null +++ b/src/float/conv/cl_DF_to_FF.cc @@ -0,0 +1,64 @@ +// cl_DF_to_FF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F.h" + + +// Implementation. + +#include "cl_DF.h" +#include "cl_FF.h" + +const cl_FF cl_DF_to_FF (const cl_DF& x) +{ + // x entpacken: + var cl_signean sign; + var sintL exp; + #if (cl_word_size==64) + var uint64 mant; + DF_decode(x, { return cl_FF_0; }, sign=,exp=,mant=); + // 52-23=29 Bits wegrunden: + var const int shiftcount = DF_mant_len-FF_mant_len; + if ( ((mant & bit(shiftcount-1)) ==0) // Bit 28 war 0 -> abrunden + || ( ((mant & (bit(shiftcount-1)-1)) ==0) // war 1, Bits 27..0 >0 -> aufrunden + // round-to-even + && ((mant & bit(shiftcount)) ==0) + ) ) + // abrunden + { mant = mant >> shiftcount; } + else + // aufrunden + { mant = mant >> shiftcount; + mant = mant+1; + if (mant >= bit(FF_mant_len+1)) + // Überlauf durchs Runden + { mant = mant>>1; exp = exp+1; } // Mantisse rechts schieben + } + return encode_FF(sign,exp,mant); + #else + var uint32 manthi; + var uint32 mantlo; + DF_decode2(x, { return cl_FF_0; }, sign=,exp=,manthi=,mantlo=); + // 52-23=29 Bits wegrunden: + var const int shiftcount = DF_mant_len-FF_mant_len; + manthi = (manthi << (32-shiftcount)) | (mantlo >> shiftcount); + if ( ((mantlo & bit(shiftcount-1)) ==0) // Bit 28 war 0 -> abrunden + || ( ((mantlo & (bit(shiftcount-1)-1)) ==0) // war 1, Bits 27..0 >0 -> aufrunden + // round-to-even + && ((mantlo & bit(shiftcount)) ==0) + ) ) + // abrunden + {} + else + // aufrunden + { manthi = manthi+1; + if (manthi >= bit(FF_mant_len+1)) + // Überlauf durchs Runden + { manthi = manthi>>1; exp = exp+1; } // Mantisse rechts schieben + } + return encode_FF(sign,exp,manthi); + #endif +} diff --git a/src/float/conv/cl_DF_to_LF.cc b/src/float/conv/cl_DF_to_LF.cc new file mode 100644 index 0000000..1a268f1 --- /dev/null +++ b/src/float/conv/cl_DF_to_LF.cc @@ -0,0 +1,47 @@ +// cl_DF_to_LF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F.h" + + +// Implementation. + +#include "cl_DF.h" +#include "cl_LF.h" +#include "cl_LF_impl.h" +#include "cl_DS.h" + +const cl_LF cl_DF_to_LF (const cl_DF& x, uintC len) +{ + // x entpacken: + var cl_signean sign; + var sintL exp; + #if (cl_word_size==64) + var uint64 mant; + DF_decode(x, { return encode_LF0(len); }, sign=,exp=(sintL),mant=); + #else + var uint32 manthi; + var uint32 mantlo; + DF_decode2(x, { return encode_LF0(len); }, sign=,exp=(sintL),manthi=,mantlo=); + #endif + // Long-Float allozieren, + // Mantisse mit intDsize*len-DF_mant_len-1 Nullbits auffüllen: + var Lfloat y = allocate_lfloat(len,exp+LF_exp_mid,sign); + var uintD* ptr = arrayMSDptr(TheLfloat(y)->data,len); + // erste k := ceiling(DF_mant_len+1,intDsize) Digits mit mant füllen: + var const int shiftcount = (ceiling(DF_mant_len+1,intDsize)*intDsize-(DF_mant_len+1)); + #if (cl_word_size==64) + mant = mant<>(32-shiftcount)); + mantlo = mantlo< abrunden + || ( ((mant & (bit(shiftcount-1)-1)) ==0) // war 1, Bits 34..0 >0 -> aufrunden + // round-to-even + && ((mant & bit(shiftcount)) ==0) + ) ) + // abrunden + { mant = mant >> shiftcount; } + else + // aufrunden + { mant = mant >> shiftcount; + mant = mant+1; + if (mant >= bit(SF_mant_len+1)) + // Überlauf durchs Runden + { mant = mant>>1; exp = exp+1; } // Mantisse rechts schieben + } + return encode_SF(sign,exp,mant); + #else + var uint32 manthi; + var uint32 mantlo; + DF_decode2(x, { return SF_0; }, sign=,exp=,manthi=,mantlo=); + // 52-16=36 Bits wegrunden: + var const int shiftcount = DF_mant_len-SF_mant_len-32; + if ( ((manthi & bit(shiftcount-1)) ==0) // Bit 35 war 0 -> abrunden + || ( ((manthi & (bit(shiftcount-1)-1)) ==0) // war 1, Bits 34..0 >0 -> aufrunden + && (mantlo==0) + // round-to-even + && ((manthi & bit(shiftcount)) ==0) + ) ) + // abrunden + { manthi = manthi >> shiftcount; } + else + // aufrunden + { manthi = manthi >> shiftcount; + manthi = manthi+1; + if (manthi >= bit(SF_mant_len+1)) + // Überlauf durchs Runden + { manthi = manthi>>1; exp = exp+1; } // Mantisse rechts schieben + } + return encode_SF(sign,exp,manthi); + #endif +} diff --git a/src/float/conv/cl_DF_to_double.cc b/src/float/conv/cl_DF_to_double.cc new file mode 100644 index 0000000..98dd214 --- /dev/null +++ b/src/float/conv/cl_DF_to_double.cc @@ -0,0 +1,53 @@ +// cl_DF_to_double(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#include "cl_DF.h" + +double cl_double_approx (const cl_DF& obj) +{ + union { dfloat eksplicit; double machine_double; } u; + #define val u.eksplicit + val = TheDfloat(obj)->dfloat_value; + // Der Exponent muß um DF_exp_mid-1022 erniedrigt werden. + if (DF_exp_mid>1022) + #if (cl_word_size==64) + { var uintL exp = (val >> DF_mant_len) & (bit(DF_exp_len)-1); // e + if (exp < DF_exp_mid-1022+1) + { // produziere denormalisiertes Float + val = (val & minus_bit(DF_exp_len+DF_mant_len)) // selbes Vorzeichen + | ((sint64)0 << DF_mant_len) // Exponent 0 + | (((val & (bit(DF_mant_len)-1)) | bit(DF_mant_len)) // Mantisse shiften + >> (DF_exp_mid-1022+1 - exp) // shiften + ); + } + else + { val -= (sint64)(DF_exp_mid - 1022) << DF_mant_len; } + } + #else + { var uintL exp = (val.semhi >> (DF_mant_len-32)) & (bit(DF_exp_len)-1); // e + if (exp < DF_exp_mid-1022+1) + { // produziere denormalisiertes Float + var uintL shiftcount = DF_exp_mid-1022+1 - exp; + val.mlo = val.mlo >> shiftcount; // Mantisse shiften + val.mlo |= val.semhi << (32-shiftcount); + val.semhi = (val.semhi & minus_bit(DF_exp_len+DF_mant_len-32)) // selbes Vorzeichen + | ((sint32)0 << (DF_mant_len-32)) // Exponent 0 + | (((val.semhi & (bit(DF_mant_len-32)-1)) | bit(DF_mant_len-32)) // Mantisse shiften + >> shiftcount // shiften + ); + } + else + { val.semhi -= (sint32)(DF_exp_mid - 1022) << (DF_mant_len-32); } + } + #endif + #undef val + return u.machine_double; +} diff --git a/src/float/conv/cl_DF_to_float.cc b/src/float/conv/cl_DF_to_float.cc new file mode 100644 index 0000000..fb2e48b --- /dev/null +++ b/src/float/conv/cl_DF_to_float.cc @@ -0,0 +1,72 @@ +// cl_DF_to_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#include "cl_DF.h" +#include "cl_FF.h" + +float cl_float_approx (const cl_DF& x) +{ + union { ffloat eksplicit; float machine_float; } u; + // x entpacken: + var cl_signean sign; + var sintL exp; + #if (cl_word_size==64) + var uint64 mant; + DF_decode(x, { return 0.0; }, sign=,exp=,mant=); + // 52-23=29 Bits wegrunden: + var const int shiftcount = DF_mant_len-FF_mant_len; + if ( ((mant & bit(shiftcount-1)) ==0) // Bit 28 war 0 -> abrunden + || ( ((mant & (bit(shiftcount-1)-1)) ==0) // war 1, Bits 27..0 >0 -> aufrunden + // round-to-even + && ((mant & bit(shiftcount)) ==0) + ) ) + // abrunden + { mant = mant >> shiftcount; } + else + // aufrunden + { mant = mant >> shiftcount; + mant = mant+1; + if (mant >= bit(FF_mant_len+1)) + // Überlauf durchs Runden + { mant = mant>>1; exp = exp+1; } // Mantisse rechts schieben + } + #else + var uint32 manthi; + var uint32 mantlo; + DF_decode2(x, { return 0.0; }, sign=,exp=,manthi=,mantlo=); + // 52-23=29 Bits wegrunden: + var const int shiftcount = DF_mant_len-FF_mant_len; + manthi = (manthi << (32-shiftcount)) | (mantlo >> shiftcount); + if ( ((mantlo & bit(shiftcount-1)) ==0) // Bit 28 war 0 -> abrunden + || ( ((mantlo & (bit(shiftcount-1)-1)) ==0) // war 1, Bits 27..0 >0 -> aufrunden + // round-to-even + && ((mantlo & bit(shiftcount)) ==0) + ) ) + // abrunden + {} + else + // aufrunden + { manthi = manthi+1; + if (manthi >= bit(FF_mant_len+1)) + // Überlauf durchs Runden + { manthi = manthi>>1; exp = exp+1; } // Mantisse rechts schieben + } + #define mant manthi + #endif + if (exp > (sintL)(FF_exp_high-FF_exp_mid)) + { u.eksplicit = make_FF_word(sign,bit(FF_exp_len)-1,0); } // Infinity + else + if (exp < (sintL)(FF_exp_low-FF_exp_mid)) + { u.eksplicit = make_FF_word(sign,0,0); } // 0.0 + else + { u.eksplicit = make_FF_word(sign,exp+FF_exp_mid,mant); } + return u.machine_float; +} diff --git a/src/float/conv/cl_FF_to_DF.cc b/src/float/conv/cl_FF_to_DF.cc new file mode 100644 index 0000000..7c717b9 --- /dev/null +++ b/src/float/conv/cl_FF_to_DF.cc @@ -0,0 +1,28 @@ +// cl_FF_to_DF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F.h" + + +// Implementation. + +#include "cl_FF.h" +#include "cl_DF.h" + +const cl_DF cl_FF_to_DF (const cl_FF& x) +{ + // x entpacken: + var cl_signean sign; + var sintL exp; + var uint32 mant; + FF_decode(x, { return cl_DF_0; }, sign=,exp=,mant=); + // Mantisse um 52-23=29 Nullbits erweitern: + #if (cl_word_size==64) + return encode_DF(sign,exp,(uint64)mant<<(DF_mant_len-FF_mant_len)); + #else + return encode_DF(sign,exp,mant>>(32-(DF_mant_len-FF_mant_len)),mant<<(DF_mant_len-FF_mant_len)); + #endif +} diff --git a/src/float/conv/cl_FF_to_LF.cc b/src/float/conv/cl_FF_to_LF.cc new file mode 100644 index 0000000..19a981f --- /dev/null +++ b/src/float/conv/cl_FF_to_LF.cc @@ -0,0 +1,41 @@ +// cl_FF_to_LF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F.h" + + +// Implementation. + +#include "cl_FF.h" +#include "cl_LF.h" +#include "cl_LF_impl.h" +#include "cl_DS.h" + +const cl_LF cl_FF_to_LF (const cl_FF& x, uintC len) +{ + // x entpacken: + var cl_signean sign; + var sintL exp; + #if (intDsize==64) + var uint64 mant; + #else + var uint32 mant; + #endif + FF_decode(x, { return encode_LF0(len); }, sign=,exp=(sintL),mant=); + // Long-Float allozieren, + // Mantisse mit intDsize*len-FF_mant_len-1 Nullbits auffüllen: + var Lfloat y = allocate_lfloat(len,exp+LF_exp_mid,sign); + var uintD* ptr = arrayMSDptr(TheLfloat(y)->data,len); + // erste k := ceiling(FF_mant_len+1,intDsize) Digits mit mant füllen: + mant = mant << (ceiling(FF_mant_len+1,intDsize)*intDsize-(FF_mant_len+1)); + #if (intDsize==64) + set_max64_Dptr(FF_mant_len+1,ptr,mant); + #else + set_max32_Dptr(FF_mant_len+1,ptr,mant); + #endif + clear_loop_msp(ptr mspop ceiling(FF_mant_len+1,intDsize),len-ceiling(FF_mant_len+1,intDsize)); + return y; +} diff --git a/src/float/conv/cl_FF_to_SF.cc b/src/float/conv/cl_FF_to_SF.cc new file mode 100644 index 0000000..7e84623 --- /dev/null +++ b/src/float/conv/cl_FF_to_SF.cc @@ -0,0 +1,40 @@ +// cl_FF_to_SF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F.h" + + +// Implementation. + +#include "cl_FF.h" +#include "cl_SF.h" + +const cl_SF cl_FF_to_SF (const cl_FF& x) +{ + // x entpacken: + var cl_signean sign; + var sintL exp; + var uint32 mant; + FF_decode(x, { return SF_0; }, sign=,exp=,mant=); + // 23-16 Bits wegrunden: + var const int shiftcount = FF_mant_len-SF_mant_len; + if ( ((mant & bit(shiftcount-1)) ==0) // Bit 6 war 0 -> abrunden + || ( ((mant & (bit(shiftcount-1)-1)) ==0) // war 1, Bits 5..0 >0 -> aufrunden + // round-to-even + && ((mant & bit(shiftcount)) ==0) + ) ) + // abrunden + { mant = mant >> shiftcount; } + else + // aufrunden + { mant = mant >> shiftcount; + mant = mant+1; + if (mant >= bit(SF_mant_len+1)) + // Überlauf durchs Runden + { mant = mant>>1; exp = exp+1; } // Mantisse rechts schieben + } + return encode_SF(sign,exp,mant); +} diff --git a/src/float/conv/cl_FF_to_double.cc b/src/float/conv/cl_FF_to_double.cc new file mode 100644 index 0000000..34f50c2 --- /dev/null +++ b/src/float/conv/cl_FF_to_double.cc @@ -0,0 +1,64 @@ +// cl_FF_to_double(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_FF.h" +#include "cl_DF.h" + +double cl_double_approx (const cl_FF& x) +{ + // x entpacken: + var cl_signean sign; + var sintL exp; + var uint32 mant; + FF_decode(x, { return 0.0; }, sign=,exp=,mant=); + // Mantisse um 52-23=29 Nullbits erweitern: + union { dfloat eksplicit; double machine_double; } u; + #if (cl_word_size==64) + if (((sintL)(FF_exp_high-FF_exp_mid) > (sintL)(DF_exp_high-DF_exp_mid)) + && (exp > (sintL)(DF_exp_high-DF_exp_mid))) + { u.eksplicit = + ((sint64)sign & bit(63)) + | ((uint64)(bit(DF_exp_len)-1) << DF_mant_len); // Infinity + } + else + if (((sintL)(FF_exp_low-FF_exp_mid) < (sintL)(DF_exp_low-DF_exp_mid)) + && (exp < (sintL)(DF_exp_low-DF_exp_mid))) + { u.eksplicit = ((sint64)sign & bit(63)); } // 0.0 + else + { u.eksplicit = + ((sint64)sign & bit(63)) /* Vorzeichen */ + | ((uint64)(exp+DF_exp_mid) << DF_mant_len) /* Exponent */ + | (((uint64)mant<<(DF_mant_len-FF_mant_len)) & (bit(DF_mant_len)-1)); /* Mantisse */ + } + #else + if (((sintL)(FF_exp_high-FF_exp_mid) > (sintL)(DF_exp_high-DF_exp_mid)) + && (exp > (sintL)(DF_exp_high-DF_exp_mid))) + { u.eksplicit.semhi = + ((sint32)sign & bit(31)) + | ((uint32)(bit(DF_exp_len)-1) << (DF_mant_len-32)); // Infinity + u.eksplicit.mlo = 0; + } + else + if (((sintL)(FF_exp_low-FF_exp_mid) < (sintL)(DF_exp_low-DF_exp_mid)) + && (exp < (sintL)(DF_exp_low-DF_exp_mid))) + { u.eksplicit.semhi = ((sint32)sign & bit(31)); // 0.0 + u.eksplicit.mlo = 0; + } + else + { u.eksplicit.semhi = + ((sint32)sign & bit(31)) /* Vorzeichen */ + | ((uint32)(exp+DF_exp_mid) << (DF_mant_len-32)) /* Exponent */ + | (((uint32)mant>>(32-(DF_mant_len-FF_mant_len))) & (bit(DF_mant_len-32)-1)); /* Mantisse */ + u.eksplicit.mlo = mant<<(DF_mant_len-FF_mant_len); + } + #endif + return u.machine_double; +} diff --git a/src/float/conv/cl_FF_to_float.cc b/src/float/conv/cl_FF_to_float.cc new file mode 100644 index 0000000..d7204bc --- /dev/null +++ b/src/float/conv/cl_FF_to_float.cc @@ -0,0 +1,35 @@ +// cl_FF_to_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_FF.h" + +float cl_float_approx (const cl_FF& obj) +{ + union { ffloat eksplicit; float machine_float; } u; + #define val u.eksplicit + val = cl_ffloat_value(obj); + // Der Exponent muß um FF_exp_mid-126 erniedrigt werden. + if (FF_exp_mid>126) + { var uintL exp = (val >> FF_mant_len) & (bit(FF_exp_len)-1); // e + if (exp < FF_exp_mid-126+1) + { // produziere denormalisiertes Float + val = (val & minus_bit(FF_exp_len+FF_mant_len)) // selbes Vorzeichen + | (0 << FF_mant_len) // Exponent 0 + | (((val & (bit(FF_mant_len)-1)) | bit(FF_mant_len)) // Mantisse shiften + >> (FF_exp_mid-126+1 - exp) // shiften + ); + } + else + { val -= (FF_exp_mid - 126) << FF_mant_len; } + } + #undef val + return u.machine_float; +} diff --git a/src/float/conv/cl_F_from_F.cc b/src/float/conv/cl_F_from_F.cc new file mode 100644 index 0000000..d96fb90 --- /dev/null +++ b/src/float/conv/cl_F_from_F.cc @@ -0,0 +1,23 @@ +// cl_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_LF.h" + +const cl_F cl_float (const cl_F& x, const cl_F& y) +{ + floattypecase(y + , return cl_F_to_SF(x); + , return cl_F_to_FF(x); + , return cl_F_to_DF(x); + , return cl_F_to_LF(x,TheLfloat(y)->len); + ); +} diff --git a/src/float/conv/cl_F_from_F_f.cc b/src/float/conv/cl_F_from_F_f.cc new file mode 100644 index 0000000..e8509e0 --- /dev/null +++ b/src/float/conv/cl_F_from_F_f.cc @@ -0,0 +1,22 @@ +// cl_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" + +const cl_F cl_float (const cl_F& x, cl_float_format_t f) +{ + floatformatcase((uintL)f + , return cl_F_to_SF(x); + , return cl_F_to_FF(x); + , return cl_F_to_DF(x); + , return cl_F_to_LF(x,len); + ); +} diff --git a/src/float/conv/cl_F_from_I.cc b/src/float/conv/cl_F_from_I.cc new file mode 100644 index 0000000..2e2ffcf --- /dev/null +++ b/src/float/conv/cl_F_from_I.cc @@ -0,0 +1,26 @@ +// cl_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_SF.h" +#include "cl_FF.h" +#include "cl_DF.h" +#include "cl_LF.h" + +const cl_F cl_float (const cl_I& x, const cl_F& y) +{ + floattypecase(y + , return cl_I_to_SF(x); + , return cl_I_to_FF(x); + , return cl_I_to_DF(x); + , return cl_I_to_LF(x,TheLfloat(y)->len); + ); +} diff --git a/src/float/conv/cl_F_from_I_def.cc b/src/float/conv/cl_F_from_I_def.cc new file mode 100644 index 0000000..18bd9f2 --- /dev/null +++ b/src/float/conv/cl_F_from_I_def.cc @@ -0,0 +1,26 @@ +// cl_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_SF.h" +#include "cl_FF.h" +#include "cl_DF.h" +#include "cl_LF.h" + +const cl_F cl_float (const cl_I& x) +{ + floatformatcase(cl_default_float_format + , return cl_I_to_SF(x); + , return cl_I_to_FF(x); + , return cl_I_to_DF(x); + , return cl_I_to_LF(x,len); + ); +} diff --git a/src/float/conv/cl_F_from_I_f.cc b/src/float/conv/cl_F_from_I_f.cc new file mode 100644 index 0000000..3c4fc50 --- /dev/null +++ b/src/float/conv/cl_F_from_I_f.cc @@ -0,0 +1,26 @@ +// cl_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_SF.h" +#include "cl_FF.h" +#include "cl_DF.h" +#include "cl_LF.h" + +const cl_F cl_float (const cl_I& x, cl_float_format_t f) +{ + floatformatcase((uintL)f + , return cl_I_to_SF(x); + , return cl_I_to_FF(x); + , return cl_I_to_DF(x); + , return cl_I_to_LF(x,len); + ); +} diff --git a/src/float/conv/cl_F_from_RA.cc b/src/float/conv/cl_F_from_RA.cc new file mode 100644 index 0000000..08bc77f --- /dev/null +++ b/src/float/conv/cl_F_from_RA.cc @@ -0,0 +1,26 @@ +// cl_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_SF.h" +#include "cl_FF.h" +#include "cl_DF.h" +#include "cl_LF.h" + +const cl_F cl_float (const cl_RA& x, const cl_F& y) +{ + floattypecase(y + , return cl_RA_to_SF(x); + , return cl_RA_to_FF(x); + , return cl_RA_to_DF(x); + , return cl_RA_to_LF(x,TheLfloat(y)->len); + ); +} diff --git a/src/float/conv/cl_F_from_RA_def.cc b/src/float/conv/cl_F_from_RA_def.cc new file mode 100644 index 0000000..8db48dc --- /dev/null +++ b/src/float/conv/cl_F_from_RA_def.cc @@ -0,0 +1,26 @@ +// cl_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_SF.h" +#include "cl_FF.h" +#include "cl_DF.h" +#include "cl_LF.h" + +const cl_F cl_float (const cl_RA& x) +{ + floatformatcase(cl_default_float_format + , return cl_RA_to_SF(x); + , return cl_RA_to_FF(x); + , return cl_RA_to_DF(x); + , return cl_RA_to_LF(x,len); + ); +} diff --git a/src/float/conv/cl_F_from_RA_f.cc b/src/float/conv/cl_F_from_RA_f.cc new file mode 100644 index 0000000..7dcd6dc --- /dev/null +++ b/src/float/conv/cl_F_from_RA_f.cc @@ -0,0 +1,26 @@ +// cl_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_SF.h" +#include "cl_FF.h" +#include "cl_DF.h" +#include "cl_LF.h" + +const cl_F cl_float (const cl_RA& x, cl_float_format_t f) +{ + floatformatcase((uintL)f + , return cl_RA_to_SF(x); + , return cl_RA_to_FF(x); + , return cl_RA_to_DF(x); + , return cl_RA_to_LF(x,len); + ); +} diff --git a/src/float/conv/cl_F_to_DF.cc b/src/float/conv/cl_F_to_DF.cc new file mode 100644 index 0000000..64f6143 --- /dev/null +++ b/src/float/conv/cl_F_to_DF.cc @@ -0,0 +1,22 @@ +// cl_F_to_DF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" + +const cl_DF cl_F_to_DF (const cl_F& x) +{ + floatcase(x + , return cl_SF_to_DF(x); + , return cl_FF_to_DF(x); + , return x; + , return cl_LF_to_DF(x); + ); +} diff --git a/src/float/conv/cl_F_to_FF.cc b/src/float/conv/cl_F_to_FF.cc new file mode 100644 index 0000000..004e4c1 --- /dev/null +++ b/src/float/conv/cl_F_to_FF.cc @@ -0,0 +1,22 @@ +// cl_F_to_FF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" + +const cl_FF cl_F_to_FF (const cl_F& x) +{ + floatcase(x + , return cl_SF_to_FF(x); + , return x; + , return cl_DF_to_FF(x); + , return cl_LF_to_FF(x); + ); +} diff --git a/src/float/conv/cl_F_to_LF.cc b/src/float/conv/cl_F_to_LF.cc new file mode 100644 index 0000000..1aa8eb6 --- /dev/null +++ b/src/float/conv/cl_F_to_LF.cc @@ -0,0 +1,23 @@ +// cl_F_to_LF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_LF.h" + +const cl_LF cl_F_to_LF (const cl_F& x, uintC len) +{ + floatcase(x + , return cl_SF_to_LF(x,len); + , return cl_FF_to_LF(x,len); + , return cl_DF_to_LF(x,len); + , return LF_to_LF(x,len); + ); +} diff --git a/src/float/conv/cl_F_to_SF.cc b/src/float/conv/cl_F_to_SF.cc new file mode 100644 index 0000000..5a7a274 --- /dev/null +++ b/src/float/conv/cl_F_to_SF.cc @@ -0,0 +1,22 @@ +// cl_F_to_SF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" + +const cl_SF cl_F_to_SF (const cl_F& x) +{ + floatcase(x + , return x; + , return cl_FF_to_SF(x); + , return cl_DF_to_SF(x); + , return cl_LF_to_SF(x); + ); +} diff --git a/src/float/conv/cl_F_to_double.cc b/src/float/conv/cl_F_to_double.cc new file mode 100644 index 0000000..3852fbf --- /dev/null +++ b/src/float/conv/cl_F_to_double.cc @@ -0,0 +1,26 @@ +// cl_F_to_double(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" + +double cl_double_approx (const cl_F& x) +{ + floatcase(x + , return cl_double_approx(x); + , return cl_double_approx(x); + , return cl_double_approx(x); + , return cl_double_approx(x); + ); +} diff --git a/src/float/conv/cl_F_to_float.cc b/src/float/conv/cl_F_to_float.cc new file mode 100644 index 0000000..ed6359c --- /dev/null +++ b/src/float/conv/cl_F_to_float.cc @@ -0,0 +1,26 @@ +// cl_F_to_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" + +float cl_float_approx (const cl_F& x) +{ + floatcase(x + , return cl_float_approx(x); + , return cl_float_approx(x); + , return cl_float_approx(x); + , return cl_float_approx(x); + ); +} diff --git a/src/float/conv/cl_LF_to_DF.cc b/src/float/conv/cl_LF_to_DF.cc new file mode 100644 index 0000000..8535f73 --- /dev/null +++ b/src/float/conv/cl_LF_to_DF.cc @@ -0,0 +1,75 @@ +// cl_LF_to_DF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F.h" + + +// Implementation. + +#include "cl_LF.h" +#include "cl_LF_impl.h" +#include "cl_DF.h" +#include "cl_DS.h" + +const cl_DF cl_LF_to_DF (const cl_LF& x) +{ + // x entpacken: + var cl_signean sign; + var sintL exp; + var uintD* ptr; + var uintC len; + LF_decode(x, { return cl_DF_0; }, sign=,exp=,ptr=,len=,); + // intDsize*len-DF_mant_len-1 Bits der Mantisse wegrunden: + // erste k := ceiling(DF_mant_len+2,intDsize) Digits nach manthi,mantlo holen: + var const int shiftcount = ceiling(DF_mant_len+2,intDsize)*intDsize-(DF_mant_len+1); + #if (cl_word_size==64) + var uint64 mant = get_max64_Dptr(DF_mant_len+2,ptr); + ptr = ptr mspop ceiling(DF_mant_len+2,intDsize); + if ( ((mant & bit(shiftcount-1)) ==0) // Bit 10 war 0 -> abrunden + || ( ((mant & (bit(shiftcount-1)-1)) ==0) // war 1, Bits 9..0 >0 -> aufrunden + && !test_loop_msp(ptr,len-ceiling(DF_mant_len+2,intDsize)) // weitere Bits /=0 -> aufrunden + // round-to-even + && ((mant & bit(shiftcount)) ==0) + ) ) + // abrunden + { mant = mant >> shiftcount; } + else + // aufrunden + { mant = mant >> shiftcount; + mant = mant+1; + if (mant >= bit(DF_mant_len+1)) + // Überlauf durchs Runden + { mant = mant>>1; exp = exp+1; } // Mantisse rechts schieben + } + return encode_DF(sign,exp,mant); + #else + var uint32 manthi = get_max32_Dptr(DF_mant_len+2-32,ptr); + var uint32 mantlo = get_32_Dptr(ptr mspop ceiling(DF_mant_len+2-32,intDsize)); + ptr = ptr mspop ceiling(DF_mant_len+2,intDsize); + if ( ((mantlo & bit(shiftcount-1)) ==0) // Bit 10 war 0 -> abrunden + || ( ((mantlo & (bit(shiftcount-1)-1)) ==0) // war 1, Bits 9..0 >0 -> aufrunden + && !test_loop_msp(ptr,len-ceiling(DF_mant_len+2,intDsize)) // weitere Bits /=0 -> aufrunden + // round-to-even + && ((mantlo & bit(shiftcount)) ==0) + ) ) + // abrunden + { mantlo = (manthi << (32-shiftcount)) | (mantlo >> shiftcount); + manthi = manthi >> shiftcount; + } + else + // aufrunden + { mantlo = (manthi << (32-shiftcount)) | (mantlo >> shiftcount); + manthi = manthi >> shiftcount; + mantlo = mantlo+1; + if (mantlo==0) + { manthi = manthi+1; + if (manthi >= bit(DF_mant_len+1-32)) + // Überlauf durchs Runden + { manthi = manthi>>1; exp = exp+1; } // Mantisse rechts schieben + } } + return encode_DF(sign,exp,manthi,mantlo); + #endif +} diff --git a/src/float/conv/cl_LF_to_FF.cc b/src/float/conv/cl_LF_to_FF.cc new file mode 100644 index 0000000..5c30d5e --- /dev/null +++ b/src/float/conv/cl_LF_to_FF.cc @@ -0,0 +1,51 @@ +// cl_LF_to_FF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F.h" + + +// Implementation. + +#include "cl_LF.h" +#include "cl_LF_impl.h" +#include "cl_FF.h" +#include "cl_DS.h" + +const cl_FF cl_LF_to_FF (const cl_LF& x) +{ + // x entpacken: + var cl_signean sign; + var sintL exp; + var uintD* ptr; + var uintC len; + LF_decode(x, { return cl_FF_0; }, sign=,exp=,ptr=,len=,); + // intDsize*len-FF_mant_len-1 Bits der Mantisse wegrunden: + // erste k := ceiling(FF_mant_len+2,intDsize) Digits nach mant holen: + #if (intDsize==64) + var uint64 mant = get_max64_Dptr(FF_mant_len+2,ptr); + #else + var uint32 mant = get_max32_Dptr(FF_mant_len+2,ptr); + #endif + ptr = ptr mspop ceiling(FF_mant_len+2,intDsize); + var const int shiftcount = ceiling(FF_mant_len+2,intDsize)*intDsize-(FF_mant_len+1); + if ( ((mant & bit(shiftcount-1)) ==0) // Bit 7 war 0 -> abrunden + || ( ((mant & (bit(shiftcount-1)-1)) ==0) // war 1, Bits 6..0 >0 -> aufrunden + && !test_loop_msp(ptr,len-ceiling(FF_mant_len+2,intDsize)) // weitere Bits /=0 -> aufrunden + // round-to-even + && ((mant & bit(shiftcount)) ==0) + ) ) + // abrunden + { mant = mant >> shiftcount; } + else + // aufrunden + { mant = mant >> shiftcount; + mant = mant+1; + if (mant >= bit(FF_mant_len+1)) + // Überlauf durchs Runden + { mant = mant>>1; exp = exp+1; } // Mantisse rechts schieben + } + return encode_FF(sign,exp,mant); +} diff --git a/src/float/conv/cl_LF_to_SF.cc b/src/float/conv/cl_LF_to_SF.cc new file mode 100644 index 0000000..c5de4c5 --- /dev/null +++ b/src/float/conv/cl_LF_to_SF.cc @@ -0,0 +1,51 @@ +// cl_LF_to_SF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F.h" + + +// Implementation. + +#include "cl_LF.h" +#include "cl_LF_impl.h" +#include "cl_SF.h" +#include "cl_DS.h" + +const cl_SF cl_LF_to_SF (const cl_LF& x) +{ + // x entpacken: + var cl_signean sign; + var sintL exp; + var uintD* ptr; + var uintC len; + LF_decode(x, { return SF_0; }, sign=,exp=,ptr=,len=,); + // intDsize*len-SF_mant_len-1 Bits der Mantisse wegrunden: + // erste k := ceiling(SF_mant_len+2,intDsize) Digits nach mant holen: + #if (intDsize==64) + var uint64 mant = get_max64_Dptr(SF_mant_len+2,ptr); + #else + var uint32 mant = get_max32_Dptr(SF_mant_len+2,ptr); + #endif + ptr = ptr mspop ceiling(SF_mant_len+2,intDsize); + var const int shiftcount = ceiling(SF_mant_len+2,intDsize)*intDsize-(SF_mant_len+1); + if ( ((mant & bit(shiftcount-1)) ==0) // Bit 14 war 0 -> abrunden + || ( ((mant & (bit(shiftcount-1)-1)) ==0) // war 1, Bits 13..0 >0 -> aufrunden + && !test_loop_msp(ptr,len-ceiling(SF_mant_len+2,intDsize)) // weitere Bits /=0 -> aufrunden + // round-to-even + && ((mant & bit(shiftcount)) ==0) + ) ) + // abrunden + { mant = mant >> shiftcount; } + else + // aufrunden + { mant = mant >> shiftcount; + mant = mant+1; + if (mant >= bit(SF_mant_len+1)) + // Überlauf durchs Runden + { mant = mant>>1; exp = exp+1; } // Mantisse rechts schieben + } + return encode_SF(sign,exp,mant); +} diff --git a/src/float/conv/cl_LF_to_double.cc b/src/float/conv/cl_LF_to_double.cc new file mode 100644 index 0000000..5228c9b --- /dev/null +++ b/src/float/conv/cl_LF_to_double.cc @@ -0,0 +1,107 @@ +// cl_LF_to_double(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" +#include "cl_LF_impl.h" +#include "cl_DF.h" +#include "cl_DS.h" + +double cl_double_approx (const cl_LF& x) +{ + // x entpacken: + var cl_signean sign; + var sintL exp; + var uintD* ptr; + var uintC len; + LF_decode(x, { return 0.0; }, sign=,exp=,ptr=,len=,); + // intDsize*len-DF_mant_len-1 Bits der Mantisse wegrunden: + // erste k := ceiling(DF_mant_len+2,intDsize) Digits nach manthi,mantlo holen: + var const int shiftcount = ceiling(DF_mant_len+2,intDsize)*intDsize-(DF_mant_len+1); + union { dfloat eksplicit; double machine_double; } u; + #if (cl_word_size==64) + var uint64 mant = get_max64_Dptr(DF_mant_len+2,ptr); + ptr = ptr mspop ceiling(DF_mant_len+2,intDsize); + if ( ((mant & bit(shiftcount-1)) ==0) // Bit 10 war 0 -> abrunden + || ( ((mant & (bit(shiftcount-1)-1)) ==0) // war 1, Bits 9..0 >0 -> aufrunden + && !test_loop_msp(ptr,len-ceiling(DF_mant_len+2,intDsize)) // weitere Bits /=0 -> aufrunden + // round-to-even + && ((mant & bit(shiftcount)) ==0) + ) ) + // abrunden + { mant = mant >> shiftcount; } + else + // aufrunden + { mant = mant >> shiftcount; + mant = mant+1; + if (mant >= bit(DF_mant_len+1)) + // Überlauf durchs Runden + { mant = mant>>1; exp = exp+1; } // Mantisse rechts schieben + } + if (exp > (sintL)(DF_exp_high-DF_exp_mid)) + { u.eksplicit = + ((sint64)sign & bit(63)) + | ((uint64)(bit(DF_exp_len)-1) << DF_mant_len); // Infinity + } + else + if (exp < (sintL)(DF_exp_low-DF_exp_mid)) + { u.eksplicit = ((sint64)sign & bit(63)); } // 0.0 + else + { u.eksplicit = + ((sint64)sign & bit(63)) /* Vorzeichen */ + | ((uint64)(exp+DF_exp_mid) << DF_mant_len) /* Exponent */ + | ((uint64)mant & (bit(DF_mant_len)-1)); /* Mantisse */ + } + #else + var uint32 manthi = get_max32_Dptr(DF_mant_len+2-32,ptr); + var uint32 mantlo = get_32_Dptr(ptr mspop ceiling(DF_mant_len+2-32,intDsize)); + ptr = ptr mspop ceiling(DF_mant_len+2,intDsize); + if ( ((mantlo & bit(shiftcount-1)) ==0) // Bit 10 war 0 -> abrunden + || ( ((mantlo & (bit(shiftcount-1)-1)) ==0) // war 1, Bits 9..0 >0 -> aufrunden + && !test_loop_msp(ptr,len-ceiling(DF_mant_len+2,intDsize)) // weitere Bits /=0 -> aufrunden + // round-to-even + && ((mantlo & bit(shiftcount)) ==0) + ) ) + // abrunden + { mantlo = (manthi << (32-shiftcount)) | (mantlo >> shiftcount); + manthi = manthi >> shiftcount; + } + else + // aufrunden + { mantlo = (manthi << (32-shiftcount)) | (mantlo >> shiftcount); + manthi = manthi >> shiftcount; + mantlo = mantlo+1; + if (mantlo==0) + { manthi = manthi+1; + if (manthi >= bit(DF_mant_len+1-32)) + // Überlauf durchs Runden + { manthi = manthi>>1; exp = exp+1; } // Mantisse rechts schieben + } } + if (exp > (sintL)(DF_exp_high-DF_exp_mid)) + { u.eksplicit.semhi = + ((sint32)sign & bit(31)) + | ((uint32)(bit(DF_exp_len)-1) << (DF_mant_len-32)); // Infinity + u.eksplicit.mlo = 0; + } + else + if (exp < (sintL)(DF_exp_low-DF_exp_mid)) + { u.eksplicit.semhi = ((sint32)sign & bit(31)); // 0.0 + u.eksplicit.mlo = 0; + } + else + { u.eksplicit.semhi = + ((sint32)sign & bit(31)) /* Vorzeichen */ + | ((uint32)(exp+DF_exp_mid) << (DF_mant_len-32)) /* Exponent */ + | ((uint32)manthi & (bit(DF_mant_len-32)-1)); /* Mantisse */ + u.eksplicit.mlo = mantlo; + } + #endif + return u.machine_double; +} diff --git a/src/float/conv/cl_LF_to_float.cc b/src/float/conv/cl_LF_to_float.cc new file mode 100644 index 0000000..53d4263 --- /dev/null +++ b/src/float/conv/cl_LF_to_float.cc @@ -0,0 +1,59 @@ +// cl_LF_to_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" +#include "cl_LF_impl.h" +#include "cl_FF.h" +#include "cl_DS.h" + +float cl_float_approx (const cl_LF& x) +{ + // x entpacken: + var cl_signean sign; + var sintL exp; + var uintD* ptr; + var uintC len; + LF_decode(x, { return 0.0; }, sign=,exp=,ptr=,len=,); + // intDsize*len-FF_mant_len-1 Bits der Mantisse wegrunden: + // erste k := ceiling(FF_mant_len+2,intDsize) Digits nach mant holen: + #if (intDsize==64) + var uint64 mant = get_max64_Dptr(FF_mant_len+2,ptr); + #else + var uint32 mant = get_max32_Dptr(FF_mant_len+2,ptr); + #endif + ptr = ptr mspop ceiling(FF_mant_len+2,intDsize); + var const int shiftcount = ceiling(FF_mant_len+2,intDsize)*intDsize-(FF_mant_len+1); + if ( ((mant & bit(shiftcount-1)) ==0) // Bit 7 war 0 -> abrunden + || ( ((mant & (bit(shiftcount-1)-1)) ==0) // war 1, Bits 6..0 >0 -> aufrunden + && !test_loop_msp(ptr,len-ceiling(FF_mant_len+2,intDsize)) // weitere Bits /=0 -> aufrunden + // round-to-even + && ((mant & bit(shiftcount)) ==0) + ) ) + // abrunden + { mant = mant >> shiftcount; } + else + // aufrunden + { mant = mant >> shiftcount; + mant = mant+1; + if (mant >= bit(FF_mant_len+1)) + // Überlauf durchs Runden + { mant = mant>>1; exp = exp+1; } // Mantisse rechts schieben + } + union { ffloat eksplicit; float machine_float; } u; + if (exp > (sintL)(FF_exp_high-FF_exp_mid)) + { u.eksplicit = make_FF_word(sign,bit(FF_exp_len)-1,0); } // Infinity + else + if (exp < (sintL)(FF_exp_low-FF_exp_mid)) + { u.eksplicit = make_FF_word(sign,0,0); } // 0.0 + else + { u.eksplicit = make_FF_word(sign,exp+FF_exp_mid,mant); } + return u.machine_float; +} diff --git a/src/float/conv/cl_SF_to_DF.cc b/src/float/conv/cl_SF_to_DF.cc new file mode 100644 index 0000000..34211a5 --- /dev/null +++ b/src/float/conv/cl_SF_to_DF.cc @@ -0,0 +1,28 @@ +// cl_SF_to_DF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F.h" + + +// Implementation. + +#include "cl_SF.h" +#include "cl_DF.h" + +const cl_DF cl_SF_to_DF (const cl_SF& x) +{ + // x entpacken: + var cl_signean sign; + var sintL exp; + var uint32 mant; + SF_decode(x, { return cl_DF_0; }, sign=,exp=,mant=); + // Mantisse um 52-16=36 Nullbits erweitern: + #if (cl_word_size==64) + return encode_DF(sign,exp,(uint64)mant<<(DF_mant_len-SF_mant_len)); + #else + return encode_DF(sign,exp,mant<<(DF_mant_len-SF_mant_len-32),0); + #endif +} diff --git a/src/float/conv/cl_SF_to_FF.cc b/src/float/conv/cl_SF_to_FF.cc new file mode 100644 index 0000000..de034f5 --- /dev/null +++ b/src/float/conv/cl_SF_to_FF.cc @@ -0,0 +1,24 @@ +// cl_SF_to_FF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F.h" + + +// Implementation. + +#include "cl_SF.h" +#include "cl_FF.h" + +const cl_FF cl_SF_to_FF (const cl_SF& x) +{ + // x entpacken: + var cl_signean sign; + var sintL exp; + var uint32 mant; + SF_decode(x, { return cl_FF_0; }, sign=,exp=,mant=); + // Mantisse um 23-16=7 Bits nach links schieben: + return encode_FF(sign,exp,mant<<(FF_mant_len-SF_mant_len)); +} diff --git a/src/float/conv/cl_SF_to_LF.cc b/src/float/conv/cl_SF_to_LF.cc new file mode 100644 index 0000000..f339705 --- /dev/null +++ b/src/float/conv/cl_SF_to_LF.cc @@ -0,0 +1,41 @@ +// cl_SF_to_LF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F.h" + + +// Implementation. + +#include "cl_SF.h" +#include "cl_LF.h" +#include "cl_LF_impl.h" +#include "cl_DS.h" + +const cl_LF cl_SF_to_LF (const cl_SF& x, uintC len) +{ + // x entpacken: + var cl_signean sign; + var sintL exp; + #if (intDsize==64) + var uint64 mant; + #else + var uint32 mant; + #endif + SF_decode(x, { return encode_LF0(len); }, sign=,exp=(sintL),mant=); + // Long-Float allozieren, + // Mantisse mit intDsize*len-SF_mant_len-1 Nullbits auffüllen: + var Lfloat y = allocate_lfloat(len,exp+LF_exp_mid,sign); + var uintD* ptr = arrayMSDptr(TheLfloat(y)->data,len); + // erste k := ceiling(SF_mant_len+1,intDsize) Digits mit mant füllen: + mant = mant << (ceiling(SF_mant_len+1,intDsize)*intDsize-(SF_mant_len+1)); + #if (intDsize==64) + set_max64_Dptr(SF_mant_len+1,ptr,mant); + #else + set_max32_Dptr(SF_mant_len+1,ptr,mant); + #endif + clear_loop_msp(ptr mspop ceiling(SF_mant_len+1,intDsize),len-ceiling(SF_mant_len+1,intDsize)); + return y; +} diff --git a/src/float/conv/cl_SF_to_double.cc b/src/float/conv/cl_SF_to_double.cc new file mode 100644 index 0000000..c27d798 --- /dev/null +++ b/src/float/conv/cl_SF_to_double.cc @@ -0,0 +1,64 @@ +// cl_SF_to_double(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#include "cl_SF.h" +#include "cl_DF.h" + +double cl_double_approx (const cl_SF& x) +{ + // x entpacken: + var cl_signean sign; + var sintL exp; + var uint32 mant; + SF_decode(x, { return 0.0; }, sign=,exp=,mant=); + // Mantisse um 52-16=36 Nullbits erweitern: + union { dfloat eksplicit; double machine_double; } u; + #if (cl_word_size==64) + if (((sintL)(SF_exp_high-SF_exp_mid) > (sintL)(DF_exp_high-DF_exp_mid)) + && (exp > (sintL)(DF_exp_high-DF_exp_mid))) + { u.eksplicit = + ((sint64)sign & bit(63)) + | ((uint64)(bit(DF_exp_len)-1) << DF_mant_len); // Infinity + } + else + if (((sintL)(SF_exp_low-SF_exp_mid) < (sintL)(DF_exp_low-DF_exp_mid)) + && (exp < (sintL)(DF_exp_low-DF_exp_mid))) + { u.eksplicit = ((sint64)sign & bit(63)); } // 0.0 + else + { u.eksplicit = + ((sint64)sign & bit(63)) /* Vorzeichen */ + | ((uint64)(exp+DF_exp_mid) << DF_mant_len) /* Exponent */ + | (((uint64)mant<<(DF_mant_len-SF_mant_len)) & (bit(DF_mant_len)-1)); /* Mantisse */ + } + #else + if (((sintL)(SF_exp_high-SF_exp_mid) > (sintL)(DF_exp_high-DF_exp_mid)) + && (exp > (sintL)(DF_exp_high-DF_exp_mid))) + { u.eksplicit.semhi = + ((sint32)sign & bit(31)) + | ((uint32)(bit(DF_exp_len)-1) << (DF_mant_len-32)); // Infinity + u.eksplicit.mlo = 0; + } + else + if (((sintL)(SF_exp_low-SF_exp_mid) < (sintL)(DF_exp_low-DF_exp_mid)) + && (exp < (sintL)(DF_exp_low-DF_exp_mid))) + { u.eksplicit.semhi = ((sint32)sign & bit(31)); // 0.0 + u.eksplicit.mlo = 0; + } + else + { u.eksplicit.semhi = + ((sint32)sign & bit(31)) /* Vorzeichen */ + | ((uint32)(exp+DF_exp_mid) << (DF_mant_len-32)) /* Exponent */ + | (((uint32)mant<<(DF_mant_len-SF_mant_len-32)) & (bit(DF_mant_len-32)-1)); /* Mantisse */ + u.eksplicit.mlo = 0; + } + #endif + return u.machine_double; +} diff --git a/src/float/conv/cl_SF_to_float.cc b/src/float/conv/cl_SF_to_float.cc new file mode 100644 index 0000000..7bb07dd --- /dev/null +++ b/src/float/conv/cl_SF_to_float.cc @@ -0,0 +1,34 @@ +// cl_SF_to_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#include "cl_SF.h" +#include "cl_FF.h" + +float cl_float_approx (const cl_SF& x) +{ + // x entpacken: + var cl_signean sign; + var sintL exp; + var uint32 mant; + SF_decode(x, { return 0.0; }, sign=,exp=,mant=); + // Mantisse um 23-16=7 Bits nach links schieben: + union { ffloat eksplicit; float machine_float; } u; + if (((sintL)(SF_exp_high-SF_exp_mid) > (sintL)(FF_exp_high-FF_exp_mid)) + && (exp > (sintL)(FF_exp_high-FF_exp_mid))) + { u.eksplicit = make_FF_word(sign,bit(FF_exp_len)-1,0); } // Infinity + else + if (((sintL)(SF_exp_low-SF_exp_mid) < (sintL)(FF_exp_low-FF_exp_mid)) + && (exp < (sintL)(FF_exp_low-FF_exp_mid))) + { u.eksplicit = make_FF_word(sign,0,0); } // 0.0 + else + { u.eksplicit = make_FF_word(sign,exp+FF_exp_mid,mant<<(FF_mant_len-SF_mant_len)); } + return u.machine_float; +} diff --git a/src/float/dfloat/Makeflags b/src/float/dfloat/Makeflags new file mode 100644 index 0000000..ec29e37 --- /dev/null +++ b/src/float/dfloat/Makeflags @@ -0,0 +1,3 @@ +# This file contains additional flags for the main Makefile. + +SUBDIR_INCLUDES = -I$(srcdir)/float/dfloat -I$(srcdir)/float -I$(srcdir)/base diff --git a/src/float/dfloat/algebraic/Makeflags b/src/float/dfloat/algebraic/Makeflags new file mode 100644 index 0000000..031a738 --- /dev/null +++ b/src/float/dfloat/algebraic/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/dfloat/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/base/digitseq -I$(srcdir)/base/digit -Ibase $(GMP_INCLUDES) diff --git a/src/float/dfloat/algebraic/cl_DF_sqrt.cc b/src/float/dfloat/algebraic/cl_DF_sqrt.cc new file mode 100644 index 0000000..a8c1b74 --- /dev/null +++ b/src/float/dfloat/algebraic/cl_DF_sqrt.cc @@ -0,0 +1,148 @@ +// sqrt(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#include "cl_DF.h" +#include "cl_F.h" +#include "cl_low.h" +#include "cl_DS.h" + +const cl_DF sqrt (const cl_DF& x) +{ +// Methode: +// x = 0.0 -> Ergebnis 0.0 +// Ergebnis-Vorzeichen := positiv, +// Ergebnis-Exponent := ceiling(e/2), +// Ergebnis-Mantisse: +// Bilde aus [1,m51,...,m0,(55 Nullbits)] bei geradem e, +// aus [0,1,m51,...,m0,(54 Nullbits)] bei ungeradem e +// die Ganzzahl-Wurzel, eine 54-Bit-Zahl mit einer führenden 1. +// Runde das letzte Bit weg: +// Bit 0 = 0 -> abrunden, +// Bit 0 = 1 und Wurzel exakt -> round-to-even, +// Bit 0 = 1 und Rest >0 -> aufrunden. +// Dabei um ein Bit nach rechts schieben. +// Bei Aufrundung auf 2^53 (rounding overflow) Mantisse um 1 Bit nach rechts +// schieben und Exponent incrementieren. +#if (cl_word_size==64) + // x entpacken: + var sintL exp; + var uint64 mantx; + DF_decode(x, { return x; }, ,exp=,mantx=); + // Um die 128-Bit-Ganzzahl-Wurzel ausnutzen zu können, fügen wir beim + // Radikanden 74 bzw. 75 statt 54 bzw. 55 Nullbits an. + if (exp & bit(0)) + // e ungerade + { mantx = mantx << (63-(DF_mant_len+1)); exp = exp+1; } + else + // e gerade + { mantx = mantx << (64-(DF_mant_len+1)); } + exp = exp >> 1; // exp := exp/2 + var uintD mant [128/intDsize]; + #if (intDsize==64) + arrayLSref(mant,128/intDsize,1) = mantx; + arrayLSref(mant,128/intDsize,0) = 0; + #else // (intDsize<=32) + set_32_Dptr(arrayMSDptr(mant,128/intDsize),(uint32)(mantx>>32)); + set_32_Dptr(arrayMSDptr(mant,128/intDsize) mspop 32/intDsize,(uint32)mantx); + set_32_Dptr(arrayMSDptr(mant,128/intDsize) mspop 2*32/intDsize,0); + set_32_Dptr(arrayMSDptr(mant,128/intDsize) mspop 3*32/intDsize,0); + #endif + {CL_ALLOCA_STACK; + var DS wurzel; + var cl_boolean exactp; + UDS_sqrt(arrayMSDptr(mant,128/intDsize),128/intDsize,arrayLSDptr(mant,128/intDsize), &wurzel, exactp=); + // wurzel = isqrt(2^74_75 * mant), eine 64-Bit-Zahl. + mantx = get_64_Dptr(wurzel.MSDptr); + // Die hinteren 63-DF_mant_len Bits wegrunden: + if ( ((mantx & bit(62-DF_mant_len)) ==0) // Bit 10 =0 -> abrunden + || ( ((mantx & (bit(62-DF_mant_len)-1)) ==0) // Bit 10 =1 und Bits 9..0 >0 -> aufrunden + && exactp // Bit 10 =1 und Bits 9..0 =0, aber Rest -> aufrunden + // round-to-even, je nach Bit 11 : + && ((mantx & bit(63-DF_mant_len)) ==0) + ) ) + // abrunden + { mantx = mantx >> (63-DF_mant_len); } + else + // aufrunden + { mantx = mantx >> (63-DF_mant_len); + mantx += 1; + if (mantx >= bit(DF_mant_len+1)) // rounding overflow? + { mantx = mantx>>1; exp = exp+1; } + } + } + return encode_DF(0,exp,mantx); +#else + // x entpacken: + var sintL exp; + var uint32 manthi; + var uint32 mantlo; + DF_decode2(x, { return x; }, ,exp=,manthi=,mantlo=); + // Um die 128-Bit-Ganzzahl-Wurzel ausnutzen zu können, fügen wir beim + // Radikanden 74 bzw. 75 statt 54 bzw. 55 Nullbits an. + if (exp & bit(0)) + // e ungerade + { manthi = (manthi << (63-(DF_mant_len+1))) | (mantlo >> ((DF_mant_len+1)-31)); + mantlo = mantlo << (63-(DF_mant_len+1)); + exp = exp+1; + } + else + // e gerade + { manthi = (manthi << (64-(DF_mant_len+1))) | (mantlo >> ((DF_mant_len+1)-32)); + mantlo = mantlo << (64-(DF_mant_len+1)); + } + exp = exp >> 1; // exp := exp/2 + var uintD mant [128/intDsize]; + #if (intDsize==32) || (intDsize==16) || (intDsize==8) + set_32_Dptr(arrayMSDptr(mant,128/intDsize),manthi); + set_32_Dptr(arrayMSDptr(mant,128/intDsize) mspop 32/intDsize,mantlo); + set_32_Dptr(arrayMSDptr(mant,128/intDsize) mspop 2*32/intDsize,0); + set_32_Dptr(arrayMSDptr(mant,128/intDsize) mspop 3*32/intDsize,0); + #else + {var uintD* ptr; + ptr = arrayLSDptr(mant,128/intDsize); + doconsttimes(64/intDsize, { lsprefnext(ptr) = 0; } ); + doconsttimes(32/intDsize, { lsprefnext(ptr) = (uintD)mantlo; mantlo = mantlo>>intDsize; } ); + doconsttimes(32/intDsize, { lsprefnext(ptr) = (uintD)manthi; manthi = manthi>>intDsize; } ); + } + #endif + {CL_ALLOCA_STACK; + var DS wurzel; + var cl_boolean exactp; + UDS_sqrt(arrayMSDptr(mant,128/intDsize),128/intDsize,arrayLSDptr(mant,128/intDsize), &wurzel, exactp=); + // wurzel = isqrt(2^74_75 * mant), eine 64-Bit-Zahl. + {var uintD* ptr = wurzel.MSDptr; + manthi = get_32_Dptr(ptr); mantlo = get_32_Dptr(ptr mspop 32/intDsize); + } + // Die hinteren 63-DF_mant_len Bits wegrunden: + if ( ((mantlo & bit(62-DF_mant_len)) ==0) // Bit 10 =0 -> abrunden + || ( ((mantlo & (bit(62-DF_mant_len)-1)) ==0) // Bit 10 =1 und Bits 9..0 >0 -> aufrunden + && exactp // Bit 10 =1 und Bits 9..0 =0, aber Rest -> aufrunden + // round-to-even, je nach Bit 11 : + && ((mantlo & bit(63-DF_mant_len)) ==0) + ) ) + // abrunden + { mantlo = (mantlo >> (63-DF_mant_len)) | (manthi << (DF_mant_len-32+1)); + manthi = manthi >> (63-DF_mant_len); + } + else + // aufrunden + { mantlo = (mantlo >> (63-DF_mant_len)) | (manthi << (DF_mant_len-32+1)); + manthi = manthi >> (63-DF_mant_len); + mantlo += 1; + if (mantlo==0) + { manthi += 1; + if (manthi >= bit(DF_mant_len-32+1)) // rounding overflow? + { manthi = manthi>>1; exp = exp+1; } + } } + } + return encode_DF(0,exp,manthi,mantlo); +#endif +} diff --git a/src/float/dfloat/cl_DF.h b/src/float/dfloat/cl_DF.h new file mode 100644 index 0000000..1cb7870 --- /dev/null +++ b/src/float/dfloat/cl_DF.h @@ -0,0 +1,308 @@ +// cl_DF internals + +#ifndef _CL_DF_H +#define _CL_DF_H + +#include "cl_number.h" +#include "cl_malloc.h" +#include "cl_low.h" +#include "cl_F.h" + +typedef // 64-bit float in IEEE format + #if (cl_word_size==64) + // Sign/Exponent/Mantissa + uint64 + #else + // Sign/Exponent/MantissaHigh and MantissaLow + #if CL_CPU_BIG_ENDIAN_P + struct { uint32 semhi, mlo; } + #else + struct { uint32 mlo, semhi; } + #endif + #endif + dfloat; + +union dfloatjanus { + dfloat eksplicit; // explicit value + #ifdef FAST_DOUBLE + double machine_double; // value as a C `double' + #endif +}; +struct cl_heap_dfloat : cl_heap { + dfloatjanus representation; +}; +inline cl_heap_dfloat* TheDfloat (const cl_number& obj) + { return (cl_heap_dfloat*)(obj.pointer); } +inline dfloat& cl_dfloat_value (/* const ?? */ cl_DF& x) +{ + return TheDfloat(x)->representation.eksplicit; +} + +// The double-word contains: +// |..|.......|........................................| +// sign exponent mantissa + + #define DF_exp_len 11 // number of bits in the exponent + #define DF_mant_len 52 // number of bits in the mantissa + // (excluding the hidden bit) + #define DF_exp_low 1 // minimum exponent + #define DF_exp_mid 1022 // exponent bias + #define DF_exp_high 2046 // maximum exponent, 2047 is NaN/Inf + #define DF_exp_shift (DF_mant_len+DF_mant_shift) // lowest exponent bit + #define DF_mant_shift 0 // lowest mantissa bit + #define DF_sign_shift (64 - 1) // = (DF_exp_len+DF_mant_len) + +// Private constructor. +inline cl_DF::cl_DF (cl_heap_dfloat* ptr) : cl_F ((cl_private_thing) ptr) {} + +extern cl_class cl_class_dfloat; + +// Builds a float from the explicit words. +#if (cl_word_size==64) +inline cl_heap_dfloat* allocate_dfloat (dfloat eksplicit) +{ + cl_heap_dfloat* p = (cl_heap_dfloat*) cl_malloc_hook(sizeof(cl_heap_dfloat)); + p->refcount = 1; + p->type = &cl_class_dfloat; + p->representation.eksplicit = eksplicit; + return p; +} +#else +inline cl_heap_dfloat* allocate_dfloat (uint32 semhi, uint32 mlo) +{ + cl_heap_dfloat* p = (cl_heap_dfloat*) cl_malloc_hook(sizeof(cl_heap_dfloat)); + p->refcount = 1; + p->type = &cl_class_dfloat; + p->representation.eksplicit.semhi = semhi; + p->representation.eksplicit.mlo = mlo; + return p; +} +#endif + +// Double Float 0.0 + extern const cl_DF cl_DF_0; +// Double Float 1.0 + extern const cl_DF cl_DF_1; +// Double Float -1.0 + extern const cl_DF cl_DF_minus1; + + +#define dfloat_value representation.eksplicit + +// Entpacken eines Double-Float: +#if (cl_word_size==64) +// DF_decode(obj, zero_statement, sign=,exp=,mant=); +// zerlegt ein Double-Float obj. +// Ist obj=0.0, wird zero_statement ausgeführt. +// Sonst: cl_signean sign = Vorzeichen (0 = +, -1 = -), +// sintL exp = Exponent (vorzeichenbehaftet), +// uintQ mant = Mantisse (>= 2^DF_mant_len, < 2^(DF_mant_len+1)) + #define dfloat_value_semhi dfloat_value + #define DF_uexp(x) (((x) >> DF_mant_len) & (bit(DF_exp_len)-1)) + #define DF_decode(obj, zero_statement, sign_zuweisung,exp_zuweisung,mant_zuweisung) \ + { var dfloat _x = TheDfloat(obj)->dfloat_value; \ + var uintL uexp = DF_uexp(_x); \ + if (uexp==0) \ + { zero_statement } /* e=0 -> Zahl 0.0 */ \ + else \ + { exp_zuweisung (sintL)(uexp - DF_exp_mid); /* Exponent */ \ + unused (sign_zuweisung ((sint64)_x >> 63)); /* Vorzeichen */ \ + mant_zuweisung (bit(DF_mant_len) | (_x & (bit(DF_mant_len)-1))); \ + } } +#else +// DF_decode2(obj, zero_statement, sign=,exp=,manthi=,mantlo=); +// zerlegt ein Double-Float obj. +// Ist obj=0.0, wird zero_statement ausgeführt. +// Sonst: cl_signean sign = Vorzeichen (0 = +, -1 = -), +// sintL exp = Exponent (vorzeichenbehaftet), +// uintL manthi,mantlo = Mantisse 2^32*manthi+mantlo +// (>= 2^DF_mant_len, < 2^(DF_mant_len+1)) + #define dfloat_value_semhi dfloat_value.semhi + #define DF_uexp(semhi) (((semhi) >> (DF_mant_len-32)) & (bit(DF_exp_len)-1)) + #define DF_decode2(obj, zero_statement, sign_zuweisung,exp_zuweisung,manthi_zuweisung,mantlo_zuweisung) \ + { var uint32 semhi = TheDfloat(obj)->dfloat_value.semhi; \ + var uint32 mlo = TheDfloat(obj)->dfloat_value.mlo; \ + var uintL uexp = DF_uexp(semhi); \ + if (uexp==0) \ + { zero_statement } /* e=0 -> Zahl 0.0 */ \ + else \ + { exp_zuweisung (sintL)(uexp - DF_exp_mid); /* Exponent */ \ + unused (sign_zuweisung sign_of((sint32)(semhi))); /* Vorzeichen */\ + manthi_zuweisung (bit(DF_mant_len-32) | (semhi & (bit(DF_mant_len-32)-1))); \ + mantlo_zuweisung mlo; \ + } } +#endif + +// Einpacken eines Double-Float: +#if (cl_word_size==64) +// encode_DF(sign,exp,mant) +// liefert ein Double-Float. +// > cl_signean sign: Vorzeichen, 0 für +, -1 für negativ. +// > sintL exp: Exponent +// > uintQ mant: Mantisse, sollte >= 2^DF_mant_len und < 2^(DF_mant_len+1) sein. +// < cl_DF ergebnis: ein Double-Float +// Der Exponent wird auf Überlauf/Unterlauf getestet. +inline const cl_DF encode_DF (cl_signean sign, sintL exp, uintQ mant) +{ + if (exp < (sintL)(DF_exp_low-DF_exp_mid)) + { if (underflow_allowed()) + { cl_error_floating_point_underflow(); } + else + { return cl_DF_0; } + } + else + if (exp > (sintL)(DF_exp_high-DF_exp_mid)) + { cl_error_floating_point_overflow(); } + else + return allocate_dfloat + ( ((sint64)sign & bit(63)) /* Vorzeichen */ + | ((uint64)(exp+DF_exp_mid) << DF_mant_len) /* Exponent */ + | ((uint64)mant & (bit(DF_mant_len)-1)) /* Mantisse */ + ); +} +#else +// encode_DF(sign,exp,manthi,mantlo) +// liefert ein Double-Float. +// > cl_signean sign: Vorzeichen, 0 für +, -1 für negativ. +// > sintL exp: Exponent +// > uintL manthi,mantlo: Mantisse 2^32*manthi+mantlo, +// sollte >= 2^DF_mant_len und < 2^(DF_mant_len+1) sein. +// < cl_DF ergebnis: ein Double-Float +// Der Exponent wird auf Überlauf/Unterlauf getestet. +inline const cl_DF encode_DF (cl_signean sign, sintL exp, uintL manthi, uintL mantlo) +{ + if (exp < (sintL)(DF_exp_low-DF_exp_mid)) + { if (underflow_allowed()) + { cl_error_floating_point_underflow(); } + else + { return cl_DF_0; } + } + else + if (exp > (sintL)(DF_exp_high-DF_exp_mid)) + { cl_error_floating_point_overflow(); } + else + return allocate_dfloat + ( ((sint32)sign & bit(31)) /* Vorzeichen */ + | ((uint32)(exp+DF_exp_mid) << (DF_mant_len-32)) /* Exponent */ + | ((uint32)manthi & (bit(DF_mant_len-32)-1)) /* Mantisse */ + , mantlo + ); +} +#endif + +#ifdef FAST_DOUBLE +// Auspacken eines Double: +inline double DF_to_double (const cl_DF& obj) +{ + return TheDfloat(obj)->representation.machine_double; +} +// Überprüfen und Einpacken eines von den 'double'-Routinen gelieferten +// IEEE-Floats. +// Klassifikation: +// 1 <= e <= 2046 : normalisierte Zahl +// e=0, m/=0: subnormale Zahl +// e=0, m=0: vorzeichenbehaftete 0.0 +// e=2047, m=0: vorzeichenbehaftete Infinity +// e=2047, m/=0: NaN +// Angabe der möglicherweise auftretenden Sonderfälle: +// maybe_overflow: Operation läuft über, liefert IEEE-Infinity +// maybe_subnormal: Ergebnis sehr klein, liefert IEEE-subnormale Zahl +// maybe_underflow: Ergebnis sehr klein und /=0, liefert IEEE-Null +// maybe_divide_0: Ergebnis unbestimmt, liefert IEEE-Infinity +// maybe_nan: Ergebnis unbestimmt, liefert IEEE-NaN + #include "cl_N.h" + #include "cl_F.h" +#if (cl_word_size==64) + #define double_to_DF(expr,ergebnis_zuweisung,maybe_overflow,maybe_subnormal,maybe_underflow,maybe_divide_0,maybe_nan) \ + { var dfloatjanus _erg; _erg.machine_double = (expr); \ + if ((_erg.eksplicit & ((uint64)bit(DF_exp_len+DF_mant_len)-bit(DF_mant_len))) == 0) /* e=0 ? */\ + { if ((maybe_underflow \ + || (maybe_subnormal && !((_erg.eksplicit << 1) == 0)) \ + ) \ + && underflow_allowed() \ + ) \ + { cl_error_floating_point_underflow(); } /* subnormal oder noch kleiner -> Underflow */\ + else \ + { ergebnis_zuweisung cl_DF_0; } /* +/- 0.0 -> 0.0 */ \ + } \ + elif ((maybe_overflow || maybe_divide_0) \ + && (((~_erg.eksplicit) & ((uint64)bit(DF_exp_len+DF_mant_len)-bit(DF_mant_len))) == 0) /* e=2047 ? */\ + ) \ + { if (maybe_nan && !((_erg.eksplicit<<(64-DF_mant_len)) == 0)) \ + { cl_error_division_by_0(); } /* NaN, also Singularität -> "Division durch 0" */\ + else /* Infinity */ \ + if (!maybe_overflow || maybe_divide_0) \ + { cl_error_division_by_0(); } /* Infinity, Division durch 0 */\ + else \ + { cl_error_floating_point_overflow(); } /* Infinity, Overflow */\ + } \ + else \ + { ergebnis_zuweisung allocate_dfloat(_erg.eksplicit); } \ + } +#else + #define double_to_DF(expr,ergebnis_zuweisung,maybe_overflow,maybe_subnormal,maybe_underflow,maybe_divide_0,maybe_nan) \ + { var dfloatjanus _erg; _erg.machine_double = (expr); \ + if ((_erg.eksplicit.semhi & ((uint32)bit(DF_exp_len+DF_mant_len-32)-bit(DF_mant_len-32))) == 0) /* e=0 ? */\ + { if ((maybe_underflow \ + || (maybe_subnormal \ + && !(((_erg.eksplicit.semhi << 1) == 0) && (_erg.eksplicit.mlo == 0)) \ + ) ) \ + && underflow_allowed() \ + ) \ + { cl_error_floating_point_underflow(); } /* subnormal oder noch kleiner -> Underflow */\ + else \ + { ergebnis_zuweisung cl_DF_0; } /* +/- 0.0 -> 0.0 */\ + } \ + elif ((maybe_overflow || maybe_divide_0) \ + && (((~_erg.eksplicit.semhi) & ((uint32)bit(DF_exp_len+DF_mant_len-32)-bit(DF_mant_len-32))) == 0) /* e=2047 ? */\ + ) \ + { if (maybe_nan && !(((_erg.eksplicit.semhi<<(64-DF_mant_len)) == 0) && (_erg.eksplicit.mlo==0))) \ + { cl_error_division_by_0(); } /* NaN, also Singularität -> "Division durch 0" */\ + else /* Infinity */\ + if (!maybe_overflow || maybe_divide_0) \ + { cl_error_division_by_0(); } /* Infinity, Division durch 0 */\ + else \ + { cl_error_floating_point_overflow(); } /* Infinity, Overflow */\ + } \ + else \ + { ergebnis_zuweisung allocate_dfloat(_erg.eksplicit.semhi,_erg.eksplicit.mlo); } \ + } +#endif +#endif + +// Liefert zu einem Double-Float x : (futruncate x), ein DF. +// x wird von der 0 weg zur nächsten ganzen Zahl gerundet. +extern const cl_DF futruncate (const cl_DF& x); + +// DF_to_I(x) wandelt ein Double-Float x, das eine ganze Zahl darstellt, +// in ein Integer um. +extern const cl_I cl_DF_to_I (const cl_DF& x); + +// cl_I_to_DF(x) wandelt ein Integer x in ein Double-Float um und rundet dabei. +extern const cl_DF cl_I_to_DF (const cl_I& x); + +// cl_RA_to_DF(x) wandelt eine rationale Zahl x in ein Double-Float um +// und rundet dabei. +extern const cl_DF cl_RA_to_DF (const cl_RA& x); + + +// IEEE-Double-Float: +// Bit 63 = s, Bits 62..52 = e, Bits 51..0 = m. +// e=0, m=0: vorzeichenbehaftete 0.0 +// e=0, m/=0: subnormale Zahl, +// Wert = (-1)^s * 2^(1-1022) * [ 0 . 0 m51 ... m0 ] +// 1 <= e <= 2046 : normalisierte Zahl, +// Wert = (-1)^s * 2^(e-1022) * [ 0 . 1 m51 ... m0 ] +// e=2047, m=0: vorzeichenbehaftete Infinity +// e=2047, m/=0: NaN + +// cl_double_to_DF(val) wandelt ein IEEE-Double-Float val in ein Double-Float um. +extern cl_heap_dfloat* cl_double_to_DF_pointer (const dfloatjanus& val); +inline const cl_DF cl_double_to_DF (const dfloatjanus& val) + { return cl_double_to_DF_pointer(val); } + +// cl_DF_to_double(obj,&val); +// wandelt ein Double-Float obj in ein IEEE-Double-Float val um. +extern void cl_DF_to_double (const cl_DF& obj, dfloatjanus* val_); + +#endif /* _CL_DF_H */ diff --git a/src/float/dfloat/conv/Makeflags b/src/float/dfloat/conv/Makeflags new file mode 100644 index 0000000..f4f386c --- /dev/null +++ b/src/float/dfloat/conv/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/dfloat/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/rational -I$(srcdir)/integer -I$(srcdir)/base/digitseq -I$(srcdir)/base/digit -Ibase $(GMP_INCLUDES) diff --git a/src/float/dfloat/conv/cl_DF_from_double.cc b/src/float/dfloat/conv/cl_DF_from_double.cc new file mode 100644 index 0000000..1a6e7f5 --- /dev/null +++ b/src/float/dfloat/conv/cl_DF_from_double.cc @@ -0,0 +1,60 @@ +// cl_double_to_FF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_DF.h" + + +// Implementation. + +cl_heap_dfloat* cl_double_to_DF_pointer (const dfloatjanus& val_) +{ + var dfloat val = val_.eksplicit; + #if (cl_word_size==64) + var uintL exp = (val >> DF_mant_len) & (bit(DF_exp_len)-1); // e + if (exp == 0) // e=0 ? + // vorzeichenbehaftete 0.0 oder subnormale Zahl + { if (!((val << 1) == 0) && underflow_allowed()) + { cl_error_floating_point_underflow(); } + else + { return cl_DF_0; } // +/- 0.0 -> 0.0 + } + elif (exp == 2047) // e=2047 ? + { if (!((val << (64-DF_mant_len)) == 0)) + { cl_error_floating_point_nan(); } // NaN + else + { cl_error_floating_point_overflow(); } // Infinity, Overflow + } + else + { // Der Exponent muß um DF_exp_mid-1022 erhöht werden. + if ((DF_exp_mid>1022) && (exp > DF_exp_high-DF_exp_mid+1022)) + { cl_error_floating_point_overflow(); } // Overflow + val += (sint64)(DF_exp_mid - 1022) << DF_mant_len; + return allocate_dfloat(val); + } + #else + var uintL exp = (val.semhi >> (DF_mant_len-32)) & (bit(DF_exp_len)-1); // e + if (exp == 0) // e=0 ? + // vorzeichenbehaftete 0.0 oder subnormale Zahl + { if (!(((val.semhi << 1) == 0) && (val.mlo == 0)) && underflow_allowed()) + { cl_error_floating_point_underflow(); } + else + { return cl_DF_0; } // +/- 0.0 -> 0.0 + } + elif (exp == 2047) // e=2047 ? + { if (!(((val.semhi << (64-DF_mant_len)) == 0) && (val.mlo == 0))) + { cl_error_floating_point_nan(); } // NaN + else + { cl_error_floating_point_overflow(); } // Infinity, Overflow + } + else + { // Der Exponent muß um DF_exp_mid-1022 erhöht werden. + if ((DF_exp_mid>1022) && (exp > DF_exp_high-DF_exp_mid+1022)) + { cl_error_floating_point_overflow(); } // Overflow + val.semhi += (sint32)(DF_exp_mid - 1022) << (DF_mant_len-32); + return allocate_dfloat(val.semhi,val.mlo); + } + #endif +} diff --git a/src/float/dfloat/conv/cl_DF_to_doublej.cc b/src/float/dfloat/conv/cl_DF_to_doublej.cc new file mode 100644 index 0000000..352a16f --- /dev/null +++ b/src/float/dfloat/conv/cl_DF_to_doublej.cc @@ -0,0 +1,48 @@ +// cl_DF_to_double(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_DF.h" + + +// Implementation. + +void cl_DF_to_double (const cl_DF& obj, dfloatjanus* val_) +{ + var dfloat val = TheDfloat(obj)->dfloat_value; + // Der Exponent muß um DF_exp_mid-1022 erniedrigt werden. + if (DF_exp_mid>1022) + #if (cl_word_size==64) + { var uintL exp = (val >> DF_mant_len) & (bit(DF_exp_len)-1); // e + if (exp < DF_exp_mid-1022+1) + { // produziere denormalisiertes Float + val = (val & minus_bit(DF_exp_len+DF_mant_len)) // selbes Vorzeichen + | ((sint64)0 << DF_mant_len) // Exponent 0 + | (((val & (bit(DF_mant_len)-1)) | bit(DF_mant_len)) // Mantisse shiften + >> (DF_exp_mid-1022+1 - exp) // shiften + ); + } + else + { val -= (sint64)(DF_exp_mid - 1022) << DF_mant_len; } + } + #else + { var uintL exp = (val.semhi >> (DF_mant_len-32)) & (bit(DF_exp_len)-1); // e + if (exp < DF_exp_mid-1022+1) + { // produziere denormalisiertes Float + var uintL shiftcount = DF_exp_mid-1022+1 - exp; + val.mlo = val.mlo >> shiftcount; // Mantisse shiften + val.mlo |= val.semhi << (32-shiftcount); + val.semhi = (val.semhi & minus_bit(DF_exp_len+DF_mant_len-32)) // selbes Vorzeichen + | ((sint32)0 << (DF_mant_len-32)) // Exponent 0 + | (((val.semhi & (bit(DF_mant_len-32)-1)) | bit(DF_mant_len-32)) // Mantisse shiften + >> shiftcount // shiften + ); + } + else + { val.semhi -= (sint32)(DF_exp_mid - 1022) << (DF_mant_len-32); } + } + #endif + val_->eksplicit = val; +} diff --git a/src/float/dfloat/conv/cl_I_to_double.cc b/src/float/dfloat/conv/cl_I_to_double.cc new file mode 100644 index 0000000..31e7038 --- /dev/null +++ b/src/float/dfloat/conv/cl_I_to_double.cc @@ -0,0 +1,149 @@ +// cl_double_approx(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_DF.h" +#include "cl_I.h" +#include "cl_DS.h" +#include "cl_F.h" + +double cl_double_approx (const cl_I& x) +{ +// Method: same as cl_I_to_DF(). + if (eq(x,0)) { return 0.0; } + var cl_signean sign = -(cl_signean)minusp(x); // Vorzeichen + var cl_I abs_x = (sign==0 ? x : -x); + var uintL exp = integer_length(abs_x); // (integer-length x) + // NDS zu |x|>0 bilden: + var const uintD* MSDptr; + var uintC len; + I_to_NDS_nocopy(abs_x, MSDptr=,len=,,cl_false,); + // MSDptr/len/LSDptr ist die NDS zu x, len>0. + // Führende Digits holen: Brauche DF_mant_len+1 Bits, dazu intDsize + // Bits (die NDS kann mit bis zu intDsize Nullbits anfangen). + // Dann werden diese Bits um (exp mod intDsize) nach rechts geschoben. + var uintD msd = msprefnext(MSDptr); // erstes Digit + #if (cl_word_size==64) + var uint64 msdd = 0; // weitere min(len-1,64/intDsize) Digits + #define NEXT_DIGIT(i) \ + { if (--len == 0) goto ok; \ + msdd |= (uint64)msprefnext(MSDptr) << (64-(i+1)*intDsize); \ + } + DOCONSTTIMES(64/intDsize,NEXT_DIGIT); + #undef NEXT_DIGIT + #else + var uint32 msdd = 0; // weitere min(len-1,32/intDsize) Digits + var uint32 msddf = 0; // weitere maximal 32/intDsize Digits + #define NEXT_DIGIT(i) \ + { if (--len == 0) goto ok; \ + msdd |= (uint32)msprefnext(MSDptr) << (32-(i+1)*intDsize); \ + } + DOCONSTTIMES(32/intDsize,NEXT_DIGIT); + #undef NEXT_DIGIT + #define NEXT_DIGIT(i) \ + { if (--len == 0) goto ok; \ + msddf |= (uint32)msprefnext(MSDptr) << (32-(i+1)*intDsize); \ + } + DOCONSTTIMES(32/intDsize,NEXT_DIGIT); + #undef NEXT_DIGIT + #endif + --len; ok: + #if (cl_word_size==64) + // Die NDS besteht aus msd, msdd und len weiteren Digits. + // Das höchste in 2^64*msd+msdd gesetzte Bit ist Bit Nummer + // 63 + (exp mod intDsize). + var uintL shiftcount = exp % intDsize; + var uint64 mant = // führende 64 Bits + (shiftcount==0 + ? msdd + : (((uint64)msd << (64-shiftcount)) | (msdd >> shiftcount)) + ); + // Das höchste in mant gesetzte Bit ist Bit Nummer 63. + if ( ((mant & bit(62-DF_mant_len)) ==0) // Bit 10 =0 -> abrunden + || ( ((mant & (bit(62-DF_mant_len)-1)) ==0) // Bit 10 =1 und Bits 9..0 =0 + && ((msdd & (bit(shiftcount)-1)) ==0) // und weitere Bits aus msddf =0 + && (!test_loop_msp(MSDptr,len)) // und alle weiteren Digits =0 + // round-to-even, je nach Bit 11 : + && ((mant & bit(63-DF_mant_len)) ==0) + ) ) + // abrunden + { mant = mant >> (63-DF_mant_len); } + else + // aufrunden + { mant = mant >> (63-DF_mant_len); + mant += 1; + if (mant >= bit(DF_mant_len+1)) // rounding overflow? + { mant = mant>>1; exp = exp+1; } + } + union { dfloat eksplicit; double machine_double; } u; + if ((sintL)exp > (sintL)(DF_exp_high-DF_exp_mid)) + { u.eksplicit = + ((sint64)sign & bit(63)) + | ((uint64)(bit(DF_exp_len)-1) << DF_mant_len); // Infinity + } + else + { u.eksplicit = + ((sint64)sign & bit(63)) /* Vorzeichen */ + | ((uint64)((sintL)exp+DF_exp_mid) << DF_mant_len) /* Exponent */ + | ((uint64)mant & (bit(DF_mant_len)-1)); /* Mantisse */ + } + return u.machine_double; + #else + // Die NDS besteht aus msd, msdd, msddf und len weiteren Digits. + // Das höchste in 2^64*msd+2^32*msdd+msddf gesetzte Bit ist Bit Nummer + // 63 + (exp mod intDsize). + var uintL shiftcount = exp % intDsize; + var uint32 manthi; // führende 32 Bits + var uint32 mantlo; // nächste 32 Bits + if (shiftcount==0) + { manthi = msdd; mantlo = msddf; } + else + { manthi = ((uint32)msd << (32-shiftcount)) | (msdd >> shiftcount); + mantlo = (msdd << (32-shiftcount)) | (msddf >> shiftcount); + } + // Das höchste in mant gesetzte Bit ist Bit Nummer 63. + if ( ((mantlo & bit(62-DF_mant_len)) ==0) // Bit 10 =0 -> abrunden + || ( ((mantlo & (bit(62-DF_mant_len)-1)) ==0) // Bit 10 =1 und Bits 9..0 =0 + && ((msddf & (bit(shiftcount)-1)) ==0) // und weitere Bits aus msddf =0 + && (!test_loop_msp(MSDptr,len)) // und alle weiteren Digits =0 + // round-to-even, je nach Bit 11 : + && ((mantlo & bit(63-DF_mant_len)) ==0) + ) ) + // abrunden + { mantlo = (mantlo >> (63-DF_mant_len)) | (manthi << (DF_mant_len-32+1)); + manthi = manthi >> (63-DF_mant_len); + } + else + // aufrunden + { mantlo = (mantlo >> (63-DF_mant_len)) | (manthi << (DF_mant_len-32+1)); + manthi = manthi >> (63-DF_mant_len); + mantlo += 1; + if (mantlo==0) + { manthi += 1; + if (manthi >= bit(DF_mant_len-32+1)) // rounding overflow? + { manthi = manthi>>1; exp = exp+1; } + } } + union { dfloat eksplicit; double machine_double; } u; + if ((sintL)exp > (sintL)(DF_exp_high-DF_exp_mid)) + { u.eksplicit.semhi = + ((sint32)sign & bit(31)) + | ((uint32)(bit(DF_exp_len)-1) << (DF_mant_len-32)); // Infinity + u.eksplicit.mlo = 0; + } + else + { u.eksplicit.semhi = + ((sint32)sign & bit(31)) /* Vorzeichen */ + | ((uint32)((sintL)exp+DF_exp_mid) << (DF_mant_len-32)) /* Exponent */ + | ((uint32)manthi & (bit(DF_mant_len-32)-1)); /* Mantisse */ + u.eksplicit.mlo = mantlo; + } + return u.machine_double; + #endif +} diff --git a/src/float/dfloat/conv/cl_RA_to_double.cc b/src/float/dfloat/conv/cl_RA_to_double.cc new file mode 100644 index 0000000..904b819 --- /dev/null +++ b/src/float/dfloat/conv/cl_RA_to_double.cc @@ -0,0 +1,186 @@ +// cl_double_approx(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_DF.h" +#include "cl_RA.h" +#include "cl_integer.h" +#include "cl_I.h" +#include "cl_F.h" + +double cl_double_approx (const cl_RA& x) +{ +// Method: same as cl_RA_to_DF(). + if (integerp(x)) { + DeclareType(cl_I,x); + return cl_double_approx(x); + } + { // x Ratio + DeclareType(cl_RT,x); + union { dfloat eksplicit; double machine_double; } u; + var cl_I a = numerator(x); // +/- a + var const cl_I& b = denominator(x); // b + var cl_signean sign = -(cl_signean)minusp(a); // Vorzeichen + if (!(sign==0)) { a = -a; } // Betrag nehmen, liefert a + var sintL lendiff = (sintL)integer_length(a) // (integer-length a) + - (sintL)integer_length(b); // (integer-length b) + if (lendiff > DF_exp_high-DF_exp_mid) // Exponent >= n-m > Obergrenze ? + { + #if (cl_word_size==64) + u.eksplicit = + ((sint64)sign & bit(63)) + | ((uint64)(bit(DF_exp_len)-1) << DF_mant_len); // Infinity + #else + u.eksplicit.semhi = + ((sint32)sign & bit(31)) + | ((uint32)(bit(DF_exp_len)-1) << (DF_mant_len-32)); // Infinity + u.eksplicit.mlo = 0; + #endif + return u.machine_double; + } + if (lendiff < DF_exp_low-DF_exp_mid-2) // Exponent <= n-m+2 < Untergrenze ? + { + #if (cl_word_size==64) + u.eksplicit = ((sint64)sign & bit(63)); // 0.0 + #else + u.eksplicit.semhi = ((sint32)sign & bit(31)); // 0.0 + u.eksplicit.mlo = 0; + #endif + return u.machine_double; + } + var cl_I zaehler; + var cl_I nenner; + if (lendiff >= DF_mant_len+2) + // n-m-54>=0 + { nenner = ash(b,lendiff - (DF_mant_len+2)); // (ash b n-m-54) + zaehler = a; // a + } + else + { zaehler = ash(a,(DF_mant_len+2) - lendiff); // (ash a -n+m+54) + nenner = b; // b + } + // Division zaehler/nenner durchführen: + var cl_I_div_t q_r = cl_divide(zaehler,nenner); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + // 2^53 <= q < 2^55, also ist q Bignum mit ceiling(55/intDsize) Digits. + var const uintD* ptr = BN_MSDptr(q); + #if (cl_word_size==64) + var uint64 mant = get_max64_Dptr(55,ptr); + if (mant >= bit(DF_mant_len+2)) + // 2^54 <= q < 2^55, schiebe um 2 Bits nach rechts + { var uint64 rounding_bits = mant & (bit(2)-1); + lendiff = lendiff+1; // Exponent := n-m+1 + mant = mant >> 2; + if ( (rounding_bits < bit(1)) // 00,01 werden abgerundet + || ( (rounding_bits == bit(1)) // 10 + && (eq(r,0)) // und genau halbzahlig (r=0) + && ((mant & bit(0)) ==0) // -> round-to-even + ) ) + // abrunden + goto ab; + else + // aufrunden + goto auf; + } + else + { var uint64 rounding_bit = mant & bit(0); + mant = mant >> 1; + if ( (rounding_bit == 0) // 0 wird abgerundet + || ( (eq(r,0)) // genau halbzahlig (r=0) + && ((mant & bit(0)) ==0) // -> round-to-even + ) ) + // abrunden + goto ab; + else + // aufrunden + goto auf; + } + auf: + mant += 1; + if (mant >= bit(DF_mant_len+1)) // rounding overflow? + { mant = mant>>1; lendiff = lendiff+1; } + ab: + // Fertig. + if (lendiff < (sintL)(DF_exp_low-DF_exp_mid)) + { u.eksplicit = ((sint64)sign & bit(63)); } // 0.0 + else if (lendiff > (sintL)(DF_exp_high-DF_exp_mid)) + { u.eksplicit = + ((sint64)sign & bit(63)) + | ((uint64)(bit(DF_exp_len)-1) << DF_mant_len); // Infinity + } + else + { u.eksplicit = + ((sint64)sign & bit(63)) /* Vorzeichen */ + | ((uint64)(lendiff+DF_exp_mid) << DF_mant_len) /* Exponent */ + | ((uint64)mant & (bit(DF_mant_len)-1)); /* Mantisse */ + } + return u.machine_double; + #else + var uint32 manthi = get_max32_Dptr(23,ptr); + var uint32 mantlo = get_32_Dptr(ptr mspop ceiling(23,intDsize)); + if (manthi >= bit(DF_mant_len-32+2)) + // 2^54 <= q < 2^55, schiebe um 2 Bits nach rechts + { var uintL rounding_bits = mantlo & (bit(2)-1); + lendiff = lendiff+1; // Exponent := n-m+1 + mantlo = (mantlo >> 2) | (manthi << 30); manthi = manthi >> 2; + if ( (rounding_bits < bit(1)) // 00,01 werden abgerundet + || ( (rounding_bits == bit(1)) // 10 + && (eq(r,0)) // und genau halbzahlig (r=0) + && ((mantlo & bit(0)) ==0) // -> round-to-even + ) ) + // abrunden + goto ab; + else + // aufrunden + goto auf; + } + else + { var uintL rounding_bit = mantlo & bit(0); + mantlo = (mantlo >> 1) | (manthi << 31); manthi = manthi >> 1; + if ( (rounding_bit == 0) // 0 wird abgerundet + || ( (eq(r,0)) // genau halbzahlig (r=0) + && ((mantlo & bit(0)) ==0) // -> round-to-even + ) ) + // abrunden + goto ab; + else + // aufrunden + goto auf; + } + auf: + mantlo += 1; + if (mantlo==0) + { manthi += 1; + if (manthi >= bit(DF_mant_len-32+1)) // rounding overflow? + { manthi = manthi>>1; lendiff = lendiff+1; } + } + ab: + // Fertig. + if (lendiff < (sintL)(DF_exp_low-DF_exp_mid)) + { u.eksplicit.semhi = ((sint32)sign & bit(31)); // 0.0 + u.eksplicit.mlo = 0; + } + else if (lendiff > (sintL)(DF_exp_high-DF_exp_mid)) + { u.eksplicit.semhi = + ((sint32)sign & bit(31)) + | ((uint32)(bit(DF_exp_len)-1) << (DF_mant_len-32)); // Infinity + u.eksplicit.mlo = 0; + } + else + { u.eksplicit.semhi = + ((sint32)sign & bit(31)) /* Vorzeichen */ + | ((uint32)(lendiff+DF_exp_mid) << (DF_mant_len-32)) /* Exponent */ + | ((uint32)manthi & (bit(DF_mant_len-32)-1)); /* Mantisse */ + u.eksplicit.mlo = mantlo; + } + return u.machine_double; + #endif +}} diff --git a/src/float/dfloat/division/Makeflags b/src/float/dfloat/division/Makeflags new file mode 100644 index 0000000..40164ab --- /dev/null +++ b/src/float/dfloat/division/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/dfloat/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/float/dfloat/elem diff --git a/src/float/dfloat/division/cl_DF_ceil22.cc b/src/float/dfloat/division/cl_DF_ceil22.cc new file mode 100644 index 0000000..ceca811 --- /dev/null +++ b/src/float/dfloat/division/cl_DF_ceil22.cc @@ -0,0 +1,22 @@ +// ceiling2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#include "cl_DF.h" + +const cl_DF_div_t ceiling2 (const cl_DF& x, const cl_DF& y) +{ +// Methode: +// (q,r) := ceiling(x/y). Liefere q und x-y*q = y*r. + var cl_DF_div_t q_r = ceiling2(x/y); + var cl_I& q = q_r.quotient; + var cl_DF& r = q_r.remainder; + return cl_DF_div_t(q,y*r); +} diff --git a/src/float/dfloat/division/cl_DF_fceil.cc b/src/float/dfloat/division/cl_DF_fceil.cc new file mode 100644 index 0000000..fb17c81 --- /dev/null +++ b/src/float/dfloat/division/cl_DF_fceil.cc @@ -0,0 +1,24 @@ +// fceiling(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#include "cl_DF.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_DF_minusp.cc" + +const cl_DF fceiling (const cl_DF& x) +{ + if (minusp(x)) + return ftruncate(x); + else + return futruncate(x); +} diff --git a/src/float/dfloat/division/cl_DF_floor22.cc b/src/float/dfloat/division/cl_DF_floor22.cc new file mode 100644 index 0000000..90fb35a --- /dev/null +++ b/src/float/dfloat/division/cl_DF_floor22.cc @@ -0,0 +1,22 @@ +// floor2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#include "cl_DF.h" + +const cl_DF_div_t floor2 (const cl_DF& x, const cl_DF& y) +{ +// Methode: +// (q,r) := floor(x/y). Liefere q und x-y*q = y*r. + var cl_DF_div_t q_r = floor2(x/y); + var cl_I& q = q_r.quotient; + var cl_DF& r = q_r.remainder; + return cl_DF_div_t(q,y*r); +} diff --git a/src/float/dfloat/division/cl_DF_recip.cc b/src/float/dfloat/division/cl_DF_recip.cc new file mode 100644 index 0000000..cda34ee --- /dev/null +++ b/src/float/dfloat/division/cl_DF_recip.cc @@ -0,0 +1,17 @@ +// recip(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#include "cl_DF.h" + +const cl_DF recip (const cl_DF& x) +{ + return cl_DF_1 / x; +} diff --git a/src/float/dfloat/division/cl_DF_round22.cc b/src/float/dfloat/division/cl_DF_round22.cc new file mode 100644 index 0000000..0f31fd2 --- /dev/null +++ b/src/float/dfloat/division/cl_DF_round22.cc @@ -0,0 +1,22 @@ +// round2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#include "cl_DF.h" + +const cl_DF_div_t round2 (const cl_DF& x, const cl_DF& y) +{ +// Methode: +// (q,r) := round(x/y). Liefere q und x-y*q = y*r. + var cl_DF_div_t q_r = round2(x/y); + var cl_I& q = q_r.quotient; + var cl_DF& r = q_r.remainder; + return cl_DF_div_t(q,y*r); +} diff --git a/src/float/dfloat/division/cl_DF_trunc22.cc b/src/float/dfloat/division/cl_DF_trunc22.cc new file mode 100644 index 0000000..5a7daac --- /dev/null +++ b/src/float/dfloat/division/cl_DF_trunc22.cc @@ -0,0 +1,22 @@ +// truncate2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#include "cl_DF.h" + +const cl_DF_div_t truncate2 (const cl_DF& x, const cl_DF& y) +{ +// Methode: +// (q,r) := truncate(x/y). Liefere q und x-y*q = y*r. + var cl_DF_div_t q_r = truncate2(x/y); + var cl_I& q = q_r.quotient; + var cl_DF& r = q_r.remainder; + return cl_DF_div_t(q,y*r); +} diff --git a/src/float/dfloat/elem/Makeflags b/src/float/dfloat/elem/Makeflags new file mode 100644 index 0000000..fa74aac --- /dev/null +++ b/src/float/dfloat/elem/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/dfloat/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/float/base -I$(srcdir)/rational -I$(srcdir)/integer -I$(srcdir)/base/digitseq -I$(srcdir)/base/digit -Ibase $(GMP_INCLUDES) diff --git a/src/float/dfloat/elem/cl_DF_compare.cc b/src/float/dfloat/elem/cl_DF_compare.cc new file mode 100644 index 0000000..970a8f5 --- /dev/null +++ b/src/float/dfloat/elem/cl_DF_compare.cc @@ -0,0 +1,82 @@ +// cl_compare(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#include "cl_DF.h" + +cl_signean cl_compare (const cl_DF& x, const cl_DF& y) +{ +// Methode: +// x und y haben verschiedenes Vorzeichen -> +// x < 0 -> x < y +// x >= 0 -> x > y +// x und y haben gleiches Vorzeichen -> +// x >=0 -> vergleiche x und y (die rechten 53 Bits) +// x <0 -> vergleiche y und x (die rechten 53 Bits) +#if (cl_word_size==64) + var dfloat x_ = TheDfloat(x)->dfloat_value; + var dfloat y_ = TheDfloat(y)->dfloat_value; + if ((sint64)y_ >= 0) + // y>=0 + { if ((sint64)x_ >= 0) + // y>=0, x>=0 + { if (x_ < y_) return signean_minus; // x y_) return signean_plus; // x>y + return signean_null; + } + else + // y>=0, x<0 + { return signean_minus; } // x= 0) + // y<0, x>=0 + { return signean_plus; } // x>y + else + // y<0, x<0 + { if (x_ > y_) return signean_minus; // |x|>|y| -> x x>y + return signean_null; + } + } +#else + var uint32 x_semhi = TheDfloat(x)->dfloat_value.semhi; + var uint32 y_semhi = TheDfloat(y)->dfloat_value.semhi; + var uint32 x_mlo = TheDfloat(x)->dfloat_value.mlo; + var uint32 y_mlo = TheDfloat(y)->dfloat_value.mlo; + if ((sint32)y_semhi >= 0) + // y>=0 + { if ((sint32)x_semhi >= 0) + // y>=0, x>=0 + { if (x_semhi < y_semhi) return signean_minus; // x y_semhi) return signean_plus; // x>y + if (x_mlo < y_mlo) return signean_minus; // x y_mlo) return signean_plus; // x>y + return signean_null; + } + else + // y>=0, x<0 + { return signean_minus; } // x= 0) + // y<0, x>=0 + { return signean_plus; } // x>y + else + // y<0, x<0 + { if (x_semhi > y_semhi) return signean_minus; // |x|>|y| -> x x>y + if (x_mlo > y_mlo) return signean_minus; // |x|>|y| -> x x>y + return signean_null; + } + } +#endif +} diff --git a/src/float/dfloat/elem/cl_DF_div.cc b/src/float/dfloat/elem/cl_DF_div.cc new file mode 100644 index 0000000..3c18e5a --- /dev/null +++ b/src/float/dfloat/elem/cl_DF_div.cc @@ -0,0 +1,222 @@ +// binary operator / + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#include "cl_DF.h" +#include "cl_N.h" +#include "cl_F.h" +#include "cl_low.h" +#include "cl_DS.h" +#include "cl_ieee.h" +NEED_IEEE_FLOATS() + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_DF_zerop.cc" + +const cl_DF operator/ (const cl_DF& x1, const cl_DF& x2) +{ +// Methode: +// x2 = 0.0 -> Error +// x1 = 0.0 -> Ergebnis 0.0 +// Sonst: +// Ergebnis-Vorzeichen = xor der beiden Vorzeichen von x1 und x2 +// Ergebnis-Exponent = Differenz der beiden Exponenten von x1 und x2 +// Ergebnis-Mantisse = Mantisse mant1 / Mantisse mant2, gerundet. +// mant1/mant2 > 1/2, mant1/mant2 < 2; +// nach Rundung mant1/mant2 >=1/2, <=2*mant1<2. +// Bei mant1/mant2 >=1 brauche 52 Nachkommabits, +// bei mant1/mant2 <1 brauche 53 Nachkommabits. +// Fürs Runden: brauche ein Rundungsbit (Rest gibt an, ob exakt). +// Brauche daher insgesamt 54 Nachkommabits von mant1/mant2. +// Dividiere daher (als Unsigned Integers) 2^54*(2^53*mant1) durch (2^53*mant2). +// Falls der Quotient >=2^54 ist, runde die letzten zwei Bits weg und +// erhöhe den Exponenten um 1. +// Falls der Quotient <2^54 ist, runde das letzte Bit weg. Bei rounding +// overflow schiebe um ein weiteres Bit nach rechts, incr. Exponenten. +#if defined(FAST_DOUBLE) && !defined(__i386__) + double_to_DF(DF_to_double(x1) / DF_to_double(x2), return , + TRUE, TRUE, // Overflow und subnormale Zahl abfangen + !zerop(x1), // ein Ergebnis +/- 0.0 + // ist genau dann in Wirklichkeit ein Underflow + zerop(x2), // Division durch Null abfangen + FALSE // kein NaN als Ergebnis möglich + ); +#else + // x1,x2 entpacken: + var cl_signean sign1; + var sintL exp1; + #if (intDsize<=32) + var uintL manthi1; + var uintL mantlo1; + #endif + var cl_signean sign2; + var sintL exp2; + #if (intDsize<=32) + var uintL manthi2; + var uintL mantlo2; + #endif + #if (cl_word_size==64) + var uint64 mantx1; + var uint64 mantx2; + DF_decode(x2, { cl_error_division_by_0(); }, sign2=,exp2=,mantx2=); + DF_decode(x1, { return x1; }, sign1=,exp1=,mantx1=); + #else + DF_decode2(x2, { cl_error_division_by_0(); }, sign2=,exp2=,manthi2=,mantlo2=); + DF_decode2(x1, { return x1; }, sign1=,exp1=,manthi1=,mantlo1=); + #endif + exp1 = exp1 - exp2; // Differenz der Exponenten + sign1 = sign1 ^ sign2; // Ergebnis-Vorzeichen + // Dividiere 2^54*mant1 durch mant2 oder (äquivalent) + // 2^i*2^54*mant1 durch 2^i*mant2 für irgendein i mit 0 <= i <= 64-53 : + // wähle i = 64-(DF_mant_len+1), also i+(DF_mant_len+2) = 65. + #if (cl_word_size==64) + mantx1 = mantx1 << 1; + mantx2 = mantx2 << (64-(DF_mant_len+1)); + #if (intDsize<=32) + manthi1 = high32(mantx1); mantlo1 = low32(mantx1); + manthi2 = high32(mantx2); mantlo2 = low32(mantx2); + #endif + #else + manthi1 = (manthi1 << 1) | (mantlo1 >> 31); mantlo1 = mantlo1 << 1; + manthi2 = (manthi2 << (64-(DF_mant_len+1))) | (mantlo2 >> ((DF_mant_len+1)-32)); mantlo2 = mantlo2 << (64-(DF_mant_len+1)); + #endif + var uintD mant1 [128/intDsize]; + var uintD mant2 [64/intDsize]; + #if (intDsize==64) + arrayLSref(mant1,128/intDsize,1) = mantx1; + arrayLSref(mant1,128/intDsize,0) = 0; + arrayLSref(mant2,64/intDsize,0) = mantx2; + #elif (intDsize==32) || (intDsize==16) || (intDsize==8) + set_32_Dptr(arrayMSDptr(mant1,128/intDsize),manthi1); + set_32_Dptr(arrayMSDptr(mant1,128/intDsize) mspop 32/intDsize,mantlo1); + set_32_Dptr(arrayMSDptr(mant1,128/intDsize) mspop 2*32/intDsize,0); + set_32_Dptr(arrayMSDptr(mant1,128/intDsize) mspop 3*32/intDsize,0); + set_32_Dptr(arrayMSDptr(mant2,64/intDsize),manthi2); + set_32_Dptr(arrayMSDptr(mant2,64/intDsize) mspop 32/intDsize,mantlo2); + #else + {var uintD* ptr; + ptr = arrayLSDptr(mant1,128/intDsize); + doconsttimes(64/intDsize, { lsprefnext(ptr) = 0; } ); + doconsttimes(32/intDsize, { lsprefnext(ptr) = (uintD)mantlo1; mantlo1 = mantlo1>>intDsize; } ); + doconsttimes(32/intDsize, { lsprefnext(ptr) = (uintD)manthi1; manthi1 = manthi1>>intDsize; } ); + } + {var uintD* ptr; + ptr = arrayLSDptr(mant2,64/intDsize); + doconsttimes(32/intDsize, { lsprefnext(ptr) = (uintD)mantlo2; mantlo2 = mantlo2>>intDsize; } ); + doconsttimes(32/intDsize, { lsprefnext(ptr) = (uintD)manthi2; manthi2 = manthi2>>intDsize; } ); + } + #endif + #if (cl_word_size==64) + var uint64 mantx; + #endif + #if (intDsize<=32) + var uintL manthi; + var uintL mantlo; + #endif + {CL_ALLOCA_STACK; + var DS q; + var DS r; + UDS_divide(arrayMSDptr(mant1,128/intDsize),128/intDsize,arrayLSDptr(mant1,128/intDsize), + arrayMSDptr(mant2,64/intDsize),64/intDsize,arrayLSDptr(mant2,64/intDsize), + &q, &r + ); + // Es ist 2^53 <= q < 2^55, also q.len = ceiling(54/intDsize)=ceiling(55/intDsize), + // und r=0 genau dann, wenn r.len=0. + ASSERT(q.len==ceiling(54,intDsize)) + {var uintD* ptr = q.MSDptr; + #if (intDsize==64) + mantx = mspref(ptr,0); + #else // (intDsize<=32) + manthi = get_max32_Dptr(23,ptr); + mantlo = get_32_Dptr(ptr mspop ceiling(23,intDsize)); + #endif + } + // q = 2^32*manthi+mantlo. + #if (cl_word_size==64) + #if (intDsize<=32) + mantx = (manthi<<32) | (uint64)mantlo; + #endif + if (mantx >= bit(DF_mant_len+2)) + // Quotient >=2^54 -> 2 Bits wegrunden + { var uint64 rounding_bits = mantx & (bit(2)-1); + exp1 += 1; // Exponenten incrementieren + mantx = mantx >> 2; + if ( (rounding_bits < bit(1)) // 00,01 werden abgerundet + || ( (rounding_bits == bit(1)) // 10 + && (r.len == 0) // und genau halbzahlig + && ((mantx & bit(0)) ==0) // -> round-to-even + ) ) + // abrunden + {} + else + // aufrunden + { mantx += 1; } + } + else + // Quotient <2^54 -> 1 Bit wegrunden + { var uint64 rounding_bit = mantx & bit(0); + mantx = mantx >> 1; + if ( (rounding_bit == 0) // 0 wird abgerundet + || ( (r.len == 0) // genau halbzahlig + && ((mantx & bit(0)) ==0) // -> round-to-even + ) ) + // abrunden + {} + else + // aufrunden + { mantx += 1; + if (mantx >= bit(DF_mant_len+1)) // rounding overflow? + { mantx = mantx>>1; exp1 = exp1+1; } + } } + #else + if (manthi >= bit(DF_mant_len-32+2)) + // Quotient >=2^54 -> 2 Bits wegrunden + { var uintL rounding_bits = mantlo & (bit(2)-1); + exp1 += 1; // Exponenten incrementieren + mantlo = (mantlo >> 2) | (manthi << 30); manthi = manthi >> 2; + if ( (rounding_bits < bit(1)) // 00,01 werden abgerundet + || ( (rounding_bits == bit(1)) // 10 + && (r.len == 0) // und genau halbzahlig + && ((mantlo & bit(0)) ==0) // -> round-to-even + ) ) + // abrunden + {} + else + // aufrunden + { mantlo += 1; if (mantlo==0) { manthi += 1; } } + } + else + // Quotient <2^54 -> 1 Bit wegrunden + { var uintL rounding_bit = mantlo & bit(0); + mantlo = (mantlo >> 1) | (manthi << 31); manthi = manthi >> 1; + if ( (rounding_bit == 0) // 0 wird abgerundet + || ( (r.len == 0) // genau halbzahlig + && ((mantlo & bit(0)) ==0) // -> round-to-even + ) ) + // abrunden + {} + else + // aufrunden + { mantlo += 1; + if (mantlo==0) + { manthi += 1; + if (manthi >= bit(DF_mant_len-32+1)) // rounding overflow? + { manthi = manthi>>1; exp1 = exp1+1; } + } } } + #endif + } + #if (cl_word_size==64) + return encode_DF(sign1,exp1,mantx); + #else + return encode_DF(sign1,exp1,manthi,mantlo); + #endif +#endif +} diff --git a/src/float/dfloat/elem/cl_DF_ffloor.cc b/src/float/dfloat/elem/cl_DF_ffloor.cc new file mode 100644 index 0000000..744ef79 --- /dev/null +++ b/src/float/dfloat/elem/cl_DF_ffloor.cc @@ -0,0 +1,24 @@ +// ffloor(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#include "cl_DF.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_DF_minusp.cc" + +const cl_DF ffloor (const cl_DF& x) +{ + if (minusp(x)) + return futruncate(x); + else + return ftruncate(x); +} diff --git a/src/float/dfloat/elem/cl_DF_from_I.cc b/src/float/dfloat/elem/cl_DF_from_I.cc new file mode 100644 index 0000000..a6c3957 --- /dev/null +++ b/src/float/dfloat/elem/cl_DF_from_I.cc @@ -0,0 +1,135 @@ +// cl_I_to_DF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_DF.h" + + +// Implementation. + +#include "cl_integer.h" +#include "cl_I.h" +#include "cl_DS.h" +#include "cl_F.h" + +const cl_DF cl_I_to_DF (const cl_I& x) +{ +// Methode: +// x=0 -> Ergebnis 0.0 +// Merke Vorzeichen von x. +// x:=(abs x) +// Exponent:=(integer-length x) +// Greife die 54 höchstwertigen Bits heraus (angeführt von einer 1). +// Runde das letzte Bit weg: +// Bit 0 = 0 -> abrunden, +// Bit 0 = 1 und Rest =0 -> round-to-even, +// Bit 0 = 1 und Rest >0 -> aufrunden. +// Dabei um ein Bit nach rechts schieben. +// Bei Aufrundung auf 2^53 (rounding overflow) Mantisse um 1 Bit nach rechts +// schieben und Exponent incrementieren. + if (eq(x,0)) { return cl_DF_0; } + var cl_signean sign = -(cl_signean)minusp(x); // Vorzeichen + var cl_I abs_x = (sign==0 ? x : -x); + var uintL exp = integer_length(abs_x); // (integer-length x) + // NDS zu |x|>0 bilden: + var const uintD* MSDptr; + var uintC len; + I_to_NDS_nocopy(abs_x, MSDptr=,len=,,cl_false,); + // MSDptr/len/LSDptr ist die NDS zu x, len>0. + // Führende Digits holen: Brauche DF_mant_len+1 Bits, dazu intDsize + // Bits (die NDS kann mit bis zu intDsize Nullbits anfangen). + // Dann werden diese Bits um (exp mod intDsize) nach rechts geschoben. + var uintD msd = msprefnext(MSDptr); // erstes Digit + #if (cl_word_size==64) + var uint64 msdd = 0; // weitere min(len-1,64/intDsize) Digits + #define NEXT_DIGIT(i) \ + { if (--len == 0) goto ok; \ + msdd |= (uint64)msprefnext(MSDptr) << (64-(i+1)*intDsize); \ + } + DOCONSTTIMES(64/intDsize,NEXT_DIGIT); + #undef NEXT_DIGIT + #else + var uint32 msdd = 0; // weitere min(len-1,32/intDsize) Digits + var uint32 msddf = 0; // weitere maximal 32/intDsize Digits + #define NEXT_DIGIT(i) \ + { if (--len == 0) goto ok; \ + msdd |= (uint32)msprefnext(MSDptr) << (32-(i+1)*intDsize); \ + } + DOCONSTTIMES(32/intDsize,NEXT_DIGIT); + #undef NEXT_DIGIT + #define NEXT_DIGIT(i) \ + { if (--len == 0) goto ok; \ + msddf |= (uint32)msprefnext(MSDptr) << (32-(i+1)*intDsize); \ + } + DOCONSTTIMES(32/intDsize,NEXT_DIGIT); + #undef NEXT_DIGIT + #endif + --len; ok: + #if (cl_word_size==64) + // Die NDS besteht aus msd, msdd und len weiteren Digits. + // Das höchste in 2^64*msd+msdd gesetzte Bit ist Bit Nummer + // 63 + (exp mod intDsize). + var uintL shiftcount = exp % intDsize; + var uint64 mant = // führende 64 Bits + (shiftcount==0 + ? msdd + : (((uint64)msd << (64-shiftcount)) | (msdd >> shiftcount)) + ); + // Das höchste in mant gesetzte Bit ist Bit Nummer 63. + if ( ((mant & bit(62-DF_mant_len)) ==0) // Bit 10 =0 -> abrunden + || ( ((mant & (bit(62-DF_mant_len)-1)) ==0) // Bit 10 =1 und Bits 9..0 =0 + && ((msdd & (bit(shiftcount)-1)) ==0) // und weitere Bits aus msddf =0 + && (!test_loop_msp(MSDptr,len)) // und alle weiteren Digits =0 + // round-to-even, je nach Bit 11 : + && ((mant & bit(63-DF_mant_len)) ==0) + ) ) + // abrunden + { mant = mant >> (63-DF_mant_len); } + else + // aufrunden + { mant = mant >> (63-DF_mant_len); + mant += 1; + if (mant >= bit(DF_mant_len+1)) // rounding overflow? + { mant = mant>>1; exp = exp+1; } + } + return encode_DF(sign,(sintL)exp,mant); + #else + // Die NDS besteht aus msd, msdd, msddf und len weiteren Digits. + // Das höchste in 2^64*msd+2^32*msdd+msddf gesetzte Bit ist Bit Nummer + // 63 + (exp mod intDsize). + var uintL shiftcount = exp % intDsize; + var uint32 manthi; // führende 32 Bits + var uint32 mantlo; // nächste 32 Bits + if (shiftcount==0) + { manthi = msdd; mantlo = msddf; } + else + { manthi = ((uint32)msd << (32-shiftcount)) | (msdd >> shiftcount); + mantlo = (msdd << (32-shiftcount)) | (msddf >> shiftcount); + } + // Das höchste in mant gesetzte Bit ist Bit Nummer 63. + if ( ((mantlo & bit(62-DF_mant_len)) ==0) // Bit 10 =0 -> abrunden + || ( ((mantlo & (bit(62-DF_mant_len)-1)) ==0) // Bit 10 =1 und Bits 9..0 =0 + && ((msddf & (bit(shiftcount)-1)) ==0) // und weitere Bits aus msddf =0 + && (!test_loop_msp(MSDptr,len)) // und alle weiteren Digits =0 + // round-to-even, je nach Bit 11 : + && ((mantlo & bit(63-DF_mant_len)) ==0) + ) ) + // abrunden + { mantlo = (mantlo >> (63-DF_mant_len)) | (manthi << (DF_mant_len-32+1)); + manthi = manthi >> (63-DF_mant_len); + } + else + // aufrunden + { mantlo = (mantlo >> (63-DF_mant_len)) | (manthi << (DF_mant_len-32+1)); + manthi = manthi >> (63-DF_mant_len); + mantlo += 1; + if (mantlo==0) + { manthi += 1; + if (manthi >= bit(DF_mant_len-32+1)) // rounding overflow? + { manthi = manthi>>1; exp = exp+1; } + } } + return encode_DF(sign,(sintL)exp,manthi,mantlo); + #endif +} diff --git a/src/float/dfloat/elem/cl_DF_from_RA.cc b/src/float/dfloat/elem/cl_DF_from_RA.cc new file mode 100644 index 0000000..13169d0 --- /dev/null +++ b/src/float/dfloat/elem/cl_DF_from_RA.cc @@ -0,0 +1,150 @@ +// cl_RA_to_DF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_DF.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" +#include "cl_I.h" +#include "cl_F.h" + +const cl_DF cl_RA_to_DF (const cl_RA& x) +{ +// Methode: +// x ganz -> klar. +// x = +/- a/b mit Integers a,b>0: +// Seien n,m so gewählt, daß +// 2^(n-1) <= a < 2^n, 2^(m-1) <= b < 2^m. +// Dann ist 2^(n-m-1) < a/b < 2^(n-m+1). +// Berechne n=(integer-length a) und m=(integer-length b) und +// floor(2^(-n+m+54)*a/b) : +// Bei n-m>=54 dividiere a durch (ash b (n-m-54)), +// bei n-m<54 dividiere (ash a (-n+m+54)) durch b. +// Der erste Wert ist >=2^53, <2^55. +// Falls er >=2^54 ist, runde 2 Bits weg, +// falls er <2^54 ist, runde 1 Bit weg. + if (integerp(x)) { + DeclareType(cl_I,x); + return cl_I_to_DF(x); + } + { // x Ratio + DeclareType(cl_RT,x); + var cl_I a = numerator(x); // +/- a + var const cl_I& b = denominator(x); // b + var cl_signean sign = -(cl_signean)minusp(a); // Vorzeichen + if (!(sign==0)) { a = -a; } // Betrag nehmen, liefert a + var sintL lendiff = (sintL)integer_length(a) // (integer-length a) + - (sintL)integer_length(b); // (integer-length b) + if (lendiff > DF_exp_high-DF_exp_mid) // Exponent >= n-m > Obergrenze ? + { cl_error_floating_point_overflow(); } // -> Overflow + if (lendiff < DF_exp_low-DF_exp_mid-2) // Exponent <= n-m+2 < Untergrenze ? + { if (underflow_allowed()) + { cl_error_floating_point_underflow(); } // -> Underflow + else + { return cl_DF_0; } + } + var cl_I zaehler; + var cl_I nenner; + if (lendiff >= DF_mant_len+2) + // n-m-54>=0 + { nenner = ash(b,lendiff - (DF_mant_len+2)); // (ash b n-m-54) + zaehler = a; // a + } + else + { zaehler = ash(a,(DF_mant_len+2) - lendiff); // (ash a -n+m+54) + nenner = b; // b + } + // Division zaehler/nenner durchführen: + var cl_I_div_t q_r = cl_divide(zaehler,nenner); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + // 2^53 <= q < 2^55, also ist q Bignum mit ceiling(55/intDsize) Digits. + var const uintD* ptr = BN_MSDptr(q); + #if (cl_word_size==64) + var uint64 mant = get_max64_Dptr(55,ptr); + if (mant >= bit(DF_mant_len+2)) + // 2^54 <= q < 2^55, schiebe um 2 Bits nach rechts + { var uint64 rounding_bits = mant & (bit(2)-1); + lendiff = lendiff+1; // Exponent := n-m+1 + mant = mant >> 2; + if ( (rounding_bits < bit(1)) // 00,01 werden abgerundet + || ( (rounding_bits == bit(1)) // 10 + && (eq(r,0)) // und genau halbzahlig (r=0) + && ((mant & bit(0)) ==0) // -> round-to-even + ) ) + // abrunden + goto ab; + else + // aufrunden + goto auf; + } + else + { var uint64 rounding_bit = mant & bit(0); + mant = mant >> 1; + if ( (rounding_bit == 0) // 0 wird abgerundet + || ( (eq(r,0)) // genau halbzahlig (r=0) + && ((mant & bit(0)) ==0) // -> round-to-even + ) ) + // abrunden + goto ab; + else + // aufrunden + goto auf; + } + auf: + mant += 1; + if (mant >= bit(DF_mant_len+1)) // rounding overflow? + { mant = mant>>1; lendiff = lendiff+1; } + ab: + // Fertig. + return encode_DF(sign,lendiff,mant); + #else + var uint32 manthi = get_max32_Dptr(23,ptr); + var uint32 mantlo = get_32_Dptr(ptr mspop ceiling(23,intDsize)); + if (manthi >= bit(DF_mant_len-32+2)) + // 2^54 <= q < 2^55, schiebe um 2 Bits nach rechts + { var uintL rounding_bits = mantlo & (bit(2)-1); + lendiff = lendiff+1; // Exponent := n-m+1 + mantlo = (mantlo >> 2) | (manthi << 30); manthi = manthi >> 2; + if ( (rounding_bits < bit(1)) // 00,01 werden abgerundet + || ( (rounding_bits == bit(1)) // 10 + && (eq(r,0)) // und genau halbzahlig (r=0) + && ((mantlo & bit(0)) ==0) // -> round-to-even + ) ) + // abrunden + goto ab; + else + // aufrunden + goto auf; + } + else + { var uintL rounding_bit = mantlo & bit(0); + mantlo = (mantlo >> 1) | (manthi << 31); manthi = manthi >> 1; + if ( (rounding_bit == 0) // 0 wird abgerundet + || ( (eq(r,0)) // genau halbzahlig (r=0) + && ((mantlo & bit(0)) ==0) // -> round-to-even + ) ) + // abrunden + goto ab; + else + // aufrunden + goto auf; + } + auf: + mantlo += 1; + if (mantlo==0) + { manthi += 1; + if (manthi >= bit(DF_mant_len-32+1)) // rounding overflow? + { manthi = manthi>>1; lendiff = lendiff+1; } + } + ab: + // Fertig. + return encode_DF(sign,lendiff,manthi,mantlo); + #endif +}} diff --git a/src/float/dfloat/elem/cl_DF_fround.cc b/src/float/dfloat/elem/cl_DF_fround.cc new file mode 100644 index 0000000..64fd2a7 --- /dev/null +++ b/src/float/dfloat/elem/cl_DF_fround.cc @@ -0,0 +1,168 @@ +// fround(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#include "cl_DF.h" + +const cl_DF fround (const cl_DF& x) +{ +// Methode: +// x = 0.0 oder e<0 -> Ergebnis 0.0 +// 0<=e<=52 -> letzte (53-e) Bits der Mantisse wegrunden, +// Exponent und Vorzeichen beibehalten. +// e>52 -> Ergebnis x +#if (cl_word_size==64) + var dfloat x_ = TheDfloat(x)->dfloat_value; + var uintL uexp = DF_uexp(x_); // e + DF_exp_mid + if (uexp < DF_exp_mid) // x = 0.0 oder e<0 ? + { return cl_DF_0; } + else + { if (uexp > DF_exp_mid+DF_mant_len) // e > 52 ? + { return x; } + else + if (uexp > DF_exp_mid+1) // e>1 ? + { var uint64 bitmask = // Bitmaske: Bit 52-e gesetzt, alle anderen gelöscht + bit(DF_mant_len+DF_exp_mid-uexp); + var uint64 mask = // Bitmaske: Bits 51-e..0 gesetzt, alle anderen gelöscht + bitmask-1; + if ( ((x_ & bitmask) ==0) // Bit 52-e =0 -> abrunden + || ( ((x_ & mask) ==0) // Bit 52-e =1 und Bits 51-e..0 >0 -> aufrunden + // round-to-even, je nach Bit 53-e : + && ((x_ & (bitmask<<1)) ==0) + ) ) + // abrunden + { mask |= bitmask; // Bitmaske: Bits 52-e..0 gesetzt, alle anderen gelöscht + return allocate_dfloat( x_ & ~mask ); + } + else + // aufrunden + { return allocate_dfloat + ((x_ | mask) // alle diese Bits 51-e..0 setzen (Bit 52-e schon gesetzt) + + 1 // letzte Stelle erhöhen, dabei evtl. Exponenten incrementieren + ); + } + } + elif (uexp == DF_exp_mid+1) // e=1 ? + // Wie bei 1 < e <= 52, nur daß Bit 53-e stets gesetzt ist. + { if ((x_ & bit(DF_mant_len-1)) ==0) // Bit 52-e =0 -> abrunden + // abrunden + { return allocate_dfloat( x_ & ~(bit(DF_mant_len)-1) ); } + else + // aufrunden + { return allocate_dfloat + ((x_ | (bit(DF_mant_len)-1)) // alle diese Bits 52-e..0 setzen + + 1 // letzte Stelle erhöhen, dabei evtl. Exponenten incrementieren + ); + } + } + else // e=0 ? + // Wie bei 1 < e <= 52, nur daß Bit 52-e stets gesetzt + // und Bit 53-e stets gelöscht ist. + { if ((x_ & (bit(DF_mant_len)-1)) ==0) + // abrunden von +-0.5 zu 0.0 + { return cl_DF_0; } + else + // aufrunden + { return allocate_dfloat + ((x_ | (bit(DF_mant_len)-1)) // alle Bits 51-e..0 setzen + + 1 // letzte Stelle erhöhen, dabei Exponenten incrementieren + ); + } } + } +#else + var uint32 semhi = TheDfloat(x)->dfloat_value.semhi; + var uint32 mlo = TheDfloat(x)->dfloat_value.mlo; + var uintL uexp = DF_uexp(semhi); // e + DF_exp_mid + if (uexp < DF_exp_mid) // x = 0.0 oder e<0 ? + { return cl_DF_0; } + else + { if (uexp > DF_exp_mid+DF_mant_len) // e > 52 ? + { return x; } + else + if (uexp > DF_exp_mid+1) // e>1 ? + { if (uexp > DF_exp_mid+DF_mant_len-32) // e > 20 ? + { var uint32 bitmask = // Bitmaske: Bit 52-e gesetzt, alle anderen gelöscht + bit(DF_mant_len+DF_exp_mid-uexp); + var uint32 mask = // Bitmaske: Bits 51-e..0 gesetzt, alle anderen gelöscht + bitmask-1; + if ( ((mlo & bitmask) ==0) // Bit 52-e =0 -> abrunden + || ( ((mlo & mask) ==0) // Bit 52-e =1 und Bits 51-e..0 >0 -> aufrunden + // round-to-even, je nach Bit 53-e : + && ( ((bitmask<<1) == 0) // e=21 ? + ? ((semhi & bit(0)) ==0) + : ((mlo & (bitmask<<1)) ==0) + ) ) ) + // abrunden + { mask |= bitmask; // Bitmaske: Bits 52-e..0 gesetzt, alle anderen gelöscht + return allocate_dfloat(semhi, mlo & ~mask ); + } + else + // aufrunden + { mlo = (mlo | mask) // alle diese Bits 51-e..0 setzen (Bit 52-e schon gesetzt) + + 1; // letzte Stelle erhöhen, + if (mlo==0) { semhi += 1; } // dabei evtl. Exponenten incrementieren + return allocate_dfloat(semhi,mlo); + } + } + else + { var uint32 bitmask = // Bitmaske: Bit 20-e gesetzt, alle anderen gelöscht + bit(DF_mant_len+DF_exp_mid-32-uexp); + var uint32 mask = // Bitmaske: Bits 19-e..0 gesetzt, alle anderen gelöscht + bitmask-1; + if ( ((semhi & bitmask) ==0) // Bit 52-e =0 -> abrunden + || ( (mlo==0) && ((semhi & mask) ==0) // Bit 52-e =1 und Bits 51-e..0 >0 -> aufrunden + // round-to-even, je nach Bit 53-e : + && ((semhi & (bitmask<<1)) ==0) + ) ) + // abrunden + { mask |= bitmask; // Bitmaske: Bits 20-e..0 gesetzt, alle anderen gelöscht + return allocate_dfloat( semhi & ~mask, 0 ); + } + else + // aufrunden + { return allocate_dfloat + ((semhi | mask) // alle diese Bits 19-e..0 setzen (Bit 20-e schon gesetzt) + + 1, // letzte Stelle erhöhen, dabei evtl. Exponenten incrementieren + 0 + ); + } + } + } + elif (uexp == DF_exp_mid+1) // e=1 ? + // Wie bei 1 < e <= 20, nur daß Bit 53-e stets gesetzt ist. + { if ((semhi & bit(DF_mant_len-32-1)) ==0) // Bit 52-e =0 -> abrunden + // abrunden + { return allocate_dfloat( semhi & ~(bit(DF_mant_len-32)-1) , 0 ); } + else + // aufrunden + { return allocate_dfloat + ((semhi | (bit(DF_mant_len-32)-1)) // alle diese Bits 52-e..0 setzen + + 1, // letzte Stelle erhöhen, dabei evtl. Exponenten incrementieren + 0 + ); + } + } + else // e=0 ? + // Wie bei 1 < e <= 20, nur daß Bit 52-e stets gesetzt + // und Bit 53-e stets gelöscht ist. + { if ((mlo==0) && ((semhi & (bit(DF_mant_len-32)-1)) ==0)) + // abrunden von +-0.5 zu 0.0 + { return cl_DF_0; } + else + // aufrunden + { return allocate_dfloat + ((semhi | (bit(DF_mant_len-32)-1)) // alle Bits 51-e..0 setzen + + 1, // letzte Stelle erhöhen, dabei Exponenten incrementieren + 0 + ); + } } + } +#endif +} diff --git a/src/float/dfloat/elem/cl_DF_ftrunc.cc b/src/float/dfloat/elem/cl_DF_ftrunc.cc new file mode 100644 index 0000000..d00a630 --- /dev/null +++ b/src/float/dfloat/elem/cl_DF_ftrunc.cc @@ -0,0 +1,62 @@ +// ftruncate(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#include "cl_DF.h" + +const cl_DF ftruncate (const cl_DF& x) +{ +// Methode: +// x = 0.0 oder e<=0 -> Ergebnis 0.0 +// 1<=e<=52 -> letzte (53-e) Bits der Mantisse auf 0 setzen, +// Exponent und Vorzeichen beibehalten +// e>=53 -> Ergebnis x +#if (cl_word_size==64) + var dfloat x_ = TheDfloat(x)->dfloat_value; + var uintL uexp = DF_uexp(x_); // e + DF_exp_mid + if (uexp <= DF_exp_mid) // 0.0 oder e<=0 ? + { return cl_DF_0; } + else + { if (uexp > DF_exp_mid+DF_mant_len) // e > 52 ? + { return x; } + else + // 1<=e<=52 + { return allocate_dfloat + ( x_ & // Bitmaske: Bits 52-e..0 gelöscht, alle anderen gesetzt + ~(bit(DF_mant_len+1+DF_exp_mid-uexp)-1) + ); + } } +#else + var uint32 semhi = TheDfloat(x)->dfloat_value.semhi; + var uint32 mlo = TheDfloat(x)->dfloat_value.mlo; + var uintL uexp = DF_uexp(semhi); // e + DF_exp_mid + if (uexp <= DF_exp_mid) // 0.0 oder e<=0 ? + { return cl_DF_0; } + else + { if (uexp > DF_exp_mid+DF_mant_len) // e > 52 ? + { return x; } + else + // 1<=e<=52 + if (uexp > DF_exp_mid+DF_mant_len+1-32) // e > 21 ? + { return allocate_dfloat + ( semhi, + mlo & // Bitmaske: Bits 52-e..0 gelöscht, alle anderen gesetzt + ~(bit(DF_mant_len+1+DF_exp_mid-uexp)-1) + ); + } + else + { return allocate_dfloat + ( semhi & // Bitmaske: Bits 20-e..0 gelöscht, alle anderen gesetzt + ~(bit(DF_mant_len+1+DF_exp_mid-32-uexp)-1), + 0 + ); + } } +#endif +} diff --git a/src/float/dfloat/elem/cl_DF_futrunc.cc b/src/float/dfloat/elem/cl_DF_futrunc.cc new file mode 100644 index 0000000..1277ea0 --- /dev/null +++ b/src/float/dfloat/elem/cl_DF_futrunc.cc @@ -0,0 +1,82 @@ +// futruncate(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_DF.h" + + +// Implementation. + +const cl_DF futruncate (const cl_DF& x) +{ +// Methode: +// x = 0.0 -> Ergebnis 0.0 +// e<=0 -> Ergebnis 1.0 oder -1.0, je nach Vorzeichen von x. +// 1<=e<=52 -> Greife die letzten (53-e) Bits von x heraus. +// Sind sie alle =0 -> Ergebnis x. +// Sonst setze sie alle und erhöhe dann die letzte Stelle um 1. +// Kein Überlauf der 52 Bit -> fertig. +// Sonst (Ergebnis eine Zweierpotenz): Mantisse := .1000...000, +// e:=e+1. (Test auf Überlauf wegen e<=53 überflüssig) +// e>=53 -> Ergebnis x. +#if (cl_word_size==64) + var dfloat x_ = TheDfloat(x)->dfloat_value; + var uintL uexp = DF_uexp(x_); // e + DF_exp_mid + if (uexp==0) // 0.0 ? + { return x; } + if (uexp <= DF_exp_mid) // e<=0 ? + { // Exponent auf 1, Mantisse auf .1000...000 setzen. + return ((x_ & bit(63))==0 ? cl_DF_1 : cl_DF_minus1); + } + else + { if (uexp > DF_exp_mid+DF_mant_len) // e > 52 ? + { return x; } + else + { var uint64 mask = // Bitmaske: Bits 52-e..0 gesetzt, alle anderen gelöscht + bit(DF_mant_len+1+DF_exp_mid-uexp)-1; + if ((x_ & mask)==0) // alle diese Bits =0 ? + { return x; } + return allocate_dfloat + ((x_ | mask) // alle diese Bits setzen + + 1 // letzte Stelle erhöhen, dabei evtl. Exponenten incrementieren + ); + } } +#else + var uint32 semhi = TheDfloat(x)->dfloat_value.semhi; + var uint32 mlo = TheDfloat(x)->dfloat_value.mlo; + var uintL uexp = DF_uexp(semhi); // e + DF_exp_mid + if (uexp==0) // 0.0 ? + { return x; } + if (uexp <= DF_exp_mid) // e<=0 ? + { // Exponent auf 1, Mantisse auf .1000...000 setzen. + return ((semhi & bit(31))==0 ? cl_DF_1 : cl_DF_minus1); + } + else + { if (uexp > DF_exp_mid+DF_mant_len) // e > 52 ? + { return x; } + else + if (uexp > DF_exp_mid+DF_mant_len+1-32) // e > 21 ? + { var uint32 mask = // Bitmaske: Bits 52-e..0 gesetzt, alle anderen gelöscht + bit(DF_mant_len+1+DF_exp_mid-uexp)-1; + if ((mlo & mask)==0) // alle diese Bits =0 ? + { return x; } + mlo = (mlo | mask) // alle diese Bits setzen + + 1; // letzte Stelle erhöhen, + if (mlo==0) { semhi += 1; } // dabei evtl. Exponenten incrementieren + return allocate_dfloat(semhi,mlo); + } + else + { var uint32 mask = // Bitmaske: Bits 20-e..0 gesetzt, alle anderen gelöscht + bit(DF_mant_len+1+DF_exp_mid-32-uexp)-1; + if ((mlo==0) && ((semhi & mask)==0)) // alle diese Bits und mlo =0 ? + { return x; } + return allocate_dfloat + ((semhi | mask) // alle diese Bits setzen + + 1, // letzte Stelle erhöhen, dabei evtl. Exponenten incrementieren + 0 + ); + } } +#endif +} diff --git a/src/float/dfloat/elem/cl_DF_globals.cc b/src/float/dfloat/elem/cl_DF_globals.cc new file mode 100644 index 0000000..f64c98e --- /dev/null +++ b/src/float/dfloat/elem/cl_DF_globals.cc @@ -0,0 +1,32 @@ +// Global variables for cl_DF. + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_DF_globals) + +// Specification. +#include "cl_DF.h" + + +// Implementation. + +#if (cl_word_size==64) + +const cl_DF cl_DF_0 = allocate_dfloat(0); // 0.0d0 + +const cl_DF cl_DF_1 = encode_DF(0,1,bit(DF_mant_len)); // 1.0d0 + +const cl_DF cl_DF_minus1 = encode_DF(-1,1,bit(DF_mant_len)); // -1.0d0 + +#else + +const cl_DF cl_DF_0 = allocate_dfloat(0,0); // 0.0d0 + +const cl_DF cl_DF_1 = encode_DF(0,1,bit(DF_mant_len-32),0); // 1.0d0 + +const cl_DF cl_DF_minus1 = encode_DF(-1,1,bit(DF_mant_len-32),0); // -1.0d0 + +#endif + +CL_PROVIDE_END(cl_DF_globals) diff --git a/src/float/dfloat/elem/cl_DF_minus.cc b/src/float/dfloat/elem/cl_DF_minus.cc new file mode 100644 index 0000000..ce24ac3 --- /dev/null +++ b/src/float/dfloat/elem/cl_DF_minus.cc @@ -0,0 +1,43 @@ +// binary operator - + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#include "cl_DF.h" +#include "cl_ieee.h" +NEED_IEEE_FLOATS() + +const cl_DF operator- (const cl_DF& x1, const cl_DF& x2) +{ +// Methode: +// (- x1 x2) = (+ x1 (- x2)) +#ifdef FAST_DOUBLE + double_to_DF(DF_to_double(x1) - DF_to_double(x2), return , + TRUE, TRUE, // Overflow und subnormale Zahl abfangen + FALSE, // kein Underflow mit Ergebnis +/- 0.0 möglich + // (nach Definition der subnormalen Zahlen) + FALSE, FALSE // keine Singularität, kein NaN als Ergebnis möglich + ); +#else +#if (cl_word_size==64) + var dfloat x2_ = TheDfloat(x2)->dfloat_value; + if (DF_uexp(x2_) == 0) + { return x1; } + else + { return x1 + allocate_dfloat(x2_ ^ bit(63)); } +#else + var uint32 x2_semhi = TheDfloat(x2)->dfloat_value.semhi; + var uint32 x2_mlo = TheDfloat(x2)->dfloat_value.mlo; + if (DF_uexp(x2_semhi) == 0) + { return x1; } + else + { return x1 + allocate_dfloat(x2_semhi ^ bit(31), x2_mlo); } +#endif +#endif +} diff --git a/src/float/dfloat/elem/cl_DF_minusp.cc b/src/float/dfloat/elem/cl_DF_minusp.cc new file mode 100644 index 0000000..a5605bf --- /dev/null +++ b/src/float/dfloat/elem/cl_DF_minusp.cc @@ -0,0 +1,22 @@ +// minusp(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#include "cl_DF.h" + +MAYBE_INLINE +cl_boolean minusp (const cl_DF& x) +{ +#if (cl_word_size==64) + return (cl_boolean) ((sint64)TheDfloat(x)->dfloat_value_semhi < 0); +#else + return (cl_boolean) ((sint32)TheDfloat(x)->dfloat_value_semhi < 0); +#endif +} diff --git a/src/float/dfloat/elem/cl_DF_mul.cc b/src/float/dfloat/elem/cl_DF_mul.cc new file mode 100644 index 0000000..783a503 --- /dev/null +++ b/src/float/dfloat/elem/cl_DF_mul.cc @@ -0,0 +1,209 @@ +// binary operator * + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#include "cl_DF.h" +#include "cl_F.h" +#include "cl_low.h" +#include "cl_DS.h" +#include "cl_ieee.h" +NEED_IEEE_FLOATS() + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_DF_zerop.cc" + +const cl_DF operator* (const cl_DF& x1, const cl_DF& x2) +{ +// Methode: +// Falls x1=0.0 oder x2=0.0 -> Ergebnis 0.0 +// Sonst: Ergebnis-Vorzeichen = VZ von x1 xor VZ von x2. +// Ergebnis-Exponent = Summe der Exponenten von x1 und x2. +// Ergebnis-Mantisse = Produkt der Mantissen von x1 und x2, gerundet: +// 2^-53 * mant1 * 2^-53 * mant2 = 2^-106 * (mant1*mant2), +// die Klammer ist >=2^104, <=(2^53-1)^2<2^106 . +// Falls die Klammer >=2^105 ist, um 53 Bit nach rechts schieben und +// runden: Falls Bit 52 Null, abrunden; falls Bit 52 Eins und +// Bits 51..0 alle Null, round-to-even; sonst aufrunden. +// Falls die Klammer <2^105 ist, um 52 Bit nach rechts schieben und +// runden: Falls Bit 51 Null, abrunden; falls Bit 51 Eins und +// Bits 50..0 alle Null, round-to-even; sonst aufrunden. Nach +// Aufrunden: Falls =2^53, um 1 Bit nach rechts schieben. Sonst +// Exponenten um 1 erniedrigen. +#ifdef FAST_DOUBLE + double_to_DF(DF_to_double(x1) * DF_to_double(x2), return , + TRUE, TRUE, // Overflow und subnormale Zahl abfangen + !(zerop(x1) || zerop(x2)), // ein Ergebnis +/- 0.0 + // ist genau dann in Wirklichkeit ein Underflow + FALSE, FALSE // keine Singularität, kein NaN als Ergebnis möglich + ); +#else + // x1,x2 entpacken: + var cl_signean sign1; + var sintL exp1; + #if (intDsize<=32) + var uintL manthi1; + var uintL mantlo1; + #endif + var cl_signean sign2; + var sintL exp2; + #if (intDsize<=32) + var uintL manthi2; + var uintL mantlo2; + #endif + #if (cl_word_size==64) + var uint64 mantx1; + DF_decode(x1, { return x1; }, sign1=,exp1=,mantx1=); + #if (intDsize<=32) + manthi1 = high32(mantx1); mantlo1 = low32(mantx1); + #endif + var uint64 mantx2; + DF_decode(x2, { return x2; }, sign2=,exp2=,mantx2=); + #if (intDsize<=32) + manthi2 = high32(mantx2); mantlo2 = low32(mantx2); + #endif + #else + DF_decode2(x1, { return x1; }, sign1=,exp1=,manthi1=,mantlo1=); + DF_decode2(x2, { return x2; }, sign2=,exp2=,manthi2=,mantlo2=); + #endif + exp1 = exp1 + exp2; // Summe der Exponenten + sign1 = sign1 ^ sign2; // Ergebnis-Vorzeichen + // Mantissen mant1 und mant2 multiplizieren (64x64-Bit-Multiplikation): + var uintD mant1 [64/intDsize]; + var uintD mant2 [64/intDsize]; + var uintD mant [128/intDsize]; + #if (intDsize==64) + arrayLSref(mant1,64/intDsize,0) = mantx1; + arrayLSref(mant2,64/intDsize,0) = mantx2; + #elif (intDsize==32) || (intDsize==16) || (intDsize==8) + set_32_Dptr(arrayMSDptr(mant1,64/intDsize),manthi1); + set_32_Dptr(arrayMSDptr(mant1,64/intDsize) mspop 32/intDsize,mantlo1); + set_32_Dptr(arrayMSDptr(mant2,64/intDsize),manthi2); + set_32_Dptr(arrayMSDptr(mant2,64/intDsize) mspop 32/intDsize,mantlo2); + #else + {var uintD* ptr; + ptr = arrayLSDptr(mant1,64/intDsize); + doconsttimes(32/intDsize, { lsprefnext(ptr) = (uintD)mantlo1; mantlo1 = mantlo1>>intDsize; } ); + doconsttimes(32/intDsize, { lsprefnext(ptr) = (uintD)manthi1; manthi1 = manthi1>>intDsize; } ); + } + {var uintD* ptr; + ptr = arrayLSDptr(mant2,64/intDsize); + doconsttimes(32/intDsize, { lsprefnext(ptr) = (uintD)mantlo2; mantlo2 = mantlo2>>intDsize; } ); + doconsttimes(32/intDsize, { lsprefnext(ptr) = (uintD)manthi2; manthi2 = manthi2>>intDsize; } ); + } + #endif + cl_UDS_mul(arrayLSDptr(mant1,64/intDsize),64/intDsize, + arrayLSDptr(mant2,64/intDsize),64/intDsize, + arrayLSDptr(mant,128/intDsize) + ); + { + #if (cl_word_size==64) + var uint64 manterg; + #else + var uintL manthi; + var uintL mantlo; + #endif + // Produkt mant = mant1 * mant2 ist >= 2^104, < 2^106. Bit 105 abtesten: + #define mant_bit(k) (arrayLSref(mant,128/intDsize,floor(k,intDsize)) & bit((k)%intDsize)) + if (mant_bit(2*DF_mant_len+1)) + // mant>=2^(2*DF_mant_len+1), um DF_mant_len+1 Bits nach rechts schieben: + { // Bits 105..53 holen: + #if (cl_word_size==64) && (intDsize==64) + manterg = ((uint64)arrayLSref(mant,2,1) << 11) | ((uint64)arrayLSref(mant,2,0) >> 53); // Bits 116..53 + #define mantrest() (arrayLSref(mant,2,0) & (bit(53)-1)) + #elif (cl_word_size==64) && (intDsize==32) + manterg = ((uint64)arrayLSref(mant,4,3) << 43) | ((uint64)arrayLSref(mant,4,2) << 11) | ((uint64)arrayLSref(mant,4,1) >> 21); // Bits 116..53 + #define mantrest() ((arrayLSref(mant,4,1) & (bit(21)-1)) || arrayLSref(mant,4,0)) + #elif (intDsize==32) + manthi = ((uint32)arrayLSref(mant,4,3) << 11) | ((uint32)arrayLSref(mant,4,2) >> 21); // Bits 116..85 + mantlo = ((uint32)arrayLSref(mant,4,2) << 11) | ((uint32)arrayLSref(mant,4,1) >> 21); // Bits 84..53 + #define mantrest() ((arrayLSref(mant,4,1) & (bit(21)-1)) || arrayLSref(mant,4,0)) + #elif (intDsize==16) + manthi = ((uint32)arrayLSref(mant,8,7) << 27) | ((uint32)arrayLSref(mant,8,6) << 11) | ((uint32)arrayLSref(mant,8,5) >> 5); // Bits 116..85 + mantlo = ((uint32)arrayLSref(mant,8,5) << 27) | ((uint32)arrayLSref(mant,8,4) << 11) | ((uint32)arrayLSref(mant,8,3) >> 5); // Bits 84..53 + #define mantrest() ((arrayLSref(mant,8,3) & (bit(5)-1)) || arrayLSref(mant,8,2) || arrayLSref(mant,8,1) || arrayLSref(mant,8,0)) + #elif (intDsize==8) + manthi = ((uint32)arrayLSref(mant,16,14) << 27) | ((uint32)arrayLSref(mant,16,13) << 19) | ((uint32)arrayLSref(mant,16,12) << 11) | ((uint32)arrayLSref(mant,16,11) << 3) | ((uint32)arrayLSref(mant,16,10) >> 5); // Bits 116..85 + mantlo = ((uint32)arrayLSref(mant,16,10) << 27) | ((uint32)arrayLSref(mant,16,9) << 19) | ((uint32)arrayLSref(mant,16,8) << 11) | ((uint32)arrayLSref(mant,16,7) << 3) | ((uint32)arrayLSref(mant,16,6) >> 5); // Bits 84..53 + #define mantrest() ((arrayLSref(mant,16,6) & (bit(5)-1)) || arrayLSref(mant,16,5) || arrayLSref(mant,16,4) || arrayLSref(mant,16,3) || arrayLSref(mant,16,2) || arrayLSref(mant,16,1) || arrayLSref(mant,16,0)) + #endif + if ( (mant_bit(DF_mant_len) ==0) // Bit DF_mant_len =0 -> abrunden + || ( !mantrest() // Bit DF_mant_len =1 und Bits DF_mant_len-1..0 >0 -> aufrunden + // round-to-even, je nach Bit DF_mant_len+1 : + && (mant_bit(DF_mant_len+1) ==0) + ) ) + // abrunden + goto ab; + else + // aufrunden + goto auf; + #undef mantrest + } + else + // mant<2^(2*DF_mant_len+1), um DF_mant_len Bits nach rechts schieben: + { exp1 = exp1-1; // Exponenten decrementieren + // Bits 104..52 holen: + #if (cl_word_size==64) && (intDsize==64) + manterg = ((uint64)arrayLSref(mant,2,1) << 12) | ((uint64)arrayLSref(mant,2,0) >> 52); // Bits 115..52 + #define mantrest() (arrayLSref(mant,2,0) & (bit(52)-1)) + #elif (cl_word_size==64) && (intDsize==32) + manterg = ((uint64)arrayLSref(mant,4,3) << 44) | ((uint64)arrayLSref(mant,4,2) << 12) | ((uint64)arrayLSref(mant,4,1) >> 20); // Bits 115..52 + #define mantrest() ((arrayLSref(mant,4,1) & (bit(20)-1)) || arrayLSref(mant,4,0)) + #elif (intDsize==32) + manthi = ((uint32)arrayLSref(mant,4,3) << 12) | ((uint32)arrayLSref(mant,4,2) >> 20); // Bits 115..84 + mantlo = ((uint32)arrayLSref(mant,4,2) << 12) | ((uint32)arrayLSref(mant,4,1) >> 20); // Bits 83..52 + #define mantrest() ((arrayLSref(mant,4,1) & (bit(20)-1)) || arrayLSref(mant,4,0)) + #elif (intDsize==16) + manthi = // ((uint32)arrayLSref(mant,8,7) << 28) | ((uint32)arrayLSref(mant,8,6) << 12) | ((uint32)arrayLSref(mant,8,5) >> 4); // Bits 115..84 + mantlo = // ((uint32)arrayLSref(mant,8,5) << 28) | ((uint32)arrayLSref(mant,8,4) << 12) | ((uint32)arrayLSref(mant,8,3) >> 4); // Bits 83..52 + #define mantrest() ((arrayLSref(mant,8,3) & (bit(4)-1)) || arrayLSref(mant,8,2) || arrayLSref(mant,8,1) || arrayLSref(mant,8,0)) + #elif (intDsize==8) + manthi = ((uint32)arrayLSref(mant,16,14) << 28) | ((uint32)arrayLSref(mant,16,13) << 20) | ((uint32)arrayLSref(mant,16,12) << 12) | ((uint32)arrayLSref(mant,16,11) << 4) | ((uint32)arrayLSref(mant,16,10) >> 4); // Bits 115..84 + mantlo = ((uint32)arrayLSref(mant,16,10) << 28) | ((uint32)arrayLSref(mant,16,9) << 20) | ((uint32)arrayLSref(mant,16,8) << 12) | ((uint32)arrayLSref(mant,16,7) << 4) | ((uint32)arrayLSref(mant,16,6) >> 4); // Bits 83..52 + #define mantrest() ((arrayLSref(mant,16,6) & (bit(4)-1)) || arrayLSref(mant,16,5) || arrayLSref(mant,16,4) || arrayLSref(mant,16,3) || arrayLSref(mant,16,2) || arrayLSref(mant,16,1) || arrayLSref(mant,16,0)) + #endif + if ( (mant_bit(DF_mant_len-1) ==0) // Bit DF_mant_len-1 =0 -> abrunden + || ( !mantrest() // Bit DF_mant_len-1 =1 und Bits DF_mant_len-2..0 >0 -> aufrunden + // round-to-even, je nach Bit DF_mant_len : + && (mant_bit(DF_mant_len) ==0) + ) ) + // abrunden + goto ab; + else + // aufrunden + goto auf; + #undef mantrest + } + #undef mant_bit + auf: + #if (cl_word_size==64) + manterg = manterg+1; + // Hier ist 2^DF_mant_len <= manterg <= 2^(DF_mant_len+1) + if (manterg >= bit(DF_mant_len+1)) // rounding overflow? + { manterg = manterg>>1; exp1 = exp1+1; } // Shift nach rechts + #else + mantlo = mantlo+1; + if (mantlo==0) + { manthi = manthi+1; + // Hier ist 2^(DF_mant_len-32) <= manthi <= 2^(DF_mant_len-32+1) + if (manthi >= bit(DF_mant_len-32+1)) // rounding overflow? + { manthi = manthi>>1; exp1 = exp1+1; } // Shift nach rechts + } + #endif + ab: + // Runden fertig, 2^DF_mant_len <= manterg < 2^(DF_mant_len+1) + #if (cl_word_size==64) + return encode_DF(sign1,exp1,manterg); + #else + return encode_DF(sign1,exp1,manthi,mantlo); + #endif + } +#endif +} diff --git a/src/float/dfloat/elem/cl_DF_plus.cc b/src/float/dfloat/elem/cl_DF_plus.cc new file mode 100644 index 0000000..781cb3c --- /dev/null +++ b/src/float/dfloat/elem/cl_DF_plus.cc @@ -0,0 +1,260 @@ +// binary operator + + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#include "cl_DF.h" +#include "cl_F.h" +#include "cl_ieee.h" +NEED_IEEE_FLOATS() +#include "cl_xmacros.h" + +const cl_DF operator+ (const cl_DF& x1, const cl_DF& x2) +{ +// Methode (nach [Knuth, II, Seminumerical Algorithms, Abschnitt 4.2.1., S.200]): +// x1=0.0 -> Ergebnis x2. +// x2=0.0 -> Ergebnis x1. +// Falls e1= e2. +// Falls e1 - e2 >= 52 + 3, Ergebnis x1. +// Schiebe beide Mantissen um 3 Bits nach links (Vorbereitung der Rundung: +// Bei e1-e2=0,1 ist keine Rundung nötig, bei e1-e2>1 ist der Exponent des +// Ergebnisses =e1-1, =e1 oder =e1+1. Brauche daher 1 Schutzbit und zwei +// Rundungsbits: 00 exakt, 01 1.Hälfte, 10 exakte Mitte, 11 2.Hälfte.) +// Schiebe die Mantisse von x2 um e0-e1 Bits nach rechts. (Dabei die Rundung +// ausführen: Bit 0 ist das logische Oder der Bits 0,-1,-2,...) +// Falls x1,x2 selbes Vorzeichen haben: Addiere dieses zur Mantisse von x1. +// Falls x1,x2 verschiedenes Vorzeichen haben: Subtrahiere dieses von der +// Mantisse von x1. <0 -> (Es war e1=e2) Vertausche die Vorzeichen, negiere. +// =0 -> Ergebnis 0.0 +// Exponent ist e1. +// Normalisiere, fertig. +#ifdef FAST_DOUBLE + double_to_DF(DF_to_double(x1) + DF_to_double(x2), return , + TRUE, TRUE, // Overflow und subnormale Zahl abfangen + FALSE, // kein Underflow mit Ergebnis +/- 0.0 möglich + // (nach Definition der subnormalen Zahlen) + FALSE, FALSE // keine Singularität, kein NaN als Ergebnis möglich + ); +#else +#if (cl_word_size==64) + // x1,x2 entpacken: + var cl_signean sign1; + var sintL exp1; + var uint64 mant1; + var cl_signean sign2; + var sintL exp2; + var uint64 mant2; + DF_decode(x1, { return x2; }, sign1=,exp1=,mant1=); + DF_decode(x2, { return x1; }, sign2=,exp2=,mant2=); + var cl_DF max_x1_x2 = x1; + if (exp1 < exp2) + { max_x1_x2 = x2; + swap(cl_signean, sign1,sign2); + swap(sintL, exp1 ,exp2 ); + swap(uint64, mant1,mant2); + } + // Nun ist exp1>=exp2. + var uintL expdiff = exp1 - exp2; // Exponentendifferenz + if (expdiff >= DF_mant_len+3) // >= 52+3 ? + { return max_x1_x2; } + mant1 = mant1 << 3; mant2 = mant2 << 3; + // Nun 2^(DF_mant_len+3) <= mant1,mant2 < 2^(DF_mant_len+4). + {var uint64 mant2_last = mant2 & (bit(expdiff)-1); // letzte expdiff Bits von mant2 + mant2 = mant2 >> expdiff; if (!(mant2_last==0)) { mant2 |= bit(0); } + } + // mant2 = um expdiff Bits nach rechts geschobene und gerundete Mantisse + // von x2. + if (!(sign1==sign2)) + // verschiedene Vorzeichen -> Mantissen subtrahieren + { if (mant1 > mant2) { mant1 = mant1 - mant2; goto norm_2; } + if (mant1 == mant2) // Ergebnis 0 ? + { return cl_DF_0; } + // negatives Subtraktionsergebnis + mant1 = mant2 - mant1; sign1 = sign2; goto norm_2; + } + else + // gleiche Vorzeichen -> Mantissen addieren + { mant1 = mant1 + mant2; } + // mant1 = Ergebnis-Mantisse >0, sign1 = Ergebnis-Vorzeichen, + // exp1 = Ergebnis-Exponent. + // Außerdem: Bei expdiff=0,1 sind die zwei letzten Bits von mant1 Null, + // bei expdiff>=2 ist mant1 >= 2^(DF_mant_len+2). + // Stets ist mant1 < 2^(DF_mant_len+5). (Daher werden die 2 Rundungsbits + // nachher um höchstens eine Position nach links geschoben werden.) + // [Knuth, S.201, leicht modifiziert: + // N1. m>=1 -> goto N4. + // N2. [Hier m<1] m>=1/2 -> goto N5. + // N3. m:=2*m, e:=e-1, goto N2. + // N4. [Hier 1<=m<2] m:=m/2, e:=e+1. + // N5. [Hier 1/2<=m<1] Runde m auf 53 Bits hinterm Komma. + // Falls hierdurch m=1 geworden, setze m:=m/2, e:=e+1. + // ] + // Bei uns ist m=mant1/2^(DF_mant_len+4), + // ab Schritt N5 ist m=mant1/2^(DF_mant_len+1). + norm_1: // [Knuth, S.201, Schritt N1] + if (mant1 >= bit(DF_mant_len+4)) goto norm_4; + norm_2: // [Knuth, S.201, Schritt N2] + // Hier ist mant1 < 2^(DF_mant_len+4) + if (mant1 >= bit(DF_mant_len+3)) goto norm_5; + // [Knuth, S.201, Schritt N3] + mant1 = mant1 << 1; exp1 = exp1-1; // Mantisse links schieben + goto norm_2; + norm_4: // [Knuth, S.201, Schritt N4] + // Hier ist 2^(DF_mant_len+4) <= mant1 < 2^(DF_mant_len+5) + exp1 = exp1+1; + mant1 = (mant1>>1) | (mant1 & bit(0)); // Mantisse rechts schieben + norm_5: // [Knuth, S.201, Schritt N5] + // Hier ist 2^(DF_mant_len+3) <= mant1 < 2^(DF_mant_len+4) + // Auf DF_mant_len echte Mantissenbits runden, d.h. rechte 3 Bits + // wegrunden, und dabei mant1 um 3 Bits nach rechts schieben: + {var uint64 rounding_bits = mant1 & (bit(3)-1); + mant1 = mant1 >> 3; + if ( (rounding_bits < bit(2)) // 000,001,010,011 werden abgerundet + || ( (rounding_bits == bit(2)) // 100 (genau halbzahlig) + && ((mant1 & bit(0)) ==0) // -> round-to-even + ) ) + // abrunden + {} + else + // aufrunden + { mant1 = mant1+1; + if (mant1 >= bit(DF_mant_len+1)) + // Bei Überlauf während der Rundung nochmals rechts schieben + // (Runden ist hier überflüssig): + { mant1 = mant1>>1; exp1 = exp1+1; } // Mantisse rechts schieben + } + }// Runden fertig + return encode_DF(sign1,exp1,mant1); +#else + // x1,x2 entpacken: + var cl_signean sign1; + var sintL exp1; + var uintL manthi1; + var uintL mantlo1; + var cl_signean sign2; + var sintL exp2; + var uintL manthi2; + var uintL mantlo2; + DF_decode2(x1, { return x2; }, sign1=,exp1=,manthi1=,mantlo1=); + DF_decode2(x2, { return x1; }, sign2=,exp2=,manthi2=,mantlo2=); + var cl_DF max_x1_x2 = x1; + if (exp1 < exp2) + { max_x1_x2 = x2; + swap(cl_signean, sign1,sign2); + swap(sintL, exp1 ,exp2 ); + swap(uintL, manthi1,manthi2); + swap(uintL, mantlo1,mantlo2); + } + // Nun ist exp1>=exp2. + var uintL expdiff = exp1 - exp2; // Exponentendifferenz + if (expdiff >= DF_mant_len+3) // >= 52+3 ? + { return max_x1_x2; } + manthi1 = (manthi1 << 3) | (mantlo1 >> (32-3)); mantlo1 = mantlo1 << 3; + manthi2 = (manthi2 << 3) | (mantlo2 >> (32-3)); mantlo2 = mantlo2 << 3; + // Nun 2^(DF_mant_len+3) <= mant1,mant2 < 2^(DF_mant_len+4). + if (expdiff<32) + {if (!(expdiff==0)) + {var uintL mant2_last = mantlo2 & (bit(expdiff)-1); // letzte expdiff Bits von mant2 + mantlo2 = (mantlo2 >> expdiff) | (manthi2 << (32-expdiff)); + manthi2 = manthi2 >> expdiff; + if (!(mant2_last==0)) { mantlo2 |= bit(0); } + } } + else + {var uintL mant2_last = (manthi2 & (bit(expdiff-32)-1)) | mantlo2; // letzte expdiff Bits von mant2 + mantlo2 = manthi2 >> (expdiff-32); manthi2 = 0; + if (!(mant2_last==0)) { mantlo2 |= bit(0); } + } + // mant2 = um expdiff Bits nach rechts geschobene und gerundete Mantisse + // von x2. + if (!(sign1==sign2)) + // verschiedene Vorzeichen -> Mantissen subtrahieren + { if (manthi1 > manthi2) + { manthi1 = manthi1 - manthi2; + if (mantlo1 < mantlo2) { manthi1 -= 1; } + mantlo1 = mantlo1 - mantlo2; + goto norm_2; + } + if (manthi1 == manthi2) + { if (mantlo1 > mantlo2) + { manthi1 = 0; mantlo1 = mantlo1 - mantlo2; goto norm_2; } + if (mantlo1 == mantlo2) // Ergebnis 0 ? + { return cl_DF_0; } + } + // Hier ((manthi1 < manthi2) || ((manthi1 == manthi2) && (mantlo1 < mantlo2))). + // negatives Subtraktionsergebnis + manthi1 = manthi2 - manthi1; + if (mantlo2 < mantlo1) { manthi1 -= 1; } + mantlo1 = mantlo2 - mantlo1; + sign1 = sign2; + goto norm_2; + } + else + // gleiche Vorzeichen -> Mantissen addieren + { manthi1 = manthi1 + manthi2; + if ((mantlo1 = mantlo1 + mantlo2) < mantlo2) { manthi1 += 1; } + } + // mant1 = Ergebnis-Mantisse >0, sign1 = Ergebnis-Vorzeichen, + // exp1 = Ergebnis-Exponent. + // Außerdem: Bei expdiff=0,1 sind die zwei letzten Bits von mant1 Null, + // bei expdiff>=2 ist mant1 >= 2^(DF_mant_len+2). + // Stets ist mant1 < 2^(DF_mant_len+5). (Daher werden die 2 Rundungsbits + // nachher um höchstens eine Position nach links geschoben werden.) + // [Knuth, S.201, leicht modifiziert: + // N1. m>=1 -> goto N4. + // N2. [Hier m<1] m>=1/2 -> goto N5. + // N3. m:=2*m, e:=e-1, goto N2. + // N4. [Hier 1<=m<2] m:=m/2, e:=e+1. + // N5. [Hier 1/2<=m<1] Runde m auf 53 Bits hinterm Komma. + // Falls hierdurch m=1 geworden, setze m:=m/2, e:=e+1. + // ] + // Bei uns ist m=mant1/2^(DF_mant_len+4), + // ab Schritt N5 ist m=mant1/2^(DF_mant_len+1). + norm_1: // [Knuth, S.201, Schritt N1] + if (manthi1 >= bit(DF_mant_len-32+4)) goto norm_4; + norm_2: // [Knuth, S.201, Schritt N2] + // Hier ist mant1 < 2^(DF_mant_len+4) + if (manthi1 >= bit(DF_mant_len-32+3)) goto norm_5; + // [Knuth, S.201, Schritt N3] + manthi1 = (manthi1 << 1) | (mantlo1 >> 31); // Mantisse links schieben + mantlo1 = mantlo1 << 1; + exp1 = exp1-1; + goto norm_2; + norm_4: // [Knuth, S.201, Schritt N4] + // Hier ist 2^(DF_mant_len+4) <= mant1 < 2^(DF_mant_len+5) + exp1 = exp1+1; + mantlo1 = (mantlo1 >> 1) | (manthi1 << 31) | (mantlo1 & bit(0)); // Mantisse rechts schieben + manthi1 = (manthi1 >> 1); + norm_5: // [Knuth, S.201, Schritt N5] + // Hier ist 2^(DF_mant_len+3) <= mant1 < 2^(DF_mant_len+4) + // Auf DF_mant_len echte Mantissenbits runden, d.h. rechte 3 Bits + // wegrunden, und dabei mant1 um 3 Bits nach rechts schieben: + {var uintL rounding_bits = mantlo1 & (bit(3)-1); + mantlo1 = (mantlo1 >> 3) | (manthi1 << (32-3)); manthi1 = manthi1 >> 3; + if ( (rounding_bits < bit(2)) // 000,001,010,011 werden abgerundet + || ( (rounding_bits == bit(2)) // 100 (genau halbzahlig) + && ((mantlo1 & bit(0)) ==0) // -> round-to-even + ) ) + // abrunden + {} + else + // aufrunden + { mantlo1 = mantlo1+1; + if (mantlo1==0) + { manthi1 = manthi1+1; + if (manthi1 >= bit(DF_mant_len-32+1)) + // Bei Überlauf während der Rundung nochmals rechts schieben + // (Runden ist hier überflüssig): + { manthi1 = manthi1>>1; exp1 = exp1+1; } // Mantisse rechts schieben + } } + }// Runden fertig + return encode_DF(sign1,exp1,manthi1,mantlo1); +#endif +#endif +} diff --git a/src/float/dfloat/elem/cl_DF_plusp.cc b/src/float/dfloat/elem/cl_DF_plusp.cc new file mode 100644 index 0000000..0de29f1 --- /dev/null +++ b/src/float/dfloat/elem/cl_DF_plusp.cc @@ -0,0 +1,28 @@ +// plusp(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#include "cl_DF.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_DF_minusp.cc" +#include "cl_DF_zerop.cc" + +MAYBE_INLINE2 +cl_boolean plusp (const cl_DF& x) +{ + if (minusp(x)) + return cl_false; // x<0 -> nein + elif (zerop(x)) + return cl_false; // x=0 -> nein + else + return cl_true; // sonst ist x>0. +} diff --git a/src/float/dfloat/elem/cl_DF_scale.cc b/src/float/dfloat/elem/cl_DF_scale.cc new file mode 100644 index 0000000..77c2ef6 --- /dev/null +++ b/src/float/dfloat/elem/cl_DF_scale.cc @@ -0,0 +1,63 @@ +// scale_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#include "cl_DF.h" +#include "cl_F.h" + +const cl_DF scale_float (const cl_DF& x, sintL delta) +{ + // Methode: + // x=0.0 -> x als Ergebnis + // delta muß betragsmäßig <= DF_exp_high-DF_exp_low sein. + // Neues DF mit um delta vergrößertem Exponenten bilden. + // x entpacken: + var cl_signean sign; + var sintL exp; +#if (cl_word_size==64) + var uint64 mant; + DF_decode(x, { return x; }, sign=,exp=,mant=); +#else + var uint32 manthi; + var uint32 mantlo; + DF_decode2(x, { return x; }, sign=,exp=,manthi=,mantlo=); +#endif + if (delta >= 0) + // delta>=0 + { var uintL udelta = delta; + if (udelta <= (uintL)(DF_exp_high-DF_exp_low)) + { exp = exp+udelta; +#if (cl_word_size==64) + return encode_DF(sign,exp,mant); +#else + return encode_DF(sign,exp,manthi,mantlo); +#endif + } + else + { cl_error_floating_point_overflow(); } + } + else + // delta<0 + { var uintL udelta = -delta; + if (udelta <= (uintL)(DF_exp_high-DF_exp_low)) + { exp = exp-udelta; +#if (cl_word_size==64) + return encode_DF(sign,exp,mant); +#else + return encode_DF(sign,exp,manthi,mantlo); +#endif + } + else + if (underflow_allowed()) + { cl_error_floating_point_underflow(); } + else + { return cl_DF_0; } + } +} diff --git a/src/float/dfloat/elem/cl_DF_scale_I.cc b/src/float/dfloat/elem/cl_DF_scale_I.cc new file mode 100644 index 0000000..2397882 --- /dev/null +++ b/src/float/dfloat/elem/cl_DF_scale_I.cc @@ -0,0 +1,69 @@ +// scale_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#include "cl_DF.h" +#include "cl_F.h" +#include "cl_I.h" + +const cl_DF scale_float (const cl_DF& x, const cl_I& delta) +{ + // Methode: + // x=0.0 -> x als Ergebnis + // delta muß ein Fixnum betragsmäßig <= DF_exp_high-DF_exp_low sein. + // Neues DF mit um delta vergrößertem Exponenten bilden. + // x entpacken: + var cl_signean sign; + var sintL exp; +#if (cl_word_size==64) + var uint64 mant; + DF_decode(x, { return x; }, sign=,exp=,mant=); +#else + var uint32 manthi; + var uint32 mantlo; + DF_decode2(x, { return x; }, sign=,exp=,manthi=,mantlo=); +#endif + if (!minusp(delta)) + // delta>=0 + { var uintL udelta; + if (fixnump(delta) + && ((udelta = FN_to_L(delta)) <= (uintL)(DF_exp_high-DF_exp_low)) + ) + { exp = exp+udelta; +#if (cl_word_size==64) + return encode_DF(sign,exp,mant); +#else + return encode_DF(sign,exp,manthi,mantlo); +#endif + } + else + { cl_error_floating_point_overflow(); } + } + else + // delta<0 + { var uintL udelta; + if (fixnump(delta) + && ((udelta = -FN_to_L(delta)) <= (uintL)(DF_exp_high-DF_exp_low)) + && ((cl_value_len+1dfloat_value; + if (DF_uexp(x_) == 0) + return x; + else + return allocate_dfloat( x_ ^ bit(63) ); +#else + var uint32 semhi = TheDfloat(x)->dfloat_value.semhi; + var uint32 mlo = TheDfloat(x)->dfloat_value.mlo; + if (DF_uexp(semhi) == 0) + return x; + else + return allocate_dfloat( semhi ^ bit(31), mlo ); +#endif +} diff --git a/src/float/dfloat/elem/cl_DF_zerop.cc b/src/float/dfloat/elem/cl_DF_zerop.cc new file mode 100644 index 0000000..3803b1e --- /dev/null +++ b/src/float/dfloat/elem/cl_DF_zerop.cc @@ -0,0 +1,22 @@ +// zerop(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#include "cl_DF.h" + +MAYBE_INLINE +cl_boolean zerop (const cl_DF& x) +{ +#if 0 + return (cl_boolean) (DF_uexp(TheDfloat(x)->dfloat_value_semhi) == 0); +#else // this is faster + return (cl_boolean) (TheDfloat(x)->dfloat_value_semhi == 0); +#endif +} diff --git a/src/float/dfloat/input/Makeflags b/src/float/dfloat/input/Makeflags new file mode 100644 index 0000000..2b0712c --- /dev/null +++ b/src/float/dfloat/input/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/dfloat/Makeflags +SUBDIR_INCLUDES += diff --git a/src/float/dfloat/input/cl_DF_from_string.cc b/src/float/dfloat/input/cl_DF_from_string.cc new file mode 100644 index 0000000..071a421 --- /dev/null +++ b/src/float/dfloat/input/cl_DF_from_string.cc @@ -0,0 +1,27 @@ +// cl_DF (const char *) constructor. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat_class.h" + + +// Implementation. + +#include "cl_dfloat.h" +#include "cl_input.h" +#include "cl_float_io.h" + +cl_read_flags cl_DF_read_flags = { + syntax_dfloat, + lsyntax_all, + 10, + { cl_float_format_dfloat, cl_float_format_lfloat_min, cl_false } +}; + +cl_DF::cl_DF (const char * string) +{ + pointer = as_cl_private_thing( + As(cl_DF)(read_float(cl_DF_read_flags,string,NULL,NULL))); +} diff --git a/src/float/dfloat/misc/Makeflags b/src/float/dfloat/misc/Makeflags new file mode 100644 index 0000000..f8842d2 --- /dev/null +++ b/src/float/dfloat/misc/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/dfloat/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/float/dfloat/elem -I$(srcdir)/integer -I$(srcdir)/base/digitseq -I$(srcdir)/base/digit -Ibase $(GMP_INCLUDES) diff --git a/src/float/dfloat/misc/cl_DF_abs.cc b/src/float/dfloat/misc/cl_DF_abs.cc new file mode 100644 index 0000000..ebadb9a --- /dev/null +++ b/src/float/dfloat/misc/cl_DF_abs.cc @@ -0,0 +1,20 @@ +// abs(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_DF_minusp.cc" + +const cl_DF abs (const cl_DF& x) +{ +// x<0 -> (- x), x>=0 -> x + if (minusp(x)) return -x; else return x; +} diff --git a/src/float/dfloat/misc/cl_DF_as.cc b/src/float/dfloat/misc/cl_DF_as.cc new file mode 100644 index 0000000..e60dc9f --- /dev/null +++ b/src/float/dfloat/misc/cl_DF_as.cc @@ -0,0 +1,29 @@ +// as_cl_DF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#include "cl_N.h" + +inline cl_boolean cl_DF_p (const cl_number& x) +{ + if (x.pointer_p()) + if (x.heappointer->type == &cl_class_dfloat) + return cl_true; + return cl_false; +} + +const cl_DF& as_cl_DF (const cl_number& x, const char * filename, int line) +{ + if (cl_DF_p(x)) { + DeclareType(cl_DF,x); + return x; + } else + cl_as_error(x,"a double-float number",filename,line); +} diff --git a/src/float/dfloat/misc/cl_DF_class.cc b/src/float/dfloat/misc/cl_DF_class.cc new file mode 100644 index 0000000..06fcfba --- /dev/null +++ b/src/float/dfloat/misc/cl_DF_class.cc @@ -0,0 +1,15 @@ +// cl_class_dfloat. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +cl_class cl_class_dfloat = { + NULL, // empty destructor + cl_class_flags_subclass_complex | cl_class_flags_subclass_real | cl_class_flags_subclass_float +}; diff --git a/src/float/dfloat/misc/cl_DF_debug.cc b/src/float/dfloat/misc/cl_DF_debug.cc new file mode 100644 index 0000000..6fa7d7c --- /dev/null +++ b/src/float/dfloat/misc/cl_DF_debug.cc @@ -0,0 +1,25 @@ +// cl_DF debugging support. + +// General includes. +#include "cl_sysdep.h" + +// Specification. + + +// Implementation. + +#include "cl_dfloat.h" +#include "cl_io.h" +#include "cl_float_io.h" + +static void dprint (cl_heap* pointer) +{ + var const cl_DF& obj = *(const cl_DF*)&pointer; + fprint(cl_debugout, "(cl_DF) "); + fprint(cl_debugout, obj); +} +AT_INITIALIZATION(dprint_DF) +{ cl_register_type_printer(cl_class_dfloat,dprint); } + +// This dummy links in this module when requires it. +int cl_DF_debug_module; diff --git a/src/float/dfloat/misc/cl_DF_decode.cc b/src/float/dfloat/misc/cl_DF_decode.cc new file mode 100644 index 0000000..641104b --- /dev/null +++ b/src/float/dfloat/misc/cl_DF_decode.cc @@ -0,0 +1,42 @@ +// decode_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#include "cl_DF.h" +#include "cl_I.h" + +const cl_decoded_dfloat decode_float (const cl_DF& x) +{ + // x entpacken: + var cl_signean sign; + var sintL exp; +#if (cl_word_size==64) + var uint64 mant; + DF_decode(x, { return cl_decoded_dfloat(cl_DF_0, 0, cl_DF_1); }, + sign=,exp=,mant= + ); + return cl_decoded_dfloat( + encode_DF(0,0,mant), // (-1)^0 * 2^0 * m erzeugen + L_to_FN(exp), // e als Fixnum + encode_DF(sign,1,bit(DF_mant_len)) // (-1)^s erzeugen + ); +#else + var uint32 manthi; + var uint32 mantlo; + DF_decode2(x, { return cl_decoded_dfloat(cl_DF_0, 0, cl_DF_1); }, + sign=,exp=,manthi=,mantlo= + ); + return cl_decoded_dfloat( + encode_DF(0,0,manthi,mantlo), // (-1)^0 * 2^0 * m erzeugen + L_to_FN(exp), // e als Fixnum + encode_DF(sign,1,bit(DF_mant_len-32),0) // (-1)^s erzeugen + ); +#endif +} diff --git a/src/float/dfloat/misc/cl_DF_digits.cc b/src/float/dfloat/misc/cl_DF_digits.cc new file mode 100644 index 0000000..5ea00a6 --- /dev/null +++ b/src/float/dfloat/misc/cl_DF_digits.cc @@ -0,0 +1,19 @@ +// float_digits(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#include "cl_DF.h" + +MAYBE_INLINE +uintL float_digits (const cl_DF& x) +{ + unused x; + return DF_mant_len+1; // 53 +} diff --git a/src/float/dfloat/misc/cl_DF_eqhashcode.cc b/src/float/dfloat/misc/cl_DF_eqhashcode.cc new file mode 100644 index 0000000..269fecc --- /dev/null +++ b/src/float/dfloat/misc/cl_DF_eqhashcode.cc @@ -0,0 +1,32 @@ +// cl_DF equal_hashcode(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#include "cl_N.h" +#include "cl_DF.h" + +MAYBE_INLINE +uint32 cl_equal_hashcode (const cl_DF& x) +{ + var cl_signean sign; + var sintL exp; +#if (cl_word_size==64) + var uint64 mant; + DF_decode(x, { return 0; }, sign=,exp=,mant=); + var uint32 msd = mant >> ((DF_mant_len+1)-32); +#else + var uint32 manthi; + var uint32 mantlo; + DF_decode2(x, { return 0; }, sign=,exp=,manthi=,mantlo=); + var uint32 msd = (manthi << (64-(DF_mant_len+1))) + | (mantlo >> ((DF_mant_len+1)-32)); +#endif + return equal_hashcode_low(msd,exp,sign); +} diff --git a/src/float/dfloat/misc/cl_DF_exponent.cc b/src/float/dfloat/misc/cl_DF_exponent.cc new file mode 100644 index 0000000..3bb84c3 --- /dev/null +++ b/src/float/dfloat/misc/cl_DF_exponent.cc @@ -0,0 +1,20 @@ +// float_exponent(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#include "cl_DF.h" + +MAYBE_INLINE +sintL float_exponent (const cl_DF& x) +{ + var uintL uexp = DF_uexp(TheDfloat(x)->dfloat_value_semhi); + if (uexp==0) { return 0; } + return (sintL)(uexp - DF_exp_mid); +} diff --git a/src/float/dfloat/misc/cl_DF_idecode.cc b/src/float/dfloat/misc/cl_DF_idecode.cc new file mode 100644 index 0000000..6140afd --- /dev/null +++ b/src/float/dfloat/misc/cl_DF_idecode.cc @@ -0,0 +1,43 @@ +// integer_decode_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#include "cl_DF.h" +#include "cl_I.h" + +MAYBE_INLINE +const cl_idecoded_float integer_decode_float (const cl_DF& x) +{ + // x entpacken: + var cl_signean sign; + var sintL exp; +#if (cl_word_size==64) + var uint64 mant; + DF_decode(x, { return cl_idecoded_float(0, 0, 1); }, + sign=,exp=,mant= + ); + return cl_idecoded_float( + Q_to_I(mant), // Mantisse (>0, <2^53) als Bignum + L_to_FN(exp-(DF_mant_len+1)), // e-53 als Fixnum + (sign>=0 ? cl_I(1) : cl_I(-1)) // (-1)^s erzeugen + ); +#else + var uint32 manthi; + var uint32 mantlo; + DF_decode2(x, { return cl_idecoded_float(0, 0, 1); }, + sign=,exp=,manthi=,mantlo= + ); + return cl_idecoded_float( + L2_to_I(manthi,mantlo), // Mantisse (>0, <2^53) als Bignum + L_to_FN(exp-(DF_mant_len+1)), // e als Fixnum + (sign>=0 ? cl_I(1) : cl_I(-1)) // (-1)^s erzeugen + ); +#endif +} diff --git a/src/float/dfloat/misc/cl_DF_max.cc b/src/float/dfloat/misc/cl_DF_max.cc new file mode 100644 index 0000000..7dfe3ca --- /dev/null +++ b/src/float/dfloat/misc/cl_DF_max.cc @@ -0,0 +1,15 @@ +// max(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +const cl_DF max (const cl_DF& x, const cl_DF& y) +{ + return (x >= y ? x : y); +} diff --git a/src/float/dfloat/misc/cl_DF_min.cc b/src/float/dfloat/misc/cl_DF_min.cc new file mode 100644 index 0000000..7768cf8 --- /dev/null +++ b/src/float/dfloat/misc/cl_DF_min.cc @@ -0,0 +1,15 @@ +// min(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +const cl_DF min (const cl_DF& x, const cl_DF& y) +{ + return (x <= y ? x : y); +} diff --git a/src/float/dfloat/misc/cl_DF_precision.cc b/src/float/dfloat/misc/cl_DF_precision.cc new file mode 100644 index 0000000..3092f94 --- /dev/null +++ b/src/float/dfloat/misc/cl_DF_precision.cc @@ -0,0 +1,23 @@ +// float_precision(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#include "cl_DF.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_DF_zerop.cc" + +MAYBE_INLINE2 +uintL float_precision (const cl_DF& x) +{ + if (zerop(x)) return 0; + return DF_mant_len+1; // 53 +} diff --git a/src/float/dfloat/misc/cl_DF_sign.cc b/src/float/dfloat/misc/cl_DF_sign.cc new file mode 100644 index 0000000..643100b --- /dev/null +++ b/src/float/dfloat/misc/cl_DF_sign.cc @@ -0,0 +1,23 @@ +// float_sign(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#include "cl_DF.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_DF_minusp.cc" + +MAYBE_INLINE2 +const cl_DF float_sign (const cl_DF& x) +{ +// Methode: x>=0 -> Ergebnis 1.0; x<0 -> Ergebnis -1.0 + return (!minusp(x) ? cl_DF_1 : cl_DF_minus1); +} diff --git a/src/float/dfloat/misc/cl_DF_signum.cc b/src/float/dfloat/misc/cl_DF_signum.cc new file mode 100644 index 0000000..5ab1b8a --- /dev/null +++ b/src/float/dfloat/misc/cl_DF_signum.cc @@ -0,0 +1,25 @@ +// signum(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_dfloat.h" + + +// Implementation. + +#include "cl_DF.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_DF_minusp.cc" +#include "cl_DF_zerop.cc" + +MAYBE_INLINE2 +const cl_DF signum (const cl_DF& x) +{ + if (minusp(x)) { return cl_DF_minus1; } // x<0 -> -1.0 + elif (zerop(x)) { return cl_DF_0; } // x=0 -> 0.0 + else { return cl_DF_1; } // x>0 -> +1.0 +} diff --git a/src/float/division/Makeflags b/src/float/division/Makeflags new file mode 100644 index 0000000..546ddeb --- /dev/null +++ b/src/float/division/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/Makeflags +SUBDIR_INCLUDES += diff --git a/src/float/division/cl_F_ceil1.cc b/src/float/division/cl_F_ceil1.cc new file mode 100644 index 0000000..55d98ab --- /dev/null +++ b/src/float/division/cl_F_ceil1.cc @@ -0,0 +1,19 @@ +// ceiling1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" + +const cl_I ceiling1 (const cl_F& x) +GEN_F_OP1(x, ceiling1, return) diff --git a/src/float/division/cl_F_ceil2.cc b/src/float/division/cl_F_ceil2.cc new file mode 100644 index 0000000..638b04d --- /dev/null +++ b/src/float/division/cl_F_ceil2.cc @@ -0,0 +1,30 @@ +// ceiling2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" +#include "cl_SF.h" +#include "cl_FF.h" +#include "cl_DF.h" +#include "cl_LF.h" + +const cl_F_div_t ceiling2 (const cl_F& x) +{ + floatcase(x + , var cl_SF q = fceiling(x); return cl_F_div_t(cl_SF_to_I(q),x-q); + , var cl_FF q = fceiling(x); return cl_F_div_t(cl_FF_to_I(q),x-q); + , var cl_DF q = fceiling(x); return cl_F_div_t(cl_DF_to_I(q),x-q); + , var cl_LF q = fceiling(x); return cl_F_div_t(cl_LF_to_I(q),LF_LF_minus_LF(x,q)); + ); +} diff --git a/src/float/division/cl_F_ceil22.cc b/src/float/division/cl_F_ceil22.cc new file mode 100644 index 0000000..abbb324 --- /dev/null +++ b/src/float/division/cl_F_ceil22.cc @@ -0,0 +1,22 @@ +// ceiling2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" + +const cl_F_div_t ceiling2 (const cl_F& x, const cl_F& y) +{ +// Methode: +// (q,r) := ceiling(x/y). Liefere q und x-y*q = y*r. + var cl_F_div_t q_r = ceiling2(x/y); + var cl_I& q = q_r.quotient; + var cl_F& r = q_r.remainder; + return cl_F_div_t(q,y*r); +} diff --git a/src/float/division/cl_F_fceil1.cc b/src/float/division/cl_F_fceil1.cc new file mode 100644 index 0000000..0fa9fb1 --- /dev/null +++ b/src/float/division/cl_F_fceil1.cc @@ -0,0 +1,19 @@ +// fceiling(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" + +const cl_F fceiling (const cl_F& x) +GEN_F_OP1(x, fceiling, return) diff --git a/src/float/division/cl_F_fceil2.cc b/src/float/division/cl_F_fceil2.cc new file mode 100644 index 0000000..00c0eeb --- /dev/null +++ b/src/float/division/cl_F_fceil2.cc @@ -0,0 +1,32 @@ +// fceiling2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" +#include "cl_LF.h" + +const cl_F_fdiv_t fceiling2 (const cl_F& x) +{ +#if 0 // 3 type dispatches + var cl_F q = fceiling(x); + return cl_F_fdiv_t(q,x-q); +#else // 1 type dispatch + floatcase(x + , var cl_SF q = fceiling(x); return cl_F_fdiv_t(q,x-q); + , var cl_FF q = fceiling(x); return cl_F_fdiv_t(q,x-q); + , var cl_DF q = fceiling(x); return cl_F_fdiv_t(q,x-q); + , var cl_LF q = fceiling(x); return cl_F_fdiv_t(q,LF_LF_minus_LF(x,q)); + ); +#endif +} diff --git a/src/float/division/cl_F_ffloor1.cc b/src/float/division/cl_F_ffloor1.cc new file mode 100644 index 0000000..6a3ab4e --- /dev/null +++ b/src/float/division/cl_F_ffloor1.cc @@ -0,0 +1,19 @@ +// ffloor(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" + +const cl_F ffloor (const cl_F& x) +GEN_F_OP1(x, ffloor, return) diff --git a/src/float/division/cl_F_ffloor2.cc b/src/float/division/cl_F_ffloor2.cc new file mode 100644 index 0000000..84b9b5f --- /dev/null +++ b/src/float/division/cl_F_ffloor2.cc @@ -0,0 +1,32 @@ +// ffloor2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" +#include "cl_LF.h" + +const cl_F_fdiv_t ffloor2 (const cl_F& x) +{ +#if 0 // 3 type dispatches + var cl_F q = ffloor(x); + return cl_F_fdiv_t(q,x-q); +#else // 1 type dispatch + floatcase(x + , var cl_SF q = ffloor(x); return cl_F_fdiv_t(q,x-q); + , var cl_FF q = ffloor(x); return cl_F_fdiv_t(q,x-q); + , var cl_DF q = ffloor(x); return cl_F_fdiv_t(q,x-q); + , var cl_LF q = ffloor(x); return cl_F_fdiv_t(q,LF_LF_minus_LF(x,q)); + ); +#endif +} diff --git a/src/float/division/cl_F_floor1.cc b/src/float/division/cl_F_floor1.cc new file mode 100644 index 0000000..1d86918 --- /dev/null +++ b/src/float/division/cl_F_floor1.cc @@ -0,0 +1,19 @@ +// floor1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" + +const cl_I floor1 (const cl_F& x) +GEN_F_OP1(x, floor1, return) diff --git a/src/float/division/cl_F_floor2.cc b/src/float/division/cl_F_floor2.cc new file mode 100644 index 0000000..6b96906 --- /dev/null +++ b/src/float/division/cl_F_floor2.cc @@ -0,0 +1,30 @@ +// floor2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" +#include "cl_SF.h" +#include "cl_FF.h" +#include "cl_DF.h" +#include "cl_LF.h" + +const cl_F_div_t floor2 (const cl_F& x) +{ + floatcase(x + , var cl_SF q = ffloor(x); return cl_F_div_t(cl_SF_to_I(q),x-q); + , var cl_FF q = ffloor(x); return cl_F_div_t(cl_FF_to_I(q),x-q); + , var cl_DF q = ffloor(x); return cl_F_div_t(cl_DF_to_I(q),x-q); + , var cl_LF q = ffloor(x); return cl_F_div_t(cl_LF_to_I(q),LF_LF_minus_LF(x,q)); + ); +} diff --git a/src/float/division/cl_F_floor22.cc b/src/float/division/cl_F_floor22.cc new file mode 100644 index 0000000..c19980e --- /dev/null +++ b/src/float/division/cl_F_floor22.cc @@ -0,0 +1,22 @@ +// floor2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" + +const cl_F_div_t floor2 (const cl_F& x, const cl_F& y) +{ +// Methode: +// (q,r) := floor(x/y). Liefere q und x-y*q = y*r. + var cl_F_div_t q_r = floor2(x/y); + var cl_I& q = q_r.quotient; + var cl_F& r = q_r.remainder; + return cl_F_div_t(q,y*r); +} diff --git a/src/float/division/cl_F_fround1.cc b/src/float/division/cl_F_fround1.cc new file mode 100644 index 0000000..83542a2 --- /dev/null +++ b/src/float/division/cl_F_fround1.cc @@ -0,0 +1,19 @@ +// fround(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" + +const cl_F fround (const cl_F& x) +GEN_F_OP1(x, fround, return) diff --git a/src/float/division/cl_F_fround2.cc b/src/float/division/cl_F_fround2.cc new file mode 100644 index 0000000..520f50a --- /dev/null +++ b/src/float/division/cl_F_fround2.cc @@ -0,0 +1,32 @@ +// fround2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" +#include "cl_LF.h" + +const cl_F_fdiv_t fround2 (const cl_F& x) +{ +#if 0 // 3 type dispatches + var cl_F q = fround(x); + return cl_F_fdiv_t(q,x-q); +#else // 1 type dispatch + floatcase(x + , var cl_SF q = fround(x); return cl_F_fdiv_t(q,x-q); + , var cl_FF q = fround(x); return cl_F_fdiv_t(q,x-q); + , var cl_DF q = fround(x); return cl_F_fdiv_t(q,x-q); + , var cl_LF q = fround(x); return cl_F_fdiv_t(q,LF_LF_minus_LF(x,q)); + ); +#endif +} diff --git a/src/float/division/cl_F_ftrunc1.cc b/src/float/division/cl_F_ftrunc1.cc new file mode 100644 index 0000000..ceb6666 --- /dev/null +++ b/src/float/division/cl_F_ftrunc1.cc @@ -0,0 +1,19 @@ +// ftruncate(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" + +const cl_F ftruncate (const cl_F& x) +GEN_F_OP1(x, ftruncate, return) diff --git a/src/float/division/cl_F_ftrunc2.cc b/src/float/division/cl_F_ftrunc2.cc new file mode 100644 index 0000000..7b3a1eb --- /dev/null +++ b/src/float/division/cl_F_ftrunc2.cc @@ -0,0 +1,32 @@ +// ftruncate2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" +#include "cl_LF.h" + +const cl_F_fdiv_t ftruncate2 (const cl_F& x) +{ +#if 0 // 3 type dispatches + var cl_F q = ftruncate(x); + return cl_F_fdiv_t(q,x-q); +#else // 1 type dispatch + floatcase(x + , var cl_SF q = ftruncate(x); return cl_F_fdiv_t(q,x-q); + , var cl_FF q = ftruncate(x); return cl_F_fdiv_t(q,x-q); + , var cl_DF q = ftruncate(x); return cl_F_fdiv_t(q,x-q); + , var cl_LF q = ftruncate(x); return cl_F_fdiv_t(q,LF_LF_minus_LF(x,q)); + ); +#endif +} diff --git a/src/float/division/cl_F_round1.cc b/src/float/division/cl_F_round1.cc new file mode 100644 index 0000000..c32dba1 --- /dev/null +++ b/src/float/division/cl_F_round1.cc @@ -0,0 +1,19 @@ +// round1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" + +const cl_I round1 (const cl_F& x) +GEN_F_OP1(x, round1, return) diff --git a/src/float/division/cl_F_round2.cc b/src/float/division/cl_F_round2.cc new file mode 100644 index 0000000..3a52851 --- /dev/null +++ b/src/float/division/cl_F_round2.cc @@ -0,0 +1,30 @@ +// round2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" +#include "cl_SF.h" +#include "cl_FF.h" +#include "cl_DF.h" +#include "cl_LF.h" + +const cl_F_div_t round2 (const cl_F& x) +{ + floatcase(x + , var cl_SF q = fround(x); return cl_F_div_t(cl_SF_to_I(q),x-q); + , var cl_FF q = fround(x); return cl_F_div_t(cl_FF_to_I(q),x-q); + , var cl_DF q = fround(x); return cl_F_div_t(cl_DF_to_I(q),x-q); + , var cl_LF q = fround(x); return cl_F_div_t(cl_LF_to_I(q),LF_LF_minus_LF(x,q)); + ); +} diff --git a/src/float/division/cl_F_round22.cc b/src/float/division/cl_F_round22.cc new file mode 100644 index 0000000..5ed1887 --- /dev/null +++ b/src/float/division/cl_F_round22.cc @@ -0,0 +1,22 @@ +// round2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" + +const cl_F_div_t round2 (const cl_F& x, const cl_F& y) +{ +// Methode: +// (q,r) := round(x/y). Liefere q und x-y*q = y*r. + var cl_F_div_t q_r = round2(x/y); + var cl_I& q = q_r.quotient; + var cl_F& r = q_r.remainder; + return cl_F_div_t(q,y*r); +} diff --git a/src/float/division/cl_F_trunc1.cc b/src/float/division/cl_F_trunc1.cc new file mode 100644 index 0000000..a23bcab --- /dev/null +++ b/src/float/division/cl_F_trunc1.cc @@ -0,0 +1,19 @@ +// truncate1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" + +const cl_I truncate1 (const cl_F& x) +GEN_F_OP1(x, truncate1, return) diff --git a/src/float/division/cl_F_trunc2.cc b/src/float/division/cl_F_trunc2.cc new file mode 100644 index 0000000..e1dd711 --- /dev/null +++ b/src/float/division/cl_F_trunc2.cc @@ -0,0 +1,30 @@ +// truncate2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" +#include "cl_SF.h" +#include "cl_FF.h" +#include "cl_DF.h" +#include "cl_LF.h" + +const cl_F_div_t truncate2 (const cl_F& x) +{ + floatcase(x + , var cl_SF q = ftruncate(x); return cl_F_div_t(cl_SF_to_I(q),x-q); + , var cl_FF q = ftruncate(x); return cl_F_div_t(cl_FF_to_I(q),x-q); + , var cl_DF q = ftruncate(x); return cl_F_div_t(cl_DF_to_I(q),x-q); + , var cl_LF q = ftruncate(x); return cl_F_div_t(cl_LF_to_I(q),LF_LF_minus_LF(x,q)); + ); +} diff --git a/src/float/division/cl_F_trunc22.cc b/src/float/division/cl_F_trunc22.cc new file mode 100644 index 0000000..b5faa9f --- /dev/null +++ b/src/float/division/cl_F_trunc22.cc @@ -0,0 +1,22 @@ +// truncate2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" + +const cl_F_div_t truncate2 (const cl_F& x, const cl_F& y) +{ +// Methode: +// (q,r) := truncate(x/y). Liefere q und x-y*q = y*r. + var cl_F_div_t q_r = truncate2(x/y); + var cl_I& q = q_r.quotient; + var cl_F& r = q_r.remainder; + return cl_F_div_t(q,y*r); +} diff --git a/src/float/elem/Makeflags b/src/float/elem/Makeflags new file mode 100644 index 0000000..704ccdc --- /dev/null +++ b/src/float/elem/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/float/sfloat/elem -I$(srcdir)/float/ffloat/elem -I$(srcdir)/float/dfloat/elem -I$(srcdir)/float/lfloat/elem -I$(srcdir)/rational -I$(srcdir)/integer diff --git a/src/float/elem/cl_F_I_div.cc b/src/float/elem/cl_F_I_div.cc new file mode 100644 index 0000000..30dfb90 --- /dev/null +++ b/src/float/elem/cl_F_I_div.cc @@ -0,0 +1,31 @@ +// binary operator / + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" +#include "cl_F.h" +#include "cl_SF.h" +#include "cl_FF.h" +#include "cl_DF.h" +#include "cl_LF.h" + +const cl_F operator/ (const cl_F& x, const cl_I& y) +{ + floatcase(x + , /* SF */ return x / cl_I_to_SF(y); + , /* FF */ return x / cl_I_to_FF(y); + , /* DF */ return x / cl_I_to_DF(y); + , /* LF */ return cl_LF_I_div(x,y); + ); +} diff --git a/src/float/elem/cl_F_I_mul.cc b/src/float/elem/cl_F_I_mul.cc new file mode 100644 index 0000000..92f8e48 --- /dev/null +++ b/src/float/elem/cl_F_I_mul.cc @@ -0,0 +1,32 @@ +// binary operator * + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" +#include "cl_F.h" +#include "cl_SF.h" +#include "cl_FF.h" +#include "cl_DF.h" +#include "cl_LF.h" + +const cl_R cl_F_I_mul (const cl_F& x, const cl_I& y) +{ + if (eq(y,0)) { return 0; } // x * 0 = exakte 0 + floatcase(x + , /* SF */ return x * cl_I_to_SF(y); + , /* FF */ return x * cl_I_to_FF(y); + , /* DF */ return x * cl_I_to_DF(y); + , /* LF */ return cl_LF_I_mul(x,y); + ); +} diff --git a/src/float/elem/cl_F_RA_div.cc b/src/float/elem/cl_F_RA_div.cc new file mode 100644 index 0000000..8ffa4e9 --- /dev/null +++ b/src/float/elem/cl_F_RA_div.cc @@ -0,0 +1,47 @@ +// binary operator / + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" +#include "cl_F.h" +#include "cl_SF.h" +#include "cl_FF.h" +#include "cl_DF.h" +#include "cl_LF.h" + +const cl_F operator/ (const cl_F& x, const cl_RA& y) +{ + floatcase(x + , /* SF */ if (integerp(y)) { + DeclareType(cl_I,y); + return x / cl_I_to_SF(y); + } else + return x / cl_RA_to_SF(y); + , /* FF */ if (integerp(y)) { + DeclareType(cl_I,y); + return x / cl_I_to_FF(y); + } else + return x / cl_RA_to_FF(y); + , /* DF */ if (integerp(y)) { + DeclareType(cl_I,y); + return x / cl_I_to_DF(y); + } else + return x / cl_RA_to_DF(y); + , /* LF */ if (integerp(y)) { + DeclareType(cl_I,y); + return cl_LF_I_div(x,y); + } else + return cl_LF_RA_div(x,y); + ); +} diff --git a/src/float/elem/cl_F_RA_mul.cc b/src/float/elem/cl_F_RA_mul.cc new file mode 100644 index 0000000..5f2905d --- /dev/null +++ b/src/float/elem/cl_F_RA_mul.cc @@ -0,0 +1,32 @@ +// binary operator * + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" +#include "cl_F.h" +#include "cl_SF.h" +#include "cl_FF.h" +#include "cl_DF.h" +#include "cl_LF.h" + +const cl_R cl_F_RA_mul (const cl_F& x, const cl_RA& y) +{ + if (eq(y,0)) { return 0; } // x * 0 = exakte 0 + floatcase(x + , /* SF */ return x * cl_RA_to_SF(y); + , /* FF */ return x * cl_RA_to_FF(y); + , /* DF */ return x * cl_RA_to_DF(y); + , /* LF */ return cl_LF_RA_mul(x,y); + ); +} diff --git a/src/float/elem/cl_F_compare.cc b/src/float/elem/cl_F_compare.cc new file mode 100644 index 0000000..9304856 --- /dev/null +++ b/src/float/elem/cl_F_compare.cc @@ -0,0 +1,20 @@ +// cl_compare(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" +#include "cl_LF.h" + +cl_signean cl_compare (const cl_F& x, const cl_F& y) +GEN_F_OP2(x,y, cl_compare, 0, 1, return) diff --git a/src/float/elem/cl_F_div.cc b/src/float/elem/cl_F_div.cc new file mode 100644 index 0000000..74d0313 --- /dev/null +++ b/src/float/elem/cl_F_div.cc @@ -0,0 +1,23 @@ +// binary operator / + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" +#include "cl_LF.h" + +ALL_cl_LF_OPERATIONS_SAME_PRECISION() + +const cl_F operator/ (const cl_F& x, const cl_F& y) +#define div(a,b) a/b +GEN_F_OP2(x,y, div, 1, 1, return) diff --git a/src/float/elem/cl_F_minus.cc b/src/float/elem/cl_F_minus.cc new file mode 100644 index 0000000..f149806 --- /dev/null +++ b/src/float/elem/cl_F_minus.cc @@ -0,0 +1,23 @@ +// binary operator - + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" +#include "cl_LF.h" + +ALL_cl_LF_OPERATIONS_SAME_PRECISION() + +const cl_F operator- (const cl_F& x, const cl_F& y) +#define minus(a,b) a-b +GEN_F_OP2(x,y, minus, 1, 0, return) diff --git a/src/float/elem/cl_F_minusp.cc b/src/float/elem/cl_F_minusp.cc new file mode 100644 index 0000000..fd429f3 --- /dev/null +++ b/src/float/elem/cl_F_minusp.cc @@ -0,0 +1,29 @@ +// minusp(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_SF_minusp.cc" +#include "cl_FF_minusp.cc" +#include "cl_DF_minusp.cc" +#include "cl_LF_minusp.cc" + +cl_boolean minusp (const cl_F& x) +{ + floatcase(x + , return minusp(x); + , return minusp(x); + , return minusp(x); + , return minusp(x); + ); +} diff --git a/src/float/elem/cl_F_mul.cc b/src/float/elem/cl_F_mul.cc new file mode 100644 index 0000000..c3bbfd7 --- /dev/null +++ b/src/float/elem/cl_F_mul.cc @@ -0,0 +1,23 @@ +// binary operator * + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" +#include "cl_LF.h" + +ALL_cl_LF_OPERATIONS_SAME_PRECISION() + +const cl_F operator* (const cl_F& x, const cl_F& y) +#define mul(a,b) a*b +GEN_F_OP2(x,y, mul, 1, 1, return) diff --git a/src/float/elem/cl_F_plus.cc b/src/float/elem/cl_F_plus.cc new file mode 100644 index 0000000..149b344 --- /dev/null +++ b/src/float/elem/cl_F_plus.cc @@ -0,0 +1,23 @@ +// binary operator + + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" +#include "cl_LF.h" + +ALL_cl_LF_OPERATIONS_SAME_PRECISION() + +const cl_F operator+ (const cl_F& x, const cl_F& y) +#define plus(a,b) a+b +GEN_F_OP2(x,y, plus, 1, 0, return) diff --git a/src/float/elem/cl_F_plusp.cc b/src/float/elem/cl_F_plusp.cc new file mode 100644 index 0000000..e091a0b --- /dev/null +++ b/src/float/elem/cl_F_plusp.cc @@ -0,0 +1,29 @@ +// plusp(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" + +#undef MAYBE_INLINE2 +#define MAYBE_INLINE2 inline +#include "cl_SF_plusp.cc" +#include "cl_FF_plusp.cc" +#include "cl_DF_plusp.cc" +#include "cl_LF_plusp.cc" + +cl_boolean plusp (const cl_F& x) +{ + floatcase(x + , return plusp(x); + , return plusp(x); + , return plusp(x); + , return plusp(x); + ); +} diff --git a/src/float/elem/cl_F_recip.cc b/src/float/elem/cl_F_recip.cc new file mode 100644 index 0000000..7469cbb --- /dev/null +++ b/src/float/elem/cl_F_recip.cc @@ -0,0 +1,19 @@ +// recip(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" + +const cl_F recip (const cl_F& x) +GEN_F_OP1(x, recip, return) diff --git a/src/float/elem/cl_F_scale.cc b/src/float/elem/cl_F_scale.cc new file mode 100644 index 0000000..f1d1126 --- /dev/null +++ b/src/float/elem/cl_F_scale.cc @@ -0,0 +1,26 @@ +// scale_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" +#include "cl_F.h" + +const cl_F scale_float (const cl_F& x, sintL delta) +{ + floatcase(x + , return scale_float(x,delta); + , return scale_float(x,delta); + , return scale_float(x,delta); + , return scale_float(x,delta); + ); +} diff --git a/src/float/elem/cl_F_scale_I.cc b/src/float/elem/cl_F_scale_I.cc new file mode 100644 index 0000000..4fac10c --- /dev/null +++ b/src/float/elem/cl_F_scale_I.cc @@ -0,0 +1,26 @@ +// scale_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" +#include "cl_F.h" + +const cl_F scale_float (const cl_F& x, const cl_I& delta) +{ + floatcase(x + , return scale_float(x,delta); + , return scale_float(x,delta); + , return scale_float(x,delta); + , return scale_float(x,delta); + ); +} diff --git a/src/float/elem/cl_F_square.cc b/src/float/elem/cl_F_square.cc new file mode 100644 index 0000000..cece02f --- /dev/null +++ b/src/float/elem/cl_F_square.cc @@ -0,0 +1,19 @@ +// square(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" + +const cl_F square (const cl_F& x) +GEN_F_OP1(x, square, return) diff --git a/src/float/elem/cl_F_uminus.cc b/src/float/elem/cl_F_uminus.cc new file mode 100644 index 0000000..60c2bc9 --- /dev/null +++ b/src/float/elem/cl_F_uminus.cc @@ -0,0 +1,20 @@ +// unary operator - + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" + +const cl_F operator- (const cl_F& x) +#define minus(a) -a +GEN_F_OP1(x, minus, return) diff --git a/src/float/elem/cl_F_zerop.cc b/src/float/elem/cl_F_zerop.cc new file mode 100644 index 0000000..6eba0b0 --- /dev/null +++ b/src/float/elem/cl_F_zerop.cc @@ -0,0 +1,29 @@ +// zerop(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_SF_zerop.cc" +#include "cl_FF_zerop.cc" +#include "cl_DF_zerop.cc" +#include "cl_LF_zerop.cc" + +cl_boolean zerop (const cl_F& x) +{ + floatcase(x + , return zerop(x); + , return zerop(x); + , return zerop(x); + , return zerop(x); + ); +} diff --git a/src/float/elem/cl_I_F_div.cc b/src/float/elem/cl_I_F_div.cc new file mode 100644 index 0000000..34a49c3 --- /dev/null +++ b/src/float/elem/cl_I_F_div.cc @@ -0,0 +1,32 @@ +// binary operator / + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" +#include "cl_F.h" +#include "cl_SF.h" +#include "cl_FF.h" +#include "cl_DF.h" +#include "cl_LF.h" + +const cl_R operator/ (const cl_I& x, const cl_F& y) +{ + if (eq(x,0)) { return 0; } + floatcase(y + , /* SF */ return cl_I_to_SF(x) / y; + , /* FF */ return cl_I_to_FF(x) / y; + , /* DF */ return cl_I_to_DF(x) / y; + , /* LF */ return cl_I_to_LF(x,LFlen0(y)) / y; // cf. cl_I_LF_div + ); +} diff --git a/src/float/elem/cl_RA_F_div.cc b/src/float/elem/cl_RA_F_div.cc new file mode 100644 index 0000000..e34d2cf --- /dev/null +++ b/src/float/elem/cl_RA_F_div.cc @@ -0,0 +1,48 @@ +// binary operator / + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" +#include "cl_F.h" +#include "cl_SF.h" +#include "cl_FF.h" +#include "cl_DF.h" +#include "cl_LF.h" + +const cl_R operator/ (const cl_RA& x, const cl_F& y) +{ + if (eq(x,0)) { return 0; } + floatcase(y + , /* SF */ if (integerp(x)) { + DeclareType(cl_I,x); + return cl_I_to_SF(x) / y; + } else + return cl_RA_to_SF(x) / y; + , /* FF */ if (integerp(x)) { + DeclareType(cl_I,x); + return cl_I_to_FF(x) / y; + } else + return cl_RA_to_FF(x) / y; + , /* DF */ if (integerp(x)) { + DeclareType(cl_I,x); + return cl_I_to_DF(x) / y; + } else + return cl_RA_to_DF(x) / y; + , /* LF */ if (integerp(x)) { + DeclareType(cl_I,x); + return cl_I_LF_div(x,y); + } else + return cl_RA_LF_div(x,y); + ); +} diff --git a/src/float/ffloat/Makeflags b/src/float/ffloat/Makeflags new file mode 100644 index 0000000..fd4b67f --- /dev/null +++ b/src/float/ffloat/Makeflags @@ -0,0 +1,3 @@ +# This file contains additional flags for the main Makefile. + +SUBDIR_INCLUDES = -I$(srcdir)/float/ffloat -I$(srcdir)/float -I$(srcdir)/base diff --git a/src/float/ffloat/algebraic/Makeflags b/src/float/ffloat/algebraic/Makeflags new file mode 100644 index 0000000..1916d46 --- /dev/null +++ b/src/float/ffloat/algebraic/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/ffloat/Makeflags +SUBDIR_INCLUDES += diff --git a/src/float/ffloat/algebraic/cl_FF_sqrt.cc b/src/float/ffloat/algebraic/cl_FF_sqrt.cc new file mode 100644 index 0000000..f6a9665 --- /dev/null +++ b/src/float/ffloat/algebraic/cl_FF_sqrt.cc @@ -0,0 +1,65 @@ +// sqrt(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_FF.h" +#include "cl_F.h" +#include "cl_low.h" + +const cl_FF sqrt (const cl_FF& x) +{ +// Methode: +// x = 0.0 -> Ergebnis 0.0 +// Ergebnis-Vorzeichen := positiv, +// Ergebnis-Exponent := ceiling(e/2), +// Ergebnis-Mantisse: +// Bilde aus [1,m22,...,m0,(26 Nullbits)] bei geradem e, +// aus [0,1,m22,...,m0,(25 Nullbits)] bei ungeradem e +// die Ganzzahl-Wurzel, eine 25-Bit-Zahl mit einer führenden 1. +// Runde das letzte Bit weg: +// Bit 0 = 0 -> abrunden, +// Bit 0 = 1 und Wurzel exakt -> round-to-even, +// Bit 0 = 1 und Rest >0 -> aufrunden. +// Dabei um ein Bit nach rechts schieben. +// Bei Aufrundung auf 2^24 (rounding overflow) Mantisse um 1 Bit nach rechts +// schieben und Exponent incrementieren. + // x entpacken: + var sintL exp; + var uint32 mant; + FF_decode(x, { return x; }, ,exp=,mant=); + // Um die 64-Bit-Ganzzahl-Wurzel ausnutzen zu können, fügen wir beim + // Radikanden 39 bzw. 40 statt 25 bzw. 26 Nullbits an. + if (exp & bit(0)) + // e ungerade + { mant = mant << (31-(FF_mant_len+1)); exp = exp+1; } + else + // e gerade + { mant = mant << (32-(FF_mant_len+1)); } + exp = exp >> 1; // exp := exp/2 + var bool exactp; + isqrt_64_32(mant,0, mant=,exactp=); // mant := isqrt(mant*2^32), eine 32-Bit-Zahl + // Die hinteren 31-FF_mant_len Bits wegrunden: + if ( ((mant & bit(30-FF_mant_len)) ==0) // Bit 7 =0 -> abrunden + || ( ((mant & (bit(30-FF_mant_len)-1)) ==0) // Bit 7 =1 und Bits 6..0 >0 -> aufrunden + && exactp // Bit 7 =1 und Bits 6..0 =0, aber Rest -> aufrunden + // round-to-even, je nach Bit 8 : + && ((mant & bit(31-FF_mant_len)) ==0) + ) ) + // abrunden + { mant = mant >> (31-FF_mant_len); } + else + // aufrunden + { mant = mant >> (31-FF_mant_len); + mant += 1; + if (mant >= bit(FF_mant_len+1)) // rounding overflow? + { mant = mant>>1; exp = exp+1; } + } + return encode_FF(0,exp,mant); +} diff --git a/src/float/ffloat/cl_FF.h b/src/float/ffloat/cl_FF.h new file mode 100644 index 0000000..50463c4 --- /dev/null +++ b/src/float/ffloat/cl_FF.h @@ -0,0 +1,244 @@ +// cl_FF internals + +#ifndef _CL_FF_H +#define _CL_FF_H + +#include "cl_number.h" +#include "cl_malloc.h" +#include "cl_low.h" +#include "cl_F.h" + +typedef uint32 ffloat; // 32-bit float in IEEE format + +union ffloatjanus { + ffloat eksplicit; // explicit value + #ifdef FAST_FLOAT + float machine_float; // value as a C `float' + #endif +}; + +#if defined(CL_WIDE_POINTERS) +#define FF_value_shift 32 +inline ffloat cl_ffloat_value (const cl_FF& x) +{ + return x.word >> FF_value_shift; +} +#else +struct cl_heap_ffloat : cl_heap { + ffloatjanus representation; +}; +inline cl_heap_ffloat* TheFfloat (const cl_number& obj) + { return (cl_heap_ffloat*)(obj.pointer); } +inline ffloat cl_ffloat_value (const cl_FF& x) +{ + return TheFfloat(x)->representation.eksplicit; +} +#endif + +// The word contains: +// |..|.......|..........................| +// sign exponent mantissa + + #define FF_exp_len 8 // number of bits in the exponent + #define FF_mant_len 23 // number of bits in the mantissa + // (excluding the hidden bit) + #define FF_exp_low 1 // minimum exponent + #define FF_exp_mid 126 // exponent bias + #define FF_exp_high 254 // maximum exponent, 255 is NaN/Inf + #define FF_exp_shift (FF_mant_len+FF_mant_shift) // lowest exponent bit + #define FF_mant_shift 0 // lowest mantissa bit + #define FF_sign_shift (32 - 1) // = (FF_exp_len+FF_mant_len) + +// Private constructor. +#if !defined(CL_WIDE_POINTERS) +inline cl_FF::cl_FF (cl_heap_ffloat* ptr) : cl_F ((cl_private_thing) ptr) {} +#endif + +extern cl_class cl_class_ffloat; + +// Builds a float from the explicit word. +#if defined(CL_WIDE_POINTERS) +inline cl_FF::cl_FF (struct cl_heap_ffloat * null, cl_uint w) + : cl_F ((cl_private_thing) w) { unused null; } +inline const cl_FF allocate_ffloat (ffloat eksplicit) +{ + return cl_FF((struct cl_heap_ffloat *) 0, ((cl_uint)eksplicit << FF_value_shift) | (cl_FF_tag << cl_tag_shift)); +} +#else +inline cl_heap_ffloat* allocate_ffloat (ffloat eksplicit) +{ + cl_heap_ffloat* p = (cl_heap_ffloat*) cl_malloc_hook(sizeof(cl_heap_ffloat)); + p->refcount = 1; + p->type = &cl_class_ffloat; + p->representation.eksplicit = eksplicit; + return p; +} +#endif + +// Builds a float word from sign (0 or -1), exponent and mantissa. +inline uint32 make_FF_word (cl_sint sign, unsigned int exp, cl_uint mant) +{ + return (sign << FF_sign_shift) + | (exp << FF_exp_shift) + | ((mant & (bit(FF_mant_len)-1)) << FF_mant_shift); +} + +// Builds a float from sign (0 or -1), exponent and mantissa. +inline const cl_FF make_FF (cl_sint sign, unsigned int exp, cl_uint mant) +{ + return allocate_ffloat(make_FF_word(sign,exp,mant)); +} + +#if defined(CL_WIDE_POINTERS) +// Single Float 0.0 + #define cl_FF_0 make_FF(0,0,0) +// Single Float 1.0 + #define cl_FF_1 make_FF(0,FF_exp_mid+1,bit(FF_mant_len)) +// Single Float -1.0 + #define cl_FF_minus1 make_FF(-1,FF_exp_mid+1,bit(FF_mant_len)) +#else +// Single Float 0.0 + extern const cl_FF cl_FF_0; +// Single Float 1.0 + extern const cl_FF cl_FF_1; +// Single Float -1.0 + extern const cl_FF cl_FF_minus1; +#endif + + +// Entpacken eines Single-Float: +// FF_decode(obj, zero_statement, sign=,exp=,mant=); +// zerlegt ein Single-Float obj. +// Ist obj=0.0, wird zero_statement ausgeführt. +// Sonst: cl_signean sign = Vorzeichen (0 = +, -1 = -), +// sintL exp = Exponent (vorzeichenbehaftet), +// uintL mant = Mantisse (>= 2^FF_mant_len, < 2^(FF_mant_len+1)) +#define FF_uexp(x) (((x) >> FF_mant_len) & (bit(FF_exp_len)-1)) +#define FF_decode(obj, zero_statement, sign_zuweisung,exp_zuweisung,mant_zuweisung) \ + { var ffloat _x = cl_ffloat_value(obj); \ + var uintL uexp = FF_uexp(_x); \ + if (uexp==0) \ + { zero_statement } /* e=0 -> Zahl 0.0 */ \ + else \ + { exp_zuweisung (sintL)(uexp - FF_exp_mid); /* Exponent */ \ + unused (sign_zuweisung sign_of((sint32)(_x))); /* Vorzeichen */\ + mant_zuweisung (bit(FF_mant_len) | (_x & (bit(FF_mant_len)-1))); \ + } } + +// Einpacken eines Single-Float: +// encode_FF(sign,exp,mant); +// liefert ein Single-Float. +// > cl_signean sign: Vorzeichen, 0 für +, -1 für negativ. +// > sintL exp: Exponent +// > uintL mant: Mantisse, sollte >= 2^FF_mant_len und < 2^(FF_mant_len+1) sein. +// < object ergebnis: ein Single-Float +// Der Exponent wird auf Überlauf/Unterlauf getestet. +inline const cl_FF encode_FF (cl_signean sign, sintL exp, uintL mant) +{ + if (exp < (sintL)(FF_exp_low-FF_exp_mid)) + { if (underflow_allowed()) + { cl_error_floating_point_underflow(); } + else + { return cl_FF_0; } + } + else + if (exp > (sintL)(FF_exp_high-FF_exp_mid)) + { cl_error_floating_point_overflow(); } + else + return make_FF(sign, exp+FF_exp_mid, mant & (bit(FF_mant_len)-1)); +} + +#ifdef FAST_FLOAT +// Auspacken eines Floats: +inline float FF_to_float (const cl_FF& obj) +{ + #if defined(CL_WIDE_POINTERS) // eines der beiden 32-Bit-Wörter + #if defined(__GNUC__) + return ((ffloatjanus) { eksplicit: cl_ffloat_value(obj) }).machine_float; + #else + return *(float*)(&((uint32*)&(obj))[BIG_ENDIAN_P+(1-2*BIG_ENDIAN_P)*(FF_value_shift/32)]); + #endif + #else + return TheFfloat(obj)->representation.machine_float; + #endif +} +// Überprüfen und Einpacken eines von den 'float'-Routinen gelieferten +// IEEE-Floats. +// Klassifikation: +// 1 <= e <= 254 : normalisierte Zahl +// e=0, m/=0: subnormale Zahl +// e=0, m=0: vorzeichenbehaftete 0.0 +// e=255, m=0: vorzeichenbehaftete Infinity +// e=255, m/=0: NaN +// Angabe der möglicherweise auftretenden Sonderfälle: +// maybe_overflow: Operation läuft über, liefert IEEE-Infinity +// maybe_subnormal: Ergebnis sehr klein, liefert IEEE-subnormale Zahl +// maybe_underflow: Ergebnis sehr klein und /=0, liefert IEEE-Null +// maybe_divide_0: Ergebnis unbestimmt, liefert IEEE-Infinity +// maybe_nan: Ergebnis unbestimmt, liefert IEEE-NaN + #include "cl_N.h" + #include "cl_F.h" + #define float_to_FF(expr,ergebnis_zuweisung,maybe_overflow,maybe_subnormal,maybe_underflow,maybe_divide_0,maybe_nan) \ + { var ffloatjanus _erg; _erg.machine_float = (expr); \ + if ((_erg.eksplicit & ((uint32)bit(FF_exp_len+FF_mant_len)-bit(FF_mant_len))) == 0) /* e=0 ? */\ + { if ((maybe_underflow \ + || (maybe_subnormal && !((_erg.eksplicit << 1) == 0)) \ + ) \ + && underflow_allowed() \ + ) \ + { cl_error_floating_point_underflow(); } /* subnormal oder noch kleiner -> Underflow */\ + else \ + { ergebnis_zuweisung cl_FF_0; } /* +/- 0.0 -> 0.0 */ \ + } \ + elif ((maybe_overflow || maybe_divide_0) \ + && (((~_erg.eksplicit) & ((uint32)bit(FF_exp_len+FF_mant_len)-bit(FF_mant_len))) == 0) /* e=255 ? */\ + ) \ + { if (maybe_nan && !((_erg.eksplicit << (32-FF_mant_len)) == 0)) \ + { cl_error_division_by_0(); } /* NaN, also Singularität -> "Division durch 0" */\ + else /* Infinity */ \ + if (!maybe_overflow || maybe_divide_0) \ + { cl_error_division_by_0(); } /* Infinity, Division durch 0 */\ + else \ + { cl_error_floating_point_overflow(); } /* Infinity, Overflow */\ + } \ + else \ + { ergebnis_zuweisung allocate_ffloat(_erg.eksplicit); } \ + } +#endif + +// Liefert zu einem Single-Float x : (futruncate x), ein FF. +// x wird von der 0 weg zur nächsten ganzen Zahl gerundet. +extern const cl_FF futruncate (const cl_FF& x); + +// FF_to_I(x) wandelt ein Single-Float x, das eine ganze Zahl darstellt, +// in ein Integer um. +extern const cl_I cl_FF_to_I (const cl_FF& x); + +// cl_I_to_FF(x) wandelt ein Integer x in ein Single-Float um und rundet dabei. +extern const cl_FF cl_I_to_FF (const cl_I& x); + +// cl_RA_to_FF(x) wandelt eine rationale Zahl x in ein Single-Float um +// und rundet dabei. +extern const cl_FF cl_RA_to_FF (const cl_RA& x); + + +// IEEE-Single-Float: +// Bit 31 = s, Bits 30..23 = e, Bits 22..0 = m. +// e=0, m=0: vorzeichenbehaftete 0.0 +// e=0, m/=0: subnormale Zahl, +// Wert = (-1)^s * 2^(1-126) * [ 0 . 0 m22 ... m0 ] +// 1 <= e <= 254 : normalisierte Zahl, +// Wert = (-1)^s * 2^(e-126) * [ 0 . 1 m22 ... m0 ] +// e=255, m=0: vorzeichenbehaftete Infinity +// e=255, m/=0: NaN + +// cl_float_to_FF(val) wandelt ein IEEE-Single-Float val in ein Single-Float um. +extern cl_private_thing cl_float_to_FF_pointer (const ffloatjanus& val); +inline const cl_FF cl_float_to_FF (const ffloatjanus& val) + { return cl_float_to_FF_pointer(val); } + +// cl_FF_to_float(obj,&val); +// wandelt ein Single-Float obj in ein IEEE-Single-Float val um. +extern void cl_FF_to_float (const cl_FF& obj, ffloatjanus* val_); + +#endif /* _CL_FF_H */ diff --git a/src/float/ffloat/conv/Makeflags b/src/float/ffloat/conv/Makeflags new file mode 100644 index 0000000..45ecb2f --- /dev/null +++ b/src/float/ffloat/conv/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/ffloat/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/rational -I$(srcdir)/integer -I$(srcdir)/base/digitseq -I$(srcdir)/base/digit -Ibase $(GMP_INCLUDES) diff --git a/src/float/ffloat/conv/cl_FF_from_float.cc b/src/float/ffloat/conv/cl_FF_from_float.cc new file mode 100644 index 0000000..54d7166 --- /dev/null +++ b/src/float/ffloat/conv/cl_FF_from_float.cc @@ -0,0 +1,40 @@ +// cl_float_to_FF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_FF.h" + + +// Implementation. + +cl_private_thing cl_float_to_FF_pointer (const ffloatjanus& val_) +{ + var ffloat val = val_.eksplicit; + var uintL exp = (val >> FF_mant_len) & (bit(FF_exp_len)-1); // e + if (exp == 0) // e=0 ? + // vorzeichenbehaftete 0.0 oder subnormale Zahl + { if (!((val << 1) == 0) && underflow_allowed()) + { cl_error_floating_point_underflow(); } + else + { return as_cl_private_thing(cl_FF_0); } // +/- 0.0 -> 0.0 + } + elif (exp == 255) // e=255 ? + { if (!((val << (32-FF_mant_len)) == 0)) + { cl_error_floating_point_nan(); } // NaN + else + { cl_error_floating_point_overflow(); } // Infinity, Overflow + } + else + { // Der Exponent muß um FF_exp_mid-126 erhöht werden. + if ((FF_exp_mid>126) && (exp > FF_exp_high-FF_exp_mid+126)) + { cl_error_floating_point_overflow(); } // Overflow + val += (FF_exp_mid - 126) << FF_mant_len; + #if defined(CL_WIDE_POINTERS) + return as_cl_private_thing(allocate_ffloat(val)); + #else + return (cl_private_thing)allocate_ffloat(val); + #endif + } +} diff --git a/src/float/ffloat/conv/cl_FF_to_floatj.cc b/src/float/ffloat/conv/cl_FF_to_floatj.cc new file mode 100644 index 0000000..52caf0b --- /dev/null +++ b/src/float/ffloat/conv/cl_FF_to_floatj.cc @@ -0,0 +1,30 @@ +// cl_FF_to_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_FF.h" + + +// Implementation. + +void cl_FF_to_float (const cl_FF& obj, ffloatjanus* val_) +{ + var ffloat val = cl_ffloat_value(obj); + // Der Exponent muß um FF_exp_mid-126 erniedrigt werden. + if (FF_exp_mid>126) + { var uintL exp = (val >> FF_mant_len) & (bit(FF_exp_len)-1); // e + if (exp < FF_exp_mid-126+1) + { // produziere denormalisiertes Float + val = (val & minus_bit(FF_exp_len+FF_mant_len)) // selbes Vorzeichen + | (0 << FF_mant_len) // Exponent 0 + | (((val & (bit(FF_mant_len)-1)) | bit(FF_mant_len)) // Mantisse shiften + >> (FF_exp_mid-126+1 - exp) // shiften + ); + } + else + { val -= (FF_exp_mid - 126) << FF_mant_len; } + } + val_->eksplicit = val; +} diff --git a/src/float/ffloat/conv/cl_I_to_float.cc b/src/float/ffloat/conv/cl_I_to_float.cc new file mode 100644 index 0000000..bfe8bb0 --- /dev/null +++ b/src/float/ffloat/conv/cl_I_to_float.cc @@ -0,0 +1,108 @@ +// cl_float_approx(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_FF.h" +#include "cl_I.h" +#include "cl_DS.h" +#include "cl_F.h" + +float cl_float_approx (const cl_I& x) +{ +// Method: same as cl_I_to_FF(). + if (eq(x,0)) { return 0.0; } + var cl_signean sign = -(cl_signean)minusp(x); // Vorzeichen + var cl_I abs_x = (sign==0 ? x : -x); + var uintL exp = integer_length(abs_x); // (integer-length x) + // NDS zu |x|>0 bilden: + var const uintD* MSDptr; + var uintC len; + I_to_NDS_nocopy(abs_x, MSDptr=,len=,,cl_false,); + // MSDptr/len/LSDptr ist die NDS zu x, len>0. + // Führende Digits holen: Brauche FF_mant_len+1 Bits, dazu intDsize + // Bits (die NDS kann mit bis zu intDsize Nullbits anfangen). + // Dann werden diese Bits um (exp mod intDsize) nach rechts geschoben. + var uintD msd = msprefnext(MSDptr); // erstes Digit + #if (intDsize==64) + var uintD msdd = 0; // weiteres Digit + if (--len == 0) goto ok; + msdd = msprefnext(MSDptr); + #else // (intDsize<=32) + var uint32 msdd = 0; // weitere min(len-1,32/intDsize) Digits + #define NEXT_DIGIT(i) \ + { if (--len == 0) goto ok; \ + msdd |= (uint32)msprefnext(MSDptr) << (32-(i+1)*intDsize); \ + } + DOCONSTTIMES(32/intDsize,NEXT_DIGIT); + #undef NEXT_DIGIT + #endif + --len; ok: + #if (intDsize==64) + // Die NDS besteht aus msd, msdd, und len weiteren Digits. + // Das höchste in 2^intDsize*msd+msdd gesetzte Bit ist Bit Nummer + // intDsize-1 + (exp mod intDsize). + var uintL shiftcount = exp % intDsize; + var uint64 mant = // führende 64 Bits + (shiftcount==0 + ? msdd + : ((msd << (64-shiftcount)) | (msdd >> shiftcount)) + ); + // Das höchste in mant gesetzte Bit ist Bit Nummer 63. + if ( ((mant & bit(62-FF_mant_len)) ==0) // Bit 39 =0 -> abrunden + || ( ((mant & (bit(62-FF_mant_len)-1)) ==0) // Bit 39 =1 und Bits 38..0 =0 + && ((msdd & (bit(shiftcount)-1)) ==0) // und weitere Bits aus msdd =0 + && (!test_loop_msp(MSDptr,len)) // und alle weiteren Digits =0 + // round-to-even, je nach Bit 40 : + && ((mant & bit(63-FF_mant_len)) ==0) + ) ) + // abrunden + { mant = mant >> (63-FF_mant_len); } + else + // aufrunden + { mant = mant >> (63-FF_mant_len); + mant += 1; + if (mant >= bit(FF_mant_len+1)) // rounding overflow? + { mant = mant>>1; exp = exp+1; } + } + #else + // Die NDS besteht aus msd, msdd, und len weiteren Digits. + // Das höchste in 2^32*msd+msdd gesetzte Bit ist Bit Nummer + // 31 + (exp mod intDsize). + var uintL shiftcount = exp % intDsize; + var uint32 mant = // führende 32 Bits + (shiftcount==0 + ? msdd + : (((uint32)msd << (32-shiftcount)) | (msdd >> shiftcount)) + ); + // Das höchste in mant gesetzte Bit ist Bit Nummer 31. + if ( ((mant & bit(30-FF_mant_len)) ==0) // Bit 7 =0 -> abrunden + || ( ((mant & (bit(30-FF_mant_len)-1)) ==0) // Bit 7 =1 und Bits 6..0 =0 + && ((msdd & (bit(shiftcount)-1)) ==0) // und weitere Bits aus msdd =0 + && (!test_loop_msp(MSDptr,len)) // und alle weiteren Digits =0 + // round-to-even, je nach Bit 8 : + && ((mant & bit(31-FF_mant_len)) ==0) + ) ) + // abrunden + { mant = mant >> (31-FF_mant_len); } + else + // aufrunden + { mant = mant >> (31-FF_mant_len); + mant += 1; + if (mant >= bit(FF_mant_len+1)) // rounding overflow? + { mant = mant>>1; exp = exp+1; } + } + #endif + union { ffloat eksplicit; float machine_float; } u; + if ((sintL)exp > (sintL)(FF_exp_high-FF_exp_mid)) + { u.eksplicit = make_FF_word(sign,bit(FF_exp_len)-1,0); } // Infinity + else + { u.eksplicit = make_FF_word(sign,(sintL)exp+FF_exp_mid,mant); } + return u.machine_float; +} diff --git a/src/float/ffloat/conv/cl_RA_to_float.cc b/src/float/ffloat/conv/cl_RA_to_float.cc new file mode 100644 index 0000000..877f824 --- /dev/null +++ b/src/float/ffloat/conv/cl_RA_to_float.cc @@ -0,0 +1,104 @@ +// cl_float_approx(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_FF.h" +#include "cl_RA.h" +#include "cl_integer.h" +#include "cl_I.h" +#include "cl_F.h" + +float cl_float_approx (const cl_RA& x) +{ +// Method: same as cl_RA_to_FF(). + if (integerp(x)) { + DeclareType(cl_I,x); + return cl_float_approx(x); + } + { // x Ratio + DeclareType(cl_RT,x); + union { ffloat eksplicit; float machine_float; } u; + var cl_I a = numerator(x); // +/- a + var const cl_I& b = denominator(x); // b + var cl_signean sign = -(cl_signean)minusp(a); // Vorzeichen + if (!(sign==0)) { a = -a; } // Betrag nehmen, liefert a + var sintL lendiff = (sintL)integer_length(a) // (integer-length a) + - (sintL)integer_length(b); // (integer-length b) + if (lendiff > FF_exp_high-FF_exp_mid) // Exponent >= n-m > Obergrenze ? + { u.eksplicit = make_FF_word(sign,bit(FF_exp_len)-1,0); // Infinity + return u.machine_float; + } + if (lendiff < FF_exp_low-FF_exp_mid-2) // Exponent <= n-m+2 < Untergrenze ? + { u.eksplicit = make_FF_word(sign,0,0); // 0.0 + return u.machine_float; + } + var cl_I zaehler; + var cl_I nenner; + if (lendiff >= FF_mant_len+2) + // n-m-25>=0 + { nenner = ash(b,lendiff - (FF_mant_len+2)); // (ash b n-m-25) + zaehler = a; // a + } + else + { zaehler = ash(a,(FF_mant_len+2) - lendiff); // (ash a -n+m+25) + nenner = b; // b + } + // Division zaehler/nenner durchführen: + var cl_I_div_t q_r = cl_divide(zaehler,nenner); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + // 2^24 <= q < 2^26, also ist q Fixnum oder Bignum mit bn_minlength Digits. + var uint32 mant = ((FF_mant_len+3 < cl_value_len) + ? FN_to_UL(q) + : cl_I_to_UL(q) + ); + if (mant >= bit(FF_mant_len+2)) + // 2^25 <= q < 2^26, schiebe um 2 Bits nach rechts + { var uintL rounding_bits = mant & (bit(2)-1); + lendiff = lendiff+1; // Exponent := n-m+1 + mant = mant >> 2; + if ( (rounding_bits < bit(1)) // 00,01 werden abgerundet + || ( (rounding_bits == bit(1)) // 10 + && (eq(r,0)) // und genau halbzahlig (r=0) + && ((mant & bit(0)) ==0) // -> round-to-even + ) ) + // abrunden + goto ab; + else + // aufrunden + goto auf; + } + else + { var uintL rounding_bit = mant & bit(0); + mant = mant >> 1; + if ( (rounding_bit == 0) // 0 wird abgerundet + || ( (eq(r,0)) // genau halbzahlig (r=0) + && ((mant & bit(0)) ==0) // -> round-to-even + ) ) + // abrunden + goto ab; + else + // aufrunden + goto auf; + } + auf: + mant += 1; + if (mant >= bit(FF_mant_len+1)) // rounding overflow? + { mant = mant>>1; lendiff = lendiff+1; } + ab: + // Fertig. + if (lendiff < (sintL)(FF_exp_low-FF_exp_mid)) + { u.eksplicit = make_FF_word(sign,0,0); } + else if (lendiff > (sintL)(FF_exp_high-FF_exp_mid)) + { u.eksplicit = make_FF_word(sign,bit(FF_exp_len)-1,0); } // Infinity + else + { u.eksplicit = make_FF_word(sign,lendiff+FF_exp_mid,mant); } + return u.machine_float; +}} diff --git a/src/float/ffloat/division/Makeflags b/src/float/ffloat/division/Makeflags new file mode 100644 index 0000000..ce55997 --- /dev/null +++ b/src/float/ffloat/division/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/ffloat/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/float/ffloat/elem diff --git a/src/float/ffloat/division/cl_FF_ceil22.cc b/src/float/ffloat/division/cl_FF_ceil22.cc new file mode 100644 index 0000000..90d7b06 --- /dev/null +++ b/src/float/ffloat/division/cl_FF_ceil22.cc @@ -0,0 +1,22 @@ +// ceiling2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_FF.h" + +const cl_FF_div_t ceiling2 (const cl_FF& x, const cl_FF& y) +{ +// Methode: +// (q,r) := ceiling(x/y). Liefere q und x-y*q = y*r. + var cl_FF_div_t q_r = ceiling2(x/y); + var cl_I& q = q_r.quotient; + var cl_FF& r = q_r.remainder; + return cl_FF_div_t(q,y*r); +} diff --git a/src/float/ffloat/division/cl_FF_fceil.cc b/src/float/ffloat/division/cl_FF_fceil.cc new file mode 100644 index 0000000..423dc21 --- /dev/null +++ b/src/float/ffloat/division/cl_FF_fceil.cc @@ -0,0 +1,24 @@ +// fceiling(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_FF.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_FF_minusp.cc" + +const cl_FF fceiling (const cl_FF& x) +{ + if (minusp(x)) + return ftruncate(x); + else + return futruncate(x); +} diff --git a/src/float/ffloat/division/cl_FF_floor22.cc b/src/float/ffloat/division/cl_FF_floor22.cc new file mode 100644 index 0000000..8a37040 --- /dev/null +++ b/src/float/ffloat/division/cl_FF_floor22.cc @@ -0,0 +1,22 @@ +// floor2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_FF.h" + +const cl_FF_div_t floor2 (const cl_FF& x, const cl_FF& y) +{ +// Methode: +// (q,r) := floor(x/y). Liefere q und x-y*q = y*r. + var cl_FF_div_t q_r = floor2(x/y); + var cl_I& q = q_r.quotient; + var cl_FF& r = q_r.remainder; + return cl_FF_div_t(q,y*r); +} diff --git a/src/float/ffloat/division/cl_FF_recip.cc b/src/float/ffloat/division/cl_FF_recip.cc new file mode 100644 index 0000000..d94aceb --- /dev/null +++ b/src/float/ffloat/division/cl_FF_recip.cc @@ -0,0 +1,17 @@ +// recip(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_FF.h" + +const cl_FF recip (const cl_FF& x) +{ + return cl_FF_1 / x; +} diff --git a/src/float/ffloat/division/cl_FF_round22.cc b/src/float/ffloat/division/cl_FF_round22.cc new file mode 100644 index 0000000..9973910 --- /dev/null +++ b/src/float/ffloat/division/cl_FF_round22.cc @@ -0,0 +1,22 @@ +// round2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_FF.h" + +const cl_FF_div_t round2 (const cl_FF& x, const cl_FF& y) +{ +// Methode: +// (q,r) := round(x/y). Liefere q und x-y*q = y*r. + var cl_FF_div_t q_r = round2(x/y); + var cl_I& q = q_r.quotient; + var cl_FF& r = q_r.remainder; + return cl_FF_div_t(q,y*r); +} diff --git a/src/float/ffloat/division/cl_FF_trunc22.cc b/src/float/ffloat/division/cl_FF_trunc22.cc new file mode 100644 index 0000000..7f05de9 --- /dev/null +++ b/src/float/ffloat/division/cl_FF_trunc22.cc @@ -0,0 +1,22 @@ +// truncate2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_FF.h" + +const cl_FF_div_t truncate2 (const cl_FF& x, const cl_FF& y) +{ +// Methode: +// (q,r) := truncate(x/y). Liefere q und x-y*q = y*r. + var cl_FF_div_t q_r = truncate2(x/y); + var cl_I& q = q_r.quotient; + var cl_FF& r = q_r.remainder; + return cl_FF_div_t(q,y*r); +} diff --git a/src/float/ffloat/elem/Makeflags b/src/float/ffloat/elem/Makeflags new file mode 100644 index 0000000..e499941 --- /dev/null +++ b/src/float/ffloat/elem/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/ffloat/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/float/base -I$(srcdir)/rational -I$(srcdir)/integer -I$(srcdir)/base/digitseq -I$(srcdir)/base/digit -Ibase $(GMP_INCLUDES) diff --git a/src/float/ffloat/elem/cl_FF_compare.cc b/src/float/ffloat/elem/cl_FF_compare.cc new file mode 100644 index 0000000..0e6fce8 --- /dev/null +++ b/src/float/ffloat/elem/cl_FF_compare.cc @@ -0,0 +1,48 @@ +// cl_compare(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_FF.h" + +cl_signean cl_compare (const cl_FF& x, const cl_FF& y) +{ +// Methode: +// x und y haben verschiedenes Vorzeichen -> +// x < 0 -> x < y +// x >= 0 -> x > y +// x und y haben gleiches Vorzeichen -> +// x >=0 -> vergleiche x und y (die rechten 24 Bits) +// x <0 -> vergleiche y und x (die rechten 24 Bits) + var uint32 x_ = cl_ffloat_value(x); + var uint32 y_ = cl_ffloat_value(y); + if ((sint32)y_ >= 0) + // y>=0 + { if ((sint32)x_ >= 0) + // y>=0, x>=0 + { if (x_ < y_) return signean_minus; // x y_) return signean_plus; // x>y + return signean_null; + } + else + // y>=0, x<0 + { return signean_minus; } // x= 0) + // y<0, x>=0 + { return signean_plus; } // x>y + else + // y<0, x<0 + { if (x_ > y_) return signean_minus; // |x|>|y| -> x x>y + return signean_null; + } + } +} diff --git a/src/float/ffloat/elem/cl_FF_div.cc b/src/float/ffloat/elem/cl_FF_div.cc new file mode 100644 index 0000000..89dc717 --- /dev/null +++ b/src/float/ffloat/elem/cl_FF_div.cc @@ -0,0 +1,103 @@ +// binary operator / + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_FF.h" +#include "cl_N.h" +#include "cl_F.h" +#include "cl_low.h" +#include "cl_ieee.h" +NEED_IEEE_FLOATS() + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_FF_zerop.cc" + +const cl_FF operator/ (const cl_FF& x1, const cl_FF& x2) +{ +// Methode: +// x2 = 0.0 -> Error +// x1 = 0.0 -> Ergebnis 0.0 +// Sonst: +// Ergebnis-Vorzeichen = xor der beiden Vorzeichen von x1 und x2 +// Ergebnis-Exponent = Differenz der beiden Exponenten von x1 und x2 +// Ergebnis-Mantisse = Mantisse mant1 / Mantisse mant2, gerundet. +// mant1/mant2 > 1/2, mant1/mant2 < 2; +// nach Rundung mant1/mant2 >=1/2, <=2*mant1<2. +// Bei mant1/mant2 >=1 brauche 23 Nachkommabits, +// bei mant1/mant2 <1 brauche 24 Nachkommabits. +// Fürs Runden: brauche ein Rundungsbit (Rest gibt an, ob exakt). +// Brauche daher insgesamt 25 Nachkommabits von mant1/mant2. +// Dividiere daher (als Unsigned Integers) 2^25*(2^24*mant1) durch (2^24*mant2). +// Falls der Quotient >=2^25 ist, runde die letzten zwei Bits weg und +// erhöhe den Exponenten um 1. +// Falls der Quotient <2^25 ist, runde das letzte Bit weg. Bei rounding +// overflow schiebe um ein weiteres Bit nach rechts, incr. Exponenten. + #if defined(FAST_FLOAT) && !defined(__i386__) + float_to_FF(FF_to_float(x1) / FF_to_float(x2), return , + TRUE, TRUE, // Overflow und subnormale Zahl abfangen + !zerop(x1), // ein Ergebnis +/- 0.0 + // ist genau dann in Wirklichkeit ein Underflow + zerop(x2), // Division durch Null abfangen + FALSE // kein NaN als Ergebnis möglich + ); + #else + // x1,x2 entpacken: + var cl_signean sign1; + var sintL exp1; + var uintL mant1; + var cl_signean sign2; + var sintL exp2; + var uintL mant2; + FF_decode(x2, { cl_error_division_by_0(); }, sign2=,exp2=,mant2=); + FF_decode(x1, { return x1; }, sign1=,exp1=,mant1=); + exp1 = exp1 - exp2; // Differenz der Exponenten + sign1 = sign1 ^ sign2; // Ergebnis-Vorzeichen + // Dividiere 2^25*mant1 durch mant2 oder (äquivalent) + // 2^i*2^25*mant1 durch 2^i*mant2 für irgendein i mit 0 <= i <= 32-24 : + var uintL mant; + var uintL rest; + // wähle i = 32-(FF_mant_len+1), also i+(FF_mant_len+2) = 33. + divu_6432_3232(mant1<<1,0, mant2<<(32-(FF_mant_len+1)), mant=,rest=); + if (mant >= bit(FF_mant_len+2)) + // Quotient >=2^25 -> 2 Bits wegrunden + { var uintL rounding_bits = mant & (bit(2)-1); + exp1 += 1; // Exponenten incrementieren + mant = mant >> 2; + if ( (rounding_bits < bit(1)) // 00,01 werden abgerundet + || ( (rounding_bits == bit(1)) // 10 + && (rest == 0) // und genau halbzahlig + && ((mant & bit(0)) ==0) // -> round-to-even + ) ) + // abrunden + {} + else + // aufrunden + { mant += 1; } + } + else + // Quotient <2^25 -> 1 Bit wegrunden + { var uintL rounding_bit = mant & bit(0); + mant = mant >> 1; + if ( (rounding_bit == 0) // 0 wird abgerundet + || ( (rest == 0) // genau halbzahlig + && ((mant & bit(0)) ==0) // -> round-to-even + ) ) + // abrunden + {} + else + // aufrunden + { mant += 1; + if (mant >= bit(FF_mant_len+1)) // rounding overflow? + { mant = mant>>1; exp1 = exp1+1; } + } } + return encode_FF(sign1,exp1,mant); + #endif +} diff --git a/src/float/ffloat/elem/cl_FF_ffloor.cc b/src/float/ffloat/elem/cl_FF_ffloor.cc new file mode 100644 index 0000000..7f9bbd7 --- /dev/null +++ b/src/float/ffloat/elem/cl_FF_ffloor.cc @@ -0,0 +1,24 @@ +// ffloor(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_FF.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_FF_minusp.cc" + +const cl_FF ffloor (const cl_FF& x) +{ + if (minusp(x)) + return futruncate(x); + else + return ftruncate(x); +} diff --git a/src/float/ffloat/elem/cl_FF_from_I.cc b/src/float/ffloat/elem/cl_FF_from_I.cc new file mode 100644 index 0000000..913cdd6 --- /dev/null +++ b/src/float/ffloat/elem/cl_FF_from_I.cc @@ -0,0 +1,115 @@ +// cl_I_to_FF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_FF.h" + + +// Implementation. + +#include "cl_integer.h" +#include "cl_I.h" +#include "cl_DS.h" +#include "cl_F.h" + +const cl_FF cl_I_to_FF (const cl_I& x) +{ +// Methode: +// x=0 -> Ergebnis 0.0 +// Merke Vorzeichen von x. +// x:=(abs x) +// Exponent:=(integer-length x) +// Greife die 25 höchstwertigen Bits heraus (angeführt von einer 1). +// Runde das letzte Bit weg: +// Bit 0 = 0 -> abrunden, +// Bit 0 = 1 und Rest =0 -> round-to-even, +// Bit 0 = 1 und Rest >0 -> aufrunden. +// Dabei um ein Bit nach rechts schieben. +// Bei Aufrundung auf 2^24 (rounding overflow) Mantisse um 1 Bit nach rechts +// schieben und Exponent incrementieren. + if (eq(x,0)) { return cl_FF_0; } + var cl_signean sign = -(cl_signean)minusp(x); // Vorzeichen + var cl_I abs_x = (sign==0 ? x : -x); + var uintL exp = integer_length(abs_x); // (integer-length x) + // NDS zu |x|>0 bilden: + var const uintD* MSDptr; + var uintC len; + I_to_NDS_nocopy(abs_x, MSDptr=,len=,,cl_false,); + // MSDptr/len/LSDptr ist die NDS zu x, len>0. + // Führende Digits holen: Brauche FF_mant_len+1 Bits, dazu intDsize + // Bits (die NDS kann mit bis zu intDsize Nullbits anfangen). + // Dann werden diese Bits um (exp mod intDsize) nach rechts geschoben. + var uintD msd = msprefnext(MSDptr); // erstes Digit + #if (intDsize==64) + var uintD msdd = 0; // weiteres Digit + if (--len == 0) goto ok; + msdd = msprefnext(MSDptr); + #else // (intDsize<=32) + var uint32 msdd = 0; // weitere min(len-1,32/intDsize) Digits + #define NEXT_DIGIT(i) \ + { if (--len == 0) goto ok; \ + msdd |= (uint32)msprefnext(MSDptr) << (32-(i+1)*intDsize); \ + } + DOCONSTTIMES(32/intDsize,NEXT_DIGIT); + #undef NEXT_DIGIT + #endif + --len; ok: + #if (intDsize==64) + // Die NDS besteht aus msd, msdd, und len weiteren Digits. + // Das höchste in 2^intDsize*msd+msdd gesetzte Bit ist Bit Nummer + // intDsize-1 + (exp mod intDsize). + var uintL shiftcount = exp % intDsize; + var uint64 mant = // führende 64 Bits + (shiftcount==0 + ? msdd + : ((msd << (64-shiftcount)) | (msdd >> shiftcount)) + ); + // Das höchste in mant gesetzte Bit ist Bit Nummer 63. + if ( ((mant & bit(62-FF_mant_len)) ==0) // Bit 39 =0 -> abrunden + || ( ((mant & (bit(62-FF_mant_len)-1)) ==0) // Bit 39 =1 und Bits 38..0 =0 + && ((msdd & (bit(shiftcount)-1)) ==0) // und weitere Bits aus msdd =0 + && (!test_loop_msp(MSDptr,len)) // und alle weiteren Digits =0 + // round-to-even, je nach Bit 40 : + && ((mant & bit(63-FF_mant_len)) ==0) + ) ) + // abrunden + { mant = mant >> (63-FF_mant_len); } + else + // aufrunden + { mant = mant >> (63-FF_mant_len); + mant += 1; + if (mant >= bit(FF_mant_len+1)) // rounding overflow? + { mant = mant>>1; exp = exp+1; } + } + #else + // Die NDS besteht aus msd, msdd, und len weiteren Digits. + // Das höchste in 2^32*msd+msdd gesetzte Bit ist Bit Nummer + // 31 + (exp mod intDsize). + var uintL shiftcount = exp % intDsize; + var uint32 mant = // führende 32 Bits + (shiftcount==0 + ? msdd + : (((uint32)msd << (32-shiftcount)) | (msdd >> shiftcount)) + ); + // Das höchste in mant gesetzte Bit ist Bit Nummer 31. + if ( ((mant & bit(30-FF_mant_len)) ==0) // Bit 7 =0 -> abrunden + || ( ((mant & (bit(30-FF_mant_len)-1)) ==0) // Bit 7 =1 und Bits 6..0 =0 + && ((msdd & (bit(shiftcount)-1)) ==0) // und weitere Bits aus msdd =0 + && (!test_loop_msp(MSDptr,len)) // und alle weiteren Digits =0 + // round-to-even, je nach Bit 8 : + && ((mant & bit(31-FF_mant_len)) ==0) + ) ) + // abrunden + { mant = mant >> (31-FF_mant_len); } + else + // aufrunden + { mant = mant >> (31-FF_mant_len); + mant += 1; + if (mant >= bit(FF_mant_len+1)) // rounding overflow? + { mant = mant>>1; exp = exp+1; } + } + #endif + return encode_FF(sign,(sintL)exp,mant); +} diff --git a/src/float/ffloat/elem/cl_FF_from_RA.cc b/src/float/ffloat/elem/cl_FF_from_RA.cc new file mode 100644 index 0000000..548d588 --- /dev/null +++ b/src/float/ffloat/elem/cl_FF_from_RA.cc @@ -0,0 +1,108 @@ +// cl_RA_to_FF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_FF.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" +#include "cl_I.h" +#include "cl_F.h" + +const cl_FF cl_RA_to_FF (const cl_RA& x) +{ +// Methode: +// x ganz -> klar. +// x = +/- a/b mit Integers a,b>0: +// Seien n,m so gewählt, daß +// 2^(n-1) <= a < 2^n, 2^(m-1) <= b < 2^m. +// Dann ist 2^(n-m-1) < a/b < 2^(n-m+1). +// Berechne n=(integer-length a) und m=(integer-length b) und +// floor(2^(-n+m+25)*a/b) : +// Bei n-m>=25 dividiere a durch (ash b (n-m-25)), +// bei n-m<25 dividiere (ash a (-n+m+25)) durch b. +// Der erste Wert ist >=2^24, <2^26. +// Falls er >=2^25 ist, runde 2 Bits weg, +// falls er <2^25 ist, runde 1 Bit weg. + if (integerp(x)) { + DeclareType(cl_I,x); + return cl_I_to_FF(x); + } + { // x Ratio + DeclareType(cl_RT,x); + var cl_I a = numerator(x); // +/- a + var const cl_I& b = denominator(x); // b + var cl_signean sign = -(cl_signean)minusp(a); // Vorzeichen + if (!(sign==0)) { a = -a; } // Betrag nehmen, liefert a + var sintL lendiff = (sintL)integer_length(a) // (integer-length a) + - (sintL)integer_length(b); // (integer-length b) + if (lendiff > FF_exp_high-FF_exp_mid) // Exponent >= n-m > Obergrenze ? + { cl_error_floating_point_overflow(); } // -> Overflow + if (lendiff < FF_exp_low-FF_exp_mid-2) // Exponent <= n-m+2 < Untergrenze ? + { if (underflow_allowed()) + { cl_error_floating_point_underflow(); } // -> Underflow + else + { return cl_FF_0; } + } + var cl_I zaehler; + var cl_I nenner; + if (lendiff >= FF_mant_len+2) + // n-m-25>=0 + { nenner = ash(b,lendiff - (FF_mant_len+2)); // (ash b n-m-25) + zaehler = a; // a + } + else + { zaehler = ash(a,(FF_mant_len+2) - lendiff); // (ash a -n+m+25) + nenner = b; // b + } + // Division zaehler/nenner durchführen: + var cl_I_div_t q_r = cl_divide(zaehler,nenner); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + // 2^24 <= q < 2^26, also ist q Fixnum oder Bignum mit bn_minlength Digits. + var uint32 mant = ((FF_mant_len+3 < cl_value_len) + ? FN_to_UL(q) + : cl_I_to_UL(q) + ); + if (mant >= bit(FF_mant_len+2)) + // 2^25 <= q < 2^26, schiebe um 2 Bits nach rechts + { var uintL rounding_bits = mant & (bit(2)-1); + lendiff = lendiff+1; // Exponent := n-m+1 + mant = mant >> 2; + if ( (rounding_bits < bit(1)) // 00,01 werden abgerundet + || ( (rounding_bits == bit(1)) // 10 + && (eq(r,0)) // und genau halbzahlig (r=0) + && ((mant & bit(0)) ==0) // -> round-to-even + ) ) + // abrunden + goto ab; + else + // aufrunden + goto auf; + } + else + { var uintL rounding_bit = mant & bit(0); + mant = mant >> 1; + if ( (rounding_bit == 0) // 0 wird abgerundet + || ( (eq(r,0)) // genau halbzahlig (r=0) + && ((mant & bit(0)) ==0) // -> round-to-even + ) ) + // abrunden + goto ab; + else + // aufrunden + goto auf; + } + auf: + mant += 1; + if (mant >= bit(FF_mant_len+1)) // rounding overflow? + { mant = mant>>1; lendiff = lendiff+1; } + ab: + // Fertig. + return encode_FF(sign,lendiff,mant); +}} diff --git a/src/float/ffloat/elem/cl_FF_fround.cc b/src/float/ffloat/elem/cl_FF_fround.cc new file mode 100644 index 0000000..3af0574 --- /dev/null +++ b/src/float/ffloat/elem/cl_FF_fround.cc @@ -0,0 +1,78 @@ +// fround(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_FF.h" + +const cl_FF fround (const cl_FF& x) +{ +// Methode: +// x = 0.0 oder e<0 -> Ergebnis 0.0 +// 0<=e<=23 -> letzte (24-e) Bits der Mantisse wegrunden, +// Exponent und Vorzeichen beibehalten. +// e>23 -> Ergebnis x + var ffloat x_ = cl_ffloat_value(x); + var uintL uexp = FF_uexp(x_); // e + FF_exp_mid + if (uexp < FF_exp_mid) // x = 0.0 oder e<0 ? + { return cl_FF_0; } + else + { if (uexp > FF_exp_mid+FF_mant_len) // e > 23 ? + { return x; } + else + if (uexp > FF_exp_mid+1) // e>1 ? + { var uint32 bitmask = // Bitmaske: Bit 23-e gesetzt, alle anderen gelöscht + bit(FF_mant_len+FF_exp_mid-uexp); + var uint32 mask = // Bitmaske: Bits 22-e..0 gesetzt, alle anderen gelöscht + bitmask-1; + if ( ((x_ & bitmask) ==0) // Bit 23-e =0 -> abrunden + || ( ((x_ & mask) ==0) // Bit 23-e =1 und Bits 22-e..0 >0 -> aufrunden + // round-to-even, je nach Bit 24-e : + && ((x_ & (bitmask<<1)) ==0) + ) ) + // abrunden + { mask |= bitmask; // Bitmaske: Bits 23-e..0 gesetzt, alle anderen gelöscht + return allocate_ffloat( x_ & ~mask ); + } + else + // aufrunden + { return allocate_ffloat + ((x_ | mask) // alle diese Bits 22-e..0 setzen (Bit 23-e schon gesetzt) + + 1 // letzte Stelle erhöhen, dabei evtl. Exponenten incrementieren + ); + } + } + elif (uexp == FF_exp_mid+1) // e=1 ? + // Wie bei 1 < e <= 23, nur daß Bit 24-e stets gesetzt ist. + { if ((x_ & bit(FF_mant_len-1)) ==0) // Bit 23-e =0 -> abrunden + // abrunden + { return allocate_ffloat( x_ & ~(bit(FF_mant_len)-1) ); } + else + // aufrunden + { return allocate_ffloat + ((x_ | (bit(FF_mant_len)-1)) // alle diese Bits 23-e..0 setzen + + 1 // letzte Stelle erhöhen, dabei evtl. Exponenten incrementieren + ); + } + } + else // e=0 ? + // Wie bei 1 < e <= 23, nur daß Bit 23-e stets gesetzt + // und Bit 24-e stets gelöscht ist. + { if ((x_ & (bit(FF_mant_len)-1)) ==0) + // abrunden von +-0.5 zu 0.0 + { return cl_FF_0; } + else + // aufrunden + { return allocate_ffloat + ((x_ | (bit(FF_mant_len)-1)) // alle Bits 22-e..0 setzen + + 1 // letzte Stelle erhöhen, dabei Exponenten incrementieren + ); + } } + } +} diff --git a/src/float/ffloat/elem/cl_FF_ftrunc.cc b/src/float/ffloat/elem/cl_FF_ftrunc.cc new file mode 100644 index 0000000..85056ac --- /dev/null +++ b/src/float/ffloat/elem/cl_FF_ftrunc.cc @@ -0,0 +1,34 @@ +// ftruncate(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_FF.h" + +const cl_FF ftruncate (const cl_FF& x) +{ +// Methode: +// x = 0.0 oder e<=0 -> Ergebnis 0.0 +// 1<=e<=23 -> letzte (24-e) Bits der Mantisse auf 0 setzen, +// Exponent und Vorzeichen beibehalten +// e>=24 -> Ergebnis x + var ffloat x_ = cl_ffloat_value(x); + var uintL uexp = FF_uexp(x_); // e + FF_exp_mid + if (uexp <= FF_exp_mid) // 0.0 oder e<=0 ? + { return cl_FF_0; } + else + { if (uexp > FF_exp_mid+FF_mant_len) // e > 23 ? + { return x; } + else + { return allocate_ffloat + ( x_ & // Bitmaske: Bits 23-e..0 gelöscht, alle anderen gesetzt + ~(bit(FF_mant_len+1+FF_exp_mid-uexp)-1) + ); + } } +} diff --git a/src/float/ffloat/elem/cl_FF_futrunc.cc b/src/float/ffloat/elem/cl_FF_futrunc.cc new file mode 100644 index 0000000..f14f09d --- /dev/null +++ b/src/float/ffloat/elem/cl_FF_futrunc.cc @@ -0,0 +1,45 @@ +// futruncate(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_FF.h" + + +// Implementation. + +const cl_FF futruncate (const cl_FF& x) +{ +// Methode: +// x = 0.0 -> Ergebnis 0.0 +// e<=0 -> Ergebnis 1.0 oder -1.0, je nach Vorzeichen von x. +// 1<=e<=23 -> Greife die letzten (24-e) Bits von x heraus. +// Sind sie alle =0 -> Ergebnis x. +// Sonst setze sie alle und erhöhe dann die letzte Stelle um 1. +// Kein Überlauf der 23 Bit -> fertig. +// Sonst (Ergebnis eine Zweierpotenz): Mantisse := .1000...000, +// e:=e+1. (Test auf Überlauf wegen e<=24 überflüssig) +// e>=24 -> Ergebnis x. + var ffloat x_ = cl_ffloat_value(x); + var uintL uexp = FF_uexp(x_); // e + FF_exp_mid + if (uexp==0) // 0.0 ? + { return x; } + if (uexp <= FF_exp_mid) // e<=0 ? + { // Exponent auf 1, Mantisse auf .1000...000 setzen. + return ((x_ & bit(31))==0 ? cl_FF_1 : cl_FF_minus1); + } + else + { if (uexp > FF_exp_mid+FF_mant_len) // e > 23 ? + { return x; } + else + { var uint32 mask = // Bitmaske: Bits 23-e..0 gesetzt, alle anderen gelöscht + bit(FF_mant_len+1+FF_exp_mid-uexp)-1; + if ((x_ & mask)==0) // alle diese Bits =0 ? + { return x; } + return allocate_ffloat + ((x_ | mask) // alle diese Bits setzen + + 1 // letzte Stelle erhöhen, dabei evtl. Exponenten incrementieren + ); + } } +} diff --git a/src/float/ffloat/elem/cl_FF_globals.cc b/src/float/ffloat/elem/cl_FF_globals.cc new file mode 100644 index 0000000..7fb6e2c --- /dev/null +++ b/src/float/ffloat/elem/cl_FF_globals.cc @@ -0,0 +1,24 @@ +// Global variables for cl_FF. + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_FF_globals) + +// Specification. +#include "cl_FF.h" + + +// Implementation. + +#if !defined(CL_WIDE_POINTERS) + +const cl_FF cl_FF_0 = allocate_ffloat(0); // 0.0f0 + +const cl_FF cl_FF_1 = encode_FF(0,1,bit(FF_mant_len)); // 1.0f0 + +const cl_FF cl_FF_minus1 = encode_FF(-1,1,bit(FF_mant_len)); // -1.0f0 + +#endif + +CL_PROVIDE_END(cl_FF_globals) diff --git a/src/float/ffloat/elem/cl_FF_minus.cc b/src/float/ffloat/elem/cl_FF_minus.cc new file mode 100644 index 0000000..f2a8996 --- /dev/null +++ b/src/float/ffloat/elem/cl_FF_minus.cc @@ -0,0 +1,32 @@ +// binary operator - + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_FF.h" +#include "cl_ieee.h" +NEED_IEEE_FLOATS() + +const cl_FF operator- (const cl_FF& x1, const cl_FF& x2) +{ + #ifdef FAST_FLOAT + float_to_FF(FF_to_float(x1) - FF_to_float(x2), return , + TRUE, TRUE, // Overflow und subnormale Zahl abfangen + FALSE, // kein Underflow mit Ergebnis +/- 0.0 möglich + // (nach Definition der subnormalen Zahlen) + FALSE, FALSE // keine Singularität, kein NaN als Ergebnis möglich + ); + #else + var ffloat x2_ = cl_ffloat_value(x2); + if (FF_uexp(x2_) == 0) + { return x1; } + else + { return x1 + allocate_ffloat(x2_ ^ bit(31)); } + #endif +} diff --git a/src/float/ffloat/elem/cl_FF_minusp.cc b/src/float/ffloat/elem/cl_FF_minusp.cc new file mode 100644 index 0000000..b979890 --- /dev/null +++ b/src/float/ffloat/elem/cl_FF_minusp.cc @@ -0,0 +1,18 @@ +// minusp(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_FF.h" + +MAYBE_INLINE +cl_boolean minusp (const cl_FF& x) +{ + return (cl_boolean) ((sint32)cl_ffloat_value(x) < 0); +} diff --git a/src/float/ffloat/elem/cl_FF_mul.cc b/src/float/ffloat/elem/cl_FF_mul.cc new file mode 100644 index 0000000..67fdf7d --- /dev/null +++ b/src/float/ffloat/elem/cl_FF_mul.cc @@ -0,0 +1,101 @@ +// binary operator * + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_FF.h" +#include "cl_F.h" +#include "cl_low.h" +#include "cl_ieee.h" +NEED_IEEE_FLOATS() + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_FF_zerop.cc" + +const cl_FF operator* (const cl_FF& x1, const cl_FF& x2) +{ +// Methode: +// Falls x1=0.0 oder x2=0.0 -> Ergebnis 0.0 +// Sonst: Ergebnis-Vorzeichen = VZ von x1 xor VZ von x2. +// Ergebnis-Exponent = Summe der Exponenten von x1 und x2. +// Ergebnis-Mantisse = Produkt der Mantissen von x1 und x2, gerundet: +// 2^-24 * mant1 * 2^-24 * mant2 = 2^-48 * (mant1*mant2), +// die Klammer ist >=2^46, <=(2^24-1)^2<2^48 . +// Falls die Klammer >=2^47 ist, um 24 Bit nach rechts schieben und +// runden: Falls Bit 23 Null, abrunden; falls Bit 23 Eins und +// Bits 22..0 alle Null, round-to-even; sonst aufrunden. +// Falls die Klammer <2^47 ist, um 23 Bit nach rechts schieben und +// runden: Falls Bit 22 Null, abrunden; falls Bit 22 Eins und +// Bits 21..0 alle Null, round-to-even; sonst aufrunden. Nach +// Aufrunden: Falls =2^24, um 1 Bit nach rechts schieben. Sonst +// Exponenten um 1 erniedrigen. + #ifdef FAST_FLOAT + float_to_FF(FF_to_float(x1) * FF_to_float(x2), return , + TRUE, TRUE, // Overflow und subnormale Zahl abfangen + !(zerop(x1) || zerop(x2)), // ein Ergebnis +/- 0.0 + // ist genau dann in Wirklichkeit ein Underflow + FALSE, FALSE // keine Singularität, kein NaN als Ergebnis möglich + ); + #else + // x1,x2 entpacken: + var cl_signean sign1; + var sintL exp1; + var uintL mant1; + var cl_signean sign2; + var sintL exp2; + var uintL mant2; + FF_decode(x1, { return x1; }, sign1=,exp1=,mant1=); + FF_decode(x2, { return x2; }, sign2=,exp2=,mant2=); + exp1 = exp1 + exp2; // Summe der Exponenten + sign1 = sign1 ^ sign2; // Ergebnis-Vorzeichen + var uintL manthi; + var uintL mantlo; + // Mantissen mant1 und mant2 multiplizieren: + mulu24(mant1,mant2, manthi=,mantlo=); + manthi = (manthi << (32-FF_mant_len)) | (mantlo >> FF_mant_len); + mantlo = mantlo & (bit(FF_mant_len)-1); + // Nun ist 2^FF_mant_len * manthi + mantlo = mant1 * mant2. + if (manthi >= bit(FF_mant_len+1)) + // mant1*mant2 >= 2^(2*FF_mant_len+1) + { if ( ((manthi & bit(0)) ==0) // Bit FF_mant_len =0 -> abrunden + || ( (mantlo ==0) // Bit FF_mant_len =1 und Bits FF_mant_len-1..0 >0 -> aufrunden + // round-to-even, je nach Bit FF_mant_len+1 : + && ((manthi & bit(1)) ==0) + ) ) + // abrunden + { manthi = manthi >> 1; goto ab; } + else + // aufrunden + { manthi = manthi >> 1; goto auf; } + } + else + // mant1*mant2 < 2^(2*FF_mant_len+1) + { exp1 = exp1-1; // Exponenten decrementieren + if ( ((mantlo & bit(FF_mant_len-1)) ==0) // Bit FF_mant_len-1 =0 -> abrunden + || ( ((mantlo & (bit(FF_mant_len-1)-1)) ==0) // Bit FF_mant_len-1 =1 und Bits FF_mant_len-2..0 >0 -> aufrunden + // round-to-even, je nach Bit FF_mant_len : + && ((manthi & bit(0)) ==0) + ) ) + // abrunden + goto ab; + else + // aufrunden + goto auf; + } + auf: + manthi = manthi+1; + // Hier ist 2^FF_mant_len <= manthi <= 2^(FF_mant_len+1) + if (manthi >= bit(FF_mant_len+1)) // rounding overflow? + { manthi = manthi>>1; exp1 = exp1+1; } // Shift nach rechts + ab: + // Runden fertig, 2^FF_mant_len <= manthi < 2^(FF_mant_len+1) + return encode_FF(sign1,exp1,manthi); + #endif +} diff --git a/src/float/ffloat/elem/cl_FF_plus.cc b/src/float/ffloat/elem/cl_FF_plus.cc new file mode 100644 index 0000000..061739b --- /dev/null +++ b/src/float/ffloat/elem/cl_FF_plus.cc @@ -0,0 +1,136 @@ +// binary operator + + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_FF.h" +#include "cl_F.h" +#include "cl_ieee.h" +NEED_IEEE_FLOATS() +#include "cl_xmacros.h" + +const cl_FF operator+ (const cl_FF& x1, const cl_FF& x2) +{ +// Methode (nach [Knuth, II, Seminumerical Algorithms, Abschnitt 4.2.1., S.200]): +// x1=0.0 -> Ergebnis x2. +// x2=0.0 -> Ergebnis x1. +// Falls e1= e2. +// Falls e1 - e2 >= 23 + 3, Ergebnis x1. +// Schiebe beide Mantissen um 3 Bits nach links (Vorbereitung der Rundung: +// Bei e1-e2=0,1 ist keine Rundung nötig, bei e1-e2>1 ist der Exponent des +// Ergebnisses =e1-1, =e1 oder =e1+1. Brauche daher 1 Schutzbit und zwei +// Rundungsbits: 00 exakt, 01 1.Hälfte, 10 exakte Mitte, 11 2.Hälfte.) +// Schiebe die Mantisse von x2 um e0-e1 Bits nach rechts. (Dabei die Rundung +// ausführen: Bit 0 ist das logische Oder der Bits 0,-1,-2,...) +// Falls x1,x2 selbes Vorzeichen haben: Addiere dieses zur Mantisse von x1. +// Falls x1,x2 verschiedenes Vorzeichen haben: Subtrahiere dieses von der +// Mantisse von x1. <0 -> (Es war e1=e2) Vertausche die Vorzeichen, negiere. +// =0 -> Ergebnis 0.0 +// Exponent ist e1. +// Normalisiere, fertig. + #ifdef FAST_FLOAT + float_to_FF(FF_to_float(x1) + FF_to_float(x2), return , + TRUE, TRUE, // Overflow und subnormale Zahl abfangen + FALSE, // kein Underflow mit Ergebnis +/- 0.0 möglich + // (nach Definition der subnormalen Zahlen) + FALSE, FALSE // keine Singularität, kein NaN als Ergebnis möglich + ); + + #else + // x1,x2 entpacken: + var cl_signean sign1; + var sintL exp1; + var uintL mant1; + var cl_signean sign2; + var sintL exp2; + var uintL mant2; + FF_decode(x1, { return x2; }, sign1=,exp1=,mant1=); + FF_decode(x2, { return x1; }, sign2=,exp2=,mant2=); + var cl_FF max_x1_x2 = x1; + if (exp1 < exp2) + { max_x1_x2 = x2; + swap(cl_signean, sign1,sign2); + swap(sintL, exp1 ,exp2 ); + swap(uintL, mant1,mant2); + } + // Nun ist exp1>=exp2. + var uintL expdiff = exp1 - exp2; // Exponentendifferenz + if (expdiff >= FF_mant_len+3) // >= 23+3 ? + { return max_x1_x2; } + mant1 = mant1 << 3; mant2 = mant2 << 3; + // Nun 2^(FF_mant_len+3) <= mant1,mant2 < 2^(FF_mant_len+4). + {var uintL mant2_last = mant2 & (bit(expdiff)-1); // letzte expdiff Bits von mant2 + mant2 = mant2 >> expdiff; if (!(mant2_last==0)) { mant2 |= bit(0); } + } + // mant2 = um expdiff Bits nach rechts geschobene und gerundete Mantisse + // von x2. + if (!(sign1==sign2)) + // verschiedene Vorzeichen -> Mantissen subtrahieren + { if (mant1 > mant2) { mant1 = mant1 - mant2; goto norm_2; } + if (mant1 == mant2) // Ergebnis 0 ? + { return cl_FF_0; } + // negatives Subtraktionsergebnis + mant1 = mant2 - mant1; sign1 = sign2; goto norm_2; + } + else + // gleiche Vorzeichen -> Mantissen addieren + { mant1 = mant1 + mant2; } + // mant1 = Ergebnis-Mantisse >0, sign1 = Ergebnis-Vorzeichen, + // exp1 = Ergebnis-Exponent. + // Außerdem: Bei expdiff=0,1 sind die zwei letzten Bits von mant1 Null, + // bei expdiff>=2 ist mant1 >= 2^(FF_mant_len+2). + // Stets ist mant1 < 2^(FF_mant_len+5). (Daher werden die 2 Rundungsbits + // nachher um höchstens eine Position nach links geschoben werden.) + // [Knuth, S.201, leicht modifiziert: + // N1. m>=1 -> goto N4. + // N2. [Hier m<1] m>=1/2 -> goto N5. + // N3. m:=2*m, e:=e-1, goto N2. + // N4. [Hier 1<=m<2] m:=m/2, e:=e+1. + // N5. [Hier 1/2<=m<1] Runde m auf 24 Bits hinterm Komma. + // Falls hierdurch m=1 geworden, setze m:=m/2, e:=e+1. + // ] + // Bei uns ist m=mant1/2^(FF_mant_len+4), + // ab Schritt N5 ist m=mant1/2^(FF_mant_len+1). + norm_1: // [Knuth, S.201, Schritt N1] + if (mant1 >= bit(FF_mant_len+4)) goto norm_4; + norm_2: // [Knuth, S.201, Schritt N2] + // Hier ist mant1 < 2^(FF_mant_len+4) + if (mant1 >= bit(FF_mant_len+3)) goto norm_5; + // [Knuth, S.201, Schritt N3] + mant1 = mant1 << 1; exp1 = exp1-1; // Mantisse links schieben + goto norm_2; + norm_4: // [Knuth, S.201, Schritt N4] + // Hier ist 2^(FF_mant_len+4) <= mant1 < 2^(FF_mant_len+5) + exp1 = exp1+1; + mant1 = (mant1>>1) | (mant1 & bit(0)); // Mantisse rechts schieben + norm_5: // [Knuth, S.201, Schritt N5] + // Hier ist 2^(FF_mant_len+3) <= mant1 < 2^(FF_mant_len+4) + // Auf FF_mant_len echte Mantissenbits runden, d.h. rechte 3 Bits + // wegrunden, und dabei mant1 um 3 Bits nach rechts schieben: + {var uintL rounding_bits = mant1 & (bit(3)-1); + mant1 = mant1 >> 3; + if ( (rounding_bits < bit(2)) // 000,001,010,011 werden abgerundet + || ( (rounding_bits == bit(2)) // 100 (genau halbzahlig) + && ((mant1 & bit(0)) ==0) // -> round-to-even + ) ) + // abrunden + {} + else + // aufrunden + { mant1 = mant1+1; + if (mant1 >= bit(FF_mant_len+1)) + // Bei Überlauf während der Rundung nochmals rechts schieben + // (Runden ist hier überflüssig): + { mant1 = mant1>>1; exp1 = exp1+1; } // Mantisse rechts schieben + } + }// Runden fertig + return encode_FF(sign1,exp1,mant1); + #endif +} diff --git a/src/float/ffloat/elem/cl_FF_plusp.cc b/src/float/ffloat/elem/cl_FF_plusp.cc new file mode 100644 index 0000000..e53e631 --- /dev/null +++ b/src/float/ffloat/elem/cl_FF_plusp.cc @@ -0,0 +1,28 @@ +// plusp(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_FF.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_FF_minusp.cc" +#include "cl_FF_zerop.cc" + +MAYBE_INLINE2 +cl_boolean plusp (const cl_FF& x) +{ + if (minusp(x)) + return cl_false; // x<0 -> nein + elif (zerop(x)) + return cl_false; // x=0 -> nein + else + return cl_true; // sonst ist x>0. +} diff --git a/src/float/ffloat/elem/cl_FF_scale.cc b/src/float/ffloat/elem/cl_FF_scale.cc new file mode 100644 index 0000000..0dae6ae --- /dev/null +++ b/src/float/ffloat/elem/cl_FF_scale.cc @@ -0,0 +1,49 @@ +// scale_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_FF.h" +#include "cl_F.h" + +const cl_FF scale_float (const cl_FF& x, sintL delta) +{ + // Methode: + // x=0.0 -> x als Ergebnis + // delta muß betragsmäßig <= FF_exp_high-FF_exp_low sein. + // Neues FF mit um delta vergrößertem Exponenten bilden. + // x entpacken: + var cl_signean sign; + var sintL exp; + var uint32 mant; + FF_decode(x, { return x; }, sign=,exp=,mant=); + if (delta >= 0) + // delta>=0 + { var uintL udelta = delta; + if (udelta <= (uintL)(FF_exp_high-FF_exp_low)) + { exp = exp+udelta; + return encode_FF(sign,exp,mant); + } + else + { cl_error_floating_point_overflow(); } + } + else + // delta<0 + { var uintL udelta = -delta; + if (udelta <= (uintL)(FF_exp_high-FF_exp_low)) + { exp = exp-udelta; + return encode_FF(sign,exp,mant); + } + else + if (underflow_allowed()) + { cl_error_floating_point_underflow(); } + else + { return cl_FF_0; } + } +} diff --git a/src/float/ffloat/elem/cl_FF_scale_I.cc b/src/float/ffloat/elem/cl_FF_scale_I.cc new file mode 100644 index 0000000..f83749d --- /dev/null +++ b/src/float/ffloat/elem/cl_FF_scale_I.cc @@ -0,0 +1,55 @@ +// scale_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_FF.h" +#include "cl_F.h" +#include "cl_I.h" + +const cl_FF scale_float (const cl_FF& x, const cl_I& delta) +{ + // Methode: + // x=0.0 -> x als Ergebnis + // delta muß ein Fixnum betragsmäßig <= FF_exp_high-FF_exp_low sein. + // Neues FF mit um delta vergrößertem Exponenten bilden. + // x entpacken: + var cl_signean sign; + var sintL exp; + var uint32 mant; + FF_decode(x, { return x; }, sign=,exp=,mant=); + if (!minusp(delta)) + // delta>=0 + { var uintL udelta; + if (fixnump(delta) + && ((udelta = FN_to_L(delta)) <= (uintL)(FF_exp_high-FF_exp_low)) + ) + { exp = exp+udelta; + return encode_FF(sign,exp,mant); + } + else + { cl_error_floating_point_overflow(); } + } + else + // delta<0 + { var uintL udelta; + if (fixnump(delta) + && ((udelta = -FN_to_L(delta)) <= (uintL)(FF_exp_high-FF_exp_low)) + && ((cl_value_len+10, <2^(FF_mant_len+1) in ein Fixnum umwandeln: + #if (FF_mant_len+1 < cl_value_len) + L_to_FN(sign==0 ? (sintL)mant : -(sintL)mant) + #else + L_to_I(sign==0 ? (sintL)mant : -(sintL)mant) + #endif + ,exp + ); +} diff --git a/src/float/ffloat/elem/cl_FF_uminus.cc b/src/float/ffloat/elem/cl_FF_uminus.cc new file mode 100644 index 0000000..2d59df0 --- /dev/null +++ b/src/float/ffloat/elem/cl_FF_uminus.cc @@ -0,0 +1,23 @@ +// unary operator - + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_FF.h" + +const cl_FF operator- (const cl_FF& x) +{ +// Methode: +// Falls x=0.0, fertig. Sonst Vorzeichenbit umdrehen. + var ffloat x_ = cl_ffloat_value(x); + if (FF_uexp(x_) == 0) + return x; + else + return allocate_ffloat( x_ ^ bit(31) ); +} diff --git a/src/float/ffloat/elem/cl_FF_zerop.cc b/src/float/ffloat/elem/cl_FF_zerop.cc new file mode 100644 index 0000000..69d8574 --- /dev/null +++ b/src/float/ffloat/elem/cl_FF_zerop.cc @@ -0,0 +1,18 @@ +// zerop(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_FF.h" + +MAYBE_INLINE +cl_boolean zerop (const cl_FF& x) +{ + return (cl_boolean) (cl_ffloat_value(x) == 0); +} diff --git a/src/float/ffloat/input/Makeflags b/src/float/ffloat/input/Makeflags new file mode 100644 index 0000000..1916d46 --- /dev/null +++ b/src/float/ffloat/input/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/ffloat/Makeflags +SUBDIR_INCLUDES += diff --git a/src/float/ffloat/input/cl_FF_from_string.cc b/src/float/ffloat/input/cl_FF_from_string.cc new file mode 100644 index 0000000..9736b62 --- /dev/null +++ b/src/float/ffloat/input/cl_FF_from_string.cc @@ -0,0 +1,27 @@ +// cl_FF (const char *) constructor. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat_class.h" + + +// Implementation. + +#include "cl_ffloat.h" +#include "cl_input.h" +#include "cl_float_io.h" + +cl_read_flags cl_FF_read_flags = { + syntax_ffloat, + lsyntax_all, + 10, + { cl_float_format_ffloat, cl_float_format_lfloat_min, cl_false } +}; + +cl_FF::cl_FF (const char * string) +{ + pointer = as_cl_private_thing( + As(cl_FF)(read_float(cl_FF_read_flags,string,NULL,NULL))); +} diff --git a/src/float/ffloat/misc/Makeflags b/src/float/ffloat/misc/Makeflags new file mode 100644 index 0000000..4934bd6 --- /dev/null +++ b/src/float/ffloat/misc/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/ffloat/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/float/ffloat/elem -I$(srcdir)/integer -I$(srcdir)/base/digitseq -I$(srcdir)/base/digit -Ibase $(GMP_INCLUDES) diff --git a/src/float/ffloat/misc/cl_FF_abs.cc b/src/float/ffloat/misc/cl_FF_abs.cc new file mode 100644 index 0000000..1b65e0a --- /dev/null +++ b/src/float/ffloat/misc/cl_FF_abs.cc @@ -0,0 +1,20 @@ +// abs(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_FF_minusp.cc" + +const cl_FF abs (const cl_FF& x) +{ +// x<0 -> (- x), x>=0 -> x + if (minusp(x)) return -x; else return x; +} diff --git a/src/float/ffloat/misc/cl_FF_as.cc b/src/float/ffloat/misc/cl_FF_as.cc new file mode 100644 index 0000000..8581d82 --- /dev/null +++ b/src/float/ffloat/misc/cl_FF_as.cc @@ -0,0 +1,35 @@ +// as_cl_FF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_N.h" + +inline cl_boolean cl_FF_p (const cl_number& x) +{ +#if defined(CL_WIDE_POINTERS) + if (!x.pointer_p()) + if (cl_tag((x).word) == cl_FF_tag) + return cl_true; +#else + if (x.pointer_p()) + if (x.heappointer->type == &cl_class_ffloat) + return cl_true; +#endif + return cl_false; +} + +const cl_FF& as_cl_FF (const cl_number& x, const char * filename, int line) +{ + if (cl_FF_p(x)) { + DeclareType(cl_FF,x); + return x; + } else + cl_as_error(x,"a single-float number",filename,line); +} diff --git a/src/float/ffloat/misc/cl_FF_class.cc b/src/float/ffloat/misc/cl_FF_class.cc new file mode 100644 index 0000000..11cf4a0 --- /dev/null +++ b/src/float/ffloat/misc/cl_FF_class.cc @@ -0,0 +1,26 @@ +// cl_class_ffloat. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +cl_class cl_class_ffloat = { +#ifdef CL_WIDE_POINTERS + NULL, // destructor not used, since not heap objects +#else + NULL, // empty destructor +#endif + cl_class_flags_subclass_complex | cl_class_flags_subclass_real | cl_class_flags_subclass_float +}; + +#ifdef CL_WIDE_POINTERS +AT_INITIALIZATION(ini_class_ffloat) +{ + cl_immediate_classes[cl_FF_tag] = &cl_class_ffloat; +} +#endif diff --git a/src/float/ffloat/misc/cl_FF_debug.cc b/src/float/ffloat/misc/cl_FF_debug.cc new file mode 100644 index 0000000..60998ac --- /dev/null +++ b/src/float/ffloat/misc/cl_FF_debug.cc @@ -0,0 +1,25 @@ +// cl_FF debugging support. + +// General includes. +#include "cl_sysdep.h" + +// Specification. + + +// Implementation. + +#include "cl_ffloat.h" +#include "cl_io.h" +#include "cl_float_io.h" + +static void dprint (cl_heap* pointer) +{ + var const cl_FF& obj = *(const cl_FF*)&pointer; + fprint(cl_debugout, "(cl_FF) "); + fprint(cl_debugout, obj); +} +AT_INITIALIZATION(dprint_FF) +{ cl_register_type_printer(cl_class_ffloat,dprint); } + +// This dummy links in this module when requires it. +int cl_FF_debug_module; diff --git a/src/float/ffloat/misc/cl_FF_decode.cc b/src/float/ffloat/misc/cl_FF_decode.cc new file mode 100644 index 0000000..31c1ccf --- /dev/null +++ b/src/float/ffloat/misc/cl_FF_decode.cc @@ -0,0 +1,29 @@ +// decode_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_FF.h" +#include "cl_I.h" + +const cl_decoded_ffloat decode_float (const cl_FF& x) +{ + // x entpacken: + var cl_signean sign; + var sintL exp; + var uint32 mant; + FF_decode(x, { return cl_decoded_ffloat(cl_FF_0, 0, cl_FF_1); }, + sign=,exp=,mant= + ); + return cl_decoded_ffloat( + encode_FF(0,0,mant), // (-1)^0 * 2^0 * m erzeugen + L_to_FN(exp), // e als Fixnum + encode_FF(sign,1,bit(FF_mant_len)) // (-1)^s erzeugen + ); +} diff --git a/src/float/ffloat/misc/cl_FF_digits.cc b/src/float/ffloat/misc/cl_FF_digits.cc new file mode 100644 index 0000000..3b48413 --- /dev/null +++ b/src/float/ffloat/misc/cl_FF_digits.cc @@ -0,0 +1,19 @@ +// float_digits(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_FF.h" + +MAYBE_INLINE +uintL float_digits (const cl_FF& x) +{ + unused x; + return FF_mant_len+1; // 24 +} diff --git a/src/float/ffloat/misc/cl_FF_eqhashcode.cc b/src/float/ffloat/misc/cl_FF_eqhashcode.cc new file mode 100644 index 0000000..2f0492e --- /dev/null +++ b/src/float/ffloat/misc/cl_FF_eqhashcode.cc @@ -0,0 +1,24 @@ +// cl_FF equal_hashcode(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_N.h" +#include "cl_FF.h" + +MAYBE_INLINE +uint32 cl_equal_hashcode (const cl_FF& x) +{ + var cl_signean sign; + var sintL exp; + var uint32 mant; + FF_decode(x, { return 0; }, sign=,exp=,mant=); + var uint32 msd = mant << (32-(FF_mant_len+1)); + return equal_hashcode_low(msd,exp,sign); +} diff --git a/src/float/ffloat/misc/cl_FF_exponent.cc b/src/float/ffloat/misc/cl_FF_exponent.cc new file mode 100644 index 0000000..4b11e8d --- /dev/null +++ b/src/float/ffloat/misc/cl_FF_exponent.cc @@ -0,0 +1,20 @@ +// float_exponent(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_FF.h" + +MAYBE_INLINE +sintL float_exponent (const cl_FF& x) +{ + var uintL uexp = FF_uexp(cl_ffloat_value(x)); + if (uexp==0) { return 0; } + return (sintL)(uexp - FF_exp_mid); +} diff --git a/src/float/ffloat/misc/cl_FF_idecode.cc b/src/float/ffloat/misc/cl_FF_idecode.cc new file mode 100644 index 0000000..7d52bd9 --- /dev/null +++ b/src/float/ffloat/misc/cl_FF_idecode.cc @@ -0,0 +1,54 @@ +// integer_decode_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_FF.h" +#include "cl_I.h" + +#if defined(__mips__) && !defined(__GNUC__) + +// Workaround SGI Irix 6.2 C++ 7.0 bug. + +#include "cl_F.h" +#include "dfloat/cl_DF.h" + +MAYBE_INLINE +const cl_idecoded_float integer_decode_float (const cl_FF& x) +{ + var cl_idecoded_float sem = integer_decode_float(cl_FF_to_DF(x)); + return cl_idecoded_float(sem.mantissa >> (DF_mant_len-FF_mant_len), + sem.exponent + (DF_mant_len-FF_mant_len), + sem.sign + ); +} + +#else + +MAYBE_INLINE +const cl_idecoded_float integer_decode_float (const cl_FF& x) +{ + // x entpacken: + var cl_signean sign; + var sintL exp; + var uint32 mant; + FF_decode(x, { return cl_idecoded_float(0, 0, 1); }, + sign=,exp=,mant= + ); + return cl_idecoded_float( + (FF_mant_len+1 < cl_value_len + ? L_to_FN(mant) // Mantisse als Fixnum + : UL_to_I(mant) // oder evtl. als Bignum + ), + L_to_FN(exp-(FF_mant_len+1)), // e-24 als Fixnum + (sign>=0 ? cl_I(1) : cl_I(-1)) // (-1)^s erzeugen + ); +} + +#endif diff --git a/src/float/ffloat/misc/cl_FF_max.cc b/src/float/ffloat/misc/cl_FF_max.cc new file mode 100644 index 0000000..00230d1 --- /dev/null +++ b/src/float/ffloat/misc/cl_FF_max.cc @@ -0,0 +1,15 @@ +// max(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +const cl_FF max (const cl_FF& x, const cl_FF& y) +{ + return (x >= y ? x : y); +} diff --git a/src/float/ffloat/misc/cl_FF_min.cc b/src/float/ffloat/misc/cl_FF_min.cc new file mode 100644 index 0000000..a9e1513 --- /dev/null +++ b/src/float/ffloat/misc/cl_FF_min.cc @@ -0,0 +1,15 @@ +// min(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +const cl_FF min (const cl_FF& x, const cl_FF& y) +{ + return (x <= y ? x : y); +} diff --git a/src/float/ffloat/misc/cl_FF_precision.cc b/src/float/ffloat/misc/cl_FF_precision.cc new file mode 100644 index 0000000..0d2a3b1 --- /dev/null +++ b/src/float/ffloat/misc/cl_FF_precision.cc @@ -0,0 +1,23 @@ +// float_precision(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_FF.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_FF_zerop.cc" + +MAYBE_INLINE2 +uintL float_precision (const cl_FF& x) +{ + if (zerop(x)) return 0; + return FF_mant_len+1; // 24 +} diff --git a/src/float/ffloat/misc/cl_FF_sign.cc b/src/float/ffloat/misc/cl_FF_sign.cc new file mode 100644 index 0000000..1e8e9bb --- /dev/null +++ b/src/float/ffloat/misc/cl_FF_sign.cc @@ -0,0 +1,23 @@ +// float_sign(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_FF.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_FF_minusp.cc" + +MAYBE_INLINE2 +const cl_FF float_sign (const cl_FF& x) +{ +// Methode: x>=0 -> Ergebnis 1.0; x<0 -> Ergebnis -1.0 + return (!minusp(x) ? cl_FF_1 : cl_FF_minus1); +} diff --git a/src/float/ffloat/misc/cl_FF_signum.cc b/src/float/ffloat/misc/cl_FF_signum.cc new file mode 100644 index 0000000..6c8bc56 --- /dev/null +++ b/src/float/ffloat/misc/cl_FF_signum.cc @@ -0,0 +1,25 @@ +// signum(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_ffloat.h" + + +// Implementation. + +#include "cl_FF.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_FF_minusp.cc" +#include "cl_FF_zerop.cc" + +MAYBE_INLINE2 +const cl_FF signum (const cl_FF& x) +{ + if (minusp(x)) { return cl_FF_minus1; } // x<0 -> -1.0 + elif (zerop(x)) { return cl_FF_0; } // x=0 -> 0.0 + else { return cl_FF_1; } // x>0 -> +1.0 +} diff --git a/src/float/input/Makeflags b/src/float/input/Makeflags new file mode 100644 index 0000000..ffd9450 --- /dev/null +++ b/src/float/input/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/rational -I$(srcdir)/integer -I$(srcdir)/base/string diff --git a/src/float/input/cl_F_from_string.cc b/src/float/input/cl_F_from_string.cc new file mode 100644 index 0000000..c734175 --- /dev/null +++ b/src/float/input/cl_F_from_string.cc @@ -0,0 +1,27 @@ +// cl_F (const char *) constructor. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float_class.h" + + +// Implementation. + +#include "cl_float.h" +#include "cl_input.h" +#include "cl_float_io.h" + +cl_read_flags cl_F_read_flags = { + syntax_float, + lsyntax_all, + 10, + { cl_float_format_ffloat, cl_float_format_lfloat_min, cl_true } +}; + +cl_F::cl_F (const char * string) +{ + pointer = as_cl_private_thing( + read_float(cl_F_read_flags,string,NULL,NULL)); +} diff --git a/src/float/input/cl_F_read.cc b/src/float/input/cl_F_read.cc new file mode 100644 index 0000000..e46e51f --- /dev/null +++ b/src/float/input/cl_F_read.cc @@ -0,0 +1,178 @@ +// read_float(). +// This file contains a slimmed down version of read_real(). +// It does not pull in all the generic real number code. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float_io.h" + + +// Implementation. + +#include +#include "cl_input.h" +#include "cl_integer.h" +#include "cl_I.h" +#include "cl_F.h" + +#undef floor +#include +#define floor cln_floor + +// Step forward over all digits, to the end of string or to the next non-digit. +static const char * skip_digits (const char * ptr, const char * string_limit, unsigned int base) +{ + for ( ; ptr != string_limit; ptr++) { + var char ch = *ptr; + if ((ch >= '0') && (ch <= '9')) + if (ch < '0' + (int)base) + continue; + else + break; + else { + if (base <= 10) + break; + if (((ch >= 'A') && (ch < 'A'-10+(int)base)) + || ((ch >= 'a') && (ch < 'a'-10+(int)base)) + ) + continue; + else + break; + } + } + return ptr; +} + +#define at_end_of_parse(ptr) \ + if (end_of_parse) \ + { *end_of_parse = (ptr); } \ + else \ + { if ((ptr) != string_limit) { read_number_junk((ptr),string,string_limit); } } + +const cl_F read_float (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse) +{ + ASSERT((flags.syntax & ~(syntax_float|syntax_maybe_bad)) == 0); + // If no string_limit is given, it defaults to the end of the string. + if (!string_limit) + string_limit = string + strlen(string); + if (flags.syntax & syntax_float) { + // Check for floating-point number syntax: + // {'+'|'-'|} {digit}+ {'.' {digit}* | } expo {'+'|'-'|} {digit}+ + // {'+'|'-'|} {digit}* '.' {digit}+ expo {'+'|'-'|} {digit}+ + // {'+'|'-'|} {digit}* '.' {digit}+ + var const char * ptr = string; + var const unsigned int float_base = 10; + var cl_signean sign = 0; + if (ptr == string_limit) goto not_float_syntax; + switch (*ptr) { + case '-': sign = ~sign; + case '+': ptr++; + default: break; + } + var const char * ptr_after_sign = ptr; + var const char * ptr_after_intpart = skip_digits(ptr_after_sign,string_limit,float_base); + var cl_boolean have_dot = cl_false; + var const char * ptr_before_fracpart = ptr_after_intpart; + var const char * ptr_after_fracpart = ptr_after_intpart; + ptr = ptr_after_intpart; + if (ptr != string_limit) + if (*ptr == '.') { + have_dot = cl_true; + ptr_before_fracpart = ptr+1; + ptr_after_fracpart = skip_digits(ptr_before_fracpart,string_limit,float_base); + } + ptr = ptr_after_fracpart; + var char exponent_marker; + var cl_boolean have_exponent; + var const char * ptr_in_exponent = ptr; + var const char * ptr_after_exponent = ptr; + if ((ptr == string_limit) || !(((*ptr >= '0') && (*ptr <= '9')) || ((*ptr >= 'A') && (*ptr <= 'Z') && (*ptr != 'I')) || ((*ptr >= 'a') && (*ptr <= 'z') && (*ptr != 'i')) || (*ptr == '.') || (*ptr == '/'))) { + // No exponent. + have_exponent = cl_false; + // Must have at least one fractional part digit. + if (ptr_after_fracpart == ptr_before_fracpart) goto not_float_syntax; + exponent_marker = 'E'; + } else { + have_exponent = cl_true; + // Must have at least one digit. + if (ptr_after_sign == ptr_after_intpart) + if (ptr_after_fracpart == ptr_before_fracpart) + goto not_float_syntax; + exponent_marker = ((*ptr >= 'a') && (*ptr <= 'z') ? *ptr - 'a' + 'A' : *ptr); + switch (exponent_marker) { + case 'E': + case 'S': case 'F': case 'D': case 'L': + break; + default: + goto not_float_syntax; + } + } + if (have_exponent) { + ptr++; + if (ptr == string_limit) goto not_float_syntax; + switch (*ptr) { + case '-': + case '+': ptr++; + default: break; + } + ptr_in_exponent = ptr; + ptr_after_exponent = skip_digits(ptr_in_exponent,string_limit,10); + if (ptr_after_exponent == ptr_in_exponent) goto not_float_syntax; + } + ptr = ptr_after_exponent; + var const char * ptr_after_prec = ptr; + var cl_float_format_t prec; + if ((ptr != string_limit) && (*ptr == '_')) { + ptr++; + ptr_after_prec = skip_digits(ptr,string_limit,10); + if (ptr_after_prec == ptr) goto not_float_syntax; + var cl_I prec1 = digits_to_I(ptr,ptr_after_prec-ptr,10); + var uintL prec2 = cl_I_to_UL(prec1); + prec = (float_base==10 ? cl_float_format(prec2) + : (cl_float_format_t)((uintL)((1+prec2)*log((double)float_base)*1.442695041)+1) + ); + } else { + switch (exponent_marker) { + case 'S': prec = cl_float_format_sfloat; break; + case 'F': prec = cl_float_format_ffloat; break; + case 'D': prec = cl_float_format_dfloat; break; + case 'L': prec = flags.float_flags.default_lfloat_format; break; + case 'E': prec = flags.float_flags.default_float_format; break; + default: NOTREACHED + } + if (flags.float_flags.mantissa_dependent_float_format) { + // Count the number of significant digits. + ptr = ptr_after_sign; + while (ptr < ptr_after_fracpart && (*ptr == '0' || *ptr == '.')) ptr++; + var uintL num_significant_digits = + (ptr_after_fracpart - ptr) - (ptr_before_fracpart > ptr ? 1 : 0); + var uintL prec2 = (num_significant_digits>=2 ? num_significant_digits-2 : 0); + var cl_float_format_t precx = + (float_base==10 ? cl_float_format(prec2) + : (cl_float_format_t)((uintL)((1+prec2)*log((double)float_base)*1.442695041)+1) + ); + if ((uintL)precx > (uintL)prec) + prec = precx; + } + } + floatformatcase(prec + , if (!(flags.syntax & syntax_sfloat)) goto not_float_syntax; + , if (!(flags.syntax & syntax_ffloat)) goto not_float_syntax; + , if (!(flags.syntax & syntax_dfloat)) goto not_float_syntax; + , unused len; + if (!(flags.syntax & syntax_lfloat)) goto not_float_syntax; + ); + at_end_of_parse(ptr_after_prec); + return read_float(float_base,prec,sign,ptr_after_sign,0,ptr_after_fracpart-ptr_after_sign,ptr_after_exponent-ptr_after_sign,ptr_before_fracpart-ptr_after_sign); + } +not_float_syntax: +bad_syntax: + if (flags.syntax & syntax_maybe_bad) { + ASSERT(end_of_parse); + *end_of_parse = string; + return cl_F(); // dummy return + } + read_number_bad_syntax(string,string_limit); +} diff --git a/src/float/input/cl_F_read_stream.cc b/src/float/input/cl_F_read_stream.cc new file mode 100644 index 0000000..30ef968 --- /dev/null +++ b/src/float/input/cl_F_read_stream.cc @@ -0,0 +1,104 @@ +// read_float(). +// This file contains a slimmed down version of read_real(). +// It does not pull in all the generic real number code. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float_io.h" + + +// Implementation. + +#include "cl_input.h" +#include "cl_io.h" +#include "cl_spushstring.h" + +// We read an entire token (or even more, if it begins with #C) into a +// buffer and then call read_float() on the buffer. + +class pushstring_hack : public cl_spushstring { +public: + char* start_pointer (void) { return buffer; } + char* end_pointer (void) { return buffer+index; } +}; + +static cl_boolean number_char_p (char c) +{ + if ((c >= '0') && (c <= '9')) + return cl_true; + if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'))) + return cl_true; + switch (c) { + case '+': case '-': case '.': case '/': + return cl_true; + default: + return cl_false; + } +} + +const cl_F read_float (cl_istream stream, const cl_read_flags& flags) +{ + // One pre-allocated buffer. This reduces the allocation/free cost. + static pushstring_hack buffer; + + var int c; + // Skip whitespace at the beginning. + loop { + c = freadchar(stream); + if (c == cl_EOF) goto eof; + if ((c == ' ') || (c == '\t') || (c == '\n')) + continue; + else + break; + } + // Found first non-whitespace character. + // Numbers cannot cross lines. We can treat EOF and '\n' the same way. + buffer.reset(); + if (c == '#') { + if (!(flags.lsyntax & lsyntax_commonlisp)) + goto syntax1; + buffer.push(c); + // Read some digits, then a letter, then a token. + loop { + c = freadchar(stream); + if (c == cl_EOF) goto eof; + buffer.push(c); + if ((c >= '0') && (c <= '9')) + continue; + else + break; + } + if (!(((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')))) + goto syntax1; + buffer.push(c); + c = freadchar(stream); + if (c == cl_EOF) goto eof; + } + // Read a number token. + if (!number_char_p(c)) + goto syntax1; + loop { + buffer.push(c); + c = freadchar(stream); + if (c == cl_EOF) + break; + if (!number_char_p(c)) { + funreadchar(stream,c); + break; + } + } + // Parse the number. + return read_float(flags, + buffer.start_pointer(), buffer.end_pointer(), + NULL + ); + + // Handle syntax error. +syntax1: buffer.push(c); + read_number_bad_syntax(buffer.start_pointer(),buffer.end_pointer()); + + // Handle premature EOF. +eof: read_number_eof(); +} diff --git a/src/float/input/cl_F_readparsed.cc b/src/float/input/cl_F_readparsed.cc new file mode 100644 index 0000000..a33e968 --- /dev/null +++ b/src/float/input/cl_F_readparsed.cc @@ -0,0 +1,93 @@ +// read_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float_io.h" + + +// Implementation. + +#include "cl_integer.h" +#include "cl_I.h" +#include "cl_rational.h" +#include "cl_RA.h" +#include "cl_float.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" +#include "cl_F.h" +#include "cl_SF.h" +#include "cl_FF.h" +#include "cl_DF.h" +#include "cl_LF.h" + +const cl_F read_float (unsigned int base, cl_float_format_t prec, cl_signean sign, const char * string, uintL index1, uintL index4, uintL index2, uintL index3) +{ + var cl_I exponent; + { + var uintL exp_len = index2-index4; // Anzahl Stellen des Exponenten + if (exp_len > 0) { + var const char * ptr = &string[index4]; // zeigt auf den Exponentmarker + ptr++; exp_len--; // Exponentmarker überlesen + var cl_signean exp_sign = 0; // Exponenten-Vorzeichen + switch (*ptr) { + case '-': exp_sign = ~exp_sign; // Vorzeichen := negativ + case '+': ptr++; exp_len--; // Exponenten-Vorzeichen überlesen + default: ; + } + exponent = digits_to_I(ptr,exp_len,(uintD)base); // Exponent in Integer umwandeln + if (!(exp_sign==0)) + exponent = -exponent; // incl. Vorzeichen + } else { + // kein Exponent da + exponent = 0; + } + } + // exponent = Exponent als Integer. + var cl_RA base_power = expt(base,exponent-(index4-index3)); // zu multiplizierende Zehnerpotenz + var cl_I mantisse = // Mantisse als Integer + digits_to_I(&string[index1],index4-index1,(uintD)base); + // Mantisse (Integer) und Zehnerpotenz (rational >0) unelegant zusammenmultiplizieren: + var cl_RA ratvalue; + if (integerp(base_power)) { + DeclareType(cl_I,base_power); + ratvalue = mantisse * base_power; + } else { + // falls mantisse/=0, in exponent=1/10^i den Zähler durch mantisse + // ersetzen (liefert ungekürzten Bruch, Vorsicht!) + DeclareType(cl_RT,base_power); + if (zerop(mantisse)) + ratvalue = 0; + else { + ASSERT(TheRatio(base_power)->refcount == 1); + TheRatio(base_power)->numerator = mantisse; + ratvalue = base_power; + } + } + // ratvalue = Mantisse * Zehnerpotenz, als ungekürzte rationale Zahl! + floatformatcase(prec + , // in Short-Float umwandeln + { + var cl_SF x = cl_RA_to_SF(ratvalue); + if (sign==0) { return x; } else { return -x; } + } + , // in Single-Float umwandeln + { + var cl_FF x = cl_RA_to_FF(ratvalue); + if (sign==0) { return x; } else { return -x; } + } + , // in Double-Float umwandeln + { + var cl_DF x = cl_RA_to_DF(ratvalue); + if (sign==0) { return x; } else { return -x; } + } + , // in Long-Float umwandeln + { + var cl_LF x = cl_RA_to_LF(ratvalue,len); + if (sign==0) { return x; } else { return -x; } + } + ); +} diff --git a/src/float/lfloat/Makeflags b/src/float/lfloat/Makeflags new file mode 100644 index 0000000..eced2ef --- /dev/null +++ b/src/float/lfloat/Makeflags @@ -0,0 +1,3 @@ +# This file contains additional flags for the main Makefile. + +SUBDIR_INCLUDES = -I$(srcdir)/float/lfloat -I$(srcdir)/float -I$(srcdir)/base/digitseq -I$(srcdir)/base/digit -Ibase -I$(srcdir)/base $(GMP_INCLUDES) diff --git a/src/float/lfloat/algebraic/Makeflags b/src/float/lfloat/algebraic/Makeflags new file mode 100644 index 0000000..b886167 --- /dev/null +++ b/src/float/lfloat/algebraic/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/lfloat/Makeflags +SUBDIR_INCLUDES += diff --git a/src/float/lfloat/algebraic/cl_LF_sqrt.cc b/src/float/lfloat/algebraic/cl_LF_sqrt.cc new file mode 100644 index 0000000..9679a40 --- /dev/null +++ b/src/float/lfloat/algebraic/cl_LF_sqrt.cc @@ -0,0 +1,130 @@ +// sqrt(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" +#include "cl_LF_impl.h" +#include "cl_F.h" +#include "cl_DS.h" +#include "cl_abort.h" + +const cl_LF sqrt (const cl_LF& x) +{ +// Methode: +// x = 0.0 -> Ergebnis 0.0 +// Ergebnis-Vorzeichen := positiv, +// Ergebnis-Exponent := ceiling(e/2), +// Ergebnis-Mantisse: +// Erweitere die Mantisse (n Digits) um n+2 Nulldigits nach hinten. +// Bei ungeradem e schiebe dies (oder nur die ersten n+1 Digits davon) +// um 1 Bit nach rechts. +// Bilde daraus die Ganzzahl-Wurzel, eine n+1-Digit-Zahl mit einer +// führenden 1. +// Runde das letzte Digit weg: +// Bit 15 = 0 -> abrunden, +// Bit 15 = 1, Rest =0 und Wurzel exakt -> round-to-even, +// sonst aufrunden. +// Bei rounding overflow Mantisse um 1 Bit nach rechts schieben +// und Exponent incrementieren. + var uintL uexp = TheLfloat(x)->expo; + if (uexp==0) { return x; } // x=0.0 -> 0.0 als Ergebnis + var uintC len = TheLfloat(x)->len; + // Radikanden bilden: + CL_ALLOCA_STACK; + var uintD* r_MSDptr; + var uintD* r_LSDptr; + var uintL r_len = 2*(uintL)len+2; // Länge des Radikanden + num_stack_alloc(r_len, r_MSDptr=,r_LSDptr=); + uexp = uexp - LF_exp_mid + 1; + if (uexp & bit(0)) + // Exponent gerade + {var uintD* ptr = + copy_loop_msp(arrayMSDptr(TheLfloat(x)->data,len),r_MSDptr,len); // n Digits kopieren + clear_loop_msp(ptr,len+2); // n+2 Nulldigits anhängen + } + else + // Exponent ungerade + {var uintD carry_rechts = // n Digits kopieren und um 1 Bit rechts shiften + shiftrightcopy_loop_msp(arrayMSDptr(TheLfloat(x)->data,len),r_MSDptr,len,1,0); + var uintD* ptr = r_MSDptr mspop len; + msprefnext(ptr) = carry_rechts; // Übertrag und + clear_loop_msp(ptr,len+1); // n+1 Nulldigits anhängen + } + uexp = (sintL)((sintL)uexp >> 1); // Exponent halbieren + uexp = uexp + LF_exp_mid; + // Ergebnis allozieren: + var Lfloat y = allocate_lfloat(len,uexp,0); + var uintD* y_mantMSDptr = arrayMSDptr(TheLfloat(y)->data,len); + // Wurzel ziehen: +#ifndef CL_LF_PEDANTIC + if (len > 1900) // Das ist etwa 10% bis 20% schneller (im Mittel 15%). + { // Kehrwert der Wurzel errechnen: + var uintD* s_MSDptr; + var uintD* s_LSDptr; + num_stack_alloc(len+2, s_MSDptr=,s_LSDptr=); + cl_UDS_recipsqrt(r_MSDptr,r_len, s_MSDptr,len); + // Mit dem Radikanden multiplizieren: + var uintD* p_MSDptr; + var uintD* p_LSDptr; + num_stack_alloc(2*len+3, p_MSDptr=,p_LSDptr=); + cl_UDS_mul(r_MSDptr mspop (len+1),len+1,s_LSDptr,len+2,p_LSDptr); + // Ablegen und runden: + copy_loop_msp(p_MSDptr mspop 1,y_mantMSDptr,len); // NUDS nach y kopieren + if (mspref(p_MSDptr,0) == 0) + { if ( ((sintD)mspref(p_MSDptr,len+1) >= 0) // nächstes Bit =0 -> abrunden + || ( ((mspref(p_MSDptr,len+1) & ((uintD)bit(intDsize-1)-1)) ==0) // =1 und weitere Bits >0 -> aufrunden + && !test_loop_msp(p_MSDptr mspop (len+2),len+1) + // round-to-even (etwas witzlos, da eh alles ungenau ist) + && ((mspref(p_MSDptr,len) & bit(0)) ==0) + ) ) + // abrunden + {} + else + // aufrunden + { if ( inc_loop_lsp(y_mantMSDptr mspop len,len) ) + // Übertrag durchs Aufrunden + { mspref(y_mantMSDptr,0) = bit(intDsize-1); // Mantisse := 10...0 + (TheLfloat(y)->expo)++; // Exponenten incrementieren + } } + } + else + // Übertrag durch Rundungsfehler + { if (test_loop_msp(y_mantMSDptr,len)) cl_abort(); + mspref(y_mantMSDptr,0) = bit(intDsize-1); // Mantisse := 10...0 + (TheLfloat(y)->expo)++; // Exponenten incrementieren + } + return y; + } +#endif + var DS w; + var cl_boolean exactp; + UDS_sqrt(r_MSDptr,r_len,r_LSDptr, &w, exactp=); + // w ist die Ganzzahl-Wurzel, eine n+1-Digit-Zahl. + copy_loop_msp(w.MSDptr,y_mantMSDptr,len); // NUDS nach y kopieren + // Runden: + if ( ((sintD)lspref(w.LSDptr,0) >= 0) // nächstes Bit =0 -> abrunden + || ( ((lspref(w.LSDptr,0) & ((uintD)bit(intDsize-1)-1)) ==0) // =1 und weitere Bits >0 oder Rest >0 -> aufrunden + && exactp + // round-to-even + && ((lspref(w.LSDptr,1) & bit(0)) ==0) + ) ) + // abrunden + {} + else + // aufrunden + { if ( inc_loop_lsp(y_mantMSDptr mspop len,len) ) + // Übertrag durchs Aufrunden + { mspref(y_mantMSDptr,0) = bit(intDsize-1); // Mantisse := 10...0 + (TheLfloat(y)->expo)++; // Exponenten incrementieren + } } + return y; +} +// Bit complexity (N := length(x)): O(M(N)). + diff --git a/src/float/lfloat/cl_LF.h b/src/float/lfloat/cl_LF.h new file mode 100644 index 0000000..a682857 --- /dev/null +++ b/src/float/lfloat/cl_LF.h @@ -0,0 +1,140 @@ +// cl_LF internals + +#ifndef _CL_LF_H +#define _CL_LF_H + +#include "cl_number.h" +#include "cl_lfloat_class.h" +#include "cl_integer_class.h" + +struct cl_heap_lfloat : cl_heap { + unsigned int len; // length of mantissa (in digits) + int sign; // sign (0 or -1) + uint32 expo; // exponent + uintD data[1]; // mantissa +}; + +// Minimum number of mantissa digits, +// so that a LF has not fewer mantissa bits than a DF. + #define LF_minlen ceiling(53,intDsize) +// Exponent. + #define LF_exp_low 1 + #define LF_exp_mid 0x80000000UL + #define LF_exp_high 0xFFFFFFFFUL + +inline cl_heap_lfloat* TheLfloat (cl_heap_lfloat* p) + { return p; } +inline cl_heap_lfloat* TheLfloat (const cl_number& obj) + { return (cl_heap_lfloat*)(obj.pointer); } + + +// Liefert zu einem Long-Float x : (futruncate x), ein LF. +// x wird von der 0 weg zur nächsten ganzen Zahl gerundet. +extern const cl_LF futruncate (const cl_LF& x); + +// shorten(x,len) verkürzt ein Long-Float x auf gegebene Länge len +// und rundet dabei. +// > cl_LF x: ein Long-FLoat +// > uintC len: gewünschte Länge (>= LF_minlen, < TheLfloat(x)->len) +// < cl_LF ergebnis: verkürztes Long-Float +extern const cl_LF shorten (const cl_LF& x, uintC len); + +// extend(x,len) verlängert ein Long-Float x auf gegebene Länge len. +// > cl_LF x: ein Long-FLoat +// > uintC len: gewünschte Länge (> TheLfloat(x)->len) +// < cl_LF ergebnis: verlängertes Long-Float +extern const cl_LF extend (const cl_LF& x, uintC len); + +// LF_to_LF(x,len) wandelt ein Long-Float x in ein Long-Float gegebener Länge +// len um und rundet dabei nötigenfalls. +// > cl_LF x: ein Long-FLoat +// > uintC len: gewünschte Länge (>= LF_minlen) +// < cl_LF ergebnis: Long-Float gegebener Länge +extern const cl_LF LF_to_LF (const cl_LF& x, uintC len); + +// GEN_LF_OP2(arg1,arg2,LF_OP,ergebnis_zuweisung) +// generates the body of a LF operation with two arguments. +// LF_OP is only executed once both arguments have been converted to the same +// float format (the longer one of arg1 and arg2). The result is then +// converted the shorter of the two float formats. +#define GEN_LF_OP2(arg1,arg2,LF_OP,ergebnis_zuweisung) \ +{ \ + var uintC len1 = TheLfloat(arg1)->len; \ + var uintC len2 = TheLfloat(arg2)->len; \ + if (len1==len2) /* gleich -> direkt ausführen */ \ + return LF_OP(arg1,arg2); \ + elif (len1>len2) /* -> arg2 auf die Länge von arg1 bringen */ \ + return shorten(LF_OP(arg1,extend(arg2,len1)),len2); \ + else /* (len1 arg1 auf die Länge von arg2 bringen */ \ + return shorten(LF_OP(extend(arg1,len2),arg2),len1); \ +} + +// Liefert zu zwei gleichlangen Long-Float x und y : (+ x y), ein LF. +// LF_LF_plus_LF(x) +extern const cl_LF LF_LF_plus_LF (const cl_LF& x, const cl_LF& y); + +// Liefert zu zwei gleichlangen Long-Float x und y : (- x y), ein LF. +// LF_LF_minus_LF(x) +extern const cl_LF LF_LF_minus_LF (const cl_LF& x, const cl_LF& y); + +// Use this macro if ALL of your cl_LF operations (+, -, *, /) in the +// rest of your file ALWAYS get two operands of the same precision. +#define ALL_cl_LF_OPERATIONS_SAME_PRECISION() \ + \ +inline const cl_LF operator+ (const cl_LF& x, const cl_LF& y) \ +{ \ + return LF_LF_plus_LF(x,y); \ +} \ + \ +inline const cl_LF operator- (const cl_LF& x, const cl_LF& y) \ +{ \ + return LF_LF_minus_LF(x,y); \ +} + +// LF_to_I(x) wandelt ein Long-Float x, das eine ganze Zahl darstellt, +// in ein Integer um. +extern const cl_I cl_LF_to_I (const cl_LF& x); + +// cl_I_to_LF(x,len) wandelt ein Integer x in ein Long-Float um und rundet dabei. +extern const cl_LF cl_I_to_LF (const cl_I& x, uintC len); + +// cl_RA_to_LF(x,len) wandelt eine rationale Zahl x in ein Long-Float um +// und rundet dabei. +extern const cl_LF cl_RA_to_LF (const cl_RA& x, uintC len); + +// cl_LF_I_mul(x,y) multipliziert ein Long-Float x und ein Integer y. +extern const cl_R cl_LF_I_mul (const cl_LF& x, const cl_I& y); + +// cl_LF_I_div(x,y) dividiert ein Long-Float x durch ein Integer y. +extern const cl_LF cl_LF_I_div (const cl_LF& x, const cl_I& y); + +// cl_I_LF_div(x,y) dividiert ein Integer x durch ein Long-Float y. +extern const cl_R cl_I_LF_div (const cl_I& x, const cl_LF& y); + +// cl_LF_RA_mul(x,y) multipliziert ein Long-Float x und eine rationale Zahl y. +extern const cl_R cl_LF_RA_mul (const cl_LF& x, const cl_RA& y); + +// cl_LF_RA_div(x,y) dividiert ein Long-Float x durch eine rationale Zahl y. +extern const cl_LF cl_LF_RA_div (const cl_LF& x, const cl_RA& y); + +// cl_RA_LF_div(x,y) dividiert eine rationale Zahl x durch ein Long-Float y. +extern const cl_R cl_RA_LF_div (const cl_RA& x, const cl_LF& y); + +// Vergrößert eine Long-Float-Länge n, so daß aus d = intDsize*n +// mindestens d+sqrt(d)+2 wird. +extern uintC cl_LF_len_incsqrt (uintC len); + +// Vergrößert eine Long-Float-Länge n, so daß aus d = intDsize*n +// mindestens d+sqrt(d)+2+(LF_exp_len-1) wird. +extern uintC cl_LF_len_incsqrtx (uintC len); + +// cl_LF_shortenrelative(x,y) tries to reduce the size of x, such that one +// wouldn't notice it when adding x to y. y must be /= 0. More precisely, +// this returns a float approximation of x, such that 1 ulp(x) < 1 ulp(y). +extern const cl_LF cl_LF_shortenrelative (const cl_LF& x, const cl_LF& y); + +// cl_LF_shortenwith(x,y) tries to reduce the size of x, such that still +// 1 ulp(x) < y. y must be >0. +extern const cl_LF cl_LF_shortenwith (const cl_LF& x, const cl_LF& y); + +#endif /* _CL_LF_H */ diff --git a/src/float/lfloat/cl_LF_impl.h b/src/float/lfloat/cl_LF_impl.h new file mode 100644 index 0000000..592da5a --- /dev/null +++ b/src/float/lfloat/cl_LF_impl.h @@ -0,0 +1,149 @@ +// cl_LF implementation + +#ifndef _CL_LF_IMPL_H +#define _CL_LF_IMPL_H + +#include "cl_number.h" +#include "cl_LF.h" +#include "cl_malloc.h" +#include "cl_offsetof.h" +#include "cl_DS.h" + +extern cl_class cl_class_lfloat; + +// Builds a long-float, without filling the mantissa. +// allocate_lfloat(len,expo,sign) +// > uintC len: length of mantissa (in digits) +// > uint32 expo: exponent +// > cl_signean sign: sign (0 = +, -1 = -) +// The long-float is only complete when the mantissa has been filled in! +inline cl_heap_lfloat* allocate_lfloat (uintC len, uint32 expo, cl_signean sign) +{ + cl_heap_lfloat* p = (cl_heap_lfloat*) cl_malloc_hook(offsetofa(cl_heap_lfloat,data)+sizeof(uintD)*len); + p->refcount = 1; + p->type = &cl_class_lfloat; + p->len = len; + p->sign = sign; + p->expo = expo; + return p; +} + +// Private constructor. +// ptr should be the result of some allocate_lfloat() call. +inline cl_LF::cl_LF (cl_heap_lfloat* ptr) : cl_F ((cl_private_thing) ptr) {} + +// Both work, but the first definition results in less compiler-generated +// temporaries. +#if 1 + #define Lfloat cl_heap_lfloat* +#else + #define Lfloat cl_LF +#endif + +// Pointers to the mantissa. +#if 1 + inline const uintD* LF_MSDptr (Lfloat lf) + { return (const uintD*) arrayMSDptr(lf->data,lf->len); } + inline const uintD* LF_LSDptr (Lfloat lf) + { return (const uintD*) arrayLSDptr(lf->data,lf->len); } +#endif + inline const uintD* LF_MSDptr (const cl_LF& obj) + { var cl_heap_lfloat* lf = TheLfloat(obj); return (const uintD*) arrayMSDptr(lf->data,lf->len); } + inline const uintD* LF_LSDptr (const cl_LF& obj) + { var cl_heap_lfloat* lf = TheLfloat(obj); return (const uintD*) arrayLSDptr(lf->data,lf->len); } + + +// Entpacken eines Long-Float: +// LF_decode(obj, zero_statement, sign=,exp=,mantMSDptr=,mantlen=,mantLSDptr=); +// zerlegt ein Long-Float obj. +// Ist obj=0.0, wird zero_statement ausgeführt. +// Sonst: cl_signean sign = Vorzeichen (0 = +, -1 = -), +// sintL exp = Exponent (vorzeichenbehaftet), +// UDS mantMSDptr/mantlen/mantLSDptr = Mantisse +// (>= 2^(intDsize*mantlen-1), < 2^(intDsize*mantlen)), +// mit mantlen>=LF_minlen. + #define LF_decode(obj, zero_statement, sign_zuweisung,exp_zuweisung,mantMSDptr_zuweisung,mantlen_zuweisung,mantLSDptr_zuweisung) \ + { var Lfloat _x = TheLfloat(obj); \ + var uintL uexp = _x->expo; \ + if (uexp==0) \ + { mantlen_zuweisung _x->len; zero_statement } /* e=0 -> Zahl 0.0 */\ + else \ + { exp_zuweisung (sintL)(uexp - LF_exp_mid); /* Exponent */ \ + sign_zuweisung _x->sign; /* Vorzeichen */\ + unused (mantMSDptr_zuweisung arrayMSDptr(_x->data, (uintP)(mantlen_zuweisung _x->len))); /* Mantissen-UDS */\ + unused (mantLSDptr_zuweisung arrayLSDptr(_x->data, (uintP)(mantlen_zuweisung _x->len))); \ + } } + +// Einpacken eines Long-Float: +// encode_LF0(len) liefert ein Long-Float 0.0 mit len Digits. +// > uintC len: Anzahl der Digits +// < cl_LF ergebnis: neues Long-Float 0.0 mit len Digits +inline const cl_LF encode_LF0 (uintC len) +{ + var Lfloat erg = allocate_lfloat(len,0,0); // Exponent 0, Vorzeichen + + DS_clear_loop(arrayMSDptr(TheLfloat(erg)->data,len),len,arrayLSDptr(TheLfloat(erg)->data,len)); // Mantisse := 0 + return erg; +} + +// Einpacken eines Long-Float: +// encode_LF1s(sign,len) liefert ein Long-Float +-1.0 mit len Digits. +// > cl_signean sign: Vorzeichen +// > uintC len: Anzahl der Digits +// < cl_LF ergebnis: neues Long-Float +1.0 oder -1.0 mit len Digits +inline const cl_LF encode_LF1s (cl_signean sign, uintC len) +{ + var Lfloat erg = allocate_lfloat(len,LF_exp_mid+1,sign); // Exponent 1 + mspref(arrayMSDptr(TheLfloat(erg)->data,len),0) = bit(intDsize-1); // Mantisse := 2^(intDsize*len-1) + DS_clear_loop(arrayMSDptr(TheLfloat(erg)->data,len) mspop 1,len-1,arrayLSDptr(TheLfloat(erg)->data,len)); + return erg; +} + +// Einpacken eines Long-Float: +// encode_LF1(len) liefert ein Long-Float 1.0 mit len Digits. +// > uintC len: Anzahl der Digits +// < cl_LF ergebnis: neues Long-Float 1.0 mit len Digits +inline const cl_LF encode_LF1 (uintC len) +{ + return encode_LF1s(0,len); +} + +// Einpacken eines Long-Float: +// encode_LFu(sign,uexp,mantMSDptr,mantlen) liefert ein Long-Float +// > cl_signean sign: Vorzeichen +// > uintL exp: Exponent + LF_exp_mid +// > uintD* mantMSDptr: Pointer auf eine NUDS mit gesetztem höchstem Bit +// > uintC mantlen: Anzahl der Digits, >= LF_minlen +// < cl_LF erg: neues Long-Float mit der UDS mantMSDptr/mantlen/.. als Mantisse +// Der Exponent wird nicht auf Überlauf/Unterlauf getestet. +inline const cl_LF encode_LFu (cl_signean sign, uintL uexp, const uintD* mantMSDptr, uintC mantlen) +{ + var Lfloat erg = allocate_lfloat(mantlen,uexp,sign); /* Exponent */ + copy_loop_msp(mantMSDptr,arrayMSDptr(TheLfloat(erg)->data,mantlen),mantlen); /* Mantisse übertragen */ + return erg; +} + +// Einpacken eines Long-Float: +// encode_LF(sign,exp,mantMSDptr,mantlen) liefert ein Long-Float +// > cl_signean sign: Vorzeichen +// > sintL exp: Exponent +// > uintD* mantMSDptr: Pointer auf eine NUDS mit gesetztem höchstem Bit +// > uintC mantlen: Anzahl der Digits, >= LF_minlen +// < cl_LF erg: neues Long-Float mit der UDS mantMSDptr/mantlen/.. als Mantisse +// Der Exponent wird nicht auf Überlauf/Unterlauf getestet. +inline const cl_LF encode_LF (cl_signean sign, sintL exp, const uintD* mantMSDptr, uintC mantlen) +{ + return encode_LFu(sign,LF_exp_mid+(uintL)exp,mantMSDptr,mantlen); +} + +// Einpacken eines Long-Float: +// encode_LF_array(sign,exp,mantarr,mantlen) liefert ein Long-Float +// > cl_signean sign: Vorzeichen +// > sintL exp: Exponent +// > uintD mantarr[]: NUDS mit gesetztem höchstem Bit +// > uintC mantlen: Anzahl der Digits, >= LF_minlen +// < cl_LF erg: neues Long-Float mit der UDS mantarr[] als Mantisse +// Der Exponent wird nicht auf Überlauf/Unterlauf getestet. +#define encode_LF_array(sign,exp,mantarr,mantlen) \ + encode_LF(sign,exp,arrayMSDptr(mantarr,mantlen),mantlen) + +#endif /* _CL_LF_IMPL_H */ diff --git a/src/float/lfloat/division/Makeflags b/src/float/lfloat/division/Makeflags new file mode 100644 index 0000000..8953135 --- /dev/null +++ b/src/float/lfloat/division/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/lfloat/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/float/lfloat/elem diff --git a/src/float/lfloat/division/cl_LF_ceil22.cc b/src/float/lfloat/division/cl_LF_ceil22.cc new file mode 100644 index 0000000..d7b7f28 --- /dev/null +++ b/src/float/lfloat/division/cl_LF_ceil22.cc @@ -0,0 +1,22 @@ +// ceiling2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" + +const cl_LF_div_t ceiling2 (const cl_LF& x, const cl_LF& y) +{ +// Methode: +// (q,r) := ceiling(x/y). Liefere q und x-y*q = y*r. + var cl_LF_div_t q_r = ceiling2(x/y); + var cl_I& q = q_r.quotient; + var cl_LF& r = q_r.remainder; + return cl_LF_div_t(q,y*r); +} diff --git a/src/float/lfloat/division/cl_LF_fceil.cc b/src/float/lfloat/division/cl_LF_fceil.cc new file mode 100644 index 0000000..9ce0f22 --- /dev/null +++ b/src/float/lfloat/division/cl_LF_fceil.cc @@ -0,0 +1,24 @@ +// fceiling(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_LF_minusp.cc" + +const cl_LF fceiling (const cl_LF& x) +{ + if (minusp(x)) + return ftruncate(x); + else + return futruncate(x); +} diff --git a/src/float/lfloat/division/cl_LF_floor22.cc b/src/float/lfloat/division/cl_LF_floor22.cc new file mode 100644 index 0000000..10f77d2 --- /dev/null +++ b/src/float/lfloat/division/cl_LF_floor22.cc @@ -0,0 +1,22 @@ +// floor2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" + +const cl_LF_div_t floor2 (const cl_LF& x, const cl_LF& y) +{ +// Methode: +// (q,r) := floor(x/y). Liefere q und x-y*q = y*r. + var cl_LF_div_t q_r = floor2(x/y); + var cl_I& q = q_r.quotient; + var cl_LF& r = q_r.remainder; + return cl_LF_div_t(q,y*r); +} diff --git a/src/float/lfloat/division/cl_LF_recip.cc b/src/float/lfloat/division/cl_LF_recip.cc new file mode 100644 index 0000000..b0162e4 --- /dev/null +++ b/src/float/lfloat/division/cl_LF_recip.cc @@ -0,0 +1,20 @@ +// recip(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" +#include "cl_LF_impl.h" + +ALL_cl_LF_OPERATIONS_SAME_PRECISION() + +const cl_LF recip (const cl_LF& x) +{ + return encode_LF1(TheLfloat(x)->len) / x; +} diff --git a/src/float/lfloat/division/cl_LF_round22.cc b/src/float/lfloat/division/cl_LF_round22.cc new file mode 100644 index 0000000..8514601 --- /dev/null +++ b/src/float/lfloat/division/cl_LF_round22.cc @@ -0,0 +1,22 @@ +// round2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" + +const cl_LF_div_t round2 (const cl_LF& x, const cl_LF& y) +{ +// Methode: +// (q,r) := round(x/y). Liefere q und x-y*q = y*r. + var cl_LF_div_t q_r = round2(x/y); + var cl_I& q = q_r.quotient; + var cl_LF& r = q_r.remainder; + return cl_LF_div_t(q,y*r); +} diff --git a/src/float/lfloat/division/cl_LF_trunc22.cc b/src/float/lfloat/division/cl_LF_trunc22.cc new file mode 100644 index 0000000..d1e5d4a --- /dev/null +++ b/src/float/lfloat/division/cl_LF_trunc22.cc @@ -0,0 +1,22 @@ +// truncate2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" + +const cl_LF_div_t truncate2 (const cl_LF& x, const cl_LF& y) +{ +// Methode: +// (q,r) := truncate(x/y). Liefere q und x-y*q = y*r. + var cl_LF_div_t q_r = truncate2(x/y); + var cl_I& q = q_r.quotient; + var cl_LF& r = q_r.remainder; + return cl_LF_div_t(q,y*r); +} diff --git a/src/float/lfloat/elem/Makeflags b/src/float/lfloat/elem/Makeflags new file mode 100644 index 0000000..9d837c7 --- /dev/null +++ b/src/float/lfloat/elem/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/lfloat/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/rational -I$(srcdir)/integer diff --git a/src/float/lfloat/elem/cl_I_LF_div.cc b/src/float/lfloat/elem/cl_I_LF_div.cc new file mode 100644 index 0000000..0d72f52 --- /dev/null +++ b/src/float/lfloat/elem/cl_I_LF_div.cc @@ -0,0 +1,33 @@ +// cl_I_LF_div(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_LF_impl.h" +#include "cl_integer.h" +#include "cl_I.h" +#include "cl_DS.h" +#include "cl_F.h" +#include "cl_N.h" + +const cl_R cl_I_LF_div (const cl_I& x, const cl_LF& y) +{ +// Method: +// If x=0, return 0. +// Else convert x to a float and divide. +// (If x is shorter than y, we would gain nothing by dividing the absolute +// value of x by the mantissa of y, since the numerator of the division would +// have to have 2*length(y)+1 words, even if length(x) is much smaller than +// length(y).) + if (eq(x,0)) { return 0; } + var uintC len = TheLfloat(y)->len; + return cl_I_to_LF(x,len) / y; +} +// Bit complexity (N = max(length(x),length(y))): O(M(N)). diff --git a/src/float/lfloat/elem/cl_LF_1minus.cc b/src/float/lfloat/elem/cl_LF_1minus.cc new file mode 100644 index 0000000..c484aa1 --- /dev/null +++ b/src/float/lfloat/elem/cl_LF_1minus.cc @@ -0,0 +1,27 @@ +// LF_LF_minus_LF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF.h" + + +// Implementation. + +#include "cl_LF_impl.h" +#include "cl_DS.h" + +const cl_LF LF_LF_minus_LF (const cl_LF& x1, const cl_LF& x2) +{ +// Methode: +// (- x1 x2) = (+ x1 (- x2)) + if (TheLfloat(x2)->expo == 0) + { return x1; } + else + { var uintC len2 = TheLfloat(x2)->len; + var Lfloat mx2 = allocate_lfloat(len2, TheLfloat(x2)->expo, ~ TheLfloat(x2)->sign); + copy_loop_up(&TheLfloat(x2)->data[0],&TheLfloat(mx2)->data[0],len2); + return LF_LF_plus_LF(x1,mx2); + } +} diff --git a/src/float/lfloat/elem/cl_LF_1plus.cc b/src/float/lfloat/elem/cl_LF_1plus.cc new file mode 100644 index 0000000..877fb2d --- /dev/null +++ b/src/float/lfloat/elem/cl_LF_1plus.cc @@ -0,0 +1,240 @@ +// LF_LF_plus_LF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF.h" + + +// Implementation. + +#include "cl_LF_impl.h" +#include "cl_DS.h" +#include "cl_F.h" +#include "cl_xmacros.h" + +const cl_LF LF_LF_plus_LF (const cl_LF& arg1, const cl_LF& arg2) +{ +// Methode (nach [Knuth, II, Seminumerical Algorithms, Abschnitt 4.2.1., S.200]): +// Falls e1= e2. +// Falls e2=0, also x2=0.0, Ergebnis x1. +// Falls e1 - e2 >= 16n+2, Ergebnis x1. +// Erweitere die Mantissen rechts um 3 Bits (Bit -1 als Schutzbit, Bits -2,-3 +// als Rundungsbits: 00 exakt, 01 1.Hälfte, 10 exakte Mitte, 11 2.Hälfte.) +// Schiebe die Mantisse von x2 um e0-e1 Bits nach rechts. (Dabei die Rundung +// ausführen: Bit -3 ist das logische Oder der Bits -3,-4,-5,...) +// Falls x1,x2 selbes Vorzeichen haben: Addiere dieses zur Mantisse von x1. +// Falls x1,x2 verschiedenes Vorzeichen haben: Subtrahiere dieses von der +// Mantisse von x1. <0 -> (Es war e1=e2) Vertausche die Vorzeichen, negiere. +// =0 -> Ergebnis 0.0 +// Exponent ist e1. +// Normalisiere, fertig. + var cl_LF x1 = arg1; + var cl_LF x2 = arg2; + var uintL uexp1 = TheLfloat(arg1)->expo; + var uintL uexp2 = TheLfloat(arg2)->expo; + if (uexp1 < uexp2) + // x1 und x2 vertauschen + { x1 = arg2; x2 = arg1; swap(uintL, uexp1,uexp2); } + // uexp1 >= uexp2 + if (uexp2==0) { return x1; } // x2=0.0 -> x1 als Ergebnis + var uintC len = TheLfloat(x1)->len; // Länge n von x1 und x2 + var uintL expdiff = uexp1-uexp2; // e1-e2 + if ((expdiff == 0) && (TheLfloat(x1)->sign != TheLfloat(x2)->sign)) + // verschiedene Vorzeichen, aber gleicher Exponent + { // Vorzeichen des Ergebnisses festlegen: + var cl_signean erg = // Mantissen (je len Digits) vergleichen + compare_loop_msp(arrayMSDptr(TheLfloat(x1)->data,len),arrayMSDptr(TheLfloat(x2)->data,len),len); + if (erg==0) // Mantissen gleich + { return encode_LF0(len); } // Ergebnis 0.0 + if (erg<0) // |x1| < |x2| + // x1 und x2 vertauschen, expdiff bleibt =0 + { x1.pointer = arg2.pointer; x2.pointer = arg1.pointer; + swap(uintL, uexp1,uexp2); + } + } + if (expdiff >= intDsize * (uintL)len + 2) // e1-e2 >= 16n+2 ? + { return x1; } // ja -> x1 als Ergebnis + // neues Long-Float allozieren: + var Lfloat y = allocate_lfloat(len,uexp1,TheLfloat(x1)->sign); + var uintL i = floor(expdiff,intDsize); // e1-e2 div 16 (>=0, <=n) + var uintL j = expdiff % intDsize; // e1-e2 mod 16 (>=0, <16) + // Mantisse von x2 muß um intDsize*i+j Bits nach rechts geschoben werden. + var uintC x2_len = len - i; // n-i Digits von x2 gebraucht + // x2_len Digits um j Bits nach rechts schieben und dabei kopieren: + CL_ALLOCA_STACK; + var uintD* x2_MSDptr; + var uintD* x2_LSDptr; + var uintD rounding_bits; + num_stack_alloc(x2_len, x2_MSDptr=,x2_LSDptr=); // x2_len Digits Platz + if (j==0) + { copy_loop_msp(arrayMSDptr(TheLfloat(x2)->data,len),x2_MSDptr,x2_len); rounding_bits = 0; } + else + { rounding_bits = shiftrightcopy_loop_msp(arrayMSDptr(TheLfloat(x2)->data,len),x2_MSDptr,x2_len,j,0); } + // x2_MSDptr/x2_len/x2_LSDptr sind die essentiellen Digits von x2. + // rounding_bits enthält die letzten j herausgeschobenen Bits. + // Aus rounding_bits und den nächsten i Digits die 3 Rundungsbits + // (als Bits intDsize-1..intDsize-3 von rounding_bits) aufbauen: + if (j>=2) + // j>=2 -> Bits -1,-2 sind OK, Bit -3 bestimmen: + { if ((rounding_bits & (bit(intDsize-3)-1)) ==0) + { if (test_loop_msp(arrayMSDptr(TheLfloat(x2)->data,len) mspop x2_len,i)) + { rounding_bits |= bit(intDsize-3); } // Rundungsbit -3 setzen + } + else + { rounding_bits |= bit(intDsize-3); // Rundungsbit -3 setzen + rounding_bits &= bitm(intDsize)-bit(intDsize-3); // andere Bits löschen + } } + else + // j<=3 -> Bits intDsize-4..0 von rounding_bits sind bereits Null. + // nächstes und weitere i-1 Digits heranziehen: + { if (i > 0) // i=0 -> Bits -1,-2,-3 sind OK. + { var uintD* ptr = arrayMSDptr(TheLfloat(x2)->data,len) mspop x2_len; + rounding_bits |= (mspref(ptr,0) >> j); // weitere relevante Bits des nächsten Digit dazu + if ((rounding_bits & (bit(intDsize-3)-1)) ==0) // Alle Bits -3,-4,... =0 ? + { if ( (!((mspref(ptr,0) & (bit(3)-1)) ==0)) // j (<=3) untere Bits von ptr[0] alle =0 ? + || test_loop_msp(ptr mspop 1,i-1) + ) + { rounding_bits |= bit(intDsize-3); } // Rundungsbit -3 setzen + } + else + { rounding_bits |= bit(intDsize-3); // Rundungsbit -3 setzen + rounding_bits &= bitm(intDsize)-bit(intDsize-3); // andere Bits löschen + } } } + // x2 liegt in verschobener Form in der UDS x2_MSDptr/x2_len/x2_LSDptr + // vor, mit Rundungsbits in Bit intDsize-1..intDsize-3 von rounding_bits. + {var uintD* y_mantMSDptr = arrayMSDptr(TheLfloat(y)->data,len); + var uintD* y_mantLSDptr = arrayLSDptr(TheLfloat(y)->data,len); + if (TheLfloat(x1)->sign == TheLfloat(x2)->sign) + // gleiche Vorzeichen -> Mantissen addieren + { // erst rechten Mantissenteil (x2_len Digits) durch Addition: + var uintD carry = + add_loop_lsp(arrayLSDptr(TheLfloat(x1)->data,len),x2_LSDptr, + y_mantLSDptr, x2_len + ); + // dann linken Mantissenteil (i Digits) direkt kopieren: + var uintD* ptr = + copy_loop_msp(arrayMSDptr(TheLfloat(x1)->data,len),y_mantMSDptr,i); + // dann Übertrag vom rechten zum linken Mantissenteil addieren: + if (!(carry==0)) + { if ( inc_loop_lsp(ptr,i) ) + // Übertrag über das erste Digit hinaus + { // Exponent von y incrementieren: + if ( ++(TheLfloat(y)->expo) == LF_exp_high+1 ) { cl_error_floating_point_overflow(); } + // normalisiere durch Schieben um 1 Bit nach rechts: + {var uintD carry_rechts = + shift1right_loop_msp(y_mantMSDptr,len,~(uintD)0); + rounding_bits = rounding_bits>>1; // Rundungsbits mitschieben + if (!(carry_rechts==0)) { rounding_bits |= bit(intDsize-1); } + } }} + } + else + // verschiedene Vorzeichen -> Mantissen subtrahieren + { // erst rechten Mantissenteil (x2_len Digits) durch Subtraktion: + rounding_bits = -rounding_bits; + {var uintD carry = + subx_loop_lsp(arrayLSDptr(TheLfloat(x1)->data,len),x2_LSDptr, + y_mantLSDptr, x2_len, + (rounding_bits==0 ? 0 : ~(uintD)0) + ); + // dann linken Mantissenteil (i Digits) direkt kopieren: + var uintD* ptr = + copy_loop_msp(arrayMSDptr(TheLfloat(x1)->data,len),y_mantMSDptr,i); + // dann Übertrag des rechten vom linken Mantissenteil subtrahieren: + if (!(carry==0)) + { if ( dec_loop_lsp(ptr,i) ) + // Übertrag über das erste Digit hinaus, also e1=e2 + { NOTREACHED } // diesen Fall haben wir schon behandelt + } + } + // UDS y_mantMSDptr/len/y_mantLSDptr/rounding_bits normalisieren: + {var uintD* ptr = y_mantMSDptr; + var uintL k = 0; + var uintC count; + dotimesC(count,len, + { if (!(mspref(ptr,0)==0)) goto nonzero_found; + ptr = ptr mspop 1; k++; + }); + if (!(rounding_bits==0)) goto nonzero_found; + // Die UDS ist ganz Null. Also war e1=e2, keine Rundungsbits. + { NOTREACHED } // diesen Fall haben wir schon behandelt + nonzero_found: // Digit /=0 gefunden + // UDS von ptr nach y_mantMSDptr um k Digits nach unten kopieren: + if (k>0) + // mindestens ein führendes Nulldigit. Also war e1-e2 = 0 oder 1. + { ptr = copy_loop_msp(ptr,y_mantMSDptr,len-k); // len-k Digits verschieben + msprefnext(ptr) = rounding_bits; // Rundungsbits als weiteres Digit + clear_loop_msp(ptr,k-1); // dann k-1 Nulldigits + rounding_bits = 0; // und keine weiteren Rundungsbits + // Exponenten um intDsize*k erniedrigen: + k = intDsize*k; + {var uintL uexp = TheLfloat(y)->expo; + #if !(LF_exp_low==1) + if (uexp < k+LF_exp_low) + #else + if (uexp <= k) + #endif + { if (underflow_allowed()) + { cl_error_floating_point_underflow(); } + else + { return encode_LF0(len); } // Ergebnis 0.0 + } + TheLfloat(y)->expo = uexp - k; + }} + } + // NUDS y_mantMSDptr/len/y_mantLSDptr/rounding_bits normalisieren: + {var uintL s; + integerlengthD(mspref(y_mantMSDptr,0), s = intDsize - ); + // s = Anzahl der führenden Nullbits im ersten Word (>=0, 0) + { // Muß die NUDS y_mantMSDptr/len/y_mantLSDptr/rounding_bits + // um s Bits nach links schieben. + // (Bei e1-e2>1 ist dabei zwangsläufig s=1.) + if (s==1) + { shift1left_loop_lsp(y_mantLSDptr,len); + if (rounding_bits & bit(intDsize-1)) + { lspref(y_mantLSDptr,0) |= bit(0); } + rounding_bits = rounding_bits << 1; + } + else // s>1, also e1-e2 <= 1 <= s. + { shiftleft_loop_lsp(y_mantLSDptr,len,s,rounding_bits>>(intDsize-s)); + rounding_bits = 0; // = rounding_bits << s; + } + // Exponenten um s erniedrigen: + {var uintL uexp = TheLfloat(y)->expo; + #if !(LF_exp_low==1) + if (uexp < s+LF_exp_low) + #else + if (uexp <= s) + #endif + { if (underflow_allowed()) + { cl_error_floating_point_underflow(); } + else + { return encode_LF0(len); } // Ergebnis 0.0 + } + TheLfloat(y)->expo = uexp - s; + }} + } } + // Hier enthält rounding_bits Bit -1 als Bit intDsize-1, Bit -2 als + // Bit intDsize-2, Bit -3 als Oder(Bits intDsize-3..0) ! + // Runden. Dazu rounding_bits inspizieren: + if ((rounding_bits & bit(intDsize-1)) ==0) goto ab; // Bit -1 gelöscht -> abrunden + rounding_bits = rounding_bits<<1; // Bits -2,-3 + if (!(rounding_bits==0)) goto auf; // Bit -2 oder Bit -3 gesetzt -> aufrunden + // round-to-even: + if ((lspref(y_mantLSDptr,0) & bit(0)) ==0) goto ab; + auf: // aufrunden + if ( inc_loop_lsp(y_mantLSDptr,len) ) + { // Übertrag durchs Aufrunden + mspref(y_mantMSDptr,0) = bit(intDsize-1); // Mantisse := 10...0 + // Exponent erhöhen: + if (++(TheLfloat(y)->expo) == LF_exp_high+1) { cl_error_floating_point_overflow(); } + } + ab: // abrunden + ; + } + // y fertig. + return y; +} diff --git a/src/float/lfloat/elem/cl_LF_2minus.cc b/src/float/lfloat/elem/cl_LF_2minus.cc new file mode 100644 index 0000000..71c4408 --- /dev/null +++ b/src/float/lfloat/elem/cl_LF_2minus.cc @@ -0,0 +1,15 @@ +// binary operator - + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" + +const cl_LF operator- (const cl_LF& x1, const cl_LF& x2) +{ GEN_LF_OP2(x1,x2,LF_LF_minus_LF,return) } diff --git a/src/float/lfloat/elem/cl_LF_2plus.cc b/src/float/lfloat/elem/cl_LF_2plus.cc new file mode 100644 index 0000000..8bfd6a1 --- /dev/null +++ b/src/float/lfloat/elem/cl_LF_2plus.cc @@ -0,0 +1,15 @@ +// binary operator + + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" + +const cl_LF operator+ (const cl_LF& x1, const cl_LF& x2) +{ GEN_LF_OP2(x1,x2,LF_LF_plus_LF,return) } diff --git a/src/float/lfloat/elem/cl_LF_I_div.cc b/src/float/lfloat/elem/cl_LF_I_div.cc new file mode 100644 index 0000000..8a61f4b --- /dev/null +++ b/src/float/lfloat/elem/cl_LF_I_div.cc @@ -0,0 +1,113 @@ +// cl_LF_I_div(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_LF_impl.h" +#include "cl_integer.h" +#include "cl_I.h" +#include "cl_DS.h" +#include "cl_F.h" +#include "cl_N.h" + +const cl_LF cl_LF_I_div (const cl_LF& x, const cl_I& y) +{ +// Method: +// If x = 0.0, return x. +// If y is longer than x, convert y to a float and divide. +// Else divide the mantissa of x by the absolute value of y, then round. + if (TheLfloat(x)->expo == 0) { + if (zerop(y)) + cl_error_division_by_0(); + else + return x; + } + var cl_signean sign = -(cl_signean)minusp(y); // Vorzeichen von y + var cl_I abs_y = (sign==0 ? y : -y); + var uintL y_exp = integer_length(abs_y); + var uintC len = TheLfloat(x)->len; +#ifndef CL_LF_PEDANTIC + if (ceiling(y_exp,intDsize) > len) + return x / cl_I_to_LF(y,len); +#endif + // x länger als y, direkt dividieren. + CL_ALLOCA_STACK; + var const uintD* y_MSDptr; + var uintC y_len; + var const uintD* y_LSDptr; + I_to_NDS_nocopy(abs_y, y_MSDptr=,y_len=,y_LSDptr=,cl_false,); // NDS zu y bilden, y_len>0 + // y nicht zu einer NUDS normalisieren! (Damit ein Bit Spielraum ist.) + // Zähler bilden: x * 2^(intDsize*y_len) + var uintD* z_MSDptr; + var uintL z_len; + var uintD* z_LSDptr; + z_len = (uintL)len + (uintL)y_len; + num_stack_alloc(z_len, z_MSDptr=,z_LSDptr=); + { var uintD* ptr = copy_loop_msp(arrayMSDptr(TheLfloat(x)->data,len),z_MSDptr,len); // len Digits + clear_loop_msp(ptr,y_len); // und y_len Null-Digits + } + // Quotienten bilden: + var DS q; + var DS r; + UDS_divide(z_MSDptr,z_len,z_LSDptr, + y_MSDptr,y_len,y_LSDptr, + &q, &r + ); + // q ist der Quotient, + // q = floor(x/y*2^(intDsize*y_len)) >= 2^(intDsize*len), + // q <= x/y*2^(intDsize*y_len) < 2^(1+intDsize+intDsize*len), + // also mit len+1 oder len+2 Digits. r der Rest. + var uintD* MSDptr = q.MSDptr; + var uintL shiftcount; + integerlengthD(mspref(MSDptr,0),shiftcount=); + // Bei q.len = len+2 : shiftcount=1, + // bei q.len = len+1 : 1<=shiftcount<=intDsize. + var uintD carry_rechts; + if (shiftcount==intDsize) { + carry_rechts = mspref(MSDptr,len); + } else { + carry_rechts = shiftright_loop_msp(MSDptr,len+1,shiftcount%intDsize); + if (q.len > len+1) { + shiftcount += intDsize; + carry_rechts |= (mspref(MSDptr,len+1)==0 ? 0 : 1); + } + msshrink(MSDptr); + } + // Quotient MSDptr/len/.. ist nun normalisiert: höchstes Bit =1. + // exponent := exponent(x) - intDsize*y_len + shiftcount + var uintL uexp = TheLfloat(x)->expo; + var uintL dexp = intDsize*y_len - shiftcount; // >= 0 ! + if ((uexp < dexp) || ((uexp = uexp - dexp) < LF_exp_low)) { + if (underflow_allowed()) + { cl_error_floating_point_underflow(); } + else + { return encode_LF0(len); } + } + // Runden: + if ( ((sintD)carry_rechts >= 0) // herausgeschobenes Bit =0 -> abrunden + || ( (carry_rechts == (uintD)bit(intDsize-1)) // =1 und weitere Bits >0 oder Rest >0 -> aufrunden + && (r.len==0) + // round-to-even + && ((mspref(MSDptr,len-1) & bit(0)) ==0) + ) ) + // abrunden + {} + else + // aufrunden + { if ( inc_loop_lsp(MSDptr mspop len,len) ) + // Übertrag durchs Aufrunden + { mspref(MSDptr,0) = bit(intDsize-1); // Mantisse := 10...0 + // Exponenten incrementieren: + if (++uexp == LF_exp_high+1) { cl_error_floating_point_overflow(); } + } } + return encode_LFu(TheLfloat(x)->sign ^ sign, uexp, MSDptr, len); +} +// Bit complexity (N := max(length(x),length(y))): O(M(N)). + diff --git a/src/float/lfloat/elem/cl_LF_I_mul.cc b/src/float/lfloat/elem/cl_LF_I_mul.cc new file mode 100644 index 0000000..5d9dbab --- /dev/null +++ b/src/float/lfloat/elem/cl_LF_I_mul.cc @@ -0,0 +1,88 @@ +// cl_LF_I_mul(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF.h" + + +// Implementation. + +#include "cl_LF_impl.h" +#include "cl_integer.h" +#include "cl_I.h" +#include "cl_DS.h" +#include "cl_F.h" + +const cl_R cl_LF_I_mul (const cl_LF& x, const cl_I& y) +{ +// Method: +// If y=0, return 0. +// If x=0.0, return x. +// If y is longer than x, convert y to a float and multiply. +// Else multiply the mantissa of x with the absolute value of y, then round. + if (eq(y,0)) { return 0; } + if (TheLfloat(x)->expo == 0) { return x; } + var cl_signean sign = -(cl_signean)minusp(y); // Vorzeichen von y + var cl_I abs_y = (sign==0 ? y : -y); + var uintL y_exp = integer_length(abs_y); + var uintC len = TheLfloat(x)->len; +#ifndef CL_LF_PEDANTIC + if (ceiling(y_exp,intDsize) > len) + return x * cl_I_to_LF(y,len); +#endif + // x länger als y, direkt multiplizieren. + CL_ALLOCA_STACK; + var const uintD* y_MSDptr; + var uintC y_len; + var const uintD* y_LSDptr; + I_to_NDS_nocopy(abs_y, y_MSDptr=,y_len=,y_LSDptr=,cl_false,); // NDS zu y bilden, y_len>0 + if (mspref(y_MSDptr,0)==0) y_len--; // NUDS zu y bilden, y_len>0 + // Multiplizieren. + var uintD* prodMSDptr; + var uintC prodlen; + UDS_UDS_mul_UDS(len,arrayLSDptr(TheLfloat(x)->data,len), + y_len,y_LSDptr, + prodMSDptr=,prodlen=,); + // x fing mit 0 Nullbits an, y mit maximal intDsize-1 Nullbits, + // daher fängt das Produkt mit maximal intDsize Nullbits an. + var uintL shiftcount; + if (mspref(prodMSDptr,0)==0) { + shiftcount = intDsize; + msshrink(prodMSDptr); prodlen--; + } else { + integerlengthD(mspref(prodMSDptr,0), shiftcount = intDsize -); + if (shiftcount > 0) + shiftleft_loop_lsp(prodMSDptr mspop (len+1),len+1,shiftcount,0); + } + // Produkt ist nun normalisiert: höchstes Bit =1. + // exponent := exponent(x) + intDsize*y_len - shiftcount + var uintL uexp = TheLfloat(x)->expo; + var uintL iexp = intDsize*y_len - shiftcount; // >= 0 ! + uexp = uexp + iexp; + if ((uexp < iexp) || (uexp > LF_exp_high)) + cl_error_floating_point_overflow(); + // Runden: + var uintD* midptr = prodMSDptr mspop len; + var uintC restlen = prodlen - len; + if ( (restlen==0) + || ((sintD)mspref(midptr,0) >= 0) // nächstes Bit =0 -> abrunden + || ( ((mspref(midptr,0) & ((uintD)bit(intDsize-1)-1)) ==0) // Bit =1, weitere Bits >0 -> aufrunden + && !test_loop_msp(midptr mspop 1,restlen-1) + // round-to-even + && ((lspref(midptr,0) & bit(0)) ==0) + ) ) + // abrunden + {} + else + // aufrunden + { if ( inc_loop_lsp(midptr,len) ) + // Übertrag durchs Aufrunden + { mspref(prodMSDptr,0) = bit(intDsize-1); // Mantisse := 10...0 + if (++uexp == LF_exp_high+1) { cl_error_floating_point_overflow(); } + } } + return encode_LFu(TheLfloat(x)->sign ^ sign, uexp, prodMSDptr, len); +} +// Bit complexity (N = max(length(x),length(y))): O(M(N)). + diff --git a/src/float/lfloat/elem/cl_LF_RA_div.cc b/src/float/lfloat/elem/cl_LF_RA_div.cc new file mode 100644 index 0000000..0a51629 --- /dev/null +++ b/src/float/lfloat/elem/cl_LF_RA_div.cc @@ -0,0 +1,29 @@ +// cl_LF_RA_div(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_rational.h" +#include "cl_RA.h" + +const cl_LF cl_LF_RA_div (const cl_LF& x, const cl_RA& y) +{ +// Method: +// Write y = u/v. Return (x*v)/u. + if (integerp(y)) { + DeclareType(cl_I,y); + return cl_LF_I_div(x,y); + } else { + DeclareType(cl_RT,y); + var const cl_I& u = TheRatio(y)->numerator; // u /= 0 + var const cl_I& v = TheRatio(y)->denominator; // v /= 0 + return cl_LF_I_div(The(cl_LF)(cl_LF_I_mul(x,v)),u); + } +} diff --git a/src/float/lfloat/elem/cl_LF_RA_mul.cc b/src/float/lfloat/elem/cl_LF_RA_mul.cc new file mode 100644 index 0000000..db3299e --- /dev/null +++ b/src/float/lfloat/elem/cl_LF_RA_mul.cc @@ -0,0 +1,49 @@ +// cl_LF_RA_mul(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_RA.h" + +const cl_R cl_LF_RA_mul (const cl_LF& x, const cl_RA& y) +{ +// Method: +// Write y = u/v. Return (x*u)/v. + if (integerp(y)) { + DeclareType(cl_I,y); + return cl_LF_I_mul(x,y); + } else { + DeclareType(cl_RT,y); + var const cl_I& u = TheRatio(y)->numerator; // u /= 0 + var const cl_I& v = TheRatio(y)->denominator; // v /= 0 + return cl_LF_I_div(The(cl_LF)(cl_LF_I_mul(x,u)),v); + } +} + +// Timings on an i486 33 MHz, running Linux, in 0.01 sec. +// First timing: (x*u)/v, using cl_LF_I_mul and cl_LF_I_div +// Second timing: x*(u/v), using cl_RA_to_LF and operator* +// with x_length = 100. +// num_length 50 70 100 200 500 +// den_length +// +// 50 1.59 1.92 1.76 1.92 1.89 1.92 1.90 2.78 1.93 8.07 +// +// 70 1.93 2.26 2.14 2.25 2.25 2.25 2.27 2.78 2.25 8.07 +// +// 100 2.44 2.77 2.65 2.77 2.79 2.80 2.80 2.81 2.80 8.05 +// +// 200 2.46 4.53 2.65 4.54 2.78 4.55 2.79 4.55 2.77 8.05 +// +// 500 2.45 8.38 2.65 8.50 2.76 8.49 2.79 8.52 2.81 8.55 +// +// We see that the first approach is always better than the second, except if +// den_length = x_length && x_length <= num_length <= 2*x_length +// when both are equally fast. diff --git a/src/float/lfloat/elem/cl_LF_compare.cc b/src/float/lfloat/elem/cl_LF_compare.cc new file mode 100644 index 0000000..1a2e97c --- /dev/null +++ b/src/float/lfloat/elem/cl_LF_compare.cc @@ -0,0 +1,103 @@ +// cl_compare(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" +#include "cl_DS.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_LF_minusp.cc" + +cl_signean cl_compare (const cl_LF& x, const cl_LF& y) +{ +// Methode: +// x und y haben verschiedenes Vorzeichen -> +// x < 0 -> x < y +// x >= 0 -> x > y +// x und y haben gleiches Vorzeichen -> +// x >=0 -> vergleiche x und y (die rechten 24 Bits) +// x <0 -> vergleiche y und x (die rechten 24 Bits) + if (!minusp(y)) + // y>=0 + { if (!minusp(x)) + // y>=0, x>=0 + { // Vergleiche Exponenten und Mantissen: + { var uintL x_uexp = TheLfloat(x)->expo; + var uintL y_uexp = TheLfloat(y)->expo; + if (x_uexp < y_uexp) return signean_minus; // x y_uexp) return signean_plus; // x>y + } + { var uintC x_len = TheLfloat(x)->len; + var uintC y_len = TheLfloat(y)->len; + var uintC len = (x_lendata,x_len),arrayMSDptr(TheLfloat(y)->data,y_len),len); + if (!(erg==0)) { return erg; } // verschieden -> fertig + // gemeinsames Teilstück war gleich + if (x_len == y_len) { return signean_null; } // gleiche Länge -> fertig + if (x_len > y_len) + // x länger als y + { if (DS_test_loop(arrayMSDptr(TheLfloat(x)->data,x_len) mspop y_len,x_len-y_len,arrayLSDptr(TheLfloat(x)->data,x_len))) + { return signean_plus; } // x>y + else + { return signean_null; } + } + else + // y länger als x + { if (DS_test_loop(arrayMSDptr(TheLfloat(y)->data,y_len) mspop x_len,y_len-x_len,arrayLSDptr(TheLfloat(y)->data,y_len))) + { return signean_minus; } // x=0, x<0 + { return signean_minus; } // x=0 + { return signean_plus; } // x>y + else + // y<0, x<0 + { // Vergleiche Exponenten und Mantissen: + { var uintL x_uexp = TheLfloat(x)->expo; + var uintL y_uexp = TheLfloat(y)->expo; + if (x_uexp < y_uexp) return signean_plus; // |x|<|y| -> x>y + if (x_uexp > y_uexp) return signean_minus; // |x|>|y| -> xlen; + var uintC y_len = TheLfloat(y)->len; + var uintC len = (x_lendata,y_len),arrayMSDptr(TheLfloat(x)->data,x_len),len); + if (!(erg==0)) { return erg; } // verschieden -> fertig + // gemeinsames Teilstück war gleich + if (x_len == y_len) { return signean_null; } // gleiche Länge -> fertig + if (x_len > y_len) + // x länger als y + { if (DS_test_loop(arrayMSDptr(TheLfloat(x)->data,x_len) mspop y_len,x_len-y_len,arrayLSDptr(TheLfloat(x)->data,x_len))) + { return signean_minus; } // |x|>|y| -> xdata,y_len) mspop x_len,y_len-x_len,arrayLSDptr(TheLfloat(y)->data,y_len))) + { return signean_plus; } // |x|<|y| -> x>y + else + { return signean_null; } + } + } } + } +} diff --git a/src/float/lfloat/elem/cl_LF_div.cc b/src/float/lfloat/elem/cl_LF_div.cc new file mode 100644 index 0000000..8958023 --- /dev/null +++ b/src/float/lfloat/elem/cl_LF_div.cc @@ -0,0 +1,167 @@ +// binary operator / + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" +#include "cl_LF_impl.h" +#include "cl_DS.h" +#include "cl_F.h" +#include "cl_N.h" + +// Workaround gcc-2.7.0 bug on i386. +#if defined(__GNUC__) + #if (__GNUC__ == 2) + #if (__GNUC_MINOR__ == 7) + #define workaround_gcc_bug() *&uexp1 = *&uexp1; + #endif + #endif +#endif +#ifndef workaround_gcc_bug + #define workaround_gcc_bug() +#endif + +const cl_LF operator/ (const cl_LF& x1, const cl_LF& x2) +{ +// Methode: +// x2 = 0.0 -> Error +// x1 = 0.0 -> Ergebnis 0.0 +// Sonst: +// Ergebnis-Vorzeichen = xor der beiden Vorzeichen von x1 und x2 +// Ergebnis-Exponent = Differenz der beiden Exponenten von x1 und x2 +// Ergebnis-Mantisse = Mantisse mant1 / Mantisse mant2, gerundet. +// mant1/mant2 > 1/2, mant1/mant2 < 2; +// nach Rundung mant1/mant2 >=1/2, <=2*mant1<2. +// Bei mant1/mant2 >=1 brauche 16n-1 Nachkommabits, +// bei mant1/mant2 <1 brauche 16n Nachkommabits. +// Fürs Runden: brauche ein Rundungsbit (Rest gibt an, ob exakt). +// Brauche daher insgesamt 16n+1 Nachkommabits von mant1/mant2. +// Dividiere daher (als Unsigned Integers) +// 2^16(n+1)*(2^16n*m0) durch (2^16n*m1). +// Falls der Quotient >=2^16(n+1) ist, schiebe ihn um 1 Bit nach rechts, +// erhöhe den Exponenten um 1 und runde das letzte Digit weg. +// Falls der Quotient <2^16(n+1) ist, runde das letzte Digit weg. Bei rounding +// overflow schiebe um 1 Bit nach rechts und erhöhe den Exponenten um 1. + var uintC len1 = TheLfloat(x1)->len; + var uintC len2 = TheLfloat(x2)->len; + var uintC len = (len1 < len2 ? len1 : len2); // min. Länge n von x1 und x2 + var uintL uexp2 = TheLfloat(x2)->expo; + if (uexp2==0) { cl_error_division_by_0(); } // x2=0.0 -> Error + var uintL uexp1 = TheLfloat(x1)->expo; + if (uexp1==0) // x1=0.0 -> Ergebnis 0.0 + { if (len < len1) return shorten(x1,len); else return x1; } + // Exponenten subtrahieren: + // (uexp1-LF_exp_mid) - (uexp2-LF_exp_mid) = (uexp1-uexp2+LF_exp_mid)-LF_exp_mid + if (uexp1 >= uexp2) + { uexp1 = uexp1 - uexp2; // kein Carry + workaround_gcc_bug(); + if (uexp1 > LF_exp_high-LF_exp_mid) { cl_error_floating_point_overflow(); } + uexp1 = uexp1 + LF_exp_mid; + } + else + { uexp1 = uexp1 - uexp2; // Carry + workaround_gcc_bug(); + if (uexp1 < (uintL)(LF_exp_low-1-LF_exp_mid)) + { if (underflow_allowed()) + { cl_error_floating_point_underflow(); } + else + { return encode_LF0(len); } // Ergebnis 0.0 + } + uexp1 = uexp1 + LF_exp_mid; + } + // Nun ist LF_exp_low-1 <= uexp1 <= LF_exp_high. + // neues Long-Float allozieren: + var Lfloat y = allocate_lfloat(len,uexp1, + TheLfloat(x1)->sign ^ TheLfloat(x2)->sign // Vorzeichen kombinieren + ); + // Nenner bilden: + var uintL n_len; + n_len = len2; +#ifndef CL_LF_PEDANTIC + if (n_len > len) { n_len = len+1; } +#endif + // Zähler bilden: + CL_ALLOCA_STACK; + var uintD* z_MSDptr; + var uintL z_len; + var uintD* z_LSDptr; + z_len = n_len + len + 1; + num_stack_alloc(z_len, z_MSDptr=,z_LSDptr=); + if (z_len > len1) + { var uintD* ptr = + copy_loop_msp(arrayMSDptr(TheLfloat(x1)->data,len1),z_MSDptr,len1); // n Digits kopieren + clear_loop_msp(ptr,z_len-len1); // und n+1 Null-Digits + } + else + { copy_loop_msp(arrayMSDptr(TheLfloat(x1)->data,len1),z_MSDptr,z_len); } + // Quotienten bilden: 2n+1-Digit-Zahl durch n-Digit-Zahl dividieren + {var DS q; + var DS r; + {var uintD* x2_mantMSDptr = arrayMSDptr(TheLfloat(x2)->data,len2); + UDS_divide(z_MSDptr,z_len,z_LSDptr, + x2_mantMSDptr,n_len,x2_mantMSDptr mspop n_len, + &q, &r + ); + } + // q ist der Quotient mit n+1 oder n+2 Digits, r der Rest. + if (q.len > len+1) + // Quotient hat n+2 Digits -> um 1 Bit nach rechts schieben: + { var uintD* y_mantMSDptr = arrayMSDptr(TheLfloat(y)->data,len); + var uintD carry_rechts = + shiftrightcopy_loop_msp(q.MSDptr mspop 1,y_mantMSDptr,len,1, + /* carry links = mspref(q.MSDptr,0) = 1 */ 1 ); + // Exponenten incrementieren: + if (++(TheLfloat(y)->expo) == LF_exp_high+1) { cl_error_floating_point_overflow(); } + // Runden: + if ( (carry_rechts == 0) // herausgeschobenes Bit =0 -> abrunden + || ( (lspref(q.LSDptr,0)==0) // =1 und weitere Bits >0 oder Rest >0 -> aufrunden + && (r.len==0) + // round-to-even + && ((lspref(q.LSDptr,1) & bit(1)) ==0) + ) ) + // abrunden + {} + else + // aufrunden + { inc_loop_lsp(y_mantMSDptr mspop len,len); } + } + else + // Quotient hat n+1 Digits -> nur kopieren: + { var uintD* y_mantMSDptr = arrayMSDptr(TheLfloat(y)->data,len); + copy_loop_msp(q.MSDptr,y_mantMSDptr,len); + // Runden: + if ( ((sintD)lspref(q.LSDptr,0) >= 0) // nächstes Bit =0 -> abrunden + || ( ((lspref(q.LSDptr,0) & ((uintD)bit(intDsize-1)-1)) ==0) // =1 und weitere Bits >0 oder Rest >0 -> aufrunden + && (r.len==0) + // round-to-even + && ((lspref(q.LSDptr,1) & bit(0)) ==0) + ) ) + // abrunden + {} + else + // aufrunden + { if ( inc_loop_lsp(y_mantMSDptr mspop len,len) ) + // Übertrag durchs Aufrunden + { mspref(y_mantMSDptr,0) = bit(intDsize-1); // Mantisse := 10...0 + // Exponenten incrementieren: + if (++(TheLfloat(y)->expo) == LF_exp_high+1) { cl_error_floating_point_overflow(); } + } } + } + } + // LF_exp_low <= exp <= LF_exp_high sicherstellen: + if (TheLfloat(y)->expo == LF_exp_low-1) + { if (underflow_allowed()) + { cl_error_floating_point_underflow(); } + else + { return encode_LF0(len); } // Ergebnis 0.0 + } + return y; +} +// Bit complexity (N := max(length(x1),length(x2))): O(M(N)). + diff --git a/src/float/lfloat/elem/cl_LF_ffloor.cc b/src/float/lfloat/elem/cl_LF_ffloor.cc new file mode 100644 index 0000000..7a1d57c --- /dev/null +++ b/src/float/lfloat/elem/cl_LF_ffloor.cc @@ -0,0 +1,24 @@ +// ffloor(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_LF_minusp.cc" + +const cl_LF ffloor (const cl_LF& x) +{ + if (minusp(x)) + return futruncate(x); + else + return ftruncate(x); +} diff --git a/src/float/lfloat/elem/cl_LF_from_I.cc b/src/float/lfloat/elem/cl_LF_from_I.cc new file mode 100644 index 0000000..378c9fc --- /dev/null +++ b/src/float/lfloat/elem/cl_LF_from_I.cc @@ -0,0 +1,116 @@ +// cl_I_to_LF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF.h" + + +// Implementation. + +#include "cl_LF_impl.h" +#include "cl_integer.h" +#include "cl_I.h" +#include "cl_DS.h" +#include "cl_F.h" + +const cl_LF cl_I_to_LF (const cl_I& x, uintC len) +{ +// Methode: +// x=0 -> Ergebnis 0.0 +// Merke Vorzeichen von x. +// x:=(abs x) +// Exponent:=(integer-length x) +// Mantisse enthalte die höchstwertigen 16n Bits des Integers x (wobei die +// führenden 16-(e mod 16) Nullbits zu streichen sind). +// Runde die weiteren Bits weg: +// Kommen keine mehr -> abrunden, +// nächstes Bit = 0 -> abrunden, +// nächstes Bit = 1 und Rest =0 -> round-to-even, +// nächstes Bit = 1 und Rest >0 -> aufrunden. +// Bei Aufrundung: rounding overflow -> Mantisse um 1 Bit nach rechts schieben +// und Exponent incrementieren. + if (eq(x,0)) { return encode_LF0(len); } // x=0 -> Ergebnis 0.0 + var cl_signean sign = -(cl_signean)minusp(x); // Vorzeichen von x + var cl_I abs_x = (sign==0 ? x : -x); + var uintL exp = integer_length(abs_x); // (integer-length x) < intDsize*2^intCsize + // Teste, ob exp <= LF_exp_high-LF_exp_mid : + if ( (log2_intDsize+intCsize < 32) + && ((uintL)(intDsize*bitc(intCsize)-1) <= (uintL)(LF_exp_high-LF_exp_mid)) + ) + {} // garantiert exp <= intDsize*2^intCsize-1 <= LF_exp_high-LF_exp_mid + else + { if (!(exp <= (uintL)(LF_exp_high-LF_exp_mid))) { cl_error_floating_point_overflow(); } } + // Long-Float bauen: + var Lfloat y = allocate_lfloat(len,exp+LF_exp_mid,sign); + var uintD* y_mantMSDptr = arrayMSDptr(TheLfloat(y)->data,len); + var const uintD* x_MSDptr; + var uintC x_len; + I_to_NDS_nocopy(abs_x, x_MSDptr=,x_len=,,cl_false,); // NDS zu x bilden, x_len>0 + // x_MSDptr/x_len/.. um (exp mod 16) Bits nach rechts shiften und in + // y einfüllen (genauer: nur maximal len Digits davon): + {var uintL shiftcount = exp % intDsize; + // Die NDS fängt mit intDsize-shiftcount Nullbits an, dann kommt eine 1. + if (x_len > len) + { x_len -= 1+len; + if (shiftcount>0) + { var uintD carry_rechts = + shiftrightcopy_loop_msp(x_MSDptr mspop 1,y_mantMSDptr,len,shiftcount,mspref(x_MSDptr,0)); + // Mantisse ist gefüllt. Runden: + if ( ((sintD)carry_rechts >= 0) // nächstes Bit =0 -> abrunden + || ( ((carry_rechts & ((uintD)bit(intDsize-1)-1)) ==0) // =1, Rest >0 -> aufrunden + && !test_loop_msp(x_MSDptr mspop 1 mspop len,x_len) + // round-to-even + && ((mspref(y_mantMSDptr,len-1) & bit(0)) ==0) + ) ) + goto ab; // aufrunden + else + goto auf; // aufrunden + } + else + { copy_loop_msp(x_MSDptr mspop 1,y_mantMSDptr,len); + // Mantisse ist gefüllt. Runden: + var const uintD* ptr = x_MSDptr mspop 1 mspop len; + if ( (x_len==0) // keine Bits mehr -> abrunden + || ((sintD)mspref(ptr,0) >= 0) // nächstes Bit =0 -> abrunden + || ( ((mspref(ptr,0) & ((uintD)bit(intDsize-1)-1)) ==0) // =1, Rest >0 -> aufrunden + && !test_loop_msp(ptr mspop 1,x_len-1) + // round-to-even + && ((lspref(ptr,0) & bit(0)) ==0) + ) ) + goto ab; // aufrunden + else + goto auf; // aufrunden + } + auf: // aufrunden + if ( inc_loop_lsp(y_mantMSDptr mspop len,len) ) + // Übertrag durchs Aufrunden + { mspref(y_mantMSDptr,0) = bit(intDsize-1); // Mantisse := 10...0 + // Exponenten incrementieren: + if ( (log2_intDsize+intCsize < 32) + && ((uintL)(intDsize*bitc(intCsize)-1) < (uintL)(LF_exp_high-LF_exp_mid)) + ) + // garantiert exp < intDsize*2^intCsize-1 <= LF_exp_high-LF_exp_mid + { (TheLfloat(y)->expo)++; } // jetzt exp <= LF_exp_high-LF_exp_mid + else + { if (++(TheLfloat(y)->expo) == LF_exp_high+1) { cl_error_floating_point_overflow(); } } + } + ab: // abrunden + ; + } + else // x_len <= len + { var uintD carry_rechts; + len -= x_len; + x_len -= 1; + if (shiftcount>0) + { carry_rechts = shiftrightcopy_loop_msp(x_MSDptr mspop 1,y_mantMSDptr,x_len,shiftcount,mspref(x_MSDptr,0)); } + else + { copy_loop_msp(x_MSDptr mspop 1,y_mantMSDptr,x_len); carry_rechts = 0; } + {var uintD* y_ptr = y_mantMSDptr mspop x_len; + msprefnext(y_ptr) = carry_rechts; // Carry als nächstes Digit + clear_loop_msp(y_ptr,len); // dann len-x_len Nulldigits + }} + } + return y; +} diff --git a/src/float/lfloat/elem/cl_LF_from_RA.cc b/src/float/lfloat/elem/cl_LF_from_RA.cc new file mode 100644 index 0000000..e1a2c25 --- /dev/null +++ b/src/float/lfloat/elem/cl_LF_from_RA.cc @@ -0,0 +1,142 @@ +// cl_RA_to_LF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF.h" + + +// Implementation. + +#include "cl_LF_impl.h" +#include "cl_RA.h" +#include "cl_integer.h" +#include "cl_I.h" +#include "cl_F.h" + +const cl_LF cl_RA_to_LF (const cl_RA& x, uintC len) +{ +// Methode: +// x ganz -> klar. +// x = +/- a/b mit Integers a,b>0: +// Sei k,m so gewählt, daß +// 2^(k-1) <= a < 2^k, 2^(m-1) <= b < 2^m. +// Dann ist 2^(k-m-1) < a/b < 2^(k-m+1). +// Ergebnis-Vorzeichen := Vorzeichen von x. +// Berechne k=(integer-length a) und m=(integer-length b). +// Ergebnis-Exponent := k-m. +// Ergebnis-Mantisse: +// Berechne floor(2^(-k+m+16n+1)*a/b) : +// Bei k-m>=16n+1 dividiere a durch (ash b (k-m-16n-1)), +// bei k-m<16n+1 dividiere (ash a (-k+m+16n+1)) durch b. +// Der erste Wert ist >=2^16n, <2^(16n+2). +// Falls er >=2^(16n+1) ist, erhöhe Exponent um 1, +// runde 2 Bits weg und schiebe dabei um 2 Bits nach rechts; +// falls er <2^(16n+1) ist, +// runde 1 Bit weg und schiebe dabei um 1 Bit nach rechts. +// NB: Wenn a und b länger sind als len, ist dieser Algorithmus weniger +// effizient, als cl_float(a,len)/cl_float(b,len) zu berechnen. Aber +// es ist wichtig, dass cl_RA_to_LF nicht mehr als 0.5 ulp Fehler hat, +// deswegen belassen wir es beim ineffizienten aber exakten Algorithmus. +// Wenn es auf Rundungsfehler nicht ankommt, muss der Aufrufer im Fall +// ceiling(integer_length(a),intDsize) >= len +// && ceiling(integer_length(b),intDsize) >= len +// einen anderen Algorithmus wählen. + if (integerp(x)) { + DeclareType(cl_I,x); + return cl_I_to_LF(x,len); + } + { // x Ratio + DeclareType(cl_RT,x); + var cl_I a = numerator(x); // +/- a + var const cl_I& b = denominator(x); // b + var cl_signean sign = -(cl_signean)minusp(a); // Vorzeichen + if (!(sign==0)) { a = -a; } // Betrag nehmen, liefert a + var sintL lendiff = (sintL)integer_length(a) // (integer-length a) + - (sintL)integer_length(b); // (integer-length b) + // |lendiff| < intDsize*2^intCsize. Da für LF-Exponenten ein sintL zur + // Verfügung steht, braucht man keinen Test auf Overflow oder Underflow. + var uintL difflimit = intDsize*(uintL)len + 1; // 16n+1 + var cl_I zaehler; + var cl_I nenner; + if (lendiff > (sintL)difflimit) + // 0 <= k-m-16n-1 < k < intDsize*2^intCsize + { nenner = ash(b,(uintL)(lendiff - difflimit)); + zaehler = a; + } + else + // 0 < -k+m+16n+1 <= m+1 + 16n < intDsize*2^intCsize + intDsize*2^intCsize + { zaehler = ash(a,(uintL)(difflimit - lendiff)); // (ash a -k+m+16n+1) + nenner = b; // b + } + // Division zaehler/nenner durchführen: + var cl_I_div_t q_r = cl_divide(zaehler,nenner); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + // 2^16n <= q < 2^(16n+2), also ist q Bignum mit n+1 Digits. + var Lfloat y = allocate_lfloat(len,lendiff+LF_exp_mid,sign); // neues Long-Float + var uintD* y_mantMSDptr = arrayMSDptr(TheLfloat(y)->data,len); + {var uintD* q_MSDptr = arrayMSDptr(TheBignum(q)->data,len+1); + if (mspref(q_MSDptr,0) == 1) // erstes Digit =1 oder =2,3 ? + // 2^16n <= q < 2^(16n+1), also 2^(k-m-1) < a/b < 2^(k-m). + { // Mantisse mit einer Schiebeschleife um 1 Bit nach rechts füllen: + var uintD rounding_bit = + shiftrightcopy_loop_msp(q_MSDptr mspop 1,y_mantMSDptr,len,1,1); + if ( (rounding_bit == 0) // herausgeschobenes Bit =0 -> abrunden + || ( eq(r,0) // =1 und Rest r > 0 -> aufrunden + // round-to-even + && ((mspref(y_mantMSDptr,len-1) & bit(0)) ==0) + ) ) + goto ab; // abrunden + else + goto auf; // aufrunden + } + else + // 2^(16n+1) <= q < 2^(16n+2), also 2^(k-m) < a/b < 2^(k-m+1). + { // Mantisse mit einer Schiebeschleife um 2 Bit nach rechts füllen: + var uintD rounding_bits = + shiftrightcopy_loop_msp(q_MSDptr mspop 1,y_mantMSDptr,len,2,mspref(q_MSDptr,0)); + (TheLfloat(y)->expo)++; // Exponenten incrementieren auf k-m+1 + if ( ((sintD)rounding_bits >= 0) // herausgeschobenes Bit =0 -> abrunden + || ( ((rounding_bits & bit(intDsize-2)) ==0) // =1 und nächstes Bit =1 oder Rest r > 0 -> aufrunden + && eq(r,0) + // round-to-even + && ((mspref(y_mantMSDptr,len-1) & bit(0)) ==0) + ) ) + goto ab; // abrunden + else + goto auf; // aufrunden + } + } + auf: // aufrunden + { if ( inc_loop_lsp(y_mantMSDptr mspop len,len) ) + // Übertrag durchs Aufrunden + { mspref(y_mantMSDptr,0) = bit(intDsize-1); // Mantisse := 10...0 + (TheLfloat(y)->expo)++; // Exponenten incrementieren + } } + ab: // abrunden + return y; +}} + +// Timings on an i486 33 MHz, running Linux, in 0.01 sec. +// First timing: cl_I_to_LF(numerator,len)/cl_I_to_LF(denominator,len) +// Second timing: cl_RA_to_LF(x,len) +// with len = 100. +// num_length 50 70 100 200 500 +// den_length +// +// 50 1.86 0.97 1.84 0.97 1.85 0.96 1.86 1.86 1.85 7.14 +// +// 70 1.86 1.33 1.85 1.31 1.85 1.32 1.84 1.84 1.85 7.13 +// +// 100 1.85 1.85 1.86 1.85 1.85 1.84 1.84 1.84 1.86 7.13 +// +// 200 1.85 3.61 1.84 3.61 1.85 3.59 1.85 3.59 1.87 7.12 +// +// 500 1.84 7.44 1.84 7.55 1.85 7.56 1.84 7.66 1.86 7.63 +// +// We see that cl_RA_to_LF is faster only if +// num_length < 2*len && den_length < len +// whereas cl_I_to_LF(numerator,len)/cl_I_to_LF(denominator,len) is faster if +// num_length > 2*len || den_length > len diff --git a/src/float/lfloat/elem/cl_LF_fround.cc b/src/float/lfloat/elem/cl_LF_fround.cc new file mode 100644 index 0000000..fd8fbcc --- /dev/null +++ b/src/float/lfloat/elem/cl_LF_fround.cc @@ -0,0 +1,134 @@ +// fround(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" +#include "cl_LF_impl.h" +#include "cl_DS.h" + +const cl_LF fround (const cl_LF& x) +{ +// Methode: +// x = 0.0 oder e<0 -> Ergebnis 0.0 +// 0<=e<16n -> letzte (16n-e) Bits der Mantisse wegrunden, +// Exponent und Vorzeichen beibehalten. +// e>=16n -> Ergebnis x +#if 0 + var cl_signean sign; + var sintL exp; + var const uintD* mantMSDptr; + var uintC mantlen; + LF_decode(x, { return x; }, sign=,exp=,mantMSDptr=,mantlen=,); + if (exp<0) { return encode_LF0(mantlen); } // e<0 -> Ergebnis 0.0 + if ((uintL)exp >= intDsize*(uintL)mantlen) // e>=16n -> x als Ergebnis + { return x; } + else + // 0 <= e < 16n + { // alle hinteren 16n-e Bits wegrunden: + var uintC count = floor((uintL)exp,intDsize); // zu kopierende Digits, < mantlen + var uintC bitcount = ((uintL)exp) % intDsize; // zu kopierende Bits danach, >=0, abrunden + if (!((mspref(mantptr,0) & ~mask) ==0)) goto auf; // Bit 16n-e-1 =1 und Bits 16n-e-2..0 >0 -> aufrunden + if (test_loop_msp(mantptr mspop 1,mantlen-count-1)) goto auf; + // round-to-even, je nach Bit 16n-e : + if (bitcount>0) + { if ((mspref(mantptr,0) & (-2*mask)) ==0) goto ab; else goto auf; } + elif (count>0) + { if ((lspref(mantptr,0) & bit(0)) ==0) goto ab; else goto auf; } + else + // bitcount=0, count=0, also exp=0: Abrunden von +-0.5 zu 0.0 + { return encode_LF0(mantlen); } + ab: // abrunden + { CL_ALLOCA_STACK; + var uintD* MSDptr; + num_stack_alloc(mantlen, MSDptr=,); + {var uintD* ptr = + copy_loop_msp(mantMSDptr,MSDptr,count); // count ganze Digits kopieren + msprefnext(ptr) = mspref(mantptr,0) & mask; // dann bitcount Bits kopieren + clear_loop_msp(ptr,mantlen-count-1); // Rest mit Nullen füllen + return encode_LF(sign,exp,MSDptr,mantlen); + }} + auf: // aufrunden + { CL_ALLOCA_STACK; + var uintD* MSDptr; + num_stack_alloc(mantlen, MSDptr=,); + {var uintD* ptr = + copy_loop_msp(mantMSDptr,MSDptr,count); // count ganze Digits kopieren + if ((mspref(ptr,0) = ((mspref(mantptr,0) & mask) - mask)) == 0) // dann bitcount Bits kopieren und incrementieren + { if (!( inc_loop_lsp(ptr,count) ==0)) // evtl. weiterincrementieren + { mspref(MSDptr,0) = bit(intDsize-1); exp = exp+1; } // evtl. Exponenten erhöhen + } + clear_loop_msp(ptr mspop 1,mantlen-count-1); // Rest mit Nullen füllen + return encode_LF(sign,exp,MSDptr,mantlen); + }} + } +#else + var uintC len = TheLfloat(x)->len; + var uintL uexp = TheLfloat(x)->expo; + if (uexp < LF_exp_mid) + { if (uexp == 0) { return x; } // x=0.0 -> Ergebnis 0.0 + return encode_LF0(len); // e<0 -> Ergebnis 0.0 + } + var uintL exp = uexp - LF_exp_mid; + if (exp >= intDsize*(uintL)len) // e>=16n -> x als Ergebnis + { return x; } + // 0 <= e < 16n + // alle hinteren 16n-e Bits wegrunden: + var uintC count = floor(exp,intDsize); // zu kopierende Digits, < mantlen + var uintC bitcount = exp % intDsize; // zu kopierende Bits danach, >=0, abrunden + #else + // Work around gcc-2.7.x bug on i386/ELF + if ((mspref(mantptr,0) & ((~mask)+1)) ==0) goto ab; // Bit 16n-e-1 =0 -> abrunden + #endif + if (!((mspref(mantptr,0) & ~mask) ==0)) goto auf; // Bit 16n-e-1 =1 und Bits 16n-e-2..0 >0 -> aufrunden + if (test_loop_msp(mantptr mspop 1,len-count-1)) goto auf; + // round-to-even, je nach Bit 16n-e : + if (bitcount>0) + { if ((mspref(mantptr,0) & (-2*mask)) ==0) goto ab; else goto auf; } + elif (count>0) + { if ((lspref(mantptr,0) & bit(0)) ==0) goto ab; else goto auf; } + else + // bitcount=0, count=0, also exp=0: Abrunden von +-0.5 zu 0.0 + { return encode_LF0(len); } + } + ab: // abrunden + {var Lfloat y = allocate_lfloat(len,uexp,TheLfloat(x)->sign); // neues Long-Float + // y_mant := NUDS mit e Bits aus x_mant und 16n-e Nullbits: + {var const uintD* x_mantMSDptr = LF_MSDptr(x); + var uintD* ptr = + copy_loop_msp(x_mantMSDptr,arrayMSDptr(TheLfloat(y)->data,len),count); // count ganze Digits kopieren + msprefnext(ptr) = mspref(x_mantMSDptr,count) & mask; // dann bitcount Bits kopieren + clear_loop_msp(ptr,len-count-1); // Rest mit Nullen füllen + } + return y; + } + auf: // aufrunden + {var Lfloat y = allocate_lfloat(len,uexp,TheLfloat(x)->sign); // neues Long-Float + // y_mant := NUDS mit e Bits aus x_mant mit Increment und 16n-e Nullbits: + {var const uintD* x_mantMSDptr = LF_MSDptr(x); + var uintD* y_mantMSDptr = arrayMSDptr(TheLfloat(y)->data,len); + var uintD* ptr = + copy_loop_msp(x_mantMSDptr,y_mantMSDptr,count); // count ganze Digits kopieren + if ((mspref(ptr,0) = ((mspref(x_mantMSDptr,count) & mask) - mask)) == 0) // dann bitcount Bits kopieren und incrementieren + { if (!( inc_loop_lsp(ptr,count) ==0)) // evtl. weiterincrementieren + { mspref(y_mantMSDptr,0) = bit(intDsize-1); (TheLfloat(y)->expo)++; } // evtl. Exponenten erhöhen + } + clear_loop_msp(ptr mspop 1,len-count-1); // Rest mit Nullen füllen + } + return y; + } +#endif +} diff --git a/src/float/lfloat/elem/cl_LF_ftrunc.cc b/src/float/lfloat/elem/cl_LF_ftrunc.cc new file mode 100644 index 0000000..4f45f01 --- /dev/null +++ b/src/float/lfloat/elem/cl_LF_ftrunc.cc @@ -0,0 +1,70 @@ +// ftruncate(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" +#include "cl_LF_impl.h" +#include "cl_DS.h" + +const cl_LF ftruncate (const cl_LF& x) +{ +// Methode: +// x = 0.0 oder e<=0 -> Ergebnis 0.0 +// 1<=e<=16n -> letzte (16n-e) Bits der Mantisse auf 0 setzen, +// Exponent und Vorzeichen beibehalten +// e>=16n -> Ergebnis x +#if 0 + var cl_signean sign; + var sintL exp; + var const uintD* mantMSDptr; + var uintC mantlen; + LF_decode(x, { return x; }, sign=,exp=,mantMSDptr=,mantlen=,); + if (exp<=0) { return encode_LF0(mantlen); } // e<=0 -> Ergebnis 0.0 + if ((uintL)exp >= intDsize*(uintL)mantlen) // e>=16n -> x als Ergebnis + { return x; } + else + // 0 < e < 16n + // neue NUDS erzeugen mit e Bits aus mant und 16n-e Nullbits: + { CL_ALLOCA_STACK; + var uintD* MSDptr; + num_stack_alloc(mantlen, MSDptr=,); + { var uintC count = floor((uintL)exp,intDsize); // zu kopierende Digits, < mantlen + var uintC bitcount = ((uintL)exp) % intDsize; // zu kopierende Bits danach, >=0, len; + var uintL uexp = TheLfloat(x)->expo; + if (uexp <= LF_exp_mid) + { if (uexp == 0) { return x; } // x=0.0 -> Ergebnis 0.0 + return encode_LF0(len); // e<=0 -> Ergebnis 0.0 + } + var uintL exp = uexp - LF_exp_mid; + if (exp >= intDsize*(uintL)len) // e>=16n -> x als Ergebnis + { return x; } + // 0 < e < 16n + var Lfloat y = allocate_lfloat(len,uexp,TheLfloat(x)->sign); // neues Long-Float + // y_mant := NUDS mit e Bits aus x_mant und 16n-e Nullbits: + {var uintC count = floor(exp,intDsize); // zu kopierende Digits, < mantlen + var uintC bitcount = exp % intDsize; // zu kopierende Bits danach, >=0, data,len),count); // count ganze Digits kopieren + msprefnext(ptr) = mspref(x_mantMSDptr,count) & minus_bitm(intDsize-bitcount); // dann bitcount Bits kopieren + clear_loop_msp(ptr,len-count-1); // Rest mit Nullen füllen + } + return y; +#endif +} diff --git a/src/float/lfloat/elem/cl_LF_futrunc.cc b/src/float/lfloat/elem/cl_LF_futrunc.cc new file mode 100644 index 0000000..01eb27e --- /dev/null +++ b/src/float/lfloat/elem/cl_LF_futrunc.cc @@ -0,0 +1,99 @@ +// futruncate(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF.h" + + +// Implementation. + +#include "cl_LF_impl.h" +#include "cl_DS.h" + +const cl_LF futruncate (const cl_LF& x) +{ +// Methode: +// x = 0.0 -> Ergebnis 0.0 +// e<=0 -> Ergebnis 1.0 oder -1.0, je nach Vorzeichen von x. +// 1<=e<16n -> Greife die letzten (16n-e) Bits von x heraus. +// Sind sie alle =0 -> Ergebnis x. +// Sonst setze sie alle auf 0 und erhöhe dann die vorderen e Bits +// um 1. +// Kein Überlauf -> fertig. +// Sonst (Ergebnis eine Zweierpotenz): Mantisse := .1000...000, +// e:=e+1. (Test auf Überlauf wegen e<=16n überflüssig) +// e>=16n -> Ergebnis x. +#if 0 + var cl_signean sign; + var sintL exp; + var const uintD* mantMSDptr; + var uintC mantlen; + LF_decode(x, { return x; }, sign=,exp=,mantMSDptr=,mantlen=,); + if (exp<=0) { return encode_LF1s(sign,mantlen); } // e<=0 -> Ergebnis +-1.0 + if ((uintL)exp >= intDsize*(uintL)mantlen) // e>=16n -> x als Ergebnis + { return x; } + else + // 0 < e < 16n + { // Testen, ob alle hinteren 16n-e Bits =0 sind: + var uintC count = floor((uintL)exp,intDsize); // zu kopierende Digits, < mantlen + var uintC bitcount = ((uintL)exp) % intDsize; // zu kopierende Bits danach, >=0, len; + var uintL uexp = TheLfloat(x)->expo; + if (uexp <= LF_exp_mid) + { if (uexp == 0) { return x; } // x=0.0 -> Ergebnis 0.0 + return encode_LF1s(TheLfloat(x)->sign,len); // e<=0 -> Ergebnis +-1.0 + } + var uintL exp = uexp - LF_exp_mid; + if (exp >= intDsize*(uintL)len) // e>=16n -> x als Ergebnis + { return x; } + // 0 < e < 16n + // Testen, ob alle hinteren 16n-e Bits =0 sind: + var uintC count = floor(exp,intDsize); // zu kopierende Digits, < mantlen + var uintC bitcount = exp % intDsize; // zu kopierende Bits danach, >=0, neues Long-Float produzieren: + var Lfloat y = allocate_lfloat(len,uexp,TheLfloat(x)->sign); // neues Long-Float + // y_mant := NUDS mit e Bits aus x_mant mit Increment und 16n-e Nullbits: + {var const uintD* x_mantMSDptr = LF_MSDptr(x); + var uintD* y_mantMSDptr = arrayMSDptr(TheLfloat(y)->data,len); + var uintD* ptr = + copy_loop_msp(x_mantMSDptr,y_mantMSDptr,count); // count ganze Digits kopieren + if ((mspref(ptr,0) = ((mspref(x_mantMSDptr,count) & mask) - mask)) == 0) // dann bitcount Bits kopieren und incrementieren + { if (!( inc_loop_lsp(ptr,count) ==0)) // evtl. weiterincrementieren + { mspref(y_mantMSDptr,0) = bit(intDsize-1); (TheLfloat(y)->expo)++; } // evtl. Exponenten erhöhen + } + clear_loop_msp(ptr mspop 1,len-count-1); // Rest mit Nullen füllen + } + return y; +#endif +} diff --git a/src/float/lfloat/elem/cl_LF_globals.cc b/src/float/lfloat/elem/cl_LF_globals.cc new file mode 100644 index 0000000..61ef41e --- /dev/null +++ b/src/float/lfloat/elem/cl_LF_globals.cc @@ -0,0 +1,20 @@ +// Global variables for cl_LF. + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_LF_globals) + +// Specification. +#include "cl_number.h" + + +// Implementation. + +#include "cl_LF.h" +#include "cl_LF_impl.h" + +// Only needed for the default constructor of cl_LF. +const cl_LF cl_LF_0 = encode_LF0(LF_minlen); // 0.0L0 + +CL_PROVIDE_END(cl_LF_globals) diff --git a/src/float/lfloat/elem/cl_LF_minus1.cc b/src/float/lfloat/elem/cl_LF_minus1.cc new file mode 100644 index 0000000..8083eda --- /dev/null +++ b/src/float/lfloat/elem/cl_LF_minus1.cc @@ -0,0 +1,19 @@ +// minus1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" + +ALL_cl_LF_OPERATIONS_SAME_PRECISION() + +const cl_LF minus1 (const cl_LF& x) +{ + return x + cl_I_to_LF(cl_I(-1),TheLfloat(x)->len); +} diff --git a/src/float/lfloat/elem/cl_LF_minusp.cc b/src/float/lfloat/elem/cl_LF_minusp.cc new file mode 100644 index 0000000..cb82588 --- /dev/null +++ b/src/float/lfloat/elem/cl_LF_minusp.cc @@ -0,0 +1,18 @@ +// minusp(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" + +MAYBE_INLINE +cl_boolean minusp (const cl_LF& x) +{ + return (cl_boolean) (- TheLfloat(x)->sign); +} diff --git a/src/float/lfloat/elem/cl_LF_mul.cc b/src/float/lfloat/elem/cl_LF_mul.cc new file mode 100644 index 0000000..2699dfa --- /dev/null +++ b/src/float/lfloat/elem/cl_LF_mul.cc @@ -0,0 +1,109 @@ +// binary operator * + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" +#include "cl_LF_impl.h" +#include "cl_DS.h" +#include "cl_F.h" + +const cl_LF operator* (const cl_LF& x1, const cl_LF& x2) +{ +// Methode: +// Falls x1=0.0 oder x2=0.0 -> Ergebnis 0.0 +// Sonst: Ergebnis-Vorzeichen = VZ von x1 xor VZ von x2. +// Ergebnis-Exponent = Summe der Exponenten von x1 und x2. +// Produkt der Mantissen bilden (2n Digits). +// Falls das führende Bit =0 ist: Mantissenprodukt um 1 Bit nach links +// schieben (die vorderen n+1 Digits genügen) +// und Exponent decrementieren. +// Runden auf n Digits liefert die Ergebnis-Mantisse. + var uintC len1 = TheLfloat(x1)->len; + var uintC len2 = TheLfloat(x2)->len; + var uintC len = (len1 < len2 ? len1 : len2); // min. Länge n von x1 und x2 + var uintL uexp1 = TheLfloat(x1)->expo; + if (uexp1==0) // x1=0.0 -> Ergebnis 0.0 + { if (len < len1) return shorten(x1,len); else return x1; } + var uintL uexp2 = TheLfloat(x2)->expo; + if (uexp2==0) // x2=0.0 -> Ergebnis 0.0 + { if (len < len2) return shorten(x2,len); else return x2; } + // Exponenten addieren: + // (uexp1-LF_exp_mid) + (uexp2-LF_exp_mid) = (uexp1+uexp2-LF_exp_mid)-LF_exp_mid + uexp1 = uexp1 + uexp2; + if (uexp1 >= uexp2) + // kein Carry + { if (uexp1 < LF_exp_mid+LF_exp_low) + { if (underflow_allowed()) + { cl_error_floating_point_underflow(); } + else + { return encode_LF0(len); } // Ergebnis 0.0 + } } + else + // Carry + { if (uexp1 > (uintL)(LF_exp_mid+LF_exp_high+1)) { cl_error_floating_point_overflow(); } } + uexp1 = uexp1 - LF_exp_mid; + // Nun ist LF_exp_low <= uexp1 <= LF_exp_high+1. + // neues Long-Float allozieren: + var Lfloat y = allocate_lfloat(len,uexp1, + TheLfloat(x1)->sign ^ TheLfloat(x2)->sign // Vorzeichen kombinieren + ); + // Produkt bilden: + var const uintD* x1_LSDptr = arrayLSDptr(TheLfloat(x1)->data,len1); + var const uintD* x2_LSDptr = arrayLSDptr(TheLfloat(x2)->data,len2); +#ifndef CL_LF_PEDANTIC + if (len1 > len2) + { x1_LSDptr = x1_LSDptr lspop (len1-(len2+1)); len1 = len2+1; } + else if (len1 < len2) + { x2_LSDptr = x2_LSDptr lspop (len2-(len1+1)); len2 = len1+1; } +#endif + var uintD* MSDptr; + CL_ALLOCA_STACK; + UDS_UDS_mul_UDS(len1,x1_LSDptr, + len2,x2_LSDptr, + MSDptr=,,); + {var uintD* midptr = MSDptr mspop len; // Pointer in die Mitte der len1+len2 Digits + if ((sintD)mspref(MSDptr,0) >= 0) // führendes Bit abtesten + { // erste n+1 Digits um 1 Bit nach links schieben: + shift1left_loop_lsp(midptr mspop 1,len+1); + // Exponenten decrementieren: + if ((TheLfloat(y)->expo)-- == LF_exp_low-1) + { if (underflow_allowed()) + { cl_error_floating_point_underflow(); } + else + { return encode_LF0(len); } // Ergebnis 0.0 + } + } + // erste Hälfte des Mantissenprodukts übertragen: + {var uintD* y_mantMSDptr = arrayMSDptr(TheLfloat(y)->data,len); + var uintD* y_mantLSDptr = copy_loop_msp(MSDptr,y_mantMSDptr,len); + // Runden: + if ( ((sintD)mspref(midptr,0) >= 0) // nächstes Bit =0 -> abrunden + || ( ((mspref(midptr,0) & ((uintD)bit(intDsize-1)-1)) ==0) // Bit =1, weitere Bits >0 -> aufrunden + && !test_loop_msp(midptr mspop 1,len1+len2-len-1) + // round-to-even + && ((lspref(midptr,0) & bit(0)) ==0) + ) ) + // abrunden + {} + else + // aufrunden + { if ( inc_loop_lsp(y_mantLSDptr,len) ) + { // Übertrag durchs Aufrunden (kann nur auftreten, + // wenn vorhin um 1 Bit nach links geschoben wurde) + mspref(y_mantMSDptr,0) = bit(intDsize-1); // Mantisse := 10...0 + (TheLfloat(y)->expo)++; // Exponent wieder zurück-erhöhen + } } + // LF_exp_low <= exp <= LF_exp_high sicherstellen: + if (TheLfloat(y)->expo == LF_exp_high+1) { cl_error_floating_point_overflow(); } + }} + return y; +} +// Bit complexity (N = max(length(x1),length(x2))): O(M(N)). + diff --git a/src/float/lfloat/elem/cl_LF_plus1.cc b/src/float/lfloat/elem/cl_LF_plus1.cc new file mode 100644 index 0000000..b431f7d --- /dev/null +++ b/src/float/lfloat/elem/cl_LF_plus1.cc @@ -0,0 +1,19 @@ +// plus1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" + +ALL_cl_LF_OPERATIONS_SAME_PRECISION() + +const cl_LF plus1 (const cl_LF& x) +{ + return x + cl_I_to_LF(cl_I(1),TheLfloat(x)->len); +} diff --git a/src/float/lfloat/elem/cl_LF_plusp.cc b/src/float/lfloat/elem/cl_LF_plusp.cc new file mode 100644 index 0000000..6602978 --- /dev/null +++ b/src/float/lfloat/elem/cl_LF_plusp.cc @@ -0,0 +1,29 @@ +// plusp(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" +#include "cl_LF_impl.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_LF_minusp.cc" +#include "cl_LF_zerop.cc" + +MAYBE_INLINE2 +cl_boolean plusp (const cl_LF& x) +{ + if (minusp(x)) + return cl_false; // x<0 -> nein + elif (zerop(x)) + return cl_false; // x=0 -> nein + else + return cl_true; // sonst ist x>0. +} diff --git a/src/float/lfloat/elem/cl_LF_scale.cc b/src/float/lfloat/elem/cl_LF_scale.cc new file mode 100644 index 0000000..7bb826b --- /dev/null +++ b/src/float/lfloat/elem/cl_LF_scale.cc @@ -0,0 +1,42 @@ +// scale_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" +#include "cl_LF_impl.h" +#include "cl_F.h" + +const cl_LF scale_float (const cl_LF& x, sintL delta) +{ + // Methode: + // delta=0 -> x als Ergebnis + // x=0.0 -> x als Ergebnis + // delta muß ein Integer betragsmäßig <= LF_exp_high-LF_exp_low sein. + // Neues LF mit um delta vergrößertem Exponenten bilden. + if (delta == 0) { return x; } // delta=0 -> x als Ergebnis + var uintL uexp = TheLfloat(x)->expo; + if (uexp==0) { return x; } + var uintL udelta = delta; + if (delta >= 0) { + // udelta = delta >=0 + if ( ((uexp = uexp+udelta) < udelta) // Exponent-Überlauf? + || (uexp > LF_exp_high) // oder Exponent zu groß? + ) + { cl_error_floating_point_overflow(); } + } else { + // delta <0, udelta = 2^32+delta + if ( ((uexp = uexp+udelta) >= udelta) // oder Exponent-Unterlauf? + || (uexp < LF_exp_low) // oder Exponent zu klein? + ) + { cl_error_floating_point_underflow(); } + } + var uintC len = TheLfloat(x)->len; + return encode_LFu(TheLfloat(x)->sign,uexp,arrayMSDptr(TheLfloat(x)->data,len),len); +} diff --git a/src/float/lfloat/elem/cl_LF_scale_I.cc b/src/float/lfloat/elem/cl_LF_scale_I.cc new file mode 100644 index 0000000..df6ec8d --- /dev/null +++ b/src/float/lfloat/elem/cl_LF_scale_I.cc @@ -0,0 +1,107 @@ +// scale_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" +#include "cl_LF_impl.h" +#include "cl_F.h" +#include "cl_I.h" + +const cl_LF scale_float (const cl_LF& x, const cl_I& delta) +{ + // Methode: + // delta=0 -> x als Ergebnis + // x=0.0 -> x als Ergebnis + // delta muß ein Integer betragsmäßig <= LF_exp_high-LF_exp_low sein. + // Neues LF mit um delta vergrößertem Exponenten bilden. + if (eq(delta,0)) { return x; } // delta=0 -> x als Ergebnis + var uintL uexp = TheLfloat(x)->expo; + if (uexp==0) { return x; } + var uintL udelta; + // |delta| muß <= LF_exp_high-LF_exp_low < 2^32 sein. Wie bei I_to_UL: + if (fixnump(delta)) { + // Fixnum + var sint32 sdelta = FN_to_L(delta); + if (sdelta >= 0) + { udelta = sdelta; goto pos; } + else + { udelta = sdelta; goto neg; } + } else { + // Bignum + var cl_heap_bignum* bn = TheBignum(delta); + if ((sintD)mspref(arrayMSDptr(bn->data,bn->length),0) >= 0) { + #define IF_LENGTH(i) \ + if (bn_minlength <= i) /* genau i Digits überhaupt möglich? */\ + if (bn->length == i) /* genau i Digits? */ \ + /* 2^((i-1)*intDsize-1) <= delta < 2^(i*intDsize-1) */ \ + if ( (i*intDsize-1 > 32) \ + && ( ((i-1)*intDsize-1 >= 32) \ + || (mspref(arrayMSDptr(bn->data,i),0) >= (uintD)bitc(32-(i-1)*intDsize)) \ + ) ) \ + goto overflow; \ + else + IF_LENGTH(1) + { udelta = get_uint1D_Dptr(arrayLSDptr(bn->data,1)); goto pos; } + IF_LENGTH(2) + { udelta = get_uint2D_Dptr(arrayLSDptr(bn->data,2)); goto pos; } + IF_LENGTH(3) + { udelta = get_uint3D_Dptr(arrayLSDptr(bn->data,3)); goto pos; } + IF_LENGTH(4) + { udelta = get_uint4D_Dptr(arrayLSDptr(bn->data,4)); goto pos; } + IF_LENGTH(5) + { udelta = get_uint4D_Dptr(arrayLSDptr(bn->data,5)); goto pos; } + #undef IF_LENGTH + goto overflow; // delta zu groß + } else { + #define IF_LENGTH(i) \ + if (bn_minlength <= i) /* genau i Digits überhaupt möglich? */\ + if (bn->length == i) /* genau i Digits? */ \ + /* - 2^((i-1)*intDsize-1) > delta >= - 2^(i*intDsize-1) */\ + if ( (i*intDsize-1 > 32) \ + && ( ((i-1)*intDsize-1 >= 32) \ + || (mspref(arrayMSDptr(bn->data,i),0) < (uintD)(-bitc(32-(i-1)*intDsize))) \ + ) ) \ + goto underflow; \ + else + IF_LENGTH(1) + { udelta = get_sint1D_Dptr(arrayLSDptr(bn->data,1)); goto pos; } + IF_LENGTH(2) + { udelta = get_sint2D_Dptr(arrayLSDptr(bn->data,2)); goto pos; } + IF_LENGTH(3) + { udelta = get_sint3D_Dptr(arrayLSDptr(bn->data,3)); goto pos; } + IF_LENGTH(4) + { udelta = get_sint4D_Dptr(arrayLSDptr(bn->data,4)); goto pos; } + IF_LENGTH(5) + { udelta = get_sint4D_Dptr(arrayLSDptr(bn->data,5)); goto pos; } + #undef IF_LENGTH + goto underflow; // delta zu klein + } + } + + pos: // udelta = delta >=0 + if ( ((uexp = uexp+udelta) < udelta) // Exponent-Überlauf? + || (uexp > LF_exp_high) // oder Exponent zu groß? + ) + overflow: + { cl_error_floating_point_overflow(); } + goto ok; + + neg: // delta <0, udelta = 2^32+delta + if ( ((uexp = uexp+udelta) >= udelta) // oder Exponent-Unterlauf? + || (uexp < LF_exp_low) // oder Exponent zu klein? + ) + underflow: + { cl_error_floating_point_underflow(); } + goto ok; + + ok: + var uintC len = TheLfloat(x)->len; + return encode_LFu(TheLfloat(x)->sign,uexp,arrayMSDptr(TheLfloat(x)->data,len),len); +} diff --git a/src/float/lfloat/elem/cl_LF_square.cc b/src/float/lfloat/elem/cl_LF_square.cc new file mode 100644 index 0000000..59c3891 --- /dev/null +++ b/src/float/lfloat/elem/cl_LF_square.cc @@ -0,0 +1,89 @@ +// square(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" +#include "cl_LF_impl.h" +#include "cl_DS.h" +#include "cl_F.h" + +const cl_LF square (const cl_LF& x) +{ +// Methode: wie operator*(x,x). + var uintC len = TheLfloat(x)->len; + var uintL uexp = TheLfloat(x)->expo; + if (uexp==0) // x=0.0 -> Ergebnis 0.0 + { return x; } + // Exponenten addieren: + // (uexp-LF_exp_mid) + (uexp-LF_exp_mid) = (2*uexp-LF_exp_mid)-LF_exp_mid + if ((sintL)uexp >= 0) + // kein Carry + { uexp = 2*uexp; + if (uexp < LF_exp_mid+LF_exp_low) + { if (underflow_allowed()) + { cl_error_floating_point_underflow(); } + else + { return encode_LF0(len); } // Ergebnis 0.0 + } } + else + // Carry + { uexp = 2*uexp; + if (uexp > (uintL)(LF_exp_mid+LF_exp_high+1)) { cl_error_floating_point_overflow(); } + } + uexp = uexp - LF_exp_mid; + // Nun ist LF_exp_low <= uexp <= LF_exp_high+1. + // neues Long-Float allozieren: + var Lfloat y = allocate_lfloat(len,uexp,0); + // Produkt bilden: + var const uintD* x_LSDptr = arrayLSDptr(TheLfloat(x)->data,len); + var uintD* MSDptr; + var uintD* LSDptr; + CL_ALLOCA_STACK; + num_stack_alloc(2*len,MSDptr=,LSDptr=); + cl_UDS_mul_square(x_LSDptr,len,LSDptr); + {var uintD* midptr = MSDptr mspop len; // Pointer in die Mitte der 2*len Digits + if ((sintD)mspref(MSDptr,0) >= 0) // führendes Bit abtesten + { // erste n+1 Digits um 1 Bit nach links schieben: + shift1left_loop_lsp(midptr mspop 1,len+1); + // Exponenten decrementieren: + if ((TheLfloat(y)->expo)-- == LF_exp_low-1) + { if (underflow_allowed()) + { cl_error_floating_point_underflow(); } + else + { return encode_LF0(len); } // Ergebnis 0.0 + } + } + // erste Hälfte des Mantissenprodukts übertragen: + {var uintD* y_mantMSDptr = arrayMSDptr(TheLfloat(y)->data,len); + var uintD* y_mantLSDptr = copy_loop_msp(MSDptr,y_mantMSDptr,len); + // Runden: + if ( ((sintD)mspref(midptr,0) >= 0) // nächstes Bit =0 -> abrunden + || ( ((mspref(midptr,0) & ((uintD)bit(intDsize-1)-1)) ==0) // Bit =1, weitere Bits >0 -> aufrunden + && !test_loop_msp(midptr mspop 1,len-1) + // round-to-even + && ((lspref(midptr,0) & bit(0)) ==0) + ) ) + // abrunden + {} + else + // aufrunden + { if ( inc_loop_lsp(y_mantLSDptr,len) ) + { // Übertrag durchs Aufrunden (kann nur auftreten, + // wenn vorhin um 1 Bit nach links geschoben wurde) + mspref(y_mantMSDptr,0) = bit(intDsize-1); // Mantisse := 10...0 + (TheLfloat(y)->expo)++; // Exponent wieder zurück-erhöhen + } } + // LF_exp_low <= exp <= LF_exp_high sicherstellen: + if (TheLfloat(y)->expo == LF_exp_high+1) { cl_error_floating_point_overflow(); } + }} + return y; +} +// Bit complexity (N = length(x)): O(M(N)). + diff --git a/src/float/lfloat/elem/cl_LF_to_I.cc b/src/float/lfloat/elem/cl_LF_to_I.cc new file mode 100644 index 0000000..a90cb28 --- /dev/null +++ b/src/float/lfloat/elem/cl_LF_to_I.cc @@ -0,0 +1,45 @@ +// cl_LF_to_I(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF.h" + + +// Implementation. + +#include "cl_integer.h" +#include "cl_I.h" +#include "cl_DS.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_LF_minusp.cc" + +const cl_I cl_LF_to_I (const cl_LF& x) +{ +// Methode: +// Falls x=0.0, Ergebnis 0. +// Sonst (ASH Vorzeichen*Mantisse (e-16n)). + var uintL uexp = TheLfloat(x)->expo; + if (uexp==0) { return 0; } // x=0.0 -> Ergebnis 0 + // Mantisse zu einem Integer machen: + CL_ALLOCA_STACK; + var uintD* MSDptr; + var uintD* LSDptr; + var uintC len = TheLfloat(x)->len; + var uintC len1 = len+1; // brauche 1 Digit mehr + num_stack_alloc(len1, MSDptr=,LSDptr=); + copy_loop_msp(arrayMSDptr(TheLfloat(x)->data,len),MSDptr mspop 1,len); // Mantisse kopieren + mspref(MSDptr,0) = 0; // und zusätzliches Nulldigit + // Mantisse ist die UDS MSDptr/len1/LSDptr. + if (minusp(x)) + // x<0 -> Mantisse negieren: + { neg_loop_lsp(LSDptr,len1); } + // Vorzeichen*Mantisse ist die DS MSDptr/len1/LSDptr. + // (ASH Vorzeichen*Mantisse (- e 16n)) durchführen: + return ash(DS_to_I(MSDptr,len1), + minus(uexp, LF_exp_mid + intDsize*(uintL)len) + ); +} diff --git a/src/float/lfloat/elem/cl_LF_uminus.cc b/src/float/lfloat/elem/cl_LF_uminus.cc new file mode 100644 index 0000000..697ffc8 --- /dev/null +++ b/src/float/lfloat/elem/cl_LF_uminus.cc @@ -0,0 +1,28 @@ +// unary operator - + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" +#include "cl_LF_impl.h" +#include "cl_DS.h" + +const cl_LF operator- (const cl_LF& x) +{ +// Methode: +// Falls x=0.0, fertig. Sonst Vorzeichenbit umdrehen und Pointer beibehalten. + if (TheLfloat(x)->expo == 0) + { return x; } + else + { var uintC len = TheLfloat(x)->len; + var Lfloat mx = allocate_lfloat(len, TheLfloat(x)->expo, ~ TheLfloat(x)->sign); + copy_loop_up(&TheLfloat(x)->data[0],&TheLfloat(mx)->data[0],len); + return mx; + } +} diff --git a/src/float/lfloat/elem/cl_LF_zerop.cc b/src/float/lfloat/elem/cl_LF_zerop.cc new file mode 100644 index 0000000..fd6f9f9 --- /dev/null +++ b/src/float/lfloat/elem/cl_LF_zerop.cc @@ -0,0 +1,18 @@ +// zerop(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" + +MAYBE_INLINE +cl_boolean zerop (const cl_LF& x) +{ + return (cl_boolean) (TheLfloat(x)->expo == 0); +} diff --git a/src/float/lfloat/elem/cl_RA_LF_div.cc b/src/float/lfloat/elem/cl_RA_LF_div.cc new file mode 100644 index 0000000..99a9a2d --- /dev/null +++ b/src/float/lfloat/elem/cl_RA_LF_div.cc @@ -0,0 +1,61 @@ +// cl_RA_LF_div(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_RA.h" + +const cl_R cl_RA_LF_div (const cl_RA& x, const cl_LF& y) +{ +// Method: +// Write x = u/v. Return u/(v*y). + if (integerp(x)) { + DeclareType(cl_I,x); + return cl_I_LF_div(x,y); + } else { + DeclareType(cl_RT,x); + var const cl_I& u = TheRatio(x)->numerator; + var const cl_I& v = TheRatio(x)->denominator; // v /= 0 + return cl_I_LF_div(u,The(cl_LF)(cl_LF_I_mul(y,v))); + } +} + +// Timings on an i486 33 MHz, running Linux. +// First timing: u/(v*y), using cl_LF_I_mul and cl_LF_I_div +// Second timing: (u/v)/y, using cl_RA_to_LF and operator/ +// With x_length = 100, in 0.01 sec. +// num_length 50 70 100 200 500 +// den_length +// +// 50 0.82 0.98 1.38 1.61 2.48 2.80 8.37 9.05 46.92 48.59 +// +// 70 0.81 1.16 1.43 1.85 2.65 3.18 8.64 9.76 47.53 50.34 +// +// 100 0.82 1.43 1.44 2.24 2.79 3.69 8.98 10.77 48.42 52.81 +// +// 200 0.80 2.31 1.43 3.44 2.78 5.43 9.93 14.31 51.08 61.57 +// +// 500 0.82 4.62 1.44 6.21 2.76 9.40 9.97 22.66 55.52 87.71 +// +// With x_length = 1000, in sec. +// num_length 500 700 1000 2000 5000 +// den_length +// +// 500 0.55 0.88 0.96 1.39 1.60 2.24 4.35 5.60 10.83 14.18 +// +// 700 0.55 0.95 0.98 1.57 1.65 2.58 4.47 6.34 10.61 15.88 +// +// 1000 0.56 1.00 0.98 1.67 1.69 2.70 4.61 7.13 10.65 16.29 +// +// 2000 0.56 1.25 0.98 1.97 1.69 3.05 4.88 7.74 10.75 17.03 +// +// 5000 0.55 1.94 0.98 2.30 1.70 3.33 4.90 7.74 11.94 19.29 +// +// We see that the first approach is always better than the second. diff --git a/src/float/lfloat/input/Makeflags b/src/float/lfloat/input/Makeflags new file mode 100644 index 0000000..b886167 --- /dev/null +++ b/src/float/lfloat/input/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/lfloat/Makeflags +SUBDIR_INCLUDES += diff --git a/src/float/lfloat/input/cl_LF_from_string.cc b/src/float/lfloat/input/cl_LF_from_string.cc new file mode 100644 index 0000000..1991a4d --- /dev/null +++ b/src/float/lfloat/input/cl_LF_from_string.cc @@ -0,0 +1,27 @@ +// cl_LF (const char *) constructor. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat_class.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_input.h" +#include "cl_float_io.h" + +cl_read_flags cl_LF_read_flags = { + syntax_lfloat, + lsyntax_all, + 10, + { cl_float_format_lfloat_min, cl_float_format_lfloat_min, cl_false } +}; + +cl_LF::cl_LF (const char * string) +{ + pointer = as_cl_private_thing( + As(cl_LF)(read_float(cl_LF_read_flags,string,NULL,NULL))); +} diff --git a/src/float/lfloat/misc/Makeflags b/src/float/lfloat/misc/Makeflags new file mode 100644 index 0000000..68f60c4 --- /dev/null +++ b/src/float/lfloat/misc/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/lfloat/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/float/lfloat/elem -I$(srcdir)/integer diff --git a/src/float/lfloat/misc/cl_LF_abs.cc b/src/float/lfloat/misc/cl_LF_abs.cc new file mode 100644 index 0000000..11cab15 --- /dev/null +++ b/src/float/lfloat/misc/cl_LF_abs.cc @@ -0,0 +1,20 @@ +// abs(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_LF_minusp.cc" + +const cl_LF abs (const cl_LF& x) +{ +// x<0 -> (- x), x>=0 -> x + if (minusp(x)) return -x; else return x; +} diff --git a/src/float/lfloat/misc/cl_LF_as.cc b/src/float/lfloat/misc/cl_LF_as.cc new file mode 100644 index 0000000..9a38f99 --- /dev/null +++ b/src/float/lfloat/misc/cl_LF_as.cc @@ -0,0 +1,29 @@ +// as_cl_LF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_N.h" + +inline cl_boolean cl_LF_p (const cl_number& x) +{ + if (x.pointer_p()) + if (x.heappointer->type == &cl_class_lfloat) + return cl_true; + return cl_false; +} + +const cl_LF& as_cl_LF (const cl_number& x, const char * filename, int line) +{ + if (cl_LF_p(x)) { + DeclareType(cl_LF,x); + return x; + } else + cl_as_error(x,"a long-float number",filename,line); +} diff --git a/src/float/lfloat/misc/cl_LF_class.cc b/src/float/lfloat/misc/cl_LF_class.cc new file mode 100644 index 0000000..7333f69 --- /dev/null +++ b/src/float/lfloat/misc/cl_LF_class.cc @@ -0,0 +1,15 @@ +// cl_class_lfloat. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +cl_class cl_class_lfloat = { + NULL, // empty destructor + cl_class_flags_subclass_complex | cl_class_flags_subclass_real | cl_class_flags_subclass_float +}; diff --git a/src/float/lfloat/misc/cl_LF_debug.cc b/src/float/lfloat/misc/cl_LF_debug.cc new file mode 100644 index 0000000..7d65e82 --- /dev/null +++ b/src/float/lfloat/misc/cl_LF_debug.cc @@ -0,0 +1,25 @@ +// cl_LF debugging support. + +// General includes. +#include "cl_sysdep.h" + +// Specification. + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_io.h" +#include "cl_float_io.h" + +static void dprint (cl_heap* pointer) +{ + var const cl_LF& obj = *(const cl_LF*)&pointer; + fprint(cl_debugout, "(cl_LF) "); + fprint(cl_debugout, obj); +} +AT_INITIALIZATION(dprint_LF) +{ cl_register_type_printer(cl_class_lfloat,dprint); } + +// This dummy links in this module when requires it. +int cl_LF_debug_module; diff --git a/src/float/lfloat/misc/cl_LF_decode.cc b/src/float/lfloat/misc/cl_LF_decode.cc new file mode 100644 index 0000000..d3889e9 --- /dev/null +++ b/src/float/lfloat/misc/cl_LF_decode.cc @@ -0,0 +1,30 @@ +// decode_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" +#include "cl_LF_impl.h" +#include "cl_I.h" + +const cl_decoded_lfloat decode_float (const cl_LF& x) +{ + // x entpacken: + var cl_signean sign; + var sintL exp; + var uintC mantlen; + var const uintD* mantMSDptr; + LF_decode(x, { return cl_decoded_lfloat(x, 0, encode_LF1(mantlen)); }, + sign=,exp=,mantMSDptr=,mantlen=,); + return cl_decoded_lfloat( + encode_LFu(0,0+LF_exp_mid,mantMSDptr,mantlen), // (-1)^0 * 2^0 * m erzeugen + L_to_I(exp), // e als Fixnum + encode_LF1s(sign,mantlen) // (-1)^s erzeugen + ); +} diff --git a/src/float/lfloat/misc/cl_LF_digits.cc b/src/float/lfloat/misc/cl_LF_digits.cc new file mode 100644 index 0000000..a7c2c55 --- /dev/null +++ b/src/float/lfloat/misc/cl_LF_digits.cc @@ -0,0 +1,18 @@ +// float_digits(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" + +MAYBE_INLINE +uintL float_digits (const cl_LF& x) +{ + return intDsize*(uintL)(TheLfloat(x)->len); +} diff --git a/src/float/lfloat/misc/cl_LF_eqhashcode.cc b/src/float/lfloat/misc/cl_LF_eqhashcode.cc new file mode 100644 index 0000000..ec70512 --- /dev/null +++ b/src/float/lfloat/misc/cl_LF_eqhashcode.cc @@ -0,0 +1,29 @@ +// cl_LF equal_hashcode(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_N.h" +#include "cl_LF_impl.h" +#include "cl_DS.h" + +MAYBE_INLINE +uint32 cl_equal_hashcode (const cl_LF& x) +{ + var cl_signean sign; + var sintL exp; + var const uintD* MSDptr; + LF_decode(x, { return 0; }, sign=,exp=,MSDptr=,,); + #if (intDsize==64) + var uint32 msd = mspref(MSDptr,0) >> 32; + #else // (intDsize<=32) + var uint32 msd = get_32_Dptr(MSDptr); + #endif + return equal_hashcode_low(msd,exp,sign); +} diff --git a/src/float/lfloat/misc/cl_LF_exponent.cc b/src/float/lfloat/misc/cl_LF_exponent.cc new file mode 100644 index 0000000..44d0291 --- /dev/null +++ b/src/float/lfloat/misc/cl_LF_exponent.cc @@ -0,0 +1,20 @@ +// float_exponent(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" + +MAYBE_INLINE +sintL float_exponent (const cl_LF& x) +{ + var uintL uexp = TheLfloat(x)->expo; + if (uexp==0) { return 0; } + return (sintL)(uexp - LF_exp_mid); +} diff --git a/src/float/lfloat/misc/cl_LF_extend.cc b/src/float/lfloat/misc/cl_LF_extend.cc new file mode 100644 index 0000000..3c1ee60 --- /dev/null +++ b/src/float/lfloat/misc/cl_LF_extend.cc @@ -0,0 +1,25 @@ +// extend(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF.h" + + +// Implementation. + +#include "cl_LF_impl.h" +#include "cl_DS.h" + +const cl_LF extend (const cl_LF& x, uintC len) +{ + var Lfloat y = allocate_lfloat(len,TheLfloat(x)->expo,TheLfloat(x)->sign); // neues LF + { var uintC oldlen = TheLfloat(x)->len; // alte Länge, < len + // Mantisse von x nach y kopieren: + var uintD* ptr = copy_loop_msp(arrayMSDptr(TheLfloat(x)->data,oldlen),arrayMSDptr(TheLfloat(y)->data,len),oldlen); + // und mit Null-Digits ergänzen: + clear_loop_msp(ptr,len-oldlen); + } + return y; +} diff --git a/src/float/lfloat/misc/cl_LF_idecode.cc b/src/float/lfloat/misc/cl_LF_idecode.cc new file mode 100644 index 0000000..959aa3d --- /dev/null +++ b/src/float/lfloat/misc/cl_LF_idecode.cc @@ -0,0 +1,38 @@ +// integer_decode_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" +#include "cl_I.h" +#include "cl_DS.h" + +MAYBE_INLINE +const cl_idecoded_float integer_decode_float (const cl_LF& x) +{ + // x entpacken: + var uintL uexp = TheLfloat(x)->expo; + if (uexp == 0) + { return cl_idecoded_float(0, 0, 1); } + var cl_signean sign = TheLfloat(x)->sign; + var uintC len = TheLfloat(x)->len; + // intDsize*len >= 53 >= 33 >= cl_value_len, also len >= bn_minlength. + // Baue Integer für die Mantisse. + // Vorne 1 Nulldigit, damit es eine NDS wird. + var Bignum mant = allocate_bignum(1+len); + mspref(arrayMSDptr(TheBignum(mant)->data,1+len),0) = 0; + copy_loop_msp(arrayMSDptr(TheLfloat(x)->data,len),arrayMSDptr(TheBignum(mant)->data,1+len) mspop 1,len); // NUDS kopieren + return cl_idecoded_float( + // Mantisse + mant, + // e-intDsize*n = uexp-LF_exp_mid-intDsize*n als Integer + minus(uexp, LF_exp_mid + intDsize*(uintL)len), + (sign>=0 ? cl_I(1) : cl_I(-1)) // (-1)^s erzeugen + ); +} diff --git a/src/float/lfloat/misc/cl_LF_leninc.cc b/src/float/lfloat/misc/cl_LF_leninc.cc new file mode 100644 index 0000000..34c3579 --- /dev/null +++ b/src/float/lfloat/misc/cl_LF_leninc.cc @@ -0,0 +1,53 @@ +// cl_LF_len_incsqrt(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF.h" + + +// Implementation. + +uintC cl_LF_len_incsqrt (uintC n) +{ +// Methode bei intDsize=16: +// n -> n+1 für n<=12 wegen 16n+sqrt(16n)+2 < 16(n+1) +// n -> n+2 für n<=56 wegen 16n+sqrt(16n)+2 < 16(n+2) +// n -> n+4 für n<=240 +// n -> n+8 für n<=992 +// n -> n+16 für n<=4032 +// n -> n+32 für n<=16256 +// n -> n+65 für n<=65535 +// Allgemein: intDsize*n + sqrt(intDsize*n) + 2 < intDsize*(n+inc) +// <==> sqrt(intDsize*n) + 2 < intDsize*inc +// <==> sqrt(intDsize*n) < intDsize*inc - 2 +// <==> intDsize*n < intDsize^2*inc^2 - 4*intDsize*inc + 4 +// <==> n <= intDsize*inc^2 - 4*inc + return + #define NMAX(k) (uintL)((intDsize*(k)-4)*(k)) + #define FITS(n,k) ((n) <= NMAX(k)) + #define n_max (uintL)(bitm(intCsize)-1) + #define TRYINC(inc) FITS(n_max,inc) || FITS(n,inc) ? RETINC(inc) : + #define RETINC(inc) \ + /* at this point we know n <= NMAX(inc) */ \ + /* Check whether n + (inc) overflows. */ \ + ((NMAX(inc) <= n_max-(inc)) || (n <= n_max-(inc)) ? n+(inc) : n_max) + #define TEST(i) TRYINC(1UL< sqrt(intDsize*n) + 33 < intDsize*inc +// <==> sqrt(intDsize*n) < intDsize*inc - 33 +// <==> intDsize*n < intDsize^2*inc^2 - 66*intDsize*inc + 1089 +// <==> n <= intDsize*inc^2 - 66*inc + floor(1089/intDsize) + return + #define NMAX(k) (uintL)((intDsize*(k)-66)*(k)+floor(1089,intDsize)) + #define FITS(n,k) ((intDsize*(k) > 33) && ((n) <= NMAX(k))) + #define n_max (uintL)(bitm(intCsize)-1) + #define TRYINC(inc) FITS(n_max,inc) || FITS(n,inc) ? RETINC(inc) : + #define RETINC(inc) \ + /* at this point we know n <= NMAX(inc) */ \ + /* Check whether n + (inc) overflows. */ \ + ((NMAX(inc) <= n_max-(inc)) || (n <= n_max-(inc)) ? n+(inc) : n_max) + #define TEST(i) TRYINC(1UL<= y ? x : y); +} diff --git a/src/float/lfloat/misc/cl_LF_min.cc b/src/float/lfloat/misc/cl_LF_min.cc new file mode 100644 index 0000000..b58bb42 --- /dev/null +++ b/src/float/lfloat/misc/cl_LF_min.cc @@ -0,0 +1,15 @@ +// min(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +const cl_LF min (const cl_LF& x, const cl_LF& y) +{ + return (x <= y ? x : y); +} diff --git a/src/float/lfloat/misc/cl_LF_precision.cc b/src/float/lfloat/misc/cl_LF_precision.cc new file mode 100644 index 0000000..7c9bdcd --- /dev/null +++ b/src/float/lfloat/misc/cl_LF_precision.cc @@ -0,0 +1,23 @@ +// float_precision(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_LF_zerop.cc" + +MAYBE_INLINE2 +uintL float_precision (const cl_LF& x) +{ + if (zerop(x)) return 0; + return intDsize*(uintL)(TheLfloat(x)->len); +} diff --git a/src/float/lfloat/misc/cl_LF_shorten.cc b/src/float/lfloat/misc/cl_LF_shorten.cc new file mode 100644 index 0000000..c3a023f --- /dev/null +++ b/src/float/lfloat/misc/cl_LF_shorten.cc @@ -0,0 +1,44 @@ +// shorten(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF.h" + + +// Implementation. + +#include "cl_LF_impl.h" +#include "cl_DS.h" +#include "cl_F.h" + +const cl_LF shorten (const cl_LF& x, uintC len) +{ + // x = 0.0 braucht nicht abgefangen zu werden, da bei Mantisse 0 dann + // sowieso abgerundet wird, die Mantisse also 0 bleibt. + var Lfloat y = allocate_lfloat(len,TheLfloat(x)->expo,TheLfloat(x)->sign); // neues LF + { var uintC oldlen = TheLfloat(x)->len; // alte Länge, > len + // Mantisse von x nach y kopieren: + copy_loop_msp(arrayMSDptr(TheLfloat(x)->data,oldlen),arrayMSDptr(TheLfloat(y)->data,len),len); + // Entscheiden, ob auf- oder abrunden: + var uintD* ptr = arrayMSDptr(TheLfloat(x)->data,oldlen) mspop len; + if ( ((sintD)mspref(ptr,0) >= 0) // nächstes Bit eine 0 -> abrunden + || ( ((mspref(ptr,0) & ((uintD)bit(intDsize-1)-1)) ==0) // eine 1 und alles weitere Nullen? + && !test_loop_msp(ptr mspop 1,oldlen-len-1) + // round-to-even + && ((lspref(ptr,0) & bit(0)) ==0) + ) ) + // abrunden + {} + else + // aufrunden + { if ( inc_loop_lsp(arrayLSDptr(TheLfloat(y)->data,len),len) ) + // Übertrag durch Aufrunden + { mspref(arrayMSDptr(TheLfloat(y)->data,len),0) = bit(intDsize-1); // Mantisse := 10...0 + // Exponent erhöhen: + if (++(TheLfloat(y)->expo) == LF_exp_high+1) { cl_error_floating_point_overflow(); } + } } + } + return y; +} diff --git a/src/float/lfloat/misc/cl_LF_shortenrel.cc b/src/float/lfloat/misc/cl_LF_shortenrel.cc new file mode 100644 index 0000000..11c1c56 --- /dev/null +++ b/src/float/lfloat/misc/cl_LF_shortenrel.cc @@ -0,0 +1,52 @@ +// cl_LF_shortenrelative(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF.h" + + +// Implementation. + +#include "cl_abort.h" + +#undef MAYBE_INLINE2 +#define MAYBE_INLINE2 inline +#include "cl_LF_precision.cc" +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_LF_exponent.cc" + +const cl_LF cl_LF_shortenrelative (const cl_LF& x, const cl_LF& y) +{ + // Methode: + // x = 0.0 -> Precision egal, return x. + // ex := float_exponent(x), ey := float_exponent(y). + // dx := float_digits(x), dy := float_digits(y). + // 1 ulp(x) = 2^(ex-dx), 1 ulp(y) = 2^(ey-dy). + // Falls ex-dx < ey-dy, x von Precision dx auf dy-ey+ex verkürzen. + var sintL ey = float_exponent(y); + var sintL dy = float_precision(y); + if (dy==0) // zerop(y) ? + cl_abort(); + var sintL ex = float_exponent(x); + var sintL dx = float_precision(x); + if (dx==0) // zerop(x) ? + return x; + var sintL d = ex - ey; + if (ex>=0 && ey<0 && d<0) // d overflow? + return x; + if (ex<0 && ey>=0 && d>=0) // d underflow? + return LF_to_LF(x,LF_minlen); + if (d >= dx - dy) + return x; + var uintL new_dx = dy + d; + var uintL len = ceiling(new_dx,intDsize); + if (len < LF_minlen) + len = LF_minlen; + if (intDsize*len < (uintL)dx) + return shorten(x,len); + else + return x; +} diff --git a/src/float/lfloat/misc/cl_LF_shortenwith.cc b/src/float/lfloat/misc/cl_LF_shortenwith.cc new file mode 100644 index 0000000..9b456f9 --- /dev/null +++ b/src/float/lfloat/misc/cl_LF_shortenwith.cc @@ -0,0 +1,49 @@ +// cl_LF_shortenwith(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF.h" + + +// Implementation. + +#include "cl_abort.h" + +#undef MAYBE_INLINE2 +#define MAYBE_INLINE2 inline +#include "cl_LF_precision.cc" +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_LF_exponent.cc" + +const cl_LF cl_LF_shortenwith (const cl_LF& x, const cl_LF& y) +{ + // Methode: + // x = 0.0 -> Precision egal, return x. + // ex := float_exponent(x), dx := float_digits(x), 1 ulp(x) = 2^(ex-dx). + // ey := float_exponent(y). + // Falls ex-dx < ey, x von Precision dx auf ex-ey verkürzen. + var sintL ey = float_exponent(y); + var sintL ex = float_exponent(x); + var uintL dx = float_precision(x); + if (dx==0) // zerop(x) ? + return x; + var sintL ulpx = ex - dx; + if ((ex<0 && ulpx>=0) // underflow? + || (ulpx < ey) + ) { // Now ex-dx < ey, hence ex-ey < dx. + var uintL new_dx; + if (ex < ey) + new_dx = intDsize*LF_minlen; + else if ((new_dx = ex - ey) < intDsize*LF_minlen) + new_dx = intDsize*LF_minlen; + var uintL len = ceiling(new_dx,intDsize); + if (intDsize*len < dx) + return shorten(x,len); + else + return x; + } else + return x; +} diff --git a/src/float/lfloat/misc/cl_LF_sign.cc b/src/float/lfloat/misc/cl_LF_sign.cc new file mode 100644 index 0000000..0d8787f --- /dev/null +++ b/src/float/lfloat/misc/cl_LF_sign.cc @@ -0,0 +1,24 @@ +// float_sign(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" +#include "cl_LF_impl.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_LF_minusp.cc" + +MAYBE_INLINE2 +const cl_LF float_sign (const cl_LF& x) +{ +// Methode: x>=0 -> Ergebnis 1.0; x<0 -> Ergebnis -1.0 + return encode_LF1s(TheLfloat(x)->sign,TheLfloat(x)->len); +} diff --git a/src/float/lfloat/misc/cl_LF_signum.cc b/src/float/lfloat/misc/cl_LF_signum.cc new file mode 100644 index 0000000..0ae4d41 --- /dev/null +++ b/src/float/lfloat/misc/cl_LF_signum.cc @@ -0,0 +1,26 @@ +// signum(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_lfloat.h" + + +// Implementation. + +#include "cl_LF.h" +#include "cl_LF_impl.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_LF_minusp.cc" +#include "cl_LF_zerop.cc" + +MAYBE_INLINE2 +const cl_LF signum (const cl_LF& x) +{ + if (zerop(x)) { return x; } // x=0 -> 0.0 + else // je nach Vorzeichen von x + { return encode_LF1s(TheLfloat(x)->sign,TheLfloat(x)->len); } +} diff --git a/src/float/lfloat/misc/cl_LF_to_LF.cc b/src/float/lfloat/misc/cl_LF_to_LF.cc new file mode 100644 index 0000000..8426cd5 --- /dev/null +++ b/src/float/lfloat/misc/cl_LF_to_LF.cc @@ -0,0 +1,19 @@ +// LF_to_LF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF.h" + + +// Implementation. + +const cl_LF LF_to_LF (const cl_LF& x, uintC len) +{ + var uintC oldlen = TheLfloat(x)->len; + if (len < oldlen) { return shorten(x,len); } + if (len > oldlen) { return extend(x,len); } + // len = oldlen + return x; +} diff --git a/src/float/misc/Makeflags b/src/float/misc/Makeflags new file mode 100644 index 0000000..908269e --- /dev/null +++ b/src/float/misc/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/float/sfloat/elem -I$(srcdir)/float/sfloat/misc -I$(srcdir)/float/ffloat/elem -I$(srcdir)/float/ffloat/misc -I$(srcdir)/float/dfloat/elem -I$(srcdir)/float/dfloat/misc -I$(srcdir)/float/lfloat/elem -I$(srcdir)/float/lfloat/misc -I$(srcdir)/rational -I$(srcdir)/integer diff --git a/src/float/misc/cl_F_abs.cc b/src/float/misc/cl_F_abs.cc new file mode 100644 index 0000000..879bc59 --- /dev/null +++ b/src/float/misc/cl_F_abs.cc @@ -0,0 +1,34 @@ +// abs(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_SF_minusp.cc" +#include "cl_FF_minusp.cc" +#include "cl_DF_minusp.cc" +#include "cl_LF_minusp.cc" + +const cl_F abs (const cl_F& x) +{ +// x<0 -> (- x), x>=0 -> x + floatcase(x + , if (minusp(x)) return -x; else return x; + , if (minusp(x)) return -x; else return x; + , if (minusp(x)) return -x; else return x; + , if (minusp(x)) return -x; else return x; + ); +} diff --git a/src/float/misc/cl_F_as.cc b/src/float/misc/cl_F_as.cc new file mode 100644 index 0000000..4f0f4c3 --- /dev/null +++ b/src/float/misc/cl_F_as.cc @@ -0,0 +1,37 @@ +// as_cl_F(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_N.h" + +inline cl_boolean cl_F_p (const cl_number& x) +{ + if (!x.pointer_p()) + switch (cl_tag((x).word)) { + case cl_SF_tag: + #if defined(CL_WIDE_POINTERS) + case cl_FF_tag: + #endif + return cl_true; + } + else + if (x.heappointer->type->flags & cl_class_flags_subclass_float) + return cl_true; + return cl_false; +} + +const cl_F& as_cl_F (const cl_number& x, const char * filename, int line) +{ + if (cl_F_p(x)) { + DeclareType(cl_F,x); + return x; + } else + cl_as_error(x,"a floating-point number",filename,line); +} diff --git a/src/float/misc/cl_F_decode.cc b/src/float/misc/cl_F_decode.cc new file mode 100644 index 0000000..af89c90 --- /dev/null +++ b/src/float/misc/cl_F_decode.cc @@ -0,0 +1,105 @@ +// decode_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_SF.h" +#include "cl_FF.h" +#include "cl_DF.h" +#include "cl_LF.h" +#include "cl_LF_impl.h" +#include "cl_I.h" +#include "cl_F.h" + +inline const cl_decoded_float decode_float (const cl_SF& x) +{ + // x entpacken: + var cl_signean sign; + var sintL exp; + var uint32 mant; + SF_decode(x, { return cl_decoded_float(SF_0, 0, SF_1); }, + sign=,exp=,mant= + ); + return cl_decoded_float( + encode_SF(0,0,mant), // (-1)^0 * 2^0 * m erzeugen + L_to_FN(exp), // e als Fixnum + encode_SF(sign,1,bit(SF_mant_len)) // (-1)^s erzeugen + ); +} + +inline const cl_decoded_float decode_float (const cl_FF& x) +{ + // x entpacken: + var cl_signean sign; + var sintL exp; + var uint32 mant; + FF_decode(x, { return cl_decoded_float(cl_FF_0, 0, cl_FF_1); }, + sign=,exp=,mant= + ); + return cl_decoded_float( + encode_FF(0,0,mant), // (-1)^0 * 2^0 * m erzeugen + L_to_FN(exp), // e als Fixnum + encode_FF(sign,1,bit(FF_mant_len)) // (-1)^s erzeugen + ); +} + +inline const cl_decoded_float decode_float (const cl_DF& x) +{ + // x entpacken: + var cl_signean sign; + var sintL exp; +#if (cl_word_size==64) + var uint64 mant; + DF_decode(x, { return cl_decoded_float(cl_DF_0, 0, cl_DF_1); }, + sign=,exp=,mant= + ); + return cl_decoded_float( + encode_DF(0,0,mant), // (-1)^0 * 2^0 * m erzeugen + L_to_FN(exp), // e als Fixnum + encode_DF(sign,1,bit(DF_mant_len)) // (-1)^s erzeugen + ); +#else + var uint32 manthi; + var uint32 mantlo; + DF_decode2(x, { return cl_decoded_float(cl_DF_0, 0, cl_DF_1); }, + sign=,exp=,manthi=,mantlo= + ); + return cl_decoded_float( + encode_DF(0,0,manthi,mantlo), // (-1)^0 * 2^0 * m erzeugen + L_to_FN(exp), // e als Fixnum + encode_DF(sign,1,bit(DF_mant_len-32),0) // (-1)^s erzeugen + ); +#endif +} + +inline const cl_decoded_float decode_float (const cl_LF& x) +{ + // x entpacken: + var cl_signean sign; + var sintL exp; + var uintC mantlen; + var const uintD* mantMSDptr; + LF_decode(x, { return cl_decoded_float(x, 0, encode_LF1(mantlen)); }, + sign=,exp=,mantMSDptr=,mantlen=,); + return cl_decoded_float( + encode_LFu(0,0+LF_exp_mid,mantMSDptr,mantlen), // (-1)^0 * 2^0 * m erzeugen + L_to_I(exp), // e als Fixnum + encode_LF1s(sign,mantlen) // (-1)^s erzeugen + ); +} + +const cl_decoded_float decode_float (const cl_F& x) +{ + floatcase(x + , return decode_float(x); + , return decode_float(x); + , return decode_float(x); + , return decode_float(x); + ); +} diff --git a/src/float/misc/cl_F_digits.cc b/src/float/misc/cl_F_digits.cc new file mode 100644 index 0000000..0e0e033 --- /dev/null +++ b/src/float/misc/cl_F_digits.cc @@ -0,0 +1,29 @@ +// float_digits(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_SF_digits.cc" +#include "cl_FF_digits.cc" +#include "cl_DF_digits.cc" +#include "cl_LF_digits.cc" + +uintL float_digits (const cl_F& x) +{ + floatcase(x + , return float_digits(x); + , return float_digits(x); + , return float_digits(x); + , return float_digits(x); + ); +} diff --git a/src/float/misc/cl_F_epsneg.cc b/src/float/misc/cl_F_epsneg.cc new file mode 100644 index 0000000..c480f0f --- /dev/null +++ b/src/float/misc/cl_F_epsneg.cc @@ -0,0 +1,63 @@ +// float_negative_epsilon(). + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_F_epsneg) + +// Specification. +#include "cl_float.h" + +// Implementation. + +#include "cl_F.h" +#include "cl_SF.h" +#include "cl_FF.h" +#include "cl_DF.h" +#include "cl_LF.h" +#include "cl_LF_impl.h" + +// Bei Floats mit d Bits (incl. Hiddem Bit, also d = ?F_mant_len+1) +// ist ?F_negative_epsilon = 2^(-d-1)*(1+2^(1-d)), +// d.h. Mantisse 10...01, Vorzeichen +. + +static const cl_SF SF_negative_epsilon = + make_SF(0,SF_exp_mid-SF_mant_len-1,bit(SF_mant_len)+1); + +static const cl_FF FF_negative_epsilon = + encode_FF(0,-FF_mant_len-1,bit(FF_mant_len)+1); + +static const cl_DF DF_negative_epsilon = + #if (cl_word_size==64) + encode_DF(0,-DF_mant_len-1,bit(DF_mant_len)+1); + #else + encode_DF(0,-DF_mant_len-1,bit(DF_mant_len-32),1); + #endif + +inline const cl_LF LF_negative_epsilon (uintC len) +{ + var Lfloat erg = allocate_lfloat(len,LF_exp_mid-intDsize*(uintL)len,0); + var uintD* ptr = &TheLfloat(erg)->data[0]; + #if CL_DS_BIG_ENDIAN_P + *ptr++ = bit(intDsize-1); + ptr = clear_loop_up(ptr,len-2); + *ptr = bit(0); + #else + *ptr++ = bit(0); + ptr = clear_loop_up(ptr,len-2); + *ptr = bit(intDsize-1); + #endif + return erg; +} + +const cl_F float_negative_epsilon (cl_float_format_t f) +{ + floatformatcase((uintL)f + , return SF_negative_epsilon; + , return FF_negative_epsilon; + , return DF_negative_epsilon; + , return LF_negative_epsilon(len); + ); +} + +CL_PROVIDE_END(cl_F_epsneg) diff --git a/src/float/misc/cl_F_epspos.cc b/src/float/misc/cl_F_epspos.cc new file mode 100644 index 0000000..c39d106 --- /dev/null +++ b/src/float/misc/cl_F_epspos.cc @@ -0,0 +1,62 @@ +// float_epsilon(). + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_F_epspos) + +// Specification. +#include "cl_float.h" + +// Implementation. + +#include "cl_F.h" +#include "cl_SF.h" +#include "cl_FF.h" +#include "cl_DF.h" +#include "cl_LF.h" +#include "cl_LF_impl.h" + +// Bei Floats mit d Bits (incl. Hiddem Bit, also d = ?F_mant_len+1) +// ist ?F_epsilon = 2^-d*(1+2^(1-d)), d.h. Mantisse 10...01, Vorzeichen +. + +static const cl_SF SF_epsilon = + make_SF(0,SF_exp_mid-SF_mant_len,bit(SF_mant_len)+1); + +static const cl_FF FF_epsilon = + encode_FF(0,-FF_mant_len,bit(FF_mant_len)+1); + +static const cl_DF DF_epsilon = + #if (cl_word_size==64) + encode_DF(0,-DF_mant_len,bit(DF_mant_len)+1); + #else + encode_DF(0,-DF_mant_len,bit(DF_mant_len-32),1); + #endif + +inline const cl_LF LF_epsilon (uintC len) +{ + var Lfloat erg = allocate_lfloat(len,LF_exp_mid+1-intDsize*(uintL)len,0); + var uintD* ptr = &TheLfloat(erg)->data[0]; + #if CL_DS_BIG_ENDIAN_P + *ptr++ = bit(intDsize-1); + ptr = clear_loop_up(ptr,len-2); + *ptr = bit(0); + #else + *ptr++ = bit(0); + ptr = clear_loop_up(ptr,len-2); + *ptr = bit(intDsize-1); + #endif + return erg; +} + +const cl_F float_epsilon (cl_float_format_t f) +{ + floatformatcase((uintL)f + , return SF_epsilon; + , return FF_epsilon; + , return DF_epsilon; + , return LF_epsilon(len); + ); +} + +CL_PROVIDE_END(cl_F_epspos) diff --git a/src/float/misc/cl_F_eqhashcode.cc b/src/float/misc/cl_F_eqhashcode.cc new file mode 100644 index 0000000..ae0b421 --- /dev/null +++ b/src/float/misc/cl_F_eqhashcode.cc @@ -0,0 +1,30 @@ +// cl_F equal_hashcode(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_N.h" +#include "cl_F.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_SF_eqhashcode.cc" +#include "cl_FF_eqhashcode.cc" +#include "cl_DF_eqhashcode.cc" +#include "cl_LF_eqhashcode.cc" + +uint32 cl_equal_hashcode (const cl_F& x) +{ + floatcase(x + , return cl_equal_hashcode(x); + , return cl_equal_hashcode(x); + , return cl_equal_hashcode(x); + , return cl_equal_hashcode(x); + ); +} diff --git a/src/float/misc/cl_F_exponent.cc b/src/float/misc/cl_F_exponent.cc new file mode 100644 index 0000000..490c960 --- /dev/null +++ b/src/float/misc/cl_F_exponent.cc @@ -0,0 +1,29 @@ +// float_exponent(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_SF_exponent.cc" +#include "cl_FF_exponent.cc" +#include "cl_DF_exponent.cc" +#include "cl_LF_exponent.cc" + +sintL float_exponent (const cl_F& x) +{ + floatcase(x + , return float_exponent(x); + , return float_exponent(x); + , return float_exponent(x); + , return float_exponent(x); + ); +} diff --git a/src/float/misc/cl_F_extendsqrt.cc b/src/float/misc/cl_F_extendsqrt.cc new file mode 100644 index 0000000..6faddb6 --- /dev/null +++ b/src/float/misc/cl_F_extendsqrt.cc @@ -0,0 +1,37 @@ +// cl_F_extendsqrt(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F.h" + + +// Implementation. + +#include "cl_SF.h" +#include "cl_LF.h" + +const cl_F cl_F_extendsqrt (const cl_F& x) +{ +// Methode: +// SF -> FF wegen 17+sqrt(17)+2 = 23.2 < 24 +// FF -> DF wegen 24+sqrt(24)+2 = 30.9 < 53 +// DF -> LF(4) wegen 53+sqrt(53)+2 = 62.3 < 64 +// LF(n) -> LF(n+1) für n<=12 wegen 16n+sqrt(16n)+2 < 16(n+1) +// LF(n) -> LF(n+2) für n<=56 wegen 16n+sqrt(16n)+2 < 16(n+2) +// LF(n) -> LF(n+4) für n<=240 +// LF(n) -> LF(n+8) für n<=992 +// LF(n) -> LF(n+16) für n<=4032 +// LF(n) -> LF(n+32) für n<=16256 +// LF(n) -> LF(n+65) für n<=65535 + floatcase(x + , if (SF_mant_len+1<=17) + return cl_SF_to_FF(x); // 17+sqrt(17)+2 = 23.2 < 24 + else + return cl_SF_to_DF(x); // 24+sqrt(24)+2 = 30.9 < 53 + , return cl_FF_to_DF(x); // 24+sqrt(24)+2 = 30.9 < 53 + , return cl_DF_to_LF(x,ceiling(63,intDsize)); // 53+sqrt(53)+2 = 62.3 < 63 + , return extend(x,cl_LF_len_incsqrt(TheLfloat(x)->len)); + ); +} diff --git a/src/float/misc/cl_F_extendsqrtx.cc b/src/float/misc/cl_F_extendsqrtx.cc new file mode 100644 index 0000000..ca9f891 --- /dev/null +++ b/src/float/misc/cl_F_extendsqrtx.cc @@ -0,0 +1,28 @@ +// cl_F_extendsqrtx(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F.h" + + +// Implementation. + +#include "cl_SF.h" +#include "cl_LF.h" + +const cl_F cl_F_extendsqrtx (const cl_F& x) +{ +// Methode: +// SF -> DF wegen 17+sqrt(17)+2+7 = 30.2 < 53 +// FF -> DF wegen 24+sqrt(24)+2+7 = 37.9 < 53 +// DF -> LF(5) wegen 53+sqrt(53)+2+10 = 72.3 < 80 +// LF(n) -> LF(n+i) + floatcase(x + , return cl_SF_to_DF(x); // 17+sqrt(17)+2+7 = 30.2 < 53 + , return cl_FF_to_DF(x); // 24+sqrt(24)+2+7 = 37.9 < 53 + , return cl_DF_to_LF(x,ceiling(73,intDsize)); // 53+sqrt(53)+2+10 = 72.3 < 73 + , return extend(x,cl_LF_len_incsqrtx(TheLfloat(x)->len)); + ); +} diff --git a/src/float/misc/cl_F_idecode.cc b/src/float/misc/cl_F_idecode.cc new file mode 100644 index 0000000..88c2ba9 --- /dev/null +++ b/src/float/misc/cl_F_idecode.cc @@ -0,0 +1,29 @@ +// integer_decode_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_SF_idecode.cc" +#include "cl_FF_idecode.cc" +#include "cl_DF_idecode.cc" +#include "cl_LF_idecode.cc" + +const cl_idecoded_float integer_decode_float (const cl_F& x) +{ + floatcase(x + , return integer_decode_float(x); + , return integer_decode_float(x); + , return integer_decode_float(x); + , return integer_decode_float(x); + ); +} diff --git a/src/float/misc/cl_F_leastneg.cc b/src/float/misc/cl_F_leastneg.cc new file mode 100644 index 0000000..5f31488 --- /dev/null +++ b/src/float/misc/cl_F_leastneg.cc @@ -0,0 +1,58 @@ +// least_negative_float(). + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_F_leastneg) + +// Specification. +#include "cl_float.h" + +// Implementation. + +#include "cl_F.h" +#include "cl_SF.h" +#include "cl_FF.h" +#include "cl_DF.h" +#include "cl_LF.h" +#include "cl_LF_impl.h" + +// Exponent so klein wie möglich, Mantisse 10...0, Vorzeichen -. + +static const cl_SF least_negative_SF = + make_SF(-1,SF_exp_low,bit(SF_mant_len)); + +static const cl_FF least_negative_FF = + encode_FF(-1,FF_exp_low-FF_exp_mid,bit(FF_mant_len)); + +static const cl_DF least_negative_DF = + #if (cl_word_size==64) + encode_DF(-1,DF_exp_low-DF_exp_mid,bit(DF_mant_len)); + #else + encode_DF(-1,DF_exp_low-DF_exp_mid,bit(DF_mant_len-32),0); + #endif + +inline const cl_LF least_negative_LF (uintC len) +{ + var Lfloat erg = allocate_lfloat(len,LF_exp_low,-1); + #if CL_DS_BIG_ENDIAN_P + TheLfloat(erg)->data[0] = bit(intDsize-1); + clear_loop_up(&TheLfloat(erg)->data[1],len-1); + #else + var uintD* ptr = clear_loop_up(&TheLfloat(erg)->data[0],len-1); + *ptr = bit(intDsize-1); + #endif + return erg; +} + +const cl_F least_negative_float (cl_float_format_t f) +{ + floatformatcase((uintL)f + , return least_negative_SF; + , return least_negative_FF; + , return least_negative_DF; + , return least_negative_LF(len); + ); +} + +CL_PROVIDE_END(cl_F_leastneg) diff --git a/src/float/misc/cl_F_leastpos.cc b/src/float/misc/cl_F_leastpos.cc new file mode 100644 index 0000000..4759378 --- /dev/null +++ b/src/float/misc/cl_F_leastpos.cc @@ -0,0 +1,58 @@ +// least_positive_float(). + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_F_leastpos) + +// Specification. +#include "cl_float.h" + +// Implementation. + +#include "cl_F.h" +#include "cl_SF.h" +#include "cl_FF.h" +#include "cl_DF.h" +#include "cl_LF.h" +#include "cl_LF_impl.h" + +// Exponent so klein wie möglich, Mantisse 10...0, Vorzeichen +. + +static const cl_SF least_positive_SF = + make_SF(0,SF_exp_low,bit(SF_mant_len)); + +static const cl_FF least_positive_FF = + encode_FF(0,FF_exp_low-FF_exp_mid,bit(FF_mant_len)); + +static const cl_DF least_positive_DF = + #if (cl_word_size==64) + encode_DF(0,DF_exp_low-DF_exp_mid,bit(DF_mant_len)); + #else + encode_DF(0,DF_exp_low-DF_exp_mid,bit(DF_mant_len-32),0); + #endif + +inline const cl_LF least_positive_LF (uintC len) +{ + var Lfloat erg = allocate_lfloat(len,LF_exp_low,0); + #if CL_DS_BIG_ENDIAN_P + TheLfloat(erg)->data[0] = bit(intDsize-1); + clear_loop_up(&TheLfloat(erg)->data[1],len-1); + #else + var uintD* ptr = clear_loop_up(&TheLfloat(erg)->data[0],len-1); + *ptr = bit(intDsize-1); + #endif + return erg; +} + +const cl_F least_positive_float (cl_float_format_t f) +{ + floatformatcase((uintL)f + , return least_positive_SF; + , return least_positive_FF; + , return least_positive_DF; + , return least_positive_LF(len); + ); +} + +CL_PROVIDE_END(cl_F_leastpos) diff --git a/src/float/misc/cl_F_max.cc b/src/float/misc/cl_F_max.cc new file mode 100644 index 0000000..d5f0fef --- /dev/null +++ b/src/float/misc/cl_F_max.cc @@ -0,0 +1,15 @@ +// max(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +const cl_F max (const cl_F& x, const cl_F& y) +{ + return (x >= y ? x : y); +} diff --git a/src/float/misc/cl_F_min.cc b/src/float/misc/cl_F_min.cc new file mode 100644 index 0000000..4988f7e --- /dev/null +++ b/src/float/misc/cl_F_min.cc @@ -0,0 +1,15 @@ +// min(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +const cl_F min (const cl_F& x, const cl_F& y) +{ + return (x <= y ? x : y); +} diff --git a/src/float/misc/cl_F_mostneg.cc b/src/float/misc/cl_F_mostneg.cc new file mode 100644 index 0000000..066c630 --- /dev/null +++ b/src/float/misc/cl_F_mostneg.cc @@ -0,0 +1,52 @@ +// most_negative_float(). + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_F_mostneg) + +// Specification. +#include "cl_float.h" + +// Implementation. + +#include "cl_F.h" +#include "cl_SF.h" +#include "cl_FF.h" +#include "cl_DF.h" +#include "cl_LF.h" +#include "cl_LF_impl.h" + +// Exponent so groß wie möglich, Mantisse 1...1, Vorzeichen -. + +static const cl_SF most_negative_SF = + make_SF(-1,SF_exp_high,bit(SF_mant_len+1)-1); + +static const cl_FF most_negative_FF = + encode_FF(-1,FF_exp_high-FF_exp_mid,bit(FF_mant_len+1)-1); + +static const cl_DF most_negative_DF = +#if (cl_word_size==64) + encode_DF(-1,DF_exp_high-DF_exp_mid,bit(DF_mant_len+1)-1); +#else + encode_DF(-1,DF_exp_high-DF_exp_mid,bit(DF_mant_len-32+1)-1,bitm(32)-1); +#endif + +inline const cl_LF most_negative_LF (uintC len) +{ + var Lfloat erg = allocate_lfloat(len,LF_exp_high,-1); + fill_loop_up(&TheLfloat(erg)->data[0],len,~(uintD)0); + return erg; +} + +const cl_F most_negative_float (cl_float_format_t f) +{ + floatformatcase((uintL)f + , return most_negative_SF; + , return most_negative_FF; + , return most_negative_DF; + , return most_negative_LF(len); + ); +} + +CL_PROVIDE_END(cl_F_mostneg) diff --git a/src/float/misc/cl_F_mostpos.cc b/src/float/misc/cl_F_mostpos.cc new file mode 100644 index 0000000..45668b4 --- /dev/null +++ b/src/float/misc/cl_F_mostpos.cc @@ -0,0 +1,52 @@ +// most_positive_float(). + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_F_mostpos) + +// Specification. +#include "cl_float.h" + +// Implementation. + +#include "cl_F.h" +#include "cl_SF.h" +#include "cl_FF.h" +#include "cl_DF.h" +#include "cl_LF.h" +#include "cl_LF_impl.h" + +// Exponent so groß wie möglich, Mantisse 1...1, Vorzeichen +. + +static const cl_SF most_positive_SF = + make_SF(0,SF_exp_high,bit(SF_mant_len+1)-1); + +static const cl_FF most_positive_FF = + encode_FF(0,FF_exp_high-FF_exp_mid,bit(FF_mant_len+1)-1); + +static const cl_DF most_positive_DF = +#if (cl_word_size==64) + encode_DF(0,DF_exp_high-DF_exp_mid,bit(DF_mant_len+1)-1); +#else + encode_DF(0,DF_exp_high-DF_exp_mid,bit(DF_mant_len-32+1)-1,bitm(32)-1); +#endif + +inline const cl_LF most_positive_LF (uintC len) +{ + var Lfloat erg = allocate_lfloat(len,LF_exp_high,0); + fill_loop_up(&TheLfloat(erg)->data[0],len,~(uintD)0); + return erg; +} + +const cl_F most_positive_float (cl_float_format_t f) +{ + floatformatcase((uintL)f + , return most_positive_SF; + , return most_positive_FF; + , return most_positive_DF; + , return most_positive_LF(len); + ); +} + +CL_PROVIDE_END(cl_F_mostpos) diff --git a/src/float/misc/cl_F_precision.cc b/src/float/misc/cl_F_precision.cc new file mode 100644 index 0000000..eebe4e6 --- /dev/null +++ b/src/float/misc/cl_F_precision.cc @@ -0,0 +1,29 @@ +// float_precision(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" + +#undef MAYBE_INLINE2 +#define MAYBE_INLINE2 inline +#include "cl_SF_precision.cc" +#include "cl_FF_precision.cc" +#include "cl_DF_precision.cc" +#include "cl_LF_precision.cc" + +uintL float_precision (const cl_F& x) +{ + floatcase(x + , return float_precision(x); + , return float_precision(x); + , return float_precision(x); + , return float_precision(x); + ); +} diff --git a/src/float/misc/cl_F_rational.cc b/src/float/misc/cl_F_rational.cc new file mode 100644 index 0000000..bef429c --- /dev/null +++ b/src/float/misc/cl_F_rational.cc @@ -0,0 +1,49 @@ +// rational(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_integer.h" +#include "cl_RA.h" + +const cl_RA rational (const cl_F& x) +{ + // Methode: + // Der mathematische Wert eines Float ist, wenn INTEGER-DECODE-FLOAT die + // drei Zahlen m,e,s (Mantisse, Exponent, Vorzeichen) liefert, + // = s * 2^e * m. + // n:=m. Falls s<0, setze n:=-m. + // Falls e>=0, ist (ash n e) das Ergebnis, + // sonst ist die rationale Zahl (/ n (ash 1 (- e))) das Ergebnis. + var cl_idecoded_float x_decoded = integer_decode_float(x); + var cl_I& m = x_decoded.mantissa; + var cl_I& e = x_decoded.exponent; + var cl_I& s = x_decoded.sign; + var cl_I n = (!minusp(s) ? m : -m); + if (!minusp(e)) + return ash(n,e); + else { +#if 0 + return I_posI_div_RA(n, ash(1,-e)); +#else // spart ggT + // n /= 0, -e > 0. Kürze mit ggT(n,2^(-e)) = 2^min(ord2(n),-e). + // 0 < -e <= LF_exp_mid-LF_exp_low + intDsize*len < 2^32, + var cl_I minus_e = -e; + var uintL _e = cl_I_to_UL(minus_e); // daher kein Überlauf + var uintL k = ord2(n); + if (k >= _e) + // Kürze mit 2^(-e). + return ash(n,e); + else + // Kürze mit 2^k, 0 <= k < -e. + return I_I_to_RT(ash(n,-(sintL)k), + ash(1,minus_e-UL_to_I(k))); +#endif + } +} diff --git a/src/float/misc/cl_F_shortenrel.cc b/src/float/misc/cl_F_shortenrel.cc new file mode 100644 index 0000000..63118d0 --- /dev/null +++ b/src/float/misc/cl_F_shortenrel.cc @@ -0,0 +1,48 @@ +// cl_F_shortenrelative(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F.h" + + +// Implementation. + +#include "cl_LF.h" +#include "cl_abort.h" + +const cl_F cl_F_shortenrelative (const cl_F& x, const cl_F& y) +{ + // Methode: + // x = 0.0 -> Precision egal, return x. + // ex := float_exponent(x), ey := float_exponent(y). + // dx := float_digits(x), dy := float_digits(y). + // 1 ulp(x) = 2^(ex-dx), 1 ulp(y) = 2^(ey-dy). + // Falls ex-dx < ey-dy, x von Precision dx auf dy-ey+ex verkürzen. + var sintL ey = float_exponent(y); + var sintL dy = float_precision(y); + if (dy==0) // zerop(y) ? + cl_abort(); + var sintL ex = float_exponent(x); + var sintL dx = float_precision(x); + if (dx==0) // zerop(x) ? + return x; + var sintL d = ex - ey; + if (ex>=0 && ey<0 && d<0) // d overflow? + return x; + if (ex<0 && ey>=0 && d>=0) // d underflow? + return cl_F_to_SF(x); + if (d >= dx - dy) + return x; + var uintL new_dx = dy + d; + floatformatcase(new_dx + , return cl_F_to_SF(x); + , return cl_F_to_FF(x); + , return cl_F_to_DF(x); + , if (intDsize*len < (uintL)dx) + return shorten(The(cl_LF)(x),len); + else + return x; + ); +} diff --git a/src/float/misc/cl_F_sign.cc b/src/float/misc/cl_F_sign.cc new file mode 100644 index 0000000..050272d --- /dev/null +++ b/src/float/misc/cl_F_sign.cc @@ -0,0 +1,30 @@ +// float_sign(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" + +#undef MAYBE_INLINE2 +#define MAYBE_INLINE2 inline +#include "cl_SF_sign.cc" +#include "cl_FF_sign.cc" +#include "cl_DF_sign.cc" +#include "cl_LF_sign.cc" + +const cl_F float_sign (const cl_F& x) +{ +// Methode: x>=0 -> Ergebnis 1.0; x<0 -> Ergebnis -1.0 + floatcase(x + , return float_sign(x); + , return float_sign(x); + , return float_sign(x); + , return float_sign(x); + ); +} diff --git a/src/float/misc/cl_F_sign2.cc b/src/float/misc/cl_F_sign2.cc new file mode 100644 index 0000000..edde7de --- /dev/null +++ b/src/float/misc/cl_F_sign2.cc @@ -0,0 +1,22 @@ +// float_sign(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" + +const cl_F float_sign (const cl_F& x, const cl_F& y) +{ + // Methode: + // Falls x<0 xor y<0, Ergebnis (- y), sonst Ergebnis y. + if (minusp(x) != minusp(y)) + return -y; + else + return y; +} diff --git a/src/float/misc/cl_F_signum.cc b/src/float/misc/cl_F_signum.cc new file mode 100644 index 0000000..5d3b945 --- /dev/null +++ b/src/float/misc/cl_F_signum.cc @@ -0,0 +1,29 @@ +// signum(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" + +#undef MAYBE_INLINE2 +#define MAYBE_INLINE2 inline +#include "cl_SF_signum.cc" +#include "cl_FF_signum.cc" +#include "cl_DF_signum.cc" +#include "cl_LF_signum.cc" + +const cl_F signum (const cl_F& x) +{ + floatcase(x + , return signum(x); + , return signum(x); + , return signum(x); + , return signum(x); + ); +} diff --git a/src/float/misc/cl_float_format.cc b/src/float/misc/cl_float_format.cc new file mode 100644 index 0000000..d033ddd --- /dev/null +++ b/src/float/misc/cl_float_format.cc @@ -0,0 +1,27 @@ +// cl_float_format(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +cl_float_format_t cl_float_format (uintL n) +{ +// Methode: +// Mindestens 1+n Dezimalstellen (inklusive Vorkommastelle) +// bedeutet mindestens ceiling((1+n)*ln(10)/ln(2)) Binärstellen. +// ln(10)/ln(2) = 3.321928095 = (binär) 11.01010010011010011110000100101111... +// = (binär) 100 - 0.10101101100101100001111011010001 +// Durch diese Berechnungsmethode wird das Ergebnis sicher >= (1+n)*ln(10)/ln(2) +// sein, evtl. um ein paar Bit zu groß, aber nicht zu klein. + n = 1+n; + return (cl_float_format_t) + ((n << 2) + - (n >> 1) - (n >> 3) - (n >> 5) - (n >> 6) - (n >> 8) + - (n >> 9) - (n >> 12) - (n >> 14) - (n >> 15) + ); +} diff --git a/src/float/output/Makeflags b/src/float/output/Makeflags new file mode 100644 index 0000000..23a5d1e --- /dev/null +++ b/src/float/output/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/float/transcendental -I$(srcdir)/integer -I$(srcdir)/base/string diff --git a/src/float/output/cl_F_aprint.cc b/src/float/output/cl_F_aprint.cc new file mode 100644 index 0000000..5c1e5d3 --- /dev/null +++ b/src/float/output/cl_F_aprint.cc @@ -0,0 +1,17 @@ +// print_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float_io.h" + + +// Implementation. + +#include "cl_output.h" + +void print_float (cl_ostream stream, const cl_print_flags& flags, const cl_F& z) +{ + print_float(stream,(const cl_print_number_flags&)flags,z); +} diff --git a/src/float/output/cl_F_bprint.cc b/src/float/output/cl_F_bprint.cc new file mode 100644 index 0000000..d19e1d5 --- /dev/null +++ b/src/float/output/cl_F_bprint.cc @@ -0,0 +1,17 @@ +// print_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float_io.h" + + +// Implementation. + +#include "cl_output.h" + +void print_float (cl_ostream stream, const cl_print_number_flags& flags, const cl_F& z) +{ + print_float(stream,(const cl_print_real_flags&)flags,z); +} diff --git a/src/float/output/cl_F_cprint.cc b/src/float/output/cl_F_cprint.cc new file mode 100644 index 0000000..28a3bd1 --- /dev/null +++ b/src/float/output/cl_F_cprint.cc @@ -0,0 +1,17 @@ +// print_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float_io.h" + + +// Implementation. + +#include "cl_output.h" + +void print_float (cl_ostream stream, const cl_print_real_flags& flags, const cl_F& z) +{ + print_float(stream,(const cl_print_float_flags&)flags,z); +} diff --git a/src/float/output/cl_F_dprint.cc b/src/float/output/cl_F_dprint.cc new file mode 100644 index 0000000..8159e32 --- /dev/null +++ b/src/float/output/cl_F_dprint.cc @@ -0,0 +1,442 @@ +// print_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float_io.h" + + +// Implementation. + +// Michael Stoll 10.2.1990 - 26.3.1990 +// Bruno Haible 8.9.1990 - 10.9.1990 + +// Grundgedanken: +// Jede Real-Zahl /= 0 repräsentiert ein (offenes) Intervall. Es wird die- +// jenige Dezimalzahl mit möglichst wenig Stellen ausgegeben, die in diesem +// Intervall liegt. +// Um auch große Exponenten zu behandeln, werden Zweier- in Zehnerpotenzen +// erst einmal näherungsweise umgerechnet. Nötigenfalls wird die Rechen- +// genauigkeit erhöht. Hierbei wird von den Long-Floats beliebiger +// Genauigkeit Gebrauch gemacht. + +// Stützt sich auf: +// cl_ln2(digits) liefert ln(2) mit mindestens digits Mantissenbits. +// cl_ln10(digits) liefert ln(10) mit mindestens digits Mantissenbits. +// cl_decimal_string(integer) liefert zu einem Integer >0 +// einen String mit seiner Dezimaldarstellung. +// (substring string start [end]) wie subseq, jedoch für Strings schneller. + +CL_REQUIRE(cl_F_ln2_var) +CL_REQUIRE(cl_F_ln10_var) +#include +#include "cl_output.h" +#include "cl_sstring.h" +#include "cl_float.h" +#include "cl_F.h" +#include "cl_LF.h" +#include "cl_F_tran.h" +#include "cl_rational.h" +#include "cl_integer.h" +#include "cl_integer_io.h" +#include "cl_I.h" + +// Hauptfunktion zur Umwandlung von Floats ins Dezimalsystem: +// Zu einem Float x werden ein String as und drei Integers k,e,s +// berechnet mit folgenden Eigenschaften: +// s = sign(x). +// Falls x/=0, betrachte |x| statt x. Also oBdA x>0. +// Seien x1 und x2 die nächstkleinere bzw. die nächstgrößere Zahl zu x +// vom selben Floating-Point-Format. Die Zahl x repräsentiert somit das +// offene Intervall von (x+x1)/2 bis (x+x2)/2. +// a ist ein Integer >0, mit genau k Dezimalstellen (k>=1), und es gilt +// (x+x1)/2 < a*10^(-k+e) < (x+x2)/2 . +// Dabei ist k minimal, also a nicht durch 10 teilbar. +// Falls x=0: a=0, k=1, e=0. +// as ist die Ziffernfolge von a, der Länge k. + +// typedef +struct cl_decimal_decoded_float { + char * a; + uintL k; + cl_I e; + cl_I s; +// Constructor. + cl_decimal_decoded_float (char * ap, uintL kp, const cl_I& ep, const cl_I& sp) : a(ap), k(kp), e(ep), s(sp) {} +}; + +static const cl_decimal_decoded_float decode_float_decimal (const cl_F& x) +{ + var cl_idecoded_float x_idecoded = integer_decode_float(x); + var cl_I& binmant = x_idecoded.mantissa; + var cl_I& binexpo = x_idecoded.exponent; + var cl_I& sign = x_idecoded.sign; + if (eq(binmant,0)) // x=0 ? + // a=0, k=1, e=0, s=0 + return cl_decimal_decoded_float(cl_sstring("0",1), 1, 0, 0); + // x/=0, also ist sign das Vorzeichen von x und + // |x| = 2^binexpo * float(binmant,x) . Ab jetzt oBdA x>0. + // Also x = 2^binexpo * float(binmant,x) . + var uintL l = integer_length(binmant); // Anzahl der Bits von binmant, >=3 + var cl_I binmant2 = ash(binmant,1); // 2*binmant + var cl_I oben = plus1(binmant2); // obere Intervallgrenze ist + // (x+x2)/2 = 2^(binexpo-1) * oben + var cl_I unten = minus1(binmant2); // untere Intervallgrenze ist + var uintL untenshift = 0; // (x+x1)/2 = 2^(binexpo-1-untenshift) * unten + if (integer_length(unten) == l) { + // Normalerweise integerlength(unten) = 1+integerlength(binmant). + // Hier integerlength(unten) = l = integerlength(binmant), + // also war binmant eine Zweierpotenz. In diesem Fall ist die + // die Toleranz nach oben 1/2 Einheit, aber die Toleranz nach unten + // nur 1/4 Einheit: (x+x1)/2 = 2^(binexpo-2) * (4*binmant-1) + unten = minus1(ash(binmant2,1)); + untenshift = 1; + } + // Bestimme d (ganz) und a1,a2 (ganz, >0) so, daß + // die ganzen a mit (x+x1)/2 < 10^d * a < (x+x2)/2 genau + // die ganzen a mit a1 <= a <= a2 sind und 0 <= a2-a1 < 20 gilt. + // Wandle dazu 2^e := 2^(binexpo-1) ins Dezimalsystem um. + var cl_I e = binexpo - 1; + var bool e_gross = (abs(e) > ash(l,1)); // Ist |e| recht groß, >2*l ? + var uintL g; // Hilfsvariablen für den Fall, daß |e| groß ist + var cl_I f; // + var cl_I zehn_d; // Hilfsvariable 10^|d| für den Fall, daß |e| klein ist + var cl_I d; // Ergebnisvariablen + var cl_I a1; // + var cl_I a2; // + if (e_gross) { // Ist |e| recht groß ? + // Da 2^e nur näherungsweise gehen kann, braucht man Schutzbits. + var uintL h = 16; // Anzahl der Schutzbits, muß >= 3 sein + neue_schutzbits: + // Ziel: 2^e ~= 10^d * f/2^g, wobei 1 <= f/2^g < 10. + g = l + h; // Anzahl der gültigen Bits von f + // Schätze d = floor(e*lg(2)) + // mit Hilfe der Näherungsbrüche von lg(2): + // (0 1/3 3/10 28/93 59/196 146/485 643/2136 4004/13301 + // 8651/28738 12655/42039 21306/70777 76573/254370 97879/325147 + // 1838395/6107016 1936274/6432163 13456039/44699994 + // 15392313/51132157 44240665/146964308 59632978/198096465 + // 103873643/345060773 475127550/1578339557 579001193/1923400330 + // ) + // e>=0 : wähle lg(2) < a/b < lg(2) + 1/e, + // dann ist d <= floor(e*a/b) <= d+1 . + // e<0 : wähle lg(2) - 1/abs(e) < a/b < lg(2), + // dann ist d <= floor(e*a/b) <= d+1 . + // Es ist bekannt, daß abs(e) <= 2^31 + 2^20 . + // Unser d sei := floor(e*a/b)-1. (d /= 0, da abs(e) >= 7.) + d = minus1(minusp(e) + ? (e >= -970 + ? floor1(e*3,10) // Näherungsbruch 3/10 + : floor1(e*21306,70777) // Näherungsbruch 21306/70777 + ) + : (e <= 22000 + ? floor1(e*28,93) // Näherungsbruch 28/93 + : floor1(e*12655,42039) // Näherungsbruch 12655/42039 + ) + ); + // Das wahre d wird durch diese Schätzung entweder getroffen + // oder um 1 unterschätzt. + // Anders ausgedrückt: 0 < e*log(2)-d*log(10) < 2*log(10). + // Nun f/2^g als exp(e*log(2)-d*log(10)) berechnen. + // Da f < 100*2^g < 2^(g+7), sind g+7 Bits relative Genauigkeit + // des Ergebnisses, also g+7 Bits absolute Genauigkeit von + // e*log(2)-d*log(10) nötig. Dazu mit l'=integerlength(e) + // für log(2): g+7+l' Bits abs. Gen., g+7+l' Bits rel. Gen., + // für log(10): g+7+l' Bits abs. Gen., g+7+l'+2 Bist rel. Gen. + var cl_float_format_t gen = (cl_float_format_t)(g + integer_length(e) + 9); // Genauigkeit + var cl_F f2g = exp(The(cl_F)(e * cl_ln2(gen)) - The(cl_F)(d * cl_ln10(gen))); // f/2^g + // Das so berechnete f/2^g ist >1, <100. + // Mit 2^g multiplizieren und auf eine ganze Zahl runden: + f = round1(scale_float(f2g,g)); // liefert f + // Eventuell f und d korrigieren: + if (f >= ash(10,g)) // f >= 10*2^g ? + { f = floor1(f,10); d = d+1; } + // Nun ist 2^e ~= 10^d * f/2^g, wobei 1 <= f/2^g < 10 und + // f ein Integer ist, der um höchstens 1 vom wahren Wert abweicht: + // 10^d * (f-1)/2^g < 2^e < 10^d * (f+1)/2^g + // Wir verkleinern nun das offene Intervall + // von (x+x1)/2 = 2^(binexpo-1-untenshift) * unten + // bis (x+x2)/2 = 2^(binexpo-1) * oben + // zu einem abgeschlossenen Intervall + // von 10^d * (f+1)/2^(g+untenshift) * unten + // bis 10^d * (f-1)/2^g * oben + // und suchen darin Zahlen der Form 10^d * a mit ganzem a. + // Wegen oben - unten/2^untenshift >= 3/2 + // und oben + unten/2^untenshift <= 4*binmant+1 < 2^(l+2) <= 2^(g-1) + // ist die Intervall-Länge + // = 10^d * ((f-1)*oben - (f+1)*unten/2^untenshift) / 2^g + // = 10^d * ( f * (oben - unten/2^untenshift) + // - (oben + unten/2^untenshift) ) / 2^g + // >= 10^d * (2^g * 3/2 - 2^(g-1)) / 2^g + // = 10^d * (3/2 - 2^(-1)) = 10^d + // und daher gibt es in dem Intervall mindestens eine Zahl + // dieser Form. + // Die Zahlen der Form 10^d * a in diesem Intervall sind die + // mit a1 <= a <= a2, wobei a2 = floor((f-1)*oben/2^g) und + // a1 = ceiling((f+1)*unten/2^(g+untenshift)) + // = floor(((f+1)*unten-1)/2^(g+untenshift))+1 . + // Wir haben eben gesehen, daß a1 <= a2 sein muß. + a1 = plus1(ash(minus1((f+1)*unten),-(g+untenshift))); + a2 = ash((f-1)*oben,-g); + // Wir können auch das offene Intervall + // von (x+x1)/2 = 2^(binexpo-1-untenshift) * unten + // bis (x+x2)/2 = 2^(binexpo-1) * oben + // in das (abgeschlossene) Intervall + // von 10^d * (f-1)/2^(g+untenshift) * unten + // bis 10^d * (f+1)/2^g * oben + // einschachteln. Hierin sind die Zahlen der Form 10^d * a + // die mit a1' <= a <= a2', wobei a1' <= a1 <= a2 <= a2' ist + // und sich a1' und a2' analog zu a1 und a2 berechnen. + // Da (f-1)*oben/2^g und (f+1)*oben/2^g sich um 2*oben/2^g + // < 2^(l+2-g) < 1 unterscheiden, unterscheiden sich a2 und + // a2' um höchstens 1. + // Ebenso, wenn 'oben' durch 'unten/2^untenshift' ersetzt + // wird: a1' und a1 unterscheiden sich um höchstens 1. + // Ist nun a1' < a1 oder a2 < a2' , so ist die Zweierpotenz- + // Näherung 10^d * f/2^g für 2^e nicht genau genug gewesen, + // und man hat das Ganze mit erhöhtem h zu wiederholen. + // Ausnahme (da hilft auch keine höhere Genauigkeit): + // Wenn die obere oder untere Intervallgrenze (x+x2)/2 bzw. + // (x+x1)/2 selbst die Gestalt 10^d * a mit ganzem a hat. + // Dies testet man so: + // (x+x2)/2 = 2^e * oben == 10^d * a mit ganzem a, wenn + // - für e>=0, (dann 0 <= d <= e): 5^d | oben, + // - für e<0, (dann e <= d < 0): 2^(d-e) | oben, was + // nur für d-e=0 der Fall ist. + // (x+x1)/2 = 2^(e-untenshift) * unten == 10^d * a + // mit ganzem a, wenn + // - für e>0, (dann 0 <= d < e): 5^d | unten, + // - für e<=0, (dann e <= d <= 0): 2^(d-e+untenshift) | unten, + // was nur für d-e+untenshift=0 der Fall ist. + // Da wir es jedoch mit großem |e| zu tun haben, kann dieser + // Ausnahmefall hier gar nicht eintreten! + // Denn im Falle e>=0: Aus e>=2*l und l>=11 folgt + // e >= (l+2)*ln(10)/ln(5) + ln(10)/ln(2), + // d >= e*ln(2)/ln(10)-1 >= (l+2)*ln(2)/ln(5), + // 5^d >= 2^(l+2), + // und wegen 0 < unten < 2^(l+2) und 0 < oben < 2^(l+1) + // sind unten und oben nicht durch 5^d teilbar. + // Und im Falle e<=0: Aus -e>=2*l und l>=6 folgt + // -e >= (l+2)*ln(10)/ln(5), + // d-e >= e*ln(2)/ln(10)-1-e = (1-ln(2)/ln(10))*(-e)-1 + // = (-e)*ln(5)/ln(10)-1 >= l+1, + // 2^(d-e) >= 2^(l+1), + // und wegen 0 < unten < 2^(l+1+untenshift) ist unten nicht + // durch 2^(d-e+untenshift) teilbar, und wegen + // 0 < oben < 2^(l+1) ist oben nicht durch 2^(d-e) teilbar. + { + var cl_I a1prime = plus1(ash(minus1((f-1)*unten),-(g+untenshift))); + if (a1prime < a1) + { h = 2*h; goto neue_schutzbits; } // h verdoppeln und alles wiederholen + var cl_I a2prime = ash((f+1)*oben,-g); + if (a2 < a2prime) + { h = 2*h; goto neue_schutzbits; } // h verdoppeln und alles wiederholen + } + // Jetzt ist a1 der kleinste und a2 der größte Wert, der + // für a möglich ist. + // Wegen oben - unten/2^untenshift <= 2 + // ist die obige Intervall-Länge + // = 10^d * ((f-1)*oben - (f+1)*unten/2^untenshift) / 2^g + // < 10^d * ((f-1)*oben - (f-1)*unten/2^untenshift) / 2^g + // = 10^d * (f-1)/2^g * (oben - unten/2^untenshift) + // < 10^d * 10 * 2, + // also gibt es höchstens 20 mögliche Werte für a. + } else { + // |e| ist recht klein -> man kann 2^e und 10^d exakt ausrechnen + if (!minusp(e)) { + // e >= 0. Schätze d = floor(e*lg(2)) wie oben. + // Es ist e<=2*l<2^21. + d = (e <= 22000 + ? floor1(e*28,93) // Näherungsbruch 28/93 + : floor1(e*4004,13301) // Näherungsbruch 4004/13301 + ); + // Das wahre d wird durch diese Schätzung entweder getroffen + // oder um 1 überschätzt, aber das können wir leicht feststellen. + zehn_d = The(cl_I)(expt(10,d)); // zehn_d = 10^d + if (ash(1,e) < zehn_d) // falls 2^e < 10^d, + { d = d-1; zehn_d = exquo(zehn_d,10); } // Schätzung korrigieren + // Nun ist 10^d <= 2^e < 10^(d+1) und zehn_d = 10^d. + // a1 sei das kleinste ganze a > 2^(e-untenshift) * unten / 10^d, + // a2 sei das größte ganze a < 2^e * oben / 10^d. + // a1 = 1+floor(unten*2^e/(2^untenshift*10^d)), + // a2 = floor((oben*2^e-1)/10^d). + a1 = plus1(floor1(ash(unten,e),ash(zehn_d,untenshift))); + a2 = floor1(minus1(ash(oben,e)),zehn_d); + } else { + // e < 0. Schätze d = floor(e*lg(2)) wie oben. + // Es ist |e|<=2*l<2^21. + d = (e >= -970 + ? floor1(e*3,10) // Näherungsbruch 3/10 + : floor1(e*643,2136) // Näherungsbruch 643/2136 + ); + // Das wahre d wird durch diese Schätzung entweder getroffen + // oder um 1 überschätzt, aber das können wir leicht feststellen. + zehn_d = The(cl_I)(expt(10,-d)); // zehn_d = 10^(-d) + if (integer_length(zehn_d) <= -e) // falls 2^e < 10^d, + { d = d-1; zehn_d = zehn_d*10; } // Schätzung korrigieren + // Nun ist 10^d <= 2^e < 10^(d+1) und zehn_d = 10^(-d). + // a1 sei das kleinste ganze a > 2^(e-untenshift) * unten / 10^d, + // a2 sei das größte ganze a < 2^e * oben / 10^d. + // a1 = 1+floor(unten*10^(-d)/2^(-e+untenshift)), + // a2 = floor((oben*10^(-d)-1)/2^(-e)) + a1 = plus1(ash(unten*zehn_d,e-untenshift)); + a2 = ash(minus1(oben*zehn_d),e); + } + } + // Nun sind die ganzen a mit (x+x1)/2 < 10^d * a < (x+x2)/2 genau + // die ganzen a mit a1 <= a <= a2. Deren gibt es höchstens 20. + // Diese werden in drei Schritten auf einen einzigen reduziert: + // 1. Enthält der Bereich eine durch 10 teilbare Zahl a ? + // ja -> setze a1:=ceiling(a1/10), a2:=floor(a2/10), d:=d+1. + // Danach enthält der Bereich a1 <= a <= a2 höchstens 10 + // mögliche Werte für a. + // 2. Falls jetzt einer der möglichen Werte durch 10 teilbar ist + // (es kann nur noch einen solchen geben), + // wird er gewählt, die anderen vergessen. + // 3. Sonst wird unter allen noch möglichen Werten der zu x + // nächstgelegene gewählt. + var cl_boolean d_shift = cl_false; // Flag, ob im 1. Schritt d incrementiert wurde + var cl_I a; // das ausgewählte a + // 1. + { + var cl_I b1 = ceiling1(a1,10); + var cl_I b2 = floor1(a2,10); + if (b1 <= b2) // noch eine durch 10 teilbare Zahl a ? + { a1 = b1; a2 = b2; d = d+1; d_shift = cl_true; } + else + goto keine_10_mehr; + } + // 2. + a = floor1(a2,10); + if (10*a >= a1) { + // Noch eine durch 10 teilbare Zahl -> durch 10 teilen. + d = d+1; // noch d erhöhen, zehn-d wird nicht mehr gebraucht + // Nun a in einen Dezimalstring umwandeln + // und dann Nullen am Schluß streichen: + var char* as = cl_decimal_string(a); // Ziffernfolge zu a>0 + var uintL las = strlen(as); // Länge der Ziffernfolge + var uintL k = las; // Länge ohne die gestrichenen Nullen am Schluß + var cl_I ee = k+d; // a * 10^d = a * 10^(-k+ee) + while (as[k-1] == '0') // eine 0 am Schluß? + { // ja -> a := a / 10 (wird aber nicht mehr gebraucht), + // d := d+1 (wird aber nicht mehr gebraucht), + k = k-1; as[k] = '\0'; + } + return cl_decimal_decoded_float(as,k,ee,sign); + } + // 3. + keine_10_mehr: + if (a1 == a2) { + // a1=a2 -> keine Frage der Auswahl mehr: + a = a1; + } else { + // a1 zu x nächstgelegenes 10^d * a wählen: + if (e_gross) { + // a = round(f*2*binmant/2^g/(1oder10)) (beliebige Rundung) + // = ceiling(floor(f*2*binmant/(1oder10)/2^(g-1))/2) wählen: + var cl_I temp = f * binmant2; + if (d_shift) { temp = floor1(temp,10); } + a = ash(plus1(ash(temp,1-g)),-1); + } else { + // |e| klein -> analog wie oben a2 berechnet wurde + if (!minusp(e)) { + // e>=0: a = round(2^e*2*binmant/10^d) + if (d_shift) { zehn_d = 10*zehn_d; } + a = round1(ash(binmant2,e),zehn_d); + } else { + // e<0, also war d<0, jetzt (wegen Schritt 1) d<=0. + // a = round(2*binmant*10^(-d)/2^(-e)) + if (d_shift) { zehn_d = floor1(zehn_d,10); } + a = ash(plus1(ash(binmant2*zehn_d,e+1)),-1); + } + } + } + var char* as = cl_decimal_string(a); // Ziffernfolge zu a>0 + var uintL k = strlen(as); + ASSERT(as[k-1] != '0'); + return cl_decimal_decoded_float(as,k,k+d,sign); +} + +// Ausgabefunktion: +void print_float (cl_ostream stream, const cl_print_float_flags& flags, const cl_F& z) +{ + var cl_decimal_decoded_float z_decoded = decode_float_decimal(z); + var char * & mantstring = z_decoded.a; + var uintL& mantlen = z_decoded.k; + var cl_I& expo = z_decoded.e; + var cl_I& sign = z_decoded.s; + // arg in Dezimaldarstellung: +/- 0.mant * 10^expo, wobei + // mant die Mantisse: als Simple-String mantstring mit Länge mantlen, + // expo der Dezimal-Exponent, + // sign das Vorzeichen (-1 oder 0 oder 1). + if (eq(sign,-1)) // z < 0 ? + fprintchar(stream,'-'); + var bool flag = (expo >= -2) && (expo <= 7); // z=0 oder 10^-3 <= |z| < 10^7 ? + // Was ist auszugeben? Fallunterscheidung: + // flag gesetzt -> "fixed-point notation": + // expo <= 0 -> Null, Punkt, -expo Nullen, alle Ziffern + // 0 < expo < mantlen -> + // die ersten expo Ziffern, Punkt, die restlichen Ziffern + // expo >= mantlen -> alle Ziffern, expo-mantlen Nullen, Punkt, Null + // Nach Möglichkeit kein Exponent// wenn nötig, Exponent 0. + // flag gelöscht -> "scientific notation": + // erste Ziffer, Punkt, die restlichen Ziffern, bei mantlen=1 eine Null + // Exponent. + if (flag && !plusp(expo)) { + // "fixed-point notation" mit expo <= 0 + // erst Null und Punkt, dann -expo Nullen, dann alle Ziffern + fprintchar(stream,'0'); + fprintchar(stream,'.'); + for (uintL i = -FN_to_L(expo); i > 0; i--) + fprintchar(stream,'0'); + fprint(stream,mantstring); + expo = 0; // auszugebender Exponent ist 0 + } else { + // "fixed-point notation" mit expo > 0 oder "scientific notation" + var uintL scale = (flag ? FN_to_L(expo) : 1); + // Der Dezimalpunkt wird um scale Stellen nach rechts geschoben, + // d.h. es gibt scale Vorkommastellen. scale > 0. + if (scale < mantlen) { + // erst scale Ziffern, dann Punkt, dann restliche Ziffern: + { for (uintL i = 0; i < scale; i++) + fprintchar(stream,mantstring[i]); + } + fprintchar(stream,'.'); + { for (uintL i = scale; i < mantlen; i++) + fprintchar(stream,mantstring[i]); + } + } else { + // scale>=mantlen -> es bleibt nichts für die Nachkommastellen. + // alle Ziffern, dann scale-mantlen Nullen, dann Punkt und Null + fprint(stream,mantstring); + for (uintL i = mantlen; i < scale; i++) + fprintchar(stream,'0'); + fprintchar(stream,'.'); + fprintchar(stream,'0'); + } + expo = expo - scale; // der auszugebende Exponent ist um scale kleiner. + } + // Nun geht's zum Exponenten: + var char exp_marker; + floattypecase(z + , exp_marker = 's'; + , exp_marker = 'f'; + , exp_marker = 'd'; + , exp_marker = 'L'; + ); + if (!flags.float_readably) { + floatformatcase(flags.default_float_format + , if (exp_marker=='s') { exp_marker = 'E'; } + , if (exp_marker=='f') { exp_marker = 'E'; } + , if (exp_marker=='d') { exp_marker = 'E'; } + , if ((exp_marker=='L') && (len == TheLfloat(z)->len)) { exp_marker = 'E'; } + ); + } + if (!(flag && (exp_marker=='E'))) { // evtl. Exponent ganz weglassen + fprintchar(stream,exp_marker); + print_integer(stream,10,expo); + } + // Fertig. Aufräumen. + cl_free_hook(mantstring); +} diff --git a/src/float/output/cl_F_printb.cc b/src/float/output/cl_F_printb.cc new file mode 100644 index 0000000..fb0b598 --- /dev/null +++ b/src/float/output/cl_F_printb.cc @@ -0,0 +1,42 @@ +// print_float_binary(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float_io.h" + + +// Implementation. + +#include "cl_float.h" +#include "cl_F.h" +#include "cl_integer_io.h" +#include "cl_I.h" + +void print_float_binary (cl_ostream stream, const cl_F& z) +{ +// Vorzeichen, Punkt, Mantisse (binär), (Zweiersystem-)Exponent (dezimal) + cl_idecoded_float m_e_s = integer_decode_float(z); + var cl_I& m = m_e_s.mantissa; + var cl_I& s = m_e_s.sign; + // Vorzeichen ausgeben, falls <0: + if (eq(s,-1)) + fprintchar(stream,'-'); + // Mantisse binär(!) ausgeben: + fprintchar(stream,'.'); + print_integer(stream,2,m); + // Exponent-Marker ausgeben: + { + var char exp_marker; + floattypecase(z + , exp_marker = 's'; + , exp_marker = 'f'; + , exp_marker = 'd'; + , exp_marker = 'L'; + ); + fprintchar(stream,exp_marker); + } + // Exponenten dezimal ausgeben: + print_integer(stream,10,cl_I(float_exponent(z))); +} diff --git a/src/float/random/Makeflags b/src/float/random/Makeflags new file mode 100644 index 0000000..bf12bd2 --- /dev/null +++ b/src/float/random/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/integer -I$(srcdir)/base/random diff --git a/src/float/random/cl_F_random.cc b/src/float/random/cl_F_random.cc new file mode 100644 index 0000000..d37fe65 --- /dev/null +++ b/src/float/random/cl_F_random.cc @@ -0,0 +1,37 @@ +// random_F(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_random_impl.h" +#include "cl_DS.h" +#include "cl_I.h" + +const cl_F random_F (cl_random_state& randomstate, const cl_F& n) +{ + var uintL d = float_digits(n); // d = (float-digits n) > 0 + // Bilde neue UDS mit d Zufallsbits: + CL_ALLOCA_STACK; + var uintL len = ceiling(d,intDsize); + var uintD* MSDptr; + num_stack_alloc_1(len,MSDptr=,); + random_UDS(randomstate,MSDptr,len); // len (>0) Zufallsdigits + // von intDsize*ceiling(d/intDsize) auf d Bits herunterschneiden: + { var uintL dr = d % intDsize; if (dr>0) { mspref(MSDptr,0) &= (bit(dr)-1); } } + // in Integer umwandeln: + var cl_I mant = UDS_to_I(MSDptr,len); + // Bilde Zufalls-Float zwischen 0 und 1 + // = (scale-float (float Zufalls-Integer,d_Bits n) (- d)) : + var cl_F result = scale_float(cl_float(mant,n),-(sintL)d) * n; + // result ist ein Zufalls-Float >=0, <=n. + if (result == n) + // falls (durch Rundung) result=n, durch 0 ersetzen: + { result = cl_float(0,result); } + return result; +} diff --git a/src/float/sfloat/Makeflags b/src/float/sfloat/Makeflags new file mode 100644 index 0000000..944ef25 --- /dev/null +++ b/src/float/sfloat/Makeflags @@ -0,0 +1,3 @@ +# This file contains additional flags for the main Makefile. + +SUBDIR_INCLUDES = -I$(srcdir)/float/sfloat -I$(srcdir)/float -I$(srcdir)/base diff --git a/src/float/sfloat/algebraic/Makeflags b/src/float/sfloat/algebraic/Makeflags new file mode 100644 index 0000000..25e2d20 --- /dev/null +++ b/src/float/sfloat/algebraic/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/sfloat/Makeflags +SUBDIR_INCLUDES += diff --git a/src/float/sfloat/algebraic/cl_SF_sqrt.cc b/src/float/sfloat/algebraic/cl_SF_sqrt.cc new file mode 100644 index 0000000..fbb254b --- /dev/null +++ b/src/float/sfloat/algebraic/cl_SF_sqrt.cc @@ -0,0 +1,64 @@ +// sqrt(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#include "cl_SF.h" +#include "cl_low.h" + +const cl_SF sqrt (const cl_SF& x) +{ +// Methode: +// x = 0.0 -> Ergebnis 0.0 +// Ergebnis-Vorzeichen := positiv, +// Ergebnis-Exponent := ceiling(e/2), +// Ergebnis-Mantisse: +// Bilde aus [1,m15,...,m0,(19 Nullbits)] bei geradem e, +// aus [0,1,m15,...,m0,(18 Nullbits)] bei ungeradem e +// die Ganzzahl-Wurzel, eine 18-Bit-Zahl mit einer führenden 1. +// Runde das letzte Bit weg: +// Bit 0 = 0 -> abrunden, +// Bit 0 = 1 und Wurzel exakt -> round-to-even, +// Bit 0 = 1 und Rest >0 -> aufrunden. +// Dabei um ein Bit nach rechts schieben. +// Bei Aufrundung auf 2^17 (rounding overflow) Mantisse um 1 Bit nach rechts +// schieben und Exponent incrementieren. + // x entpacken: + var sintL exp; + var uint32 mant; + SF_decode(x, { return x; }, ,exp=,mant=); + // Um die 64-Bit-Ganzzahl-Wurzel ausnutzen zu können, fügen wir beim + // Radikanden 46 bzw. 47 statt 18 bzw. 19 Nullbits an. + if (exp & bit(0)) + // e ungerade + { mant = mant << (31-(SF_mant_len+1)); exp = exp+1; } + else + // e gerade + { mant = mant << (32-(SF_mant_len+1)); } + exp = exp >> 1; // exp := exp/2 + var bool exactp; + isqrt_64_32(mant,0, mant=,exactp=); // mant := isqrt(mant*2^32), eine 32-Bit-Zahl + // Die hinteren 31-SF_mant_len Bits wegrunden: + if ( ((mant & bit(30-SF_mant_len)) ==0) // Bit 14 =0 -> abrunden + || ( ((mant & (bit(30-SF_mant_len)-1)) ==0) // Bit 14 =1 und Bits 13..0 >0 -> aufrunden + && exactp // Bit 14 =1 und Bits 13..0 =0, aber Rest -> aufrunden + // round-to-even, je nach Bit 15 : + && ((mant & bit(31-SF_mant_len)) ==0) + ) ) + // abrunden + { mant = mant >> (31-SF_mant_len); } + else + // aufrunden + { mant = mant >> (31-SF_mant_len); + mant += 1; + if (mant >= bit(SF_mant_len+1)) // rounding overflow? + { mant = mant>>1; exp = exp+1; } + } + return encode_SF(0,exp,mant); +} diff --git a/src/float/sfloat/cl_SF.h b/src/float/sfloat/cl_SF.h new file mode 100644 index 0000000..f871d56 --- /dev/null +++ b/src/float/sfloat/cl_SF.h @@ -0,0 +1,133 @@ +// cl_SF internals + +#ifndef _CL_SF_H +#define _CL_SF_H + +#include "cl_number.h" +#include "cl_F.h" + +// The immediate word contains: +// |..|.......|..........................|....| +// sign exponent mantissa tag + + #define SF_value_shift 7 // could also be = cl_value_shift + #define SF_exp_len 8 // number of bits in the exponent + #define SF_mant_len 16 // number of bits in the mantissa + // (excluding the hidden bit) + #define SF_mant_hiddenbit 1 // yes, we have a hidden bit representation + // (this is hardwired in some of the code) + #define SF_exp_low 1 // minimum exponent + #define SF_exp_mid bit(SF_exp_len-1) // exponent bias + #define SF_exp_high (bit(SF_exp_len)-1) // maximum exponent + #define SF_exp_shift (SF_mant_len+SF_mant_shift) // lowest exponent bit + #define SF_mant_shift SF_value_shift // lowest mantissa bit + #define SF_sign_shift (cl_word_size - 1) + +// Builds a float from the immediate word. +inline cl_SF::cl_SF (struct cl_sfloat * null, cl_uint w) + : cl_F ((cl_private_thing) w) { unused null; } +inline const cl_SF cl_SF_from_word (cl_uint word) +{ + return cl_SF((struct cl_sfloat *) 0, word); +} + +// Builds a float word from sign (0 or -1), exponent and mantissa. +inline cl_uint make_SF_word (cl_sint sign, unsigned int exp, cl_uint mant) +{ + return (sign & ((cl_uint)1 << SF_sign_shift)) + | (exp << SF_exp_shift) + #if SF_mant_hiddenbit + | ((mant & (bit(SF_mant_len)-1)) << SF_mant_shift) + #else + | (mant << SF_mant_shift) + #endif + | (cl_SF_tag << cl_tag_shift); +} + +// Builds a float from sign (0 or -1), exponent and mantissa. +inline const cl_SF make_SF (cl_sint sign, unsigned int exp, cl_uint mant) +{ + return cl_SF_from_word(make_SF_word(sign,exp,mant)); +} + +// Short Float 0.0 + #define SF_0 make_SF(0,0,0) +// Short Float 1.0 + #define SF_1 make_SF(0,SF_exp_mid+1,bit(SF_mant_len)) +// Short Float -1.0 + #define SF_minus1 make_SF(-1,SF_exp_mid+1,bit(SF_mant_len)) + + +// Entpacken eines Short-Float: +// SF_decode(obj, zero_statement, sign=,exp=,mant=); +// zerlegt ein Short-Float obj. +// Ist obj=0.0, wird zero_statement ausgeführt. +// Sonst: cl_signean sign = Vorzeichen (0 = +, -1 = -), +// sintL exp = Exponent (vorzeichenbehaftet), +// uintL mant = Mantisse (>= 2^SF_mant_len, < 2^(SF_mant_len+1)) +inline uintL SF_uexp (const cl_SF& x) +{ + return (x.word >> SF_exp_shift) & (bit(SF_exp_len)-1); +} +inline cl_signean SF_sign (const cl_SF& x) +{ + return ((cl_sint)x.word << (cl_word_size-1 - SF_sign_shift)) >> (cl_word_size-1); +} +inline uintL SF_mant (const cl_SF& x) +{ + return + #if SF_mant_hiddenbit + bit(SF_mant_len) | + #endif + ((uintL)(x.word >> SF_mant_shift) & (bit(SF_mant_len)-1)); +} +#define SF_decode(_x, zero_statement, sign_zuweisung,exp_zuweisung,mant_zuweisung) \ + { var uintL uexp = SF_uexp(_x); \ + if (uexp==0) \ + { zero_statement } /* e=0 -> Zahl 0.0 */ \ + else \ + { exp_zuweisung (sintL)(uexp - SF_exp_mid); /* Exponent */ \ + unused (sign_zuweisung SF_sign(_x)); /* Vorzeichen */\ + mant_zuweisung SF_mant(_x); /* Mantisse */ \ + } } + +// Einpacken eines Short-Float: +// encode_SF(sign,exp,mant) +// liefert ein Short-Float. +// > cl_signean sign: Vorzeichen, 0 für +, -1 für negativ. +// > sintL exp: Exponent +// > uintL mant: Mantisse, sollte >= 2^SF_mant_len und < 2^(SF_mant_len+1) sein. +// < object ergebnis: ein Short-Float +// Der Exponent wird auf Überlauf/Unterlauf getestet. +inline const cl_SF encode_SF (cl_signean sign, sintL exp, uintL mant) +{ + if (exp < (sintL)(SF_exp_low-SF_exp_mid)) + { if (underflow_allowed()) + { cl_error_floating_point_underflow(); } + else + { return SF_0; } + } + else + if (exp > (sintL)(SF_exp_high-SF_exp_mid)) + { cl_error_floating_point_overflow(); } + else + return make_SF(sign, exp+SF_exp_mid, mant); +} + + +// Liefert zu einem Short-Float x : (futruncate x), ein SF. +// x wird von der 0 weg zur nächsten ganzen Zahl gerundet. +extern const cl_SF futruncate (const cl_SF& x); + +// SF_to_I(x) wandelt ein Short-Float x, das eine ganze Zahl darstellt, +// in ein Integer um. +extern const cl_I cl_SF_to_I (const cl_SF& x); + +// cl_I_to_SF(x) wandelt ein Integer x in ein Short-Float um und rundet dabei. +extern const cl_SF cl_I_to_SF (const cl_I& x); + +// cl_RA_to_SF(x) wandelt eine rationale Zahl x in ein Short-Float um +// und rundet dabei. +extern const cl_SF cl_RA_to_SF (const cl_RA& x); + +#endif /* _CL_SF_H */ diff --git a/src/float/sfloat/division/Makeflags b/src/float/sfloat/division/Makeflags new file mode 100644 index 0000000..7f060ee --- /dev/null +++ b/src/float/sfloat/division/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/sfloat/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/float/sfloat/elem diff --git a/src/float/sfloat/division/cl_SF_ceil22.cc b/src/float/sfloat/division/cl_SF_ceil22.cc new file mode 100644 index 0000000..a9c5bcc --- /dev/null +++ b/src/float/sfloat/division/cl_SF_ceil22.cc @@ -0,0 +1,22 @@ +// ceiling2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#include "cl_SF.h" + +const cl_SF_div_t ceiling2 (const cl_SF& x, const cl_SF& y) +{ +// Methode: +// (q,r) := ceiling(x/y). Liefere q und x-y*q = y*r. + var cl_SF_div_t q_r = ceiling2(x/y); + var cl_I& q = q_r.quotient; + var cl_SF& r = q_r.remainder; + return cl_SF_div_t(q,y*r); +} diff --git a/src/float/sfloat/division/cl_SF_fceil.cc b/src/float/sfloat/division/cl_SF_fceil.cc new file mode 100644 index 0000000..ba46ba8 --- /dev/null +++ b/src/float/sfloat/division/cl_SF_fceil.cc @@ -0,0 +1,24 @@ +// fceiling(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#include "cl_SF.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_SF_minusp.cc" + +const cl_SF fceiling (const cl_SF& x) +{ + if (minusp(x)) + return ftruncate(x); + else + return futruncate(x); +} diff --git a/src/float/sfloat/division/cl_SF_ffloor.cc b/src/float/sfloat/division/cl_SF_ffloor.cc new file mode 100644 index 0000000..f381d22 --- /dev/null +++ b/src/float/sfloat/division/cl_SF_ffloor.cc @@ -0,0 +1,24 @@ +// ffloor(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#include "cl_SF.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_SF_minusp.cc" + +const cl_SF ffloor (const cl_SF& x) +{ + if (minusp(x)) + return futruncate(x); + else + return ftruncate(x); +} diff --git a/src/float/sfloat/division/cl_SF_floor22.cc b/src/float/sfloat/division/cl_SF_floor22.cc new file mode 100644 index 0000000..adf10d0 --- /dev/null +++ b/src/float/sfloat/division/cl_SF_floor22.cc @@ -0,0 +1,22 @@ +// floor2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#include "cl_SF.h" + +const cl_SF_div_t floor2 (const cl_SF& x, const cl_SF& y) +{ +// Methode: +// (q,r) := floor(x/y). Liefere q und x-y*q = y*r. + var cl_SF_div_t q_r = floor2(x/y); + var cl_I& q = q_r.quotient; + var cl_SF& r = q_r.remainder; + return cl_SF_div_t(q,y*r); +} diff --git a/src/float/sfloat/division/cl_SF_recip.cc b/src/float/sfloat/division/cl_SF_recip.cc new file mode 100644 index 0000000..508c1cb --- /dev/null +++ b/src/float/sfloat/division/cl_SF_recip.cc @@ -0,0 +1,17 @@ +// recip(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#include "cl_SF.h" + +const cl_SF recip (const cl_SF& x) +{ + return SF_1 / x; +} diff --git a/src/float/sfloat/division/cl_SF_round22.cc b/src/float/sfloat/division/cl_SF_round22.cc new file mode 100644 index 0000000..cc4720b --- /dev/null +++ b/src/float/sfloat/division/cl_SF_round22.cc @@ -0,0 +1,22 @@ +// round2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#include "cl_SF.h" + +const cl_SF_div_t round2 (const cl_SF& x, const cl_SF& y) +{ +// Methode: +// (q,r) := round(x/y). Liefere q und x-y*q = y*r. + var cl_SF_div_t q_r = round2(x/y); + var cl_I& q = q_r.quotient; + var cl_SF& r = q_r.remainder; + return cl_SF_div_t(q,y*r); +} diff --git a/src/float/sfloat/division/cl_SF_trunc22.cc b/src/float/sfloat/division/cl_SF_trunc22.cc new file mode 100644 index 0000000..d7737ef --- /dev/null +++ b/src/float/sfloat/division/cl_SF_trunc22.cc @@ -0,0 +1,22 @@ +// truncate2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#include "cl_SF.h" + +const cl_SF_div_t truncate2 (const cl_SF& x, const cl_SF& y) +{ +// Methode: +// (q,r) := truncate(x/y). Liefere q und x-y*q = y*r. + var cl_SF_div_t q_r = truncate2(x/y); + var cl_I& q = q_r.quotient; + var cl_SF& r = q_r.remainder; + return cl_SF_div_t(q,y*r); +} diff --git a/src/float/sfloat/elem/Makeflags b/src/float/sfloat/elem/Makeflags new file mode 100644 index 0000000..830c0f8 --- /dev/null +++ b/src/float/sfloat/elem/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/sfloat/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/rational -I$(srcdir)/integer -I$(srcdir)/base/digitseq -I$(srcdir)/base/digit -Ibase $(GMP_INCLUDES) diff --git a/src/float/sfloat/elem/cl_SF_compare.cc b/src/float/sfloat/elem/cl_SF_compare.cc new file mode 100644 index 0000000..d6c022c --- /dev/null +++ b/src/float/sfloat/elem/cl_SF_compare.cc @@ -0,0 +1,48 @@ +// cl_compare(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_SF_minusp.cc" + +cl_signean cl_compare (const cl_SF& x, const cl_SF& y) +{ +// Methode: +// x und y haben verschiedenes Vorzeichen -> +// x < 0 -> x < y +// x >= 0 -> x > y +// x und y haben gleiches Vorzeichen -> +// x >=0 -> vergleiche x und y (die rechten 24 Bits) +// x <0 -> vergleiche y und x (die rechten 24 Bits) + if (!minusp(y)) + // y>=0 + { if (!minusp(x)) + // y>=0, x>=0 + { if (x.word < y.word) return signean_minus; // x y.word) return signean_plus; // x>y + return signean_null; + } + else + // y>=0, x<0 + { return signean_minus; } // x=0 + { return signean_plus; } // x>y + else + // y<0, x<0 + { if (x.word > y.word) return signean_minus; // |x|>|y| -> x x>y + return signean_null; + } + } +} diff --git a/src/float/sfloat/elem/cl_SF_div.cc b/src/float/sfloat/elem/cl_SF_div.cc new file mode 100644 index 0000000..ca315e1 --- /dev/null +++ b/src/float/sfloat/elem/cl_SF_div.cc @@ -0,0 +1,86 @@ +// binary operator / + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#include "cl_SF.h" +#include "cl_N.h" +#include "cl_low.h" + +const cl_SF operator/ (const cl_SF& x1, const cl_SF& x2) +{ +// Methode: +// x2 = 0.0 -> Error +// x1 = 0.0 -> Ergebnis 0.0 +// Sonst: +// Ergebnis-Vorzeichen = xor der beiden Vorzeichen von x1 und x2 +// Ergebnis-Exponent = Differenz der beiden Exponenten von x1 und x2 +// Ergebnis-Mantisse = Mantisse mant1 / Mantisse mant2, gerundet. +// mant1/mant2 > 1/2, mant1/mant2 < 2; +// nach Rundung mant1/mant2 >=1/2, <=2*mant1<2. +// Bei mant1/mant2 >=1 brauche 16 Nachkommabits, +// bei mant1/mant2 <1 brauche 17 Nachkommabits. +// Fürs Runden: brauche ein Rundungsbit (Rest gibt an, ob exakt). +// Brauche daher insgesamt 18 Nachkommabits von mant1/mant2. +// Dividiere daher (als Unsigned Integers) 2^18*(2^17*mant1) durch (2^17*mant2). +// Falls der Quotient >=2^18 ist, runde die letzten zwei Bits weg und +// erhöhe den Exponenten um 1. +// Falls der Quotient <2^18 ist, runde das letzte Bit weg. Bei rounding +// overflow schiebe um ein weiteres Bit nach rechts, incr. Exponenten. + // x1,x2 entpacken: + var cl_signean sign1; + var sintL exp1; + var uintL mant1; + var cl_signean sign2; + var sintL exp2; + var uintL mant2; + SF_decode(x2, { cl_error_division_by_0(); }, sign2=,exp2=,mant2=); + SF_decode(x1, { return x1; }, sign1=,exp1=,mant1=); + exp1 = exp1 - exp2; // Differenz der Exponenten + sign1 = sign1 ^ sign2; // Ergebnis-Vorzeichen + // Dividiere 2^18*mant1 durch mant2 oder (äquivalent) + // 2^i*2^18*mant1 durch 2^i*mant2 für irgendein i mit 0 <= i <= 32-17 : + var uintL mant; + var uintL rest; + // wähle i = 32-(SF_mant_len+1), also i+(SF_mant_len+2) = 33. + divu_6432_3232(mant1<<1,0, mant2<<(32-(SF_mant_len+1)), mant=,rest=); + if (mant >= bit(SF_mant_len+2)) + // Quotient >=2^18 -> 2 Bits wegrunden + { var uintL rounding_bits = mant & (bit(2)-1); + exp1 += 1; // Exponenten incrementieren + mant = mant >> 2; + if ( (rounding_bits < bit(1)) // 00,01 werden abgerundet + || ( (rounding_bits == bit(1)) // 10 + && (rest == 0) // und genau halbzahlig + && ((mant & bit(0)) ==0) // -> round-to-even + ) ) + // abrunden + {} + else + // aufrunden + { mant += 1; } + } + else + // Quotient <2^18 -> 1 Bit wegrunden + { var uintL rounding_bit = mant & bit(0); + mant = mant >> 1; + if ( (rounding_bit == 0) // 0 wird abgerundet + || ( (rest == 0) // genau halbzahlig + && ((mant & bit(0)) ==0) // -> round-to-even + ) ) + // abrunden + {} + else + // aufrunden + { mant += 1; + if (mant >= bit(SF_mant_len+1)) // rounding overflow? + { mant = mant>>1; exp1 = exp1+1; } + } } + return encode_SF(sign1,exp1,mant); +} diff --git a/src/float/sfloat/elem/cl_SF_from_I.cc b/src/float/sfloat/elem/cl_SF_from_I.cc new file mode 100644 index 0000000..edaa1a5 --- /dev/null +++ b/src/float/sfloat/elem/cl_SF_from_I.cc @@ -0,0 +1,114 @@ +// cl_I_to_SF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_SF.h" + + +// Implementation. + +#include "cl_integer.h" +#include "cl_I.h" +#include "cl_DS.h" + +const cl_SF cl_I_to_SF (const cl_I& x) +{ +// Methode: +// x=0 -> Ergebnis 0.0 +// Merke Vorzeichen von x. +// x:=(abs x) +// Exponent:=(integer-length x) +// Greife die 18 höchstwertigen Bits heraus (angeführt von einer 1). +// Runde das letzte Bit weg: +// Bit 0 = 0 -> abrunden, +// Bit 0 = 1 und Rest =0 -> round-to-even, +// Bit 0 = 1 und Rest >0 -> aufrunden. +// Dabei um ein Bit nach rechts schieben. +// Bei Aufrundung auf 2^17 (rounding overflow) Mantisse um 1 Bit nach rechts +// schieben und Exponent incrementieren. + if (eq(x,0)) { return SF_0; } + var cl_signean sign = -(cl_signean)minusp(x); // Vorzeichen + var cl_I abs_x = (sign==0 ? x : -x); + var uintL exp = integer_length(abs_x); // (integer-length x) + // NDS zu |x|>0 bilden: + var const uintD* MSDptr; + var uintC len; + I_to_NDS_nocopy(abs_x, MSDptr=,len=,,cl_false,); + // MSDptr/len/LSDptr ist die NDS zu x, len>0. + // Führende Digits holen: Brauche SF_mant_len+1 Bits, dazu intDsize + // Bits (die NDS kann mit bis zu intDsize Nullbits anfangen). + // Dann werden diese Bits um (exp mod intDsize) nach rechts geschoben. + var uintD msd = msprefnext(MSDptr); // erstes Digit + #if (intDsize==64) + var uintD msdd = 0; // weiteres Digit + if (--len == 0) goto ok; + msdd = msprefnext(MSDptr); + #else // (intDsize<=32) + var uint32 msdd = 0; // weitere min(len-1,32/intDsize) Digits + #define NEXT_DIGIT(i) \ + { if (--len == 0) goto ok; \ + msdd |= (uint32)msprefnext(MSDptr) << (32-(i+1)*intDsize); \ + } + DOCONSTTIMES(32/intDsize,NEXT_DIGIT); + #undef NEXT_DIGIT + #endif + --len; ok: + #if (intDsize==64) + // Die NDS besteht aus msd, msdd, und len weiteren Digits. + // Das höchste in 2^intDsize*msd+msdd gesetzte Bit ist Bit Nummer + // intDsize-1 + (exp mod intDsize). + var uintL shiftcount = exp % intDsize; + var uint64 mant = // führende 64 Bits + (shiftcount==0 + ? msdd + : ((msd << (64-shiftcount)) | (msdd >> shiftcount)) + ); + // Das höchste in mant gesetzte Bit ist Bit Nummer 63. + if ( ((mant & bit(62-SF_mant_len)) ==0) // Bit 46 =0 -> abrunden + || ( ((mant & (bit(62-SF_mant_len)-1)) ==0) // Bit 46 =1 und Bits 45..0 =0 + && ((msdd & (bit(shiftcount)-1)) ==0) // und weitere Bits aus msdd =0 + && (!test_loop_msp(MSDptr,len)) // und alle weiteren Digits =0 + // round-to-even, je nach Bit 47 : + && ((mant & bit(63-SF_mant_len)) ==0) + ) ) + // abrunden + { mant = mant >> (63-SF_mant_len); } + else + // aufrunden + { mant = mant >> (63-SF_mant_len); + mant += 1; + if (mant >= bit(SF_mant_len+1)) // rounding overflow? + { mant = mant>>1; exp = exp+1; } + } + #else + // Die NDS besteht aus msd, msdd, und len weiteren Digits. + // Das höchste in 2^32*msd+msdd gesetzte Bit ist Bit Nummer + // 31 + (exp mod intDsize). + var uintL shiftcount = exp % intDsize; + var uint32 mant = // führende 32 Bits + (shiftcount==0 + ? msdd + : (((uint32)msd << (32-shiftcount)) | (msdd >> shiftcount)) + ); + // Das höchste in mant gesetzte Bit ist Bit Nummer 31. + if ( ((mant & bit(30-SF_mant_len)) ==0) // Bit 14 =0 -> abrunden + || ( ((mant & (bit(30-SF_mant_len)-1)) ==0) // Bit 14 =1 und Bits 13..0 =0 + && ((msdd & (bit(shiftcount)-1)) ==0) // und weitere Bits aus msdd =0 + && (!test_loop_msp(MSDptr,len)) // und alle weiteren Digits =0 + // round-to-even, je nach Bit 15 : + && ((mant & bit(31-SF_mant_len)) ==0) + ) ) + // abrunden + { mant = mant >> (31-SF_mant_len); } + else + // aufrunden + { mant = mant >> (31-SF_mant_len); + mant += 1; + if (mant >= bit(SF_mant_len+1)) // rounding overflow? + { mant = mant>>1; exp = exp+1; } + } + #endif + return encode_SF(sign,(sintL)exp,mant); +} diff --git a/src/float/sfloat/elem/cl_SF_from_RA.cc b/src/float/sfloat/elem/cl_SF_from_RA.cc new file mode 100644 index 0000000..ef157b2 --- /dev/null +++ b/src/float/sfloat/elem/cl_SF_from_RA.cc @@ -0,0 +1,104 @@ +// cl_RA_to_SF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_SF.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" +#include "cl_I.h" + +const cl_SF cl_RA_to_SF (const cl_RA& x) +{ +// Methode: +// x ganz -> klar. +// x = +/- a/b mit Integers a,b>0: +// Seien n,m so gewählt, daß +// 2^(n-1) <= a < 2^n, 2^(m-1) <= b < 2^m. +// Dann ist 2^(n-m-1) < a/b < 2^(n-m+1). +// Berechne n=(integer-length a) und m=(integer-length b) und +// floor(2^(-n+m+18)*a/b) : +// Bei n-m>=18 dividiere a durch (ash b (n-m-18)), +// bei n-m<18 dividiere (ash a (-n+m+18)) durch b. +// Der erste Wert ist >=2^17, <2^19. +// Falls er >=2^18 ist, runde 2 Bits weg, +// falls er <2^18 ist, runde 1 Bit weg. + if (integerp(x)) { + DeclareType(cl_I,x); + return cl_I_to_SF(x); + } + { // x Ratio + DeclareType(cl_RT,x); + var cl_I a = numerator(x); // +/- a + var const cl_I& b = denominator(x); // b + var cl_signean sign = -(cl_signean)minusp(a); // Vorzeichen + if (!(sign==0)) { a = -a; } // Betrag nehmen, liefert a + var sintL lendiff = (sintL)integer_length(a) // (integer-length a) + - (sintL)integer_length(b); // (integer-length b) + if (lendiff > SF_exp_high-SF_exp_mid) // Exponent >= n-m > Obergrenze ? + { cl_error_floating_point_overflow(); } // -> Overflow + if (lendiff < SF_exp_low-SF_exp_mid-2) // Exponent <= n-m+2 < Untergrenze ? + { if (underflow_allowed()) + { cl_error_floating_point_underflow(); } // -> Underflow + else + { return SF_0; } + } + var cl_I zaehler; + var cl_I nenner; + if (lendiff >= SF_mant_len+2) + // n-m-18>=0 + { nenner = ash(b,lendiff - (SF_mant_len+2)); // (ash b n-m-18) + zaehler = a; // a + } + else + { zaehler = ash(a,(SF_mant_len+2) - lendiff); // (ash a -n+m+18) + nenner = b; // b + } + // Division zaehler/nenner durchführen: + var cl_I_div_t q_r = cl_divide(zaehler,nenner); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + // 2^17 <= q < 2^19, also ist q Fixnum. + var uint32 mant = FN_to_UL(q); + if (mant >= bit(SF_mant_len+2)) + // 2^18 <= q < 2^19, schiebe um 2 Bits nach rechts + { var uintL rounding_bits = mant & (bit(2)-1); + lendiff = lendiff+1; // Exponent := n-m+1 + mant = mant >> 2; + if ( (rounding_bits < bit(1)) // 00,01 werden abgerundet + || ( (rounding_bits == bit(1)) // 10 + && (eq(r,0)) // und genau halbzahlig (r=0) + && ((mant & bit(0)) ==0) // -> round-to-even + ) ) + // abrunden + goto ab; + else + // aufrunden + goto auf; + } + else + { var uintL rounding_bit = mant & bit(0); + mant = mant >> 1; + if ( (rounding_bit == 0) // 0 wird abgerundet + || ( (eq(r,0)) // genau halbzahlig (r=0) + && ((mant & bit(0)) ==0) // -> round-to-even + ) ) + // abrunden + goto ab; + else + // aufrunden + goto auf; + } + auf: + mant += 1; + if (mant >= bit(SF_mant_len+1)) // rounding overflow? + { mant = mant>>1; lendiff = lendiff+1; } + ab: + // Fertig. + return encode_SF(sign,lendiff,mant); +}} diff --git a/src/float/sfloat/elem/cl_SF_fround.cc b/src/float/sfloat/elem/cl_SF_fround.cc new file mode 100644 index 0000000..1a651d7 --- /dev/null +++ b/src/float/sfloat/elem/cl_SF_fround.cc @@ -0,0 +1,77 @@ +// fround(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#include "cl_SF.h" + +const cl_SF fround (const cl_SF& x) +{ +// Methode: +// x = 0.0 oder e<0 -> Ergebnis 0.0 +// 0<=e<=16 -> letzte (17-e) Bits der Mantisse wegrunden, +// Exponent und Vorzeichen beibehalten. +// e>16 -> Ergebnis x + var uintL uexp = SF_uexp(x); // e + SF_exp_mid + if (uexp < SF_exp_mid) // x = 0.0 oder e<0 ? + { return SF_0; } + else + { if (uexp > SF_exp_mid+SF_mant_len) // e > 16 ? + { return x; } + else + if (uexp > SF_exp_mid+1) // e>1 ? + { var cl_uint bitmask = // Bitmaske: Bit 16-e gesetzt, alle anderen gelöscht + bit(SF_mant_len+SF_mant_shift + SF_exp_mid-uexp); + var cl_uint mask = // Bitmaske: Bits 15-e..0 gesetzt, alle anderen gelöscht + bitmask - bit(SF_mant_shift); + if ( ((x.word & bitmask) ==0) // Bit 16-e =0 -> abrunden + || ( ((x.word & mask) ==0) // Bit 16-e =1 und Bits 15-e..0 >0 -> aufrunden + // round-to-even, je nach Bit 17-e : + && ((x.word & (bitmask<<1)) ==0) + ) ) + // abrunden + { mask |= bitmask; // Bitmaske: Bits 16-e..0 gesetzt, alle anderen gelöscht + return cl_SF_from_word(x.word & ~mask); + } + else + // aufrunden + { return cl_SF_from_word( + (x.word | mask) // alle diese Bits 15-e..0 setzen (Bit 16-e schon gesetzt) + + bit(SF_mant_shift) // letzte Stelle erhöhen, dabei evtl. Exponenten incrementieren + ); + } + } + elif (uexp == SF_exp_mid+1) // e=1 ? + // Wie bei 1 < e <= 16, nur daß Bit 17-e stets gesetzt ist. + { if ((x.word & bit(SF_mant_len+SF_mant_shift-1)) ==0) // Bit 16-e =0 -> abrunden + // abrunden + { return cl_SF_from_word(x.word & ~(bit(SF_mant_len+SF_mant_shift)-bit(SF_mant_shift))); } + else + // aufrunden + { return cl_SF_from_word( + (x.word | (bit(SF_mant_len+SF_mant_shift)-bit(SF_mant_shift))) // alle diese Bits 16-e..0 setzen + + bit(SF_mant_shift) // letzte Stelle erhöhen, dabei evtl. Exponenten incrementieren + ); + } + } + else // e=0 ? + // Wie bei 1 < e <= 16, nur daß Bit 16-e stets gesetzt + // und Bit 17-e stets gelöscht ist. + { if ((x.word & (bit(SF_mant_len+SF_mant_shift)-bit(SF_mant_shift))) ==0) + // abrunden von +-0.5 zu 0.0 + { return SF_0; } + else + // aufrunden + { return cl_SF_from_word( + (x.word | (bit(SF_mant_len+SF_mant_shift)-bit(SF_mant_shift))) // alle Bits 15-e..0 setzen + + bit(SF_mant_shift) // letzte Stelle erhöhen, dabei Exponenten incrementieren + ); + } } + } +} diff --git a/src/float/sfloat/elem/cl_SF_ftrunc.cc b/src/float/sfloat/elem/cl_SF_ftrunc.cc new file mode 100644 index 0000000..073b0f6 --- /dev/null +++ b/src/float/sfloat/elem/cl_SF_ftrunc.cc @@ -0,0 +1,34 @@ +// ftruncate(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#include "cl_SF.h" + +const cl_SF ftruncate (const cl_SF& x) +{ +// Methode: +// x = 0.0 oder e<=0 -> Ergebnis 0.0 +// 1<=e<=16 -> letzte (17-e) Bits der Mantisse auf 0 setzen, +// Exponent und Vorzeichen beibehalten +// e>=17 -> Ergebnis x + var uintL uexp = SF_uexp(x); // e + SF_exp_mid + if (uexp <= SF_exp_mid) // 0.0 oder e<=0 ? + { return SF_0; } + else + { if (uexp > SF_exp_mid+SF_mant_len) // e > 16 ? + { return x; } + else + { return cl_SF_from_word( + x.word & // Bitmaske: Bits 16-e..0 gelöscht, alle anderen gesetzt + ~(bit(SF_mant_len+SF_mant_shift + 1+SF_exp_mid-uexp) - bit(SF_mant_shift)) + ); + } + } +} diff --git a/src/float/sfloat/elem/cl_SF_futrunc.cc b/src/float/sfloat/elem/cl_SF_futrunc.cc new file mode 100644 index 0000000..867d992 --- /dev/null +++ b/src/float/sfloat/elem/cl_SF_futrunc.cc @@ -0,0 +1,49 @@ +// futruncate(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_SF.h" + + +// Implementation. + +const cl_SF futruncate (const cl_SF& x) +{ +// Methode: +// x = 0.0 -> Ergebnis 0.0 +// e<=0 -> Ergebnis 1.0 oder -1.0, je nach Vorzeichen von x. +// 1<=e<=16 -> Greife die letzten (17-e) Bits von x heraus. +// Sind sie alle =0 -> Ergebnis x. +// Sonst setze sie alle und erhöhe dann die letzte Stelle um 1. +// Kein Überlauf der 16 Bit -> fertig. +// Sonst (Ergebnis eine Zweierpotenz): Mantisse := .1000...000, +// e:=e+1. (Test auf Überlauf wegen e<=17 überflüssig) +// e>=17 -> Ergebnis x. + var uintL uexp = SF_uexp(x); // e + SF_exp_mid + if (uexp==0) // 0.0 ? + { return x; } + if (uexp <= SF_exp_mid) // e<=0 ? + { // Exponent auf 1, Mantisse auf .1000...000 setzen. + return cl_SF_from_word( + (x.word & ~(bit(SF_exp_len+SF_exp_shift)-bit(SF_exp_shift) + + bit(SF_mant_len+SF_mant_shift)-bit(SF_mant_shift))) + | ((cl_uint)(SF_exp_mid+1) << SF_exp_shift) + | ((cl_uint)0 << SF_mant_shift) + ); + } + else + { if (uexp > SF_exp_mid+SF_mant_len) // e > 16 ? + { return x; } + else + { var cl_uint mask = // Bitmaske: Bits 16-e..0 gesetzt, alle anderen gelöscht + bit(SF_mant_len+SF_mant_shift + 1+SF_exp_mid-uexp) - bit(SF_mant_shift); + if ((x.word & mask)==0) // alle diese Bits =0 ? + { return x; } + return cl_SF_from_word( + (x.word | mask) // alle diese Bits setzen + + bit(SF_mant_shift) // letzte Stelle erhöhen, dabei evtl. Exponenten incrementieren + ); + } } +} diff --git a/src/float/sfloat/elem/cl_SF_minus.cc b/src/float/sfloat/elem/cl_SF_minus.cc new file mode 100644 index 0000000..0447196 --- /dev/null +++ b/src/float/sfloat/elem/cl_SF_minus.cc @@ -0,0 +1,26 @@ +// binary operator - + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#include "cl_SF.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_SF_zerop.cc" + +const cl_SF operator- (const cl_SF& x1, const cl_SF& x2) +{ +// Methode: +// (- x1 x2) = (+ x1 (- x2)) + if (zerop(x2)) + return x1; + else + return x1 + cl_SF_from_word(x2.word ^ bit(SF_sign_shift)); +} diff --git a/src/float/sfloat/elem/cl_SF_minusp.cc b/src/float/sfloat/elem/cl_SF_minusp.cc new file mode 100644 index 0000000..900519d --- /dev/null +++ b/src/float/sfloat/elem/cl_SF_minusp.cc @@ -0,0 +1,18 @@ +// minusp(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#include "cl_SF.h" + +MAYBE_INLINE +cl_boolean minusp (const cl_SF& x) +{ + return (cl_boolean) ((x.word & bit(SF_sign_shift)) != 0); +} diff --git a/src/float/sfloat/elem/cl_SF_mul.cc b/src/float/sfloat/elem/cl_SF_mul.cc new file mode 100644 index 0000000..3e5556d --- /dev/null +++ b/src/float/sfloat/elem/cl_SF_mul.cc @@ -0,0 +1,96 @@ +// binary operator * + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#include "cl_SF.h" +#include "cl_low.h" + +const cl_SF operator* (const cl_SF& x1, const cl_SF& x2) +{ +// Methode: +// Falls x1=0.0 oder x2=0.0 -> Ergebnis 0.0 +// Sonst: Ergebnis-Vorzeichen = VZ von x1 xor VZ von x2. +// Ergebnis-Exponent = Summe der Exponenten von x1 und x2. +// Ergebnis-Mantisse = Produkt der Mantissen von x1 und x2, gerundet: +// 2^-17 * (2^16 + m1) * 2^-17 * (2^16 + m2) +// = 2^-34 * (2^32 + 2^16*m1 + 2^16*m2 + m1*m2), +// die Klammer ist >=2^32, <=(2^17-1)^2<2^34 . +// Falls die Klammer >=2^33 ist, um 17 Bit nach rechts schieben und +// runden: Falls Bit 16 Null, abrunden; falls Bit 16 Eins und +// Bits 15..0 alle Null, round-to-even; sonst aufrunden. +// Falls die Klammer <2^33 ist, um 16 Bit nach rechts schieben und +// runden: Falls Bit 15 Null, abrunden; falls Bit 15 Eins und +// Bits 14..0 alle Null, round-to-even; sonst aufrunden. Nach +// Aufrunden: Falls =2^17, um 1 Bit nach rechts schieben. Sonst +// Exponenten um 1 erniedrigen. + // x1,x2 entpacken: + var cl_signean sign1; + var sintL exp1; + var uintL mant1; + var cl_signean sign2; + var sintL exp2; + var uintL mant2; + SF_decode(x1, { return x1; }, sign1=,exp1=,mant1=); + SF_decode(x2, { return x2; }, sign2=,exp2=,mant2=); + exp1 = exp1 + exp2; // Summe der Exponenten + sign1 = sign1 ^ sign2; // Ergebnis-Vorzeichen + var uintL manthi; + var uintL mantlo; + // Mantissen mant1 und mant2 multiplizieren: + #if (SF_mant_len<16) + mantlo = mulu16(mant1,mant2); + manthi = mantlo >> SF_mant_len; + mantlo = mantlo & (bit(SF_mant_len)-1); + #elif (SF_mant_len==16) + manthi = mulu16(low16(mant1),low16(mant2)); + mantlo = low16(manthi); + manthi = (uint32)(high16(manthi)) + (uint32)(low16(mant1)) + mant2; + #else // (SF_mant_len>16) + mulu24(mant1,mant2, manthi=,mantlo=); + manthi = (manthi << (32-SF_mant_len)) | (mantlo >> SF_mant_len); + mantlo = mantlo & (bit(SF_mant_len)-1); + #endif + // Nun ist 2^SF_mant_len * manthi + mantlo = mant1 * mant2. + if (manthi >= bit(SF_mant_len+1)) + // mant1*mant2 >= 2^(2*SF_mant_len+1) + { if ( ((manthi & bit(0)) ==0) // Bit SF_mant_len =0 -> abrunden + || ( (mantlo ==0) // Bit SF_mant_len =1 und Bits SF_mant_len-1..0 >0 -> aufrunden + // round-to-even, je nach Bit SF_mant_len+1 : + && ((manthi & bit(1)) ==0) + ) ) + // abrunden + { manthi = manthi >> 1; goto ab; } + else + // aufrunden + { manthi = manthi >> 1; goto auf; } + } + else + // mant1*mant2 < 2^(2*SF_mant_len+1) + { exp1 = exp1-1; // Exponenten decrementieren + if ( ((mantlo & bit(SF_mant_len-1)) ==0) // Bit SF_mant_len-1 =0 -> abrunden + || ( ((mantlo & (bit(SF_mant_len-1)-1)) ==0) // Bit SF_mant_len-1 =1 und Bits SF_mant_len-2..0 >0 -> aufrunden + // round-to-even, je nach Bit SF_mant_len : + && ((manthi & bit(0)) ==0) + ) ) + // abrunden + goto ab; + else + // aufrunden + goto auf; + } + auf: + manthi = manthi+1; + // Hier ist 2^SF_mant_len <= manthi <= 2^(SF_mant_len+1) + if (manthi >= bit(SF_mant_len+1)) // rounding overflow? + { manthi = manthi>>1; exp1 = exp1+1; } // Shift nach rechts + ab: + // Runden fertig, 2^SF_mant_len <= manthi < 2^(SF_mant_len+1) + return encode_SF(sign1,exp1,manthi); +} diff --git a/src/float/sfloat/elem/cl_SF_plus.cc b/src/float/sfloat/elem/cl_SF_plus.cc new file mode 100644 index 0000000..9e81451 --- /dev/null +++ b/src/float/sfloat/elem/cl_SF_plus.cc @@ -0,0 +1,124 @@ +// binary operator + + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#include "cl_SF.h" +#include "cl_xmacros.h" + +const cl_SF operator+ (const cl_SF& x1, const cl_SF& x2) +{ +// Methode (nach [Knuth, II, Seminumerical Algorithms, Abschnitt 4.2.1., S.200]): +// x1=0.0 -> Ergebnis x2. +// x2=0.0 -> Ergebnis x1. +// Falls e1= e2. +// Falls e1 - e2 >= 16 + 3, Ergebnis x1. +// Schiebe beide Mantissen um 3 Bits nach links (Vorbereitung der Rundung: +// Bei e1-e2=0,1 ist keine Rundung nötig, bei e1-e2>1 ist der Exponent des +// Ergebnisses =e1-1, =e1 oder =e1+1. Brauche daher 1 Schutzbit und zwei +// Rundungsbits: 00 exakt, 01 1.Hälfte, 10 exakte Mitte, 11 2.Hälfte.) +// Schiebe die Mantisse von x2 um e0-e1 Bits nach rechts. (Dabei die Rundung +// ausführen: Bit 0 ist das logische Oder der Bits 0,-1,-2,...) +// Falls x1,x2 selbes Vorzeichen haben: Addiere dieses zur Mantisse von x1. +// Falls x1,x2 verschiedenes Vorzeichen haben: Subtrahiere dieses von der +// Mantisse von x1. <0 -> (Es war e1=e2) Vertausche die Vorzeichen, negiere. +// =0 -> Ergebnis 0.0 +// Exponent ist e1. +// Normalisiere, fertig. + // x1,x2 entpacken: + var cl_signean sign1; + var sintL exp1; + var uintL mant1; + var cl_signean sign2; + var sintL exp2; + var uintL mant2; + SF_decode(x1, { return x2; }, sign1=,exp1=,mant1=); + SF_decode(x2, { return x1; }, sign2=,exp2=,mant2=); + var cl_uint max_x1_x2 = x1.word; + if (exp1 < exp2) + { max_x1_x2 = x2.word; + swap(cl_signean, sign1,sign2); + swap(sintL, exp1 ,exp2 ); + swap(uintL, mant1,mant2); + } + // Nun ist exp1>=exp2. + {var uintL expdiff = exp1 - exp2; // Exponentendifferenz + if (expdiff >= SF_mant_len+3) // >= 16+3 ? + { return cl_SF_from_word(max_x1_x2); } + mant1 = mant1 << 3; mant2 = mant2 << 3; + // Nun 2^(SF_mant_len+3) <= mant1,mant2 < 2^(SF_mant_len+4). + {var uintL mant2_last = mant2 & (bit(expdiff)-1); // letzte expdiff Bits von mant2 + mant2 = mant2 >> expdiff; if (!(mant2_last==0)) { mant2 |= bit(0); } + } + // mant2 = um expdiff Bits nach rechts geschobene und gerundete Mantisse + // von x2. + if ((x1.word ^ x2.word) & bit(SF_sign_shift)) + // verschiedene Vorzeichen -> Mantissen subtrahieren + { if (mant1 > mant2) { mant1 = mant1 - mant2; goto norm_2; } + if (mant1 == mant2) // Ergebnis 0 ? + { return SF_0; } + // negatives Subtraktionsergebnis + mant1 = mant2 - mant1; sign1 = sign2; goto norm_2; + } + else + // gleiche Vorzeichen -> Mantissen addieren + { mant1 = mant1 + mant2; } + // mant1 = Ergebnis-Mantisse >0, sign1 = Ergebnis-Vorzeichen, + // exp1 = Ergebnis-Exponent. + // Außerdem: Bei expdiff=0,1 sind die zwei letzten Bits von mant1 Null, + // bei expdiff>=2 ist mant1 >= 2^(SF_mant_len+2). + // Stets ist mant1 < 2^(SF_mant_len+5). (Daher werden die 2 Rundungsbits + // nachher um höchstens eine Position nach links geschoben werden.) + // [Knuth, S.201, leicht modifiziert: + // N1. m>=1 -> goto N4. + // N2. [Hier m<1] m>=1/2 -> goto N5. + // N3. m:=2*m, e:=e-1, goto N2. + // N4. [Hier 1<=m<2] m:=m/2, e:=e+1. + // N5. [Hier 1/2<=m<1] Runde m auf 17 Bits hinterm Komma. + // Falls hierdurch m=1 geworden, setze m:=m/2, e:=e+1. + // ] + // Bei uns ist m=mant1/2^(SF_mant_len+4), + // ab Schritt N5 ist m=mant1/2^(SF_mant_len+1). + norm_1: // [Knuth, S.201, Schritt N1] + if (mant1 >= bit(SF_mant_len+4)) goto norm_4; + norm_2: // [Knuth, S.201, Schritt N2] + // Hier ist mant1 < 2^(SF_mant_len+4) + if (mant1 >= bit(SF_mant_len+3)) goto norm_5; + // [Knuth, S.201, Schritt N3] + mant1 = mant1 << 1; exp1 = exp1-1; // Mantisse links schieben + goto norm_2; + norm_4: // [Knuth, S.201, Schritt N4] + // Hier ist 2^(SF_mant_len+4) <= mant1 < 2^(SF_mant_len+5) + exp1 = exp1+1; + mant1 = (mant1>>1) | (mant1 & bit(0)); // Mantisse rechts schieben + norm_5: // [Knuth, S.201, Schritt N5] + // Hier ist 2^(SF_mant_len+3) <= mant1 < 2^(SF_mant_len+4) + // Auf SF_mant_len echte Mantissenbits runden, d.h. rechte 3 Bits + // wegrunden, und dabei mant1 um 3 Bits nach rechts schieben: + {var uintL rounding_bits = mant1 & (bit(3)-1); + mant1 = mant1 >> 3; + if ( (rounding_bits < bit(2)) // 000,001,010,011 werden abgerundet + || ( (rounding_bits == bit(2)) // 100 (genau halbzahlig) + && ((mant1 & bit(0)) ==0) // -> round-to-even + ) ) + // abrunden + {} + else + // aufrunden + { mant1 = mant1+1; + if (mant1 >= bit(SF_mant_len+1)) + // Bei Überlauf während der Rundung nochmals rechts schieben + // (Runden ist hier überflüssig): + { mant1 = mant1>>1; exp1 = exp1+1; } // Mantisse rechts schieben + } + }// Runden fertig + return encode_SF(sign1,exp1,mant1); + } +} diff --git a/src/float/sfloat/elem/cl_SF_plusp.cc b/src/float/sfloat/elem/cl_SF_plusp.cc new file mode 100644 index 0000000..7fe1a0c --- /dev/null +++ b/src/float/sfloat/elem/cl_SF_plusp.cc @@ -0,0 +1,28 @@ +// plusp(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#include "cl_SF.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_SF_minusp.cc" +#include "cl_SF_zerop.cc" + +MAYBE_INLINE2 +cl_boolean plusp (const cl_SF& x) +{ + if (minusp(x)) + return cl_false; // x<0 -> nein + elif (zerop(x)) + return cl_false; // x=0 -> nein + else + return cl_true; // sonst ist x>0. +} diff --git a/src/float/sfloat/elem/cl_SF_scale.cc b/src/float/sfloat/elem/cl_SF_scale.cc new file mode 100644 index 0000000..4981e26 --- /dev/null +++ b/src/float/sfloat/elem/cl_SF_scale.cc @@ -0,0 +1,49 @@ +// scale_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#include "cl_SF.h" +#include "cl_F.h" + +const cl_SF scale_float (const cl_SF& x, sintL delta) +{ + // Methode: + // x=0.0 -> x als Ergebnis + // delta muß betragsmäßig <= SF_exp_high-SF_exp_low sein. + // Neues SF mit um delta vergrößertem Exponenten bilden. + // x entpacken: + var cl_signean sign; + var sintL exp; + var uint32 mant; + SF_decode(x, { return x; }, sign=,exp=,mant=); + if (delta >= 0) + // delta>=0 + { var uintL udelta = delta; + if (udelta <= (uintL)(SF_exp_high-SF_exp_low)) + { exp = exp+udelta; + return encode_SF(sign,exp,mant); + } + else + { cl_error_floating_point_overflow(); } + } + else + // delta<0 + { var uintL udelta = -delta; + if (udelta <= (uintL)(SF_exp_high-SF_exp_low)) + { exp = exp-udelta; + return encode_SF(sign,exp,mant); + } + else + if (underflow_allowed()) + { cl_error_floating_point_underflow(); } + else + { return SF_0; } + } +} diff --git a/src/float/sfloat/elem/cl_SF_scale_I.cc b/src/float/sfloat/elem/cl_SF_scale_I.cc new file mode 100644 index 0000000..443c2d7 --- /dev/null +++ b/src/float/sfloat/elem/cl_SF_scale_I.cc @@ -0,0 +1,55 @@ +// scale_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#include "cl_SF.h" +#include "cl_F.h" +#include "cl_I.h" + +const cl_SF scale_float (const cl_SF& x, const cl_I& delta) +{ + // Methode: + // x=0.0 -> x als Ergebnis + // delta muß ein Fixnum betragsmäßig <= SF_exp_high-SF_exp_low sein. + // Neues SF mit um delta vergrößertem Exponenten bilden. + // x entpacken: + var cl_signean sign; + var sintL exp; + var uint32 mant; + SF_decode(x, { return x; }, sign=,exp=,mant=); + if (!minusp(delta)) + // delta>=0 + { var uintL udelta; + if (fixnump(delta) + && ((udelta = FN_to_L(delta)) <= (uintL)(SF_exp_high-SF_exp_low)) + ) + { exp = exp+udelta; + return encode_SF(sign,exp,mant); + } + else + { cl_error_floating_point_overflow(); } + } + else + // delta<0 + { var uintL udelta; + if (fixnump(delta) + && ((udelta = -FN_to_L(delta)) <= (uintL)(SF_exp_high-SF_exp_low)) + && ((cl_value_len+10 + : -(sintL)mant // -mant als Fixnum <0 + ), + exp + ); +} diff --git a/src/float/sfloat/elem/cl_SF_uminus.cc b/src/float/sfloat/elem/cl_SF_uminus.cc new file mode 100644 index 0000000..7887698 --- /dev/null +++ b/src/float/sfloat/elem/cl_SF_uminus.cc @@ -0,0 +1,25 @@ +// unary operator - + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#include "cl_SF.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_SF_zerop.cc" + +const cl_SF operator- (const cl_SF& x) +{ +// Methode: +// Falls x=0.0, fertig. Sonst Vorzeichenbit umdrehen. + if (zerop(x)) + return SF_0; + return cl_SF_from_word(x.word ^ ((cl_uint)1 << SF_sign_shift)); +} diff --git a/src/float/sfloat/elem/cl_SF_zerop.cc b/src/float/sfloat/elem/cl_SF_zerop.cc new file mode 100644 index 0000000..0a876d8 --- /dev/null +++ b/src/float/sfloat/elem/cl_SF_zerop.cc @@ -0,0 +1,18 @@ +// zerop(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#include "cl_SF.h" + +MAYBE_INLINE +cl_boolean zerop (const cl_SF& x) +{ + return (cl_boolean) (x.word == make_SF_word(0,0,0)); +} diff --git a/src/float/sfloat/input/Makeflags b/src/float/sfloat/input/Makeflags new file mode 100644 index 0000000..25e2d20 --- /dev/null +++ b/src/float/sfloat/input/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/sfloat/Makeflags +SUBDIR_INCLUDES += diff --git a/src/float/sfloat/input/cl_SF_from_string.cc b/src/float/sfloat/input/cl_SF_from_string.cc new file mode 100644 index 0000000..6c9767e --- /dev/null +++ b/src/float/sfloat/input/cl_SF_from_string.cc @@ -0,0 +1,27 @@ +// cl_SF (const char *) constructor. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat_class.h" + + +// Implementation. + +#include "cl_sfloat.h" +#include "cl_input.h" +#include "cl_float_io.h" + +cl_read_flags cl_SF_read_flags = { + syntax_sfloat, + lsyntax_all, + 10, + { cl_float_format_sfloat, cl_float_format_lfloat_min, cl_false } +}; + +cl_SF::cl_SF (const char * string) +{ + pointer = as_cl_private_thing( + As(cl_SF)(read_float(cl_SF_read_flags,string,NULL,NULL))); +} diff --git a/src/float/sfloat/misc/Makeflags b/src/float/sfloat/misc/Makeflags new file mode 100644 index 0000000..9799575 --- /dev/null +++ b/src/float/sfloat/misc/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/sfloat/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/float/sfloat/elem -I$(srcdir)/integer -I$(srcdir)/base/digitseq -I$(srcdir)/base/digit -Ibase $(GMP_INCLUDES) diff --git a/src/float/sfloat/misc/cl_SF_abs.cc b/src/float/sfloat/misc/cl_SF_abs.cc new file mode 100644 index 0000000..e65bb4e --- /dev/null +++ b/src/float/sfloat/misc/cl_SF_abs.cc @@ -0,0 +1,20 @@ +// abs(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_SF_minusp.cc" + +const cl_SF abs (const cl_SF& x) +{ +// x<0 -> (- x), x>=0 -> x + if (minusp(x)) return -x; else return x; +} diff --git a/src/float/sfloat/misc/cl_SF_as.cc b/src/float/sfloat/misc/cl_SF_as.cc new file mode 100644 index 0000000..fd02392 --- /dev/null +++ b/src/float/sfloat/misc/cl_SF_as.cc @@ -0,0 +1,29 @@ +// as_cl_SF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#include "cl_N.h" + +inline cl_boolean cl_SF_p (const cl_number& x) +{ + if (!x.pointer_p()) + if (cl_tag((x).word) == cl_SF_tag) + return cl_true; + return cl_false; +} + +const cl_SF& as_cl_SF (const cl_number& x, const char * filename, int line) +{ + if (cl_SF_p(x)) { + DeclareType(cl_SF,x); + return x; + } else + cl_as_error(x,"a short-float number",filename,line); +} diff --git a/src/float/sfloat/misc/cl_SF_class.cc b/src/float/sfloat/misc/cl_SF_class.cc new file mode 100644 index 0000000..f487db9 --- /dev/null +++ b/src/float/sfloat/misc/cl_SF_class.cc @@ -0,0 +1,20 @@ +// cl_class_sfloat. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +cl_class cl_class_sfloat = { + NULL, // destructor not used, since not heap objects + cl_class_flags_subclass_complex | cl_class_flags_subclass_real | cl_class_flags_subclass_float +}; + +AT_INITIALIZATION(ini_class_sfloat) +{ + cl_immediate_classes[cl_SF_tag] = &cl_class_sfloat; +} diff --git a/src/float/sfloat/misc/cl_SF_debug.cc b/src/float/sfloat/misc/cl_SF_debug.cc new file mode 100644 index 0000000..256e8e1 --- /dev/null +++ b/src/float/sfloat/misc/cl_SF_debug.cc @@ -0,0 +1,25 @@ +// cl_SF debugging support. + +// General includes. +#include "cl_sysdep.h" + +// Specification. + + +// Implementation. + +#include "cl_sfloat.h" +#include "cl_io.h" +#include "cl_float_io.h" + +static void dprint (cl_heap* pointer) +{ + var const cl_SF& obj = *(const cl_SF*)&pointer; + fprint(cl_debugout, "(cl_SF) "); + fprint(cl_debugout, obj); +} +AT_INITIALIZATION(dprint_SF) +{ cl_register_type_printer(cl_class_sfloat,dprint); } + +// This dummy links in this module when requires it. +int cl_SF_debug_module; diff --git a/src/float/sfloat/misc/cl_SF_decode.cc b/src/float/sfloat/misc/cl_SF_decode.cc new file mode 100644 index 0000000..ec78a27 --- /dev/null +++ b/src/float/sfloat/misc/cl_SF_decode.cc @@ -0,0 +1,29 @@ +// decode_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#include "cl_SF.h" +#include "cl_I.h" + +const cl_decoded_sfloat decode_float (const cl_SF& x) +{ + // x entpacken: + var cl_signean sign; + var sintL exp; + var uint32 mant; + SF_decode(x, { return cl_decoded_sfloat(SF_0, 0, SF_1); }, + sign=,exp=,mant= + ); + return cl_decoded_sfloat( + encode_SF(0,0,mant), // (-1)^0 * 2^0 * m erzeugen + L_to_FN(exp), // e als Fixnum + encode_SF(sign,1,bit(SF_mant_len)) // (-1)^s erzeugen + ); +} diff --git a/src/float/sfloat/misc/cl_SF_digits.cc b/src/float/sfloat/misc/cl_SF_digits.cc new file mode 100644 index 0000000..aa92266 --- /dev/null +++ b/src/float/sfloat/misc/cl_SF_digits.cc @@ -0,0 +1,19 @@ +// float_digits(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#include "cl_SF.h" + +MAYBE_INLINE +uintL float_digits (const cl_SF& x) +{ + unused x; + return SF_mant_len+1; // 17 +} diff --git a/src/float/sfloat/misc/cl_SF_eqhashcode.cc b/src/float/sfloat/misc/cl_SF_eqhashcode.cc new file mode 100644 index 0000000..e5fcbe6 --- /dev/null +++ b/src/float/sfloat/misc/cl_SF_eqhashcode.cc @@ -0,0 +1,24 @@ +// cl_SF equal_hashcode(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#include "cl_N.h" +#include "cl_SF.h" + +MAYBE_INLINE +uint32 cl_equal_hashcode (const cl_SF& x) +{ + var cl_signean sign; + var sintL exp; + var uint32 mant; + SF_decode(x, { return 0; }, sign=,exp=,mant=); + var uint32 msd = mant << (32-(SF_mant_len+1)); + return equal_hashcode_low(msd,exp,sign); +} diff --git a/src/float/sfloat/misc/cl_SF_exponent.cc b/src/float/sfloat/misc/cl_SF_exponent.cc new file mode 100644 index 0000000..3717277 --- /dev/null +++ b/src/float/sfloat/misc/cl_SF_exponent.cc @@ -0,0 +1,20 @@ +// float_exponent(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#include "cl_SF.h" + +MAYBE_INLINE +sintL float_exponent (const cl_SF& x) +{ + var uintL uexp = SF_uexp(x); + if (uexp==0) { return 0; } + return (sintL)(uexp - SF_exp_mid); +} diff --git a/src/float/sfloat/misc/cl_SF_idecode.cc b/src/float/sfloat/misc/cl_SF_idecode.cc new file mode 100644 index 0000000..a3b59a5 --- /dev/null +++ b/src/float/sfloat/misc/cl_SF_idecode.cc @@ -0,0 +1,30 @@ +// integer_decode_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#include "cl_SF.h" +#include "cl_I.h" + +MAYBE_INLINE +const cl_idecoded_float integer_decode_float (const cl_SF& x) +{ + // x entpacken: + var cl_signean sign; + var sintL exp; + var uint32 mant; + SF_decode(x, { return cl_idecoded_float(0, 0, 1); }, + sign=,exp=,mant= + ); + return cl_idecoded_float( + L_to_FN(mant), // Mantisse als Fixnum (>0, <2^17) + L_to_FN(exp-(SF_mant_len+1)), // e-17 als Fixnum + (sign>=0 ? cl_I(1) : cl_I(-1)) // (-1)^s erzeugen + ); +} diff --git a/src/float/sfloat/misc/cl_SF_max.cc b/src/float/sfloat/misc/cl_SF_max.cc new file mode 100644 index 0000000..6098870 --- /dev/null +++ b/src/float/sfloat/misc/cl_SF_max.cc @@ -0,0 +1,15 @@ +// max(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +const cl_SF max (const cl_SF& x, const cl_SF& y) +{ + return (x >= y ? x : y); +} diff --git a/src/float/sfloat/misc/cl_SF_min.cc b/src/float/sfloat/misc/cl_SF_min.cc new file mode 100644 index 0000000..fe4ec52 --- /dev/null +++ b/src/float/sfloat/misc/cl_SF_min.cc @@ -0,0 +1,15 @@ +// min(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +const cl_SF min (const cl_SF& x, const cl_SF& y) +{ + return (x <= y ? x : y); +} diff --git a/src/float/sfloat/misc/cl_SF_precision.cc b/src/float/sfloat/misc/cl_SF_precision.cc new file mode 100644 index 0000000..206e6ce --- /dev/null +++ b/src/float/sfloat/misc/cl_SF_precision.cc @@ -0,0 +1,23 @@ +// float_precision(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#include "cl_SF.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_SF_zerop.cc" + +MAYBE_INLINE2 +uintL float_precision (const cl_SF& x) +{ + if (zerop(x)) return 0; + return SF_mant_len+1; // 17 +} diff --git a/src/float/sfloat/misc/cl_SF_sign.cc b/src/float/sfloat/misc/cl_SF_sign.cc new file mode 100644 index 0000000..3a3d0bf --- /dev/null +++ b/src/float/sfloat/misc/cl_SF_sign.cc @@ -0,0 +1,23 @@ +// float_sign(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#include "cl_SF.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_SF_minusp.cc" + +MAYBE_INLINE2 +const cl_SF float_sign (const cl_SF& x) +{ +// Methode: x>=0 -> Ergebnis 1.0; x<0 -> Ergebnis -1.0 + return encode_SF(SF_sign(x),1,bit(SF_mant_len)); +} diff --git a/src/float/sfloat/misc/cl_SF_signum.cc b/src/float/sfloat/misc/cl_SF_signum.cc new file mode 100644 index 0000000..08e294e --- /dev/null +++ b/src/float/sfloat/misc/cl_SF_signum.cc @@ -0,0 +1,25 @@ +// signum(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_sfloat.h" + + +// Implementation. + +#include "cl_SF.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_SF_minusp.cc" +#include "cl_SF_zerop.cc" + +MAYBE_INLINE2 +const cl_SF signum (const cl_SF& x) +{ + if (minusp(x)) { return SF_minus1; } // x<0 -> -1.0 + elif (zerop(x)) { return SF_0; } // x=0 -> 0.0 + else { return SF_1; } // x>0 -> +1.0 +} diff --git a/src/float/transcendental/Makefile.devel b/src/float/transcendental/Makefile.devel new file mode 100644 index 0000000..63641b6 --- /dev/null +++ b/src/float/transcendental/Makefile.devel @@ -0,0 +1,16 @@ +# This is the developer's makefile, not the user's makefile. +# Don't use it unless you know exactly what you do! + + +SRCDIR = ../.. +include $(SRCDIR)/Makerules.devel + + +DATA_HEADERS = cl_F_ln2_var.h cl_F_ln10_var.h cl_F_pi_var.h cl_F_exp1_var.h cl_F_eulerconst_var.h cl_F_catalanconst_var.h + +all : $(DATA_HEADERS) + +$(DATA_HEADERS) : % : %.in $(DIGIT_HEADER) + $(DIGIT_HEADER) < $< > $@ + + diff --git a/src/float/transcendental/Makeflags b/src/float/transcendental/Makeflags new file mode 100644 index 0000000..db8904b --- /dev/null +++ b/src/float/transcendental/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/float/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/float/lfloat/elem -I$(srcdir)/float/lfloat/misc diff --git a/src/float/transcendental/cl_F_atanhx.cc b/src/float/transcendental/cl_F_atanhx.cc new file mode 100644 index 0000000..24131d5 --- /dev/null +++ b/src/float/transcendental/cl_F_atanhx.cc @@ -0,0 +1,185 @@ +// atanhx(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F_tran.h" +#include "cl_F.h" +#include "cl_lfloat.h" +#include "cl_LF.h" + + +// Implementation. + +#include "cl_float.h" +#include "cl_low.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_LF_zerop.cc" +#include "cl_LF_minusp.cc" +#include "cl_LF_exponent.cc" + +// cl_F atanhx (const cl_F& x) +// cl_LF atanhx (const cl_LF& x) +// +// Methode: +// e := Exponent aus (decode-float x), d := (float-digits x) +// Bei x=0.0 oder e<=-d/2 liefere x +// (denn bei e<=-d/2 ist x^2 < 2^(-d), also +// 1 <= atanh(x)/x = 1+x^2/3+x^4/5+... < 1+x^2/2 < 1+2^(-d-1) < 1+2^(-d), +// also ist atanh(x)/x, auf d Bits gerundet, gleich 1.0). +// Bei großem d verwende die Formel ln((1+x)/(1-x))/2 (asymptotisch schneller), +// aber erhöhe die Genauigkeit, so daß beim Bilden von 1+x keine Bits verloren +// gehen. +// Bei e<=-sqrt(d) verwende die Potenzreihe +// atanh(x)/x = sum(j=0..inf,(x^2)^j/(2j+1)): +// a:=x^2, b:=1, i:=1, sum:=0, +// while (/= sum (setq sum (+ sum (/ b i)))) do i:=i+2, b:=b*a. +// Ergebnis x*sum. +// Sonst setze y := x/(1+sqrt(1-x^2)), berechne rekursiv z:=atanh(y) +// und liefere 2*z = (scale-float z 1). +// Diese Rekursion wird entrekursiviert. Statt k mal hintereinander +// x := x/(1+sqrt(1-x^2)) zu bilden, arbeitet man lieber mit den Kehrwerten, +// setzt also x := 1/|x|, dann k mal x := x+sqrt(x^2-1), dann x := +- 1/x. +// Aufwand: asymptotisch d^2.5 . + +const cl_LF atanhx (const cl_LF& x) +{ + if (zerop(x)) + return x; + var uintL actuallen = TheLfloat(x)->len; + var uintL d = float_digits(x); + var sintL e = float_exponent(x); + if (e <= (sintL)(-d)>>1) // e <= -d/2 <==> e <= -ceiling(d/2) + return x; // ja -> x als Ergebnis + if (actuallen >= 34) { + DeclareType(cl_LF,x); + var cl_LF xx = extend(x,TheLfloat(x)->len+ceiling((uintL)(-e),intDsize)); + return cl_float(scale_float(ln((1+xx)/(1-xx)),-1),x); + } + var uintL k = 0; // Rekursionszähler k:=0 + // Bei e <= -1-limit_slope*floor(sqrt(d)) kann die Potenzreihe + // angewandt werden. limit_slope = 1.0 ist schlecht (ca. 15% zu + // schlecht). Ein guter Wert ist: + // für naive1: limit_scope = 0.625 = 5/8, + // für naive2: limit_scope = 0.4 = 13/32. + var uintL sqrt_d = floor(isqrt(d)*13,32); // limit_slope*floor(sqrt(d)) + var cl_LF xx = x; + if (e >= (sintL)(-sqrt_d)) { + // e > -1-limit_slope*floor(sqrt(d)) -> muß |x| verkleinern. + var sintL e_limit = 1+sqrt_d; // 1+limit_slope*floor(sqrt(d)) + xx = recip(abs(xx)); // 1/|x| + do { + // nächstes x nach der Formel x := x+sqrt(x^2 - 1) berechnen: + xx = sqrt(square(xx) + cl_float(-1,xx)) + xx; + k = k+1; + } until (float_exponent(xx) > e_limit); + // Schleifenende mit Exponent(x) > 1+limit_slope*floor(sqrt(d)), + // also x >= 2^(1+limit_slope*floor(sqrt(d))), + // also 1/x <= 2^(-1-limit_slope*floor(sqrt(d))). + // Nun kann die Potenzreihe auf 1/x angewandt werden. + xx = recip(xx); + if (minusp(x)) + xx = - xx; // Vorzeichen wieder rein + } + // Potenzreihe anwenden: + var int i = 1; + var cl_LF a = square(xx); // a = x^2 + var cl_LF b = cl_float(1,xx); // b := (float 1 x) + var cl_LF sum = cl_float(0,xx); // sum := (float 0 x) + if (0) { + // naive1: + // floating-point representation + loop { + var cl_LF new_sum = sum + b/(cl_I)i; // (+ sum (/ b i)) + if (new_sum == sum) // = sum ? + break; // ja -> Potenzreihe abbrechen + sum = new_sum; + b = b*a; + i = i+2; + } + } else { + // naive2: + // floating-point representation with smooth precision reduction + var cl_LF eps = scale_float(b,-(sintL)d-10); + loop { + var cl_LF new_sum = sum + LF_to_LF(b/(cl_I)i,actuallen); // (+ sum (/ b i)) + if (new_sum == sum) // = sum ? + break; // ja -> Potenzreihe abbrechen + sum = new_sum; + b = cl_LF_shortenwith(b,eps); + b = b*a; + i = i+2; + } + } + var cl_LF erg = sum*xx; // sum*x als Ergebnis + return scale_float(erg,k); // wegen Rekursion noch mal 2^k +} +// Bit complexity (N = length(x)): O(log(N)^2*M(N)). + +const cl_F atanhx (const cl_F& x) +{ + if (longfloatp(x)) { + DeclareType(cl_LF,x); + return atanhx(x); + } + if (zerop(x)) + return x; + var uintL d = float_digits(x); + var sintL e = float_exponent(x); + if (e <= (sintL)(-d)>>1) // e <= -d/2 <==> e <= -ceiling(d/2) + return x; // ja -> x als Ergebnis + var uintL k = 0; // Rekursionszähler k:=0 + // Bei e <= -1-limit_slope*floor(sqrt(d)) kann die Potenzreihe + // angewandt werden. limit_slope = 1.0 ist schlecht (ca. 15% zu + // schlecht). Ein guter Wert ist limit_scope = 0.625 = 5/8. + var uintL sqrt_d = floor(isqrt(d)*5,8); // limit_slope*floor(sqrt(d)) + var cl_F xx = x; + if (e >= (sintL)(-sqrt_d)) { + // e > -1-limit_slope*floor(sqrt(d)) -> muß |x| verkleinern. + var sintL e_limit = 1+sqrt_d; // 1+limit_slope*floor(sqrt(d)) + xx = recip(abs(xx)); // 1/|x| + do { + // nächstes x nach der Formel x := x+sqrt(x^2 - 1) berechnen: + xx = sqrt(square(xx) + cl_float(-1,xx)) + xx; + k = k+1; + } until (float_exponent(xx) > e_limit); + // Schleifenende mit Exponent(x) > 1+limit_slope*floor(sqrt(d)), + // also x >= 2^(1+limit_slope*floor(sqrt(d))), + // also 1/x <= 2^(-1-limit_slope*floor(sqrt(d))). + // Nun kann die Potenzreihe auf 1/x angewandt werden. + xx = recip(xx); + if (minusp(x)) + xx = - xx; // Vorzeichen wieder rein + } + // Potenzreihe anwenden: + var int i = 1; + var cl_F a = square(xx); // a = x^2 + var cl_F b = cl_float(1,xx); // b := (float 1 x) + var cl_F sum = cl_float(0,xx); // sum := (float 0 x) + loop { + var cl_F new_sum = sum + b / (cl_I)i; // (+ sum (/ b i)) + if (new_sum == sum) // = sum ? + break; // ja -> Potenzreihe abbrechen + sum = new_sum; + b = b*a; + i = i+2; + } + var cl_F erg = sum*xx; // sum*x als Ergebnis + return scale_float(erg,k); // wegen Rekursion noch mal 2^k +} +// Bit complexity (N = length(x)): O(log(N)^2*M(N)). + +// Timings of the above algorithms, on an i486 33 MHz, running Linux, +// applied to x = sqrt(2)-1 = 0.414... +// N naive1 naive2 use ln +// 10 0.013 0.013 0.015 +// 25 0.064 0.050 0.049 +// 50 0.25 0.018 0.17 +// 100 1.07 0.75 0.64 +// 250 7.6 5.2 2.7 +// 500 35.5 24.2 9.7 +// 1000 168 116 29.6 +// ==> using ln faster for N >= 34. diff --git a/src/float/transcendental/cl_F_atanx.cc b/src/float/transcendental/cl_F_atanx.cc new file mode 100644 index 0000000..8132387 --- /dev/null +++ b/src/float/transcendental/cl_F_atanx.cc @@ -0,0 +1,258 @@ +// atanx(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +#include "cl_float.h" +#include "cl_low.h" +#include "cl_F.h" +#include "cl_lfloat.h" +#include "cl_LF.h" +#include "cl_integer.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_LF_zerop.cc" +#include "cl_LF_minusp.cc" +#include "cl_LF_exponent.cc" + +// cl_F atanx_naive (const cl_F& x) +// cl_LF atanx_naive (const cl_LF& x) +// +// Methode: +// e := Exponent aus (decode-float x), d := (float-digits x) +// Bei x=0.0 oder e<=-d/2 liefere x +// (denn bei e<=-d/2 ist x^2/3 < x^2/2 < 2^(-d)/2 = 2^(-d-1), also +// 1 >= atan(x)/x > 1-x^2/3 > 1-2^(-d-1), +// also ist atan(x)/x, auf d Bits gerundet, gleich 1.0). +// Bei e<=-sqrt(d) verwende die Potenzreihe +// atan(x)/x = sum(j=0..inf,(-x^2)^j/(2j+1)): +// a:=-x^2, b:=1, i:=1, sum:=0, +// while (/= sum (setq sum (+ sum (/ b i)))) do i:=i+2, b:=b*a. +// Ergebnis x*sum. +// Sonst setze y := x/(1+sqrt(1+x^2)), berechne rekursiv z:=atan(y) +// und liefere 2*z = (scale-float z 1). +// Diese Rekursion wird entrekursiviert. Statt k mal hintereinander +// x := x/(1+sqrt(1+x^2)) zu bilden, arbeitet man lieber mit den Kehrwerten, +// setzt also x := 1/|x|, dann k mal x := x+sqrt(x^2+1), dann x := +- 1/x. +// Aufwand: asymptotisch d^2.5 . + +static const cl_LF atanx_naive (const cl_LF& x) +{ + if (zerop(x)) + return x; + var uintL actuallen = TheLfloat(x)->len; + var uintL d = float_digits(x); + var sintL e = float_exponent(x); + if (e <= (sintL)(-d)>>1) // e <= -d/2 <==> e <= -ceiling(d/2) + return x; // ja -> x als Ergebnis + var uintL k = 0; // Rekursionszähler k:=0 + // Bei e <= -1-limit_slope*floor(sqrt(d)) kann die Potenzreihe + // angewandt werden. limit_slope = 1.0 ist schlecht (ca. 20% zu + // schlecht). Ein guter Wert ist: + // Für naive1: limit_scope = 0.5. + // Für naive2: limit_scope = 0.375 (ca. 0.5 für kleine len, 0.35 für + // große len). + var uintL sqrt_d = floor(isqrt(d)*3,8); // limit_slope*floor(sqrt(d)) + var cl_LF xx = x; + if (e >= (sintL)(-sqrt_d)) { + // e > -1-limit_slope*floor(sqrt(d)) -> muß |x| verkleinern. + var sintL e_limit = 1+sqrt_d; // 1+limit_slope*floor(sqrt(d)) + xx = recip(abs(xx)); // 1/|x| + do { + // nächstes x nach der Formel x := x+sqrt(x^2 + 1) berechnen: + xx = sqrt(square(xx) + cl_float(1,xx)) + xx; + k = k+1; + } until (float_exponent(xx) > e_limit); + // Schleifenende mit Exponent(x) > 1+limit_slope*floor(sqrt(d)), + // also x >= 2^(1+limit_slope*floor(sqrt(d))), + // also 1/x <= 2^(-1-limit_slope*floor(sqrt(d))). + // Nun kann die Potenzreihe auf 1/x angewandt werden. + xx = recip(xx); + if (minusp(x)) + xx = - xx; // Vorzeichen wieder rein + } + // Potenzreihe anwenden: + var int i = 1; + var cl_LF a = - square(xx); // a = - x^2 + var cl_LF b = cl_float(1,xx); // b := (float 1 x) + var cl_LF sum = cl_float(0,xx); // sum := (float 0 x) + if (0) { + // naive1: + // floating-point representation + loop { + var cl_LF new_sum = sum + b / (cl_I)i; // (+ sum (/ b i)) + if (new_sum == sum) // = sum ? + break; // ja -> Potenzreihe abbrechen + sum = new_sum; + b = b*a; + i = i+2; + } + } else { + // naive2: + // floating-point representation with smooth precision reduction + var cl_LF eps = scale_float(b,-(sintL)d-10); + loop { + var cl_LF new_sum = sum + LF_to_LF(b/(cl_I)i,actuallen); // (+ sum (/ b i)) + if (new_sum == sum) // = sum ? + break; // ja -> Potenzreihe abbrechen + sum = new_sum; + b = cl_LF_shortenwith(b,eps); + b = b*a; + i = i+2; + } + } + var cl_LF erg = sum*xx; // sum*x als Ergebnis + return scale_float(erg,k); // wegen Rekursion noch mal 2^k +} +// Bit complexity (N = length(x)): O(N^(1/2)*M(N)). + +static const cl_F atanx_naive (const cl_F& x) +{ + if (zerop(x)) + return x; + var uintL d = float_digits(x); + var sintL e = float_exponent(x); + if (e <= (sintL)(-d)>>1) // e <= -d/2 <==> e <= -ceiling(d/2) + return x; // ja -> x als Ergebnis + var uintL k = 0; // Rekursionszähler k:=0 + var uintL sqrt_d = floor(isqrt(d),2); // limit_slope*floor(sqrt(d)) + // Bei e <= -1-limit_slope*floor(sqrt(d)) kann die Potenzreihe + // angewandt werden. limit_slope = 1.0 ist schlecht (ca. 20% zu + // schlecht). Ein guter Wert ist limit_scope = 0.5. + var cl_F xx = x; + if (e >= (sintL)(-sqrt_d)) { + // e > -1-limit_slope*floor(sqrt(d)) -> muß |x| verkleinern. + var sintL e_limit = 1+sqrt_d; // 1+limit_slope*floor(sqrt(d)) + xx = recip(abs(xx)); // 1/|x| + do { + // nächstes x nach der Formel x := x+sqrt(x^2 + 1) berechnen: + xx = sqrt(square(xx) + cl_float(1,xx)) + xx; + k = k+1; + } until (float_exponent(xx) > e_limit); + // Schleifenende mit Exponent(x) > 1+limit_slope*floor(sqrt(d)), + // also x >= 2^(1+limit_slope*floor(sqrt(d))), + // also 1/x <= 2^(-1-limit_slope*floor(sqrt(d))). + // Nun kann die Potenzreihe auf 1/x angewandt werden. + xx = recip(xx); + if (minusp(x)) + xx = - xx; // Vorzeichen wieder rein + } + // Potenzreihe anwenden: + var int i = 1; + var cl_F a = - square(xx); // a = - x^2 + var cl_F b = cl_float(1,xx); // b := (float 1 x) + var cl_F sum = cl_float(0,xx); // sum := (float 0 x) + loop { + var cl_F new_sum = sum + b / (cl_I)i; // (+ sum (/ b i)) + if (new_sum == sum) // = sum ? + break; // ja -> Potenzreihe abbrechen + sum = new_sum; + b = b*a; + i = i+2; + } + var cl_F erg = sum*xx; // sum*x als Ergebnis + return scale_float(erg,k); // wegen Rekursion noch mal 2^k +} +// Bit complexity (N = length(x)): O(N^(1/2)*M(N)). + +static const cl_LF atanx_ratseries (const cl_LF& t) +{ + // Method: + // Based on the same ideas as lnx_ratseries. + // e := exponent of (decode-float t), d := (float-digits t). + // If t=0.0 or e<=-d/2, return t. + // (x,y) := (1/sqrt(1+t^2),t/sqrt(1+t^2)), z := 0. + // Loop + // [(x+i*y)*exp(i*z) is invariant, x>0, sqrt(x^2+y^2)=1] + // e := exponent of (decode-float y), d := (float-digits y). + // If y=0.0 or e<=-d/2, return z+y + // (because if e<=-d/2 then |y|^3/6 < 2^(-d)/2*|y|, and since + // asin(y) = y+y^3/6+..., asin(y) rounded to d bits is = y). + // Choose approximation z' of angle(x+i*y): + // If |y| >= 1/2, set z' = 1/2 * sign(y). + // If |y| < 2^-n with n maximal, set + // z' = truncate(y*2^(2n))/2^(2n). + // Set z := z + z' and x+i*y := (x+i*y)*exp(-i*z'). + var uintC len = TheLfloat(t)->len; + var uintL d = intDsize*(uintL)len; + if (zerop(t) || (float_exponent(t) <= (sintL)(-d)>>1)) + return t; + var cl_LF x = recip(sqrt(cl_I_to_LF(1,len) + square(t))); + var cl_LF y = t*x; + var cl_LF z = cl_I_to_LF(0,len); + loop { + if (zerop(y) || (float_exponent(y) <= (sintL)(-d)>>1)) + break; + var cl_idecoded_float y_ = integer_decode_float(y); + // y = (-1)^sign * 2^exponent * mantissa + var uintL lm = integer_length(y_.mantissa); + var uintL me = cl_I_to_UL(- y_.exponent); + var cl_I p; + var uintL lq; + var cl_boolean last_step = cl_false; + if (lm >= me) { // |y| >= 1/2 ? + p = y_.sign; // 1 or -1 + lq = 1; + } else { + var uintL n = me - lm; // |y| < 2^-n with n maximal + // Set p to the first n bits of |y|: + if (lm > n) { + p = y_.mantissa >> (lm - n); + lq = 2*n; + } else { + p = y_.mantissa; + lq = lm + n; + } + if (minusp(y_.sign)) { p = -p; } + // If 2*n >= lm = intDsize*len, then within our + // precision exp(-i*z')=1-i*z' (because |z'^2| < 2^-lm), + // and we know a priori that the iteration will stop + // after the next big multiplication. This saves one + // big multiplication at the end. + if (2*n >= lm) + last_step = cl_true; + } + z = z + scale_float(cl_I_to_LF(p,len),-(sintL)lq); + if (last_step) + break; + var cl_LF_cos_sin_t cis_z = cl_cossin_aux(-p,lq,len); + var cl_LF new_x = x*cis_z.cos - y*cis_z.sin; + var cl_LF new_y = x*cis_z.sin + y*cis_z.cos; + x = new_x; y = new_y; + } + return z+y; +} +// Bit complexity (N = length(x)): O(log(N)^2*M(N)). + +// Timings of the above algorithms, on an i486 33 MHz, running Linux, +// applied to x = sqrt(2)-1 = 0.414... +// N naive1 naive2 ratseries +// 10 0.013 0.013 0.043 +// 25 0.062 0.048 0.122 +// 50 0.25 0.17 0.34 +// 100 1.06 0.70 1.07 +// 250 7.5 5.0 5.6 +// 500 34.7 23.2 20.0 +// 1000 167 112 65 +// ==> ratseries faster for N >= 325. + +const cl_F atanx (const cl_F& x) +{ + if (longfloatp(x)) { + DeclareType(cl_LF,x); + if (TheLfloat(x)->len >= 325) + return cl_float(atanx_ratseries(extend(x,TheLfloat(x)->len+1)),x); + else + return atanx_naive(x); + } else + return atanx_naive(x); +} +// Bit complexity (N = length(x)): O(log(N)^2*M(N)). + diff --git a/src/float/transcendental/cl_F_catalanconst.cc b/src/float/transcendental/cl_F_catalanconst.cc new file mode 100644 index 0000000..d31b4a3 --- /dev/null +++ b/src/float/transcendental/cl_F_catalanconst.cc @@ -0,0 +1,24 @@ +// cl_catalanconst(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_F_tran.h" +#include "cl_LF.h" + +const cl_F cl_catalanconst (const cl_F& y) +{ + floattypecase(y + , return cl_SF_catalanconst; + , return cl_FF_catalanconst; + , return cl_DF_catalanconst; + , return cl_catalanconst(TheLfloat(y)->len); + ); +} diff --git a/src/float/transcendental/cl_F_catalanconst_def.cc b/src/float/transcendental/cl_F_catalanconst_def.cc new file mode 100644 index 0000000..f427257 --- /dev/null +++ b/src/float/transcendental/cl_F_catalanconst_def.cc @@ -0,0 +1,23 @@ +// cl_catalanconst(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_F_tran.h" + +const cl_F cl_catalanconst (void) +{ + floatformatcase(cl_default_float_format + , return cl_SF_catalanconst; + , return cl_FF_catalanconst; + , return cl_DF_catalanconst; + , return cl_catalanconst(len); + ); +} diff --git a/src/float/transcendental/cl_F_catalanconst_f.cc b/src/float/transcendental/cl_F_catalanconst_f.cc new file mode 100644 index 0000000..3e4d325 --- /dev/null +++ b/src/float/transcendental/cl_F_catalanconst_f.cc @@ -0,0 +1,23 @@ +// cl_catalanconst(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_F_tran.h" + +const cl_F cl_catalanconst (cl_float_format_t f) +{ + floatformatcase((uintL)f + , return cl_SF_catalanconst; + , return cl_FF_catalanconst; + , return cl_DF_catalanconst; + , return cl_catalanconst(len); + ); +} diff --git a/src/float/transcendental/cl_F_catalanconst_var.cc b/src/float/transcendental/cl_F_catalanconst_var.cc new file mode 100644 index 0000000..733bc2e --- /dev/null +++ b/src/float/transcendental/cl_F_catalanconst_var.cc @@ -0,0 +1,33 @@ +// cl_F_catalanconst. + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_F_catalanconst_var) + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +#include "cl_DS.h" +#include "cl_LF.h" +#include "cl_LF_impl.h" +#include "cl_F.h" + +// Mantisse der Catalanschen Konstante : + static const uintD catalanconst_mantisse [64/intDsize] = + #include "cl_F_catalanconst_var.h" + +cl_LF cl_LF_catalanconst = encode_LF_array(0,0,catalanconst_mantisse,64/intDsize); + +// Problem: If someone changes cl_free_hook, the destructor of this +// will call the new hook, passing it some pointer obtained by the old +// cl_malloc_hook. ?? + +const cl_SF cl_SF_catalanconst = cl_LF_to_SF(cl_LF_catalanconst); +const cl_FF cl_FF_catalanconst = cl_LF_to_FF(cl_LF_catalanconst); +const cl_DF cl_DF_catalanconst = cl_LF_to_DF(cl_LF_catalanconst); + +CL_PROVIDE_END(cl_F_catalanconst_var) diff --git a/src/float/transcendental/cl_F_catalanconst_var.h b/src/float/transcendental/cl_F_catalanconst_var.h new file mode 100644 index 0000000..6cfaaf2 --- /dev/null +++ b/src/float/transcendental/cl_F_catalanconst_var.h @@ -0,0 +1,29 @@ +{ +#if CL_DS_BIG_ENDIAN_P + #if (intDsize==8) + D1(0xEA), D1(0x7C), D1(0xB8), D1(0x9F), D1(0x40), D1(0x9A), D1(0xE8), D1(0x45) + #endif + #if (intDsize==16) + D2(0xEA,0x7C), D2(0xB8,0x9F), D2(0x40,0x9A), D2(0xE8,0x45) + #endif + #if (intDsize==32) + D4(0xEA,0x7C,0xB8,0x9F), D4(0x40,0x9A,0xE8,0x45) + #endif + #if (intDsize==64) + D8(0xEA,0x7C,0xB8,0x9F,0x40,0x9A,0xE8,0x45) + #endif +#else + #if (intDsize==8) + D1(0x45), D1(0xE8), D1(0x9A), D1(0x40), D1(0x9F), D1(0xB8), D1(0x7C), D1(0xEA) + #endif + #if (intDsize==16) + D2(0xE8,0x45), D2(0x40,0x9A), D2(0xB8,0x9F), D2(0xEA,0x7C) + #endif + #if (intDsize==32) + D4(0x40,0x9A,0xE8,0x45), D4(0xEA,0x7C,0xB8,0x9F) + #endif + #if (intDsize==64) + D8(0xEA,0x7C,0xB8,0x9F,0x40,0x9A,0xE8,0x45) + #endif +#endif +} ; diff --git a/src/float/transcendental/cl_F_catalanconst_var.h.in b/src/float/transcendental/cl_F_catalanconst_var.h.in new file mode 100644 index 0000000..a560ad0 --- /dev/null +++ b/src/float/transcendental/cl_F_catalanconst_var.h.in @@ -0,0 +1,2 @@ +// Digits of Catalan's constant. + { D(0xEA,0x7C,0xB8,0x9F,) D(0x40,0x9A,0xE8,0x45,) } ; diff --git a/src/float/transcendental/cl_F_cos.cc b/src/float/transcendental/cl_F_cos.cc new file mode 100644 index 0000000..87cf8d5 --- /dev/null +++ b/src/float/transcendental/cl_F_cos.cc @@ -0,0 +1,91 @@ +// cos(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F_tran.h" +#include "cl_F.h" +#include "cl_integer.h" +#include "cl_lfloat.h" +#include "cl_LF.h" + +const cl_F cos (const cl_F& x) +{ +// Methode: +// Genauigkeit erhöhen, +// (q,r) := (round x (float pi x)), so daß |r|<=pi/2. +// e := Exponent aus (decode-float r), d := (float-digits r) +// Bei r=0.0 oder e<=-d/2 liefere 1.0 +// (denn bei e<=-d/2 ist r^2/2 < 2^(-d)/2 = 2^(-d-1), also +// 1 >= cos(r) > 1-r^2/2 > 1-2^(-d-1), +// also ist cos(r), auf d Bits gerundet, gleich 1.0). +// Sonst s := r/2 = (scale-float r -1), +// (sin(s)/s)^2 errechnen, cos(r) = 1-r*s*(sin(s)/s)^2 errechnen. +// Falls q ungerade: Vorzeichenwechsel. + + // Rechengenauigkeit erhöhen und durch pi dividieren: + var cl_F cos_r; + if (longfloatp(x)) { + DeclareType(cl_LF,x); + if (TheLfloat(x)->len >= 2850) { + var cl_F_div_t q_r = cl_round_pi2(extend(x,TheLfloat(x)->len+1)); + var cl_I& q = q_r.quotient; + var cl_LF r = The(cl_LF)(q_r.remainder); + var cl_LF_cos_sin_t trig = cl_cossin_ratseries(r); + switch (cl_I_to_UL(logand(q,3))) { // q mod 4 + case 0: return cl_float(trig.cos,x); + case 1: return -cl_float(trig.sin,x); + case 2: return -cl_float(trig.cos,x); + case 3: return cl_float(trig.sin,x); + default: NOTREACHED + } + } else { + var cl_F_div_t q_r = cl_round_pi(cl_F_extendsqrt(x)); + var cl_I& q = q_r.quotient; + var cl_LF r = The(cl_LF)(q_r.remainder); + if (zerop(r) || (float_exponent(r) <= (-(sintL)float_digits(r))>>1)) + cos_r = cl_float(1,x); // (cos r) = 1.0 + else { + var cl_LF s = scale_float(r,-1); // s := r/2 + cos_r = cl_float(1-scale_float(sinx_naive(s),1),x); // cos(2s) = 1-2*sin(s)^2 + } + if (oddp(q)) + return -cos_r; // q ungerade -> mal -1 + else + return cos_r; + } + } else { + var cl_F_div_t q_r = cl_round_pi(cl_F_extendsqrt(x)); + var cl_I& q = q_r.quotient; + var cl_F& r = q_r.remainder; + if (zerop(r) || (float_exponent(r) <= (-(sintL)float_digits(r))>>1)) + cos_r = cl_float(1,x); // (cos r) = 1.0 + else { + var cl_F s = scale_float(r,-1); // s := r/2 + cos_r = cl_float(1 - r * s * sinxbyx_naive(s),x); + } + if (oddp(q)) + return -cos_r; // q ungerade -> mal -1 + else + return cos_r; + } +} + +// Timings of the two algorithms, on an i486 33 MHz, running Linux, +// applied to x = sqrt(2)-1 = 0.414... +// N naive ratseries +// 10 0.009 0.049 +// 25 0.033 0.137 +// 50 0.11 0.37 +// 100 0.41 1.15 +// 250 2.7 5.5 +// 500 11.1 19.4 +// 1000 46 64 +// 2500 239 260 +// ==> ratseries faster for N >= 2850. diff --git a/src/float/transcendental/cl_F_cosh.cc b/src/float/transcendental/cl_F_cosh.cc new file mode 100644 index 0000000..3885af3 --- /dev/null +++ b/src/float/transcendental/cl_F_cosh.cc @@ -0,0 +1,84 @@ +// cosh(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F_tran.h" +#include "cl_F.h" +#include "cl_lfloat.h" +#include "cl_LF.h" + +const cl_F cosh (const cl_F& x) +{ +// Methode: +// Genauigkeit erhöhen, +// e := Exponent aus (decode-float x), d := (float-digits x) +// falls x=0.0 oder e<=(1-d)/2 liefere 1.0 +// (denn bei e<=(1-d)/2 ist 1 <= cosh(x) = 1+x^2/2+... < 1+2^(-d), +// also ist cosh(x), auf d Bits gerundet, gleich 1.0). +// falls e<0: +// y := x/2 = (scale-float x -1), (sinh(y)/y)^2 errechnen, +// cosh(x) = 1+x*y*(sinh(y)/y)^2 errechnen. +// falls e>=0: y:=exp(x) errechnen, (scale-float (+ y (/ y)) -1) bilden. + + var sintL e = float_exponent(x); + if (e < 0) { // Exponent e abtesten + // e<0 + if (zerop(x)) + return cl_float(1,x); + var uintL d = float_digits(x); + if (e <= (1-(sintL)d)>>1) // e <= (1-d)/2 <==> e <= -ceiling((d-1)/2) ? + return cl_float(1,x); // ja -> 1.0 als Ergebnis + // Rechengenauigkeit erhöhen + if (longfloatp(x)) { + DeclareType(cl_LF,x); + #if 0 + if (TheLfloat(x)->len >= infty) { + var cl_LF xx = extend(x,TheLfloat(x)->len+1); + var cl_LF_cosh_sinh_t hyp = cl_coshsinh_ratseries(xx); + return cl_float(hyp.cosh,x); + } else + #endif + if (TheLfloat(x)->len >= 600) { + // verwende exp(x), schneller als cl_coshsinh_ratseries + var cl_LF xx = extend(x,TheLfloat(x)->len+1); + var cl_F y = exp(xx); + var cl_F z = scale_float(y + recip(y), -1); // (/ (+ y (/ y)) 2) + return cl_float(z,x); + } else { + var cl_LF xx = The(cl_LF)(cl_F_extendsqrt(x)); + var cl_LF y = scale_float(xx,-1); + // 1 + 2*sinh(y)^2, und wieder runden + return cl_float(1 + scale_float(sinhx_naive(y),1), x); + } + } else { + var cl_F xx = cl_F_extendsqrt(x); + var cl_F y = scale_float(xx,-1); + // 1 + 2*y^2*(sinh(y)/y)^2, und wieder runden + return cl_float(1 + scale_float(square(y) * sinhxbyx_naive(y),1), x); + } + } else { + // e>=0 -> verwende exp(x) + var cl_F y = exp(x); + return scale_float(y + recip(y), -1); // (/ (+ y (/ y)) 2) + } +} + +// Timings of the three algorithms, on an i486 33 MHz, running Linux, +// applied to x = sqrt(2)-1 = 0.414... +// N naive ratseries exp&recip +// 10 0.008 0.037 0.012 +// 25 0.032 0.117 0.047 +// 50 0.11 0.33 0.017 +// 100 0.40 1.06 0.63 +// 250 2.65 5.2 3.3 +// 500 11.1 18.7 11.5 +// 1000 46 61 35 +// 2500 238 250 143 +// ==> exp&recip fastest for N >= 600. diff --git a/src/float/transcendental/cl_F_coshsinh.cc b/src/float/transcendental/cl_F_coshsinh.cc new file mode 100644 index 0000000..9aa32f2 --- /dev/null +++ b/src/float/transcendental/cl_F_coshsinh.cc @@ -0,0 +1,90 @@ +// cl_cosh_sinh(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F_tran.h" +#include "cl_F.h" +#include "cl_lfloat.h" +#include "cl_LF.h" + +const cl_cosh_sinh_t cl_cosh_sinh (const cl_F& x) +{ +// Methode: +// Genauigkeit erhöhen, +// e := Exponent aus (decode-float x), d := (float-digits x) +// falls x=0.0 oder e<=(1-d)/2 liefere (1.0,x) +// (denn bei e<=(1-d)/2 ist +// 1 <= sinh(x)/x < cosh(x) = 1+x^2/2+... < 1+2^(-d), +// also ist cosh(x), auf d Bits gerundet, gleich 1.0 +// und sinh(x), auf d Bits gerundet, gleich x). +// falls e<0: +// y:=(sinh(x)/x)^2 errechnen, +// cosh(x) = sqrt(1+x^2*y) und sinh(x) = x*sqrt(y) errechnen. +// falls e>=0: y:=exp(x) errechnen, +// (scale-float (+ y (/ y)) -1) und (scale-float (- y (/ y)) -1) bilden. +// Genauigkeit wieder verringern. + + var sintL e = float_exponent(x); + if (e < 0) { // Exponent e abtesten + // e<0 + if (zerop(x) || (e <= (1-(sintL)float_digits(x))>>1)) + // e <= (1-d)/2 <==> e <= -ceiling((d-1)/2) + return cl_cosh_sinh_t(cl_float(1,x),x); + // Rechengenauigkeit erhöhen + if (longfloatp(x)) { + DeclareType(cl_LF,x); + #if 0 + if (TheLfloat(x)->len >= infty) { + var cl_LF xx = extend(x,TheLfloat(x)->len+1); + var cl_LF_cosh_sinh_t hyp = cl_coshsinh_ratseries(xx); + return cl_cosh_sinh_t( + cl_float(hyp.cosh,x), + cl_float(hyp.sinh,x) + ); + } else + #endif + if (TheLfloat(x)->len >= 585) { + // verwende exp(x), schneller als cl_coshsinh_ratseries + var cl_LF xx = extend(x,TheLfloat(x)->len+ceiling((uintL)(-e),intDsize)); + var cl_F y = exp(xx); + var cl_F y_inv = recip(y); + return cl_cosh_sinh_t( + cl_float(scale_float(y + y_inv, -1), x), + cl_float(scale_float(y - y_inv, -1), x) + ); + } else { + var cl_LF xx = The(cl_LF)(cl_F_extendsqrt(x)); + var cl_LF y = sinhx_naive(xx); + var cl_LF z = sqrt(y); + if (minusp(xx)) + z = -z; + return cl_cosh_sinh_t( + cl_float(sqrt(1+y),x), // sqrt(1+y) + cl_float(z,x) + ); + } + } else { + var cl_F xx = cl_F_extendsqrt(x); + var cl_F y = sinhxbyx_naive(xx); + return cl_cosh_sinh_t( + cl_float(sqrt(1+square(xx)*y),x), // sqrt(1+x^2*y) + cl_float(xx*sqrt(y),x) + ); + } + } else { + // e>=0 -> verwende exp(x) + var cl_F y = exp(x); + var cl_F y_inv = recip(y); + return cl_cosh_sinh_t( + scale_float(y+y_inv,-1), + scale_float(y-y_inv,-1) + ); + } +} diff --git a/src/float/transcendental/cl_F_cossin.cc b/src/float/transcendental/cl_F_cossin.cc new file mode 100644 index 0000000..8283a5c --- /dev/null +++ b/src/float/transcendental/cl_F_cossin.cc @@ -0,0 +1,87 @@ +// cl_cos_sin(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F_tran.h" +#include "cl_F.h" +#include "cl_integer.h" +#include "cl_lfloat.h" +#include "cl_LF.h" + +const cl_cos_sin_t cl_cos_sin (const cl_F& x) +{ +// Methode: +// Genauigkeit erhöhen, +// (q,r) := (round x (float pi/2 x)), so daß |r|<=pi/4. +// y:=(sin(r)/r)^2 errechnen. +// cos(r) berechnen: +// e := Exponent aus (decode-float r), d := (float-digits r) +// Bei r=0.0 oder e<=-d/2 liefere 1.0 +// (denn bei e<=-d/2 ist r^2/2 < 2^(-d)/2 = 2^(-d-1), also +// 1 >= cos(r) > 1-r^2/2 > 1-2^(-d-1), +// also ist cos(r), auf d Bits gerundet, gleich 1.0). +// Sonst sqrt(1-r^2*y). +// sin(r) berechnen: r*sqrt(y). +// Genauigkeit wieder verringern. +// Falls q = 0 mod 4: (cos(r), sin(r)) +// Falls q = 1 mod 4: (-sin(r), cos(r)) +// Falls q = 2 mod 4: (-cos(r), -sin(r)) +// Falls q = 3 mod 4: (sin(r), -cos(r)) + + // Rechengenauigkeit erhöhen und durch pi/2 dividieren: + var cl_F cos_r; + var cl_F sin_r; + var cl_I q; + if (longfloatp(x)) { + DeclareType(cl_LF,x); + if (TheLfloat(x)->len >= 2710) { + var cl_F_div_t q_r = cl_round_pi2(extend(x,TheLfloat(x)->len+1)); + q = q_r.quotient; + var cl_LF r = The(cl_LF)(q_r.remainder); + var cl_LF_cos_sin_t trig = cl_cossin_ratseries(r); + cos_r = cl_float(trig.cos,x); + sin_r = cl_float(trig.sin,x); + } else { + var cl_F_div_t q_r = cl_round_pi2(cl_F_extendsqrt(x)); + q = q_r.quotient; + var cl_LF r = The(cl_LF)(q_r.remainder); + var cl_LF y = sinx_naive(r); // y := sin(r)^2 + // erste Komponente cos(r) berechnen: + if (zerop(r) || (float_exponent(r) <= (-(sintL)float_digits(r))>>1)) + cos_r = cl_float(1,x); // cos(r) = 1.0 + else + cos_r = cl_float(sqrt(1-y),x); // cos(r) = sqrt(1-y) + // zweite Komponente sin(r) berechnen: + sin_r = cl_float(sqrt(y),x); + if (minusp(r)) + sin_r = - sin_r; + } + } else { + var cl_F_div_t q_r = cl_round_pi2(cl_F_extendsqrt(x)); + q = q_r.quotient; + var cl_F& r = q_r.remainder; + var cl_F y = sinxbyx_naive(r); // y := (sin(r)/r)^2 + // erste Komponente cos(r) berechnen: + if (zerop(r) || (float_exponent(r) <= (-(sintL)float_digits(r))>>1)) + cos_r = cl_float(1,x); // cos(r) = 1.0 + else + cos_r = cl_float(sqrt(1 - square(r)*y),x); // sqrt(1-r^2*y) + // zweite Komponente sin(r) berechnen: + sin_r = cl_float(r*sqrt(y),x); + } + // evtl. Vorzeichenwechsel oder Vertauschen: + switch (cl_I_to_UL(logand(q,3))) { // q mod 4 + case 0: return cl_cos_sin_t(cos_r,sin_r); + case 1: return cl_cos_sin_t(-sin_r,cos_r); + case 2: return cl_cos_sin_t(-cos_r,-sin_r); + case 3: return cl_cos_sin_t(sin_r,-cos_r); + default: NOTREACHED + } +} diff --git a/src/float/transcendental/cl_F_eulerconst.cc b/src/float/transcendental/cl_F_eulerconst.cc new file mode 100644 index 0000000..d41d427 --- /dev/null +++ b/src/float/transcendental/cl_F_eulerconst.cc @@ -0,0 +1,24 @@ +// cl_eulerconst(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_F_tran.h" +#include "cl_LF.h" + +const cl_F cl_eulerconst (const cl_F& y) +{ + floattypecase(y + , return cl_SF_eulerconst; + , return cl_FF_eulerconst; + , return cl_DF_eulerconst; + , return cl_eulerconst(TheLfloat(y)->len); + ); +} diff --git a/src/float/transcendental/cl_F_eulerconst_def.cc b/src/float/transcendental/cl_F_eulerconst_def.cc new file mode 100644 index 0000000..a841496 --- /dev/null +++ b/src/float/transcendental/cl_F_eulerconst_def.cc @@ -0,0 +1,23 @@ +// cl_eulerconst(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_F_tran.h" + +const cl_F cl_eulerconst (void) +{ + floatformatcase(cl_default_float_format + , return cl_SF_eulerconst; + , return cl_FF_eulerconst; + , return cl_DF_eulerconst; + , return cl_eulerconst(len); + ); +} diff --git a/src/float/transcendental/cl_F_eulerconst_f.cc b/src/float/transcendental/cl_F_eulerconst_f.cc new file mode 100644 index 0000000..3643e0d --- /dev/null +++ b/src/float/transcendental/cl_F_eulerconst_f.cc @@ -0,0 +1,23 @@ +// cl_eulerconst(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_F_tran.h" + +const cl_F cl_eulerconst (cl_float_format_t f) +{ + floatformatcase((uintL)f + , return cl_SF_eulerconst; + , return cl_FF_eulerconst; + , return cl_DF_eulerconst; + , return cl_eulerconst(len); + ); +} diff --git a/src/float/transcendental/cl_F_eulerconst_var.cc b/src/float/transcendental/cl_F_eulerconst_var.cc new file mode 100644 index 0000000..997e985 --- /dev/null +++ b/src/float/transcendental/cl_F_eulerconst_var.cc @@ -0,0 +1,33 @@ +// cl_F_eulerconst. + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_F_eulerconst_var) + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +#include "cl_DS.h" +#include "cl_LF.h" +#include "cl_LF_impl.h" +#include "cl_F.h" + +// Mantisse der Eulerschen Konstante : + static const uintD eulerconst_mantisse [64/intDsize] = + #include "cl_F_eulerconst_var.h" + +cl_LF cl_LF_eulerconst = encode_LF_array(0,0,eulerconst_mantisse,64/intDsize); + +// Problem: If someone changes cl_free_hook, the destructor of this +// will call the new hook, passing it some pointer obtained by the old +// cl_malloc_hook. ?? + +const cl_SF cl_SF_eulerconst = cl_LF_to_SF(cl_LF_eulerconst); +const cl_FF cl_FF_eulerconst = cl_LF_to_FF(cl_LF_eulerconst); +const cl_DF cl_DF_eulerconst = cl_LF_to_DF(cl_LF_eulerconst); + +CL_PROVIDE_END(cl_F_eulerconst_var) diff --git a/src/float/transcendental/cl_F_eulerconst_var.h b/src/float/transcendental/cl_F_eulerconst_var.h new file mode 100644 index 0000000..d4ecb5f --- /dev/null +++ b/src/float/transcendental/cl_F_eulerconst_var.h @@ -0,0 +1,29 @@ +{ +#if CL_DS_BIG_ENDIAN_P + #if (intDsize==8) + D1(0x93), D1(0xC4), D1(0x67), D1(0xE3), D1(0x7D), D1(0xB0), D1(0xC7), D1(0xA5) + #endif + #if (intDsize==16) + D2(0x93,0xC4), D2(0x67,0xE3), D2(0x7D,0xB0), D2(0xC7,0xA5) + #endif + #if (intDsize==32) + D4(0x93,0xC4,0x67,0xE3), D4(0x7D,0xB0,0xC7,0xA5) + #endif + #if (intDsize==64) + D8(0x93,0xC4,0x67,0xE3,0x7D,0xB0,0xC7,0xA5) + #endif +#else + #if (intDsize==8) + D1(0xA5), D1(0xC7), D1(0xB0), D1(0x7D), D1(0xE3), D1(0x67), D1(0xC4), D1(0x93) + #endif + #if (intDsize==16) + D2(0xC7,0xA5), D2(0x7D,0xB0), D2(0x67,0xE3), D2(0x93,0xC4) + #endif + #if (intDsize==32) + D4(0x7D,0xB0,0xC7,0xA5), D4(0x93,0xC4,0x67,0xE3) + #endif + #if (intDsize==64) + D8(0x93,0xC4,0x67,0xE3,0x7D,0xB0,0xC7,0xA5) + #endif +#endif +} ; diff --git a/src/float/transcendental/cl_F_eulerconst_var.h.in b/src/float/transcendental/cl_F_eulerconst_var.h.in new file mode 100644 index 0000000..56fa1b2 --- /dev/null +++ b/src/float/transcendental/cl_F_eulerconst_var.h.in @@ -0,0 +1,2 @@ +// Digits of Euler's constant. + { D(0x93,0xC4,0x67,0xE3,) D(0x7D,0xB0,0xC7,0xA5,) } ; diff --git a/src/float/transcendental/cl_F_exp.cc b/src/float/transcendental/cl_F_exp.cc new file mode 100644 index 0000000..553c972 --- /dev/null +++ b/src/float/transcendental/cl_F_exp.cc @@ -0,0 +1,62 @@ +// exp(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F_tran.h" +#include "cl_float.h" +#include "cl_F.h" +#include "cl_lfloat.h" +#include "cl_LF.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_LF_minusp.cc" +#include "cl_LF_exponent.cc" + +// Division durch ln(2). +inline const cl_F_div_t cl_floor_ln2 (const cl_F& x) +{ + // Bei 0<=x<1/2 kann man sofort q:=0 setzen. + if (!minusp(x) && (float_exponent(x) < 0)) + return cl_F_div_t(0,x); + else + return floor2(x,cl_ln2(x)); +} +inline const cl_LF_div_t cl_floor_ln2 (const cl_LF& x) +{ + // Bei 0<=x<1/2 kann man sofort q:=0 setzen. + if (!minusp(x) && (float_exponent(x) < 0)) + return cl_LF_div_t(0,x); + else + return floor2(x,The(cl_LF)(cl_ln2(x))); +} + +const cl_F exp (const cl_F& x) +{ +// Methode: +// d := (float-digits x), +// Genauigkeit um sqrt(d)+max(integer-length(e)) Bits erhöhen, +// (q,r) := (floor x ln(2)) +// Ergebnis ist exp(q*ln(2)+r) = (scale-float exp(r) q). + + // Rechengenauigkeit erhöhen und durch ln(2) dividieren: + if (longfloatp(x) && (TheLfloat(x)->len >= 84)) { + DeclareType(cl_LF,x); + var cl_LF_div_t q_r = cl_floor_ln2(extend(x,TheLfloat(x)->len+1)); + var cl_I& q = q_r.quotient; + var cl_LF& r = q_r.remainder; + return cl_float(scale_float(expx_ratseries(r),q),x); + } else { + var cl_F_div_t q_r = cl_floor_ln2(cl_F_extendsqrtx(x)); + var cl_I& q = q_r.quotient; + var cl_F& r = q_r.remainder; + return cl_float(scale_float(expx_naive(r),q),x); + } +} diff --git a/src/float/transcendental/cl_F_exp1.cc b/src/float/transcendental/cl_F_exp1.cc new file mode 100644 index 0000000..56a679e --- /dev/null +++ b/src/float/transcendental/cl_F_exp1.cc @@ -0,0 +1,24 @@ +// cl_exp1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F_tran.h" +#include "cl_F.h" +#include "cl_LF.h" + +const cl_F cl_exp1 (const cl_F& y) +{ + floattypecase(y + , return cl_SF_exp1; + , return cl_FF_exp1; + , return cl_DF_exp1; + , return cl_exp1(TheLfloat(y)->len); + ); +} diff --git a/src/float/transcendental/cl_F_exp1_def.cc b/src/float/transcendental/cl_F_exp1_def.cc new file mode 100644 index 0000000..3667a28 --- /dev/null +++ b/src/float/transcendental/cl_F_exp1_def.cc @@ -0,0 +1,23 @@ +// cl_exp1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_F_tran.h" + +const cl_F cl_exp1 (void) +{ + floatformatcase(cl_default_float_format + , return cl_SF_exp1; + , return cl_FF_exp1; + , return cl_DF_exp1; + , return cl_exp1(len); + ); +} diff --git a/src/float/transcendental/cl_F_exp1_f.cc b/src/float/transcendental/cl_F_exp1_f.cc new file mode 100644 index 0000000..2c09b64 --- /dev/null +++ b/src/float/transcendental/cl_F_exp1_f.cc @@ -0,0 +1,23 @@ +// cl_exp1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F_tran.h" +#include "cl_F.h" + +const cl_F cl_exp1 (cl_float_format_t f) +{ + floatformatcase((uintL)f + , return cl_SF_exp1; + , return cl_FF_exp1; + , return cl_DF_exp1; + , return cl_exp1(len); + ); +} diff --git a/src/float/transcendental/cl_F_exp1_var.cc b/src/float/transcendental/cl_F_exp1_var.cc new file mode 100644 index 0000000..d77161c --- /dev/null +++ b/src/float/transcendental/cl_F_exp1_var.cc @@ -0,0 +1,33 @@ +// cl_F_exp1. + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_F_exp1_var) + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +#include "cl_DS.h" +#include "cl_LF.h" +#include "cl_LF_impl.h" +#include "cl_F.h" + +// Mantisse von exp(1) : + static const uintD exp1_mantisse [64/intDsize] = + #include "cl_F_exp1_var.h" + +cl_LF cl_LF_exp1 = encode_LF_array(0,2,exp1_mantisse,64/intDsize); + +// Problem: If someone changes cl_free_hook, the destructor of this +// will call the new hook, passing it some pointer obtained by the old +// cl_malloc_hook. ?? + +const cl_SF cl_SF_exp1 = cl_LF_to_SF(cl_LF_exp1); +const cl_FF cl_FF_exp1 = cl_LF_to_FF(cl_LF_exp1); +const cl_DF cl_DF_exp1 = cl_LF_to_DF(cl_LF_exp1); + +CL_PROVIDE_END(cl_F_exp1_var) diff --git a/src/float/transcendental/cl_F_exp1_var.h b/src/float/transcendental/cl_F_exp1_var.h new file mode 100644 index 0000000..37df40a --- /dev/null +++ b/src/float/transcendental/cl_F_exp1_var.h @@ -0,0 +1,29 @@ +{ +#if CL_DS_BIG_ENDIAN_P + #if (intDsize==8) + D1(0xAD), D1(0xF8), D1(0x54), D1(0x58), D1(0xA2), D1(0xBB), D1(0x4A), D1(0x9B) + #endif + #if (intDsize==16) + D2(0xAD,0xF8), D2(0x54,0x58), D2(0xA2,0xBB), D2(0x4A,0x9B) + #endif + #if (intDsize==32) + D4(0xAD,0xF8,0x54,0x58), D4(0xA2,0xBB,0x4A,0x9B) + #endif + #if (intDsize==64) + D8(0xAD,0xF8,0x54,0x58,0xA2,0xBB,0x4A,0x9B) + #endif +#else + #if (intDsize==8) + D1(0x9B), D1(0x4A), D1(0xBB), D1(0xA2), D1(0x58), D1(0x54), D1(0xF8), D1(0xAD) + #endif + #if (intDsize==16) + D2(0x4A,0x9B), D2(0xA2,0xBB), D2(0x54,0x58), D2(0xAD,0xF8) + #endif + #if (intDsize==32) + D4(0xA2,0xBB,0x4A,0x9B), D4(0xAD,0xF8,0x54,0x58) + #endif + #if (intDsize==64) + D8(0xAD,0xF8,0x54,0x58,0xA2,0xBB,0x4A,0x9B) + #endif +#endif +} ; diff --git a/src/float/transcendental/cl_F_exp1_var.h.in b/src/float/transcendental/cl_F_exp1_var.h.in new file mode 100644 index 0000000..85b3023 --- /dev/null +++ b/src/float/transcendental/cl_F_exp1_var.h.in @@ -0,0 +1,2 @@ +// Digits of exp(1). + { D(0xAD,0xF8,0x54,0x58,) D(0xA2,0xBB,0x4A,0x9B,) } ; diff --git a/src/float/transcendental/cl_F_expx.cc b/src/float/transcendental/cl_F_expx.cc new file mode 100644 index 0000000..104c621 --- /dev/null +++ b/src/float/transcendental/cl_F_expx.cc @@ -0,0 +1,190 @@ +// expx(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +#include "cl_float.h" +#include "cl_low.h" +#include "cl_F.h" +#include "cl_lfloat.h" +#include "cl_LF.h" +#include "cl_integer.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_LF_zerop.cc" +#include "cl_LF_exponent.cc" + +// cl_F expx_naive (const cl_F& x) +// cl_LF expx_naive (const cl_LF& x) +// +// Methode: +// e := Exponent aus (decode-float x), d := (float-digits x) +// Bei x=0.0 oder e<-d liefere 1.0 +// (denn bei e<=-d-1 ist abs(exp(x)-1) = abs(x)+O(x^2) < 2^(-d-1), +// also ist exp(x), auf d Bits gerundet, gleich 1.0). +// Bei e<=-sqrt(d) verwende die Potenzreihe +// exp(x) = sum(j=0..inf,x^j/j!): +// b:=1, i:=0, sum:=0, +// while (/= sum (setq sum (+ sum b))) do b:=b*x/(i+1), i:=i+1. +// Ergebnis sum. +// Sonst setze y := x/2 = (scale-float x -1), +// berechne rekursiv z:=exp(y) und liefere z^2. +// Aufwand: asymptotisch d^2.5 . + +const cl_LF expx_naive (const cl_LF& x) +{ +// Methode: +// wie oben, mit adaptiver Genauigkeit während der Potenzreihen-Summation. + if (zerop(x)) + return cl_float(1,x); + var uintL actuallen = TheLfloat(x)->len; + var uintL d = float_digits(x); + var sintL e = float_exponent(x); + if (e < -(sintL)d) // e < -d ? + return cl_float(1,x); // ja -> 1.0 als Ergebnis + { Mutable(cl_LF,x); + var uintL k = 0; // Rekursionszähler k:=0 + // Bei e <= -1-limit_slope*floor(sqrt(d)) kann die Potenzreihe + // angewandt werden. limit_slope = 1.0 ist nicht schlecht, + // auch im Bereich d = ca. 800. + var sintL e_limit = -1-isqrt(d); // -1-floor(sqrt(d)) + if (e > e_limit) { + // e > -1-floor(sqrt(d)) -> muß |x| verkleinern. + k = e - e_limit; + x = scale_float(x,-(sintL)k); // x := x/2^k + // Neuer Exponent = e-k = e_limit. + } + // Potenzreihe anwenden: + var int i = 0; + var cl_LF b = cl_float(1,x); // b := (float 1 x) + var cl_LF eps = scale_float(b,-(sintL)d-10); + var cl_LF sum = cl_float(0,x); // sum := (float 0 x) + loop { + var cl_LF new_sum = sum + LF_to_LF(b,actuallen); + if (new_sum == sum) // = sum ? + break; // ja -> Potenzreihe abbrechen + sum = new_sum; + i = i+1; + b = cl_LF_shortenwith(b,eps); + b = (b*x)/(cl_I)i; // b := b*x/i + } + var cl_LF& result = sum; // sum als Ergebnis + // Wegen Rekursion noch k mal quadrieren: + for ( ; k > 0; k--) + result = square(result); + return result; +}} +// Bit complexity (N = length(x)): O(N^(1/2)*M(N)). + +const cl_F expx_naive (const cl_F& x) +{ + if (longfloatp(x)) { + DeclareType(cl_LF,x); + return expx_naive(x); + } + if (zerop(x)) + return cl_float(1,x); + var uintL d = float_digits(x); + var sintL e = float_exponent(x); + if (e < -(sintL)d) // e < -d ? + return cl_float(1,x); // ja -> 1.0 als Ergebnis + { Mutable(cl_F,x); + var uintL k = 0; // Rekursionszähler k:=0 + // Bei e <= -1-limit_slope*floor(sqrt(d)) kann die Potenzreihe + // angewandt werden. limit_slope = 1.0 ist nicht schlecht. Für + // d > 1600 scheint der Bereich 2.0 <= limit_slope <= 2.6 am besten + // zu sein (mit bis zu 15% Beschleunigung gegenüber limit_slope = 1.0), + // aber in diesem Bereich rechnen wir gar nicht. + // Wir wählen limit_slope = 1.5. + var sintL e_limit = -1-floor(isqrt(d)*3,2); // -1-floor(sqrt(d)) + if (e > e_limit) { + // e > -1-floor(sqrt(d)) -> muß |x| verkleinern. + k = e - e_limit; + x = scale_float(x,-(sintL)k); // x := x/2^k + // Neuer Exponent = e-k = e_limit. + } + // Potenzreihe anwenden: + var int i = 0; + var cl_F b = cl_float(1,x); // b := (float 1 x) + var cl_F sum = cl_float(0,x); // sum := (float 0 x) + loop { + var cl_F new_sum = sum + b; + if (new_sum == sum) // = sum ? + break; // ja -> Potenzreihe abbrechen + sum = new_sum; + i = i+1; + b = (b*x)/(cl_I)i; // b := b*x/i + } + var cl_F& result = sum; // sum als Ergebnis + // Wegen Rekursion noch k mal quadrieren: + for ( ; k > 0; k--) + result = square(result); + return result; +}} +// Bit complexity (N = length(x)): O(N^(1/2)*M(N)). + +const cl_LF expx_ratseries (const cl_LF& x) +{ + // [Jonathan M. Borwein, Peter B. Borwein: Pi and the AGM. + // Wiley 1987. Section 10.2.3] + var uintC len = TheLfloat(x)->len; + var cl_idecoded_float x_ = integer_decode_float(x); + // x = (-1)^sign * 2^exponent * mantissa + var uintL lq = cl_I_to_UL(- x_.exponent); + var const cl_I& p = x_.mantissa; + // Compute exp(p/2^lq) by splitting into pieces. + // Each piece gives rise to a factor exp(pk/2^lqk). + // Instead of the standard choice lqk = 2^k, we choose + // lqk = c^k + O(1), where c > 1 is real. + // Running time on Linux i486, 33 Mhz, computing exp(sqrt(2)-1): + // c 2.0 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 3.0 3.1 3.2 3.3 3.4 3.5 + // (a) 400 393 390 377 371 360 363 367 367 358 362 362 363 362 376 372 + // (b) 311 317 305 312 295 291 286 293 291 284 295 284 293 287 288 305 + // (a): N=300, time in 0.01 sec. (b): N=1000, time in 0.1 sec. + // Values 2.5 <= c <= 3.2 seem best. Let's choose c = 2.875. + var cl_boolean first_factor = cl_true; + var cl_LF product; + var uintL b1; + var uintL b2; + for (b1 = 0, b2 = 1; b1 < lq; b1 = b2, b2 = ceiling(b2*23,8)) { + // Piece containing bits b1+1..b2 after "decimal point" + // in the binary representation of (p/2^lq). + var uintL lqk = (lq >= b2 ? b2 : lq); + var cl_I pk = ldb(p,cl_byte(lqk-b1,lq-lqk)); + // Compute exp(pk/2^lqk). + if (!zerop(pk)) { + if (minusp(x_.sign)) { pk = -pk; } + var cl_LF factor = cl_exp_aux(pk,lqk,len); + if (first_factor) { + product = factor; + first_factor = cl_false; + } else + product = product * factor; + } + } + if (first_factor) + return cl_I_to_LF(1,len); + else + return product; +} +// Bit complexity (N = length(x)): O(log(N)^2*M(N)). + +// Timings of the above algorithms, on an i486 33 MHz, running Linux, +// applied to x = sqrt(2)-1 = 0.414... +// ("naive" with adaptive limit_slope, about sqrt(ln(len)).) +// N naive ratseries +// 10 0.010 0.027 +// 25 0.039 0.072 +// 50 0.15 0.19 +// 100 0.60 0.55 +// 250 3.9 2.6 +// 500 16.3 9.3 +// 1000 68 29 +// ==> ratseries faster for N >= 84. diff --git a/src/float/transcendental/cl_F_ln.cc b/src/float/transcendental/cl_F_ln.cc new file mode 100644 index 0000000..7a2ed80 --- /dev/null +++ b/src/float/transcendental/cl_F_ln.cc @@ -0,0 +1,55 @@ +// ln(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F_tran.h" +#include "cl_F.h" +#include "cl_SF.h" +#include "cl_integer.h" +#include "cl_lfloat.h" +#include "cl_LF.h" + +const cl_F ln (const cl_F& x) +{ +// Methode: +// d := (float-digits x), +// Genauigkeit um sqrt(d)+max(integer-length(e)) Bits erhöhen, +// (m,e) := (decode-float x), so daß 1/2 <= m < 1. +// m<2/3 -> m:=2m, e:=e-1, so daß 2/3 <= m <= 4/3. +// ln(m) errechnen, ln(x)=ln(m)+e*ln(2) als Ergebnis. + + // Rechengenauigkeit erhöhen und m,e,s bestimmen: + if (longfloatp(x) && (TheLfloat(x)->len >= 110)) { + DeclareType(cl_LF,x); + var cl_decoded_lfloat m_e_s = decode_float(extend(x,TheLfloat(x)->len+1)); + var cl_LF& m = m_e_s.mantissa; + var cl_I& e = m_e_s.exponent; + if (m < make_SF(0,0+SF_exp_mid,floor(bit(SF_mant_len+2),3))) { // Short-Float 2/3 + m = scale_float(m,1); // m verdoppeln + e = minus1(e); // e decrementieren + } + var cl_F res = lnx_ratseries(m); + if (!zerop(e)) + res = res + cl_float(e,m)*cl_ln2(m); // ln(m)+e*ln(2) + return cl_float(res,x); + } else { + var cl_decoded_float m_e_s = decode_float(cl_F_extendsqrtx(x)); + var cl_F& m = m_e_s.mantissa; + var cl_I& e = m_e_s.exponent; + if (m < make_SF(0,0+SF_exp_mid,floor(bit(SF_mant_len+2),3))) { // Short-Float 2/3 + m = scale_float(m,1); // m verdoppeln + e = minus1(e); // e decrementieren + } + var cl_F res = lnx_naive(m); + if (!zerop(e)) + res = res + cl_float(e,m)*cl_ln2(m); // ln(m)+e*ln(2) + return cl_float(res,x); + } +} diff --git a/src/float/transcendental/cl_F_ln10.cc b/src/float/transcendental/cl_F_ln10.cc new file mode 100644 index 0000000..69db310 --- /dev/null +++ b/src/float/transcendental/cl_F_ln10.cc @@ -0,0 +1,23 @@ +// cl_ln10(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_LF.h" + +const cl_F cl_ln10 (const cl_F& y) +{ + floattypecase(y + , return cl_SF_ln10; + , return cl_FF_ln10; + , return cl_DF_ln10; + , return cl_ln10(TheLfloat(y)->len); + ); +} diff --git a/src/float/transcendental/cl_F_ln10_f.cc b/src/float/transcendental/cl_F_ln10_f.cc new file mode 100644 index 0000000..7552674 --- /dev/null +++ b/src/float/transcendental/cl_F_ln10_f.cc @@ -0,0 +1,22 @@ +// cl_ln10(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +#include "cl_F.h" + +const cl_F cl_ln10 (cl_float_format_t f) +{ + floatformatcase((uintL)f + , return cl_SF_ln10; + , return cl_FF_ln10; + , return cl_DF_ln10; + , return cl_ln10(len); + ); +} diff --git a/src/float/transcendental/cl_F_ln10_var.cc b/src/float/transcendental/cl_F_ln10_var.cc new file mode 100644 index 0000000..18b32f4 --- /dev/null +++ b/src/float/transcendental/cl_F_ln10_var.cc @@ -0,0 +1,33 @@ +// cl_F_ln10. + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_F_ln10_var) + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +#include "cl_DS.h" +#include "cl_LF.h" +#include "cl_LF_impl.h" +#include "cl_F.h" + +// Mantisse von ln(10) : + static const uintD ln10_mantisse [64/intDsize] = + #include "cl_F_ln10_var.h" + +cl_LF cl_LF_ln10 = encode_LF_array(0,2,ln10_mantisse,64/intDsize); + +// Problem: If someone changes cl_free_hook, the destructor of this +// will call the new hook, passing it some pointer obtained by the old +// cl_malloc_hook. ?? + +const cl_SF cl_SF_ln10 = cl_LF_to_SF(cl_LF_ln10); +const cl_FF cl_FF_ln10 = cl_LF_to_FF(cl_LF_ln10); +const cl_DF cl_DF_ln10 = cl_LF_to_DF(cl_LF_ln10); + +CL_PROVIDE_END(cl_F_ln10_var) diff --git a/src/float/transcendental/cl_F_ln10_var.h b/src/float/transcendental/cl_F_ln10_var.h new file mode 100644 index 0000000..16c3e7d --- /dev/null +++ b/src/float/transcendental/cl_F_ln10_var.h @@ -0,0 +1,29 @@ +{ +#if CL_DS_BIG_ENDIAN_P + #if (intDsize==8) + D1(0x93), D1(0x5D), D1(0x8D), D1(0xDD), D1(0xAA), D1(0xA8), D1(0xAC), D1(0x17) + #endif + #if (intDsize==16) + D2(0x93,0x5D), D2(0x8D,0xDD), D2(0xAA,0xA8), D2(0xAC,0x17) + #endif + #if (intDsize==32) + D4(0x93,0x5D,0x8D,0xDD), D4(0xAA,0xA8,0xAC,0x17) + #endif + #if (intDsize==64) + D8(0x93,0x5D,0x8D,0xDD,0xAA,0xA8,0xAC,0x17) + #endif +#else + #if (intDsize==8) + D1(0x17), D1(0xAC), D1(0xA8), D1(0xAA), D1(0xDD), D1(0x8D), D1(0x5D), D1(0x93) + #endif + #if (intDsize==16) + D2(0xAC,0x17), D2(0xAA,0xA8), D2(0x8D,0xDD), D2(0x93,0x5D) + #endif + #if (intDsize==32) + D4(0xAA,0xA8,0xAC,0x17), D4(0x93,0x5D,0x8D,0xDD) + #endif + #if (intDsize==64) + D8(0x93,0x5D,0x8D,0xDD,0xAA,0xA8,0xAC,0x17) + #endif +#endif +} ; diff --git a/src/float/transcendental/cl_F_ln10_var.h.in b/src/float/transcendental/cl_F_ln10_var.h.in new file mode 100644 index 0000000..a262d4a --- /dev/null +++ b/src/float/transcendental/cl_F_ln10_var.h.in @@ -0,0 +1,2 @@ +// Digits of ln(10). + { D(0x93,0x5D,0x8D,0xDD,) D(0xAA,0xA8,0xAC,0x17,) } ; diff --git a/src/float/transcendental/cl_F_ln2.cc b/src/float/transcendental/cl_F_ln2.cc new file mode 100644 index 0000000..08ec12f --- /dev/null +++ b/src/float/transcendental/cl_F_ln2.cc @@ -0,0 +1,23 @@ +// cl_ln2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_LF.h" + +const cl_F cl_ln2 (const cl_F& y) +{ + floattypecase(y + , return cl_SF_ln2; + , return cl_FF_ln2; + , return cl_DF_ln2; + , return cl_ln2(TheLfloat(y)->len); + ); +} diff --git a/src/float/transcendental/cl_F_ln2_f.cc b/src/float/transcendental/cl_F_ln2_f.cc new file mode 100644 index 0000000..f1bcc31 --- /dev/null +++ b/src/float/transcendental/cl_F_ln2_f.cc @@ -0,0 +1,22 @@ +// cl_ln2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +#include "cl_F.h" + +const cl_F cl_ln2 (cl_float_format_t f) +{ + floatformatcase((uintL)f + , return cl_SF_ln2; + , return cl_FF_ln2; + , return cl_DF_ln2; + , return cl_ln2(len); + ); +} diff --git a/src/float/transcendental/cl_F_ln2_var.cc b/src/float/transcendental/cl_F_ln2_var.cc new file mode 100644 index 0000000..eac6286 --- /dev/null +++ b/src/float/transcendental/cl_F_ln2_var.cc @@ -0,0 +1,33 @@ +// cl_F_ln2. + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_F_ln2_var) + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +#include "cl_DS.h" +#include "cl_LF.h" +#include "cl_LF_impl.h" +#include "cl_F.h" + +// Mantisse von ln(2) : + static const uintD ln2_mantisse [64/intDsize] = + #include "cl_F_ln2_var.h" + +cl_LF cl_LF_ln2 = encode_LF_array(0,0,ln2_mantisse,64/intDsize); + +// Problem: If someone changes cl_free_hook, the destructor of this +// will call the new hook, passing it some pointer obtained by the old +// cl_malloc_hook. ?? + +const cl_SF cl_SF_ln2 = cl_LF_to_SF(cl_LF_ln2); +const cl_FF cl_FF_ln2 = cl_LF_to_FF(cl_LF_ln2); +const cl_DF cl_DF_ln2 = cl_LF_to_DF(cl_LF_ln2); + +CL_PROVIDE_END(cl_F_ln2_var) diff --git a/src/float/transcendental/cl_F_ln2_var.h b/src/float/transcendental/cl_F_ln2_var.h new file mode 100644 index 0000000..3a13285 --- /dev/null +++ b/src/float/transcendental/cl_F_ln2_var.h @@ -0,0 +1,29 @@ +{ +#if CL_DS_BIG_ENDIAN_P + #if (intDsize==8) + D1(0xB1), D1(0x72), D1(0x17), D1(0xF7), D1(0xD1), D1(0xCF), D1(0x79), D1(0xAC) + #endif + #if (intDsize==16) + D2(0xB1,0x72), D2(0x17,0xF7), D2(0xD1,0xCF), D2(0x79,0xAC) + #endif + #if (intDsize==32) + D4(0xB1,0x72,0x17,0xF7), D4(0xD1,0xCF,0x79,0xAC) + #endif + #if (intDsize==64) + D8(0xB1,0x72,0x17,0xF7,0xD1,0xCF,0x79,0xAC) + #endif +#else + #if (intDsize==8) + D1(0xAC), D1(0x79), D1(0xCF), D1(0xD1), D1(0xF7), D1(0x17), D1(0x72), D1(0xB1) + #endif + #if (intDsize==16) + D2(0x79,0xAC), D2(0xD1,0xCF), D2(0x17,0xF7), D2(0xB1,0x72) + #endif + #if (intDsize==32) + D4(0xD1,0xCF,0x79,0xAC), D4(0xB1,0x72,0x17,0xF7) + #endif + #if (intDsize==64) + D8(0xB1,0x72,0x17,0xF7,0xD1,0xCF,0x79,0xAC) + #endif +#endif +} ; diff --git a/src/float/transcendental/cl_F_ln2_var.h.in b/src/float/transcendental/cl_F_ln2_var.h.in new file mode 100644 index 0000000..3b09486 --- /dev/null +++ b/src/float/transcendental/cl_F_ln2_var.h.in @@ -0,0 +1,2 @@ +// Digits of ln(2). + { D(0xB1,0x72,0x17,0xF7,) D(0xD1,0xCF,0x79,0xAC,) } ; diff --git a/src/float/transcendental/cl_F_lnx.cc b/src/float/transcendental/cl_F_lnx.cc new file mode 100644 index 0000000..10673db --- /dev/null +++ b/src/float/transcendental/cl_F_lnx.cc @@ -0,0 +1,248 @@ +// lnx(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +#include "cl_float.h" +#include "cl_low.h" +#include "cl_F.h" +#include "cl_lfloat.h" +#include "cl_LF.h" +#include "cl_integer.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_LF_zerop.cc" +#include "cl_LF_minusp.cc" +#include "cl_LF_exponent.cc" + +// cl_F lnx_naive (const cl_F& x) +// cl_LF lnx_naive (const cl_LF& x) +// +// Methode: +// y:=x-1, e := Exponent aus (decode-float y), d := (float-digits y) +// Bei y=0.0 oder e<=-d liefere y +// (denn bei e<=-d ist y/2 < 2^(-d)/2 = 2^(-d-1), also +// 0 <= y - ln(x) < y^2/2 < 2^(-d-1)*y +// also ist ln(x)/y, auf d Bits gerundet, gleich y). +// Bei e<=-sqrt(d) verwende die Potenzreihe +// ln(x) = sum(j=0..inf,(-1)^j*y^(j+1)/(j+1)): +// a:=-y, b:=y, i:=1, sum:=0, +// while (/= sum (setq sum (+ sum (/ b i)))) do i:=i+1, b:=b*a. +// Ergebnis sum. +// Sonst setze y := sqrt(x), berechne rekursiv z:=ln(y) +// und liefere 2*z = (scale-float z 1). +// Aufwand: asymptotisch d^0.5*M(d) = d^2.5 . + +const cl_LF lnx_naive (const cl_LF& x) +{ + var cl_LF y = x-cl_float(1,x); + if (zerop(y)) // y=0.0 -> y als Ergebnis + return y; + var uintL actuallen = TheLfloat(x)->len; + var uintL d = float_digits(x); + var sintL e = float_exponent(y); + if (e <= -(sintL)d) // e <= -d ? + return y; // ja -> y als Ergebnis + { Mutable(cl_LF,x); + var uintL k = 0; // Rekursionszähler k:=0 + // Bei e <= -1-limit_slope*floor(sqrt(d)) kann die Potenzreihe + // angewandt werden. + // Wähle für ln(1+y), naive1: limit_slope = 1.0, + // für ln(1+y), naive2: limit_slope = 11/16 = 0.7, + // für atanh(z), naive1: limit_slope = 0.6, + // für atanh(z), naive1: limit_slope = 0.5. + var sintL e_limit = -1-floor(isqrt(d),2); // -1-floor(sqrt(d)) + while (e > e_limit) { + // e > -1-floor(sqrt(d)) -> muß |y| verkleinern. + x = sqrt(x); // x := (sqrt x) + y = x-cl_float(1,x); // y := (- x 1) und + e = float_exponent(y); // e neu berechnen + k = k+1; // k:=k+1 + } + if (0) { + // Potenzreihe ln(1+y) anwenden: + var int i = 1; + var cl_LF sum = cl_float(0,x); // sum := (float 0 x) + var cl_LF a = -y; + var cl_LF b = y; + if (0) { + // naive1: + // floating-point representation + loop { + var cl_LF new_sum = sum + b/(cl_I)i; // (+ sum (/ b i)) + if (new_sum == sum) // = sum ? + break; // ja -> Potenzreihe abbrechen + sum = new_sum; + b = b*a; + i = i+1; + } + } else { + // naive2: + // floating-point representation with smooth precision reduction + var cl_LF eps = scale_float(b,-(sintL)d-10); + loop { + var cl_LF new_sum = sum + LF_to_LF(b/(cl_I)i,actuallen); // (+ sum (/ b i)) + if (new_sum == sum) // = sum ? + break; // ja -> Potenzreihe abbrechen + sum = new_sum; + b = cl_LF_shortenwith(b,eps); + b = b*a; + i = i+1; + } + } + return scale_float(sum,k); // sum als Ergebnis, wegen Rekursion noch mal 2^k + } else { + var cl_LF z = y / (x+cl_float(1,x)); + // Potenzreihe atanh(z) anwenden: + var int i = 1; + var cl_LF a = square(z); // a = x^2 + var cl_LF b = cl_float(1,x); // b := (float 1 x) + var cl_LF sum = cl_float(0,x); // sum := (float 0 x) + if (0) { + // naive1: + // floating-point representation + loop { + var cl_LF new_sum = sum + b / (cl_I)i; // (+ sum (/ b i)) + if (new_sum == sum) // = sum ? + break; // ja -> Potenzreihe abbrechen + sum = new_sum; + b = b*a; + i = i+2; + } + } else { + // naive2: + // floating-point representation with smooth precision reduction + var cl_LF eps = scale_float(b,-(sintL)d-10); + loop { + var cl_LF new_sum = sum + LF_to_LF(b/(cl_I)i,actuallen); // (+ sum (/ b i)) + if (new_sum == sum) // = sum ? + break; // ja -> Potenzreihe abbrechen + sum = new_sum; + b = cl_LF_shortenwith(b,eps); + b = b*a; + i = i+2; + } + } + return scale_float(sum*z,k+1); // 2*sum*z als Ergebnis, wegen Rekursion noch mal 2^k + } +}} +// Bit complexity (N = length(x)): O(N^(1/2)*M(N)). + +const cl_F lnx_naive (const cl_F& x) +{ + if (longfloatp(x)) { + DeclareType(cl_LF,x); + return lnx_naive(x); + } + var cl_F y = x-cl_float(1,x); + if (zerop(y)) // y=0.0 -> y als Ergebnis + return y; + var uintL d = float_digits(x); + var sintL e = float_exponent(y); + if (e <= -(sintL)d) // e <= -d ? + return y; // ja -> y als Ergebnis + { Mutable(cl_F,x); + var uintL k = 0; // Rekursionszähler k:=0 + // Bei e <= -1-floor(sqrt(d)) kann die Potenzreihe angewandt werden. + var sintL e_limit = -1-isqrt(d); // -1-floor(sqrt(d)) + while (e > e_limit) { + // e > -1-floor(sqrt(d)) -> muß |y| verkleinern. + x = sqrt(x); // x := (sqrt x) + y = x-cl_float(1,x); // y := (- x 1) und + e = float_exponent(y); // e neu berechnen + k = k+1; // k:=k+1 + } + // Potenzreihe anwenden: + var int i = 1; + var cl_F sum = cl_float(0,x); // sum := (float 0 x) + var cl_F a = -y; + var cl_F b = y; + loop { + var cl_F new_sum = sum + b/(cl_I)i; // (+ sum (/ b i)) + if (new_sum == sum) // = sum ? + break; // ja -> Potenzreihe abbrechen + sum = new_sum; + b = b*a; + i = i+1; + } + return scale_float(sum,k); // sum als Ergebnis, wegen Rekursion noch mal 2^k +}} +// Bit complexity (N = length(x)): O(N^(1/2)*M(N)). + +const cl_LF lnx_ratseries (const cl_LF& x) +{ + // Method: + // Based on the same ideas as expx_ratseries. + // y := 0. + // Loop + // [x*exp(y) is invariant] + // x' := x-1. If x' = 0, terminate the loop. + // Choose approximation y' of log(x) = log(1+x'): + // If |x'| >= 1/2, set y' = 1/2 * sign(x'). + // If |x'| < 2^-n with n maximal, set + // y' = truncate(x'*2^(2n))/2^(2n). + // Set y := y + y' and x := x*exp(-y'). + var uintC len = TheLfloat(x)->len; + { Mutable(cl_LF,x); + var cl_LF y = cl_I_to_LF(0,len); + loop { + var cl_LF x1 = x + cl_I_to_LF(-1,len); + var cl_idecoded_float x1_ = integer_decode_float(x1); + // x1 = (-1)^sign * 2^exponent * mantissa + if (zerop(x1_.mantissa)) + break; + var uintL lm = integer_length(x1_.mantissa); + var uintL me = cl_I_to_UL(- x1_.exponent); + var cl_I p; + var uintL lq; + var cl_boolean last_step = cl_false; + if (lm >= me) { // |x'| >= 1/2 ? + p = x1_.sign; // 1 or -1 + lq = 1; + } else { + var uintL n = me - lm; // |x'| < 2^-n with n maximal + // Set p to the first n bits of |x'|: + if (lm > n) { + p = x1_.mantissa >> (lm - n); + lq = 2*n; + } else { + p = x1_.mantissa; + lq = lm + n; + } + if (minusp(x1_.sign)) { p = -p; } + // If 2*n >= lm = intDsize*len, then within our + // precision exp(-y') = 1-y', (because |y'^2| < 2^-lm), + // and we know a priori that the iteration will stop + // after the next big multiplication. This saves one + // big multiplication at the end. + if (2*n >= lm) + last_step = cl_true; + } + y = y + scale_float(cl_I_to_LF(p,len),-(sintL)lq); + if (last_step) + break; + x = x * cl_exp_aux(-p,lq,len); + } + return y; +}} +// Bit complexity (N = length(x)): O(log(N)^2*M(N)). + +// Timings of the above algorithms, on an i486 33 MHz, running Linux, +// applied to x = sqrt(sqrt(2)) = 1.189... +// N ln(1+y) ln(1+y) atanh z atanh z exp +// naive1 naive2 naive1 naive2 ratseries +// 10 0.019 0.016 0.013 0.012 0.036 +// 25 0.077 0.056 0.057 0.040 0.087 +// 50 0.30 0.21 0.23 0.15 0.21 +// 100 1.24 0.81 0.92 0.59 0.61 +// 250 8.8 5.8 6.3 4.3 2.77 +// 500 43.9 28.8 29.7 21.0 9.8 +// 1000 223 149 144 107 30 +// ==> ratseries faster for N >= 110. (N = length before extended by the caller.) diff --git a/src/float/transcendental/cl_F_pi.cc b/src/float/transcendental/cl_F_pi.cc new file mode 100644 index 0000000..b461e61 --- /dev/null +++ b/src/float/transcendental/cl_F_pi.cc @@ -0,0 +1,24 @@ +// cl_pi(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_F_tran.h" +#include "cl_LF.h" + +const cl_F cl_pi (const cl_F& y) +{ + floattypecase(y + , return cl_SF_pi; + , return cl_FF_pi; + , return cl_DF_pi; + , return cl_pi(TheLfloat(y)->len); + ); +} diff --git a/src/float/transcendental/cl_F_pi_def.cc b/src/float/transcendental/cl_F_pi_def.cc new file mode 100644 index 0000000..793e7e0 --- /dev/null +++ b/src/float/transcendental/cl_F_pi_def.cc @@ -0,0 +1,23 @@ +// cl_pi(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_F_tran.h" + +const cl_F cl_pi (void) +{ + floatformatcase(cl_default_float_format + , return cl_SF_pi; + , return cl_FF_pi; + , return cl_DF_pi; + , return cl_pi(len); + ); +} diff --git a/src/float/transcendental/cl_F_pi_f.cc b/src/float/transcendental/cl_F_pi_f.cc new file mode 100644 index 0000000..b2cd04f --- /dev/null +++ b/src/float/transcendental/cl_F_pi_f.cc @@ -0,0 +1,23 @@ +// cl_pi(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_F_tran.h" + +const cl_F cl_pi (cl_float_format_t f) +{ + floatformatcase((uintL)f + , return cl_SF_pi; + , return cl_FF_pi; + , return cl_DF_pi; + , return cl_pi(len); + ); +} diff --git a/src/float/transcendental/cl_F_pi_var.cc b/src/float/transcendental/cl_F_pi_var.cc new file mode 100644 index 0000000..3c708f1 --- /dev/null +++ b/src/float/transcendental/cl_F_pi_var.cc @@ -0,0 +1,33 @@ +// cl_SF_pi, cl_FF_pi, cl_DF_pi, cl_LF_pi. + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_F_pi_var) + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +#include "cl_DS.h" +#include "cl_LF.h" +#include "cl_LF_impl.h" +#include "cl_F.h" + +// Mantisse von pi : + static const uintD pi_mantisse [2048/intDsize] = + #include "cl_F_pi_var.h" + +cl_LF cl_LF_pi = encode_LF_array(0,2,pi_mantisse,2048/intDsize); + +// Problem: If someone changes cl_free_hook, the destructor of this +// will call the new hook, passing it some pointer obtained by the old +// cl_malloc_hook. ?? + +const cl_SF cl_SF_pi = cl_LF_to_SF(cl_LF_pi); +const cl_FF cl_FF_pi = cl_LF_to_FF(cl_LF_pi); +const cl_DF cl_DF_pi = cl_LF_to_DF(cl_LF_pi); + +CL_PROVIDE_END(cl_F_pi_var) diff --git a/src/float/transcendental/cl_F_pi_var.h b/src/float/transcendental/cl_F_pi_var.h new file mode 100644 index 0000000..c13fac7 --- /dev/null +++ b/src/float/transcendental/cl_F_pi_var.h @@ -0,0 +1,29 @@ +{ +#if CL_DS_BIG_ENDIAN_P + #if (intDsize==8) + D1(0xC9), D1(0x0F), D1(0xDA), D1(0xA2), D1(0x21), D1(0x68), D1(0xC2), D1(0x34), D1(0xC4), D1(0xC6), D1(0x62), D1(0x8B), D1(0x80), D1(0xDC), D1(0x1C), D1(0xD1), D1(0x29), D1(0x02), D1(0x4E), D1(0x08), D1(0x8A), D1(0x67), D1(0xCC), D1(0x74), D1(0x02), D1(0x0B), D1(0xBE), D1(0xA6), D1(0x3B), D1(0x13), D1(0x9B), D1(0x22), D1(0x51), D1(0x4A), D1(0x08), D1(0x79), D1(0x8E), D1(0x34), D1(0x04), D1(0xDD), D1(0xEF), D1(0x95), D1(0x19), D1(0xB3), D1(0xCD), D1(0x3A), D1(0x43), D1(0x1B), D1(0x30), D1(0x2B), D1(0x0A), D1(0x6D), D1(0xF2), D1(0x5F), D1(0x14), D1(0x37), D1(0x4F), D1(0xE1), D1(0x35), D1(0x6D), D1(0x6D), D1(0x51), D1(0xC2), D1(0x45), D1(0xE4), D1(0x85), D1(0xB5), D1(0x76), D1(0x62), D1(0x5E), D1(0x7E), D1(0xC6), D1(0xF4), D1(0x4C), D1(0x42), D1(0xE9), D1(0xA6), D1(0x37), D1(0xED), D1(0x6B), D1(0x0B), D1(0xFF), D1(0x5C), D1(0xB6), D1(0xF4), D1(0x06), D1(0xB7), D1(0xED), D1(0xEE), D1(0x38), D1(0x6B), D1(0xFB), D1(0x5A), D1(0x89), D1(0x9F), D1(0xA5), D1(0xAE), D1(0x9F), D1(0x24), D1(0x11), D1(0x7C), D1(0x4B), D1(0x1F), D1(0xE6), D1(0x49), D1(0x28), D1(0x66), D1(0x51), D1(0xEC), D1(0xE4), D1(0x5B), D1(0x3D), D1(0xC2), D1(0x00), D1(0x7C), D1(0xB8), D1(0xA1), D1(0x63), D1(0xBF), D1(0x05), D1(0x98), D1(0xDA), D1(0x48), D1(0x36), D1(0x1C), D1(0x55), D1(0xD3), D1(0x9A), D1(0x69), D1(0x16), D1(0x3F), D1(0xA8), D1(0xFD), D1(0x24), D1(0xCF), D1(0x5F), D1(0x83), D1(0x65), D1(0x5D), D1(0x23), D1(0xDC), D1(0xA3), D1(0xAD), D1(0x96), D1(0x1C), D1(0x62), D1(0xF3), D1(0x56), D1(0x20), D1(0x85), D1(0x52), D1(0xBB), D1(0x9E), D1(0xD5), D1(0x29), D1(0x07), D1(0x70), D1(0x96), D1(0x96), D1(0x6D), D1(0x67), D1(0x0C), D1(0x35), D1(0x4E), D1(0x4A), D1(0xBC), D1(0x98), D1(0x04), D1(0xF1), D1(0x74), D1(0x6C), D1(0x08), D1(0xCA), D1(0x18), D1(0x21), D1(0x7C), D1(0x32), D1(0x90), D1(0x5E), D1(0x46), D1(0x2E), D1(0x36), D1(0xCE), D1(0x3B), D1(0xE3), D1(0x9E), D1(0x77), D1(0x2C), D1(0x18), D1(0x0E), D1(0x86), D1(0x03), D1(0x9B), D1(0x27), D1(0x83), D1(0xA2), D1(0xEC), D1(0x07), D1(0xA2), D1(0x8F), D1(0xB5), D1(0xC5), D1(0x5D), D1(0xF0), D1(0x6F), D1(0x4C), D1(0x52), D1(0xC9), D1(0xDE), D1(0x2B), D1(0xCB), D1(0xF6), D1(0x95), D1(0x58), D1(0x17), D1(0x18), D1(0x39), D1(0x95), D1(0x49), D1(0x7C), D1(0xEA), D1(0x95), D1(0x6A), D1(0xE5), D1(0x15), D1(0xD2), D1(0x26), D1(0x18), D1(0x98), D1(0xFA), D1(0x05), D1(0x10), D1(0x15), D1(0x72), D1(0x8E), D1(0x5A), D1(0x8A), D1(0xAA), D1(0xC4), D1(0x2D), D1(0xAD), D1(0x33), D1(0x17), D1(0x0D), D1(0x04), D1(0x50), D1(0x7A), D1(0x33), D1(0xA8), D1(0x55), D1(0x21), D1(0xAB), D1(0xDF), D1(0x1C), D1(0xBA), D1(0x65) + #endif + #if (intDsize==16) + D2(0xC9,0x0F), D2(0xDA,0xA2), D2(0x21,0x68), D2(0xC2,0x34), D2(0xC4,0xC6), D2(0x62,0x8B), D2(0x80,0xDC), D2(0x1C,0xD1), D2(0x29,0x02), D2(0x4E,0x08), D2(0x8A,0x67), D2(0xCC,0x74), D2(0x02,0x0B), D2(0xBE,0xA6), D2(0x3B,0x13), D2(0x9B,0x22), D2(0x51,0x4A), D2(0x08,0x79), D2(0x8E,0x34), D2(0x04,0xDD), D2(0xEF,0x95), D2(0x19,0xB3), D2(0xCD,0x3A), D2(0x43,0x1B), D2(0x30,0x2B), D2(0x0A,0x6D), D2(0xF2,0x5F), D2(0x14,0x37), D2(0x4F,0xE1), D2(0x35,0x6D), D2(0x6D,0x51), D2(0xC2,0x45), D2(0xE4,0x85), D2(0xB5,0x76), D2(0x62,0x5E), D2(0x7E,0xC6), D2(0xF4,0x4C), D2(0x42,0xE9), D2(0xA6,0x37), D2(0xED,0x6B), D2(0x0B,0xFF), D2(0x5C,0xB6), D2(0xF4,0x06), D2(0xB7,0xED), D2(0xEE,0x38), D2(0x6B,0xFB), D2(0x5A,0x89), D2(0x9F,0xA5), D2(0xAE,0x9F), D2(0x24,0x11), D2(0x7C,0x4B), D2(0x1F,0xE6), D2(0x49,0x28), D2(0x66,0x51), D2(0xEC,0xE4), D2(0x5B,0x3D), D2(0xC2,0x00), D2(0x7C,0xB8), D2(0xA1,0x63), D2(0xBF,0x05), D2(0x98,0xDA), D2(0x48,0x36), D2(0x1C,0x55), D2(0xD3,0x9A), D2(0x69,0x16), D2(0x3F,0xA8), D2(0xFD,0x24), D2(0xCF,0x5F), D2(0x83,0x65), D2(0x5D,0x23), D2(0xDC,0xA3), D2(0xAD,0x96), D2(0x1C,0x62), D2(0xF3,0x56), D2(0x20,0x85), D2(0x52,0xBB), D2(0x9E,0xD5), D2(0x29,0x07), D2(0x70,0x96), D2(0x96,0x6D), D2(0x67,0x0C), D2(0x35,0x4E), D2(0x4A,0xBC), D2(0x98,0x04), D2(0xF1,0x74), D2(0x6C,0x08), D2(0xCA,0x18), D2(0x21,0x7C), D2(0x32,0x90), D2(0x5E,0x46), D2(0x2E,0x36), D2(0xCE,0x3B), D2(0xE3,0x9E), D2(0x77,0x2C), D2(0x18,0x0E), D2(0x86,0x03), D2(0x9B,0x27), D2(0x83,0xA2), D2(0xEC,0x07), D2(0xA2,0x8F), D2(0xB5,0xC5), D2(0x5D,0xF0), D2(0x6F,0x4C), D2(0x52,0xC9), D2(0xDE,0x2B), D2(0xCB,0xF6), D2(0x95,0x58), D2(0x17,0x18), D2(0x39,0x95), D2(0x49,0x7C), D2(0xEA,0x95), D2(0x6A,0xE5), D2(0x15,0xD2), D2(0x26,0x18), D2(0x98,0xFA), D2(0x05,0x10), D2(0x15,0x72), D2(0x8E,0x5A), D2(0x8A,0xAA), D2(0xC4,0x2D), D2(0xAD,0x33), D2(0x17,0x0D), D2(0x04,0x50), D2(0x7A,0x33), D2(0xA8,0x55), D2(0x21,0xAB), D2(0xDF,0x1C), D2(0xBA,0x65) + #endif + #if (intDsize==32) + D4(0xC9,0x0F,0xDA,0xA2), D4(0x21,0x68,0xC2,0x34), D4(0xC4,0xC6,0x62,0x8B), D4(0x80,0xDC,0x1C,0xD1), D4(0x29,0x02,0x4E,0x08), D4(0x8A,0x67,0xCC,0x74), D4(0x02,0x0B,0xBE,0xA6), D4(0x3B,0x13,0x9B,0x22), D4(0x51,0x4A,0x08,0x79), D4(0x8E,0x34,0x04,0xDD), D4(0xEF,0x95,0x19,0xB3), D4(0xCD,0x3A,0x43,0x1B), D4(0x30,0x2B,0x0A,0x6D), D4(0xF2,0x5F,0x14,0x37), D4(0x4F,0xE1,0x35,0x6D), D4(0x6D,0x51,0xC2,0x45), D4(0xE4,0x85,0xB5,0x76), D4(0x62,0x5E,0x7E,0xC6), D4(0xF4,0x4C,0x42,0xE9), D4(0xA6,0x37,0xED,0x6B), D4(0x0B,0xFF,0x5C,0xB6), D4(0xF4,0x06,0xB7,0xED), D4(0xEE,0x38,0x6B,0xFB), D4(0x5A,0x89,0x9F,0xA5), D4(0xAE,0x9F,0x24,0x11), D4(0x7C,0x4B,0x1F,0xE6), D4(0x49,0x28,0x66,0x51), D4(0xEC,0xE4,0x5B,0x3D), D4(0xC2,0x00,0x7C,0xB8), D4(0xA1,0x63,0xBF,0x05), D4(0x98,0xDA,0x48,0x36), D4(0x1C,0x55,0xD3,0x9A), D4(0x69,0x16,0x3F,0xA8), D4(0xFD,0x24,0xCF,0x5F), D4(0x83,0x65,0x5D,0x23), D4(0xDC,0xA3,0xAD,0x96), D4(0x1C,0x62,0xF3,0x56), D4(0x20,0x85,0x52,0xBB), D4(0x9E,0xD5,0x29,0x07), D4(0x70,0x96,0x96,0x6D), D4(0x67,0x0C,0x35,0x4E), D4(0x4A,0xBC,0x98,0x04), D4(0xF1,0x74,0x6C,0x08), D4(0xCA,0x18,0x21,0x7C), D4(0x32,0x90,0x5E,0x46), D4(0x2E,0x36,0xCE,0x3B), D4(0xE3,0x9E,0x77,0x2C), D4(0x18,0x0E,0x86,0x03), D4(0x9B,0x27,0x83,0xA2), D4(0xEC,0x07,0xA2,0x8F), D4(0xB5,0xC5,0x5D,0xF0), D4(0x6F,0x4C,0x52,0xC9), D4(0xDE,0x2B,0xCB,0xF6), D4(0x95,0x58,0x17,0x18), D4(0x39,0x95,0x49,0x7C), D4(0xEA,0x95,0x6A,0xE5), D4(0x15,0xD2,0x26,0x18), D4(0x98,0xFA,0x05,0x10), D4(0x15,0x72,0x8E,0x5A), D4(0x8A,0xAA,0xC4,0x2D), D4(0xAD,0x33,0x17,0x0D), D4(0x04,0x50,0x7A,0x33), D4(0xA8,0x55,0x21,0xAB), D4(0xDF,0x1C,0xBA,0x65) + #endif + #if (intDsize==64) + D8(0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34), D8(0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1), D8(0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74), D8(0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22), D8(0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD), D8(0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B), D8(0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37), D8(0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45), D8(0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6), D8(0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B), D8(0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED), D8(0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5), D8(0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6), D8(0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D), D8(0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05), D8(0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A), D8(0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F), D8(0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96), D8(0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB), D8(0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D), D8(0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04), D8(0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C), D8(0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B), D8(0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03), D8(0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F), D8(0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9), D8(0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18), D8(0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5), D8(0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10), D8(0x15,0x72,0x8E,0x5A,0x8A,0xAA,0xC4,0x2D), D8(0xAD,0x33,0x17,0x0D,0x04,0x50,0x7A,0x33), D8(0xA8,0x55,0x21,0xAB,0xDF,0x1C,0xBA,0x65) + #endif +#else + #if (intDsize==8) + D1(0x65), D1(0xBA), D1(0x1C), D1(0xDF), D1(0xAB), D1(0x21), D1(0x55), D1(0xA8), D1(0x33), D1(0x7A), D1(0x50), D1(0x04), D1(0x0D), D1(0x17), D1(0x33), D1(0xAD), D1(0x2D), D1(0xC4), D1(0xAA), D1(0x8A), D1(0x5A), D1(0x8E), D1(0x72), D1(0x15), D1(0x10), D1(0x05), D1(0xFA), D1(0x98), D1(0x18), D1(0x26), D1(0xD2), D1(0x15), D1(0xE5), D1(0x6A), D1(0x95), D1(0xEA), D1(0x7C), D1(0x49), D1(0x95), D1(0x39), D1(0x18), D1(0x17), D1(0x58), D1(0x95), D1(0xF6), D1(0xCB), D1(0x2B), D1(0xDE), D1(0xC9), D1(0x52), D1(0x4C), D1(0x6F), D1(0xF0), D1(0x5D), D1(0xC5), D1(0xB5), D1(0x8F), D1(0xA2), D1(0x07), D1(0xEC), D1(0xA2), D1(0x83), D1(0x27), D1(0x9B), D1(0x03), D1(0x86), D1(0x0E), D1(0x18), D1(0x2C), D1(0x77), D1(0x9E), D1(0xE3), D1(0x3B), D1(0xCE), D1(0x36), D1(0x2E), D1(0x46), D1(0x5E), D1(0x90), D1(0x32), D1(0x7C), D1(0x21), D1(0x18), D1(0xCA), D1(0x08), D1(0x6C), D1(0x74), D1(0xF1), D1(0x04), D1(0x98), D1(0xBC), D1(0x4A), D1(0x4E), D1(0x35), D1(0x0C), D1(0x67), D1(0x6D), D1(0x96), D1(0x96), D1(0x70), D1(0x07), D1(0x29), D1(0xD5), D1(0x9E), D1(0xBB), D1(0x52), D1(0x85), D1(0x20), D1(0x56), D1(0xF3), D1(0x62), D1(0x1C), D1(0x96), D1(0xAD), D1(0xA3), D1(0xDC), D1(0x23), D1(0x5D), D1(0x65), D1(0x83), D1(0x5F), D1(0xCF), D1(0x24), D1(0xFD), D1(0xA8), D1(0x3F), D1(0x16), D1(0x69), D1(0x9A), D1(0xD3), D1(0x55), D1(0x1C), D1(0x36), D1(0x48), D1(0xDA), D1(0x98), D1(0x05), D1(0xBF), D1(0x63), D1(0xA1), D1(0xB8), D1(0x7C), D1(0x00), D1(0xC2), D1(0x3D), D1(0x5B), D1(0xE4), D1(0xEC), D1(0x51), D1(0x66), D1(0x28), D1(0x49), D1(0xE6), D1(0x1F), D1(0x4B), D1(0x7C), D1(0x11), D1(0x24), D1(0x9F), D1(0xAE), D1(0xA5), D1(0x9F), D1(0x89), D1(0x5A), D1(0xFB), D1(0x6B), D1(0x38), D1(0xEE), D1(0xED), D1(0xB7), D1(0x06), D1(0xF4), D1(0xB6), D1(0x5C), D1(0xFF), D1(0x0B), D1(0x6B), D1(0xED), D1(0x37), D1(0xA6), D1(0xE9), D1(0x42), D1(0x4C), D1(0xF4), D1(0xC6), D1(0x7E), D1(0x5E), D1(0x62), D1(0x76), D1(0xB5), D1(0x85), D1(0xE4), D1(0x45), D1(0xC2), D1(0x51), D1(0x6D), D1(0x6D), D1(0x35), D1(0xE1), D1(0x4F), D1(0x37), D1(0x14), D1(0x5F), D1(0xF2), D1(0x6D), D1(0x0A), D1(0x2B), D1(0x30), D1(0x1B), D1(0x43), D1(0x3A), D1(0xCD), D1(0xB3), D1(0x19), D1(0x95), D1(0xEF), D1(0xDD), D1(0x04), D1(0x34), D1(0x8E), D1(0x79), D1(0x08), D1(0x4A), D1(0x51), D1(0x22), D1(0x9B), D1(0x13), D1(0x3B), D1(0xA6), D1(0xBE), D1(0x0B), D1(0x02), D1(0x74), D1(0xCC), D1(0x67), D1(0x8A), D1(0x08), D1(0x4E), D1(0x02), D1(0x29), D1(0xD1), D1(0x1C), D1(0xDC), D1(0x80), D1(0x8B), D1(0x62), D1(0xC6), D1(0xC4), D1(0x34), D1(0xC2), D1(0x68), D1(0x21), D1(0xA2), D1(0xDA), D1(0x0F), D1(0xC9) + #endif + #if (intDsize==16) + D2(0xBA,0x65), D2(0xDF,0x1C), D2(0x21,0xAB), D2(0xA8,0x55), D2(0x7A,0x33), D2(0x04,0x50), D2(0x17,0x0D), D2(0xAD,0x33), D2(0xC4,0x2D), D2(0x8A,0xAA), D2(0x8E,0x5A), D2(0x15,0x72), D2(0x05,0x10), D2(0x98,0xFA), D2(0x26,0x18), D2(0x15,0xD2), D2(0x6A,0xE5), D2(0xEA,0x95), D2(0x49,0x7C), D2(0x39,0x95), D2(0x17,0x18), D2(0x95,0x58), D2(0xCB,0xF6), D2(0xDE,0x2B), D2(0x52,0xC9), D2(0x6F,0x4C), D2(0x5D,0xF0), D2(0xB5,0xC5), D2(0xA2,0x8F), D2(0xEC,0x07), D2(0x83,0xA2), D2(0x9B,0x27), D2(0x86,0x03), D2(0x18,0x0E), D2(0x77,0x2C), D2(0xE3,0x9E), D2(0xCE,0x3B), D2(0x2E,0x36), D2(0x5E,0x46), D2(0x32,0x90), D2(0x21,0x7C), D2(0xCA,0x18), D2(0x6C,0x08), D2(0xF1,0x74), D2(0x98,0x04), D2(0x4A,0xBC), D2(0x35,0x4E), D2(0x67,0x0C), D2(0x96,0x6D), D2(0x70,0x96), D2(0x29,0x07), D2(0x9E,0xD5), D2(0x52,0xBB), D2(0x20,0x85), D2(0xF3,0x56), D2(0x1C,0x62), D2(0xAD,0x96), D2(0xDC,0xA3), D2(0x5D,0x23), D2(0x83,0x65), D2(0xCF,0x5F), D2(0xFD,0x24), D2(0x3F,0xA8), D2(0x69,0x16), D2(0xD3,0x9A), D2(0x1C,0x55), D2(0x48,0x36), D2(0x98,0xDA), D2(0xBF,0x05), D2(0xA1,0x63), D2(0x7C,0xB8), D2(0xC2,0x00), D2(0x5B,0x3D), D2(0xEC,0xE4), D2(0x66,0x51), D2(0x49,0x28), D2(0x1F,0xE6), D2(0x7C,0x4B), D2(0x24,0x11), D2(0xAE,0x9F), D2(0x9F,0xA5), D2(0x5A,0x89), D2(0x6B,0xFB), D2(0xEE,0x38), D2(0xB7,0xED), D2(0xF4,0x06), D2(0x5C,0xB6), D2(0x0B,0xFF), D2(0xED,0x6B), D2(0xA6,0x37), D2(0x42,0xE9), D2(0xF4,0x4C), D2(0x7E,0xC6), D2(0x62,0x5E), D2(0xB5,0x76), D2(0xE4,0x85), D2(0xC2,0x45), D2(0x6D,0x51), D2(0x35,0x6D), D2(0x4F,0xE1), D2(0x14,0x37), D2(0xF2,0x5F), D2(0x0A,0x6D), D2(0x30,0x2B), D2(0x43,0x1B), D2(0xCD,0x3A), D2(0x19,0xB3), D2(0xEF,0x95), D2(0x04,0xDD), D2(0x8E,0x34), D2(0x08,0x79), D2(0x51,0x4A), D2(0x9B,0x22), D2(0x3B,0x13), D2(0xBE,0xA6), D2(0x02,0x0B), D2(0xCC,0x74), D2(0x8A,0x67), D2(0x4E,0x08), D2(0x29,0x02), D2(0x1C,0xD1), D2(0x80,0xDC), D2(0x62,0x8B), D2(0xC4,0xC6), D2(0xC2,0x34), D2(0x21,0x68), D2(0xDA,0xA2), D2(0xC9,0x0F) + #endif + #if (intDsize==32) + D4(0xDF,0x1C,0xBA,0x65), D4(0xA8,0x55,0x21,0xAB), D4(0x04,0x50,0x7A,0x33), D4(0xAD,0x33,0x17,0x0D), D4(0x8A,0xAA,0xC4,0x2D), D4(0x15,0x72,0x8E,0x5A), D4(0x98,0xFA,0x05,0x10), D4(0x15,0xD2,0x26,0x18), D4(0xEA,0x95,0x6A,0xE5), D4(0x39,0x95,0x49,0x7C), D4(0x95,0x58,0x17,0x18), D4(0xDE,0x2B,0xCB,0xF6), D4(0x6F,0x4C,0x52,0xC9), D4(0xB5,0xC5,0x5D,0xF0), D4(0xEC,0x07,0xA2,0x8F), D4(0x9B,0x27,0x83,0xA2), D4(0x18,0x0E,0x86,0x03), D4(0xE3,0x9E,0x77,0x2C), D4(0x2E,0x36,0xCE,0x3B), D4(0x32,0x90,0x5E,0x46), D4(0xCA,0x18,0x21,0x7C), D4(0xF1,0x74,0x6C,0x08), D4(0x4A,0xBC,0x98,0x04), D4(0x67,0x0C,0x35,0x4E), D4(0x70,0x96,0x96,0x6D), D4(0x9E,0xD5,0x29,0x07), D4(0x20,0x85,0x52,0xBB), D4(0x1C,0x62,0xF3,0x56), D4(0xDC,0xA3,0xAD,0x96), D4(0x83,0x65,0x5D,0x23), D4(0xFD,0x24,0xCF,0x5F), D4(0x69,0x16,0x3F,0xA8), D4(0x1C,0x55,0xD3,0x9A), D4(0x98,0xDA,0x48,0x36), D4(0xA1,0x63,0xBF,0x05), D4(0xC2,0x00,0x7C,0xB8), D4(0xEC,0xE4,0x5B,0x3D), D4(0x49,0x28,0x66,0x51), D4(0x7C,0x4B,0x1F,0xE6), D4(0xAE,0x9F,0x24,0x11), D4(0x5A,0x89,0x9F,0xA5), D4(0xEE,0x38,0x6B,0xFB), D4(0xF4,0x06,0xB7,0xED), D4(0x0B,0xFF,0x5C,0xB6), D4(0xA6,0x37,0xED,0x6B), D4(0xF4,0x4C,0x42,0xE9), D4(0x62,0x5E,0x7E,0xC6), D4(0xE4,0x85,0xB5,0x76), D4(0x6D,0x51,0xC2,0x45), D4(0x4F,0xE1,0x35,0x6D), D4(0xF2,0x5F,0x14,0x37), D4(0x30,0x2B,0x0A,0x6D), D4(0xCD,0x3A,0x43,0x1B), D4(0xEF,0x95,0x19,0xB3), D4(0x8E,0x34,0x04,0xDD), D4(0x51,0x4A,0x08,0x79), D4(0x3B,0x13,0x9B,0x22), D4(0x02,0x0B,0xBE,0xA6), D4(0x8A,0x67,0xCC,0x74), D4(0x29,0x02,0x4E,0x08), D4(0x80,0xDC,0x1C,0xD1), D4(0xC4,0xC6,0x62,0x8B), D4(0x21,0x68,0xC2,0x34), D4(0xC9,0x0F,0xDA,0xA2) + #endif + #if (intDsize==64) + D8(0xA8,0x55,0x21,0xAB,0xDF,0x1C,0xBA,0x65), D8(0xAD,0x33,0x17,0x0D,0x04,0x50,0x7A,0x33), D8(0x15,0x72,0x8E,0x5A,0x8A,0xAA,0xC4,0x2D), D8(0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10), D8(0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5), D8(0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18), D8(0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9), D8(0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F), D8(0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03), D8(0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B), D8(0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C), D8(0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04), D8(0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D), D8(0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB), D8(0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96), D8(0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F), D8(0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A), D8(0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05), D8(0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D), D8(0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6), D8(0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5), D8(0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED), D8(0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B), D8(0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6), D8(0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45), D8(0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37), D8(0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B), D8(0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD), D8(0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22), D8(0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74), D8(0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1), D8(0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34) + #endif +#endif +} ; diff --git a/src/float/transcendental/cl_F_pi_var.h.in b/src/float/transcendental/cl_F_pi_var.h.in new file mode 100644 index 0000000..ddf82f8 --- /dev/null +++ b/src/float/transcendental/cl_F_pi_var.h.in @@ -0,0 +1,23 @@ +// Digits of pi. + { D(0xC9,0x0F,0xDA,0xA2,) D(0x21,0x68,0xC2,0x34,) D(0xC4,0xC6,0x62,0x8B,) + D(0x80,0xDC,0x1C,0xD1,) D(0x29,0x02,0x4E,0x08,) D(0x8A,0x67,0xCC,0x74,) + D(0x02,0x0B,0xBE,0xA6,) D(0x3B,0x13,0x9B,0x22,) D(0x51,0x4A,0x08,0x79,) + D(0x8E,0x34,0x04,0xDD,) D(0xEF,0x95,0x19,0xB3,) D(0xCD,0x3A,0x43,0x1B,) + D(0x30,0x2B,0x0A,0x6D,) D(0xF2,0x5F,0x14,0x37,) D(0x4F,0xE1,0x35,0x6D,) + D(0x6D,0x51,0xC2,0x45,) D(0xE4,0x85,0xB5,0x76,) D(0x62,0x5E,0x7E,0xC6,) + D(0xF4,0x4C,0x42,0xE9,) D(0xA6,0x37,0xED,0x6B,) D(0x0B,0xFF,0x5C,0xB6,) + D(0xF4,0x06,0xB7,0xED,) D(0xEE,0x38,0x6B,0xFB,) D(0x5A,0x89,0x9F,0xA5,) + D(0xAE,0x9F,0x24,0x11,) D(0x7C,0x4B,0x1F,0xE6,) D(0x49,0x28,0x66,0x51,) + D(0xEC,0xE4,0x5B,0x3D,) D(0xC2,0x00,0x7C,0xB8,) D(0xA1,0x63,0xBF,0x05,) + D(0x98,0xDA,0x48,0x36,) D(0x1C,0x55,0xD3,0x9A,) D(0x69,0x16,0x3F,0xA8,) + D(0xFD,0x24,0xCF,0x5F,) D(0x83,0x65,0x5D,0x23,) D(0xDC,0xA3,0xAD,0x96,) + D(0x1C,0x62,0xF3,0x56,) D(0x20,0x85,0x52,0xBB,) D(0x9E,0xD5,0x29,0x07,) + D(0x70,0x96,0x96,0x6D,) D(0x67,0x0C,0x35,0x4E,) D(0x4A,0xBC,0x98,0x04,) + D(0xF1,0x74,0x6C,0x08,) D(0xCA,0x18,0x21,0x7C,) D(0x32,0x90,0x5E,0x46,) + D(0x2E,0x36,0xCE,0x3B,) D(0xE3,0x9E,0x77,0x2C,) D(0x18,0x0E,0x86,0x03,) + D(0x9B,0x27,0x83,0xA2,) D(0xEC,0x07,0xA2,0x8F,) D(0xB5,0xC5,0x5D,0xF0,) + D(0x6F,0x4C,0x52,0xC9,) D(0xDE,0x2B,0xCB,0xF6,) D(0x95,0x58,0x17,0x18,) + D(0x39,0x95,0x49,0x7C,) D(0xEA,0x95,0x6A,0xE5,) D(0x15,0xD2,0x26,0x18,) + D(0x98,0xFA,0x05,0x10,) D(0x15,0x72,0x8E,0x5A,) D(0x8A,0xAA,0xC4,0x2D,) + D(0xAD,0x33,0x17,0x0D,) D(0x04,0x50,0x7A,0x33,) D(0xA8,0x55,0x21,0xAB,) + D(0xDF,0x1C,0xBA,0x65,) } ; diff --git a/src/float/transcendental/cl_F_roundpi.cc b/src/float/transcendental/cl_F_roundpi.cc new file mode 100644 index 0000000..dad4e04 --- /dev/null +++ b/src/float/transcendental/cl_F_roundpi.cc @@ -0,0 +1,20 @@ +// cl_round_pi(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +const cl_F_div_t cl_round_pi (const cl_F& x) +{ + if (float_exponent(x) <= 0) + // Exponent <=0 -> |x|<1 -> |x/pi| < 1/2, also Division unnötig + return cl_F_div_t(0,x); // Quotient 0, Rest x + else + // x durch pi (mit hinreichender Genauigkeit) dividieren + return round2(x,cl_pi(x)); +} diff --git a/src/float/transcendental/cl_F_roundpi2.cc b/src/float/transcendental/cl_F_roundpi2.cc new file mode 100644 index 0000000..9503a77 --- /dev/null +++ b/src/float/transcendental/cl_F_roundpi2.cc @@ -0,0 +1,20 @@ +// cl_round_pi2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +const cl_F_div_t cl_round_pi2 (const cl_F& x) +{ + if (float_exponent(x) < 0) + // Exponent <0 -> |x|<1/2 -> |x/(pi/2)| < 1/2, also Division unnötig + return cl_F_div_t(0,x); // Quotient 0, Rest x + else + // x durch pi/2 (mit hinreichender Genauigkeit) dividieren + return round2(x,scale_float(cl_pi(x),-1)); +} diff --git a/src/float/transcendental/cl_F_sin.cc b/src/float/transcendental/cl_F_sin.cc new file mode 100644 index 0000000..517afcc --- /dev/null +++ b/src/float/transcendental/cl_F_sin.cc @@ -0,0 +1,102 @@ +// sin(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F_tran.h" +#include "cl_F.h" +#include "cl_integer.h" +#include "cl_lfloat.h" +#include "cl_LF.h" + +const cl_F sin (const cl_F& x) +{ +// Methode: +// Genauigkeit erhöhen, +// (q,r) := (round x (float pi/2 x)), so daß |r|<=pi/4. +// y:=(sin(r)/r)^2 errechnen. +// Falls q gerade: +// sin(r) berechnen: r*sqrt(y). +// Falls q ungerade: +// cos(r) berechnen: +// e := Exponent aus (decode-float r), d := (float-digits r) +// Bei r=0.0 oder e<=-d/2 liefere 1.0 +// (denn bei e<=-d/2 ist r^2/2 < 2^(-d)/2 = 2^(-d-1), also +// 1 >= cos(r) > 1-r^2/2 > 1-2^(-d-1), +// also ist cos(r), auf d Bits gerundet, gleich 1.0). +// Sonst sqrt(1-r^2*y). +// Falls q == 2,3 mod 4, Vorzeichenwechsel. + + // Rechengenauigkeit erhöhen und durch pi/2 dividieren: + var cl_F z; + var cl_I q; + if (longfloatp(x)) { + DeclareType(cl_LF,x); + if (TheLfloat(x)->len >= 2750) { + var cl_F_div_t q_r = cl_round_pi2(extend(x,TheLfloat(x)->len+1)); + q = q_r.quotient; + var cl_LF r = The(cl_LF)(q_r.remainder); + var cl_LF_cos_sin_t trig = cl_cossin_ratseries(r); + if (evenp(q)) + z = cl_float(trig.sin,x); + else + z = cl_float(trig.cos,x); + } else { + var cl_F_div_t q_r = cl_round_pi2(cl_F_extendsqrt(x)); + q = q_r.quotient; + var cl_LF r = The(cl_LF)(q_r.remainder); + var cl_LF y = sinx_naive(r); // y := sin(r)^2 + if (evenp(q)) { + // sin(r) berechnen: + z = cl_float(sqrt(y),x); + if (minusp(r)) + z = -z; + } else { + // cos(r) berechnen: + if (zerop(r) || (float_exponent(r) <= (-(sintL)float_digits(r))>>1)) + z = cl_float(1,x); // cos(r) = 1.0 + else + z = cl_float(sqrt(1 - y),x); // sqrt(1-y) + } + } + } else { + var cl_F_div_t q_r = cl_round_pi2(cl_F_extendsqrt(x)); + q = q_r.quotient; + var cl_F& r = q_r.remainder; + var cl_F y = sinxbyx_naive(r); // y := (sin(r)/r)^2 + if (evenp(q)) { + // sin(r) berechnen: + z = cl_float(r*sqrt(y),x); + } else { + // cos(r) berechnen: + if (zerop(r) || (float_exponent(r) <= (-(sintL)float_digits(r))>>1)) + z = cl_float(1,x); // cos(r) = 1.0 + else + z = cl_float(sqrt(1 - square(r)*y),x); // sqrt(1-r^2*y) + } + } + // evtl. Vorzeichenwechsel: + if (cl_I_to_UL(logand(q,2))==0) + return z; + else + return -z; +} + +// Timings of the two algorithms, on an i486 33 MHz, running Linux, +// applied to x = sqrt(2)-1 = 0.414... +// N naive ratseries +// 10 0.010 0.048 +// 25 0.035 0.119 +// 50 0.12 0.37 +// 100 0.44 1.09 +// 250 2.8 5.5 +// 500 11.6 19.4 +// 1000 48 64 +// 2500 243 261 +// ==> ratseries faster for N >= 2750. diff --git a/src/float/transcendental/cl_F_sinh.cc b/src/float/transcendental/cl_F_sinh.cc new file mode 100644 index 0000000..25ae007 --- /dev/null +++ b/src/float/transcendental/cl_F_sinh.cc @@ -0,0 +1,77 @@ +// sinh(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F_tran.h" +#include "cl_F.h" +#include "cl_lfloat.h" +#include "cl_LF.h" + +const cl_F sinh (const cl_F& x) +{ +// Methode: +// Genauigkeit erhöhen, +// e := Exponent aus (decode-float x) +// falls e<0: (sinh(x)/x)^2 errechnen, Wurzel ziehen, mit x multiplizieren. +// falls e>=0: y:=exp(x) errechnen, (scale-float (- y (/ y)) -1) bilden. + + if (float_exponent(x) < 0) { // Exponent e abtesten + // e<0 + // Rechengenauigkeit erhöhen + if (longfloatp(x)) { + DeclareType(cl_LF,x); + #if 0 + if (TheLfloat(x)->len >= infty) { + var cl_LF xx = extend(x,TheLfloat(x)->len+1); + var cl_LF_cosh_sinh_t hyp = cl_coshsinh_ratseries(xx); + return cl_float(hyp.sinh,x); + } else + #endif + if ((TheLfloat(x)->len >= 500) + && (float_exponent(x) > (-(sintL)float_digits(x))>>1)) { + // verwende exp(x), schneller als cl_coshsinh_ratseries + // (aber nur bei 0 > e > -d/2, denn wir müssen, um + // Auslöschung zu verhindern, |e| Bits dazunehmen) + var cl_LF xx = extend(x,TheLfloat(x)->len+ceiling((uintL)(-float_exponent(x)),intDsize)); + var cl_F y = exp(xx); + var cl_F z = scale_float(y - recip(y), -1); // (/ (- y (/ y)) 2) + return cl_float(z,x); + } else { + var cl_LF xx = The(cl_LF)(cl_F_extendsqrt(x)); + // Wurzel aus sinh(x)^2 bilden + var cl_LF z = sqrt(sinhx_naive(xx)); + if (minusp(xx)) + z = -z; + return cl_float(z,x); + } + } else { + var cl_F xx = cl_F_extendsqrt(x); + // Wurzel aus (sinh(x)/x)^2 mit x multiplizieren und wieder runden + return cl_float(sqrt(sinhxbyx_naive(xx))*xx,x); + } + } else { + // e>=0 -> verwende exp(x) + var cl_F y = exp(x); + return scale_float(y - recip(y), -1); // (/ (- y (/ y)) 2) + } +} + +// Timings of the two algorithms, on an i486 33 MHz, running Linux, +// applied to x = sqrt(2)-1 = 0.414... +// N naive ratseries +// 10 0.008 0.037 +// 25 0.034 0.115 +// 50 0.13 0.33 +// 100 0.50 1.07 +// 250 3.3 5.2 +// 500 14.2 18.8 +// 1000 59 61 +// 2500 297 247 +// ==> ratseries faster for N >= 1300. diff --git a/src/float/transcendental/cl_F_sinhx.cc b/src/float/transcendental/cl_F_sinhx.cc new file mode 100644 index 0000000..b440196 --- /dev/null +++ b/src/float/transcendental/cl_F_sinhx.cc @@ -0,0 +1,206 @@ +// sinhxbyx(), sinhx(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +#include "cl_float.h" +#include "cl_low.h" +#include "cl_F.h" +#include "cl_lfloat.h" +#include "cl_LF.h" +#include "cl_integer.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_LF_zerop.cc" +#include "cl_LF_exponent.cc" + +// sinhxbyx is mainly for cl_SF, cl_FF, cl_DF, where we want to avoid underflow. + +const cl_F sinhxbyx_naive (const cl_F& x) +{ +// Methode: +// e := Exponent aus (decode-float x), d := (float-digits x) +// Bei x=0.0 oder e<=(1-d)/2 liefere 1.0 +// (denn bei e<=(1-d)/2 ist x^2/6 < x^2/4 < 2^(1-d)/4 = 2^(-d-1), also +// 1 <= sinh(x)/x = 1+x^2/6+... < 1+2^(-d-1), also 1 <= (sinh(x)/x)^2 < 1+2^(-d), +// also ist (sinh(x)/x)^2, auf d Bits gerundet, gleich 1.0). +// Bei e<=-sqrt(d) verwende die Potenzreihe +// sinh(x)/x = sum(j=0..inf,(x^2)^j/(2j+1)!): +// a:=x^2, b:=1, i:=1, sum:=0, +// while (/= sum (setq sum (+ sum b))) do b:=b*a/((i+1)*(i+2)), i:=i+2. +// Ergebnis sum^2. +// Sonst setze y := x/2 = (scale-float x -1), +// berechne rekursiv z:=(sinh(y)/y)^2 und liefere z*(1+y^2*z). +// [Die Grenze sqrt(d) ergibt sich so: +// Man braucht bei der Potenzreihe mit x=2^-k etwa j Glieder, mit +// k*j*ln 2 + j*(ln j - 1) = d, und der Aufwand beträgt etwa 2.8*(j/2) +// Multiplikationen von d-Bit-Zahlen. Bei Halbierungen bis x=2^-k ist der +// Gesamtaufwand etwa 2*(k+e)+1.4*j(k). Dieses minimieren nach k: Soll sein +// -1.4 = d/dk j(k) = (d/dj k(j))^-1 = - j^2/(d+j)*ln 2, also j^2=2(d+j), +// grob j=sqrt(2d) und damit k=sqrt(d).] +// Aufwand: asymptotisch d^2.5 . + + if (zerop(x)) + return cl_float(1,x); + var uintL d = float_digits(x); + var sintL e = float_exponent(x); + if (e <= (1-(sintL)d)>>1) // e <= (1-d)/2 <==> e <= -ceiling((d-1)/2) ? + return cl_float(1,x); // ja -> 1.0 als Ergebnis + { Mutable(cl_F,x); + // Bei e <= -1-limit_slope*floor(sqrt(d)) kann die Potenzreihe + // angewandt werden. Wähle limit_slope = 13/32 = 0.4. + var sintL e_limit = -1-floor(isqrt(d)*13,32); // -1-floor(sqrt(d)) + if (e > e_limit) { + // e > -1-limit_slope*floor(sqrt(d)) -> muß |x| verkleinern. + x = scale_float(x,e_limit-e); + // Neuer Exponent = e_limit. + } + var cl_F x2 = square(x); // x^2 + // Potenzreihe anwenden: + var cl_F a = x2; // a := x^2 + var int i = 1; + var cl_F b = cl_float(1,x); // b := (float 1 x) + var cl_F sum = cl_float(0,x); // sum := (float 0 x) + loop { + var cl_F new_sum = sum + b; + if (new_sum == sum) // = sum ? + break; // ja -> Potenzreihe abbrechen + sum = new_sum; + b = (b*a)/(cl_I)((i+1)*(i+2)); + i = i+2; + } + var cl_F z = square(sum); // sum^2 als Ergebnis + while (e > e_limit) { + z = z + x2 * square(z); + x2 = scale_float(x2,2); // x^2 := x^2*4 + e_limit++; + } + return z; +}} +// Bit complexity (N = length(x)): O(N^(1/2)*M(N)). + +const cl_LF sinhx_naive (const cl_LF& x) +{ +// Methode: +// e := Exponent aus (decode-float x), d := (float-digits x) +// Bei x=0.0 oder e<=(1-d)/2 liefere x +// (denn bei e<=(1-d)/2 ist x^2/6 < x^2/4 < 2^(1-d)/4 = 2^(-d-1), also +// 1 <= sinh(x)/x = 1+x^2/6+... < 1+2^(-d-1), also ist sinh(x)^2, auf d Bits +// gerundet, gleich x). +// Bei e<=-sqrt(d) verwende die Potenzreihe +// sinh(x) = sum(j=0..inf,x*(x^2)^j/(2j+1)!): +// a:=x^2, b:=x, i:=1, sum:=0, +// while (/= sum (setq sum (+ sum b))) do b:=b*a/((i+1)*(i+2)), i:=i+2. +// Ergebnis sum^2. +// Sonst setze y := x/2 = (scale-float x -1), +// berechne rekursiv z:=sinh(y)^2 und liefere 4*z*(1+z) = (1+2*z)^2-1. +// [Die Grenze sqrt(d) ergibt sich so: +// Man braucht bei der Potenzreihe mit x=2^-k etwa j Glieder, mit +// k*j*ln 2 + j*(ln j - 1) = d, und der Aufwand beträgt etwa 2.8*(j/2) +// Multiplikationen von d-Bit-Zahlen. Bei Halbierungen bis x=2^-k ist der +// Gesamtaufwand etwa 2*(k+e)+1.4*j(k). Dieses minimieren nach k: Soll sein +// -1.4 = d/dk j(k) = (d/dj k(j))^-1 = - j^2/(d+j)*ln 2, also j^2=2(d+j), +// grob j=sqrt(2d) und damit k=sqrt(d).] +// Aufwand: asymptotisch d^2.5 . + + if (zerop(x)) + return x; + var uintL actuallen = TheLfloat(x)->len; + var uintL d = float_digits(x); + var sintL e = float_exponent(x); + if (e <= (1-(sintL)d)>>1) // e <= (1-d)/2 <==> e <= -ceiling((d-1)/2) ? + return x; // ja -> x als Ergebnis + { Mutable(cl_LF,x); + var sintL ee = e; + // Bei e <= -1-limit_slope*floor(sqrt(d)) kann die Potenzreihe + // angewandt werden. Ein guter Wert für naive1 ist limit_slope = 0.6, + // für naive3 aber limit_slope = 0.5. + var sintL e_limit = -1-floor(isqrt(d),2); // -1-floor(sqrt(d)) + if (e > e_limit) { + // e > -1-limit_slope*floor(sqrt(d)) -> muß |x| verkleinern. + x = scale_float(x,e_limit-e); + ee = e_limit; // Neuer Exponent = e_limit. + } + var cl_LF x2 = square(x); // x^2 + // Potenzreihe anwenden: + var cl_LF powser_value; + var cl_LF a = x2; // a := x^2 + var int i = 1; + if (0) { + // naive1: + // fixed-point representation + d = d-ee; // fixed-point representation with d mantissa bits + var cl_I b = round1(scale_float(x,d)); // b := x + var cl_I sum = 0; // sum := (float 0 x) + loop { + if (b == 0) break; + sum = sum + b; + b = round1(round1(The(cl_LF)(b*a)),(cl_I)((i+1)*(i+2))); + i = i+2; + } + powser_value = scale_float(cl_float(sum,x),-d); + } else if (actuallen <= 7) { // Break-even-Point before extendsqrt: N<=6 + // naive2: + // floating-point representation + var cl_LF b = x; // b := x + var cl_LF sum = cl_float(0,x); // sum := (float 0 x) + loop { + var cl_LF new_sum = sum + b; + if (new_sum == sum) // = sum ? + break; // ja -> Potenzreihe abbrechen + sum = new_sum; + b = (b*a)/(cl_I)((i+1)*(i+2)); + i = i+2; + } + powser_value = sum; + } else { + // naive3: + // floating-point representation with smooth precision reduction + var cl_LF b = x; // b := x + var cl_LF eps = scale_float(b,-(sintL)d-10); + var cl_LF sum = cl_float(0,x); // sum := (float 0 x) + loop { + var cl_LF new_sum = sum + LF_to_LF(b,actuallen); + if (new_sum == sum) // = sum ? + break; // ja -> Potenzreihe abbrechen + sum = new_sum; + b = cl_LF_shortenwith(b,eps); + b = (b*a)/(cl_I)((i+1)*(i+2)); + i = i+2; + } + powser_value = sum; + } + var cl_LF z = square(powser_value); // sinh^2 als Ergebnis + while (e > e_limit) { + z = square(cl_float(1,x) + scale_float(z,1)) - cl_float(1,x); // z := (1+2*z)^2-1 + e_limit++; + } + return z; +}} +// Bit complexity (N = length(x)): O(N^(1/2)*M(N)). + +// Timings of the three variants, on an i486 33 MHz, running Linux, +// applied to x = sqrt(2)-1 = 0.414... +// N naive1 naive2 naive3 ratseries exp&recip +// 4 0.0055 0.0039 0.0041 0.021 0.0046 +// 6 0.0073 0.0054 0.0054 0.029 0.0062 +// 8 0.0093 0.0075 0.0070 0.036 0.0081 +// 10 0.011 0.010 0.009 0.046 0.0011 +// 25 0.041 0.046 0.033 0.133 0.043 +// 50 0.14 0.18 0.12 0.36 0.16 +// 100 0.56 0.70 0.43 1.12 0.61 +// 250 3.5 4.5 2.7 5.3 3.3 +// 500 14.9 19.4 11.4 19.0 11.4 +// 1000 63 82 47 63 35 +// 2500 328 381 243 261 143 +// ==> naive2 fastest for N <= 6, +// naive3 fastest for 6 <= N <= 500, +// exp&recip (which uses exp's own ratseries) fastest for N >= 500. + diff --git a/src/float/transcendental/cl_F_sinx.cc b/src/float/transcendental/cl_F_sinx.cc new file mode 100644 index 0000000..6df8643 --- /dev/null +++ b/src/float/transcendental/cl_F_sinx.cc @@ -0,0 +1,217 @@ +// sinxbyx(), sinx(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +#include "cl_float.h" +#include "cl_low.h" +#include "cl_F.h" +#include "cl_lfloat.h" +#include "cl_LF.h" +#include "cl_integer.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_LF_zerop.cc" +#include "cl_LF_exponent.cc" + +// sinxbyx is mainly for cl_SF, cl_FF, cl_DF, where we want to avoid underflow. + +const cl_F sinxbyx_naive (const cl_F& x) +{ +// Methode: +// e := Exponent aus (decode-float x), d := (float-digits x) +// Bei x=0.0 oder e<=-d/2 liefere 1.0 +// (denn bei e<=-d/2 ist x^2/6 < x^2/4 < 2^(-d)/4 = 2^(-d-2), also +// 1 >= sin(x)/x > 1-x^2/6 > 1-2^(-d-2), also 1 >= (sin(x)/x)^2 > 1-2^(-d-1), +// also ist (sin(x)/x)^2, auf d Bits gerundet, gleich 1.0). +// Bei e<=-sqrt(d) verwende die Potenzreihe +// sin(x)/x = sum(j=0..inf,(-x^2)^j/(2j+1)!): +// a:=-x^2, b:=1, i:=1, sum:=0, +// while (/= sum (setq sum (+ sum b))) do b:=b*a/((i+1)*(i+2)), i:=i+2. +// Ergebnis sum^2. +// Sonst setze y := x/2 = (scale-float x -1), +// berechne rekursiv z:=(sin(y)/y)^2 und liefere z*(1-y^2*z). +// [Die Grenze sqrt(d) ergibt sich so: +// Man braucht bei der Potenzreihe mit x=2^-k etwa j Glieder, mit +// k*j*ln 2 + j*(ln j - 1) = d, und der Aufwand beträgt etwa 2.8*(j/2) +// Multiplikationen von d-Bit-Zahlen. Bei Halbierungen bis x=2^-k ist der +// Gesamtaufwand etwa 2*(k+e)+1.4*j(k). Dieses minimieren nach k: Soll sein +// -1.4 = d/dk j(k) = (d/dj k(j))^-1 = - j^2/(d+j)*ln 2, also j^2=2(d+j), +// grob j=sqrt(2d) und damit k=sqrt(d).] +// Aufwand: asymptotisch d^2.5 . + + if (zerop(x)) + return cl_float(1,x); + var uintL d = float_digits(x); + var sintL e = float_exponent(x); + if (e <= (-(sintL)d)>>1) // e <= (-d)/2 <==> e <= -ceiling(d/2) ? + return cl_float(1,x); // ja -> 1.0 als Ergebnis + { Mutable(cl_F,x); + // Bei e <= -1-limit_slope*floor(sqrt(d)) kann die Potenzreihe + // angewandt werden. limit_slope = 1.0 ist sehr schlecht (ca. 30% + // zu schlecht). Gute Werte bei N limbs: + // N limit_slope + // 5 0.15-0.30 + // 10 0.25 + // 25 0.25-0.35 + // 50 0.35-0.40 + // 100 0.40-0.45 + // 200 0.40-0.45 + // Wähle limit_slope = 13/32 = 0.4. + var sintL e_limit = -1-floor(isqrt(d)*13,32); // -1-floor(sqrt(d)) + if (e > e_limit) { + // e > -1-limit_slope*floor(sqrt(d)) -> muß |x| verkleinern. + x = scale_float(x,e_limit-e); + // Neuer Exponent = e_limit. + } + var cl_F x2 = square(x); // x^2 + // Potenzreihe anwenden: + var cl_F a = - x2; // a := -x^2 + var int i = 1; + var cl_F b = cl_float(1,x); // b := (float 1 x) + var cl_F sum = cl_float(0,x); // sum := (float 0 x) + loop { + var cl_F new_sum = sum + b; + if (new_sum == sum) // = sum ? + break; // ja -> Potenzreihe abbrechen + sum = new_sum; + b = (b*a)/(cl_I)((i+1)*(i+2)); + i = i+2; + } + var cl_F z = square(sum); // sum^2 als Ergebnis + while (e > e_limit) { + z = z - x2 * square(z); + x2 = scale_float(x2,2); // x^2 := x^2*4 + e_limit++; + } + return z; +}} +// Bit complexity (N = length(x)): O(N^(1/2)*M(N)). + +const cl_LF sinx_naive (const cl_LF& x) +{ +// Methode: +// e := Exponent aus (decode-float x), d := (float-digits x) +// Bei x=0.0 oder e<=-d/2 liefere x +// (denn bei e<=-d/2 ist x^2/6 < x^2/4 < 2^(-d)/4 = 2^(-d-2), also +// 1 >= sin(x)/x > 1-x^2/6 > 1-2^(-d-2), also ist sin(x)^2, auf d Bits +// gerundet, gleich x). +// Bei e<=-sqrt(d) verwende die Potenzreihe +// sin(x) = sum(j=0..inf,x*(-x^2)^j/(2j+1)!): +// a:=-x^2, b:=x, i:=1, sum:=0, +// while (/= sum (setq sum (+ sum b))) do b:=b*a/((i+1)*(i+2)), i:=i+2. +// Ergebnis sum^2. +// Sonst setze y := x/2 = (scale-float x -1), +// berechne rekursiv z:=sin(y)^2 und liefere 4*z*(1-z) = 1-(1-2*z)^2. +// [Die Grenze sqrt(d) ergibt sich so: +// Man braucht bei der Potenzreihe mit x=2^-k etwa j Glieder, mit +// k*j*ln 2 + j*(ln j - 1) = d, und der Aufwand beträgt etwa 2.8*(j/2) +// Multiplikationen von d-Bit-Zahlen. Bei Halbierungen bis x=2^-k ist der +// Gesamtaufwand etwa 2*(k+e)+1.4*j(k). Dieses minimieren nach k: Soll sein +// -1.4 = d/dk j(k) = (d/dj k(j))^-1 = - j^2/(d+j)*ln 2, also j^2=2(d+j), +// grob j=sqrt(2d) und damit k=sqrt(d).] +// Aufwand: asymptotisch d^2.5 . + + if (zerop(x)) + return x; + var uintL actuallen = TheLfloat(x)->len; + var uintL d = float_digits(x); + var sintL e = float_exponent(x); + if (e <= (-(sintL)d)>>1) // e <= (-d)/2 <==> e <= -ceiling(d/2) ? + return x; // ja -> x als Ergebnis + { Mutable(cl_LF,x); + var sintL ee = e; + // Bei e <= -1-limit_slope*floor(sqrt(d)) kann die Potenzreihe + // angewandt werden. limit_slope = 1.0 ist schlecht (ca. 10% zu + // schlecht). Ein guter Wert für naive1 ist limit_slope = 0.6, + // für naive3 aber limit_slope = 0.5. + var sintL e_limit = -1-floor(isqrt(d),2); // -1-floor(sqrt(d)) + if (e > e_limit) { + // e > -1-limit_slope*floor(sqrt(d)) -> muß |x| verkleinern. + x = scale_float(x,e_limit-e); + ee = e_limit; // Neuer Exponent = e_limit. + } + var cl_LF x2 = square(x); // x^2 + // Potenzreihe anwenden: + var cl_LF powser_value; + var cl_LF a = - x2; // a := -x^2 + var int i = 1; + if (0) { + // naive1: + // fixed-point representation + d = d-ee; // fixed-point representation with d mantissa bits + var cl_I b = round1(scale_float(x,d)); // b := x + var cl_I sum = 0; // sum := (float 0 x) + loop { + if (b == 0) break; + sum = sum + b; + b = round1(round1(The(cl_LF)(b*a)),(cl_I)((i+1)*(i+2))); + i = i+2; + } + powser_value = scale_float(cl_float(sum,x),-d); + } else if (actuallen <= 7) { // Break-even-Point before extendsqrt: N<=6 + // naive2: + // floating-point representation + var cl_LF b = x; // b := x + var cl_LF sum = cl_float(0,x); // sum := (float 0 x) + loop { + var cl_LF new_sum = sum + b; + if (new_sum == sum) // = sum ? + break; // ja -> Potenzreihe abbrechen + sum = new_sum; + b = (b*a)/(cl_I)((i+1)*(i+2)); + i = i+2; + } + powser_value = sum; + } else { + // naive3: + // floating-point representation with smooth precision reduction + var cl_LF b = x; // b := x + var cl_LF eps = scale_float(b,-(sintL)d-10); + var cl_LF sum = cl_float(0,x); // sum := (float 0 x) + loop { + var cl_LF new_sum = sum + LF_to_LF(b,actuallen); + if (new_sum == sum) // = sum ? + break; // ja -> Potenzreihe abbrechen + sum = new_sum; + b = cl_LF_shortenwith(b,eps); + b = (b*a)/(cl_I)((i+1)*(i+2)); + i = i+2; + } + powser_value = sum; + } + var cl_LF z = square(powser_value); // sin^2 als Ergebnis + while (e > e_limit) { + z = cl_float(1,x) - square(cl_float(1,x) - scale_float(z,1)); // z := 1-(1-2*z)^2 + e_limit++; + } + return z; +}} +// Bit complexity (N = length(x)): O(N^(1/2)*M(N)). + +// Timings of the three variants, on an i486 33 MHz, running Linux, +// applied to x = sqrt(2)-1 = 0.414... +// N naive1 naive2 naive3 ratseries +// 4 0.0064 0.0048 0.0049 0.023 +// 6 0.0081 0.0064 0.0065 0.031 +// 8 0.0103 0.0085 0.0083 0.038 +// 10 0.012 0.011 0.010 0.048 +// 25 0.043 0.047 0.035 0.119 +// 50 0.15 0.17 0.12 0.37 +// 100 0.54 0.67 0.44 1.09 +// 250 3.5 4.4 2.8 5.5 +// 500 14.7 18.5 11.6 19.4 +// 1000 61 78 48 64 +// 2500 315 361 243 261 +// 2700 265 270 +// 3000 294 282 +// 3500 339 303 +// ==> ratseries faster for N >= 2750. + diff --git a/src/float/transcendental/cl_F_tan.cc b/src/float/transcendental/cl_F_tan.cc new file mode 100644 index 0000000..dac0f28 --- /dev/null +++ b/src/float/transcendental/cl_F_tan.cc @@ -0,0 +1,19 @@ +// tan(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +MAYBE_INLINE +const cl_F tan (const cl_F& x) +{ +// Methode: +// (/ (sin x) (cos x)) + var cl_cos_sin_t trig = cl_cos_sin(x); + return The(cl_F)(trig.sin) / The(cl_F)(trig.cos); +} diff --git a/src/float/transcendental/cl_F_tanh.cc b/src/float/transcendental/cl_F_tanh.cc new file mode 100644 index 0000000..5694a04 --- /dev/null +++ b/src/float/transcendental/cl_F_tanh.cc @@ -0,0 +1,19 @@ +// tanh(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +MAYBE_INLINE +const cl_F tanh (const cl_F& x) +{ +// Methode: +// (/ (sinh x) (cosh x)) + var cl_cosh_sinh_t hyp = cl_cosh_sinh(x); + return The(cl_F)(hyp.sinh) / The(cl_F)(hyp.cosh); +} diff --git a/src/float/transcendental/cl_F_tran.h b/src/float/transcendental/cl_F_tran.h new file mode 100644 index 0000000..70a39da --- /dev/null +++ b/src/float/transcendental/cl_F_tran.h @@ -0,0 +1,148 @@ +// Internals for transcendental functions on floating-point numbers + +#ifndef _CL_F_TRAN_H +#define _CL_F_TRAN_H + +#include "cl_number.h" +#include "cl_float.h" + +// pi. +extern const cl_SF cl_SF_pi; +extern const cl_FF cl_FF_pi; +extern const cl_DF cl_DF_pi; +extern cl_LF cl_LF_pi; // as long as it has ever been computed +extern const cl_LF cl_pi (uintC len); // computes it even further +//CL_REQUIRE(cl_F_pi_var) + +// cl_exp_aux(p,lq,len) liefert die Zahl exp(p/2^lq) mit len Digits. +// 0 < |p| < 2^lq. +// Es sollte |p|^2 < 2^lq sein, sonst ist das nicht effizient. +extern const cl_LF cl_exp_aux (const cl_I& p, uintL lq, uintC len); + +// cl_cossin_aux(p,lq,len) liefert cos(p/2^lq) und sin(p/2^lq) mit len Digits. +// 0 < |p| < 2^lq. +// Es sollte |p|^2 < 2^lq sein, sonst ist das nicht effizient. +struct cl_LF_cos_sin_t { + cl_LF cos; + cl_LF sin; +// Constructor: + cl_LF_cos_sin_t (const cl_LF& u, const cl_LF& v) : cos (u), sin (v) {} + cl_LF_cos_sin_t () {} +}; +extern const cl_LF_cos_sin_t cl_cossin_aux (const cl_I& p, uintL lq, uintC len); + +// cl_coshsinh_aux(p,lq,len) liefert cosh(p/2^lq) und sinh(p/2^lq) mit len Digits. +// 0 < |p| < 2^lq. +// Es sollte |p|^2 < 2^lq sein, sonst ist das nicht effizient. +struct cl_LF_cosh_sinh_t { + cl_LF cosh; + cl_LF sinh; +// Constructor: + cl_LF_cosh_sinh_t (const cl_LF& u, const cl_LF& v) : cosh (u), sinh (v) {} + cl_LF_cosh_sinh_t () {} +}; +extern const cl_LF_cosh_sinh_t cl_coshsinh_aux (const cl_I& p, uintL lq, uintC len); + +// atanhx(x) liefert zu einem Float x (betragsmäßig <1/2) atanh(x) als Float. +extern const cl_F atanhx (const cl_F& x); + +// atanx(x) liefert zu einem Float x (betragsmäßig <=1) atan(x) als Float. +extern const cl_F atanx (const cl_F& x); + +// sinx(x) liefert zu einem Float x (betragsmäßig <1) sin(x)^2 als Float. +// sinxbyx(x) liefert zu einem Float x (betragsmäßig <1) (sin(x)/x)^2 als Float. +extern const cl_LF sinx_naive (const cl_LF& x); // requires cl_F_extendsqrt +extern const cl_F sinxbyx_naive (const cl_F& x); // requires cl_F_extendsqrt +// (cos(x),sin(x)) für ein Long-Float x (betragsmäßig <1). +extern const cl_LF_cos_sin_t cl_cossin_ratseries (const cl_LF& x); // requires extend by 1 + +// sinhx(x) liefert zu einem Float x (betragsmäßig <1) sinh(x)^2 als Float. +// sinhxbyx(x) liefert zu einem Float x (betragsmäßig <1) (sinh(x)/x)^2 als Float. +extern const cl_LF sinhx_naive (const cl_LF& x); // requires cl_F_extendsqrt +extern const cl_F sinhxbyx_naive (const cl_F& x); // requires cl_F_extendsqrt +// (cosh(x),sinh(x)) für ein Long-Float x (betragsmäßig <1). +extern const cl_LF_cosh_sinh_t cl_coshsinh_ratseries (const cl_LF& x); // requires extend by 1 + +// cl_round_pi(x) dividiert ein Float x mit Rest durch pi. +// Beide Werte von (round x (float pi x)). +extern const cl_F_div_t cl_round_pi (const cl_F& x); + +// cl_round_pi2(x) dividiert ein Float x mit Rest durch pi/2. +// Beide Werte von (round x (float pi/2 x)). +extern const cl_F_div_t cl_round_pi2 (const cl_F& x); + +// cl_atan_recip(m,len) liefert arctan(1/m) mit len Digits. +extern const cl_LF cl_atan_recip (cl_I m, uintC len); + +// lnx(x) liefert zu einem Float x (>=1/2, <=2) ln(x) als Float. +extern const cl_F lnx_naive (const cl_F& x); // requires cl_F_extendsqrtx +extern const cl_LF lnx_naive (const cl_LF& x); // requires cl_F_extendsqrtx +extern const cl_LF lnx_ratseries (const cl_LF& x); // requires extend by 1 + +// cl_atanh_recip(m,len) liefert artanh(1/m) mit len Digits. +extern const cl_LF cl_atanh_recip (cl_I m, uintC len); + +// ln(2). +extern const cl_SF cl_SF_ln2; +extern const cl_FF cl_FF_ln2; +extern const cl_DF cl_DF_ln2; +extern cl_LF cl_LF_ln2; // as long as it has ever been computed +extern const cl_LF cl_ln2 (uintC len); // computes it even further +//CL_REQUIRE(cl_F_ln2_var) + +// cl_ln2(y) liefert die Zahl ln(2) im selben Float-Format wie y. +// > y: ein Float +extern const cl_F cl_ln2 (const cl_F& y); + +// cl_ln2(y) liefert die Zahl ln(2) im Float-Format f. +// > f: eine Float-Format-Spezifikation +extern const cl_F cl_ln2 (cl_float_format_t f); + +// ln(10). +extern const cl_SF cl_SF_ln10; +extern const cl_FF cl_FF_ln10; +extern const cl_DF cl_DF_ln10; +extern cl_LF cl_LF_ln10; // as long as it has ever been computed +extern const cl_LF cl_ln10 (uintC len); // computes it even further +//CL_REQUIRE(cl_F_ln10_var) + +// cl_ln10(y) liefert die Zahl ln(10) im selben Float-Format wie y. +// > y: ein Float +extern const cl_F cl_ln10 (const cl_F& y); + +// cl_ln10(y) liefert die Zahl ln(10) im Float-Format f. +// > f: eine Float-Format-Spezifikation +extern const cl_F cl_ln10 (cl_float_format_t f); + +// e = exp(1). +extern const cl_SF cl_SF_exp1; +extern const cl_FF cl_FF_exp1; +extern const cl_DF cl_DF_exp1; +extern cl_LF cl_LF_exp1; // as long as it has ever been computed +extern const cl_LF cl_exp1 (uintC len); // computes it even further + +// expx(x) liefert zu einem Float x (betragsmäßig <1) exp(x) als Float. +extern const cl_F expx_naive (const cl_F& x); // requires cl_F_extendsqrtx +extern const cl_LF expx_naive (const cl_LF& x); // requires cl_F_extendsqrtx +extern const cl_LF expx_ratseries (const cl_LF& x); // requires extend by 1 + +// Eulersche Konstante. +extern const cl_SF cl_SF_eulerconst; +extern const cl_FF cl_FF_eulerconst; +extern const cl_DF cl_DF_eulerconst; +extern cl_LF cl_LF_eulerconst; // as long as it has ever been computed +extern const cl_LF cl_eulerconst (uintC len); // computes it even further + +// Catalansche Konstante. +extern const cl_SF cl_SF_catalanconst; +extern const cl_FF cl_FF_catalanconst; +extern const cl_DF cl_DF_catalanconst; +extern cl_LF cl_LF_catalanconst; // as long as it has ever been computed +extern const cl_LF cl_catalanconst (uintC len); // computes it even further + +// Zeta-Funktion für s>1 ganzzahlig. +extern const cl_LF cl_zeta (int s, uintC len); +// Zeta-Funktion für s=3. +extern const cl_LF cl_zeta3 (uintC len); + +#endif /* _CL_F_TRAN_H */ diff --git a/src/float/transcendental/cl_F_zeta_int.cc b/src/float/transcendental/cl_F_zeta_int.cc new file mode 100644 index 0000000..6e17d76 --- /dev/null +++ b/src/float/transcendental/cl_F_zeta_int.cc @@ -0,0 +1,24 @@ +// cl_zeta(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_F_tran.h" +#include "cl_LF.h" + +const cl_F cl_zeta (int s, const cl_F& y) +{ + floattypecase(y + , return cl_LF_to_SF(cl_zeta(s,LF_minlen)); + , return cl_LF_to_FF(cl_zeta(s,LF_minlen)); + , return cl_LF_to_DF(cl_zeta(s,LF_minlen)); + , return cl_zeta(s,TheLfloat(y)->len); + ); +} diff --git a/src/float/transcendental/cl_F_zeta_int_def.cc b/src/float/transcendental/cl_F_zeta_int_def.cc new file mode 100644 index 0000000..ded95e2 --- /dev/null +++ b/src/float/transcendental/cl_F_zeta_int_def.cc @@ -0,0 +1,24 @@ +// cl_zeta(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_F_tran.h" +#include "cl_LF.h" + +const cl_F cl_zeta (int s) +{ + floatformatcase(cl_default_float_format + , return cl_LF_to_SF(cl_zeta(s,LF_minlen)); + , return cl_LF_to_FF(cl_zeta(s,LF_minlen)); + , return cl_LF_to_DF(cl_zeta(s,LF_minlen)); + , return cl_zeta(s,len); + ); +} diff --git a/src/float/transcendental/cl_F_zeta_int_f.cc b/src/float/transcendental/cl_F_zeta_int_f.cc new file mode 100644 index 0000000..78cf29e --- /dev/null +++ b/src/float/transcendental/cl_F_zeta_int_f.cc @@ -0,0 +1,24 @@ +// cl_zeta(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_float.h" + + +// Implementation. + +#include "cl_F.h" +#include "cl_F_tran.h" +#include "cl_LF.h" + +const cl_F cl_zeta (int s, cl_float_format_t f) +{ + floatformatcase((uintL)f + , return cl_LF_to_SF(cl_zeta(s,LF_minlen)); + , return cl_LF_to_FF(cl_zeta(s,LF_minlen)); + , return cl_LF_to_DF(cl_zeta(s,LF_minlen)); + , return cl_zeta(s,len); + ); +} diff --git a/src/float/transcendental/cl_LF_atan_recip.cc b/src/float/transcendental/cl_LF_atan_recip.cc new file mode 100644 index 0000000..44879a5 --- /dev/null +++ b/src/float/transcendental/cl_LF_atan_recip.cc @@ -0,0 +1,50 @@ +// cl_atan_recip(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +#include "cl_integer.h" +#include "cl_lfloat.h" +#include "cl_LF.h" +#include "cl_LF_tran.h" +#include "cl_alloca.h" + +#undef floor +#include +#define floor cln_floor + +// Method: +// See examples/atan_recip.cc for a comparison of the algorithms. +// Here we take algorithm 2d. It's the fastest throughout the range. + +const cl_LF cl_atan_recip (cl_I m, uintC len) +{ + var uintC actuallen = len + 1; + var cl_I m2 = m*m+1; + var uintL N = (uintL)(0.69314718*intDsize*actuallen/log(cl_double_approx(m2))) + 1; + CL_ALLOCA_STACK; + var cl_I* pv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var cl_I* qv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var uintL n; + new (&pv[0]) cl_I (m); + new (&qv[0]) cl_I (m2); + for (n = 1; n < N; n++) { + new (&pv[n]) cl_I (2*n); + new (&qv[n]) cl_I ((2*n+1)*m2); + } + var cl_pq_series series; + series.pv = pv; series.qv = qv; series.qsv = NULL; + var cl_LF result = eval_rational_series(N,series,actuallen); + for (n = 0; n < N; n++) { + pv[n].~cl_I(); + qv[n].~cl_I(); + } + return shorten(result,len); +} +// Bit complexity (N = len): O(log(N)^2*M(N)). diff --git a/src/float/transcendental/cl_LF_atanh_recip.cc b/src/float/transcendental/cl_LF_atanh_recip.cc new file mode 100644 index 0000000..ab26505 --- /dev/null +++ b/src/float/transcendental/cl_LF_atanh_recip.cc @@ -0,0 +1,49 @@ +// cl_atanh_recip(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +#include "cl_integer.h" +#include "cl_lfloat.h" +#include "cl_LF.h" +#include "cl_LF_tran.h" +#include "cl_alloca.h" + +#undef floor +#include +#define floor cln_floor + +// Method: +// See examples/atanh_recip.cc for a comparison of the algorithms. +// Here we take algorithm 1d. It's the fastest throughout the range. + +const cl_LF cl_atanh_recip (cl_I m, uintC len) +{ + var uintC actuallen = len + 1; + var cl_I m2 = m*m; + var uintL N = (uintL)(0.69314718*intDsize/2*actuallen/log(cl_double_approx(m))) + 1; + CL_ALLOCA_STACK; + var cl_I* bv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var cl_I* qv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var uintL n; + for (n = 0; n < N; n++) { + new (&bv[n]) cl_I ((cl_I)(2*n+1)); + new (&qv[n]) cl_I (n==0 ? m : m2); + } + var cl_qb_series series; + series.bv = bv; + series.qv = qv; series.qsv = NULL; + var cl_LF result = eval_rational_series(N,series,actuallen); + for (n = 0; n < N; n++) { + bv[n].~cl_I(); + qv[n].~cl_I(); + } + return shorten(result,len); +} +// Bit complexity (N = len): O(log(N)^2*M(N)). diff --git a/src/float/transcendental/cl_LF_catalanconst.cc b/src/float/transcendental/cl_LF_catalanconst.cc new file mode 100644 index 0000000..8a946f5 --- /dev/null +++ b/src/float/transcendental/cl_LF_catalanconst.cc @@ -0,0 +1,275 @@ +// cl_catalanconst(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_LF_tran.h" +#include "cl_LF.h" +#include "cl_integer.h" +#include "cl_alloca.h" + +const cl_LF compute_catalanconst_ramanujan (uintC len) +{ + // [Jonathan M. Borwein, Peter B. Borwein: Pi and the AGM. + // Wiley 1987. Section 11.3, exercise 16 g, p. 386] + // G = 3/8 * sum(n=0..infty, n!^2 / (2n+1)!*(2n+1)) + // + pi/8 * log(2+sqrt(3)). + // Every summand gives 0.6 new decimal digits in precision. + // The sum is best evaluated using fixed-point arithmetic, + // so that the precision is reduced for the later summands. + var uintL actuallen = len + 2; // 2 Schutz-Digits + var sintL scale = intDsize*actuallen; + var cl_I sum = 0; + var cl_I n = 0; + var cl_I factor = ash(1,scale); + while (!zerop(factor)) { + sum = sum + truncate1(factor,2*n+1); + n = n+1; + factor = truncate1(factor*n,2*(2*n+1)); + } + var cl_LF fsum = scale_float(cl_I_to_LF(sum,actuallen),-scale); + var cl_LF g = + scale_float(The(cl_LF)(3*fsum) + + The(cl_LF)(cl_pi(actuallen)) + * ln(cl_I_to_LF(2,actuallen)+sqrt(cl_I_to_LF(3,actuallen))), + -3); + return shorten(g,len); // verkürzen und fertig +} +// Bit complexity (N := len): O(N^2). + +const cl_LF compute_catalanconst_ramanujan_fast (uintC len) +{ + // Same formula as above, using a binary splitting evaluation. + // See [Borwein, Borwein, section 10.2.3]. + var uintL actuallen = len + 2; // 2 Schutz-Digits + // Evaluate a sum(0 <= n < N, a(n)/b(n) * (p(0)...p(n))/(q(0)...q(n))) + // with appropriate N, and + // a(n) = 1, b(n) = 2*n+1, + // p(n) = n for n>0, q(n) = 2*(2*n+1) for n>0. + var uintL N = (intDsize/2)*actuallen; + // 4^-N <= 2^(-intDsize*actuallen). + CL_ALLOCA_STACK; + var cl_I* bv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var cl_I* pv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var cl_I* qv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var uintL n; + init1(cl_I, bv[0]) (1); + init1(cl_I, pv[0]) (1); + init1(cl_I, qv[0]) (1); + for (n = 1; n < N; n++) { + init1(cl_I, bv[n]) (2*n+1); + init1(cl_I, pv[n]) (n); + init1(cl_I, qv[n]) (2*(2*n+1)); + } + var cl_pqb_series series; + series.bv = bv; + series.pv = pv; series.qv = qv; series.qsv = NULL; + var cl_LF fsum = eval_rational_series(N,series,actuallen); + for (n = 0; n < N; n++) { + bv[n].~cl_I(); + pv[n].~cl_I(); + qv[n].~cl_I(); + } + var cl_LF g = + scale_float(The(cl_LF)(3*fsum) + + The(cl_LF)(cl_pi(actuallen)) + * ln(cl_I_to_LF(2,actuallen)+sqrt(cl_I_to_LF(3,actuallen))), + -3); + return shorten(g,len); // verkürzen und fertig +} +// Bit complexity (N := len): O(log(N)^2*M(N)). + +const cl_LF compute_catalanconst_expintegral1 (uintC len) +{ + // We compute f(x) classically and g(x) using the partial sums of f(x). + var uintC actuallen = len+2; // 2 Schutz-Digits + var uintL x = (uintL)(0.693148*intDsize*actuallen)+1; + var uintL N = (uintL)(2.718281828*x); + var cl_LF fterm = cl_I_to_LF(1,actuallen); + var cl_LF fsum = fterm; + var cl_LF gterm = fterm; + var cl_LF gsum = gterm; + var uintL n; + // After n loops + // fterm = x^n/n!, fsum = 1 + x/1! + ... + x^n/n!, + // gterm = S_n*x^n/n!, gsum = S_0*x^0/0! + ... + S_n*x^n/n!. + for (n = 1; n < N; n++) { + fterm = The(cl_LF)(fterm*x)/n; + fsum = fsum + fterm; + gterm = The(cl_LF)(gterm*x)/n; + if (evenp(n)) + gterm = gterm + fterm/square((cl_I)(2*n+1)); + else + gterm = gterm - fterm/square((cl_I)(2*n+1)); + gsum = gsum + gterm; + } + var cl_LF result = gsum/fsum; + return shorten(result,len); // verkürzen und fertig +} +// Bit complexity (N = len): O(N^2). + +// Same algorithm as expintegral1, but using binary splitting to evaluate +// the sums. +const cl_LF compute_catalanconst_expintegral2 (uintC len) +{ + var uintC actuallen = len+2; // 2 Schutz-Digits + var uintL x = (uintL)(0.693148*intDsize*actuallen)+1; + var uintL N = (uintL)(2.718281828*x); + CL_ALLOCA_STACK; + var cl_pqd_series_term* args = (cl_pqd_series_term*) cl_alloca(N*sizeof(cl_pqd_series_term)); + var uintL n; + for (n = 0; n < N; n++) { + if (n==0) { + init1(cl_I, args[n].p) (1); + init1(cl_I, args[n].q) (1); + } else { + init1(cl_I, args[n].p) (x); + init1(cl_I, args[n].q) (n); + } + init1(cl_I, args[n].d) (evenp(n) + ? square((cl_I)(2*n+1)) + : -square((cl_I)(2*n+1))); + } + var cl_LF result = eval_pqd_series(N,args,actuallen); + for (n = 0; n < N; n++) { + args[n].p.~cl_I(); + args[n].q.~cl_I(); + args[n].d.~cl_I(); + } + return shorten(result,len); // verkürzen und fertig +} +// Bit complexity (N = len): O(log(N)^2*M(N)). + +// Using Cohen-Villegas-Zagier acceleration, but without binary splitting. +const cl_LF compute_catalanconst_cvz1 (uintC len) +{ + var uintC actuallen = len+2; // 2 Schutz-Digits + var uintL N = (uintL)(0.39321985*intDsize*actuallen)+1; +#if 0 + var cl_LF fterm = cl_I_to_LF(2*(cl_I)N*(cl_I)N,actuallen); + var cl_LF fsum = fterm; + var cl_LF gterm = fterm; + var cl_LF gsum = gterm; + var uintL n; + // After n loops + // fterm = (N+n)!N/(2n+2)!(N-n-1)!*2^(2n+2), fsum = ... + fterm, + // gterm = S_n*fterm, gsum = ... + gterm. + for (n = 1; n < N; n++) { + fterm = The(cl_LF)(fterm*(2*(cl_I)(N-n)*(cl_I)(N+n)))/((cl_I)(2*n+1)*(cl_I)(n+1)); + fsum = fsum + fterm; + gterm = The(cl_LF)(gterm*(2*(cl_I)(N-n)*(cl_I)(N+n)))/((cl_I)(2*n+1)*(cl_I)(n+1)); + if (evenp(n)) + gterm = gterm + fterm/square((cl_I)(2*n+1)); + else + gterm = gterm - fterm/square((cl_I)(2*n+1)); + gsum = gsum + gterm; + } + var cl_LF result = gsum/(cl_I_to_LF(1,actuallen)+fsum); +#else + // Take advantage of the fact that fterm and fsum are integers. + var cl_I fterm = 2*(cl_I)N*(cl_I)N; + var cl_I fsum = fterm; + var cl_LF gterm = cl_I_to_LF(fterm,actuallen); + var cl_LF gsum = gterm; + var uintL n; + // After n loops + // fterm = (N+n)!N/(2n+2)!(N-n-1)!*2^(2n+2), fsum = ... + fterm, + // gterm = S_n*fterm, gsum = ... + gterm. + for (n = 1; n < N; n++) { + fterm = exquopos(fterm*(2*(cl_I)(N-n)*(cl_I)(N+n)),(cl_I)(2*n+1)*(cl_I)(n+1)); + fsum = fsum + fterm; + gterm = The(cl_LF)(gterm*(2*(cl_I)(N-n)*(cl_I)(N+n)))/((cl_I)(2*n+1)*(cl_I)(n+1)); + if (evenp(n)) + gterm = gterm + cl_I_to_LF(fterm,actuallen)/square((cl_I)(2*n+1)); + else + gterm = gterm - cl_I_to_LF(fterm,actuallen)/square((cl_I)(2*n+1)); + gsum = gsum + gterm; + } + var cl_LF result = gsum/cl_I_to_LF(1+fsum,actuallen); +#endif + return shorten(result,len); // verkürzen und fertig +} +// Bit complexity (N = len): O(N^2). + +// Using Cohen-Villegas-Zagier acceleration, with binary splitting. +const cl_LF compute_catalanconst_cvz2 (uintC len) +{ + var uintC actuallen = len+2; // 2 Schutz-Digits + var uintL N = (uintL)(0.39321985*intDsize*actuallen)+1; + CL_ALLOCA_STACK; + var cl_pqd_series_term* args = (cl_pqd_series_term*) cl_alloca(N*sizeof(cl_pqd_series_term)); + var uintL n; + for (n = 0; n < N; n++) { + init1(cl_I, args[n].p) (2*(cl_I)(N-n)*(cl_I)(N+n)); + init1(cl_I, args[n].q) ((cl_I)(2*n+1)*(cl_I)(n+1)); + init1(cl_I, args[n].d) (evenp(n) + ? square((cl_I)(2*n+1)) + : -square((cl_I)(2*n+1))); + } + var cl_pqd_series_result sums; + eval_pqd_series_aux(N,args,sums); + // Here we need U/(1+S) = V/D(Q+T). + var cl_LF result = + cl_I_to_LF(sums.V,actuallen) / The(cl_LF)(sums.D * cl_I_to_LF(sums.Q+sums.T,actuallen)); + for (n = 0; n < N; n++) { + args[n].p.~cl_I(); + args[n].q.~cl_I(); + args[n].d.~cl_I(); + } + return shorten(result,len); // verkürzen und fertig +} +// Bit complexity (N = len): O(log(N)^2*M(N)). + +// Timings of the above algorithms, on an i486 33 MHz, running Linux. +// N ram ramfast exp1 exp2 cvz1 cvz2 +// 10 0.055 0.068 0.32 0.91 0.076 0.11 +// 25 0.17 0.26 0.95 3.78 0.23 0.43 +// 50 0.43 0.73 2.81 11.5 0.63 1.36 +// 100 1.32 2.24 8.82 34.1 1.90 4.48 +// 250 6.60 10.4 48.7 127.5 10.3 20.8 +// 500 24.0 30.9 186 329 38.4 58.6 +// 1000 83.0 89.0 944 860 149 163 +// 2500 446 352 6964 3096 1032 545 +// 5000 1547 899 +// asymp. N^2 FAST N^2 FAST N^2 FAST +// (FAST means O(log(N)^2*M(N))) +// +// The "exp1" and "exp2" algorithms are always about 10 to 15 times slower +// than the "ram" and "ramfast" algorithms. +// The break-even point between "ram" and "ramfast" is at about N = 1410. + +const cl_LF compute_catalanconst (uintC len) +{ + if (len >= 1410) + return compute_catalanconst_ramanujan_fast(len); + else + return compute_catalanconst_ramanujan(len); +} +// Bit complexity (N := len): O(log(N)^2*M(N)). + +const cl_LF cl_catalanconst (uintC len) +{ + var uintC oldlen = TheLfloat(cl_LF_catalanconst)->len; // vorhandene Länge + if (len < oldlen) + return shorten(cl_LF_catalanconst,len); + if (len == oldlen) + return cl_LF_catalanconst; + + // TheLfloat(cl_LF_catalanconst)->len um mindestens einen konstanten Faktor + // > 1 wachsen lassen, damit es nicht zu häufig nachberechnet wird: + var uintC newlen = len; + oldlen += floor(oldlen,2); // oldlen * 3/2 + if (newlen < oldlen) + newlen = oldlen; + + // gewünschte > vorhandene Länge -> muß nachberechnen: + cl_LF_catalanconst = compute_catalanconst(newlen); + return (len < newlen ? shorten(cl_LF_catalanconst,len) : cl_LF_catalanconst); +} diff --git a/src/float/transcendental/cl_LF_coshsinh.cc b/src/float/transcendental/cl_LF_coshsinh.cc new file mode 100644 index 0000000..87d230a --- /dev/null +++ b/src/float/transcendental/cl_LF_coshsinh.cc @@ -0,0 +1,55 @@ +// cl_coshsinh_ratseries(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_LF.h" +#include "cl_integer.h" + +inline const cl_LF_cosh_sinh_t operator* (const cl_LF_cosh_sinh_t& a, const cl_LF_cosh_sinh_t& b) +{ + return cl_LF_cosh_sinh_t(a.cosh*b.cosh+a.sinh*b.sinh,a.sinh*b.cosh+a.cosh*b.sinh); +} + +const cl_LF_cosh_sinh_t cl_coshsinh_ratseries (const cl_LF& x) +{ + // Similar to expx_ratseries. + var uintC len = TheLfloat(x)->len; + var cl_idecoded_float x_ = integer_decode_float(x); + // x = (-1)^sign * 2^exponent * mantissa + var uintL lq = cl_I_to_UL(- x_.exponent); + var const cl_I& p = x_.mantissa; + // Compute sinh(p/2^lq) and cosh(p/2^lq) by splitting into pieces. + var cl_boolean first_factor = cl_true; + var cl_LF_cosh_sinh_t product; + var uintL b1; + var uintL b2; + for (b1 = 0, b2 = 1; b1 < lq; b1 = b2, b2 = 2*b2) { + // Piece containing bits b1+1..b2 after "decimal point" + // in the binary representation of (p/2^lq). + var uintL lqk = (lq >= b2 ? b2 : lq); + var cl_I pk = ldb(p,cl_byte(lqk-b1,lq-lqk)); + // Compute sinh(pk/2^lqk) and cosh(pk/2^lqk). + if (!zerop(pk)) { + if (minusp(x_.sign)) { pk = -pk; } + var cl_LF_cosh_sinh_t factor = cl_coshsinh_aux(pk,lqk,len); + if (first_factor) { + product = factor; + first_factor = cl_false; + } else + product = product * factor; + } + } + if (first_factor) + return cl_LF_cosh_sinh_t(cl_I_to_LF(1,len),cl_I_to_LF(0,len)); + else + return product; +} +// Bit complexity (N = length(x)): O(log(N)^2*M(N)). diff --git a/src/float/transcendental/cl_LF_coshsinh_aux.cc b/src/float/transcendental/cl_LF_coshsinh_aux.cc new file mode 100644 index 0000000..33d794d --- /dev/null +++ b/src/float/transcendental/cl_LF_coshsinh_aux.cc @@ -0,0 +1,117 @@ +// cl_coshsinh_aux(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_LF_tran.h" +#include "cl_LF.h" +#include "cl_integer.h" +#include "cl_alloca.h" +#include "cl_abort.h" + +#undef floor +#include +#define floor cln_floor + +// Computing cosh(x) = sqrt(1+sinh(x)^2) instead of computing separately +// by a power series evaluation brings 20% speedup, even more for small lengths. +#define TRIVIAL_SPEEDUP + +const cl_LF_cosh_sinh_t cl_coshsinh_aux (const cl_I& p, uintL lq, uintC len) +{ + { Mutable(cl_I,p); + var uintL lp = integer_length(p); // now |p| < 2^lp. + if (!(lp <= lq)) cl_abort(); + lp = lq - lp; // now |p/2^lq| < 2^-lp. + // Minimize lq (saves computation time). + { + var uintL lp2 = ord2(p); + if (lp2 > 0) { + p = p >> lp2; + lq = lq - lp2; + } + } + // cosh(p/2^lq): + // Evaluate a sum(0 <= n < N, a(n)/b(n) * (p(0)...p(n))/(q(0)...q(n))) + // with appropriate N, and + // a(n) = 1, b(n) = 1, + // p(n) = p^2 for n>0, + // q(n) = (2*n-1)*(2*n)*(2^lq)^2 for n>0. + // sinh(p/2^lq): + // Evaluate a sum(0 <= n < N, a(n)/b(n) * (p(0)...p(n))/(q(0)...q(n))) + // with appropriate N, and + // a(n) = 1, b(n) = 1, + // p(0) = p, p(n) = p^2 for n>0, + // q(0) = 2^lq, q(n) = (2*n)*(2*n+1)*(2^lq)^2 for n>0. + var uintC actuallen = len+1; // 1 Schutz-Digit + // How many terms to we need for M bits of precision? N/2 terms suffice, + // provided that + // 1/(2^(N*lp)*N!) < 2^-M + // <== N*(log(N)-1)+N*lp*log(2) > M*log(2) + // First approximation: + // N0 = M will suffice, so put N<=N0. + // Second approximation: + // N1 = floor(M*log(2)/(log(N0)-1+lp*log(2))), slightly too small, + // so put N>=N1. + // Third approximation: + // N2 = ceiling(M*log(2)/(log(N1)-1+lp*log(2))), slightly too large. + // N = N2+2, two more terms for safety. + var uintL N0 = intDsize*actuallen; + var uintL N1 = (uintL)(0.693147*intDsize*actuallen/(log((double)N0)-1.0+0.693148*lp)); + var uintL N2 = (uintL)(0.693148*intDsize*actuallen/(log((double)N1)-1.0+0.693147*lp))+1; + var uintL N = N2+2; + N = ceiling(N,2); + CL_ALLOCA_STACK; + var cl_I* pv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var cl_I* qv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var uintL* qsv = (uintL*) cl_alloca(N*sizeof(uintL)); + var uintL n; + var cl_I p2 = square(p); + var cl_LF sinhsum; + { + init1(cl_I, pv[0]) (p); + init1(cl_I, qv[0]) ((cl_I)1 << lq); + for (n = 1; n < N; n++) { + init1(cl_I, pv[n]) (p2); + init1(cl_I, qv[n]) (((cl_I)n*(cl_I)(2*n+1)) << (2*lq+1)); + } + var cl_pq_series series; + series.pv = pv; series.qv = qv; series.qsv = qsv; + sinhsum = eval_rational_series(N,series,actuallen); + for (n = 0; n < N; n++) { + pv[n].~cl_I(); + qv[n].~cl_I(); + } + } + #if !defined(TRIVIAL_SPEEDUP) + var cl_LF coshsum; + { + init1(cl_I, pv[0]) (1); + init1(cl_I, qv[0]) (1); + for (n = 1; n < N; n++) { + init1(cl_I, pv[n]) (p2); + init1(cl_I, qv[n]) (((cl_I)n*(cl_I)(2*n-1)) << (2*lq+1)); + } + var cl_pq_series series; + series.pv = pv; series.qv = qv; series.qsv = qsv; + coshsum = eval_rational_series(N,series,actuallen); + for (n = 0; n < N; n++) { + pv[n].~cl_I(); + qv[n].~cl_I(); + } + } + #else // TRIVIAL_SPEEDUP + var cl_LF coshsum = sqrt(cl_I_to_LF(1,actuallen) + square(sinhsum)); + #endif + return cl_LF_cosh_sinh_t(shorten(coshsum,len),shorten(sinhsum,len)); // verkürzen und fertig +}} +// Bit complexity (N = len, and if p has length O(log N) and ql = O(log N)): +// O(log(N)*M(N)). + diff --git a/src/float/transcendental/cl_LF_cossin.cc b/src/float/transcendental/cl_LF_cossin.cc new file mode 100644 index 0000000..2dcd82f --- /dev/null +++ b/src/float/transcendental/cl_LF_cossin.cc @@ -0,0 +1,55 @@ +// cl_cossin_ratseries(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_LF.h" +#include "cl_integer.h" + +inline const cl_LF_cos_sin_t operator* (const cl_LF_cos_sin_t& a, const cl_LF_cos_sin_t& b) +{ + return cl_LF_cos_sin_t(a.cos*b.cos-a.sin*b.sin,a.sin*b.cos+a.cos*b.sin); +} + +const cl_LF_cos_sin_t cl_cossin_ratseries (const cl_LF& x) +{ + // Similar to expx_ratseries. + var uintC len = TheLfloat(x)->len; + var cl_idecoded_float x_ = integer_decode_float(x); + // x = (-1)^sign * 2^exponent * mantissa + var uintL lq = cl_I_to_UL(- x_.exponent); + var const cl_I& p = x_.mantissa; + // Compute sin(p/2^lq) and cos(p/2^lq) by splitting into pieces. + var cl_boolean first_factor = cl_true; + var cl_LF_cos_sin_t product; + var uintL b1; + var uintL b2; + for (b1 = 0, b2 = 1; b1 < lq; b1 = b2, b2 = 2*b2) { + // Piece containing bits b1+1..b2 after "decimal point" + // in the binary representation of (p/2^lq). + var uintL lqk = (lq >= b2 ? b2 : lq); + var cl_I pk = ldb(p,cl_byte(lqk-b1,lq-lqk)); + // Compute sin(pk/2^lqk) and cos(pk/2^lqk). + if (!zerop(pk)) { + if (minusp(x_.sign)) { pk = -pk; } + var cl_LF_cos_sin_t factor = cl_cossin_aux(pk,lqk,len); + if (first_factor) { + product = factor; + first_factor = cl_false; + } else + product = product * factor; + } + } + if (first_factor) + return cl_LF_cos_sin_t(cl_I_to_LF(1,len),cl_I_to_LF(0,len)); + else + return product; +} +// Bit complexity (N = length(x)): O(log(N)^2*M(N)). diff --git a/src/float/transcendental/cl_LF_cossin_aux.cc b/src/float/transcendental/cl_LF_cossin_aux.cc new file mode 100644 index 0000000..ce47078 --- /dev/null +++ b/src/float/transcendental/cl_LF_cossin_aux.cc @@ -0,0 +1,117 @@ +// cl_cossin_aux(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_LF_tran.h" +#include "cl_LF.h" +#include "cl_integer.h" +#include "cl_alloca.h" +#include "cl_abort.h" + +#undef floor +#include +#define floor cln_floor + +// Computing cos(x) = sqrt(1-sin(x)^2) instead of computing separately +// by a power series evaluation brings 20% speedup, even more for small lengths. +#define TRIVIAL_SPEEDUP + +const cl_LF_cos_sin_t cl_cossin_aux (const cl_I& p, uintL lq, uintC len) +{ + { Mutable(cl_I,p); + var uintL lp = integer_length(p); // now |p| < 2^lp. + if (!(lp <= lq)) cl_abort(); + lp = lq - lp; // now |p/2^lq| < 2^-lp. + // Minimize lq (saves computation time). + { + var uintL lp2 = ord2(p); + if (lp2 > 0) { + p = p >> lp2; + lq = lq - lp2; + } + } + // cos(p/2^lq): + // Evaluate a sum(0 <= n < N, a(n)/b(n) * (p(0)...p(n))/(q(0)...q(n))) + // with appropriate N, and + // a(n) = 1, b(n) = 1, + // p(n) = -p^2 for n>0, + // q(n) = (2*n-1)*(2*n)*(2^lq)^2 for n>0. + // sin(p/2^lq): + // Evaluate a sum(0 <= n < N, a(n)/b(n) * (p(0)...p(n))/(q(0)...q(n))) + // with appropriate N, and + // a(n) = 1, b(n) = 1, + // p(0) = p, p(n) = -p^2 for n>0, + // q(0) = 2^lq, q(n) = (2*n)*(2*n+1)*(2^lq)^2 for n>0. + var uintC actuallen = len+1; // 1 Schutz-Digit + // How many terms to we need for M bits of precision? N/2 terms suffice, + // provided that + // 1/(2^(N*lp)*N!) < 2^-M + // <== N*(log(N)-1)+N*lp*log(2) > M*log(2) + // First approximation: + // N0 = M will suffice, so put N<=N0. + // Second approximation: + // N1 = floor(M*log(2)/(log(N0)-1+lp*log(2))), slightly too small, + // so put N>=N1. + // Third approximation: + // N2 = ceiling(M*log(2)/(log(N1)-1+lp*log(2))), slightly too large. + // N = N2+2, two more terms for safety. + var uintL N0 = intDsize*actuallen; + var uintL N1 = (uintL)(0.693147*intDsize*actuallen/(log((double)N0)-1.0+0.693148*lp)); + var uintL N2 = (uintL)(0.693148*intDsize*actuallen/(log((double)N1)-1.0+0.693147*lp))+1; + var uintL N = N2+2; + N = ceiling(N,2); + CL_ALLOCA_STACK; + var cl_I* pv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var cl_I* qv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var uintL* qsv = (uintL*) cl_alloca(N*sizeof(uintL)); + var uintL n; + var cl_I p2 = -square(p); + var cl_LF sinsum; + { + init1(cl_I, pv[0]) (p); + init1(cl_I, qv[0]) ((cl_I)1 << lq); + for (n = 1; n < N; n++) { + init1(cl_I, pv[n]) (p2); + init1(cl_I, qv[n]) (((cl_I)n*(cl_I)(2*n+1)) << (2*lq+1)); + } + var cl_pq_series series; + series.pv = pv; series.qv = qv; series.qsv = qsv; + sinsum = eval_rational_series(N,series,actuallen); + for (n = 0; n < N; n++) { + pv[n].~cl_I(); + qv[n].~cl_I(); + } + } + #if !defined(TRIVIAL_SPEEDUP) + var cl_LF cossum; + { + init1(cl_I, pv[0]) (1); + init1(cl_I, qv[0]) (1); + for (n = 1; n < N; n++) { + init1(cl_I, pv[n]) (p2); + init1(cl_I, qv[n]) (((cl_I)n*(cl_I)(2*n-1)) << (2*lq+1)); + } + var cl_pq_series series; + series.pv = pv; series.qv = qv; series.qsv = qsv; + cossum = eval_rational_series(N,series,actuallen); + for (n = 0; n < N; n++) { + pv[n].~cl_I(); + qv[n].~cl_I(); + } + } + #else // TRIVIAL_SPEEDUP + var cl_LF cossum = sqrt(cl_I_to_LF(1,actuallen) - square(sinsum)); + #endif + return cl_LF_cos_sin_t(shorten(cossum,len),shorten(sinsum,len)); // verkürzen und fertig +}} +// Bit complexity (N = len, and if p has length O(log N) and ql = O(log N)): +// O(log(N)*M(N)). + diff --git a/src/float/transcendental/cl_LF_eulerconst.cc b/src/float/transcendental/cl_LF_eulerconst.cc new file mode 100644 index 0000000..d6cdcf7 --- /dev/null +++ b/src/float/transcendental/cl_LF_eulerconst.cc @@ -0,0 +1,519 @@ +// cl_eulerconst(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_LF_tran.h" +#include "cl_LF.h" +#include "cl_integer.h" +#include "cl_alloca.h" +#include "cl_abort.h" + +#if 0 // works, but besselintegral4 is always faster + +const cl_LF compute_eulerconst_expintegral (uintC len) +{ + // [Jonathan M. Borwein, Peter B. Borwein: Pi and the AGM. + // Wiley 1987. Section 10.2.3, exercise 11, p. 336] + // Use the following formula for the modified exponential integral + // (valid for Re(z) > 0) + // E1(z) := integral(t = z..+infty, exp(-t)/t dt) + // E1(z) = - log z - C + sum(n=1..infty, (-1)^(n-1) z^n / (n*n!)) + // [Hint for proving this formula: + // 1. Learn about the elementary properties of the Gamma function. + // 2. -C = derivative of Gamma at 1 + // = lim_{z -> 0} (Gamma(z) - 1/z) + // = integral(t = 0..1, (exp(-t)-1)/t dt) + // + integral(t = 1..infty, exp(-t)/t dt) + // 3. Add + // 0 = integral(t=0..1, 1/(t+1)) - integral(t=1..infty, 1/t(t+1) dt) + // to get + // -C = integral(t = 0..infty, (exp(-t)/t - 1/t(t+1)) dt) + // 4. Compute E1(z) + C and note that E1(z) + C + log z is the integral + // of an entire function, hence an entire function as well.] + // Of course we also have the estimate + // |E1(z)| < exp(-Re(z)). + // This means that we can get C by computing + // sum(n=1..infty, (-1)^(n-1) z^n / (n*n!)) - log z + // for large z. + // In order to get M bits of precision, we first choose z (real) such + // that exp(-z) < 2^-M. This will make |E1(z)| small enough. z should + // be chosen as an integer, this is the key to computing the series + // sum very fast. z = M*log(2) + O(1). + // Then we choose the number N of terms: + // Note than the n-th term's absolute value is (logarithmically) + // n*log(z) - n*log(n) + n - 3/2*log(n) - log(sqrt(2 pi)) + o(1). + // The derivative of this with respect to n is + // log(z) - log(n) - 3/(2n) + o(1/n), + // hence is increasing for n < z and decreasing for n > z. + // The maximum value is attained at n = z + O(1), and is z + O(log z), + // which means that we need z/log(2) + O(log z) bits before the + // decimal point. + // We can cut off the series when + // n*log(z) - n*log(n) + n - 3/2*log(n) - log(sqrt(2 pi)) < -M*log(2) + // This happens at n = alpha*z - 3/(2*log(alpha))*log(z) + O(1), + // where alpha = 3.591121477... is the solution of + // -alpha*log(alpha) + alpha + 1 = 0. + // [Use the Newton iteration alpha --> (alpha+1)/log(alpha) to + // compute this number.] + // Finally we compute the series's sum as + // sum(0 <= n < N, a(n)/b(n) * (p(0)...p(n))/(q(0)...q(n))) + // with a(n) = 1, b(n) = n+1, p(n) = z for n=0, -z for n>0, q(n) = n+1. + // If we computed this with floating-point numbers, we would have + // to more than double the floating-point precision because of the large + // extinction which takes place. But luckily we compute with integers. + var uintC actuallen = len+1; // 1 Schutz-Digit + var uintL z = (uintL)(0.693148*intDsize*actuallen)+1; + var uintL N = (uintL)(3.591121477*z); + CL_ALLOCA_STACK; + var cl_I* bv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var cl_I* pv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var cl_I* qv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var uintL n; + for (n = 0; n < N; n++) { + init1(cl_I, bv[n]) (n+1); + init1(cl_I, pv[n]) (n==0 ? (cl_I)z : -(cl_I)z); + init1(cl_I, qv[n]) (n+1); + } + var cl_pqb_series series; + series.bv = bv; + series.pv = pv; series.qv = qv; series.qsv = NULL; + var cl_LF fsum = eval_rational_series(N,series,actuallen); + for (n = 0; n < N; n++) { + bv[n].~cl_I(); + pv[n].~cl_I(); + qv[n].~cl_I(); + } + fsum = fsum - ln(cl_I_to_LF(z,actuallen)); // log(z) subtrahieren + return shorten(fsum,len); // verkürzen und fertig +} +// Bit complexity (N = len): O(log(N)^2*M(N)). + +#endif + +#if 0 // works, but besselintegral1 is twice as fast + +const cl_LF compute_eulerconst_expintegral1 (uintC len) +{ + // Define f(z) := sum(n=0..infty, z^n/n!) = exp(z) + // and g(z) := sum(n=0..infty, H_n*z^n/n!) + // where H_n := 1/1 + 1/2 + ... + 1/n. + // The following formula can be proved: + // g'(z) - g(z) = (exp(z)-1)/z, + // g(z) = exp(z)*(log(z) + c3 + integral(t=..z, exp(-t)/t dt)) + // The Laplace method for determining the asymptotics of an integral + // or sum yields for real x>0 (the terms n = x+O(x^(1/2)) are + // dominating): + // f(x) = exp(x)*(1 + O(x^(-1/2))) + // g(x) = exp(x)*(log(x) + C + O(log(x)*x^(-1/2))) + // Hence + // g(x)/f(x) - log(x) - C = O(log(x)*x^(-1/2)) + // This determines the constant c3, we thus have + // g(z) = exp(z)*(log(z) + C + integral(t=z..infty, exp(-t)/t dt)) + // Hence we have for x -> infty: + // g(x)/f(x) - log(x) - C == O(exp(-x)) + // This means that we can get C by computing + // g(x)/f(x) - log(x) + // for large x. + // In order to get M bits of precision, we first choose x (real) such + // that exp(-x) < 2^-M. This will make the absolute value of the + // integral small enough. x should be chosen as an integer, this is + // the key to computing the series sum very fast. x = M*log(2) + O(1). + // Then we choose the number N of terms: + // Note than the n-th term's absolute value is (logarithmically) + // n*log(x) - n*log(n) + n - 1/2*log(n) - 1/2*log(2 pi) + o(1). + // The derivative of this with respect to n is + // log(x) - log(n) - 1/2n + o(1/n), + // hence is increasing for n < x and decreasing for n > x. + // The maximum value is attained at n = x + O(1), and is + // x + O(log x), which means that we need x/log(2) + O(log x) + // bits before the decimal point. This also follows from the + // asymptotic estimate for f(x). + // We can cut off the series when the relative error is < 2^-M, + // i.e. when the absolute error is < 2^-M*exp(x), i.e. + // n*log(x) - n*log(n) + n - 1/2*log(n) - 1/2*log(2 pi) < + // < -M*log(2) + x + // This happens at n = e*x - 1/2*log(x) + O(1). + // Finally we compute the sums of the series f(x) and g(x) with N terms + // each. + // We compute f(x) classically and g(x) using the partial sums of f(x). + var uintC actuallen = len+2; // 2 Schutz-Digits + var uintL x = (uintL)(0.693148*intDsize*actuallen)+1; + var uintL N = (uintL)(2.718281828*x); + var cl_LF one = cl_I_to_LF(1,actuallen); + var cl_LF fterm = one; + var cl_LF fsum = fterm; + var cl_LF gterm = cl_I_to_LF(0,actuallen); + var cl_LF gsum = gterm; + var uintL n; + // After n loops + // fterm = x^n/n!, fsum = 1 + x/1! + ... + x^n/n!, + // gterm = H_n*x^n/n!, gsum = H_1*x/1! + ... + H_n*x^n/n!. + for (n = 1; n < N; n++) { + fterm = The(cl_LF)(fterm*x)/n; + gterm = (The(cl_LF)(gterm*x) + fterm)/n; + if (len < 10 || n <= x) { + fsum = fsum + fterm; + gsum = gsum + gterm; + } else { + // For n > x, the terms are decreasing. + // So we can reduce the precision accordingly. + fterm = cl_LF_shortenwith(fterm,one); + gterm = cl_LF_shortenwith(gterm,one); + fsum = fsum + LF_to_LF(fterm,actuallen); + gsum = gsum + LF_to_LF(gterm,actuallen); + } + } + var cl_LF result = gsum/fsum - ln(cl_I_to_LF(x,actuallen)); + return shorten(result,len); // verkürzen und fertig +} +// Bit complexity (N = len): O(N^2). + +#endif + +#if 0 // works, but besselintegral4 is always faster + +// Same algorithm as expintegral1, but using binary splitting to evaluate +// the sums. +const cl_LF compute_eulerconst_expintegral2 (uintC len) +{ + var uintC actuallen = len+2; // 2 Schutz-Digits + var uintL x = (uintL)(0.693148*intDsize*actuallen)+1; + var uintL N = (uintL)(2.718281828*x); + CL_ALLOCA_STACK; + var cl_pqd_series_term* args = (cl_pqd_series_term*) cl_alloca(N*sizeof(cl_pqd_series_term)); + var uintL n; + for (n = 0; n < N; n++) { + init1(cl_I, args[n].p) (x); + init1(cl_I, args[n].q) (n+1); + init1(cl_I, args[n].d) (n+1); + } + var cl_pqd_series_result sums; + eval_pqd_series_aux(N,args,sums); + // Instead of computing fsum = 1 + T/Q and gsum = V/(D*Q) + // and then dividing them, to compute gsum/fsum, we save two + // divisions by computing V/(D*(Q+T)). + var cl_LF result = + cl_I_to_LF(sums.V,actuallen) + / The(cl_LF)(sums.D * cl_I_to_LF(sums.Q+sums.T,actuallen)) + - ln(cl_I_to_LF(x,actuallen)); + for (n = 0; n < N; n++) { + args[n].p.~cl_I(); + args[n].q.~cl_I(); + args[n].d.~cl_I(); + } + return shorten(result,len); // verkürzen und fertig +} +// Bit complexity (N = len): O(log(N)^2*M(N)). + +#endif + +// cl_LF compute_eulerconst_besselintegral (uintC len) + // This is basically the algorithm used in Pari. + // Define f(z) := sum(n=0..infty, z^n/n!^2) + // and g(z) := sum(n=0..infty, H_n*z^n/n!^2) + // where H_n := 1/1 + 1/2 + ... + 1/n. + // [f(z) and g(z) are intimately related to the Bessel functions: + // f(x^2) = I_0(2*x), g(x^2) = K_0(2*x) + I_0(2*x*)*(C + log(x)).] + // The following formulas can be proved: + // z f''(z) + f'(z) - f(z) = 0, + // z g''(z) + g'(z) - g(z) = f'(z), + // g(z) = (log(z)/2 + c3 - 1/2 integral(t=..z, 1/(t f(t)^2) dt)) f(z) + // The Laplace method for determining the asymptotics of an integral + // or sum yields for real x>0 (the terms n = sqrt(x)+O(x^(1/4)) are + // dominating): + // f(x) = exp(2*sqrt(x))*x^(-1/4)*1/(2*sqrt(pi))*(1 + O(x^(-1/4))) + // g(x) = exp(2*sqrt(x))*x^(-1/4)*1/(2*sqrt(pi))* + // (1/2*log(x) + C + O(log(x)*x^(-1/4))) + // Hence + // g(x)/f(x) - 1/2*log(x) - C = O(log(x)*x^(-1/4)) + // This determines the constant c3, we thus have + // g(z)= (log(z)/2 + C + 1/2 integral(t=z..infty, 1/(t f(t)^2) dt)) f(z) + // Hence we have for x -> infty: + // g(x)/f(x) - 1/2*log(x) - C == pi*exp(-4*sqrt(x)) [approx.] + // This means that we can get C by computing + // g(x)/f(x) - 1/2*log(x) + // for large x. + // In order to get M bits of precision, we first choose x (real) such + // that exp(-4*sqrt(x)) < 2^-(M+2). This will make the absolute value + // of the integral small enough. x should be chosen as an integer, + // this is the key to computing the series sum very fast. sqrt(x) + // need not be an integer. Set sx = sqrt(x). + // sx = M*log(2)/4 + O(1). + // Then we choose the number N of terms: + // Note than the n-th term's absolute value is (logarithmically) + // n*log(x) - 2*n*log(n) + 2*n - log(n) - log(2 pi) + o(1). + // The derivative of this with respect to n is + // log(x) - 2*log(n) - 1/n + o(1/n), + // hence is increasing for n < sx and decreasing for n > sx. + // The maximum value is attained at n = sx + O(1), and is + // 2*sx + O(log x), which means that we need 2*sx/log(2) + O(log x) + // bits before the decimal point. This also follows from the + // asymptotic estimate for f(x). + // We can cut off the series when the relative error is < 2^-M, + // i.e. when the absolute error is + // < 2^-M*exp(2*sx)*sx^(-1/2)*1/(2*sqrt(pi)), + // i.e. + // n*log(x) - 2*n*log(n) + 2*n - log(n) - log(2 pi) < + // < -M*log(2) + 2*sx - 1/2*log(sx) - log(2 sqrt(pi)) + // This happens at n = alpha*sx - 1/(4*log(alpha))*log(sx) + O(1), + // where alpha = 3.591121477... is the solution of + // -alpha*log(alpha) + alpha + 1 = 0. + // [Use the Newton iteration alpha --> (alpha+1)/log(alpha) to + // compute this number.] + // Finally we compute the sums of the series f(x) and g(x) with N terms + // each. + +const cl_LF compute_eulerconst_besselintegral1 (uintC len) +{ + // We compute f(x) classically and g(x) using the partial sums of f(x). + var uintC actuallen = len+1; // 1 Schutz-Digit + var uintL sx = (uintL)(0.25*0.693148*intDsize*actuallen)+1; + var uintL N = (uintL)(3.591121477*sx); + var cl_I x = square((cl_I)sx); + var cl_LF eps = scale_float(cl_I_to_LF(1,LF_minlen),-(sintL)(sx*2.88539+10)); + var cl_LF fterm = cl_I_to_LF(1,actuallen); + var cl_LF fsum = fterm; + var cl_LF gterm = cl_I_to_LF(0,actuallen); + var cl_LF gsum = gterm; + var uintL n; + // After n loops + // fterm = x^n/n!^2, fsum = 1 + x/1!^2 + ... + x^n/n!^2, + // gterm = H_n*x^n/n!^2, gsum = H_1*x/1!^2 + ... + H_n*x^n/n!^2. + for (n = 1; n < N; n++) { + fterm = The(cl_LF)(fterm*x)/square((cl_I)n); + gterm = (The(cl_LF)(gterm*x)/(cl_I)n + fterm)/(cl_I)n; + if (len < 10 || n <= sx) { + fsum = fsum + fterm; + gsum = gsum + gterm; + } else { + // For n > sx, the terms are decreasing. + // So we can reduce the precision accordingly. + fterm = cl_LF_shortenwith(fterm,eps); + gterm = cl_LF_shortenwith(gterm,eps); + fsum = fsum + LF_to_LF(fterm,actuallen); + gsum = gsum + LF_to_LF(gterm,actuallen); + } + } + var cl_LF result = gsum/fsum - ln(cl_I_to_LF(sx,actuallen)); + return shorten(result,len); // verkürzen und fertig +} +// Bit complexity (N = len): O(N^2). + +#if 0 // works, but besselintegral1 is faster + +const cl_LF compute_eulerconst_besselintegral2 (uintC len) +{ + // We compute the sum of the series f(x) as + // sum(0 <= n < N, a(n)/b(n) * (p(0)...p(n))/(q(0)...q(n))) + // with a(n) = 1, b(n) = 1, p(n) = x for n>0, q(n) = n^2 for n>0. + // and the sum of the series g(x) as + // sum(0 <= n < N, a(n)/b(n) * (p(0)...p(n))/(q(0)...q(n))) + // with + // a(n) = HN_{n+1}, b(n) = 1, p(n) = x, q(n) = (n+1)^2 * HD_{n+1}/HD_{n} + // where HD_n := lcm(1,...,n) and HN_n := HD_n * H_n. (Note that + // HD_n need not be the lowest possible denominator of H_n. For + // example, n=6: H_6 = 49/20, but HD_6 = 60.) + // WARNING: The memory used by this algorithm grown quadratically in N. + // (Because HD_n grows like exp(n), hence HN_n grows like exp(n) as + // well, and we store all HN_n values in an array!) + var uintC actuallen = len+1; // 1 Schutz-Digit + var uintL sx = (uintL)(0.25*0.693148*intDsize*actuallen)+1; + var uintL N = (uintL)(3.591121477*sx); + var cl_I x = square((cl_I)sx); + CL_ALLOCA_STACK; + var cl_I* av = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var cl_I* pv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var cl_I* qv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var uintL n; + // Evaluate f(x). + init1(cl_I, pv[0]) (1); + init1(cl_I, qv[0]) (1); + for (n = 1; n < N; n++) { + init1(cl_I, pv[n]) (x); + init1(cl_I, qv[n]) ((cl_I)n*(cl_I)n); + } + var cl_pq_series fseries; + fseries.pv = pv; fseries.qv = qv; fseries.qsv = NULL; + var cl_LF fsum = eval_rational_series(N,fseries,actuallen); + for (n = 0; n < N; n++) { + pv[n].~cl_I(); + qv[n].~cl_I(); + } + // Evaluate g(x). + var cl_I HN = 0; + var cl_I HD = 1; + for (n = 0; n < N; n++) { + // Now HN/HD = H_n. + var cl_I Hu = gcd(HD,n+1); + var cl_I Hv = exquopos(n+1,Hu); + HN = HN*Hv + exquopos(HD,Hu); + HD = HD*Hv; + // Now HN/HD = H_{n+1}. + init1(cl_I, av[n]) (HN); + init1(cl_I, pv[n]) (x); + init1(cl_I, qv[n]) (Hv*(cl_I)(n+1)*(cl_I)(n+1)); + } + var cl_pqa_series gseries; + gseries.av = av; + gseries.pv = pv; gseries.qv = qv; gseries.qsv = NULL; + var cl_LF gsum = eval_rational_series(N,gseries,actuallen); + for (n = 0; n < N; n++) { + av[n].~cl_I(); + pv[n].~cl_I(); + qv[n].~cl_I(); + } + var cl_LF result = gsum/fsum - ln(cl_I_to_LF(sx,actuallen)); + return shorten(result,len); // verkürzen und fertig +} +// Bit complexity (N = len): O(N^2). +// Memory consumption: O(N^2). + +// Same algorithm as besselintegral2, but without quadratic memory consumption. +#define cl_rational_series_for_g cl_rational_series_for_besselintegral3_g +struct cl_rational_series_for_g : cl_pqa_series_stream { + uintL n; + cl_I HN; + cl_I HD; + cl_I x; + static cl_pqa_series_term computenext (cl_pqa_series_stream& thisss) + { + var cl_rational_series_for_g& thiss = (cl_rational_series_for_g&)thisss; + var uintL n = thiss.n; + // Now HN/HD = H_n. + var cl_I Hu = gcd(thiss.HD,n+1); + var cl_I Hv = exquopos(n+1,Hu); + thiss.HN = thiss.HN*Hv + exquopos(thiss.HD,Hu); + thiss.HD = thiss.HD*Hv; + // Now HN/HD = H_{n+1}. + var cl_pqa_series_term result; + result.p = thiss.x; + result.q = Hv*(cl_I)(n+1)*(cl_I)(n+1); + result.a = thiss.HN; + thiss.n = n+1; + return result; + } + cl_rational_series_for_g (const cl_I& _x) + : cl_pqa_series_stream (cl_rational_series_for_g::computenext), + n (0), HN (0), HD (1), x (_x) {} +}; +const cl_LF compute_eulerconst_besselintegral3 (uintC len) +{ + var uintC actuallen = len+1; // 1 Schutz-Digit + var uintL sx = (uintL)(0.25*0.693148*intDsize*actuallen)+1; + var uintL N = (uintL)(3.591121477*sx); + var cl_I x = square((cl_I)sx); + CL_ALLOCA_STACK; + var cl_I* pv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var cl_I* qv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var uintL n; + // Evaluate f(x). + init1(cl_I, pv[0]) (1); + init1(cl_I, qv[0]) (1); + for (n = 1; n < N; n++) { + init1(cl_I, pv[n]) (x); + init1(cl_I, qv[n]) ((cl_I)n*(cl_I)n); + } + var cl_pq_series fseries; + fseries.pv = pv; fseries.qv = qv; fseries.qsv = NULL; + var cl_LF fsum = eval_rational_series(N,fseries,actuallen); + for (n = 0; n < N; n++) { + pv[n].~cl_I(); + qv[n].~cl_I(); + } + // Evaluate g(x). + var cl_rational_series_for_g gseries = cl_rational_series_for_g(x); + var cl_LF gsum = eval_rational_series(N,gseries,actuallen); + var cl_LF result = gsum/fsum - ln(cl_I_to_LF(sx,actuallen)); + return shorten(result,len); // verkürzen und fertig +} +// Bit complexity (N = len): O(N^2). + +#endif + +// Same algorithm as besselintegral1, but using binary splitting to evaluate +// the sums. +const cl_LF compute_eulerconst_besselintegral4 (uintC len) +{ + var uintC actuallen = len+2; // 2 Schutz-Digits + var uintL sx = (uintL)(0.25*0.693148*intDsize*actuallen)+1; + var uintL N = (uintL)(3.591121477*sx); + var cl_I x = square((cl_I)sx); + CL_ALLOCA_STACK; + var cl_pqd_series_term* args = (cl_pqd_series_term*) cl_alloca(N*sizeof(cl_pqd_series_term)); + var uintL n; + for (n = 0; n < N; n++) { + init1(cl_I, args[n].p) (x); + init1(cl_I, args[n].q) (square((cl_I)(n+1))); + init1(cl_I, args[n].d) (n+1); + } + var cl_pqd_series_result sums; + eval_pqd_series_aux(N,args,sums); + // Instead of computing fsum = 1 + T/Q and gsum = V/(D*Q) + // and then dividing them, to compute gsum/fsum, we save two + // divisions by computing V/(D*(Q+T)). + var cl_LF result = + cl_I_to_LF(sums.V,actuallen) + / The(cl_LF)(sums.D * cl_I_to_LF(sums.Q+sums.T,actuallen)) + - ln(cl_I_to_LF(sx,actuallen)); + for (n = 0; n < N; n++) { + args[n].p.~cl_I(); + args[n].q.~cl_I(); + args[n].d.~cl_I(); + } + return shorten(result,len); // verkürzen und fertig +} +// Bit complexity (N = len): O(log(N)^2*M(N)). + +// Timings of the above algorithms, on an i486 33 MHz, running Linux. +// N exp exp1 exp2 bessel1 bessel2 bessel3 bessel4 +// 10 0.51 0.28 0.52 0.11 0.16 0.16 0.15 +// 25 2.23 0.83 2.12 0.36 0.62 0.63 0.62 +// 50 6.74 2.23 6.54 0.95 1.95 1.97 1.95 +// 100 19.1 6.74 20.6 2.96 6.47 6.42 6.3 +// 250 84 37.4 78 16.3 33.6 32.0 28.8 +// 500 230 136.5 206 60.5 --- 111 85 +// 1000 591 520 536 229 --- 377 241 +// 1050 254 252 +// 1100 277 266 +// 2500 1744 2108 (1268) 855 (run) +// 2500 1845 2192 (1269) 891 (real) +// +// asymp. FAST N^2 FAST N^2 N^2 N^2 FAST +// (FAST means O(log(N)^2*M(N))) +// +// The break-even point between "bessel1" and "bessel4" is at about N = 1050. +const cl_LF compute_eulerconst (uintC len) +{ + if (len >= 1050) + return compute_eulerconst_besselintegral4(len); + else + return compute_eulerconst_besselintegral1(len); +} + +const cl_LF cl_eulerconst (uintC len) +{ + var uintC oldlen = TheLfloat(cl_LF_eulerconst)->len; // vorhandene Länge + if (len < oldlen) + return shorten(cl_LF_eulerconst,len); + if (len == oldlen) + return cl_LF_eulerconst; + + // TheLfloat(cl_LF_eulerconst)->len um mindestens einen konstanten Faktor + // > 1 wachsen lassen, damit es nicht zu häufig nachberechnet wird: + var uintC newlen = len; + oldlen += floor(oldlen,2); // oldlen * 3/2 + if (newlen < oldlen) + newlen = oldlen; + + // gewünschte > vorhandene Länge -> muß nachberechnen: + cl_LF_eulerconst = compute_eulerconst(newlen); + return (len < newlen ? shorten(cl_LF_eulerconst,len) : cl_LF_eulerconst); +} diff --git a/src/float/transcendental/cl_LF_exp1.cc b/src/float/transcendental/cl_LF_exp1.cc new file mode 100644 index 0000000..c9272fb --- /dev/null +++ b/src/float/transcendental/cl_LF_exp1.cc @@ -0,0 +1,94 @@ +// cl_exp1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_LF_tran.h" +#include "cl_LF.h" +#include "cl_integer.h" +#include "cl_alloca.h" + +#undef floor +#include +#define floor cln_floor + +const cl_LF compute_exp1 (uintC len) +{ + // Evaluate a sum(0 <= n < N, a(n)/b(n) * (p(0)...p(n))/(q(0)...q(n))) + // with appropriate N, and + // a(n) = 1, b(n) = 1, p(n) = 1, q(n) = n for n>0. + var uintC actuallen = len+1; // 1 Schutz-Digit + // How many terms to we need for M bits of precision? N terms suffice, + // provided that + // 1/N! < 2^-M + // <== N*(log(N)-1) > M*log(2) + // First approximation: + // N0 = M will suffice, so put N<=N0. + // Second approximation: + // N1 = floor(M*log(2)/(log(N0)-1)), slightly too small, so put N>=N1. + // Third approximation: + // N2 = ceiling(M*log(2)/(log(N1)-1)), slightly too large. + // N = N2+2, two more terms for safety. + var uintL N0 = intDsize*actuallen; + var uintL N1 = (uintL)(0.693147*intDsize*actuallen/(log((double)N0)-1.0)); + var uintL N2 = (uintL)(0.693148*intDsize*actuallen/(log((double)N1)-1.0))+1; + var uintL N = N2+2; + CL_ALLOCA_STACK; + var cl_I* qv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var uintL* qsv = (uintL*) cl_alloca(N*sizeof(uintL)); + var uintL n; + for (n = 0; n < N; n++) { + init1(cl_I, qv[n]) (n==0 ? 1 : n); + } + var cl_q_series series; + series.qv = qv; + series.qsv = (len >= 1000 && len <= 10000 ? qsv : 0); // tiny speedup + var cl_LF fsum = eval_rational_series(N,series,actuallen); + for (n = 0; n < N; n++) { + qv[n].~cl_I(); + } + return shorten(fsum,len); // verkürzen und fertig +} +// Bit complexity (N = len): O(log(N)*M(N)). + +// Timings of the above algorithm, on an i486 33 MHz, running Linux. +// N +// 10 0.0040 +// 25 0.0096 +// 50 0.0218 +// 100 0.057 +// 250 0.24 +// 500 0.78 +// 1000 2.22 +// 2500 7.6 +// 5000 17.8 +// 10000 41.4 +// 25000 111 +// 50000 254 + +const cl_LF cl_exp1 (uintC len) +{ + var uintC oldlen = TheLfloat(cl_LF_exp1)->len; // vorhandene Länge + if (len < oldlen) + return shorten(cl_LF_exp1,len); + if (len == oldlen) + return cl_LF_exp1; + + // TheLfloat(cl_LF_exp1)->len um mindestens einen konstanten Faktor + // > 1 wachsen lassen, damit es nicht zu häufig nachberechnet wird: + var uintC newlen = len; + oldlen += floor(oldlen,2); // oldlen * 3/2 + if (newlen < oldlen) + newlen = oldlen; + + // gewünschte > vorhandene Länge -> muß nachberechnen: + cl_LF_exp1 = compute_exp1(newlen); // (exp 1) + return (len < newlen ? shorten(cl_LF_exp1,len) : cl_LF_exp1); +} diff --git a/src/float/transcendental/cl_LF_exp_aux.cc b/src/float/transcendental/cl_LF_exp_aux.cc new file mode 100644 index 0000000..145bbe2 --- /dev/null +++ b/src/float/transcendental/cl_LF_exp_aux.cc @@ -0,0 +1,79 @@ +// cl_exp_aux(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_LF_tran.h" +#include "cl_LF.h" +#include "cl_integer.h" +#include "cl_alloca.h" +#include "cl_abort.h" + +#undef floor +#include +#define floor cln_floor + +const cl_LF cl_exp_aux (const cl_I& p, uintL lq, uintC len) +{ + { Mutable(cl_I,p); + var uintL lp = integer_length(p); // now |p| < 2^lp. + if (!(lp <= lq)) cl_abort(); + lp = lq - lp; // now |p/2^lq| < 2^-lp. + // Minimize lq (saves computation time). + { + var uintL lp2 = ord2(p); + if (lp2 > 0) { + p = p >> lp2; + lq = lq - lp2; + } + } + // Evaluate a sum(0 <= n < N, a(n)/b(n) * (p(0)...p(n))/(q(0)...q(n))) + // with appropriate N, and + // a(n) = 1, b(n) = 1, p(n) = p for n>0, q(n) = n*2^lq for n>0. + var uintC actuallen = len+1; // 1 Schutz-Digit + // How many terms to we need for M bits of precision? N terms suffice, + // provided that + // 1/(2^(N*lp)*N!) < 2^-M + // <== N*(log(N)-1)+N*lp*log(2) > M*log(2) + // First approximation: + // N0 = M will suffice, so put N<=N0. + // Second approximation: + // N1 = floor(M*log(2)/(log(N0)-1+lp*log(2))), slightly too small, + // so put N>=N1. + // Third approximation: + // N2 = ceiling(M*log(2)/(log(N1)-1+lp*log(2))), slightly too large. + // N = N2+2, two more terms for safety. + var uintL N0 = intDsize*actuallen; + var uintL N1 = (uintL)(0.693147*intDsize*actuallen/(log((double)N0)-1.0+0.693148*lp)); + var uintL N2 = (uintL)(0.693148*intDsize*actuallen/(log((double)N1)-1.0+0.693147*lp))+1; + var uintL N = N2+2; + CL_ALLOCA_STACK; + var cl_I* pv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var cl_I* qv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var uintL* qsv = (uintL*) cl_alloca(N*sizeof(uintL)); + var uintL n; + init1(cl_I, pv[0]) (1); + init1(cl_I, qv[0]) (1); + for (n = 1; n < N; n++) { + init1(cl_I, pv[n]) (p); + init1(cl_I, qv[n]) ((cl_I)n << lq); + } + var cl_pq_series series; + series.pv = pv; series.qv = qv; series.qsv = qsv; + var cl_LF fsum = eval_rational_series(N,series,actuallen); + for (n = 0; n < N; n++) { + pv[n].~cl_I(); + qv[n].~cl_I(); + } + return shorten(fsum,len); // verkürzen und fertig +}} +// Bit complexity (N = len, and if p has length O(log N) and ql = O(log N)): +// O(log(N)*M(N)). + diff --git a/src/float/transcendental/cl_LF_ln10.cc b/src/float/transcendental/cl_LF_ln10.cc new file mode 100644 index 0000000..8f05a8a --- /dev/null +++ b/src/float/transcendental/cl_LF_ln10.cc @@ -0,0 +1,65 @@ +// cl_ln10(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_LF.h" + +static inline const cl_LF compute_ln10_old (uintC len) +{ + return ln(cl_I_to_LF(10,len)); +} + +// ln 10 = +// = 46 atanh(1/31) + 34 atanh(1/49) + 20 atanh(1/161) +// = 478 atanh(1/251) + 180 atanh(1/449) - 126 atanh(1/4801) + 206 atanh(1/8749) + +static inline const cl_LF compute_ln10_p235 (uintC len) +{ + var uintC actuallen = len+1; + return shorten( The(cl_LF)(46 * cl_atanh_recip(31,actuallen)) + + The(cl_LF)(34 * cl_atanh_recip(49,actuallen)) + + The(cl_LF)(20 * cl_atanh_recip(161,actuallen)), + len + ); +} + +static inline const cl_LF compute_ln10_p2357 (uintC len) +{ + var uintC actuallen = len+1; + return shorten( The(cl_LF)(478 * cl_atanh_recip(251,actuallen)) + + The(cl_LF)(180 * cl_atanh_recip(449,actuallen)) + - The(cl_LF)(126 * cl_atanh_recip(4801,actuallen)) + + The(cl_LF)(206 * cl_atanh_recip(8749,actuallen)), + len + ); +} + +#define compute_ln10 compute_ln10_p2357 + +const cl_LF cl_ln10 (uintC len) +{ + var uintC oldlen = TheLfloat(cl_LF_ln10)->len; // vorhandene Länge + if (len < oldlen) + return shorten(cl_LF_ln10,len); + if (len == oldlen) + return cl_LF_ln10; + + // TheLfloat(cl_LF_ln10)->len um mindestens einen konstanten Faktor + // > 1 wachsen lassen, damit es nicht zu häufig nachberechnet wird: + var uintC newlen = len; + oldlen += floor(oldlen,2); // oldlen * 3/2 + if (newlen < oldlen) + newlen = oldlen; + + // gewünschte > vorhandene Länge -> muß nachberechnen: + cl_LF_ln10 = compute_ln10(newlen); + return (len < newlen ? shorten(cl_LF_ln10,len) : cl_LF_ln10); +} diff --git a/src/float/transcendental/cl_LF_ln2.cc b/src/float/transcendental/cl_LF_ln2.cc new file mode 100644 index 0000000..8ff8096 --- /dev/null +++ b/src/float/transcendental/cl_LF_ln2.cc @@ -0,0 +1,93 @@ +// cl_ln2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_LF.h" + +static inline const cl_LF compute_ln2_old (uintC len) +{ + // Here, it is tricky to avoid a recursive loop. We assume that ln() + // will not invoke cl_ln2() if its argument is between 2/3 and 4/3. + // So we compute -2*ln(1/sqrt(2)). + return -scale_float(ln(sqrt(scale_float(cl_I_to_LF(1,len),-1))),1); +} + +// ln 2 = +// = 2 atanh(1/3) +// = 4 atanh(1/7) + 2 atanh(1/17) +// = 14 atanh(1/31) + 10 atanh(1/49) + 6 atanh(1/161) +// = 144 atanh(1/251) + 54 atanh(1/449) - 38 atanh(1/4801) + 62 atanh(1/8749) + +static inline const cl_LF compute_ln2_p2 (uintC len) +{ + return scale_float(cl_atanh_recip(3,len),1); +} + +static inline const cl_LF compute_ln2_p23 (uintC len) +{ + var uintC actuallen = len+1; + return shorten(scale_float(cl_atanh_recip(7,actuallen),2) + + scale_float(cl_atanh_recip(17,actuallen),1), + len + ); +} + +static inline const cl_LF compute_ln2_p235 (uintC len) +{ + var uintC actuallen = len+1; + return shorten( The(cl_LF)(14 * cl_atanh_recip(31,actuallen)) + + The(cl_LF)(10 * cl_atanh_recip(49,actuallen)) + + The(cl_LF)( 6 * cl_atanh_recip(161,actuallen)), + len + ); +} + +static inline const cl_LF compute_ln2_p2357 (uintC len) +{ + var uintC actuallen = len+1; + return shorten( The(cl_LF)(144 * cl_atanh_recip(251,actuallen)) + + The(cl_LF)( 54 * cl_atanh_recip(449,actuallen)) + - The(cl_LF)( 38 * cl_atanh_recip(4801,actuallen)) + + The(cl_LF)( 62 * cl_atanh_recip(8749,actuallen)), + len + ); +} + +// Timings of the above algorithms, on an i486 33 MHz, running Linux. +// N = 250 +// p2 1.71 s total 1.71 s +// p23 0.88 + 0.60 s total 1.48 s +// p235 0.51 + 0.48 + 0.40 s total 1.39 s +// p2357 0.38 + 0.37 + 0.31 + 0.29 s total 1.35 s +// In general, for fixed precision N, the computation time of atanh(1/m) +// seems to be proportional to 1/log(m). + +#define compute_ln2 compute_ln2_p2357 + +const cl_LF cl_ln2 (uintC len) +{ + var uintC oldlen = TheLfloat(cl_LF_ln2)->len; // vorhandene Länge + if (len < oldlen) + return shorten(cl_LF_ln2,len); + if (len == oldlen) + return cl_LF_ln2; + + // TheLfloat(cl_LF_ln2)->len um mindestens einen konstanten Faktor + // > 1 wachsen lassen, damit es nicht zu häufig nachberechnet wird: + var uintC newlen = len; + oldlen += floor(oldlen,2); // oldlen * 3/2 + if (newlen < oldlen) + newlen = oldlen; + + // gewünschte > vorhandene Länge -> muß nachberechnen: + cl_LF_ln2 = compute_ln2(newlen); + return (len < newlen ? shorten(cl_LF_ln2,len) : cl_LF_ln2); +} diff --git a/src/float/transcendental/cl_LF_pi.cc b/src/float/transcendental/cl_LF_pi.cc new file mode 100644 index 0000000..ef22cb7 --- /dev/null +++ b/src/float/transcendental/cl_LF_pi.cc @@ -0,0 +1,277 @@ +// cl_pi(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_LF_tran.h" +#include "cl_LF.h" +#include "cl_integer.h" +#include "cl_alloca.h" + +ALL_cl_LF_OPERATIONS_SAME_PRECISION() + +// For the next algorithms, I warmly recommend +// [Jörg Arndt: hfloat documentation, august 1996, +// http://www.tu-chemnitz.de/~arndt/ hfdoc.dvi +// But beware of the typos in his formulas! ] + +const cl_LF compute_pi_brent_salamin (uintC len) +{ + // Methode: + // [Richard P. Brent: Fast multiple-precision evaluation of elementary + // functions. J. ACM 23(1976), 242-251.] + // [Jonathan M. Borwein, Peter B. Borwein: Pi and the AGM. + // Wiley 1987. Algorithm 2.2, p. 48.] + // [Jörg Arndt, formula (4.51)-(4.52).] + // pi = AGM(1,1/sqrt(2))^2 * 2/(1 - sum(k=0..infty, 2^k c_k^2)). + // where the AGM iteration reads + // a_0 := 1, b_0 := 1/sqrt(2). + // a_(k+1) := (a_k + b_k)/2, b_(k+1) := sqrt(a_k*b_k). + // and we set + // c_k^2 := a_k^2 - b_k^2, + // i.e. c_0^2 = 1/2, + // c_(k+1)^2 = a_(k+1)^2 - b_(k+1)^2 = (a_k - b_k)^2/4 + // = (a_k - a_(k+1))^2. + // (Actually c_(k+1) is _defined_ as = a_k - a_(k+1) = (a_k - b_k)/2.) + // d=len, n:=intDsize*d. Verwende Long-Floats mit intDsize*(d+1) + // Mantissenbits. + // (let* ((a (coerce 1 'long-float)) ; 1 + // (b (sqrt (scale-float a -1))) ; 2^-(1/2) + // (eps (scale-float a (- n))) ; 2^-n + // (t (scale-float a -2)) ; 1/4 + // (k 0) + // ) + // (loop + // (when (< (- a b) eps) (return)) + // (let ((y a)) + // (setq a (scale-float (+ a b) -1)) + // (setq b (sqrt (* b y))) + // (setq t (- t (scale-float (expt (- a y) 2) k))) + // ) + // (incf k) + // ) + // (/ (expt a 2) t) + // ) + var uintC actuallen = len + 1; // 1 Schutz-Digit + var uintL uexp_limit = LF_exp_mid - intDsize*(uintL)len; + // Ein Long-Float ist genau dann betragsmäßig <2^-n, wenn + // sein Exponent < LF_exp_mid-n = uexp_limit ist. + var cl_LF a = cl_I_to_LF(1,actuallen); + var cl_LF b = sqrt(scale_float(a,-1)); + var uintL k = 0; + var cl_LF t = scale_float(a,-2); + until (TheLfloat(a-b)->expo < uexp_limit) { + // |a-b| < 2^-n -> fertig + var cl_LF new_a = scale_float(a+b,-1); // (a+b)/2 + b = sqrt(a*b); + var cl_LF a_diff = new_a - a; + t = t - scale_float(square(a_diff),k); + a = new_a; + k++; + } + var cl_LF pi = square(a)/t; // a^2/t + return shorten(pi,len); // verkürzen und fertig +} +// Bit complexity (N := len): O(log(N)*M(N)). + +const cl_LF compute_pi_brent_salamin_quartic (uintC len) +{ + // See [Borwein, Borwein, section 1.4, exercise 3, p. 17]. + // See also [Jörg Arndt], formulas (4.52) and (3.30)[wrong!]. + // As above, we are using the formula + // pi = AGM(1,1/sqrt(2))^2 * 2/(1 - sum(k=0..infty, 2^k c_k^2)). + // where the AGM iteration reads + // a_0 := 1, b_0 := 1/sqrt(2). + // a_(k+1) := (a_k + b_k)/2, b_(k+1) := sqrt(a_k*b_k). + // But we keep computing with + // wa_k := sqrt(a_k) and wb_k := sqrt(b_k) + // at the same time and do two iteration steps at once. + // The iteration takes now takes the form + // wa_0 := 1, wb_0 := 2^-1/4, + // (wa_k, wb_k, a_k, b_k) + // --> ((wa_k^2 + wb_k^2)/2, wa_k*wb_k) + // --> (((wa_k + wb_k)/2)^2, sqrt(wa_k*wb_k*(wa_k^2 + wb_k^2)/2)), + // i.e. wa_(k+2) = (wa_k + wb_k)/2 and + // wb_(k+2) = sqrt(sqrt(wa_k*wb_k*(wa_k^2 + wb_k^2)/2)). + // For the sum, we can group two successive items together: + // 2^k * c_k^2 + 2^(k+1) * c_(k+1)^2 + // = 2^k * [(a_k^2 - b_k^2) + 2*((a_k - b_k)/2)^2] + // = 2^k * [3/2*a_k^2 - a_k*b_k - 1/2*b_k^2] + // = 2^k * [2*a_k^2 - 1/2*(a_k+b_k)^2] + // = 2^(k+1) * [a_k^2 - ((a_k+b_k)/2)^2] + // = 2^(k+1) * [wa_k^4 - ((wa_k^2+wb_k^2)/2)^2]. + // Hence, + // pi = AGM(1,1/sqrt(2))^2 * 1/(1/2 - sum(k even, 2^k*[....])). + var uintC actuallen = len + 1; // 1 Schutz-Digit + var uintL uexp_limit = LF_exp_mid - intDsize*(uintL)len; + var cl_LF one = cl_I_to_LF(1,actuallen); + var cl_LF a = one; + var cl_LF wa = one; + var cl_LF b = sqrt(scale_float(one,-1)); + var cl_LF wb = sqrt(b); + // We keep a = wa^2, b = wb^2. + var uintL k = 0; + var cl_LF t = scale_float(one,-1); + until (TheLfloat(wa-wb)->expo < uexp_limit) { + // |wa-wb| < 2^-n -> fertig + var cl_LF wawb = wa*wb; + var cl_LF new_wa = scale_float(wa+wb,-1); + var cl_LF a_b = scale_float(a+b,-1); + var cl_LF new_a = scale_float(a_b+wawb,-1); + var cl_LF new_b = sqrt(wawb*a_b); + var cl_LF new_wb = sqrt(new_b); + t = t - scale_float((a - a_b)*(a + a_b),k); + a = new_a; wa = new_wa; + b = new_b; wb = new_wb; + k += 2; + } + var cl_LF pi = square(a)/t; + return shorten(pi,len); // verkürzen und fertig +} +// Bit complexity (N := len): O(log(N)*M(N)). + +const cl_LF compute_pi_ramanujan_163 (uintC len) +{ + // 1/pi = 1/sqrt(-1728 J) + // * sum(n=0..infty, (6n)! (A+nB) / 12^(3n) (3n)! n!^3 J^n) + // mit J = -53360^3 = - (2^4 5 23 29)^3 + // A = 163096908 = 2^2 3 13 1045493 + // B = 6541681608 = 2^3 3^3 7 11 19 127 163 + // See [Jörg Arndt], formulas (4.27)-(4.30). + // This is also the formula used in Pari. + // The absolute value of the n-th summand is approximately + // |J|^-n * n^(-1/2) * B/(2*pi^(3/2)), + // hence every summand gives more than 14 new decimal digits + // in precision. + // The sum is best evaluated using fixed-point arithmetic, + // so that the precision is reduced for the later summands. + var uintL actuallen = len + 4; // 4 Schutz-Digits + var sintL scale = intDsize*actuallen; + static const cl_I A = "163096908"; + static const cl_I B = "6541681608"; + //static const cl_I J1 = "10939058860032000"; // 72*abs(J) + static const cl_I J2 = "333833583375"; // odd part of J1 + var cl_I sum = 0; + var cl_I n = 0; + var cl_I factor = ash(1,scale); + while (!zerop(factor)) { + sum = sum + factor * (A+n*B); + factor = factor * ((6*n+1)*(2*n+1)*(6*n+5)); + n = n+1; + factor = truncate1(factor,n*n*n*J2); + // Finally divide by 2^15 and change sign. + if (minusp(factor)) + factor = (-factor) >> 15; + else + factor = -(factor >> 15); + } + var cl_LF fsum = scale_float(cl_I_to_LF(sum,actuallen),-scale); + static const cl_I J3 = "262537412640768000"; // -1728*J + var cl_LF pi = sqrt(cl_I_to_LF(J3,actuallen)) / fsum; + return shorten(pi,len); // verkürzen und fertig +} +// Bit complexity (N := len): O(N^2). + +#if defined(__mips__) && !defined(__GNUC__) // workaround SGI CC bug +#define A A_fast +#define B B_fast +#define J3 J3_fast +#endif + +const cl_LF compute_pi_ramanujan_163_fast (uintC len) +{ + // Same formula as above, using a binary splitting evaluation. + // See [Borwein, Borwein, section 10.2.3]. + var uintL actuallen = len + 4; // 4 Schutz-Digits + static const cl_I A = "163096908"; + static const cl_I B = "6541681608"; + static const cl_I J1 = "10939058860032000"; // 72*abs(J) + // Evaluate a sum(0 <= n < N, a(n)/b(n) * (p(0)...p(n))/(q(0)...q(n))) + // with appropriate N, and + // a(n) = A+n*B, b(n) = 1, + // p(n) = -(6n-5)(2n-1)(6n-1) for n>0, + // q(n) = 72*|J|*n^3 for n>0. + var const uintL n_slope = (uintL)(intDsize*32*0.02122673)+1; + // n_slope >= 32*intDsize*log(2)/log(|J|), normally n_slope = 22. + var uintL N = (n_slope*actuallen)/32 + 1; + // N > intDsize*log(2)/log(|J|) * actuallen, hence + // |J|^-N < 2^(-intDsize*actuallen). + CL_ALLOCA_STACK; + var cl_I* av = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var cl_I* pv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var cl_I* qv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var uintL* qsv = (uintL*) cl_alloca(N*sizeof(uintL)); + var uintL n; + for (n = 0; n < N; n++) { + init1(cl_I, av[n]) (A+n*B); + if (n==0) { + init1(cl_I, pv[n]) (1); + init1(cl_I, qv[n]) (1); + } else { + init1(cl_I, pv[n]) (-((cl_I)(6*n-5)*(cl_I)(2*n-1)*(cl_I)(6*n-1))); + init1(cl_I, qv[n]) ((cl_I)n*(cl_I)n*(cl_I)n*J1); + } + } + var cl_pqa_series series; + series.av = av; + series.pv = pv; series.qv = qv; + series.qsv = (len >= 35 ? qsv : 0); // 5% speedup for large len's + var cl_LF fsum = eval_rational_series(N,series,actuallen); + for (n = 0; n < N; n++) { + av[n].~cl_I(); + pv[n].~cl_I(); + qv[n].~cl_I(); + } + static const cl_I J3 = "262537412640768000"; // -1728*J + var cl_LF pi = sqrt(cl_I_to_LF(J3,actuallen)) / fsum; + return shorten(pi,len); // verkürzen und fertig +} +// Bit complexity (N := len): O(log(N)^2*M(N)). + +// Timings of the above algorithms, on an i486 33 MHz, running Linux. +// N Brent Brent4 R 163 R 163 fast +// 10 0.0079 0.0079 0.0052 0.0042 +// 25 0.026 0.026 0.014 0.012 +// 50 0.085 0.090 0.037 0.033 +// 100 0.29 0.29 0.113 0.098 +// 250 1.55 1.63 0.60 0.49 +// 500 5.7 5.7 2.24 1.71 +// 1000 21.6 22.9 8.5 5.5 +// 2500 89 95 49 19.6 +// 5000 217 218 188 49 +// 10000 509 540 747 117 +// 25000 1304 1310 4912 343 +// We see that +// - "Brent4" isn't worth it: No speed improvement over "Brent". +// - "R 163" is pretty fast at the beginning, but it is an O(N^2) +// algorithm, hence it loses in the end, +// - "R 163 fast", which uses the same formula as "R 163", but evaluates +// it using binary splitting, is an O(log N * M(N)) algorithm, and +// outperforms all of the others. + +const cl_LF cl_pi (uintC len) +{ + var uintC oldlen = TheLfloat(cl_LF_pi)->len; // vorhandene Länge + if (len < oldlen) + return shorten(cl_LF_pi,len); + if (len == oldlen) + return cl_LF_pi; + + // TheLfloat(cl_LF_pi)->len um mindestens einen konstanten Faktor + // > 1 wachsen lassen, damit es nicht zu häufig nachberechnet wird: + var uintC newlen = len; + oldlen += floor(oldlen,2); // oldlen * 3/2 + if (newlen < oldlen) + newlen = oldlen; + + // gewünschte > vorhandene Länge -> muß nachberechnen: + cl_LF_pi = compute_pi_ramanujan_163_fast(newlen); + return (len < newlen ? shorten(cl_LF_pi,len) : cl_LF_pi); +} diff --git a/src/float/transcendental/cl_LF_ratseries.cc b/src/float/transcendental/cl_LF_ratseries.cc new file mode 100644 index 0000000..23cdec6 --- /dev/null +++ b/src/float/transcendental/cl_LF_ratseries.cc @@ -0,0 +1,108 @@ +// eval_rational_series(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF_tran.h" + + +// Implementation. + +// Subroutine. +// Evaluates S = sum(N1 <= n < N2, a(n)/b(n) * (p(N1)...p(n))/(q(N1)...q(n))) +// and returns P = p(N1)...p(N2-1), Q = q(N1)...q(N2-1), B = B(N1)...B(N2-1) +// and T = B*Q*S (all integers). On entry N1 < N2. +// P will not be computed if a NULL pointer is passed. + +const cl_LF eval_rational_series (uintL N, const cl_rational_series& args, uintC len) +{ + if (args.pv) + if (args.qv) + if (args.bv) + if (args.av) { + var cl_pqab_series series = + { args.pv, args.qv, args.av, args.bv, args.qsv }; + return eval_rational_series(N,series,len); + } else { + var cl_pqb_series series = + { args.pv, args.qv, args.bv, args.qsv }; + return eval_rational_series(N,series,len); + } + else + if (args.av) { + var cl_pqa_series series = + { args.pv, args.qv, args.av, args.qsv }; + return eval_rational_series(N,series,len); + } else { + var cl_pq_series series = + { args.pv, args.qv, args.qsv }; + return eval_rational_series(N,series,len); + } + else + if (args.bv) + if (args.av) { + var cl_pab_series series = + { args.pv, args.av, args.bv }; + return eval_rational_series(N,series,len); + } else { + var cl_pb_series series = + { args.pv, args.bv }; + return eval_rational_series(N,series,len); + } + else + if (args.av) { + var cl_pa_series series = + { args.pv, args.av }; + return eval_rational_series(N,series,len); + } else { + var cl_p_series series = + { args.pv }; + return eval_rational_series(N,series,len); + } + else + if (args.qv) + if (args.bv) + if (args.av) { + var cl_qab_series series = + { args.qv, args.av, args.bv, args.qsv }; + return eval_rational_series(N,series,len); + } else { + var cl_qb_series series = + { args.qv, args.bv, args.qsv }; + return eval_rational_series(N,series,len); + } + else + if (args.av) { + var cl_qa_series series = + { args.qv, args.av, args.qsv }; + return eval_rational_series(N,series,len); + } else { + var cl_q_series series = + { args.qv, args.qsv }; + return eval_rational_series(N,series,len); + } + else + if (args.bv) + if (args.av) { + var cl_ab_series series = + { args.av, args.bv }; + return eval_rational_series(N,series,len); + } else { + var cl_b_series series = + { args.bv }; + return eval_rational_series(N,series,len); + } + else + if (args.av) { + var cl_a_series series = + { args.av }; + return eval_rational_series(N,series,len); + } else { + var cl__series series = + { }; + return eval_rational_series(N,series,len); + } +} +// Bit complexity (if p(n), q(n), a(n), b(n) have length O(log(n))): +// O(log(N)^2*M(N)). diff --git a/src/float/transcendental/cl_LF_ratseries_.cc b/src/float/transcendental/cl_LF_ratseries_.cc new file mode 100644 index 0000000..c8753eb --- /dev/null +++ b/src/float/transcendental/cl_LF_ratseries_.cc @@ -0,0 +1,40 @@ +// eval_rational_series(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_integer.h" +#include "cl_abort.h" +#include "cl_LF.h" + +// Subroutine. +// Evaluates S = sum(N1 <= n < N2, a(n)/b(n) * (p(N1)...p(n))/(q(N1)...q(n))) +// and returns P = p(N1)...p(N2-1), Q = q(N1)...q(N2-1), B = B(N1)...B(N2-1) +// and T = B*Q*S (all integers). On entry N1 < N2. +// P will not be computed if a NULL pointer is passed. + +static inline void eval__series_aux (uintL N1, uintL N2, + const cl__series& args, + cl_I* T) +{ + unused args; + *T = N2-N1; +} + +const cl_LF eval_rational_series (uintL N, const cl__series& args, uintC len) +{ + if (N==0) + return cl_I_to_LF(0,len); + var cl_I T; + eval__series_aux(0,N,args,&T); + return cl_I_to_LF(T,len); +} +// Bit complexity (if p(n), q(n), a(n), b(n) have length O(log(n))): +// O(log(N)^2*M(N)). diff --git a/src/float/transcendental/cl_LF_ratseries_a.cc b/src/float/transcendental/cl_LF_ratseries_a.cc new file mode 100644 index 0000000..3e7bcf3 --- /dev/null +++ b/src/float/transcendental/cl_LF_ratseries_a.cc @@ -0,0 +1,76 @@ +// eval_rational_series(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_integer.h" +#include "cl_abort.h" +#include "cl_LF.h" + +// Subroutine. +// Evaluates S = sum(N1 <= n < N2, a(n)/b(n) * (p(N1)...p(n))/(q(N1)...q(n))) +// and returns P = p(N1)...p(N2-1), Q = q(N1)...q(N2-1), B = B(N1)...B(N2-1) +// and T = B*Q*S (all integers). On entry N1 < N2. +// P will not be computed if a NULL pointer is passed. + +static void eval_a_series_aux (uintL N1, uintL N2, + const cl_a_series& args, + cl_I* T) +{ + switch (N2 - N1) { + case 0: + cl_abort(); break; + case 1: + *T = args.av[N1]; + break; + case 2: { + *T = args.av[N1] + + args.av[N1+1]; + break; + } + case 3: { + *T = args.av[N1] + + args.av[N1+1] + + args.av[N1+2]; + break; + } + case 4: { + *T = args.av[N1] + + args.av[N1+1] + + args.av[N1+2] + + args.av[N1+3]; + break; + } + default: { + var uintL Nm = (N1+N2)/2; // midpoint + // Compute left part. + var cl_I LT; + eval_a_series_aux(N1,Nm,args,<); + // Compute right part. + var cl_I RT; + eval_a_series_aux(Nm,N2,args,&RT); + // Put together partial results. + // S = LS + RS, so T = LT + RT. + *T = LT + RT; + break; + } + } +} + +const cl_LF eval_rational_series (uintL N, const cl_a_series& args, uintC len) +{ + if (N==0) + return cl_I_to_LF(0,len); + var cl_I T; + eval_a_series_aux(0,N,args,&T); + return cl_I_to_LF(T,len); +} +// Bit complexity (if p(n), q(n), a(n), b(n) have length O(log(n))): +// O(log(N)^2*M(N)). diff --git a/src/float/transcendental/cl_LF_ratseries_ab.cc b/src/float/transcendental/cl_LF_ratseries_ab.cc new file mode 100644 index 0000000..945ba2e --- /dev/null +++ b/src/float/transcendental/cl_LF_ratseries_ab.cc @@ -0,0 +1,84 @@ +// eval_rational_series(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_integer.h" +#include "cl_abort.h" +#include "cl_LF.h" + +// Subroutine. +// Evaluates S = sum(N1 <= n < N2, a(n)/b(n) * (p(N1)...p(n))/(q(N1)...q(n))) +// and returns P = p(N1)...p(N2-1), Q = q(N1)...q(N2-1), B = B(N1)...B(N2-1) +// and T = B*Q*S (all integers). On entry N1 < N2. +// P will not be computed if a NULL pointer is passed. + +static void eval_ab_series_aux (uintL N1, uintL N2, + const cl_ab_series& args, + cl_I* B, cl_I* T) +{ + switch (N2 - N1) { + case 0: + cl_abort(); break; + case 1: + *B = args.bv[N1]; + *T = args.av[N1]; + break; + case 2: { + *B = args.bv[N1] * args.bv[N1+1]; + *T = args.bv[N1+1] * args.av[N1] + + args.bv[N1] * args.av[N1+1]; + break; + } + case 3: { + var cl_I b12 = args.bv[N1+1] * args.bv[N1+2]; + *B = args.bv[N1] * b12; + *T = b12 * args.av[N1] + + args.bv[N1] * (args.bv[N1+2] * args.av[N1+1] + + args.bv[N1+1] * args.av[N1+2]); + break; + } + case 4: { + var cl_I b01 = args.bv[N1] * args.bv[N1+1]; + var cl_I b23 = args.bv[N1+2] * args.bv[N1+3]; + *B = b01 * b23; + *T = b23 * (args.bv[N1+1] * args.av[N1] + + args.bv[N1] * args.av[N1+1]) + + b01 * (args.bv[N1+3] * args.av[N1+2] + + args.bv[N1+2] * args.av[N1+3]); + break; + } + default: { + var uintL Nm = (N1+N2)/2; // midpoint + // Compute left part. + var cl_I LB, LT; + eval_ab_series_aux(N1,Nm,args,&LB,<); + // Compute right part. + var cl_I RB, RT; + eval_ab_series_aux(Nm,N2,args,&RB,&RT); + // Put together partial results. + *B = LB*RB; + // S = LS + RS, so T = RB*LT + LB*RT. + *T = RB*LT + LB*RT; + break; + } + } +} + +const cl_LF eval_rational_series (uintL N, const cl_ab_series& args, uintC len) +{ + if (N==0) + return cl_I_to_LF(0,len); + var cl_I B, T; + eval_ab_series_aux(0,N,args,&B,&T); + return cl_I_to_LF(T,len) / cl_I_to_LF(B,len); +} +// Bit complexity (if p(n), q(n), a(n), b(n) have length O(log(n))): +// O(log(N)^2*M(N)). diff --git a/src/float/transcendental/cl_LF_ratseries_b.cc b/src/float/transcendental/cl_LF_ratseries_b.cc new file mode 100644 index 0000000..4fc409b --- /dev/null +++ b/src/float/transcendental/cl_LF_ratseries_b.cc @@ -0,0 +1,84 @@ +// eval_rational_series(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_integer.h" +#include "cl_abort.h" +#include "cl_LF.h" + +// Subroutine. +// Evaluates S = sum(N1 <= n < N2, a(n)/b(n) * (p(N1)...p(n))/(q(N1)...q(n))) +// and returns P = p(N1)...p(N2-1), Q = q(N1)...q(N2-1), B = B(N1)...B(N2-1) +// and T = B*Q*S (all integers). On entry N1 < N2. +// P will not be computed if a NULL pointer is passed. + +static void eval_b_series_aux (uintL N1, uintL N2, + const cl_b_series& args, + cl_I* B, cl_I* T) +{ + switch (N2 - N1) { + case 0: + cl_abort(); break; + case 1: + *B = args.bv[N1]; + *T = 1; + break; + case 2: { + *B = args.bv[N1] * args.bv[N1+1]; + *T = args.bv[N1+1] + + args.bv[N1]; + break; + } + case 3: { + var cl_I b12 = args.bv[N1+1] * args.bv[N1+2]; + *B = args.bv[N1] * b12; + *T = b12 + + args.bv[N1] * (args.bv[N1+2] + + args.bv[N1+1]); + break; + } + case 4: { + var cl_I b01 = args.bv[N1] * args.bv[N1+1]; + var cl_I b23 = args.bv[N1+2] * args.bv[N1+3]; + *B = b01 * b23; + *T = b23 * (args.bv[N1+1] + + args.bv[N1]) + + b01 * (args.bv[N1+3] + + args.bv[N1+2]); + break; + } + default: { + var uintL Nm = (N1+N2)/2; // midpoint + // Compute left part. + var cl_I LB, LT; + eval_b_series_aux(N1,Nm,args,&LB,<); + // Compute right part. + var cl_I RB, RT; + eval_b_series_aux(Nm,N2,args,&RB,&RT); + // Put together partial results. + *B = LB*RB; + // S = LS + RS, so T = RB*LT + LB*RT. + *T = RB*LT + LB*RT; + break; + } + } +} + +const cl_LF eval_rational_series (uintL N, const cl_b_series& args, uintC len) +{ + if (N==0) + return cl_I_to_LF(0,len); + var cl_I B, T; + eval_b_series_aux(0,N,args,&B,&T); + return cl_I_to_LF(T,len) / cl_I_to_LF(B,len); +} +// Bit complexity (if p(n), q(n), a(n), b(n) have length O(log(n))): +// O(log(N)^2*M(N)). diff --git a/src/float/transcendental/cl_LF_ratseries_p.cc b/src/float/transcendental/cl_LF_ratseries_p.cc new file mode 100644 index 0000000..95cde10 --- /dev/null +++ b/src/float/transcendental/cl_LF_ratseries_p.cc @@ -0,0 +1,87 @@ +// eval_rational_series(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_integer.h" +#include "cl_abort.h" +#include "cl_LF.h" + +// Subroutine. +// Evaluates S = sum(N1 <= n < N2, a(n)/b(n) * (p(N1)...p(n))/(q(N1)...q(n))) +// and returns P = p(N1)...p(N2-1), Q = q(N1)...q(N2-1), B = B(N1)...B(N2-1) +// and T = B*Q*S (all integers). On entry N1 < N2. +// P will not be computed if a NULL pointer is passed. + +static void eval_p_series_aux (uintL N1, uintL N2, + const cl_p_series& args, + cl_I* P, cl_I* T) +{ + switch (N2 - N1) { + case 0: + cl_abort(); break; + case 1: + if (P) { *P = args.pv[N1]; } + *T = args.pv[N1]; + break; + case 2: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + if (P) { *P = p01; } + *T = args.pv[N1] + + p01; + break; + } + case 3: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + var cl_I p012 = p01 * args.pv[N1+2]; + if (P) { *P = p012; } + *T = args.pv[N1] + + p01 + + p012; + break; + } + case 4: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + var cl_I p012 = p01 * args.pv[N1+2]; + var cl_I p0123 = p012 * args.pv[N1+3]; + if (P) { *P = p0123; } + *T = args.pv[N1] + + p01 + + p012 + + p0123; + break; + } + default: { + var uintL Nm = (N1+N2)/2; // midpoint + // Compute left part. + var cl_I LP, LT; + eval_p_series_aux(N1,Nm,args,&LP,<); + // Compute right part. + var cl_I RP, RT; + eval_p_series_aux(Nm,N2,args,(P?&RP:(cl_I*)0),&RT); + // Put together partial results. + if (P) { *P = LP*RP; } + // S = LS + LP * RS, so T = LT + LP*RT. + *T = LT + LP*RT; + break; + } + } +} + +const cl_LF eval_rational_series (uintL N, const cl_p_series& args, uintC len) +{ + if (N==0) + return cl_I_to_LF(0,len); + var cl_I T; + eval_p_series_aux(0,N,args,NULL,&T); + return cl_I_to_LF(T,len); +} +// Bit complexity (if p(n), q(n), a(n), b(n) have length O(log(n))): +// O(log(N)^2*M(N)). diff --git a/src/float/transcendental/cl_LF_ratseries_pa.cc b/src/float/transcendental/cl_LF_ratseries_pa.cc new file mode 100644 index 0000000..8c4e363 --- /dev/null +++ b/src/float/transcendental/cl_LF_ratseries_pa.cc @@ -0,0 +1,87 @@ +// eval_rational_series(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_integer.h" +#include "cl_abort.h" +#include "cl_LF.h" + +// Subroutine. +// Evaluates S = sum(N1 <= n < N2, a(n)/b(n) * (p(N1)...p(n))/(q(N1)...q(n))) +// and returns P = p(N1)...p(N2-1), Q = q(N1)...q(N2-1), B = B(N1)...B(N2-1) +// and T = B*Q*S (all integers). On entry N1 < N2. +// P will not be computed if a NULL pointer is passed. + +static void eval_pa_series_aux (uintL N1, uintL N2, + const cl_pa_series& args, + cl_I* P, cl_I* T) +{ + switch (N2 - N1) { + case 0: + cl_abort(); break; + case 1: + if (P) { *P = args.pv[N1]; } + *T = args.av[N1] * args.pv[N1]; + break; + case 2: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + if (P) { *P = p01; } + *T = args.av[N1] * args.pv[N1] + + args.av[N1+1] * p01; + break; + } + case 3: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + var cl_I p012 = p01 * args.pv[N1+2]; + if (P) { *P = p012; } + *T = args.av[N1] * args.pv[N1] + + args.av[N1+1] * p01 + + args.av[N1+2] * p012; + break; + } + case 4: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + var cl_I p012 = p01 * args.pv[N1+2]; + var cl_I p0123 = p012 * args.pv[N1+3]; + if (P) { *P = p0123; } + *T = args.av[N1] * args.pv[N1] + + args.av[N1+1] * p01 + + args.av[N1+2] * p012 + + args.av[N1+3] * p0123; + break; + } + default: { + var uintL Nm = (N1+N2)/2; // midpoint + // Compute left part. + var cl_I LP, LT; + eval_pa_series_aux(N1,Nm,args,&LP,<); + // Compute right part. + var cl_I RP, RT; + eval_pa_series_aux(Nm,N2,args,(P?&RP:(cl_I*)0),&RT); + // Put together partial results. + if (P) { *P = LP*RP; } + // S = LS + LP * RS, so T = LT + LP*RT. + *T = LT + LP*RT; + break; + } + } +} + +const cl_LF eval_rational_series (uintL N, const cl_pa_series& args, uintC len) +{ + if (N==0) + return cl_I_to_LF(0,len); + var cl_I T; + eval_pa_series_aux(0,N,args,NULL,&T); + return cl_I_to_LF(T,len); +} +// Bit complexity (if p(n), q(n), a(n), b(n) have length O(log(n))): +// O(log(N)^2*M(N)). diff --git a/src/float/transcendental/cl_LF_ratseries_pab.cc b/src/float/transcendental/cl_LF_ratseries_pab.cc new file mode 100644 index 0000000..03a2bd4 --- /dev/null +++ b/src/float/transcendental/cl_LF_ratseries_pab.cc @@ -0,0 +1,95 @@ +// eval_rational_series(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_integer.h" +#include "cl_abort.h" +#include "cl_LF.h" + +// Subroutine. +// Evaluates S = sum(N1 <= n < N2, a(n)/b(n) * (p(N1)...p(n))/(q(N1)...q(n))) +// and returns P = p(N1)...p(N2-1), Q = q(N1)...q(N2-1), B = B(N1)...B(N2-1) +// and T = B*Q*S (all integers). On entry N1 < N2. +// P will not be computed if a NULL pointer is passed. + +static void eval_pab_series_aux (uintL N1, uintL N2, + const cl_pab_series& args, + cl_I* P, cl_I* B, cl_I* T) +{ + switch (N2 - N1) { + case 0: + cl_abort(); break; + case 1: + if (P) { *P = args.pv[N1]; } + *B = args.bv[N1]; + *T = args.av[N1] * args.pv[N1]; + break; + case 2: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + if (P) { *P = p01; } + *B = args.bv[N1] * args.bv[N1+1]; + *T = args.bv[N1+1] * args.av[N1] * args.pv[N1] + + args.bv[N1] * args.av[N1+1] * p01; + break; + } + case 3: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + var cl_I p012 = p01 * args.pv[N1+2]; + if (P) { *P = p012; } + var cl_I b12 = args.bv[N1+1] * args.bv[N1+2]; + *B = args.bv[N1] * b12; + *T = b12 * args.av[N1] * args.pv[N1] + + args.bv[N1] * (args.bv[N1+2] * args.av[N1+1] * p01 + + args.bv[N1+1] * args.av[N1+2] * p012); + break; + } + case 4: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + var cl_I p012 = p01 * args.pv[N1+2]; + var cl_I p0123 = p012 * args.pv[N1+3]; + if (P) { *P = p0123; } + var cl_I b01 = args.bv[N1] * args.bv[N1+1]; + var cl_I b23 = args.bv[N1+2] * args.bv[N1+3]; + *B = b01 * b23; + *T = b23 * (args.bv[N1+1] * args.av[N1] * args.pv[N1] + + args.bv[N1] * args.av[N1+1] * p01) + + b01 * (args.bv[N1+3] * args.av[N1+2] * p012 + + args.bv[N1+2] * args.av[N1+3] * p0123); + break; + } + default: { + var uintL Nm = (N1+N2)/2; // midpoint + // Compute left part. + var cl_I LP, LB, LT; + eval_pab_series_aux(N1,Nm,args,&LP,&LB,<); + // Compute right part. + var cl_I RP, RB, RT; + eval_pab_series_aux(Nm,N2,args,(P?&RP:(cl_I*)0),&RB,&RT); + // Put together partial results. + if (P) { *P = LP*RP; } + *B = LB*RB; + // S = LS + LP * RS, so T = RB*LT + LB*LP*RT. + *T = RB*LT + LB*LP*RT; + break; + } + } +} + +const cl_LF eval_rational_series (uintL N, const cl_pab_series& args, uintC len) +{ + if (N==0) + return cl_I_to_LF(0,len); + var cl_I B, T; + eval_pab_series_aux(0,N,args,NULL,&B,&T); + return cl_I_to_LF(T,len) / cl_I_to_LF(B,len); +} +// Bit complexity (if p(n), q(n), a(n), b(n) have length O(log(n))): +// O(log(N)^2*M(N)). diff --git a/src/float/transcendental/cl_LF_ratseries_pb.cc b/src/float/transcendental/cl_LF_ratseries_pb.cc new file mode 100644 index 0000000..18d6424 --- /dev/null +++ b/src/float/transcendental/cl_LF_ratseries_pb.cc @@ -0,0 +1,95 @@ +// eval_rational_series(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_integer.h" +#include "cl_abort.h" +#include "cl_LF.h" + +// Subroutine. +// Evaluates S = sum(N1 <= n < N2, a(n)/b(n) * (p(N1)...p(n))/(q(N1)...q(n))) +// and returns P = p(N1)...p(N2-1), Q = q(N1)...q(N2-1), B = B(N1)...B(N2-1) +// and T = B*Q*S (all integers). On entry N1 < N2. +// P will not be computed if a NULL pointer is passed. + +static void eval_pb_series_aux (uintL N1, uintL N2, + const cl_pb_series& args, + cl_I* P, cl_I* B, cl_I* T) +{ + switch (N2 - N1) { + case 0: + cl_abort(); break; + case 1: + if (P) { *P = args.pv[N1]; } + *B = args.bv[N1]; + *T = args.pv[N1]; + break; + case 2: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + if (P) { *P = p01; } + *B = args.bv[N1] * args.bv[N1+1]; + *T = args.bv[N1+1] * args.pv[N1] + + args.bv[N1] * p01; + break; + } + case 3: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + var cl_I p012 = p01 * args.pv[N1+2]; + if (P) { *P = p012; } + var cl_I b12 = args.bv[N1+1] * args.bv[N1+2]; + *B = args.bv[N1] * b12; + *T = b12 * args.pv[N1] + + args.bv[N1] * (args.bv[N1+2] * p01 + + args.bv[N1+1] * p012); + break; + } + case 4: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + var cl_I p012 = p01 * args.pv[N1+2]; + var cl_I p0123 = p012 * args.pv[N1+3]; + if (P) { *P = p0123; } + var cl_I b01 = args.bv[N1] * args.bv[N1+1]; + var cl_I b23 = args.bv[N1+2] * args.bv[N1+3]; + *B = b01 * b23; + *T = b23 * (args.bv[N1+1] * args.pv[N1] + + args.bv[N1] * p01) + + b01 * (args.bv[N1+3] * p012 + + args.bv[N1+2] * p0123); + break; + } + default: { + var uintL Nm = (N1+N2)/2; // midpoint + // Compute left part. + var cl_I LP, LB, LT; + eval_pb_series_aux(N1,Nm,args,&LP,&LB,<); + // Compute right part. + var cl_I RP, RB, RT; + eval_pb_series_aux(Nm,N2,args,(P?&RP:(cl_I*)0),&RB,&RT); + // Put together partial results. + if (P) { *P = LP*RP; } + *B = LB*RB; + // S = LS + LP * RS, so T = RB*LT + LB*LP*RT. + *T = RB*LT + LB*LP*RT; + break; + } + } +} + +const cl_LF eval_rational_series (uintL N, const cl_pb_series& args, uintC len) +{ + if (N==0) + return cl_I_to_LF(0,len); + var cl_I B, T; + eval_pb_series_aux(0,N,args,NULL,&B,&T); + return cl_I_to_LF(T,len) / cl_I_to_LF(B,len); +} +// Bit complexity (if p(n), q(n), a(n), b(n) have length O(log(n))): +// O(log(N)^2*M(N)). diff --git a/src/float/transcendental/cl_LF_ratseries_pq.cc b/src/float/transcendental/cl_LF_ratseries_pq.cc new file mode 100644 index 0000000..dbb9644 --- /dev/null +++ b/src/float/transcendental/cl_LF_ratseries_pq.cc @@ -0,0 +1,188 @@ +// eval_rational_series(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_integer.h" +#include "cl_abort.h" +#include "cl_LF.h" + +// Subroutine. +// Evaluates S = sum(N1 <= n < N2, a(n)/b(n) * (p(N1)...p(n))/(q(N1)...q(n))) +// and returns P = p(N1)...p(N2-1), Q = q(N1)...q(N2-1), B = B(N1)...B(N2-1) +// and T = B*Q*S (all integers). On entry N1 < N2. +// P will not be computed if a NULL pointer is passed. + +static void eval_pq_series_aux (uintL N1, uintL N2, + const cl_pq_series& args, + cl_I* P, cl_I* Q, cl_I* T) +{ + switch (N2 - N1) { + case 0: + cl_abort(); break; + case 1: + if (P) { *P = args.pv[N1]; } + *Q = args.qv[N1]; + *T = args.pv[N1]; + break; + case 2: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + if (P) { *P = p01; } + *Q = args.qv[N1] * args.qv[N1+1]; + *T = args.qv[N1+1] * args.pv[N1] + + p01; + break; + } + case 3: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + var cl_I p012 = p01 * args.pv[N1+2]; + if (P) { *P = p012; } + var cl_I q12 = args.qv[N1+1] * args.qv[N1+2]; + *Q = args.qv[N1] * q12; + *T = q12 * args.pv[N1] + + args.qv[N1+2] * p01 + + p012; + break; + } + case 4: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + var cl_I p012 = p01 * args.pv[N1+2]; + var cl_I p0123 = p012 * args.pv[N1+3]; + if (P) { *P = p0123; } + var cl_I q23 = args.qv[N1+2] * args.qv[N1+3]; + var cl_I q123 = args.qv[N1+1] * q23; + *Q = args.qv[N1] * q123; + *T = q123 * args.pv[N1] + + q23 * p01 + + args.qv[N1+3] * p012 + + p0123; + break; + } + default: { + var uintL Nm = (N1+N2)/2; // midpoint + // Compute left part. + var cl_I LP, LQ, LT; + eval_pq_series_aux(N1,Nm,args,&LP,&LQ,<); + // Compute right part. + var cl_I RP, RQ, RT; + eval_pq_series_aux(Nm,N2,args,(P?&RP:(cl_I*)0),&RQ,&RT); + // Put together partial results. + if (P) { *P = LP*RP; } + *Q = LQ*RQ; + // S = LS + LP/LQ * RS, so T = RQ*LT + LP*RT. + *T = RQ*LT + LP*RT; + break; + } + } +} + +static void eval_pqs_series_aux (uintL N1, uintL N2, + const cl_pq_series& args, + cl_I* P, cl_I* Q, uintL* QS, cl_I* T) +{ + switch (N2 - N1) { + case 0: + cl_abort(); break; + case 1: + if (P) { *P = args.pv[N1]; } + *Q = args.qv[N1]; + *QS = args.qsv[N1]; + *T = args.pv[N1]; + break; + case 2: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + if (P) { *P = p01; } + *Q = args.qv[N1] * args.qv[N1+1]; + *QS = args.qsv[N1] + args.qsv[N1+1]; + *T = ((args.qv[N1+1] * args.pv[N1]) << args.qsv[N1+1]) + + p01; + break; + } + case 3: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + var cl_I p012 = p01 * args.pv[N1+2]; + if (P) { *P = p012; } + var cl_I q12 = args.qv[N1+1] * args.qv[N1+2]; + *Q = args.qv[N1] * q12; + *QS = args.qsv[N1] + args.qsv[N1+1] + args.qsv[N1+2]; + *T = ((q12 * args.pv[N1]) << (args.qsv[N1+1] + args.qsv[N1+2])) + + ((args.qv[N1+2] * p01) << args.qsv[N1+2]) + + p012; + break; + } + case 4: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + var cl_I p012 = p01 * args.pv[N1+2]; + var cl_I p0123 = p012 * args.pv[N1+3]; + if (P) { *P = p0123; } + var cl_I q23 = args.qv[N1+2] * args.qv[N1+3]; + var cl_I q123 = args.qv[N1+1] * q23; + *Q = args.qv[N1] * q123; + *QS = args.qsv[N1] + args.qsv[N1+1] + args.qsv[N1+2] + args.qsv[N1+3]; + *T = ((((((q123 * args.pv[N1]) << args.qsv[N1+1]) + + q23 * p01) << args.qsv[N1+2]) + + args.qv[N1+3] * p012) << args.qsv[N1+3]) + + p0123; + break; + } + default: { + var uintL Nm = (N1+N2)/2; // midpoint + // Compute left part. + var cl_I LP, LQ, LT; + var uintL LQS; + eval_pqs_series_aux(N1,Nm,args,&LP,&LQ,&LQS,<); + // Compute right part. + var cl_I RP, RQ, RT; + var uintL RQS; + eval_pqs_series_aux(Nm,N2,args,(P?&RP:(cl_I*)0),&RQ,&RQS,&RT); + // Put together partial results. + if (P) { *P = LP*RP; } + *Q = LQ*RQ; + *QS = LQS+RQS; + // S = LS + LP/LQ * RS, so T = RQ*LT + LP*RT. + *T = ((RQ*LT) << RQS) + LP*RT; + break; + } + } +} + +const cl_LF eval_rational_series (uintL N, const cl_pq_series& args, uintC len) +{ + if (N==0) + return cl_I_to_LF(0,len); + var cl_I Q, T; + if (!args.qsv) { + eval_pq_series_aux(0,N,args,NULL,&Q,&T); + return cl_I_to_LF(T,len) / cl_I_to_LF(Q,len); + } else { + // Precomputation of the shift counts: + // Split qv[n] into qv[n]*2^qsv[n]. + { + var cl_I* qp = args.qv; + var uintL* qsp = args.qsv; + for (var uintL n = 0; n < N; n++, qp++, qsp++) { + // Pull out maximal power of 2 out of *qp = args.qv[n]. + var uintL qs = 0; + if (!zerop(*qp)) { + qs = ord2(*qp); + if (qs > 0) + *qp = *qp >> qs; + } + *qsp = qs; + } + } + // Main computation. + var uintL QS; + eval_pqs_series_aux(0,N,args,NULL,&Q,&QS,&T); + return cl_I_to_LF(T,len) / scale_float(cl_I_to_LF(Q,len),QS); + } +} +// Bit complexity (if p(n), q(n), a(n), b(n) have length O(log(n))): +// O(log(N)^2*M(N)). diff --git a/src/float/transcendental/cl_LF_ratseries_pqa.cc b/src/float/transcendental/cl_LF_ratseries_pqa.cc new file mode 100644 index 0000000..36fed64 --- /dev/null +++ b/src/float/transcendental/cl_LF_ratseries_pqa.cc @@ -0,0 +1,188 @@ +// eval_rational_series(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_integer.h" +#include "cl_abort.h" +#include "cl_LF.h" + +// Subroutine. +// Evaluates S = sum(N1 <= n < N2, a(n)/b(n) * (p(N1)...p(n))/(q(N1)...q(n))) +// and returns P = p(N1)...p(N2-1), Q = q(N1)...q(N2-1), B = B(N1)...B(N2-1) +// and T = B*Q*S (all integers). On entry N1 < N2. +// P will not be computed if a NULL pointer is passed. + +static void eval_pqa_series_aux (uintL N1, uintL N2, + const cl_pqa_series& args, + cl_I* P, cl_I* Q, cl_I* T) +{ + switch (N2 - N1) { + case 0: + cl_abort(); break; + case 1: + if (P) { *P = args.pv[N1]; } + *Q = args.qv[N1]; + *T = args.av[N1] * args.pv[N1]; + break; + case 2: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + if (P) { *P = p01; } + *Q = args.qv[N1] * args.qv[N1+1]; + *T = args.qv[N1+1] * args.av[N1] * args.pv[N1] + + args.av[N1+1] * p01; + break; + } + case 3: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + var cl_I p012 = p01 * args.pv[N1+2]; + if (P) { *P = p012; } + var cl_I q12 = args.qv[N1+1] * args.qv[N1+2]; + *Q = args.qv[N1] * q12; + *T = q12 * args.av[N1] * args.pv[N1] + + args.qv[N1+2] * args.av[N1+1] * p01 + + args.av[N1+2] * p012; + break; + } + case 4: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + var cl_I p012 = p01 * args.pv[N1+2]; + var cl_I p0123 = p012 * args.pv[N1+3]; + if (P) { *P = p0123; } + var cl_I q23 = args.qv[N1+2] * args.qv[N1+3]; + var cl_I q123 = args.qv[N1+1] * q23; + *Q = args.qv[N1] * q123; + *T = q123 * args.av[N1] * args.pv[N1] + + q23 * args.av[N1+1] * p01 + + args.qv[N1+3] * args.av[N1+2] * p012 + + args.av[N1+3] * p0123; + break; + } + default: { + var uintL Nm = (N1+N2)/2; // midpoint + // Compute left part. + var cl_I LP, LQ, LT; + eval_pqa_series_aux(N1,Nm,args,&LP,&LQ,<); + // Compute right part. + var cl_I RP, RQ, RT; + eval_pqa_series_aux(Nm,N2,args,(P?&RP:(cl_I*)0),&RQ,&RT); + // Put together partial results. + if (P) { *P = LP*RP; } + *Q = LQ*RQ; + // S = LS + LP/LQ * RS, so T = RQ*LT + LP*RT. + *T = RQ*LT + LP*RT; + break; + } + } +} + +static void eval_pqsa_series_aux (uintL N1, uintL N2, + const cl_pqa_series& args, + cl_I* P, cl_I* Q, uintL* QS, cl_I* T) +{ + switch (N2 - N1) { + case 0: + cl_abort(); break; + case 1: + if (P) { *P = args.pv[N1]; } + *Q = args.qv[N1]; + *QS = args.qsv[N1]; + *T = args.av[N1] * args.pv[N1]; + break; + case 2: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + if (P) { *P = p01; } + *Q = args.qv[N1] * args.qv[N1+1]; + *QS = args.qsv[N1] + args.qsv[N1+1]; + *T = ((args.qv[N1+1] * args.av[N1] * args.pv[N1]) << args.qsv[N1+1]) + + args.av[N1+1] * p01; + break; + } + case 3: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + var cl_I p012 = p01 * args.pv[N1+2]; + if (P) { *P = p012; } + var cl_I q12 = args.qv[N1+1] * args.qv[N1+2]; + *Q = args.qv[N1] * q12; + *QS = args.qsv[N1] + args.qsv[N1+1] + args.qsv[N1+2]; + *T = ((q12 * args.av[N1] * args.pv[N1]) << (args.qsv[N1+1] + args.qsv[N1+2])) + + ((args.qv[N1+2] * args.av[N1+1] * p01) << args.qsv[N1+2]) + + args.av[N1+2] * p012; + break; + } + case 4: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + var cl_I p012 = p01 * args.pv[N1+2]; + var cl_I p0123 = p012 * args.pv[N1+3]; + if (P) { *P = p0123; } + var cl_I q23 = args.qv[N1+2] * args.qv[N1+3]; + var cl_I q123 = args.qv[N1+1] * q23; + *Q = args.qv[N1] * q123; + *QS = args.qsv[N1] + args.qsv[N1+1] + args.qsv[N1+2] + args.qsv[N1+3]; + *T = ((((((q123 * args.av[N1] * args.pv[N1]) << args.qsv[N1+1]) + + q23 * args.av[N1+1] * p01) << args.qsv[N1+2]) + + args.qv[N1+3] * args.av[N1+2] * p012) << args.qsv[N1+3]) + + args.av[N1+3] * p0123; + break; + } + default: { + var uintL Nm = (N1+N2)/2; // midpoint + // Compute left part. + var cl_I LP, LQ, LT; + var uintL LQS; + eval_pqsa_series_aux(N1,Nm,args,&LP,&LQ,&LQS,<); + // Compute right part. + var cl_I RP, RQ, RT; + var uintL RQS; + eval_pqsa_series_aux(Nm,N2,args,(P?&RP:(cl_I*)0),&RQ,&RQS,&RT); + // Put together partial results. + if (P) { *P = LP*RP; } + *Q = LQ*RQ; + *QS = LQS+RQS; + // S = LS + LP/LQ * RS, so T = RQ*LT + LP*RT. + *T = ((RQ*LT) << RQS) + LP*RT; + break; + } + } +} + +const cl_LF eval_rational_series (uintL N, const cl_pqa_series& args, uintC len) +{ + if (N==0) + return cl_I_to_LF(0,len); + var cl_I Q, T; + if (!args.qsv) { + eval_pqa_series_aux(0,N,args,NULL,&Q,&T); + return cl_I_to_LF(T,len) / cl_I_to_LF(Q,len); + } else { + // Precomputation of the shift counts: + // Split qv[n] into qv[n]*2^qsv[n]. + { + var cl_I* qp = args.qv; + var uintL* qsp = args.qsv; + for (var uintL n = 0; n < N; n++, qp++, qsp++) { + // Pull out maximal power of 2 out of *qp = args.qv[n]. + var uintL qs = 0; + if (!zerop(*qp)) { + qs = ord2(*qp); + if (qs > 0) + *qp = *qp >> qs; + } + *qsp = qs; + } + } + // Main computation. + var uintL QS; + eval_pqsa_series_aux(0,N,args,NULL,&Q,&QS,&T); + return cl_I_to_LF(T,len) / scale_float(cl_I_to_LF(Q,len),QS); + } +} +// Bit complexity (if p(n), q(n), a(n), b(n) have length O(log(n))): +// O(log(N)^2*M(N)). diff --git a/src/float/transcendental/cl_LF_ratseries_pqab.cc b/src/float/transcendental/cl_LF_ratseries_pqab.cc new file mode 100644 index 0000000..fdd2602 --- /dev/null +++ b/src/float/transcendental/cl_LF_ratseries_pqab.cc @@ -0,0 +1,204 @@ +// eval_rational_series(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_integer.h" +#include "cl_abort.h" +#include "cl_LF.h" + +// Subroutine. +// Evaluates S = sum(N1 <= n < N2, a(n)/b(n) * (p(N1)...p(n))/(q(N1)...q(n))) +// and returns P = p(N1)...p(N2-1), Q = q(N1)...q(N2-1), B = B(N1)...B(N2-1) +// and T = B*Q*S (all integers). On entry N1 < N2. +// P will not be computed if a NULL pointer is passed. + +static void eval_pqab_series_aux (uintL N1, uintL N2, + const cl_pqab_series& args, + cl_I* P, cl_I* Q, cl_I* B, cl_I* T) +{ + switch (N2 - N1) { + case 0: + cl_abort(); break; + case 1: + if (P) { *P = args.pv[N1]; } + *Q = args.qv[N1]; + *B = args.bv[N1]; + *T = args.av[N1] * args.pv[N1]; + break; + case 2: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + if (P) { *P = p01; } + *Q = args.qv[N1] * args.qv[N1+1]; + *B = args.bv[N1] * args.bv[N1+1]; + *T = args.bv[N1+1] * args.qv[N1+1] * args.av[N1] * args.pv[N1] + + args.bv[N1] * args.av[N1+1] * p01; + break; + } + case 3: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + var cl_I p012 = p01 * args.pv[N1+2]; + if (P) { *P = p012; } + var cl_I q12 = args.qv[N1+1] * args.qv[N1+2]; + *Q = args.qv[N1] * q12; + var cl_I b12 = args.bv[N1+1] * args.bv[N1+2]; + *B = args.bv[N1] * b12; + *T = b12 * q12 * args.av[N1] * args.pv[N1] + + args.bv[N1] * (args.bv[N1+2] * args.qv[N1+2] * args.av[N1+1] * p01 + + args.bv[N1+1] * args.av[N1+2] * p012); + break; + } + case 4: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + var cl_I p012 = p01 * args.pv[N1+2]; + var cl_I p0123 = p012 * args.pv[N1+3]; + if (P) { *P = p0123; } + var cl_I q23 = args.qv[N1+2] * args.qv[N1+3]; + var cl_I q123 = args.qv[N1+1] * q23; + *Q = args.qv[N1] * q123; + var cl_I b01 = args.bv[N1] * args.bv[N1+1]; + var cl_I b23 = args.bv[N1+2] * args.bv[N1+3]; + *B = b01 * b23; + *T = b23 * (args.bv[N1+1] * q123 * args.av[N1] * args.pv[N1] + + args.bv[N1] * q23 * args.av[N1+1] * p01) + + b01 * (args.bv[N1+3] * args.qv[N1+3] * args.av[N1+2] * p012 + + args.bv[N1+2] * args.av[N1+3] * p0123); + break; + } + default: { + var uintL Nm = (N1+N2)/2; // midpoint + // Compute left part. + var cl_I LP, LQ, LB, LT; + eval_pqab_series_aux(N1,Nm,args,&LP,&LQ,&LB,<); + // Compute right part. + var cl_I RP, RQ, RB, RT; + eval_pqab_series_aux(Nm,N2,args,(P?&RP:(cl_I*)0),&RQ,&RB,&RT); + // Put together partial results. + if (P) { *P = LP*RP; } + *Q = LQ*RQ; + *B = LB*RB; + // S = LS + LP/LQ * RS, so T = RB*RQ*LT + LB*LP*RT. + *T = RB*RQ*LT + LB*LP*RT; + break; + } + } +} + +static void eval_pqsab_series_aux (uintL N1, uintL N2, + const cl_pqab_series& args, + cl_I* P, cl_I* Q, uintL* QS, cl_I* B, cl_I* T) +{ + switch (N2 - N1) { + case 0: + cl_abort(); break; + case 1: + if (P) { *P = args.pv[N1]; } + *Q = args.qv[N1]; + *QS = args.qsv[N1]; + *B = args.bv[N1]; + *T = args.av[N1] * args.pv[N1]; + break; + case 2: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + if (P) { *P = p01; } + *Q = args.qv[N1] * args.qv[N1+1]; + *QS = args.qsv[N1] + args.qsv[N1+1]; + *B = args.bv[N1] * args.bv[N1+1]; + *T = ((args.bv[N1+1] * args.qv[N1+1] * args.av[N1] * args.pv[N1]) << args.qsv[N1+1]) + + args.bv[N1] * args.av[N1+1] * p01; + break; + } + case 3: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + var cl_I p012 = p01 * args.pv[N1+2]; + if (P) { *P = p012; } + var cl_I q12 = args.qv[N1+1] * args.qv[N1+2]; + *Q = args.qv[N1] * q12; + *QS = args.qsv[N1] + args.qsv[N1+1] + args.qsv[N1+2]; + var cl_I b12 = args.bv[N1+1] * args.bv[N1+2]; + *B = args.bv[N1] * b12; + *T = ((b12 * q12 * args.av[N1] * args.pv[N1]) << (args.qsv[N1+1] + args.qsv[N1+2])) + + args.bv[N1] * (((args.bv[N1+2] * args.qv[N1+2] * args.av[N1+1] * p01) << args.qsv[N1+2]) + + args.bv[N1+1] * args.av[N1+2] * p012); + break; + } + case 4: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + var cl_I p012 = p01 * args.pv[N1+2]; + var cl_I p0123 = p012 * args.pv[N1+3]; + if (P) { *P = p0123; } + var cl_I q23 = args.qv[N1+2] * args.qv[N1+3]; + var cl_I q123 = args.qv[N1+1] * q23; + *Q = args.qv[N1] * q123; + *QS = args.qsv[N1] + args.qsv[N1+1] + args.qsv[N1+2] + args.qsv[N1+3]; + var cl_I b01 = args.bv[N1] * args.bv[N1+1]; + var cl_I b23 = args.bv[N1+2] * args.bv[N1+3]; + *B = b01 * b23; + *T = ((b23 * (((args.bv[N1+1] * q123 * args.av[N1] * args.pv[N1]) << args.qsv[N1+1]) + + args.bv[N1] * q23 * args.av[N1+1] * p01)) << (args.qsv[N1+2] + args.qsv[N1+3])) + + b01 * (((args.bv[N1+3] * args.qv[N1+3] * args.av[N1+2] * p012) << args.qsv[N1+3]) + + args.bv[N1+2] * args.av[N1+3] * p0123); + break; + } + default: { + var uintL Nm = (N1+N2)/2; // midpoint + // Compute left part. + var cl_I LP, LQ, LB, LT; + var uintL LQS; + eval_pqsab_series_aux(N1,Nm,args,&LP,&LQ,&LQS,&LB,<); + // Compute right part. + var cl_I RP, RQ, RB, RT; + var uintL RQS; + eval_pqsab_series_aux(Nm,N2,args,(P?&RP:(cl_I*)0),&RQ,&RQS,&RB,&RT); + // Put together partial results. + if (P) { *P = LP*RP; } + *Q = LQ*RQ; + *QS = LQS+RQS; + *B = LB*RB; + // S = LS + LP/LQ * RS, so T = RB*RQ*LT + LB*LP*RT. + *T = ((RB*RQ*LT) << RQS) + LB*LP*RT; + break; + } + } +} + +const cl_LF eval_rational_series (uintL N, const cl_pqab_series& args, uintC len) +{ + if (N==0) + return cl_I_to_LF(0,len); + var cl_I Q, B, T; + if (!args.qsv) { + eval_pqab_series_aux(0,N,args,NULL,&Q,&B,&T); + return cl_I_to_LF(T,len) / cl_I_to_LF(B*Q,len); + } else { + // Precomputation of the shift counts: + // Split qv[n] into qv[n]*2^qsv[n]. + { + var cl_I* qp = args.qv; + var uintL* qsp = args.qsv; + for (var uintL n = 0; n < N; n++, qp++, qsp++) { + // Pull out maximal power of 2 out of *qp = args.qv[n]. + var uintL qs = 0; + if (!zerop(*qp)) { + qs = ord2(*qp); + if (qs > 0) + *qp = *qp >> qs; + } + *qsp = qs; + } + } + // Main computation. + var uintL QS; + eval_pqsab_series_aux(0,N,args,NULL,&Q,&QS,&B,&T); + return cl_I_to_LF(T,len) / scale_float(cl_I_to_LF(B*Q,len),QS); + } +} +// Bit complexity (if p(n), q(n), a(n), b(n) have length O(log(n))): +// O(log(N)^2*M(N)). diff --git a/src/float/transcendental/cl_LF_ratseries_pqb.cc b/src/float/transcendental/cl_LF_ratseries_pqb.cc new file mode 100644 index 0000000..14d7f67 --- /dev/null +++ b/src/float/transcendental/cl_LF_ratseries_pqb.cc @@ -0,0 +1,204 @@ +// eval_rational_series(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_integer.h" +#include "cl_abort.h" +#include "cl_LF.h" + +// Subroutine. +// Evaluates S = sum(N1 <= n < N2, a(n)/b(n) * (p(N1)...p(n))/(q(N1)...q(n))) +// and returns P = p(N1)...p(N2-1), Q = q(N1)...q(N2-1), B = B(N1)...B(N2-1) +// and T = B*Q*S (all integers). On entry N1 < N2. +// P will not be computed if a NULL pointer is passed. + +static void eval_pqb_series_aux (uintL N1, uintL N2, + const cl_pqb_series& args, + cl_I* P, cl_I* Q, cl_I* B, cl_I* T) +{ + switch (N2 - N1) { + case 0: + cl_abort(); break; + case 1: + if (P) { *P = args.pv[N1]; } + *Q = args.qv[N1]; + *B = args.bv[N1]; + *T = args.pv[N1]; + break; + case 2: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + if (P) { *P = p01; } + *Q = args.qv[N1] * args.qv[N1+1]; + *B = args.bv[N1] * args.bv[N1+1]; + *T = args.bv[N1+1] * args.qv[N1+1] * args.pv[N1] + + args.bv[N1] * p01; + break; + } + case 3: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + var cl_I p012 = p01 * args.pv[N1+2]; + if (P) { *P = p012; } + var cl_I q12 = args.qv[N1+1] * args.qv[N1+2]; + *Q = args.qv[N1] * q12; + var cl_I b12 = args.bv[N1+1] * args.bv[N1+2]; + *B = args.bv[N1] * b12; + *T = b12 * q12 * args.pv[N1] + + args.bv[N1] * (args.bv[N1+2] * args.qv[N1+2] * p01 + + args.bv[N1+1] * p012); + break; + } + case 4: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + var cl_I p012 = p01 * args.pv[N1+2]; + var cl_I p0123 = p012 * args.pv[N1+3]; + if (P) { *P = p0123; } + var cl_I q23 = args.qv[N1+2] * args.qv[N1+3]; + var cl_I q123 = args.qv[N1+1] * q23; + *Q = args.qv[N1] * q123; + var cl_I b01 = args.bv[N1] * args.bv[N1+1]; + var cl_I b23 = args.bv[N1+2] * args.bv[N1+3]; + *B = b01 * b23; + *T = b23 * (args.bv[N1+1] * q123 * args.pv[N1] + + args.bv[N1] * q23 * p01) + + b01 * (args.bv[N1+3] * args.qv[N1+3] * p012 + + args.bv[N1+2] * p0123); + break; + } + default: { + var uintL Nm = (N1+N2)/2; // midpoint + // Compute left part. + var cl_I LP, LQ, LB, LT; + eval_pqb_series_aux(N1,Nm,args,&LP,&LQ,&LB,<); + // Compute right part. + var cl_I RP, RQ, RB, RT; + eval_pqb_series_aux(Nm,N2,args,(P?&RP:(cl_I*)0),&RQ,&RB,&RT); + // Put together partial results. + if (P) { *P = LP*RP; } + *Q = LQ*RQ; + *B = LB*RB; + // S = LS + LP/LQ * RS, so T = RB*RQ*LT + LB*LP*RT. + *T = RB*RQ*LT + LB*LP*RT; + break; + } + } +} + +static void eval_pqsb_series_aux (uintL N1, uintL N2, + const cl_pqb_series& args, + cl_I* P, cl_I* Q, uintL* QS, cl_I* B, cl_I* T) +{ + switch (N2 - N1) { + case 0: + cl_abort(); break; + case 1: + if (P) { *P = args.pv[N1]; } + *Q = args.qv[N1]; + *QS = args.qsv[N1]; + *B = args.bv[N1]; + *T = args.pv[N1]; + break; + case 2: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + if (P) { *P = p01; } + *Q = args.qv[N1] * args.qv[N1+1]; + *QS = args.qsv[N1] + args.qsv[N1+1]; + *B = args.bv[N1] * args.bv[N1+1]; + *T = ((args.bv[N1+1] * args.qv[N1+1] * args.pv[N1]) << args.qsv[N1+1]) + + args.bv[N1] * p01; + break; + } + case 3: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + var cl_I p012 = p01 * args.pv[N1+2]; + if (P) { *P = p012; } + var cl_I q12 = args.qv[N1+1] * args.qv[N1+2]; + *Q = args.qv[N1] * q12; + *QS = args.qsv[N1] + args.qsv[N1+1] + args.qsv[N1+2]; + var cl_I b12 = args.bv[N1+1] * args.bv[N1+2]; + *B = args.bv[N1] * b12; + *T = ((b12 * q12 * args.pv[N1]) << (args.qsv[N1+1] + args.qsv[N1+2])) + + args.bv[N1] * (((args.bv[N1+2] * args.qv[N1+2] * p01) << args.qsv[N1+2]) + + args.bv[N1+1] * p012); + break; + } + case 4: { + var cl_I p01 = args.pv[N1] * args.pv[N1+1]; + var cl_I p012 = p01 * args.pv[N1+2]; + var cl_I p0123 = p012 * args.pv[N1+3]; + if (P) { *P = p0123; } + var cl_I q23 = args.qv[N1+2] * args.qv[N1+3]; + var cl_I q123 = args.qv[N1+1] * q23; + *Q = args.qv[N1] * q123; + *QS = args.qsv[N1] + args.qsv[N1+1] + args.qsv[N1+2] + args.qsv[N1+3]; + var cl_I b01 = args.bv[N1] * args.bv[N1+1]; + var cl_I b23 = args.bv[N1+2] * args.bv[N1+3]; + *B = b01 * b23; + *T = ((b23 * (((args.bv[N1+1] * q123 * args.pv[N1]) << args.qsv[N1+1]) + + args.bv[N1] * q23 * p01)) << (args.qsv[N1+2] + args.qsv[N1+3])) + + b01 * (((args.bv[N1+3] * args.qv[N1+3] * p012) << args.qsv[N1+3]) + + args.bv[N1+2] * p0123); + break; + } + default: { + var uintL Nm = (N1+N2)/2; // midpoint + // Compute left part. + var cl_I LP, LQ, LB, LT; + var uintL LQS; + eval_pqsb_series_aux(N1,Nm,args,&LP,&LQ,&LQS,&LB,<); + // Compute right part. + var cl_I RP, RQ, RB, RT; + var uintL RQS; + eval_pqsb_series_aux(Nm,N2,args,(P?&RP:(cl_I*)0),&RQ,&RQS,&RB,&RT); + // Put together partial results. + if (P) { *P = LP*RP; } + *Q = LQ*RQ; + *QS = LQS+RQS; + *B = LB*RB; + // S = LS + LP/LQ * RS, so T = RB*RQ*LT + LB*LP*RT. + *T = ((RB*RQ*LT) << RQS) + LB*LP*RT; + break; + } + } +} + +const cl_LF eval_rational_series (uintL N, const cl_pqb_series& args, uintC len) +{ + if (N==0) + return cl_I_to_LF(0,len); + var cl_I Q, B, T; + if (!args.qsv) { + eval_pqb_series_aux(0,N,args,NULL,&Q,&B,&T); + return cl_I_to_LF(T,len) / cl_I_to_LF(B*Q,len); + } else { + // Precomputation of the shift counts: + // Split qv[n] into qv[n]*2^qsv[n]. + { + var cl_I* qp = args.qv; + var uintL* qsp = args.qsv; + for (var uintL n = 0; n < N; n++, qp++, qsp++) { + // Pull out maximal power of 2 out of *qp = args.qv[n]. + var uintL qs = 0; + if (!zerop(*qp)) { + qs = ord2(*qp); + if (qs > 0) + *qp = *qp >> qs; + } + *qsp = qs; + } + } + // Main computation. + var uintL QS; + eval_pqsb_series_aux(0,N,args,NULL,&Q,&QS,&B,&T); + return cl_I_to_LF(T,len) / scale_float(cl_I_to_LF(B*Q,len),QS); + } +} +// Bit complexity (if p(n), q(n), a(n), b(n) have length O(log(n))): +// O(log(N)^2*M(N)). diff --git a/src/float/transcendental/cl_LF_ratseries_q.cc b/src/float/transcendental/cl_LF_ratseries_q.cc new file mode 100644 index 0000000..a2e8f17 --- /dev/null +++ b/src/float/transcendental/cl_LF_ratseries_q.cc @@ -0,0 +1,84 @@ +// eval_rational_series(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_integer.h" +#include "cl_abort.h" +#include "cl_LF.h" + +// Subroutine. +// Evaluates S = sum(N1 <= n < N2, a(n)/b(n) * (p(N1)...p(n))/(q(N1)...q(n))) +// and returns P = p(N1)...p(N2-1), Q = q(N1)...q(N2-1), B = B(N1)...B(N2-1) +// and T = B*Q*S (all integers). On entry N1 < N2. +// P will not be computed if a NULL pointer is passed. + +static void eval_q_series_aux (uintL N1, uintL N2, + const cl_q_series& args, + cl_I* Q, cl_I* T) +{ + switch (N2 - N1) { + case 0: + cl_abort(); break; + case 1: + *Q = args.qv[N1]; + *T = 1; + break; + case 2: { + *Q = args.qv[N1] * args.qv[N1+1]; + *T = args.qv[N1+1] + + 1; + break; + } + case 3: { + var cl_I q12 = args.qv[N1+1] * args.qv[N1+2]; + *Q = args.qv[N1] * q12; + *T = q12 + + args.qv[N1+2] + + 1; + break; + } + case 4: { + var cl_I q23 = args.qv[N1+2] * args.qv[N1+3]; + var cl_I q123 = args.qv[N1+1] * q23; + *Q = args.qv[N1] * q123; + *T = q123 + + q23 + + args.qv[N1+3] + + 1; + break; + } + default: { + var uintL Nm = (N1+N2)/2; // midpoint + // Compute left part. + var cl_I LQ, LT; + eval_q_series_aux(N1,Nm,args,&LQ,<); + // Compute right part. + var cl_I RQ, RT; + eval_q_series_aux(Nm,N2,args,&RQ,&RT); + // Put together partial results. + *Q = LQ*RQ; + // S = LS + 1/LQ * RS, so T = RQ*LT + RT. + *T = RQ*LT + RT; + break; + } + } +} + +const cl_LF eval_rational_series (uintL N, const cl_q_series& args, uintC len) +{ + if (N==0) + return cl_I_to_LF(0,len); + var cl_I Q, T; + eval_q_series_aux(0,N,args,&Q,&T); + return cl_I_to_LF(T,len) / cl_I_to_LF(Q,len); +} +// Bit complexity (if p(n), q(n), a(n), b(n) have length O(log(n))): +// O(log(N)^2*M(N)). diff --git a/src/float/transcendental/cl_LF_ratseries_qa.cc b/src/float/transcendental/cl_LF_ratseries_qa.cc new file mode 100644 index 0000000..b98e8bb --- /dev/null +++ b/src/float/transcendental/cl_LF_ratseries_qa.cc @@ -0,0 +1,84 @@ +// eval_rational_series(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_integer.h" +#include "cl_abort.h" +#include "cl_LF.h" + +// Subroutine. +// Evaluates S = sum(N1 <= n < N2, a(n)/b(n) * (p(N1)...p(n))/(q(N1)...q(n))) +// and returns P = p(N1)...p(N2-1), Q = q(N1)...q(N2-1), B = B(N1)...B(N2-1) +// and T = B*Q*S (all integers). On entry N1 < N2. +// P will not be computed if a NULL pointer is passed. + +static void eval_qa_series_aux (uintL N1, uintL N2, + const cl_qa_series& args, + cl_I* Q, cl_I* T) +{ + switch (N2 - N1) { + case 0: + cl_abort(); break; + case 1: + *Q = args.qv[N1]; + *T = args.av[N1]; + break; + case 2: { + *Q = args.qv[N1] * args.qv[N1+1]; + *T = args.qv[N1+1] * args.av[N1] + + args.av[N1+1]; + break; + } + case 3: { + var cl_I q12 = args.qv[N1+1] * args.qv[N1+2]; + *Q = args.qv[N1] * q12; + *T = q12 * args.av[N1] + + args.qv[N1+2] * args.av[N1+1] + + args.av[N1+2]; + break; + } + case 4: { + var cl_I q23 = args.qv[N1+2] * args.qv[N1+3]; + var cl_I q123 = args.qv[N1+1] * q23; + *Q = args.qv[N1] * q123; + *T = q123 * args.av[N1] + + q23 * args.av[N1+1] + + args.qv[N1+3] * args.av[N1+2] + + args.av[N1+3]; + break; + } + default: { + var uintL Nm = (N1+N2)/2; // midpoint + // Compute left part. + var cl_I LQ, LT; + eval_qa_series_aux(N1,Nm,args,&LQ,<); + // Compute right part. + var cl_I RQ, RT; + eval_qa_series_aux(Nm,N2,args,&RQ,&RT); + // Put together partial results. + *Q = LQ*RQ; + // S = LS + 1/LQ * RS, so T = RQ*LT + RT. + *T = RQ*LT + RT; + break; + } + } +} + +const cl_LF eval_rational_series (uintL N, const cl_qa_series& args, uintC len) +{ + if (N==0) + return cl_I_to_LF(0,len); + var cl_I Q, T; + eval_qa_series_aux(0,N,args,&Q,&T); + return cl_I_to_LF(T,len) / cl_I_to_LF(Q,len); +} +// Bit complexity (if p(n), q(n), a(n), b(n) have length O(log(n))): +// O(log(N)^2*M(N)). diff --git a/src/float/transcendental/cl_LF_ratseries_qab.cc b/src/float/transcendental/cl_LF_ratseries_qab.cc new file mode 100644 index 0000000..e862ac5 --- /dev/null +++ b/src/float/transcendental/cl_LF_ratseries_qab.cc @@ -0,0 +1,92 @@ +// eval_rational_series(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_integer.h" +#include "cl_abort.h" +#include "cl_LF.h" + +// Subroutine. +// Evaluates S = sum(N1 <= n < N2, a(n)/b(n) * (p(N1)...p(n))/(q(N1)...q(n))) +// and returns P = p(N1)...p(N2-1), Q = q(N1)...q(N2-1), B = B(N1)...B(N2-1) +// and T = B*Q*S (all integers). On entry N1 < N2. +// P will not be computed if a NULL pointer is passed. + +static void eval_qab_series_aux (uintL N1, uintL N2, + const cl_qab_series& args, + cl_I* Q, cl_I* B, cl_I* T) +{ + switch (N2 - N1) { + case 0: + cl_abort(); break; + case 1: + *Q = args.qv[N1]; + *B = args.bv[N1]; + *T = args.av[N1]; + break; + case 2: { + *Q = args.qv[N1] * args.qv[N1+1]; + *B = args.bv[N1] * args.bv[N1+1]; + *T = args.bv[N1+1] * args.qv[N1+1] * args.av[N1] + + args.bv[N1] * args.av[N1+1]; + break; + } + case 3: { + var cl_I q12 = args.qv[N1+1] * args.qv[N1+2]; + *Q = args.qv[N1] * q12; + var cl_I b12 = args.bv[N1+1] * args.bv[N1+2]; + *B = args.bv[N1] * b12; + *T = b12 * q12 * args.av[N1] + + args.bv[N1] * (args.bv[N1+2] * args.qv[N1+2] * args.av[N1+1] + + args.bv[N1+1] * args.av[N1+2]); + break; + } + case 4: { + var cl_I q23 = args.qv[N1+2] * args.qv[N1+3]; + var cl_I q123 = args.qv[N1+1] * q23; + *Q = args.qv[N1] * q123; + var cl_I b01 = args.bv[N1] * args.bv[N1+1]; + var cl_I b23 = args.bv[N1+2] * args.bv[N1+3]; + *B = b01 * b23; + *T = b23 * (args.bv[N1+1] * q123 * args.av[N1] + + args.bv[N1] * q23 * args.av[N1+1]) + + b01 * (args.bv[N1+3] * args.qv[N1+3] * args.av[N1+2] + + args.bv[N1+2] * args.av[N1+3]); + break; + } + default: { + var uintL Nm = (N1+N2)/2; // midpoint + // Compute left part. + var cl_I LQ, LB, LT; + eval_qab_series_aux(N1,Nm,args,&LQ,&LB,<); + // Compute right part. + var cl_I RQ, RB, RT; + eval_qab_series_aux(Nm,N2,args,&RQ,&RB,&RT); + // Put together partial results. + *Q = LQ*RQ; + *B = LB*RB; + // S = LS + 1/LQ * RS, so T = RB*RQ*LT + LB*RT. + *T = RB*RQ*LT + LB*RT; + break; + } + } +} + +const cl_LF eval_rational_series (uintL N, const cl_qab_series& args, uintC len) +{ + if (N==0) + return cl_I_to_LF(0,len); + var cl_I Q, B, T; + eval_qab_series_aux(0,N,args,&Q,&B,&T); + return cl_I_to_LF(T,len) / cl_I_to_LF(B*Q,len); +} +// Bit complexity (if p(n), q(n), a(n), b(n) have length O(log(n))): +// O(log(N)^2*M(N)). diff --git a/src/float/transcendental/cl_LF_ratseries_qb.cc b/src/float/transcendental/cl_LF_ratseries_qb.cc new file mode 100644 index 0000000..37b32c4 --- /dev/null +++ b/src/float/transcendental/cl_LF_ratseries_qb.cc @@ -0,0 +1,92 @@ +// eval_rational_series(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_integer.h" +#include "cl_abort.h" +#include "cl_LF.h" + +// Subroutine. +// Evaluates S = sum(N1 <= n < N2, a(n)/b(n) * (p(N1)...p(n))/(q(N1)...q(n))) +// and returns P = p(N1)...p(N2-1), Q = q(N1)...q(N2-1), B = B(N1)...B(N2-1) +// and T = B*Q*S (all integers). On entry N1 < N2. +// P will not be computed if a NULL pointer is passed. + +static void eval_qb_series_aux (uintL N1, uintL N2, + const cl_qb_series& args, + cl_I* Q, cl_I* B, cl_I* T) +{ + switch (N2 - N1) { + case 0: + cl_abort(); break; + case 1: + *Q = args.qv[N1]; + *B = args.bv[N1]; + *T = 1; + break; + case 2: { + *Q = args.qv[N1] * args.qv[N1+1]; + *B = args.bv[N1] * args.bv[N1+1]; + *T = args.bv[N1+1] * args.qv[N1+1] + + args.bv[N1]; + break; + } + case 3: { + var cl_I q12 = args.qv[N1+1] * args.qv[N1+2]; + *Q = args.qv[N1] * q12; + var cl_I b12 = args.bv[N1+1] * args.bv[N1+2]; + *B = args.bv[N1] * b12; + *T = b12 * q12 + + args.bv[N1] * (args.bv[N1+2] * args.qv[N1+2] + + args.bv[N1+1]); + break; + } + case 4: { + var cl_I q23 = args.qv[N1+2] * args.qv[N1+3]; + var cl_I q123 = args.qv[N1+1] * q23; + *Q = args.qv[N1] * q123; + var cl_I b01 = args.bv[N1] * args.bv[N1+1]; + var cl_I b23 = args.bv[N1+2] * args.bv[N1+3]; + *B = b01 * b23; + *T = b23 * (args.bv[N1+1] * q123 + + args.bv[N1] * q23) + + b01 * (args.bv[N1+3] * args.qv[N1+3] + + args.bv[N1+2]); + break; + } + default: { + var uintL Nm = (N1+N2)/2; // midpoint + // Compute left part. + var cl_I LQ, LB, LT; + eval_qb_series_aux(N1,Nm,args,&LQ,&LB,<); + // Compute right part. + var cl_I RQ, RB, RT; + eval_qb_series_aux(Nm,N2,args,&RQ,&RB,&RT); + // Put together partial results. + *Q = LQ*RQ; + *B = LB*RB; + // S = LS + 1/LQ * RS, so T = RB*RQ*LT + LB*RT. + *T = RB*RQ*LT + LB*RT; + break; + } + } +} + +const cl_LF eval_rational_series (uintL N, const cl_qb_series& args, uintC len) +{ + if (N==0) + return cl_I_to_LF(0,len); + var cl_I Q, B, T; + eval_qb_series_aux(0,N,args,&Q,&B,&T); + return cl_I_to_LF(T,len) / cl_I_to_LF(B*Q,len); +} +// Bit complexity (if p(n), q(n), a(n), b(n) have length O(log(n))): +// O(log(N)^2*M(N)). diff --git a/src/float/transcendental/cl_LF_ratseries_stream_pq.cc b/src/float/transcendental/cl_LF_ratseries_stream_pq.cc new file mode 100644 index 0000000..a922fce --- /dev/null +++ b/src/float/transcendental/cl_LF_ratseries_stream_pq.cc @@ -0,0 +1,98 @@ +// eval_rational_series(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_integer.h" +#include "cl_abort.h" +#include "cl_LF.h" + +static void eval_pq_series_aux (uintL N1, uintL N2, + cl_pq_series_stream& args, + cl_I* P, cl_I* Q, cl_I* T) +{ + switch (N2 - N1) { + case 0: + cl_abort(); break; + case 1: { + var cl_pq_series_term v0 = args.next(); // [N1] + if (P) { *P = v0.p; } + *Q = v0.q; + *T = v0.p; + break; + } + case 2: { + var cl_pq_series_term v0 = args.next(); // [N1] + var cl_pq_series_term v1 = args.next(); // [N1+1] + var cl_I p01 = v0.p * v1.p; + if (P) { *P = p01; } + *Q = v0.q * v1.q; + *T = v1.q * v0.p + + p01; + break; + } + case 3: { + var cl_pq_series_term v0 = args.next(); // [N1] + var cl_pq_series_term v1 = args.next(); // [N1+1] + var cl_pq_series_term v2 = args.next(); // [N1+2] + var cl_I p01 = v0.p * v1.p; + var cl_I p012 = p01 * v2.p; + if (P) { *P = p012; } + var cl_I q12 = v1.q * v2.q; + *Q = v0.q * q12; + *T = q12 * v0.p + + v2.q * p01 + + p012; + break; + } + case 4: { + var cl_pq_series_term v0 = args.next(); // [N1] + var cl_pq_series_term v1 = args.next(); // [N1+1] + var cl_pq_series_term v2 = args.next(); // [N1+2] + var cl_pq_series_term v3 = args.next(); // [N1+3] + var cl_I p01 = v0.p * v1.p; + var cl_I p012 = p01 * v2.p; + var cl_I p0123 = p012 * v3.p; + if (P) { *P = p0123; } + var cl_I q23 = v2.q * v3.q; + var cl_I q123 = v1.q * q23; + *Q = v0.q * q123; + *T = q123 * v0.p + + q23 * p01 + + v3.q * p012 + + p0123; + break; + } + default: { + var uintL Nm = (N1+N2)/2; // midpoint + // Compute left part. + var cl_I LP, LQ, LT; + eval_pq_series_aux(N1,Nm,args,&LP,&LQ,<); + // Compute right part. + var cl_I RP, RQ, RT; + eval_pq_series_aux(Nm,N2,args,(P?&RP:(cl_I*)0),&RQ,&RT); + // Put together partial results. + if (P) { *P = LP*RP; } + *Q = LQ*RQ; + // S = LS + LP/LQ * RS, so T = RQ*LT + LP*RT. + *T = RQ*LT + LP*RT; + break; + } + } +} + +const cl_LF eval_rational_series (uintL N, cl_pq_series_stream& args, uintC len) +{ + if (N==0) + return cl_I_to_LF(0,len); + var cl_I Q, T; + eval_pq_series_aux(0,N,args,NULL,&Q,&T); + return cl_I_to_LF(T,len) / cl_I_to_LF(Q,len); +} diff --git a/src/float/transcendental/cl_LF_ratseries_stream_pqa.cc b/src/float/transcendental/cl_LF_ratseries_stream_pqa.cc new file mode 100644 index 0000000..b76beb0 --- /dev/null +++ b/src/float/transcendental/cl_LF_ratseries_stream_pqa.cc @@ -0,0 +1,98 @@ +// eval_rational_series(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_integer.h" +#include "cl_abort.h" +#include "cl_LF.h" + +static void eval_pqa_series_aux (uintL N1, uintL N2, + cl_pqa_series_stream& args, + cl_I* P, cl_I* Q, cl_I* T) +{ + switch (N2 - N1) { + case 0: + cl_abort(); break; + case 1: { + var cl_pqa_series_term v0 = args.next(); // [N1] + if (P) { *P = v0.p; } + *Q = v0.q; + *T = v0.a * v0.p; + break; + } + case 2: { + var cl_pqa_series_term v0 = args.next(); // [N1] + var cl_pqa_series_term v1 = args.next(); // [N1+1] + var cl_I p01 = v0.p * v1.p; + if (P) { *P = p01; } + *Q = v0.q * v1.q; + *T = v1.q * v0.a * v0.p + + v1.a * p01; + break; + } + case 3: { + var cl_pqa_series_term v0 = args.next(); // [N1] + var cl_pqa_series_term v1 = args.next(); // [N1+1] + var cl_pqa_series_term v2 = args.next(); // [N1+2] + var cl_I p01 = v0.p * v1.p; + var cl_I p012 = p01 * v2.p; + if (P) { *P = p012; } + var cl_I q12 = v1.q * v2.q; + *Q = v0.q * q12; + *T = q12 * v0.a * v0.p + + v2.q * v1.a * p01 + + v2.a * p012; + break; + } + case 4: { + var cl_pqa_series_term v0 = args.next(); // [N1] + var cl_pqa_series_term v1 = args.next(); // [N1+1] + var cl_pqa_series_term v2 = args.next(); // [N1+2] + var cl_pqa_series_term v3 = args.next(); // [N1+3] + var cl_I p01 = v0.p * v1.p; + var cl_I p012 = p01 * v2.p; + var cl_I p0123 = p012 * v3.p; + if (P) { *P = p0123; } + var cl_I q23 = v2.q * v3.q; + var cl_I q123 = v1.q * q23; + *Q = v0.q * q123; + *T = q123 * v0.a * v0.p + + q23 * v1.a * p01 + + v3.q * v2.a * p012 + + v3.a * p0123; + break; + } + default: { + var uintL Nm = (N1+N2)/2; // midpoint + // Compute left part. + var cl_I LP, LQ, LT; + eval_pqa_series_aux(N1,Nm,args,&LP,&LQ,<); + // Compute right part. + var cl_I RP, RQ, RT; + eval_pqa_series_aux(Nm,N2,args,(P?&RP:(cl_I*)0),&RQ,&RT); + // Put together partial results. + if (P) { *P = LP*RP; } + *Q = LQ*RQ; + // S = LS + LP/LQ * RS, so T = RQ*LT + LP*RT. + *T = RQ*LT + LP*RT; + break; + } + } +} + +const cl_LF eval_rational_series (uintL N, cl_pqa_series_stream& args, uintC len) +{ + if (N==0) + return cl_I_to_LF(0,len); + var cl_I Q, T; + eval_pqa_series_aux(0,N,args,NULL,&Q,&T); + return cl_I_to_LF(T,len) / cl_I_to_LF(Q,len); +} diff --git a/src/float/transcendental/cl_LF_ratseries_stream_pqab.cc b/src/float/transcendental/cl_LF_ratseries_stream_pqab.cc new file mode 100644 index 0000000..0f406ac --- /dev/null +++ b/src/float/transcendental/cl_LF_ratseries_stream_pqab.cc @@ -0,0 +1,106 @@ +// eval_rational_series(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_integer.h" +#include "cl_abort.h" +#include "cl_LF.h" + +static void eval_pqab_series_aux (uintL N1, uintL N2, + cl_pqab_series_stream& args, + cl_I* P, cl_I* Q, cl_I* B, cl_I* T) +{ + switch (N2 - N1) { + case 0: + cl_abort(); break; + case 1: { + var cl_pqab_series_term v0 = args.next(); // [N1] + if (P) { *P = v0.p; } + *Q = v0.q; + *B = v0.b; + *T = v0.a * v0.p; + break; + } + case 2: { + var cl_pqab_series_term v0 = args.next(); // [N1] + var cl_pqab_series_term v1 = args.next(); // [N1+1] + var cl_I p01 = v0.p * v1.p; + if (P) { *P = p01; } + *Q = v0.q * v1.q; + *B = v0.b * v1.b; + *T = v1.b * v1.q * v0.a * v0.p + + v0.b * v1.a * p01; + break; + } + case 3: { + var cl_pqab_series_term v0 = args.next(); // [N1] + var cl_pqab_series_term v1 = args.next(); // [N1+1] + var cl_pqab_series_term v2 = args.next(); // [N1+2] + var cl_I p01 = v0.p * v1.p; + var cl_I p012 = p01 * v2.p; + if (P) { *P = p012; } + var cl_I q12 = v1.q * v2.q; + *Q = v0.q * q12; + var cl_I b12 = v1.b * v2.b; + *B = v0.b * b12; + *T = b12 * q12 * v0.a * v0.p + + v0.b * (v2.b * v2.q * v1.a * p01 + + v1.b * v2.a * p012); + break; + } + case 4: { + var cl_pqab_series_term v0 = args.next(); // [N1] + var cl_pqab_series_term v1 = args.next(); // [N1+1] + var cl_pqab_series_term v2 = args.next(); // [N1+2] + var cl_pqab_series_term v3 = args.next(); // [N1+3] + var cl_I p01 = v0.p * v1.p; + var cl_I p012 = p01 * v2.p; + var cl_I p0123 = p012 * v3.p; + if (P) { *P = p0123; } + var cl_I q23 = v2.q * v3.q; + var cl_I q123 = v1.q * q23; + *Q = v0.q * q123; + var cl_I b01 = v0.b * v1.b; + var cl_I b23 = v2.b * v3.b; + *B = b01 * b23; + *T = b23 * (v1.b * q123 * v0.a * v0.p + + v0.b * q23 * v1.a * p01) + + b01 * (v3.b * v3.q * v2.a * p012 + + v2.b * v3.a * p0123); + break; + } + default: { + var uintL Nm = (N1+N2)/2; // midpoint + // Compute left part. + var cl_I LP, LQ, LB, LT; + eval_pqab_series_aux(N1,Nm,args,&LP,&LQ,&LB,<); + // Compute right part. + var cl_I RP, RQ, RB, RT; + eval_pqab_series_aux(Nm,N2,args,(P?&RP:(cl_I*)0),&RQ,&RB,&RT); + // Put together partial results. + if (P) { *P = LP*RP; } + *Q = LQ*RQ; + *B = LB*RB; + // S = LS + LP/LQ * RS, so T = RB*RQ*LT + LB*LP*RT. + *T = RB*RQ*LT + LB*LP*RT; + break; + } + } +} + +const cl_LF eval_rational_series (uintL N, cl_pqab_series_stream& args, uintC len) +{ + if (N==0) + return cl_I_to_LF(0,len); + var cl_I Q, B, T; + eval_pqab_series_aux(0,N,args,NULL,&Q,&B,&T); + return cl_I_to_LF(T,len) / cl_I_to_LF(B*Q,len); +} diff --git a/src/float/transcendental/cl_LF_ratseries_stream_pqb.cc b/src/float/transcendental/cl_LF_ratseries_stream_pqb.cc new file mode 100644 index 0000000..efb6877 --- /dev/null +++ b/src/float/transcendental/cl_LF_ratseries_stream_pqb.cc @@ -0,0 +1,106 @@ +// eval_rational_series(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_integer.h" +#include "cl_abort.h" +#include "cl_LF.h" + +static void eval_pqb_series_aux (uintL N1, uintL N2, + cl_pqb_series_stream& args, + cl_I* P, cl_I* Q, cl_I* B, cl_I* T) +{ + switch (N2 - N1) { + case 0: + cl_abort(); break; + case 1: { + var cl_pqb_series_term v0 = args.next(); // [N1] + if (P) { *P = v0.p; } + *Q = v0.q; + *B = v0.b; + *T = v0.p; + break; + } + case 2: { + var cl_pqb_series_term v0 = args.next(); // [N1] + var cl_pqb_series_term v1 = args.next(); // [N1+1] + var cl_I p01 = v0.p * v1.p; + if (P) { *P = p01; } + *Q = v0.q * v1.q; + *B = v0.b * v1.b; + *T = v1.b * v1.q * v0.p + + v0.b * p01; + break; + } + case 3: { + var cl_pqb_series_term v0 = args.next(); // [N1] + var cl_pqb_series_term v1 = args.next(); // [N1+1] + var cl_pqb_series_term v2 = args.next(); // [N1+2] + var cl_I p01 = v0.p * v1.p; + var cl_I p012 = p01 * v2.p; + if (P) { *P = p012; } + var cl_I q12 = v1.q * v2.q; + *Q = v0.q * q12; + var cl_I b12 = v1.b * v2.b; + *B = v0.b * b12; + *T = b12 * q12 * v0.p + + v0.b * (v2.b * v2.q * p01 + + v1.b * p012); + break; + } + case 4: { + var cl_pqb_series_term v0 = args.next(); // [N1] + var cl_pqb_series_term v1 = args.next(); // [N1+1] + var cl_pqb_series_term v2 = args.next(); // [N1+2] + var cl_pqb_series_term v3 = args.next(); // [N1+3] + var cl_I p01 = v0.p * v1.p; + var cl_I p012 = p01 * v2.p; + var cl_I p0123 = p012 * v3.p; + if (P) { *P = p0123; } + var cl_I q23 = v2.q * v3.q; + var cl_I q123 = v1.q * q23; + *Q = v0.q * q123; + var cl_I b01 = v0.b * v1.b; + var cl_I b23 = v2.b * v3.b; + *B = b01 * b23; + *T = b23 * (v1.b * q123 * v0.p + + v0.b * q23 * p01) + + b01 * (v3.b * v3.q * p012 + + v2.b * p0123); + break; + } + default: { + var uintL Nm = (N1+N2)/2; // midpoint + // Compute left part. + var cl_I LP, LQ, LB, LT; + eval_pqb_series_aux(N1,Nm,args,&LP,&LQ,&LB,<); + // Compute right part. + var cl_I RP, RQ, RB, RT; + eval_pqb_series_aux(Nm,N2,args,(P?&RP:(cl_I*)0),&RQ,&RB,&RT); + // Put together partial results. + if (P) { *P = LP*RP; } + *Q = LQ*RQ; + *B = LB*RB; + // S = LS + LP/LQ * RS, so T = RB*RQ*LT + LB*LP*RT. + *T = RB*RQ*LT + LB*LP*RT; + break; + } + } +} + +const cl_LF eval_rational_series (uintL N, cl_pqb_series_stream& args, uintC len) +{ + if (N==0) + return cl_I_to_LF(0,len); + var cl_I Q, B, T; + eval_pqb_series_aux(0,N,args,NULL,&Q,&B,&T); + return cl_I_to_LF(T,len) / cl_I_to_LF(B*Q,len); +} diff --git a/src/float/transcendental/cl_LF_ratsumseries_pqcd.cc b/src/float/transcendental/cl_LF_ratsumseries_pqcd.cc new file mode 100644 index 0000000..2cf52a7 --- /dev/null +++ b/src/float/transcendental/cl_LF_ratsumseries_pqcd.cc @@ -0,0 +1,28 @@ +// eval_pqcd_series(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_integer.h" +#include "cl_abort.h" +#include "cl_LF.h" + +const cl_LF eval_pqcd_series (uintL N, cl_pqcd_series_term* args, uintC len) +{ + if (N==0) + return cl_I_to_LF(0,len); + var cl_pqcd_series_result sums; + eval_pqcd_series_aux(N,args,sums); + // Instead of computing fsum = T/Q and gsum = V/(D*Q) + // and then dividing them, to compute gsum/fsum, we save two + // divisions by computing V/(D*T). + return + cl_I_to_LF(sums.V,len) / The(cl_LF)(sums.D * cl_I_to_LF(sums.T,len)); +} diff --git a/src/float/transcendental/cl_LF_ratsumseries_pqcd_aux.cc b/src/float/transcendental/cl_LF_ratsumseries_pqcd_aux.cc new file mode 100644 index 0000000..b42ed08 --- /dev/null +++ b/src/float/transcendental/cl_LF_ratsumseries_pqcd_aux.cc @@ -0,0 +1,79 @@ +// eval_pqcd_series_aux(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF_tran.h" + + +// Implementation. + +#include "cl_integer.h" +#include "cl_abort.h" + +void eval_pqcd_series_aux (uintL N, cl_pqcd_series_term* args, cl_pqcd_series_result& Z, cl_boolean rightmost) +{ + // N = N2-N1 + switch (N) { + case 0: + cl_abort(); break; + case 1: + if (!rightmost) { Z.P = args[0].p; } + Z.Q = args[0].q; + Z.T = args[0].p; + if (!rightmost) { Z.C = args[0].c; } + Z.D = args[0].d; + Z.V = args[0].c * args[0].p; + break; + case 2: { + var cl_I p01 = args[0].p * args[1].p; + if (!rightmost) { Z.P = p01; } + Z.Q = args[0].q * args[1].q; + var cl_I p0q1 = args[0].p * args[1].q + p01; + Z.T = p0q1; + var cl_I c0d1 = args[0].c * args[1].d; + var cl_I c1d0 = args[1].c * args[0].d; + if (!rightmost) { Z.C = c0d1 + c1d0; } + Z.D = args[0].d * args[1].d; + Z.V = c0d1 * p0q1 + c1d0 * p01; + break; + } + case 3: { + var cl_I p01 = args[0].p * args[1].p; + var cl_I p012 = p01 * args[2].p; + if (!rightmost) { Z.P = p012; } + Z.Q = args[0].q * args[1].q * args[2].q; + var cl_I p0q1 = args[0].p * args[1].q + p01; + Z.T = args[2].q * p0q1 + p012; + var cl_I c0d1 = args[0].c * args[1].d; + var cl_I c1d0 = args[1].c * args[0].d; + var cl_I d01 = args[0].d * args[1].d; + if (!rightmost) { Z.C = (c0d1 + c1d0) * args[2].d + args[2].c * d01; } + Z.D = d01 * args[2].d; + Z.V = args[2].d * (args[2].q * (c0d1 * p0q1 + c1d0 * p01) + (c0d1 + c1d0) * p012) + args[2].c * d01 * p012; + break; + } + default: { + var uintL Nm = N/2; // midpoint + // Compute left part. + var cl_pqcd_series_result L; + eval_pqcd_series_aux(Nm,args+0,L,cl_false); + // Compute right part. + var cl_pqcd_series_result R; + eval_pqcd_series_aux(N-Nm,args+Nm,R,rightmost); + // Put together partial results. + if (!rightmost) { Z.P = L.P * R.P; } + Z.Q = L.Q * R.Q; + // Z.S = L.S + L.P/L.Q*R.S; + var cl_I tmp = L.P * R.T; + Z.T = R.Q * L.T + tmp; + if (!rightmost) { Z.C = L.C * R.D + L.D * R.C; } + Z.D = L.D * R.D; + // Z.U = L.U + L.C/L.D * L.P/L.Q * R.S + L.P/L.Q * R.U; + // Z.V = R.D * R.Q * L.V + R.D * L.C * L.P * R.T + L.D * L.P * R.V; + Z.V = R.D * (R.Q * L.V + L.C * tmp) + L.D * L.P * R.V; + break; + } + } +} diff --git a/src/float/transcendental/cl_LF_ratsumseries_pqd.cc b/src/float/transcendental/cl_LF_ratsumseries_pqd.cc new file mode 100644 index 0000000..891c5b4 --- /dev/null +++ b/src/float/transcendental/cl_LF_ratsumseries_pqd.cc @@ -0,0 +1,28 @@ +// eval_pqd_series(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_integer.h" +#include "cl_abort.h" +#include "cl_LF.h" + +const cl_LF eval_pqd_series (uintL N, cl_pqd_series_term* args, uintC len) +{ + if (N==0) + return cl_I_to_LF(0,len); + var cl_pqd_series_result sums; + eval_pqd_series_aux(N,args,sums); + // Instead of computing fsum = T/Q and gsum = V/(D*Q) + // and then dividing them, to compute gsum/fsum, we save two + // divisions by computing V/(D*T). + return + cl_I_to_LF(sums.V,len) / The(cl_LF)(sums.D * cl_I_to_LF(sums.T,len)); +} diff --git a/src/float/transcendental/cl_LF_ratsumseries_pqd_aux.cc b/src/float/transcendental/cl_LF_ratsumseries_pqd_aux.cc new file mode 100644 index 0000000..4266c1e --- /dev/null +++ b/src/float/transcendental/cl_LF_ratsumseries_pqd_aux.cc @@ -0,0 +1,75 @@ +// eval_pqd_series_aux(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_LF_tran.h" + + +// Implementation. + +#include "cl_integer.h" +#include "cl_abort.h" + +void eval_pqd_series_aux (uintL N, cl_pqd_series_term* args, cl_pqd_series_result& Z, cl_boolean rightmost) +{ + // N = N2-N1 + switch (N) { + case 0: + cl_abort(); break; + case 1: + if (!rightmost) { Z.P = args[0].p; } + Z.Q = args[0].q; + Z.T = args[0].p; + if (!rightmost) { Z.C = 1; } + Z.D = args[0].d; + Z.V = args[0].p; + break; + case 2: { + var cl_I p01 = args[0].p * args[1].p; + if (!rightmost) { Z.P = p01; } + Z.Q = args[0].q * args[1].q; + var cl_I p0q1 = args[0].p * args[1].q + p01; + Z.T = p0q1; + if (!rightmost) { Z.C = args[1].d + args[0].d; } + Z.D = args[0].d * args[1].d; + Z.V = args[1].d * p0q1 + args[0].d * p01; + break; + } + case 3: { + var cl_I p01 = args[0].p * args[1].p; + var cl_I p012 = p01 * args[2].p; + if (!rightmost) { Z.P = p012; } + Z.Q = args[0].q * args[1].q * args[2].q; + var cl_I p0q1 = args[0].p * args[1].q + p01; + Z.T = args[2].q * p0q1 + p012; + var cl_I d01 = args[0].d * args[1].d; + if (!rightmost) { Z.C = (args[1].d + args[0].d) * args[2].d + d01; } + Z.D = d01 * args[2].d; + Z.V = args[2].d * (args[2].q * (args[1].d * p0q1 + args[0].d * p01) + (args[1].d + args[0].d) * p012) + d01 * p012; + break; + } + default: { + var uintL Nm = N/2; // midpoint + // Compute left part. + var cl_pqd_series_result L; + eval_pqd_series_aux(Nm,args+0,L,cl_false); + // Compute right part. + var cl_pqd_series_result R; + eval_pqd_series_aux(N-Nm,args+Nm,R,rightmost); + // Put together partial results. + if (!rightmost) { Z.P = L.P * R.P; } + Z.Q = L.Q * R.Q; + // Z.S = L.S + L.P/L.Q*R.S; + var cl_I tmp = L.P * R.T; + Z.T = R.Q * L.T + tmp; + if (!rightmost) { Z.C = L.C * R.D + L.D * R.C; } + Z.D = L.D * R.D; + // Z.U = L.U + L.C/L.D * L.P/L.Q * R.S + L.P/L.Q * R.U; + // Z.V = R.D * R.Q * L.V + R.D * L.C * L.P * R.T + L.D * L.P * R.V; + Z.V = R.D * (R.Q * L.V + L.C * tmp) + L.D * L.P * R.V; + break; + } + } +} diff --git a/src/float/transcendental/cl_LF_tran.h b/src/float/transcendental/cl_LF_tran.h new file mode 100644 index 0000000..f19083a --- /dev/null +++ b/src/float/transcendental/cl_LF_tran.h @@ -0,0 +1,262 @@ +// cl_LF internals, transcendental functions + +#ifndef _CL_LF_TRAN_H +#define _CL_LF_TRAN_H + +#include "cl_integer.h" +#include "cl_lfloat.h" + + +// Subroutine for evaluating +// sum(0 <= n < N, a(n)/b(n) * (p(0)...p(n))/(q(0)...q(n))) +// where all the entries are small integers (ideally polynomials in n). +// This is fast because it groups factors together before multiplying. +// Arguments: +// Vectors p[0..N-1], q[0..N-1], a[0..N-1], b[0..N-1], N. +// Some of the vectors (a,b,p,q) can be a NULL pointer, all of its entries +// are then understood to be 1. +// If given, a vector qs[0..N-1] which the evaluation routine may use to +// split off q[n] into q[n]*2^qs[n]. qs may be NULL, in that case no shift +// optimizations will be used. (They are worth it only if a significant +// amount of multiplication work can be saved by shifts.) +// Result will be a cl_LF with len digits. + +struct cl_rational_series { + // To be set explicitly. + const cl_I* pv; + cl_I* qv; + const cl_I* av; + const cl_I* bv; + uintL* qsv; +}; +extern const cl_LF eval_rational_series (uintL N, const cl_rational_series& args, uintC len); + +// In each the special cases below, none of (a,b,p,q) can be NULL. But qs can +// still be given or NULL. + +struct cl_pqab_series { + const cl_I* pv; + cl_I* qv; + const cl_I* av; + const cl_I* bv; + uintL* qsv; +}; +extern const cl_LF eval_rational_series (uintL N, const cl_pqab_series& args, uintC len); + +struct cl_pqb_series { + const cl_I* pv; + cl_I* qv; + const cl_I* bv; + uintL* qsv; +}; +extern const cl_LF eval_rational_series (uintL N, const cl_pqb_series& args, uintC len); + +struct cl_pqa_series { + const cl_I* pv; + cl_I* qv; + const cl_I* av; + uintL* qsv; +}; +extern const cl_LF eval_rational_series (uintL N, const cl_pqa_series& args, uintC len); + +struct cl_pq_series { + const cl_I* pv; + cl_I* qv; + uintL* qsv; +}; +extern const cl_LF eval_rational_series (uintL N, const cl_pq_series& args, uintC len); + +struct cl_pab_series { + const cl_I* pv; + const cl_I* av; + const cl_I* bv; +}; +extern const cl_LF eval_rational_series (uintL N, const cl_pab_series& args, uintC len); + +struct cl_pb_series { + const cl_I* pv; + const cl_I* bv; +}; +extern const cl_LF eval_rational_series (uintL N, const cl_pb_series& args, uintC len); + +struct cl_pa_series { + const cl_I* pv; + const cl_I* av; +}; +extern const cl_LF eval_rational_series (uintL N, const cl_pa_series& args, uintC len); + +struct cl_p_series { + const cl_I* pv; +}; +extern const cl_LF eval_rational_series (uintL N, const cl_p_series& args, uintC len); + +struct cl_qab_series { + cl_I* qv; + const cl_I* av; + const cl_I* bv; + uintL* qsv; +}; +extern const cl_LF eval_rational_series (uintL N, const cl_qab_series& args, uintC len); + +struct cl_qb_series { + cl_I* qv; + const cl_I* bv; + uintL* qsv; +}; +extern const cl_LF eval_rational_series (uintL N, const cl_qb_series& args, uintC len); + +struct cl_qa_series { + cl_I* qv; + const cl_I* av; + uintL* qsv; +}; +extern const cl_LF eval_rational_series (uintL N, const cl_qa_series& args, uintC len); + +struct cl_q_series { + cl_I* qv; + uintL* qsv; +}; +extern const cl_LF eval_rational_series (uintL N, const cl_q_series& args, uintC len); + +struct cl_ab_series { + const cl_I* av; + const cl_I* bv; +}; +extern const cl_LF eval_rational_series (uintL N, const cl_ab_series& args, uintC len); + +struct cl_b_series { + const cl_I* bv; +}; +extern const cl_LF eval_rational_series (uintL N, const cl_b_series& args, uintC len); + +struct cl_a_series { + const cl_I* av; +}; +extern const cl_LF eval_rational_series (uintL N, const cl_a_series& args, uintC len); + +struct cl__series { +}; +extern const cl_LF eval_rational_series (uintL N, const cl__series& args, uintC len); + + +// In this alternate implementation the series is not represented as a couple +// of arrays, but as a method returning each tuple (p(n),q(n),a(n),b(n)) +// in turn. This is preferrable if the a(n) are big, in order to avoid too +// much memory usage at the same time. +// Some of the factors (a,b) may be omitted. They are then understood to be 1. +// The next function is called N times and is expected to return +// (p(n),q(n),a(n),b(n)) for n=0..N-1 in that order. + +struct cl_pqab_series_term { + cl_I p; + cl_I q; + cl_I a; + cl_I b; +}; +struct cl_pqab_series_stream { + cl_pqab_series_term (*nextfn)(cl_pqab_series_stream&); + cl_pqab_series_term next () { return nextfn(*this); } + // Constructor. + cl_pqab_series_stream (cl_pqab_series_term (*n)(cl_pqab_series_stream&)) : nextfn (n) {} +}; +extern const cl_LF eval_rational_series (uintL N, cl_pqab_series_stream& args, uintC len); + +struct cl_pqb_series_term { + cl_I p; + cl_I q; + cl_I b; +}; +struct cl_pqb_series_stream { + cl_pqb_series_term (*nextfn)(cl_pqb_series_stream&); + cl_pqb_series_term next () { return nextfn(*this); } + // Constructor. + cl_pqb_series_stream (cl_pqb_series_term (*n)(cl_pqb_series_stream&)) : nextfn (n) {} +}; +extern const cl_LF eval_rational_series (uintL N, cl_pqb_series_stream& args, uintC len); + +struct cl_pqa_series_term { + cl_I p; + cl_I q; + cl_I a; +}; +struct cl_pqa_series_stream { + cl_pqa_series_term (*nextfn)(cl_pqa_series_stream&); + cl_pqa_series_term next () { return nextfn(*this); } + // Constructor. + cl_pqa_series_stream (cl_pqa_series_term (*n)(cl_pqa_series_stream&)) : nextfn (n) {} +}; +extern const cl_LF eval_rational_series (uintL N, cl_pqa_series_stream& args, uintC len); + +struct cl_pq_series_term { + cl_I p; + cl_I q; +}; +struct cl_pq_series_stream { + cl_pq_series_term (*nextfn)(cl_pq_series_stream&); + cl_pq_series_term next () { return nextfn(*this); } + // Constructor. + cl_pq_series_stream (cl_pq_series_term (*n)(cl_pq_series_stream&)) : nextfn (n) {} +}; +extern const cl_LF eval_rational_series (uintL N, cl_pq_series_stream& args, uintC len); + + +// [Generalization.] +// Subroutine: +// Evaluates S = sum(N1 <= n < N2, (p(N1)...p(n))/(q(N1)...q(n))) +// and U = sum(N1 <= n < N2, +// (c(N1)/d(N1)+...+c(n)/d(n))*(p(N1)...p(n))/(q(N1)...q(n))) +// and returns +// P = p(N1)...p(N2-1), +// Q = q(N1)...q(N2-1), +// T = Q*S, +// C/D = c(N1)/d(N1)+...+c(N2-1)/d(N2-1), +// V = D*Q*U, +// all integers. On entry N1 < N2. +struct cl_pqcd_series_term { + cl_I p; + cl_I q; + cl_I c; + cl_I d; +}; +struct cl_pqcd_series_result { + cl_I P; + cl_I Q; + cl_I T; + cl_I C; + cl_I D; + cl_I V; +}; +extern void eval_pqcd_series_aux (uintL N, cl_pqcd_series_term* args, cl_pqcd_series_result& Z, cl_boolean rightmost = cl_true); +// Ditto, but returns U/S. +extern const cl_LF eval_pqcd_series (uintL N, cl_pqcd_series_term* args, uintC len); + +// [Special case c(n)=1.] +// Subroutine: +// Evaluates S = sum(N1 <= n < N2, (p(N1)...p(n))/(q(N1)...q(n))) +// and U = sum(N1 <= n < N2, (1/d(N1)+...+1/d(n))*(p(N1)...p(n))/(q(N1)...q(n))) +// and returns +// P = p(N1)...p(N2-1), +// Q = q(N1)...q(N2-1), +// T = Q*S, +// C/D = 1/d(N1)+...+1/d(N2-1), +// V = D*Q*U, +// all integers. On entry N1 < N2. +struct cl_pqd_series_term { + cl_I p; + cl_I q; + cl_I d; +}; +struct cl_pqd_series_result { + cl_I P; + cl_I Q; + cl_I T; + cl_I C; + cl_I D; + cl_I V; +}; +extern void eval_pqd_series_aux (uintL N, cl_pqd_series_term* args, cl_pqd_series_result& Z, cl_boolean rightmost = cl_true); +// Ditto, but returns U/S. +extern const cl_LF eval_pqd_series (uintL N, cl_pqd_series_term* args, uintC len); + + +#endif /* _CL_LF_TRAN_H */ diff --git a/src/float/transcendental/cl_LF_zeta3.cc b/src/float/transcendental/cl_LF_zeta3.cc new file mode 100644 index 0000000..0455da5 --- /dev/null +++ b/src/float/transcendental/cl_LF_zeta3.cc @@ -0,0 +1,83 @@ +// cl_zeta3(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_LF_tran.h" +#include "cl_LF.h" +#include "cl_integer.h" +#include "cl_alloca.h" + +const cl_LF cl_zeta3 (uintC len) +{ + // Method: + // /infinity \ + // | ----- (n + 1) 2 | + // 1 | \ (-1) (205 n - 160 n + 32)| + // - | ) ---------------------------------| + // 2 | / 5 5 | + // | ----- n binomial(2 n, n) | + // \ n = 1 / + // + // The formula used to compute Zeta(3) has reference in the paper + // "Acceleration of Hypergeometric Series via the WZ method" by + // T. Amdeberhan and Doron Zeilberger, to appear in the Electronic + // Journal of Combinatorics [Wilf Festschrift Volume]. + // + // Computation of the sum: + // Evaluate a sum(0 <= n < N, a(n)/b(n) * (p(0)...p(n))/(q(0)...q(n))) + // with appropriate N, and + // a(n) = 205*n^2+250*n+77, b(n) = 1, + // p(0) = 1, p(n) = -n^5 for n>0, q(n) = 32*(2n+1)^5. + var uintC actuallen = len+2; // 2 Schutz-Digits + var uintL N = ceiling(actuallen*intDsize,10); + // 1024^-N <= 2^(-intDsize*actuallen). + CL_ALLOCA_STACK; + var cl_I* av = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var cl_I* pv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var cl_I* qv = (cl_I*) cl_alloca(N*sizeof(cl_I)); + var uintL n; + for (n = 0; n < N; n++) { + init1(cl_I, av[n]) (205*square((cl_I)n) + 250*(cl_I)n + 77); + if (n==0) + init1(cl_I, pv[n]) (1); + else + init1(cl_I, pv[n]) (-expt_pos(n,5)); + init1(cl_I, qv[n]) (expt_pos(2*n+1,5)<<5); + } + var cl_pqa_series series; + series.av = av; + series.pv = pv; series.qv = qv; series.qsv = NULL; + var cl_LF sum = eval_rational_series(N,series,actuallen); + for (n = 0; n < N; n++) { + av[n].~cl_I(); + pv[n].~cl_I(); + qv[n].~cl_I(); + } + return scale_float(shorten(sum,len),-1); +} +// Bit complexity (N := len): O(log(N)^2*M(N)). + +// Timings of the above algorithm, on an i486 33 MHz, running Linux. +// N sum_exp sum_cvz1 sum_cvz2 hypgeom +// 10 1.17 0.081 0.125 0.013 +// 25 5.1 0.23 0.50 0.045 +// 50 15.7 0.66 1.62 0.14 +// 100 45.5 1.93 5.4 0.44 +// 250 169 13.1 25.1 2.03 +// 500 436 56.5 70.6 6.44 +// 1000 236 192 18.2 +// 2500 78.3 +// 5000 202 +// 10000 522 +// 25000 1512 +// 50000 3723 +// asymp. FAST N^2 FAST FAST +// (FAST means O(log(N)^2*M(N))) diff --git a/src/float/transcendental/cl_LF_zeta_int.cc b/src/float/transcendental/cl_LF_zeta_int.cc new file mode 100644 index 0000000..a1167d3 --- /dev/null +++ b/src/float/transcendental/cl_LF_zeta_int.cc @@ -0,0 +1,144 @@ +// cl_zeta(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_F_tran.h" + + +// Implementation. + +#include "cl_lfloat.h" +#include "cl_LF_tran.h" +#include "cl_LF.h" +#include "cl_integer.h" +#include "cl_abort.h" +#include "cl_alloca.h" + +const cl_LF compute_zeta_exp (int s, uintC len) +{ + // Method: + // zeta(s) = 1/(1-2^(1-s)) sum(n=0..infty, (-1)^n/(n+1)^s), + // with convergence acceleration through exp(x), and evaluated + // using the binary-splitting algorithm. + var uintC actuallen = len+2; // 2 Schutz-Digits + var uintL x = (uintL)(0.693148*intDsize*actuallen)+1; + var uintL N = (uintL)(2.718281828*x); + CL_ALLOCA_STACK; + var cl_pqd_series_term* args = (cl_pqd_series_term*) cl_alloca(N*sizeof(cl_pqd_series_term)); + var uintL n; + for (n = 0; n < N; n++) { + if (n==0) { + init1(cl_I, args[n].p) (1); + init1(cl_I, args[n].q) (1); + } else { + init1(cl_I, args[n].p) (x); + init1(cl_I, args[n].q) (n); + } + init1(cl_I, args[n].d) (evenp(n) + ? expt_pos(n+1,s) + : -expt_pos(n+1,s)); + } + var cl_LF result = eval_pqd_series(N,args,actuallen); + for (n = 0; n < N; n++) { + args[n].p.~cl_I(); + args[n].q.~cl_I(); + args[n].d.~cl_I(); + } + result = shorten(result,len); // verkürzen und fertig + // Zum Schluss mit 2^(s-1)/(2^(s-1)-1) multiplizieren: + return scale_float(result,s-1) / (ash(1,s-1)-1); +} +// Bit complexity (N = len): O(log(N)^2*M(N)). + +const cl_LF compute_zeta_cvz1 (int s, uintC len) +{ + // Method: + // zeta(s) = 1/(1-2^(1-s)) sum(n=0..infty, (-1)^n/(n+1)^s), + // with Cohen-Villegas-Zagier convergence acceleration. + var uintC actuallen = len+2; // 2 Schutz-Digits + var uintL N = (uintL)(0.39321985*intDsize*actuallen)+1; + var cl_I fterm = 2*(cl_I)N*(cl_I)N; + var cl_I fsum = fterm; + var cl_LF gterm = cl_I_to_LF(fterm,actuallen); + var cl_LF gsum = gterm; + var uintL n; + // After n loops + // fterm = (N+n)!N/(2n+2)!(N-n-1)!*2^(2n+2), fsum = ... + fterm, + // gterm = S_n*fterm, gsum = ... + gterm. + for (n = 1; n < N; n++) { + fterm = exquopos(fterm*(2*(cl_I)(N-n)*(cl_I)(N+n)),(cl_I)(2*n+1)*(cl_I)(n+1)); + fsum = fsum + fterm; + gterm = The(cl_LF)(gterm*(2*(cl_I)(N-n)*(cl_I)(N+n)))/((cl_I)(2*n+1)*(cl_I)(n+1)); + if (evenp(n)) + gterm = gterm + cl_I_to_LF(fterm,actuallen)/expt_pos(n+1,s); + else + gterm = gterm - cl_I_to_LF(fterm,actuallen)/expt_pos(n+1,s); + gsum = gsum + gterm; + } + var cl_LF result = gsum/cl_I_to_LF(1+fsum,actuallen); + result = shorten(result,len); // verkürzen und fertig + // Zum Schluss mit 2^(s-1)/(2^(s-1)-1) multiplizieren: + return scale_float(result,s-1) / (ash(1,s-1)-1); +} +// Bit complexity (N = len): O(N^2). + +const cl_LF compute_zeta_cvz2 (int s, uintC len) +{ + // Method: + // zeta(s) = 1/(1-2^(1-s)) sum(n=0..infty, (-1)^n/(n+1)^s), + // with Cohen-Villegas-Zagier convergence acceleration, and + // evaluated using the binary splitting algorithm. + var uintC actuallen = len+2; // 2 Schutz-Digits + var uintL N = (uintL)(0.39321985*intDsize*actuallen)+1; + CL_ALLOCA_STACK; + var cl_pqd_series_term* args = (cl_pqd_series_term*) cl_alloca(N*sizeof(cl_pqd_series_term)); + var uintL n; + for (n = 0; n < N; n++) { + init1(cl_I, args[n].p) (2*(cl_I)(N-n)*(cl_I)(N+n)); + init1(cl_I, args[n].q) ((cl_I)(2*n+1)*(cl_I)(n+1)); + init1(cl_I, args[n].d) (evenp(n) + ? expt_pos(n+1,s) + : -expt_pos(n+1,s)); + } + var cl_pqd_series_result sums; + eval_pqd_series_aux(N,args,sums); + // Here we need U/(1+S) = V/D(Q+T). + var cl_LF result = + cl_I_to_LF(sums.V,actuallen) / The(cl_LF)(sums.D * cl_I_to_LF(sums.Q+sums.T,actuallen)); + for (n = 0; n < N; n++) { + args[n].p.~cl_I(); + args[n].q.~cl_I(); + args[n].d.~cl_I(); + } + result = shorten(result,len); // verkürzen und fertig + // Zum Schluss mit 2^(s-1)/(2^(s-1)-1) multiplizieren: + return scale_float(result,s-1) / (ash(1,s-1)-1); +} +// Bit complexity (N = len): O(log(N)^2*M(N)). + +// Timings of the above algorithm, on an i486 33 MHz, running Linux. +// s 5 15 +// N sum_exp sum_cvz1 sum_cvz2 sum_exp sum_cvz1 sum_cvz2 +// 10 2.04 0.09 0.17 8.0 0.11 0.49 +// 25 8.6 0.30 0.76 30.6 0.37 2.36 +// 50 25.1 0.92 2.49 91.1 1.15 7.9 +// 100 2.97 8.46 3.75 24.5 +// 250 16.7 36.5 21.7 108 +// 500 64.2 106 85.3 295 +// 1000 263 285 342 788 +// asymp. FAST N^2 FAST FAST N^2 FAST +// +// The break-even point between cvz1 and cvz2 seems to grow linearly with s. + +const cl_LF cl_zeta (int s, uintC len) +{ + if (!(s > 1)) + cl_abort(); + if (len < 280*(uintL)s) + return compute_zeta_cvz1(s,len); + else + return compute_zeta_cvz2(s,len); +} +// Bit complexity (N = len): O(log(N)^2*M(N)). diff --git a/src/integer/2adic/Makeflags b/src/integer/2adic/Makeflags new file mode 100644 index 0000000..c8d2dc9 --- /dev/null +++ b/src/integer/2adic/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/integer/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/integer/bitwise diff --git a/src/integer/2adic/cl_I_2adic_div.cc b/src/integer/2adic/cl_I_2adic_div.cc new file mode 100644 index 0000000..97791fe --- /dev/null +++ b/src/integer/2adic/cl_I_2adic_div.cc @@ -0,0 +1,50 @@ +// cl_div2adic(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_DS.h" +#include "cl_2DS.h" +#include "cl_I_log.h" + +const cl_I cl_div2adic (uintL n, const cl_I& x, const cl_I& y) +{ + var uintL len = ceiling(n,intDsize); + CL_ALLOCA_STACK; + var const uintD* x_LSDptr; + var const uintD* y_LSDptr; + if (bignump(x) && TheBignum(x)->length >= len) + // no need to copy x + x_LSDptr = BN_LSDptr(x); + else { // copy x + var uintL x_len = I_to_DS_need(x); + if (x_len < len) { x_len = len; } + I_to_DS_n(x,x_len,x_LSDptr=); + x_LSDptr = x_LSDptr mspop x_len; + } + if (bignump(y) && TheBignum(y)->length >= len) + // no need to copy y + y_LSDptr = BN_LSDptr(y); + else { // copy y + var uintL y_len = I_to_DS_need(y); + if (y_len < len) { y_len = len; } + I_to_DS_n(y,y_len,y_LSDptr=); + y_LSDptr = y_LSDptr mspop y_len; + } + var uintD* z_LSDptr; + num_stack_alloc_1(len,,z_LSDptr=); + // Compute quotient mod 2^(intDsize*len). + div2adic(len,x_LSDptr,y_LSDptr,z_LSDptr); + // Reduce mod 2^n. + if ((n % intDsize) != 0) + lspref(z_LSDptr,floor(n,intDsize)) &= (bit(n % intDsize) - 1); + return UDS_to_I(z_LSDptr lspop len,len); +} +// Bit complexity (N := n): O(M(N)). + diff --git a/src/integer/2adic/cl_I_2adic_recip.cc b/src/integer/2adic/cl_I_2adic_recip.cc new file mode 100644 index 0000000..f997850 --- /dev/null +++ b/src/integer/2adic/cl_I_2adic_recip.cc @@ -0,0 +1,40 @@ +// cl_recip2adic(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_DS.h" +#include "cl_2DS.h" +#include "cl_I_log.h" + +const cl_I cl_recip2adic (uintL n, const cl_I& x) +{ + var uintL len = ceiling(n,intDsize); + CL_ALLOCA_STACK; + var const uintD* x_LSDptr; + if (bignump(x) && TheBignum(x)->length >= len) + // no need to copy x + x_LSDptr = BN_LSDptr(x); + else { // copy x + var uintL x_len = I_to_DS_need(x); + if (x_len < len) { x_len = len; } + I_to_DS_n(x,x_len,x_LSDptr=); + x_LSDptr = x_LSDptr mspop x_len; + } + var uintD* y_LSDptr; + num_stack_alloc_1(len,,y_LSDptr=); + // Compute inverse mod 2^(intDsize*len). + recip2adic(len,x_LSDptr,y_LSDptr); + // Reduce mod 2^n. + if ((n % intDsize) != 0) + lspref(y_LSDptr,floor(n,intDsize)) &= (bit(n % intDsize) - 1); + return UDS_to_I(y_LSDptr lspop len,len); +} +// Bit complexity (N := n): O(M(N)). + diff --git a/src/integer/Makeflags b/src/integer/Makeflags new file mode 100644 index 0000000..04eee3b --- /dev/null +++ b/src/integer/Makeflags @@ -0,0 +1,3 @@ +# This file contains additional flags for the main Makefile. + +SUBDIR_INCLUDES = -I$(srcdir)/integer -I$(srcdir)/base/digitseq -I$(srcdir)/base/digit -Ibase -I$(srcdir)/base $(GMP_INCLUDES) diff --git a/src/integer/algebraic/Makeflags b/src/integer/algebraic/Makeflags new file mode 100644 index 0000000..3696f90 --- /dev/null +++ b/src/integer/algebraic/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/integer/Makeflags +SUBDIR_INCLUDES += diff --git a/src/integer/algebraic/cl_I_rootp.cc b/src/integer/algebraic/cl_I_rootp.cc new file mode 100644 index 0000000..934d948 --- /dev/null +++ b/src/integer/algebraic/cl_I_rootp.cc @@ -0,0 +1,27 @@ +// rootp(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" + +// Methode: +// Falls x=0 oder x=1: x = x^n -> JA, x als Ergebnis. +// Hier also x>1. Suche ein Integer y > 1 mit x=y^n. +// Falls n >= integer_length(x): NEIN. (Da y>=2, müßte x>=2^n gelten.) +// Hier also n>0 klein... + +cl_boolean rootp (const cl_I& x, uintL n, cl_I* w) +{ + if (eq(x,0) || eq(x,1)) // x=0 oder x=1 ? + { *w = x; return cl_true; } // ja -> x als Ergebnis + if (n >= integer_length(x)) + { return cl_false; } + return cl_rootp_aux(x,n,w); +} diff --git a/src/integer/algebraic/cl_I_rootp_I.cc b/src/integer/algebraic/cl_I_rootp_I.cc new file mode 100644 index 0000000..c229cb1 --- /dev/null +++ b/src/integer/algebraic/cl_I_rootp_I.cc @@ -0,0 +1,28 @@ +// rootp(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" + +// Methode: +// Falls x=0 oder x=1: x = x^n -> JA, x als Ergebnis. +// Hier also x>1. Suche ein Integer y > 1 mit x=y^n. +// Falls n >= integer_length(x): NEIN. (Da y>=2, müßte x>=2^n gelten.) +// Hier also n>0 klein... + +cl_boolean rootp (const cl_I& x, const cl_I& n, cl_I* w) +{ + if (eq(x,0) || eq(x,1)) // x=0 oder x=1 ? + { *w = x; return cl_true; } // ja -> x als Ergebnis + if (n >= UL_to_I(integer_length(x))) + { return cl_false; } + // Nun ist n < (integer-length x). Also paßt n in ein uintL. + return cl_rootp_aux(x,cl_I_to_UL(n),w); +} diff --git a/src/integer/algebraic/cl_I_rootp_aux.cc b/src/integer/algebraic/cl_I_rootp_aux.cc new file mode 100644 index 0000000..a8f5f95 --- /dev/null +++ b/src/integer/algebraic/cl_I_rootp_aux.cc @@ -0,0 +1,196 @@ +// cl_rootp_aux(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" +#include "cl_2D.h" +#include "cl_2DS.h" + +// Stellt fest, ob ein Integer >=0 eine n-te Potenz ist. +// rootp(x,n,&w) +// > x: ein Integer >=0 +// > n: ein Integer >0 +// > Annahme: x > 1 und n < (integer-length x). +// < w: Integer (expt x (/ n)) falls x eine n-te Potenz +// < ergebnis: cl_true ........................, cl_false sonst + +cl_boolean cl_rootp_aux (cl_I x, uintL n, cl_I* w) +{ + +// Methode: +// Falls x=0 oder x=1: x = x^n -> JA, x als Ergebnis. +// Hier also x>1. Suche ein Integer y > 1 mit x=y^n. +// Falls n >= integer_length(x): NEIN. (Da y>=2, müßte x>=2^n gelten.) +// Hier also n>0 klein. +// Solange n gerade ist: x := (sqrt x), n := (/ n 2). x nicht ganz -> NEIN. +// Hier also n>0 ungerade. +// Falls n=1: x = x^n -> JA, x als Ergebnis. +// Falls o := ord2(x) nicht durch n teilbar ist: NEIN. +// Sonst dividiere x durch 2^o, am Schluß y mit 2^(o/n) multiplizieren. +// Hier also n>0 ungerade, x ungerade. +// beta := 2^intDsize, m := ceiling(integer_length(x)/(intDsize*n)). +// Suche ein y mit y>=0, y fertig. +// Setze y == y0 + beta^k*y1 mod beta^2k an, wobei 2k := min(2*k,m). +// Dabei wird y1 mod beta^(2k-k) so gewählt, daß mod beta^2k +// x == y^n == y0^n + n * y0^(n-1) * beta^k*y1. Dazu wird +// (x - y0^n) mod beta^2k errechnet, durch beta^k dividiert (die Division +// muß nach Voraussetzung an y0 aufgehen) und +// y1 := ((x-y0^n)/beta^k) / (n*y0^(n-1)) mod beta^(2k-k) gebildet. +// Damit hat man (y0 + beta^k*y1)^n == x mod beta^2k . 2k=m -> fertig. +// Den Anfang (k=1) bekommt man analog, mit beta:=2 und k=1,k=2,k=4,... +// Dann testet man, ob wirklich x = y^n, und ist fertig. + + while ((n % 2) == 0) // n gerade? + { if (!sqrtp(x,&x)) // Quadratwurzel ziehen versuchen + { return cl_false; } // nicht ganzzahlig -> fertig + n = n >> 1; // n := (/ n 2) + } + // Nun ist n ungerade. + if (n==1) { *w = x; return cl_true; } // n=1 -> x als Ergebnis + var uintL oq = 0; // Shift von y am Schluß + {var uintL o = ord2(x); + if (!(o==0)) + {var uintL o_r; divu_3232_3232(o,n, oq=,o_r=); // o_r = o mod n + if (!(o_r==0)) { return cl_false; } // o nicht durch n teilbar -> fertig + // oq = o/n. + // dividiere x durch 2^o: + x = ash(x,-(sintL)o); + } } + // Nun ist n ungerade, x ungerade. + CL_ALLOCA_STACK; + var uintC n_len; + var uintD* n_LSDptr; + var uintC x_len; + var const uintD* x_LSDptr; + // UDS zu n bilden, 00 + var uintD x_lsd = lspref(x_LSDptr,0); // letztes Digit von x + var uintD y_lsd; // n-te Wurzel von x_lsd mod 2^intDsize + y_lsd = 1; // Wurzel mod 2^1 + // Für k=1,2,4,...: + // y_lsd := y_lsd + 2^k * (x_lsd-y_lsd^n)/2^k / (n*y_lsd^(n-1)) + // = y_lsd + (x_lsd-y_lsd^n) / (n*y_lsd^(n-1)) + doconsttimes(log2_intDsize, // log2(intDsize) Iterationen reichen aus + { var uintD y_lsd_n1 = expt_pos(y_lsd,n-1); // y_lsd^(n-1) + var uintD y_lsd_n = mul2adic(y_lsd_n1,y_lsd); // y_lsd^n + var uintD delta = x_lsd-y_lsd_n; // x_lsd - y_lsd^n + if (delta==0) goto y_lsd_ok; + y_lsd = y_lsd + div2adic(delta,mul2adic((uintD)n,y_lsd_n1)); + }); + y_lsd_ok: + ASSERT(expt_pos(y_lsd,n)==x_lsd); + // Nun ist y_lsd^n == x_lsd mod beta=2^intDsize. + { var uintL m = ceiling((uintL)x_len,n); // für y nötige Länge, >0, <=x_len + var uintD* y_LSDptr; + { var uintD* z1_LSDptr; + var uintD* z2_LSDptr; + var uintD* z3_LSDptr; + num_stack_alloc_1(m, ,y_LSDptr=); // Platz für y + {var uintL need = 2*m+(32/intDsize-1); // >= max(2*m,m+32/intDsize) + num_stack_alloc(need, ,z1_LSDptr=); // Platz für Rechenregister 1 + num_stack_alloc(need, ,z2_LSDptr=); // Platz für Rechenregister 2 + num_stack_alloc(need, ,z3_LSDptr=); // Platz für Rechenregister 3 + } + {var uintL k = 1; // y ist bisher mod beta^k bekannt + lspref(y_LSDptr,0) = y_lsd; // Startwert von y + until (k==m) + { var uintL k2 = 2*k; if (k2>m) { k2=m; } // k2 = min(2*k,m) > k + // bisheriges y mod beta^k2 mit n-1 potenzieren: + // Methode für z := y^(n-1) : + // zz:=y, e:=n-1. + // Solange e gerade, setze zz:=zz*zz, e:=e/2. + // z:=zz. + // Solange (e:=floor(e/2)) >0, + // setze zz:=zz*zz, und falls e ungerade, setze z:=z*zz. + var uintL e = n-1; // e:=n-1 + var uintD* free_LSDptr = z1_LSDptr; + var uintD* zz_LSDptr = z2_LSDptr; + var uintD* z_LSDptr; + // Ab jetzt {zz_LSDptr,free_LSDptr} = {z1_LSDptr,z2_LSDptr}. + clear_loop_lsp(y_LSDptr lspop k,k2-k); // y auf k2 Digits erweitern + copy_loop_lsp(y_LSDptr,zz_LSDptr,k2); // zz:=y + do { var uintD* new_zz_LSDptr = free_LSDptr; + cl_UDS_mul(zz_LSDptr,k2,zz_LSDptr,k2,new_zz_LSDptr); // zz:=zz*zz + free_LSDptr = zz_LSDptr; zz_LSDptr = new_zz_LSDptr; + e = e>>1; // e:=e/2 + } + while ((e & bit(0)) ==0); // solange e gerade + z_LSDptr = zz_LSDptr; // z:=zz + // (zz nicht kopieren; ab der nächsten Veränderung von zz wird + // {zz_LSDptr,z_LSDptr,free_LSDptr} = {z1_LSDptr,z2_LSDptr,z3_LSDptr} + // gelten.) + until ((e = e>>1) == 0) + { {var uintD* new_zz_LSDptr = free_LSDptr; + cl_UDS_mul(zz_LSDptr,k2,zz_LSDptr,k2,new_zz_LSDptr); // zz:=zz*zz + free_LSDptr = (z_LSDptr==zz_LSDptr ? z3_LSDptr : zz_LSDptr); + zz_LSDptr = new_zz_LSDptr; + } + if (!((e & bit(0)) == 0)) + {var uintD* new_z_LSDptr = free_LSDptr; + cl_UDS_mul(z_LSDptr,k2,zz_LSDptr,k2,new_z_LSDptr); // z:=z*zz + free_LSDptr = z_LSDptr; z_LSDptr = new_z_LSDptr; + } } + // z = y^(n-1) mod beta^k2 ist fertig. + if (z_LSDptr==zz_LSDptr) { zz_LSDptr = z3_LSDptr; } // zz ist jetzt auch frei + cl_UDS_mul(z_LSDptr,k2,y_LSDptr,k2,free_LSDptr); // y^n + sub_loop_lsp(x_LSDptr,free_LSDptr,zz_LSDptr,k2); // zz:=x-y^n + ASSERT(!DS_test_loop(zz_LSDptr lspop k,k,zz_LSDptr)); // zz == 0 mod beta^k + cl_UDS_mul(z_LSDptr,k2-k,n_LSDptr,n_len,free_LSDptr); // n*y^(n-1) + // Quotienten mod beta^(k2-k) bilden und an y mod beta^k ankleben: + div2adic(k2-k,zz_LSDptr lspop k,free_LSDptr,y_LSDptr lspop k); + k = k2; // jetzt gilt y^n == x sogar mod beta^k2. + }} } + // y mit y^n == x mod beta^m ist gefunden. + var cl_I y = UDS_to_I(y_LSDptr lspop m,m); // y als Integer >=0 + // y^n (mit n ungerade) bilden: + // c:=a:=y, b:=n. + // Solange b:=floor(b/2) >0 ist, + // setze a:=a*a, und falls b ungerade, setze c:=a*c. + // Liefere c. + { var cl_I c = y; + var cl_I a = y; + until ((n = n>>1) == 0) + { a = square(a); if (!((n & bit(0)) == 0)) { c = a * c; } } + // c = y^n + // mit x vergleichen: + if (!(x == c)) + // Die ganze Rechnung war umsonst. + { return cl_false; } + } + // y ist tatsächlich n-te Wurzel von x. + // Noch mit 2^oq multiplizieren: + if (oq==0) // kein Shift nötig? + { *w = y; } + else + { *w = ash(y,oq); } + return cl_true; + } +} diff --git a/src/integer/algebraic/cl_I_sqrt.cc b/src/integer/algebraic/cl_I_sqrt.cc new file mode 100644 index 0000000..6d44f54 --- /dev/null +++ b/src/integer/algebraic/cl_I_sqrt.cc @@ -0,0 +1,39 @@ +// isqrt(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_number.h" +#include "cl_io.h" +#include "cl_integer_io.h" +#include "cl_abort.h" +#include "cl_I.h" +#include "cl_DS.h" + +cl_boolean isqrt (const cl_I& x, cl_I* w) +{ + if (minusp(x)) { + fprint(cl_stderr, "isqrt: applied to negative number: "); + fprint(cl_stderr, x); + fprint(cl_stderr, "\n"); + cl_abort(); + } + CL_ALLOCA_STACK; + var const uintD* x_MSDptr; + var uintC x_len; + var const uintD* x_LSDptr; + I_to_NDS_nocopy(x, x_MSDptr=,x_len=,x_LSDptr=,cl_true,); // Digit sequence >=0 zu x + var DS y; + var cl_boolean squarep; + UDS_sqrt(x_MSDptr,x_len,x_LSDptr, &y, squarep=); // Wurzel ziehen + *w = NUDS_to_I(y.MSDptr,y.len); // als Integer + return squarep; +} +// Bit complexity (x of length N): O(M(N)). + diff --git a/src/integer/algebraic/cl_I_sqrtp.cc b/src/integer/algebraic/cl_I_sqrtp.cc new file mode 100644 index 0000000..ab40247 --- /dev/null +++ b/src/integer/algebraic/cl_I_sqrtp.cc @@ -0,0 +1,87 @@ +// sqrtp(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" + +cl_boolean sqrtp (const cl_I& x, cl_I* w) +{ +// Methode: +// [Henri Cohen: A course in computational algebraic number theory, 2nd prnt., +// section 1.7.2.] +// If x is a square, it has not only to be ==0,1 mod 4, but also +// - one of the 12 squares mod 64, +// - one of the 16 squares mod 63, +// - one of the 21 squares mod 65, +// - one of the 6 squares mod 11. +// Then we check whether the ISQRT gives the remainder 0. + static char squares_mod_11 [11] = + // 0 1 3 4 5 9 + { 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0 }; + static char squares_mod_63 [63] = + // 0 1 4 7 9 16 18 22 25 28 36 37 43 46 49 58 + { 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0 + }; + static char squares_mod_64 [64] = + // 0 1 4 9 16 17 25 33 36 41 49 57 + { 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 + }; + static char squares_mod_65 [65] = + // 0 1 4 9 10 14 16 25 26 29 30 35 36 39 40 49 51 55 56 61 64 + { 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 1, 0, 0, 1 + }; + { CL_ALLOCA_STACK; + var const uintD* x_MSDptr; + var uintC x_len; + var const uintD* x_LSDptr; + I_to_NDS_nocopy(x, x_MSDptr=,x_len=,x_LSDptr=, // Digit sequence >=0 zu x + cl_true, { *w = 0; return cl_true; } // 0 is a square + ); + // Check mod 64. + { var uintD lsd = lspref(x_LSDptr,0); + if (!squares_mod_64[lsd & 63]) + { return cl_false; } // not a square mod 64 -> not a square + } + // Check mod 63. + { var cl_I_div_t div63 = cl_divide(x,L_to_FN(63)); + if (!squares_mod_63[FN_to_UL(div63.remainder)]) + { return cl_false; } // not a square mod 63 -> not a square + } + // Check mod 65. + { var cl_I_div_t div65 = cl_divide(x,L_to_FN(65)); + if (!squares_mod_65[FN_to_UL(div65.remainder)]) + { return cl_false; } // not a square mod 65 -> not a square + } + // Check mod 11. + { var cl_I_div_t div11 = cl_divide(x,L_to_FN(11)); + if (!squares_mod_11[FN_to_UL(div11.remainder)]) + { return cl_false; } // not a square mod 11 -> not a square + } + // Check with full precision. + { var DS y; + var cl_boolean squarep; + UDS_sqrt(x_MSDptr,x_len,x_LSDptr, &y, squarep=); // Wurzel ziehen + if (squarep) + { *w = NUDS_to_I(y.MSDptr,y.len); } // als Integer + return squarep; + } } +} +// Bit complexity (x of length N): O(M(N)). + diff --git a/src/integer/bitwise/Makeflags b/src/integer/bitwise/Makeflags new file mode 100644 index 0000000..3696f90 --- /dev/null +++ b/src/integer/bitwise/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/integer/Makeflags +SUBDIR_INCLUDES += diff --git a/src/integer/bitwise/cl_I_ash.cc b/src/integer/bitwise/cl_I_ash.cc new file mode 100644 index 0000000..388697f --- /dev/null +++ b/src/integer/bitwise/cl_I_ash.cc @@ -0,0 +1,88 @@ +// ash(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" +#include "cl_I_ash.h" + +const cl_I ash (const cl_I& x, sintL y) +{ + // Methode: + // x = 0 -> 0 als Ergebnis + // y = 0 -> x als Ergebnis + // y > 0 -> y = intDsize*k + i, j=k+(1 falls i>0, 0 falls i=0). + // j Wörter mehr reservieren, k Nullwörter, dann übertragen, + // bei i>0: um i Bits links schieben (i=1 geht einfacher). + // y < 0 -> y <= - intDsize * (Länge(A0) in Digits) -> Ergebnis = 0 oder -1. + // Sonst: -y = intDsize*k + i mit k0: schiebe sie um i Bits nach rechts (i=1 geht einfacher). + if (zerop(x)) + return 0; // x=0 -> 0 als Ergebnis + if (y == 0) + return x; // y=0 -> x als Ergebnis + CL_ALLOCA_STACK; + if (y >= 0) { + // y>0 + var uintL y_ = (uintL)y; + var uintL i = y_%intDsize; // i = y mod intDsize, >=0, =0, <2^intCsize + var uintD* LSDptr; + var uintC len; + var const uintD* x_LSDptr; + I_to_NDS_nocopy(x, ,len=,x_LSDptr=,cl_false,); // DS zu x bilden. + if (k >= (uintC)(~(uintC)len)) // kann len+k+1 Überlauf geben? + { cl_ash_error(y); } // ja -> Fehler + num_stack_alloc_1(len+k,,LSDptr=); + LSDptr = clear_loop_lsp(LSDptr,k); // k Nulldigits + {var uintD* MSDptr = copy_loop_lsp(x_LSDptr,LSDptr,len); + // Nun ist MSDptr/len/LSDptr die DS zu x. + // Oberhalb von ihr liegen k Nulldigits, unterhalb ist 1 Digit Platz. + // MSDptr/len+k/.. ist jetzt die Gesamt-DS. + // Noch um i Bits nach links schieben: + if (!(i==0)) // Bei i>0 + { // noch ein weiteres Digit dazunehmen (Vorzeichen) + {var uintD sign = sign_of_sintD(mspref(MSDptr,0)); + lsprefnext(MSDptr) = sign; + len++; + } + // Schiebeschleife: die unteren len Digits um i Bits schieben + if (i==1) + { shift1left_loop_lsp(LSDptr,len); } + else + { shiftleft_loop_lsp(LSDptr,len,i,0); } + } + return DS_to_I(MSDptr,len+k); + } + } else { + // y<0 + var uintL y_ = (uintL)(-y); // Wert von -y, >0 + var uintL i = y_%intDsize; // i = (-y) mod intDsize, >=0, =0 + // DS zu x bilden: + var uintD* MSDptr; + var uintC len; + I_to_NDS(x, MSDptr=,len=,); // DS zu x bilden. + if (k>=len) goto sign; // -y >= intDsize*len -> Vorzeichen von x zurück + len -= k; // rechte k Digits einfach streichen + // Noch ist len>0. Um i Bits nach rechts schieben: + if (!(i==0)) // Bei i>0: + { // Schiebe len Digits ab MSDptr um i Bits nach rechts: + if (i==1) + { shift1right_loop_msp(MSDptr,len,sign_of_sintD(mspref(MSDptr,0))); } + else + { shiftrightsigned_loop_msp(MSDptr,len,i); } + } + return DS_to_I(MSDptr,len); + } +sign: // Ergebnis ist 0, falls x>=0, und -1, falls x<0: + return (minusp(x) ? cl_I(-1) : cl_I(0)); +} diff --git a/src/integer/bitwise/cl_I_ash.h b/src/integer/bitwise/cl_I_ash.h new file mode 100644 index 0000000..d820b1a --- /dev/null +++ b/src/integer/bitwise/cl_I_ash.h @@ -0,0 +1,12 @@ +// cl_I internals for ash + +#ifndef _CL_I_ASH_H +#define _CL_I_ASH_H + +#include "cl_number.h" +#include "cl_integer_class.h" +#include "cl_macros.h" + +nonreturning_function(extern, cl_ash_error, (const cl_I& badamount)); + +#endif /* _CL_I_ASH_H */ diff --git a/src/integer/bitwise/cl_I_ash_I.cc b/src/integer/bitwise/cl_I_ash_I.cc new file mode 100644 index 0000000..8ff1a56 --- /dev/null +++ b/src/integer/bitwise/cl_I_ash_I.cc @@ -0,0 +1,169 @@ +// ash(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" +#include "cl_I_ash.h" + +const cl_I ash (const cl_I& x, const cl_I& y) +{ + // Methode: + // x = 0 -> 0 als Ergebnis + // y = 0 -> x als Ergebnis + // y > 0 -> y = intDsize*k + i, j=k+(1 falls i>0, 0 falls i=0). + // j Wörter mehr reservieren, k Nullwörter, dann übertragen, + // bei i>0: um i Bits links schieben (i=1 geht einfacher). + // y < 0 -> y <= - intDsize * (Länge(A0) in Digits) -> Ergebnis = 0 oder -1. + // Sonst: -y = intDsize*k + i mit k0: schiebe sie um i Bits nach rechts (i=1 geht einfacher). + if (zerop(x)) + return 0; // x=0 -> 0 als Ergebnis + if (zerop(y)) + return x; // y=0 -> x als Ergebnis + CL_ALLOCA_STACK; + if (!minusp(y)) { + // y>=0 + var uintL i; // i = y mod intDsize, >=0, =0, <2^intCsize + if (bignump(y)) { + #if (log2_intDsize+intCsize <= cl_value_len-1) + // y >= 2^(cl_value_len-1) >= intDsize*2^intCsize + cl_ash_error(y); + #else + // y >= 2^(cl_value_len-1) + // usable only if y < intDsize*2^intCsize + var cl_heap_bignum* bn = TheBignum(y); + var uintC len = bn->length; + if (len > ceiling(log2_intDsize+intCsize+1,intDsize)) + cl_ash_error(y); + // bn_minlength <= len <= ceiling(log2_intDsize+intCsize+1,intDsize). + if (bn_minlength == ceiling(log2_intDsize+intCsize+1,intDsize) + || len == ceiling(log2_intDsize+intCsize+1,intDsize)) + if (mspref(arrayMSDptr(bn->data,len),0) >= (uintD)bit((log2_intDsize+intCsize)%intDsize)) + cl_ash_error(y); + #define IF_LENGTH(i) \ + if (bn_minlength <= i && i <= ceiling(log2_intDsize+intCsize+1,intDsize) && (i == ceiling(log2_intDsize+intCsize+1,intDsize) || len == i)) + IF_LENGTH(1) + k = 0; + else IF_LENGTH(2) + k = get_uint1D_Dptr(arrayLSDptr(bn->data,2) lspop 1); + else IF_LENGTH(3) + k = get_uint2D_Dptr(arrayLSDptr(bn->data,3) lspop 1); + else IF_LENGTH(4) + k = get_uint3D_Dptr(arrayLSDptr(bn->data,4) lspop 1); + else IF_LENGTH(5) + k = get_uint4D_Dptr(arrayLSDptr(bn->data,5) lspop 1); + else + cl_abort(); + #undef IF_LENGTH + k = k << (intDsize-log2_intDsize); + k |= lspref(arrayLSDptr(bn->data,len),0) >> log2_intDsize; + i = lspref(arrayLSDptr(bn->data,len),0) % intDsize; + #endif + } else { + var uintL y_ = FN_to_L(y); // Wert von y, >=0, = (uintC)(~(uintC)len)) // kann len+k+1 Überlauf geben? + { cl_ash_error(y); } // ja -> Fehler + num_stack_alloc_1(len+k,,LSDptr=); + LSDptr = clear_loop_lsp(LSDptr,k); // k Nulldigits + var uintD* MSDptr = copy_loop_lsp(x_LSDptr,LSDptr,len); + // Nun ist MSDptr/len/LSDptr die DS zu x. + // Oberhalb von ihr liegen k Nulldigits, unterhalb ist 1 Digit Platz. + // MSDptr/len+k/.. ist jetzt die Gesamt-DS. + // Noch um i Bits nach links schieben: + if (!(i==0)) // Bei i>0 + { // noch ein weiteres Digit dazunehmen (Vorzeichen) + {var uintD sign = sign_of_sintD(mspref(MSDptr,0)); + lsprefnext(MSDptr) = sign; + len++; + } + // Schiebeschleife: die unteren len Digits um i Bits schieben + if (i==1) + { shift1left_loop_lsp(LSDptr,len); } + else + { shiftleft_loop_lsp(LSDptr,len,i,0); } + } + return DS_to_I(MSDptr,len+k); + } else { + // y<0 + var uintL i; // i = (-y) mod intDsize, >=0, =0, <2^intCsize + if (bignump(y)) { + #if (log2_intDsize+intCsize <= cl_value_len-1) + // -y-1 >= 2^(cl_value_len-1) >= intDsize*2^intCsize + goto sign; + #else + // -y-1 >= 2^(cl_value_len-1) + // usable only if -y-1 < intDsize*2^intCsize + // We write -y-1 = lognot(y) = k*intDsize+i and then add 1. + var cl_heap_bignum* bn = TheBignum(y); + var uintC len = bn->length; + if (len > ceiling(log2_intDsize+intCsize+1,intDsize)) + goto sign; + // bn_minlength <= len <= ceiling(log2_intDsize+intCsize+1,intDsize). + if (bn_minlength == ceiling(log2_intDsize+intCsize+1,intDsize) + || len == ceiling(log2_intDsize+intCsize+1,intDsize)) + if (mspref(arrayMSDptr(bn->data,len),0) < (uintD)(-bit((log2_intDsize+intCsize)%intDsize))) + goto sign; + #define IF_LENGTH(i) \ + if (bn_minlength <= i && i <= ceiling(log2_intDsize+intCsize+1,intDsize) && (i == ceiling(log2_intDsize+intCsize+1,intDsize) || len == i)) + IF_LENGTH(1) + k = 0; + else IF_LENGTH(2) + k = ~get_sint1D_Dptr(arrayLSDptr(bn->data,2) lspop 1); + else IF_LENGTH(3) + k = ~get_sint2D_Dptr(arrayLSDptr(bn->data,3) lspop 1); + else IF_LENGTH(4) + k = ~get_sint3D_Dptr(arrayLSDptr(bn->data,4) lspop 1); + else IF_LENGTH(5) + k = ~get_sint4D_Dptr(arrayLSDptr(bn->data,5) lspop 1); + else + cl_abort(); + #undef IF_LENGTH + k = k << (intDsize-log2_intDsize); + k |= (uintD)(~lspref(arrayLSDptr(bn->data,len),0)) >> log2_intDsize; + i = (uintD)(-lspref(arrayLSDptr(bn->data,len),0)) % intDsize; + if (i == 0) + if (++k == 0) + goto sign; + #endif + } else { + var uintL y_ = -FN_to_L(y); // Wert von -y, >0, =len) goto sign; // -y >= intDsize*len -> Vorzeichen von x zurück + len -= k; // rechte k Digits einfach streichen + // Noch ist len>0. Um i Bits nach rechts schieben: + if (!(i==0)) // Bei i>0: + { // Schiebe len Digits ab MSDptr um i Bits nach rechts: + if (i==1) + { shift1right_loop_msp(MSDptr,len,sign_of_sintD(mspref(MSDptr,0))); } + else + { shiftrightsigned_loop_msp(MSDptr,len,i); } + } + return DS_to_I(MSDptr,len); + } +sign: // Ergebnis ist 0, falls x>=0, und -1, falls x<0: + return (minusp(x) ? cl_I(-1) : cl_I(0)); +} diff --git a/src/integer/bitwise/cl_I_asherr.cc b/src/integer/bitwise/cl_I_asherr.cc new file mode 100644 index 0000000..7ec6c2f --- /dev/null +++ b/src/integer/bitwise/cl_I_asherr.cc @@ -0,0 +1,23 @@ +// cl_ash_error(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I_ash.h" + + +// Implementation. + +#include "cl_number.h" +#include "cl_io.h" +#include "cl_integer_io.h" +#include "cl_abort.h" + +void cl_ash_error (const cl_I& badamount) +{ + fprint(cl_stderr, "ash: too large shift amount: "); + fprint(cl_stderr, badamount); + fprint(cl_stderr, "\n"); + cl_abort(); +} diff --git a/src/integer/bitwise/cl_I_boole.cc b/src/integer/bitwise/cl_I_boole.cc new file mode 100644 index 0000000..7e69c25 --- /dev/null +++ b/src/integer/bitwise/cl_I_boole.cc @@ -0,0 +1,50 @@ +// boole(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +const cl_I boole (cl_boole op, const cl_I& x, const cl_I& y) +{ + switch (op) { + case boole_clr: + return 0; + case boole_set: + return -1; + case boole_1: + return x; + case boole_2: + return y; + case boole_c1: + return lognot(x); + case boole_c2: + return lognot(y); + case boole_and: + return logand(x,y); + case boole_ior: + return logior(x,y); + case boole_xor: + return logxor(x,y); + case boole_eqv: + return logeqv(x,y); + case boole_nand: + return lognand(x,y); + case boole_nor: + return lognor(x,y); + case boole_andc1: + return logandc1(x,y); + case boole_andc2: + return logandc2(x,y); + case boole_orc1: + return logorc1(x,y); + case boole_orc2: + return logorc2(x,y); + default: + NOTREACHED + } +} diff --git a/src/integer/bitwise/cl_I_byte.h b/src/integer/bitwise/cl_I_byte.h new file mode 100644 index 0000000..370db10 --- /dev/null +++ b/src/integer/bitwise/cl_I_byte.h @@ -0,0 +1,29 @@ +// cl_I internals for BYTE operations + +#ifndef _CL_I_BYTE_H +#define _CL_I_BYTE_H + +#include "cl_number.h" +#include "cl_integer_class.h" + +// cl_fullbyte(p,q) liefert zu p,q die Zahl 2^q-2^p als Integer, +// wobei p und q uintL sind. Bei p<=q ist das Ergebnis also +// ein Integer >=0, bei dem genau die Bits p,...,q-1 gesetzt sind. +extern const cl_I cl_fullbyte (uintL p, uintL q); + +// Extrahiere die Bits p,...,q-1 der Zahl x, +// wobei 0 <= p <= q <= l = (integer-length x). +// Ergebnis (wie bei LDB) ein Integer >=0. +extern const cl_I ldb_extract (const cl_I& x, uintL p, uintL q); + +// Teste, ob eines der Bits p,...,q-1 der Zahl x /=0 ist, +// wobei 0 <= p <= q <= l = (integer-length x). +// Ergebnis (wie bei LDB-TEST) cl_false wenn nein, cl_true wenn ja. +extern cl_boolean ldb_extract_test (const cl_I& x, uintL p, uintL q); + +// Extrahiere die Bits p,...,q-1 der Zahl x, +// wobei 0 <= p <= q <= l = (integer-length x). +// Ergebnis (wie bei MASK-FIELD) ein Integer >=0. +extern const cl_I mkf_extract (const cl_I& x, uintL p, uintL q); + +#endif /* _CL_I_BYTE_H */ diff --git a/src/integer/bitwise/cl_I_dpb.cc b/src/integer/bitwise/cl_I_dpb.cc new file mode 100644 index 0000000..fc64225 --- /dev/null +++ b/src/integer/bitwise/cl_I_dpb.cc @@ -0,0 +1,21 @@ +// dpb(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_integer.h" +#include "cl_I.h" + +const cl_I dpb (const cl_I& newbyte, const cl_I& n, const cl_byte& b) +{ + // Methode: + // (DPB newbyte (byte s p) integer) + // = (DEPOSIT-FIELD (ASH newbyte p) (byte s p) integer) + return deposit_field(ash(newbyte,b.position),n,b); +} diff --git a/src/integer/bitwise/cl_I_dpf.cc b/src/integer/bitwise/cl_I_dpf.cc new file mode 100644 index 0000000..7597853 --- /dev/null +++ b/src/integer/bitwise/cl_I_dpf.cc @@ -0,0 +1,24 @@ +// deposit_field(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_integer.h" +#include "cl_I.h" + +const cl_I deposit_field (const cl_I& newbyte, const cl_I& n, const cl_byte& b) +{ + // Methode: + // (DEPOSIT-FIELD newbyte (byte s p) integer) + // = (logxor integer + // (ash (logxor (ldb (byte s p) newbyte) (ldb (byte s p) integer)) + // p + // ) ) + return logxor(n, ash(logxor(ldb(newbyte,b),ldb(n,b)), b.position)); +} diff --git a/src/integer/bitwise/cl_I_fullbyte.cc b/src/integer/bitwise/cl_I_fullbyte.cc new file mode 100644 index 0000000..593378f --- /dev/null +++ b/src/integer/bitwise/cl_I_fullbyte.cc @@ -0,0 +1,21 @@ +// cl_fullbyte(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I_byte.h" + + +// Implementation. + +#include "cl_integer.h" +#include "cl_I.h" + +const cl_I cl_fullbyte (uintL p, uintL q) +{ + if (p==q) + return 0; + else + return ash(-1,UL_to_I(p)) + ash(1,UL_to_I(q)); +} diff --git a/src/integer/bitwise/cl_I_ilength.cc b/src/integer/bitwise/cl_I_ilength.cc new file mode 100644 index 0000000..00e17aa --- /dev/null +++ b/src/integer/bitwise/cl_I_ilength.cc @@ -0,0 +1,38 @@ +// integer_length(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" + +uintL integer_length (const cl_I& x) +{ + if (fixnump(x)) + { var uintL bitcount = 0; + var uint32 x_ = FN_to_L(x); // x als 32-Bit-Zahl + if (FN_L_minusp(x,(sint32)x_)) { x_ = ~ x_; } // falls <0, komplementieren + if (!(x_==0)) { integerlength32(x_,bitcount=); } + return bitcount; // 0 <= bitcount < 32. + } + else + { var const uintD* MSDptr; + var uintC len; + BN_to_NDS_nocopy(x, MSDptr=,len=,); // normalisierte DS zu x bilden. + var uintL bitcount = intDsize*(uintL)(len-1); // Anzahl Digits mal intDsize + // MSDigit nehmen, testen, welches das höchste Bit ist, das vom + // Vorzeichenbit abweicht: + var uintD msd = mspref(MSDptr,0); // MSDigit + if ((sintD)msd < 0) { msd = ~msd; } // falls negativ, invertieren + // Position des höchsten Bits in msd suchen und entsprechend bit_count + // erhöhen (um höchstens intDsize-1): + if (!(msd == 0)) { integerlengthD(msd, bitcount += ); } + return bitcount; // 0 <= bitcount < intDsize*2^intCsize. + } +} diff --git a/src/integer/bitwise/cl_I_ldb.cc b/src/integer/bitwise/cl_I_ldb.cc new file mode 100644 index 0000000..dd94d5c --- /dev/null +++ b/src/integer/bitwise/cl_I_ldb.cc @@ -0,0 +1,48 @@ +// ldb(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_integer.h" +#include "cl_I.h" +#include "cl_I_byte.h" + +const cl_I ldb (const cl_I& n, const cl_byte& b) +{ + // Methode: + // (ldb (byte s p) n) extrahiere die Bits p,...,p+s-1 von n. + // l:=(integer-length n) + // Falls l <= p : + // Falls n>=0: 0, falls n<0: 2^s - 1 (s Einsenbits). + // Falls p <= l : + // q:=min(p+s,l). + // Extrahiere die Bits p,...,q-1 von n. + // Falls p+s>l und n<0, füge p+s-l Einsenbits an (addiere 2^s-2^(l-p)). + var uintL s = b.size; + var uintL p = b.position; + var uintL l = integer_length(n); // l = (integer-length n) + if (l<=p) + // l<=p + if (!minusp(n)) + // n>=0 + return 0; // 0 als Ergebnis + else + // n<0 + return cl_fullbyte(0,s); // 2^s-2^0 als Ergebnis + else + // l>p + { var cl_I erg = ldb_extract(n,p,(p+slp) && minusp(n)) // s>l-p und n<0 ? + { return logior(erg,cl_fullbyte(lp,s)); } // setze Bits l-p,...,s-1 + // (logisches Exklusiv-Oder oder Addition ginge auch) + else + return erg; + } +} diff --git a/src/integer/bitwise/cl_I_ldbtest.cc b/src/integer/bitwise/cl_I_ldbtest.cc new file mode 100644 index 0000000..2c9653c --- /dev/null +++ b/src/integer/bitwise/cl_I_ldbtest.cc @@ -0,0 +1,48 @@ +// ldb_test(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_integer.h" +#include "cl_I.h" +#include "cl_I_byte.h" + +cl_boolean ldb_test (const cl_I& n, const cl_byte& b) +{ + // Methode: + // (ldb-test (byte s p) n) + // Falls s=0: =0. + // Falls s>0: + // l:=(integer-length n) + // Falls l <= p : Falls n>=0, =0, denn Bits p+s-1..p sind =0. + // Falls n<0, /=0, denn Bits p+s-1..p sind =1. + // Falls p < l : + // Falls p+s>l, /=0, denn bei n>=0 ist Bit l-1 =1, + // und bei n<0 sind Bits p+s-1..l =1. + // Falls p+s<=l, + // extrahiere die Bits p,...,p+s-1 von n und teste sie. + var uintL s = b.size; + var uintL p = b.position; + if (s==0) return cl_false; + var uintL l = integer_length(n); // l = (integer-length n) + if (l<=p) + // l<=p + if (!minusp(n)) + return cl_false; // n>=0 + else + return cl_true; // n<0 + else + // l>p + { var uintL ps = p+s; + if (ps>l) // p+s>l ? + return cl_true; + // Bits p,...,q-1 mit q = min(p+s,l) = p+s extrahieren und testen: + return ldb_extract_test(n,p,ps); + } +} diff --git a/src/integer/bitwise/cl_I_ldbx.cc b/src/integer/bitwise/cl_I_ldbx.cc new file mode 100644 index 0000000..587f9f2 --- /dev/null +++ b/src/integer/bitwise/cl_I_ldbx.cc @@ -0,0 +1,56 @@ +// ldb_extract(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I_byte.h" + + +// Implementation. + +#include "cl_integer.h" +#include "cl_I.h" +#include "cl_DS.h" + +const cl_I ldb_extract (const cl_I& x, uintL p, uintL q) + { CL_ALLOCA_STACK; + var const uintD* MSDptr; + var uintC len; + var const uintD* LSDptr; + I_to_NDS_nocopy(x, MSDptr=,len=,LSDptr=,cl_true, { return 0; } ); // NDS zu x bilden + // MSDptr erhöhen und len erniedrigen, so daß len = ceiling(q/intDsize) wird: + { var uintL qD = ceiling(q,intDsize); // ceiling(q/intDsize) + // wegen q<=l ist qD = ceiling(q/intDsize) <= ceiling((l+1)/intDsize) = len, also + // paßt qD ebenso wie len in ein uintC. + MSDptr = MSDptr mspop ((uintL)len - qD); // MSDptr um len-qD Digits erhöhen + len = qD; // len um len-qD erniedrigen + } + // LSDptr und len um floor(p/intDsize) erniedrigen: + { var uintL pD = floor(p,intDsize); // floor(p/intDsize) + LSDptr = LSDptr lspop pD; + len -= pD; + } + // Jetzt enthält MSDptr/len/LSDptr genau die maßgeblichen Digits. + var uintD* newMSDptr; + { var uintL i = p%intDsize; // p mod intDsize + // Kopiere sie und schiebe sie dabei um i Bits nach rechts: + num_stack_alloc_1((uintL)len, newMSDptr=,); // neue UDS newMSDptr/len/.. + if (i==0) + { copy_loop_msp(MSDptr,newMSDptr,len); } + else + { shiftrightcopy_loop_msp(MSDptr,newMSDptr,len,i,0); } + } + // newMSDptr/len/.. = geschobene Kopie der maßgeblichen Digits + // Ausblenden der Bits mit Nummern >= q-p: + { var uintL bitcount = intDsize*(uintL)len - (q-p); + // Anzahl vorne auszublendender Bits ( >=0, <= intDsize-1 + intDsize-1 ) + if (bitcount>=intDsize) + { bitcount -= intDsize; msshrink(newMSDptr); len -= 1; } // intDsize Bits ausblenden + // Noch 0 <= bitcount < intDsize Bits auszublenden: + if (bitcount > 0) + { mspref(newMSDptr,0) &= (uintD)(bit(intDsize-bitcount)-1); } + } + // Jetzt enthält die UDS newMSDptr/len/.. die extrahierten Bits. + return UDS_to_I(newMSDptr,len); // UDS in Integer umwandeln + } diff --git a/src/integer/bitwise/cl_I_ldbxtest.cc b/src/integer/bitwise/cl_I_ldbxtest.cc new file mode 100644 index 0000000..75678a3 --- /dev/null +++ b/src/integer/bitwise/cl_I_ldbxtest.cc @@ -0,0 +1,57 @@ +// ldb_extract_test(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I_byte.h" + + +// Implementation. + +#include "cl_integer.h" +#include "cl_I.h" +#include "cl_DS.h" + +cl_boolean ldb_extract_test (const cl_I& x, uintL p, uintL q) + { var const uintD* MSDptr; + var uintC len; + var const uintD* LSDptr; + I_to_NDS_nocopy(x, MSDptr=,len=,LSDptr=,cl_true, { return cl_false; } ); // NDS zu x bilden + // MSDptr erhöhen und len erniedrigen, so daß len = ceiling(q/intDsize) wird: + { var uintL qD = ceiling(q,intDsize); // ceiling(q/intDsize) + // wegen q<=l ist qD = ceiling(q/intDsize) <= ceiling((l+1)/intDsize) = len, also + // paßt qD ebenso wie len in ein uintC. + MSDptr = MSDptr mspop ((uintL)len - qD); // MSDptr um len-qD Digits erhöhen + len = qD; // len um len-qD erniedrigen + } + // LSDptr und len um floor(p/intDsize) erniedrigen: + { var uintL pD = p/intDsize; // floor(p/intDsize) + LSDptr = LSDptr lspop pD; + len -= pD; + } + // Jetzt enthält MSDptr/len/LSDptr genau die maßgeblichen Digits. + if (len==0) return cl_false; // len=0 -> keine Bits abzutesten + q = ((q-1)%intDsize); // q := intDsize - (intDsize*ceiling(q/intDsize) - q) - 1 + p = p%intDsize; // p := p - intDsize*floor(p/intDsize) + // Jetzt ist 0 <= q < intDsize, 0 <= p < intDsize. + // Vom ersten Digit müssen die vorderen intDsize-1-q Bits unberücksichtigt bleiben. + // Ein AND 2^(q+1)-1 erreicht dies. + // Vom letzten Digit müssen die hinteren p Bits unberücksichtigt bleiben. + // Ein AND -2^p erreicht dies. + if (--len==0) + // 1 Digit maßgeblich, wird von beiden Seiten angeschnitten: + // Ein AND 2^(q+1)-2^p erreicht dies. + if (!(((uintD)(bitm(q+1)-bit(p)) & mspref(MSDptr,0)) == 0)) + return cl_true; + else + return cl_false; + // mindestens 2 Digits. Teste erst die Randdigits, dann die inneren: + if (!(((msprefnext(MSDptr) & (uintD)(bitm(q+1)-1)) == 0) && + ((lsprefnext(LSDptr) & (uintD)(minus_bit(p))) == 0) + ) ) + return cl_true; + len--; // die beiden Randdigits sind jetzt abgezogen. + if (DS_test_loop(MSDptr,len,LSDptr)) { return cl_true; } else { return cl_false; } + } + diff --git a/src/integer/bitwise/cl_I_log.h b/src/integer/bitwise/cl_I_log.h new file mode 100644 index 0000000..a424cfe --- /dev/null +++ b/src/integer/bitwise/cl_I_log.h @@ -0,0 +1,34 @@ +// cl_I internals for logical operations + +#ifndef _CL_I_LOG_H +#define _CL_I_LOG_H + +#include "cl_number.h" +#include "cl_I.h" +#include "cl_DS.h" + +// Liefert die Anzahl Digits, die ein Integer als DS bräuchte. +// (Leicht aufgerundet.) +inline uintC I_to_DS_need (const cl_I& x) +{ + if (fixnump(x)) + return FN_maxlength; // das wird reichen + else + return TheBignum(x)->length; +} + +// Integer to Digit sequence, n Digits +// I_to_DS_n(obj,n,ptr=); +// Integer obj zu einer Digit sequence MSDptr/n/LSDptr machen, +// die genau n Digits hat (sollte n >= Bedarf und >= FN_maxlength sein). +// Die neue Digit-sequence darf modifiziert werden. +// < ptr: MSDptr der neuen DS +// Dabei wird num_stack erniedrigt. + #define I_to_DS_n(obj,n,ptr_zuweisung) \ + {var uintD* destptr; \ + num_stack_alloc(n,,destptr=); \ + ptr_zuweisung I_to_DS_n_aux(obj,n,destptr); \ + } + extern uintD* I_to_DS_n_aux (const cl_I& obj, uintC n, uintD* destptr); + +#endif /* _CL_I_LOG_H */ diff --git a/src/integer/bitwise/cl_I_log_aux.cc b/src/integer/bitwise/cl_I_log_aux.cc new file mode 100644 index 0000000..f6dcaf4 --- /dev/null +++ b/src/integer/bitwise/cl_I_log_aux.cc @@ -0,0 +1,53 @@ +// I_to_DS_n_aux(). +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I_log.h" + + +// Implementation. + +#include "cl_number.h" +#include "cl_I.h" +#include "cl_DS.h" + +uintD* I_to_DS_n_aux (const cl_I& obj, uintC n, uintD* destptr) + { // Nun sind unterhalb von destptr n Digits Platz. + // oberen Teil der DS aus obj füllen, dabei destptr erniedrigen: + if (fixnump(obj)) + // Fixnum: + { + #if (intDsize==64) // && (FN_maxlength==1) + lsprefnext(destptr) = FN_to_Q(obj); + #else // (intDsize<=32) + var uint32 wert = FN_to_L(obj); + #define FN_maxlength_a (intLsize/intDsize) + #define FN_maxlength_b (FN_maxlength<=FN_maxlength_a ? FN_maxlength : FN_maxlength_a) + // FN_maxlength Digits ablegen. Davon kann man FN_maxlength_b Digits aus wert nehmen. + #if (FN_maxlength_b > 1) + doconsttimes(FN_maxlength_b-1, + lsprefnext(destptr) = (uintD)wert; wert = wert >> intDsize; + ); + #endif + lsprefnext(destptr) = (uintD)wert; + #if (FN_maxlength > FN_maxlength_b) + // Es ist oint_data_len = intLsize, brauche + // noch FN_maxlength-FN_maxlength_b = 1 Digit. + lsprefnext(destptr) = (sintD)sign_of(FN_to_L(obj)); + #endif + #endif + n -= FN_maxlength; + } + else + // Bignum: + { var uintC len = TheBignum(obj)->length; + n -= len; + destptr = copy_loop_lsp(BN_LSDptr(obj),destptr,len); // DS kopieren + } + // unteren Teil mit Fülldigits, gebildet aus dem Vorzeichen, füllen: + if (!(n==0)) + { destptr = fill_loop_lsp(destptr,n,sign_of_sintD(mspref(destptr,0))); } + // destptr zeigt nun aufs untere Ende der DS. + return destptr; + } diff --git a/src/integer/bitwise/cl_I_logand.cc b/src/integer/bitwise/cl_I_logand.cc new file mode 100644 index 0000000..e7b4ccc --- /dev/null +++ b/src/integer/bitwise/cl_I_logand.cc @@ -0,0 +1,51 @@ +// logand(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" +#include "cl_I_log.h" + +// Logische Operationen auf Integers: +// Methode: aus den Längen der beiden Argumente eine obere Schranke für +// die Länge des Ergebnisses berechnen (das Maximum der beiden Längen und +// FN_maxlength), so daß das MSD für unendlich viele Bits steht. +// Dann beide Argumente in gleichgroße Digit sequences umwandeln, Operation +// mit einer einfachen Schleife durchführen. + +const cl_I logand (const cl_I& x, const cl_I& y) + { if (fixnump(x) && fixnump(y)) // Beides Fixnums -> ganz einfach: + { // bitweise als Fixnum zurück + return cl_I_from_word(x.word & y.word); + } + if (fixnump(x)) + { DeclareType(cl_FN,x); + if (!minusp(x)) + // PosFixnum AND Bignum -> PosFixnum + { return cl_I_from_word(x.word & cl_combine(cl_FN_tag,pFN_maxlength_digits_at(BN_LSDptr(y)))); } + } + if (fixnump(y)) + { DeclareType(cl_FN,y); + if (!minusp(y)) + // Bignum AND PosFixnum -> PosFixnum + { return cl_I_from_word(cl_combine(cl_FN_tag,pFN_maxlength_digits_at(BN_LSDptr(x))) & y.word); } + } + { CL_ALLOCA_STACK; + var uintC n; // Anzahl der Digits + {var uintC nx = I_to_DS_need(x); + var uintC ny = I_to_DS_need(y); + n = (nx>=ny ? nx : ny); + } + {var uintD* xptr; I_to_DS_n(x,n,xptr=); // Pointer in DS zu x + var uintD* yptr; I_to_DS_n(y,n,yptr=); // Pointer in DS zu y + var uintD* zptr = xptr; // Pointer aufs Ergebnis + and_loop_msp(xptr,yptr,n); // mit AND verknüpfen + return DS_to_I(zptr,n); // Ergebnis als Integer + } }} diff --git a/src/integer/bitwise/cl_I_logandc2.cc b/src/integer/bitwise/cl_I_logandc2.cc new file mode 100644 index 0000000..52e8457 --- /dev/null +++ b/src/integer/bitwise/cl_I_logandc2.cc @@ -0,0 +1,45 @@ +// logandc2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" +#include "cl_I_log.h" + +// Logische Operationen auf Integers: +// Methode: aus den Längen der beiden Argumente eine obere Schranke für +// die Länge des Ergebnisses berechnen (das Maximum der beiden Längen und +// FN_maxlength), so daß das MSD für unendlich viele Bits steht. +// Dann beide Argumente in gleichgroße Digit sequences umwandeln, Operation +// mit einer einfachen Schleife durchführen. + +const cl_I logandc2 (const cl_I& x, const cl_I& y) + { if (fixnump(x) && fixnump(y)) // Beides Fixnums -> ganz einfach: + { // bitweise als Fixnum zurück + return cl_I_from_word((x.word & ~ y.word) | cl_combine(cl_FN_tag,0)); + } + if (fixnump(x)) + { DeclareType(cl_FN,x); + if (!minusp(x)) + // PosFixnum AND Bignum -> PosFixnum + { return cl_I_from_word(x.word & ~ cl_combine(0,pFN_maxlength_digits_at(BN_LSDptr(y)))); } + } + { CL_ALLOCA_STACK; + var uintC n; // Anzahl der Digits + {var uintC nx = I_to_DS_need(x); + var uintC ny = I_to_DS_need(y); + n = (nx>=ny ? nx : ny); + } + {var uintD* xptr; I_to_DS_n(x,n,xptr=); // Pointer in DS zu x + var uintD* yptr; I_to_DS_n(y,n,yptr=); // Pointer in DS zu y + var uintD* zptr = xptr; // Pointer aufs Ergebnis + andc2_loop_msp(xptr,yptr,n); // mit AND NOT verknüpfen + return DS_to_I(zptr,n); // Ergebnis als Integer + } }} diff --git a/src/integer/bitwise/cl_I_logbitp.cc b/src/integer/bitwise/cl_I_logbitp.cc new file mode 100644 index 0000000..0353ee0 --- /dev/null +++ b/src/integer/bitwise/cl_I_logbitp.cc @@ -0,0 +1,37 @@ +// logbitp(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" + +cl_boolean logbitp (uintL x, const cl_I& y) +{ + // Methode: + // Falls x>=intDsize*Länge(y), teste Vorzeichen von y. + // Sonst x=intDsize*k+i, Teste Bit i vom Worte Nr. k+1 (von oben herab). + + var const uintD* yMSDptr; + var uintC ylen; + var const uintD* yLSDptr; + I_to_NDS_nocopy(y, yMSDptr=,ylen=,yLSDptr=,cl_true, { return cl_false; } ); // DS zu y + if (x < intDsize*(uintL)ylen) + // x ist >=0, < intDsize*ylen + { if (lspref(yLSDptr,floor(x,intDsize)) & bit(x%intDsize)) + return cl_true; + else + return cl_false; + } + // Vorzeichen von y testen + if (/* (ylen > 0) && */ ((sintD)mspref(yMSDptr,0) < 0)) + return cl_true; + else + return cl_false; +} diff --git a/src/integer/bitwise/cl_I_logbitp_I.cc b/src/integer/bitwise/cl_I_logbitp_I.cc new file mode 100644 index 0000000..2b58a56 --- /dev/null +++ b/src/integer/bitwise/cl_I_logbitp_I.cc @@ -0,0 +1,50 @@ +// logbitp(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" +#include "cl_io.h" +#include "cl_integer_io.h" +#include "cl_abort.h" + +cl_boolean logbitp (const cl_I& x, const cl_I& y) +{ + // Methode: + // Falls x<0, Error. + // Falls x>=0: Falls x>=intDsize*Länge(y), teste Vorzeichen von y. + // Sonst x=intDsize*k+i, Teste Bit i vom Worte Nr. k+1 (von oben herab). + if (!minusp(x)) // x>=0 ? + { if (fixnump(x)) + { var uintL x_ = FN_to_L(x); + var uintC ylen; + var const uintD* yLSDptr; + I_to_NDS_nocopy(y, ,ylen=,yLSDptr=,cl_true, { return cl_false; } ); // DS zu y + if (x_ < intDsize*(uintL)ylen) + // x ist ein Fixnum >=0, < intDsize*ylen + { if (lspref(yLSDptr,floor(x_,intDsize)) & bit(x_%intDsize)) + return cl_true; + else + return cl_false; + } } + // Vorzeichen von y testen + if (minusp(y)) + return cl_true; + else + return cl_false; + } + else + // x<0 + { fprint(cl_stderr, "logbitp: Index is negative: "); + fprint(cl_stderr, x); + fprint(cl_stderr, "\n"); + cl_abort(); + } +} diff --git a/src/integer/bitwise/cl_I_logcount.cc b/src/integer/bitwise/cl_I_logcount.cc new file mode 100644 index 0000000..50bf4db --- /dev/null +++ b/src/integer/bitwise/cl_I_logcount.cc @@ -0,0 +1,37 @@ +// logcount(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" +#include "cl_D.h" +#include "cl_low.h" + +uintL logcount (const cl_I& x) +{ + if (fixnump(x)) + { var uint32 x32 = FN_to_L(x); // x als 32-Bit-Zahl + if (FN_L_minusp(x,(sint32)x32)) { x32 = ~ x32; } // falls <0, komplementieren + logcount_32(); // Bits von x32 zählen + return x32; + } + else + { var const uintD* MSDptr; + var uintC len; + BN_to_NDS_nocopy(x, MSDptr=,len=,); // DS zu x bilden, len>0. + var uintL bitcount = 0; // Bitzähler + var const uintD* ptr = MSDptr; // läuft durch die Digits durch + var uintD sign = sign_of_sintD(mspref(ptr,0)); // Vorzeichen + dotimespC(len,len, + { bitcount += (uintL)logcountD(msprefnext(ptr) ^ sign); }); + // 0 <= bitcount < intDsize*2^intCsize. + return bitcount; + } +} diff --git a/src/integer/bitwise/cl_I_logeqv.cc b/src/integer/bitwise/cl_I_logeqv.cc new file mode 100644 index 0000000..904231a --- /dev/null +++ b/src/integer/bitwise/cl_I_logeqv.cc @@ -0,0 +1,40 @@ +// logeqv(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" +#include "cl_I_log.h" + +// Logische Operationen auf Integers: +// Methode: aus den Längen der beiden Argumente eine obere Schranke für +// die Länge des Ergebnisses berechnen (das Maximum der beiden Längen und +// FN_maxlength), so daß das MSD für unendlich viele Bits steht. +// Dann beide Argumente in gleichgroße Digit sequences umwandeln, Operation +// mit einer einfachen Schleife durchführen. + +const cl_I logeqv (const cl_I& x, const cl_I& y) + { if (fixnump(x) && fixnump(y)) // Beides Fixnums -> ganz einfach: + { // bitweise als Fixnum zurück + return cl_I_from_word(~(x.word ^ y.word) & cl_combine(cl_FN_tag,~(cl_uint)0)); + } + else + { CL_ALLOCA_STACK; + var uintC n; // Anzahl der Digits + {var uintC nx = I_to_DS_need(x); + var uintC ny = I_to_DS_need(y); + n = (nx>=ny ? nx : ny); + } + {var uintD* xptr; I_to_DS_n(x,n,xptr=); // Pointer in DS zu x + var uintD* yptr; I_to_DS_n(y,n,yptr=); // Pointer in DS zu y + var uintD* zptr = xptr; // Pointer aufs Ergebnis + eqv_loop_msp(xptr,yptr,n); // mit NOT XOR verknüpfen + return DS_to_I(zptr,n); // Ergebnis als Integer + } }} diff --git a/src/integer/bitwise/cl_I_logior.cc b/src/integer/bitwise/cl_I_logior.cc new file mode 100644 index 0000000..a2ee846 --- /dev/null +++ b/src/integer/bitwise/cl_I_logior.cc @@ -0,0 +1,40 @@ +// logior(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" +#include "cl_I_log.h" + +// Logische Operationen auf Integers: +// Methode: aus den Längen der beiden Argumente eine obere Schranke für +// die Länge des Ergebnisses berechnen (das Maximum der beiden Längen und +// FN_maxlength), so daß das MSD für unendlich viele Bits steht. +// Dann beide Argumente in gleichgroße Digit sequences umwandeln, Operation +// mit einer einfachen Schleife durchführen. + +const cl_I logior (const cl_I& x, const cl_I& y) + { if (fixnump(x) && fixnump(y)) // Beides Fixnums -> ganz einfach: + { // bitweise als Fixnum zurück + return cl_I_from_word(x.word | y.word); + } + else + { CL_ALLOCA_STACK; + var uintC n; // Anzahl der Digits + {var uintC nx = I_to_DS_need(x); + var uintC ny = I_to_DS_need(y); + n = (nx>=ny ? nx : ny); + } + {var uintD* xptr; I_to_DS_n(x,n,xptr=); // Pointer in DS zu x + var uintD* yptr; I_to_DS_n(y,n,yptr=); // Pointer in DS zu y + var uintD* zptr = xptr; // Pointer aufs Ergebnis + or_loop_msp(xptr,yptr,n); // mit OR verknüpfen + return DS_to_I(zptr,n); // Ergebnis als Integer + } }} diff --git a/src/integer/bitwise/cl_I_lognand.cc b/src/integer/bitwise/cl_I_lognand.cc new file mode 100644 index 0000000..2b4bd6f --- /dev/null +++ b/src/integer/bitwise/cl_I_lognand.cc @@ -0,0 +1,51 @@ +// lognand(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" +#include "cl_I_log.h" + +// Logische Operationen auf Integers: +// Methode: aus den Längen der beiden Argumente eine obere Schranke für +// die Länge des Ergebnisses berechnen (das Maximum der beiden Längen und +// FN_maxlength), so daß das MSD für unendlich viele Bits steht. +// Dann beide Argumente in gleichgroße Digit sequences umwandeln, Operation +// mit einer einfachen Schleife durchführen. + +const cl_I lognand (const cl_I& x, const cl_I& y) + { if (fixnump(x) && fixnump(y)) // Beides Fixnums -> ganz einfach: + { // bitweise als Fixnum zurück + return cl_I_from_word((x.word & y.word) ^ cl_combine(0,~(cl_uint)0)); + } + if (fixnump(x)) + { DeclareType(cl_FN,x); + if (!minusp(x)) + // PosFixnum AND Bignum -> PosFixnum + { return cl_I_from_word((x.word & cl_combine(0,pFN_maxlength_digits_at(BN_LSDptr(y)))) ^ cl_combine(cl_FN_tag,~(cl_uint)0)); } + } + if (fixnump(y)) + { DeclareType(cl_FN,y); + if (!minusp(y)) + // Bignum AND PosFixnum -> PosFixnum + { return cl_I_from_word((cl_combine(0,pFN_maxlength_digits_at(BN_LSDptr(x))) & y.word) ^ cl_combine(cl_FN_tag,~(cl_uint)0)); } + } + { CL_ALLOCA_STACK; + var uintC n; // Anzahl der Digits + {var uintC nx = I_to_DS_need(x); + var uintC ny = I_to_DS_need(y); + n = (nx>=ny ? nx : ny); + } + {var uintD* xptr; I_to_DS_n(x,n,xptr=); // Pointer in DS zu x + var uintD* yptr; I_to_DS_n(y,n,yptr=); // Pointer in DS zu y + var uintD* zptr = xptr; // Pointer aufs Ergebnis + nand_loop_msp(xptr,yptr,n); // mit NOT AND verknüpfen + return DS_to_I(zptr,n); // Ergebnis als Integer + } }} diff --git a/src/integer/bitwise/cl_I_lognor.cc b/src/integer/bitwise/cl_I_lognor.cc new file mode 100644 index 0000000..b1debf0 --- /dev/null +++ b/src/integer/bitwise/cl_I_lognor.cc @@ -0,0 +1,40 @@ +// lognor(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" +#include "cl_I_log.h" + +// Logische Operationen auf Integers: +// Methode: aus den Längen der beiden Argumente eine obere Schranke für +// die Länge des Ergebnisses berechnen (das Maximum der beiden Längen und +// FN_maxlength), so daß das MSD für unendlich viele Bits steht. +// Dann beide Argumente in gleichgroße Digit sequences umwandeln, Operation +// mit einer einfachen Schleife durchführen. + +const cl_I lognor (const cl_I& x, const cl_I& y) + { if (fixnump(x) && fixnump(y)) // Beides Fixnums -> ganz einfach: + { // bitweise als Fixnum zurück + return cl_I_from_word((x.word | y.word) ^ cl_combine(0,~(cl_uint)0)); + } + else + { CL_ALLOCA_STACK; + var uintC n; // Anzahl der Digits + {var uintC nx = I_to_DS_need(x); + var uintC ny = I_to_DS_need(y); + n = (nx>=ny ? nx : ny); + } + {var uintD* xptr; I_to_DS_n(x,n,xptr=); // Pointer in DS zu x + var uintD* yptr; I_to_DS_n(y,n,yptr=); // Pointer in DS zu y + var uintD* zptr = xptr; // Pointer aufs Ergebnis + nor_loop_msp(xptr,yptr,n); // mit NOT OR verknüpfen + return DS_to_I(zptr,n); // Ergebnis als Integer + } }} diff --git a/src/integer/bitwise/cl_I_lognot.cc b/src/integer/bitwise/cl_I_lognot.cc new file mode 100644 index 0000000..7ce1685 --- /dev/null +++ b/src/integer/bitwise/cl_I_lognot.cc @@ -0,0 +1,34 @@ +// lognot(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" +#include "cl_I_log.h" + +const cl_I lognot (const cl_I& x) + { if (fixnump(x)) // Fixnum -> ganz einfach: + { // bitweise als Fixnum zurück + return cl_I_from_word(x.word ^ cl_combine(0,~(cl_uint)0)); + } + else + // Bignum: + { CL_ALLOCA_STACK; + var uintD* MSDptr; + var uintC n; + BN_to_NDS(x, MSDptr=,n=,); // NDS zu x bilden + // Es ist n>=bn_minlength, + // und die ersten intDsize+1 Bit sind nicht alle gleich. + not_loop_msp(MSDptr,n); // mit NOT komplementieren, + // wegen n>0 wird auch das Vorzeichenbit umgedreht + // MSDptr/n/LSDptr ist immer noch eine NDS, da n>=bn_minlength + // und die ersten intDsize+1 Bit nicht alle gleich sind. + return NDS_to_I(MSDptr,n); // Ergebnis als Integer + } } diff --git a/src/integer/bitwise/cl_I_logorc2.cc b/src/integer/bitwise/cl_I_logorc2.cc new file mode 100644 index 0000000..ffa59b8 --- /dev/null +++ b/src/integer/bitwise/cl_I_logorc2.cc @@ -0,0 +1,40 @@ +// logorc2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" +#include "cl_I_log.h" + +// Logische Operationen auf Integers: +// Methode: aus den Längen der beiden Argumente eine obere Schranke für +// die Länge des Ergebnisses berechnen (das Maximum der beiden Längen und +// FN_maxlength), so daß das MSD für unendlich viele Bits steht. +// Dann beide Argumente in gleichgroße Digit sequences umwandeln, Operation +// mit einer einfachen Schleife durchführen. + +const cl_I logorc2 (const cl_I& x, const cl_I& y) + { if (fixnump(x) && fixnump(y)) // Beides Fixnums -> ganz einfach: + { // bitweise als Fixnum zurück + return cl_I_from_word((x.word | ~ y.word) & cl_combine(cl_FN_tag,~(cl_uint)0)); + } + else + { CL_ALLOCA_STACK; + var uintC n; // Anzahl der Digits + {var uintC nx = I_to_DS_need(x); + var uintC ny = I_to_DS_need(y); + n = (nx>=ny ? nx : ny); + } + {var uintD* xptr; I_to_DS_n(x,n,xptr=); // Pointer in DS zu x + var uintD* yptr; I_to_DS_n(y,n,yptr=); // Pointer in DS zu y + var uintD* zptr = xptr; // Pointer aufs Ergebnis + orc2_loop_msp(xptr,yptr,n); // mit OR NOT verknüpfen + return DS_to_I(zptr,n); // Ergebnis als Integer + } }} diff --git a/src/integer/bitwise/cl_I_logtest.cc b/src/integer/bitwise/cl_I_logtest.cc new file mode 100644 index 0000000..586b190 --- /dev/null +++ b/src/integer/bitwise/cl_I_logtest.cc @@ -0,0 +1,95 @@ +// logtest(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" + +cl_boolean logtest (const cl_I& x, const cl_I& y) +{ + // Methode: + // Fixnums separat behandeln. + // Sei oBdA x die kürzere der beiden Zahlen (in Digits). + // x echt kürzer und x<0 -> [eines der most signif. intDsize+1 Bits von y ist 1] Ja. + // Beide gleich lang oder x>=0 -> + // Kann mich auf die untersten length(x) Digits beschraenken. + // Mit AND durchlaufen, abbrechen (mit "Ja") falls /=0. Am Ende: Nein. + if (fixnump(x)) + if (fixnump(y)) + // beides Fixnums + { if ((x.word & y.word & cl_combine(0,~(cl_uint)0))==0) + return cl_false; + else + return cl_true; + } + else + // x Fixnum, y Bignum, also ist x echt kürzer + { if (FN_L_minusp(x,FN_to_L(x))) return cl_true; // x<0 -> ja. + // x>=0. Kombiniere x mit den pFN_maxlength letzten Digits von y. + {var const uintD* yLSDptr; + var uintL x_ = FN_to_L(x); + BN_to_NDS_nocopy(y, ,,yLSDptr=); + #if (pFN_maxlength > 1) + doconsttimes(pFN_maxlength-1, + if (lsprefnext(yLSDptr) & (uintD)x_) return cl_true; + x_ = x_ >> intDsize; + ); + #endif + if (lsprefnext(yLSDptr) & (uintD)x_) return cl_true; + return cl_false; + }} + else + if (fixnump(y)) + // x Bignum, y Fixnum, analog wie oben, nur x und y vertauscht + { if (FN_L_minusp(y,FN_to_L(y))) return cl_true; // y<0 -> ja. + // y>=0. Kombiniere y mit den pFN_maxlength letzten Digits von x. + {var const uintD* xLSDptr; + var uintL y_ = FN_to_L(y); + BN_to_NDS_nocopy(x, ,,xLSDptr=); + #if (pFN_maxlength > 1) + doconsttimes(pFN_maxlength-1, + if (lsprefnext(xLSDptr) & (uintD)y_) return cl_true; + y_ = y_ >> intDsize; + ); + #endif + if (lsprefnext(xLSDptr) & (uintD)y_) return cl_true; + return cl_false; + }} + else + // x,y Bignums + { var const uintD* xMSDptr; + var uintC xlen; + var const uintD* yMSDptr; + var uintC ylen; + BN_to_NDS_nocopy(x, xMSDptr=,xlen=,); + BN_to_NDS_nocopy(y, yMSDptr=,ylen=,); + // Beachte: xlen>0, ylen>0. + if (!(xlen==ylen)) + // beide verschieden lang + { if (xlen ganz einfach: + { // bitweise als Fixnum zurück + return cl_I_from_word((x.word ^ y.word) | cl_combine(cl_FN_tag,0)); + } + else + { CL_ALLOCA_STACK; + var uintC n; // Anzahl der Digits + {var uintC nx = I_to_DS_need(x); + var uintC ny = I_to_DS_need(y); + n = (nx>=ny ? nx : ny); + } + {var uintD* xptr; I_to_DS_n(x,n,xptr=); // Pointer in DS zu x + var uintD* yptr; I_to_DS_n(y,n,yptr=); // Pointer in DS zu y + var uintD* zptr = xptr; // Pointer aufs Ergebnis + xor_loop_msp(xptr,yptr,n); // mit XOR verknüpfen + return DS_to_I(zptr,n); // Ergebnis als Integer + } }} diff --git a/src/integer/bitwise/cl_I_mkf.cc b/src/integer/bitwise/cl_I_mkf.cc new file mode 100644 index 0000000..0e6b65c --- /dev/null +++ b/src/integer/bitwise/cl_I_mkf.cc @@ -0,0 +1,49 @@ +// mask_field(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_integer.h" +#include "cl_I.h" +#include "cl_I_byte.h" + +const cl_I mask_field (const cl_I& n, const cl_byte& b) +{ + // Methode: + // (mask-field (byte s p) n) extrahiere die Bits p,...,p+s-1 von n. + // l:=(integer-length n) + // Falls l <= p : + // Falls n>=0: 0, falls n<0: 2^(p+s) - 2^p (s Einsenbits). + // Falls p <= l : + // q:=min(p+s,l). + // Extrahiere die Bits p,...,q-1 von n. + // Falls p+s>l und n<0, füge p+s-l Einsenbits an (addiere 2^(p+s)-2^l). + var uintL s = b.size; + var uintL p = b.position; + {var uintL ps = p+s; + var uintL l = integer_length(n); // l = (integer-length n) + if (l<=p) + // l<=p + if (!minusp(n)) + // n>=0 + return 0; // 0 als Ergebnis + else + // n<0 + return cl_fullbyte(p,ps); // 2^(p+s)-2^p als Ergebnis + else + // l>p + { // Bits p,...,q-1 mit q = min(p+s,l) extrahieren: + var cl_I erg = mkf_extract(n,p,(psl) && minusp(n)) // p+s>l und n<0 ? + { return logior(erg,cl_fullbyte(l,ps)); } // setze Bits l,...,p+s-1 + // (logisches Exklusiv-Oder oder Addition ginge auch) + else + return erg; + } } +} diff --git a/src/integer/bitwise/cl_I_mkfx.cc b/src/integer/bitwise/cl_I_mkfx.cc new file mode 100644 index 0000000..ceb322c --- /dev/null +++ b/src/integer/bitwise/cl_I_mkfx.cc @@ -0,0 +1,50 @@ +// mkf_extract(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I_byte.h" + + +// Implementation. + +#include "cl_integer.h" +#include "cl_I.h" +#include "cl_DS.h" + +const cl_I mkf_extract (const cl_I& x, uintL p, uintL q) +{ + CL_ALLOCA_STACK; + var const uintD* MSDptr; + var uintC len; + var const uintD* LSDptr; + I_to_NDS_nocopy(x, MSDptr=,len=,LSDptr=,cl_true, { return 0; } ); // NDS zu x bilden + // MSDptr erhöhen und len erniedrigen, so daß len = ceiling(q/intDsize) wird: + { var uintL qD = ceiling(q,intDsize); // ceiling(q/intDsize) + // wegen q<=l ist qD = ceiling(q/intDsize) <= ceiling((l+1)/intDsize) = len, also + // paßt qD ebenso wie len in ein uintC. + MSDptr = MSDptr mspop ((uintL)len - qD); // MSDptr um len-qD Digits erhöhen + len = qD; // len um len-qD erniedrigen + } + // Platz (len Digits) für die neue UDS bereitstellen: + var uintD* newMSDptr; + num_stack_alloc_1((uintL)len, newMSDptr = ,); // Platz belegen + {var uintL pD = p/intDsize; // floor(p/intDsize), paßt in ein uintC + // Kopiere len-pD Digits aus der DS zu x heraus: + var uintD* midptr = copy_loop_msp(MSDptr,newMSDptr,len-(uintC)pD); + // Lösche p-intDsize*floor(p/intDsize) Bits im Digit unterhalb von midptr: + {var uintL p_D = p%intDsize; + if (!(p_D==0)) { lspref(midptr,0) &= minus_bit(p_D); } + } + // Lösche pD Digits darüber: + clear_loop_msp(midptr,pD); + } + // Lösche intDsize*ceiling(q/intDsize)-q Bits im ersten Digit: + {var uintL q_D = q%intDsize; + if (!(q_D==0)) + { mspref(newMSDptr,0) &= (uintD)((1L<refcount = 1; + p->type = &cl_class_bignum; + p->length = length; + return p; +} + +// Private constructor. +// ptr should be the result of some allocate_bignum() call. +inline cl_I::cl_I (cl_heap_bignum* ptr) + : cl_RA ((cl_private_thing) ptr) {} + +// Both work, but the first definition results in less compiler-generated +// temporaries. +#if 1 + #define Bignum cl_heap_bignum* +#else + #define Bignum cl_I +#endif + + +// Integers in general. + +// Type tests. +inline cl_boolean integerp (const cl_I& x) + { unused x; return cl_true; } +inline cl_boolean fixnump (const cl_I& x) + { return (cl_boolean) !x.pointer_p(); } +inline cl_boolean bignump (const cl_I& x) + { return x.pointer_p(); } + +// Sign test: + +// (MINUSP x) == (< x 0) +inline cl_boolean minusp (const cl_I& x) +{ + if (fixnump(x)) + // This assumes cl_value_shift + cl_value_len == cl_word_size. + return (cl_boolean)((cl_sint) x.word < 0); + else + return (cl_boolean)((sintD)mspref(arrayMSDptr(TheBignum(x)->data,TheBignum(x)->length),0) < 0); +} + +// (ZEROP x) == (= x 0) +inline cl_boolean zerop (const cl_I& x) +{ + return (cl_boolean)(x.word == cl_combine(cl_FN_tag,0)); +} + +// (EQ x y) == (= x y), assuming y a fixnum +inline cl_boolean eq (const cl_I& x, sint32 y) +{ + return (cl_boolean)(x.word == cl_combine(cl_FN_tag,y)); +} + + +// Umwandlungsroutinen Integer <--> Longword: + +// Wandelt Fixnum >=0 in Unsigned Longword um. +// FN_to_UL(obj) +// > obj: ein Fixnum >=0 +// < ergebnis: der Wert des Fixnum als 32-Bit-Zahl. +inline uint32 FN_to_UL (const cl_I& x) +{ + // This assumes cl_value_shift + cl_value_len == cl_word_size. + return (cl_uint)(x.word) >> cl_value_shift; +} + +// Wandelt Fixnum in Longword um. +// FN_to_L(obj) +// > obj: ein Fixnum +// < ergebnis: der Wert des Fixnum als 32-Bit-Zahl. +inline sint32 FN_to_L (const cl_I& x) +{ + // This assumes cl_value_shift + cl_value_len == cl_word_size. + return (cl_sint)(x.word) >> cl_value_shift; +} + +// FN_L_zerop(x,x_) stellt fest, ob x = 0 ist. +// Dabei ist x ein Fixnum und x_ = FN_to_L(x). + #define FN_L_zerop(x,x_) (x_==0) + +// FN_L_minusp(x,x_) stellt fest, ob x < 0 ist. +// Dabei ist x ein Fixnum und x_ = FN_to_L(x). + #define FN_L_minusp(x,x_) (x_<0) + +#ifdef intQsize + +// Wandelt Fixnum in Quadword um. +// FN_to_Q(obj) +// > obj: ein Fixnum +// < ergebnis: der Wert des Fixnum als 64-Bit-Zahl. +inline sint64 FN_to_Q (const cl_I& x) +{ + // This assumes cl_value_shift + cl_value_len == cl_word_size. + return (cl_sint)(x.word) >> cl_value_shift; +} + +// Wandelt Integer >=0 in Unsigned Quadword um. +// cl_I_to_UQ(obj) +// > obj: ein Objekt, sollte ein Integer >=0, <2^64 sein +// < ergebnis: der Wert des Integer als 64-Bit-Zahl. + extern uint64 cl_I_to_UQ (const cl_I& obj); + +// Wandelt Integer in Signed Quadword um. +// cl_I_to_Q(obj) +// > obj: ein Objekt, sollte ein Integer >=-2^63, <2^63 sein +// < ergebnis: der Wert des Integer als 64-Bit-Zahl. + extern sint64 cl_I_to_Q (const cl_I& obj); + +#endif + +// Wandelt Longword in Fixnum um. +// L_to_FN(wert) +// > wert: Wert des Fixnums, ein signed 32-Bit-Integer +// >= -2^(cl_value_len-1), < 2^(cl_value_len-1) +// < ergebnis: Fixnum mit diesem Wert. + inline const cl_I L_to_FN (sint32 wert) + { + return cl_I_from_word(cl_combine(cl_FN_tag,wert)); + } + +// Wandelt Longword in Integer um. +// L_to_I(wert) +// > wert: Wert des Integers, ein signed 32-Bit-Integer. +// < ergebnis: Integer mit diesem Wert. +#if (cl_value_len >= 32) + #define L_to_I(wert) L_to_FN(wert) +#else + extern cl_private_thing cl_I_constructor_from_L (sint32 wert); + inline const cl_I L_to_I (sint32 wert) + { + return cl_I(cl_I_constructor_from_L(wert)); + } +#endif + +// Wandelt Unsigned Longword in Fixnum >=0 um. +// UL_to_FN(wert) +// > wert: Wert des Integers, ein unsigned 32-Bit-Integer < 2^(cl_value_len-1). +// < ergebnis: Fixnum mit diesem Wert. + inline const cl_I UL_to_FN (uint32 wert) + { + return cl_I_from_word(cl_combine(cl_FN_tag,wert)); + } + +// Wandelt Unsigned Longword in Integer >=0 um. +// UL_to_I(wert) +// > wert: Wert des Integers, ein unsigned 32-Bit-Integer. +// < ergebnis: Integer mit diesem Wert. +#if (cl_value_len > 32) + #define UL_to_I(wert) UL_to_FN(wert) +#else + extern cl_private_thing cl_I_constructor_from_UL (uint32 wert); + inline const cl_I UL_to_I (uint32 wert) + { + return cl_I(cl_I_constructor_from_UL(wert)); + } +#endif + +// Wandelt Doppel-Longword in Integer um. +// L2_to_I(wert_hi,wert_lo) +// > wert_hi|wert_lo: Wert des Integers, ein signed 64-Bit-Integer. +// < ergebnis: Integer mit diesem Wert. + extern cl_private_thing cl_I_constructor_from_L2 (sint32 wert_hi, uint32 wert_lo); + inline const cl_I L2_to_I (sint32 wert_hi, uint32 wert_lo) + { + return cl_I(cl_I_constructor_from_L2(wert_hi,wert_lo)); + } + +// Wandelt Unsigned Doppel-Longword in Integer um. +// UL2_to_I(wert_hi,wert_lo) +// > wert_hi|wert_lo: Wert des Integers, ein unsigned 64-Bit-Integer. +// < ergebnis: Integer mit diesem Wert. + extern cl_private_thing cl_I_constructor_from_UL2 (uint32 wert_hi, uint32 wert_lo); + inline const cl_I UL2_to_I (uint32 wert_hi, uint32 wert_lo) + { + return cl_I(cl_I_constructor_from_UL2(wert_hi,wert_lo)); + } + +#ifdef intQsize + +// Wandelt Quadword in Integer um. +// Q_to_I(wert) +// > wert: Wert des Integers, ein signed 64-Bit-Integer. +// < ergebnis: Integer mit diesem Wert. + extern cl_private_thing cl_I_constructor_from_Q (sint64 wert); + inline const cl_I Q_to_I (sint64 wert) + { + return cl_I(cl_I_constructor_from_Q(wert)); + } + +// Wandelt Unsigned Quadword in Integer >=0 um. +// UQ_to_I(wert) +// > wert: Wert des Integers, ein unsigned 64-Bit-Integer. +// < ergebnis: Integer mit diesem Wert. + extern cl_private_thing cl_I_constructor_from_UQ (uint64 wert); + inline const cl_I UQ_to_I (uint64 wert) + { + return cl_I(cl_I_constructor_from_UQ(wert)); + } + +#endif + +// Wandelt uintD in Integer >=0 um. +// UD_to_I(wert) +// > wert: Wert des Integers, ein uintD. +// < ergebnis: Integer mit diesem Wert. +#if (intDsize < cl_value_len) + #define UD_to_I(wert) UL_to_FN(wert) +#elif (intDsize<=32) + #define UD_to_I(wert) UL_to_I(wert) +#elif (intDsize==64) + #define UD_to_I(wert) UQ_to_I(wert) +#endif + +// Liefert die Differenz x-y zweier Unsigned Longwords x,y als Integer. +// minus(x,y) +inline const cl_I minus (uintL x, uintL y) +{ +#if (cl_word_size==64) + return Q_to_I((sintQ)(uintQ)x - (sintQ)(uintQ)y); +#else + return L2_to_I( (x Longword: + +#if (intDsize<=32) + +// Holt die nächsten pFN_maxlength Digits in ein uint32. +inline uint32 pFN_maxlength_digits_at (const uintD* ptr) +{ +#if (pFN_maxlength==1) + return (uint32)lspref(ptr,0); +#elif (pFN_maxlength==2) + return ((uint32)lspref(ptr,1)<>intDsize); + lspref(ptr,0) = (uintD)(wert); +#elif (pFN_maxlength==3) + lspref(ptr,2) = (uintD)(wert>>(2*intDsize)); + lspref(ptr,1) = (uintD)(wert>>intDsize); + lspref(ptr,0) = (uintD)(wert); +#elif (pFN_maxlength==4) + lspref(ptr,3) = (uintD)(wert>>(3*intDsize)); + lspref(ptr,2) = (uintD)(wert>>(2*intDsize)); + lspref(ptr,1) = (uintD)(wert>>intDsize); + lspref(ptr,0) = (uintD)(wert); +#endif +} + +#elif (intDsize==64) + +// Holt die nächsten pFN_maxlength Digits in ein uint64. +inline uint64 pFN_maxlength_digits_at (const uintD* ptr) +{ + return (uint64)lspref(ptr,0); +} + +#endif + + +// Umwandlungsroutinen Digit sequence --> Integer: + +// Normalized Digit sequence to Integer +// NDS_to_I(MSDptr,len) +// Digit Sequence MSDptr/len/.. in Integer umwandeln. + extern const cl_I NDS_to_I (const uintD* MSDptr, uintC len); + +// Normalized Unsigned Digit Sequence to Integer +// NUDS_to_I(MSDptr,len) +// Normalized UDS MSDptr/len/.. in Integer >=0 umwandeln. +// Unterhalb von MSDptr muß 1 Digit Platz sein. + extern const cl_I NUDS_to_I (uintD* MSDptr, uintC len); + +// Unsigned Digit Sequence to Integer +// UDS_to_I(MSDptr,len) +// UDS MSDptr/len/.. in Integer >=0 umwandeln. +// Unterhalb von MSDptr muß 1 Digit Platz sein. + extern const cl_I UDS_to_I (uintD* MSDptr, uintC len); + +// Digit Sequence to Integer +// DS_to_I(MSDptr,len) +// DS MSDptr/len/.. in Integer umwandeln. + extern const cl_I DS_to_I (const uintD* MSDptr, uintC len); + + +// Umwandlungsroutinen Integer --> Digit sequence: + +// Unterteilung eines Fixnums in Digits: +// intDsize=8 -> MSD=LSD3,LSD2,LSD1,LSD0, sollte FN_maxlength=4 sein. +// intDsize=16 -> MSD=LSD1,LSD0, sollte FN_maxlength=2 sein. +// intDsize=32 -> MSD=LSD0, sollte FN_maxlength=1 sein. + +inline sintD FN_MSD (cl_uint word) +{ + // This assumes cl_value_shift + cl_value_len == cl_word_size. + return (cl_sint)word >> (cl_value_shift + (FN_maxlength-1)*intDsize); +} + +#if (FN_maxlength==1) + #define FN_LSD0(word) FN_MSD(word) + #define FN_LSD1(word) (cl_abort(), (uintD)0) // never used + #define FN_LSD2(word) (cl_abort(), (uintD)0) // never used + #define FN_LSD3(word) (cl_abort(), (uintD)0) // never used +#endif +#if (FN_maxlength==2) + inline uintD FN_LSD0 (cl_uint word) + { + return (uintD)(word >> cl_value_shift); + } + #define FN_LSD1(word) FN_MSD(word) + #define FN_LSD2(word) (cl_abort(), (uintD)0) // never used + #define FN_LSD3(word) (cl_abort(), (uintD)0) // never used +#endif +#if (FN_maxlength==4) + inline uintD FN_LSD0 (cl_uint word) + { + return (uintD)(word >> cl_value_shift); + } + inline uintD FN_LSD1 (cl_uint word) + { + return (uintD)(word >> (cl_value_shift + intDsize)); + } + inline uintD FN_LSD2 (cl_uint word) + { + return (uintD)(word >> (cl_value_shift + 2*intDsize)); + } + #define FN_LSD3(word) FN_MSD(word) +#endif + +// wird nur bei FN_maxlength >= 2 gebraucht, d.h. intDsize < cl_value_len +#define FN_MSD1_mask (~((cl_uint)(bitc(intDsize-1)-1) << cl_value_shift)) +// wird nur bei FN_maxlength >= 3 gebraucht, d.h. 2*intDsize < cl_value_len +#define FN_MSD2_mask (~((cl_uint)(bitc(2*intDsize-1)-1) << cl_value_shift)) +// wird nur bei FN_maxlength >= 4 gebraucht, d.h. 3*intDsize < cl_value_len +#define FN_MSD3_mask (~((cl_uint)(bitc(3*intDsize-1)-1) << cl_value_shift)) + +// Store a Fixnum at destLSDptr, <= FN_maxlength digits below destLSDptr needed. +#define FN_to_NDS(destLSDptr, word, MSDptr_zuweisung,len_zuweisung,LSDptr_zuweisung, check_for_0,zero_statement) \ +{ var uintC len_from_FN_to_NDS; \ + if (check_for_0 && (word == cl_combine(cl_FN_tag,0))) \ + { len_from_FN_to_NDS = 0; zero_statement } \ + else \ + { var cl_uint testMSD; \ + if ((FN_maxlength<=1) || \ + ((testMSD = (word) & FN_MSD1_mask) == 0) || (testMSD == FN_MSD1_mask) \ + ) \ + { len_from_FN_to_NDS = 1; \ + lspref(destLSDptr,0) = FN_LSD0(word); \ + } \ + elif ((FN_maxlength<=2) || \ + ((testMSD = (word) & FN_MSD2_mask) == 0) || (testMSD == FN_MSD2_mask) \ + ) \ + { len_from_FN_to_NDS = 2; \ + lspref(destLSDptr,0) = FN_LSD0(word); \ + lspref(destLSDptr,1) = FN_LSD1(word); \ + } \ + elif ((FN_maxlength<=3) || \ + ((testMSD = (word) & FN_MSD3_mask) == 0) || (testMSD == FN_MSD3_mask) \ + ) \ + { len_from_FN_to_NDS = 3; \ + lspref(destLSDptr,0) = FN_LSD0(word); \ + lspref(destLSDptr,1) = FN_LSD1(word); \ + lspref(destLSDptr,2) = FN_LSD2(word); \ + } \ + else /* (FN_maxlength<=4) */ \ + { len_from_FN_to_NDS = 4; \ + lspref(destLSDptr,0) = FN_LSD0(word); \ + lspref(destLSDptr,1) = FN_LSD1(word); \ + lspref(destLSDptr,2) = FN_LSD2(word); \ + lspref(destLSDptr,3) = FN_LSD3(word); \ + } \ + } \ + unused (MSDptr_zuweisung (destLSDptr) lspop len_from_FN_to_NDS); \ + unused (len_zuweisung len_from_FN_to_NDS); \ + unused (LSDptr_zuweisung (destLSDptr)); \ +} + +// Bignum to Normalized Digit sequence, Kopieren unnötig +// BN_to_NDS_nocopy(obj, MSDptr=,len=,LSDptr=); +// > obj: ein Bignum +// < MSDptr/len/LSDptr: Normalized Digit sequence +#if CL_DS_BIG_ENDIAN_P + #define BN_to_NDS_nocopy(obj, MSDptr_zuweisung,len_zuweisung,LSDptr_zuweisung) \ + { var Bignum bn_from_BN_to_NDS_nocopy = TheBignum(obj); \ + unused (MSDptr_zuweisung (const uintD*) &bn_from_BN_to_NDS_nocopy->data[0]); \ + unused (LSDptr_zuweisung (const uintD*) &bn_from_BN_to_NDS_nocopy->data[(uintP)( len_zuweisung bn_from_BN_to_NDS_nocopy->length )]); \ + } +#else + #define BN_to_NDS_nocopy(obj, MSDptr_zuweisung,len_zuweisung,LSDptr_zuweisung) \ + { var Bignum bn_from_BN_to_NDS_nocopy = TheBignum(obj); \ + unused (LSDptr_zuweisung (const uintD*) &bn_from_BN_to_NDS_nocopy->data[0]); \ + unused (MSDptr_zuweisung (const uintD*) &bn_from_BN_to_NDS_nocopy->data[(uintP)( len_zuweisung bn_from_BN_to_NDS_nocopy->length )]); \ + } +#endif + inline const uintD* BN_MSDptr (const cl_I& obj) + { var Bignum bn = TheBignum(obj); return (const uintD*) arrayMSDptr(bn->data,bn->length); } + inline const uintD* BN_LSDptr (const cl_I& obj) + { var Bignum bn = TheBignum(obj); return (const uintD*) arrayLSDptr(bn->data,bn->length); } + +// Bignum to Normalized Digit sequence +// BN_to_NDS(obj, MSDptr=,len=,LSDptr=); +// > obj: ein Bignum +// < MSDptr/len/LSDptr: Normalized Digit sequence, darf modifiziert werden. +// Dabei wird num_stack erniedrigt. + #define BN_to_NDS(obj, MSDptr_zuweisung,len_zuweisung,LSDptr_zuweisung) \ + { var const cl_I& obj_from_BN_to_NDS = (obj); \ + var uintD* MSDptr_from_BN_to_NDS; \ + var uintC len_from_BN_to_NDS; \ + len_zuweisung len_from_BN_to_NDS = TheBignum(obj_from_BN_to_NDS)->length; \ + num_stack_alloc(len_from_BN_to_NDS, MSDptr_zuweisung MSDptr_from_BN_to_NDS = , LSDptr_zuweisung); \ + copy_loop_msp(BN_MSDptr(obj_from_BN_to_NDS),MSDptr_from_BN_to_NDS,len_from_BN_to_NDS); \ + } + +// Bignum to Normalized Digit sequence +// BN_to_NDS_1(obj, MSDptr=,len=,LSDptr=); +// > obj: ein Bignum +// < MSDptr/len/LSDptr: Normalized Digit sequence, darf modifiziert werden. +// Unterhalb von MSDptr ist noch 1 Digit Platz. +// Dabei wird num_stack erniedrigt. + #define BN_to_NDS_1(obj, MSDptr_zuweisung,len_zuweisung,LSDptr_zuweisung) \ + { var const cl_I& obj_from_BN_to_NDS = (obj); \ + var uintD* MSDptr_from_BN_to_NDS; \ + var uintC len_from_BN_to_NDS; \ + len_zuweisung len_from_BN_to_NDS = TheBignum(obj_from_BN_to_NDS)->length; \ + num_stack_alloc_1(len_from_BN_to_NDS, MSDptr_zuweisung MSDptr_from_BN_to_NDS = , LSDptr_zuweisung); \ + copy_loop_msp(BN_MSDptr(obj_from_BN_to_NDS),MSDptr_from_BN_to_NDS,len_from_BN_to_NDS); \ + } + +// Integer to Normalized Digit sequence, Kopieren unnötig. +// I_to_NDS_nocopy(obj, MSDptr=,len=,LSDptr=,check_for_0,zero_statement); +// > obj: ein Integer +// > check_for_0: ob obj möglicherweise =0 sein kann +// > zero_statement: wird bei obj=0 ausgeführt +// < MSDptr/len/LSDptr: Normalized Digit sequence + #define I_to_NDS_nocopy(obj, MSDptr_zuweisung,len_zuweisung,LSDptr_zuweisung, check_for_0,zero_statement) \ + var uintD CONCAT(FN_store_,__LINE__) [FN_maxlength]; \ + { var const cl_I& obj_from_I_to_NDS_nocopy = (obj); \ + if (fixnump(obj_from_I_to_NDS_nocopy)) \ + { FN_to_NDS(arrayLSDptr(CONCAT(FN_store_,__LINE__),FN_maxlength), cl_FN_word(obj_from_I_to_NDS_nocopy), MSDptr_zuweisung,len_zuweisung,LSDptr_zuweisung, check_for_0,zero_statement); } \ + else \ + { BN_to_NDS_nocopy(obj_from_I_to_NDS_nocopy,MSDptr_zuweisung,len_zuweisung, LSDptr_zuweisung); } \ + } + +// Integer to Normalized Digit sequence +// I_to_NDS(obj, MSDptr=,len=,LSDptr=); +// > obj: ein Integer +// < MSDptr/len/LSDptr: Normalized Digit sequence, darf modifiziert werden. +// Dabei wird num_stack erniedrigt. + #define I_to_NDS(obj, MSDptr_zuweisung,len_zuweisung,LSDptr_zuweisung) \ + var uintD CONCAT(FN_store_,__LINE__) [FN_maxlength]; \ + { var const cl_I& obj_from_I_to_NDS = (obj); \ + if (fixnump(obj_from_I_to_NDS)) \ + { FN_to_NDS(arrayLSDptr(CONCAT(FN_store_,__LINE__),FN_maxlength), cl_FN_word(obj_from_I_to_NDS), MSDptr_zuweisung,len_zuweisung,LSDptr_zuweisung, cl_true,); } \ + else \ + { BN_to_NDS(obj_from_I_to_NDS,MSDptr_zuweisung,len_zuweisung, LSDptr_zuweisung); } \ + } + +// Integer to Normalized Digit sequence +// I_to_NDS_1(obj, MSDptr=,len=,LSDptr=); +// > obj: ein Integer +// < MSDptr/len/LSDptr: Normalized Digit sequence, darf modifiziert werden. +// Unterhalb von MSDptr ist noch 1 Digit Platz. +// Dabei wird num_stack erniedrigt. + #define I_to_NDS_1(obj, MSDptr_zuweisung,len_zuweisung,LSDptr_zuweisung) \ + var uintD CONCAT(FN_store_,__LINE__) [1+FN_maxlength]; \ + { var const cl_I& obj_from_I_to_NDS = (obj); \ + if (fixnump(obj_from_I_to_NDS)) \ + { FN_to_NDS(arrayLSDptr(CONCAT(FN_store_,__LINE__),1+FN_maxlength), cl_FN_word(obj_from_I_to_NDS), MSDptr_zuweisung,len_zuweisung,LSDptr_zuweisung, cl_true,); } \ + else \ + { BN_to_NDS_1(obj_from_I_to_NDS,MSDptr_zuweisung,len_zuweisung, LSDptr_zuweisung); } \ + } + + +// Division ganzer Zahlen + +// Dividiert zwei Integers x,y >=0 und liefert Quotient und Rest +// der Division x/y. Bei y=0 Error. +// cl_divide(x,y) +// > x,y: Integers >=0 +// < q,r: Quotient q, Rest r + extern const cl_I_div_t cl_divide (const cl_I& x, const cl_I& y); + +// Fehler, wenn Quotient keine ganze Zahl ist + nonreturning_function(extern, cl_error_exquo, (const cl_I& x, const cl_I& y)); + + +// ggT und kgV von Integers + + // Teilfunktion für die Durchführung des Euklid-Algorithmus auf + // den führenden Ziffern a' und b': + // partial_gcd(a',b',&erg); mit a'>b' + // liefert in erg: x1,y1,x2,y2 mit den in cl_I_gcd.cc angegebenen Invarianten. + typedef struct { uintD x1,y1,x2,y2; } partial_gcd_result; + extern void partial_gcd (uintD z1, uintD z2, partial_gcd_result* erg); + #if HAVE_DD + extern void partial_gcd (uintDD z1, uintDD z2, partial_gcd_result* erg); + #else + extern void partial_gcd (uintD z1hi, uintD z1lo, uintD z2hi, uintD z2lo, partial_gcd_result* erg); + #endif + + +// Wurzel aus ganzen Zahlen + +// Stellt fest, ob ein Integer >=0 eine n-te Potenz ist. +// cl_rootp_aux(x,n,&w) +// > x: ein Integer >=0 +// > n: ein Integer >0 +// > Annahme: x > 1 und n < (integer-length x). +// < w: Integer (expt x (/ n)) falls x eine n-te Potenz +// < ergebnis: cl_true ........................, cl_false sonst + extern cl_boolean cl_rootp_aux (cl_I x, uintL n, cl_I* w); + + +// Hilfsfunktion zur Eingabe von Integers + +// Wandelt eine Ziffernfolge in ein Integer >=0 um. +// digits_to_I(MSBptr,len,base) +// > base: Stellenwertsystem-Basis, >=2, <=36 +// > MSBptr/len/..: Ziffernfolge, bestehend aus Punkten (werden überlesen) +// und Ziffern/Buchstaben mit Wert < base. +// < ergebnis: der dargestellte Integer >=0 + extern const cl_I digits_to_I (const char * MSBptr, uintL len, uintD base); + + +// Hilfsfunktion zur Ausgabe von Integers + +// cl_digits_need(len,base) liefert eine obere Abschätzung für die Anzahl der +// Ziffern im Stellenwertsystem der Basis base, die x >= 0 braucht. + extern uintL cl_digits_need (const cl_I& x, uintL base); + +// Wandelt ein Integer in ein Stellensystem um. +// I_to_digits(x,base, &ergebnis); +// > x: ein Integer >=0 +// > base: Stellensystem-Basis, 2 <= base <= 36. +// > ergebnis.LSBptr: darunter ist mindestens digits_need(len) Bytes Platz +// < ergebnis: fertige Folge MSBptr/len/LSBptr von Ziffern + typedef struct { uintB* MSBptr; uintL len; uintB* LSBptr; } cl_digits; + extern void I_to_digits (const cl_I& x, uintD base, cl_digits* erg); + + +// Hash code. + extern unsigned long hashcode (const cl_I& x); + + +// A fixnum (cl_FN) is an immediate integer. + +// typedef +class cl_FN : public cl_I { +public: +// Optimization of method pointer_p(). + cl_boolean pointer_p() const + { return cl_false; } +}; + +inline cl_boolean fixnump (const cl_FN& x) + { unused x; return cl_true; } +inline cl_boolean bignump (const cl_FN& x) + { unused x; return cl_false; } + +inline cl_boolean minusp (const cl_FN& x) +{ + // This assumes cl_value_shift + cl_value_len == cl_word_size. + return (cl_boolean)((cl_sint) x.word < 0); +} + + +// A bignum (cl_BN) is a heap-allocated integer. + +// typedef +class cl_BN : public cl_I { +public: +// Optimization of method pointer_p(). + cl_boolean pointer_p() const + { return cl_true; } +}; + +inline cl_boolean fixnump (const cl_BN& x) + { unused x; return cl_false; } +inline cl_boolean bignump (const cl_BN& x) + { unused x; return cl_true; } + +inline cl_boolean minusp (const cl_BN& x) +{ + return (cl_boolean)((sintD)mspref(arrayMSDptr(TheBignum(x)->data,TheBignum(x)->length),0) < 0); +} +inline cl_boolean zerop (const cl_BN& x) + { unused x; return cl_false; } + +#endif /* _CL_I_H */ diff --git a/src/integer/conv/Makeflags b/src/integer/conv/Makeflags new file mode 100644 index 0000000..3696f90 --- /dev/null +++ b/src/integer/conv/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/integer/Makeflags +SUBDIR_INCLUDES += diff --git a/src/integer/conv/cl_I_digits_need.cc b/src/integer/conv/cl_I_digits_need.cc new file mode 100644 index 0000000..8ffe13a --- /dev/null +++ b/src/integer/conv/cl_I_digits_need.cc @@ -0,0 +1,62 @@ +// cl_digits_need(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I.h" + + +// Implementation. + +uintL cl_digits_need (const cl_I& x, uintL base) +{ + if (fixnump(x)) + { return cl_value_len; } // x < 2^cl_value_len, base >= 2, also reicht das + else + { var uintC len = TheBignum(x)->length; + // 1+ceiling(len * intDsize*log(2)/log(base)) Bytes oder etwas mehr + var uintL need = 1+floor(len,1024/intDsize); // > ceiling(len*intDsize/1024) >= 0 + switch (base) // need mit ceiling(1024*log(2)/log(base)) multiplizieren: + { case 2: need = 1024*need; break; + case 3: need = 647*need; break; + case 4: need = 512*need; break; + case 5: need = 442*need; break; + case 6: need = 397*need; break; + case 7: need = 365*need; break; + case 8: need = 342*need; break; + case 9: need = 324*need; break; + case 10: need = 309*need; break; + case 11: need = 297*need; break; + case 12: need = 286*need; break; + case 13: need = 277*need; break; + case 14: need = 269*need; break; + case 15: need = 263*need; break; + case 16: need = 256*need; break; + case 17: need = 251*need; break; + case 18: need = 246*need; break; + case 19: need = 242*need; break; + case 20: need = 237*need; break; + case 21: need = 234*need; break; + case 22: need = 230*need; break; + case 23: need = 227*need; break; + case 24: need = 224*need; break; + case 25: need = 221*need; break; + case 26: need = 218*need; break; + case 27: need = 216*need; break; + case 28: need = 214*need; break; + case 29: need = 211*need; break; + case 30: need = 209*need; break; + case 31: need = 207*need; break; + case 32: need = 205*need; break; + case 33: need = 203*need; break; + case 34: need = 202*need; break; + case 35: need = 200*need; break; + case 36: need = 199*need; break; + default: NOTREACHED + } + // Nun gilt need >= len*intDsize*log(2)/log(base). + need += 1; // Platzbedarf in Bytes + return need; + } +} diff --git a/src/integer/conv/cl_I_from_DS.cc b/src/integer/conv/cl_I_from_DS.cc new file mode 100644 index 0000000..8c4fb2d --- /dev/null +++ b/src/integer/conv/cl_I_from_DS.cc @@ -0,0 +1,41 @@ +// DS_to_I(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I.h" + + +// Implementation. + +#include "cl_number.h" +#include "cl_DS.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_I_from_NDS.cc" + +MAYBE_INLINE2 +const cl_I DS_to_I (const uintD* MSDptr, uintC len) +{ + // erst normalisieren. + // Dabei evtl. MSDptr erhöhen und len erniedrigen: + if (!(len==0)) // leere DS ist normalisiert + { var uintC count = len-1; + if ((sintD)mspref(MSDptr,0) >= 0) + // Zahl >= 0 + { // versuche maximal len-1 führende Nullen-Digits zu streichen: + while (!(count==0) && (mspref(MSDptr,0)==0) && ((sintD)mspref(MSDptr,1)>=0)) + { msshrink(MSDptr); len--; count--; } // Nulldigit streichen + } + else + // Zahl < 0 + // versuche maximal len-1 führende Einsen-Digits zu streichen: + { while (!(count==0) && ((sintD)mspref(MSDptr,0)==-1) && ((sintD)mspref(MSDptr,1)<0)) + { msshrink(MSDptr); len--; count--; } // Einsen-digit streichen + } } + // Eventuell ist jetzt noch bei der DS 0 ausnahmsweise len=1, + // aber NDS_to_I wird auch damit fertig. + return NDS_to_I(MSDptr,len); +} diff --git a/src/integer/conv/cl_I_from_L.cc b/src/integer/conv/cl_I_from_L.cc new file mode 100644 index 0000000..3419d0c --- /dev/null +++ b/src/integer/conv/cl_I_from_L.cc @@ -0,0 +1,104 @@ +// L_to_I() helper. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I.h" + + +// Implementation. + +#include "cl_number.h" + +#if (cl_value_len < 32) + +#include "cl_DS.h" + +cl_private_thing cl_I_constructor_from_L (sint32 wert) +{ + var uint32 test = wert & minus_bit(cl_value_len-1); + // test enthält die Bits, die nicht in den Fixnum-Wert >= 0 reinpassen. + if ((test == 0) || (test == (uint32)minus_bit(cl_value_len-1))) + { return (cl_private_thing)(cl_combine(cl_FN_tag,wert)); } + // Bignum erzeugen: + // (dessen Länge bn_minlength <= n <= ceiling(32/intDsize) erfüllt) + if (bn_minlength == ceiling(32,intDsize)) { + #if (intDsize==8) + goto bignum4; + #endif + #if (intDsize==16) + goto bignum2; + #endif + #if (intDsize==32) + goto bignum1; + #endif + } + if (wert >= 0) { + #define IF_LENGTH(i) \ + if ((bn_minlength <= i) && (i*intDsize <= 32)) \ + if (!((i+1)*intDsize <= 32) \ + || ((uint32)wert < (uint32)bitc(i*intDsize-1)) \ + ) + #if (intDsize <= 32) + IF_LENGTH(1) + bignum1: + { var cl_heap_bignum* ptr = allocate_bignum(1); + arrayLSref(ptr->data,1,0) = wert; + return (cl_private_thing)(ptr); + } + #if (intDsize <= 16) + IF_LENGTH(2) + bignum2: + { var cl_heap_bignum* ptr = allocate_bignum(2); + arrayLSref(ptr->data,2,0) = (uintD)wert; + arrayLSref(ptr->data,2,1) = (uintD)(wert>>intDsize); + return (cl_private_thing)(ptr); + } + #if (intDsize <= 8) + IF_LENGTH(3) + bignum3: + { var cl_heap_bignum* ptr = allocate_bignum(3); + arrayLSref(ptr->data,3,0) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,3,1) = (uintD)wert; + arrayLSref(ptr->data,3,2) = (uintD)(wert>>intDsize); + return (cl_private_thing)(ptr); + } + IF_LENGTH(4) + bignum4: + { var cl_heap_bignum* ptr = allocate_bignum(4); + arrayLSref(ptr->data,4,0) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,4,1) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,4,2) = (uintD)wert; + arrayLSref(ptr->data,4,3) = (uintD)(wert>>intDsize); + return (cl_private_thing)(ptr); + } + #endif + #endif + #endif + #undef IF_LENGTH + } else { + #define IF_LENGTH(i) \ + if ((bn_minlength <= i) && (i*intDsize <= 32)) \ + if (!((i+1)*intDsize <= 32) \ + || ((uint32)wert >= (uint32)(-bitc(i*intDsize-1))) \ + ) + #if (intDsize <= 32) + IF_LENGTH(1) + goto bignum1; + #if (intDsize <= 16) + IF_LENGTH(2) + goto bignum2; + #if (intDsize <= 8) + IF_LENGTH(3) + goto bignum3; + IF_LENGTH(4) + goto bignum4; + #endif + #endif + #endif + #undef IF_LENGTH + } +} + +#endif diff --git a/src/integer/conv/cl_I_from_L2.cc b/src/integer/conv/cl_I_from_L2.cc new file mode 100644 index 0000000..88dba6a --- /dev/null +++ b/src/integer/conv/cl_I_from_L2.cc @@ -0,0 +1,131 @@ +// L2_to_I() helper. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I.h" + + +// Implementation. + +#include "cl_number.h" +#include "cl_DS.h" + +cl_private_thing cl_I_constructor_from_L2 (sint32 wert_hi, uint32 wert_lo) +{ + if (wert_hi == 0) { + if ((wert_lo & minus_bit(cl_value_len-1)) == 0) + return (cl_private_thing)(cl_combine(cl_FN_tag,wert_lo)); + } + elif (wert_hi == ~(sint32)0) { + if ((~wert_lo & minus_bit(cl_value_len-1)) == 0) + return (cl_private_thing)(cl_combine(cl_FN_tag,(sint32)wert_lo)); + } + // Bignum erzeugen: + // (dessen Länge bn_minlength <= n <= ceiling(64/intDsize) erfüllt) + #define FILL_1_DIGIT(l,i,from) \ + arrayLSref(ptr->data,l,i) = (uintD)from; + #define FILL_2_DIGIT(l,i,from) \ + arrayLSref(ptr->data,l,i) = (uintD)from; \ + arrayLSref(ptr->data,l,i+1) = (uintD)(from>>intDsize); + #define FILL_3_DIGIT(l,i,from) \ + arrayLSref(ptr->data,l,i) = (uintD)from; from>>=intDsize; \ + arrayLSref(ptr->data,l,i+1) = (uintD)from; \ + arrayLSref(ptr->data,l,i+2) = (uintD)(from>>intDsize); + #define FILL_4_DIGIT(l,i,from) \ + arrayLSref(ptr->data,l,i) = (uintD)from; from>>=intDsize; \ + arrayLSref(ptr->data,l,i+1) = (uintD)from; from>>=intDsize; \ + arrayLSref(ptr->data,l,i+2) = (uintD)from; \ + arrayLSref(ptr->data,l,i+3) = (uintD)(from>>intDsize); + #if (intDsize==64) + #define FILL_1 FILL_1_DIGIT(1,0,highlow64(wert_hi,wert_lo)); + #endif + #if (32/intDsize==1) + #define FILL_1 FILL_1_DIGIT(1,0,wert_lo); + #define FILL_2 FILL_1_DIGIT(2,1,wert_hi); FILL_1_DIGIT(2,0,wert_lo); + #endif + #if (32/intDsize==2) + #define FILL_1 FILL_1_DIGIT(1,0,wert_lo); + #define FILL_2 FILL_2_DIGIT(2,0,wert_lo); + #define FILL_3 FILL_1_DIGIT(3,2,wert_hi); FILL_2_DIGIT(3,0,wert_lo); + #define FILL_4 FILL_2_DIGIT(4,2,wert_hi); FILL_2_DIGIT(4,0,wert_lo); + #endif + #if (32/intDsize==4) + #define FILL_1 FILL_1_DIGIT(1,0,wert_lo); + #define FILL_2 FILL_2_DIGIT(2,0,wert_lo); + #define FILL_3 FILL_3_DIGIT(3,0,wert_lo); + #define FILL_4 FILL_4_DIGIT(4,0,wert_lo); + #define FILL_5 FILL_1_DIGIT(5,4,wert_hi); FILL_4_DIGIT(5,0,wert_lo); + #define FILL_6 FILL_2_DIGIT(6,4,wert_hi); FILL_4_DIGIT(6,0,wert_lo); + #define FILL_7 FILL_3_DIGIT(7,4,wert_hi); FILL_4_DIGIT(7,0,wert_lo); + #define FILL_8 FILL_4_DIGIT(8,4,wert_hi); FILL_4_DIGIT(8,0,wert_lo); + #endif + if (wert_hi >= 0) { + #define IF_LENGTH(i) \ + if ((bn_minlength <= i) && (i*intDsize <= 64)) \ + if (!((i+1)*intDsize <= 64) \ + || (i*intDsize-1 < 32 \ + ? ((wert_hi == 0) && (wert_lo < (uint32)bitc(i*intDsize-1))) \ + : ((uint32)wert_hi < (uint32)bitc(i*intDsize-1-32)) \ + ) ) + #define ALLOC(i) \ + var cl_heap_bignum* ptr = allocate_bignum(i); + #define OK \ + return (cl_private_thing)(ptr); + IF_LENGTH(1) + bignum1: { ALLOC(1); FILL_1; OK; } + #if (intDsize <= 32) + IF_LENGTH(2) + bignum2: { ALLOC(2); FILL_2; OK; } + #if (intDsize <= 16) + IF_LENGTH(3) + bignum3: { ALLOC(3); FILL_3; OK; } + IF_LENGTH(4) + bignum4: { ALLOC(4); FILL_4; OK; } + #if (intDsize <= 8) + IF_LENGTH(5) + bignum5: { ALLOC(5); FILL_5; OK; } + IF_LENGTH(6) + bignum6: { ALLOC(6); FILL_6; OK; } + IF_LENGTH(7) + bignum7: { ALLOC(7); FILL_7; OK; } + IF_LENGTH(8) + bignum8: { ALLOC(8); FILL_8; OK; } + #endif + #endif + #endif + #undef IF_LENGTH + } else { + #define IF_LENGTH(i) \ + if ((bn_minlength <= i) && (i*intDsize <= 64)) \ + if (!((i+1)*intDsize <= 64) \ + || (i*intDsize-1 < 32 \ + ? ((wert_hi == ~(sint32)0) && (wert_lo >= (uint32)(-bitc(i*intDsize-1)))) \ + : ((uint32)wert_hi >= (uint32)(-bitc(i*intDsize-1-32))) \ + ) ) + IF_LENGTH(1) + goto bignum1; + #if (intDsize <= 32) + IF_LENGTH(2) + goto bignum2; + #if (intDsize <= 16) + IF_LENGTH(3) + goto bignum3; + IF_LENGTH(4) + goto bignum4; + #if (intDsize <= 8) + IF_LENGTH(5) + goto bignum5; + IF_LENGTH(6) + goto bignum6; + IF_LENGTH(7) + goto bignum7; + IF_LENGTH(8) + goto bignum8; + #endif + #endif + #endif + #undef IF_LENGTH + } +} diff --git a/src/integer/conv/cl_I_from_NDS.cc b/src/integer/conv/cl_I_from_NDS.cc new file mode 100644 index 0000000..23f3285 --- /dev/null +++ b/src/integer/conv/cl_I_from_NDS.cc @@ -0,0 +1,100 @@ +// NDS_to_I(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I.h" + + +// Implementation. + +#include "cl_number.h" +#include "cl_DS.h" + +MAYBE_INLINE +const cl_I NDS_to_I (const uintD* MSDptr, uintC len) +{ + // Mehr als bn_minlength Digits -> Bignum. + // Weniger als bn_minlength Digits -> Fixnum. + // Genau bn_minlength Digits -> Bignum oder Fixnum. + if (len < bn_minlength) + { // 0..bn_minlength-1 Digits, paßt in ein Fixnum: + if (bn_minlength>1 ? (len==0) : TRUE) + // 0 Digits + { return 0; } + #if (cl_word_size <= 32) + var sint32 wert; + if (bn_minlength>2 ? (len==1) : TRUE) + // 1 Digit + len_1: + { wert = get_sint1D_Dptr(MSDptr mspop 1); } + elif (bn_minlength>3 ? (len==2) : TRUE) + // 2 Digits + len_2: + { wert = get_sint2D_Dptr(MSDptr mspop 2); } + elif (bn_minlength>4 ? (len==3) : TRUE) + // 3 Digits + len_3: + { wert = get_sint3D_Dptr(MSDptr mspop 3); } + elif (TRUE) + // 4 Digits + len_4: + { wert = get_sint4D_Dptr(MSDptr mspop 4); } + elif (FALSE) + // 5 Digits + len_5: + { wert = get_sint4D_Dptr(MSDptr mspop 5); } + #else // (cl_word_size==64) + var sint64 wert; + #if (intDsize==32) + if (TRUE) + // 1 Digit + len_1: + { wert = (sint64)(sintD)mspref(MSDptr,0); } + elif (FALSE) + // 2 Digits + len_2: + { wert = ((sint64)(sintD)mspref(MSDptr,0) << intDsize) | (uint64)(uintD)mspref(MSDptr,1); } + #endif + #if (intDsize==64) + if (TRUE) + // 1 Digit + len_1: + { wert = (sintD)mspref(MSDptr,0); } + #endif + #endif + return L_to_FN(wert); + } + #if (cl_value_len > (bn_minlength-1)*intDsize) + if (len == bn_minlength) + // bn_minlength Digits, also (incl. Vorzeichen) zwischen + // (bn_minlength-1)*intDsize+1 und bn_minlength*intDsize Bits. + // Höchstens cl_value_len Bits -> paßt in ein Fixnum: + { if ( (mspref(MSDptr,0) <= (uintD)(bit(cl_value_len-1-(bn_minlength-1)*intDsize)-1)) // Fixnum >=0 ? + ||(mspref(MSDptr,0) >= (uintD)(-bit(cl_value_len-1-(bn_minlength-1)*intDsize))) // Fixnum <0 ? + ) + #if (bn_minlength==1) + goto len_1; + #endif + #if (bn_minlength==2) + goto len_2; + #endif + #if (bn_minlength==3) + goto len_3; + #endif + #if (bn_minlength==4) + goto len_4; + #endif + #if (bn_minlength==5) + goto len_5; + #endif + } + #endif + // mindestens bn_minlength Digits, mache ein Bignum + { var Bignum result = allocate_bignum(len); + // neues Bignum mit dem Inhalt der NDS füllen: + copy_loop_msp(MSDptr,arrayMSDptr(result->data,len),len); + return result; + } +} diff --git a/src/integer/conv/cl_I_from_NUDS.cc b/src/integer/conv/cl_I_from_NUDS.cc new file mode 100644 index 0000000..7b0ac8d --- /dev/null +++ b/src/integer/conv/cl_I_from_NUDS.cc @@ -0,0 +1,27 @@ +// NUDS_to_I(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I.h" + + +// Implementation. + +#include "cl_number.h" +#include "cl_DS.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_I_from_NDS.cc" + +MAYBE_INLINE2 +const cl_I NUDS_to_I (uintD* MSDptr, uintC len) +{ + if ((!(len==0)) && ((sintD)mspref(MSDptr,0) < 0)) + // Falls die Länge >0 und das Most significant Bit = 1 sind, + // die Digit Sequence um ein Nulldigit erweitern: + { lsprefnext(MSDptr) = 0; len++; } + return NDS_to_I(MSDptr,len); +} diff --git a/src/integer/conv/cl_I_from_Q.cc b/src/integer/conv/cl_I_from_Q.cc new file mode 100644 index 0000000..9fd8265 --- /dev/null +++ b/src/integer/conv/cl_I_from_Q.cc @@ -0,0 +1,147 @@ +// Q_to_I() helper. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I.h" + + +// Implementation. + +#include "cl_number.h" + +#ifdef intQsize + +#include "cl_DS.h" + +cl_private_thing cl_I_constructor_from_Q (sint64 wert) +{ + var uint64 test = wert & (sint64)minus_bit(cl_value_len-1); + // test enthält die Bits, die nicht in den Fixnum-Wert >= 0 reinpassen. + if ((test == 0) || (test == (uint64)(sint64)minus_bit(cl_value_len-1))) + return (cl_private_thing)(cl_combine(cl_FN_tag,(sint32)wert)); + // Bignum erzeugen: + // (dessen Länge bn_minlength <= n <= ceiling(32/intDsize) erfüllt) + if (wert >= 0) { + #define IF_LENGTH(i) \ + if ((bn_minlength <= i) && (i*intDsize <= 64)) \ + if (!((i+1)*intDsize <= 64) \ + || ((uint64)wert < ((uint64)1 << (i*intDsize-1))) \ + ) + IF_LENGTH(1) + bignum1: + { var cl_heap_bignum* ptr = allocate_bignum(1); + arrayLSref(ptr->data,1,0) = (uintD)wert; + return (cl_private_thing)(ptr); + } + #if (intDsize <= 32) + IF_LENGTH(2) + bignum2: + { var cl_heap_bignum* ptr = allocate_bignum(2); + arrayLSref(ptr->data,2,0) = (uintD)wert; + arrayLSref(ptr->data,2,1) = (uintD)(wert>>intDsize); + return (cl_private_thing)(ptr); + } + #if (intDsize <= 16) + IF_LENGTH(3) + bignum3: + { var cl_heap_bignum* ptr = allocate_bignum(3); + arrayLSref(ptr->data,3,0) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,3,1) = (uintD)wert; + arrayLSref(ptr->data,3,2) = (uintD)(wert>>intDsize); + return (cl_private_thing)(ptr); + } + IF_LENGTH(4) + bignum4: + { var cl_heap_bignum* ptr = allocate_bignum(4); + arrayLSref(ptr->data,4,0) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,4,1) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,4,2) = (uintD)wert; + arrayLSref(ptr->data,4,3) = (uintD)(wert>>intDsize); + return (cl_private_thing)(ptr); + } + #if (intDsize <= 8) + IF_LENGTH(5) + bignum5: + { var cl_heap_bignum* ptr = allocate_bignum(5); + arrayLSref(ptr->data,5,0) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,5,1) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,5,2) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,5,3) = (uintD)wert; + arrayLSref(ptr->data,5,4) = (uintD)(wert>>intDsize); + return (cl_private_thing)(ptr); + } + IF_LENGTH(6) + bignum6: + { var cl_heap_bignum* ptr = allocate_bignum(6); + arrayLSref(ptr->data,6,0) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,6,1) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,6,2) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,6,3) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,6,4) = (uintD)wert; + arrayLSref(ptr->data,6,5) = (uintD)(wert>>intDsize); + return (cl_private_thing)(ptr); + } + IF_LENGTH(7) + bignum7: + { var cl_heap_bignum* ptr = allocate_bignum(7); + arrayLSref(ptr->data,7,0) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,7,1) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,7,2) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,7,3) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,7,4) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,7,5) = (uintD)wert; + arrayLSref(ptr->data,7,6) = (uintD)(wert>>intDsize); + return (cl_private_thing)(ptr); + } + IF_LENGTH(8) + bignum8: + { var cl_heap_bignum* ptr = allocate_bignum(8); + arrayLSref(ptr->data,8,0) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,8,1) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,8,2) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,8,3) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,8,4) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,8,5) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,8,6) = (uintD)wert; + arrayLSref(ptr->data,8,7) = (uintD)(wert>>intDsize); + return (cl_private_thing)(ptr); + } + #endif + #endif + #endif + #undef IF_LENGTH + } else { + #define IF_LENGTH(i) \ + if ((bn_minlength <= i) && (i*intDsize <= 64)) \ + if (!((i+1)*intDsize <= 64) \ + || ((uint64)wert >= ((uint64)(-1) << (i*intDsize-1))) \ + ) + IF_LENGTH(1) + goto bignum1; + #if (intDsize <= 32) + IF_LENGTH(2) + goto bignum2; + #if (intDsize <= 16) + IF_LENGTH(3) + goto bignum3; + IF_LENGTH(4) + goto bignum4; + #if (intDsize <= 8) + IF_LENGTH(5) + goto bignum5; + IF_LENGTH(6) + goto bignum6; + IF_LENGTH(7) + goto bignum7; + IF_LENGTH(8) + goto bignum8; + #endif + #endif + #endif + #undef IF_LENGTH + } +} + +#endif diff --git a/src/integer/conv/cl_I_from_UDS.cc b/src/integer/conv/cl_I_from_UDS.cc new file mode 100644 index 0000000..0f6b129 --- /dev/null +++ b/src/integer/conv/cl_I_from_UDS.cc @@ -0,0 +1,30 @@ +// UDS_to_I(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I.h" + + +// Implementation. + +#include "cl_number.h" +#include "cl_DS.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_I_from_NDS.cc" + +MAYBE_INLINE2 +const cl_I UDS_to_I (uintD* MSDptr, uintC len) +{ + while ( (!(len==0)) && (mspref(MSDptr,0)==0) ) // solange len>0 und MSD = 0, + { msshrink(MSDptr); len--; } // Nulldigit streichen + // Dann wie bei NUDS_to_I : + if ((!(len==0)) && ((sintD)mspref(MSDptr,0) < 0)) + // Falls die Länge >0 und das Most significant Bit = 1 sind, + // die Digit Sequence um ein Nulldigit erweitern: + { lsprefnext(MSDptr) = 0; len++; } + return NDS_to_I(MSDptr,len); +} diff --git a/src/integer/conv/cl_I_from_UL.cc b/src/integer/conv/cl_I_from_UL.cc new file mode 100644 index 0000000..b8401bb --- /dev/null +++ b/src/integer/conv/cl_I_from_UL.cc @@ -0,0 +1,92 @@ +// UL_to_I() helper. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I.h" + + +// Implementation. + +#include "cl_number.h" + +#if (cl_value_len <= 32) + +#include "cl_DS.h" + +cl_private_thing cl_I_constructor_from_UL (uint32 wert) +{ + if ((wert & minus_bit(cl_value_len-1)) == 0) + // Bits, die nicht in den Fixnum-Wert >= 0 reinpassen. + return (cl_private_thing)(cl_combine(cl_FN_tag,wert)); + // Bignum erzeugen: + // (dessen Länge bn_minlength <= n <= ceiling((32+1)/intDsize) erfüllt) + #define UL_maxlength ceiling(32+1,intDsize) + #define IF_LENGTH(i) \ + if ((bn_minlength <= i) && (i <= UL_maxlength)) \ + if (!(i+1 <= UL_maxlength) \ + || ((uint32)wert < (uint32)bitc(i*intDsize-1)) \ + ) + IF_LENGTH(1) + { var cl_heap_bignum* ptr = allocate_bignum(1); + arrayLSref(ptr->data,1,0) = wert; + return (cl_private_thing)(ptr); + } + #if (intDsize <= 32) + IF_LENGTH(2) + { var cl_heap_bignum* ptr = allocate_bignum(2); + arrayLSref(ptr->data,2,0) = (uintD)wert; + #if (intDsize>=32) + arrayLSref(ptr->data,2,1) = 0; + #else + arrayLSref(ptr->data,2,1) = (uintD)(wert>>intDsize); + #endif + return (cl_private_thing)(ptr); + } + #if (intDsize <= 16) + IF_LENGTH(3) + { var cl_heap_bignum* ptr = allocate_bignum(3); + arrayLSref(ptr->data,3,0) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,3,1) = (uintD)wert; + #if (2*intDsize>=32) + arrayLSref(ptr->data,3,2) = 0; + #else + arrayLSref(ptr->data,3,2) = (uintD)(wert>>intDsize); + #endif + return (cl_private_thing)(ptr); + } + #if (intDsize <= 8) + IF_LENGTH(4) + { var cl_heap_bignum* ptr = allocate_bignum(4); + arrayLSref(ptr->data,4,0) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,4,1) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,4,2) = (uintD)wert; + #if (3*intDsize>=32) + arrayLSref(ptr->data,4,3) = 0; + #else + arrayLSref(ptr->data,4,3) = (uintD)(wert>>intDsize); + #endif + return (cl_private_thing)(ptr); + } + IF_LENGTH(5) + { var cl_heap_bignum* ptr = allocate_bignum(5); + arrayLSref(ptr->data,5,0) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,5,1) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,5,2) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,5,3) = (uintD)wert; + #if (4*intDsize>=32) + arrayLSref(ptr->data,5,4) = 0; + #else + arrayLSref(ptr->data,5,4) = (uintD)(wert>>intDsize); + #endif + return (cl_private_thing)(ptr); + } + #endif + #endif + #endif + #undef IF_LENGTH + #undef UL_maxlength +} + +#endif diff --git a/src/integer/conv/cl_I_from_UL2.cc b/src/integer/conv/cl_I_from_UL2.cc new file mode 100644 index 0000000..4409b65 --- /dev/null +++ b/src/integer/conv/cl_I_from_UL2.cc @@ -0,0 +1,102 @@ +// UL2_to_I() helper. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I.h" + + +// Implementation. + +#include "cl_number.h" +#include "cl_DS.h" + +cl_private_thing cl_I_constructor_from_UL2 (uint32 wert_hi, uint32 wert_lo) +{ + if ((wert_hi == 0) + && ((wert_lo & minus_bit(cl_value_len-1)) == 0) + ) + return (cl_private_thing)(cl_combine(cl_FN_tag,wert_lo)); + // Bignum erzeugen: + // (dessen Länge bn_minlength <= n <= ceiling((64+1)/intDsize) erfüllt) + #define UL2_maxlength ceiling(64+1,intDsize) + #define FILL_1_DIGIT(l,i,from) \ + arrayLSref(ptr->data,l,i) = (uintD)from; + #define FILL_2_DIGIT(l,i,from) \ + arrayLSref(ptr->data,l,i) = (uintD)from; \ + arrayLSref(ptr->data,l,i+1) = (uintD)(from>>intDsize); + #define FILL_3_DIGIT(l,i,from) \ + arrayLSref(ptr->data,l,i) = (uintD)from; from>>=intDsize; \ + arrayLSref(ptr->data,l,i+1) = (uintD)from; \ + arrayLSref(ptr->data,l,i+2) = (uintD)(from>>intDsize); + #define FILL_4_DIGIT(l,i,from) \ + arrayLSref(ptr->data,l,i) = (uintD)from; from>>=intDsize; \ + arrayLSref(ptr->data,l,i+1) = (uintD)from; from>>=intDsize; \ + arrayLSref(ptr->data,l,i+2) = (uintD)from; \ + arrayLSref(ptr->data,l,i+3) = (uintD)(from>>intDsize); + #if (intDsize==64) + #define FILL_1 FILL_1_DIGIT(1,0,highlow64(wert_hi,wert_lo)); + #define FILL_2 FILL_1_DIGIT(2,1,0); FILL_1_DIGIT(2,0,highlow64(wert_hi,wert_lo)); + #endif + #if (32/intDsize==1) + #define FILL_1 FILL_1_DIGIT(1,0,wert_lo); + #define FILL_2 FILL_1_DIGIT(2,1,wert_hi); FILL_1_DIGIT(2,0,wert_lo); + #define FILL_3 FILL_1_DIGIT(3,2,0); FILL_1_DIGIT(3,1,wert_hi); FILL_1_DIGIT(3,0,wert_lo); + #endif + #if (32/intDsize==2) + #define FILL_1 FILL_1_DIGIT(1,0,wert_lo); + #define FILL_2 FILL_2_DIGIT(2,0,wert_lo); + #define FILL_3 FILL_1_DIGIT(3,2,wert_hi); FILL_2_DIGIT(3,0,wert_lo); + #define FILL_4 FILL_2_DIGIT(4,2,wert_hi); FILL_2_DIGIT(4,0,wert_lo); + #define FILL_5 FILL_1_DIGIT(5,4,0); FILL_2_DIGIT(5,2,wert_hi); FILL_2_DIGIT(5,0,wert_lo); + #endif + #if (32/intDsize==4) + #define FILL_1 FILL_1_DIGIT(1,0,wert_lo); + #define FILL_2 FILL_2_DIGIT(2,0,wert_lo); + #define FILL_3 FILL_3_DIGIT(3,0,wert_lo); + #define FILL_4 FILL_4_DIGIT(4,0,wert_lo); + #define FILL_5 FILL_1_DIGIT(5,4,wert_hi); FILL_4_DIGIT(5,0,wert_lo); + #define FILL_6 FILL_2_DIGIT(6,4,wert_hi); FILL_4_DIGIT(6,0,wert_lo); + #define FILL_7 FILL_3_DIGIT(7,4,wert_hi); FILL_4_DIGIT(7,0,wert_lo); + #define FILL_8 FILL_4_DIGIT(8,4,wert_hi); FILL_4_DIGIT(8,0,wert_lo); + #define FILL_9 FILL_1_DIGIT(9,8,0); FILL_4_DIGIT(9,4,wert_hi); FILL_4_DIGIT(9,0,wert_lo); + #endif + #define IF_LENGTH(i) \ + if ((bn_minlength <= i) && (i <= UL2_maxlength)) \ + if (!(i+1 <= UL2_maxlength) \ + || (i*intDsize-1 < 32 \ + ? ((wert_hi == 0) && (wert_lo < (uint32)bitc(i*intDsize-1))) \ + : (wert_hi < (uint32)bitc(i*intDsize-1-32)) \ + ) ) + #define ALLOC(i) \ + var cl_heap_bignum* ptr = allocate_bignum(i); + #define OK \ + return (cl_private_thing)(ptr); + IF_LENGTH(1) + { ALLOC(1); FILL_1; OK; } + IF_LENGTH(2) + { ALLOC(2); FILL_2; OK; } + #if (intDsize <= 32) + IF_LENGTH(3) + { ALLOC(3); FILL_3; OK; } + #if (intDsize <= 16) + IF_LENGTH(4) + { ALLOC(4); FILL_4; OK; } + IF_LENGTH(5) + { ALLOC(5); FILL_5; OK; } + #if (intDsize <= 8) + IF_LENGTH(6) + { ALLOC(6); FILL_6; OK; } + IF_LENGTH(7) + { ALLOC(7); FILL_7; OK; } + IF_LENGTH(8) + { ALLOC(8); FILL_8; OK; } + IF_LENGTH(9) + { ALLOC(9); FILL_9; OK; } + #endif + #endif + #endif + #undef IF_LENGTH + #undef UL2_maxlength +} diff --git a/src/integer/conv/cl_I_from_UQ.cc b/src/integer/conv/cl_I_from_UQ.cc new file mode 100644 index 0000000..5721dcc --- /dev/null +++ b/src/integer/conv/cl_I_from_UQ.cc @@ -0,0 +1,154 @@ +// UQ_to_I() helper. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I.h" + + +// Implementation. + +#include "cl_number.h" + +#ifdef intQsize + +#include "cl_DS.h" + +cl_private_thing cl_I_constructor_from_UQ (uint64 wert) +{ + if ((wert & (sint64)minus_bit(cl_value_len-1)) == 0) + // Bits, die nicht in den Fixnum-Wert >= 0 reinpassen. + return (cl_private_thing)(cl_combine(cl_FN_tag,(uint32)wert)); + // Bignum erzeugen: + // (dessen Länge bn_minlength <= n <= ceiling((32+1)/intDsize) erfüllt) + #define UQ_maxlength ceiling(64+1,intDsize) + #define IF_LENGTH(i) \ + if ((bn_minlength <= i) && (i <= UQ_maxlength)) \ + if (!(i+1 <= UQ_maxlength) \ + || ((uint64)wert < ((uint64)1 << (i*intDsize-1 < 64 ? i*intDsize-1 : 0))) \ + ) + IF_LENGTH(1) + { var cl_heap_bignum* ptr = allocate_bignum(1); + arrayLSref(ptr->data,1,0) = (uintD)wert; + return (cl_private_thing)(ptr); + } + IF_LENGTH(2) + { var cl_heap_bignum* ptr = allocate_bignum(2); + arrayLSref(ptr->data,2,0) = (uintD)wert; + #if (intDsize>=64) + arrayLSref(ptr->data,2,1) = 0; + #else + arrayLSref(ptr->data,2,1) = (uintD)(wert>>intDsize); + #endif + return (cl_private_thing)(ptr); + } + #if (intDsize <= 32) + IF_LENGTH(3) + { var cl_heap_bignum* ptr = allocate_bignum(3); + arrayLSref(ptr->data,3,0) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,3,1) = (uintD)wert; + #if (2*intDsize>=64) + arrayLSref(ptr->data,3,2) = 0; + #else + arrayLSref(ptr->data,3,2) = (uintD)(wert>>intDsize); + #endif + return (cl_private_thing)(ptr); + } + #if (intDsize <= 16) + IF_LENGTH(4) + { var cl_heap_bignum* ptr = allocate_bignum(4); + arrayLSref(ptr->data,4,0) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,4,1) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,4,2) = (uintD)wert; + #if (3*intDsize>=64) + arrayLSref(ptr->data,4,3) = 0; + #else + arrayLSref(ptr->data,4,3) = (uintD)(wert>>intDsize); + #endif + return (cl_private_thing)(ptr); + } + IF_LENGTH(5) + { var cl_heap_bignum* ptr = allocate_bignum(5); + arrayLSref(ptr->data,5,0) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,5,1) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,5,2) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,5,3) = (uintD)wert; + #if (4*intDsize>=64) + arrayLSref(ptr->data,5,4) = 0; + #else + arrayLSref(ptr->data,5,4) = (uintD)(wert>>intDsize); + #endif + return (cl_private_thing)(ptr); + } + #if (intDsize <= 8) + IF_LENGTH(6) + { var cl_heap_bignum* ptr = allocate_bignum(6); + arrayLSref(ptr->data,6,0) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,6,1) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,6,2) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,6,3) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,6,4) = (uintD)wert; + #if (5*intDsize>=64) + arrayLSref(ptr->data,6,5) = 0; + #else + arrayLSref(ptr->data,6,5) = (uintD)(wert>>intDsize); + #endif + return (cl_private_thing)(ptr); + } + IF_LENGTH(7) + { var cl_heap_bignum* ptr = allocate_bignum(7); + arrayLSref(ptr->data,7,0) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,7,1) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,7,2) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,7,3) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,7,4) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,7,5) = (uintD)wert; + #if (6*intDsize>=64) + arrayLSref(ptr->data,7,6) = 0; + #else + arrayLSref(ptr->data,7,6) = (uintD)(wert>>intDsize); + #endif + return (cl_private_thing)(ptr); + } + IF_LENGTH(8) + { var cl_heap_bignum* ptr = allocate_bignum(8); + arrayLSref(ptr->data,8,0) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,8,1) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,8,2) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,8,3) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,8,4) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,8,5) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,8,6) = (uintD)wert; + #if (7*intDsize>=64) + arrayLSref(ptr->data,8,7) = 0; + #else + arrayLSref(ptr->data,8,7) = (uintD)(wert>>intDsize); + #endif + return (cl_private_thing)(ptr); + } + IF_LENGTH(9) + { var cl_heap_bignum* ptr = allocate_bignum(9); + arrayLSref(ptr->data,9,0) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,9,1) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,9,2) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,9,3) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,9,4) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,9,5) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,9,6) = (uintD)wert; wert >>= intDsize; + arrayLSref(ptr->data,9,7) = (uintD)wert; + #if (8*intDsize>=64) + arrayLSref(ptr->data,9,8) = 0; + #else + arrayLSref(ptr->data,9,8) = (uintD)(wert>>intDsize); + #endif + return (cl_private_thing)(ptr); + } + #endif + #endif + #endif + #undef IF_LENGTH + #undef UQ_maxlength +} + +#endif diff --git a/src/integer/conv/cl_I_from_digits.cc b/src/integer/conv/cl_I_from_digits.cc new file mode 100644 index 0000000..e79c298 --- /dev/null +++ b/src/integer/conv/cl_I_from_digits.cc @@ -0,0 +1,86 @@ +// digits_to_I(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I.h" + + +// Implementation. + +#include "cl_DS.h" + +const cl_I digits_to_I (const char * MSBptr, uintL len, uintD base) +{ + CL_ALLOCA_STACK; + var uintD* erg_MSDptr; + var uintC erg_len; + var uintD* erg_LSDptr; + // Platz fürs Ergebnis: + // 1+ceiling(len*log(base)/(intDsize*log(2))) oder etwas mehr Digits + var uintL need = 1+floor(len,intDsize*256); // > len/(intDsize*256) >=0 + switch (base) // need mit ceiling(256*log(base)/log(2)) multiplizieren: + { case 2: need = 256*need; break; + case 3: need = 406*need; break; + case 4: need = 512*need; break; + case 5: need = 595*need; break; + case 6: need = 662*need; break; + case 7: need = 719*need; break; + case 8: need = 768*need; break; + case 9: need = 812*need; break; + case 10: need = 851*need; break; + case 11: need = 886*need; break; + case 12: need = 918*need; break; + case 13: need = 948*need; break; + case 14: need = 975*need; break; + case 15: need = 1001*need; break; + case 16: need = 1024*need; break; + case 17: need = 1047*need; break; + case 18: need = 1068*need; break; + case 19: need = 1088*need; break; + case 20: need = 1107*need; break; + case 21: need = 1125*need; break; + case 22: need = 1142*need; break; + case 23: need = 1159*need; break; + case 24: need = 1174*need; break; + case 25: need = 1189*need; break; + case 26: need = 1204*need; break; + case 27: need = 1218*need; break; + case 28: need = 1231*need; break; + case 29: need = 1244*need; break; + case 30: need = 1257*need; break; + case 31: need = 1269*need; break; + case 32: need = 1280*need; break; + case 33: need = 1292*need; break; + case 34: need = 1303*need; break; + case 35: need = 1314*need; break; + case 36: need = 1324*need; break; + default: NOTREACHED + } + // Nun gilt need >= len*log(base)/(intDsize*log(2)). + need += 1; + num_stack_alloc(need,,erg_LSDptr=); + erg_MSDptr = erg_LSDptr; erg_len = 0; + // Ziffern einzeln draufaddieren: + while (len > 0) + { // erg_MSDptr/erg_len/erg_LSDptr ist eine NUDS, erg_len < need. + var uintB ch = *(const uintB *)MSBptr; MSBptr++; // nächstes Character + if (!(ch=='.')) // Punkt überlesen + { // Wert von ch ('0'-'9','A'-'Z','a'-'z') bilden: + ch = ch - '0'; + if (ch > '9'-'0') // keine Ziffer? + { ch = ch+'0'-'A'+10; + if (ch > 'Z'-'A'+10) // kein Großbuchstabe? + { ch = ch+'A'-'a'; } // dann ein Kleinbuchstabe + } + // multipliziere erg mit base und addiere ch: + {var uintD carry = mulusmall_loop_lsp(base,erg_LSDptr,erg_len,ch); + if (!(carry==0)) + // muß NUDS vergrößern: + { lsprefnext(erg_MSDptr) = carry; erg_len++; } + }} + len--; + } + return NUDS_to_I(erg_MSDptr,erg_len); +} diff --git a/src/integer/conv/cl_I_mul10plus.cc b/src/integer/conv/cl_I_mul10plus.cc new file mode 100644 index 0000000..3f1fde9 --- /dev/null +++ b/src/integer/conv/cl_I_mul10plus.cc @@ -0,0 +1,26 @@ +// mul_10_plus_x(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" + +const cl_I mul_10_plus_x (const cl_I& y, unsigned char x) +{ + CL_ALLOCA_STACK; + var uintD* MSDptr; + var uintC len; + var uintD* LSDptr; + I_to_NDS_1(y, MSDptr=,len=,LSDptr=); // NDS zu Y + var uintD carry = mulusmall_loop_lsp(10,LSDptr,len,x); // mal 10, plus x + if (!(carry==0)) + { lsprefnext(MSDptr) = carry; len++; } + return UDS_to_I(MSDptr,len); // UDS als Integer zurück +} diff --git a/src/integer/conv/cl_I_to_L.cc b/src/integer/conv/cl_I_to_L.cc new file mode 100644 index 0000000..c7e4b66 --- /dev/null +++ b/src/integer/conv/cl_I_to_L.cc @@ -0,0 +1,76 @@ +// cl_I_to_L(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_number.h" +#include "cl_I.h" +#include "cl_DS.h" +#include "cl_io.h" +#include "cl_integer_io.h" +#include "cl_abort.h" + +sint32 cl_I_to_L (const cl_I& obj) +{ + if (fixnump(obj)) + // Fixnum + return FN_to_L(obj); + { // Bignum + var cl_heap_bignum* bn = TheBignum(obj); + var uintC len = bn->length; + if ((sintD)mspref(arrayMSDptr(bn->data,len),0) >= 0) { + // Bignum > 0 + #define IF_LENGTH(i) \ + if (bn_minlength <= i) /* genau i Digits überhaupt möglich? */\ + if (len == i) /* genau i Digits? */ \ + /* 2^((i-1)*intDsize-1) <= obj < 2^(i*intDsize-1) */ \ + if ( (i*intDsize > 32) \ + && ( ((i-1)*intDsize >= 32) \ + || (mspref(arrayMSDptr(bn->data,len),0) >= (uintD)bitc(31-(i-1)*intDsize)) \ + ) ) \ + goto bad; \ + else + IF_LENGTH(1) + return get_uint1D_Dptr(arrayLSDptr(bn->data,1)); + IF_LENGTH(2) + return get_uint2D_Dptr(arrayLSDptr(bn->data,2)); + IF_LENGTH(3) + return get_uint3D_Dptr(arrayLSDptr(bn->data,3)); + IF_LENGTH(4) + return get_uint4D_Dptr(arrayLSDptr(bn->data,4)); + #undef IF_LENGTH + } else { + // Bignum < 0 + #define IF_LENGTH(i) \ + if (bn_minlength <= i) /* genau i Digits überhaupt möglich? */\ + if (len == i) /* genau i Digits? */ \ + /* - 2^(i*intDsize-1) <= obj < - 2^((i-1)*intDsize-1) */ \ + if ( (i*intDsize > 32) \ + && ( ((i-1)*intDsize >= 32) \ + || (mspref(arrayMSDptr(bn->data,len),0) < (uintD)(-bitc(31-(i-1)*intDsize))) \ + ) ) \ + goto bad; \ + else + IF_LENGTH(1) + return get_sint1D_Dptr(arrayLSDptr(bn->data,1)); + IF_LENGTH(2) + return get_sint2D_Dptr(arrayLSDptr(bn->data,2)); + IF_LENGTH(3) + return get_sint3D_Dptr(arrayLSDptr(bn->data,3)); + IF_LENGTH(4) + return get_sint4D_Dptr(arrayLSDptr(bn->data,4)); + #undef IF_LENGTH + } + bad: // unpassendes Objekt + fprint(cl_stderr, "Not a 32-bit integer: "); + fprint(cl_stderr, obj); + fprint(cl_stderr, "\n"); + cl_abort(); + } +} diff --git a/src/integer/conv/cl_I_to_Q.cc b/src/integer/conv/cl_I_to_Q.cc new file mode 100644 index 0000000..11a8c0b --- /dev/null +++ b/src/integer/conv/cl_I_to_Q.cc @@ -0,0 +1,139 @@ +// cl_I_to_Q(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I.h" + + +// Implementation. + +#ifdef intQsize + +#include "cl_number.h" +#include "cl_DS.h" +#include "cl_io.h" +#include "cl_integer_io.h" +#include "cl_abort.h" + +sint64 cl_I_to_Q (const cl_I& obj) +{ + if (fixnump(obj)) + // Fixnum + return (sint64)(sint32)FN_to_L(obj); + { // Bignum + var cl_heap_bignum* bn = TheBignum(obj); + var uintC len = bn->length; + if ((sintD)mspref(arrayMSDptr(bn->data,len),0) >= 0) { + // Bignum > 0 + #define IF_LENGTH(i) \ + if (bn_minlength <= i) /* genau i Digits überhaupt möglich? */\ + if (len == i) /* genau i Digits? */ \ + /* 2^((i-1)*intDsize-1) <= obj < 2^(i*intDsize-1) */ \ + if ( (i*intDsize > 64) \ + && ( ((i-1)*intDsize >= 64) \ + || (mspref(arrayMSDptr(bn->data,len),0) >= (uintD)bitc(63-(i-1)*intDsize)) \ + ) ) \ + goto bad; \ + else + #if (intDsize==64) + IF_LENGTH(1) + return (uint64)arrayLSref(bn->data,1,0); + #endif + #if (intDsize==32) + IF_LENGTH(1) + return (uint64)get_uint1D_Dptr(arrayLSDptr(bn->data,1)); + IF_LENGTH(2) + return ((uint64)get_uint1D_Dptr(arrayLSDptr(bn->data,2) lspop 1) << 32) | (uint64)get_uint1D_Dptr(arrayLSDptr(bn->data,2)); + #endif + #if (intDsize==16) + IF_LENGTH(1) + return (uint64)get_uint1D_Dptr(arrayLSDptr(bn->data,1)); + IF_LENGTH(2) + return (uint64)get_uint2D_Dptr(arrayLSDptr(bn->data,2)); + IF_LENGTH(3) + return ((uint64)get_uint1D_Dptr(arrayLSDptr(bn->data,3) lspop 2) << 32) | (uint64)get_uint2D_Dptr(arrayLSDptr(bn->data,3)); + IF_LENGTH(4) + return ((uint64)get_uint2D_Dptr(arrayLSDptr(bn->data,4) lspop 2) << 32) | (uint64)get_uint2D_Dptr(arrayLSDptr(bn->data,4)); + #endif + #if (intDsize==8) + IF_LENGTH(1) + return (uint64)get_uint1D_Dptr(arrayLSDptr(bn->data,1)); + IF_LENGTH(2) + return (uint64)get_uint2D_Dptr(arrayLSDptr(bn->data,2)); + IF_LENGTH(3) + return (uint64)get_uint3D_Dptr(arrayLSDptr(bn->data,3)); + IF_LENGTH(4) + return (uint64)get_uint4D_Dptr(arrayLSDptr(bn->data,4)); + IF_LENGTH(5) + return ((uint64)get_uint1D_Dptr(arrayLSDptr(bn->data,5) lspop 4) << 32) | (uint64)get_uint4D_Dptr(arrayLSDptr(bn->data,5)); + IF_LENGTH(6) + return ((uint64)get_uint2D_Dptr(arrayLSDptr(bn->data,6) lspop 4) << 32) | (uint64)get_uint4D_Dptr(arrayLSDptr(bn->data,6)); + IF_LENGTH(7) + return ((uint64)get_uint3D_Dptr(arrayLSDptr(bn->data,7) lspop 4) << 32) | (uint64)get_uint4D_Dptr(arrayLSDptr(bn->data,7)); + IF_LENGTH(8) + return ((uint64)get_uint4D_Dptr(arrayLSDptr(bn->data,8) lspop 4) << 32) | (uint64)get_uint4D_Dptr(arrayLSDptr(bn->data,8)); + #endif + #undef IF_LENGTH + } else { + // Bignum < 0 + #define IF_LENGTH(i) \ + if (bn_minlength <= i) /* genau i Digits überhaupt möglich? */\ + if (len == i) /* genau i Digits? */ \ + /* - 2^(i*intDsize-1) <= obj < - 2^((i-1)*intDsize-1) */ \ + if ( (i*intDsize > 64) \ + && ( ((i-1)*intDsize >= 64) \ + || (mspref(arrayMSDptr(bn->data,len),0) < (uintD)(-bitc(63-(i-1)*intDsize))) \ + ) ) \ + goto bad; \ + else + #if (intDsize==64) + IF_LENGTH(1) + return (sint64)arrayLSref(bn->data,1,0); + #endif + #if (intDsize==32) + IF_LENGTH(1) + return (sint64)get_sint1D_Dptr(arrayLSDptr(bn->data,1)); + IF_LENGTH(2) + return ((sint64)get_sint1D_Dptr(arrayLSDptr(bn->data,2) lspop 1) << 32) | (uint64)get_uint1D_Dptr(arrayLSDptr(bn->data,2)); + #endif + #if (intDsize==16) + IF_LENGTH(1) + return (sint64)get_sint1D_Dptr(arrayLSDptr(bn->data,1)); + IF_LENGTH(2) + return (sint64)get_sint2D_Dptr(arrayLSDptr(bn->data,2)); + IF_LENGTH(3) + return ((sint64)get_sint1D_Dptr(arrayLSDptr(bn->data,3) lspop 2) << 32) | (uint64)get_uint2D_Dptr(arrayLSDptr(bn->data,3)); + IF_LENGTH(4) + return ((sint64)get_sint2D_Dptr(arrayLSDptr(bn->data,4) lspop 2) << 32) | (uint64)get_uint2D_Dptr(arrayLSDptr(bn->data,4)); + #endif + #if (intDsize==8) + IF_LENGTH(1) + return (sint64)get_sint1D_Dptr(arrayLSDptr(bn->data,1)); + IF_LENGTH(2) + return (sint64)get_sint2D_Dptr(arrayLSDptr(bn->data,2)); + IF_LENGTH(3) + return (sint64)get_sint3D_Dptr(arrayLSDptr(bn->data,3)); + IF_LENGTH(4) + return (sint64)get_sint4D_Dptr(arrayLSDptr(bn->data,4)); + IF_LENGTH(5) + return ((sint64)get_sint1D_Dptr(arrayLSDptr(bn->data,5) lspop 4) << 32) | (uint64)get_uint4D_Dptr(arrayLSDptr(bn->data,5)); + IF_LENGTH(6) + return ((sint64)get_sint2D_Dptr(arrayLSDptr(bn->data,6) lspop 4) << 32) | (uint64)get_uint4D_Dptr(arrayLSDptr(bn->data,6)); + IF_LENGTH(7) + return ((sint64)get_sint3D_Dptr(arrayLSDptr(bn->data,7) lspop 4) << 32) | (uint64)get_uint4D_Dptr(arrayLSDptr(bn->data,7)); + IF_LENGTH(8) + return ((sint64)get_sint4D_Dptr(arrayLSDptr(bn->data,8) lspop 4) << 32) | (uint64)get_uint4D_Dptr(arrayLSDptr(bn->data,8)); + #endif + #undef IF_LENGTH + } + bad: // unpassendes Objekt + fprint(cl_stderr, "Not a 64-bit integer: "); + fprint(cl_stderr, obj); + fprint(cl_stderr, "\n"); + cl_abort(); + } +} + +#endif diff --git a/src/integer/conv/cl_I_to_UL.cc b/src/integer/conv/cl_I_to_UL.cc new file mode 100644 index 0000000..e3aca20 --- /dev/null +++ b/src/integer/conv/cl_I_to_UL.cc @@ -0,0 +1,59 @@ +// cl_I_to_UL(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_number.h" +#include "cl_I.h" +#include "cl_DS.h" +#include "cl_io.h" +#include "cl_integer_io.h" +#include "cl_abort.h" + +uint32 cl_I_to_UL (const cl_I& obj) +{ + if (fixnump(obj)) { + // Fixnum + var sint32 wert = FN_to_L(obj); + if (wert >= 0) + return (uint32)wert; + goto bad; + } else { // Bignum + var cl_heap_bignum* bn = TheBignum(obj); + var uintC len = bn->length; + if ((sintD)mspref(arrayMSDptr(bn->data,len),0) < 0) + goto bad; + #define IF_LENGTH(i) \ + if (bn_minlength <= i) /* genau i Digits überhaupt möglich? */\ + if (len == i) /* genau i Digits? */ \ + /* 2^((i-1)*intDsize-1) <= obj < 2^(i*intDsize-1) */ \ + if ( (i*intDsize-1 > 32) \ + && ( ((i-1)*intDsize-1 >= 32) \ + || (mspref(arrayMSDptr(bn->data,len),0) >= (uintD)bitc(32-(i-1)*intDsize)) \ + ) ) \ + goto bad; \ + else + IF_LENGTH(1) + return get_uint1D_Dptr(arrayLSDptr(bn->data,1)); + IF_LENGTH(2) + return get_uint2D_Dptr(arrayLSDptr(bn->data,2)); + IF_LENGTH(3) + return get_uint3D_Dptr(arrayLSDptr(bn->data,3)); + IF_LENGTH(4) + return get_uint4D_Dptr(arrayLSDptr(bn->data,4)); + IF_LENGTH(5) + return get_uint4D_Dptr(arrayLSDptr(bn->data,5)); + #undef IF_LENGTH + } + bad: // unpassendes Objekt + fprint(cl_stderr, "Not a 32-bit integer: "); + fprint(cl_stderr, obj); + fprint(cl_stderr, "\n"); + cl_abort(); +} diff --git a/src/integer/conv/cl_I_to_UQ.cc b/src/integer/conv/cl_I_to_UQ.cc new file mode 100644 index 0000000..5e522f2 --- /dev/null +++ b/src/integer/conv/cl_I_to_UQ.cc @@ -0,0 +1,98 @@ +// cl_I_to_UQ(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I.h" + + +// Implementation. + +#ifdef intQsize + +#include "cl_number.h" +#include "cl_DS.h" +#include "cl_io.h" +#include "cl_integer_io.h" +#include "cl_abort.h" + +uint64 cl_I_to_UQ (const cl_I& obj) +{ + if (fixnump(obj)) { + // Fixnum + var sint32 wert = FN_to_L(obj); + if (wert >= 0) + return (uint64)(uint32)wert; + goto bad; + } else { // Bignum + var cl_heap_bignum* bn = TheBignum(obj); + var uintC len = bn->length; + if ((sintD)mspref(arrayMSDptr(bn->data,len),0) < 0) + goto bad; + #define IF_LENGTH(i) \ + if (bn_minlength <= i) /* genau i Digits überhaupt möglich? */\ + if (len == i) /* genau i Digits? */ \ + /* 2^((i-1)*intDsize-1) <= obj < 2^(i*intDsize-1) */ \ + if ( (i*intDsize-1 > 64) \ + && ( ((i-1)*intDsize-1 >= 64) \ + || (mspref(arrayMSDptr(bn->data,len),0) >= (uintD)bitc(64-(i-1)*intDsize)) \ + ) ) \ + goto bad; \ + else + #if (intDsize==64) + IF_LENGTH(1) + return (uint64)arrayLSref(bn->data,1,0); + IF_LENGTH(2) + return (uint64)arrayLSref(bn->data,2,0); + #endif + #if (intDsize==32) + IF_LENGTH(1) + return (uint64)get_uint1D_Dptr(arrayLSDptr(bn->data,1)); + IF_LENGTH(2) + return ((uint64)get_uint1D_Dptr(arrayLSDptr(bn->data,2) lspop 1) << 32) | (uint64)get_uint1D_Dptr(arrayLSDptr(bn->data,2)); + IF_LENGTH(3) + return ((uint64)get_uint1D_Dptr(arrayLSDptr(bn->data,3) lspop 1) << 32) | (uint64)get_uint1D_Dptr(arrayLSDptr(bn->data,3)); + #endif + #if (intDsize==16) + IF_LENGTH(1) + return (uint64)get_uint1D_Dptr(arrayLSDptr(bn->data,1)); + IF_LENGTH(2) + return (uint64)get_uint2D_Dptr(arrayLSDptr(bn->data,2)); + IF_LENGTH(3) + return ((uint64)get_uint1D_Dptr(arrayLSDptr(bn->data,3) lspop 2) << 32) | (uint64)get_uint2D_Dptr(arrayLSDptr(bn->data,3)); + IF_LENGTH(4) + return ((uint64)get_uint2D_Dptr(arrayLSDptr(bn->data,4) lspop 2) << 32) | (uint64)get_uint2D_Dptr(arrayLSDptr(bn->data,4)); + IF_LENGTH(5) + return ((uint64)get_uint2D_Dptr(arrayLSDptr(bn->data,5) lspop 2) << 32) | (uint64)get_uint2D_Dptr(arrayLSDptr(bn->data,5)); + #endif + #if (intDsize==8) + IF_LENGTH(1) + return (uint64)get_uint1D_Dptr(arrayLSDptr(bn->data,1)); + IF_LENGTH(2) + return (uint64)get_uint2D_Dptr(arrayLSDptr(bn->data,2)); + IF_LENGTH(3) + return (uint64)get_uint3D_Dptr(arrayLSDptr(bn->data,3)); + IF_LENGTH(4) + return (uint64)get_uint4D_Dptr(arrayLSDptr(bn->data,4)); + IF_LENGTH(5) + return ((uint64)get_uint1D_Dptr(arrayLSDptr(bn->data,5) lspop 4) << 32) | (uint64)get_uint4D_Dptr(arrayLSDptr(bn->data,5)); + IF_LENGTH(6) + return ((uint64)get_uint2D_Dptr(arrayLSDptr(bn->data,6) lspop 4) << 32) | (uint64)get_uint4D_Dptr(arrayLSDptr(bn->data,6)); + IF_LENGTH(7) + return ((uint64)get_uint3D_Dptr(arrayLSDptr(bn->data,7) lspop 4) << 32) | (uint64)get_uint4D_Dptr(arrayLSDptr(bn->data,7)); + IF_LENGTH(8) + return ((uint64)get_uint4D_Dptr(arrayLSDptr(bn->data,8) lspop 4) << 32) | (uint64)get_uint4D_Dptr(arrayLSDptr(bn->data,8)); + IF_LENGTH(9) + return ((uint64)get_uint4D_Dptr(arrayLSDptr(bn->data,9) lspop 4) << 32) | (uint64)get_uint4D_Dptr(arrayLSDptr(bn->data,9)); + #endif + #undef IF_LENGTH + } + bad: // unpassendes Objekt + fprint(cl_stderr, "Not a 64-bit integer: "); + fprint(cl_stderr, obj); + fprint(cl_stderr, "\n"); + cl_abort(); +} + +#endif diff --git a/src/integer/conv/cl_I_to_digits.cc b/src/integer/conv/cl_I_to_digits.cc new file mode 100644 index 0000000..b66f6e4 --- /dev/null +++ b/src/integer/conv/cl_I_to_digits.cc @@ -0,0 +1,411 @@ +// UDS_to_digits(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I.h" + + +// Implementation. + +#include "cl_DS.h" + +// Tabelle: enthält zu jeder Basis b (2 <= b <= 36) +// - eine Kettenbruchapproximation num/den von intDsize*log(2)/log(b) +// (num/den >= intDsize*log(2)/log(b), mit num <= 2^10) +// - k-1 und b^k mit b^k < 2^intDsize, k maximal. + typedef struct { /* uintW num,den; */ uintC k_1; uintD b_hoch_k; } power_table_entry; + static power_table_entry table [36-2+1] = { + #if (intDsize==8) + { /* 8, 1, */ 7-1, 2*2*2*2*2*2*2}, + { /* 106, 21, */ 5-1, 3*3*3*3*3}, + { /* 4, 1, */ 3-1, 4*4*4}, + { /* 789,229, */ 3-1, 5*5*5}, + { /* 359,116, */ 3-1, 6*6*6}, + { /* 436,153, */ 2-1, 7*7}, + { /* 8, 3, */ 2-1, 8*8}, + { /* 53, 21, */ 2-1, 9*9}, + { /* 525,218, */ 2-1, 10*10}, + { /* 1006,435, */ 2-1, 11*11}, + { /* 665,298, */ 2-1, 12*12}, + { /* 988,457, */ 2-1, 13*13}, + { /* 872,415, */ 2-1, 14*14}, + { /* 987,482, */ 2-1, 15*15}, + { /* 2, 1, */ 1-1, 16}, + { /* 869,444, */ 1-1, 17}, + { /* 871,454, */ 1-1, 18}, + { /* 597,317, */ 1-1, 19}, + { /* 87, 47, */ 1-1, 20}, + { /* 989,543, */ 1-1, 21}, + { /* 949,529, */ 1-1, 22}, + { /* 191,108, */ 1-1, 23}, + { /* 930,533, */ 1-1, 24}, + { /* 789,458, */ 1-1, 25}, + { /* 691,406, */ 1-1, 26}, + { /* 461,274, */ 1-1, 27}, + { /* 218,131, */ 1-1, 28}, + { /* 690,419, */ 1-1, 29}, + { /* 494,303, */ 1-1, 30}, + { /* 633,392, */ 1-1, 31}, + { /* 8, 5, */ 1-1, 32}, + { /* 766,483, */ 1-1, 33}, + { /* 629,400, */ 1-1, 34}, + { /* 967,620, */ 1-1, 35}, + { /* 359,232, */ 1-1, 36}, + #endif + #if (intDsize==16) + { /* 16, 1, */ 15-1, 2*2*2*2*2*2*2*2*2*2*2*2*2*2*2}, + { /* 212, 21, */ 10-1, 3*3*3*3*3*3*3*3*3*3}, + { /* 8, 1, */ 7-1, 4*4*4*4*4*4*4}, + { /* 379, 55, */ 6-1, 5*5*5*5*5*5}, + { /* 359, 58, */ 6-1, 6*6*6*6*6*6}, + { /* 872,153, */ 5-1, 7*7*7*7*7}, + { /* 16, 3, */ 5-1, 8*8*8*8*8}, + { /* 106, 21, */ 5-1, 9*9*9*9*9}, + { /* 525,109, */ 4-1, 10*10*10*10}, + { /* 1013,219, */ 4-1, 11*11*11*11}, + { /* 665,149, */ 4-1, 12*12*12*12}, + { /* 761,176, */ 4-1, 13*13*13*13}, + { /* 685,163, */ 4-1, 14*14*14*14}, + { /* 987,241, */ 4-1, 15*15*15*15}, + { /* 4, 1, */ 3-1, 16*16*16}, + { /* 869,222, */ 3-1, 17*17*17}, + { /* 871,227, */ 3-1, 18*18*18}, + { /* 113, 30, */ 3-1, 19*19*19}, + { /* 174, 47, */ 3-1, 20*20*20}, + { /* 51, 14, */ 3-1, 21*21*21}, + { /* 653,182, */ 3-1, 22*22*22}, + { /* 191, 54, */ 3-1, 23*23*23}, + { /* 677,194, */ 3-1, 24*24*24}, + { /* 789,229, */ 3-1, 25*25*25}, + { /* 691,203, */ 3-1, 26*26*26}, + { /* 461,137, */ 3-1, 27*27*27}, + { /* 436,131, */ 3-1, 28*28*28}, + { /* 359,109, */ 3-1, 29*29*29}, + { /* 988,303, */ 3-1, 30*30*30}, + { /* 633,196, */ 3-1, 31*31*31}, + { /* 16, 5, */ 3-1, 32*32*32}, + { /* 203, 64, */ 3-1, 33*33*33}, + { /* 629,200, */ 3-1, 34*34*34}, + { /* 967,310, */ 3-1, 35*35*35}, + { /* 359,116, */ 3-1, 36*36*36}, + #endif + #if (intDsize==32) + { /* 32, 1, */ 31-1, 2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL}, + { /* 424, 21, */ 20-1, 3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL}, + { /* 16, 1, */ 15-1, 4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL}, + { /* 758, 55, */ 13-1, 5UL*5UL*5UL*5UL*5UL*5UL*5UL*5UL*5UL*5UL*5UL*5UL*5UL}, + { /* 359, 29, */ 12-1, 6UL*6UL*6UL*6UL*6UL*6UL*6UL*6UL*6UL*6UL*6UL*6UL}, + { /* 57, 5, */ 11-1, 7UL*7UL*7UL*7UL*7UL*7UL*7UL*7UL*7UL*7UL*7UL}, + { /* 32, 3, */ 10-1, 8UL*8UL*8UL*8UL*8UL*8UL*8UL*8UL*8UL*8UL}, + { /* 212, 21, */ 10-1, 9UL*9UL*9UL*9UL*9UL*9UL*9UL*9UL*9UL*9UL}, + { /* 289, 30, */ 9-1, 10UL*10UL*10UL*10UL*10UL*10UL*10UL*10UL*10UL}, + { /* 990,107, */ 9-1, 11UL*11UL*11UL*11UL*11UL*11UL*11UL*11UL*11UL}, + { /* 848, 95, */ 8-1, 12UL*12UL*12UL*12UL*12UL*12UL*12UL*12UL}, + { /* 761, 88, */ 8-1, 13UL*13UL*13UL*13UL*13UL*13UL*13UL*13UL}, + { /* 1017,121, */ 8-1, 14UL*14UL*14UL*14UL*14UL*14UL*14UL*14UL}, + { /* 901,110, */ 8-1, 15UL*15UL*15UL*15UL*15UL*15UL*15UL*15UL}, + { /* 8, 1, */ 7-1, 16UL*16UL*16UL*16UL*16UL*16UL*16UL}, + { /* 869,111, */ 7-1, 17UL*17UL*17UL*17UL*17UL*17UL*17UL}, + { /* 683, 89, */ 7-1, 18UL*18UL*18UL*18UL*18UL*18UL*18UL}, + { /* 113, 15, */ 7-1, 19UL*19UL*19UL*19UL*19UL*19UL*19UL}, + { /* 348, 47, */ 7-1, 20UL*20UL*20UL*20UL*20UL*20UL*20UL}, + { /* 51, 7, */ 7-1, 21UL*21UL*21UL*21UL*21UL*21UL*21UL}, + { /* 653, 91, */ 7-1, 22UL*22UL*22UL*22UL*22UL*22UL*22UL}, + { /* 191, 27, */ 7-1, 23UL*23UL*23UL*23UL*23UL*23UL*23UL}, + { /* 677, 97, */ 6-1, 24UL*24UL*24UL*24UL*24UL*24UL}, + { /* 379, 55, */ 6-1, 25UL*25UL*25UL*25UL*25UL*25UL}, + { /* 851,125, */ 6-1, 26UL*26UL*26UL*26UL*26UL*26UL}, + { /* 922,137, */ 6-1, 27UL*27UL*27UL*27UL*27UL*27UL}, + { /* 872,131, */ 6-1, 28UL*28UL*28UL*28UL*28UL*28UL}, + { /* 718,109, */ 6-1, 29UL*29UL*29UL*29UL*29UL*29UL}, + { /* 150, 23, */ 6-1, 30UL*30UL*30UL*30UL*30UL*30UL}, + { /* 633, 98, */ 6-1, 31UL*31UL*31UL*31UL*31UL*31UL}, + { /* 32, 5, */ 6-1, 32UL*32UL*32UL*32UL*32UL*32UL}, + { /* 203, 32, */ 6-1, 33UL*33UL*33UL*33UL*33UL*33UL}, + { /* 629,100, */ 6-1, 34UL*34UL*34UL*34UL*34UL*34UL}, + { /* 967,155, */ 6-1, 35UL*35UL*35UL*35UL*35UL*35UL}, + { /* 359, 58, */ 6-1, 36UL*36UL*36UL*36UL*36UL*36UL}, + #endif + #if (intDsize==64) + { /* 64, 1, */ 63-1, 2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL*2UL}, + { /* 848, 21, */ 40-1, 3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL*3UL}, + { /* 32, 1, */ 31-1, 4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL*4UL}, + { /* 634, 23, */ 27-1, 5UL*5UL*5UL*5UL*5UL*5UL*5UL*5UL*5UL*5UL*5UL*5UL*5UL*5UL*5UL*5UL*5UL*5UL*5UL*5UL*5UL*5UL*5UL*5UL*5UL*5UL*5UL}, + { /* 718, 29, */ 24-1, 6UL*6UL*6UL*6UL*6UL*6UL*6UL*6UL*6UL*6UL*6UL*6UL*6UL*6UL*6UL*6UL*6UL*6UL*6UL*6UL*6UL*6UL*6UL*6UL}, + { /* 114, 5, */ 22-1, 7UL*7UL*7UL*7UL*7UL*7UL*7UL*7UL*7UL*7UL*7UL*7UL*7UL*7UL*7UL*7UL*7UL*7UL*7UL*7UL*7UL*7UL}, + { /* 64, 3, */ 21-1, 8UL*8UL*8UL*8UL*8UL*8UL*8UL*8UL*8UL*8UL*8UL*8UL*8UL*8UL*8UL*8UL*8UL*8UL*8UL*8UL*8UL}, + { /* 424, 21, */ 20-1, 9UL*9UL*9UL*9UL*9UL*9UL*9UL*9UL*9UL*9UL*9UL*9UL*9UL*9UL*9UL*9UL*9UL*9UL*9UL*9UL}, + { /* 289, 15, */ 19-1, 10UL*10UL*10UL*10UL*10UL*10UL*10UL*10UL*10UL*10UL*10UL*10UL*10UL*10UL*10UL*10UL*10UL*10UL*10UL}, + { /* 1018, 55, */ 18-1, 11UL*11UL*11UL*11UL*11UL*11UL*11UL*11UL*11UL*11UL*11UL*11UL*11UL*11UL*11UL*11UL*11UL*11UL}, + { /* 607, 34, */ 17-1, 12UL*12UL*12UL*12UL*12UL*12UL*12UL*12UL*12UL*12UL*12UL*12UL*12UL*12UL*12UL*12UL*12UL}, + { /* 761, 44, */ 17-1, 13UL*13UL*13UL*13UL*13UL*13UL*13UL*13UL*13UL*13UL*13UL*13UL*13UL*13UL*13UL*13UL*13UL}, + { /* 975, 58, */ 16-1, 14UL*14UL*14UL*14UL*14UL*14UL*14UL*14UL*14UL*14UL*14UL*14UL*14UL*14UL*14UL*14UL}, + { /* 901, 55, */ 16-1, 15UL*15UL*15UL*15UL*15UL*15UL*15UL*15UL*15UL*15UL*15UL*15UL*15UL*15UL*15UL*15UL}, + { /* 16, 1, */ 15-1, 16UL*16UL*16UL*16UL*16UL*16UL*16UL*16UL*16UL*16UL*16UL*16UL*16UL*16UL*16UL}, + { /* 595, 38, */ 15-1, 17UL*17UL*17UL*17UL*17UL*17UL*17UL*17UL*17UL*17UL*17UL*17UL*17UL*17UL*17UL}, + { /* 1013, 66, */ 15-1, 18UL*18UL*18UL*18UL*18UL*18UL*18UL*18UL*18UL*18UL*18UL*18UL*18UL*18UL*18UL}, + { /* 226, 15, */ 15-1, 19UL*19UL*19UL*19UL*19UL*19UL*19UL*19UL*19UL*19UL*19UL*19UL*19UL*19UL*19UL}, + { /* 696, 47, */ 14-1, 20UL*20UL*20UL*20UL*20UL*20UL*20UL*20UL*20UL*20UL*20UL*20UL*20UL*20UL}, + { /* 102, 7, */ 14-1, 21UL*21UL*21UL*21UL*21UL*21UL*21UL*21UL*21UL*21UL*21UL*21UL*21UL*21UL}, + { /* 775, 54, */ 14-1, 22UL*22UL*22UL*22UL*22UL*22UL*22UL*22UL*22UL*22UL*22UL*22UL*22UL*22UL}, + { /* 382, 27, */ 14-1, 23UL*23UL*23UL*23UL*23UL*23UL*23UL*23UL*23UL*23UL*23UL*23UL*23UL*23UL}, + { /* 1019, 73, */ 13-1, 24UL*24UL*24UL*24UL*24UL*24UL*24UL*24UL*24UL*24UL*24UL*24UL*24UL}, + { /* 758, 55, */ 13-1, 25UL*25UL*25UL*25UL*25UL*25UL*25UL*25UL*25UL*25UL*25UL*25UL*25UL}, + { /* 994, 73, */ 13-1, 26UL*26UL*26UL*26UL*26UL*26UL*26UL*26UL*26UL*26UL*26UL*26UL*26UL}, + { /* 673, 50, */ 13-1, 27UL*27UL*27UL*27UL*27UL*27UL*27UL*27UL*27UL*27UL*27UL*27UL*27UL}, + { /* 892, 67, */ 13-1, 28UL*28UL*28UL*28UL*28UL*28UL*28UL*28UL*28UL*28UL*28UL*28UL*28UL}, + { /* 830, 63, */ 13-1, 29UL*29UL*29UL*29UL*29UL*29UL*29UL*29UL*29UL*29UL*29UL*29UL*29UL}, + { /* 300, 23, */ 13-1, 30UL*30UL*30UL*30UL*30UL*30UL*30UL*30UL*30UL*30UL*30UL*30UL*30UL}, + { /* 633, 49, */ 12-1, 31UL*31UL*31UL*31UL*31UL*31UL*31UL*31UL*31UL*31UL*31UL*31UL}, + { /* 64, 5, */ 12-1, 32UL*32UL*32UL*32UL*32UL*32UL*32UL*32UL*32UL*32UL*32UL*32UL}, + { /* 203, 16, */ 12-1, 33UL*33UL*33UL*33UL*33UL*33UL*33UL*33UL*33UL*33UL*33UL*33UL}, + { /* 629, 50, */ 12-1, 34UL*34UL*34UL*34UL*34UL*34UL*34UL*34UL*34UL*34UL*34UL*34UL}, + { /* 836, 67, */ 12-1, 35UL*35UL*35UL*35UL*35UL*35UL*35UL*35UL*35UL*35UL*35UL*35UL}, + { /* 359, 29, */ 12-1, 36UL*36UL*36UL*36UL*36UL*36UL*36UL*36UL*36UL*36UL*36UL*36UL}, + #endif + }; + +// Timing für Dezimal-Umwandlung einer Zahl mit N Digits = (N*32) Bits, +// auf einem i486 33 MHz unter Linux: +// N standard dnq(div) dnq(mul) combined +// 10 0.00031 0.00043 0.00059 0.00031 +// 25 0.00103 0.00125 0.00178 0.00103 +// 50 0.0030 0.0034 0.0051 0.0030 +// 100 0.0100 0.0108 0.0155 0.0100 +// 250 0.054 0.055 0.064 0.054 +// 500 0.207 0.209 0.229 0.207 +// 750 0.47 0.48 0.47 0.47 +// 1000 0.81 0.81 0.86 0.81 +// 1250 1.25 1.12 1.20 1.12 +// 1500 1.81 1.60 1.64 1.61 +// 1750 2.45 2.24 2.15 2.25 +// 1940 3.01 3.03 3.12 2.80 +// 2000 3.20 3.11 3.30 2.89 +// 2500 5.00 4.11 4.38 3.91 +// 3000 7.3 5.8 5.7 5.5 +// 4000 13.0 12.4 12.9 9.7 +// 5000 20.3 15.3 15.1 12.4 +// 10000 81.4 57.8 56.4 32.5 +// 25000 112 +// 50000 265 +// dnq(div) means divide-and-conquer using division by B at the topmost call, +// threshold = 1015. +// dnq(mul) means divide-and-conquer using multiplication by 1/B at the topmost +// call, threshold = 2050. +// combined means divide-and-conquer as long as length >= threshold. + const unsigned int cl_digits_div_threshold = 1015; + //#define MUL_REPLACES_DIV + const int cl_digits_algo = 1; + +// Tabelle: enthält zu jeder Basis b (2 <= b <= 36) +// NULL oder einen Vektor von lazy berechneten b^(k*2^i) und 1/b^(k*2^i). + typedef struct cached_power_table_entry { + ALLOCATE_ANYWHERE(cached_power_table_entry) + cl_I base_pow; // 0 or b^(k*2^i) + #ifdef MUL_REPLACES_DIV + cl_I inv_base_pow; // if base_pow: floor(2^(2*integer_length(base_pow))/base_pow) + #endif + } cached_power_table_entry; + struct cached_power_table { + cached_power_table_entry element[30]; + // Constructor and destructor - nothing special. + cached_power_table () {} + ~cached_power_table () {} + // Allocation and deallocation. + void* operator new (size_t size) { return cl_malloc_hook(size); } + void operator delete (void* ptr) { cl_free_hook(ptr); } + }; + static cached_power_table* ctable [36-2+1] = + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL + }; + static const cached_power_table_entry * cached_power (uintD base, uintL i) + { var cached_power_table* ptr; + if (!(ptr = ctable[base-2])) + { ctable[base-2] = ptr = new cached_power_table (); } + var uintL j; + for (j = 0; j <= i; j++) + if (zerop(ptr->element[j].base_pow)) + { // Compute b^(k*2^j) and its inverse. + cl_I x = + (j==0 ? (cl_I)(unsigned long)(table[base-2].b_hoch_k) + : ptr->element[j-1].base_pow * ptr->element[j-1].base_pow + ); + ptr->element[j].base_pow = x; + #ifdef MUL_REPLACES_DIV + ptr->element[j].inv_base_pow = floor1(ash(1,2*integer_length(x)),x); + #endif + } + return &ptr->element[i]; + } + AT_DESTRUCTION(cached_power) + { for (var uintD base = 2; base <= 36; base++) + { var cached_power_table* ptr = ctable[base-2]; + if (ptr) + { delete ptr; ctable[base-2] = NULL; } + } + } + +// like I_to_digits, except that the result has exactly erg_len characters. +static inline void I_to_digits_noshrink (const cl_I& X, uintD base, uintL erg_len, cl_digits* erg) +{ + I_to_digits(X,base,erg); + if (erg->len > erg_len) cl_abort(); + var uintL count = erg_len - erg->len; + if (count > 0) + { var uintB* ptr = erg->MSBptr; + do { *--ptr = '0'; } while (--count > 0); + erg->MSBptr = ptr; erg->len = erg->len; + } +} + +void I_to_digits (const cl_I& X, uintD base, cl_digits* erg) +{ +// Methode: +// Umwandlung ins Stellensystem der Basis b geht durch Umwandlung ins Stellen- +// system der Basis b^k (k>=1, b^k<2^intDsize, k maximal) vor sich. +// Aufsuchen von k und b^k aus einer Tabelle. +// Reduktion der UDS zu einer NUDS X. +// Falls X=0: die eine Ziffer 0. +// Falls X>0: +// Dividiere X durch das Wort b^k, +// (Single-Precision-Division, vgl. UDS_DIVIDE mit n=1: +// r:=0, j:=m=Länge(X), +// while j>0 do +// j:=j-1, r:=r*beta+X[j], X[j]:=floor(r/b^k), r:=r-b^k*q[j]. +// r=Rest.) +// zerlege den Rest (mit k-1 Divisionen durch b) in k Ziffern, wandle diese +// Ziffern einzeln in Ascii um und lege sie an die DIGITS an. +// Teste auf Speicherüberlauf. +// X := Quotient. +// Mache aus X wieder eine NUDS (maximal 1 Nulldigit streichen). +// Dies solange bis X=0. +// Streiche die führenden Nullen. + // Aufsuchen von k-1 und b^k aus der Tabelle: + var power_table_entry* tableptr = &table[base-2]; + var uintC k_1 = tableptr->k_1; // k-1 + var uintD b_hoch_k = tableptr->b_hoch_k; // b^k + var uintB* erg_ptr = erg->LSBptr; + #define next_digit(d) { *--erg_ptr = (d<10 ? '0'+d : 'A'-10+d); } + // Spezialfälle: + if (zerop(X)) + { next_digit(0); goto fertig; } // 0 -> eine Ziffer '0' + else if ((base & (base-1)) == 0) + { // Schneller Algorithmus für Zweierpotenzen + var const uintD* MSDptr; + var uintC len; + var const uintD* LSDptr; + I_to_NDS_nocopy(X, MSDptr=,len=,LSDptr=,cl_false,); + var int b = (base==2 ? 1 : base==4 ? 2 : base==8 ? 3 : /*base==16*/ 4); + var uintD carry = 0; + var int carrybits = 0; + loop + { if (carrybits >= b) + { var uintD d = carry & (base-1); + next_digit(d); + carry = carry >> b; carrybits -= b; + } + else + { var uintD d = carry; + if (LSDptr != MSDptr) + { carry = lsprefnext(LSDptr); + d |= (carry << carrybits) & (base-1); + next_digit(d); + carry = carry >> (b-carrybits); carrybits = intDsize - (b-carrybits); + } + else + { next_digit(d); break; } + } + } + } + else if (fixnump(X) || TheBignum(X)->length < cl_digits_div_threshold + || !cl_digits_algo) + { // Standard-Algorithmus + CL_ALLOCA_STACK; + var uintD* MSDptr; + var uintC len; + var uintD* LSDptr; + I_to_NDS(X, MSDptr=,len=,LSDptr=); + // normalisiere zu einer NUDS: + if (mspref(MSDptr,0)==0) { msshrink(MSDptr); len--; } + loop + { // Noch die NUDS MSDptr/len/.. mit len>0 abzuarbeiten. + // Single-Precision-Division durch b^k: + var uintD rest = divu_loop_msp(b_hoch_k,MSDptr,len); + // Zerlegen des Restes in seine k Ziffern: + var uintC count = k_1; + if ((intDsize>=11) || (count>0)) + // (Bei intDsize>=11 ist wegen b<=36 zwangsläufig + // k = ceiling(intDsize*log(2)/log(b))-1 >= 2, also count = k_1 > 0.) + do { var uintD d; + #if HAVE_DD + divuD((uintDD)rest,base,rest=,d=); + #else + divuD(0,rest,base,rest=,d=); + #endif + next_digit(d); + } + until (--count == 0); + next_digit(rest); // letzte der k Ziffern ablegen + // Quotienten normalisieren (max. 1 Digit streichen): + if (mspref(MSDptr,0)==0) { msshrink(MSDptr); len--; if (len==0) break; } + } } + else + { // Divide-and-conquer: + // Find largest i such that B = base^(k*2^i) satisfies B <= X. + // Divide by B: X = X1*B + X0. Convert X0 to string, fill up + // for k*2^i characters, convert X1 to string. (Have to convert + // X0 first because the conversion may temporarily prepend some + // zero characters.) + var uintL ilen_X = integer_length(X); + var const cached_power_table_entry * p; + var uintL ilen_B; + var uintL i; + for (i = 0; ; i++) + { p = cached_power(base,i); + ilen_B = integer_length(p->base_pow); + if (2*ilen_B >= ilen_X) break; + // 2*ilen_B < ilen_X, so certainly B^2 < X, let's continue with i+1. + } + // 2*ilen_B >= ilen_X, implies X < 2*B^2. + // Of course also X >= B, implies ilen_X >= ilen_B. + #ifdef MUL_REPLACES_DIV + // Divide by B by computing + // q := floor((X * floor(2^ilen_X/B)) / 2^ilen_X). + // We have q <= floor(X/B) <= q+1, so we may have to increment q. + // Note also that + // floor(2^ilen_X/B) = floor(floor(2^(2*ilen_B)/B)/2^(2*ilen_B-ilen_X)) + var cl_I q = (X * (p->inv_base_pow >> (2*ilen_B-ilen_X))) >> ilen_X; + var cl_I r = X - q * p->base_pow; + if (r < 0) cl_abort(); + if (r >= p->base_pow) + { q = q+1; r = r - p->base_pow; + if (r >= p->base_pow) cl_abort(); + } + #else + var cl_I_div_t q_r = floor2(X,p->base_pow); + var const cl_I& q = q_r.quotient; + var const cl_I& r = q_r.remainder; + #endif + var const cl_I& X1 = q; + var const cl_I& X0 = r; + var uintL B_baselen = (uintL)(k_1+1)<LSBptr -= B_baselen; + I_to_digits(X1,base,erg); + erg->LSBptr += B_baselen; + erg_ptr = erg->MSBptr; + } + #undef next_digit + // Streiche führende Nullen: + while (*erg_ptr == '0') { erg_ptr++; } + fertig: + erg->MSBptr = erg_ptr; + erg->len = erg->LSBptr - erg_ptr; +} +// Bit complexity (N := length(X)): O(log(N)*M(N)). + diff --git a/src/integer/division/Makeflags b/src/integer/division/Makeflags new file mode 100644 index 0000000..3696f90 --- /dev/null +++ b/src/integer/division/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/integer/Makeflags +SUBDIR_INCLUDES += diff --git a/src/integer/division/cl_I_ceil1.cc b/src/integer/division/cl_I_ceil1.cc new file mode 100644 index 0000000..6c117ac --- /dev/null +++ b/src/integer/division/cl_I_ceil1.cc @@ -0,0 +1,33 @@ +// ceiling1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" + +const cl_I ceiling1 (const cl_I& x, const cl_I& y) +{ +// Methode: +// (ceiling x y) :== +// (DIVIDE (abs x) (abs y)) -> q,r +// Falls x,y selbes Vorzeichen haben und r<>0, +// setze q:=q+1 und r:=r-abs(y). +// Falls x<0, setze r:=-r. +// Falls x,y verschiedene Vorzeichen haben, setze q:=-q. +// Liefere nur q. + var cl_I abs_y = abs(y); + var cl_I_div_t q_r = cl_divide(abs(x),abs_y); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + if (minusp(x) == minusp(y)) + { if (!zerop(r)) { q = q + 1; } } + else + { q = -q; } + return q; +} diff --git a/src/integer/division/cl_I_ceil2.cc b/src/integer/division/cl_I_ceil2.cc new file mode 100644 index 0000000..2686539 --- /dev/null +++ b/src/integer/division/cl_I_ceil2.cc @@ -0,0 +1,35 @@ +// ceiling2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" + +const cl_I_div_t ceiling2 (const cl_I& x, const cl_I& y) +{ +// Methode: +// (ceiling x y) :== +// (DIVIDE (abs x) (abs y)) -> q,r +// Falls x,y selbes Vorzeichen haben und r<>0, +// setze q:=q+1 und r:=r-abs(y). +// Falls x<0, setze r:=-r. +// Falls x,y verschiedene Vorzeichen haben, setze q:=-q. +// Liefere q,r. + var cl_I abs_y = abs(y); + var cl_I_div_t q_r = cl_divide(abs(x),abs_y); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + if ((minusp(x) == minusp(y)) && !zerop(r)) + { q = q + 1; r = r - abs_y; } + if (minusp(x)) + { r = -r; } + if (minusp(x) != minusp(y)) + { q = -q; } + return q_r; +} diff --git a/src/integer/division/cl_I_exquo.cc b/src/integer/division/cl_I_exquo.cc new file mode 100644 index 0000000..37d7189 --- /dev/null +++ b/src/integer/division/cl_I_exquo.cc @@ -0,0 +1,27 @@ +// exquo(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" + +const cl_I exquo (const cl_I& x, const cl_I& y) +{ +// Methode: +// (exquo x y) :== +// (DIVIDE (abs x) (abs y)) -> q,r +// Falls r<>0, Error. +// Falls x,y verschiedene Vorzeichen haben, liefere -q, sonst q. + var cl_I_div_t q_r = cl_divide(abs(x),abs(y)); + if (!zerop(q_r.remainder)) { cl_error_exquo(x,y); } + if (minusp(x) == minusp(y)) + { return q_r.quotient; } + else + { return -q_r.quotient; } +} diff --git a/src/integer/division/cl_I_exquoerr.cc b/src/integer/division/cl_I_exquoerr.cc new file mode 100644 index 0000000..a295c96 --- /dev/null +++ b/src/integer/division/cl_I_exquoerr.cc @@ -0,0 +1,24 @@ +// cl_error_exquo(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I.h" + + +// Implementation. + +#include "cl_io.h" +#include "cl_integer_io.h" +#include "cl_abort.h" + +void cl_error_exquo (const cl_I& x, const cl_I& y) +{ + fprint(cl_stderr, "Quotient "); + fprint(cl_stderr, x); + fprint(cl_stderr, " / "); + fprint(cl_stderr, y); + fprint(cl_stderr, " is not an integer.\n"); + cl_abort(); +} diff --git a/src/integer/division/cl_I_exquopos.cc b/src/integer/division/cl_I_exquopos.cc new file mode 100644 index 0000000..91bbde2 --- /dev/null +++ b/src/integer/division/cl_I_exquopos.cc @@ -0,0 +1,24 @@ +// exquopos(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" + +const cl_I exquopos (const cl_I& x, const cl_I& y) +{ +// Methode: +// (exquopos x y) :== +// (DIVIDE x y) -> q,r +// Falls r<>0, Error. +// Liefere q. + var cl_I_div_t q_r = cl_divide(x,y); + if (!zerop(q_r.remainder)) { cl_error_exquo(x,y); } + return q_r.quotient; +} diff --git a/src/integer/division/cl_I_floor1.cc b/src/integer/division/cl_I_floor1.cc new file mode 100644 index 0000000..a0528aa --- /dev/null +++ b/src/integer/division/cl_I_floor1.cc @@ -0,0 +1,33 @@ +// floor1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" + +const cl_I floor1 (const cl_I& x, const cl_I& y) +{ +// Methode: +// (floor x y) :== +// (DIVIDE (abs x) (abs y)) -> q,r +// Falls x,y verschiedene Vorzeichen haben und r<>0, +// setze q:=q+1 und r:=r-abs(y). +// Falls x<0, setze r:=-r. +// Falls x,y verschiedene Vorzeichen haben, setze q:=-q. +// Liefere nur q. + var cl_I abs_y = abs(y); + var cl_I_div_t q_r = cl_divide(abs(x),abs_y); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + if (minusp(x) != minusp(y)) { + if (!zerop(r)) { q = q + 1; } + q = -q; + } + return q; +} diff --git a/src/integer/division/cl_I_floor2.cc b/src/integer/division/cl_I_floor2.cc new file mode 100644 index 0000000..1db80b1 --- /dev/null +++ b/src/integer/division/cl_I_floor2.cc @@ -0,0 +1,35 @@ +// floor2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" + +const cl_I_div_t floor2 (const cl_I& x, const cl_I& y) +{ +// Methode: +// (floor x y) :== +// (DIVIDE (abs x) (abs y)) -> q,r +// Falls x,y verschiedene Vorzeichen haben und r<>0, +// setze q:=q+1 und r:=r-abs(y). +// Falls x<0, setze r:=-r. +// Falls x,y verschiedene Vorzeichen haben, setze q:=-q. +// Liefere q,r. + var cl_I abs_y = abs(y); + var cl_I_div_t q_r = cl_divide(abs(x),abs_y); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + if ((minusp(x) != minusp(y)) && !zerop(r)) + { q = q + 1; r = r - abs_y; } + if (minusp(x)) + { r = -r; } + if (minusp(x) != minusp(y)) + { q = -q; } + return q_r; +} diff --git a/src/integer/division/cl_I_mod.cc b/src/integer/division/cl_I_mod.cc new file mode 100644 index 0000000..b770476 --- /dev/null +++ b/src/integer/division/cl_I_mod.cc @@ -0,0 +1,29 @@ +// mod(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" + +const cl_I mod (const cl_I& x, const cl_I& y) +{ +// Methode: +// (mod x y) :== +// (DIVIDE (abs x) (abs y)) -> q,r +// Falls x,y verschiedene Vorzeichen haben und r<>0, setze r:=r-abs(y). +// Falls x<0, setze r:=-r. +// Liefere r. + var cl_I abs_y = abs(y); + var cl_I r = cl_divide(abs(x),abs_y).remainder; + if (minusp(x) != minusp(y)) + { if (zerop(r)) { return 0; } + r = r - abs_y; + } + if (minusp(x)) { return -r; } else { return r; } +} diff --git a/src/integer/division/cl_I_rem.cc b/src/integer/division/cl_I_rem.cc new file mode 100644 index 0000000..5491677 --- /dev/null +++ b/src/integer/division/cl_I_rem.cc @@ -0,0 +1,23 @@ +// rem(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" + +const cl_I rem (const cl_I& x, const cl_I& y) +{ +// Methode: +// (rem x y) :== +// (DIVIDE (abs x) (abs y)) -> q,r +// Falls x<0, setze r:=-r. +// Liefere r. + var cl_I r = cl_divide(abs(x),abs(y)).remainder; + if (minusp(x)) { return -r; } else { return r; } +} diff --git a/src/integer/division/cl_I_round1.cc b/src/integer/division/cl_I_round1.cc new file mode 100644 index 0000000..2709993 --- /dev/null +++ b/src/integer/division/cl_I_round1.cc @@ -0,0 +1,37 @@ +// round1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" + +const cl_I round1 (const cl_I& x, const cl_I& y) +{ +// Methode: +// (round x y) :== +// (DIVIDE (abs x) (abs y)) -> q,r +// Setze s:=abs(y)-r. +// Falls (r>s) oder (r=s und q ungerade), +// (d.h. falls r>abs(y)/2 oder r=abs(y)/2 und q ungerade), +// setze q:=q+1 und r:=-s (d.h. r:=r-abs(y)). +// {Nun ist abs(r) <= abs(y)/2, bei abs(r)=abs(y)/2 ist q gerade.} +// Falls x<0, setze r:=-r. +// Falls x,y verschiedene Vorzeichen haben, setze q:=-q. +// Liefere nur q. + var cl_I abs_y = abs(y); + var cl_I_div_t q_r = cl_divide(abs(x),abs_y); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + var cl_I s = abs_y - r; + if ((r > s) || ((r == s) && oddp(q))) + { q = q + 1; } + if (minusp(x) != minusp(y)) + { q = -q; } + return q; +} diff --git a/src/integer/division/cl_I_round2.cc b/src/integer/division/cl_I_round2.cc new file mode 100644 index 0000000..bfa24c1 --- /dev/null +++ b/src/integer/division/cl_I_round2.cc @@ -0,0 +1,39 @@ +// round2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" + +const cl_I_div_t round2 (const cl_I& x, const cl_I& y) +{ +// Methode: +// (round x y) :== +// (DIVIDE (abs x) (abs y)) -> q,r +// Setze s:=abs(y)-r. +// Falls (r>s) oder (r=s und q ungerade), +// (d.h. falls r>abs(y)/2 oder r=abs(y)/2 und q ungerade), +// setze q:=q+1 und r:=-s (d.h. r:=r-abs(y)). +// {Nun ist abs(r) <= abs(y)/2, bei abs(r)=abs(y)/2 ist q gerade.} +// Falls x<0, setze r:=-r. +// Falls x,y verschiedene Vorzeichen haben, setze q:=-q. +// Liefere q,r. + var cl_I abs_y = abs(y); + var cl_I_div_t q_r = cl_divide(abs(x),abs_y); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + var cl_I s = abs_y - r; + if ((r > s) || ((r == s) && oddp(q))) + { q = q + 1; r = - s; } + if (minusp(x)) + { r = -r; } + if (minusp(x) != minusp(y)) + { q = -q; } + return q_r; +} diff --git a/src/integer/division/cl_I_trunc1.cc b/src/integer/division/cl_I_trunc1.cc new file mode 100644 index 0000000..08f2205 --- /dev/null +++ b/src/integer/division/cl_I_trunc1.cc @@ -0,0 +1,27 @@ +// truncate1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" + +const cl_I truncate1 (const cl_I& x, const cl_I& y) +{ +// Methode: +// (truncate x y) :== +// (DIVIDE (abs x) (abs y)) -> q,r +// Falls x<0, setze r:=-r. +// Falls x,y verschiedene Vorzeichen haben, setze q:=-q. +// Liefere nur q. + var cl_I_div_t q_r = cl_divide(abs(x),abs(y)); + var cl_I& q = q_r.quotient; + if (minusp(x) != minusp(y)) + { q = -q; } + return q; +} diff --git a/src/integer/division/cl_I_trunc2.cc b/src/integer/division/cl_I_trunc2.cc new file mode 100644 index 0000000..f9d6700 --- /dev/null +++ b/src/integer/division/cl_I_trunc2.cc @@ -0,0 +1,30 @@ +// truncate2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" + +const cl_I_div_t truncate2 (const cl_I& x, const cl_I& y) +{ +// Methode: +// (truncate x y) :== +// (DIVIDE (abs x) (abs y)) -> q,r +// Falls x<0, setze r:=-r. +// Falls x,y verschiedene Vorzeichen haben, setze q:=-q. +// Liefere q,r. + var cl_I_div_t q_r = cl_divide(abs(x),abs(y)); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + if (minusp(x)) + { r = -r; } + if (minusp(x) != minusp(y)) + { q = -q; } + return q_r; +} diff --git a/src/integer/elem/Makeflags b/src/integer/elem/Makeflags new file mode 100644 index 0000000..3696f90 --- /dev/null +++ b/src/integer/elem/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/integer/Makeflags +SUBDIR_INCLUDES += diff --git a/src/integer/elem/cl_I_compare.cc b/src/integer/elem/cl_I_compare.cc new file mode 100644 index 0000000..5e6e42e --- /dev/null +++ b/src/integer/elem/cl_I_compare.cc @@ -0,0 +1,103 @@ +// cl_compare(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" + +cl_signean cl_compare (const cl_I& x, const cl_I& y) +{ + // Methode: + // x und y haben verschiedenes Vorzeichen -> + // x < 0 -> x < y + // x >= 0 -> x > y + // x und y haben gleiches Vorzeichen -> + // x Fixnum -> + // y Fixnum -> direkt vergleichen. + // y Bignum -> + // y > 0 -> x < y + // y < 0 -> x > y + // x Bignum -> + // y Fixnum -> + // x < 0 -> x < y + // x > 0 -> x > y + // y Bignum -> + // falls beide gleich lang -> wortweise vergleichen + // x kürzer als y -> bei x,y > 0 : x < y, bei x,y < 0 : x > y + // y kürzer als x -> bei x,y > 0 : x > y, bei x,y > 0 : x < y + var uintC xlen; + var uintC ylen; + if (fixnump(x)) + // x Fixnum + if (fixnump(y)) + // x Fixnum, y Fixnum + { // This assumes cl_value_shift + cl_value_len == cl_word_size. + if ((cl_sint)x.word == (cl_sint)y.word) return signean_null; + else if ((cl_sint)x.word > (cl_sint)y.word) return signean_plus; + else return signean_minus; + } + else + // x Fixnum, y Bignum + if ((sintD)mspref(BN_MSDptr(y),0) >= 0) + // x Fixnum, y Bignum >0 + return signean_minus; // xy + else + // x Bignum + if (fixnump(y)) + // x Bignum, y Fixnum + if ((sintD)mspref(BN_MSDptr(x),0) >= 0) + // x Bignum >0, y Fixnum + return signean_plus; // x>y + else + // x Bignum <0, y Fixnum + return signean_minus; // x= 0) + // x Bignum >0, y Bignum + if ((sintD)mspref(BN_MSDptr(y),0) >= 0) + // x und y Bignums >0 + if (x.pointer == y.pointer) + return signean_null; // gleiche Pointer -> selbe Zahl + else + { xlen = TheBignum(x)->length; + ylen = TheBignum(y)->length; + if (xlen==ylen) + samelength: + // gleiche Länge -> digitweise vergleichen + return compare_loop_msp(BN_MSDptr(x),BN_MSDptr(y),xlen); + else + return (xlen > ylen ? signean_plus : signean_minus); + } + else + // x Bignum >0, y Bignum <0 + return signean_plus; // x>y + else + // x Bignum <0, y Bignum + if ((sintD)mspref(BN_MSDptr(y),0) >= 0) + // x Bignum <0, y Bignum >0 + return signean_minus; // x selbe Zahl + else + { xlen = TheBignum(x)->length; + ylen = TheBignum(y)->length; + if (xlen==ylen) + // gleiche Länge -> wortweise vergleichen + goto samelength; // wie oben + else + return (xlen > ylen ? signean_minus : signean_plus); + } +} diff --git a/src/integer/elem/cl_I_div.cc b/src/integer/elem/cl_I_div.cc new file mode 100644 index 0000000..3ff043e --- /dev/null +++ b/src/integer/elem/cl_I_div.cc @@ -0,0 +1,88 @@ +// cl_divide(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I.h" + + +// Implementation. + +#include "cl_N.h" + +// Dividiert zwei Integers x,y >=0 und liefert Quotient und Rest +// der Division x/y. Bei y=0 Error. +// cl_divide(x,y) +// > x,y: Integers >=0 +// < q,r: Quotient q, Rest r + const cl_I_div_t cl_divide (const cl_I& x, const cl_I& y) + { if (fixnump(x)) + // x Fixnum >=0 + { if (fixnump(y)) + // auch y Fixnum >=0 + { var uint32 x_ = FN_to_UL(x); + var uint32 y_ = FN_to_UL(y); + if (y_==0) { cl_error_division_by_0(); } + elif (x_ < y_) + // Trivialfall: q=0, r=x + goto trivial; + elif (y_ < bit(16)) + // 32-durch-16-Bit-Division + { var uint32 q; + var uint16 r; + divu_3216_3216(x_,y_,q=,r=); + return cl_I_div_t( + /* result.quotient = */ UL_to_I(q), + /* result.remainder = */ L_to_FN((uintL)r) + ); + } + else + // volle 32-durch-32-Bit-Division + { var uint32 q; + var uint32 r; + divu_3232_3232(x_,y_,q=,r=); + return cl_I_div_t( + /* result.quotient = */ UL_to_I(q), + /* result.remainder = */ UL_to_I(r) + ); + } + } + else + // y Bignum >0 + { trivial: + // Trivialfall: q=0, r=x + return cl_I_div_t( + /* result.quotient = */ 0, + /* result.remainder = */ x + ); + } + } + else + // x Bignum -> allgemeine Division: + { CL_ALLOCA_STACK; + var const uintD* x_MSDptr; + var uintC x_len; + var const uintD* x_LSDptr; + var const uintD* y_MSDptr; + var uintC y_len; + var const uintD* y_LSDptr; + // x in NDS umwandeln, als UDS auffassen: + BN_to_NDS_nocopy(x, x_MSDptr=,x_len=,x_LSDptr=); + // y in NDS umwandeln, als UDS auffassen: + I_to_NDS_nocopy(y, y_MSDptr=,y_len=,y_LSDptr=,/*cl_true*/cl_false,); + // dividieren: + {var DS q; + var DS r; + UDS_divide(x_MSDptr,x_len,x_LSDptr,y_MSDptr,y_len,y_LSDptr, &q,&r); + // q in Integer umwandeln: + var cl_I quotient = NUDS_to_I(q.MSDptr,q.len); + // r in Integer umwandeln (jetzt erst, nachdem q verwertet ist!): + return cl_I_div_t( + quotient, + /* result.remainder = */ NUDS_to_I(r.MSDptr,r.len) + ); + }} + } +// Bit complexity (N = length(x)): O(M(N)). + diff --git a/src/integer/elem/cl_I_equal.cc b/src/integer/elem/cl_I_equal.cc new file mode 100644 index 0000000..4bcc646 --- /dev/null +++ b/src/integer/elem/cl_I_equal.cc @@ -0,0 +1,54 @@ +// cl_equal(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" + +cl_boolean cl_equal (const cl_I& x, const cl_I& y) +{ +// Methode: +// x und y haben gleiches Vorzeichen -> +// x Fixnum -> +// y Fixnum -> direkt vergleichen. +// y Bignum -> verschieden. +// x Bignum -> +// y Fixnum -> verschieden. +// y Bignum -> +// falls beide gleich lang, wortweise vergleichen, sonst verschieden. + if (fixnump(x)) + // x Fixnum + if (fixnump(y)) + // x Fixnum, y Fixnum + { // This assumes cl_value_shift + cl_value_len == cl_word_size. + return (cl_boolean) ((cl_sint)x.word == (cl_sint)y.word); + } + else + // x Fixnum, y Bignum + return cl_false; + else + // x Bignum + if (fixnump(y)) + // x Bignum, y Fixnum + return cl_false; + else + // x Bignum, y Bignum + if (x.pointer == y.pointer) + return cl_true; // gleiche Pointer -> selbe Zahl + else + { var uintC xlen = TheBignum(x)->length; + var uintC ylen = TheBignum(y)->length; + if (xlen==ylen) + // gleiche Länge -> digitweise vergleichen + return (cl_boolean) (compare_loop_msp(BN_MSDptr(x),BN_MSDptr(y),xlen) == 0); + else + return cl_false; + } +} diff --git a/src/integer/elem/cl_I_minus.cc b/src/integer/elem/cl_I_minus.cc new file mode 100644 index 0000000..263728c --- /dev/null +++ b/src/integer/elem/cl_I_minus.cc @@ -0,0 +1,206 @@ +// binary operator - + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" + +const cl_I operator- (const cl_I& x, const cl_I& y) +{ + // Methode: + // x Fixnum -> + // y Fixnum -> beide direkt subtrahieren, mit L_to_I beenden + // y Bignum -> falls x=0, (- y); sonst beide zu DS machen, subtrahieren. + // x Bignum -> + // y Fixnum -> falls y=0, x; sonst beide zu DS machen, subtrahieren. + // y Bignum -> beide zu DS machen, subtrahieren. + var uintD* MSDptr; + var uintC len; + var uintD* LSDptr; + // MSDptr/len/LSDptr bilden die DS des Ergebnisses. + if (fixnump(x)) + { // x ist Fixnum + if (fixnump(y)) + { // x,y sind Fixnums + #if (cl_value_len < intLsize) + return L_to_I( FN_to_L(x) - FN_to_L(y) ); // als 32-Bit-Zahlen subtrahieren + #elif (cl_word_size==64) + return Q_to_I( FN_to_Q(x) - FN_to_Q(y) ); // als 64-Bit-Zahlen subtrahieren + #else // (cl_value_len == intLsize) + var sint32 xhi = sign_of(FN_to_L(x)); + var uint32 xlo = FN_to_L(x); + var sint32 yhi = sign_of(FN_to_L(y)); + var uint32 ylo = FN_to_L(y); + xhi -= yhi; + if (xlo < ylo) { xhi -= 1; } + xlo -= ylo; + return L2_to_I(xhi,xlo); + #endif + } + else + { // x ist Fixnum, y ist Bignum, also y länger + #if (intDsize==64) + var sint64 x_ = FN_to_L(x); // Wert von x + #else + var sint32 x_ = FN_to_L(x); // Wert von x + #endif + if (FN_L_zerop(x,x_)) { return -y; } // bei x=0 Ergebnis (- y) + CL_ALLOCA_STACK; + BN_to_NDS_1(y, MSDptr=,len=,LSDptr=); // NDS zu y bilden. + // vorsorglich 1 Digit mehr belegen: + { var sintD sign = sign_of_sintD(mspref(MSDptr,0)); + lsprefnext(MSDptr) = sign; len++; + } + // Negierschleife: + neg_loop_lsp(LSDptr,len); + // MSDigit ist nun = 0x0000 oder = 0xFFFF + // x_ zu den oberen pFN_maxlength Digits von -y addieren: + { + #if (intDsize==64) + var uint64 y_ = lspref(LSDptr,0); + var uint64 y_new = y_+(uint64)x_; + lspref(LSDptr,0) = y_new; + #else + var uint32 y_ = pFN_maxlength_digits_at(LSDptr); + var uint32 y_new = y_+(uint32)x_; + set_pFN_maxlength_digits_at(LSDptr,y_new); + #endif + var uintD* midptr = LSDptr lspop pFN_maxlength; + if (y_new < y_) + { // Carry. + if (!FN_L_minusp(x,x_)) // kürzerer Summand war positiv + // Dann ist ein positiver Übertrag weiterzutragen + // (Beispiel: 0002FFFC + 0007 = 00030003) + { DS_1_plus(midptr,len-pFN_maxlength); } + } + else + { // Kein Carry. + if (FN_L_minusp(x,x_)) // kürzerer Summand war negativ + // Dann ist ein negativer Übertrag weiterzutragen + // (Beispiel: 00020003 + FFF5 = 0001FFF8) + { DS_minus1_plus(midptr,len-pFN_maxlength); } + } } + return DS_to_I(MSDptr,len); // DS wieder zum Integer machen + } + } + else + { // x ist Bignum + if (fixnump(y)) + { // x ist Bignum, y ist Fixnum, also x länger + #if (intDsize==64) + var sint64 y_ = FN_to_L(y); // Wert von y + #else + var sint32 y_ = FN_to_L(y); // Wert von y + #endif + if (FN_L_zerop(y,y_)) { return x; } // bei y=0 Ergebnis x + CL_ALLOCA_STACK; + BN_to_NDS_1(x, MSDptr=,len=,LSDptr=); // NDS zu x bilden. + // len>=bn_minlength. len>pFN_maxlength erzwingen: + if ((bn_minlength==pFN_maxlength) && (len==pFN_maxlength)) + { var sintD sign = sign_of_sintD(mspref(MSDptr,0)); + lsprefnext(MSDptr) = sign; len++; + } + // y_ von den oberen pFN_maxlength Digits von x subtrahieren: + { + #if (intDsize==64) + var uint64 x_ = lspref(LSDptr,0); + var uint64 x_new = x_-(uint64)y_; + lspref(LSDptr,0) = x_new; + #else + var uint32 x_ = pFN_maxlength_digits_at(LSDptr); + var uint32 x_new = x_-(uint32)y_; + set_pFN_maxlength_digits_at(LSDptr,x_new); + #endif + var uintD* midptr = LSDptr lspop pFN_maxlength; + if (x_new > x_) + { // Carry. + if (!FN_L_minusp(y,y_)) // kürzerer Summand war positiv + // Dann ist ein negativer Übertrag weiterzutragen + // (Beispiel: 00030003 - 0007 = 0002FFFC) + { DS_minus1_plus(midptr,len-pFN_maxlength); } + } + else + { // Kein Carry. + if (FN_L_minusp(y,y_)) // kürzerer Summand war negativ + // Dann ist ein positiver Übertrag weiterzutragen + // (Beispiel: 0002FFF8 - FFF5 = 00030003) + { DS_1_plus(midptr,len-pFN_maxlength); } + } } + return DS_to_I(MSDptr,len); // DS wieder zum Integer machen + } + else + { // x und y sind Bignums + if (TheBignum(x)->length > TheBignum(y)->length) + { // x das längere von beiden. + CL_ALLOCA_STACK; + BN_to_NDS_1(x, MSDptr=,len=,LSDptr=); // NDS zu x bilden. + var const uintD* yMSDptr; + var uintC ylen; + var const uintD* yLSDptr; + BN_to_NDS_nocopy(y, yMSDptr=,ylen=,yLSDptr=); // NDS zu y bilden. + // yMSDptr/ylen/yLSDptr bilden die DS des kürzeren Arguments y. + // Es ist len>ylen. + // subtrahieren: + { var uintD* midptr = LSDptr lspop ylen; + var uintD carry = subfrom_loop_lsp(yLSDptr,LSDptr,ylen); + if (carry) + { // Carry. + if ((sintD)mspref(yMSDptr,0) >=0) // kürzerer Summand war positiv + // Dann ist ein negativer Übertrag weiterzutragen + // (Beispiel: 00030003 - 0007 = 0002FFFC) + { DS_minus1_plus(midptr,len-ylen); } + } + else + { // Kein Carry. + if ((sintD)mspref(yMSDptr,0) <0) // kürzerer Summand war negativ + // Dann ist ein positiver Übertrag weiterzutragen + // (Beispiel: 0002FFF8 - FFF5 = 00030003) + { DS_1_plus(midptr,len-ylen); } + } } + return DS_to_I(MSDptr,len); // DS wieder zum Integer machen + } + else + { // y das längere von beiden. + CL_ALLOCA_STACK; + BN_to_NDS_1(y, MSDptr=,len=,LSDptr=); // NDS zu y bilden. + // vorsorglich 1 Digit mehr belegen: + { var sintD sign = sign_of_sintD(mspref(MSDptr,0)); + lsprefnext(MSDptr) = sign; len++; + } + // Negierschleife: + neg_loop_lsp(LSDptr,len); + // MSDigit ist nun = 0x0000 oder = 0xFFFF + var const uintD* xMSDptr; + var uintC xlen; + var const uintD* xLSDptr; + BN_to_NDS_nocopy(x, xMSDptr=,xlen=,xLSDptr=); // NDS zu x bilden. + // xMSDptr/xlen/xLSDptr bilden die DS des kürzeren Arguments x. + // Es ist jetzt len>xlen. + // addieren: + { var uintD* midptr = LSDptr lspop xlen; + var uintD carry = addto_loop_lsp(xLSDptr,LSDptr,xlen); + if (carry) + { // Carry. + if ((sintD)mspref(xMSDptr,0) >=0) // kürzerer Summand war positiv + // Dann ist ein positiver Übertrag weiterzutragen + // (Beispiel: 0002FFFC + 0007 = 00030003) + { DS_1_plus(midptr,len-xlen); } + } + else + { // Kein Carry. + if ((sintD)mspref(xMSDptr,0) <0) // kürzerer Summand war negativ + // Dann ist ein negativer Übertrag weiterzutragen + // (Beispiel: 00020003 + FFF5 = 0001FFF8) + { DS_minus1_plus(midptr,len-xlen); } + } } + return DS_to_I(MSDptr,len); // DS wieder zum Integer machen + } + } } +} diff --git a/src/integer/elem/cl_I_minus1.cc b/src/integer/elem/cl_I_minus1.cc new file mode 100644 index 0000000..38aa660 --- /dev/null +++ b/src/integer/elem/cl_I_minus1.cc @@ -0,0 +1,33 @@ +// minus1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" + +const cl_I minus1 (const cl_I& x) +{ + if (fixnump(x)) + { // x ist Fixnum + if (x.word != cl_combine(cl_FN_tag,bit(cl_value_len-1))) + // bleibt Fixnum: direkt 1 subtrahieren + // This assumes cl_value_shift + cl_value_len == cl_word_size. + { return cl_I_from_word(x.word - cl_combine(0,1)); } + } + // die sichere Methode + { CL_ALLOCA_STACK; + var uintD* MSDptr; + var uintC len; + var uintD* LSDptr; + I_to_NDS_1(x, MSDptr=,len=,LSDptr=); // NDS zu x bilden. + DS_minus1_plus(LSDptr,len); // von der NDS 1 subtrahieren + return DS_to_I(MSDptr,len); // wieder zum Integer machen + } +} diff --git a/src/integer/elem/cl_I_minusp.cc b/src/integer/elem/cl_I_minusp.cc new file mode 100644 index 0000000..b2a2cac --- /dev/null +++ b/src/integer/elem/cl_I_minusp.cc @@ -0,0 +1,19 @@ +// minusp(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#define minusp inline_minusp +#include "cl_I.h" +#undef minusp + +cl_boolean minusp (const cl_I& x) +{ + return inline_minusp(x); +} diff --git a/src/integer/elem/cl_I_mul.cc b/src/integer/elem/cl_I_mul.cc new file mode 100644 index 0000000..1558797 --- /dev/null +++ b/src/integer/elem/cl_I_mul.cc @@ -0,0 +1,52 @@ +// binary operator * + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" +#include "cl_low.h" + +const cl_I operator* (const cl_I& x, const cl_I& y) +{ + // Methode: + // x=0 oder y=0 -> Ergebnis 0 + // x und y beide Fixnums -> direkt multiplizieren + // sonst: zu DS machen, multiplizieren. + if (zerop(x)) + { return 0; } + if (zerop(y)) + { return 0; } + if (fixnump(x) && fixnump(y)) + { var sint32 x_ = FN_to_L(x); + var sint32 y_ = FN_to_L(y); + // Werte direkt multiplizieren: + var uint32 hi; + var uint32 lo; + mulu32((uint32)x_,(uint32)y_,hi=,lo=); // erst unsigned multiplizieren + if (x_ < 0) { hi -= (uint32)y_; } // dann Korrektur für Vorzeichen + if (y_ < 0) { hi -= (uint32)x_; } // (vgl. DS_DS_mul_DS) + return L2_to_I(hi,lo); + } + CL_ALLOCA_STACK; + var const uintD* xMSDptr; + var uintC xlen; + var const uintD* xLSDptr; + var const uintD* yMSDptr; + var uintC ylen; + var const uintD* yLSDptr; + var uintD* ergMSDptr; + var uintC erglen; + I_to_NDS_nocopy(x, xMSDptr = , xlen = , xLSDptr = , cl_false,); + I_to_NDS_nocopy(y, yMSDptr = , ylen = , yLSDptr = , cl_false,); + DS_DS_mul_DS(xMSDptr,xlen,xLSDptr,yMSDptr,ylen,yLSDptr, ergMSDptr=,erglen=,); + return DS_to_I(ergMSDptr,erglen); +} +// Bit complexity (x,y of length N): O(M(N)). + diff --git a/src/integer/elem/cl_I_plus.cc b/src/integer/elem/cl_I_plus.cc new file mode 100644 index 0000000..bd2b014 --- /dev/null +++ b/src/integer/elem/cl_I_plus.cc @@ -0,0 +1,201 @@ +// binary operator + + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" + +const cl_I operator+ (const cl_I& x, const cl_I& y) +{ + // Methode: + // x Fixnum -> + // y Fixnum -> beide direkt addieren, mit L_to_I beenden + // y Bignum -> falls x=0, y; sonst beide zu DS machen, addieren. + // x Bignum -> + // y Fixnum -> falls y=0, x; sonst beide zu DS machen, addieren. + // y Bignum -> beide zu DS machen, addieren. + var uintD* MSDptr; + var uintC len; + var uintD* LSDptr; + // MSDptr/len/LSDptr bilden die DS des Ergebnisses. + if (fixnump(x)) + { // x ist Fixnum + if (fixnump(y)) + { // x,y sind Fixnums + #if (cl_value_len < intLsize) + return L_to_I( FN_to_L(x) + FN_to_L(y) ); // als 32-Bit-Zahlen addieren + #elif (cl_word_size==64) + return Q_to_I( FN_to_Q(x) + FN_to_Q(y) ); // als 64-Bit-Zahlen addieren + #else // (cl_value_len == intLsize) + var sint32 xhi = sign_of(FN_to_L(x)); + var uint32 xlo = FN_to_L(x); + var sint32 yhi = sign_of(FN_to_L(y)); + var uint32 ylo = FN_to_L(y); + xhi += yhi; + xlo += ylo; + if (xlo < ylo) { xhi += 1; } + return L2_to_I(xhi,xlo); + #endif + } + else + { // x ist Fixnum, y ist Bignum, also y länger + #if (intDsize==64) + var sint64 x_ = FN_to_L(x); // Wert von x + #else + var sint32 x_ = FN_to_L(x); // Wert von x + #endif + if (FN_L_zerop(x,x_)) { return y; } // bei x=0 Ergebnis y + CL_ALLOCA_STACK; + BN_to_NDS_1(y, MSDptr=,len=,LSDptr=); // NDS zu y bilden. + // len>=bn_minlength. len>pFN_maxlength erzwingen: + if ((bn_minlength==pFN_maxlength) && (len==pFN_maxlength)) + { var sintD sign = sign_of_sintD(mspref(MSDptr,0)); + lsprefnext(MSDptr) = sign; len++; + } + // x_ zu den oberen pFN_maxlength Digits von y addieren: + { + #if (intDsize==64) + var uint64 y_ = lspref(LSDptr,0); + var uint64 y_new = y_+(uint64)x_; + lspref(LSDptr,0) = y_new; + #else + var uint32 y_ = pFN_maxlength_digits_at(LSDptr); + var uint32 y_new = y_+(uint32)x_; + set_pFN_maxlength_digits_at(LSDptr,y_new); + #endif + var uintD* midptr = LSDptr lspop pFN_maxlength; + if (y_new < y_) + { // Carry. + if (!FN_L_minusp(x,x_)) // kürzerer Summand war positiv + // Dann ist ein positiver Übertrag weiterzutragen + // (Beispiel: 0002FFFC + 0007 = 00030003) + { DS_1_plus(midptr,len-pFN_maxlength); } + } + else + { // Kein Carry. + if (FN_L_minusp(x,x_)) // kürzerer Summand war negativ + // Dann ist ein negativer Übertrag weiterzutragen + // (Beispiel: 00020003 + FFF5 = 0001FFF8) + { DS_minus1_plus(midptr,len-pFN_maxlength); } + } } + return DS_to_I(MSDptr,len); // DS wieder zum Integer machen + } + } + else + { // x ist Bignum + if (fixnump(y)) + { // x ist Bignum, y ist Fixnum, also x länger + #if (intDsize==64) + var sint64 y_ = FN_to_L(y); // Wert von y + #else + var sint32 y_ = FN_to_L(y); // Wert von y + #endif + if (FN_L_zerop(y,y_)) { return x; } // bei y=0 Ergebnis x + CL_ALLOCA_STACK; + BN_to_NDS_1(x, MSDptr=,len=,LSDptr=); // NDS zu x bilden. + // len>=bn_minlength. len>pFN_maxlength erzwingen: + if ((bn_minlength==pFN_maxlength) && (len==pFN_maxlength)) + { var sintD sign = sign_of_sintD(mspref(MSDptr,0)); + lsprefnext(MSDptr) = sign; len++; + } + // y_ zu den oberen pFN_maxlength Digits von x addieren: + { + #if (intDsize==64) + var uint64 x_ = lspref(LSDptr,0); + var uint64 x_new = x_+(uint64)y_; + lspref(LSDptr,0) = x_new; + #else + var uint32 x_ = pFN_maxlength_digits_at(LSDptr); + var uint32 x_new = x_+(uint32)y_; + set_pFN_maxlength_digits_at(LSDptr,x_new); + #endif + var uintD* midptr = LSDptr lspop pFN_maxlength; + if (x_new < x_) + { // Carry. + if (!FN_L_minusp(y,y_)) // kürzerer Summand war positiv + // Dann ist ein positiver Übertrag weiterzutragen + // (Beispiel: 0002FFFC + 0007 = 00030003) + { DS_1_plus(midptr,len-pFN_maxlength); } + } + else + { // Kein Carry. + if (FN_L_minusp(y,y_)) // kürzerer Summand war negativ + // Dann ist ein negativer Übertrag weiterzutragen + // (Beispiel: 00020003 + FFF5 = 0001FFF8) + { DS_minus1_plus(midptr,len-pFN_maxlength); } + } } + return DS_to_I(MSDptr,len); // DS wieder zum Integer machen + } + else + { // x und y sind Bignums + CL_ALLOCA_STACK; + if (TheBignum(x)->length > TheBignum(y)->length) + { // x das längere von beiden. + BN_to_NDS_1(x, MSDptr=,len=,LSDptr=); // NDS zu x bilden. + var const uintD* yMSDptr; + var uintC ylen; + var const uintD* yLSDptr; + BN_to_NDS_nocopy(y, yMSDptr=,ylen=,yLSDptr=); // NDS zu y bilden. + // yMSDptr/ylen/yLSDptr bilden die DS des kürzeren Arguments y. + // Es ist len>ylen. + // addieren: + { var uintD* midptr = LSDptr lspop ylen; + var uintD carry = addto_loop_lsp(yLSDptr,LSDptr,ylen); + if (carry) + { // Carry. + if ((sintD)mspref(yMSDptr,0) >=0) // kürzerer Summand war positiv + // Dann ist ein positiver Übertrag weiterzutragen + // (Beispiel: 0002FFFC + 0007 = 00030003) + { DS_1_plus(midptr,len-ylen); } + } + else + { // Kein Carry. + if ((sintD)mspref(yMSDptr,0) <0) // kürzerer Summand war negativ + // Dann ist ein negativer Übertrag weiterzutragen + // (Beispiel: 00020003 + FFF5 = 0001FFF8) + { DS_minus1_plus(midptr,len-ylen); } + } } + return DS_to_I(MSDptr,len); // DS wieder zum Integer machen + } + else + { // y das längere von beiden. + BN_to_NDS_1(y, MSDptr=,len=,LSDptr=); // NDS zu y bilden. + var const uintD* xMSDptr; + var uintC xlen; + var const uintD* xLSDptr; + BN_to_NDS_nocopy(x, xMSDptr=,xlen=,xLSDptr=); // NDS zu x bilden. + // xMSDptr/xlen/xLSDptr bilden die DS des kürzeren Arguments x. + // len>xlen erzwingen: + if (len==xlen) + { var sintD sign = sign_of_sintD(mspref(MSDptr,0)); + lsprefnext(MSDptr) = sign; len++; + } + // addieren: + { var uintD* midptr = LSDptr lspop xlen; + var uintD carry = addto_loop_lsp(xLSDptr,LSDptr,xlen); + if (carry) + { // Carry. + if ((sintD)mspref(xMSDptr,0) >=0) // kürzerer Summand war positiv + // Dann ist ein positiver Übertrag weiterzutragen + // (Beispiel: 0002FFFC + 0007 = 00030003) + { DS_1_plus(midptr,len-xlen); } + } + else + { // Kein Carry. + if ((sintD)mspref(xMSDptr,0) <0) // kürzerer Summand war negativ + // Dann ist ein negativer Übertrag weiterzutragen + // (Beispiel: 00020003 + FFF5 = 0001FFF8) + { DS_minus1_plus(midptr,len-xlen); } + } } + return DS_to_I(MSDptr,len); // DS wieder zum Integer machen + } + } + } +} diff --git a/src/integer/elem/cl_I_plus1.cc b/src/integer/elem/cl_I_plus1.cc new file mode 100644 index 0000000..58c90d7 --- /dev/null +++ b/src/integer/elem/cl_I_plus1.cc @@ -0,0 +1,33 @@ +// plus1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" + +const cl_I plus1 (const cl_I& x) +{ + if (fixnump(x)) + { // x ist Fixnum + if (x.word != cl_combine(cl_FN_tag,bit(cl_value_len-1)-1)) + // bleibt Fixnum: direkt 1 addieren + // This assumes cl_value_shift + cl_value_len == cl_word_size. + { return cl_I_from_word(x.word + cl_combine(0,1)); } + } + // die sichere Methode + { CL_ALLOCA_STACK; + var uintD* MSDptr; + var uintC len; + var uintD* LSDptr; + I_to_NDS_1(x, MSDptr=,len=,LSDptr=); // NDS zu x bilden. + DS_1_plus(LSDptr,len); // zur NDS 1 addieren + return DS_to_I(MSDptr,len); // wieder zum Integer machen + } +} diff --git a/src/integer/elem/cl_I_plusp.cc b/src/integer/elem/cl_I_plusp.cc new file mode 100644 index 0000000..ce47a98 --- /dev/null +++ b/src/integer/elem/cl_I_plusp.cc @@ -0,0 +1,26 @@ +// plusp(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#define minusp inline_minusp +#define zerop inline_zerop +#include "cl_I.h" +#undef zerop +#undef minusp + +cl_boolean plusp (const cl_I& x) +{ + if (inline_minusp(x)) + return cl_false; // x<0 -> nein + elif (inline_zerop(x)) + return cl_false; // x=0 -> nein + else + return cl_true; // sonst ist x>0. +} diff --git a/src/integer/elem/cl_I_square.cc b/src/integer/elem/cl_I_square.cc new file mode 100644 index 0000000..d14f3cd --- /dev/null +++ b/src/integer/elem/cl_I_square.cc @@ -0,0 +1,51 @@ +// square(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" +#include "cl_low.h" + +const cl_I square (const cl_I& x) +{ + // Methode: + // x Fixnum -> direkt multiplizieren + // sonst: zu DS machen, multiplizieren. + if (fixnump(x)) + { var sint32 x_ = FN_to_L(x); + // Werte direkt multiplizieren: + var uint32 hi; + var uint32 lo; + mulu32((uint32)x_,(uint32)x_,hi=,lo=); // erst unsigned multiplizieren + if (x_ < 0) { hi -= 2*(uint32)x_; } // dann Korrektur für Vorzeichen + return L2_to_I(hi,lo); + } + CL_ALLOCA_STACK; + var const uintD* xMSDptr; + var uintC xlen; + var const uintD* xLSDptr; + I_to_NDS_nocopy(x, xMSDptr = , xlen = , xLSDptr = , cl_false,); + var uintD* ergMSDptr; + var uintC erglen = 2*xlen; + var uintD* ergLSDptr; + num_stack_alloc(erglen,ergMSDptr=,ergLSDptr=); + var uintC len = xlen; + var uintD MSD = mspref(xMSDptr,0); + if (MSD==0) + { mspref(ergMSDptr,0) = 0; mspref(ergMSDptr,1) = 0; len--; } + cl_UDS_mul_square(xLSDptr,len,ergLSDptr); + if ((sintD)MSD < 0) + { subfrom_loop_lsp(xLSDptr,ergLSDptr lspop xlen,xlen); + subfrom_loop_lsp(xLSDptr,ergLSDptr lspop xlen,xlen); + } + return DS_to_I(ergMSDptr,erglen); +} +// Bit complexity (x of length N): O(M(N)). + diff --git a/src/integer/elem/cl_I_uminus.cc b/src/integer/elem/cl_I_uminus.cc new file mode 100644 index 0000000..d9dbb20 --- /dev/null +++ b/src/integer/elem/cl_I_uminus.cc @@ -0,0 +1,43 @@ +// unary operator - + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" + +const cl_I operator- (const cl_I& x) +{ + if (fixnump(x)) { + #if (cl_value_len < intLsize) + return L_to_I(- FN_to_L(x)); + #elif (cl_word_size==64) + return Q_to_I(- FN_to_Q(x)); + #else // (cl_value_len == intLsize) + var sint32 xhi = sign_of(FN_to_L(x)); + var uint32 xlo = FN_to_L(x); + return L2_to_I(-xhi-(xlo!=0),-xlo); + #endif + } else { + // x Bignum + CL_ALLOCA_STACK; + var uintD* MSDptr; + var uintC len; + var uintD* LSDptr; + BN_to_NDS_1(x, MSDptr=,len=,LSDptr=); // NDS zu x bilden, len>0 + // vorsorglich 1 Digit mehr belegen: + { var sintD sign = sign_of_sintD(mspref(MSDptr,0)); + lsprefnext(MSDptr) = sign; len++; + } + // Negierschleife: + neg_loop_lsp(LSDptr,len); + // MSDigit ist nun = 0x0000 oder = 0xFFFF + return DS_to_I(MSDptr,len); // DS wieder zum Integer machen + } +} diff --git a/src/integer/elem/cl_I_zerop.cc b/src/integer/elem/cl_I_zerop.cc new file mode 100644 index 0000000..db57125 --- /dev/null +++ b/src/integer/elem/cl_I_zerop.cc @@ -0,0 +1,19 @@ +// zerop(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#define zerop inline_zerop +#include "cl_I.h" +#undef zerop + +cl_boolean zerop (const cl_I& x) +{ + return inline_zerop(x); +} diff --git a/src/integer/gcd/Makeflags b/src/integer/gcd/Makeflags new file mode 100644 index 0000000..3696f90 --- /dev/null +++ b/src/integer/gcd/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/integer/Makeflags +SUBDIR_INCLUDES += diff --git a/src/integer/gcd/cl_I_gcd.cc b/src/integer/gcd/cl_I_gcd.cc new file mode 100644 index 0000000..f530ed6 --- /dev/null +++ b/src/integer/gcd/cl_I_gcd.cc @@ -0,0 +1,519 @@ +// gcd(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" +#include "cl_D.h" +#include "cl_xmacros.h" + +#define GCD_ALGO 3 // 1: binär, 2: Schulmethode, 3: Lehmer + + +#if (GCD_ALGO == 1) + +// binäre Methode: +// (gcd a b) :== +// b=0 --> (abs a) +// a=0 --> (abs b) +// sonst: +// (abs a) und (abs b) in zwei Buffer packen, als Unsigned Digit Sequences. +// [Schreibe oBdA wieder a,b] +// (prog ((j 0)) +// 1 {a,b >0} +// (if (evenp a) +// (if (evenp b) +// (progn (incf j) (setq a (/ a 2)) (setq b (/ b 2)) (go 1)) +// (go 4) +// ) +// (while (evenp b) (setq b (/ b 2))) +// ) +// 2 {a,b >0, beide ungerade} +// (cond ((> a b)) +// ((= a b) (go 5)) +// ((< a b) (rotatef a b)) +// ) +// 3 {a,b >0, beide ungerade, a>b} +// (setq a (- a b)) +// 4 {a,b >0, a gerade, b ungerade} +// (repeat (setq a (/ a 2)) (until (oddp a))) +// (go 2) +// 5 {a=b>0} +// (return (ash a j)) +// ) +// weil es oft auftritt (insbesondere bei GCD's mehrerer Zahlen): +// a=1 oder b=1 --> 1 + + const cl_I gcd (const cl_I& a, const cl_I& b) + { if (eq(a,1)) { return 1; } // a=1 -> 1 + if (eq(b,1)) { return 1; } // b=1 -> 1 + if (eq(b,0)) { return abs(a); } // b=0 -> (abs a) + if (eq(a,0)) { return abs(b); } // a=0 -> (abs b) + CL_ALLOCA_STACK; + var uintD* a_MSDptr; + var uintC a_len; + var uintD* a_LSDptr; + var uintD* b_MSDptr; + var uintC b_len; + var uintD* b_LSDptr; + // Macro: erzeugt die NUDS zu (abs x), erniedrigt num_stack + #define I_abs_to_NUDS(x) \ + I_to_NDS_1(x, x##_MSDptr = , x##_len = , x##_LSDptr = ); /* (nichtleere) NDS holen */\ + if ((sintD)mspref(x##_MSDptr,0) < 0) /* falls <0, negieren: */\ + { neg_loop_lsp(x##_LSDptr,x##_len); } \ + if (mspref(x##_MSDptr,0) == 0) /* normalisieren (max. 1 Nulldigit entfernen) */\ + { msshrink(x##_MSDptr); x##_len--; } + I_abs_to_NUDS(a); // (abs a) als NUDS erzeugen + I_abs_to_NUDS(b); // (abs b) als NUDS erzeugen + // Jetzt ist a = a_MSDptr/a_len/a_LSDptr, b = b_MSDptr/b_len/b_LSDptr, + // beides NUDS, und a_len>0, b_len>0. + // Macro: Halbiere x. + #define halb(x) \ + { shift1right_loop_msp(x##_MSDptr,x##_len,0); /* um 1 Bit rechts schieben */ \ + if (mspref(x##_MSDptr,0) == 0) { msshrink(x##_MSDptr); x##_len--; } /* normalisieren */\ + } + // Macro: Ob x gerade ist. + #define evenp(x) \ + ((lspref(x##_LSDptr,0) & bit(0)) ==0) + { var uintL j = 0; + label_1: // a,b >0 + if (evenp(a)) + { if (evenp(b)) + { j++; halb(a); halb(b); goto label_1; } + else + goto label_4; + } + while (evenp(b)) { halb(b); } + label_2: // a,b >0, beide ungerade + // Vergleiche a und b: + if (a_len > b_len) goto label_3; // a>b ? + if (a_len == b_len) + { var cl_signean vergleich = compare_loop_msp(a_MSDptr,b_MSDptr,a_len); + if (vergleich > 0) goto label_3; // a>b ? + if (vergleich == 0) goto label_5; // a=b ? + } + // a a,b vertauschen: + swap(uintD*, a_MSDptr,b_MSDptr); + swap(uintC, a_len,b_len); + swap(uintD*, a_LSDptr,b_LSDptr); + label_3: // a,b >0, beide ungerade, a>b + // subtrahiere a := a - b + if (!( subfrom_loop_lsp(b_LSDptr,a_LSDptr,b_len) ==0)) + { dec_loop_lsp(a_LSDptr lspop b_len,a_len-b_len); } + while (mspref(a_MSDptr,0) == 0) { msshrink(a_MSDptr); a_len--; } // normalisieren + label_4: // a,b >0, a gerade, b ungerade + do { halb(a); } while (evenp(a)); + goto label_2; + label_5: // a=b>0 + // a zu einer NDS machen: + return ash(NUDS_to_I(a_MSDptr,a_len),j); // ggT der ungeraden Anteile als Integer, mal 2^j + } + #undef evenp + #undef halb + #undef I_abs_to_NUDS + } + +#endif /* GCD_ALGO == 1 */ + + +#if (GCD_ALGO == 2) + +// Schulmethode: +// (gcd a b) :== +// [a:=(abs a), b:=(abs b), while b>0 do (a,b) := (b,(mod a b)), -> a] +// verbessert: +// a=0 -> (abs b) +// b=0 -> (abs a) +// a=1 -> 1 +// b=1 -> 1 +// a:=(abs a), b:=(abs b) +// Falls a=b: return a; falls ab>0} +// Falls b=1, return 1. {spart eine Division durch 1} +// Sonst dividieren (divide a b), a:=b, b:=Rest. +// Falls b=0, return a, sonst goto (*). + + const cl_I gcd (const cl_I& a, const cl_I& b) + { if (eq(a,1)) { return 1; } // a=1 -> 1 + if (eq(b,1)) { return 1; } // b=1 -> 1 + if (eq(b,0)) { return abs(a); } // b=0 -> (abs a) + if (eq(a,0)) { return abs(b); } // a=0 -> (abs b) + // Beträge nehmen: + {var cl_I abs_a = abs(a); + var cl_I abs_b = abs(b); + var cl_I& a = abs_a; + var cl_I& b = abs_b; + if (fixnump(a) && fixnump(b)) // ggT zweier Fixnums >0 + { // bleibt Fixnum, da (gcd a b) <= (min a b) + return L_to_FN(gcd(FN_to_UL(a),FN_to_UL(b))); + } + { var cl_signean vergleich = cl_compare(a,b); + if (vergleich == 0) { return a; } // a=b -> fertig + if (vergleich < 0) { var cl_I tmp = a; a = b; b = a; } // a a,b vertauschen + } + loop // Hier a > b > 0 + { if (eq(b,1)) { return 1; } // b=1 -> Ergebnis 1 + { var cl_I_div_t div = cl_divide(a,b); a = b; b = div.remainder; } + if (eq(b,0)) { return a; } + } + }} + +#endif /* GCD_ALGO == 2 */ + + +#if (GCD_ALGO == 3) + +// Lehmer-Methode: +// vgl. [ D. E. Knuth: The Art of Computer Programming, Vol. 2: Seminumerical +// Algorithms, Sect. 4.5.2., Algorithm L ] +// und [ Collins, Loos: SAC-2, Algorithms IGCD, DPCC ]. +// (gcd a b) :== +// a=0 -> (abs b) +// b=0 -> (abs a) +// a=1 -> 1 +// b=1 -> 1 +// a:=(abs a), b:=(abs b) +// (*) {Hier a,b>0} +// Falls a=b: return a; falls ab>0} +// Falls (- (integer-length a) (integer-length b)) >= intDsize/2, +// lohnt sich eine Division: (a,b) := (b , a mod b). Falls b=0: return a. +// Falls dagegen 0 <= (- (integer-length a) (integer-length b)) < intDsize/2, +// seien a' die führenden intDsize Bits von a +// (2^(intDsize-1) <= a' < 2^intDsize) und b' die entsprechenden Bits von b +// (2^(intDsize/2) <= b' <= a' < 2^intDsize). +// Rechne den Euklid-Algorithmus mit Beifaktoren für ALLE Zahlen (a,b) aus, +// die mit a' bzw. b' anfangen; das liefert x1,y1,x2,y2, so daß +// ggT(a,b) = ggT(x1*a-y1*b,-x2*a+y2*b) und x1*a-y1*b>=0,-x2*a+y2*b>=0. +// Genauer: Mit offensichtlicher Skalierung betrachten wir +// a als beliebiges Element des Intervalls [a',a'+1) und +// b als beliebiges Element des Intervalls [b',b'+1) und +// führen den Euklid-Algorithmus schrittweise durch: +// (x1,y1,z1) := (1,0,a'), (x2,y2,z2) := (0,1,b'), +// Schleife: +// {Hier x1*a'-y1*b'=z1, x1*a-y1*b in [z1-y1,z1+x1), z1-y1>=0, z1>0, +// und -x2*a'+y2*b'=z2, -x2*a+y2*b in [z2-x2,z2+y2), z2-x2>=0, z2>0, +// x1*y2-x2*y1=1, x1*z2+x2*z1=b', y1*z2+y2*z1=a'.} +// Falls z1-y1>=z2+y2: +// (x1,y1,z1) := (x1+x2,y1+y2,z1-z2), goto Schleife. +// Falls z2-x2>=z1+x1: +// (x2,y2,z2) := (x2+x1,y2+y1,z2-z1), goto Schleife. +// Sonst muß man abbrechen. +// {Zu den Schleifeninvarianten: +// 1. Die Gleichungen x1*a'-y1*b'=z1, -x2*a'+y2*b'=z2, +// x1*y2-x2*y1=1, x1*z2+x2*z1=b', y1*z2+y2*z1=a' mit Induktion. +// 2. Die Ungleichungen x1>0, y1>=0, x2>=0, y2>0 mit Induktion. +// 3. Die Ungleichungen z1>=0, z2>=0 nach Fallauswahl. +// 4. Die Ungleichung x1+x2>0 aus x1*z2+x2*z1=b'>0, +// die Ungleichung y1+y2>0 aus y1*z2+y2*z1=a'>0. +// 5. Die Ungleichung z1>0 wegen Fallauswahl und y1+y2>0, +// Die Ungleichung z2>0 wegen Fallauswahl und x1+x2>0. +// 6. Die Ungleichungen z1-y1>=0, z2-x2>=0 wegen Fallauswahl. +// 7. Die Ungleichung max(z1,z2) <= a' mit Induktion. +// 8. Die Ungleichung x1+x2 <= x1*z2+x2*z1 = b', +// die Ungleichung y1+y2 <= y1*z2+y2*z1 = a'. +// Damit bleiben alle Größen im Intervall [0,beta), kein Überlauf. +// 9. Die Ungleichungen z1+x1<=beta, z2+y2<=beta mit Induktion. +// 10. x1*a-y1*b in (z1-y1,z1+x1) (bzw. [z1,z1+x1) bei y1=0), +// -x2*a+y2*b in (z2-x2,z2+y2) (bzw. [z2,z2+y2) bei x2=0), +// da a in a'+[0,1) und b in b'+[0,1). +// Jedenfalls 0 < x1*a-y1*b < z1+x1 <= x2*z1+x1*z2 = b' falls x2>0, +// und 0 < -x2*a+y2*b < z2+y2 <= y1*z2+y2*z1 = a' falls y1>0.} +// Man kann natürlich auch mehrere Subtraktionsschritte auf einmal +// durchführen: +// Falls q := floor((z1-y1)/(z2+y2)) > 0 : +// (x1,y1,z1) := (x1+q*x2,y1+q*y2,z1-q*z2), goto Schleife. +// Falls q := floor((z2-x2)/(z1+x1)) > 0 : +// (x2,y2,z2) := (x2+q*x1,y2+q*y1,z2-q*z1), goto Schleife. +// {Am Schluß gilt -(x1+x2) < z1-z2 < y1+y2 und daher +// z2-x2 <= b'/(x1+x2) < z1+x1, z1-y1 <= a'/(y1+y2) < z2+y2, +// und - unter Berücksichtigung von x1*y2-x2*y1=1 - +// z1-y1 <= b'/(x1+x2) < z2+y2, z2-x2 <= a'/(y1+y2) < z1+x1, +// also max(z1-y1,z2-x2) <= min(b'/(x1+x2),a'/(y1+y2)) +// <= max(b'/(x1+x2),a'/(y1+y2)) < min(z1+x1,z2+y2).} +// Im Fall y1=x2=0 => x1=y2=1 (der nur bei a'=z1=z2=b' eintreten kann) +// ersetze (a,b) := (a-b,b). {Beide >0, da a>b>0 war.} +// Der Fall y1=0,x2>0 => x1=y2=1 => a' = z1 < z2+x2*z1 = b' +// kann nicht eintreten. +// Im Fall x2=0,y1>0 => x1=y2=1 ersetze (a,b) := (a-y1*b,b). +// {Das ist OK, da 0 <= z1-y1 = a'-y1*(b'+1) < a-y1*b < a.} +// Sonst (y1>0,x2>0) ersetze (a,b) := (x1*a-y1*b,-x2*a+y2*b). +// {Das ist OK, da 0 <= z1-y1 = x1*a'-y1*(b'+1) < x1*a-y1*b +// und 0 <= z2-x2 = -x2*(a'+1)+y2*b' < -x2*a+y2*b +// und x1*a-y1*b < x1*(a'+1)-y1*b' = z1+x1 <= x2*z1+x1*z2 = b' <= b +// und -x2*a+y2*b < -x2*a'+y2*(b'+1) = z2+y2 <= y1*z2+y2*z1 = a' <= a.} +// goto (*). + + // Define this to 1 in order to use double-word sized a' and b'. + // This gives better x1,y1,x2,y2, because normally the values x1,y1,x2,y2 + // have only about intDsize/2 bits and so half of the multiplication work + // is lost. Actually, this flag multiplies the gcd speed by 1.5, not 2.0. + #define DOUBLE_SPEED 1 + // Speed increases only for large integers. For small ones, computing + // with double-word sized a' and b' is too costly. The threshold is + // between 12 and 20, around 15. + #define cl_gcd_double_threshold 16 + + // gcd of two single-word numbers >0 + static uintD gcdD (uintD a, uintD b) + { var uintD bit_j = (a | b); // endet mit einer 1 und j Nullen + bit_j = bit_j ^ (bit_j - 1); // Maske = bit(j) | bit(j-1) | ... | bit(0) + if (!((a & bit_j) ==0)) + { if (!((b & bit_j) ==0)) goto odd_odd; else goto odd_even; } + if (!((b & bit_j) ==0)) goto even_odd; + NOTREACHED; + loop + { odd_odd: // a,b >0, beide ungerade + // Vergleiche a und b: + if (a == b) break; // a=b>0 -> fertig + if (a > b) // a>b ? + { a = a-b; + even_odd: // a,b >0, a gerade, b ungerade + do { a = a>>1; } while ((a & bit_j) ==0); + } + else // a0, a ungerade, b gerade + do { b = b>>1; } while ((b & bit_j) ==0); + } + } + // a=b>0 + return a; + } + + const cl_I gcd (const cl_I& a, const cl_I& b) + { if (eq(a,1)) { return 1; } // a=1 -> 1 + if (eq(b,1)) { return 1; } // b=1 -> 1 + if (eq(b,0)) { return abs(a); } // b=0 -> (abs a) + if (eq(a,0)) { return abs(b); } // a=0 -> (abs b) + if (fixnump(a) && fixnump(b)) // ggT zweier Fixnums /=0 + { var sintL a_ = FN_to_L(a); + if (a_ < 0) { a_ = -a_; } + var sintL b_ = FN_to_L(b); + if (b_ < 0) { b_ = -b_; } + return UL_to_I(gcd((uint32)a_,(uint32)b_)); + } + CL_ALLOCA_STACK; + var uintD* a_MSDptr; + var uintC a_len; + var uintD* a_LSDptr; + var uintD* b_MSDptr; + var uintC b_len; + var uintD* b_LSDptr; + // Macro: erzeugt die NUDS zu (abs x), erniedrigt num_stack + #define I_abs_to_NUDS(x) \ + I_to_NDS_1(x, x##_MSDptr = , x##_len = , x##_LSDptr = ); /* (nichtleere) NDS holen */\ + if ((sintD)mspref(x##_MSDptr,0) < 0) /* falls <0, negieren: */\ + { neg_loop_lsp(x##_LSDptr,x##_len); } \ + if (mspref(x##_MSDptr,0) == 0) /* normalisieren (max. 1 Nulldigit entfernen) */\ + { msshrink(x##_MSDptr); x##_len--; } + I_abs_to_NUDS(a); // (abs a) als NUDS erzeugen + I_abs_to_NUDS(b); // (abs b) als NUDS erzeugen + // Jetzt ist a = a_MSDptr/a_len/a_LSDptr, b = b_MSDptr/b_len/b_LSDptr, + // beides NUDS, und a_len>0, b_len>0. + // Platz für zwei Rechenregister besorgen, mit je max(a_len,b_len)+1 Digits: + {var uintD* divroomptr; // Platz für Divisionsergebnis + var uintD* c_LSDptr; + var uintD* d_LSDptr; + {var uintL c_len = (uintL)(a_len>=b_len ? a_len : b_len) + 1; + num_stack_alloc(c_len,divroomptr=,c_LSDptr=); + num_stack_alloc(c_len,,d_LSDptr=); + // Jetzt ist ../c_len/c_LSDptr, ../c_len/d_LSDptr frei. + } + loop + { // Hier a,b>0, beides NUDS. + // Vergleiche a und b: + if (a_len > b_len) goto a_greater_b; // a>b ? + if (a_len == b_len) + { var cl_signean vergleich = compare_loop_msp(a_MSDptr,b_MSDptr,a_len); + if (vergleich > 0) goto a_greater_b; // a>b ? + if (vergleich == 0) break; // a=b ? + } + // a a,b vertauschen: + swap(uintD*, a_MSDptr,b_MSDptr); + swap(uintC, a_len,b_len); + swap(uintD*, a_LSDptr,b_LSDptr); + a_greater_b: + // Hier a>b>0, beides NUDS. + if (b_len==1) // Beschleunigung eines häufigen Falles + { var uintD b0 = mspref(b_MSDptr,0); + if (b0==1) + // a>b=1 -> Ergebnis 1. + { return 1; } + // a>b>1 -> evtl. Division durch b + var uintD a0; + if (a_len==1) + { a0 = mspref(a_MSDptr,0); } + else + { a0 = divu_loop_msp(b0,a_MSDptr,a_len); + if (a0==0) + { return UD_to_I(b0); } + } + return UD_to_I(gcdD(a0,b0)); + } + // Entscheidung, ob Division oder Linearkombination: + { var uintD a_msd; // führende intDsize Bits von a + var uintD b_msd; // entsprechende Bits von b + #if DOUBLE_SPEED + var uintD a_nsd; // nächste intDsize Bits von a + var uintD b_nsd; // entsprechende Bits von b + #endif + { var uintC len_diff = a_len-b_len; // Längendifferenz + if (len_diff > 1) goto divide; // >=2 -> Bitlängendifferenz>intDsize -> dividieren + #define bitlendiff_limit (intDsize/2) // sollte >0,0,<=intDsize) berechnen + b_msd = mspref(b_MSDptr,0); + #if HAVE_DD + {var uintDD b_msdd = // 2 führende Digits von b + (len_diff==0 + ? highlowDD(b_msd, mspref(b_MSDptr,1)) + : (uintDD)b_msd + ); + // a_msd_size+intDsize - b_msdd_size >= bitlendiff_limit -> dividieren: + b_msd = lowD(b_msdd >> a_msd_size); + if (b_msd < (uintD)bit(intDsize-bitlendiff_limit)) goto divide; + #if DOUBLE_SPEED + b_nsd = lowD(highlowDD(lowD(b_msdd), (b_len<=2-len_diff ? 0 : mspref(b_MSDptr,2-len_diff))) >> a_msd_size); + #endif + } + {var uintDD a_msdd = // 2 führende Digits von a + highlowDD(a_msd, mspref(a_MSDptr,1)); + a_msd = lowD(a_msdd >> a_msd_size); + #if DOUBLE_SPEED + a_nsd = lowD(highlowDD(lowD(a_msdd), (a_len<=2 ? 0 : mspref(a_MSDptr,2))) >> a_msd_size); + #endif + } + if (a_msd == b_msd) goto subtract; + #else + if (len_diff==0) + { // a_msd_size - b_msd_size >= bitlendiff_limit -> dividieren: + if ((a_msd_size > bitlendiff_limit) + && (b_msd < (uintD)bit(a_msd_size-bitlendiff_limit)) + ) + goto divide; + // Entscheidung für Linearkombination ist gefallen. + // a_msd und b_msd so erweitern, daß a_msd die führenden + // intDsize Bits von a enthält: + {var uintC shiftcount = intDsize-a_msd_size; // Shiftcount nach links (>=0, 0) + { a_msd = a_msd << shiftcount; + b_msd = b_msd << shiftcount; + a_msd |= mspref(a_MSDptr,1) >> a_msd_size; + b_msd |= mspref(b_MSDptr,1) >> a_msd_size; + } + if (a_msd == b_msd) goto subtract; + #if DOUBLE_SPEED + a_nsd = mspref(a_MSDptr,1); + b_nsd = mspref(b_MSDptr,1); + if (shiftcount>0) + { a_nsd = a_nsd << shiftcount; + b_nsd = b_nsd << shiftcount; + if (a_len>2) + { a_nsd |= mspref(a_MSDptr,2) >> a_msd_size; + b_nsd |= mspref(b_MSDptr,2) >> a_msd_size; + } } + #endif + }} + else + // len_diff=1 + { // a_msd_size+intDsize - b_msd_size >= bitlendiff_limit -> dividieren: + if ((a_msd_size >= bitlendiff_limit) + || (b_msd < (uintD)bit(a_msd_size+intDsize-bitlendiff_limit)) + ) + goto divide; + // Entscheidung für Linearkombination ist gefallen. + // a_msd und b_msd so erweitern, daß a_msd die führenden + // intDsize Bits von a enthält: + // 0 < a_msd_size < b_msd_size + bitlendiff_limit - intDsize <= bitlendiff_limit < intDsize. + a_msd = (a_msd << (intDsize-a_msd_size)) | (mspref(a_MSDptr,1) >> a_msd_size); + #if DOUBLE_SPEED + a_nsd = mspref(a_MSDptr,1) << (intDsize-a_msd_size); + b_nsd = b_msd << (intDsize-a_msd_size); + a_nsd |= mspref(a_MSDptr,2) >> a_msd_size; + b_nsd |= mspref(b_MSDptr,1) >> a_msd_size; + #endif + b_msd = b_msd >> a_msd_size; + } + #endif + #undef bitlendiff_limit + }} + // Nun ist a_msd = a' > b' = b_msd. + { // Euklid-Algorithmus auf den führenden Digits durchführen: + var partial_gcd_result likobi; + #if DOUBLE_SPEED + if (a_len >= cl_gcd_double_threshold) + { + #if HAVE_DD + partial_gcd(highlowDD(a_msd,a_nsd),highlowDD(b_msd,b_nsd),&likobi); // liefert x1,y1,x2,y2 + #else + partial_gcd(a_msd,a_nsd,b_msd,b_nsd,&likobi); // liefert x1,y1,x2,y2 + #endif + } + else + #endif + { partial_gcd(a_msd,b_msd,&likobi); } // liefert x1,y1,x2,y2, aber nur halb so gut + // Hier y1>0. + if (likobi.x2==0) + { // Ersetze (a,b) := (a-y1*b,b). + if (likobi.y1==1) goto subtract; // einfacherer Fall + // Dazu evtl. a um 1 Digit erweitern, so daß a_len=b_len+1: + if (a_len == b_len) { lsprefnext(a_MSDptr) = 0; a_len++; } + // und y1*b von a subtrahieren: + mspref(a_MSDptr,0) -= mulusub_loop_lsp(likobi.y1,b_LSDptr,a_LSDptr,b_len); + } + else + { // Ersetze (a,b) := (x1*a-y1*b,-x2*a+y2*b). + // Dazu evtl. b um 1 Digit erweitern, so daß a_len=b_len: + if (!(a_len==b_len)) { lsprefnext(b_MSDptr) = 0; b_len++; } + // c := x1*a-y1*b bilden: + mulu_loop_lsp(likobi.x1,a_LSDptr,c_LSDptr,a_len); + /* lspref(c_LSDptr,a_len) -= */ + mulusub_loop_lsp(likobi.y1,b_LSDptr,c_LSDptr,a_len); + // d := -x2*a+y2*b bilden: + mulu_loop_lsp(likobi.y2,b_LSDptr,d_LSDptr,a_len); + /* lspref(d_LSDptr,a_len) -= */ + mulusub_loop_lsp(likobi.x2,a_LSDptr,d_LSDptr,a_len); + // Wir wissen, daß 0 < c < b und 0 < d < a. Daher müßten + // lspref(c_LSDptr,a_len) und lspref(d_LSDptr,a_len) =0 sein. + // a := c und b := d kopieren: + copy_loop_lsp(c_LSDptr,a_LSDptr,a_len); + copy_loop_lsp(d_LSDptr,b_LSDptr,a_len); + // b normalisieren: + while (mspref(b_MSDptr,0)==0) { msshrink(b_MSDptr); b_len--; } + } } + if (cl_false) + { subtract: // Ersetze (a,b) := (a-b,b). + if (!( subfrom_loop_lsp(b_LSDptr,a_LSDptr,b_len) ==0)) + // Übertrag nach b_len Stellen, muß also a_len=b_len+1 sein. + { mspref(a_MSDptr,0) -= 1; } + } + // a normalisieren: + while (mspref(a_MSDptr,0)==0) { msshrink(a_MSDptr); a_len--; } + } + if (cl_false) + { divide: // Ersetze (a,b) := (b , a mod b). + {var uintD* old_a_LSDptr = a_LSDptr; + var DS q; + var DS r; + cl_UDS_divide(a_MSDptr,a_len,a_LSDptr,b_MSDptr,b_len,b_LSDptr, divroomptr, &q,&r); + a_MSDptr = b_MSDptr; a_len = b_len; a_LSDptr = b_LSDptr; // a := b + b_len = r.len; if (b_len==0) break; // b=0 -> fertig + b_LSDptr = old_a_LSDptr; // b übernimmt den vorherigen Platz von a + b_MSDptr = copy_loop_lsp(r.LSDptr,b_LSDptr,b_len); // b := r kopieren + goto a_greater_b; // Nun ist a>b>0 + }} + } } + return NUDS_to_I(a_MSDptr,a_len); // NUDS a als Ergebnis + #undef I_abs_to_NUDS + } + +#endif /* GCD_ALGO == 3 */ diff --git a/src/integer/gcd/cl_I_gcd_aux.cc b/src/integer/gcd/cl_I_gcd_aux.cc new file mode 100644 index 0000000..0062463 --- /dev/null +++ b/src/integer/gcd/cl_I_gcd_aux.cc @@ -0,0 +1,59 @@ +// partial_gcd(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I.h" + + +// Implementation. + +#include "cl_integer.h" +#include "cl_D.h" + +void partial_gcd (uintD z1, uintD z2, partial_gcd_result* erg) + { var uintD x1 = 1; + var uintD y1 = 0; + var uintD x2 = 0; + var uintD y2 = 1; + for (;;) + { + // Hier ist z1-y1>=z2+y2. + // Bestimme q := floor((z1-y1)/(z2+y2)) >= 1 : + { var uintD zaehler = z1-y1; + var uintD nenner = z2+y2; // z2+y2 <= z1-y1 < beta ! + if (floor(zaehler,8) >= nenner) // zaehler >= 8*nenner ? + // ja -> Dividieren lohnt sich wohl + { var uintD q = floorD(zaehler,nenner); + x1 += muluD_unchecked(q,x2); // x1 := x1+q*x2 + y1 += muluD_unchecked(q,y2); // y1 := y1+q*y2 + z1 -= muluD_unchecked(q,z2); // z1 := z1-q*z2 + } + else + // nein -> ein paarmal subtrahieren ist wohl schneller + do { x1 += x2; y1 += y2; z1 -= z2; } // (x1,y1,z1) := (x1+x2,y1+y2,z1-z2) + while (z1-y1 >= nenner); + } + if (z2-x2 <= z1+x1-1) break; + // Hier ist z2-x2>=z1+x1. + // Bestimme q := floor((z2-x2)/(z1+x1)) >= 1 : + { var uintD zaehler = z2-x2; + var uintD nenner = z1+x1; // z1+x1 <= z2-x2 < beta ! + if (floor(zaehler,8) >= nenner) // zaehler >= 8*nenner ? + // ja -> Dividieren lohnt sich wohl + { var uintD q = floorD(zaehler,nenner); + x2 += muluD_unchecked(q,x1); // x2 := x2+q*x1 + y2 += muluD_unchecked(q,y1); // y2 := y2+q*y1 + z2 -= muluD_unchecked(q,z1); // z2 := z2-q*z1 + } + else + // nein -> ein paarmal subtrahieren ist wohl schneller + do { x2 += x1; y2 += y1; z2 -= z1; } // (x2,y2,z2) := (x2+x1,y2+y1,z2-z1) + while (z2-x2 >= nenner); + } + if (z1-y1 <= z2+y2-1) break; + } + // Keine Subtraktion mehr möglich. + erg->x1 = x1; erg->y1 = y1; erg->x2 = x2; erg->y2 = y2; // Ergebnis + } diff --git a/src/integer/gcd/cl_I_gcd_aux2.cc b/src/integer/gcd/cl_I_gcd_aux2.cc new file mode 100644 index 0000000..adb6f61 --- /dev/null +++ b/src/integer/gcd/cl_I_gcd_aux2.cc @@ -0,0 +1,453 @@ +// partial_gcd(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I.h" + + +// Implementation. + +#include "cl_integer.h" +#include "cl_D.h" + +// Dasselbe wie partial_gcd(z1,z2,erg), nur daß z1 und z2 Doppelworte sind. +// Bevor im Ergebnis erg ein Überlauf eintritt, wird abgebrochen. + +#if HAVE_DD + +static inline uintDD muluDD_unchecked(uintD q, uintDD a) +{ + return muluD(q,lowD(a)) + highlowDD_0(muluD_unchecked(q,highD(a))); +} + +// Division: liefert min(floor(x / y), 2^intDsize-1). +// Vorausgesetzt wird, daß x >= 2 * y > 0. +static uintD floorDD (uintDD x, uintDD y) +{ + // vgl. Algorithmus für divu_3232_3232(). + var uintD q; + if (y < ((uintDD)1 << intDsize)) { + if (highD(x) >= y) + q = ~(uintD)0; // instead of overflow + else + divuD(x, (uintD)y, q =, ); + return q; + } + { + var uintC shift; + integerlengthD(highD(y), shift=); + // NB: 0 < shift < intDsize since 2^intDsize <= y < 2^(2*intDsize-1). + // Determine q := floor((x>>shift) / ((y>>shift)+1)). + var uintD y_shifted = y >> shift; + y_shifted += 1; + if (y_shifted == 0) + q = highD(x) >> shift; + else + divuD(x,y_shifted, q =, ); + } + // May need to increment q at most twice. + { + var uintDD p = muluDD_unchecked(q,y); + #ifdef DEBUG_GCD + if (x < p) + cl_abort(); + #endif + x -= p; + } + if (x >= y) { + q += 1; + x -= y; + if (x >= y) { + q += 1; + #ifdef DEBUG_GCD + x -= y; + if (x >= y) + cl_abort(); + #endif + } + } + return q; +} + +void partial_gcd (uintDD z1, uintDD z2, partial_gcd_result* erg) +{ + var uintD x1 = 1; + var uintD y1 = 0; + var uintD x2 = 0; + var uintD y2 = 1; + for (;;) { + // Hier ist z1-y1>=z2+y2. + // Bestimme q := floor((z1-y1)/(z2+y2)) >= 1 : + { + var uintDD zaehler = z1 - (uintDD)y1; + var uintDD nenner = z2 + (uintDD)y2; + // z2+y2 <= z1-y1 < beta^2 ! + if (x2 > (~x1) >> 3) // x1 + 8*x2 >= beta ? + goto do_subtract_1; + if (y2 > (~y1) >> 3) // y1 + 8*y2 >= beta ? + goto do_subtract_1; + // Ist floor(zaehler,8) >= nenner ? Wenn nein -> do_subtract_1. + if ((zaehler >> 3) < nenner) + goto do_subtract_1; + if (1) { + var uintD q = floorDD(zaehler,nenner); + repeat_1: + var uintDD qx = muluD(q,x2); + if (qx > (uintDD)(~x1)) { + // Choose a smaller value for q, to avoid overflow of x1. + q = floorD(~x1,x2); + goto repeat_1; + } + var uintDD qy = muluD(q,y2); + if (qy > (uintDD)(~y1)) { + // Choose a smaller value for q, to avoid overflow of y1. + q = floorD(~y1,y2); + goto repeat_1; + } + x1 += (uintD)qx; + y1 += (uintD)qy; + z1 -= muluDD_unchecked(q,z2); + } else { + do_subtract_1: + do { + // Checks to avoid overflow. + if (x2 > ~x1) goto done; + if (y2 > ~y1) goto done; + #ifdef DEBUG_GCD + if (z1 < z2) cl_abort(); + #endif + // Now really subtract. + x1 += x2; + y1 += y2; + z1 -= z2; + } while (z1 - (uintDD)y1 >= nenner); + } + } + if (z2 - (uintDD)x2 <= z1 + (uintDD)(x1-1)) goto done; + // Hier ist z2-x2>=z1+x1. + // Bestimme q := floor((z2-x2)/(z1+x1)) >= 1 : + { + var uintDD zaehler = z2 - (uintDD)x2; + var uintDD nenner = z1 + (uintDD)x1; + // z1+x1 <= z2-x2 < beta^2 ! + if (x1 > (~x2) >> 3) // x2 + 8*x1 >= beta ? + goto do_subtract_2; + if (y1 > (~y2) >> 3) // y2 + 8*y1 >= beta ? + goto do_subtract_2; + // Ist floor(zaehler,8) >= nenner ? Wenn nein -> do_subtract_2. + if ((zaehler >> 3) < nenner) + goto do_subtract_2; + if (1) { + var uintD q = floorDD(zaehler,nenner); + repeat_2: + var uintDD qx = muluD(q,x1); + if (qx > (uintDD)(~x2)) { + // Choose a smaller value for q, to avoid overflow of x2. + q = floorD(~x2,x1); + goto repeat_2; + } + var uintDD qy = muluD(q,y1); + if (qy > (uintDD)(~y2)) { + // Choose a smaller value for q, to avoid overflow of y2. + q = floorD(~y2,y1); + goto repeat_2; + } + x2 += (uintD)qx; + y2 += (uintD)qy; + z2 -= muluDD_unchecked(q,z1); + } else { + do_subtract_2: + do { + // Checks to avoid overflow. + if (x1 > ~x2) goto done; + if (y1 > ~y2) goto done; + #ifdef DEBUG_GCD + if (z2 < z1) cl_abort(); + #endif + // Now really subtract. + x2 += x1; + y2 += y1; + z2 -= z1; + } while (z2 - (uintDD)x2 >= nenner); + } + } + if (z1 - (uintDD)y1 <= z2 + (uintDD)(y2-1)) goto done; + } + done: + // Keine Subtraktion (ohne Überlauf) mehr möglich. + erg->x1 = x1; erg->y1 = y1; erg->x2 = x2; erg->y2 = y2; // Ergebnis +} + +#else + +// Division: liefert min(floor(xhi|xlo / yhi|ylo), 2^intDsize-1). +// Vorausgesetzt wird, daß xhi|xlo >= 2 * yhi|ylo > 0. +static uintD floorDD (uintD xhi, uintD xlo, uintD yhi, uintD ylo) +{ + // vgl. Algorithmus für divu_3232_3232(). + var uintD q; + if (yhi == 0) { + if (xhi >= ylo) + q = ~(uintD)0; // instead of overflow + else + divuD(xhi,xlo, ylo, q =, ); + return q; + } + { + var uintC shift; + integerlengthD(yhi, shift=); + // NB: 0 < shift < intDsize since 2^intDsize <= y < 2^(2*intDsize-1). + // Determine q := floor((x>>shift) / ((y>>shift)+1)). + var uintD y_shifted = (uintD)(yhi << (intDsize-shift)) | (ylo >> shift); + y_shifted += 1; + if (y_shifted == 0) + q = xhi >> shift; + else + divuD(xhi >> shift, (uintD)(xhi << (intDsize-shift)) | (xlo >> shift), + y_shifted, + q =, ); + } + // May need to increment q at most twice. + { + var uintD phi; + var uintD plo; + muluD(q,ylo, phi =, plo =); + muluD(q,yhi, , phi +=); + #ifdef DEBUG_GCD + if ((xhi < phi) || ((xhi == phi) && (xlo < plo))) + cl_abort(); + #endif + xhi = xhi - phi; + if (xlo < plo) + xhi -= 1; + xlo = xlo - plo; + } + if ((xhi > yhi) || ((xhi == yhi) && (xlo >= ylo))) { + q += 1; + xhi = xhi - yhi; + if (xlo < ylo) + xhi -= 1; + xlo = xlo - ylo; + if ((xhi > yhi) || ((xhi == yhi) && (xlo >= ylo))) { + q += 1; + #ifdef DEBUG_GCD + xhi = xhi - yhi; + if (xlo < ylo) + xhi -= 1; + xlo = xlo - ylo; + if ((xhi > yhi) || ((xhi == yhi) && (xlo >= ylo))) + cl_abort(); + #endif + } + } + return q; +} + +void partial_gcd (uintD z1hi, uintD z1lo, uintD z2hi, uintD z2lo, partial_gcd_result* erg) +{ + var uintD x1 = 1; + var uintD y1 = 0; + var uintD x2 = 0; + var uintD y2 = 1; + for (;;) { + // Hier ist z1-y1>=z2+y2. + // Bestimme q := floor((z1-y1)/(z2+y2)) >= 1 : + { + var uintD zaehlerhi = z1hi; + var uintD zaehlerlo = z1lo - y1; + if (zaehlerlo > z1lo) { zaehlerhi--; } + var uintD nennerhi = z2hi; + var uintD nennerlo = z2lo + y2; + if (nennerlo < z2lo) { nennerhi++; } + // z2+y2 <= z1-y1 < beta^2 ! + if (x2 > (~x1) >> 3) // x1 + 8*x2 >= beta ? + goto do_subtract_1; + if (y2 > (~y1) >> 3) // y1 + 8*y2 >= beta ? + goto do_subtract_1; + // Ist floor(zaehler,8) >= nenner ? Wenn nein -> do_subtract_1. + if ((zaehlerhi >> 3) < nennerhi) + goto do_subtract_1; + if ((zaehlerhi >> 3) == nennerhi) + if (((uintD)(zaehlerhi << (intDsize-3)) | (zaehlerlo >> 3)) < nennerlo) + goto do_subtract_1; + if (1) { + var uintD q = floorDD(zaehlerhi,zaehlerlo,nennerhi,nennerlo); + repeat_1: + var uintD qx; + var uintD qy; + { + var uintD qxhi; + muluD(q,x2, qxhi =, qx =); + if ((qxhi > 0) || (qx > ~x1)) { + // Choose a smaller value for q, to avoid overflow of x1. + q = floorD(~x1,x2); + goto repeat_1; + } + } + { + var uintD qyhi; + muluD(q,y2, qyhi =, qy =); + if ((qyhi > 0) || (qy > ~y1)) { + // Choose a smaller value for q, to avoid overflow of y1. + q = floorD(~y1,y2); + goto repeat_1; + } + } + x1 += qx; + y1 += qy; + { + var uintD qzhi; + var uintD qzlo; + muluD(q,z2lo, qzhi =, qzlo =); + muluD(q,z2hi, , qzhi +=); + z1hi -= qzhi; + if (z1lo < qzlo) + z1hi -= 1; + z1lo -= qzlo; + } + } else { + do_subtract_1: + for (;;) { + // Checks to avoid overflow. + if (x2 > ~x1) goto done; + if (y2 > ~y1) goto done; + #ifdef DEBUG_GCD + if (z1hi < z2hi) cl_abort(); + if (z1hi == z2hi) if (z1lo < z2lo) cl_abort(); + #endif + // Now really subtract. + x1 += x2; + y1 += y2; + z1hi -= z2hi; + if (z1lo < z2lo) + z1hi -= 1; + z1lo -= z2lo; + var uintD z1dec_hi = z1hi; + var uintD z1dec_lo = z1lo - y1; + if (z1lo < y1) + z1dec_hi -= 1; + if (z1dec_hi < nennerhi) + break; + if (z1dec_hi == nennerhi) + if (z1dec_lo < nennerlo) + break; + } + } + } + { + var uintD z1inc_hi = z1hi; + var uintD z1inc_lo = z1lo + x1-1; + if (z1inc_lo < z1lo) + z1inc_hi += 1; + var uintD z2dec_hi = z2hi; + var uintD z2dec_lo = z2lo - x2; + if (z2dec_lo > z2lo) + z2dec_hi -= 1; + if (z2dec_hi < z1inc_hi) goto done; + if (z2dec_hi == z1inc_hi) if (z2dec_lo <= z1inc_lo) goto done; + } + // Hier ist z2-x2>=z1+x1. + // Bestimme q := floor((z2-x2)/(z1+x1)) >= 1 : + { + var uintD zaehlerhi = z2hi; + var uintD zaehlerlo = z2lo - x2; + if (zaehlerlo > z2lo) { zaehlerhi--; } + var uintD nennerhi = z1hi; + var uintD nennerlo = z1lo + x1; + if (nennerlo < z1lo) { nennerhi++; } + // z1+x1 <= z2-x2 < beta^2 ! + if (x1 > (~x2) >> 3) // x2 + 8*x1 >= beta ? + goto do_subtract_2; + if (y1 > (~y2) >> 3) // y2 + 8*y1 >= beta ? + goto do_subtract_2; + // Ist floor(zaehler,8) >= nenner ? Wenn nein -> do_subtract_2. + if ((zaehlerhi >> 3) < nennerhi) + goto do_subtract_2; + if ((zaehlerhi >> 3) == nennerhi) + if (((uintD)(zaehlerhi << (intDsize-3)) | (zaehlerlo >> 3)) < nennerlo) + goto do_subtract_2; + if (1) { + var uintD q = floorDD(zaehlerhi,zaehlerlo,nennerhi,nennerlo); + repeat_2: + var uintD qx; + var uintD qy; + { + var uintD qxhi; + muluD(q,x1, qxhi =, qx =); + if ((qxhi > 0) || (qx > ~x2)) { + // Choose a smaller value for q, to avoid overflow of x2. + q = floorD(~x2,x1); + goto repeat_2; + } + } + { + var uintD qyhi; + muluD(q,y1, qyhi =, qy =); + if ((qyhi > 0) || (qy > ~y2)) { + // Choose a smaller value for q, to avoid overflow of y2. + q = floorD(~y2,y1); + goto repeat_2; + } + } + x2 += qx; + y2 += qy; + { + var uintD qzhi; + var uintD qzlo; + muluD(q,z1lo, qzhi =, qzlo =); + muluD(q,z1hi, , qzhi +=); + z2hi -= qzhi; + if (z2lo < qzlo) + z2hi -= 1; + z2lo -= qzlo; + } + } else { + do_subtract_2: + for (;;) { + // Checks to avoid overflow. + if (x1 > ~x2) goto done; + if (y1 > ~y2) goto done; + #ifdef DEBUG_GCD + if (z2hi < z1hi) cl_abort(); + if (z2hi == z1hi) if (z2lo < z1lo) cl_abort(); + #endif + // Now really subtract. + x2 += x1; + y2 += y1; + z2hi -= z1hi; + if (z2lo < z1lo) + z2hi -= 1; + z2lo -= z1lo; + var uintD z2dec_hi = z2hi; + var uintD z2dec_lo = z2lo - x2; + if (z2lo < x2) + z2dec_hi -= 1; + if (z2dec_hi < nennerhi) + break; + if (z2dec_hi == nennerhi) + if (z2dec_lo < nennerlo) + break; + } + } + } + { + var uintD z2inc_hi = z2hi; + var uintD z2inc_lo = z2lo + y2-1; + if (z2inc_lo < z2lo) + z2inc_hi += 1; + var uintD z1dec_hi = z1hi; + var uintD z1dec_lo = z1lo - y1; + if (z1dec_lo > z1lo) + z1dec_hi -= 1; + if (z1dec_hi < z2inc_hi) goto done; + if (z1dec_hi == z2inc_hi) if (z1dec_lo <= z2inc_lo) goto done; + } + } + done: + // Keine Subtraktion (ohne Überlauf) mehr möglich. + erg->x1 = x1; erg->y1 = y1; erg->x2 = x2; erg->y2 = y2; // Ergebnis +} + +#endif diff --git a/src/integer/gcd/cl_I_lcm.cc b/src/integer/gcd/cl_I_lcm.cc new file mode 100644 index 0000000..e7837ef --- /dev/null +++ b/src/integer/gcd/cl_I_lcm.cc @@ -0,0 +1,32 @@ +// lcm(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" + +const cl_I lcm (const cl_I& a, const cl_I& b) +{ +// Methode: +// a=0 oder b=0 -> Ergebnis 0. +// a:=(abs a), b:=(abs b). +// g:=ggT(a,b)>0. +// Falls g=1, Ergebnis a*b, sonst Ergebnis (a/g)*b. + if (eq(a,0)) { return 0; } + if (eq(b,0)) { return 0; } + // Beträge nehmen: + {var cl_I abs_a = abs(a); + var cl_I abs_b = abs(b); + var cl_I& a = abs_a; + var cl_I& b = abs_b; + var cl_I g = gcd(a,b); + if (!eq(g,1)) { a = exquopos(a,g); } // a durch g (beide >0) dividieren + return a*b; + } +} diff --git a/src/integer/gcd/cl_I_xgcd.cc b/src/integer/gcd/cl_I_xgcd.cc new file mode 100644 index 0000000..8286ec3 --- /dev/null +++ b/src/integer/gcd/cl_I_xgcd.cc @@ -0,0 +1,530 @@ +// xgcd(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" +#include "cl_D.h" +#include "cl_xmacros.h" + +#define GCD_ALGO 3 // 1: binär, 2: Schulmethode, 3: Lehmer + + +#if (GCD_ALGO == 2) + +// Schulmethode: +// (gcd A B) :== +// [a:=(abs A), b:=(abs B), while b>0 do (a,b) := (b,(mod a b)), -> a] +// verbessert: +// A=1 -> return g=1, (u,v)=(1,0) +// B=1 -> return g=1, (u,v)=(0,1) +// a:=(abs A), ua:=(signum A), va:=0 +// b:=(abs B), ub:=0, vb:=(signum B) +// A=0 -> return g=b, (u,v) = (ub,vb) +// B=0 -> return g=a, (u,v) = (ua,va) +// {Stets ua*A+va*B=a, ub*A+vb*B=b, ua*vb-ub*va = +/- 1.} +// Falls a=b: return a,ua,va; +// falls ab>0} +// Falls b=1, return 1,ub,vb. {spart eine Division durch 1} +// Sonst dividieren (divide a b) -> q,r. +// Falls r=0, return b,ub,vb. +// a:=b, b := Rest r = a-q*b, (ua,va,ub,vb) := (ub,vb,ua-q*ub,va-q*vb). +// goto (*). + + const cl_I xgcd (const cl_I& a, const cl_I& b, cl_I* u, cl_I* v) + { if (eq(a,1)) // a=1 -> g=1, (u,v)=(1,0) + { *u = 1; *v = 0; return a; } + if (eq(b,1)) // b=1 -> g=1, (u,v)=(0,1) + { *u = 0; *v = 1; return b; } + // Vorzeichen nehmen: + var cl_I ua = (minusp(a) ? cl_I(-1) : cl_I(1)); // ua := +/- 1 + var cl_I va = 0; + var cl_I ub = 0; + var cl_I vb = (minusp(b) ? cl_I(-1) : cl_I(1)); // vb := +/- 1 + // Beträge nehmen: + {var cl_I abs_a = abs(a); + var cl_I abs_b = abs(b); + var cl_I& a = abs_a; + var cl_I& b = abs_b; + if (eq(b,0)) // b=0 -> g=a, (u,v) = (ua,va) + { *u = ua; *v = va; return a; } + if (eq(a,0)) // a=0 -> g=b, (u,v) = (ub,vb) + { *u = ub; *v = vb; return b; } + { var cl_signean vergleich = cl_compare(a,b); + if (vergleich == 0) // a=b -> fertig + { *u = ua; *v = va; return a; } + if (vergleich < 0) // a a,b vertauschen + { swap(cl_I,a,b); swap(cl_I,ua,ub); swap(cl_I,va,vb); } + } + loop // Hier a>b>0 + { if (eq(b,1)) // b=1 -> g=b, (u,v) = (ub,vb) + { *u = ub; *v = vb; return b; } + var cl_I_div_t div = cl_divide(a,b); // Division a / b + var cl_I& q = div.quotient; + var cl_I& r = div.remainder; + if (eq(r,0)) // r=0 -> fertig + { *u = ub; *v = vb; return b; } + { var cl_I x = ua-q*ub; ua = ub; ub = x; } + { var cl_I x = va-q*vb; va = vb; vb = x; } + a = b; b = r; + } + }} + +#endif /* GCD_ALGO == 2 */ + + +#if (GCD_ALGO == 3) +// (xgcd A B) :== +// wie oben bei (gcd A B). +// Zusätzlich werden Variablen sA,sB,sk,uAa,uBa,uAb,uBb geführt, +// wobei sA,sB,sk Vorzeichen (+/- 1) und uAa,uBa,uAb,uBb Integers >=0 sind mit +// uAa * sA*A - uBa * sB*B = a, +// - uAb * sA*A + uBb * sB*B = b, +// ferner uAa * uBb - uAb * uBa = sk und daher (Cramersche Regel) +// uBb * a + uBa * b = sk*sA*A, uAb * a + uAa * b = sk*sB*B. +// Zu Beginn (a,b) := (|A|,|B|), (sA,sB) := ((signum A), (signumB)), +// (uAa,uBa,uAb,uBb) := (1,0,0,1). +// Beim Ersetzen (a,b) := (a-b,b) +// ersetzt man (uAa,uBa,uAb,uBb) := (uAa+uAb,uBa+uBb,uAb,uBb). +// Beim Ersetzen (a,b) := (a-y1*b,b) +// ersetzt man (uAa,uBa,uAb,uBb) := (uAa+y1*uAb,uBa+y1*uBb,uAb,uBb). +// Beim Ersetzen (a,b) := (x1*a-y1*b,-x2*a+y2*b) mit x1*y2-x2*y1=1 +// ersetzt man (uAa,uBa,uAb,uBb) := +// (x1*uAa+y1*uAb,x1*uBa+y1*uBb,x2*uAa+y2*uAb,x2*uBa+y2*uBb). +// Beim Ersetzen (a,b) := (b,a) +// ersetzt man (uAa,uBa,uAb,uBb) := (uAb,uBb,uAa,uBa), +// sk := -sk, (sA,sB) := (-sA,-sB). +// Beim Ersetzen (a,b) := (b,a-q*b) +// ersetzt man (uAa,uBa,uAb,uBb) := (uAb,uBb,uAa+q*uAb,uBa+q*uBb), +// sk := -sk, (sA,sB) := (-sA,-sB). +// Zum Schluß ist a der ggT und a = uAa*sA * A + -uBa*sB * B +// die gewünschte Linearkombination. +// Da stets gilt sk*sA*A = |A|, sk*sB*B = |B|, a>=1, b>=1, +// folgt 0 <= uAa <= |B|, 0 <= uAb <= |B|, 0 <= uBa <= |A|, 0 <= uBb <= |A|. +// Ferner wird sk nie benutzt, braucht also nicht mitgeführt zu werden. + + // Define this to 1 in order to use double-word sized a' and b'. + // This gives better x1,y1,x2,y2, because normally the values x1,y1,x2,y2 + // have only about intDsize/2 bits and so half of the multiplication work + // is lost. Actually, this flag multiplies the gcd speed by 1.5, not 2.0. + #define DOUBLE_SPEED 1 + + // Bildet u := u + v, wobei für u genügend Platz sei: + // (Benutzt v.MSDptr nicht.) + static void NUDS_likobi0_NUDS (DS* u, DS* v) + { var uintC u_len = u->len; + var uintC v_len = v->len; + if (u_len >= v_len) + { if (!( addto_loop_lsp(v->LSDptr,u->LSDptr,v_len) ==0)) + { if (!( inc_loop_lsp(u->LSDptr lspop v_len,u_len-v_len) ==0)) + { lsprefnext(u->MSDptr) = 1; u->len++; } + } } + else // u_len <= v_len + { u->MSDptr = copy_loop_lsp(v->LSDptr lspop u_len,u->LSDptr lspop u_len,v_len-u_len); + u->len = v_len; + if (!( addto_loop_lsp(v->LSDptr,u->LSDptr,u_len) ==0)) + { if (!( inc_loop_lsp(u->LSDptr lspop u_len,v_len-u_len) ==0)) + { lsprefnext(u->MSDptr) = 1; u->len++; } + } } + } + + // Bildet u := u + q*v, wobei für u genügend Platz sei: + // (Dabei sei nachher u>0.) + static void NUDS_likobi1_NUDS (DS* u, DS* v, uintD q) + { var uintC v_len = v->len; + if (v_len>0) // nur nötig, falls v /=0 + { var uintC u_len = u->len; + var uintD carry; + if (u_len <= v_len) // evtl. u vergrößern + { u->MSDptr = clear_loop_lsp(u->MSDptr,v_len-u_len+1); + u->len = u_len = v_len+1; + } // Nun ist u_len > v_len. + carry = muluadd_loop_lsp(q,v->LSDptr,u->LSDptr,v_len); + if (!(carry==0)) + { var uintD* ptr = u->LSDptr lspop v_len; + if ((lspref(ptr,0) += carry) < carry) + { if (!( inc_loop_lsp(ptr lspop 1,u_len-v_len-1) ==0)) + { lsprefnext(u->MSDptr) = 1; u->len++; } + } } + while (mspref(u->MSDptr,0)==0) { msshrink(u->MSDptr); u->len--; } // normalisieren + } } + + // Bildet (u,v) := (x1*u+y1*v,x2*u+y2*v), wobei für u,v genügend Platz sei: + // (Dabei sei u>0 oder v>0, nachher u>0 und v>0.) + static void NUDS_likobi2_NUDS (DS* u, DS* v, partial_gcd_result* q, uintD* c_LSDptr, uintD* d_LSDptr) + { var uintC u_len = u->len; + var uintC v_len = v->len; + var uintC c_len; + var uintC d_len; + if (u_len >= v_len) + { mulu_loop_lsp(q->x1,u->LSDptr,c_LSDptr,u_len); c_len = u_len+1; + mulu_loop_lsp(q->x2,u->LSDptr,d_LSDptr,u_len); d_len = u_len+1; + if (!(v_len==0)) + {{var uintD carry = + muluadd_loop_lsp(q->y1,v->LSDptr,c_LSDptr,v_len); + if (!(carry==0)) + { var uintD* ptr = c_LSDptr lspop v_len; + if ((lspref(ptr,0) += carry) < carry) + { if (!( inc_loop_lsp(ptr lspop 1,u_len-v_len) ==0)) + { lspref(c_LSDptr,c_len) = 1; c_len++; } + } } } + {var uintD carry = + muluadd_loop_lsp(q->y2,v->LSDptr,d_LSDptr,v_len); + if (!(carry==0)) + { var uintD* ptr = d_LSDptr lspop v_len; + if ((lspref(ptr,0) += carry) < carry) + { if (!(inc_loop_lsp(ptr lspop 1,u_len-v_len) ==0)) + { lspref(d_LSDptr,d_len) = 1; d_len++; } + }} } } + } + else + { mulu_loop_lsp(q->y1,v->LSDptr,c_LSDptr,v_len); c_len = v_len+1; + mulu_loop_lsp(q->y2,v->LSDptr,d_LSDptr,v_len); d_len = v_len+1; + if (!(u_len==0)) + {{var uintD carry = + muluadd_loop_lsp(q->x1,u->LSDptr,c_LSDptr,u_len); + if (!(carry==0)) + { var uintD* ptr = c_LSDptr lspop u_len; + if ((lspref(ptr,0) += carry) < carry) + { if (!( inc_loop_lsp(ptr lspop 1,v_len-u_len) ==0)) + { lspref(c_LSDptr,c_len) = 1; c_len++; } + } } } + {var uintD carry = + muluadd_loop_lsp(q->x2,u->LSDptr,d_LSDptr,u_len); + if (!(carry==0)) + { var uintD* ptr = d_LSDptr lspop u_len; + if ((lspref(ptr,0) += carry) < carry) + { if (!( inc_loop_lsp(ptr lspop 1,v_len-u_len) ==0)) + { lspref(d_LSDptr,d_len) = 1; d_len++; } + }} } } + } + u->MSDptr = copy_loop_lsp(c_LSDptr,u->LSDptr,c_len); + while (mspref(u->MSDptr,0)==0) { msshrink(u->MSDptr); c_len--; } + u->len = c_len; + v->MSDptr = copy_loop_lsp(d_LSDptr,v->LSDptr,d_len); + while (mspref(v->MSDptr,0)==0) { msshrink(v->MSDptr); d_len--; } + v->len = d_len; + } + + // Los geht's: + const cl_I xgcd (const cl_I& a, const cl_I& b, cl_I* u, cl_I* v) + { if (eq(a,1)) // a=1 -> g=1, (u,v)=(1,0) + { *u = 1; *v = 0; return a; } + if (eq(b,1)) // b=1 -> g=1, (u,v)=(0,1) + { *u = 0; *v = 1; return b; } + var sintL sA = (minusp(a) ? ~0 : 0); // Vorzeichen von A + var sintL sB = (minusp(b) ? ~0 : 0); // Vorzeichen von B + CL_ALLOCA_STACK; + var uintD* a_MSDptr; + var uintC a_len; + var uintD* a_LSDptr; + var uintD* b_MSDptr; + var uintC b_len; + var uintD* b_LSDptr; + // Macro: erzeugt die NUDS zu (abs x), erniedrigt num_stack + #define I_abs_to_NUDS(x,zero_statement) \ + I_to_NDS_1(x, x##_MSDptr = , x##_len = , x##_LSDptr = ); /* (nichtleere) NDS holen */\ + if (x##_len == 0) { zero_statement } /* falls =0, fertig */\ + if ((sintD)mspref(x##_MSDptr,0) < 0) /* falls <0, negieren: */\ + { neg_loop_lsp(x##_LSDptr,x##_len); } \ + if (mspref(x##_MSDptr,0) == 0) /* normalisieren (max. 1 Nulldigit entfernen) */\ + { msshrink(x##_MSDptr); x##_len--; } + I_abs_to_NUDS(a, // (abs A) als NUDS erzeugen + // A=0 -> g=|B|, (u,v) = (0,sB) + { *u = 0; *v = (sB==0 ? cl_I(1) : cl_I(-1)); + return abs(b); + }); + I_abs_to_NUDS(b, // (abs B) als NUDS erzeugen + // B=0 -> g=|A|, (u,v) = (sA,0) + { *u = (sA==0 ? cl_I(1) : cl_I(-1)); *v = 0; + return abs(a); + }); + // Jetzt ist a = a_MSDptr/a_len/a_LSDptr, b = b_MSDptr/b_len/b_LSDptr, + // beides NUDS, und a_len>0, b_len>0. + {// Beifaktoren: + var DS uAa; + var DS uBa; + var DS uAb; + var DS uBb; + // Rechenregister: + var uintD* divroomptr; // Platz für Divisionsergebnis + var uintD* c_LSDptr; + var uintD* d_LSDptr; + // Platz für uAa,uBa,uAb,uBb besorgen: + {var uintC u_len = b_len+1; + num_stack_alloc(u_len,,uAa.LSDptr=); uAa.MSDptr = uAa.LSDptr; + num_stack_alloc(u_len,,uAb.LSDptr=); uAb.MSDptr = uAb.LSDptr; + } + {var uintC u_len = a_len+1; + num_stack_alloc(u_len,,uBa.LSDptr=); uBa.MSDptr = uBa.LSDptr; + num_stack_alloc(u_len,,uBb.LSDptr=); uBb.MSDptr = uBb.LSDptr; + } + lsprefnext(uAa.MSDptr) = 1; uAa.len = 1; // uAa := 1 + uBa.len = 0; // uBa := 0 + uAb.len = 0; // uAb := 0 + lsprefnext(uBb.MSDptr) = 1; uBb.len = 1; // uBb := 1 + // Jetzt ist uAa = uAa.MSDptr/uAa.len/uAa.LSDptr, + // uBa = uBa.MSDptr/uBa.len/uBa.LSDptr, + // uAb = uAb.MSDptr/uAb.len/uAb.LSDptr, + // uBb = uBb.MSDptr/uBb.len/uBb.LSDptr, + // alles NUDS. + // Platz für zwei Rechenregister besorgen, mit je max(a_len,b_len)+1 Digits: + {var uintL c_len = (uintL)(a_len>=b_len ? a_len : b_len) + 1; + num_stack_alloc(c_len,,c_LSDptr=); + num_stack_alloc(c_len,divroomptr=,d_LSDptr=); + // Jetzt ist ../c_len/c_LSDptr, ../c_len/d_LSDptr frei. + } + loop + { // Hier a,b>0, beides NUDS. + // Vergleiche a und b: + if (a_len > b_len) goto a_greater_b; // a>b ? + if (a_len == b_len) + { var cl_signean vergleich = compare_loop_msp(a_MSDptr,b_MSDptr,a_len); + if (vergleich > 0) goto a_greater_b; // a>b ? + if (vergleich == 0) break; // a=b ? + } + // a a,b vertauschen: + swap(uintD*, a_MSDptr,b_MSDptr); + swap(uintC, a_len,b_len); + swap(uintD*, a_LSDptr,b_LSDptr); + a_greater_b_swap: + swap(DS, uAa,uAb); // und uAa und uAb vertauschen + swap(DS, uBa,uBb); // und uBa und uBb vertauschen + sA = ~sA; sB = ~sB; // und sA und sB umdrehen + a_greater_b: + // Hier a>b>0, beides NUDS. + // Entscheidung, ob Division oder Linearkombination: + { var uintD a_msd; // führende intDsize Bits von a + var uintD b_msd; // entsprechende Bits von b + #if DOUBLE_SPEED + var uintD a_nsd; // nächste intDsize Bits von a + var uintD b_nsd; // entsprechende Bits von b + #endif + { var uintC len_diff = a_len-b_len; // Längendifferenz + if (len_diff > 1) goto divide; // >=2 -> Bitlängendifferenz>intDsize -> dividieren + #define bitlendiff_limit (intDsize/2) // sollte >0,0,<=intDsize) berechnen + b_msd = mspref(b_MSDptr,0); + #if HAVE_DD + {var uintDD b_msdd = // 2 führende Digits von b + (len_diff==0 + ? highlowDD(b_msd, (b_len==1 ? 0 : mspref(b_MSDptr,1))) + : (uintDD)b_msd + ); + // a_msd_size+intDsize - b_msdd_size >= bitlendiff_limit -> dividieren: + b_msd = lowD(b_msdd >> a_msd_size); + if (b_msd < (uintD)bit(intDsize-bitlendiff_limit)) goto divide; + #if DOUBLE_SPEED + b_nsd = lowD(highlowDD(lowD(b_msdd), (b_len<=2-len_diff ? 0 : mspref(b_MSDptr,2-len_diff))) >> a_msd_size); + #endif + } + {var uintDD a_msdd = // 2 führende Digits von a + highlowDD(a_msd, (a_len==1 ? 0 : mspref(a_MSDptr,1))); + a_msd = lowD(a_msdd >> a_msd_size); + #if DOUBLE_SPEED + a_nsd = lowD(highlowDD(lowD(a_msdd), (a_len<=2 ? 0 : mspref(a_MSDptr,2))) >> a_msd_size); + #endif + } + if (a_msd == b_msd) goto subtract; + #else + if (len_diff==0) + { // a_msd_size - b_msd_size >= bitlendiff_limit -> dividieren: + if ((a_msd_size > bitlendiff_limit) + && (b_msd < (uintD)bit(a_msd_size-bitlendiff_limit)) + ) + goto divide; + // Entscheidung für Linearkombination ist gefallen. + // a_msd und b_msd so erweitern, daß a_msd die führenden + // intDsize Bits von a enthält: + {var uintC shiftcount = intDsize-a_msd_size; // Shiftcount nach links (>=0, 0) + { a_msd = a_msd << shiftcount; + b_msd = b_msd << shiftcount; + if (a_len>1) + { a_msd |= mspref(a_MSDptr,1) >> a_msd_size; + b_msd |= mspref(b_MSDptr,1) >> a_msd_size; + } } + if (a_msd == b_msd) goto subtract; + #if DOUBLE_SPEED + if (a_len>1) + { a_nsd = mspref(a_MSDptr,1); + b_nsd = mspref(b_MSDptr,1); + if (shiftcount>0) + { a_nsd = a_nsd << shiftcount; + b_nsd = b_nsd << shiftcount; + if (a_len>2) + { a_nsd |= mspref(a_MSDptr,2) >> a_msd_size; + b_nsd |= mspref(b_MSDptr,2) >> a_msd_size; + } } } + else + { a_nsd = 0; b_nsd = 0; } + #endif + }} + else + // len_diff=1 + { // a_msd_size+intDsize - b_msd_size >= bitlendiff_limit -> dividieren: + if ((a_msd_size >= bitlendiff_limit) + || (b_msd < (uintD)bit(a_msd_size+intDsize-bitlendiff_limit)) + ) + goto divide; + // Entscheidung für Linearkombination ist gefallen. + // a_msd und b_msd so erweitern, daß a_msd die führenden + // intDsize Bits von a enthält: + // 0 < a_msd_size < b_msd_size + bitlendiff_limit - intDsize <= bitlendiff_limit < intDsize. + a_msd = (a_msd << (intDsize-a_msd_size)) | (mspref(a_MSDptr,1) >> a_msd_size); + #if DOUBLE_SPEED + a_nsd = mspref(a_MSDptr,1) << (intDsize-a_msd_size); + b_nsd = b_msd << (intDsize-a_msd_size); + if (a_len>2) + { a_nsd |= mspref(a_MSDptr,2) >> a_msd_size; + b_nsd |= mspref(b_MSDptr,1) >> a_msd_size; + } + #endif + b_msd = b_msd >> a_msd_size; + } + #endif + #undef bitlendiff_limit + }} + // Nun ist a_msd = a' > b' = b_msd. + { // Euklid-Algorithmus auf den führenden Digits durchführen: + var partial_gcd_result likobi; + #if DOUBLE_SPEED + #if HAVE_DD + partial_gcd(highlowDD(a_msd,a_nsd),highlowDD(b_msd,b_nsd),&likobi); // liefert x1,y1,x2,y2 + #else + partial_gcd(a_msd,a_nsd,b_msd,b_nsd,&likobi); // liefert x1,y1,x2,y2 + #endif + #else + partial_gcd(a_msd,b_msd,&likobi); // liefert x1,y1,x2,y2, aber nur halb so gut + #endif + // Hier y1>0. + if (likobi.x2==0) + { // Ersetze (a,b) := (a-y1*b,b). + if (likobi.y1==1) goto subtract; // einfacherer Fall + // Dazu evtl. a um 1 Digit erweitern, so daß a_len=b_len+1: + if (a_len == b_len) { lsprefnext(a_MSDptr) = 0; a_len++; } + // und y1*b von a subtrahieren: + mspref(a_MSDptr,0) -= mulusub_loop_lsp(likobi.y1,b_LSDptr,a_LSDptr,b_len); + NUDS_likobi1_NUDS(&uAa,&uAb,likobi.y1); // uAa := uAa + y1 * uAb + NUDS_likobi1_NUDS(&uBa,&uBb,likobi.y1); // uBa := uBa + y1 * uBb + } + else + { // Ersetze (uAa,uAb) := (x1*uAa+y1*uAb,x2*uAa+y2*uAb) : + NUDS_likobi2_NUDS(&uAa,&uAb,&likobi,c_LSDptr,d_LSDptr); + // Ersetze (uBa,uBb) := (x1*uBa+y1*uBb,x2*uBa+y2*uBb) : + NUDS_likobi2_NUDS(&uBa,&uBb,&likobi,c_LSDptr,d_LSDptr); + // Ersetze (a,b) := (x1*a-y1*b,-x2*a+y2*b). + // Dazu evtl. b um 1 Digit erweitern, so daß a_len=b_len: + if (!(a_len==b_len)) { lsprefnext(b_MSDptr) = 0; b_len++; } + // c := x1*a-y1*b bilden: + mulu_loop_lsp(likobi.x1,a_LSDptr,c_LSDptr,a_len); + /* lspref(c_LSDptr,a_len) -= */ + mulusub_loop_lsp(likobi.y1,b_LSDptr,c_LSDptr,a_len); + // d := -x2*a+y2*b bilden: + mulu_loop_lsp(likobi.y2,b_LSDptr,d_LSDptr,a_len); + /* lspref(d_LSDptr,a_len) -= */ + mulusub_loop_lsp(likobi.x2,a_LSDptr,d_LSDptr,a_len); + // Wir wissen, daß 0 < c < b und 0 < d < a. Daher müßten + // lspref(c_LSDptr,a_len) und lspref(d_LSDptr,a_len) =0 sein. + // a := c und b := d kopieren: + copy_loop_lsp(c_LSDptr,a_LSDptr,a_len); + copy_loop_lsp(d_LSDptr,b_LSDptr,a_len); + // b normalisieren: + while (mspref(b_MSDptr,0)==0) { msshrink(b_MSDptr); b_len--; } + } } + if (cl_false) + { subtract: // Ersetze (a,b) := (a-b,b). + NUDS_likobi0_NUDS(&uAa,&uAb); // uAa := uAa + uAb + NUDS_likobi0_NUDS(&uBa,&uBb); // uBa := uBa + uBb + if (!( subfrom_loop_lsp(b_LSDptr,a_LSDptr,b_len) ==0)) + // Übertrag nach b_len Stellen, muß also a_len=b_len+1 sein. + { mspref(a_MSDptr,0) -= 1; } + } + // a normalisieren: + while (mspref(a_MSDptr,0)==0) { msshrink(a_MSDptr); a_len--; } + } + if (cl_false) + { divide: // Ersetze (a,b) := (b , a mod b). + {var uintD* old_a_LSDptr = a_LSDptr; + var DS q; + var DS r; + cl_UDS_divide(a_MSDptr,a_len,a_LSDptr,b_MSDptr,b_len,b_LSDptr, divroomptr, &q,&r); + a_MSDptr = b_MSDptr; a_len = b_len; a_LSDptr = b_LSDptr; // a := b + b_len = r.len; if (b_len==0) goto return_a_coeffsb; // b=0 -> fertig + b_LSDptr = old_a_LSDptr; // b übernimmt den vorherigen Platz von a + b_MSDptr = copy_loop_lsp(r.LSDptr,b_LSDptr,b_len); // b := r kopieren + // (uAa,uAb) := (uAb,uAa+q*uAb) : + if (!(uAb.len==0)) + { cl_UDS_mul(q.LSDptr,q.len,uAb.LSDptr,uAb.len,c_LSDptr); // q * uAb + var DS c; + c.LSDptr = c_LSDptr; c.len = q.len + uAb.len; + if (lspref(c_LSDptr,c.len-1)==0) { c.len--; } // normalisieren + NUDS_likobi0_NUDS(&uAa,&c); // zu uAa addieren + } // noch uAa,uAb vertauschen (später) + // (uBa,uBb) := (uBb,uBa+q*uBb) : + if (!(uBb.len==0)) + { cl_UDS_mul(q.LSDptr,q.len,uBb.LSDptr,uBb.len,c_LSDptr); // q * uBb + var DS c; + c.LSDptr = c_LSDptr; c.len = q.len + uBb.len; + if (lspref(c_LSDptr,c.len-1)==0) { c.len--; } // normalisieren + NUDS_likobi0_NUDS(&uBa,&c); // zu uBa addieren + } // noch uBa,uBb vertauschen (später) + goto a_greater_b_swap; // Nun ist a>b>0 + }} + } + // Nun ist a = b. Wähle diejenige der beiden Linearkombinationen + // a = uAa*sA * A + -uBa*sB * B + // b = -uAb*sA * A + uBb*sB * B + // die die betragsmäßig kleinsten Koeffizienten hat. + // Teste auf uBa < uBb. (Das kann auftreten, z.B. bei + // A=560014183, B=312839871 wird a=b=1, uAa < uAb, uBa < uBb.) + // Falls uBa = uBb, teste auf uAa < uAb. (Das kann auftreten, z.B. bei + // A=2, B=3 wird a=b=1, uAa < uAb, uBa = uBb.) + if (uBb.len > uBa.len) goto return_a_coeffsa; + if (uBb.len < uBa.len) goto return_a_coeffsb; + // (uBb.len == uBa.len) + { var cl_signean vergleich = compare_loop_msp(uBb.MSDptr,uBa.MSDptr,uBb.len); + if (vergleich > 0) goto return_a_coeffsa; + if (vergleich < 0) goto return_a_coeffsb; + } + if (uAb.len > uAa.len) goto return_a_coeffsa; + if (uAb.len < uAa.len) goto return_a_coeffsb; + // (uAb.len == uAa.len) + if (compare_loop_msp(uAb.MSDptr,uAa.MSDptr,uAb.len) > 0) + return_a_coeffsa: + { // uAa mit Vorfaktor sA versehen: + lsprefnext(uAa.MSDptr) = 0; uAa.len++; + if (!(sA==0)) { neg_loop_lsp(uAa.LSDptr,uAa.len); } + // uBa mit Vorfaktor -sB versehen: + lsprefnext(uBa.MSDptr) = 0; uBa.len++; + if (sB==0) { neg_loop_lsp(uBa.LSDptr,uBa.len); } + *u = DS_to_I(uAa.MSDptr,uAa.len); // DS uAa als Vorfaktor von A + *v = DS_to_I(uBa.MSDptr,uBa.len); // DS uBa als Vorfaktor von B + } + else + return_a_coeffsb: + { // uAb mit Vorfaktor -sA versehen: + lsprefnext(uAb.MSDptr) = 0; uAb.len++; + if (sA==0) { neg_loop_lsp(uAb.LSDptr,uAb.len); } + // uBb mit Vorfaktor sB versehen: + lsprefnext(uBb.MSDptr) = 0; uBb.len++; + if (!(sB==0)) { neg_loop_lsp(uBb.LSDptr,uBb.len); } + *u = DS_to_I(uAb.MSDptr,uAb.len); // DS uAb als Vorfaktor von A + *v = DS_to_I(uBb.MSDptr,uBb.len); // DS uBb als Vorfaktor von B + } + } + return NUDS_to_I(a_MSDptr,a_len); // NUDS a als ggT + #undef I_abs_to_NUDS + } + +#endif /* GCD_ALGO == 3 */ diff --git a/src/integer/gcd/cl_low_gcd.cc b/src/integer/gcd/cl_low_gcd.cc new file mode 100644 index 0000000..b68729d --- /dev/null +++ b/src/integer/gcd/cl_low_gcd.cc @@ -0,0 +1,91 @@ +// gcd(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +// Liefert den ggT zweier Integers. +// gcd(a,b) +// > a,b: zwei Integers +// < ergebnis: (gcd a b), ein Integer >=0 + uint32 gcd (uint32 a, uint32 b) +// binäre Methode: +// (gcd a b) :== +// (prog ((j 0)) +// 1 {a,b >0} +// (when (oddp a) (if (oddp b) (go 2) (go 4))) +// (when (oddp b) (go 3)) +// (incf j) (setq a (/ a 2)) (setq b (/ b 2)) +// (go 1) +// 2 {a,b >0, beide ungerade} +// (cond ((> a b) (setq a (- a b)) (go 3)) +// ((= a b) (go 5)) +// ((< a b) (setq b (- b a)) (go 4)) +// ) +// 3 {a,b >0, a gerade, b ungerade} +// (repeat (setq a (/ a 2)) (until (oddp a))) +// (go 2) +// 4 {a,b >0, a ungerade, b gerade} +// (repeat (setq b (/ b 2)) (until (oddp b))) +// (go 2) +// 5 {a=b>0} +// (return (ash a j)) +// ) +// Statt j zu erhöhen und immer Bit 0 von a und b abfragen, +// fragen wir stattdessen immer Bit j von a und b ab; Bits j-1..0 sind =0. +{ + #ifdef DUMMER_GGT // so macht's ein Mathematiker: + if (a==0) { return b; } + if (b==0) { return a; } + var uint32 bit_j = bit(0); + loop + { // a,b >0 + if (!((a & bit_j) ==0)) + { if (!((b & bit_j) ==0)) goto odd_odd; else goto odd_even; } + if (!((b & bit_j) ==0)) goto even_odd; + // a,b >0 gerade + bit_j = bit_j<<1; + } + #else // Trick von B. Degel: + var uint32 bit_j = (a | b); // endet mit einer 1 und j Nullen + bit_j = bit_j ^ (bit_j - 1); // Maske = bit(j) | bit(j-1) | ... | bit(0) + if (!((a & bit_j) ==0)) + { if (!((b & bit_j) ==0)) + goto odd_odd; + else + if (b==0) + return a; + else + goto odd_even; + } + if (!((b & bit_j) ==0)) + { if (a==0) + return b; + else + goto even_odd; + } + return 0; // a=b=0 -> Ergebnis 0 + #endif + loop + { odd_odd: // a,b >0, beide ungerade + // Vergleiche a und b: + if (a == b) break; // a=b>0 -> fertig + if (a > b) // a>b ? + { a = a-b; + even_odd: // a,b >0, a gerade, b ungerade + do { a = a>>1; } while ((a & bit_j) ==0); + } + else // a0, a ungerade, b gerade + do { b = b>>1; } while ((b & bit_j) ==0); + } + } + // a=b>0 + return a; +} diff --git a/src/integer/hash/Makeflags b/src/integer/hash/Makeflags new file mode 100644 index 0000000..fc69747 --- /dev/null +++ b/src/integer/hash/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/integer/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/base/hash diff --git a/src/integer/hash/cl_I_hash_gcobject.cc b/src/integer/hash/cl_I_hash_gcobject.cc new file mode 100644 index 0000000..31e4d70 --- /dev/null +++ b/src/integer/hash/cl_I_hash_gcobject.cc @@ -0,0 +1,48 @@ +// class cl_ht_from_integer_to_gcobject. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I_hash_gcobject.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_hash1.h" + +static void cl_hashtable_from_integer_to_gcobject_destructor (cl_heap* pointer) +{ +#if (defined(__mips__) || defined(__mips64__)) && !defined(__GNUC__) // workaround SGI CC bug + (*(cl_heap_hashtable_from_integer_to_gcobject*)pointer).~cl_heap_hashtable_1(); +#else + (*(cl_heap_hashtable_from_integer_to_gcobject*)pointer).~cl_heap_hashtable_from_integer_to_gcobject(); +#endif +} + +cl_class cl_class_hashtable_from_integer_to_gcobject = { + cl_hashtable_from_integer_to_gcobject_destructor, + 0 +}; + +// These are not inline, because they tend to duplicate a lot of template code. + +cl_ht_from_integer_to_gcobject::cl_ht_from_integer_to_gcobject () +{ + var cl_heap_hashtable_from_integer_to_gcobject* ht = new cl_heap_hashtable_from_integer_to_gcobject (); + ht->refcount = 1; + ht->type = &cl_class_hashtable_from_integer_to_gcobject; + pointer = ht; +} + +cl_gcobject * cl_ht_from_integer_to_gcobject::get (const cl_I& x) const +{ + return ((cl_heap_hashtable_from_integer_to_gcobject*)pointer)->get(x); +} + +void cl_ht_from_integer_to_gcobject::put (const cl_I& x, const cl_gcobject& y) const +{ + ((cl_heap_hashtable_from_integer_to_gcobject*)pointer)->put(x,y); +} + diff --git a/src/integer/hash/cl_I_hash_gcobject.h b/src/integer/hash/cl_I_hash_gcobject.h new file mode 100644 index 0000000..7839b39 --- /dev/null +++ b/src/integer/hash/cl_I_hash_gcobject.h @@ -0,0 +1,39 @@ +// cl_I hash tables + +#ifndef _CL_I_HASH_GCOBJECT_H +#define _CL_I_HASH_GCOBJECT_H + +#include "cl_number.h" +#include "cl_integer.h" + +// For the sake of gcc-2.7.x, this declaration must come before cl_hash1.h. +extern unsigned long hashcode (const cl_I& x); + +#include "cl_hash1.h" + +// Equality. +static inline bool equal (const cl_I& x, const cl_I& y) +{ return (bool)cl_equal(x,y); } + +typedef cl_htentry1 cl_htentry_from_integer_to_gcobject; + +typedef cl_heap_hashtable_1 cl_heap_hashtable_from_integer_to_gcobject; + +typedef _cl_hashtable_iterator cl_hashtable_from_integer_to_gcobject_iterator; + +struct cl_ht_from_integer_to_gcobject : public cl_gcpointer { + // Constructors. + cl_ht_from_integer_to_gcobject (); + cl_ht_from_integer_to_gcobject (const cl_ht_from_integer_to_gcobject&); + // Assignment operators. + cl_ht_from_integer_to_gcobject& operator= (const cl_ht_from_integer_to_gcobject&); + // Iterator. + cl_hashtable_from_integer_to_gcobject_iterator iterator () const + { return ((cl_heap_hashtable_from_integer_to_gcobject*)pointer)->iterator(); } + // Lookup. + cl_gcobject * get (const cl_I& x) const; + // Store. + void put (const cl_I& x, const cl_gcobject& y) const; +}; + +#endif /* _CL_I_HASH_GCOBJECT_H */ diff --git a/src/integer/hash/cl_I_hash_gcpointer.cc b/src/integer/hash/cl_I_hash_gcpointer.cc new file mode 100644 index 0000000..a05cf8a --- /dev/null +++ b/src/integer/hash/cl_I_hash_gcpointer.cc @@ -0,0 +1,48 @@ +// class cl_ht_from_integer_to_gcpointer. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I_hash_gcpointer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_hash1.h" + +static void cl_hashtable_from_integer_to_gcpointer_destructor (cl_heap* pointer) +{ +#if (defined(__mips__) || defined(__mips64__)) && !defined(__GNUC__) // workaround SGI CC bug + (*(cl_heap_hashtable_from_integer_to_gcpointer*)pointer).~cl_heap_hashtable_1(); +#else + (*(cl_heap_hashtable_from_integer_to_gcpointer*)pointer).~cl_heap_hashtable_from_integer_to_gcpointer(); +#endif +} + +cl_class cl_class_hashtable_from_integer_to_gcpointer = { + cl_hashtable_from_integer_to_gcpointer_destructor, + 0 +}; + +// These are not inline, because they tend to duplicate a lot of template code. + +cl_ht_from_integer_to_gcpointer::cl_ht_from_integer_to_gcpointer () +{ + var cl_heap_hashtable_from_integer_to_gcpointer* ht = new cl_heap_hashtable_from_integer_to_gcpointer (); + ht->refcount = 1; + ht->type = &cl_class_hashtable_from_integer_to_gcpointer; + pointer = ht; +} + +cl_gcpointer * cl_ht_from_integer_to_gcpointer::get (const cl_I& x) const +{ + return ((cl_heap_hashtable_from_integer_to_gcpointer*)pointer)->get(x); +} + +void cl_ht_from_integer_to_gcpointer::put (const cl_I& x, const cl_gcpointer& y) const +{ + ((cl_heap_hashtable_from_integer_to_gcpointer*)pointer)->put(x,y); +} + diff --git a/src/integer/hash/cl_I_hash_gcpointer.h b/src/integer/hash/cl_I_hash_gcpointer.h new file mode 100644 index 0000000..e97cb3a --- /dev/null +++ b/src/integer/hash/cl_I_hash_gcpointer.h @@ -0,0 +1,39 @@ +// cl_I hash tables + +#ifndef _CL_I_HASH_GCPOINTER_H +#define _CL_I_HASH_GCPOINTER_H + +#include "cl_number.h" +#include "cl_integer.h" + +// For the sake of gcc-2.7.x, this declaration must come before cl_hash1.h. +extern unsigned long hashcode (const cl_I& x); + +#include "cl_hash1.h" + +// Equality. +static inline bool equal (const cl_I& x, const cl_I& y) +{ return (bool)cl_equal(x,y); } + +typedef cl_htentry1 cl_htentry_from_integer_to_gcpointer; + +typedef cl_heap_hashtable_1 cl_heap_hashtable_from_integer_to_gcpointer; + +typedef _cl_hashtable_iterator cl_hashtable_from_integer_to_gcpointer_iterator; + +struct cl_ht_from_integer_to_gcpointer : public cl_gcpointer { + // Constructors. + cl_ht_from_integer_to_gcpointer (); + cl_ht_from_integer_to_gcpointer (const cl_ht_from_integer_to_gcpointer&); + // Assignment operators. + cl_ht_from_integer_to_gcpointer& operator= (const cl_ht_from_integer_to_gcpointer&); + // Iterator. + cl_hashtable_from_integer_to_gcpointer_iterator iterator () const + { return ((cl_heap_hashtable_from_integer_to_gcpointer*)pointer)->iterator(); } + // Lookup. + cl_gcpointer * get (const cl_I& x) const; + // Store. + void put (const cl_I& x, const cl_gcpointer& y) const; +}; + +#endif /* _CL_I_HASH_GCPOINTER_H */ diff --git a/src/integer/hash/cl_I_hash_pointer.cc b/src/integer/hash/cl_I_hash_pointer.cc new file mode 100644 index 0000000..eb436e1 --- /dev/null +++ b/src/integer/hash/cl_I_hash_pointer.cc @@ -0,0 +1,48 @@ +// class cl_ht_from_integer_to_pointer. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I_hash_pointer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_hash1.h" + +static void cl_hashtable_from_integer_to_pointer_destructor (cl_heap* pointer) +{ +#if (defined(__mips__) || defined(__mips64__)) && !defined(__GNUC__) // workaround SGI CC bug + (*(cl_heap_hashtable_from_integer_to_pointer*)pointer).~cl_heap_hashtable_1(); +#else + (*(cl_heap_hashtable_from_integer_to_pointer*)pointer).~cl_heap_hashtable_from_integer_to_pointer(); +#endif +} + +cl_class cl_class_hashtable_from_integer_to_pointer = { + cl_hashtable_from_integer_to_pointer_destructor, + 0 +}; + +// These are not inline, because they tend to duplicate a lot of template code. + +cl_ht_from_integer_to_pointer::cl_ht_from_integer_to_pointer () +{ + var cl_heap_hashtable_from_integer_to_pointer* ht = new cl_heap_hashtable_from_integer_to_pointer (); + ht->refcount = 1; + ht->type = &cl_class_hashtable_from_integer_to_pointer; + pointer = ht; +} + +void* * cl_ht_from_integer_to_pointer::get (const cl_I& x) const +{ + return ((cl_heap_hashtable_from_integer_to_pointer*)pointer)->get(x); +} + +void cl_ht_from_integer_to_pointer::put (const cl_I& x, void* y) const +{ + ((cl_heap_hashtable_from_integer_to_pointer*)pointer)->put(x,y); +} + diff --git a/src/integer/hash/cl_I_hash_pointer.h b/src/integer/hash/cl_I_hash_pointer.h new file mode 100644 index 0000000..77fd1ea --- /dev/null +++ b/src/integer/hash/cl_I_hash_pointer.h @@ -0,0 +1,39 @@ +// cl_I hash tables + +#ifndef _CL_I_HASH_POINTER_H +#define _CL_I_HASH_POINTER_H + +#include "cl_number.h" +#include "cl_integer.h" + +// For the sake of gcc-2.7.x, this declaration must come before cl_hash1.h. +extern unsigned long hashcode (const cl_I& x); + +#include "cl_hash1.h" + +// Equality. +static inline bool equal (const cl_I& x, const cl_I& y) +{ return (bool)cl_equal(x,y); } + +typedef cl_htentry1 cl_htentry_from_integer_to_pointer; + +typedef cl_heap_hashtable_1 cl_heap_hashtable_from_integer_to_pointer; + +typedef _cl_hashtable_iterator cl_hashtable_from_integer_to_pointer_iterator; + +struct cl_ht_from_integer_to_pointer : public cl_gcpointer { + // Constructors. + cl_ht_from_integer_to_pointer (); + cl_ht_from_integer_to_pointer (const cl_ht_from_integer_to_pointer&); + // Assignment operators. + cl_ht_from_integer_to_pointer& operator= (const cl_ht_from_integer_to_pointer&); + // Iterator. + cl_hashtable_from_integer_to_pointer_iterator iterator () const + { return ((cl_heap_hashtable_from_integer_to_pointer*)pointer)->iterator(); } + // Lookup. + void* * get (const cl_I& x) const; + // Store. + void put (const cl_I& x, void* y) const; +}; + +#endif /* _CL_I_HASH_POINTER_H */ diff --git a/src/integer/hash/cl_I_hash_rcobject.cc b/src/integer/hash/cl_I_hash_rcobject.cc new file mode 100644 index 0000000..f6dcaf2 --- /dev/null +++ b/src/integer/hash/cl_I_hash_rcobject.cc @@ -0,0 +1,48 @@ +// class cl_ht_from_integer_to_rcobject. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I_hash_rcobject.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_hash1.h" + +static void cl_hashtable_from_integer_to_rcobject_destructor (cl_heap* pointer) +{ +#if (defined(__mips__) || defined(__mips64__)) && !defined(__GNUC__) // workaround SGI CC bug + (*(cl_heap_hashtable_from_integer_to_rcobject*)pointer).~cl_heap_hashtable_1(); +#else + (*(cl_heap_hashtable_from_integer_to_rcobject*)pointer).~cl_heap_hashtable_from_integer_to_rcobject(); +#endif +} + +cl_class cl_class_hashtable_from_integer_to_rcobject = { + cl_hashtable_from_integer_to_rcobject_destructor, + 0 +}; + +// These are not inline, because they tend to duplicate a lot of template code. + +cl_ht_from_integer_to_rcobject::cl_ht_from_integer_to_rcobject () +{ + var cl_heap_hashtable_from_integer_to_rcobject* ht = new cl_heap_hashtable_from_integer_to_rcobject (); + ht->refcount = 1; + ht->type = &cl_class_hashtable_from_integer_to_rcobject; + pointer = ht; +} + +cl_rcobject * cl_ht_from_integer_to_rcobject::get (const cl_I& x) const +{ + return ((cl_heap_hashtable_from_integer_to_rcobject*)pointer)->get(x); +} + +void cl_ht_from_integer_to_rcobject::put (const cl_I& x, const cl_rcobject& y) const +{ + ((cl_heap_hashtable_from_integer_to_rcobject*)pointer)->put(x,y); +} + diff --git a/src/integer/hash/cl_I_hash_rcobject.h b/src/integer/hash/cl_I_hash_rcobject.h new file mode 100644 index 0000000..e8c34ca --- /dev/null +++ b/src/integer/hash/cl_I_hash_rcobject.h @@ -0,0 +1,39 @@ +// cl_I hash tables + +#ifndef _CL_I_HASH_RCOBJECT_H +#define _CL_I_HASH_RCOBJECT_H + +#include "cl_number.h" +#include "cl_integer.h" + +// For the sake of gcc-2.7.x, this declaration must come before cl_hash1.h. +extern unsigned long hashcode (const cl_I& x); + +#include "cl_hash1.h" + +// Equality. +static inline bool equal (const cl_I& x, const cl_I& y) +{ return (bool)cl_equal(x,y); } + +typedef cl_htentry1 cl_htentry_from_integer_to_rcobject; + +typedef cl_heap_hashtable_1 cl_heap_hashtable_from_integer_to_rcobject; + +typedef _cl_hashtable_iterator cl_hashtable_from_integer_to_rcobject_iterator; + +struct cl_ht_from_integer_to_rcobject : public cl_gcpointer { + // Constructors. + cl_ht_from_integer_to_rcobject (); + cl_ht_from_integer_to_rcobject (const cl_ht_from_integer_to_rcobject&); + // Assignment operators. + cl_ht_from_integer_to_rcobject& operator= (const cl_ht_from_integer_to_rcobject&); + // Iterator. + cl_hashtable_from_integer_to_rcobject_iterator iterator () const + { return ((cl_heap_hashtable_from_integer_to_rcobject*)pointer)->iterator(); } + // Lookup. + cl_rcobject * get (const cl_I& x) const; + // Store. + void put (const cl_I& x, const cl_rcobject& y) const; +}; + +#endif /* _CL_I_HASH_RCOBJECT_H */ diff --git a/src/integer/hash/cl_I_hash_rcpointer.cc b/src/integer/hash/cl_I_hash_rcpointer.cc new file mode 100644 index 0000000..00b7a7e --- /dev/null +++ b/src/integer/hash/cl_I_hash_rcpointer.cc @@ -0,0 +1,48 @@ +// class cl_ht_from_integer_to_rcpointer. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I_hash_rcpointer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_hash1.h" + +static void cl_hashtable_from_integer_to_rcpointer_destructor (cl_heap* pointer) +{ +#if (defined(__mips__) || defined(__mips64__)) && !defined(__GNUC__) // workaround SGI CC bug + (*(cl_heap_hashtable_from_integer_to_rcpointer*)pointer).~cl_heap_hashtable_1(); +#else + (*(cl_heap_hashtable_from_integer_to_rcpointer*)pointer).~cl_heap_hashtable_from_integer_to_rcpointer(); +#endif +} + +cl_class cl_class_hashtable_from_integer_to_rcpointer = { + cl_hashtable_from_integer_to_rcpointer_destructor, + 0 +}; + +// These are not inline, because they tend to duplicate a lot of template code. + +cl_ht_from_integer_to_rcpointer::cl_ht_from_integer_to_rcpointer () +{ + var cl_heap_hashtable_from_integer_to_rcpointer* ht = new cl_heap_hashtable_from_integer_to_rcpointer (); + ht->refcount = 1; + ht->type = &cl_class_hashtable_from_integer_to_rcpointer; + pointer = ht; +} + +cl_rcpointer * cl_ht_from_integer_to_rcpointer::get (const cl_I& x) const +{ + return ((cl_heap_hashtable_from_integer_to_rcpointer*)pointer)->get(x); +} + +void cl_ht_from_integer_to_rcpointer::put (const cl_I& x, const cl_rcpointer& y) const +{ + ((cl_heap_hashtable_from_integer_to_rcpointer*)pointer)->put(x,y); +} + diff --git a/src/integer/hash/cl_I_hash_rcpointer.h b/src/integer/hash/cl_I_hash_rcpointer.h new file mode 100644 index 0000000..6f595ea --- /dev/null +++ b/src/integer/hash/cl_I_hash_rcpointer.h @@ -0,0 +1,39 @@ +// cl_I hash tables + +#ifndef _CL_I_HASH_RCPOINTER_H +#define _CL_I_HASH_RCPOINTER_H + +#include "cl_number.h" +#include "cl_integer.h" + +// For the sake of gcc-2.7.x, this declaration must come before cl_hash1.h. +extern unsigned long hashcode (const cl_I& x); + +#include "cl_hash1.h" + +// Equality. +static inline bool equal (const cl_I& x, const cl_I& y) +{ return (bool)cl_equal(x,y); } + +typedef cl_htentry1 cl_htentry_from_integer_to_rcpointer; + +typedef cl_heap_hashtable_1 cl_heap_hashtable_from_integer_to_rcpointer; + +typedef _cl_hashtable_iterator cl_hashtable_from_integer_to_rcpointer_iterator; + +struct cl_ht_from_integer_to_rcpointer : public cl_gcpointer { + // Constructors. + cl_ht_from_integer_to_rcpointer (); + cl_ht_from_integer_to_rcpointer (const cl_ht_from_integer_to_rcpointer&); + // Assignment operators. + cl_ht_from_integer_to_rcpointer& operator= (const cl_ht_from_integer_to_rcpointer&); + // Iterator. + cl_hashtable_from_integer_to_rcpointer_iterator iterator () const + { return ((cl_heap_hashtable_from_integer_to_rcpointer*)pointer)->iterator(); } + // Lookup. + cl_rcpointer * get (const cl_I& x) const; + // Store. + void put (const cl_I& x, const cl_rcpointer& y) const; +}; + +#endif /* _CL_I_HASH_RCPOINTER_H */ diff --git a/src/integer/hash/cl_I_hashcode.cc b/src/integer/hash/cl_I_hashcode.cc new file mode 100644 index 0000000..4d78ed9 --- /dev/null +++ b/src/integer/hash/cl_I_hashcode.cc @@ -0,0 +1,38 @@ +// cl_I hashcode(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I.h" + + +// Implementation. + +unsigned long hashcode (const cl_I& x) +{ + var unsigned long code = 0x814BE3A5; + // We walk through all limbs. It may take some time for very large + // integers, but it's better than completely ignoring some limbs. + if (fixnump(x)) { + #if (cl_value_len <= intLsize) + code += FN_to_L(x); + #elif (cl_word_size==64) + code += FN_to_Q(x); + code ^= (code >> 32); + #endif + code &= 0xFFFFFFFF; + } else { + var const uintD* MSDptr; + var uintC len; + BN_to_NDS_nocopy(x, MSDptr=,len=,); + for (; len > 0; len--) { + var uintD c = msprefnext(MSDptr); + code = (code << 5) | (code >> 27); // rotate left 5 bits + code += (long)c << 16; + code ^= (long)c; + code &= 0xFFFFFFFF; + } + } + return code; +} diff --git a/src/integer/hash/cl_I_hashweak_rcpointer.cc b/src/integer/hash/cl_I_hashweak_rcpointer.cc new file mode 100644 index 0000000..86af55e --- /dev/null +++ b/src/integer/hash/cl_I_hashweak_rcpointer.cc @@ -0,0 +1,48 @@ +// class cl_wht_from_integer_to_rcpointer. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I_hashweak_rcpointer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_hash1weak.h" + +static void cl_weak_hashtable_from_integer_to_rcpointer_destructor (cl_heap* pointer) +{ +#if (defined(__mips__) || defined(__mips64__)) && !defined(__GNUC__) // workaround SGI CC bug + (*(cl_heap_weak_hashtable_from_integer_to_rcpointer*)pointer).~cl_heap_weak_hashtable_1(); +#else + (*(cl_heap_weak_hashtable_from_integer_to_rcpointer*)pointer).~cl_heap_weak_hashtable_from_integer_to_rcpointer(); +#endif +} + +cl_class cl_class_weak_hashtable_from_integer_to_rcpointer = { + cl_weak_hashtable_from_integer_to_rcpointer_destructor, + 0 +}; + +// These are not inline, because they tend to duplicate a lot of template code. + +cl_wht_from_integer_to_rcpointer::cl_wht_from_integer_to_rcpointer (cl_boolean (*maygc_htentry) (const cl_htentry_from_integer_to_rcpointer&)) +{ + var cl_heap_weak_hashtable_from_integer_to_rcpointer* ht = new cl_heap_weak_hashtable_from_integer_to_rcpointer (maygc_htentry); + ht->refcount = 1; + ht->type = &cl_class_weak_hashtable_from_integer_to_rcpointer; + pointer = ht; +} + +cl_rcpointer * cl_wht_from_integer_to_rcpointer::get (const cl_I& x) const +{ + return ((cl_heap_weak_hashtable_from_integer_to_rcpointer*)pointer)->get(x); +} + +void cl_wht_from_integer_to_rcpointer::put (const cl_I& x, const cl_rcpointer& y) const +{ + ((cl_heap_weak_hashtable_from_integer_to_rcpointer*)pointer)->put(x,y); +} + diff --git a/src/integer/hash/cl_I_hashweak_rcpointer.h b/src/integer/hash/cl_I_hashweak_rcpointer.h new file mode 100644 index 0000000..833ef2a --- /dev/null +++ b/src/integer/hash/cl_I_hashweak_rcpointer.h @@ -0,0 +1,39 @@ +// cl_I hash tables + +#ifndef _CL_I_HASHWEAK_RCPOINTER_H +#define _CL_I_HASHWEAK_RCPOINTER_H + +#include "cl_number.h" +#include "cl_integer.h" + +// For the sake of gcc-2.7.x, this declaration must come before cl_hash1.h. +extern unsigned long hashcode (const cl_I& x); + +#include "cl_hash1weak.h" + +// Equality. +static inline bool equal (const cl_I& x, const cl_I& y) +{ return (bool)cl_equal(x,y); } + +typedef cl_htentry1 cl_htentry_from_integer_to_rcpointer; + +typedef cl_heap_weak_hashtable_1 cl_heap_weak_hashtable_from_integer_to_rcpointer; + +typedef _cl_hashtable_iterator cl_hashtable_from_integer_to_rcpointer_iterator; + +struct cl_wht_from_integer_to_rcpointer : public cl_gcpointer { + // Constructors. + cl_wht_from_integer_to_rcpointer (cl_boolean (*maygc_htentry) (const cl_htentry_from_integer_to_rcpointer&)); + cl_wht_from_integer_to_rcpointer (const cl_wht_from_integer_to_rcpointer&); + // Assignment operators. + cl_wht_from_integer_to_rcpointer& operator= (const cl_wht_from_integer_to_rcpointer&); + // Iterator. + cl_hashtable_from_integer_to_rcpointer_iterator iterator () const + { return ((cl_heap_weak_hashtable_from_integer_to_rcpointer*)pointer)->iterator(); } + // Lookup. + cl_rcpointer * get (const cl_I& x) const; + // Store. + void put (const cl_I& x, const cl_rcpointer& y) const; +}; + +#endif /* _CL_I_HASHWEAK_RCPOINTER_H */ diff --git a/src/integer/input/Makeflags b/src/integer/input/Makeflags new file mode 100644 index 0000000..542d768 --- /dev/null +++ b/src/integer/input/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/integer/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/base/string diff --git a/src/integer/input/cl_I_from_string.cc b/src/integer/input/cl_I_from_string.cc new file mode 100644 index 0000000..1ce6930 --- /dev/null +++ b/src/integer/input/cl_I_from_string.cc @@ -0,0 +1,26 @@ +// cl_I (const char *) constructor. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer_class.h" + + +// Implementation. + +#include "cl_input.h" +#include "cl_integer_io.h" + +cl_read_flags cl_I_read_flags = { + syntax_integer, + lsyntax_all, + 10, + { cl_float_format_ffloat, cl_float_format_lfloat_min, cl_true } +}; + +cl_I::cl_I (const char * string) +{ + pointer = as_cl_private_thing( + read_integer(cl_I_read_flags,string,NULL,NULL)); +} diff --git a/src/integer/input/cl_I_read.cc b/src/integer/input/cl_I_read.cc new file mode 100644 index 0000000..06f3cd4 --- /dev/null +++ b/src/integer/input/cl_I_read.cc @@ -0,0 +1,134 @@ +// read_integer(). +// This file contains a slimmed down version of read_rational(). +// It does not pull in all the rational number code. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer_io.h" + + +// Implementation. + +#include +#include "cl_input.h" +#include "cl_integer.h" +#include "cl_I.h" +#include "cl_abort.h" + +#undef floor +#include +#define floor cln_floor + +// Step forward over all digits, to the end of string or to the next non-digit. +static const char * skip_digits (const char * ptr, const char * string_limit, unsigned int base) +{ + for ( ; ptr != string_limit; ptr++) { + var char ch = *ptr; + if ((ch >= '0') && (ch <= '9')) + if (ch < '0' + (int)base) + continue; + else + break; + else { + if (base <= 10) + break; + if (((ch >= 'A') && (ch < 'A'-10+(int)base)) + || ((ch >= 'a') && (ch < 'a'-10+(int)base)) + ) + continue; + else + break; + } + } + return ptr; +} + +#define at_end_of_parse(ptr) \ + if (end_of_parse) \ + { *end_of_parse = (ptr); } \ + else \ + { if ((ptr) != string_limit) { read_number_junk((ptr),string,string_limit); } } + +const cl_I read_integer (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse) +{ + ASSERT((flags.syntax & ~(syntax_integer|syntax_maybe_bad)) == 0); + // If no string_limit is given, it defaults to the end of the string. + if (!string_limit) + string_limit = string + strlen(string); + if (flags.syntax & syntax_integer) { + // Check for integer syntax. + var unsigned int rational_base = flags.rational_base; + var const char * ptr = string; + if (flags.lsyntax & lsyntax_commonlisp) { + if (ptr == string_limit) goto not_integer_syntax; + if (*ptr == '#') { + // Check for #b, #o, #x, #nR syntax. + ptr++; + if (ptr == string_limit) goto not_integer_syntax; + switch (*ptr) { + case 'b': case 'B': + rational_base = 2; break; + case 'o': case 'O': + rational_base = 8; break; + case 'x': case 'X': + rational_base = 16; break; + default: + var const char * base_end_ptr = + skip_digits(ptr,string_limit,10); + if (base_end_ptr == ptr) goto not_integer_syntax; + if (base_end_ptr == string_limit) goto not_integer_syntax; + if (!((*base_end_ptr == 'r') || (*base_end_ptr == 'R'))) + goto not_integer_syntax; + var cl_I base = read_integer(10,0,ptr,0,base_end_ptr-ptr); + if (!((base >= 2) && (base <= 36))) { + fprint(cl_stderr, "Base must be an integer in the range from 2 to 36, not "); + fprint(cl_stderr, base); + fprint(cl_stderr, "\n"); + cl_abort(); + } + rational_base = FN_to_UL(base); ptr = base_end_ptr; + break; + } + ptr++; + } + } + var const char * ptr_after_prefix = ptr; + var cl_signean sign = 0; + if (ptr == string_limit) goto not_integer_syntax; + switch (*ptr) { + case '-': sign = ~sign; + case '+': ptr++; + default: break; + } + var const char * ptr_after_sign = ptr; + // Check for integer syntax: {'+'|'-'|} {digit}+ {'.'|} + // Allow final dot only in Common Lisp syntax if there was no # prefix. + if ((flags.lsyntax & lsyntax_commonlisp) && (ptr_after_prefix == string)) { + ptr = skip_digits(ptr_after_sign,string_limit,10); + if (ptr != ptr_after_sign) + if (ptr != string_limit) + if (*ptr == '.') { + ptr++; + if ((ptr == string_limit) || !(((*ptr >= '0') && (*ptr <= '9')) || ((*ptr >= 'A') && (*ptr <= 'Z') && (*ptr != 'I')) || ((*ptr >= 'a') && (*ptr <= 'z') && (*ptr != 'i')) || (*ptr == '.') || (*ptr == '_') || (*ptr == '/'))) { + at_end_of_parse(ptr); + return read_integer(10,sign,ptr_after_sign,0,ptr-ptr_after_sign); + } + } + } + ptr = skip_digits(ptr_after_sign,string_limit,rational_base); + if ((ptr == string_limit) || !(((*ptr >= '0') && (*ptr <= '9')) || ((*ptr >= 'A') && (*ptr <= 'Z') && (*ptr != 'I')) || ((*ptr >= 'a') && (*ptr <= 'z') && (*ptr != 'i')) || (*ptr == '.') || (*ptr == '_') || (*ptr == '/'))) { + at_end_of_parse(ptr); + return read_integer(rational_base,sign,ptr_after_sign,0,ptr-ptr_after_sign); + } + } +not_integer_syntax: +bad_syntax: + if (flags.syntax & syntax_maybe_bad) { + ASSERT(end_of_parse); + *end_of_parse = string; + return 0; // dummy return + } + read_number_bad_syntax(string,string_limit); +} diff --git a/src/integer/input/cl_I_read_stream.cc b/src/integer/input/cl_I_read_stream.cc new file mode 100644 index 0000000..e375665 --- /dev/null +++ b/src/integer/input/cl_I_read_stream.cc @@ -0,0 +1,104 @@ +// read_integer(). +// This file contains a slimmed down version of read_rational(). +// It does not pull in all the rational number code. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer_io.h" + + +// Implementation. + +#include "cl_input.h" +#include "cl_io.h" +#include "cl_spushstring.h" + +// We read an entire token (or even more, if it begins with #C) into a +// buffer and then call read_integer() on the buffer. + +class pushstring_hack : public cl_spushstring { +public: + char* start_pointer (void) { return buffer; } + char* end_pointer (void) { return buffer+index; } +}; + +static cl_boolean number_char_p (char c) +{ + if ((c >= '0') && (c <= '9')) + return cl_true; + if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'))) + return cl_true; + switch (c) { + case '+': case '-': case '.': case '/': + return cl_true; + default: + return cl_false; + } +} + +const cl_I read_integer (cl_istream stream, const cl_read_flags& flags) +{ + // One pre-allocated buffer. This reduces the allocation/free cost. + static pushstring_hack buffer; + + var int c; + // Skip whitespace at the beginning. + loop { + c = freadchar(stream); + if (c == cl_EOF) goto eof; + if ((c == ' ') || (c == '\t') || (c == '\n')) + continue; + else + break; + } + // Found first non-whitespace character. + // Numbers cannot cross lines. We can treat EOF and '\n' the same way. + buffer.reset(); + if (c == '#') { + if (!(flags.lsyntax & lsyntax_commonlisp)) + goto syntax1; + buffer.push(c); + // Read some digits, then a letter, then a token. + loop { + c = freadchar(stream); + if (c == cl_EOF) goto eof; + buffer.push(c); + if ((c >= '0') && (c <= '9')) + continue; + else + break; + } + if (!(((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')))) + goto syntax1; + buffer.push(c); + c = freadchar(stream); + if (c == cl_EOF) goto eof; + } + // Read a number token. + if (!number_char_p(c)) + goto syntax1; + loop { + buffer.push(c); + c = freadchar(stream); + if (c == cl_EOF) + break; + if (!number_char_p(c)) { + funreadchar(stream,c); + break; + } + } + // Parse the number. + return read_integer(flags, + buffer.start_pointer(), buffer.end_pointer(), + NULL + ); + + // Handle syntax error. +syntax1: buffer.push(c); + read_number_bad_syntax(buffer.start_pointer(),buffer.end_pointer()); + + // Handle premature EOF. +eof: read_number_eof(); +} diff --git a/src/integer/input/cl_I_readparsed.cc b/src/integer/input/cl_I_readparsed.cc new file mode 100644 index 0000000..8f68249 --- /dev/null +++ b/src/integer/input/cl_I_readparsed.cc @@ -0,0 +1,21 @@ +// read_integer(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer_io.h" + + +// Implementation. + +#include "cl_I.h" + +const cl_I read_integer (unsigned int base, cl_signean sign, const char * string, uintL index1, uintL index2) +{ + var cl_I x = digits_to_I(&string[index1],index2-index1,(uintD)base); + if (sign == 0) + return x; + else + return -x; // negatives Vorzeichen -> Vorzeichenwechsel +} diff --git a/src/integer/misc/Makeflags b/src/integer/misc/Makeflags new file mode 100644 index 0000000..3696f90 --- /dev/null +++ b/src/integer/misc/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/integer/Makeflags +SUBDIR_INCLUDES += diff --git a/src/integer/misc/cl_BN_class.cc b/src/integer/misc/cl_BN_class.cc new file mode 100644 index 0000000..9572725 --- /dev/null +++ b/src/integer/misc/cl_BN_class.cc @@ -0,0 +1,15 @@ +// cl_class_bignum. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +cl_class cl_class_bignum = { + NULL, // empty destructor + cl_class_flags_subclass_complex | cl_class_flags_subclass_real | cl_class_flags_subclass_rational +}; diff --git a/src/integer/misc/cl_FN_class.cc b/src/integer/misc/cl_FN_class.cc new file mode 100644 index 0000000..0e383a8 --- /dev/null +++ b/src/integer/misc/cl_FN_class.cc @@ -0,0 +1,20 @@ +// cl_class_fixnum. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +cl_class cl_class_fixnum = { + NULL, // destructor not used, since not heap objects + cl_class_flags_subclass_complex | cl_class_flags_subclass_real | cl_class_flags_subclass_rational +}; + +AT_INITIALIZATION(ini_class_fixnum) +{ + cl_immediate_classes[cl_FN_tag] = &cl_class_fixnum; +} diff --git a/src/integer/misc/cl_I_abs.cc b/src/integer/misc/cl_I_abs.cc new file mode 100644 index 0000000..6202f38 --- /dev/null +++ b/src/integer/misc/cl_I_abs.cc @@ -0,0 +1,22 @@ +// abs(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" + +const cl_I abs (const cl_I& x) +{ + // Methode: + // Bei x<0: (- x), sonst x. + if (minusp(x)) + return -x; + else + return x; +} diff --git a/src/integer/misc/cl_I_as.cc b/src/integer/misc/cl_I_as.cc new file mode 100644 index 0000000..6aaee30 --- /dev/null +++ b/src/integer/misc/cl_I_as.cc @@ -0,0 +1,38 @@ +// as_cl_I(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_N.h" + +// Cf. cl_I_p in cl_I_ring.cc. +// But here, for better inlining in g++, it is preferrable to finish every +// alternative with either "return cl_true;" or "return cl_false;". + +inline cl_boolean cl_I_p (const cl_number& x) +{ + if (!x.pointer_p()) + switch (x.nonpointer_tag()) { + case cl_FN_tag: + return cl_true; + } + else + if (x.pointer_type() == &cl_class_bignum) + return cl_true; + return cl_false; +} + +const cl_I& as_cl_I (const cl_number& x, const char * filename, int line) +{ + if (cl_I_p(x)) { + DeclareType(cl_I,x); + return x; + } else + cl_as_error(x,"an integer",filename,line); +} diff --git a/src/integer/misc/cl_I_debug.cc b/src/integer/misc/cl_I_debug.cc new file mode 100644 index 0000000..3941aaf --- /dev/null +++ b/src/integer/misc/cl_I_debug.cc @@ -0,0 +1,28 @@ +// cl_I debugging support. + +// General includes. +#include "cl_sysdep.h" + +// Specification. + + +// Implementation. + +#include "cl_integer.h" +#include "cl_io.h" +#include "cl_integer_io.h" + +static void dprint (cl_heap* pointer) +{ + var const cl_I& obj = *(const cl_I*)&pointer; + fprint(cl_debugout, "(cl_I) "); + fprint(cl_debugout, obj); +} +AT_INITIALIZATION(dprint_I) +{ + cl_register_type_printer(cl_class_fixnum,dprint); + cl_register_type_printer(cl_class_bignum,dprint); +} + +// This dummy links in this module when requires it. +int cl_I_debug_module; diff --git a/src/integer/misc/cl_I_eqhashcode.cc b/src/integer/misc/cl_I_eqhashcode.cc new file mode 100644 index 0000000..b36072b --- /dev/null +++ b/src/integer/misc/cl_I_eqhashcode.cc @@ -0,0 +1,133 @@ +// cl_I equal_hashcode(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_N.h" +#include "cl_I.h" + +inline uint32 cl_equal_hashcode (const cl_FN& x) +{ + var cl_signean sign; + var uint32 x32 = FN_to_L(x); // x als 32-Bit-Zahl + if (FN_L_minusp(x,(sint32)x32)) { + x32 = -x32; + sign = -1; + } else { + sign = 0; + if (x32 == 0) + return 0; + } + var uintL s; + integerlength32(x32, s = 32 - ); + var uint32 msd = x32 << s; + var sintL exp = 32-s; + return equal_hashcode_low(msd,exp,sign); +} + +inline uint32 cl_equal_hashcode (const cl_BN& x) +{ + var const uintD* MSDptr; + var uintC len; + BN_to_NDS_nocopy(x, MSDptr = , len = ,); + // Nicht alle führenden intDsize+1 Bits sind gleich. +#if (intDsize==64) + var uint64 msd = mspref(MSDptr,0); + var uint64 msd2 = (len >= 2 ? mspref(MSDptr,1) : 0); + var cl_signean sign; + if ((sint64)msd < 0) { // falls <0, negieren + sign = -1; + // msd|msd2 := - msd|msd2 - (1 falls noch weitere Bits /= 0) + msd = ~msd; msd2 = ~msd2; + if ((len <= 2) + || !test_loop_msp(MSDptr mspop 2, len - 2) + ) { + msd2++; + if (msd2 == 0) + msd++; + } + } else { + sign = 0; + } + var sintL exp = (uintL)len * intDsize; + // Nicht alle führenden 65 Bits sind =0. + if (msd==0) { + msd = msd2; + exp -= 64; + } else { + var uintL s; + integerlength64(msd, s = 64 - ); + if (s > 0) + msd = (msd << s) | (msd2 >> (64-s)); + exp -= s; + } + return equal_hashcode_low((uint32)(msd>>32),exp,sign); +#else // (intDsize<=32) + var uint32 msd; + var uint32 msd2; + if (len >= 64/intDsize) { + msd = get_32_Dptr(MSDptr); + msd2 = get_32_Dptr(MSDptr mspop 32/intDsize); + } elif (len > 32/intDsize) { + msd = get_32_Dptr(MSDptr); + msd2 = get_max32_Dptr(intDsize*len-32, MSDptr mspop 32/intDsize) + << (64-intDsize*len); + } elif ((32/intDsize == 1) || (len == 32/intDsize)) { + msd = get_32_Dptr(MSDptr); + msd2 = 0; + } else { // (len > 0) && (len < 32/intDsize) + msd = get_max32_Dptr(intDsize*len,MSDptr) << (32-intDsize*len); + msd2 = 0; + } + var cl_signean sign; + if ((sint32)msd < 0) { // falls <0, negieren + sign = -1; + // msd|msd2 := - msd|msd2 - (1 falls noch weitere Bits /= 0) + msd = ~msd; msd2 = ~msd2; + if ((len <= 64/intDsize) + || !test_loop_msp(MSDptr mspop 64/intDsize, len - 64/intDsize) + ) { + msd2++; + if (msd2 == 0) + msd++; + } + } else { + sign = 0; + } + var sintL exp = (uintL)len * intDsize; + // Nicht alle führenden intDsize+1 Bits sind =0. + // Wegen intDsize<=32: Nicht alle führenden 33 Bits sind =0. + if (msd==0) { + msd = msd2; + exp -= 32; + } + // Nicht alle führenden 32 Bits sind =0. + // Führendes Bit auf 1 normalisieren: + else { + var uintL s; + integerlength32(msd, s = 32 - ); + if (s > 0) + msd = (msd << s) | (msd2 >> (32-s)); + exp -= s; + } + return equal_hashcode_low(msd,exp,sign); +#endif +} + +MAYBE_INLINE +uint32 cl_equal_hashcode (const cl_I& x) +{ + if (fixnump(x)) { + DeclareType(cl_FN,x); + return cl_equal_hashcode(x); + } else { + DeclareType(cl_BN,x); + return cl_equal_hashcode(x); + } +} diff --git a/src/integer/misc/cl_I_exptpos.cc b/src/integer/misc/cl_I_exptpos.cc new file mode 100644 index 0000000..d3a2de3 --- /dev/null +++ b/src/integer/misc/cl_I_exptpos.cc @@ -0,0 +1,54 @@ +// expt_pos(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +const cl_I expt_pos (const cl_I& x, uintL y) +{ + // Methode: + // a:=x, b:=y, c:=1. [a^b*c bleibt invariant, = x^y.] + // Solange b>1, + // falls b ungerade, setze c:=a*c, + // setze b:=floor(b/2), + // setze a:=a*a. + // Wenn b=1, setze c:=a*c. + // Liefere c. + // Oder optimiert: + // a:=x, b:=y. + // Solange b gerade, setze a:=a*a, b:=b/2. [a^b bleibt invariant, = x^y.] + // c:=a. + // Solange b:=floor(b/2) >0 ist, + // setze a:=a*a, und falls b ungerade, setze c:=a*c. + // Liefere c. + #if 0 // unoptimiert + var cl_I a = x; + var uintL b = y; + var cl_I c = 1; + until (b == 1) + { if (b % 2) // b ungerade? + { c = a * c; } + b = b >> 1; // b := (floor b 2) + a = square(a); + } + return a * c; + #else // optimiert + var cl_I a = x; + var uintL b = y; + while (!(b % 2)) { a = square(a); b = b >> 1; } + var cl_I c = a; + until (b == 1) + { b = b >> 1; + a = square(a); + if (b % 2) { c = a * c; } + } + return c; + #endif +} +// Bit complexity (x of length N): O(M(N*y)). + diff --git a/src/integer/misc/cl_I_exptpos_I.cc b/src/integer/misc/cl_I_exptpos_I.cc new file mode 100644 index 0000000..b0266aa --- /dev/null +++ b/src/integer/misc/cl_I_exptpos_I.cc @@ -0,0 +1,56 @@ +// expt_pos(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" + +const cl_I expt_pos (const cl_I& x, const cl_I& y) +{ + // Methode: + // a:=x, b:=y, c:=1. [a^b*c bleibt invariant, = x^y.] + // Solange b>1, + // falls b ungerade, setze c:=a*c, + // setze b:=floor(b/2), + // setze a:=a*a. + // Wenn b=1, setze c:=a*c. + // Liefere c. + // Oder optimiert: + // a:=x, b:=y. + // Solange b gerade, setze a:=a*a, b:=b/2. [a^b bleibt invariant, = x^y.] + // c:=a. + // Solange b:=floor(b/2) >0 ist, + // setze a:=a*a, und falls b ungerade, setze c:=a*c. + // Liefere c. + #if 0 // unoptimiert + var cl_I a = x; + var cl_I b = y; + var cl_I c = 1; + until (eq(b,1)) + { if (oddp(b)) + { c = a * c; } + b = b >> 1; // b := (floor b 2) + a = square(a); + } + return a * c; + #else // optimiert + var cl_I a = x; + var cl_I b = y; + while (!oddp(b)) { a = square(a); b = b >> 1; } + var cl_I c = a; + until (eq(b,1)) + { b = b >> 1; + a = square(a); + if (oddp(b)) { c = a * c; } + } + return c; + #endif +} +// Bit complexity (x of length N): O(M(N*y)). + diff --git a/src/integer/misc/cl_I_max.cc b/src/integer/misc/cl_I_max.cc new file mode 100644 index 0000000..c8cdef9 --- /dev/null +++ b/src/integer/misc/cl_I_max.cc @@ -0,0 +1,15 @@ +// max(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +const cl_I max (const cl_I& x, const cl_I& y) +{ + return (x >= y ? x : y); +} diff --git a/src/integer/misc/cl_I_min.cc b/src/integer/misc/cl_I_min.cc new file mode 100644 index 0000000..08ea62d --- /dev/null +++ b/src/integer/misc/cl_I_min.cc @@ -0,0 +1,15 @@ +// min(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +const cl_I min (const cl_I& x, const cl_I& y) +{ + return (x <= y ? x : y); +} diff --git a/src/integer/misc/cl_I_oddp.cc b/src/integer/misc/cl_I_oddp.cc new file mode 100644 index 0000000..98301de --- /dev/null +++ b/src/integer/misc/cl_I_oddp.cc @@ -0,0 +1,30 @@ +// oddp(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" + +cl_boolean oddp (const cl_I& x) +{ + if (fixnump(x)) { + // Fixnum: Bit 0 abprüfen + if (x.word & bit(cl_value_shift)) + return cl_true; + else + return cl_false; + } else { + // Bignum: Bit 0 im letzten Digit abprüfen + if (lspref(BN_LSDptr(x),0) & bit(0)) + return cl_true; + else + return cl_false; + } +} diff --git a/src/integer/misc/cl_I_ord2.cc b/src/integer/misc/cl_I_ord2.cc new file mode 100644 index 0000000..efc5fd6 --- /dev/null +++ b/src/integer/misc/cl_I_ord2.cc @@ -0,0 +1,44 @@ +// ord2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" + +// Methode 1a: +// Sei n = ord2(x). Dann ist logxor(x,x-1) = 2^n + (2^n-1) = 2^(n+1)-1. +// Also (ord2 x) = (1- (integer-length (logxor x (1- x)))) . +// Methode 1b: +// Sei n = ord2(x). Dann ist logand(x,-x) = 2^n. +// Also (ord2 x) = (1- (integer-length (logand x (- x)))) . +// Methode 1c: +// Sei n = ord2(x). Dann ist lognot(logior(x,-x)) = 2^n-1. +// Also (ord2 x) = (integer-length (lognot (logior x (- x)))) . +// Methode 2: +// Nullbits am Schluß von x abzählen: +// (ord2 x) = intDsize * Anzahl der Nulldigits am Schluß +// + Anzahl der Nullbits am Ende des letzten Digits /=0. + +uintL ord2 (const cl_I& x) // x /= 0 +{ + if (fixnump(x)) + { var uint32 x_ = FN_to_L(x); // x als 32-Bit-Zahl + ord2_32(x_,return); + } + else + { var uintL bitcount = 0; + var const uintD* ptr; + BN_to_NDS_nocopy(x, ,,ptr=); // normalisierte DS zu x bilden. + while (lspref(ptr,0) == 0) { lsshrink(ptr); bitcount += intDsize; } // Nulldigits abzählen + var uintD lsd = lspref(ptr,0); // letztes Digit /=0 + ord2_D(lsd,bitcount +=); // dessen Nullbits abzählen + return bitcount; + } +} diff --git a/src/integer/misc/cl_I_power2p.cc b/src/integer/misc/cl_I_power2p.cc new file mode 100644 index 0000000..07790ca --- /dev/null +++ b/src/integer/misc/cl_I_power2p.cc @@ -0,0 +1,40 @@ +// power2p(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" + +uintL power2p (const cl_I& x) // x > 0 +{ +// Methode 1: Wenn ord2(x) = integer_length(x)-1. +// Methode 2: Wenn logand(x,x-1) = 0. +// Methode 3: Wenn das erste Digit /=0 eine Zweierpotenz ist und alle weiteren +// Digits Null sind. + if (fixnump(x)) + { var uintL x_ = FN_to_UL(x); + if (!((x_ & (x_-1)) == 0)) return 0; // keine Zweierpotenz + integerlength32(x_,return); // Zweierpotenz: n = integer_length(x) + } + else + { var const uintD* MSDptr; + var uintC len; + var const uintD* LSDptr; + BN_to_NDS_nocopy(x, MSDptr=,len=,LSDptr=); // normalisierte DS zu x bilden. + var uintD msd = mspref(MSDptr,0); + if (msd==0) { msshrink(MSDptr); msd = mspref(MSDptr,0); len--; } + // len = Anzahl der Digits ab MSDptr, len>0, msd = erstes Digit (/=0) + if (!((msd & (msd-1)) == 0)) return 0; // erstes Digit muß Zweierpotenz sein + if (DS_test_loop(MSDptr mspop 1,len-1,LSDptr)) return 0; // danach alles Nullen + {var uintL msdlen; + integerlengthD(msd, msdlen=); + return intDsize*(uintL)(len-1) + msdlen; // integer_length(x) als Ergebnis + }} +} diff --git a/src/integer/misc/cl_I_signum.cc b/src/integer/misc/cl_I_signum.cc new file mode 100644 index 0000000..dd9f207 --- /dev/null +++ b/src/integer/misc/cl_I_signum.cc @@ -0,0 +1,20 @@ +// signum(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" + +MAYBE_INLINE +const cl_I signum (const cl_I& x) +{ + if (minusp(x)) { return -1; } // x<0 -> -1 + elif (zerop(x)) { return 0; } // x=0 -> 0 + else { return 1; } // x>0 -> +1 +} diff --git a/src/integer/misc/combin/Makeflags b/src/integer/misc/combin/Makeflags new file mode 100644 index 0000000..3696f90 --- /dev/null +++ b/src/integer/misc/combin/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/integer/Makeflags +SUBDIR_INCLUDES += diff --git a/src/integer/misc/combin/cl_I_binomial.cc b/src/integer/misc/combin/cl_I_binomial.cc new file mode 100644 index 0000000..b85d387 --- /dev/null +++ b/src/integer/misc/combin/cl_I_binomial.cc @@ -0,0 +1,56 @@ +// binomial(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I_combin.h" + +const cl_I binomial (uintL n, uintL k) +{ + // Method: + // Ensure 0 <= k <= n: If nn/2, replace k by n-k. + // Compute the product (n-k+1)...n and divide by k!. + // When computing the product m < i <= n, split into the odd part + // and the even part. The even part is 2^(ord2(n!)-ord2(m!)), + // and recall that ord2(n!) = n - logcount(n). The odd part is + // computed recursively: It is the product of the odd part of + // m/2 < i <= n/2, times the product of m < 2*i+1 <= n. The + // recursion goes until floor(m/2^j) = floor(n/2^j) or floor(n/2^j) < 2. + if (n < k) + return 0; + // Now 0 <= k <= n. + if (2*k > n) + k = n-k; + // Now 0 <= k <= n/2. + var cl_I prod = 1; + var uintL m = n-k; + var uintL j = 0; + { + var uintL a = m; + var uintL b = n; + while (a < b && b > 1) { + a = floor(a,2); b = floor(b,2); + j++; + } + } + while (j > 0) { + j--; + var uintL a = m>>j; + var uintL b = n>>j; + // Compute product(a < i <= b and i odd, i) + a = floor(a-1,2); + b = floor(b-1,2); + // = product(a < i <= b, 2i+1) + if (a < b) + prod = prod * cl_I_prod_ungerade(a,b); + } + prod = prod << (k + logcount(m) - logcount(n)); + return exquopos(prod,factorial(k)); +} diff --git a/src/integer/misc/combin/cl_I_combin.h b/src/integer/misc/combin/cl_I_combin.h new file mode 100644 index 0000000..73f02f0 --- /dev/null +++ b/src/integer/misc/combin/cl_I_combin.h @@ -0,0 +1,13 @@ +// cl_I internals for combinatorial functions + +#ifndef _CL_I_COMBIN_H +#define _CL_I_COMBIN_H + +#include "cl_number.h" +#include "cl_integer_class.h" + +// UP für Fakultät: +// Bilde das Produkt prod(a < i <= b, 2*i+1), wobei 0 <= a < b klein. +extern const cl_I cl_I_prod_ungerade (uintL a, uintL b); + +#endif /* _CL_I_COMBIN_H */ diff --git a/src/integer/misc/combin/cl_I_doublefactorial.cc b/src/integer/misc/combin/cl_I_doublefactorial.cc new file mode 100644 index 0000000..2b9193f --- /dev/null +++ b/src/integer/misc/combin/cl_I_doublefactorial.cc @@ -0,0 +1,139 @@ +// doublefactorial(). + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_I_doublefactorial) + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_I_combin.h" + + // Method: + // n <= 19 -> Get result (Fixnum) from table + // Else: + // odd n: same procedure as factorial(n) but now, each odd number in + // n/2^k < m <= n/2^(k-1) occurs only once in the product and we do not + // shift at the end, since there are no powers of two. + // even n: set m to n/2 and calculate n!!=factorial(m)*2^m using the same + // divide and conquer method as in the function factorial() to compute + // the product of all odd numbers. At the end, apply a shift of + // ord2(n!) = n - logcount(n) to account both for 2^m and for powers of + // two in factorial(m). + +static cl_I const doublefakul_table [] = { + L_to_FN(1), + L_to_FN(1UL), + L_to_FN(1UL*2), + L_to_FN(1UL*3), + #if (cl_value_len>=5) + L_to_FN(1UL*2*4), + L_to_FN(1UL*3*5), + #if (cl_value_len>=7) + L_to_FN(1UL*2*4*6), + #if (cl_value_len>=8) + L_to_FN(1UL*3*5*7), + #if (cl_value_len>=10) + L_to_FN(1UL*2*4*6*8), + #if (cl_value_len>=11) + L_to_FN(1UL*3*5*7*9), + #if (cl_value_len>=13) + L_to_FN(1UL*2*4*6*8*10), + #if (cl_value_len>=15) + L_to_FN(1UL*3*5*7*9*11), + #if (cl_value_len>=17) + L_to_FN(1UL*2*4*6*8*10*12), + #if (cl_value_len>=19) + L_to_FN(1UL*3*5*7*9*11*13), + #if (cl_value_len>=21) + L_to_FN(1UL*2*4*6*8*10*12*14), + #if (cl_value_len>=22) + L_to_FN(1UL*3*5*7*9*11*13*15), + #if (cl_value_len>=25) + L_to_FN(1UL*2*4*6*8*10*12*14*16), + #if (cl_value_len>=27) + L_to_FN(1UL*3*5*7*9*11*13*15*17), + #if (cl_value_len>=29) + L_to_FN(1UL*2*4*6*8*10*12*14*16*18), + #if (cl_value_len>=31) + L_to_FN(1UL*3*5*7*9*11*13*15*17*19), + #if (cl_value_len>=33) + ... + #endif + #endif + #endif + #endif + #endif + #endif + #endif + #endif + #endif + #endif + #endif + #endif + #endif + #endif + #endif + #endif +}; + +const cl_I doublefactorial (uintL n) // assume n >= 0 small +{ + if (n < sizeof(doublefakul_table)/sizeof(cl_I)) + { return doublefakul_table[n]; } + else { + if (n%2) // n odd + { var cl_I prod = 1; // bisheriges Produkt := 1 + var uintL k = 1; + var uintL A = n; + var uintL B = n; // obere Intervallgrenze floor(n/2^(k-1)) + loop + { // 'A' enthält floor(n/2^(k-1)). + A = A >> 1; // untere Grenze floor(n/2^k) + // 'A' enthält floor(n/2^k). + // Bilde Teilprodukt prod(A < i <= B & oddp(i), i) + // = prod(floor((A-1)/2) < i <= floor((B-1)/2), 2*i+1) + // wobei B = floor(n/2^(k-1)), A = floor(n/2^k) = floor(B/2). + { var uintL b = floor(B-1,2); + if (b==0) break; // B=2 oder B=1 -> Produkt fertig + var uintL a = floor(A-1,2); + prod = cl_I_prod_ungerade(a,b) * prod; // aufmultiplizieren + } + k = k+1; + B = A; + } + return prod; + } else // n even + { var cl_I prod = 1; // bisheriges Produkt := 1 + var uintL m = n/2; + var uintL k = 1; + var uintL A = m; + var uintL B = m; // obere Intervallgrenze floor(m/2^(k-1)) + loop + { // 'A' enthält floor(m/2^(k-1)). + A = A >> 1; // untere Grenze floor(m/2^k) + // 'A' enthält floor(m/2^k). + // Bilde Teilprodukt prod(A < i <= B & oddp(i), i) + // = prod(floor((A-1)/2) < i <= floor((B-1)/2), 2*i+1) + // wobei B = floor(m/2^(k-1)), A = floor(m/2^k) = floor(B/2). + { var uintL b = floor(B-1,2); + if (b==0) break; // B=2 oder B=1 -> Produkt fertig + var uintL a = floor(A-1,2); + prod = expt_pos(cl_I_prod_ungerade(a,b),k) * prod; // aufmultiplizieren + } + k = k+1; + B = A; + } + return prod << (n - logcount(n)); + } + } +} +// Bit complexity (N := n): O(log(N)^2*M(N)). + +CL_PROVIDE_END(cl_I_doublefactorial) + diff --git a/src/integer/misc/combin/cl_I_factorial.cc b/src/integer/misc/combin/cl_I_factorial.cc new file mode 100644 index 0000000..34ea69c --- /dev/null +++ b/src/integer/misc/combin/cl_I_factorial.cc @@ -0,0 +1,99 @@ +// factorial(). + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_I_factorial) + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_I_combin.h" + + // Methode: + // n <= 10 -> Ergebnis (Fixnum) aus Tabelle + // Sonst: + // Zweierpotenzen extra am Schluß durch einen Shift um + // ord2(n!) = sum(k>=1, floor(n/2^k) ) = n - logcount(n) Bits. + // Für k>=1 wird jede ungerade Zahl m im Intervall n/2^k < m <= n/2^(k-1) + // genau k mal gebraucht (als ungerader Anteil von m*2^0,...,m*2^(k-1) ). + // Zur Bestimmung des Produkts aller ungeraden Zahlen in einem Intervall + // a < m <= b verwenden wir eine rekursive Funktion, die nach Divide-and- + // Conquer das Produkt über die Intervalle a < m <= c und c < m <= b + // (c := floor((a+b)/2)) bestimmt und beide zusammenmultipliziert. Dies + // vermeidet, daß oft große Zahlen mit ganz kleinen Zahlen multipliziert + // werden. + +static cl_I const fakul_table [] = { + L_to_FN(1), + L_to_FN(1UL), + L_to_FN(1UL*2), + #if (cl_value_len>=4) + L_to_FN(1UL*2*3), + #if (cl_value_len>=6) + L_to_FN(1UL*2*3*4), + #if (cl_value_len>=8) + L_to_FN(1UL*2*3*4*5), + #if (cl_value_len>=11) + L_to_FN(1UL*2*3*4*5*6), + #if (cl_value_len>=14) + L_to_FN(1UL*2*3*4*5*6*7), + #if (cl_value_len>=17) + L_to_FN(1UL*2*3*4*5*6*7*8), + #if (cl_value_len>=20) + L_to_FN(1UL*2*3*4*5*6*7*8*9), + #if (cl_value_len>=23) + L_to_FN(1UL*2*3*4*5*6*7*8*9*10), + #if (cl_value_len>=27) + L_to_FN(1UL*2*3*4*5*6*7*8*9*10*11), + #if (cl_value_len>=30) + L_to_FN(1UL*2*3*4*5*6*7*8*9*10*11*12), + #if (cl_value_len>=34) + ... + #endif + #endif + #endif + #endif + #endif + #endif + #endif + #endif + #endif + #endif + #endif +}; + +const cl_I factorial (uintL n) // assume n >= 0 small +{ + if (n < sizeof(fakul_table)/sizeof(cl_I)) + { return fakul_table[n]; } + else + { var cl_I prod = 1; // bisheriges Produkt := 1 + var uintL k = 1; + var uintL A = n; + var uintL B = n; // obere Intervallgrenze floor(n/2^(k-1)) + loop + { // 'A' enthält floor(n/2^(k-1)). + A = A >> 1; // untere Grenze floor(n/2^k) + // 'A' enthält floor(n/2^k). + // Bilde Teilprodukt prod(A < i <= B & oddp(i), i) + // = prod(floor((A-1)/2) < i <= floor((B-1)/2), 2*i+1) + // wobei B = floor(n/2^(k-1)), A = floor(n/2^k) = floor(B/2). + { var uintL b = floor(B-1,2); + if (b==0) break; // B=2 oder B=1 -> Produkt fertig + var uintL a = floor(A-1,2); + prod = expt_pos(cl_I_prod_ungerade(a,b),k) * prod; // aufmultiplizieren + } + k = k+1; + B = A; + } + return prod << (n - logcount(n)); + } +} +// Bit complexity (N := n): O(log(N)^2*M(N)). + +CL_PROVIDE_END(cl_I_factorial) diff --git a/src/integer/misc/combin/cl_I_factorial_aux.cc b/src/integer/misc/combin/cl_I_factorial_aux.cc new file mode 100644 index 0000000..983c805 --- /dev/null +++ b/src/integer/misc/combin/cl_I_factorial_aux.cc @@ -0,0 +1,32 @@ +// cl_I_prod_ungerade(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_I_combin.h" + + +// Implementation. + +#include "cl_I.h" + +const cl_I cl_I_prod_ungerade (uintL a, uintL b) +{ + var uintL diff = b-a; // Anzahl der Faktoren + if (diff <= 4) { + // Produkt iterativ bilden + var cl_I faktor = L_to_FN(2*b+1); // 2*b+1 als letzter Faktor + var cl_I produkt = faktor; + var uintC count; + dotimesC(count,diff-1, + { faktor = faktor-2; // nächster Faktor + produkt = faktor*produkt; // mit bisherigem Produkt multiplizieren + }); + return produkt; + } else { + // Produkt rekursiv bilden + var uintL c = floor(a+b,2); // c:=floor((a+b)/2) + return cl_I_prod_ungerade(a,c) * cl_I_prod_ungerade(c,b); // zwei Teilprodukte + } +} diff --git a/src/integer/output/Makeflags b/src/integer/output/Makeflags new file mode 100644 index 0000000..542d768 --- /dev/null +++ b/src/integer/output/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/integer/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/base/string diff --git a/src/integer/output/cl_I_aprint.cc b/src/integer/output/cl_I_aprint.cc new file mode 100644 index 0000000..7c0e1c5 --- /dev/null +++ b/src/integer/output/cl_I_aprint.cc @@ -0,0 +1,17 @@ +// print_integer(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer_io.h" + + +// Implementation. + +#include "cl_output.h" + +void print_integer (cl_ostream stream, const cl_print_flags& flags, const cl_I& z) +{ + print_integer(stream,(const cl_print_number_flags&)flags,z); +} diff --git a/src/integer/output/cl_I_bprint.cc b/src/integer/output/cl_I_bprint.cc new file mode 100644 index 0000000..84253bd --- /dev/null +++ b/src/integer/output/cl_I_bprint.cc @@ -0,0 +1,17 @@ +// print_integer(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer_io.h" + + +// Implementation. + +#include "cl_output.h" + +void print_integer (cl_ostream stream, const cl_print_number_flags& flags, const cl_I& z) +{ + print_integer(stream,(const cl_print_real_flags&)flags,z); +} diff --git a/src/integer/output/cl_I_cprint.cc b/src/integer/output/cl_I_cprint.cc new file mode 100644 index 0000000..1a72b06 --- /dev/null +++ b/src/integer/output/cl_I_cprint.cc @@ -0,0 +1,17 @@ +// print_integer(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer_io.h" + + +// Implementation. + +#include "cl_output.h" + +void print_integer (cl_ostream stream, const cl_print_real_flags& flags, const cl_I& z) +{ + print_integer(stream,(const cl_print_rational_flags&)flags,z); +} diff --git a/src/integer/output/cl_I_decstring.cc b/src/integer/output/cl_I_decstring.cc new file mode 100644 index 0000000..013c482 --- /dev/null +++ b/src/integer/output/cl_I_decstring.cc @@ -0,0 +1,25 @@ +// cl_decimal_string(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer_io.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" +#include "cl_sstring.h" + +char * cl_decimal_string (const cl_I& x) +{ + CL_ALLOCA_STACK; + var uintL need = cl_digits_need(x,10); + var uintB* ziffern = cl_alloc_array(uintB,need); // Platz für die Ziffern + var cl_digits erg; erg.LSBptr = &ziffern[need]; + I_to_digits(x,10,&erg); // Umwandlung in Ziffern + var char* result = cl_sstring((char*)erg.MSBptr,erg.len); // Ziffern in String schreiben + return result; +} diff --git a/src/integer/output/cl_I_dprint.cc b/src/integer/output/cl_I_dprint.cc new file mode 100644 index 0000000..82d6c0c --- /dev/null +++ b/src/integer/output/cl_I_dprint.cc @@ -0,0 +1,47 @@ +// print_integer(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer_io.h" + + +// Implementation. + +#include "cl_output.h" + +void print_integer (cl_ostream stream, const cl_print_rational_flags& flags, const cl_I& z) +{ + var unsigned int base = flags.rational_base; + if (flags.rational_readably) + // Radix-Specifier ausgeben: + switch (base) { + case 2: + fprintchar(stream,'#'); + fprintchar(stream,'b'); + break; + case 8: + fprintchar(stream,'#'); + fprintchar(stream,'o'); + break; + case 16: + fprintchar(stream,'#'); + fprintchar(stream,'x'); + break; + case 10: + // Basis 10 bei Integers durch + // nachgestellten Punkt kennzeichnen: + print_integer(stream,base,z); + fprintchar(stream,'.'); + return; + default: + // Basis in #nR-Schreibweise ausgeben: + fprintchar(stream,'#'); + print_integer(stream,10,base); + fprintchar(stream,'r'); + break; + } + // Integer in Basis base ausgeben: + print_integer(stream,base,z); +} diff --git a/src/integer/output/cl_I_print.cc b/src/integer/output/cl_I_print.cc new file mode 100644 index 0000000..5b973c1 --- /dev/null +++ b/src/integer/output/cl_I_print.cc @@ -0,0 +1,36 @@ +// print_integer(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer_io.h" + + +// Implementation. + +#include "cl_io.h" +#include "cl_I.h" +#include "cl_DS.h" + +void print_integer (cl_ostream stream, unsigned int base, const cl_I& z) +{ + var cl_I abs_z; + if (minusp(z)) { + // z<0 -> Vorzeichen ausgeben: + fprintchar(stream,'-'); + abs_z = -z; + } else + abs_z = z; + CL_ALLOCA_STACK; + var uintL need = cl_digits_need(abs_z,base); + var uintB* ziffern = cl_alloc_array(uintB,need); // Platz für die Ziffern + var cl_digits erg; erg.LSBptr = &ziffern[need]; + I_to_digits(abs_z,(uintD)base,&erg); // Umwandlung in Ziffern + // Ziffern ausgeben: + { + var uintB* ptr = erg.MSBptr; + var uintL count = erg.len; + do { fprintchar(stream,*ptr++); } until (--count==0); + } +} diff --git a/src/integer/output/cl_I_print_string.cc b/src/integer/output/cl_I_print_string.cc new file mode 100644 index 0000000..28d41ad --- /dev/null +++ b/src/integer/output/cl_I_print_string.cc @@ -0,0 +1,40 @@ +// print_integer_to_string(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer_io.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" +#include "cl_sstring.h" + +char * print_integer_to_string (unsigned int base, const cl_I& z) +{ + var cl_boolean minus_p = cl_false; + var cl_I abs_z; + if (minusp(z)) { + // z<0 -> später Vorzeichen ausgeben: + minus_p = cl_true; + abs_z = -z; + } else + abs_z = z; + CL_ALLOCA_STACK; + var uintL need = 1+cl_digits_need(abs_z,base); + var uintB* ziffern = cl_alloc_array(uintB,need); // Platz für die Ziffern + var cl_digits erg; erg.LSBptr = &ziffern[need]; + I_to_digits(abs_z,(uintD)base,&erg); // Umwandlung in Ziffern + // Vorzeichen ankleben: + var char* ergptr = (char*)erg.MSBptr; + var uintL erglen = erg.len; + if (minus_p) { + *--ergptr = '-'; + erglen++; + } + var char* result = cl_sstring(ergptr,erglen); // Ziffern in String schreiben + return result; +} diff --git a/src/integer/random/Makeflags b/src/integer/random/Makeflags new file mode 100644 index 0000000..61e5ec7 --- /dev/null +++ b/src/integer/random/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/integer/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/base/random diff --git a/src/integer/random/cl_I_random.cc b/src/integer/random/cl_I_random.cc new file mode 100644 index 0000000..36c4f42 --- /dev/null +++ b/src/integer/random/cl_I_random.cc @@ -0,0 +1,34 @@ +// random_I(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_random_impl.h" +#include "cl_I.h" +#include "cl_DS.h" + +const cl_I random_I (cl_random_state& randomstate, const cl_I& n) +{ + CL_ALLOCA_STACK; + var const uintD* n_MSDptr; + var uintC n_len; + var const uintD* n_LSDptr; + I_to_NDS_nocopy(n, n_MSDptr=,n_len=,n_LSDptr=,cl_false,); // Digit sequence >0 zu n + var uintD* MSDptr; + var uintC len = n_len + ceiling(16,intDsize); // 16 Bits mehr + // neue UDS mit len Zufallsdigits bilden: + num_stack_alloc(len,MSDptr=,); + random_UDS(randomstate,MSDptr,len); + // und durch n dividieren: + var DS q; + var DS r; + UDS_divide(MSDptr,len,MSDptr mspop len, n_MSDptr,n_len,n_LSDptr, &q,&r); + // Rest in Integer umwandeln: + return NUDS_to_I(r.MSDptr,r.len); +} diff --git a/src/integer/random/cl_I_trandom.cc b/src/integer/random/cl_I_trandom.cc new file mode 100644 index 0000000..bd27ab1 --- /dev/null +++ b/src/integer/random/cl_I_trandom.cc @@ -0,0 +1,41 @@ +// testrandom_I(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_integer.h" + + +// Implementation. + +#include "cl_random_impl.h" +#include "cl_I.h" +#include "cl_DS.h" + +const cl_I testrandom_I (cl_random_state& randomstate) +{ + var uint32 ran = random32(randomstate); + var cl_boolean negative = (cl_boolean)(ran & 1); + var cl_boolean algo = (cl_boolean)((ran>>1) & 1); + ran = ran >> 2; + ran = ran & ((1<<8)-1); + var uintC len = + (ran == 0 ? 0 : + ran <= 80 ? 1 : + ran <= 128 ? 2 : + ran <= 158 ? 3 : + ran <= 172 ? 4 : + ran <= 200 ? (ran-153)/4 : // 5..11 + ran-189 // 12..66 + ); + CL_ALLOCA_STACK; + var uintD* MSDptr; + num_stack_alloc_1(len,MSDptr=,); + if (algo) + { testrandom_UDS(randomstate,MSDptr,len); } + else + { random_UDS(randomstate,MSDptr,len); } + var cl_I x = UDS_to_I(MSDptr,len); + return (negative ? -x : x); +} diff --git a/src/integer/ring/Makeflags b/src/integer/ring/Makeflags new file mode 100644 index 0000000..3696f90 --- /dev/null +++ b/src/integer/ring/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/integer/Makeflags +SUBDIR_INCLUDES += diff --git a/src/integer/ring/cl_0_ring.cc b/src/integer/ring/cl_0_ring.cc new file mode 100644 index 0000000..8ba2a21 --- /dev/null +++ b/src/integer/ring/cl_0_ring.cc @@ -0,0 +1,129 @@ +// Null ring. + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_0_ring) + +// Specification. +#include "cl_null_ring.h" + + +// Implementation. + +#include "cl_integer_class.h" + +static const _cl_ring_element null_op0 (cl_heap_ring* R) +{ + return _cl_ring_element(R, (cl_I)0); +} + +static const _cl_ring_element null_op1 (cl_heap_ring* R, const _cl_ring_element& x) +{ + unused x; + return _cl_ring_element(R, (cl_I)0); +} + +static const _cl_ring_element null_op2 (cl_heap_ring* R, const _cl_ring_element& x, const _cl_ring_element& y) +{ + unused x; + unused y; + return _cl_ring_element(R, (cl_I)0); +} + +static void null_fprint (cl_heap_ring* R, cl_ostream stream, const _cl_ring_element& x) +{ + unused R; + unused x; + fprint(stream,"0"); +} + +static cl_boolean null_equal (cl_heap_ring* R, const _cl_ring_element& x, const _cl_ring_element& y) +{ + unused R; + unused x; + unused y; + return cl_true; +} + +#define null_zero null_op0 +static cl_boolean null_zerop (cl_heap_ring* R, const _cl_ring_element& x) +{ + unused R; + unused x; + return cl_true; +} +#define null_plus null_op2 +#define null_minus null_op2 +#define null_uminus null_op1 + +#define null_one null_op0 +static const _cl_ring_element null_canonhom (cl_heap_ring* R, const cl_I& x) +{ + unused x; + return _cl_ring_element(R, (cl_I)0); +} +#define null_mul null_op2 +#define null_square null_op1 +static const _cl_ring_element null_expt_pos (cl_heap_ring* R, const _cl_ring_element& x, const cl_I& y) +{ + unused x; + unused y; + return _cl_ring_element(R, (cl_I)0); +} + +static cl_ring_setops null_setops = { + null_fprint, + null_equal +}; +static cl_ring_addops null_addops = { + null_zero, + null_zerop, + null_plus, + null_minus, + null_uminus +}; +static cl_ring_mulops null_mulops = { + null_one, + null_canonhom, + null_mul, + null_square, + null_expt_pos +}; + +extern cl_class cl_class_null_ring; + +class cl_heap_null_ring : public cl_heap_ring { + SUBCLASS_cl_heap_ring() +public: + // Constructor. + cl_heap_null_ring () + : cl_heap_ring (&null_setops,&null_addops,&null_mulops) + { type = &cl_class_null_ring; } + // Destructor. + ~cl_heap_null_ring () {} +}; + +static void cl_null_ring_destructor (cl_heap* pointer) +{ + (*(cl_heap_null_ring*)pointer).~cl_heap_null_ring(); +} + +static void cl_null_ring_dprint (cl_heap* pointer) +{ + unused pointer; + fprint(cl_debugout, "(cl_null_ring) cl_0_ring"); +} + +cl_class cl_class_null_ring = { + cl_null_ring_destructor, + cl_class_flags_number_ring, + cl_null_ring_dprint +}; + +inline cl_null_ring::cl_null_ring () + : cl_ring (new cl_heap_null_ring()) {} + +const cl_null_ring cl_0_ring; + +CL_PROVIDE_END(cl_0_ring) diff --git a/src/integer/ring/cl_I_ring.cc b/src/integer/ring/cl_I_ring.cc new file mode 100644 index 0000000..817715f --- /dev/null +++ b/src/integer/ring/cl_I_ring.cc @@ -0,0 +1,156 @@ +// Ring of integers. + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_I_ring) + +// Specification. +#include "cl_integer_ring.h" + + +// Implementation. + +#include "cl_integer.h" +#include "cl_integer_io.h" +#include "cl_I.h" + +static void I_fprint (cl_heap_ring* R, cl_ostream stream, const _cl_ring_element& x) +{ + unused R; + fprint(stream,The(cl_I)(x)); +} + +static cl_boolean I_equal (cl_heap_ring* R, const _cl_ring_element& x, const _cl_ring_element& y) +{ + unused R; + return cl_equal(The(cl_I)(x),The(cl_I)(y)); +} + +static const _cl_ring_element I_zero (cl_heap_ring* R) +{ + return _cl_ring_element(R, (cl_I)0); +} + +static cl_boolean I_zerop (cl_heap_ring* R, const _cl_ring_element& x) +{ + unused R; + return zerop(The(cl_I)(x)); +} + +static const _cl_ring_element I_plus (cl_heap_ring* R, const _cl_ring_element& x, const _cl_ring_element& y) +{ + return _cl_ring_element(R, The(cl_I)(x) + The(cl_I)(y)); +} + +static const _cl_ring_element I_minus (cl_heap_ring* R, const _cl_ring_element& x, const _cl_ring_element& y) +{ + return _cl_ring_element(R, The(cl_I)(x) - The(cl_I)(y)); +} + +static const _cl_ring_element I_uminus (cl_heap_ring* R, const _cl_ring_element& x) +{ + return _cl_ring_element(R, - The(cl_I)(x)); +} + +static const _cl_ring_element I_one (cl_heap_ring* R) +{ + return _cl_ring_element(R, (cl_I)1); +} + +static const _cl_ring_element I_canonhom (cl_heap_ring* R, const cl_I& x) +{ + return _cl_ring_element(R, (cl_I)x); +} + +static const _cl_ring_element I_mul (cl_heap_ring* R, const _cl_ring_element& x, const _cl_ring_element& y) +{ + return _cl_ring_element(R, The(cl_I)(x) * The(cl_I)(y)); +} + +static const _cl_ring_element I_square (cl_heap_ring* R, const _cl_ring_element& x) +{ + return _cl_ring_element(R, square(The(cl_I)(x))); +} + +static const _cl_ring_element I_expt_pos (cl_heap_ring* R, const _cl_ring_element& x, const cl_I& y) +{ + return _cl_ring_element(R, expt_pos(The(cl_I)(x),y)); +} + +static cl_boolean cl_I_p (const cl_number& x) +{ + return (cl_boolean) + (!x.pointer_p() + ? x.nonpointer_tag() == cl_FN_tag + : x.pointer_type() == &cl_class_bignum + ); +} + +static cl_ring_setops I_setops = { + I_fprint, + I_equal +}; +static cl_ring_addops I_addops = { + I_zero, + I_zerop, + I_plus, + I_minus, + I_uminus +}; +static cl_ring_mulops I_mulops = { + I_one, + I_canonhom, + I_mul, + I_square, + I_expt_pos +}; + +static cl_number_ring_ops I_ops = { + cl_I_p, + cl_equal, + zerop, + operator+, + operator-, + operator-, + operator*, + square, + expt_pos +}; + +class cl_heap_integer_ring : public cl_heap_number_ring { + SUBCLASS_cl_heap_ring() +public: + // Constructor. + cl_heap_integer_ring () + : cl_heap_number_ring (&I_setops,&I_addops,&I_mulops, + (cl_number_ring_ops*) &I_ops) + { type = &cl_class_integer_ring; } + // Destructor. + ~cl_heap_integer_ring () {} +}; + +static void cl_integer_ring_destructor (cl_heap* pointer) +{ + (*(cl_heap_integer_ring*)pointer).~cl_heap_integer_ring(); +} + +static void cl_integer_ring_dprint (cl_heap* pointer) +{ + unused pointer; + fprint(cl_debugout, "(cl_integer_ring) cl_I_ring"); +} + +cl_class cl_class_integer_ring = { + cl_integer_ring_destructor, + cl_class_flags_number_ring, + cl_integer_ring_dprint +}; + +// Constructor. +inline cl_integer_ring::cl_specialized_number_ring () + : cl_number_ring (new cl_heap_integer_ring()) {} + +const cl_integer_ring cl_I_ring; + +CL_PROVIDE_END(cl_I_ring) diff --git a/src/modinteger/Makeflags b/src/modinteger/Makeflags new file mode 100644 index 0000000..99cd642 --- /dev/null +++ b/src/modinteger/Makeflags @@ -0,0 +1,3 @@ +# This file contains additional flags for the main Makefile. + +SUBDIR_INCLUDES = -I$(srcdir)/integer/hash -I$(srcdir)/integer -I$(srcdir)/base/hash -I$(srcdir)/base/digitseq -I$(srcdir)/base/digit -Ibase -I$(srcdir)/base $(GMP_INCLUDES) diff --git a/src/modinteger/cl_MI.cc b/src/modinteger/cl_MI.cc new file mode 100644 index 0000000..864d110 --- /dev/null +++ b/src/modinteger/cl_MI.cc @@ -0,0 +1,178 @@ +// Modular integer operations. + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_MI) + +// Specification. +#include "cl_modinteger.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" +#include "cl_2DS.h" +#include "cl_io.h" +#include "cl_integer_io.h" +#include "cl_N.h" +#include "cl_MI.h" +#include "cl_abort.h" +#include "cl_alloca.h" + + +cl_heap_modint_ring::cl_heap_modint_ring (cl_I m, cl_modint_setops* setopv, cl_modint_addops* addopv, cl_modint_mulops* mulopv) + : setops (setopv), addops (addopv), mulops (mulopv), modulus (m) +{ + refcount = 0; // will be incremented by the `cl_modint_ring' constructor + type = &cl_class_modint_ring; + if (minusp(m)) cl_abort(); + if (!::zerop(m)) { + var uintL b = integer_length(m-1); + // m <= 2^b, hence one needs b bits for a representative mod m. + if (b <= 1) { + log2_bits = 0; bits = 1; + } else if (b <= cl_word_size) { + var uintL bb; + integerlength32(b-1,bb=); // b <= 2^bb with bb minimal + log2_bits = bb; bits = 1<= 0 +{ + if (m == 0) + return new cl_heap_modint_ring_int(); + // Now m > 0. + { + var uintL log2_m = power2p(m); + if (log2_m) + return new cl_heap_modint_ring_pow2(m,log2_m-1); + } + // Now m > 1. + { + var uintL log2_m = integer_length(m); // = integerlength(m-1) + if (log2_m < 16) // m < 0x10000 + return new cl_heap_modint_ring_fix16(m); + #if (cl_value_len <= 32) + if (log2_m < cl_value_len) + return new cl_heap_modint_ring_fix29(m); + if (log2_m < 32) // m < 0x100000000 + return new cl_heap_modint_ring_int32(m); + #else + if (log2_m < 32) // m < 0x100000000 + return new cl_heap_modint_ring_fix32(m); + #endif + } + { + var uintL m1 = power2p(m+1); + if (m1) + return new cl_heap_modint_ring_pow2m1(m,m1-1); + } + { + var uintL m1 = power2p(m-1); + if (m1) + return new cl_heap_modint_ring_pow2p1(m,m1-1); + } + { + var cl_heap_modint_ring* R = try_make_modint_ring_montgom(m); + if (R) + return R; + } + return new cl_heap_modint_ring_std(m); +} + + +// The table of modular integer rings. +// A weak hash table cl_I -> cl_modint_ring. +// (It could also be a weak hashuniq table cl_I -> cl_modint_ring.) + +#include "cl_I_hashweak_rcpointer.h" + +// An entry can be collected when the value (the ring) isn't referenced any more +// except from the hash table, and when the key (the modulus) isn't referenced +// any more except from the hash table and the ring. Note that the ring contains +// exactly one reference to the modulus. + +static cl_boolean maygc_htentry (const cl_htentry_from_integer_to_rcpointer& entry) +{ + if (!entry.key.pointer_p() || (entry.key.heappointer->refcount == 2)) + if (!entry.val.pointer_p() || (entry.val.heappointer->refcount == 1)) + return cl_true; + return cl_false; +} + +static const cl_wht_from_integer_to_rcpointer modint_ring_table = cl_wht_from_integer_to_rcpointer(maygc_htentry); + +static inline cl_modint_ring* get_modint_ring (const cl_I& m) +{ + return (cl_modint_ring*) modint_ring_table.get(m); +} + +static inline void store_modint_ring (const cl_modint_ring& R) +{ + modint_ring_table.put(R->modulus,R); +} + + +const cl_modint_ring cl_find_modint_ring (const cl_I& m) +{ + { Mutable(cl_I,m); + m = abs(m); + var cl_modint_ring* ring_in_table = get_modint_ring(m); + if (!ring_in_table) { + var cl_modint_ring R = make_modint_ring(m); + store_modint_ring(R); + ring_in_table = get_modint_ring(m); + if (!ring_in_table) + cl_abort(); + } + return *ring_in_table; +}} + + +const cl_modint_ring cl_modint0_ring = cl_find_modint_ring(0); + +CL_PROVIDE_END(cl_MI) diff --git a/src/modinteger/cl_MI.h b/src/modinteger/cl_MI.h new file mode 100644 index 0000000..19ec66e --- /dev/null +++ b/src/modinteger/cl_MI.h @@ -0,0 +1,10 @@ +// Private modular integer operations. + +#ifndef _CL_MI_H +#define _CL_MI_H + +#include "cl_modinteger.h" + +extern cl_composite_condition* cl_notify_composite (const cl_modint_ring& R, const cl_I& nonunit); + +#endif /* _CL_MI_H */ diff --git a/src/modinteger/cl_MI_cond_composite.cc b/src/modinteger/cl_MI_cond_composite.cc new file mode 100644 index 0000000..8dbfcd8 --- /dev/null +++ b/src/modinteger/cl_MI_cond_composite.cc @@ -0,0 +1,30 @@ +// class cl_composite_condition. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_modinteger.h" + + +// Implementation. + +#include "cl_io.h" +#include "cl_integer_io.h" + +const char * cl_composite_condition::name () const +{ return "cl_composite_condition"; } + +void cl_composite_condition::print (cl_ostream strm) const +{ + fprint(strm, "Exception occurred: p = "); + fprint(strm, p); + fprint(strm, " is not a prime, "); + if (zerop(factor)) + fprint(strm, "no factor found"); + else { + fprint(strm, "factor found: "); + fprint(strm, factor); + } + fprint(strm, "\n"); +} diff --git a/src/modinteger/cl_MI_debug.cc b/src/modinteger/cl_MI_debug.cc new file mode 100644 index 0000000..1c47320 --- /dev/null +++ b/src/modinteger/cl_MI_debug.cc @@ -0,0 +1,31 @@ +// cl_modint_ring debugging support. + +// General includes. +#include "cl_sysdep.h" + +// Specification. + + +// Implementation. + +#include "cl_modinteger.h" +#include "cl_io.h" +#include "cl_integer_io.h" + +static void dprint (cl_heap* pointer) +{ + var const cl_modint_ring& obj = *(const cl_modint_ring*)&pointer; + fprint(cl_debugout, "(cl_modint_ring) Z mod "); + fprint(cl_debugout, obj->modulus); +} +AT_INITIALIZATION(dprint_modint_ring) +{ cl_register_type_printer(cl_class_modint_ring,dprint); } + +void cl_MI::debug_print () const +{ + fprint(cl_debugout, *this); + fprint(cl_debugout, "\n"); +} + +// This dummy links in this module when requires it. +int cl_MI_debug_module; diff --git a/src/modinteger/cl_MI_err_comp.cc b/src/modinteger/cl_MI_err_comp.cc new file mode 100644 index 0000000..2f785f0 --- /dev/null +++ b/src/modinteger/cl_MI_err_comp.cc @@ -0,0 +1,18 @@ +// cl_notify_composite(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_MI.h" + + +// Implementation. + +#include "cl_io.h" +#include "cl_abort.h" + +cl_composite_condition* cl_notify_composite (const cl_modint_ring& R, const cl_I& nonunit) +{ + return new cl_composite_condition(R->modulus,gcd(R->modulus,nonunit)); +} diff --git a/src/modinteger/cl_MI_fix16.h b/src/modinteger/cl_MI_fix16.h new file mode 100644 index 0000000..b5225e6 --- /dev/null +++ b/src/modinteger/cl_MI_fix16.h @@ -0,0 +1,71 @@ +// 1 < m < 2^16, standard representation + +static const _cl_MI fix16_plus (cl_heap_modint_ring* R, const _cl_MI& x, const _cl_MI& y) +{ + var uint32 zr = FN_to_UL(x.rep) + FN_to_UL(y.rep); + if (zr >= FN_to_UL(R->modulus)) { zr = zr - FN_to_UL(R->modulus); } + return _cl_MI(R, L_to_FN(zr)); +} + +static const _cl_MI fix16_minus (cl_heap_modint_ring* R, const _cl_MI& x, const _cl_MI& y) +{ + var uint32 xr = FN_to_UL(x.rep); + var uint32 yr = FN_to_UL(y.rep); + var sint32 zr = xr - yr; + if (zr < 0) { zr = zr + FN_to_UL(R->modulus); } + return _cl_MI(R, L_to_FN(zr)); +} + +static const _cl_MI fix16_uminus (cl_heap_modint_ring* R, const _cl_MI& x) +{ + var uint32 xr = FN_to_UL(x.rep); + var uint32 zr = (xr==0 ? 0 : FN_to_UL(R->modulus)-xr); + return _cl_MI(R, L_to_FN(zr)); +} + +static const _cl_MI fix16_mul (cl_heap_modint_ring* R, const _cl_MI& x, const _cl_MI& y) +{ + var uint32 xr = FN_to_UL(x.rep); + var uint32 yr = FN_to_UL(y.rep); + var uint32 zr = mulu16(xr,yr); + divu_3216_1616(zr,FN_to_UL(R->modulus),,zr=); + return _cl_MI(R, L_to_FN(zr)); +} + +static const _cl_MI fix16_square (cl_heap_modint_ring* R, const _cl_MI& x) +{ + var uint32 xr = FN_to_UL(x.rep); + var uint32 zr = mulu16(xr,xr); + divu_3216_1616(zr,FN_to_UL(R->modulus),,zr=); + return _cl_MI(R, L_to_FN(zr)); +} + +static cl_modint_addops fix16_addops = { + std_zero, + std_zerop, + fix16_plus, + fix16_minus, + fix16_uminus +}; +static cl_modint_mulops fix16_mulops = { + std_one, + std_canonhom, + fix16_mul, + fix16_square, + std_expt_pos, + std_recip, + std_div, + std_expt, + std_reduce_modulo, + std_retract +}; + +class cl_heap_modint_ring_fix16 : public cl_heap_modint_ring { + SUBCLASS_cl_heap_modint_ring() +public: + // Constructor. + cl_heap_modint_ring_fix16 (const cl_I& m) + : cl_heap_modint_ring (m, &std_setops, &fix16_addops, &fix16_mulops) {} + // Virtual destructor. + ~cl_heap_modint_ring_fix16 () {} +}; diff --git a/src/modinteger/cl_MI_fix29.h b/src/modinteger/cl_MI_fix29.h new file mode 100644 index 0000000..d940ee4 --- /dev/null +++ b/src/modinteger/cl_MI_fix29.h @@ -0,0 +1,78 @@ +// 1 < m < 2^(cl_value_len-1), standard representation +// Assuming (cl_value_len <= 32). + +static const _cl_MI fix29_plus (cl_heap_modint_ring* R, const _cl_MI& x, const _cl_MI& y) +{ + var uint32 zr = FN_to_UL(x.rep) + FN_to_UL(y.rep); + if (zr >= FN_to_UL(R->modulus)) { zr = zr - FN_to_UL(R->modulus); } + return _cl_MI(R, L_to_FN(zr)); +} + +static const _cl_MI fix29_minus (cl_heap_modint_ring* R, const _cl_MI& x, const _cl_MI& y) +{ + var uint32 xr = FN_to_UL(x.rep); + var uint32 yr = FN_to_UL(y.rep); + var sint32 zr = xr - yr; + if (zr < 0) { zr = zr + FN_to_UL(R->modulus); } + return _cl_MI(R, L_to_FN(zr)); +} + +static const _cl_MI fix29_uminus (cl_heap_modint_ring* R, const _cl_MI& x) +{ + var uint32 xr = FN_to_UL(x.rep); + var uint32 zr = (xr==0 ? 0 : FN_to_UL(R->modulus)-xr); + return _cl_MI(R, L_to_FN(zr)); +} + +static const _cl_MI fix29_mul (cl_heap_modint_ring* R, const _cl_MI& x, const _cl_MI& y) +{ + var uint32 xr = FN_to_UL(x.rep); + var uint32 yr = FN_to_UL(y.rep); + var uint32 zrhi; + var uint32 zrlo; + mulu32(xr,yr,zrhi=,zrlo=); + var uint32 zr; + divu_6432_3232(zrhi,zrlo,FN_to_UL(R->modulus),,zr=); + return _cl_MI(R, L_to_FN(zr)); +} + +static const _cl_MI fix29_square (cl_heap_modint_ring* R, const _cl_MI& x) +{ + var uint32 xr = FN_to_UL(x.rep); + var uint32 zrhi; + var uint32 zrlo; + mulu32(xr,xr,zrhi=,zrlo=); + var uint32 zr; + divu_6432_3232(zrhi,zrlo,FN_to_UL(R->modulus),,zr=); + return _cl_MI(R, L_to_FN(zr)); +} + +static cl_modint_addops fix29_addops = { + std_zero, + std_zerop, + fix29_plus, + fix29_minus, + fix29_uminus +}; +static cl_modint_mulops fix29_mulops = { + std_one, + std_canonhom, + fix29_mul, + fix29_square, + std_expt_pos, + std_recip, + std_div, + std_expt, + std_reduce_modulo, + std_retract +}; + +class cl_heap_modint_ring_fix29 : public cl_heap_modint_ring { + SUBCLASS_cl_heap_modint_ring() +public: + // Constructor. + cl_heap_modint_ring_fix29 (const cl_I& m) + : cl_heap_modint_ring (m, &std_setops, &fix29_addops, &fix29_mulops) {} + // Virtual destructor. + ~cl_heap_modint_ring_fix29 () {} +}; diff --git a/src/modinteger/cl_MI_fix32.h b/src/modinteger/cl_MI_fix32.h new file mode 100644 index 0000000..3cdb776 --- /dev/null +++ b/src/modinteger/cl_MI_fix32.h @@ -0,0 +1,80 @@ +// 1 < m < 2^32, standard representation +// Assuming (cl_value_len > 32). + +static const _cl_MI fix32_plus (cl_heap_modint_ring* R, const _cl_MI& x, const _cl_MI& y) +{ + var uint32 xr = FN_to_UL(x.rep); + var uint32 yr = FN_to_UL(y.rep); + var uint32 zr = xr + yr; + var uint32 m = FN_to_UL(R->modulus); + if ((zr < xr) || (zr >= m)) { zr = zr - m; } + return _cl_MI(R, L_to_FN(zr)); +} + +static const _cl_MI fix32_minus (cl_heap_modint_ring* R, const _cl_MI& x, const _cl_MI& y) +{ + var uint32 xr = FN_to_UL(x.rep); + var uint32 yr = FN_to_UL(y.rep); + var sint32 zr = (xr >= yr ? xr - yr : xr - yr + FN_to_UL(R->modulus)); + return _cl_MI(R, L_to_FN(zr)); +} + +static const _cl_MI fix32_uminus (cl_heap_modint_ring* R, const _cl_MI& x) +{ + var uint32 xr = FN_to_UL(x.rep); + var uint32 zr = (xr==0 ? 0 : FN_to_UL(R->modulus)-xr); + return _cl_MI(R, L_to_FN(zr)); +} + +static const _cl_MI fix32_mul (cl_heap_modint_ring* R, const _cl_MI& x, const _cl_MI& y) +{ + var uint32 xr = FN_to_UL(x.rep); + var uint32 yr = FN_to_UL(y.rep); + var uint32 zrhi; + var uint32 zrlo; + mulu32(xr,yr,zrhi=,zrlo=); + var uint32 zr; + divu_6432_3232(zrhi,zrlo,FN_to_UL(R->modulus),,zr=); + return _cl_MI(R, L_to_FN(zr)); +} + +static const _cl_MI fix32_square (cl_heap_modint_ring* R, const _cl_MI& x) +{ + var uint32 xr = FN_to_UL(x.rep); + var uint32 zrhi; + var uint32 zrlo; + mulu32(xr,xr,zrhi=,zrlo=); + var uint32 zr; + divu_6432_3232(zrhi,zrlo,FN_to_UL(R->modulus),,zr=); + return _cl_MI(R, L_to_FN(zr)); +} + +static cl_modint_addops fix32_addops = { + std_zero, + std_zerop, + fix32_plus, + fix32_minus, + fix32_uminus +}; +static cl_modint_mulops fix32_mulops = { + std_one, + std_canonhom, + fix32_mul, + fix32_square, + std_expt_pos, + std_recip, + std_div, + std_expt, + std_reduce_modulo, + std_retract +}; + +class cl_heap_modint_ring_fix32 : public cl_heap_modint_ring { + SUBCLASS_cl_heap_modint_ring() +public: + // Constructor. + cl_heap_modint_ring_fix32 (const cl_I& m) + : cl_heap_modint_ring (m, &std_setops, &fix32_addops, &fix32_mulops) {} + // Virtual destructor. + ~cl_heap_modint_ring_fix32 () {} +}; diff --git a/src/modinteger/cl_MI_int.h b/src/modinteger/cl_MI_int.h new file mode 100644 index 0000000..10aadb9 --- /dev/null +++ b/src/modinteger/cl_MI_int.h @@ -0,0 +1,149 @@ +// m = 0 : Z/mZ \isomorph Z + +static void int_fprint (cl_heap_modint_ring* R, cl_ostream stream, const _cl_MI &x) +{ + fprint(stream,R->_retract(x)); +} + +static const cl_I int_reduce_modulo (cl_heap_modint_ring* R, const cl_I& x) +{ + unused R; + return x; // reducing modulo 0 does nothing +} + +// This is the only case where canonhom is injective. +static const _cl_MI int_canonhom (cl_heap_modint_ring* R, const cl_I& x) +{ + return _cl_MI(R, x); +} + +// This is the only case where retract is surjective. +static const cl_I int_retract (cl_heap_modint_ring* R, const _cl_MI& x) +{ + unused R; + return x.rep; +} + +// This is the only case where random yields an error. +static const _cl_MI int_random (cl_heap_modint_ring* R, cl_random_state& randomstate) +{ + unused R; + unused randomstate; + fprint(cl_stderr, "Z / 0 Z not a finite set - no equidistributed random function.\n"); + cl_abort(); +#if ((defined(__sparc__) || defined(__sparc64__)) && !defined(__GNUC__)) // Sun CC wants a return value + return _cl_MI(R, 0); +#endif +} + +static const _cl_MI int_zero (cl_heap_modint_ring* R) +{ + return _cl_MI(R, 0); +} + +static cl_boolean int_zerop (cl_heap_modint_ring* R, const _cl_MI& x) +{ + unused R; + return zerop(x.rep); +} + +static const _cl_MI int_plus (cl_heap_modint_ring* R, const _cl_MI& x, const _cl_MI& y) +{ + return _cl_MI(R, x.rep + y.rep); +} + +static const _cl_MI int_minus (cl_heap_modint_ring* R, const _cl_MI& x, const _cl_MI& y) +{ + return _cl_MI(R, x.rep - y.rep); +} + +static const _cl_MI int_uminus (cl_heap_modint_ring* R, const _cl_MI& x) +{ + return _cl_MI(R, - x.rep); +} + +static const _cl_MI int_one (cl_heap_modint_ring* R) +{ + return _cl_MI(R, 1); +} + +static const _cl_MI int_mul (cl_heap_modint_ring* R, const _cl_MI& x, const _cl_MI& y) +{ + return _cl_MI(R, x.rep * y.rep); +} + +static const _cl_MI int_square (cl_heap_modint_ring* R, const _cl_MI& x) +{ + return _cl_MI(R, square(x.rep)); +} + +static const cl_MI_x int_recip (cl_heap_modint_ring* R, const _cl_MI& x) +{ + var const cl_I& xr = x.rep; + if (eq(xr,1) || eq(xr,-1)) { return cl_MI(R,x); } + if (zerop(xr)) { cl_error_division_by_0(); } + return cl_notify_composite(R,xr); +} + +static const cl_MI_x int_div (cl_heap_modint_ring* R, const _cl_MI& x, const _cl_MI& y) +{ + var const cl_I& yr = y.rep; + if (eq(yr,1)) { return cl_MI(R,x.rep); } + if (eq(yr,-1)) { return cl_MI(R,-x.rep); } + if (zerop(yr)) { cl_error_division_by_0(); } + return cl_notify_composite(R,yr); +} + +static const _cl_MI int_expt_pos (cl_heap_modint_ring* R, const _cl_MI& x, const cl_I& y) +{ + return _cl_MI(R, expt_pos(x.rep,y)); +} + +static const cl_MI_x int_expt (cl_heap_modint_ring* R, const _cl_MI& x, const cl_I& y) +{ + if (eq(x.rep,1)) { return cl_MI(R,1); } + if (eq(x.rep,-1)) { return cl_MI(R,evenp(y)?1:-1); } + if (!minusp(y)) { + if (zerop(y)) + return cl_MI(R,1); + else + return cl_MI(R,expt_pos(x.rep,y)); + } + // y < 0, x nonunit. + if (zerop(x.rep)) { cl_error_division_by_0(); } + return cl_notify_composite(R,x.rep); +} + +static cl_modint_setops int_setops = { + int_fprint, + modint_equal, + int_random +}; +static cl_modint_addops int_addops = { + int_zero, + int_zerop, + int_plus, + int_minus, + int_uminus +}; +static cl_modint_mulops int_mulops = { + int_one, + int_canonhom, + int_mul, + int_square, + int_expt_pos, + int_recip, + int_div, + int_expt, + int_reduce_modulo, + int_retract +}; + +class cl_heap_modint_ring_int : public cl_heap_modint_ring { + SUBCLASS_cl_heap_modint_ring() +public: + // Constructor. + cl_heap_modint_ring_int () : cl_heap_modint_ring (0, &int_setops, &int_addops, &int_mulops) {} + // Virtual destructor. + ~cl_heap_modint_ring_int () {} +}; diff --git a/src/modinteger/cl_MI_int32.h b/src/modinteger/cl_MI_int32.h new file mode 100644 index 0000000..16e0f98 --- /dev/null +++ b/src/modinteger/cl_MI_int32.h @@ -0,0 +1,79 @@ +// 1 < m < 2^32, standard representation + +static const _cl_MI int32_plus (cl_heap_modint_ring* R, const _cl_MI& x, const _cl_MI& y) +{ + var uint32 xr = cl_I_to_UL(x.rep); + var uint32 yr = cl_I_to_UL(y.rep); + var uint32 zr = xr + yr; + var uint32 m = cl_I_to_UL(R->modulus); + if ((zr < xr) || (zr >= m)) { zr = zr - m; } + return _cl_MI(R, UL_to_I(zr)); +} + +static const _cl_MI int32_minus (cl_heap_modint_ring* R, const _cl_MI& x, const _cl_MI& y) +{ + var uint32 xr = cl_I_to_UL(x.rep); + var uint32 yr = cl_I_to_UL(y.rep); + var sint32 zr = (xr >= yr ? xr - yr : xr - yr + cl_I_to_UL(R->modulus)); + return _cl_MI(R, UL_to_I(zr)); +} + +static const _cl_MI int32_uminus (cl_heap_modint_ring* R, const _cl_MI& x) +{ + var uint32 xr = cl_I_to_UL(x.rep); + var uint32 zr = (xr==0 ? 0 : cl_I_to_UL(R->modulus)-xr); + return _cl_MI(R, UL_to_I(zr)); +} + +static const _cl_MI int32_mul (cl_heap_modint_ring* R, const _cl_MI& x, const _cl_MI& y) +{ + var uint32 xr = cl_I_to_UL(x.rep); + var uint32 yr = cl_I_to_UL(y.rep); + var uint32 zrhi; + var uint32 zrlo; + mulu32(xr,yr,zrhi=,zrlo=); + var uint32 zr; + divu_6432_3232(zrhi,zrlo,cl_I_to_UL(R->modulus),,zr=); + return _cl_MI(R, UL_to_I(zr)); +} + +static const _cl_MI int32_square (cl_heap_modint_ring* R, const _cl_MI& x) +{ + var uint32 xr = cl_I_to_UL(x.rep); + var uint32 zrhi; + var uint32 zrlo; + mulu32(xr,xr,zrhi=,zrlo=); + var uint32 zr; + divu_6432_3232(zrhi,zrlo,cl_I_to_UL(R->modulus),,zr=); + return _cl_MI(R, UL_to_I(zr)); +} + +static cl_modint_addops int32_addops = { + std_zero, + std_zerop, + int32_plus, + int32_minus, + int32_uminus +}; +static cl_modint_mulops int32_mulops = { + std_one, + std_canonhom, + int32_mul, + int32_square, + std_expt_pos, + std_recip, + std_div, + std_expt, + std_reduce_modulo, + std_retract +}; + +class cl_heap_modint_ring_int32 : public cl_heap_modint_ring { + SUBCLASS_cl_heap_modint_ring() +public: + // Constructor. + cl_heap_modint_ring_int32 (const cl_I& m) + : cl_heap_modint_ring (m, &std_setops, &int32_addops, &int32_mulops) {} + // Virtual destructor. + ~cl_heap_modint_ring_int32 () {} +}; diff --git a/src/modinteger/cl_MI_lshift.cc b/src/modinteger/cl_MI_lshift.cc new file mode 100644 index 0000000..0bfea4f --- /dev/null +++ b/src/modinteger/cl_MI_lshift.cc @@ -0,0 +1,31 @@ +// operator<< on cl_MI. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_modinteger.h" + + +// Implementation. + +#include "cl_integer.h" + +const cl_MI operator<< (const cl_MI& x, sintL y) // assume 0 <= y < 2^31 +{ + if (y == 0) + return x; + if (y == 1) // frequent case + return x+x; + var const cl_modint_ring& R = x.ring(); + // Method: + // Algorithm 1: divide (x.rep << y) by m. + // asymptotical cost: O(y * log m). + // Algorithm 2: x * expt(2 mod m,y) using modular integer operations. + // asymptotical cost: O(log y * (log m)^2). + // Use algorithm 1 for small y, algorithm 2 for large y. + if ((R->bits < 0) || (y <= 2*R->bits)) + return cl_MI(R, R->reduce_modulo(x.rep << y)); + else + return x * expt_pos(R->canonhom(2), (cl_I)(long)y); +} diff --git a/src/modinteger/cl_MI_montgom.h b/src/modinteger/cl_MI_montgom.h new file mode 100644 index 0000000..e78e8dd --- /dev/null +++ b/src/modinteger/cl_MI_montgom.h @@ -0,0 +1,222 @@ +// m > 1 odd, Montgomery representation + +// We use Montgomery's modular multiplication trick +// [Peter L. Montgomery: Modular multiplication without trial division, +// Mathematics of Computation 44 (1985), 519-521.] +// +// Assume we want to compute modulo M, M odd. V and N will be chosen +// so that V*N==1 mod M and that (a,b) --> a*b*V mod M can be more easily +// computed than (a,b) --> a*b mod M. Then, we have a ring isomorphism +// (Z/MZ, +, * mod M) \isomorph (Z/MZ, +, (a,b) --> a*b*V mod M) +// x mod M --------> x*N mod M +// It is thus preferrable to use x*N mod M as a "representation" of x mod M, +// especially for computations which involve at least several multiplications. +// +// The precise algorithm to compute a*b*V mod M, given a and b, and the choice +// of N and V depend on M and on the hardware. The general idea is this: +// Choose N = 2^n, so that division by N is easy. Recall that V == N^-1 mod M. +// 1. Given a and b as m-bit numbers (M <= 2^m), compute a*b in full +// precision. +// 2. Write a*b = c*N+d, i.e. split it into components c and d. +// 3. Now a*b*V = c*N*V+d*V == c+d*V mod M. +// 4. Instead of computing d*V mod M +// a. by full multiplication and then division mod M, or +// b. by left shifts: repeated application of +// x := 2*x+(0 or 1); if (x >= M) { x := x-M; } +// we compute +// c. by right shifts (recall that d*V == d*2^-n mod M): repeated application +// of if (x odd) { x := (x+M)/2; } else { x := x/2; } +// Usually one will choose N = 2^m, so that c and d have both m bits. +// Several variations are possible: In step 4 one can implement the right +// shifts in hardware. Or (for example when N = 2^160 and working on a +// 32-bit machine) one can do 32 shift steps at the same time: +// Choose M' == M^-1 mod 2^32 and compute n/32 times +// x := (x - ((x mod 2^32) * M' mod 2^32) * M) / 2^32. + +// Here, we choose to use Montgomery representation only if |V| can be chosen +// to be very small, and in that case we compute d*V mod M using standard +// multiplication and division. +// So we choose N = 2^n with 0 < n <= m (the larger n, the better) and hope +// that it will yield V with |V| < 2^k. We thus replace a division of +// 2m bits by m bits (cost: approx. m^2) by a multiplication of n bits with +// k bits (cost: approx. n*k) and a division of max(2m-n,n+k) bits by m bits +// (cost: approx. (max(2m-n,n+k)-m)*m). Of course, U*M+V*N=1 implies (roughly) +// n+k >= m. It is worth it when +// m^2 > n*k + (n+k-m)*m and m^2 > n*k + (m-n)*m +// <==> 3*m^2 > (n+m)*(k+m) and m > k +// <== 3/2*m > k+m (assume n to be near m) +// <==> m/2 > k . +// +// How to find N and V: +// U*M+V*N=1 means that U = (M mod 2^n)^-1 = U_m mod 2^n, where +// U_m := (M mod 2^m)^-1 (2-adic reciprocal). |V| < 2^(m/2) is more or less +// equivalent to |V*N| < 2^(n+m/2) <==> |U|*M < 2^(n+m/2) <==> |U| < n-m/2 +// <==> the most significant m/2 bits of |U| are all equal. So we search +// for a bit string of at least m/2+1 equal bits in U_m, which has m bits. +// Very easy: take the middle bit of U_m, look how many bits adjacent to it +// (at the left and at the right) have the same value. Say these are the +// bits n-1,...,n-l. (Choose n and l as large as possible. k = m-l + O(1).) +// If l < m/2, forget it. Else fix n and compute V = (1-U*M)/2^n. +// +// It is now clear that only very few moduli M will allow such a good +// choice of N and V, but in these cases the Montgomery multiplication +// reduces the multiplication complexity by a large constant factor. + + +class cl_heap_modint_ring_montgom : public cl_heap_modint_ring { + SUBCLASS_cl_heap_modint_ring() +public: + // Constructor. + cl_heap_modint_ring_montgom (const cl_I& M, uintL m, uintL n, const cl_I& V); + // Virtual destructor. + ~cl_heap_modint_ring_montgom () {} + // Additional information. + uintL m; // M = 2^m + uintL n; // N = 2^n, n <= m + cl_I V; +}; + +// Assuming 0 <= x < 2^(2m), return V*x mod M. +static inline const cl_I montgom_redc (cl_heap_modint_ring_montgom* R, const cl_I& x) +{ + return mod((x >> R->n) + (R->V * ldb(x,cl_byte(R->n,0))), R->modulus); +} + +static const _cl_MI montgom_canonhom (cl_heap_modint_ring* _R, const cl_I& x) +{ + var cl_heap_modint_ring_montgom* R = (cl_heap_modint_ring_montgom*)_R; + return _cl_MI(R, mod(x << R->n, R->modulus)); +} + +static const cl_I montgom_retract (cl_heap_modint_ring* _R, const _cl_MI& x) +{ + var cl_heap_modint_ring_montgom* R = (cl_heap_modint_ring_montgom*)_R; + return montgom_redc(R,x.rep); +} + +static const _cl_MI montgom_one (cl_heap_modint_ring* _R) +{ + var cl_heap_modint_ring_montgom* R = (cl_heap_modint_ring_montgom*)_R; + var cl_I zr = (cl_I)1 << R->n; + return _cl_MI(R, R->n == R->m ? zr - R->modulus : zr); +} + +static const _cl_MI montgom_mul (cl_heap_modint_ring* _R, const _cl_MI& x, const _cl_MI& y) +{ + var cl_heap_modint_ring_montgom* R = (cl_heap_modint_ring_montgom*)_R; + return _cl_MI(R, montgom_redc(R,x.rep * y.rep)); +} + +static const _cl_MI montgom_square (cl_heap_modint_ring* _R, const _cl_MI& x) +{ + var cl_heap_modint_ring_montgom* R = (cl_heap_modint_ring_montgom*)_R; + return _cl_MI(R, montgom_redc(R,square(x.rep))); +} + +static const cl_MI_x montgom_recip (cl_heap_modint_ring* _R, const _cl_MI& x) +{ + var cl_heap_modint_ring_montgom* R = (cl_heap_modint_ring_montgom*)_R; + var const cl_I& xr = x.rep; + var cl_I u, v; + var cl_I g = xgcd(xr,R->modulus,&u,&v); + // g = gcd(x,M) = x*u+M*v + if (eq(g,1)) + return cl_MI(R, mod((minusp(u) ? u + R->modulus : u) << (2*R->n), R->modulus)); + if (zerop(xr)) + cl_error_division_by_0(); + return cl_notify_composite(R,xr); +} + +static const cl_MI_x montgom_div (cl_heap_modint_ring* _R, const _cl_MI& x, const _cl_MI& y) +{ + var cl_heap_modint_ring_montgom* R = (cl_heap_modint_ring_montgom*)_R; + var const cl_I& yr = y.rep; + var cl_I u, v; + var cl_I g = xgcd(yr,R->modulus,&u,&v); + // g = gcd(y,M) = y*u+M*v + if (eq(g,1)) + return cl_MI(R, mod((x.rep * (minusp(u) ? u + R->modulus : u)) << R->n, R->modulus)); + if (zerop(yr)) + cl_error_division_by_0(); + return cl_notify_composite(R,yr); +} + +#define montgom_addops std_addops +static cl_modint_mulops montgom_mulops = { + montgom_one, + montgom_canonhom, + montgom_mul, + montgom_square, + std_expt_pos, + montgom_recip, + montgom_div, + std_expt, + std_reduce_modulo, + montgom_retract +}; + +// Constructor. +inline cl_heap_modint_ring_montgom::cl_heap_modint_ring_montgom (const cl_I& M, uintL _m, uintL _n, const cl_I& _V) + : cl_heap_modint_ring (M, &std_setops, &montgom_addops, &montgom_mulops), + m (_m), n (_n), V (_V) +{} + +static cl_heap_modint_ring* try_make_modint_ring_montgom (const cl_I& M) +{ + if (!oddp(M)) + return NULL; + var uintL m = integer_length(M); + CL_ALLOCA_STACK; + var uintC len; + var const uintD* M_LSDptr; + I_to_NDS_nocopy(M, ,len=,M_LSDptr=,cl_false,); + if (lspref(M_LSDptr,len-1)==0) { len--; } // normalize + // Compute U as 2-adic inverse of M. + var uintD* U_LSDptr; + num_stack_alloc(len,,U_LSDptr=); + recip2adic(len,M_LSDptr,U_LSDptr); + // Look at U's bits. + #define U_bit(i) (lspref(U_LSDptr,floor(i,intDsize)) & ((uintD)1 << ((i)%intDsize))) + var uintL i_min; + var uintL i_max; + var uintL i = floor(m,2); + var cl_boolean negative; + if (U_bit(i)) { + for (; --i > 0; ) + if (!U_bit(i)) break; + i_min = i+1; + i = floor(m,2); + for (; ++i < m; ) + if (!U_bit(i)) break; + i_max = i; + negative = cl_true; + } else { + for (; --i > 0; ) + if (U_bit(i)) break; + i_min = i+1; + i = floor(m,2); + for (; ++i < m; ) + if (U_bit(i)) break; + i_max = i; + negative = cl_false; + } + #undef U_bit + // OK, all the bits i_max-1..i_min of U are equal. + if (i_max - i_min <= floor(m,2)) + return NULL; + var uintL n = i_max; + // Turn U (mod 2^n) into a signed integer. + if (n % intDsize) { + if (negative) + lspref(U_LSDptr,floor(n,intDsize)) |= (uintD)(-1) << (n % intDsize); + else + lspref(U_LSDptr,floor(n,intDsize)) &= ((uintD)1 << (n % intDsize)) - 1; + } + var uintL U_len = ceiling(n,intDsize); + var cl_I U = DS_to_I(U_LSDptr lspop U_len,U_len); + var cl_I V_N = 1 - U*M; + if (ldb_test(V_N,cl_byte(n,0))) + cl_abort(); + var cl_I V = V_N >> n; + return new cl_heap_modint_ring_montgom(M,m,n,V); +} diff --git a/src/modinteger/cl_MI_pow2.h b/src/modinteger/cl_MI_pow2.h new file mode 100644 index 0000000..195726b --- /dev/null +++ b/src/modinteger/cl_MI_pow2.h @@ -0,0 +1,144 @@ +// m > 0, m = 2^m1 + +class cl_heap_modint_ring_pow2 : public cl_heap_modint_ring { + SUBCLASS_cl_heap_modint_ring() +public: + // Constructor. + cl_heap_modint_ring_pow2 (const cl_I& m, uintL m1); // m = 2^m1 + // Virtual destructor. + ~cl_heap_modint_ring_pow2 () {} + // Additional information. + uintL m1; +}; + +static +#if !(defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ <= 90)) // workaround g++-2.7.2 and egcs-1.0.2-prerelease bug +inline +#endif +const cl_I pow2_reduce_modulo (cl_heap_modint_ring* _R, const cl_I& x) +{ + var cl_heap_modint_ring_pow2* R = (cl_heap_modint_ring_pow2*)_R; + return ldb(x,cl_byte(R->m1,0)); +} + +static const _cl_MI pow2_canonhom (cl_heap_modint_ring* R, const cl_I& x) +{ + return _cl_MI(R, pow2_reduce_modulo(R,x)); +} + +static const _cl_MI pow2_plus (cl_heap_modint_ring* _R, const _cl_MI& x, const _cl_MI& y) +{ + var cl_heap_modint_ring_pow2* R = (cl_heap_modint_ring_pow2*)_R; + var cl_I zr = x.rep + y.rep; + return _cl_MI(R, ldb(zr,cl_byte(R->m1,0))); +} + +static const _cl_MI pow2_minus (cl_heap_modint_ring* _R, const _cl_MI& x, const _cl_MI& y) +{ + var cl_heap_modint_ring_pow2* R = (cl_heap_modint_ring_pow2*)_R; + var cl_I zr = x.rep - y.rep; + return _cl_MI(R, ldb(zr,cl_byte(R->m1,0))); +} + +static const _cl_MI pow2_uminus (cl_heap_modint_ring* _R, const _cl_MI& x) +{ + var cl_heap_modint_ring_pow2* R = (cl_heap_modint_ring_pow2*)_R; + var cl_I zr = - x.rep; + return _cl_MI(R, ldb(zr,cl_byte(R->m1,0))); +} + +static const _cl_MI pow2_one (cl_heap_modint_ring* _R) +{ + var cl_heap_modint_ring_pow2* R = (cl_heap_modint_ring_pow2*)_R; + return _cl_MI(R, R->m1==0 ? 0 : 1); +} + +static const _cl_MI pow2_mul (cl_heap_modint_ring* _R, const _cl_MI& x, const _cl_MI& y) +{ + var cl_heap_modint_ring_pow2* R = (cl_heap_modint_ring_pow2*)_R; + var cl_I zr = x.rep * y.rep; + return _cl_MI(R, ldb(zr,cl_byte(R->m1,0))); +} + +static const _cl_MI pow2_square (cl_heap_modint_ring* _R, const _cl_MI& x) +{ + var cl_heap_modint_ring_pow2* R = (cl_heap_modint_ring_pow2*)_R; + var cl_I zr = square(x.rep); + return _cl_MI(R, ldb(zr,cl_byte(R->m1,0))); +} + +// Timing comparison with std_recip, on a i486 33 MHz running Linux: +// timeMIpow2recip N inverts an (N*32)-bit number. +// N std_recip pow2_recip +// 10 0.0030 0.00017 +// 25 0.011 0.00068 +// 50 0.035 0.0024 +// 100 0.124 0.0090 +// 250 0.71 0.055 +// 500 2.76 0.193 +// 1000 11.0 0.61 +// 2500 68.7 2.2 +// 5000 283 5.0 +static const cl_MI_x pow2_recip (cl_heap_modint_ring* _R, const _cl_MI& x) +{ + var cl_heap_modint_ring_pow2* R = (cl_heap_modint_ring_pow2*)_R; + var const cl_I& xr = x.rep; + if (!oddp(xr)) { + if (R->m1 == 0) + return cl_MI(R, 0); + if (zerop(xr)) + cl_error_division_by_0(); + else + return cl_notify_composite(R,xr); + } else + return cl_MI(R, cl_recip2adic(R->m1,xr)); +} + +// Timing comparison with std_div, on a i486 33 MHz running Linux: +// timeMIpow2div N divides two (N*32)-bit numbers. +// N std_div pow2_div +// 10 0.0035 0.00017 +// 25 0.0136 0.00068 +// 50 0.043 0.0024 +// 100 0.151 0.0090 +// 250 0.85 0.054 +// 500 3.3 0.21 +// 1000 12.3 0.86 +static const cl_MI_x pow2_div (cl_heap_modint_ring* _R, const _cl_MI& x, const _cl_MI& y) +{ + var cl_heap_modint_ring_pow2* R = (cl_heap_modint_ring_pow2*)_R; + var const cl_I& yr = y.rep; + if (!oddp(yr)) { + if (R->m1 == 0) + return cl_MI(R, 0); + if (zerop(yr)) + cl_error_division_by_0(); + else + return cl_notify_composite(R,yr); + } else + return cl_MI(R, cl_div2adic(R->m1,x.rep,yr)); +} + +static cl_modint_addops pow2_addops = { + std_zero, + std_zerop, + pow2_plus, + pow2_minus, + pow2_uminus +}; +static cl_modint_mulops pow2_mulops = { + pow2_one, + pow2_canonhom, + pow2_mul, + pow2_square, + std_expt_pos, + pow2_recip, + pow2_div, + std_expt, + pow2_reduce_modulo, + std_retract +}; + +// Constructor. +inline cl_heap_modint_ring_pow2::cl_heap_modint_ring_pow2 (const cl_I& m, uintL _m1) + : cl_heap_modint_ring (m, &std_setops, &pow2_addops, &pow2_mulops), m1 (_m1) {} diff --git a/src/modinteger/cl_MI_pow2m1.h b/src/modinteger/cl_MI_pow2m1.h new file mode 100644 index 0000000..6c7f9d0 --- /dev/null +++ b/src/modinteger/cl_MI_pow2m1.h @@ -0,0 +1,85 @@ +// m > 0, m = 2^m1 - 1 (m1 > 1) + +class cl_heap_modint_ring_pow2m1 : public cl_heap_modint_ring { + SUBCLASS_cl_heap_modint_ring() +public: + // Constructor. + cl_heap_modint_ring_pow2m1 (const cl_I& m, uintL m1); // m = 2^m1 - 1 + // Virtual destructor. + ~cl_heap_modint_ring_pow2m1 () {} + // Additional information. + uintL m1; +}; + +static +#if !(defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ <= 90)) // workaround g++-2.7.2 and egcs-1.0.2-prerelease bug +inline +#endif +const cl_I pow2m1_reduce_modulo (cl_heap_modint_ring* _R, const cl_I& x) +{ + var cl_heap_modint_ring_pow2m1* R = (cl_heap_modint_ring_pow2m1*)_R; + // Method: + // If x>=0, split x into pieces of m1 bits and sum them up. + // x = x0 + 2^m1*x1 + 2^(2*m1)*x2 + ... ==> + // mod(x,m) = mod(x0+x1+x2+...,m). + // If x<0, apply this to -1-x, and use mod(x,m) = m-1-mod(-1-x,m). + { Mutable(cl_I,x); + var cl_boolean sign = minusp(x); + if (sign) { x = lognot(x); } + var const uintL m1 = R->m1; + if (x >= R->modulus) { + x = plus1(x); // avoid staying at x = m + do { + var uintL xlen = integer_length(x); + var cl_I y = ldb(x,cl_byte(m1,0)); + for (var uintL i = m1; i < xlen; i += m1) + y = y + ldb(x,cl_byte(m1,i)); + x = y; + } while (x > R->modulus); + x = minus1(x); + } + // Now 0 <= x < m. + if (sign) { x = R->modulus - 1 - x; } + return x; +}} + +static const _cl_MI pow2m1_canonhom (cl_heap_modint_ring* R, const cl_I& x) +{ + return _cl_MI(R, pow2m1_reduce_modulo(R,x)); +} + +static const _cl_MI pow2m1_mul (cl_heap_modint_ring* _R, const _cl_MI& x, const _cl_MI& y) +{ + var cl_heap_modint_ring_pow2m1* R = (cl_heap_modint_ring_pow2m1*)_R; + var const uintL m1 = R->m1; + var cl_I zr = x.rep * y.rep; + zr = ldb(zr,cl_byte(m1,m1)) + ldb(zr,cl_byte(m1,0)); + return _cl_MI(R, zr >= R->modulus ? zr - R->modulus : zr); +} + +static const _cl_MI pow2m1_square (cl_heap_modint_ring* _R, const _cl_MI& x) +{ + var cl_heap_modint_ring_pow2m1* R = (cl_heap_modint_ring_pow2m1*)_R; + var const uintL m1 = R->m1; + var cl_I zr = square(x.rep); + zr = ldb(zr,cl_byte(m1,m1)) + ldb(zr,cl_byte(m1,0)); + return _cl_MI(R, zr >= R->modulus ? zr - R->modulus : zr); +} + +#define pow2m1_addops std_addops +static cl_modint_mulops pow2m1_mulops = { + std_one, + pow2m1_canonhom, + pow2m1_mul, + pow2m1_square, + std_expt_pos, + std_recip, + std_div, + std_expt, + pow2m1_reduce_modulo, + std_retract +}; + +// Constructor. +inline cl_heap_modint_ring_pow2m1::cl_heap_modint_ring_pow2m1 (const cl_I& m, uintL _m1) + : cl_heap_modint_ring (m, &std_setops, &pow2m1_addops, &pow2m1_mulops), m1 (_m1) {} diff --git a/src/modinteger/cl_MI_pow2p1.h b/src/modinteger/cl_MI_pow2p1.h new file mode 100644 index 0000000..2b71d30 --- /dev/null +++ b/src/modinteger/cl_MI_pow2p1.h @@ -0,0 +1,96 @@ +// m > 0, m = 2^m1 + 1 (m1 > 1) + +class cl_heap_modint_ring_pow2p1 : public cl_heap_modint_ring { + SUBCLASS_cl_heap_modint_ring() +public: + // Constructor. + cl_heap_modint_ring_pow2p1 (const cl_I& m, uintL m1); // m = 2^m1 + 1 + // Virtual destructor. + ~cl_heap_modint_ring_pow2p1 () {} + // Additional information. + uintL m1; +}; + +static +#if !(defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ <= 90)) // workaround g++-2.7.2 and egcs-1.0.2-prerelease bug +inline +#endif +const cl_I pow2p1_reduce_modulo (cl_heap_modint_ring* _R, const cl_I& x) +{ + var cl_heap_modint_ring_pow2p1* R = (cl_heap_modint_ring_pow2p1*)_R; + // Method: + // If x>=0, split x into pieces of m1 bits and sum them up. + // x = x0 + 2^m1*x1 + 2^(2*m1)*x2 + ... ==> + // mod(x,m) = mod(x0-x1+x2-+...,m). + // If x<0, apply this to -1-x, and use mod(x,m) = m-1-mod(-1-x,m). + { Mutable(cl_I,x); + var bool sign = minusp(x); + if (sign) { x = lognot(x); } + var const uintL m1 = R->m1; + while (x >= R->modulus) { + var uintL xlen = integer_length(x); + var cl_I y = ldb(x,cl_byte(m1,0)); + for (var uintL i = m1; ; ) { + y = y - ldb(x,cl_byte(m1,i)); + i += m1; + if (i >= xlen) + break; + y = y + ldb(x,cl_byte(m1,i)); + i += m1; + if (i >= xlen) + break; + } + if (minusp(y)) + { sign = !sign; x = lognot(y); } + else + x = y; + } + // Now 0 <= x < m. + if (sign) { x = R->modulus - 1 - x; } + return x; +}} + +static const _cl_MI pow2p1_canonhom (cl_heap_modint_ring* R, const cl_I& x) +{ + return _cl_MI(R, pow2p1_reduce_modulo(R,x)); +} + +static const _cl_MI pow2p1_mul (cl_heap_modint_ring* _R, const _cl_MI& x, const _cl_MI& y) +{ + var cl_heap_modint_ring_pow2p1* R = (cl_heap_modint_ring_pow2p1*)_R; + var const uintL m1 = R->m1; + var cl_I zr = x.rep * y.rep; + // Now 0 <= zr <= 2^(2*m1). + zr = ldb(zr,cl_byte(1,2*m1)) - ldb(zr,cl_byte(m1,m1)) + ldb(zr,cl_byte(m1,0)); + // Now -(2^m1-1) <= zr <= 2^m1. + return _cl_MI(R, minusp(zr) ? zr + R->modulus : zr); +} + +static const _cl_MI pow2p1_square (cl_heap_modint_ring* _R, const _cl_MI& x) +{ + var cl_heap_modint_ring_pow2p1* R = (cl_heap_modint_ring_pow2p1*)_R; + var const uintL m1 = R->m1; + var cl_I zr = square(x.rep); + // Now 0 <= zr <= 2^(2*m1). + zr = ldb(zr,cl_byte(1,2*m1)) - ldb(zr,cl_byte(m1,m1)) + ldb(zr,cl_byte(m1,0)); + // Now -(2^m1-1) <= zr <= 2^m1. + return _cl_MI(R, minusp(zr) ? zr + R->modulus : zr); +} + +#define pow2p1_addops std_addops +static cl_modint_mulops pow2p1_mulops = { + std_one, + pow2p1_canonhom, + pow2p1_mul, + pow2p1_square, + std_expt_pos, + std_recip, + std_div, + std_expt, + pow2p1_reduce_modulo, + std_retract +}; + +// Constructor. +inline cl_heap_modint_ring_pow2p1::cl_heap_modint_ring_pow2p1 (const cl_I& m, uintL _m1) + : cl_heap_modint_ring (m, &std_setops, &pow2p1_addops, &pow2p1_mulops), m1 (_m1) {} diff --git a/src/modinteger/cl_MI_rshift.cc b/src/modinteger/cl_MI_rshift.cc new file mode 100644 index 0000000..09400fb --- /dev/null +++ b/src/modinteger/cl_MI_rshift.cc @@ -0,0 +1,42 @@ +// operator>> on cl_MI. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_modinteger.h" + + +// Implementation. + +#include "cl_integer.h" +#include "cl_N.h" +#include "cl_MI.h" + +const cl_MI operator>> (const cl_MI& x, sintL y) // assume 0 <= y < 2^31 +{ + if (y == 0) + return x; + var const cl_modint_ring& R = x.ring(); + if (!oddp(R->modulus)) { + if (R->modulus == 2) + cl_error_division_by_0(); + else + return (cl_MI_x)cl_notify_composite(R,2); + } + if (y == 1) // frequent case + return cl_MI(R, (evenp(x.rep) ? x.rep : x.rep + R->modulus) >> 1); + // Method: + // Algorithm 1: add a multiple of m to x.rep so that it becomes + // divisible by 2^y (2-adic division), then shift right. + // asymptotical cost: O(y * log m). + // Algorithm 2: x * expt(2 mod m,-y) using modular integer operations. + // asymptotical cost: O(log y * (log m)^2). + // Use algorithm 1 for small y, algorithm 2 for large y. +#if 0 + if (y <= 2*R->bits) + cl_abort(); // not yet implemented + else +#endif + return R->div(x, expt_pos(R->canonhom(2), (cl_I)(long)y)); +} diff --git a/src/modinteger/cl_MI_std.h b/src/modinteger/cl_MI_std.h new file mode 100644 index 0000000..4cd56e0 --- /dev/null +++ b/src/modinteger/cl_MI_std.h @@ -0,0 +1,350 @@ +// m > 1, standard representation, no tricks + +static void std_fprint (cl_heap_modint_ring* R, cl_ostream stream, const _cl_MI &x) +{ + fprint(stream,R->_retract(x)); + fprint(stream," mod "); + fprint(stream,R->modulus); +} + +static const cl_I std_reduce_modulo (cl_heap_modint_ring* R, const cl_I& x) +{ + return mod(x,R->modulus); +} + +static const _cl_MI std_canonhom (cl_heap_modint_ring* R, const cl_I& x) +{ + return _cl_MI(R, mod(x,R->modulus)); +} + +static const cl_I std_retract (cl_heap_modint_ring* R, const _cl_MI& x) +{ + unused R; + return x.rep; +} + +static const _cl_MI std_random (cl_heap_modint_ring* R, cl_random_state& randomstate) +{ + return _cl_MI(R, random_I(randomstate,R->modulus)); +} + +static const _cl_MI std_zero (cl_heap_modint_ring* R) +{ + return _cl_MI(R, 0); +} + +static cl_boolean std_zerop (cl_heap_modint_ring* R, const _cl_MI& x) +{ + unused R; + return zerop(x.rep); +} + +static const _cl_MI std_plus (cl_heap_modint_ring* R, const _cl_MI& x, const _cl_MI& y) +{ + var cl_I zr = x.rep + y.rep; + return _cl_MI(R, (zr >= R->modulus ? zr - R->modulus : zr)); +} + +static const _cl_MI std_minus (cl_heap_modint_ring* R, const _cl_MI& x, const _cl_MI& y) +{ + var cl_I zr = x.rep - y.rep; + return _cl_MI(R, (minusp(zr) ? zr + R->modulus : zr)); +} + +static const _cl_MI std_uminus (cl_heap_modint_ring* R, const _cl_MI& x) +{ + return _cl_MI(R, (zerop(x.rep) ? (cl_I)0 : R->modulus - x.rep)); +} + +static const _cl_MI std_one (cl_heap_modint_ring* R) +{ + return _cl_MI(R, 1); +} + +static const _cl_MI std_mul (cl_heap_modint_ring* R, const _cl_MI& x, const _cl_MI& y) +{ + return _cl_MI(R, mod(x.rep * y.rep, R->modulus)); +} + +static const _cl_MI std_square (cl_heap_modint_ring* R, const _cl_MI& x) +{ + return _cl_MI(R, mod(square(x.rep), R->modulus)); +} + +static const cl_MI_x std_recip (cl_heap_modint_ring* R, const _cl_MI& x) +{ + var const cl_I& xr = x.rep; + var cl_I u, v; + var cl_I g = xgcd(xr,R->modulus,&u,&v); + // g = gcd(x,m) = x*u+m*v + if (eq(g,1)) + return cl_MI(R, (minusp(u) ? u + R->modulus : u)); + if (zerop(xr)) + cl_error_division_by_0(); + return cl_notify_composite(R,xr); +} + +static const cl_MI_x std_div (cl_heap_modint_ring* R, const _cl_MI& x, const _cl_MI& y) +{ + var const cl_I& yr = y.rep; + var cl_I u, v; + var cl_I g = xgcd(yr,R->modulus,&u,&v); + // g = gcd(y,m) = y*u+m*v + if (eq(g,1)) + return cl_MI(R, mod(x.rep * (minusp(u) ? u + R->modulus : u), R->modulus)); + if (zerop(yr)) + cl_error_division_by_0(); + return cl_notify_composite(R,yr); +} + +static uint8 const ord2_table[256] = // maps i -> ord2(i) for i>0 +{ + 63, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 +}; + +static uint8 const odd_table[256] = // maps i -> i/2^ord2(i) for i>0 +{ + 0, 1, 1, 3, 1, 5, 3, 7, 1, 9, 5, 11, 3, 13, 7, 15, + 1, 17, 9, 19, 5, 21, 11, 23, 3, 25, 13, 27, 7, 29, 15, 31, + 1, 33, 17, 35, 9, 37, 19, 39, 5, 41, 21, 43, 11, 45, 23, 47, + 3, 49, 25, 51, 13, 53, 27, 55, 7, 57, 29, 59, 15, 61, 31, 63, + 1, 65, 33, 67, 17, 69, 35, 71, 9, 73, 37, 75, 19, 77, 39, 79, + 5, 81, 41, 83, 21, 85, 43, 87, 11, 89, 45, 91, 23, 93, 47, 95, + 3, 97, 49, 99, 25, 101, 51, 103, 13, 105, 53, 107, 27, 109, 55, 111, + 7, 113, 57, 115, 29, 117, 59, 119, 15, 121, 61, 123, 31, 125, 63, 127, + 1, 129, 65, 131, 33, 133, 67, 135, 17, 137, 69, 139, 35, 141, 71, 143, + 9, 145, 73, 147, 37, 149, 75, 151, 19, 153, 77, 155, 39, 157, 79, 159, + 5, 161, 81, 163, 41, 165, 83, 167, 21, 169, 85, 171, 43, 173, 87, 175, + 11, 177, 89, 179, 45, 181, 91, 183, 23, 185, 93, 187, 47, 189, 95, 191, + 3, 193, 97, 195, 49, 197, 99, 199, 25, 201, 101, 203, 51, 205, 103, 207, + 13, 209, 105, 211, 53, 213, 107, 215, 27, 217, 109, 219, 55, 221, 111, 223, + 7, 225, 113, 227, 57, 229, 115, 231, 29, 233, 117, 235, 59, 237, 119, 239, + 15, 241, 121, 243, 61, 245, 123, 247, 31, 249, 125, 251, 63, 253, 127, 255 +}; + +static const _cl_MI std_expt_pos (cl_heap_modint_ring* R, const _cl_MI& x, const cl_I& y) +{ +#if 0 + // Methode: + // Right-Left Binary, [Cohen, Algorithm 1.2.1.] + // a:=x, b:=y. + // Solange b gerade, setze a:=a*a, b:=b/2. (Invariante: a^b = x^y.) + // c:=a. + // Solange b:=floor(b/2) >0 ist, + // setze a:=a*a, und falls b ungerade, setze c:=a*c. + // Liefere c. + var _cl_MI a = x; + var cl_I b = y; + while (!oddp(b)) { a = R->_square(a); b = b >> 1; } // a^b = x^y + var _cl_MI c = a; + until (eq(b,1)) { + b = b >> 1; + a = R->_square(a); + // a^b*c = x^y + if (oddp(b)) + c = R->_mul(a,c); + } + return c; +#else + // Methode: + // Left-Right base 2^k, [Cohen, Algorithm 1.2.4.] + // Good values of k, depending on the size nn of the exponent n: + // k = 1 for nn <= 8 + // k = 2 for nn <= 24 + // k = 3 for nn <= 69.8 + // ... k for nn <= k*(k+1)*2^(2k)/(2^(k+1)-k-2) + var cl_I n = y; + var uintL nn = integer_length(n); + // n has nn bits. + if (nn <= 8) { + // k = 1, normal Left-Right Binary algorithm. + var uintL _n = FN_to_UL(n); + var _cl_MI a = x; + for (var int i = nn-2; i >= 0; i--) { + a = R->_square(a); + if (_n & bit(i)) + a = R->_mul(a,x); + } + return cl_MI(R,a); + } else { + // General Left-Right base 2^k algorithm. + CL_ALLOCA_STACK; + var uintL k; + if (nn <= 24) k = 2; + else if (nn <= 69) k = 3; + else if (nn <= 196) k = 4; + else if (nn <= 538) k = 5; + else if (nn <= 1433) k = 6; + else if (nn <= 3714) k = 7; + else if (nn <= 9399) k = 8; + else if (nn <= 23290) k = 9; + else if (nn <= 56651) k = 10; + else if (nn <= 135598) k = 11; + else if (nn <= 320034) k = 12; + else if (nn <= 746155) k = 13; + else if (nn <= 1721160) k = 14; + else if (nn <= 3933180) k = 15; + else /* if (nn <= 8914120) */ k = 16; + var uintL nnk = ceiling(nn,k); // number of base-2^k digits in n + var uint16* n_digits = cl_alloc_array(uint16,nnk); + // Split n into base-2^k digits. + { + var const uintD* n_LSDptr; + var const uintD* n_MSDptr; + I_to_NDS_nocopy(n, n_MSDptr=,,n_LSDptr=,cl_false,); + var const uintL k_mask = bit(k)-1; + var uintD carry = 0; + var unsigned int carrybits = 0; + for (var uintL i = 0; i < nnk; i++) { + if (carrybits >= k) { + n_digits[i] = carry & k_mask; + carry = carry >> k; + carrybits -= k; + } else { + var uintD next = + (n_LSDptr==n_MSDptr ? 0 : lsprefnext(n_LSDptr)); + n_digits[i] = (carry | (next << carrybits)) & k_mask; + carry = next >> (k-carrybits); + carrybits = intDsize - (k-carrybits); + } + } + } + // Compute maximum odd base-2^k digit. + var uintL maxodd = 1; + if (k <= 8) { + for (var uintL i = 0; i < nnk; i++) { + var uintL d = n_digits[i]; + if (d > 0) { + d = odd_table[d]; + if (d > maxodd) maxodd = d; + } + } + } else { + for (var uintL i = 0; i < nnk; i++) { + var uintL d = n_digits[i]; + if (d > 0) { + var uintL d2; ord2_32(d,d2=); + d = d>>d2; + if (d > maxodd) maxodd = d; + } + } + } + maxodd = (maxodd+1)/2; // number of odd powers we need + var _cl_MI* x_oddpow = cl_alloc_array(_cl_MI,maxodd); + var _cl_MI x2 = (maxodd > 1 ? R->_square(x) : R->_zero()); + { + init1(_cl_MI, x_oddpow[0]) (x); + for (var uintL i = 1; i < maxodd; i++) + init1(_cl_MI, x_oddpow[i]) (R->_mul(x_oddpow[i-1],x2)); + } + var _cl_MI a; + // Compute a = x^n_digits[nnk-1]. + { + var uintL d = n_digits[nnk-1]; + if (d == 0) cl_abort(); + var uintL d2; + if (k <= 8) + d2 = ord2_table[d]; + else + ord2_32(d,d2=); + d = d>>d2; // d := d/2^ord2(d) + d = floor(d,2); + a = x_oddpow[d]; // x^d + // Square d2 times. + if (d==0 && maxodd > 1 && d2>0) { + a = x2; d2--; + } + if (!(d2 < k)) cl_abort(); + for ( ; d2>0; d2--) + a = R->_square(a); + } + for (var sintL i = nnk-2; i >= 0; i--) { + // Compute a := a^(2^k) * x^n_digits[i]. + var uintL d = n_digits[i]; + var uintL d2; + if (d > 0) { + if (k <= 8) + d2 = ord2_table[d]; + else + ord2_32(d,d2=); + d = d>>d2; // d/2^ord2(d) + d = floor(d,2); + for (var sintL j = k-d2; j>0; j--) + a = R->_square(a); + a = R->_mul(a,x_oddpow[d]); + } else + d2 = k; + // Square d2 times. + if (!(d2 <= k)) cl_abort(); + for ( ; d2>0; d2--) + a = R->_square(a); + } + { + for (var uintL i = 0; i < maxodd; i++) + x_oddpow[i].~_cl_MI(); + } + return cl_MI(R,a); + } +#endif +} + +static const cl_MI_x std_expt (cl_heap_modint_ring* R, const _cl_MI& x, const cl_I& y) +{ + if (!minusp(y)) { + if (zerop(y)) + return R->one(); + else + return cl_MI(R,R->_expt_pos(x,y)); + } else + return R->_recip(R->_expt_pos(x,-y)); +} + +static cl_modint_setops std_setops = { + std_fprint, + modint_equal, + std_random +}; +static cl_modint_addops std_addops = { + std_zero, + std_zerop, + std_plus, + std_minus, + std_uminus +}; +static cl_modint_mulops std_mulops = { + std_one, + std_canonhom, + std_mul, + std_square, + std_expt_pos, + std_recip, + std_div, + std_expt, + std_reduce_modulo, + std_retract +}; + +class cl_heap_modint_ring_std : public cl_heap_modint_ring { + SUBCLASS_cl_heap_modint_ring() +public: + // Constructor. + cl_heap_modint_ring_std (const cl_I& m) + : cl_heap_modint_ring (m, &std_setops, &std_addops, &std_mulops) {} + // Virtual destructor. + ~cl_heap_modint_ring_std () {} +}; diff --git a/src/modpolynomial/Makeflags b/src/modpolynomial/Makeflags new file mode 100644 index 0000000..4b0afee --- /dev/null +++ b/src/modpolynomial/Makeflags @@ -0,0 +1,3 @@ +# This file contains additional flags for the main Makefile. + +SUBDIR_INCLUDES = diff --git a/src/numtheory/Makeflags b/src/numtheory/Makeflags new file mode 100644 index 0000000..04eee3b --- /dev/null +++ b/src/numtheory/Makeflags @@ -0,0 +1,3 @@ +# This file contains additional flags for the main Makefile. + +SUBDIR_INCLUDES = -I$(srcdir)/integer -I$(srcdir)/base/digitseq -I$(srcdir)/base/digit -Ibase -I$(srcdir)/base $(GMP_INCLUDES) diff --git a/src/numtheory/cl_IF.h b/src/numtheory/cl_IF.h new file mode 100644 index 0000000..2d632db --- /dev/null +++ b/src/numtheory/cl_IF.h @@ -0,0 +1,52 @@ +// Integer factorization and primality testing. + +#ifndef _CL_IF_H +#define _CL_IF_H + +#include "cl_number.h" +#include "cl_integer.h" + +// Table of primes > 2, < 2^16 +const uint32 cl_small_prime_table_limit = 65536; +const int cl_small_prime_table_size = 6541; +extern uint16 cl_small_prime_table[cl_small_prime_table_size]; + +// Given 0 < d <= cl_small_prime_table_limit, return the smallest index i +// such that cl_small_prime_table[i] >= d. (Or i = cl_small_prime_table_size +// if none exists.) +inline uintL cl_small_prime_table_search (uint32 d) +{ + var uintL i1 = 0; + var uintL i2 = cl_small_prime_table_size; + if (cl_small_prime_table[i1] >= d) + return i1; + loop { + // Here i1 < i2 and + // cl_small_prime_table[i1] < d <= cl_small_prime_table[i2]. + var uintL i3 = floor(i1+i2,2); + if (i3 == i1) // (i2-i1 == 1) ? + return i2; + if (cl_small_prime_table[i3] >= d) + i2 = i3; + else + i1 = i3; + } +} + +// Trial division. +// Divides n > 0 by the primes in the range d1 <= d <= d2 +// (0 < d1 <= d2 <= min(isqrt(n),cl_small_prime_table_limit)) +// and returns the divisor d if found, or 0 if no divisor found. +extern uint32 cl_trialdivision (uint32 n, uint32 d1, uint32 d2); +extern uint32 cl_trialdivision (uint32 nhi, uint32 nlo, uint32 d1, uint32 d2); +extern uint32 cl_trialdivision (const cl_I& n, uint32 d1, uint32 d2); + +// Miller-Rabin compositeness test. +// Performs count times the Miller-Rabin test on n > 1 odd. +// Returns true if n looks like a prime (with error probability < 4^-count). +// Returns false if n is definitely composite, and then sets factor = some +// nontrivial factor or 0. +extern cl_boolean cl_miller_rabin_test (const cl_I& n, int count, cl_I* factor); + + +#endif /* _CL_IF_H */ diff --git a/src/numtheory/cl_IF_millerrabin.cc b/src/numtheory/cl_IF_millerrabin.cc new file mode 100644 index 0000000..a049eca --- /dev/null +++ b/src/numtheory/cl_IF_millerrabin.cc @@ -0,0 +1,63 @@ +// cl_miller_rabin_test(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_IF.h" + + +// Implementation. + +#include "cl_modinteger.h" + +cl_boolean cl_miller_rabin_test (const cl_I& n, int count, cl_I* factor) +{ + // [Cohen], section 8.2, algorithm 8.2.2. + var cl_modint_ring R = cl_find_modint_ring(n); // Z/nZ + var cl_I m = n-1; + var uintL e = ord2(m); + m = m>>e; + // n-1 = 2^e*m + var cl_MI one = R->one(); + var cl_MI minusone = R->uminus(one); + for (int i = 0; i < count; i++) { + // Choosing aa small makes the expt_pos faster. + var cl_I aa = (i == 0 + ? (cl_I) 2 + : i <= cl_small_prime_table_size + ? (cl_I) (unsigned int) cl_small_prime_table[i-1] // small prime + : 2+random_I(n-2)); // or random >=2, = n) + break; + // Now 1 < aa < n. + var cl_MI a = R->canonhom(aa); + var cl_MI b = R->expt_pos(a,m); // b = a^m + if (b == one) + goto passed; + for (uintL s = e; s > 0; s--) { + if (b == minusone) + goto passed; + var cl_MI new_b = R->square(b); + if (new_b == one) { + // (b-1)*(b+1) == 0 mod n, hence n not prime. + if (factor) + *factor = gcd(R->retract(b)-1,n); + return cl_false; + } + b = new_b; + } + // b = a^(2^e*m) = a^(n-1), but b != -1 mod n, hence n not prime. + if (factor) { + var cl_I g = gcd(aa,n); + if (g > 1) + *factor = g; + else + *factor = 0; + } + return cl_false; + passed: + ; + } + return cl_true; +} diff --git a/src/numtheory/cl_IF_smallprimes.cc b/src/numtheory/cl_IF_smallprimes.cc new file mode 100644 index 0000000..a07014a --- /dev/null +++ b/src/numtheory/cl_IF_smallprimes.cc @@ -0,0 +1,668 @@ +// cl_small_prime_table. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_IF.h" + + +// Implementation. + +uint16 cl_small_prime_table[cl_small_prime_table_size] = { + 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, + 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, + 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, + 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, + 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, + 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, + 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, + 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, + 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, + 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, + 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, + 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, + 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, + 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, + 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, + 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, + 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, + 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, + 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, + 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, + 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297, + 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, + 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, + 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, + 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, + 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, + 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, + 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, + 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, + 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, + 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, + 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, + 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, + 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, + 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, + 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, + 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, 2539, + 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621, + 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, + 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, + 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819, 2833, + 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, 2909, + 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, + 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, + 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, + 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, + 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, + 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, + 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, + 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, + 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, 3659, + 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733, + 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, + 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, + 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 4001, + 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, + 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, + 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, 4241, + 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, 4327, + 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, + 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, + 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591, + 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, 4663, + 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, + 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, + 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, 4943, + 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, + 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, + 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, + 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, 5281, + 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, + 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, 5449, + 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 5527, + 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, + 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, + 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, 5801, + 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, 5861, + 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, + 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, + 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, 6143, + 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, + 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, + 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367, 6373, + 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, 6481, + 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, + 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673, 6679, + 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761, 6763, + 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, + 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, + 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, 7001, + 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, 7109, + 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, + 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297, 7307, + 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411, 7417, + 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, + 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, + 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643, 7649, + 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, 7727, + 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, + 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, 7927, + 7933, 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017, 8039, + 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117, + 8123, 8147, 8161, 8167, 8171, 8179, 8191, 8209, 8219, 8221, + 8231, 8233, 8237, 8243, 8263, 8269, 8273, 8287, 8291, 8293, + 8297, 8311, 8317, 8329, 8353, 8363, 8369, 8377, 8387, 8389, + 8419, 8423, 8429, 8431, 8443, 8447, 8461, 8467, 8501, 8513, + 8521, 8527, 8537, 8539, 8543, 8563, 8573, 8581, 8597, 8599, + 8609, 8623, 8627, 8629, 8641, 8647, 8663, 8669, 8677, 8681, + 8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737, 8741, 8747, + 8753, 8761, 8779, 8783, 8803, 8807, 8819, 8821, 8831, 8837, + 8839, 8849, 8861, 8863, 8867, 8887, 8893, 8923, 8929, 8933, + 8941, 8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011, 9013, + 9029, 9041, 9043, 9049, 9059, 9067, 9091, 9103, 9109, 9127, + 9133, 9137, 9151, 9157, 9161, 9173, 9181, 9187, 9199, 9203, + 9209, 9221, 9227, 9239, 9241, 9257, 9277, 9281, 9283, 9293, + 9311, 9319, 9323, 9337, 9341, 9343, 9349, 9371, 9377, 9391, + 9397, 9403, 9413, 9419, 9421, 9431, 9433, 9437, 9439, 9461, + 9463, 9467, 9473, 9479, 9491, 9497, 9511, 9521, 9533, 9539, + 9547, 9551, 9587, 9601, 9613, 9619, 9623, 9629, 9631, 9643, + 9649, 9661, 9677, 9679, 9689, 9697, 9719, 9721, 9733, 9739, + 9743, 9749, 9767, 9769, 9781, 9787, 9791, 9803, 9811, 9817, + 9829, 9833, 9839, 9851, 9857, 9859, 9871, 9883, 9887, 9901, + 9907, 9923, 9929, 9931, 9941, 9949, 9967, 9973, 10007, 10009, + 10037, 10039, 10061, 10067, 10069, 10079, 10091, 10093, 10099, 10103, + 10111, 10133, 10139, 10141, 10151, 10159, 10163, 10169, 10177, 10181, + 10193, 10211, 10223, 10243, 10247, 10253, 10259, 10267, 10271, 10273, + 10289, 10301, 10303, 10313, 10321, 10331, 10333, 10337, 10343, 10357, + 10369, 10391, 10399, 10427, 10429, 10433, 10453, 10457, 10459, 10463, + 10477, 10487, 10499, 10501, 10513, 10529, 10531, 10559, 10567, 10589, + 10597, 10601, 10607, 10613, 10627, 10631, 10639, 10651, 10657, 10663, + 10667, 10687, 10691, 10709, 10711, 10723, 10729, 10733, 10739, 10753, + 10771, 10781, 10789, 10799, 10831, 10837, 10847, 10853, 10859, 10861, + 10867, 10883, 10889, 10891, 10903, 10909, 10937, 10939, 10949, 10957, + 10973, 10979, 10987, 10993, 11003, 11027, 11047, 11057, 11059, 11069, + 11071, 11083, 11087, 11093, 11113, 11117, 11119, 11131, 11149, 11159, + 11161, 11171, 11173, 11177, 11197, 11213, 11239, 11243, 11251, 11257, + 11261, 11273, 11279, 11287, 11299, 11311, 11317, 11321, 11329, 11351, + 11353, 11369, 11383, 11393, 11399, 11411, 11423, 11437, 11443, 11447, + 11467, 11471, 11483, 11489, 11491, 11497, 11503, 11519, 11527, 11549, + 11551, 11579, 11587, 11593, 11597, 11617, 11621, 11633, 11657, 11677, + 11681, 11689, 11699, 11701, 11717, 11719, 11731, 11743, 11777, 11779, + 11783, 11789, 11801, 11807, 11813, 11821, 11827, 11831, 11833, 11839, + 11863, 11867, 11887, 11897, 11903, 11909, 11923, 11927, 11933, 11939, + 11941, 11953, 11959, 11969, 11971, 11981, 11987, 12007, 12011, 12037, + 12041, 12043, 12049, 12071, 12073, 12097, 12101, 12107, 12109, 12113, + 12119, 12143, 12149, 12157, 12161, 12163, 12197, 12203, 12211, 12227, + 12239, 12241, 12251, 12253, 12263, 12269, 12277, 12281, 12289, 12301, + 12323, 12329, 12343, 12347, 12373, 12377, 12379, 12391, 12401, 12409, + 12413, 12421, 12433, 12437, 12451, 12457, 12473, 12479, 12487, 12491, + 12497, 12503, 12511, 12517, 12527, 12539, 12541, 12547, 12553, 12569, + 12577, 12583, 12589, 12601, 12611, 12613, 12619, 12637, 12641, 12647, + 12653, 12659, 12671, 12689, 12697, 12703, 12713, 12721, 12739, 12743, + 12757, 12763, 12781, 12791, 12799, 12809, 12821, 12823, 12829, 12841, + 12853, 12889, 12893, 12899, 12907, 12911, 12917, 12919, 12923, 12941, + 12953, 12959, 12967, 12973, 12979, 12983, 13001, 13003, 13007, 13009, + 13033, 13037, 13043, 13049, 13063, 13093, 13099, 13103, 13109, 13121, + 13127, 13147, 13151, 13159, 13163, 13171, 13177, 13183, 13187, 13217, + 13219, 13229, 13241, 13249, 13259, 13267, 13291, 13297, 13309, 13313, + 13327, 13331, 13337, 13339, 13367, 13381, 13397, 13399, 13411, 13417, + 13421, 13441, 13451, 13457, 13463, 13469, 13477, 13487, 13499, 13513, + 13523, 13537, 13553, 13567, 13577, 13591, 13597, 13613, 13619, 13627, + 13633, 13649, 13669, 13679, 13681, 13687, 13691, 13693, 13697, 13709, + 13711, 13721, 13723, 13729, 13751, 13757, 13759, 13763, 13781, 13789, + 13799, 13807, 13829, 13831, 13841, 13859, 13873, 13877, 13879, 13883, + 13901, 13903, 13907, 13913, 13921, 13931, 13933, 13963, 13967, 13997, + 13999, 14009, 14011, 14029, 14033, 14051, 14057, 14071, 14081, 14083, + 14087, 14107, 14143, 14149, 14153, 14159, 14173, 14177, 14197, 14207, + 14221, 14243, 14249, 14251, 14281, 14293, 14303, 14321, 14323, 14327, + 14341, 14347, 14369, 14387, 14389, 14401, 14407, 14411, 14419, 14423, + 14431, 14437, 14447, 14449, 14461, 14479, 14489, 14503, 14519, 14533, + 14537, 14543, 14549, 14551, 14557, 14561, 14563, 14591, 14593, 14621, + 14627, 14629, 14633, 14639, 14653, 14657, 14669, 14683, 14699, 14713, + 14717, 14723, 14731, 14737, 14741, 14747, 14753, 14759, 14767, 14771, + 14779, 14783, 14797, 14813, 14821, 14827, 14831, 14843, 14851, 14867, + 14869, 14879, 14887, 14891, 14897, 14923, 14929, 14939, 14947, 14951, + 14957, 14969, 14983, 15013, 15017, 15031, 15053, 15061, 15073, 15077, + 15083, 15091, 15101, 15107, 15121, 15131, 15137, 15139, 15149, 15161, + 15173, 15187, 15193, 15199, 15217, 15227, 15233, 15241, 15259, 15263, + 15269, 15271, 15277, 15287, 15289, 15299, 15307, 15313, 15319, 15329, + 15331, 15349, 15359, 15361, 15373, 15377, 15383, 15391, 15401, 15413, + 15427, 15439, 15443, 15451, 15461, 15467, 15473, 15493, 15497, 15511, + 15527, 15541, 15551, 15559, 15569, 15581, 15583, 15601, 15607, 15619, + 15629, 15641, 15643, 15647, 15649, 15661, 15667, 15671, 15679, 15683, + 15727, 15731, 15733, 15737, 15739, 15749, 15761, 15767, 15773, 15787, + 15791, 15797, 15803, 15809, 15817, 15823, 15859, 15877, 15881, 15887, + 15889, 15901, 15907, 15913, 15919, 15923, 15937, 15959, 15971, 15973, + 15991, 16001, 16007, 16033, 16057, 16061, 16063, 16067, 16069, 16073, + 16087, 16091, 16097, 16103, 16111, 16127, 16139, 16141, 16183, 16187, + 16189, 16193, 16217, 16223, 16229, 16231, 16249, 16253, 16267, 16273, + 16301, 16319, 16333, 16339, 16349, 16361, 16363, 16369, 16381, 16411, + 16417, 16421, 16427, 16433, 16447, 16451, 16453, 16477, 16481, 16487, + 16493, 16519, 16529, 16547, 16553, 16561, 16567, 16573, 16603, 16607, + 16619, 16631, 16633, 16649, 16651, 16657, 16661, 16673, 16691, 16693, + 16699, 16703, 16729, 16741, 16747, 16759, 16763, 16787, 16811, 16823, + 16829, 16831, 16843, 16871, 16879, 16883, 16889, 16901, 16903, 16921, + 16927, 16931, 16937, 16943, 16963, 16979, 16981, 16987, 16993, 17011, + 17021, 17027, 17029, 17033, 17041, 17047, 17053, 17077, 17093, 17099, + 17107, 17117, 17123, 17137, 17159, 17167, 17183, 17189, 17191, 17203, + 17207, 17209, 17231, 17239, 17257, 17291, 17293, 17299, 17317, 17321, + 17327, 17333, 17341, 17351, 17359, 17377, 17383, 17387, 17389, 17393, + 17401, 17417, 17419, 17431, 17443, 17449, 17467, 17471, 17477, 17483, + 17489, 17491, 17497, 17509, 17519, 17539, 17551, 17569, 17573, 17579, + 17581, 17597, 17599, 17609, 17623, 17627, 17657, 17659, 17669, 17681, + 17683, 17707, 17713, 17729, 17737, 17747, 17749, 17761, 17783, 17789, + 17791, 17807, 17827, 17837, 17839, 17851, 17863, 17881, 17891, 17903, + 17909, 17911, 17921, 17923, 17929, 17939, 17957, 17959, 17971, 17977, + 17981, 17987, 17989, 18013, 18041, 18043, 18047, 18049, 18059, 18061, + 18077, 18089, 18097, 18119, 18121, 18127, 18131, 18133, 18143, 18149, + 18169, 18181, 18191, 18199, 18211, 18217, 18223, 18229, 18233, 18251, + 18253, 18257, 18269, 18287, 18289, 18301, 18307, 18311, 18313, 18329, + 18341, 18353, 18367, 18371, 18379, 18397, 18401, 18413, 18427, 18433, + 18439, 18443, 18451, 18457, 18461, 18481, 18493, 18503, 18517, 18521, + 18523, 18539, 18541, 18553, 18583, 18587, 18593, 18617, 18637, 18661, + 18671, 18679, 18691, 18701, 18713, 18719, 18731, 18743, 18749, 18757, + 18773, 18787, 18793, 18797, 18803, 18839, 18859, 18869, 18899, 18911, + 18913, 18917, 18919, 18947, 18959, 18973, 18979, 19001, 19009, 19013, + 19031, 19037, 19051, 19069, 19073, 19079, 19081, 19087, 19121, 19139, + 19141, 19157, 19163, 19181, 19183, 19207, 19211, 19213, 19219, 19231, + 19237, 19249, 19259, 19267, 19273, 19289, 19301, 19309, 19319, 19333, + 19373, 19379, 19381, 19387, 19391, 19403, 19417, 19421, 19423, 19427, + 19429, 19433, 19441, 19447, 19457, 19463, 19469, 19471, 19477, 19483, + 19489, 19501, 19507, 19531, 19541, 19543, 19553, 19559, 19571, 19577, + 19583, 19597, 19603, 19609, 19661, 19681, 19687, 19697, 19699, 19709, + 19717, 19727, 19739, 19751, 19753, 19759, 19763, 19777, 19793, 19801, + 19813, 19819, 19841, 19843, 19853, 19861, 19867, 19889, 19891, 19913, + 19919, 19927, 19937, 19949, 19961, 19963, 19973, 19979, 19991, 19993, + 19997, 20011, 20021, 20023, 20029, 20047, 20051, 20063, 20071, 20089, + 20101, 20107, 20113, 20117, 20123, 20129, 20143, 20147, 20149, 20161, + 20173, 20177, 20183, 20201, 20219, 20231, 20233, 20249, 20261, 20269, + 20287, 20297, 20323, 20327, 20333, 20341, 20347, 20353, 20357, 20359, + 20369, 20389, 20393, 20399, 20407, 20411, 20431, 20441, 20443, 20477, + 20479, 20483, 20507, 20509, 20521, 20533, 20543, 20549, 20551, 20563, + 20593, 20599, 20611, 20627, 20639, 20641, 20663, 20681, 20693, 20707, + 20717, 20719, 20731, 20743, 20747, 20749, 20753, 20759, 20771, 20773, + 20789, 20807, 20809, 20849, 20857, 20873, 20879, 20887, 20897, 20899, + 20903, 20921, 20929, 20939, 20947, 20959, 20963, 20981, 20983, 21001, + 21011, 21013, 21017, 21019, 21023, 21031, 21059, 21061, 21067, 21089, + 21101, 21107, 21121, 21139, 21143, 21149, 21157, 21163, 21169, 21179, + 21187, 21191, 21193, 21211, 21221, 21227, 21247, 21269, 21277, 21283, + 21313, 21317, 21319, 21323, 21341, 21347, 21377, 21379, 21383, 21391, + 21397, 21401, 21407, 21419, 21433, 21467, 21481, 21487, 21491, 21493, + 21499, 21503, 21517, 21521, 21523, 21529, 21557, 21559, 21563, 21569, + 21577, 21587, 21589, 21599, 21601, 21611, 21613, 21617, 21647, 21649, + 21661, 21673, 21683, 21701, 21713, 21727, 21737, 21739, 21751, 21757, + 21767, 21773, 21787, 21799, 21803, 21817, 21821, 21839, 21841, 21851, + 21859, 21863, 21871, 21881, 21893, 21911, 21929, 21937, 21943, 21961, + 21977, 21991, 21997, 22003, 22013, 22027, 22031, 22037, 22039, 22051, + 22063, 22067, 22073, 22079, 22091, 22093, 22109, 22111, 22123, 22129, + 22133, 22147, 22153, 22157, 22159, 22171, 22189, 22193, 22229, 22247, + 22259, 22271, 22273, 22277, 22279, 22283, 22291, 22303, 22307, 22343, + 22349, 22367, 22369, 22381, 22391, 22397, 22409, 22433, 22441, 22447, + 22453, 22469, 22481, 22483, 22501, 22511, 22531, 22541, 22543, 22549, + 22567, 22571, 22573, 22613, 22619, 22621, 22637, 22639, 22643, 22651, + 22669, 22679, 22691, 22697, 22699, 22709, 22717, 22721, 22727, 22739, + 22741, 22751, 22769, 22777, 22783, 22787, 22807, 22811, 22817, 22853, + 22859, 22861, 22871, 22877, 22901, 22907, 22921, 22937, 22943, 22961, + 22963, 22973, 22993, 23003, 23011, 23017, 23021, 23027, 23029, 23039, + 23041, 23053, 23057, 23059, 23063, 23071, 23081, 23087, 23099, 23117, + 23131, 23143, 23159, 23167, 23173, 23189, 23197, 23201, 23203, 23209, + 23227, 23251, 23269, 23279, 23291, 23293, 23297, 23311, 23321, 23327, + 23333, 23339, 23357, 23369, 23371, 23399, 23417, 23431, 23447, 23459, + 23473, 23497, 23509, 23531, 23537, 23539, 23549, 23557, 23561, 23563, + 23567, 23581, 23593, 23599, 23603, 23609, 23623, 23627, 23629, 23633, + 23663, 23669, 23671, 23677, 23687, 23689, 23719, 23741, 23743, 23747, + 23753, 23761, 23767, 23773, 23789, 23801, 23813, 23819, 23827, 23831, + 23833, 23857, 23869, 23873, 23879, 23887, 23893, 23899, 23909, 23911, + 23917, 23929, 23957, 23971, 23977, 23981, 23993, 24001, 24007, 24019, + 24023, 24029, 24043, 24049, 24061, 24071, 24077, 24083, 24091, 24097, + 24103, 24107, 24109, 24113, 24121, 24133, 24137, 24151, 24169, 24179, + 24181, 24197, 24203, 24223, 24229, 24239, 24247, 24251, 24281, 24317, + 24329, 24337, 24359, 24371, 24373, 24379, 24391, 24407, 24413, 24419, + 24421, 24439, 24443, 24469, 24473, 24481, 24499, 24509, 24517, 24527, + 24533, 24547, 24551, 24571, 24593, 24611, 24623, 24631, 24659, 24671, + 24677, 24683, 24691, 24697, 24709, 24733, 24749, 24763, 24767, 24781, + 24793, 24799, 24809, 24821, 24841, 24847, 24851, 24859, 24877, 24889, + 24907, 24917, 24919, 24923, 24943, 24953, 24967, 24971, 24977, 24979, + 24989, 25013, 25031, 25033, 25037, 25057, 25073, 25087, 25097, 25111, + 25117, 25121, 25127, 25147, 25153, 25163, 25169, 25171, 25183, 25189, + 25219, 25229, 25237, 25243, 25247, 25253, 25261, 25301, 25303, 25307, + 25309, 25321, 25339, 25343, 25349, 25357, 25367, 25373, 25391, 25409, + 25411, 25423, 25439, 25447, 25453, 25457, 25463, 25469, 25471, 25523, + 25537, 25541, 25561, 25577, 25579, 25583, 25589, 25601, 25603, 25609, + 25621, 25633, 25639, 25643, 25657, 25667, 25673, 25679, 25693, 25703, + 25717, 25733, 25741, 25747, 25759, 25763, 25771, 25793, 25799, 25801, + 25819, 25841, 25847, 25849, 25867, 25873, 25889, 25903, 25913, 25919, + 25931, 25933, 25939, 25943, 25951, 25969, 25981, 25997, 25999, 26003, + 26017, 26021, 26029, 26041, 26053, 26083, 26099, 26107, 26111, 26113, + 26119, 26141, 26153, 26161, 26171, 26177, 26183, 26189, 26203, 26209, + 26227, 26237, 26249, 26251, 26261, 26263, 26267, 26293, 26297, 26309, + 26317, 26321, 26339, 26347, 26357, 26371, 26387, 26393, 26399, 26407, + 26417, 26423, 26431, 26437, 26449, 26459, 26479, 26489, 26497, 26501, + 26513, 26539, 26557, 26561, 26573, 26591, 26597, 26627, 26633, 26641, + 26647, 26669, 26681, 26683, 26687, 26693, 26699, 26701, 26711, 26713, + 26717, 26723, 26729, 26731, 26737, 26759, 26777, 26783, 26801, 26813, + 26821, 26833, 26839, 26849, 26861, 26863, 26879, 26881, 26891, 26893, + 26903, 26921, 26927, 26947, 26951, 26953, 26959, 26981, 26987, 26993, + 27011, 27017, 27031, 27043, 27059, 27061, 27067, 27073, 27077, 27091, + 27103, 27107, 27109, 27127, 27143, 27179, 27191, 27197, 27211, 27239, + 27241, 27253, 27259, 27271, 27277, 27281, 27283, 27299, 27329, 27337, + 27361, 27367, 27397, 27407, 27409, 27427, 27431, 27437, 27449, 27457, + 27479, 27481, 27487, 27509, 27527, 27529, 27539, 27541, 27551, 27581, + 27583, 27611, 27617, 27631, 27647, 27653, 27673, 27689, 27691, 27697, + 27701, 27733, 27737, 27739, 27743, 27749, 27751, 27763, 27767, 27773, + 27779, 27791, 27793, 27799, 27803, 27809, 27817, 27823, 27827, 27847, + 27851, 27883, 27893, 27901, 27917, 27919, 27941, 27943, 27947, 27953, + 27961, 27967, 27983, 27997, 28001, 28019, 28027, 28031, 28051, 28057, + 28069, 28081, 28087, 28097, 28099, 28109, 28111, 28123, 28151, 28163, + 28181, 28183, 28201, 28211, 28219, 28229, 28277, 28279, 28283, 28289, + 28297, 28307, 28309, 28319, 28349, 28351, 28387, 28393, 28403, 28409, + 28411, 28429, 28433, 28439, 28447, 28463, 28477, 28493, 28499, 28513, + 28517, 28537, 28541, 28547, 28549, 28559, 28571, 28573, 28579, 28591, + 28597, 28603, 28607, 28619, 28621, 28627, 28631, 28643, 28649, 28657, + 28661, 28663, 28669, 28687, 28697, 28703, 28711, 28723, 28729, 28751, + 28753, 28759, 28771, 28789, 28793, 28807, 28813, 28817, 28837, 28843, + 28859, 28867, 28871, 28879, 28901, 28909, 28921, 28927, 28933, 28949, + 28961, 28979, 29009, 29017, 29021, 29023, 29027, 29033, 29059, 29063, + 29077, 29101, 29123, 29129, 29131, 29137, 29147, 29153, 29167, 29173, + 29179, 29191, 29201, 29207, 29209, 29221, 29231, 29243, 29251, 29269, + 29287, 29297, 29303, 29311, 29327, 29333, 29339, 29347, 29363, 29383, + 29387, 29389, 29399, 29401, 29411, 29423, 29429, 29437, 29443, 29453, + 29473, 29483, 29501, 29527, 29531, 29537, 29567, 29569, 29573, 29581, + 29587, 29599, 29611, 29629, 29633, 29641, 29663, 29669, 29671, 29683, + 29717, 29723, 29741, 29753, 29759, 29761, 29789, 29803, 29819, 29833, + 29837, 29851, 29863, 29867, 29873, 29879, 29881, 29917, 29921, 29927, + 29947, 29959, 29983, 29989, 30011, 30013, 30029, 30047, 30059, 30071, + 30089, 30091, 30097, 30103, 30109, 30113, 30119, 30133, 30137, 30139, + 30161, 30169, 30181, 30187, 30197, 30203, 30211, 30223, 30241, 30253, + 30259, 30269, 30271, 30293, 30307, 30313, 30319, 30323, 30341, 30347, + 30367, 30389, 30391, 30403, 30427, 30431, 30449, 30467, 30469, 30491, + 30493, 30497, 30509, 30517, 30529, 30539, 30553, 30557, 30559, 30577, + 30593, 30631, 30637, 30643, 30649, 30661, 30671, 30677, 30689, 30697, + 30703, 30707, 30713, 30727, 30757, 30763, 30773, 30781, 30803, 30809, + 30817, 30829, 30839, 30841, 30851, 30853, 30859, 30869, 30871, 30881, + 30893, 30911, 30931, 30937, 30941, 30949, 30971, 30977, 30983, 31013, + 31019, 31033, 31039, 31051, 31063, 31069, 31079, 31081, 31091, 31121, + 31123, 31139, 31147, 31151, 31153, 31159, 31177, 31181, 31183, 31189, + 31193, 31219, 31223, 31231, 31237, 31247, 31249, 31253, 31259, 31267, + 31271, 31277, 31307, 31319, 31321, 31327, 31333, 31337, 31357, 31379, + 31387, 31391, 31393, 31397, 31469, 31477, 31481, 31489, 31511, 31513, + 31517, 31531, 31541, 31543, 31547, 31567, 31573, 31583, 31601, 31607, + 31627, 31643, 31649, 31657, 31663, 31667, 31687, 31699, 31721, 31723, + 31727, 31729, 31741, 31751, 31769, 31771, 31793, 31799, 31817, 31847, + 31849, 31859, 31873, 31883, 31891, 31907, 31957, 31963, 31973, 31981, + 31991, 32003, 32009, 32027, 32029, 32051, 32057, 32059, 32063, 32069, + 32077, 32083, 32089, 32099, 32117, 32119, 32141, 32143, 32159, 32173, + 32183, 32189, 32191, 32203, 32213, 32233, 32237, 32251, 32257, 32261, + 32297, 32299, 32303, 32309, 32321, 32323, 32327, 32341, 32353, 32359, + 32363, 32369, 32371, 32377, 32381, 32401, 32411, 32413, 32423, 32429, + 32441, 32443, 32467, 32479, 32491, 32497, 32503, 32507, 32531, 32533, + 32537, 32561, 32563, 32569, 32573, 32579, 32587, 32603, 32609, 32611, + 32621, 32633, 32647, 32653, 32687, 32693, 32707, 32713, 32717, 32719, + 32749, 32771, 32779, 32783, 32789, 32797, 32801, 32803, 32831, 32833, + 32839, 32843, 32869, 32887, 32909, 32911, 32917, 32933, 32939, 32941, + 32957, 32969, 32971, 32983, 32987, 32993, 32999, 33013, 33023, 33029, + 33037, 33049, 33053, 33071, 33073, 33083, 33091, 33107, 33113, 33119, + 33149, 33151, 33161, 33179, 33181, 33191, 33199, 33203, 33211, 33223, + 33247, 33287, 33289, 33301, 33311, 33317, 33329, 33331, 33343, 33347, + 33349, 33353, 33359, 33377, 33391, 33403, 33409, 33413, 33427, 33457, + 33461, 33469, 33479, 33487, 33493, 33503, 33521, 33529, 33533, 33547, + 33563, 33569, 33577, 33581, 33587, 33589, 33599, 33601, 33613, 33617, + 33619, 33623, 33629, 33637, 33641, 33647, 33679, 33703, 33713, 33721, + 33739, 33749, 33751, 33757, 33767, 33769, 33773, 33791, 33797, 33809, + 33811, 33827, 33829, 33851, 33857, 33863, 33871, 33889, 33893, 33911, + 33923, 33931, 33937, 33941, 33961, 33967, 33997, 34019, 34031, 34033, + 34039, 34057, 34061, 34123, 34127, 34129, 34141, 34147, 34157, 34159, + 34171, 34183, 34211, 34213, 34217, 34231, 34253, 34259, 34261, 34267, + 34273, 34283, 34297, 34301, 34303, 34313, 34319, 34327, 34337, 34351, + 34361, 34367, 34369, 34381, 34403, 34421, 34429, 34439, 34457, 34469, + 34471, 34483, 34487, 34499, 34501, 34511, 34513, 34519, 34537, 34543, + 34549, 34583, 34589, 34591, 34603, 34607, 34613, 34631, 34649, 34651, + 34667, 34673, 34679, 34687, 34693, 34703, 34721, 34729, 34739, 34747, + 34757, 34759, 34763, 34781, 34807, 34819, 34841, 34843, 34847, 34849, + 34871, 34877, 34883, 34897, 34913, 34919, 34939, 34949, 34961, 34963, + 34981, 35023, 35027, 35051, 35053, 35059, 35069, 35081, 35083, 35089, + 35099, 35107, 35111, 35117, 35129, 35141, 35149, 35153, 35159, 35171, + 35201, 35221, 35227, 35251, 35257, 35267, 35279, 35281, 35291, 35311, + 35317, 35323, 35327, 35339, 35353, 35363, 35381, 35393, 35401, 35407, + 35419, 35423, 35437, 35447, 35449, 35461, 35491, 35507, 35509, 35521, + 35527, 35531, 35533, 35537, 35543, 35569, 35573, 35591, 35593, 35597, + 35603, 35617, 35671, 35677, 35729, 35731, 35747, 35753, 35759, 35771, + 35797, 35801, 35803, 35809, 35831, 35837, 35839, 35851, 35863, 35869, + 35879, 35897, 35899, 35911, 35923, 35933, 35951, 35963, 35969, 35977, + 35983, 35993, 35999, 36007, 36011, 36013, 36017, 36037, 36061, 36067, + 36073, 36083, 36097, 36107, 36109, 36131, 36137, 36151, 36161, 36187, + 36191, 36209, 36217, 36229, 36241, 36251, 36263, 36269, 36277, 36293, + 36299, 36307, 36313, 36319, 36341, 36343, 36353, 36373, 36383, 36389, + 36433, 36451, 36457, 36467, 36469, 36473, 36479, 36493, 36497, 36523, + 36527, 36529, 36541, 36551, 36559, 36563, 36571, 36583, 36587, 36599, + 36607, 36629, 36637, 36643, 36653, 36671, 36677, 36683, 36691, 36697, + 36709, 36713, 36721, 36739, 36749, 36761, 36767, 36779, 36781, 36787, + 36791, 36793, 36809, 36821, 36833, 36847, 36857, 36871, 36877, 36887, + 36899, 36901, 36913, 36919, 36923, 36929, 36931, 36943, 36947, 36973, + 36979, 36997, 37003, 37013, 37019, 37021, 37039, 37049, 37057, 37061, + 37087, 37097, 37117, 37123, 37139, 37159, 37171, 37181, 37189, 37199, + 37201, 37217, 37223, 37243, 37253, 37273, 37277, 37307, 37309, 37313, + 37321, 37337, 37339, 37357, 37361, 37363, 37369, 37379, 37397, 37409, + 37423, 37441, 37447, 37463, 37483, 37489, 37493, 37501, 37507, 37511, + 37517, 37529, 37537, 37547, 37549, 37561, 37567, 37571, 37573, 37579, + 37589, 37591, 37607, 37619, 37633, 37643, 37649, 37657, 37663, 37691, + 37693, 37699, 37717, 37747, 37781, 37783, 37799, 37811, 37813, 37831, + 37847, 37853, 37861, 37871, 37879, 37889, 37897, 37907, 37951, 37957, + 37963, 37967, 37987, 37991, 37993, 37997, 38011, 38039, 38047, 38053, + 38069, 38083, 38113, 38119, 38149, 38153, 38167, 38177, 38183, 38189, + 38197, 38201, 38219, 38231, 38237, 38239, 38261, 38273, 38281, 38287, + 38299, 38303, 38317, 38321, 38327, 38329, 38333, 38351, 38371, 38377, + 38393, 38431, 38447, 38449, 38453, 38459, 38461, 38501, 38543, 38557, + 38561, 38567, 38569, 38593, 38603, 38609, 38611, 38629, 38639, 38651, + 38653, 38669, 38671, 38677, 38693, 38699, 38707, 38711, 38713, 38723, + 38729, 38737, 38747, 38749, 38767, 38783, 38791, 38803, 38821, 38833, + 38839, 38851, 38861, 38867, 38873, 38891, 38903, 38917, 38921, 38923, + 38933, 38953, 38959, 38971, 38977, 38993, 39019, 39023, 39041, 39043, + 39047, 39079, 39089, 39097, 39103, 39107, 39113, 39119, 39133, 39139, + 39157, 39161, 39163, 39181, 39191, 39199, 39209, 39217, 39227, 39229, + 39233, 39239, 39241, 39251, 39293, 39301, 39313, 39317, 39323, 39341, + 39343, 39359, 39367, 39371, 39373, 39383, 39397, 39409, 39419, 39439, + 39443, 39451, 39461, 39499, 39503, 39509, 39511, 39521, 39541, 39551, + 39563, 39569, 39581, 39607, 39619, 39623, 39631, 39659, 39667, 39671, + 39679, 39703, 39709, 39719, 39727, 39733, 39749, 39761, 39769, 39779, + 39791, 39799, 39821, 39827, 39829, 39839, 39841, 39847, 39857, 39863, + 39869, 39877, 39883, 39887, 39901, 39929, 39937, 39953, 39971, 39979, + 39983, 39989, 40009, 40013, 40031, 40037, 40039, 40063, 40087, 40093, + 40099, 40111, 40123, 40127, 40129, 40151, 40153, 40163, 40169, 40177, + 40189, 40193, 40213, 40231, 40237, 40241, 40253, 40277, 40283, 40289, + 40343, 40351, 40357, 40361, 40387, 40423, 40427, 40429, 40433, 40459, + 40471, 40483, 40487, 40493, 40499, 40507, 40519, 40529, 40531, 40543, + 40559, 40577, 40583, 40591, 40597, 40609, 40627, 40637, 40639, 40693, + 40697, 40699, 40709, 40739, 40751, 40759, 40763, 40771, 40787, 40801, + 40813, 40819, 40823, 40829, 40841, 40847, 40849, 40853, 40867, 40879, + 40883, 40897, 40903, 40927, 40933, 40939, 40949, 40961, 40973, 40993, + 41011, 41017, 41023, 41039, 41047, 41051, 41057, 41077, 41081, 41113, + 41117, 41131, 41141, 41143, 41149, 41161, 41177, 41179, 41183, 41189, + 41201, 41203, 41213, 41221, 41227, 41231, 41233, 41243, 41257, 41263, + 41269, 41281, 41299, 41333, 41341, 41351, 41357, 41381, 41387, 41389, + 41399, 41411, 41413, 41443, 41453, 41467, 41479, 41491, 41507, 41513, + 41519, 41521, 41539, 41543, 41549, 41579, 41593, 41597, 41603, 41609, + 41611, 41617, 41621, 41627, 41641, 41647, 41651, 41659, 41669, 41681, + 41687, 41719, 41729, 41737, 41759, 41761, 41771, 41777, 41801, 41809, + 41813, 41843, 41849, 41851, 41863, 41879, 41887, 41893, 41897, 41903, + 41911, 41927, 41941, 41947, 41953, 41957, 41959, 41969, 41981, 41983, + 41999, 42013, 42017, 42019, 42023, 42043, 42061, 42071, 42073, 42083, + 42089, 42101, 42131, 42139, 42157, 42169, 42179, 42181, 42187, 42193, + 42197, 42209, 42221, 42223, 42227, 42239, 42257, 42281, 42283, 42293, + 42299, 42307, 42323, 42331, 42337, 42349, 42359, 42373, 42379, 42391, + 42397, 42403, 42407, 42409, 42433, 42437, 42443, 42451, 42457, 42461, + 42463, 42467, 42473, 42487, 42491, 42499, 42509, 42533, 42557, 42569, + 42571, 42577, 42589, 42611, 42641, 42643, 42649, 42667, 42677, 42683, + 42689, 42697, 42701, 42703, 42709, 42719, 42727, 42737, 42743, 42751, + 42767, 42773, 42787, 42793, 42797, 42821, 42829, 42839, 42841, 42853, + 42859, 42863, 42899, 42901, 42923, 42929, 42937, 42943, 42953, 42961, + 42967, 42979, 42989, 43003, 43013, 43019, 43037, 43049, 43051, 43063, + 43067, 43093, 43103, 43117, 43133, 43151, 43159, 43177, 43189, 43201, + 43207, 43223, 43237, 43261, 43271, 43283, 43291, 43313, 43319, 43321, + 43331, 43391, 43397, 43399, 43403, 43411, 43427, 43441, 43451, 43457, + 43481, 43487, 43499, 43517, 43541, 43543, 43573, 43577, 43579, 43591, + 43597, 43607, 43609, 43613, 43627, 43633, 43649, 43651, 43661, 43669, + 43691, 43711, 43717, 43721, 43753, 43759, 43777, 43781, 43783, 43787, + 43789, 43793, 43801, 43853, 43867, 43889, 43891, 43913, 43933, 43943, + 43951, 43961, 43963, 43969, 43973, 43987, 43991, 43997, 44017, 44021, + 44027, 44029, 44041, 44053, 44059, 44071, 44087, 44089, 44101, 44111, + 44119, 44123, 44129, 44131, 44159, 44171, 44179, 44189, 44201, 44203, + 44207, 44221, 44249, 44257, 44263, 44267, 44269, 44273, 44279, 44281, + 44293, 44351, 44357, 44371, 44381, 44383, 44389, 44417, 44449, 44453, + 44483, 44491, 44497, 44501, 44507, 44519, 44531, 44533, 44537, 44543, + 44549, 44563, 44579, 44587, 44617, 44621, 44623, 44633, 44641, 44647, + 44651, 44657, 44683, 44687, 44699, 44701, 44711, 44729, 44741, 44753, + 44771, 44773, 44777, 44789, 44797, 44809, 44819, 44839, 44843, 44851, + 44867, 44879, 44887, 44893, 44909, 44917, 44927, 44939, 44953, 44959, + 44963, 44971, 44983, 44987, 45007, 45013, 45053, 45061, 45077, 45083, + 45119, 45121, 45127, 45131, 45137, 45139, 45161, 45179, 45181, 45191, + 45197, 45233, 45247, 45259, 45263, 45281, 45289, 45293, 45307, 45317, + 45319, 45329, 45337, 45341, 45343, 45361, 45377, 45389, 45403, 45413, + 45427, 45433, 45439, 45481, 45491, 45497, 45503, 45523, 45533, 45541, + 45553, 45557, 45569, 45587, 45589, 45599, 45613, 45631, 45641, 45659, + 45667, 45673, 45677, 45691, 45697, 45707, 45737, 45751, 45757, 45763, + 45767, 45779, 45817, 45821, 45823, 45827, 45833, 45841, 45853, 45863, + 45869, 45887, 45893, 45943, 45949, 45953, 45959, 45971, 45979, 45989, + 46021, 46027, 46049, 46051, 46061, 46073, 46091, 46093, 46099, 46103, + 46133, 46141, 46147, 46153, 46171, 46181, 46183, 46187, 46199, 46219, + 46229, 46237, 46261, 46271, 46273, 46279, 46301, 46307, 46309, 46327, + 46337, 46349, 46351, 46381, 46399, 46411, 46439, 46441, 46447, 46451, + 46457, 46471, 46477, 46489, 46499, 46507, 46511, 46523, 46549, 46559, + 46567, 46573, 46589, 46591, 46601, 46619, 46633, 46639, 46643, 46649, + 46663, 46679, 46681, 46687, 46691, 46703, 46723, 46727, 46747, 46751, + 46757, 46769, 46771, 46807, 46811, 46817, 46819, 46829, 46831, 46853, + 46861, 46867, 46877, 46889, 46901, 46919, 46933, 46957, 46993, 46997, + 47017, 47041, 47051, 47057, 47059, 47087, 47093, 47111, 47119, 47123, + 47129, 47137, 47143, 47147, 47149, 47161, 47189, 47207, 47221, 47237, + 47251, 47269, 47279, 47287, 47293, 47297, 47303, 47309, 47317, 47339, + 47351, 47353, 47363, 47381, 47387, 47389, 47407, 47417, 47419, 47431, + 47441, 47459, 47491, 47497, 47501, 47507, 47513, 47521, 47527, 47533, + 47543, 47563, 47569, 47581, 47591, 47599, 47609, 47623, 47629, 47639, + 47653, 47657, 47659, 47681, 47699, 47701, 47711, 47713, 47717, 47737, + 47741, 47743, 47777, 47779, 47791, 47797, 47807, 47809, 47819, 47837, + 47843, 47857, 47869, 47881, 47903, 47911, 47917, 47933, 47939, 47947, + 47951, 47963, 47969, 47977, 47981, 48017, 48023, 48029, 48049, 48073, + 48079, 48091, 48109, 48119, 48121, 48131, 48157, 48163, 48179, 48187, + 48193, 48197, 48221, 48239, 48247, 48259, 48271, 48281, 48299, 48311, + 48313, 48337, 48341, 48353, 48371, 48383, 48397, 48407, 48409, 48413, + 48437, 48449, 48463, 48473, 48479, 48481, 48487, 48491, 48497, 48523, + 48527, 48533, 48539, 48541, 48563, 48571, 48589, 48593, 48611, 48619, + 48623, 48647, 48649, 48661, 48673, 48677, 48679, 48731, 48733, 48751, + 48757, 48761, 48767, 48779, 48781, 48787, 48799, 48809, 48817, 48821, + 48823, 48847, 48857, 48859, 48869, 48871, 48883, 48889, 48907, 48947, + 48953, 48973, 48989, 48991, 49003, 49009, 49019, 49031, 49033, 49037, + 49043, 49057, 49069, 49081, 49103, 49109, 49117, 49121, 49123, 49139, + 49157, 49169, 49171, 49177, 49193, 49199, 49201, 49207, 49211, 49223, + 49253, 49261, 49277, 49279, 49297, 49307, 49331, 49333, 49339, 49363, + 49367, 49369, 49391, 49393, 49409, 49411, 49417, 49429, 49433, 49451, + 49459, 49463, 49477, 49481, 49499, 49523, 49529, 49531, 49537, 49547, + 49549, 49559, 49597, 49603, 49613, 49627, 49633, 49639, 49663, 49667, + 49669, 49681, 49697, 49711, 49727, 49739, 49741, 49747, 49757, 49783, + 49787, 49789, 49801, 49807, 49811, 49823, 49831, 49843, 49853, 49871, + 49877, 49891, 49919, 49921, 49927, 49937, 49939, 49943, 49957, 49991, + 49993, 49999, 50021, 50023, 50033, 50047, 50051, 50053, 50069, 50077, + 50087, 50093, 50101, 50111, 50119, 50123, 50129, 50131, 50147, 50153, + 50159, 50177, 50207, 50221, 50227, 50231, 50261, 50263, 50273, 50287, + 50291, 50311, 50321, 50329, 50333, 50341, 50359, 50363, 50377, 50383, + 50387, 50411, 50417, 50423, 50441, 50459, 50461, 50497, 50503, 50513, + 50527, 50539, 50543, 50549, 50551, 50581, 50587, 50591, 50593, 50599, + 50627, 50647, 50651, 50671, 50683, 50707, 50723, 50741, 50753, 50767, + 50773, 50777, 50789, 50821, 50833, 50839, 50849, 50857, 50867, 50873, + 50891, 50893, 50909, 50923, 50929, 50951, 50957, 50969, 50971, 50989, + 50993, 51001, 51031, 51043, 51047, 51059, 51061, 51071, 51109, 51131, + 51133, 51137, 51151, 51157, 51169, 51193, 51197, 51199, 51203, 51217, + 51229, 51239, 51241, 51257, 51263, 51283, 51287, 51307, 51329, 51341, + 51343, 51347, 51349, 51361, 51383, 51407, 51413, 51419, 51421, 51427, + 51431, 51437, 51439, 51449, 51461, 51473, 51479, 51481, 51487, 51503, + 51511, 51517, 51521, 51539, 51551, 51563, 51577, 51581, 51593, 51599, + 51607, 51613, 51631, 51637, 51647, 51659, 51673, 51679, 51683, 51691, + 51713, 51719, 51721, 51749, 51767, 51769, 51787, 51797, 51803, 51817, + 51827, 51829, 51839, 51853, 51859, 51869, 51871, 51893, 51899, 51907, + 51913, 51929, 51941, 51949, 51971, 51973, 51977, 51991, 52009, 52021, + 52027, 52051, 52057, 52067, 52069, 52081, 52103, 52121, 52127, 52147, + 52153, 52163, 52177, 52181, 52183, 52189, 52201, 52223, 52237, 52249, + 52253, 52259, 52267, 52289, 52291, 52301, 52313, 52321, 52361, 52363, + 52369, 52379, 52387, 52391, 52433, 52453, 52457, 52489, 52501, 52511, + 52517, 52529, 52541, 52543, 52553, 52561, 52567, 52571, 52579, 52583, + 52609, 52627, 52631, 52639, 52667, 52673, 52691, 52697, 52709, 52711, + 52721, 52727, 52733, 52747, 52757, 52769, 52783, 52807, 52813, 52817, + 52837, 52859, 52861, 52879, 52883, 52889, 52901, 52903, 52919, 52937, + 52951, 52957, 52963, 52967, 52973, 52981, 52999, 53003, 53017, 53047, + 53051, 53069, 53077, 53087, 53089, 53093, 53101, 53113, 53117, 53129, + 53147, 53149, 53161, 53171, 53173, 53189, 53197, 53201, 53231, 53233, + 53239, 53267, 53269, 53279, 53281, 53299, 53309, 53323, 53327, 53353, + 53359, 53377, 53381, 53401, 53407, 53411, 53419, 53437, 53441, 53453, + 53479, 53503, 53507, 53527, 53549, 53551, 53569, 53591, 53593, 53597, + 53609, 53611, 53617, 53623, 53629, 53633, 53639, 53653, 53657, 53681, + 53693, 53699, 53717, 53719, 53731, 53759, 53773, 53777, 53783, 53791, + 53813, 53819, 53831, 53849, 53857, 53861, 53881, 53887, 53891, 53897, + 53899, 53917, 53923, 53927, 53939, 53951, 53959, 53987, 53993, 54001, + 54011, 54013, 54037, 54049, 54059, 54083, 54091, 54101, 54121, 54133, + 54139, 54151, 54163, 54167, 54181, 54193, 54217, 54251, 54269, 54277, + 54287, 54293, 54311, 54319, 54323, 54331, 54347, 54361, 54367, 54371, + 54377, 54401, 54403, 54409, 54413, 54419, 54421, 54437, 54443, 54449, + 54469, 54493, 54497, 54499, 54503, 54517, 54521, 54539, 54541, 54547, + 54559, 54563, 54577, 54581, 54583, 54601, 54617, 54623, 54629, 54631, + 54647, 54667, 54673, 54679, 54709, 54713, 54721, 54727, 54751, 54767, + 54773, 54779, 54787, 54799, 54829, 54833, 54851, 54869, 54877, 54881, + 54907, 54917, 54919, 54941, 54949, 54959, 54973, 54979, 54983, 55001, + 55009, 55021, 55049, 55051, 55057, 55061, 55073, 55079, 55103, 55109, + 55117, 55127, 55147, 55163, 55171, 55201, 55207, 55213, 55217, 55219, + 55229, 55243, 55249, 55259, 55291, 55313, 55331, 55333, 55337, 55339, + 55343, 55351, 55373, 55381, 55399, 55411, 55439, 55441, 55457, 55469, + 55487, 55501, 55511, 55529, 55541, 55547, 55579, 55589, 55603, 55609, + 55619, 55621, 55631, 55633, 55639, 55661, 55663, 55667, 55673, 55681, + 55691, 55697, 55711, 55717, 55721, 55733, 55763, 55787, 55793, 55799, + 55807, 55813, 55817, 55819, 55823, 55829, 55837, 55843, 55849, 55871, + 55889, 55897, 55901, 55903, 55921, 55927, 55931, 55933, 55949, 55967, + 55987, 55997, 56003, 56009, 56039, 56041, 56053, 56081, 56087, 56093, + 56099, 56101, 56113, 56123, 56131, 56149, 56167, 56171, 56179, 56197, + 56207, 56209, 56237, 56239, 56249, 56263, 56267, 56269, 56299, 56311, + 56333, 56359, 56369, 56377, 56383, 56393, 56401, 56417, 56431, 56437, + 56443, 56453, 56467, 56473, 56477, 56479, 56489, 56501, 56503, 56509, + 56519, 56527, 56531, 56533, 56543, 56569, 56591, 56597, 56599, 56611, + 56629, 56633, 56659, 56663, 56671, 56681, 56687, 56701, 56711, 56713, + 56731, 56737, 56747, 56767, 56773, 56779, 56783, 56807, 56809, 56813, + 56821, 56827, 56843, 56857, 56873, 56891, 56893, 56897, 56909, 56911, + 56921, 56923, 56929, 56941, 56951, 56957, 56963, 56983, 56989, 56993, + 56999, 57037, 57041, 57047, 57059, 57073, 57077, 57089, 57097, 57107, + 57119, 57131, 57139, 57143, 57149, 57163, 57173, 57179, 57191, 57193, + 57203, 57221, 57223, 57241, 57251, 57259, 57269, 57271, 57283, 57287, + 57301, 57329, 57331, 57347, 57349, 57367, 57373, 57383, 57389, 57397, + 57413, 57427, 57457, 57467, 57487, 57493, 57503, 57527, 57529, 57557, + 57559, 57571, 57587, 57593, 57601, 57637, 57641, 57649, 57653, 57667, + 57679, 57689, 57697, 57709, 57713, 57719, 57727, 57731, 57737, 57751, + 57773, 57781, 57787, 57791, 57793, 57803, 57809, 57829, 57839, 57847, + 57853, 57859, 57881, 57899, 57901, 57917, 57923, 57943, 57947, 57973, + 57977, 57991, 58013, 58027, 58031, 58043, 58049, 58057, 58061, 58067, + 58073, 58099, 58109, 58111, 58129, 58147, 58151, 58153, 58169, 58171, + 58189, 58193, 58199, 58207, 58211, 58217, 58229, 58231, 58237, 58243, + 58271, 58309, 58313, 58321, 58337, 58363, 58367, 58369, 58379, 58391, + 58393, 58403, 58411, 58417, 58427, 58439, 58441, 58451, 58453, 58477, + 58481, 58511, 58537, 58543, 58549, 58567, 58573, 58579, 58601, 58603, + 58613, 58631, 58657, 58661, 58679, 58687, 58693, 58699, 58711, 58727, + 58733, 58741, 58757, 58763, 58771, 58787, 58789, 58831, 58889, 58897, + 58901, 58907, 58909, 58913, 58921, 58937, 58943, 58963, 58967, 58979, + 58991, 58997, 59009, 59011, 59021, 59023, 59029, 59051, 59053, 59063, + 59069, 59077, 59083, 59093, 59107, 59113, 59119, 59123, 59141, 59149, + 59159, 59167, 59183, 59197, 59207, 59209, 59219, 59221, 59233, 59239, + 59243, 59263, 59273, 59281, 59333, 59341, 59351, 59357, 59359, 59369, + 59377, 59387, 59393, 59399, 59407, 59417, 59419, 59441, 59443, 59447, + 59453, 59467, 59471, 59473, 59497, 59509, 59513, 59539, 59557, 59561, + 59567, 59581, 59611, 59617, 59621, 59627, 59629, 59651, 59659, 59663, + 59669, 59671, 59693, 59699, 59707, 59723, 59729, 59743, 59747, 59753, + 59771, 59779, 59791, 59797, 59809, 59833, 59863, 59879, 59887, 59921, + 59929, 59951, 59957, 59971, 59981, 59999, 60013, 60017, 60029, 60037, + 60041, 60077, 60083, 60089, 60091, 60101, 60103, 60107, 60127, 60133, + 60139, 60149, 60161, 60167, 60169, 60209, 60217, 60223, 60251, 60257, + 60259, 60271, 60289, 60293, 60317, 60331, 60337, 60343, 60353, 60373, + 60383, 60397, 60413, 60427, 60443, 60449, 60457, 60493, 60497, 60509, + 60521, 60527, 60539, 60589, 60601, 60607, 60611, 60617, 60623, 60631, + 60637, 60647, 60649, 60659, 60661, 60679, 60689, 60703, 60719, 60727, + 60733, 60737, 60757, 60761, 60763, 60773, 60779, 60793, 60811, 60821, + 60859, 60869, 60887, 60889, 60899, 60901, 60913, 60917, 60919, 60923, + 60937, 60943, 60953, 60961, 61001, 61007, 61027, 61031, 61043, 61051, + 61057, 61091, 61099, 61121, 61129, 61141, 61151, 61153, 61169, 61211, + 61223, 61231, 61253, 61261, 61283, 61291, 61297, 61331, 61333, 61339, + 61343, 61357, 61363, 61379, 61381, 61403, 61409, 61417, 61441, 61463, + 61469, 61471, 61483, 61487, 61493, 61507, 61511, 61519, 61543, 61547, + 61553, 61559, 61561, 61583, 61603, 61609, 61613, 61627, 61631, 61637, + 61643, 61651, 61657, 61667, 61673, 61681, 61687, 61703, 61717, 61723, + 61729, 61751, 61757, 61781, 61813, 61819, 61837, 61843, 61861, 61871, + 61879, 61909, 61927, 61933, 61949, 61961, 61967, 61979, 61981, 61987, + 61991, 62003, 62011, 62017, 62039, 62047, 62053, 62057, 62071, 62081, + 62099, 62119, 62129, 62131, 62137, 62141, 62143, 62171, 62189, 62191, + 62201, 62207, 62213, 62219, 62233, 62273, 62297, 62299, 62303, 62311, + 62323, 62327, 62347, 62351, 62383, 62401, 62417, 62423, 62459, 62467, + 62473, 62477, 62483, 62497, 62501, 62507, 62533, 62539, 62549, 62563, + 62581, 62591, 62597, 62603, 62617, 62627, 62633, 62639, 62653, 62659, + 62683, 62687, 62701, 62723, 62731, 62743, 62753, 62761, 62773, 62791, + 62801, 62819, 62827, 62851, 62861, 62869, 62873, 62897, 62903, 62921, + 62927, 62929, 62939, 62969, 62971, 62981, 62983, 62987, 62989, 63029, + 63031, 63059, 63067, 63073, 63079, 63097, 63103, 63113, 63127, 63131, + 63149, 63179, 63197, 63199, 63211, 63241, 63247, 63277, 63281, 63299, + 63311, 63313, 63317, 63331, 63337, 63347, 63353, 63361, 63367, 63377, + 63389, 63391, 63397, 63409, 63419, 63421, 63439, 63443, 63463, 63467, + 63473, 63487, 63493, 63499, 63521, 63527, 63533, 63541, 63559, 63577, + 63587, 63589, 63599, 63601, 63607, 63611, 63617, 63629, 63647, 63649, + 63659, 63667, 63671, 63689, 63691, 63697, 63703, 63709, 63719, 63727, + 63737, 63743, 63761, 63773, 63781, 63793, 63799, 63803, 63809, 63823, + 63839, 63841, 63853, 63857, 63863, 63901, 63907, 63913, 63929, 63949, + 63977, 63997, 64007, 64013, 64019, 64033, 64037, 64063, 64067, 64081, + 64091, 64109, 64123, 64151, 64153, 64157, 64171, 64187, 64189, 64217, + 64223, 64231, 64237, 64271, 64279, 64283, 64301, 64303, 64319, 64327, + 64333, 64373, 64381, 64399, 64403, 64433, 64439, 64451, 64453, 64483, + 64489, 64499, 64513, 64553, 64567, 64577, 64579, 64591, 64601, 64609, + 64613, 64621, 64627, 64633, 64661, 64663, 64667, 64679, 64693, 64709, + 64717, 64747, 64763, 64781, 64783, 64793, 64811, 64817, 64849, 64853, + 64871, 64877, 64879, 64891, 64901, 64919, 64921, 64927, 64937, 64951, + 64969, 64997, 65003, 65011, 65027, 65029, 65033, 65053, 65063, 65071, + 65089, 65099, 65101, 65111, 65119, 65123, 65129, 65141, 65147, 65167, + 65171, 65173, 65179, 65183, 65203, 65213, 65239, 65257, 65267, 65269, + 65287, 65293, 65309, 65323, 65327, 65353, 65357, 65371, 65381, 65393, + 65407, 65413, 65419, 65423, 65437, 65447, 65449, 65479, 65497, 65519, + 65521, +}; diff --git a/src/numtheory/cl_IF_trialdiv.cc b/src/numtheory/cl_IF_trialdiv.cc new file mode 100644 index 0000000..8798ad5 --- /dev/null +++ b/src/numtheory/cl_IF_trialdiv.cc @@ -0,0 +1,40 @@ +// cl_trialdivision(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_IF.h" + + +// Implementation. + +#include "cl_I.h" + +#if !(intDsize >= 16) +#error "intDsize too small for trialdivision!" +#endif + +uint32 cl_trialdivision (const cl_I& n, uint32 d1, uint32 d2) +{ + var uintL i = cl_small_prime_table_search(d1); + var const uint16 * ptr = &cl_small_prime_table[i]; + var const uint16 * ptr_limit = &cl_small_prime_table[cl_small_prime_table_search(d2+1)]; + // Unpack n. + CL_ALLOCA_STACK; + var const uintD* n_MSDptr; + var uintC n_len; + I_to_NDS_nocopy(n, n_MSDptr=,n_len=,,cl_false,); + if (mspref(n_MSDptr,0)==0) { msshrink(n_MSDptr); n_len--; } + // Make room for a quotient. + var uintD* q_MSDptr; + num_stack_alloc(n_len,q_MSDptr=,); + // Division loop. + for ( ; ptr < ptr_limit; ptr++) { + var uint32 prime = *ptr; + var uintD r = divucopy_loop_msp(prime,n_MSDptr,q_MSDptr,n_len); + if (r == 0) + return prime; + } + return 0; +} diff --git a/src/numtheory/cl_IF_trialdiv1.cc b/src/numtheory/cl_IF_trialdiv1.cc new file mode 100644 index 0000000..136f800 --- /dev/null +++ b/src/numtheory/cl_IF_trialdiv1.cc @@ -0,0 +1,27 @@ +// cl_trialdivision(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_IF.h" + + +// Implementation. + +#include "cl_low.h" + +uint32 cl_trialdivision (uint32 n, uint32 d1, uint32 d2) +{ + var uintL i = cl_small_prime_table_search(d1); + var const uint16 * ptr = &cl_small_prime_table[i]; + var const uint16 * ptr_limit = &cl_small_prime_table[cl_small_prime_table_search(d2+1)]; + for ( ; ptr < ptr_limit; ptr++) { + var uint32 prime = *ptr; + var uint32 r; + r = n % prime; // or: divu_3232_3232(n,prime,,r=); + if (r == 0) + return prime; + } + return 0; +} diff --git a/src/numtheory/cl_IF_trialdiv2.cc b/src/numtheory/cl_IF_trialdiv2.cc new file mode 100644 index 0000000..bf8b3e6 --- /dev/null +++ b/src/numtheory/cl_IF_trialdiv2.cc @@ -0,0 +1,29 @@ +// cl_trialdivision(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_IF.h" + + +// Implementation. + +#include "cl_low.h" + +uint32 cl_trialdivision (uint32 nhi, uint32 nlo, uint32 d1, uint32 d2) +{ + var uintL i = cl_small_prime_table_search(d1); + var const uint16 * ptr = &cl_small_prime_table[i]; + var const uint16 * ptr_limit = &cl_small_prime_table[cl_small_prime_table_search(d2+1)]; + for ( ; ptr < ptr_limit; ptr++) { + var uint32 prime = *ptr; + var uint32 hi; + var uint32 r; + hi = nhi % prime; // or: divu_3232_3232(nhi,prime,,hi=); + divu_6432_3232(hi,nlo,prime,,r=); + if (r == 0) + return prime; + } + return 0; +} diff --git a/src/numtheory/cl_nt_cornacchia1.cc b/src/numtheory/cl_nt_cornacchia1.cc new file mode 100644 index 0000000..36b8e2d --- /dev/null +++ b/src/numtheory/cl_nt_cornacchia1.cc @@ -0,0 +1,101 @@ +// cornacchia1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_numtheory.h" + + +// Implementation. + +#include "cl_xmacros.h" + +// [Cohen], section 1.5.2, algorithm 1.5.2. +// For proofs refer to [F. Morain, J.-L. Nicolas: On Cornacchia's algorithm +// for solving the diophantine equation u^2+v*d^2=m]. + +// Quick remark about the uniqueness of the solutions: +// If (x,y) is a solution with x>=0, y>=0, then it is the only one, +// except for d=1 where (x,y) and (y,x) are the only solutions. +// Proof: +// If d > 4: +// Obviously 0 <= x <= sqrt(p), 0 <= y <= sqrt(p)/sqrt(d). +// Assume two solutions (x1,y1) and (x2,y2). +// Then (x1*y2-x2*y1)*(x1*y2+x2*y1) = x1^2*y2^2 - x2^2*y1^2 +// = (x1^2+d*y1^2)*y2^2 - (x2^2+d*y2^2)*y1^2 = p*y2^2 - p*y1^2 +// is divisible by p. But 0 < x1*y2+x2*y1 <= 2*p/sqrt(d) < p and +// -p < -p/sqrt(d) <= x1*y2-x2*y1 <= p/sqrt(d) < p, hence x1*y2-x2*y1 = 0. +// This means that (x1,y1) and (x2,y2) are linearly dependent over Q, hence +// they must be equal. +// If d <= 4: +// The equation is equivalent to (x+sqrt(-d)*y)*(x-sqrt(-d)*y) = p, i.e. +// a factorization of p in Q(sqrt(-d)). It is known that (for d=1 and d=4) +// Q(sqrt(-1)) = Quot(Z[i]) has class number 1, and (for d=2) Q(sqrt(-2)) +// has class number 1, and (for d=3) Q(sqrt(-3)) has class number 1. +// Hence the prime factors of p in this number field are uniquely determined +// up to units. +// In the case d=2, the only units are {1,-1}, hence there are 4 solutions +// in ZxZ, hence with the restrictions x>=0, y>=0, (x,y) is unique. +// In the case d=1, the only units are {1,-1,i,-i}, hence there are 8 +// solutions [4 if x=y], hence with the restrictions x>=0, y>=0, +// (x,y) and (y,x) are the only nonnegative solutions. +// The case d=4 is basically the same as d=1, with the restriction that y be +// even. But since x and y cannot be both even in x^2+y^2=p, this forbids +// swapping of x and y. Hence (x,y) is unique. +// In the case d=3, the units are generated by e = (1+sqrt(-3))/2, hence +// multiplication of x+sqrt(-3)*y or x-sqrt(-3)*y with e^k (k=0..5) gives +// rise to 12 solutions. But since x and y have different parity and +// e*(x+sqrt(-3)*y) = (x-3*y)/2 + sqrt(-3)*(x+y)/2, the values k=1,2,4,5 +// give non-integral (x,y). Only 4 solutions remain in ZxZ, hence with the +// restrictions x>=0, y>=0, (x,y) is unique. + +const cornacchia_t cornacchia1 (const cl_I& d, const cl_I& p) +{ + if (d >= p) { + if (d == p) + // (x,y) = (0,1) + return cornacchia_t(1, 0,1); + else + // d > p -> no solution + return cornacchia_t(0); + } + // Now 0 < d < p. + if (p == 2) + // (x,y) = (1,1) + return cornacchia_t(1, 1,1); + switch (jacobi(-d,p)) { + case -1: // no solution + return cornacchia_t(0); + case 0: // gcd(d,p) > 1 + return new cl_composite_condition(p,gcd(d,p)); + case 1: + break; + } + // Compute x with x^2+d == 0 mod p. + var cl_modint_ring R = cl_find_modint_ring(p); + var sqrt_mod_p_t init = sqrt_mod_p(R,R->canonhom(-d)); + if (init.condition) + return init.condition; + if (init.solutions != 2) + cl_abort(); + // Euclidean algorithm. + var cl_I a = p; + var cl_I b = R->retract(init.solution[0]); + if (b <= (p>>1)) { b = p-b; } // Enforce p/2 < b < p + var cl_I limit = isqrt(p); + while (b > limit) { + var cl_I r = mod(a,b); + a = b; b = r; + } + // b is the first euclidean remainder <= sqrt(p). + var cl_I& x = b; + var cl_I_div_t div = floor2(p-square(b),d); + if (!zerop(div.remainder)) + return cornacchia_t(0); + var cl_I& c = div.quotient; + var cl_I y; + if (!sqrtp(c,&y)) + return cornacchia_t(0); + return cornacchia_t(1, x,y); +} diff --git a/src/numtheory/cl_nt_cornacchia4.cc b/src/numtheory/cl_nt_cornacchia4.cc new file mode 100644 index 0000000..460f186 --- /dev/null +++ b/src/numtheory/cl_nt_cornacchia4.cc @@ -0,0 +1,115 @@ +// cornacchia4(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_numtheory.h" + + +// Implementation. + +#include "cl_I.h" + +// [Cohen], section 1.5.2, algorithm 1.5.3. +// For proofs refer to [F. Morain, J.-L. Nicolas: On Cornacchia's algorithm +// for solving the diophantine equation u^2+v*d^2=m]. + +const cornacchia_t cornacchia4 (const cl_I& d, const cl_I& p) +{ + // Method: + // Goal: Solve x^2+d*y^2 = 4*p. + // If p=2: {0,1,4,...} + d*{0,1,4,...} = 8. + // d=1: (x,y) = (2,2). + // d=2: (x,y) = (0,2). + // d=4: (x,y) = (2,1). + // d=7: (x,y) = (1,1). + // Else no solution. + // If p>2: + // If d == 0 mod 4: + // x must be even. Solve u^2 + (d/4)*y^2 = p, return (2*u,y). + // If d == 2 mod 4: + // x must be even, then y must be even. Solve u^2 + d*v^2 = p, + // return (2*u,2*v). + // If d == 1,5,7 mod 8: + // x^2+d*y^2 == 4 mod 8, x^2 and y^2 can only be == 0,1,4 mod 8. + // x and y must be even. Solve u^2 + d*v^2 = p, return (2*u,2*v). + // If d == 3 mod 8: + // Compute x with x^2+d == 0 mod 4*p. + // Euclidean algorithm on a = 2*p, b = x, stop when a remainder + // <= 2*sqrt(p) has been reached. + var cl_I p4 = p<<2; + if (d >= p4) { + if (d == p4) + // (x,y) = (0,1) + return cornacchia_t(1, 0,1); + else + // d > 4*p -> no solution + return cornacchia_t(0); + } + // Now 0 < d < 4*p. + if (p == 2) { + if (d==1) return cornacchia_t(1, 2,2); + if (d==2) return cornacchia_t(1, 0,2); + if (d==4) return cornacchia_t(1, 2,1); + if (d==7) return cornacchia_t(1, 1,1); + return cornacchia_t(0); + } + switch (FN_to_L(logand(d,7))) { + case 0: case 4: { + // d == 0 mod 4 + var cornacchia_t s = cornacchia1(d>>2,p); + if (!s.condition) + if (s.solutions != 0) + s.solution_x = s.solution_x<<1; + return s; + } + case 1: case 2: case 5: case 6: case 7: { + var cornacchia_t s = cornacchia1(d,p); + if (!s.condition) + if (s.solutions != 0) { + s.solution_x = s.solution_x<<1; + s.solution_y = s.solution_y<<1; + } + return s; + } + case 3: + break; + } + switch (jacobi(-d,p)) { + case -1: // no solution + return cornacchia_t(0); + case 0: // gcd(d,p) > 1 + return new cl_composite_condition(p,gcd(d,p)); + case 1: + break; + } + // Compute x with x^2+d == 0 mod p. + var cl_modint_ring R = cl_find_modint_ring(p); + var sqrt_mod_p_t init = sqrt_mod_p(R,R->canonhom(-d)); + if (init.condition) + return init.condition; + if (init.solutions != 2) + cl_abort(); + // Compute x with x^2+d == 0 mod 4*p. + var cl_I x0 = R->retract(init.solution[0]); + if (evenp(x0)) { x0 = p-x0; } // Enforce x0^2+d == 0 mod 4. + // Euclidean algorithm. + var cl_I a = p<<1; + var cl_I b = x0; + var cl_I limit = isqrt(p4); + while (b > limit) { + var cl_I r = mod(a,b); + a = b; b = r; + } + // b is the first euclidean remainder <= 2*sqrt(p). + var cl_I& x = b; + var cl_I_div_t div = floor2(p4-square(b),d); + if (!zerop(div.remainder)) + return cornacchia_t(0); + var cl_I& c = div.quotient; + var cl_I y; + if (!sqrtp(c,&y)) + return cornacchia_t(0); + return cornacchia_t(1, x,y); +} diff --git a/src/numtheory/cl_nt_isprobprime.cc b/src/numtheory/cl_nt_isprobprime.cc new file mode 100644 index 0000000..2a0d096 --- /dev/null +++ b/src/numtheory/cl_nt_isprobprime.cc @@ -0,0 +1,55 @@ +// isprobprime(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_numtheory.h" + + +// Implementation. + +#include "cl_IF.h" +#include "cl_abort.h" + +cl_boolean isprobprime (const cl_I& n) +{ + if (!(n > 0)) + cl_abort(); + // With a Miller-Rabin count = 50 the final error probability is + // 4^-50 < 10^-30. + var int count = 50; + // Step 1: Trial division (rules out 87% of all numbers quickly). + const uint32 trialdivide_limit = 70; + var uintL l = integer_length(n); + if (l <= 32) { + var uint32 nn = cl_I_to_UL(n); + if (nn <= cl_small_prime_table_limit) { + // Table lookup. + var uintL i = cl_small_prime_table_search(nn); + if (i < cl_small_prime_table_size + && ((unsigned int) cl_small_prime_table[i] == nn + || nn == 2)) + return cl_true; + else + return cl_false; + } + if ((nn % 2) == 0 || cl_trialdivision(nn,1,trialdivide_limit)) + return cl_false; + // For small n, only few Miller-Rabin tests are needed. + if (nn < 2000U) count = 1; // {2} + else if (nn < 1300000U) count = 2; // {2,3} + else if (nn < 25000000U) count = 3; // {2,3,5} + else if (nn < 3200000000U) count = 4; // {2,3,5,7} + } else if (l <= 64) { + var uint32 nhi = cl_I_to_UL(ldb(n,cl_byte(32,32))); + var uint32 nlo = cl_I_to_UL(ldb(n,cl_byte(32,0))); + if ((nlo % 2) == 0 || cl_trialdivision(nhi,nlo,1,trialdivide_limit)) + return cl_false; + } else { + if (evenp(n) || cl_trialdivision(n,1,trialdivide_limit)) + return cl_false; + } + // Step 2: Miller-Rabin test. + return cl_miller_rabin_test(n,count,NULL); +} diff --git a/src/numtheory/cl_nt_jacobi.cc b/src/numtheory/cl_nt_jacobi.cc new file mode 100644 index 0000000..52191c0 --- /dev/null +++ b/src/numtheory/cl_nt_jacobi.cc @@ -0,0 +1,68 @@ +// jacobi(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_numtheory.h" + + +// Implementation. + +#include "cl_integer.h" +#include "cl_I.h" +#include "cl_abort.h" +#include "cl_xmacros.h" + +int jacobi (const cl_I& a, const cl_I& b) +{ + // Check b > 0, b odd. + if (!(b > 0)) + cl_abort(); + if (!oddp(b)) + cl_abort(); + { Mutable(cl_I,a); + Mutable(cl_I,b); + // Ensure 0 <= a < b. + a = mod(a,b); + // If a and b are fixnums, choose faster routine. + if (fixnump(b)) + return jacobi(FN_to_L(a),FN_to_L(b)); + var int v = 1; + for (;;) { + // (a/b) * v is invariant. + if (b == 1) + // b=1 implies (a/b) = 1. + return v; + if (a == 0) + // b>1 and a=0 imply (a/b) = 0. + return 0; + if (a > (b >> 1)) { + // a > b/2, so (a/b) = (-1/b) * ((b-a)/b), + // and (-1/b) = -1 if b==3 mod 4. + a = b-a; + if (FN_to_L(logand(b,3)) == 3) + v = -v; + continue; + } + if ((a & 1) == 0) { + // b>1 and a=2a', so (a/b) = (2/b) * (a'/b), + // and (2/b) = -1 if b==3,5 mod 8. + a = a>>1; + switch (FN_to_L(logand(b,7))) { + case 3: case 5: v = -v; break; + } + continue; + } + // a and b odd, 0 < a < b/2 < b, so apply quadratic reciprocity + // law (a/b) = (-1)^((a-1)/2)((b-1)/2) * (b/a). + if (FN_to_L(logand(logand(a,b),3)) == 3) + v = -v; + swap(cl_I, a,b); + // Now a > 2*b, set a := a mod b. + if ((a >> 3) >= b) + a = mod(a,b); + else + { a = a-b; do { a = a-b; } while (a >= b); } + } +}} diff --git a/src/numtheory/cl_nt_jacobi_low.cc b/src/numtheory/cl_nt_jacobi_low.cc new file mode 100644 index 0000000..00368a2 --- /dev/null +++ b/src/numtheory/cl_nt_jacobi_low.cc @@ -0,0 +1,75 @@ +// jacobi(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_numtheory.h" + + +// Implementation. + +#include "cl_abort.h" +#include "cl_xmacros.h" + +// Assume 0 <= a < b. +inline int jacobi_aux (uint32 a, uint32 b) +{ + var int v = 1; + for (;;) { + // (a/b) * v is invariant. + if (b == 1) + // b=1 implies (a/b) = 1. + return v; + if (a == 0) + // b>1 and a=0 imply (a/b) = 0. + return 0; + if (a > (b >> 1)) { + // a > b/2, so (a/b) = (-1/b) * ((b-a)/b), + // and (-1/b) = -1 if b==3 mod 4. + a = b-a; + switch (b % 4) { + case 1: break; + case 3: v = -v; break; + default: cl_abort(); + } + continue; + } + if ((a & 1) == 0) { + // b>1 and a=2a', so (a/b) = (2/b) * (a'/b), + // and (2/b) = -1 if b==3,5 mod 8. + a = a>>1; + switch (b % 8) { + case 1: case 7: break; + case 3: case 5: v = -v; break; + default: cl_abort(); + } + continue; + } + // a and b odd, 0 < a < b/2 < b, so apply quadratic reciprocity + // law (a/b) = (-1)^((a-1)/2)((b-1)/2) * (b/a). + if ((a & b & 3) == 3) + v = -v; + swap(sint32, a,b); + // Now a > 2*b, set a := a mod b. + if ((a >> 3) >= b) + a = a % b; + else + { a = a-b; do { a = a-b; } while (a >= b); } + } +} + +int jacobi (sint32 a, sint32 b) +{ + // Check b > 0, b odd. + if (!(b > 0)) + cl_abort(); + if ((b & 1) == 0) + cl_abort(); + // Ensure 0 <= a < b. + if (a >= 0) + a = (uint32)a % (uint32)b; + else + a = b-1-((uint32)(~a) % (uint32)b); + return jacobi_aux(a,b); +} diff --git a/src/numtheory/cl_nt_nextprobprime.cc b/src/numtheory/cl_nt_nextprobprime.cc new file mode 100644 index 0000000..ea702d4 --- /dev/null +++ b/src/numtheory/cl_nt_nextprobprime.cc @@ -0,0 +1,31 @@ +// nextprobprime(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_numtheory.h" + + +// Implementation. + +#include "cl_real.h" + +const cl_I nextprobprime (const cl_R& x) +{ + if (minusp(x)) + return 2; + // Now x >= 0. + var cl_I n = ceiling1(x); + if (n <= 2) + return 2; + // Now n>=3. + if (evenp(n)) + n = n+1; + // Now n>=3 odd. + loop { + if (isprobprime(n)) + return n; + n = n+2; + } +} diff --git a/src/numtheory/cl_nt_sqrtmodp.cc b/src/numtheory/cl_nt_sqrtmodp.cc new file mode 100644 index 0000000..30cc801 --- /dev/null +++ b/src/numtheory/cl_nt_sqrtmodp.cc @@ -0,0 +1,307 @@ +// sqrt_mod_p(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_numtheory.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_abort.h" + +#undef floor +#include +#define floor cln_floor + +// Algorithm 1 (for very small p only): +// Try different values. +// Assume p is prime and a nonzero square in Z/pZ. +static uint32 search_sqrt (uint32 p, uint32 a) +{ + var uint32 x = 1; + var uint32 x2 = 1; + loop { + // 0 < x <= p/2, x2 = x^2 mod p. + if (x2 == a) + return x; + x2 += x; x++; x2 += x; + if (x2 >= p) + x2 -= p; + } +} + +// Algorithm 2 (for p > 2 only): +// Cantor-Zassenhaus. +// [Beth et al.: Computer Algebra, 1988, Kapitel 5.3.3.] +// [Cohen, A Course in Computational Algebraic Number Theory, +// Section 3.4.4., Algorithm 3.4.6.] +// Input: R = Z/pZ with p>2, and a (nonzero square in R). +static const sqrt_mod_p_t cantor_zassenhaus_sqrt (const cl_modint_ring& R, const cl_MI& a); + // Compute in the polynomial ring R[X]/(X^2-a). + struct pol2 { + // A polynomial c0+c1*X mod (X^2-a) + cl_MI c0; + cl_MI c1; + // Constructor. + pol2 (const cl_MI& _c0, const cl_MI& _c1) : c0 (_c0), c1 (_c1) {} + }; + struct pol2ring { + const cl_modint_ring& R; + const cl_MI& a; + const pol2 zero () + { + return pol2(R->zero(),R->zero()); + } + const pol2 one () + { + return pol2(R->one(),R->zero()); + } + const pol2 plus (const pol2& u, const pol2& v) + { + return pol2(u.c0+v.c0, u.c1+v.c1); + } + const pol2 minus (const pol2& u, const pol2& v) + { + return pol2(u.c0-v.c0, u.c1-v.c1); + } + const pol2 mul (const pol2& u, const pol2& v) + { + return pol2(u.c0*v.c0+u.c1*v.c1*a, u.c0*v.c1+u.c1*v.c0); + } + const pol2 square (const pol2& u) + { + return pol2(::square(u.c0) + ::square(u.c1)*a, (u.c0*u.c1)<<1); + } + const pol2 expt_pos (const pol2& x, const cl_I& y) + { + // Right-Left Binary, [Cohen, Algorithm 1.2.1.] + var pol2 a = x; + var cl_I b = y; + while (!oddp(b)) { a = square(a); b = b = b >> 1; } // a^b = x^y + var pol2 c = a; + until (eq(b,1)) { + b = b >> 1; + a = square(a); + // a^b*c = x^y + if (oddp(b)) + c = mul(a,c); + } + return c; + } + const pol2 random () + { + return pol2(R->random(),R->random()); + } + // Computes the degree of gcd(u(X),X^2-a) and, if it is 1, + // also the zero if this polynomial of degree 1. + struct gcd_result { + cl_composite_condition* condition; + int gcd_degree; + cl_MI solution; + // Constructors. + gcd_result (cl_composite_condition* c) : condition (c) {} + gcd_result (int deg) : condition (NULL), gcd_degree (deg) {} + gcd_result (int deg, const cl_MI& sol) : condition (NULL), gcd_degree (deg), solution (sol) {} + }; + const gcd_result gcd (const pol2& u) + { + if (zerop(u.c1)) + // constant polynomial u(X) + if (zerop(u.c0)) + return gcd_result(2); + else + return gcd_result(0); + // u(X) = c0 + c1*X has zero -c0/c1. + var cl_MI_x c1inv = R->recip(u.c1); + if (c1inv.condition) + return c1inv.condition; + var cl_MI z = -u.c0*c1inv; + if (::square(z) == a) + return gcd_result(1,z); + else + return gcd_result(0); + } + // Constructor. + pol2ring (const cl_modint_ring& _R, const cl_MI& _a) : R (_R), a (_a) {} + }; +static const sqrt_mod_p_t cantor_zassenhaus_sqrt (const cl_modint_ring& R, const cl_MI& a) +{ + var pol2ring PR = pol2ring(R,a); + var cl_I& p = R->modulus; + // Assuming p is a prime, then R[X]/(X^2-a) is the direct product of + // two rings R[X]/(X-sqrt(a)), each being isomorphic to R. Thus taking + // a (p-1)/2-th power in this ring will return one of (0,+1,-1) in + // each ring, with independent probabilities (1/p, (p-1)/2p, (p-1)/2p). + // For any polynomial u(X), setting v(X) := u(X)^((p-1)/2) yields + // gcd(u(X),X^2-a) * gcd(v(X)-1,X^2-a) * gcd(v(X)+1,X^2-a) = X^2-a. + // If p is not prime, all of these gcd's are likely to be 1. + var cl_I e = (p-1) >> 1; + loop { + // Choose a random polynomial u(X) in the ring. + var pol2 u = PR.random(); + // Compute v(X) = u(X)^((p-1)/2). + var pol2 v = PR.expt_pos(u,e); + // Compute the three gcds. + var pol2ring::gcd_result g1 = PR.gcd(PR.minus(v,PR.one())); + if (g1.condition) + return g1.condition; + if (g1.gcd_degree == 1) + return sqrt_mod_p_t(2,g1.solution,-g1.solution); + if (g1.gcd_degree == 2) + continue; + var pol2ring::gcd_result g2 = PR.gcd(PR.plus(v,PR.one())); + if (g2.condition) + return g2.condition; + if (g2.gcd_degree == 1) + return sqrt_mod_p_t(2,g2.solution,-g2.solution); + if (g2.gcd_degree == 2) + continue; + var pol2ring::gcd_result g3 = PR.gcd(u); + if (g3.condition) + return g3.condition; + if (g3.gcd_degree == 1) + return sqrt_mod_p_t(2,g3.solution,-g3.solution); + if (g1.gcd_degree + g2.gcd_degree + g3.gcd_degree < 2) + // If the sum of the degrees of the gcd is != 2, + // p cannot be prime. + return new cl_composite_condition(p); + } +} + +// Algorithm 3 (for p > 2 only): +// Tonelli-Shanks. +// [Cohen, A Course in Computational Algebraic Number Theory, +// Section 1.5.1., Algorithm 1.5.1.] +static const sqrt_mod_p_t tonelli_shanks_sqrt (const cl_modint_ring& R, const cl_MI& a) +{ + // Idea: + // Write p-1 = 2^e*m, m odd. G = (Z/pZ)^* (cyclic of order p-1) has + // subgroups G_0 < G_1 < ... < G_e, G_j of order 2^j. (G_e is called + // the "2-Sylow subgroup" of G.) More precisely + // G_j = { x in (Z/pZ)^* : x^(2^j) = 1 }, + // G/G_j = { x^(2^j) : x in (Z/pZ)^* }. + // We compute the square root of a first in G/G_e, then lift it to + // G/G_(e-1), etc., up to G/G_0. + // Start with b = a^((m+1)/2), then (a^-1*b^2)^(2^e) = 1, i.e. + // a = b^2 in G/G_e. + // Lifting from G/G_j to G/G_(j-1) is easy: Assume a = b^2 in G/G_j. + // If a = b^2 in G/G_(j-1), then nothing needs to be done. Else + // a^-1*b^2 is in G_j \ G_(j-1). If j=e, a^-1*b^2 is a non-square + // mod p, hence a is a non-square as well, contradiction. If jmodulus; + var uintL e = ord2(p-1); + var cl_I m = (p-1) >> e; + // p-1 = 2^e*m, m odd. + // We will have the invariant c = a^-1*b^2 in G/G_j. + var uintL j = e; + // Initialize b = a^((m+1)/2), c = a^m, but avoid to divide by a. + var cl_MI c = R->expt_pos(a,(m-1)>>1); + var cl_MI b = R->mul(a,c); + c = R->mul(b,c); + // Find h in G_e \ G_(e-1): h = h'^m, where h' is any non-square. + var cl_MI h; + if (e==1) + h = - R->one(); + else { + // Since this computation is a bit costly, we cache its result + // on the ring's property list. + static const cl_symbol key = (cl_symbol)(cl_string)"generator of 2-Sylow subgroup of (Z/pZ)^*"; + struct cl_sylow2gen_property : public cl_property { + SUBCLASS_cl_property(); + public: + cl_I h_rep; + // Constructor. + cl_sylow2gen_property (const cl_symbol& k, const cl_MI& h) : cl_property (k), h_rep (h.rep) {} + }; + var cl_sylow2gen_property* prop = (cl_sylow2gen_property*) R->get_property(key); + if (prop) + h = cl_MI(R,prop->h_rep); + else { + do { h = R->random(); } + until (jacobi(R->retract(h),p) == -1); + h = R->expt_pos(h,m); + R->add_property(new cl_sylow2gen_property(key,h)); + } + } + do { + // Now c = a^-1*b^2 in G_j, h in G_j \ G_(j-1). + // Determine the smallest i such that c in G_i. + var uintL i = 0; + var cl_MI ci = c; // c_i = c^(2^i) + for ( ; i < j; i++, ci = R->square(ci)) + if (ci == R->one()) + break; + if (i==j) + // Some problem: if j=e, a non-square, if j 0; count--) + h = R->square(h); + // Now h in G_(i+1) \ G_i. + b = R->mul(b,h); + h = R->square(h); + c = R->mul(c,h); + // Now c = a^-1*b^2 in G_(i-1), h in G_i \ G_(i-1). + j = i; + } while (j > 0); + if (R->square(b) != a) + // Problem again. + return new cl_composite_condition(p); + return sqrt_mod_p_t(2,b,-b); +} + +// Break-Even-Points (on a i486 with 33 MHz): +// Algorithm 1 fastest for p < 1500..2000 +// Algorithm 3 generally fastest for p > 2000. +// But the running time of algorithm 3 is proportional to e^2. +// For large e, algorithm 2 becomes faster. +// l=50 bits: for e >= 40 +// l=100 bits: for e >= 55 +// l=200 bits: for e >= 80 +// l=400 bits: for e >= 130 +// in general something like e > l/(log(l)/(2*log(2))-1). + +const sqrt_mod_p_t sqrt_mod_p (const cl_modint_ring& R, const cl_MI& a) +{ + if (!(a.ring() == R)) cl_abort(); + var cl_I& p = R->modulus; + var cl_I aa = R->retract(a); + switch (jacobi(aa,p)) { + case -1: // no solution + return sqrt_mod_p_t(0); + case 0: // gcd(aa,p) > 1 + if (zerop(a)) + // one solution + return sqrt_mod_p_t(1,a); + else + // found factor of p + return new cl_composite_condition(p,gcd(aa,p)); + case 1: // two solutions + break; + } + if (p < 2000) { + // Algorithm 1. + var cl_I x1 = search_sqrt(cl_I_to_UL(p),cl_I_to_UL(aa)); + var cl_I x2 = p-x1; + if (x1==x2) // can only happen when p = 2 + return sqrt_mod_p_t(1,R->canonhom(x1)); + else + return sqrt_mod_p_t(2,R->canonhom(x1),R->canonhom(x2)); + } + var uintL l = integer_length(p); + var uintL e = ord2(p-1); + //if (e > 30 && e > l/(log((double)l)*0.72-1)) + if (e > 30 && e > l/(log((double)l)*0.92-2.41)) + // Algorithm 2. + return cantor_zassenhaus_sqrt(R,a); + else + // Algorithm 3. + return tonelli_shanks_sqrt(R,a); +} diff --git a/src/polynomial/Makeflags b/src/polynomial/Makeflags new file mode 100644 index 0000000..ad57807 --- /dev/null +++ b/src/polynomial/Makeflags @@ -0,0 +1,3 @@ +# This file contains additional flags for the main Makefile. + +SUBDIR_INCLUDES = -I$(srcdir)/polynomial -I$(srcdir)/base diff --git a/src/polynomial/cl_UP.h b/src/polynomial/cl_UP.h new file mode 100644 index 0000000..a289f79 --- /dev/null +++ b/src/polynomial/cl_UP.h @@ -0,0 +1,31 @@ +// Internals of Univariate polynomials. + +#ifndef _CL_UP_H +#define _CL_UP_H + +#include "cl_univpoly.h" +#include "cl_output.h" + +extern cl_heap_univpoly_ring* cl_make_univpoly_ring (const cl_ring& r); + +struct cl_varname_property : public cl_property { + SUBCLASS_cl_property(); +public: + cl_symbol varname; + // Constructor. + cl_varname_property (const cl_symbol& k, const cl_symbol& v) : cl_property (k), varname (v) {} +}; + +// The property list key used to look up the varname. +extern cl_symbol cl_univpoly_varname_key; + +static inline const cl_string get_varname (cl_heap_univpoly_ring* UPR) +{ + cl_property* p = UPR->get_property(cl_univpoly_varname_key); + if (p) + return ((cl_varname_property*)p)->varname; + else + return cl_default_print_flags.univpoly_varname; +} + +#endif /* _CL_UP_H */ diff --git a/src/polynomial/elem/Makeflags b/src/polynomial/elem/Makeflags new file mode 100644 index 0000000..38911b4 --- /dev/null +++ b/src/polynomial/elem/Makeflags @@ -0,0 +1,5 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/polynomial/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/base/hash -I$(srcdir)/base/digitseq -I$(srcdir)/base/digit -Ibase $(GMP_INCLUDES) + diff --git a/src/polynomial/elem/cl_UP.cc b/src/polynomial/elem/cl_UP.cc new file mode 100644 index 0000000..a16d4d1 --- /dev/null +++ b/src/polynomial/elem/cl_UP.cc @@ -0,0 +1,73 @@ +// Univariate Polynomial operations. + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_UP) + +// Specification. +#define CL_GV_NO_RANGECHECKS +#define CL_SV_NO_RANGECHECKS +#include "cl_univpoly.h" +#include "cl_UP.h" + + +// Implementation. + +#include "cl_output.h" + +cl_symbol cl_univpoly_varname_key = (cl_symbol)(cl_string)"variable name"; + +// Prepare for looking into a polynomial. + #define DeclarePoly(type,x) \ + const type& __tmp_##x = *(const type*) &(x).rep; \ + const type& x = __tmp_##x; + #define DeclareMutablePoly(type,x) \ + type& __tmp_##x = *(type*) &(x).rep; \ + type& x = __tmp_##x; + +// Four different implementations of the polynomial operations, for efficiency: +#include "cl_UP_number.h" // polynomials over number rings +#include "cl_UP_MI.h" // polynomials over modular integer rings +#include "cl_UP_GF2.h" // polynomials over the modular integer ring GF(2) +#include "cl_UP_gen.h" // polynomials over all other rings + +cl_heap_univpoly_ring::cl_heap_univpoly_ring (const cl_ring& r, cl_univpoly_setops* setopv, cl_univpoly_addops* addopv, cl_univpoly_mulops* mulopv, cl_univpoly_modulops* modulopv, cl_univpoly_polyops* polyopv) + : setops (setopv), addops (addopv), mulops (mulopv), modulops (modulopv), polyops (polyopv), + _basering (r) +{ + refcount = 0; // will be incremented by the `cl_univpoly_ring' constructor + type = &cl_class_univpoly_ring; +} + +static void cl_univpoly_ring_destructor (cl_heap* pointer) +{ + (*(cl_heap_univpoly_ring*)pointer).~cl_heap_univpoly_ring(); +} + +cl_class cl_class_univpoly_ring = { + cl_univpoly_ring_destructor, + 0 +}; + +// This tells the compiler to put the `cl_heap_univpoly_ring' vtable +// into this file. +void cl_heap_univpoly_ring::dummy () {} + + +// Create a new univariate polynomial ring. + +cl_heap_univpoly_ring* cl_make_univpoly_ring (const cl_ring& r) +{ + if (r.pointer_type()->flags & cl_class_flags_number_ring) + return new cl_heap_num_univpoly_ring(r); + else if (r.pointer_type() == &cl_class_modint_ring) { + if (((cl_heap_modint_ring*)r.heappointer)->modulus == 2) + return new cl_heap_gf2_univpoly_ring(r); + else + return new cl_heap_modint_univpoly_ring(r); + } else + return new cl_heap_gen_univpoly_ring(r); +} + +CL_PROVIDE_END(cl_UP) diff --git a/src/polynomial/elem/cl_UP_GF2.h b/src/polynomial/elem/cl_UP_GF2.h new file mode 100644 index 0000000..cd95578 --- /dev/null +++ b/src/polynomial/elem/cl_UP_GF2.h @@ -0,0 +1,1044 @@ +// Univariate Polynomials over the ring GF(2) = Z/2Z. + +#include "cl_GV_modinteger.h" +#include "cl_modinteger.h" +#include "cl_GV_integer.h" +#include "cl_DS.h" +#include "cl_abort.h" + + +// This is actually defined in cl_GV_I.cc (*ugh*). +struct cl_heap_GV_I_bits1 : public cl_heap_GV_I { + uintD data[1]; +}; + +static cl_boolean gf2_equal (cl_heap_univpoly_ring* UPR, const _cl_UP& x, const _cl_UP& y) +{{ + DeclarePoly(cl_GV_MI,x); + DeclarePoly(cl_GV_MI,y); + unused UPR; + var const cl_heap_GV_I_bits1 * xv = (const cl_heap_GV_I_bits1 *) x.heappointer; + var const cl_heap_GV_I_bits1 * yv = (const cl_heap_GV_I_bits1 *) y.heappointer; + var uintL xlen = xv->v.length(); + var uintL ylen = yv->v.length(); + if (!(xlen == ylen)) + return cl_false; + // We can compare full words since unused bits in the last word are 0. + var uintL count = ceiling(xlen,intDsize); + if (compare_loop_up(xv->data,yv->data,count) != 0) + return cl_false; + return cl_true; +}} + +static const _cl_UP gf2_plus (cl_heap_univpoly_ring* UPR, const _cl_UP& x, const _cl_UP& y) +{{ + DeclarePoly(cl_GV_MI,x); + DeclarePoly(cl_GV_MI,y); + var const cl_heap_GV_I_bits1 * xv = (const cl_heap_GV_I_bits1 *) x.heappointer; + var const cl_heap_GV_I_bits1 * yv = (const cl_heap_GV_I_bits1 *) y.heappointer; + var uintL xlen = xv->v.length(); + var uintL ylen = yv->v.length(); + if (xlen == 0) + return _cl_UP(UPR, y); + if (ylen == 0) + return _cl_UP(UPR, x); + // Now xlen > 0, ylen > 0. + var cl_heap_modint_ring* R = TheModintRing(UPR->basering()); + if (xlen > ylen) { + var cl_GV_MI result = cl_GV_MI(xlen,R); + var cl_heap_GV_I_bits1 * rv = (cl_heap_GV_I_bits1 *) result.heappointer; + // Copy xv into rv. + copy_loop_up(xv->data,rv->data,ceiling(xlen,intDsize)); + // Add yv to rv. + xor_loop_up(rv->data,yv->data,ceiling(ylen,intDsize)); + return _cl_UP(UPR, result); + } + if (xlen < ylen) { + var cl_GV_MI result = cl_GV_MI(ylen,R); + var cl_heap_GV_I_bits1 * rv = (cl_heap_GV_I_bits1 *) result.heappointer; + // Copy yv into rv. + copy_loop_up(yv->data,rv->data,ceiling(ylen,intDsize)); + // Add xv to rv. + xor_loop_up(rv->data,xv->data,ceiling(xlen,intDsize)); + return _cl_UP(UPR, result); + } + // Now xlen = ylen > 0. Add and normalize simultaneously. + for (;;) { + var uintL index = floor(xlen-1,intDsize); + var uintD rword = xv->data[index] ^ yv->data[index]; + if (rword == 0) { + xlen = index*intDsize; + if (xlen == 0) + return _cl_UP(UPR, cl_null_GV_I); + } else { + xlen = index*intDsize; + integerlengthD(rword, xlen += ); + // Build result. + var cl_GV_MI result = cl_GV_MI(xlen,R); + var cl_heap_GV_I_bits1 * rv = (cl_heap_GV_I_bits1 *) result.heappointer; + copy_loop_up(xv->data,rv->data,index); + xor_loop_up(rv->data,yv->data,index); + rv->data[index] = rword; + return _cl_UP(UPR, result); + } + } +}} + +// In characteristic 2, x-y = x+y. +#define gf2_minus gf2_plus + +// In characteristic 2, -x = x. +static const _cl_UP gf2_uminus (cl_heap_univpoly_ring* UPR, const _cl_UP& x) +{ + unused UPR; + return x; +} + +#if !(defined(__sparc__) || defined(__sparc64__)) +// Multiplication of polynomials over GF(2) can unfortunately not profit +// from hardware multiply instructions. Use a table instead. +// This is a 2^8 x 2^4 table. Maybe a 2^6 x 2^6 table would be better? +// (LiDIA uses a 2^8 x 2^8 table, which is way too large.) +static uint16 gf2_mul_table[0x100][0x10] = + { + { 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000 }, + { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, + 0x008, 0x009, 0x00A, 0x00B, 0x00C, 0x00D, 0x00E, 0x00F }, + { 0x000, 0x002, 0x004, 0x006, 0x008, 0x00A, 0x00C, 0x00E, + 0x010, 0x012, 0x014, 0x016, 0x018, 0x01A, 0x01C, 0x01E }, + { 0x000, 0x003, 0x006, 0x005, 0x00C, 0x00F, 0x00A, 0x009, + 0x018, 0x01B, 0x01E, 0x01D, 0x014, 0x017, 0x012, 0x011 }, + { 0x000, 0x004, 0x008, 0x00C, 0x010, 0x014, 0x018, 0x01C, + 0x020, 0x024, 0x028, 0x02C, 0x030, 0x034, 0x038, 0x03C }, + { 0x000, 0x005, 0x00A, 0x00F, 0x014, 0x011, 0x01E, 0x01B, + 0x028, 0x02D, 0x022, 0x027, 0x03C, 0x039, 0x036, 0x033 }, + { 0x000, 0x006, 0x00C, 0x00A, 0x018, 0x01E, 0x014, 0x012, + 0x030, 0x036, 0x03C, 0x03A, 0x028, 0x02E, 0x024, 0x022 }, + { 0x000, 0x007, 0x00E, 0x009, 0x01C, 0x01B, 0x012, 0x015, + 0x038, 0x03F, 0x036, 0x031, 0x024, 0x023, 0x02A, 0x02D }, + { 0x000, 0x008, 0x010, 0x018, 0x020, 0x028, 0x030, 0x038, + 0x040, 0x048, 0x050, 0x058, 0x060, 0x068, 0x070, 0x078 }, + { 0x000, 0x009, 0x012, 0x01B, 0x024, 0x02D, 0x036, 0x03F, + 0x048, 0x041, 0x05A, 0x053, 0x06C, 0x065, 0x07E, 0x077 }, + { 0x000, 0x00A, 0x014, 0x01E, 0x028, 0x022, 0x03C, 0x036, + 0x050, 0x05A, 0x044, 0x04E, 0x078, 0x072, 0x06C, 0x066 }, + { 0x000, 0x00B, 0x016, 0x01D, 0x02C, 0x027, 0x03A, 0x031, + 0x058, 0x053, 0x04E, 0x045, 0x074, 0x07F, 0x062, 0x069 }, + { 0x000, 0x00C, 0x018, 0x014, 0x030, 0x03C, 0x028, 0x024, + 0x060, 0x06C, 0x078, 0x074, 0x050, 0x05C, 0x048, 0x044 }, + { 0x000, 0x00D, 0x01A, 0x017, 0x034, 0x039, 0x02E, 0x023, + 0x068, 0x065, 0x072, 0x07F, 0x05C, 0x051, 0x046, 0x04B }, + { 0x000, 0x00E, 0x01C, 0x012, 0x038, 0x036, 0x024, 0x02A, + 0x070, 0x07E, 0x06C, 0x062, 0x048, 0x046, 0x054, 0x05A }, + { 0x000, 0x00F, 0x01E, 0x011, 0x03C, 0x033, 0x022, 0x02D, + 0x078, 0x077, 0x066, 0x069, 0x044, 0x04B, 0x05A, 0x055 }, + { 0x000, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, + 0x080, 0x090, 0x0A0, 0x0B0, 0x0C0, 0x0D0, 0x0E0, 0x0F0 }, + { 0x000, 0x011, 0x022, 0x033, 0x044, 0x055, 0x066, 0x077, + 0x088, 0x099, 0x0AA, 0x0BB, 0x0CC, 0x0DD, 0x0EE, 0x0FF }, + { 0x000, 0x012, 0x024, 0x036, 0x048, 0x05A, 0x06C, 0x07E, + 0x090, 0x082, 0x0B4, 0x0A6, 0x0D8, 0x0CA, 0x0FC, 0x0EE }, + { 0x000, 0x013, 0x026, 0x035, 0x04C, 0x05F, 0x06A, 0x079, + 0x098, 0x08B, 0x0BE, 0x0AD, 0x0D4, 0x0C7, 0x0F2, 0x0E1 }, + { 0x000, 0x014, 0x028, 0x03C, 0x050, 0x044, 0x078, 0x06C, + 0x0A0, 0x0B4, 0x088, 0x09C, 0x0F0, 0x0E4, 0x0D8, 0x0CC }, + { 0x000, 0x015, 0x02A, 0x03F, 0x054, 0x041, 0x07E, 0x06B, + 0x0A8, 0x0BD, 0x082, 0x097, 0x0FC, 0x0E9, 0x0D6, 0x0C3 }, + { 0x000, 0x016, 0x02C, 0x03A, 0x058, 0x04E, 0x074, 0x062, + 0x0B0, 0x0A6, 0x09C, 0x08A, 0x0E8, 0x0FE, 0x0C4, 0x0D2 }, + { 0x000, 0x017, 0x02E, 0x039, 0x05C, 0x04B, 0x072, 0x065, + 0x0B8, 0x0AF, 0x096, 0x081, 0x0E4, 0x0F3, 0x0CA, 0x0DD }, + { 0x000, 0x018, 0x030, 0x028, 0x060, 0x078, 0x050, 0x048, + 0x0C0, 0x0D8, 0x0F0, 0x0E8, 0x0A0, 0x0B8, 0x090, 0x088 }, + { 0x000, 0x019, 0x032, 0x02B, 0x064, 0x07D, 0x056, 0x04F, + 0x0C8, 0x0D1, 0x0FA, 0x0E3, 0x0AC, 0x0B5, 0x09E, 0x087 }, + { 0x000, 0x01A, 0x034, 0x02E, 0x068, 0x072, 0x05C, 0x046, + 0x0D0, 0x0CA, 0x0E4, 0x0FE, 0x0B8, 0x0A2, 0x08C, 0x096 }, + { 0x000, 0x01B, 0x036, 0x02D, 0x06C, 0x077, 0x05A, 0x041, + 0x0D8, 0x0C3, 0x0EE, 0x0F5, 0x0B4, 0x0AF, 0x082, 0x099 }, + { 0x000, 0x01C, 0x038, 0x024, 0x070, 0x06C, 0x048, 0x054, + 0x0E0, 0x0FC, 0x0D8, 0x0C4, 0x090, 0x08C, 0x0A8, 0x0B4 }, + { 0x000, 0x01D, 0x03A, 0x027, 0x074, 0x069, 0x04E, 0x053, + 0x0E8, 0x0F5, 0x0D2, 0x0CF, 0x09C, 0x081, 0x0A6, 0x0BB }, + { 0x000, 0x01E, 0x03C, 0x022, 0x078, 0x066, 0x044, 0x05A, + 0x0F0, 0x0EE, 0x0CC, 0x0D2, 0x088, 0x096, 0x0B4, 0x0AA }, + { 0x000, 0x01F, 0x03E, 0x021, 0x07C, 0x063, 0x042, 0x05D, + 0x0F8, 0x0E7, 0x0C6, 0x0D9, 0x084, 0x09B, 0x0BA, 0x0A5 }, + { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0A0, 0x0C0, 0x0E0, + 0x100, 0x120, 0x140, 0x160, 0x180, 0x1A0, 0x1C0, 0x1E0 }, + { 0x000, 0x021, 0x042, 0x063, 0x084, 0x0A5, 0x0C6, 0x0E7, + 0x108, 0x129, 0x14A, 0x16B, 0x18C, 0x1AD, 0x1CE, 0x1EF }, + { 0x000, 0x022, 0x044, 0x066, 0x088, 0x0AA, 0x0CC, 0x0EE, + 0x110, 0x132, 0x154, 0x176, 0x198, 0x1BA, 0x1DC, 0x1FE }, + { 0x000, 0x023, 0x046, 0x065, 0x08C, 0x0AF, 0x0CA, 0x0E9, + 0x118, 0x13B, 0x15E, 0x17D, 0x194, 0x1B7, 0x1D2, 0x1F1 }, + { 0x000, 0x024, 0x048, 0x06C, 0x090, 0x0B4, 0x0D8, 0x0FC, + 0x120, 0x104, 0x168, 0x14C, 0x1B0, 0x194, 0x1F8, 0x1DC }, + { 0x000, 0x025, 0x04A, 0x06F, 0x094, 0x0B1, 0x0DE, 0x0FB, + 0x128, 0x10D, 0x162, 0x147, 0x1BC, 0x199, 0x1F6, 0x1D3 }, + { 0x000, 0x026, 0x04C, 0x06A, 0x098, 0x0BE, 0x0D4, 0x0F2, + 0x130, 0x116, 0x17C, 0x15A, 0x1A8, 0x18E, 0x1E4, 0x1C2 }, + { 0x000, 0x027, 0x04E, 0x069, 0x09C, 0x0BB, 0x0D2, 0x0F5, + 0x138, 0x11F, 0x176, 0x151, 0x1A4, 0x183, 0x1EA, 0x1CD }, + { 0x000, 0x028, 0x050, 0x078, 0x0A0, 0x088, 0x0F0, 0x0D8, + 0x140, 0x168, 0x110, 0x138, 0x1E0, 0x1C8, 0x1B0, 0x198 }, + { 0x000, 0x029, 0x052, 0x07B, 0x0A4, 0x08D, 0x0F6, 0x0DF, + 0x148, 0x161, 0x11A, 0x133, 0x1EC, 0x1C5, 0x1BE, 0x197 }, + { 0x000, 0x02A, 0x054, 0x07E, 0x0A8, 0x082, 0x0FC, 0x0D6, + 0x150, 0x17A, 0x104, 0x12E, 0x1F8, 0x1D2, 0x1AC, 0x186 }, + { 0x000, 0x02B, 0x056, 0x07D, 0x0AC, 0x087, 0x0FA, 0x0D1, + 0x158, 0x173, 0x10E, 0x125, 0x1F4, 0x1DF, 0x1A2, 0x189 }, + { 0x000, 0x02C, 0x058, 0x074, 0x0B0, 0x09C, 0x0E8, 0x0C4, + 0x160, 0x14C, 0x138, 0x114, 0x1D0, 0x1FC, 0x188, 0x1A4 }, + { 0x000, 0x02D, 0x05A, 0x077, 0x0B4, 0x099, 0x0EE, 0x0C3, + 0x168, 0x145, 0x132, 0x11F, 0x1DC, 0x1F1, 0x186, 0x1AB }, + { 0x000, 0x02E, 0x05C, 0x072, 0x0B8, 0x096, 0x0E4, 0x0CA, + 0x170, 0x15E, 0x12C, 0x102, 0x1C8, 0x1E6, 0x194, 0x1BA }, + { 0x000, 0x02F, 0x05E, 0x071, 0x0BC, 0x093, 0x0E2, 0x0CD, + 0x178, 0x157, 0x126, 0x109, 0x1C4, 0x1EB, 0x19A, 0x1B5 }, + { 0x000, 0x030, 0x060, 0x050, 0x0C0, 0x0F0, 0x0A0, 0x090, + 0x180, 0x1B0, 0x1E0, 0x1D0, 0x140, 0x170, 0x120, 0x110 }, + { 0x000, 0x031, 0x062, 0x053, 0x0C4, 0x0F5, 0x0A6, 0x097, + 0x188, 0x1B9, 0x1EA, 0x1DB, 0x14C, 0x17D, 0x12E, 0x11F }, + { 0x000, 0x032, 0x064, 0x056, 0x0C8, 0x0FA, 0x0AC, 0x09E, + 0x190, 0x1A2, 0x1F4, 0x1C6, 0x158, 0x16A, 0x13C, 0x10E }, + { 0x000, 0x033, 0x066, 0x055, 0x0CC, 0x0FF, 0x0AA, 0x099, + 0x198, 0x1AB, 0x1FE, 0x1CD, 0x154, 0x167, 0x132, 0x101 }, + { 0x000, 0x034, 0x068, 0x05C, 0x0D0, 0x0E4, 0x0B8, 0x08C, + 0x1A0, 0x194, 0x1C8, 0x1FC, 0x170, 0x144, 0x118, 0x12C }, + { 0x000, 0x035, 0x06A, 0x05F, 0x0D4, 0x0E1, 0x0BE, 0x08B, + 0x1A8, 0x19D, 0x1C2, 0x1F7, 0x17C, 0x149, 0x116, 0x123 }, + { 0x000, 0x036, 0x06C, 0x05A, 0x0D8, 0x0EE, 0x0B4, 0x082, + 0x1B0, 0x186, 0x1DC, 0x1EA, 0x168, 0x15E, 0x104, 0x132 }, + { 0x000, 0x037, 0x06E, 0x059, 0x0DC, 0x0EB, 0x0B2, 0x085, + 0x1B8, 0x18F, 0x1D6, 0x1E1, 0x164, 0x153, 0x10A, 0x13D }, + { 0x000, 0x038, 0x070, 0x048, 0x0E0, 0x0D8, 0x090, 0x0A8, + 0x1C0, 0x1F8, 0x1B0, 0x188, 0x120, 0x118, 0x150, 0x168 }, + { 0x000, 0x039, 0x072, 0x04B, 0x0E4, 0x0DD, 0x096, 0x0AF, + 0x1C8, 0x1F1, 0x1BA, 0x183, 0x12C, 0x115, 0x15E, 0x167 }, + { 0x000, 0x03A, 0x074, 0x04E, 0x0E8, 0x0D2, 0x09C, 0x0A6, + 0x1D0, 0x1EA, 0x1A4, 0x19E, 0x138, 0x102, 0x14C, 0x176 }, + { 0x000, 0x03B, 0x076, 0x04D, 0x0EC, 0x0D7, 0x09A, 0x0A1, + 0x1D8, 0x1E3, 0x1AE, 0x195, 0x134, 0x10F, 0x142, 0x179 }, + { 0x000, 0x03C, 0x078, 0x044, 0x0F0, 0x0CC, 0x088, 0x0B4, + 0x1E0, 0x1DC, 0x198, 0x1A4, 0x110, 0x12C, 0x168, 0x154 }, + { 0x000, 0x03D, 0x07A, 0x047, 0x0F4, 0x0C9, 0x08E, 0x0B3, + 0x1E8, 0x1D5, 0x192, 0x1AF, 0x11C, 0x121, 0x166, 0x15B }, + { 0x000, 0x03E, 0x07C, 0x042, 0x0F8, 0x0C6, 0x084, 0x0BA, + 0x1F0, 0x1CE, 0x18C, 0x1B2, 0x108, 0x136, 0x174, 0x14A }, + { 0x000, 0x03F, 0x07E, 0x041, 0x0FC, 0x0C3, 0x082, 0x0BD, + 0x1F8, 0x1C7, 0x186, 0x1B9, 0x104, 0x13B, 0x17A, 0x145 }, + { 0x000, 0x040, 0x080, 0x0C0, 0x100, 0x140, 0x180, 0x1C0, + 0x200, 0x240, 0x280, 0x2C0, 0x300, 0x340, 0x380, 0x3C0 }, + { 0x000, 0x041, 0x082, 0x0C3, 0x104, 0x145, 0x186, 0x1C7, + 0x208, 0x249, 0x28A, 0x2CB, 0x30C, 0x34D, 0x38E, 0x3CF }, + { 0x000, 0x042, 0x084, 0x0C6, 0x108, 0x14A, 0x18C, 0x1CE, + 0x210, 0x252, 0x294, 0x2D6, 0x318, 0x35A, 0x39C, 0x3DE }, + { 0x000, 0x043, 0x086, 0x0C5, 0x10C, 0x14F, 0x18A, 0x1C9, + 0x218, 0x25B, 0x29E, 0x2DD, 0x314, 0x357, 0x392, 0x3D1 }, + { 0x000, 0x044, 0x088, 0x0CC, 0x110, 0x154, 0x198, 0x1DC, + 0x220, 0x264, 0x2A8, 0x2EC, 0x330, 0x374, 0x3B8, 0x3FC }, + { 0x000, 0x045, 0x08A, 0x0CF, 0x114, 0x151, 0x19E, 0x1DB, + 0x228, 0x26D, 0x2A2, 0x2E7, 0x33C, 0x379, 0x3B6, 0x3F3 }, + { 0x000, 0x046, 0x08C, 0x0CA, 0x118, 0x15E, 0x194, 0x1D2, + 0x230, 0x276, 0x2BC, 0x2FA, 0x328, 0x36E, 0x3A4, 0x3E2 }, + { 0x000, 0x047, 0x08E, 0x0C9, 0x11C, 0x15B, 0x192, 0x1D5, + 0x238, 0x27F, 0x2B6, 0x2F1, 0x324, 0x363, 0x3AA, 0x3ED }, + { 0x000, 0x048, 0x090, 0x0D8, 0x120, 0x168, 0x1B0, 0x1F8, + 0x240, 0x208, 0x2D0, 0x298, 0x360, 0x328, 0x3F0, 0x3B8 }, + { 0x000, 0x049, 0x092, 0x0DB, 0x124, 0x16D, 0x1B6, 0x1FF, + 0x248, 0x201, 0x2DA, 0x293, 0x36C, 0x325, 0x3FE, 0x3B7 }, + { 0x000, 0x04A, 0x094, 0x0DE, 0x128, 0x162, 0x1BC, 0x1F6, + 0x250, 0x21A, 0x2C4, 0x28E, 0x378, 0x332, 0x3EC, 0x3A6 }, + { 0x000, 0x04B, 0x096, 0x0DD, 0x12C, 0x167, 0x1BA, 0x1F1, + 0x258, 0x213, 0x2CE, 0x285, 0x374, 0x33F, 0x3E2, 0x3A9 }, + { 0x000, 0x04C, 0x098, 0x0D4, 0x130, 0x17C, 0x1A8, 0x1E4, + 0x260, 0x22C, 0x2F8, 0x2B4, 0x350, 0x31C, 0x3C8, 0x384 }, + { 0x000, 0x04D, 0x09A, 0x0D7, 0x134, 0x179, 0x1AE, 0x1E3, + 0x268, 0x225, 0x2F2, 0x2BF, 0x35C, 0x311, 0x3C6, 0x38B }, + { 0x000, 0x04E, 0x09C, 0x0D2, 0x138, 0x176, 0x1A4, 0x1EA, + 0x270, 0x23E, 0x2EC, 0x2A2, 0x348, 0x306, 0x3D4, 0x39A }, + { 0x000, 0x04F, 0x09E, 0x0D1, 0x13C, 0x173, 0x1A2, 0x1ED, + 0x278, 0x237, 0x2E6, 0x2A9, 0x344, 0x30B, 0x3DA, 0x395 }, + { 0x000, 0x050, 0x0A0, 0x0F0, 0x140, 0x110, 0x1E0, 0x1B0, + 0x280, 0x2D0, 0x220, 0x270, 0x3C0, 0x390, 0x360, 0x330 }, + { 0x000, 0x051, 0x0A2, 0x0F3, 0x144, 0x115, 0x1E6, 0x1B7, + 0x288, 0x2D9, 0x22A, 0x27B, 0x3CC, 0x39D, 0x36E, 0x33F }, + { 0x000, 0x052, 0x0A4, 0x0F6, 0x148, 0x11A, 0x1EC, 0x1BE, + 0x290, 0x2C2, 0x234, 0x266, 0x3D8, 0x38A, 0x37C, 0x32E }, + { 0x000, 0x053, 0x0A6, 0x0F5, 0x14C, 0x11F, 0x1EA, 0x1B9, + 0x298, 0x2CB, 0x23E, 0x26D, 0x3D4, 0x387, 0x372, 0x321 }, + { 0x000, 0x054, 0x0A8, 0x0FC, 0x150, 0x104, 0x1F8, 0x1AC, + 0x2A0, 0x2F4, 0x208, 0x25C, 0x3F0, 0x3A4, 0x358, 0x30C }, + { 0x000, 0x055, 0x0AA, 0x0FF, 0x154, 0x101, 0x1FE, 0x1AB, + 0x2A8, 0x2FD, 0x202, 0x257, 0x3FC, 0x3A9, 0x356, 0x303 }, + { 0x000, 0x056, 0x0AC, 0x0FA, 0x158, 0x10E, 0x1F4, 0x1A2, + 0x2B0, 0x2E6, 0x21C, 0x24A, 0x3E8, 0x3BE, 0x344, 0x312 }, + { 0x000, 0x057, 0x0AE, 0x0F9, 0x15C, 0x10B, 0x1F2, 0x1A5, + 0x2B8, 0x2EF, 0x216, 0x241, 0x3E4, 0x3B3, 0x34A, 0x31D }, + { 0x000, 0x058, 0x0B0, 0x0E8, 0x160, 0x138, 0x1D0, 0x188, + 0x2C0, 0x298, 0x270, 0x228, 0x3A0, 0x3F8, 0x310, 0x348 }, + { 0x000, 0x059, 0x0B2, 0x0EB, 0x164, 0x13D, 0x1D6, 0x18F, + 0x2C8, 0x291, 0x27A, 0x223, 0x3AC, 0x3F5, 0x31E, 0x347 }, + { 0x000, 0x05A, 0x0B4, 0x0EE, 0x168, 0x132, 0x1DC, 0x186, + 0x2D0, 0x28A, 0x264, 0x23E, 0x3B8, 0x3E2, 0x30C, 0x356 }, + { 0x000, 0x05B, 0x0B6, 0x0ED, 0x16C, 0x137, 0x1DA, 0x181, + 0x2D8, 0x283, 0x26E, 0x235, 0x3B4, 0x3EF, 0x302, 0x359 }, + { 0x000, 0x05C, 0x0B8, 0x0E4, 0x170, 0x12C, 0x1C8, 0x194, + 0x2E0, 0x2BC, 0x258, 0x204, 0x390, 0x3CC, 0x328, 0x374 }, + { 0x000, 0x05D, 0x0BA, 0x0E7, 0x174, 0x129, 0x1CE, 0x193, + 0x2E8, 0x2B5, 0x252, 0x20F, 0x39C, 0x3C1, 0x326, 0x37B }, + { 0x000, 0x05E, 0x0BC, 0x0E2, 0x178, 0x126, 0x1C4, 0x19A, + 0x2F0, 0x2AE, 0x24C, 0x212, 0x388, 0x3D6, 0x334, 0x36A }, + { 0x000, 0x05F, 0x0BE, 0x0E1, 0x17C, 0x123, 0x1C2, 0x19D, + 0x2F8, 0x2A7, 0x246, 0x219, 0x384, 0x3DB, 0x33A, 0x365 }, + { 0x000, 0x060, 0x0C0, 0x0A0, 0x180, 0x1E0, 0x140, 0x120, + 0x300, 0x360, 0x3C0, 0x3A0, 0x280, 0x2E0, 0x240, 0x220 }, + { 0x000, 0x061, 0x0C2, 0x0A3, 0x184, 0x1E5, 0x146, 0x127, + 0x308, 0x369, 0x3CA, 0x3AB, 0x28C, 0x2ED, 0x24E, 0x22F }, + { 0x000, 0x062, 0x0C4, 0x0A6, 0x188, 0x1EA, 0x14C, 0x12E, + 0x310, 0x372, 0x3D4, 0x3B6, 0x298, 0x2FA, 0x25C, 0x23E }, + { 0x000, 0x063, 0x0C6, 0x0A5, 0x18C, 0x1EF, 0x14A, 0x129, + 0x318, 0x37B, 0x3DE, 0x3BD, 0x294, 0x2F7, 0x252, 0x231 }, + { 0x000, 0x064, 0x0C8, 0x0AC, 0x190, 0x1F4, 0x158, 0x13C, + 0x320, 0x344, 0x3E8, 0x38C, 0x2B0, 0x2D4, 0x278, 0x21C }, + { 0x000, 0x065, 0x0CA, 0x0AF, 0x194, 0x1F1, 0x15E, 0x13B, + 0x328, 0x34D, 0x3E2, 0x387, 0x2BC, 0x2D9, 0x276, 0x213 }, + { 0x000, 0x066, 0x0CC, 0x0AA, 0x198, 0x1FE, 0x154, 0x132, + 0x330, 0x356, 0x3FC, 0x39A, 0x2A8, 0x2CE, 0x264, 0x202 }, + { 0x000, 0x067, 0x0CE, 0x0A9, 0x19C, 0x1FB, 0x152, 0x135, + 0x338, 0x35F, 0x3F6, 0x391, 0x2A4, 0x2C3, 0x26A, 0x20D }, + { 0x000, 0x068, 0x0D0, 0x0B8, 0x1A0, 0x1C8, 0x170, 0x118, + 0x340, 0x328, 0x390, 0x3F8, 0x2E0, 0x288, 0x230, 0x258 }, + { 0x000, 0x069, 0x0D2, 0x0BB, 0x1A4, 0x1CD, 0x176, 0x11F, + 0x348, 0x321, 0x39A, 0x3F3, 0x2EC, 0x285, 0x23E, 0x257 }, + { 0x000, 0x06A, 0x0D4, 0x0BE, 0x1A8, 0x1C2, 0x17C, 0x116, + 0x350, 0x33A, 0x384, 0x3EE, 0x2F8, 0x292, 0x22C, 0x246 }, + { 0x000, 0x06B, 0x0D6, 0x0BD, 0x1AC, 0x1C7, 0x17A, 0x111, + 0x358, 0x333, 0x38E, 0x3E5, 0x2F4, 0x29F, 0x222, 0x249 }, + { 0x000, 0x06C, 0x0D8, 0x0B4, 0x1B0, 0x1DC, 0x168, 0x104, + 0x360, 0x30C, 0x3B8, 0x3D4, 0x2D0, 0x2BC, 0x208, 0x264 }, + { 0x000, 0x06D, 0x0DA, 0x0B7, 0x1B4, 0x1D9, 0x16E, 0x103, + 0x368, 0x305, 0x3B2, 0x3DF, 0x2DC, 0x2B1, 0x206, 0x26B }, + { 0x000, 0x06E, 0x0DC, 0x0B2, 0x1B8, 0x1D6, 0x164, 0x10A, + 0x370, 0x31E, 0x3AC, 0x3C2, 0x2C8, 0x2A6, 0x214, 0x27A }, + { 0x000, 0x06F, 0x0DE, 0x0B1, 0x1BC, 0x1D3, 0x162, 0x10D, + 0x378, 0x317, 0x3A6, 0x3C9, 0x2C4, 0x2AB, 0x21A, 0x275 }, + { 0x000, 0x070, 0x0E0, 0x090, 0x1C0, 0x1B0, 0x120, 0x150, + 0x380, 0x3F0, 0x360, 0x310, 0x240, 0x230, 0x2A0, 0x2D0 }, + { 0x000, 0x071, 0x0E2, 0x093, 0x1C4, 0x1B5, 0x126, 0x157, + 0x388, 0x3F9, 0x36A, 0x31B, 0x24C, 0x23D, 0x2AE, 0x2DF }, + { 0x000, 0x072, 0x0E4, 0x096, 0x1C8, 0x1BA, 0x12C, 0x15E, + 0x390, 0x3E2, 0x374, 0x306, 0x258, 0x22A, 0x2BC, 0x2CE }, + { 0x000, 0x073, 0x0E6, 0x095, 0x1CC, 0x1BF, 0x12A, 0x159, + 0x398, 0x3EB, 0x37E, 0x30D, 0x254, 0x227, 0x2B2, 0x2C1 }, + { 0x000, 0x074, 0x0E8, 0x09C, 0x1D0, 0x1A4, 0x138, 0x14C, + 0x3A0, 0x3D4, 0x348, 0x33C, 0x270, 0x204, 0x298, 0x2EC }, + { 0x000, 0x075, 0x0EA, 0x09F, 0x1D4, 0x1A1, 0x13E, 0x14B, + 0x3A8, 0x3DD, 0x342, 0x337, 0x27C, 0x209, 0x296, 0x2E3 }, + { 0x000, 0x076, 0x0EC, 0x09A, 0x1D8, 0x1AE, 0x134, 0x142, + 0x3B0, 0x3C6, 0x35C, 0x32A, 0x268, 0x21E, 0x284, 0x2F2 }, + { 0x000, 0x077, 0x0EE, 0x099, 0x1DC, 0x1AB, 0x132, 0x145, + 0x3B8, 0x3CF, 0x356, 0x321, 0x264, 0x213, 0x28A, 0x2FD }, + { 0x000, 0x078, 0x0F0, 0x088, 0x1E0, 0x198, 0x110, 0x168, + 0x3C0, 0x3B8, 0x330, 0x348, 0x220, 0x258, 0x2D0, 0x2A8 }, + { 0x000, 0x079, 0x0F2, 0x08B, 0x1E4, 0x19D, 0x116, 0x16F, + 0x3C8, 0x3B1, 0x33A, 0x343, 0x22C, 0x255, 0x2DE, 0x2A7 }, + { 0x000, 0x07A, 0x0F4, 0x08E, 0x1E8, 0x192, 0x11C, 0x166, + 0x3D0, 0x3AA, 0x324, 0x35E, 0x238, 0x242, 0x2CC, 0x2B6 }, + { 0x000, 0x07B, 0x0F6, 0x08D, 0x1EC, 0x197, 0x11A, 0x161, + 0x3D8, 0x3A3, 0x32E, 0x355, 0x234, 0x24F, 0x2C2, 0x2B9 }, + { 0x000, 0x07C, 0x0F8, 0x084, 0x1F0, 0x18C, 0x108, 0x174, + 0x3E0, 0x39C, 0x318, 0x364, 0x210, 0x26C, 0x2E8, 0x294 }, + { 0x000, 0x07D, 0x0FA, 0x087, 0x1F4, 0x189, 0x10E, 0x173, + 0x3E8, 0x395, 0x312, 0x36F, 0x21C, 0x261, 0x2E6, 0x29B }, + { 0x000, 0x07E, 0x0FC, 0x082, 0x1F8, 0x186, 0x104, 0x17A, + 0x3F0, 0x38E, 0x30C, 0x372, 0x208, 0x276, 0x2F4, 0x28A }, + { 0x000, 0x07F, 0x0FE, 0x081, 0x1FC, 0x183, 0x102, 0x17D, + 0x3F8, 0x387, 0x306, 0x379, 0x204, 0x27B, 0x2FA, 0x285 }, + { 0x000, 0x080, 0x100, 0x180, 0x200, 0x280, 0x300, 0x380, + 0x400, 0x480, 0x500, 0x580, 0x600, 0x680, 0x700, 0x780 }, + { 0x000, 0x081, 0x102, 0x183, 0x204, 0x285, 0x306, 0x387, + 0x408, 0x489, 0x50A, 0x58B, 0x60C, 0x68D, 0x70E, 0x78F }, + { 0x000, 0x082, 0x104, 0x186, 0x208, 0x28A, 0x30C, 0x38E, + 0x410, 0x492, 0x514, 0x596, 0x618, 0x69A, 0x71C, 0x79E }, + { 0x000, 0x083, 0x106, 0x185, 0x20C, 0x28F, 0x30A, 0x389, + 0x418, 0x49B, 0x51E, 0x59D, 0x614, 0x697, 0x712, 0x791 }, + { 0x000, 0x084, 0x108, 0x18C, 0x210, 0x294, 0x318, 0x39C, + 0x420, 0x4A4, 0x528, 0x5AC, 0x630, 0x6B4, 0x738, 0x7BC }, + { 0x000, 0x085, 0x10A, 0x18F, 0x214, 0x291, 0x31E, 0x39B, + 0x428, 0x4AD, 0x522, 0x5A7, 0x63C, 0x6B9, 0x736, 0x7B3 }, + { 0x000, 0x086, 0x10C, 0x18A, 0x218, 0x29E, 0x314, 0x392, + 0x430, 0x4B6, 0x53C, 0x5BA, 0x628, 0x6AE, 0x724, 0x7A2 }, + { 0x000, 0x087, 0x10E, 0x189, 0x21C, 0x29B, 0x312, 0x395, + 0x438, 0x4BF, 0x536, 0x5B1, 0x624, 0x6A3, 0x72A, 0x7AD }, + { 0x000, 0x088, 0x110, 0x198, 0x220, 0x2A8, 0x330, 0x3B8, + 0x440, 0x4C8, 0x550, 0x5D8, 0x660, 0x6E8, 0x770, 0x7F8 }, + { 0x000, 0x089, 0x112, 0x19B, 0x224, 0x2AD, 0x336, 0x3BF, + 0x448, 0x4C1, 0x55A, 0x5D3, 0x66C, 0x6E5, 0x77E, 0x7F7 }, + { 0x000, 0x08A, 0x114, 0x19E, 0x228, 0x2A2, 0x33C, 0x3B6, + 0x450, 0x4DA, 0x544, 0x5CE, 0x678, 0x6F2, 0x76C, 0x7E6 }, + { 0x000, 0x08B, 0x116, 0x19D, 0x22C, 0x2A7, 0x33A, 0x3B1, + 0x458, 0x4D3, 0x54E, 0x5C5, 0x674, 0x6FF, 0x762, 0x7E9 }, + { 0x000, 0x08C, 0x118, 0x194, 0x230, 0x2BC, 0x328, 0x3A4, + 0x460, 0x4EC, 0x578, 0x5F4, 0x650, 0x6DC, 0x748, 0x7C4 }, + { 0x000, 0x08D, 0x11A, 0x197, 0x234, 0x2B9, 0x32E, 0x3A3, + 0x468, 0x4E5, 0x572, 0x5FF, 0x65C, 0x6D1, 0x746, 0x7CB }, + { 0x000, 0x08E, 0x11C, 0x192, 0x238, 0x2B6, 0x324, 0x3AA, + 0x470, 0x4FE, 0x56C, 0x5E2, 0x648, 0x6C6, 0x754, 0x7DA }, + { 0x000, 0x08F, 0x11E, 0x191, 0x23C, 0x2B3, 0x322, 0x3AD, + 0x478, 0x4F7, 0x566, 0x5E9, 0x644, 0x6CB, 0x75A, 0x7D5 }, + { 0x000, 0x090, 0x120, 0x1B0, 0x240, 0x2D0, 0x360, 0x3F0, + 0x480, 0x410, 0x5A0, 0x530, 0x6C0, 0x650, 0x7E0, 0x770 }, + { 0x000, 0x091, 0x122, 0x1B3, 0x244, 0x2D5, 0x366, 0x3F7, + 0x488, 0x419, 0x5AA, 0x53B, 0x6CC, 0x65D, 0x7EE, 0x77F }, + { 0x000, 0x092, 0x124, 0x1B6, 0x248, 0x2DA, 0x36C, 0x3FE, + 0x490, 0x402, 0x5B4, 0x526, 0x6D8, 0x64A, 0x7FC, 0x76E }, + { 0x000, 0x093, 0x126, 0x1B5, 0x24C, 0x2DF, 0x36A, 0x3F9, + 0x498, 0x40B, 0x5BE, 0x52D, 0x6D4, 0x647, 0x7F2, 0x761 }, + { 0x000, 0x094, 0x128, 0x1BC, 0x250, 0x2C4, 0x378, 0x3EC, + 0x4A0, 0x434, 0x588, 0x51C, 0x6F0, 0x664, 0x7D8, 0x74C }, + { 0x000, 0x095, 0x12A, 0x1BF, 0x254, 0x2C1, 0x37E, 0x3EB, + 0x4A8, 0x43D, 0x582, 0x517, 0x6FC, 0x669, 0x7D6, 0x743 }, + { 0x000, 0x096, 0x12C, 0x1BA, 0x258, 0x2CE, 0x374, 0x3E2, + 0x4B0, 0x426, 0x59C, 0x50A, 0x6E8, 0x67E, 0x7C4, 0x752 }, + { 0x000, 0x097, 0x12E, 0x1B9, 0x25C, 0x2CB, 0x372, 0x3E5, + 0x4B8, 0x42F, 0x596, 0x501, 0x6E4, 0x673, 0x7CA, 0x75D }, + { 0x000, 0x098, 0x130, 0x1A8, 0x260, 0x2F8, 0x350, 0x3C8, + 0x4C0, 0x458, 0x5F0, 0x568, 0x6A0, 0x638, 0x790, 0x708 }, + { 0x000, 0x099, 0x132, 0x1AB, 0x264, 0x2FD, 0x356, 0x3CF, + 0x4C8, 0x451, 0x5FA, 0x563, 0x6AC, 0x635, 0x79E, 0x707 }, + { 0x000, 0x09A, 0x134, 0x1AE, 0x268, 0x2F2, 0x35C, 0x3C6, + 0x4D0, 0x44A, 0x5E4, 0x57E, 0x6B8, 0x622, 0x78C, 0x716 }, + { 0x000, 0x09B, 0x136, 0x1AD, 0x26C, 0x2F7, 0x35A, 0x3C1, + 0x4D8, 0x443, 0x5EE, 0x575, 0x6B4, 0x62F, 0x782, 0x719 }, + { 0x000, 0x09C, 0x138, 0x1A4, 0x270, 0x2EC, 0x348, 0x3D4, + 0x4E0, 0x47C, 0x5D8, 0x544, 0x690, 0x60C, 0x7A8, 0x734 }, + { 0x000, 0x09D, 0x13A, 0x1A7, 0x274, 0x2E9, 0x34E, 0x3D3, + 0x4E8, 0x475, 0x5D2, 0x54F, 0x69C, 0x601, 0x7A6, 0x73B }, + { 0x000, 0x09E, 0x13C, 0x1A2, 0x278, 0x2E6, 0x344, 0x3DA, + 0x4F0, 0x46E, 0x5CC, 0x552, 0x688, 0x616, 0x7B4, 0x72A }, + { 0x000, 0x09F, 0x13E, 0x1A1, 0x27C, 0x2E3, 0x342, 0x3DD, + 0x4F8, 0x467, 0x5C6, 0x559, 0x684, 0x61B, 0x7BA, 0x725 }, + { 0x000, 0x0A0, 0x140, 0x1E0, 0x280, 0x220, 0x3C0, 0x360, + 0x500, 0x5A0, 0x440, 0x4E0, 0x780, 0x720, 0x6C0, 0x660 }, + { 0x000, 0x0A1, 0x142, 0x1E3, 0x284, 0x225, 0x3C6, 0x367, + 0x508, 0x5A9, 0x44A, 0x4EB, 0x78C, 0x72D, 0x6CE, 0x66F }, + { 0x000, 0x0A2, 0x144, 0x1E6, 0x288, 0x22A, 0x3CC, 0x36E, + 0x510, 0x5B2, 0x454, 0x4F6, 0x798, 0x73A, 0x6DC, 0x67E }, + { 0x000, 0x0A3, 0x146, 0x1E5, 0x28C, 0x22F, 0x3CA, 0x369, + 0x518, 0x5BB, 0x45E, 0x4FD, 0x794, 0x737, 0x6D2, 0x671 }, + { 0x000, 0x0A4, 0x148, 0x1EC, 0x290, 0x234, 0x3D8, 0x37C, + 0x520, 0x584, 0x468, 0x4CC, 0x7B0, 0x714, 0x6F8, 0x65C }, + { 0x000, 0x0A5, 0x14A, 0x1EF, 0x294, 0x231, 0x3DE, 0x37B, + 0x528, 0x58D, 0x462, 0x4C7, 0x7BC, 0x719, 0x6F6, 0x653 }, + { 0x000, 0x0A6, 0x14C, 0x1EA, 0x298, 0x23E, 0x3D4, 0x372, + 0x530, 0x596, 0x47C, 0x4DA, 0x7A8, 0x70E, 0x6E4, 0x642 }, + { 0x000, 0x0A7, 0x14E, 0x1E9, 0x29C, 0x23B, 0x3D2, 0x375, + 0x538, 0x59F, 0x476, 0x4D1, 0x7A4, 0x703, 0x6EA, 0x64D }, + { 0x000, 0x0A8, 0x150, 0x1F8, 0x2A0, 0x208, 0x3F0, 0x358, + 0x540, 0x5E8, 0x410, 0x4B8, 0x7E0, 0x748, 0x6B0, 0x618 }, + { 0x000, 0x0A9, 0x152, 0x1FB, 0x2A4, 0x20D, 0x3F6, 0x35F, + 0x548, 0x5E1, 0x41A, 0x4B3, 0x7EC, 0x745, 0x6BE, 0x617 }, + { 0x000, 0x0AA, 0x154, 0x1FE, 0x2A8, 0x202, 0x3FC, 0x356, + 0x550, 0x5FA, 0x404, 0x4AE, 0x7F8, 0x752, 0x6AC, 0x606 }, + { 0x000, 0x0AB, 0x156, 0x1FD, 0x2AC, 0x207, 0x3FA, 0x351, + 0x558, 0x5F3, 0x40E, 0x4A5, 0x7F4, 0x75F, 0x6A2, 0x609 }, + { 0x000, 0x0AC, 0x158, 0x1F4, 0x2B0, 0x21C, 0x3E8, 0x344, + 0x560, 0x5CC, 0x438, 0x494, 0x7D0, 0x77C, 0x688, 0x624 }, + { 0x000, 0x0AD, 0x15A, 0x1F7, 0x2B4, 0x219, 0x3EE, 0x343, + 0x568, 0x5C5, 0x432, 0x49F, 0x7DC, 0x771, 0x686, 0x62B }, + { 0x000, 0x0AE, 0x15C, 0x1F2, 0x2B8, 0x216, 0x3E4, 0x34A, + 0x570, 0x5DE, 0x42C, 0x482, 0x7C8, 0x766, 0x694, 0x63A }, + { 0x000, 0x0AF, 0x15E, 0x1F1, 0x2BC, 0x213, 0x3E2, 0x34D, + 0x578, 0x5D7, 0x426, 0x489, 0x7C4, 0x76B, 0x69A, 0x635 }, + { 0x000, 0x0B0, 0x160, 0x1D0, 0x2C0, 0x270, 0x3A0, 0x310, + 0x580, 0x530, 0x4E0, 0x450, 0x740, 0x7F0, 0x620, 0x690 }, + { 0x000, 0x0B1, 0x162, 0x1D3, 0x2C4, 0x275, 0x3A6, 0x317, + 0x588, 0x539, 0x4EA, 0x45B, 0x74C, 0x7FD, 0x62E, 0x69F }, + { 0x000, 0x0B2, 0x164, 0x1D6, 0x2C8, 0x27A, 0x3AC, 0x31E, + 0x590, 0x522, 0x4F4, 0x446, 0x758, 0x7EA, 0x63C, 0x68E }, + { 0x000, 0x0B3, 0x166, 0x1D5, 0x2CC, 0x27F, 0x3AA, 0x319, + 0x598, 0x52B, 0x4FE, 0x44D, 0x754, 0x7E7, 0x632, 0x681 }, + { 0x000, 0x0B4, 0x168, 0x1DC, 0x2D0, 0x264, 0x3B8, 0x30C, + 0x5A0, 0x514, 0x4C8, 0x47C, 0x770, 0x7C4, 0x618, 0x6AC }, + { 0x000, 0x0B5, 0x16A, 0x1DF, 0x2D4, 0x261, 0x3BE, 0x30B, + 0x5A8, 0x51D, 0x4C2, 0x477, 0x77C, 0x7C9, 0x616, 0x6A3 }, + { 0x000, 0x0B6, 0x16C, 0x1DA, 0x2D8, 0x26E, 0x3B4, 0x302, + 0x5B0, 0x506, 0x4DC, 0x46A, 0x768, 0x7DE, 0x604, 0x6B2 }, + { 0x000, 0x0B7, 0x16E, 0x1D9, 0x2DC, 0x26B, 0x3B2, 0x305, + 0x5B8, 0x50F, 0x4D6, 0x461, 0x764, 0x7D3, 0x60A, 0x6BD }, + { 0x000, 0x0B8, 0x170, 0x1C8, 0x2E0, 0x258, 0x390, 0x328, + 0x5C0, 0x578, 0x4B0, 0x408, 0x720, 0x798, 0x650, 0x6E8 }, + { 0x000, 0x0B9, 0x172, 0x1CB, 0x2E4, 0x25D, 0x396, 0x32F, + 0x5C8, 0x571, 0x4BA, 0x403, 0x72C, 0x795, 0x65E, 0x6E7 }, + { 0x000, 0x0BA, 0x174, 0x1CE, 0x2E8, 0x252, 0x39C, 0x326, + 0x5D0, 0x56A, 0x4A4, 0x41E, 0x738, 0x782, 0x64C, 0x6F6 }, + { 0x000, 0x0BB, 0x176, 0x1CD, 0x2EC, 0x257, 0x39A, 0x321, + 0x5D8, 0x563, 0x4AE, 0x415, 0x734, 0x78F, 0x642, 0x6F9 }, + { 0x000, 0x0BC, 0x178, 0x1C4, 0x2F0, 0x24C, 0x388, 0x334, + 0x5E0, 0x55C, 0x498, 0x424, 0x710, 0x7AC, 0x668, 0x6D4 }, + { 0x000, 0x0BD, 0x17A, 0x1C7, 0x2F4, 0x249, 0x38E, 0x333, + 0x5E8, 0x555, 0x492, 0x42F, 0x71C, 0x7A1, 0x666, 0x6DB }, + { 0x000, 0x0BE, 0x17C, 0x1C2, 0x2F8, 0x246, 0x384, 0x33A, + 0x5F0, 0x54E, 0x48C, 0x432, 0x708, 0x7B6, 0x674, 0x6CA }, + { 0x000, 0x0BF, 0x17E, 0x1C1, 0x2FC, 0x243, 0x382, 0x33D, + 0x5F8, 0x547, 0x486, 0x439, 0x704, 0x7BB, 0x67A, 0x6C5 }, + { 0x000, 0x0C0, 0x180, 0x140, 0x300, 0x3C0, 0x280, 0x240, + 0x600, 0x6C0, 0x780, 0x740, 0x500, 0x5C0, 0x480, 0x440 }, + { 0x000, 0x0C1, 0x182, 0x143, 0x304, 0x3C5, 0x286, 0x247, + 0x608, 0x6C9, 0x78A, 0x74B, 0x50C, 0x5CD, 0x48E, 0x44F }, + { 0x000, 0x0C2, 0x184, 0x146, 0x308, 0x3CA, 0x28C, 0x24E, + 0x610, 0x6D2, 0x794, 0x756, 0x518, 0x5DA, 0x49C, 0x45E }, + { 0x000, 0x0C3, 0x186, 0x145, 0x30C, 0x3CF, 0x28A, 0x249, + 0x618, 0x6DB, 0x79E, 0x75D, 0x514, 0x5D7, 0x492, 0x451 }, + { 0x000, 0x0C4, 0x188, 0x14C, 0x310, 0x3D4, 0x298, 0x25C, + 0x620, 0x6E4, 0x7A8, 0x76C, 0x530, 0x5F4, 0x4B8, 0x47C }, + { 0x000, 0x0C5, 0x18A, 0x14F, 0x314, 0x3D1, 0x29E, 0x25B, + 0x628, 0x6ED, 0x7A2, 0x767, 0x53C, 0x5F9, 0x4B6, 0x473 }, + { 0x000, 0x0C6, 0x18C, 0x14A, 0x318, 0x3DE, 0x294, 0x252, + 0x630, 0x6F6, 0x7BC, 0x77A, 0x528, 0x5EE, 0x4A4, 0x462 }, + { 0x000, 0x0C7, 0x18E, 0x149, 0x31C, 0x3DB, 0x292, 0x255, + 0x638, 0x6FF, 0x7B6, 0x771, 0x524, 0x5E3, 0x4AA, 0x46D }, + { 0x000, 0x0C8, 0x190, 0x158, 0x320, 0x3E8, 0x2B0, 0x278, + 0x640, 0x688, 0x7D0, 0x718, 0x560, 0x5A8, 0x4F0, 0x438 }, + { 0x000, 0x0C9, 0x192, 0x15B, 0x324, 0x3ED, 0x2B6, 0x27F, + 0x648, 0x681, 0x7DA, 0x713, 0x56C, 0x5A5, 0x4FE, 0x437 }, + { 0x000, 0x0CA, 0x194, 0x15E, 0x328, 0x3E2, 0x2BC, 0x276, + 0x650, 0x69A, 0x7C4, 0x70E, 0x578, 0x5B2, 0x4EC, 0x426 }, + { 0x000, 0x0CB, 0x196, 0x15D, 0x32C, 0x3E7, 0x2BA, 0x271, + 0x658, 0x693, 0x7CE, 0x705, 0x574, 0x5BF, 0x4E2, 0x429 }, + { 0x000, 0x0CC, 0x198, 0x154, 0x330, 0x3FC, 0x2A8, 0x264, + 0x660, 0x6AC, 0x7F8, 0x734, 0x550, 0x59C, 0x4C8, 0x404 }, + { 0x000, 0x0CD, 0x19A, 0x157, 0x334, 0x3F9, 0x2AE, 0x263, + 0x668, 0x6A5, 0x7F2, 0x73F, 0x55C, 0x591, 0x4C6, 0x40B }, + { 0x000, 0x0CE, 0x19C, 0x152, 0x338, 0x3F6, 0x2A4, 0x26A, + 0x670, 0x6BE, 0x7EC, 0x722, 0x548, 0x586, 0x4D4, 0x41A }, + { 0x000, 0x0CF, 0x19E, 0x151, 0x33C, 0x3F3, 0x2A2, 0x26D, + 0x678, 0x6B7, 0x7E6, 0x729, 0x544, 0x58B, 0x4DA, 0x415 }, + { 0x000, 0x0D0, 0x1A0, 0x170, 0x340, 0x390, 0x2E0, 0x230, + 0x680, 0x650, 0x720, 0x7F0, 0x5C0, 0x510, 0x460, 0x4B0 }, + { 0x000, 0x0D1, 0x1A2, 0x173, 0x344, 0x395, 0x2E6, 0x237, + 0x688, 0x659, 0x72A, 0x7FB, 0x5CC, 0x51D, 0x46E, 0x4BF }, + { 0x000, 0x0D2, 0x1A4, 0x176, 0x348, 0x39A, 0x2EC, 0x23E, + 0x690, 0x642, 0x734, 0x7E6, 0x5D8, 0x50A, 0x47C, 0x4AE }, + { 0x000, 0x0D3, 0x1A6, 0x175, 0x34C, 0x39F, 0x2EA, 0x239, + 0x698, 0x64B, 0x73E, 0x7ED, 0x5D4, 0x507, 0x472, 0x4A1 }, + { 0x000, 0x0D4, 0x1A8, 0x17C, 0x350, 0x384, 0x2F8, 0x22C, + 0x6A0, 0x674, 0x708, 0x7DC, 0x5F0, 0x524, 0x458, 0x48C }, + { 0x000, 0x0D5, 0x1AA, 0x17F, 0x354, 0x381, 0x2FE, 0x22B, + 0x6A8, 0x67D, 0x702, 0x7D7, 0x5FC, 0x529, 0x456, 0x483 }, + { 0x000, 0x0D6, 0x1AC, 0x17A, 0x358, 0x38E, 0x2F4, 0x222, + 0x6B0, 0x666, 0x71C, 0x7CA, 0x5E8, 0x53E, 0x444, 0x492 }, + { 0x000, 0x0D7, 0x1AE, 0x179, 0x35C, 0x38B, 0x2F2, 0x225, + 0x6B8, 0x66F, 0x716, 0x7C1, 0x5E4, 0x533, 0x44A, 0x49D }, + { 0x000, 0x0D8, 0x1B0, 0x168, 0x360, 0x3B8, 0x2D0, 0x208, + 0x6C0, 0x618, 0x770, 0x7A8, 0x5A0, 0x578, 0x410, 0x4C8 }, + { 0x000, 0x0D9, 0x1B2, 0x16B, 0x364, 0x3BD, 0x2D6, 0x20F, + 0x6C8, 0x611, 0x77A, 0x7A3, 0x5AC, 0x575, 0x41E, 0x4C7 }, + { 0x000, 0x0DA, 0x1B4, 0x16E, 0x368, 0x3B2, 0x2DC, 0x206, + 0x6D0, 0x60A, 0x764, 0x7BE, 0x5B8, 0x562, 0x40C, 0x4D6 }, + { 0x000, 0x0DB, 0x1B6, 0x16D, 0x36C, 0x3B7, 0x2DA, 0x201, + 0x6D8, 0x603, 0x76E, 0x7B5, 0x5B4, 0x56F, 0x402, 0x4D9 }, + { 0x000, 0x0DC, 0x1B8, 0x164, 0x370, 0x3AC, 0x2C8, 0x214, + 0x6E0, 0x63C, 0x758, 0x784, 0x590, 0x54C, 0x428, 0x4F4 }, + { 0x000, 0x0DD, 0x1BA, 0x167, 0x374, 0x3A9, 0x2CE, 0x213, + 0x6E8, 0x635, 0x752, 0x78F, 0x59C, 0x541, 0x426, 0x4FB }, + { 0x000, 0x0DE, 0x1BC, 0x162, 0x378, 0x3A6, 0x2C4, 0x21A, + 0x6F0, 0x62E, 0x74C, 0x792, 0x588, 0x556, 0x434, 0x4EA }, + { 0x000, 0x0DF, 0x1BE, 0x161, 0x37C, 0x3A3, 0x2C2, 0x21D, + 0x6F8, 0x627, 0x746, 0x799, 0x584, 0x55B, 0x43A, 0x4E5 }, + { 0x000, 0x0E0, 0x1C0, 0x120, 0x380, 0x360, 0x240, 0x2A0, + 0x700, 0x7E0, 0x6C0, 0x620, 0x480, 0x460, 0x540, 0x5A0 }, + { 0x000, 0x0E1, 0x1C2, 0x123, 0x384, 0x365, 0x246, 0x2A7, + 0x708, 0x7E9, 0x6CA, 0x62B, 0x48C, 0x46D, 0x54E, 0x5AF }, + { 0x000, 0x0E2, 0x1C4, 0x126, 0x388, 0x36A, 0x24C, 0x2AE, + 0x710, 0x7F2, 0x6D4, 0x636, 0x498, 0x47A, 0x55C, 0x5BE }, + { 0x000, 0x0E3, 0x1C6, 0x125, 0x38C, 0x36F, 0x24A, 0x2A9, + 0x718, 0x7FB, 0x6DE, 0x63D, 0x494, 0x477, 0x552, 0x5B1 }, + { 0x000, 0x0E4, 0x1C8, 0x12C, 0x390, 0x374, 0x258, 0x2BC, + 0x720, 0x7C4, 0x6E8, 0x60C, 0x4B0, 0x454, 0x578, 0x59C }, + { 0x000, 0x0E5, 0x1CA, 0x12F, 0x394, 0x371, 0x25E, 0x2BB, + 0x728, 0x7CD, 0x6E2, 0x607, 0x4BC, 0x459, 0x576, 0x593 }, + { 0x000, 0x0E6, 0x1CC, 0x12A, 0x398, 0x37E, 0x254, 0x2B2, + 0x730, 0x7D6, 0x6FC, 0x61A, 0x4A8, 0x44E, 0x564, 0x582 }, + { 0x000, 0x0E7, 0x1CE, 0x129, 0x39C, 0x37B, 0x252, 0x2B5, + 0x738, 0x7DF, 0x6F6, 0x611, 0x4A4, 0x443, 0x56A, 0x58D }, + { 0x000, 0x0E8, 0x1D0, 0x138, 0x3A0, 0x348, 0x270, 0x298, + 0x740, 0x7A8, 0x690, 0x678, 0x4E0, 0x408, 0x530, 0x5D8 }, + { 0x000, 0x0E9, 0x1D2, 0x13B, 0x3A4, 0x34D, 0x276, 0x29F, + 0x748, 0x7A1, 0x69A, 0x673, 0x4EC, 0x405, 0x53E, 0x5D7 }, + { 0x000, 0x0EA, 0x1D4, 0x13E, 0x3A8, 0x342, 0x27C, 0x296, + 0x750, 0x7BA, 0x684, 0x66E, 0x4F8, 0x412, 0x52C, 0x5C6 }, + { 0x000, 0x0EB, 0x1D6, 0x13D, 0x3AC, 0x347, 0x27A, 0x291, + 0x758, 0x7B3, 0x68E, 0x665, 0x4F4, 0x41F, 0x522, 0x5C9 }, + { 0x000, 0x0EC, 0x1D8, 0x134, 0x3B0, 0x35C, 0x268, 0x284, + 0x760, 0x78C, 0x6B8, 0x654, 0x4D0, 0x43C, 0x508, 0x5E4 }, + { 0x000, 0x0ED, 0x1DA, 0x137, 0x3B4, 0x359, 0x26E, 0x283, + 0x768, 0x785, 0x6B2, 0x65F, 0x4DC, 0x431, 0x506, 0x5EB }, + { 0x000, 0x0EE, 0x1DC, 0x132, 0x3B8, 0x356, 0x264, 0x28A, + 0x770, 0x79E, 0x6AC, 0x642, 0x4C8, 0x426, 0x514, 0x5FA }, + { 0x000, 0x0EF, 0x1DE, 0x131, 0x3BC, 0x353, 0x262, 0x28D, + 0x778, 0x797, 0x6A6, 0x649, 0x4C4, 0x42B, 0x51A, 0x5F5 }, + { 0x000, 0x0F0, 0x1E0, 0x110, 0x3C0, 0x330, 0x220, 0x2D0, + 0x780, 0x770, 0x660, 0x690, 0x440, 0x4B0, 0x5A0, 0x550 }, + { 0x000, 0x0F1, 0x1E2, 0x113, 0x3C4, 0x335, 0x226, 0x2D7, + 0x788, 0x779, 0x66A, 0x69B, 0x44C, 0x4BD, 0x5AE, 0x55F }, + { 0x000, 0x0F2, 0x1E4, 0x116, 0x3C8, 0x33A, 0x22C, 0x2DE, + 0x790, 0x762, 0x674, 0x686, 0x458, 0x4AA, 0x5BC, 0x54E }, + { 0x000, 0x0F3, 0x1E6, 0x115, 0x3CC, 0x33F, 0x22A, 0x2D9, + 0x798, 0x76B, 0x67E, 0x68D, 0x454, 0x4A7, 0x5B2, 0x541 }, + { 0x000, 0x0F4, 0x1E8, 0x11C, 0x3D0, 0x324, 0x238, 0x2CC, + 0x7A0, 0x754, 0x648, 0x6BC, 0x470, 0x484, 0x598, 0x56C }, + { 0x000, 0x0F5, 0x1EA, 0x11F, 0x3D4, 0x321, 0x23E, 0x2CB, + 0x7A8, 0x75D, 0x642, 0x6B7, 0x47C, 0x489, 0x596, 0x563 }, + { 0x000, 0x0F6, 0x1EC, 0x11A, 0x3D8, 0x32E, 0x234, 0x2C2, + 0x7B0, 0x746, 0x65C, 0x6AA, 0x468, 0x49E, 0x584, 0x572 }, + { 0x000, 0x0F7, 0x1EE, 0x119, 0x3DC, 0x32B, 0x232, 0x2C5, + 0x7B8, 0x74F, 0x656, 0x6A1, 0x464, 0x493, 0x58A, 0x57D }, + { 0x000, 0x0F8, 0x1F0, 0x108, 0x3E0, 0x318, 0x210, 0x2E8, + 0x7C0, 0x738, 0x630, 0x6C8, 0x420, 0x4D8, 0x5D0, 0x528 }, + { 0x000, 0x0F9, 0x1F2, 0x10B, 0x3E4, 0x31D, 0x216, 0x2EF, + 0x7C8, 0x731, 0x63A, 0x6C3, 0x42C, 0x4D5, 0x5DE, 0x527 }, + { 0x000, 0x0FA, 0x1F4, 0x10E, 0x3E8, 0x312, 0x21C, 0x2E6, + 0x7D0, 0x72A, 0x624, 0x6DE, 0x438, 0x4C2, 0x5CC, 0x536 }, + { 0x000, 0x0FB, 0x1F6, 0x10D, 0x3EC, 0x317, 0x21A, 0x2E1, + 0x7D8, 0x723, 0x62E, 0x6D5, 0x434, 0x4CF, 0x5C2, 0x539 }, + { 0x000, 0x0FC, 0x1F8, 0x104, 0x3F0, 0x30C, 0x208, 0x2F4, + 0x7E0, 0x71C, 0x618, 0x6E4, 0x410, 0x4EC, 0x5E8, 0x514 }, + { 0x000, 0x0FD, 0x1FA, 0x107, 0x3F4, 0x309, 0x20E, 0x2F3, + 0x7E8, 0x715, 0x612, 0x6EF, 0x41C, 0x4E1, 0x5E6, 0x51B }, + { 0x000, 0x0FE, 0x1FC, 0x102, 0x3F8, 0x306, 0x204, 0x2FA, + 0x7F0, 0x70E, 0x60C, 0x6F2, 0x408, 0x4F6, 0x5F4, 0x50A }, + { 0x000, 0x0FF, 0x1FE, 0x101, 0x3FC, 0x303, 0x202, 0x2FD, + 0x7F8, 0x707, 0x606, 0x6F9, 0x404, 0x4FB, 0x5FA, 0x505 } + }; +// Generated in CLISP: +// (dotimes (x 256) +// (dotimes (y 16) +// (let ((z 0)) +// (dotimes (b 4) (when (logbitp b y) (setq z (logxor z (ash x b))))) +// (when (zerop (mod y 8)) (format t "~% ")) +// (format t " 0x~3,'0X," z)))) +#endif + +// Multiply two GF2-polynomials of degree < 16. +#if defined(__sparc__) || defined(__sparc64__) +extern "C" uint32 gf2_mul16 (uint16 x, uint16 y); +#else +uint32 gf2_mul16 (uint16 x, uint16 y) +{ + var uint16 *ptr; // uint16 ptr[0x10]; + var uint32 res = 0; + // 8 table accesses. + ptr = gf2_mul_table[x & 0xFF]; + res ^= (uint32)ptr[y & 0xF]; + res ^= (uint32)ptr[(y >> 4) & 0xF] << 4; + res ^= (uint32)ptr[(y >> 8) & 0xF] << 8; + res ^= (uint32)ptr[(y >> 12) & 0xF] << 12; + ptr = gf2_mul_table[(x >> 8) & 0xFF]; + res ^= (uint32)ptr[y & 0xF] << 8; + res ^= (uint32)ptr[(y >> 4) & 0xF] << 12; + res ^= (uint32)ptr[(y >> 8) & 0xF] << 16; + res ^= (uint32)ptr[(y >> 12) & 0xF] << 20; + return res; +} +#endif + +// Multiply two GF2-polynomials of degree < 32. +// Stores the low part, returns the high part. +#if defined(__sparc__) || defined(__sparc64__) +extern "C" uint32 gf2_mul32 (uint32 x, uint32 y, uint32* plo); +#else +uint32 gf2_mul32 (uint32 x, uint32 y, uint32* plo) +{ + var uint16 *ptr; // uint16 ptr[0x10]; + var uint32 hi = 0; + var uint32 lo = 0; + var uint32 mid = 0; + // Result will be (hi << 32) ^ (mid << 16) ^ (lo << 0). +#if 0 + // Standard multiplication, 32 table accesses. + ptr = gf2_mul_table[x & 0xFF]; + lo ^= (uint32)ptr[y & 0xF]; + lo ^= (uint32)ptr[(y >> 4) & 0xF] << 4; + lo ^= (uint32)ptr[(y >> 8) & 0xF] << 8; + lo ^= (uint32)ptr[(y >> 12) & 0xF] << 12; + mid ^= (uint32)ptr[(y >> 16) & 0xF]; + mid ^= (uint32)ptr[(y >> 20) & 0xF] << 4; + mid ^= (uint32)ptr[(y >> 24) & 0xF] << 8; + mid ^= (uint32)ptr[(y >> 28) & 0xF] << 12; + ptr = gf2_mul_table[(x >> 8) & 0xFF]; + lo ^= (uint32)ptr[y & 0xF] << 8; + lo ^= (uint32)ptr[(y >> 4) & 0xF] << 12; + mid ^= (uint32)ptr[(y >> 8) & 0xF]; + mid ^= (uint32)ptr[(y >> 12) & 0xF] << 4; + mid ^= (uint32)ptr[(y >> 16) & 0xF] << 8; + mid ^= (uint32)ptr[(y >> 20) & 0xF] << 12; + hi ^= (uint32)ptr[(y >> 24) & 0xF]; + hi ^= (uint32)ptr[(y >> 28) & 0xF] << 4; + ptr = gf2_mul_table[(x >> 16) & 0xFF]; + mid ^= (uint32)ptr[y & 0xF]; + mid ^= (uint32)ptr[(y >> 4) & 0xF] << 4; + mid ^= (uint32)ptr[(y >> 8) & 0xF] << 8; + mid ^= (uint32)ptr[(y >> 12) & 0xF] << 12; + hi ^= (uint32)ptr[(y >> 16) & 0xF]; + hi ^= (uint32)ptr[(y >> 20) & 0xF] << 4; + hi ^= (uint32)ptr[(y >> 24) & 0xF] << 8; + hi ^= (uint32)ptr[(y >> 28) & 0xF] << 12; + ptr = gf2_mul_table[(x >> 24) & 0xFF]; + mid ^= (uint32)ptr[y & 0xF] << 8; + mid ^= (uint32)ptr[(y >> 4) & 0xF] << 12; + hi ^= (uint32)ptr[(y >> 8) & 0xF]; + hi ^= (uint32)ptr[(y >> 12) & 0xF] << 4; + hi ^= (uint32)ptr[(y >> 16) & 0xF] << 8; + hi ^= (uint32)ptr[(y >> 20) & 0xF] << 12; + hi ^= (uint32)ptr[(y >> 24) & 0xF] << 16; + hi ^= (uint32)ptr[(y >> 28) & 0xF] << 20; +#else + // Apply Karatsuba: + // lo := low16(x)*low16(y) + // hi := high16(x)*high16(y) + // mid := (high16(x)+low16(x))*(high16(y)+low16(y)) + // mid := mid + lo + hi + // 24 table accesses. + ptr = gf2_mul_table[x & 0xFF]; + lo ^= (uint32)ptr[y & 0xF]; + lo ^= (uint32)ptr[(y >> 4) & 0xF] << 4; + lo ^= (uint32)ptr[(y >> 8) & 0xF] << 8; + lo ^= (uint32)ptr[(y >> 12) & 0xF] << 12; + ptr = gf2_mul_table[(x >> 8) & 0xFF]; + lo ^= (uint32)ptr[y & 0xF] << 8; + lo ^= (uint32)ptr[(y >> 4) & 0xF] << 12; + lo ^= (uint32)ptr[(y >> 8) & 0xF] << 16; + lo ^= (uint32)ptr[(y >> 12) & 0xF] << 20; + ptr = gf2_mul_table[(x >> 16) & 0xFF]; + hi ^= (uint32)ptr[(y >> 16) & 0xF]; + hi ^= (uint32)ptr[(y >> 20) & 0xF] << 4; + hi ^= (uint32)ptr[(y >> 24) & 0xF] << 8; + hi ^= (uint32)ptr[(y >> 28) & 0xF] << 12; + ptr = gf2_mul_table[(x >> 24) & 0xFF]; + hi ^= (uint32)ptr[(y >> 16) & 0xF] << 8; + hi ^= (uint32)ptr[(y >> 20) & 0xF] << 12; + hi ^= (uint32)ptr[(y >> 24) & 0xF] << 16; + hi ^= (uint32)ptr[(y >> 28) & 0xF] << 20; + x ^= x >> 16; + y ^= y >> 16; + ptr = gf2_mul_table[x & 0xFF]; + mid ^= (uint32)ptr[y & 0xF]; + mid ^= (uint32)ptr[(y >> 4) & 0xF] << 4; + mid ^= (uint32)ptr[(y >> 8) & 0xF] << 8; + mid ^= (uint32)ptr[(y >> 12) & 0xF] << 12; + ptr = gf2_mul_table[(x >> 8) & 0xFF]; + mid ^= (uint32)ptr[y & 0xF] << 8; + mid ^= (uint32)ptr[(y >> 4) & 0xF] << 12; + mid ^= (uint32)ptr[(y >> 8) & 0xF] << 16; + mid ^= (uint32)ptr[(y >> 12) & 0xF] << 20; + mid ^= lo; + mid ^= hi; +#endif + *plo = lo ^ (mid << 16); + return hi ^ (mid >> 16); +} +#endif + +// Multiply two GF2-polynomials of degree < intDsize. +// Stores the low part, returns the high part. +#if (intDsize==32) + #define gf2_mul_uintD gf2_mul32 +#endif +#if (intDsize==64) + inline uint64 gf2_mul32_ (uint32 x, uint32 y) + { + var uint16 *ptr; // uint16 ptr[0x10]; + var uint32 hi = 0; + var uint32 lo = 0; + var uint32 mid = 0; + // Result will be (hi << 32) ^ (mid << 16) ^ (lo << 0). + // Apply Karatsuba: + // lo := low16(x)*low16(y) + // hi := high16(x)*high16(y) + // mid := (high16(x)+low16(x))*(high16(y)+low16(y)) + // mid := mid + lo + hi + // 24 table accesses. + ptr = gf2_mul_table[x & 0xFF]; + lo ^= (uint32)ptr[y & 0xF]; + lo ^= (uint32)ptr[(y >> 4) & 0xF] << 4; + lo ^= (uint32)ptr[(y >> 8) & 0xF] << 8; + lo ^= (uint32)ptr[(y >> 12) & 0xF] << 12; + ptr = gf2_mul_table[(x >> 8) & 0xFF]; + lo ^= (uint32)ptr[y & 0xF] << 8; + lo ^= (uint32)ptr[(y >> 4) & 0xF] << 12; + lo ^= (uint32)ptr[(y >> 8) & 0xF] << 16; + lo ^= (uint32)ptr[(y >> 12) & 0xF] << 20; + ptr = gf2_mul_table[(x >> 16) & 0xFF]; + hi ^= (uint32)ptr[(y >> 16) & 0xF]; + hi ^= (uint32)ptr[(y >> 20) & 0xF] << 4; + hi ^= (uint32)ptr[(y >> 24) & 0xF] << 8; + hi ^= (uint32)ptr[(y >> 28) & 0xF] << 12; + ptr = gf2_mul_table[(x >> 24) & 0xFF]; + hi ^= (uint32)ptr[(y >> 16) & 0xF] << 8; + hi ^= (uint32)ptr[(y >> 20) & 0xF] << 12; + hi ^= (uint32)ptr[(y >> 24) & 0xF] << 16; + hi ^= (uint32)ptr[(y >> 28) & 0xF] << 20; + x ^= x >> 16; + y ^= y >> 16; + ptr = gf2_mul_table[x & 0xFF]; + mid ^= (uint32)ptr[y & 0xF]; + mid ^= (uint32)ptr[(y >> 4) & 0xF] << 4; + mid ^= (uint32)ptr[(y >> 8) & 0xF] << 8; + mid ^= (uint32)ptr[(y >> 12) & 0xF] << 12; + ptr = gf2_mul_table[(x >> 8) & 0xFF]; + mid ^= (uint32)ptr[y & 0xF] << 8; + mid ^= (uint32)ptr[(y >> 4) & 0xF] << 12; + mid ^= (uint32)ptr[(y >> 8) & 0xF] << 16; + mid ^= (uint32)ptr[(y >> 12) & 0xF] << 20; + mid ^= lo; + mid ^= hi; + return (((uint64)hi << 32) | ((uint64)lo)) ^ ((uint64)mid << 16); + } + static uintD gf2_mul_uintD (uintD x, uintD y, uintD* plo) + { + // Apply Karatsuba: + // lo := low32(x)*low32(y) + // hi := high32(x)*high32(y) + // mid := (high32(x)+low32(x))*(high32(y)+low32(y)) + // mid := mid + lo + hi + // 72 table accesses. + var uint64 lo = gf2_mul32_(x,y); + var uint64 hi = gf2_mul32_(x>>32,y>>32); + var uint64 mid = gf2_mul32_(x^(x>>32),y^(y>>32)); + // Result will be (hi << 64) ^ (mid << 32) ^ (lo << 0). + *plo = lo ^ (mid << 32); + return hi ^ (mid >> 32); + } +#endif + +static const _cl_UP gf2_mul (cl_heap_univpoly_ring* UPR, const _cl_UP& x, const _cl_UP& y) +{{ + DeclarePoly(cl_GV_MI,x); + DeclarePoly(cl_GV_MI,y); + var const cl_heap_GV_I_bits1 * xv = (const cl_heap_GV_I_bits1 *) x.heappointer; + var const cl_heap_GV_I_bits1 * yv = (const cl_heap_GV_I_bits1 *) y.heappointer; + var uintL xlen = xv->v.length(); + var uintL ylen = yv->v.length(); + if (xlen == 0) + return _cl_UP(UPR, x); + if (ylen == 0) + return _cl_UP(UPR, y); + var cl_heap_modint_ring* R = TheModintRing(UPR->basering()); + var uintL len = xlen+ylen-1; + var cl_GV_MI result = cl_GV_MI(len,R); + var cl_heap_GV_I_bits1 * rv = (cl_heap_GV_I_bits1 *) result.heappointer; + xlen = ceiling(xlen,intDsize); + ylen = ceiling(ylen,intDsize); + if (xlen < ylen) { + var uintL xlen1 = ceiling(len,intDsize)-ylen; // = xlen-{0,1} + for (uintL i = 0; i < xlen; i++) { + var uintD xw = xv->data[i]; + var uintD* rvptr = &rv->data[i]; + var uintD carry = 0; + for (uintL j = 0; j < ylen; j++) { + var uintD rwlo; + var uintD rwhi + = gf2_mul_uintD(xw,yv->data[j],&rwlo); + *rvptr++ ^= carry ^ rwlo; + carry = rwhi; + } + if (i < xlen1) + *rvptr ^= carry; + } + } else { + var uintL ylen1 = ceiling(len,intDsize)-xlen; // = ylen-{0,1} + for (uintL j = 0; j < ylen; j++) { + var uintD yw = yv->data[j]; + var uintD* rvptr = &rv->data[j]; + var uintD carry = 0; + for (uintL i = 0; i < xlen; i++) { + var uintD rwlo; + var uintD rwhi + = gf2_mul_uintD(xv->data[i],yw,&rwlo); + *rvptr++ ^= carry ^ rwlo; + carry = rwhi; + } + if (j < ylen1) + *rvptr ^= carry; + } + } + return _cl_UP(UPR, result); +}} + +// In characteristic 2, we square a polynomial by doubling the exponents: +// (sum(a_i T^i))^2 = sum(a_i^2 T^2i) = sum(a_i T^2i). + +static uint16 gf2_square_table[0x100] = + { + 0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, 0x0015, + 0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055, + 0x0100, 0x0101, 0x0104, 0x0105, 0x0110, 0x0111, 0x0114, 0x0115, + 0x0140, 0x0141, 0x0144, 0x0145, 0x0150, 0x0151, 0x0154, 0x0155, + 0x0400, 0x0401, 0x0404, 0x0405, 0x0410, 0x0411, 0x0414, 0x0415, + 0x0440, 0x0441, 0x0444, 0x0445, 0x0450, 0x0451, 0x0454, 0x0455, + 0x0500, 0x0501, 0x0504, 0x0505, 0x0510, 0x0511, 0x0514, 0x0515, + 0x0540, 0x0541, 0x0544, 0x0545, 0x0550, 0x0551, 0x0554, 0x0555, + 0x1000, 0x1001, 0x1004, 0x1005, 0x1010, 0x1011, 0x1014, 0x1015, + 0x1040, 0x1041, 0x1044, 0x1045, 0x1050, 0x1051, 0x1054, 0x1055, + 0x1100, 0x1101, 0x1104, 0x1105, 0x1110, 0x1111, 0x1114, 0x1115, + 0x1140, 0x1141, 0x1144, 0x1145, 0x1150, 0x1151, 0x1154, 0x1155, + 0x1400, 0x1401, 0x1404, 0x1405, 0x1410, 0x1411, 0x1414, 0x1415, + 0x1440, 0x1441, 0x1444, 0x1445, 0x1450, 0x1451, 0x1454, 0x1455, + 0x1500, 0x1501, 0x1504, 0x1505, 0x1510, 0x1511, 0x1514, 0x1515, + 0x1540, 0x1541, 0x1544, 0x1545, 0x1550, 0x1551, 0x1554, 0x1555, + 0x4000, 0x4001, 0x4004, 0x4005, 0x4010, 0x4011, 0x4014, 0x4015, + 0x4040, 0x4041, 0x4044, 0x4045, 0x4050, 0x4051, 0x4054, 0x4055, + 0x4100, 0x4101, 0x4104, 0x4105, 0x4110, 0x4111, 0x4114, 0x4115, + 0x4140, 0x4141, 0x4144, 0x4145, 0x4150, 0x4151, 0x4154, 0x4155, + 0x4400, 0x4401, 0x4404, 0x4405, 0x4410, 0x4411, 0x4414, 0x4415, + 0x4440, 0x4441, 0x4444, 0x4445, 0x4450, 0x4451, 0x4454, 0x4455, + 0x4500, 0x4501, 0x4504, 0x4505, 0x4510, 0x4511, 0x4514, 0x4515, + 0x4540, 0x4541, 0x4544, 0x4545, 0x4550, 0x4551, 0x4554, 0x4555, + 0x5000, 0x5001, 0x5004, 0x5005, 0x5010, 0x5011, 0x5014, 0x5015, + 0x5040, 0x5041, 0x5044, 0x5045, 0x5050, 0x5051, 0x5054, 0x5055, + 0x5100, 0x5101, 0x5104, 0x5105, 0x5110, 0x5111, 0x5114, 0x5115, + 0x5140, 0x5141, 0x5144, 0x5145, 0x5150, 0x5151, 0x5154, 0x5155, + 0x5400, 0x5401, 0x5404, 0x5405, 0x5410, 0x5411, 0x5414, 0x5415, + 0x5440, 0x5441, 0x5444, 0x5445, 0x5450, 0x5451, 0x5454, 0x5455, + 0x5500, 0x5501, 0x5504, 0x5505, 0x5510, 0x5511, 0x5514, 0x5515, + 0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555 + }; +// Generated in CLISP: +// (dotimes (i 256) +// (let ((j 0)) +// (dotimes (b 8) (when (logbitp b i) (setq j (logior j (ash 1 (+ b b)))))) +// (when (zerop (mod i 8)) (format t "~% ")) +// (format t " 0x~4,'0X," j))) + +// Square a GF2-polynomial of degree < intDsize. +// Stores the low part, returns the high part. +static uintD gf2_square_uintD (uintD x, uintD* lo) +{ +#if (intDsize==32) + *lo = ((uintD)gf2_square_table[(x>>8) & 0xFF] << 16) + | (uintD)gf2_square_table[x & 0xFF]; + x = x>>16; + return ((uintD)gf2_square_table[(x>>8) & 0xFF] << 16) + | (uintD)gf2_square_table[x & 0xFF]; +#endif +#if (intDsize==64) + *lo = ((uintD)gf2_square_table[(x>>24) & 0xFF] << 48) + | ((uintD)gf2_square_table[(x>>16) & 0xFF] << 32) + | ((uintD)gf2_square_table[(x>>8) & 0xFF] << 16) + | (uintD)gf2_square_table[x & 0xFF]; + x = x>>32; + return ((uintD)gf2_square_table[(x>>24) & 0xFF] << 48) + | ((uintD)gf2_square_table[(x>>16) & 0xFF] << 32) + | ((uintD)gf2_square_table[(x>>8) & 0xFF] << 16) + | (uintD)gf2_square_table[x & 0xFF]; +#endif +} + +static const _cl_UP gf2_square (cl_heap_univpoly_ring* UPR, const _cl_UP& x) +{{ + DeclarePoly(cl_GV_MI,x); + var const cl_heap_GV_I_bits1 * xv = (const cl_heap_GV_I_bits1 *) x.heappointer; + var uintL xlen = xv->v.length(); + if (xlen == 0) + return _cl_UP(UPR, x); + var cl_heap_modint_ring* R = TheModintRing(UPR->basering()); + var uintL len = 2*xlen-1; + var cl_GV_MI result = cl_GV_MI(len,R); + var cl_heap_GV_I_bits1 * rv = (cl_heap_GV_I_bits1 *) result.heappointer; + var uintL count = floor(xlen,intDsize); + for (uintL i = 0; i < count; i++) + rv->data[2*i+1] = gf2_square_uintD(xv->data[i],&rv->data[2*i]); + xlen = xlen%intDsize; + if (xlen > 0) { + var uintD hiword = xv->data[count]; // xlen bits + hiword = gf2_square_uintD(hiword,&rv->data[2*count]); + if (xlen > intDsize/2) + rv->data[2*count+1] = hiword; + } + return _cl_UP(UPR, result); +}} + +// Scalar multiplication of GF(2)-polynomials is trivial: 0*y = 0, 1*y = y. +static const _cl_UP gf2_scalmul (cl_heap_univpoly_ring* UPR, const cl_ring_element& x, const _cl_UP& y) +{ + if (!(UPR->basering() == x.ring())) cl_abort(); + { + DeclarePoly(_cl_MI,x); + var cl_heap_modint_ring* R = TheModintRing(UPR->basering()); + if (R->_zerop(x)) + return _cl_UP(UPR, cl_null_GV_I); + return y; +}} + +// Evaluation of GF(2)-polynomials is trivial: +// At 0, it's the coefficient 0. At 1, it's the sum of all coefficients, +// i.e. the parity of the number of nonzero coefficients. +static const cl_ring_element gf2_eval (cl_heap_univpoly_ring* UPR, const _cl_UP& x, const cl_ring_element& y) +{{ + DeclarePoly(cl_GV_MI,x); + if (!(UPR->basering() == y.ring())) cl_abort(); + { DeclarePoly(_cl_MI,y); + var cl_heap_modint_ring* R = TheModintRing(UPR->basering()); + var const cl_heap_GV_I_bits1 * xv = (const cl_heap_GV_I_bits1 *) x.heappointer; + var uintL len = xv->v.length(); + if (len==0) + return R->zero(); + if (R->_zerop(y)) + return cl_MI(R, x[0]); + else { + var uintL count = ceiling(len,intDsize); + var uintL bitcount = 0; + do { + count--; + bitcount += logcountD(xv->data[count]); + } while (count > 0); + return R->canonhom(bitcount%2); + } +}}} + +static cl_univpoly_setops gf2_setops = { + modint_fprint, + gf2_equal +}; + +static cl_univpoly_addops gf2_addops = { + modint_zero, + modint_zerop, + gf2_plus, + gf2_minus, + gf2_uminus +}; + +static cl_univpoly_mulops gf2_mulops = { + modint_one, + modint_canonhom, + gf2_mul, + gf2_square, + modint_exptpos +}; + +static cl_univpoly_modulops gf2_modulops = { + gf2_scalmul +}; + +static cl_univpoly_polyops gf2_polyops = { + modint_degree, + modint_monomial, + modint_coeff, + modint_create, + modint_set_coeff, + modint_finalize, + gf2_eval +}; + +class cl_heap_gf2_univpoly_ring : public cl_heap_univpoly_ring { + SUBCLASS_cl_heap_univpoly_ring() +public: + // Constructor. + cl_heap_gf2_univpoly_ring (const cl_ring& r) + : cl_heap_univpoly_ring (r, &gf2_setops, &gf2_addops, &gf2_mulops, &gf2_modulops, &gf2_polyops) {} +}; diff --git a/src/polynomial/elem/cl_UP_MI.h b/src/polynomial/elem/cl_UP_MI.h new file mode 100644 index 0000000..ceee70d --- /dev/null +++ b/src/polynomial/elem/cl_UP_MI.h @@ -0,0 +1,471 @@ +// Univariate Polynomials over a ring of modular integers. + +#include "cl_GV_modinteger.h" +#include "cl_modinteger.h" +#include "cl_abort.h" + +// Assume a ring is a modint ring. + inline cl_heap_modint_ring* TheModintRing (const cl_ring& R) + { return (cl_heap_modint_ring*) R.heappointer; } + +// Normalize a vector: remove leading zero coefficients. +// The result vector is known to have length len > 0. +static inline void modint_normalize (cl_heap_modint_ring* R, cl_GV_MI& result, uintL len) +{ + if (R->_zerop(result[len-1])) { + len--; + while (len > 0) { + if (!R->_zerop(result[len-1])) + break; + len--; + } + var cl_GV_MI newresult = cl_GV_MI(len,R); + #if 0 + for (var sintL i = len-1; i >= 0; i--) + newresult[i] = result[i]; + #else + cl_GV_MI::copy_elements(result,0,newresult,0,len); + #endif + result = newresult; + } +} + +static void modint_fprint (cl_heap_univpoly_ring* UPR, cl_ostream stream, const _cl_UP& x) +{{ + DeclarePoly(cl_GV_MI,x); + var cl_heap_modint_ring* R = TheModintRing(UPR->basering()); + var sintL xlen = x.length(); + if (xlen == 0) + fprint(stream, "0"); + else { + var cl_string varname = get_varname(UPR); + for (var sintL i = xlen-1; i >= 0; i--) + if (!R->_zerop(x[i])) { + if (i < xlen-1) + fprint(stream, " + "); + fprint(stream, "("); + R->_fprint(stream, x[i]); + fprint(stream, ")"); + if (i > 0) { + fprint(stream, "*"); + fprint(stream, varname); + if (i != 1) { + fprint(stream, "^"); + fprintdecimal(stream, i); + } + } + } + } +}} + +static cl_boolean modint_equal (cl_heap_univpoly_ring* UPR, const _cl_UP& x, const _cl_UP& y) +{{ + DeclarePoly(cl_GV_MI,x); + DeclarePoly(cl_GV_MI,y); + var cl_heap_modint_ring* R = TheModintRing(UPR->basering()); + var sintL xlen = x.length(); + var sintL ylen = y.length(); + if (!(xlen == ylen)) + return cl_false; + for (var sintL i = xlen-1; i >= 0; i--) + if (!R->_equal(x[i],y[i])) + return cl_false; + return cl_true; +}} + +static const _cl_UP modint_zero (cl_heap_univpoly_ring* UPR) +{ + return _cl_UP(UPR, cl_null_GV_I); +} + +static cl_boolean modint_zerop (cl_heap_univpoly_ring* UPR, const _cl_UP& x) +{ + unused UPR; + { DeclarePoly(cl_GV_MI,x); + var sintL xlen = x.length(); + if (xlen == 0) + return cl_true; + else + return cl_false; +}} + +static const _cl_UP modint_plus (cl_heap_univpoly_ring* UPR, const _cl_UP& x, const _cl_UP& y) +{{ + DeclarePoly(cl_GV_MI,x); + DeclarePoly(cl_GV_MI,y); + var cl_heap_modint_ring* R = TheModintRing(UPR->basering()); + var sintL xlen = x.length(); + var sintL ylen = y.length(); + if (xlen == 0) + return _cl_UP(UPR, y); + if (ylen == 0) + return _cl_UP(UPR, x); + // Now xlen > 0, ylen > 0. + if (xlen > ylen) { + var cl_GV_MI result = cl_GV_MI(xlen,R); + var sintL i; + #if 0 + for (i = xlen-1; i >= ylen; i--) + result[i] = x[i]; + #else + cl_GV_MI::copy_elements(x,ylen,result,ylen,xlen-ylen); + #endif + for (i = ylen-1; i >= 0; i--) + result[i] = R->_plus(x[i],y[i]); + return _cl_UP(UPR, result); + } + if (xlen < ylen) { + var cl_GV_MI result = cl_GV_MI(ylen,R); + var sintL i; + #if 0 + for (i = ylen-1; i >= xlen; i--) + result[i] = y[i]; + #else + cl_GV_MI::copy_elements(y,xlen,result,xlen,ylen-xlen); + #endif + for (i = xlen-1; i >= 0; i--) + result[i] = R->_plus(x[i],y[i]); + return _cl_UP(UPR, result); + } + // Now xlen = ylen > 0. Add and normalize simultaneously. + for (var sintL i = xlen-1; i >= 0; i--) { + var _cl_MI hicoeff = R->_plus(x[i],y[i]); + if (!R->_zerop(hicoeff)) { + var cl_GV_MI result = cl_GV_MI(i+1,R); + result[i] = hicoeff; + for (i-- ; i >= 0; i--) + result[i] = R->_plus(x[i],y[i]); + return _cl_UP(UPR, result); + } + } + return _cl_UP(UPR, cl_null_GV_I); +}} + +static const _cl_UP modint_minus (cl_heap_univpoly_ring* UPR, const _cl_UP& x, const _cl_UP& y) +{{ + DeclarePoly(cl_GV_MI,x); + DeclarePoly(cl_GV_MI,y); + var cl_heap_modint_ring* R = TheModintRing(UPR->basering()); + var sintL xlen = x.length(); + var sintL ylen = y.length(); + if (xlen == 0) + return _cl_UP(UPR, y); + if (ylen == 0) + return _cl_UP(UPR, x); + // Now xlen > 0, ylen > 0. + if (xlen > ylen) { + var cl_GV_MI result = cl_GV_MI(xlen,R); + var sintL i; + #if 0 + for (i = xlen-1; i >= ylen; i--) + result[i] = x[i]; + #else + cl_GV_MI::copy_elements(x,ylen,result,ylen,xlen-ylen); + #endif + for (i = ylen-1; i >= 0; i--) + result[i] = R->_minus(x[i],y[i]); + return _cl_UP(UPR, result); + } + if (xlen < ylen) { + var cl_GV_MI result = cl_GV_MI(ylen,R); + var sintL i; + for (i = ylen-1; i >= xlen; i--) + result[i] = R->_uminus(y[i]); + for (i = xlen-1; i >= 0; i--) + result[i] = R->_minus(x[i],y[i]); + return _cl_UP(UPR, result); + } + // Now xlen = ylen > 0. Add and normalize simultaneously. + for (var sintL i = xlen-1; i >= 0; i--) { + var _cl_MI hicoeff = R->_minus(x[i],y[i]); + if (!R->_zerop(hicoeff)) { + var cl_GV_MI result = cl_GV_MI(i+1,R); + result[i] = hicoeff; + for (i-- ; i >= 0; i--) + result[i] = R->_minus(x[i],y[i]); + return _cl_UP(UPR, result); + } + } + return _cl_UP(UPR, cl_null_GV_I); +}} + +static const _cl_UP modint_uminus (cl_heap_univpoly_ring* UPR, const _cl_UP& x) +{{ + DeclarePoly(cl_GV_MI,x); + var cl_heap_modint_ring* R = TheModintRing(UPR->basering()); + var sintL xlen = x.length(); + if (xlen == 0) + return _cl_UP(UPR, x); + // Now xlen > 0. + // Negate. No normalization necessary, since the degree doesn't change. + var sintL i = xlen-1; + var _cl_MI hicoeff = R->_uminus(x[i]); + if (R->_zerop(hicoeff)) cl_abort(); + var cl_GV_MI result = cl_GV_MI(xlen,R); + result[i] = hicoeff; + for (i-- ; i >= 0; i--) + result[i] = R->_uminus(x[i]); + return _cl_UP(UPR, result); +}} + +static const _cl_UP modint_one (cl_heap_univpoly_ring* UPR) +{ + var cl_heap_modint_ring* R = TheModintRing(UPR->basering()); + var cl_GV_MI result = cl_GV_MI(1,R); + result[0] = R->_one(); + return _cl_UP(UPR, result); +} + +static const _cl_UP modint_canonhom (cl_heap_univpoly_ring* UPR, const cl_I& x) +{ + var cl_heap_modint_ring* R = TheModintRing(UPR->basering()); + var cl_GV_MI result = cl_GV_MI(1,R); + result[0] = R->_canonhom(x); + return _cl_UP(UPR, result); +} + +static const _cl_UP modint_mul (cl_heap_univpoly_ring* UPR, const _cl_UP& x, const _cl_UP& y) +{{ + DeclarePoly(cl_GV_MI,x); + DeclarePoly(cl_GV_MI,y); + var cl_heap_modint_ring* R = TheModintRing(UPR->basering()); + var sintL xlen = x.length(); + var sintL ylen = y.length(); + if (xlen == 0) + return _cl_UP(UPR, x); + if (ylen == 0) + return _cl_UP(UPR, y); + // Multiply. + var sintL len = xlen + ylen - 1; + var cl_GV_MI result = cl_GV_MI(len,R); + if (xlen < ylen) { + { + var sintL i = xlen-1; + var _cl_MI xi = x[i]; + for (sintL j = ylen-1; j >= 0; j--) + result[i+j] = R->_mul(xi,y[j]); + } + for (sintL i = xlen-2; i >= 0; i--) { + var _cl_MI xi = x[i]; + for (sintL j = ylen-1; j > 0; j--) + result[i+j] = R->_plus(result[i+j],R->_mul(xi,y[j])); + /* j=0 */ result[i] = R->_mul(xi,y[0]); + } + } else { + { + var sintL j = ylen-1; + var _cl_MI yj = y[j]; + for (sintL i = xlen-1; i >= 0; i--) + result[i+j] = R->_mul(x[i],yj); + } + for (sintL j = ylen-2; j >= 0; j--) { + var _cl_MI yj = y[j]; + for (sintL i = xlen-1; i > 0; i--) + result[i+j] = R->_plus(result[i+j],R->_mul(x[i],yj)); + /* i=0 */ result[j] = R->_mul(x[0],yj); + } + } + // Normalize (not necessary in integral domains). + //modint_normalize(R,result,len); + if (R->_zerop(result[len-1])) cl_abort(); + return _cl_UP(UPR, result); +}} + +static const _cl_UP modint_square (cl_heap_univpoly_ring* UPR, const _cl_UP& x) +{{ + DeclarePoly(cl_GV_MI,x); + var cl_heap_modint_ring* R = TheModintRing(UPR->basering()); + var sintL xlen = x.length(); + if (xlen == 0) + return cl_UP(UPR, x); + var sintL len = 2*xlen-1; + var cl_GV_MI result = cl_GV_MI(len,R); + if (xlen > 1) { + // Loop through all 0 <= j < i <= xlen-1. + { + var sintL i = xlen-1; + var _cl_MI xi = x[i]; + for (sintL j = i-1; j >= 0; j--) + result[i+j] = R->_mul(xi,x[j]); + } + {for (sintL i = xlen-2; i >= 1; i--) { + var _cl_MI xi = x[i]; + for (sintL j = i-1; j >= 1; j--) + result[i+j] = R->_plus(result[i+j],R->_mul(xi,x[j])); + /* j=0 */ result[i] = R->_mul(xi,x[0]); + }} + // Double. + {for (sintL i = len-2; i >= 1; i--) + result[i] = R->_plus(result[i],result[i]); + } + // Add squares. + result[2*(xlen-1)] = R->_square(x[xlen-1]); + for (sintL i = xlen-2; i >= 1; i--) + result[2*i] = R->_plus(result[2*i],R->_square(x[i])); + } + result[0] = R->_square(x[0]); + // Normalize (not necessary in integral domains). + //modint_normalize(R,result,len); + if (R->_zerop(result[len-1])) cl_abort(); + return _cl_UP(UPR, result); +}} + +static const _cl_UP modint_exptpos (cl_heap_univpoly_ring* UPR, const _cl_UP& x, const cl_I& y) +{ + var _cl_UP a = x; + var cl_I b = y; + while (!oddp(b)) { a = UPR->_square(a); b = b >> 1; } + var _cl_UP c = a; + until (b == 1) + { b = b >> 1; + a = UPR->_square(a); + if (oddp(b)) { c = UPR->_mul(a,c); } + } + return c; +} + +static const _cl_UP modint_scalmul (cl_heap_univpoly_ring* UPR, const cl_ring_element& x, const _cl_UP& y) +{ + if (!(UPR->basering() == x.ring())) cl_abort(); + { + DeclarePoly(_cl_MI,x); + DeclarePoly(cl_GV_MI,y); + var cl_heap_modint_ring* R = TheModintRing(UPR->basering()); + var sintL ylen = y.length(); + if (ylen == 0) + return _cl_UP(UPR, y); + if (R->_zerop(x)) + return _cl_UP(UPR, cl_null_GV_I); + // Now ylen > 0. + // No normalization necessary, since the degree doesn't change. + var cl_GV_MI result = cl_GV_MI(ylen,R); + for (sintL i = ylen-1; i >= 0; i--) + result[i] = R->_mul(x,y[i]); + return _cl_UP(UPR, result); +}} + +static sintL modint_degree (cl_heap_univpoly_ring* UPR, const _cl_UP& x) +{ + unused UPR; + { DeclarePoly(cl_GV_MI,x); + return (sintL) x.length() - 1; +}} + +static const _cl_UP modint_monomial (cl_heap_univpoly_ring* UPR, const cl_ring_element& x, uintL e) +{ + if (!(UPR->basering() == x.ring())) cl_abort(); + { DeclarePoly(_cl_MI,x); + var cl_heap_modint_ring* R = TheModintRing(UPR->basering()); + if (R->_zerop(x)) + return _cl_UP(UPR, cl_null_GV_I); + else { + var sintL len = e+1; + var cl_GV_MI result = cl_GV_MI(len,R); + result[e] = x; + return _cl_UP(UPR, result); + } +}} + +static const cl_ring_element modint_coeff (cl_heap_univpoly_ring* UPR, const _cl_UP& x, uintL index) +{{ + DeclarePoly(cl_GV_MI,x); + var cl_heap_modint_ring* R = TheModintRing(UPR->basering()); + if (index < x.length()) + return cl_MI(R, x[index]); + else + return R->zero(); +}} + +static const _cl_UP modint_create (cl_heap_univpoly_ring* UPR, sintL deg) +{ + if (deg < 0) + return _cl_UP(UPR, cl_null_GV_I); + else { + var sintL len = deg+1; + var cl_heap_modint_ring* R = TheModintRing(UPR->basering()); + return _cl_UP(UPR, cl_GV_MI(len,R)); + } +} + +static void modint_set_coeff (cl_heap_univpoly_ring* UPR, _cl_UP& x, uintL index, const cl_ring_element& y) +{{ + DeclareMutablePoly(cl_GV_MI,x); + if (!(UPR->basering() == y.ring())) cl_abort(); + { DeclarePoly(_cl_MI,y); + if (!(index < x.length())) cl_abort(); + x[index] = y; +}}} + +static void modint_finalize (cl_heap_univpoly_ring* UPR, _cl_UP& x) +{{ + DeclareMutablePoly(cl_GV_MI,x); // NB: x is modified by reference! + var cl_heap_modint_ring* R = TheModintRing(UPR->basering()); + var uintL len = x.length(); + if (len > 0) + modint_normalize(R,x,len); +}} + +static const cl_ring_element modint_eval (cl_heap_univpoly_ring* UPR, const _cl_UP& x, const cl_ring_element& y) +{{ + // Method: + // If x = 0, return 0. + // If y = 0, return x[0]. + // Else compute (...(x[len-1]*y+x[len-2])*y ...)*y + x[0]. + DeclarePoly(cl_GV_MI,x); + if (!(UPR->basering() == y.ring())) cl_abort(); + { DeclarePoly(_cl_MI,y); + var cl_heap_modint_ring* R = TheModintRing(UPR->basering()); + var uintL len = x.length(); + if (len==0) + return R->zero(); + if (R->_zerop(y)) + return cl_MI(R, x[0]); + var sintL i = len-1; + var _cl_MI z = x[i]; + for ( ; --i >= 0; ) + z = R->_plus(R->_mul(z,y),x[i]); + return cl_MI(R, z); +}}} + +static cl_univpoly_setops modint_setops = { + modint_fprint, + modint_equal +}; + +static cl_univpoly_addops modint_addops = { + modint_zero, + modint_zerop, + modint_plus, + modint_minus, + modint_uminus +}; + +static cl_univpoly_mulops modint_mulops = { + modint_one, + modint_canonhom, + modint_mul, + modint_square, + modint_exptpos +}; + +static cl_univpoly_modulops modint_modulops = { + modint_scalmul +}; + +static cl_univpoly_polyops modint_polyops = { + modint_degree, + modint_monomial, + modint_coeff, + modint_create, + modint_set_coeff, + modint_finalize, + modint_eval +}; + +class cl_heap_modint_univpoly_ring : public cl_heap_univpoly_ring { + SUBCLASS_cl_heap_univpoly_ring() +public: + // Constructor. + cl_heap_modint_univpoly_ring (const cl_ring& r) + : cl_heap_univpoly_ring (r, &modint_setops, &modint_addops, &modint_mulops, &modint_modulops, &modint_polyops) {} +}; diff --git a/src/polynomial/elem/cl_UP_gen.h b/src/polynomial/elem/cl_UP_gen.h new file mode 100644 index 0000000..c5970dd --- /dev/null +++ b/src/polynomial/elem/cl_UP_gen.h @@ -0,0 +1,451 @@ +// Univariate Polynomials over a general ring. + +#include "cl_SV_ringelt.h" +#include "cl_integer.h" +#include "cl_abort.h" + +// Assume a ring is a ring. + inline cl_heap_ring* TheRing (const cl_ring& R) + { return (cl_heap_ring*) R.heappointer; } + +// Normalize a vector: remove leading zero coefficients. +// The result vector is known to have length len > 0. +static inline void gen_normalize (cl_heap_ring* R, cl_SV_ringelt& result, uintL len) +{ + if (R->_zerop(result[len-1])) { + len--; + while (len > 0) { + if (!R->_zerop(result[len-1])) + break; + len--; + } + var cl_SV_ringelt newresult = cl_SV_ringelt(cl_make_heap_SV_ringelt_uninit(len)); + for (var sintL i = len-1; i >= 0; i--) + init1(_cl_ring_element, newresult[i]) (result[i]); + result = newresult; + } +} + +static void gen_fprint (cl_heap_univpoly_ring* UPR, cl_ostream stream, const _cl_UP& x) +{{ + DeclarePoly(cl_SV_ringelt,x); + var cl_heap_ring* R = TheRing(UPR->basering()); + var sintL xlen = x.length(); + if (xlen == 0) + fprint(stream, "0"); + else { + var cl_string varname = get_varname(UPR); + for (var sintL i = xlen-1; i >= 0; i--) + if (!R->_zerop(x[i])) { + if (i < xlen-1) + fprint(stream, " + "); + fprint(stream, "("); + R->_fprint(stream, x[i]); + fprint(stream, ")"); + if (i > 0) { + fprint(stream, "*"); + fprint(stream, varname); + if (i != 1) { + fprint(stream, "^"); + fprintdecimal(stream, i); + } + } + } + } +}} + +static cl_boolean gen_equal (cl_heap_univpoly_ring* UPR, const _cl_UP& x, const _cl_UP& y) +{{ + DeclarePoly(cl_SV_ringelt,x); + DeclarePoly(cl_SV_ringelt,y); + var cl_heap_ring* R = TheRing(UPR->basering()); + var sintL xlen = x.length(); + var sintL ylen = y.length(); + if (!(xlen == ylen)) + return cl_false; + for (var sintL i = xlen-1; i >= 0; i--) + if (!R->_equal(x[i],y[i])) + return cl_false; + return cl_true; +}} + +static const _cl_UP gen_zero (cl_heap_univpoly_ring* UPR) +{ + return _cl_UP(UPR, cl_null_SV_ringelt); +} + +static cl_boolean gen_zerop (cl_heap_univpoly_ring* UPR, const _cl_UP& x) +{ + unused UPR; + { DeclarePoly(cl_SV_ringelt,x); + var sintL xlen = x.length(); + if (xlen == 0) + return cl_true; + else + return cl_false; +}} + +static const _cl_UP gen_plus (cl_heap_univpoly_ring* UPR, const _cl_UP& x, const _cl_UP& y) +{{ + DeclarePoly(cl_SV_ringelt,x); + DeclarePoly(cl_SV_ringelt,y); + var cl_heap_ring* R = TheRing(UPR->basering()); + var sintL xlen = x.length(); + var sintL ylen = y.length(); + if (xlen == 0) + return _cl_UP(UPR, y); + if (ylen == 0) + return _cl_UP(UPR, x); + // Now xlen > 0, ylen > 0. + if (xlen > ylen) { + var cl_SV_ringelt result = cl_SV_ringelt(cl_make_heap_SV_ringelt_uninit(xlen)); + var sintL i; + for (i = xlen-1; i >= ylen; i--) + init1(_cl_ring_element, result[i]) (x[i]); + for (i = ylen-1; i >= 0; i--) + init1(_cl_ring_element, result[i]) (R->_plus(x[i],y[i])); + return _cl_UP(UPR, result); + } + if (xlen < ylen) { + var cl_SV_ringelt result = cl_SV_ringelt(cl_make_heap_SV_ringelt_uninit(ylen)); + var sintL i; + for (i = ylen-1; i >= xlen; i--) + init1(_cl_ring_element, result[i]) (y[i]); + for (i = xlen-1; i >= 0; i--) + init1(_cl_ring_element, result[i]) (R->_plus(x[i],y[i])); + return _cl_UP(UPR, result); + } + // Now xlen = ylen > 0. Add and normalize simultaneously. + for (var sintL i = xlen-1; i >= 0; i--) { + var _cl_ring_element hicoeff = R->_plus(x[i],y[i]); + if (!R->_zerop(hicoeff)) { + var cl_SV_ringelt result = cl_SV_ringelt(cl_make_heap_SV_ringelt_uninit(i+1)); + init1(_cl_ring_element, result[i]) (hicoeff); + for (i-- ; i >= 0; i--) + init1(_cl_ring_element, result[i]) (R->_plus(x[i],y[i])); + return _cl_UP(UPR, result); + } + } + return _cl_UP(UPR, cl_null_SV_ringelt); +}} + +static const _cl_UP gen_minus (cl_heap_univpoly_ring* UPR, const _cl_UP& x, const _cl_UP& y) +{{ + DeclarePoly(cl_SV_ringelt,x); + DeclarePoly(cl_SV_ringelt,y); + var cl_heap_ring* R = TheRing(UPR->basering()); + var sintL xlen = x.length(); + var sintL ylen = y.length(); + if (xlen == 0) + return _cl_UP(UPR, y); + if (ylen == 0) + return _cl_UP(UPR, x); + // Now xlen > 0, ylen > 0. + if (xlen > ylen) { + var cl_SV_ringelt result = cl_SV_ringelt(cl_make_heap_SV_ringelt_uninit(xlen)); + var sintL i; + for (i = xlen-1; i >= ylen; i--) + init1(_cl_ring_element, result[i]) (x[i]); + for (i = ylen-1; i >= 0; i--) + init1(_cl_ring_element, result[i]) (R->_minus(x[i],y[i])); + return _cl_UP(UPR, result); + } + if (xlen < ylen) { + var cl_SV_ringelt result = cl_SV_ringelt(cl_make_heap_SV_ringelt_uninit(ylen)); + var sintL i; + for (i = ylen-1; i >= xlen; i--) + init1(_cl_ring_element, result[i]) (R->_uminus(y[i])); + for (i = xlen-1; i >= 0; i--) + init1(_cl_ring_element, result[i]) (R->_minus(x[i],y[i])); + return _cl_UP(UPR, result); + } + // Now xlen = ylen > 0. Add and normalize simultaneously. + for (var sintL i = xlen-1; i >= 0; i--) { + var _cl_ring_element hicoeff = R->_minus(x[i],y[i]); + if (!R->_zerop(hicoeff)) { + var cl_SV_ringelt result = cl_SV_ringelt(cl_make_heap_SV_ringelt_uninit(i+1)); + init1(_cl_ring_element, result[i]) (hicoeff); + for (i-- ; i >= 0; i--) + init1(_cl_ring_element, result[i]) (R->_minus(x[i],y[i])); + return _cl_UP(UPR, result); + } + } + return _cl_UP(UPR, cl_null_SV_ringelt); +}} + +static const _cl_UP gen_uminus (cl_heap_univpoly_ring* UPR, const _cl_UP& x) +{{ + DeclarePoly(cl_SV_ringelt,x); + var cl_heap_ring* R = TheRing(UPR->basering()); + var sintL xlen = x.length(); + if (xlen == 0) + return _cl_UP(UPR, x); + // Now xlen > 0. + // Negate. No normalization necessary, since the degree doesn't change. + var sintL i = xlen-1; + var _cl_ring_element hicoeff = R->_uminus(x[i]); + if (R->_zerop(hicoeff)) cl_abort(); + var cl_SV_ringelt result = cl_SV_ringelt(cl_make_heap_SV_ringelt_uninit(xlen)); + init1(_cl_ring_element, result[i]) (hicoeff); + for (i-- ; i >= 0; i--) + init1(_cl_ring_element, result[i]) (R->_uminus(x[i])); + return _cl_UP(UPR, result); +}} + +static const _cl_UP gen_one (cl_heap_univpoly_ring* UPR) +{ + var cl_heap_ring* R = TheRing(UPR->basering()); + var cl_SV_ringelt result = cl_SV_ringelt(cl_make_heap_SV_ringelt_uninit(1)); + init1(_cl_ring_element, result[0]) (R->_one()); + return _cl_UP(UPR, result); +} + +static const _cl_UP gen_canonhom (cl_heap_univpoly_ring* UPR, const cl_I& x) +{ + var cl_heap_ring* R = TheRing(UPR->basering()); + var cl_SV_ringelt result = cl_SV_ringelt(cl_make_heap_SV_ringelt_uninit(1)); + init1(_cl_ring_element, result[0]) (R->_canonhom(x)); + return _cl_UP(UPR, result); +} + +static const _cl_UP gen_mul (cl_heap_univpoly_ring* UPR, const _cl_UP& x, const _cl_UP& y) +{{ + DeclarePoly(cl_SV_ringelt,x); + DeclarePoly(cl_SV_ringelt,y); + var cl_heap_ring* R = TheRing(UPR->basering()); + var sintL xlen = x.length(); + var sintL ylen = y.length(); + if (xlen == 0) + return _cl_UP(UPR, x); + if (ylen == 0) + return _cl_UP(UPR, y); + // Multiply. + var sintL len = xlen + ylen - 1; + var cl_SV_ringelt result = cl_SV_ringelt(cl_make_heap_SV_ringelt_uninit(len)); + if (xlen < ylen) { + { + var sintL i = xlen-1; + var _cl_ring_element xi = x[i]; + for (sintL j = ylen-1; j >= 0; j--) + init1(_cl_ring_element, result[i+j]) (R->_mul(xi,y[j])); + } + for (sintL i = xlen-2; i >= 0; i--) { + var _cl_ring_element xi = x[i]; + for (sintL j = ylen-1; j > 0; j--) + result[i+j] = R->_plus(result[i+j],R->_mul(xi,y[j])); + /* j=0 */ init1(_cl_ring_element, result[i]) (R->_mul(xi,y[0])); + } + } else { + { + var sintL j = ylen-1; + var _cl_ring_element yj = y[j]; + for (sintL i = xlen-1; i >= 0; i--) + init1(_cl_ring_element, result[i+j]) (R->_mul(x[i],yj)); + } + for (sintL j = ylen-2; j >= 0; j--) { + var _cl_ring_element yj = y[j]; + for (sintL i = xlen-1; i > 0; i--) + result[i+j] = R->_plus(result[i+j],R->_mul(x[i],yj)); + /* i=0 */ init1(_cl_ring_element, result[j]) (R->_mul(x[0],yj)); + } + } + // Normalize (not necessary in integral domains). + //gen_normalize(R,result,len); + if (R->_zerop(result[len-1])) cl_abort(); + return _cl_UP(UPR, result); +}} + +static const _cl_UP gen_square (cl_heap_univpoly_ring* UPR, const _cl_UP& x) +{{ + DeclarePoly(cl_SV_ringelt,x); + var cl_heap_ring* R = TheRing(UPR->basering()); + var sintL xlen = x.length(); + if (xlen == 0) + return cl_UP(UPR, x); + var sintL len = 2*xlen-1; + var cl_SV_ringelt result = cl_SV_ringelt(cl_make_heap_SV_ringelt_uninit(len)); + if (xlen > 1) { + // Loop through all 0 <= j < i <= xlen-1. + { + var sintL i = xlen-1; + var _cl_ring_element xi = x[i]; + for (sintL j = i-1; j >= 0; j--) + init1(_cl_ring_element, result[i+j]) (R->_mul(xi,x[j])); + } + {for (sintL i = xlen-2; i >= 1; i--) { + var _cl_ring_element xi = x[i]; + for (sintL j = i-1; j >= 1; j--) + result[i+j] = R->_plus(result[i+j],R->_mul(xi,x[j])); + /* j=0 */ init1(_cl_ring_element, result[i]) (R->_mul(xi,x[0])); + }} + // Double. + {for (sintL i = len-2; i >= 1; i--) + result[i] = R->_plus(result[i],result[i]); + } + // Add squares. + init1(_cl_ring_element, result[2*(xlen-1)]) (R->_square(x[xlen-1])); + for (sintL i = xlen-2; i >= 1; i--) + result[2*i] = R->_plus(result[2*i],R->_square(x[i])); + } + init1(_cl_ring_element, result[0]) (R->_square(x[0])); + // Normalize (not necessary in integral domains). + //gen_normalize(R,result,len); + if (R->_zerop(result[len-1])) cl_abort(); + return _cl_UP(UPR, result); +}} + +static const _cl_UP gen_exptpos (cl_heap_univpoly_ring* UPR, const _cl_UP& x, const cl_I& y) +{ + var _cl_UP a = x; + var cl_I b = y; + while (!oddp(b)) { a = UPR->_square(a); b = b >> 1; } + var _cl_UP c = a; + until (b == 1) + { b = b >> 1; + a = UPR->_square(a); + if (oddp(b)) { c = UPR->_mul(a,c); } + } + return c; +} + +static const _cl_UP gen_scalmul (cl_heap_univpoly_ring* UPR, const cl_ring_element& x, const _cl_UP& y) +{ + if (!(UPR->basering() == x.ring())) cl_abort(); + { + DeclarePoly(cl_SV_ringelt,y); + var cl_heap_ring* R = TheRing(UPR->basering()); + var sintL ylen = y.length(); + if (ylen == 0) + return _cl_UP(UPR, y); + if (R->zerop(x)) + return _cl_UP(UPR, cl_null_SV_ringelt); + var cl_SV_ringelt result = cl_SV_ringelt(cl_make_heap_SV_ringelt_uninit(ylen)); + for (sintL i = ylen-1; i >= 0; i--) + init1(_cl_ring_element, result[i]) (R->_mul(x,y[i])); + // Normalize (not necessary in integral domains). + //gen_normalize(R,result,ylen); + if (R->_zerop(result[ylen-1])) cl_abort(); + return _cl_UP(UPR, result); +}} + +static sintL gen_degree (cl_heap_univpoly_ring* UPR, const _cl_UP& x) +{ + unused UPR; + { DeclarePoly(cl_SV_ringelt,x); + return (sintL) x.length() - 1; +}} + +static const _cl_UP gen_monomial (cl_heap_univpoly_ring* UPR, const cl_ring_element& x, uintL e) +{ + if (!(UPR->basering() == x.ring())) cl_abort(); + var cl_heap_ring* R = TheRing(UPR->basering()); + if (R->_zerop(x)) + return _cl_UP(UPR, cl_null_SV_ringelt); + else { + var sintL len = e+1; + var cl_SV_ringelt result = cl_SV_ringelt(len); + result[e] = x; + return _cl_UP(UPR, result); + } +} + +static const cl_ring_element gen_coeff (cl_heap_univpoly_ring* UPR, const _cl_UP& x, uintL index) +{{ + DeclarePoly(cl_SV_ringelt,x); + var cl_heap_ring* R = TheRing(UPR->basering()); + if (index < x.length()) + return cl_ring_element(R, x[index]); + else + return R->zero(); +}} + +static const _cl_UP gen_create (cl_heap_univpoly_ring* UPR, sintL deg) +{ + if (deg < 0) + return _cl_UP(UPR, cl_null_SV_ringelt); + else { + var sintL len = deg+1; + return _cl_UP(UPR, cl_SV_ringelt(len)); + } +} + +static void gen_set_coeff (cl_heap_univpoly_ring* UPR, _cl_UP& x, uintL index, const cl_ring_element& y) +{{ + DeclareMutablePoly(cl_SV_ringelt,x); + if (!(UPR->basering() == y.ring())) cl_abort(); + if (!(index < x.length())) cl_abort(); + x[index] = y; +}} + +static void gen_finalize (cl_heap_univpoly_ring* UPR, _cl_UP& x) +{{ + DeclareMutablePoly(cl_SV_ringelt,x); // NB: x is modified by reference! + var cl_heap_ring* R = TheRing(UPR->basering()); + var uintL len = x.length(); + if (len > 0) + gen_normalize(R,x,len); +}} + +static const cl_ring_element gen_eval (cl_heap_univpoly_ring* UPR, const _cl_UP& x, const cl_ring_element& y) +{{ + // Method: + // If x = 0, return 0. + // If y = 0, return x[0]. + // Else compute (...(x[len-1]*y+x[len-2])*y ...)*y + x[0]. + DeclarePoly(cl_SV_ringelt,x); + var cl_heap_ring* R = TheRing(UPR->basering()); + if (!(y.ring() == R)) cl_abort(); + var uintL len = x.length(); + if (len==0) + return R->zero(); + if (R->_zerop(y)) + return cl_ring_element(R, x[0]); + var sintL i = len-1; + var _cl_ring_element z = x[i]; + for ( ; --i >= 0; ) + z = R->_plus(R->_mul(z,y),x[i]); + return cl_ring_element(R, z); +}} + +static cl_univpoly_setops gen_setops = { + gen_fprint, + gen_equal +}; + +static cl_univpoly_addops gen_addops = { + gen_zero, + gen_zerop, + gen_plus, + gen_minus, + gen_uminus +}; + +static cl_univpoly_mulops gen_mulops = { + gen_one, + gen_canonhom, + gen_mul, + gen_square, + gen_exptpos +}; + +static cl_univpoly_modulops gen_modulops = { + gen_scalmul +}; + +static cl_univpoly_polyops gen_polyops = { + gen_degree, + gen_monomial, + gen_coeff, + gen_create, + gen_set_coeff, + gen_finalize, + gen_eval +}; + +class cl_heap_gen_univpoly_ring : public cl_heap_univpoly_ring { + SUBCLASS_cl_heap_univpoly_ring() +public: + // Constructor. + cl_heap_gen_univpoly_ring (const cl_ring& r) + : cl_heap_univpoly_ring (r, &gen_setops, &gen_addops, &gen_mulops, &gen_modulops, &gen_polyops) {} +}; diff --git a/src/polynomial/elem/cl_UP_named.cc b/src/polynomial/elem/cl_UP_named.cc new file mode 100644 index 0000000..959f08b --- /dev/null +++ b/src/polynomial/elem/cl_UP_named.cc @@ -0,0 +1,73 @@ +// cl_find_univpoly_ring(). + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_UP_named) + +// Specification. +#include "cl_univpoly.h" + + +// Implementation. + +#include "cl_UP.h" + +// Create a new univariate polynomial ring with a named variable. + +static inline cl_heap_univpoly_ring* cl_make_univpoly_ring (const cl_ring& r, const cl_symbol& varname) +{ + cl_heap_univpoly_ring* UPR = cl_make_univpoly_ring(r); + UPR->add_property(new cl_varname_property(cl_univpoly_varname_key,varname)); + return UPR; +} + + +// The table of univariate polynomial rings with named variable. +// A weak hash table (cl_ring,cl_symbol) -> cl_univpoly_ring. + +#include "cl_rcpointer2_hashweak_rcpointer.h" + +// An entry can be collected when the value (the ring) isn't referenced any more +// except from the hash table, and when the keys (the base ring and the name) +// are't referenced any more except from the hash table and the ring. Note that +// the ring contains exactly one reference to the base ring and exactly one +// reference to the name (on the property list). + +static cl_boolean maygc_htentry (const cl_htentry_from_rcpointer2_to_rcpointer& entry) +{ + if (!entry.key1.pointer_p() || (entry.key1.heappointer->refcount == 2)) + if (!entry.key2.pointer_p() || (entry.key2.heappointer->refcount == 2)) + if (!entry.val.pointer_p() || (entry.val.heappointer->refcount == 1)) + return cl_true; + return cl_false; +} + +static const cl_wht_from_rcpointer2_to_rcpointer univpoly_ring_table = cl_wht_from_rcpointer2_to_rcpointer(maygc_htentry); + +static inline cl_univpoly_ring* get_univpoly_ring (const cl_ring& r, const cl_symbol& v) +{ + return (cl_univpoly_ring*) univpoly_ring_table.get(r,v); +} + +static inline void store_univpoly_ring (const cl_univpoly_ring& R) +{ + univpoly_ring_table.put(R->basering(), ((cl_varname_property*)(R->get_property(cl_univpoly_varname_key)))->varname, + R); +} + + +const cl_univpoly_ring cl_find_univpoly_ring (const cl_ring& r, const cl_symbol& varname) +{ + var cl_univpoly_ring* ring_in_table = get_univpoly_ring(r,varname); + if (!ring_in_table) { + var cl_univpoly_ring R = cl_make_univpoly_ring(r,varname); + store_univpoly_ring(R); + ring_in_table = get_univpoly_ring(r,varname); + if (!ring_in_table) + cl_abort(); + } + return *ring_in_table; +} + +CL_PROVIDE_END(cl_UP_named) diff --git a/src/polynomial/elem/cl_UP_no_ring.cc b/src/polynomial/elem/cl_UP_no_ring.cc new file mode 100644 index 0000000..199fcf0 --- /dev/null +++ b/src/polynomial/elem/cl_UP_no_ring.cc @@ -0,0 +1,202 @@ +// Dummy ring. + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_UP_no_ring) + +// Specification. +#include "cl_univpoly.h" + + +// Implementation. + +#include "cl_io.h" +#include "cl_abort.h" + +nonreturning_function(static, uninitialized_ring, (void)); +static void uninitialized_ring () +{ + fprint(cl_stderr, "Uninitialized ring operation called\n"); + cl_abort(); +} + +nonreturning_function(static, uninitialized_error, (const _cl_UP&)); +static void uninitialized_error (const _cl_UP& obj) +{ + fprint(cl_stderr, "Uninitialized ring element @0x"); + fprinthexadecimal(cl_stderr, (unsigned long)(void*)&obj); + fprint(cl_stderr, ": 0x"); + fprinthexadecimal(cl_stderr, (unsigned long)obj.rep.word); + fprint(cl_stderr, "\n"); + cl_abort(); +} + +#if ((defined(__sparc__) || defined(__sparc64__)) && !defined(__GNUC__)) + // avoid Sun C++ 4.1 compiler bug + #define RETDUMMY return *(_cl_UP*)R +#else + #define RETDUMMY return *(_cl_UP*)0 +#endif + +static const _cl_UP dummy_op0 (cl_heap_univpoly_ring* R) +{ + unused R; + uninitialized_ring(); RETDUMMY; +} + +static const _cl_UP dummy_op1 (cl_heap_univpoly_ring* R, const _cl_UP& x) +{ + unused R; + uninitialized_error(x); RETDUMMY; +} + +static const _cl_UP dummy_op2 (cl_heap_univpoly_ring* R, const _cl_UP& x, const _cl_UP& y) +{ + unused R; + uninitialized_error(x); uninitialized_error(y); RETDUMMY; +} + +static void dummy_fprint (cl_heap_univpoly_ring* R, cl_ostream stream, const _cl_UP& x) +{ + unused R; + unused stream; + uninitialized_error(x); +} +static cl_boolean dummy_equal (cl_heap_univpoly_ring* R, const _cl_UP& x, const _cl_UP& y) +{ + unused R; + uninitialized_error(x); uninitialized_error(y); return cl_false; +} + +#define dummy_zero dummy_op0 +static cl_boolean dummy_zerop (cl_heap_univpoly_ring* R, const _cl_UP& x) +{ + unused R; + uninitialized_error(x); return cl_false; +} +#define dummy_plus dummy_op2 +#define dummy_minus dummy_op2 +#define dummy_uminus dummy_op1 + +#define dummy_one dummy_op0 +static const _cl_UP dummy_canonhom (cl_heap_univpoly_ring* R, const cl_I& x) +{ + unused R; + (void)&x; // unused x; + uninitialized_ring(); RETDUMMY; +} +#define dummy_mul dummy_op2 +#define dummy_square dummy_op1 +static const _cl_UP dummy_expt_pos (cl_heap_univpoly_ring* R, const _cl_UP& x, const cl_I& y) +{ + unused R; + (void)&y; // unused y; + uninitialized_error(x); RETDUMMY; +} + +static const _cl_UP dummy_scalmul (cl_heap_univpoly_ring* R, const cl_ring_element& x, const _cl_UP& y) +{ + unused R; + unused x; + uninitialized_error(y); RETDUMMY; +} + +static sintL dummy_degree (cl_heap_univpoly_ring* R, const _cl_UP& x) +{ + unused R; + uninitialized_error(x); return 0; +} +static const _cl_UP dummy_monomial (cl_heap_univpoly_ring* R, const cl_ring_element& x, uintL e) +{ + unused R; + unused x; + unused e; + uninitialized_ring(); RETDUMMY; +} +static const cl_ring_element dummy_coeff (cl_heap_univpoly_ring* R, const _cl_UP& x, uintL index) +{ + unused R; + unused index; + uninitialized_error(x); return *(cl_ring_element*)0; +} +static const _cl_UP dummy_create (cl_heap_univpoly_ring* R, sintL deg) +{ + unused R; + unused deg; + uninitialized_ring(); RETDUMMY; +} +static void dummy_set_coeff (cl_heap_univpoly_ring* R, _cl_UP& x, uintL index, const cl_ring_element& y) +{ + unused R; + unused index; + unused y; + uninitialized_error(x); +} +static void dummy_finalize (cl_heap_univpoly_ring* R, _cl_UP& x) +{ + unused R; + uninitialized_error(x); +} +static const cl_ring_element dummy_eval (cl_heap_univpoly_ring* R, const _cl_UP& x, const cl_ring_element& y) +{ + unused R; + unused y; + uninitialized_error(x); return *(cl_ring_element*)0; +} + +static cl_univpoly_setops dummy_setops = { + dummy_fprint, + dummy_equal +}; +static cl_univpoly_addops dummy_addops = { + dummy_zero, + dummy_zerop, + dummy_plus, + dummy_minus, + dummy_uminus +}; +static cl_univpoly_mulops dummy_mulops = { + dummy_one, + dummy_canonhom, + dummy_mul, + dummy_square, + dummy_expt_pos +}; +static cl_univpoly_modulops dummy_modulops = { + dummy_scalmul +}; +static cl_univpoly_polyops dummy_polyops = { + dummy_degree, + dummy_monomial, + dummy_coeff, + dummy_create, + dummy_set_coeff, + dummy_finalize, + dummy_eval +}; + +class cl_heap_no_univpoly_ring : public cl_heap_univpoly_ring { + SUBCLASS_cl_heap_univpoly_ring() +public: + // Constructor. + cl_heap_no_univpoly_ring () + : cl_heap_univpoly_ring (cl_no_ring,&dummy_setops,&dummy_addops,&dummy_mulops,&dummy_modulops,&dummy_polyops) + { type = &cl_class_no_univpoly_ring; } + // Destructor. + ~cl_heap_no_univpoly_ring () {} +}; + +static void cl_no_univpoly_ring_destructor (cl_heap* pointer) +{ + (*(cl_heap_no_univpoly_ring*)pointer).~cl_heap_no_univpoly_ring(); +} + +cl_class cl_class_no_univpoly_ring = { + cl_no_univpoly_ring_destructor, + 0 +}; + +const cl_univpoly_ring cl_no_univpoly_ring = cl_univpoly_ring (new cl_heap_no_univpoly_ring()); + +CL_PROVIDE_END(cl_UP_no_ring) diff --git a/src/polynomial/elem/cl_UP_number.h b/src/polynomial/elem/cl_UP_number.h new file mode 100644 index 0000000..37e8c58 --- /dev/null +++ b/src/polynomial/elem/cl_UP_number.h @@ -0,0 +1,453 @@ +// Univariate Polynomials over some subring of the numbers. + +#include "cl_SV_number.h" +#include "cl_number.h" +#include "cl_integer.h" +#include "cl_abort.h" + +// Assume a ring is a number ring. + inline cl_heap_number_ring* TheNumberRing (const cl_ring& R) + { return (cl_heap_number_ring*) R.heappointer; } + +// Normalize a vector: remove leading zero coefficients. +// The result vector is known to have length len > 0. +static inline void num_normalize (cl_number_ring_ops& ops, cl_SV_number& result, uintL len) +{ + if (ops.zerop(result[len-1])) { + len--; + while (len > 0) { + if (!ops.zerop(result[len-1])) + break; + len--; + } + var cl_SV_number newresult = cl_SV_number(cl_make_heap_SV_number_uninit(len)); + for (var sintL i = len-1; i >= 0; i--) + init1(cl_number, newresult[i]) (result[i]); + result = newresult; + } +} + +static void num_fprint (cl_heap_univpoly_ring* UPR, cl_ostream stream, const _cl_UP& x) +{{ + DeclarePoly(cl_SV_number,x); + var cl_number_ring_ops& ops = *TheNumberRing(UPR->basering())->ops; + var sintL xlen = x.length(); + if (xlen == 0) + fprint(stream, "0"); + else { + var const cl_ring& R = UPR->basering(); + var cl_string varname = get_varname(UPR); + for (var sintL i = xlen-1; i >= 0; i--) + if (!ops.zerop(x[i])) { + if (i < xlen-1) + fprint(stream, " + "); + fprint(stream, cl_ring_element(R,x[i])); + if (i > 0) { + fprint(stream, "*"); + fprint(stream, varname); + if (i != 1) { + fprint(stream, "^"); + fprintdecimal(stream, i); + } + } + } + } +}} + +static cl_boolean num_equal (cl_heap_univpoly_ring* UPR, const _cl_UP& x, const _cl_UP& y) +{{ + DeclarePoly(cl_SV_number,x); + DeclarePoly(cl_SV_number,y); + var cl_number_ring_ops& ops = *TheNumberRing(UPR->basering())->ops; + var sintL xlen = x.length(); + var sintL ylen = y.length(); + if (!(xlen == ylen)) + return cl_false; + for (var sintL i = xlen-1; i >= 0; i--) + if (!ops.equal(x[i],y[i])) + return cl_false; + return cl_true; +}} + +static const _cl_UP num_zero (cl_heap_univpoly_ring* UPR) +{ + return _cl_UP(UPR, cl_null_SV_number); +} + +static cl_boolean num_zerop (cl_heap_univpoly_ring* UPR, const _cl_UP& x) +{ + unused UPR; + { DeclarePoly(cl_SV_number,x); + var sintL xlen = x.length(); + if (xlen == 0) + return cl_true; + else + return cl_false; +}} + +static const _cl_UP num_plus (cl_heap_univpoly_ring* UPR, const _cl_UP& x, const _cl_UP& y) +{{ + DeclarePoly(cl_SV_number,x); + DeclarePoly(cl_SV_number,y); + var cl_number_ring_ops& ops = *TheNumberRing(UPR->basering())->ops; + var sintL xlen = x.length(); + var sintL ylen = y.length(); + if (xlen == 0) + return _cl_UP(UPR, y); + if (ylen == 0) + return _cl_UP(UPR, x); + // Now xlen > 0, ylen > 0. + if (xlen > ylen) { + var cl_SV_number result = cl_SV_number(cl_make_heap_SV_number_uninit(xlen)); + var sintL i; + for (i = xlen-1; i >= ylen; i--) + init1(cl_number, result[i]) (x[i]); + for (i = ylen-1; i >= 0; i--) + init1(cl_number, result[i]) (ops.plus(x[i],y[i])); + return _cl_UP(UPR, result); + } + if (xlen < ylen) { + var cl_SV_number result = cl_SV_number(cl_make_heap_SV_number_uninit(ylen)); + var sintL i; + for (i = ylen-1; i >= xlen; i--) + init1(cl_number, result[i]) (y[i]); + for (i = xlen-1; i >= 0; i--) + init1(cl_number, result[i]) (ops.plus(x[i],y[i])); + return _cl_UP(UPR, result); + } + // Now xlen = ylen > 0. Add and normalize simultaneously. + for (var sintL i = xlen-1; i >= 0; i--) { + var cl_number hicoeff = ops.plus(x[i],y[i]); + if (!ops.zerop(hicoeff)) { + var cl_SV_number result = cl_SV_number(cl_make_heap_SV_number_uninit(i+1)); + init1(cl_number, result[i]) (hicoeff); + for (i-- ; i >= 0; i--) + init1(cl_number, result[i]) (ops.plus(x[i],y[i])); + return _cl_UP(UPR, result); + } + } + return _cl_UP(UPR, cl_null_SV_number); +}} + +static const _cl_UP num_minus (cl_heap_univpoly_ring* UPR, const _cl_UP& x, const _cl_UP& y) +{{ + DeclarePoly(cl_SV_number,x); + DeclarePoly(cl_SV_number,y); + var cl_number_ring_ops& ops = *TheNumberRing(UPR->basering())->ops; + var sintL xlen = x.length(); + var sintL ylen = y.length(); + if (xlen == 0) + return _cl_UP(UPR, y); + if (ylen == 0) + return _cl_UP(UPR, x); + // Now xlen > 0, ylen > 0. + if (xlen > ylen) { + var cl_SV_number result = cl_SV_number(cl_make_heap_SV_number_uninit(xlen)); + var sintL i; + for (i = xlen-1; i >= ylen; i--) + init1(cl_number, result[i]) (x[i]); + for (i = ylen-1; i >= 0; i--) + init1(cl_number, result[i]) (ops.minus(x[i],y[i])); + return _cl_UP(UPR, result); + } + if (xlen < ylen) { + var cl_SV_number result = cl_SV_number(cl_make_heap_SV_number_uninit(ylen)); + var sintL i; + for (i = ylen-1; i >= xlen; i--) + init1(cl_number, result[i]) (ops.uminus(y[i])); + for (i = xlen-1; i >= 0; i--) + init1(cl_number, result[i]) (ops.minus(x[i],y[i])); + return _cl_UP(UPR, result); + } + // Now xlen = ylen > 0. Add and normalize simultaneously. + for (var sintL i = xlen-1; i >= 0; i--) { + var cl_number hicoeff = ops.minus(x[i],y[i]); + if (!ops.zerop(hicoeff)) { + var cl_SV_number result = cl_SV_number(cl_make_heap_SV_number_uninit(i+1)); + init1(cl_number, result[i]) (hicoeff); + for (i-- ; i >= 0; i--) + init1(cl_number, result[i]) (ops.minus(x[i],y[i])); + return _cl_UP(UPR, result); + } + } + return _cl_UP(UPR, cl_null_SV_number); +}} + +static const _cl_UP num_uminus (cl_heap_univpoly_ring* UPR, const _cl_UP& x) +{{ + DeclarePoly(cl_SV_number,x); + var cl_number_ring_ops& ops = *TheNumberRing(UPR->basering())->ops; + var sintL xlen = x.length(); + if (xlen == 0) + return _cl_UP(UPR, x); + // Now xlen > 0. + // Negate. No normalization necessary, since the degree doesn't change. + var sintL i = xlen-1; + var cl_number hicoeff = ops.uminus(x[i]); + if (ops.zerop(hicoeff)) cl_abort(); + var cl_SV_number result = cl_SV_number(cl_make_heap_SV_number_uninit(xlen)); + init1(cl_number, result[i]) (hicoeff); + for (i-- ; i >= 0; i--) + init1(cl_number, result[i]) (ops.uminus(x[i])); + return _cl_UP(UPR, result); +}} + +static const _cl_UP num_one (cl_heap_univpoly_ring* UPR) +{ + var cl_SV_number result = cl_SV_number(cl_make_heap_SV_number_uninit(1)); + init1(cl_number, result[0]) (1); + return _cl_UP(UPR, result); +} + +static const _cl_UP num_canonhom (cl_heap_univpoly_ring* UPR, const cl_I& x) +{ + var cl_SV_number result = cl_SV_number(cl_make_heap_SV_number_uninit(1)); + init1(cl_number, result[0]) (x); + return _cl_UP(UPR, result); +} + +static const _cl_UP num_mul (cl_heap_univpoly_ring* UPR, const _cl_UP& x, const _cl_UP& y) +{{ + DeclarePoly(cl_SV_number,x); + DeclarePoly(cl_SV_number,y); + var cl_number_ring_ops& ops = *TheNumberRing(UPR->basering())->ops; + var sintL xlen = x.length(); + var sintL ylen = y.length(); + if (xlen == 0) + return _cl_UP(UPR, x); + if (ylen == 0) + return _cl_UP(UPR, y); + // Multiply. + var sintL len = xlen + ylen - 1; + var cl_SV_number result = cl_SV_number(cl_make_heap_SV_number_uninit(len)); + if (xlen < ylen) { + { + var sintL i = xlen-1; + var cl_number xi = x[i]; + for (sintL j = ylen-1; j >= 0; j--) + init1(cl_number, result[i+j]) (ops.mul(xi,y[j])); + } + for (sintL i = xlen-2; i >= 0; i--) { + var cl_number xi = x[i]; + for (sintL j = ylen-1; j > 0; j--) + result[i+j] = ops.plus(result[i+j],ops.mul(xi,y[j])); + /* j=0 */ init1(cl_number, result[i]) (ops.mul(xi,y[0])); + } + } else { + { + var sintL j = ylen-1; + var cl_number yj = y[j]; + for (sintL i = xlen-1; i >= 0; i--) + init1(cl_number, result[i+j]) (ops.mul(x[i],yj)); + } + for (sintL j = ylen-2; j >= 0; j--) { + var cl_number yj = y[j]; + for (sintL i = xlen-1; i > 0; i--) + result[i+j] = ops.plus(result[i+j],ops.mul(x[i],yj)); + /* i=0 */ init1(cl_number, result[j]) (ops.mul(x[0],yj)); + } + } + // Normalize (not necessary in integral domains). + //num_normalize(ops,result,len); + if (ops.zerop(result[len-1])) cl_abort(); + return _cl_UP(UPR, result); +}} + +static const _cl_UP num_square (cl_heap_univpoly_ring* UPR, const _cl_UP& x) +{{ + DeclarePoly(cl_SV_number,x); + var cl_number_ring_ops& ops = *TheNumberRing(UPR->basering())->ops; + var sintL xlen = x.length(); + if (xlen == 0) + return cl_UP(UPR, x); + var sintL len = 2*xlen-1; + var cl_SV_number result = cl_SV_number(cl_make_heap_SV_number_uninit(len)); + if (xlen > 1) { + // Loop through all 0 <= j < i <= xlen-1. + { + var sintL i = xlen-1; + var cl_number xi = x[i]; + for (sintL j = i-1; j >= 0; j--) + init1(cl_number, result[i+j]) (ops.mul(xi,x[j])); + } + {for (sintL i = xlen-2; i >= 1; i--) { + var cl_number xi = x[i]; + for (sintL j = i-1; j >= 1; j--) + result[i+j] = ops.plus(result[i+j],ops.mul(xi,x[j])); + /* j=0 */ init1(cl_number, result[i]) (ops.mul(xi,x[0])); + }} + // Double. + {for (sintL i = len-2; i >= 1; i--) + result[i] = ops.plus(result[i],result[i]); + } + // Add squares. + init1(cl_number, result[2*(xlen-1)]) (ops.square(x[xlen-1])); + for (sintL i = xlen-2; i >= 1; i--) + result[2*i] = ops.plus(result[2*i],ops.square(x[i])); + } + init1(cl_number, result[0]) (ops.square(x[0])); + // Normalize (not necessary in integral domains). + //num_normalize(ops,result,len); + if (ops.zerop(result[len-1])) cl_abort(); + return _cl_UP(UPR, result); +}} + +static const _cl_UP num_exptpos (cl_heap_univpoly_ring* UPR, const _cl_UP& x, const cl_I& y) +{ + var _cl_UP a = x; + var cl_I b = y; + while (!oddp(b)) { a = UPR->_square(a); b = b >> 1; } + var _cl_UP c = a; + until (b == 1) + { b = b >> 1; + a = UPR->_square(a); + if (oddp(b)) { c = UPR->_mul(a,c); } + } + return c; +} + +static const _cl_UP num_scalmul (cl_heap_univpoly_ring* UPR, const cl_ring_element& x, const _cl_UP& y) +{ + if (!(UPR->basering() == x.ring())) cl_abort(); + { + DeclarePoly(cl_number,x); + DeclarePoly(cl_SV_number,y); + var cl_number_ring_ops& ops = *TheNumberRing(UPR->basering())->ops; + var sintL ylen = y.length(); + if (ylen == 0) + return _cl_UP(UPR, y); + if (ops.zerop(x)) + return _cl_UP(UPR, cl_null_SV_number); + // Now ylen > 0. + // No normalization necessary, since the degree doesn't change. + var cl_SV_number result = cl_SV_number(cl_make_heap_SV_number_uninit(ylen)); + for (sintL i = ylen-1; i >= 0; i--) + init1(cl_number, result[i]) (ops.mul(x,y[i])); + return _cl_UP(UPR, result); +}} + +static sintL num_degree (cl_heap_univpoly_ring* UPR, const _cl_UP& x) +{ + unused UPR; + { DeclarePoly(cl_SV_number,x); + return (sintL) x.length() - 1; +}} + +static const _cl_UP num_monomial (cl_heap_univpoly_ring* UPR, const cl_ring_element& x, uintL e) +{ + if (!(UPR->basering() == x.ring())) cl_abort(); + { DeclarePoly(cl_number,x); + var cl_number_ring_ops& ops = *TheNumberRing(UPR->basering())->ops; + if (ops.zerop(x)) + return _cl_UP(UPR, cl_null_SV_number); + else { + var sintL len = e+1; + var cl_SV_number result = cl_SV_number(len); + result[e] = x; + return _cl_UP(UPR, result); + } +}} + +static const cl_ring_element num_coeff (cl_heap_univpoly_ring* UPR, const _cl_UP& x, uintL index) +{{ + DeclarePoly(cl_SV_number,x); + var cl_heap_number_ring* R = TheNumberRing(UPR->basering()); + if (index < x.length()) + return cl_ring_element(R, x[index]); + else + return R->zero(); +}} + +static const _cl_UP num_create (cl_heap_univpoly_ring* UPR, sintL deg) +{ + if (deg < 0) + return _cl_UP(UPR, cl_null_SV_number); + else { + var sintL len = deg+1; + return _cl_UP(UPR, cl_SV_number(len)); + } +} + +static void num_set_coeff (cl_heap_univpoly_ring* UPR, _cl_UP& x, uintL index, const cl_ring_element& y) +{{ + DeclareMutablePoly(cl_SV_number,x); + if (!(UPR->basering() == y.ring())) cl_abort(); + { DeclarePoly(cl_number,y); + if (!(index < x.length())) cl_abort(); + x[index] = y; +}}} + +static void num_finalize (cl_heap_univpoly_ring* UPR, _cl_UP& x) +{{ + DeclareMutablePoly(cl_SV_number,x); // NB: x is modified by reference! + var cl_number_ring_ops& ops = *TheNumberRing(UPR->basering())->ops; + var uintL len = x.length(); + if (len > 0) + num_normalize(ops,x,len); +}} + +static const cl_ring_element num_eval (cl_heap_univpoly_ring* UPR, const _cl_UP& x, const cl_ring_element& y) +{{ + // Method: + // If x = 0, return 0. + // If y = 0, return x[0]. + // Else compute (...(x[len-1]*y+x[len-2])*y ...)*y + x[0]. + DeclarePoly(cl_SV_number,x); + if (!(UPR->basering() == y.ring())) cl_abort(); + { DeclarePoly(cl_number,y); + var cl_heap_number_ring* R = TheNumberRing(UPR->basering()); + var cl_number_ring_ops& ops = *R->ops; + var uintL len = x.length(); + if (len==0) + return R->zero(); + if (ops.zerop(y)) + return cl_ring_element(R, x[0]); + var sintL i = len-1; + var cl_number z = x[i]; + for ( ; --i >= 0; ) + z = ops.plus(ops.mul(z,y),x[i]); + return cl_ring_element(R, z); +}}} + +static cl_univpoly_setops num_setops = { + num_fprint, + num_equal +}; + +static cl_univpoly_addops num_addops = { + num_zero, + num_zerop, + num_plus, + num_minus, + num_uminus +}; + +static cl_univpoly_mulops num_mulops = { + num_one, + num_canonhom, + num_mul, + num_square, + num_exptpos +}; + +static cl_univpoly_modulops num_modulops = { + num_scalmul +}; + +static cl_univpoly_polyops num_polyops = { + num_degree, + num_monomial, + num_coeff, + num_create, + num_set_coeff, + num_finalize, + num_eval +}; + +class cl_heap_num_univpoly_ring : public cl_heap_univpoly_ring { + SUBCLASS_cl_heap_univpoly_ring() +public: + // Constructor. + cl_heap_num_univpoly_ring (const cl_ring& r) + : cl_heap_univpoly_ring (r, &num_setops, &num_addops, &num_mulops, &num_modulops, &num_polyops) {} +}; diff --git a/src/polynomial/elem/cl_UP_unnamed.cc b/src/polynomial/elem/cl_UP_unnamed.cc new file mode 100644 index 0000000..a37a992 --- /dev/null +++ b/src/polynomial/elem/cl_UP_unnamed.cc @@ -0,0 +1,61 @@ +// cl_find_univpoly_ring(). + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_UP_unnamed) + +// Specification. +#include "cl_univpoly.h" + + +// Implementation. + +#include "cl_UP.h" + +// The table of univariate polynomial rings without named variable. +// A weak hash table cl_ring -> cl_univpoly_ring. +// (It could also be a weak hashuniq table cl_ring -> cl_univpoly_ring.) + +#include "cl_rcpointer_hashweak_rcpointer.h" + +// An entry can be collected when the value (the ring) isn't referenced any more +// except from the hash table, and when the key (the base ring) isn't referenced +// any more except from the hash table and the ring. Note that the ring contains +// exactly one reference to the base ring. + +static cl_boolean maygc_htentry (const cl_htentry_from_rcpointer_to_rcpointer& entry) +{ + if (!entry.key.pointer_p() || (entry.key.heappointer->refcount == 2)) + if (!entry.val.pointer_p() || (entry.val.heappointer->refcount == 1)) + return cl_true; + return cl_false; +} + +static const cl_wht_from_rcpointer_to_rcpointer univpoly_ring_table = cl_wht_from_rcpointer_to_rcpointer(maygc_htentry); + +static inline cl_univpoly_ring* get_univpoly_ring (const cl_ring& r) +{ + return (cl_univpoly_ring*) univpoly_ring_table.get(r); +} + +static inline void store_univpoly_ring (const cl_univpoly_ring& R) +{ + univpoly_ring_table.put(R->basering(),R); +} + + +const cl_univpoly_ring cl_find_univpoly_ring (const cl_ring& r) +{ + var cl_univpoly_ring* ring_in_table = get_univpoly_ring(r); + if (!ring_in_table) { + var cl_univpoly_ring R = cl_make_univpoly_ring(r); + store_univpoly_ring(R); + ring_in_table = get_univpoly_ring(r); + if (!ring_in_table) + cl_abort(); + } + return *ring_in_table; +} + +CL_PROVIDE_END(cl_UP_unnamed) diff --git a/src/polynomial/elem/cl_asm_GF2.cc b/src/polynomial/elem/cl_asm_GF2.cc new file mode 100644 index 0000000..dbdfb68 --- /dev/null +++ b/src/polynomial/elem/cl_asm_GF2.cc @@ -0,0 +1,8 @@ +// Includes the CPU specific cl_asm_*.cc file. + +#include "cl_config.h" + +#if defined(__sparc__) || defined(__sparc64__) + #include "cl_asm_sparc_GF2.cc" +#endif + diff --git a/src/polynomial/elem/cl_asm_sparc_GF2.cc b/src/polynomial/elem/cl_asm_sparc_GF2.cc new file mode 100644 index 0000000..815b686 --- /dev/null +++ b/src/polynomial/elem/cl_asm_sparc_GF2.cc @@ -0,0 +1,642 @@ +// Externe Routinen +// Prozessor: SPARC +// Compiler: GNU-C oder SUN-C +// Parameter-Übergabe: in Registern %o0-%o5. +// Einstellungen: intCsize=32, intDsize=32. + +#ifdef ASM_UNDERSCORE /* SunOS 4 */ + #if defined(__STDC__) || defined (__cplusplus) + #define C(entrypoint) _##entrypoint + #else + #define C(entrypoint) _/**/entrypoint + #endif +#else /* SunOS 5 = Solaris 2 */ + #define C(entrypoint) entrypoint +#endif + +// When this file is compiled into a shared library, ELF linkers need to +// know which symbols are functions. +#if defined(__NetBSD__) || defined(__OpenBSD__) + #define DECLARE_FUNCTION(name) .type C(name),@function +#elif defined(__svr4__) || defined(__ELF__) + // Some preprocessors keep the backslash in place, some don't. + // Some complain about the # being not in front of an ANSI C macro. + // Therefore we use a dollar, which will be sed-converted to # later. + #define DECLARE_FUNCTION(name) .type C(name),$function +#else + #define DECLARE_FUNCTION(name) +#endif + + // Indikatoren für Anweisungen (Instruktionen) in Delay-Slots + // (diese werden VOR der vorigen Instruktion ausgeführt): + #define _ // Instruktion, die stets ausgeführt wird + #define __ // Instruktion, die nur im Sprung-Fall ausgeführt wird + // Abkürzungen für Anweisungen: + #define ret jmp %i7+8 // return from subroutine + #define retl jmp %o7+8 // return from leaf subroutine (no save/restore) + + .seg "text" + + .global C(gf2_mul16),C(gf2_mul32) + +// extern uint32 gf2_mul16 (uint16 x, uint16 y); + DECLARE_FUNCTION(gf2_mul16) +C(gf2_mul16:) // Input in %o0,%o1, Output in %o0 + sll %o0,16,%o0 + sll %o1,16,%o1 + srl %o1,16,%o1 + // 16-bit multiply of x and y + // input %o1 = factor1, %o0 = 2^16*factor2, output %o0 + addcc %o0,%o0,%o0 + bcs Lb01 + _ addcc %o0,%o0,%o0 +La01: bcs Lb02 + _ addcc %o0,%o0,%o0 +La02: bcs Lb03 + _ addcc %o0,%o0,%o0 +La03: bcs Lb04 + _ addcc %o0,%o0,%o0 +La04: bcs Lb05 + _ addcc %o0,%o0,%o0 +La05: bcs Lb06 + _ addcc %o0,%o0,%o0 +La06: bcs Lb07 + _ addcc %o0,%o0,%o0 +La07: bcs Lb08 + _ addcc %o0,%o0,%o0 +La08: bcs Lb09 + _ addcc %o0,%o0,%o0 +La09: bcs Lb10 + _ addcc %o0,%o0,%o0 +La10: bcs Lb11 + _ addcc %o0,%o0,%o0 +La11: bcs Lb12 + _ addcc %o0,%o0,%o0 +La12: bcs Lb13 + _ addcc %o0,%o0,%o0 +La13: bcs Lb14 + _ addcc %o0,%o0,%o0 +La14: bcs Lb15 + _ addcc %o0,%o0,%o0 +La15: bcs Lb16 + _ add %o0,%o0,%o0 +La16: retl + _ nop +Lb01: xor %o0,%o1,%o0 + bcc La02 + _ addcc %o0,%o0,%o0 +Lb02: xor %o0,%o1,%o0 + bcc La03 + _ addcc %o0,%o0,%o0 +Lb03: xor %o0,%o1,%o0 + bcc La04 + _ addcc %o0,%o0,%o0 +Lb04: xor %o0,%o1,%o0 + bcc La05 + _ addcc %o0,%o0,%o0 +Lb05: xor %o0,%o1,%o0 + bcc La06 + _ addcc %o0,%o0,%o0 +Lb06: xor %o0,%o1,%o0 + bcc La07 + _ addcc %o0,%o0,%o0 +Lb07: xor %o0,%o1,%o0 + bcc La08 + _ addcc %o0,%o0,%o0 +Lb08: xor %o0,%o1,%o0 + bcc La09 + _ addcc %o0,%o0,%o0 +Lb09: xor %o0,%o1,%o0 + bcc La10 + _ addcc %o0,%o0,%o0 +Lb10: xor %o0,%o1,%o0 + bcc La11 + _ addcc %o0,%o0,%o0 +Lb11: xor %o0,%o1,%o0 + bcc La12 + _ addcc %o0,%o0,%o0 +Lb12: xor %o0,%o1,%o0 + bcc La13 + _ addcc %o0,%o0,%o0 +Lb13: xor %o0,%o1,%o0 + bcc La14 + _ addcc %o0,%o0,%o0 +Lb14: xor %o0,%o1,%o0 + bcc La15 + _ addcc %o0,%o0,%o0 +Lb15: xor %o0,%o1,%o0 + bcc La16 + _ add %o0,%o0,%o0 +Lb16: retl + _ xor %o0,%o1,%o0 + +// extern uint32 gf2_mul32 (uint32 x, uint32 y, uint32* plo); + DECLARE_FUNCTION(gf2_mul32) +C(gf2_mul32:) // Input in %o0,%o1,%o2, Output in [%o2],%o0 +#if 0 + sll %o0,16,%o4 + srl %o4,16,%o4 // %o4 = low16(x) + sll %o1,16,%o5 // %o5 = 2^16*low16(y) + srl %o0,16,%o0 // %o0 = high16(x) + srl %o1,16,%o1 + sll %o1,16,%o1 // %o1 = 2^16*high16(y) + xor %o1,%o5,%o3 // %o3 = 2^16*(high16(y)+low16(y)) + // 16-bit multiply of low16(x) and low16(y) + // input %o4 = factor1, %o5 = 2^16*factor2, output %o5 + addcc %o5,%o5,%o5 + bcs Ld01 + _ addcc %o5,%o5,%o5 +Lc01: bcs Ld02 + _ addcc %o5,%o5,%o5 +Lc02: bcs Ld03 + _ addcc %o5,%o5,%o5 +Lc03: bcs Ld04 + _ addcc %o5,%o5,%o5 +Lc04: bcs Ld05 + _ addcc %o5,%o5,%o5 +Lc05: bcs Ld06 + _ addcc %o5,%o5,%o5 +Lc06: bcs Ld07 + _ addcc %o5,%o5,%o5 +Lc07: bcs Ld08 + _ addcc %o5,%o5,%o5 +Lc08: bcs Ld09 + _ addcc %o5,%o5,%o5 +Lc09: bcs Ld10 + _ addcc %o5,%o5,%o5 +Lc10: bcs Ld11 + _ addcc %o5,%o5,%o5 +Lc11: bcs Ld12 + _ addcc %o5,%o5,%o5 +Lc12: bcs Ld13 + _ addcc %o5,%o5,%o5 +Lc13: bcs Ld14 + _ addcc %o5,%o5,%o5 +Lc14: bcs Ld15 + _ addcc %o5,%o5,%o5 +Lc15: bcs Ld16 + _ add %o5,%o5,%o5 +Lc16: b Ld17 + _ nop +Ld01: xor %o5,%o4,%o5 + bcc Lc02 + _ addcc %o5,%o5,%o5 +Ld02: xor %o5,%o4,%o5 + bcc Lc03 + _ addcc %o5,%o5,%o5 +Ld03: xor %o5,%o4,%o5 + bcc Lc04 + _ addcc %o5,%o5,%o5 +Ld04: xor %o5,%o4,%o5 + bcc Lc05 + _ addcc %o5,%o5,%o5 +Ld05: xor %o5,%o4,%o5 + bcc Lc06 + _ addcc %o5,%o5,%o5 +Ld06: xor %o5,%o4,%o5 + bcc Lc07 + _ addcc %o5,%o5,%o5 +Ld07: xor %o5,%o4,%o5 + bcc Lc08 + _ addcc %o5,%o5,%o5 +Ld08: xor %o5,%o4,%o5 + bcc Lc09 + _ addcc %o5,%o5,%o5 +Ld09: xor %o5,%o4,%o5 + bcc Lc10 + _ addcc %o5,%o5,%o5 +Ld10: xor %o5,%o4,%o5 + bcc Lc11 + _ addcc %o5,%o5,%o5 +Ld11: xor %o5,%o4,%o5 + bcc Lc12 + _ addcc %o5,%o5,%o5 +Ld12: xor %o5,%o4,%o5 + bcc Lc13 + _ addcc %o5,%o5,%o5 +Ld13: xor %o5,%o4,%o5 + bcc Lc14 + _ addcc %o5,%o5,%o5 +Ld14: xor %o5,%o4,%o5 + bcc Lc15 + _ addcc %o5,%o5,%o5 +Ld15: xor %o5,%o4,%o5 + bcc Ld17 + _ add %o5,%o5,%o5 +Ld16: xor %o5,%o4,%o5 +Ld17: // %o5 = low16(x)*low16(y) + // 16-bit multiply of high16(x) and high16(y) + // input %o0 = factor1, %o1 = 2^16*factor2, output %o1 + addcc %o1,%o1,%o1 + bcs Lf01 + _ addcc %o1,%o1,%o1 +Le01: bcs Lf02 + _ addcc %o1,%o1,%o1 +Le02: bcs Lf03 + _ addcc %o1,%o1,%o1 +Le03: bcs Lf04 + _ addcc %o1,%o1,%o1 +Le04: bcs Lf05 + _ addcc %o1,%o1,%o1 +Le05: bcs Lf06 + _ addcc %o1,%o1,%o1 +Le06: bcs Lf07 + _ addcc %o1,%o1,%o1 +Le07: bcs Lf08 + _ addcc %o1,%o1,%o1 +Le08: bcs Lf09 + _ addcc %o1,%o1,%o1 +Le09: bcs Lf10 + _ addcc %o1,%o1,%o1 +Le10: bcs Lf11 + _ addcc %o1,%o1,%o1 +Le11: bcs Lf12 + _ addcc %o1,%o1,%o1 +Le12: bcs Lf13 + _ addcc %o1,%o1,%o1 +Le13: bcs Lf14 + _ addcc %o1,%o1,%o1 +Le14: bcs Lf15 + _ addcc %o1,%o1,%o1 +Le15: bcs Lf16 + _ add %o1,%o1,%o1 +Le16: b Lf17 + _ nop +Lf01: xor %o1,%o0,%o1 + bcc Le02 + _ addcc %o1,%o1,%o1 +Lf02: xor %o1,%o0,%o1 + bcc Le03 + _ addcc %o1,%o1,%o1 +Lf03: xor %o1,%o0,%o1 + bcc Le04 + _ addcc %o1,%o1,%o1 +Lf04: xor %o1,%o0,%o1 + bcc Le05 + _ addcc %o1,%o1,%o1 +Lf05: xor %o1,%o0,%o1 + bcc Le06 + _ addcc %o1,%o1,%o1 +Lf06: xor %o1,%o0,%o1 + bcc Le07 + _ addcc %o1,%o1,%o1 +Lf07: xor %o1,%o0,%o1 + bcc Le08 + _ addcc %o1,%o1,%o1 +Lf08: xor %o1,%o0,%o1 + bcc Le09 + _ addcc %o1,%o1,%o1 +Lf09: xor %o1,%o0,%o1 + bcc Le10 + _ addcc %o1,%o1,%o1 +Lf10: xor %o1,%o0,%o1 + bcc Le11 + _ addcc %o1,%o1,%o1 +Lf11: xor %o1,%o0,%o1 + bcc Le12 + _ addcc %o1,%o1,%o1 +Lf12: xor %o1,%o0,%o1 + bcc Le13 + _ addcc %o1,%o1,%o1 +Lf13: xor %o1,%o0,%o1 + bcc Le14 + _ addcc %o1,%o1,%o1 +Lf14: xor %o1,%o0,%o1 + bcc Le15 + _ addcc %o1,%o1,%o1 +Lf15: xor %o1,%o0,%o1 + bcc Lf17 + _ add %o1,%o1,%o1 +Lf16: xor %o1,%o0,%o1 +Lf17: // %o1 = high16(x)*high16(y) + xor %o0,%o4,%o4 // %o4 = high16(x)+low16(x) + // 16-bit multiply of high16(x)+low16(x) and high16(y)+low16(y) + // input %o4 = factor1, %o3 = 2^16*factor2, output %o3 + addcc %o3,%o3,%o3 + bcs Lh01 + _ addcc %o3,%o3,%o3 +Lg01: bcs Lh02 + _ addcc %o3,%o3,%o3 +Lg02: bcs Lh03 + _ addcc %o3,%o3,%o3 +Lg03: bcs Lh04 + _ addcc %o3,%o3,%o3 +Lg04: bcs Lh05 + _ addcc %o3,%o3,%o3 +Lg05: bcs Lh06 + _ addcc %o3,%o3,%o3 +Lg06: bcs Lh07 + _ addcc %o3,%o3,%o3 +Lg07: bcs Lh08 + _ addcc %o3,%o3,%o3 +Lg08: bcs Lh09 + _ addcc %o3,%o3,%o3 +Lg09: bcs Lh10 + _ addcc %o3,%o3,%o3 +Lg10: bcs Lh11 + _ addcc %o3,%o3,%o3 +Lg11: bcs Lh12 + _ addcc %o3,%o3,%o3 +Lg12: bcs Lh13 + _ addcc %o3,%o3,%o3 +Lg13: bcs Lh14 + _ addcc %o3,%o3,%o3 +Lg14: bcs Lh15 + _ addcc %o3,%o3,%o3 +Lg15: bcs Lh16 + _ add %o3,%o3,%o3 +Lg16: b Lh17 + _ nop +Lh01: xor %o3,%o4,%o3 + bcc Lg02 + _ addcc %o3,%o3,%o3 +Lh02: xor %o3,%o4,%o3 + bcc Lg03 + _ addcc %o3,%o3,%o3 +Lh03: xor %o3,%o4,%o3 + bcc Lg04 + _ addcc %o3,%o3,%o3 +Lh04: xor %o3,%o4,%o3 + bcc Lg05 + _ addcc %o3,%o3,%o3 +Lh05: xor %o3,%o4,%o3 + bcc Lg06 + _ addcc %o3,%o3,%o3 +Lh06: xor %o3,%o4,%o3 + bcc Lg07 + _ addcc %o3,%o3,%o3 +Lh07: xor %o3,%o4,%o3 + bcc Lg08 + _ addcc %o3,%o3,%o3 +Lh08: xor %o3,%o4,%o3 + bcc Lg09 + _ addcc %o3,%o3,%o3 +Lh09: xor %o3,%o4,%o3 + bcc Lg10 + _ addcc %o3,%o3,%o3 +Lh10: xor %o3,%o4,%o3 + bcc Lg11 + _ addcc %o3,%o3,%o3 +Lh11: xor %o3,%o4,%o3 + bcc Lg12 + _ addcc %o3,%o3,%o3 +Lh12: xor %o3,%o4,%o3 + bcc Lg13 + _ addcc %o3,%o3,%o3 +Lh13: xor %o3,%o4,%o3 + bcc Lg14 + _ addcc %o3,%o3,%o3 +Lh14: xor %o3,%o4,%o3 + bcc Lg15 + _ addcc %o3,%o3,%o3 +Lh15: xor %o3,%o4,%o3 + bcc Lh17 + _ add %o3,%o3,%o3 +Lh16: xor %o3,%o4,%o3 +Lh17: // %o3 = (high16(x)+low16(x))*(high16(y)+low16(y)) + // Now %o5 = low16(x)*low16(y) + // %o1 = high16(x)*high16(y) + // %o3 = (high16(x)+low16(x))*(high16(y)+low16(y)) + // The result is x*y = 2^32*%o1 + 2^16*(%o3+%o1+%o5) + %o5 + xor %o3,%o1,%o3 + xor %o3,%o5,%o3 + // The result is x*y = 2^32*%o1 + 2^16*%o3 + %o5 + srl %o3,16,%o0 + xor %o0,%o1,%o0 // high 32 bits in %o0 + sll %o3,16,%o1 + xor %o1,%o5,%o1 // low 32 bits in %o1 + retl + _ st %o1,[%o2] +#else + mov 0,%o3 + // 32-bit multiply of x and y + // input %o1 = factor1, %o0|%o3 = 2^32*factor2, output %o0|%o3 + addcc %o0,%o0,%o0 + bcs Ld01 + _ addcc %o3,%o3,%o3 +Lc01: addxcc %o0,%o0,%o0 + bcs Ld02 + _ addcc %o3,%o3,%o3 +Lc02: addxcc %o0,%o0,%o0 + bcs Ld03 + _ addcc %o3,%o3,%o3 +Lc03: addxcc %o0,%o0,%o0 + bcs Ld04 + _ addcc %o3,%o3,%o3 +Lc04: addxcc %o0,%o0,%o0 + bcs Ld05 + _ addcc %o3,%o3,%o3 +Lc05: addxcc %o0,%o0,%o0 + bcs Ld06 + _ addcc %o3,%o3,%o3 +Lc06: addxcc %o0,%o0,%o0 + bcs Ld07 + _ addcc %o3,%o3,%o3 +Lc07: addxcc %o0,%o0,%o0 + bcs Ld08 + _ addcc %o3,%o3,%o3 +Lc08: addxcc %o0,%o0,%o0 + bcs Ld09 + _ addcc %o3,%o3,%o3 +Lc09: addxcc %o0,%o0,%o0 + bcs Ld10 + _ addcc %o3,%o3,%o3 +Lc10: addxcc %o0,%o0,%o0 + bcs Ld11 + _ addcc %o3,%o3,%o3 +Lc11: addxcc %o0,%o0,%o0 + bcs Ld12 + _ addcc %o3,%o3,%o3 +Lc12: addxcc %o0,%o0,%o0 + bcs Ld13 + _ addcc %o3,%o3,%o3 +Lc13: addxcc %o0,%o0,%o0 + bcs Ld14 + _ addcc %o3,%o3,%o3 +Lc14: addxcc %o0,%o0,%o0 + bcs Ld15 + _ addcc %o3,%o3,%o3 +Lc15: addxcc %o0,%o0,%o0 + bcs Ld16 + _ addcc %o3,%o3,%o3 +Lc16: addxcc %o0,%o0,%o0 + bcs Ld17 + _ addcc %o3,%o3,%o3 +Lc17: addxcc %o0,%o0,%o0 + bcs Ld18 + _ addcc %o3,%o3,%o3 +Lc18: addxcc %o0,%o0,%o0 + bcs Ld19 + _ addcc %o3,%o3,%o3 +Lc19: addxcc %o0,%o0,%o0 + bcs Ld20 + _ addcc %o3,%o3,%o3 +Lc20: addxcc %o0,%o0,%o0 + bcs Ld21 + _ addcc %o3,%o3,%o3 +Lc21: addxcc %o0,%o0,%o0 + bcs Ld22 + _ addcc %o3,%o3,%o3 +Lc22: addxcc %o0,%o0,%o0 + bcs Ld23 + _ addcc %o3,%o3,%o3 +Lc23: addxcc %o0,%o0,%o0 + bcs Ld24 + _ addcc %o3,%o3,%o3 +Lc24: addxcc %o0,%o0,%o0 + bcs Ld25 + _ addcc %o3,%o3,%o3 +Lc25: addxcc %o0,%o0,%o0 + bcs Ld26 + _ addcc %o3,%o3,%o3 +Lc26: addxcc %o0,%o0,%o0 + bcs Ld27 + _ addcc %o3,%o3,%o3 +Lc27: addxcc %o0,%o0,%o0 + bcs Ld28 + _ addcc %o3,%o3,%o3 +Lc28: addxcc %o0,%o0,%o0 + bcs Ld29 + _ addcc %o3,%o3,%o3 +Lc29: addxcc %o0,%o0,%o0 + bcs Ld30 + _ addcc %o3,%o3,%o3 +Lc30: addxcc %o0,%o0,%o0 + bcs Ld31 + _ addcc %o3,%o3,%o3 +Lc31: addxcc %o0,%o0,%o0 + bcs Ld32 + _ addcc %o3,%o3,%o3 +Lc32: b Ld34 + _ addx %o0,%o0,%o0 +Ld01: addxcc %o0,%o0,%o0 + xor %o3,%o1,%o3 + bcc Lc02 + _ addcc %o3,%o3,%o3 +Ld02: addxcc %o0,%o0,%o0 + xor %o3,%o1,%o3 + bcc Lc03 + _ addcc %o3,%o3,%o3 +Ld03: addxcc %o0,%o0,%o0 + xor %o3,%o1,%o3 + bcc Lc04 + _ addcc %o3,%o3,%o3 +Ld04: addxcc %o0,%o0,%o0 + xor %o3,%o1,%o3 + bcc Lc05 + _ addcc %o3,%o3,%o3 +Ld05: addxcc %o0,%o0,%o0 + xor %o3,%o1,%o3 + bcc Lc06 + _ addcc %o3,%o3,%o3 +Ld06: addxcc %o0,%o0,%o0 + xor %o3,%o1,%o3 + bcc Lc07 + _ addcc %o3,%o3,%o3 +Ld07: addxcc %o0,%o0,%o0 + xor %o3,%o1,%o3 + bcc Lc08 + _ addcc %o3,%o3,%o3 +Ld08: addxcc %o0,%o0,%o0 + xor %o3,%o1,%o3 + bcc Lc09 + _ addcc %o3,%o3,%o3 +Ld09: addxcc %o0,%o0,%o0 + xor %o3,%o1,%o3 + bcc Lc10 + _ addcc %o3,%o3,%o3 +Ld10: addxcc %o0,%o0,%o0 + xor %o3,%o1,%o3 + bcc Lc11 + _ addcc %o3,%o3,%o3 +Ld11: addxcc %o0,%o0,%o0 + xor %o3,%o1,%o3 + bcc Lc12 + _ addcc %o3,%o3,%o3 +Ld12: addxcc %o0,%o0,%o0 + xor %o3,%o1,%o3 + bcc Lc13 + _ addcc %o3,%o3,%o3 +Ld13: addxcc %o0,%o0,%o0 + xor %o3,%o1,%o3 + bcc Lc14 + _ addcc %o3,%o3,%o3 +Ld14: addxcc %o0,%o0,%o0 + xor %o3,%o1,%o3 + bcc Lc15 + _ addcc %o3,%o3,%o3 +Ld15: addxcc %o0,%o0,%o0 + xor %o3,%o1,%o3 + bcc Lc16 + _ addcc %o3,%o3,%o3 +Ld16: addxcc %o0,%o0,%o0 + xor %o3,%o1,%o3 + bcc Lc17 + _ addcc %o3,%o3,%o3 +Ld17: addxcc %o0,%o0,%o0 + xor %o3,%o1,%o3 + bcc Lc18 + _ addcc %o3,%o3,%o3 +Ld18: addxcc %o0,%o0,%o0 + xor %o3,%o1,%o3 + bcc Lc19 + _ addcc %o3,%o3,%o3 +Ld19: addxcc %o0,%o0,%o0 + xor %o3,%o1,%o3 + bcc Lc20 + _ addcc %o3,%o3,%o3 +Ld20: addxcc %o0,%o0,%o0 + xor %o3,%o1,%o3 + bcc Lc21 + _ addcc %o3,%o3,%o3 +Ld21: addxcc %o0,%o0,%o0 + xor %o3,%o1,%o3 + bcc Lc22 + _ addcc %o3,%o3,%o3 +Ld22: addxcc %o0,%o0,%o0 + xor %o3,%o1,%o3 + bcc Lc23 + _ addcc %o3,%o3,%o3 +Ld23: addxcc %o0,%o0,%o0 + xor %o3,%o1,%o3 + bcc Lc24 + _ addcc %o3,%o3,%o3 +Ld24: addxcc %o0,%o0,%o0 + xor %o3,%o1,%o3 + bcc Lc25 + _ addcc %o3,%o3,%o3 +Ld25: addxcc %o0,%o0,%o0 + xor %o3,%o1,%o3 + bcc Lc26 + _ addcc %o3,%o3,%o3 +Ld26: addxcc %o0,%o0,%o0 + xor %o3,%o1,%o3 + bcc Lc27 + _ addcc %o3,%o3,%o3 +Ld27: addxcc %o0,%o0,%o0 + xor %o3,%o1,%o3 + bcc Lc28 + _ addcc %o3,%o3,%o3 +Ld28: addxcc %o0,%o0,%o0 + xor %o3,%o1,%o3 + bcc Lc29 + _ addcc %o3,%o3,%o3 +Ld29: addxcc %o0,%o0,%o0 + xor %o3,%o1,%o3 + bcc Lc30 + _ addcc %o3,%o3,%o3 +Ld30: addxcc %o0,%o0,%o0 + xor %o3,%o1,%o3 + bcc Lc31 + _ addcc %o3,%o3,%o3 +Ld31: addxcc %o0,%o0,%o0 + xor %o3,%o1,%o3 + bcc Ld33 + _ addcc %o3,%o3,%o3 +Ld32: xor %o3,%o1,%o3 +Ld33: addx %o0,%o0,%o0 +Ld34: // Now x*y = 2^32*%o0+%o3 + retl + _ st %o3,[%o2] +#endif + diff --git a/src/polynomial/misc/Makeflags b/src/polynomial/misc/Makeflags new file mode 100644 index 0000000..76ce56d --- /dev/null +++ b/src/polynomial/misc/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/polynomial/Makeflags +SUBDIR_INCLUDES += diff --git a/src/polynomial/misc/cl_UP_I_hermite.cc b/src/polynomial/misc/cl_UP_I_hermite.cc new file mode 100644 index 0000000..b2807bf --- /dev/null +++ b/src/polynomial/misc/cl_UP_I_hermite.cc @@ -0,0 +1,58 @@ +// cl_hermite(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_univpoly_integer.h" + + +// Implementation. + +#include "cl_integer.h" + +const cl_UP_I cl_hermite (sintL n) +{ +// The Hermite polynomials H_n(x) are defined as +// +// ( d ) n +// H_n(x) = (-1)^n exp(x^2) (----) exp(- x^2) +// ( dx ) +// +// They satisfy the recurrence relation +// +// H_0(x) = 1 +// H_{n+1}(x) = 2x H_n(x) - 2n H_{n-1}(x) for n >= 0. +// +// Theorem: +// H_n(x) satisfies the differential equation +// H_n''(x) - 2x*H_n'(x) + 2n*H_n(x) = 0. +// +// Proof: See elsewhere. +// +// Corollary: +// The coefficients c_{n,k} of H_n(x) = sum(k=0..n, c_{n,k} x^k) +// satisfy: +// c_{n,n} = 2^n, +// c_{n,n-1} = 0, +// c_{n,k} = (k+1)(k+2)/2(k-n)*c_{n,k+2} +// +// It follows that for n>=0 +// +// H_n(x) = sum(j=0..floor(n/2), (-1)^j n!/j!(n-2j)! 2^(n-2j) x^(n-2j)) +// + var cl_univpoly_integer_ring R = cl_find_univpoly_ring(cl_I_ring); + var cl_UP_I h = R->create(n); + var sintL k = n; + var cl_I c_k = ash(1,n); + for (;;) { + h.set_coeff(k,c_k); + k = k-2; + if (k < 0) + break; + c_k = exquo((cl_I)(k+1) * (cl_I)(k+2) * c_k, + 2*(cl_I)(k-n)); + } + h.finalize(); + return h; +} diff --git a/src/polynomial/misc/cl_UP_I_laguerre.cc b/src/polynomial/misc/cl_UP_I_laguerre.cc new file mode 100644 index 0000000..43e7400 --- /dev/null +++ b/src/polynomial/misc/cl_UP_I_laguerre.cc @@ -0,0 +1,57 @@ +// cl_laguerre(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_univpoly_integer.h" + + +// Implementation. + +#include "cl_integer.h" + +const cl_UP_I cl_laguerre (sintL n) +{ +// The Laguerre polynomials L_n(x) are defined as +// +// ( d ) n +// L_n(x) = exp(x) (----) (x^n exp(-x)) +// ( dx ) +// +// They satisfy the recurrence relation +// +// L_0(x) = 1 +// L_{n+1}(x) = (2n+1-x) L_n(x) - n^2 L_{n-1}(x) for n >= 0. +// +// Theorem: +// L_n(x) satisfies the differential equation +// x*L_n''(x) + (1-x)*L_n'(x) + n*L_n(x) = 0. +// +// Proof: See elsewhere. +// +// Corollary: +// The coefficients c_{n,k} of L_n(x) = sum(k=0..n, c_{n,k} x^k) +// satisfy: +// c_{n,n} = (-1)^n, +// c_{n,k} = (k+1)^2/(k-n)*c_{n,k+1} +// +// It follows that for n>=0 +// +// L_n(x) = sum(j=0..n, (-1)^(n-j) n!^2/j!(n-j)!^2 x^(n-j)) +// + var cl_univpoly_integer_ring R = cl_find_univpoly_ring(cl_I_ring); + var cl_UP_I l = R->create(n); + var sintL k = n; + var cl_I c_k = (evenp(n) ? 1 : -1); + for (;;) { + l.set_coeff(k,c_k); + k = k-1; + if (k < 0) + break; + c_k = exquo((cl_I)(k+1) * (cl_I)(k+1) * c_k, + (cl_I)(k-n)); + } + l.finalize(); + return l; +} diff --git a/src/polynomial/misc/cl_UP_I_tchebychev.cc b/src/polynomial/misc/cl_UP_I_tchebychev.cc new file mode 100644 index 0000000..030e7ed --- /dev/null +++ b/src/polynomial/misc/cl_UP_I_tchebychev.cc @@ -0,0 +1,56 @@ +// cl_tschebychev(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_univpoly_integer.h" + + +// Implementation. + +#include "cl_integer.h" + +const cl_UP_I cl_tschebychev (sintL n) +{ +// The Tschebychev polynomials (of the 1st kind) T_n(x) are defined +// through the recurrence relation +// +// T_0(x) = 1 +// T_1(x) = x +// T_{n+2}(x) = 2x T_{n+1}(x) - T_n(x) for n >= 0. +// +// Theorem: +// T_n(x) satisfies the differential equation +// (x^2-1)*T_n''(x) + x*T_n'(x) - n^2*T_n(x) = 0. +// +// Proof: See elsewhere. +// +// Corollary: +// The coefficients c_{n,k} of T_n(x) = sum(k=0..n, c_{n,k} x^k) +// satisfy: +// c_{n,n} = 2^(n-1) for n>=1, 1 for n=0, +// c_{n,n-1} = 0, +// c_{n,k} = (k+1)(k+2)/(k^2-n^2)*c_{n,k+2} +// +// It follows that for n>0 +// +// T_n(x) = sum(j=0..floor(n/2), (-1)^j (n-j-1)!n/j!(n-2j)! 2^(n-2j-1) x^(n-2j)) +// + var cl_univpoly_integer_ring R = cl_find_univpoly_ring(cl_I_ring); + if (n == 0) + return R->one(); + var cl_UP_I t = R->create(n); + var sintL k = n; + var cl_I c_k = ash(1,n-1); + for (;;) { + t.set_coeff(k,c_k); + k = k-2; + if (k < 0) + break; + c_k = exquo((cl_I)(k+1) * (cl_I)(k+2) * c_k, + (cl_I)(k-n) * (cl_I)(k+n)); + } + t.finalize(); + return t; +} diff --git a/src/polynomial/misc/cl_UP_RA_legendre.cc b/src/polynomial/misc/cl_UP_RA_legendre.cc new file mode 100644 index 0000000..0879718 --- /dev/null +++ b/src/polynomial/misc/cl_UP_RA_legendre.cc @@ -0,0 +1,60 @@ +// cl_legendre(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_univpoly_rational.h" + + +// Implementation. + +#include "cl_integer.h" +#include "cl_rational.h" + +const cl_UP_RA cl_legendre (sintL n) +{ +// The Legendre polynomials P_n(x) are defined as +// +// 1 ( d ) n n +// P_n(x) = ------ (----) (x^2 - 1) +// 2^n n! ( dx ) +// +// They satisfy the recurrence relation +// +// P_0(x) = 1 +// P_{n+1}(x) = 1/(n+1) * ((2n+1)x P_n(x) - n P_{n-1}(x)) for n >= 0. +// +// Theorem: +// P_n(x) satisfies the differential equation +// (1-x^2)*P_n''(x) - 2x*P_n'(x) + (n^2+n)*P_n(x) = 0. +// +// Proof: See elsewhere. +// +// Corollary: +// The coefficients c_{n,k} of P_n(x) = sum(k=0..n, c_{n,k} x^k) +// satisfy: +// c_{n,n} = (2n)!/(n!^2 2^n), +// c_{n,n-1} = 0, +// c_{n,k} = (k+1)(k+2)/(k-n)(k+n+1)*c_{n,k+2} +// +// It follows that for n>=0 +// +// P_n(x) = sum(j=0..floor(n/2), (-1)^j (2n-2j)!/j!(n-2j)!(n-j)! 2^-n x^(n-2j)) +// + var cl_univpoly_rational_ring R = cl_find_univpoly_ring(cl_RA_ring); + var cl_UP_RA p = R->create(n); + var cl_I denom = ash(1,n); + var sintL k = n; + var cl_I c_k = binomial(2*n,n); + for (;;) { + p.set_coeff(k,c_k/denom); + k = k-2; + if (k < 0) + break; + c_k = exquo((cl_I)(k+1) * (cl_I)(k+2) * c_k, + (cl_I)(k-n) * (cl_I)(k+n+1)); + } + p.finalize(); + return p; +} diff --git a/src/polynomial/misc/cl_UP_debug.cc b/src/polynomial/misc/cl_UP_debug.cc new file mode 100644 index 0000000..25438a5 --- /dev/null +++ b/src/polynomial/misc/cl_UP_debug.cc @@ -0,0 +1,31 @@ +// cl_univpoly_ring debugging support. + +// General includes. +#include "cl_sysdep.h" + +// Specification. + + +// Implementation. + +#include "cl_univpoly.h" +#include "cl_UP.h" +#include "cl_io.h" + +static void dprint (cl_heap* pointer) +{ +// var const cl_univpoly_ring& obj = *(const cl_univpoly_ring*)&pointer; + fprint(cl_debugout, "(cl_univpoly_ring) ring"); + fprint(cl_debugout, get_varname((cl_heap_univpoly_ring*)pointer)); +} +AT_INITIALIZATION(dprint_univpoly_ring) +{ cl_register_type_printer(cl_class_univpoly_ring,dprint); } + +void cl_UP::debug_print () const +{ + fprint(cl_debugout, *this); + fprint(cl_debugout, "\n"); +} + +// This dummy links in this module when requires it. +int cl_UP_debug_module; diff --git a/src/polynomial/misc/cl_UP_deriv.cc b/src/polynomial/misc/cl_UP_deriv.cc new file mode 100644 index 0000000..0697079 --- /dev/null +++ b/src/polynomial/misc/cl_UP_deriv.cc @@ -0,0 +1,30 @@ +// deriv(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_univpoly.h" + + +// Implementation. + +#include "cl_integer.h" + +const cl_UP deriv (const cl_UP& x) +{ + // Method: + // Write x = a0 T^0 + ... + an T^n. + // Then deriv(x) = 1*a1 T^0 + ... + n*an T^(n-1) (= 0 if n <= 0). + var cl_univpoly_ring UPR = x.ring(); + var sintL n = degree(x); + if (n <= 0) + return UPR->zero(); + else { + var cl_UP y = UPR->create(n-1); + for ( ; n > 0; n--) + y.set_coeff(n-1, n * coeff(x,n)); + y.finalize(); + return y; + } +} diff --git a/src/rational/Makeflags b/src/rational/Makeflags new file mode 100644 index 0000000..701b7f8 --- /dev/null +++ b/src/rational/Makeflags @@ -0,0 +1,3 @@ +# This file contains additional flags for the main Makefile. + +SUBDIR_INCLUDES = -I$(srcdir)/rational -I$(srcdir)/integer -I$(srcdir)/base/digitseq -I$(srcdir)/base/digit -Ibase -I$(srcdir)/base $(GMP_INCLUDES) diff --git a/src/rational/algebraic/Makeflags b/src/rational/algebraic/Makeflags new file mode 100644 index 0000000..6ed2160 --- /dev/null +++ b/src/rational/algebraic/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/rational/Makeflags +SUBDIR_INCLUDES += diff --git a/src/rational/algebraic/cl_RA_rootp.cc b/src/rational/algebraic/cl_RA_rootp.cc new file mode 100644 index 0000000..9c998ea --- /dev/null +++ b/src/rational/algebraic/cl_RA_rootp.cc @@ -0,0 +1,37 @@ +// rootp(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" + +cl_boolean rootp (const cl_RA& x, uintL n, cl_RA* w) +{ +// Methode: +// Bei Integers: klar. +// Bei Brüchen a/b : muß a=c^n und b=d^n sein. Dann ist die Wurzel = c/d +// (mit ggT(c,d)=1 und d>1). + if (integerp(x)) { + DeclareType(cl_I,x); + return rootp(x,n,(cl_I*)w); + } else { + // x ist Ratio + DeclareType(cl_RT,x); + var const cl_I& b = denominator(x); + var cl_I d; + if (!rootp(b,n,&d)) // Nenner auf n-te Potenz testen + return cl_false; + var const cl_I& a = numerator(x); + var cl_I c; + if (!rootp(a,n,&c)) // Zähler auf n-te Potenz testen + return cl_false; + // beides n-te Potenzen -> Quotient der Wurzeln bilden + *w = I_I_to_RT(c,d); return cl_true; +}} diff --git a/src/rational/algebraic/cl_RA_rootp_I.cc b/src/rational/algebraic/cl_RA_rootp_I.cc new file mode 100644 index 0000000..adf07d0 --- /dev/null +++ b/src/rational/algebraic/cl_RA_rootp_I.cc @@ -0,0 +1,37 @@ +// rootp(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" + +cl_boolean rootp (const cl_RA& x, const cl_I& n, cl_RA* w) +{ +// Methode: +// Bei Integers: klar. +// Bei Brüchen a/b : muß a=c^n und b=d^n sein. Dann ist die Wurzel = c/d +// (mit ggT(c,d)=1 und d>1). + if (integerp(x)) { + DeclareType(cl_I,x); + return rootp(x,n,(cl_I*)w); + } else { + // x ist Ratio + DeclareType(cl_RT,x); + var const cl_I& b = denominator(x); + var cl_I d; + if (!rootp(b,n,&d)) // Nenner auf n-te Potenz testen + return cl_false; + var const cl_I& a = numerator(x); + var cl_I c; + if (!rootp(a,n,&c)) // Zähler auf n-te Potenz testen + return cl_false; + // beides n-te Potenzen -> Quotient der Wurzeln bilden + *w = I_I_to_RT(c,d); return cl_true; +}} diff --git a/src/rational/algebraic/cl_RA_sqrtp.cc b/src/rational/algebraic/cl_RA_sqrtp.cc new file mode 100644 index 0000000..d49cb99 --- /dev/null +++ b/src/rational/algebraic/cl_RA_sqrtp.cc @@ -0,0 +1,37 @@ +// sqrtp(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" + +cl_boolean sqrtp (const cl_RA& x, cl_RA* w) +{ +// Methode: +// Bei Integers: klar. +// Bei Brüchen a/b : muß a=c^2 und b=d^2 sein. Dann ist die Wurzel = c/d +// (mit ggT(c,d)=1 und d>1). + if (integerp(x)) { + DeclareType(cl_I,x); + return sqrtp(x,(cl_I*)w); + } else { + // x ist Ratio + DeclareType(cl_RT,x); + var const cl_I& b = denominator(x); + var cl_I d; + if (!sqrtp(b,&d)) // Nenner auf Quadratzahl testen + return cl_false; + var const cl_I& a = numerator(x); + var cl_I c; + if (!sqrtp(a,&c)) // Zähler auf Quadratzahl testen + return cl_false; + // beides Quadratzahlen -> Quotient der Wurzeln bilden + *w = I_I_to_RT(c,d); return cl_true; +}} diff --git a/src/rational/cl_RA.h b/src/rational/cl_RA.h new file mode 100644 index 0000000..4c6a71c --- /dev/null +++ b/src/rational/cl_RA.h @@ -0,0 +1,172 @@ +// cl_RA internals + +#ifndef _CL_RA_H +#define _CL_RA_H + +#include "cl_number.h" +#include "cl_rational.h" +#include "cl_macros.h" +#include "cl_malloc.h" +#include "cl_I.h" + +struct cl_heap_ratio : cl_heap { + cl_I numerator; + cl_I denominator; +}; + +inline cl_heap_ratio* TheRatio (cl_heap_ratio* p) + { return p; } +inline cl_heap_ratio* TheRatio (const cl_number& obj) + { return (cl_heap_ratio*)(obj.pointer); } + +inline cl_heap_ratio* allocate_ratio (const cl_I& num, const cl_I& den) +{ + cl_heap_ratio* p = (cl_heap_ratio*) cl_malloc_hook(sizeof(cl_heap_ratio)); + p->refcount = 1; + p->type = &cl_class_ratio; + p->numerator.pointer = num.pointer; cl_inc_refcount(num); + p->denominator.pointer = den.pointer; cl_inc_refcount(den); + return p; +} + +// Private constructor. +// ptr should be the result of some allocate_ratio() call. +inline cl_RA::cl_RA (cl_heap_ratio* ptr) + : cl_R ((cl_private_thing) ptr) {} + +// Both work, but the first definition results in less compiler-generated +// temporaries. +#if 1 + #define Ratio cl_heap_ratio* +#else + #define Ratio cl_RA +#endif + +// Type tests. +inline cl_boolean rationalp (const cl_RA& x) + { unused x; return cl_true; } +inline cl_boolean integerp (const cl_RA& x) +{ + if (!x.pointer_p()) + return cl_true; + else + if (x.pointer_type() == &cl_class_bignum) + return cl_true; + return cl_false; +} +inline cl_boolean ratiop (const cl_RA& x) +{ + if (!x.pointer_p()) + return cl_false; + else + if (x.pointer_type() == &cl_class_bignum) + return cl_false; + return cl_true; +} + + +// A ratio (cl_RT) is a rational number which is not an integer (cl_I). + +// typedef +class cl_RT : public cl_RA { +public: +}; + +inline cl_boolean integerp (const cl_RT& x) + { unused x; return cl_false; } +inline cl_boolean ratiop (const cl_RT& x) + { unused x; return cl_true; } + +// Access numerator and denominator. +inline const cl_I& numerator (const cl_RT& x) + { return TheRatio(x)->numerator; } +inline const cl_I& denominator (const cl_RT& x) + { return TheRatio(x)->denominator; } + + +// Sign test: + +// (MINUSP x) == (< x 0) +inline cl_boolean minusp (const cl_RT& x) + { return minusp(numerator(x)); } +inline cl_boolean minusp (const cl_RA& x) +{ + if (ratiop(x)) { + DeclareType(cl_RT,x); + return minusp(x); + } else { + DeclareType(cl_I,x); + return minusp(x); + } +} + +// (ZEROP x) == (= x 0) +inline cl_boolean zerop (const cl_RT& x) + { unused x; return cl_false; } +inline cl_boolean zerop (const cl_RA& x) +{ + return (cl_boolean)(x.word == cl_combine(cl_FN_tag,0)); +} + +// (EQ x y) == (= x y), assuming y a fixnum +inline cl_boolean eq (const cl_RA& x, sint32 y) +{ + return (cl_boolean)(x.word == cl_combine(cl_FN_tag,y)); +} + +// Liefert zu den Integers a und b mit b>1 und ggT(a,b)=1 den Bruch a/b. +// I_I_to_RT(a,b) + extern const cl_RA I_I_to_RT (const cl_I& a, const cl_I& b); + +// Liefert zu den Integers a und b mit b>0 und ggT(a,b)=1 den Bruch a/b +// (Ratio oder Integer). +// I_I_to_RA(a,b) + extern const cl_RA I_I_to_RA (const cl_I& a, const cl_I& b); + +// Liefert zu den Integers a und b mit b>0 den Bruch a/b (Ratio oder Integer). +// I_posI_div_RA(a,b) + extern const cl_RA I_posI_div_RA (const cl_I& a, const cl_I& b); + +// Liefert zu den Integers a und b den Bruch a/b (Ratio oder Integer). +// I_I_div_RA(a,b) + extern const cl_RA I_I_div_RA (const cl_I& a, const cl_I& b); + +// Liefert den Zähler einer rationalen Zahl. +// numerator(r) +inline const cl_I numerator (const cl_RA& r) +{ + if (integerp(r)) { + DeclareType(cl_I,r); + return r; + } else + return TheRatio(r)->numerator; +} + +// Liefert den Nenner einer rationalen Zahl. +// denominator(r) +inline const cl_I denominator (const cl_RA& r) +{ + if (integerp(r)) + return 1; + else + return TheRatio(r)->denominator; +} + +// Liefert Zähler und Nenner einer rationalen Zahl. +// RA_numden_I_I(r, num=,den=); +// > r: rationale Zahl +// < num: (numerator r) +// < den: (denominator r) + #define RA_numden_I_I(r,num_zuweisung,den_zuweisung) \ + { if (integerp(r)) \ + { num_zuweisung *(const cl_I *)&r; \ + den_zuweisung 1; /* Zähler = r, Nenner = 1 */ \ + } \ + else \ + { num_zuweisung TheRatio(r)->numerator; \ + den_zuweisung TheRatio(r)->denominator; \ + } \ + } + + +#endif /* _CL_RA_H */ diff --git a/src/rational/division/Makeflags b/src/rational/division/Makeflags new file mode 100644 index 0000000..6ed2160 --- /dev/null +++ b/src/rational/division/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/rational/Makeflags +SUBDIR_INCLUDES += diff --git a/src/rational/division/cl_RA_ceil1.cc b/src/rational/division/cl_RA_ceil1.cc new file mode 100644 index 0000000..e60c63c --- /dev/null +++ b/src/rational/division/cl_RA_ceil1.cc @@ -0,0 +1,29 @@ +// ceiling1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" + +const cl_I ceiling1 (const cl_RA& x) +{ +// Methode: +// x Integer -> q := x +// x Ratio a/b -> (ceiling a b) + if (integerp(x)) { + DeclareType(cl_I,x); + return x; + } else { + DeclareType(cl_RT,x); + var const cl_I& a = numerator(x); + var const cl_I& b = denominator(x); + return ceiling1(a,b); + } +} diff --git a/src/rational/division/cl_RA_ceil12.cc b/src/rational/division/cl_RA_ceil12.cc new file mode 100644 index 0000000..8d1ced7 --- /dev/null +++ b/src/rational/division/cl_RA_ceil12.cc @@ -0,0 +1,47 @@ +// ceiling1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" + +const cl_I ceiling1 (const cl_RA& x, const cl_RA& y) +{ +// Methode: +// x = a/b, y = c/d -> liefere (ceiling (* a d) (* b c)). +// x Integer -> dito mit b=1. +// y Integer -> dito mit d=1. +// x und y Integer -> bekannt. + if (integerp(x)) { + DeclareType(cl_I,x); + if (integerp(y)) { + DeclareType(cl_I,y); + return ceiling1(x,y); + } else { + DeclareType(cl_RT,y); + var const cl_I& c = numerator(y); + var const cl_I& d = denominator(y); + return ceiling1(x*d,c); + } + } else { + DeclareType(cl_RT,x); + var const cl_I& a = numerator(x); + var const cl_I& b = denominator(x); + if (integerp(y)) { + DeclareType(cl_I,y); + return ceiling1(a,b*y); + } else { + DeclareType(cl_RT,y); + var const cl_I& c = numerator(y); + var const cl_I& d = denominator(y); + return ceiling1(a*d,b*c); + } + } +} diff --git a/src/rational/division/cl_RA_ceil2.cc b/src/rational/division/cl_RA_ceil2.cc new file mode 100644 index 0000000..3d40cd8 --- /dev/null +++ b/src/rational/division/cl_RA_ceil2.cc @@ -0,0 +1,35 @@ +// ceiling2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" + +const cl_RA_div_t ceiling2 (const cl_RA& x) +{ +// Methode: +// x Integer -> (q,r) := (x,0) +// x Ratio a/b -> +// (ceiling a b) liefert q und r. +// Liefere q und r/b (mit b>1 und ggT(r,b)=ggT(r+q*b,b)=ggT(a,b)=1). + if (integerp(x)) { + DeclareType(cl_I,x); + // (q,r) := (x,0) + return cl_RA_div_t(x,0); + } else { + DeclareType(cl_RT,x); + var const cl_I& a = numerator(x); + var const cl_I& b = denominator(x); + var cl_I_div_t q_r = ceiling2(a,b); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + return cl_RA_div_t(q,I_I_to_RT(r,b)); + } +} diff --git a/src/rational/division/cl_RA_ceil22.cc b/src/rational/division/cl_RA_ceil22.cc new file mode 100644 index 0000000..7980541 --- /dev/null +++ b/src/rational/division/cl_RA_ceil22.cc @@ -0,0 +1,70 @@ +// ceiling2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" + +const cl_RA_div_t ceiling2 (const cl_RA& x, const cl_RA& y) +{ +#if 1 // Ist das wirklich schneller?? +// Methode: +// x = a/b, y = c/d -> +// (ceiling (* a d) (* b c)) liefert q und r. +// Liefere q und r/(b*d). +// x Integer -> dito mit b=1. +// y Integer -> dito mit d=1. +// x und y Integer -> bekannt. + if (integerp(x)) { + DeclareType(cl_I,x); + if (integerp(y)) { + DeclareType(cl_I,y); + var cl_I_div_t q_r = ceiling2(x,y); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + return cl_RA_div_t(q,r); + } else { + DeclareType(cl_RT,y); + var const cl_I& c = numerator(y); + var const cl_I& d = denominator(y); + var cl_I_div_t q_r = ceiling2(x*d,c); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + return cl_RA_div_t(q,I_posI_div_RA(r,d)); + } + } else { + DeclareType(cl_RT,x); + var const cl_I& a = numerator(x); + var const cl_I& b = denominator(x); + if (integerp(y)) { + DeclareType(cl_I,y); + var cl_I_div_t q_r = ceiling2(a,b*y); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + return cl_RA_div_t(q,I_posI_div_RA(r,b)); + } else { + DeclareType(cl_RT,y); + var const cl_I& c = numerator(y); + var const cl_I& d = denominator(y); + var cl_I_div_t q_r = ceiling2(a*d,b*c); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + return cl_RA_div_t(q,I_posI_div_RA(r,b*d)); + } + } +#else +// Methode: +// ceiling2(x/y) -> (q,r). Liefere q und x-y*q=y*r. + var cl_RA_div_t q_r = ceiling2(x/y); + var cl_I& q = q_r.quotient; + var cl_RA& r = q_r.remainder; + return cl_RA_div_t(q,y*r); +#endif +} diff --git a/src/rational/division/cl_RA_floor1.cc b/src/rational/division/cl_RA_floor1.cc new file mode 100644 index 0000000..780dc23 --- /dev/null +++ b/src/rational/division/cl_RA_floor1.cc @@ -0,0 +1,29 @@ +// floor1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" + +const cl_I floor1 (const cl_RA& x) +{ +// Methode: +// x Integer -> q := x +// x Ratio a/b -> (floor a b) + if (integerp(x)) { + DeclareType(cl_I,x); + return x; + } else { + DeclareType(cl_RT,x); + var const cl_I& a = numerator(x); + var const cl_I& b = denominator(x); + return floor1(a,b); + } +} diff --git a/src/rational/division/cl_RA_floor12.cc b/src/rational/division/cl_RA_floor12.cc new file mode 100644 index 0000000..501e367 --- /dev/null +++ b/src/rational/division/cl_RA_floor12.cc @@ -0,0 +1,47 @@ +// floor1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" + +const cl_I floor1 (const cl_RA& x, const cl_RA& y) +{ +// Methode: +// x = a/b, y = c/d -> liefere (floor (* a d) (* b c)). +// x Integer -> dito mit b=1. +// y Integer -> dito mit d=1. +// x und y Integer -> bekannt. + if (integerp(x)) { + DeclareType(cl_I,x); + if (integerp(y)) { + DeclareType(cl_I,y); + return floor1(x,y); + } else { + DeclareType(cl_RT,y); + var const cl_I& c = numerator(y); + var const cl_I& d = denominator(y); + return floor1(x*d,c); + } + } else { + DeclareType(cl_RT,x); + var const cl_I& a = numerator(x); + var const cl_I& b = denominator(x); + if (integerp(y)) { + DeclareType(cl_I,y); + return floor1(a,b*y); + } else { + DeclareType(cl_RT,y); + var const cl_I& c = numerator(y); + var const cl_I& d = denominator(y); + return floor1(a*d,b*c); + } + } +} diff --git a/src/rational/division/cl_RA_floor2.cc b/src/rational/division/cl_RA_floor2.cc new file mode 100644 index 0000000..ef4e21b --- /dev/null +++ b/src/rational/division/cl_RA_floor2.cc @@ -0,0 +1,35 @@ +// floor2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" + +const cl_RA_div_t floor2 (const cl_RA& x) +{ +// Methode: +// x Integer -> (q,r) := (x,0) +// x Ratio a/b -> +// (floor a b) liefert q und r. +// Liefere q und r/b (mit b>1 und ggT(r,b)=ggT(r+q*b,b)=ggT(a,b)=1). + if (integerp(x)) { + DeclareType(cl_I,x); + // (q,r) := (x,0) + return cl_RA_div_t(x,0); + } else { + DeclareType(cl_RT,x); + var const cl_I& a = numerator(x); + var const cl_I& b = denominator(x); + var cl_I_div_t q_r = floor2(a,b); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + return cl_RA_div_t(q,I_I_to_RT(r,b)); + } +} diff --git a/src/rational/division/cl_RA_floor22.cc b/src/rational/division/cl_RA_floor22.cc new file mode 100644 index 0000000..3300961 --- /dev/null +++ b/src/rational/division/cl_RA_floor22.cc @@ -0,0 +1,70 @@ +// floor2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" + +const cl_RA_div_t floor2 (const cl_RA& x, const cl_RA& y) +{ +#if 1 // Ist das wirklich schneller?? +// Methode: +// x = a/b, y = c/d -> +// (floor (* a d) (* b c)) liefert q und r. +// Liefere q und r/(b*d). +// x Integer -> dito mit b=1. +// y Integer -> dito mit d=1. +// x und y Integer -> bekannt. + if (integerp(x)) { + DeclareType(cl_I,x); + if (integerp(y)) { + DeclareType(cl_I,y); + var cl_I_div_t q_r = floor2(x,y); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + return cl_RA_div_t(q,r); + } else { + DeclareType(cl_RT,y); + var const cl_I& c = numerator(y); + var const cl_I& d = denominator(y); + var cl_I_div_t q_r = floor2(x*d,c); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + return cl_RA_div_t(q,I_posI_div_RA(r,d)); + } + } else { + DeclareType(cl_RT,x); + var const cl_I& a = numerator(x); + var const cl_I& b = denominator(x); + if (integerp(y)) { + DeclareType(cl_I,y); + var cl_I_div_t q_r = floor2(a,b*y); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + return cl_RA_div_t(q,I_posI_div_RA(r,b)); + } else { + DeclareType(cl_RT,y); + var const cl_I& c = numerator(y); + var const cl_I& d = denominator(y); + var cl_I_div_t q_r = floor2(a*d,b*c); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + return cl_RA_div_t(q,I_posI_div_RA(r,b*d)); + } + } +#else +// Methode: +// floor2(x/y) -> (q,r). Liefere q und x-y*q=y*r. + var cl_RA_div_t q_r = floor2(x/y); + var cl_I& q = q_r.quotient; + var cl_RA& r = q_r.remainder; + return cl_RA_div_t(q,y*r); +#endif +} diff --git a/src/rational/division/cl_RA_round1.cc b/src/rational/division/cl_RA_round1.cc new file mode 100644 index 0000000..73c6f83 --- /dev/null +++ b/src/rational/division/cl_RA_round1.cc @@ -0,0 +1,29 @@ +// round1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" + +const cl_I round1 (const cl_RA& x) +{ +// Methode: +// x Integer -> q := x +// x Ratio a/b -> (round a b) + if (integerp(x)) { + DeclareType(cl_I,x); + return x; + } else { + DeclareType(cl_RT,x); + var const cl_I& a = numerator(x); + var const cl_I& b = denominator(x); + return round1(a,b); + } +} diff --git a/src/rational/division/cl_RA_round12.cc b/src/rational/division/cl_RA_round12.cc new file mode 100644 index 0000000..c57078c --- /dev/null +++ b/src/rational/division/cl_RA_round12.cc @@ -0,0 +1,47 @@ +// round1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" + +const cl_I round1 (const cl_RA& x, const cl_RA& y) +{ +// Methode: +// x = a/b, y = c/d -> liefere (round (* a d) (* b c)). +// x Integer -> dito mit b=1. +// y Integer -> dito mit d=1. +// x und y Integer -> bekannt. + if (integerp(x)) { + DeclareType(cl_I,x); + if (integerp(y)) { + DeclareType(cl_I,y); + return round1(x,y); + } else { + DeclareType(cl_RT,y); + var const cl_I& c = numerator(y); + var const cl_I& d = denominator(y); + return round1(x*d,c); + } + } else { + DeclareType(cl_RT,x); + var const cl_I& a = numerator(x); + var const cl_I& b = denominator(x); + if (integerp(y)) { + DeclareType(cl_I,y); + return round1(a,b*y); + } else { + DeclareType(cl_RT,y); + var const cl_I& c = numerator(y); + var const cl_I& d = denominator(y); + return round1(a*d,b*c); + } + } +} diff --git a/src/rational/division/cl_RA_round2.cc b/src/rational/division/cl_RA_round2.cc new file mode 100644 index 0000000..8a38ee2 --- /dev/null +++ b/src/rational/division/cl_RA_round2.cc @@ -0,0 +1,35 @@ +// round2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" + +const cl_RA_div_t round2 (const cl_RA& x) +{ +// Methode: +// x Integer -> (q,r) := (x,0) +// x Ratio a/b -> +// (round a b) liefert q und r. +// Liefere q und r/b (mit b>1 und ggT(r,b)=ggT(r+q*b,b)=ggT(a,b)=1). + if (integerp(x)) { + DeclareType(cl_I,x); + // (q,r) := (x,0) + return cl_RA_div_t(x,0); + } else { + DeclareType(cl_RT,x); + var const cl_I& a = numerator(x); + var const cl_I& b = denominator(x); + var cl_I_div_t q_r = round2(a,b); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + return cl_RA_div_t(q,I_I_to_RT(r,b)); + } +} diff --git a/src/rational/division/cl_RA_round22.cc b/src/rational/division/cl_RA_round22.cc new file mode 100644 index 0000000..36141a7 --- /dev/null +++ b/src/rational/division/cl_RA_round22.cc @@ -0,0 +1,70 @@ +// round2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" + +const cl_RA_div_t round2 (const cl_RA& x, const cl_RA& y) +{ +#if 1 // Ist das wirklich schneller?? +// Methode: +// x = a/b, y = c/d -> +// (round (* a d) (* b c)) liefert q und r. +// Liefere q und r/(b*d). +// x Integer -> dito mit b=1. +// y Integer -> dito mit d=1. +// x und y Integer -> bekannt. + if (integerp(x)) { + DeclareType(cl_I,x); + if (integerp(y)) { + DeclareType(cl_I,y); + var cl_I_div_t q_r = round2(x,y); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + return cl_RA_div_t(q,r); + } else { + DeclareType(cl_RT,y); + var const cl_I& c = numerator(y); + var const cl_I& d = denominator(y); + var cl_I_div_t q_r = round2(x*d,c); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + return cl_RA_div_t(q,I_posI_div_RA(r,d)); + } + } else { + DeclareType(cl_RT,x); + var const cl_I& a = numerator(x); + var const cl_I& b = denominator(x); + if (integerp(y)) { + DeclareType(cl_I,y); + var cl_I_div_t q_r = round2(a,b*y); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + return cl_RA_div_t(q,I_posI_div_RA(r,b)); + } else { + DeclareType(cl_RT,y); + var const cl_I& c = numerator(y); + var const cl_I& d = denominator(y); + var cl_I_div_t q_r = round2(a*d,b*c); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + return cl_RA_div_t(q,I_posI_div_RA(r,b*d)); + } + } +#else +// Methode: +// round2(x/y) -> (q,r). Liefere q und x-y*q=y*r. + var cl_RA_div_t q_r = round2(x/y); + var cl_I& q = q_r.quotient; + var cl_RA& r = q_r.remainder; + return cl_RA_div_t(q,y*r); +#endif +} diff --git a/src/rational/division/cl_RA_trunc1.cc b/src/rational/division/cl_RA_trunc1.cc new file mode 100644 index 0000000..c64a7ba --- /dev/null +++ b/src/rational/division/cl_RA_trunc1.cc @@ -0,0 +1,29 @@ +// truncate1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" + +const cl_I truncate1 (const cl_RA& x) +{ +// Methode: +// x Integer -> q := x +// x Ratio a/b -> (truncate a b) + if (integerp(x)) { + DeclareType(cl_I,x); + return x; + } else { + DeclareType(cl_RT,x); + var const cl_I& a = numerator(x); + var const cl_I& b = denominator(x); + return truncate1(a,b); + } +} diff --git a/src/rational/division/cl_RA_trunc12.cc b/src/rational/division/cl_RA_trunc12.cc new file mode 100644 index 0000000..c6c7537 --- /dev/null +++ b/src/rational/division/cl_RA_trunc12.cc @@ -0,0 +1,47 @@ +// truncate1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" + +const cl_I truncate1 (const cl_RA& x, const cl_RA& y) +{ +// Methode: +// x = a/b, y = c/d -> liefere (truncate (* a d) (* b c)). +// x Integer -> dito mit b=1. +// y Integer -> dito mit d=1. +// x und y Integer -> bekannt. + if (integerp(x)) { + DeclareType(cl_I,x); + if (integerp(y)) { + DeclareType(cl_I,y); + return truncate1(x,y); + } else { + DeclareType(cl_RT,y); + var const cl_I& c = numerator(y); + var const cl_I& d = denominator(y); + return truncate1(x*d,c); + } + } else { + DeclareType(cl_RT,x); + var const cl_I& a = numerator(x); + var const cl_I& b = denominator(x); + if (integerp(y)) { + DeclareType(cl_I,y); + return truncate1(a,b*y); + } else { + DeclareType(cl_RT,y); + var const cl_I& c = numerator(y); + var const cl_I& d = denominator(y); + return truncate1(a*d,b*c); + } + } +} diff --git a/src/rational/division/cl_RA_trunc2.cc b/src/rational/division/cl_RA_trunc2.cc new file mode 100644 index 0000000..b0c483d --- /dev/null +++ b/src/rational/division/cl_RA_trunc2.cc @@ -0,0 +1,35 @@ +// truncate2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" + +const cl_RA_div_t truncate2 (const cl_RA& x) +{ +// Methode: +// x Integer -> (q,r) := (x,0) +// x Ratio a/b -> +// (truncate a b) liefert q und r. +// Liefere q und r/b (mit b>1 und ggT(r,b)=ggT(r+q*b,b)=ggT(a,b)=1). + if (integerp(x)) { + DeclareType(cl_I,x); + // (q,r) := (x,0) + return cl_RA_div_t(x,0); + } else { + DeclareType(cl_RT,x); + var const cl_I& a = numerator(x); + var const cl_I& b = denominator(x); + var cl_I_div_t q_r = truncate2(a,b); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + return cl_RA_div_t(q,I_I_to_RT(r,b)); + } +} diff --git a/src/rational/division/cl_RA_trunc22.cc b/src/rational/division/cl_RA_trunc22.cc new file mode 100644 index 0000000..31e96eb --- /dev/null +++ b/src/rational/division/cl_RA_trunc22.cc @@ -0,0 +1,70 @@ +// truncate2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" + +const cl_RA_div_t truncate2 (const cl_RA& x, const cl_RA& y) +{ +#if 1 // Ist das wirklich schneller?? +// Methode: +// x = a/b, y = c/d -> +// (truncate (* a d) (* b c)) liefert q und r. +// Liefere q und r/(b*d). +// x Integer -> dito mit b=1. +// y Integer -> dito mit d=1. +// x und y Integer -> bekannt. + if (integerp(x)) { + DeclareType(cl_I,x); + if (integerp(y)) { + DeclareType(cl_I,y); + var cl_I_div_t q_r = truncate2(x,y); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + return cl_RA_div_t(q,r); + } else { + DeclareType(cl_RT,y); + var const cl_I& c = numerator(y); + var const cl_I& d = denominator(y); + var cl_I_div_t q_r = truncate2(x*d,c); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + return cl_RA_div_t(q,I_posI_div_RA(r,d)); + } + } else { + DeclareType(cl_RT,x); + var const cl_I& a = numerator(x); + var const cl_I& b = denominator(x); + if (integerp(y)) { + DeclareType(cl_I,y); + var cl_I_div_t q_r = truncate2(a,b*y); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + return cl_RA_div_t(q,I_posI_div_RA(r,b)); + } else { + DeclareType(cl_RT,y); + var const cl_I& c = numerator(y); + var const cl_I& d = denominator(y); + var cl_I_div_t q_r = truncate2(a*d,b*c); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + return cl_RA_div_t(q,I_posI_div_RA(r,b*d)); + } + } +#else +// Methode: +// truncate2(x/y) -> (q,r). Liefere q und x-y*q=y*r. + var cl_RA_div_t q_r = truncate2(x/y); + var cl_I& q = q_r.quotient; + var cl_RA& r = q_r.remainder; + return cl_RA_div_t(q,y*r); +#endif +} diff --git a/src/rational/elem/Makeflags b/src/rational/elem/Makeflags new file mode 100644 index 0000000..6ed2160 --- /dev/null +++ b/src/rational/elem/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/rational/Makeflags +SUBDIR_INCLUDES += diff --git a/src/rational/elem/cl_RA_compare.cc b/src/rational/elem/cl_RA_compare.cc new file mode 100644 index 0000000..1716020 --- /dev/null +++ b/src/rational/elem/cl_RA_compare.cc @@ -0,0 +1,70 @@ +// cl_compare(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" + +cl_signean cl_compare (const cl_RA& r, const cl_RA& s) +{ +// Methode: +// r,s Integer -> klar +// r<0, s>=0 -> r=0, s<0 -> r>s. +// r Integer, s Ratio: r=a, s=b/c. Vergleiche a*c und b. +// r Ratio, s Integer: r=a/b, s=c. Vergleiche a und b*c. +// r,s Ratios: r=a/b, s=c/d. Vergleiche a*d und b*c. + // 1. Schritt: Test, ob beides Integers: + if (integerp(r) && integerp(s)) { + DeclareType(cl_I,r); + DeclareType(cl_I,s); + return cl_compare(r,s); + } + // r,s nicht beide Integers. + // 2. Schritt: Test, ob die Vorzeichen bereits das Ergebnis hergeben: + if (minusp(r)) { + if (!minusp(s)) + return signean_minus; // r<0, s>=0 -> r=0, s<0 -> r>s + } + // r,s haben gleiches Vorzeichen. + // 3. Schritt: Fallunterscheidung nach Typen + if (integerp(r)) { + DeclareType(cl_I,r); + DeclareType(cl_RT,s); + // r Integer, s Ratio: r=a, s=b/c. Vergleiche a*c und b. + var const cl_I& a = r; + var const cl_I& b = numerator(s); + var const cl_I& c = denominator(s); + return cl_compare(a*c,b); + } + elif (integerp(s)) { + DeclareType(cl_I,s); + DeclareType(cl_RT,r); + // r Ratio, s Integer: r=a/b, s=c. Vergleiche a und b*c. + var const cl_I& a = numerator(r); + var const cl_I& b = denominator(r); + var const cl_I& c = s; + return cl_compare(a,b*c); + } + else { + DeclareType(cl_RT,r); + DeclareType(cl_RT,s); + // r,s Ratios: r=a/b, s=c/d. Vergleiche a*d und b*c. + var const cl_I& a = numerator(r); + var const cl_I& b = denominator(r); + var const cl_I& c = numerator(s); + var const cl_I& d = denominator(s); + return cl_compare(a*d,b*c); + } +} +// Beschleunigung durch Konversion zu Short-Floats diese zuerst vergleichen?? diff --git a/src/rational/elem/cl_RA_denominator.cc b/src/rational/elem/cl_RA_denominator.cc new file mode 100644 index 0000000..d2c2668 --- /dev/null +++ b/src/rational/elem/cl_RA_denominator.cc @@ -0,0 +1,19 @@ +// denominator(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#define denominator inline_denominator +#include "cl_RA.h" +#undef denominator + +const cl_I denominator (const cl_RA& r) +{ + return inline_denominator(r); +} diff --git a/src/rational/elem/cl_RA_div.cc b/src/rational/elem/cl_RA_div.cc new file mode 100644 index 0000000..00ed7b1 --- /dev/null +++ b/src/rational/elem/cl_RA_div.cc @@ -0,0 +1,26 @@ +// binary operator / + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" + +const cl_RA operator/ (const cl_RA& r, const cl_RA& s) +{ +// Methode: +// (* r (/ s)) + if (integerp(r) && integerp(s)) { + DeclareType(cl_I,r); + DeclareType(cl_I,s); + // r und s Integers -> schnell abhandeln + return I_I_div_RA(r,s); + } + return r * recip(s); +} diff --git a/src/rational/elem/cl_RA_equal.cc b/src/rational/elem/cl_RA_equal.cc new file mode 100644 index 0000000..9f131d0 --- /dev/null +++ b/src/rational/elem/cl_RA_equal.cc @@ -0,0 +1,45 @@ +// cl_equal(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" + +cl_boolean cl_equal (const cl_RA& r, const cl_RA& s) +{ +// Methode: +// r,s Integer -> klar +// r Integer, s Ratio: verschieden. +// r Ratio, s Integer: verschieden. +// r,s Ratios: r=a/b, s=c/d. Vergleiche a mit c und b mit d. + if (integerp(r)) + if (integerp(s)) { + // r,s beide Integer + DeclareType(cl_I,r); + DeclareType(cl_I,s); + return cl_equal(r,s); + } else + // r Integer, s Ratio + return cl_false; + else + if (integerp(s)) + // r Ratio, s Integer + return cl_false; + else { + DeclareType(cl_RT,r); + DeclareType(cl_RT,s); + // r,s Ratios + if (!cl_equal(numerator(r),numerator(s))) + return cl_false; + if (!cl_equal(denominator(r),denominator(s))) + return cl_false; + return cl_true; + } +} diff --git a/src/rational/elem/cl_RA_from_I_I_div.cc b/src/rational/elem/cl_RA_from_I_I_div.cc new file mode 100644 index 0000000..f6c51cb --- /dev/null +++ b/src/rational/elem/cl_RA_from_I_I_div.cc @@ -0,0 +1,27 @@ +// I_I_div_RA(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_RA.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_N.h" + +const cl_RA I_I_div_RA (const cl_I& a, const cl_I& b) +{ +// Methode: +// Falls b=0: Error. +// Falls b>0: I_posI_div_RA anwenden. +// Falls b<0: I_posI_div_RA auf (- a) und (- b) anwenden. + if (eq(b,0)) + cl_error_division_by_0(); + if (minusp(b)) + return I_posI_div_RA(-a,-b); + else + return I_posI_div_RA(a,b); +} diff --git a/src/rational/elem/cl_RA_from_I_posI.cc b/src/rational/elem/cl_RA_from_I_posI.cc new file mode 100644 index 0000000..bcecc7e --- /dev/null +++ b/src/rational/elem/cl_RA_from_I_posI.cc @@ -0,0 +1,22 @@ +// I_I_to_RA(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_RA.h" + + +// Implementation. + +#include "cl_I.h" + +const cl_RA I_I_to_RA (const cl_I& a, const cl_I& b) +{ +// Methode: +// falls b=1, a als Ergebnis, sonst der echte Bruch a/b. + if (eq(b,1)) + return a; + else + return allocate_ratio(a,b); +} diff --git a/src/rational/elem/cl_RA_from_I_posI1.cc b/src/rational/elem/cl_RA_from_I_posI1.cc new file mode 100644 index 0000000..e1ff5c3 --- /dev/null +++ b/src/rational/elem/cl_RA_from_I_posI1.cc @@ -0,0 +1,15 @@ +// I_I_to_RT(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_RA.h" + + +// Implementation. + +const cl_RA I_I_to_RT (const cl_I& a, const cl_I& b) +{ + return allocate_ratio(a,b); +} diff --git a/src/rational/elem/cl_RA_from_I_posI_div.cc b/src/rational/elem/cl_RA_from_I_posI_div.cc new file mode 100644 index 0000000..a0be726 --- /dev/null +++ b/src/rational/elem/cl_RA_from_I_posI_div.cc @@ -0,0 +1,26 @@ +// I_posI_div_RA(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_RA.h" + + +// Implementation. + +#include "cl_integer.h" +#include "cl_I.h" + +const cl_RA I_posI_div_RA (const cl_I& a, const cl_I& b) +{ +// Methode: +// d:=ggT(a,b). +// Falls d=1: I_I_to_RA anwenden, +// sonst: I_I_to_RA auf a/d und b/d anwenden. + var cl_I d = gcd(a,b); + if (eq(d,1)) + return I_I_to_RA(a,b); + else + return I_I_to_RA(exquo(a,d),exquopos(b,d)); +} diff --git a/src/rational/elem/cl_RA_minus.cc b/src/rational/elem/cl_RA_minus.cc new file mode 100644 index 0000000..385b3b2 --- /dev/null +++ b/src/rational/elem/cl_RA_minus.cc @@ -0,0 +1,110 @@ +// binary operator - + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" +#include "cl_I.h" + +const cl_RA operator- (const cl_RA& r, const cl_RA& s) +{ +#if 0 +// Methode: +// (+ r (- s)) + return r + (- s); +#else +// Methode (vgl. [Buchberger, Collins, Loos: Computer Algebra, S.200-201]) +// r,s beide Integers -> klar. +// r=a/b, s=c -> Ergebnis (a-b*c)/b +// (mit b>1 und ggT(a-b*c,b) = ggT(a,b) = 1) +// Bei c=0 direkt r als Ergebnis. +// r=a, s=c/d -> Ergebnis (a*d-c)/d +// (mit d>1 und ggT(a*d-c,d) = ggT(-c,d) = ggT(c,d) = 1) +// Bei a=0 direkt -s = (-c)/d als Ergebnis. +// r=a/b, s=c/d: +// g:=ggT(b,d)>0. +// Falls g=1: +// Ergebnis (a*d-b*c)/(b*d), +// (mit b*d>1 wegen b>1, d>1, und +// ggT(a*d-b*c,b*d) = 1 +// wegen ggT(a*d-b*c,b) = ggT(a*d,b) = 1 (wegen ggT(a,b)=1 und ggT(d,b)=1) +// und ggT(a*d-b*c,d) = ggT(b*c,d) = 1 (wegen ggT(b,d)=1 und ggT(c,d)=1) +// ) +// Sonst b' := b/g, d' := d/g. e := a*d'-b'*c, f:= b'*d = b*d'. +// Es ist g = ggT(g*b',g*d') = g*ggT(b',d'), also ggT(b',d')=1. +// Es ist r-s = (a*d-b*c)/(b*d) = (nach Kürzen mit g) e/f. +// Außerdem: +// ggT(a,b') teilt ggT(a,b)=1, also ggT(a,b')=1. Mit ggT(d',b')=1 folgt +// 1 = ggT(a*d',b') = ggT(a*d'-b'*c,b') = ggT(e,b'). +// ggT(c,d') teilt ggT(c,d)=1, also ggT(c,d')=1. Mit ggT(b',d')=1 folgt +// 1 = ggT(b'*c,d') = ggT(a*d'-b'*c,d') = ggT(e,d'). +// Daher ist ggT(e,f) = ggT(e,b'*d'*g) = ggT(e,g). +// Errechne daher h=ggT(e,g). +// Bei h=1 ist e/f das Ergebnis (mit f>1, da d>1, und ggT(e,f)=1), +// sonst ist (e/h)/(f/h) das Ergebnis. + if (integerp(s)) { + // s ist Integer + DeclareType(cl_I,s); + if (eq(s,0)) { return r; } // s=0 -> r als Ergebnis + if (integerp(r)) { + // beides Integers + DeclareType(cl_I,r); + return r-s; + } else { + DeclareType(cl_RT,r); + var const cl_I& a = numerator(r); + var const cl_I& b = denominator(r); + var const cl_I& c = s; + // r = a/b, s = c. + return I_I_to_RT(a-b*c,b); + } + } else { + // s ist Ratio + DeclareType(cl_RT,s); + if (integerp(r)) { + // r ist Integer + DeclareType(cl_I,r); + if (eq(r,0)) { + // r=0 -> -s als Ergebnis + var const cl_I& c = numerator(s); + var const cl_I& d = denominator(s); + return I_I_to_RT(-c,d); + } + var const cl_I& a = r; + var const cl_I& c = numerator(s); + var const cl_I& d = denominator(s); + // r = a, s = c/d. + return I_I_to_RT(a*d-c,d); + } else { + // r,s beide Ratios + DeclareType(cl_RT,r); + var const cl_I& a = numerator(r); + var const cl_I& b = denominator(r); + var const cl_I& c = numerator(s); + var const cl_I& d = denominator(s); + var cl_I g = gcd(b,d); // g = ggT(b,d) >0 bilden + if (eq(g,1)) + // g=1 -> Ergebnis (a*d-b*c)/(b*d) + return I_I_to_RT(a*d-b*c,b*d); + // g>1 + var cl_I bp = exquopos(b,g); // b' := b/g (b,g>0) + var cl_I dp = exquopos(d,g); // d' := d/g (d,g>0) + var cl_I e = a*dp-bp*c; // e := a*d'-b'*c + var cl_I f = bp*d; // f := b'*d + var cl_I h = gcd(e,g); // h := ggT(e,g) + if (eq(h,1)) + // h=1 + return I_I_to_RT(e,f); + // h>1 + return I_I_to_RA(exquo(e,h),exquopos(f,h)); // (e/h)/(f/h) als Ergebnis + } + } +#endif +} diff --git a/src/rational/elem/cl_RA_minus1.cc b/src/rational/elem/cl_RA_minus1.cc new file mode 100644 index 0000000..5f46e66 --- /dev/null +++ b/src/rational/elem/cl_RA_minus1.cc @@ -0,0 +1,29 @@ +// minus1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" + +const cl_RA minus1 (const cl_RA& r) +{ +// Methode: +// Falls r ein Integer ist: I_minus1_plus_I anwenden +// Falls r = a/b: (a-b)/b, wobei b>1 und ggT(a-b,b)=ggT(a,b)=1 ist. + if (integerp(r)) { + DeclareType(cl_I,r); + return minus1(r); + } else { + DeclareType(cl_RT,r); + var const cl_I& a = numerator(r); + var const cl_I& b = denominator(r); + return I_I_to_RT(a-b,b); + } +} diff --git a/src/rational/elem/cl_RA_minusp.cc b/src/rational/elem/cl_RA_minusp.cc new file mode 100644 index 0000000..4f3d325 --- /dev/null +++ b/src/rational/elem/cl_RA_minusp.cc @@ -0,0 +1,19 @@ +// minusp(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#define minusp inline_minusp +#include "cl_RA.h" +#undef minusp + +cl_boolean minusp (const cl_RA& x) +{ + return inline_minusp(x); +} diff --git a/src/rational/elem/cl_RA_mul.cc b/src/rational/elem/cl_RA_mul.cc new file mode 100644 index 0000000..6f0dfab --- /dev/null +++ b/src/rational/elem/cl_RA_mul.cc @@ -0,0 +1,99 @@ +// binary operator * + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" +#include "cl_I.h" + +const cl_RA operator* (const cl_RA& r, const cl_RA& s) +{ +// Methode (vgl. [Buchberger, Collins, Loos: Computer Algebra, S.201]) +// r,s beide Integers -> klar. +// r=a/b, s=c -> +// Bei c=0 Ergebnis 0. +// g:=ggT(b,c). +// Falls g=1: Ergebnis (a*c)/b (mit b>1, ggT(a*c,b)=1). +// Sonst: b':=b/g, c':=c/g, Ergebnis (a*c')/b' (mit ggT(a*c',b')=1). +// r=a, s=c/d analog. +// r=a/b, s=c/d -> +// g:=ggT(a,d), h:=ggT(b,c). +// a':=a/g, d':=d/g (nur bei g>1 bedeutet das Rechnung). +// b':=b/h, c':=c/h (nur bei h>1 bedeutet das Rechnung). +// Ergebnis ist = (a'*c')/(b'*d'). + if (integerp(s)) { + // s Integer + DeclareType(cl_I,s); + if (integerp(r)) { + // beides Integer + DeclareType(cl_I,r); + return r*s; + } else { + DeclareType(cl_RT,r); + var const cl_I& a = numerator(r); + var const cl_I& b = denominator(r); + var const cl_I& c = s; + // r=a/b, s=c, bilde a/b * c. + if (zerop(c)) + { return 0; } // c=0 -> Ergebnis 0 + var cl_I g = gcd(b,c); + if (eq(g,1)) + // g=1 + return I_I_to_RT(a*c,b); // (a*c)/b + else + // g>1 + return I_I_to_RA(a*exquo(c,g),exquopos(b,g)); // (a*(c/g))/(b/g) + } + } else { + // s ist Ratio + DeclareType(cl_RT,s); + if (integerp(r)) { + // r Integer + DeclareType(cl_I,r); + var const cl_I& a = r; + var const cl_I& b = numerator(s); + var const cl_I& c = denominator(s); + // r=a, s=b/c, bilde a * b/c. + if (zerop(a)) + { return 0; } // a=0 -> Ergebnis 0 + var cl_I g = gcd(a,c); + if (eq(g,1)) + // g=1 + return I_I_to_RT(a*b,c); // (a*b)/c + else + // g>1 + return I_I_to_RA(exquo(a,g)*b,exquopos(c,g)); // ((a/g)*b)/(c/g) + } else { + // r,s beide Ratios + DeclareType(cl_RT,r); + var const cl_I& a = numerator(r); + var const cl_I& b = denominator(r); + var const cl_I& c = numerator(s); + var const cl_I& d = denominator(s); + var cl_I ap, dp; + { + var cl_I g = gcd(a,d); + if (eq(g,1)) + { ap = a; dp = d; } + else + { ap = exquo(a,g); dp = exquopos(d,g); } + } + var cl_I cp, bp; + { + var cl_I h = gcd(b,c); + if (eq(h,1)) + { cp = c; bp = b; } + else + { cp = exquo(c,h); bp = exquopos(b,h); } + } + return I_I_to_RA(ap*cp,bp*dp); // (a'*c')/(b'*d') + } + } +} diff --git a/src/rational/elem/cl_RA_numerator.cc b/src/rational/elem/cl_RA_numerator.cc new file mode 100644 index 0000000..b4d1b4c --- /dev/null +++ b/src/rational/elem/cl_RA_numerator.cc @@ -0,0 +1,19 @@ +// numerator(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#define numerator inline_numerator +#include "cl_RA.h" +#undef numerator + +const cl_I numerator (const cl_RA& r) +{ + return inline_numerator(r); +} diff --git a/src/rational/elem/cl_RA_plus.cc b/src/rational/elem/cl_RA_plus.cc new file mode 100644 index 0000000..a70b42f --- /dev/null +++ b/src/rational/elem/cl_RA_plus.cc @@ -0,0 +1,99 @@ +// binary operator + + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" +#include "cl_I.h" + +const cl_RA operator+ (const cl_RA& r, const cl_RA& s) +{ +// Methode (vgl. [Buchberger, Collins, Loos: Computer Algebra, S.200-201]) +// r,s beide Integers -> klar. +// r=a/b, s=c -> Ergebnis (a+b*c)/b +// (mit b>1 und ggT(a+b*c,b) = ggT(a,b) = 1) +// Bei c=0 direkt r als Ergebnis. +// r=a, s=c/d -> Ergebnis (a*d+c)/d +// (mit d>1 und ggT(a*d+c,d) = ggT(c,d) = 1) +// Bei a=0 direkt s als Ergebnis. +// r=a/b, s=c/d: +// g:=ggT(b,d)>0. +// Falls g=1: +// Ergebnis (a*d+b*c)/(b*d), +// (mit b*d>1 wegen b>1, d>1, und +// ggT(a*d+b*c,b*d) = 1 +// wegen ggT(a*d+b*c,b) = ggT(a*d,b) = 1 (wegen ggT(a,b)=1 und ggT(d,b)=1) +// und ggT(a*d+b*c,d) = ggT(b*c,d) = 1 (wegen ggT(b,d)=1 und ggT(c,d)=1) +// ) +// Sonst b' := b/g, d' := d/g. e := a*d'+b'*c, f:= b'*d = b*d'. +// Es ist g = ggT(g*b',g*d') = g*ggT(b',d'), also ggT(b',d')=1. +// Es ist r+s = (a*d+b*c)/(b*d) = (nach Kürzen mit g) e/f. +// Außerdem: +// ggT(a,b') teilt ggT(a,b)=1, also ggT(a,b')=1. Mit ggT(d',b')=1 folgt +// 1 = ggT(a*d',b') = ggT(a*d'+b'*c,b') = ggT(e,b'). +// ggT(c,d') teilt ggT(c,d)=1, also ggT(c,d')=1. Mit ggT(b',d')=1 folgt +// 1 = ggT(b'*c,d') = ggT(a*d'+b'*c,d') = ggT(e,d'). +// Daher ist ggT(e,f) = ggT(e,b'*d'*g) = ggT(e,g). +// Errechne daher h=ggT(e,g). +// Bei h=1 ist e/f das Ergebnis (mit f>1, da d>1, und ggT(e,f)=1), +// sonst ist (e/h)/(f/h) das Ergebnis. + if (integerp(s)) { + // s ist Integer + DeclareType(cl_I,s); + if (eq(s,0)) { return r; } // s=0 -> r als Ergebnis + if (integerp(r)) { + // beides Integers + DeclareType(cl_I,r); + return r+s; + } else { + DeclareType(cl_RT,r); + var const cl_I& a = numerator(r); + var const cl_I& b = denominator(r); + var const cl_I& c = s; + // r = a/b, s = c. + return I_I_to_RT(a+b*c,b); + } + } else { + // s ist Ratio + DeclareType(cl_RT,s); + if (integerp(r)) { + // r ist Integer + DeclareType(cl_I,r); + if (eq(r,0)) { return s; } // r=0 -> s als Ergebnis + var const cl_I& a = r; + var const cl_I& c = numerator(s); + var const cl_I& d = denominator(s); + // r = a, s = c/d. + return I_I_to_RT(a*d+c,d); + } else { + // r,s beide Ratios + DeclareType(cl_RT,r); + var const cl_I& a = numerator(r); + var const cl_I& b = denominator(r); + var const cl_I& c = numerator(s); + var const cl_I& d = denominator(s); + var cl_I g = gcd(b,d); // g = ggT(b,d) >0 bilden + if (eq(g,1)) + // g=1 -> Ergebnis (a*d+b*c)/(b*d) + return I_I_to_RT(a*d+b*c,b*d); + // g>1 + var cl_I bp = exquopos(b,g); // b' := b/g (b,g>0) + var cl_I dp = exquopos(d,g); // d' := d/g (d,g>0) + var cl_I e = a*dp+bp*c; // e := a*d'+b'*c + var cl_I f = bp*d; // f := b'*d + var cl_I h = gcd(e,g); // h := ggT(e,g) + if (eq(h,1)) + // h=1 + return I_I_to_RT(e,f); + // h>1 + return I_I_to_RA(exquo(e,h),exquopos(f,h)); // (e/h)/(f/h) als Ergebnis + } + } +} diff --git a/src/rational/elem/cl_RA_plus1.cc b/src/rational/elem/cl_RA_plus1.cc new file mode 100644 index 0000000..aa60f10 --- /dev/null +++ b/src/rational/elem/cl_RA_plus1.cc @@ -0,0 +1,29 @@ +// plus1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" + +const cl_RA plus1 (const cl_RA& r) +{ +// Methode: +// Falls r ein Integer ist: I_1_plus_I anwenden +// Falls r = a/b: (a+b)/b, wobei b>1 und ggT(a+b,b)=ggT(a,b)=1 ist. + if (integerp(r)) { + DeclareType(cl_I,r); + return plus1(r); + } else { + DeclareType(cl_RT,r); + var const cl_I& a = numerator(r); + var const cl_I& b = denominator(r); + return I_I_to_RT(a+b,b); + } +} diff --git a/src/rational/elem/cl_RA_plusp.cc b/src/rational/elem/cl_RA_plusp.cc new file mode 100644 index 0000000..5461caa --- /dev/null +++ b/src/rational/elem/cl_RA_plusp.cc @@ -0,0 +1,26 @@ +// plusp(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#define minusp inline_minusp +#define zerop inline_zerop +#include "cl_RA.h" +#undef zerop +#undef minusp + +cl_boolean plusp (const cl_RA& x) +{ + if (inline_minusp(x)) + return cl_false; // x<0 -> nein + elif (inline_zerop(x)) + return cl_false; // x=0 -> nein + else + return cl_true; // sonst ist x>0. +} diff --git a/src/rational/elem/cl_RA_recip.cc b/src/rational/elem/cl_RA_recip.cc new file mode 100644 index 0000000..c213dfd --- /dev/null +++ b/src/rational/elem/cl_RA_recip.cc @@ -0,0 +1,33 @@ +// recip(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_N.h" +#include "cl_I.h" + +const cl_RA recip (const cl_RA& r) +{ +// Methode: +// r=0 -> Error. +// a:=(numerator r), b:=(denominator r). +// a>0 -> Ergebnis b/a (mit ggT(b,a)=1). +// a<0 -> Ergebnis (- b)/(- a) (mit ggT(-b,-a)=1). + if (zerop(r)) + cl_error_division_by_0(); + var cl_I a; + var cl_I b; + RA_numden_I_I(r, a = , b = ); + if (!minusp(a)) + return I_I_to_RA(b,a); + else + // a<0 + return I_I_to_RA(-b,-a); +} diff --git a/src/rational/elem/cl_RA_square.cc b/src/rational/elem/cl_RA_square.cc new file mode 100644 index 0000000..490fd6a --- /dev/null +++ b/src/rational/elem/cl_RA_square.cc @@ -0,0 +1,30 @@ +// square(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" + +const cl_RA square (const cl_RA& r) +{ +// Methode: +// r Integer -> klar. +// r = a/b -> Ergebnis a^2/b^2 + if (integerp(r)) { + DeclareType(cl_I,r); + return square(r); + } else { + DeclareType(cl_RT,r); + var const cl_I& a = numerator(r); + var const cl_I& b = denominator(r); + // Immer noch b^2>1 und ggT(a^2,b^2) = ggT(a,b)^2 = 1 + return I_I_to_RT(square(a),square(b)); + } +} diff --git a/src/rational/elem/cl_RA_uminus.cc b/src/rational/elem/cl_RA_uminus.cc new file mode 100644 index 0000000..c8ea606 --- /dev/null +++ b/src/rational/elem/cl_RA_uminus.cc @@ -0,0 +1,30 @@ +// unary operator - + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" + +const cl_RA operator- (const cl_RA& r) +{ +// Methode: +// r Integer -> klar. +// r = a/b -> Ergebnis (- a)/b + if (integerp(r)) { + DeclareType(cl_I,r); + return -r; + } else { + DeclareType(cl_RT,r); + var const cl_I& a = numerator(r); + var const cl_I& b = denominator(r); + // Immer noch b>1 und ggT(-a,b) = ggT(a,b) = 1 + return I_I_to_RT(-a,b); + } +} diff --git a/src/rational/elem/cl_RA_zerop.cc b/src/rational/elem/cl_RA_zerop.cc new file mode 100644 index 0000000..91b4f8a --- /dev/null +++ b/src/rational/elem/cl_RA_zerop.cc @@ -0,0 +1,19 @@ +// zerop(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#define zerop inline_zerop +#include "cl_RA.h" +#undef zerop + +cl_boolean zerop (const cl_RA& x) +{ + return inline_zerop(x); +} diff --git a/src/rational/input/Makeflags b/src/rational/input/Makeflags new file mode 100644 index 0000000..f43d855 --- /dev/null +++ b/src/rational/input/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/rational/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/base/string diff --git a/src/rational/input/cl_RA_from_string.cc b/src/rational/input/cl_RA_from_string.cc new file mode 100644 index 0000000..4f68d73 --- /dev/null +++ b/src/rational/input/cl_RA_from_string.cc @@ -0,0 +1,26 @@ +// cl_RA (const char *) constructor. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational_class.h" + + +// Implementation. + +#include "cl_input.h" +#include "cl_rational_io.h" + +cl_read_flags cl_RA_read_flags = { + syntax_rational, + lsyntax_all, + 10, + { cl_float_format_ffloat, cl_float_format_lfloat_min, cl_true } +}; + +cl_RA::cl_RA (const char * string) +{ + pointer = as_cl_private_thing( + read_rational(cl_RA_read_flags,string,NULL,NULL)); +} diff --git a/src/rational/input/cl_RA_read.cc b/src/rational/input/cl_RA_read.cc new file mode 100644 index 0000000..8252a7d --- /dev/null +++ b/src/rational/input/cl_RA_read.cc @@ -0,0 +1,153 @@ +// read_rational(). +// This file contains a slimmed down version of read_real(). +// It does not pull in all the floating-point, complex and transcendental +// function code. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational_io.h" + + +// Implementation. + +#include +#include "cl_input.h" +#include "cl_integer.h" +#include "cl_integer_io.h" +#include "cl_I.h" +#include "cl_abort.h" + +#undef floor +#include +#define floor cln_floor + +// Step forward over all digits, to the end of string or to the next non-digit. +static const char * skip_digits (const char * ptr, const char * string_limit, unsigned int base) +{ + for ( ; ptr != string_limit; ptr++) { + var char ch = *ptr; + if ((ch >= '0') && (ch <= '9')) + if (ch < '0' + (int)base) + continue; + else + break; + else { + if (base <= 10) + break; + if (((ch >= 'A') && (ch < 'A'-10+(int)base)) + || ((ch >= 'a') && (ch < 'a'-10+(int)base)) + ) + continue; + else + break; + } + } + return ptr; +} + +#define at_end_of_parse(ptr) \ + if (end_of_parse) \ + { *end_of_parse = (ptr); } \ + else \ + { if ((ptr) != string_limit) { read_number_junk((ptr),string,string_limit); } } + +const cl_RA read_rational (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse) +{ + ASSERT((flags.syntax & ~(syntax_rational|syntax_maybe_bad)) == 0); + // If no string_limit is given, it defaults to the end of the string. + if (!string_limit) + string_limit = string + strlen(string); + if (flags.syntax & syntax_rational) { + // Check for rational number syntax. + var unsigned int rational_base = flags.rational_base; + var const char * ptr = string; + if (flags.lsyntax & lsyntax_commonlisp) { + if (ptr == string_limit) goto not_rational_syntax; + if (*ptr == '#') { + // Check for #b, #o, #x, #nR syntax. + ptr++; + if (ptr == string_limit) goto not_rational_syntax; + switch (*ptr) { + case 'b': case 'B': + rational_base = 2; break; + case 'o': case 'O': + rational_base = 8; break; + case 'x': case 'X': + rational_base = 16; break; + default: + var const char * base_end_ptr = + skip_digits(ptr,string_limit,10); + if (base_end_ptr == ptr) goto not_rational_syntax; + if (base_end_ptr == string_limit) goto not_rational_syntax; + if (!((*base_end_ptr == 'r') || (*base_end_ptr == 'R'))) + goto not_rational_syntax; + var cl_I base = read_integer(10,0,ptr,0,base_end_ptr-ptr); + if (!((base >= 2) && (base <= 36))) { + fprint(cl_stderr, "Base must be an integer in the range from 2 to 36, not "); + fprint(cl_stderr, base); + fprint(cl_stderr, "\n"); + cl_abort(); + } + rational_base = FN_to_UL(base); ptr = base_end_ptr; + break; + } + ptr++; + } + } + var const char * ptr_after_prefix = ptr; + var cl_signean sign = 0; + if (ptr == string_limit) goto not_rational_syntax; + switch (*ptr) { + case '-': sign = ~sign; + case '+': ptr++; + default: break; + } + var const char * ptr_after_sign = ptr; + if (flags.syntax & syntax_integer) { + // Check for integer syntax: {'+'|'-'|} {digit}+ {'.'|} + // Allow final dot only in Common Lisp syntax if there was no # prefix. + if ((flags.lsyntax & lsyntax_commonlisp) && (ptr_after_prefix == string)) { + ptr = skip_digits(ptr_after_sign,string_limit,10); + if (ptr != ptr_after_sign) + if (ptr != string_limit) + if (*ptr == '.') { + ptr++; + if ((ptr == string_limit) || !(((*ptr >= '0') && (*ptr <= '9')) || ((*ptr >= 'A') && (*ptr <= 'Z') && (*ptr != 'I')) || ((*ptr >= 'a') && (*ptr <= 'z') && (*ptr != 'i')) || (*ptr == '.') || (*ptr == '_') || (*ptr == '/'))) { + at_end_of_parse(ptr); + return read_integer(10,sign,ptr_after_sign,0,ptr-ptr_after_sign); + } + } + } + ptr = skip_digits(ptr_after_sign,string_limit,rational_base); + if ((ptr == string_limit) || !(((*ptr >= '0') && (*ptr <= '9')) || ((*ptr >= 'A') && (*ptr <= 'Z') && (*ptr != 'I')) || ((*ptr >= 'a') && (*ptr <= 'z') && (*ptr != 'i')) || (*ptr == '.') || (*ptr == '_') || (*ptr == '/'))) { + at_end_of_parse(ptr); + return read_integer(rational_base,sign,ptr_after_sign,0,ptr-ptr_after_sign); + } + } + if (flags.syntax & syntax_ratio) { + // Check for ratio syntax: {'+'|'-'|} {digit}+ '/' {digit}+ + ptr = skip_digits(ptr_after_sign,string_limit,rational_base); + if (ptr != ptr_after_sign) + if (ptr != string_limit) + if (*ptr == '/') { + var const char * ptr_at_slash = ptr; + ptr = skip_digits(ptr_at_slash+1,string_limit,rational_base); + if (ptr != ptr_at_slash+1) + if ((ptr == string_limit) || !(((*ptr >= '0') && (*ptr <= '9')) || ((*ptr >= 'A') && (*ptr <= 'Z') && (*ptr != 'I')) || ((*ptr >= 'a') && (*ptr <= 'z') && (*ptr != 'i')) || (*ptr == '.') || (*ptr == '_') || (*ptr == '/'))) { + at_end_of_parse(ptr); + return read_rational(rational_base,sign,ptr_after_sign,0,ptr_at_slash-ptr_after_sign,ptr-ptr_after_sign); + } + } + } + } +not_rational_syntax: +bad_syntax: + if (flags.syntax & syntax_maybe_bad) { + ASSERT(end_of_parse); + *end_of_parse = string; + return 0; // dummy return + } + read_number_bad_syntax(string,string_limit); +} diff --git a/src/rational/input/cl_RA_read_stream.cc b/src/rational/input/cl_RA_read_stream.cc new file mode 100644 index 0000000..b7a8ce7 --- /dev/null +++ b/src/rational/input/cl_RA_read_stream.cc @@ -0,0 +1,105 @@ +// read_rational(). +// This file contains a slimmed down version of read_real(). +// It does not pull in all the floating-point, complex and transcendental +// function code. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational_io.h" + + +// Implementation. + +#include "cl_input.h" +#include "cl_io.h" +#include "cl_spushstring.h" + +// We read an entire token (or even more, if it begins with #C) into a +// buffer and then call read_rational() on the buffer. + +class pushstring_hack : public cl_spushstring { +public: + char* start_pointer (void) { return buffer; } + char* end_pointer (void) { return buffer+index; } +}; + +static cl_boolean number_char_p (char c) +{ + if ((c >= '0') && (c <= '9')) + return cl_true; + if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'))) + return cl_true; + switch (c) { + case '+': case '-': case '.': case '/': + return cl_true; + default: + return cl_false; + } +} + +const cl_RA read_rational (cl_istream stream, const cl_read_flags& flags) +{ + // One pre-allocated buffer. This reduces the allocation/free cost. + static pushstring_hack buffer; + + var int c; + // Skip whitespace at the beginning. + loop { + c = freadchar(stream); + if (c == cl_EOF) goto eof; + if ((c == ' ') || (c == '\t') || (c == '\n')) + continue; + else + break; + } + // Found first non-whitespace character. + // Numbers cannot cross lines. We can treat EOF and '\n' the same way. + buffer.reset(); + if (c == '#') { + if (!(flags.lsyntax & lsyntax_commonlisp)) + goto syntax1; + buffer.push(c); + // Read some digits, then a letter, then a token. + loop { + c = freadchar(stream); + if (c == cl_EOF) goto eof; + buffer.push(c); + if ((c >= '0') && (c <= '9')) + continue; + else + break; + } + if (!(((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')))) + goto syntax1; + buffer.push(c); + c = freadchar(stream); + if (c == cl_EOF) goto eof; + } + // Read a number token. + if (!number_char_p(c)) + goto syntax1; + loop { + buffer.push(c); + c = freadchar(stream); + if (c == cl_EOF) + break; + if (!number_char_p(c)) { + funreadchar(stream,c); + break; + } + } + // Parse the number. + return read_rational(flags, + buffer.start_pointer(), buffer.end_pointer(), + NULL + ); + + // Handle syntax error. +syntax1: buffer.push(c); + read_number_bad_syntax(buffer.start_pointer(),buffer.end_pointer()); + + // Handle premature EOF. +eof: read_number_eof(); +} diff --git a/src/rational/input/cl_RA_readparsed.cc b/src/rational/input/cl_RA_readparsed.cc new file mode 100644 index 0000000..59c017e --- /dev/null +++ b/src/rational/input/cl_RA_readparsed.cc @@ -0,0 +1,28 @@ +// read_rational(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational_io.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_I.h" +#include "cl_N.h" + +const cl_RA read_rational (unsigned int base, cl_signean sign, const char * string, uintL index1, uintL index3, uintL index2) +{ + var uintL index3_1 = index3+1; // Index der ersten Nennerziffer + var cl_I den = // Nenner + digits_to_I(&string[index3_1],index2-index3_1,(uintD)base); + if (zerop(den)) // Division durch 0 abfangen + { cl_error_division_by_0(); } + var cl_I num = // Zähler + digits_to_I(&string[index1],index3-index1,(uintD)base); + if (!(sign == 0)) + num = -num; // incl. Vorzeichen + return I_posI_div_RA(num,den); +} diff --git a/src/rational/misc/Makeflags b/src/rational/misc/Makeflags new file mode 100644 index 0000000..6ed2160 --- /dev/null +++ b/src/rational/misc/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/rational/Makeflags +SUBDIR_INCLUDES += diff --git a/src/rational/misc/cl_RA_abs.cc b/src/rational/misc/cl_RA_abs.cc new file mode 100644 index 0000000..3c5113b --- /dev/null +++ b/src/rational/misc/cl_RA_abs.cc @@ -0,0 +1,23 @@ +// abs(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" + +const cl_RA abs (const cl_RA& r) +{ + // Methode: + // Bei r<0: (- r), sonst r. + if (minusp(r)) + return -r; + else + return r; +} diff --git a/src/rational/misc/cl_RA_as.cc b/src/rational/misc/cl_RA_as.cc new file mode 100644 index 0000000..f5d786e --- /dev/null +++ b/src/rational/misc/cl_RA_as.cc @@ -0,0 +1,38 @@ +// as_cl_RA(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_N.h" + +// Cf. cl_RA_p in cl_RA_ring.cc. +// But here, for better inlining in g++, it is preferrable to finish every +// alternative with either "return cl_true;" or "return cl_false;". + +inline cl_boolean cl_RA_p (const cl_number& x) +{ + if (!x.pointer_p()) + switch (x.nonpointer_tag()) { + case cl_FN_tag: + return cl_true; + } + else + if (x.pointer_type()->flags & cl_class_flags_subclass_rational) + return cl_true; + return cl_false; +} + +const cl_RA& as_cl_RA (const cl_number& x, const char * filename, int line) +{ + if (cl_RA_p(x)) { + DeclareType(cl_RA,x); + return x; + } else + cl_as_error(x,"a rational number",filename,line); +} diff --git a/src/rational/misc/cl_RA_class.cc b/src/rational/misc/cl_RA_class.cc new file mode 100644 index 0000000..e44387c --- /dev/null +++ b/src/rational/misc/cl_RA_class.cc @@ -0,0 +1,22 @@ +// cl_class_ratio. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" + +static void ratio_destructor (cl_heap* pointer) +{ + (*(cl_heap_ratio*)pointer).~cl_heap_ratio(); +} + +cl_class cl_class_ratio = { + ratio_destructor, + cl_class_flags_subclass_complex | cl_class_flags_subclass_real | cl_class_flags_subclass_rational +}; diff --git a/src/rational/misc/cl_RA_debug.cc b/src/rational/misc/cl_RA_debug.cc new file mode 100644 index 0000000..ade07df --- /dev/null +++ b/src/rational/misc/cl_RA_debug.cc @@ -0,0 +1,30 @@ +// cl_RA debugging support. + +// General includes. +#include "cl_sysdep.h" + +// Specification. + + +// Implementation. + +#include "cl_rational.h" +#include "cl_io.h" +#include "cl_rational_io.h" + +static void dprint (cl_heap* pointer) +{ + var const cl_RA& obj = *(const cl_RA*)&pointer; + fprint(cl_debugout, "(cl_RA) "); + fprint(cl_debugout, obj); +} +AT_INITIALIZATION(dprint_RA) +{ cl_register_type_printer(cl_class_ratio,dprint); } + +// This dummy links in this module when requires it. +int cl_RA_debug_module; + +extern int cl_I_debug_module; +static void* dummy[] = { &dummy, + &cl_I_debug_module +}; diff --git a/src/rational/misc/cl_RA_eqhashcode.cc b/src/rational/misc/cl_RA_eqhashcode.cc new file mode 100644 index 0000000..32de95a --- /dev/null +++ b/src/rational/misc/cl_RA_eqhashcode.cc @@ -0,0 +1,29 @@ +// cl_RA equal_hashcode(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_N.h" +#include "cl_RA.h" + +uint32 cl_equal_hashcode (const cl_RA& r) +{ + if (integerp(r)) { + DeclareType(cl_I,r); + return cl_equal_hashcode(r); + } else { + // Making sure that a float and its rational equivalent have + // the same hash code is tricky. This code depends on the fact + // that the equal_hashcode_low macro is linear in `exp'. + DeclareType(cl_RT,r); + return cl_equal_hashcode(numerator(r)) + - cl_equal_hashcode(denominator(r)) + + equal_hashcode_one; + } +} diff --git a/src/rational/misc/cl_RA_expt.cc b/src/rational/misc/cl_RA_expt.cc new file mode 100644 index 0000000..d65f8d6 --- /dev/null +++ b/src/rational/misc/cl_RA_expt.cc @@ -0,0 +1,24 @@ +// expt(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +const cl_RA expt (const cl_RA& x, sintL y) +{ +// Methode: +// Für y>0: klar. +// Für y=0: Ergebnis 1. +// Für y<0: (/ (expt x (- y))). + if (y > 0) + return expt_pos(x,(uintL)y); + elif (y == 0) + return 1; + else // y < 0 + return recip(expt_pos(x,(uintL)(-y))); +} diff --git a/src/rational/misc/cl_RA_expt_I.cc b/src/rational/misc/cl_RA_expt_I.cc new file mode 100644 index 0000000..0a0cd79 --- /dev/null +++ b/src/rational/misc/cl_RA_expt_I.cc @@ -0,0 +1,27 @@ +// expt(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_integer.h" +#include "cl_I.h" + +const cl_RA expt (const cl_RA& x, const cl_I& y) +{ +// Methode: +// Für y>0: klar. +// Für y=0: Ergebnis 1. +// Für y<0: (/ (expt x (- y))). + if (minusp(y)) + return recip(expt_pos(x,-y)); + elif (zerop(y)) + return 1; + else // y > 0 + return expt_pos(x,y); +} diff --git a/src/rational/misc/cl_RA_exptpos.cc b/src/rational/misc/cl_RA_exptpos.cc new file mode 100644 index 0000000..2db9d74 --- /dev/null +++ b/src/rational/misc/cl_RA_exptpos.cc @@ -0,0 +1,29 @@ +// expt_pos(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" + +const cl_RA expt_pos (const cl_RA& x, uintL y) +{ + // Methode: + // x Integer -> klar + // x Ratio a/b -> x^y = (a^y)/(b^y), gekürzt, mit b^y>=b>1. + if (integerp(x)) { + DeclareType(cl_I,x); + return expt_pos(x,y); + } else { + DeclareType(cl_RT,x); + var const cl_I& a = numerator(x); + var const cl_I& b = denominator(x); + return I_I_to_RT(expt_pos(a,y),expt_pos(b,y)); + } +} diff --git a/src/rational/misc/cl_RA_exptpos_I.cc b/src/rational/misc/cl_RA_exptpos_I.cc new file mode 100644 index 0000000..2f048b8 --- /dev/null +++ b/src/rational/misc/cl_RA_exptpos_I.cc @@ -0,0 +1,29 @@ +// expt_pos(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_integer.h" + +const cl_RA expt_pos (const cl_RA& x, const cl_I& y) +{ + // Methode: + // x Integer -> klar + // x Ratio a/b -> x^y = (a^y)/(b^y), gekürzt, mit b^y>=b>1. + if (integerp(x)) { + DeclareType(cl_I,x); + return expt_pos(x,y); + } else { + DeclareType(cl_RT,x); + var const cl_I& a = numerator(x); + var const cl_I& b = denominator(x); + return I_I_to_RT(expt_pos(a,y),expt_pos(b,y)); + } +} diff --git a/src/rational/misc/cl_RA_max.cc b/src/rational/misc/cl_RA_max.cc new file mode 100644 index 0000000..a1050f9 --- /dev/null +++ b/src/rational/misc/cl_RA_max.cc @@ -0,0 +1,15 @@ +// max(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +const cl_RA max (const cl_RA& x, const cl_RA& y) +{ + return (x >= y ? x : y); +} diff --git a/src/rational/misc/cl_RA_min.cc b/src/rational/misc/cl_RA_min.cc new file mode 100644 index 0000000..9fead91 --- /dev/null +++ b/src/rational/misc/cl_RA_min.cc @@ -0,0 +1,15 @@ +// min(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +const cl_RA min (const cl_RA& x, const cl_RA& y) +{ + return (x <= y ? x : y); +} diff --git a/src/rational/misc/cl_RA_signum.cc b/src/rational/misc/cl_RA_signum.cc new file mode 100644 index 0000000..1a0ae86 --- /dev/null +++ b/src/rational/misc/cl_RA_signum.cc @@ -0,0 +1,21 @@ +// signum(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_RA.h" +#include "cl_I.h" + +MAYBE_INLINE +const cl_RA signum (const cl_RA& x) +{ + if (minusp(x)) { return -1; } // x<0 -> -1 + elif (zerop(x)) { return 0; } // x=0 -> 0 + else { return 1; } // x>0 -> +1 +} diff --git a/src/rational/output/Makeflags b/src/rational/output/Makeflags new file mode 100644 index 0000000..6ed2160 --- /dev/null +++ b/src/rational/output/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/rational/Makeflags +SUBDIR_INCLUDES += diff --git a/src/rational/output/cl_RA_aprint.cc b/src/rational/output/cl_RA_aprint.cc new file mode 100644 index 0000000..2b4ae3c --- /dev/null +++ b/src/rational/output/cl_RA_aprint.cc @@ -0,0 +1,17 @@ +// print_rational(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational_io.h" + + +// Implementation. + +#include "cl_output.h" + +void print_rational (cl_ostream stream, const cl_print_flags& flags, const cl_RA& z) +{ + print_rational(stream,(const cl_print_number_flags&)flags,z); +} diff --git a/src/rational/output/cl_RA_bprint.cc b/src/rational/output/cl_RA_bprint.cc new file mode 100644 index 0000000..c735a6f --- /dev/null +++ b/src/rational/output/cl_RA_bprint.cc @@ -0,0 +1,17 @@ +// print_rational(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational_io.h" + + +// Implementation. + +#include "cl_output.h" + +void print_rational (cl_ostream stream, const cl_print_number_flags& flags, const cl_RA& z) +{ + print_rational(stream,(const cl_print_real_flags&)flags,z); +} diff --git a/src/rational/output/cl_RA_cprint.cc b/src/rational/output/cl_RA_cprint.cc new file mode 100644 index 0000000..4c56b64 --- /dev/null +++ b/src/rational/output/cl_RA_cprint.cc @@ -0,0 +1,17 @@ +// print_rational(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational_io.h" + + +// Implementation. + +#include "cl_output.h" + +void print_rational (cl_ostream stream, const cl_print_real_flags& flags, const cl_RA& z) +{ + print_rational(stream,(const cl_print_rational_flags&)flags,z); +} diff --git a/src/rational/output/cl_RA_dprint.cc b/src/rational/output/cl_RA_dprint.cc new file mode 100644 index 0000000..49a2037 --- /dev/null +++ b/src/rational/output/cl_RA_dprint.cc @@ -0,0 +1,62 @@ +// print_rational(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational_io.h" + + +// Implementation. + +#include "cl_output.h" +#include "cl_integer_io.h" +#include "cl_rational.h" +#include "cl_RA.h" + +void print_rational (cl_ostream stream, const cl_print_rational_flags& flags, const cl_RA& z) +{ + var unsigned int base = flags.rational_base; + if (flags.rational_readably) + // Radix-Specifier ausgeben: + switch (base) { + case 2: + fprintchar(stream,'#'); + fprintchar(stream,'b'); + break; + case 8: + fprintchar(stream,'#'); + fprintchar(stream,'o'); + break; + case 16: + fprintchar(stream,'#'); + fprintchar(stream,'x'); + break; + case 10: + if (integerp(z)) { + DeclareType(cl_I,z); + // Basis 10 bei Integers durch + // nachgestellten Punkt kennzeichnen: + print_integer(stream,base,z); + fprintchar(stream,'.'); + return; + } + default: + // Basis in #nR-Schreibweise ausgeben: + fprintchar(stream,'#'); + print_integer(stream,10,base); + fprintchar(stream,'r'); + break; + } + if (integerp(z)) { + DeclareType(cl_I,z); + // Integer in Basis base ausgeben: + print_integer(stream,base,z); + } else { + DeclareType(cl_RT,z); + // Ratio in Basis base ausgeben; Zähler / Nenner + print_integer(stream,base,numerator(z)); + fprintchar(stream,'/'); + print_integer(stream,base,denominator(z)); + } +} diff --git a/src/rational/output/cl_RA_print.cc b/src/rational/output/cl_RA_print.cc new file mode 100644 index 0000000..cc55872 --- /dev/null +++ b/src/rational/output/cl_RA_print.cc @@ -0,0 +1,30 @@ +// print_rational(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational_io.h" + + +// Implementation. + +#include "cl_integer_io.h" +#include "cl_rational.h" +#include "cl_RA.h" + +void print_rational (cl_ostream stream, unsigned int base, const cl_RA& z) +{ + if (integerp(z)) { + DeclareType(cl_I,z); + print_integer(stream,base,z); + } else { + DeclareType(cl_RT,z); + var const cl_I& num = numerator(z); + var const cl_I& den = denominator(z); + // Der Zähler trägt das Vorzeichen. + print_integer(stream,base,num); // Zähler ausgeben + fprintchar(stream,'/'); + print_integer(stream,base,den); // Nenner ausgeben + } +} diff --git a/src/rational/ring/Makeflags b/src/rational/ring/Makeflags new file mode 100644 index 0000000..6ed2160 --- /dev/null +++ b/src/rational/ring/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/rational/Makeflags +SUBDIR_INCLUDES += diff --git a/src/rational/ring/cl_RA_ring.cc b/src/rational/ring/cl_RA_ring.cc new file mode 100644 index 0000000..f5f25fc --- /dev/null +++ b/src/rational/ring/cl_RA_ring.cc @@ -0,0 +1,156 @@ +// Ring of rational numbers. + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_RA_ring) + +// Specification. +#include "cl_rational_ring.h" + + +// Implementation. + +#include "cl_rational.h" +#include "cl_rational_io.h" +#include "cl_RA.h" + +static void RA_fprint (cl_heap_ring* R, cl_ostream stream, const _cl_ring_element& x) +{ + unused R; + fprint(stream,The(cl_RA)(x)); +} + +static cl_boolean RA_equal (cl_heap_ring* R, const _cl_ring_element& x, const _cl_ring_element& y) +{ + unused R; + return cl_equal(The(cl_RA)(x),The(cl_RA)(y)); +} + +static const _cl_ring_element RA_zero (cl_heap_ring* R) +{ + return _cl_ring_element(R, (cl_RA)0); +} + +static cl_boolean RA_zerop (cl_heap_ring* R, const _cl_ring_element& x) +{ + unused R; + return zerop(The(cl_RA)(x)); +} + +static const _cl_ring_element RA_plus (cl_heap_ring* R, const _cl_ring_element& x, const _cl_ring_element& y) +{ + return _cl_ring_element(R, The(cl_RA)(x) + The(cl_RA)(y)); +} + +static const _cl_ring_element RA_minus (cl_heap_ring* R, const _cl_ring_element& x, const _cl_ring_element& y) +{ + return _cl_ring_element(R, The(cl_RA)(x) - The(cl_RA)(y)); +} + +static const _cl_ring_element RA_uminus (cl_heap_ring* R, const _cl_ring_element& x) +{ + return _cl_ring_element(R, - The(cl_RA)(x)); +} + +static const _cl_ring_element RA_one (cl_heap_ring* R) +{ + return _cl_ring_element(R, (cl_RA)1); +} + +static const _cl_ring_element RA_canonhom (cl_heap_ring* R, const cl_I& x) +{ + return _cl_ring_element(R, (cl_RA)x); +} + +static const _cl_ring_element RA_mul (cl_heap_ring* R, const _cl_ring_element& x, const _cl_ring_element& y) +{ + return _cl_ring_element(R, The(cl_RA)(x) * The(cl_RA)(y)); +} + +static const _cl_ring_element RA_square (cl_heap_ring* R, const _cl_ring_element& x) +{ + return _cl_ring_element(R, square(The(cl_RA)(x))); +} + +static const _cl_ring_element RA_expt_pos (cl_heap_ring* R, const _cl_ring_element& x, const cl_I& y) +{ + return _cl_ring_element(R, expt_pos(The(cl_RA)(x),y)); +} + +static cl_boolean cl_RA_p (const cl_number& x) +{ + return (cl_boolean) + (!x.pointer_p() + ? x.nonpointer_tag() == cl_FN_tag + : (x.pointer_type()->flags & cl_class_flags_subclass_rational) != 0 + ); +} + +static cl_ring_setops RA_setops = { + RA_fprint, + RA_equal +}; +static cl_ring_addops RA_addops = { + RA_zero, + RA_zerop, + RA_plus, + RA_minus, + RA_uminus +}; +static cl_ring_mulops RA_mulops = { + RA_one, + RA_canonhom, + RA_mul, + RA_square, + RA_expt_pos +}; + +static cl_number_ring_ops RA_ops = { + cl_RA_p, + cl_equal, + zerop, + operator+, + operator-, + operator-, + operator*, + square, + expt_pos +}; + +class cl_heap_rational_ring : public cl_heap_number_ring { + SUBCLASS_cl_heap_ring() +public: + // Constructor. + cl_heap_rational_ring () + : cl_heap_number_ring (&RA_setops,&RA_addops,&RA_mulops, + (cl_number_ring_ops*) &RA_ops) + { type = &cl_class_rational_ring; } + // Destructor. + ~cl_heap_rational_ring () {} +}; + +static void cl_rational_ring_destructor (cl_heap* pointer) +{ + (*(cl_heap_rational_ring*)pointer).~cl_heap_rational_ring(); +} + +static void cl_rational_ring_dprint (cl_heap* pointer) +{ + unused pointer; + fprint(cl_debugout, "(cl_rational_ring) cl_RA_ring"); +} + +cl_class cl_class_rational_ring = { + cl_rational_ring_destructor, + cl_class_flags_number_ring, + cl_rational_ring_dprint +}; + +// Constructor. +inline cl_rational_ring::cl_specialized_number_ring () + : cl_number_ring (new cl_heap_rational_ring()) {} + +const cl_rational_ring cl_RA_ring; + +CL_PROVIDE_END(cl_RA_ring) diff --git a/src/rational/transcendental/Makeflags b/src/rational/transcendental/Makeflags new file mode 100644 index 0000000..6ed2160 --- /dev/null +++ b/src/rational/transcendental/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/rational/Makeflags +SUBDIR_INCLUDES += diff --git a/src/rational/transcendental/cl_I_logp.cc b/src/rational/transcendental/cl_I_logp.cc new file mode 100644 index 0000000..6b0279e --- /dev/null +++ b/src/rational/transcendental/cl_I_logp.cc @@ -0,0 +1,70 @@ +// logp(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_RA.h" +#include "cl_xmacros.h" + +cl_boolean logp (const cl_I& a, const cl_I& b, cl_RA* l) +{ +// Methode: +// log(a,b) soll Bruch c/d mit teilerfremdem c>=0,d>0 ergeben. +// a=1 -> c=0, d=1. +// a>=b -> Dividiere a durch b. Rest da -> geht nicht. +// Sonst log(a,b) = 1+log(a/b,b). +// Berechne also c/d := log(a/b,b) und setze c:=c+d. +// 1 log(a,b) = 1/log(b,a). +// Berechne also c/d := log(b,a) und vertausche c und d. +// Man konstruiert hierbei eigentlich die Kettenbruchentwicklung von c/d. +// Wegen a>=2^c, b>=2^d sind c,d < (integer-length a,b) < intDsize*2^intCsize. +// In Matrizenschreibweise: +// Wenn eine Folge von Divisionsschritten D und Vertauschungsschritten V +// ausgeführt werden muß, z.B. (a,b) V D D = (1,*), so ist +// ( c ) ( 0 ) ( 1 1 ) ( 0 1 ) +// ( d ) = V D D ( 1 ) wobei D = ( 0 1 ) und V = ( 1 0 ). +// Man baut diese Matrizen nun von links nach rechts auf, zum Schluß von +// ( 0 ) +// rechts mit ( 1 ) multiplizieren. +// Entrekursiviert: +// Wir werden (a,b) und damit auch c/d = log(a/b) verändern. +// Invariante: Statt (c,d) wollen wir (uc*c+ud*d,vc*c+vd*d) zurückliefern. +// ( uc ud ) +// D.h. die bisherige Matrix von links ist ( vc vd ). +// uc:=1, ud:=0, vc:=0, vd:=1. +// Solange a>1, +// a>=b -> Dividiere a durch b. Rest da -> geht nicht. +// Sonst a:=a/b, und (für später c:=c+d) ud:=uc+ud, vd:=vc+vd. +// 1 vertausche a und b, uc und ud, vc und vd. +// Liefere (ud,vd), der Bruch ud/vd ist gekürzt. + { Mutable(cl_I,a); + Mutable(cl_I,b); + var uintL uc = 1; + var uintL ud = 0; + var uintL vc = 0; + var uintL vd = 1; + loop { + if (eq(a,1)) // a=1 -> Rekursion zu Ende + break; + if (a >= b) { + var cl_I_div_t div = cl_divide(a,b); // a durch b dividieren + if (!eq(div.remainder,0)) // Rest /=0 ? + return cl_false; // -> fertig + a = div.quotient; // a := a/b + ud = uc + ud; vd = vc + vd; + } else { + // 1 a und b vertauschen + swap(cl_I, a, b); + swap(uintL, uc, ud); swap(uintL, vc, vd); + } + } + // a=1 -> c=0,d=1 -> Ergebnis ud/vd + *l = I_I_to_RA(UL_to_I(ud),UL_to_I(vd)); return cl_true; +}} diff --git a/src/rational/transcendental/cl_RA_logp.cc b/src/rational/transcendental/cl_RA_logp.cc new file mode 100644 index 0000000..4c7bf34 --- /dev/null +++ b/src/rational/transcendental/cl_RA_logp.cc @@ -0,0 +1,103 @@ +// logp(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_rational.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_RA.h" + +cl_boolean logp (const cl_RA& a, const cl_RA& b, cl_RA* pl) +{ +// Methode: +// a=1 -> Ergebnis 0 +// b Integer: +// a Integer: log(a,b) rational errechenbar -> liefern +// a Ratio: a=a1/a2 mit a1>0, a2>1. +// a1=1 und log(a2,b) rational errechenbar -> -log(a2,b) liefern +// b Ratio: a=a1/a2, b=b1/b2 mit a1>0, a2>0, b1>0, b2>1. +// log(a2,b2) rational errechenbar -> +// b1=1 -> bei a1=1 liefern, sonst nicht. +// b1>1 -> log(a1,b1) rational errechenbar und +// log(a1,b1)=log(a2,b2) -> liefern, sonst nicht. +// sonst a1,a2 vertauschen: +// log(a2/a1,b1/b2) versuchen (wie oben) -> +// -log(a2/a1,b1/b2) liefern + + if (eq(a,1)) { // a=1 -> Ergebnis 0 + *pl = 0; return cl_true; + } + if (integerp(b)) { + // b Integer + DeclareType(cl_I,b); + if (integerp(a)) { + // a,b beide Integers + DeclareType(cl_I,a); + return logp(a,b,pl); + } else { + // a Ratio, b Integer + DeclareType(cl_RT,a); + var const cl_I& a1 = numerator(a); + var const cl_I& a2 = denominator(a); + if (!eq(a1,1)) + return cl_false; + // a1=1 + var cl_RA l; + if (logp(a2,b,pl)) { + *pl = -l; return cl_true; + } else + return cl_false; + } + } else { + // a rational, b Ratio + DeclareType(cl_RT,b); + var cl_I a1; + var cl_I a2; + RA_numden_I_I(a, a1 =, a2 =); + var const cl_I& b1 = numerator(b); + var const cl_I& b2 = denominator(b); + { + var cl_RA l2; + // rationalen log(a2,b2) versuchen + if (logp(a2,b2,&l2)) { + if (eq(b1,1)) { + if (eq(a1,1)) + { *pl = l2; return cl_true; } + else + return cl_false; + } else { + var cl_RA l1; + // rationalen log(a1,b1) versuchen + if (logp(a1,b1,&l1)) + if (l1 == l2) + { *pl = l2; return cl_true; } + return cl_false; + } + } + } + { + var cl_RA l2; + // rationalen log(a1,b2) versuchen + if (logp(a1,b2,&l2)) { + if (eq(b1,1)) { + if (eq(a2,1)) + { *pl = -l2; return cl_true; } + else + return cl_false; + } else { + var cl_RA l1; + // rationalen log(a2,b1) versuchen + if (logp(a2,b1,&l1)) + if (l1 == l2) + { *pl = -l2; return cl_true; } + } + } + } + return cl_false; + } +} diff --git a/src/real/Makeflags b/src/real/Makeflags new file mode 100644 index 0000000..7658c93 --- /dev/null +++ b/src/real/Makeflags @@ -0,0 +1,3 @@ +# This file contains additional flags for the main Makefile. + +SUBDIR_INCLUDES = -I$(srcdir)/real -I$(srcdir)/float/sfloat -I$(srcdir)/float/ffloat -I$(srcdir)/float/dfloat -I$(srcdir)/float/lfloat -I$(srcdir)/float -I$(srcdir)/rational -I$(srcdir)/integer -I$(srcdir)/base/digitseq -I$(srcdir)/base/digit -Ibase -I$(srcdir)/base $(GMP_INCLUDES) diff --git a/src/real/algebraic/Makeflags b/src/real/algebraic/Makeflags new file mode 100644 index 0000000..635f2c3 --- /dev/null +++ b/src/real/algebraic/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/real/Makeflags +SUBDIR_INCLUDES += diff --git a/src/real/algebraic/cl_RA_sqrt.cc b/src/real/algebraic/cl_RA_sqrt.cc new file mode 100644 index 0000000..93fffd5 --- /dev/null +++ b/src/real/algebraic/cl_RA_sqrt.cc @@ -0,0 +1,24 @@ +// sqrt(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_rational.h" +#include "cl_float.h" + +MAYBE_INLINE +const cl_R sqrt (const cl_RA& x) +{ + var cl_RA w; + if (sqrtp(x,&w)) // auf Quadrat testen + return w; // war Quadrat, w ist die Wurzel + else + // x in Float umwandeln, dann die Wurzel ziehen: + return sqrt(cl_float(x)); +} diff --git a/src/real/algebraic/cl_R_sqrt.cc b/src/real/algebraic/cl_R_sqrt.cc new file mode 100644 index 0000000..e5bf39c --- /dev/null +++ b/src/real/algebraic/cl_R_sqrt.cc @@ -0,0 +1,21 @@ +// sqrt(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_float.h" +#include "cl_rational.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_RA_sqrt.cc" + +const cl_R sqrt (const cl_R& x) +GEN_R_OP1_2(x, sqrt, return) diff --git a/src/real/cl_R.h b/src/real/cl_R.h new file mode 100644 index 0000000..7277a9b --- /dev/null +++ b/src/real/cl_R.h @@ -0,0 +1,205 @@ +// cl_R internals + +#ifndef _CL_R_H +#define _CL_R_H + +#include "cl_number.h" +#include "cl_real.h" + +extern cl_class cl_class_bignum; +extern cl_class cl_class_ratio; +extern cl_class cl_class_ffloat; +extern cl_class cl_class_dfloat; +extern cl_class cl_class_lfloat; + +// Type tests. +inline cl_boolean rationalp (const cl_R& x) +{ + if (!x.pointer_p()) { + if (x.nonpointer_tag() == cl_FN_tag) + return cl_true; + } else { + if (x.pointer_type()->flags & cl_class_flags_subclass_rational) + return cl_true; + } + return cl_false; +} +inline cl_boolean integerp (const cl_R& x) +{ + if (!x.pointer_p()) { + if (x.nonpointer_tag() == cl_FN_tag) + return cl_true; + } else { + if (x.pointer_type() == &cl_class_bignum) + return cl_true; + } + return cl_false; +} +inline cl_boolean floatp (const cl_R& x) +{ + if (!x.pointer_p()) { + switch (x.nonpointer_tag()) { + case cl_SF_tag: + #if defined(CL_WIDE_POINTERS) + case cl_FF_tag: + #endif + return cl_true; + } + } else { + if (x.pointer_type()->flags & cl_class_flags_subclass_float) + return cl_true; + } + return cl_false; +} + +// Comparison with a fixnum. +inline cl_boolean eq (const cl_R& x, sint32 y) +{ + return (cl_boolean)(x.word == cl_combine(cl_FN_tag,y)); +} + +inline cl_boolean exact_zerop (const cl_R& x) +{ + return eq(x,0); +} + + +// Macro: verteilt je nach Real-Typ eines Floats x auf 2 Statements, +// die x vom jeweiligen Real-Typ benutzen dürfen. +// realcase2(x, RA_statement,F_statement); +// x sollte eine Variable sein. + #define realcase2(x, RA_statement,F_statement) \ + if (rationalp(x)) \ + { var cl_RA& __tmp = *(cl_RA*)&x; var cl_RA& x = __tmp; RA_statement } \ + else \ + { var cl_F& __tmp = *(cl_F*)&x; var cl_F& x = __tmp; F_statement } + +// Macro: verteilt je nach Real-Typ eines Floats x auf 7 Statements. +// realtypecase(x, FN_statement,BN_statement,RT_statement,SF_statement,FF_statement,DF_statement,LF_statement); +// x sollte eine Variable sein. +#ifdef CL_WIDE_POINTERS + #define realtypecase(x, FN_statement,BN_statement,RT_statement,SF_statement,FF_statement,DF_statement,LF_statement) \ + if (!(x).pointer_p()) \ + switch ((x).nonpointer_tag()) \ + { case cl_FN_tag: { FN_statement } break; \ + case cl_SF_tag: { SF_statement } break; \ + case cl_FF_tag: { FF_statement } break; \ + default: NOTREACHED \ + } \ + else { \ + if ((x).pointer_type() == &cl_class_bignum) { BN_statement } \ + else if ((x).pointer_type() == &cl_class_ratio) { RT_statement } \ + else if ((x).pointer_type() == &cl_class_dfloat) { DF_statement } \ + else if ((x).pointer_type() == &cl_class_lfloat) { LF_statement } \ + else NOTREACHED \ + } +#else + #define realtypecase(x, FN_statement,BN_statement,RT_statement,SF_statement,FF_statement,DF_statement,LF_statement) \ + if (!(x).pointer_p()) \ + switch ((x).nonpointer_tag()) \ + { case cl_FN_tag: { FN_statement } break; \ + case cl_SF_tag: { SF_statement } break; \ + default: NOTREACHED \ + } \ + else { \ + if ((x).pointer_type() == &cl_class_bignum) { BN_statement } \ + else if ((x).pointer_type() == &cl_class_ratio) { RT_statement } \ + else if ((x).pointer_type() == &cl_class_ffloat) { FF_statement } \ + else if ((x).pointer_type() == &cl_class_dfloat) { DF_statement } \ + else if ((x).pointer_type() == &cl_class_lfloat) { LF_statement } \ + else NOTREACHED \ + } +#endif + +// Macro: verteilt je nach Real-Typ eines Floats x auf 7 Statements, +// die x vom jeweiligen Real-Typ benutzen dürfen. +// realcase7(x, FN_statement,BN_statement,RT_statement,SF_statement,FF_statement,DF_statement,LF_statement); +// x sollte eine Variable sein. + #define realcase7(x, FN_statement,BN_statement,RT_statement,SF_statement,FF_statement,DF_statement,LF_statement) \ + realtypecase(x \ + , var cl_FN& __tmp = *(cl_FN*)&x; var cl_FN& x = __tmp; FN_statement \ + , var cl_BN& __tmp = *(cl_BN*)&x; var cl_BN& x = __tmp; BN_statement \ + , var cl_RT& __tmp = *(cl_RT*)&x; var cl_RT& x = __tmp; RT_statement \ + , var cl_SF& __tmp = *(cl_SF*)&x; var cl_SF& x = __tmp; SF_statement \ + , var cl_FF& __tmp = *(cl_FF*)&x; var cl_FF& x = __tmp; FF_statement \ + , var cl_DF& __tmp = *(cl_DF*)&x; var cl_DF& x = __tmp; DF_statement \ + , var cl_LF& __tmp = *(cl_LF*)&x; var cl_LF& x = __tmp; LF_statement \ + ) + +// Macro: verteilt je nach Real-Typ eines Floats x auf 6 Statements, +// die x vom jeweiligen Real-Typ benutzen dürfen. +// realcase6(x, I_statement,RT_statement,SF_statement,FF_statement,DF_statement,LF_statement); +// x sollte eine Variable sein. + #define realcase6(x, I_statement,RT_statement,SF_statement,FF_statement,DF_statement,LF_statement) \ + realcase7(x, I_statement,I_statement,RT_statement,SF_statement,FF_statement,DF_statement,LF_statement) + +// contagion(x,y) liefert eine reelle Zahl, die so ungenau ist wie die +// ungenauere der beiden reellen Zahlen x und y. +extern const cl_R contagion (const cl_R& x, const cl_R& y); +// ?? Lieber ein uintL (0, SF_mant_len+1, FF_mant_len+1, DF_mant_len+1, intDsize*len liefern, weniger Kopieraufwand! + +// GEN_R_OP1_2(arg1,R_OP,ergebnis_zuweisung) +// generates the body of a real operation with one argument. +// Distinguish two cases (rational/float) only. +#define GEN_R_OP1_2(arg1,R_OP,ergebnis_zuweisung) \ +{ \ + realcase2(arg1 \ + , ergebnis_zuweisung R_OP(arg1); \ + , ergebnis_zuweisung R_OP(arg1); \ + ); \ +} + +// GEN_R_OP1_7(arg1,R_OP,ergebnis_zuweisung) +// generates the body of a real operation with one argument. +// Full type dispatch, faster than GEN_R_OP1_2. +#define GEN_R_OP1_7(arg1,R_OP,ergebnis_zuweisung) \ +{ \ + realcase7(arg1 \ + , ergebnis_zuweisung R_OP(arg1); \ + , ergebnis_zuweisung R_OP(arg1); \ + , ergebnis_zuweisung R_OP(arg1); \ + , ergebnis_zuweisung R_OP(arg1); \ + , ergebnis_zuweisung R_OP(arg1); \ + , ergebnis_zuweisung R_OP(arg1); \ + , ergebnis_zuweisung R_OP(arg1); \ + ); \ +} + +// GEN_R_OP2_2(arg1,arg2,R_OP,ergebnis_zuweisung) +// generates the body of a real operation with two arguments. +// Distinguish two cases (rational/float) only. +#define GEN_R_OP2_2(arg1,arg2,R_OP,ergebnis_zuweisung) \ +{ \ + realcase2(arg1 \ + , realcase2(arg2 \ + , /* beides rationale Zahlen */ \ + ergebnis_zuweisung R_OP(arg1,arg2); \ + , /* arg1 rational, arg2 Float -> arg1 in Float umwandeln */ \ + ergebnis_zuweisung R_OP(cl_float(arg1,arg2),arg2); \ + ); \ + , realcase2(arg2 \ + , /* arg1 Float, arg2 rational -> arg2 in Float umwandeln */ \ + ergebnis_zuweisung R_OP(arg1,cl_float(arg2,arg1)); \ + , /* beides Floats */ \ + ergebnis_zuweisung R_OP(arg1,arg2); \ + ); \ + ); \ +} + +// cl_somefloat(x,y) wandelt eine reelle Zahl x in ein Float-Format um +// (das von y, falls x rational ist) und rundet dabei nötigenfalls. +// > x: eine reelle Zahl +// > y: ein Float +// < ergebnis: x als Float +inline const cl_F cl_somefloat (const cl_R& x, const cl_F& y) +{ + if (rationalp(x)) { + DeclareType(cl_RA,x); + return cl_float(x,y); + } else { + DeclareType(cl_F,x); + return x; + } +} + +#endif /* _CL_R_H */ diff --git a/src/real/conv/Makeflags b/src/real/conv/Makeflags new file mode 100644 index 0000000..635f2c3 --- /dev/null +++ b/src/real/conv/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/real/Makeflags +SUBDIR_INCLUDES += diff --git a/src/real/conv/cl_F_from_R.cc b/src/real/conv/cl_F_from_R.cc new file mode 100644 index 0000000..5bdeb57 --- /dev/null +++ b/src/real/conv/cl_F_from_R.cc @@ -0,0 +1,42 @@ +// cl_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" + +#if 0 + +const cl_F cl_float (const cl_R& x, const cl_F& y) +{ + if (rationalp(x)) { + DeclareType(cl_RA,x); + return cl_float(x,y); + } else { + DeclareType(cl_F,x); + return cl_float(x,y); + } +} + +#else // less type dispatch overhead + +#include "cl_F.h" +#include "cl_LF.h" + +const cl_F cl_float (const cl_R& x, const cl_F& y) +{ + floattypecase(y + , return cl_R_to_SF(x); + , return cl_R_to_FF(x); + , return cl_R_to_DF(x); + , return cl_R_to_LF(x,TheLfloat(y)->len); + ); +} + +#endif diff --git a/src/real/conv/cl_F_from_R_def.cc b/src/real/conv/cl_F_from_R_def.cc new file mode 100644 index 0000000..eeb0f49 --- /dev/null +++ b/src/real/conv/cl_F_from_R_def.cc @@ -0,0 +1,24 @@ +// cl_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" + +MAYBE_INLINE +const cl_F cl_float (const cl_R& x) +{ + if (rationalp(x)) { + DeclareType(cl_RA,x); + return cl_float(x); + } else { + DeclareType(cl_F,x); + return x; + } +} diff --git a/src/real/conv/cl_F_from_R_f.cc b/src/real/conv/cl_F_from_R_f.cc new file mode 100644 index 0000000..c7d9d68 --- /dev/null +++ b/src/real/conv/cl_F_from_R_f.cc @@ -0,0 +1,24 @@ +// cl_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_float.h" +#include "cl_F.h" + +const cl_F cl_float (const cl_R& x, cl_float_format_t f) +{ + floatformatcase((uintL)f + , return cl_R_to_SF(x); + , return cl_R_to_FF(x); + , return cl_R_to_DF(x); + , return cl_R_to_LF(x,len); + ); +} diff --git a/src/real/conv/cl_R_to_DF.cc b/src/real/conv/cl_R_to_DF.cc new file mode 100644 index 0000000..b645154 --- /dev/null +++ b/src/real/conv/cl_R_to_DF.cc @@ -0,0 +1,46 @@ +// cl_F_to_DF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_F.h" +#include "cl_DF.h" + +#if 0 + +const cl_DF cl_R_to_DF (const cl_R& x) +{ + if (rationalp(x)) { + DeclareType(cl_RA,x); + return cl_RA_to_DF(x); + } else { + DeclareType(cl_F,x); + return cl_F_to_DF(x); + } +} + +#else // fully inlined, faster + +#include "cl_RA.h" +#include "cl_I.h" + +const cl_DF cl_R_to_DF (const cl_R& x) +{ + realcase6(x + , return cl_I_to_DF(x); + , return cl_RA_to_DF(x); + , return cl_SF_to_DF(x); + , return cl_FF_to_DF(x); + , return x; + , return cl_LF_to_DF(x); + ); +} + +#endif diff --git a/src/real/conv/cl_R_to_FF.cc b/src/real/conv/cl_R_to_FF.cc new file mode 100644 index 0000000..5da5479 --- /dev/null +++ b/src/real/conv/cl_R_to_FF.cc @@ -0,0 +1,46 @@ +// cl_R_to_FF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_F.h" +#include "cl_FF.h" + +#if 0 + +const cl_FF cl_R_to_FF (const cl_R& x) +{ + if (rationalp(x)) { + DeclareType(cl_RA,x); + return cl_RA_to_FF(x); + } else { + DeclareType(cl_F,x); + return cl_F_to_FF(x); + } +} + +#else // fully inlined, faster + +#include "cl_RA.h" +#include "cl_I.h" + +const cl_FF cl_R_to_FF (const cl_R& x) +{ + realcase6(x + , return cl_I_to_FF(x); + , return cl_RA_to_FF(x); + , return cl_SF_to_FF(x); + , return x; + , return cl_DF_to_FF(x); + , return cl_LF_to_FF(x); + ); +} + +#endif diff --git a/src/real/conv/cl_R_to_LF.cc b/src/real/conv/cl_R_to_LF.cc new file mode 100644 index 0000000..4c84ce3 --- /dev/null +++ b/src/real/conv/cl_R_to_LF.cc @@ -0,0 +1,46 @@ +// cl_F_to_LF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_F.h" +#include "cl_LF.h" + +#if 0 + +const cl_LF cl_R_to_LF (const cl_R& x, uintC len) +{ + if (rationalp(x)) { + DeclareType(cl_RA,x); + return cl_RA_to_LF(x,len); + } else { + DeclareType(cl_F,x); + return cl_F_to_LF(x,len); + } +} + +#else // fully inlined, faster + +#include "cl_RA.h" +#include "cl_I.h" + +const cl_LF cl_R_to_LF (const cl_R& x, uintC len) +{ + realcase6(x + , return cl_I_to_LF(x,len); + , return cl_RA_to_LF(x,len); + , return cl_SF_to_LF(x,len); + , return cl_FF_to_LF(x,len); + , return cl_DF_to_LF(x,len); + , return LF_to_LF(x,len); + ); +} + +#endif diff --git a/src/real/conv/cl_R_to_SF.cc b/src/real/conv/cl_R_to_SF.cc new file mode 100644 index 0000000..5354534 --- /dev/null +++ b/src/real/conv/cl_R_to_SF.cc @@ -0,0 +1,46 @@ +// cl_R_to_SF(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_F.h" +#include "cl_SF.h" + +#if 0 + +const cl_SF cl_R_to_SF (const cl_R& x) +{ + if (rationalp(x)) { + DeclareType(cl_RA,x); + return cl_RA_to_SF(x); + } else { + DeclareType(cl_F,x); + return cl_F_to_SF(x); + } +} + +#else // fully inlined, faster + +#include "cl_RA.h" +#include "cl_I.h" + +const cl_SF cl_R_to_SF (const cl_R& x) +{ + realcase6(x + , return cl_I_to_SF(x); + , return cl_RA_to_SF(x); + , return x; + , return cl_FF_to_SF(x); + , return cl_DF_to_SF(x); + , return cl_LF_to_SF(x); + ); +} + +#endif diff --git a/src/real/conv/cl_R_to_double.cc b/src/real/conv/cl_R_to_double.cc new file mode 100644 index 0000000..af22927 --- /dev/null +++ b/src/real/conv/cl_R_to_double.cc @@ -0,0 +1,52 @@ +// cl_R_to_double(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_F.h" +#include "cl_integer.h" +#include "cl_rational.h" +#include "cl_float.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" + +#if 0 + +double cl_double_approx (const cl_R& x) +{ + if (rationalp(x)) { + DeclareType(cl_RA,x); + return cl_double_approx(x); + } else { + DeclareType(cl_F,x); + return cl_double_approx(x); + } +} + +#else // fully inlined, faster + +#include "cl_RA.h" +#include "cl_I.h" + +double cl_double_approx (const cl_R& x) +{ + realcase6(x + , return cl_double_approx(x); + , return cl_double_approx(x); + , return cl_double_approx(x); + , return cl_double_approx(x); + , return cl_double_approx(x); + , return cl_double_approx(x); + ); +} + +#endif diff --git a/src/real/conv/cl_R_to_float.cc b/src/real/conv/cl_R_to_float.cc new file mode 100644 index 0000000..8f8498e --- /dev/null +++ b/src/real/conv/cl_R_to_float.cc @@ -0,0 +1,52 @@ +// cl_R_to_float(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_F.h" +#include "cl_integer.h" +#include "cl_rational.h" +#include "cl_float.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" + +#if 0 + +float cl_float_approx (const cl_R& x) +{ + if (rationalp(x)) { + DeclareType(cl_RA,x); + return cl_float_approx(x); + } else { + DeclareType(cl_F,x); + return cl_float_approx(x); + } +} + +#else // fully inlined, faster + +#include "cl_RA.h" +#include "cl_I.h" + +float cl_float_approx (const cl_R& x) +{ + realcase6(x + , return cl_float_approx(x); + , return cl_float_approx(x); + , return cl_float_approx(x); + , return cl_float_approx(x); + , return cl_float_approx(x); + , return cl_float_approx(x); + ); +} + +#endif diff --git a/src/real/division/Makeflags b/src/real/division/Makeflags new file mode 100644 index 0000000..635f2c3 --- /dev/null +++ b/src/real/division/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/real/Makeflags +SUBDIR_INCLUDES += diff --git a/src/real/division/cl_R_ceil1.cc b/src/real/division/cl_R_ceil1.cc new file mode 100644 index 0000000..26fc0b3 --- /dev/null +++ b/src/real/division/cl_R_ceil1.cc @@ -0,0 +1,17 @@ +// ceiling1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_rational.h" +#include "cl_float.h" + +const cl_I ceiling1 (const cl_R& x) +GEN_R_OP1_2(x, ceiling1, return) diff --git a/src/real/division/cl_R_ceil12.cc b/src/real/division/cl_R_ceil12.cc new file mode 100644 index 0000000..48ffdfb --- /dev/null +++ b/src/real/division/cl_R_ceil12.cc @@ -0,0 +1,27 @@ +// ceiling1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_rational.h" + +const cl_I ceiling1 (const cl_R& x, const cl_R& y) +{ +// Methode: +// Beides rationale Zahlen -> ceiling1(x,y). +// Sonst: ceiling1(x/y). + if (rationalp(x)) + if (rationalp(y)) { + DeclareType(cl_RA,x); + DeclareType(cl_RA,y); + return ceiling1(x,y); + } + return ceiling1(x/y); +} diff --git a/src/real/division/cl_R_ceil2.cc b/src/real/division/cl_R_ceil2.cc new file mode 100644 index 0000000..667c181 --- /dev/null +++ b/src/real/division/cl_R_ceil2.cc @@ -0,0 +1,18 @@ +// ceiling2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_rational.h" +#include "cl_float.h" +#include "cl_R_div_t.h" + +const cl_R_div_t ceiling2 (const cl_R& x) +GEN_R_OP1_2(x, ceiling2, return) diff --git a/src/real/division/cl_R_ceil22.cc b/src/real/division/cl_R_ceil22.cc new file mode 100644 index 0000000..e62b195 --- /dev/null +++ b/src/real/division/cl_R_ceil22.cc @@ -0,0 +1,31 @@ +// ceiling2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_rational.h" +#include "cl_R_div_t.h" + +const cl_R_div_t ceiling2 (const cl_R& x, const cl_R& y) +{ +// Methode: +// Beides rationale Zahlen -> ceiling2(x,y). +// Sonst: ceiling2(x/y) -> (q,r). Liefere q und x-y*q=y*r. + if (rationalp(x)) + if (rationalp(y)) { + DeclareType(cl_RA,x); + DeclareType(cl_RA,y); + return ceiling2(x,y); + } + var cl_R_div_t q_r = ceiling2(x/y); + var cl_I& q = q_r.quotient; + var cl_R& r = q_r.remainder; + return cl_R_div_t(q,y*r); +} diff --git a/src/real/division/cl_R_div_t.h b/src/real/division/cl_R_div_t.h new file mode 100644 index 0000000..b31125e --- /dev/null +++ b/src/real/division/cl_R_div_t.h @@ -0,0 +1,22 @@ +// cl_R_div_t and cl_R_fdiv_t constructors + +#ifndef _CL_R_DIV_T_H +#define _CL_R_DIV_T_H + +#include "cl_real.h" +#include "cl_RA.h" +#include "cl_float.h" + +inline cl_R_div_t::cl_R_div_t (const cl_I_div_t& result) + : quotient(result.quotient), remainder(result.remainder) {} + +inline cl_R_div_t::cl_R_div_t (const cl_RA_div_t& result) + : quotient(result.quotient), remainder(result.remainder) {} + +inline cl_R_div_t::cl_R_div_t (const cl_F_div_t& result) + : quotient(result.quotient), remainder(result.remainder) {} + +inline cl_R_fdiv_t::cl_R_fdiv_t (const cl_F_fdiv_t& result) + : quotient(result.quotient), remainder(result.remainder) {} + +#endif /* _CL_R_DIV_T_H */ diff --git a/src/real/division/cl_R_fceil1.cc b/src/real/division/cl_R_fceil1.cc new file mode 100644 index 0000000..f4fa263 --- /dev/null +++ b/src/real/division/cl_R_fceil1.cc @@ -0,0 +1,32 @@ +// fceiling(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_RA.h" +#include "cl_integer.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" + +const cl_F fceiling (const cl_R& x) +{ + realcase6(x + , return cl_float(x); + , var const cl_I& a = numerator(x); + var const cl_I& b = denominator(x); + return cl_float(ceiling1(a,b)); + , return fceiling(x); + , return fceiling(x); + , return fceiling(x); + , return fceiling(x); + ); +} diff --git a/src/real/division/cl_R_fceil12.cc b/src/real/division/cl_R_fceil12.cc new file mode 100644 index 0000000..43beb64 --- /dev/null +++ b/src/real/division/cl_R_fceil12.cc @@ -0,0 +1,27 @@ +// fceiling(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" + +const cl_F fceiling (const cl_R& x, const cl_R& y) +{ +// Methode: +// x,y beide rational: ceiling(x,y), Quotienten in Float umwandeln. +// Sonst: fceiling(x/y). + if (rationalp(x)) + if (rationalp(y)) { + // beides rationale Zahlen + DeclareType(cl_RA,x); + DeclareType(cl_RA,y); + return cl_float(ceiling1(x,y)); + } + return fceiling(x/y); +} diff --git a/src/real/division/cl_R_fceil2.cc b/src/real/division/cl_R_fceil2.cc new file mode 100644 index 0000000..9ec4a68 --- /dev/null +++ b/src/real/division/cl_R_fceil2.cc @@ -0,0 +1,62 @@ +// fceiling2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_R_div_t.h" + +#if 0 // 2 type dispatches + +#include "cl_rational.h" +#include "cl_float.h" +#include "cl_R_div_t.h" + +const cl_R_fdiv_t fceiling2 (const cl_R& x) +{ + if (rationalp(x)) { + DeclareType(cl_RA,x); + var cl_RA_div_t q_r = ceiling2(x); + var cl_I& q = q_r.quotient; + var cl_RA& r = q_r.remainder; + return cl_R_fdiv_t(cl_float(q),r); + } else { + DeclareType(cl_F,x); + return fceiling2(x); + } +} + +#else // 1 type dispatch + +#include "cl_RA.h" +#include "cl_integer.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" +#include "cl_LF.h" + +const cl_R_fdiv_t fceiling2 (const cl_R& x) +{ + realcase6(x + , return cl_R_fdiv_t(cl_float(x),0); + , var const cl_I& a = numerator(x); + var const cl_I& b = denominator(x); + var cl_I_div_t q_r = ceiling2(a,b); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + return cl_R_fdiv_t(cl_float(q),I_I_to_RT(r,b)); + , var cl_SF q = fceiling(x); return cl_R_fdiv_t(q,x-q); + , var cl_FF q = fceiling(x); return cl_R_fdiv_t(q,x-q); + , var cl_DF q = fceiling(x); return cl_R_fdiv_t(q,x-q); + , var cl_LF q = fceiling(x); return cl_R_fdiv_t(q,LF_LF_minus_LF(x,q)); + ); +} + +#endif diff --git a/src/real/division/cl_R_fceil22.cc b/src/real/division/cl_R_fceil22.cc new file mode 100644 index 0000000..0e9f53d --- /dev/null +++ b/src/real/division/cl_R_fceil22.cc @@ -0,0 +1,34 @@ +// fceiling2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_R_div_t.h" + +const cl_R_fdiv_t fceiling2 (const cl_R& x, const cl_R& y) +{ +// Methode: +// x,y beide rational: ceiling(x,y), Quotienten in Float umwandeln. +// Sonst: fceiling(x/y) -> q,r. Liefere die Werte q und x-y*q = y*r. + if (rationalp(x)) + if (rationalp(y)) { + // beides rationale Zahlen + DeclareType(cl_RA,x); + DeclareType(cl_RA,y); + var cl_R_div_t q_r = ceiling2(x,y); + var cl_I& q = q_r.quotient; + var cl_R& r = q_r.remainder; + return cl_R_fdiv_t(cl_float(q),r); + } + var cl_R_fdiv_t q_r = fceiling2(x/y); + var cl_F& q = q_r.quotient; + var cl_R& r = q_r.remainder; + return cl_R_fdiv_t(q,y*r); +} diff --git a/src/real/division/cl_R_ffloor1.cc b/src/real/division/cl_R_ffloor1.cc new file mode 100644 index 0000000..fec326b --- /dev/null +++ b/src/real/division/cl_R_ffloor1.cc @@ -0,0 +1,32 @@ +// ffloor(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_RA.h" +#include "cl_integer.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" + +const cl_F ffloor (const cl_R& x) +{ + realcase6(x + , return cl_float(x); + , var const cl_I& a = numerator(x); + var const cl_I& b = denominator(x); + return cl_float(floor1(a,b)); + , return ffloor(x); + , return ffloor(x); + , return ffloor(x); + , return ffloor(x); + ); +} diff --git a/src/real/division/cl_R_ffloor12.cc b/src/real/division/cl_R_ffloor12.cc new file mode 100644 index 0000000..83ede63 --- /dev/null +++ b/src/real/division/cl_R_ffloor12.cc @@ -0,0 +1,27 @@ +// ffloor(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" + +const cl_F ffloor (const cl_R& x, const cl_R& y) +{ +// Methode: +// x,y beide rational: floor(x,y), Quotienten in Float umwandeln. +// Sonst: ffloor(x/y). + if (rationalp(x)) + if (rationalp(y)) { + // beides rationale Zahlen + DeclareType(cl_RA,x); + DeclareType(cl_RA,y); + return cl_float(floor1(x,y)); + } + return ffloor(x/y); +} diff --git a/src/real/division/cl_R_ffloor2.cc b/src/real/division/cl_R_ffloor2.cc new file mode 100644 index 0000000..0a735a4 --- /dev/null +++ b/src/real/division/cl_R_ffloor2.cc @@ -0,0 +1,62 @@ +// ffloor2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_R_div_t.h" + +#if 0 // 2 type dispatches + +#include "cl_rational.h" +#include "cl_float.h" +#include "cl_R_div_t.h" + +const cl_R_fdiv_t ffloor2 (const cl_R& x) +{ + if (rationalp(x)) { + DeclareType(cl_RA,x); + var cl_RA_div_t q_r = floor2(x); + var cl_I& q = q_r.quotient; + var cl_RA& r = q_r.remainder; + return cl_R_fdiv_t(cl_float(q),r); + } else { + DeclareType(cl_F,x); + return ffloor2(x); + } +} + +#else // 1 type dispatch + +#include "cl_RA.h" +#include "cl_integer.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" +#include "cl_LF.h" + +const cl_R_fdiv_t ffloor2 (const cl_R& x) +{ + realcase6(x + , return cl_R_fdiv_t(cl_float(x),0); + , var const cl_I& a = numerator(x); + var const cl_I& b = denominator(x); + var cl_I_div_t q_r = floor2(a,b); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + return cl_R_fdiv_t(cl_float(q),I_I_to_RT(r,b)); + , var cl_SF q = ffloor(x); return cl_R_fdiv_t(q,x-q); + , var cl_FF q = ffloor(x); return cl_R_fdiv_t(q,x-q); + , var cl_DF q = ffloor(x); return cl_R_fdiv_t(q,x-q); + , var cl_LF q = ffloor(x); return cl_R_fdiv_t(q,LF_LF_minus_LF(x,q)); + ); +} + +#endif diff --git a/src/real/division/cl_R_ffloor22.cc b/src/real/division/cl_R_ffloor22.cc new file mode 100644 index 0000000..e2f85ac --- /dev/null +++ b/src/real/division/cl_R_ffloor22.cc @@ -0,0 +1,34 @@ +// ffloor2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_R_div_t.h" + +const cl_R_fdiv_t ffloor2 (const cl_R& x, const cl_R& y) +{ +// Methode: +// x,y beide rational: floor(x,y), Quotienten in Float umwandeln. +// Sonst: ffloor(x/y) -> q,r. Liefere die Werte q und x-y*q = y*r. + if (rationalp(x)) + if (rationalp(y)) { + // beides rationale Zahlen + DeclareType(cl_RA,x); + DeclareType(cl_RA,y); + var cl_R_div_t q_r = floor2(x,y); + var cl_I& q = q_r.quotient; + var cl_R& r = q_r.remainder; + return cl_R_fdiv_t(cl_float(q),r); + } + var cl_R_fdiv_t q_r = ffloor2(x/y); + var cl_F& q = q_r.quotient; + var cl_R& r = q_r.remainder; + return cl_R_fdiv_t(q,y*r); +} diff --git a/src/real/division/cl_R_floor1.cc b/src/real/division/cl_R_floor1.cc new file mode 100644 index 0000000..14a70f2 --- /dev/null +++ b/src/real/division/cl_R_floor1.cc @@ -0,0 +1,17 @@ +// floor1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_rational.h" +#include "cl_float.h" + +const cl_I floor1 (const cl_R& x) +GEN_R_OP1_2(x, floor1, return) diff --git a/src/real/division/cl_R_floor12.cc b/src/real/division/cl_R_floor12.cc new file mode 100644 index 0000000..1441e9b --- /dev/null +++ b/src/real/division/cl_R_floor12.cc @@ -0,0 +1,27 @@ +// floor1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_rational.h" + +const cl_I floor1 (const cl_R& x, const cl_R& y) +{ +// Methode: +// Beides rationale Zahlen -> floor1(x,y). +// Sonst: floor1(x/y). + if (rationalp(x)) + if (rationalp(y)) { + DeclareType(cl_RA,x); + DeclareType(cl_RA,y); + return floor1(x,y); + } + return floor1(x/y); +} diff --git a/src/real/division/cl_R_floor2.cc b/src/real/division/cl_R_floor2.cc new file mode 100644 index 0000000..900b889 --- /dev/null +++ b/src/real/division/cl_R_floor2.cc @@ -0,0 +1,18 @@ +// floor2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_rational.h" +#include "cl_float.h" +#include "cl_R_div_t.h" + +const cl_R_div_t floor2 (const cl_R& x) +GEN_R_OP1_2(x, floor2, return) diff --git a/src/real/division/cl_R_floor22.cc b/src/real/division/cl_R_floor22.cc new file mode 100644 index 0000000..1cbb9ca --- /dev/null +++ b/src/real/division/cl_R_floor22.cc @@ -0,0 +1,31 @@ +// floor2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_rational.h" +#include "cl_R_div_t.h" + +const cl_R_div_t floor2 (const cl_R& x, const cl_R& y) +{ +// Methode: +// Beides rationale Zahlen -> floor2(x,y). +// Sonst: floor2(x/y) -> (q,r). Liefere q und x-y*q=y*r. + if (rationalp(x)) + if (rationalp(y)) { + DeclareType(cl_RA,x); + DeclareType(cl_RA,y); + return floor2(x,y); + } + var cl_R_div_t q_r = floor2(x/y); + var cl_I& q = q_r.quotient; + var cl_R& r = q_r.remainder; + return cl_R_div_t(q,y*r); +} diff --git a/src/real/division/cl_R_fround1.cc b/src/real/division/cl_R_fround1.cc new file mode 100644 index 0000000..efc4274 --- /dev/null +++ b/src/real/division/cl_R_fround1.cc @@ -0,0 +1,32 @@ +// fround(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_RA.h" +#include "cl_integer.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" + +const cl_F fround (const cl_R& x) +{ + realcase6(x + , return cl_float(x); + , var const cl_I& a = numerator(x); + var const cl_I& b = denominator(x); + return cl_float(round1(a,b)); + , return fround(x); + , return fround(x); + , return fround(x); + , return fround(x); + ); +} diff --git a/src/real/division/cl_R_fround12.cc b/src/real/division/cl_R_fround12.cc new file mode 100644 index 0000000..6562bad --- /dev/null +++ b/src/real/division/cl_R_fround12.cc @@ -0,0 +1,27 @@ +// fround(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" + +const cl_F fround (const cl_R& x, const cl_R& y) +{ +// Methode: +// x,y beide rational: round(x,y), Quotienten in Float umwandeln. +// Sonst: fround(x/y). + if (rationalp(x)) + if (rationalp(y)) { + // beides rationale Zahlen + DeclareType(cl_RA,x); + DeclareType(cl_RA,y); + return cl_float(round1(x,y)); + } + return fround(x/y); +} diff --git a/src/real/division/cl_R_fround2.cc b/src/real/division/cl_R_fround2.cc new file mode 100644 index 0000000..a256f77 --- /dev/null +++ b/src/real/division/cl_R_fround2.cc @@ -0,0 +1,62 @@ +// fround2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_R_div_t.h" + +#if 0 // 2 type dispatches + +#include "cl_rational.h" +#include "cl_float.h" +#include "cl_R_div_t.h" + +const cl_R_fdiv_t fround2 (const cl_R& x) +{ + if (rationalp(x)) { + DeclareType(cl_RA,x); + var cl_RA_div_t q_r = round2(x); + var cl_I& q = q_r.quotient; + var cl_RA& r = q_r.remainder; + return cl_R_fdiv_t(cl_float(q),r); + } else { + DeclareType(cl_F,x); + return fround2(x); + } +} + +#else // 1 type dispatch + +#include "cl_RA.h" +#include "cl_integer.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" +#include "cl_LF.h" + +const cl_R_fdiv_t fround2 (const cl_R& x) +{ + realcase6(x + , return cl_R_fdiv_t(cl_float(x),0); + , var const cl_I& a = numerator(x); + var const cl_I& b = denominator(x); + var cl_I_div_t q_r = round2(a,b); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + return cl_R_fdiv_t(cl_float(q),I_I_to_RT(r,b)); + , var cl_SF q = fround(x); return cl_R_fdiv_t(q,x-q); + , var cl_FF q = fround(x); return cl_R_fdiv_t(q,x-q); + , var cl_DF q = fround(x); return cl_R_fdiv_t(q,x-q); + , var cl_LF q = fround(x); return cl_R_fdiv_t(q,LF_LF_minus_LF(x,q)); + ); +} + +#endif diff --git a/src/real/division/cl_R_fround22.cc b/src/real/division/cl_R_fround22.cc new file mode 100644 index 0000000..2da3fa4 --- /dev/null +++ b/src/real/division/cl_R_fround22.cc @@ -0,0 +1,34 @@ +// fround2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_R_div_t.h" + +const cl_R_fdiv_t fround2 (const cl_R& x, const cl_R& y) +{ +// Methode: +// x,y beide rational: round(x,y), Quotienten in Float umwandeln. +// Sonst: fround(x/y) -> q,r. Liefere die Werte q und x-y*q = y*r. + if (rationalp(x)) + if (rationalp(y)) { + // beides rationale Zahlen + DeclareType(cl_RA,x); + DeclareType(cl_RA,y); + var cl_R_div_t q_r = round2(x,y); + var cl_I& q = q_r.quotient; + var cl_R& r = q_r.remainder; + return cl_R_fdiv_t(cl_float(q),r); + } + var cl_R_fdiv_t q_r = fround2(x/y); + var cl_F& q = q_r.quotient; + var cl_R& r = q_r.remainder; + return cl_R_fdiv_t(q,y*r); +} diff --git a/src/real/division/cl_R_ftrunc1.cc b/src/real/division/cl_R_ftrunc1.cc new file mode 100644 index 0000000..62550bd --- /dev/null +++ b/src/real/division/cl_R_ftrunc1.cc @@ -0,0 +1,32 @@ +// ftruncate(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_RA.h" +#include "cl_integer.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" + +const cl_F ftruncate (const cl_R& x) +{ + realcase6(x + , return cl_float(x); + , var const cl_I& a = numerator(x); + var const cl_I& b = denominator(x); + return cl_float(truncate1(a,b)); + , return ftruncate(x); + , return ftruncate(x); + , return ftruncate(x); + , return ftruncate(x); + ); +} diff --git a/src/real/division/cl_R_ftrunc12.cc b/src/real/division/cl_R_ftrunc12.cc new file mode 100644 index 0000000..cb80654 --- /dev/null +++ b/src/real/division/cl_R_ftrunc12.cc @@ -0,0 +1,27 @@ +// ftruncate(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" + +const cl_F ftruncate (const cl_R& x, const cl_R& y) +{ +// Methode: +// x,y beide rational: truncate(x,y), Quotienten in Float umwandeln. +// Sonst: ftruncate(x/y). + if (rationalp(x)) + if (rationalp(y)) { + // beides rationale Zahlen + DeclareType(cl_RA,x); + DeclareType(cl_RA,y); + return cl_float(truncate1(x,y)); + } + return ftruncate(x/y); +} diff --git a/src/real/division/cl_R_ftrunc2.cc b/src/real/division/cl_R_ftrunc2.cc new file mode 100644 index 0000000..0101ba2 --- /dev/null +++ b/src/real/division/cl_R_ftrunc2.cc @@ -0,0 +1,62 @@ +// ftruncate2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_R_div_t.h" + +#if 0 // 2 type dispatches + +#include "cl_rational.h" +#include "cl_float.h" +#include "cl_R_div_t.h" + +const cl_R_fdiv_t ftruncate2 (const cl_R& x) +{ + if (rationalp(x)) { + DeclareType(cl_RA,x); + var cl_RA_div_t q_r = truncate2(x); + var cl_I& q = q_r.quotient; + var cl_RA& r = q_r.remainder; + return cl_R_fdiv_t(cl_float(q),r); + } else { + DeclareType(cl_F,x); + return ftruncate2(x); + } +} + +#else // 1 type dispatch + +#include "cl_RA.h" +#include "cl_integer.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" +#include "cl_LF.h" + +const cl_R_fdiv_t ftruncate2 (const cl_R& x) +{ + realcase6(x + , return cl_R_fdiv_t(cl_float(x),0); + , var const cl_I& a = numerator(x); + var const cl_I& b = denominator(x); + var cl_I_div_t q_r = truncate2(a,b); + var cl_I& q = q_r.quotient; + var cl_I& r = q_r.remainder; + return cl_R_fdiv_t(cl_float(q),I_I_to_RT(r,b)); + , var cl_SF q = ftruncate(x); return cl_R_fdiv_t(q,x-q); + , var cl_FF q = ftruncate(x); return cl_R_fdiv_t(q,x-q); + , var cl_DF q = ftruncate(x); return cl_R_fdiv_t(q,x-q); + , var cl_LF q = ftruncate(x); return cl_R_fdiv_t(q,LF_LF_minus_LF(x,q)); + ); +} + +#endif diff --git a/src/real/division/cl_R_ftrunc22.cc b/src/real/division/cl_R_ftrunc22.cc new file mode 100644 index 0000000..8a6def8 --- /dev/null +++ b/src/real/division/cl_R_ftrunc22.cc @@ -0,0 +1,34 @@ +// ftruncate2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_R_div_t.h" + +const cl_R_fdiv_t ftruncate2 (const cl_R& x, const cl_R& y) +{ +// Methode: +// x,y beide rational: truncate(x,y), Quotienten in Float umwandeln. +// Sonst: ftruncate(x/y) -> q,r. Liefere die Werte q und x-y*q = y*r. + if (rationalp(x)) + if (rationalp(y)) { + // beides rationale Zahlen + DeclareType(cl_RA,x); + DeclareType(cl_RA,y); + var cl_R_div_t q_r = truncate2(x,y); + var cl_I& q = q_r.quotient; + var cl_R& r = q_r.remainder; + return cl_R_fdiv_t(cl_float(q),r); + } + var cl_R_fdiv_t q_r = ftruncate2(x/y); + var cl_F& q = q_r.quotient; + var cl_R& r = q_r.remainder; + return cl_R_fdiv_t(q,y*r); +} diff --git a/src/real/division/cl_R_mod.cc b/src/real/division/cl_R_mod.cc new file mode 100644 index 0000000..0ac034b --- /dev/null +++ b/src/real/division/cl_R_mod.cc @@ -0,0 +1,27 @@ +// mod(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_integer.h" + +const cl_R mod (const cl_R& x, const cl_R& y) +{ +// Methode: +// Beides Integers -> mod(x,y). +// Sonst: floor2(x/y) -> (q,r). Liefere x-y*q=y*r. + if (integerp(x)) + if (integerp(y)) { + DeclareType(cl_I,x); + DeclareType(cl_I,y); + return mod(x,y); + } + return y * floor2(x/y).remainder; +} diff --git a/src/real/division/cl_R_rem.cc b/src/real/division/cl_R_rem.cc new file mode 100644 index 0000000..c52031d --- /dev/null +++ b/src/real/division/cl_R_rem.cc @@ -0,0 +1,27 @@ +// rem(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_integer.h" + +const cl_R rem (const cl_R& x, const cl_R& y) +{ +// Methode: +// Beides Integers -> rem(x,y). +// Sonst: truncate2(x/y) -> (q,r). Liefere x-y*q=y*r. + if (integerp(x)) + if (integerp(y)) { + DeclareType(cl_I,x); + DeclareType(cl_I,y); + return rem(x,y); + } + return y * truncate2(x/y).remainder; +} diff --git a/src/real/division/cl_R_round1.cc b/src/real/division/cl_R_round1.cc new file mode 100644 index 0000000..ee0fcc6 --- /dev/null +++ b/src/real/division/cl_R_round1.cc @@ -0,0 +1,17 @@ +// round1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_rational.h" +#include "cl_float.h" + +const cl_I round1 (const cl_R& x) +GEN_R_OP1_2(x, round1, return) diff --git a/src/real/division/cl_R_round12.cc b/src/real/division/cl_R_round12.cc new file mode 100644 index 0000000..71652e3 --- /dev/null +++ b/src/real/division/cl_R_round12.cc @@ -0,0 +1,27 @@ +// round1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_rational.h" + +const cl_I round1 (const cl_R& x, const cl_R& y) +{ +// Methode: +// Beides rationale Zahlen -> round1(x,y). +// Sonst: round1(x/y). + if (rationalp(x)) + if (rationalp(y)) { + DeclareType(cl_RA,x); + DeclareType(cl_RA,y); + return round1(x,y); + } + return round1(x/y); +} diff --git a/src/real/division/cl_R_round2.cc b/src/real/division/cl_R_round2.cc new file mode 100644 index 0000000..21d9430 --- /dev/null +++ b/src/real/division/cl_R_round2.cc @@ -0,0 +1,18 @@ +// round2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_rational.h" +#include "cl_float.h" +#include "cl_R_div_t.h" + +const cl_R_div_t round2 (const cl_R& x) +GEN_R_OP1_2(x, round2, return) diff --git a/src/real/division/cl_R_round22.cc b/src/real/division/cl_R_round22.cc new file mode 100644 index 0000000..189ab0e --- /dev/null +++ b/src/real/division/cl_R_round22.cc @@ -0,0 +1,31 @@ +// round2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_rational.h" +#include "cl_R_div_t.h" + +const cl_R_div_t round2 (const cl_R& x, const cl_R& y) +{ +// Methode: +// Beides rationale Zahlen -> round2(x,y). +// Sonst: round2(x/y) -> (q,r). Liefere q und x-y*q=y*r. + if (rationalp(x)) + if (rationalp(y)) { + DeclareType(cl_RA,x); + DeclareType(cl_RA,y); + return round2(x,y); + } + var cl_R_div_t q_r = round2(x/y); + var cl_I& q = q_r.quotient; + var cl_R& r = q_r.remainder; + return cl_R_div_t(q,y*r); +} diff --git a/src/real/division/cl_R_trunc1.cc b/src/real/division/cl_R_trunc1.cc new file mode 100644 index 0000000..a3177f0 --- /dev/null +++ b/src/real/division/cl_R_trunc1.cc @@ -0,0 +1,17 @@ +// truncate1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_rational.h" +#include "cl_float.h" + +const cl_I truncate1 (const cl_R& x) +GEN_R_OP1_2(x, truncate1, return) diff --git a/src/real/division/cl_R_trunc12.cc b/src/real/division/cl_R_trunc12.cc new file mode 100644 index 0000000..a8d23e6 --- /dev/null +++ b/src/real/division/cl_R_trunc12.cc @@ -0,0 +1,27 @@ +// truncate1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_rational.h" + +const cl_I truncate1 (const cl_R& x, const cl_R& y) +{ +// Methode: +// Beides rationale Zahlen -> truncate1(x,y). +// Sonst: truncate1(x/y). + if (rationalp(x)) + if (rationalp(y)) { + DeclareType(cl_RA,x); + DeclareType(cl_RA,y); + return truncate1(x,y); + } + return truncate1(x/y); +} diff --git a/src/real/division/cl_R_trunc2.cc b/src/real/division/cl_R_trunc2.cc new file mode 100644 index 0000000..f18999a --- /dev/null +++ b/src/real/division/cl_R_trunc2.cc @@ -0,0 +1,18 @@ +// truncate2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_rational.h" +#include "cl_float.h" +#include "cl_R_div_t.h" + +const cl_R_div_t truncate2 (const cl_R& x) +GEN_R_OP1_2(x, truncate2, return) diff --git a/src/real/division/cl_R_trunc22.cc b/src/real/division/cl_R_trunc22.cc new file mode 100644 index 0000000..1b7bdf7 --- /dev/null +++ b/src/real/division/cl_R_trunc22.cc @@ -0,0 +1,31 @@ +// truncate2(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_rational.h" +#include "cl_R_div_t.h" + +const cl_R_div_t truncate2 (const cl_R& x, const cl_R& y) +{ +// Methode: +// Beides rationale Zahlen -> truncate2(x,y). +// Sonst: truncate2(x/y) -> (q,r). Liefere q und x-y*q=y*r. + if (rationalp(x)) + if (rationalp(y)) { + DeclareType(cl_RA,x); + DeclareType(cl_RA,y); + return truncate2(x,y); + } + var cl_R_div_t q_r = truncate2(x/y); + var cl_I& q = q_r.quotient; + var cl_R& r = q_r.remainder; + return cl_R_div_t(q,y*r); +} diff --git a/src/real/elem/Makeflags b/src/real/elem/Makeflags new file mode 100644 index 0000000..75f2dff --- /dev/null +++ b/src/real/elem/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/real/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/float/sfloat/elem -I$(srcdir)/float/ffloat/elem -I$(srcdir)/float/dfloat/elem -I$(srcdir)/float/lfloat/elem diff --git a/src/real/elem/cl_R_compare.cc b/src/real/elem/cl_R_compare.cc new file mode 100644 index 0000000..771f144 --- /dev/null +++ b/src/real/elem/cl_R_compare.cc @@ -0,0 +1,44 @@ +// cl_compare(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_rational.h" +#include "cl_float.h" + +cl_signean cl_compare (const cl_R& x, const cl_R& y) +{ + // Methode: + // Beide rational oder beide Floats -> klar. + // Eine rational, eine Float -> + // Die rationale Zahl zum Float machen, vergleichen. + // Verschieden -> Das war's. + // Gleich -> Das Float mit RATIONAL rational machen, nochmals vergleichen. + realcase2(x + , realcase2(y + , // beides rationale Zahlen + return cl_compare(x,y); + , // x rational, y Float -> x in Float umwandeln + var cl_signean result = cl_compare(cl_float(x,y),y); + if (result != signean_null) + return result; + return cl_compare(x,rational(y)); + ); + , realcase2(y + , // x Float, y rational -> y in Float umwandeln + var cl_signean result = cl_compare(x,cl_float(y,x)); + if (result != signean_null) + return result; + return cl_compare(rational(x),y); + , // beides Floats + return cl_compare(x,y); + ); + ); +} diff --git a/src/real/elem/cl_R_div.cc b/src/real/elem/cl_R_div.cc new file mode 100644 index 0000000..df389e0 --- /dev/null +++ b/src/real/elem/cl_R_div.cc @@ -0,0 +1,97 @@ +// binary operator / + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_rational.h" +#include "cl_RA.h" +#include "cl_integer.h" +#include "cl_I.h" +#include "cl_F.h" +#include "cl_sfloat.h" +#include "cl_SF.h" +#include "cl_ffloat.h" +#include "cl_FF.h" +#include "cl_dfloat.h" +#include "cl_DF.h" +#include "cl_lfloat.h" +#include "cl_LF.h" +#include "cl_N.h" + +ALL_cl_LF_OPERATIONS_SAME_PRECISION() + +const cl_R operator/ (const cl_R& x, const cl_R& y) +{ + if (eq(x,0)) + // 0 / y = exakte 0, außer wenn y=0 + { if (zerop(y)) + { cl_error_division_by_0(); } + else + return 0; + } + else +#define div(a,b) a/b + realcase6(x + , /* I */ + realcase6(y + , /* I */ return div(x,y); + , /* RT */ return div(x,y); + , /* SF */ return div(cl_I_to_SF(x),y); + , /* FF */ return div(cl_I_to_FF(x),y); + , /* DF */ return div(cl_I_to_DF(x),y); + , /* LF */ return div(cl_I_to_LF(x,LFlen0(y)),y); // cf. cl_I_LF_div + ); + , /* RT */ + realcase6(y + , /* I */ return div(x,y); + , /* RT */ return div(x,y); + , /* SF */ return div(cl_RA_to_SF(x),y); + , /* FF */ return div(cl_RA_to_FF(x),y); + , /* DF */ return div(cl_RA_to_DF(x),y); + , /* LF */ return cl_RA_LF_div(x,y); + ); + , /* SF */ + realcase6(y + , /* I */ return div(x,cl_I_to_SF(y)); + , /* RT */ return div(x,cl_RA_to_SF(y)); + , /* SF */ return div(x,y); + , /* FF */ return cl_FF_to_SF(div(cl_SF_to_FF(x),y)); + , /* DF */ return cl_DF_to_SF(div(cl_SF_to_DF(x),y)); + , /* LF */ return cl_LF_to_SF(div(cl_SF_to_LF(x,LFlen0(y)),y)); + ); + , /* FF */ + realcase6(y + , /* I */ return div(x,cl_I_to_FF(y)); + , /* RT */ return div(x,cl_RA_to_FF(y)); + , /* SF */ return cl_FF_to_SF(div(x,cl_SF_to_FF(y))); + , /* FF */ return div(x,y); + , /* DF */ return cl_DF_to_FF(div(cl_FF_to_DF(x),y)); + , /* LF */ return cl_LF_to_FF(div(cl_FF_to_LF(x,LFlen0(y)),y)); + ); + , /* DF */ + realcase6(y + , /* I */ return div(x,cl_I_to_DF(y)); + , /* RT */ return div(x,cl_RA_to_DF(y)); + , /* SF */ return cl_DF_to_SF(div(x,cl_SF_to_DF(y))); + , /* FF */ return cl_DF_to_FF(div(x,cl_FF_to_DF(y))); + , /* DF */ return div(x,y); + , /* LF */ return cl_LF_to_DF(div(cl_DF_to_LF(x,LFlen0(y)),y)); + ); + , /* LF */ + realcase6(y + , /* I */ return cl_LF_I_div(x,y); + , /* RT */ return cl_LF_RA_div(x,y); + , /* SF */ return cl_LF_to_SF(div(x,cl_SF_to_LF(y,LFlen0(x)))); + , /* FF */ return cl_LF_to_FF(div(x,cl_FF_to_LF(y,LFlen0(x)))); + , /* DF */ return cl_LF_to_DF(div(x,cl_DF_to_LF(y,LFlen0(x)))); + , /* LF */ return div(x,y); + ); + ); +} diff --git a/src/real/elem/cl_R_equal.cc b/src/real/elem/cl_R_equal.cc new file mode 100644 index 0000000..6d6f17e --- /dev/null +++ b/src/real/elem/cl_R_equal.cc @@ -0,0 +1,52 @@ +// cl_equal(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_RA.h" +#include "cl_integer.h" + +inline cl_boolean cl_equal (const cl_F& x, const cl_F& y) +{ + return (cl_boolean) (cl_compare(x,y) == 0); +} + +cl_boolean cl_equal (const cl_R& x, const cl_R& y) +{ +// Methode: +// Beide rational oder beide Floats -> klar. +// Eine rational, eine Float -> +// Die rationale Zahl muß einen Zweierpotenz-Nenner haben, sonst verschieden. +// Die rationale Zahl zum Float machen, vergleichen. +// Verschieden -> Das war's. +// Gleich -> Das Float mit RATIONAL rational machen, nochmals vergleichen. + realcase2(x + , realcase2(y + , // beides rationale Zahlen + return cl_equal(x,y); + , // x rational, y Float -> x in Float umwandeln + if (!power2p(denominator(x))) + return cl_false; + if (!cl_equal(cl_float(x,y),y)) + return cl_false; + return cl_equal(x,rational(y)); + ); + , realcase2(y + , // x Float, y rational -> y in Float umwandeln + if (!power2p(denominator(y))) + return cl_false; + if (!cl_equal(x,cl_float(y,x))) + return cl_false; + return cl_equal(rational(x),y); + , // beides Floats + return cl_equal(x,y); + ); + ); +} diff --git a/src/real/elem/cl_R_minus.cc b/src/real/elem/cl_R_minus.cc new file mode 100644 index 0000000..ee2b105 --- /dev/null +++ b/src/real/elem/cl_R_minus.cc @@ -0,0 +1,23 @@ +// binary operator - + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_rational.h" +#include "cl_float.h" + +const cl_R operator- (const cl_R& x, const cl_R& y) +{ + if (eq(y,0)) { return x; } + elif (eq(x,0)) { return -y; } + else +#define minus(a,b) a-b +GEN_R_OP2_2(x,y, minus, return) +} diff --git a/src/real/elem/cl_R_minus1.cc b/src/real/elem/cl_R_minus1.cc new file mode 100644 index 0000000..5344097 --- /dev/null +++ b/src/real/elem/cl_R_minus1.cc @@ -0,0 +1,17 @@ +// minus1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_rational.h" +#include "cl_float.h" + +const cl_R minus1 (const cl_R& x) +GEN_R_OP1_2(x, minus1, return) diff --git a/src/real/elem/cl_R_minusp.cc b/src/real/elem/cl_R_minusp.cc new file mode 100644 index 0000000..497f89d --- /dev/null +++ b/src/real/elem/cl_R_minusp.cc @@ -0,0 +1,29 @@ +// minusp(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_RA.h" +#include "cl_I.h" +#include "cl_F.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_SF_minusp.cc" +#include "cl_FF_minusp.cc" +#include "cl_DF_minusp.cc" +#include "cl_LF_minusp.cc" + +cl_boolean minusp (const cl_R& x) +#if 0 +GEN_R_OP1_2(x, minusp, return) +#else // fully inlined, faster +GEN_R_OP1_7(x, minusp, return) +#endif diff --git a/src/real/elem/cl_R_mul.cc b/src/real/elem/cl_R_mul.cc new file mode 100644 index 0000000..ed23502 --- /dev/null +++ b/src/real/elem/cl_R_mul.cc @@ -0,0 +1,92 @@ +// binary operator * + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_rational.h" +#include "cl_RA.h" +#include "cl_integer.h" +#include "cl_I.h" +#include "cl_F.h" +#include "cl_sfloat.h" +#include "cl_SF.h" +#include "cl_ffloat.h" +#include "cl_FF.h" +#include "cl_dfloat.h" +#include "cl_DF.h" +#include "cl_lfloat.h" +#include "cl_LF.h" +#include "cl_N.h" + +ALL_cl_LF_OPERATIONS_SAME_PRECISION() + +const cl_R operator* (const cl_R& x, const cl_R& y) +{ + if (eq(x,0)) { return 0; } // 0 * y = exakte 0 + elif (eq(y,0)) { return 0; } // x * 0 = exakte 0 + else +#define mul(a,b) a*b + realcase6(x + , /* I */ + realcase6(y + , /* I */ return mul(x,y); + , /* RT */ return mul(x,y); + , /* SF */ return mul(cl_I_to_SF(x),y); + , /* FF */ return mul(cl_I_to_FF(x),y); + , /* DF */ return mul(cl_I_to_DF(x),y); + , /* LF */ return cl_LF_I_mul(y,x); + ); + , /* RT */ + realcase6(y + , /* I */ return mul(x,y); + , /* RT */ return mul(x,y); + , /* SF */ return mul(cl_RA_to_SF(x),y); + , /* FF */ return mul(cl_RA_to_FF(x),y); + , /* DF */ return mul(cl_RA_to_DF(x),y); + , /* LF */ return cl_LF_RA_mul(y,x); + ); + , /* SF */ + realcase6(y + , /* I */ return mul(x,cl_I_to_SF(y)); + , /* RT */ return mul(x,cl_RA_to_SF(y)); + , /* SF */ return mul(x,y); + , /* FF */ return cl_FF_to_SF(mul(cl_SF_to_FF(x),y)); + , /* DF */ return cl_DF_to_SF(mul(cl_SF_to_DF(x),y)); + , /* LF */ return cl_LF_to_SF(mul(cl_SF_to_LF(x,LFlen0(y)),y)); + ); + , /* FF */ + realcase6(y + , /* I */ return mul(x,cl_I_to_FF(y)); + , /* RT */ return mul(x,cl_RA_to_FF(y)); + , /* SF */ return cl_FF_to_SF(mul(x,cl_SF_to_FF(y))); + , /* FF */ return mul(x,y); + , /* DF */ return cl_DF_to_FF(mul(cl_FF_to_DF(x),y)); + , /* LF */ return cl_LF_to_FF(mul(cl_FF_to_LF(x,LFlen0(y)),y)); + ); + , /* DF */ + realcase6(y + , /* I */ return mul(x,cl_I_to_DF(y)); + , /* RT */ return mul(x,cl_RA_to_DF(y)); + , /* SF */ return cl_DF_to_SF(mul(x,cl_SF_to_DF(y))); + , /* FF */ return cl_DF_to_FF(mul(x,cl_FF_to_DF(y))); + , /* DF */ return mul(x,y); + , /* LF */ return cl_LF_to_DF(mul(cl_DF_to_LF(x,LFlen0(y)),y)); + ); + , /* LF */ + realcase6(y + , /* I */ return cl_LF_I_mul(x,y); + , /* RT */ return cl_LF_RA_mul(x,y); + , /* SF */ return cl_LF_to_SF(mul(x,cl_SF_to_LF(y,LFlen0(x)))); + , /* FF */ return cl_LF_to_FF(mul(x,cl_FF_to_LF(y,LFlen0(x)))); + , /* DF */ return cl_LF_to_DF(mul(x,cl_DF_to_LF(y,LFlen0(x)))); + , /* LF */ return mul(x,y); + ); + ); +} diff --git a/src/real/elem/cl_R_plus.cc b/src/real/elem/cl_R_plus.cc new file mode 100644 index 0000000..02d6692 --- /dev/null +++ b/src/real/elem/cl_R_plus.cc @@ -0,0 +1,23 @@ +// binary operator + + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_rational.h" +#include "cl_float.h" + +const cl_R operator+ (const cl_R& x, const cl_R& y) +{ + if (eq(y,0)) { return x; } + elif (eq(x,0)) { return y; } + else +#define plus(a,b) a+b +GEN_R_OP2_2(x,y, plus, return) +} diff --git a/src/real/elem/cl_R_plus1.cc b/src/real/elem/cl_R_plus1.cc new file mode 100644 index 0000000..208b88a --- /dev/null +++ b/src/real/elem/cl_R_plus1.cc @@ -0,0 +1,17 @@ +// plus1(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_rational.h" +#include "cl_float.h" + +const cl_R plus1 (const cl_R& x) +GEN_R_OP1_2(x, plus1, return) diff --git a/src/real/elem/cl_R_plusp.cc b/src/real/elem/cl_R_plusp.cc new file mode 100644 index 0000000..7067f64 --- /dev/null +++ b/src/real/elem/cl_R_plusp.cc @@ -0,0 +1,20 @@ +// plusp(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +cl_boolean plusp (const cl_R& x) +{ + if (minusp(x)) + return cl_false; // x<0 -> nein + elif (zerop(x)) + return cl_false; // x=0 -> nein + else + return cl_true; // sonst ist x>0. +} diff --git a/src/real/elem/cl_R_recip.cc b/src/real/elem/cl_R_recip.cc new file mode 100644 index 0000000..7561ded --- /dev/null +++ b/src/real/elem/cl_R_recip.cc @@ -0,0 +1,17 @@ +// recip(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_rational.h" +#include "cl_float.h" + +const cl_R recip (const cl_R& x) +GEN_R_OP1_2(x, recip, return) diff --git a/src/real/elem/cl_R_square.cc b/src/real/elem/cl_R_square.cc new file mode 100644 index 0000000..669770a --- /dev/null +++ b/src/real/elem/cl_R_square.cc @@ -0,0 +1,28 @@ +// square(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_rational.h" +#include "cl_integer.h" +#include "cl_float.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" +#include "cl_RA.h" +#include "cl_I.h" + +const cl_R square (const cl_R& x) +#if 0 +GEN_R_OP1_2(x, square, return) +#else // fully inlined, faster +GEN_R_OP1_7(x, square, return) +#endif diff --git a/src/real/elem/cl_R_uminus.cc b/src/real/elem/cl_R_uminus.cc new file mode 100644 index 0000000..c8e5f06 --- /dev/null +++ b/src/real/elem/cl_R_uminus.cc @@ -0,0 +1,29 @@ +// unary operator - + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_rational.h" +#include "cl_integer.h" +#include "cl_float.h" +#include "cl_sfloat.h" +#include "cl_ffloat.h" +#include "cl_dfloat.h" +#include "cl_lfloat.h" +#include "cl_RA.h" +#include "cl_I.h" + +const cl_R operator- (const cl_R& x) +#define minus(a) -a +#if 0 +GEN_R_OP1_2(x, minus, return) +#else // fully inlined, faster +GEN_R_OP1_7(x, minus, return) +#endif diff --git a/src/real/elem/cl_R_zerop.cc b/src/real/elem/cl_R_zerop.cc new file mode 100644 index 0000000..530d2e0 --- /dev/null +++ b/src/real/elem/cl_R_zerop.cc @@ -0,0 +1,29 @@ +// zerop(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_RA.h" +#include "cl_I.h" +#include "cl_F.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_SF_zerop.cc" +#include "cl_FF_zerop.cc" +#include "cl_DF_zerop.cc" +#include "cl_LF_zerop.cc" + +cl_boolean zerop (const cl_R& x) +#if 0 +GEN_R_OP1_2(x, zerop, return) +#else // fully inlined, faster +GEN_R_OP1_7(x, zerop, return) +#endif diff --git a/src/real/format-output/Makeflags b/src/real/format-output/Makeflags new file mode 100644 index 0000000..cd9512e --- /dev/null +++ b/src/real/format-output/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/real/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/base/string diff --git a/src/real/format-output/TODO-format b/src/real/format-output/TODO-format new file mode 100644 index 0000000..c6bff7b --- /dev/null +++ b/src/real/format-output/TODO-format @@ -0,0 +1,222 @@ +- operator<< should respect and reset the istream flags +- operator>> should respect and reset the ostream flags + See ANSI/ISO C++ section 22.2.2.2 num_put + see egcs-1.1b/libio/iostream.cc : write_int, + uses stream.flags(), stream.width(0), stream.fill() + +; (format-float-for-f w d k overflowchar padchar plus-sign-flag arg stream) +; gibt die Floating-Point-Zahl arg in Festkommadarstellung auf stream aus. +(defun format-float-for-f (w d k overflowchar padchar plus-sign-flag arg stream) + (let ((width (if w (if (or plus-sign-flag (minusp arg)) (1- w) w) nil))) + ; width = zur Verfügung stehende Zeichen ohne Vorzeichen + (multiple-value-bind (digits digitslength leadingpoint trailingpoint) + (format-float-to-string arg width d k nil) + (when (eql d 0) (setq trailingpoint nil)) ; d=0 -> keine Zusatz-Null hinten + (when w + (setq width (- width digitslength)) + (when leadingpoint ; evtl. Zusatz-Null vorne einplanen + (if (> width 0) (setq width (1- width)) (setq leadingpoint nil)) + ) + (when trailingpoint ; evtl. Zusatz-Null hinten einplanen + (if (> width 0) (setq width (1- width)) (setq trailingpoint nil)) + ) + ) + ; Es bleiben noch width Zeichen übrig. + (if (and overflowchar w (minusp width)) + (format-padding w overflowchar stream) ; Zu wenig Platz -> overflow + (progn + (when (and w (> width 0)) (format-padding width padchar stream)) + (if (minusp arg) + (write-char #\- stream) + (if plus-sign-flag (write-char #\+ stream)) + ) + (when leadingpoint (write-char #\0 stream)) + (write-string digits stream) + (when trailingpoint (write-char #\0 stream)) + ) ) +) ) ) + +; (format-float-for-e w d e k overflowchar padchar exponentchar plus-sign-flag +; arg stream) +; gibt die Floating-point-Zahl arg in Exponentialdarstellung auf den stream aus. +; (vgl. CLTL S.392-394) +; Aufteilung der Mantisse: +; Falls k<=0, erst 1 Null (falls von der Breite her passend), dann der Punkt, +; dann |k| Nullen, dann d-|k| signifikante Stellen; +; zusammen also d Nachkommastellen. +; Falls k>0, erst k signifikante Stellen, dann der Punkt, +; dann weitere d-k+1 signifikante Stellen; +; zusammen also d+1 signifikante Stellen. Keine Nullen vorne. +; (Der Defaultwert in FORMAT-EXPONENTIAL-FLOAT ist k=1.) +; Vor der Mantisse das Vorzeichen (ein + nur falls arg>=0 und plus-sign-flag). +; Dann der Exponent, eingeleitet durch exponentchar, dann Vorzeichen des +; Exponenten (stets + oder -), dann e Stellen für den Exponenten. +; Dann wird das Ganze mit padchars auf w Zeichen Breite aufgefüllt. +; Sollte das (auch nach evtl. Unterdrückung einer führenden Null) mehr als +; w Zeichen ergeben, so werden statt dessen w overflowchars ausgegeben, oder +; (falls overflowchar = nil) die Zahl mit so vielen Stellen wie nötig +; ausgegeben. +(defun format-float-for-e (w d e k + overflowchar padchar exponentchar plus-sign-flag arg stream) + (multiple-value-bind (mantissa oldexponent) (format-scale-exponent (abs arg)) + (let* ((exponent (if (zerop arg) 0 (- oldexponent k))) ; auszugebender Exponent + (expdigits (write-to-string (abs exponent) :base 10. :radix nil :readably nil)) + (expdigitsneed (if e (max (length expdigits) e) (length expdigits))) + ; expdigitsneed = Anzahl der Stellen, die für die Ziffern des + ; Exponenten nötig sind. + (mantd (if d (if (> k 0) (1+ (- d k)) d) nil)) + ; mantd = Anzahl der Mantissenstellen hinter dem Punkt + (dmin (if (minusp k) (- 1 k) nil)) ; nachher: fordere, daß + ; nicht in die ersten (+ 1 (abs k)) Stellen hineingerundet wird. + (mantwidth (if w (- w 2 expdigitsneed) nil)) + ; mantwidth = Anzahl der für die Mantisse (inkl. Vorzeichen, Punkt) + ; zur Verfügung stehenden Zeichen (oder nil) + ) + (declare (simple-string expdigits) (fixnum exponent expdigitsneed)) + (if (and overflowchar w e (> expdigitsneed e)) + ; Falls Overflowchar und w und e angegeben, Exponent mehr braucht: + (format-padding w overflowchar stream) + (progn + (if w + (if (or plus-sign-flag (minusp arg)) (setq mantwidth (1- mantwidth))) + ) + ; mantwidth = Anzahl der für die Mantisse (ohne Vorzeichen, + ; inklusive Punkt) zur Verfügung stehenden Zeichen (oder nil) + (multiple-value-bind (mantdigits mantdigitslength + leadingpoint trailingpoint) + (format-float-to-string mantissa mantwidth mantd k dmin) + (when w + (setq mantwidth (- mantwidth mantdigitslength)) + (if trailingpoint + (if (or (null mantd) (> mantd 0)) + (setq mantwidth (- mantwidth 1)) + (setq trailingpoint nil) + ) ) + (if leadingpoint + (if (> mantwidth 0) + (setq mantwidth (- mantwidth 1)) + (setq leadingpoint nil) + ) ) + ) + ; Es bleiben noch mantwidth Zeichen übrig. + (if (and overflowchar w (minusp mantwidth)) + (format-padding w overflowchar stream) ; Zu wenig Platz -> overflow + (progn + (when (and w (> mantwidth 0)) + (format-padding mantwidth padchar stream) + ) + (if (minusp arg) + (write-char #\- stream) + (if plus-sign-flag (write-char #\+ stream)) + ) + (if leadingpoint (write-char #\0 stream)) + (write-string mantdigits stream) + (if trailingpoint (write-char #\0 stream)) + (write-char + (cond (exponentchar) + ((and (not *PRINT-READABLY*) + (typep arg *READ-DEFAULT-FLOAT-FORMAT*) + ) + #\E + ) + ((short-float-p arg) #\s) + ((single-float-p arg) #\f) + ((double-float-p arg) #\d) + ((long-float-p arg) #\L) + ) + stream + ) + (write-char (if (minusp exponent) #\- #\+) stream) + (when (and e (> e (length expdigits))) + (format-padding (- e (length expdigits)) #\0 stream) + ) + (write-string expdigits stream) + ) ) ) + ) ) ) +) ) + +; ~F, CLTL S.390-392, CLtL2 S. 588-590 +(defformat-simple format-fixed-float (stream colon-modifier atsign-modifier + (w nil) (d nil) (k 0) (overflowchar nil) (padchar #\Space)) + (arg) + (declare (ignore colon-modifier)) + (when (rationalp arg) (setq arg (float arg))) + (if (floatp arg) + (format-float-for-f w d k overflowchar padchar atsign-modifier arg stream) + (print_rational arg stream 10) +) ) + +; ~E, CLTL S.392-395, CLtL2 S. 590-593 +(defformat-simple format-exponential-float (stream colon-modifier atsign-modifier + (w nil) (d nil) (e nil) (k 1) + (overflowchar nil) (padchar #\Space) (exponentchar nil)) + (arg) + (declare (ignore colon-modifier)) + (when (rationalp arg) (setq arg (float arg))) + (if (floatp arg) + (format-float-for-e w d e k overflowchar padchar exponentchar + atsign-modifier arg stream + ) + (print_rational arg stream 10) +) ) + +; ~G, CLTL S.395-396, CLtL2 S. 594-595 +(defformat-simple format-general-float (stream colon-modifier atsign-modifier + (w nil) (d nil) (e nil) (k 1) + (overflowchar nil) (padchar #\Space) (exponentchar nil)) + (arg) + (declare (ignore colon-modifier)) + (if (rationalp arg) (setq arg (float arg))) + (if (floatp arg) + (multiple-value-bind (mantissa n) (format-scale-exponent (abs arg)) + (declare (ignore mantissa)) + (if (null d) + (setq d + (multiple-value-bind (digits digitslength) + (format-float-to-string (abs arg) nil nil nil nil) + (declare (ignore digits)) + (max (max (1- digitslength) 1) (min n 7)) + ) ) ) + (let* ((ee (if e (+ 2 e) 4)) + (dd (- d n))) + (if (<= 0 dd d) + (progn + (format-float-for-f + (if w (- w ee) nil) + dd 0 + overflowchar padchar atsign-modifier arg stream + ) + (format-padding ee #\Space stream) + ) + (format-float-for-e w d e k overflowchar padchar exponentchar + atsign-modifier arg stream + ) ) ) ) + (print_rational arg stream 10) +) ) + +; ~$, CLTL S.396-397, CLtL2 S. 595-596 +(defformat-simple format-dollars-float (stream colon-modifier atsign-modifier + (d 2) (n 1) (w 0) (padchar #\Space)) + (arg) + (when (rationalp arg) (setq arg (float arg))) + (if (floatp arg) + (multiple-value-bind (digits digitslength + leadingpoint trailingpoint leadings) + (format-float-to-string arg nil d 0 nil) + (declare (ignore digitslength leadingpoint trailingpoint)) + (let* ((lefts (max leadings n)) + (totalwidth (+ (if (or atsign-modifier (minusp arg)) 1 0) + lefts 1 d + ) ) + (padcount (max (- w totalwidth) 0))) + (if (not colon-modifier) (format-padding padcount padchar stream)) + (if (minusp arg) + (write-char #\- stream) + (if atsign-modifier (write-char #\+ stream)) + ) + (if colon-modifier (format-padding padcount padchar stream)) + (format-padding (- lefts leadings) #\0 stream) + (write-string digits stream) + ) ) + (print_rational arg stream 10) +) ) diff --git a/src/real/format-output/cl_fmt_cardinal.cc b/src/real/format-output/cl_fmt_cardinal.cc new file mode 100644 index 0000000..2685f47 --- /dev/null +++ b/src/real/format-output/cl_fmt_cardinal.cc @@ -0,0 +1,134 @@ +// format_cardinal(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_format.h" + + +// Implementation. + +#include "cl_integer.h" +#include "cl_integer_io.h" +#include "cl_abort.h" + +static const char * const cl_format_ones [20] = { + NULL, + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", + "ten", + "eleven", + "twelve", + "thirteen", + "fourteen", + "fifteen", + "sixteen", + "seventeen", + "eighteen", + "nineteen", +}; + +// gibt eine ganze Zahl >0, <1000 im Klartext auf englisch auf den stream aus. +// (arg=0 -> gibt nichts aus.) +static void format_small_cardinal (cl_ostream stream, uintL arg) +{ + var uintL hundreds = floor(arg,100); + var uintL tens_and_ones = arg % 100; + if (hundreds > 0) { + fprint(stream,cl_format_ones[hundreds]); + fprint(stream," hundred"); + } + if (tens_and_ones > 0) { + if (hundreds > 0) + fprint(stream," and "); + var uintL tens = floor(tens_and_ones,10); + var uintL ones = tens_and_ones % 10; + if (tens < 2) + fprint(stream,cl_format_ones[tens_and_ones]); + else { + fprint(stream,cl_format_tens[tens]); + if (ones > 0) { + fprintchar(stream,'-'); + fprint(stream,cl_format_ones[ones]); + } + } + } +} + +void format_cardinal (cl_ostream stream, const cl_I& argument) +{ + if (zerop(argument)) + fprint(stream,"zero"); + else { + var cl_I arg = argument; + if (minusp(arg)) { + fprint(stream,"minus "); + arg = -arg; + } + // amerikanisch (billion=10^9) + static const char * const illions[] = { + "", + " thousand", + " million", + " billion", + " trillion", + " quadrillion", + " quintillion", + " sextillion", + " septillion", + " octillion", + " nonillion", + " decillion", + " undecillion", + " duodecillion", + " tredecillion", + " quattuordecillion", + " quindecillion", + " sexdecillion", + " septendecillion", + " octodecillion", + " novemdecillion", + " vigintillion", + NULL + }; + var uintL small_pieces [sizeof(illions)/sizeof(illions[0])]; + // Let the recursion begin. + var const char * const * illion_ptr = &illions[0]; + var uintL * small_piece_ptr = &small_pieces[0]; + do { + if (*illion_ptr == NULL) { + fprint(cl_stderr, "format_cardinal: argument too large: "); + fprint(cl_stderr, argument); + fprint(cl_stderr, "\n"); + cl_abort(); + } + var cl_I_div_t div = floor2(arg,1000); + var const cl_I& thousands = div.quotient; + var uintL small = cl_I_to_UL(div.remainder); + illion_ptr++; + *small_piece_ptr++ = small; + arg = thousands; + } while (arg > 0); + // Roll back the recursion. + var cl_boolean first_piece = cl_true; + do { + var uintL small = *--small_piece_ptr; + var const char * illion = *--illion_ptr; + if (small > 0) { + if (!first_piece) + fprint(stream,", "); + format_small_cardinal(stream,small); + fprint(stream,illion); + first_piece = cl_false; + } + } until (illion_ptr == &illions[0]); + } +} diff --git a/src/real/format-output/cl_fmt_floatstring.cc b/src/real/format-output/cl_fmt_floatstring.cc new file mode 100644 index 0000000..dc20a6e --- /dev/null +++ b/src/real/format-output/cl_fmt_floatstring.cc @@ -0,0 +1,254 @@ +// format_float_to_string(). + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_fmt_floatstring) + +// Specification. +#include "cl_format.h" + + +// Implementation. + +// BUGS: +// - This is slow. + +#include "cl_output.h" +#include "cl_malloc.h" +#include "cl_float.h" +#include "cl_integer.h" +#include "cl_I.h" +#include "cl_spushstring.h" + +// format_float_to_string(arg,width,d,k,dmin) +// ergibt einen String zum Floating-point arg: +// er hat den Wert von abs(arg)*expt(10,k), dabei mind. d Nachkommastellen +// und höchstens die Länge width (width<=0 -> keine Einschränkung). +// Trotzdem wird nicht auf weniger als dmin Stellen gerundet. + +const digits_with_dot format_float_to_string (const cl_F& arg, const sintL width, const sintL d, const sintL k, const sintL dmin) +{ + // One pre-allocated buffer. This reduces the allocation/free cost. + static cl_spushstring digitstring; + + if (zerop(arg)) { + var sintL places = (d < dmin ? dmin : d); + if (width > 0) + // width angegeben -> places := min(places,width-1) + if (places >= width) + places = width-1; + // ein Punkt und places Nullen + var char* string = (char *) cl_malloc_hook(1+places+1); + string[0] = '.'; + for (sintL i = 1; i <= places; i++) string[i] = '0'; + string[1+places] = '\0'; + return digits_with_dot(string, 1+places, + cl_true, (cl_boolean)(places==0), 0 + ); + } + // significand : Integer >0 + // expon : Integer + // mantprec : Anzahl der echten Mantissenbits von significand + // (also 2^mantprec <= significand < 2^(mantprec+1)) + // width : Anzahl Stellen, die die Zahl (inklusive Punkt) nicht + // überschreiten soll, oder 0 + // d : Mindestanzahl Nachkommastellen oder 0 + // k : Skalierungsfaktor (siehe CLTL S.394) + // dmin : Mindestanzahl von Dezimaltellen, die (trotz Angabe von width + // oder d) nicht gerundet werden dürfen. + // (Nur interessant, falls d <= dmin <= (precision der Zahl).) + // wandelt die Zahl significand*2^expon um in einen Dezimalstring um. + // Es ist kein Exponent dabei. + var cl_idecoded_float decoded = integer_decode_float(arg); + var const cl_I& significand = decoded.mantissa; + var const cl_I& expon = decoded.exponent; + var uintL mantprec = float_digits(arg)-1; + var cl_I numerator = significand; + var cl_I denominator = 1; + var cl_I abrund_einh = 1; // Abrundungseinheit: + // Abrunden um 1 in der letzten abrundbaren Stelle entspricht + // einer Erniedrigung von numerator um abrund_einh. + var cl_I aufrund_einh = 1; // Aufrundungseinheit: + // Aufrunden um 1 in der letzten aufrundbaren Stelle entspricht + // einer Erhöhung von numerator um aufrund_einh. + digitstring.reset(); + if (expon > 0) { + numerator = numerator << expon; + aufrund_einh = abrund_einh = 1 << expon; + } + elif (expon < 0) { + denominator = denominator << -expon; + // aufrund_einh = abrund_einh = 1; + } + // Zahl = numerator/denominator + if (significand == ash(1,mantprec)) { + // Ist der Significand=2^mantprec, so ist abrund-einh zu halbieren. + // Man kann stattdessen auch alle 3 anderen Grössen verdoppeln: + aufrund_einh = aufrund_einh << 1; + numerator = numerator << 1; + denominator = denominator << 1; + } + // Defaultmäßig: Auf-/Abrunde-Einheit = eine Einheit in der letzten + // BINÄRstelle. + // Zahl = numerator/denominator + // Skalierungsfaktor k in die Zahl mit einbeziehen (vgl. CLTL S.394) + // k<0 -> Mantisse durch 10^|k| dividieren + // k>0 -> Mantisse mit 10^k multiplizieren + // Dabei aufrund-einh, abrund-einh im Verhältnis zu numerator beibehalten. + if (k != 0) { + if (k < 0) { + var cl_I skal_faktor = expt_pos(10,-k); + denominator = denominator * skal_faktor; + } + elif (k > 0) { + var cl_I skal_faktor = expt_pos(10,k); + numerator = numerator * skal_faktor; + aufrund_einh = aufrund_einh * skal_faktor; + abrund_einh = abrund_einh * skal_faktor; + } + } + // Stellen: 0 = 1. Stelle vor dem Punkt, -1 = 1. Stelle nach dem Punkt. + var sintL stelle = 0; // Stelle der als nächstes auszugebenden Ziffer + // auf >= 1/10 adjustieren: + // (jeweils numerator mit 10 multiplizieren, eine führende 0 mehr vorsehen) + until (10*numerator >= denominator) { + stelle = stelle-1; + numerator = numerator * 10; + aufrund_einh = aufrund_einh * 10; + abrund_einh = abrund_einh * 10; + } + // stelle = Stelle der letzten führenden 0 + // = 1 + Stelle der 1. signifikanten Ziffer + // oder =0, falls k>=0 + // Ausführung der Rundung: + var cl_boolean letzte_stelle_p = cl_false; // d oder width angegeben? + var sintL letzte_stelle = 0; // falls d oder width angegeben waren: + // Stelle der letzten signifikanten Ziffer + var cl_boolean halbzahlig = cl_false; // zeigt an, ob hinten genau ein 0.500000 wegfällt + do { + // Solange das Ergebnis auch nach Aufrundung >= 1 bliebe, + // eine Vorkommastelle mehr einplanen: + until (((numerator << 1) + aufrund_einh) < (denominator << 1)) { + denominator = denominator * 10; + stelle = stelle+1; + } + // Falls d oder width angegeben: + // letzte_stelle ausrechnen + if (d != 0) { + // Falls dmin angegeben: min(-d,-dmin) = -max(d,dmin). + // Sonst -d. + letzte_stelle = -d; + if (dmin > 0) + if (letzte_stelle > -dmin) + letzte_stelle = -dmin; + letzte_stelle_p = cl_true; + } + elif (width > 0) { + // Falls nicht d, nur width angegeben: + if (stelle < 0) + // Es kommen führende Nullen nach dem Punkt -> d:=width-1 + letzte_stelle = 1-width; + else + // Es kommen keine führenden Nullen nach dem Punkt -> + // Es wird stelle Vorkommaziffern geben, d:=width-1-stelle + letzte_stelle = 1+stelle-width; + // also letzte_stelle = -(width-1 - max(stelle,0)) + // wieder dmin berücksichtigen: + if (dmin > 0) + if (letzte_stelle > -dmin) + letzte_stelle = -dmin; + letzte_stelle_p = cl_true; + } + if (letzte_stelle_p) { + var sintL ziffernzahl = letzte_stelle - stelle; + // ziffernzahl = - Zahl signifikanter Stellen oder >=0. + var cl_I dezimal_einh = denominator; + // dezimal-einh := ceiling(dezimal_einh*expt(10,ziffernzahl)) + if (ziffernzahl > 0) + dezimal_einh = dezimal_einh*expt_pos(10,ziffernzahl); + elif (ziffernzahl < 0) + dezimal_einh = ceiling1(dezimal_einh,expt_pos(10,-ziffernzahl)); + // dezimal-einh = Um wieviel numerator erhöht bzw. erniedigt werden + // müßte, damit sich die Dezimaldarstellung um genau 1 an der + // Position letzte_stelle verändert. + if (abrund_einh < dezimal_einh) + abrund_einh = dezimal_einh; + if (aufrund_einh < dezimal_einh) + aufrund_einh = dezimal_einh; + // Jetzt darf auch um eine (halbe) DEZIMAL-Einheit gerundet werden. + if (aufrund_einh == dezimal_einh) + halbzahlig = cl_true; + } + } until (((numerator << 1) + aufrund_einh) < (denominator << 1)); + // stelle = Position der ersten signifikanten Stelle + 1 + var uintL digit_count = 0; // Zahl der bisher in digit-string + // ausgegebenen Ziffern (exklusive den Punkt) + var uintL point_pos = 0; // Punkt-Position = Zahl führender Stellen + // = Zahl der Ziffern vor dem Punkt + // Führenden Punkt und nachfolgende Nullen ausgeben: + if (stelle < 0) { + digitstring.push('.'); + point_pos = digit_count; + for (int i = -stelle; i >= 0; i--) { + digitstring.push('0'); + digit_count++; + } + } + // Ziffern der Mantisse ausgeben: + var uintL digit; // die laufende Ziffer, >=0, <10 + var bool abrunden; // letzte Ziffer abzurunden? + var bool aufrunden; // letzte Ziffer aufzurunden? + for (;;) { + if (stelle == 0) { + digitstring.push('.'); + point_pos = digit_count; + } + stelle = stelle-1; + var cl_I_div_t div = cl_divide(numerator*10,denominator); + digit = cl_I_to_UL(div.quotient); + numerator = div.remainder; + abrund_einh = abrund_einh*10; + aufrund_einh = aufrund_einh*10; + abrunden = ((numerator<<1) < abrund_einh); + aufrunden = (halbzahlig + ? (numerator<<1) >= (denominator<<1) - aufrund_einh + : (numerator<<1) > (denominator<<1) - aufrund_einh + ); + if (abrunden || aufrunden + || (letzte_stelle_p && (stelle <= letzte_stelle)) + ) + break; + digitstring.push("0123456789"[digit]); + digit_count++; + } + // letzte signifikante Ziffer ausgeben: + if (letzte_stelle_p ? (cl_boolean)(stelle >= letzte_stelle) : cl_true) { + digit = (abrunden && !aufrunden ? digit : + aufrunden && !abrunden ? digit+1 : + (numerator<<1) <= denominator ? digit : digit+1); + digitstring.push("0123456789"[digit]); + digit_count++; + } + // Nachfolgende Nullen und Punkt ausgeben + if (stelle >= 0) { + for (int i = stelle; i >= 0; i--) { + digitstring.push('0'); + digit_count++; + } + digitstring.push('.'); + point_pos = digit_count; + } + if (d != 0) + for (int i = d - (digit_count - point_pos); i >= 0; i--) { + digitstring.push('0'); + digit_count++; + } + return digits_with_dot(digitstring.contents(), digit_count+1, + (cl_boolean)(point_pos==0), + (cl_boolean)(point_pos==digit_count), + point_pos + ); +} + +CL_PROVIDE_END(cl_fmt_floatstring) diff --git a/src/real/format-output/cl_fmt_integer.cc b/src/real/format-output/cl_fmt_integer.cc new file mode 100644 index 0000000..0a9393c --- /dev/null +++ b/src/real/format-output/cl_fmt_integer.cc @@ -0,0 +1,65 @@ +// format_integer(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_format.h" + + +// Implementation. + +#include "cl_integer_io.h" +#include +#include "cl_I.h" + +void format_integer (cl_ostream stream, const cl_I& arg, + unsigned int base, sintL mincol, char padchar, + char commachar, uintL commainterval, cl_boolean commaflag, + cl_boolean positive_sign_flag) +{ + if ((mincol == 0) && !commaflag && !positive_sign_flag) { + // Normale Ausgabe tut's. + print_integer(stream,base,arg); + return; + } + var char* oldstring = print_integer_to_string(base,arg); + var uintL oldstring_length = strlen(oldstring); + var uintL number_of_digits = (minusp(arg) ? oldstring_length-1 : oldstring_length); + var uintL number_of_commas = (commaflag ? floor(number_of_digits-1,commainterval) : 0); + var cl_boolean positive_sign = (cl_boolean) (positive_sign_flag && (arg > 0)); + var uintL newstring_length = (positive_sign ? 1 : 0) + oldstring_length + number_of_commas; + var char* newstring = (char *) cl_malloc_hook(newstring_length+1); + newstring[newstring_length] = '\0'; // newstring termination + // newstring füllen: + { + // Erst Vorzeichen +: + if (positive_sign) + newstring[0] = '+'; + // Dann oldstring in newstring übertragen, dabei Kommata überspringen: + var uintL oldpos = oldstring_length; + var uintL oldpos_mod = 0; // = (oldstring_length - oldpos) % commainterval + var uintL newpos = newstring_length; + until (oldpos == 0) { + newstring[--newpos] = oldstring[--oldpos]; + if (number_of_commas > 0) { + // Check whether ((oldstring_length - oldpos) % commainterval) == 0 + if (++oldpos_mod == commainterval) { + oldpos_mod = 0; + // noch ein Komma einzufügen + newstring[--newpos] = commachar; + number_of_commas--; + } + } + } + } +#if 0 + format_padded_string(stream,mincol,1,0,padchar,cl_true,newstring); +#else // expand this special case of format_padded_string inline: + if ((sintL)newstring_length < mincol) + format_padding(stream,mincol-newstring_length,padchar); + fprint(stream,newstring); +#endif + cl_free_hook(newstring); + cl_free_hook(oldstring); +} diff --git a/src/real/format-output/cl_fmt_newroman.cc b/src/real/format-output/cl_fmt_newroman.cc new file mode 100644 index 0000000..863a524 --- /dev/null +++ b/src/real/format-output/cl_fmt_newroman.cc @@ -0,0 +1,54 @@ +// format_new_roman(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_format.h" + + +// Implementation. + +#include "cl_integer.h" +#include "cl_integer_io.h" +#include "cl_abort.h" + +void format_new_roman (cl_ostream stream, const cl_I& arg) +{ + if (!(0 < arg && arg < 4000)) { + fprint(cl_stderr, "format_new_roman: argument should be in the range 1 - 3999, not "); + fprint(cl_stderr, arg); + fprint(cl_stderr, ".\n"); + cl_abort(); + } + var uintL value = cl_I_to_UL(arg); + struct roman { char symbol; uintL value; }; + static const roman scale[7] = { + { 'I', 1 }, + { 'V', 5 }, + { 'X', 10 }, + { 'L', 50 }, + { 'C', 100 }, + { 'D', 500 }, + { 'M', 1000 }, + }; + for (int i = 6; value > 0 /* && i >= 0 */ ; i--) { + var const roman * p = &scale[i]; + var uintL multiplicity = floor(value,p->value); + value = value % p->value; + while (multiplicity > 0) { + fprintchar(stream,p->symbol); + multiplicity--; + } + if (value == 0) + break; + // Must have i > 0 here. + var const roman * p_minor = &scale[(i-1) & ~1]; + var uintL lowered_value = p->value - p_minor->value; + if (value >= lowered_value) { + fprintchar(stream,p_minor->symbol); + fprintchar(stream,p->symbol); + value = value - lowered_value; + } + } +} diff --git a/src/real/format-output/cl_fmt_oldroman.cc b/src/real/format-output/cl_fmt_oldroman.cc new file mode 100644 index 0000000..36e622e --- /dev/null +++ b/src/real/format-output/cl_fmt_oldroman.cc @@ -0,0 +1,44 @@ +// format_old_roman(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_format.h" + + +// Implementation. + +#include "cl_integer.h" +#include "cl_integer_io.h" +#include "cl_abort.h" + +void format_old_roman (cl_ostream stream, const cl_I& arg) +{ + if (!(0 < arg && arg < 5000)) { + fprint(cl_stderr, "format_old_roman: argument should be in the range 1 - 4999, not "); + fprint(cl_stderr, arg); + fprint(cl_stderr, ".\n"); + cl_abort(); + } + var uintL value = cl_I_to_UL(arg); + struct roman { char symbol; uintL value; }; + static const roman scale[7] = { + { 'I', 1 }, + { 'V', 5 }, + { 'X', 10 }, + { 'L', 50 }, + { 'C', 100 }, + { 'D', 500 }, + { 'M', 1000 }, + }; + for (int i = 6; value > 0 /* && i >= 0 */ ; i--) { + var const roman * p = &scale[i]; + var uintL multiplicity = floor(value,p->value); + value = value % p->value; + while (multiplicity > 0) { + fprintchar(stream,p->symbol); + multiplicity--; + } + } +} diff --git a/src/real/format-output/cl_fmt_ordinal.cc b/src/real/format-output/cl_fmt_ordinal.cc new file mode 100644 index 0000000..7bd3373 --- /dev/null +++ b/src/real/format-output/cl_fmt_ordinal.cc @@ -0,0 +1,83 @@ +// format_ordinal(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_format.h" + + +// Implementation. + +#include "cl_integer.h" + +static const char * const cl_format_ordinal_ones [20] = { + NULL, + "first", + "second", + "third", + "fourth", + "fifth", + "sixth", + "seventh", + "eighth", + "ninth", + "tenth", + "eleventh", + "twelfth", + "thirteenth", + "fourteenth", + "fifteenth", + "sixteenth", + "seventeenth", + "eighteenth", + "nineteenth", +}; + +static const char * const cl_format_ordinal_tens [10] = { + NULL, + "tenth", + "twentieth", + "thirtieth", + "fortieth", + "fiftieth", + "sixtieth", + "seventieth", + "eightieth", + "ninetieth", +}; + +void format_ordinal (cl_ostream stream, const cl_I& argument) +{ + if (zerop(argument)) + fprint(stream,"zeroth"); + else { + var cl_I arg = argument; + if (minusp(arg)) { + fprint(stream,"minus "); + arg = -arg; + } + var cl_I_div_t div = floor2(arg,100); + var const cl_I& hundreds = div.quotient; + var uintL tens_and_ones = cl_I_to_UL(div.remainder); + if (hundreds > 0) + format_cardinal(stream,hundreds*100); + if (tens_and_ones == 0) + fprint(stream,"th"); + else { + var uintL tens = floor(tens_and_ones,10); + var uintL ones = tens_and_ones % 10; + if (hundreds > 0) + fprintchar(stream,' '); + if (tens < 2) + fprint(stream,cl_format_ordinal_ones[tens_and_ones]); + elif (ones == 0) + fprint(stream,cl_format_ordinal_tens[tens]); + else { + fprint(stream,cl_format_tens[tens]); + fprintchar(stream,'-'); + fprint(stream,cl_format_ordinal_ones[ones]); + } + } + } +} diff --git a/src/real/format-output/cl_fmt_paddedstring.cc b/src/real/format-output/cl_fmt_paddedstring.cc new file mode 100644 index 0000000..4deefb0 --- /dev/null +++ b/src/real/format-output/cl_fmt_paddedstring.cc @@ -0,0 +1,26 @@ +// format_padded_string(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_format.h" + + +// Implementation. + +#include + +void format_padded_string (cl_ostream stream, sintL mincol, sintL colinc, sintL minpad, char padchar, cl_boolean padleftflag, const char * str) +{ + var sintL need = strlen(str) + minpad; // so viele Zeichen mindestens + var uintL auxpad = (need < mincol + ? ceiling((uintL)(mincol - need), colinc) * colinc + : 0 + ); + if (!padleftflag) + fprint(stream,str); + format_padding(stream,minpad+auxpad,padchar); + if (padleftflag) + fprint(stream,str); +} diff --git a/src/real/format-output/cl_fmt_scaleexp.cc b/src/real/format-output/cl_fmt_scaleexp.cc new file mode 100644 index 0000000..8d4af32 --- /dev/null +++ b/src/real/format-output/cl_fmt_scaleexp.cc @@ -0,0 +1,114 @@ +// format_scale_exponent(). + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_fmt_scaleexp) + +// Specification. +#include "cl_format.h" + + +// Implementation. + +#include "cl_real.h" +#include "cl_integer.h" +#include "cl_float.h" +#include "cl_F.h" +#include "cl_SF.h" +#include "cl_FF.h" +#include "cl_DF.h" +#include "cl_LF.h" + +// NOTE: This may introduce roundoff-errors, through the use of *, /, expt. +// But this doesn't matter since format_float_to_string() works with +// exact integers, starting with integer_decode_float(). + +// For a floating point format f, five characteristic numbers: +struct float_format_params { + cl_F zero; // cl_float(0,f) + cl_F one; // cl_float(1,f) + cl_F ten; // cl_float(10,f) + cl_F tenth; // cl_float(1/10,f) + cl_F lg2; // log(10,2), as needed (max. 32 bits) +// Constructor: + float_format_params (cl_F a, cl_F b, cl_F c, cl_F d, cl_F e) + : zero(a), one(b), ten(c), tenth(d), lg2(e) {} +}; + +static const cl_RA tenth = (cl_RA)"1/10"; +static const cl_SF SF_zero = cl_RA_to_SF(0); +static const cl_SF SF_one = cl_RA_to_SF(1); +static const cl_SF SF_ten = cl_RA_to_SF(10); +static const cl_SF SF_tenth = cl_RA_to_SF(tenth); +static const cl_FF FF_zero = cl_RA_to_FF(0); +static const cl_FF FF_one = cl_RA_to_FF(1); +static const cl_FF FF_ten = cl_RA_to_FF(10); +static const cl_FF FF_tenth = cl_RA_to_FF(tenth); +static const cl_DF DF_zero = cl_RA_to_DF(0); +static const cl_DF DF_one = cl_RA_to_DF(1); +static const cl_DF DF_ten = cl_RA_to_DF(10); +static const cl_DF DF_tenth = cl_RA_to_DF(tenth); +static const cl_SF SF_lg2 = (cl_SF)"0.30103"; +static const cl_DF DF_lg2 = (cl_DF)"0.30102999566"; + +static const float_format_params get_float_params (const cl_F& arg) +{ + floattypecase(arg + , return float_format_params(SF_zero,SF_one,SF_ten,SF_tenth,SF_lg2); + , return float_format_params(FF_zero,FF_one,FF_ten,FF_tenth,SF_lg2); + , return float_format_params(DF_zero,DF_one,DF_ten,DF_tenth,SF_lg2); + , var uintC len = TheLfloat(arg)->len; + return float_format_params( + cl_I_to_LF(0,len), + cl_I_to_LF(1,len), + cl_I_to_LF(10,len), + cl_RA_to_LF(tenth,len), + DF_lg2 // lg2 wird mit 32 Bit Genauigkeit gebraucht + ); + ); +} + +const cl_decoded_float format_scale_exponent (const cl_F& arg) +{ + // Get float format parameters. + var const float_format_params params = get_float_params(arg); + var const cl_F& zero = params.zero; + var const cl_F& one = params.one; + var const cl_F& ten = params.ten; + var const cl_F& tenth = params.tenth; + var const cl_F& lg2 = params.lg2; + // Decode arg. + if (zerop(arg)) + return cl_decoded_float(zero,0,one); + var cl_F abs_arg = abs(arg); + var cl_decoded_float decoded = decode_float(abs_arg); + var cl_I& expon = decoded.exponent; + var cl_I expon10a = truncate1(expon*lg2); // nicht round, um Überlauf zu vermeiden + var cl_F signif10a = abs_arg / expt(ten,expon10a); + // Maybe need to increment expon10. + var cl_I expon10b = expon10a; + var cl_F signif10b = signif10a; + { + var cl_F tenpow = ten; + until (signif10b < one) { + expon10b = expon10b + 1; + signif10b = signif10a / tenpow; + tenpow = tenpow * ten; + } + } + // Maybe need to decrement expon10. + var cl_I expon10c = expon10b; + var cl_F signif10c = signif10b; + { + var cl_F tenpow = ten; + until (signif10c >= tenth) { + expon10c = expon10c - 1; + signif10c = signif10b * tenpow; + tenpow = tenpow * ten; + } + } + return cl_decoded_float(signif10c,expon10c,float_sign(arg)); +} + +CL_PROVIDE_END(cl_fmt_scaleexp) diff --git a/src/real/format-output/cl_fmt_tens.cc b/src/real/format-output/cl_fmt_tens.cc new file mode 100644 index 0000000..8c8f6f7 --- /dev/null +++ b/src/real/format-output/cl_fmt_tens.cc @@ -0,0 +1,23 @@ +// cl_format_tens. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_format.h" + + +// Implementation. + +const char * const cl_format_tens [10] = { + NULL, + NULL, + "twenty", + "thirty", + "forty", + "fifty", + "sixty", + "seventy", + "eighty", + "ninety", +}; diff --git a/src/real/format-output/cl_format.h b/src/real/format-output/cl_format.h new file mode 100644 index 0000000..be1a72d --- /dev/null +++ b/src/real/format-output/cl_format.h @@ -0,0 +1,74 @@ +// Formatted output functions à la Common Lisp. + +#ifndef _CL_FORMAT_H +#define _CL_FORMAT_H + +#include "cl_number.h" +#include "cl_io.h" +#include "cl_float.h" + +// gibt arg als römische Zahl auf stream aus, z.B. 4 als IIII. +extern void format_old_roman (cl_ostream stream, const cl_I& arg); + +// gibt arg als römische Zahl auf stream aus, z.B. 4 als IV. +extern void format_new_roman (cl_ostream stream, const cl_I& arg); + +extern const char * const cl_format_tens [10]; + +// gibt die ganze Zahl arg im Klartext auf englisch auf den Stream aus. +extern void format_cardinal (cl_ostream stream, const cl_I& arg); + +// gibt eine ganze Zahl arg als Abzählnummer im Klartext auf englisch +// auf den stream aus. +extern void format_ordinal (cl_ostream stream, const cl_I& arg); + +// gibt count (>=0) Zeichen ch auf stream aus. +inline void format_padding (cl_ostream stream, sintL count, char ch) +{ + for (; count >= 0; count--) + fprintchar(stream,ch); +} + +// gibt auf den Stream stream aus: +// den String str, eventuell aufgefüllt mit Padding characters padchar. +// Und zwar so, daß die Breite mindestens mincol ist. Um das zu erreichen, +// werden mindestens minpad Zeichen eingefügt, eventuelle weitere dann in +// Blöcken à colinc Zeichen. Falls padleftflag, werden sie links eingefügt, +// sonst rechts vom String. +extern void format_padded_string (cl_ostream stream, sintL mincol, sintL colinc, sintL minpad, char padchar, cl_boolean padleftflag, const char * str); + +// gibt den Integer arg auf den Stream aus: +// in Zahlenbasis base, mit Vorzeichen (+ nur falls >0 und positive-sign-flag), +// bei commaflag alle drei Stellen unterbrochen durch ein Zeichen commachar. +// Das Ganze links aufgefüllt mit padchar's, so daß die Gesamtbreite mindestens +// mincol ist. +extern void format_integer (cl_ostream stream, const cl_I& arg, unsigned int base, sintL mincol, char padchar, char commachar, uintL commainterval, cl_boolean commaflag, cl_boolean positive_sign_flag); + +// format_scale_exponent(arg) liefert zur Floating-Point-Zahl arg +// drei Werte: mantissa und n, mit +// ganzem n und mantissa floating-point, 0.1 <= mantissa < 1, +// arg = mantissa * 10^n * sign (also 10^(n-1) <= abs(arg) < 10^n ). +// (Bei arg=0.0: 0.0 und n=0.) +extern const cl_decoded_float format_scale_exponent (const cl_F& arg); +CL_REQUIRE(cl_fmt_scaleexp) + +// format_float_to_string(arg,width,d,k,dmin) +// ergibt einen String zum Floating-point arg: +// er hat den Wert von abs(arg)*expt(10,k), dabei mind. d Nachkommastellen +// und höchstens die Länge width (width<=0 -> keine Einschränkung). +// Trotzdem wird nicht auf weniger als dmin Stellen gerundet. +struct digits_with_dot { + char * string; // Mit cl_malloc_hook() alloziert, mit cl_free_hook() freizugeben. + uintL length; // strlen(string) + cl_boolean dot_comes_first; // string[0] == '.' ? + cl_boolean dot_comes_last; // string[strlen(string)-1] == '.' ? + uintL dot_position; // string[dot_position] is '.' +// Constructor. + digits_with_dot (char* s, uintL l, cl_boolean df, cl_boolean dl, uintL dp) + : string(s), length(l), dot_comes_first(df), dot_comes_last(dl), dot_position(dp) {} +}; +extern const digits_with_dot format_float_to_string (const cl_F& arg, const sintL width, const sintL d, const sintL k, const sintL dmin); +CL_REQUIRE(cl_fmt_floatstring) + + +#endif /* _CL_FORMAT_H */ diff --git a/src/real/input/Makeflags b/src/real/input/Makeflags new file mode 100644 index 0000000..cd9512e --- /dev/null +++ b/src/real/input/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/real/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/base/string diff --git a/src/real/input/cl_R_from_string.cc b/src/real/input/cl_R_from_string.cc new file mode 100644 index 0000000..a62e904 --- /dev/null +++ b/src/real/input/cl_R_from_string.cc @@ -0,0 +1,26 @@ +// cl_R (const char *) constructor. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real_class.h" + + +// Implementation. + +#include "cl_input.h" +#include "cl_real_io.h" + +cl_read_flags cl_R_read_flags = { + syntax_real, + lsyntax_all, + 10, + { cl_float_format_ffloat, cl_float_format_lfloat_min, cl_true } +}; + +cl_R::cl_R (const char * string) +{ + pointer = as_cl_private_thing( + read_real(cl_R_read_flags,string,NULL,NULL)); +} diff --git a/src/real/input/cl_R_read.cc b/src/real/input/cl_R_read.cc new file mode 100644 index 0000000..eda1ec7 --- /dev/null +++ b/src/real/input/cl_R_read.cc @@ -0,0 +1,266 @@ +// read_real(). +// This file contains a slimmed down version of read_complex(). +// It does not pull in all the complex function code. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real_io.h" + + +// Implementation. + +#include +#include "cl_input.h" +#include "cl_rational_io.h" +#include "cl_integer_io.h" +#include "cl_float_io.h" +#include "cl_integer.h" +#include "cl_I.h" +#include "cl_F.h" +#include "cl_abort.h" + +#undef floor +#include +#define floor cln_floor + +// Step forward over all digits, to the end of string or to the next non-digit. +static const char * skip_digits (const char * ptr, const char * string_limit, unsigned int base) +{ + for ( ; ptr != string_limit; ptr++) { + var char ch = *ptr; + if ((ch >= '0') && (ch <= '9')) + if (ch < '0' + (int)base) + continue; + else + break; + else { + if (base <= 10) + break; + if (((ch >= 'A') && (ch < 'A'-10+(int)base)) + || ((ch >= 'a') && (ch < 'a'-10+(int)base)) + ) + continue; + else + break; + } + } + return ptr; +} + +#define at_end_of_parse(ptr) \ + if (end_of_parse) \ + { *end_of_parse = (ptr); } \ + else \ + { if ((ptr) != string_limit) { read_number_junk((ptr),string,string_limit); } } + +const cl_R read_real (const cl_read_flags& flags, const char * string, const char * string_limit, const char * * end_of_parse) +{ + ASSERT((flags.syntax & ~(syntax_real|syntax_maybe_bad)) == 0); + // If no string_limit is given, it defaults to the end of the string. + if (!string_limit) + string_limit = string + strlen(string); + if (flags.syntax & syntax_rational) { + // Check for rational number syntax. + var unsigned int rational_base = flags.rational_base; + var const char * ptr = string; + if (flags.lsyntax & lsyntax_commonlisp) { + if (ptr == string_limit) goto not_rational_syntax; + if (*ptr == '#') { + // Check for #b, #o, #x, #nR syntax. + ptr++; + if (ptr == string_limit) goto not_rational_syntax; + switch (*ptr) { + case 'b': case 'B': + rational_base = 2; break; + case 'o': case 'O': + rational_base = 8; break; + case 'x': case 'X': + rational_base = 16; break; + default: + var const char * base_end_ptr = + skip_digits(ptr,string_limit,10); + if (base_end_ptr == ptr) goto not_rational_syntax; + if (base_end_ptr == string_limit) goto not_rational_syntax; + if (!((*base_end_ptr == 'r') || (*base_end_ptr == 'R'))) + goto not_rational_syntax; + var cl_I base = read_integer(10,0,ptr,0,base_end_ptr-ptr); + if (!((base >= 2) && (base <= 36))) { + fprint(cl_stderr, "Base must be an integer in the range from 2 to 36, not "); + fprint(cl_stderr, base); + fprint(cl_stderr, "\n"); + cl_abort(); + } + rational_base = FN_to_UL(base); ptr = base_end_ptr; + break; + } + ptr++; + } + } + var const char * ptr_after_prefix = ptr; + var cl_signean sign = 0; + if (ptr == string_limit) goto not_rational_syntax; + switch (*ptr) { + case '-': sign = ~sign; + case '+': ptr++; + default: break; + } + var const char * ptr_after_sign = ptr; + if (flags.syntax & syntax_integer) { + // Check for integer syntax: {'+'|'-'|} {digit}+ {'.'|} + // Allow final dot only in Common Lisp syntax if there was no # prefix. + if ((flags.lsyntax & lsyntax_commonlisp) && (ptr_after_prefix == string)) { + ptr = skip_digits(ptr_after_sign,string_limit,10); + if (ptr != ptr_after_sign) + if (ptr != string_limit) + if (*ptr == '.') { + ptr++; + if ((ptr == string_limit) || !(((*ptr >= '0') && (*ptr <= '9')) || ((*ptr >= 'A') && (*ptr <= 'Z') && (*ptr != 'I')) || ((*ptr >= 'a') && (*ptr <= 'z') && (*ptr != 'i')) || (*ptr == '.') || (*ptr == '_') || (*ptr == '/'))) { + at_end_of_parse(ptr); + return read_integer(10,sign,ptr_after_sign,0,ptr-ptr_after_sign); + } + } + } + ptr = skip_digits(ptr_after_sign,string_limit,rational_base); + if ((ptr == string_limit) || !(((*ptr >= '0') && (*ptr <= '9')) || ((*ptr >= 'A') && (*ptr <= 'Z') && (*ptr != 'I')) || ((*ptr >= 'a') && (*ptr <= 'z') && (*ptr != 'i')) || (*ptr == '.') || (*ptr == '_') || (*ptr == '/'))) { + at_end_of_parse(ptr); + return read_integer(rational_base,sign,ptr_after_sign,0,ptr-ptr_after_sign); + } + } + if (flags.syntax & syntax_ratio) { + // Check for ratio syntax: {'+'|'-'|} {digit}+ '/' {digit}+ + ptr = skip_digits(ptr_after_sign,string_limit,rational_base); + if (ptr != ptr_after_sign) + if (ptr != string_limit) + if (*ptr == '/') { + var const char * ptr_at_slash = ptr; + ptr = skip_digits(ptr_at_slash+1,string_limit,rational_base); + if (ptr != ptr_at_slash+1) + if ((ptr == string_limit) || !(((*ptr >= '0') && (*ptr <= '9')) || ((*ptr >= 'A') && (*ptr <= 'Z') && (*ptr != 'I')) || ((*ptr >= 'a') && (*ptr <= 'z') && (*ptr != 'i')) || (*ptr == '.') || (*ptr == '_') || (*ptr == '/'))) { + at_end_of_parse(ptr); + return read_rational(rational_base,sign,ptr_after_sign,0,ptr_at_slash-ptr_after_sign,ptr-ptr_after_sign); + } + } + } + } +not_rational_syntax: + if (flags.syntax & syntax_float) { + // Check for floating-point number syntax: + // {'+'|'-'|} {digit}+ {'.' {digit}* | } expo {'+'|'-'|} {digit}+ + // {'+'|'-'|} {digit}* '.' {digit}+ expo {'+'|'-'|} {digit}+ + // {'+'|'-'|} {digit}* '.' {digit}+ + var const char * ptr = string; + var const unsigned int float_base = 10; + var cl_signean sign = 0; + if (ptr == string_limit) goto not_float_syntax; + switch (*ptr) { + case '-': sign = ~sign; + case '+': ptr++; + default: break; + } + var const char * ptr_after_sign = ptr; + var const char * ptr_after_intpart = skip_digits(ptr_after_sign,string_limit,float_base); + var cl_boolean have_dot = cl_false; + var const char * ptr_before_fracpart = ptr_after_intpart; + var const char * ptr_after_fracpart = ptr_after_intpart; + ptr = ptr_after_intpart; + if (ptr != string_limit) + if (*ptr == '.') { + have_dot = cl_true; + ptr_before_fracpart = ptr+1; + ptr_after_fracpart = skip_digits(ptr_before_fracpart,string_limit,float_base); + } + ptr = ptr_after_fracpart; + var char exponent_marker; + var cl_boolean have_exponent; + var const char * ptr_in_exponent = ptr; + var const char * ptr_after_exponent = ptr; + if ((ptr == string_limit) || !(((*ptr >= '0') && (*ptr <= '9')) || ((*ptr >= 'A') && (*ptr <= 'Z') && (*ptr != 'I')) || ((*ptr >= 'a') && (*ptr <= 'z') && (*ptr != 'i')) || (*ptr == '.') || (*ptr == '/'))) { + // No exponent. + have_exponent = cl_false; + // Must have at least one fractional part digit. + if (ptr_after_fracpart == ptr_before_fracpart) goto not_float_syntax; + exponent_marker = 'E'; + } else { + have_exponent = cl_true; + // Must have at least one digit. + if (ptr_after_sign == ptr_after_intpart) + if (ptr_after_fracpart == ptr_before_fracpart) + goto not_float_syntax; + exponent_marker = ((*ptr >= 'a') && (*ptr <= 'z') ? *ptr - 'a' + 'A' : *ptr); + switch (exponent_marker) { + case 'E': + case 'S': case 'F': case 'D': case 'L': + break; + default: + goto not_float_syntax; + } + } + if (have_exponent) { + ptr++; + if (ptr == string_limit) goto not_float_syntax; + switch (*ptr) { + case '-': + case '+': ptr++; + default: break; + } + ptr_in_exponent = ptr; + ptr_after_exponent = skip_digits(ptr_in_exponent,string_limit,10); + if (ptr_after_exponent == ptr_in_exponent) goto not_float_syntax; + } + ptr = ptr_after_exponent; + var const char * ptr_after_prec = ptr; + var cl_float_format_t prec; + if ((ptr != string_limit) && (*ptr == '_')) { + ptr++; + ptr_after_prec = skip_digits(ptr,string_limit,10); + if (ptr_after_prec == ptr) goto not_float_syntax; + var cl_I prec1 = digits_to_I(ptr,ptr_after_prec-ptr,10); + var uintL prec2 = cl_I_to_UL(prec1); + prec = (float_base==10 ? cl_float_format(prec2) + : (cl_float_format_t)((uintL)((1+prec2)*log((double)float_base)*1.442695041)+1) + ); + } else { + switch (exponent_marker) { + case 'S': prec = cl_float_format_sfloat; break; + case 'F': prec = cl_float_format_ffloat; break; + case 'D': prec = cl_float_format_dfloat; break; + case 'L': prec = flags.float_flags.default_lfloat_format; break; + case 'E': prec = flags.float_flags.default_float_format; break; + default: NOTREACHED + } + if (flags.float_flags.mantissa_dependent_float_format) { + // Count the number of significant digits. + ptr = ptr_after_sign; + while (ptr < ptr_after_fracpart && (*ptr == '0' || *ptr == '.')) ptr++; + var uintL num_significant_digits = + (ptr_after_fracpart - ptr) - (ptr_before_fracpart > ptr ? 1 : 0); + var uintL prec2 = (num_significant_digits>=2 ? num_significant_digits-2 : 0); + var cl_float_format_t precx = + (float_base==10 ? cl_float_format(prec2) + : (cl_float_format_t)((uintL)((1+prec2)*log((double)float_base)*1.442695041)+1) + ); + if ((uintL)precx > (uintL)prec) + prec = precx; + } + } + floatformatcase(prec + , if (!(flags.syntax & syntax_sfloat)) goto not_float_syntax; + , if (!(flags.syntax & syntax_ffloat)) goto not_float_syntax; + , if (!(flags.syntax & syntax_dfloat)) goto not_float_syntax; + , unused len; + if (!(flags.syntax & syntax_lfloat)) goto not_float_syntax; + ); + at_end_of_parse(ptr_after_prec); + return read_float(float_base,prec,sign,ptr_after_sign,0,ptr_after_fracpart-ptr_after_sign,ptr_after_exponent-ptr_after_sign,ptr_before_fracpart-ptr_after_sign); + } +not_float_syntax: +bad_syntax: + if (flags.syntax & syntax_maybe_bad) { + ASSERT(end_of_parse); + *end_of_parse = string; + return 0; // dummy return + } + read_number_bad_syntax(string,string_limit); +} diff --git a/src/real/input/cl_R_read_stream.cc b/src/real/input/cl_R_read_stream.cc new file mode 100644 index 0000000..5bdc773 --- /dev/null +++ b/src/real/input/cl_R_read_stream.cc @@ -0,0 +1,104 @@ +// read_real(). +// This file contains a slimmed down version of read_complex(). +// It does not pull in all the complex function code. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real_io.h" + + +// Implementation. + +#include "cl_io.h" +#include "cl_spushstring.h" +#include "cl_input.h" + +// We read an entire token (or even more, if it begins with #C) into a +// buffer and then call read_real() on the buffer. + +class pushstring_hack : public cl_spushstring { +public: + char* start_pointer (void) { return buffer; } + char* end_pointer (void) { return buffer+index; } +}; + +static cl_boolean number_char_p (char c) +{ + if ((c >= '0') && (c <= '9')) + return cl_true; + if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'))) + return cl_true; + switch (c) { + case '+': case '-': case '.': case '/': + return cl_true; + default: + return cl_false; + } +} + +const cl_R read_real (cl_istream stream, const cl_read_flags& flags) +{ + // One pre-allocated buffer. This reduces the allocation/free cost. + static pushstring_hack buffer; + + var int c; + // Skip whitespace at the beginning. + loop { + c = freadchar(stream); + if (c == cl_EOF) goto eof; + if ((c == ' ') || (c == '\t') || (c == '\n')) + continue; + else + break; + } + // Found first non-whitespace character. + // Numbers cannot cross lines. We can treat EOF and '\n' the same way. + buffer.reset(); + if (c == '#') { + if (!(flags.lsyntax & lsyntax_commonlisp)) + goto syntax1; + buffer.push(c); + // Read some digits, then a letter, then a token. + loop { + c = freadchar(stream); + if (c == cl_EOF) goto eof; + buffer.push(c); + if ((c >= '0') && (c <= '9')) + continue; + else + break; + } + if (!(((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')))) + goto syntax1; + buffer.push(c); + c = freadchar(stream); + if (c == cl_EOF) goto eof; + } + // Read a number token. + if (!number_char_p(c)) + goto syntax1; + loop { + buffer.push(c); + c = freadchar(stream); + if (c == cl_EOF) + break; + if (!number_char_p(c)) { + funreadchar(stream,c); + break; + } + } + // Parse the number. + return read_real(flags, + buffer.start_pointer(), buffer.end_pointer(), + NULL + ); + + // Handle syntax error. +syntax1: buffer.push(c); + read_number_bad_syntax(buffer.start_pointer(),buffer.end_pointer()); + + // Handle premature EOF. +eof: read_number_eof(); +} diff --git a/src/real/misc/Makeflags b/src/real/misc/Makeflags new file mode 100644 index 0000000..0e9a378 --- /dev/null +++ b/src/real/misc/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/real/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/float/sfloat/elem -I$(srcdir)/float/sfloat/misc -I$(srcdir)/float/ffloat/elem -I$(srcdir)/float/ffloat/misc -I$(srcdir)/float/dfloat/elem -I$(srcdir)/float/dfloat/misc -I$(srcdir)/float/lfloat/elem -I$(srcdir)/float/lfloat/misc -I$(srcdir)/rational/misc -I$(srcdir)/integer/misc diff --git a/src/real/misc/cl_R_abs.cc b/src/real/misc/cl_R_abs.cc new file mode 100644 index 0000000..8c8601c --- /dev/null +++ b/src/real/misc/cl_R_abs.cc @@ -0,0 +1,20 @@ +// abs(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +const cl_R abs (const cl_R& x) +{ + // Methode: + // Bei x<0: (- x), sonst x. + if (minusp(x)) + return -x; + else + return x; +} diff --git a/src/real/misc/cl_R_as.cc b/src/real/misc/cl_R_as.cc new file mode 100644 index 0000000..555614a --- /dev/null +++ b/src/real/misc/cl_R_as.cc @@ -0,0 +1,42 @@ +// as_cl_R(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_N.h" + +// Cf. cl_R_p in cl_R_ring.cc. +// But here, for better inlining in g++, it is preferrable to finish every +// alternative with either "return cl_true;" or "return cl_false;". + +inline cl_boolean cl_R_p (const cl_number& x) +{ + if (!x.pointer_p()) + switch (x.nonpointer_tag()) { + case cl_FN_tag: + case cl_SF_tag: + #if defined(CL_WIDE_POINTERS) + case cl_FF_tag: + #endif + return cl_true; + } + else + if (x.pointer_type()->flags & cl_class_flags_subclass_real) + return cl_true; + return cl_false; +} + +const cl_R& as_cl_R (const cl_number& x, const char * filename, int line) +{ + if (cl_R_p(x)) { + DeclareType(cl_R,x); + return x; + } else + cl_as_error(x,"a real number",filename,line); +} diff --git a/src/real/misc/cl_R_contagion.cc b/src/real/misc/cl_R_contagion.cc new file mode 100644 index 0000000..a02d460 --- /dev/null +++ b/src/real/misc/cl_R_contagion.cc @@ -0,0 +1,43 @@ +// contagion(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_R.h" + + +// Implementation. + +#include "cl_LF.h" + +const cl_R contagion (const cl_R& x, const cl_R& y) +{ +#define X { return x; } +#define Y { return y; } +#if 0 + if (R_rationalp(x)) Y + elif (R_rationalp(y)) X + else + floattypecase(x + , X // floattypecase(y, X,X,X,X) + , floattypecase(y, Y,X,X,X) + , floattypecase(y, Y,Y,X,X) + , floattypecase(y, Y,Y,Y, + if (TheLfloat(x)->len <= TheLfloat(y)->len) X else Y + ) + ); +#else // faster type dispatch + realtypecase(x + , Y + , Y + , Y + , X // realtypecase(y, X,X,X, X,X,X,X) + , realtypecase(y, X,X,X, Y,X,X,X) + , realtypecase(y, X,X,X, Y,Y,X,X) + , realtypecase(y, X,X,X, Y,Y,Y, + if (TheLfloat(x)->len <= TheLfloat(y)->len) X else Y + ) + ); +#endif +} diff --git a/src/real/misc/cl_R_debug.cc b/src/real/misc/cl_R_debug.cc new file mode 100644 index 0000000..8525c1a --- /dev/null +++ b/src/real/misc/cl_R_debug.cc @@ -0,0 +1,25 @@ +// cl_R debugging support. + +// General includes. +#include "cl_sysdep.h" + +// Specification. + + +// Implementation. + +// This dummy links in this module when requires it. +int cl_R_debug_module; + +extern int cl_SF_debug_module; +extern int cl_FF_debug_module; +extern int cl_DF_debug_module; +extern int cl_LF_debug_module; +extern int cl_RA_debug_module; +static void* dummy[] = { &dummy, + &cl_SF_debug_module, + &cl_FF_debug_module, + &cl_DF_debug_module, + &cl_LF_debug_module, + &cl_RA_debug_module +}; diff --git a/src/real/misc/cl_R_eqhashcode.cc b/src/real/misc/cl_R_eqhashcode.cc new file mode 100644 index 0000000..be89b0c --- /dev/null +++ b/src/real/misc/cl_R_eqhashcode.cc @@ -0,0 +1,27 @@ +// cl_R equal_hashcode(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_N.h" +#include "cl_R.h" +#include "cl_RA.h" +#include "cl_I.h" +#include "cl_F.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_I_eqhashcode.cc" +#include "cl_SF_eqhashcode.cc" +#include "cl_FF_eqhashcode.cc" +#include "cl_DF_eqhashcode.cc" +#include "cl_LF_eqhashcode.cc" + +uint32 cl_equal_hashcode (const cl_R& x) +GEN_R_OP1_7(x, cl_equal_hashcode, return) diff --git a/src/real/misc/cl_R_expt.cc b/src/real/misc/cl_R_expt.cc new file mode 100644 index 0000000..4d0e013 --- /dev/null +++ b/src/real/misc/cl_R_expt.cc @@ -0,0 +1,54 @@ +// expt(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_rational.h" +#include "cl_integer.h" + +// Methode: +// Für y>0: +// a:=x, b:=y. +// Solange b gerade, setze a:=a*a, b:=b/2. [a^b bleibt invariant, = x^y.] +// c:=a. +// Solange b:=floor(b/2) >0 ist, +// setze a:=a*a, und falls b ungerade, setze c:=a*c. +// Ergebnis c. +// Für y=0: Ergebnis 1. +// Für y<0: (/ (expt x (- y))). + +// Assume y>0. +inline const cl_R expt_pos (const cl_R& x, uintL y) +{ + if (rationalp(x)) { + DeclareType(cl_RA,x); + return expt(x,y); // x rational -> schnellere Routine + } else { + DeclareType(cl_F,x); + var cl_F a = x; + var uintL b = y; + while (!(b % 2)) { a = square(a); b = b >> 1; } + var cl_F c = a; + until (b == 1) + { b = b >> 1; + a = square(a); + if (b % 2) { c = a * c; } + } + return c; + } +} + +const cl_R expt (const cl_R& x, sintL y) +{ + if (y==0) { return 1; } // y=0 -> Ergebnis 1 + var uintL abs_y = (y<0 ? (uintL)(-y) : y); // Betrag von y nehmen + var cl_R z = expt_pos(x,abs_y); // (expt x (abs y)) + return (y<0 ? recip(z) : z); // evtl. noch Kehrwert nehmen +} diff --git a/src/real/misc/cl_R_expt_I.cc b/src/real/misc/cl_R_expt_I.cc new file mode 100644 index 0000000..93db843 --- /dev/null +++ b/src/real/misc/cl_R_expt_I.cc @@ -0,0 +1,56 @@ +// expt(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_rational.h" +#include "cl_integer.h" +#include "cl_I.h" + +// Methode: +// Für y>0: +// a:=x, b:=y. +// Solange b gerade, setze a:=a*a, b:=b/2. [a^b bleibt invariant, = x^y.] +// c:=a. +// Solange b:=floor(b/2) >0 ist, +// setze a:=a*a, und falls b ungerade, setze c:=a*c. +// Ergebnis c. +// Für y=0: Ergebnis 1. +// Für y<0: (/ (expt x (- y))). + +// Assume y>0. +inline const cl_R expt_pos (const cl_R& x, const cl_I& y) +{ + if (rationalp(x)) { + DeclareType(cl_RA,x); + return expt(x,y); // x rational -> schnellere Routine + } else { + DeclareType(cl_F,x); + var cl_F a = x; + var cl_I b = y; + while (!oddp(b)) { a = square(a); b = b >> 1; } + var cl_F c = a; + until (eq(b,1)) + { b = b >> 1; + a = square(a); + if (oddp(b)) { c = a * c; } + } + return c; + } +} + +const cl_R expt (const cl_R& x, const cl_I& y) +{ + if (eq(y,0)) { return 1; } // y=0 -> Ergebnis 1 + var cl_boolean y_negative = minusp(y); + var cl_I abs_y = (y_negative ? -y : y); // Betrag von y nehmen + var cl_R z = expt_pos(x,abs_y); // (expt x (abs y)) + return (y_negative ? recip(z) : z); // evtl. noch Kehrwert nehmen +} diff --git a/src/real/misc/cl_R_max.cc b/src/real/misc/cl_R_max.cc new file mode 100644 index 0000000..b353887 --- /dev/null +++ b/src/real/misc/cl_R_max.cc @@ -0,0 +1,15 @@ +// max(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +const cl_R max (const cl_R& x, const cl_R& y) +{ + return (x >= y ? x : y); +} diff --git a/src/real/misc/cl_R_min.cc b/src/real/misc/cl_R_min.cc new file mode 100644 index 0000000..6b5861c --- /dev/null +++ b/src/real/misc/cl_R_min.cc @@ -0,0 +1,15 @@ +// min(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +const cl_R min (const cl_R& x, const cl_R& y) +{ + return (x <= y ? x : y); +} diff --git a/src/real/misc/cl_R_rational.cc b/src/real/misc/cl_R_rational.cc new file mode 100644 index 0000000..fdace63 --- /dev/null +++ b/src/real/misc/cl_R_rational.cc @@ -0,0 +1,15 @@ +// rational(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" + +const cl_RA rational (const cl_R& x) +GEN_R_OP1_2(x, rational, return) diff --git a/src/real/misc/cl_R_rationalize.cc b/src/real/misc/cl_R_rationalize.cc new file mode 100644 index 0000000..f5e43f1 --- /dev/null +++ b/src/real/misc/cl_R_rationalize.cc @@ -0,0 +1,113 @@ +// rationalize(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_float.h" +#include "cl_rational.h" +#include "cl_integer.h" +#include "cl_RA.h" +#include "cl_I.h" + +// Methode (rekursiv dargestellt): +// Falls x rational ist: x. +// Falls x=0.0: 0. +// Falls x<0.0: (- (rationalize (- x))) +// Falls x>0.0: +// (Integer-Decode-Float x) liefert m,e,s=1. +// Falls e>=0 : Liefere x=m*2^e als Ergebnis. +// Suche rationale Zahl zwischen a=(m-1/2)*2^e und b=(m+1/2)*2^e mit +// möglichst kleinem Zähler und Nenner. (a,b einschließlich, aber da a,b +// den Nenner 2^(|e|+1) haben, während x selbst den Nenner <=2^|e| hat, +// können weder a noch b als Ergebnis herauskommen.) +// Suche also bei gegebenem a,b (0=0 -> m*2^e*s als Ergebnis (darin ist x=0.0 inbegriffen). +// Bilde a:=(2*m-1)*2^(e-1) und b:=(2*m+1)*2^(e-1), rationale Zahlen >0, +// (unkürzbar, da Nenner Zweierpotenz und Zähler ungerade). +// Starte Kettenbruchentwicklung (d.h. p[-1]:=0, p[0]:=1, q[-1]:=1, q[0]:=0, i:=0.) +// Schleife: +// c:=(ceiling a) +// if c>=b then k:=c-1, "Ziffer k", (a,b) := (1/(b-k),1/(a-k)), goto Schleife +// "Ziffer c". +// (Dabei bedeutet "Ziffer a" die Iteration +// i:=i+1, p[i]:=a*p[i-1]+p[i-2], q[i]:=a*q[i-1]+q[i-2].) +// Ende, liefere s * (p[i]/q[i]), das ist wegen der Invarianten +// p[i]*q[i-1]-p[i-1]*q[i]=(-1)^i ein bereits gekürzter Bruch. + +inline const cl_RA rationalize (const cl_RA& x) +{ + // x rational -> x als Ergebnis. + return x; +} + +inline const cl_RA rationalize (const cl_F& x) +{ + var cl_idecoded_float x_decoded = integer_decode_float(x); + var cl_I& m = x_decoded.mantissa; + var cl_I& e = x_decoded.exponent; + var cl_I& s = x_decoded.sign; + if (!minusp(e)) { + // e>=0. + var cl_I y = ash(m,e); + if (minusp(s)) { y = -y; } + return y; + } + // e<0. + var cl_I m2 = ash(m,1); // 2*m + var cl_I num1 = minus1(m2); // 2*m-1 + var cl_I num2 = plus1(m2); // 2*m+1 + var cl_I den = ash(1,plus1(-e)); // 2^(1-e) + var cl_RA a = I_I_to_RT(num1,den); // a := (2*m-1)/(2^(1-e)) + var cl_RA b = I_I_to_RT(num2,den); // b := (2*m+1)/(2^(1-e)) + var cl_I p_iminus1 = 0; // p[i-1] + var cl_I p_i = 1; // p[i] + var cl_I q_iminus1 = 1; // q[i-1] + var cl_I q_i = 0; // q[i] + var cl_I c; + for (;;) { + c = ceiling1(a); + if (c < b) + break; + var cl_I k = minus1(c); // k = c-1 + { + var cl_I p_iplus1 = k * p_i + p_iminus1; + p_iminus1 = p_i; p_i = p_iplus1; + } + { + var cl_I q_iplus1 = k * q_i + q_iminus1; + q_iminus1 = q_i; q_i = q_iplus1; + } + { + var cl_RA new_b = recip(a-k); // 1/(a-k) + var cl_RA new_a = recip(b-k); // 1/(b-k) + a = new_a; b = new_b; + } + } + // letzte "Ziffer" k=c : + var cl_I p_last = c * p_i + p_iminus1; + var cl_I q_last = c * q_i + q_iminus1; + if (minusp(s)) + p_last = - p_last; + return I_I_to_RA(p_last,q_last); // +-p[i] / q[i] bilden +} + +const cl_RA rationalize (const cl_R& x) +GEN_R_OP1_2(x, rationalize, return) diff --git a/src/real/misc/cl_R_signum.cc b/src/real/misc/cl_R_signum.cc new file mode 100644 index 0000000..0653a03 --- /dev/null +++ b/src/real/misc/cl_R_signum.cc @@ -0,0 +1,26 @@ +// signum(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" + +#undef MAYBE_INLINE +#define MAYBE_INLINE inline +#include "cl_I_signum.cc" +#include "cl_RA_signum.cc" +#undef MAYBE_INLINE2 +#define MAYBE_INLINE2 inline +#include "cl_SF_signum.cc" +#include "cl_FF_signum.cc" +#include "cl_DF_signum.cc" +#include "cl_LF_signum.cc" + +const cl_R signum (const cl_R& x) +GEN_R_OP1_7(x, signum, return) diff --git a/src/real/output/Makeflags b/src/real/output/Makeflags new file mode 100644 index 0000000..635f2c3 --- /dev/null +++ b/src/real/output/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/real/Makeflags +SUBDIR_INCLUDES += diff --git a/src/real/output/cl_R_aprint.cc b/src/real/output/cl_R_aprint.cc new file mode 100644 index 0000000..e1c4472 --- /dev/null +++ b/src/real/output/cl_R_aprint.cc @@ -0,0 +1,17 @@ +// print_real(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real_io.h" + + +// Implementation. + +#include "cl_output.h" + +void print_real (cl_ostream stream, const cl_print_flags& flags, const cl_R& z) +{ + print_real(stream,(const cl_print_number_flags&)flags,z); +} diff --git a/src/real/output/cl_R_bprint.cc b/src/real/output/cl_R_bprint.cc new file mode 100644 index 0000000..f346060 --- /dev/null +++ b/src/real/output/cl_R_bprint.cc @@ -0,0 +1,17 @@ +// print_real(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real_io.h" + + +// Implementation. + +#include "cl_output.h" + +void print_real (cl_ostream stream, const cl_print_number_flags& flags, const cl_R& z) +{ + print_real(stream,(const cl_print_real_flags&)flags,z); +} diff --git a/src/real/output/cl_R_cprint.cc b/src/real/output/cl_R_cprint.cc new file mode 100644 index 0000000..317ee46 --- /dev/null +++ b/src/real/output/cl_R_cprint.cc @@ -0,0 +1,28 @@ +// print_real(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real_io.h" + + +// Implementation. + +#include "cl_real.h" +#include "cl_R.h" +#include "cl_rational_io.h" +#include "cl_float_io.h" + +void print_real (cl_ostream stream, const cl_print_real_flags& flags, const cl_R& z) +{ + if (rationalp(z)) { + DeclareType(cl_RA,z); + // rationale Zahl + print_rational(stream,flags,z); + } else { + DeclareType(cl_F,z); + // Float + print_float(stream,flags,z); + } +} diff --git a/src/real/random/Makeflags b/src/real/random/Makeflags new file mode 100644 index 0000000..635f2c3 --- /dev/null +++ b/src/real/random/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/real/Makeflags +SUBDIR_INCLUDES += diff --git a/src/real/random/cl_R_random.cc b/src/real/random/cl_R_random.cc new file mode 100644 index 0000000..1d9b3ff --- /dev/null +++ b/src/real/random/cl_R_random.cc @@ -0,0 +1,37 @@ +// random_R(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_R.h" +#include "cl_RA.h" +#include "cl_io.h" +#include "cl_real_io.h" +#include "cl_abort.h" + +const cl_R random_R (cl_random_state& r, const cl_R& n) +{ + // n muß eine reelle Zahl sein, >0 und Float oder Integer + if (plusp(n)) { + if (floatp(n)) { + DeclareType(cl_F,n); + return random_F(r,n); + } else { + DeclareType(cl_RA,n); + if (integerp(n)) { + DeclareType(cl_I,n); + return random_I(r,n); + } + } + } + fprint(cl_stderr, "random: argument should be positive and an integer or float: "); + fprint(cl_stderr, n); + fprint(cl_stderr, "\n"); + cl_abort(); +} diff --git a/src/real/ring/Makeflags b/src/real/ring/Makeflags new file mode 100644 index 0000000..635f2c3 --- /dev/null +++ b/src/real/ring/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/real/Makeflags +SUBDIR_INCLUDES += diff --git a/src/real/ring/cl_R_ring.cc b/src/real/ring/cl_R_ring.cc new file mode 100644 index 0000000..1105bbe --- /dev/null +++ b/src/real/ring/cl_R_ring.cc @@ -0,0 +1,160 @@ +// Ring of real numbers. + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_R_ring) + +// Specification. +#include "cl_real_ring.h" + + +// Implementation. + +#include "cl_real.h" +#include "cl_R.h" +#include "cl_io.h" +#include "cl_real_io.h" + +static void R_fprint (cl_heap_ring* R, cl_ostream stream, const _cl_ring_element& x) +{ + unused R; + fprint(stream,The(cl_R)(x)); +} + +static cl_boolean R_equal (cl_heap_ring* R, const _cl_ring_element& x, const _cl_ring_element& y) +{ + unused R; + return cl_equal(The(cl_R)(x),The(cl_R)(y)); +} + +static const _cl_ring_element R_zero (cl_heap_ring* R) +{ + return _cl_ring_element(R, (cl_R)0); +} + +static cl_boolean R_zerop (cl_heap_ring* R, const _cl_ring_element& x) +{ + unused R; + // Here we return true only if x is the *exact* zero. Because we + // don't want the degree of polynomials to depend on rounding errors. + // For all ring theoretic purposes, we treat 0.0 as if it were a + // zero divisor. + return exact_zerop(The(cl_R)(x)); +} + +static const _cl_ring_element R_plus (cl_heap_ring* R, const _cl_ring_element& x, const _cl_ring_element& y) +{ + return _cl_ring_element(R, The(cl_R)(x) + The(cl_R)(y)); +} + +static const _cl_ring_element R_minus (cl_heap_ring* R, const _cl_ring_element& x, const _cl_ring_element& y) +{ + return _cl_ring_element(R, The(cl_R)(x) - The(cl_R)(y)); +} + +static const _cl_ring_element R_uminus (cl_heap_ring* R, const _cl_ring_element& x) +{ + return _cl_ring_element(R, - The(cl_R)(x)); +} + +static const _cl_ring_element R_one (cl_heap_ring* R) +{ + return _cl_ring_element(R, (cl_R)1); +} + +static const _cl_ring_element R_canonhom (cl_heap_ring* R, const cl_I& x) +{ + return _cl_ring_element(R, (cl_R)x); +} + +static const _cl_ring_element R_mul (cl_heap_ring* R, const _cl_ring_element& x, const _cl_ring_element& y) +{ + return _cl_ring_element(R, The(cl_R)(x) * The(cl_R)(y)); +} + +static const _cl_ring_element R_square (cl_heap_ring* R, const _cl_ring_element& x) +{ + return _cl_ring_element(R, square(The(cl_R)(x))); +} + +static const _cl_ring_element R_expt_pos (cl_heap_ring* R, const _cl_ring_element& x, const cl_I& y) +{ + return _cl_ring_element(R, expt(The(cl_R)(x),y)); +} + +static cl_boolean cl_R_p (const cl_number& x) +{ + return (cl_boolean) + (!x.pointer_p() + || (x.pointer_type()->flags & cl_class_flags_subclass_real) != 0 + ); +} + +static cl_ring_setops R_setops = { + R_fprint, + R_equal +}; +static cl_ring_addops R_addops = { + R_zero, + R_zerop, + R_plus, + R_minus, + R_uminus +}; +static cl_ring_mulops R_mulops = { + R_one, + R_canonhom, + R_mul, + R_square, + R_expt_pos +}; + +static cl_number_ring_ops R_ops = { + cl_R_p, + cl_equal, + exact_zerop, + operator+, + operator-, + operator-, + operator*, + square, + expt +}; + +class cl_heap_real_ring : public cl_heap_number_ring { + SUBCLASS_cl_heap_ring() +public: + // Constructor. + cl_heap_real_ring () + : cl_heap_number_ring (&R_setops,&R_addops,&R_mulops, + (cl_number_ring_ops*) &R_ops) + { type = &cl_class_real_ring; } + // Destructor. + ~cl_heap_real_ring () {} +}; + +static void cl_real_ring_destructor (cl_heap* pointer) +{ + (*(cl_heap_real_ring*)pointer).~cl_heap_real_ring(); +} + +static void cl_real_ring_dprint (cl_heap* pointer) +{ + unused pointer; + fprint(cl_debugout, "(cl_real_ring) cl_R_ring"); +} + +cl_class cl_class_real_ring = { + cl_real_ring_destructor, + cl_class_flags_number_ring, + cl_real_ring_dprint +}; + +// Constructor. +inline cl_real_ring::cl_specialized_number_ring () + : cl_number_ring (new cl_heap_real_ring()) {} + +const cl_real_ring cl_R_ring; + +CL_PROVIDE_END(cl_R_ring) diff --git a/src/real/transcendental/Makeflags b/src/real/transcendental/Makeflags new file mode 100644 index 0000000..ceec96e --- /dev/null +++ b/src/real/transcendental/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/real/Makeflags +SUBDIR_INCLUDES += -I$(srcdir)/float/transcendental diff --git a/src/real/transcendental/cl_R_atan.cc b/src/real/transcendental/cl_R_atan.cc new file mode 100644 index 0000000..be80b3e --- /dev/null +++ b/src/real/transcendental/cl_R_atan.cc @@ -0,0 +1,17 @@ +// atan(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +const cl_R atan (const cl_R& x) +{ +// Methode: +// arctan(x) = arctan(X=1,Y=x). + return atan(1,x); +} diff --git a/src/real/transcendental/cl_R_atan2.cc b/src/real/transcendental/cl_R_atan2.cc new file mode 100644 index 0000000..1e967a9 --- /dev/null +++ b/src/real/transcendental/cl_R_atan2.cc @@ -0,0 +1,84 @@ +// atan(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_float.h" +#include "cl_F_tran.h" +#include "cl_N.h" +#include "cl_R.h" + +const cl_R atan (const cl_R& x, const cl_R& y) +{ +// Methode: +// y=0 -> bei x>0: 0 als Ergebnis, +// bei x<0: pi als Ergebnis. +// bei x=0: Error. +// x=0 -> bei y>0: pi/2 als Ergebnis. +// bei y<0: -pi/2 als Ergebnis. +// bei y=0: Error. +// Falls x und y beide rational: beide in Floats umwandeln. +// 0 <= |y| <= x -> atan(y/x) +// 0 <= |x| <= y -> pi/2 - atan(x/y) +// 0 <= |x| <= -y -> -pi/2 - atan(x/y) +// 0 <= |y| <= -x -> für y>=0: pi + atan(y/x), für y<0: -pi + atan(y/x) + + if (eq(y,0)) { + // y=0 (exakt) + if (zerop(x)) // x=0 -> Error + { cl_error_division_by_0(); } + if (minusp(x)) // x<0 -> pi in Default-Float-Genauigkeit + { return cl_pi(); } + return 0; // x>0 -> 0 + } + elif (eq(x,0)) { + // x=0 (exakt) + if (zerop(y)) // y=0 -> Error + { cl_error_division_by_0(); } + if (minusp(y)) // y<0 -> -pi/2 + { return - scale_float(cl_pi(),-1); } + return scale_float(cl_pi(),-1); // y>0 -> pi/2 + } else { + Mutable(cl_R,x); + Mutable(cl_R,y); + // Check special case of rational numbers: + if (rationalp(x)) + if (rationalp(y)) { + // x,y in Floats umwandeln: + x = cl_float(The(cl_RA)(x)); + y = cl_float(The(cl_RA)(y)); + } + // x,y nicht exakt =0, x/y und y/x werden Floats sein. + if (abs(x) >= abs(y)) { + // |x| >= |y| + var cl_F z = atanx(The(cl_F)(y/x)); + // Division war erfolgreich, also x/=0. + if (minusp(x)) + // x<0 -> pi bzw. -pi addieren: + if (!minusp(y)) + // y>=0 -> atan(y/x) + pi + return z + cl_pi(z); + else + // y<0 -> atan(y/x) - pi + return z - cl_pi(z); + else + return z; + } else { + // |x| < |y| + var cl_F z = atanx(The(cl_F)(x/y)); + // von pi/2 bzw. -pi/2 subtrahieren: + if (!minusp(y)) + // y>=0 -> pi/2 - atan(x/y) + return scale_float(cl_pi(z),-1) - z; + else + // y<0 -> -pi/2 - atan(x/y) + return - scale_float(cl_pi(z),-1) - z; + } + } +} diff --git a/src/real/transcendental/cl_R_cos.cc b/src/real/transcendental/cl_R_cos.cc new file mode 100644 index 0000000..5630d1a --- /dev/null +++ b/src/real/transcendental/cl_R_cos.cc @@ -0,0 +1,30 @@ +// cos(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_float.h" +#include "cl_R.h" + +const cl_R cos (const cl_R& x) +{ +// Methode: +// x rational -> bei x=0 1 als Ergebnis, sonst x in Float umwandeln. +// x Float -> bekannt. + + if (rationalp(x)) { + DeclareType(cl_RA,x); + if (zerop(x)) // x=0 -> 1 als Ergebnis + return 1; + return cos(cl_float(x)); // sonst in Float umwandeln + } else { + DeclareType(cl_F,x); + return cos(x); + } +} diff --git a/src/real/transcendental/cl_R_cosh.cc b/src/real/transcendental/cl_R_cosh.cc new file mode 100644 index 0000000..52b7ed4 --- /dev/null +++ b/src/real/transcendental/cl_R_cosh.cc @@ -0,0 +1,30 @@ +// cosh(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_float.h" +#include "cl_R.h" + +const cl_R cosh (const cl_R& x) +{ +// Methode: +// x rational -> bei x=0 1 als Ergebnis, sonst x in Float umwandeln. +// x Float -> bekannt. + + if (rationalp(x)) { + DeclareType(cl_RA,x); + if (zerop(x)) // x=0 -> 1 als Ergebnis + return 1; + return cosh(cl_float(x)); // sonst in Float umwandeln + } else { + DeclareType(cl_F,x); + return cosh(x); + } +} diff --git a/src/real/transcendental/cl_R_coshsinh.cc b/src/real/transcendental/cl_R_coshsinh.cc new file mode 100644 index 0000000..fc341de --- /dev/null +++ b/src/real/transcendental/cl_R_coshsinh.cc @@ -0,0 +1,30 @@ +// cl_cosh_sinh(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_float.h" +#include "cl_R.h" + +const cl_cosh_sinh_t cl_cosh_sinh (const cl_R& x) +{ +// Methode: +// x rational -> bei x=0 (1,0) als Ergebnis, sonst x in Float umwandeln. +// x Float -> bekannt. + + if (rationalp(x)) { + DeclareType(cl_RA,x); + if (zerop(x)) // x=0 -> (1,0) als Ergebnis + return cl_cosh_sinh_t(1,0); + return cl_cosh_sinh(cl_float(x)); // sonst in Float umwandeln + } else { + DeclareType(cl_F,x); + return cl_cosh_sinh(x); + } +} diff --git a/src/real/transcendental/cl_R_cossin.cc b/src/real/transcendental/cl_R_cossin.cc new file mode 100644 index 0000000..0a3fc7e --- /dev/null +++ b/src/real/transcendental/cl_R_cossin.cc @@ -0,0 +1,30 @@ +// cl_cos_sin(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_float.h" +#include "cl_R.h" + +const cl_cos_sin_t cl_cos_sin (const cl_R& x) +{ +// Methode: +// x rational -> bei x=0 (1,0) als Ergebnis, sonst x in Float umwandeln. +// x Float -> bekannt. + + if (rationalp(x)) { + DeclareType(cl_RA,x); + if (zerop(x)) // x=0 -> (1,0) als Ergebnis + return cl_cos_sin_t(1,0); + return cl_cos_sin(cl_float(x)); // sonst in Float umwandeln + } else { + DeclareType(cl_F,x); + return cl_cos_sin(x); + } +} diff --git a/src/real/transcendental/cl_R_exp.cc b/src/real/transcendental/cl_R_exp.cc new file mode 100644 index 0000000..1c62b07 --- /dev/null +++ b/src/real/transcendental/cl_R_exp.cc @@ -0,0 +1,30 @@ +// exp(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_float.h" +#include "cl_R.h" + +const cl_R exp (const cl_R& x) +{ +// Methode: +// x rational -> bei x=0 1 als Ergebnis, sonst x in Float umwandeln. +// x Float -> bekannt. + + if (rationalp(x)) { + DeclareType(cl_RA,x); + if (zerop(x)) // x=0 -> 1 als Ergebnis + return 1; + return exp(cl_float(x)); // sonst in Float umwandeln + } else { + DeclareType(cl_F,x); + return exp(x); + } +} diff --git a/src/real/transcendental/cl_R_ln.cc b/src/real/transcendental/cl_R_ln.cc new file mode 100644 index 0000000..7862428 --- /dev/null +++ b/src/real/transcendental/cl_R_ln.cc @@ -0,0 +1,30 @@ +// ln(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_float.h" +#include "cl_R.h" + +const cl_R ln (const cl_R& x) +{ +// Methode: +// x rational -> bei x=1 0 als Ergebnis, sonst x in Float umwandeln. +// x Float -> bekannt. + + if (rationalp(x)) { + DeclareType(cl_RA,x); + if (x == 1) // x=1 -> 0 als Ergebnis + return 0; + return ln(cl_float(x)); // sonst in Float umwandeln + } else { + DeclareType(cl_F,x); + return ln(x); + } +} diff --git a/src/real/transcendental/cl_R_log.cc b/src/real/transcendental/cl_R_log.cc new file mode 100644 index 0000000..f183e3a --- /dev/null +++ b/src/real/transcendental/cl_R_log.cc @@ -0,0 +1,51 @@ +// log(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_N.h" +#include "cl_R.h" +#include "cl_rational.h" +#include "cl_float.h" + +const cl_R log (const cl_R& a, const cl_R& b) +{ +// Methode: +// a und b rational: +// b=1 -> Error +// log(a,b) rational errechenbar -> liefern. +// Sonst a und b in Floats umwandeln. +// a Float, b rational -> bei b=1 Error, sonst b := (float b a) +// a rational, b Float -> bei a=1 Ergebnis 0, sonst a := (float a b) +// a,b Floats -> log(a,b) = ln(a)/ln(b) + { Mutable(cl_R,a); + Mutable(cl_R,b); + if (rationalp(b)) { + // b rational + if (eq(b,1)) { cl_error_division_by_0(); } + if (rationalp(a)) { + // a,b beide rational + var cl_RA l; + if (logp(The(cl_RA)(a),The(cl_RA)(b),&l)) + return l; + // a,b beide in Floats umwandeln: + a = cl_float(The(cl_RA)(a)); b = cl_float(The(cl_RA)(b)); + } else + // a Float + b = cl_float(The(cl_RA)(b),The(cl_F)(a)); // b := (float b a) + } else { + // b Float + if (rationalp(a)) { + if (eq(a,1)) { return 0; } // a=1 -> Ergebnis 0 + a = cl_float(The(cl_RA)(a),The(cl_F)(b)); // a := (float a b) + } + } + // Nun a,b beide Floats. + return ln(The(cl_F)(a)) / ln(The(cl_F)(b)); +}} diff --git a/src/real/transcendental/cl_R_sin.cc b/src/real/transcendental/cl_R_sin.cc new file mode 100644 index 0000000..045ea25 --- /dev/null +++ b/src/real/transcendental/cl_R_sin.cc @@ -0,0 +1,30 @@ +// sin(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_float.h" +#include "cl_R.h" + +const cl_R sin (const cl_R& x) +{ +// Methode: +// x rational -> bei x=0 0 als Ergebnis, sonst x in Float umwandeln. +// x Float -> bekannt. + + if (rationalp(x)) { + DeclareType(cl_RA,x); + if (zerop(x)) // x=0 -> 0 als Ergebnis + return 0; + return sin(cl_float(x)); // sonst in Float umwandeln + } else { + DeclareType(cl_F,x); + return sin(x); + } +} diff --git a/src/real/transcendental/cl_R_sinh.cc b/src/real/transcendental/cl_R_sinh.cc new file mode 100644 index 0000000..85d53c0 --- /dev/null +++ b/src/real/transcendental/cl_R_sinh.cc @@ -0,0 +1,30 @@ +// sinh(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +#include "cl_float.h" +#include "cl_R.h" + +const cl_R sinh (const cl_R& x) +{ +// Methode: +// x rational -> bei x=0 0 als Ergebnis, sonst x in Float umwandeln. +// x Float -> bekannt. + + if (rationalp(x)) { + DeclareType(cl_RA,x); + if (zerop(x)) // x=0 -> 0 als Ergebnis + return 0; + return sinh(cl_float(x)); // sonst in Float umwandeln + } else { + DeclareType(cl_F,x); + return sinh(x); + } +} diff --git a/src/real/transcendental/cl_R_tan.cc b/src/real/transcendental/cl_R_tan.cc new file mode 100644 index 0000000..d155217 --- /dev/null +++ b/src/real/transcendental/cl_R_tan.cc @@ -0,0 +1,19 @@ +// tan(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +MAYBE_INLINE +const cl_R tan (const cl_R& x) +{ +// Methode: +// (/ (sin x) (cos x)) + var cl_cos_sin_t trig = cl_cos_sin(x); + return trig.sin / trig.cos; +} diff --git a/src/real/transcendental/cl_R_tanh.cc b/src/real/transcendental/cl_R_tanh.cc new file mode 100644 index 0000000..04be1ec --- /dev/null +++ b/src/real/transcendental/cl_R_tanh.cc @@ -0,0 +1,19 @@ +// tanh(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_real.h" + + +// Implementation. + +MAYBE_INLINE +const cl_R tanh (const cl_R& x) +{ +// Methode: +// (/ (sinh x) (cosh x)) + var cl_cosh_sinh_t hyp = cl_cosh_sinh(x); + return hyp.sinh / hyp.cosh; +} diff --git a/src/timing/Makeflags b/src/timing/Makeflags new file mode 100644 index 0000000..43f15e5 --- /dev/null +++ b/src/timing/Makeflags @@ -0,0 +1,3 @@ +# This file contains additional flags for the main Makefile. + +SUBDIR_INCLUDES = -I$(srcdir)/base -Itiming diff --git a/src/timing/cl_t_c1.cc b/src/timing/cl_t_c1.cc new file mode 100644 index 0000000..5367e8d --- /dev/null +++ b/src/timing/cl_t_c1.cc @@ -0,0 +1,29 @@ +// constructor cl_timing(cl_time_consumption&). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_timing.h" + + +// Implementation. + +static void report_accu (const cl_timing& t) +{ + var const cl_time_consumption usage_end = cl_current_time_consumption(); + var const cl_time_consumption& usage_start = t.tmp; + var cl_time_consumption usage; + usage.realtime = usage_end.realtime - usage_start.realtime; + usage.usertime = usage_end.usertime - usage_start.usertime; + + var cl_time_consumption& accumulator = *(cl_time_consumption*)(t.report_destination); + accumulator.realtime = accumulator.realtime + usage.realtime; + accumulator.usertime = accumulator.usertime + usage.usertime; +} + +cl_timing::cl_timing (cl_time_consumption& accumulator) +{ + report_fn = report_accu; report_destination = &accumulator; + tmp = cl_current_time_consumption(); +} diff --git a/src/timing/cl_t_c2.cc b/src/timing/cl_t_c2.cc new file mode 100644 index 0000000..c42237b --- /dev/null +++ b/src/timing/cl_t_c2.cc @@ -0,0 +1,57 @@ +// constructor cl_timing(cl_ostream). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_timing.h" + + +// Implementation. + +static void report_stream (const cl_timing& t) +{ + var const cl_time_consumption usage_end = cl_current_time_consumption(); + var const cl_time_consumption& usage_start = t.tmp; + var cl_time_consumption usage; + usage.realtime = usage_end.realtime - usage_start.realtime; + usage.usertime = usage_end.usertime - usage_start.usertime; + + var cl_ostream destination = +#if defined(CL_IO_STDIO) + (FILE*) t.report_destination; +#endif +#if defined(CL_IO_IOSTREAM) + *(ostream*) t.report_destination; +#endif + if (t.comment) + fprint(destination,t.comment); + cl_timing_report(destination,usage); + fprint(destination,"\n"); +} + +cl_timing::cl_timing (cl_ostream destination) +{ + report_fn = report_stream; +#if defined(CL_IO_STDIO) + report_destination = destination; +#endif +#if defined(CL_IO_IOSTREAM) + report_destination = &destination; +#endif + comment = NULL; + tmp = cl_current_time_consumption(); +} + +cl_timing::cl_timing (const char * msg, cl_ostream destination) +{ + report_fn = report_stream; +#if defined(CL_IO_STDIO) + report_destination = destination; +#endif +#if defined(CL_IO_IOSTREAM) + report_destination = &destination; +#endif + comment = msg; + tmp = cl_current_time_consumption(); +} diff --git a/src/timing/cl_t_config.h.in b/src/timing/cl_t_config.h.in new file mode 100644 index 0000000..25d9f27 --- /dev/null +++ b/src/timing/cl_t_config.h.in @@ -0,0 +1,45 @@ +// Defines OS dependent macros + +#ifndef _CL_T_CONFIG_H +#define _CL_T_CONFIG_H + +/* These definitions are adjusted by `configure' automatically. */ + + +/* functions and declarations */ + +/* CL_GETTIMEOFDAY */ +/* Define if you have the gettimeofday() function. */ +#undef HAVE_GETTIMEOFDAY +/* Define if the declaration of gettimeofday() needs dots. */ +#undef GETTIMEOFDAY_DOTS +/* Define as the type of `tzp' in gettimeofday() declaration. */ +#undef GETTIMEOFDAY_TZP_T + +/* CL_FTIME */ +/* Define if you have the ftime() function. */ +#undef HAVE_FTIME + +/* CL_TIMES_CLOCK */ +/* Define if you have the times() function and it returns the real time, + but don't have the gettimeofday() or ftime() function. */ +#undef HAVE_TIMES_CLOCK + +/* CL_RUSAGE */ +/* Define if you have . */ +#undef HAVE_SYS_RESOURCE_H +/* Define if you also have , the getrusage() function, + the struct rusage type, and defines RUSAGE_SELF. */ +#undef HAVE_GETRUSAGE +/* Define as the type of `who' in getrusage() declaration. */ +#undef RUSAGE_WHO_T +/* Define if you have . */ +#undef HAVE_SYS_TIMES_H + +/* CL_PERROR */ +/* Define if or contains a declaration for perror(). */ +#undef HAVE_PERROR_DECL + + +#endif /* _CL_T_CONFIG_H */ + diff --git a/src/timing/cl_t_current.cc b/src/timing/cl_t_current.cc new file mode 100644 index 0000000..93b40d2 --- /dev/null +++ b/src/timing/cl_t_current.cc @@ -0,0 +1,58 @@ +// cl_current_time(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_timing.h" + + +// Implementation. + +#include "cl_t_config.h" + +#if defined(HAVE_GETTIMEOFDAY) + #include + #ifdef GETTIMEOFDAY_DOTS + extern "C" int gettimeofday (struct timeval * tp, ...); + #else + extern "C" int gettimeofday (struct timeval * tp, GETTIMEOFDAY_TZP_T tzp); + #endif +#elif defined(HAVE_FTIME) + #include + #ifdef _WIN32 + extern "C" void ftime (struct timeb * tp); + #else + extern "C" int ftime (struct timeb * tp); + #endif +#else + #include +#endif +#ifdef HAVE_PERROR_DECL + #include + #include +#else + extern "C" int perror (const char *); +#endif + +const cl_timespec cl_current_time () +{ +#if defined(HAVE_GETTIMEOFDAY) + var struct timeval tv; + if (gettimeofday(&tv,NULL) != 0) { + perror("gettimeofday"); + tv.tv_sec = 0; tv.tv_usec = 0; + } + return cl_timespec(tv.tv_sec, + tv.tv_usec * (1000000000/1000000) + ); +#elif defined(HAVE_FTIME) + var struct timeb timebuf; + ftime(&timebuf); + return cl_timespec(timebuf.time, + (uintL)timebuf.millitm * (1000000000/1000) + ); +#else + return cl_timespec(time(NULL),0); +#endif +} diff --git a/src/timing/cl_t_current2.cc b/src/timing/cl_t_current2.cc new file mode 100644 index 0000000..5a0bfb0 --- /dev/null +++ b/src/timing/cl_t_current2.cc @@ -0,0 +1,66 @@ +// cl_current_time_consumption(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_timing.h" + + +// Implementation. + +#include "cl_t_config.h" + +#if defined(HAVE_GETRUSAGE) + #include + #include + #include + extern "C" int getrusage (RUSAGE_WHO_T who, struct rusage * rusage); +#elif defined(HAVE_SYS_TIMES_H) + #include + #include // defines HZ, unit for times() is 1/HZ seconds + #include + extern "C" clock_t times (struct tms * buffer); +#endif +#ifdef HAVE_PERROR_DECL + #include + #include +#else + extern "C" int perror (const char *); +#endif + +const cl_time_consumption cl_current_time_consumption () +{ + var cl_time_consumption result; + + var cl_timespec time = cl_current_time(); + result.realtime.tv_sec = time.tv_sec; + result.realtime.tv_nsec = time.tv_nsec; + +#if defined(HAVE_GETRUSAGE) + var struct rusage usage; + if (getrusage(RUSAGE_SELF,&usage) == 0) { + // use ru_utime only, ignore ru_stime. + result.usertime.tv_sec = usage.ru_utime.tv_sec; + result.usertime.tv_nsec = usage.ru_utime.tv_usec * (1000000000/1000000); + } else { + perror("getrusage"); + result.usertime.tv_sec = 0; result.usertime.tv_nsec = 0; + } +#elif defined(HAVE_SYS_TIMES_H) + var struct tms usage; + if (times(&usage) != (clock_t)(-1)) { + // use tms_utime only, ignore tms_stime. + var uintL used_time = usage.tms_utime; + result.usertime.tv_sec = used_time / HZ; + result.usertime.tv_nsec = (used_time % HZ) * ((2*1000000000+HZ)/(2*HZ)); + } else { + // ignore error ?? + result.usertime.tv_sec = 0; result.usertime.tv_nsec = 0; + } +#else + result.usertime = result.realtime; +#endif + + return result; +} diff --git a/src/timing/cl_t_d.cc b/src/timing/cl_t_d.cc new file mode 100644 index 0000000..00d0e1e --- /dev/null +++ b/src/timing/cl_t_d.cc @@ -0,0 +1,15 @@ +// destructor ~cl_timing(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_timing.h" + + +// Implementation. + +cl_timing::~cl_timing () +{ + report_fn(*this); +} diff --git a/src/timing/cl_t_dec.cc b/src/timing/cl_t_dec.cc new file mode 100644 index 0000000..f15096c --- /dev/null +++ b/src/timing/cl_t_dec.cc @@ -0,0 +1,21 @@ +// operator- (const cl_timespec&, const cl_time_duration&) + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_timing.h" + + +// Implementation. + +const cl_timespec operator- (const cl_timespec& a, const cl_time_duration& b) +{ + var uintL sec = a.tv_sec - b.tv_sec; + var sintL nsec = a.tv_nsec - b.tv_nsec; + if (nsec < 0) { + nsec += 1000000000; + sec -= 1; + } + return cl_timespec(sec,nsec); +} diff --git a/src/timing/cl_t_inc.cc b/src/timing/cl_t_inc.cc new file mode 100644 index 0000000..349167e --- /dev/null +++ b/src/timing/cl_t_inc.cc @@ -0,0 +1,21 @@ +// operator+ (const cl_timespec&, const cl_time_duration&) + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_timing.h" + + +// Implementation. + +const cl_timespec operator+ (const cl_timespec& a, const cl_time_duration& b) +{ + var uintL sec = a.tv_sec + b.tv_sec; + var sintL nsec = a.tv_nsec + b.tv_nsec; + if (nsec >= 1000000000) { + nsec -= 1000000000; + sec += 1; + } + return cl_timespec(sec,nsec); +} diff --git a/src/timing/cl_t_minus.cc b/src/timing/cl_t_minus.cc new file mode 100644 index 0000000..7dbf194 --- /dev/null +++ b/src/timing/cl_t_minus.cc @@ -0,0 +1,24 @@ +// operator- (const cl_timespec&, const cl_timespec&) + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_timing.h" + + +// Implementation. + +const cl_time_duration operator- (const cl_timespec& a, const cl_timespec& b) +{ + var sintL sec = a.tv_sec - b.tv_sec; + var sintL nsec = a.tv_nsec - b.tv_nsec; + if (nsec < 0) { + nsec += 1000000000; + sec -= 1; + } + if (sec < 0) { + sec = 0; nsec = 0; + } + return cl_time_duration(sec,nsec); +} diff --git a/src/timing/cl_t_report.cc b/src/timing/cl_t_report.cc new file mode 100644 index 0000000..e0c23bd --- /dev/null +++ b/src/timing/cl_t_report.cc @@ -0,0 +1,43 @@ +// cl_timing_report(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_timing.h" + + +// Implementation. + +// Round to 3 decimal places. +#define CL_HZ 1000 +#define CL_HZ_NSECS (1000000000/CL_HZ) + +void cl_timing_report (cl_ostream stream, const cl_time_consumption& t) +{ + var uintL real_sec = t.realtime.tv_sec; + var uintL real_msec = (t.realtime.tv_nsec + (CL_HZ_NSECS-1)/2) / CL_HZ_NSECS; + if (real_msec >= CL_HZ) { real_msec -= CL_HZ; real_sec += 1; } + var uintL user_sec = t.usertime.tv_sec; + var uintL user_msec = (t.usertime.tv_nsec + (CL_HZ_NSECS-1)/2) / CL_HZ_NSECS; + if (user_msec >= CL_HZ) { user_msec -= CL_HZ; user_sec += 1; } +#if defined(CL_IO_STDIO) + fprintf(stream, "real time: %4u.%03u s, run time: %4u.%03u s", + real_sec, real_msec, user_sec, user_msec); +#endif +#if defined(CL_IO_IOSTREAM) + var char oldfill = stream.fill(); + var int oldwidth = stream.width(); + stream << "real time: "; + stream.width(4); stream << real_sec; stream << "."; + stream.fill('0'); stream.width(3); stream << real_msec; + stream.fill(oldfill); + stream << " s, "; + stream << "run time: "; + stream.width(4); stream << user_sec; stream << "."; + stream.fill('0'); stream.width(3); stream << user_msec; + stream.fill(oldfill); + stream << " s"; + stream.width(oldwidth); +#endif +} diff --git a/src/timing/cl_t_td_minus.cc b/src/timing/cl_t_td_minus.cc new file mode 100644 index 0000000..609a656 --- /dev/null +++ b/src/timing/cl_t_td_minus.cc @@ -0,0 +1,24 @@ +// operator- (const cl_time_duration&, const cl_time_duration&) + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_timing.h" + + +// Implementation. + +const cl_time_duration operator- (const cl_time_duration& a, const cl_time_duration& b) +{ + var sintL sec = a.tv_sec - b.tv_sec; + var sintL nsec = a.tv_nsec - b.tv_nsec; + if (nsec < 0) { + nsec += 1000000000; + sec -= 1; + } + if (sec < 0) { + sec = 0; nsec = 0; + } + return cl_time_duration(sec,nsec); +} diff --git a/src/timing/cl_t_td_plus.cc b/src/timing/cl_t_td_plus.cc new file mode 100644 index 0000000..fc2f9a6 --- /dev/null +++ b/src/timing/cl_t_td_plus.cc @@ -0,0 +1,21 @@ +// operator+ (const cl_time_duration&, const cl_time_duration&) + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_timing.h" + + +// Implementation. + +const cl_time_duration operator+ (const cl_time_duration& a, const cl_time_duration& b) +{ + var uintL sum_sec = a.tv_sec + b.tv_sec; + var uintL sum_nsec = a.tv_nsec + b.tv_nsec; + if (sum_nsec >= 1000000000) { + sum_nsec -= 1000000000; + sum_sec += 1; + } + return cl_time_duration(sum_sec,sum_nsec); +} diff --git a/src/vector/Makeflags b/src/vector/Makeflags new file mode 100644 index 0000000..1557a11 --- /dev/null +++ b/src/vector/Makeflags @@ -0,0 +1,3 @@ +# This file contains additional flags for the main Makefile. + +SUBDIR_INCLUDES = -I$(srcdir)/vector -I$(srcdir)/integer -I$(srcdir)/base/digitseq -I$(srcdir)/base/digit -Ibase -I$(srcdir)/base $(GMP_INCLUDES) diff --git a/src/vector/cl_GV_I.cc b/src/vector/cl_GV_I.cc new file mode 100644 index 0000000..c1520a2 --- /dev/null +++ b/src/vector/cl_GV_I.cc @@ -0,0 +1,492 @@ +// cl_make_heap_GV_I(). + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_GV_I) + +// Specification. +#include "cl_GV_integer.h" + + +// Implementation. + +#include "cl_I.h" +#include "cl_DS.h" +#include "cl_abort.h" +#include "cl_offsetof.h" + + +// Memory-efficient integer vectors: If all entries are known in advance to +// be >= 0 and < 2^m, we reserve only m bits for each entry. (m=1,2,4,8,16,32). +// Thus we end up with 6 kinds of bit/byte vectors, and the general integer +// vectors. +// For enquiring purposes, we store m in the vectorops table. Because of this, +// treating a cl_GV_RA as cl_GV_I is wrong. In particular, we cannot use the +// cl_null_GV_N to initialize a cl_GV_I; need a special cl_null_GV_I. + + +static void cl_gvector_integer_destructor (cl_heap* pointer) +{ +#if (defined(__mips__) || defined(__mips64__)) && !defined(__GNUC__) // workaround SGI CC bug + (*(cl_heap_GV_I*)pointer).~cl_heap_GV(); +#else + (*(cl_heap_GV_I*)pointer).~cl_heap_GV_I(); +#endif +} + +cl_class cl_class_gvector_integer = { + cl_gvector_integer_destructor, + 0 +}; + + +static inline cl_heap_GV_I * outcast (cl_GV_inner* vec) +{ + return (cl_heap_GV_I *)((char *) vec - offsetof(cl_heap_GV_I,v)); +} +static inline const cl_heap_GV_I * outcast (const cl_GV_inner* vec) +{ + return (const cl_heap_GV_I *)((const char *) vec - offsetof(cl_heap_GV_I,v)); +} + + +// Add more info to the vectorops tables. + +struct cl_GV_I_vectorops { + cl_GV_vectorops ops; + sintL m; // for maxbits +}; + +static inline cl_GV_I_vectorops* outcast (cl_GV_vectorops* vectorops) +{ + return (cl_GV_I_vectorops*)((char *) vectorops - offsetof(cl_GV_I_vectorops,ops)); +} + + +// Vectors of general integers. + +struct cl_heap_GV_I_general : public cl_heap_GV_I { + cl_I data[1]; + // Standard allocation disabled. + void* operator new (size_t size) { unused size; cl_abort(); return (void*)1; } + // Standard deallocation disabled. + void operator delete (void* ptr) { unused ptr; cl_abort(); } + // No default constructor. + cl_heap_GV_I_general (); +}; + +static const cl_I general_element (const cl_GV_inner* vec, uintL index) +{ + return ((const cl_heap_GV_I_general *) outcast(vec))->data[index]; +} + +static void general_set_element (cl_GV_inner* vec, uintL index, const cl_I& x) +{ + ((cl_heap_GV_I_general *) outcast(vec))->data[index] = x; +} + +static void general_do_delete (cl_GV_inner* vec) +{ + var cl_heap_GV_I_general* hv = (cl_heap_GV_I_general *) outcast(vec); + var uintL len = hv->v.length(); + for (var uintL i = 0; i < len; i++) + hv->data[i].~cl_I(); +} + +static void general_copy_elements (const cl_GV_inner* srcvec, uintL srcindex, cl_GV_inner* destvec, uintL destindex, uintL count) +{ + if (count > 0) { + var const cl_heap_GV_I_general* srcv = + (const cl_heap_GV_I_general *) outcast(srcvec); + var cl_heap_GV_I_general* destv = + (cl_heap_GV_I_general *) outcast(destvec); + var uintL srclen = srcv->v.length(); + var uintL destlen = destv->v.length(); + if (!(srcindex <= srcindex+count && srcindex+count <= srclen)) + cl_abort(); + if (!(destindex <= destindex+count && destindex+count <= destlen)) + cl_abort(); + do { + destv->data[destindex++] = srcv->data[srcindex++]; + } while (--count > 0); + } +} + +static cl_GV_I_vectorops general_vectorops = {{ + general_element, + general_set_element, + general_do_delete, + general_copy_elements }, + -1 +}; + +cl_heap_GV_I* cl_make_heap_GV_I (uintL len) +{ + var cl_heap_GV_I_general* hv = (cl_heap_GV_I_general*) cl_malloc_hook(offsetofa(cl_heap_GV_I_general,data)+sizeof(cl_I)*len); + hv->refcount = 1; + hv->type = &cl_class_gvector_integer; + new (&hv->v) cl_GV_inner (len,&general_vectorops.ops); + for (var uintL i = 0; i < len; i++) + init1(cl_I, hv->data[i]) (); + return hv; +} + + +// Vectors of integers requiring only few bits. + +#define DEFINE_cl_heap_GV_I_bits(m,uint_t) \ +struct cl_heap_GV_I_bits##m : public cl_heap_GV_I { \ + uint_t data[1]; \ + /* Standard allocation disabled. */ \ + void* operator new (size_t size) { unused size; cl_abort(); return (void*)1; } \ + /* Standard deallocation disabled. */ \ + void operator delete (void* ptr) { unused ptr; cl_abort(); } \ + /* No default constructor. */ \ + cl_heap_GV_I_bits##m (); \ +}; \ +static const cl_I bits##m##_element (const cl_GV_inner* vec, uintL index); \ +static void bits##m##_set_element (cl_GV_inner* vec, uintL index, const cl_I& x); \ +static void bits##m##_copy_elements (const cl_GV_inner* srcvec, uintL srcindex, cl_GV_inner* destvec, uintL destindex, uintL count) \ +{ \ + if (count > 0) { \ + var const cl_heap_GV_I_bits##m * srcv = \ + (const cl_heap_GV_I_bits##m *) outcast(srcvec); \ + var cl_heap_GV_I_bits##m * destv = \ + (cl_heap_GV_I_bits##m *) outcast(destvec); \ + var uintL srclen = srcv->v.length(); \ + var uintL destlen = destv->v.length(); \ + if (!(srcindex <= srcindex+count && srcindex+count <= srclen)) \ + cl_abort(); \ + if (!(destindex <= destindex+count && destindex+count <= destlen)) \ + cl_abort(); \ + if (m == intDsize) { \ + var const uintD* srcptr = &srcv->data[srcindex]; \ + var uintD* destptr = &destv->data[destindex]; \ + do { \ + *destptr++ = *srcptr++; \ + } while (--count > 0); \ + } else \ + bits_copy(srcv->data,m*srcindex,destv->data,m*destindex,m*count); \ + } \ +} \ +static cl_GV_I_vectorops bits##m##_vectorops = {{ \ + bits##m##_element, \ + bits##m##_set_element, \ + bits_do_delete, \ + bits##m##_copy_elements }, \ + m \ +}; + +static void bits_do_delete (cl_GV_inner* vec) +{ + unused vec; +} + +// Copy bits srcptr.bits[srcindex..srcindex+count-1] into destptr.bits[destindex..destindex+count-1]. +// Assumes that all range checks have already been performed. +static void bits_copy (const uintD* srcptr, uintL srcindex, uintD* destptr, uintL destindex, uintL count) +{ + srcptr += floor(srcindex,intDsize); + destptr += floor(destindex,intDsize); + srcindex = srcindex%intDsize; + destindex = destindex%intDsize; + // Now 0 <= srcindex < intDsize and 0 <= destindex < intDsize. + if (srcindex == destindex) { + // src and dest are aligned with respect to each other. + if (srcindex > 0) { + if (count <= intDsize-srcindex) { + *destptr ^= (*destptr ^ *srcptr) & ((uintD)(bit(count)-1) << srcindex); + return; + } + *destptr ^= (*destptr ^ *srcptr) & (uintD)minus_bit(srcindex); + srcptr++; + destptr++; + count -= intDsize-srcindex; + } + // Now srcindex and destindex can be assumed to be 0. + var uintL count1 = count%intDsize; + count = floor(count,intDsize); + if (count > 0) { + do { + *destptr++ = *srcptr++; + } while (--count > 0); + } + if (count1 > 0) { + *destptr ^= (*destptr ^ *srcptr) & (uintD)(bit(count1)-1); + } + } else { + var uintL i = destindex - srcindex; + var uintD tmp; + if (destindex >= srcindex) { // i > 0 + if (count <= intDsize-destindex) { + *destptr ^= (*destptr ^ (*srcptr << i)) & ((uintD)(bit(count)-1) << destindex); + return; + } + *destptr ^= (*destptr ^ (*srcptr << i)) & (uintD)minus_bit(destindex); + destptr++; + tmp = *srcptr >> (intDsize-i); + count -= intDsize-destindex; + } else { // i < 0 + if (count <= intDsize-srcindex) { + *destptr ^= (*destptr ^ (*srcptr >> -i)) & ((uintD)(bit(count)-1) << destindex); + return; + } + tmp = (*destptr & (uintD)(bit(destindex)-1)) | ((*srcptr >> srcindex) << destindex); + count += destindex; + i += intDsize; + } + srcptr++; + // tmp now contains the low i bits to be put into *destptr. + var uintL count1 = count%intDsize; + count = floor(count,intDsize); + var uintD lastdest; + if (count == 0) + lastdest = tmp; + else { + lastdest = shiftleftcopy_loop_up(srcptr,destptr,count,i); + *destptr |= tmp; + } + // lastdest now contains the i bits shifted out of the top of the source. + if (count1 > 0) { + destptr += count; + if (count1 > i) + lastdest |= *(srcptr += count) << i; + *destptr ^= (*destptr ^ lastdest) & (uintD)(bit(count1)-1); + } + } +} + + +// It would be most natural to use the following type for uint_t: +// m = 1: uint_t = uint8 +// m = 2: uint_t = uint8 +// m = 4: uint_t = uint8 +// m = 8: uint_t = uint8 +// m = 16: uint_t = uint16 +// m = 32: uint_t = uint32 +// But we want to have a fast copy_elements routine. And for m=1, +// we also want to use the fast shiftxor_loop_up() function for addition. +// Hence we use the uint_t = uintD in all cases. (NB: intDsize>=32.) + +// The last ceiling(len*m/intDsize)*intDsize-len*m unused bits in the last word +// are always 0. This provides some simplification for routines which work on +// entire words: They don't need to special-case the last word. + + +DEFINE_cl_heap_GV_I_bits(1,uintD) + +static const cl_I bits1_element (const cl_GV_inner* vec, uintL index) +{ + return (unsigned int)((((const cl_heap_GV_I_bits1 *) outcast(vec))->data[index/intDsize] >> (index%intDsize)) & 0x1); +} +static void bits1_set_element (cl_GV_inner* vec, uintL index, const cl_I& x) +{ + var uint32 xval; + if (fixnump(x)) { + xval = FN_to_UL(x); + if (xval <= 0x1) { + var uintD* ptr = &((cl_heap_GV_I_bits1 *) outcast(vec))->data[index/intDsize]; + index = index%intDsize; + *ptr = *ptr ^ ((*ptr ^ ((uintD)xval << index)) & ((uintD)0x1 << index)); + return; + } + } + cl_abort(); +} + + +DEFINE_cl_heap_GV_I_bits(2,uintD) + +static const cl_I bits2_element (const cl_GV_inner* vec, uintL index) +{ + return (unsigned int)((((const cl_heap_GV_I_bits2 *) outcast(vec))->data[index/(intDsize/2)] >> (2*(index%(intDsize/2)))) & 0x3); +} +static void bits2_set_element (cl_GV_inner* vec, uintL index, const cl_I& x) +{ + var uint32 xval; + if (fixnump(x)) { + xval = FN_to_UL(x); + if (xval <= 0x3) { + var uintD* ptr = &((cl_heap_GV_I_bits2 *) outcast(vec))->data[index/(intDsize/2)]; + index = 2*(index%(intDsize/2)); + *ptr = *ptr ^ ((*ptr ^ ((uintD)xval << index)) & ((uintD)0x3 << index)); + return; + } + } + cl_abort(); +} + + +DEFINE_cl_heap_GV_I_bits(4,uintD) + +static const cl_I bits4_element (const cl_GV_inner* vec, uintL index) +{ + return (unsigned int)((((const cl_heap_GV_I_bits4 *) outcast(vec))->data[index/(intDsize/4)] >> (4*(index%(intDsize/4)))) & 0xF); +} +static void bits4_set_element (cl_GV_inner* vec, uintL index, const cl_I& x) +{ + var uint32 xval; + if (fixnump(x)) { + xval = FN_to_UL(x); + if (xval <= 0xF) { + var uintD* ptr = &((cl_heap_GV_I_bits4 *) outcast(vec))->data[index/(intDsize/4)]; + index = 4*(index%(intDsize/4)); + *ptr = *ptr ^ ((*ptr ^ ((uintD)xval << index)) & ((uintD)0xF << index)); + return; + } + } + cl_abort(); +} + + +DEFINE_cl_heap_GV_I_bits(8,uintD) + +static const cl_I bits8_element (const cl_GV_inner* vec, uintL index) +{ + #if CL_CPU_BIG_ENDIAN_P + return (unsigned int)((((const cl_heap_GV_I_bits8 *) outcast(vec))->data[index/(intDsize/8)] >> (8*(index%(intDsize/8)))) & 0xFF); + #else + // Optimization which assumes little-endian storage of uint8 in an uintD + return (unsigned int)(((uint8*)(((const cl_heap_GV_I_bits8 *) outcast(vec))->data))[index]); + #endif +} +static void bits8_set_element (cl_GV_inner* vec, uintL index, const cl_I& x) +{ + var uint32 xval; + if (fixnump(x)) { + xval = FN_to_UL(x); + if (xval <= 0xFF) { + #if CL_CPU_BIG_ENDIAN_P + var uintD* ptr = &((cl_heap_GV_I_bits8 *) outcast(vec))->data[index/(intDsize/8)]; + index = 8*(index%(intDsize/8)); + *ptr = *ptr ^ ((*ptr ^ ((uintD)xval << index)) & ((uintD)0xFF << index)); + #else + // Optimization which assumes little-endian storage of uint8 in an uintD + ((uint8*)(((cl_heap_GV_I_bits8 *) outcast(vec))->data))[index] = xval; + #endif + return; + } + } + cl_abort(); +} + + +DEFINE_cl_heap_GV_I_bits(16,uintD) + +static const cl_I bits16_element (const cl_GV_inner* vec, uintL index) +{ + #if CL_CPU_BIG_ENDIAN_P + return (unsigned int)((((const cl_heap_GV_I_bits16 *) outcast(vec))->data[index/(intDsize/16)] >> (16*(index%(intDsize/16)))) & 0xFFFF); + #else + // Optimization which assumes little-endian storage of uint16 in an uintD + return (unsigned int)(((uint16*)(((const cl_heap_GV_I_bits16 *) outcast(vec))->data))[index]); + #endif +} +static void bits16_set_element (cl_GV_inner* vec, uintL index, const cl_I& x) +{ + var uint32 xval; + if (fixnump(x)) { + xval = FN_to_UL(x); + if (xval <= 0xFFFF) { + #if CL_CPU_BIG_ENDIAN_P + var uintD* ptr = &((cl_heap_GV_I_bits16 *) outcast(vec))->data[index/(intDsize/16)]; + index = 16*(index%(intDsize/16)); + *ptr = *ptr ^ ((*ptr ^ ((uintD)xval << index)) & ((uintD)0xFFFF << index)); + #else + // Optimization which assumes little-endian storage of uint16 in an uintD + ((uint16*)(((cl_heap_GV_I_bits16 *) outcast(vec))->data))[index] = xval; + #endif + return; + } + } + cl_abort(); +} + + +DEFINE_cl_heap_GV_I_bits(32,uintD) + +static const cl_I bits32_element (const cl_GV_inner* vec, uintL index) +{ + #if (intDsize==32) + return (unsigned long)(((const cl_heap_GV_I_bits32 *) outcast(vec))->data[index]); + #elif CL_CPU_BIG_ENDIAN_P + return (unsigned long)((((const cl_heap_GV_I_bits32 *) outcast(vec))->data[index/(intDsize/32)] >> (32*(index%(intDsize/32)))) & 0xFFFFFFFF); + #else + // Optimization which assumes little-endian storage of uint32 in an uintD + return (unsigned long)(((uint32*)(((const cl_heap_GV_I_bits32 *) outcast(vec))->data))[index]); + #endif +} +static void bits32_set_element (cl_GV_inner* vec, uintL index, const cl_I& x) +{ + var uint32 xval = cl_I_to_UL(x); + #if (intDsize==32) + ((cl_heap_GV_I_bits32 *) outcast(vec))->data[index] = xval; + #elif CL_CPU_BIG_ENDIAN_P + var uintD* ptr = &((cl_heap_GV_I_bits32 *) outcast(vec))->data[index/(intDsize/32)]; + index = 32*(index%(intDsize/32)); + *ptr = *ptr ^ ((*ptr ^ ((uintD)xval << index)) & ((uintD)0xFFFFFFFF << index)); + #else + // Optimization which assumes little-endian storage of uint32 in an uintD + ((uint32*)(((cl_heap_GV_I_bits32 *) outcast(vec))->data))[index] = xval; + #endif +} + + +static cl_GV_I_vectorops* bits_vectorops[6] = { + &bits1_vectorops, + &bits2_vectorops, + &bits4_vectorops, + &bits8_vectorops, + &bits16_vectorops, + &bits32_vectorops +}; + +cl_heap_GV_I* cl_make_heap_GV_I (uintL len, sintL m) +{ + // Determine log2(bits). + var uintL log2_bits; + switch (m) { + case 0: case 1: + log2_bits = 0; break; + case 2: + log2_bits = 1; break; + case 3: case 4: + log2_bits = 2; break; + case 5: case 6: case 7: case 8: + log2_bits = 3; break; + case 9: case 10: case 11: case 12: + case 13: case 14: case 15: case 16: + log2_bits = 4; break; + case 17: case 18: case 19: case 20: + case 21: case 22: case 23: case 24: + case 25: case 26: case 27: case 28: + case 29: case 30: case 31: case 32: + log2_bits = 5; break; + default: + return cl_make_heap_GV_I(len); + } + // For room allocation purposes, be pessimistic: assume the uintD case (since intDsize>=32). + var uintL words = // ceiling(len*2^log2_bits,intDsize) + (((sintL)len-1)>>(log2_intDsize-log2_bits))+1; + var cl_heap_GV_I_bits32* hv = (cl_heap_GV_I_bits32*) cl_malloc_hook(offsetofa(cl_heap_GV_I_bits32,data)+sizeof(uintD)*words); + hv->refcount = 1; + hv->type = &cl_class_gvector_integer; + new (&hv->v) cl_GV_inner (len,&bits_vectorops[log2_bits]->ops); + var uintD* ptr = (uintD*)(hv->data); + for (var uintL i = 0; i < words; i++) + ptr[i] = 0; + return (cl_heap_GV_I*) hv; +} + + +sintL cl_heap_GV_I::maxbits () const +{ + return outcast(v.vectorops)->m; +} + + +// An empty vector. +const cl_GV_I cl_null_GV_I = cl_GV_I((uintL)0); + +CL_PROVIDE_END(cl_GV_I) diff --git a/src/vector/cl_GV_I_copy.cc b/src/vector/cl_GV_I_copy.cc new file mode 100644 index 0000000..28c36d7 --- /dev/null +++ b/src/vector/cl_GV_I_copy.cc @@ -0,0 +1,19 @@ +// copy(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#define CL_GV_NO_RANGECHECKS +#include "cl_GV_integer.h" + + +// Implementation. + +const cl_GV_I copy (const cl_GV_I& v) +{ + var uintL len = v.length(); + var cl_GV_I w = cl_GV_I(len,v.maxbits()); + cl_GV_I::copy_elements(v,0,w,0,len); + return w; +} diff --git a/src/vector/cl_GV_I_debug.cc b/src/vector/cl_GV_I_debug.cc new file mode 100644 index 0000000..a2c5439 --- /dev/null +++ b/src/vector/cl_GV_I_debug.cc @@ -0,0 +1,24 @@ +// cl_GV_I debugging support. + +// General includes. +#include "cl_sysdep.h" + +// Specification. + + +// Implementation. + +#include "cl_GV_integer.h" +#include "cl_io.h" + +static void dprint (cl_heap* pointer) +{ + var const cl_GV_I& obj = *(const cl_GV_I*)&pointer; + fprint(cl_debugout, "(cl_GV_I) "); + fprint(cl_debugout, obj); +} +AT_INITIALIZATION(dprint_GV_I) +{ cl_register_type_printer(cl_class_gvector_integer,dprint); } + +// This dummy links in this module when requires it. +int cl_GV_I_debug_module; diff --git a/src/vector/cl_GV_io.h b/src/vector/cl_GV_io.h new file mode 100644 index 0000000..40e9e65 --- /dev/null +++ b/src/vector/cl_GV_io.h @@ -0,0 +1,20 @@ +// I/O of vectors. + +#ifndef _CL_GV_IO_H +#define _CL_GV_IO_H + +#include "cl_number_io.h" +#include "cl_GV.h" +#include "cl_GV_complex.h" + + +// Gibt einen Vektor aus. +// print_vector(stream,flags,fun,z); +// > stream: Stream +// > flags: Flags +// > fun: Ausgabefunktion für die einzelnen Elemente +// > vector: Vektor +extern void print_vector (cl_ostream stream, const cl_print_flags& flags, void (* fun) (cl_ostream, const cl_print_flags&, const cl_number&), const cl_GV_number& vector); + + +#endif /* _CL_GV_IO_H */ diff --git a/src/vector/cl_GV_number.cc b/src/vector/cl_GV_number.cc new file mode 100644 index 0000000..30d00ec --- /dev/null +++ b/src/vector/cl_GV_number.cc @@ -0,0 +1,113 @@ +// cl_make_heap_GV_number(). + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_GV_number) + +// Specification. +#include "cl_GV_number.h" + + +// Implementation. + +#include "cl_abort.h" +#include "cl_offsetof.h" + + +static void cl_gvector_number_destructor (cl_heap* pointer) +{ +#if (defined(__mips__) || defined(__mips64__)) && !defined(__GNUC__) // workaround SGI CC bug + (*(cl_heap_GV_number*)pointer).~cl_heap_GV(); +#else + (*(cl_heap_GV_number*)pointer).~cl_heap_GV_number(); +#endif +} + +cl_class cl_class_gvector_number = { + cl_gvector_number_destructor, + 0 +}; + + +static inline cl_heap_GV_number * outcast (cl_GV_inner* vec) +{ + return (cl_heap_GV_number *)((char *) vec - offsetof(cl_heap_GV_number,v)); +} +static inline const cl_heap_GV_number * outcast (const cl_GV_inner* vec) +{ + return (const cl_heap_GV_number *)((const char *) vec - offsetof(cl_heap_GV_number,v)); +} + + +// Vectors of numbers. + +struct cl_heap_GV_number_general : public cl_heap_GV_number { + cl_number data[1]; + // Standard allocation disabled. + void* operator new (size_t size) { unused size; cl_abort(); return (void*)1; } + // Standard deallocation disabled. + void operator delete (void* ptr) { unused ptr; cl_abort(); } + // No default constructor. + cl_heap_GV_number_general (); +}; + +static const cl_number general_element (const cl_GV_inner* vec, uintL index) +{ + return ((const cl_heap_GV_number_general *) outcast(vec))->data[index]; +} + +static void general_set_element (cl_GV_inner* vec, uintL index, const cl_number& x) +{ + ((cl_heap_GV_number_general *) outcast(vec))->data[index] = x; +} + +static void general_do_delete (cl_GV_inner* vec) +{ + var cl_heap_GV_number_general* hv = (cl_heap_GV_number_general *) outcast(vec); + var uintL len = hv->v.length(); + for (var uintL i = 0; i < len; i++) + hv->data[i].~cl_number(); +} + +static void general_copy_elements (const cl_GV_inner* srcvec, uintL srcindex, cl_GV_inner* destvec, uintL destindex, uintL count) +{ + if (count > 0) { + var const cl_heap_GV_number_general* srcv = + (const cl_heap_GV_number_general *) outcast(srcvec); + var cl_heap_GV_number_general* destv = + (cl_heap_GV_number_general *) outcast(destvec); + var uintL srclen = srcv->v.length(); + var uintL destlen = destv->v.length(); + if (!(srcindex <= srcindex+count && srcindex+count <= srclen)) + cl_abort(); + if (!(destindex <= destindex+count && destindex+count <= destlen)) + cl_abort(); + do { + destv->data[destindex++] = srcv->data[srcindex++]; + } while (--count > 0); + } +} + +static cl_GV_vectorops general_vectorops = { + general_element, + general_set_element, + general_do_delete, + general_copy_elements +}; + +cl_heap_GV_number* cl_make_heap_GV_number (uintL len) +{ + var cl_heap_GV_number_general* hv = (cl_heap_GV_number_general*) cl_malloc_hook(offsetofa(cl_heap_GV_number_general,data)+sizeof(cl_number)*len); + hv->refcount = 1; + hv->type = &cl_class_gvector_number; + new (&hv->v) cl_GV_inner (len,&general_vectorops); + for (var uintL i = 0; i < len; i++) + init1(cl_number, hv->data[i]) (); + return hv; +} + +// An empty vector. +const cl_GV_number cl_null_GV_number = cl_GV_number((uintL)0); + +CL_PROVIDE_END(cl_GV_number) diff --git a/src/vector/cl_GV_number_copy.cc b/src/vector/cl_GV_number_copy.cc new file mode 100644 index 0000000..cdd92ce --- /dev/null +++ b/src/vector/cl_GV_number_copy.cc @@ -0,0 +1,19 @@ +// copy(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#define CL_GV_NO_RANGECHECKS +#include "cl_GV_number.h" + + +// Implementation. + +const cl_GV_number copy (const cl_GV_number& v) +{ + var uintL len = v.length(); + var cl_GV_number w = cl_GV_number(len); + cl_GV_number::copy_elements(v,0,w,0,len); + return w; +} diff --git a/src/vector/cl_GV_number_debug.cc b/src/vector/cl_GV_number_debug.cc new file mode 100644 index 0000000..1e9e2bd --- /dev/null +++ b/src/vector/cl_GV_number_debug.cc @@ -0,0 +1,38 @@ +// cl_GV_number debugging support. + +// General includes. +#include "cl_sysdep.h" + +// Specification. + + +// Implementation. + +#include "cl_output.h" +#include "cl_GV_number.h" +#include "cl_io.h" +#include "cl_GV_io.h" + +static void print_for_debug (cl_ostream stream, const cl_print_flags& flags, const cl_number& z) +{ + unused stream; // must be cl_debugout + unused flags; // must be cl_default_print_flags + z.debug_print(); +} + +static void dprint (cl_heap* pointer) +{ + var const cl_GV_number& obj = *(const cl_GV_number*)&pointer; + fprint(cl_debugout, "(cl_GV_number) "); + print_vector(cl_debugout,cl_default_print_flags,&print_for_debug,obj); +} +AT_INITIALIZATION(dprint_GV_number) +{ cl_register_type_printer(cl_class_gvector_number,dprint); } + +// This dummy links in this module when requires it. +int cl_GV_number_debug_module; + +extern int cl_GV_I_debug_module; +static void* dummy[] = { &dummy, + &cl_GV_I_debug_module +}; diff --git a/src/vector/cl_SV_copy.cc b/src/vector/cl_SV_copy.cc new file mode 100644 index 0000000..b3a0155 --- /dev/null +++ b/src/vector/cl_SV_copy.cc @@ -0,0 +1,25 @@ +// copy(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#define CL_SV_NO_RANGECHECKS +#include "cl_SV.h" + + +// Implementation. + +#include "cl_malloc.h" + +const cl_SV_any copy (const cl_SV_any& src) +{ + var uintL len = src.length(); + var cl_heap_SV_any* hv = (cl_heap_SV_any*) cl_malloc_hook(sizeof(cl_heap_SV_any)+sizeof(cl_gcobject)*len); + hv->refcount = 1; + hv->type = src.pointer_type(); + new (&hv->v) cl_SV_inner (len); + for (var uintL i = 0; i < len; i++) + init1(cl_gcobject, hv->v[i]) (src[i]); + return hv; +} diff --git a/src/vector/cl_SV_io.h b/src/vector/cl_SV_io.h new file mode 100644 index 0000000..420266f --- /dev/null +++ b/src/vector/cl_SV_io.h @@ -0,0 +1,20 @@ +// I/O of vectors. + +#ifndef _CL_SV_IO_H +#define _CL_SV_IO_H + +#include "cl_number_io.h" +#include "cl_SV.h" +#include "cl_SV_number.h" + + +// Gibt einen Vektor aus. +// print_vector(stream,flags,fun,z); +// > stream: Stream +// > flags: Flags +// > fun: Ausgabefunktion für die einzelnen Elemente +// > vector: Vektor +extern void print_vector (cl_ostream stream, const cl_print_flags& flags, void (* fun) (cl_ostream, const cl_print_flags&, const cl_number&), const cl_SV_number& vector); + + +#endif /* _CL_SV_IO_H */ diff --git a/src/vector/cl_SV_number.cc b/src/vector/cl_SV_number.cc new file mode 100644 index 0000000..af45534 --- /dev/null +++ b/src/vector/cl_SV_number.cc @@ -0,0 +1,55 @@ +// cl_make_heap_SV_number(). + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_SV_number) + +// Specification. +#include "cl_SV_number.h" + + +// Implementation. + +#include "cl_abort.h" + + +static void cl_svector_number_destructor (cl_heap* pointer) +{ +#if (defined(__mips__) || defined(__mips64__)) && !defined(__GNUC__) // workaround SGI CC bug + (*(cl_heap_SV_number*)pointer).~cl_heap_SV(); +#else + (*(cl_heap_SV_number*)pointer).~cl_heap_SV_number(); +#endif +} + +cl_class cl_class_svector_number = { + cl_svector_number_destructor, + 0 +}; + +cl_heap_SV_number* cl_make_heap_SV_number_uninit (uintL len) +{ + var cl_heap_SV_number* hv = (cl_heap_SV_number*) cl_malloc_hook(sizeof(cl_heap_SV_number)+sizeof(cl_number)*len); + hv->refcount = 1; + hv->type = &cl_class_svector_number; + new (&hv->v) cl_SV_inner (len); + // Have to fill hv->v[i] (0 <= i < len) yourself. + return hv; +} + +cl_heap_SV_number* cl_make_heap_SV_number (uintL len) +{ + var cl_heap_SV_number* hv = (cl_heap_SV_number*) cl_malloc_hook(sizeof(cl_heap_SV_number)+sizeof(cl_number)*len); + hv->refcount = 1; + hv->type = &cl_class_svector_number; + new (&hv->v) cl_SV_inner (len); + for (var uintL i = 0; i < len; i++) + init1(cl_number, hv->v[i]) (0); + return hv; +} + +// An empty vector. +const cl_SV_number cl_null_SV_number = cl_SV_number((uintL)0); + +CL_PROVIDE_END(cl_SV_number) diff --git a/src/vector/cl_SV_number_debug.cc b/src/vector/cl_SV_number_debug.cc new file mode 100644 index 0000000..8060081 --- /dev/null +++ b/src/vector/cl_SV_number_debug.cc @@ -0,0 +1,33 @@ +// cl_SV_number debugging support. + +// General includes. +#include "cl_sysdep.h" + +// Specification. + + +// Implementation. + +#include "cl_output.h" +#include "cl_SV_number.h" +#include "cl_io.h" +#include "cl_SV_io.h" + +static void print_for_debug (cl_ostream stream, const cl_print_flags& flags, const cl_number& z) +{ + unused stream; // must be cl_debugout + unused flags; // must be cl_default_print_flags + z.debug_print(); +} + +static void dprint (cl_heap* pointer) +{ + var const cl_SV_number& obj = *(const cl_SV_number*)&pointer; + fprint(cl_debugout, "(cl_SV_number) "); + print_vector(cl_debugout,cl_default_print_flags,&print_for_debug,obj); +} +AT_INITIALIZATION(dprint_SV_number) +{ cl_register_type_printer(cl_class_svector_number,dprint); } + +// This dummy links in this module when requires it. +int cl_SV_number_debug_module; diff --git a/src/vector/cl_SV_ringelt.cc b/src/vector/cl_SV_ringelt.cc new file mode 100644 index 0000000..0af6c93 --- /dev/null +++ b/src/vector/cl_SV_ringelt.cc @@ -0,0 +1,55 @@ +// cl_make_heap_SV_ringelt(). + +// General includes. +#include "cl_sysdep.h" + +CL_PROVIDE(cl_SV_ringelt) + +// Specification. +#include "cl_SV_ringelt.h" + + +// Implementation. + +#include "cl_abort.h" + + +static void cl_svector_ringelt_destructor (cl_heap* pointer) +{ +#if (defined(__mips__) || defined(__mips64__)) && !defined(__GNUC__) // workaround SGI CC bug + (*(cl_heap_SV_ringelt*)pointer).~cl_heap_SV(); +#else + (*(cl_heap_SV_ringelt*)pointer).~cl_heap_SV_ringelt(); +#endif +} + +cl_class cl_class_svector_ringelt = { + cl_svector_ringelt_destructor, + 0 +}; + +cl_heap_SV_ringelt* cl_make_heap_SV_ringelt_uninit (uintL len) +{ + var cl_heap_SV_ringelt* hv = (cl_heap_SV_ringelt*) cl_malloc_hook(sizeof(cl_heap_SV_ringelt)+sizeof(_cl_ring_element)*len); + hv->refcount = 1; + hv->type = &cl_class_svector_ringelt; + new (&hv->v) cl_SV_inner<_cl_ring_element> (len); + // Have to fill hv->v[i] (0 <= i < len) yourself. + return hv; +} + +cl_heap_SV_ringelt* cl_make_heap_SV_ringelt (uintL len) +{ + var cl_heap_SV_ringelt* hv = (cl_heap_SV_ringelt*) cl_malloc_hook(sizeof(cl_heap_SV_ringelt)+sizeof(_cl_ring_element)*len); + hv->refcount = 1; + hv->type = &cl_class_svector_ringelt; + new (&hv->v) cl_SV_inner<_cl_ring_element> (len); + for (var uintL i = 0; i < len; i++) + init1(_cl_ring_element, hv->v[i]) (); + return hv; +} + +// An empty vector. +const cl_SV_ringelt cl_null_SV_ringelt = cl_SV_ringelt((uintL)0); + +CL_PROVIDE_END(cl_SV_ringelt) diff --git a/src/vector/cl_SV_ringelt_debug.cc b/src/vector/cl_SV_ringelt_debug.cc new file mode 100644 index 0000000..b46a9d6 --- /dev/null +++ b/src/vector/cl_SV_ringelt_debug.cc @@ -0,0 +1,25 @@ +// cl_SV_ringelt debugging support. + +// General includes. +#include "cl_sysdep.h" + +// Specification. + + +// Implementation. + +#include "cl_SV_ringelt.h" +#include "cl_io.h" + +extern void cl_dprint_unknown (cl_heap* pointer); +static void dprint (cl_heap* pointer) +{ +// var const cl_SV_ringelt& obj = *(const cl_SV_ringelt*)&pointer; + fprint(cl_debugout, "(cl_SV_ringelt) "); + cl_dprint_unknown(pointer); +} +AT_INITIALIZATION(dprint_SV_ringelt) +{ cl_register_type_printer(cl_class_svector_ringelt,dprint); } + +// This dummy links in this module when requires it. +int cl_SV_ringelt_debug_module; diff --git a/src/vector/output/Makeflags b/src/vector/output/Makeflags new file mode 100644 index 0000000..da6ad7c --- /dev/null +++ b/src/vector/output/Makeflags @@ -0,0 +1,4 @@ +# This file contains additional flags for the main Makefile. + +include $(srcdir)/vector/Makeflags +SUBDIR_INCLUDES += diff --git a/src/vector/output/cl_GV_number_aprint.cc b/src/vector/output/cl_GV_number_aprint.cc new file mode 100644 index 0000000..dae97cf --- /dev/null +++ b/src/vector/output/cl_GV_number_aprint.cc @@ -0,0 +1,39 @@ +// print_vector(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_GV_complex.h" +#include "cl_GV_real.h" +#include "cl_GV_rational.h" +#include "cl_GV_integer.h" +#include "cl_GV_io.h" + + +// Implementation. + +#include "cl_output.h" + +void print_vector (cl_ostream stream, const cl_print_flags& flags, void (* printfun) (cl_ostream, const cl_print_flags&, const cl_number&), const cl_GV_number& vector) +{ + var uintL len = vector.length(); + if (flags.vector_syntax == vsyntax_commonlisp) { + fprintchar(stream,'#'); + fprintchar(stream,'('); + } else + fprintchar(stream,'['); + for (var uintL i = 0; i < len; i++) { + if (i > 0) { + if (flags.vector_syntax == vsyntax_algebraic) + fprintchar(stream,','); + fprintchar(stream,' '); + } + // The conversion to cl_number below is needed for SGI CC. + printfun(stream,flags,(cl_number)vector[i]); + } + if (flags.vector_syntax == vsyntax_commonlisp) + fprintchar(stream,')'); + else + fprintchar(stream,']'); +} diff --git a/src/vector/output/cl_SV_aprint.cc b/src/vector/output/cl_SV_aprint.cc new file mode 100644 index 0000000..1891c25 --- /dev/null +++ b/src/vector/output/cl_SV_aprint.cc @@ -0,0 +1,35 @@ +// fprint() for cl_SV_ringelt. + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_SV_ringelt.h" + + +// Implementation. + +#include "cl_output.h" + +void fprint (cl_ostream stream, const cl_ring& R, const cl_SV_ringelt& vector) +{ + var const cl_print_flags& flags = cl_default_print_flags; + var uintL len = vector.length(); + if (flags.vector_syntax == vsyntax_commonlisp) { + fprintchar(stream,'#'); + fprintchar(stream,'('); + } else + fprintchar(stream,'['); + for (var uintL i = 0; i < len; i++) { + if (i > 0) { + if (flags.vector_syntax == vsyntax_algebraic) + fprintchar(stream,','); + fprintchar(stream,' '); + } + R->_fprint(stream,vector[i]); + } + if (flags.vector_syntax == vsyntax_commonlisp) + fprintchar(stream,')'); + else + fprintchar(stream,']'); +} diff --git a/src/vector/output/cl_SV_number_aprint.cc b/src/vector/output/cl_SV_number_aprint.cc new file mode 100644 index 0000000..762aa22 --- /dev/null +++ b/src/vector/output/cl_SV_number_aprint.cc @@ -0,0 +1,38 @@ +// print_vector(). + +// General includes. +#include "cl_sysdep.h" + +// Specification. +#include "cl_SV_complex.h" +#include "cl_SV_real.h" +#include "cl_SV_rational.h" +#include "cl_SV_integer.h" +#include "cl_SV_io.h" + + +// Implementation. + +#include "cl_output.h" + +void print_vector (cl_ostream stream, const cl_print_flags& flags, void (* printfun) (cl_ostream, const cl_print_flags&, const cl_number&), const cl_SV_number& vector) +{ + var uintL len = vector.length(); + if (flags.vector_syntax == vsyntax_commonlisp) { + fprintchar(stream,'#'); + fprintchar(stream,'('); + } else + fprintchar(stream,'['); + for (var uintL i = 0; i < len; i++) { + if (i > 0) { + if (flags.vector_syntax == vsyntax_algebraic) + fprintchar(stream,','); + fprintchar(stream,' '); + } + printfun(stream,flags,vector[i]); + } + if (flags.vector_syntax == vsyntax_commonlisp) + fprintchar(stream,')'); + else + fprintchar(stream,']'); +} diff --git a/tests/.gdbinit b/tests/.gdbinit new file mode 100644 index 0000000..39a8ef3 --- /dev/null +++ b/tests/.gdbinit @@ -0,0 +1,6 @@ +break cl_abort + +define cprint +call ($1).debug_print() +end + diff --git a/tests/FILES b/tests/FILES new file mode 100644 index 0000000..e0abaf5 --- /dev/null +++ b/tests/FILES @@ -0,0 +1,12 @@ +Files in this directory +======================= + +Makefile.in master Makefile, instantiated by running "configure" + +exam* test result for specific input (like a pupils' exam) + +test* test coherence of results among each other, + for random input + +main.cc playing around + diff --git a/tests/Makefile.in b/tests/Makefile.in new file mode 100644 index 0000000..2c3b8e5 --- /dev/null +++ b/tests/Makefile.in @@ -0,0 +1,186 @@ +# Makefile for cln/tests + +#### Start of system configuration section. #### + +# Directories used by "make": +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ + +# Programs used by "make": +# C compiler +CC = @CC@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +# C++ compiler +CXX = @CXX@ +CXXFLAGS = @CXXFLAGS@ +CXXCPP = @CXXCPP@ +INCLUDES = -I../include -I$(top_srcdir)/include -I$(srcdir) -I$(top_srcdir)/src -I$(top_srcdir)/src/base -I$(top_srcdir)/src/float -I$(top_srcdir)/src/float/lfloat -I$(top_srcdir)/src/integer -I$(top_srcdir)/src/base/random -I$(top_srcdir)/src/base/digitseq -I$(top_srcdir)/src/base/digit -I../src/base -I$(top_srcdir)/src/base @GMP_INCLUDES@ +CPPFLAGS += $(INCLUDES) +LIBTOOL = @LIBTOOL@ +LIBTOOL_LINK = $(LIBTOOL) --mode=link +MV = mv +LN = ln +RM = rm -f +@SET_MAKE@ + +#### End of system configuration section. #### + +SHELL = /bin/sh + +# Needed by $(LIBTOOL). +top_builddir = .. + +VPATH = $(srcdir) + +FILES_CC := $(notdir $(wildcard $(srcdir)/*.cc)) +FILES_CC := $(filter-out %.i.cc, $(FILES_CC)) + +FILES_I_CC := $(patsubst %.cc,%.i.cc,$(FILES_CC)) + +FILES_S := $(patsubst %.cc,%.s,$(FILES_CC)) + +FILES_O := $(patsubst %.cc,%.o,$(FILES_CC)) + +OBJECTS = $(FILES_O) + +LIBS = ../src/libcln.la -lm +LIBDEPS = ../src/libcln.la + +PROGRAMS = exam tests timemul timesquare timediv timesqrt timegcd timefact timeprint timeLFsqrt timeRAtoLF timeLFRAmul timeRALFdiv timepi timeexp1 timeeuler timecatalan timezeta3 timeLFln timeLFexp timeLFsin timeLFcos timeLFsinh timeLFcosh timeLFatan timeLFatanh timerecip2adic timediv2adic timeMIpow2recip timeMIpow2div timeMImisc5 timeUPMImul timesqrtmodp main +MODULES_exam = exam exam_I exam_RA exam_SF exam_FF exam_DF exam_LF exam_I_gcd exam_I_sqrtp +MODULES_tests = tests \ + test_I \ + test_I_abs test_I_compare test_I_plus test_I_minus test_I_plus1 test_I_minus1 test_I_mul test_I_div \ + test_I_gcd test_I_xgcd \ + test_I_ash test_I_evenp test_I_oddp test_I_lognot test_I_logand test_I_logandc1 test_I_logandc2 test_I_logior test_I_logorc1 test_I_logorc2 test_I_logxor test_I_lognand test_I_lognor test_I_logeqv test_I_boole test_I_logbitp test_I_logtest test_I_ldb test_I_ldbtest test_I_mkf test_I_dpb test_I_dpf test_I_logcount test_I_ilength test_I_ord2 test_I_power2p \ + test_I_isqrt test_I_sqrtp \ + test_I_GV \ + test_MI \ + test_MI_canonhom test_MI_plus test_MI_minus test_MI_mul test_MI_recip test_MI_div test_MI_expt \ + test_nt \ + test_nt_jacobi +MODULES_timemul = timemul +MODULES_timesquare = timesquare +MODULES_timediv = timediv +MODULES_timesqrt = timesqrt +MODULES_timegcd = timegcd +MODULES_timefact = timefact +MODULES_timeprint = timeprint +MODULES_timeLFsqrt = timeLFsqrt +MODULES_timeRAtoLF = timeRAtoLF +MODULES_timeLFRAmul = timeLFRAmul +MODULES_timeRALFdiv = timeRALFdiv +MODULES_timepi = timepi +MODULES_timeexp1 = timeexp1 +MODULES_timeeuler = timeeuler +MODULES_timecatalan = timecatalan +MODULES_timezeta3 = timezeta3 +MODULES_timeLFln = timeLFln +MODULES_timeLFexp = timeLFexp +MODULES_timeLFsin = timeLFsin +MODULES_timeLFcos = timeLFcos +MODULES_timeLFsinh = timeLFsinh +MODULES_timeLFcosh = timeLFcosh +MODULES_timeLFatan = timeLFatan +MODULES_timeLFatanh = timeLFatanh +MODULES_timerecip2adic = timerecip2adic +MODULES_timediv2adic = timediv2adic +MODULES_timeMIpow2recip = timeMIpow2recip +MODULES_timeMIpow2div = timeMIpow2div +MODULES_timeMImisc5 = timeMImisc5 +MODULES_timeUPMImul = timeUPMImul +MODULES_timesqrtmodp = timesqrtmodp +MODULES_main = main + +all : exam tests + +%.s : %.c + $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -S $< -o $@ + +%.s : %.cc + $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -S $< -o $@ + +ifdef notyet + +%.o : %.c + $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ + +%.o : %.cc + $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ + +else + +$(FILES_O) : %.o : %.s + $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ + +endif + +%.i : %.c + $(CPP) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) $< > $@ + +%.i.cc : %.cc + $(CXXCPP) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) $< > $@ + +../src/libcln.a : + cd ../src ; $(MAKE) libcln.a + +exam : $(patsubst %,%.o,$(MODULES_exam)) +tests : $(patsubst %,%.o,$(MODULES_tests)) +timemul : $(patsubst %,%.o,$(MODULES_timemul)) +timesquare : $(patsubst %,%.o,$(MODULES_timesquare)) +timediv : $(patsubst %,%.o,$(MODULES_timediv)) +timesqrt : $(patsubst %,%.o,$(MODULES_timesqrt)) +timegcd : $(patsubst %,%.o,$(MODULES_timegcd)) +timefact : $(patsubst %,%.o,$(MODULES_timefact)) +timeprint : $(patsubst %,%.o,$(MODULES_timeprint)) +timeLFsqrt : $(patsubst %,%.o,$(MODULES_timeLFsqrt)) +timeRAtoLF : $(patsubst %,%.o,$(MODULES_timeRAtoLF)) +timeLFRAmul : $(patsubst %,%.o,$(MODULES_timeLFRAmul)) +timeRALFdiv : $(patsubst %,%.o,$(MODULES_timeRALFdiv)) +timepi : $(patsubst %,%.o,$(MODULES_timepi)) +timeexp1 : $(patsubst %,%.o,$(MODULES_timeexp1)) +timeeuler : $(patsubst %,%.o,$(MODULES_timeeuler)) +timecatalan : $(patsubst %,%.o,$(MODULES_timecatalan)) +timezeta3 : $(patsubst %,%.o,$(MODULES_timezeta3)) +timeLFln : $(patsubst %,%.o,$(MODULES_timeLFln)) +timeLFexp : $(patsubst %,%.o,$(MODULES_timeLFexp)) +timeLFsin : $(patsubst %,%.o,$(MODULES_timeLFsin)) +timeLFcos : $(patsubst %,%.o,$(MODULES_timeLFcos)) +timeLFsinh : $(patsubst %,%.o,$(MODULES_timeLFsinh)) +timeLFcosh : $(patsubst %,%.o,$(MODULES_timeLFcosh)) +timeLFatan : $(patsubst %,%.o,$(MODULES_timeLFatan)) +timeLFatanh : $(patsubst %,%.o,$(MODULES_timeLFatanh)) +timerecip2adic : $(patsubst %,%.o,$(MODULES_timerecip2adic)) +timediv2adic : $(patsubst %,%.o,$(MODULES_timediv2adic)) +timeMIpow2recip : $(patsubst %,%.o,$(MODULES_timeMIpow2recip)) +timeMIpow2div : $(patsubst %,%.o,$(MODULES_timeMIpow2div)) +timeMImisc5 : $(patsubst %,%.o,$(MODULES_timeMImisc5)) +timeUPMImul : $(patsubst %,%.o,$(MODULES_timeUPMImul)) +timesqrtmodp : $(patsubst %,%.o,$(MODULES_timesqrtmodp)) +main : $(patsubst %,%.o,$(MODULES_main)) +$(PROGRAMS) : % : $(LIBDEPS) + $(LIBTOOL_LINK) $(CXX) $(CXXFLAGS) $(TARGET_ARCH) $(patsubst %,%.o,$(MODULES_$(*F))) $(LIBS) -o $@ + + +install : all + +installdirs : + +uninstall : + +check : all + ./exam + ./tests + +mostlyclean : clean + +clean : force + $(RM) *.s *.o *.a exam tests main a.out core + +distclean : clean + $(RM) config.status config.log config.cache Makefile + +maintainer-clean : distclean + +force : diff --git a/tests/exam.cc b/tests/exam.cc new file mode 100644 index 0000000..b1a4e7b --- /dev/null +++ b/tests/exam.cc @@ -0,0 +1,47 @@ +#include +#include +#include + +extern int test_integer(); +extern int test_rational(); +extern int test_sfloat(); +extern int test_ffloat(); +extern int test_dfloat(); +extern int test_lfloat(); + +int test_elementary (void) +{ + int error = 0; + error |= test_integer(); + error |= test_rational(); + error |= test_sfloat(); + error |= test_ffloat(); + error |= test_dfloat(); + error |= test_lfloat(); + return error; +} + +extern int test_gcd (void); +extern int test_xgcd (void); +extern int test_sqrtp (void); + +int test_all (void) +{ + int error = 0; + error |= test_elementary(); + error |= test_gcd(); + error |= test_xgcd(); + error |= test_sqrtp(); + return error; +} + +int main () +{ + if (!test_all()) { + fprint (cl_stdout, "Tests passed.\n"); + exit(0); + } else { + fprint (cl_stdout, "Tests failed.\n"); + exit(1); + } +} diff --git a/tests/exam.h b/tests/exam.h new file mode 100644 index 0000000..6d5b2dc --- /dev/null +++ b/tests/exam.h @@ -0,0 +1,119 @@ +#ifndef _EXAM_H +#define _EXAM_H + +#include +#include + +// Michael Stoll 23. 3. 1993 +// C++ version: Bruno Haible 1.11.1995 + +struct plus_test { + const char * arg1; + const char * arg2; + const char * result; +}; + +struct minus_test { + const char * arg1; + const char * arg2; + const char * result; +}; + +struct mul_test { + const char * arg1; + const char * arg2; + const char * result; +}; + +struct floor_test { + const char * arg1; + const char * arg2; + const char * result1; + const char * result2; +}; + +struct div_test { + const char * arg1; + const char * arg2; + const char * result; +}; + +#define num_elements(array) (sizeof(array)/sizeof(array[0])) + +#define DO_BINOP_TEST(typename,type,rtype,opname,op) \ +static int test_##typename##_##opname (void) \ +{ \ + int error = 0; \ + for (unsigned int i = 0; i < num_elements(typename##_##opname##_tests); i++) { \ + opname##_test& test = typename##_##opname##_tests[i]; \ + type arg1 = type(test.arg1); \ + type arg2 = type(test.arg2); \ + rtype computed_result = arg1 op arg2; \ + rtype result = rtype(test.result); \ + if (computed_result != result) { \ + fprint(cl_stderr, "Error in " #typename "_" #opname "_tests["); \ + fprintdecimal(cl_stderr, i); \ + fprint(cl_stderr, "] !\n"); \ + fprint(cl_stderr, "Result should be: "); \ + fprint(cl_stderr, result); \ + fprint(cl_stderr, "\n"); \ + fprint(cl_stderr, "Result computed : "); \ + fprint(cl_stderr, computed_result); \ + fprint(cl_stderr, "\n"); \ + fprint(cl_stderr, "\n"); \ + error = 1; \ + } \ + } \ + return error; \ +} + +#define DO_FLOOR_TEST(typename,type) \ +static int test_##typename##_floor (void) \ +{ \ + int error = 0; \ + for (unsigned int i = 0; i < num_elements(typename##_floor_tests); i++) { \ + floor_test& test = typename##_floor_tests[i]; \ + type arg1 = type(test.arg1); \ + type arg2 = type(test.arg2); \ + type##_div_t computed_result = floor2(arg1,arg2); \ + cl_I result1 = cl_I(test.result1); \ + type result2 = type(test.result2); \ + if ((computed_result.quotient != result1) || (computed_result.remainder != result2)) { \ + fprint(cl_stderr, "Error in " #typename "_floor_tests["); \ + fprintdecimal(cl_stderr, i); \ + fprint(cl_stderr, "] !\n"); \ + fprint(cl_stderr, "Results should be: "); \ + fprint(cl_stderr, result1); \ + fprint(cl_stderr, ", "); \ + fprint(cl_stderr, result2); \ + fprint(cl_stderr, "\n"); \ + fprint(cl_stderr, "Results computed : "); \ + fprint(cl_stderr, computed_result.quotient); \ + fprint(cl_stderr, ", "); \ + fprint(cl_stderr, computed_result.remainder); \ + fprint(cl_stderr, "\n"); \ + fprint(cl_stderr, "\n"); \ + error = 1; \ + } \ + } \ + return error; \ +} + +#define DO_TESTS(typename,type,qtype) \ + DO_BINOP_TEST(typename,type,type,plus,+) \ + DO_BINOP_TEST(typename,type,type,minus,-) \ + DO_BINOP_TEST(typename,type,type,mul,*) \ + DO_FLOOR_TEST(typename,type) \ + DO_BINOP_TEST(typename,type,qtype,div,/) \ +int test_##typename (void) \ +{ \ + int error = 0; \ + error |= test_##typename##_plus(); \ + error |= test_##typename##_minus(); \ + error |= test_##typename##_mul(); \ + error |= test_##typename##_floor(); \ + error |= test_##typename##_div(); \ + return error; \ +} + +#endif /* _EXAM_H */ diff --git a/tests/exam_DF.cc b/tests/exam_DF.cc new file mode 100644 index 0000000..fb6c915 --- /dev/null +++ b/tests/exam_DF.cc @@ -0,0 +1,7 @@ +#include "exam_DF_plus.cc" +#include "exam_DF_minus.cc" +#include "exam_DF_mul.cc" +#include "exam_DF_div.cc" +#include "exam_DF_floor.cc" + +DO_TESTS(dfloat,cl_DF,cl_DF) diff --git a/tests/exam_DF_div.cc b/tests/exam_DF_div.cc new file mode 100644 index 0000000..02edee8 --- /dev/null +++ b/tests/exam_DF_div.cc @@ -0,0 +1,457 @@ +#include "exam.h" +#include +#include + +static div_test dfloat_div_tests[] = { + +{ "-0.651381628953465d0", "-0.9237050214744277d0", + "0.7051835962889135d0" }, + +{ "0.5067986732438687d0", "0.6260017267692811d0", + "0.8095803119575966d0" }, + +{ "-0.8399445051045212d0", "0.1829250718359493d0", + "-4.591740742120902d0" }, + +{ "-0.5987041550692662d0", "-0.4124053212463479d0", + "1.4517372211878756d0" }, + +{ "0.5861382519823647d0", "-0.7560374696447822d0", + "-0.7752767230673855d0" }, + +{ "-0.012882644582824954d0", "-0.4671067448591679d0", + "0.02757965866390787d0" }, + +{ "-0.7830198970435231d0", "2.1690164135025935d9", + "-3.610022921767931d-10" }, + +{ "-0.2339206226652567d0", "2.729373380002701d9", + "-8.57048817062271d-11" }, + +{ "-0.2285806315782951d0", "-2.602073870582813d9", + "8.784555817667759d-11" }, + +{ "-0.5298716781559242d0", "1.3509547453340487d9", + "-3.9222015392151683d-10" }, + +{ "0.7287190523338418d0", "-8.244205871151566d9", + "-8.839166121309548d-11" }, + +{ "0.18973054487786212d0", "6.557593452200545d9", + "2.893295326415727d-11" }, + +{ "0.5084032300982587d0", "4.5431682148621014d-11", + "1.119049980221105d10" }, + +{ "0.6621212705475221d0", "-1.838873437953206d-11", + "-3.600689731450519d10" }, + +{ "-0.4041791750277005d0", "7.707875701307648d-11", + "-5.243716825365141d9" }, + +{ "-0.09569063343466655d0", "4.789751448902253d-11", + "-1.9978204392338054d9" }, + +{ "-0.6471008513340974d0", "1.890250884404079d-11", + "-3.4233596009563705d10" }, + +{ "-0.4301276572683971d0", "9.134844738134672d-11", + "-4.708647706651978d9" }, + +{ "-0.5061027989171409d0", "4.246468515299164d19", + "-1.1918204434902915d-20" }, + +{ "-0.9601783702217944d0", "7.495754288877955d19", + "-1.2809629734615065d-20" }, + +{ "-0.6477754868655262d0", "-8.507334914535449d19", + "7.614317449272521d-21" }, + +{ "0.1934462826116784d0", "3.6173521417193476d19", + "5.347731573618163d-21" }, + +{ "-0.7794308505212441d0", "4.172217291786081d19", + "-1.8681453913144062d-20" }, + +{ "-0.8462346361305484d0", "7.378170819620111d19", + "-1.1469436759043748d-20" }, + +{ "0.9783005897625496d0", "6.175045007596078d-21", + "1.584280905740958d20" }, + +{ "-0.9700832605850568d0", "-1.7695051741124812d-21", + "5.482229013948009d20" }, + +{ "0.07062591404368701d0", "-8.855398515753737d-21", + "-7.975464223100028d18" }, + +{ "0.4751383409805402d0", "-8.1371029771106d-21", + "-5.8391585103087485d19" }, + +{ "-0.5103510786836052d0", "8.302178001281015d-21", + "-6.14719509271975d19" }, + +{ "0.7148807879199733d0", "4.338856119331781d-21", + "1.6476250151158982d20" }, + +{ "4.180670608983218d9", "-0.8621420131862095d0", + "-4.849167010818503d9" }, + +{ "3.202209376555907d9", "0.008113117870009012d0", + "3.9469528581523615d11" }, + +{ "7.767843042272955d9", "-0.04145956871894663d0", + "-1.8735947532235483d11" }, + +{ "1.1937839884817846d9", "0.45557753834605563d0", + "2.6203749921818776d9" }, + +{ "-2.4205138097471213d9", "-0.3737757916008485d0", + "6.475844247109412d9" }, + +{ "-7.534066568550288d9", "-0.3609372553147958d0", + "2.0873618496321087d10" }, + +{ "6.098867840095913d9", "3.0464612528039427d9", + "2.0019515542771322d0" }, + +{ "4.956687716396978d9", "7.035407926465974d9", + "0.704534515724495d0" }, + +{ "6.969049109639194d9", "-8.115758334653503d9", + "-0.8587058438990264d0" }, + +{ "-8.0699835500126705d9", "-1.1896420666819375d9", + "6.783539163608158d0" }, + +{ "-2.229793060172571d9", "-2.658809828346301d9", + "0.8386433043838396d0" }, + +{ "3.0672739776038485d9", "-7.988270854370873d9", + "-0.3839722054398737d0" }, + +{ "2.477055391151669d9", "-1.3522358047779648d-11", + "-1.8318220700851785d20" }, + +{ "1.1318646612469008d9", "-8.457695758685169d-11", + "-1.3382659929385544d19" }, + +{ "-7.978772126259147d9", "6.210468872769038d-11", + "-1.2847294286013678d20" }, + +{ "-9.057338243339752d9", "7.364415429198257d-11", + "-1.2298787772658011d20" }, + +{ "-5.341117220720213d9", "4.7359651161519756d-11", + "-1.1277779902779204d20" }, + +{ "5.838003830912871d9", "-5.0625478501901024d-11", + "-1.153175042225754d20" }, + +{ "6.407156672927742d9", "5.006339136594536d19", + "1.279808758079079d-10" }, + +{ "4.687485139826675d8", "-3.5561755068968083d19", + "-1.3181253655045475d-11" }, + +{ "-5.838044723576891d9", "-6.843985743599882d19", + "8.530182473036721d-11" }, + +{ "3.9279221543350096d9", "-5.882918042982924d19", + "-6.67682623765291d-11" }, + +{ "-9.686323716926361d9", "-3.44800215666902d19", + "2.8092568614527606d-10" }, + +{ "7.301304808910639d9", "1.2845297359643038d19", + "5.684029419085038d-10" }, + +{ "4.380345662298534d9", "-4.352751895415198d-21", + "-1.0063393842668593d30" }, + +{ "8.239490918139045d9", "3.2397577733346748d-21", + "2.5432428886984834d30" }, + +{ "3.8980499504872713d9", "8.311650110069505d-21", + "4.689862901910189d29" }, + +{ "-9.425472285331268d9", "-3.294031046828316d-21", + "2.861379310436876d30" }, + +{ "2.517833161624173d9", "3.6891560299469316d-21", + "6.824957093669991d29" }, + +{ "-5.463519676339016d9", "-7.298583081866205d-22", + "7.485726496576409d30" }, + +{ "1.39357009199772d-11", "0.417842407627649d0", + "3.335157146709649d-11" }, + +{ "8.58494900746665d-11", "-0.6481371063028898d0", + "-1.3245575548724563d-10" }, + +{ "-9.310282234439046d-11", "0.9146343299129254d0", + "-1.0179239866631073d-10" }, + +{ "-8.800556770159418d-11", "-0.9305573406536135d0", + "9.45729659601417d-11" }, + +{ "-1.3361456473382827d-11", "0.06420301636905124d0", + "-2.081125970247039d-10" }, + +{ "6.1406425153971765d-12", "-0.3082496074575478d0", + "-1.992100676476244d-11" }, + +{ "-3.6962256202372035d-11", "3.089420488573177d9", + "-1.1964139015418631d-20" }, + +{ "-6.145126590884831d-11", "-6.225608984106817d9", + "9.870723661849874d-21" }, + +{ "9.052281678541901d-11", "-6.9187138778508625d9", + "-1.3083763598782874d-20" }, + +{ "-3.4950245360118636d-11", "7.543342567738434d9", + "-4.633257080169575d-21" }, + +{ "-3.482822570743636d-11", "-3.87599225187502d9", + "8.985628309909062d-21" }, + +{ "-9.42226868788213d-11", "7.501937454180854d9", + "-1.2559780383974101d-20" }, + +{ "-4.8165035309367155d-11", "9.484620130429997d-11", + "-0.5078225026096383d0" }, + +{ "6.880022773725747d-11", "-9.699156104509544d-11", + "-0.7093424107822056d0" }, + +{ "1.5817962388036865d-11", "-7.11651152335492d-11", + "-0.22227129593095693d0" }, + +{ "-7.0140750853949335d-12", "-4.4677941652531186d-11", + "0.15699190307254357d0" }, + +{ "-2.6947489262085355d-11", "8.365454450205894d-11", + "-0.3221282169723859d0" }, + +{ "8.703167674410303d-11", "-4.88739813223768d-11", + "-1.7807363834354917d0" }, + +{ "1.165112061543483d-12", "-5.899528740399518d19", + "-1.9749239520860124d-32" }, + +{ "7.126386981630328d-12", "5.091741402945837d19", + "1.3995971942933598d-31" }, + +{ "-7.132349854872655d-13", "7.70347159367981d19", + "-9.258617712985763d-33" }, + +{ "4.507266517270466d-11", "-1.6192737232544485d19", + "-2.7835111831566513d-30" }, + +{ "-3.025128309814261d-11", "-5.606736896306867d19", + "5.395523930874836d-31" }, + +{ "-5.390258677516223d-11", "6.628750121976767d18", + "-8.131636550373976d-30" }, + +{ "-8.484515181627938d-11", "6.226893371743352d-21", + "-1.3625598954575508d10" }, + +{ "5.110456708789676d-11", "-7.434814854731122d-21", + "-6.873683889434922d9" }, + +{ "-7.784815533665352d-11", "-8.942884975553875d-21", + "8.705038200698988d9" }, + +{ "6.06871371776654d-11", "-8.4720755768444d-21", + "-7.163195916657484d9" }, + +{ "6.395725883763629d-11", "3.2465500186809204d-21", + "1.970006883295217d10" }, + +{ "8.23766365482318d-11", "3.5665958051648335d-21", + "2.3096712116618633d10" }, + +{ "-6.882125490660233d19", "0.680553203393516d0", + "-1.0112545876418106d20" }, + +{ "-8.955858402134752d19", "0.11144092291315044d0", + "-8.03641801236189d20" }, + +{ "4.517225460957592d19", "-0.5804969398143229d0", + "-7.781652496570381d19" }, + +{ "-9.741926397385082d19", "-0.9037000739789977d0", + "1.0780043819728059d20" }, + +{ "9.654390326446178d19", "-0.061963385089831124d0", + "-1.558079874501655d21" }, + +{ "9.50855454738802d19", "0.30375471599023185d0", + "3.130339727036138d20" }, + +{ "4.323538184184934d19", "-2.6027608151521606d9", + "-1.661135421670383d10" }, + +{ "4.0554081767557594d17", "4.814123702784068d9", + "8.423979995384136d7" }, + +{ "5.12727309625028d19", "1.761988796449604d9", + "2.9099351293162037d10" }, + +{ "-7.335661993746345d19", "-4.961351435504d9", + "1.4785612527368061d10" }, + +{ "3.7135994768593306d18", "3.273427798269768d8", + "1.1344681189614824d10" }, + +{ "1.3911083524706402d19", "8.651242909451927d9", + "1.6079866985942366d9" }, + +{ "6.473382688386894d19", "-3.700509647679497d-11", + "-1.7493219325738552d30" }, + +{ "7.25328632809461d19", "6.793518758100849d-11", + "1.0676773828651782d30" }, + +{ "7.053090091571119d19", "8.009021819073383d-11", + "8.806431360661643d29" }, + +{ "-1.6322872380348074d19", "-1.234889420758779d-11", + "1.3218084231637898d30" }, + +{ "-7.716951191497702d19", "-2.473367210466666d-11", + "3.12001839388891d30" }, + +{ "-2.1174708383466066d19", "-9.66632270128099d-11", + "2.1905650202077337d29" }, + +{ "4.0902039392392786d18", "-5.029423690873208d19", + "-0.08132549951322827d0" }, + +{ "1.4562115759233494d17", "4.2665150414889705d19", + "0.0034131171735308037d0" }, + +{ "-3.309692589578652d19", "1.1329455009949342d19", + "-2.9213166799922274d0" }, + +{ "3.059130103268258d19", "-7.719433592654628d19", + "-0.3962894513632647d0" }, + +{ "5.622979366632147d19", "-8.407251901594788d19", + "-0.6688248945610293d0" }, + +{ "-7.457587910839625d18", "1.102755747735572d19", + "-0.6762683328700153d0" }, + +{ "1.2026615920578564d19", "-3.77964792582931d-21", + "-3.1819407935832407d39" }, + +{ "-2.74643694419756d19", "2.538907641816601d-22", + "-1.0817396028760112d41" }, + +{ "8.267361397156658d18", "-4.986401395715489d-21", + "-1.6579815263689556d39" }, + +{ "9.876393891158812d19", "-5.792612775193684d-22", + "-1.7049981199250076d41" }, + +{ "3.927461252713038d17", "4.810589424292295d-21", + "8.164199656866003d37" }, + +{ "7.29943837795987d19", "-4.8820727437034755d-21", + "-1.4951514983823475d40" }, + +{ "-7.837850970911807d-21", "0.41514160181315674d0", + "-1.8879945870708947d-20" }, + +{ "1.1499234744049124d-21", "0.4643166529612681d0", + "2.4765932194571437d-21" }, + +{ "-1.094368243984769d-21", "0.9008053219044149d0", + "-1.2148776404552516d-21" }, + +{ "2.4821206327531197d-21", "0.22988631081892086d0", + "1.0797165885654937d-20" }, + +{ "-4.56226662576732d-22", "0.6695285124602162d0", + "-6.814148375851899d-22" }, + +{ "6.442796853653397d-21", "-0.0419134640377401d0", + "-1.5371663978553802d-19" }, + +{ "-5.584403218169678d-21", "-8.092869169805251d9", + "6.9003997235062955d-31" }, + +{ "-9.796722996869492d-21", "-3.2988270899833827d9", + "2.9697594719700335d-30" }, + +{ "9.441829923771915d-22", "5.464575083746736d9", + "1.7278250877830762d-31" }, + +{ "-6.419360319610147d-21", "-7.333962810289677d9", + "8.752921831841952d-31" }, + +{ "7.973734412555454d-21", "-9.367577614661436d9", + "-8.512055880994846d-31" }, + +{ "8.105484193881594d-21", "-8.664550975192905d9", + "-9.354765431108951d-31" }, + +{ "-5.3151708182942476d-21", "-3.406928289732576d-11", + "1.560106455516696d-10" }, + +{ "-7.026602845639829d-21", "-9.92483846943868d-11", + "7.079815824989677d-11" }, + +{ "-5.901970468193158d-21", "2.074489043942647d-11", + "-2.8450236868815825d-10" }, + +{ "-6.40466723844613d-21", "-2.551008177490094d-11", + "2.510641594550906d-10" }, + +{ "8.056066940872177d-21", "4.645883100460603d-11", + "1.7340227394170724d-10" }, + +{ "7.453765056481805d-21", "6.956136187014756d-11", + "1.0715381148511711d-10" }, + +{ "7.357434693258832d-21", "-7.093525088486332d19", + "-1.0372042956753416d-40" }, + +{ "-3.3759558579798473d-21", "9.991075630444324d19", + "-3.3789713769084054d-41" }, + +{ "6.908026973557955d-21", "-4.20805893397862d19", + "-1.6416183998227845d-40" }, + +{ "5.181767322756247d-21", "7.46986056263721d19", + "6.936899664063931d-41" }, + +{ "-5.7217313601659264d-21", "5.604979023134118d19", + "-1.0208301113260054d-40" }, + +{ "-9.340193892824771d-21", "9.147101848766205d19", + "-1.021109641857176d-40" }, + +{ "8.331002176099931d-21", "2.0276444314093977d-21", + "4.108709617449606d0" }, + +{ "-3.747505523684784d-21", "4.394623185543803d-21", + "-0.8527478615259381d0" }, + +{ "-3.310403953328861d-21", "2.3420390876737627d-21", + "-1.413470838617356d0" }, + +{ "6.23845405853013d-21", "-8.933620117412232d-21", + "-0.6983119918397873d0" }, + +{ "-4.276770609150315d-21", "6.853299965034864d-21", + "-0.624045442483205d0" }, + +{ "-8.847946637724495d-21", "6.33827952828724d-21", + "-1.3959539963860554d0" }, + +}; diff --git a/tests/exam_DF_floor.cc b/tests/exam_DF_floor.cc new file mode 100644 index 0000000..2ee83d4 --- /dev/null +++ b/tests/exam_DF_floor.cc @@ -0,0 +1,459 @@ +#include "exam.h" +#include +#include +#include +#include + +static floor_test dfloat_floor_tests[] = { + +{ "0.6173351962722496d0", "-0.11820538775792844d0", + "-6", "-0.09189713027532098d0" }, + +{ "-0.17517225806171177d0", "0.1118228341753209d0", + "-2", "0.04847341028893004d0" }, + +{ "-0.9387909021047899d0", "-0.16826318310698907d0", + "5", "-0.09747498656984459d0" }, + +{ "0.8036728904567848d0", "0.6774308237913269d0", + "1", "0.1262420666654578d0" }, + +{ "0.6882568422881421d0", "0.3302150266778784d0", + "2", "0.02782678893238538d0" }, + +{ "0.3618917435888378d0", "0.5454396894763598d0", + "0", "0.3618917435888378d0" }, + +{ "-0.478470818234076d0", "9.035797971846054d9", + "-1", "9.035797971367584d9" }, + +{ "0.6423779722022549d0", "2.0589504447793393d9", + "0", "0.6423779722022549d0" }, + +{ "0.21698095744051404d0", "1.570908384361449d9", + "0", "0.21698095744051404d0" }, + +{ "0.24033995915823747d0", "6.968395233824382d9", + "0", "0.24033995915823747d0" }, + +{ "-0.8531247643149816d0", "-5.299783511441018d9", + "0", "-0.8531247643149817d0" }, + +{ "-0.5134978162655872d0", "2.297671112225289d9", + "-1", "2.297671111711791d9" }, + +{ "0.6192405432591311d0", "5.4403538407469436d-11", + "11382357864", "3.744539199218032d-11" }, + +{ "-0.20340731452742233d0", "5.44351944436815d-12", + "-37366875715", "2.4681729170135434d-12" }, + +{ "-0.29394735220898527d0", "-3.6328318262890404d-12", + "80914109505", "-3.3847154436219604d-12" }, + +{ "-0.8359336184185098d0", "6.064791537508077d-11", + "-13783385847", "1.2432123964511977d-11" }, + +{ "-0.9762544843227843d0", "2.2086465633336306d-11", + "-44201480696", "1.1997821346734454d-11" }, + +{ "-0.2919696169517234d0", "6.922295436251983d-11", + "-4217815025", "3.3402028237741715d-11" }, + +{ "0.9452118035872986d0", "-1.1093667270485797d19", + "-1", "-1.1093667270485797d19" }, + +{ "0.3379784391207531d0", "-3.0106029588222304d19", + "-1", "-3.0106029588222304d19" }, + +{ "0.3907483945162724d0", "-9.823409070968835d19", + "-1", "-9.823409070968835d19" }, + +{ "-0.4293216868359586d0", "5.965415751655242d19", + "-1", "5.965415751655242d19" }, + +{ "0.13727607148241305d0", "-8.310631671228052d19", + "-1", "-8.310631671228052d19" }, + +{ "-0.7478116595122868d0", "7.235991436975452d19", + "-1", "7.235991436975452d19" }, + +{ "-0.9425796643098138d0", "-1.7749544068364875d-21", + "531044437355311857664", "0.0d0" }, + +{ "0.20835281321620536d0", "2.7983277403481253d-21", + "74456186890490986496", "0.0d0" }, + +{ "-0.5404541167071248d0", "9.266841531614177d-22", + "-583212861537931100160", "0.0d0" }, + +{ "-0.06796825059990208d0", "-6.350644782153893d-21", + "10702574767038046208", "0.0d0" }, + +{ "0.30647600932087793d0", "-9.704243038852408d-21", + "-31581650221851901952", "0.0d0" }, + +{ "-0.7939481974521416d0", "-7.44148349933678d-21", + "106692193501860495360", "0.0d0" }, + +{ "2.622471924924206d9", "0.3428958732728865d0", + "7648012499", "0.2776496600055352d0" }, + +{ "9.96303133513731d9", "-0.6839887200892081d0", + "-14566075496", "-0.09450688719173875d0" }, + +{ "9.438132647041376d8", "-0.9350840745499996d0", + "-1009335193", "-0.15301271996267998d0" }, + +{ "-5.031281076435459d9", "0.8566679205528436d0", + "-5873082155", "0.5244045303768723d0" }, + +{ "-9.504293159523993d9", "-0.17779074115973026d0", + "53457750935", "-0.058079864158457416d0" }, + +{ "5.593337221858664d8", "0.6365106532159245d0", + "878749977", "0.3121177083383602d0" }, + +{ "-9.849085830660753d9", "5.465582064164139d9", + "-2", "1.0820782976675239d9" }, + +{ "6.254242990207708d9", "1.9986128256161973d9", + "3", "2.5840451335911673d8" }, + +{ "-9.644949290710447d9", "3.677515142398587d9", + "-3", "1.3875961364853137d9" }, + +{ "9.966654669106707d9", "3.622741134738514d9", + "2", "2.7211723996296782d9" }, + +{ "-7.024110605080818d9", "-1.3131548351819434d9", + "5", "-4.583364291711011d8" }, + +{ "-4.5982831731090415d8", "-4.587607917895467d9", + "0", "-4.5982831731090415d8" }, + +{ "6.779683583609543d9", "-8.732134194560264d-11", + "-77640625218895380480", "0.0d0" }, + +{ "3.040910010354103d8", "-6.386892985922651d-11", + "-4761172634419539968", "0.0d0" }, + +{ "-9.081490496057175d9", "-8.389512916135551d-11", + "108248125807050637312", "0.0d0" }, + +{ "-2.3391140718625803d9", "4.078343101769488d-11", + "-57354519065541566464", "0.0d0" }, + +{ "9.740679130260033d9", "-4.1307299498162d-11", + "-235810117064018001920", "0.0d0" }, + +{ "4.630742761978566d9", "-8.36053471494181d-11", + "-55388117146413842432", "0.0d0" }, + +{ "6.607827158404311d8", "1.9791074337467208d19", + "0", "6.607827158404311d8" }, + +{ "1.5835379695092866d9", "-5.599741962857091d19", + "-1", "-5.599741962698737d19" }, + +{ "-9.972337740404726d9", "-1.4833907125668299d19", + "0", "-9.972337740404726d9" }, + +{ "-2.8545208802037845d9", "5.460276762513134d19", + "-1", "5.4602767622276825d19" }, + +{ "3.4574292483978963d9", "8.177006210253868d19", + "0", "3.4574292483978963d9" }, + +{ "-6.94800692720856d9", "5.400944544004402d19", + "-1", "5.400944543309601d19" }, + +{ "2.2301147741459103d9", "4.352417825189536d-22", + "5123852680777023531125296857088", "0.0d0" }, + +{ "2.855798499915275d9", "-2.1597757039453335d-21", + "-1322266240285272897749142994944", "0.0d0" }, + +{ "6.247757812861889d9", "-8.000803060408911d-21", + "-780891338743010366964468023296", "0.0d0" }, + +{ "-8.41352264607702d8", "2.4583479152659926d-21", + "-342242958933120698647142465536", "0.0d0" }, + +{ "9.08798064415713d9", "-4.6826703076651156d-21", + "-1940768844921862497464005689344", "0.0d0" }, + +{ "-2.450923950975804d9", "-8.516681149015905d-21", + "287779230910741073293637320704", "0.0d0" }, + +{ "-6.535114995775952d-11", "-0.4217447234387455d0", + "0", "-6.535114995775952d-11" }, + +{ "6.91351782048677d-13", "-0.8578740601420116d0", + "-1", "-0.8578740601413203d0" }, + +{ "-9.879448244992307d-11", "-0.6016918305263045d0", + "0", "-9.879448244992307d-11" }, + +{ "7.820572196574365d-11", "-0.8508242256358738d0", + "-1", "-0.8508242255576681d0" }, + +{ "-4.4420680878896835d-11", "0.6509799475016377d0", + "-1", "0.650979947457217d0" }, + +{ "-8.35377304874932d-11", "-0.7623592484047194d0", + "0", "-8.35377304874932d-11" }, + +{ "-4.697219220983554d-11", "-2.0199834401398075d9", + "0", "-4.697219220983554d-11" }, + +{ "4.027899822164905d-11", "-3.0043885624092436d8", + "-1", "-3.0043885624092436d8" }, + +{ "-9.473748837497406d-11", "-6.081705720880249d8", + "0", "-9.473748837497406d-11" }, + +{ "-6.257060775257221d-11", "4.479345462936419d9", + "-1", "4.479345462936419d9" }, + +{ "-4.076402998599221d-11", "3.0379052042471523d9", + "-1", "3.0379052042471523d9" }, + +{ "3.2516054170046405d-11", "9.075782126517027d9", + "0", "3.2516054170046405d-11" }, + +{ "7.77186165285192d-12", "-7.011585244893556d-11", + "-1", "-6.234399079608364d-11" }, + +{ "-4.129939073543463d-11", "-4.398862671531905d-11", + "0", "-4.129939073543463d-11" }, + +{ "-4.986332353670153d-11", "4.056354917830567d-11", + "-2", "3.126377481990981d-11" }, + +{ "-6.358815251785654d-11", "3.044610839789864d-11", + "-3", "2.7750172675839383d-11" }, + +{ "-1.5218538547762808d-11", "-4.9239841620755075d-11", + "0", "-1.5218538547762808d-11" }, + +{ "-3.714719523899548d-11", "-3.338962509681127d-11", + "1", "-3.757570142184203d-12" }, + +{ "-3.7559900032627426d-11", "-7.103620895893612d19", + "0", "-3.7559900032627426d-11" }, + +{ "3.442771371655891d-11", "3.2650979291930292d19", + "0", "3.442771371655891d-11" }, + +{ "-8.026236668129701d-11", "-7.030175018925641d19", + "0", "-8.026236668129701d-11" }, + +{ "4.0245932625540036d-11", "9.919022649131396d19", + "0", "4.0245932625540036d-11" }, + +{ "6.558019989897738d-11", "9.805879474847002d19", + "0", "6.558019989897738d-11" }, + +{ "-8.950419173616613d-11", "7.8967335533488d19", + "-1", "7.8967335533488d19" }, + +{ "-4.2555105814142415d-11", "-7.367149245343951d-22", + "57763327980", "-5.012024424412273d-22" }, + +{ "-7.125466497249949d-11", "-9.625683307253578d-21", + "7402556545", "-6.2922712544984485d-21" }, + +{ "8.076311292972551d-11", "5.7198456178965606d-21", + "14119806429", "1.262169607592943d-21" }, + +{ "-7.024787982764915d-11", "1.5125149703168537d-21", + "-46444419531", "6.648179051963393d-22" }, + +{ "2.3153240875994985d-11", "-1.5025822462858028d-21", + "-15408967419", "-1.3907844732195436d-21" }, + +{ "9.445189938981536d-11", "-1.8886893988697117d-21", + "-50009228329", "-8.218058303553574d-22" }, + +{ "-8.982223463756733d19", "0.20677548795071854d0", + "-434394983311440412672", "0.0d0" }, + +{ "-2.6872844858317455d19", "0.00946240694180256d0", + "-2839958693765316083712", "0.0d0" }, + +{ "-9.566658458393646d19", "-0.38847162936974444d0", + "246264018659858710528", "0.0d0" }, + +{ "-4.235085548018657d19", "-0.06527446136754045d0", + "648812025299173376000", "0.0d0" }, + +{ "2.8443413501845017d19", "-0.04996947402848739d0", + "-569215787335074643968", "0.0d0" }, + +{ "-4.484750058861429d19", "-0.2338784192921971d0", + "191755616975433072640", "0.0d0" }, + +{ "-2.986802109112903d19", "5.923385648786668d9", + "-5042390090", "3.561083576852057d9" }, + +{ "8.088567504347222d18", "9.070536452627407d9", + "891740807", "8.158341046664973d9" }, + +{ "-3.09688480137261d19", "-6.508291621550677d9", + "4758368219", "-1.75538588669977d9" }, + +{ "4.226418080435591d19", "7.892147197133178d9", + "5355219530", "6.335538696917366d8" }, + +{ "1.4013831972690205d19", "-2.4924246236187544d9", + "-5622570023", "-6.556610185422871d8" }, + +{ "6.1838203826708914d19", "8.941814127664919d9", + "6915621700", "8.062833976289089d9" }, + +{ "-6.916774706038343d18", "3.120694095597196d-11", + "-221642189018039718512504602624", "0.0d0" }, + +{ "9.435687674071892d19", "-3.149833308668829d-11", + "-2995614926067172775889444274176", "0.0d0" }, + +{ "-6.212546775235241d19", "3.239266009361982d-11", + "-1917887187183768183263136317440", "0.0d0" }, + +{ "4.749482734068419d19", "-5.5235623432819116d-11", + "-859858627258009608103722483712", "0.0d0" }, + +{ "3.0587261660909548d19", "4.4929685621578874d-11", + "680780674018761986414328414208", "0.0d0" }, + +{ "4.141754743467259d19", "5.235000122629564d-11", + "791166121575339566219965497344", "0.0d0" }, + +{ "-1.2481803107227873d19", "7.39878580568375d18", + "-2", "2.3157685041396265d18" }, + +{ "-1.5884453212818639d19", "-8.336283910718495d19", + "0", "-1.5884453212818639d19" }, + +{ "5.000368279611168d19", "-5.031778160332162d19", + "-1", "-3.1409880720993677d17" }, + +{ "-3.6360612893747024d19", "4.7875734964388405d19", + "-1", "1.1515122070641383d19" }, + +{ "2.357251757890727d19", "-4.493498319637942d19", + "-1", "-2.136246561747215d19" }, + +{ "5.0747068626287395d19", "8.591364094011977d19", + "0", "5.0747068626287395d19" }, + +{ "2.1440483442615423d19", "9.668454918695627d-21", + "2217570813838780736509865871750106972160", "0.0d0" }, + +{ "8.818664212173065d19", "-8.186497379734964d-21", + "-10772206724212702608743560617665161592832", "0.0d0" }, + +{ "-7.376250633760416d19", "-6.382238421048869d-21", + "11557466435965877316178494055246213414912", "0.0d0" }, + +{ "-4.374244855009332d19", "3.864539687646209d-21", + "-11318928536282082575630148538694692241408", "0.0d0" }, + +{ "7.578656580690454d19", "9.103502086399884d-22", + "83249902166909342613269419960118328426496", "0.0d0" }, + +{ "5.759312769216988d19", "-9.830658049049094d-21", + "-5858522125865295462884970652182979280896", "0.0d0" }, + +{ "-7.091696063135083d-21", "0.3220521420236615d0", + "-1", "0.3220521420236615d0" }, + +{ "-7.472975994693659d-21", "-0.06404310380828848d0", + "0", "-7.472975994693657d-21" }, + +{ "2.2994935284804662d-21", "0.8294627436562217d0", + "0", "2.2994935284804662d-21" }, + +{ "-6.098532726052559d-21", "-0.5103342535054871d0", + "0", "-6.098532726052559d-21" }, + +{ "-7.8237727943808d-21", "0.20193503990844952d0", + "-1", "0.20193503990844952d0" }, + +{ "-5.357065560054238d-21", "0.535324456368991d0", + "-1", "0.535324456368991d0" }, + +{ "8.67862366495009d-23", "5.869284875063336d9", + "0", "8.67862366495009d-23" }, + +{ "-3.913399519946995d-21", "4.645302733766437d9", + "-1", "4.645302733766437d9" }, + +{ "6.256033435453117d-21", "3.5904533516671333d9", + "0", "6.2560334354531166d-21" }, + +{ "-7.970558626381476d-21", "4.548434922363557d9", + "-1", "4.548434922363557d9" }, + +{ "7.442840440717647d-21", "-3.3266294818989463d9", + "-1", "-3.3266294818989463d9" }, + +{ "-4.6732789449833775d-21", "5.614289998802058d8", + "-1", "5.614289998802058d8" }, + +{ "7.136201304639634d-21", "-1.152382297069954d-12", + "-1", "-1.1523822899337527d-12" }, + +{ "-7.575364316308001d-21", "-4.790622052171537d-11", + "0", "-7.575364316308001d-21" }, + +{ "9.212759331893804d-21", "-6.41398602124991d-11", + "-1", "-6.413986020328634d-11" }, + +{ "-1.9103188467401064d-21", "-5.1860189481412404d-11", + "0", "-1.9103188467401064d-21" }, + +{ "-4.473075242507236d-21", "2.3036197131739102d-11", + "-1", "2.303619712726603d-11" }, + +{ "5.138595152941494d-21", "2.9424719822474346d-11", + "0", "5.138595152941494d-21" }, + +{ "-5.137698996313833d-22", "2.2468745456943227d19", + "-1", "2.2468745456943227d19" }, + +{ "-7.229848882029144d-21", "-3.031606285079872d19", + "0", "-7.229848882029144d-21" }, + +{ "-6.85451854164106d-21", "1.7676693722776926d19", + "-1", "1.7676693722776926d19" }, + +{ "5.372223270507929d-21", "-7.439745956384552d19", + "-1", "-7.439745956384552d19" }, + +{ "5.598138480271164d-21", "5.149401801116799d19", + "0", "5.598138480271163d-21" }, + +{ "9.285618896860432d-21", "6.546424273112694d19", + "0", "9.285618896860432d-21" }, + +{ "7.511556502656318d-21", "4.2351039143592516d-21", + "1", "3.2764525882970666d-21" }, + +{ "6.050106800286075d-21", "-1.187392681676287d-21", + "-6", "-1.0742492897716469d-21" }, + +{ "4.274671258683056d-21", "8.647095729321104d-21", + "0", "4.274671258683056d-21" }, + +{ "7.344809600387072d-21", "6.305446958850813d-21", + "1", "1.039362641536258d-21" }, + +{ "9.753544125648588d-21", "9.227661371269332d-21", + "1", "5.258827543792571d-22" }, + +{ "-7.227362780459908d-21", "-6.70179577363263d-21", + "1", "-5.255670068272766d-22" }, + +}; diff --git a/tests/exam_DF_minus.cc b/tests/exam_DF_minus.cc new file mode 100644 index 0000000..09fbad5 --- /dev/null +++ b/tests/exam_DF_minus.cc @@ -0,0 +1,457 @@ +#include "exam.h" +#include +#include + +static minus_test dfloat_minus_tests[] = { + +{ "-0.011326914400453525d0", "-0.6668141757661364d0", + "0.6554872613656829d0" }, + +{ "-0.46185382764946437d0", "0.7488210697846337d0", + "-1.2106748974340982d0" }, + +{ "-0.35834120541234993d0", "-0.30919976341834987d0", + "-0.04914144199400006d0" }, + +{ "0.44705025064976966d0", "-0.9277893553610955d0", + "1.3748396060108652d0" }, + +{ "-0.47647537517067917d0", "0.29158058381073604d0", + "-0.7680559589814152d0" }, + +{ "-0.021697999002707746d0", "0.1779871773524142d0", + "-0.19968517635512195d0" }, + +{ "0.4179484378019861d0", "9.9990307469939d9", + "-9.999030746575953d9" }, + +{ "-0.7475415524823718d0", "1.3993312799214797d9", + "-1.3993312806690214d9" }, + +{ "0.2519442433861928d0", "-6.699632771871848d9", + "6.699632772123793d9" }, + +{ "-0.5124988631497671d0", "2.7959244812290273d9", + "-2.795924481741526d9" }, + +{ "-0.6870193827604301d0", "4.851102442573468d9", + "-4.851102443260488d9" }, + +{ "0.7609656780357723d0", "7.481252865855436d8", + "-7.481252858245779d8" }, + +{ "-0.6301276042170191d0", "-7.099314875214215d-11", + "-0.630127604146026d0" }, + +{ "-0.4139053484357884d0", "-2.897413526398709d-11", + "-0.41390534840681426d0" }, + +{ "-0.6944623060197281d0", "-3.291569879873739d-11", + "-0.6944623059868125d0" }, + +{ "-0.2057822500703933d0", "3.6505182026159854d-11", + "-0.2057822501068985d0" }, + +{ "-0.8792706674467908d0", "8.094527736950817d-11", + "-0.8792706675277361d0" }, + +{ "-0.6888184243601332d0", "9.127622796988807d-11", + "-0.6888184244514094d0" }, + +{ "-0.980711030497252d0", "8.752272461345245d19", + "-8.752272461345245d19" }, + +{ "0.8035082489836539d0", "-3.903355151264917d19", + "3.903355151264917d19" }, + +{ "-0.7537841372394811d0", "-5.879942447417834d19", + "5.879942447417834d19" }, + +{ "-0.6877475951546845d0", "-2.3972266191169642d19", + "2.3972266191169642d19" }, + +{ "-0.43128282112433525d0", "-5.422824998003439d19", + "5.422824998003439d19" }, + +{ "0.29538116818276694d0", "1.1291858990580939d19", + "-1.1291858990580939d19" }, + +{ "0.9166687388673976d0", "6.395175407123937d-21", + "0.9166687388673976d0" }, + +{ "0.41840538498193025d0", "-2.6655662412599155d-21", + "0.41840538498193025d0" }, + +{ "-0.8036940092501853d0", "6.7473779576832565d-21", + "-0.8036940092501853d0" }, + +{ "0.8555054025209989d0", "-7.939970418096797d-21", + "0.8555054025209989d0" }, + +{ "0.3365495704567003d0", "8.694519827555395d-21", + "0.3365495704567003d0" }, + +{ "-0.7430322011471231d0", "7.430332379292914d-22", + "-0.7430322011471231d0" }, + +{ "5.102372414731216d9", "-0.5073635765350494d0", + "5.10237241523858d9" }, + +{ "4.629827365822252d9", "0.6534380055543355d0", + "4.629827365168815d9" }, + +{ "7.218192507117569d9", "0.9781542046565127d0", + "7.218192506139415d9" }, + +{ "6.595760326622413d8", "0.7339510561932947d0", + "6.595760319282902d8" }, + +{ "7.191166637703489d9", "0.80792475493853d0", + "7.191166636895564d9" }, + +{ "-7.95531405213956d9", "0.5353636841430115d0", + "-7.955314052674924d9" }, + +{ "5.438904545553836d8", "6.533536518165114d9", + "-5.989646063609731d9" }, + +{ "-7.389650313101625d8", "-9.983943153365381d9", + "9.244978122055218d9" }, + +{ "8.364404619492165d9", "-7.600563055115287d9", + "1.5964967674607452d10" }, + +{ "2.070813748323649d9", "6.421052769114957d9", + "-4.350239020791307d9" }, + +{ "-2.8555256820439434d9", "-3.4077342921686625d8", + "-2.514752252827077d9" }, + +{ "9.147878229420991d8", "8.439982790150545d9", + "-7.5251949672084465d9" }, + +{ "-4.315772980070098d9", "-6.48869466068404d-11", + "-4.315772980070098d9" }, + +{ "-3.5186299785635023d9", "3.990046539849716d-11", + "-3.5186299785635023d9" }, + +{ "2.5645532837267537d9", "8.566645694205622d-13", + "2.5645532837267537d9" }, + +{ "6.145110896031829d9", "-9.242734002954773d-11", + "6.145110896031829d9" }, + +{ "-6.6836855975624d9", "9.117930361283473d-11", + "-6.6836855975624d9" }, + +{ "-1.7472828462085754d8", "-5.125838712019503d-11", + "-1.7472828462085754d8" }, + +{ "9.05675399397055d9", "9.086705650502484d19", + "-9.08670564959681d19" }, + +{ "-5.834806594586836d9", "9.981576053842906d19", + "-9.981576054426386d19" }, + +{ "3.047010922754272d9", "1.1715352070471352d19", + "-1.1715352067424342d19" }, + +{ "7.294295638574767d9", "2.845702947515113d19", + "-2.8457029467856835d19" }, + +{ "8.264143132493019d9", "-1.6322956072452289d19", + "1.6322956080716431d19" }, + +{ "-9.597823287256088d9", "3.954126758718671d19", + "-3.954126759678453d19" }, + +{ "3.229389511771705d9", "-4.329831377266493d-21", + "3.229389511771705d9" }, + +{ "6.897089200279753d9", "2.4428208790287663d-21", + "6.897089200279753d9" }, + +{ "2.3579775300187545d9", "4.729400988996349d-21", + "2.3579775300187545d9" }, + +{ "1.6718929117460046d9", "5.8162277016717065d-21", + "1.6718929117460046d9" }, + +{ "2.537177500868296d9", "1.4856605280697543d-21", + "2.537177500868296d9" }, + +{ "6.117674696930935d9", "-1.6187214719634357d-21", + "6.117674696930935d9" }, + +{ "4.1877888304549216d-11", "-0.06920550501017497d0", + "0.06920550505205286d0" }, + +{ "9.61054846124015d-11", "0.885309193732889d0", + "-0.8853091936367835d0" }, + +{ "2.5559085051828467d-11", "-0.8112181469812297d0", + "0.8112181470067888d0" }, + +{ "-1.4549570208293283d-12", "-0.5049325945871657d0", + "0.5049325945857107d0" }, + +{ "-7.091628047158497d-11", "0.61946884965934d0", + "-0.6194688497302563d0" }, + +{ "2.877466355456826d-11", "0.4496491857374d0", + "-0.44964918570862533d0" }, + +{ "1.3041612488449928d-12", "5.408018587130755d9", + "-5.408018587130755d9" }, + +{ "-5.379752339715717d-11", "-4.009594691514288d9", + "4.009594691514288d9" }, + +{ "7.023042501342336d-12", "-3.4153434285746374d9", + "3.4153434285746374d9" }, + +{ "6.968174934871611d-11", "4.713087404332662d9", + "-4.713087404332662d9" }, + +{ "-5.153562653896506d-11", "-8.44732228013254d8", + "8.44732228013254d8" }, + +{ "-8.424177457818745d-11", "1.6817117809824567d9", + "-1.6817117809824567d9" }, + +{ "3.374755984316538d-11", "8.893678266883364d-11", + "-5.5189222825668264d-11" }, + +{ "-8.684123447823306d-11", "-7.888825869147879d-11", + "-7.952975786754267d-12" }, + +{ "7.788477523205632d-11", "1.741674745286914d-11", + "6.046802777918718d-11" }, + +{ "6.546622477606044d-11", "-4.7719651007530584d-11", + "1.1318587578359101d-10" }, + +{ "-1.8595152377503265d-11", "5.7288738553553045d-11", + "-7.588389093105631d-11" }, + +{ "-8.184033550427558d-11", "-8.834399228929296d-11", + "6.503656785017376d-12" }, + +{ "5.749469292140762d-11", "7.493129199779113d19", + "-7.493129199779113d19" }, + +{ "-5.2285095120702066d-11", "-2.0611179974216552d19", + "2.0611179974216552d19" }, + +{ "-8.84727820032067d-11", "4.7423077384022024d19", + "-4.7423077384022024d19" }, + +{ "3.437676989338625d-11", "-3.5368755480277647d19", + "3.5368755480277647d19" }, + +{ "2.2665031619145437d-11", "-6.072845659234921d19", + "6.072845659234921d19" }, + +{ "-8.429070146313393d-11", "5.134329153614969d18", + "-5.134329153614969d18" }, + +{ "-9.009531819191212d-11", "2.301790665456671d-22", + "-9.00953181921423d-11" }, + +{ "-2.706942469371907d-11", "9.282350542107287d-21", + "-2.706942470300142d-11" }, + +{ "5.358266626996117d-11", "-4.409057695582885d-22", + "5.358266627040208d-11" }, + +{ "-7.189537285608088d-11", "9.569273217393917d-21", + "-7.189537286565016d-11" }, + +{ "-4.160295905335358d-11", "5.930867524794025d-21", + "-4.160295905928445d-11" }, + +{ "6.7922062777334035d-12", "-7.747524338474154d-22", + "6.792206278508156d-12" }, + +{ "-9.038821102045805d19", "0.04779131019959271d0", + "-9.038821102045805d19" }, + +{ "2.2020595055495963d19", "-0.424631558292516d0", + "2.2020595055495963d19" }, + +{ "-8.164003027214308d19", "0.6832198147365239d0", + "-8.164003027214308d19" }, + +{ "-3.878233560364984d19", "-0.28756619113600546d0", + "-3.878233560364984d19" }, + +{ "7.0829003521450525d19", "-0.6071548125948544d0", + "7.0829003521450525d19" }, + +{ "5.968540808784698d19", "0.7674294173432648d0", + "5.968540808784698d19" }, + +{ "-2.2143621795153547d19", "-2.443529365769125d9", + "-2.2143621792710017d19" }, + +{ "-9.77092538926342d18", "5.903189771537687d8", + "-9.77092538985374d18" }, + +{ "9.974714452399537d19", "-6.980456691485629d9", + "9.974714453097582d19" }, + +{ "1.7428950527159094d18", "3.68843657888816d9", + "1.742895049027473d18" }, + +{ "-1.1094381875350845d19", "-7.157723640671709d9", + "-1.1094381868193122d19" }, + +{ "-3.638795590369631d19", "6.9246542750294075d9", + "-3.6387955910620963d19" }, + +{ "-5.66543282261991d19", "-5.1005028153082024d-11", + "-5.66543282261991d19" }, + +{ "-3.901527864456216d19", "-1.064153465992923d-12", + "-3.901527864456216d19" }, + +{ "1.1477489418879848d19", "3.327888063907735d-11", + "1.1477489418879848d19" }, + +{ "3.508978072054437d19", "9.238453417997638d-11", + "3.508978072054437d19" }, + +{ "-4.7642024461416964d19", "-4.758309941438892d-11", + "-4.7642024461416964d19" }, + +{ "-8.307715835429606d19", "3.313910202186439d-11", + "-8.307715835429606d19" }, + +{ "2.704675010192592d18", "-2.6840207147078365d19", + "2.954488215727096d19" }, + +{ "-9.860969100714668d18", "-4.719594638795429d19", + "3.7334977287239614d19" }, + +{ "7.87799781828944d18", "-6.657221298850535d19", + "7.44502108067948d19" }, + +{ "-3.3937781740759863d19", "4.783805995045389d19", + "-8.177584169121376d19" }, + +{ "-1.0747572720102216d19", "-1.7144708598072445d19", + "6.397135877970229d18" }, + +{ "1.3938845733158445d19", "5.604369854609131d19", + "-4.210485281293287d19" }, + +{ "6.0938348303695315d19", "1.1005522580049531d-21", + "6.0938348303695315d19" }, + +{ "-2.4870844028694925d19", "1.5391650322730598d-22", + "-2.4870844028694925d19" }, + +{ "7.323118607079343d19", "6.637280375859432d-21", + "7.323118607079343d19" }, + +{ "-4.181201584825501d19", "4.768935182006663d-21", + "-4.181201584825501d19" }, + +{ "4.1225910279381205d19", "6.117191687463543d-21", + "4.1225910279381205d19" }, + +{ "6.438313875980151d17", "-1.4883489002691529d-21", + "6.438313875980151d17" }, + +{ "-4.573961206963222d-21", "0.3586300020381973d0", + "-0.3586300020381973d0" }, + +{ "7.74206782371325d-22", "0.23168389210368656d0", + "-0.23168389210368656d0" }, + +{ "8.572446613640605d-21", "0.6114581963443891d0", + "-0.6114581963443891d0" }, + +{ "-8.539467934859551d-21", "0.33474735899049d0", + "-0.33474735899049d0" }, + +{ "-5.55811309570968d-21", "-0.9637216018651454d0", + "0.9637216018651454d0" }, + +{ "-6.705839413964189d-21", "0.3787619614522374d0", + "-0.3787619614522374d0" }, + +{ "1.338539206480238d-22", "6.683968625235106d9", + "-6.683968625235106d9" }, + +{ "-9.64078167549023d-21", "3.291420859310843d9", + "-3.291420859310843d9" }, + +{ "-9.26536204591093d-22", "2.9839295142529476d8", + "-2.9839295142529476d8" }, + +{ "-3.647737608953592d-21", "6.115300020921433d8", + "-6.115300020921433d8" }, + +{ "1.4069763806331204d-21", "-1.183109060480878d9", + "1.183109060480878d9" }, + +{ "-6.0037865798761924d-21", "-7.442246743849378d9", + "7.442246743849378d9" }, + +{ "-5.994118986299138d-21", "-9.091558282012836d-11", + "9.091558281413425d-11" }, + +{ "6.969393585974241d-21", "3.435352867093995d-11", + "-3.435352866397056d-11" }, + +{ "-6.278554484817533d-22", "-4.7211920270841604d-11", + "4.721192027021375d-11" }, + +{ "-8.603262886304741d-21", "1.7296517702077242d-11", + "-1.7296517710680505d-11" }, + +{ "4.104502790901735d-21", "-4.8473213720301105d-11", + "4.847321372440561d-11" }, + +{ "-4.449725859444968d-21", "-8.944265568403936d-11", + "8.944265567958964d-11" }, + +{ "4.828216540804827d-21", "-1.1712152029346877d19", + "1.1712152029346877d19" }, + +{ "-5.65034940464881d-21", "-9.445303840982011d19", + "9.445303840982011d19" }, + +{ "-7.24107519738777d-21", "2.340578690102746d19", + "-2.340578690102746d19" }, + +{ "1.7659593956231534d-21", "-8.048768257390671d18", + "8.048768257390671d18" }, + +{ "-3.0538518255248124d-21", "8.834631867521575d19", + "-8.834631867521575d19" }, + +{ "8.57952908388053d-21", "-5.730742870111307d19", + "5.730742870111307d19" }, + +{ "-4.5090103564928485d-21", "1.8907114777916313d-21", + "-6.399721834284479d-21" }, + +{ "-3.8487625143236447d-22", "5.354282198078924d-21", + "-5.739158449511288d-21" }, + +{ "2.6660110440404615d-22", "3.833744224501756d-22", + "-1.1677331804612944d-22" }, + +{ "-7.503762004261027d-22", "-9.623906576475644d-21", + "8.873530376049542d-21" }, + +{ "-9.113431042260725d-21", "-3.5516521546085545d-21", + "-5.56177888765217d-21" }, + +{ "-3.4813735333296525d-21", "-2.6602650182385188d-21", + "-8.211085150911337d-22" }, + +}; diff --git a/tests/exam_DF_mul.cc b/tests/exam_DF_mul.cc new file mode 100644 index 0000000..8526f43 --- /dev/null +++ b/tests/exam_DF_mul.cc @@ -0,0 +1,457 @@ +#include "exam.h" +#include +#include + +static mul_test dfloat_mul_tests[] = { + +{ "-0.2554913394465045d0", "0.27042187315261135d0", + "-0.0690904465873934d0" }, + +{ "-0.4489211233229662d0", "-0.42892136850270857d0", + "0.19255186256545986d0" }, + +{ "-0.44586465919973783d0", "-0.15168042462027043d0", + "0.0676289408305884d0" }, + +{ "0.5509395670465355d0", "0.3577558280766836d0", + "0.19710184102894285d0" }, + +{ "-0.42780066410606965d0", "0.22704747885906007d0", + "-0.0971310622395147d0" }, + +{ "0.20955388816500042d0", "0.605628751935113d0", + "0.12691185975251945d0" }, + +{ "0.9993471610818964d0", "-4.363771855901198d9", + "-4.360923015803941d9" }, + +{ "0.10502219375257282d0", "3.425205053451057d9", + "3.5972254876582843d8" }, + +{ "0.7768651149081368d0", "1.666066330143864d9", + "1.2943088110117908d9" }, + +{ "-0.6438389801759042d0", "2.8922130868526487d9", + "-1.8621195242906134d9" }, + +{ "-0.7427680566504474d0", "6.763974500466173d9", + "-5.02406419494444d9" }, + +{ "-0.8563035843259611d0", "2.9100478627456827d9", + "-2.4918844154292307d9" }, + +{ "0.6219502737119671d0", "2.8868752190811842d-11", + "1.7954928326798375d-11" }, + +{ "0.6767479505813657d0", "2.9324524289075574d-11", + "1.9845311714405376d-11" }, + +{ "0.7944531541461581d0", "8.282076647859848d-11", + "6.579721915772496d-11" }, + +{ "-0.4662914070981966d0", "-6.921260263903422d-11", + "3.227324187348362d-11" }, + +{ "0.037804762510578516d0", "-3.044514833184461d-11", + "-1.1509716022847211d-12" }, + +{ "-0.5364168049485208d0", "-3.695280705974925d-11", + "1.9822106696869836d-11" }, + +{ "0.10343751426551051d0", "4.8902635121181385d19", + "5.058367017968255d18" }, + +{ "-0.45511004829813784d0", "1.8210069906740634d19", + "-8.287585794769196d18" }, + +{ "-0.9675158737162977d0", "8.097401718869682d19", + "-7.83436469886405d19" }, + +{ "-0.06573561186185628d0", "2.6049125586869125d19", + "-1.712355208919178d18" }, + +{ "-0.5574365795036731d0", "-8.822383181882661d19", + "4.917919103979403d19" }, + +{ "-0.4222667103024276d0", "-1.8561723355961213d19", + "7.837997859065477d18" }, + +{ "-0.8412207478192143d0", "2.3416069046402696d-22", + "-1.9698083114201234d-22" }, + +{ "0.24291385591230452d0", "-9.448120185342916d-21", + "-2.295079305344525d-21" }, + +{ "-0.37792600430678414d0", "-2.3929024368177364d-21", + "9.043400566424941d-22" }, + +{ "-0.007648867433060369d0", "-5.3162210182098465d-21", + "4.066306981313633d-23" }, + +{ "-0.7631807323096114d0", "-4.534410248041209d-21", + "3.4605745336922964d-21" }, + +{ "0.4735366300649959d0", "-1.3895270471326203d-21", + "-6.579919552833457d-22" }, + +{ "-8.64834403600587d9", "-0.14057280586223464d0", + "1.215721987203268d9" }, + +{ "-1.5525713051163936d9", "0.10621224657238759d0", + "-1.64902086280236d8" }, + +{ "3.297132746298694d9", "0.05318660311813239d0", + "1.7536329080518654d8" }, + +{ "2.1659831568875275d9", "0.11704159596099262d0", + "2.5351012550674528d8" }, + +{ "-5.533403510176525d9", "0.37778599060251605d0", + "-2.0904423264954782d9" }, + +{ "-2.4217306331294374d9", "0.6051350227557695d0", + "-1.465474021787126d9" }, + +{ "1.4048311850866513d9", "-4.304799039580996d9", + "-6.047515936334449d18" }, + +{ "-5.070278162013437d9", "-9.116233758795675d9", + "4.622184094703138d19" }, + +{ "8.452801605894673d9", "-9.002885976919611d9", + "-7.609960904339272d19" }, + +{ "6.352601599408395d9", "-4.484034289922495d9", + "-2.848528340196373d19" }, + +{ "-6.565407710101401d8", "-6.718825369609182d9", + "4.4111827884457016d18" }, + +{ "-9.37193973536698d9", "9.577576231327314d9", + "-8.976046725088279d19" }, + +{ "-1.7766859308675253d9", "-4.079350537765101d-11", + "0.0724772470752413d0" }, + +{ "2.3810136983742104d9", "9.195156930614704d-11", + "0.2189379461049417d0" }, + +{ "-3.313966320976337d9", "-3.44704749912067d-11", + "0.11423399318891611d0" }, + +{ "6.598963960681895d9", "-2.4298605961767928d-11", + "-0.1603456250365168d0" }, + +{ "7.908258993705348d9", "1.528909719631646d-11", + "0.12091014040840486d0" }, + +{ "-5.906667889594469d9", "5.917852809041966d-11", + "-0.3495479116251461d0" }, + +{ "4.86261281419926d9", "-2.3925611132123714d19", + "-1.1634098327861323d29" }, + +{ "-9.753392818607462d9", "-2.5653634777279775d18", + "2.502099772078992d28" }, + +{ "1.5861252889272392d9", "5.12939252547053d19", + "8.135859201483165d28" }, + +{ "-8.422142961023593d8", "1.0428099441045047d19", + "-8.782694430425161d27" }, + +{ "-3.109042783121446d9", "-4.138252722536039d19", + "1.286600476173335d29" }, + +{ "-6.459303282089468d8", "1.8408981660472957d19", + "-1.189091956594178d28" }, + +{ "-1.432764110232635d9", "8.98766033001457d-21", + "-1.2877197155806476d-11" }, + +{ "8.539623949953406d9", "-3.498784805440049d-21", + "-2.987830652026891d-11" }, + +{ "7.336784327799637d9", "-1.048985206018761d-21", + "-7.696178219612119d-12" }, + +{ "-4.320357143553698d9", "2.591531476439043d-21", + "-1.119634152697768d-11" }, + +{ "-9.374098076239548d9", "5.5773248420603045d-21", + "-5.228239007252054d-11" }, + +{ "9.118926580475056d9", "-1.379170270330765d-21", + "-1.2576552437120181d-11" }, + +{ "8.145792307872788d-11", "-0.06511382435429458d0", + "-5.304036895613926d-12" }, + +{ "-6.1928426627437d-11", "0.2526275616632321d0", + "-1.5644827416529785d-11" }, + +{ "-8.555119338859813d-11", "-0.8366318482083728d0", + "7.157485304113478d-11" }, + +{ "8.243060442429263d-12", "0.3939656708074719d0", + "3.2474828367081808d-12" }, + +{ "8.600529286105945d-11", "-0.891441509265547d0", + "-7.666868807288822d-11" }, + +{ "-7.531046724969747d-11", "0.24398797995196886d0", + "-1.8374848773492595d-11" }, + +{ "-3.7666526619188126d-12", "4.659322150343885d9", + "-0.017550048180330083d0" }, + +{ "3.032501107241211d-11", "-9.592046453776636d9", + "-0.2908789149178678d0" }, + +{ "7.311626957349528d-11", "-9.061108567148174d9", + "-0.6625144566303135d0" }, + +{ "4.898078204161461d-11", "8.88014689134599d9", + "0.4349565393825394d0" }, + +{ "1.278207138618518d-11", "-4.279966992086118d9", + "-0.05470684362336102d0" }, + +{ "-8.538580654966055d-11", "-5.191059833953482d8", + "0.0443242830769665d0" }, + +{ "4.0761422500127225d-11", "1.527607426117321d-11", + "6.226745171030001d-22" }, + +{ "-9.186363051001198d-11", "8.557763803549676d-11", + "-7.861472520412421d-21" }, + +{ "-9.89183505930065d-11", "9.717968160611499d-11", + "-9.612853815630427d-21" }, + +{ "7.440627873114725d-12", "-4.535521332601712d-11", + "-3.374712644646274d-22" }, + +{ "8.701410920357686d-11", "-7.032883383151379d-12", + "-6.119600827175551d-22" }, + +{ "9.866226673114161d-11", "-2.814669610817353d-11", + "-2.777016839025002d-21" }, + +{ "5.192240545105114d-11", "-3.366056660574579d19", + "-1.747737587015645d9" }, + +{ "-1.372355669576939d-11", "-4.819955130360066d19", + "6.61469275025609d8" }, + +{ "3.637511103766519d-11", "-4.071776382810416d19", + "-1.4811131804527159d9" }, + +{ "7.446388208685151d-13", "2.7760294268649034d19", + "2.0671392791169815d7" }, + +{ "6.267855179410938d-11", "7.471751480940298d19", + "4.683185621908299d9" }, + +{ "-4.336562006766369d-11", "8.143188451558233d19", + "-3.5313441652966094d9" }, + +{ "-1.0432655006975122d-11", "-9.379512413340694d-21", + "9.785321714202411d-32" }, + +{ "-8.167646898574611d-11", "-5.810795749825724d-21", + "4.746052788431461d-31" }, + +{ "-4.33805459341994d-11", "-2.4289860591796017d-21", + "1.053707413137707d-31" }, + +{ "-1.384613082275421d-11", "2.2174009100764947d-21", + "-3.070242308741339d-32" }, + +{ "-4.910905591314494d-11", "-5.456657623752349d-21", + "2.679713043437427d-31" }, + +{ "1.3653011366548008d-11", "-3.925911962906968d-21", + "-5.360052065363564d-32" }, + +{ "7.641468950470222d19", "0.9034599537348024d0", + "6.903761184457755d19" }, + +{ "5.146778093125584d19", "-0.2791459460022878d0", + "-1.436702239669392d19" }, + +{ "-8.874303077863696d19", "-0.23153988023519345d0", + "2.054755071819369d19" }, + +{ "7.10798162637783d19", "-0.4719034863212067d0", + "-3.354281310194779d19" }, + +{ "-9.820386602197546d19", "0.03346146041258036d0", + "-3.286044775256677d18" }, + +{ "-5.210458089116161d19", "0.11173798093222442d0", + "-5.822060666098161d18" }, + +{ "3.257626718953688d18", "-6.150510855712356d9", + "-2.0036068498783283d28" }, + +{ "-7.755105754004988d19", "5.514896832715505d9", + "-4.27686081601359d29" }, + +{ "2.426235084788384d19", "8.685431434428486d9", + "2.1072898472734294d29" }, + +{ "-2.847383850475709d19", "-2.412830829567453d9", + "6.870255538040273d28" }, + +{ "1.4664659669727164d19", "-4.8673539253155d9", + "-7.1378088806862425d28" }, + +{ "-4.24770317054668d19", "1.3102543269150825d9", + "-5.5655714586597015d28" }, + +{ "2.17116835964837d19", "-3.654789326884115d-11", + "-7.935162947711353d8" }, + +{ "-1.8125809977916906d17", "-5.944782899600832d-11", + "1.0775400519813456d7" }, + +{ "-7.915462827540546d19", "9.762153025588201d-11", + "-7.727195939080587d9" }, + +{ "-4.360953588949649d19", "-7.152431005584812d-11", + "3.119141966351983d9" }, + +{ "3.550776271395866d19", "-6.387656982922894d-11", + "-2.268114084477872d9" }, + +{ "-8.278954580496595d19", "-7.359178231519021d-11", + "6.092630232852524d9" }, + +{ "-5.5022682113038156d19", "-8.979630229039327d19", + "4.940833395850589d39" }, + +{ "1.1716230943203277d19", "5.5764415854118265d19", + "6.533487745596758d38" }, + +{ "7.462799608352103d19", "6.061883497941003d19", + "4.523862179431019d39" }, + +{ "-3.2160334983646097d19", "-3.8817785710003675d19", + "1.2483929917571087d39" }, + +{ "5.868090263060238d19", "-8.37300331667736d19", + "-4.91335392351655d39" }, + +{ "-7.3652924769962656d19", "9.725738480757314d19", + "-7.163290846555493d39" }, + +{ "-6.447063647969567d19", "4.0587529685661844d-21", + "-0.2616703871973161d0" }, + +{ "-3.1999317568381926d17", "3.015031281949113d-21", + "-9.647894346969533d-4" }, + +{ "-1.5005852398726605d19", "5.391316601974659d-21", + "-0.080901301164036d0" }, + +{ "1.0084552719733576d19", "2.78150956101201d-21", + "0.02805027980846861d0" }, + +{ "-7.171404412051077d19", "1.4733392992015492d-21", + "-0.10565911950742231d0" }, + +{ "-5.909802783283228d19", "5.356071274587122d-21", + "-0.31653324926018317d0" }, + +{ "8.272641144282955d-22", "-0.16191056182923802d0", + "-1.3394279754825238d-22" }, + +{ "8.410471541398583d-21", "-0.43256058128353736d0", + "-3.63803845881602d-21" }, + +{ "-7.887238384137063d-22", "0.5589746137044918d0", + "-4.408766028968254d-22" }, + +{ "4.778995446616728d-21", "0.21608373898977795d0", + "1.0326632047200663d-21" }, + +{ "3.992449163872154d-21", "0.9593422165456676d0", + "3.830125030315009d-21" }, + +{ "-9.700320218813958d-21", "-0.42620535269852766d0", + "4.134328400148262d-21" }, + +{ "-1.7901566262876555d-21", "9.461674014776534d8", + "-1.6937878433325936d-12" }, + +{ "1.0928019952544443d-22", "8.279199780524873d9", + "9.047526039267738d-13" }, + +{ "9.942869097320962d-21", "9.523169242022762d9", + "9.468762516506561d-11" }, + +{ "-2.7432601692209267d-21", "-4.922145522647528d9", + "1.3502725759388083d-11" }, + +{ "-5.97929682563092d-21", "-6.147792689359443d8", + "3.6759477312123895d-12" }, + +{ "-1.3564305221188254d-21", "1.0862842413758955d9", + "-1.473469100698958d-12" }, + +{ "-5.446806293721964d-21", "-1.5358504316888942d-11", + "8.365479797538665d-32" }, + +{ "-1.0222776562632463d-21", "-1.9781477525280056d-11", + "2.0222162481967376d-32" }, + +{ "8.192540157543917d-21", "3.3215076993103644d-11", + "2.7211585210191467d-31" }, + +{ "9.685592607330157d-21", "6.034805605641166d-11", + "5.8450668560672665d-31" }, + +{ "6.671870463340688d-21", "-9.07657686679269d-11", + "-6.055774510579552d-31" }, + +{ "-1.109409648670322d-21", "-4.7905821901849965d-11", + "5.314718104539439d-32" }, + +{ "-3.9052432481663676d-22", "2.0306112771345453d19", + "-0.007930030979680168d0" }, + +{ "8.596834841113507d-21", "-9.453548987989818d19", + "-0.8127059931212419d0" }, + +{ "3.946325780779758d-21", "-9.084484011754447d19", + "-0.35850333460668093d0" }, + +{ "5.3518824877647604d-21", "-6.814116447592617d19", + "-0.36468350485460743d0" }, + +{ "-7.456278485417833d-22", "9.61914445493285d19", + "-0.07172301984744206d0" }, + +{ "-5.0781537010216826d-21", "9.216915512986622d19", + "-0.4680491362427718d0" }, + +{ "3.2906792172396555d-22", "4.571445785546992d-21", + "1.50431616392373d-42" }, + +{ "5.39814714322422d-21", "6.687033308557664d-21", + "3.6097589751235757d-41" }, + +{ "4.3506183844841724d-21", "7.266196706225928d-21", + "3.1612448975384865d-41" }, + +{ "6.910763289107986d-21", "3.910584203890238d-21", + "2.702512175521024d-41" }, + +{ "-4.6131515924393325d-21", "5.228174479773633d-21", + "-2.411836142691841d-41" }, + +{ "-2.1886866436065787d-21", "6.29322016055891d-22", + "-1.3773886910690934d-42" }, + +}; diff --git a/tests/exam_DF_plus.cc b/tests/exam_DF_plus.cc new file mode 100644 index 0000000..c7e9faf --- /dev/null +++ b/tests/exam_DF_plus.cc @@ -0,0 +1,457 @@ +#include "exam.h" +#include +#include + +static plus_test dfloat_plus_tests[] = { + +{ "0.6049332056786565d0", "-0.9611373574853808d0", + "-0.35620415180672427d0" }, + +{ "-0.4763715667865308d0", "0.25936932107685584d0", + "-0.21700224570967497d0" }, + +{ "0.2666481927718355d0", "-0.04984768063142031d0", + "0.21680051214041518d0" }, + +{ "-0.29478659758474846d0", "0.3371004337672615d0", + "0.042313836182513054d0" }, + +{ "0.8203063910979178d0", "0.28968607542857916d0", + "1.109992466526497d0" }, + +{ "-0.08207985138263585d0", "0.4368723951711785d0", + "0.35479254378854264d0" }, + +{ "-0.8659875373355486d0", "-6.631430771196765d9", + "-6.631430772062753d9" }, + +{ "0.15071385783307878d0", "-7.154424279496395d9", + "-7.154424279345681d9" }, + +{ "-0.8969642760814789d0", "-2.4070067380831727d8", + "-2.4070067470528156d8" }, + +{ "-0.9610362081435054d0", "9.070410778399954d9", + "9.070410777438917d9" }, + +{ "0.5129052501104072d0", "-7.47841120327471d9", + "-7.478411202761805d9" }, + +{ "0.3840242289740675d0", "7.793048210060242d9", + "7.793048210444266d9" }, + +{ "0.07603066126204616d0", "5.215008470388369d-11", + "0.07603066131419625d0" }, + +{ "-0.17187858025312586d0", "-5.116645189173968d-11", + "-0.17187858030429232d0" }, + +{ "0.2521315816245864d0", "8.603210607505339d-11", + "0.2521315817106185d0" }, + +{ "-0.3557185853193914d0", "-2.0371324697272998d-11", + "-0.3557185853397627d0" }, + +{ "0.7142792289542045d0", "-7.106356053331326d-11", + "0.7142792288831409d0" }, + +{ "0.4380415886629452d0", "-3.069969538383403d-11", + "0.43804158863224546d0" }, + +{ "0.24798614227178573d0", "3.972393639614975d19", + "3.972393639614975d19" }, + +{ "-0.5210677288128815d0", "4.846393336901129d19", + "4.846393336901129d19" }, + +{ "0.5825404819115d0", "1.9710987361264255d19", + "1.9710987361264255d19" }, + +{ "0.9105175208730549d0", "2.391166552096775d19", + "2.391166552096775d19" }, + +{ "0.48414423368371695d0", "-9.696117779740095d19", + "-9.696117779740095d19" }, + +{ "0.25780758450697716d0", "6.094683117025535d19", + "6.094683117025535d19" }, + +{ "0.9824539149570484d0", "-5.4680066990812835d-21", + "0.9824539149570484d0" }, + +{ "-0.9520982941158654d0", "3.2513564801568073d-21", + "-0.9520982941158654d0" }, + +{ "0.0630170624560149d0", "-9.858852595793203d-21", + "0.0630170624560149d0" }, + +{ "0.24705141169888878d0", "1.4582081178692862d-22", + "0.24705141169888878d0" }, + +{ "0.7440948700757135d0", "-3.0932442581890818d-21", + "0.7440948700757135d0" }, + +{ "-0.5055970869515372d0", "4.0277457257516025d-21", + "-0.5055970869515372d0" }, + +{ "1.672355787134947d9", "0.0064909681594120805d0", + "1.672355787141438d9" }, + +{ "-9.694504381396599d9", "-0.8925470085542831d0", + "-9.694504382289146d9" }, + +{ "-1.6695005924298635d9", "-0.34426964741306d0", + "-1.6695005927741332d9" }, + +{ "-6.085591212594774d9", "0.5107956920100049d0", + "-6.085591212083979d9" }, + +{ "7.457486660952688d9", "-0.4323787588338597d0", + "7.457486660520309d9" }, + +{ "-8.790796444526546d9", "0.911415263281967d0", + "-8.790796443615131d9" }, + +{ "9.667548804251982d9", "-1.266547751029956d8", + "9.540894029148987d9" }, + +{ "-6.169561898845145d9", "9.627911197121864d9", + "3.458349298276719d9" }, + +{ "-9.870287253215279d9", "9.004242781937655d8", + "-8.969862975021513d9" }, + +{ "-8.175630881172554d9", "-4.08632236263908d9", + "-1.2261953243811634d10" }, + +{ "2.9069444232153206d9", "-7.961831315741894d9", + "-5.054886892526573d9" }, + +{ "-7.003647401371184d9", "-1.768371514817526d9", + "-8.772018916188711d9" }, + +{ "-6.418847599138249d9", "2.755257250162372d-11", + "-6.418847599138249d9" }, + +{ "2.3093152687241793d9", "1.2205440142364766d-11", + "2.3093152687241793d9" }, + +{ "8.634577667577518d9", "-9.065714034538668d-11", + "8.634577667577518d9" }, + +{ "1.711283212591781d9", "-3.235019197733951d-11", + "1.711283212591781d9" }, + +{ "2.583886638357791d9", "-8.199109798920928d-11", + "2.583886638357791d9" }, + +{ "-7.517123950474774d9", "5.2057802142431697d-11", + "-7.517123950474774d9" }, + +{ "3.266571938086574d9", "-4.4782768261898355d19", + "-4.478276825863179d19" }, + +{ "2.1000389219899452d9", "-8.547158903365463d19", + "-8.54715890315546d19" }, + +{ "-3.9140926801217155d9", "7.387959860641422d19", + "7.387959860250013d19" }, + +{ "-7.087607465790431d9", "7.96875093387599d19", + "7.96875093316723d19" }, + +{ "-8.341000808926519d9", "6.9360028397637304d19", + "6.93600283892963d19" }, + +{ "-5.507940634743809d9", "9.760028858210094d19", + "9.7600288576593d19" }, + +{ "8.492522971238823d9", "-2.8253881864964467d-22", + "8.492522971238823d9" }, + +{ "1.2731765723336241d9", "-5.8473937102910264d-21", + "1.2731765723336241d9" }, + +{ "9.654280758878323d9", "-4.2332114049658973d-22", + "9.654280758878323d9" }, + +{ "-6.864618926120946d9", "-1.245648314796599d-21", + "-6.864618926120946d9" }, + +{ "-3.9916044043798673d8", "1.697737588450543d-21", + "-3.9916044043798673d8" }, + +{ "-7.818041624198686d9", "4.635421587404246d-21", + "-7.818041624198686d9" }, + +{ "2.0609929543990767d-12", "-0.2126306554359736d0", + "-0.2126306554339126d0" }, + +{ "-1.5923091695877845d-11", "0.515731533720818d0", + "0.515731533704895d0" }, + +{ "4.794527092905871d-11", "-0.9066947202676092d0", + "-0.9066947202196639d0" }, + +{ "-8.63854477728633d-11", "0.3122982022565777d0", + "0.3122982021701922d0" }, + +{ "-7.577966666552416d-11", "-0.24137602092437593d0", + "-0.2413760210001556d0" }, + +{ "-4.971730475882754d-11", "-0.8202688719750202d0", + "-0.8202688720247375d0" }, + +{ "-5.249369194379291d-11", "-8.546120620321186d9", + "-8.546120620321186d9" }, + +{ "8.280786962526793d-11", "5.758373397436368d9", + "5.758373397436368d9" }, + +{ "6.370323595535815d-11", "-8.470663335712393d9", + "-8.470663335712393d9" }, + +{ "3.59771226839467d-11", "3.5042505440266216d8", + "3.5042505440266216d8" }, + +{ "-3.945501687396375d-11", "-5.082779978069177d9", + "-5.082779978069177d9" }, + +{ "9.780590963267516d-11", "-5.05591945120475d9", + "-5.05591945120475d9" }, + +{ "6.323293597096768d-11", "-7.208898910487284d-11", + "-8.85605313390516d-12" }, + +{ "-4.549781732354749d-11", "-6.095452636416357d-11", + "-1.0645234368771105d-10" }, + +{ "-5.372680267837374d-11", "2.0748354219485134d-11", + "-3.297844845888861d-11" }, + +{ "3.550879553916665d-11", "-4.374873254056574d-11", + "-8.23993700139909d-12" }, + +{ "-6.746002242414832d-11", "3.0803985031459436d-11", + "-3.665603739268888d-11" }, + +{ "-7.902512161494214d-11", "-8.907842858073236d-11", + "-1.681035501956745d-10" }, + +{ "-4.1465935469350415d-11", "6.244210696961323d19", + "6.244210696961323d19" }, + +{ "4.921297536286578d-11", "-1.694436650099881d19", + "-1.694436650099881d19" }, + +{ "-7.879478980672654d-11", "6.41757969360492d19", + "6.41757969360492d19" }, + +{ "-8.200749317872953d-11", "-9.490225542618815d19", + "-9.490225542618815d19" }, + +{ "-7.572981329795812d-11", "-3.350367078181029d19", + "-3.350367078181029d19" }, + +{ "-5.955255565125549d-11", "-5.009913629288125d19", + "-5.009913629288125d19" }, + +{ "-9.818180775332558d-11", "-7.926156011681593d-21", + "-9.818180776125174d-11" }, + +{ "-5.2466438379505935d-12", "8.468830229031857d-21", + "-5.246643829481763d-12" }, + +{ "3.582774358441715d-11", "3.6865211729351863d-22", + "3.58277435847858d-11" }, + +{ "7.169296413565744d-11", "-9.974881413980864d-21", + "7.169296412568256d-11" }, + +{ "-9.615073655516977d-11", "4.9552491300097786d-21", + "-9.615073655021452d-11" }, + +{ "6.7696956269187d-11", "4.1431488006404866d-21", + "6.769695627333016d-11" }, + +{ "-4.663397365185298d19", "0.9758464195927673d0", + "-4.663397365185298d19" }, + +{ "-4.77977261393851d19", "0.04145189313162445d0", + "-4.77977261393851d19" }, + +{ "7.195364554121596d19", "0.5169917736820715d0", + "7.195364554121596d19" }, + +{ "-7.766254779507882d19", "0.5919134938460356d0", + "-7.766254779507882d19" }, + +{ "-8.411122653901408d19", "-0.14463225181516137d0", + "-8.411122653901408d19" }, + +{ "-9.101920591747218d19", "0.23349918704239836d0", + "-9.101920591747218d19" }, + +{ "7.037477746142529d18", "-3.250947575909365d9", + "7.037477742891581d18" }, + +{ "-6.864341752972099d19", "-4.0510449339565725d9", + "-6.864341753377203d19" }, + +{ "-5.329540273290228d19", "8.14869777458878d9", + "-5.329540272475358d19" }, + +{ "-9.726234388247201d19", "2.053976989398215d9", + "-9.726234388041803d19" }, + +{ "-1.910324088450308d19", "6.247052535748024d9", + "-1.910324087825603d19" }, + +{ "-6.079933001949367d18", "6.316829148809886d9", + "-6.079932995632539d18" }, + +{ "-4.499107911798452d19", "9.659763881732633d-11", + "-4.499107911798452d19" }, + +{ "-3.0972208018542522d19", "-9.077209886078653d-11", + "-3.0972208018542522d19" }, + +{ "-2.3000547840875442d19", "-3.2043634522621155d-11", + "-2.3000547840875442d19" }, + +{ "2.124555308489292d19", "2.252166800652451d-11", + "2.124555308489292d19" }, + +{ "-7.74280238703686d19", "1.7289553748884322d-11", + "-7.74280238703686d19" }, + +{ "-8.119446783121816d19", "-4.3461802389685114d-11", + "-8.119446783121816d19" }, + +{ "-4.70848534032654d18", "-4.698316648967506d19", + "-5.169165183000161d19" }, + +{ "2.853799842810312d19", "-5.56805968603395d19", + "-2.7142598432236384d19" }, + +{ "-2.9128622996090335d19", "-5.153369106520702d19", + "-8.066231406129735d19" }, + +{ "-5.415993984772977d19", "4.481932558278175d19", + "-9.340614264948015d18" }, + +{ "-1.4652301908531261d19", "7.89284449966826d19", + "6.427614308815133d19" }, + +{ "-8.241911630479252d19", "5.377001886877124d19", + "-2.8649097436021277d19" }, + +{ "-6.923631123395076d19", "7.100129853298664d-22", + "-6.923631123395076d19" }, + +{ "-5.864213410820717d19", "-2.649878514627326d-21", + "-5.864213410820717d19" }, + +{ "8.660575002861176d19", "2.751926085897399d-21", + "8.660575002861176d19" }, + +{ "-3.0252871646631318d19", "6.852831573716124d-21", + "-3.0252871646631318d19" }, + +{ "-9.155476807340938d19", "-5.552907466957205d-21", + "-9.155476807340938d19" }, + +{ "-4.03382621358461d19", "6.670808279457885d-21", + "-4.03382621358461d19" }, + +{ "8.842980509187577d-21", "0.5028466982188534d0", + "0.5028466982188534d0" }, + +{ "1.7292043381396136d-21", "0.19490424064972922d0", + "0.19490424064972922d0" }, + +{ "-5.854820918836103d-21", "-0.6700030154364615d0", + "-0.6700030154364615d0" }, + +{ "-2.152396491682048d-21", "0.5002930268902921d0", + "0.5002930268902921d0" }, + +{ "-1.0897149666610629d-21", "0.16555534170490604d0", + "0.16555534170490604d0" }, + +{ "6.321421497987867d-24", "-0.08008112131564671d0", + "-0.08008112131564671d0" }, + +{ "-6.1552667309563055d-21", "7.235074489769488d9", + "7.235074489769488d9" }, + +{ "-2.2311335001219955d-22", "1.220011008333989d9", + "1.220011008333989d9" }, + +{ "8.523565724937177d-23", "-4.1650242034123087d9", + "-4.1650242034123087d9" }, + +{ "-2.4400041303825447d-21", "4.435554678685388d9", + "4.435554678685388d9" }, + +{ "-3.4479065449345757d-22", "8.491084033112451d8", + "8.491084033112451d8" }, + +{ "-7.919939059912893d-21", "-7.610637842585286d9", + "-7.610637842585286d9" }, + +{ "4.4958602369105625d-21", "5.758376768873417d-11", + "5.7583767693230034d-11" }, + +{ "2.4375297386412195d-21", "9.417086717671841d-11", + "9.417086717915595d-11" }, + +{ "1.0040647133383462d-21", "3.4701016271268983d-12", + "3.470101628130963d-12" }, + +{ "-3.885093055726793d-21", "-8.523534862249969d-11", + "-8.523534862638479d-11" }, + +{ "1.027951323422187d-21", "-7.65508060829868d-11", + "-7.655080608195885d-11" }, + +{ "-9.83813940552434d-21", "-5.048380063082019d-11", + "-5.0483800640658324d-11" }, + +{ "-7.640856498925806d-21", "-5.743808556015994d19", + "-5.743808556015994d19" }, + +{ "8.053891045717591d-21", "4.0840032650134725d19", + "4.0840032650134725d19" }, + +{ "-4.794782783871528d-21", "-3.431216587740782d18", + "-3.431216587740782d18" }, + +{ "1.860870988390988d-21", "-3.757945694933625d19", + "-3.757945694933625d19" }, + +{ "5.445498222566789d-21", "7.575823566817991d19", + "7.575823566817991d19" }, + +{ "2.631896745307223d-21", "4.906449817201212d19", + "4.906449817201212d19" }, + +{ "-6.61689881073516d-21", "5.357007670385275d-21", + "-1.2598911403498852d-21" }, + +{ "3.0173001109587537d-21", "5.2947222461350496d-21", + "8.312022357093803d-21" }, + +{ "-8.792518441030627d-21", "-1.0516787854168774d-21", + "-9.844197226447504d-21" }, + +{ "7.349451992884509d-21", "-8.427997362671486d-21", + "-1.0785453697869767d-21" }, + +{ "-7.881179611953633d-21", "3.2080446524364824d-21", + "-4.6731349595171506d-21" }, + +{ "-9.614117725927607d-21", "-5.35667712698602d-21", + "-1.4970794852913628d-20" }, + +}; diff --git a/tests/exam_FF.cc b/tests/exam_FF.cc new file mode 100644 index 0000000..c28679a --- /dev/null +++ b/tests/exam_FF.cc @@ -0,0 +1,7 @@ +#include "exam_FF_plus.cc" +#include "exam_FF_minus.cc" +#include "exam_FF_mul.cc" +#include "exam_FF_div.cc" +#include "exam_FF_floor.cc" + +DO_TESTS(ffloat,cl_FF,cl_FF) diff --git a/tests/exam_FF_div.cc b/tests/exam_FF_div.cc new file mode 100644 index 0000000..30ca9c6 --- /dev/null +++ b/tests/exam_FF_div.cc @@ -0,0 +1,424 @@ +#include "exam.h" +#include +#include + +static div_test ffloat_div_tests[] = { + +{ "0.73739415", "0.6416277", + "1.1492554" }, + +{ "0.6736158", "-0.25522494", + "-2.6393025" }, + +{ "-0.44216943", "0.31134832", + "-1.420176" }, + +{ "-0.7041118", "-0.26929635", + "2.6146355" }, + +{ "0.3573562", "0.73521775", + "0.4860549" }, + +{ "-0.7661392", "0.77110463", + "-0.9935606" }, + +{ "-0.91306114", "1.6586358E9", + "-5.504892E-10" }, + +{ "-0.68994707", "4.0230333E8", + "-1.7149921E-9" }, + +{ "0.28498656", "-7.617844E9", + "-3.7410394E-11" }, + +{ "-0.72419757", "-9.226896E9", + "7.848767E-11" }, + +{ "0.8352187", "8.3102536E9", + "1.00504605E-10" }, + +{ "0.9707725", "3.3669448E9", + "2.8832445E-10" }, + +{ "0.50785017", "6.048824E-11", + "8.3958497E9" }, + +{ "-0.17675805", "4.1391092E-11", + "-4.270437E9" }, + +{ "-0.42162335", "-4.4007357E-11", + "9.580747E9" }, + +{ "-7.945299E-4", "-5.4965265E-11", + "1.4455128E7" }, + +{ "-0.65178335", "-9.78151E-12", + "6.6634228E10" }, + +{ "-0.6209788", "-3.8544803E-11", + "1.611057E10" }, + +{ "0.94332725", "-4.9823833E19", + "-1.8933253E-20" }, + +{ "0.30150706", "-4.9741757E19", + "-6.061448E-21" }, + +{ "-0.8478371", "-9.85865E18", + "8.5999306E-20" }, + +{ "-0.28524554", "3.1389898E19", + "-9.087176E-21" }, + +{ "-0.5260848", "-7.936286E19", + "6.6288534E-21" }, + +{ "-0.12941593", "-5.3575864E19", + "2.415564E-21" }, + +{ "-0.20859545", "-9.867267E-21", + "2.1140145E19" }, + +{ "0.35158414", "-8.2825064E-22", + "-4.2449002E20" }, + +{ "-0.05635804", "-2.2999601E-21", + "2.450392E19" }, + +{ "-0.003138721", "-3.3988403E-21", + "9.234682E17" }, + +{ "-0.91386896", "-5.8199337E-21", + "1.5702395E20" }, + +{ "-0.5374476", "2.256708E-21", + "-2.3815556E20" }, + +{ "1.9669795E9", "-0.58137333", + "-3.3833329E9" }, + +{ "-8.9879334E8", "0.35829848", + "-2.5085046E9" }, + +{ "-9.057627E9", "0.4849478", + "-1.867753E10" }, + +{ "3.687799E8", "-0.34055912", + "-1.082866E9" }, + +{ "-5.1049994E9", "-0.16858816", + "3.0280888E10" }, + +{ "-4.512774E9", "0.9385354", + "-4.8083154E9" }, + +{ "-1.9312024E9", "-8.3940613E9", + "0.2300677" }, + +{ "-8.2104387E9", "6.769607E9", + "-1.2128383" }, + +{ "-6.9613486E9", "4.576518E9", + "-1.5211015" }, + +{ "-1.486333E9", "1.2476433E9", + "-1.1913126" }, + +{ "-7.653413E9", "5.167656E9", + "-1.4810221" }, + +{ "-2.9815204E9", "8.942396E9", + "-0.33341402" }, + +{ "9.304549E9", "-5.8002263E-11", + "-1.60417E20" }, + +{ "-2.0750719E9", "1.272735E-11", + "-1.6304037E20" }, + +{ "-1.1557549E9", "-7.2220556E-11", + "1.6003129E19" }, + +{ "-3.3273495E9", "-9.9207274E-11", + "3.353937E19" }, + +{ "-3.2167434E9", "7.7474506E-11", + "-4.1520026E19" }, + +{ "4.4169416E9", "-4.638272E-11", + "-9.5228166E19" }, + +{ "-3.732909E9", "-2.2763849E18", + "1.6398409E-9" }, + +{ "-6.243126E9", "-4.1274483E19", + "1.5125873E-10" }, + +{ "4.7162563E9", "-7.524631E19", + "-6.267758E-11" }, + +{ "-1.3657349E9", "7.728982E19", + "-1.7670308E-11" }, + +{ "-4.6216906E8", "-7.972877E19", + "5.7967663E-12" }, + +{ "4.4542986E9", "3.1531836E19", + "1.4126353E-10" }, + +{ "1.4738977E9", "-9.8130876E-21", + "-1.5019714E29" }, + +{ "-5.918336E9", "2.9877495E-21", + "-1.9808676E30" }, + +{ "-3.7166292E9", "-1.0826009E-21", + "3.433056E30" }, + +{ "7.390683E9", "-2.1678685E-22", + "-3.4091935E31" }, + +{ "6.2302886E8", "8.9466635E-21", + "6.963812E28" }, + +{ "5.2357125E9", "4.854464E-22", + "1.0785356E31" }, + +{ "-2.7721167E-11", "0.99550104", + "-2.7846447E-11" }, + +{ "5.754337E-11", "-0.6344538", + "-9.06975E-11" }, + +{ "-7.663363E-11", "0.020810604", + "-3.6824317E-9" }, + +{ "3.2576632E-11", "0.6209498", + "5.2462586E-11" }, + +{ "-9.507874E-11", "-0.19174337", + "4.958645E-10" }, + +{ "-9.681176E-11", "-0.82680905", + "1.1709084E-10" }, + +{ "6.458532E-11", "3.442031E8", + "1.8763725E-19" }, + +{ "1.9113166E-11", "-7.0712125E9", + "-2.7029546E-21" }, + +{ "-2.0099402E-12", "2.600844E9", + "-7.7280303E-22" }, + +{ "-4.9634992E-12", "8.041176E9", + "-6.1726036E-22" }, + +{ "3.2738747E-12", "7.299675E9", + "4.484959E-22" }, + +{ "9.133733E-12", "-2.6318538E9", + "-3.470456E-21" }, + +{ "-3.4146054E-11", "-1.5331155E-11", + "2.227233" }, + +{ "6.06336E-11", "4.3750472E-11", + "1.385896" }, + +{ "-4.229064E-11", "-9.169808E-11", + "0.4611944" }, + +{ "6.166104E-11", "-3.5474658E-11", + "-1.7381715" }, + +{ "-3.979801E-11", "-1.9510412E-11", + "2.0398343" }, + +{ "9.726933E-11", "-5.6926824E-11", + "-1.7086731" }, + +{ "8.041786E-11", "2.3718388E19", + "3.3905282E-30" }, + +{ "-6.747094E-11", "-6.7324465E19", + "1.0021756E-30" }, + +{ "-3.0713255E-11", "-4.8310887E19", + "6.357419E-31" }, + +{ "-2.8496396E-11", "-4.9017306E19", + "5.813538E-31" }, + +{ "-9.354275E-12", "-9.035095E19", + "1.0353266E-31" }, + +{ "4.9274265E-12", "7.241873E19", + "6.8040775E-32" }, + +{ "-4.377009E-11", "7.138917E-21", + "-6.131195E9" }, + +{ "9.422678E-12", "-5.8862136E-21", + "-1.6008046E9" }, + +{ "-6.83782E-11", "-3.6098812E-21", + "1.8941952E10" }, + +{ "-8.1755075E-11", "-6.8725736E-21", + "1.1895846E10" }, + +{ "-6.360949E-11", "4.2976342E-21", + "-1.4801049E10" }, + +{ "3.3879413E-11", "-1.7169743E-21", + "-1.9732044E10" }, + +{ "-9.948093E18", "-0.8695114", + "1.1441014E19" }, + +{ "6.2748975E19", "-0.94829553", + "-6.6170272E19" }, + +{ "-6.204444E18", "0.6874813", + "-9.0248915E18" }, + +{ "6.7599936E19", "-0.45808762", + "-1.4756988E20" }, + +{ "7.624068E19", "0.008471012", + "9.0001855E21" }, + +{ "8.342225E19", "-0.3031574", + "-2.7517803E20" }, + +{ "-6.3366795E19", "-1.4882481E9", + "4.2578113E10" }, + +{ "-1.7335874E19", "-7.42875E9", + "2.3336195E9" }, + +{ "-8.662651E19", "1.0327226E9", + "-8.388168E10" }, + +{ "-4.9590965E19", "8.334462E9", + "-5.95011E9" }, + +{ "8.191562E18", "5.930472E9", + "1.3812664E9" }, + +{ "-3.5910857E19", "-7.342098E9", + "4.8910894E9" }, + +{ "-3.6083056E19", "5.7372277E-11", + "-6.2892843E29" }, + +{ "2.2896613E19", "-4.541202E-11", + "-5.0419717E29" }, + +{ "6.1438805E19", "8.512014E-11", + "7.217893E29" }, + +{ "6.3211746E19", "-6.185377E-12", + "-1.0219547E31" }, + +{ "4.5452835E18", "2.0429606E-11", + "2.2248514E29" }, + +{ "9.226608E19", "1.3297486E-11", + "6.9386104E30" }, + +{ "1.8852943E19", "-1.623413E19", + "-1.1613153" }, + +{ "-3.117305E18", "-9.5760065E19", + "0.03255329" }, + +{ "-7.719376E19", "3.3627052E19", + "-2.295585" }, + +{ "3.1309093E19", "-7.820006E19", + "-0.4003717" }, + +{ "3.941958E19", "-9.51598E19", + "-0.41424614" }, + +{ "-3.6364467E19", "-1.0757047E19", + "3.380525" }, + +{ "2.906561E17", "-8.595159E-21", + "-3.3816258E37" }, + +{ "-7.826226E-21", "-0.21695328", + "3.6073327E-20" }, + +{ "-1.888169E-21", "0.5031878", + "-3.7524144E-21" }, + +{ "8.304594E-21", "-0.3528648", + "-2.3534775E-20" }, + +{ "-8.441606E-21", "-0.3639353", + "2.3195348E-20" }, + +{ "-7.815205E-21", "0.38263506", + "-2.0424697E-20" }, + +{ "-3.2837188E-21", "0.46961308", + "-6.992392E-21" }, + +{ "-5.1739832E-21", "-3.8917279E9", + "1.3294822E-30" }, + +{ "-5.3318596E-21", "-7.1995423E9", + "7.405831E-31" }, + +{ "-7.4979364E-22", "9.148773E9", + "-8.195565E-32" }, + +{ "4.6800053E-21", "3.9532006E8", + "1.1838522E-29" }, + +{ "4.914653E-22", "-2.414465E9", + "-2.035504E-31" }, + +{ "5.4722133E-21", "-9.977777E9", + "-5.484401E-31" }, + +{ "9.815656E-21", "6.059642E-11", + "1.619841E-10" }, + +{ "7.660357E-21", "9.7074675E-11", + "7.891201E-11" }, + +{ "9.77743E-21", "2.5170428E-11", + "3.8844908E-10" }, + +{ "8.818017E-21", "1.18070545E-11", + "7.468431E-10" }, + +{ "5.445426E-21", "9.6208916E-11", + "5.6600016E-11" }, + +{ "4.6823916E-21", "-1.9853067E-11", + "-2.358523E-10" }, + +{ "9.347429E-21", "-7.285392E-22", + "-12.830372" }, + +{ "-7.304412E-21", "6.766496E-21", + "-1.079497" }, + +{ "-2.6850204E-21", "6.894023E-21", + "-0.38947076" }, + +{ "-2.24644E-21", "-9.533858E-21", + "0.23562758" }, + +{ "-8.525939E-21", "-9.961187E-22", + "8.559159" }, + +{ "8.145676E-21", "4.304153E-22", + "18.925154" }, + +}; diff --git a/tests/exam_FF_floor.cc b/tests/exam_FF_floor.cc new file mode 100644 index 0000000..00e7922 --- /dev/null +++ b/tests/exam_FF_floor.cc @@ -0,0 +1,423 @@ +#include "exam.h" +#include +#include +#include +#include + +static floor_test ffloat_floor_tests[] = { + +{ "-0.8227301", "-0.25283414", + "3", "-0.06422769" }, + +{ "-0.6686161", "0.4833234", + "-2", "0.29803064" }, + +{ "-0.57436657", "0.52642506", + "-2", "0.47848356" }, + +{ "0.60395426", "-0.61624163", + "-1", "-0.012287392" }, + +{ "-0.21636301", "0.90365344", + "-1", "0.68729043" }, + +{ "0.8705054", "-0.7953333", + "-2", "-0.72016126" }, + +{ "0.4544462", "-9.890925E9", + "-1", "-9.890925E9" }, + +{ "-0.4954149", "-3.8786918E9", + "0", "-0.49541488" }, + +{ "-0.692049", "6.4791506E9", + "-1", "6.4791506E9" }, + +{ "0.75464755", "-3.618496E9", + "-1", "-3.618496E9" }, + +{ "-0.5929247", "-5.442471E9", + "0", "-0.5929247" }, + +{ "-0.30383867", "9.262864E9", + "-1", "9.262864E9" }, + +{ "0.9345329", "3.26737E-11", + "28601991168", "0.0" }, + +{ "0.3772617", "-7.991702E-11", + "-4720667648", "0.0" }, + +{ "0.74438447", "-1.0977978E-11", + "-67807064064", "0.0" }, + +{ "-0.9220973", "-1.2655998E-11", + "72858525696", "0.0" }, + +{ "-0.4615329", "6.48833E-11", + "-7113276928", "0.0" }, + +{ "0.2851941", "-8.262349E-11", + "-3451731456", "0.0" }, + +{ "0.61539984", "3.5826177E19", + "0", "0.61539984" }, + +{ "-0.8195054", "8.793426E19", + "-1", "8.793426E19" }, + +{ "-0.26412165", "7.015103E18", + "-1", "7.015103E18" }, + +{ "-0.527393", "8.434833E19", + "-1", "8.434833E19" }, + +{ "-0.1846056", "1.8252128E19", + "-1", "1.8252128E19" }, + +{ "-0.6079822", "6.106683E19", + "-1", "6.106683E19" }, + +{ "0.5564819", "5.953872E-21", + "93465542827563810816", "0.0" }, + +{ "-0.52575815", "-1.8358678E-21", + "286381261476583178240", "0.0" }, + +{ "-0.6321403", "-5.830945E-21", + "108411292344853200896", "0.0" }, + +{ "-0.9675891", "-9.936226E-21", + "97379936163841703936", "0.0" }, + +{ "-0.63503754", "-5.0137436E-21", + "126659359065470140416", "0.0" }, + +{ "0.8053654", "-3.4055888E-22", + "-2364834534832713236480", "0.0" }, + +{ "8.784645E9", "0.9775517", + "8986374144", "0.0" }, + +{ "-9.314413E9", "-0.8318871", + "11196726272", "0.0" }, + +{ "8.4695936E9", "-0.9823455", + "-8621807616", "0.0" }, + +{ "-5.8406625E9", "-0.031723082", + "184113971200", "0.0" }, + +{ "-7.325545E9", "0.93169844", + "-7862571008", "0.0" }, + +{ "-5.2999526E9", "0.11515945", + "-46022733824", "0.0" }, + +{ "6.680458E9", "7.170729E9", + "0", "6.680458E9" }, + +{ "-2.2146278E9", "5.2909993E9", + "-1", "3.0763715E9" }, + +{ "6.4947005E9", "3.1265188E9", + "2", "2.4166298E8" }, + +{ "7.947109E9", "2.464481E9", + "3", "5.53666E8" }, + +{ "8.899791E9", "3.5788132E9", + "2", "1.7421644E9" }, + +{ "5.272568E9", "-5.3260964E9", + "-1", "-5.3528532E7" }, + +{ "9.729838E8", "8.6379175E-11", + "11264101901890748416", "0.0" }, + +{ "1.210882E9", "-4.412428E-11", + "-27442532596777484288", "0.0" }, + +{ "9.169561E9", "-9.41537E-11", + "-97389277614631288832", "0.0" }, + +{ "9.289745E9", "3.1269442E-11", + "297087021478284623872", "0.0" }, + +{ "-5.334722E9", "2.0158666E-11", + "-264636651022615314432", "0.0" }, + +{ "9.910798E9", "-2.985589E-11", + "-331954558296456691712", "0.0" }, + +{ "-1.7169357E9", "2.220112E19", + "-1", "2.220112E19" }, + +{ "4.9906683E9", "6.857979E19", + "0", "4.9906683E9" }, + +{ "-9.90463E9", "-2.342953E19", + "0", "-9.90463E9" }, + +{ "-5.4878054E8", "5.438576E19", + "-1", "5.438576E19" }, + +{ "-6.1080986E9", "9.25119E19", + "-1", "9.25119E19" }, + +{ "-8.4138286E9", "-9.682224E19", + "0", "-8.4138286E9" }, + +{ "2.7084977E9", "2.542436E-23", + "106531597407755826831748572905472", "0.0" }, + +{ "-5.720767E9", "9.438407E-21", + "-606115738076318963177881600000", "0.0" }, + +{ "-3.4958034E9", "9.250327E-21", + "-377911344579488968728001904640", "0.0" }, + +{ "-8.3702047E9", "6.0186186E-21", + "-1390718493086361392338557730816", "0.0" }, + +{ "-7.517619E9", "-9.417701E-21", + "798243593937800371539149848576", "0.0" }, + +{ "-2.1220838E9", "3.931208E-21", + "-539804494597454582830132625408", "0.0" }, + +{ "-3.9606828E-11", "0.34267086", + "-1", "0.34267086" }, + +{ "2.495503E-11", "-0.4518087", + "-1", "-0.4518087" }, + +{ "-7.98698E-11", "-0.5665642", + "0", "-7.98698E-11" }, + +{ "2.1465689E-11", "0.17276591", + "0", "2.146569E-11" }, + +{ "4.9463066E-11", "-0.5659616", + "-1", "-0.5659616" }, + +{ "-1.8961567E-11", "-0.7758364", + "0", "-1.8961567E-11" }, + +{ "7.8871874E-11", "-5.768549E9", + "-1", "-5.768549E9" }, + +{ "-9.079439E-11", "-3.807195E9", + "0", "-9.079439E-11" }, + +{ "7.879919E-12", "-1.9198149E9", + "-1", "-1.9198149E9" }, + +{ "4.389072E-11", "-8.657572E9", + "-1", "-8.657572E9" }, + +{ "7.430157E-11", "-3.8599355E9", + "-1", "-3.8599355E9" }, + +{ "-5.8839114E-11", "-5.3409536E9", + "0", "-5.8839114E-11" }, + +{ "-3.3353615E-11", "8.9096924E-11", + "-1", "5.574331E-11" }, + +{ "6.335122E-11", "3.606541E-11", + "1", "2.7285809E-11" }, + +{ "-5.6885465E-11", "7.070333E-12", + "-9", "6.7475353E-12" }, + +{ "-7.581576E-11", "-3.4334775E-11", + "2", "-7.1462155E-12" }, + +{ "3.6686505E-11", "-1.9221425E-11", + "-2", "-1.7563462E-12" }, + +{ "3.066395E-11", "-2.3198866E-11", + "-2", "-1.573378E-11" }, + +{ "9.1089344E-11", "7.429058E19", + "0", "9.1089344E-11" }, + +{ "-7.2265194E-11", "-6.5831596E19", + "0", "-7.2265194E-11" }, + +{ "-4.9087675E-11", "1.9182038E19", + "-1", "1.9182038E19" }, + +{ "-7.907188E-11", "4.405831E19", + "-1", "4.405831E19" }, + +{ "6.118759E-11", "3.4342181E19", + "0", "6.118759E-11" }, + +{ "5.4731882E-11", "-5.861447E19", + "-1", "-5.861447E19" }, + +{ "6.121101E-11", "-1.8234462E-21", + "-33568860160", "0.0" }, + +{ "9.788758E-11", "-2.65478E-21", + "-36872200192", "0.0" }, + +{ "7.827001E-11", "-8.5754775E-21", + "-9127189504", "0.0" }, + +{ "-3.738018E-11", "-7.810784E-21", + "4785714176", "0.0" }, + +{ "7.31308E-11", "-2.0431058E-21", + "-35793936384", "0.0" }, + +{ "9.4578095E-11", "-3.0466443E-21", + "-31043366912", "0.0" }, + +{ "-4.8186137E19", "-0.95250696", + "50588749896299315200", "0.0" }, + +{ "9.548003E18", "-0.9061317", + "-10537102614582001664", "0.0" }, + +{ "5.5254813E19", "0.51959753", + "106341562860634636288", "0.0" }, + +{ "-4.2787504E19", "0.14769173", + "-289708190148186865664", "0.0" }, + +{ "-4.27109E17", "-0.03677529", + "11614021477430460416", "0.0" }, + +{ "-3.9238043E19", "0.26663417", + "-147160597790283792384", "0.0" }, + +{ "-2.0174873E19", "-6.7035556E7", + "300957794304", "0.0" }, + +{ "1.6296811E19", "-7.2014956E9", + "-2262976000", "0.0" }, + +{ "7.794499E19", "-7.412829E9", + "-10514876416", "0.0" }, + +{ "-1.2546485E19", "6.1565005E9", + "-2037924864", "0.0" }, + +{ "5.4549757E18", "-4.778849E9", + "-1141483264", "0.0" }, + +{ "-8.9214324E18", "3.0002557E9", + "-2973557248", "0.0" }, + +{ "8.790958E19", "-8.224902E-11", + "-1068822197453670185020302557184", "0.0" }, + +{ "9.029222E18", "1.3127345E-11", + "687817816164697187548814901248", "0.0" }, + +{ "6.7356843E19", "-9.1816894E-11", + "-733599685837775742566290948096", "0.0" }, + +{ "4.0346153E19", "2.0593792E-11", + "1959141510822234462049892564992", "0.0" }, + +{ "1.3402778E19", "-4.8733902E-11", + "-275019611403690085233016700928", "0.0" }, + +{ "-1.3005549E19", "5.6579824E-11", + "-229861963021783171398467846144", "0.0" }, + +{ "8.550302E19", "6.4624324E19", + "1", "2.0878699E19" }, + +{ "4.7897585E19", "-1.5724218E19", + "-4", "-1.4999288E19" }, + +{ "-8.6050445E19", "1.4007867E19", + "-7", "1.2004627E19" }, + +{ "-6.0799387E19", "-5.667626E19", + "1", "-4.1231221E18" }, + +{ "-7.847746E19", "-3.972193E19", + "1", "-3.875553E19" }, + +{ "-6.425414E19", "3.0601436E19", + "-3", "2.7550168E19" }, + +{ "2.8220074E-21", "-0.9401483", + "-1", "-0.9401483" }, + +{ "9.867747E-21", "0.86288685", + "0", "9.867747E-21" }, + +{ "6.2856053E-21", "-0.5235996", + "-1", "-0.5235996" }, + +{ "8.709991E-22", "0.42678982", + "0", "8.709991E-22" }, + +{ "1.0493481E-21", "0.9355661", + "0", "1.0493481E-21" }, + +{ "-6.137466E-21", "0.4328317", + "-1", "0.4328317" }, + +{ "6.5872774E-21", "-8.80464E9", + "-1", "-8.80464E9" }, + +{ "-1.0479629E-22", "-9.353607E9", + "0", "-1.0479629E-22" }, + +{ "-2.636932E-21", "9.794678E9", + "-1", "9.794678E9" }, + +{ "-7.912024E-21", "-2.9102356E9", + "0", "-7.912024E-21" }, + +{ "1.0071349E-21", "8.762459E9", + "0", "1.0071349E-21" }, + +{ "-6.795979E-21", "-9.445545E9", + "0", "-6.795979E-21" }, + +{ "6.0598967E-22", "-3.961637E-11", + "-1", "-3.961637E-11" }, + +{ "3.481348E-21", "-7.485006E-11", + "-1", "-7.485006E-11" }, + +{ "-5.610974E-21", "-4.073898E-11", + "0", "-5.610974E-21" }, + +{ "-6.2362584E-21", "8.403202E-11", + "-1", "8.403202E-11" }, + +{ "4.2029927E-21", "7.823452E-11", + "0", "4.2029927E-21" }, + +{ "-7.765272E-21", "-8.502908E-11", + "0", "-7.765272E-21" }, + +{ "2.7845436E-21", "3.490416E-21", + "0", "2.7845436E-21" }, + +{ "-1.4630091E-21", "9.193901E-21", + "-1", "7.730892E-21" }, + +{ "-8.1823826E-21", "8.941324E-21", + "-1", "7.5894165E-22" }, + +{ "-1.8218875E-21", "3.8057304E-21", + "-1", "1.9838427E-21" }, + +{ "5.8037763E-21", "-5.1721612E-21", + "-2", "-4.5405462E-21" }, + +{ "-8.179982E-21", "6.2204556E-21", + "-2", "4.2609293E-21" }, + +}; diff --git a/tests/exam_FF_minus.cc b/tests/exam_FF_minus.cc new file mode 100644 index 0000000..7544001 --- /dev/null +++ b/tests/exam_FF_minus.cc @@ -0,0 +1,457 @@ +#include "exam.h" +#include +#include + +static minus_test ffloat_minus_tests[] = { + +{ "-0.41894162", "0.23777992", + "-0.65672153" }, + +{ "0.74937063", "0.4803756", + "0.26899505" }, + +{ "0.46964037", "-0.94880456", + "1.4184449" }, + +{ "0.16453332", "0.035123527", + "0.12940979" }, + +{ "0.7353321", "-0.3952883", + "1.1306204" }, + +{ "-0.33693552", "-0.6941588", + "0.35722327" }, + +{ "-0.61853", "-9.25498E9", + "9.25498E9" }, + +{ "0.5172653", "-6.728693E9", + "6.728693E9" }, + +{ "0.1268478", "-1.8808037E9", + "1.8808037E9" }, + +{ "0.29479754", "-3.4643973E9", + "3.4643973E9" }, + +{ "0.34332883", "1.4258218E9", + "-1.4258218E9" }, + +{ "-0.4093976", "-1.6698813E9", + "1.6698813E9" }, + +{ "0.10942185", "-2.015636E-11", + "0.10942185" }, + +{ "0.30351585", "4.4276416E-11", + "0.30351585" }, + +{ "-0.41279083", "6.5274E-11", + "-0.41279083" }, + +{ "0.7813598", "-5.028443E-11", + "0.7813598" }, + +{ "-0.72214615", "2.5959075E-11", + "-0.72214615" }, + +{ "-0.8924311", "-5.2076333E-11", + "-0.8924311" }, + +{ "-0.26128495", "6.8887236E19", + "-6.8887236E19" }, + +{ "0.906616", "-2.0519019E18", + "2.0519019E18" }, + +{ "0.96452767", "-1.6347343E19", + "1.6347343E19" }, + +{ "-0.99801517", "8.383864E19", + "-8.383864E19" }, + +{ "-0.60573876", "-4.890489E19", + "4.890489E19" }, + +{ "-0.004701972", "6.3981E18", + "-6.3981E18" }, + +{ "0.34311903", "3.52871E-21", + "0.34311903" }, + +{ "-0.38159567", "-2.3400748E-21", + "-0.38159567" }, + +{ "-0.6719565", "-5.4333447E-21", + "-0.6719565" }, + +{ "-0.21363729", "8.021308E-21", + "-0.21363729" }, + +{ "0.5275244", "-4.88554E-21", + "0.5275244" }, + +{ "0.9064559", "-6.5840867E-21", + "0.9064559" }, + +{ "-3.0312538E8", "0.26249015", + "-3.0312538E8" }, + +{ "-9.217122E9", "0.22172129", + "-9.217122E9" }, + +{ "-1.157806E9", "-0.95704305", + "-1.157806E9" }, + +{ "6.743087E9", "-0.37863714", + "6.743087E9" }, + +{ "-4.0819942E8", "-0.068549395", + "-4.0819942E8" }, + +{ "4.586502E9", "0.29215187", + "4.586502E9" }, + +{ "5.091125E9", "-2.971223E9", + "8.0623483E9" }, + +{ "-2.1147072E8", "-8.537374E9", + "8.3259034E9" }, + +{ "-9.075735E9", "-9.072693E9", + "-3041280.0" }, + +{ "1.4614451E9", "3.0213921E9", + "-1.559947E9" }, + +{ "8.960645E9", "5.4822825E9", + "3.4783626E9" }, + +{ "-3.7246787E9", "-2.823592E9", + "-9.010867E8" }, + +{ "-3.4256804E9", "-1.8245674E-11", + "-3.4256804E9" }, + +{ "7.0777057E9", "3.6826153E-11", + "7.0777057E9" }, + +{ "3.4600579E9", "-5.207135E-11", + "3.4600579E9" }, + +{ "9.57872E9", "8.222393E-11", + "9.57872E9" }, + +{ "8.388926E9", "-1.1216945E-11", + "8.388926E9" }, + +{ "3.8273395E8", "1.153788E-11", + "3.8273395E8" }, + +{ "-1.2011469E8", "-9.879852E19", + "9.879852E19" }, + +{ "3.850388E9", "4.8155957E19", + "-4.8155957E19" }, + +{ "5.5329756E9", "-5.067925E19", + "5.067925E19" }, + +{ "3.3222902E9", "5.2892763E19", + "-5.2892763E19" }, + +{ "4.431185E9", "-8.005187E19", + "8.005187E19" }, + +{ "-7.307553E8", "-6.8217897E19", + "6.8217897E19" }, + +{ "7.9813893E9", "9.68989E-21", + "7.9813893E9" }, + +{ "-5.7208223E9", "9.790913E-21", + "-5.7208223E9" }, + +{ "-5.9564112E7", "9.217466E-21", + "-5.9564112E7" }, + +{ "5.4524237E9", "4.947411E-21", + "5.4524237E9" }, + +{ "1.4269632E9", "-5.1552662E-21", + "1.4269632E9" }, + +{ "3.7555832E9", "-4.168443E-21", + "3.7555832E9" }, + +{ "-4.1575327E-11", "-0.38582206", + "0.38582206" }, + +{ "-5.810516E-11", "-0.5456566", + "0.5456566" }, + +{ "-1.2386638E-11", "-0.6209788", + "0.6209788" }, + +{ "2.0245033E-11", "-0.7418727", + "0.7418727" }, + +{ "3.7671637E-11", "0.1772576", + "-0.1772576" }, + +{ "-2.2774244E-11", "-0.5959606", + "0.5959606" }, + +{ "-5.6623112E-11", "6.8330056E9", + "-6.8330056E9" }, + +{ "-9.2078116E-11", "-3.4236897E9", + "3.4236897E9" }, + +{ "-3.317883E-11", "-3.2438755E8", + "3.2438755E8" }, + +{ "6.711307E-11", "-7.9204526E9", + "7.9204526E9" }, + +{ "-5.1150143E-11", "9.1128E9", + "-9.1128E9" }, + +{ "-7.3234044E-11", "-8.067016E9", + "8.067016E9" }, + +{ "-3.217777E-11", "-1.6301262E-11", + "-1.5876508E-11" }, + +{ "9.6583325E-11", "5.882668E-11", + "3.7756645E-11" }, + +{ "-7.573351E-11", "6.3386435E-11", + "-1.3911994E-10" }, + +{ "-4.5759726E-11", "8.069604E-11", + "-1.2645576E-10" }, + +{ "-9.538651E-11", "-9.01152E-11", + "-5.271311E-12" }, + +{ "6.2486766E-11", "-3.414284E-11", + "9.662961E-11" }, + +{ "5.530477E-13", "-3.1361222E18", + "3.1361222E18" }, + +{ "1.7998643E-11", "1.5437615E19", + "-1.5437615E19" }, + +{ "-4.7948378E-11", "2.6669319E19", + "-2.6669319E19" }, + +{ "-6.8626884E-12", "-5.7713735E19", + "5.7713735E19" }, + +{ "6.195949E-11", "2.8851469E19", + "-2.8851469E19" }, + +{ "2.4957127E-11", "-2.661574E18", + "2.661574E18" }, + +{ "9.8157565E-11", "-4.561507E-21", + "9.8157565E-11" }, + +{ "-9.332288E-11", "-9.280375E-21", + "-9.332288E-11" }, + +{ "-9.916877E-11", "-1.6945641E-21", + "-9.916877E-11" }, + +{ "-6.460804E-11", "-3.6695186E-21", + "-6.460804E-11" }, + +{ "6.712223E-11", "-2.5360524E-21", + "6.712223E-11" }, + +{ "2.3824066E-11", "-7.439168E-21", + "2.3824066E-11" }, + +{ "-5.189389E19", "0.01453203", + "-5.189389E19" }, + +{ "7.0132006E19", "0.45530832", + "7.0132006E19" }, + +{ "2.9365046E19", "0.36346745", + "2.9365046E19" }, + +{ "-4.1377934E19", "0.37368965", + "-4.1377934E19" }, + +{ "-1.891423E19", "0.159002", + "-1.891423E19" }, + +{ "1.8096083E19", "-0.6511793", + "1.8096083E19" }, + +{ "6.4361307E19", "6.6511677E9", + "6.4361307E19" }, + +{ "-1.8698508E19", "1.1925399E9", + "-1.8698508E19" }, + +{ "7.75824E19", "7.7361823E9", + "7.75824E19" }, + +{ "-7.2570015E19", "3.0842496E9", + "-7.2570015E19" }, + +{ "-1.9014525E19", "-3.8941514E9", + "-1.9014525E19" }, + +{ "3.2787157E19", "-8.612244E9", + "3.2787157E19" }, + +{ "6.4268583E19", "-1.2707472E-11", + "6.4268583E19" }, + +{ "-6.5179933E19", "8.61941E-11", + "-6.5179933E19" }, + +{ "-8.106952E19", "2.1709537E-11", + "-8.106952E19" }, + +{ "2.5455064E19", "3.5653924E-11", + "2.5455064E19" }, + +{ "1.574235E19", "-2.7033407E-11", + "1.574235E19" }, + +{ "-1.1099541E19", "-8.620364E-12", + "-1.1099541E19" }, + +{ "-6.346294E19", "2.9902512E19", + "-9.336545E19" }, + +{ "4.9783164E19", "-2.079425E19", + "7.0577414E19" }, + +{ "-7.149202E19", "1.4282865E19", + "-8.577488E19" }, + +{ "6.0978866E19", "5.256896E19", + "8.409905E18" }, + +{ "-9.961146E19", "-1.9834548E19", + "-7.977691E19" }, + +{ "2.5196015E18", "5.0534214E19", + "-4.8014613E19" }, + +{ "-3.6981453E19", "-1.005367E-21", + "-3.6981453E19" }, + +{ "8.881044E19", "-9.717088E-22", + "8.881044E19" }, + +{ "4.9637263E19", "-7.544846E-21", + "4.9637263E19" }, + +{ "-4.2414725E19", "1.3904184E-21", + "-4.2414725E19" }, + +{ "7.844454E18", "-8.659333E-21", + "7.844454E18" }, + +{ "1.5733016E19", "8.638849E-21", + "1.5733016E19" }, + +{ "1.7531192E-21", "-0.8690463", + "0.8690463" }, + +{ "9.449351E-21", "0.7848489", + "-0.7848489" }, + +{ "5.5016538E-21", "-0.8998171", + "0.8998171" }, + +{ "-6.977279E-21", "-0.9815793", + "0.9815793" }, + +{ "-7.9253305E-21", "-0.21357381", + "0.21357381" }, + +{ "4.026555E-21", "0.5610563", + "-0.5610563" }, + +{ "-7.080433E-21", "-1.9501078E9", + "1.9501078E9" }, + +{ "-8.152211E-21", "8.164317E9", + "-8.164317E9" }, + +{ "2.177096E-21", "-8.591886E9", + "8.591886E9" }, + +{ "9.387247E-21", "3.5730028E9", + "-3.5730028E9" }, + +{ "-7.589234E-21", "-4.9193774E9", + "4.9193774E9" }, + +{ "1.5755653E-21", "-2.3484498E9", + "2.3484498E9" }, + +{ "9.3034425E-21", "8.28104E-11", + "-8.28104E-11" }, + +{ "-6.417297E-21", "-8.352926E-11", + "8.352926E-11" }, + +{ "8.728735E-21", "9.160732E-11", + "-9.160732E-11" }, + +{ "3.8984202E-21", "6.5116944E-12", + "-6.5116944E-12" }, + +{ "6.288995E-21", "-5.6701328E-11", + "5.6701328E-11" }, + +{ "-2.7652023E-22", "-1.01428276E-11", + "1.01428276E-11" }, + +{ "4.7200214E-21", "-3.726995E18", + "3.726995E18" }, + +{ "-2.2945808E-21", "-7.3098524E19", + "7.3098524E19" }, + +{ "-9.493033E-21", "3.4235436E19", + "-3.4235436E19" }, + +{ "3.7946773E-21", "-5.126768E18", + "5.126768E18" }, + +{ "-1.2865209E-21", "3.5096026E19", + "-3.5096026E19" }, + +{ "-8.403449E-21", "5.704743E18", + "-5.704743E18" }, + +{ "2.928304E-21", "-5.574477E-21", + "8.502781E-21" }, + +{ "-9.46122E-21", "-3.858943E-21", + "-5.602277E-21" }, + +{ "7.296878E-22", "1.8123137E-21", + "-1.0826259E-21" }, + +{ "5.866651E-21", "2.4605584E-21", + "3.4060923E-21" }, + +{ "-7.633577E-21", "9.915102E-21", + "-1.7548679E-20" }, + +{ "-8.7881085E-24", "3.001468E-21", + "-3.0102563E-21" }, + +}; diff --git a/tests/exam_FF_mul.cc b/tests/exam_FF_mul.cc new file mode 100644 index 0000000..396225c --- /dev/null +++ b/tests/exam_FF_mul.cc @@ -0,0 +1,421 @@ +#include "exam.h" +#include +#include + +static mul_test ffloat_mul_tests[] = { + +{ "0.3098436", "0.0057770014", + "0.001789967" }, + +{ "-0.14583993", "-0.028087378", + "0.004096261" }, + +{ "0.21399558", "0.96054405", + "0.20555218" }, + +{ "0.7590452", "0.8427266", + "0.6396676" }, + +{ "-0.34523207", "0.20272356", + "-0.06998668" }, + +{ "-0.98096234", "0.98158866", + "-0.96290153" }, + +{ "0.40309322", "4.0009994E9", + "1.6127757E9" }, + +{ "0.15507132", "9.481803E9", + "1.4703557E9" }, + +{ "0.5218476", "-2.1933102E9", + "-1.1445737E9" }, + +{ "0.17258328", "2.6295781E8", + "4.538212E7" }, + +{ "0.25962013", "8.699164E9", + "2.258478E9" }, + +{ "0.47902477", "-1.4075732E9", + "-6.7426246E8" }, + +{ "0.9642294", "-1.6256952E-11", + "-1.5675431E-11" }, + +{ "0.6098744", "-8.802921E-12", + "-5.3686764E-12" }, + +{ "-0.25792134", "4.804327E-11", + "-1.2391385E-11" }, + +{ "-0.8724403", "-9.101418E-11", + "7.940444E-11" }, + +{ "-0.13318628", "8.1157005E-11", + "-1.08089995E-11" }, + +{ "-0.54116476", "-9.353639E-11", + "5.0618596E-11" }, + +{ "0.9018487", "7.411783E19", + "6.6843068E19" }, + +{ "-0.6835444", "-7.590606E19", + "5.188516E19" }, + +{ "-0.9896146", "5.195105E18", + "-5.141152E18" }, + +{ "-0.4838531", "1.88174E19", + "-9.1048573E18" }, + +{ "-0.31826657", "-3.3103586E19", + "1.0535765E19" }, + +{ "0.6818549", "-9.227651E19", + "-6.2919192E19" }, + +{ "0.7676919", "7.320194E-21", + "5.6196534E-21" }, + +{ "0.49369502", "4.9805288E-21", + "2.4588622E-21" }, + +{ "0.9599328", "7.903804E-21", + "7.58712E-21" }, + +{ "0.13215566", "7.603894E-21", + "1.0048976E-21" }, + +{ "-0.35744518", "-9.408464E-21", + "3.36301E-21" }, + +{ "-0.79346496", "9.006081E-21", + "-7.146009E-21" }, + +{ "4.1775434E9", "-0.13509268", + "-5.643555E8" }, + +{ "7.27846E9", "-0.8181822", + "-5.9551063E9" }, + +{ "2.9669427E9", "0.7082195", + "2.1012467E9" }, + +{ "7.609933E9", "-0.33963126", + "-2.5845711E9" }, + +{ "3.4241843E9", "0.3924479", + "1.3438139E9" }, + +{ "-3.8366538E9", "0.56461394", + "-2.1662282E9" }, + +{ "3.7237007E9", "1.2646783E9", + "4.7092836E18" }, + +{ "-2.7657871E9", "-3.6314278E9", + "1.0043756E19" }, + +{ "-4.753982E9", "-5.8879616E8", + "2.7991263E18" }, + +{ "8.877933E9", "7.973602E9", + "7.07891E19" }, + +{ "-8.312081E9", "-8.941637E9", + "7.432361E19" }, + +{ "-4.297749E9", "9.913122E9", + "-4.260411E19" }, + +{ "-7.893335E9", "-4.7961794E-11", + "0.3785785" }, + +{ "-4.1332334E9", "7.221582E-11", + "-0.29848483" }, + +{ "1.9981688E9", "2.8169871E-11", + "0.056288157" }, + +{ "-5.8555295E9", "-7.562528E-11", + "0.44282603" }, + +{ "7.377872E9", "-1.5020383E-11", + "-0.11081846" }, + +{ "8.891134E9", "-7.035395E-11", + "-0.6255264" }, + +{ "-7.1412096E9", "5.1873507E19", + "-3.7043958E29" }, + +{ "8.0983844E9", "9.136914E19", + "7.399425E29" }, + +{ "-6.1437537E9", "-9.398771E19", + "5.7743737E29" }, + +{ "-2.3000973E9", "6.8743785E19", + "-1.5811739E29" }, + +{ "3.5817969E9", "-6.0353143E19", + "-2.161727E29" }, + +{ "6.544234E9", "8.265139E19", + "5.4089003E29" }, + +{ "2.1273733E8", "-2.3684083E-21", + "-5.0384886E-13" }, + +{ "-4.2644698E9", "2.956708E-21", + "-1.2608792E-11" }, + +{ "-5.1238026E9", "5.341445E-21", + "-2.7368509E-11" }, + +{ "-3.0125368E9", "5.201843E-21", + "-1.5670742E-11" }, + +{ "-4.4709827E9", "-1.5399217E-22", + "6.8849635E-13" }, + +{ "-4.934225E9", "5.9229795E-21", + "-2.9225313E-11" }, + +{ "-2.1100623E-11", "0.9615048", + "-2.028835E-11" }, + +{ "6.6090705E-12", "0.4100405", + "2.7099865E-12" }, + +{ "-9.541609E-11", "0.82497185", + "-7.871559E-11" }, + +{ "-2.7884627E-11", "-0.5218528", + "1.4551671E-11" }, + +{ "9.180904E-13", "-0.26436818", + "-2.4271386E-13" }, + +{ "2.6154882E-11", "0.2004636", + "5.2431015E-12" }, + +{ "9.751009E-11", "-7.0098227E9", + "-0.6835284" }, + +{ "-1.312651E-11", "1.9450307E8", + "-0.0025531466" }, + +{ "-4.591856E-11", "-4.6141565E8", + "0.021187542" }, + +{ "-4.1950752E-11", "-9.55923E9", + "0.4010169" }, + +{ "-2.1888996E-11", "9.976215E9", + "-0.21836932" }, + +{ "4.2696267E-11", "-7.927695E9", + "-0.33848298" }, + +{ "1.9615304E-11", "-5.3584637E-12", + "-1.05107896E-22" }, + +{ "-8.7289814E-11", "3.4389686E-11", + "-3.0018693E-21" }, + +{ "6.8621386E-11", "-1.4248663E-11", + "-9.77763E-22" }, + +{ "-9.5643375E-11", "-7.7591066E-11", + "7.421071E-21" }, + +{ "-6.3313584E-11", "5.173857E-11", + "-3.2757542E-21" }, + +{ "-6.968663E-11", "-4.966581E-12", + "3.461043E-22" }, + +{ "7.942278E-11", "-3.1309486E19", + "-2.4866865E9" }, + +{ "1.7023414E-11", "2.5512804E19", + "4.34315E8" }, + +{ "2.6554937E-11", "9.146128E19", + "2.4287485E9" }, + +{ "9.309172E-13", "-3.6298406E19", + "-3.3790812E7" }, + +{ "-6.106873E-11", "3.5271824E18", + "-2.1540056E8" }, + +{ "-2.8420502E-11", "-6.6643682E19", + "1.8940468E9" }, + +{ "-5.84991E-11", "1.5304011E-21", + "-8.952709E-32" }, + +{ "6.30787E-11", "-9.366236E-21", + "-5.9081004E-31" }, + +{ "1.9745445E-11", "7.034156E-21", + "1.3889253E-31" }, + +{ "2.440728E-11", "6.50959E-22", + "1.5888139E-32" }, + +{ "6.0243255E-11", "-1.7734902E-21", + "-1.0684082E-31" }, + +{ "1.0381073E-11", "7.167948E-21", + "7.441099E-32" }, + +{ "6.3378214E18", "0.022634745", + "1.43454966E17" }, + +{ "5.4942345E19", "0.26696533", + "1.4667702E19" }, + +{ "9.807893E19", "-0.99720424", + "-9.780473E19" }, + +{ "-7.1504E18", "0.045440495", + "-3.249177E17" }, + +{ "-7.265508E19", "0.37276286", + "-2.7083115E19" }, + +{ "9.3705245E19", "0.6617385", + "6.200837E19" }, + +{ "7.768628E19", "1.37205E9", + "1.0658947E29" }, + +{ "1.5640021E18", "9.344063E9", + "1.4614135E28" }, + +{ "3.8593804E19", "-9.424651E8", + "-3.6373312E28" }, + +{ "-9.23689E19", "-6.980498E9", + "6.447809E29" }, + +{ "7.926599E19", "5.0871127E9", + "4.0323505E29" }, + +{ "3.540541E19", "-5.11486E9", + "-1.810937E29" }, + +{ "-7.023858E19", "6.959093E-11", + "-4.8879683E9" }, + +{ "-2.0809586E19", "-4.045683E-12", + "8.418899E7" }, + +{ "5.3608545E19", "-7.0354486E-11", + "-3.7716017E9" }, + +{ "8.974303E19", "-6.383404E-11", + "-5.72866E9" }, + +{ "-6.8900017E19", "9.845904E-11", + "-6.7838295E9" }, + +{ "9.325442E19", "-3.9829796E-11", + "-3.7143045E9" }, + +{ "5.9436735E19", "-5.713992E-21", + "-0.33962104" }, + +{ "7.266224E18", "8.9780915E-21", + "0.06523682" }, + +{ "-3.6717237E18", "3.3338123E-21", + "-0.012240837" }, + +{ "4.119367E19", "-7.309974E-21", + "-0.30112466" }, + +{ "-8.453134E19", "4.6281215E-22", + "-0.03912213" }, + +{ "-3.7493624E19", "5.480264E-21", + "-0.20547494" }, + +{ "6.3693945E-21", "-0.25352144", + "-1.6147781E-21" }, + +{ "-8.51531E-21", "0.6031129", + "-5.135693E-21" }, + +{ "-9.771993E-21", "0.2740926", + "-2.678431E-21" }, + +{ "-4.2903415E-21", "0.5916119", + "-2.5382172E-21" }, + +{ "-3.7330673E-21", "0.9738175", + "-3.6353263E-21" }, + +{ "5.860415E-21", "-0.9997709", + "-5.8590725E-21" }, + +{ "-9.4827234E-21", "7.6195564E9", + "-7.225415E-11" }, + +{ "5.9501194E-21", "9.102942E9", + "5.4163594E-11" }, + +{ "2.8867428E-21", "-9.615872E9", + "-2.7758549E-11" }, + +{ "5.0077543E-21", "7.8715663E9", + "3.941887E-11" }, + +{ "7.082003E-21", "4.5221494E9", + "3.2025875E-11" }, + +{ "-2.9215627E-21", "5.131017E9", + "-1.4990589E-11" }, + +{ "-9.1914904E-21", "-2.3301847E-11", + "2.141787E-31" }, + +{ "1.3389891E-21", "-7.032628E-11", + "-9.4166125E-32" }, + +{ "-8.540776E-21", "3.052019E-11", + "-2.6066613E-31" }, + +{ "-2.7608417E-21", "-6.8345785E-12", + "1.886919E-32" }, + +{ "1.2978333E-21", "-2.1870255E-12", + "-2.8383944E-33" }, + +{ "8.2235335E-23", "-3.5080876E-11", + "-2.8848876E-33" }, + +{ "-3.958064E-21", "8.038726E19", + "-0.3181779" }, + +{ "7.752178E-21", "1.0747784E19", + "0.08331874" }, + +{ "-5.5964265E-21", "-8.700492E19", + "0.48691663" }, + +{ "3.2236927E-21", "3.6203593E19", + "0.116709255" }, + +{ "-6.308517E-21", "-3.8032156E19", + "0.2399265" }, + +{ "4.8663387E-21", "9.008218E19", + "0.43837038" }, + +}; diff --git a/tests/exam_FF_plus.cc b/tests/exam_FF_plus.cc new file mode 100644 index 0000000..4000735 --- /dev/null +++ b/tests/exam_FF_plus.cc @@ -0,0 +1,457 @@ +#include "exam.h" +#include +#include + +static plus_test ffloat_plus_tests[] = { + +{ "0.79351956", "0.07393837", + "0.8674579" }, + +{ "-0.52145976", "-0.14409256", + "-0.6655523" }, + +{ "-0.094845235", "-0.091273725", + "-0.18611896" }, + +{ "-0.11106694", "-0.90595967", + "-1.0170267" }, + +{ "0.46902913", "0.6453068", + "1.114336" }, + +{ "-0.30989015", "0.6634996", + "0.35360944" }, + +{ "-0.58887166", "-3.1150198E9", + "-3.1150198E9" }, + +{ "0.08032262", "-8.451643E9", + "-8.451643E9" }, + +{ "-0.734433", "7.601292E9", + "7.601292E9" }, + +{ "0.77958024", "-4.2334996E9", + "-4.2334996E9" }, + +{ "-0.5492505", "4.4427484E9", + "4.4427484E9" }, + +{ "-0.45681345", "4.7386803E9", + "4.7386803E9" }, + +{ "-0.5951412", "7.866326E-11", + "-0.5951412" }, + +{ "0.8511461", "8.396644E-11", + "0.8511461" }, + +{ "-0.94777477", "-7.635105E-11", + "-0.94777477" }, + +{ "-0.20783025", "-1.7222382E-11", + "-0.20783025" }, + +{ "0.82520634", "-5.3449255E-11", + "0.82520634" }, + +{ "0.7797032", "3.7409843E-11", + "0.7797032" }, + +{ "0.9915549", "5.16192E19", + "5.16192E19" }, + +{ "-0.6311349", "2.1599532E19", + "2.1599532E19" }, + +{ "0.42801672", "4.8533796E18", + "4.8533796E18" }, + +{ "-0.11165339", "6.518633E19", + "6.518633E19" }, + +{ "-0.5133993", "-5.5200484E19", + "-5.5200484E19" }, + +{ "0.11643493", "-1.0541451E19", + "-1.0541451E19" }, + +{ "-0.7063649", "8.243067E-21", + "-0.7063649" }, + +{ "8.4728E-4", "-7.5151976E-21", + "8.4728E-4" }, + +{ "-0.47157037", "-8.748518E-21", + "-0.47157037" }, + +{ "0.7662331", "-5.6591384E-21", + "0.7662331" }, + +{ "-0.9418909", "-4.455382E-21", + "-0.9418909" }, + +{ "-0.88412094", "6.6664897E-21", + "-0.88412094" }, + +{ "5.5891533E9", "-0.11624104", + "5.5891533E9" }, + +{ "-8.760519E9", "0.22073412", + "-8.760519E9" }, + +{ "6.8390047E9", "-0.6434584", + "6.8390047E9" }, + +{ "5.1620844E9", "-0.93939686", + "5.1620844E9" }, + +{ "9.21372E9", "-0.93054956", + "9.21372E9" }, + +{ "-2.7403366E9", "-0.9354063", + "-2.7403366E9" }, + +{ "6.4755876E9", "7.780013E9", + "1.4255601E10" }, + +{ "3.6402857E9", "-4.6589404E9", + "-1.0186547E9" }, + +{ "9.858497E9", "-3.1216233E9", + "6.7368735E9" }, + +{ "-5.199144E9", "-8.3410964E9", + "-1.354024E10" }, + +{ "-2.2145843E9", "7.4088115E9", + "5.194227E9" }, + +{ "3.6034734E9", "-4.7355105E9", + "-1.1320371E9" }, + +{ "-3.974853E9", "8.344858E-11", + "-3.974853E9" }, + +{ "9.633741E9", "9.879035E-11", + "9.633741E9" }, + +{ "-5.84563E9", "-2.8054357E-11", + "-5.84563E9" }, + +{ "1.6814709E8", "-6.702281E-11", + "1.6814709E8" }, + +{ "6.627381E8", "8.1083654E-11", + "6.627381E8" }, + +{ "6.617609E9", "-7.74835E-11", + "6.617609E9" }, + +{ "-4.325255E9", "7.48992E19", + "7.48992E19" }, + +{ "8.963769E9", "5.6527995E19", + "5.6527995E19" }, + +{ "3.2307428E9", "-3.772047E19", + "-3.772047E19" }, + +{ "-1.5719092E9", "9.119215E19", + "9.119215E19" }, + +{ "-3.1338138E9", "2.7048826E19", + "2.7048826E19" }, + +{ "-4.4506363E9", "9.624759E19", + "9.624759E19" }, + +{ "1.8499094E9", "4.968932E-21", + "1.8499094E9" }, + +{ "1.1302281E9", "1.590079E-21", + "1.1302281E9" }, + +{ "5.7261727E9", "-3.3212954E-21", + "5.7261727E9" }, + +{ "1.8314988E9", "-6.247946E-21", + "1.8314988E9" }, + +{ "-7.301286E9", "-8.870309E-21", + "-7.301286E9" }, + +{ "8.0970737E9", "-6.944993E-21", + "8.0970737E9" }, + +{ "9.076142E-11", "0.79629874", + "0.79629874" }, + +{ "-2.5569331E-11", "-0.11109424", + "-0.11109424" }, + +{ "5.817238E-11", "0.8669617", + "0.8669617" }, + +{ "5.0001194E-11", "0.1629681", + "0.1629681" }, + +{ "-5.314657E-11", "0.33499128", + "0.33499128" }, + +{ "3.4244614E-11", "0.7846571", + "0.7846571" }, + +{ "5.016508E-11", "1.2850774E9", + "1.2850774E9" }, + +{ "-6.236206E-11", "-3.9463657E9", + "-3.9463657E9" }, + +{ "-9.461717E-11", "-2.86016E9", + "-2.86016E9" }, + +{ "9.271425E-11", "9.936099E9", + "9.936099E9" }, + +{ "-9.330213E-12", "4.2810826E9", + "4.2810826E9" }, + +{ "8.8110796E-11", "-7.967343E9", + "-7.967343E9" }, + +{ "-3.252064E-11", "9.310712E-11", + "6.058648E-11" }, + +{ "9.2616026E-11", "-4.2321837E-11", + "5.029419E-11" }, + +{ "-6.138445E-11", "2.0083374E-11", + "-4.130108E-11" }, + +{ "-1.672895E-11", "-4.1673078E-11", + "-5.8402026E-11" }, + +{ "-5.054619E-11", "-1.9569606E-11", + "-7.0115795E-11" }, + +{ "-6.765585E-11", "6.200571E-11", + "-5.65014E-12" }, + +{ "-8.958499E-11", "9.627367E18", + "9.627367E18" }, + +{ "-3.639458E-11", "-6.774422E19", + "-6.774422E19" }, + +{ "5.885664E-11", "7.710968E19", + "7.710968E19" }, + +{ "-2.8348934E-11", "-6.8805507E19", + "-6.8805507E19" }, + +{ "3.783013E-11", "-4.363011E19", + "-4.363011E19" }, + +{ "9.9192224E-11", "7.840148E19", + "7.840148E19" }, + +{ "1.5157771E-11", "-6.578477E-21", + "1.5157771E-11" }, + +{ "3.269849E-11", "-1.5641468E-21", + "3.269849E-11" }, + +{ "-2.4697334E-11", "-5.9471063E-21", + "-2.4697334E-11" }, + +{ "-7.226034E-11", "-8.027814E-21", + "-7.226034E-11" }, + +{ "6.705153E-12", "1.3146739E-21", + "6.705153E-12" }, + +{ "-9.281199E-11", "1.940757E-22", + "-9.281199E-11" }, + +{ "6.841885E19", "0.29873258", + "6.841885E19" }, + +{ "-7.487633E19", "-0.41199452", + "-7.487633E19" }, + +{ "9.324847E19", "-0.12986994", + "9.324847E19" }, + +{ "1.7454827E19", "-0.9480438", + "1.7454827E19" }, + +{ "-2.2794772E19", "-0.85242146", + "-2.2794772E19" }, + +{ "-1.4789046E18", "-0.3244334", + "-1.4789046E18" }, + +{ "-1.0913384E19", "6.2691034E8", + "-1.0913384E19" }, + +{ "9.054158E19", "6.7361736E9", + "9.054158E19" }, + +{ "-2.404365E19", "2.819194E9", + "-2.404365E19" }, + +{ "3.0628145E19", "3.8188636E9", + "3.0628145E19" }, + +{ "-3.7020847E19", "-4.248917E8", + "-3.7020847E19" }, + +{ "8.556466E19", "-5.431256E9", + "8.556466E19" }, + +{ "4.8590555E19", "-4.0259546E-11", + "4.8590555E19" }, + +{ "-1.990289E19", "-3.2150872E-11", + "-1.990289E19" }, + +{ "-1.5843934E19", "5.37822E-11", + "-1.5843934E19" }, + +{ "1.596058E19", "2.465645E-11", + "1.596058E19" }, + +{ "8.179266E19", "-8.080585E-11", + "8.179266E19" }, + +{ "8.673572E19", "-2.1405459E-11", + "8.673572E19" }, + +{ "-4.5302206E19", "4.4819714E19", + "-4.824921E17" }, + +{ "2.1413618E19", "-7.160984E19", + "-5.0196224E19" }, + +{ "9.760235E19", "-7.810464E19", + "1.949771E19" }, + +{ "-7.518544E19", "-5.7398474E19", + "-1.32583915E20" }, + +{ "-2.459352E19", "6.0089863E19", + "3.5496343E19" }, + +{ "-9.009707E19", "1.9710512E19", + "-7.0386556E19" }, + +{ "4.9167807E19", "-1.261897E-21", + "4.9167807E19" }, + +{ "-8.647001E18", "-1.4144885E-21", + "-8.647001E18" }, + +{ "-6.2763383E19", "6.69688E-21", + "-6.2763383E19" }, + +{ "1.6851938E19", "-4.9109547E-21", + "1.6851938E19" }, + +{ "-7.0371058E19", "-9.246501E-21", + "-7.0371058E19" }, + +{ "-2.8498996E19", "3.3614294E-21", + "-2.8498996E19" }, + +{ "-4.8211753E-21", "0.5153807", + "0.5153807" }, + +{ "-9.730312E-21", "0.3705088", + "0.3705088" }, + +{ "-8.83036E-21", "0.21063423", + "0.21063423" }, + +{ "1.8688595E-21", "-0.38304192", + "-0.38304192" }, + +{ "-7.9137435E-21", "-0.9482965", + "-0.9482965" }, + +{ "-5.7913193E-21", "-0.16538233", + "-0.16538233" }, + +{ "-4.667948E-21", "5.69782E9", + "5.69782E9" }, + +{ "-1.6254025E-21", "1.100067E9", + "1.100067E9" }, + +{ "5.4919865E-21", "9.125866E9", + "9.125866E9" }, + +{ "2.1973532E-21", "-5.218964E9", + "-5.218964E9" }, + +{ "-4.018586E-21", "-6.5943096E9", + "-6.5943096E9" }, + +{ "-7.7845274E-22", "4.172669E9", + "4.172669E9" }, + +{ "-2.843846E-21", "9.243441E-12", + "9.243441E-12" }, + +{ "1.1533075E-21", "3.327943E-11", + "3.327943E-11" }, + +{ "5.977113E-21", "6.507544E-11", + "6.507544E-11" }, + +{ "1.1817801E-21", "-4.1877824E-11", + "-4.1877824E-11" }, + +{ "1.932947E-21", "9.4013144E-11", + "9.4013144E-11" }, + +{ "8.526454E-21", "8.396772E-11", + "8.396772E-11" }, + +{ "-4.8870485E-21", "5.9277504E19", + "5.9277504E19" }, + +{ "-4.7174987E-21", "2.5545484E19", + "2.5545484E19" }, + +{ "-8.818029E-21", "1.2602901E19", + "1.2602901E19" }, + +{ "-1.2268113E-21", "-9.071741E19", + "-9.071741E19" }, + +{ "-7.0568975E-21", "-6.9825405E19", + "-6.9825405E19" }, + +{ "8.723312E-21", "-5.802767E19", + "-5.802767E19" }, + +{ "7.1661314E-21", "4.10364E-21", + "1.1269772E-20" }, + +{ "8.181265E-21", "-4.6898657E-21", + "3.4913997E-21" }, + +{ "-8.570217E-21", "-5.5145446E-21", + "-1.4084761E-20" }, + +{ "1.3507604E-23", "-7.152723E-21", + "-7.139215E-21" }, + +{ "-7.859527E-21", "-9.369602E-21", + "-1.7229128E-20" }, + +{ "-4.9014434E-21", "1.4580911E-21", + "-3.443352E-21" }, + +}; diff --git a/tests/exam_I.cc b/tests/exam_I.cc new file mode 100644 index 0000000..7636831 --- /dev/null +++ b/tests/exam_I.cc @@ -0,0 +1,7 @@ +#include "exam_I_plus.cc" +#include "exam_I_minus.cc" +#include "exam_I_mul.cc" +#include "exam_I_div.cc" +#include "exam_I_floor.cc" + +DO_TESTS(integer,cl_I,cl_RA) diff --git a/tests/exam_I_div.cc b/tests/exam_I_div.cc new file mode 100644 index 0000000..3311796 --- /dev/null +++ b/tests/exam_I_div.cc @@ -0,0 +1,299 @@ +#include "exam.h" +#include +#include +#include +#include + +static div_test integer_div_tests[] = { + +{ "10105597264942543888", "14352488138967388642", + "5052798632471271944/7176244069483694321" }, + +{ "-17631701977702695093", "3931860028646338313", + "-17631701977702695093/3931860028646338313" }, + +{ "-1606495881715082381", "16324360910828438638", + "-1606495881715082381/16324360910828438638" }, + +{ "-7960193178071300653", "-10280747961248435844", + "7960193178071300653/10280747961248435844" }, + +{ "-11544909483975853384", "-16041992360613233027", + "11544909483975853384/16041992360613233027" }, + +{ "-5758820541298901548", "-2596462557714095861", + "5758820541298901548/2596462557714095861" }, + +{ "-13056342734667572546", "46502284983183419157350605242474199851", + "-13056342734667572546/46502284983183419157350605242474199851" }, + +{ "12668118634717482325", "-338544675918656078399121171905238525746", + "-12668118634717482325/338544675918656078399121171905238525746" }, + +{ "-16738429327795346815", "164053836541028518093058940786011794219", + "-16738429327795346815/164053836541028518093058940786011794219" }, + +{ "-9884600460121235549", "-53914696297933680001835530599748561584", + "9884600460121235549/53914696297933680001835530599748561584" }, + +{ "6753521264659576004", "71759828079371803409570464915096122874", + "3376760632329788002/35879914039685901704785232457548061437" }, + +{ "-6072478784520825268", "83641961138289700975241455431547940418", + "-3036239392260412634/41820980569144850487620727715773970209" }, + +{ "-6708950756971973620", "-9847903810677323447803434015107261150885944735136350527205856921771320298384705376646797569973415403097847060539915279223391112430240736564839483430569706", + "3354475378485986810/4923951905338661723901717007553630575442972367568175263602928460885660149192352688323398784986707701548923530269957639611695556215120368282419741715284853" }, + +{ "11263779860755455072", "2292311486393743282743453705144070351222990311578446825826935237655927864700827857707370158936582804478427014131790879562565658386819339761919809732496450", + "1877296643459242512/382051914398957213790575617524011725203831718596407804304489206275987977450137976284561693156097134079737835688631813260427609731136556626986634955416075" }, + +{ "9956488981426387585", "-12351244248621474338537656633137999145154500022264356186225225426288301330225259889671144104952158102155582320296061124840400655528634050137479515338944145", + "-1991297796285277517/2470248849724294867707531326627599829030900004452871237245045085257660266045051977934228820990431620431116464059212224968080131105726810027495903067788829" }, + +{ "-14875992781716065391", "4906952781757522095285156014969507916562921709689447567404076064849249737893410245743456952512717420040816186768213920574809530298070437840356629617118643", + "-2125141825959437913/700993254536788870755022287852786845223274529955635366772010866407035676841915749391922421787531060005830883824030560082115647185438633977193804231016949" }, + +{ "16043178952268979636", "-4962728781666935768923030490263743715131420507991284894489828489607808897271220927863958149140648859077934323268424257800724618076505149638049461104621679", + "-5347726317422993212/1654242927222311922974343496754581238377140169330428298163276163202602965757073642621319383046882953025978107756141419266908206025501716546016487034873893" }, + +{ "-14889985628902581941", "3075736124701105220602924325296812116294816310089906623707854625135862902005059305428034753787024827094954645083406870532379125275086885405969947540175361", + "-14889985628902581941/3075736124701105220602924325296812116294816310089906623707854625135862902005059305428034753787024827094954645083406870532379125275086885405969947540175361" }, + +{ "-1719613957783789857", "19860562547348050982501313785551054055826630539673708970554435103060535649825139319625648954889488501680865494719253019921780044205805557658109807483499994523398090829033362953135186523580359552555144614353929273831853529446536288544481045105104526669277307473478898498061888931858821517694257595658138564305517447595298378933983614114298000880741350618424855028965861930329619462261269994651112266861896630584883581092431090390354633458596611690990999635499563944625720180529318327647519405136188243979680965052005899543797270970540925042201315580510136864931200059448645464256385079735225156720340173280541113382758", + "-1719613957783789857/19860562547348050982501313785551054055826630539673708970554435103060535649825139319625648954889488501680865494719253019921780044205805557658109807483499994523398090829033362953135186523580359552555144614353929273831853529446536288544481045105104526669277307473478898498061888931858821517694257595658138564305517447595298378933983614114298000880741350618424855028965861930329619462261269994651112266861896630584883581092431090390354633458596611690990999635499563944625720180529318327647519405136188243979680965052005899543797270970540925042201315580510136864931200059448645464256385079735225156720340173280541113382758" }, + +{ "-10969623867482498359", "1292477254230352575769754773488799598312602810841892384475535212194939033905139960602724737178675944133847094464739764817257836826367652752931492512753561670732296265459534230949226553571982695924178928914002527460943582374603078611662312521259541641138419845784008028215876048965254023368247445173694441960256131358058174374542730502334351759171930973722361567186133851896057677818979314942434199157003833234473048838906103902832115569853657335216793235394595479328932380393044485884605451918890395812628720641212850763944658735838941829604119213195707479940053016354291972875689927240247563236506479099606571912595", + "-10969623867482498359/1292477254230352575769754773488799598312602810841892384475535212194939033905139960602724737178675944133847094464739764817257836826367652752931492512753561670732296265459534230949226553571982695924178928914002527460943582374603078611662312521259541641138419845784008028215876048965254023368247445173694441960256131358058174374542730502334351759171930973722361567186133851896057677818979314942434199157003833234473048838906103902832115569853657335216793235394595479328932380393044485884605451918890395812628720641212850763944658735838941829604119213195707479940053016354291972875689927240247563236506479099606571912595" }, + +{ "-3716891004757979686", "-19452372993227550502015765258932159656814363741878583541173956168837566077148160901999018823586675966076058615847408138956450751813058209394199427182041779436168298455103717521843644244801542056954603631432685194627158423459586845252167819811850263444712218938833443253125954475476481099092216538126519474183531297423759923656571895377587989169731023397615799830371852298135015608612181670362528239430952907458704415974164085176066242388561893721949244663406941558257051263727439679525692652639731850971185056484335828001005009903973037524233097329857690857731943951449292814500362180170793919266389501882641682782987", + "3716891004757979686/19452372993227550502015765258932159656814363741878583541173956168837566077148160901999018823586675966076058615847408138956450751813058209394199427182041779436168298455103717521843644244801542056954603631432685194627158423459586845252167819811850263444712218938833443253125954475476481099092216538126519474183531297423759923656571895377587989169731023397615799830371852298135015608612181670362528239430952907458704415974164085176066242388561893721949244663406941558257051263727439679525692652639731850971185056484335828001005009903973037524233097329857690857731943951449292814500362180170793919266389501882641682782987" }, + +{ "-4863232114852441787", "-22963038454503597269981750990033903654256693514059439027985256604978917966584414065892146187253799108250061573972673983350956191446047978392921074610323648301008272837432907303975548030552369880338022067315042332692023645592417869181836251486577977896077712912433381480614752789750181208326525834629219729662085632321271870762094800588296544243340047360684854239747242066367921596241226349790282723168222543448385227922748241223520686047460119733024390425165073367321644498280127168757335614077882325524816799960018589278475564547840614315473357481582710826551932681173443524724802157570101916268510464302946527662720", + "4863232114852441787/22963038454503597269981750990033903654256693514059439027985256604978917966584414065892146187253799108250061573972673983350956191446047978392921074610323648301008272837432907303975548030552369880338022067315042332692023645592417869181836251486577977896077712912433381480614752789750181208326525834629219729662085632321271870762094800588296544243340047360684854239747242066367921596241226349790282723168222543448385227922748241223520686047460119733024390425165073367321644498280127168757335614077882325524816799960018589278475564547840614315473357481582710826551932681173443524724802157570101916268510464302946527662720" }, + +{ "-16248276650501285553", "-3381199474840825715485713565301777938368574604710714363907009216856320913536015299178065264912798511857598595067318796576494480424838898250138649774858742984769125731728430552285782315111538920026330816414650913188340281906359149109963139438960274321560117812365241840204034925444652058916966934904097509799291744775242863360284348334605170437300543978049053839829106628489146216325576991696936733592366926096500684308845306493636196092408597450926695579897293944488261001228478152650490677071497874746121221519036861983646423005753475340900508665494162949119110128646472783016552527735050067363030838015919512260159", + "16248276650501285553/3381199474840825715485713565301777938368574604710714363907009216856320913536015299178065264912798511857598595067318796576494480424838898250138649774858742984769125731728430552285782315111538920026330816414650913188340281906359149109963139438960274321560117812365241840204034925444652058916966934904097509799291744775242863360284348334605170437300543978049053839829106628489146216325576991696936733592366926096500684308845306493636196092408597450926695579897293944488261001228478152650490677071497874746121221519036861983646423005753475340900508665494162949119110128646472783016552527735050067363030838015919512260159" }, + +{ "18296946401228630959", "3302341071702763311560113831030141639804425031433511503765833897787925467295486187687396312611805794369889470239777040624530990622212474466940548049117664906468330871893337410618797113677420975837622378808494314918471282099855916016026079371666730617071364751834080179173620476977670099126230223862266413091012344741482772771219725893630556702028108027870656512750807359335108428687238687397060104669074315031780019301768744978815422943986587389425726602444937024004102212071953113581935989741954695450085391443134273670514145585869912689150728183940456773133212037846765421397201956541430155664614978559762638030787", + "494512064898071107/89252461397371981393516590027841665940660135984689500101779294534808796413391518586145846286805562009997012709183163260122459206005742553160555352678855808282927861402522632719426949018308675022638442670499846349147872489185295027460164307342344070731658506806326491329016769648045137814222438482763957110567901209229264128951884483611636667622381298050558284128400198900948876451006451010731354180245251757615676197345101215643660079567205064579073691957971270919029789515458192258971242965998775552705010579544169558662544475293781424031100761728120453327924649671534200578302755582200815017962566988101692919751" }, + +{ "-60488682170925814337492051725122486652", "14880088785789146426", + "-30244341085462907168746025862561243326/7440044392894573213" }, + +{ "126617729996196635247771282957911941277", "-7166506344996883172", + "-126617729996196635247771282957911941277/7166506344996883172" }, + +{ "-278675896803726074870988122161067771390", "7744689831802931490", + "-27867589680372607487098812216106777139/774468983180293149" }, + +{ "-283351838662873779255871649630248958879", "6912311315831153835", + "-14913254666467041013466928927907839941/363805858727955465" }, + +{ "-9715584046609700027352634666499181378", "3368831995960494221", + "-9715584046609700027352634666499181378/3368831995960494221" }, + +{ "-137493547985106345282009151869389470397", "-1916381539906956855", + "137493547985106345282009151869389470397/1916381539906956855" }, + +{ "-328662747577960331872949773416436800743", "-231069430804205460334599495337085157308", + "328662747577960331872949773416436800743/231069430804205460334599495337085157308" }, + +{ "213595640581249636406536485951630735277", "-48492294677143227478357598229530842959", + "-213595640581249636406536485951630735277/48492294677143227478357598229530842959" }, + +{ "85922846498729014445816145204889624189", "193533957681757355413031965695625196813", + "85922846498729014445816145204889624189/193533957681757355413031965695625196813" }, + +{ "24053342958857142686054803491202486471", "196417511107100936775397820630955772553", + "24053342958857142686054803491202486471/196417511107100936775397820630955772553" }, + +{ "102038936612518756467074084117019701214", "-111946989731587760700903475996379168167", + "-102038936612518756467074084117019701214/111946989731587760700903475996379168167" }, + +{ "-3006867214208872584699983438179656913", "-234257597822744479264249663225224173340", + "3006867214208872584699983438179656913/234257597822744479264249663225224173340" }, + +{ "-279839802710533516603863620922251878907", "-3244112647743502769852782626803305310331045534071805654982307107362388474314396636799597033636575215617240554815450017779373048313695795886893032630263219", + "279839802710533516603863620922251878907/3244112647743502769852782626803305310331045534071805654982307107362388474314396636799597033636575215617240554815450017779373048313695795886893032630263219" }, + +{ "123635964546481689465778244982425098404", "7701433613491146708866098469269971554817017737111287276993583150548359764165526640986060909954451793171933304569726872785964805121981749276421956645830854", + "61817982273240844732889122491212549202/3850716806745573354433049234634985777408508868555643638496791575274179882082763320493030454977225896585966652284863436392982402560990874638210978322915427" }, + +{ "166158110049010486343321316578688184578", "4093720847216792748840371965199135052196058344862447621818024731938681519017878880275303125899149558774718190527651555811733139227128378041055212888819294", + "83079055024505243171660658289344092289/2046860423608396374420185982599567526098029172431223810909012365969340759508939440137651562949574779387359095263825777905866569613564189020527606444409647" }, + +{ "147416259636838312272435267341375281181", "-11266711292262839805944890501811605204323255169233519804446548849178247889563130015168799346120099052214488209897402054530713234143622703174309015777885801", + "-147416259636838312272435267341375281181/11266711292262839805944890501811605204323255169233519804446548849178247889563130015168799346120099052214488209897402054530713234143622703174309015777885801" }, + +{ "102557200511608632541115941654031896919", "3866177549962722728707550488877109233779215384377007088712280650225992470307822792085413087509167847767889824884877044539352696974351192629898363157976511", + "102557200511608632541115941654031896919/3866177549962722728707550488877109233779215384377007088712280650225992470307822792085413087509167847767889824884877044539352696974351192629898363157976511" }, + +{ "47794953079190110032282671989549362415", "3802290983508829335098916118339496411537222492645529399519373082799614656011270200284796148989094312601047370399228868583158444769807910513767845541589667", + "47794953079190110032282671989549362415/3802290983508829335098916118339496411537222492645529399519373082799614656011270200284796148989094312601047370399228868583158444769807910513767845541589667" }, + +{ "-169956065319483471022234920202991103615", "-9934427489865644196610501807375648335352544234206717324511161205173460054921759084767897792996557220898467288533128078406604709773449948420404563411793533441010236017064154469575084055359823982786110746700747423674942932421964955746280671982635899487781780756099620799397239156211815110739544719746684712086075069101799537802834839550142629064374734870047412916259754010150500874430055034366305216104752636211802195447299210332237598443674867760860326529472901775427058078447963316168327741049511844237329137194533000697525539835371015163158135757326482343130221118201740819963770851200676279882978581431999960842565", + "33991213063896694204446984040598220723/1986885497973128839322100361475129667070508846841343464902232241034692010984351816953579558599311444179693457706625615681320941954689989684080912682358706688202047203412830893915016811071964796557222149340149484734988586484392991149256134396527179897556356151219924159879447831242363022147908943949336942417215013820359907560566967910028525812874946974009482583251950802030100174886011006873261043220950527242360439089459842066447519688734973552172065305894580355085411615689592663233665548209902368847465827438906600139505107967074203032631627151465296468626044223640348163992754170240135255976595716286399992168513" }, + +{ "-83006311763073652927964071041666508273", "13480787677843057038436344704360462056114592749322481662307876594244244638227291805757775026215166740035048814729231681821563443093991755779505400592913963236010573873554317250153995160235771659208137440518282824497744092608999871327127239673370293239927529076145825972430101380272357235582367639159280348164804218713823424182167974242317526959809443701996053548231667727254858428867000011055354779789221097183515832386890638024105232865079002765479933320220378271026425568216748186200736499581088153390350474814123049637951929317200314355414551809067125550551841102097159644340520444983020267926123546444838010089690", + "-83006311763073652927964071041666508273/13480787677843057038436344704360462056114592749322481662307876594244244638227291805757775026215166740035048814729231681821563443093991755779505400592913963236010573873554317250153995160235771659208137440518282824497744092608999871327127239673370293239927529076145825972430101380272357235582367639159280348164804218713823424182167974242317526959809443701996053548231667727254858428867000011055354779789221097183515832386890638024105232865079002765479933320220378271026425568216748186200736499581088153390350474814123049637951929317200314355414551809067125550551841102097159644340520444983020267926123546444838010089690" }, + +{ "-312626207169475064151212222217866488926", "6989069923898656093413456232544365450599471748502878018530391549015151484336014906416216966193568842618920902504390187814247729346977677905224098932673981665869061845335443588666641982676550205160521286690015544764015602751932938178737949961754714143180917985455875095030469699198116593730005119922928175789172042067281849364217595912265452199938281052984802042194034638773435768458457616208103331213440768472281882976004050012769415198321241810008696147179275528426468408383757692656341606162350211696837361434874035354680073309142183699892959618671515841112321607728427286289324836870027735590091451421689980776552", + "-52104367861579177358535370369644414821/1164844987316442682235576038757394241766578624750479669755065258169191914056002484402702827698928140436486817084065031302374621557829612984204016488778996944311510307555907264777773663779425034193420214448335924127335933791988823029789658326959119023863486330909312515838411616533019432288334186653821362631528673677880308227369599318710908699989713508830800340365672439795572628076409602701350555202240128078713647162667341668794902533053540301668116024529879254737744734730626282109390267693725035282806226905812339225780012218190363949982159936445252640185386934621404547714887472811671289265015241903614996796092" }, + +{ "-151709660794612786408772973806200383563", "-26960472721919005254400858042130056790831511338891584787669209989714807518625849812230185079206081782191501696661436514815190623849929065098497737155759771863508038766934134444191240792356114381746781342181881402424707118515655119761011977116554236461222788625158348668147995099157685699761135150772589445239536582228655532345059046596356954495360132444243748421428095867292294626357084961338288369883088525401649234025290736504802104065029036642533076183281468647642956623788270236516849523210698622687255735945678505925047193818483603361307498423724202227256505312543145618362906047473400380196192622607541097732443", + "151709660794612786408772973806200383563/26960472721919005254400858042130056790831511338891584787669209989714807518625849812230185079206081782191501696661436514815190623849929065098497737155759771863508038766934134444191240792356114381746781342181881402424707118515655119761011977116554236461222788625158348668147995099157685699761135150772589445239536582228655532345059046596356954495360132444243748421428095867292294626357084961338288369883088525401649234025290736504802104065029036642533076183281468647642956623788270236516849523210698622687255735945678505925047193818483603361307498423724202227256505312543145618362906047473400380196192622607541097732443" }, + +{ "138834496986391136939574372853300933725", "-8052690543272184576133758511645801940246473546142520821850130421981395129853341888352999304040698251945886555605291324954368612109314080471658982022831338507499254609048475429862437003158379101603576571787302167207044118847876475134352180874260998595377014195145760071923429129767580115085764485254455919915567128572731355497418831212259648020550107573824886521471697331410754043280744066090848295906051303624846301488010249980896364883452154860562864255354208802313850527991005497484253401461375477060954782095047043919500670383372218536999834862885439984085848342867301834247551832677237328664699302165347765799113", + "-15426055220710126326619374761477881525/894743393696909397348195390182866882249608171793613424650014491331266125539260209816999922671188694660654061733921258328263179123257120052406553558092370945277694956560941714429159667017597677955952952420811351911893790983097386126039131208251222066153001577238417785769269903307508901676196053917161768879507458730303483944157647912473294224505567508202765169052410814601194893697860451787872032878450144847205144609778916664544040542605794984506984917261578755812650058665667277498250377940152830784550531343894115991055630042596913170777759429209493331565094260318589092694172425853026369851633255796149751755457" }, + +{ "276499207940187081393841843387608369874", "27347897028734618663428054896349668572244941195143856840032842195489553215406302254043947382368793914074147314353589439281000471813879502242851166670252197853998033813694814376228360691543987661407996785043637351295817024680721181205269262470473172181965930243852520386958529041036476807810647578694133804796395977642274699322030062940721165202488695975750512485574440928370802874677938542169620505668128224812441566912043326338714451629730522324228356364241376445033028898865300103247057378058702233150414643818049655628999871012383236520330575609745427181485617250755214922048672375947942288446974485524776744246517", + "8919329288393131657865865915729302254/882190226733374795594453383753215115233707780488511510968801361144824297271171040453030560721573997228198300463019014170354853929479983943317779570008135414645097864957897237942850344888515731013161186614310882299865065312281328425976427821628166844579546136898468399579307388420531509929375728344972058219238579923944345139420324610991005329112538579862919757599175513818412995957352856199020016311875104026207792481033655688345627471926791042717043753685205691775258996737590325911195399292216201069368214316711279213838705516528491500655825019669207328435019911314684352324150721804772331885386273726605701427307" }, + +{ "-8979365591106781219797187096315899769868799444656824967426553299158070014074001230883484015880186603742048949313393413640240595706939311540002219411120389", "-1698360947072008877", + "1282766513015254459971026728045128538552685634950974995346650471308295716296285890126212002268598086248864135616199059091462942243848473077143174201588627/242622992438858411" }, + +{ "-12831814656788829919185319784994714617782749504716966706877579983082880759985031662545957372565411439648298939198657738497464024214657609856476819270030801", "454910754379715", + "-273017333123166594025219569893504566335803180951424823550586808150699590637979397075445901543944924247836147642524632733988596259886332124605889771702783/9678952220845" }, + +{ "-7834266257250691217409788323211914445703052638619784568844628449769010091330019095736167988675873769434766592786720961949649685040028101508217441360672222", "-428418418877192732", + "3917133128625345608704894161605957222851526319309892284422314224884505045665009547868083994337936884717383296393360480974824842520014050754108720680336111/214209209438596366" }, + +{ "5737805823029931079838944835405107564434908634489801628049345331760087020955028323378020396677249341204498685189403657652738071833877470777083253103936452", "9588993061977446661", + "5737805823029931079838944835405107564434908634489801628049345331760087020955028323378020396677249341204498685189403657652738071833877470777083253103936452/9588993061977446661" }, + +{ "-4001605821592542867351046644170905984672346731784670159062281252096012802838642896466582343641124674682428297533953704119505640938363392225910275838094045", "15760991890495426717", + "-4001605821592542867351046644170905984672346731784670159062281252096012802838642896466582343641124674682428297533953704119505640938363392225910275838094045/15760991890495426717" }, + +{ "2876630161532936743269451364955814480771395635620140205538288339793482694260173239474830738010159518887660000673207712630507802368373928478641773477534499", "-6788234478844960330", + "-2876630161532936743269451364955814480771395635620140205538288339793482694260173239474830738010159518887660000673207712630507802368373928478641773477534499/6788234478844960330" }, + +{ "6230070442453337264527950102774203962152836811174649694700041895216739851602598854067104967963392074425258687296947909484969927078206601660837276754799333", "190237375887614033974333796608341639595", + "6230070442453337264527950102774203962152836811174649694700041895216739851602598854067104967963392074425258687296947909484969927078206601660837276754799333/190237375887614033974333796608341639595" }, + +{ "-12098771374444180013224380531550204930654718468097503123335711776524055419889032578894177605164827523969169377266342179411916625188550162928371789854647472", "-41681385674896602840749705069663453185", + "12098771374444180013224380531550204930654718468097503123335711776524055419889032578894177605164827523969169377266342179411916625188550162928371789854647472/41681385674896602840749705069663453185" }, + +{ "13185465843955116174925558412278612918939024395488172088108029202384613698982949554556435640011161663974075894844304583900497170806796813871943782330552768", "-155202352609947911537719051033334010254", + "-6592732921977558087462779206139306459469512197744086044054014601192306849491474777278217820005580831987037947422152291950248585403398406935971891165276384/77601176304973955768859525516667005127" }, + +{ "12784980722915659825738808684740823452025110516624579136271791852138148426775553817114893299569867520414470532361018804123866264934222335562072872489963044", "-249441012384365373362771955533424187237", + "-12784980722915659825738808684740823452025110516624579136271791852138148426775553817114893299569867520414470532361018804123866264934222335562072872489963044/249441012384365373362771955533424187237" }, + +{ "8517839393030302736298983538193047531846908718502576675615969705563208303329257882565359266876007571790337440612227785062203468682754778416335180236967433", "-23101645464137481399279134347982485126", + "-8517839393030302736298983538193047531846908718502576675615969705563208303329257882565359266876007571790337440612227785062203468682754778416335180236967433/23101645464137481399279134347982485126" }, + +{ "-10157767522292361462005308817460390811646115952647174687477824271227382383351453540195549992670001314693794150879368708343715654899952822395459036505947192", "-25611473771508763579433379623726126173", + "10157767522292361462005308817460390811646115952647174687477824271227382383351453540195549992670001314693794150879368708343715654899952822395459036505947192/25611473771508763579433379623726126173" }, + +{ "-8580252632668820290302987230726290672170301642399871646484841866604753910447257372311950907045477729554307803379310475132687855999835211879267570997069974", "5347050029330174629945013741349819215851040371727058829687387719215168997632386672310746837193930669173408831178932364105722911104309540550576485594530627", + "-8580252632668820290302987230726290672170301642399871646484841866604753910447257372311950907045477729554307803379310475132687855999835211879267570997069974/5347050029330174629945013741349819215851040371727058829687387719215168997632386672310746837193930669173408831178932364105722911104309540550576485594530627" }, + +{ "7706102251141221799524762336156378964168657337573751909064577951085535246905735244239132983582998872001001594454632956803416956154262109939446710205558308", "6334400709835247308796432875490978646658012545184955441452799118298109610816693049400832749087993843490999852355789914065232784070007399786089389453289854", + "3853051125570610899762381168078189482084328668786875954532288975542767623452867622119566491791499436000500797227316478401708478077131054969723355102779154/3167200354917623654398216437745489323329006272592477720726399559149054805408346524700416374543996921745499926177894957032616392035003699893044694726644927" }, + +{ "12609622044672092190084693450911157599596799695538449568681964257744962273690941575572590166273187189250007688411096790312605666562908125521094386992971478", "-8237858212652788898158635047388584411011830102060269605835391741772914864422465141467281143809161251942948659243584296367296559912373856433388249393853968", + "-6304811022336046095042346725455578799798399847769224784340982128872481136845470787786295083136593594625003844205548395156302833281454062760547193496485739/4118929106326394449079317523694292205505915051030134802917695870886457432211232570733640571904580625971474329621792148183648279956186928216694124696926984" }, + +{ "-9988492519236282081446302885464711911055350309732728352574982611126604133339499170845224383282665522673248920309221355720665956477799939031063172954469785", "-1878204914631111607000020160429571305542722711529281855381736226230242796648854769713662269068364131804626863789957256573308715572826753755672493154125086", + "9988492519236282081446302885464711911055350309732728352574982611126604133339499170845224383282665522673248920309221355720665956477799939031063172954469785/1878204914631111607000020160429571305542722711529281855381736226230242796648854769713662269068364131804626863789957256573308715572826753755672493154125086" }, + +{ "-10729942326579120947061030583094707809945059776287551713953926998992375520903658867971835616518813070294302895655369081976222497359056962112544408591462495", "-4917625712783289245414023733273041940212797202855299465496072729329693853584860839801663152618595377553772371725021213143455497822882736730281253858119747", + "10729942326579120947061030583094707809945059776287551713953926998992375520903658867971835616518813070294302895655369081976222497359056962112544408591462495/4917625712783289245414023733273041940212797202855299465496072729329693853584860839801663152618595377553772371725021213143455497822882736730281253858119747" }, + +{ "8114113595157517238445304590338354472776364877475201453112450680537221171989478096363668912966343706408770932684807802285529572133696646343108263717309148", "5443953102973235688784499815692116502566847594605098596244123647428188581304528525010862185203718640610834003873728718183528722470626702382993497913086105", + "8114113595157517238445304590338354472776364877475201453112450680537221171989478096363668912966343706408770932684807802285529572133696646343108263717309148/5443953102973235688784499815692116502566847594605098596244123647428188581304528525010862185203718640610834003873728718183528722470626702382993497913086105" }, + +{ "-7125100205152691887479515774712530950031072786448635736036405923401522078562323494262148946679985384635556474075282302608446439950458673260234175964199684", "-23871420315894180764743988478670341498770583257649869670486332228804693253344466615199983955886679924409910043885402198203427975742868174334723967563526738510726448815413356678504144193747696164586135745786501041060322480940451156015256191962506052700295351077719851275026974629635679531161390660244641370183176979934485671396035404817388717005746812037357500295693454623478902942336087760288091719793968445716246099043828787040340339906538864570506773535078524092440112404847904632624419421052178754041718790915772437556681684830937503838434712179830722395832238257078212535157309743054115702650740005055678387806081", + "7125100205152691887479515774712530950031072786448635736036405923401522078562323494262148946679985384635556474075282302608446439950458673260234175964199684/23871420315894180764743988478670341498770583257649869670486332228804693253344466615199983955886679924409910043885402198203427975742868174334723967563526738510726448815413356678504144193747696164586135745786501041060322480940451156015256191962506052700295351077719851275026974629635679531161390660244641370183176979934485671396035404817388717005746812037357500295693454623478902942336087760288091719793968445716246099043828787040340339906538864570506773535078524092440112404847904632624419421052178754041718790915772437556681684830937503838434712179830722395832238257078212535157309743054115702650740005055678387806081" }, + +{ "4801495919363827077158204249631885157347198552733998896638174958434968555935827788499392382851493568264006507028024783408190862186734863708684652212703744", "29234959990138609668202089052356468732793041824333219340488007351402997202222578434579705387840772390513345507274006495462445058795870182760749392281528881636623188890883479914921272700981309656920982410970774047916714087713562927554033500521877735827036675598267184309367127514966388636440710253467328441763131873309183205727440365838789320851968108312559316922678357314418486932673434031479515016224407618177089903730349114511598373251388750023508633761000320088841886505077453257141723747388913336375142897897501529451618927178835485127020789481918641637409265186365292847057986276062625965612268181771076051892980", + "1200373979840956769289551062407971289336799638183499724159543739608742138983956947124848095712873392066001626757006195852047715546683715927171163053175936/7308739997534652417050522263089117183198260456083304835122001837850749300555644608644926346960193097628336376818501623865611264698967545690187348070382220409155797222720869978730318175245327414230245602742693511979178521928390731888508375130469433956759168899566796077341781878741597159110177563366832110440782968327295801431860091459697330212992027078139829230669589328604621733168358507869878754056101904544272475932587278627899593312847187505877158440250080022210471626269363314285430936847228334093785724474375382362904731794708871281755197370479660409352316296591323211764496569015656491403067045442769012973245" }, + +{ "10769619761532897875307527770350128978615798426116103116325434914975512103385205123955114305107607195469345895102375220593168903042839441996791318999499708", "-7224105715967976893083374742254251507019823877014718307738328810406361200631626366722837314776666720638271529652546975342143108973422364041422652163016078890272393678677152791565494865444430757858556891645947268886646732022748338160528677218733159766121781240328812893374941548395710123982510227501927393735585082736583984561348450061452997663109932611188779299623613963995350679177776686423432406091192517292522853783968685873925548901506191291253596763183277703635837071862492572256145656312023955675669362656148946145528559574994353884313568526553663370513565393821926602014407548325293145102073923450066319746913", + "-10769619761532897875307527770350128978615798426116103116325434914975512103385205123955114305107607195469345895102375220593168903042839441996791318999499708/7224105715967976893083374742254251507019823877014718307738328810406361200631626366722837314776666720638271529652546975342143108973422364041422652163016078890272393678677152791565494865444430757858556891645947268886646732022748338160528677218733159766121781240328812893374941548395710123982510227501927393735585082736583984561348450061452997663109932611188779299623613963995350679177776686423432406091192517292522853783968685873925548901506191291253596763183277703635837071862492572256145656312023955675669362656148946145528559574994353884313568526553663370513565393821926602014407548325293145102073923450066319746913" }, + +{ "1505915608160301518246681692927442986955390537144107830770082927276722640395785957392652130911646706470337068266772174699405268120590454296080828168261019", "31152879253507543898583880698200027990847289346701738353567402100527465991154555548630544962150902011282973749886327325250084401181379196961322399337408341296727915922288276602390334861175305055229766353672502691855637668618950047400571070157436221479289152631256433294884836727331457389922838951144187501751190662594278336543502171639899940796536926507796271202659224890656712231014450702948847764643603683153113663072089256293587951842007583210791100743318865647555912543508324790181772321217524164822106191538518498016236866957803105254555578252294418243701672226181762763332992886540089416888889135117147250495261", + "1505915608160301518246681692927442986955390537144107830770082927276722640395785957392652130911646706470337068266772174699405268120590454296080828168261019/31152879253507543898583880698200027990847289346701738353567402100527465991154555548630544962150902011282973749886327325250084401181379196961322399337408341296727915922288276602390334861175305055229766353672502691855637668618950047400571070157436221479289152631256433294884836727331457389922838951144187501751190662594278336543502171639899940796536926507796271202659224890656712231014450702948847764643603683153113663072089256293587951842007583210791100743318865647555912543508324790181772321217524164822106191538518498016236866957803105254555578252294418243701672226181762763332992886540089416888889135117147250495261" }, + +{ "-4912349668310730778272626761660101328812783790262451913449395750351147048676353891314609774894027305081515542385381430403698808605768281804457186380542764", "6582102431028556562269167182029950958541569095123705594954788174046339660437206159173417583841743892857066740116322758515837624700881569925244230209567223461401193316695082415261197843574563450002486582967745135870782254839990479649574452750850133306720341823136645982650022199634379361313745598455049448887744206616434903460504591098363901961758069797933831934878649993183747273660007900662110776570580293994733189753806312784239743585453090900671308673380802381312083077891736513388250097195232616017027333586286786139736783210630705878401429301217589001317082952461701571026008195534878902572422952568763551674434", + "-2456174834155365389136313380830050664406391895131225956724697875175573524338176945657304887447013652540757771192690715201849404302884140902228593190271382/3291051215514278281134583591014975479270784547561852797477394087023169830218603079586708791920871946428533370058161379257918812350440784962622115104783611730700596658347541207630598921787281725001243291483872567935391127419995239824787226375425066653360170911568322991325011099817189680656872799227524724443872103308217451730252295549181950980879034898966915967439324996591873636830003950331055388285290146997366594876903156392119871792726545450335654336690401190656041538945868256694125048597616308008513666793143393069868391605315352939200714650608794500658541476230850785513004097767439451286211476284381775837217" }, + +{ "-11503235648135220410087372678575470255397243144180272745183844970864347348074104828328211521698012119761674096067066173927209129755062269068090560678650614", "-5548338218081690289723998288742945948643693817491921699797822887914665364835947234564530865119623677435878746610856459141463506776423054050179729345956931675338102809929977610828639446535095411122377961067651902947030310564736893080382424590568134091858634304377553326990788802662029347894499019277621467098333287442862683493159356014650672092060912274570436879076161496563079759704321556494898013269338428360856068237785049960484767969682269790642298701577934519452927652996671267126348627432295779183359417597868330923329974640383630473044712419371517153268338860560601603043892503067815822312755611206254762903436", + "5751617824067610205043686339287735127698621572090136372591922485432173674037052414164105760849006059880837048033533086963604564877531134534045280339325307/2774169109040845144861999144371472974321846908745960849898911443957332682417973617282265432559811838717939373305428229570731753388211527025089864672978465837669051404964988805414319723267547705561188980533825951473515155282368446540191212295284067045929317152188776663495394401331014673947249509638810733549166643721431341746579678007325336046030456137285218439538080748281539879852160778247449006634669214180428034118892524980242383984841134895321149350788967259726463826498335633563174313716147889591679708798934165461664987320191815236522356209685758576634169430280300801521946251533907911156377805603127381451718" }, + +{ "-22964048032108117904633365483799091488990853392670636861794813863757795874434768543212887316456319246155824842161717179767513360050328383696194174741889496306018655333450647372293193335577883672679165775070112770359697627614883420620410888137853011387271594559450892054491963940112235887802995117234918878648066362268919389271696465517050425727202664230530633207566444357393843669758809938086228366322548799235049875711702216182219182908217345405023677260470015666831191434586902791186444958476491096759363292487221288620810273243009200212776634572092195691654105986099646006756823055390654876878195583529521482548988", "10644501761877612307", + "-22964048032108117904633365483799091488990853392670636861794813863757795874434768543212887316456319246155824842161717179767513360050328383696194174741889496306018655333450647372293193335577883672679165775070112770359697627614883420620410888137853011387271594559450892054491963940112235887802995117234918878648066362268919389271696465517050425727202664230530633207566444357393843669758809938086228366322548799235049875711702216182219182908217345405023677260470015666831191434586902791186444958476491096759363292487221288620810273243009200212776634572092195691654105986099646006756823055390654876878195583529521482548988/10644501761877612307" }, + +{ "-19058897134776675884737764093896349427183484738023061956638485191239529906311503740032626797095131123523175909943402828257449376045336777553758951620699386266853663342003969442142858702229701661125904623724248177901462857013835790939020450746503125344631958534655024089231193396521561965297735217497608287565163852923704017958259400904834287026933197193592591423799328167149965328232560408884408251535373934831244856695227539243433290481951528897142697352526450162440279318507285454432916819060795455956931254810171588139618689138022062041222735056137988435900866680084665165131313435515187611756148824388549448126467", "-8326067459929079652", + "19058897134776675884737764093896349427183484738023061956638485191239529906311503740032626797095131123523175909943402828257449376045336777553758951620699386266853663342003969442142858702229701661125904623724248177901462857013835790939020450746503125344631958534655024089231193396521561965297735217497608287565163852923704017958259400904834287026933197193592591423799328167149965328232560408884408251535373934831244856695227539243433290481951528897142697352526450162440279318507285454432916819060795455956931254810171588139618689138022062041222735056137988435900866680084665165131313435515187611756148824388549448126467/8326067459929079652" }, + +{ "25828007361450952719858846443651616751980622231808382804245407702688699228397920589229449608543284896555585501243582045708656531815385828908740757435341854996277769645696261182122648194952548457487178342682313459444433667556195761154944956714756269417591048771194019245925463541886773351873002480266654825771525233808830260734678788520487541379982691221386179066818743751876186761036101255542680066874888848011074569355779905086056095043888696435054884292698783753890317487209955316141370052511469715869816445031102161253514609763532756500340262263800747279044587806090353812452308490155782240390040070679663451429071", "-16419739031141199968", + "-25828007361450952719858846443651616751980622231808382804245407702688699228397920589229449608543284896555585501243582045708656531815385828908740757435341854996277769645696261182122648194952548457487178342682313459444433667556195761154944956714756269417591048771194019245925463541886773351873002480266654825771525233808830260734678788520487541379982691221386179066818743751876186761036101255542680066874888848011074569355779905086056095043888696435054884292698783753890317487209955316141370052511469715869816445031102161253514609763532756500340262263800747279044587806090353812452308490155782240390040070679663451429071/16419739031141199968" }, + +{ "-1669696848499325185991294008037906453080648048592518700324899343297324898656645662186964240087582483813312797482298159224575128489696846451225871663856944749639170892311973606684486632224811435175199158920841554176114937196187087530038509898368755036744105403511353564606301040888877621412514452110348953863172547944175251415725815533087344857665837809749724257466399374547882097484009980477192931829030533366309859182367479867549644502538060694266048652224732348150866071381652452605392696555259221463464108413747443898588713629829490175098280805280460168541344102200890646453100478450456898359263676257882174308268", "-3154577849943484396", + "417424212124831296497823502009476613270162012148129675081224835824331224664161415546741060021895620953328199370574539806143782122424211612806467915964236187409792723077993401671121658056202858793799789730210388544028734299046771882509627474592188759186026350877838391151575260222219405353128613027587238465793136986043812853931453883271836214416459452437431064366599843636970524371002495119298232957257633341577464795591869966887411125634515173566512163056183087037716517845413113151348174138814805365866027103436860974647178407457372543774570201320115042135336025550222661613275119612614224589815919064470543577067/788644462485871099" }, + +{ "-2215504974719141921873290809898041836016933916943403987778356628123168736190963062169230280020568365292362281642280014010817115943641228422541948070912910166283758843455538187697141038676028739959626556519808411324617157646799936128314485433146912658200236754847332237438334421065771940922444296618134121662770699950019164632463150784605652351782139277998735272280336096528241168196650073301607171613955878761317417480490869592669781417658461696905996344800864447403426286476662235990122025654999230690604488053668524888833992415515434190712628587043474760836969696399229242018051635699746048823240033842587927229964", "-11305319675542865070", + "1107752487359570960936645404949020918008466958471701993889178314061584368095481531084615140010284182646181140821140007005408557971820614211270974035456455083141879421727769093848570519338014369979813278259904205662308578823399968064157242716573456329100118377423666118719167210532885970461222148309067060831385349975009582316231575392302826175891069638999367636140168048264120584098325036650803585806977939380658708740245434796334890708829230848452998172400432223701713143238331117995061012827499615345302244026834262444416996207757717095356314293521737380418484848199614621009025817849873024411620016921293963614982/5652659837771432535" }, + +{ "24358677073350645219370308521851912760304925518671532565724702185818845784332554892130070740233218685874351979772556877899278790031132507391155876157108663291716896413773711734271947599485714147026138105714458778787734198938526335256418673319464023475137997251085298903419563039860433435847755093653670989129405749785476487449599232956305952768800154351414655365461746574761818724131185410194605648466196476174400166047788352670171627261342369793028465418799251589432585363577887467959594667618177199696618852093807640490831859585621198048572586882398004957371434677752931134884039120875470266936204172511104679441462", "8754800987327220648", + "12179338536675322609685154260925956380152462759335766282862351092909422892166277446065035370116609342937175989886278438949639395015566253695577938078554331645858448206886855867135973799742857073513069052857229389393867099469263167628209336659732011737568998625542649451709781519930216717923877546826835494564702874892738243724799616478152976384400077175707327682730873287380909362065592705097302824233098238087200083023894176335085813630671184896514232709399625794716292681788943733979797333809088599848309426046903820245415929792810599024286293441199002478685717338876465567442019560437735133468102086255552339720731/4377400493663610324" }, + +{ "-26302114071841994464108666310942614602208671348774320769941579409198660404735714925432808094014718434192516800374483192192707032773903982752997957629389083405320034044554226640590549491188742685901503166669355807243735533977994184111229208270447279559478659750835531593667003322059717930484363943660175452777363121025595100592911646539549735930625865256846706785601753749996181113742254145758187876411260965175520035400453360390392991183382425735199046574346992179663247011131958270717402007532256308394559029768974932620173103778338779940189812875680687510582798628982957687329572431433891809534332514765287899172737", "196971971351558855568201373145365478995", + "-26302114071841994464108666310942614602208671348774320769941579409198660404735714925432808094014718434192516800374483192192707032773903982752997957629389083405320034044554226640590549491188742685901503166669355807243735533977994184111229208270447279559478659750835531593667003322059717930484363943660175452777363121025595100592911646539549735930625865256846706785601753749996181113742254145758187876411260965175520035400453360390392991183382425735199046574346992179663247011131958270717402007532256308394559029768974932620173103778338779940189812875680687510582798628982957687329572431433891809534332514765287899172737/196971971351558855568201373145365478995" }, + +{ "-25700334917103749626396366612061842558162882395534131493737229591609654899446089376271023701490708870843231350129849819430092002268875830384992877382393956173037794109904701961390126146975281052960293513473777226100954163054292968509501976296424278813632162404905591038465215586347229260479401862039805429711982871702185657527199220459658257385112793877259572278229045135617281858788415643567614198333459934599272409406206213115625226065750113120833933806486512117533453281522448845990642550827848765145774541658722594353290694745164913189694785762218575339370800538946514325662656804799046877175035545715523049884960", "56325873113907570153638933263921340484", + "-6425083729275937406599091653015460639540720598883532873434307397902413724861522344067755925372677217710807837532462454857523000567218957596248219345598489043259448527476175490347531536743820263240073378368444306525238540763573242127375494074106069703408040601226397759616303896586807315119850465509951357427995717925546414381799805114914564346278198469314893069557261283904320464697103910891903549583364983649818102351551553278906306516437528280208483451621628029383363320380612211497660637706962191286443635414680648588322673686291228297423696440554643834842700134736628581415664201199761719293758886428880762471240/14081468278476892538409733315980335121" }, + +{ "-25716495567761925495340309269248196976121711927176026606462843116646034561721958499564011513233986043633061335866265799467020807570689498961190839877265773450484494789052182300993137822542881883769593344810286970036960228835955266304979090841345697560418139960733748874044680214388098802745248923989851173047158103142988835055585349795022662576576434371181693607267864646932929998659458265265400181839509356921460222604661909947838434113964465769102604033848276159366897885013231683417270877512514679528402888899725431524867260144325739317224922955028035417867933390409466302057857579158202739536568407090965929352402", "-92089830031261826185903006947297196357", + "25716495567761925495340309269248196976121711927176026606462843116646034561721958499564011513233986043633061335866265799467020807570689498961190839877265773450484494789052182300993137822542881883769593344810286970036960228835955266304979090841345697560418139960733748874044680214388098802745248923989851173047158103142988835055585349795022662576576434371181693607267864646932929998659458265265400181839509356921460222604661909947838434113964465769102604033848276159366897885013231683417270877512514679528402888899725431524867260144325739317224922955028035417867933390409466302057857579158202739536568407090965929352402/92089830031261826185903006947297196357" }, + +{ "6427758281007308443295844679532867042370757542760390680622584758338041709910068192973790897624827722686313216884084305612889554116246627679267186323854642904894988936981064543865794245002470271142875081223308666588659587718561791667575945670118263124267218395749059879636505504607358472659126298770422135028955713148882314050530771750859372048576074912599265823577267962213046012777760882389021047579367276198483178024744924299929585515193595330026399302022065656106472153858484998010254767462854235008343139218888170221421046454280858208068658907389288543063912721882521711363713136166478126504226820360347652405439", "80854661163518168674595213426641201760", + "6427758281007308443295844679532867042370757542760390680622584758338041709910068192973790897624827722686313216884084305612889554116246627679267186323854642904894988936981064543865794245002470271142875081223308666588659587718561791667575945670118263124267218395749059879636505504607358472659126298770422135028955713148882314050530771750859372048576074912599265823577267962213046012777760882389021047579367276198483178024744924299929585515193595330026399302022065656106472153858484998010254767462854235008343139218888170221421046454280858208068658907389288543063912721882521711363713136166478126504226820360347652405439/80854661163518168674595213426641201760" }, + +{ "1960728263483597985471065015024594804771170333646104429205729831998416939777820080209106943861368202560376682136488253096512360698625765514606930980274938979705620987031595592685578710084284618125325617453699875318678007463857705931376750632972266553809944621631324385690517092215690694024807784270742388108802858889381036105223858467345514041786882957807868961085072340965930749117411726729713477739990680381647988935514765113077094375924848051541167125595015542791382355149166582367766443782842193396221676952668624805183924877889696428989259842153378327156342464279071638070457876940165186524833987190050817072048", "91266493124541431873557009470479491083", + "1960728263483597985471065015024594804771170333646104429205729831998416939777820080209106943861368202560376682136488253096512360698625765514606930980274938979705620987031595592685578710084284618125325617453699875318678007463857705931376750632972266553809944621631324385690517092215690694024807784270742388108802858889381036105223858467345514041786882957807868961085072340965930749117411726729713477739990680381647988935514765113077094375924848051541167125595015542791382355149166582367766443782842193396221676952668624805183924877889696428989259842153378327156342464279071638070457876940165186524833987190050817072048/91266493124541431873557009470479491083" }, + +{ "4941680418946960910262990974014623728051861920391294141439502190044830922127013115391726343950340163023958511659132792063033185693862678433421115681422259770928656196358763089894449447854011668445981430826871764812047994423858851467292757304285634515474652989618200442851239459073981986390515468331839802701176644729973346052528164203299481240263263697394061787580128379398464090163611942724580936445878570184925290925246112514015572149640886198984723311273144361235138411362294735799814160816806773736605477503201836095726740734281001021071803299510239436683913500734680524381145064985356627091311888606290704759943", "291575320383555320391938911470370670502", + "1647226806315653636754330324671541242683953973463764713813167396681610307375671038463908781316780054341319503886377597354344395231287559477807038560474086590309552065452921029964816482618003889481993810275623921604015998141286283822430919101428544838491550996539400147617079819691327328796838489443946600900392214909991115350842721401099827080087754565798020595860042793132821363387870647574860312148626190061641763641748704171338524049880295399661574437091048120411712803787431578599938053605602257912201825834400612031908913578093667007023934433170079812227971166911560174793715021661785542363770629535430234919981/97191773461185106797312970490123556834" }, + +{ "-17803449239532304707372697093467431202778585961066204978641168716990033159088600623106396534094218402005803618121159982050197012697237961155375180768349707725936023283589475384693590539312637333226292265409814019687105755522332846972859860649558844229320481883408457674560284773922666633054564243260924189551494368660033292970122831009582038986061326503238023206238467592238752824663935316307653075615249537594229930297642710570473007696494702367783692850946455203144153509057520651038068881755863521371187245025834292163874467913915588768778393773565536027848586260129438664753479013894698439967637389690509120223682", "-10962227285754340409566802000064407225866105372406170304563353147415988225079632767886653994299800743521362563345682593189107807948342418743229049299449088", + "8901724619766152353686348546733715601389292980533102489320584358495016579544300311553198267047109201002901809060579991025098506348618980577687590384174853862968011641794737692346795269656318666613146132704907009843552877761166423486429930324779422114660240941704228837280142386961333316527282121630462094775747184330016646485061415504791019493030663251619011603119233796119376412331967658153826537807624768797114965148821355285236503848247351183891846425473227601572076754528760325519034440877931760685593622512917146081937233956957794384389196886782768013924293130064719332376739506947349219983818694845254560111841/5481113642877170204783401000032203612933052686203085152281676573707994112539816383943326997149900371760681281672841296594553903974171209371614524649724544" }, + +{ "-11349783565099575757929584771389010505157850113880084607145768380886038854233583951229136273631022011781914171912628263930864052254964518914857757025547156428098062812984733912827827545722979442676567330004437902674729872754963478834939047061999292143602525229120558979819117729589695377623970606315287270030693151486803968345724658003068961239204812937084581894755863859944500186226990319892122692007317326534880413455575446314965159569830188583093978564829748603480193166063624130610256395632946002879039047154077629561745862713628266069928068634042545592328263646730943717246953000457159714049930890865576634096206", "-5169948998417532948043886408019867395123131165917923418040862036041756675786217242743410895008311710518018466892169868028617239526646914529999134517417939", + "11349783565099575757929584771389010505157850113880084607145768380886038854233583951229136273631022011781914171912628263930864052254964518914857757025547156428098062812984733912827827545722979442676567330004437902674729872754963478834939047061999292143602525229120558979819117729589695377623970606315287270030693151486803968345724658003068961239204812937084581894755863859944500186226990319892122692007317326534880413455575446314965159569830188583093978564829748603480193166063624130610256395632946002879039047154077629561745862713628266069928068634042545592328263646730943717246953000457159714049930890865576634096206/5169948998417532948043886408019867395123131165917923418040862036041756675786217242743410895008311710518018466892169868028617239526646914529999134517417939" }, + +{ "-4372008041495429462966226028389793326873997497126815043214338280101332483009650104005998792061125254101227371430911497751865710691604158789733634394053254604723940088324934622768312096370232736965692181452463495731681105253628558429524788376108667441329817524961077744083376843098018692898745743361309486938506049017980865957895278210133305721083115513131884239744064081819033733041876411992332060293539102545847193260167588667810376670587099064558298380310132769718526554738650709745767046942440481512965138461694790645096012018276362849398785863823724642554436182185786302301222529261914437437947741031113015699315", "-13213007132248918651858333568248204618745148942720942572088217188768868803339938910599097839075045781852237705726227293430250507070717570662238736211897310", + "874401608299085892593245205677958665374799499425363008642867656020266496601930020801199758412225050820245474286182299550373142138320831757946726878810650920944788017664986924553662419274046547393138436290492699146336221050725711685904957675221733488265963504992215548816675368619603738579749148672261897387701209803596173191579055642026661144216623102626376847948812816363806746608375282398466412058707820509169438652033517733562075334117419812911659676062026553943705310947730141949153409388488096302593027692338958129019202403655272569879757172764744928510887236437157260460244505852382887487589548206222603139863/2642601426449783730371666713649640923749029788544188514417643437753773760667987782119819567815009156370447541145245458686050101414143514132447747242379462" }, + +{ "-24003371850945507239307096734506644624830254935119140199726507920301383328662376914775504920527918338079792692943250446679097229950654636321252144129692109999375967030689211646504258922323499994340282315270808545865248969923421472430657741998787024263629527291510416193284540865950122841477102934165296344839654902079279846705581902668360663987722715177845485423354226653585575109653937253382583158263755381721094429734122004436184054214443676096492583897635497699417294183504529284810360226314491839533303380490277211336049582128602304906849999737224506976061216780230350942535246958957024226614847691329767208211525", "10686139440491678930358521446524488461285005495304677740436234635584738003880529034339295291091217655777627375148264449580064000634364863951333061091724053", + "-1263335360576079328384584038658244453938434470269428431564553048436914912034861942882921311606732544109462773312802655088373538418455507174802744427878532105230314054246800612973908364332815789175804332382674133992907840522285340654245144315725632855980501436395285062804449519260532781130373838640278754991560784319962097195030626456229508630932774483044499232808117192293977637350207223862241218855987125353741812091269579180851792327075982952446978099875552510495647062289712067621597906648131149449121230552119853228213135901505384468781578933538131946108485093696334260133434050471422327716570931122619326747975/562428391604825206860974812974973076909737131331825144233486033451828315993712054438910278478485139777769861849908655241056000033387624418491213741669687" }, + +{ "11114571678097117920369007866358540243142633567044843952020632081573546909920632543585596494530749645890342978505657174505155646987551523455565703297238406590291026899487431109110746657023874064284362499621762851387854720746040865741433394111425240861542892218169985953747711593827913014379823797703717216676877313898809377467394109623799717556800777662963842899812297087284510893865429864819927951428138755600792987191034272014681606301885821862650098620488569288170357746018556395309910262410994899971436293672676949544989196526035130226777567220128838888396668158456237490064462262193759918857287915854681904206680", "4808076329737968688023887165061921594706561818755147855784713748545995818001333418509444774306288638038607173052166709335820929501845348060033808100812677", + "11114571678097117920369007866358540243142633567044843952020632081573546909920632543585596494530749645890342978505657174505155646987551523455565703297238406590291026899487431109110746657023874064284362499621762851387854720746040865741433394111425240861542892218169985953747711593827913014379823797703717216676877313898809377467394109623799717556800777662963842899812297087284510893865429864819927951428138755600792987191034272014681606301885821862650098620488569288170357746018556395309910262410994899971436293672676949544989196526035130226777567220128838888396668158456237490064462262193759918857287915854681904206680/4808076329737968688023887165061921594706561818755147855784713748545995818001333418509444774306288638038607173052166709335820929501845348060033808100812677" }, + +{ "-27971792815424016824370019866875377333122266892537700816201893161065327053508379094007350664178576160161460501442627646041422270472469587140689725524176629653056006769618104516779694726446739085332330345789012312708713495757968594985567285237456431009983022526625885024663335598317191838389804118084831445251467492693688286258834282078888862754754572546522075833632779922232880101875914894393005204887265821991459415144492487189071888581048779385051174007698853920104709378859053075296413813207007405843448595681090932498329066591349910723578718333092115184652723310842559914379989208301125396793101430807658654849482", "3169580893680227534064172567436590084742349042688765883461923377455374714865282199177755353861979892274552092801376364846717140845237173266602633583445110", + "-4661965469237336137395003311145896222187044482089616802700315526844221175584729849001225110696429360026910083573771274340237045078744931190114954254029438275509334461603017419463282454407789847555388390964835385451452249292994765830927880872909405168330503754437647504110555933052865306398300686347471907541911248782281381043139047013148143792459095424420345972272129987038813350312652482398834200814544303665243235857415414531511981430174796564175195667949808986684118229809842179216068968867834567640574765946848488749721511098558318453929786388848685864108787218473759985729998201383520899465516905134609775808247/528263482280037922344028761239431680790391507114794313910320562909229119144213699862959225643663315379092015466896060807786190140872862211100438930574185" }, + +#if 0 // more than two arguments +{ "-138888658164471549506154385143989713534453638138516110941977029 48484067562152384719540184707188444570280914254129306788137384972303743285284814 56428088099244342456240635263153370817851703737803685168591843059886944388583310 6984617762898435035101945891920384937438416626357047934508608980105797822504000 90193136183227859939744547239819443586783276313678017953708293432043879247302040 70539472782976230144489157899475475029273447055080677052149474853222128626227832 2525164589393997980217929709704832829968554364529060039097810436136432713906553063644429644328565051224269893261942396763235990073001625976866246420775436", "15614337547041181126817477188043219628044963126229393225781917631975649438502836750353253851523795212263078850399716875892512719059737913422781999218667136371648316387382440793865460028660248325297931269646982047533754121791358966254514009830876592200454797694143082163294323565673200905929297174223061890100210054105027025488322289599106119653451218493916291922340123640475500240519924011764050880374885136181582395113140580448936759383024305870622004464940344826337458060607492042593813585998516868215921180540240201095202617277388950504036371411600204964284568597705251929695275183521036281637399204541958859605054", + "-138888658164471549506154385143989713534453638138516110941977029/4793535847709521198063287553243915170068914691727215964454867625024011698922303669226389748584276840530192157568469968220857898703102351955898913589325705637953049380748829567692600765708909637920797057370082064005557328769108356548100875674196976079597658854339583183901899349355521527519781721778545444496852540362424465770767219571362842157786846795990148969989617793004579188905882473140017509154008696803103206996067638134383708975696867028865870695941933200225325283190379262695816923376790224594063264297952504481719779782130509306530621779762254864669078635401870023086312919956154224782043667754741333688780367667466505233610011253346902821033707597517691608103391952937194719540981992469020284583499872663129517095879706480339710037976698298522952071766717472040399518290905103777436461474880898550115925718887748413534479076504168236430697214654069473800915087572730747027455509241250627470590715812698745630545585772046458363388764449879417348554556621640336029897762172500880501074103433267444717053504878282494505367980026597725927414511391047010801407870379019921551218005714825277162504166028680939100225793768617321830389705750902850499916610355200000" }, + +{ "2902267908619179684129536324641634394442732593027015198805855082 4748067699021154152763168285921806700655154833226062437593302484475663167752990 92172802787151156076284963978247829387076983213530315481815585776147505007251090 15808981285029107672090190966349736198141855760941720122983980047623201110025085 60559202289239963744584432021634662330089323842876293477363484160210450706125345 20641717016962556495214267565148984505293698026059157698737040675346468206231142 142380249473014630955299439077662853963947100833592874440361316474000948841420058017600161066408668117933232436922811486348705081331372574460204309908598", "22418721268614574393232189860262616514600143215945007038687873335656746730488694050883006164427390756358558140145027011322151188565843290717535647848841274550496431839061217253488169143292339455650565906288959125935798633464526818546688779845699340483771625364583343140648892889571715648295855169294054985996834093294240640072029711789359793649773566295329912082241637482772608479106201840565936084243727069954911883243252762742415647868355726139789907900798435783365130277592703989608678774745914668128791639635886550753850811717805962562157686110637810320436812644047534536168343578232389700410352900247092236175044", + "1451133954309589842064768162320817197221366296513507599402927541/13803211377640454778526029288269623376813125655593684775595099045285713415153039020789267800416616529908688645478733023490751981264976732618374046330204398361829051480928696426688037404239513603403603849882719851670264413777889524531938606364925013854252374108222701436535488401321603495905123597139234414735397259257280679663147039651553472142280954446675036289021783142392760217244908768132158498744301278889276778209560846418263599491357632762902447742083022806085077053406738681250354036208472026046315736408632370478801849290705001622808552373129971427533249307210975612625050706661691322027927380443494854794852235813844542319971019369687589916047377092369702778251658652143114091304960406840026816351348391618676357634544120732441610431417230403811846208113160343697557236265319994702483700922393762500190362776377442551539417224595247790865885105594005740401824824367904020732469833438717527758468635665777261969819260766044978137909489986407113029460354144391595512642835261443393260585888868936164331461486646676578398836326366036777321522851855085808626766493197635871100152761464712744017549919220291986785134521319127277292845352756807452050073157340000" }, + +{ "7798204144688205291220879078360728451593323170355809361079096742 35808393784851478122520372074317359817820799318259895240196875729073154197251420 58532175726063855694248618287185551673975962776708803423334853085996022345828434 97834368697888769536063057370864051207348099191057106781292664602519775900739777 92489021460656714290092899983209031746574776013841975324837145038810562509209529 71083733375588666647468985607775761710974844539643116636307037921671845148256816 6123989271760127932230015643359630675168106436173654465119508990415235040641894537960236511442249258231302028977221206744158863083898145166446430168108", "-27418900206398855942064397259705713102524342707255992250395147550519659429645343464288092288218160406382406024735131578979728501208163782063519839258876833755387025755815673514708453862847139552613587001235204464673999898312854941659541050445981594990466469147364579547089805525464252876345032296745312923488525701877655352034887018931755379078328147999631937419977103372927428613463482328465834563846802083044643719319690088670748858904291298575733560600669924511028715689681303059001186388754140003746463568171428267337107394361025465082282061651196456268663181772211292647101192148287507051053367729008997838464209", + "-3899102072344102645610439539180364225796661585177904680539548371/113184205287561573324139833190653102440730360395399197973956984769580868365256138025034414373155098575475566747215877030265786675432252675717351889433714136838615056208470421665419618669892136317438270826178251174708190860235979949204785938786562420189510825909814566675745650194525647207897976611434325225523578368855952217879373499055292850828774005130267218801086474623429504045290678320168493275019256514768273116059350700654655821674309331585233552793659038912697151359657915391954687630783641745610431060563252789714638916120291482852533638921356624929690158752601417722733222880768367060672103351737811624242610815140332559619520810810999145535251960674284283045907801934328911198563750515779896457101601178888594882087326241517566336011980952110586199881600553269825310575512911473547251704677890770772166895623118832621335417348044312911888377718725944255218219811801447500167145561774582342171995333086224230231746597452848775656030037837271428187450747141983599129861631612369300880722326218963779650411119279310045263996988089484063433088077868691314162108392639864773907107325220582413508233901954483499166402135445110435112499264825479433389003494762240" }, + +{ "6291885367078853457481986049409245691302078375827782321496819120 20959289231548357352292073342856567687394126070322865796282035211176720583560298 24366038587110130209541647226271577368736240640393242419005751016119649778306566 40118119174220166901790237425673316895032570534639145502274313654443256239236466 73598137358602854818844747625643480865061277528564461120022408463105339470504117 36695182446520138181079917512512743290981469731336486456411609014364293489978544 8671667981598505073194269824535189054936442262459158402875147736469644925300845122881093216273840895555488593258562684601176239455526568314028830532770", "15920064019095473156324398162334173238735268739049399738654357508344572552411935473846021991360836375685872129737682603096450566258725052013769725919038955505690389573813769125933987978360857342250911865713011888064725725934341157729878064563080803955584985269499994186472079783942404183377695242296289152788154908185130552013951432753148997632323578507137074131845177376689609114975253308906745794984371839952312988353950198030866538756253618535421214253194954603293145507537939731320546686208032528588232652963255550963088571344119439249328480867640436815434047309164687808223851012490130534705427647158409623238123", + "1439421788255379275215959765325419043929720157723371200401/1747562187028503746686299553853635643553063923188506902759251937250022196751705340155682655202720363192751787186892107863159676381018035068965958466119538181810433273947829904580526582292369320932134048728374142501965682147541817431447933591106030690334465450755701191781243754499216697336293783127396687916725975251100500896467549458036395977769801208905203001097425041200299917628353220804629035768571072498715030261324138691471497255335498185741379289492513543474304524261634247519034231348033379344777678679950561777846684978640375273167561174451700942154388980887510088060818147834369595669846115248027925007288445161871535514130090907585140894883683709507099726386549038354860875469377442908932714711235823032704493155679240378374325069782368108779247450762222838197717507164088182062062215767468125843278459189085290703729281279344184417197883359351058003644499215541300350121854220342250451978930421772367851329849662028719768708399155817754711362398236471946313773603716759409265530444582884661320404389499624411965234669344882203618613097197387901166904575791500958722726774956950592290330175936039556139052663816485140080963740296685158607671768592" }, + +{ "7377598052472799909620353419322603137723415431070641423056433630 50990728761110292768803869421408199244526424730838143228662194914314857136430737 89434155113971221138805303763480423496687322824531744020762041598590716339098287 91343386111124700155689622654961840380754244946720984970313893805578518003516073 5641075230099727784981579696383316732450130418277879081291954534985607255267932 91040802121912074401640073226003257602385910518707524375098380810792151468159323 59272268188012925764499414539835790113036863511169317924034366016920114706179376837448098952655862721652129333873020625135398431500899131874782270590048", "26690053756452308398721390096804652429111408747235998849320348549870126230712525274708597346508961935323823048352116439255386668122483555236157562141222434006899926132549352821247340442387991613448730451171206857242290791156220288682675982609964518905569737166444127835826079348146626921864776959482079234994631361894786436656768739968380067890165160954836874044821979903056957225885565092422439358816023307475581832942250031121721325840673134241504501661692722633100336840768527354183989544434614842654682324213774503456414914613412547380720171088896588158750436205804689590730033393056191028424154915201435563063992", + "3688799026236399954810176709661301568861707715535320711528216815/169215718032454146095901737002485678790901914179482864125777331106759302744215797822810809511498045518338288799757661725047129775976254373463314416017128993811694804386237923340900604770406784566473173755998386770282409830097844352035251738093305402541509197084964701114515390028814839744480965823142680384744649624767291550851759670297818996073873968006960956353033659153219390871979066743795530136868490210455800714335529013059123604101460242870160400211866883478263106349349114199154533363251799944090298252763172390952446660627602934622584400932001701907172000401485323481964448487312714644861543740014645407417493588261100128985848137181719614326345024112347151970444057551896842474702539258687521054961314443551837168457190568932765925484427579811571491887599619302241390226818415165012748654917331557679228501007751078584244340346651276906088856205294333241792044902850102153793417101337667969641035858108457362954650972654353600494166650067557014544136240962457086782865870886529792004619668808741311540795514394731398977642092124679638585188974746423756335151669217754388004341907440529525288302872368689364872785975840444000802518095138062596107983803117056" }, + +{ "-239344771695510351349291992975349015183687755312261264640655565 59880027487583466136533364102518649070390160795136023810470091681171428955831193 48344457085007359228086666145324485903333773379391455489556219681156342646858065 96824393663737121700189215323825147927318524415097221824671795011444303522438090 73240728471954064253765051525185557601431281145369716902120469411886093226662465 53476482728312567840603110355495270554470432250981685279567813448298175801364992 2468459436652089730331798017030410049989399340882712030505584719342958436741536069714790640546086933185494149096286590992747248311590137695839482679011866", "-20583944357058654336975302336113341974001469085102805363209530168831840401111182124827636905521584509677325966689931599005216123375088335255672290604710305325984961984791919524676460851699284525672773368217606895110240237523696098521003978238685169880199868729577660354717875890521074505342309726366304528678619465048659607726264456481345739318939431629704180230985397408136331466856633265343276511285483458860216756106887559724757372775728879136089013590836231272961497930729470443491032308329051560641396901204040829291495325588896591482909336032903587307512310970849256645908744180630660878534263566681640143534823", + "15956318113034023423286132865023267678912517020817417642710371/3718709813392127924163278362562751486187605430152002432053108623099406465632705761508167478249438322470295467114170871555665890539409511492475240415534629792791729596612426725326976353265532166735941330128195885206087665506220364347120981130748862937276841801804372097254983242962029582754709606117339082763083905960784323141929645331591164015455383939302728076410053178677168172481507115685831178503426055335630689722163467637005123748113214310366231893390818795405612007113310547901224920768646006621130651182788173442625298859454337696280614462941186626306295514630883052819172301830539345633711941340491653447613466053205836875456839023743314390098829184111583809697328393569588632000669468187410368485286035179259523632217543401146996259011916302393091677624838641658623073752023082344005134299104409908004250830639232078441523519412192782367689826532215394196055149255026188549091956300108740792221660678858924234682223183500313556198187095251404633698868186071148295957994257417049500872570631774233307260384902571112475241073598945295745287525486108978093728296107260155093397986671349139935376427469718767763295900745932105722655724205000829205748307261900800" }, +#endif + +}; diff --git a/tests/exam_I_floor.cc b/tests/exam_I_floor.cc new file mode 100644 index 0000000..b2be038 --- /dev/null +++ b/tests/exam_I_floor.cc @@ -0,0 +1,295 @@ +#include "exam.h" +#include +#include + +static floor_test integer_floor_tests[] = { + +{ "7853255233330224291", "-3336928547114505419", + "-3", "-2157530408013291966" }, + +{ "14068934522023857270", "16292006600125740074", + "0", "14068934522023857270" }, + +{ "10985143198741137410", "2820546847025452162", + "3", "2523502657664780924" }, + +{ "-8108344024060626734", "17657489924906565585", + "-1", "9549145900845938851" }, + +{ "9793321542618752251", "18086526939764980195", + "0", "9793321542618752251" }, + +{ "-17146297557940039430", "12031974228591547856", + "-2", "6917650899243056282" }, + +{ "-11002425733929018635", "317353195315898710776749437474283191162", + "-1", "317353195315898710765747011740354172527" }, + +{ "-7045772845268193739", "-89864936462331315327547597221973588375", + "0", "-7045772845268193739" }, + +{ "-3519209948682231610", "336646025916394184314065151550367317320", + "-1", "336646025916394184310545941601685085710" }, + +{ "-14043580588957562420", "-222396907959379818229719625081455476397", + "0", "-14043580588957562420" }, + +{ "-9551193686327136711", "75278849342865310446781730521816023755", + "-1", "75278849342865310437230536835488887044" }, + +{ "-5159693807678286583", "-271047212583781769863421872046042817014", + "0", "-5159693807678286583" }, + +{ "-468628810409465000", "4096333242794181573565417750313678008664626221486481835906739336082806890901464399325558358976385254948318232837795406709018062193288308568894691407903633", + "-1", "4096333242794181573565417750313678008664626221486481835906739336082806890901464399325558358976385254948318232837795406709018062193288308100265880998438633" }, + +{ "-5244261521146873643", "4921965954460062114436531997676458648483262898583452823054595308486273272424691697564822554202559195140246785942292198280651275061385828405859241079703409", + "-1", "4921965954460062114436531997676458648483262898583452823054595308486273272424691697564822554202559195140246785942292198280651275061385823161597719932829766" }, + +{ "-7155077620310044967", "8812163272024170253854686552273644496512722723120222844613502711675792665532423218585794856067792762737333036865054171911349107383532358686613366666267909", + "-1", "8812163272024170253854686552273644496512722723120222844613502711675792665532423218585794856067792762737333036865054171911349107383532351531535746356222942" }, + +{ "-6816314458740361202", "12075686527410596248188273566406493470578404199548730085391183041200273406509336777783445118538744079686672261898288597639090345296674064493442338947240247", + "-1", "12075686527410596248188273566406493470578404199548730085391183041200273406509336777783445118538744079686672261898288597639090345296674057677127880206879045" }, + +{ "-1890766085089344496", "-7408951123352997019624764400646833541081866912262454311449242781355699966135127365870537542305320515188627454777019144990896651509964466134772403923321917", + "0", "-1890766085089344496" }, + +{ "-17760474272160473768", "10671898954663586353020741847122236830297651230263271051052178674502913972809415507874936117140992859978582852208528956402833042707438860216609301338079639", + "-1", "10671898954663586353020741847122236830297651230263271051052178674502913972809415507874936117140992859978582852208528956402833042707438842456135029177605871" }, + +{ "17203040353218460773", "-2087162439393804055245476778327445230668947133920484097696589818636894139336038424853265430700117127209095408439503149361955520500062568298413951113007815520417010757436097548975086796164496676384718866185751276003374984886645837833063272909444571294955778352876647505220277070946109654595325494251711661808952794932834009121950804034627054856954463330684354292113876259596011570415522831755074832239680022834732540878425796300024337145992774113324576942861121693541507092307262607720008434123040550199401165667835993232451530119579950363100932584067714571588474895040209606410481479858029354372704983248137195749442", + "-1", "-2087162439393804055245476778327445230668947133920484097696589818636894139336038424853265430700117127209095408439503149361955520500062568298413951113007815520417010757436097548975086796164496676384718866185751276003374984886645837833063272909444571294955778352876647505220277070946109654595325494251711661808952794932834009121950804034627054856954463330684354292113876259596011570415522831755074832239680022834732540878425796300024337145992774113324576942861121693541507092307262607720008434123040550199401165667835993232451530119579950363100932584067714571588474895040209606410481479858029354372687780207783977288669" }, + +{ "-669078238914427842", "-2079683283534812796000190145696654156804430677578086735229530182730363039425073862859919937645919418081821481495275802097707156965850792454067873053943961704938117974314269568411834037549827330778321735965757574814268024643310969429104824266062514450939201453648232801402417276979456869834703061150723202264463831469016146310260625377771326468627250569024458585844135123967133684658903385261562998370487428947011971199332502829621504477139578507890165895257527873153869666215808793006714467381179632834850697420959155528830942491523671012905291756947015477293335637719271764878661266856465788562934083754663149622043", + "0", "-669078238914427842" }, + +{ "7327608361251253460", "-11696871058150243071087622230096689496181624466205249401376348902965608647385664229774648233384515557654898456058685820740766304363182039373157014626506361274439760335671626498691756724181737933201816787306863365879304649516313681157144055793349950077334014446025781487249267998958541998722387302987853596488202173446477234627919885268339967510098356435511938337505060706688248914394292741973765745281640737883810857064447143652281758869836897346742791897670275478332406904414773228555812810686551346417028168391700814494167715137071887755902595471083839770070956620494992791342919563605887139693691074220696797086954", + "-1", "-11696871058150243071087622230096689496181624466205249401376348902965608647385664229774648233384515557654898456058685820740766304363182039373157014626506361274439760335671626498691756724181737933201816787306863365879304649516313681157144055793349950077334014446025781487249267998958541998722387302987853596488202173446477234627919885268339967510098356435511938337505060706688248914394292741973765745281640737883810857064447143652281758869836897346742791897670275478332406904414773228555812810686551346417028168391700814494167715137071887755902595471083839770070956620494992791342919563605887139693683746612335545833494" }, + +{ "294675307927425004", "-9548883545732446060252072829565833006884749934819836721462955213854827688043000170303649263042149519854567992890424662453846646328000352698376041008580371118805742958892669824820331301849741711055204656684075622499980143446475914450482604391515448002257899292716976191315018524528823574850034894770209999447615978958086058881855069519056370913875205852377738400734853568252684386414540818555760214483168738870291995504569592275824832746669965860852593991220739290892286776371571179317949624919667076576237866033103387061005489130212740740367035039239029315995502459013799346342754507246725497131746887762156527202924", + "-1", "-9548883545732446060252072829565833006884749934819836721462955213854827688043000170303649263042149519854567992890424662453846646328000352698376041008580371118805742958892669824820331301849741711055204656684075622499980143446475914450482604391515448002257899292716976191315018524528823574850034894770209999447615978958086058881855069519056370913875205852377738400734853568252684386414540818555760214483168738870291995504569592275824832746669965860852593991220739290892286776371571179317949624919667076576237866033103387061005489130212740740367035039239029315995502459013799346342754507246725497131746593086848599777920" }, + +{ "14347605674351973575", "16781108313723465798753322947549009969874803839178924211234447140560213638432451682705091051257464849827979202356053729300113370530117630421654608371240669238603643549128642643200948947465613904905607632005913664436128507306181734648889038561843797684348733053132088104433891457988693229945931772136047702319895617567109469705064237812979865949533824478284021673220084274688077361876364538071423609125747407610677136416454538389383594373243559248761308999294417964846813960148782443892858983199711111035244418968070018974928177662516580063782128203214203321005133744081558995859628472663680467632605080081460859254457", + "0", "14347605674351973575" }, + +{ "-13687180458303546035", "-19965807258690898827399047857329749541944041888361526571512375013574840494217451526698619297248029675659091093507275385543103914023886879938416253663550378748995953654394575052030527774451712268159052917447058332864628753215292671454945836228787137495936035900814206996568155366945096185932229795907560606361081170245972586794828085080152240904698184990372898689089164281206741448028676272453255619644103230837682506759429084083781590844603079867247577101977877828608823440256009103689824572652465343135798570848914557962085239341382269526989381779235955669274286569338275810475113610787290242075588029043316765795281", + "0", "-13687180458303546035" }, + +{ "-18925243707105550517292233464727657082", "9190307209239173280", + "-2059261271274988371", "2728041824926269798" }, + +{ "-2268729715267556753620172461333386061", "2091801429708129323", + "-1084581778674907194", "1902605633041663601" }, + +{ "240105871177433673480858499581307555362", "-18137436669813972164", + "-13238136984210147236", "-7622864679137983342" }, + +{ "-262280851402380072992262860428676408462", "-16900353177245877861", + "15519252683754978805", "-1413263307002672357" }, + +{ "232088877459084367318095567773397104766", "6879279671528853911", + "33737380734733937751", "5401711328350210605" }, + +{ "28127709642032836544705999676759725409", "10932535648386303235", + "2572844081801336427", "10537089091686284064" }, + +{ "-306937202176830380291551701368328539229", "-296436198830834971825518518346845101512", + "1", "-10501003345995408466033183021483437717" }, + +{ "53182351345555180643155906117731554036", "-239211638592486301383761475381736024507", + "-1", "-186029287246931120740605569264004470471" }, + +{ "280879521805922529084106054377533635149", "86259942955448859132329436894499980462", + "3", "22099692939575951687117743694033693763" }, + +{ "270479016313808755540727122565065208981", "324912300098276215771804552548480817149", + "0", "270479016313808755540727122565065208981" }, + +{ "-36931767825051824504116995033958612864", "319307981922121038618879980001580483695", + "-1", "282376214097069214114762984967621870831" }, + +{ "107405040163562716679444439233633957914", "-141652913538112981614728925754765362880", + "-1", "-34247873374550264935284486521131404966" }, + +{ "184790583924323275311064238756309559899", "9405763068924930772523308542613843828189472529194204592633223103364008985533829727911596099340788835060163612329614413033927995456162272921833539208882402", + "0", "184790583924323275311064238756309559899" }, + +{ "-232146313651929815140292892576650425884", "127874042542498530491272428412953321188339770863893691736473766303033699167382382296818126363236257463426694846772750451609560841554300961480864245159756", + "-1", "127874042542498530491272428412953321188339770863893691736473766303033699167382382296818126363236257463426694846772518305295908911739160668588287594733872" }, + +{ "8728026917336931021644334642968359261", "-4025737651718879467086249421940400743845718511565541383201031450532496911741243591880148294568060736532264934821412351158153056198557273134546519285439196", + "-1", "-4025737651718879467086249421940400743845718511565541383201031450532496911741243591880148294568060736532264934821412342430126138861626251490211876317079935" }, + +{ "-21247806463473594155821742168531145877", "9874623814693251335287095436063900170315895560443374584548447111313954604343515085076726174459237734570523327188441412904116251434030306488421699399082287", + "-1", "9874623814693251335287095436063900170315895560443374584548447111313954604343515085076726174459237734570523327188441391656309787960436150666679530867936410" }, + +{ "286071012976663674972497644839812778135", "8117963470049102990205107814791130105126121536354646949522748212681559213640860255350655907507344188574393108661850973221437234442503731759547377868482253", + "0", "286071012976663674972497644839812778135" }, + +{ "-31984072490103846239901254171623218449", "5692584577100138206704178766874348327662006017031045734962382737701553237360572309466111381682998567474445884555969155997528896962520199289069413649945515", + "-1", "5692584577100138206704178766874348327662006017031045734962382737701553237360572309466111381682998567474445884555969124013456406858673959387815242026727066" }, + +{ "-118786321298036108045826901623494422286", "-13104687393529855246189161514016061367829206536234756076440701117699438900634808212710497707688898041370523685367660273492555927331371333817584456923437812254937564791326005224466260676246116823279440552837098144298072108885163702544652442198253976130758036230979750526665070549806140578651660117367824058664768255971820333797528263566114021182845197585116811208610765478558726491630221448907739229750716647693886681440731920621825762708622208585945445501310666367635378515829380161368994361558247741326227866296163878689192696502960274515396418704173356117106149549811507516298161494760216869495774889685228097554343", + "0", "-118786321298036108045826901623494422286" }, + +{ "-243504960196882294351576664380857968998", "-21587937181410571895883243216668490389074705797891859245233974857468088393972175783210897703383951091997858590608339069503309630378648345491373074180865032523580053667127292664354305946146706860083207200717386662398495588729927890691458790805600368902559075452315483293077820819619965677979632040202844747133012382862591603017396270452230496812292060122531819615885125296991557805051862986461441377986436031061301043809602913037623299360710776463563079053501286633046825608308134411478010516309133407298319800662521169341026639016773610132691088293480775753098006068864600975258749129292334356727402877150032641596013", + "0", "-243504960196882294351576664380857968998" }, + +{ "-232153120215337418381368832017470265942", "30369869998519160635038439385899036531726274899243107662193573776561025086030508184579231487739439638990032661366370630132003795988534362627493292132764049369361254377811101088096885616264297545296183017838644655031800075015262568240918564555865889092855166242732548296118581123607728694721796055009838837557999873738362196508994398492388283391000153200151108985088421583241872508945550713986000643154770628316896294096213588875028875159647959209523043158262383137987983806573391208706198841017176042216759223869369001945418516819972673432636326816040752486579776281338052626173120273068890045743383055115108151149136", + "-1", "30369869998519160635038439385899036531726274899243107662193573776561025086030508184579231487739439638990032661366370630132003795988534362627493292132764049369361254377811101088096885616264297545296183017838644655031800075015262568240918564555865889092855166242732548296118581123607728694721796055009838837557999873738362196508994398492388283391000153200151108985088421583241872508945550713986000643154770628316896294096213588875028875159647959209523043158262383137987983806573391208706198841017176042216759223869369001945418516819972673432636326816040752486579776281338052626172888119948674708325001686283090680883194" }, + +{ "-259060284965774946595436776839639567158", "-21169437398760148980356190208468018621145492999838564155598571671707045137252408058263155870788514173361612648418947991691931017566701206182096411121805142388703524692384188551391839307655250861401059757668540803453257330609840260191124331324376455691656017965418225557221321063048013134701879342357330536176553693912196231407222911508076200690973402778332647229863066211873019193191946948707769594605725700542299351271155436324879464212647734978854222464094486372144771948169422844206687239103281296767882465060755610256361348437002775612357787333990788742488962974294617778863800504758143312112916148210635178700875", + "0", "-259060284965774946595436776839639567158" }, + +{ "-306407220440527520801126245152934343544", "23776904469041910002999929986640006577749806048379780143306978176280330224333859620859305982085584460504452577150094943864349273103240498588108336792264540481132832425653265046674475461727185564436156797869482735166850827691928781085870354146365177855543550807539877079785312955597311473866546268560309551339704009052837019611095284429480282839060448969927393502922337023493529232757886223011597039473438267362519775173848264262428693937605086393282678388857244739695710639089112115821491015511241179389623611704128686301802869094211111183507607222840602723592206395532989319304742353354849715544201896997806941793031", + "-1", "23776904469041910002999929986640006577749806048379780143306978176280330224333859620859305982085584460504452577150094943864349273103240498588108336792264540481132832425653265046674475461727185564436156797869482735166850827691928781085870354146365177855543550807539877079785312955597311473866546268560309551339704009052837019611095284429480282839060448969927393502922337023493529232757886223011597039473438267362519775173848264262428693937605086393282678388857244739695710639089112115821491015511241179389623611704128686301802869094211111183507607222840602723592206395532989319304435946134409188023400770752654007449487" }, + +{ "-195344089877883615473604540022799066156", "3662747206396136814780716441352319011395583880744440623779519524132715621398922492090110915810914165138435343905061143614931233310311653264955206314385113727380922840781471233570237875610273247058183529977038444774890036917021403875269188605058323112809901006876685005810599540694986877767813641408707144817551209014119080068666341132956917595575721029282915413432788003670940873484464479035116187361986468817764174983360339341760904395062935668506379254915132158079325547293981795720009601997338615068852024788929328937759791477545407878160402653256560646902444406842976796122784294159073232675729939439754133572694", + "-1", "3662747206396136814780716441352319011395583880744440623779519524132715621398922492090110915810914165138435343905061143614931233310311653264955206314385113727380922840781471233570237875610273247058183529977038444774890036917021403875269188605058323112809901006876685005810599540694986877767813641408707144817551209014119080068666341132956917595575721029282915413432788003670940873484464479035116187361986468817764174983360339341760904395062935668506379254915132158079325547293981795720009601997338615068852024788929328937759791477545407878160402653256560646902444406842976796122588950069195349060256334899731334506538" }, + +{ "9264891165355739565190184416501921531110089392234481682785663537978152834210043205322426048946857682928713233093454298987718151514375312698287977140085629", "7037874176512351849", + "1316433191754927814343121270936699199595699278862016004420926865721433832616431797693201713416985056700387482358940219476958754936526117", "3725966351458345296" }, + +{ "4200307032774171266112621290628586259036811354993551074625290503853725932886889027855146647188583607214617803535833936888841730747156500044307235280341823", "1284895891758199540", + "3268986273297707492966046995014614916998242647231210827092764188090140439361457237468815188241626314878458369000334553644889671709204514", "686385384999618263" }, + +{ "4633581426210593840116821588308941075113609939505374670564216205139790589811590001728944069668539972864711443927654873778749890460797761818777105143436310", "-2962967916964005701", + "-1563831116658993795279542101101791208522139405163357327177345954575873595639420625598557391282445499923781922172975036467881769387028636", "-2305528351410817526" }, + +{ "12717552468498637611743035736272812618998169576927971614333302239794587794960622996075191568720328790968571121428403438724885597787608886055291630047062012", "13314634913503466421", + "955155928128432692468469826248574845938797371431354312846155816839032798664341688948121282840353830287784283921940330056923616110441287", "3054936783550538185" }, + +{ "12062294501874959722722826646961478850437392058690935960962546316456440331759806886386062852332964852589981740852222339370133938328830299239599161668985128", "-16763340409247566945", + "-719563894032763567901416565485723597235798340734444183600832520303761799320002945942723929422229544393458648487318438477478730610009081", "-8784252901936442417" }, + +{ "3044847544275515285523698330617680562098304367055502952571345800359603621492376638228899902071703358030930686556600015395721763778348780143354036450288026", "-346996692199522190", + "-8774860431593785670059820118794469144363980632658525112469174051232043754755411530275560319174086707639904288765947602493995823751245651", "-238735003065207664" }, + +{ "2509912747961300370421908848463238376627618739583712646450568707494390365647434163992939257405972498499963653610934135188560348612028561201284997136414467", "-103539220471632131715513528655357150478", + "-24241178719797015812049763065806339919024561304709065585003455368093218973185992185403749066840410575011438662859226", "-96472873114015658715754743886276195561" }, + +{ "903584156603757584665316743639288345339689627067279191353819345586609786559389840933430566508676924801215959188934167984436460131912383813696092800782502", "331768089796013775863175470747253254043", + "2723541486944457282998823558887230609702011905460231484608706829329099534108144630923237396663979818212898288888162", "206235332161320659528701690369799443536" }, + +{ "5673315779132616764913839385550510388979090539569302085655840858178135330568442902409259209441411672724870197775936862625748838206738247202566588717953664", "174314453261637397091517016624017866910", + "32546445076572334426551736182476341541840123356058415149120265601377736759669652080905093959104527787429999911903291", "116692109360780668718335531020688952854" }, + +{ "-1042174796681883628708939541235268651605049912220225874766096393016094308719465113556241387514699104237113811358810257758037463299809921161083533137718034", "-222161050831883826404696847740663687900", + "4691077903977550484144586938760520043889189188344556635834217114054282381408390083982959968194813858480017307031811", "-99596643070173880773679158795261931134" }, + +{ "514620852714641065399283188571474686623886013323210978774935263256584816823822985571618774823719005380283570413767760460152207111047429811764462688164598", "-249379962778237023348159084806351533829", + "-2063601449697349844851896329155481297775287042332288194884672211603708613220802144442049441368964502372230090742486", "-95322380544583572818596570976868394296" }, + +{ "4269600385716644031357008587416832262633392539755787971157199376810061034292825362806383550016756143465036715717235613514913396047178769910869994174370663", "285417980748490192096950554131180300340", + "14959114960171371128118740711875740516756226597819143207915053559296218628291049058344647983358827408473567791787490", "241314195989544958480263376470519624063" }, + +{ "6257762944066060502889009610562625466881502649685643619949901701091938859953222566838296129679249506961399045004819501125771060525963805468605899184284857", "2403901388951678895074087838271029994884292204266026258064846860089259517515609086601789420041871201768080771502802345608184755582676267305500365461987443", + "2", "1449960166162702712740833934020565477112918241153591103820207980913419824922004393634717289595507103425237501999214809909401549360611270857605168260309971" }, + +{ "-11993484600336960787296361130458404039545119394875472848786275539588308627572632551925095053909141197737731742215007587172062102742960429155637516154567478", "-10601606227266649325153572936490025724316912773656025997862708934485961793376598665748396482615905529759961488391911046336857148489489874009257983913322770", + "1", "-1391878373070311462142788193968378315228206621219446850923566605102346834196033886176698571293235667977770253823096540835204954253470555146379532241244708" }, + +{ "-8099353584218727402496117482244315513694479151831901237119469501251316930293170263154474101121202090352876083340578448720444998702069748972927117400667238", "3544314361305784888681580682051379178614889611356920001389193108853540699763802421224233206957629368752496825814976307915371579698349690086107445288844845", + "-3", "2533589499698627263548624563909822022150189682238858767048109825309305168998237000518225519751686015904614394104350475025669740392979321285395218465867297" }, + +{ "-2978635751180326260478380464684854159186938695694356726729544155114559498149136630265180287452727795680214540092030170434165319182046797389540988376220992", "-11044560433803724847345327269572156674554851849210901400046696801586678634230888624140822828361962132102290537138655249676050009778590939633587416463610415", + "0", "-2978635751180326260478380464684854159186938695694356726729544155114559498149136630265180287452727795680214540092030170434165319182046797389540988376220992" }, + +{ "13340538348613289212198643243040710073441733600226599862111857175429956610033827913042723029883753278922272401272143183977342753296395660841047710386806625", "-12505012580354283714273335370179473407347376833608196161777727706326565713505585671787333065372262611606233460666323939469037058474587043990269917174242835", + "-2", "-11669486812095278216348027497318236741253020066989792461443598237223174816977343430531943100860771944290194520060504694960731363652778427139492123961679045" }, + +{ "-3452499360915990528305851079744650498637858290301947784400848134276013289408593218875969649149167701046100505360083493320272180164238716241369492874982856", "-2841735595132421145030480470066423226109731223189024018875906078709951146850527470934664784555907173906888591079310297248898808599295604861461544021697908", + "1", "-610763765783569383275370609678227272528127067112923765524942055566062142558065747941304864593260527139211914280773196071373371564943111379907948853284948" }, + +{ "-12837726014506093148099404481188410844577204272048603185395045047349565142592994407238657335674129551317417810603584063833795494760777857363295221929632592", "-5400672038070763758928059302309515863608512780764658336296609520612929827128710430832496604060142364086061442480255889774184624927820479974807630834638627053061502551989845184646873008822134065011205730341955561862333543891572685472831543459711809182159609688999832404181689665081467086838440500602969410420032314939424736094367166550148605570451238900811316075091818613634658092771400323953464835124475741159313252328998401218032670762735091435255199537815920258090766640501899817468173756745613666544200642455036991967916355826412137450931256645775349763991939102903236911444655964118925598580974976427195132959063", + "0", "-12837726014506093148099404481188410844577204272048603185395045047349565142592994407238657335674129551317417810603584063833795494760777857363295221929632592" }, + +{ "6578123342051874578301723989032639872736755816906003001838468752363433436477439123182015773040480790196872643618542950300401093404997067180920740266777136", "30227534847135453106177887048045830910966009330493682541426640262878585964314188306388368740002450969080153107270718818194095421631888634061517731024627240634873991685067246458822125591350775226166707968203074411304172314390138208453777131423508042090910198631120304798774511984974823253005683386272038346156403540545900138637964682890471751795844957640450350739073841005154467987598913264762974403365908691068629911370262907886883158252280853615622312950774196097179304856495254526220900137020823369927850276669023897589972466867500466273084668060310345544901231841857904496215091732346299276586847479136514947400671", + "0", "6578123342051874578301723989032639872736755816906003001838468752363433436477439123182015773040480790196872643618542950300401093404997067180920740266777136" }, + +{ "12403944923950846249231475663107427245396603223802100275104415443763524399953865335344297718622152249002880852792246968794311649331174399649925724682365691", "-12888526328266820415927145054786787145889555649382608442248161845973745960691528655550360088202102799744537495406020539568745771467756467183613368156733378808019164713600978887019905699871417123365613340681673916006626966649924170996253273073733852663021384681382051909095614154557333966638418401258055946731820806422207820872515345183005729150326803604361512295955159943694411555067679327842378949865992521340416781113735936437694218150384351520004302169462501770232864597266654390198260481651327159066598217103147752784312005857617885666670915444340917773878003125490279146098981790584757296196254721882965728596834", + "-1", "-12888526328266820415927145054786787145889555649382608442248161845973745960691528655550360088202102799744537495406020539568745771467756467183613368156733378808019164713600978887019905699871417123365613340681673916006626966649924170996253273073733852663021384681382051909095614154557333966638418401258055946731820806422207820872515345183005729150326803604361512295955159943694411555067679327842378949865992521340416781113735936437694218150384351520004302169462501757828919673315808140966784818543899913669994993301047477679896562094093485712805580100043199151725754122609426353852012996273107965021855071957241046231143" }, + +{ "10948926687039959668263034501276830818625159748756208667794639002017960671515169323966433371280908617310031465455790806503858320395456591407286777524363944", "15489368888944605373650389556533647343231613227589912336942045556008797399070972592836944702007913599282985878262526911196097512734678645706417084706692047107683744531285802197270639216129852640210205547180574081479052109734758880839510339349237982383997307379952940072013079809351763653427560483156946719035644278683384662348499193303099798764213152890786143522348717903997482162057330324665060570551176318195643585920374603137371921517627526609290876303058743280212715019326447206678291320236859616579863769668727778545628289338458285997742887048186232356815344233169348134282594953756462483528235310248146271138654", + "0", "10948926687039959668263034501276830818625159748756208667794639002017960671515169323966433371280908617310031465455790806503858320395456591407286777524363944" }, + +{ "11464576772189320419261665628466949872551044398628568459420638211702970737332076526558331636045640676437486199912474581890841933557822038200509907802936313", "-22467560825853172479037421968188386486420879368653733048793951227030601094142939166908251610058992921146938740897141065727494001469172869273657374887890530345239013255211792126218659779037493454354985213639803588241949068595974842726845550080803721118359501094994460828504625140423100683538018569820187798018489678377090273255263020908779694768888896507998040871877361662889436371169588814603494476932238384716309803290555316924487478792149178773379217766514013266795383492328680695659480010501872205935050314706513127406414046031915649062646891311739001532048668245929929298605152418405630093221583825629790103566902", + "-1", "-22467560825853172479037421968188386486420879368653733048793951227030601094142939166908251610058992921146938740897141065727494001469172869273657374887890530345239013255211792126218659779037493454354985213639803588241949068595974842726845550080803721118359501094994460828504625140423100683538018569820187798018489678377090273255263020908779694768888896507998040871877361662889436371169588814603494476932238384716309803290555316924487478792149178773379217766514013255330806720139360276397814382034922333384005916077944667985775834328944911730570364753407365486407991808443729386130570527563696535399545625119882300630589" }, + +{ "8938867625495530153186421114297747048040597826172184076413640033054738602015847458230139602813250873350372960139469151926251587994978713194477868118851140", "32078375072910127937267277353555359769886046039319229674839329288579279294400524798815635423380870475101996161416889444654312193048344262195882716890119398121411812112449203794619431500846260449790771355510015457009235934372609093350279916863051987911050185220414029935306290325311701907978862607656115228781358052463349741922708496995681137879712967466047121123132315277071458202185149672157950295326835513685167006326116804121841993768353882369640078584371838201520000042076939249781755766637255305083290727182613012935978235950698890245889658464214791358409590524627630419359189066595841389501082705783042993303059", + "0", "8938867625495530153186421114297747048040597826172184076413640033054738602015847458230139602813250873350372960139469151926251587994978713194477868118851140" }, + +{ "8722682937170431050833187146084378340001260037987475887522226657702929497643381574300242436757970258082372353322466430729560481174965555877218498123235127972650642792093407571195465205419575987213014443482975328738475261835806620444520634849116095235065774422144459742716160248838471185163698000228745859478158104063095766855794756463409807333016407203497851105737138480852953389782284594500871170431951978989370255765328498664056929197514187424012915608945460596104718351333193752820591185791608965252963085687083606400804224201063308456591357967802486377986437493144904666736661926951141864058594174814702200209409", "17412472792254218853", + "500944526446044913245854704095754296476914947449773601840238266000641308362538841153234090543298285278030309320940403936325404298435972916448525262079072487832742313980507689645024811947475736929391921911894727993931203210832413457668815952782782949239897550712034201783959782842323270598876666346488371315244615931371511266927466746002593260083813695350859233907674818312186201150675556646229110170730257749054381148001252368819048293261475322932890858943640868603051493461480912552795132518076648186629059596407623028993206501153697237322059149347109211519809718392500920402797396035977014151301", "13717640401691531656" }, + +{ "28355649069936648964480577421600521514076854589748655538478527484386692848040560920378270353295750065522502408426901852657385194373002516782134462463403619404085937808470896616603996134884288656277511001166614643845546560002367982733683422291378278295503032478358197654941019479109634084898326003113897170044006328598213579789377859798284810297339455100733353158770429621612618690067430491463355522146151298846940191011096497912423339688256950368577997428204387561345591508638698782496102293891198658979297125431373501637906166414269821235570899541062164735301390814949753951678580623524363615439367796948526661114273", "8633859053023126034", + "3284238125245742016855698157684933898976923158153988299571059835059738533454483417199061360717949675767825259147742326435714596823475742487511565640155717557287585352355724513814056546156034557507060565711152037955657280498048473524523497495066421726381315710512047045674071154161308957202034177182801687183543929989744017034272683534975659632492076519296858840261469439577557507171156150551483889412665000065287799665100306570592222219949067222441707356112651967102951988787499729560738632591896472356839552808850928783757605816255738706660766653939585897846868373880810762740938652879077841365007", "8480542101902822035" }, + +{ "695804210379264643979583966247939985121477063798866833769029083451619832314943028815111717357207629373097980486420088049066444875218919515464168730784010670913213630418336413807551517181427706050442981412812560910674568907086122536915068847926867597666432252300779682993163510641754139318056267379096886236384894321926559804092457910184502775704660359338939407870665678723351102313495695271753077268239934810069567863069912893064736153816317584230084541663742856849855885433861537874945479324326871485256528265492542514387227516996450338546971631790859699133015684902494112907242906699969802617955900147949678000702", "6681774530135049718", + "104134643759851814351147451693200005177949603843035721223567744815305881538588822665583702468671678158123657386652154620049781061631961328262453617035662063853637317024464861861946266314086911857166878173456014196637218631863393572542109069255296051532325807248516303174349857623773438852122643289226264801658953137748153296436411578898337203701260654377419646372368642303334799023574274991890918545934625239992964365706183254509198057965378271765137299881104144690382322308740670412140492093203922319672781421992523823019735773183797196153517598307995654976625437636949948229208840097078305544042", "753510048969320546" }, + +{ "23793846839231724395641481096168600821165863841834871677817770057997115862268350281729411419898015728222764385314741974298570203231459954889026804768374989204737469979104608191592488617915776065920825549826544170491376474603565313317103382409887303248767928207436610335921923003830631904883475966155908755916279914050461058817604412376332860234542206749755476863494453482771627934874030957391163592500144106720406855489772599751499515034904792907346159848425450017939743424553771285003901024075692162881112993617392057913260097840038314973483416617082316428401467936188718832437149607288888734084245887947167600476942", "14251636779665730013", + "1669551870223134151303903342674455433642542678166026329327716199552424270739267924882373474967130314854205248773422856606186537084529373808518256136223710801915037299873741750309033582768093390015183894640465684163714303454407585554851774795653260663343812169894506517621409762650950455752948417517702896344204545008148927831629685230911115972567815995382195887880974480058637498609515045000261275580213450984765289759768577989085446697886224919418538617830152205807256503108619376475835548388022966261347231830397100233962945745245326537590040744120991719469590787920917431072137837209281279829978", "13846244437708747228" }, + +{ "5157109352853249971318864071100809054313778706912280725237530653514718017885603638808994268309662830522966266131723296476071219223553003512249189605920498878997009866938158487186969488205976122254188731320527219934117903279062529020046834522969499499006879142996400588997334123741485390256248878878301063076286830584096271875934275097457786951285271567141607668681320623976130528011279831938224824782139301311433982239041406699687231975177586985955350651094601995816681979048980035660883809964491229857363116776116215144288428315817606755704237448380042774619545204701291306469557276264456990236770565662987790837189", "-10013270743141522218", + "-515027455577944332776599219259294388811187969682242219239790206822600106136108551964834930674442778634657645567794824061780492131991288077428371773780758138983535394992930162959647831148714333399217585802721010849103285390761891312665489859363343081240130486926587552859706337223282598959658826457912110150229463850079329163597771797337822709730777565370953422223408595882843118286956939988955846229075579330815290845722563420243422752650828997772215730429207767090119357203878107337884921705286570049639435686342039828502912430702417787311741719990865608911989344378016685337998208215872207554274", "-920760231421022543" }, + +{ "6494479986256116541104296929948745881595810377963953264991072983439840586308068782167240611739100078965050725068818882183756338815160036859027539278041681781661292616356111680897493765185363894557565156777508945778492400417041556530072176186473028646756075186621344659621007329706013704866019055199752880400583535752226648517005237843095412900402261752786336175778761394870284838510406493285835836510084377115102990988520712094164167646661458280428910514014249834132126729469995977022911113044853980749549364759880528586645949565758303087716543654543586861828638440479331739588108393797432477382024670823562517526646", "5646044948886972124", + "1150270684178027997729638025310141697535651329313468129284627631873742535270359534840413194117215304029010709513909008920532146218787185595227269977210380838656683242728568521891853665038056999715825712357842110695616824097006318159870253326008969365677078769387050477555367309756230306675796151995910498740461667569866473279089249936015985131524549691332989894205425117195925594673141706705491188937755834316410829046680432307112608812689099288880996341318638564624566449876699247700823589547245730672763432749619618807750355174780947014272103851229064036660484535227006468477136474311066305263226", "3785857158573214622" }, + +{ "-31360864680221422030140415094508859225037184177278863690330048646310966010764143021431123151508104188281687033827937090369965061135751835578522568620174870624326364591751719134017727476315825913896303730502231987133828454596458972192605628269836766485752863341723932456882638706013143064500915331711791221807863285445277518932935928879510111580179238430718068897684115464091110803073393785115849134031970572952341156248906594900067269723116623961645695573540685417690666812895681389324387236630659047254288574908905115640816788218380202062908240234242061857266935270268131606785945960533363545765413571210356588614272", "158731480268028865375787109312788454557", + "-197571802564094255018835618501836237470451780852464910702917947610328490115600879542277218044587953977482033832066853445897949746594340123621010571525423525283265694134335278880857970722363261435835440841138075424370755023622549046990506755720823389094963930373207384718204282462412342807880786115573288541223692700693236309165845190755419998468567231783954117079063183652374494384463667165956585068985935341133217173168221529758860606207789154326413767211275484817995028454435144966634656180655573506329003296926488159246532512031996848763667993503525898127688305577417054301089", "22128982064863884081225183621483498301" }, + +{ "6972688127252138459564959519023672734797720350352562732688801457617542500099509865574973489633915033719003377224851429368921013349700580153017928134596084737004044411366993842119504403376959959480789333673755655063117787017101298662107070542628327980482897959181812093955456006698786827411711446400770298021381400926276799694253767942575674933967663793055141073318481678170963516082521833862017762649825976536694779299584090771859213561628651925244725218133964348562464473355036335901024895778660125505334188112559810228121975479770611339038859346371817450184722764849484125019138077786325611240207689562646177214862", "212229494710249959442576275005814060115", + "32854472639496801513625266171869868980490382632885983229822011721729192329270622778562010916862699719016516950898363598128121229189750116863530046554995732003476968354657890095157193194509736774942176733534056571834590366060961121671289385934253368995757730753667329275656966343378668081666905678760988072374390324867142186156887369444294667350127131255070935565628787125782523108523608392770938414227072810340675454608542379054058487857197652824285799185253955626498482144435788461420918351383205430463919873128183751743772403931916447474872579786344165522578418757820262494633", "202602247999430336716424978770050352067" }, + +{ "16146477881044981814872185978005786543642189695578037880128585850657582227346785609949631520306446259385630057714250080634804935779512167368598228578137970013047546260870411704532863029107179381174130047754949458719207263855344249323475379597824225167477700328511898116621808311449385399905867898699564040099050435706021172544369947305690899952295406293447506146823515423102232662385522802025721933657658703659553626211653699561780784625213816227416468145185123310306319508640423290747072654284738002434784128270456278391972933415297337582959158202392632248570451671740383769937167912379559021602080900933189192375421", "-20310422672054016316639412907518719590", + "-794984828319777650694385094127543908631549711061207837016795411776676915426259473368853160688756737034823729254185786121643208845684214393842790938031685686187522759314947140818495607328399712740082388950671812621562726517214947696883370445215206445278987678057453772575168165658852145270562955365137991966349779422574705948837912807073553643238677887356778699590679423929808592396737386221680984966466476609537799000714595283015387280145210362603689829188312020767177147038887361232908826207585485585717770550283815412266616448789002231614634998653868395118016500112836083648523", "-11799925147898511149643800539362290149" }, + +{ "-13333386402689284528955650425278647711888918022382802858930735354762601039626630790596510115878972126652469762677159574447095103432811719733783031083771953511074739306201836852090205483055377050725227473420407492132102122918222222661174330427122421429872287465154597256840268514193104109407101719163350519145025605863849817679140939130213133277602018019855074419919415918787364400403970284236218639542926948339939839929520062948689163759711059171596722904754429438151009753108425737178467425999202826949155777669899192519705543679208977557190789421238295365156644743397621766685402593133067165504533347334868817548870", "107895899863035416090758241115761545328", + "-123576395577726995467509810094692559795501216776624732643654929468261569953970620516962817836961555200657486752392956631475337670018968072148956742753944568338154539759184635744464807131713977468703479999463417456632584312098725347773265375061594795112459950102134313707118281441803361728717545150343139196161174674989680811767284271234273952364761695483244122531302983909975719498713709629935106791776293856798291478157380963024628448230576871460269799644149756524167414024818290038046315016119726155391403548599527926110598142014566712845146844517328059271906387663525750970076", "88916219636034843584282198824028056058" }, + +{ "17396957313719309181655810621342598276769983942993211094806395284201495622288603530182348401034532670779772026613959220329662328631746748840677422913897389222211979435071300283979361385673923168895608787064277711550661080470385607194607715097404666355341496134600730286695020337462621706659365279865288817231582460135505994785679557826378614057840182487774381015927951405829305139118747627556929090278010945530871104877221509669969637405745641517281958386251071953311649218819211648218403974139963448683937267881136641329201897530450274203549882462469989176813129608929688681288830465486480047730094845155570312862849", "104186547224209978415781641589908237686", + "166978921724711432713743436094800137505239032223722714964309089009506614535895519867110422644603923287110323367280581626196181748165083370852210731028149827924135420402322644021166934074442323617970930798783252483767604446788478644579242675426052418474560530381252273076756647943610269802844827006798614570113552490465455602498689920520721194207399033534120048155924790694559525815508064767545247429922864279482054330586837508112647624007190343625308333109186981945018060033849826856038685383194624273212670683254990051450794748656874003602039616482791671154071071940218956513118", "9689041137085346765396894259391897901" }, + +{ "26296668029363560180578472840636347646283515109787546573773133131169235303278230292620358193183994696837168281782424510501462932715289179113988102147665778902989371433141498385910026219307721742927641650208826808587628688330897125412814594284814050899367007933796796475217266168539594147019546294897573039387284123267787652073296654465797846788961105602455421819896924940988943972769457383697764285807789932427485615761627567609238909525216550007481876466503244451415718439500787125259366798747857812030734235875561021422659158282642054300429948383202431010170473103089719168265166132037042278884136592980721399898848", "-145151976679874338336058059363314537", + "-181166447959297097309632649706277310462287087273328158550559504514077025970552462585976881228509338936991115036681066334762526041621219901153411893847383132947014037561714726163730996723689359625350327562359371926025189504119439124542211108302015324941630060663441114185165191476531119095379776949183747807676488899740428054170566283213350742091333006110702325305863276507428847828894436119391753135134140918882254262557249907254757481730047992171259860818951015886963391969368286964814563381601392580107247382831740092922947642920341973871311541502943677603328463821550096331015449", "-110577937214275422567781046193383265" }, + +{ "-19994387832358687564296482880955715923586831477222916410597818184152857711804843023778287694318724091304456899035183525127967566364649938785565453184727547598671504088541688780249133503129117660562371945085803761853547276588271572826270417538713473845464667687405215144939251922714172491714494707146884856110703801489923219443900691887441959990915961809557008130581221371957930424791112777130507507175854695038524747304496126685506502272017923871345301904089286401283977464945598827719321374155830270851832155999413594990591210770207211404582078047399265487243377424091264415562555479103296829671606309227114918559411", "-12290727751262531359522445814787932748157034294075544178515373320704162497192584943859172528304649072004548036058435558708785921268699678655127651925033127", + "1626786325187686206254527912536268233229423573477257270053889346415589499220953871015742625081244397640382477041911954315181713027690095532216560352291641519082404655148801601548476351855968135320238312168182690718232048560912434032449056943124604465352409935769208624710904989903415445402236977791654195811881494578919123294926181940156782515461241607944723498957864382829554865120206763098110715049165623436566759235599826844834593966722456940122296028858654743", "-9304614710679256891239598861411560332304324920434685965899525875715186019084445758952863067134832791421060008856516918122255022315420901512824783987888050" }, + +{ "29916764548363516315213840380698377536192609328827808911066465815108876776179490417834258307994776308911573596103626976278007330105709262864909645777842169226871227147054313657605129607087589187123503174807369386299991859056839377153696490642393964375926230602462747312790529261100240727992473466712957240583216041201088172946856263144111813006598318253235946940685055230369936673556047728831107329646718919450916347559724523856479721600705891348359262178740659519774585983326669798219391447115538287743254388570949370216658299333436961807924794235560183973249587386381643272943817567729138289488897133971529039695757", "8476334091496252719253471844340714224307718865976339399900779938495486609491382968889867250990569753004524377073297071391348967807704774866029247355531618", + "3529446129120492576886933802306348265603546401021071145489371491655402978871242160302127070993421776756377896228018319062438889879832901903630775379375474362476945682118589732246954574638082665328364641573132346715748566497144048040413137331852635046499249704620713985392482170976329565026453768403409435575238922748145312555307402543771398751056417238642358386670853730480256387244547289563589645563705382910276075835741806800308617595407635175179549186349623407", "1121598720662440742988451944089192258208677258393969079460095922943603039995215206852920630773807538691962340221388452566848135314318278502721876458313231" }, + +{ "-30744743258986840974825934925400463284355151584175701001085034454282509186617636999187209301942468580138651572968436145883508307958710953672541548503099036345172087541186583358599035971842953063792288589346835317805238011836025866089112384348158834439025788655670125182111347815257445264926636792871229400549827577321670531162443103810493815924151448637886392962948822485797619344455378736429734156821345757186019132123507024835777255364976075865806996283635073664232613154449751312293463363442122204887362535000774934247468263702545257658938264075634847752288018235968497021028555508346290918717339789336670514080457", "9934634309555858804270980126309615970053320780519373855793924975583204316518242194797388422238716941854010764960600214725109000476250489194524103405530739", + "-3094703066162616114961725586598761886126440000450319657542750158557542422972265973994772432239434133706930345695126019787070526540238058168248601279554005834087067802027491094801318957724338773860374084056857766237802500357570852135835098188033303615905411388899090151866056131910609183545491275118194384669083917607888152562507000146957250511707959497676133004912560741040750644659008842081402439245159076407113469036885418577123982203712293205143214370192534124", "4583596897489701137708573201509728063693689464812281935974761545728663079569821440573072545991527054461975034582959468944964678550288258358252037074357179" }, + +{ "24643502519803888691586762836893695554672668882609252497967357925433058477865049537403781351424439957461939549800248300068008928283760882152105280755728186165336818042947891471506568092832294726444765034759769551554808855491501013689374698042749154404230203678454785382207604303955330803002216399957247238380783055267792042696128953561495320963977422797650867160007702447898131066450706964885725041540562948429789541526915479497874153956586286026740960933319749986950590370162278200833957789772606366304927219928607487195862425188567871883130961914293433624774413725427494180502314592349900074269004608052919421088368", "2717450167284225996753981867457220829510500841312068511238048532529427648370573174539553585183069673827813696207263846346713773366926177883038970327669336", + "9068612486988930041452615817812610262395413380750714216172624755617167719146150429506179809229439286481063525474263171526993584649905549895379552966354856688607031124385144196292585204982548068977456744404073207215088901248836694827956726571697679223311674675917482789361649212542123782029147076771863216074461137218175127751607336902080642274682219411530926094644805942929937073627694007279189212959755881318530033893691479717411893927131774283641886860168845194", "2630363844657415178536247490974293939778607568925570410250370678327072798984411202414449734187268017772490491616031334354084510652181851150192386816317184" }, + +{ "1857471144762621226078309760048781819853808902834007243224510947324703640579895884811355396539307768563652552656687272466757001311647739575925654454617797724205998847128737511426204839085303003071906438273332520201294499647651016586411018765198623236956366866836742835368817430092030307634950795461633849978479504285561783793523293571899866834127333885745234267982498066548934305641020559144124243564372784715821253591393010485777361901806233522170298666402318233462164642692695586402286093353406704474285764942607399336515494566976327035651095257443119526233432484730549923908643983835638400244551332963304703341991", "362612878824948204766041465498605121983038344328923889813821008133012829955553725429013872301357114460102737976404433762806451909620639548491755012601032", + "5122463247256360173380682454830667735994909336257131094636868172398931453441644851286253058553683806107714242214425234484025628771776577335533690016729030113210376620329656025707882934177847398968795670307669192526890837607471635669459016090183544133427748745285201703705268883110778706355536331762965138118319801447738265213248123408984033840769670544118622199016226728679039309116650227118501163822195946867970684116882706924781160720494209768961175300546225784", "299760236823448232299335077352435634442705524236228994156709162318327253866985319237312495500717724311867426639654094420477947147244359720759776119932903" }, + +{ "-15512250050509017569431653406374218468191654707236673402325185299702995515514048891881128604127259128940966966514594946451486134694476273851559935124397715410737724278746590654901453457150411276548615199767807502093455391898384739629715289928761836102897197661380120487438391395985221415090269132778914962364055598932950972975325423902250870789291669816092405224971234605691036355433974706922342506063057313987759468269851537540937400869685698983579620650290591582484180497444639057157757973753179907365231695893268694300775677678977541920955165836544926807198464657683328635157477957240884116233992874779933793654204", "3358541127950670805593397985550958371637657834938091938230318311713415017140090677340291997759883758478618605945079413061265904587739160855880393703427541", + "-4618746491270258642196486131268015112521835423420717615093174172980857448220383551186758990917205762587881579670823547496170992786073126440511182401809159567300795932372630208424356476743332043619346311088384079059435373790499576304419282368802375623485321283238175405485184862968207039638749406944454331623523507687428477960605913568521627594126207284882249627708423470608914416155986620408793531083231293214124556072929628635430705354422888702360112306375650944", "3005102575063606384680566102915562580638230938191281335082512965430334791588194853068845397234960243041587407778382851298719244486316278864423824018594500" }, + +{ "-7795907266149417935880848054805638357926463272237741460640947569644048588447722511612181517607450880049915905557897989678236704307693907736247058983016545076253121570693500226105057772914231058133990872553093077477246778482972908671114493634160355090012802248700706280069417479488180111886570768297449284497993155476453139747448123977064178202693174347058572053686548952330935409613585349836865130827901523001778569465270141666026392762544863707172069660941583975586471593214627992137708766736399392527511202198595607734119123667475481080585901379489987633325665012548140296404667154265922084962379380813206642961141", "3266322496024458154155982586177367205241879884975448114046439840444265881425140636480586339953113858345978121218157346057285955670573379845528853928778649121198573716895875372950665878135491926664618467827249347334921049358968885123014320008238518111491029267663871866232098994215220584035091470875989416180732388925174422587186795087858194659347743269411322176680238569785902471836835335166112452646235228206195081915725782645939016905926964169376697807870023636080042287120562847150399762713196525578131013908505157176421364232903071413436786302567498639276925676203136397430977438669196132229839190136276524068288", + "-3", "2003060221923956526587099703726463257799176382688602881498371951688749055827699397829577502251890694988018458096574048493621162704026231800339502803319402287342599579994125892746939861492244721859864530928654964527516369593933746697928466390555199244460285554290909318626879503157481640218703644330518964044204011299070128014112261286510405775350055461175394476354166757026772005896920655661472227110804161616806676281907206271790657955236028800958023762668486932653655268147060549313490521403190184206881839526919863795144969031233733159724457528212508284505112016061268895888265161741666311727138189595622929243723" }, + +{ "11613527140000568192482756738253388762224453894786686024705324634643336086154640452808765642911437980109688560443031730927780624431102238262306897218656077453053740901919490705730434109001630505554615644472687423755323577388664893480041595787444776915986509240983988768996984961291424649229547505632144971266842770877960364848817464904515794389771780820407027606373375049573795106795237627834701205331678265805568350911815774813018183599320960878173351437520785364220474506113269284418886794765499703487689302735252054649064328797761871733823998210784410557300554983737071496100764692702245794941065431902323619975581", "7587249511488455291481574592043097850017617150850944854151430663857438629054661904725186504711545142985024178310267212940242316767124495452290378757849233879415880641974894427201010329762690544890887138507664079244754338469394276854749839357593153274763991475638253761900794536890806900100092838214316658164432730592513062527370014192403678448098350118128696785002089891158354556141292773760767431084006166964515144211080310413063362654706066932594296395740249062444674285627590937186704887659632200604451417990996813320236575100574875972599186794102474813935877205799664448604353627460661673753990274449050152179527", + "1", "4026277628512112901001182146210290912206836743935741170553893970785897457099978548083579138199892837124664382132764517987538307663977742810016518460806843573637860259944596278529423779238939960663728505965023344510569238919270616625291756429851623641222517765345735007096190424400617749129454667417828313102410040285447302321447450712112115941673430702278330821371285158415440550653944854073933774247672098841053206700735464399954820944614893945579055041780536301775800220485678347232181907105867502883237884744255241328827753697186995761224811416681935743364677777937407047496411065241584121187075157453273467796054" }, + +{ "-7305781671042805086205879027901218372025263744748476920370936801215407682690507181906856060500614379569331564964369672229742583709815447579920249246854986585035499467980872113078927984775191185433409825799075510115669850322522523768142598684481781858254267858499128954637862215107851239397355311785880257523971110240017078879170794103136756816178851155500522519324993786026829680880063502983144325993463559477297984845168078230705008144229777150602704982383890956566628052218375163513110904344758464487972471262152773773566261138354198738738504010228322403241824600361830597196538559114936352203702189317843297305612", "-11937423884971453925821024083751259499642447259766781297912835275709052311299551864192658177304486399283699058384364751376568714457361090099824205847610164922413207048832164141112741434740690851620879666916091683114805059397520385319965609291355819302668926633114618391597972110270104195729524521712155052417250364832858246777602394209216012243471719585422463867924602236259070514326289155605995143153426519592268534452020820494702940294360007255909971183689215427975382460838239606147437401771039532404179010791325434773433170447691511043481857627662741058910094855501029573945308325534013127380693322055343068093073", + "0", "-7305781671042805086205879027901218372025263744748476920370936801215407682690507181906856060500614379569331564964369672229742583709815447579920249246854986585035499467980872113078927984775191185433409825799075510115669850322522523768142598684481781858254267858499128954637862215107851239397355311785880257523971110240017078879170794103136756816178851155500522519324993786026829680880063502983144325993463559477297984845168078230705008144229777150602704982383890956566628052218375163513110904344758464487972471262152773773566261138354198738738504010228322403241824600361830597196538559114936352203702189317843297305612" }, + +{ "17209502052655993695999949678678881817732805080961191774214537634467104669997820051278559964292611469011761231649311262525642916746094372962648405298787080759403024379693612743720557853611946286870304197122036126838107226222151419136402861650399432372524638862075613534601535719033760228742681750726602275976151585576407980278472053570791272866409613117043122126348697545507835143620584132787128003876247255766444872271317786602207376422907474443135464267851639815814827163426470735478362760843575789201717413221027220343295978806345517086041608240978720520050196395624694268550345436208830801369557317350938753101681", "-25492366031674865714603800130440722297248675391454036922399382654290017832413394991423912006244487394226853780856833445493556957899686872020567315114599762113500546176766623020864155665149937580279148318691466089932874147998457966225079089491216886106456935347049916843309661581230809710698689198580162954443484103521650233141750002940462046212610545804018834324858009370780731978549694951052575612824613445810777717659953126577086301947235560041125102454055651800601741899891885690488712713049609045874194541526013910595588271596050758340197535035493872183554373796733932414738278642683363241812520579194986842248406", + "-1", "-8282863979018872018603850451761840479515870310492845148184845019822913162415574940145352041951875925215092549207522182967914041153592499057918909815812681354097521797073010277143597811537991293408844121569429963094766921776306547088676227840817453733932296484974303308708125862197049481956007447853560678467332517945242252863277949369670773346200932686975712198509311825272896834929110818265447608948366190044332845388635339974878925524328085597989638186204011984786914736465414955010349952206033256672477128304986690252292292789705241254155926794515151663504177401109238146187933206474532440442963261844048089146725" }, + +{ "-8264418404762904935971540586212553189369665581268178138984287355704267971035469114147004054957406066365602520300857203610010249719556414712966642864630190534880504909484466848336120976452116710282569157883499369927614177722612839620755683557142607127318366680113418741529273669250116389195268121444810596743918472573214391707744942602210637166261703132552343842498400457951297867678005414165609775233338084350550320105330065321705398390488050253072298385134487973139665686164664754618413684815943926055617247418686500187322182211450203615430634564054858334306443836925011966962933359925972720453678168762605413687214", "5659270408666391096654451960229302202479994399681938594290004159630195588392730314741316662127233421095165804881532974934939182755121225362126950700260935754690609887023434283325604581248499606543036334396521593447377999307285561199879892626309791285854660250329582118972672086769638010239857182094917068742207521552140484875546416914612991626798295801703343486711676899362639653362756374154843829963089403048720579483739833657436575344900585844370562669493206999896738589003961397524062927929845521761767153927579517203070144813897742036471334901681673999002492983666998353060616069539877603853178826800408499832716", + "-2", "3054122412569877257337363334246051215590323218095699049595720963556123205749991515335629269297060775824729089462208746259868115790686036011287258535891680974500714864562401718315088186044882502803503510909543816967141820891958282779004101695476975444390953820545745496416070504289159631284446242745023540740496570531066578043347891227015346087334888470854343130924953340773981439047507334144077884692840721746890838862149601993167752299313121435668826953851926026653811491843258040429712171043747117467917060436472534218818107416345280457512035239308489663698542130408984739158298779153782487252679484838211585978218" }, + +{ "4195250682093770808206657488351701663023767531608220002369022288787894743733460069813218793361969185403525213558437941222523116136985128137372308027033996674188008302853626391013869026313385724383785051935256506784450227965020957296318645208598488161413279403683346821629439117327209071527878791167163980953326296620631874274522101994118890706372879111377721965738161511000396672294975037034526549811513789043244305969633354034500541113123255063232374386942908997046756046017320772897856114275234707703184161983806610888947627465435762937561231247173215724615365040435541390265704981699351563837340527277633975576176", "-11523670060248463390302653643248573080204626895667435502164973305972185748470395654926094006744012148505197326052121545710242241891352369937317053719774706293090545099894988182012473466703170157783937873302934404896538337261995680454862441735502556865637909145839304694688324140057229642104588273654096346180116632418345589170248829444934471179206795690822184585196864577932274205101316913141872261673241280391442045565990088555353753789476615480189520529331131737084431448177942371080785938641454814169544682945510387155405628842164935394830439534834414364899293061798829902686953424000191565445443376301466821322836", + "-1", "-7328419378154692582095996154896871417180859364059215499795951017184291004736935585112875213382042963101672112493683604487719125754367241799944745692740709618902536797041361790998604440389784433400152821367677898112088109296974723158543796526904068704224629742155957873058885022730020570576709482486932365226790335797713714895726727450815580472833916579444462619458703066931877532806341876107345711861727491348197739596356734520853212676353360416957146142388222740037675402160621598182929824366220106466360520961703776266458001376729172457269208287661198640283928021363288512421248442300840001608102849023832845746660" }, + +}; diff --git a/tests/exam_I_gcd.cc b/tests/exam_I_gcd.cc new file mode 100644 index 0000000..ead642a --- /dev/null +++ b/tests/exam_I_gcd.cc @@ -0,0 +1,119 @@ +#include +#include +#include + +#define ASSERT(expr) \ + if (!(expr)) { \ + fprint(cl_stderr,"Assertion failed! File "); \ + fprint(cl_stderr,__FILE__); \ + fprint(cl_stderr,", line "); \ + fprintdecimal(cl_stderr,__LINE__); \ + fprint(cl_stderr,".\n"); \ + error = 1; \ + } + +struct gcd_test { + const char * arg1; + const char * arg2; + const char * result; +}; + +#define num_elements(array) (sizeof(array)/sizeof(array[0])) + +// Note: This macro differs slightly from the one in "exam.h". +#define DO_BINOP_TEST(typename,type,rtype,opname) \ +static int test_##typename##_##opname (void) \ +{ \ + int error = 0; \ + for (unsigned int i = 0; i < num_elements(typename##_##opname##_tests); i++) { \ + opname##_test& test = typename##_##opname##_tests[i]; \ + type arg1 = type(test.arg1); \ + type arg2 = type(test.arg2); \ + rtype computed_result = opname(arg1,arg2); \ + rtype result = rtype(test.result); \ + if (computed_result != result) { \ + fprint(cl_stderr, "Error in " #typename "_" #opname "_tests["); \ + fprintdecimal(cl_stderr, i); \ + fprint(cl_stderr, "] !\n"); \ + fprint(cl_stderr, "Result should be: "); \ + fprint(cl_stderr, result); \ + fprint(cl_stderr, "\n"); \ + fprint(cl_stderr, "Result computed : "); \ + fprint(cl_stderr, computed_result); \ + fprint(cl_stderr, "\n"); \ + fprint(cl_stderr, "\n"); \ + error = 1; \ + } \ + } \ + return error; \ +} + +static gcd_test integer_gcd_tests[] = { + { "123456789", "345", "3" }, + { "345", "123456789", "3" }, + { "10", "0", "10" }, + { "0", "10", "10" }, + { "2523533737", "855322739", "1" }, + { "855322739", "2523533737", "1" }, + { "101611479673163974026724715741235467160607959655653420075620", "533177863832047932237026621580126811198495699416238676294977", "1" }, + { "30729415811", "323233683197", "31071199" }, + { "77874422", "32223899", "1" }, + { "974507656412513757857315037382926980395082974811562770185617915360", "-1539496810360685510909469177732386446833404488164283", "1" } +}; + +DO_BINOP_TEST(integer,cl_I,cl_I,gcd) + +int test_gcd (void) +{ + int error = 0; + error |= test_integer_gcd(); + return error; +} + +int test_xgcd (void) +{ + int error = 0; + { + cl_I a = 77874422; + cl_I b = 32223899; + cl_I u; + cl_I v; + cl_I g = xgcd(a,b, &u,&v); + ASSERT(g == 1); + ASSERT(g == a*u+b*v); + ASSERT(u == -9206830); + ASSERT(v == 22249839); + } + { + cl_I a = "560014183"; + cl_I b = 312839871; + cl_I u; + cl_I v; + cl_I g = xgcd(a,b, &u,&v); + ASSERT(g == 1); + ASSERT(g == a*u+b*v); + ASSERT(u == 77165803); + ASSERT(v == -138134388); + } + { + cl_I a = "#x80000000"; + cl_I b = "#x-C0000000"; + cl_I u; + cl_I v; + cl_I g = xgcd(a,b, &u,&v); + ASSERT(g == (cl_I)"#x40000000"); + ASSERT(g == a*u+b*v); + ASSERT(u == -1); + ASSERT(v == -1); + } + { + cl_I a = "974507656412513757857315037382926980395082974811562770185617915360"; + cl_I b = "-1539496810360685510909469177732386446833404488164283"; + cl_I u; + cl_I v; + cl_I g = xgcd(a,b, &u,&v); + ASSERT(g == 1); + ASSERT(g == a*u+b*v); + } + return error; +} diff --git a/tests/exam_I_minus.cc b/tests/exam_I_minus.cc new file mode 100644 index 0000000..29fca86 --- /dev/null +++ b/tests/exam_I_minus.cc @@ -0,0 +1,295 @@ +#include "exam.h" +#include +#include + +static minus_test integer_minus_tests[] = { + +{ "3872339191937382556", "13437882608410293981", + "-9565543416472911425" }, + +{ "12702320881720530101", "13823645380834800545", + "-1121324499114270444" }, + +{ "10222969257152373972", "-3454292165863475982", + "13677261423015849954" }, + +{ "591233951053628288", "-17639978232337836611", + "18231212183391464899" }, + +{ "-7878405903223218778", "9050739027069287469", + "-16929144930292506247" }, + +{ "11347120771894057376", "8443917396834074370", + "2903203375059983006" }, + +{ "7831959259127703467", "-257470007821066702597399141202130667973", + "257470007821066702605231100461258371440" }, + +{ "1092406341647857980", "-325710450166845666190895573961860069495", + "325710450166845666191987980303507927475" }, + +{ "-4220606126689357919", "73461013742902296577411907972196819778", + "-73461013742902296581632514098886177697" }, + +{ "-5112059189225304080", "334306213789148650102245018234146620793", + "-334306213789148650107357077423371924873" }, + +{ "3093346224554776175", "-204967241927023874963787190016588249299", + "204967241927023874966880536241143025474" }, + +{ "-5735747638156472357", "-3881750746805128137401544408305666047", + "3881750746805128131665796770149193690" }, + +{ "17639095392510638323", "13312205908441007415860933757605397223142073616822325142416364932887680287063250296996056787873086490231950036662943632990219865746131453861285495087665017", + "-13312205908441007415860933757605397223142073616822325142416364932887680287063250296996056787873086490231950036662943632990219865746131436222190102577026694" }, + +{ "16304056910692545233", "1463591032326743052350022746892396184459320617971409440301562638996633667625451301419074212369365394140737678584830314878769698416417465834928609990708982", + "-1463591032326743052350022746892396184459320617971409440301562638996633667625451301419074212369365394140737678584830314878769698416417449530871699298163749" }, + +{ "-10347586523508777315", "12614325304787850623826535169596975975360455924114817820074336137897280818245940873677389644701038550150832199897314137414727161192173691528917744363375331", + "-12614325304787850623826535169596975975360455924114817820074336137897280818245940873677389644701038550150832199897314137414727161192173701876504267872152646" }, + +{ "16875252323587344863", "-10230183557696638447600885112945653217398839137450096120772416948425622105048400944465287395231588821521217980407867153259741079758527788318592431794213674", + "10230183557696638447600885112945653217398839137450096120772416948425622105048400944465287395231588821521217980407867153259741079758527805193844755381558537" }, + +{ "8574302739232756920", "2945205250727759066959418729185252318153395797902208079569164623770839848878181416073351760975066439564334127158302281471631001294503759011790017443478716", + "-2945205250727759066959418729185252318153395797902208079569164623770839848878181416073351760975066439564334127158302281471631001294503750437487278210721796" }, + +{ "-17657597319577965851", "-470389901349206124503884936612357721199915776516939967013182926735009022045917047211666512521578494339222795740836335004070464944715357800461845632614015", + "470389901349206124503884936612357721199915776516939967013182926735009022045917047211666512521578494339222795740836335004070464944715340142864526054648164" }, + +{ "11472336850218354926", "16764018932433717867649699977474298016589762238077229911249331402108995850754999065988360217500238643747316139204767820295123085026049273617874157749889925712672510963712964034497935503076689670786498045302562704435768723916334451317158760704743066709581593570757498670622547878516907127632802801541072452593999435195637193819500375063696114131057474475407791672955417184592088612921927282233762919112197264895445408873539746256555444555901857369535350160665235184955438709679669964546134487688796078142789125799020704969226557493354453298489954288702387159956161243151013189140749021799388406290339231792790773612376", + "-16764018932433717867649699977474298016589762238077229911249331402108995850754999065988360217500238643747316139204767820295123085026049273617874157749889925712672510963712964034497935503076689670786498045302562704435768723916334451317158760704743066709581593570757498670622547878516907127632802801541072452593999435195637193819500375063696114131057474475407791672955417184592088612921927282233762919112197264895445408873539746256555444555901857369535350160665235184955438709679669964546134487688796078142789125799020704969226557493354453298489954288702387159956161243151013189140749021799388406290327759455940555257450" }, + +{ "12682607562584942903", "32133619583510009354538204193505267426986629771080807813988708187761849276650847958886764459302043799013813125903744946349479743277662066609741649009023451783267511140245797235200413941774959851628239089013586399425314412329003636059313583335807925401822165199322334470452126484173417518861322963430951772895619791799137157183662289329901964728384697377777905235894234370773419160283767144177627084271804319157013765325677633945370597318765372346484383325176768117059688792498687750479618961541872574768601477738410497806623403054372221338126223825515939164627992974469102910882915893925327931884157735553718792115929", + "-32133619583510009354538204193505267426986629771080807813988708187761849276650847958886764459302043799013813125903744946349479743277662066609741649009023451783267511140245797235200413941774959851628239089013586399425314412329003636059313583335807925401822165199322334470452126484173417518861322963430951772895619791799137157183662289329901964728384697377777905235894234370773419160283767144177627084271804319157013765325677633945370597318765372346484383325176768117059688792498687750479618961541872574768601477738410497806623403054372221338126223825515939164627992974469102910882915893925327931884145052946156207173026" }, + +{ "14621880654476679971", "-10075923784619510279100488003620810539888599376089081798647754628017452762406215094511315867213396543200861274584884759429891242650999761503100661310915213260386281412125687376866399124849043409890009033179987278297335571911640353059036551139958369871790768643514550179661619387008678118363266091945225880595898524898713646458647465935791224159084684209727153050053537752111696883536364966526666445737103854446009305531519860527938394412863332757413309423156200192973778629503534709731073637828912608835085933003410694216843775182940057891552358942312728978810053715387504707194992816961400377579655168106377696154728", + "10075923784619510279100488003620810539888599376089081798647754628017452762406215094511315867213396543200861274584884759429891242650999761503100661310915213260386281412125687376866399124849043409890009033179987278297335571911640353059036551139958369871790768643514550179661619387008678118363266091945225880595898524898713646458647465935791224159084684209727153050053537752111696883536364966526666445737103854446009305531519860527938394412863332757413309423156200192973778629503534709731073637828912608835085933003410694216843775182940057891552358942312728978810053715387504707194992816961400377579669789987032172834699" }, + +{ "-3220156644655019630", "-8347829670073174550775641165362740628312221836466572623516708794243074870361401136762432100726575330214254748615114820602945887237367461962207075265579588481261313345359877816874924645801358760718027997416917747796144940020489321523749233377708490614979453376328244189926517907474704635785063100359787580409065317918203485474119227673185211436285930586838616288721370975925191964611302275354365110550116042403226844820172448647475637867255305805337047967053177320593337377763657329816935516961201488840745892529800883680912275812320160312651894919502389242002380151562481051684439333368396132543667539444686619670713", + "8347829670073174550775641165362740628312221836466572623516708794243074870361401136762432100726575330214254748615114820602945887237367461962207075265579588481261313345359877816874924645801358760718027997416917747796144940020489321523749233377708490614979453376328244189926517907474704635785063100359787580409065317918203485474119227673185211436285930586838616288721370975925191964611302275354365110550116042403226844820172448647475637867255305805337047967053177320593337377763657329816935516961201488840745892529800883680912275812320160312651894919502389242002380151562481051684439333368396132543664319288041964651083" }, + +{ "11628988978410243120", "21091260149209133824278525560739673446778991946138130571540201996950100883736332286627324787663044982195445635023357027423513202277912840570399895946346028843517588470258087913846945044832851780108963206182331994065720076983528527849542421619745503796476103034657238118665288185878258232226731582201217795631247916614224227701409259346052937919425072595891571572960468193421257458185693656090215937518204243652916583730260295885562094977775951577484951577581277292356830523013216949489797535362720471761788697932265967910160407593278848113303674799017334692501935041730808945554336564957621028111014116286675587727714", + "-21091260149209133824278525560739673446778991946138130571540201996950100883736332286627324787663044982195445635023357027423513202277912840570399895946346028843517588470258087913846945044832851780108963206182331994065720076983528527849542421619745503796476103034657238118665288185878258232226731582201217795631247916614224227701409259346052937919425072595891571572960468193421257458185693656090215937518204243652916583730260295885562094977775951577484951577581277292356830523013216949489797535362720471761788697932265967910160407593278848113303674799017334692501935041730808945554336564957621028111002487297697177484594" }, + +{ "-15960716439913426281", "18799211173341989380260980155501104944815245973352765317821146163884181375747259542484535639646490774929026134833947975785613727050541297797675705933339289016115326958150660323801621778641184271728990164666383865587422591755046779736996211052149338115836473967202556153668963815595875844414662034458693455631979862997316049580586739835122770408911308146605671192538040301857163633538268589024651373766021087864982140201615461513687698136663128896835597598904095187715456109340116329587986878167776146023396961265667934659006280575496363066974484893764810659481361856335795455814679851690737943592227795474197104696127", + "-18799211173341989380260980155501104944815245973352765317821146163884181375747259542484535639646490774929026134833947975785613727050541297797675705933339289016115326958150660323801621778641184271728990164666383865587422591755046779736996211052149338115836473967202556153668963815595875844414662034458693455631979862997316049580586739835122770408911308146605671192538040301857163633538268589024651373766021087864982140201615461513687698136663128896835597598904095187715456109340116329587986878167776146023396961265667934659006280575496363066974484893764810659481361856335795455814679851690737943592243756190637018122408" }, + +{ "-181065640455671431985325539445069267017", "14120143334024043377", + "-181065640455671431999445682779093310394" }, + +{ "-91295299684959299024846233061686623774", "6891102275697080803", + "-91295299684959299031737335337383704577" }, + +{ "-252582289949155881579950873916766853744", "883304029266526072", + "-252582289949155881580834177946033379816" }, + +{ "-10104159950635417603045689770006558103", "17251490913777465304", + "-10104159950635417620297180683784023407" }, + +{ "288463495341489091297108607960869684860", "-16376960611483226267", + "288463495341489091313485568572352911127" }, + +{ "204661965092367792468062569536290631004", "7774991291341524479", + "204661965092367792460287578244949106525" }, + +{ "174559967167400201536723778015754014369", "168183438971818617783400303174116396891", + "6376528195581583753323474841637617478" }, + +{ "-253300708624436983509156598368557395374", "-77166863757693227553099778725240875400", + "-176133844866743755956056819643316519974" }, + +{ "-38587765028356074196061530813295290944", "5999161273284748726648331130480323187", + "-44586926301640822922709861943775614131" }, + +{ "-236400856885875891058508662756360145662", "222191413471626205952456600591947275777", + "-458592270357502097010965263348307421439" }, + +{ "212937903940173587742882129816769611096", "336470165768472077447806282475185249734", + "-123532261828298489704924152658415638638" }, + +{ "-264812595676159375893264580577855253845", "-247068943830535581577267897204259299723", + "-17743651845623794315996683373595954122" }, + +{ "-1725732715479127274526681751197327660", "-2279805492899538651574406423954277869507456204136276822451602661149698386520868702017367409743272511010382761246500508887739763323997191435566266331339917", + "2279805492899538651574406423954277869507456204136276822451602661149698386520868702017367409743272511010382761246500507162007047844869916908884515134012257" }, + +{ "-220007189346579184019349894240059989979", "9116030813176547770422918633286023943039811682891023288884273747820892639481842291616424036020927750322528731882517057595815179415042385175627374957565803", + "-9116030813176547770422918633286023943039811682891023288884273747820892639481842291616424036020927750322528731882517277603004525994226404525521615017555782" }, + +{ "139683266109784685815165642637380856544", "5782493350903499652295971390391981928106911831248674750993968151944332845911526084530951283012280786005612601970108688202931002414214353708335212597807345", + "-5782493350903499652295971390391981928106911831248674750993968151944332845911526084530951283012280786005612601970108548519664892629528538542692575216950801" }, + +{ "239160165978290709841254489756277328273", "5152132850125501873897264811465207492706871561577273155117982457627773151595716641409297120994045059130053034927464958986304380141364542178714472948085275", + "-5152132850125501873897264811465207492706871561577273155117982457627773151595716641409297120994045059130053034927464719826138401850654700924224716670757002" }, + +{ "315772704643232632782106484978382006176", "-3689252327480456512393153800679864208480329729627292260734151097785848947569336194072922395859496552999163037466184616218582046814434719444842678248982224", + "3689252327480456512393153800679864208480329729627292260734151097785848947569336194072922395859496552999163037466184931991286690047067501551327656630988400" }, + +{ "82735713197488344149642668226610301853", "-12473025194535761005577066561696471986140205263843017221991729197337093872383371857001077050460827652296473928714097816492579684543651922277865558518876774", + "12473025194535761005577066561696471986140205263843017221991729197337093872383371857001077050460827652296473928714097899228292882031996071920533785129178627" }, + +{ "63472235942371758467270296983419551089", "-7866520408163137968600317959735552406794938230345293650627055135268307695389903092041438746530663083967329111232451176014649873249349534808700483360707382397988918594143264031213181385790969271527978925616276399184489007642142996251807222768397530946779296600805549276528669432847672215219943599871223372831999133812100481632278022608906065923652981249057846548868473376683960144009223047416366697876553049362242497225174860431577034875737250719899362881567590934060155436179316063810148362442197071642183371654740845983314705249832168923202400873364289483910868432511677656218937984504828452980698439495961392749596", + "7866520408163137968600317959735552406794938230345293650627055135268307695389903092041438746530663083967329111232451176014649873249349534808700483360707382397988918594143264031213181385790969271527978925616276399184489007642142996251807222768397530946779296600805549276528669432847672215219943599871223372831999133812100481632278022608906065923652981249057846548868473376683960144009223047416366697876553049362242497225174860431577034875737250719899362881567590934060155436179316063810148362442197071642183371654740845983314705249832168923202400873364289483910868432511677656219001456740770824739165709792944812300685" }, + +{ "-284018520801241078671538235859630240269", "-5529748211779294240854894683633173443789067073881249229985499707296461959655918837051490512357840133495603640185675483847478587849599477020706893805485599954539589062532211767295361120129440287144117406526027552427750375526095104163474774446716012360038076376952619723549765229763943818011605991300849052030142173100367582906381575666628005795818339029350398340616624791399526643991489247585213423174803853961438830286737553181353007081438503238779644371968004083452645077716952159339978836669723137339898471600546912430030276920763475622536295311290657163861398519747560279682401429552174530714298081464588450842581", + "5529748211779294240854894683633173443789067073881249229985499707296461959655918837051490512357840133495603640185675483847478587849599477020706893805485599954539589062532211767295361120129440287144117406526027552427750375526095104163474774446716012360038076376952619723549765229763943818011605991300849052030142173100367582906381575666628005795818339029350398340616624791399526643991489247585213423174803853961438830286737553181353007081438503238779644371968004083452645077716952159339978836669723137339898471600546912430030276920763475622536295311290657163861398519747560279682117411031373289635626543228728820602312" }, + +{ "-171812101820192353275910956459431262142", "11401673303315394031728944442295528921842441448377692701102691446500671963119794838260543877466107345474902885032629120622020177051592733148817057943390167845763358795044702079370835841331467130719834250134674578757640577473495192331790176510774020541399177011446664359866582351045889299070080989390219063301859447807907203943168891690028442190793548699886572720360741686677780644932612683647303776634496172481504075784427704287335805355801794320914944330891519283383694196486986108936857630373759865062862204149003789919218681050221366182434949855054760827976853645027544605870235074909890698574792562001595287630131", + "-11401673303315394031728944442295528921842441448377692701102691446500671963119794838260543877466107345474902885032629120622020177051592733148817057943390167845763358795044702079370835841331467130719834250134674578757640577473495192331790176510774020541399177011446664359866582351045889299070080989390219063301859447807907203943168891690028442190793548699886572720360741686677780644932612683647303776634496172481504075784427704287335805355801794320914944330891519283383694196486986108936857630373759865062862204149003789919218681050221366182434949855054760827976853645027544605870406887011710890928068472958054718892273" }, + +{ "-243638660221338112796448050030955119997", "-32214383478080953899491069562585164652288236626686985994647827422262342469970423345510055643470262764747630363450204055220886177681745412924556264758690138113272748656941509018308925555317383307928766093730384151056027828368474245304944063213926492719166086055718735381341569379006804236876950175122702350552198046290567043195716369691666842524594399597143281611765509174168738392889075290806378316647736667077047013214732267367344808724905727602402784621437141760604478301412768904784950365257469208085143467704875589485635570084387755189599791857576855454112556762755762408826226326879491415484319411662301650468948", + "32214383478080953899491069562585164652288236626686985994647827422262342469970423345510055643470262764747630363450204055220886177681745412924556264758690138113272748656941509018308925555317383307928766093730384151056027828368474245304944063213926492719166086055718735381341569379006804236876950175122702350552198046290567043195716369691666842524594399597143281611765509174168738392889075290806378316647736667077047013214732267367344808724905727602402784621437141760604478301412768904784950365257469208085143467704875589485635570084387755189599791857576855454112556762755762408825982688219270077371522963612270695348951" }, + +{ "-126332081511349770866908261827634312283", "31497387372874133218238910173378055967910722258532087598053588964599898753455370244114881403020152175272452951858324158004662566613339529101292284073176382818309096142522412043073218657587031893636358434796164444941535757484360125937835242214199979245499374972029624710574236962978707708765065292759037309958875006017588240959790355958632745299212449602934380927677385974488564420550408281673927387615657765312151272852486266800510090872812376232597458154951925709496664568906509814364388823105469855516803225244972466742963619633076158367569109107733990828830121948130235858799809203410103682003414364238243553515261", + "-31497387372874133218238910173378055967910722258532087598053588964599898753455370244114881403020152175272452951858324158004662566613339529101292284073176382818309096142522412043073218657587031893636358434796164444941535757484360125937835242214199979245499374972029624710574236962978707708765065292759037309958875006017588240959790355958632745299212449602934380927677385974488564420550408281673927387615657765312151272852486266800510090872812376232597458154951925709496664568906509814364388823105469855516803225244972466742963619633076158367569109107733990828830121948130235858799935535491615031774281272500071187827544" }, + +{ "219979452670016849533060110266815720199", "3900115048441644499033281842448985956665866771934663536385503692700586024397767816761943054115584011069129310718114010862034970648115172218305599786238607524420973404711138276011261135403209178420948996472570042497859127324157786975578751148348046315727383390370594954695454631662061021971027739429505825056455676233533511412589936865597034183410893428831818716136282201523804692574965779771140320669492229416601369453681528301333865290947482219850340728455965391492610516639151652595539203632139883064874286555941718154489936421274731413286355640404192677546692090304496817063325766995908926108582896362623757323811", + "-3900115048441644499033281842448985956665866771934663536385503692700586024397767816761943054115584011069129310718114010862034970648115172218305599786238607524420973404711138276011261135403209178420948996472570042497859127324157786975578751148348046315727383390370594954695454631662061021971027739429505825056455676233533511412589936865597034183410893428831818716136282201523804692574965779771140320669492229416601369453681528301333865290947482219850340728455965391492610516639151652595539203632139883064874286555941718154489936421274731413286355640404192677546692090304496817063105787543238909259049836252356941603612" }, + +{ "585873325961105129055557280004608765382109855007674169500308242261038324959928764512890600512016613154122762798104714052579267789493643522748210870974797", "-1855792162818946202", + "585873325961105129055557280004608765382109855007674169500308242261038324959928764512890600512016613154122762798104714052579267789493645378540373689920999" }, + +{ "-3026050092505200332789765255096964033685859497096213532090644235603419347590512426830117415222669642053441336442247132403948783838396746566100575461602162", "18009081534399282710", + "-3026050092505200332789765255096964033685859497096213532090644235603419347590512426830117415222669642053441336442247132403948783838396764575182109860884872" }, + +{ "-11124638695599888462310706699308855434715251048597328942409434888923094027849143412724699165971400546471660924330688750607774759764580214088920441698992069", "-4827559068742614723", + "-11124638695599888462310706699308855434715251048597328942409434888923094027849143412724699165971400546471660924330688750607774759764580209261361372956377346" }, + +{ "4950293428090696283711882613183655723616682297360442241017758383241177602498881186549809051670562038601658285833496694108818253845693871318067007752043113", "17597810481352184048", + "4950293428090696283711882613183655723616682297360442241017758383241177602498881186549809051670562038601658285833496694108818253845693853720256526399859065" }, + +{ "-5733769947958740467479139247420201065087494801172241127791526686385518674532830661413722661802560247463032020003355494614502034002778775472609306735864748", "-3892174127829225880", + "-5733769947958740467479139247420201065087494801172241127791526686385518674532830661413722661802560247463032020003355494614502034002778771580435178906638868" }, + +{ "8320894458193427045187598554188178307429755504967209344418448624882517461814957461249858674758807195827056824653471934409067429988676743031117653237018365", "-12861394200627120797", + "8320894458193427045187598554188178307429755504967209344418448624882517461814957461249858674758807195827056824653471934409067429988676755892511853864139162" }, + +{ "13033402737450594044106258936169013897237368708138118260402180886096095497725071502601849887805439844083105685971731015312020770945603825344926844435936044", "236396022362585261770052671762207864597", + "13033402737450594044106258936169013897237368708138118260402180886096095497725071502601849887805439844083105685971730778915998408360342055292255082228071447" }, + +{ "12170667278114656173974716189098171384426379753661081475485441559687661443127166543908925678856145097632475832903680828294561265828775791256812588754280222", "-276673555533799047589626400978981416789", + "12170667278114656173974716189098171384426379753661081475485441559687661443127166543908925678856145097632475832903681104968116799627823380883213567735697011" }, + +{ "-12755594876262399860618168642932232021734362385933348033134635580177924615701078617214764415318471507488803810365565826229169313660087149542130819663319659", "-157671440495648010763311068579191828684", + "-12755594876262399860618168642932232021734362385933348033134635580177924615701078617214764415318471507488803810365565668557728818012076386231062240471490975" }, + +{ "8664063140780163008577373335591938905735059211566906376953760862047748343846207426667781783874718320339071949903053785280430612875488847226724390758938740", "54361107931665215623681874454167019934", + "8664063140780163008577373335591938905735059211566906376953760862047748343846207426667781783874718320339071949903053730919322681210273223544849936591918806" }, + +{ "3699576825118349347309026261327541749454660339251578894574483235547605815416603169143590292164644149607672871236942391817131531474661895913650810587431606", "-50508350367572393968128467319633674717", + "3699576825118349347309026261327541749454660339251578894574483235547605815416603169143590292164644149607672871236942442325481899047055864042118130221106323" }, + +{ "5626548453644136572409808769267055618695663227750732922630041368983808478347120771651822300668480671524976882745306794511840379704578900504784165956486985", "170502882789371639987361620116696459267", + "5626548453644136572409808769267055618695663227750732922630041368983808478347120771651822300668480671524976882745306624008957590332938913143164049260027718" }, + +{ "-10859007735074693411217019392659638207496329895257318665547454149984863458541990037760564769787816800806064437172810158051442267508476778676439633382657890", "-7558060977666720080449823996328496253877735754811271086853901493753796001778345391546991917892931500169890406340928835457635973812901681485438886367096185", + "-3300946757407973330767195396331141953618594140446047578693552656231067456763644646213572851894885300636174030831881322593806293695575097191000747015561705" }, + +{ "9842028993407961669727766131360795288615020071102475108883839785397865740828387076847892646234215787999498419839351470775471313077046438080666908734795616", "8259939762466350877481193620364896193464602165170783019804380181692322874550956777598992104871440502758410340359413403619753571535498118388286469082729503", + "1582089230941610792246572510995899095150417905931692089079459603705542866277430299248900541362775285241088079479938067155717741541548319692380439652066113" }, + +{ "3122315115429970622394662815735050825423438028108957393747131991771456957037829402044934484343765915727397519247940959221091465331254497476137639859816450", "10737995515603450913722681305571315249864367824351372254572936648132763616823019940208526402092654554035074813865303483747097673960803093638463005072804384", + "-7615680400173480291328018489836264424440929796242414860825804656361306659785190538163591917748888638307677294617362524526006208629548596162325365212987934" }, + +{ "11618335890332522671268040181306950825004789685088262996478365976802329054158653675768163009290064139158450983598701977173152384425333441365287895694522192", "-13130287008197231017935223399369698658354829835061356451363818961959486828237111511740029441613108087354987794332115218978284937263725126538295501305403242", + "24748622898529753689203263580676649483359619520149619447842184938761815882395765187508192450903172226513438777930817196151437321689058567903583396999925434" }, + +{ "-4829477140897377009195646150061276059814366801005389903693533021027427566117360765323647260121062827801190746646296803957067548167571028717513392985791293", "10716557117391614298810040587314742187092120526669273567183969821384063434473189717686678450880765426943205955814024872764413373364846268902370055526485180", + "-15546034258288991308005686737376018246906487327674663470877502842411491000590550483010325711001828254744396702460321676721480921532417297619883448512276473" }, + +{ "1560421244904974852620371975782132605421448226892487453928759432083522187778803424020804578027100625536441377609275030418285893555753560195716001014786650", "-11797558308994912054526619290334311429749533070145154703018977152548370444659962978040151671210413666186432921816690953994784423526183449271023503069393845", + "13357979553899886907146991266116444035170981297037642156947736584631892632438766402060956249237514291722874299425965984413070317081937009466739504084180495" }, + +{ "-7701347923966912534344428538744620884561375267012102797292378941649984539207353887059064943586048644516121387166836442084007442716291792933061162738380376", "5290969389374230541016502448421359606252744677802288901830045825873182202718418905866055323957065013553046698199939002159982374580735362593037515863844280108947533575824820196689891621498006303535207762625068798755031433921940066544809959896067184147997503827988613858484669349726945188167613248195147619673963531690938913245110754715059472477991342216448470339490385593605806518967792963339193162830698488489270925945408227996742278697477358272529028932771642478870844024835907350391770605391526921411004262446196112836319091260967898895009427182171643279100998182191816962677328417390867021108292139204864164048286", + "-5290969389374230541016502448421359606252744677802288901830045825873182202718418905866055323957065013553046698199939002159982374580735362593037515863844280108947533575824820196689891621498006303535207762625068798755031433921940066544809959896067184147997503827988613858484669349726945188167613248195147619673963531690938913245110754715059472477991342216448470339490385593605806518967792963339193162830698488489270925945408227996742278697477358272529028932771642486572191948802819884736199144136147805972379529458298910128698032910952438102363314241236586865149642698313204129513770501398309737400085072266026902428662" }, + +{ "9733743430220591762422540139212426729307515492818443460852332805653889275463385649305231919846970974905736816260992940027028218064265519723018527155353151", "-29407855293830047984154639411082591337348779678279017647951764366455421210163494489475996514661359700145916243499452007595041420522019751347743105082745321262372977262641488359297167392118038994384136863563032667040671405618315550876997904307423736276844997706938133936081058323434935833614475654922773162140266784233792639117145232791514703532554345086520312281500696798706889025860427142771458666376271994240028586899592254884476941388776984078337603148583453255593120138178690189726206775893096279000909079330468718593887702543025737308336025198677457129910473491269839827087491228569718246503140134413881896746751", + "29407855293830047984154639411082591337348779678279017647951764366455421210163494489475996514661359700145916243499452007595041420522019751347743105082745321262372977262641488359297167392118038994384136863563032667040671405618315550876997904307423736276844997706938133936081058323434935833614475654922773162140266784233792639117145232791514703532554345086520312281500696798706889025860427142771458666376271994240028586899592254884476941388776984078337603148583453265326863568399281952148746915105523008308424572148912179446220508196915012771721674503909376976881448397006656088080431255597936310768659857432409052099902" }, + +{ "-276731217243271862683214238489380950428392903790808046630969592255272629537001990355375434170910931115552132394269672247616298060929507021008951190291387", "100289083769237476480554074865040988004216167545459907207847010762380733541100608695693297149249375537088329431700364201275915507683345148401600569951338052791424407090330310974243070931256108167365334162914085216447196038922091547331474328250886730614683299908003398886233860613008266913065047699535081030427106800418656336608005860846045905149012346378286475449307630537665901621055008855374148058291266835796203075976592585729940879567246284967856356337849150102261744547461816282538319258966892339056695718919291240188920586288417893106046698069355647145603908383687239983874164793005765733782432717429040621674", + "-100289083769237476480554074865040988004216167545459907207847010762380733541100608695693297149249375537088329431700364201275915507683345148401600569951338052791424407090330310974243070931256108167365334162914085216447196038922091547331474328250886730614683299908003398886233860613008266913065047699535081030427106800418656336608005860846045905149012346378286475449307630537665901621055008855374148058291266835796203075976592585729940879567246284967856356337849150378992961790733678965752557748347842767449599509727337871158512841561047430108037053444789818056535023935819634253546412409303826663289453726380230913061" }, + +{ "8505070389896098095621766692413480203366379968950158493268895987250690600795955783113900096527432416791184386061684833478921638080978014176210898461637606", "-16410711613672171332126342754193842244915477287016327757357714698751777287458963458682349581881560880814595167244857846847668988374679430572782121021084683986742283012573569894084166107235597351093334125816075658348307113218478800035703971671113417712009419861470917307849916674203301497919242668373376352901312309673053175315189945730756118172940886476343290174961420986113367531057713782438374928471960914578818951372282574754612716278516397754222547513576728677459134022062202283647690649100602260948409511070624300011106517649666031530376191755817891213910847547809248990517666613043010292627100428536737652546738", + "16410711613672171332126342754193842244915477287016327757357714698751777287458963458682349581881560880814595167244857846847668988374679430572782121021084683986742283012573569894084166107235597351093334125816075658348307113218478800035703971671113417712009419861470917307849916674203301497919242668373376352901312309673053175315189945730756118172940886476343290174961420986113367531057713782438374928471960914578818951372282574754612716278516397754222547513576728685964204411958300379269457341514082464314789480020782793280002504900356632326331974869717987741343264338993635052202500091964648373605114604747636114184344" }, + +{ "-12618010259109779267590315037969998053964054382853891516547435925972388025118492931596200697357628900783311183940584302426381939302632641549019984810957030", "-30500906828861638007306362171210132987300359439962044769219457463653547834815716264412200930088623097530758080891972640000479943534665059199377729854850415258341537838023739964147532129877743393965857370995558748807382396090020006195649251292012405690725917389684473999400905751109361754679152179983739269026226054012963756892488872262522587481931950410504651253101938824790285623805566521723062029033001745636445860437154344665483641408727637784045030118212476306906983993748299291616038887011943864441807818857508443930272872365334665976442185494702520760793786640113779099219233665607521784524244604432396247693263", + "30500906828861638007306362171210132987300359439962044769219457463653547834815716264412200930088623097530758080891972640000479943534665059199377729854850415258341537838023739964147532129877743393965857370995558748807382396090020006195649251292012405690725917389684473999400905751109361754679152179983739269026226054012963756892488872262522587481931950410504651253101938824790285623805566521723062029033001745636445860437154344665483641408727637784045030118212476294288973734638520024025723849041945810477753436003616927382836946392946640857949253898501823403164885856802595158634931239225582481891603055412411436736233" }, + +{ "793528769616879938852241178439496352527042950647521648629732169156958768358523029837406526207126598190786120139491813624819360632811627576064199559812277", "-7357484069649002655190557040768215614708659708788999334802985986235721030962928900092675952032143512196279092521450986819067071570862007086586132687661085824939677603953832219860573980632016025218580608321648907608385784471745482257672314890331358256478273312255285010343369949412955387472116587504557483184506548209831317705115523967163525846685455369176657510129844566195941925821733027993620517287411895496215426174909366458092382652675628195464969405904518323018004882611048769247228828875493680284766874334247375868318795940759082324831733175858991629741478124633015067484305547002438816473086042218906532116413", + "7357484069649002655190557040768215614708659708788999334802985986235721030962928900092675952032143512196279092521450986819067071570862007086586132687661085824939677603953832219860573980632016025218580608321648907608385784471745482257672314890331358256478273312255285010343369949412955387472116587504557483184506548209831317705115523967163525846685455369176657510129844566195941925821733027993620517287411895496215426174909366458092382652675628195464969405904518323811533652227928708099470007314990032811809824981769024498050965097717850683354763013265517836868076315419135206976119171821799449284713618283106091928690" }, + +{ "30958566711373255787092081401292877738974978442987704470984765018293851031728996862405055424093249924047528792113585028592262445810946419909807061004531455817427671594281537965628880611732831524185850161910304038646992464838306728350704966234151134620041799373762432970330864023007632010865749239024802839173884778578927209741320635135275002489733299806669933393428518104197594560039136096527206600870299327752296492029012993590212340409989598323540081430189567580333356380487749078595746626408529223195894600223743978246922817054226858311823994547784553612982586322603593335538875728113115443554199017672360091721648", "9164115638960783470", + "30958566711373255787092081401292877738974978442987704470984765018293851031728996862405055424093249924047528792113585028592262445810946419909807061004531455817427671594281537965628880611732831524185850161910304038646992464838306728350704966234151134620041799373762432970330864023007632010865749239024802839173884778578927209741320635135275002489733299806669933393428518104197594560039136096527206600870299327752296492029012993590212340409989598323540081430189567580333356380487749078595746626408529223195894600223743978246922817054226858311823994547784553612982586322603593335538875728113115443554189853556721130938178" }, + +{ "-22540807692474380279530794404584230073523360203115293035869063366926380719566516089428840111682263403627532047214106171892715667227836310498366393991106231487046533598391969789120283294510723096483520917309134391072655861112766764278247568027435618337967113341863713181603534251049249873125130781073437913954718595729437608729446837417196899902194261111827656247095442897532040935029872731410799530408713850806239149348700486268275019296069828199088780767614008685960242354118969741283398882689239770114582524756296906388861630890288875920861344939520380841337675934551587994259348267613541166769237154904791412049964", "16928681651977808800", + "-22540807692474380279530794404584230073523360203115293035869063366926380719566516089428840111682263403627532047214106171892715667227836310498366393991106231487046533598391969789120283294510723096483520917309134391072655861112766764278247568027435618337967113341863713181603534251049249873125130781073437913954718595729437608729446837417196899902194261111827656247095442897532040935029872731410799530408713850806239149348700486268275019296069828199088780767614008685960242354118969741283398882689239770114582524756296906388861630890288875920861344939520380841337675934551587994259348267613541166769254083586443389858764" }, + +{ "-5403850875869356031749551669837202919756114555261706106905659104903792701565965475066159243529680606410723686422444947172225540145977333194008702465610630608545009270872541652430806931212184915840724378685979865349848151917650322286497417985248678815214889868576385900691591784772762893647315325310416150353725001943778473686980157692817497562783521120544549784746647104651038037129984152623720529803205580894126664077380391379306511348324442512538418658728022685805514196592544294177914956734669359073791151050869328577099869772182315103156047405800398706114122356939316464974680113324979723289916823063616573634058", "-10755560408227106818", + "-5403850875869356031749551669837202919756114555261706106905659104903792701565965475066159243529680606410723686422444947172225540145977333194008702465610630608545009270872541652430806931212184915840724378685979865349848151917650322286497417985248678815214889868576385900691591784772762893647315325310416150353725001943778473686980157692817497562783521120544549784746647104651038037129984152623720529803205580894126664077380391379306511348324442512538418658728022685805514196592544294177914956734669359073791151050869328577099869772182315103156047405800398706114122356939316464974680113324979723289906067503208346527240" }, + +{ "16201587974698660164372991183566748501003872177894450603471850345714117528335101264234127789041855420954511595895378320972957964222386731614839583078498685801156670229700092209313747849610762975747730086443186821337319452128253859293962343891549207804191088925361935683615063225197130192492652062735684739784075955094308092423304262201429421582566117390598395895220976999990205945523225411701169301910362640419341608407294018105959688929256136725564385243617240412649023368133778798063226772467915584333795357813292935080009919284755332034998122912861893282865727947810588086156919649131720183722427134042574317487793", "-126159569916621842", + "16201587974698660164372991183566748501003872177894450603471850345714117528335101264234127789041855420954511595895378320972957964222386731614839583078498685801156670229700092209313747849610762975747730086443186821337319452128253859293962343891549207804191088925361935683615063225197130192492652062735684739784075955094308092423304262201429421582566117390598395895220976999990205945523225411701169301910362640419341608407294018105959688929256136725564385243617240412649023368133778798063226772467915584333795357813292935080009919284755332034998122912861893282865727947810588086156919649131720183722427260202144234109635" }, + +{ "-9976758107386398142455037422077809088581080675608340830198269021688955930541332630075972471934165382030070969307731206728197760190279942894255740733209190331510591013089699837164445642396864912572863786290237335963836376543389815671640509582958465164874961381137096877288362944469137669502842448492172241151419831252572392809173900377271652074261706120638052379886108764460001026094198502028776365675088466580595870167840105746912975236851293882732079317535103041585285239081516202482201377111734010788198635874359396626004300532752450289119192633850562141516671742961938277967783337559307443617308447853505824391099", "13449070890444925581", + "-9976758107386398142455037422077809088581080675608340830198269021688955930541332630075972471934165382030070969307731206728197760190279942894255740733209190331510591013089699837164445642396864912572863786290237335963836376543389815671640509582958465164874961381137096877288362944469137669502842448492172241151419831252572392809173900377271652074261706120638052379886108764460001026094198502028776365675088466580595870167840105746912975236851293882732079317535103041585285239081516202482201377111734010788198635874359396626004300532752450289119192633850562141516671742961938277967783337559307443617321896924396269316680" }, + +{ "-8570952518585194406209873586517687582701183275108243979199329595605282282125006489076327154374449108678257552384372919282846744626955206382078850958298637157198962032090439427286914716782317030245513658212430127586764421559372214829010306717557679285031617989735914399954286846456953917915955558448774972943731602144914068097214910567329340361564904028964471241318105967747431610163083002382821902859161510204381788262611298660559327478615315484763561786397041779926288206767156863141140852268323253657685018587945456372648431446464389004257999049529945532453598011773843788498650935959375182414447893892341891463988", "4431555062692055371", + "-8570952518585194406209873586517687582701183275108243979199329595605282282125006489076327154374449108678257552384372919282846744626955206382078850958298637157198962032090439427286914716782317030245513658212430127586764421559372214829010306717557679285031617989735914399954286846456953917915955558448774972943731602144914068097214910567329340361564904028964471241318105967747431610163083002382821902859161510204381788262611298660559327478615315484763561786397041779926288206767156863141140852268323253657685018587945456372648431446464389004257999049529945532453598011773843788498650935959375182414452325447404583519359" }, + +{ "4117976000917214601143188578494558474138167055110060832594841842655428229500889876131794484851166401425675703592388271925904534237338595998991043982676292549088043959446082382516734793718348862105938692342851330680670593768890094290655852108130945387988863730762717733881418314989528719379494082656897158942547008663543153236129762264443358316776532465284014215413819415615612452225913947961681691310132286840303081453109375175436902292224029179426794714036524361081174901146731799945483243427138748119832116750910126386838614645397770107366925613473924955965862778639046707637382775371488874447622330992324750207465", "329466253508616383200261654231797136951", + "4117976000917214601143188578494558474138167055110060832594841842655428229500889876131794484851166401425675703592388271925904534237338595998991043982676292549088043959446082382516734793718348862105938692342851330680670593768890094290655852108130945387988863730762717733881418314989528719379494082656897158942547008663543153236129762264443358316776532465284014215413819415615612452225913947961681691310132286840303081453109375175436902292224029179426794714036524361081174901146731799945483243427138748119832116750910126386838614645397770107366925613473924955965862778639046707637053309117980258064422069338092953070514" }, + +{ "28857935543824608075326348244201981931023939250259142606733822094071772153858420201297951828741003977413353359215638528196235956061529059419904405354390715114239219947402126760298132539402386106279333968395498788354937020337343839325588433318100331044091923709732742795159387846354148919054314582749477292946200912006940503778924320301062789466388997936618573519744795661160190636101768486096961991215006236190655062992372061052426455063703038765465688361316141792840153608145888307784845264037109867657483109819380082597605481013612040648149090345778910883349230476481347645708269410828528742743794495302359380494607", "126536164564464424337714470705049463978", + "28857935543824608075326348244201981931023939250259142606733822094071772153858420201297951828741003977413353359215638528196235956061529059419904405354390715114239219947402126760298132539402386106279333968395498788354937020337343839325588433318100331044091923709732742795159387846354148919054314582749477292946200912006940503778924320301062789466388997936618573519744795661160190636101768486096961991215006236190655062992372061052426455063703038765465688361316141792840153608145888307784845264037109867657483109819380082597605481013612040648149090345778910883349230476481347645708142874663964278319456780831654331030629" }, + +{ "3146199586408378667812619157270468624370984629500707476575291934586478540055436137993431548830607708293475788354970610669452058906009873485175438772484599603993015239438297747261356407887781450787482447252615210880612867127689283653562498484594955015919746443263740095372831444793239911996227663006098501180972347442107190398034048225264564325230296723559400768342331039755765597288518435463475921534765025262262798267314969774604439319964638461636007229819888743218820584570149249791727508891676067767073852694327748467914037392778283816153183422263956621516748627574334199731850712255885395479903525322397561293553", "-169494171680584797187706369710105239124", + "3146199586408378667812619157270468624370984629500707476575291934586478540055436137993431548830607708293475788354970610669452058906009873485175438772484599603993015239438297747261356407887781450787482447252615210880612867127689283653562498484594955015919746443263740095372831444793239911996227663006098501180972347442107190398034048225264564325230296723559400768342331039755765597288518435463475921534765025262262798267314969774604439319964638461636007229819888743218820584570149249791727508891676067767073852694327748467914037392778283816153183422263956621516748627574334199732020206427565980277091231692107666532677" }, + +{ "-17024716654716744558842421452239026542281806678754026383430912733874686056449261218428541803113383766132449624540209841726047308927951820311213785345168358108138304716549475322223600292513384537980742126687035576531330089447100646214364923043445903103768701639992829171572718403272488931980504461938688955457870904289239032709146514866818331202329982821151580491257491540240579366183525075936339515949345815704583685855315810611089822402567649542290589282153225725537026309623090382054078872576985425957096858376112688308214148412270019118710904983829984589093557307164347051152307499446188262820058714564165108542508", "-26845770031559702758807696432929071597", + "-17024716654716744558842421452239026542281806678754026383430912733874686056449261218428541803113383766132449624540209841726047308927951820311213785345168358108138304716549475322223600292513384537980742126687035576531330089447100646214364923043445903103768701639992829171572718403272488931980504461938688955457870904289239032709146514866818331202329982821151580491257491540240579366183525075936339515949345815704583685855315810611089822402567649542290589282153225725537026309623090382054078872576985425957096858376112688308214148412270019118710904983829984589093557307164347051152280653676156703117299906867732179470911" }, + +{ "-20875354448001792153279041347864644172439177882677780548397567327274288309764204295853633150227327732322157811413794613378828291977852467550695289535036337326494269114787031260705326469002279939986228049380615128280814933748700667874022724707001736732724010699175779382411342385842744973636495738468838244099596215421975861650998954057316519632062827510021706536194961332185926551767127180751211669386674770139039516623606727799489291663572125587356845055646322930167536458093283930082765496058330805117442824718962237069840252138957395570892073194575112213410604881673785921789655406716271370732069643455590690035701", "-321447426701397438572265325285879998363", + "-20875354448001792153279041347864644172439177882677780548397567327274288309764204295853633150227327732322157811413794613378828291977852467550695289535036337326494269114787031260705326469002279939986228049380615128280814933748700667874022724707001736732724010699175779382411342385842744973636495738468838244099596215421975861650998954057316519632062827510021706536194961332185926551767127180751211669386674770139039516623606727799489291663572125587356845055646322930167536458093283930082765496058330805117442824718962237069840252138957395570892073194575112213410604881673785921789333959289569973293497378130304810037338" }, + +{ "-6750548706930727136186675393752693335334383613941059024795513640678178119089262068912855951615043660442324823673049951182143778744824110223137384940032268718291241014850714197673735719784663896993460156686600813524168487673234842233781654493200950459723884918456280719440022930492599128086690014332139955274261568563155723011697763382009890186816226119314994799655369791620499988988986590903148198659095740939986627235565633349906453726759224441608018598520571182643709143072528030332708598472074166415467718451869993686505339408706320298338691467040585228617379086727764240955696690287600957842671916189752415855520", "132223863177855649509430852484092802671", + "-6750548706930727136186675393752693335334383613941059024795513640678178119089262068912855951615043660442324823673049951182143778744824110223137384940032268718291241014850714197673735719784663896993460156686600813524168487673234842233781654493200950459723884918456280719440022930492599128086690014332139955274261568563155723011697763382009890186816226119314994799655369791620499988988986590903148198659095740939986627235565633349906453726759224441608018598520571182643709143072528030332708598472074166415467718451869993686505339408706320298338691467040585228617379086727764240955828914150778813492181347042236508658191" }, + +{ "15737797902964168014939893286340956118635524170934156177365242966267432695262586636031957242055461736359478270642576860414422844075672388559647477705484719667060463718865742735598799928335211410004369240278699196301127699945374217439676378682879115442203681638050752745036508637214733712716867800216723838016099572951915042604603457902610639317648800296497583507890473114507231814851908526534709496988648572353272479026750068932474334642929727977996779536604912743446197670724757690108283368934769626461285961947257397454619164856011847736479229692086038931510067165282571276049292116713101550911614590774659556899356", "-6114512833799784097991148713266650451765474382378581896952003894922931741133332233338460555227243451198289670274036744955599177213449957470212981501678055", + "15737797902964168014939893286340956118635524170934156177365242966267432695262586636031957242055461736359478270642576860414422844075672388559647477705484719667060463718865742735598799928335211410004369240278699196301127699945374217439676378682879115442203681638050752745036508637214733712716867800216723838016099572951915042604603457902610639317648800296497583507890473114507231814851908526534709496988648572353272479026750068932474334642929727977996779536604912749560710504524541788099432082201420078226760344325839294406623059778943588869811463030546594158753518363572241550086037072312278764361572060987641058577411" }, + +{ "-26633154627863501044020127597209297142657179797586777727331879111280843451446814109347357601013807189824906954310855123313836812409388745541128842840054310853220032505914307470215180950497357091093642400638925719682307925365402618310180378684705799724964274776149984064608716300479893889145492885897234574442542501896696821902329473018442082678749291668341477914681413039643187020003425962922948452894682558162414623956491734656939841377698702802567258906642912449969621455596132708975438173455827361542712483153981422051943690720556013580161324856788091093465837542336129629269227369781823515673967591796132853515009", "3321161637038961370471515250185392889390643163295535903347391615170504064647249127732639364682803744773593849851778894972403397573953564801884397178069327", + "-26633154627863501044020127597209297142657179797586777727331879111280843451446814109347357601013807189824906954310855123313836812409388745541128842840054310853220032505914307470215180950497357091093642400638925719682307925365402618310180378684705799724964274776149984064608716300479893889145492885897234574442542501896696821902329473018442082678749291668341477914681413039643187020003425962922948452894682558162414623956491734656939841377698702802567258906642912453290783092635094079446953423641220250933355646449517325399335305891060078227410452589427455776269582315929979481048122342185221089627532393680530031584336" }, + +{ "27668394897866653012794531261739800318882766882548843941974485394983434533400277607364280566269718161470415771058329222680901477416257843578362127708934184467195154000133252468684612556324066063725677629160438683034201285122508880444372096430021219637788794365539396242345208611990491721052691567092029622640533057073151980959055665792776356282961971341363712186503783566960850166774438868528799819047163739437906559674823146932668464230936946321915236658512741918196732794332451120218658490129307932187658010681746557120172585093207839141764683325214902696969028472942954863209641597556494684135445935915485525220911", "204625459185084436546676461283890328511903949966691877662249903659689934813784661695047569885195881142676761876303280806728760511429260843727967794322777", + "27668394897866653012794531261739800318882766882548843941974485394983434533400277607364280566269718161470415771058329222680901477416257843578362127708934184467195154000133252468684612556324066063725677629160438683034201285122508880444372096430021219637788794365539396242345208611990491721052691567092029622640533057073151980959055665792776356282961971341363712186503783566960850166774438868528799819047163739437906559674823146932668464230936946321915236658512741917992107335147366683671982028845417603675754060715054679457922681433517904327980021630167332811773147330266192986906360790827734172706185092187517730898134" }, + +{ "18944451653774463090918576081661764936021793389045063662102219434278236461286997354190032851092512146937346521704215170240383659165117708716738711782597164244188741818096207452074083439983059414271417130274747048227795964884943105011205424198661201055104372863019759130697888820715782179466491256695453118035286889359217448004524564796840711987314064158194625731263591557915838970249677548534895064545467992194029425250039951132361639559343536937119283951538321037694842089561504643350632756961329867761604760788760440497535611072991056505806805291706178639395690245460397975614715123591611301423752799666149495108752", "994321141213369910357526037382331323092462599623554452705525887587326552002660849455542761618020243106424015447778226642816634338781654345001677083881111", + "18944451653774463090918576081661764936021793389045063662102219434278236461286997354190032851092512146937346521704215170240383659165117708716738711782597164244188741818096207452074083439983059414271417130274747048227795964884943105011205424198661201055104372863019759130697888820715782179466491256695453118035286889359217448004524564796840711987314064158194625731263591557915838970249677548534895064545467992194029425250039951132361639559343536937119283951538321036700520948348134732993106719578998544669142161165205987792009723485664504503145955836163417021375447139036382527836488480774976962642098454664472411227641" }, + +{ "-25075128489482657321316021943980016828761861550379828525731288423212311433274066958090940464803020097932875912251380196071686918459370667428905844496548191635733867314315152547202859654044591981512687559437417616479425752991419002108503390319869665933757684966460526631533822984311725217788657567199485442486045019468844265484117570385156844404625735176559901986920712550964238722824122000259551821135404274194791706113272773768366572120227974096419295159271316157215551931810740200836725504693738229444336470213883741520460842708733150362983831267583568258736572295448486287825894301201018490203520738439038977754991", "-7402949251688548738762242219263594861535354011996392637087346760786292549376145193266590582054224293289596877537643409310483743293801574030358189880866069", + "-25075128489482657321316021943980016828761861550379828525731288423212311433274066958090940464803020097932875912251380196071686918459370667428905844496548191635733867314315152547202859654044591981512687559437417616479425752991419002108503390319869665933757684966460526631533822984311725217788657567199485442486045019468844265484117570385156844404625735176559901986920712550964238722824122000259551821135404274194791706113272773768366572120227974096419295159271316149812602680122191462074483285430143367908982458217491104433114081922440600986838638000992986204512279005851608750182484990717275196401946708080849096888922" }, + +{ "-26509487378481600038412836495388065888781507388737194948728047318975269277448073484403390476243134990463394380967295356958474984927721196047241216945988250219075749832868804186657201899994373052648345989716938779173325348547767647529160988985542438998030764420175306438858518207072038513664360905985908879070216069156102379349899544471658754952888660878997691670566078979940005195987259493512159628198906090101827331841914429358969184839073862821059400943312264269215878469013316796620921077244799814690434355127994011220041638393750697699141479399553359747084811371804524490919966410379714725200415331414459870271869", "-9247155945465656153397925559476432992975541781462281935278489123804934847762489500833913193183733932905776020790478662969835879365116238125565077744775032", + "-26509487378481600038412836495388065888781507388737194948728047318975269277448073484403390476243134990463394380967295356958474984927721196047241216945988250219075749832868804186657201899994373052648345989716938779173325348547767647529160988985542438998030764420175306438858518207072038513664360905985908879070216069156102379349899544471658754952888660878997691670566078979940005195987259493512159628198906090101827331841914429358969184839073862821059400943312264259968722523547660643222995517768366821714892573665712075941552514588815849936651978565640166563350878466028503700441303440543835360084177205849382125496837" }, + +{ "-17010604274474750006607667808593883725990508452473783283717890546525148212376267233909567638545898628257361383837671935903199638230375408397752251127816717091041943873728526445398525706450929660366518707254053655364610471112296477865068960744948010561798109833411657930112293904378353445961131058136287425064317621271289456901138718557297733713446119244533144377470099270824020439428168481914824420861176457152299497728390918971852021025089592998997807574907789524112450146545688385954763667980124432645276563626082835790429598328230426471161191074551543308732791287559033843466623138171520961684959997180979203053477", "-17319079025684619178510812811805110270463447771889107440996086020812918555191263705580533644731591929176480040622705607552852994906782176254877135818109655911838591767583157894999741648979817400330572419476101372927546509769818404491634583907246692993992514876697330603464497645633398167129555001859772111887143352351860130929715392173452396253437927361301990735683539169040916027268831202732178553152351117118606495416985612909248422655861312689027789401950549626643389790516560291620711705848717875304929186131258525831197192620523261738944873398924939726689336762464320190834794155527335576391767307110012289717973", + "308474751209869171903145003211226544472939319415324157278195474287770342814996471670966006185693300919118656785033671649653356676406767857124884690292938820796647893854631449601215942528887739964053712222047717562936038657521926626565623162298682432194405043285672673352203741255044721168423943723484686822825731080570674028576673616154662539991808116768846358213439898216895587840662720817354132291174659966306997688594693937396401630771719690029981827042760102530939643970871905665948037868593442659652622505175690040767594292292835267783682324373396417956545474905286347368171017355814614706807309929033086664496" }, + +{ "-28362352496476494327713713233021518136860402239251781438945998574753662942796270292818595738100959519541952077905620088422871490191217157269435052965329201030095268586136492980900212955645939325800541690754639292707053269767151001292253701853012092829784482071789669480438026889625605099744553642207773753943711175375843649210118677569597324789367425691177169929576236753018329085700397911235750600921874606148324025962628852167093806152864269874177214562322576097931390470469397118268354868919899638376323751276807304678316688836173746719723312665764603485606350244811113608471530958617108833879194264695174468397461", "-4081062111675377984305281082755054920741203741273067094307824323728798665450292976016160959354997082250970415737745853292134965575242789548167162064123232363464302136338349828801951197252612093077640695564825095503535921549690447893467349156939791370286866987224201115453216606688305427702274940837032716124925028835914047967887674858015919302546781010326385758988488478290741665427521820112231266659657169118374988259423444686317389869729817643396097464874333968181509317307320406521221309011946212308190273531009796563611621389720223920155554879800901239072885025170342349379379336047732368458185953903872634982504", + "-24281290384801116343408432150266463216119198497978714344638174251024864277345977316802434778745962437290981662167874235130736524615974367721267890901205968666630966449798143152098261758393327232722900995189814197203517348217460553398786352696072301459497615084565468364984810282937299672042278701370741037818786146539929601242231002711581405486820644680850784170587748274727587420272876091123519334262217437029949037703205407480776416283134452230781117097448242129749881153162076711747133559907953426068133477745797508114705067446453522799567757785963702246533465219640771259092151622569376465421008310791301833414957" }, + +{ "10367142604728811799331249565431331488313655422005202933702176605382043644320209814639311439871418581341534233560256605231366966869093495784665834232350567124110194965198962966795893926025854156729633358240069116588609932539289897499402463770167927610848388138020589286461244557962368497723086593344721146859584146431437967506007518396464517349944129896971137720357645026281243138165214047233258394590454775153944241555543594427555914116439316287902470043292624597940465373006598913770411505099332700167695871387948271302951230983772351549087620538875967635100644404345317626621438913980275970160864401622986870735123", "-13323117602411502623386235160326625769048477819798659261203460002048250420188223753407093545503703207645050883770850457071863684414849353264890601744588860687970804808452855795406182324143949747985869939791374195222513169904228914579995165180964917538177994190229733465224857616114628815752065632238207474599531507602861647623695058640735949593381112671690796335596142010430124683781417828023076027476816068202219709673411776556090962187853799456968290579708094595903778622705850818245685205707447012659247018940946510378371952655457988959551256869060428488498330109152756599450626641948447980234503249330875085656261", + "23690260207140314422717484725757957257362133241803862194905636607430294064508433568046404985375121788986585117331107062303230651283942849049556435976939427812080999773651818762202076250169803904715503298031443311811123102443518812079397628951132845149026382328250322751686102174076997313475152225582928621459115654034299615129702577037200466943325242568661934055953787036711367821946631875256334422067270843356163951228955370983646876304293115744870760623000719193844243995712449732016096710806779712826942890328894781681323183639230340508638877407936396123598974513498074226072065555928723950395367650953861956391384" }, + +{ "-25321281404861286799950777949097462701962113587443565138655462269365151737118518315058035825695270231347401755128007072923189452859397209062457461602335603630181865680063451525170253746137368267674863889514153713728814272332433431604233690200451816570240227260445028630591376891139306370205846627093813889699170594185178241812081296510140572331372738998993116117098817936927692238682202717231675283209016857095739468507690090676681400453024293870135659990528969837132054786661560150259115734877162158755858653364070279937027014730947342216816307219127474721622123875699701715404820384545693058511056735799834754890692", "-15870257059811626693754498423136372480069134596343998984549199283973854570508228359295418026089909378687774627821225399931314225867711515277913855368473873536462450935842786002269065816311054834857109074848803122494252885020527074586145467185882674518032764708782999568002770206995683800833252068328835778749976046128872525287656002968632147457840467536682726059599593635219947081138082647985895437016641903078766878782632503812736486529143041369932038649270950453231711525943737962179463585338023463992816994328519710963267459007592689204838965317062070771191372220277256094361390952025057574056586665509010902583686", + "-9451024345049660106196279525961090221892978991099566154106262985391297166610289955762617799605360852659627127306781672991875226991685693784543606233861730093719414744220665522901187929826313432817754814665350591234561387311906357018088223014569142052207462551662029062588606684143622569372594558764978110949194548056305716524425293541508424873532271462310390057499224301707745157544120069245779846192374954016972589725057586863944913923881252500203621341258019383900343260717822188079652149539138694763041659035550568973759555723354653011977341902065403950430751655422445621043429432520635484454470070290823852307006" }, + +{ "-10064759312484387184876313010284016458560725440641239737323234767636591183611201479885347260175161165340917225306019885202675573016295152797559983194160634880140345743489989007821872426587698574795394887035658449467358615185057180305109018898637903449135520486663185036663238956537895356325733583128141439025002140924158670346599492383552938312402521066705186885506193758499006001382444818328802338159713646715901977137011576113434170842422373328479181457354927400927267448788528116619711184792932525071391797130057189079431487557270366699175956757661488296856660145077706273571985222726397848614141194988258117115194", "-3689074607001776735792882994440038588887963294487080609346609068733026224735369468180206799966728461935654851527895876039403151156669223687679382665269013769686991783531091821265184956524448064027733731862929686596729449196238312997460578818232100254940830907672953344544031914926653652310468671685310332327057444910423081752028857828828473637496272809899061573593874011995802487442092326045415689987885712749026491545159340468151000027397821404233369034594141219014219707193746581364791219277489927025992135462852894714639406751538919395016165215641239054420028872350709704191189169571752512626755385998505584006855", + "-6375684705482610449083430015843977869672762146154159127976625698903564958875832011705140460208432703405262373778124009163272421859625929109880600528891621110453353959958897186556687470063250510767661155172728762870629165988818867307648440080405803194194689578990231692119207041611241704015264911442831106697944696013735588594570634554724464674906248256806125311912319746503203513940352492283386648171827933966875485591852235645283170815024551924245812422760786181913047741594781535254919965515442598045399661667204294364792080805731447304159791542020249242436631272726996569380796053154645335987385808989752533108339" }, + +{ "-4621513851362114851854472268081584822344822740665629177305004335694395719163541988311496405455186973857145245414214464449674464879082042971313025249648887349614046805778335573547862191522938924075560443632614665169520240664970180760364771373836023824195690134618554368845612471858027311791638881380352344527105480173917778084361560336490212845414303819150625355111300877737042696291233444311426721588476948565949641149735838580313236869041013210454558557732497012037162735013212361842433337324577522358968152852532145622765032318936569346015498130151789662274686368870963891262060214274101000058555635785833724062234", "20283847238128227963042817384468009365120280641032764409860857066215336820785816567924217697745867082423864450685360959383940995237907453126362378908108545669654749698030305432673477271848544313029448526561606175059997663752601262173667861202924953502866611309434183496911206954880840674239880495147451496219568787221129244201657487090244435562896841733049066453539864301122516559479757096183362477594406691085946787803323712522074578611082872627361465163804239673539339633332349145205596371287028267780080937728455742966681547897652607170788637996317683436193829274172400558140357237480809582038468874094877651383053", + "-24905361089490342814897289652549594187465103381698393587165861401909732539949358556235714103201054056281009696099575423833615460116989496097675404157757433019268796503808641006221339463371483237105008970194220840229517904417571442934032632576760977327062301444052737865756819426738867986031519376527803840746674267395047022286019047426734648408311145552199691808651165178859559255770990540494789199182883639651896428953059551102387815480123885837816023721536736685576502368345561507048029708611605790139049090580987888589446580216589176516804136126469473098468515643043364449402417451754910582097024509880711375445287" }, + +}; diff --git a/tests/exam_I_mul.cc b/tests/exam_I_mul.cc new file mode 100644 index 0000000..f90d61e --- /dev/null +++ b/tests/exam_I_mul.cc @@ -0,0 +1,288 @@ +#include "exam.h" +#include +#include + +static mul_test integer_mul_tests[] = { + +{ "-1412797070596191471", "-15492755620416346417", + "21888119755986895161222137392796809407" }, + +{ "16686841096925954110", "1491135775021813104", + "24882345731730524499708005167300657440" }, + +{ "13262412958100188045", "-18379071970155621919", + "-243750842254847872704698616507823758355" }, + +{ "889503034794263569", "-16600674457216690894", + "-14766350309325860687849239111838240686" }, + +{ "3148165694020236318", "-11771070679825280729", + "-37057280896113409834434531491271315822" }, + +{ "-4443818546267181727", "-12001052312087213799", + "53330498839175802532024121011435050873" }, + +{ "8305259347214213793", "-229351169208067535459370186456659711595", + "-1904820941859811670566233132773219565154696335396051029835" }, + +{ "-18273334758510166901", "290047155020180552782039318570071650475", + "-5300128759437251944808204783222405076790289915320785927975" }, + +{ "-703280433697652940", "91110448009482115063492795153459771021", + "-64076195390496041906141380919369524419358692517527451740" }, + +{ "15279634596127882146", "-220998726467849290098339792307263567896", + "-3376779786638352686104608499923871317791563686466157184816" }, + +{ "-4472497681184076830", "325612942672822430032905460436166528379", + "-1456303131067722058341139305566346079551678140995111358570" }, + +{ "-6180420673489141029", "-161157288800853703711204405567379740552", + "996019839388256252540244286609069684717518686623358308008" }, + +{ "14044956603588468379", "10163190459901171254101452124764637970005230126310661589196828892266636678427020930101076689732526935899135126391465178494895371156141265424428405590113790", + "142741568963316278148132287599703960511135825069792278910440475692913696263448088587778211787403889397993501704943449376875999977937418748662459138952952917221024170426846410" }, + +{ "2133283347509865817", "10577710515843519541178984366353275630877942729579274295972091544607384358263130633386329706527832990861547566574369528634541156662300858851752195966167381", + "22565253698228972909216255630133478029433774404794962869038558824053350969301054394347471181756471783852326407546652836376109109470959746153989521923555764579738243072315277" }, + +{ "7812722507014599311", "-5055959518947106416800910724733658104378582281318226107212861190073091017493970778425583956006925004399967175604321778956828368132273155364830637407968648", + "-39500808728232764770485117356353304373275127104839804121600969932458363071148383405901570717732548020267052999198017578112731079638156026910705662052515278317807704170401528" }, + +{ "-17560801708050275829", "9842515227842383346577123873881045824143545509071137371075701856197189100217561683579562062872293951325890789283651221922663521213150065638405410634222129", + "-172842458224605375239887212582262805312641302639067963604956593404910080268476692854082531021580381176489626536608405283010496488558204787140272050713264572452317265305619941" }, + +{ "16743386830114877156", "7347065846171565625701636575261347705942035850951855454324853850791855951431141198155170102434274509450315416946729031216385536668189501958761688618635668", + "123014765528775807847206414290825117502032199391400884957413813554539073118943905948723779020186281150198999824020769031248882909461419778092564985979904308229718874140000208" }, + +{ "12697192948029671719", "-11416780209809507417142822520376617951137069007568339428552592261458272400645205700952156716454820410468812274673183389934216970221062627926131479014990611", + "-144961061169197993494569769162151457365959287966302572862364500950127981616038900865036521107816831702945678695331078399461327412574397914795455218447174498277798426197230309" }, + +{ "17005139720743105479", "-29990519259587469661876904501488342396062731024702923152492275204626478246142153608222329335341363164148761307659972897552084842238285026253664841395295138667328930482145590159132144957515157474957872335043653264146346772142483721767458961320947069718037828473530001033848282453826154763424789967441239969918856795769965946388666154136004597297855416503729657013008165049478441197537144135384444157408972370236442813734429031404855591324183846423588871065272526864866155918285777640819778251612915859290336548446745308788013234099839998683451658620461972798204104633072664604846231692505409653434538208644416538994256", + "-509992970306921990341332390474393215554862069848994183152714032617297815196921655222705396130464246880845576204295466273071779248718654338767559016551390771145212884412809612574391658668778295682412755916528976282396155832617323980694289208942491001345059122414240884660276842648466533488559879226195446807748573906940273568334343093922652142252689341425941673567630236228358747411926991658260241924294146562230425295426217833820067881064577380516936937782688004146531121831211284735538742160763820814174631414364095096099434285754767091040812242751724012532803037860394426031234340719537172735695313262283511554154662650333168783128624" }, + +{ "-15877530153400521290", "27863984127681242643954505352420303514833683768731313003271701952957204538094398204984051331105594788039352443762851136101330385230866919393696564428736685568762923746771275677491379334452751710169529933675128178840986001684425353245791752781476028565228371147542431713985092322787978914276414008774443194161599919167210582437024618824616489802661351916633993681556274980075051797120207655478780052593534285265078265845445633803877185868676955831374479850746658711791169579387317321983669227930929736238215792068273805543745311609083833407544342964285215427999724272264458975101474080574470499647168865409458531868592", + "-442411248181132450919255517905812929771246981404050821923231762557171158858876183536414772404562764742655092127161703706239729646027465795612501446223663310668879007072125975886873343449629108246953385822769744013416908613100114754904323190537317463286500657291202287742354250227377164455244103312266617146454847578457073139633297517170508179596166314955134347046515455569689877574427319658085169791949003021426613961459610227430636932814700361914589752207776142403364490846294795496119883683491811246550808038342285518518431538295199537270236275774546666026424361019715280652576803278928827199810150387207105149968313623040090578323680" }, + +{ "-14162897687527555611", "-23016403916121951319848021112075986869602408568431399211927062304968548663313037929311574133954267816204873252195499803324830278637331653769648377216095499136975244697758388851688873078022850203685120154634090802825656419418077380419130449990938627982123188424119187922828250625318327074513352279785514062876718714640725789938556578327139793467832731546881422469843509318627826856881082450937188956068348931459011923844607158528494902828851692203126881727638511348944908726926619613375594042390434147948508706733126737304560579515324106834237197081860910657003346633962662773394999353766192391746258372744063777808796", + "325978973798843759388794644178802841408656469654887121096165875654577046313115917671847505813174070119516580105483409446057747653173640660143855580491229746795572929387698247460831363721394707501497262525550824977473864621747159715947297817600227665840640555029633517390896890601028716769035575763283168066843141870124768085499453574902575378368669494153555135898430469356384416638130459557518713454927909937610851489821263029886989981438507377741962130296498574556444168140838201069779040087521405032426995145166201901368032136008107323350679784004016321425234898132080844200202007395427054392280809376612533414505539109579739614954356" }, + +{ "10844738523441551664", "13010289169828379103330191247192587220592807931898339555723704078985668371901953113936581573750666143303899278973814509164982887504269303358034042953769514772858989849512527461308415676004712388964136857232374888643347097138114199889581495448978914022318770898259317738823514820591042321773469959130347470144905381758960436645008051488666423115693738341045851119808222048272924385188356021826450267608127588500233526688704136268009202730309974485584784539415807259862449203760469406037505772435323036790641520939576046423540699016607317147689982042035523118533555744274806239272109508745089640043900389441390176681340", + "141093184161152226992592021994885140117836445291515772908453669279294934817987511015413332614094493905560980363483549300117114491702466085602279965168041684355125886388302948336158133555051817733078300668260616983283027038746214728386770752826764135491650323133831923154477800324207350667020747545837613879364064704092093040155243919335078139087599906324684688427176309081290932504214653249366429592335409761783188358003723753633106574740731573467850133547164922532633897844647383889253777956821171583261238607289172489135768839436605233457738153233579088224808850428203888700116300637190661108848906846940291749737998056247719674749760" }, + +{ "-16402132873169057380", "8202725117980211375579199554494319645475746305836527475507064811368616698686329266053570766100878145903342129595869654087772486685252653587846560946850102095086896668181099435964053041678323706849735936082196618754721606824996486473796843333331029865501790248862590712245450877098960007272754260813822886287008295409755783478345202299352891066800825979067590290793893933819913530599309037639082839491869155044147367415785329077864525961799400923643936705317921900308490987828345313709179960659814100113658528990241758360711799009722683007157350272749544178688961738222930753008443755881419398858537860612954576778456", + "-134542187307192759584182063854799850608007421111316277594191532129597970622559949723743396309231347084450105499455916612009290113746722460358793168839937004812915757145655285798961178877391232945062437277255128401572171216279188126380587081673725314534095093062983435026047851041796084651601813918099532876684901239903769891552275465470747567830660442193995685219383258617057944010709906130655663966913354414611799232001438943448374556294933488875450563987147224709383408815994320229340710143082135667640802837699940654151297907451396297241124380508001357553893328703788960812706653503939250831164194874527033594779746890593262611805280" }, + +{ "-12094905083549825231", "-7303327854122277566083382629094740392048421584433028903125893639493993705575691832165314461496849401726460344615713884253150283931509897329926825128629833541892164122168618243719393446304446866677253728405617434021389128710195093788280203239300086905325641224801020413858421914412156234316517981228056539721130386645649016559425091470643854813419057026759188125291655398451427686659900364573485593902992038773538760663063071699966278379037038361219424927031644750173900916227834573604566165762753650347331082640552394430002401423199016978155236550541225512734287851807727860645247391524620773399994302380387697957581", + "88333057189654571362020288527489792875655269960629008914349561689924145109953656394378545526256758871407020025766992398117775520525507898420898102744530402370720932219749861094609497366188371774072368034971851022164946370916317410415503705484491514312339956381120953283812334833067601825812118392757289250628861166579446800637104996060739031010579056633535166403083327528575504427815713481850979373113173151813491831551023902022537957860211597622343157802805275942920911544696695931809085743355666792408029743911424760065578742910735408262758198787195579745280191859776661700139596074108035867940154338953640690242795671183308201526211" }, + +{ "-81618231044418675360403541307856740187", "9751573706924018395", + "-795906195858402819552264165081526765614024708979523739865" }, + +{ "-167600745660011044249531125104202473984", "-12960244919927910377", + "2172146712516287908809731894157839567367040369214826131968" }, + +{ "90306383312124738690336097936949488486", "156109477991590792", + "14097682358164298866835386043901377722456291173827620912" }, + +{ "126202800261728727198105694812165074067", "-17404362862588500316", + "-2196479330029905727399352310201914876903532806486592905172" }, + +{ "-80093647977875266525946940496137725572", "-9499399805878278852", + "760841584053111508349403804472960020663660465509267203344" }, + +{ "304052889577333477963637861956318521374", "7233536405885618691", + "2199377646072361697737485358722028853038393128548297401434" }, + +{ "-124787646062877233829165925777950698937", "-125798384154373172164515376683173327013", + "15698084237137783175768362160964949930745617334715009097620154581879012485181" }, + +{ "259623502197082370239517374851053110076", "307089583871541575627915295134832918432", + "79727673252974285068387698133566605944659309374400074880377824560177225320832" }, + +{ "-245358177397026033963771466683003477163", "-285087883756432161967673595037725276963", + "69948643556453419103498093570621669430956866597291662675473644085666220495969" }, + +{ "46731711386059374483493216849082745840", "-216522280665540473581476116002923812173", + "-10118456728713381305690589407461434638634240429858378588644634276171257110320" }, + +{ "-301422430661955757433852743238845048860", "-737194742467573013847855072675441356", + "222207031145790358162820429948896977201848379524899474475604149595884654160" }, + +{ "109781582310220385246795023904554278713", "-273317662617851276579672019029762858338", + "-30005245475518685175699313262818315773200953201653075289648004177366787958994" }, + +{ "-312236719893391897821327608828679767006", "-661158307192284418474080017860142217763949256471548515134335997907628404839044913830388499435166012788226998900468665646723366842553747501004752506346280", + "206437901167986463762021023207669068873036145952740267172145693855475451354717023377588805030022300923600718715029262618794758202955817341818233889201852381575043965927328029955969846754837680" }, + +{ "-134379788461141842858846278268259347105", "-5535479645589936472405910397299739073641612836770238183712206042659632410776896398062277742229906915852933418684231779996404071421767274180368154310128427", + "743856583805332082970350662728998610690268824090148728726850517499798631519601137183443104910590855501252539324674812560702657332874686395923181633958702249128106139207076314713649515720653835" }, + +{ "278271843790644800793473851247546123375", "-3845690285506025443856370771250487683891303505653819308540635173436088084480277686684743918745832832765066355874381847690771330587033980524869033600561589", + "-1070147326395532917564114389205677334125034378502074943828571411806344559859053091006175486397820822872698474899835730026158782698085673635033947150554253148685482702599776833910878579880042875" }, + +{ "22345490710865165412267189692679994671", "-13168094845644809414256057134926669929759930873747535851687323456073141938879368460977723280750841588750507348317544461824280674332488497533955177541413394", + "-294247541053147552931885013427268298282376074124656716577088212043667912662239091316191145352314750820026626159649861330384837204227899202392764926604802655267738710003310052268554637728023374" }, + +{ "-223445051950608517881717261787296926498", "-2609806601119499724524852022247741111662431776874117401343811680374867931883996125145979162937751368655661775097445043144114599069842524778189198926688379", + "583148371568187658089071213924575304457465978545376486297236105670932990897420147110485946155066725440999079357995678147717407410446012970360780626554347417807723098476525833332400212113766742" }, + +{ "12604140228725912459681435851589379433", "10671266866958584640992033560488052420339425977492420594983497264069815016478448589306666811246532193922229713077112601565462530332258877522384022088660628", + "134502144009302626262781543880199144227907004673612064586081220538754991037447647926963488301214672345398823354945333417956344119228084327815583754032364976497975702972112644238248704660063924" }, + +{ "-221289678591114384943252477126208006780", "20020996887149770966522122735176842174467884990518978494604707026520269232864200848420530223248762875769520715632742683760311747174524709550334825291720803698613541109690224185041740294906022358446325921538593105347423518731748623037078340006459454656405997570119591344894717789372844612253617591807770017562530034107842444403952657949565007792107071767260484233194674888488789619319597151367813735192433631007526015463229060702510632792171187339118004038505860316305860704455466207113207893106982258864355430481457640304138738182009363353560090082819036973601710432437342931523433079941958203038050750205966472435692", + "-4430439966231074415853738608900692925851705818190624801199561884242897308817127146763274284287396980593383317678766559004881552228480591814939402896201244425805503258878061459604511214900528594870260206969839682573246490602076070316760182753341371682323914671418233629420599310422437691170629449435494697829163966912842611408632129590129483811802031178053300073562716917597174161526976287351465154825036851645956354853960835948518860624747958440181683978083391663149733813297698623499283645627889274004656942800842013709298338912226207338477579862672216831422765369078886850523202897989792734789430796029206661261129141144642117177625405158700499049991760" }, + +{ "180785619668676509441152734583033930295", "-11909038209406834057075682058438206007134213485822042209417443270921391661498900475635417780140585878716264253792335317341527677051828500780153492153490249297998660274828986996948999762620400587091118252205695562417522111840305140989214300921122857271717052213225664738544344394774362885331856170636862181712515248810239601812262573113794334115259873527539564296101166439562124016438281173202196876398090029995104489712272260608848551754611421227761245487365953257890749115194455096508613617028024932657498899001119282498614739316599704645009607294747043489655424155986912576002393048535846081096337705941547991821928", + "-2152982852345560218506186041143281789706715672110278207735389192913214838321097754496849942223194392302524369156102301165660674797665128931611291246607346536492650554391248756408556789391955568308599431054809433808337036546281323840555452571430884302696950144068129601527530304907460164571704857360215834011779559395577299313379666503707563751314135201994045874159291100986903645360754621200008830207429980872071814202801994486961737459218017354210479544121100423399040398021780750351097082070296255480707530391964970754186799748521538525274241709676878827522138880241734356460339681718690408853314007343934035505873192699052380699509877559455199604508760" }, + +{ "-196121729286794751535600080816329923561", "31755463535476988506639447113088283661031267977524968610501132544098607201258848456920865390506381665724254592728643925608893982794532243733117636645689751360224314774452374503339856173343683819017479955914451013484169313685311530532055735999039466721411777061709328450052490025363788971916050033904534189719389237878257877112162843506491071470067738867693853480174965212750301808781573369342701195147083717623066339671595077736036738235636996351642097684597005928843274525502529735435418805821748637387888409663397547514467435322454217015563134545731593492200855670248739786405074231658957946422903165662016649229286", + "-6227936422881500100190187768375947805694946596622670066116457374856427496311253030141271922822486386675428302332027411428470488965226898801659352566022706152307022438261392466548357753526474097246042956052374187605144719189465046544498482461077851578811186829094445089366592317045580466302238653533114619908864036973070346979261546801894831273337217021756025770590122176562027129481076270727248949609326868225755958667670279949371399535144788247565199415296122873444199709788941984099349149684384486618280260678252604631431089580057102263617056951788273430713908768738965854953667135156866028646584137788146112300214498814212865170902491169332389942607446" }, + +{ "-149247491509558553673630984739524508601", "-9241905448313719916485289537122695595500213295294799660583133638026091750542612875183284894676615989153030773719811347110864468582634048542108726080717551794580656021381515769591713295631818532114918070215760259364277583650102628486861397602958930509695263902920994329409932518607260720657755504091822028630927071374796474717671220452208310602827254296323761245420486376569048549643478954846020045263141546849795367522490793641049509748005893155533480849922847230018411440739584477452313387881413141538766185123978087175960946255649923135634987656065468774634483495944248865774633962770893338531522570776854773975281", + "1379331204929344851843348280532786532350930013132149419346606977890849868537539899667631713548510207947097949976792337278764045110931774279794402312944786743575421497528669859045492875676005849752425421867514661792129580445000023570590786705609341859529483054902802038173138834528021423393677908655442991197348183257271932188161681770513283703502340499171444058119260228931558784004778969491586252899270869275893402714040693571919281494643765571068045362364213060063345212881008657925426024923296369533374671614852576576041747836643356665301762059898161073609265572267138950725010661453917338098901465732991316661901878681888138048552901254914604845891881" }, + +{ "-246070233154436622785727814428081917418", "29761582253452470642591719346200231425423204062498655510037025199574178834762931489817919404889920159374886981199608181795387339523762458361385170203883094308920011218315748466148953320570427838912637152446837553950810011344492780712558515815917745810385725989241835877316836808088478276603934260581342710503593237081689944686263274319354100341139245512159619947319496638082702549196795236216458749363904150768879765280332386830831409591769966706351022328535490587838695167807967607003680703048770719240872629379640571077329748828739281770075441660330884779539288220944313294762143588847790653176774089774033399559617", + "-7323439484151992757431054484912931979861244043627630118213112440051387392428853497035249623931234821362770902740177541812170377563064854590834087655133962963430877452052749127605572395112726398103244974178157574726551814002744001021805127518246639418981066588073652668879613252372759895389345727455380224104332342029151667860553645106555190741775758687650292791318963679857313030729683299101577207875499929500963723267185390425716927303375831321783415003339099100562942730763231688479910689887284950156875532151104047755803876078837921949287811575034368641167438367411569736575067233548122814012421044943430647665260439418887639347030312118291762161708906" }, + +{ "203826295936164259559522643510940430939", "428315860474710981601019542870649234168732095026625500771233691514247613083810271191136212287636290276352210600151884730196161003906066671915478570992925366265552107746965374246537358349673161970290367972281768471743836339191023211359427335141701167253694144280251188008871929010775436125645541749886873478179599464478734149706121117222690271210887178499620737860802605991262799781279373870647695125320153193063528861104479576369448865373971847676465682752435142074973627172566791961541105525781297462635428308325033717669972726101583722868689418677558787287897456521530400671342257419067050354522203242849353639864", + "87302035331271280954456598486072605056704393103691656908943847729634903654600322194677794243221825233700566108459784062758955025931450719283517278054268553004951352280583820782976072352456972931479389375165173986780482062859853305469143408707179895843295115510597584169486406323435925707638987591151227843652210256611991940374072593149367903739596883229844326054223707236369465710416960023659329202073724249764308867733476242261506975691004092043954515337899900837434270833782490145948781128533218641649564543508314976001614187701395586824982250794852925954991265270537649691628899148413763865280007928191637215283244406869662872539567459561720369352296" }, + +{ "-5899540498246269366107488541138263797694914692322476860852796858749106720144552037986906792251681094769894732746138541066810195167688318229720888479512583", "5834015210744942902", + "-34418009003174534626858248456163154666511779871358190892629413477534042866009573638264296461516598238780495750056279721797403178867717911762916049857737963922333901125535866" }, + +{ "-7558198374656605586076446665394545534375963428962439959101805545423930654069723860456022097647139432324162475685494459942871728608277717748075653794546685", "-2079670855873590264", + "15718564882684481784074014915267371190416032453294568239793060140651422710113447422494938907375595456199203928496644205320139985222135619659630853564447794621716315309474840" }, + +{ "-9442744083812363570102321552182535031605446031706376100893354933468482520577272174689455502380973733378565213055641110431767353396963744600184737808983381", "-7204974197101757391", + "68034727473703353914019458883709211780958983263702756416891835054494728840771498925306650413027883039860202168095834137357212487561983607389479135319040711944281262212918971" }, + +{ "-10658732210276096534851972646242288663170038580488752611749460640657411087860047053151548660331707024718100598181073744715506934778234716535781332588396176", "9193953347013373121", + "-97995886679587166046252015742839992974979220158813197140160489510432960510418039749924861744197553021702396544307690217470606424904065359660871469041838900287446937257585296" }, + +{ "3330096979672637104536573277593029682675932033891010715180474877149733802060455951241981993421466123791200840797318740359792251505430948855600408060492000", "-9413190658845804679", + "-31346837782105095097578725347257193539696338226258990009265748336528353873277500144838721882313026604404426563737656928378230261942407473822851842589487713775609448642068000" }, + +{ "2224201331350479188470378485954814766783857696988331736807430786504130570570323948774102396158334805040994159865821844362926631687258969480929122732089195", "10226747830478556903", + "22746346139936030910929166328517425029735137934434969334578972386859485783192993228082340012742115893176871887387993591191632260444955081663604449277961804869872353878963085" }, + +{ "-12394770820700925077767705800588617445613665027183406054209162910642613421436080064653443098327137503596792411463268187212855350864330592654862321763110243", "336135860956209890623046930607725140868", + "-4166326961171213704571179876442248501325782360170764344978629523457550315208845439497110652079907652744850691289494398473488033083739905461347650605270023127087625641779424751335704552988710924" }, + +{ "11792778994619176404079667787533709801900490264171877873621265044313417667869688303207909681289642260521608966405181881416781694320672906600599581862090088", "-197661229068721548419113517262926820105", + "-2330975190212228827672814304508257223671550753091700552243633152084831515892056240354560520878171696176381845689952044935988868477421447557890739834031207059212175922089523097911477486879619240" }, + +{ "11608994516281296345925963401821217560860934641820086911326880657644311461955556832927259499969983808078591149768068360172431078248807463030805586293656663", "-40654941048774156019243747229920736005", + "-471962987694958552110784676392477007070112288398143925079396435246284471999814508543057304008480666763661066976653446723271982094424149279649226771823800871458389214002872916339341019732251315" }, + +{ "4821517917539756801293776911844480642406562140007084392649374723119190602353617113036081438891134008988421494142194891002983491670246762173236312873933599", "-255528396376819316172341014108564420589", + "-1232034741571035406264710387186737842510579499938716343220834781077329515145216794636313459582844773420679078031627466542930137302257934575129329529129776153159694412903937370462708576694469811" }, + +{ "7638751115643228563298483305056828584775811590562130101723525925933790010789130133831569153863129513189315440899053288261039147463032870669035935364282061", "114438828287750304954799140618669114911", + "874169727255956505920153418854946321208907128396839975975317705220623267360648189969313978740314703015845506506608054761304647627635292132043887080298168302864314697920637105700927041824911571" }, + +{ "-3653826017463740005170218884285271512636869606149686475539243914909566619638259666405831445823138528809165270360144267462878986866506114069923299116957450", "215752050445782448772085819939961259625", + "-788320455239949216234629350585027855111249573063377172522422069903710014529292638311216050777840734448624510386643245486023092483841464815987597578151663227035102742664709136512524899527956250" }, + +{ "-43242564273985683175827997542883970694363047476880657467026050730764924897992516355909421962249292250047896135687573746158665836208681548975073555418266", "4424346097667245771102179669235543742385176589624011161914909311078645828684936231569739522607200308028372644149306431599085361996722603718517735348761218", + "-191320070498733614136284309000213964486426347688040889144514933290125387693498098446328694172047943298442181705949005984031677324306763731212307716485454004382079159622650481983102917517993601466178931324415483972311904823997211920702201161092866663969163567426868740120661073974542958600768774774949607988" }, + +{ "-5093597555679260616199210906198149266592665304134802327659606846977583233938836318559188141955851256260954289429418183711191354912372372976165948043123133", "-2240632735861652612028397136046974907251405868353380459030143407902436514978447480884513019736738955326732458088791830752499716417751919868492224207936623", + "11412881426559848135724717164530530041659963797467536748076144863846600718211858527283843975968920120508569299672573958424908957105703597501013710262110218780710678312197455759181436286391257283676806548463507528765947919856827004176416634630489598937924092540289712219714362500246928243091408698274649199859" }, + +{ "6049789822056553589237940133475342650218069231558204589924996117723031491205673061674252841792149409384720347601549237626288416453061224734057079515141650", "-826416247951451524584060567988229017033981218652490450160817307801130685352465013890931297548015267655971295627931896259998420078888499206031390299169584", + "-4999644605638856588581238481465237523157457201817697008198975191261856978252081380810200468420738807464233192102972784271159116426108806200426852134469939032473362689081653859652824862066224063273799612269941254948709760659691148103622071316554194507524610166457990087959160807415102946877307193349131573600" }, + +{ "-1175978338162966145239180473229656000174129248706173549637767835154921467129547950144109700900405904250603515318348888619371004435353505449762899046094747", "8633693716102199391202401198009047492431980605560930404972542822133579985462906768067706391388213605203282586546130434156768523403030127356256666478340720", + "-10153036788469908062299722391986722149392791936544969945546931764708792252481931153733789787389051773529081688846141949513463792442701686406966696738286561777611293604311491896230769507535896070984747493738525389837795316954065260075941524322954935690803870500012809797698319359975893462672845329776468197840" }, + +{ "-5083395547684319640767882199938390155755986838939007846911062687871291096073452055061784159768637502151635665247461348347470360218957222873087414506633886", "10813098236568616588240471432239693891825284805405416395976866126102880121934298269375465735278296789484402954117593716698067735458182402220278016922449294", + "-54967255432446073625448401244836956268872685687128644401372608170106281377801209665004925733448944141633739594240156882328181133879414641109484442890809130544146420476457200729843868300396656004198615619691952536924980482714767859804902602805398865249514544806725162402291122143659939645240358379962457176484" }, + +{ "-8944626200084865988157251013718979706166428261352840753194709093968177704853157211364231059892647813839391802007588961807572842923682104089512428902387812", "3814836951264415657788614449012480613328314590744410079075164918748648723114236698412482309581077603776489883375576245233128800002373843611668945838558629", + "-34122290543331565327874124324135450224668275222811493728051290368641401807963502623692504750924543845019291736982354932620821594287780848608647686402233097059022704206628297180782771812500512744911371653368388270442874670230118309469599458827222162362901084328510647514081302476000779049412605744638457029748" }, + +{ "5186176030253526423885531264483408352469356233262336223619904269047786350470477526433506158542551137478071074193659876898065998079440819597952826155782068", "21428324964794197485898135923805540163916541943812058590308650649384013587098638034673796533027113673143959572855470411726978105342739938341516634354246514986124789451866589211982659199267654387148420461876524076040233779391563396552267276880650559148637067641021059664960876301072636635299261389450890094318429077561092553337025096293793433968243940381587994428364726938534453507046761494257538813861046058298873206568935790790373886840765817404479239485444563488020955730741209738203470138117422899051269778988135668626686262669881048094388220931264751830393793846372816717368806996496715219806062282836392457741918", + "111131065300898907482632501071313138589398597291097276435916516379173430095773463468344138866282820740991088290299992221985607057347883717514843661030457396422379155394966857856069231504805779448809986906434617741485942621643754096548512120178021034054648207248963478122178145159262707381679354401629366698488021743300737044695960363216253889163551918513521913593214414139637549577618641974388739304727218804595402055185824193445089425262833385286117064481648652550355832014346131722965510192584901901111154083186713580209077544982897821477349293279848852596241762198202012197892321827305803333334823616660229870976569043453639028059771892706354703750763908127611939169337399882784092285804830644630059487027413697220038110815990084742241055099963659761569486906596326424" }, + +{ "-12615422028124847936088012564413126213419674293830655240645918456932358053670311316461359727921727680491520480380615359506308571290338231702217134487397730", "21538722931308708400287621200994476771789912594554241036641406577761480056366647329031140922034590767810855360008375309986798226712928670905618807986829790199948665185268081173685941421700542631395958882077936923141152528333121096909688700106365468854487023847026564219531968849793109908193037522063952753477768381591929787242143631287330811801315216116212154423972654430356675401769729358415036943501470085182304183033246682446978634892995900678975109490698283226559860736462409705544079080978470202336645384768211440438501339641775269445439018148409151795830925198162301321965042997632479354427154223366199106583051", + "-271720079725309675925162538296715595434811519956795637977932956405490708202732964133816538801099235844279338645471102896234318181092598033040518838847055114923365599862266767493227393553801736813141780001130539648588341196802606083178208108557367013886856183999712817955194261262279080641101769944037282423238147653270651419282545398168930625797556638625301898893565965773914460998322350526545278664715332414172614761548301364063397364632709194713561073496860524124460861314674679928692398440036071116570829193414179054372604203478369755566003622621281005164747628075596444178089558747835994702060740334079222508147598079351187013336751322569865313532407367116553748939535664259669808534100091049960040092785009707220249025633808590643620557093069849490009472441113874230" }, + +{ "10381022953674450046578890619826448644067144294659610359943634722044183130638243233110364436029778310048006743033299956844491228999113516347401915490861208", "-20974871685432829994714153210121536409377362402944992609230062091789259307033495284524234519701670462495676590513192861649457148897274608767543942797542628100823017887236899471151903799837558453043431373811892813126194662218472834650841742305925226558315372771353677064933578639099452438843500601586038910108679737480263349221244638463171088589123712367802373159421798288708123925853179931628847579314900787361946716531755600236755527982132768286927549323465697241340003870259800347640599467922823203446834792229595507968354687630029075884034263531531423883902851487995214646322431057626558858528344843531280263328354", + "-217740624416854507100100919338835880277259264187442792458843251425095703739537223785767883764746809214920580060316177442387941385712712426957388995082877226019966428812240179251716274377143798847348759498926420314709056615470455134468678662646006408843897699718742372199854223008996321568642038054564397441209859567556502098420151667437837356649730396360374136203172669776530655738388121236079327354422138744456395348910073462618440421257604563050031602590345028438897601523520973759458890228893913090702884911857207117714231568437403212806578764580006787626657709435954760239671948147344463295520930250155876010414461245194991189183956653772752290656063730950237649394743456230607077768595983629559996700837383822873994717987698780007691157576205450973669241823945091632" }, + +{ "-3984492646329789478973994496812455855595578196959138558282015917391108383154917581748539892089090551298072688793487597623310815918942283997753800645644511", "22199897116873160263914990610762123553075230334116099569358672964060004245706770678771431369917479502828754815568950371273785689812698287446020480951417047185190067265849637510591502642000414540862689426343523077229502494771352820057572619644085930901096534031496492870227890836816886496090287321502805172125273822231241073590840684742085641304915656543831190976008986490532066597410386596132766422026234488163435487889876791504407434387555507637783709991326338482319227500686541368087892665100076351075069628862376686619537655838590687615291898971286325099164241688147975845320979841704002364545072665891829427213069", + "-88455326811459002089798581395024759975871889172872668466370443703433800509268320055453743803627754859670391415348970278548381190662701716228279482045339649051139909543850883613464992501666524385524517648069873862957915620016943364950043289963237718026629805297916194484838158010754666017024585366330526135823515744339445036315966714684052345462172808299142368905939297220895721123725415007532441824406115746741972351142687017849809593982432484296719999502992792447259391592152463664807498752410740679664044620898308783634092355737296495489953554685938970593890496829484673393665321572846542839714620847185428664388282452532264810310019327395691530430185946743995669191791841546685206884247468693248673484055915613115527492005264289557719000245333079386593840592027314259" }, + +{ "-10672574004830373997900438516438419278676753890756925443116289034080220708922677740383425352837266631691319394850521121221541344600832530724104047804922665", "-7307684417326792807224298894786988180161884427390942431653062127076829842696634441114228528164049031680536693195116703321494895319862805505304314401000204515985676763063862569446064343853536464020413910728442475032187317639476018710375702206456631041987826826225461927793241495220512935434301833094232834266749666697332380140380619185254354273073522191066457437931022783436360434167505326773192959291779779370530770935758482422581712556111319611455306383173529090289274267200543081481693078804068524057891845603351773722737987393428313340760607600482724483853560340630587029610437280601010173185018227638972500038072", + "77991802747865927212086621295493124451256238920588746597961055391511562690441964216934615500942858653797884925704270904527938466874924049039962754703188019915846345804228044693122758075602494985337649496117180241872910247079655077012999375809878184011356481981590430241786534827516536543734645410817621964035091467871491521760928486006653992134635010794346993161329777270345449763927429735191213854873362673179799811714902439637861750855639857969259787075469241319618538795721956528400353086156169058060112255274542232054021662809196965752800525093125763127895334967094763817500702626282397394521201385439419885607578137159972521677923972708827090645776826953976605193554447841693259586575931864396484621463004541561908426383260772786784541411548146173991869741515701880" }, + +{ "1420855003086789510813111205540636553863493314684153860389816109865085846062678305775289632805233481596171530412925552158799875183492757047174905459819169", "13897739053062356545217161606361735964779941697726983959749295377836209520566715597422965426908191354971972501742952706730523748574796773473606175934144970768662226027157110240776527834790487577863781140089347362129598158760833470434895693782503529955845076709376071972727346128409008293671217324995682020009675316075606538241192607139905488719485728099428376369506685875348346231688684483781160648420909364963718027571565217314827671844485031440079254478598236877074793221578612249882886835580737423192061550370069895525711885220268707201966615936769696379335772521903910689934596134239331592980694745008817040569590", + "19746672065138309742065153069587996891492444461032276894328314121573439684229636534026409362850111716212254549198595854140809664451286626009917828620279583631575940837712663100442879662416765138504151063632823014639305658882804073655537352377258786105147057375069447099908107785635606190515362082317465738205179108333064680370909383338688734129396788764959056886328471374018961975554190739706996184818378586233017775166959010668462907838359485424792026496574369912033757997469014639705459505746723512361959074802456098328538419933637295482429555127226978561859965498424173552676019033370307387047798600024901453757451579262061785051932535359410827170361533603618131510421439128567361259204833501190218719779570258541358012741265599985490513564378203502703406698160470710" }, + +{ "-25117824099635104147178796272946098711514362630774369209876335291088434247131228189812265510495277875692804180473811834186270331245779845635089547499275113671007257221593872123397418355506777725721168216892830217596134983713752526559153149600553468865338887605949011743043425900799896245185282419637806859906582214420191794114207677635194054239563071023206500505880052007267243210206807805387341085613436600843317096291021780624738422589234020279836961194869688005260369009833026575446099544900581955685627511787510900479881434909308757027825050977932238481841909425598834367032841935054158448815026264505726593064239", "7846111496222858966", + "-197077248428250572361351389692146917243277049539013604789802566767174747369897711991559940484392921619974209620152008632450612546796556905740493507885376190913893140368029841033442857949219716681475253727058707723386016055991276120001690579154370788782636181079931076758384034193266737114305362492836167078199155929937891579224024229182935372106924021709421948701131654358516297806197381566809357458374057189773041520552821330635689748583803171230633654728360451100477472934847975252390985102859262992904778849652221553818627134153578436315973777720706502751232660284910468721430874674021521629540714057383398858244828214000543075116874" }, + +{ "-12000343217458212092754251360179138661969968218789048702097501439124892987400633614429800307263114371624489988815324366411323242909652002510513570900627875514001409309670202055060404640758548257776155562167062337394219073071639153822126554525439988062676648294108951003012550815746564810508912122306190725453386412796036693387315128514162061147675205485143205925649214342646148112549805850530430229663418469577245456944558387628002442451042105749848177325651852669794048215063957689756465788955050513359977166122710392613631703123491357791351447110169966270916789849428298930624807758982400706608788793481972190953569", "15463017349709835150", + "-185561515374029078700596518575548896805308728003103939537818954646551372890610870275966055765608887701776880889777402229764948269089126750201922167386201171243298907675542965323275634529293654817279957832652909009385491998537031060285890512199675273422070784691446251899120095880199298512230290860589352290462643231396804350623684034400741386070220057232978556614620855818271117742675632435727751812101639747357642295230273344552327870600519422276996860893842363996198017494117619585153346745838853026029459826407782259598477529242420507010652705302341725948095720110508044256096963772599572721279996322424269691990173052929936294150350" }, + +{ "20244597897909303129995907707212050478823487084391413473821544089492035634291726811145005824559631386634261268723753786161463497881725871168747275110149007801865428978596190887145324535224079986377522166727137028753272158887188902047835658826867304220850429481233026043496635847568448251753504834367809877190895369288045026559783632709799678639927825194847005181499299410953860627694080906167346078299421796974815616608326704894611151743720515377248152215241639534004099341398238713597030368980166731393247619511322804984829747216779359780372801101821087516269912916462719248736442644433057333788741151270815989388229", "17931151643499274580", + "363008954869078360197158713265773114114991766614027768774402465306840646219477262855625957403406166192075865834283840624408916170935610374573318606346031792128003204902147985329385955814330782527184421959263266167048755628089412213360508944817963403092490479480264538027768728303095523018598016863928762335410109567604756183580676503045557867957273324581082608248341332512325136675167966306268035077761004923732568405295901819511346235524577361289712297365403327125212199451099538443576479787130510546755789504852631291774614010584650672707483555436445926222945298928326313943231688436271883746272589347954697213098866117569339490918820" }, + +{ "18134862906191691435095953372467318196853760384894170022863300447691250350836421337333332682828557871096554531436829166444150586004379181099133295174348038948038399079336722004125999533719492457544642570217406286811480006881054375314838605871238868968956868878182133492469763282800195060849734382249696543089869191257451321764806079423169235271658993054867624410589213892458246001270123109841429271429275464249821855221014782727398959126117031823977229309775211695677345378510417534328974531801634095862859684508240122911023047425473036305928743193594967362216559973174709883576295373749738633873828863608550295977368", "15082354452174510460", + "273516430292774638949326170314933525797985748367549139070674899956657807928629067317576809269188258819686207094298714770978509118959142516619521080722291318367607601498107007447014759288176261262818034997399866363248136237609824401265450913244758024085739876914482935655100890803279961929047974391299795570244708811454483314898873277493486428279875241232025231140855860469097028388778917980779775554139507550577255217032521719099071084956515691364008526064349956553916033914728254580848198941020806723485184338914882588931083516851849558411503129184026079582257756707601984686901646494090820169212279581209612798749779318126482639269280" }, + +{ "19213874382308276075905228027166553836726993832150876980655958901416537033385379180983129528081628446454583401834309285184752924794893846406622935494758142810049493348116192315865522516744262115026742103678965417868790607689989205765793528434388393584537260717130892518011447327847533083474230074174308157934463971640826422302901570010591182715932658037868980053012095115562188975692530473556182305847290196895478280679341869546292639446526021874910117953225154204035612531584978136604161393474554294315903436682283787080297348697922389355209790646124024053098888687638640826064745026930980189268652291562437512941810", "3155416591710364359", + "60627778016974262766014671335614995348970065077989108071534610098195400001445248886220725085881796599270026085183075312353388418711598523030563716616967792282609748819081238929738105086199457414615236966895805539596649555457494710621217412773036416007129418290246899690911654008867819945724649185574237527152410775686803449108977881160831441280833577932476667657759420192656716352190871667386955409426879693856001112340390304980532208752863058384169885129364117656404549585836664647784765508649117301622797243353610345828189312360124462238989888436478381583689386509617357901461416012201469794664889076397809504626996523928173064949790" }, + +{ "-6561903839860415551587224953276060627466820222543175464705113686962550773423611522044145975606965294164125376820288981286542044306677764776675868357117109664125730405280822770267329297542599719353907954399688197248115043785617436343303277493146049939491224480136371029084354063731401026459653680017632996944506546122253686805764620116169065663214526857151412139439538335533979733329962892417175374550305659302592107472151941922230309227785266745974334776462642676959433923828440435340579340133192678341787895007461237846313005612116885419002449356480017828933592324336731295317076205553526568668826499450826560670163", "14908715577157091280", + "-97829557993133908713082095435440645457469053259814412551982534425389603663024461131358343104414088618618030154957456050473312402460589893359522167472060177968099538846750606564761307960896264958539903740023783283814849937681270591589750181462708056758506230073751440847913386576449367635057595344744119561166438538811561109125506233466453974371464999669336530949393433719456191822836826214814780222021267726528396849558417851727452246676857867278196266042327956933753121947589485377148388716839519782819642328655117625818256334190717182923260613562191698788004591479576661108985313450029332968584240383859113741485244318702724563478640" }, + +{ "-10378013547095983701124686671659666242518351347561698092030999302329372512356819420877395264401390796163955327080881297568412490286247154759694714275858127906305200295043241717769593877683535229411640745872559018085757273530771413156968541499388413497221629366848027355125816131586610997516488552323667400115617175682996681969687885201321292153656071894385242141321468096793766926179134511319941715949712230831768643024119693594235207988046511542691719002262040067921088838755337917414526554050602539873232518619281766327369577617796816586064895744680567067970817494102948032924671421242699225194947982378019119315136", "30004910492448871409155105619400474385", + "-311391367570036811050052853596227388481520279736812036769684195465110674594690412517879149770622679377262288447706750813509857551308594851067359841826754786725926298013483569424123912020079066150719085450400229896983461212531213110847425940968466564079253939695853896434719530729030897976597410468081535234663568150722646854183317007227669132983719314653861536414057481478039579810285535699518386214012059191958557306338432321511585867535008319640705419431310336566447165302011113284064246284641707577414470505948868362067233709611758700034131461348997580441628136979257037186480770286846026250437141175360847735150981343952303257191661069675154710791360" }, + +{ "6311357747888359229575837883366949670125882865462293491587368290797766017168248637163030339387377997726585769250585768079027576213724941259801478313127113803503561717311996500019522893295813684259416551410025111443510215766297835872165689077882298506134885487991732718254835036694083204758447948541157893533099634169589161496492972953698758234452126564385255035294546278732684663873459439615228706684138982066055370429797835904846166362278557095045056472775166294675997320598469599722704075215700819354957397052721573993997624711445698656580401684113096559767093466880001548887739825916626416328760047783071058963451", "-212654096583990292869707082365869207538", + "-1342136080095566600483524091094048745061145155430997807005186206704767933140306297188996797343723817220160636373424666345108189275851749622201429179882167381735732553825696482751584102093819432866729465599060815670807282181979889263381844726842751894916887860819210652174987999919869623292751389157233409465756974677789790982740267208982768450215563288024088369480574425410032306456026930809228182100949940216614156925537929648841127727165386031716586596638254705402653861723407930666152691102484352058909219619985877341630210918347460471644327858114815713557305185589162775699323253049631349906791700893878999711846225062306568467992135934882289075693638" }, + +{ "25104391676237653962996674810232896003857294806799086059884413856421530328279649263948893056601611073815235439115612155497964541323584159786678357898152394779494741995735881624055133443980324145256438160990490767324719276757840825641421547232460969806196141938571103617707677351907526127993230143577974386169402623023560579220343920203666762052525898442578990183400559087522259053245822827313206196194989095468393682721753147596892214609346047051670610252732846805143964713621673722554204896154742594858056891979146566683467510164875593192581407047920719605560716270697985110227952698114701527191421628561835164291236", "-205991315859231724218751687295926841150", + "-5171286675233738337789203670843122752625713948587464573381323151628930998435518250812603433784823922283042037694290795352461861058217142213862777203850665369756106838860420507328654214723398688455622487003912073924323587826356928211672752672052670663842775836967587150049181838707784871641183683742967716787111671792311389517753578360293551031540853470719098360013225516593755039537796518619542838794169319227197212817921098393499332268929332950035803734983497370378852859829228973012039890600437082235032378948656232679080766068869430262740600476498399803176452431728914806536862849281928869092524387549297345184969051926149006293586531930828748109161400" }, + +{ "-25971587288596053786734900662696128734726180676323130693160397208008930123341700520454723462226657743365779183466120836187720332442041321870351823609046027805781414454998487673927365486893294110931852680018706479684281928396163669935417207859889405108139261480861908067489849403284000981453574189898304616775302917687860062501465417706095450121596418236563421425311420755550335597318818628123183624214438801254105808079227429950505879366254661664881055965092586612702279548151277733307180663770432418397550642136953750720624507617115504303570076531620003848642167562950736271141440609700821621532583527124386811144839", "-182748557863603655835821910989658558236", + "4746270122419629115710902425435990509747636609113505336611751359043717100752575149404352359855260443259846554733621122684788488984010741203981300775978945529551335641218319619542248418128319220383298229263331638090009313676486209764655429828385994626323209879925281409485074778611946493692237774852428345451174837474328995186242262565013937544898941834362941815633750896882758939509605799422068815435202904271722442099465950700886702949580264958171808372530471918175963644209760378395316412115175988232945569517230829200985652504383431054550902852797293952515652017940918628980037316292352828228005975466732028971159947131994753006597870175664981312344004" }, + +{ "2117427896392849163304163145095251890404997781812823978967013619233450901604407363671467658244435728579079751353560538034596183240362499870272373308111405924505741579887345118857908796509418246599428633956038017783178050402412769812823236255234302205027282366926174916871858199918908361186936687654278623156607813451034087735179167324944824913226799346886951212979149617678949292799645035425029596869092844906629996914674904522806258932192931217652241231736891642224851547474205131131019084734780208254203537633402057673465583362982905095029133132240839391503135932501785844503813910210348239157828902668852795945482", "-296778668392678698960782643314222141731", + "-628407431508980610909134894336322264939705333430111861505965183839156278363647883745193463537783397824947515214540990712455315080515980803996660089847066076833542492719707493333185909990202372284811233272987993068106356248349054482194817336258302692039392400931536481136340269417905505366385505196886218794044229758585631131853635721528813397816307666671727692971421531381290925317161326036075629905443938124481334173158440927555118173661486114828362551889594188958723424604273078091320087897088472418346754088900034854230711982602435635574895960156993014703292551046970069204857846207328434544990709459402656908170089318995291341536347275682867153109342" }, + +{ "24743327715258194976385899813930363006464428087412805068703455203318769863096919192538751530954777047772548306936907016751357570434930538612382851621309732767199276228580401695793317612267605312672263736938703887622824117576912830029817460033437752668221355377879837833796222831371174014543622739933433581963103361464022058091243110136610854806189138108937004805781857031030005354158991203388998364340053773883952742645161560754545458260688560269655272249435540890073696261770299845722705104648358053080678920468895189601731801025555650490534399590288852165862135571140382055044665678298182909026026068995867606241201", "309156501491030456401354118244509785044", + "7649560631695275371386748526795333430293346807872366006552933839286343590101586516802834568317627508914888989005968805867728947519409222814667350103434422356009252082456906520988877859152125402282765775845766265340707473525444185795403554160270722809642681642831847296672303556012796775586274347178092325226458743113317655523655255626670958156216225968018208281266858684283741496986683426354716284780229004376492833583965647875097951642088252875535823145900129967026856898970545720526282798418382467634180690243423325770596949644122541224189780082061715230852249880601371985342796525016176048518593825361248232406051886794538203297084423942036889326397844" }, + +{ "31345149697924857384985323414506591310628538098830133854928154990821019223495435414394178930529373634315044777562902565397455028894455733092896622048288278424884040917250546068175763309233883078972879622697667174865833277342334219810618450605650614585133187005110148963483824629405555603493157452295284935004578187488673124814714326405406894084902824045787647963172437833905574178160343833139650913077173865287057167288286708807322607983179910358234015596109655900840652230258122852488289951986129788952718105898226951651151495867246384586164892018870981480003722043190639707903266193064807571586900961788679579912089", "2067227180806746570739122295766566373146995767544546241400900414826379465803168632854028593293108913670556431832056563218709444199286888840721753894461468", + "64797545442006646811970698282511426059102976298051534827345388707272469591333019870381858263624490336448197115781363489554169207652559213486772008013638214870324260793199674746523791257170452738018910619029072942848422098770309928561867618844814267276213608306045020686764830302020953883994906997293368193331696747777630621086600981981357507299729947717565760536305785574555255589190221698706036770081438750974356437738060098906046001271392354762036427049946092656701257615490057677558059955825843182799904828201890893555678855718728417223845757559310912618029462136640226686626513375024547351747669476392735304999046232068947570708757930233036922714350584650744960478326257916948676866148362166017752159953504981324652709881831381637989229842766220141292801807437886652" }, + +{ "1965759082776833678304908699214846485256126608825750175641683294458978302204367346739996602241053060915897480812220051082619942907491598551933638540412113496542245474287364500698693202553692963910123752514310355402167440783023542848697962967771951714434359320001430281377747193083851165947498546085410216620013287853719686698746328198021011905482303248172483782066908570502837009924228011993318265674390462360820566174204659723461994730913995303015012684826295802887547970851558451858623353950391701673651959262042520584275132971807158231859672678070714276061110616753309305801080136339206017351200193800253572481467", "-11092241138073130060021642325471345789108575712118027611362686690749327689527135459714040658411176246054106270789083336195599640521602432629024562630323934", + "-21804673765518097879589124792137157558586438669762099454880024920520894260754279593873244443852337739758694535682558790532827482894104906218015712179591886600693703465749571299271429989154199263793230178266758966678432691901731270899259065726530463438316383699558373053423999416350780342222940065486831353604365192968606300436304827279383661172824549131179471364227618431414928702407510473319879188990689163932586727702195573766225861364297410904859137393184592815970592502081722125458353280743087607273547490382023433724488604177909671497082747464946083901888849483505451426245881736990810339421864101129619181017696837017966116165703320918568645290788634265522956017905246042460811062666193790657969385648522736090098231379029903772234867701846824572274796526421531178" }, + +{ "-4067457132547237558852016696244696525033953641638067592741078194074861352472861925779476293767777560910963786727886946479865734639031042985368829200802420611189793957001730656623744670821921724417176679009632346904384261431052972127975733031277489967119978909321422086102208644766894305071609385305464547231057263658903212521469801833214062476735046735467944834107695748433481665714184831786462886261252526036621257865158497049125410241033365487816324425563483999957660557670189397770488996359512245971368638615503320507431381893539767352426795415898379765583574977542068222040889423739693921998717145084904555464058", "9635268828818063607505341812331931088336041632536136269505180222913464638532245578488168867093853062326136774925531196873279749483997619950077042084971972", + "-39191042921786100943542578352486285322085069425292685238158202937549417928185097567102615300826629615520476316505465412722375794150552330462353356124896483739321653441446703127728441315609093330694305784991844511900128172079464896650958648496336601612657347012294121239821167759496102233234525084695798195547141521849769350204659392602605928907953707277320590923278178152903602506284861018886300148663530071056792375593665422754923886137410482547324901798328311927545105456397213670390651819229021443747424183114992653572959318104053511452473611466305149349027962240989590453237778130260105665310067480846969449221473610614214933278048389171979184119355459010233147440293881252851501522689209874112819966647846701257081192324007280573826673895648273593609466000383382376" }, + +{ "-22047771987573494284336211037167956208924595972749016352929724093971147687332865088249749580556015503923927321586913446367676445848750229391300778587369581738560634537089081840938984779012854694220894920437076215176060179241185151442003472788530160589267677502568156006531439509890061829154786579353177129190813899423306499631144919702707240832059008168851983259611724134448165201725432622521420667808597545410136493805873769372831833878868603946583848422310946469083400330960925084024624317866822897278934924368888332618046649078771617892961267312226309927786691384460940015979582201446635756024251269978545916298961", "7481502540911026808093162425787184755732317118387068406204973030847892995155568099553397887864257088525242568880427634318737874025160499293315047534753494", + "-164950462146458057264341765173378248123415893870534274075422323606836246718538063890359159423074703472625232511667875897808555123518162244263016096627959208397334135559180524195701526029092734741010866589515172934676451385008535538102832400604699294088534999994990970130226363762230944961249818769566697211068918154629209895730969522747736738946126971914549491889482944152891334838234907190697109929512401661529882587076352559260375439428815896053844621297552401396168240947357044985051323834074355418902009161796886350497072010833513601114819625605048943438304411954380599728561071485061414856047768286383287807924135081902458690495890129203192613070824670256334683011083767124852354110322463725619194174195587835939047474059288568764831570274891727391545546467943319734" }, + +{ "22607201423790553279447786193696575272983924506336369475058795405894123712509544256099524616893423762658394830755129501447553593365768543361107397299007141714383407862976654294384881771985218996697067215804348472693636567074361380875512341556932579903687576929186215185312685712277482751425466251201421842248749944123326048360909954588266368306843116245625635467041934524547983478110533044085242847795585598341867070787331785945399446665919396062565614516404861115244243161694059679274045050270546536781907061002623188435269769778378780371158624481539046590932125320888745103158180784231722265376331553893647061533815", "10075764395489719205294189472045365742345400155046712954334138069917417587273618147303160957788995022989479371576840422540097479703418600112174202202728054", + "227784835187493343385594867881830022845566753253174983274076326016001091958812135049265213053390506720261776960833046225700903422206015373488419693650378821159134369608830936915027161415300759990632038898164509761337714774392506802504397626551196717184785586630245704512525844329038355790338277254618639554796026366029578805283659986085947726260520495140332204643887370987929304924491772630534558682402396784510750317396488402942581973350428066695976988812610467654886227733900635715495731445319565054848075104982244316563526232071957624002266648721592744376122065531440026836549316222728280595228806728872537793522244957258060730038589170810090676474272044568671474692128168357087077816573419470273384256552275636517940058764711467508281344270125535855785388198570146010" }, + +{ "21997874907846585575969651776904015812729615626636027149446399573806943459105370044846476738175828244018281160136531735881270437472624605280356112191272531838028896521621800558410217146758345955334174583639352151367532676985598470747138461153212653362188252002768647808852054182649808145379073620834551216386805267446360709820441771932135218282126427988826945094538034579367527908530151926679515746133600376612899354099328788736038811470295396365432559354070365548930628714861826464935305416998192532029724853617023971964507955475554955277722555849603716733374588174421463022213135839490633927005539569058361144905451", "-1400498192750070094581812894241996480373581610489471746158083224360249880335094841398529960182484181641387946900090289855375996313447832474435929084180606", + "-30807984052781257825246153008277875918087659020905755686964119182052911551148620538090633516362197112383237624321406969368641524681503231262834662890145617622830207559490089313283375890353617292096501953380469351747504928597461154633889236826060654886877907382241867167198409355653371944304660938495445848950444683274236538890057643038410268234731745456035923559528706349316582901179686671568504971088561096469997823300883298811440849031903066114422309644669680078733839046643542078157684064686933779591609758494599988463628362190034612412739669041368897594110022347872452261447359402810277413572637740870748949093642723240662839444216981630862346445890780016393330114883270596630385367407921496982236074288475142085411632630374714528706189796772213264952893973677883306" }, + +#if 0 // more than two arguments +{ "-270155241925436273159477510619232592261228150696806729750247050 15545126743930076938536195287546926534964892301082800206802745964245668351235397 72127079799316080210744562119267314209211162112457416152560774669179705347659265 58427280233475514109627698916382980237252687770812483048907352594138577656301900 91336330475502063985843547526216808965829995610054777216888670176112782119332811 99495081134815818196404370468895496198561677002653930126818668800341380375657337 6904264296552316628911621065724553059847235903647375662685025031963599691416829398469283631386160328944460790101458427909545198569619131058877708293713734", "-16074984786353617526516141164566295497596312655026144270863093715961484079732496604871734572736757225277596743795506589617891195569235287256031608792067121393492186703333733526879481948463529609113624075923052999494363547340563039654910799974388353472433635130983731604982117092991918514078659590068643956240711810902756784590442416249652077644077280371860780741318193975770906075446772544431670392964384669681404295839302410058434872964315897505894833409101781069230919347279857855594782111721176074849502391457684148683668165019969667481755384384017844104770253558111588611189351637275389688093074751942960310850074", + "17849860827147993486644896214424106325295064110723402251474432199595968349198253682890653243676378684005650871261983711134190416277366473221365848417375107498764965893729640224952922241531788638514200018520970345581414705756736222535562338748426356003659523260330725662384208724142177900990027225665451069059291754155591197426279006090296512196415617974140965334686090032257444820748820516976632201388937358434205022475303705442914044454220818215336283948743042841946229853366515552653568436171217572212088935263340599371830215580988184775240338748954666846379831467518505260487989636951404886967842600777836444030434816421999334066711024026401362115623932221335906548647785232855815515579448393689650116225664467056283988125816950714780486880294535933597118808163054631168063568847830481653855357008353733414826165759079092633441356914450038756281940532159493763482047244493174370100586359619040444818634156576789665732998111907245928253704097384811414269835758656988678207624731164159069547745777423464124959379113843649940896359346515513936964849811155238140671698227057228045173997904545787593258286212427476788605370334985423461194148838623911634821153061693257996982252745844329344589168264774527631972524787804330730506700000" }, + +{ "6411564443509812216548163965666668398784964137255201222920640150 65325385402074288043601436729391841747319174569548241717675134253657593233436152 63305037198546989906433329294566491017476837189978173607681765241525113921707860 72383582945810879300930057856704905379805338886592055772943486702915907397618845 35525980101796892634292856352740658817031405780112750352735419884048051630180860 47579150292602967366908574298176357632207539947399443701205872093150879604391127 7775494633965874654516687741429737470333189902121089184439228657893110997221737422210698789286625633365548095171257583020272703565350668755439139356570", "-7847653632223099338936161226557020783515367997970448568586056286591257384101422312757649765574456754668588904917800060981155642916520580540801153603733496143328839018174649200566737789874193483124577734129346933208306772618814806884416239295732454033604210880463262467564639515484363761639994642888910703066277724414372379965872478153546766131136324967950786993982228851928269842355632200589446224738709869729930285189047112131897218464505263042012855229737941639093204086147932759923796947642895167078971517834730472596647456786099215405165290569214043431009370032818978995463168133051136053246705694337584724712230", + "-197949741939898550383903354028842356745461597695099989904494711851411610441324234089773644533872304737431480244289438922163630848266242200711131210228027234579469457105291847132071566876246332653149194709623963836885480655282595345693084881617726426841183231475364991154699746506928116505297453355016975688761948609740314324443406930215518937775475617384099331839748494157863510168743547396262979908353122625808170296763676837551973930928848463398657587603606321137626467028732193151671337338929938959296176472483674270114824853018199281637976410726195357458134038379491704909997939715446657856320452698914513791221947734373322868574099599391493563479057703049036936132407025278683219316357543078875410080612067641232277376174351958080693019953378024732243763129075732499165068171168470237875348580987967740148512425201518758344757030205911031119619416763996490581551977913711646761182756531618786226541010835120092904291975494846126923510483263978074437667987560077422810120462938292680423746968095994108344184522240467647491991837793653579480334442342102339933473270535800619630342940590477752278184994533764839125736268376640933720554199782388890444619996919031351334561766248781813883867406045414518951152508504891407920000000" }, + +{ "1669833986019218156514274418186396165434871163342486930502417566 58528969848472951398118375496887849181512821636583415470809040929690124231959506 50098163184827557635697120379841225459445103589988345336880332217224622666020381 90445522698871905833766573423181067004916996574451008349087758531794463581708977 92366726802191504770638415639612204654473958526592425718659284841373421985393966 69096133232785816552402133765198624674167660496399099321713067612475604030259084 323971624832697152056406152359288553860210436839331005469891386690556929684663075996719803995137130737141925308417709520389528780839777347463558171582753", "2635514624483961079560488004237441873979133312246005082134175818331132377114926863102436691793380965631848192666106793612266994709357524826644421074908075389316030912936338175907209987972553710900613011802455058538786723149316934049388525865455871552882282353445228425640452635081303490379594663330152071465360003249884180020993032086861074931796165970076448856988084523672973069824258299029863033098237556417571526135639288006133579174344589248428714474318969988990720790226604664141927030250855550010512291136517209169959021730625428868037074528890516086527430801590050720467893089085308995719513895962750896813152", + "2413207990093478676325592386500172980330574558867366638913149256222218924700401110600319869300256745035993991818342784487193857053589994816247466074246569162659879368383295411190237107255160498774228460295857931362161062884154872938368166514128474751716517750517217000290486110198899480877593169193610813452614906598055909439037075588626529658637140089909227353944313408987644743661503976835580507054926908821206921014266535160031749397432350114673787218438589065861056449106115395189057409933330355574558853874223262465965933679584884152813357065227868165556818717270584803360466149860292769520737249610469675917864449261901859162854558012721179400237645357401213337423255109839806528503425658270050436129019270883446965562683284298538825840361267548675967778385927410390726055957928634152514415917053614892441910675109517307682075989998558764742821214685548219206933043196677521610851950501225469125512893859254575460130829051324112015464552874242522140166275233893076603452098841950130740353331198999756316969161591691095397245996664755249875720008141774247384884623389430842799829690618405724986702942913150258769060684255363816662231923570491001519802836627028431389746450987110456127797025006251203111629141890634728548553728" }, +#endif + +}; diff --git a/tests/exam_I_plus.cc b/tests/exam_I_plus.cc new file mode 100644 index 0000000..cef57c1 --- /dev/null +++ b/tests/exam_I_plus.cc @@ -0,0 +1,295 @@ +#include "exam.h" +#include +#include + +static plus_test integer_plus_tests[] = { + +{ "17009115185923538769", "-12047631083067675031", + "4961484102855863738" }, + +{ "12677011568664239747", "3269056182420253574", + "15946067751084493321" }, + +{ "9315504781982082433", "13857624532376678678", + "23173129314358761111" }, + +{ "15226508728194069537", "11481952022080775416", + "26708460750274844953" }, + +{ "7461641943684774743", "12249026721402718630", + "19710668665087493373" }, + +{ "1180469445886971055", "-3208456171287181032", + "-2027986725400209977" }, + +{ "18358552990465743315", "221529797579218180385160273426219343697", + "221529797579218180403518826416685087012" }, + +{ "-14819874956616484359", "30498815629431206969122152847973230849", + "30498815629431206954302277891356746490" }, + +{ "-11781881800334342169", "112219460388643619332860331282276228017", + "112219460388643619321078449481941885848" }, + +{ "3570694277032201957", "284821691832196381859344006870088122712", + "284821691832196381862914701147120324669" }, + +{ "-17005463295060938595", "69162171850264911722979835561124066203", + "69162171850264911705974372266063127608" }, + +{ "15647113311796203488", "150750467185419235519670165664526735459", + "150750467185419235535317278976322938947" }, + +{ "-14330150541101371097", "-13054027994001826312503071338715966858478218093171762021549815587520723118772963817341751396703629529810372702877555022105594068768886421335353882155416908", + "-13054027994001826312503071338715966858478218093171762021549815587520723118772963817341751396703629529810372702877555022105594068768886435665504423256788005" }, + +{ "7406427184711759740", "-4059250217961011548005203450962458026528281798230141192186669580689721046971433745892994467792118611646113962840750314719233572760336084100766391093756252", + "-4059250217961011548005203450962458026528281798230141192186669580689721046971433745892994467792118611646113962840750314719233572760336076694339206381996512" }, + +{ "8819522415901031498", "7274905269237471130619913887005155660991437201841760414347836177003483932007334374478344594178179032728521106519295465031750530183363793325150672647162846", + "7274905269237471130619913887005155660991437201841760414347836177003483932007334374478344594178179032728521106519295465031750530183363802144673088548194344" }, + +{ "-7242932332215698200", "-10558564312909325527488520195600871241245891651644550509993750377630234801225525279855157008009255586978047154906058790342845859331159009687703010657137320", + "-10558564312909325527488520195600871241245891651644550509993750377630234801225525279855157008009255586978047154906058790342845859331159016930635342872835520" }, + +{ "9794320575955609492", "13380937715397052566925484435342184213544885758759259410983243841206628594840271850190097746775475837233042430565529099681550277688470325394342993771343357", + "13380937715397052566925484435342184213544885758759259410983243841206628594840271850190097746775475837233042430565529099681550277688470335188663569726952849" }, + +{ "-18404048401680891243", "6690884608978704096379677348142836785900717005050936986370615083929607190833180925295418079551348559691161519822750772440155040888224482801864925665484770", + "6690884608978704096379677348142836785900717005050936986370615083929607190833180925295418079551348559691161519822750772440155040888224464397816523984593527" }, + +{ "-10763220363947284865", "-30985722824355332972176356513316569304601382411274079243859710673739383446566598659878378034375348869471278415635671865753349734809209959160389615096293457362383744562507969316522225741589739150453090393424063226271167062127000223628785686999799282795143706407082119829140399988180879618548495395684946331608899565543458192773899200054228140747414544792128323269250618482622488195333106891323515989863192944848391405358725993695671970811097285270641251816244586360288952156538400321933146150313939864593445583603568771077260174826348411367609521412133720180359748539721570562669201065857989876521301209899829037444385", + "-30985722824355332972176356513316569304601382411274079243859710673739383446566598659878378034375348869471278415635671865753349734809209959160389615096293457362383744562507969316522225741589739150453090393424063226271167062127000223628785686999799282795143706407082119829140399988180879618548495395684946331608899565543458192773899200054228140747414544792128323269250618482622488195333106891323515989863192944848391405358725993695671970811097285270641251816244586360288952156538400321933146150313939864593445583603568771077260174826348411367609521412133720180359748539721570562669201065857989876521311973120192984729250" }, + +{ "-12742462236537568498", "8711131313747826394504271797986775572294949693272674156076339989631171694968899228610359983845552623710580616605402899155485071497929100432998183040757832449369366844015907530612334721882095163137705867337969942902346066961718232788529860214990099385213558935023241940238638069647809530490438245386869385682221280939688108487754251075630026707075310465788398213293782900699868609660892232563106662995330591906155134237356516622436517046191466823447743155250482328613449506396571170001248589926831956459700467126756876526930443317428628239358666456771112897986098390410773312792390699312960051747534683311506465130527", + "8711131313747826394504271797986775572294949693272674156076339989631171694968899228610359983845552623710580616605402899155485071497929100432998183040757832449369366844015907530612334721882095163137705867337969942902346066961718232788529860214990099385213558935023241940238638069647809530490438245386869385682221280939688108487754251075630026707075310465788398213293782900699868609660892232563106662995330591906155134237356516622436517046191466823447743155250482328613449506396571170001248589926831956459700467126756876526930443317428628239358666456771112897986098390410773312792390699312960051747521940849269927562029" }, + +{ "9991390529516174614", "7879872958436992955898278403297937595295396115022400543178444946646147916754852888072481665174663073269556311758611700754643170639645548596647557683044355930340624784190093631808382820554407595007761070026239341594197877214157118335743842022627898879376346092898666610367809537340994845045475091410516226225078052019727419030585524815982151736622865401299588936172760762386183577504972623377661437665668080131418564228642443266935225613702941906491478788336262289516199380144218708241406077806669686589734333554945412904560108150202389909124657090061223183441083590340175629756198442568877659538345749595968764873879", + "7879872958436992955898278403297937595295396115022400543178444946646147916754852888072481665174663073269556311758611700754643170639645548596647557683044355930340624784190093631808382820554407595007761070026239341594197877214157118335743842022627898879376346092898666610367809537340994845045475091410516226225078052019727419030585524815982151736622865401299588936172760762386183577504972623377661437665668080131418564228642443266935225613702941906491478788336262289516199380144218708241406077806669686589734333554945412904560108150202389909124657090061223183441083590340175629756198442568877659538355740986498281048493" }, + +{ "831234034418847630", "-744676478858160349467117341859049692149463503380690495147216354303526704924280287782902146026018180364963325847811379182950159627878800024734206345960410146056000392683000433501805629464626281031086102425271022388473812300724085127447081771317912465921636737545371909901577246384446144919253141375367648958387948463576516115079816552636772639965957498569187848459747361493535081532845254971492261148968198806736512864867151355002902241562014241077734122599581732704243705918200179789271894804233542502502119523149682814025979598424744685548054183678652651244898867735764030968089217841214778606507809487462642341164", + "-744676478858160349467117341859049692149463503380690495147216354303526704924280287782902146026018180364963325847811379182950159627878800024734206345960410146056000392683000433501805629464626281031086102425271022388473812300724085127447081771317912465921636737545371909901577246384446144919253141375367648958387948463576516115079816552636772639965957498569187848459747361493535081532845254971492261148968198806736512864867151355002902241562014241077734122599581732704243705918200179789271894804233542502502119523149682814025979598424744685548054183678652651244898867735764030968089217841214778606506978253428223493534" }, + +{ "-6996572501442843347", "-16567158719848992553565776505785820491834685475229611199353714982570065913508303466008005931649515528390057456882757990896824841386431756898386429000065518724021230756426613661219891419166146764347562529640689229693578574350948436847247856000438153789455857903402883189892697143647998643667467614427922009931545254965075041050860609824086811877108940020349157317276288348430058535959434983921323332907180869396258655826781438419383792024592535415693101119109484610789291889841197827977530804650015884500878613240443324806805475203272442094530735476095374446946252236490708915034012846683015547314889561060687692538144", + "-16567158719848992553565776505785820491834685475229611199353714982570065913508303466008005931649515528390057456882757990896824841386431756898386429000065518724021230756426613661219891419166146764347562529640689229693578574350948436847247856000438153789455857903402883189892697143647998643667467614427922009931545254965075041050860609824086811877108940020349157317276288348430058535959434983921323332907180869396258655826781438419383792024592535415693101119109484610789291889841197827977530804650015884500878613240443324806805475203272442094530735476095374446946252236490708915034012846683015547314896557633189135381491" }, + +{ "-8920936222630165483", "-18738991973681679876688842391791783563249057933653045519186959571392922172943405646958686202208790537612746921398028331540617848217445632123805070077600768524509025758950743971128222843292926773668584735575066246660802064630842300367821042873152766467703905048558085377302000898639290554395913805527529259855535801856020623830262396582180677933562523957295341539162448074423901242873918231922121053192425691524797238343327318801359521456598967984637483081312932069399045363737622797213185099130529375169698811801965974416555301085043300426947769193582129151016159057101028336667142913854943018973494705119572045938607", + "-18738991973681679876688842391791783563249057933653045519186959571392922172943405646958686202208790537612746921398028331540617848217445632123805070077600768524509025758950743971128222843292926773668584735575066246660802064630842300367821042873152766467703905048558085377302000898639290554395913805527529259855535801856020623830262396582180677933562523957295341539162448074423901242873918231922121053192425691524797238343327318801359521456598967984637483081312932069399045363737622797213185099130529375169698811801965974416555301085043300426947769193582129151016159057101028336667142913854943018973503626055794676104090" }, + +{ "-243510292488206214847646757340020705642", "5940577100149745132", + "-243510292488206214841706180239870960510" }, + +{ "35446324064743728955945058978206455057", "-6248622708755929572", + "35446324064743728949696436269450525485" }, + +{ "-285342226760657637664173494795024413673", "-11942737781617905307", + "-285342226760657637676116232576642318980" }, + +{ "180790435817422032042321866247362452865", "12401641959336396832", + "180790435817422032054723508206698849697" }, + +{ "-179994871947239535956826388240542999950", "13573822506399140772", + "-179994871947239535943252565734143859178" }, + +{ "-308198027295905163635866438671452347268", "-8790069282378476990", + "-308198027295905163644656507953830824258" }, + +{ "-139324757925833055762410227358605285566", "-190622873846936719063564661032771271922", + "-329947631772769774825974888391376557488" }, + +{ "332866352618304570046318203427223999347", "147978646177673305481282943528696833018", + "480844998795977875527601146955920832365" }, + +{ "-39471620476300923970352914034802271156", "28992893610776120142668950821916856486", + "-10478726865524803827683963212885414670" }, + +{ "274120253734611965146455315763505869288", "254675910805265090692978775702306142625", + "528796164539877055839434091465812011913" }, + +{ "-122086811464559635596206661886176775901", "287312583034687582188356355813963609701", + "165225771570127946592149693927786833800" }, + +{ "288576174771266329955482943556556984728", "-57843540651903655425270706396868707777", + "230732634119362674530212237159688276951" }, + +{ "-47977736580820486006305788441965482221", "984809271313988066640898939725532304075331399066274624928410251834520283291912387208948664716457549646483445981126881113426109906085249657168046936670489", + "984809271313988066640898939725532304075331399066274624928410251834520283291912387208948664716457549646483445981126833135689529085599243351379604971188268" }, + +{ "21225484205143479814642328762121362291", "11839789093732539327981861490012713257538550745921177905266671749716203131127256902110452504526721633943016923389974867770082516862899595554460170417713940", + "11839789093732539327981861490012713257538550745921177905266671749716203131127256902110452504526721633943016923389974888995566722006379410196788932539076231" }, + +{ "-193095363331703875886398909106293703000", "4389392021031719669078675478621418677903292147307684123866099084349756491860737402449105804868232530632178577388168068485304437343508442251302846768269976", + "4389392021031719669078675478621418677903292147307684123866099084349756491860737402449105804868232530632178577388167875389941105639632555852393740474566976" }, + +{ "-14827657635864183514988182371035598180", "-7256545787852407071411458891023580461638051949278710509801472046178301830006724297747051044450550248499056073213660185258676369175307019300952192657194576", + "-7256545787852407071411458891023580461638051949278710509801472046178301830006724297747051044450550248499056073213660200086334005039490534289134563692792756" }, + +{ "54301423175725658626298504084995819705", "-13385853291610595576947504757201441006088030688464261540642594993520424631577281077984278942244446266776534612440941312995898184903431893212829646845766101", + "-13385853291610595576947504757201441006088030688464261540642594993520424631577281077984278942244446266776534612440941258694475009177773266914325561849946396" }, + +{ "195114404067053480147948948510253723990", "-8373866462448797623435948949281383906369538962237624940506813188612614128993186653340202956656303504523161255703176374041758276069255591562198514767063594", + "-8373866462448797623435948949281383906369538962237624940506813188612614128993186653340202956656303504523161255703176178927354209015775443613250004513339604" }, + +{ "-308030589512186791277525017840002670741", "-11922204352024596469278978325035646517433105521287613403902396944414655739824695945028308092245747333098422116078042326104667969967224788442970266049942774583538734406057081597034454910987815490244451193242377705191422489528853976486607580169986057592557285271953385769215318545520155212402919465580052078255078759756709086185424029620805084776442744700501748376290562843380642608395240491162047933014854466267084965223593172702334466729933986413870670083326499598274393380692146118979961818816348097032083332695128587696590646086980241100792624502607816103195636761141133903550454815591457829485684936036414823492160", + "-11922204352024596469278978325035646517433105521287613403902396944414655739824695945028308092245747333098422116078042326104667969967224788442970266049942774583538734406057081597034454910987815490244451193242377705191422489528853976486607580169986057592557285271953385769215318545520155212402919465580052078255078759756709086185424029620805084776442744700501748376290562843380642608395240491162047933014854466267084965223593172702334466729933986413870670083326499598274393380692146118979961818816348097032083332695128587696590646086980241100792624502607816103195636761141133903550762846180970016276962461054254826162901" }, + +{ "-172649878347923210775992373331623646864", "22180935775581457002090790736532281654456312526625354262953960635330604551829750571440878712430708012807252279301365732385899228826740712544768476577874129759972563823209525283326887563301081200476495752033290851190327066070873711444930389093339915885090143783170994309089448293499799071372787520776773788274677288230540162485916160484352398851925328125588729604931589867889917097887951581817207079060016091919559509735997493084833476849835444339835031436580214492450731100723026312163752403946315983551266206214298679421644737804098691991631489261658890937663698502561036246447760919715595005106669653475931803053499", + "22180935775581457002090790736532281654456312526625354262953960635330604551829750571440878712430708012807252279301365732385899228826740712544768476577874129759972563823209525283326887563301081200476495752033290851190327066070873711444930389093339915885090143783170994309089448293499799071372787520776773788274677288230540162485916160484352398851925328125588729604931589867889917097887951581817207079060016091919559509735997493084833476849835444339835031436580214492450731100723026312163752403946315983551266206214298679421644737804098691991631489261658890937663698502561036246447588269837247081895893661102600179406635" }, + +{ "17539006966816771902104329685391462527", "15609797782337099611892065465036826453911053690739041627254619195700021040383385710184052653282070244915503750549545390475671883312314708978681904377133928647935359080875691628246716591529028104762422990155477702994042953196747769893182153631482194578269859879402160062955490194674372351117284129320011166238130774752386987036267064693133554447596069886693581191241594745541512444806003236372840085705813835001957163976961730871756250344335996073970142337882238844723800849054637237549515249957267772181010402413375667537558243971058326641257721901094391380667244006959028327507917720426571969997513984360849930719808", + "15609797782337099611892065465036826453911053690739041627254619195700021040383385710184052653282070244915503750549545390475671883312314708978681904377133928647935359080875691628246716591529028104762422990155477702994042953196747769893182153631482194578269859879402160062955490194674372351117284129320011166238130774752386987036267064693133554447596069886693581191241594745541512444806003236372840085705813835001957163976961730871756250344335996073970142337882238844723800849054637237549515249957267772181010402413375667537558243971058326641257721901094391380667244006959028327507935259433538786769416088690535322182335" }, + +{ "244901855797156286376563377540855746602", "-22138106346578776369849317622304392466030036563754663379976505966920461958652141160336156065177498990718609170201272980114106671808245437660234479124938853665375934080221740523696180221118540569603989748587853373569525751680828044059607889572522502629277877343410298879764820905044284757389006201848194571453112545228115550224254565141563427486518108434758694923122284117299374156393942906293546318323661938734959824887786185558612820887463537294120950912969343488704744978847504513710882720654330147775174336365363311173472002077960424794151168301281665765411704505095008907760396535767621855642720080219960822554492", + "-22138106346578776369849317622304392466030036563754663379976505966920461958652141160336156065177498990718609170201272980114106671808245437660234479124938853665375934080221740523696180221118540569603989748587853373569525751680828044059607889572522502629277877343410298879764820905044284757389006201848194571453112545228115550224254565141563427486518108434758694923122284117299374156393942906293546318323661938734959824887786185558612820887463537294120950912969343488704744978847504513710882720654330147775174336365363311173472002077960424794151168301281665765411704505095008907760151633911824699356343516842419966807890" }, + +{ "-119403662992279138748600939857239307122", "26272999248235953724172008428088697264933069743507017434844709711501131900922919455931092196539942532993887162365511473221418376205773427597933886270411672062672089518774390132453916538404354895529975888201032175628249480896964400801763570333497287321002961557096975786141940970260074557095118887294558700145949117395512768347250531196100831164663613049206690894640391431616112104502483838173255614981302462548882276825096564828583591963617871547373532874400764134244496979962241959713525053686209002866840900623246072884125102845824992994967009109046451949348656842486048332953732384499190437432898387573320391878853", + "26272999248235953724172008428088697264933069743507017434844709711501131900922919455931092196539942532993887162365511473221418376205773427597933886270411672062672089518774390132453916538404354895529975888201032175628249480896964400801763570333497287321002961557096975786141940970260074557095118887294558700145949117395512768347250531196100831164663613049206690894640391431616112104502483838173255614981302462548882276825096564828583591963617871547373532874400764134244496979962241959713525053686209002866840900623246072884125102845824992994967009109046451949348656842486048332953612980836198158294149786633463152571731" }, + +{ "313963939617834410089002930298454269912", "23286645405607099799151331553995799851855144387826191186590140820016670502830395945076644578998873585162998873396623634135231418574284200209367505115739462344028303923666952261030907434438322884189133236837089851688275865098623902644385995630973049587854251981548128145516004461191094062488421288607625783540996659060285661398859383778209495884203323937672739376151794507745282074538961033778823733980759695886879886017489555795079194346438911010371103435094677167286870898482214310646392174423422237727456012197253183422715313378603607058548706460095379882633958651034759773864354021315490712575535559549015858088608", + "23286645405607099799151331553995799851855144387826191186590140820016670502830395945076644578998873585162998873396623634135231418574284200209367505115739462344028303923666952261030907434438322884189133236837089851688275865098623902644385995630973049587854251981548128145516004461191094062488421288607625783540996659060285661398859383778209495884203323937672739376151794507745282074538961033778823733980759695886879886017489555795079194346438911010371103435094677167286870898482214310646392174423422237727456012197253183422715313378603607058548706460095379882633958651034759773864667985255108546985624562479314312358520" }, + +{ "2000877973959266893810594143560134441447453310844726478119781029700338468704683515329516333146806175216349912753585564808803731447160643580198590073658869", "-17993015014355471903", + "2000877973959266893810594143560134441447453310844726478119781029700338468704683515329516333146806175216349912753585564808803731447160625587183575718186966" }, + +{ "5492930533666246223206322654398877802091439062008700770880939594548305919677404080859141226095489505872709347538974725998600861651942609010590873980143878", "15372278140141207703", + "5492930533666246223206322654398877802091439062008700770880939594548305919677404080859141226095489505872709347538974725998600861651942624382869014121351581" }, + +{ "-13405500833215428652808705089190188280715732437731292502890523313631564795139560159124390691283401484515088713758307366404145018349044148223082253439210893", "-14793401891248640808", + "-13405500833215428652808705089190188280715732437731292502890523313631564795139560159124390691283401484515088713758307366404145018349044163016484144687851701" }, + +{ "9945195259699924701593703207751086973468898794114625092150620088406276196469184233537941913755508476427888065765634203723512911676149274871082481174186606", "8699133332160461067", + "9945195259699924701593703207751086973468898794114625092150620088406276196469184233537941913755508476427888065765634203723512911676149283570215813334647673" }, + +{ "-1785165974800693006461065312083337532938610906605533088558498259067461510781028452552786542598361030690629530721209490413999022804146471920873844686294838", "-13079925952361275418", + "-1785165974800693006461065312083337532938610906605533088558498259067461510781028452552786542598361030690629530721209490413999022804146485000799797047570256" }, + +{ "-4861207515430071951958387366611380234482792653010151054346367776006873932152600469133110239669746470475230906073865131648496652783311445471793936775767736", "-9381557743227419896", + "-4861207515430071951958387366611380234482792653010151054346367776006873932152600469133110239669746470475230906073865131648496652783311454853351680003187632" }, + +{ "-6638723469626495957966112633999375479181736600737250559572415894485618850919815869703127084789143821420728194272094956858541960962483734293877093635361160", "277811698220276334443479876776376776138", + "-6638723469626495957966112633999375479181736600737250559572415894485618850919815869703127084789143821420728194272094679046843740686149290814000317258585022" }, + +{ "1983880417172931934469534542170437296262471214582817006917470485544552211448284732460451903536334682269123998240709059499894818265755197559390728940140016", "-118940994129137705779355371753506018694", + "1983880417172931934469534542170437296262471214582817006917470485544552211448284732460451903536334682269123998240708940558900689128049418204018975434121322" }, + +{ "-9354509264984586574958285335910611806441061705184818350015454221731287473282231343722010109181841005578131927454778025302197744540571159656556971614966757", "120224841184491944160266976391113485817", + "-9354509264984586574958285335910611806441061705184818350015454221731287473282231343722010109181841005578131927454777905077356560048626999389580580501480940" }, + +{ "4389359421234641412950681847970318834150108533025088077429496538447029921663033978550089607257809597829358374972237448178553189381274150213236222139873594", "106674783386899772113212633712093787897", + "4389359421234641412950681847970318834150108533025088077429496538447029921663033978550089607257809597829358374972237554853336576281046263425869934233661491" }, + +{ "-9319417879153488839579936799737117639058244394679644240663244688680826325564084529474537634510092069422987165268448907193562300482925125162731530249763801", "192969103435503875767216559494769734726", + "-9319417879153488839579936799737117639058244394679644240663244688680826325564084529474537634510092069422987165268448714224458864979049357946172035480029075" }, + +{ "1394404616168163951844558734723678125985464491792846741433683801962971891047718103736551854371207400145441134823994228143957746922511631911996296931168332", "-211230038021470285136061932161632203274", + "1394404616168163951844558734723678125985464491792846741433683801962971891047718103736551854371207400145441134823994016913919725452226495850064135298965058" }, + +{ "-2935941510094051560788359387128767361559188973149773593522440619832472030019457317998381634585179453958737810428870232715146002408187749944694186205812791", "-1221176156661231926164756142840452419679061324806989304452215660535991083923207702827717652226257158321829748247784282139952864899457896871473184473608543", + "-4157117666755283486953115529969219781238250297956762897974656280368463113942665020826099286811436612280567558676654514855098867307645646816167370679421334" }, + +{ "-1338674579024795395027232680327531457830908239605718353094975139226848400289367913459076082700361212506196070727982446232782659114647371030398516119682505", "-1298372177520411182435886041880377054374169787570856408996533471838082317927648953576721017727347029007573543972764860712708420553928791798580799809858729", + "-2637046756545206577463118722207908512205078027176574762091508611064930718217016867035797100427708241513769614700747306945491079668576162828979315929541234" }, + +{ "-2072456075229532951804023218627137969798924912365258263779029006567941400203608770518731715660383378937120213112973528605594220795605977413985543331908189", "-9744489461776287963808523409593616918248399004543154581056479712028497082820841423941781438667661074968238703192056877665754560746003512076830245760254982", + "-11816945537005820915612546628220754888047323916908412844835508718596438483024450194460513154328044453905358916305030406271348781541609489490815789092163171" }, + +{ "-2570682164188734368809161664810917340861573482754788446510182252413437925852206735928397938304353826925422441004271229738766803460790995673395984247950088", "656920705293329551826685120408221577679101260931105312141757138825917579070505267306626244216341686712802796891966598838285570807961966448181138356047523", + "-1913761458895404816982476544402695763182472221823683134368425113587520346781701468621771694088012140212619644112304630900481232652829029225214845891902565" }, + +{ "7846359203342053693101523606887617345982401999003795257520576318451663998927274759872692123323796450295314377046602880394071105863527900699633560551732837", "3683380639347829102597675045842249667669675715600522157867595962635108482512780509393310714588544837398923613138772339053021025559943198965234376657126821", + "11529739842689882795699198652729867013652077714604317415388172281086772481440055269266002837912341287694237990185375219447092131423471099664867937208859658" }, + +{ "-11692323148567132684205145901751681947225824260005631214936266006610207543813382900867093989444659986091234552140689684476541703112098935301322850961583953", "-8534276689564199122569555420819240948691777228327984555753862457592427992599992931175844172478864477440165366128106812103785256271256853749622592560655914", + "-20226599838131331806774701322570922895917601488333615770690128464202635536413375832042938161923524463531399918268796496580326959383355789050945443522239867" }, + +{ "-10734754884168724884333968138739681643742524619139397687680049322697740991391014196697040576174049452737571835233123127815762146577096625434481167057340772", "17059878151450238567815178684522345445687980385106446646013863901583786249398194029757376950491550197185231926262467028755342392379269039238766592672298850588065335172902157386017520689203005559576263548017475991638498600879259882041932152385436968424098224966518534467302264172016376096778201462205990822825056602379115848799619564610033123837036507127427054121975400703490855123544706355545059512146550901507159940126280812512339749605195422987937677650572797378799103456094203126081464905326203083057134061673694975250599375795827437561275156235513192978645909947341297774926450637694325145427434486258223666250272", + "17059878151450238567815178684522345445687980385106446646013863901583786249398194029757376950491550197185231926262467028755342392379269039238766592672298850588065335172902157386017520689203005559576263548017475991638498600879259882041932152385436968424098224966518534467302264172016376096778201462205990822825056602379115848799619564610033123837036507127427054121975400703490855123544706355545059512146550901507159940126280812512339749605195422987937677650572797368064348571925478241747496766586521439314609442534297287570550053098086446170260959538472616804596457209769462541803322821932178568330809051777056608909500" }, + +{ "1982582032974021971225071139786536402936929744496433027195224299475980201425925452469321205602618940472354066218156609448199804973454183972974358405933935", "-5591374624026484498020036332218412149978824230210339582240360391202660977358546150723165491729699122647688030937226316069237264083850854032732663284717882873051337566653841254365703461654061656817936193716386141166210237666314879751427421825450110467888973152907618520704486700443275358649289847595635931220181024199692771066498714511145489237541761266539978351840438236927937894376002981658065431416811632941197501676956304254109064936038146674412392128883565757325842468006824235119684861972224857533964558963441079998949499582965764591461900562931342373507763081479989957632695010603500633322408246084430203281475", + "-5591374624026484498020036332218412149978824230210339582240360391202660977358546150723165491729699122647688030937226316069237264083850854032732663284717882873051337566653841254365703461654061656817936193716386141166210237666314879751427421825450110467888973152907618520704486700443275358649289847595635931220181024199692771066498714511145489237541761266539978351840438236927937894376002981658065431416811632941197501676956304254109064936038146674412392128883565755343260435032802263894613722185688454597034814467008052803725200106985563165536448093610136770888822609125923739476085562403695659868224273110071797347540" }, + +{ "11532228364136654310006206557545352284448588590560137249197311142901246089838098630841794341370689745410654263817911440601934362503092628725755210859171724", "-25776236925500995542036591604259749301547568770017466769502569415611770276300787105037848049555500555975152877716727294374436703766730618054071617947449695177320842403963009384468257891933593584757723535299746543328292715942626303315235241470269740287031317322772461137186093930239744879822272349431389779234805703118929710210161489122272898252221025966631463842234537744822906696719691188223105175714602909117904182229960075276443648211003011686250829474364425483901920822837775032295913486152631638908227467242772081310515646217115760180349854601959031626524004201825198439309850266508687796415478396821644422350208", + "-25776236925500995542036591604259749301547568770017466769502569415611770276300787105037848049555500555975152877716727294374436703766730618054071617947449695177320842403963009384468257891933593584757723535299746543328292715942626303315235241470269740287031317322772461137186093930239744879822272349431389779234805703118929710210161489122272898252221025966631463842234537744822906696719691188223105175714602909117904182229960075276443648211003011686250829474364425472369692458701120722289706928607279354459638876682634832113204503315869670342251223760164690255834258791170934621398409664574325293322849671066433563178484" }, + +{ "-2603756427337798371354526130541868239006085657393372011847827118826669474695402075575479286172808099892726251004549675772420422527946534088483901153485670", "-10844269742362409682236511127219508926736627172993604953084481596070757241623728297275447608738915355190715664012379562650777199088096670239050254578284071100042116609747208178716191571268815994455064584659920497876052406993834873124981417288518101426395560764186717660091472734401090302285129741058888303693710456902635092811413971399734306158050053239768185860958896447298052082493590498954512083131068867270078638929796561440903919430094619437872896595720463663570751134804664228918188923926951933302878771189484614604311920655871182974081898031051411394311700207305532216445616083858025977851570522763537300875989", + "-10844269742362409682236511127219508926736627172993604953084481596070757241623728297275447608738915355190715664012379562650777199088096670239050254578284071100042116609747208178716191571268815994455064584659920497876052406993834873124981417288518101426395560764186717660091472734401090302285129741058888303693710456902635092811413971399734306158050053239768185860958896447298052082493590498954512083131068867270078638929796561440903919430094619437872896595720463666174507562142462600272715054468820172308964428582856626452139039482540657669483973606530697567119800100031783220995291856278448505798104611247438454361659" }, + +{ "-5929887196386997518766568868806997104240129372360669348628384183712406620199102166145939206783172815805659513128544493795329100599632286529420772709366102", "24544958491142793859949310604465694574872439331169358241746200808802938771527900616394258199996170862256988647191747967628756772368808644819831481350919782560499270148419601775750932556119448001824346026042068416905254113155445053931789404515589532235225580737103411251232560863878948880220469490014568323308965914171394449781093816607870593225534700167342589927524232815571862258490314644577819742372918446373756857848586825568514909823940075182825283229026250682015641747568282510036326125505522447591703308661608718100933027549520132308555240654655887041040427813131621391320267698106519650611462269033902177180035", + "24544958491142793859949310604465694574872439331169358241746200808802938771527900616394258199996170862256988647191747967628756772368808644819831481350919782560499270148419601775750932556119448001824346026042068416905254113155445053931789404515589532235225580737103411251232560863878948880220469490014568323308965914171394449781093816607870593225534700167342589927524232815571862258490314644577819742372918446373756857848586825568514909823940075182825283229026250676085754551181284991269757256698525343351573936300939369472548843837113512109453074508716680257867612007472108262775773902777419050979175739613129467813933" }, + +{ "-8848084327536592532063677611386811805244460767433749071435930786126721080365289638381557872263825830664387392539638767251180242665642373539064690745095464", "-15917950175678012281826361248776190984758236997789474333609547749168308439513527143790323694526378056113636462939674273462177686456811495629631337058042159570336251822399402513133598701991665209363955263097315081570618652783181494594400709239428597117944511110842795526862595552977665064029517628515465251448116061875878430407784298951946811321795808932206846491091803276390661869369638950672478828532423383951689632136029256108992610781912267083149156104328033893238864631158195280554850035949666897861529711006187241710164902350100555999894332438423857208747342184052953230247487231455921360593096823760117493579248", + "-15917950175678012281826361248776190984758236997789474333609547749168308439513527143790323694526378056113636462939674273462177686456811495629631337058042159570336251822399402513133598701991665209363955263097315081570618652783181494594400709239428597117944511110842795526862595552977665064029517628515465251448116061875878430407784298951946811321795808932206846491091803276390661869369638950672478828532423383951689632136029256108992610781912267083149156104328033902086948958694787812618527647336478703105990478439936313146095688476821636365183970819981729472573172848440345769886254482636164026235470362824808238674712" }, + +{ "-16314775600714318471451792035636584056297958597339492996728118376578145765736873313518831390349547274517050864260054903974054712997529177834428786007341762649083404743713562157667828894017440065599882523458121037421757904691003094608420565550031561905074671735751685371533975894842331113347413787808917193134135744321547478500861021485075363990553639161661734684228250909589741380076008551020384304303171431833670236949934603973673998262066558668396388979463892768199916011368116729432353268535563246463324517035331079693172060671712718486388759443825620676228470068291448236914050793177812037679396721657020438979754", "12553426083939460917", + "-16314775600714318471451792035636584056297958597339492996728118376578145765736873313518831390349547274517050864260054903974054712997529177834428786007341762649083404743713562157667828894017440065599882523458121037421757904691003094608420565550031561905074671735751685371533975894842331113347413787808917193134135744321547478500861021485075363990553639161661734684228250909589741380076008551020384304303171431833670236949934603973673998262066558668396388979463892768199916011368116729432353268535563246463324517035331079693172060671712718486388759443825620676228470068291448236914050793177812037679384168230936499518837" }, + +{ "20637030084881771176788188367974505419050866216433677435050410899110162793040751338330447574748263391136356400036001988938659722098883893353523409458775455519257672423829361150611806294256710309281788819450225670112435352092313483086404714074567539245791066202051788986426960935796927738180831688497683293306590464598379493141645539253898709000874685535467854788184424886911457134522632486730390913239660179785071885982403741669161655812015114272497907946919026898579927936299607156006210124954460880383605958519412435713868501997649784658832599101777001703519408664662715322044086646014163774269660274683400619225321", "11620128128044940816", + "20637030084881771176788188367974505419050866216433677435050410899110162793040751338330447574748263391136356400036001988938659722098883893353523409458775455519257672423829361150611806294256710309281788819450225670112435352092313483086404714074567539245791066202051788986426960935796927738180831688497683293306590464598379493141645539253898709000874685535467854788184424886911457134522632486730390913239660179785071885982403741669161655812015114272497907946919026898579927936299607156006210124954460880383605958519412435713868501997649784658832599101777001703519408664662715322044086646014163774269671894811528664166137" }, + +{ "-9838804688358141062268493389453191808060717708062736103828856866310283812230958467655270667206937622979717683919584610288962829724022506216738929136418489468786902364550847498615864720240589837282441807174290461916292258263929411081218952357662703079709351365960916688275651864441386750529258343003652300629003597744958152243494244227986280506395347894285277364095898602965258114321853474000520432831298793365139040664543928707100657375292032051256485942532600998813627925626928634068613637417702688610315924917761411247617905738119218110678854564441914784262998574445847209847985439514580300936248281049628734475702", "2380166482232871816", + "-9838804688358141062268493389453191808060717708062736103828856866310283812230958467655270667206937622979717683919584610288962829724022506216738929136418489468786902364550847498615864720240589837282441807174290461916292258263929411081218952357662703079709351365960916688275651864441386750529258343003652300629003597744958152243494244227986280506395347894285277364095898602965258114321853474000520432831298793365139040664543928707100657375292032051256485942532600998813627925626928634068613637417702688610315924917761411247617905738119218110678854564441914784262998574445847209847985439514580300936245900883146501603886" }, + +{ "-30961575335426221869515496362216292453766907587859856766456625722888557357647164641922707199324601608700561081422636642523431947551124957385652791834855425829101761914145137205962610515642614866296480715893528289170482422505734612327038754622917335073993027434927547277037587173529054849390646376806910407207016292483185533697336599641898250465186168797820802225861771331652801064811222606773495565340386327294310913503461903243119204619412324538886439122443769008953829820425376589389335553937319588224864611583436327810214798652896733118881040503785110481197462772022447173744898802421806800203373153221004361953729", "-10586442965055062759", + "-30961575335426221869515496362216292453766907587859856766456625722888557357647164641922707199324601608700561081422636642523431947551124957385652791834855425829101761914145137205962610515642614866296480715893528289170482422505734612327038754622917335073993027434927547277037587173529054849390646376806910407207016292483185533697336599641898250465186168797820802225861771331652801064811222606773495565340386327294310913503461903243119204619412324538886439122443769008953829820425376589389335553937319588224864611583436327810214798652896733118881040503785110481197462772022447173744898802421806800203383739663969417016488" }, + +{ "8835746018617511846981408800319983340292665114153404569022025834059427359831684523399830234196625160662387716033871154398104436720494608541518837969397374272734698261557358249258503982414578618525420572597611597792132117034895074841909295420434392963714805547538976612884853497014341345150095544449860198192757839489063747595073430612069212219930749783824683135433987509303139260133564905961552149844964215891730262218278214035649706577154652729844092199333026620127958228847111442161350881527928460177763370427262298116900358910460957772350452949782281117704005514462730290063772968929608448642592954601418753021512", "-12227722924075527556", + "8835746018617511846981408800319983340292665114153404569022025834059427359831684523399830234196625160662387716033871154398104436720494608541518837969397374272734698261557358249258503982414578618525420572597611597792132117034895074841909295420434392963714805547538976612884853497014341345150095544449860198192757839489063747595073430612069212219930749783824683135433987509303139260133564905961552149844964215891730262218278214035649706577154652729844092199333026620127958228847111442161350881527928460177763370427262298116900358910460957772350452949782281117704005514462730290063772968929608448642580726878494677493956" }, + +{ "-5455184800550144006991157215735481579353213544152145628297990102571936052187486515129266239245491863623978659179559754999567936067584384479787934704340911556625153536160778495579370425428019248950494107696016864499055854257192071541354806671987402367524770228296322497224645429524493838356022616251290117624472061673033274133156467148770562815676767117605001434288573911556053311048284534341905722947046607192815465807736361991479044698448267471087552952494477144251510778491315012457514838113324210534577956298926109164909779987221094000880908857594198276812276890284008572664102792405452379662935026125770444036994", "-7349798942312432150", + "-5455184800550144006991157215735481579353213544152145628297990102571936052187486515129266239245491863623978659179559754999567936067584384479787934704340911556625153536160778495579370425428019248950494107696016864499055854257192071541354806671987402367524770228296322497224645429524493838356022616251290117624472061673033274133156467148770562815676767117605001434288573911556053311048284534341905722947046607192815465807736361991479044698448267471087552952494477144251510778491315012457514838113324210534577956298926109164909779987221094000880908857594198276812276890284008572664102792405452379662942375924712756469144" }, + +{ "27233955893140063612427006607965940109569052437681267421929959186535416115028420267622879017163568256526042146282241931623674996867133390355390677118211537487769195270234259640386625552763891339073878417517169618832945750393661600092643257470064376916337734385887099957095417541169462231630821139075814859604097878094729685589777579267192538715202397220666651307185763054526407234767132218634060693076054116575833737797189157152326979078121760900891899319809724675232853322526718686306470372869701173824664984405178677187081936624687293494821338781534163633206006387449585716391843039459733925494003066841874935048611", "-66646390577667468207341453008390168215", + "27233955893140063612427006607965940109569052437681267421929959186535416115028420267622879017163568256526042146282241931623674996867133390355390677118211537487769195270234259640386625552763891339073878417517169618832945750393661600092643257470064376916337734385887099957095417541169462231630821139075814859604097878094729685589777579267192538715202397220666651307185763054526407234767132218634060693076054116575833737797189157152326979078121760900891899319809724675232853322526718686306470372869701173824664984405178677187081936624687293494821338781534163633206006387449585716391776393069156258025795725388866544880396" }, + +{ "15030400024888781078933103028897733817304421960545019199443871381537070197157227994520524631721701055962609956080413517776229513420814407790533237358129529547793422514837651333555776540939235592155512951229106778709351772195248438493792786143040421233061520515971787881798980515709417481015662862327435825812557205663033601853937647320838585333754027488605638576977560072206293290493215523194883494322543800546276353830683084405428005815296131527861252717516620765986589669237487765523936713749717927502645633123584240464131140829496052170285171610845098023517906586134613874506419828208611247177336492131262918439281", "-164048419232636429449474429717211197442", + "15030400024888781078933103028897733817304421960545019199443871381537070197157227994520524631721701055962609956080413517776229513420814407790533237358129529547793422514837651333555776540939235592155512951229106778709351772195248438493792786143040421233061520515971787881798980515709417481015662862327435825812557205663033601853937647320838585333754027488605638576977560072206293290493215523194883494322543800546276353830683084405428005815296131527861252717516620765986589669237487765523936713749717927502645633123584240464131140829496052170285171610845098023517906586134613874506255779789378610747887017701545707241839" }, + +{ "-10227062646189307616073129048534031298512434237226774743330733206156788005874968173984804649812506029813402205606562016228122184161577517837608957023376079537037472977098465137152327215807765130656192272994478964341604278041664840636982572214751638093860605132350960802560601354006634296348422600320863531059118477125143903734159707623839282511184908969206873548650544269932394344952983661665472663102992782521888857016369837211403335306200813816060883478434441858442549261115972947741929087886423170398410216855322384956160289855500229952405068604320121652911887067414460828300146993858360430784079225137421074839819", "117460076430162201914796277915447781936", + "-10227062646189307616073129048534031298512434237226774743330733206156788005874968173984804649812506029813402205606562016228122184161577517837608957023376079537037472977098465137152327215807765130656192272994478964341604278041664840636982572214751638093860605132350960802560601354006634296348422600320863531059118477125143903734159707623839282511184908969206873548650544269932394344952983661665472663102992782521888857016369837211403335306200813816060883478434441858442549261115972947741929087886423170398410216855322384956160289855500229952405068604320121652911887067414460828300029533781930268582164428859505627057883" }, + +{ "27989453264793973121573869640708223239762902243991948581280654553806618470632044367386680716040316895884976837122054709584963028986161694425215067648887944710852278135008221491665079705797192389681328802747226171436158375378499411314855257919224316919346771317457123252623293612958336691335423245293660257386649100685560072354549579281852792682734916555498283053758141666658137856828164206947320523255487437004565021167276952652515632644458005291855624829941937578229983628962137595011570216766689546500517528191189928660433013004254032861383790553611840534023221000900694995707453499030166286828319347894538505334235", "-59175168207571178843658955348404514921", + "27989453264793973121573869640708223239762902243991948581280654553806618470632044367386680716040316895884976837122054709584963028986161694425215067648887944710852278135008221491665079705797192389681328802747226171436158375378499411314855257919224316919346771317457123252623293612958336691335423245293660257386649100685560072354549579281852792682734916555498283053758141666658137856828164206947320523255487437004565021167276952652515632644458005291855624829941937578229983628962137595011570216766689546500517528191189928660433013004254032861383790553611840534023221000900694995707394323861958715649475688939190100819314" }, + +{ "1178650930337394440162727078866515771626896502845852711186000991913866844090831426017480263676964607121490209778220339316756171449922437605552456088105443130477974682689512446683178356259305893852096425478878588001446154476458310269704392486398646169362313605456233489086567865316333034897433650974160168545492823208575634152241341906068149887959566983066154182855136114289266802474404127414747112706158621650063987662749553991791509795764642256261917497984177610694405881831052199417235241109412927893781778469398975117797578753730248539151297798807326284978255001046995523851829184120171969918537718488250577987049", "-151873924489040812813761508259707631973", + "1178650930337394440162727078866515771626896502845852711186000991913866844090831426017480263676964607121490209778220339316756171449922437605552456088105443130477974682689512446683178356259305893852096425478878588001446154476458310269704392486398646169362313605456233489086567865316333034897433650974160168545492823208575634152241341906068149887959566983066154182855136114289266802474404127414747112706158621650063987662749553991791509795764642256261917497984177610694405881831052199417235241109412927893781778469398975117797578753730248539151297798807326284978255001046995523851677310195682929105723956979990870355076" }, + +{ "28233332719950979786871881804755080223325040620170668729385709165879717973040387558150293205758215739710262749733170837042434162049732587908182282319848154049410849721309988807368466228286699721201975848741931128639324322061892706638973259354962358866000024260698793885547287093369940035337370984725857550291339492871017395328145015077506882578124550084937438336881072124376107623716831044079223921566902242543198986921476998895559488862309653154914291349588095330683589871173449191854284433182368052817373384461363574550061788800329400860372148193491004593903732351395815409821222597665222975816418433744748143385431", "-43245950360315656184924888243641533635", + "28233332719950979786871881804755080223325040620170668729385709165879717973040387558150293205758215739710262749733170837042434162049732587908182282319848154049410849721309988807368466228286699721201975848741931128639324322061892706638973259354962358866000024260698793885547287093369940035337370984725857550291339492871017395328145015077506882578124550084937438336881072124376107623716831044079223921566902242543198986921476998895559488862309653154914291349588095330683589871173449191854284433182368052817373384461363574550061788800329400860372148193491004593903732351395815409821179351714862660160233508856504501851796" }, + +{ "17311283930487575047109155431670372891723312431004343097275158353815289445461275098157423001160013464866170709729134076291306322952612660169010483426086431377525432637844274608988581691477819008626983761905899834444008235608280930166913911248710072733217113558125600345343437000427963292980921009445490627620344145866648036116660335905940809860199697939729919140888034303887423527841395304960072549430314367914315102150378504502158659627719016733307736583749830415574905929299482373462584995162798576853564481617711234957058703455021082855018642616999836886763535412642684228990890160568207941504887072856663966242787", "1954009743321912552050341299974626734964446274711484506734354360114801426013796892421541915293157994203607853436799102383078659985249097057923578528366737", + "17311283930487575047109155431670372891723312431004343097275158353815289445461275098157423001160013464866170709729134076291306322952612660169010483426086431377525432637844274608988581691477819008626983761905899834444008235608280930166913911248710072733217113558125600345343437000427963292980921009445490627620344145866648036116660335905940809860199697939729919140888034303887423527841395304960072549430314367914315102150378504502158659627719016733307736583749830417528915672621394925512926295137425311818010756329195741691413063569822508868815535038541752179921529616250537665789992543646867926753984130780242494609524" }, + +{ "1135960177108146621604027872788612991247811085764456406834564014092038611848908717507207251239454266163702244932570537009884467598603226302482406831131219148530146321028801515381981782506355042255201016953375149829517466449677312249611502599434850555618739830488706171667035140895674806873502543300909514568759918040129665855731078258004983486524477103833885001539135541445685573269814159175744401893663504523858005835387122082112362666991112899837534230326730196110477118156871579503345757821268248575583821695674912517830056856597644827244194658166928026249459511837772775196175188368236573504643083995409774002567", "-5513982495816270388232134254127393284677692173792609278582774509636977743203029647121158805174638642867428501907786521939155900331399058909602425073976766", + "1135960177108146621604027872788612991247811085764456406834564014092038611848908717507207251239454266163702244932570537009884467598603226302482406831131219148530146321028801515381981782506355042255201016953375149829517466449677312249611502599434850555618739830488706171667035140895674806873502543300909514568759918040129665855731078258004983486524477103833885001539135541445685573269814159175744401893663504523858005835387122082112362666991112899837534230326730190596494622340601191271211503693874963897891647903065633935055547219619901624214547537008122851610816644409270867409653249212336242105584174392984700025801" }, + +{ "-30369736932762868789456108597366835061749107555998091727589163626331595118680326568212941898571309672187038272915036839449380083450246957904300051802617002374912724325419651633014408152565340519439718081357147324136023867003917288524338643759680061563616479323818330115572573568245719292922176485298767387601922362893307843067637295955606642841006993776777666041277965868780958830666697755738164183356399977211227424725670822944234275611849032230010745799964550976844117943559190671369193871330514473741920389633762695829790016565565261170688485790141638094160105909405353382982945608773290740598479367828342651860878", "3451570547959142767282758882796967240086418127970526029661337442068316209707489088420708984628065070358319478649952710478991064476168799556496237099109563", + "-30369736932762868789456108597366835061749107555998091727589163626331595118680326568212941898571309672187038272915036839449380083450246957904300051802617002374912724325419651633014408152565340519439718081357147324136023867003917288524338643759680061563616479323818330115572573568245719292922176485298767387601922362893307843067637295955606642841006993776777666041277965868780958830666697755738164183356399977211227424725670822944234275611849032230010745799964550973392547395600047904086434988533547233655502261663236666168452574497249051463199397369432653466095035551085874733030235129782226264429679811332105552751315" }, + +{ "24749014370880469345815230363662696846133977441600857690896762642529872426102613384561609594131771018575590861342023688138502403609639138062665279129058939911797019091643704220495944170754490238422880589600838613701783818105188827633578438439212856537589855796204839275633245851474930725845096235668385012500773524750522781174430369067441632028068262240870795850561389232369373523415592833273932285308223863420210049445377497367753786125779044716949754454461623397410528064697616617917065021866397277409044449982605591256067763430930720398889239414812509701319783809830072841056369381573100589260104551934136733317845", "-9461623592584966196513107657889418526847060851423069480904645009418813160370721071067349946095573698635859409908288864150475056170059858850823883834932131", + "24749014370880469345815230363662696846133977441600857690896762642529872426102613384561609594131771018575590861342023688138502403609639138062665279129058939911797019091643704220495944170754490238422880589600838613701783818105188827633578438439212856537589855796204839275633245851474930725845096235668385012500773524750522781174430369067441632028068262240870795850561389232369373523415592833273932285308223863420210049445377497367753786125779044716949754454461623387948904472112650421403957363976978750561983598559536110351422754012117560028168168347462563605746085173970662932767505231098044419200245701110252898385714" }, + +{ "19070246171469235561279483225919489206942407814032615339351735800304747459507922411906751965555240682457214768298108831815622470433175555196912899313888991765436434867025639919521068437191248198117664398275835972573354886915721765715992151871453808224011999677700078879590132676060988550961950472536029228350169237717222998397029428440792110955380302156159849645211726041489206565536560827557279129751110297078563108009278363910936720061216511798518178957070787710331228500533067546198458251241005176280410230146430275074766072259256583499095689284871987010372039977403712023630453400259082684930755893684499232318008", "12330599952818018622104330691506128012101935028731995985677032980931398338453806827555760801312052792065671886621851470997557806941112316627790755867100463", + "19070246171469235561279483225919489206942407814032615339351735800304747459507922411906751965555240682457214768298108831815622470433175555196912899313888991765436434867025639919521068437191248198117664398275835972573354886915721765715992151871453808224011999677700078879590132676060988550961950472536029228350169237717222998397029428440792110955380302156159849645211726041489206565536560827557279129751110297078563108009278363910936720061216511798518178957070787722661828453351086168302788942747133188382345258878426260751799053190654921952902516840632788322424832043075598645481924397816889626043072521475255099418471" }, + +{ "-20895998178036569919774658790651496115060841511658297683195804524712012347695091074325978179977718571444320688167469052862702339462089668992243209990795362064005869602003990235714500149401994013174762139297327430396441552225926368085284222509085197484452650071390132794942944512235132641643003294762547138305644086106533258432786768644384855008506026923783604514268955071498269812887794817192371944269611642901807443894686178438687102834127061425955994253034824027771176714559050403098437684091684851207513969915720607528045624635094984539637789113651579846373399975502788877555747414523231999341294756679330384323996", "764238600803843266244444637050072967342049538611688895792923539838804953492110953673720766879606601435939162680753428779068917662740403667549850724878795", + "-20895998178036569919774658790651496115060841511658297683195804524712012347695091074325978179977718571444320688167469052862702339462089668992243209990795362064005869602003990235714500149401994013174762139297327430396441552225926368085284222509085197484452650071390132794942944512235132641643003294762547138305644086106533258432786768644384855008506026923783604514268955071498269812887794817192371944269611642901807443894686178438687102834127061425955994253034824027006938113755207136853993047041611883865464431304031711735122084796290031047526835439930812966766798539563626196802318635454314336600891089129479659445201" }, + +{ "6243894672855694190803081952962387322599009058758027960092936187687064819462191583137945440936085088260632250436567758576422207449236613172605950116622271404444221039084346501796818945639456207912207604248991842124079786471250102192718092353598850889806607728696519257402580732995770031331187089424192803722612735557735028710899438934171272639518928194764526910590046378401600819132587804143949995694950116915803127294011661411525934100144319021440919928013617766507409909846670172516021888661284467975865076091834094160862228180625536450124272957206172214541444266874056050295270719541605687740822711659847211976891", "11877496607682442993105675644902145742318375725225741293060927105303783712520284640625374957608051032540491531573337817824773543104969422017506696018037874641947740606655370938613842356322585858034851150595788166740174872996252792014218946552442572806242471174234462119454014379628228878122072189387777413014452140618318641689597452676091677588204537830401725113931418426919671512011822864583481449136550835952005765386885680701637038206002172218712504732572449659704181315669255320876647592649071711438131711904976335957846353867776093588236311654631696625859173554395714740218099921290128795607292259527492722462071", + "18121391280538137183908757597864533064917384783983769253153863292990848531982476223763320398544136120801123782009905576401195750554206035190112646134660146046391961645739717440410661301962042065947058754844780008864254659467502894206937038906041423696049078902930981376856595112623998909453259278811970216737064876176053670400496891610262950227723466025166252024521464805321272331144410668727431444831500952867808892680897342113162972306146491240153424660586067426211591225515925493392669481310356179413996787996810430118708582048401630038360584611837868840400617821269770790513370640831734483348114971187339934438962" }, + +{ "-24023960171862805266003610953999097357395283354964456554686635290239019705581779621120391229617494503580661676939681517550103414632840981987397485411400553792707518662609532504246677658012933762605038799352109564432278094548068984563394926376371580465135388578139331334464060067790936072127680597181415407099723844313625277987147283697141407959289588588489162704824409673099509423520008795428217612706997355591985894255450783091681112776112997887084157623388943538145736618168104404283342039105202585543852590302154958791010622670839015475427693311663800177428904406869645066988663292128104453773413982185343111560886", "-31939808827732134714870375774276102357277346245583282398423150631754622253109692213928642228787888509211781331649081002266227303203259124984426497846441848502574293640959494009564992092503141598640200823656998243767453860939156780549404892392521391484933772285520949470194562525777116137058001008184603332597820522016200623301007194309404025522056113671560767212894303567191067178003014955596425115379852712737129325098876542459702682095445350281859042779889411325882123213577906096942649941285655935053362468972482748617111598313960198743596285343178242282172686940700127068972627110105953098737923773182254460772630", + "-55963768999594939980873986728275199714672629600547738953109785921993641958691471835049033458405383012792443008588762519816330717836100106971823983257842402295281812303569026513811669750516075361245239623009107808199731955487225765112799818768892971950069160863660280804658622593568052209185681605366018739697544366329825901288154478006545433481345702260049929917718713240290576601523023751024642728086850068329115219354327325551383794871558348168943200403278354864027859831746010501225991980390858520597215059274637707408122220984799214219023978654842042459601591347569772135961290402234057552511337755367597572333516" }, + +{ "14513652183174940741664411990199277445706189147726874603036586212536012746892966848269748909379750612027025331446918381470766609543142456872580466135425754204680927122749772612276850998180593344389487924747722210296498854143380696064338777945015153982467675141485724865534995199700908286263993697988986805404864429385840512740226775506122190698806967785494289035976495492863456705096841250592980439363856397663738211335801835896091823148249303370609165910779981271035234045185574995335952208702661648744928539539455138167482396767268362221492607154709559716065850417221174683768503217544145599044845325824451589309835", "-12814535978730024053359592817368712576084646962861720729844389627130663192435154658607204342320327460695280260731620465435530495952836598646143907272825807563512741964987882356778796849529260646503692618525570185450780889283642116889481314560395290434301143877809550098309214046129802023655714098730144464028249594406616074059558969757405392170810220921023905546104487938441503430332099605473144930508420331873995741851604525954472341693863067199617721032815462094767522339305487934030130207039176659398466616780628644572276059410087128533031562978399689702766028716401176531098447698206272762966470643604141938670152", + "1699116204444916688304819172830564869621542184865153873192196585405349554457812189662544567059423151331745070715297916035236113590305858226436558862599946641168185157761890255498054148651332697885795306222152024845717964859738579174857463384619863548166531263676174767225781153571106262608279599258842341376614834979224438680667805748716798527996746864470383489872007554421953274764741645119835508855436065789742469484197309941619481454386236170991444877964519176267711705880087061305822001663484989346461922758826493595206337357181233688461044176309870013299821700819998152670055519337872836078374682220309650639683" }, + +{ "11356479761814008572465147431830778885327227506593483181241437802252618729479905490826767363633131720717461693888023278837835457496021519184903984385091047829540007466025527592005114414671285638168997562037691602144751434208304408870143450743278437854754504713023422097017723330207792526222436928747286558205279330508360438281011315147578105966454344087225699378388309094140949428028313539634103047841948634832398526343605363013644180832752120081735152285507591096001749463421326282317713079361827765412853023201330345752038722069405404812511739634687282327711258974520622248165974215116400638833123609666501349513623", "-2451734542868054449539778460457497703609327132304922810342762480808881050209276687756391911546806187586640918078231508181876445466503459873508196878629364924241891220686182517218825181707207808769770392864734466652524094735160185556148554260517746279303022469784592528209667497664672945900929888144529727881050106027775707933311860110618130543481573815538047460723253898548348335762406437618625388229555824532715231231491787570056329865617082709588903922431713098922691537317839185452018617461891748518176708607861270770493263960554805373552348256747200291438630960804647686832667981625018361034564086859426490014044", + "8904745218945954122925368971373281181717900374288560370898675321443737679270628803070375452086325533130820775809791770655959012029518059311395787506461682905298116245339345074786289232964077829399227169172957135492227339473144223313994896482760691575451482243238829568808055832543119580321507040602756830324229224480584730347699455036959975422972770271687651917665055195592601092265907102015477659612392810299683295112113575443587850967135037372146248363075877997079057926103487096865694461899936016894676314593469074981545458108850599438959391377940082036272628013715974561333306233491382277798559522807074859499579" }, + +{ "-1814184401790217165873937825605141478060935014868566665644215718762341535891730598045990231798382966074312671040257824056876679135909008140059087311700216658095793352051583071432744886316274989901835606602224927350560604355249919901932382803472476702792978322468747380191775778902733911968522382089332819162367884984027854067607561808704316828316820133400099093450636968732151876570835173932998599031643640476109466728761033062776578175554441947411139184426213290292577467587355369954997241091769769542810051228504545831588488726789173405585678190671534386784806998695797717346491308862362775748058331375692317599945", "15466182953987394334491149436346080039471412309427279110582769586053943302670765125931570041904640518032832554998553018838321871748542118021556398569294085708441934948186080236498081517178574839977996802813431873543309853609838200338534343580791382510179184571852290959723696010410340740895530535423959476873857191548113125728667781953125153120447892632916574768078583174099545013854248664119997703948998871566374080719541931440495888606776561795893839624084254684939434035018741535261951124673664746010067859317726891535170781460914710499572006592206360512398012457295755926986236618644330364227754380084585899275327", + "13651998552197177168617211610740938561410477294558712444938553867291601766779034527885579810106257551958519883958295194781445192612633109881497311257593869050346141596134497165065336630862299850076161196211206946192749249254588280436601960777318905807386206249383543579531920231507606828927008153334626657711489306564085271661060220144420836292131072499516475674627946205367393137283413490186999104917355231090264613990780898377719310431222119848482700439658041394646856567431386165306953883581894976467257808089222345703582292734125537093986328401534826125613205458599958209639745309781967588479696048708893581675382" }, + +{ "-27127130599753372624001250456405972983012981437652156246797208697430661165612459362971759027335854588888552031022264244768883843080959804690580574272908031271224646245152017114094021048441971097191444782106551075175878815012595015584723250801765859461211934306789890718268168352614164589637346918581658850565274510502652089457352942736418509881708568727739912127781455473660768550022762222130489047215089836402367851853412705556570667960548570630054608024914653686223423908494006675057953013815512203710764854485332282975729323105427143207127239069826750682633272289409910001698385240596625059970587393681128674617278", "5719655139276246085992066702308194672442413085748146924567717361937179810269300239821879673460959112727066470468217892213025828988023367028158410455624528688729907493639908638553730770145274142147983721694721139760883483821883267129411125364089207412089113869427479340283853501026803387874124668123626271531796990801822527792189514551888019206405597994403243358155410088320317141454525417323186389587327532772638942220300149829241141659063128602316305332848477566686425551944956989370838072872906293845914921103561360871571846865478762953536949621421094416539099628942010528483544062050170673327754206501716239719529", + "-21407475460477126538009183754097778310570568351904009322229491335493481355343159123149879353874895476161485560554046352555858014092936437662422163817283502582494738751512108475540290278296696955043461060411829935414995331190711748455312125437676652049122820437362411377984314851587361201763222250458032579033477519700829561665163428184530490675302970733336668769626045385340451408568236804807302657627762303629728909633112555727329526301485442027738302692066176119536998356549049685687114940942605909864849933381770922104157476239948380253590289448405656266094172660467899473214841178546454386642833187179412434897749" }, + +}; diff --git a/tests/exam_I_sqrtp.cc b/tests/exam_I_sqrtp.cc new file mode 100644 index 0000000..17abfd0 --- /dev/null +++ b/tests/exam_I_sqrtp.cc @@ -0,0 +1,24 @@ +#include "test_I.h" +#define floor(a,b) ((a) / (b)) + +int test_sqrtp (void) +{ + int error = 0; + // As our algorithm for sqrtp does pre-filtering mod (64*63*65*11), + // we check that no square is thrown away by this pre-filtering. + { + uintL a, b, c, d; + for (a = 0; a <= floor(64,2); a++) + for (b = 0; b <= floor(63,2); b++) + for (c = 0; c <= floor(65,2); c++) + for (d = 0; d <= floor(11,2); d++) { + // Produce a number x == a mod 64, x == b mod 63, + // x == c mod 65, x == d mod 11, and square it. + uintL x = 1306305*a + 1967680*b + 133056*c + 2358720*d; + x = x % 2882880; // not strictly necessary + cl_I w; + ASSERT4(sqrtp(expt_pos(x,2),&w) && w == x, a,b,c,d); + } + } + return error; +} diff --git a/tests/exam_LF.cc b/tests/exam_LF.cc new file mode 100644 index 0000000..29d136a --- /dev/null +++ b/tests/exam_LF.cc @@ -0,0 +1,7 @@ +#include "exam_LF_plus.cc" +#include "exam_LF_minus.cc" +#include "exam_LF_mul.cc" +#include "exam_LF_div.cc" +#include "exam_LF_floor.cc" + +DO_TESTS(lfloat,cl_LF,cl_LF) diff --git a/tests/exam_LF_div.cc b/tests/exam_LF_div.cc new file mode 100644 index 0000000..fb13927 --- /dev/null +++ b/tests/exam_LF_div.cc @@ -0,0 +1,457 @@ +#include "exam.h" +#include +#include + +static div_test lfloat_div_tests[] = { + +{ "0.8476517865511829377L0", "0.14598720922015648169L0", + "5.8063428370144327317L0" }, + +{ "-0.16515392772872533974L0", "0.2885771921352848653L0", + "-0.5723041606534907598L0" }, + +{ "-0.25791761734650428572L0", "-0.17472849542471660309L0", + "1.4761050664322265015L0" }, + +{ "-0.9418668871216534004L0", "-0.25801526180943099573L0", + "3.6504309106230792821L0" }, + +{ "-0.25726582509610465451L0", "0.7704327058756196045L0", + "-0.33392381078074095957L0" }, + +{ "-0.021409432992321506645L0", "-0.44293479613874918959L0", + "0.048335405524597819813L0" }, + +{ "-0.26771090178828336857L0", "-7.7011892538310270067L9", + "3.4762280599078659542L-11" }, + +{ "0.82867609196336006595L0", "-3.0042819216966844948L9", + "-2.7583166745395210866L-10" }, + +{ "0.40732354689187331287L0", "-7.559832309976744222L9", + "-5.387997116739304149L-11" }, + +{ "-0.53349543673778000914L0", "-5.104278761341346705L8", + "1.045192595628502556L-9" }, + +{ "0.17669669311850475256L0", "-9.181879875841464834L9", + "-1.9244064996255633173L-11" }, + +{ "-0.38525727576606363245L0", "-4.8936643582468263693L9", + "7.872572525674472248L-11" }, + +{ "0.028580272067667963345L0", "-7.9841173999044091L-11", + "-3.5796407587907142282L8" }, + +{ "0.72167998280372380157L0", "-3.6437273419914776347L-12", + "-1.980609181391958688L11" }, + +{ "-0.5863461999919387516L0", "7.881986348526466578L-11", + "-7.4390664239294943926L9" }, + +{ "0.54541403791059564303L0", "-2.6107257402815120583L-11", + "-2.089128051619026705L10" }, + +{ "0.7985324354238058011L0", "9.752737902348257611L-12", + "8.187777047012979847L10" }, + +{ "0.14104671220162837288L0", "-1.679932803469743255L-11", + "-8.3959734526470136372L9" }, + +{ "0.84226961154302812054L0", "-3.7790325979515268584L19", + "-2.2287968936801211454L-20" }, + +{ "-0.17023320737807742781L0", "-7.0544793122604881768L19", + "2.4131222141684768152L-21" }, + +{ "0.51147038234753495475L0", "7.2890488826322506176L19", + "7.01697012303244035L-21" }, + +{ "0.15424860911694467965L0", "-9.2121691156562017736L19", + "-1.6744005367291526718L-21" }, + +{ "0.18043991101271504866L0", "-1.5135729370916590423L19", + "-1.1921454631676461953L-20" }, + +{ "-0.8669749687756526617L0", "8.7133495928438747096L19", + "-9.949961946754488136L-21" }, + +{ "-0.6448505560111598971L0", "3.636469578348857873L-21", + "-1.7732873659951112376L20" }, + +{ "-0.81857582399766609004L0", "5.2916132942068490006L-21", + "-1.546930545536701092L20" }, + +{ "0.77524450276763022L0", "-7.652595302708246449L-21", + "-1.0130478250865714831L20" }, + +{ "0.627858729575384142L0", "9.627326573065363056L-21", + "6.5216311590796329432L19" }, + +{ "-0.42943946308533227006L0", "-2.2414950519882640498L-21", + "1.9158617490786266339L20" }, + +{ "-0.34220208112358558038L0", "-7.4545803279812700505L-21", + "4.5904942473972275588L19" }, + +{ "5.560943842255079481L9", "-0.55841023848214400133L0", + "-9.958527725728472542L9" }, + +{ "-8.661678305761957921L9", "-0.87958882986448744696L0", + "9.847417351919312785L9" }, + +{ "3.6954900583503502368L9", "-0.36989453222048823558L0", + "-9.9906587863470431315L9" }, + +{ "6.740385471899914443L8", "-0.2745720588185960522L0", + "-2.454869406924301959L9" }, + +{ "-5.1381279403866914758L9", "-0.32555782051482221485L0", + "1.578253574821668073L10" }, + +{ "-3.2065087686035281697L9", "0.50505516522796299416L0", + "-6.3488287802308291444L9" }, + +{ "-7.7979994067331648055L9", "-6.4459990751639263853L9", + "1.2097425574847536075L0" }, + +{ "-4.7272619195621447717L9", "-3.825695015629283172L8", + "12.356609453314103588L0" }, + +{ "-3.5376744034596315073L9", "2.7483444719369282795L9", + "-1.2872019645217230068L0" }, + +{ "-2.2400216393287578975L9", "-3.7058330823204350567L9", + "0.6044583200509807153L0" }, + +{ "3.0621742151056386386L9", "-8.846101104908494769L9", + "-0.34616088814613589822L0" }, + +{ "7.5149875074517868906L9", "4.423024956398348232L9", + "1.6990606161017937287L0" }, + +{ "7.6970261502618782055L9", "-9.7716080626747355186L-11", + "-7.876928854384493259L19" }, + +{ "-8.725835744855911806L8", "8.409822932470646079L-11", + "-1.0375766309139670758L19" }, + +{ "5.820797723708174118L9", "-2.882166534035175912L-11", + "-2.0195910454760464445L20" }, + +{ "1.207852991950790034L9", "5.840354579417081103L-11", + "2.068115857567237665L19" }, + +{ "3.1046967393071541823L9", "-5.5642977043818474125L-11", + "-5.5796740294147564416L19" }, + +{ "4.392532668212736406L9", "-7.535498815249885942L-11", + "-5.8291199771983175508L19" }, + +{ "1.3280881496906639524L9", "-1.766515912740190632L19", + "-7.518121632035316941L-11" }, + +{ "1.4277961930808139626L9", "-8.986506745304867108L19", + "-1.5888222571321021114L-11" }, + +{ "-7.9134656119390343763L9", "-3.4095849226963530828L19", + "2.3209469162249057589L-10" }, + +{ "-8.7882725472722691335L9", "-5.186325400713441962L19", + "1.6945085138821670647L-10" }, + +{ "3.8930727351090315925L9", "-7.3980221641298868864L19", + "-5.2623155875161027887L-11" }, + +{ "9.998404421166073569L9", "-8.1317115085820412065L18", + "-1.2295571984586471158L-9" }, + +{ "4.623792381028250544L9", "6.996281129080973142L-21", + "6.6089287947690416075L29" }, + +{ "8.472924939037688662L9", "-4.3460987737519244214L-22", + "-1.9495472560839050376L31" }, + +{ "1.9551595642940545935L9", "-7.5324972045717692564L-21", + "-2.5956326450508222435L29" }, + +{ "-8.5478772651240992225L9", "-2.4212066230883777513L-21", + "3.5304204042779411337L30" }, + +{ "6.881700625121950854L9", "-8.203099619911879591L-21", + "-8.389146717684109215L29" }, + +{ "6.097099876947129031L9", "-4.76850418677518328L-21", + "-1.2786189627046213921L30" }, + +{ "-5.0358061432469478737L-11", "-0.6780392915138573621L0", + "7.427012278305451381L-11" }, + +{ "-1.49762284327640383L-11", "0.15227257119521089694L0", + "-9.835145171066142436L-11" }, + +{ "-7.1678035946969115934L-11", "0.75360681415553320054L0", + "-9.511330656861051013L-11" }, + +{ "4.583894304978394541L-12", "0.68934670181533335835L0", + "6.6496210004445016106L-12" }, + +{ "-3.8885547056166489716L-12", "-0.010643810658165133798L0", + "3.6533482513930678043L-10" }, + +{ "9.49880444227161124L-11", "-0.122629749019578004226L0", + "-7.745921783428843474L-10" }, + +{ "2.1990660545226500317L-11", "-1.4161745224867819854L9", + "-1.552821364602098501L-20" }, + +{ "9.951737846856727225L-11", "-6.0164204240154494783L9", + "-1.6540961477912788069L-20" }, + +{ "-5.873282338412930208L-11", "2.3788798751415933107L9", + "-2.4689276662460085614L-20" }, + +{ "2.2209512664584027642L-11", "5.1944018613813348683L9", + "4.2756631576205975403L-21" }, + +{ "-6.722318330051584872L-11", "6.7936247801916195024L9", + "-9.895039169151724367L-21" }, + +{ "-7.528877773200399613L-12", "-9.535757813603057891L9", + "7.89541630604357328L-22" }, + +{ "-2.0857643618410047184L-11", "2.701544718271986855L-11", + "-0.77206360780699598463L0" }, + +{ "2.5510439626733908612L-11", "1.6734405694946451074L-11", + "1.5244305708709866576L0" }, + +{ "3.048460642905138835L-11", "5.1568899955161432057L-11", + "0.5911432366321058725L0" }, + +{ "9.876491787625061464L-12", "8.667781903943973216L-11", + "0.113944858062604306884L0" }, + +{ "1.1166642175553123016L-11", "-7.759981600144040302L-11", + "-0.14390036923986841014L0" }, + +{ "-2.7282824760136843772L-11", "-9.160281916489131182L-11", + "0.2978382653379466574L0" }, + +{ "-3.1587174777348029438L-11", "-4.9090150171793744104L19", + "6.4345239659701453497L-31" }, + +{ "-4.512784364891002838L-11", "5.9600731551720265308L19", + "-7.571692909465218857L-31" }, + +{ "-1.431681316436341718L-11", "-4.22349605246125618L19", + "3.3898014788057508284L-31" }, + +{ "-6.719040537613210677L-11", "-4.545488183802435408L19", + "1.47817797911258332435L-30" }, + +{ "2.5092238442261623676L-11", "3.3004591427193857704L19", + "7.602650830449936487L-31" }, + +{ "-6.198495042920933878L-12", "1.8747110273916984954L19", + "-3.306373596972410786L-31" }, + +{ "8.3326031863190006605L-11", "6.3679312781687389584L-21", + "1.3085259281747860217L10" }, + +{ "2.228308172351851791L-11", "-4.6204647093882084617L-22", + "-4.822692764700068564L10" }, + +{ "9.7676469315043868665L-11", "-6.6370355345926113967L-21", + "-1.4716882078745621587L10" }, + +{ "-8.9713798012161717115L-11", "-3.669192301028840519L-21", + "2.445055768459069116L10" }, + +{ "7.214258511983827207L-11", "-1.5195990661514104949L-21", + "-4.7474749574931692373L10" }, + +{ "1.4822028144092954099L-12", "2.269595713994387529L-21", + "6.530690929974856047L8" }, + +{ "-4.6354687290142894644L19", "0.032331325634476806982L0", + "-1.4337391486574910728L21" }, + +{ "-2.389352438897577318L19", "0.8660312577952003013L0", + "-2.7589678979723536864L19" }, + +{ "-2.4109458405628950432L19", "0.26688102636777617506L0", + "-9.0337851040803631776L19" }, + +{ "8.961066349333904704L19", "-0.66178143682771294813L0", + "-1.35408245844568974384L20" }, + +{ "6.6419769467305502364L19", "-0.8456142496793601811L0", + "-7.854618047471472417L19" }, + +{ "3.7389082257286159308L19", "0.56261989685796304976L0", + "6.645531462021022254L19" }, + +{ "7.814283695666500025L19", "-4.6620013293904720047L9", + "-1.6761650509199167363L10" }, + +{ "6.6434731737611309404L19", "-2.858805223329136325L9", + "-2.323863521567472329L10" }, + +{ "-1.3409334390407788129L19", "6.1497605350647401055L9", + "-2.1804644772671013651L9" }, + +{ "7.0858597943822241668L19", "-2.58410378455919273L9", + "-2.7420956684179617314L10" }, + +{ "-6.6455998228898640428L19", "-7.7545004942277582046L9", + "8.569990843171226794L9" }, + +{ "2.9602494058183339616L19", "-5.7169856186590364077L9", + "-5.1779899465842692843L9" }, + +{ "-6.698311323164055808L19", "-6.553232827426109497L-11", + "1.02213846197113193186L30" }, + +{ "-7.554561034956199475L19", "6.4764910162760040714L-11", + "-1.1664589692120175174L30" }, + +{ "6.7796490729162210612L19", "9.9915237995070190003L-11", + "6.785400514434773617L29" }, + +{ "-6.9067747658009050975L18", "-2.5761632749585983355L-11", + "2.681031452058062687L29" }, + +{ "1.629413698021581386L19", "-8.612780517302459862L-11", + "-1.8918555915226283107L29" }, + +{ "8.8732593909692189064L19", "-4.0536919536865455935L-12", + "-2.1889328277398133904L31" }, + +{ "4.8426213700963381164L19", "7.883038261101094331L19", + "0.61430900240485778846L0" }, + +{ "-5.2968355222513127376L19", "1.5071497411718048594L19", + "-3.5144719715328600349L0" }, + +{ "-6.2610887651422622925L18", "1.0358424497888766788L19", + "-0.60444411854509194816L0" }, + +{ "-2.4670994205369878408L19", "6.9747461294856021948L19", + "-0.3537188844920639511L0" }, + +{ "6.9460731069354980812L19", "3.1486762233902586798L19", + "2.2060296499639734035L0" }, + +{ "8.8228286449463631936L19", "6.7354354317536527728L19", + "1.3099121406987093833L0" }, + +{ "3.2098388728662261428L19", "-2.6305167886064038438L-21", + "-1.2202312818412901165L40" }, + +{ "-7.144492994496515916L19", "-2.0335028635662185032L-21", + "3.5133921483478965099L40" }, + +{ "-6.3695870249569899508L19", "1.9319318539671607067L-21", + "-3.2970039869042198792L40" }, + +{ "-5.4056057590545112688L19", "6.6371220252553042967L-21", + "-8.144502599899959829L39" }, + +{ "-4.5534797093596626272L19", "9.223324048915255164L-21", + "-4.9369182793650108047L39" }, + +{ "3.9206183123968272208L19", "-1.6559061178638737343L-21", + "-2.3676573629998072004L40" }, + +{ "-8.768637785982664131L-21", "-0.18184176456694917492L0", + "4.8221253279547290195L-20" }, + +{ "2.6823352573966718016L-21", "-0.55524799130252431824L0", + "-4.830877912956219511L-21" }, + +{ "-4.0350541003620172524L-21", "0.27000304046926068644L0", + "-1.4944476526446376082L-20" }, + +{ "6.332356861830292899L-21", "0.65544003241974460534L0", + "9.6612299350294242524L-21" }, + +{ "3.5603120340723305693L-21", "-0.124100556644984066966L0", + "-2.86889288035778711L-20" }, + +{ "5.5961094005028721084L-21", "0.47201702367299511838L0", + "1.18557363820414998006L-20" }, + +{ "1.7187188076305931646L-21", "8.3685668129856246863L9", + "2.0537791548292745125L-31" }, + +{ "-2.7220241842791803757L-21", "2.2892422122227956846L9", + "-1.1890503196846804849L-30" }, + +{ "-6.028203796038167925L-21", "-5.415224539645905615L9", + "1.1131955382282900156L-30" }, + +{ "6.6310444174308960725L-21", "9.461342958972558645L9", + "7.0085657460946591684L-31" }, + +{ "-8.8033709586752979635L-21", "2.8098765759657792274L9", + "-3.1330098389284241575L-30" }, + +{ "-3.4027974212452472475L-21", "6.219628754500815959L8", + "-5.4710619484849846614L-30" }, + +{ "8.388977931970215088L-21", "2.8213325814913435694L-11", + "2.9734097947204223302L-10" }, + +{ "-9.3496400462478483586L-21", "-9.381494249123695733L-11", + "9.966045704415559596L-11" }, + +{ "-6.936639418470504025L-21", "5.6618206553549859367L-11", + "-1.2251605694909792675L-10" }, + +{ "-2.3667892015182913211L-21", "-7.1545639578577691874L-11", + "3.3080830857887236957L-11" }, + +{ "-9.576766108065157562L-21", "-6.4350290609494113365L-11", + "1.4882242204905008798L-10" }, + +{ "-2.5955914883538434001L-22", "5.8091383646322322124L-11", + "-4.4681178609147595716L-12" }, + +{ "-2.9619491950657497217L-21", "-5.3730670726011346488L19", + "5.512585558757694777L-41" }, + +{ "2.5726455340193007026L-22", "3.0037766865540527038L19", + "8.564703047118500122L-42" }, + +{ "-2.8277317971003367574L-21", "-4.4068191966128705184L19", + "6.4167184332721487087L-41" }, + +{ "7.503784949731224261L-21", "5.9540210967055505192L19", + "1.2602886062804146604L-40" }, + +{ "1.4876876016319254574L-22", "8.6818746213386148185L18", + "1.7135557313571827969L-41" }, + +{ "2.699544264870480357L-21", "3.6796341400587007856L19", + "7.3364474893892979093L-41" }, + +{ "-7.285812539718203862L-21", "5.700589904684711396L-21", + "-1.2780804551000530294L0" }, + +{ "3.6474102791520560028L-21", "-6.343773677116707765L-21", + "-0.574959080319812269L0" }, + +{ "-4.2510720089860863712L-21", "-8.281980897162330288L-21", + "0.51329169455614642465L0" }, + +{ "5.770684998505203844L-21", "6.5700291863604419324L-21", + "0.8783347584642853315L0" }, + +{ "-4.8018196973750014744L-21", "-7.3250029580209059804L-21", + "0.6555382605159211192L0" }, + +{ "-3.9261100835261094614L-21", "-8.986577968334144672L-21", + "0.436885997913830856L0" }, + +}; diff --git a/tests/exam_LF_floor.cc b/tests/exam_LF_floor.cc new file mode 100644 index 0000000..795b856 --- /dev/null +++ b/tests/exam_LF_floor.cc @@ -0,0 +1,459 @@ +#include "exam.h" +#include +#include +#include +#include + +static floor_test lfloat_floor_tests[] = { + +{ "-0.9677507664075728311L0", "0.09829392666835353511L0", + "-10", "0.015188500275962520004L0" }, + +{ "-0.084596576622269801105L0", "-0.78271578747309396924L0", + "0", "-0.084596576622269801105L0" }, + +{ "0.97785517019559092334L0", "-0.24687352093087197807L0", + "-4", "-0.009638913527896988987L0" }, + +{ "0.36348468689259258175L0", "0.5156866254701831051L0", + "0", "0.36348468689259258175L0" }, + +{ "-0.51463186192345608164L0", "0.8683136279312965567L0", + "-1", "0.35368176600784047506L0" }, + +{ "0.36128372948365635348L0", "-0.5061584717303788097L0", + "-1", "-0.1448747422467224562L0" }, + +{ "-0.83188875677783952054L0", "-6.988497329115560525L9", + "0", "-0.83188875677783952054L0" }, + +{ "-0.09110744229488624391L0", "-9.792597852253288497L9", + "0", "-0.09110744229488624391L0" }, + +{ "0.23616060202132526459L0", "-1.5882829404848723914L9", + "-1", "-1.5882829402487117894L9" }, + +{ "-0.09652925723903261584L0", "6.2261024177069773893L9", + "-1", "6.226102417610448132L9" }, + +{ "0.5413601234707634158L0", "9.144943549323542538L9", + "0", "0.5413601234707634158L0" }, + +{ "-0.57037258938648310115L0", "4.436821091919698621L9", + "-1", "4.4368210913493260317L9" }, + +{ "-0.9973297751770725278L0", "3.4051851548139874998L-11", + "-29288562291", "1.4506986275662661537L-11" }, + +{ "0.6604979952397203417L0", "-4.3497555374342239963L-11", + "-15184715315", "-1.8114827519649365006L-11" }, + +{ "0.38589975187928444138L0", "1.0289103184336123803L-12", + "375056742036", "3.5046726009323829848L-13" }, + +{ "0.9402638162334174371L0", "4.2262799834524861567L-11", + "22248024738", "1.7766010468098603481L-11" }, + +{ "-0.8642082843541437474L0", "8.911777256338402297L-11", + "-9697373033", "6.304376014060421794L-11" }, + +{ "0.7435773981922973139L0", "5.910629837324535378L-11", + "12580341159", "1.1224045374678474888L-11" }, + +{ "0.7898063255151059068L0", "1.2757118849664610875L18", + "0", "0.7898063255151059068L0" }, + +{ "0.19544684487626281231L0", "-3.6071314846523434156L19", + "-1", "-3.6071314846523434156L19" }, + +{ "-0.032130218136830583316L0", "-3.367647816525978896L18", + "0", "-0.032130218136830583316L0" }, + +{ "-0.25693079625787854222L0", "2.3815464531684079734L19", + "-1", "2.3815464531684079734L19" }, + +{ "-0.3975875412090936933L0", "3.9957351306215043416L19", + "-1", "3.9957351306215043416L19" }, + +{ "0.16223305219726616216L0", "-5.3922124894358790612L19", + "-1", "-5.3922124894358790612L19" }, + +{ "0.14869268750642991106L0", "-4.676414410846522305L-21", + "-31796302560686368198", "0.0L0" }, + +{ "0.4848921957991629974L0", "7.275052251851656838L-21", + "66651369504012501536", "0.0L0" }, + +{ "0.44996459510190342355L0", "-3.96515259272563559L-21", + "-113479767696052002376", "0.0L0" }, + +{ "0.7246909129638354568L0", "-1.2540349367528059089L-21", + "-577887339279675740320", "0.0L0" }, + +{ "0.83383904440522878455L0", "3.5186204165781412753L-21", + "236978970643311773536", "0.0L0" }, + +{ "0.26779759740636464572L0", "-6.954613119627800336L-21", + "-38506469418200611672", "0.0L0" }, + +{ "-7.4845680268023566543L9", "-0.2629469688312594538L0", + "28464173061", "-0.1240146549242767677L0" }, + +{ "6.1612132433805581187L9", "-0.09975641287987705455L0", + "-61762578120", "-0.083822638930812785824L0" }, + +{ "-3.6629628120558108524L9", "0.35361739315194823028L0", + "-10358548203", "0.32784699422401302726L0" }, + +{ "-6.999024858613990497L9", "-0.6086338795192380592L0", + "11499564999", "-0.48897756390533489348L0" }, + +{ "4.2927999071819381092L9", "-0.8483437666321241058L0", + "-5060212707", "-0.6341788853647631104L0" }, + +{ "-4.377925687006929662L9", "0.3220507356662819166L0", + "-13593900595", "0.18712780555802854961L0" }, + +{ "-9.5387759396672939425L9", "7.7154581598602048657L9", + "-2", "5.892140380053115789L9" }, + +{ "-5.64339842966998351L9", "4.025489717604319313L9", + "-2", "2.4075810055386551162L9" }, + +{ "-4.811594948157823536L9", "-7.834071766040306942L9", + "0", "-4.811594948157823536L9" }, + +{ "4.4476035118893197435L9", "3.0450117757143498866L9", + "1", "1.4025917361749698569L9" }, + +{ "-7.3465328576805684287L9", "-4.603589573313564281L9", + "1", "-2.7429432843670041477L9" }, + +{ "4.956277095163508632L9", "-6.664438280281275845L9", + "-1", "-1.708161185117767213L9" }, + +{ "4.367757792316331005L9", "-7.8163461329531150714L-11", + "-55879789840705743024", "0.0L0" }, + +{ "-4.7778036898247465523L8", "3.4933422750724630952L-11", + "-13676883951274541565", "0.0L0" }, + +{ "-6.667353710605079077L9", "5.3863219342714070564L-11", + "-123783052553596643928", "0.0L0" }, + +{ "-6.6004002390836614547L9", "-9.313678706634845693L-11", + "70867811173061956036", "0.0L0" }, + +{ "-9.439278803200832958L9", "-6.7075776392225367144L-11", + "140725598880953434976", "0.0L0" }, + +{ "-9.207319097846486017L9", "-5.7812820689283059893L-11", + "159260852317369718528", "0.0L0" }, + +{ "-7.564134292866958547L9", "6.4508269927189105468L19", + "-1", "6.4508269919624971176L19" }, + +{ "-5.7520914080101070246L9", "-4.4901662701989554116L17", + "0", "-5.7520914080101070246L9" }, + +{ "-9.801170739094381102L9", "9.482698257311007893L19", + "-1", "9.482698256330890819L19" }, + +{ "7.471594576665974082L8", "3.1667053210759199935L18", + "0", "7.471594576665974081L8" }, + +{ "-6.4762144691604037974L9", "-8.2417624342716462896L19", + "0", "-6.4762144691604037974L9" }, + +{ "-5.5263312844382694187L9", "9.5950716135522835064L19", + "-1", "9.5950716129996503776L19" }, + +{ "3.1312033848911460338L9", "-8.61316266389637687L-21", + "-363537008074414891396807786496", "0.0L0" }, + +{ "2.6279029713558476835L9", "-4.516664720059022692L-21", + "-581823786849847663134534270976", "0.0L0" }, + +{ "4.502075635961923785L9", "-9.685834626464620576L-21", + "-464810293545679143271024033792", "0.0L0" }, + +{ "1.4031562604294053729L9", "3.412866773725220897L-21", + "411137132932332056394984325120", "0.0L0" }, + +{ "-4.3024038761755407723L9", "2.485284435684751149L-21", + "-1731151498959165530746191347712", "0.0L0" }, + +{ "6.136473603422627364L9", "5.6959828635137213127L-21", + "1077333578850898685241017237504", "0.0L0" }, + +{ "-8.202208473677937235L-11", "0.12393605769441814725L0", + "-1", "0.123936057612396062516L0" }, + +{ "-8.6757073154686102475L-11", "-0.37237633673270687662L0", + "0", "-8.675707315468610247L-11" }, + +{ "5.6028622390057924218L-11", "0.6499341232771672055L0", + "0", "5.6028622390057924218L-11" }, + +{ "4.5783899320025937576L-11", "-0.7229560019811405793L0", + "-1", "-0.7229560019353566799L0" }, + +{ "7.224213822400873615L-11", "-0.87051303270552073176L0", + "-1", "-0.87051303263327859354L0" }, + +{ "-5.5008008233955830292L-11", "-0.45974678868400245752L0", + "0", "-5.5008008233955830295L-11" }, + +{ "-5.949553569817051437L-11", "-4.9088361621296460857L9", + "0", "-5.949553569817051437L-11" }, + +{ "9.068981360820356321L-11", "3.9567179334666110438L9", + "0", "9.068981360820356321L-11" }, + +{ "3.4621680776088405294L-13", "4.3691679646970805987L9", + "0", "3.4621680776088405294L-13" }, + +{ "4.005939678622022073L-11", "-9.2132271371400602936L8", + "-1", "-9.213227137140060293L8" }, + +{ "6.8015601712459487755L-11", "-4.769849366969915586L9", + "-1", "-4.769849366969915586L9" }, + +{ "8.736177705951390388L-11", "8.3701230195943479203L9", + "0", "8.736177705951390388L-11" }, + +{ "-8.8368349664293751446L-11", "1.7247862508910726963L-11", + "-6", "1.5118825389170610328L-11" }, + +{ "-2.0922301210797840822L-11", "2.9157326021078492393L-11", + "-1", "8.235024810280651572L-12" }, + +{ "-9.929248815922456709L-11", "-6.9934608623319373425L-11", + "1", "-2.9357879535905193665L-11" }, + +{ "8.809298490106908006L-11", "2.521478295865126635L-11", + "3", "1.244863602511528101L-11" }, + +{ "7.3620267190952160604L-11", "-5.0806267993123045533L-11", + "-2", "-2.7992268795293930463L-11" }, + +{ "-9.070716461299934103L-11", "1.372581158818204212L-11", + "-7", "5.3735165042749538097L-12" }, + +{ "-7.459630170957188741L-11", "-3.429772398019229389L19", + "0", "-7.459630170957188741L-11" }, + +{ "1.9725650506989118904L-11", "-1.7770668980460508816L19", + "-1", "-1.7770668980460508816L19" }, + +{ "6.3974118251214889016L-12", "-5.69117448017374684L19", + "-1", "-5.69117448017374684L19" }, + +{ "9.080192761938897539L-11", "5.1550284925054312868L19", + "0", "9.080192761938897539L-11" }, + +{ "7.694299339180548789L-11", "3.1601030797220572842L19", + "0", "7.694299339180548789L-11" }, + +{ "5.5788554873601060938L-11", "5.5699367746931070664L19", + "0", "5.5788554873601060938L-11" }, + +{ "-4.087371164243010522L-11", "1.7025318283693090775L-21", + "-24007605005", "1.5007203773756006028L-21" }, + +{ "-7.3575974688385316083L-11", "-1.6670029902289832508L-21", + "44136678290", "-1.8066891019200848581L-22" }, + +{ "1.0850282868697332469L-11", "5.7344803128377181472L-21", + "1892112672", "1.4425616831217755076L-21" }, + +{ "-9.848519351300913193L-11", "-7.121687974823219785L-21", + "13828911609", "-2.300608125189343731L-21" }, + +{ "3.0260591554314098406L-12", "1.7303586387117179437L-22", + "17488046048", "9.689796116124082976L-23" }, + +{ "5.867643793784483945L-11", "2.9831220978672803306L-21", + "19669472456", "9.594326475082730988L-22" }, + +{ "9.453252855247919707L19", "0.3964594556008910194L0", + "238441856328540902016", "0.0L0" }, + +{ "1.9865852464762410773L17", "0.8745495786051183551L0", + "227155245977568008", "0.08198902299422984579L0" }, + +{ "5.8003655986843771616L19", "-0.57075967601329721915L0", + "-101625357264188433960", "0.0L0" }, + +{ "6.5463855676706502812L19", "0.5124698839969514896L0", + "127741859026189966704", "0.0L0" }, + +{ "8.053368905864221505L19", "0.40679331708739617821L0", + "197972006116659527920", "0.0L0" }, + +{ "8.5722362029533885376L19", "0.1793174966141533504L0", + "478047952085719142240", "0.0L0" }, + +{ "-6.6056603867132043536L19", "1.8364346532401849241L9", + "-35970026895", "8.274070785684816422L8" }, + +{ "2.473965171745108034L19", "5.5749126908032718576L9", + "4437675186", "5.356910410798194379L9" }, + +{ "-4.405924011882179756L19", "-6.4568556406242929674L9", + "6823637165", "-4.1798826632701602209L8" }, + +{ "2.1093676314099077168L19", "5.727620773112868108L8", + "36827990451", "1.8408274540307780489L8" }, + +{ "-1.0962340119185741432L19", "-8.173187675545835245L9", + "1341256380", "-4.422519927692124746L9" }, + +{ "-9.664836922872330681L19", "-4.5461452948374001435L9", + "21259410546", "-4.0088028420210172099L9" }, + +{ "9.9654629946168490416L19", "-6.27691916031617149L-11", + "-1587636026543136775574879469568", "0.0L0" }, + +{ "-1.2700534905234296955L19", "-7.6392648594402208417L-11", + "166253365198349054807791108096", "0.0L0" }, + +{ "-7.837735447773461618L18", "-8.6041613252133785413L-11", + "91092381366746282195935035392", "0.0L0" }, + +{ "4.849306367034469812L19", "-8.744903371098252931L-11", + "-554529439749024491444258209792", "0.0L0" }, + +{ "-6.3895751736590951245L18", "-8.9218106166526971406L-11", + "71617471477514379195326660608", "0.0L0" }, + +{ "-1.1249006547358954392L19", "-3.749899421128778124L-11", + "299981553744522252727485464576", "0.0L0" }, + +{ "-4.8298889769606521412L19", "3.2897859420995047714L19", + "-2", "1.7496829072383574016L19" }, + +{ "-7.618272569239742257L19", "-2.4246730847406800364L19", + "3", "-3.4425331501770214745L18" }, + +{ "-9.9344217376670949096L19", "-2.187787768895506888L19", + "4", "-1.1832706620850673572L19" }, + +{ "3.9222824564168688912L19", "-9.476307993509074433L19", + "-1", "-5.5540255370922055412L19" }, + +{ "-2.012988112115775752L19", "-1.01146191266402097525L18", + "19", "-9.1210478054135899006L17" }, + +{ "8.6136075623649245696L19", "-9.374471951386232653L19", + "-1", "-7.6086438902130808345L18" }, + +{ "-4.0954879593227223964L19", "3.4785793369902262412L-21", + "-11773449913223093127289481096658923028480", "0.0L0" }, + +{ "-5.7633820540313762628L19", "-6.9799216943629666126L-21", + "8257086979479904139315172946770002968576", "0.0L0" }, + +{ "-4.5945941433359568196L19", "-9.26874309885338918L-21", + "4957084357969034092339972319162935541760", "0.0L0" }, + +{ "9.069653875532044557L19", "1.1607862998892810815L-21", + "78133708817868823323292026086376001765376", "0.0L0" }, + +{ "1.9663881236128118596L19", "-7.53224056983834607L-21", + "-2610628411799403924128603371383036051456", "0.0L0" }, + +{ "3.8155182638858600344L19", "-9.78280482738867461L-21", + "-3900229362854759958152852242692868931584", "0.0L0" }, + +{ "2.0785751397779279812L-21", "0.84874462118484074924L0", + "0", "2.0785751397779279812L-21" }, + +{ "9.468679817093889512L-22", "-0.14230041428757812886L0", + "-1", "-0.14230041428757812886L0" }, + +{ "-3.5329587582370771722L-21", "-0.75145077780984780047L0", + "0", "-3.5329587582370771722L-21" }, + +{ "1.0147425004279850959L-21", "0.55049889413410685307L0", + "0", "1.0147425004279850959L-21" }, + +{ "-9.214176537319943048L-21", "-0.45008902557926736644L0", + "0", "-9.214176537319943048L-21" }, + +{ "-1.146684367801419132L-21", "0.3317375182580383851L0", + "-1", "0.3317375182580383851L0" }, + +{ "9.8958965362796452575L-23", "-8742129.925142999928L0", + "-1", "-8742129.925142999928L0" }, + +{ "-8.629925553125559817L-22", "1.4904768761159059732L9", + "-1", "1.4904768761159059732L9" }, + +{ "-1.7636696713810751494L-21", "1.2803675755746476424L9", + "-1", "1.2803675755746476424L9" }, + +{ "7.8572218293550540256L-21", "7.311951574932556098L9", + "0", "7.8572218293550540256L-21" }, + +{ "5.8831628670454666175L-21", "-2.430599936529262355L9", + "-1", "-2.430599936529262355L9" }, + +{ "5.891885696934149925L-21", "6.0077688200842341403L9", + "0", "5.891885696934149925L-21" }, + +{ "-5.5378511525885539255L-21", "-4.317564477957860586L-11", + "0", "-5.5378511525885539255L-21" }, + +{ "-1.9525004120740256159L-21", "9.454884961900014292L-11", + "-1", "9.454884961704764251L-11" }, + +{ "5.461359828153347278L-21", "-9.7061135180917529105L-11", + "-1", "-9.706113517545616928L-11" }, + +{ "9.644530490453124287L-21", "8.28693431641614359L-11", + "0", "9.644530490453124287L-21" }, + +{ "8.997549905605484822L-21", "5.2672865249640494307L-11", + "0", "8.997549905605484822L-21" }, + +{ "-1.55338435917637846L-21", "5.9708770769690056966L-11", + "-1", "5.9708770768136672606L-11" }, + +{ "3.9285675924255819076L-21", "5.674913585946206864L19", + "0", "3.9285675924255819076L-21" }, + +{ "-3.6185336116295331734L-21", "-9.043926006483480333L19", + "0", "-3.6185336116295331734L-21" }, + +{ "-7.32672036508508268L-21", "1.205614654464109627L19", + "-1", "1.205614654464109627L19" }, + +{ "-3.3565132746900103151L-21", "8.585503247975515849L19", + "-1", "8.585503247975515849L19" }, + +{ "-6.9204354176156616745L-21", "-3.6158709669328356396L19", + "0", "-6.9204354176156616745L-21" }, + +{ "-7.5176747956103960436L-21", "9.3440027997860057096L19", + "-1", "9.3440027997860057096L19" }, + +{ "-6.302622462978502841L-21", "8.1107309029375862425L-21", + "-1", "1.8081084399590834014L-21" }, + +{ "1.4803054325001667241L-22", "6.3345497995208400772L-21", + "0", "1.4803054325001667241L-22" }, + +{ "-5.7089861270321677843L-21", "9.540482421100450586L-21", + "-1", "3.831496294068282802L-21" }, + +{ "3.3765199428161524112L-21", "9.669802014415968729L-21", + "0", "3.3765199428161524112L-21" }, + +{ "7.52101063082155294L-21", "8.827949370572986921L-21", + "0", "7.52101063082155294L-21" }, + +{ "4.196504310402249954L-23", "3.785428476220113075L-21", + "0", "4.196504310402249954L-23" }, + +}; diff --git a/tests/exam_LF_minus.cc b/tests/exam_LF_minus.cc new file mode 100644 index 0000000..2ba301a --- /dev/null +++ b/tests/exam_LF_minus.cc @@ -0,0 +1,457 @@ +#include "exam.h" +#include +#include + +static minus_test lfloat_minus_tests[] = { + +{ "0.3211111183819802968L0", "-0.7024866236309383056L0", + "1.0235977420129186024L0" }, + +{ "-0.29770116676264721836L0", "0.8494818768850108081L0", + "-1.1471830436476580264L0" }, + +{ "-0.7677860965279355367L0", "0.9474539728585997539L0", + "-1.7152400693865352905L0" }, + +{ "-0.25414380069764370257L0", "0.82619594943351718565L0", + "-1.0803397501311608883L0" }, + +{ "0.21685951051311267031L0", "0.13084151170902027524L0", + "0.08601799880409239507L0" }, + +{ "-0.6658362643286463323L0", "-0.101768362258000388376L0", + "-0.56406790207064594393L0" }, + +{ "-0.8594165074009265017L0", "3.58724520062188585L9", + "-3.5872452014813023575L9" }, + +{ "-0.58779846333918551446L0", "-2.8410824560251060135L9", + "2.84108245543730755L9" }, + +{ "0.37819983918255152712L0", "1.75837003745458279L9", + "-1.7583700370763829509L9" }, + +{ "-0.19345242719447268632L0", "-8.900743696911070234L9", + "8.900743696717617807L9" }, + +{ "0.9170636757513836193L0", "-5.181144559509726756L9", + "5.1811445604267904316L9" }, + +{ "0.20643137049004858552L0", "3.3215544303850617772L9", + "-3.3215544301786304067L9" }, + +{ "-0.4014437452394343757L0", "4.7898418688154180505L-11", + "-0.40144374528733279438L0" }, + +{ "0.0725076594551243524L0", "-3.5321788599004111594L-11", + "0.072507659490446140996L0" }, + +{ "-0.65551702819898271043L0", "3.1653130032883009534L-11", + "-0.6555170282306358405L0" }, + +{ "0.9237105409310637695L0", "-8.9028024814928743296L-11", + "0.9237105410200917943L0" }, + +{ "0.8779771368966066218L0", "7.399233988536237696L-12", + "0.8779771368892073878L0" }, + +{ "0.51385216558296334914L0", "-3.3989256599054576304L-11", + "0.51385216561695260575L0" }, + +{ "0.74939199427992763254L0", "-6.6998781480191798724L19", + "6.6998781480191798724L19" }, + +{ "0.8073774220299670944L0", "2.0433771569275457978L18", + "-2.043377156927545797L18" }, + +{ "-0.75286822781531276375L0", "-7.7011647701976081504L19", + "7.7011647701976081504L19" }, + +{ "-0.6361916050116532222L0", "1.2717052281488651182L19", + "-1.2717052281488651183L19" }, + +{ "0.08977643006115956575L0", "1.2624046205072289204L19", + "-1.2624046205072289204L19" }, + +{ "-0.4220171145412169327L0", "8.9155115345908061576L19", + "-8.9155115345908061576L19" }, + +{ "0.397772867452284942L0", "5.7785851646148710778L-21", + "0.397772867452284942L0" }, + +{ "-0.53062845978690011166L0", "-3.648685738612220277L-21", + "-0.53062845978690011166L0" }, + +{ "0.25409096540159836552L0", "-7.8088660109317384514L-21", + "0.25409096540159836552L0" }, + +{ "0.78038095936361252965L0", "5.166705522400390383L-21", + "0.78038095936361252965L0" }, + +{ "0.2384997171475220939L0", "9.580584601627251829L-21", + "0.23849971714752209389L0" }, + +{ "0.38777493167494073L0", "-7.930455614605653916L-22", + "0.38777493167494073L0" }, + +{ "9.34906594120583919L8", "-0.06276538462885111519L0", + "9.349065941833493036L8" }, + +{ "3.8000098261497040978L9", "0.08156195452126583918L0", + "3.8000098260681421433L9" }, + +{ "-8.5084000619874580647L9", "-0.49084164337509169664L0", + "-8.5084000614966164213L9" }, + +{ "-9.367354572017391158L9", "0.7369625068937909906L0", + "-9.367354572754353665L9" }, + +{ "6.810025547716964613L9", "-0.65456201729278556224L0", + "6.8100255483715266306L9" }, + +{ "-2.0476539871173359762L9", "-0.61684944260168028793L0", + "-2.0476539865004865336L9" }, + +{ "7.927587886187347037L9", "-9.075678068210342653L9", + "1.700326595439768969L10" }, + +{ "8.3881162961959078424L9", "-8.168276983460029623L9", + "1.6556393279655937465L10" }, + +{ "-9.837108887605194379L9", "-5.518197215327419734L9", + "-4.3189116722777746445L9" }, + +{ "6.0530403690423784372L9", "-4.794777582812792957L9", + "1.0847817951855171394L10" }, + +{ "-7.6786817362598780694L8", "3.0685743382723052597L9", + "-3.8364425118982930668L9" }, + +{ "-1.035869943077157163L9", "6.964469962306024778L8", + "-1.7323169393077596407L9" }, + +{ "-5.236689202734255992L9", "-3.2118444581504684365L-12", + "-5.236689202734255992L9" }, + +{ "-5.374622629137047618L9", "6.0449117144963868685L-11", + "-5.374622629137047618L9" }, + +{ "-1.03444332932187716727L9", "-7.849504746710041045L-11", + "-1.0344433293218771672L9" }, + +{ "5.1103879354813158946L8", "6.53093826849017485L-11", + "5.110387935481315894L8" }, + +{ "-9.748335199611953219L9", "-1.0598402609119659922L-11", + "-9.748335199611953219L9" }, + +{ "-7.3482164921795502603L9", "7.644598674874161005L-11", + "-7.3482164921795502603L9" }, + +{ "-7.4770248834652064083L8", "-6.510822784079429222L19", + "6.5108227840046589732L19" }, + +{ "8.3114910321533068423L9", "-6.2387352982669333472L19", + "6.2387352990980824504L19" }, + +{ "-1.0718584220381511548L9", "8.521462332927085385L19", + "-8.521462333034271227L19" }, + +{ "-1.9155322368803175137L8", "1.3150623743950738752L19", + "-1.3150623744142291976L19" }, + +{ "3.8652241507510457716L9", "8.702412273358053775L19", + "-8.70241227297153136L19" }, + +{ "2.922009617968977308L8", "-8.409184530486676791L19", + "8.409184530515896887L19" }, + +{ "-7.3431860804237713437L9", "9.020687655591526829L-21", + "-7.3431860804237713437L9" }, + +{ "-1.1188563145822172016L9", "-2.7575065881283248758L-21", + "-1.1188563145822172016L9" }, + +{ "2.5835681218682880315L9", "-3.786022710650191692L-21", + "2.5835681218682880315L9" }, + +{ "4.3854765424506375063L9", "1.8847509423241615905L-21", + "4.3854765424506375063L9" }, + +{ "-3.4713769831512517224L9", "-2.322290027198980782L-21", + "-3.4713769831512517224L9" }, + +{ "414355.71501652302632L0", "3.5411352752491676944L-21", + "414355.71501652302632L0" }, + +{ "9.032857346451659148L-11", "0.45111022909893884074L0", + "-0.45111022900861026729L0" }, + +{ "-6.5860623447077106086L-11", "-0.16349916999618723413L0", + "0.16349916993032661068L0" }, + +{ "-9.239429491581222244L-11", "0.34742997377809253703L0", + "-0.34742997387048683193L0" }, + +{ "-1.3189202177704638207L-11", "0.6447775025861344695L0", + "-0.64477750259932367166L0" }, + +{ "-8.6095719029859522596L-11", "0.36611643318066821885L0", + "-0.3661164332667639379L0" }, + +{ "-7.9284738631391966236L-11", "-0.28883099180012157807L0", + "0.28883099172083683944L0" }, + +{ "-9.9602023259578447484L-11", "8.944817052366967221L9", + "-8.944817052366967221L9" }, + +{ "-4.7036434158090755064L-11", "-7.652311009876441256L9", + "7.652311009876441256L9" }, + +{ "-7.237899450242616437L-11", "-2.0865196011945540415L9", + "2.0865196011945540414L9" }, + +{ "1.619466049424876382L-11", "5.1184733211578935236L9", + "-5.1184733211578935236L9" }, + +{ "4.1799408897021043963L-11", "7.3289378733409777703L9", + "-7.3289378733409777703L9" }, + +{ "-7.1652994078281664426L-11", "-8.756819754593247181L9", + "8.756819754593247181L9" }, + +{ "-3.7074082585707708083L-11", "7.8185038704847907146L-11", + "-1.1525912129055561523L-10" }, + +{ "-6.236585731179139659L-11", "7.2778046100364844843L-11", + "-1.3514390341215624144L-10" }, + +{ "4.435573645212270856L-11", "-5.0777570123416204425L-11", + "9.5133306575538912986L-11" }, + +{ "-8.308776483243665939L-11", "9.147453931535851365L-11", + "-1.7456230414779517304L-10" }, + +{ "9.9047307392438733836L-11", "-2.5521271062995892868L-11", + "1.245685784554346267L-10" }, + +{ "7.964304540045338675L-11", "-8.2763721216842256806L-11", + "1.6240676661729564355L-10" }, + +{ "6.3981149909251410836L-11", "-8.199461198383311753L19", + "8.199461198383311753L19" }, + +{ "3.2676777703423324814L-11", "4.4068061681801047868L19", + "-4.4068061681801047868L19" }, + +{ "-6.239367423070186989L-11", "3.6883672788938434168L19", + "-3.6883672788938434168L19" }, + +{ "-2.2122757699951901351L-11", "2.1264312306673926188L19", + "-2.1264312306673926188L19" }, + +{ "8.873182931301984606L-11", "1.6930709481447417272L19", + "-1.6930709481447417272L19" }, + +{ "-6.88393272917067128L-11", "9.590650870092490293L19", + "-9.590650870092490293L19" }, + +{ "6.858643038376546876L-11", "7.344128953107545512L-21", + "6.858643037642133981L-11" }, + +{ "2.6458055358368033053L-11", "5.403788941414579396L-21", + "2.6458055352964244111L-11" }, + +{ "-2.0808117056914325832L-11", "-9.598437242399057154L-21", + "-2.080811704731588859L-11" }, + +{ "-6.7475294377176982065L-11", "7.066634775850918749L-21", + "-6.747529438424361684L-11" }, + +{ "-9.3542684131795074026L-11", "-2.671834604826394793L-22", + "-9.354268413152789057L-11" }, + +{ "-3.656675383727620855L-11", "-5.7226858095399702763L-21", + "-3.656675383155352274L-11" }, + +{ "4.4004114393746579576L19", "0.9981645829158248139L0", + "4.4004114393746579576L19" }, + +{ "-2.1157157847974045162L19", "-0.73136590134089295135L0", + "-2.1157157847974045162L19" }, + +{ "-6.58288354566033103L19", "0.6435204448077814454L0", + "-6.58288354566033103L19" }, + +{ "-6.1300052513232283715L18", "0.37782114066015354996L0", + "-6.130005251323228372L18" }, + +{ "-8.3428987469650376416L19", "0.092302889297602909923L0", + "-8.3428987469650376416L19" }, + +{ "4.478146018721476673L18", "-0.7594367116407568048L0", + "4.4781460187214766738L18" }, + +{ "3.9553793567888621644L19", "7.272309486263127643L9", + "3.9553793560616312156L19" }, + +{ "8.4985452245750157485L18", "-8.180191224624705388L9", + "8.498545232755206973L18" }, + +{ "-4.9006940756698268444L19", "5.635530637330344937L9", + "-4.900694076233379908L19" }, + +{ "3.321094625885548145L19", "7.739325488496469393L9", + "3.3210946251116155962L19" }, + +{ "-4.094717236852398814L19", "2.8833151826524522544L9", + "-4.0947172371407303324L19" }, + +{ "-7.297938416992967256L19", "1.7849049534461509205L9", + "-7.2979384171714577512L19" }, + +{ "-1.6274534493365811085L19", "-7.214220253590898893L-11", + "-1.6274534493365811085L19" }, + +{ "-8.8349360721401487896L19", "4.4201546048906225832L-11", + "-8.8349360721401487896L19" }, + +{ "2.1193875854469716176L19", "5.4852102858193519493L-11", + "2.1193875854469716176L19" }, + +{ "5.8956188285652689564L19", "5.2591781987716878005L-12", + "5.8956188285652689564L19" }, + +{ "3.8130742288947136824L19", "-6.2032926048476626596L-11", + "3.8130742288947136824L19" }, + +{ "-8.2648264381835919784L19", "5.240041099543619651L-11", + "-8.2648264381835919784L19" }, + +{ "-8.9795702979594840016L19", "5.3071479395700422216L19", + "-1.4286718237529526223L20" }, + +{ "7.4902067869555502376L19", "8.527286348112666809L18", + "6.6374781521442835568L19" }, + +{ "-9.945686226441305483L19", "-7.164943842935287866L19", + "-2.7807423835060176172L19" }, + +{ "-6.9451908461424534725L18", "1.7337328244166615333L19", + "-2.4282519090309068806L19" }, + +{ "-7.2554820480127785552L19", "-3.6345553532831870424L19", + "-3.6209266947295915128L19" }, + +{ "4.80739562024854996L19", "-9.8058600290712759904L19", + "1.46132556493198259504L20" }, + +{ "-2.2910115296639597206L19", "3.7450560231732721633L-21", + "-2.2910115296639597206L19" }, + +{ "6.3398397438838205245L18", "5.9452907771459291318L-21", + "6.3398397438838205245L18" }, + +{ "-3.6223171453314706578L19", "-7.3897558037422565484L-21", + "-3.6223171453314706578L19" }, + +{ "-5.253323265732561348L19", "-2.4894382246759080012L-21", + "-5.253323265732561348L19" }, + +{ "8.706482285826808214L18", "-5.353671688426432468L-21", + "8.706482285826808214L18" }, + +{ "2.2257683364797036278L18", "-8.640543721759613242L-21", + "2.2257683364797036278L18" }, + +{ "4.793610535063041737L-21", "-0.46707949288138879385L0", + "0.46707949288138879385L0" }, + +{ "-8.1177127707349576126L-22", "-0.524723160625887566L0", + "0.524723160625887566L0" }, + +{ "4.3845050204409245572L-21", "0.25137862247046227512L0", + "-0.25137862247046227512L0" }, + +{ "9.521149905664397992L-21", "-0.8412363166750659234L0", + "0.8412363166750659234L0" }, + +{ "9.174773471390805996L-21", "-0.101196005202611894716L0", + "0.10119600520261189472L0" }, + +{ "7.109559498077443181L-21", "0.9205539164614073537L0", + "-0.9205539164614073537L0" }, + +{ "4.698785699006337068L-21", "-2.1800327611972026394L9", + "2.1800327611972026394L9" }, + +{ "5.613624265510662971L-21", "-9.950548243828975189L9", + "9.950548243828975189L9" }, + +{ "4.6909741937286841078L-21", "-1.7837781830572891826L9", + "1.7837781830572891826L9" }, + +{ "-4.846242463794952647L-21", "-8.0162418694778434667L9", + "8.0162418694778434667L9" }, + +{ "2.40959428070040729L-21", "-8.889381116534260471L9", + "8.889381116534260471L9" }, + +{ "3.767840665510686708L-21", "-6.5742819327593306936L9", + "6.5742819327593306936L9" }, + +{ "-4.2984578582437655097L-21", "-7.11707524430297521L-11", + "7.117075243873129424L-11" }, + +{ "-8.2197602823824843314L-21", "5.6157517586290544195L-11", + "-5.6157517594510304478L-11" }, + +{ "9.693403466151038911L-21", "-2.4790192993953556532L-11", + "2.4790193003646959998L-11" }, + +{ "-1.7473025967684817638L-21", "-6.763791909706180161L-11", + "6.763791909531449901L-11" }, + +{ "-4.545821853960128388L-21", "-2.0149758755990572603L-11", + "2.0149758751444750749L-11" }, + +{ "-6.727743751498960878L-21", "4.6105155267302345166L-11", + "-4.6105155274030088917L-11" }, + +{ "3.1693009676315354841L-21", "-8.292132887357976433L19", + "8.292132887357976433L19" }, + +{ "-1.5197222855116101305L-21", "-6.8790212191073234628L19", + "6.8790212191073234628L19" }, + +{ "9.221684449614781083L-21", "-5.9085200983462461748L19", + "5.9085200983462461748L19" }, + +{ "8.784720275148798145L-21", "-3.507151222326700691L19", + "3.507151222326700691L19" }, + +{ "3.824100155304652155L-21", "1.2903444775641864255L19", + "-1.2903444775641864255L19" }, + +{ "-1.0750770892330241413L-21", "2.516785805333378789L19", + "-2.516785805333378789L19" }, + +{ "-9.607606672669937465L-21", "2.8158700323501294737L-21", + "-1.2423476705020066939L-20" }, + +{ "7.9685140548406097L-21", "-1.4252185339263422407L-21", + "9.393732588766951941L-21" }, + +{ "-3.1900732903251523987L-21", "1.30212230775860485605L-21", + "-4.4921955980837572548L-21" }, + +{ "2.845180721925488069L-21", "9.0340678136597289194L-21", + "-6.1888870917342408505L-21" }, + +{ "-5.1500491616497403683L-21", "-5.4818765813663490764L-21", + "3.3182741971660870814L-22" }, + +{ "5.3946808417918276896L-21", "2.1630450195342998269L-21", + "3.2316358222575278627L-21" }, + +}; diff --git a/tests/exam_LF_mul.cc b/tests/exam_LF_mul.cc new file mode 100644 index 0000000..953fda7 --- /dev/null +++ b/tests/exam_LF_mul.cc @@ -0,0 +1,457 @@ +#include "exam.h" +#include +#include + +static mul_test lfloat_mul_tests[] = { + +{ "0.49162375558276684976L0", "-0.27595139770835290185L0", + "-0.13566426249969417521L0" }, + +{ "-0.43085705615141429406L0", "0.76537655129782028376L0", + "-0.32976788773950077688L0" }, + +{ "-0.34725675573811781168L0", "-0.44040731024013641718L0", + "0.15293441375734052306L0" }, + +{ "-0.47158645084591665022L0", "-0.5531952534025612003L0", + "0.26087938617692133303L0" }, + +{ "-0.86377959068682791106L0", "-0.8711108145957097161L0", + "0.7524477428743513754L0" }, + +{ "0.07688091831246728666L0", "-0.727039245375017451L0", + "-0.055895444833634576195L0" }, + +{ "-0.65693719777446694155L0", "-5.4929597366864347663L9", + "3.6085295769067602507L9" }, + +{ "0.9553509506606886749L0", "2.7316499794256227606L9", + "2.609684404716519364L9" }, + +{ "0.86245066819702621825L0", "-5.6471738746979076876L9", + "-4.8704088816580000957L9" }, + +{ "-0.0011095142242845852372L0", "3.5868904614046262004L9", + "-3979705.9878791318615L0" }, + +{ "-0.07537979049336559763L0", "8.268739091555253606L9", + "-6.2329582036573719373L8" }, + +{ "-0.67924101443000006024L0", "-4.2094803212494913754L9", + "2.8592516836286270604L9" }, + +{ "0.30774277681107480866L0", "-2.7334742019139702906L-11", + "-8.412069412384417957L-12" }, + +{ "-0.35713749207523871768L0", "-6.5398928539622633783L-11", + "2.3356409323048581577L-11" }, + +{ "-0.14801577485738927266L0", "-9.963460779718656755L-11", + "1.474749367571264873L-11" }, + +{ "0.3104124542612814659L0", "-2.9286317751062608258L-11", + "-9.09083776938307737L-12" }, + +{ "-0.11446530018625016218L0", "6.4232974401995419684L-11", + "-7.352446696780128213L-12" }, + +{ "-0.96939447601348607505L0", "4.1094462170225605183L-11", + "-3.9836744622561876338L-11" }, + +{ "0.051486415762180288123L0", "9.676829213398296352L19", + "4.9822525214063672425L18" }, + +{ "0.6313327973134614946L0", "3.2653448877462378072L19", + "2.06151932217404323L19" }, + +{ "-0.37403303660944479204L0", "9.102796469067070187L19", + "-3.4047466049628882508L19" }, + +{ "0.8707828063294901403L0", "-5.5603708853312765524L19", + "-4.8418753637615606188L19" }, + +{ "-0.21026381134874289964L0", "-8.2572592232280544185L18", + "1.7362027955704909688L18" }, + +{ "-0.77817271482774886984L0", "-5.862569134483721118L19", + "4.5620913392465632268L19" }, + +{ "0.10774233598980040668L0", "8.42277329172514105L-21", + "9.074892699629673044L-22" }, + +{ "0.25190108887664378198L0", "9.9261121984538427104L-21", + "2.5003984711022594346L-21" }, + +{ "-0.6756036645959631085L0", "9.531794528346356556L-21", + "-6.4397153135265482465L-21" }, + +{ "-0.6857203923976410447L0", "-1.6874445000752253093L-21", + "1.1571151047408247225L-21" }, + +{ "-0.44633489376857998266L0", "2.2805928928283052886L-21", + "-1.0179081865499001544L-21" }, + +{ "0.6194914893234261562L0", "6.122106446320417613L-21", + "3.7925928402275834338L-21" }, + +{ "6.0914569120648219218L9", "-0.13082334282848865785L0", + "-7.969047559320230858L8" }, + +{ "3.6214037646489572409L9", "-0.42724054260765242458L0", + "-1.5472105094100157093L9" }, + +{ "-2.3587970682548096273L9", "0.30389573937962490564L0", + "-7.168283791037869264L8" }, + +{ "-1.2092840284272862272L9", "-0.9464357317324953064L0", + "1.1445096143169982957L9" }, + +{ "9.742195251878672378L9", "-0.8436238049826486367L0", + "-8.2187478272737786206L9" }, + +{ "-1.6670311480587791415L9", "-0.7664626357070004785L0", + "1.277717087546798815L9" }, + +{ "-9.63709082566058824L8", "3.5038182805272664595L9", + "-3.376661500605117691L18" }, + +{ "-6.819958133674458717L9", "5.570090504807835795L9", + "-3.7987784043567071428L19" }, + +{ "5.7990616985027046753L9", "5.7633314369957429715L9", + "3.3421914592058566914L19" }, + +{ "-8.4466610113280742876L9", "-8.965949996407538079L9", + "7.5732340264172639616L19" }, + +{ "-7.670563670654851578L9", "-6.431751468798164421L9", + "4.9335159155244181172L19" }, + +{ "8.268803418474998627L9", "-6.6310260568279516366L9", + "-5.4830650926695757004L19" }, + +{ "-9.461472353405244053L9", "-3.3101188730107237675L-11", + "0.31318598203475886787L0" }, + +{ "6.8579221981166585744L9", "-8.515361268298587097L-11", + "-0.5839768506684770405L0" }, + +{ "1.6137913170162297342L9", "-8.897666779537493419L-11", + "-0.14358977390521366923L0" }, + +{ "8.022366744559274285L9", "6.8759798363047156095L-11", + "0.5516163197503107306L0" }, + +{ "6.268637730252729325L8", "3.8798987053952144677L-13", + "2.4321679414199160154L-4" }, + +{ "8.165455714479826517L9", "-7.748491839935670887L-11", + "-0.6326996697300302909L0" }, + +{ "-9.245309913477613381L9", "-2.7267702243723164598L19", + "2.5209835787164953515L29" }, + +{ "9.113617507957836761L9", "-3.6781774780542862056L19", + "-3.3521502661371744663L29" }, + +{ "3695599.756951605604L0", "-4.4160607831464309996L19", + "-1.6319993156879467502L26" }, + +{ "-3.1080975558777002585L9", "4.5635619314557275256L19", + "-1.41839956852540638L29" }, + +{ "4.379846040113489209L9", "-2.380244519018666713L19", + "-1.0425104531125744157L29" }, + +{ "7.799437686108443071L9", "-8.213835920178370665L19", + "-6.40633014233504056L29" }, + +{ "-5.0032293022496024175L9", "3.9947928432298324106L-21", + "-1.9986864609664499789L-11" }, + +{ "5.1002825856458055377L9", "-8.630588067810955288L-21", + "-4.4018438026138695895L-11" }, + +{ "-1.4798783656292287931L9", "-2.1821599778945012917L-21", + "3.2293313416280286032L-12" }, + +{ "6.2153176651245460436L9", "-4.842239650508967686L-21", + "-3.009605763857489489L-11" }, + +{ "1.1476929860538426329L9", "8.143327858153323155L-21", + "9.34604026593943011L-12" }, + +{ "-6.8097130569212408313L9", "-4.5006072118169309446L-21", + "3.0647843694383655263L-11" }, + +{ "-8.088711469864653681L-11", "0.55856748494727835656L0", + "-4.518091222186502735L-11" }, + +{ "4.4880121763658923538L-11", "0.14537105272497022953L0", + "6.52427054720794526L-12" }, + +{ "2.0273639671422034382L-11", "0.5267742506127895251L0", + "1.0679631345107062621L-11" }, + +{ "-9.078881981481347403L-11", "0.86040896737522678964L0", + "-7.811551470607918988L-11" }, + +{ "-7.2713602444015266416L-11", "0.029963115152720655096L0", + "-2.1787260431991794891L-12" }, + +{ "5.8587076221559354985L-11", "0.39205420166003709617L0", + "2.2969309395639195554L-11" }, + +{ "9.465227148840012531L-12", "-8.4020295562921954743L9", + "-0.07952711826157309293L0" }, + +{ "-9.156088652050785426L-11", "-7.272635024207867507L9", + "0.66588891015656744834L0" }, + +{ "3.6865969618651574387L-11", "4.532198690564411727L9", + "0.16708389923204005057L0" }, + +{ "-7.773548969171738747L-11", "6.487140494299404015L9", + "-0.5042810430233337584L0" }, + +{ "3.181536837232243521L-12", "-8.8275599983550392825L8", + "-0.0028085207317644360498L0" }, + +{ "3.512130320642090343L-11", "-6.775467122704530228L9", + "-0.23796323518164203024L0" }, + +{ "-7.489684894543042722L-11", "1.3562671200654034619L-11", + "-1.015801336211924759L-21" }, + +{ "-6.615171167169027831L-11", "6.4492881876773102747L-11", + "-4.2663145267886736825L-21" }, + +{ "5.9969037329081164062L-12", "6.979117807067958578L-11", + "4.1853097629611348155L-22" }, + +{ "-9.1419010578306515213L-11", "-3.0321662473944421986L-11", + "2.7719763824573648138L-21" }, + +{ "8.653994294784604749L-11", "-2.618325063862645785L-12", + "-2.2658970164558872502L-22" }, + +{ "3.778177082827084054L-11", "5.7986141594804582746L-11", + "2.1908191129505701787L-21" }, + +{ "9.107023861930220456L-11", "-8.1609888558011610015L18", + "-7.432232024672778029L8" }, + +{ "-6.185675579794400257L-11", "8.145498215172660237L19", + "-5.0385409394852397568L9" }, + +{ "-5.0086846264250856304L-12", "7.333671928137704804L19", + "-3.6732049841708537418L8" }, + +{ "-6.133300578664362783L-11", "-4.647031661618042392L19", + "2.8501641979273554706L9" }, + +{ "4.014159298839782726L-12", "7.077385833663047478L18", + "2.8409754155675469803L7" }, + +{ "3.9529027598797003857L-11", "3.1931221840357166776L19", + "1.2622101493907881026L9" }, + +{ "5.2407793550579649295L-11", "8.178146405814506225L-21", + "4.2859860846234161862L-31" }, + +{ "-4.5792905534935737864L-11", "-1.1970719995732820388L-21", + "5.481740499497593831L-32" }, + +{ "4.113879746633747024L-11", "5.1093090279978304893L-21", + "2.1019082929573231173L-31" }, + +{ "1.9918804321687295055L-11", "1.8243807936344826748L-21", + "3.6339484036649830696L-32" }, + +{ "-6.1549842617771214656L-11", "7.210193834294849238L-22", + "-4.4378629574447235495L-32" }, + +{ "-3.483482946766538465L-12", "7.8771698631837073084L-22", + "-2.743998688718375137L-33" }, + +{ "-3.0540130142847980374L19", "-0.08015004741507677209L0", + "2.4477928790118809798L18" }, + +{ "-7.721729897125586787L19", "-0.71282981020428696123L0", + "5.5042792570168003116L19" }, + +{ "6.855667806362567159L18", "0.83087248440613607433L0", + "5.69618574253563119L18" }, + +{ "-1.0247670372283575993L17", "-0.21215039186338500874L0", + "2.1740472851667611836L16" }, + +{ "-4.2451902701279432204L19", "0.363650960045267158L0", + "-1.5437675173068535736L19" }, + +{ "-2.3286355030172533736L19", "0.49713327148260372132L0", + "-1.1576421857055056984L19" }, + +{ "-6.1529172975127592432L19", "-7.1685660040728041152L9", + "4.4107593764821477366L29" }, + +{ "6.7120643409032119372L19", "-2.1673488299796731996L9", + "-1.45473847960048627434L29" }, + +{ "8.1354429987417636456L19", "-7.205222753181797397L9", + "-5.861767900174770815L29" }, + +{ "7.1263614941049137416L19", "5.4835530180135407083L8", + "3.907778107845448494L28" }, + +{ "5.0833800113097826724L19", "-6.2188724451883454807L9", + "-3.1612891880755627472L29" }, + +{ "-7.0947371956905508468L19", "-2.434705753418370145L9", + "1.7273597469339097183L29" }, + +{ "6.6532780031620346828L19", "-5.126482819920582625L-11", + "-3.4107915379365690604L9" }, + +{ "3.3916052110984390742L19", "1.2477416554656457027L-11", + "4.2318471007818771302L8" }, + +{ "-2.0596546301412947634L18", "1.4681903489886446838L-11", + "-3.0239650502232254483L7" }, + +{ "5.4448198096650564945L18", "-8.328351500006325204L-11", + "-4.534637322908812735L8" }, + +{ "-9.0101064221252591136L19", "-8.313725422339249255L-11", + "7.4907550819604901853L9" }, + +{ "9.807792586975021252L19", "-8.1013942555768171325L-11", + "-7.9456794524008327797L9" }, + +{ "-6.569928333884882197L17", "1.8031274577764523257L19", + "-1.1846418174451330701L37" }, + +{ "9.966374081256518232L19", "1.1925741835931471136L18", + "1.1885640433338393863L38" }, + +{ "-5.1958776350000747272L19", "9.541066943279536452L19", + "-4.957421634462466998L39" }, + +{ "3.0864687811444473814L19", "-7.292720897062086383L17", + "-2.2508755378381858676L37" }, + +{ "-4.9023499593352016396L19", "-7.837521201177228469L19", + "3.8422271741879966693L39" }, + +{ "1.1092141282192635266L19", "-8.705681388875638857L19", + "-9.656464792316359058L38" }, + +{ "9.719341608862581484L18", "3.910223765755272544L-21", + "0.038004800546468552602L0" }, + +{ "9.0834836835472717744L19", "2.3217130663560934873L-22", + "0.021089242756124079488L0" }, + +{ "-8.9569500426805542816L19", "-6.8114530414478270673L-22", + "0.061009844610312705923L0" }, + +{ "-6.250871904307721917L18", "-1.7897852706103755451L-21", + "0.01118771846280218958L0" }, + +{ "-4.8350255195162635852L19", "-5.4114390027140489403L-21", + "0.26164445675428065787L0" }, + +{ "-3.787718813779143278L19", "4.715777953310022763L-22", + "-0.017862040875357275534L0" }, + +{ "-9.6946973380533561685L-21", "0.29842171245928506197L0", + "-2.8931081813963549629L-21" }, + +{ "-1.5138229787560283214L-21", "-0.63587548364028950173L0", + "9.626029187622732088L-22" }, + +{ "6.9088409628577453984L-21", "0.6675889882861618064L0", + "4.6122661486241942486L-21" }, + +{ "-5.9331491274547789645L-21", "0.1840021396402183602L0", + "-1.0917121342561739605L-21" }, + +{ "6.5714942924276749333L-21", "0.042451475976117785684L0", + "2.789696320821885891L-22" }, + +{ "8.381861494201174241L-21", "-0.14355711097860731382L0", + "-1.2032758207303532943L-21" }, + +{ "2.014342763215141127L-21", "-1.2338457666735291661L9", + "-2.4853882910224610282L-12" }, + +{ "-5.670580024618139724L-21", "-8.0192486381311308156L8", + "4.5473791139832611237L-12" }, + +{ "-1.9225557816894129732L-21", "7.9269598913745234357L9", + "-1.5240022570382171054L-11" }, + +{ "4.0368254062037218916L-21", "-9.5325393449487114215L8", + "-3.848119701332554298L-12" }, + +{ "4.2776037356780859957L-21", "-5.1221437260809706463L9", + "-2.1910501137364030878L-11" }, + +{ "-6.7334467986153699064L-21", "-7.7745493828541701813L9", + "5.2349514652656512034L-11" }, + +{ "-4.315187380180362795L-21", "1.3410692406986483366L-11", + "-5.786965063410868682L-32" }, + +{ "3.343397258359340776L-21", "3.0757040339096610197L-12", + "1.0283300434498325547L-32" }, + +{ "8.5537743863632264L-21", "7.5263454541513394514L-11", + "6.4378660968641032133L-31" }, + +{ "-2.842610565794174946L-21", "3.153716909493170071L-11", + "-8.9647890084490369953L-32" }, + +{ "2.8400800161467519014L-22", "2.0497242686367281441L-11", + "5.8213809339661880995L-33" }, + +{ "9.982896581447590365L-21", "1.6568727649785948007L-11", + "1.654038946139843086L-31" }, + +{ "4.678227176611232891L-21", "8.297236114758786796L19", + "0.38816355482824754693L0" }, + +{ "-2.7181316933272033506L-21", "-7.7081523870452907184L19", + "0.20951773300223540615L0" }, + +{ "3.755562697893016061L-21", "-9.043255746258523336L19", + "-0.33962513948155180184L0" }, + +{ "-6.788248742851763723L-21", "-2.3639021583849588926L19", + "0.16046755854881268057L0" }, + +{ "-4.100847017987407598L-21", "-3.6481227061862975968L19", + "0.14960393120916230025L0" }, + +{ "-2.001548479939126796L-21", "-8.705055796099425971L19", + "0.17423591196468091344L0" }, + +{ "-3.670443367722997441L-21", "3.6588667206894740936L-22", + "-1.34296630883370731296L-42" }, + +{ "-6.6783435670093499397L-22", "-8.113066551196750321L-21", + "5.4181845810903550342L-42" }, + +{ "4.816859192586505112L-21", "-1.1868626619923445382L-22", + "-5.716950323755514841L-43" }, + +{ "4.6402358755296483015L-21", "-4.244356902115351796L-22", + "-1.9694817165747535215L-42" }, + +{ "9.3247068197076461794L-21", "3.5271238356611001996L-21", + "3.288939568434245211L-41" }, + +{ "8.7860048755888267426L-21", "7.187872989134290154L-21", + "6.315268712764710716L-41" }, + +}; diff --git a/tests/exam_LF_plus.cc b/tests/exam_LF_plus.cc new file mode 100644 index 0000000..67bc9c1 --- /dev/null +++ b/tests/exam_LF_plus.cc @@ -0,0 +1,457 @@ +#include "exam.h" +#include +#include + +static plus_test lfloat_plus_tests[] = { + +{ "0.31465012912061093874L0", "-0.07221963987249409544L0", + "0.2424304892481168433L0" }, + +{ "0.7168586654865411176L0", "-0.19348808923554474066L0", + "0.52337057625099637695L0" }, + +{ "-0.64115701400120904706L0", "0.70535558267169594756L0", + "0.0641985686704869005L0" }, + +{ "-0.8607621650923123159L0", "0.8368256394262067108L0", + "-0.023936525666105605082L0" }, + +{ "0.44168990042410450855L0", "-0.6041911435521196045L0", + "-0.16250124312801509594L0" }, + +{ "0.0234267775301613878L0", "-0.43594485933986284478L0", + "-0.41251808180970145698L0" }, + +{ "-0.99559578594307881024L0", "-9.836107054378142702L9", + "-9.836107055373738488L9" }, + +{ "-0.72423071295455899397L0", "9.238843039595790172L9", + "9.238843038871559459L9" }, + +{ "-0.20719390117857393156L0", "-9.029224604657100362L9", + "-9.029224604864294263L9" }, + +{ "0.20816015380514039224L0", "-7.4782571284307568003L9", + "-7.4782571282225966468L9" }, + +{ "-0.16613875159201114463L0", "-1.203554507952656804L9", + "-1.2035545081187955556L9" }, + +{ "-0.9837368636729942673L0", "7.5892747601936916704L9", + "7.5892747592099548066L9" }, + +{ "-0.92391870362276300936L0", "-5.309205414965326826L-11", + "-0.9239187036758550635L0" }, + +{ "-0.2308075581152660786L0", "-2.5400598439608570973L-11", + "-0.23080755814066667704L0" }, + +{ "0.5668336039528930528L0", "1.9300606943253841182L-12", + "0.56683360395482311353L0" }, + +{ "-0.19685144163870526662L0", "-8.548847281762266571L-11", + "-0.19685144172419373944L0" }, + +{ "0.053837363417219887007L0", "-8.4734948552444605444L-11", + "0.053837363332484938454L0" }, + +{ "0.24539562474220232599L0", "-1.3753029433519360674L-11", + "0.24539562472844929655L0" }, + +{ "-0.83198492765474177585L0", "-1.0728971972413839207L19", + "-1.0728971972413839208L19" }, + +{ "0.58494670591273850794L0", "-2.6078285749436068966L19", + "-2.6078285749436068966L19" }, + +{ "-0.6489422625947265175L0", "5.675479528094312524L19", + "5.675479528094312524L19" }, + +{ "0.82416783003308421654L0", "3.4337105673864461624L19", + "3.4337105673864461624L19" }, + +{ "0.5977825969561704576L0", "9.447212597358366985L19", + "9.447212597358366985L19" }, + +{ "0.81709616259702447027L0", "1.8840697606071622024L19", + "1.8840697606071622024L19" }, + +{ "0.99140689029640294337L0", "-7.9441986163714183364L-21", + "0.99140689029640294337L0" }, + +{ "0.49487318874207713882L0", "-2.377409962381832069L-21", + "0.49487318874207713882L0" }, + +{ "0.050320977002567080524L0", "-1.3329877923173878127L-21", + "0.050320977002567080524L0" }, + +{ "-0.25724170819862546218L0", "7.609825486664252559L-22", + "-0.25724170819862546218L0" }, + +{ "0.3667308347763138993L0", "4.077152141636570548L-21", + "0.3667308347763138993L0" }, + +{ "0.5130660492586603372L0", "-5.091230019243679202L-21", + "0.5130660492586603372L0" }, + +{ "8.916053557053472733L8", "0.59999700846599703845L0", + "8.916053563053442818L8" }, + +{ "1.250980635471676891L9", "-0.46325398810664378442L0", + "1.2509806350084229029L9" }, + +{ "-5.548594356609427516L9", "-0.21577258386321002115L0", + "-5.5485943568252001L9" }, + +{ "1.06508055885340104636L9", "0.8422978396429581549L0", + "1.065080559695698886L9" }, + +{ "6.225756677310580186L9", "0.49531151031004978726L0", + "6.2257566778058916964L9" }, + +{ "-2.273191688409860673L9", "-0.80983784631745405196L0", + "-2.2731916892196985192L9" }, + +{ "5.688674258485728496L8", "8.2409948814224157357L9", + "8.809862307270988585L9" }, + +{ "-2.7544302700606018156L9", "9.230174236450698873L9", + "6.4757439663900970574L9" }, + +{ "-4.588747139238971857L9", "6.342892129519977196L9", + "1.7541449902810053392L9" }, + +{ "1.5275587581475159762L9", "4.3720035959575018324L9", + "5.8995623541050178087L9" }, + +{ "2.8881760807020099163L9", "7.5622154923755766074L9", + "1.0450391573077586524L10" }, + +{ "6.1044519092512786468L9", "1.3858854402983849103L9", + "7.490337349549663557L9" }, + +{ "4.8767035174458515886L9", "6.3051681974292703475L-11", + "4.8767035174458515886L9" }, + +{ "-9.4188975960705796466L8", "-8.975187577611984141L-12", + "-9.4188975960705796466L8" }, + +{ "-9.689819354179956828L9", "-9.7453604450079548966L-11", + "-9.689819354179956828L9" }, + +{ "4.987209054002559248L9", "9.284991248759031191L-11", + "4.987209054002559248L9" }, + +{ "-3.5572071813296941216L9", "-6.261737879308894803L-11", + "-3.5572071813296941216L9" }, + +{ "-7.5872628366112743053L9", "2.2152240842834943001L-11", + "-7.5872628366112743053L9" }, + +{ "7.0206128338340270845L9", "5.9246012493594508704L19", + "5.9246012500615121536L19" }, + +{ "5.3017367315254228474L9", "-1.0933628665004153848L19", + "-1.0933628659702417116L19" }, + +{ "-6.339538144593375358L9", "-8.0543624921112893224L19", + "-8.054362492745243137L19" }, + +{ "-1.6010717980362600647L9", "9.973849926670833376L19", + "9.973849926510726196L19" }, + +{ "3.2030522063397198562L9", "-2.4396867565423101768L19", + "-2.4396867562220049562L19" }, + +{ "8.8622195973163761245L9", "-6.4961266512803550736L19", + "-6.496126650394133114L19" }, + +{ "5.45529926142043848L9", "6.939479435912862762L-21", + "5.45529926142043848L9" }, + +{ "-4.484627189114150671L9", "-1.6571134694524616111L-21", + "-4.484627189114150671L9" }, + +{ "8.813820141949620774L9", "-2.8267147580155665537L-21", + "8.813820141949620774L9" }, + +{ "-9.972890003927356798L9", "-3.0273462676816521264L-21", + "-9.972890003927356798L9" }, + +{ "6.792889851253184185L9", "-5.937539083879130763L-21", + "6.792889851253184185L9" }, + +{ "-3.2663407400779399923L9", "-4.0747082067253115984L-21", + "-3.2663407400779399923L9" }, + +{ "-3.4242541190221825202L-11", "-0.71988400153646663195L0", + "-0.71988400157070917316L0" }, + +{ "-7.8906347145510431055L-11", "-0.22021321631029436988L0", + "-0.22021321638920071702L0" }, + +{ "-7.486719858997914782L-11", "0.38102237422222776873L0", + "0.38102237414736057013L0" }, + +{ "-2.6956794925506179954L-12", "-0.49627581161649902356L0", + "-0.49627581161919470304L0" }, + +{ "-8.312064814531952837L-11", "0.5797009072836515581L0", + "0.57970090720053090995L0" }, + +{ "-4.0305959593285763394L-11", "0.16233584979062195143L0", + "0.16233584975031599183L0" }, + +{ "3.731977491280278192L-11", "3.0305998235716452734L9", + "3.0305998235716452734L9" }, + +{ "2.7847304030282320388L-11", "-6.146190065628934066L9", + "-6.146190065628934066L9" }, + +{ "-1.1797664511795163538L-11", "1.4888590774768513251L9", + "1.4888590774768513251L9" }, + +{ "-3.736849276790130025L-11", "1.9988395869145483342L9", + "1.9988395869145483342L9" }, + +{ "5.7818526942690563386L-12", "3.5155514714363584847L9", + "3.5155514714363584847L9" }, + +{ "1.8183862272066184134L-11", "-4.635399960322760982L9", + "-4.635399960322760982L9" }, + +{ "3.5539523819420841283L-11", "4.3044646394847154864L-11", + "7.858417021426799615L-11" }, + +{ "8.719537619908441472L-11", "-8.580989797275158101L-11", + "1.3854782263328337111L-12" }, + +{ "2.49701168436805957L-12", "-2.6066406246366064513L-11", + "-2.3569394561998004944L-11" }, + +{ "4.2774640500882048993L-11", "3.7620100241760410496L-11", + "8.039474074264245949L-11" }, + +{ "3.9907211434460210612L-11", "9.72066373418363098L-11", + "1.3711384877629652041L-10" }, + +{ "-7.851637932849992129L-11", "4.9296626910685147652L-11", + "-2.9219752417814773637L-11" }, + +{ "3.14874349918113769L-11", "-1.8148353890339025639L19", + "-1.8148353890339025639L19" }, + +{ "-8.444922682942673745L-11", "-5.0034364072191331772L19", + "-5.0034364072191331772L19" }, + +{ "4.762299619586316462L-12", "-1.3412404578328588061L19", + "-1.3412404578328588061L19" }, + +{ "-9.22833351501850052L-12", "3.1000370791158631634L19", + "3.1000370791158631634L19" }, + +{ "6.1164399913981911425L-11", "6.1863455383782109436L19", + "6.1863455383782109436L19" }, + +{ "-8.413645565754525347L-11", "-2.5034082588556447364L19", + "-2.5034082588556447364L19" }, + +{ "3.4875247204061292656L-11", "-7.8682893445087250245L-21", + "3.487524719619300331L-11" }, + +{ "-2.1647610944488691768L-11", "-8.371089558230910183L-21", + "-2.1647610952859781326L-11" }, + +{ "5.7598234760228848032L-11", "2.8011007358408259187L-21", + "5.7598234763029948767L-11" }, + +{ "-9.268425959344303144L-11", "-6.4655012698265179856L-21", + "-9.2684259599908532713L-11" }, + +{ "7.067467072298381137L-11", "-3.8206328350148818058L-21", + "7.0674670719163178536L-11" }, + +{ "7.8912028748606542386L-11", "8.456364925917236866L-21", + "7.891202875706290731L-11" }, + +{ "-6.976183652817340798L18", "0.08822040416435015717L0", + "-6.976183652817340798L18" }, + +{ "-1.2414457404200743984L19", "-0.85791705029429396234L0", + "-1.2414457404200743985L19" }, + +{ "-8.9687515173878579424L19", "-0.3328210335620137057L0", + "-8.9687515173878579424L19" }, + +{ "-5.438581645592863998L19", "-0.67774278184358142436L0", + "-5.438581645592863998L19" }, + +{ "-5.4350840695201649084L19", "-0.72739900682842943577L0", + "-5.4350840695201649084L19" }, + +{ "7.814697448090367615L19", "0.24326892882624165414L0", + "7.814697448090367615L19" }, + +{ "-2.4356768540932142124L19", "6.5169042447583127604L9", + "-2.435676853441523788L19" }, + +{ "-8.7464253032141704904L19", "6.8315507162032823036L9", + "-8.7464253025310154184L19" }, + +{ "-2.4810334273518910993L18", "-7.638114077520272164L9", + "-2.4810334349900051768L18" }, + +{ "-9.80334620432051716L19", "4.474822777555302305L9", + "-9.8033462038730348824L19" }, + +{ "-1.5185085475715921137L19", "8.496315073274781452L9", + "-1.5185085467219606064L19" }, + +{ "-9.3842548893937585184L19", "-9.948865349103608366L9", + "-9.3842548903886450536L19" }, + +{ "5.9391253980818643888L19", "5.6213951287112563564L-11", + "5.9391253980818643888L19" }, + +{ "-4.8270749631022207188L19", "6.506986668488438766L-11", + "-4.8270749631022207188L19" }, + +{ "8.953940231252599753L19", "-1.7735448342981541823L-11", + "8.953940231252599753L19" }, + +{ "-6.1065165153181616235L18", "-1.8103764902203059955L-11", + "-6.1065165153181616235L18" }, + +{ "-9.6224955477275161216L19", "9.4659333494557267205L-11", + "-9.6224955477275161216L19" }, + +{ "-9.2620034246522033504L19", "-8.920063409062509698L-11", + "-9.2620034246522033504L19" }, + +{ "5.9633456897700879935L18", "4.0390945943970882336L19", + "4.6354291633740970328L19" }, + +{ "-6.1420542659063065884L19", "-3.9869088703267959336L19", + "-1.01289631362331025216L20" }, + +{ "7.804124970286546613L19", "8.061318173712112305L19", + "1.5865443143998658918L20" }, + +{ "-7.763817772329800516L19", "-4.9349702057713961232L19", + "-1.2698787978101196639L20" }, + +{ "-3.1480955091040648274L19", "-4.706529024129812914L19", + "-7.8546245332338777416L19" }, + +{ "-4.7131343507844737428L19", "5.4602299451983202032L19", + "7.470955944138464604L18" }, + +{ "5.9403761194093478956L19", "-6.280541343011718101L-21", + "5.9403761194093478956L19" }, + +{ "-3.763295388652278206L19", "-9.963494853851408371L-21", + "-3.763295388652278206L19" }, + +{ "2.5136958358030666948L19", "5.335607709622335287L-21", + "2.5136958358030666948L19" }, + +{ "6.2273952762016960176L19", "-5.6012630121574213906L-21", + "6.2273952762016960176L19" }, + +{ "-9.3934610912833028936L19", "-2.59552531586503232L-21", + "-9.3934610912833028936L19" }, + +{ "2.9584554660239488776L19", "6.875837450751388893L-21", + "2.9584554660239488776L19" }, + +{ "-8.4905558825256936576L-21", "0.112912972443893420624L0", + "0.11291297244389342062L0" }, + +{ "-5.3259362300699140443L-21", "0.44064771529278198132L0", + "0.44064771529278198132L0" }, + +{ "-9.245572241572266517L-21", "0.043497459079983070442L0", + "0.043497459079983070432L0" }, + +{ "7.6311333407948593004L-22", "0.74437178299084331024L0", + "0.74437178299084331024L0" }, + +{ "-7.71114100404407176L-21", "-0.30667849853816871164L0", + "-0.30667849853816871164L0" }, + +{ "3.544120177696956032L-21", "0.79322122717232419205L0", + "0.79322122717232419205L0" }, + +{ "7.7913861181291523115L-21", "8.526554352243632931L9", + "8.526554352243632931L9" }, + +{ "-3.9196632415032070805L-21", "-2.5228304289307799614L9", + "-2.5228304289307799614L9" }, + +{ "7.643174046933518012L-22", "2.9248526891356128762L9", + "2.9248526891356128762L9" }, + +{ "1.8801815336593227227L-21", "6.8178694125314363L9", + "6.8178694125314363L9" }, + +{ "-2.6985037225367287349L-21", "-4.5571976978858014136L9", + "-4.5571976978858014136L9" }, + +{ "6.0444611510506986126L-21", "-8.64585025875790907L9", + "-8.64585025875790907L9" }, + +{ "-1.250177749198396931L-21", "6.428634063301101147L-11", + "6.428634063176083372L-11" }, + +{ "-1.5666058964343815161L-21", "3.552568414787808555L-11", + "3.5525684146311479653L-11" }, + +{ "-5.8078119773790503857L-21", "8.896395897015492877L-12", + "8.8963958912076809L-12" }, + +{ "6.7472260162031965506L-21", "-6.617115409846031908L-11", + "-6.617115409171309306L-11" }, + +{ "-4.16121984125470857L-21", "-3.095053467302410671L-11", + "-3.095053467718532655L-11" }, + +{ "-2.114411383443366621L-21", "9.716046816037651671L-11", + "9.716046815826210533L-11" }, + +{ "-2.3406730990296292957L-21", "7.900725768498098123L18", + "7.900725768498098123L18" }, + +{ "-4.1514248667302411754L-21", "-8.4325334951006246184L19", + "-8.4325334951006246184L19" }, + +{ "8.433933541545648577L-21", "-4.9459088765496691632L19", + "-4.9459088765496691632L19" }, + +{ "2.2922577085250648752L-21", "7.813245819908182463L19", + "7.813245819908182463L19" }, + +{ "8.887270525300553388L-21", "8.651116139112459977L19", + "8.651116139112459977L19" }, + +{ "1.1406539199130032192L-21", "2.3931812472136783544L19", + "2.3931812472136783544L19" }, + +{ "-3.778523001798117503L-21", "2.0779948578933832532L-22", + "-3.5707235160087791776L-21" }, + +{ "-1.6066062689688361383L-21", "-3.5232009896946632975L-21", + "-5.1298072586634994358L-21" }, + +{ "3.9703618511174300454L-21", "-8.036088455194107478L-21", + "-4.0657266040766774324L-21" }, + +{ "6.46657477279861825L-21", "2.6384883907642781157L-21", + "9.105063163562896366L-21" }, + +{ "4.9706631077050274314L-21", "2.3628052244020145395L-21", + "7.333468332107041971L-21" }, + +{ "7.065951142271372955L-21", "3.1965272324939519L-21", + "1.02624783747653248544L-20" }, + +}; diff --git a/tests/exam_RA.cc b/tests/exam_RA.cc new file mode 100644 index 0000000..eef5e69 --- /dev/null +++ b/tests/exam_RA.cc @@ -0,0 +1,7 @@ +#include "exam_RA_plus.cc" +#include "exam_RA_minus.cc" +#include "exam_RA_mul.cc" +#include "exam_RA_div.cc" +#include "exam_RA_floor.cc" + +DO_TESTS(rational,cl_RA,cl_RA) diff --git a/tests/exam_RA_div.cc b/tests/exam_RA_div.cc new file mode 100644 index 0000000..605dbe9 --- /dev/null +++ b/tests/exam_RA_div.cc @@ -0,0 +1,142 @@ +#include "exam.h" +#include +#include + +static div_test rational_div_tests[] = { + +{ "7013212896988366906/12397903473277899947", "818833870013215068/2125577647443895255", + "7453564285301859120853045020886215515/5075911640537211768265804260348400698" }, + +{ "-15781329068048599432/14942574238341613337", "4388772934226358350/2640112802717985697", + "-20832244458230302534551181278529162052/32789782692450857054331267544650656975" }, + +{ "-9015230453321124271/17425619133302730035", "-10422000746814766599/14972344381173680534", + "134979135022768387806775446187867640714/181609815620990738305316999098032100965" }, + +{ "-14741075237791868512/12448692140900938227", "-1090381863721238817/1060836378253796023", + "15637868866825840780217685066084527776/13573828137487503515304766902031557459" }, + +{ "-7371815071140740177/4722722556038701367", "3872455829192658988/994203944294825175", + "-7329087620340161131469364260313555975/18288534491791723206480607737200436596" }, + +{ "-9856364379969390509/7988230468709836259", "-7208901117187058135/7430860779232874136", + "1093153305924514768551484985555671272/859497963436269188803272225817371895" }, + +{ "-16740689272507881147/56924866550406451570641164619431212169", "-14712532880452686095/143481612520580129383584255576273223983", + "2401981091525408257128502717450566513166280001357873948501/837508970838236191644285394369194561392491093277901090055" }, + +{ "1874027699956565000/65960003455647360668413772300355814843", "-172394881832672950/2006879686300828197846469567507151887", + "-75218962452157875130617756878839223573611935155763100/227423340028380523596387094039260091189651621559491937" }, + +{ "851521912886492079/58839621451933520132430725102159653727", "-5525838657334730480/268863138354222710211869290179088409033", + "-228942853876053297959532391872114722003932597144466549607/325138254802036127673497464266072288930584674567672498960" }, + +{ "2130823024472312937/30463932363736038600114358208342163020", "413938864244113775/131673792970459944919771618253738144891", + "280573549781056638388629087822719475587456644826399754867/12610205563054396144647765193069861697742251186477600500" }, + +{ "17234694073181371137/253506951459931119968572673772742357160", "8407879684613951161/42697666588937447817581914537644794355", + "147176244259806896721181660841298454615950364713859506327/426291189417673978158704851675227114861497071554451732552" }, + +{ "14739301038477826821/4801125431810347467140397350459581435", "-1752125940488995048/127905197451270157484305628763539243969", + "-1885233209620217720514367144506571751170505057476450692549/8412176412616337518572109406238500578932979745867733880" }, + +{ "9194848570227974720/45448499872046683203864930109076126035374684748838016011669264943000310475483", "-4572473918523931944/28941042619577200519536336906341131911598596429670188136734086846500956354149", + "-33263563043940787786171015409141766453199063320923723716765930467953050399983260590187417389160/25976510037621464639740779963549572814837984766154635046133743883024710122710674726552171566119" }, + +{ "-2662376868940711929/2674240208804755702377222409224408783678596883960539287029565653749020338064", "-5046618244273151929/26826013625152995057141957222948811537350409769204161465077735924332004069058", + "35710479080747854012875521001477955195584454274704368888444222736697434540936425667291700196441/6747934713661461716612153292457811722283965560031580498434684530869001786777260513409206862728" }, + +{ "646980248518054663/28444849537262537816809349756569888989442483441699293309597267649158853799707", "-10174938507557455325/16470612178414296088079890015341965945714023680627341561729034923083435428747", + "-10656160760434978971303471120231114671340660575734505071429575384684610862775940451177787597261/289424594898370460244167952344748286246980979584479610186308309369583658143095854438992150589775" }, + +{ "1268676597518744714/6024937921458004492480888468749320142603908196076058575752452561172018490893", "17823595902143962912/85935047374548136904062562443188289405155329832270007415035044821925251080203", + "18170630585125644385503771892175817370913744757273904248648000044618805359154885235028182716157/17897676474595109057512045856227678061218241143085827332930191066967148125532813505892133626736" }, + +{ "-3035741006152688190/58890268425224581569217175195410848521985674465189565646495474378301884202047", "-4870935665435665519/47998868922405332801456101880162843269583282603435159879276723163289928325531", + "145712134636693761356266465698326002831562744975420904782663360472436650653549187025441059178890/286850708819506259357726384810790881448875152111132928069815447961129371272624891025817707117393" }, + +{ "-4420263280205408439/38682162086456801604593696710774835436326970692840048042132553053971380151628", "-758651402628235427/1755534012040040367913026343944696058732638465867705260088080517539506722166", + "3879961265286134914514096239640695384126081133972137242327715997675029567458817030555062379437/14673138261791601182714628661554161812345431143865809776872034934342213839184709418896670662578" }, + +{ "-312487180249669742743295380499853180353/9828632991038934281", "-86131955660561774942466932680637336739/10268762916730341592", + "3208856768501438660232746468300370677374054716853273141976/846559380988100144557815474234956961169507773676687849659" }, + +{ "105376075880566042097567073713047434893/11411565636673693365", "-220737802783327232867818580441304577024/5817406274606660773", + "-613015445021032499619145665530563205764250055719854552289/2518963924957071797477174332253152325843619212749200245760" }, + +{ "-311533429150518992652072799089375050497/4403073054828470603", "-320230219907951760832723580313293021909/1370493254961533625", + "426954463345823097468320537904981772054351338526938461625/1409997052618498081840381197699863669488222338862641441127" }, + +{ "305676222727436457375950609916137360009/2001517485431820526", "324338803123828318219640932070020543912/11123178903397935211", + "3400091311912189654145957985944153094384781502787164376899/649169785656371151621897383467144093766684841422885937712" }, + +{ "8845112929712368402815105446090151026/8124751572615311799", "-107609110538267962880281203537194473336/8714443449141779053", + "-38540118213625599008519681983731393728094066419546629189/437148645036763776481446937412401903340367189496615845732" }, + +{ "152921217721894690043853278309581658066/11705615305395353865", "184187448038871874764725486848823516773/4171619104693691390", + "127585814672335876029018138907883882524550368713261650348/431205482165106014329333719781838993214328411764819575529" }, + +{ "16414254293541341780725162107696242521/155838132618727968561620486302365154071", "323320173010032367023620851618405869489/49801924105617352177018959505967933104", + "817461446577249670665800625691379410535771218196808189195363718417488315184/50385611999847495177988476252475899813264458225659097815552272081452203039719" }, + +{ "-188149667625860588508273820953820709614/21438745582767797684161462130971215025", "128458309657689922121539794960212789849/134174286369366827879740776978166655691", + "-25244847384333405496229128525982900130397411994350175944375943735942831513274/2753985018743617742875555653653797261370358442640799457019039857068516281225" }, + +{ "1218460641064115152742257147372113443/1773382194117714970762642066492794929", "-105212349758139121832338365854603836112/35045896682356785176328011712384921341", + "-42702045738251194875426595475683618047253961691478453648029952948483687063/186581707662369193907913729212042024270164277319717456729276609131940676048" }, + +{ "1467722271775252460214852151179762687/1747611358981474614363356529179985509", "25495740211005247928144692929451604259/29615224810946461612486375021101910565", + "14488975012885720730598332784736375353299643425098519766594278819666029385/14852215066131169889445443721709162270198753408805825268529301698140894277" }, + +{ "6278399735526726207674375684072448068/13890681759576280617381650633747782321", "-112063146811220963294237186476216238443/46495820670393894026441353693945662660", + "-291919348200099113895651901892723884699250237261456280525601785996696740880/1556633509331345870779770006255469001211806559199158615405344674499795966203" }, + +{ "248406099260780863433196593538936526373/315762135750029127758352280023694126018", "-24578051912523675039725210046249323571/3033769619337997374435389027823294736", + "-376803438597807975522050212312559316811899647514236724224019181136008036264/3880409082236781853269738100403484871805889674074731389226471480469265885139" }, + +{ "-305871752543087256004326578375555909668/80170799467978436032303243749692785696371676780847080230403479135749775915991", "-208573266832391890136462745593008906685/96016271562601269514856687672805175650907293023094157826925793080307407361434", + "29368665255505841438632782694581946057561031972462112644657516768267440383833513431444679871238206541553985530943912/16721485549600848123731461311227384049611071114404954309505697259277905994635125654414916826332204568970567318299835" }, + +{ "-171651126582338417143004525987733942986/48126955023093310081685702171788275811688444573315712039582092051531229683107", "32570134112026732491936310765048378699/18584159151613423191553551933672204731023422884196280183931777685641069715348", + "-3189991854959918631828923606391779823799241149346421336570141741355492000935500642040047513113849334779592681149128/1567501379505627719887579027549074087653888429037997616626567546431482074522690424133509833932668944596793898937793" }, + +{ "-31304786393644787215292629624842492472/10539846271603297974613179098685212701091372728582260780054561526149580513583", "43496364289252206338797704034889660065/966865502932307025364733802774045297740949567802356684866342045679773834966", + "-30267518040679809082934454680954168768135550720881039440573156734314284479043791824457029301083428211405425375952/458444992982373700837242411005687390212275114474481688646320865335043970683786989531994936463047685893258985162895" }, + +{ "124366625369659591476708994326732418029/107684759001536292829359995221778346870065030877016948429894748600664800488759", "-90949754058598173499067700725927605729/79727020098830307921496202496061295138733611655702270828135321391380898414003", + "-9915380440470549523296226431396644117384598256053664887332801972488440466568616812942647849957495261151611303260087/9793902347049141646079571573977765974008832433473016883117384010293158932212528563016145547341801740792289848500311" }, + +{ "26792084925762094333829722201654015569/6815899891200140342329613369008754659665480100088941978786466272502677117648", "179968988142253715757129058636648023126/97033837835570527321466682927970125702018459951415339098532052222053589117353", + "866579607987744230609336186273867662887766686833260209925103055244528379635362816895584608387230956963010276689619/408883535566062149539621907018509777969515872715944952500700527207173412646715462423653890585029605025758308909216" }, + +{ "320794852821756057819990044473359503428/42380074203350930293358543616207018031675687905746455222111844144668904183229", "-11813439835454851567822019323728871339/51852159737956631156972450987013128151750117741949546305537111598356497409240", + "-5544635317209327550045071802859986261979158492907374734760649234578367469399038563605323839330681533705071632958240/166884818941132804535892580774781586387104334774784737031184369589400544303785250219152004898392301479219940857877" }, + +{ "63160395612932962868082774785156358041658469338654564454114468396132462549944/5671929772244157797", "19541045450680948617094710246839287171374470593288265457341382295544977156173/10827756125123268218", + "227961786821047895774887365257727015864174017882302289602409601101722343657899277052494444293264/36945145824164509580938949252327087600266044162541122809277442696583642758457532273140841543627" }, + +{ "31389399613343712511677734270541516183531975055644318154870016415582858008412/11320913214023484367", "-95931706646769408081251897664360951854776052790951374912970042200868629796051/14301831604104230477", + "-149641969141325406602881756591195860220337618158488775091717625369334526143115090325362684257508/362011508473745439254610688691597507367516106821889963803421575701854031622412859179610532278239" }, + +{ "-50845041077039215658764589763556935122444212169574762080162289087527164772395/482986173890811026", "-51342299909113507561385579724776151277474630060658338514843664853027455595538/3864573616937705869", + "196494404298439669659681446421686066898686292162412914850963937042669022612531239234324840686255/24797620991857267698917294149872672843409173617406514673128342148521539559341861421304646801988" }, + +{ "76283614020376921713154299810619585257752996149145061806263596894412414185408/337890011287912517039286436540240936661", "70530558237421368381589233382700323659036925075366138096846582768833233488577/12121510300837787759729092713205686989", + "924672613133132744522463879340347327755455994321131972145048214329608890428265966744607561005512244129921459256512/23831571118985077324412202325831974453532679575894228007993082738742295289254461850021038245882565939546151124021397" }, + +{ "13518475961402756750057330871273933874583566313800024119371308450919239424622/71146816100737230880567880716110051085", "-11914742388051168959634071864657967837347162591767656949770878950409478930980/166466796775669753065110807850377519909", + "-1125188695291804746273664719520877594103080002716204716437885631737502681157239448228517736957154781558316254899699/423847992785167635691798025732868758201476408654527740579259436528169254792708107390082891890404030666159494556650" }, + +{ "-53624051286117226406327700847140806598091981633622544805551583455315188018537/149060170957501829683988930330276188371", "-49540630291338976658332195799658601133012561780540500265134312414843218811481/313014990314092319823049811442768272842", + "16785131893926373429171158665038393627227592608630727377590747943991201054188961463248027101037470630205119769672154/7384534820569381535972144752572408048556227885764547207137140227958732266609348654686668662110083737942669493487451" }, + +{ "2634758410586745842739353561704344884865889793873131750193619887157306355755/83106075320614705363810122092414199463231740446254118542567688658288107572919", "10787649314660479714744029413883607304719873485501736976813666398631455642569/2439964488756696481271244145022481444549967702052558191280867337292105066432", + "2142905652761565172685487282499186838096673751132490328620490049367034561455889328384026705096013173825469773464105722689198047146574263705663366838720/298839732158850477765824602476778580028064205733214070073086531571837859351705342746223206218407306637658483098569582239416197836311325170250187389329637" }, + +{ "-1907320079310938642409293211056905401889419041722087613680756850005726714712/10387378553621846874105702088597026076825105075730032753153301604042569998683", "113647247724474559442709588703965365251731833799417671287796250968092484717057/58756890421232187224353930678527831208703723187770044891160428018937233424397", + "-37356065632762902117955690133395145368676268194116097031480521390942668514422835237280325034441435052929702455487858500299401976652159912902024146542888/393498994563785425899168694480259206994308562177080555315323154941891277193612821825931878224565302417504072329241812530787363937691786269618438039211977" }, + +{ "-54987418627898620923060954379316763081930842855917193391807940070173620336071/17370345837184638879794373707261631548922174314274224219546763452439685451597", "107349939397731511365417710412808670916754334908520065561311453951414109180973/7800708635318451621630266369706695626474649690647985662113853436261704078874", + "-428940831324519456770429889832838610542119304716244392653623661175655561457214418178921042544524225772650432309479656622489393939407340321261255371264054/1864705572939408818246392762570376592749103793151936455808919833872532407312841098160841844995663367019074328670998871082130543124576872890789577304863881" }, + +}; diff --git a/tests/exam_RA_floor.cc b/tests/exam_RA_floor.cc new file mode 100644 index 0000000..fca1fdc --- /dev/null +++ b/tests/exam_RA_floor.cc @@ -0,0 +1,153 @@ +#include "exam.h" +#include +#include +#include +#include + +static floor_test rational_floor_tests[] = { + +{ "13918288150951705093/1401140429528746218", "8037346830653401534/12140087246062147767", + "15", "15819536596165521240797345101333717/5669989019487990500153722689252798402" }, + +{ "-3027396677293618661/17394867614909941317", "-2291333958125929004/3188627451035828949", + "0", "-3027396677293618661/17394867614909941317" }, + +{ "2672347537044132983/1242644867650938739", "-18408840898134373335/10231522001278674776", + "-2", "-9204560351304414094275545654164256161/6357074151573303338260935869140273732" }, + +{ "2909960574201625242/1140661215026522267", "13303037060238089383/18166352033245030796", + "3", "7340592943788470245594328177983578849/20721653182840810059519494723194734532" }, + +{ "8198662690782244017/1375380265264517299", "-9940234650829186147/17690753691491997765", + "-11", "-486100547007747193780627302695509498/2211955773175772955922986386719257885" }, + +{ "3966139130172032305/18040321970861620778", "152082737803043526/946729689784517957", + "1", "1011240112172972726360628393816617657/17079308423086645837394450304465310546" }, + +{ "10199468022732280591/121419468943382552600797741323914786260", "-2627475271750260665/95465240194344921114274153619846654671", + "-4", "-302411943986468199606823674581501024373007929237189061039/11591338766949818909386523271402122174353420293128216789558932652732995620460" }, + +{ "-8471401573321747185/5927836485002954534423728282157030389", "-10006560123550811854/209494971446104969537769985569938393355", + "29", "-54515717208483066409886298754350924985999966734110450701/1241851935162873209670541996670866824232223815534136678858726178724570665095" }, + +{ "3041516402669280559/23467966340832028705164128018098446335", "6098690148519419819/74694157223362514640536233319542912231", + "1", "12008521321399654679364472921217933270209469640706386252/250417138224955291159963090840561809997874350767164909187205124534624089055" }, + +{ "12371726101368968041/23093272201098893335944386552801821150", "552920335555268471/59704833009801809998987650097493815639", + "57", "10833671498697672110331389655963519805471190684307179149/1378779960416507709477447168250340219220272308941040290894608990101550964850" }, + +{ "3936278768643199217/61530125725985401304656961990591319570", "-4622522820386904221/99931589582562481620405120529601200875", + "-2", "-11699348415245273343366505594272785590391481515341739671/409920218067509498701508662179031915635595553469094563928706113041525908250" }, + +{ "3378221394828629408/57360271731094852990248264232533113197", "-4121489923477642292/582636574825978160767401314647264235", + "-1", "-234441506605160102966099186988989055202999923102442904644/33420192252492486160839993475212088893408362946965395344436948483624609295" }, + +{ "-3136864170660359113/44018155426864484368550814560728963265607376469242388043913852619483671810359", "7592249764621265399/61218932554330370729612969835045191215382261653025522947071546902482986859295", + "-1", "142161354082922159316702479104046765633220994190482626315401062617857980099757409386379034462906/2694744488243248258380889922671073488004909384816885899374920518252041793957332742201117787314100221762775952924983170065632438581816845330037820256436905" }, + +{ "8388845076992722039/113324439625023255923060004687633012536810961583168953468887128369059333869915", "29270787347930250/338347801532036561796340241450622341080868991428994657767799334610272208941", + "0", "8388845076992722039/113324439625023255923060004687633012536810961583168953468887128369059333869915" }, + +{ "4061469742865314937/64801603451247667482343238717974543532449298971352747107214551636724513855613", "1344403291462061700/38470586305356068360716898225197866224089081322833216143931662358746898751411", + "1", "759644321951821493138045865317431182965861074290543254824595494322779964610920583206631767077/27395117343919593983759778902763691133722708413625034340026933459895718790907695509798551507285536033282436777270923749566119049487283571076783727846373" }, + +{ "-6300876868463754766/63495830134457398131576869576746882401947668656296419431644557856865817622371", "2683373787654434721/32958906466135519543294750118994566579246721224880398401534853634103601897753", + "-2", "133096081053989316587079956940067402118415059770888001584265696499152144351877946562766899046184/2092753126391210514581307904104631961415819403699771474276457943469530908829049497503906750315560161637143522534287446520082226490203274292567625907432363" }, + +{ "-472307136668592250/36283411370339306010717878389083492352344779970196813667782297535345620767127", "-3180306511295187523/75166923119981694900512094733973876755239261156251968596129974579413418042019", + "0", "-472307136668592250/36283411370339306010717878389083492352344779970196813667782297535345620767127" }, + +{ "-3148795985647001686/64429795462330994424525695145310698340316900821860011346129307089831843824641", "-11298596415200487525/56650030835870774988744337125832477562271330606264442454925440669251648355512", + "0", "-3148795985647001686/64429795462330994424525695145310698340316900821860011346129307089831843824641" }, + +{ "-102545151309532699273956369870862301497/6030775709520909501", "-3288683205470962892631604702141093469/1221554251153305018", + "6", "-348033375896483356529697355308057680498851424685117674/409273316984297575168605808523732001" }, + +{ "262657016871433510082498751402781174749/7573480743368102221", "51080528722906667824171406466289726452/1601607284756767193", + "1", "33815990969774126823949725673411671713268069951579559665/12129741929543448973808409847523235653" }, + +{ "138482489784362691982393629835416135309/3631852344347114410", "-24756007176022054565783765242491988918/219932185588761813", + "-1", "-59453406054861418860933161489781197608471921856017953163/798761223827929241442393231350025330" }, + +{ "-212217151846170123039362268732482984696/11596630494102963285", "157767757347916893207763952109296030356/10257360923209581435", + "-2", "32941352246943117620876731374547894383947184420447916448/2643351654913607911070701558622724755" }, + +{ "-66747006612989726802598039638160699571/2655077042212383298", "40811355885089157404164119163071734769/5571784139947382276", + "-4", "15382315863254661753182362315746357118308047043239937263/3698379038534340915097856546560906562" }, + +{ "68762140087929702254258676232660238758/15300356027061891153", "-35857327153107467171153230588794581375/12686181688605082704", + "-2", "-37488456798327399439537660212002603897618511901320984853/32350516076608496130809185423035152952" }, + +{ "242045811640213090811968332747485173382/200549144102874156362839425688475328049", "-14720899626826592765120758929463878529/55362986404688226126571951930830517493", + "-5", "-1360940123773119189782995319087829718305547957827775584170427519233923828279/11102999538439281856672090511521389719230333671905312848993361013013608061157" }, + +{ "-119845294654504250162135973476212065855/100235561394484311088266800183679226574", "80594461105267736432364594799413149425/61631997559252488378599155330559465978", + "-1", "173031536634535211165479230108382118112369885610634326444128663790131209690/1544429468803790002857581373808877159258315141389178393568445604388376624843" }, + +{ "-230485693234637510798211679560546639349/52735224446003804525152654032694494673", "-216057981617610709644611545583688426965/260006637986112259187147152181319007048", + "5", "-2958479432060194175681245276352090941756054532611547690395592385359334844527/13711508411648488620980405764270377927416829995446554240961159998044485455304" }, + +{ "-6594316542549343232263525515993767282/10217421010314527320204876001269664067", "150738011702184633072457541580514087744/135040956724953232085930818414328999685", + "-1", "216550304321963092517168155612888510209814057236150214483836375316700196226/459923436164837338339599279302608001719626738369225259576013169605366272965" }, + +{ "215280935061082631947114960623303029323/207354325693067193327551969107966799241", "79751059907103262336474674983968289237/4337760464235769010513178238272088134", + "0", "215280935061082631947114960623303029323/207354325693067193327551969107966799241" }, + +{ "310160128112311271225164732000676894965/86670395306350722800942425502835485142", "178141651878134061724955020964246844473/148821875093870378260620578385076958277", + "2", "5093132355806944300558276298272344941234347692198850733707837927916021244991/4299483581539365588748720077960621199296398702837049138084337644406995806778" }, + +{ "-108659820552054791199784298344597956614/11790531032698157780195997261827578010352156078055016836768011974016954903741", "-92538322534416259700833065660026629223/19585963177324586927996277066630337817907750129846119872015696245293090497388", + "1", "-1037131280631376361623284528995684848351041247146708940120596004521550738167239284685366257725745514224913041700989/230928906647528953486003129436653219142752591225509660589870619206780147714239888278154624266956202529317853226309156501996262035307639197627615351928508" }, + +{ "5394706491096230323847274166255447931/10999333470518091906908673737442830723710024941373839628113269063387717150756", "105688652677006186461732590041930264063/21972728496093720326374563200555762299989227113998910666496198593694363180514", + "0", "5394706491096230323847274166255447931/10999333470518091906908673737442830723710024941373839628113269063387717150756" }, + +{ "-191689412702065586724423672263415136270/93810201821180445246181740077575222573046098171118578720996957721548578622199", "-96035306478379345278597023485459703599/90477882577875726723065337577743037040931870384035502080606137411367114071296", + "1", "-8334560691183765714134253806956288712175511004636349604358505688696669629914037375584956898475941052209595993911719/8487748424983587977143569651002086894691875550521839392659856872027244953584789975128015403703285861633097358090901236825413778659897331594626425134299904" }, + +{ "-23269937861894460494044792238228308465/36609152344338882339480850660297061488131282119857763060331849352205685148721", "325068909216594106686082320524489871331/91177237475655724082435461235746167562462517272459785633509544221351873775622", + "-1", "9778808569440655820425835535754928474979020881405653286273845718180424961228320899578451645656486131670752875977421/3337921377082244749772660717107363339434489502423902307989133990817960972244485458695718522007125256227586389900645261310720433804087640398154830854279462" }, + +{ "-238326953836192259685740729837504392751/14355772111692545517089448796014758311054554297101342377064555342044509505629", "-2243842813596041779461072557214411973/26977869328891440663623277939723739398284518432434090329689171706564354694000", + "199", "-6448765647740977471904737113847651808330060639815597135148713750030489976324569684096986913258458168828297495539/129096048048195144296601029799754739460578975322841318685536300111243981862070688561642588911885232705019881753766051653025282618058049676501115190842000" }, + +{ "-154358049055187385619395426022892405693/9651466522903571511806795329901971873531573523740147689205585933143787251744", "234831599528611417562275088467151900111/23212020955553784427152057042945842586938059290340162186208579138883161355663", + "-2", "316658791137724604029754690574124702890700231484127998714230110560397057808441246896564869593555547226559779365903/74676681060487840411987924431521223169933844488425876950176937169482763523750924018302125631058404128587876741120722730563623397211887516476096033675424" }, + +{ "-43654015885600226452139253734240763904114948357839504394635758939147918485226/8959421350865475053", "-71396498978827369985021009185210519228191289633806094987720268011017813959395/5118659875263168828", + "0", "-43654015885600226452139253734240763904114948357839504394635758939147918485226/8959421350865475053" }, + +{ "30206748063040753946799836869317684942154090322823467523870425873885298155111/10481539418044277488", "47024848487236673350978260730205414416590483746605328718368229684499622280474/7191921838593099535", + "0", "30206748063040753946799836869317684942154090322823467523870425873885298155111/10481539418044277488" }, + +{ "-78297878369391722158254897331818780133560455296543117876032852961696240531334/3439835335342974343", "-12036259456916995957158314961009661904873237837146662571140339452059150719867/7648180594799196815", + "14", "-19197805765101853520494699712598051602631126933023081616555585309855479307669655742300981287876/26308481861074724148503061769552317545" }, + +{ "-11644466368871135752271367372638717312589950278007329817169736850185519100737/1311440431008130360", "16666792145043036974187190230561351375866940864814143604767927371030164658327/1190204555866760523", + "-1", "7998208151350462202845967149504108047636942539158206705970028049633264098721802988652183702269/1560882375733744790369742288085778280" }, + +{ "-79973663368880337215592714973251653953011156710750446016524362581184906490344/13217906252057303539", "58550120458525994168414457422879483045080411293174816365332363703279727325517/11983119832054095608", + "-2", "294743007488634911900879023610601157709203210196036764662698142539282328840165292825377976700087/79195877273629847756913363266891378356" }, + +{ "-41283916983957018057492477658728498328100012640087810269690534262888976961251/890401703093780527", "37905097813993829793947873722213455441729327992618875876994782685865871567157/6801392244603328629", + "-9", "7656253348038361960592683452946138937700391767097248361228404271354846832369355003597180736924/2018657079334544839920956083927269161" }, + +{ "-18621387073793741287833632061282985993236184599525107084971126746444001531559/112377251064249742125143336262406044187", "-80344252057643577515390451958447799739023169996897035042227858478107352127859/16565237077789941458934656364080562722", + "0", "-18621387073793741287833632061282985993236184599525107084971126746444001531559/112377251064249742125143336262406044187" }, + +{ "-11067278490740390186400140048488373691939192899502978554850454064301747327289/279730468938850077684950205987597341304", "10742600231685337944302634339424380376867728558611903252501449407612160123471/85514692364145379323997472383947484080", + "-1", "85775736874497976296219552104494263998937714945890467644689458878788010379480929901293727971077618208617170461961/996711041507662039484243506170638972651237308243642442559705598573661101680" }, + +{ "60114400703399744178227904113253512958642740092037841351403601970012663733574/137652538688206271590219421417082587275", "48818636606796573849225811493965362933035106650390076441334389457476994620122/53029693036557887125608655547988906029", + "0", "60114400703399744178227904113253512958642740092037841351403601970012663733574/137652538688206271590219421417082587275" }, + +{ "3914498366778062569843980805049542971189141573995351572704819538012574198620/2893535793927099250376915741311683101565016171163532500028982710856616653543", "-64455977862771995990556362474021252617135665526576459531278423102067698175925/3427268293660091333898426457103031174054024747619806545506815375759964110507", + "-1", "-173089642940460836493548201378493831666834527213381638819285816422714170656111775323359444521902045952676537769939820706047335458029055584112252141651935/9916923483096927116177052980173451074387932639677487416966276325060341893415045555506102924285291258490295955820662010134773377007870870750288985076301" }, + +{ "88685468991633001080737925907185943038820418099572822599681084512202985499349/12356339561700478684701129356342132279853496560835988907745653698832814553183", "6529471572210817352014560971376587702394496047549533959161274051805568907/3739659250056306079416159597801009351379164652345884310988690700223397485", + "4", "8931962841313470806790103494237286341563410404854617106114803081793820819240374925219641539537617481113314045913411523358730270170471325648745013341/46208499538749877879324553712339970407875860449933229680283463405247211324108302788607460717099015088790299594129098751336540918286885704752480944755" }, + +{ "5294621876959552948152278397535786930445255402598688035901577017296377116948/5881250468392395166026135319241737823103911942970361556821993967308880332607", "-65630221834131781450865541487035630878349246622282004360445526978282263449249/98696808137715829282209856003081855629375417101578635063186137762415694777903", + "-2", "-249413266253338816038191146071217173249587815937933968995202267999853691656986532179554523041282106904325952906300316562845535251623832095499430051524242/580460649088775579832453445973177920831893989101100068436102498480125976298386547626652311003668489010795846489626845062951616643824353457996671633983121" }, + +}; diff --git a/tests/exam_RA_minus.cc b/tests/exam_RA_minus.cc new file mode 100644 index 0000000..fa38820 --- /dev/null +++ b/tests/exam_RA_minus.cc @@ -0,0 +1,169 @@ +#include "exam.h" +#include +#include + +static minus_test rational_minus_tests[] = { + +{ "8229768172162771789/4094631553683915058", "14916542302144281688/9648520391570031013", + "18327341244785642013243791303754634353/39507136041685332578233153660317693754" }, + +{ "13554976081719376860/5850035209629724601", "-6813034992928443315/16012083383654426278", + "256899901877002811987490932642058619395/93671251573905451634945335611797465078" }, + +{ "-221798849980968127/896588178875000428", "-10118632981534633697/16809799818197706916", + "333990778095757160537366868413422249/941966737890699707694484674257410003" }, + +{ "-10398409463665680242/10672871071680021919", "908300169382593227/1663860017749090135", + "-2076589873614048366639515256135965791/1366012573135328609279238070700513005" }, + +{ "-2198518713248421187/494031967775171833", "162489257999262168/3608560229859558061", + "-8013762081101965644053022173225152351/1782744111192743850497670941715295813" }, + +{ "4025149216228566945/640594137312937394", "5467380276809034025/15813352732084653151", + "60148732603712157399679443099667862845/10129941051434949990590527231467828494" }, + +{ "45649282670476595/278386580761220266717341154184065537", "-8637266763647548631/320617180101036447149595031898805939080", + "17040443444897688379155017841073877168061229451634462447/89255520501631886327999278515127058459530587144975987720686743155549485960" }, + +{ "5648415331928005377/86815630814151297970860026950116430492", "-3858618729527320883/27855468652821710859204555976171379400", + "123081918822962876101148539477322308270739795776139149559/604572520679633516300271119677141637780408278090307422820905500994965166200" }, + +{ "9781572955588417059/112881800445343004034168709823458687843", "-5059688483724168531/4577416283528891230944530353546966748", + "615921077060787960354561606126348783111829996215681822765/516706991472571912574910836774186280180852506048696459094758451180832844564" }, + +{ "-4967914039344839478/238170260180199675500515253723794945205", "1851848905279976507/5731170327270969184071911155742503278", + "-469527297115675955424190428047537920421409443442551107819/1364994327983166854234805393053180119374354994464588574791772715189542881990" }, + +{ "-16853061581795824324/96404437352723357070647888504166371117", "2887610208906060444/32980643277330946266739822018299212963", + "-834203249643667606680245846951263316484378801689149307960/3179480358681967952651970543397987660141008737601948320258541111852875189671" }, + +{ "-10766003534404571638/1736320411127247334175538439020437437", "-220564366893542891/24024005562370344889629855466198025799", + "-11228676451427374102904112111967705085778332338188090365/1813624835433832784217556253227924899981441517333394378436857197512671181" }, + +{ "-4039872531792560303/2717817538621352660433068255065439787147153801016478776178010367557953211548", "-17969900169229544519/10371230759745501411127733226376204123221866394120596070959771442399588297129", + "6940459580028931824293913174633904994365279610168782399332846513086074139209123514834476635325/28187112855925579976299840753672542065528422968220885043792832460046226866036339425358907691441054924266606457279617295071355282523744922239122018045692" }, + +{ "11905720953886477738/26349991043344773150817457299711471013733618033386232710348739943906972457535", "-1868508269239354100/7915113871665192715310471309271830385175189228544536787145345883401181858893", + "15941145914794937177093386304443205602552827651536706608400845076162777444155363739893353329726/23173686625047977587990304423741788120258508897732978034793987736019678129860415537604628640859289817332994555163435451240013483415438259775849311623195" }, + +{ "-2449440712560236858/3924161613720467738425590715321110829708355586356453490516463081317902575263", "3313932993860824279/18392642760231276916239249302906853654153090246504347205856270072174622214792", + "-19352032211145724571420568734409847660231095572377236173431089875006133635431666731719362137971/24058567564857748536604240288023690440577404826273237225585673569644473540232022448230431237781096357243673961302816983638647478040822458289501843963432" }, + +{ "2375854596996813469/17171542567603713573317138241061150416263899780234956304631913156611236192733", "-1690236091628058998/115698505401619203741389026136939663329574241316722960060260525901879106902321", + "303906786920788985464713527121698374469813384178920405503303785899916213843318155692692663023083/1986721810512032345893371071989737461519340072368099757524397292434629497187713075053126253107235936414498803590298681018206068059043963268488989361033293" }, + +{ "-9066703779833220052/53996509329904595759286231403247566365148374715934463324003880626270687736687", "10104829441267883881/34350188217372122913844475743718288066233853695548819225257606841719829170673", + "-857068498550946301314281599902676812596945461499639532351672507051201056365247232693696093577243/1854790258563312749374056592838765632813507083399863975139987272744324437901043103651094837595789610803765303659351781344942305171362498886075754606580351" }, + +{ "-712905705954993103/38361275706852471555340413672243335795384295466685977818182375699688812583403", "-3487523845474404757/24004509207225606167828624323100421869226668573968691661898194620137716910067", + "116672912187985693533424614379662678476187446315443107971581372764612623068602629062267386180170/920843595906060126846114857872490000269306626188013726759480780006531676144330596572087176480154495471428384288229491172449159350622326294294528887818001" }, + +{ "-104068455909264700529593875361271227125/3443783531459345396", "94266182755532992545775726171008609186/10986871169556601787", + "-1468019045636814162670978305715811638938423723806410280031/37836405995984502494576730289263822652" }, + +{ "6250188382163250356218308848100308290/74975517450841979", "10057222263694104272437942231238950849/1377150882331486572", + "7853407001895533030925726629648778749078643531548391709/103252600010686800286181264132405988" }, + +{ "-325869560300902552275820653500571757882/6390430580148850471", "94468553562411191993094256419298214695/11908765973274803007", + "-4484399064985071999330976874105690617426359030318059422519/76102142247451389303559481900024166297" }, + +{ "-93570528036598407567281714804477572547/1681213810574384291", "-244906502561054838674546679498356325029/6878656438675875801", + "-231899320744132980638168050942881155823492361410591515708/11564492202898292712047439710761442091" }, + +{ "-81411835730261219386583131450337332863/716127167248934", "305772198898084305417824619321954306670/5852119619187572757", + "-476650772889757879179369019399921041943854248979406203071/4190861845290706865359628655691038" }, + +{ "8378821874364768218652992773582270365/264620166167099506", "-235085292482743132422942426826553295351/5218853722286899445", + "105936154887632142427944491040385766054707164161382644031/1381013939193345109641609957531174170" }, + +{ "-46932041053326337601984043288899377207/83004348019257810472659105973646518650", "-172752976692389001100875729845538600392/64697064048458368935602368307247306331", + "11302882932785858045495103305619355060523322049764297548269071809310077113283/5370137620102451116225827082734739449691101289924623877117727128768254573150" }, + +{ "-5215113722152182902641295804790889582/37267147737183802417372262122851319461", "-174324915479281952095382231256728338942/198797486533978895289571841018885549001", + "1819946959828587625889363843813156766676787993042778284071188313098762447560/2469538433480866339929667414220581052912334718874062150193407525506073469487" }, + +{ "-308468863588547635528373349890793262605/277175417813474671446046438490775760091", "-88071245580784145343997181342216325733/109042592277517238289414020635536175644", + "-9225060231388102579469362745283215538990500777711808852192407359260779270917/30223926073985207174135233898799350451872811382182855106546181559011381423604" }, + +{ "-139281160373255540085888405052544101003/21590054032847718908692432707921390245", "-175128181843395150044469443628898278945/101874815793501611839718166887463701141", + "-10408215647857282226079103083273257459322595128147732742048301223816698452898/2199482777568107961766315941206227462112836158088743951492692685709912769545" }, + +{ "-13653637423911886957204229566898836211/6724361745919744069899921221745423919", "60537422461958273742622747790343370991/323722395245687564470126807800714703749", + "-4827063738484690108652046326448960810791170812913084889649499536314520788768/2176826490887613088066161490358401961235974091796973399049221882998503572331" }, + +{ "207284509647982883454717074874778610186/315575836476247924963087075944676754095", "59454580888278446469281150437143941047/3799382139920332759258392540934029749", + "-17974876032324524053425850245755672169670471578477359535347261991433397414151/1198993196898275844180025803639723883733761367273976879884312817813487572155" }, + +{ "-149255714031984711085009662216310611563/61209488724728410476016289765233999883959861482512968048939594260689484910535", "-206353007879160639705730135450663155/12341134377195982958424940281067948493740598784362073339140017508008773524522", + "-1829354061323966095884091779117676852909282652562065419187935424186237303685407507859167669375269438805585201409961/755394525511335693198081866608161950899365908489933659716533239785460293292606918153507868614180865950008697266433342863460741791684603303270127798639270" }, + +{ "286228990947356503137685907205210886138/64525193112922470913382853022276019736227442678252533126077234112153953877503", "-93778927468512815169462456699065596479/70019706577332037325570327903202382111804035215024271930215402736305222068556", + "26092773364888269343302672267572690894453186378630697330693315371426642609003667116358459590920104883240139740188665/4518035088612517412858008269349176355736855744033363257986123715832709510554983209440815107866748014413528943649032845277041680450752670951433682692095668" }, + +{ "128067958966292694713545212085241612749/50804897676960765097908813878456128842417954009101908722816951877006748778869", "-331437715897535092432788513322484606485/102911257177761006574263802557003927106564530572416215828322919550454967864323", + "30018293903870953799879886574342637699455128356488843398998059810000258259055116602688738404467489640369684487419392/5228395890723542025866546462435908982096651119675992137235094920338650164475761939608730060759309002063498665792819192135030537577109853650729817121390687" }, + +{ "27065789167947870065829490227927612633/10795458608984562931374526676297845621730864739104955678079256994070639461197", "53314096352440087811254806167289750292/44807028208492548064750449353871285104149154384082409595945081934090139448067", + "637187458285170434834128234123875152637450428605039275620795715002449318075555518355578432548587274399560043210887/483712418416385035748598509413117409273155809870339120248356475239836262578288026980177669113025449532258001487616187498682131415946755647640047843156199" }, + +{ "275528434092876314751862670579225752027/23290954563951481764306221308726902093226107549717031306984541394996363441752", "118398743375843543978994815511147957868/26050691402435592629863948804505350954161759382372519491414484055670238339031", + "4420086456754111377514058698455330162869575963826459083894390154200727636413353382047981846196341965799691593361101/606745469813648893293125236863835131523556569847025597910312571817347251611730291043895952533706547565767925058454286630395458711598751591845070996622312" }, + +{ "-263828172858355421790882308711676546531/27836884730007976814146538035133148053942251062564400015534567388490010158584", "31580638196736633522674344981675107601/26210154715367115936541726366619494863883445533448748701891278370021519416412", + "-1948520953518189888695889830515156795224640917019574042614412953331052369986548949517168001067643449389746489215939/182402263891837359872743630675214135004512597266032306942151126033873543370078488920825920736994254287019873146147276876145783659805845233146169813070152" }, + +{ "43029409555492054023102681165249027816896930295612442385573977041111849786681/17478431621804970398", "-63831159286570708329826084149841946467426290005331979697932225104261019322894/15909114936773208135", + "1800228375210677909820927489860838061135888931548234366640994061734196466170531105718785437541747/278066377585826623354880511023167787730" }, + +{ "-34677827126365037739221949705076349308552841821108642369491195428278121711851/12321935233094032355", "2466652720703038662112375481129216761044838204088317060529010755963314905661/458077759838279587", + "-46279076433142446690218423399092373290016631287423134630356063713373023144989129659854095947192/5644404488448083755690706619714037385" }, + +{ "75657421640076548917316021979547903196453821552146142751737530624725671569062/5416811919979369403", "-51031635143911513328361770575139950616395278082588474953679149885798666896870/16274277637120569843", + "1507698654622877634185545368063085304919907004898369478770589865697455127479301592176158803465876/88154701093808389139357381843158713729" }, + +{ "-86696779369804422745383183615836359604633179506005810847902134850836986706763/15354752711854066426", "83875579121692496325618937810567731584819474189441279434601944065565889174333/1890321146489013312", + "-725886765676185953186290796464189476910148783977596698524963064505627422317719186476684911836457/14512706875163632554860591439823131456" }, + +{ "-2824584270835350806110810310308644313069326027498380007733023821989145840779/3128200028313826545", "-16485532380752962986834975164722153533427821569516340079793116204530103476885/4044901389917631001", + "40144878017198534388242075435853869853984060096218401720566307902396394251666454424383286522546/12653260642466969643085415999628721545" }, + +{ "-71140717297594692514165816539390347954764512441693085945645019026357644035048/15130773661553937219", "106518314860779634188990156539381479314908411240039365434170935270962911954978/11202282371121185733", + "-267626990691150539404999353980899804835901788880218020004516046839225745741587662342920970677374/18833244338916713919008552672213388503" }, + +{ "-31372444086039981530710911528326367048894875160807395940269724829549418985367/149682691887362386596593782520991059630", "13980025800771566396092717430902170466939197897483207383178768135899198010674/143215924045734814208985239450703841431", + "-6585601463869631351127457963734548845246885851328680299125624347680443020577881573937479731612385878788264587830797/21436945032301618223045694723696447349670080755369221855700055538448185530530" }, + +{ "60002561005149795132492915799111287923312170708430066011808292212167201814322/16346766380600148228286881361520329811", "104734497917913613491539581495799848702023341599268915776996571583385896191203/61937476024742321910315674059586179787", + "19844918952732846654680216616282727016967753441473733514766184661191061075852141231786969917096326062063227788681/10024529215648371311559365663430434349900555024451481776473735938354274557" }, + +{ "78980655687309201443760271907411093305339297143458162112992101000746746121121/24094471248783344167514231679460830840", "10562090177736342378322146805187203837437609238688017154037816697523731420573/74961473522415640988394298626742882726", + "2833009175986364875175323375606672657538996734036576482627590142336455915129629838687125527863027857335645122892263/903078534276138789186206765245648729133926893901427360507431923032322034920" }, + +{ "96507496069338193466683209170737942070468924698476218759487496209308948365/19252547784216386872197161331387216893", "12563973560096321588715986952435909079270363887929001032891628645353358046011/79879611474172059435223762585596250921", + "-234179520035021783886726161079163865833895106001667476480293126893061678147610754451356994012799045797572757769658/1537886036891137155393554113191390737924110193971845147480358562685078008453" }, + +{ "-95307376781556674397571761484869767912211504027346871580288574968524683908606/128329921725822403056205582017133271311", "36170894925879686192917617159219095595164782822289198001474013555499918728596/240886887357120796976726436320063138705", + "-27600105449672599524131749634403660999916186956076872373762346977331203119722064380924286397976905109959929163304586/30912995399316310109755266138690547023211992922143297688759057498082990192255" }, + +{ "-22104893896795356297688360407985617971036912713007110938688208155601366216839/5790727918973991999188987227357894380", "-2339372311396919406471876113751500811577555408710269902369834593304924842262/12937689744925498650506694361349920911", + "-90813196841584888136609582546105640167792279132393576014002859436259486025871518847027719826829986116492656710923/24972880404321196721702428178050372850585634300866259560981343234830460060" }, + +{ "-3426218098660813853559652497557253942819662042768623922183022792185928242671/2077407536662385613357832628600529321326686191757127715026249042748302985178", "102639297566540827510784861997871251414598617775200449087621943894148321803293/83089038429507982364103335021257902316010144851865721965726693103637274338545", + "-497904817589969304680335736144278473886197067420059149312627956679073246109792679236301202959163792633927112737045328517845259242265445360227131779644849/172609794647490471018785535271654901168315737813115654161745630290269473799997219289162551586864155467201760250711449118429648095083028041134558889086010" }, + +{ "1543899448831604569141696144740105016328586790221799945430718394112623114412/1094690716976737526626281319975432667416762320123576900412499904933271786567", "-101835025746074730017715423582062511397387458863000475669454309217160145993/55116548932808468782187525862059393507883043749327746382569396580129398962", + "196572266866178229534134252625134989714563665559807019513454337864363053729628560611312158082929567528955985669620113192156991984486011150099776316375/60335574468539540262844259780498204139853746803235564167348945699931512713417761400790104247218084745081610815218855896912895393599203789305655343454" }, + +{ "-37581128364300495505521143552535972339959603365602244668159915869829949338997/42947503543372015019662104425995959382231280059683481488692141811517675950053", "-64888994735350842409379226446854438865448614840503930577860382883594178287934/83188698741706753136718468601650233481619465918167616089202536622553688681087", + "-339504834548876267781536981106771553482515399809961247195394672491113984585270709765073243997043174508213253440272888923497173265137136111635177948889237/3572746933977957867604303713153220827104741303667912510494658617478381525690274918494624922428110123336345510454960178899375325287131764283538305257747611" }, + +{ "-16230533405187239318665866908175768720879595131719076634847964191318368133798/22572606803697929681675696479626869642065470042484269772607381297011844085929", "-3238806615045730440879378702226410558103197865253164974472379309242480970831/7167633180423354812410246140643720752789573307606828791458541239290047771821", + "-43226201536346598702395278529841763047400215735214225929426206339139243925579733185594282160061132691154727543083543034702325848468839969037250195569159/161792165494835249202675342837643048016103040739685489755239980324180308179745586573032524649518850731442178659412287492012066453331740508600962908806709" }, + +{ "-58154703770626762920775801228739843350302933064569814497417973139312614069763/25655935043535628671780902110427599603857741303802203417196105196580175051005", "2291927744682353823611191393035210406213286149316388597509251757479544491322/2075117977066796442381930295725401140983312287419314083032058820231519915051", + "-2848879691864593463404526996418656511058536739346277043463623510210968076493148319480555434626780964688210750895957968447300033820091387019574369485421/845064952814266442598400897276554701819815257830830535600041451476645443978805142044657833921127247033533628716506571358424324423237490438402971304385" }, + +{ "16233726784138742204308718138203086218138595789383817317246449554340898453104/16370584482945481446847872945862788646563748664837147378940234530469832625057", "14431071141710676049963542765626402177344958369162454874051268130438178883381/21166786163219212747261378458659387864767326410261049063051557406799162784072", + "107370754167217929909136144689909613387440429633745577224054233373886366171618903318258855919060113440621302505589923655976636732694637334616990468681771/346512661117421566971293748815177161526095870176610277140325665174756629068111228154091043637596506814557119477231243643171068111260010676990408227692104" }, + +}; diff --git a/tests/exam_RA_mul.cc b/tests/exam_RA_mul.cc new file mode 100644 index 0000000..0beabc2 --- /dev/null +++ b/tests/exam_RA_mul.cc @@ -0,0 +1,151 @@ +#include "exam.h" +#include +#include + +static mul_test rational_mul_tests[] = { + +{ "-6520062188352981842/3213004995534018829", "-3812444292971845716/15284944374811818089", + "24857373879807849010516976362973488872/49110602632729971801355498746248797781" }, + +{ "-844583948128454879/4750740551331102615", "-1309778567130405125/4885884698278749707", + "221243590680205607733892613510570975/4642314113048197066962569716783636761" }, + +{ "-4579815856418431271/16947444571374397297", "7990245706938186906/12540719430158043191", + "-36593853985314806270746820601513137526/212533147427761354206383017714519654727" }, + +{ "-3587966953201943536/3194797554208122281", "975954052071387816/2707062718507963111", + "-3501690886675668292903668827990357376/8648517352177231144330968693325176191" }, + +{ "710265334225408429/567023629756400552", "-5578988760400430103/4131535930210536898", + "-3962562316545608552741467762441538187/2342678499616965424161446427863567696" }, + +{ "18305319006789031727/4480148641441744463", "-1641093267260986094/16028097657311023719", + "-30040735777106040963634910981471804338/71808259944297590021537032075729917897" }, + +{ "522499067029593907/142530390958606446621834761330018829110", "1567459634764499377/31663510497342378306792964160850079086", + "818996196770998943862055820464495939/4513012530308148429025282037949729145117603192483641232823845248212618993460" }, + +{ "6214041481074460220/139497414619784295310756757536261769729", "12187470171919324678/129216394212432939561557938117593031955", + "15146689039532873328968703771155061832/3605070583825050709361064709099418651298807367637359842488375232197429738039" }, + +{ "10022419596195177499/91129297586760817507648681092594591108", "239769653037576215/24086455608554015268646156321002022494", + "104481394312031409685890479072416795/95433990476618390508514520731482064738017476445225501421324446942302103624" }, + +{ "127731839927226607/59760640855511386051149338950192132591", "3679984267166095161/269870724770589242613062477043917992045", + "470051161348371979221331000573148727/16127647460431744118786930146746069875784110572380855085272434637353123238595" }, + +{ "4919926511230586366/29288587285987487013553554568227355149", "-2914615432991234299/34407808954885309804037535414452526052", + "-7169846869407694119621783007930483717/503878057947370143933800273784055481319429768630967123178484618174989420874" }, + +{ "-4322680734125283661/246950524730861178141734701180345535020", "11581515233057355754/82204027418720951285150957025638971309", + "-3575942340708251875937466941988609671/1450023407574517046920597087724458064116343346221474061477327267648859624370" }, + +{ "-5552456004563371781/36434418778024040927761226774271610950778609263056622471030041615086459120568", "233319937833204741/228703279535756717601739981368829304509550463672786894384479957768850829340", + "-1295498689806330283646616799874813721/8332671062513255913250553083541810221054209355142441164334390514659539371361850837178162594438925276666798780352514152276296209564179606228713851865120" }, + +{ "7279569964232187047/36316165899095632459738478614507512808578186173163489609755035948221062420580", "4568992288187244990/18279847281938710983382796940666233712517527808023718591530848159479207220137", + "1108676634263212048809114991909788151/22128465550033953372731954247755694375180631486898426116907313824243654714198100644737500721615620412852035450119116976232805701601749863504629937973982" }, + +{ "-8689289043809733973/34365105035540924847908154205433563929060132734873649554594240958996510665976", "281724695877043289/3383396067954681850718083474385093262190311835985400909911383280975222535225", + "-2447987313255021583629117408894957197/116270761252098802423406562021935246701911690887646043563899994409915142686943691634418411056232663942535537938126289647041118885713303684881867869004600" }, + +{ "-4176416206981759902/47077361360975682486641492558477246171356187409295624938308162261216397376441", "-10870319933050648575/51626085927005484523186190379579228801774286705829757742503501130303410401261", + "2670528255498212232918897515060496450/142965876637554026205455979922464979254073063785755559223760631646970673683621524411341782655829702451013418009338618833412062193643308417898164204593653" }, + +{ "4496049401725150702/8024116634872885909638996643719901973664008349644172107626390134736213108465", "-5231341280619167012/99267989241776204190444307671763754306088564051099822830201760217121508089279", + "-23520368834947889555464127765407042424/796537923785319116837266627763277272873506235001122453584405648384893204423914484193595265931840447141766909166026026228531619859740155558402735330646735" }, + +{ "-2488955833769033882/80573015130339486598712021266263458487997757617589137912729682647628329090307", "17723590657579960683/79078600039601362101827108583564759878924923849842119643649415446502020994810", + "-22056617181258995266120581914227430703/3185800618738432636378738398589185111057563002909241393794402306079667392482341108052833514927720630087013771419748846412352850012097731569487991234153335" }, + +{ "24410613567363183821142175154197794689/2233491913446620869", "-289777146895293391500645889398422195537/12394177861163531771", + "-7073637953514043162500219088395995153310329907185649946877180402954938102993/27682296026727883467940485833673128999" }, + +{ "15029397898618080393623393093137341347/9939158597399833599", "268484092305118852707129202725716126526/9752180454987984749", + "1345051417567645337656755504737828287428006597367109244226136136424901090174/32309489404196149853047846865649927217" }, + +{ "175291724581304230067306380062677652261/4791591464449055089", "-207911166974886786162808240992513636954/957635297799905137", + "-36445107018739410292029741836217649994267718828374576884161821761303211252994/4588597118993154438342028473487092193" }, + +{ "208446980882041538439350888438428103817/11756453246592156788", "-99855903858077543170703702663212319708/7775813092266901197", + "-1734555140205305628415286772698507060801514301420325900368570916304368260453/7617998589456250715053087609460739603" }, + +{ "-49595797981179247160347259926801311825/16426101929443877636", "104499598328969971414586784725010079457/3085074725343747115", + "-1036548193567594227670217621556353400490405002875929378150074378019016735805/10135150379689493069951723318357604028" }, + +{ "-288919818051255959565698296502103975540/9373352185361138021", "77343596824463059344208562767410464067/8355013728778983070", + "-319229970313622361785032672064391711775428287673147624981393545586243098874/1118778374191039878067165437747032921" }, + +{ "301194765217764762175383920433701358543/150076401641721289621709469985978858175", "-109319143590504335906407585568245068241/158084148208214805386290412276525928977", + "-32926353787549066990014316879429253235742017240010356390402491456481443332863/23724700119685440084214937112355810539035473428177368317381421021523605836975" }, + +{ "14575317438235510996984657523859363247/6747043355688580686998987940004831062", "-98472042392613093668204392119412188287/152397803267436514292317070561082866275", + "-1435261276663720115408306632770383012566806521695455296458086302958691687889/1028234585957093005711368462502470683211464374115746651290896689614112234050" }, + +{ "7543367187310376010646193530301789591/61115754966424662873097894247178344192", "309940239796651595482411737112678240799/200261667764086238794802895148430893795", + "2337993034909171213000031444662193658341848356694420878002930517675329723209/12239143016237439360279809707749702660797878084581096344749106125186707088640" }, + +{ "306232835922656327867425959604977465100/55646521674811091128956181530575055283", "45245255551837746690160535427248646677/3669533234425940180962041078287629087", + "13855582919684583969821610044729507626133731299765443289084519977056998472700/204196760665922729081584465192637337445710456706084552841012480810023816621" }, + +{ "-280037880297253633994139513185953058494/23798550327416056573646642830182072429", "13967268482262630670960486883264178489/7947215947745048068401387767511847243", + "-434596028812829556627014314125713048434599389957141408329542154357763726174/21014690966139335562014814134594464675233042588696546668504776333756662583" }, + +{ "87160410649223805266866345018804635271/204719779683096591635231158476535039583", "91197762560765392928084914476898132964/277206223024759381433146631560580134513", + "7948834435086720002947247338196997812861466884983039250681993725808882173244/56749596904412078223459353928850191672356004665473536520452927516595919428079" }, + +{ "272801380449749740391855824723351316848/2170368723435176720708253536680067463416474841046765138040214254204061862261", "14545537787709209389572055399030228996/8381323291479119825335849511027103148981778425333781230074116361235206363821", + "3968042787871071204066360146704950989545352280096012736206796950415592924608/18190561932825050861659739926693806725838682397154479213760300500132465705680046683155463862909993066621811136554677896021527098482779305371951555659281" }, + +{ "58980225701104541897366713189611773567/10973700523953435846969235385386214078292603476932194022615006557054104506344", "21633357583056027790037764923811848217/41236459355840549300942497778444413350482341379076368704834339005347182486274", + "1275940312921345964633100864283753667394719832288287163056787891633576680039/452516555639171997520308257003811683819837367444947027711901120987864272999978391252372420644671039873982401560595091423172287702745925783369137325922256" }, + +{ "-39569537110370574225194522625562874655/36290593978404925051095380486087641410218299612051669925683823165483928853304", "39273660356839128453616088747231247259/28875229647500294680887983884278577441525691250738380954940513956990510132534", + "-1554040560950035541902707236381071410695075315482961522429891905381129320645/1047899235170633560739863801929205639611958070150694189488499584527041043137082563721218908614201921449076002548982308540689571766482794493357171683792336" }, + +{ "8957762734053174688386697837976422606/712105675122280831038408324375785815130945929819518342973925027507219300067", "118977607972668646264715307919875588738/36563306353035936296510796886853084280648109576589600551753305930842020963283", + "355257727628119695756412145322380851760544279491883270008434507085780737076/8678979318410478400681656718586483785992423192579006235728835173903750764880944673586689792087386144715446501744012435157310426693657188196381455479987" }, + +{ "114386050140129336980347743358441052599/11994188887964574384037137314302737861703229337059619512751326848591488081229", "-50822174853799566513638003084407139228/97406657802317796912648600328217961853548397771614449630742570869667560514587", + "-5813347841057137571369557065847591420664634372223088557679866032754664253572/1168313852626327929522799656188055465298138284154709873285311568978496136227795809646907486798429717114923178357702460243511883684964123937654308495387423" }, + +{ "-22147677230189664783449572410799931501/75580058176304394102183955194485040346816524663599269056794063928343401057143", "-127672554664595215026114551202414743739/35777311684781371234035985601066874920871049301826919955489852676067316906014", + "2827650531865200718433745248471704607394596478050653604940563621773668622239/2704051298527551014378337257898371613519363350219566689647796093438747503077807722203668806231503452508016974614236112792032033672965127824348803574358002" }, + +{ "3468729773587632113679855593063165286551216344725198121609354788619580819847/7106612002452012151", "20863200733446307102600190583661606839853255577505815215312643683864543217073/5700246487811068117", + "72368805556440529088812813715602124890901251289457147618293618526488567540302416253970205832659523238561757581481150988870947074663135867252252227647831/40509440107213064064897416415172689667" }, + +{ "43306673717838918980731699770600730039727453611468399058203483818093233880231/6173575908538565981", "106634227988568775671050783423559067905086861634892257032833451008548321218936/17988169594879808463", + "1539324572884864883885215269788177741067901747630436643318399808029602335378536990210735234944615096105103848497832537965483619535769637171783464984418072/37017110149885307295697375341989232401" }, + +{ "61636028396239445662576777415312348317278054920190931147781159688109244233565/149659999183936017", "50280832809996410949441105432174396823883728565382915986396125237655209339731/3406752842984125790", + "206607389257567119017662603624829733217835095238758046754428174885007999774491792658838812826043033826701244157167565054600950156595290052398436186551401/33990308513391731439280046802638562" }, + +{ "-100579490802304807750359433955474958462342659278486016345156932756807754105945/15683759624513404963", "7314396152134987983181095955389244247502417255088677055075146925285457081540/950287995699608967", + "-735678240508074701153113537069655056596152436111651040530896921701439724727486696483134676487497031899584038731663111390949471467249259023050011663755300/14904088498613295322494450308817103221" }, + +{ "25984831699359211750216710442693374608159925357093100400945034699383345074385/10463598404993207796", "-2395913226491242076662067669730978955981403048697660449593722338244504668974/7015215522730452775", + "-6225740195664363384298636893730784883811595661227613249243163802476751022407971476247993440178871949687923603921101094083879668063131450147131783163099/7340439795432595812648347200273983390" }, + +{ "5173661857391320950903772549611256023540539838210520778403003347430938670915/2590493168574884173", "100300641976357496491877756123729102910724064566692821682523911939220592349990/15304416107565779147", + "518921605664943617990486317157527087053001312760892500249127957517476408720600460633868004681188890038115877413554399588737851074382787744833707113540850/39645985375676570588146199684023740431" }, + +{ "30299639015164203561126609159677900559022306879488518544803392527841364186955/97638167801975054493877206805944332747", "-50150465496280036231382225902610460555496341860773955714344071185921583266663/170117675960786609061777750278261277482", + "-1519541000979732808188648781832621044050652591754537200855596768903085847105531546641139177813880505696192826380113425984545675787584857974943247950981165/16609978191541300835961154615181304582159561006676548938424954151558306303054" }, + +{ "-34494394944257769716276791009665812125094062960425641316440943461722789694119/69239821080832171466311153221314488591", "-68027404272124217088707268142523090163964888591405843143848585935878552833247/257149529774225346004390673137885895872", + "2346564149995340998782934409780604815295734898030424565252099571337345550054284934036215402972664245125313098735082896555892607540059632597741979943574393/17804987432587488254198543762235568841018786223139145264591718687823557996352" }, + +{ "22330754509472350470460807673039908304726422770752644988051418230315708975569/141163736844241522445115344332946835969", "-3776092949566234532895208849184634613770861313997034923686862122594334787771/22367110097535579962848998753563258272", + "-9369222740190326741203615957382420344247102784278353165345406236082475331042528539717966581690645628370939381978953360215380653092335198860022382107411/350824982641632215769272917522017419782283768012468846380070797128085153952" }, + +{ "1376215273451682681102140384578115142238259557166158859699272578561460124263/3593386179017642636485249017714833669104405991325015697577507088650274886871", "37146275008876311604039415809582675415172661567487888072055609579242279390723/55424998453085285819414374477780690192979527887019008768378662580126754826472", + "51121271019052119686352858568900325361226598163234091421115939503875711782442415328681175322030659510284806538410228985354770913411724825992699509412149/199163423413390889071651575953261174839972499014963134990506980080139461063269751906284862132821075544766093817070661266293471833091996501160433036049112" }, + +{ "-88175289711320073148300791156190227927348022787624424521937188958291199926437/38194742314758366741668899229532351990874883495690656157862650973602784662629", "93421911195279228911508870033119580111709458306921869937709821511660370035352/66371395138592894543765954603571534463846496049156722497129962530412046587003", + "-8237504085028962150049531747535213236460729066521397582683209771842938254589363802757604921456170821878391951762499073662677974506165863935238701489400824/2535038334389561782321790943041741331416028402594806464107449488311138037598457377927652600804722340759363172755193254192462811091332303758223034251210887" }, + +{ "-88364214910455569163017945328431687038422451206033411348821431934742389780753/43010507830592044720656702803904712217809857004582018186125828892174875808576", "10405170283887792832024806983921158923908589830001636723872220129826733402834/4055629711949631304631599195955105801456753694558712994574702123032807265321", + "-459722351572673455425943766571506569631562018487574498847133029199411842205331593858852090421782204158679934054007027833206633183796877753882057444427001/87217346741895687976684378003169607737518608233754137677854312677618987931466495788077930577814677920791330694741284253568592140275298729115088619596448" }, + +}; diff --git a/tests/exam_RA_plus.cc b/tests/exam_RA_plus.cc new file mode 100644 index 0000000..db60c3c --- /dev/null +++ b/tests/exam_RA_plus.cc @@ -0,0 +1,169 @@ +#include "exam.h" +#include +#include + +static plus_test rational_plus_tests[] = { + +{ "-6069217517368004039/4076344942716985944", "-399587800008780737/578697755310708616", + "-321318766345655960630110128852941297/147435729263904928853096856396980844" }, + +{ "-41285036778370718/305793940074617155", "-1396094619926552183/15846027887642356854", + "-1081121118676718273499338028514700537/4845619302294419132297197085940230370" }, + +{ "15975644088444536091/18063939613598316583", "17501188199168431305/2979264551795273683", + "363736076920798535449296038324193823968/53817254956563877935003279344562385189" }, + +{ "10197734562406803221/17452826108659293487", "14639450560606090654/236781760961536951", + "257914422508077920978698094723491089669/4132510899763835955061848877304138137" }, + +{ "-16810360766832230069/13652857552883800956", "5011749175730438558/4169057419710079215", + "-184295743992738197672588473692806043/6324394120121667288243293659228081060" }, + +{ "2234573531734039025/1128831476977636536", "5842177084459535064/10255356071975483971", + "29511180623959738330730559435115466579/11576568741659658592450950022331964456" }, + +{ "2268894928233321367/45672733521488298991909987382109984899", "-10510750087507287356/187832098427494353069556175466145198255", + "-53883392376116199828369509984040539934420061636271022459/8578805378260910951788610598591490227836321974082207035230408675959411151245" }, + +{ "14273433611429514043/7774518083776389556784045601066955324", "17247074371340283485/225579726714102822702316919752160926694", + "1676942472465190408518249346164012571239098147062478293991/876886832336064155131767120243155911448808491410701588797601053820468509428" }, + +{ "-384768590020206817/26284423885474502132625533495652664626", "-913687410374243983/254477371735734658619949996700223764026", + "-10160887225658731404416073535892287983824191154410167550/557399258996959835387173465565070652935481894323496556880024318994528462023" }, + +{ "-4465222504572200650/89674568206322981678158378582739708537", "4148550863841320780/74302497820894496090312266744880513261", + "2118016946376507498169590394563632549990739165791772590/350686547828419379316750498534703170285368675911953477374458878558215968903" }, + +{ "-4466938407638238142/281859125741189685767904931589784285893", "7302241525893379697/204618108204962312932373858463395271264", + "1144186926000295881841982161759159994442430111060328362933/57673481089466829503954266461746705742702466399988738560842837126631263478752" }, + +{ "6692616266348342275/280491911593106290120490189988812804382", "5414100524539959087/183579771905991028181574615911067652873", + "2747240373316006570071525025488180559154305534334705425309/51492641151737853299832848099101317109893853469394209716061486746077629289486" }, + +{ "-2794289802081124319/15768464977850217600859580216291365931410230647587457388598921425875331529149", "10869776169503285673/33805119742344157512165738805682358903614971418053290198565741206390317449856", + "76938383491719886409504555688515759257937029058461512747558964579607347503639994773101488934213/533054846729186819415263583890627325668798847177803707144003483502948153457972377767011992167761176556555806720273883868208938866192358148729990609852544" }, + +{ "-253222140119290489/2123024034843473393742534167007121513293496410591072104903085284304117612082", "17957334013642389787/32058972871090153103034645121513493401113378486125580864856088310966601405847", + "30005809992231287609744177955201962181880644831204431411802631067134766877061419104162728517351/68061969937719269465960475690278941280799593161143759512261685488134507341176789799765185182008442410081522124548392827986923668912612728349293792643454" }, + +{ "-13318881947309618/3105936147298438543619802738126617974207009907186580731552500517452462642139", "1850968757748704519/36469179946212878965111748233319050931475015876401494718861814560453153824935", + "5263262069792987469108717688485565287648879759118200779949761992573778798556738644541735401311/113270944257273905484832818286307416845956086746130199501242465128236430928807948126409718436237517505516279133169796919230385184900609912160483959935965" }, + +{ "-9937822914683494298/36414156259035675966580098631253549474580108307284844243190992829476777586283", "-13712605099585970325/17758145954890657915358548152198427387923366136638180213650029984340849686198", + "-675810254607579372158951115566887998278519717754376916387787672973408477396668549189167387350979/646647901672150721610792561233068038707362067627156669418022102308446036384411330678972562863413004325878365438890328206637571985169324874284800419222034" }, + +{ "2479135971595944301/28169711053558469409458629766960029324030958129245230797895768033968717159836", "3427244662960653095/28446538857424788738244844756675951434179713170118835630969510829753715142438", + "83533664807147783700314944003289704497366290621039272787320536148072960487262393639109696219129/400665390043739792096386856839000624247597803909916773326187593475005945995926511155915226239317839405221783416485999405286913042389632370302962776360084" }, + +{ "14865500635281371370/56222262470894935247131881777606182311286871927285650835673424014252462156319", "6436092572090050725/19282524131572095520593158313261757267758159099923763177708581262473988426947", + "648496060602737474174747620183913927791943082591316359990137585798909535115053578637078811588665/1084107132826611778585714784136700465449309125114745313342842325649687943726086785657821763235618936882528385000712567133180567926723616940173290425928093" }, + +{ "340196811925805824067049620503247332111/14422464039094716975", "51285507111580975533385007190438537498/3230944134273302873", + "1838820276033673324738967436225477772648372110186756083453/46598175588880723338390245118389369175" }, + +{ "-210449319160504160992731982827917332322/5436857856220342451", "251628249079137248539965770847855056283/4323109210037952829", + "458271632943884346915405609513071881239303671882386130695/23504130271893362375786510953364243879" }, + +{ "-40984360445255688839942109197081457275/6593417935076565019", "-138094174027187773198981391229349265879/7135512300754720691", + "-1202957011856131413678873259651070808566709454882536663726/47047414779755620074837011989046108129" }, + +{ "-289704472880230079383856507128133962457/10452740760651010288", "-55251460678415911958671096669490155237/10333740726609314202", + "-1785630052601050832889834016432677758176770083879794496285/54007956451514283340719766211063255088" }, + +{ "276702099951674677215621541062877777467/3899918017008359516", "42623843937285717338660228144403811741/1973785812353331893", + "712380176058162142132059442064597996057720566915757732387/7697602851312240113570356856612843788" }, + +{ "-323480614013303716597188084301661616596/12957985934572321773", "-72966206939397711493108854138997499334/4539020357040680881", + "-2413780175334213399707013296172687953960842714316410700258/58816561943270580900205343368941122013" }, + +{ "65443777543319569578713907336699651721/218804857459609839540825438673960136766", "-61986861924091374470669233802827103921/65997977315012279293170493460332070399", + "-9243869541956614722377007489838492339200370508580665293676272508698701352807/14440678019033825487758061900150103876633207457375858942267120523885980189634" }, + +{ "75417845823236070411341994633288547531/70553457686181702397810927701121800017", "-7132208259849175775323757110664708879/24379326462014713478002790304943339422", + "1335434330716260509518880689691257567128541829706203586134358870209350816139/1720045777955364955754847231620711706115121721983605654691934662747636370174" }, + +{ "-144692585186931942602350348772472248638/135233395864627580439431775527364081053", "282512666765911374279543408363363928190/317835040256607665191397469890906044457", + "-7783226336195038987381961251409043080655184208289882004756343793157154115496/42981911818671667582796085276418080952868666330715445603855323471628969373221" }, + +{ "44888992584766727877549626240272070725/30583318432547259097085073976959329092", "8004917623696885952432014881247978821/22005016116109025986417835664774768346", + "616299974987760892931461886440810919939264155149950328291076750435394215691/336493207496148335911511951044490614757807556827643881435283379298939260916" }, + +{ "78378756441281199312006031491361997668/175125578595003447448566412156266355477", "41128705932035853424044828385766740319/216359823601433445464965619660717081261", + "24160702340946845080381231961736762955784254747832931999121777482667650876511/37890139292913914697800186893609983979783140570423836226844401085057321416497" }, + +{ "-36669293296367265584135816683983780855/7341750629088488427994322429098120058", "-110335983484012479290765295565662258281/5944410911181873015545360879141666465", + "-1028036623331099574157832708037007047972965676333418398303213384036005227873/43642382546729990922161061763293407461832155878510163500678954788762454970" }, + +{ "228535455883892721240720366651075744967/13353170075841095813026701300679754576855418298534901819672803635370738730013", "50622643250826426975012800479360461693/18462345430382979738234695697296360785230118465695284267226773073149552698303", + "4895273294635392498665165879164922265508724130843670837390305811645771221742112327485665544066552056189958877583010/246530838530831602270074647792752210668736478466245992891169449973883874207653264921203783108295835419855394180777469634862446033810927048792871560267939" }, + +{ "11355068601761731966774720678777239425/4604724775053993730579400400679579947095967462408565975449642189823843820753", "140083339434585694465706029861026468774/44667214322013486680993684507177513903616004462434123967566781106229226297333", + "1152244506542792151980649054527153167035843960949499862764543674633978109831264344257976000890169981044543787620347/205680228421222079539939271800361418862113882206694593495620042859527547538342323521609420336002641308832164587573546802806916292021672743366881933951749" }, + +{ "-1347509007210283053816302848714698886/1127513773036247565111791991337919355855664936242166138889250311777351432819", "-29464928273311615445392112247506626497/61933028109313748081628643142485450090725737246358993405254280723087421657760", + "-116677425670791909053501267317366054796703074907755330120413752187834449333299886015456661052906469074533366060403/69830342199092322009251417145364324484174202256910311362396720371574344280505889954115533896831727771442604285956749924105078563356474162416148250025440" }, + +{ "-324250487660721070279458563122233299722/81069650926979269606211148691445887485067008319429991878657612702576019034861", "221744296343315457943731256980089803078/69422237643162665956763790134527973903052044485041686255401689654420090859107", + "-1511153903564243978242173323335554031611949546418082039382510246845821774680210236992700372319944685567533765722032/1876012190766999122356500320654631447623282613780323887424324139799202291067983209550065997185860196433399782230215269625922714982832188312141580824109709" }, + +{ "-5518324152042099343909980322067306333/114786626838714403445081775763480415805466836213320421844559660900880511042496", "-34415425451618992284220085078832944671/96012285963709194218263616278916829663708037691620330613749177799086889040577", + "-121088040955051148243092870850103339772063863319219725752028251933576579890093496821887384992074112246777968211161/297862876779681729593084954525306275464788137269287692384941959703420459939692410434239827100068259769782676124741025632728203586961467995819025176090816" }, + +{ "-14763921690861243371082340598041267817/5580497386043551028888310256097864185640794395615400088682607872958152738111", "-37917865546640067592937379176813765341/6460563866107795917092814416816176677900242086501650458839130903088333290440", + "-306983808565398982164654624310995401934900925070311336095043743767915008644459192438083753301097540174379867380331/36053159767181973313125557585868206969047484351694148822117591172786449966899079869470557965303954072842600790897257698854023751399649072014440219958840" }, + +{ "-50167218239107621378232529938205077788547946059832391744348095230748591585676/15685777859540025727", "2959973815535345735348053015389999235839609978295604181643547897863515739931/7556072538495923601", + "-332637648328710384664787658442281566361265475773778265650094684540358159241317316408573560734439/118522875329417757148187346888166482927" }, + +{ "36275100136090483878026478935942224245036692059657264537598788566553406654319/7192442039871568876", "31833552596558882106090352174644817045294359487590746360517241517440556146007/5115621724114081523", + "6795584791386081942310910570767193224876510928834120433155946649367201608618436115134135392229/603177258173744207443043238127434068" }, + +{ "1518304705177739493483387141342904186483658277690975456045607777812450680478/1837349761252804045", "-98159070764971437450169149833809835519268242923913777966502463698396945141091/17238232824535200528", + "-154179655228376218743158291724235398278770272999447263973992852061897564252670941977524115620711/31672662964580000612902147746364535760" }, + +{ "-16820231344048323866426670709751443650129113909724546927974450301780935205864/4879137683452153951", "41987219452495799378686134495924115238909423831017150785452046648616005475639/10470103987572807938", + "28751853386830083847297108941057082854166610198448421498169760256533906032780671559334244751257/51085078915429149801779227663330863038" }, + +{ "106981694162678522688926793970551228214793665448093395251834862896418045995969/12359470989873920972", "57736849967187961211538031441400807467468650239660040144967046985609433512403/9148121311784151716", + "211534804819567028232303054650327703050869189253958355919997046592895748577556985792570078031065/14133242495605447754080611005730273494" }, + +{ "32477400086615533920132766925666506741908300936974348739732763951610256880146/9045135183308696243", "-27444990730472195954051975667481893116650518055101159075033425831129583042846/14815776448343565085", + "232934248044934592851252865496377968609159820017147884670610366058217203617961573611006127074832/134010700820948737148715427669965475655" }, + +{ "-110053921687226074580746319073262192216481755737797790655164396095655530752161/255625377233605953547425802301922658850", "104095037267817888539158192425982072195078148060302393917025130946535913363779/52156238014583575190277280296975732513", + "20869334635774913818120011435677143948904421430726712952150525645851498022294865158343391008006649321440592131083557/13332458017563665620865770931104425383051282278510599570476131200251352190050" }, + +{ "-29732769078100192507326444863945498799317005912797369958801703828462203585495/153426302667449722633466432797809987061", "36094569840376017510791155197897623093337784636438580042046806320700826250193/73286165979315961333009750429763545174", + "3358855747298609357265422062476767573626163217619249414656940907348235709105513077913806378841119674678021275101643/11244025482879487592663298816607141776071841230792806495601092332558428993614" }, + +{ "-5942892427460131788264792587455286675871284855854073854440582948253436001319/42136930106315714728428443448730580823", "4013357443728612356640061171485791666303136232331145404661874650095235381569/4039594279673425548586623641599574814", + "48367895947790658831309709091377784501687363167039737892874371817395083020674648576881857510385191335175551957207/56738700606823969419119152217721454504573192499839513549171731025354063974" }, + +{ "83833896550100013648317056712064289497247852876055488793078639582729685477353/188580876675619574786621140720273228537", "-94310653397371924313725082402708514144086936359594289802762093989853507835016/223423274286761439988276492107364036191", + "945257965914081840217765265999453398105151083284254483307155736205796420255026737575918161700355729594975143830831/42133356934734885127066999419230498520039134905254787577957770920054881982567" }, + +{ "-14753992026457621496269953958381833108089826525439816493815533773338622353285/187171041855711408638339193132645929319", "41340837577662628944845446369855468662228665858415210386857356535970453143469/322471558852595372991189266479896691326", + "993354944176102401496932276511264091214577507066786487301109889019709943488537161608732610457423116833164991120567/20119112546425211128699888199278894685207186285215928241217590790016852128998" }, + +{ "1370528773439579327226257222995383030603284075640526658282329726447335048230/305600505683287165495713194488435114383", "65450762047588146235054351616480175308174618406941901794570541085963681607527/78934496562987400429145916504112602768", + "2234440886428442112499564751364146150136438855986167755259621093816030535881959724370423862435538502079424185584609/2680269118389404699570998335430047660909241475691839354273569734988880268016" }, + +{ "-76890617375308981455205142622328108690129081798840077873315966300000409208129/15716637731576156581128288257209679492686622162926707938907282962815471734862", "38716252217351070567267262306332875768795464072349655597599997486613800623507/8966639693620677733207403249675415446338239705879120765911896990394928596139", + "-80961151400006413290662155450270992168701818633203071886556882897757813544592915596861717853520674107309124394292702460320442121704840951425284048212897/140925427734207212133604717335369986754855062343668899363006574618520848268718851310007161609443093589067206438198588881828988648068282656538084484897818" }, + +{ "-43290760758277846058307167265569849910514905939554272559141355223092464986939/39390771697068809730875092892395235497943839933482798653607450783947201796777", "-34021960935937170163894986285771504067448629886312440795733904794894095253649/106500928228745564800818258673435811176493306775154643113582742982704678574998", + "-5950657500399238361998292872481533631424138885403498309639150240712482075115081624153513501886127772738596607451116548616099047843190357858736503567640395/4195153749384427435979718872073512266029328962522899010907363614544821318917440413166534226890289043064894115954085809567292470182917919104836361549181446" }, + +{ "17906146982204022925114071077515882010955693727109005464426577098738402001871/11978213712662686419384559301746021856683603106261241838035626618416021524231", "37108371752538653389309509075248119316034595087990649061240232817571629131708/23044877611981158676785639370406786635050056158699399001947422631523989139615", + "857136973087880657664203854652754375000000796400911171478039451763440064550649429609696307332611304395324153178602635490321877797571177424460384122636213/276036469018466057777760709173569478463866562650149880633721199971933767458324034017734890892482223472007882939609440193626728031771767304374122564511065" }, + +{ "-77062185592993847534024832256462395143306675613123510837298699277378172890089/108133793614758275822883834459865239455798743725021300772336023406871185253111", "11169356025540464491224577661206910726665825152149521753528516637690366838655/6369000033300801574913390611244042297918207179453133439308688067382050608197", + "716975776667538986425481530620118513423964367153518065425241139444161780269039780459555836804116752462325735011822817367819625929553250251515977390346172/688704135133337463423649074673019029541747166391680122270752018123634233590688096940261480888455237095078029621363428114402137147558304641222314936350867" }, + +{ "13583698920327742567560325715281067532806062839142769830536738488850089822247/37364394142255392010559408553278838878570049727027927213977555360874308098434", "89809462356450792524214360688853318641058652796345720882094866396911421360072/67457610947238032712889230619376608100793287037427539672885124981055281513463", + "4272000026182362299819817378001862956001381379478285995446709640464951377212652125169846305230835604666564953883168949950485767679005929254184987140738609/2520512763327523955464432226120154092742373168521113224665257966793820057379494860454732800329019773731110452438496395974166220481124541266348389100216942" }, + +{ "-56124163112538495128545947597589743957824668875494126834084658670528264380488/4752969512023182700122983723156599300062332404522277372984645779569746369511", "-24794747728228571193100294011820993825205231022194400752319729320185378063197/98168688073468429337427023004226732413974455700654808087001957859427678524065", + "-5627484141989830997868845457242226973925524393512774885292323552602180052845805156311097870316601631410500655735815037997645271136502511615781690896430387/466592781448509275992390948177487068548424631274164031114910250651063315574511979617153568070687706304645818907382693929886654490427484894987856595782215" }, + +}; diff --git a/tests/exam_SF.cc b/tests/exam_SF.cc new file mode 100644 index 0000000..69770e9 --- /dev/null +++ b/tests/exam_SF.cc @@ -0,0 +1,7 @@ +#include "exam_SF_plus.cc" +#include "exam_SF_minus.cc" +#include "exam_SF_mul.cc" +#include "exam_SF_div.cc" +#include "exam_SF_floor.cc" + +DO_TESTS(sfloat,cl_SF,cl_SF) diff --git a/tests/exam_SF_div.cc b/tests/exam_SF_div.cc new file mode 100644 index 0000000..49caa43 --- /dev/null +++ b/tests/exam_SF_div.cc @@ -0,0 +1,421 @@ +#include "exam.h" +#include +#include + +static div_test sfloat_div_tests[] = { + +{ "0.4319s0", "0.279747s0", + "1.5439s0" }, + +{ "0.58111s0", "0.474937s0", + "1.22354s0" }, + +{ "0.95817s0", "-0.209396s0", + "-4.57587s0" }, + +{ "-0.30497s0", "-0.182861s0", + "1.66777s0" }, + +{ "-0.69316s0", "-0.32908s0", + "2.10635s0" }, + +{ "-0.87152s0", "0.518326s0", + "-1.68141s0" }, + +{ "-0.81208s0", "3.27736s9", + "-2.47784s-10" }, + +{ "0.88465s0", "2.15492s9", + "4.10527s-10" }, + +{ "-0.96446s0", "8.0971s9", + "-1.19112s-10" }, + +{ "-0.65258s0", "-3.98033s9", + "1.6395s-10" }, + +{ "0.663826s0", "-7.88726s8", + "-8.41645s-10" }, + +{ "-0.31185s0", "4.1015s9", + "-7.6033s-11" }, + +{ "-0.89607s0", "-3.887s-14", + "2.3053s13" }, + +{ "-0.670135s0", "-5.027s-14", + "1.33306s13" }, + +{ "0.94663s0", "-6.153s-14", + "-1.5385s13" }, + +{ "-0.76772s0", "4.033s-14", + "-1.90358s13" }, + +{ "-0.446358s0", "-1.9017s-13", + "2.34713s12" }, + +{ "-0.157814s0", "-2.0401s-13", + "7.73555s11" }, + +{ "0.636185s0", "-3.78516s19", + "-1.68073s-20" }, + +{ "-0.90556s0", "7.7192s19", + "-1.17314s-20" }, + +{ "0.85053s0", "8.3134s19", + "1.02309s-20" }, + +{ "-0.3058s0", "3.00674s19", + "-1.01705s-20" }, + +{ "0.219429s0", "-8.1184s19", + "-2.70286s-21" }, + +{ "0.319603s0", "-2.0739s19", + "-1.54106s-20" }, + +{ "0.58943s0", "-5.280s-24", + "-1.11635s23" }, + +{ "0.72955s0", "7.852s-24", + "9.2914s22" }, + +{ "-0.66327s0", "-3.124s-24", + "2.12315s23" }, + +{ "-0.0137558s0", "-7.918s-24", + "1.73729s21" }, + +{ "0.35823s0", "5.467s-24", + "6.55263s22" }, + +{ "0.93861s0", "9.968s-24", + "9.4163s22" }, + +{ "3.83346s9", "0.99782s0", + "3.84185s9" }, + +{ "8.7033s9", "-0.81822s0", + "-1.06369s10" }, + +{ "3.52326s8", "-0.79994s0", + "-4.4044s8" }, + +{ "8.0525s9", "-0.91803s0", + "-8.7715s9" }, + +{ "-2.12784s9", "-0.761246s0", + "2.7952s9" }, + +{ "1.18805s9", "-0.903534s0", + "-1.3149s9" }, + +{ "-6.50556s9", "-5.4642s9", + "1.19058s0" }, + +{ "3.3333s8", "1.8341s8", + "1.81738s0" }, + +{ "3.70934s9", "9.1957s8", + "4.03375s0" }, + +{ "-8.0459s9", "4.5511s9", + "-1.76791s0" }, + +{ "3.54982s9", "4.6631s8", + "7.6126s0" }, + +{ "-6.27016s9", "-3.42858s9", + "1.8288s0" }, + +{ "-4.3213s9", "7.223s-15", + "-5.98274s23" }, + +{ "-2.57753s9", "-2.533s-15", + "1.01759s24" }, + +{ "3.8858s9", "-4.505s-14", + "-8.6256s22" }, + +{ "3.5946s9", "-5.067s-14", + "-7.0941s22" }, + +{ "2.94434s9", "8.333s-14", + "3.53333s22" }, + +{ "5.6178s9", "-8.241s-14", + "-6.81694s22" }, + +{ "4.9591s8", "3.9972s19", + "1.24064s-11" }, + +{ "2.4166s9", "-9.2141s19", + "-2.62272s-11" }, + +{ "-1.484s9", "2.0281s19", + "-7.3172s-11" }, + +{ "2.2339s8", "1.96374s19", + "1.13758s-11" }, + +{ "-6.6306s9", "-2.414s19", + "2.7467s-10" }, + +{ "9.9114s9", "9.6187s19", + "1.03043s-10" }, + +{ "4.4579s9", "5.343s-24", + "8.3434s32" }, + +{ "-6.35994s9", "-6.301s-24", + "1.00936s33" }, + +{ "5.49677s9", "-1.9306s-25", + "-2.84717s34" }, + +{ "-5.007s9", "3.692s-24", + "-1.35617s33" }, + +{ "8.6837s9", "-1.6358s-23", + "-5.3085s32" }, + +{ "5.5898s9", "-5.435s-24", + "-1.02849s33" }, + +{ "-5.042s-14", "0.79081s0", + "-6.3758s-14" }, + +{ "-6.231s-14", "0.96946s0", + "-6.4273s-14" }, + +{ "6.016s-14", "0.418983s0", + "1.43587s-13" }, + +{ "-1.1682s-13", "0.70944s0", + "-1.64663s-13" }, + +{ "-1.7485s-13", "0.83207s0", + "-2.1014s-13" }, + +{ "7.831s-15", "-0.083374s0", + "-9.3926s-14" }, + +{ "3.947s-14", "9.2342s9", + "4.2744s-24" }, + +{ "-1.1537s-13", "-6.44075s9", + "1.79124s-23" }, + +{ "6.751s-14", "5.8395s8", + "1.1561s-22" }, + +{ "-5.026s-14", "7.9677s9", + "-6.308s-24" }, + +{ "-1.0105s-13", "-1.71082s9", + "5.9066s-23" }, + +{ "-4.996s-14", "9.426s9", + "-5.30024s-24" }, + +{ "-6.837s-14", "-3.573s-14", + "1.91351s0" }, + +{ "-7.736s-14", "-4.898s-14", + "1.57942s0" }, + +{ "3.777s-14", "8.025s-14", + "0.470657s0" }, + +{ "-6.239s-14", "8.518s-15", + "-7.32446s0" }, + +{ "-7.548s-15", "-4.573s-14", + "0.165056s0" }, + +{ "1.6293s-14", "4.712s-14", + "0.345776s0" }, + +{ "-4.47s-14", "2.73658s19", + "-1.63342s-33" }, + +{ "1.0583s-13", "2.52534s19", + "4.19073s-33" }, + +{ "4.351s-15", "2.70326s19", + "1.60955s-34" }, + +{ "3.699s-14", "-6.00707s19", + "-6.1577s-34" }, + +{ "6.358s-14", "5.18274s19", + "1.22677s-33" }, + +{ "-2.971s-14", "6.153s19", + "-4.8286s-34" }, + +{ "-4.968s-14", "7.699s-24", + "-6.4528s9" }, + +{ "-3.654s-14", "8.434s-24", + "-4.3325s9" }, + +{ "-9.276s-14", "-7.079s-24", + "1.31035s10" }, + +{ "-4.556s-14", "1.3900s-23", + "-3.27772s9" }, + +{ "3.832s-14", "1.55715s-22", + "2.4609s8" }, + +{ "1.4186s-13", "1.64482s-21", + "8.6246s7" }, + +{ "-7.0974s19", "-0.705536s0", + "1.00596s20" }, + +{ "-7.687s19", "-0.241531s0", + "3.1826s20" }, + +{ "3.37013s19", "-0.425987s0", + "-7.9114s19" }, + +{ "6.56473s19", "-0.60696s0", + "-1.08158s20" }, + +{ "4.1598s19", "0.60135s0", + "6.9175s19" }, + +{ "8.8312s19", "0.93547s0", + "9.4404s19" }, + +{ "2.81357s19", "-2.62832s9", + "-1.07048s10" }, + +{ "5.9243s19", "-4.5189s8", + "-1.311s11" }, + +{ "-8.3887s19", "9.5761s9", + "-8.7601s9" }, + +{ "7.7606s19", "-8.5369s9", + "-9.0906s9" }, + +{ "-7.9868s19", "5.0173s9", + "-1.59186s10" }, + +{ "7.4128s19", "-6.7781s9", + "-1.09364s10" }, + +{ "1.27472s19", "1.1699s-13", + "1.0896s32" }, + +{ "2.97578s19", "4.448s-14", + "6.6901s32" }, + +{ "7.19416s19", "1.3834s-13", + "5.20034s32" }, + +{ "6.61843s19", "-4.268s-14", + "-1.55071s33" }, + +{ "2.8579s19", "4.364s-14", + "6.5488s32" }, + +{ "8.2451s18", "-6.532s-14", + "-1.26227s32" }, + +{ "4.63364s19", "9.4305s19", + "0.491344s0" }, + +{ "-1.81999s19", "1.05424s19", + "-1.72636s0" }, + +{ "-1.41579s19", "-4.03517s19", + "0.350864s0" }, + +{ "-1.88523s18", "-3.3165s18", + "0.568436s0" }, + +{ "8.4152s17", "-7.3293s19", + "-0.0114815s0" }, + +{ "-8.674s19", "-3.63595s19", + "2.38562s0" }, + +{ "-1.64643s-22", "0.78035s0", + "-2.10986s-22" }, + +{ "-7.455s-24", "-0.63174s0", + "1.18009s-23" }, + +{ "-3.259s-24", "-0.89363s0", + "3.64694s-24" }, + +{ "1.5803s-23", "-0.11338s0", + "-1.39382s-22" }, + +{ "-3.534s-24", "0.407562s0", + "-8.6711s-24" }, + +{ "-7.221s-24", "0.90274s0", + "-7.999s-24" }, + +{ "1.0479s-23", "5.66256s8", + "1.85059s-32" }, + +{ "1.62856s-21", "-1.9551s9", + "-8.3298s-31" }, + +{ "-8.102s-24", "9.7896s9", + "-8.2761s-34" }, + +{ "9.693s-24", "-8.777s9", + "-1.10437s-33" }, + +{ "8.643s-24", "-1.25557s9", + "-6.8837s-33" }, + +{ "3.224s-24", "9.8161s9", + "3.2844s-34" }, + +{ "1.06582s-21", "-1.0408s-13", + "-1.02405s-8" }, + +{ "1.6738s-23", "9.851s-14", + "1.69914s-10" }, + +{ "-1.1514s-23", "-6.509s-14", + "1.76893s-10" }, + +{ "9.171s-24", "9.292s-14", + "9.8698s-11" }, + +{ "1.8589s-23", "-4.213s-14", + "-4.4123s-10" }, + +{ "1.2837s-23", "1.1034s-13", + "1.16341s-10" }, + +{ "3.671s-24", "1.0091s-23", + "0.363792s0" }, + +{ "-3.373s-24", "-1.7017s-23", + "0.198214s0" }, + +{ "-2.0157s-23", "1.0021s-23", + "-2.01147s0" }, + +{ "8.041s-24", "-1.3974s-23", + "-0.575424s0" }, + +{ "-5.391s-24", "1.1762s-23", + "-0.458344s0" }, + +{ "1.7735s-23", "-3.313s-24", + "-5.3531s0" }, + +}; diff --git a/tests/exam_SF_floor.cc b/tests/exam_SF_floor.cc new file mode 100644 index 0000000..d31ec96 --- /dev/null +++ b/tests/exam_SF_floor.cc @@ -0,0 +1,420 @@ +#include "exam.h" +#include +#include +#include +#include + +static floor_test sfloat_floor_tests[] = { + +{ "-0.403114s0", "0.64293s0", + "-1", "0.239813s0" }, + +{ "-0.538574s0", "0.74157s0", + "-1", "0.202993s0" }, + +{ "0.59919s0", "-0.433258s0", + "-2", "-0.26733s0" }, + +{ "-0.62148s0", "-0.185875s0", + "3", "-0.063861s0" }, + +{ "0.298317s0", "-0.79534s0", + "-1", "-0.49703s0" }, + +{ "0.84822s0", "9.519s9", + "0", "0.84822s0" }, + +{ "0.185059s0", "-4.4452s9", + "-1", "-4.4452s9" }, + +{ "-0.442635s0", "-4.64486s9", + "0", "-0.442635s0" }, + +{ "0.78401s0", "-8.4401s9", + "-1", "-8.4401s9" }, + +{ "0.300156s0", "-4.4083s9", + "-1", "-4.4083s9" }, + +{ "0.67763s0", "2.54755s9", + "0", "0.67763s0" }, + +{ "-0.189995s0", "-1.9236s-13", + "987708260352", "0.0s0" }, + +{ "0.442696s0", "-4.184s-15", + "-105806519336960", "0.0s0" }, + +{ "0.175987s0", "-5.055s-15", + "-34814468030464", "0.0s0" }, + +{ "0.30565s0", "-4.296s-14", + "-7114747543552", "0.0s0" }, + +{ "0.256264s0", "4.541s-14", + "5643318591488", "0.0s0" }, + +{ "-0.51656s0", "4.057s-14", + "-12732698984448", "0.0s0" }, + +{ "-0.221672s0", "-5.9783s19", + "0", "-0.221672s0" }, + +{ "-0.441925s0", "-8.1227s19", + "0", "-0.441925s0" }, + +{ "0.73287s0", "-3.99683s19", + "-1", "-3.99683s19" }, + +{ "-0.376198s0", "9.1146s19", + "-1", "9.1146s19" }, + +{ "0.61628s0", "-5.83824s19", + "-1", "-5.83824s19" }, + +{ "-0.072037s0", "4.40705s19", + "-1", "4.40705s19" }, + +{ "0.378708s0", "3.258s-24", + "116238699015966918967296", "0.0s0" }, + +{ "0.98937s0", "-7.698s-24", + "-128524230569057480343552", "0.0s0" }, + +{ "-0.94075s0", "-1.0053s-23", + "93579179764423948500992", "0.0s0" }, + +{ "0.263123s0", "-3.060s-24", + "-85988344578092468011008", "0.0s0" }, + +{ "-0.58892s0", "-1.1106s-23", + "53027471682887319814144", "0.0s0" }, + +{ "-0.38977s0", "-2.812s-24", + "138609987891358177689600", "0.0s0" }, + +{ "-1.46599s9", "0.338676s0", + "-4328587264", "0.0s0" }, + +{ "-6.326s9", "0.91743s0", + "-6895370240", "0.0s0" }, + +{ "-3.63617s9", "-0.569855s0", + "6380847104", "0.0s0" }, + +{ "-1.45737s9", "0.9508s0", + "-1532788736", "0.0s0" }, + +{ "5.24714s9", "0.45768s0", + "11464605696", "0.0s0" }, + +{ "8.1693s9", "0.69472s0", + "11759255552", "0.0s0" }, + +{ "-2.7664s9", "-1.9246s9", + "1", "-8.418s8" }, + +{ "8.29057s9", "-7.18694s9", + "-2", "-6.0833s9" }, + +{ "6.7409s9", "8.9158s9", + "0", "6.7409s9" }, + +{ "9.4039s9", "-1.80932s9", + "-6", "-1.45206s9" }, + +{ "4.4432s9", "-7.587s9", + "-1", "-3.14373s9" }, + +{ "-4.8365s9", "-3.4401s8", + "14", "-2.03249s7" }, + +{ "4.70575s9", "2.813s-15", + "1672861433068424397848576", "0.0s0" }, + +{ "8.37706s8", "1.1696s-13", + "7162308674587923054592", "0.0s0" }, + +{ "4.9421s9", "3.384s-15", + "1460410281571511491887104", "0.0s0" }, + +{ "9.4391s8", "6.964s-14", + "13554177553722320617472", "0.0s0" }, + +{ "3.56217s8", "3.380s-14", + "10538999588799264063488", "0.0s0" }, + +{ "7.53166s9", "7.011s-14", + "107426919956256787529728", "0.0s0" }, + +{ "-5.3385s9", "-7.8903s19", + "0", "-5.3385s9" }, + +{ "-5.5786s8", "-6.5112s19", + "0", "-5.5786s8" }, + +{ "-7.0502s9", "-2.57187s18", + "0", "-7.0502s9" }, + +{ "3.48724s9", "3.0864s19", + "0", "3.48724s9" }, + +{ "-1.195s9", "6.9068s19", + "-1", "6.9068s19" }, + +{ "6.40785s9", "6.1696s19", + "0", "6.40785s9" }, + +{ "-9.9772s9", "-3.455s-24", + "2887787295482420840947083445796864", "0.0s0" }, + +{ "6.3337s9", "-2.757s-24", + "-2297319607304237298946798769930240", "0.0s0" }, + +{ "2.24916s9", "8.958s-24", + "251078998767860827355040375111680", "0.0s0" }, + +{ "-4.695s9", "-9.695s-24", + "484267288087969338977238606938112", "0.0s0" }, + +{ "-5.84457s9", "-7.7713s-22", + "7520717852416051178813723246592", "0.0s0" }, + +{ "-2.01576s9", "6.682s-24", + "-301671132293375748429617783898112", "0.0s0" }, + +{ "1.7042s-13", "-0.80732s0", + "-1", "-0.80732s0" }, + +{ "4.959s-14", "0.9918s0", + "0", "4.959s-14" }, + +{ "2.0820s-13", "0.75837s0", + "0", "2.08202s-13" }, + +{ "4.808s-14", "0.89121s0", + "0", "4.808s-14" }, + +{ "-4.005s-14", "0.71084s0", + "-1", "0.71084s0" }, + +{ "4.497s-14", "-0.83223s0", + "-1", "-0.83223s0" }, + +{ "-4.538s-14", "3.81524s9", + "-1", "3.81524s9" }, + +{ "-1.0888s-13", "2.5705s9", + "-1", "2.5705s9" }, + +{ "-1.0445s-15", "3.9579s9", + "-1", "3.9579s9" }, + +{ "-3.399s-14", "3.8115s9", + "-1", "3.8115s9" }, + +{ "8.889s-14", "1.02951s9", + "0", "8.889s-14" }, + +{ "-4.408s-14", "-5.5562s9", + "0", "-4.40806s-14" }, + +{ "1.4679s-13", "-1.9105s-13", + "-1", "-4.426s-14" }, + +{ "1.2740s-14", "-4.935s-14", + "-1", "-3.661s-14" }, + +{ "-4.321s-14", "-8.355s-14", + "0", "-4.32102s-14" }, + +{ "-1.1228s-13", "-3.641s-14", + "3", "-3.0501s-15" }, + +{ "4.643s-14", "9.809s-14", + "0", "4.643s-14" }, + +{ "6.832s-14", "1.2918s-13", + "0", "6.832s-14" }, + +{ "-3.186s-15", "7.2502s19", + "-1", "7.2502s19" }, + +{ "7.570s-14", "-6.8838s19", + "-1", "-6.8838s19" }, + +{ "-1.5446s-14", "-8.6798s19", + "0", "-1.5446s-14" }, + +{ "-1.2496s-13", "-8.0029s19", + "0", "-1.24963s-13" }, + +{ "-3.303s-15", "-9.7969s19", + "0", "-3.303s-15" }, + +{ "-3.832s-14", "5.17976s19", + "-1", "5.17976s19" }, + +{ "-1.1039s-13", "1.1031s-23", + "-10007216128", "0.0s0" }, + +{ "-3.303s-14", "-1.61171s-21", + "20493824", "0.0s0" }, + +{ "3.660s-14", "-1.3664s-23", + "-2678554624", "0.0s0" }, + +{ "-1.9574s-13", "-6.864s-24", + "28516810752", "0.0s0" }, + +{ "3.285s-14", "-3.329s-24", + "-9867755520", "0.0s0" }, + +{ "-3.291s-15", "4.2038s-23", + "-78285824", "0.0s0" }, + +{ "-7.18707s19", "0.231445s0", + "-310527697906823069696", "0.0s0" }, + +{ "9.5173s19", "-0.0566254s0", + "-1680761395333178589184", "0.0s0" }, + +{ "-6.6524s19", "-0.697136s0", + "95424520704539754496", "0.0s0" }, + +{ "3.42423s19", "0.68306s0", + "50130693352167833600", "0.0s0" }, + +{ "-7.2388s19", "0.0522995s0", + "-1384100280679029276672", "0.0s0" }, + +{ "5.9235s18", "-0.24643s0", + "-24037400061136601088", "0.0s0" }, + +{ "-2.63137s18", "-1.6819s9", + "1564524544", "0.0s0" }, + +{ "2.4749s19", "-2.36457s9", + "-10466623488", "0.0s0" }, + +{ "-2.07847s19", "6.4981s9", + "-3198582784", "0.0s0" }, + +{ "-2.54907s19", "4.4446s9", + "-5735186432", "0.0s0" }, + +{ "2.34573s19", "3.0757s9", + "7626620928", "0.0s0" }, + +{ "-1.93055s19", "4.8192s9", + "-4005953536", "0.0s0" }, + +{ "4.4928s19", "9.588s-14", + "468585063670302141654816501268480", "0.0s0" }, + +{ "-2.17698s19", "-3.259s-14", + "667992445198391196335567431270400", "0.0s0" }, + +{ "-8.3605s19", "-1.2702s-13", + "658197863607565267600565560410112", "0.0s0" }, + +{ "5.2775s19", "3.555s-15", + "14845297722947765992252704150257664", "0.0s0" }, + +{ "-5.0371s19", "6.922s-15", + "-7276948270610150879291824750460928", "0.0s0" }, + +{ "8.3107s18", "-1.0201s-13", + "-81468833985370875891111365181440", "0.0s0" }, + +{ "-3.8796s19", "3.8685s19", + "-2", "3.85733s19" }, + +{ "4.11224s18", "-7.757s19", + "-1", "-7.34577s19" }, + +{ "-1.7228s19", "-6.0107s19", + "0", "-1.72278s19" }, + +{ "9.1191s19", "-4.49645s19", + "-3", "-4.3702s19" }, + +{ "4.2755s19", "8.9417s19", + "0", "4.2755s19" }, + +{ "-4.3237s19", "-1.9687s19", + "2", "-3.86314s18" }, + +{ "3.109s-24", "0.00614166s0", + "0", "3.109s-24" }, + +{ "-6.2027s-23", "0.0328217s0", + "-1", "0.0328217s0" }, + +{ "-6.017s-24", "0.76966s0", + "-1", "0.76966s0" }, + +{ "-7.628s-24", "0.47249s0", + "-1", "0.47249s0" }, + +{ "3.323s-24", "-0.86671s0", + "-1", "-0.86671s0" }, + +{ "-5.302s-24", "0.0245514s0", + "-1", "0.0245514s0" }, + +{ "5.342s-24", "6.0717s9", + "0", "5.34194s-24" }, + +{ "-2.664s-24", "5.573s9", + "-1", "5.573s9" }, + +{ "-2.830s-24", "7.0363s9", + "-1", "7.0363s9" }, + +{ "-3.176s-24", "1.12686s9", + "-1", "1.12686s9" }, + +{ "-2.2026s-22", "-3.99255s9", + "0", "-2.2026s-22" }, + +{ "6.994s-24", "5.81167s9", + "0", "6.994s-24" }, + +{ "6.054s-24", "-8.915s-14", + "-1", "-8.915s-14" }, + +{ "2.875s-24", "3.652s-14", + "0", "2.875s-24" }, + +{ "-1.57853s-22", "-4.501s-14", + "0", "-1.57853s-22" }, + +{ "-1.3880s-23", "-1.0479s-13", + "0", "-1.388s-23" }, + +{ "-8.879s-24", "3.974s-14", + "-1", "3.974s-14" }, + +{ "-1.14395s-21", "-4.527s-14", + "0", "-1.14395s-21" }, + +{ "6.149s-24", "9.418s-24", + "0", "6.149s-24" }, + +{ "7.661s-24", "-2.956s-24", + "-3", "-1.20701s-24" }, + +{ "3.254s-24", "1.2764s-22", + "0", "3.254s-24" }, + +{ "-5.4542s-22", "5.574s-24", + "-98", "8.2738s-25" }, + +{ "-1.4523s-23", "3.091s-24", + "-5", "9.3198s-25" }, + +{ "-5.913s-24", "8.419s-24", + "-1", "2.506s-24" }, + +}; diff --git a/tests/exam_SF_minus.cc b/tests/exam_SF_minus.cc new file mode 100644 index 0000000..e5fc941 --- /dev/null +++ b/tests/exam_SF_minus.cc @@ -0,0 +1,457 @@ +#include "exam.h" +#include +#include + +static minus_test sfloat_minus_tests[] = { + +{ "0.57362s0", "-0.0545654s0", + "0.62819s0" }, + +{ "-0.121063s0", "-0.157204s0", + "0.0361404s0" }, + +{ "0.75334s0", "-0.186554s0", + "0.939896s0" }, + +{ "0.879036s0", "-0.54558s0", + "1.42462s0" }, + +{ "-0.245338s0", "-0.003891s0", + "-0.241447s0" }, + +{ "-0.89576s0", "0.61608s0", + "-1.51184s0" }, + +{ "-0.59227s0", "6.61s9", + "-6.61s9" }, + +{ "0.381363s0", "1.88003s9", + "-1.88003s9" }, + +{ "0.858986s0", "1.31028s9", + "-1.31028s9" }, + +{ "0.56377s0", "-3.26553s9", + "3.26553s9" }, + +{ "0.80342s0", "-1.46217s9", + "1.46217s9" }, + +{ "0.093941s0", "8.30203s9", + "-8.30203s9" }, + +{ "0.266243s0", "4.980s-14", + "0.266243s0" }, + +{ "-0.169983s0", "8.01s-15", + "-0.169983s0" }, + +{ "0.77925s0", "-2.777s-15", + "0.77925s0" }, + +{ "-0.379807s0", "3.990s-15", + "-0.379807s0" }, + +{ "-0.392517s0", "1.1080s-13", + "-0.392517s0" }, + +{ "-0.26274s0", "-7.575s-14", + "-0.26274s0" }, + +{ "0.72031s0", "4.1223s19", + "-4.1223s19" }, + +{ "0.589775s0", "-2.9271s19", + "2.9271s19" }, + +{ "0.205704s0", "-8.4906s19", + "8.4906s19" }, + +{ "0.362556s0", "6.8624s19", + "-6.8624s19" }, + +{ "-0.604004s0", "-1.42777s19", + "1.42777s19" }, + +{ "-0.53121s0", "2.3539s19", + "-2.3539s19" }, + +{ "-0.684906s0", "8.179s-24", + "-0.684906s0" }, + +{ "0.43084s0", "-5.849s-24", + "0.43084s0" }, + +{ "0.153358s0", "3.633s-24", + "0.153358s0" }, + +{ "0.93678s0", "9.13s-24", + "0.93678s0" }, + +{ "0.78924s0", "-7.766s-24", + "0.78924s0" }, + +{ "0.33867s0", "3.510s-24", + "0.33867s0" }, + +{ "8.0573s9", "-0.86206s0", + "8.0573s9" }, + +{ "9.3318s9", "-0.93273s0", + "9.3318s9" }, + +{ "-4.26515s9", "0.464104s0", + "-4.26515s9" }, + +{ "-3.35557s9", "-0.93267s0", + "-3.35557s9" }, + +{ "-6.81614s9", "-0.64528s0", + "-6.81614s9" }, + +{ "-5.099s9", "0.67011s0", + "-5.099s9" }, + +{ "-4.2206s9", "4.9182s9", + "-9.1389s9" }, + +{ "-5.18173s9", "2.267s9", + "-7.4487s9" }, + +{ "5.53314s9", "6.08856s9", + "-5.5542s8" }, + +{ "9.88s9", "-3.3333s9", + "1.32132s10" }, + +{ "4.87404s9", "7.17075s9", + "-2.2967s9" }, + +{ "-2.9911s9", "-1.37177s8", + "-2.85393s9" }, + +{ "-8.1379s9", "3.023s-15", + "-8.1379s9" }, + +{ "4.8877s9", "-1.1596s-13", + "4.8877s9" }, + +{ "-1.89071s9", "-4.330s-14", + "-1.89071s9" }, + +{ "8.7563s9", "-4.676s-14", + "8.7563s9" }, + +{ "-4.4533s9", "2.743s-15", + "-4.4533s9" }, + +{ "4.0261s9", "2.1618s-13", + "4.0261s9" }, + +{ "9.1731s9", "-8.0954s19", + "8.0954s19" }, + +{ "6.984s9", "1.09772s19", + "-1.09772s19" }, + +{ "-9.8832s9", "-8.0905s19", + "8.0905s19" }, + +{ "-8.5769s9", "-6.24565s19", + "6.24565s19" }, + +{ "8.5486s9", "2.77396s19", + "-2.77396s19" }, + +{ "-9.4026s9", "-3.5611s19", + "3.5611s19" }, + +{ "5.1003s9", "-1.9535s-23", + "5.1003s9" }, + +{ "1.88706s9", "-1.6304s-23", + "1.88706s9" }, + +{ "-9.4567s9", "-1.9848s-23", + "-9.4567s9" }, + +{ "9.6498s9", "-1.57531s-21", + "9.6498s9" }, + +{ "-5.733s9", "1.23215s-21", + "-5.733s9" }, + +{ "-4.0567s9", "-5.229s-24", + "-4.0567s9" }, + +{ "-4.379s-14", "-0.0201035s0", + "0.0201035s0" }, + +{ "-4.036s-14", "0.82034s0", + "-0.82034s0" }, + +{ "1.6661s-13", "-0.70753s0", + "0.70753s0" }, + +{ "3.360s-14", "0.60217s0", + "-0.60217s0" }, + +{ "4.977s-14", "-0.95905s0", + "0.95905s0" }, + +{ "-2.967s-14", "0.55465s0", + "-0.55465s0" }, + +{ "4.394s-14", "2.01859s9", + "-2.01859s9" }, + +{ "3.683s-14", "4.77836s9", + "-4.77836s9" }, + +{ "-6.887s-14", "-9.26s9", + "9.26s9" }, + +{ "-2.643s-15", "-5.6812s9", + "5.6812s9" }, + +{ "-8.498s-14", "-9.3728s9", + "9.3728s9" }, + +{ "9.033s-14", "2.18002s9", + "-2.18002s9" }, + +{ "3.113s-14", "-9.207s-14", + "1.232s-13" }, + +{ "-3.239s-15", "-1.2957s-13", + "1.26331s-13" }, + +{ "3.098s-15", "-6.117s-15", + "9.2151s-15" }, + +{ "1.7706s-13", "4.829s-14", + "1.2877s-13" }, + +{ "2.793s-15", "8.620s-14", + "-8.3407s-14" }, + +{ "-5.019s-14", "4.125s-14", + "-9.144s-14" }, + +{ "-9.495s-14", "-6.06994s18", + "6.06994s18" }, + +{ "9.385s-14", "-7.9288s19", + "7.9288s19" }, + +{ "-3.099s-14", "-6.64095s19", + "6.64095s19" }, + +{ "3.397s-15", "2.92222s19", + "-2.92222s19" }, + +{ "-8.463s-14", "-4.9708s19", + "4.9708s19" }, + +{ "-2.735s-15", "-9.2672s19", + "9.2672s19" }, + +{ "-2.974s-14", "-7.975s-24", + "-2.974s-14" }, + +{ "-2.1853s-13", "2.736s-24", + "-2.1853s-13" }, + +{ "3.243s-15", "-6.867s-24", + "3.243s-15" }, + +{ "4.792s-14", "-2.659s-24", + "4.792s-14" }, + +{ "4.672s-14", "7.831s-24", + "4.672s-14" }, + +{ "2.0285s-13", "2.741s-24", + "2.0285s-13" }, + +{ "-9.1884s19", "-0.22573s0", + "-9.1884s19" }, + +{ "3.32245s19", "0.7651s0", + "3.32245s19" }, + +{ "4.13513s17", "0.85135s0", + "4.13513s17" }, + +{ "2.2249s19", "0.45778s0", + "2.2249s19" }, + +{ "4.9103s19", "0.84862s0", + "4.9103s19" }, + +{ "4.27386s19", "-0.06662s0", + "4.27386s19" }, + +{ "-6.725s19", "5.11246s8", + "-6.725s19" }, + +{ "-2.40906s19", "7.2238s9", + "-2.40906s19" }, + +{ "6.1667s19", "-7.4303s9", + "6.1667s19" }, + +{ "-7.746s19", "-4.29687s8", + "-7.746s19" }, + +{ "-1.81419s19", "-5.68164s9", + "-1.81419s19" }, + +{ "7.0665s19", "-8.9546s8", + "7.0665s19" }, + +{ "2.47788s19", "-2.2961s-13", + "2.47788s19" }, + +{ "-7.4962s19", "-3.378s-14", + "-7.4962s19" }, + +{ "1.72135s19", "7.168s-14", + "1.72135s19" }, + +{ "8.3699s19", "4.887s-14", + "8.3699s19" }, + +{ "-4.5701s19", "-8.009s-14", + "-4.5701s19" }, + +{ "-2.845s18", "1.1087s-13", + "-2.845s18" }, + +{ "6.4084s19", "-4.569s19", + "1.09774s20" }, + +{ "1.33888s19", "-6.8446s19", + "8.1835s19" }, + +{ "-4.0631s19", "1.50864s19", + "-5.57174s19" }, + +{ "-5.61754s18", "2.6413s18", + "-8.2588s18" }, + +{ "-9.0749s19", "6.21626s19", + "-1.5291s20" }, + +{ "-8.5269s19", "6.2002s19", + "-1.47271s20" }, + +{ "3.15773s19", "5.433s-24", + "3.15773s19" }, + +{ "5.1563s19", "-1.6366s-23", + "5.1563s19" }, + +{ "-5.8449s19", "3.282s-24", + "-5.8449s19" }, + +{ "4.70947s19", "1.5640s-23", + "4.70947s19" }, + +{ "-4.32334s19", "-1.0593s-23", + "-4.32334s19" }, + +{ "7.9621s19", "5.610s-24", + "7.9621s19" }, + +{ "8.164s-24", "0.133362s0", + "-0.133362s0" }, + +{ "-1.57089s-21", "0.3154s0", + "-0.3154s0" }, + +{ "-3.736s-24", "-0.66536s0", + "0.66536s0" }, + +{ "-6.923s-24", "-0.431366s0", + "0.431366s0" }, + +{ "3.345s-24", "0.77436s0", + "-0.77436s0" }, + +{ "-1.4322s-23", "0.799644s0", + "-0.799644s0" }, + +{ "-1.3249s-23", "-4.22035s9", + "4.22035s9" }, + +{ "2.707s-24", "-6.5029s9", + "6.5029s9" }, + +{ "-3.490s-24", "-2.5205s9", + "2.5205s9" }, + +{ "-1.0086s-23", "1.35048s9", + "-1.35048s9" }, + +{ "1.4406s-23", "1.55487s9", + "-1.55487s9" }, + +{ "3.370s-24", "-4.3973s9", + "4.3973s9" }, + +{ "-1.31249s-21", "3.448s-14", + "-3.448s-14" }, + +{ "-7.706s-24", "-1.9488s-13", + "1.9488s-13" }, + +{ "-9.8403s-22", "2.2940s-13", + "-2.294s-13" }, + +{ "-3.355s-24", "1.0187s-13", + "-1.0187s-13" }, + +{ "9.5635s-22", "-8.663s-14", + "8.663s-14" }, + +{ "-5.713s-24", "-3.169s-14", + "3.169s-14" }, + +{ "2.645s-24", "-5.2307s19", + "5.2307s19" }, + +{ "-9.960s-24", "-9.2854s19", + "9.2854s19" }, + +{ "8.036s-24", "-7.11434s19", + "7.11434s19" }, + +{ "3.475s-24", "-4.845s19", + "4.845s19" }, + +{ "-3.062s-24", "4.91714s19", + "-4.91714s19" }, + +{ "-2.541s-24", "-2.91276s19", + "2.91276s19" }, + +{ "1.4371s-23", "1.1606s-23", + "2.76508s-24" }, + +{ "-1.8769s-23", "2.965s-24", + "-2.1734s-23" }, + +{ "3.713s-24", "-1.7581s-23", + "2.1294s-23" }, + +{ "-5.954s-24", "-2.764s-24", + "-3.19s-24" }, + +{ "3.21502s-22", "8.56s-24", + "3.12942s-22" }, + +{ "9.969s-24", "5.912s-24", + "4.057s-24" }, + +}; diff --git a/tests/exam_SF_mul.cc b/tests/exam_SF_mul.cc new file mode 100644 index 0000000..fbc6195 --- /dev/null +++ b/tests/exam_SF_mul.cc @@ -0,0 +1,424 @@ +#include "exam.h" +#include +#include + +static mul_test sfloat_mul_tests[] = { + +{ "-0.56581s0", "-0.117477s0", + "0.06647s0" }, + +{ "0.73841s0", "0.08886s0", + "0.065615s0" }, + +{ "-0.75174s0", "-0.173615s0", + "0.130512s0" }, + +{ "0.557236s0", "-0.105034s0", + "-0.0585284s0" }, + +{ "-0.62105s0", "0.828835s0", + "-0.51475s0" }, + +{ "-0.54287s0", "-0.92243s0", + "0.50076s0" }, + +{ "-0.2173s0", "5.5084s9", + "-1.19698s9" }, + +{ "0.467354s0", "-7.9517s9", + "-3.71625s9" }, + +{ "-0.95485s0", "5.6451s9", + "-5.3902s9" }, + +{ "0.0472946s0", "-6.774s9", + "-3.20373s8" }, + +{ "0.196037s0", "7.3548s8", + "1.44181s8" }, + +{ "-0.25535s0", "4.91907s9", + "-1.25608s9" }, + +{ "0.047058s0", "6.612s-14", + "3.11147s-15" }, + +{ "-0.35054s0", "3.764s-14", + "-1.31943s-14" }, + +{ "0.372635s0", "1.0613s-13", + "3.9548s-14" }, + +{ "0.627266s0", "-9.519s-14", + "-5.971s-14" }, + +{ "-0.0293884s0", "1.1626s-13", + "-3.41667s-15" }, + +{ "-0.88304s0", "-1.1160s-13", + "9.8547s-14" }, + +{ "0.318016s0", "-6.86827s19", + "-2.18422s19" }, + +{ "0.605064s0", "3.4281s19", + "2.07422s19" }, + +{ "-0.65415s0", "-8.185s19", + "5.3542s19" }, + +{ "0.87548s0", "6.72325s19", + "5.8861s19" }, + +{ "0.45806s0", "-9.503s19", + "-4.35295s19" }, + +{ "-0.995384s0", "1.62797s19", + "-1.62045s19" }, + +{ "0.26301s0", "-1.3169s-23", + "-3.46357s-24" }, + +{ "0.82762s0", "-3.411s-24", + "-2.82304s-24" }, + +{ "-0.042412s0", "-3.339s-24", + "1.41613s-25" }, + +{ "0.858284s0", "-7.610s-24", + "-6.53157s-24" }, + +{ "0.75574s0", "1.0518s-23", + "7.9488s-24" }, + +{ "0.977s0", "-5.944s-24", + "-5.8073s-24" }, + +{ "1.1316s9", "0.87906s0", + "9.9474s8" }, + +{ "9.7596s9", "0.58181s0", + "5.67824s9" }, + +{ "5.5896s9", "-0.91708s0", + "-5.12616s9" }, + +{ "-7.677s9", "-0.67695s0", + "5.19694s9" }, + +{ "-4.73655s9", "0.65572s0", + "-3.10588s9" }, + +{ "-3.2158s9", "-0.30076s0", + "9.6717s8" }, + +{ "5.94916s9", "-1.02867s9", + "-6.1197s18" }, + +{ "-3.19098s9", "8.125s9", + "-2.59267s19" }, + +{ "-6.57215s9", "9.4253s9", + "-6.1944s19" }, + +{ "-5.2792s9", "3.93547s9", + "-2.0776s19" }, + +{ "2.502s9", "4.1275s9", + "1.0327s19" }, + +{ "-8.9462s9", "-4.72174s9", + "4.22415s19" }, + +{ "-8.9588s9", "-1.4190s-14", + "1.27126s-4" }, + +{ "-3.56218s9", "-9.982s-14", + "3.5558s-4" }, + +{ "-3.4449s9", "4.582s-15", + "-1.57845s-5" }, + +{ "-3.7047s9", "1.2985s-14", + "-4.8105s-5" }, + +{ "-8.9172s8", "-7.294s-14", + "6.5043s-5" }, + +{ "1.64864s9", "1.8344s-13", + "3.02427s-4" }, + +{ "-9.935s8", "-7.9116s19", + "7.8602s28" }, + +{ "-7.0441s9", "-6.3448s19", + "4.4693s29" }, + +{ "7.72866s9", "1.44264s19", + "1.11497s29" }, + +{ "3.7816s9", "-3.16285s19", + "-1.19606s29" }, + +{ "-1.06926s9", "6.67816s19", + "-7.1407s28" }, + +{ "4.04482s9", "-3.52235s19", + "-1.42473s29" }, + +{ "-8.77s8", "-3.499s-24", + "3.06864s-15" }, + +{ "-9.5508s9", "1.0006s-23", + "-9.5566s-14" }, + +{ "-2.98736s9", "-7.070s-24", + "2.11207s-14" }, + +{ "9.9779s9", "1.2683s-23", + "1.26548s-13" }, + +{ "7.4813s9", "-1.3730s-23", + "-1.02719s-13" }, + +{ "8.5804s9", "6.999s-24", + "6.0054s-14" }, + +{ "4.637s-14", "0.895805s0", + "4.15384s-14" }, + +{ "1.0125s-13", "-0.322685s0", + "-3.26718s-14" }, + +{ "2.310s-16", "0.0601425s0", + "1.38928s-17" }, + +{ "1.0579s-13", "-0.27089s0", + "-2.86576s-14" }, + +{ "9.540s-14", "-0.21251s0", + "-2.02735s-14" }, + +{ "-4.463s-14", "-0.96336s0", + "4.2995s-14" }, + +{ "3.270s-14", "-5.9141s9", + "-1.93391s-4" }, + +{ "-6.515s-14", "1.01791s9", + "-6.6318s-5" }, + +{ "3.695s-14", "8.7417s9", + "3.23005s-4" }, + +{ "-1.0900s-13", "-6.75794s9", + "7.3662s-4" }, + +{ "4.551s-14", "-7.1112s9", + "-3.2363s-4" }, + +{ "5.456s-15", "-5.44014s9", + "-2.96813s-5" }, + +{ "-3.377s-14", "3.358s-15", + "-1.13399s-28" }, + +{ "3.862s-14", "7.278s-14", + "2.81079s-27" }, + +{ "9.449s-14", "3.170s-14", + "2.99533s-27" }, + +{ "7.051s-14", "-4.234s-14", + "-2.98537s-27" }, + +{ "-8.955s-14", "9.895s-14", + "-8.861s-27" }, + +{ "-1.6752s-13", "-7.341s-14", + "1.22977s-26" }, + +{ "9.420s-14", "4.50844s19", + "4246900.0s0" }, + +{ "2.0183s-13", "9.598s19", + "1.93715s7" }, + +{ "-7.441s-14", "-5.7324s19", + "4265500.0s0" }, + +{ "7.241s-14", "-5.79135s19", + "-4193500.0s0" }, + +{ "7.987s-14", "8.1113s19", + "6478500.0s0" }, + +{ "-1.1603s-13", "7.4468s19", + "-8640500.0s0" }, + +{ "-4.432s-14", "-6.851s-24", + "3.03637s-37" }, + +{ "-5.064s-14", "-8.119s-24", + "4.1115s-37" }, + +{ "3.553s-15", "-6.404s-24", + "-2.27533s-38" }, + +{ "8.699s-14", "-3.558s-24", + "-3.0951s-37" }, + +{ "9.820s-14", "-5.771s-24", + "-5.6671s-37" }, + +{ "-3.477s-14", "7.723s-24", + "-2.6853s-37" }, + +{ "7.9082s19", "0.71604s0", + "5.6626s19" }, + +{ "-6.83905s19", "-0.36905s0", + "2.52396s19" }, + +{ "-7.7697s19", "-0.34073s0", + "2.64736s19" }, + +{ "-2.10557s19", "-0.58961s0", + "1.24146s19" }, + +{ "9.0963s19", "-0.37693s0", + "-3.42865s19" }, + +{ "-4.24076s19", "0.91147s0", + "-3.8653s19" }, + +{ "-3.5865s19", "-6.4046s9", + "2.297s29" }, + +{ "7.19225s18", "-7.7232s9", + "-5.5547s28" }, + +{ "1.98907s19", "-9.9239s9", + "-1.97393s29" }, + +{ "-4.27195s19", "7.0734s9", + "-3.02173s29" }, + +{ "-8.3115s19", "5.2947s9", + "-4.40073s29" }, + +{ "9.4386s19", "8.6548s8", + "8.169s28" }, + +{ "6.21677s19", "-3.135s-14", + "-1948960.0s0" }, + +{ "-6.30774s19", "1.5884s-13", + "-1.00192s7" }, + +{ "7.6073s19", "3.922s-14", + "2983550.0s0" }, + +{ "-1.44485s19", "-3.355s-14", + "484748.0s0" }, + +{ "3.39653s19", "-7.679s-14", + "-2608200.0s0" }, + +{ "-6.0072s19", "1.7825s-13", + "-1.07078s7" }, + +{ "1.06812s16", "-1.19583s19", + "-1.2773s35" }, + +{ "1.1438s19", "2.616s-24", + "2.99218s-5" }, + +{ "-5.79304s18", "-3.095s-24", + "1.79296s-5" }, + +{ "-7.6387s19", "8.607s-24", + "-6.5746s-4" }, + +{ "4.03933s19", "3.058s-24", + "1.23523s-4" }, + +{ "-2.06994s19", "-1.1381s-23", + "2.3558s-4" }, + +{ "3.7857s18", "-3.590s-24", + "-1.35906s-5" }, + +{ "5.656s-24", "-0.096458s0", + "-5.4557s-25" }, + +{ "-5.799s-24", "-0.148445s0", + "8.6083s-25" }, + +{ "-9.041s-24", "0.86431s0", + "-7.8143s-24" }, + +{ "-2.645s-24", "-0.911865s0", + "2.41187s-24" }, + +{ "-9.758s-24", "-0.397186s0", + "3.87574s-24" }, + +{ "-5.345s-24", "-0.27215s0", + "1.45463s-24" }, + +{ "-3.713s-24", "9.11335s8", + "-3.38382s-15" }, + +{ "-3.010s-24", "-9.5278s9", + "2.86784s-14" }, + +{ "-1.6904s-23", "-8.37655s9", + "1.41599s-13" }, + +{ "-5.074s-24", "-9.2804s9", + "4.7089s-14" }, + +{ "-6.942s-22", "-8.7038s9", + "6.04217s-12" }, + +{ "-7.643s-24", "-3.1665s9", + "2.42018s-14" }, + +{ "-2.659s-24", "-9.238s-14", + "2.4564s-37" }, + +{ "-1.7036s-23", "3.138s-14", + "-5.34586s-37" }, + +{ "7.684s-24", "8.639s-14", + "6.6383s-37" }, + +{ "-3.424s-24", "-6.046s-14", + "2.07014s-37" }, + +{ "9.3102s-22", "-1.1344s-13", + "-1.05614s-34" }, + +{ "8.070s-24", "3.573s-14", + "2.8834s-37" }, + +{ "3.557s-24", "7.9957s19", + "2.84407s-4" }, + +{ "7.281s-24", "-3.45443s19", + "-2.5152s-4" }, + +{ "-1.6093s-23", "3.22463s19", + "-5.1894s-4" }, + +{ "-1.8628s-23", "4.95593s19", + "-9.2319s-4" }, + +{ "3.463s-24", "-4.44685s19", + "-1.53994s-4" }, + +{ "-8.081s-24", "-1.54701s19", + "1.25013s-4" }, + +}; diff --git a/tests/exam_SF_plus.cc b/tests/exam_SF_plus.cc new file mode 100644 index 0000000..3a9742b --- /dev/null +++ b/tests/exam_SF_plus.cc @@ -0,0 +1,457 @@ +#include "exam.h" +#include +#include + +static plus_test sfloat_plus_tests[] = { + +{ "0.52019s0", "0.98203s0", + "1.50223s0" }, + +{ "0.026268s0", "0.6137s0", + "0.63997s0" }, + +{ "-0.338943s0", "0.450523s0", + "0.11158s0" }, + +{ "-0.032799s0", "0.995186s0", + "0.96239s0" }, + +{ "0.249222s0", "0.96463s0", + "1.21385s0" }, + +{ "-0.46177s0", "-0.80114s0", + "-1.26291s0" }, + +{ "-0.127754s0", "-1.88775s9", + "-1.88775s9" }, + +{ "-0.65572s0", "-9.1112s9", + "-9.1112s9" }, + +{ "-0.99359s0", "-7.6134s9", + "-7.6134s9" }, + +{ "0.0169907s0", "-5.9027s9", + "-5.9027s9" }, + +{ "0.77272s0", "-9.5384s9", + "-9.5384s9" }, + +{ "-0.50671s0", "1.95366s9", + "1.95366s9" }, + +{ "-0.281487s0", "-1.4109s-13", + "-0.281487s0" }, + +{ "0.86259s0", "-1.8225s-13", + "0.86259s0" }, + +{ "0.42874s0", "6.326s-14", + "0.42874s0" }, + +{ "-0.53545s0", "3.607s-14", + "-0.53545s0" }, + +{ "0.63671s0", "-4.723s-14", + "0.63671s0" }, + +{ "0.34449s0", "-4.873s-14", + "0.34449s0" }, + +{ "-0.480698s0", "3.03292s19", + "3.03292s19" }, + +{ "0.85132s0", "-6.325s19", + "-6.325s19" }, + +{ "-0.54742s0", "-2.83806s19", + "-2.83806s19" }, + +{ "0.45269s0", "1.62964s19", + "1.62964s19" }, + +{ "-0.5122s0", "-3.6148s18", + "-3.6148s18" }, + +{ "0.192093s0", "5.3618s19", + "5.3618s19" }, + +{ "-0.43486s0", "-8.918s-24", + "-0.43486s0" }, + +{ "0.289955s0", "-5.911s-24", + "0.289955s0" }, + +{ "0.274345s0", "-1.6779s-23", + "0.274345s0" }, + +{ "0.392723s0", "-7.441s-24", + "0.392723s0" }, + +{ "-0.62215s0", "3.521s-24", + "-0.62215s0" }, + +{ "-0.5406s0", "-7.718s-24", + "-0.5406s0" }, + +{ "6.5444s9", "-0.060898s0", + "6.5444s9" }, + +{ "-8.541s9", "-0.181755s0", + "-8.541s9" }, + +{ "3.02993s9", "0.694534s0", + "3.02993s9" }, + +{ "9.3926s9", "-0.77226s0", + "9.3926s9" }, + +{ "-6.4481s9", "0.252235s0", + "-6.4481s9" }, + +{ "-1.1734s8", "0.94104s0", + "-1.1734s8" }, + +{ "-5.1049s9", "1.28059s9", + "-3.82435s9" }, + +{ "-7.39554s9", "8.9347s9", + "1.53911s9" }, + +{ "3.11457s9", "1.71478s9", + "4.82935s9" }, + +{ "-8.0461s9", "9.0508s9", + "1.00467s9" }, + +{ "-8.58006s8", "-2.82289s7", + "-8.86235s8" }, + +{ "1.82954s9", "-1.83914s9", + "-9601000.0s0" }, + +{ "7.6292s9", "1.3988s-13", + "7.6292s9" }, + +{ "-1.43837s9", "-2.482s-15", + "-1.43837s9" }, + +{ "-6.4696s9", "-1.3269s-13", + "-6.4696s9" }, + +{ "9.6744s9", "-3.132s-14", + "9.6744s9" }, + +{ "-1.18927s9", "-1.9405s-13", + "-1.18927s9" }, + +{ "-3.81462s9", "-8.602s-14", + "-3.81462s9" }, + +{ "5.5761s9", "1.32286s19", + "1.32286s19" }, + +{ "7.1631s9", "-9.3184s19", + "-9.3184s19" }, + +{ "4.7921s9", "-5.8008s19", + "-5.8008s19" }, + +{ "7.792s9", "9.7695s19", + "9.7695s19" }, + +{ "8.9575s9", "7.0198s19", + "7.0198s19" }, + +{ "4.4688s9", "7.2066s19", + "7.2066s19" }, + +{ "8.9222s9", "-1.3243s-23", + "8.9222s9" }, + +{ "-9.7717s9", "3.434s-24", + "-9.7717s9" }, + +{ "-4.22478s9", "-7.938s-24", + "-4.22478s9" }, + +{ "3.9261s8", "7.916s-24", + "3.9261s8" }, + +{ "-3.239s9", "-8.986s-24", + "-3.239s9" }, + +{ "-4.6268s9", "-1.0129s-23", + "-4.6268s9" }, + +{ "1.1171s-13", "0.73372s0", + "0.73372s0" }, + +{ "-3.575s-14", "0.94588s0", + "0.94588s0" }, + +{ "3.176s-14", "-0.160759s0", + "-0.160759s0" }, + +{ "5.055s-15", "-0.0258102s0", + "-0.0258102s0" }, + +{ "6.371s-14", "0.480484s0", + "0.480484s0" }, + +{ "-9.257s-14", "0.698975s0", + "0.698975s0" }, + +{ "-1.0281s-13", "-9.4453s9", + "-9.4453s9" }, + +{ "5.960s-14", "-1.71395s9", + "-1.71395s9" }, + +{ "6.805s-14", "-5.8515s9", + "-5.8515s9" }, + +{ "1.1645s-13", "7.4758s9", + "7.4758s9" }, + +{ "-1.0064s-13", "-1.86868s9", + "-1.86868s9" }, + +{ "8.912s-15", "-8.4908s9", + "-8.4908s9" }, + +{ "4.036s-14", "3.308s-15", + "4.3668s-14" }, + +{ "-2.503s-15", "-7.642s-14", + "-7.8923s-14" }, + +{ "4.653s-14", "-4.612s-14", + "4.10262s-16" }, + +{ "4.700s-14", "-8.456s-14", + "-3.756s-14" }, + +{ "8.181s-14", "-4.658s-14", + "3.52305s-14" }, + +{ "-1.5467s-13", "2.3608s-13", + "8.1409s-14" }, + +{ "-4.341s-14", "-5.14576s19", + "-5.14576s19" }, + +{ "-3.159s-14", "-9.4925s19", + "-9.4925s19" }, + +{ "-7.325s-14", "3.49983s19", + "3.49983s19" }, + +{ "4.134s-14", "7.07955s19", + "7.07955s19" }, + +{ "4.080s-15", "-3.7832s19", + "-3.7832s19" }, + +{ "1.1577s-13", "3.30522s19", + "3.30522s19" }, + +{ "-6.838s-14", "2.739s-24", + "-6.838s-14" }, + +{ "5.050s-14", "6.768s-24", + "5.05s-14" }, + +{ "-1.9477s-13", "-6.657s-24", + "-1.9477s-13" }, + +{ "-6.348s-14", "-5.222s-24", + "-6.348s-14" }, + +{ "-8.770s-14", "-1.58234s-22", + "-8.77s-14" }, + +{ "7.906s-14", "4.9202s-22", + "7.906s-14" }, + +{ "3.7985s19", "0.8199s0", + "3.7985s19" }, + +{ "9.891s19", "0.79037s0", + "9.891s19" }, + +{ "-1.49583s19", "-0.360153s0", + "-1.49583s19" }, + +{ "-7.36023s19", "0.8185s0", + "-7.36023s19" }, + +{ "3.62075s19", "-0.364594s0", + "3.62075s19" }, + +{ "8.0477s19", "-0.531815s0", + "8.0477s19" }, + +{ "3.62182s19", "-7.2661s9", + "3.62182s19" }, + +{ "-3.23868s19", "-9.6806s9", + "-3.23868s19" }, + +{ "-6.08735s19", "2.89138s9", + "-6.08735s19" }, + +{ "5.00175s19", "-6.3548s9", + "5.00175s19" }, + +{ "2.82944s19", "4.7262s9", + "2.82944s19" }, + +{ "4.6168s19", "-6.8772s9", + "4.6168s19" }, + +{ "1.15555s19", "-3.786s-14", + "1.15555s19" }, + +{ "8.1897s19", "-8.971s-14", + "8.1897s19" }, + +{ "4.32734s19", "-4.794s-14", + "4.32734s19" }, + +{ "-9.4559s19", "-1.9717s-13", + "-9.4559s19" }, + +{ "-4.20726s19", "-8.657s-14", + "-4.20726s19" }, + +{ "9.7697s19", "-3.376s-14", + "9.7697s19" }, + +{ "6.09264s19", "-7.5608s18", + "5.33654s19" }, + +{ "-5.2828s19", "6.8924s18", + "-4.59356s19" }, + +{ "5.73685s19", "-1.4978s19", + "4.23907s19" }, + +{ "-1.30897s19", "4.8593s19", + "3.55036s19" }, + +{ "-8.5586s19", "-9.712s19", + "-1.82707s20" }, + +{ "3.8772s19", "-8.6355s19", + "-4.75833s19" }, + +{ "-1.03845s19", "6.88s-24", + "-1.03845s19" }, + +{ "8.4716s19", "9.614s-24", + "8.4716s19" }, + +{ "-4.3023s19", "-7.649s-24", + "-4.3023s19" }, + +{ "5.9593s19", "-2.552s-24", + "5.9593s19" }, + +{ "9.8934s19", "1.3093s-23", + "9.8934s19" }, + +{ "-5.70567s19", "7.918s-24", + "-5.70567s19" }, + +{ "-2.893s-24", "-0.93898s0", + "-0.93898s0" }, + +{ "8.795s-24", "-0.030014s0", + "-0.030014s0" }, + +{ "-9.366s-24", "0.200493s0", + "0.200493s0" }, + +{ "-9.3102s-22", "-0.28704s0", + "-0.28704s0" }, + +{ "7.142s-24", "-0.45701s0", + "-0.45701s0" }, + +{ "9.420s-24", "0.957794s0", + "0.957794s0" }, + +{ "2.975s-24", "-6.84104s9", + "-6.84104s9" }, + +{ "2.26822s-22", "-8.9898s9", + "-8.9898s9" }, + +{ "-1.531s-23", "8.1961s9", + "8.1961s9" }, + +{ "1.7221s-23", "-1.53725s9", + "-1.53725s9" }, + +{ "-9.488s-24", "-4.77676s8", + "-4.77676s8" }, + +{ "-1.5077s-23", "2.8251s9", + "2.8251s9" }, + +{ "3.410s-24", "-4.701s-14", + "-4.701s-14" }, + +{ "-3.361s-24", "-4.947s-15", + "-4.947s-15" }, + +{ "9.026s-24", "7.353s-14", + "7.353s-14" }, + +{ "-6.385s-24", "7.789s-14", + "7.789s-14" }, + +{ "1.8237s-23", "8.517s-14", + "8.517s-14" }, + +{ "3.4439s-22", "-4.345s-14", + "-4.345s-14" }, + +{ "-6.817s-24", "-9.8611s19", + "-9.8611s19" }, + +{ "6.213s-24", "-2.7257s19", + "-2.7257s19" }, + +{ "-1.9353s-23", "-2.71446s19", + "-2.71446s19" }, + +{ "-3.653s-24", "-7.7565s19", + "-7.7565s19" }, + +{ "1.2298s-23", "-1.56532s19", + "-1.56532s19" }, + +{ "2.905s-24", "2.334s19", + "2.334s19" }, + +{ "3.182s-24", "-5.727s-24", + "-2.545s-24" }, + +{ "-1.0745s-23", "3.640s-24", + "-7.1049s-24" }, + +{ "-9.7145s-22", "8.77s-24", + "-9.6267s-22" }, + +{ "1.3734s-23", "3.225s-24", + "1.69588s-23" }, + +{ "2.745s-24", "1.0505s-23", + "1.325s-23" }, + +{ "2.780s-24", "2.747s-24", + "5.527s-24" }, + +}; diff --git a/tests/main.cc b/tests/main.cc new file mode 100644 index 0000000..6978abd --- /dev/null +++ b/tests/main.cc @@ -0,0 +1,110 @@ +//#define WANT_OBFUSCATING_OPERATORS +#include +#include +//#include +//#include +//#include +//#include +//#include +#include +#include +//#include +//#include +#include + +#define DUMP(expr) \ + fprint(cl_stdout, #expr" = "); fprint(cl_stdout, expr); fprint(cl_stdout, "\n"); + +int main (int argc, char* argv[]) +{ + (void)argc; (void)argv; + +#if 0 + cl_F pi = cl_pi((cl_float_format_t)10000); + fprint(cl_stdout, pi); + fprint(cl_stdout, "\n"); +#endif + +#if 0 + cl_FF a; + cl_FF x1 = "-0.2173f0"; + cl_FF x2 = "5.5084f9"; + cl_FF y = "-1.19698f9"; + fprint(cl_stdout, "x1 = "); print_float_binary(cl_stdout,x1); fprint(cl_stdout, " = "); fprint(cl_stdout,x1); fprint(cl_stdout, "\n"); + fprint(cl_stdout, "x2 = "); print_float_binary(cl_stdout,x2); fprint(cl_stdout, " = "); fprint(cl_stdout,x2); fprint(cl_stdout, "\n"); + fprint(cl_stdout, "y = "); print_float_binary(cl_stdout,y); fprint(cl_stdout, " = "); fprint(cl_stdout,y); fprint(cl_stdout, "\n"); + cl_FF x = x1*x2; + fprint(cl_stdout, "x1*x2 = "); print_float_binary(cl_stdout,x); fprint(cl_stdout, " = "); fprint(cl_stdout,x); fprint(cl_stdout, "\n"); +#endif + +#if 0 + cl_I x = 10; + cl_I y = ++x; + x *= 2; + x++; + fprint(cl_stdout, "x = "); fprint(cl_stdout, x); fprint(cl_stdout, "\n"); + fprint(cl_stdout, "y = "); fprint(cl_stdout, y); fprint(cl_stdout, "\n"); +#endif + +#if 0 + cl_I a = "77371252437321868671713407"; + cl_I w; + cl_boolean squarep = isqrt(a,&w); + DUMP(squarep); + DUMP(w); + DUMP(expt_pos(w,2) <= a); + DUMP(a < expt_pos(w+1,2)); +#endif + +#if 0 + cl_I m = "79228162513111556826425457664"; + cl_I a = "19787815858762768436681494528"; + cl_modint_ring R = cl_find_modint_ring(m); + cl_I b = R->retract(R->canonhom(a)); + cl_I c = mod(a,abs(m)); + DUMP(b); + DUMP(c); + DUMP(b==c); +#endif + +#if 0 + cl_N x = argv[1]; + cl_N y = sinh(x); + { CL_TIMING; y = sinh(x); } + cout << y << endl; +#endif + +#if 0 + cl_I x = argv[1]; + cout << x << " is " << (isprobprime(x) ? "" : "not ") << "prime" << endl; +#endif + +#if 0 + cl_float_format_t f = cl_float_format(atoi(argv[1])); + extern cl_LF cl_zeta3 (uintC len); + uintC len = (uintL)f/intDsize+1; + { CL_TIMING; cout << cl_zeta(2,f) << endl; } + { CL_TIMING; cout << expt(cl_pi(f),2)/6 << endl; } + { CL_TIMING; cout << cl_zeta(3,f) << endl; } + { CL_TIMING; cout << cl_zeta3(len) << endl; } + { CL_TIMING; cout << cl_zeta(4,f) << endl; } +#endif + + cl_I a = cl_I(argv[1]); + cl_I b = cl_I(argv[2]); + cl_I u; + cl_I v; + cl_I g = xgcd(a,b,&u,&v); + cout << "a = " << a << endl; + cout << "b = " << b << endl; + cout << "gcd = " << gcd(a,b) << endl; + cout << "g = " << g << endl; + cout << "u = " << u << endl; + cout << "v = " << v << endl; + +#if 0 + cl_F x = argv[1]; + cout << x << endl; +#endif + +} diff --git a/tests/test.h b/tests/test.h new file mode 100644 index 0000000..ae3c3c4 --- /dev/null +++ b/tests/test.h @@ -0,0 +1,76 @@ +#include + +#define ASSERT(expr) \ + if (!(expr)) { \ + fprint(cl_stderr,"Assertion failed! File "); \ + fprint(cl_stderr,__FILE__); \ + fprint(cl_stderr,", line "); \ + fprintdecimal(cl_stderr,__LINE__); \ + fprint(cl_stderr,".\n"); \ + error = 1; \ + } + +#define ASSERT1(expr,a) \ + if (!(expr)) { \ + fprint(cl_stderr,"Assertion failed! File "); \ + fprint(cl_stderr,__FILE__); \ + fprint(cl_stderr,", line "); \ + fprintdecimal(cl_stderr,__LINE__); \ + fprint(cl_stderr,".\n"); \ + fprint(cl_stderr,#a" = "); \ + fprint(cl_stderr,a); \ + fprint(cl_stderr,"\n"); \ + error = 1; \ + } + +#define ASSERT2(expr,a,b) \ + if (!(expr)) { \ + fprint(cl_stderr,"Assertion failed! File "); \ + fprint(cl_stderr,__FILE__); \ + fprint(cl_stderr,", line "); \ + fprintdecimal(cl_stderr,__LINE__); \ + fprint(cl_stderr,".\n"); \ + fprint(cl_stderr,#a" = "); \ + fprint(cl_stderr,a); \ + fprint(cl_stderr,"\n"#b" = "); \ + fprint(cl_stderr,b); \ + fprint(cl_stderr,"\n"); \ + error = 1; \ + } + +#define ASSERT3(expr,a,b,c) \ + if (!(expr)) { \ + fprint(cl_stderr,"Assertion failed! File "); \ + fprint(cl_stderr,__FILE__); \ + fprint(cl_stderr,", line "); \ + fprintdecimal(cl_stderr,__LINE__); \ + fprint(cl_stderr,".\n"); \ + fprint(cl_stderr,#a" = "); \ + fprint(cl_stderr,a); \ + fprint(cl_stderr,"\n"#b" = "); \ + fprint(cl_stderr,b); \ + fprint(cl_stderr,"\n"#c" = "); \ + fprint(cl_stderr,c); \ + fprint(cl_stderr,"\n"); \ + error = 1; \ + } + +#define ASSERT4(expr,a,b,c,d) \ + if (!(expr)) { \ + fprint(cl_stderr,"Assertion failed! File "); \ + fprint(cl_stderr,__FILE__); \ + fprint(cl_stderr,", line "); \ + fprintdecimal(cl_stderr,__LINE__); \ + fprint(cl_stderr,".\n"); \ + fprint(cl_stderr,#a" = "); \ + fprint(cl_stderr,a); \ + fprint(cl_stderr,"\n"#b" = "); \ + fprint(cl_stderr,b); \ + fprint(cl_stderr,"\n"#c" = "); \ + fprint(cl_stderr,c); \ + fprint(cl_stderr,"\n"#d" = "); \ + fprint(cl_stderr,d); \ + fprint(cl_stderr,"\n"); \ + error = 1; \ + } + diff --git a/tests/test_I.cc b/tests/test_I.cc new file mode 100644 index 0000000..06dc83b --- /dev/null +++ b/tests/test_I.cc @@ -0,0 +1,100 @@ +#include + +// Elementary operations. +extern int test_I_abs (int iterations); +extern int test_I_compare (int iterations); +extern int test_I_plus (int iterations); +extern int test_I_minus (int iterations); +extern int test_I_plus1 (int iterations); +extern int test_I_minus1 (int iterations); +extern int test_I_mul (int iterations); +extern int test_I_div (int iterations); +// Euclidean ring operations. +extern int test_I_gcd (int iterations); +extern int test_I_xgcd (int iterations); +// Bit vector operations. +extern int test_I_ash (int iterations); +extern int test_I_evenp (int iterations); +extern int test_I_oddp (int iterations); +extern int test_I_lognot (int iterations); +extern int test_I_logand (int iterations); +extern int test_I_logandc1 (int iterations); +extern int test_I_logandc2 (int iterations); +extern int test_I_logior (int iterations); +extern int test_I_logorc1 (int iterations); +extern int test_I_logorc2 (int iterations); +extern int test_I_logxor (int iterations); +extern int test_I_lognand (int iterations); +extern int test_I_lognor (int iterations); +extern int test_I_logeqv (int iterations); +extern int test_I_boole (int iterations); +extern int test_I_logbitp (int iterations); +extern int test_I_logtest (int iterations); +extern int test_I_ldb (int iterations); +extern int test_I_ldb_test (int iterations); +extern int test_I_mask_field (int iterations); +extern int test_I_dpb (int iterations); +extern int test_I_deposit_field (int iterations); +extern int test_I_logcount (int iterations); +extern int test_I_integer_length (int iterations); +extern int test_I_ord2 (int iterations); +extern int test_I_power2p (int iterations); +// More complex operations. +extern int test_I_isqrt (int iterations); +extern int test_I_sqrtp (int iterations); +// Miscellaneous. +extern int test_I_GV (int iterations); + +#define RUN(tester,iterations) \ + fprint(cl_stdout,"Testing "#tester"...\n"); \ + error |= tester (iterations); + +int test_I (int iterations) +{ + int error = 0; + // Elementary operations. + RUN(test_I_abs,iterations); + RUN(test_I_compare,iterations); + RUN(test_I_plus,iterations); + RUN(test_I_minus,iterations); + RUN(test_I_plus1,iterations); + RUN(test_I_minus1,iterations); + RUN(test_I_mul,iterations); + RUN(test_I_div,iterations); + // Euclidean ring operations. + RUN(test_I_gcd,iterations); + RUN(test_I_xgcd,iterations); + // Bit vector operations. + RUN(test_I_ash,iterations); + RUN(test_I_evenp,iterations); + RUN(test_I_oddp,iterations); + RUN(test_I_lognot,iterations); + RUN(test_I_logand,iterations); + RUN(test_I_logandc1,iterations); + RUN(test_I_logandc2,iterations); + RUN(test_I_logior,iterations); + RUN(test_I_logorc1,iterations); + RUN(test_I_logorc2,iterations); + RUN(test_I_logxor,iterations); + RUN(test_I_lognand,iterations); + RUN(test_I_lognor,iterations); + RUN(test_I_logeqv,iterations); + RUN(test_I_boole,iterations); + RUN(test_I_logbitp,iterations); + RUN(test_I_logtest,iterations); + RUN(test_I_ldb,iterations); + RUN(test_I_ldb_test,iterations); + RUN(test_I_mask_field,iterations); + RUN(test_I_dpb,iterations); + RUN(test_I_deposit_field,iterations); + RUN(test_I_logcount,iterations); + RUN(test_I_integer_length,iterations); + RUN(test_I_ord2,iterations); + RUN(test_I_power2p,iterations); + // More complex operations. + RUN(test_I_isqrt,iterations); + RUN(test_I_sqrtp,iterations); + // Miscellaneous. + RUN(test_I_GV,iterations); + return error; +} diff --git a/tests/test_I.h b/tests/test_I.h new file mode 100644 index 0000000..26d08f6 --- /dev/null +++ b/tests/test_I.h @@ -0,0 +1,4 @@ +#include +#include +#include "test.h" + diff --git a/tests/test_I_GV.cc b/tests/test_I_GV.cc new file mode 100644 index 0000000..cfb3185 --- /dev/null +++ b/tests/test_I_GV.cc @@ -0,0 +1,25 @@ +#include "test_I.h" +#include "cl_GV_integer.h" + +int test_I_GV (int iterations) +{ + int error = 0; + int i; + for (i = iterations; i > 0; i--) { + uintL m = random32() % 70; + uintL len = random32() % 64; + cl_GV_I v = cl_GV_I(len,m); + cl_I M = random_I((cl_I)1 << m) + 1; // 0 < M <= 2^m + cl_I a = random_I(M); + int j; + for (j = 0; j < len; j++) + v[j] = mod(a*(j*j),M); + for (j = len-1; j >= 0; j--) +#if !(defined(__GNUC__) && (__GNUC_MINOR__ < 8)) + ASSERT4(v[j] == mod(a*(j*j),M), m,len,M,j); +#else // work around g++ 2.7.2 bug + ASSERT4(v[j] == mod(a*(j*j),M), (cl_I)m,(cl_I)len,M,(cl_I)j); +#endif + } + return error; +} diff --git a/tests/test_I_abs.cc b/tests/test_I_abs.cc new file mode 100644 index 0000000..3247098 --- /dev/null +++ b/tests/test_I_abs.cc @@ -0,0 +1,13 @@ +#include "test_I.h" + +int test_I_abs (int iterations) +{ + int error = 0; + int i; + // Check against "-". + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + ASSERT1(abs(a) == (a < 0 ? -a : a), a); + } + return error; +} diff --git a/tests/test_I_ash.cc b/tests/test_I_ash.cc new file mode 100644 index 0000000..a7299e3 --- /dev/null +++ b/tests/test_I_ash.cc @@ -0,0 +1,36 @@ +#include "test_I.h" + +int test_I_ash (int iterations) +{ + int error = 0; + int i; + // Check against "*" and floor1. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + uintL b = random32() % 1024; + cl_I pow2 = 1; + for (uintL j = 0; j < b; j++) + pow2 = pow2+pow2; + ASSERT1(ash(1,(sintL)b) == pow2, b); + ASSERT1(ash(1,(cl_I)b) == pow2, b); + ASSERT2(ash(a,(sintL)b) == a*pow2, a,b); + ASSERT2(ash(a,-(sintL)b) == floor1(a,pow2), a,b); + } + // Check homomorphism w.r.t. second argument. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + sintL b = random32() % 1024; + sintL c = random32() % 1024; + ASSERT3(ash(ash(a,b),c) == ash(a,b+c), a,b,c); + ASSERT3(ash(ash(a,b),-c) == ash(a,b-c), a,b,c); + ASSERT3(ash(ash(a,-b),-c) == ash(a,-b-c), a,b,c); + } + // Check against each other. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + uintL b = random32() % 1024; + ASSERT2(ash(a,(cl_I)b) == ash(a,(sintL)b), a,b); + ASSERT2(ash(a,-(cl_I)b) == ash(a,-(sintL)b), a,b); + } + return error; +} diff --git a/tests/test_I_boole.cc b/tests/test_I_boole.cc new file mode 100644 index 0000000..bc09488 --- /dev/null +++ b/tests/test_I_boole.cc @@ -0,0 +1,28 @@ +#include "test_I.h" + +int test_I_boole (int iterations) +{ + int error = 0; + int i; + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + ASSERT2(boole(boole_clr,a,b) == 0, a,b); + ASSERT2(boole(boole_set,a,b) == -1, a,b); + ASSERT2(boole(boole_1,a,b) == a, a,b); + ASSERT2(boole(boole_2,a,b) == b, a,b); + ASSERT2(boole(boole_c1,a,b) == lognot(a), a,b); + ASSERT2(boole(boole_c2,a,b) == lognot(b), a,b); + ASSERT2(boole(boole_and,a,b) == logand(a,b), a,b); + ASSERT2(boole(boole_ior,a,b) == logior(a,b), a,b); + ASSERT2(boole(boole_xor,a,b) == logxor(a,b), a,b); + ASSERT2(boole(boole_eqv,a,b) == logeqv(a,b), a,b); + ASSERT2(boole(boole_nand,a,b) == lognand(a,b), a,b); + ASSERT2(boole(boole_nor,a,b) == lognor(a,b), a,b); + ASSERT2(boole(boole_andc1,a,b) == logandc1(a,b), a,b); + ASSERT2(boole(boole_andc2,a,b) == logandc2(a,b), a,b); + ASSERT2(boole(boole_orc1,a,b) == logorc1(a,b), a,b); + ASSERT2(boole(boole_orc2,a,b) == logorc2(a,b), a,b); + } + return error; +} diff --git a/tests/test_I_compare.cc b/tests/test_I_compare.cc new file mode 100644 index 0000000..cd530d3 --- /dev/null +++ b/tests/test_I_compare.cc @@ -0,0 +1,21 @@ +#include "test_I.h" + +int test_I_compare (int iterations) +{ + int error = 0; + int i; + // Check anticommutativity. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + ASSERT2(cl_compare(a,b) == -cl_compare(b,a), a,b); + } + // Check a < b <==> a+c < b+c . + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + cl_I c = testrandom_I(); + ASSERT3(cl_compare(a,b) == cl_compare(a+c,b+c), a,b,c); + } + return error; +} diff --git a/tests/test_I_div.cc b/tests/test_I_div.cc new file mode 100644 index 0000000..d4e1b33 --- /dev/null +++ b/tests/test_I_div.cc @@ -0,0 +1,67 @@ +#include "test_I.h" + +int test_I_div (int iterations) +{ + int error = 0; + int i; + // Check floor. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + if (b != 0) { + cl_I_div_t qr = floor2(a,b); + const cl_I& q = qr.quotient; + const cl_I& r = qr.remainder; + ASSERT2(a == q*b+r, a,b); + ASSERT2(b >= 0 ? (r >= 0 && r < b) : (r <= 0 && r > b), a,b); + } + } + // Check ceiling. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + if (b != 0) { + cl_I_div_t qr = ceiling2(a,b); + const cl_I& q = qr.quotient; + const cl_I& r = qr.remainder; + ASSERT2(a == q*b+r, a,b); + ASSERT2(b >= 0 ? (r <= 0 && r > -b) : (r >= 0 && r < -b), a,b); + } + } + // Check truncate. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + if (b != 0) { + cl_I_div_t qr = truncate2(a,b); + const cl_I& q = qr.quotient; + const cl_I& r = qr.remainder; + ASSERT2(a == q*b+r, a,b); + if (b >= 0) + if (a >= 0) + { ASSERT2(r >= 0 && r < b, a,b); } + else + { ASSERT2(r <= 0 && r > -b, a,b); } + else + if (a >= 0) + { ASSERT2(r >= 0 && r < -b, a,b); } + else + { ASSERT2(r <= 0 && r > b, a,b); } + } + } + // Check round. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + if (b != 0) { + cl_I_div_t qr = round2(a,b); + const cl_I& q = qr.quotient; + const cl_I& r = qr.remainder; + ASSERT2(a == q*b+r, a,b); + ASSERT2(2*abs(r) <= abs(b), a,b); + if (2*abs(r) == abs(b)) + ASSERT2(evenp(q), a,b); + } + } + return error; +} diff --git a/tests/test_I_dpb.cc b/tests/test_I_dpb.cc new file mode 100644 index 0000000..61e2d15 --- /dev/null +++ b/tests/test_I_dpb.cc @@ -0,0 +1,17 @@ +#include "test_I.h" + +int test_I_dpb (int iterations) +{ + int error = 0; + int i; + // Check against ash. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + sintL s = random32() % 1024; + sintL p = random32() % 1024; + cl_I mask = ash(ash(1,s)-1,p); + ASSERT4(dpb(a,b,cl_byte(s,p)) == logxor(logand(ash(a,p),mask),logandc2(b,mask)), a,s,p,b); + } + return error; +} diff --git a/tests/test_I_dpf.cc b/tests/test_I_dpf.cc new file mode 100644 index 0000000..c03fd4c --- /dev/null +++ b/tests/test_I_dpf.cc @@ -0,0 +1,17 @@ +#include "test_I.h" + +int test_I_deposit_field (int iterations) +{ + int error = 0; + int i; + // Check against ash. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + sintL s = random32() % 1024; + sintL p = random32() % 1024; + cl_I mask = ash(ash(1,s)-1,p); + ASSERT4(deposit_field(a,b,cl_byte(s,p)) == logxor(logand(a,mask),logandc2(b,mask)), a,s,p,b); + } + return error; +} diff --git a/tests/test_I_evenp.cc b/tests/test_I_evenp.cc new file mode 100644 index 0000000..0df9c51 --- /dev/null +++ b/tests/test_I_evenp.cc @@ -0,0 +1,14 @@ +#include "test_I.h" + +int test_I_evenp (int iterations) +{ + int error = 0; + int i; + // Check against division. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I r = mod(a,2); + ASSERT1(evenp(a) == (r==0), a); + } + return error; +} diff --git a/tests/test_I_gcd.cc b/tests/test_I_gcd.cc new file mode 100644 index 0000000..e7872c8 --- /dev/null +++ b/tests/test_I_gcd.cc @@ -0,0 +1,27 @@ +#include "test_I.h" + +int test_I_gcd (int iterations) +{ + int error = 0; + int i; + // Check commutativity. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + ASSERT2(gcd(a,b) == gcd(b,a), a,b); + } + // Check some axioms. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + cl_I g = gcd(a,b); + if (g > 1) { + ASSERT2(mod(a,g) == 0, a,b); + ASSERT2(mod(b,g) == 0, a,b); + ASSERT2(gcd(exquo(a,g),exquo(b,g)) == 1, a,b); + } + cl_I c = testrandom_I(); + ASSERT3(gcd(a+b*c,b) == g, a,b,c); + } + return error; +} diff --git a/tests/test_I_ilength.cc b/tests/test_I_ilength.cc new file mode 100644 index 0000000..0332c55 --- /dev/null +++ b/tests/test_I_ilength.cc @@ -0,0 +1,40 @@ +#include "test_I.h" + +int test_I_integer_length (int iterations) +{ + int error = 0; + int i; + // Check against ash. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + uintL l = integer_length(a); + if (a >= 0) { +#if !(defined(__GNUC__) && (__GNUC_MINOR__ < 8)) + ASSERT1(a < ash(1,l) && (a == 0 ? l == 0 : l > 0 && a >= ash(1,l-1)), a); +#else // work around g++ 2.7.0 bug + int b = 0; + if (a < ash(1,l)) { + if (a == 0) + b = (l == 0); + else + b = (l > 0 && a >= ash(1,l-1)); + } + ASSERT1(b, a); +#endif + } else { +#if !(defined(__GNUC__) && (__GNUC_MINOR__ < 8)) + ASSERT1(a >= ash(-1,l) && (a == -1 ? l == 0 : l > 0 && a < ash(-1,l-1)), a); +#else // work around g++ 2.7.0 bug + int b = 0; + if (a >= ash(-1,l)) { + if (a == -1) + b = (l == 0); + else + b = (l > 0 && a < ash(-1,l-1)); + } + ASSERT1(b, a); +#endif + } + } + return error; +} diff --git a/tests/test_I_isqrt.cc b/tests/test_I_isqrt.cc new file mode 100644 index 0000000..6813b76 --- /dev/null +++ b/tests/test_I_isqrt.cc @@ -0,0 +1,29 @@ +#include "test_I.h" + +int test_I_isqrt (int iterations) +{ + int error = 0; + int i; + // Check against "*". + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + if (a >= 0) { + cl_I w; + cl_boolean squarep = isqrt(a,&w); + ASSERT1(w >= 0 && expt_pos(w,2) <= a && a < expt_pos(w+1,2), a); + ASSERT1(squarep ? w*w==a : w*w 0; i--) { + cl_I a = abs(testrandom_I()); + cl_I w; + // Check a^2 is a square. + ASSERT1(isqrt(a*a,&w) && w == a, a); + // Check a^2+1 is not a square, except when a=0. + ASSERT1((a==0) || (!isqrt(a*a+1,&w) && w == a), a); + // Check a^2+2*a is not a square, except when a=0. + ASSERT1(isqrt(a*(a+2),&w)==(a==0) && w == a, a); + } + return error; +} diff --git a/tests/test_I_ldb.cc b/tests/test_I_ldb.cc new file mode 100644 index 0000000..ef91836 --- /dev/null +++ b/tests/test_I_ldb.cc @@ -0,0 +1,15 @@ +#include "test_I.h" + +int test_I_ldb (int iterations) +{ + int error = 0; + int i; + // Check against ash. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + sintL s = random32() % 1024; + sintL p = random32() % 1024; + ASSERT3(ldb(a,cl_byte(s,p)) == logand(ash(a,-p),ash(1,s)-1), a,s,p); + } + return error; +} diff --git a/tests/test_I_ldbtest.cc b/tests/test_I_ldbtest.cc new file mode 100644 index 0000000..0a2f5d5 --- /dev/null +++ b/tests/test_I_ldbtest.cc @@ -0,0 +1,15 @@ +#include "test_I.h" + +int test_I_ldb_test (int iterations) +{ + int error = 0; + int i; + // Check against ash. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + sintL s = random32() % 1024; + sintL p = random32() % 1024; + ASSERT3(ldb_test(a,cl_byte(s,p)) == logtest(ash(a,-p),ash(1,s)-1), a,s,p); + } + return error; +} diff --git a/tests/test_I_logand.cc b/tests/test_I_logand.cc new file mode 100644 index 0000000..df9d8f8 --- /dev/null +++ b/tests/test_I_logand.cc @@ -0,0 +1,23 @@ +#include "test_I.h" + +int test_I_logand (int iterations) +{ + int error = 0; + int i; + // Check commutativity. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + ASSERT2(logand(a,b) == logand(b,a), a,b); + } + // Check against ash and oddp. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + ASSERT2(oddp(logand(a,b)) == (oddp(a) & oddp(b)), a,b); + sintL c = random32() % 1024; + ASSERT3(logand(ash(a,c),ash(b,c)) == ash(logand(a,b),c), a,b,c); + ASSERT3(logand(ash(a,-c),ash(b,-c)) == ash(logand(a,b),-c), a,b,c); + } + return error; +} diff --git a/tests/test_I_logandc1.cc b/tests/test_I_logandc1.cc new file mode 100644 index 0000000..5c3f1ae --- /dev/null +++ b/tests/test_I_logandc1.cc @@ -0,0 +1,14 @@ +#include "test_I.h" + +int test_I_logandc1 (int iterations) +{ + int error = 0; + int i; + // Check against logand. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + ASSERT2(logandc1(a,b) == logand(lognot(a),b), a,b); + } + return error; +} diff --git a/tests/test_I_logandc2.cc b/tests/test_I_logandc2.cc new file mode 100644 index 0000000..636fe53 --- /dev/null +++ b/tests/test_I_logandc2.cc @@ -0,0 +1,14 @@ +#include "test_I.h" + +int test_I_logandc2 (int iterations) +{ + int error = 0; + int i; + // Check against logand. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + ASSERT2(logandc2(a,b) == logand(a,lognot(b)), a,b); + } + return error; +} diff --git a/tests/test_I_logbitp.cc b/tests/test_I_logbitp.cc new file mode 100644 index 0000000..7d4d561 --- /dev/null +++ b/tests/test_I_logbitp.cc @@ -0,0 +1,26 @@ +#include "test_I.h" + +int test_I_logbitp (int iterations) +{ + int error = 0; + int i; + // Check against ash and oddp. + for (i = iterations; i > 0; i--) { + uintL a = random32() % 1024; + cl_I b = testrandom_I(); + ASSERT2(logbitp(a,b) == oddp(ash(b,-(sintL)a)), a,b); + } + // Check against ash and logand. + for (i = iterations; i > 0; i--) { + uintL a = random32() % 1024; + cl_I b = testrandom_I(); + ASSERT2(logbitp(a,b) == !zerop(logand(b,ash(1,(sintL)a))), a,b); + } + // Check against each other. + for (i = iterations; i > 0; i--) { + uintL a = random32() % 1024; + cl_I b = testrandom_I(); + ASSERT2(logbitp((cl_I)a,b) == logbitp(a,b), a,b); + } + return error; +} diff --git a/tests/test_I_logcount.cc b/tests/test_I_logcount.cc new file mode 100644 index 0000000..0471533 --- /dev/null +++ b/tests/test_I_logcount.cc @@ -0,0 +1,26 @@ +#include "test_I.h" + +int test_I_logcount (int iterations) +{ + int error = 0; + int i; + // Check additivity. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + if (a >= 0 && b >= 0) + ASSERT2(logcount(a) == logcount(logand(a,b)) + logcount(logandc2(a,b)), a,b); + } + // Check behaviour on sign change. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + ASSERT1(logcount(lognot(a)) == logcount(a), a); + } + // Check shift invariance. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + sintL b = random32() % 1024; + ASSERT2(logcount(ash(a,b)) == logcount(a) + (minusp(a) ? b : 0), a,b); + } + return error; +} diff --git a/tests/test_I_logeqv.cc b/tests/test_I_logeqv.cc new file mode 100644 index 0000000..f79e943 --- /dev/null +++ b/tests/test_I_logeqv.cc @@ -0,0 +1,14 @@ +#include "test_I.h" + +int test_I_logeqv (int iterations) +{ + int error = 0; + int i; + // Check against logxor. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + ASSERT2(logeqv(a,b) == lognot(logxor(a,b)), a,b); + } + return error; +} diff --git a/tests/test_I_logior.cc b/tests/test_I_logior.cc new file mode 100644 index 0000000..140f8b1 --- /dev/null +++ b/tests/test_I_logior.cc @@ -0,0 +1,24 @@ +#include "test_I.h" + +int test_I_logior (int iterations) +{ + int error = 0; + int i; + // Check commutativity. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + ASSERT2(logior(a,b) == logior(b,a), a,b); + } + // Check against ash and oddp. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + ASSERT2(oddp(logior(a,b)) == (oddp(a) | oddp(b)), a,b); + sintL c = random32() % 1024; + ASSERT3(logior(ash(a,c),ash(b,c)) == ash(logior(a,b),c), a,b,c); + ASSERT3(logior(ash(a,-c),ash(b,-c)) == ash(logior(a,b),-c), a,b,c); + } + + return error; +} diff --git a/tests/test_I_lognand.cc b/tests/test_I_lognand.cc new file mode 100644 index 0000000..e6c26ab --- /dev/null +++ b/tests/test_I_lognand.cc @@ -0,0 +1,14 @@ +#include "test_I.h" + +int test_I_lognand (int iterations) +{ + int error = 0; + int i; + // Check against logand. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + ASSERT2(lognand(a,b) == lognot(logand(a,b)), a,b); + } + return error; +} diff --git a/tests/test_I_lognor.cc b/tests/test_I_lognor.cc new file mode 100644 index 0000000..2d3e858 --- /dev/null +++ b/tests/test_I_lognor.cc @@ -0,0 +1,14 @@ +#include "test_I.h" + +int test_I_lognor (int iterations) +{ + int error = 0; + int i; + // Check against logior. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + ASSERT2(lognor(a,b) == lognot(logior(a,b)), a,b); + } + return error; +} diff --git a/tests/test_I_lognot.cc b/tests/test_I_lognot.cc new file mode 100644 index 0000000..9ede552 --- /dev/null +++ b/tests/test_I_lognot.cc @@ -0,0 +1,18 @@ +#include "test_I.h" + +int test_I_lognot (int iterations) +{ + int error = 0; + int i; + // Check involution, sign, and against "+". + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = lognot(a); + ASSERT1(lognot(b) == a, a); + ASSERT1(minusp(a) != minusp(b), a); + ASSERT1(a+b == -1, a); + } + // Check special cases 0 and -1. + ASSERT(lognot(0) == -1); + return error; +} diff --git a/tests/test_I_logorc1.cc b/tests/test_I_logorc1.cc new file mode 100644 index 0000000..202d278 --- /dev/null +++ b/tests/test_I_logorc1.cc @@ -0,0 +1,14 @@ +#include "test_I.h" + +int test_I_logorc1 (int iterations) +{ + int error = 0; + int i; + // Check against logior. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + ASSERT2(logorc1(a,b) == logior(lognot(a),b), a,b); + } + return error; +} diff --git a/tests/test_I_logorc2.cc b/tests/test_I_logorc2.cc new file mode 100644 index 0000000..6fe1b09 --- /dev/null +++ b/tests/test_I_logorc2.cc @@ -0,0 +1,14 @@ +#include "test_I.h" + +int test_I_logorc2 (int iterations) +{ + int error = 0; + int i; + // Check against logior. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + ASSERT2(logorc2(a,b) == logior(a,lognot(b)), a,b); + } + return error; +} diff --git a/tests/test_I_logtest.cc b/tests/test_I_logtest.cc new file mode 100644 index 0000000..341c645 --- /dev/null +++ b/tests/test_I_logtest.cc @@ -0,0 +1,33 @@ +#include "test_I.h" + +int test_I_logtest (int iterations) +{ + int error = 0; + int i; + // Check commutativity. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + ASSERT2(logtest(a,b) == logtest(b,a), a,b); + } + // Check some axioms. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + ASSERT2(!logtest(a,logand(b,lognot(a))), a,b); + ASSERT2(!logtest(logand(b,lognot(a)),a), a,b); + ASSERT2(!logtest(b,logand(a,lognot(b))), a,b); + ASSERT2(!logtest(logand(a,lognot(b)),b), a,b); + if (a != 0) + ASSERT2(logtest(a,logior(a,b)), a,b); + if (b != 0) + ASSERT2(logtest(b,logior(a,b)), a,b); + } + // Check some special cases, against ash and logbitp. + for (i = iterations; i > 0; i--) { + uintL a = random32() % 1024; + cl_I b = testrandom_I(); + ASSERT2(logbitp(a,b) == logtest(b,ash(1,(sintL)a)), a,b); + } + return error; +} diff --git a/tests/test_I_logxor.cc b/tests/test_I_logxor.cc new file mode 100644 index 0000000..ed0ad53 --- /dev/null +++ b/tests/test_I_logxor.cc @@ -0,0 +1,29 @@ +#include "test_I.h" + +int test_I_logxor (int iterations) +{ + int error = 0; + int i; + // Check commutativity. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + ASSERT2(logxor(a,b) == logxor(b,a), a,b); + } + // Check associativity. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + cl_I c = testrandom_I(); + ASSERT3(logxor(logxor(a,b),c) == logxor(a,logxor(b,c)), a,b,c); + } + // Check special cases 0 and -1. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + ASSERT1(logxor(a,0) == a, a); + ASSERT1(logxor(a,a) == 0, a); + ASSERT1(logxor(a,-1) == lognot(a), a); + ASSERT1(logxor(a,lognot(a)) == -1, a); + } + return error; +} diff --git a/tests/test_I_minus.cc b/tests/test_I_minus.cc new file mode 100644 index 0000000..566b5d5 --- /dev/null +++ b/tests/test_I_minus.cc @@ -0,0 +1,27 @@ +#include "test_I.h" + +int test_I_minus (int iterations) +{ + int error = 0; + int i; + // Check anti-commutativity. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + ASSERT2((a-b) + (b-a) == 0, a,b); + } + // Check associativity. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + cl_I c = testrandom_I(); + ASSERT3(a-(b-c) == c-(b-a), a,b,c); + } + // Check special case 0. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + ASSERT1(a-0 == a, a); + ASSERT1(0-(0-a) == a, a); + } + return error; +} diff --git a/tests/test_I_minus1.cc b/tests/test_I_minus1.cc new file mode 100644 index 0000000..d770f31 --- /dev/null +++ b/tests/test_I_minus1.cc @@ -0,0 +1,13 @@ +#include "test_I.h" + +int test_I_minus1 (int iterations) +{ + int error = 0; + int i; + // Check against "+". + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + ASSERT1(minus1(a) == -1+a, a); + } + return error; +} diff --git a/tests/test_I_mkf.cc b/tests/test_I_mkf.cc new file mode 100644 index 0000000..d36d36a --- /dev/null +++ b/tests/test_I_mkf.cc @@ -0,0 +1,15 @@ +#include "test_I.h" + +int test_I_mask_field (int iterations) +{ + int error = 0; + int i; + // Check against ash. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + sintL s = random32() % 1024; + sintL p = random32() % 1024; + ASSERT3(mask_field(a,cl_byte(s,p)) == logand(a,ash(ash(1,s)-1,p)), a,s,p); + } + return error; +} diff --git a/tests/test_I_mul.cc b/tests/test_I_mul.cc new file mode 100644 index 0000000..df04354 --- /dev/null +++ b/tests/test_I_mul.cc @@ -0,0 +1,41 @@ +#include "test_I.h" + +int test_I_mul (int iterations) +{ + int error = 0; + int i; + // Check commutativity. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + ASSERT2(a*b == b*a, a,b); + } + // Check associativity. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + cl_I c = testrandom_I(); + ASSERT3((a*b)*c == a*(b*c), a,b,c); + } + // Check second binomial formula. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + ASSERT2((a+b)*(a-b) == a*a-b*b, a,b); + } + // Check distributive formula. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + cl_I c = testrandom_I(); + ASSERT3((a+c)*(b+c) == a*b+(a+b)*c+c*c, a,b,c); + } + // Check special cases 0, 1, -1. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + ASSERT1(a*0 == 0, a); + ASSERT1(a*1 == a, a); + ASSERT1(a*-1 == -a, a); + } + return error; +} diff --git a/tests/test_I_oddp.cc b/tests/test_I_oddp.cc new file mode 100644 index 0000000..ccd3b72 --- /dev/null +++ b/tests/test_I_oddp.cc @@ -0,0 +1,14 @@ +#include "test_I.h" + +int test_I_oddp (int iterations) +{ + int error = 0; + int i; + // Check against division. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I r = mod(a,2); + ASSERT1(oddp(a) == (r!=0), a); + } + return error; +} diff --git a/tests/test_I_ord2.cc b/tests/test_I_ord2.cc new file mode 100644 index 0000000..b4c1bd4 --- /dev/null +++ b/tests/test_I_ord2.cc @@ -0,0 +1,18 @@ +#include "test_I.h" + +int test_I_ord2 (int iterations) +{ + int error = 0; + int i; + // Check against ash and oddp. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + if (a != 0) { + uintL n = ord2(a); + cl_I b = ash(a,-(sintL)n); + ASSERT1(oddp(b), a); + ASSERT1(a == ash(b,(sintL)n), a); + } + } + return error; +} diff --git a/tests/test_I_plus.cc b/tests/test_I_plus.cc new file mode 100644 index 0000000..ed9b901 --- /dev/null +++ b/tests/test_I_plus.cc @@ -0,0 +1,26 @@ +#include "test_I.h" + +int test_I_plus (int iterations) +{ + int error = 0; + int i; + // Check commutativity. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + ASSERT2(a+b == b+a, a,b); + } + // Check associativity. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + cl_I c = testrandom_I(); + ASSERT3((a+b)+c == a+(b+c), a,b,c); + } + // Check special case 0. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + ASSERT1(a+0 == a, a); + } + return error; +} diff --git a/tests/test_I_plus1.cc b/tests/test_I_plus1.cc new file mode 100644 index 0000000..76cb73a --- /dev/null +++ b/tests/test_I_plus1.cc @@ -0,0 +1,13 @@ +#include "test_I.h" + +int test_I_plus1 (int iterations) +{ + int error = 0; + int i; + // Check against "+". + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + ASSERT1(plus1(a) == 1+a, a); + } + return error; +} diff --git a/tests/test_I_power2p.cc b/tests/test_I_power2p.cc new file mode 100644 index 0000000..146f73c --- /dev/null +++ b/tests/test_I_power2p.cc @@ -0,0 +1,20 @@ +#include "test_I.h" + +int test_I_power2p (int iterations) +{ + int error = 0; + int i; + // Check powers of 2. + for (i = iterations; i > 0; i--) { + uintL n = random32() % 1024; + cl_I a = ash(1,n); + ASSERT1(power2p(a) == n+1, n); + } + // Check against logcount. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + if (a > 0) + ASSERT1(power2p(a) == (logcount(a) == 1 ? integer_length(a) : 0), a); + } + return error; +} diff --git a/tests/test_I_sqrtp.cc b/tests/test_I_sqrtp.cc new file mode 100644 index 0000000..cc70dcf --- /dev/null +++ b/tests/test_I_sqrtp.cc @@ -0,0 +1,33 @@ +#include "test_I.h" +#define floor(a,b) ((a) / (b)) + +int test_I_sqrtp (int iterations) +{ + int error = 0; + int i; + // Check against isqrt. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + if (a >= 0) { + cl_I w; + cl_boolean squarep = sqrtp(a,&w); + cl_I correct_w; + cl_boolean correct_squarep = isqrt(a,&correct_w); + ASSERT1(squarep == correct_squarep, a); + if (squarep) + ASSERT1(w == correct_w, a); + } + } + // Check certain special cases. + for (i = iterations; i > 0; i--) { + cl_I a = abs(testrandom_I()); + cl_I w; + // Check a^2 is a square. + ASSERT1(sqrtp(a*a,&w) && w == a, a); + // Check a^2+1 is not a square, except when a=0. + if (a > 0) ASSERT1(!isqrt(a*a+1,&w) && w == a, a); + // Check a^2+2*a is not a square, except when a=0. + ASSERT1(isqrt(a*(a+2),&w)==(a==0) && w == a, a); + } + return error; +} diff --git a/tests/test_I_xgcd.cc b/tests/test_I_xgcd.cc new file mode 100644 index 0000000..cfdeb16 --- /dev/null +++ b/tests/test_I_xgcd.cc @@ -0,0 +1,31 @@ +#include "test_I.h" + +int test_I_xgcd (int iterations) +{ + int error = 0; + int i; + // Check against gcd. + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b = testrandom_I(); + cl_I u, v; + cl_I g = xgcd(a,b,&u,&v); + ASSERT3(g == gcd(a,b), a,b,g); + ASSERT4(g == u*a+v*b, a,b,u,v); + if (a != 0 && b != 0) { + if (abs(a) == abs(b)) { + ASSERT4((u == signum(a) && v == 0) || (u == 0 && v == signum(b)), a,b,u,v); + } + else if (mod(abs(a),abs(b)) == 0) { + ASSERT4(u == 0 && v == signum(b), a,b,u,v); + } + else if (mod(abs(b),abs(a)) == 0) { + ASSERT4(u == signum(a) && v == 0, a,b,u,v); + } + else { + ASSERT4(abs(u) <= floor1(abs(b),2*g) && abs(v) <= floor1(abs(a),2*g), a,b,u,v); + } + } + } + return error; +} diff --git a/tests/test_MI.cc b/tests/test_MI.cc new file mode 100644 index 0000000..6ae77f6 --- /dev/null +++ b/tests/test_MI.cc @@ -0,0 +1,27 @@ +#include +#include "cl_macros.h" + +extern int test_MI_canonhom (int iterations); +extern int test_MI_plus (int iterations); +extern int test_MI_minus (int iterations); +extern int test_MI_mul (int iterations); +extern int test_MI_recip (int iterations); +extern int test_MI_div (int iterations); +extern int test_MI_expt (int iterations); + +#define RUN(tester,iterations) \ + fprint(cl_stdout,"Testing "#tester"...\n"); \ + error |= tester (iterations); + +int test_MI (int iterations) +{ + int error = 0; + RUN(test_MI_canonhom,iterations); + RUN(test_MI_plus,iterations); + RUN(test_MI_minus,iterations); + RUN(test_MI_mul,iterations); + RUN(test_MI_recip,iterations); + RUN(test_MI_div,iterations); + RUN(test_MI_expt,ceiling(iterations,20)); + return error; +} diff --git a/tests/test_MI.h b/tests/test_MI.h new file mode 100644 index 0000000..f4a8337 --- /dev/null +++ b/tests/test_MI.h @@ -0,0 +1,5 @@ +#include +#include +#include +#include "test.h" + diff --git a/tests/test_MI_canonhom.cc b/tests/test_MI_canonhom.cc new file mode 100644 index 0000000..5fd2b97 --- /dev/null +++ b/tests/test_MI_canonhom.cc @@ -0,0 +1,15 @@ +#include "test_MI.h" + +int test_MI_canonhom (int iterations) +{ + int error = 0; + int i; + // Check canonhom followed by retract. + for (i = iterations; i > 0; i--) { + cl_I m = testrandom_I(); + cl_modint_ring R = cl_find_modint_ring(m); + cl_I a = testrandom_I(); + ASSERT2(R->retract(R->canonhom(a)) == (m==0 ? a : mod(a,abs(m))), m,a); + } + return error; +} diff --git a/tests/test_MI_div.cc b/tests/test_MI_div.cc new file mode 100644 index 0000000..fb64be2 --- /dev/null +++ b/tests/test_MI_div.cc @@ -0,0 +1,19 @@ +#include "test_MI.h" + +int test_MI_div (int iterations) +{ + int error = 0; + int i; + // Check against multiplication. + for (i = iterations; i > 0; i--) { + cl_I m = testrandom_I(); + cl_modint_ring R = cl_find_modint_ring(m); + cl_I ai = testrandom_I(); + if (gcd(m,ai)==1) { + cl_MI a = R->canonhom(ai); + cl_MI b = R->canonhom(testrandom_I()); + ASSERT3(a*R->div(b,a) == b, m,a,b); + } + } + return error; +} diff --git a/tests/test_MI_expt.cc b/tests/test_MI_expt.cc new file mode 100644 index 0000000..c976d14 --- /dev/null +++ b/tests/test_MI_expt.cc @@ -0,0 +1,52 @@ +#include "test_MI.h" + +int test_MI_expt (int iterations) +{ + int error = 0; + int i; + // Check special cases 0, 1, 2. + for (i = iterations; i > 0; i--) { + cl_I m = testrandom_I(); + cl_modint_ring R = cl_find_modint_ring(m); + cl_MI a = R->canonhom(testrandom_I()); + ASSERT2(expt(a,0) == R->one(), m,a); + ASSERT2(expt(a,1) == a, m,a); + ASSERT2(expt(a,2) == a*a, m,a); + } + // Check special cases -1, -2. + for (i = iterations; i > 0; i--) { + cl_I m = testrandom_I(); + cl_modint_ring R = cl_find_modint_ring(m); + cl_I ai = testrandom_I(); + if (gcd(m,ai)==1) { + cl_MI a = R->canonhom(ai); + cl_MI ar = R->recip(a); + ASSERT2(expt(a,-1) == ar, m,a); + ASSERT2(expt(a,-2) == ar*ar, m,a); + } + } + // Check homomorphism (fixed exponent). + for (i = iterations; i > 0; i--) { + cl_I m = testrandom_I(); + if (!zerop(m)) { // avoid generating huge numbers + cl_modint_ring R = cl_find_modint_ring(m); + cl_MI a = R->canonhom(testrandom_I()); + cl_MI b = R->canonhom(testrandom_I()); + cl_I e = abs(testrandom_I()); + ASSERT4(expt(a,e)*expt(b,e) == expt(a*b,e), m,a,b,e); + } + } + // Check distributive formulas (fixed base). + for (i = iterations; i > 0; i--) { + cl_I m = testrandom_I(); + if (!zerop(m)) { // avoid generating huge numbers + cl_modint_ring R = cl_find_modint_ring(m); + cl_MI a = R->canonhom(testrandom_I()); + cl_I e = abs(testrandom_I()); + cl_I f = abs(testrandom_I()); + ASSERT4(expt(a,e)*expt(a,f) == expt(a,e+f), m,a,e,f); + ASSERT4(expt(expt(a,e),f) == expt(a,e*f), m,a,e,f); + } + } + return error; +} diff --git a/tests/test_MI_minus.cc b/tests/test_MI_minus.cc new file mode 100644 index 0000000..7694f0f --- /dev/null +++ b/tests/test_MI_minus.cc @@ -0,0 +1,35 @@ +#include "test_MI.h" + +int test_MI_minus (int iterations) +{ + int error = 0; + int i; + // Check anti-commutativity. + for (i = iterations; i > 0; i--) { + cl_I m = testrandom_I(); + cl_modint_ring R = cl_find_modint_ring(m); + cl_MI a = R->canonhom(testrandom_I()); + cl_MI b = R->canonhom(testrandom_I()); + cl_MI z = R->zero(); + ASSERT3((a-b) + (b-a) == z, m,a,b); + } + // Check associativity. + for (i = iterations; i > 0; i--) { + cl_I m = testrandom_I(); + cl_modint_ring R = cl_find_modint_ring(m); + cl_MI a = R->canonhom(testrandom_I()); + cl_MI b = R->canonhom(testrandom_I()); + cl_MI c = R->canonhom(testrandom_I()); + ASSERT4(a-(b-c) == c-(b-a), m,a,b,c); + } + // Check special case 0. + for (i = iterations; i > 0; i--) { + cl_I m = testrandom_I(); + cl_modint_ring R = cl_find_modint_ring(m); + cl_MI a = R->canonhom(testrandom_I()); + cl_MI z = R->zero(); + ASSERT2(a-z == a, m,a); + ASSERT2(z-(z-a) == a, m,a); + } + return error; +} diff --git a/tests/test_MI_mul.cc b/tests/test_MI_mul.cc new file mode 100644 index 0000000..0b733b8 --- /dev/null +++ b/tests/test_MI_mul.cc @@ -0,0 +1,54 @@ +#include "test_MI.h" + +int test_MI_mul (int iterations) +{ + int error = 0; + int i; + // Check commutativity. + for (i = iterations; i > 0; i--) { + cl_I m = testrandom_I(); + cl_modint_ring R = cl_find_modint_ring(m); + cl_MI a = R->canonhom(testrandom_I()); + cl_MI b = R->canonhom(testrandom_I()); + ASSERT3(a*b == b*a, m,a,b); + } + // Check associativity. + for (i = iterations; i > 0; i--) { + cl_I m = testrandom_I(); + cl_modint_ring R = cl_find_modint_ring(m); + cl_MI a = R->canonhom(testrandom_I()); + cl_MI b = R->canonhom(testrandom_I()); + cl_MI c = R->canonhom(testrandom_I()); + ASSERT4((a*b)*c == a*(b*c), m,a,b,c); + } + // Check second binomial formula. + for (i = iterations; i > 0; i--) { + cl_I m = testrandom_I(); + cl_modint_ring R = cl_find_modint_ring(m); + cl_MI a = R->canonhom(testrandom_I()); + cl_MI b = R->canonhom(testrandom_I()); + ASSERT3((a+b)*(a-b) == a*a-b*b, m,a,b); + } + // Check distributive formula. + for (i = iterations; i > 0; i--) { + cl_I m = testrandom_I(); + cl_modint_ring R = cl_find_modint_ring(m); + cl_MI a = R->canonhom(testrandom_I()); + cl_MI b = R->canonhom(testrandom_I()); + cl_MI c = R->canonhom(testrandom_I()); + ASSERT4((a+c)*(b+c) == a*b+(a+b)*c+c*c, m,a,b,c); + } + // Check special cases 0, 1, -1. + for (i = iterations; i > 0; i--) { + cl_I m = testrandom_I(); + cl_modint_ring R = cl_find_modint_ring(m); + cl_MI a = R->canonhom(testrandom_I()); + cl_MI z = R->zero(); + cl_MI o = R->one(); + cl_MI mo = R->canonhom(-1); + ASSERT2(a*z == z, m,a); + ASSERT2(a*o == a, m,a); + ASSERT2(a*mo == -a, m,a); + } + return error; +} diff --git a/tests/test_MI_plus.cc b/tests/test_MI_plus.cc new file mode 100644 index 0000000..492bf18 --- /dev/null +++ b/tests/test_MI_plus.cc @@ -0,0 +1,33 @@ +#include "test_MI.h" + +int test_MI_plus (int iterations) +{ + int error = 0; + int i; + // Check commutativity. + for (i = iterations; i > 0; i--) { + cl_I m = testrandom_I(); + cl_modint_ring R = cl_find_modint_ring(m); + cl_MI a = R->canonhom(testrandom_I()); + cl_MI b = R->canonhom(testrandom_I()); + ASSERT3(a+b == b+a, m,a,b); + } + // Check associativity. + for (i = iterations; i > 0; i--) { + cl_I m = testrandom_I(); + cl_modint_ring R = cl_find_modint_ring(m); + cl_MI a = R->canonhom(testrandom_I()); + cl_MI b = R->canonhom(testrandom_I()); + cl_MI c = R->canonhom(testrandom_I()); + ASSERT4((a+b)+c == a+(b+c), m,a,b,c); + } + // Check special case 0. + for (i = iterations; i > 0; i--) { + cl_I m = testrandom_I(); + cl_modint_ring R = cl_find_modint_ring(m); + cl_MI a = R->canonhom(testrandom_I()); + cl_MI z = R->zero(); + ASSERT2(a+z == a, m,a); + } + return error; +} diff --git a/tests/test_MI_recip.cc b/tests/test_MI_recip.cc new file mode 100644 index 0000000..7c02fac --- /dev/null +++ b/tests/test_MI_recip.cc @@ -0,0 +1,18 @@ +#include "test_MI.h" + +int test_MI_recip (int iterations) +{ + int error = 0; + int i; + // Check against multiplication. + for (i = iterations; i > 0; i--) { + cl_I m = testrandom_I(); + cl_modint_ring R = cl_find_modint_ring(m); + cl_I ai = testrandom_I(); + if (gcd(m,ai)==1) { + cl_MI a = R->canonhom(ai); + ASSERT2(a*R->recip(a) == R->one(), m,a); + } + } + return error; +} diff --git a/tests/test_nt.cc b/tests/test_nt.cc new file mode 100644 index 0000000..51f1496 --- /dev/null +++ b/tests/test_nt.cc @@ -0,0 +1,14 @@ +#include + +extern int test_nt_jacobi (int iterations); + +#define RUN(tester,iterations) \ + fprint(cl_stdout,"Testing "#tester"...\n"); \ + error |= tester (iterations); + +int test_nt (int iterations) +{ + int error = 0; + RUN(test_nt_jacobi,iterations); + return error; +} diff --git a/tests/test_nt.h b/tests/test_nt.h new file mode 100644 index 0000000..425abba --- /dev/null +++ b/tests/test_nt.h @@ -0,0 +1,5 @@ +#include +#include +#include +#include "test.h" + diff --git a/tests/test_nt_jacobi.cc b/tests/test_nt_jacobi.cc new file mode 100644 index 0000000..cde1f32 --- /dev/null +++ b/tests/test_nt_jacobi.cc @@ -0,0 +1,56 @@ +#include "test_nt.h" + +int test_nt_jacobi (int iterations) +{ + int error = 0; + int i; + // Check special cases. + for (i = iterations; i > 0; i--) { + cl_I b = 1+2*abs(testrandom_I()); + cl_I c = testrandom_I(); + if (b==1) { + ASSERT2(jacobi(b*c,b) == 1, b,c); + } else { + ASSERT2(jacobi(b*c,b) == 0, b,c); + } + } + for (i = iterations; i > 0; i--) { + cl_I b = 1+2*abs(testrandom_I()); + if (mod(b,4)==1) { + ASSERT1(jacobi(-1,b) == 1, b); + } else { + ASSERT1(jacobi(-1,b) == -1, b); + } + if (abs(mod(b,8)-4)==1) { + ASSERT1(jacobi(2,b) == -1, b); + } else { + ASSERT1(jacobi(2,b) == 1, b); + } + } + // Check quadratic residues. + for (i = iterations; i > 0; i--) { + cl_I b = 1+2*abs(testrandom_I()); + cl_I c = testrandom_I(); + cl_I a = mod(square(c),b); + if (gcd(a,b)==1) { + ASSERT2(jacobi(a,b) == 1, b,c); + } else { + ASSERT2(jacobi(a,b) == 0, b,c); + } + } + // Check homomorphism (fixed b). + for (i = iterations; i > 0; i--) { + cl_I b = 1+2*abs(testrandom_I()); + cl_I a1 = testrandom_I(); + cl_I a2 = testrandom_I(); + ASSERT3(jacobi(a1,b)*jacobi(a2,b) == jacobi(a1*a2,b), b,a1,a2); + } + // Check homomorphism (fixed a). + for (i = iterations; i > 0; i--) { + cl_I a = testrandom_I(); + cl_I b1 = 1+2*abs(testrandom_I()); + cl_I b2 = 1+2*abs(testrandom_I()); + ASSERT3(jacobi(a,b1)*jacobi(a,b2) == jacobi(a,b1*b2), a,b1,b2); + } + return error; +} diff --git a/tests/tests.cc b/tests/tests.cc new file mode 100644 index 0000000..29a9573 --- /dev/null +++ b/tests/tests.cc @@ -0,0 +1,35 @@ +#include +#include +#include + +extern int test_I (int iterations); +extern int test_MI (int iterations); +extern int test_nt (int iterations); + +int test_all (int iterations) +{ + int error = 0; + error |= test_I(iterations); + error |= test_MI(iterations); + error |= test_nt(iterations); + return error; +} + +int main (int argc, char* argv[]) +{ + int iterations = 10000; + if ((argc >= 3) && !strcmp(argv[1],"-i")) { + iterations = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 1) + exit(1); + + if (!test_all(iterations)) { + fprint (cl_stdout, "Tests passed.\n"); + exit(0); + } else { + fprint (cl_stdout, "Tests failed.\n"); + exit(1); + } +} diff --git a/tests/timeLFRAmul.cc b/tests/timeLFRAmul.cc new file mode 100644 index 0000000..11f7cea --- /dev/null +++ b/tests/timeLFRAmul.cc @@ -0,0 +1,44 @@ +#include +#include +#include +#include +#include "cl_LF.h" +#include +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 4) + exit(1); + uintL m1 = atoi(argv[1]); + cl_I m2 = cl_I(argv[2]); + cl_I M2 = (cl_I)1 << (intDsize*m2); + cl_I m3 = cl_I(argv[3]); + cl_I M3 = (cl_I)1 << (intDsize*m3); + cl_LF x = The(cl_LF)(random_F(cl_I_to_LF(1,m1))); + cl_I u; + cl_I v; + do { u = random_I(M2); } while (zerop(u)); + do { v = random_I(M3); } while (zerop(v) || gcd(u,v) > 1); + cl_RA y = u / v; + cl_F p; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = cl_LF_I_div(The(cl_LF)(cl_LF_I_mul(x,u)),v); } + } + cout << p << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = x * cl_RA_to_LF(y,TheLfloat(x)->len); } + } + cout << p << endl; +} diff --git a/tests/timeLFatan-compare.cc b/tests/timeLFatan-compare.cc new file mode 100644 index 0000000..2667507 --- /dev/null +++ b/tests/timeLFatan-compare.cc @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include "cl_LF.h" +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 3) + exit(1); + extern double cl_atanx_factor; + extern int cl_atan_algo; + uintL len = atoi(argv[1]); + cl_atanx_factor = atof(argv[2]); +#if 0 + cl_LF one = cl_I_to_LF(1,len); + cl_F x = scale_float(random_F(one),-1); + cout << x << endl; +#else + cl_F x = sqrt(cl_I_to_LF(2,len))-1; +#endif + cl_F y; + cl_atan_algo = 0; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { y = atan(x); } + } + cout << y << endl; + cl_atan_algo = 1; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { y = atan(x); } + } + cout << y << endl; +} diff --git a/tests/timeLFatan.cc b/tests/timeLFatan.cc new file mode 100644 index 0000000..d4d58a8 --- /dev/null +++ b/tests/timeLFatan.cc @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include +#include "cl_LF.h" +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); + extern int cl_atan_algo; + uintL len = atoi(argv[1]); +#if 0 + cl_LF one = cl_I_to_LF(1,len); + cl_F x = scale_float(random_F(one),-1); + cout << x << endl; +#else + cl_F x = sqrt(cl_I_to_LF(2,len))-1; +#endif + cl_F y; +#if 0 + cl_atan_algo = 0; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { y = atan(x); } + } + cout << y << endl; + cl_atan_algo = 1; +#endif + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { y = atan(x); } + } + cout << y << endl; +} diff --git a/tests/timeLFatanh-compare.cc b/tests/timeLFatanh-compare.cc new file mode 100644 index 0000000..847c13b --- /dev/null +++ b/tests/timeLFatanh-compare.cc @@ -0,0 +1,47 @@ +#include +#include +#include +#include +#include "cl_LF.h" +#include +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 3) + exit(1); + extern double cl_atanhx_factor; + extern int cl_atanh_algo; + uintL len = atoi(argv[1]); + cl_atanhx_factor = atof(argv[2]); +#if 0 + cl_LF one = cl_I_to_LF(1,len); + cl_F x = scale_float(random_F(one),-1); + cout << x << endl; +#else + cl_F x = sqrt(cl_I_to_LF(2,len))-1; +#endif + cl_N y; + ln(cl_I_to_LF(1000,len+10)); // fill cache + cl_atanh_algo = 0; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { y = atanh(x); } + } + cout << y << endl; + cl_atanh_algo = 1; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { y = atanh(x); } + } + cout << y << endl; +} diff --git a/tests/timeLFatanh.cc b/tests/timeLFatanh.cc new file mode 100644 index 0000000..8e6a826 --- /dev/null +++ b/tests/timeLFatanh.cc @@ -0,0 +1,43 @@ +#include +#include +#include +#include +#include "cl_LF.h" +#include +#include +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); + uintL len = atoi(argv[1]); +#if 0 + cl_LF one = cl_I_to_LF(1,len); + cl_F x = scale_float(random_F(one),-1); + cout << x << endl; +#else + cl_F x = sqrt(cl_I_to_LF(2,len))-1; +#endif + cl_N y; + ln(cl_I_to_LF(1000,len+10)); // fill cache + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { y = atanh(x); } + } + cout << y << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { y = ln((1+x)/(1-x))/2; } + } + cout << y << endl; +} diff --git a/tests/timeLFcos-compare.cc b/tests/timeLFcos-compare.cc new file mode 100644 index 0000000..d7b7f49 --- /dev/null +++ b/tests/timeLFcos-compare.cc @@ -0,0 +1,43 @@ +#include +#include +#include +#include +#include "cl_LF.h" +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); + extern int cl_cos_algo; + uintL len = atoi(argv[1]); +#if 0 + cl_LF one = cl_I_to_LF(1,len); + cl_F x = scale_float(random_F(one),-1); + cout << x << endl; +#else + cl_F x = sqrt(cl_I_to_LF(2,len))-1; +#endif + cl_F y; + cl_cos_algo = 0; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { y = cos(x); } + } + cout << y << endl; + cl_cos_algo = 1; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { y = cos(x); } + } + cout << y << endl; +} diff --git a/tests/timeLFcos.cc b/tests/timeLFcos.cc new file mode 100644 index 0000000..9e21d1a --- /dev/null +++ b/tests/timeLFcos.cc @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include +#include "cl_LF.h" +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); + extern int cl_cos_algo; + uintL len = atoi(argv[1]); +#if 0 + cl_LF one = cl_I_to_LF(1,len); + cl_F x = scale_float(random_F(one),-1); + cout << x << endl; +#else + cl_F x = sqrt(cl_I_to_LF(2,len))-1; +#endif + cl_F y; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { y = cos(x); } + } + cout << y << endl; +} diff --git a/tests/timeLFcosh.cc b/tests/timeLFcosh.cc new file mode 100644 index 0000000..8c1eb91 --- /dev/null +++ b/tests/timeLFcosh.cc @@ -0,0 +1,47 @@ +#include +#include +#include +#include +#include +#include "cl_LF.h" +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); + extern int cl_cosh_algo; + uintL len = atoi(argv[1]); +#if 0 + cl_LF one = cl_I_to_LF(1,len); + cl_F x = scale_float(random_F(one),-1); + cout << x << endl; +#else + cl_F x = sqrt(cl_I_to_LF(2,len))-1; +#endif + cl_F y; + y = exp(x); // fill cache +#if 0 + cl_cosh_algo = 0; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { y = cosh(x); } + } + cout << y << endl; + cl_cosh_algo = 1; +#endif + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { y = cosh(x); } + } + cout << y << endl; +} diff --git a/tests/timeLFexp-compare.cc b/tests/timeLFexp-compare.cc new file mode 100644 index 0000000..6678909 --- /dev/null +++ b/tests/timeLFexp-compare.cc @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include "cl_LF.h" +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 3) + exit(1); + extern double cl_exp_factor; + extern int cl_exp_algo; + uintL len = atoi(argv[1]); + cl_exp_factor = atof(argv[2]); +#if 0 + cl_LF one = cl_I_to_LF(1,len); + cl_F x = scale_float(random_F(one),-1); + cout << x << endl; +#else + cl_F x = sqrt(cl_I_to_LF(2,len))-1; +#endif + cl_F y; + cl_exp_algo = 0; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { y = exp(x); } + } +// cout << y << endl; + cl_exp_algo = 1; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { y = exp(x); } + } +// cout << y << endl; +} diff --git a/tests/timeLFexp.cc b/tests/timeLFexp.cc new file mode 100644 index 0000000..94b4c1c --- /dev/null +++ b/tests/timeLFexp.cc @@ -0,0 +1,47 @@ +#include +#include +#include +#include +#include +#include "cl_LF.h" +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); + uintL len = atoi(argv[1]); +#if 0 + cl_LF one = cl_I_to_LF(1,len); + cl_F x = scale_float(random_F(one),-1); + cout << x << endl; +#else + cl_F x = sqrt(cl_I_to_LF(2,len))-1; +#endif + cl_F y; + extern int cl_exp_algo; + y = exp(x); // fill cache +#if 0 + cl_exp_algo = 0; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { y = exp(x); } + } + cout << y << endl; + cl_exp_algo = 1; +#endif + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { y = exp(x); } + } + cout << y << endl; +} diff --git a/tests/timeLFln-compare.cc b/tests/timeLFln-compare.cc new file mode 100644 index 0000000..51df5c9 --- /dev/null +++ b/tests/timeLFln-compare.cc @@ -0,0 +1,44 @@ +#include +#include +#include +#include +#include "cl_LF.h" +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); + uintL len = atoi(argv[1]); +#if 0 + cl_LF one = cl_I_to_LF(1,len); + cl_F x = one + random_F(one)/3; + cout << x << endl; +#else + cl_F x = sqrt(sqrt(cl_I_to_LF(2,len))); +#endif + cl_F y; + extern int cl_lnx_algo; + cl_lnx_algo = 0; + y = ln(x); // fill cache + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { y = ln(x); } + } + cout << y << endl; + cl_lnx_algo = 1; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { y = ln(x); } + } + cout << y << endl; +} diff --git a/tests/timeLFln.cc b/tests/timeLFln.cc new file mode 100644 index 0000000..315500c --- /dev/null +++ b/tests/timeLFln.cc @@ -0,0 +1,47 @@ +#include +#include +#include +#include +#include +#include "cl_LF.h" +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); + uintL len = atoi(argv[1]); +#if 0 + cl_LF one = cl_I_to_LF(1,len); + cl_F x = one + random_F(one)/3; + cout << x << endl; +#else + cl_F x = sqrt(sqrt(cl_I_to_LF(2,len))); +#endif + cl_F y; + extern int cl_lnx_algo; + y = ln(x); // fill cache +#if 0 + cl_lnx_algo = 0; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { y = ln(x); } + } + cout << y << endl; + cl_lnx_algo = 1; +#endif + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { y = ln(x); } + } + cout << y << endl; +} diff --git a/tests/timeLFsin-compare.cc b/tests/timeLFsin-compare.cc new file mode 100644 index 0000000..ab1d32d --- /dev/null +++ b/tests/timeLFsin-compare.cc @@ -0,0 +1,52 @@ +#include +#include +#include +#include +#include "cl_LF.h" +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 3) + exit(1); + extern double cl_sin_factor; + extern int cl_sin_algo; + extern int cl_aux_algo; + uintL len = atoi(argv[1]); + cl_sin_factor = atof(argv[2]); +#if 0 + cl_LF one = cl_I_to_LF(1,len); + cl_F x = scale_float(random_F(one),-1); + cout << x << endl; +#else + cl_F x = sqrt(cl_I_to_LF(2,len))-1; +#endif + cl_F y; + cl_sin_algo = 0; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { y = sin(x); } + } + cout << y << endl; + cl_sin_algo = 1; cl_aux_algo = 0; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { y = sin(x); } + } + cout << y << endl; + cl_sin_algo = 1; cl_aux_algo = 1; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { y = sin(x); } + } + cout << y << endl; +} diff --git a/tests/timeLFsin.cc b/tests/timeLFsin.cc new file mode 100644 index 0000000..451963a --- /dev/null +++ b/tests/timeLFsin.cc @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include +#include "cl_LF.h" +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); + extern int cl_sin_algo; + uintL len = atoi(argv[1]); +#if 0 + cl_LF one = cl_I_to_LF(1,len); + cl_F x = scale_float(random_F(one),-1); + cout << x << endl; +#else + cl_F x = sqrt(cl_I_to_LF(2,len))-1; +#endif + cl_F y; +#if 0 + cl_sin_algo = 0; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { y = sin(x); } + } + cout << y << endl; + cl_sin_algo = 1; +#endif + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { y = sin(x); } + } + cout << y << endl; +} diff --git a/tests/timeLFsinh.cc b/tests/timeLFsinh.cc new file mode 100644 index 0000000..5dcbac1 --- /dev/null +++ b/tests/timeLFsinh.cc @@ -0,0 +1,52 @@ +#include +#include +#include +#include +#include +#include "cl_LF.h" +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); + extern int cl_sinh_algo; + uintL len = atoi(argv[1]); +#if 0 + cl_LF one = cl_I_to_LF(1,len); + cl_F x = scale_float(random_F(one),-1); + cout << x << endl; +#else + cl_F x = sqrt(cl_I_to_LF(2,len))-1; +#endif + cl_F y; + y = exp(x); // fill cache +#if 0 + cl_sinh_algo = 0; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { y = sinh(x); } + } + cout << y << endl; + cl_sinh_algo = 1; +#endif + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { y = sinh(x); } + } + cout << y << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { y = exp(x); y = (y-recip(y))/2; } + } + cout << y << endl; +} diff --git a/tests/timeLFsqrt.cc b/tests/timeLFsqrt.cc new file mode 100644 index 0000000..5e22e84 --- /dev/null +++ b/tests/timeLFsqrt.cc @@ -0,0 +1,31 @@ +#include +#include +#include +#include +#include +#include "cl_LF.h" +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); + uintL len = atoi(argv[1]); + cl_LF one = cl_I_to_LF(1,len); + cl_F x = random_F(one); + cl_F y; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { y = sqrt(x); } + } + cout << y << endl; +} diff --git a/tests/timeMImisc5.cc b/tests/timeMImisc5.cc new file mode 100644 index 0000000..36e8134 --- /dev/null +++ b/tests/timeMImisc5.cc @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 1) + exit(1); + cl_I p = "1269281897404513557783934075031171555202695168107"; + cl_modint_ring R = cl_find_modint_ring(p); + { + cl_MI a = R->canonhom("1111111111111111111111111111111111111111111111111"); + cl_MI b = R->canonhom("777777777777777777777777777777777777777777777777"); + cl_stdout << "product modulo p" << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_MI c = R->mul(a,b); } + } + cl_stdout << "square modulo p" << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_MI c = R->square(a); } + } + cl_stdout << "quotient modulo p" << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_MI c = R->div(a,b); } + } + } + { + cl_MI a = R->canonhom("1234567890123456789012345678901234567890123456789"); + cl_MI b = R->canonhom("909090909090909090909090909090909090909090909090"); + cl_stdout << "product modulo p" << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_MI c = R->mul(a,b); } + } + cl_stdout << "square modulo p" << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_MI c = R->square(a); } + } + cl_stdout << "quotient modulo p" << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_MI c = R->div(a,b); } + } + } +} diff --git a/tests/timeMIpow2div.cc b/tests/timeMIpow2div.cc new file mode 100644 index 0000000..54c36a9 --- /dev/null +++ b/tests/timeMIpow2div.cc @@ -0,0 +1,27 @@ +#include +#include +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); + uintL len = atoi(argv[1]); + cl_modint_ring R = cl_find_modint_ring((cl_I)1 << (intDsize*len)); + cl_MI a = R->random(); + cl_MI b; + do { b = R->random(); } while (!oddp(R->retract(b))); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_MI c = R->div(a,b); } + } +} diff --git a/tests/timeMIpow2recip.cc b/tests/timeMIpow2recip.cc new file mode 100644 index 0000000..c5972ee --- /dev/null +++ b/tests/timeMIpow2recip.cc @@ -0,0 +1,26 @@ +#include +#include +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); + uintL len = atoi(argv[1]); + cl_modint_ring R = cl_find_modint_ring((cl_I)1 << (intDsize*len)); + cl_MI a; + do { a = R->random(); } while (!oddp(R->retract(a))); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_MI b = R->recip(a); } + } +} diff --git a/tests/timeRALFdiv.cc b/tests/timeRALFdiv.cc new file mode 100644 index 0000000..84cd86e --- /dev/null +++ b/tests/timeRALFdiv.cc @@ -0,0 +1,44 @@ +#include +#include +#include +#include +#include "cl_LF.h" +#include +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 4) + exit(1); + cl_I m1 = cl_I(argv[1]); + cl_I M1 = (cl_I)1 << (intDsize*m1); + cl_I m2 = cl_I(argv[2]); + cl_I M2 = (cl_I)1 << (intDsize*m2); + uintL m3 = atoi(argv[1]); + cl_I u; + cl_I v; + do { u = random_I(M1); } while (zerop(u)); + do { v = random_I(M2); } while (zerop(v) || gcd(u,v) > 1); + cl_RA x = u / v; + cl_LF y = The(cl_LF)(random_F(cl_I_to_LF(1,m3))); + cl_F p; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = The(cl_LF)(cl_I_LF_div(u,The(cl_LF)(cl_LF_I_mul(y,v)))); } + } + cout << p << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = cl_RA_to_LF(x,TheLfloat(y)->len) / y; } + } + cout << p << endl; +} diff --git a/tests/timeRAtoLF.cc b/tests/timeRAtoLF.cc new file mode 100644 index 0000000..70bf671 --- /dev/null +++ b/tests/timeRAtoLF.cc @@ -0,0 +1,43 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 4) + exit(1); + uintL m1 = atoi(argv[1]); + cl_I m2 = cl_I(argv[2]); + cl_I M2 = (cl_I)1 << (intDsize*m2); + cl_I m3 = cl_I(argv[3]); + cl_I M3 = (cl_I)1 << (intDsize*m3); + cl_float_format_t M1 = (cl_float_format_t)(m1*intDsize); + cl_I u; + cl_I v; + do { u = random_I(M2); } while (zerop(u)); + do { v = random_I(M3); } while (zerop(v) || gcd(u,v) > 1); + cl_RA y = u / v; + cl_F p; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = cl_float(u,M1)/cl_float(v,M1); } + } + cout << p << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = cl_float(y,M1); } + } + cout << p << endl; +} diff --git a/tests/timeUPMImul.cc b/tests/timeUPMImul.cc new file mode 100644 index 0000000..d26dcf9 --- /dev/null +++ b/tests/timeUPMImul.cc @@ -0,0 +1,52 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); + + int n = atoi(argv[1]); + cl_I m = 100001; + int i; + + cl_modint_ring R1 = cl_find_modint_ring(m); + cl_univpoly_ring PR1 = cl_find_univpoly_ring(R1); + cl_UP p1 = PR1->create(n-1); + for (i = 0; i < n; i++) + p1.set_coeff(i, R1->canonhom((int)(1.618033989*i*i))); + p1.finalize(); + + cl_stdout << p1 << endl; + + cl_UP sp1 = PR1->zero(); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { sp1 = square(p1); } + } + + cl_stdout << sp1 << endl; +} + +// Time: +// n modint modint2 neu +// 2 0.000123 0.000082 0.000086 +// 5 0.00051 0.00031 0.00032 +// 10 0.00169 0.00095 0.00100 +// 25 0.0089 0.0049 0.0053 +// 50 0.031 0.018 0.020 +// 100 0.118 0.070 0.079 +// 250 0.72 0.43 0.48 +// 500 2.87 1.76 1.91 +// 1000 11.4 7.0 8.0 diff --git a/tests/timecatalan.cc b/tests/timecatalan.cc new file mode 100644 index 0000000..840990a --- /dev/null +++ b/tests/timecatalan.cc @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "cl_LF.h" + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); + uintL len = atoi(argv[1]); + extern cl_LF compute_catalanconst_ramanujan (uintC len); + extern cl_LF compute_catalanconst_ramanujan_fast (uintC len); + extern cl_LF compute_catalanconst_expintegral1 (uintC len); + extern cl_LF compute_catalanconst_expintegral2 (uintC len); + extern cl_LF compute_catalanconst_cvz1 (uintC len); + extern cl_LF compute_catalanconst_cvz2 (uintC len); + cl_LF p; + ln(cl_I_to_LF(1000,len+10)); // fill cache + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = compute_catalanconst_ramanujan(len); } + } + cout << p << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = compute_catalanconst_ramanujan_fast(len); } + } + cout << p << endl; +#if 0 + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = compute_catalanconst_expintegral1(len); } + } + cout << p << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = compute_catalanconst_expintegral2(len); } + } + cout << p << endl; +#endif + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = compute_catalanconst_cvz1(len); } + } + cout << p << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = compute_catalanconst_cvz2(len); } + } + cout << p << endl; +} diff --git a/tests/timediv.cc b/tests/timediv.cc new file mode 100644 index 0000000..a2431ee --- /dev/null +++ b/tests/timediv.cc @@ -0,0 +1,35 @@ +#include +#include +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); + cl_I m1; + cl_I m2; + if (argc > 2) { + m1 = cl_I(argv[1]); + m2 = cl_I(argv[2]); + } else { + m2 = cl_I(argv[1]); + m1 = 2*m2; + } + cl_I M1 = (cl_I)1 << (intDsize*m1); + cl_I M2 = (cl_I)1 << (intDsize*m2); + cl_I a = random_I(M1); + cl_I b = random_I(M2); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_I_div_t qr = floor2(a,b); } + } +} diff --git a/tests/timediv2adic-compare.cc b/tests/timediv2adic-compare.cc new file mode 100644 index 0000000..de1aeeb --- /dev/null +++ b/tests/timediv2adic-compare.cc @@ -0,0 +1,60 @@ +#include +#include +#include +#include "cl_DS.h" +#include "cl_2DS.h" +#include +#include "cl_random_impl.h" +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 3) + exit(1); + uintL a_len = atoi(argv[1]); + uintL b_len = atoi(argv[2]); + if (!(a_len >= b_len && b_len > 0)) + exit(1); + SAVE_NUM_STACK; + uintD* a_MSDptr; + uintD* a_LSDptr; + uintD* b_MSDptr; + uintD* b_LSDptr; + uintD* q_MSDptr; + uintD* q_LSDptr; + uintD* q1_MSDptr; + uintD* q1_LSDptr; + num_stack_alloc(a_len,a_MSDptr=,a_LSDptr=); + num_stack_alloc(b_len,b_MSDptr=,b_LSDptr=); + num_stack_alloc(a_len,q_MSDptr=,q_LSDptr=); + num_stack_alloc(a_len,q1_MSDptr=,q1_LSDptr=); + random_UDS(cl_default_random_state,a_MSDptr,a_len); + random_UDS(cl_default_random_state,b_MSDptr,b_len); + lspref(b_LSDptr,0) |= 1; // force b to be odd + extern int div2adic_algo; + // Check. + div2adic_algo = 0; + div2adic(a_len,a_LSDptr,b_len,b_LSDptr,q_LSDptr); + div2adic_algo = 1; + div2adic(a_len,a_LSDptr,b_len,b_LSDptr,q1_LSDptr); + if (compare_loop_msp(q_MSDptr,q1_MSDptr,a_len)) cl_abort(); + // Time. + div2adic_algo = 0; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { div2adic(a_len,a_LSDptr,b_len,b_LSDptr,q_LSDptr); } + } + div2adic_algo = 1; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { div2adic(a_len,a_LSDptr,b_len,b_LSDptr,q_LSDptr); } + } +} diff --git a/tests/timediv2adic.cc b/tests/timediv2adic.cc new file mode 100644 index 0000000..a944574 --- /dev/null +++ b/tests/timediv2adic.cc @@ -0,0 +1,46 @@ +#include +#include +#include +#include "cl_DS.h" +#include "cl_2DS.h" +#include +#include "cl_random_impl.h" +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 3) + exit(1); + uintL a_len = atoi(argv[1]); + uintL b_len = atoi(argv[2]); + if (!(a_len >= b_len && b_len > 0)) + exit(1); + SAVE_NUM_STACK; + uintD* a_MSDptr; + uintD* a_LSDptr; + uintD* b_MSDptr; + uintD* b_LSDptr; + uintD* q_MSDptr; + uintD* q_LSDptr; + uintD* q1_MSDptr; + uintD* q1_LSDptr; + num_stack_alloc(a_len,a_MSDptr=,a_LSDptr=); + num_stack_alloc(b_len,b_MSDptr=,b_LSDptr=); + num_stack_alloc(a_len,q_MSDptr=,q_LSDptr=); + num_stack_alloc(a_len,q1_MSDptr=,q1_LSDptr=); + random_UDS(cl_default_random_state,a_MSDptr,a_len); + random_UDS(cl_default_random_state,b_MSDptr,b_len); + lspref(b_LSDptr,0) |= 1; // force b to be odd + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { div2adic(a_len,a_LSDptr,b_len,b_LSDptr,q_LSDptr); } + } +} diff --git a/tests/timeeuler.cc b/tests/timeeuler.cc new file mode 100644 index 0000000..712f588 --- /dev/null +++ b/tests/timeeuler.cc @@ -0,0 +1,77 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "cl_LF.h" + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); + uintL len = atoi(argv[1]); + extern cl_LF compute_eulerconst (uintC len); + extern cl_LF compute_eulerconst_expintegral (uintC len); + extern cl_LF compute_eulerconst_expintegral1 (uintC len); + extern cl_LF compute_eulerconst_expintegral2 (uintC len); + extern cl_LF compute_eulerconst_besselintegral1 (uintC len); + extern cl_LF compute_eulerconst_besselintegral2 (uintC len); + extern cl_LF compute_eulerconst_besselintegral3 (uintC len); + extern cl_LF compute_eulerconst_besselintegral4 (uintC len); + cl_LF p; + ln(cl_I_to_LF(1000,len+10)); // fill cache +#if 0 + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = compute_eulerconst(len); } + } +#else +#if 0 + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = compute_eulerconst_expintegral(len); } + } +// cout << p << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = compute_eulerconst_expintegral1(len); } + } +// cout << p << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = compute_eulerconst_expintegral2(len); } + } +// cout << p << endl; +#endif + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = compute_eulerconst_besselintegral1(len); } + } +// cout << p << endl; +#if 0 + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = compute_eulerconst_besselintegral2(len); } + } +// cout << p << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = compute_eulerconst_besselintegral3(len); } + } +// cout << p << endl; +#endif + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = compute_eulerconst_besselintegral4(len); } + } +// cout << p << endl; +#endif +} diff --git a/tests/timeexp1.cc b/tests/timeexp1.cc new file mode 100644 index 0000000..ca840f5 --- /dev/null +++ b/tests/timeexp1.cc @@ -0,0 +1,27 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); + uintL len = atoi(argv[1]); + extern cl_LF compute_exp1 (uintC len); + cl_LF p; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = compute_exp1(len); } + } +// cout << p << endl; +} diff --git a/tests/timefact.cc b/tests/timefact.cc new file mode 100644 index 0000000..78688b7 --- /dev/null +++ b/tests/timefact.cc @@ -0,0 +1,24 @@ +#include +#include +#include +#include +#include "cl_I.h" +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); + cl_I m = cl_I(argv[1]); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + cl_I f = factorial(FN_to_L(m)); + } +} diff --git a/tests/timegcd.cc b/tests/timegcd.cc new file mode 100644 index 0000000..a15dfd4 --- /dev/null +++ b/tests/timegcd.cc @@ -0,0 +1,29 @@ +#include +#include +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); + cl_I m1 = cl_I(argv[1]); + cl_I M1 = (cl_I)1 << (intDsize*m1); + cl_I m2 = (argc>2 ? cl_I(argv[2]) : m1); + cl_I M2 = (cl_I)1 << (intDsize*m2); + cl_I a = random_I(M1); + cl_I b = random_I(M2); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_I g = gcd(a,b); } +// { cl_I u; cl_I v; cl_I g = xgcd(a,b,&u,&v); } + } +} diff --git a/tests/timemul-compare.cc b/tests/timemul-compare.cc new file mode 100644 index 0000000..0939d7b --- /dev/null +++ b/tests/timemul-compare.cc @@ -0,0 +1,50 @@ +#include +#include +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); + cl_I m1 = cl_I(argv[1]); + cl_I M1 = (cl_I)1 << (intDsize*m1); + cl_I m2 = (argc>2 ? cl_I(argv[2]) : m1); + cl_I M2 = (cl_I)1 << (intDsize*m2); + cl_I a = random_I(M1); + cl_I b = random_I(M2); + extern int cl_mul_algo; + cl_mul_algo = 0; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_I p = a * b; } + } + cl_mul_algo = 1; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_I p = a * b; } + } + cl_mul_algo = 2; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_I p = a * b; } + } + cl_mul_algo = 3; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_I p = a * b; } + } + cl_mul_algo = 4; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_I p = a * b; } + } +} diff --git a/tests/timemul.cc b/tests/timemul.cc new file mode 100644 index 0000000..253d1e4 --- /dev/null +++ b/tests/timemul.cc @@ -0,0 +1,28 @@ +#include +#include +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); + cl_I m1 = cl_I(argv[1]); + cl_I M1 = (cl_I)1 << (intDsize*m1); + cl_I m2 = (argc>2 ? cl_I(argv[2]) : m1); + cl_I M2 = (cl_I)1 << (intDsize*m2); + cl_I a = random_I(M1); + cl_I b = random_I(M2); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_I p = a * b; } + } +} diff --git a/tests/timepi.cc b/tests/timepi.cc new file mode 100644 index 0000000..f2bdcbe --- /dev/null +++ b/tests/timepi.cc @@ -0,0 +1,57 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); +#if 0 + uintL len = atoi(argv[1]); + extern cl_LF compute_pi_brent_salamin (uintC len); + extern cl_LF compute_pi_brent_salamin_quartic (uintC len); + extern cl_LF compute_pi_ramanujan_163 (uintC len); + extern cl_LF compute_pi_ramanujan_163_fast (uintC len); + cl_LF p; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = compute_pi_brent_salamin(len); } + } +// cout << p << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = compute_pi_brent_salamin_quartic(len); } + } +// cout << p << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = compute_pi_ramanujan_163(len); } + } +// cout << p << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = compute_pi_ramanujan_163_fast(len); } + } +// cout << p << endl; +#else + // Here the argument is N *decimal* digits, not N*32 bits! + int n = atoi(argv[1]); + cl_float_format_t prec = cl_float_format(n); + cl_F p; + fprint(cl_stderr, "Computing pi\n"); + { CL_TIMING; p = cl_pi(prec); } + fprint(cl_stderr, "Converting pi to decimal\n"); + { CL_TIMING; cout << p << endl << endl; } +#endif +} diff --git a/tests/timepi.out2-i486 b/tests/timepi.out2-i486 new file mode 100644 index 0000000..bf98577 --- /dev/null +++ b/tests/timepi.out2-i486 @@ -0,0 +1,6 @@ +Computing pi +real time: 2967.085 s, run time: 2033.140 s +Converting pi to decimal +real time: 1073.538 s, run time: 929.310 s + +i486 33 MHz, 8 MB RAM, Linux 2.0 diff --git a/tests/timepi.out2-i586 b/tests/timepi.out2-i586 new file mode 100644 index 0000000..8f4878a --- /dev/null +++ b/tests/timepi.out2-i586 @@ -0,0 +1,6 @@ +Computing pi +real time: 373.802 s, run time: 371.240 s +Converting pi to decimal +real time: 204.513 s, run time: 184.210 s + +i586 120 MHz, 32 MB RAM, Linux 1.2 diff --git a/tests/timeprint-compare.cc b/tests/timeprint-compare.cc new file mode 100644 index 0000000..91cb703 --- /dev/null +++ b/tests/timeprint-compare.cc @@ -0,0 +1,44 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); + cl_I m = cl_I(argv[1]); + cl_I M = (cl_I)1 << (intDsize*m); + cl_I a = random_I(M); + extern int cl_digits_algo; + // One run to fill the cache. + { + char* p = (cl_digits_algo = 0, cl_decimal_string(a)); + char* q = (cl_digits_algo = 1, cl_decimal_string(a)); + if (strcmp(p,q)) cl_abort(); + cl_free_hook(p); + cl_free_hook(q); + } + // Now start the timing. + cl_digits_algo = 0; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { char* p = cl_decimal_string(a); cl_free_hook(p); } + } + cl_digits_algo = 1; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { char* p = cl_decimal_string(a); cl_free_hook(p); } + } +} diff --git a/tests/timeprint.cc b/tests/timeprint.cc new file mode 100644 index 0000000..b8774aa --- /dev/null +++ b/tests/timeprint.cc @@ -0,0 +1,34 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); + cl_I m = cl_I(argv[1]); + cl_I M = (cl_I)1 << (intDsize*m); + cl_I a = random_I(M); + // One run to fill the cache. + { + char* p = cl_decimal_string(a); + cl_free_hook(p); + } + // Now start the timing. + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { char* p = cl_decimal_string(a); cl_free_hook(p); } + } +} diff --git a/tests/timerecip2adic-compare.cc b/tests/timerecip2adic-compare.cc new file mode 100644 index 0000000..9d45328 --- /dev/null +++ b/tests/timerecip2adic-compare.cc @@ -0,0 +1,54 @@ +#include +#include +#include +#include "cl_DS.h" +#include "cl_2DS.h" +#include +#include "cl_random_impl.h" +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 3) + exit(1); + uintL len = atoi(argv[1]); + int threshold = atoi(argv[2]); + SAVE_NUM_STACK; + uintD* a_MSDptr; + uintD* a_LSDptr; + uintD* b_MSDptr; + uintD* b_LSDptr; + uintD* bn_MSDptr; + uintD* bn_LSDptr; + num_stack_alloc(len,a_MSDptr=,a_LSDptr=); + num_stack_alloc(len,b_MSDptr=,b_LSDptr=); + num_stack_alloc(len,bn_MSDptr=,bn_LSDptr=); + random_UDS(cl_default_random_state,a_MSDptr,len); + lspref(a_LSDptr,0) |= 1; // force a to be odd + extern int recip2adic_threshold; + // Check. + recip2adic_threshold = 1000000; + recip2adic(len,a_LSDptr,b_LSDptr); + recip2adic_threshold = threshold; + recip2adic(len,a_LSDptr,bn_LSDptr); + if (compare_loop_msp(b_MSDptr,bn_MSDptr,len)) cl_abort(); + // Time. + recip2adic_threshold = 1000000; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { recip2adic(len,a_LSDptr,b_LSDptr); } + } + recip2adic_threshold = threshold; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { recip2adic(len,a_LSDptr,b_LSDptr); } + } +} diff --git a/tests/timerecip2adic.cc b/tests/timerecip2adic.cc new file mode 100644 index 0000000..0006859 --- /dev/null +++ b/tests/timerecip2adic.cc @@ -0,0 +1,35 @@ +#include +#include +#include +#include "cl_DS.h" +#include "cl_2DS.h" +#include +#include "cl_random_impl.h" +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); + uintL len = atoi(argv[1]); + SAVE_NUM_STACK; + uintD* a_MSDptr; + uintD* a_LSDptr; + uintD* b_MSDptr; + uintD* b_LSDptr; + num_stack_alloc(len,a_MSDptr=,a_LSDptr=); + num_stack_alloc(len,b_MSDptr=,b_LSDptr=); + random_UDS(cl_default_random_state,a_MSDptr,len); + lspref(a_LSDptr,0) |= 1; // force a to be odd + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { recip2adic(len,a_LSDptr,b_LSDptr); } + } +} diff --git a/tests/timesqrt.cc b/tests/timesqrt.cc new file mode 100644 index 0000000..9f4e1d9 --- /dev/null +++ b/tests/timesqrt.cc @@ -0,0 +1,26 @@ +#include +#include +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); + cl_I m1 = cl_I(argv[1]); + cl_I M1 = (cl_I)1 << (intDsize*m1); + cl_I a = abs(random_I(M1)); + extern int cl_sqrt_algo; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_I b; isqrt(a,&b); } + } +} diff --git a/tests/timesqrtmodp.cc b/tests/timesqrtmodp.cc new file mode 100644 index 0000000..6c5371a --- /dev/null +++ b/tests/timesqrtmodp.cc @@ -0,0 +1,77 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); + cl_I len = cl_I(argv[1]); + int e = (argc > 2 ? atoi(argv[2]) : 0); + if (e < 1) + e = 1; + if (len <= e) + exit(0); + cl_I p; + do { + p = ((random_I((cl_I)1 << (len-1-e))*2+1) << e) + 1; + } while (!isprobprime(p)); + cout << "p = " << p << endl; + cl_modint_ring R = cl_find_modint_ring(p); + cl_MI x = R->random(); + cl_MI a = square(x); + sqrt_mod_p_t sol; +#if 0 + extern int cl_sqrt_algo; + cl_sqrt_algo = 1; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { sol = sqrt_mod_p(R,a); } + } + if (sol.condition) + cerr << "p not prime!" << endl; + else { + if (sol.solutions == 0) + cerr << "No sqrt found!" << endl; + if (!(sol.solution[0] == x || sol.solution[0] == -x)) + cerr << "Wrong result!" << endl; + } + cl_sqrt_algo = 2; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { sol = sqrt_mod_p(R,a); } + } + if (sol.condition) + cerr << "p not prime!" << endl; + else { + if (sol.solutions == 0) + cerr << "No sqrt found!" << endl; + if (!(sol.solution[0] == x || sol.solution[0] == -x)) + cerr << "Wrong result!" << endl; + } + cl_sqrt_algo = 3; +#endif + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { sol = sqrt_mod_p(R,a); } + } + if (sol.condition) + cerr << "p not prime!" << endl; + else { + if (sol.solutions == 0) + cerr << "No sqrt found!" << endl; + if (!(sol.solution[0] == x || sol.solution[0] == -x)) + cerr << "Wrong result!" << endl; + } +} diff --git a/tests/timesquare.cc b/tests/timesquare.cc new file mode 100644 index 0000000..5e47164 --- /dev/null +++ b/tests/timesquare.cc @@ -0,0 +1,34 @@ +#include +#include +#include +#include +#include +#include +#include + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); + cl_I m1 = cl_I(argv[1]); + cl_I M1 = (cl_I)1 << (intDsize*m1); + cl_I m2 = (argc>2 ? cl_I(argv[2]) : m1); + cl_I M2 = (cl_I)1 << (intDsize*m2); + cl_I a = random_I(M1); + cl_I b = random_I(M2); + fprint(cl_stderr, "Squaring: "); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_I p = a * a; } + } + fprint(cl_stderr, "Multiplication: "); + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { cl_I p = a * b; } + } +} diff --git a/tests/timezeta3.cc b/tests/timezeta3.cc new file mode 100644 index 0000000..8488f26 --- /dev/null +++ b/tests/timezeta3.cc @@ -0,0 +1,47 @@ +#include +#include +#include +#include +#include +#include +#include +#include "cl_LF.h" + +int main (int argc, char * argv[]) +{ + int repetitions = 1; + if ((argc >= 3) && !strcmp(argv[1],"-r")) { + repetitions = atoi(argv[2]); + argc -= 2; argv += 2; + } + if (argc < 2) + exit(1); + uintL len = atoi(argv[1]); + extern cl_LF cl_zeta (int s, uintC len); + extern cl_LF compute_zeta_exp (int s, uintC len); + extern cl_LF compute_zeta_cvz1 (int s, uintC len); + extern cl_LF compute_zeta_cvz2 (int s, uintC len); + extern cl_LF cl_zeta3 (uintC len); + cl_LF p; + ln(cl_I_to_LF(1000,len+10)); // fill cache + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = compute_zeta_exp(3,len); } + } + cout << p << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = compute_zeta_cvz1(3,len); } + } + cout << p << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = compute_zeta_cvz2(3,len); } + } + cout << p << endl; + { CL_TIMING; + for (int rep = repetitions; rep > 0; rep--) + { p = cl_zeta3(len); } + } + cout << p << endl; +} -- 2.45.2