Skip to content

Commit 695f92e

Browse files
committed
Update to latest libprimesieve
1 parent 918921b commit 695f92e

File tree

3 files changed

+126
-72
lines changed

3 files changed

+126
-72
lines changed

lib/primesieve/src/app/CmdOptions.cpp

+49-66
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323

2424
#include "CmdOptions.hpp"
2525

26-
#include <primesieve/calculator.hpp>
2726
#include <primesieve/PrimeSieve.hpp>
2827
#include <primesieve/primesieve_error.hpp>
2928

@@ -50,29 +49,6 @@ enum IsParam
5049
OPTIONAL_PARAM
5150
};
5251

53-
/// Command-line option
54-
struct Option
55-
{
56-
// Example:
57-
// str = "--threads=32"
58-
// opt = "--threads"
59-
// val = "32"
60-
std::string str;
61-
std::string opt;
62-
std::string val;
63-
64-
template <typename T>
65-
T getValue() const
66-
{
67-
try {
68-
return calculator::eval<T>(val);
69-
}
70-
catch (std::exception&) {
71-
throw primesieve_error("invalid option '" + opt + "=" + val + "'");
72-
}
73-
}
74-
};
75-
7652
/// Options start with "-" or "--", then
7753
/// follows a Latin ASCII character.
7854
///
@@ -210,29 +186,42 @@ Option parseOption(int argc,
210186
return opt;
211187
}
212188

213-
void optionPrint(Option& opt,
214-
CmdOptions& opts)
189+
} // namespace
190+
191+
void CmdOptions::setMainOption(OptionID optionID,
192+
const std::string& optStr)
215193
{
216-
opts.quiet = true;
194+
// Multiple main options are not allowed
195+
if (!optionStr.empty())
196+
throw primesieve_error("incompatible options: " + optionStr + " " + optStr);
197+
else
198+
{
199+
optionStr = optStr;
200+
option = optionID;
201+
}
202+
}
203+
204+
void CmdOptions::optionPrint(Option& opt)
205+
{
206+
quiet = true;
217207

218208
// by default print primes
219209
if (opt.val.empty())
220210
opt.val = "1";
221211

222212
switch (opt.getValue<int>())
223213
{
224-
case 1: opts.flags |= PRINT_PRIMES; break;
225-
case 2: opts.flags |= PRINT_TWINS; break;
226-
case 3: opts.flags |= PRINT_TRIPLETS; break;
227-
case 4: opts.flags |= PRINT_QUADRUPLETS; break;
228-
case 5: opts.flags |= PRINT_QUINTUPLETS; break;
229-
case 6: opts.flags |= PRINT_SEXTUPLETS; break;
214+
case 1: flags |= PRINT_PRIMES; break;
215+
case 2: flags |= PRINT_TWINS; break;
216+
case 3: flags |= PRINT_TRIPLETS; break;
217+
case 4: flags |= PRINT_QUADRUPLETS; break;
218+
case 5: flags |= PRINT_QUINTUPLETS; break;
219+
case 6: flags |= PRINT_SEXTUPLETS; break;
230220
default: throw primesieve_error("invalid option '" + opt.str + "'");
231221
}
232222
}
233223

