~ubuntu-branches/ubuntu/quantal/gclcvs/quantal

« back to all changes in this revision

Viewing changes to gmp3/tune/many.pl

  • Committer: Bazaar Package Importer
  • Author(s): Camm Maguire
  • Date: 2004-06-24 15:13:46 UTC
  • Revision ID: james.westby@ubuntu.com-20040624151346-xh0xaaktyyp7aorc
Tags: 2.7.0-26
C_GC_OFFSET is 2 on m68k-linux

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#! /usr/bin/perl -w
 
2
 
 
3
# Copyright 2000, 2001 Free Software Foundation, Inc.
 
4
#
 
5
# This file is part of the GNU MP Library.
 
6
#
 
7
# The GNU MP Library is free software; you can redistribute it and/or modify
 
8
# it under the terms of the GNU Lesser General Public License as published by
 
9
# the Free Software Foundation; either version 2.1 of the License, or (at your
 
10
# option) any later version.
 
11
#
 
12
# The GNU MP Library is distributed in the hope that it will be useful, but
 
13
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 
14
# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 
15
# License for more details.
 
16
#
 
17
# You should have received a copy of the GNU Lesser General Public License
 
18
# along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
 
19
# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 
20
# MA 02111-1307, USA.
 
21
 
 
22
 
 
23
# Usage:  cd $builddir/tune
 
24
#         perl $srcdir/tune/many.pl [-t] <files/dirs>...
 
25
#
 
26
# Output: speed-many.c
 
27
#         try-many.c
 
28
#         Makefile.many
 
29
#
 
30
# Make alternate versions of various mpn routines available for measuring
 
31
# and testing.
 
32
#
 
33
# The $srcdir and $builddir in the invocation above just means the script
 
34
# lives in the tune source directory, but should be run in the tune build
 
35
# directory.  When not using a separate object directory this just becomes
 
36
#
 
37
#       cd tune
 
38
#       perl many.pl [-t] <files/dirs>...
 
39
#
 
40
#
 
41
# SINGLE FILES
 
42
#
 
43
# Suppose $HOME/newcode/mul_1_experiment.asm is a new implementation of
 
44
# mpn_mul_1, then
 
45
#
 
46
#       cd $builddir/tune
 
47
#       perl $srcdir/tune/many.pl $HOME/newcode/mul_1_experiment.asm
 
48
#
 
49
# will produce rules and renaming so that a speed program incorporating it
 
50
# can be built,
 
51
#
 
52
#       make -f Makefile.many speed-many
 
53
#
 
54
# then for example it can be compared to the standard mul_1,
 
55
#
 
56
#       ./speed-many -s 1-30 mpn_mul_1 mpn_mul_1_experiment
 
57
#
 
58
# An expanded try program can be used to check correctness,
 
59
#
 
60
#       make -f Makefile.many try-many
 
61
#
 
62
# and run
 
63
#
 
64
#       ./try-many mpn_mul_1_experiment
 
65
#
 
66
# Files can be ".c", ".S" or ".asm".  ".s" files can't be used because they
 
67
# don't get any preprocessing so there's no way to do renaming of their
 
68
# functions.
 
69
#
 
70
#
 
71
# WHOLE DIRECTORIES
 
72
#
 
73
# If a directory is given, then all files in it will be made available.
 
74
# For example,
 
75
#
 
76
#       cd $builddir/tune
 
77
#       perl $srcdir/tune/many.pl $HOME/newcode
 
78
#
 
79
# Each file should have a suffix, like "_experiment" above.
 
80
#
 
81
#
 
82
# MPN DIRECTORIES
 
83
#
 
84
# mpn directories from the GMP source tree can be included, and this is a
 
85
# convenient way to compare multiple implementations suiting different chips
 
86
# in a CPU family.  For example the following would make all x86 routines
 
87
# available,
 
88
#
 
89
#       cd $builddir/tune
 
90
#       perl $srcdir/tune/many.pl `find $srcdir/mpn/x86 -type d`
 
91
#
 
92
# On a new x86 chip a comparison could then be made to see how existing code
 
93
# runs.  For example,
 
94
#
 
95
#       make -f Makefile.many speed-many
 
96
#       ./speed-many -s 1-30 -c \
 
97
#               mpn_add_n_x86 mpn_add_n_pentium mpn_add_n_k6 mpn_add_n_k7
 
98
#
 
99
# Files in "mpn" subdirectories don't need the "_experiment" style suffix
 
100
# described above, instead a suffix is constructed from the subdirectory.
 
101
# For example "mpn/x86/k7/mmx/mod_1.asm" will generate a function
 
102
# mpn_mod_1_k7_mmx.  The rule is to take the last directory name after the
 
103
# "mpn", or the last two if there's three or more.  (Check the generated
 
104
# speed-many.c if in doubt.)
 
105
#
 
106
#
 
107
# GENERIC C
 
108
#
 
109
# The mpn/generic directory can be included too, just like any processor
 
110
# specific directory.  This is a good way to compare assembler and generic C
 
111
# implementations.  For example,
 
112
#
 
113
#       cd $builddir/tune
 
114
#       perl $srcdir/tune/many.pl $srcdir/mpn/generic
 
115
#
 
116
# or if just a few routines are of interest, then for example
 
117
#
 
118
#       cd $builddir/tune
 
119
#       perl $srcdir/tune/many.pl \
 
120
#               $srcdir/mpn/generic/lshift.c \
 
121
#               $srcdir/mpn/generic/mod_1.c \
 
122
#               $srcdir/mpn/generic/aorsmul_1.c
 
123
#
 
124
# giving mpn_lshift_generic etc.
 
125
#
 
126
#
 
127
# TESTS/DEVEL PROGRAMS
 
128
#
 
129
# Makefile.many also has rules to build the tests/devel programs with suitable
 
130
# renaming, and with some parameters for correctness or speed.  This is less
 
131
# convenient than the speed and try programs, but provides an independent
 
132
# check.  For example,
 
133
#
 
134
#       make -f Makefile.many tests_mul_1_experimental
 
135
#       ./tests_mul_1_experimental
 
136
#
 
137
# and for speed
 
138
#
 
139
#       make -f Makefile.many tests_mul_1_experimental_sp
 
140
#       ./tests_mul_1_experimental_sp
 
141
#
 
142
# Not all the programs support speed measuring, in which case only the
 
143
# correctness test will be useful.
 
144
#
 
145
# The parameters for repetitions and host clock speed are -D defines.  Some
 
146
# defaults are provided at the end of Makefile.many, but probably these will
 
147
# want to be overridden.  For example,
 
148
#
 
149
#       rm tests_mul_1_experimental.o
 
150
#       make -f Makefile.many \
 
151
#          CFLAGS_TESTS="-DSIZE=50 -DTIMES=1000 -DRANDOM -DCLOCK=175000000" \
 
152
#          tests_mul_1_experimental
 
153
#       ./tests_mul_1_experimental
 
154
#
 
155
#
 
156
# OTHER NOTES
 
157
#
 
158
# The mappings of file names to functions, and the macros to then use for
 
159
# speed measuring etc are driven by @table below.  The scheme isn't
 
160
# completely general, it's only got as many variations as have been needed
 
161
# so far.
 
162
#
 
163
# Some functions are only made available in speed-many, or others only in
 
164
# try-many.  An @table entry speed=>none means no speed measuring is
 
165
# available, or try=>none no try program testing.  These can be removed
 
166
# if/when the respective programs get the necessary support.
 
167
#
 
168
# If a file has "1c" or "nc" carry-in entrypoints, they're renamed and made
 
169
# available too.  These are recognised from PROLOGUE or MULFUNC_PROLOGUE in
 
170
# .S and .asm files, or from a line starting with "mpn_foo_1c" in a .c file
 
171
# (possibly via a #define), and on that basis are entirely optional.  This
 
