Merge #689: Remove "except in benchmarks" exception for fp math
bde2a32286
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: ACKbde2a32286
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
This commit is contained in:
commit
d644dda5c9
|
@ -23,7 +23,7 @@ Implementation details
|
|||
* Extensive testing infrastructure.
|
||||
* Structured to facilitate review and analysis.
|
||||
* Intended to be portable to any system with a C89 compiler and uint64_t support.
|
||||
* No use of floating types, except in benchmarks.
|
||||
* No use of floating types.
|
||||
* Expose only higher level interfaces to minimize the API surface and improve application security. ("Be difficult to use insecurely.")
|
||||
* Field operations
|
||||
* Optimized implementation of arithmetic modulo the curve's field size (2^256 - 0x1000003D1).
|
||||
|
|
82
src/bench.h
82
src/bench.h
|
@ -7,43 +7,85 @@
|
|||
#ifndef SECP256K1_BENCH_H
|
||||
#define SECP256K1_BENCH_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "sys/time.h"
|
||||
|
||||
static double gettimedouble(void) {
|
||||
static int64_t gettime_i64(void) {
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return tv.tv_usec * 0.000001 + tv.tv_sec;
|
||||
return (int64_t)tv.tv_usec + (int64_t)tv.tv_sec * 1000000LL;
|
||||
}
|
||||
|
||||
void print_number(double x) {
|
||||
double y = x;
|
||||
int c = 0;
|
||||
if (y < 0.0) {
|
||||
y = -y;
|
||||
#define FP_EXP (6)
|
||||
#define FP_MULT (1000000LL)
|
||||
|
||||
/* Format fixed point number. */
|
||||
void print_number(const int64_t x) {
|
||||
int64_t x_abs, y;
|
||||
int c, i, rounding;
|
||||
size_t ptr;
|
||||
char buffer[30];
|
||||
|
||||
if (x == INT64_MIN) {
|
||||
/* Prevent UB. */
|
||||
printf("ERR");
|
||||
return;
|
||||
}
|
||||
while (y > 0 && y < 100.0) {
|
||||
y *= 10.0;
|
||||
x_abs = x < 0 ? -x : x;
|
||||
|
||||
/* Determine how many decimals we want to show (more than FP_EXP makes no
|
||||
* sense). */
|
||||
y = x_abs;
|
||||
c = 0;
|
||||
while (y > 0LL && y < 100LL * FP_MULT && c < FP_EXP) {
|
||||
y *= 10LL;
|
||||
c++;
|
||||
}
|
||||
printf("%.*f", c, x);
|
||||
|
||||
/* Round to 'c' decimals. */
|
||||
y = x_abs;
|
||||
rounding = 0;
|
||||
for (i = c; i < FP_EXP; ++i) {
|
||||
rounding = (y % 10) >= 5;
|
||||
y /= 10;
|
||||
}
|
||||
y += rounding;
|
||||
|
||||
/* Format and print the number. */
|
||||
ptr = sizeof(buffer) - 1;
|
||||
buffer[ptr] = 0;
|
||||
if (c != 0) {
|
||||
for (i = 0; i < c; ++i) {
|
||||
buffer[--ptr] = '0' + (y % 10);
|
||||
y /= 10;
|
||||
}
|
||||
buffer[--ptr] = '.';
|
||||
}
|
||||
do {
|
||||
buffer[--ptr] = '0' + (y % 10);
|
||||
y /= 10;
|
||||
} while (y != 0);
|
||||
if (x < 0) {
|
||||
buffer[--ptr] = '-';
|
||||
}
|
||||
printf("%s", &buffer[ptr]);
|
||||
}
|
||||
|
||||
void run_benchmark(char *name, void (*benchmark)(void*), void (*setup)(void*), void (*teardown)(void*), void* data, int count, int iter) {
|
||||
int i;
|
||||
double min = HUGE_VAL;
|
||||
double sum = 0.0;
|
||||
double max = 0.0;
|
||||
int64_t min = INT64_MAX;
|
||||
int64_t sum = 0;
|
||||
int64_t max = 0;
|
||||
for (i = 0; i < count; i++) {
|
||||
double begin, total;
|
||||
int64_t begin, total;
|
||||
if (setup != NULL) {
|
||||
setup(data);
|
||||
}
|
||||
begin = gettimedouble();
|
||||
begin = gettime_i64();
|
||||
benchmark(data);
|
||||
total = gettimedouble() - begin;
|
||||
total = gettime_i64() - begin;
|
||||
if (teardown != NULL) {
|
||||
teardown(data);
|
||||
}
|
||||
|
@ -56,11 +98,11 @@ void run_benchmark(char *name, void (*benchmark)(void*), void (*setup)(void*), v
|
|||
sum += total;
|
||||
}
|
||||
printf("%s: min ", name);
|
||||
print_number(min * 1000000.0 / iter);
|
||||
print_number(min * FP_MULT / iter);
|
||||
printf("us / avg ");
|
||||
print_number((sum / count) * 1000000.0 / iter);
|
||||
print_number(((sum * FP_MULT) / count) / iter);
|
||||
printf("us / max ");
|
||||
print_number(max * 1000000.0 / iter);
|
||||
print_number(max * FP_MULT / iter);
|
||||
printf("us\n");
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue