Title | kmul (Constant multiplication routine generator) |
Author | Nikolaos Kavvadias |
Contact | nikolaos.kavvadias@gmail.com |
Website | http://www.nkavvadias.com |
Release Date | 04 January 2021 |
Version | 0.1.5 |
Rev. history | |
|
2021-01-04 Remove |
|
2020-10-17 Add a binary decomposition algorithm. |
|
2016-07-29 Add support for C99, GNU89 data types, fix support for ANSI C ones. |
|
2016-04-12 Cumulative update; flag management cleanup, cleanup scripts. |
|
2014-11-29 Added project logo in README. |
|
2014-10-16 Documentation updates and fixes. |
|
2014-06-13 Changed README to README.rst. |
|
2014-06-12 Updated contact information. Replaced COPYING.BSD by LICENSE. |
|
2013-04-28 Converted documentation to RestructuredText. |
|
2012-03-17 Split build-and-test scripts to "build" and "test". |
|
2011-12-03 Minor README updates regarding multiple releases, tutorial usage. |
|
2011-11-20 Minor README, Makefile updates. |
|
2011-06-07 Initial release. |
kmul
is a generator of routines for optimized multiplication by an integer constant. In order to calculate a constant integer multiplication, it uses the public domain routines presented in the work: Preston Briggs and Tim Harvey, "Multiplication by integer constants," Technical report, Rice University, July 1994. This technical report implements Bernstein's algorithm documented in: R. Bernstein, "Multiplication by integer constants," Software - Practice and Experience, Vol. 16, No. 7, pp. 641-652, July 1986.
A simpler algorithm based on binary decomposition can also be used for comparison.
kmul
emits either a NAC (generic assembly language) or an ANSI C/C99 implementation of the multiplication.
The kmul
distribution includes the following files:
/kmul | Top-level directory |
LICENSE | Description of the Modified BSD license. |
Makefile | Makefile for generating the kmul executable. |
README.html | HTML version of README.rst. |
README.pdf | PDF version of README.rst. |
README.rst | This file. |
build.sh | Build script for kmul . |
clean.sh | Clean the files produced from test.sh . |
clean2.sh | Clean the files produced from test2.sh . |
kmul.c | The source code for the application. |
kmul.png | PNG image for the kmul project logo. |
rst2docs.sh | Bash script for generating the HTML and PDF versions. |
test.c | Sample test file. |
test.opt.c | Expected optimized version of test.c . |
test.sh | Perform some sample runs. |
test2.sh | Another test script to perform more sample runs. |
There exists a quite portable Makefile (Makefile
in the current directory). Running make
from the command prompt should compile kmul
.
- [mandatory for building] Standard UNIX-based tools (make)
- gcc (tested with gcc-3.4.4+ on cygwin/x86 and gcc-4.6+ on linux/x64)
- bash
The kmul
program can be invoked with several options (see complete option listing below). The usual tasks that can be accomplished with kmul
are:
- generate a NAC optimized software routine for the multiplication
- generate an ANSI C optimized software routine for the multiplication.
ANSI C routines are emitted only for a width of 32-bits (see option below).
kmul
can be invoked as:
$ ./kmul.exe [options]
The complete kmul
options listing:
- -h
Print this help.
- -d
Enable debug/diagnostic output.
- -bindecomp
Use binary decomposition instead of the Bernstein-Briggs algorithm.
- -mul <num>
Set the value of the multiplier. Default: 1.
- -width <num>
Set the bitwidth of all operands: multiplier, multiplicand and product. Default: 32.
- -signed
Construct optimized routine for signed multiplication.
- -unsigned
Construct optimized routine for unsigned multiplication (default).
- -nac
Emit software routine in the NAC general assembly language (default).
- -ansic
Emit software routine in ANSI C (for widths up to 32 bits).
- -c99
Emit software routine in C99 (for widths up to 64 bits).
Here follow some simple usage examples of kmul
.
- Generate the ANSI C implementation of the optimized routine for
n * 11
.
$ ./kmul.exe -mul 11 -width 32 -unsigned -ansic
- Generate the NAC implementation of the optimized routine for
n * (-7)
.
$ ./kmul.exe -mul -7 -width 32 -signed -ansic
- Generate the ANSI C implementation of the optimized routine for
n * 23
with debugging output.
$ ./kmul.exe -mul 23 -width 32 -unsigned -ansic -d
- Generate the C99 implementation of the optimized routine for the signed
n * 23
multiplication and for a data width of 17 bits.
$ ./kmul.exe -mul 23 -width 17 -signed -c99
kmul
can be used for arithmetic optimizations in user programs. Assume the following user program (test.c
):
// test.c
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
int a, b;
a = atoi(argv[1]);
b = a * 23;
printf("b = %d\n", b);
return b;
}
This file is compiled and run as follows with one additional argument:
$ gcc -Wall -O2 -o test.exe test.c
$ ./test.exe 155
and the expected result is:
$ b = 3565
The user can apply kmul
for generating a constant multiplication routine for a*23
:
$ ./kmul -mul 23 -width 32 -signed -ansic
and the corresponding routine is produced (local variables t5
to t15
can be deleted by the user; the compiler will be optimize them away eventually). Then, the user should edit a new file, let's say test.opt.c
and include the produced routine. The resulting optimized source file should be as follows:
// test.opt.c
#include <stdio.h>
#include <stdlib.h>
long kmul_o_s32_p_23 (long x)
{
long t0;
long t1;
long t2;
long t3;
long t4;
long t5;
long t6;
long t7;
long t8;
long t9;
long t10;
long t11;
long t12;
long t13;
long t14;
long t15;
long y;
t0 = x;
t1 = t0 << 1;
t2 = t1 + x;
t3 = t2 << 3;
t4 = t3 - x;
y = t4;
return (y);
}
int main(int argc, char *argv[])
{
int a, b;
a = atoi(argv[1]);
b = kmul_o_s32_p_23(a);
printf("b = %d\n", b);
return b;
}
This file is compiled and run as follows with one additional argument:
$ gcc -Wall -O2 -o test.opt.exe test.opt.c
$ ./test.opt.exe 155
The target platform compiler (e.g., gcc
or llvm
) is expected to inline the kmul_o_s32_p_23
function at its call site.
In order to build and run a series of sample tests do the following:
$ ./build.sh
$ ./test.sh
or for a more extensive set of tests:
$ ./test2.sh
To clean-up the produced files and only these use:
$ ./clean.sh
or
$ ./clean2.sh
for test.sh
and test2.sh
, correspondingly.