172
# entrypoint matching is done for the standard entrypoints too, but it would
 
173
# be very unusual to have for instance a mul_1c without a mul_1.
 
174
#
 
175
# Some mpz files are recognized.  For example an experimental copy of
 
176
# mpz/powm.c could be included as powm_new.c and would be called
 
177
# mpz_powm_new.  So far only speed measuring is available for these.
 
178
#
 
179
# For the ".S" and ".asm" files, both PIC and non-PIC objects are built.
 
180
# The PIC functions have a "_pic" suffix, for example "mpn_mod_1_k7_mmx_pic".
 
181
# This can be ignored for routines that don't differ for PIC, or for CPUs
 
182
# where everything is PIC anyway.
 
183
#
 
184
# K&R compilers are supported via the same ansi2knr mechanism used by
 
185
# automake, though it's hard to believe anyone will have much interest in
 
186
# measuring a compiler so old that it doesn't even have an ANSI mode.
 
187
#
 
188
# The "-t" option can be used to print a trace of the files found and what's
 
189
# done with them.  A great deal of obscure output is produced, but it can
 
190
# indicate where or why some files aren't being recognised etc.  For
 
191
# example,
 
192
#
 
193
#       cd $builddir/tune
 
194
#       perl $srcdir/tune/many.pl -t $HOME/newcode/add_n_weird.asm
 
195
#
 
196
# In general, when including new code, all that's really necessary is that
 
197
# it will compile or assemble under the current configuration.  It's fine if
 
198
# some code doesn't actually run due to bugs, or to needing a newer CPU or
 
199
# whatever, simply don't ask for the offending routines when invoking
 
200
# speed-many or try-many, or don't try to run them on sizes they don't yet
 
201
# support, or whatever.
 
202
#
 
203
#
 
204
# CPU SPECIFICS
 
205
#
 
206
# x86 - All the x86 code will assemble on any system, but code for newer
 
207
#       chips might not run on older chips.  Expect SIGILLs from new
 
208
#       instructions on old chips.
 
209
#
 
210
#       A few "new" instructions, like cmov for instance, are done as macros
 
211
#       and will generate some equivalent plain i386 code when HAVE_HOST_CPU
 
212
#       in config.m4 indicates an old CPU.  It won't run fast, but it does
 
213
#       make it possible to test correctness.
 
214
#
 
215
#
 
216
# INTERNALS
 
217
#
 
218
# The nonsense involving $ENV is some hooks used during development to add
 
219
# additional functions temporarily.
 
220
#
 
221
#
 
222
# FUTURE
 
223
#
 
224
# Maybe the C files should be compiled pic and non-pic too.  Wait until
 
225
# there's a difference that might be of interest.
 
226
#
 
227
# Warn if a file provides no functions.
 
228
#
 
229
# Allow mpz and mpn files of the same name.  Currently the mpn fib2_ui
 
230
# matching hides the mpz version of that.  Will need to check the file
 
231
# contents to see which it is.  Would be worth allowing an "mpz_" or "mpn_"
 
232
# prefix on the filenames to have working versions of both in one directory.
 
233
#
 
234
#
 
235
# LIMITATIONS
 
236
#
 
237
# Some of the command lines can become very long when a lot of files are
 
238
# included.  If this is a problem on a given system the only suggestion is
 
239
# to run many.pl for just those that are actually wanted at a particular
 
240
# time.
 
241
#
 
242
# DOS 8.3 or SysV 14 char filesystems won't work, since the long filenames
 
243
# generated will almost certainly fail to be unique.
 
244
 
 
245
 
 
246
use strict;
 
247
use File::Basename;
 
248
use Getopt::Std;
 
249
 
 
250
my %opt;
 
251
getopts('t', \%opt);
 
252
 
 
253
my @DIRECTORIES = @ARGV;
 
254
if (defined $ENV{directories}) { push @DIRECTORIES, @{$ENV{directories}} }
 
255
 
 
256
 
 
257
# regexp - matched against the start of the filename.  If a grouping "(...)"
 
258
#          is present then only the first such part is used.
 
259
#
 
260
# mulfunc - filenames to be generated from a multi-function file.
 
261
#
 
262
# funs - functions provided by the file, defaulting to the filename with mpn
 
263
#          (or mpX).
 
264
#
 
265
# mpX - prefix like "mpz", defaulting to "mpn".
 
266
#
 
267
# ret - return value type.
 
268
#
 
269
# args, args_<fun> - arguments for the given function.  If an args_<fun> is
 
270
#          set then it's used, otherwise plain args is used.  "mp_limb_t
 
271
#          carry" is appended for carry-in variants.
 
272
#
 
273
# try - try.c TYPE_ to use, defaulting to TYPE_fun with the function name
 
274
#          in upper case.  "C" is appended for carry-in variants.  Can be
 
275
#          'none' for no try program entry.
 
276
#
 
277
# speed - SPEED_ROUTINE_ to use, handled like "try".
 
278
#
 
279
# speed_flags - SPEED_ROUTINE_ to use, handled like "try".
 
280
 
 
281
 
 
282
my @table =
 