234-
void optionCount(Option& opt,
235-
CmdOptions& opts)
224+
void CmdOptions::optionCount(Option& opt)
236225
{
237226
// by default count primes
238227
if (opt.val.empty())
@@ -244,52 +233,48 @@ void optionCount(Option& opt,
244233
{
245234
switch (n % 10)
246235
{
247-
case 1: opts.flags |= COUNT_PRIMES; break;
248-
case 2: opts.flags |= COUNT_TWINS; break;
249-
case 3: opts.flags |= COUNT_TRIPLETS; break;
250-
case 4: opts.flags |= COUNT_QUADRUPLETS; break;
251-
case 5: opts.flags |= COUNT_QUINTUPLETS; break;
252-
case 6: opts.flags |= COUNT_SEXTUPLETS; break;
236+
case 1: flags |= COUNT_PRIMES; break;
237+
case 2: flags |= COUNT_TWINS; break;
238+
case 3: flags |= COUNT_TRIPLETS; break;
239+
case 4: flags |= COUNT_QUADRUPLETS; break;
240+
case 5: flags |= COUNT_QUINTUPLETS; break;
241+
case 6: flags |= COUNT_SEXTUPLETS; break;
253242
default: throw primesieve_error("invalid option '" + opt.str + "'");
254243
}
255244
}
256245
}
257246

258-
void optionDistance(Option& opt,
259-
CmdOptions& opts)
247+
void CmdOptions::optionDistance(Option& opt)
260248
{
261249
uint64_t start = 0;
262250
uint64_t val = opt.getValue<uint64_t>();
263-
auto& numbers = opts.numbers;
264251

265252
if (!numbers.empty())
266253
start = numbers[0];
267254

268255
numbers.push_back(start + val);
269256
}
270257

271-
void optionStressTest(Option& opt,
272-
CmdOptions& opts)
258+
void CmdOptions::optionStressTest(Option& opt)
273259
{
274-
opts.option = OPTION_STRESS_TEST;
260+
setMainOption(OPTION_STRESS_TEST, opt.str);
275261
std::transform(opt.val.begin(), opt.val.end(), opt.val.begin(),
276262
[](unsigned char c){ return std::toupper(c); });
277263

278264
// If the stress test mode is not specified
279265
// we use "CPU" by default.
280266
if (opt.val.empty())
281-
opts.stressTestMode = "CPU";
267+
stressTestMode = "CPU";
282268
else if (opt.val == "CPU")
283-
opts.stressTestMode = "CPU";
269+
stressTestMode = "CPU";
284270
else if (opt.val == "RAM")
285-
opts.stressTestMode = "RAM";
271+
stressTestMode = "RAM";
286272
else
287273
throw primesieve_error("invalid option '" + opt.str + "=" + opt.val + "'");
288274
}
289275

290276
/// Stress test timeout
291-
void optionTimeout(Option& opt,
292-
CmdOptions& opts)
277+
void CmdOptions::optionTimeout(Option& opt)
293278
{
294279
std::transform(opt.val.begin(), opt.val.end(), opt.val.begin(),
295280
[](unsigned char c){ return std::tolower(c); });
@@ -298,19 +283,17 @@ void optionTimeout(Option& opt,
298283
// https://manpages.debian.org/unstable/stress-ng/stress-ng.1.en.html
299284
switch (opt.val.back())
300285
{
301-
case 's': opt.val.pop_back(); opts.timeout = opt.getValue<int64_t>(); break;
302-
case 'm': opt.val.pop_back(); opts.timeout = opt.getValue<int64_t>() * 60; break;
303-
case 'h': opt.val.pop_back(); opts.timeout = opt.getValue<int64_t>() * 3600; break;
304-
case 'd': opt.val.pop_back(); opts.timeout = opt.getValue<int64_t>() * 24 * 3600; break;
305-
case 'y': opt.val.pop_back(); opts.timeout = opt.getValue<int64_t>() * 365 * 24 * 3600; break;
286+
case 's': opt.val.pop_back(); timeout = opt.getValue<int64_t>(); break;
287+
case 'm': opt.val.pop_back(); timeout = opt.getValue<int64_t>() * 60; break;
288+
case 'h': opt.val.pop_back(); timeout = opt.getValue<int64_t>() * 3600; break;
289+
case 'd': opt.val.pop_back(); timeout = opt.getValue<int64_t>() * 24 * 3600; break;
290+
case 'y': opt.val.pop_back(); timeout = opt.getValue<int64_t>() * 365 * 24 * 3600; break;
306291

307292
// By default assume seconds like stress-ng
308-
default: opts.timeout = opt.getValue<int64_t>();
293+
default: timeout = opt.getValue<int64_t>();
309294
}
310295
}
311296

312-
} // namespace
313-
314297
CmdOptions parseOptions(int argc, char* argv[])
315298
{
316299
// No command-line options provided
@@ -361,18 +344,18 @@ CmdOptions parseOptions(int argc, char* argv[])
361344

362345
switch (optionID)
363346
{
364-
case OPTION_COUNT: optionCount(opt, opts); break;
365-
case OPTION_DISTANCE: optionDistance(opt, opts); break;
366-
case OPTION_PRINT: optionPrint(opt, opts); break;
367-
case OPTION_STRESS_TEST: optionStressTest(opt, opts); break;
368-
case OPTION_TIMEOUT: optionTimeout(opt, opts); break;
347+
case OPTION_COUNT: opts.optionCount(opt); break;
348+
case OPTION_DISTANCE: opts.optionDistance(opt); break;
349+
case OPTION_PRINT: opts.optionPrint(opt); break;
350+
case OPTION_STRESS_TEST: opts.optionStressTest(opt); break;
351+
case OPTION_TIMEOUT: opts.optionTimeout(opt); break;
369352
case OPTION_SIZE: opts.sieveSize = opt.getValue<int>(); break;
370353
case OPTION_THREADS: opts.threads = opt.getValue<int>(); break;
371354
case OPTION_QUIET: opts.quiet = true; break;
372355
case OPTION_NO_STATUS: opts.status = false; break;
373356
case OPTION_TIME: opts.time = true; break;
374357
case OPTION_NUMBER: opts.numbers.push_back(opt.getValue<uint64_t>()); break;
375-
default: opts.option = optionID;
358+
default: opts.setMainOption(optionID, opt.str);
376359
}
377360
}
378361

lib/primesieve/src/app/CmdOptions.hpp

+35
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@
1010
#ifndef CMDOPTIONS_HPP
1111
#define CMDOPTIONS_HPP
1212

13+
#include <primesieve/calculator.hpp>
14+
#include <primesieve/primesieve_error.hpp>
1315
#include <primesieve/Vector.hpp>
16+
17+
#include <exception>
1418
#include <stdint.h>
1519
#include <string>
1620

@@ -36,10 +40,34 @@ enum OptionID
3640
OPTION_VERSION
3741
};
3842

43+
/// Command-line option
44+
struct Option
45+
{
46+
// Example:
47+
// str = "--threads=32"
48+
// opt = "--threads"
49+
// val = "32"
50+
std::string str;
51+
std::string opt;
52+
std::string val;
53+
54+
template <typename T>
55+
T getValue() const
56+
{
57+
try {
58+
return calculator::eval<T>(val);
59+
}
60+
catch (std::exception&) {
61+
throw primesieve::primesieve_error("invalid option '" + opt + "=" + val + "'");
62+
}
63+
}
64+
};
65+
3966
struct CmdOptions
4067
{
4168
primesieve::Vector<uint64_t> numbers;
4269
std::string stressTestMode;
70+
std::string optionStr;
4371
int option = -1;
4472
int flags = 0;
4573
int sieveSize = 0;
@@ -50,6 +78,13 @@ struct CmdOptions
5078
bool quiet = false;
5179
bool status = true;
5280
bool time = false;
81+
82+
void setMainOption(OptionID optionID, const std::string& optStr);
83+
void optionPrint(Option& opt);
84+
void optionCount(Option& opt);
85+
void optionDistance(Option& opt);
86+
void optionStressTest(Option& opt);
87+
void optionTimeout(Option& opt);
5388
};
5489

5590
CmdOptions parseOptions(int, char**);

lib/primesieve/src/app/stressTest.cpp

+42-6
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <algorithm>
2424
#include <cmath>
2525
#include <cstdlib>
26+
#include <ctime>
2627
#include <exception>
2728
#include <iostream>
2829
#include <iomanip>
@@ -125,9 +126,9 @@ std::string getTimeElapsed(int64_t secs)
125126

126127
for (std::size_t i = 0; i < time.size(); i++)
127128
{
128-
if (secs >= time[i])
129+
if (secs > time[i])
129130
{
130-
timeStr += (timeStr.empty()) ? "" : " ";
131+
timeStr += timeStr.empty() ? "" : " ";
131132
timeStr += std::to_string(secs / time[i]) + suffix[i];
132133
secs %= time[i];
133134
}
@@ -179,6 +180,39 @@ std::string getStartString(uint64_t start)
179180
}
180181
}
181182

183+
/// Date time format: "[Jan 13 22:07] "
184+
std::string getDateTime()
185+
{
186+
#if 0
187+
// Thread safe.
188+
// Requires C23, but does not work yet with the
189+
// MSVC 2022 and MinGW-w64 compilers.
190+
std::tm result;
191+
std::time_t currentTime = std::time(nullptr);
192+
if (!localtime_r(&currentTime, &result))
193+
return "";
194+
195+
std::ostringstream oss;
196+
oss << std::put_time(&result, "[%b %d %H:%M] ");
197+
return oss.str();
198+
#else
199+
// Not thread safe.
200+
// But we lock a mutex before calling getDateTime()
201+
// hence this is not an issue for us.
202+
#if defined(_MSC_VER)
203+
#pragma warning(disable : 4996)
204+
#endif
205+
std::time_t currentTime = std::time(nullptr);
206+
std::tm* currentDateTime = std::localtime(&currentTime);
207+
if (!currentDateTime)
208+
return "";
209+
210+
std::ostringstream oss;
211+
oss << std::put_time(currentDateTime, "[%b %d %H:%M] ");
212+
return oss.str();
213+
#endif
214+
}
215+
182216
void printResult(int threadId,
183217
int threads,
184218
uint64_t i,
@@ -194,15 +228,17 @@ void printResult(int threadId,
194228

195229
if (count == primeCounts[i])
196230
{
197-
std::cout << "Thread: " << std::setw(threadIdPadding) << std::right << threadId
198-
<< ", secs: " << std::fixed << std::setprecision(3) << secsThread.count()
231+
std::cout << getDateTime()
232+
<< "Thread " << std::setw(threadIdPadding) << std::right << threadId
233+
<< ", " << std::fixed << std::setprecision(2) << secsThread.count() << " secs"
199234
<< ", PrimePi(" << startStr << std::setw(iPadding) << std::right << i-1 << "e11, "
200235
<< startStr << std::setw(iPadding) << std::right << i << "e11) = " << count << " OK" << std::endl;
201236
}
202237
else
203238
{
204-
std::cerr << "Thread: " << std::setw(threadIdPadding) << std::right << threadId
205-
<< ", secs: " << std::fixed << std::setprecision(3) << secsThread.count()
239+
std::cerr << getDateTime()
240+
<< "Thread " << std::setw(threadIdPadding) << std::right << threadId
241+
<< ", " << std::fixed << std::setprecision(2) << secsThread.count() << " secs"
206242
<< ", PrimePi(" << startStr << std::setw(iPadding) << std::right << i-1 << "e11, "
207243
<< startStr << std::setw(iPadding) << std::right << i << "e11) = " << count << " ERROR" << std::endl;
208244

0 commit comments

Comments
 (0)