-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathadd_epsilon_mod_4.c
176 lines (144 loc) · 4.59 KB
/
add_epsilon_mod_4.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/* add_epsilon_mod_4.c -- add a column with n-2^k to a cvs file
*
* Copyright 2014 by Colin Benner <[email protected]>
*
* This file is part of frobenius-test.
*
* frobenius-test is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* frobenius-test is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with frobenius-test. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gmp.h>
#include "common.h"
// How many number of each type to read from disk.
#define NUM_PRIMES 40
#define NUM_COMPOSITES 58
#define NUM_MERSENNE_NUMBERS 292
#define NUM_MERSENNE_PRIMES 25
// Test inputs
static unsigned bits_primes[NUM_PRIMES];
static unsigned bits_composites[NUM_COMPOSITES];
static unsigned bits_mersenne_numbers[NUM_MERSENNE_NUMBERS];
static unsigned bits_mersenne_primes[NUM_MERSENNE_PRIMES];
static mpz_t primes[NUM_PRIMES];
static mpz_t composites[NUM_COMPOSITES];
static mpz_t mersenne_numbers[NUM_MERSENNE_NUMBERS];
static mpz_t mersenne_primes[NUM_MERSENNE_PRIMES];
/*
* Read a set of numbers for testing
*/
static unsigned load_numbers(unsigned num_bits[], mpz_t nums[], const char file[], size_t length)
{
unsigned p, i = 0;
FILE *fp = fopen(file, "r");
mpz_t tmp;
if (NULL == fp)
return 0;
mpz_init(tmp);
while (EOF != gmp_fscanf(fp, "%u\t%Zd\n", &p, tmp)) {
mpz_init(nums[i]);
mpz_set(nums[i], tmp);
if (NULL != num_bits)
num_bits[i] = p;
i++;
if (i >= length)
break;
}
fclose(fp);
mpz_clear(tmp);
return i;
}
/*
* Count the number of commas in a given string.
*/
static int count_commas(char *s)
{
int counter = 0;
for (char *c = s; *c != '\0'; c++) {
counter += (*c == ',');
}
return counter;
}
/*
* Find the number used in a test given which set the number belongs two and
* the logarithm of the closest power of 2.
*/
static void get_num(mpz_t num, mpz_t numbers[], unsigned bits_numbers[], uint64_t bits)
{
int i;
for (i = 0; bits_numbers[i] < bits; i++);
assert(bits_numbers[i] == bits);
mpz_set(num, numbers[i]);
}
int main()
{
FILE *input, *output;
mpz_t n, tmp;
// Read all the benchmarking inputs.
load_numbers(bits_primes, primes, "primes.txt", NUM_PRIMES)
|| die("failed to load primes\n");
load_numbers(bits_composites, composites, "composites.txt", NUM_COMPOSITES)
|| die("failed to load composites\n");
load_numbers(bits_mersenne_numbers, mersenne_numbers, "mersenne_numbers.txt", NUM_MERSENNE_NUMBERS)
|| die("failed to load Mersenne numbers\n");
load_numbers(bits_mersenne_primes, mersenne_primes, "mersenne_primes.txt", NUM_MERSENNE_PRIMES)
|| die("failed to load Mersenne primes\n");
// Open the old timings file
input = fopen("timings_20140708.csv", "r");
if (NULL == input)
die("failed to open input file");
// and the new file
output = fopen("timings_new.csv", "w");
if (NULL == output)
die("failed to open output file");
mpz_inits(n, tmp, NULL);
/*
* Now we have to read the file with the measurements. For every of
* its lines, we add the missing measurements, if there are any. The
* first line containing the column headers is skipped.
*/
long read;
char *line = NULL;
size_t len;
while ((read = getline(&line, &len, input)) != -1) {
uint64_t bits;
// Get rid of the final newline character.
line[strlen(line)-1] = '\0';
if (count_commas(line) == 10) {
fprintf(output, "%s\n", line);
continue;
}
sscanf(line, "%lu,", &bits);
mpz_ui_pow_ui(tmp, 2, bits);
if (NULL != strstr(line, ",primes,"))
get_num(n, primes, bits_primes, bits);
else if (NULL != strstr(line, ",composites,"))
get_num(n, composites, bits_composites, bits);
else if (NULL != strstr(line, ",Mersenne numbers,"))
get_num(n, mersenne_numbers, bits_mersenne_numbers, bits);
else if (NULL != strstr(line, ",composites,"))
get_num(n, mersenne_primes, bits_mersenne_primes, bits);
// We do not have to do anything otherwise, because it is the
// line containing the column headers.
mpz_sub(tmp, n, tmp);
fprintf(output, "%lu,%ld%s,%lu\n", bits, mpz_get_si(tmp), strchr(line, ','), mpz_fdiv_ui(n, 4));
}
free(line);
mpz_clears(n, tmp, NULL);
fclose(input);
fclose(output);
return 0;
}