283
    (
 
284
     {
 
285
       'regexp'=> 'add_n|sub_n',
 
286
       'ret'   => 'mp_limb_t',
 
287
       'args'  => 'mp_ptr wp, mp_srcptr xp, mp_srcptr yp, mp_size_t size',
 
288
       'speed' => 'SPEED_ROUTINE_MPN_BINARY_N',
 
289
     },
 
290
     {
 
291
       'regexp'=> 'aors_n',
 
292
       'mulfunc'=> ['add_n','sub_n'],
 
293
       'ret'   => 'mp_limb_t',
 
294
       'args'  => 'mp_ptr wp, mp_srcptr xp, mp_srcptr yp, mp_size_t size',
 
295
       'speed' => 'SPEED_ROUTINE_MPN_BINARY_N',
 
296
     },
 
297
     
 
298
     {
 
299
       'regexp'=> 'addmul_1|submul_1',
 
300
       'ret'   => 'mp_limb_t',
 
301
       'args'  => 'mp_ptr wp, mp_srcptr xp, mp_size_t size, mp_limb_t mult',
 
302
       'speed' => 'SPEED_ROUTINE_MPN_UNARY_1',
 
303
       'speed_flags'=> 'FLAG_R',
 
304
     },
 
305
     {
 
306
       'regexp'=> 'aorsmul_1',
 
307
       'mulfunc'=> ['addmul_1','submul_1'],
 
308
       'ret'   => 'mp_limb_t',
 
309
       'args'  => 'mp_ptr wp, mp_srcptr xp, mp_size_t size, mp_limb_t mult',
 
310
       'speed' => 'SPEED_ROUTINE_MPN_UNARY_1',
 
311
       'speed_flags'=> 'FLAG_R',
 
312
     },
 
313
 
 
314
     {
 
315
       'regexp'=> 'addsub_n',
 
316
       'ret'   => 'mp_limb_t',
 
317
       'args'  => 'mp_ptr sum, mp_ptr diff, mp_srcptr xp, mp_srcptr yp, mp_size_t size',
 
318
       'speed_flags'=> 'FLAG_R_OPTIONAL',
 
319
     },
 
320
 
 
321
     {
 
322
       'regexp'=> 'bdivmod',
 
323
       'ret'   => 'mp_limb_t',
 
324
       'args'  => 'mp_ptr qp, mp_ptr up, mp_size_t usize, mp_srcptr vp, mp_size_t vsize, unsigned long int d',
 
325
       'carrys'=> [''],
 
326
       'try'   => 'none',
 
327
       'speed' => 'none',
 
328
     },
 
329
 
 
330
     {
 
331
       'regexp'=> 'com_n|copyi|copyd',
 
332
       'ret'   => 'void',
 
333
       'args'  => 'mp_ptr wp, mp_srcptr xp, mp_size_t size',
 
334
       'speed' => 'SPEED_ROUTINE_MPN_COPY',
 
335
     },
 
336
 
 
337
     {
 
338
       'regexp'=> 'dive_1',
 
339
       'funs'  => ['divexact_1'],
 
340
       'ret'   => 'void',
 
341
       'args'  => 'mp_ptr dst, mp_srcptr src, mp_size_t size, mp_limb_t divisor',
 
342
       'speed_flags'=> 'FLAG_R',
 
343
     },
 
344
     {
 
345
       'regexp'=> 'diveby3',
 
346
       'funs'  => ['divexact_by3c'],
 
347
       'ret'   => 'mp_limb_t',
 
348
       'args'  => 'mp_ptr dst, mp_srcptr src, mp_size_t size',
 
349
       'carrys'=> [''],
 
350
       'speed' => 'SPEED_ROUTINE_MPN_COPY',
 
351
     },
 
352
     
 
353
     {
 
354
       'regexp'=> 'divrem_1',
 
355
       'ret'   => 'mp_limb_t',
 
356
       'args'  => 'mp_ptr rp, mp_size_t xsize, mp_srcptr sp, mp_size_t size, mp_limb_t divisor',
 
357
       'speed_flags' => 'FLAG_R',
 
358
       'speed_suffixes' => ['f'],
 
359
     },
 
360
     {
 
361
       'regexp'=> 'divrem_2',
 
362
       'ret'   => 'mp_limb_t',
 
363
       'args'  => 'mp_ptr qp, mp_size_t qxn, mp_srcptr np, mp_size_t nsize, mp_srcptr dp',
 
364
       'try'   => 'none',
 
365
     },
 
366
 
 
367
     {
 
368
       'regexp'=> 'sb_divrem_mn',
 
369
       'ret'   => 'mp_limb_t',
 
370
       'args'  => 'mp_ptr qp, mp_ptr np, mp_size_t nsize, mp_srcptr dp, mp_size_t dsize',
 
371
       'speed' => 'SPEED_ROUTINE_MPN_DC_DIVREM_SB',
 
372
       'try-minsize' => 3,
 
373
     },
 
374
     {
 
375
       'regexp'=> 'tdiv_qr',
 
376
       'ret'   => 'void',
 
377
       'args'  => 'mp_ptr qp, mp_size_t qxn, mp_ptr np, mp_size_t nsize, mp_srcptr dp, mp_size_t dsize',
 
378
       'speed' => 'none',
 
379
     },
 
380
 
 
381
     {
 
382
       'regexp'=> 'get_str',
 
383
       'ret'   => 'size_t',
 
384
       'args'  => 'unsigned char *str, int base, mp_ptr mptr, mp_size_t msize',
 
385
       'speed_flags' => 'FLAG_R_OPTIONAL',
 
386
       'try'   => 'none',
 
387
     },
 
388
     {
 
389
       'regexp'=> 'set_str',
 
390
       'ret'   => 'mp_size_t',
 
391
       'args'  => 'mp_ptr xp, const unsigned char *str, size_t str_len, int base',
 
392
       'speed_flags' => 'FLAG_R_OPTIONAL',
 
393
       'try'   => 'none',
 
394
     },
 
395
 
 
396
     {
 
397
       'regexp'=> 'fac_ui',
 
398
       'mpX'   => 'mpz',
 
399
       'ret'   => 'void',
 
400
       'args'  => 'mpz_ptr r, unsigned long n',
 
401
       'speed_flags' => 'FLAG_NODATA',
 
402
       'try'   => 'none',
 
403
     },
 
404
 
 
405
     {
 
406
       'regexp'=> 'fib2_ui',
 
407
       'ret'   => 'void',
 
408
       'args'  => 'mp_ptr fp, mp_ptr f1p, unsigned long n',
 
409
       'rename'=> ['__gmp_fib_table'],
 
410
       'speed_flags' => 'FLAG_NODATA',
 
411
       'try'   => 'none',
 
412
     },
 
413
     {
 
414
       'regexp'=> 'fib_ui',
 
415
       'mpX'   => 'mpz',
 
416
       'ret'   => 'void',
 
417
       'args'  => 'mpz_ptr fn, unsigned long n',
 
418
       'speed_flags' => 'FLAG_NODATA',
 
419
       'try'   => 'none',
 
420
     },
 
421
     {
 
422
       'regexp'=> 'fib2_ui',
 
423
       'mpX'   => 'mpz',
 
424
       'ret'   => 'void',
 
425
       'args'  => 'mpz_ptr fn, mpz_ptr fnsub1, unsigned long n',
 
426
       'speed_flags' => 'FLAG_NODATA',
 
427
       'try'   => 'none',
 
428
     },
 
429
 
 
430
     {
 
431
       'regexp'=> 'lucnum_ui',
 
432
       'mpX'   => 'mpz',
 
433
       'ret'   => 'void',
 
434
       'args'  => 'mpz_ptr ln, unsigned long n',
 
435
       'speed_flags' => 'FLAG_NODATA',
 
436
       'try'   => 'none',
 
437
     },
 
438
     {
 
439
       'regexp'=> 'lucnum2_ui',
 
440
       'mpX'   => 'mpz',
 
441
       'ret'   => 'void',
 
442
       'args'  => 'mpz_ptr ln, mpz_ptr lnsub1, unsigned long n',
 
443
       'speed_flags' => 'FLAG_NODATA',
 
444
       'try'   => 'none',
 
445
     },
 
446
 
 
447
     {
 
448
       'regexp'=> 'gcd_1',
 
449
       'ret'   => 'mp_limb_t',
 
450
       'args'  => 'mp_ptr xp, mp_size_t xsize, mp_limb_t y',
 
451
       'attrib'=> '__GMP_ATTRIBUTE_PURE',
 
452
       'speed_flags'=> 'FLAG_R_OPTIONAL',
 
453
       'speed_suffixes' => ['N'],
 
454
     },
 
455
     {
 
456
       'regexp'=> '(gcd)(?!(_1|ext|_finda))',
 
457
       'ret'   => 'mp_size_t',
 
458
       'args'  => 'mp_ptr gp, mp_ptr up, mp_size_t usize, mp_ptr vp, mp_size_t vsize',
 
459
     },
 
460
     {
 
461
       'regexp'=> 'gcd_finda',
 
462
       'ret'   => 'mp_limb_t',
 
463
       'args'  => 'mp_srcptr cp',
 
464
       'attrib'=> '__GMP_ATTRIBUTE_PURE',
 
465
     },
 
466
     
 
467
 
 
468
     {
 
469
       'regexp'=> 'jacobi',
 
470
       'funs'  => ['jacobi', 'legendre', 'kronecker'],
 
471
       'mpX'   => 'mpz',
 
472
       'ret'   => 'int',
 
473
       'args'  => 'mpz_srcptr a, mpz_srcptr b',
 
474
       'attrib'=> '__GMP_ATTRIBUTE_PURE',
 
475
       'try-legendre' => 'TYPE_MPZ_JACOBI',
 
476
     },
 
477
     {
 
478
       'regexp'=> 'jacbase',
 
479
       'funs'  => ['jacobi_base'],
 
480
       'ret'   => 'mp_limb_t',
 
481
       'args'  => 'mp_limb_t a, mp_limb_t b, int bit1',
 
482
       'attrib'=> 'ATTRIBUTE_CONST',
 
483
       'speed' => 'SPEED_ROUTINE_MPN_JACBASE',
 
484
       'try'   => 'none',
 
485
     },
 
486
 
 
487
     {
 
488
       'regexp'=> 'logops_n',
 
489
       'mulfunc'=> ['and_n','andn_n','nand_n','ior_n','iorn_n','nior_n','xor_n','xnor_n'],
 
490
       'ret'   => 'void',
 
491
       'args'  => 'mp_ptr wp, mp_srcptr xp, mp_srcptr yp, mp_size_t size',
 
492
       'speed' => 'SPEED_ROUTINE_MPN_BINARY_N',
 
493
     },
 
494
 
 
495
     {
 
496
       'regexp'=> '[lr]shift',
 
497
       'ret'   => 'mp_limb_t',
 
498
       'args'  => 'mp_ptr wp, mp_srcptr xp, mp_size_t size, unsigned shift',
 
499
       'speed' => 'SPEED_ROUTINE_MPN_UNARY_1',
 
500
       'speed_flags'=> 'FLAG_R',
 
501
     },
 
502
 
 
503
     # mpn_preinv_mod_1 is an optional extra entrypoint
 
504
     {
 
505
       'regexp'=> '(mod_1)(?!_rs)',
 
506
       'funs'  => ['mod_1','preinv_mod_1'],
 
507
       'ret'   => 'mp_limb_t',
 
508
       'args_mod_1'       => 'mp_srcptr xp, mp_size_t size, mp_limb_t divisor',
 
509
       'args_preinv_mod_1'=> 'mp_srcptr xp, mp_size_t size, mp_limb_t divisor, mp_limb_t inverse',
 
510
       'attrib'=> '__GMP_ATTRIBUTE_PURE',
 
511
       'speed_flags'=> 'FLAG_R',
 
512
     },
 
513
     {
 
514
       'regexp'=> 'pre_mod_1',
 
515
       'funs'  => ['preinv_mod_1'],
 
516
       'ret'   => 'mp_limb_t',
 
517
       'args'  => 'mp_srcptr xp, mp_size_t size, mp_limb_t divisor, mp_limb_t inverse',
 
518
       'attrib'=> '__GMP_ATTRIBUTE_PURE',
 
519
       'speed_flags'=> 'FLAG_R',
 
520
     },
 
521
     {
 
522
       'regexp'=> 'mod_34lsub1',
 
523
       'ret'   => 'mp_limb_t',
 
524
       'args'  => 'mp_srcptr src, mp_size_t len',
 
525
       'attrib'=> '__GMP_ATTRIBUTE_PURE',
 
526
     },
 
527
     {
 
528
       'regexp'=> 'invert_limb',
 
529
       'ret'   => 'mp_limb_t',
 
530
       'args'  => 'mp_limb_t divisor',
 
531
       'attrib'=> 'ATTRIBUTE_CONST',
 
532
       'speed_flags'=> 'FLAG_R_OPTIONAL',
 
533
       'try'   => 'none',
 
534
     },
 
535
 
 
536
     {
 
537
       'regexp'=> 'mode1o',
 
538
       'funs'  => ['modexact_1_odd'],
 
539
       'ret'   => 'mp_limb_t',
 
540
       'args'  => 'mp_srcptr src, mp_size_t size, mp_limb_t divisor',
 
541
       'attrib'=> '__GMP_ATTRIBUTE_PURE',
 
542
       'speed_flags'=> 'FLAG_R',
 
543
     },
 
544
     {
 
545
       'regexp'=> 'modlinv',
 
546
       'funs'  => ['modlimb_invert'],
 
547
       'ret'   => 'mp_limb_t',
 
548
       'args'  => 'mp_limb_t v',
 
549
       'attrib'=> 'ATTRIBUTE_CONST',
 
550
       'carrys'=> [''],
 
551
       'try'   => 'none',
 
552
     },
 
553
 
 
554
     {
 
555
       'regexp'=> 'mul_1',
 
556
       'ret'   => 'mp_limb_t',
 
557
       'args'  => 'mp_ptr wp, mp_srcptr xp, mp_size_t size, mp_limb_t mult',
 
558
       'speed' => 'SPEED_ROUTINE_MPN_UNARY_1',
 
559
       'speed_flags'=> 'FLAG_R',
 
560
     },
 
561
     {
 
562
       'regexp'=> 'mul_2',
 
563
       'ret'   => 'mp_limb_t',
 
564
       'args'  => 'mp_ptr wp, mp_srcptr xp, mp_size_t size, mp_limb_t low, mp_limb_t high',
 
565
       'speed' => 'SPEED_ROUTINE_MPN_UNARY_2',
 
566
     },
 
567
     
 
568
     {
 
569
       'regexp'=> 'mul_basecase',
 
570
       'ret'   => 'void',
 
571
       'args'  => 'mp_ptr wp, mp_srcptr xp, mp_size_t xsize, mp_srcptr yp, mp_size_t ysize',
 
572
       'speed_flags' => 'FLAG_R_OPTIONAL | FLAG_RSIZE',
 
573
     },
 
574
     {
 
575
       'regexp'=> '(mul_n)[_.]',
 
576
       'ret'   => 'void',
 
577
       'args'  => 'mp_ptr wp, mp_srcptr xp, mp_srcptr yp, mp_size_t size',
 
578
       'rename'=> ['kara_mul_n','kara_sqr_n','toom3_mul_n','toom3_sqr_n'],
 
579
     },
 
580
     {
 
581
       # not for use with hppa reversed argument versions of mpn_umul_ppmm
 
582
       'regexp'=> 'umul',
 
583
       'funs'  => ['umul_ppmm'],
 
584
       'ret'   => 'mp_limb_t',
 
585
       'args'  => 'mp_limb_t *lowptr, mp_limb_t m1, mp_limb_t m2',
 
586
       'speed' => 'none',
 
587
       'try-minsize' => 3,
 
588
     },
 
589
       
 
590
 
 
591
     {
 
592
       'regexp'=> 'popham',
 
593
       'mulfunc'=> ['popcount','hamdist'],
 
594
       'ret'   => 'unsigned long',
 
595
       'args_popcount'=> 'mp_srcptr xp, mp_size_t size',
 
596
       'args_hamdist' => 'mp_srcptr xp, mp_srcptr yp, mp_size_t size',
 
597
       'attrib'=> '__GMP_ATTRIBUTE_PURE',
 
598
     },
 
599
     {
 
600
       'regexp'=> 'popcount',
 
601
       'ret'   => 'unsigned long',
 
602
       'args'  => 'mp_srcptr xp, mp_size_t size',
 
603
       'attrib'=> '__GMP_ATTRIBUTE_PURE',
 
604
     },
 
605
     {
 
606
       'regexp'=> 'hamdist',
 
607
       'ret'   => 'unsigned long',
 
608
       'args'  => 'mp_srcptr xp, mp_srcptr yp, mp_size_t size',
 
609
       'attrib'=> '__GMP_ATTRIBUTE_PURE',
 
610
       # extra renaming to support sharing a data table with mpn_popcount
 
611
       'rename'=> ['popcount'],
 
612
     },
 
613
 
 
614
     {
 
615
       'regexp'=> 'sqr_basecase',
 
616
       'ret'   => 'void',
 
617
       'args'  => 'mp_ptr wp, mp_srcptr xp, mp_size_t size',
 
618
       'speed' => 'SPEED_ROUTINE_MPN_SQR',
 
619
       'try'   => 'TYPE_SQR',
 
620
     },
 
621
     {
 
622
       'regexp'=> 'sqr_diagonal',
 
623
       'ret'   => 'void',
 
624
       'args'  => 'mp_ptr wp, mp_srcptr xp, mp_size_t size',
 
625
       'try'   => 'none',
 
626
     },
 
627
 
 
628
     {
 
629
       'regexp'=> 'sqrtrem',
 
630
       'ret'   => 'mp_size_t',
 
631
       'args'  => 'mp_ptr root, mp_ptr rem, mp_srcptr src, mp_size_t size',
 
632
       'try'   => 'none',
 
633
     },
 
634
 
 
635
     {
 
636
       'regexp'=> 'cntlz',
 
637
       'funs'  => ['count_leading_zeros'],
 
638
       'ret'   => 'unsigned',
 
639
       'args'  => 'mp_limb_t',
 
640
       'attrib'=> 'ATTRIBUTE_CONST',
 
641
       'macro-before' => "#undef COUNT_LEADING_ZEROS_0",
 
642
       'macro-speed'  =>
 
643
'#ifdef COUNT_LEADING_ZEROS_0
 
644
#define COUNT_LEADING_ZEROS_0_ALLOWED   1
 
645
#else
 
646
#define COUNT_LEADING_ZEROS_0_ALLOWED   0
 
647
#endif
 
648
  SPEED_ROUTINE_COUNT_LEADING_ZEROS_C ($fun (c, n),
 
649
    COUNT_LEADING_ZEROS_0_ALLOWED)',
 
650
       'speed_flags'=> 'FLAG_R_OPTIONAL',
 
651
       'try'   => 'none',
 
652
     },
 
653
     {
 
654
       'regexp'=> 'cnttz',
 
655
       'funs'  => ['count_trailing_zeros'],
 
656
       'ret'   => 'unsigned',
 
657
       'args'  => 'mp_limb_t',
 
658
       'attrib'=> 'ATTRIBUTE_CONST',
 
659
       'macro-speed' => 'SPEED_ROUTINE_COUNT_TRAILING_ZEROS_C ($fun(c,n), 0)',
 
660
       'speed_flags' => 'FLAG_R_OPTIONAL',
 
661
       'try'   => 'none',
 
662
     },
 
663
 
 
664
     {
 
665
       'regexp'=> 'zero',
 
666
       'ret'   => 'void',
 
667
       'args'  => 'mp_ptr ptr, mp_size_t size',
 
668
     },
 
669
 
 
670
     {
 
671
       'regexp'=> '(powm)(?!_ui)',
 
672
       'mpX'   => 'mpz',
 
673
       'ret'   => 'void',
 
674
       'args'  => 'mpz_ptr r, mpz_srcptr b, mpz_srcptr e, mpz_srcptr m',
 
675
       'try'   => 'none',
 
676
     },
 
677
     {
 
678
       'regexp'=> 'powm_ui',
 
679
       'mpX'   => 'mpz',
 
680
       'ret'   => 'void',
 
681
       'args'  => 'mpz_ptr r, mpz_srcptr b, unsigned long e, mpz_srcptr m',
 
682
       'try'   => 'none',
 
683
     },
 
684
 
 
685
     # special for use during development
 
686
     {
 
687
       'regexp'=> 'back',
 
688
       'funs'  => ['back_to'],
 
689
       'ret'   => 'void',
 
690
       'args'  => 'void',
 
691
       'suffix'=> 'back',
 
692
       'pic'   => 'no',
 
693
       'try'   => 'none',
 
694
       'speed_flags'=> 'FLAG_NODATA',
 
695
     },
 
696
     );
 
