Skip to content

Commit d644dda

Browse files
Merge #689: Remove "except in benchmarks" exception for fp math
bde2a32 Convert bench.h to fixed-point math (Wladimir J. van der Laan) Pull request description: Convert `bench.h` to fixed-point math, removing all use of float math from the repository: - Use 64-bit integer microsecond timestamps - Use decimal fixed-point math for formatting numbers It turned out to be a little trickier than I expected because of formatting and rounding. But, output should be the same before and after. I used the following to test the number formatting: https://gist.github.com/laanwj/f971bfbe018e39c19677a21ff954d0c7 ACKs for top commit: real-or-random: ACK bde2a32 I've read the code in detail and I've tested it. I haven't explicitly tested the formatting function with known/hardcoded inputs. Tree-SHA512: 41ab6024b88c65a4b194272097c70d527bedb396dc7ab9d3d93165f1a19d31092798370f66399443a8d5393d0a6dcf5825679de5a325550865cfdef3586bf64c
2 parents 387d723 + bde2a32 commit d644dda

File tree

2 files changed

+63
-21
lines changed

2 files changed

+63
-21
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Implementation details
2323
* Extensive testing infrastructure.
2424
* Structured to facilitate review and analysis.
2525
* Intended to be portable to any system with a C89 compiler and uint64_t support.
26-
* No use of floating types, except in benchmarks.
26+
* No use of floating types.
2727
* Expose only higher level interfaces to minimize the API surface and improve application security. ("Be difficult to use insecurely.")
2828
* Field operations
2929
* Optimized implementation of arithmetic modulo the curve's field size (2^256 - 0x1000003D1).

src/bench.h

Lines changed: 62 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,43 +7,85 @@
77
#ifndef SECP256K1_BENCH_H
88
#define SECP256K1_BENCH_H
99

10+
#include <stdint.h>
1011
#include <stdio.h>
1112
#include <string.h>
12-
#include <math.h>
1313
#include "sys/time.h"
1414

15-
static double gettimedouble(void) {
15+
static int64_t gettime_i64(void) {
1616
struct timeval tv;
1717
gettimeofday(&tv, NULL);
18-
return tv.tv_usec * 0.000001 + tv.tv_sec;
18+
return (int64_t)tv.tv_usec + (int64_t)tv.tv_sec * 1000000LL;
1919
}
2020

21-
void print_number(double x) {
22-
double y = x;
23-
int c = 0;
24-
if (y < 0.0) {
25-
y = -y;
21+
#define FP_EXP (6)
22+
#define FP_MULT (1000000LL)
23+
24+
/* Format fixed point number. */
25+
void print_number(const int64_t x) {
26+
int64_t x_abs, y;
27+
int c, i, rounding;
28+
size_t ptr;
29+
char buffer[30];
30+
31+
if (x == INT64_MIN) {
32+
/* Prevent UB. */
33+
printf("ERR");
34+
return;
2635
}
27-
while (y > 0 && y < 100.0) {
28-
y *= 10.0;
36+
x_abs = x < 0 ? -x : x;
37+
38+
/* Determine how many decimals we want to show (more than FP_EXP makes no
39+
* sense). */
40+
y = x_abs;
41+
c = 0;
42+
while (y > 0LL && y < 100LL * FP_MULT && c < FP_EXP) {
43+
y *= 10LL;
2944
c++;
3045
}
31-
printf("%.*f", c, x);
46+
47+
/* Round to 'c' decimals. */
48+
y = x_abs;
49+
rounding = 0;
50+
for (i = c; i < FP_EXP; ++i) {
51+
rounding = (y % 10) >= 5;
52+
y /= 10;
53+
}
54+
y += rounding;
55+
56+
/* Format and print the number. */
57+
ptr = sizeof(buffer) - 1;
58+
buffer[ptr] = 0;
59+
if (c != 0) {
60+
for (i = 0; i < c; ++i) {
61+
buffer[--ptr] = '0' + (y % 10);
62+
y /= 10;
63+
}
64+
buffer[--ptr] = '.';
65+
}
66+
do {
67+
buffer[--ptr] = '0' + (y % 10);
68+
y /= 10;
69+
} while (y != 0);
70+
if (x < 0) {
71+
buffer[--ptr] = '-';
72+
}
73+
printf("%s", &buffer[ptr]);
3274
}
3375

3476
void run_benchmark(char *name, void (*benchmark)(void*), void (*setup)(void*), void (*teardown)(void*), void* data, int count, int iter) {
3577
int i;
36-
double min = HUGE_VAL;
37-
double sum = 0.0;
38-
double max = 0.0;
78+
int64_t min = INT64_MAX;
79+
int64_t sum = 0;
80+
int64_t max = 0;
3981
for (i = 0; i < count; i++) {
40-
double begin, total;
82+
int64_t begin, total;
4183
if (setup != NULL) {
4284
setup(data);
4385
}
44-
begin = gettimedouble();
86+
begin = gettime_i64();
4587
benchmark(data);
46-
total = gettimedouble() - begin;
88+
total = gettime_i64() - begin;
4789
if (teardown != NULL) {
4890
teardown(data);
4991
}
@@ -56,11 +98,11 @@ void run_benchmark(char *name, void (*benchmark)(void*), void (*setup)(void*), v
5698
sum += total;
5799
}
58100
printf("%s: min ", name);
59-
print_number(min * 1000000.0 / iter);
101+
print_number(min * FP_MULT / iter);
60102
printf("us / avg ");
61-
print_number((sum / count) * 1000000.0 / iter);
103+
print_number(((sum * FP_MULT) / count) / iter);
62104
printf("us / max ");
63-
print_number(max * 1000000.0 / iter);
105+
print_number(max * FP_MULT / iter);
64106
printf("us\n");
65107
}
66108

0 commit comments

Comments
 (0)