1/* Copyright (c) 1998 Apple Computer, Inc.  All rights reserved.
2 *
3 * giantAsmBench.c - Benchmark of platform-specific giantInteger primitives.
4 *
5 * Revision History
6 * ----------------
7 * 18 Apr 98	Doug Mitchell at Apple
8 * 	Created.
9 */
10
11#include <security_cryptkit/giantPortCommon.h>
12#include <security_cryptkit/feeDebug.h>
13#include <security_cryptkit/feeFunctions.h>
14#include <stdlib.h>
15#include "ckutilsPlatform.h"
16#include <stdio.h>
17#include <time.h>
18
19#define LOOPS_DEF	10000
20#define MIN_SIZE_DEF	1	/* mix digits for vectorMultiply test */
21#define MAX_SIZE_DEF	8	/* max digits */
22
23
24static void usage(char **argv)
25{
26	printf("usage: %s [options]\n", argv[0]);
27	printf("   Options:\n");
28	printf("   l=loops    (default = %d)\n", LOOPS_DEF);
29	printf("   n=maxDigits (default = %d)\n", MIN_SIZE_DEF);
30	printf("   x=maxDigits (default = %d)\n", MAX_SIZE_DEF);
31	printf("   s=seed\n");
32	printf("   h(elp)\n");
33	exit(1);
34}
35
36/*
37 * Fill buffer with random data. Assumes giantDigits is native int size.
38 */
39static void randDigits(unsigned numDigits,
40	giantDigit *digits)
41{
42	int 		i;
43
44	for(i=0; i<numDigits; i++) {
45		/* RAND() only returns 31 bits on Unix.... */
46		digits[i]= RAND() + ((RAND() & 1) << 31);
47	}
48}
49
50
51
52int main(int argc, char **argv)
53{
54	int		arg;
55	char		*argp;
56	giantDigit	*digit1;		// mallocd arrays
57	giantDigit	*digit2;
58	giantDigit	*vect1;
59	giantDigit	*vect2;
60	giantDigit	*dig1p;			// ptr into mallocd arrays
61	giantDigit	*dig2p;
62	giantDigit	*vect1p;
63	giantDigit	*vect2p;
64	unsigned	numDigits;
65	unsigned	i;
66	PLAT_TIME	startTime;
67	PLAT_TIME	endTime;
68	unsigned	elapsed;
69	giantDigit	scr1;			// op result
70	giantDigit	scr2;			// op result
71	int 		loops = LOOPS_DEF;
72	int		seedSpec = 0;
73	unsigned	seed = 0;
74	unsigned	maxSize = MAX_SIZE_DEF;
75	unsigned	minSize = MIN_SIZE_DEF;
76
77	initCryptKit();
78
79	#if	macintosh
80	argc = ccommand(&argv);
81	#endif
82
83	for(arg=1; arg<argc; arg++) {
84		argp = argv[arg];
85		switch(argp[0]) {
86		    case 'x':
87		    	maxSize = atoi(&argp[2]);
88			break;
89		    case 'n':
90		    	minSize = atoi(&argp[2]);
91			break;
92		    case 'l':
93		    	loops = atoi(&argp[2]);
94			break;
95		    case 's':
96			seed = atoi(&argp[2]);
97			seedSpec = 1;
98			break;
99		    case 'h':
100		    default:
101		    	usage(argv);
102		}
103	}
104
105	if(!seedSpec) {
106		unsigned long	tim;
107		time(&tim);
108		seed = (unsigned)tim;
109	}
110	SRAND(seed);
111
112	/*
113	 * Scratch digits, big enough for anything. Malloc here, init with
114	 * random data before each test.
115	 */
116	digit1 = malloc(sizeof(giantDigit) * loops * 2);
117	digit2 = malloc(sizeof(giantDigit) * loops * 2);
118
119	/* vect1 and vect2 are arrays of giantDigit arrays */
120	vect1 = malloc(sizeof(giantDigit) * loops * maxSize);
121	vect2 = malloc(sizeof(giantDigit) * loops * maxSize);
122
123	if((digit1 == NULL) || (digit1 == NULL) ||
124	   (vect1 == NULL) || (vect2 == NULL)) {
125	    printf("malloc error\n");
126	    exit(1);
127	}
128
129	printf("Starting giantAsm test: seed %d\n", seed);
130
131	/* giantAddDigits test */
132	randDigits(loops, digit1);
133	randDigits(loops, digit2);
134	dig1p = digit1;
135	dig2p = digit2;
136	PLAT_GET_TIME(startTime);
137	for(i=0; i<loops; i++) {
138		scr1 = giantAddDigits(*dig1p++, *dig2p++, &scr2);
139	}
140	PLAT_GET_TIME(endTime);
141	elapsed = PLAT_GET_NS(startTime, endTime);
142	printf("giantAddDigits: %f ns\n",
143		(double)elapsed / (double)loops);
144
145	/* giantAddDouble test */
146	randDigits(loops, digit1);
147	randDigits(loops * 2, digit2);
148	dig1p = digit1;
149	dig2p = digit2;
150	PLAT_GET_TIME(startTime);
151	for(i=0; i<loops; i++) {
152		giantAddDouble(dig2p, dig2p+1, *dig1p++);
153		dig2p += 2;
154	}
155	PLAT_GET_TIME(endTime);
156	elapsed = PLAT_GET_NS(startTime, endTime);
157	printf("giantAddDouble: %f ns\n",
158		(double)elapsed / (double)loops);
159
160	/* giantSubDigits test */
161	randDigits(loops, digit1);
162	randDigits(loops, digit2);
163	dig1p = digit1;
164	dig2p = digit2;
165	PLAT_GET_TIME(startTime);
166	for(i=0; i<loops; i++) {
167		scr1 = giantSubDigits(*dig1p++, *dig2p++, &scr2);
168	}
169	PLAT_GET_TIME(endTime);
170	elapsed = PLAT_GET_NS(startTime, endTime);
171	printf("giantSubDigits: %f ns\n",
172		(double)elapsed / (double)loops);
173
174	/* giantMulDigits test */
175	randDigits(loops, digit1);
176	randDigits(loops, digit2);
177	dig1p = digit1;
178	dig2p = digit2;
179	PLAT_GET_TIME(startTime);
180	for(i=0; i<loops; i++) {
181		giantMulDigits(*dig1p++, *dig2p++, &scr1, &scr2);
182	}
183	PLAT_GET_TIME(endTime);
184	elapsed = PLAT_GET_NS(startTime, endTime);
185	printf("giantMulDigits: %f ns\n",
186		(double)elapsed / (double)loops);
187
188	printf("\nvectorMultiply:\n");
189	for(numDigits=minSize; numDigits<=maxSize; numDigits*=2) {
190
191		randDigits(loops, digit1);		// plierDigit
192		randDigits(loops * numDigits, vect1);	// candVector
193		randDigits(loops * numDigits, vect2);	// prodVector
194		dig1p = digit1;
195		vect1p = vect1;
196		vect2p = vect2;
197
198		PLAT_GET_TIME(startTime);
199		for(i=0; i<loops; i++) {
200			scr1 = VectorMultiply(*dig1p++,	// plierDigit
201				vect1p,			// candVector
202				numDigits,
203				vect2p);		// prodVector
204			vect1p += numDigits;
205			vect2p += numDigits;
206		}
207		PLAT_GET_TIME(endTime);
208		elapsed = PLAT_GET_NS(startTime, endTime);
209		printf(" bits = %4d  : %f ns\n",
210			numDigits * GIANT_BITS_PER_DIGIT,
211			(double)elapsed / (double)loops);
212
213		} /* for numDigits */
214	return 0;
215}
216