697
 
 
698
if (defined $ENV{table2}) {
 
699
  my @newtable = @{$ENV{table2}};
 
700
  push @newtable, @table;
 
701
  @table = @newtable;
 
702
}
 
703
 
 
704
 
 
705
my %pictable = 
 
706
    (
 
707
     'yes' => {
 
708
       'suffix' =>  '_pic',
 
709
       'asmflags'=> '$(ASMFLAGS_PIC)',
 
710
       'cflags' =>  '$(CFLAGS_PIC)',
 
711
     },
 
712
     'no' => {
 
713
       'suffix' =>  '',
 
714
       'asmflags'=> '',
 
715
       'cflags' =>  '',
 
716
     },
 
717
     );
 
718
 
 
719
 
 
720
my $builddir = $ENV{builddir};
 
721
$builddir = "." if (! defined $builddir);
 
722
 
 
723
my $top_builddir = "${builddir}/..";
 
724
 
 
725
 
 
726
open(MAKEFILE, "<${builddir}/Makefile")
 
727
    or die "Cannot open Makefile: $!\nIs this a tune build directory?";
 
728
my ($srcdir, $top_srcdir);
 
729
while (<MAKEFILE>) {
 
730
  if (/^srcdir = (.*)/) {     $srcdir = $1;     }
 
731
  if (/^top_srcdir = (.*)/) { $top_srcdir = $1; }
 
732
}
 
