1
0

testlib.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866
  1. #ifndef _TESTLIB_H_
  2. #define _TESTLIB_H_
  3. /*
  4. *
  5. * Copyright (c) 2005-2008
  6. */
  7. #define VERSION "0.5.2"
  8. /*
  9. * Mike Mirzayanov
  10. *
  11. * This material is provided "as is", with absolutely no warranty expressed
  12. * or implied. Any use is at your own risk.
  13. *
  14. * Permission to use or copy this software for any purpose is hereby granted
  15. * without fee, provided the above notices are retained on all copies.
  16. * Permission to modify the code and to distribute modified code is granted,
  17. * provided the above notices are retained, and a notice that the code was
  18. * modified is included with the above copyright notice.
  19. *
  20. */
  21. /* NOTE: This file contains testlib library for C++.
  22. *
  23. * Program, using testlib running format:
  24. * check.exe <Input_File> <Output_File> <Answer_File> [<Result_File> [-appes]],
  25. *
  26. * If result file is specified it will contain results.
  27. */
  28. const char* latestFeatures[] = {
  29. "Added InStream::readLong() and removed InStream::readLongint()",
  30. "Now no footer added to each report by default (use directive FOOTER to switch on)",
  31. "Now every checker has a name, use setName(const char* format, ...) to set it",
  32. "Now it is compatible with TTS (by Kittens Computing)",
  33. "Added \'ensure(condition, message = \"\")\' feature, it works like assert()",
  34. "Fixed compatibility with MS C++ 7.1",
  35. "Added footer with exit code information",
  36. "Added compatibility with EJUDGE (compile with EJUDGE directive)"
  37. };
  38. #ifdef _MSC_VER
  39. #define _CRT_SECURE_NO_DEPRECATE
  40. #endif
  41. #include <cstdio>
  42. #include <cctype>
  43. #include <string>
  44. #include <string.h>
  45. #include <stdarg.h>
  46. #include <cstdlib>
  47. #if ( _WIN32 || __WIN32__ )
  48. #include <windows.h>
  49. #else
  50. #define WORD unsigned short
  51. #endif
  52. #define ABS(f) ((f) < 0 ? -(f) : (f))
  53. #define MIN(a, b) ((a) < (b) ? (a) : (b))
  54. #define MAX(a, b) ((a) > (b) ? (a) : (b))
  55. #define OUTPUT_BUFFER_SIZE (2097152)
  56. #define LF (char)10
  57. #define CR (char)13
  58. #define TAB (char)9
  59. #define SPACE (char)' '
  60. #define EOFCHAR (EOF)
  61. #define EOFREMAP SPACE
  62. #define NUMBERBEFORE LF, CR, SPACE, TAB, EOFCHAR
  63. #define NUMBERAFTER LF, CR, TAB, EOFCHAR
  64. #define LINEAFTER LF, CR, EOFCHAR
  65. #define BLANKS LF, CR, SPACE, TAB
  66. #define EOLNCHAR LF, CR, EOFCHAR
  67. #ifndef EJUDGE
  68. #define OK_EXIT_CODE 0
  69. #define WA_EXIT_CODE 1
  70. #define PE_EXIT_CODE 2
  71. #define FAIL_EXIT_CODE 3
  72. #define DIRT_EXIT_CODE 4
  73. #else
  74. #define OK_EXIT_CODE 0
  75. #define WA_EXIT_CODE 5
  76. #define PE_EXIT_CODE 4
  77. #define FAIL_EXIT_CODE 6
  78. #define DIRT_EXIT_CODE 6
  79. #endif
  80. inline bool isEofChar(char c)
  81. {
  82. return (c == EOFCHAR);
  83. }
  84. inline bool isEofRemap(char c)
  85. {
  86. return (c == EOFREMAP);
  87. }
  88. inline bool isNumberBefore(char c)
  89. {
  90. return (c == LF || c == CR || c == SPACE || c == TAB);
  91. }
  92. inline bool isNumberAfter(char c)
  93. {
  94. return (c == LF || c == CR || c == SPACE || c == TAB || c == EOFCHAR || c == (char)26);
  95. }
  96. inline bool isLineAfter(char c)
  97. {
  98. return (c == LF || c == CR || c == EOFCHAR || c == (char)26);
  99. }
  100. inline bool isBlanks(char c)
  101. {
  102. return (c == LF || c == CR || c == SPACE || c == TAB);
  103. }
  104. inline bool isEolnChar(char c)
  105. {
  106. return (c == LF || c == CR || c == EOFCHAR || c == (char)26);
  107. }
  108. struct TCharSet
  109. {
  110. unsigned int data[64];
  111. void insert(char c)
  112. {
  113. int pc = (int)c;
  114. data[pc >> 3] |= (1 << (pc & 7));
  115. }
  116. bool count(char c)
  117. {
  118. unsigned int pc = (unsigned char)c;
  119. return (data[pc >> 3] & (1 << (pc & 7))) != 0;
  120. }
  121. void clear()
  122. {
  123. memset(data, 0, sizeof(data));
  124. }
  125. TCharSet()
  126. {
  127. clear();
  128. }
  129. TCharSet(char c0)
  130. {
  131. clear();
  132. insert(c0);
  133. }
  134. TCharSet(char c0, char c1)
  135. {
  136. clear();
  137. insert(c0); insert(c1);
  138. }
  139. TCharSet(char c0, char c1, char c2)
  140. {
  141. clear();
  142. insert(c0); insert(c1); insert(c2);
  143. }
  144. TCharSet(char c0, char c1, char c2, char c3)
  145. {
  146. clear();
  147. insert(c0); insert(c1); insert(c2); insert(c3);
  148. }
  149. TCharSet(char c0, char c1, char c2, char c3, char c4)
  150. {
  151. clear();
  152. insert(c0); insert(c1); insert(c2); insert(c3); insert(c4);
  153. }
  154. };
  155. enum TMode
  156. {
  157. _input, _output, _answer
  158. };
  159. enum TResult
  160. {
  161. _ok, _wa, _pe, _fail, _dirt
  162. };
  163. const std::string outcomes[] =
  164. {"accepted", "wrong-answer", "presentation-error", "fail", "fail"};
  165. struct InStream
  166. {
  167. InStream();
  168. std::FILE * file;
  169. std::string name;
  170. TMode mode;
  171. bool opened;
  172. void init(std::string fileName, TMode mode);
  173. char curChar();
  174. void skipChar();
  175. char nextChar();
  176. void reset();
  177. bool eof();
  178. bool seekEof();
  179. bool eoln();
  180. bool seekEoln();
  181. void nextLine();
  182. void skip(TCharSet setof);
  183. std::string readWord(TCharSet before, TCharSet after);
  184. std::string readWord();
  185. long long readLong();
  186. int readInteger();
  187. int readInt();
  188. double readReal();
  189. double readDouble();
  190. std::string readString();
  191. void quit(TResult result, const char * msg);
  192. void quits(TResult result, std::string msg);
  193. void close();
  194. const static WORD LightGray = 0x07;
  195. const static WORD LightRed = 0x0c;
  196. const static WORD LightCyan = 0x0b;
  197. const static WORD LightGreen = 0x0a;
  198. static void textColor(WORD color);
  199. static void quitscr(WORD color, const char * msg);
  200. static void quitscrS(WORD color, std::string msg);
  201. void xmlSafeWrite(std::FILE * file, const char * msg);
  202. };
  203. InStream inf;
  204. InStream ouf;
  205. InStream ans;
  206. bool appesMode;
  207. std::string resultName;
  208. std::string checkerName = "untitled checker";
  209. /* implementation
  210. */
  211. InStream::InStream()
  212. {
  213. file = NULL;
  214. name = "";
  215. mode = _input;
  216. }
  217. int resultExitCode(TResult r)
  218. {
  219. if (r == _ok)
  220. return OK_EXIT_CODE;
  221. if (r == _wa)
  222. return WA_EXIT_CODE;
  223. if (r == _pe)
  224. return PE_EXIT_CODE;
  225. if (r == _fail)
  226. return FAIL_EXIT_CODE;
  227. if (r == _dirt)
  228. return DIRT_EXIT_CODE;
  229. return FAIL_EXIT_CODE;
  230. }
  231. void InStream::textColor(WORD color)
  232. {
  233. #if ( _WIN32 || __WIN32__ )
  234. HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
  235. SetConsoleTextAttribute(handle, color);
  236. #endif
  237. }
  238. void halt(int exitCode)
  239. {
  240. #ifdef FOOTER
  241. InStream::textColor(InStream::LightGray);
  242. std::printf("Checker: \"%s\"\n", checkerName.c_str());
  243. std::printf("Exit code: %d\n", exitCode);
  244. InStream::textColor(InStream::LightGray);
  245. #endif
  246. std::exit(exitCode);
  247. }
  248. void InStream::quit(TResult result, const char * msg)
  249. {
  250. if (mode != _output && result != _fail)
  251. quits(_fail, std::string(msg) + " (" + name + ")");
  252. std::FILE * resultFile;
  253. std::string errorName;
  254. if (result == _ok)
  255. {
  256. if (!ouf.seekEof())
  257. quit(_dirt, "Extra information in the output file");
  258. }
  259. switch (result)
  260. {
  261. case _fail:
  262. errorName = "FAIL ";
  263. quitscrS(LightRed, errorName);
  264. break;
  265. case _dirt:
  266. errorName = "wrong output format ";
  267. quitscrS(LightCyan, errorName);
  268. result = _pe;
  269. break;
  270. case _pe:
  271. errorName = "wrong output format ";
  272. quitscrS(LightRed, errorName);
  273. break;
  274. case _ok:
  275. errorName = "ok ";
  276. quitscrS(LightGreen, errorName);
  277. break;
  278. case _wa:
  279. errorName = "wrong answer ";
  280. quitscrS(LightRed, errorName);
  281. break;
  282. default:
  283. quit(_fail, "What is the code ??? ");
  284. }
  285. if (resultName != "")
  286. {
  287. resultFile = std::fopen(resultName.c_str(), "w");
  288. if (resultFile == NULL)
  289. quit(_fail, "Can not write to Result file");
  290. if (appesMode)
  291. {
  292. fprintf(resultFile, "<?xml version=\"1.0\" encoding=\"windows-1251\"?>");
  293. fprintf(resultFile, "<result outcome = \"%s\">", outcomes[(int)result].c_str());
  294. xmlSafeWrite(resultFile, msg);
  295. fprintf(resultFile, "</result>\n");
  296. }
  297. else
  298. {
  299. /** old-style format
  300. * fprintf(resultFile, ".Testlib Result Number = %d\n", (int)result);
  301. * fprintf(resultFile, ".Result name (optional) = %s\n", errorName.c_str());
  302. * fprintf(resultFile, ".Check Comments = %s\n", msg);
  303. */
  304. fprintf(resultFile, "%s", msg);
  305. }
  306. if (NULL == resultFile || fclose(resultFile) != 0)
  307. quit(_fail, "Can not write to Result file");
  308. }
  309. quitscr(LightGray, msg);
  310. std::printf("\n");
  311. if (inf.file)
  312. fclose(inf.file);
  313. if (ouf.file)
  314. fclose(ouf.file);
  315. if (ans.file)
  316. fclose(ans.file);
  317. textColor(LightGray);
  318. if (resultName != "")
  319. std::printf("See file to check exit message\n");
  320. halt(resultExitCode(result));
  321. }
  322. void InStream::quits(TResult result, std::string msg)
  323. {
  324. InStream::quit(result, msg.c_str());
  325. }
  326. void InStream::xmlSafeWrite(std::FILE * file, const char * msg)
  327. {
  328. size_t lmsg = strlen(msg);
  329. for (size_t i = 0; i < lmsg; i++)
  330. {
  331. if (msg[i] == '&')
  332. {
  333. fprintf(file, "%s", "&amp;");
  334. continue;
  335. }
  336. if (msg[i] == '<')
  337. {
  338. fprintf(file, "%s", "&lt;");
  339. continue;
  340. }
  341. if (msg[i] == '>')
  342. {
  343. fprintf(file, "%s", "&gt;");
  344. continue;
  345. }
  346. if (msg[i] == '"')
  347. {
  348. fprintf(file, "%s", "&quot;");
  349. continue;
  350. }
  351. if (0 <= msg[i] && msg[i] <= 31)
  352. {
  353. fprintf(file, "%c", '.');
  354. continue;
  355. }
  356. fprintf(file, "%c", msg[i]);
  357. }
  358. }
  359. void InStream::quitscrS(WORD color, std::string msg)
  360. {
  361. quitscr(color, msg.c_str());
  362. }
  363. void InStream::quitscr(WORD color, const char * msg)
  364. {
  365. if (resultName == "")
  366. {
  367. textColor(color);
  368. std::printf("%s", msg);
  369. textColor(LightGray);
  370. }
  371. }
  372. void InStream::reset()
  373. {
  374. if (opened)
  375. close();
  376. if (NULL == (file = std::fopen(name.c_str(), "r")))
  377. {
  378. if (mode == _output)
  379. quits(_pe, std::string("File not found: \"") + name + "\"");
  380. }
  381. opened = true;
  382. }
  383. void InStream::init(std::string fileName, TMode mode)
  384. {
  385. opened = false;
  386. name = fileName;
  387. this->mode = mode;
  388. reset();
  389. }
  390. char InStream::curChar()
  391. {
  392. char c = (char)getc(file);
  393. ungetc(c, file);
  394. return c;
  395. }
  396. char InStream::nextChar()
  397. {
  398. return (char)getc(file);
  399. }
  400. void InStream::skipChar()
  401. {
  402. getc(file);
  403. }
  404. std::string InStream::readWord(TCharSet before, TCharSet after)
  405. {
  406. char cur;
  407. while (before.count(cur = (char)getc(file)) == 1);
  408. if (cur == EOFCHAR && !after.count(cur))
  409. {
  410. quit(_pe, "Unexpected end of file");
  411. }
  412. std::string result = "";
  413. while (!(after.count(cur) || cur == EOFCHAR))
  414. {
  415. result += cur;
  416. cur = (char)getc(file);
  417. }
  418. ungetc(cur, file);
  419. return result;
  420. }
  421. std::string InStream::readWord()
  422. {
  423. return readWord(TCharSet(BLANKS), TCharSet(BLANKS));
  424. }
  425. int InStream::readInteger()
  426. {
  427. char cur;
  428. while (isNumberBefore(cur = (char)getc(file)));
  429. if (cur == EOFCHAR)
  430. quit(_pe, "Unexpected end of file - integer expected");
  431. ungetc(cur, file);
  432. int retval;
  433. if (fscanf(file, "%d", &retval) != 1)
  434. // todo: show insted-of
  435. quit(_pe, "Expected integer");
  436. return retval;
  437. }
  438. long long InStream::readLong()
  439. {
  440. char cur;
  441. while (isNumberBefore(cur = (char)getc(file)));
  442. if (cur == EOFCHAR)
  443. quit(_pe, "Unexpected end of file - long expected");
  444. ungetc(cur, file);
  445. long long retval = 0;
  446. char buffer[32] = {0};
  447. if (fscanf(file, "%s", buffer) != 1)
  448. quit(_pe, "Expected int64");
  449. else
  450. {
  451. bool minus = false;
  452. size_t length = strlen(buffer);
  453. if (length > 1 && buffer[0] == '-')
  454. minus = true;
  455. if (length > 20)
  456. quit(_pe, ("Expected int64, but \"" + (std::string)buffer + "\" found").c_str());
  457. for (size_t i = (minus ? 1 : 0); i < length; i++)
  458. {
  459. if (buffer[i] < '0' || buffer[i] > '9')
  460. quit(_pe, ("Expected int64, but \"" + (std::string)buffer + "\" found").c_str());
  461. retval = retval * 10 + (buffer[i] - '0');
  462. }
  463. if (retval < 0)
  464. quit(_pe, ("Expected int64, but \"" + (std::string)buffer + "\" found").c_str());
  465. return (minus ? -retval : +retval);
  466. }
  467. throw "it should not be executed";
  468. }
  469. int InStream::readInt()
  470. {
  471. return readInteger();
  472. }
  473. double InStream::readReal()
  474. {
  475. if (seekEof())
  476. quit(_pe, "Unexpected end of file - double expected");
  477. double retval;
  478. if (fscanf(file, "%lf", &retval) != 1)
  479. // todo: show insted-of
  480. quit(_pe, "Expected double");
  481. return retval;
  482. }
  483. double InStream::readDouble()
  484. {
  485. return readReal();
  486. }
  487. void InStream::skip(TCharSet setof)
  488. {
  489. char cur;
  490. while (setof.count(cur = (char)getc(file)) == 1);
  491. ungetc(cur, file);
  492. }
  493. bool InStream::eof()
  494. {
  495. return (NULL == file || feof(file) != 0);
  496. }
  497. bool InStream::seekEof()
  498. {
  499. if (NULL == file)
  500. return true;
  501. char cur;
  502. while (isBlanks(cur = (char)getc(file)));
  503. ungetc(cur, file);
  504. return (NULL == file || feof(file) != 0 || cur == EOF);
  505. }
  506. bool InStream::eoln()
  507. {
  508. if (NULL == file)
  509. return true;
  510. char c = curChar();
  511. return isEolnChar(c);
  512. }
  513. bool InStream::seekEoln()
  514. {
  515. if (NULL == file)
  516. return true;
  517. char cur;
  518. do
  519. {
  520. cur = (char)getc(file);
  521. }
  522. while (cur == SPACE || cur == TAB);
  523. ungetc(cur, file);
  524. return isEolnChar(cur);
  525. }
  526. void InStream::nextLine()
  527. {
  528. if (NULL == file)
  529. return;
  530. char cur;
  531. while (!isEolnChar(cur = (char)getc(file)));
  532. if (cur == CR)
  533. {
  534. cur = (char)getc(file);
  535. if (cur != LF)
  536. ungetc(cur, file);
  537. }
  538. else
  539. {
  540. if (cur != LF)
  541. ungetc(cur, file);
  542. }
  543. }
  544. std::string InStream::readString()
  545. {
  546. if (NULL == file)
  547. quit(_pe, "Expected line");
  548. std::string retval = "";
  549. char cur;
  550. while (!isEolnChar(cur = (char)getc(file)))
  551. retval += cur;
  552. if (cur == CR)
  553. {
  554. cur = (char)getc(file);
  555. if (cur != LF)
  556. ungetc(cur, file);
  557. }
  558. else
  559. {
  560. if (cur != LF)
  561. ungetc(cur, file);
  562. }
  563. return retval;
  564. }
  565. void InStream::close()
  566. {
  567. if (opened)
  568. fclose(file);
  569. opened = false;
  570. }
  571. void quit(TResult result, const std::string& msg)
  572. {
  573. ouf.quit(result, msg.c_str());
  574. }
  575. void quit(TResult result, const char * msg)
  576. {
  577. ouf.quit(result, msg);
  578. }
  579. void quitf(TResult result, const char * format, ...)
  580. {
  581. char * buffer = new char [OUTPUT_BUFFER_SIZE];
  582. va_list ap;
  583. va_start(ap, format);
  584. std::vsprintf(buffer, format, ap);
  585. va_end(ap);
  586. std::string output(buffer);
  587. delete[] buffer;
  588. quit(result, output);
  589. }
  590. void registerTestlibCmd(int argc, char * argv[])
  591. {
  592. if (argc > 1 && !strcmp("--help", argv[1]))
  593. {
  594. InStream::textColor(InStream::LightCyan);
  595. std::printf("TESTLIB %s ", VERSION);
  596. std::printf("by Mike Mirzayanov, copyright(c) 2005-2006\n");
  597. std::printf("Checker name: \"%s\"\n", checkerName.c_str());
  598. InStream::textColor(InStream::LightGray);
  599. std::printf("\n");
  600. std::printf("Latest features: \n");
  601. for (size_t i = 0; i < sizeof(latestFeatures) / sizeof(char*); i++)
  602. {
  603. std::printf("*) %s\n", latestFeatures[i]);
  604. }
  605. std::printf("\n");
  606. std::printf("Program must be run with the following arguments: \n");
  607. std::printf(" <input-file> <output-file> <answer-file> [<report-file> [<-appes>]]\n\n");
  608. std::exit(0);
  609. }
  610. if (sizeof(int) != 4)
  611. quit(_fail, "'testlib' unit assumes 'sizeof(integer) = 4'");
  612. if (argc < 4 || argc > 6)
  613. {
  614. quit(_fail, std::string("Program must be run with the following arguments: ") +
  615. std::string("<input-file> <output-file> <answer-file> [<report-file> [<-appes>]]") +
  616. "\nUse \"--help\" to get help information");
  617. }
  618. if (argc == 4)
  619. {
  620. resultName = "";
  621. appesMode = false;
  622. }
  623. if (argc == 5)
  624. {
  625. resultName = argv[4];
  626. appesMode = false;
  627. }
  628. if (argc == 6)
  629. {
  630. if (strcmp("-APPES", argv[5]) && strcmp("-appes", argv[5]))
  631. {
  632. quit(_fail, std::string("Program must be run with the following arguments: ") +
  633. "<input-file> <output-file> <answer-file> [<report-file> [<-appes>]]");
  634. }
  635. else
  636. {
  637. resultName = argv[4];
  638. appesMode = true;
  639. }
  640. }
  641. inf.init(argv[1], _input);
  642. ouf.init(argv[2], _output);
  643. ans.init(argv[3], _answer);
  644. }
  645. void registerTestlib(int argc, ...)
  646. {
  647. if (argc < 3 || argc > 5)
  648. quit(_fail, std::string("Program must be run with the following arguments: ") +
  649. "<input-file> <output-file> <answer-file> [<report-file> [<-appes>]]");
  650. char ** argv = new char*[argc + 1];
  651. va_list ap;
  652. va_start(ap, argc);
  653. argv[0] = NULL;
  654. for (int i = 0; i < argc; i++)
  655. {
  656. argv[i + 1] = va_arg(ap, char *);
  657. }
  658. va_end(ap);
  659. registerTestlibCmd(argc + 1, argv);
  660. delete[] argv;
  661. }
  662. inline bool isNaN(double r)
  663. {
  664. return ((r != r) == true) && ((r == r) == false) && ((1.0 > r) == false) && ((1.0 < r) == false);
  665. }
  666. inline bool isInfinite(double r)
  667. {
  668. return (r > 1E100 || r < -1E100);
  669. }
  670. bool doubleCompare(double expected, double result, double MAX_DOUBLE_ERROR)
  671. {
  672. if(isNaN(expected))
  673. {
  674. return isNaN(result);
  675. }
  676. else
  677. if(isInfinite(expected))
  678. {
  679. if(expected > 0)
  680. {
  681. return result > 0 && isInfinite(result);
  682. }
  683. else
  684. {
  685. return result < 0 && isInfinite(result);
  686. }
  687. }
  688. else
  689. if(isNaN(result) || isInfinite(result))
  690. {
  691. return false;
  692. }
  693. else
  694. if(ABS(result - expected) < MAX_DOUBLE_ERROR)
  695. {
  696. return true;
  697. }
  698. else
  699. {
  700. double minv = MIN(expected * (1.0 - MAX_DOUBLE_ERROR),
  701. expected * (1.0 + MAX_DOUBLE_ERROR));
  702. double maxv = MAX(expected * (1.0 - MAX_DOUBLE_ERROR),
  703. expected * (1.0 + MAX_DOUBLE_ERROR));
  704. return result > minv && result < maxv;
  705. }
  706. }
  707. double doubleDelta(double expected, double result)
  708. {
  709. double absolute = ABS(result - expected);
  710. if (ABS(expected) > 1E-9)
  711. {
  712. double relative = ABS(absolute / expected);
  713. return MIN(absolute, relative);
  714. }
  715. else
  716. return absolute;
  717. }
  718. void ensure(bool cond, const std::string msg = "")
  719. {
  720. if (!cond)
  721. {
  722. quitf(_fail, msg.c_str());
  723. }
  724. }
  725. void setName(const char* format, ...)
  726. {
  727. char * buffer = new char [OUTPUT_BUFFER_SIZE];
  728. va_list ap;
  729. va_start(ap, format);
  730. std::vsprintf(buffer, format, ap);
  731. va_end(ap);
  732. std::string name(buffer);
  733. delete[] buffer;
  734. checkerName = name;
  735. }
  736. #endif