Skip to content

Commit 149b77d

Browse files
committed
Update C++ fixture runner
1 parent 07e1827 commit 149b77d

7 files changed

Lines changed: 363 additions & 183 deletions

File tree

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
2+
# VARIABLES #
3+
4+
ifndef VERBOSE
5+
QUIET := @
6+
endif
7+
8+
# Specify the path to Boost:
9+
BOOST ?=
10+
11+
# Determine the OS:
12+
#
13+
# [1]: https://en.wikipedia.org/wiki/Uname#Examples
14+
# [2]: http://stackoverflow.com/a/27776822/2225624
15+
OS ?= $(shell uname)
16+
ifneq (, $(findstring MINGW,$(OS)))
17+
OS := WINNT
18+
else
19+
ifneq (, $(findstring MSYS,$(OS)))
20+
OS := WINNT
21+
else
22+
ifneq (, $(findstring CYGWIN,$(OS)))
23+
OS := WINNT
24+
endif
25+
endif
26+
endif
27+
28+
# Define the program used for compiling C++ source files:
29+
ifdef CXX_COMPILER
30+
CXX := $(CXX_COMPILER)
31+
else
32+
CXX := g++
33+
endif
34+
35+
# Define the command-line options when compiling C++ files:
36+
CXXFLAGS ?= \
37+
-std=c++11 \
38+
-O3 \
39+
-Wall \
40+
-pedantic
41+
42+
# Determine whether to generate [position independent code][1]:
43+
#
44+
# [1]: https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#Code-Gen-Options
45+
# [2]: http://stackoverflow.com/questions/5311515/gcc-fpic-option
46+
ifeq ($(OS), WINNT)
47+
fPIC ?=
48+
else
49+
fPIC ?= -fPIC
50+
endif
51+
52+
# List of C++ targets:
53+
cxx_targets := runner.out
54+
55+
56+
# TARGETS #
57+
58+
# Default target.
59+
#
60+
# This target is the default target.
61+
62+
all: $(cxx_targets)
63+
64+
.PHONY: all
65+
66+
67+
# Compile C++ source.
68+
#
69+
# This target compiles C++ source files.
70+
71+
$(cxx_targets): %.out: %.cpp $(BOOST)
72+
$(QUIET) $(CXX) $(CXXFLAGS) $(fPIC) -I $(BOOST) -o $@ $< -lm
73+
74+
75+
# Generate text fixtures.
76+
#
77+
# This target generates test fixtures.
78+
79+
run: $(cxx_targets)
80+
$(QUIET) ./$<
81+
82+
.PHONY: run
83+
84+
85+
# Perform clean-up.
86+
#
87+
# This target removes generated files.
88+
89+
clean:
90+
$(QUIET) -rm -f *.o *.out
91+
92+
.PHONY: clean
93+
94+
95+
# Remove fixtures.
96+
#
97+
# This target removes fixture data.
98+
99+
clean-fixtures:
100+
$(QUIET) -rm -f *.json
101+
102+
.PHONY: clean-fixtures
Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
/**
2+
* Generate Boost test fixtures.
3+
*
4+
* ## Notes
5+
*
6+
* - Run this script from the directory in which fixtures should be written.
7+
*
8+
*/
9+
#include <stdlib.h>
10+
#include <stdio.h>
11+
#include <unistd.h>
12+
#include <math.h>
13+
#include <sys/time.h>
14+
#include <boost/random/mersenne_twister.hpp>
15+
#include <boost/random/uniform_int_distribution.hpp>
16+
#include <boost/random/uniform_real_distribution.hpp>
17+
#include <boost/math/special_functions/gamma.hpp>
18+
19+
using boost::random::uniform_real_distribution;
20+
using boost::random::uniform_int_distribution;
21+
using boost::random::mt19937;
22+
23+
// Define a new pseudorandom number generator:
24+
mt19937 rng;
25+
26+
/**
27+
* Generates a linearly spaced numeric array of doubles.
28+
*
29+
* ## Notes
30+
*
31+
* - Assumes that the output array has at least 2 elements.
32+
* - Output array is guaranteed to include both the start and end values.
33+
*
34+
*
35+
* @param out output array
36+
* @param len array length
37+
* @param start first value
38+
* @param end last value
39+
*/
40+
void linspace_f64( double *out, const unsigned int len, const double start, const double end ) {
41+
unsigned int i;
42+
double incr;
43+
44+
incr = (end-start) / (len-1);
45+
for ( i = 0; i < len-1; i++ ) {
46+
out[ i ] = start + (incr*i);
47+
}
48+
out[ i ] = end;
49+
}
50+
51+
/**
52+
* Generates a linearly spaced numeric array of integers.
53+
*
54+
* ## Notes
55+
*
56+
* - Assumes that the output array has at least 2 elements.
57+
* - Output array is guaranteed to include both the start and end values.
58+
*
59+
*
60+
* @param out output array
61+
* @param len array length
62+
* @param start first value
63+
* @param end last value
64+
*/
65+
void linspace_i32( int *out, const unsigned int len, const int start, const int end ) {
66+
unsigned int i;
67+
int incr;
68+
69+
incr = (end-start) / (len-1);
70+
for ( i = 0; i < len-1; i++ ) {
71+
out[ i ] = start + (incr*i);
72+
}
73+
out[ i ] = end;
74+
}
75+
76+
/**
77+
* Generates an array of pseudorandom doubles drawn from a uniform distribution.
78+
*
79+
* @param out output array
80+
* @param len array length
81+
* @param a lower bound (inclusive)
82+
* @param b upper bound (exclusive)
83+
*/
84+
void rand_array_f64( double *out, const unsigned int len, const double a, const double b ) {
85+
unsigned int i;
86+
87+
// Define a uniform distribution for generating pseudorandom numbers:
88+
uniform_real_distribution<> randu( a, b );
89+
90+
for ( i = 0; i < len; i++ ) {
91+
out[ i ] = randu( rng );
92+
}
93+
}
94+
95+
/**
96+
* Generates an array of pseudorandom integers drawn from a uniform distribution.
97+
*
98+
* @param out output array
99+
* @param len array length
100+
* @param a lower bound (inclusive)
101+
* @param b upper bound (exclusive)
102+
*/
103+
void rand_array_i32( int *out, const unsigned int len, const int a, const int b ) {
104+
unsigned int i;
105+
106+
// Define a uniform distribution for generating pseudorandom numbers:
107+
uniform_int_distribution<> randi( a, b );
108+
109+
for ( i = 0; i < len; i++ ) {
110+
out[ i ] = randi( rng );
111+
}
112+
}
113+
114+
/**
115+
* Writes an array of doubles to a file as a series of comma-separated values.
116+
*
117+
* @param f file to write to
118+
* @param x array of doubles
119+
* @param len array length
120+
*/
121+
void write_array_f64( FILE *f, const double *x, const unsigned int len ) {
122+
unsigned int i;
123+
124+
for ( i = 0; i < len; i++ ) {
125+
fprintf( f, "%.17g", x[ i ] );
126+
if ( i < len-1 ) {
127+
fprintf( f, "," );
128+
}
129+
}
130+
}
131+
132+
/**
133+
* Writes an array of integers to a file as a series of comma-separated values.
134+
*
135+
* @param f file to write to
136+
* @param x array of integers
137+
* @param len array length
138+
*/
139+
void write_array_i32( FILE *f, const int *x, const unsigned int len ) {
140+
unsigned int i;
141+
142+
for ( i = 0; i < len; i++ ) {
143+
fprintf( f, "%d", x[ i ] );
144+
if ( i < len-1 ) {
145+
fprintf( f, "," );
146+
}
147+
}
148+
}
149+
150+
/**
151+
* Writes a named array of doubles to a file as JSON.
152+
*
153+
* @param f file to write to
154+
* @param name array name
155+
* @param x data
156+
* @param len array length
157+
*/
158+
void write_named_array_f64( FILE *f, const char *name, const double *x, const unsigned int len ) {
159+
fprintf( f, "\"%s\":[", name );
160+
write_array_f64( f, x, len );
161+
fprintf( f, "]" );
162+
}
163+
164+
/**
165+
* Writes a named array of integers to a file as JSON.
166+
*
167+
* @param f file to write to
168+
* @param name array name
169+
* @param x data
170+
* @param len array length
171+
*/
172+
void write_named_array_i32( FILE *f, const char *name, const int *x, const unsigned int len ) {
173+
fprintf( f, "\"%s\":[", name );
174+
write_array_i32( f, x, len );
175+
fprintf( f, "]" );
176+
}
177+
178+
/**
179+
* Writes data to a file as JSON.
180+
*
181+
* ## Notes
182+
*
183+
* - This function SHOULD be tailored to the input data (e.g., input types, output types, number of arguments, etc) and may vary from use case to use case.
184+
*
185+
*
186+
* @param f file to write to
187+
* @param x domain
188+
* @param y results
189+
* @param len array length
190+
*/
191+
void write_data_as_json( FILE *f, const double *x, const double *y, const unsigned int len ) {
192+
fprintf( f, "{" );
193+
write_named_array_f64( f, "x", x, len );
194+
fprintf( f, "," );
195+
write_named_array_f64( f, "expected", y, len );
196+
fprintf( f, "}" );
197+
}
198+
199+
/**
200+
* Generates test fixtures.
201+
*
202+
* @param x domain
203+
* @param len number of values in the domain
204+
* @param name output filename
205+
*/
206+
void generate( double *x, const unsigned int len, const char *name ) {
207+
unsigned int i;
208+
double *y;
209+
FILE *f;
210+
211+
// Allocate an output array:
212+
y = (double*) malloc( len * sizeof(double) );
213+
214+
// Generate fixture data:
215+
for ( i = 0; i < len; i++ ) {
216+
y[ i ] = boost::math::tgamma1pm1( x[ i ] );
217+
}
218+
// Open a new file:
219+
f = fopen( name, "w" );
220+
if ( f == NULL ) {
221+
printf( "Error opening file.\n" );
222+
exit( 1 );
223+
}
224+
// Write data as JSON...
225+
write_data_as_json( f, x, y, len );
226+
227+
// Close the file:
228+
fclose( f );
229+
230+
// Free allocated memory:
231+
free( y );
232+
}
233+
234+
/**
235+
* Main execution sequence.
236+
*/
237+
int main( void ) {
238+
unsigned int len;
239+
double *x;
240+
241+
// Define the array length:
242+
len = 1000;
243+
244+
// Allocate an array:
245+
x = (double*) malloc( len * sizeof(double) );
246+
247+
// Generate fixture data:
248+
linspace_f64( x, len, -0.5, 0.0 );
249+
generate( x, len, "small_negative.json" );
250+
251+
linspace_f64( x, len, 0.0, 2.0 );
252+
generate( x, len, "small_positive.json" );
253+
254+
// Free allocated memory:
255+
free( x );
256+
257+
return 0;
258+
}

0 commit comments

Comments
 (0)