733
die "Cannot find \$srcdir in Makefile\n" if (! defined $srcdir);
 
734
die "Cannot find \$top_srcdir in Makefile\n" if (! defined $top_srcdir);
 
735
print "srcdir $srcdir\n" if $opt{'t'};
 
736
print "top_srcdir $top_srcdir\n" if $opt{'t'};
 
737
close(MAKEFILE);
 
738
 
 
739
 
 
740
open(SPEED, ">speed-many.c") or die;
 
741
print SPEED
 
742
"/* speed-many.c generated by many.pl - DO NOT EDIT, CHANGES WILL BE LOST */
 
743
 
 
744
";
 
745
my $SPEED_EXTRA_ROUTINES = "#define SPEED_EXTRA_ROUTINES \\\n";
 
746
my $SPEED_EXTRA_PROTOS = "#define SPEED_EXTRA_PROTOS \\\n";
 
747
my $SPEED_CODE = "";
 
748
 
 
749
open(TRY, ">try-many.c") or die;
 
750
print TRY
 
751
    "/* try-many.c generated by many.pl - DO NOT EDIT, CHANGES WILL BE LOST */\n" .
 
752
    "\n";
 
753
my $TRY_EXTRA_ROUTINES = "#define EXTRA_ROUTINES \\\n";
 
754
my $TRY_EXTRA_PROTOS = "#define EXTRA_PROTOS \\\n";
 
755
 
 
756
open(FD,"<${top_builddir}/libtool") or die "Cannot open \"${top_builddir}/libtool\": $!\n";
 
757
my $pic_flag;
 
758
while (<FD>) {
 
759
  if (/^pic_flag="?([^"]*)"?$/) {
 
760
    $pic_flag=$1;
 
761
    last;
 
762
  }
 
763
}
 
764
close FD;
 
765
if (! defined $pic_flag) {
 
766
  die "Cannot find pic_flag in ${top_builddir}/libtool";
 
767
}
 
768
 
 
769
my $CFLAGS_PIC = $pic_flag;
 
770
 
 
771
my $ASMFLAGS_PIC = "";
 
772
foreach (split /[ \t]/, $pic_flag) {
 
773
  if (/^-D/) {
 
774
    $ASMFLAGS_PIC .= " " . $_;
 
775
  }
 
776
}
 
777
 
 
778
open(MAKEFILE, ">Makefile.many") or die;
 
779
print MAKEFILE
 
780
    "# Makefile.many generated by many.pl - DO NOT EDIT, CHANGES WILL BE LOST\n" .
 
781
    "\n" .
 
782
    "all: speed-many try-many\n" .
 
783
    "\n" .
 
784
    "#--------- begin included copy of basic Makefile ----------\n" .
 
785
    "\n";
 
786
open(FD,"<${builddir}/Makefile") or die "Cannot open \"${builddir}/Makefile\": $!\n";
 
787
print MAKEFILE <FD>;
 
788
close FD;
 
789
print MAKEFILE
 
790
    "\n" .
 
791
    "#--------- end included copy of basic Makefile ----------\n" .
 
792
    "\n" .
 
793
    "CFLAGS_PIC = $CFLAGS_PIC\n" .
 
794
    "ASMFLAGS_PIC = $ASMFLAGS_PIC\n" .
 
795
    "\n";
 
796
 
 
797
my $CLEAN="";
 
798
my $MANY_OBJS="";
 
799
 
 
800
 
 
801
sub print_ansi2knr {
 
802
  my ($base,$file,$includes) = @_;
 
803
  if (! defined $file)     { $file = "$base.c"; }
 
804
  if (! defined $includes) { $includes = ""; }
 
805
 
 
806
  print MAKEFILE <<EOF;
 
807
${base}_.c: $file \$(ANSI2KNR)
 
808
        \$(CPP) \$(DEFS) \$(INCLUDES) $includes \$(AM_CPPFLAGS) \$(CPPFLAGS) $file | sed 's/^# \([0-9]\)/#line \\1/' | \$(ANSI2KNR) >${base}_.c
 
809
 
 
810
EOF
 
811
}
 
812
 
 
813
 
 
814
# Spawning a glob is a touch slow when there's lots of files.
 
815
my @files = ();
 
816
foreach my $dir (@DIRECTORIES) {
 
817
  print "dir $dir\n" if $opt{'t'};
 
818
  if (-f $dir) {
 
819
    push @files,$dir;
 
820
  } else {
 
821
    if (! opendir DD,$dir) {
 
822
      print "Cannot open $dir: $!\n";
 
823
    } else {
 
824
      push @files, map {$_="$dir/$_"} grep /\.(c|asm|S|h)$/, readdir DD;
 
825
      closedir DD;
 
826
    }
 
827
  }
 
828
}
 
829
@files = sort @files;
 
830
print "@files ",join(" ",@files),"\n" if $opt{'t'};
 
831
 
 
832
my $count_files = 0;
 
833
my $count_functions = 0;
 
834
my %seen_obj;
 
835
my %seen_file;
 
836
 
 
837
foreach my $file_full (@files) {
 
838
  if (! -f $file_full) {
 
839
    print "Not a file: $file_full\n";
 
840
    next;
 
841
  }
 
842
  if (defined $seen_file{$file_full}) {
 
843
    print "Skipping duplicate file: $file_full\n";
 
844
    next;
 
845
  }
 
846
  $seen_file{$file_full} = 1;
 
847
 
 
848
  my ($FILE,$path,$lang) = fileparse($file_full,"\.[a-zA-Z]+");
 
849
  $path =~ s/\/$//;
 
850
  print "file $FILE path $path lang $lang\n" if $opt{'t'};
 
851
 
 
852
  my @pic_choices;
 
853
  if ($lang eq '.asm')  { @pic_choices=('no','yes'); }
 
854
  elsif ($lang eq '.c') { @pic_choices=('no'); }
 
855
  elsif ($lang eq '.S') { @pic_choices=('no','yes'); }
 
856
  elsif ($lang eq '.h') { @pic_choices=('no'); }
 
857
  else { next };
 
858
  
 
859
  my ($t, $file_match);
 
860
  foreach my $p (@table) {
 
861
    # print " ",$p->{'regexp'},"\n" if $opt{'t'};
 
862
    if ($FILE =~ "^($p->{'regexp'})") {
 
863
      $t = $p;
 
864
      $file_match = $1;
 
865
      $file_match = $2 if defined $2;
 
866
      last;
 
867
    }
 
868
  }
 
869
  next if ! defined $t;
 
870
  print "match $t->{'regexp'} $FILE ($file_full)\n" if $opt{'t'};
 
871
 
 
872
  if (! open FD,"<$file_full") { print "Can't open $file_full: $!\n"; next }
 
873
  my @file_contents = <FD>;
 
874
  close FD;
 
875
 
 
876
  my $objs;
 
877
  if (defined $t->{'mulfunc'}) { $objs = $t->{'mulfunc'}; }
 
878
  else                         { $objs = [$file_match]; }
 
879
  print "objs @$objs\n" if $opt{'t'};
 
880
 
 
881
  my $ret = $t->{'ret'};
 
882
  if (! defined $ret && $lang eq '.h') { $ret = ''; }
 
883
  if (! defined $ret) { die "$FILE return type not defined\n" };
 
884
  print "ret $ret\n" if $opt{'t'};
 
885
 
 
886
  my $mpX = $t->{'mpX'};
 
887
  if (! defined $mpX) { $mpX = ($lang eq '.h' ? '' : 'mpn'); }
 
888
  $mpX = "${mpX}_" if $mpX ne '';
 
889
  print "mpX $mpX\n" if $opt{'t'};
 
890
 
 
891
  my $carrys;
 
892
  if (defined $t->{'carrys'}) { $carrys = $t->{'carrys'}; }
 
893
  else                        { $carrys = ['','c'];       }
 
894
  print "carrys $carrys @$carrys\n" if $opt{'t'};
 
895
  
 
896
  # some restriction functions are implemented, but they're not very useful
 
897
  my $restriction='';
 
898
 
 
899
  my $suffix;
 
900
  if ($FILE =~ ("${file_match}_(.+)")) {
 
901
    $suffix = $1;
 
902
  } elsif ($path =~ /\/mp[zn]\/(.*)$/) {
 
903
    # derive the suffix from the path
 
904
    $suffix = $1;
 
905
    $suffix =~ s/\//_/g;
 
906
    # use last directory name, or if there's 3 or more then the last two
 
907
    if ($suffix =~ /([^_]*_)+([^_]+_[^_]+)$/) {
 
908
      $suffix = $2;
 
909
    } elsif ($suffix =~ /([^_]*_)*([^_]+)$/) {
 
910
      $suffix = $2;
 
911
    }
 
912
  } elsif (defined $t->{'suffix'}) {
 
913
    $suffix = $t->{'suffix'};
 
914
  } else {
 
915
    die "Can't determine suffix for: $file_full (path $path)\n";
 
916
  }
 
917
  print "suffix $suffix\n" if $opt{'t'};
 
918
  
 
919
  $count_files++;
 
920
  
 
921
  foreach my $obj (@{$objs}) {
 
922
    print "obj $obj\n" if $opt{'t'};
 
923
 
 
924
    my $obj_with_suffix = "${obj}_$suffix";
 
925
    if (defined $seen_obj{$obj_with_suffix}) {
 
926
      print "Skipping duplicate object: $obj_with_suffix\n";
 
927
      print "   first from: $seen_obj{$obj_with_suffix}\n";
 
928
      print "   now from:   $file_full\n";
 
929
      next;
 
930
    }
 
931
    $seen_obj{$obj_with_suffix} = $file_full;
 
932
 
 
933
    my $funs = $t->{'funs'};
 
934
    $funs = [$obj] if ! defined $funs;
 
935
    print "funs @$funs\n" if $opt{'t'};
 
936
 
 
937
    if (defined $t->{'pic'}) { @pic_choices = ('no'); }
 
938
 
 
939
    foreach my $pic (map {$pictable{$_}} @pic_choices) {
 
940
      print "pic $pic->{'suffix'}\n" if $opt{'t'};
 
941
      
 
942
      my $objbase = "${obj}_$suffix$pic->{'suffix'}";
 
943
      print "objbase $objbase\n" if $opt{'t'};
 
944
 
 
945
      if ($path !~ "." && -f "${objbase}.c") {
 
946
        die "Already have ${objbase}.c";
 
947
      }
 
948
 
 
949
      my $tmp_file = "tmp-$objbase.c";
 
950
      
 
951
      my $renaming;
 
952
      foreach my $fun (@{$funs}) {
 
953
        my $fun_carry = $fun;
 
954
        if (! ($fun_carry =~ s/_1/_1c/)) { $fun_carry = "${fun}c"; }
 
955
        $renaming .=
 
956
            "\t\t-D__g$mpX$fun=$mpX${fun}_$suffix$pic->{'suffix'} \\\n" .
 
957
            "\t\t-D__g$mpX$fun_carry=$mpX${fun_carry}_$suffix$pic->{'suffix'} \\\n";
 
958
      }
 
959
      foreach my $r (@{$t->{'rename'}}) {
 
960
        if ($r =~ /^__gmp/) {
 
961
          $renaming .= "\\\n" .
 
962
              "\t\t-D$r=${r}_$suffix$pic->{'suffix'}";
 
963
        } else {
 
964
          $renaming .= "\\\n" .
 
965
              "\t\t-D__g$mpX$r=$mpX${r}_$suffix$pic->{'suffix'}";
 
966
        }
 
967
      }
 
968
      print "renaming $renaming\n" if $opt{'t'};
 
969
 
 
970
      print MAKEFILE "\n";
 
971
      if ($lang eq '.asm') {
 
972
        print MAKEFILE
 
973
            "$objbase.o: $file_full \$(ASM_HEADERS)\n" .
 
974
            "   \$(M4) \$(M4FLAGS) -DOPERATION_$obj $pic->{'asmflags'} \\\n" .
 
975
            "$renaming" .
 
976
            "           $file_full >tmp-$objbase.s\n" .
 
977
            "   \$(CCAS) \$(COMPILE_FLAGS) $pic->{'cflags'} tmp-$objbase.s -o $objbase.o\n" .
 
978
            "   \$(RM_TMP) tmp-$objbase.s\n";
 
979
        $MANY_OBJS .= " $objbase.o";
 
980
 
 
981
      } elsif ($lang eq '.c') {
 
982
        print MAKEFILE
 
983
            "$objbase.o: $file_full\n" .
 
984
            "   \$(COMPILE) -DOPERATION_$obj $pic->{'cflags'} \\\n" .
 
985
            "$renaming" .
 
986
            "           -c $file_full -o $objbase.o\n";
 
987
        print_ansi2knr($objbase,
 
988
                       $file_full,
 
989
                       " -DOPERATION_$obj\\\n$renaming\t\t");
 
990
        $MANY_OBJS .= " $objbase\$U.o";
 
991
 
 
992
      } elsif ($lang eq '.S') {
 
993
        print MAKEFILE
 
994
            "$objbase.o: $file_full\n" .
 
995
            "   \$(COMPILE) -g $pic->{'asmflags'} \\\n" .
 
996
            "$renaming" .
 
997
            "   -c $file_full -o $objbase.o\n";
 
998
        $MANY_OBJS .= " $objbase.o";
 
999
 
 
1000
      } elsif ($lang eq '.h') {
 
1001
        print MAKEFILE
 
1002
            "$objbase.o: tmp-$objbase.c $file_full\n" .
 
1003
            "   \$(COMPILE) -DOPERATION_$obj $pic->{'cflags'} \\\n" .
 
1004
            "$renaming" .
 
1005
            "           -c tmp-$objbase.c -o $objbase.o\n";
 
1006
        print_ansi2knr($objbase,
 
1007
                       "tmp-$objbase.c",
 
1008
                       " -DOPERATION_$obj\\\n$renaming\t\t");
 
1009
        $MANY_OBJS .= " $objbase\$U.o";
 
1010
 
 
1011
        $CLEAN .= " tmp-$objbase.c";
 
1012
        open(TMP_C,">tmp-$objbase.c")
 
1013
            or die "Can't create tmp-$objbase.c: $!\n";
 
1014
        print TMP_C
 
1015
"/* tmp-$objbase.c generated by many.pl - DO NOT EDIT, CHANGES WILL BE LOST */
 
1016
 
 
1017
#include \"gmp.h\"
 
1018
#include \"gmp-impl.h\"
 
1019
#include \"longlong.h\"
 
1020
#include \"speed.h\"
 
1021
 
 
1022
";
 
1023
      }
 
1024
 
 
1025
      my $tests_program = "$top_srcdir/tests/devel/$obj.c";
 
1026
      if (-f $tests_program) {
 
1027
        $tests_program = "\$(top_srcdir)/tests/devel/$obj.c";
 
1028
        print_ansi2knr("tests_${objbase}",
 
1029
                       $tests_program,
 
1030
                       "\\\n$renaming\t\t\$(CFLAGS_TESTS_SP)");
 
1031
        print_ansi2knr("tests_${objbase}_sp",
 
1032
                       $tests_program,
 
1033
                       "\\\n$renaming\t\t\$(CFLAGS_TESTS_SP)");
 
1034
 
 
1035
        print MAKEFILE <<EOF;
 
1036
tests_$objbase.o: $tests_program
 
1037
        \$(COMPILE) \$(CFLAGS_TESTS) \\
 
1038
$renaming               -c $tests_program -o tests_$objbase.o
 
1039
 
 
1040
tests_$objbase: $objbase\$U.o tests_$objbase\$U.o ../libgmp.la
 
1041
        \$(LINK) tests_$objbase\$U.o $objbase\$U.o ../libgmp.la -o tests_$objbase
 
1042
 
 
1043
tests_${objbase}_sp.o: $tests_program
 
1044
        \$(COMPILE) \$(CFLAGS_TESTS_SP) \\
 
1045
$renaming               -c $tests_program -o tests_${objbase}_sp.o
 
1046
 
 
1047
tests_${objbase}_sp: $objbase\$U.o tests_${objbase}_sp\$U.o ../libgmp.la
 
1048
        \$(LINK) tests_${objbase}_sp\$U.o $objbase\$U.o ../libgmp.la -o tests_${objbase}_sp
 
1049
 
 
1050
EOF
 
1051
        $CLEAN .= " tests_$objbase tests_${objbase}_sp";
 
1052
      }
 
1053
 
 
1054
      foreach my $fun (@{$funs}) {
 
1055
        print "fun $fun\n" if $opt{'t'};
 
1056
 
 
1057
        if ($lang eq '.h') {
 
1058
          my $macro_before = $t->{'macro_before'};
 
1059
          $macro_before = "" if ! defined $macro_before;
 
1060
          print TMP_C
 
1061
"$macro_before
 
1062
#undef $fun
 
1063
#include \"$file_full\"
 
1064
 
 
1065
";
 
1066
        }
 
1067
 
 
1068
        my $args = $t->{"args_$fun"};
 
1069
        if (! defined $args) { $args = $t->{'args'}; }
 
1070
        if (! defined $args) { die "Need args for $fun\n"; }
 
1071
        print "args $args\n" if $opt{'t'};
 
1072
      
 
1073
        foreach my $carry (@$carrys) {
 
1074
          print "carry $carry\n" if $opt{'t'};
 
1075
 
 
1076
          my $fun_carry = $fun;
 
1077
          if (! ($fun_carry =~ s/_1/_1$carry/)) { $fun_carry = "$fun$carry"; }
 
1078
          print "fun_carry $fun_carry\n" if $opt{'t'};
 
1079
                    
 
1080
          if ($lang =~ /\.(asm|S)/
 
1081
              && ! grep(m"PROLOGUE.*$mpX$fun_carry",@file_contents)) {
 
1082
            print "no PROLOGUE $mpX$fun_carry\n" if $opt{'t'};
 
1083
            next;
 
1084
          }
 
1085
          if ($lang eq '.c'
 
1086
              && ! grep(m"^(#define FUNCTION\s+)?$mpX$fun_carry\W", @file_contents)) {
 
1087
            print "no mention of $mpX$fun_carry\n" if $opt{'t'};
 
1088
            next;
 
1089
          }
 
1090
          if ($lang eq '.h'
 
1091
              && ! grep(m"^#define $fun_carry\W", @file_contents)) {
 
1092
            print "no mention of #define $fun_carry\n" if $opt{'t'};
 
1093
            next;
 
1094
          }
 
1095
          
 
1096
          $count_functions++;
 
1097
 
 
1098
          my $carryarg;
 
1099
          if (defined $t->{'carryarg'}) { $carryarg = $t->{'carryarg'}; }
 
1100
          if ($carry eq '')             { $carryarg = ''; }
 
1101
          else                          { $carryarg = ', mp_limb_t carry'; }
 
1102
          print "carryarg $carryarg\n" if $opt{'t'};
 
1103
          
 
1104
          my $funfull="$mpX${fun_carry}_$suffix$pic->{'suffix'}";
 
1105
          print "funfull $funfull\n" if $opt{'t'};
 
1106
 
 
1107
          if ($lang ne '.h') {
 
1108
            my $attrib = $t->{'attrib'};
 
1109
            if (defined $attrib) { $attrib = " $attrib"; }
 
1110
            else { $attrib = ''; }
 
1111
 
 
1112
            my $proto = "$t->{'ret'} $funfull _PROTO (($args$carryarg))$attrib; \\\n";
 
1113
            $SPEED_EXTRA_PROTOS .= $proto;
 
1114
            $TRY_EXTRA_PROTOS .= $proto;
 
1115
          }
 
1116
          
 
1117
          my $try_type = $t->{"try-$fun"};
 
1118
          $try_type = $t->{'try'} if ! defined $try_type;
 
1119
          if (! defined $try_type) {
 
1120
            if ($mpX eq 'mpn_') {
 
1121
              $try_type = "TYPE_\U$fun_carry";
 
1122
            } else {
 
1123
              $try_type = "TYPE_\U$mpX\U$fun_carry";
 
1124
            }
 
1125
          }
 
1126
          print "try_type $try_type\n" if $opt{'t'};
 
1127
          
 
1128
          my $try_minsize = $t->{'try-minsize'};
 
1129
          if (defined $try_minsize) {
 
1130
            $try_minsize = ", " . $try_minsize;
 
1131
          } else {
 
1132
            $try_minsize = "";
 
1133
          }
 
1134
          print "try_minsize $try_minsize\n" if $opt{'t'};
 
1135
          
 
1136
          if ($try_type ne 'none') {
 
1137
            $TRY_EXTRA_ROUTINES .=
 
1138
                "  { TRY($mpX${fun_carry}_$suffix$pic->{'suffix'}), $try_type$try_minsize }, \\\n";
 
1139
          }
 
1140
 
 
1141
          my $speed_flags = $t->{'speed_flags'};
 
1142
          $speed_flags = '0' if ! defined $speed_flags;
 
1143
          print "speed_flags $speed_flags\n" if $opt{'t'};
 
1144
          
 
1145
          my $speed_routine = $t->{'speed'};
 
1146
          $speed_routine = "SPEED_ROUTINE_\U$mpX\U$fun"
 
1147
              if !defined $speed_routine;
 
1148
          if (! ($speed_routine =~ s/_1/_1\U$carry/)) {
 
1149
            $speed_routine = "$speed_routine\U$carry";
 
1150
          }
 
1151
          print "speed_routine $speed_routine\n" if $opt{'t'};
 
1152
          
 
1153
          my @speed_suffixes = ();
 
1154
          push (@speed_suffixes, '') if $speed_routine ne 'none';
 
1155
          push (@speed_suffixes, @{$t->{'speed_suffixes'}})
 
1156
              if defined $t->{'speed_suffixes'};
 
1157
          
 
1158
          my $macro_speed = $t->{'macro-speed'};
 
1159
          $macro_speed = "$speed_routine ($fun_carry)" if ! defined $macro_speed;
 
1160
          $macro_speed =~ s/\$fun/$fun_carry/g;
 
1161
 
 
1162
          foreach my $S (@speed_suffixes) {
 
1163
            my $Sfunfull="$mpX${fun_carry}${S}_$suffix$pic->{'suffix'}";
 
1164
            
 
1165
            $SPEED_EXTRA_PROTOS .=
 
1166
              "double speed_$Sfunfull _PROTO ((struct speed_params *s)); \\\n";
 
1167
            $SPEED_EXTRA_ROUTINES .=
 
1168
              "  { \"$Sfunfull\", speed_$Sfunfull, $speed_flags }, \\\n";
 
1169
            if ($lang eq '.h') {
 
1170
              print TMP_C
 
1171
"double
 
1172
speed_$Sfunfull (struct speed_params *s)
 
1173
{
 
1174
$macro_speed
 
1175
}
 
1176
 
 
1177
";
 
1178
            } else {
 
1179
              $SPEED_CODE .=
 
1180
                "double\n" .
 
1181
                "speed_$Sfunfull (struct speed_params *s)\n" .
 
1182
                "{\n" .
 
1183
                "$restriction" .
 
1184
                "  $speed_routine\U$S\E ($funfull)\n" .
 
1185
                "}\n";
 
1186
            }
 
1187
          }
 
1188
        }
 
1189
      }
 
1190
    }
 
1191
  }
 
1192
}
 
1193
 
 
1194
 
 
1195
print SPEED $SPEED_EXTRA_PROTOS . "\n";
 
1196
print SPEED $SPEED_EXTRA_ROUTINES . "\n";
 
1197
if (defined $ENV{speedinc}) { print SPEED $ENV{speedinc} . "\n"; }
 
1198
print SPEED
 
1199
    "#include \"speed.c\"\n" .
 
1200
    "\n";
 
1201
print SPEED $SPEED_CODE;
 
1202
 
 
1203
print TRY $TRY_EXTRA_ROUTINES . "\n";
 
1204
print TRY $TRY_EXTRA_PROTOS . "\n";
 
1205
my $tryinc = "";
 
1206
if (defined $ENV{tryinc}) {
 
1207
  $tryinc = $ENV{tryinc};
 
1208
  print TRY "#include \"$tryinc\"\n";
 
1209
}
 
1210
print "tryinc $tryinc\n" if $opt{'t'};
 
1211
print TRY
 
1212
    "#include \"try.c\"\n" .
 
1213
    "\n";
 
1214
 
 
1215
my $extra_libraries = "";
 
1216
if (defined $ENV{extra_libraries}) { $extra_libraries = $ENV{extra_libraries};}
 
1217
 
 
1218
my $trydeps = "";
 
1219
if (defined $ENV{trydeps}) { $trydeps = $ENV{trydeps}; }
 
1220
$trydeps .= " $tryinc";
 
1221
print "trydeps $trydeps\n" if $opt{'t'};
 
1222
 
 
1223
print MAKEFILE <<EOF;
 
1224
 
 
1225
MANY_OBJS = $MANY_OBJS
 
1226
MANY_CLEAN = \$(MANY_OBJS) \\
 
1227
        speed-many.c speed-many\$U.o speed-many\$(EXEEXT) \\
 
1228
        try-many.c try-many\$U.o try-many \\
 
1229
        $CLEAN
 
1230
MANY_DISTCLEAN = Makefile.many
 
1231
 
 
1232
speed-many: \$(MANY_OBJS) speed-many\$U.o libspeed.la $extra_libraries
 
1233
        \$(LINK) \$(LDFLAGS) speed-many\$U.o \$(MANY_OBJS) \$(LDADD) \$(LIBS) $extra_libraries
 
1234
 
 
1235
try-many: \$(MANY_OBJS) try-many\$U.o libspeed.la $extra_libraries
 
1236
        \$(LINK) \$(LDFLAGS) try-many\$U.o \$(MANY_OBJS)  \$(LDADD) \$(LIBS) $extra_libraries
 
1237
 
 
1238
try-many.o: try-many.c \$(top_srcdir)/tests/devel/try.c $trydeps
 
1239
        \$(COMPILE) -I\$(top_srcdir)/tests/devel -c try-many.c
 
1240
 
 
1241
EOF
 
1242
 
 
1243
print_ansi2knr("speed-many");
 
1244
print_ansi2knr("try-many",
 
1245
               "\$(top_srcdir)/tests/devel/try.c",
 
1246
               "-I\$(top_srcdir)/tests/devel");
 
1247
 
 
1248
print MAKEFILE <<EOF;
 
1249
RM_TMP = rm -f
 
1250
CFLAGS_TESTS = -DSIZE=50 -DTIMES=1 -DRANDOM -DCLOCK=333000000
 
1251
CFLAGS_TESTS_SP = -DSIZE=1024 -DNOCHECK -DOPS=200000000 -DCLOCK=333000000
 
1252
EOF
 
1253
 
 
1254
 
 
1255
print "Total $count_files files, $count_functions functions\n";    
 
1256
 
 
1257
 
 
1258
 
 
1259
# Local variables:
 
1260
# perl-indent-level: 2
 
1261
# End: