1 /*- 2 * Copyright (c) 2018 Netflix, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 29 /* 30 * Author: Lawrence Stewart <lstewart@netflix.com> 31 */ 32 33 #include <sys/param.h> 34 #include <sys/qmath.h> 35 36 #include <errno.h> 37 #include <math.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 41 #include <atf-c.h> 42 43 #define QTEST_IV 3 44 #define QTEST_IVSTR "3.00" 45 #define QTEST_RPSHFT 2 46 #define QTEST_INTBITS(q) (Q_NTBITS(q) - Q_SIGNED(q) - Q_NFBITS(q) - Q_NCBITS) 47 #define QTEST_QITRUNC(q, iv) ((iv) >> Q_RPSHFT(q)) 48 #define QTEST_FFACTOR 32.0 49 50 #define bitsperrand 31 51 #define GENRAND(a, lb, ub) \ 52 ({ \ 53 int _rembits; \ 54 do { \ 55 _rembits = Q_BITSPERBASEUP(ub) + Q_LTZ(lb); \ 56 *(a) = (__typeof(*(a)))0; \ 57 while (_rembits > 0) { \ 58 *(a) |= (((uint64_t)random()) & \ 59 ((1ULL << (_rembits > bitsperrand ? \ 60 bitsperrand : _rembits)) - 1)); \ 61 *(a) <<= (_rembits - (_rembits > bitsperrand ? \ 62 bitsperrand : _rembits)); \ 63 _rembits -= bitsperrand; \ 64 } \ 65 *(a) += lb; \ 66 } while (*(a) < (lb) || (uint64_t)*(a) > (ub)); \ 67 *(a); \ 68 }) 69 70 /* 71 * Smoke tests for basic qmath operations, such as initialization 72 * or string formatting. 73 */ 74 ATF_TC_WITHOUT_HEAD(basic_s8q); 75 ATF_TC_BODY(basic_s8q, tc) 76 { 77 char buf[128]; 78 s8q_t s8; 79 80 Q_INI(&s8, QTEST_IV, 0, QTEST_RPSHFT); 81 Q_TOSTR(s8, -1, 10, buf, sizeof(buf)); 82 ATF_CHECK_STREQ(QTEST_IVSTR, buf); 83 ATF_CHECK_EQ(sizeof(s8) << 3, Q_NTBITS(s8)); 84 ATF_CHECK_EQ(QTEST_RPSHFT, Q_NFBITS(s8)); 85 ATF_CHECK_EQ(QTEST_INTBITS(s8), Q_NIBITS(s8)); 86 ATF_CHECK_EQ(QTEST_QITRUNC(s8, INT8_MAX), Q_IMAXVAL(s8)); 87 ATF_CHECK_EQ(-Q_IMAXVAL(s8), Q_IMINVAL(s8)); 88 } 89 90 ATF_TC_WITHOUT_HEAD(basic_s16q); 91 ATF_TC_BODY(basic_s16q, tc) 92 { 93 char buf[128]; 94 s16q_t s16; 95 96 Q_INI(&s16, QTEST_IV, 0, QTEST_RPSHFT); 97 Q_TOSTR(s16, -1, 10, buf, sizeof(buf)); 98 ATF_CHECK_STREQ(QTEST_IVSTR, buf); 99 ATF_CHECK_EQ(sizeof(s16) << 3, Q_NTBITS(s16)); 100 ATF_CHECK_EQ(QTEST_RPSHFT, Q_NFBITS(s16)); 101 ATF_CHECK_EQ(QTEST_INTBITS(s16), Q_NIBITS(s16)); 102 ATF_CHECK_EQ(QTEST_QITRUNC(s16, INT16_MAX), Q_IMAXVAL(s16)); 103 ATF_CHECK_EQ(-Q_IMAXVAL(s16), Q_IMINVAL(s16)); 104 } 105 106 ATF_TC_WITHOUT_HEAD(basic_s32q); 107 ATF_TC_BODY(basic_s32q, tc) 108 { 109 char buf[128]; 110 s32q_t s32; 111 112 Q_INI(&s32, QTEST_IV, 0, QTEST_RPSHFT); 113 Q_TOSTR(s32, -1, 10, buf, sizeof(buf)); 114 ATF_CHECK_STREQ(QTEST_IVSTR, buf); 115 ATF_CHECK_EQ(sizeof(s32) << 3, Q_NTBITS(s32)); 116 ATF_CHECK_EQ(QTEST_RPSHFT, Q_NFBITS(s32)); 117 ATF_CHECK_EQ(QTEST_INTBITS(s32), Q_NIBITS(s32)); 118 ATF_CHECK_EQ(QTEST_QITRUNC(s32, INT32_MAX), Q_IMAXVAL(s32)); 119 ATF_CHECK_EQ(-Q_IMAXVAL(s32), Q_IMINVAL(s32)); 120 } 121 122 ATF_TC_WITHOUT_HEAD(basic_s64q); 123 ATF_TC_BODY(basic_s64q, tc) 124 { 125 char buf[128]; 126 s64q_t s64; 127 128 Q_INI(&s64, QTEST_IV, 0, QTEST_RPSHFT); 129 Q_TOSTR(s64, -1, 10, buf, sizeof(buf)); 130 ATF_CHECK_STREQ(QTEST_IVSTR, buf); 131 ATF_CHECK_EQ(sizeof(s64) << 3, Q_NTBITS(s64)); 132 ATF_CHECK_EQ(QTEST_RPSHFT, Q_NFBITS(s64)); 133 ATF_CHECK_EQ(QTEST_INTBITS(s64), Q_NIBITS(s64)); 134 ATF_CHECK_EQ(QTEST_QITRUNC(s64, INT64_MAX), Q_IMAXVAL(s64)); 135 ATF_CHECK_EQ(-Q_IMAXVAL(s64), Q_IMINVAL(s64)); 136 } 137 138 ATF_TC_WITHOUT_HEAD(basic_u8q); 139 ATF_TC_BODY(basic_u8q, tc) 140 { 141 char buf[128]; 142 u8q_t u8; 143 144 Q_INI(&u8, QTEST_IV, 0, QTEST_RPSHFT); 145 Q_TOSTR(u8, -1, 10, buf, sizeof(buf)); 146 ATF_CHECK_STREQ(QTEST_IVSTR, buf); 147 ATF_CHECK_EQ(sizeof(u8) << 3, Q_NTBITS(u8)); 148 ATF_CHECK_EQ(QTEST_RPSHFT, Q_NFBITS(u8)); 149 ATF_CHECK_EQ(QTEST_INTBITS(u8), Q_NIBITS(u8)); 150 ATF_CHECK_EQ(QTEST_QITRUNC(u8, UINT8_MAX), Q_IMAXVAL(u8)); 151 ATF_CHECK_EQ(0, Q_IMINVAL(u8)); 152 } 153 154 ATF_TC_WITHOUT_HEAD(basic_u16q); 155 ATF_TC_BODY(basic_u16q, tc) 156 { 157 char buf[128]; 158 u16q_t u16; 159 160 Q_INI(&u16, QTEST_IV, 0, QTEST_RPSHFT); 161 Q_TOSTR(u16, -1, 10, buf, sizeof(buf)); 162 ATF_CHECK_STREQ(QTEST_IVSTR, buf); 163 ATF_CHECK_EQ(sizeof(u16) << 3, Q_NTBITS(u16)); 164 ATF_CHECK_EQ(QTEST_RPSHFT, Q_NFBITS(u16)); 165 ATF_CHECK_EQ(QTEST_INTBITS(u16), Q_NIBITS(u16)); 166 ATF_CHECK_EQ(QTEST_QITRUNC(u16, UINT16_MAX), Q_IMAXVAL(u16)); 167 ATF_CHECK_EQ(0, Q_IMINVAL(u16)); 168 } 169 170 ATF_TC_WITHOUT_HEAD(basic_u32q); 171 ATF_TC_BODY(basic_u32q, tc) 172 { 173 char buf[128]; 174 u32q_t u32; 175 176 Q_INI(&u32, QTEST_IV, 0, QTEST_RPSHFT); 177 Q_TOSTR(u32, -1, 10, buf, sizeof(buf)); 178 ATF_CHECK_STREQ(QTEST_IVSTR, buf); 179 ATF_CHECK_EQ(sizeof(u32) << 3, Q_NTBITS(u32)); 180 ATF_CHECK_EQ(QTEST_RPSHFT, Q_NFBITS(u32)); 181 ATF_CHECK_EQ(QTEST_INTBITS(u32), Q_NIBITS(u32)); 182 ATF_CHECK_EQ(QTEST_QITRUNC(u32, UINT32_MAX), Q_IMAXVAL(u32)); 183 ATF_CHECK_EQ(0, Q_IMINVAL(u32)); 184 } 185 186 ATF_TC_WITHOUT_HEAD(basic_u64q); 187 ATF_TC_BODY(basic_u64q, tc) 188 { 189 char buf[128]; 190 u64q_t u64; 191 192 Q_INI(&u64, QTEST_IV, 0, QTEST_RPSHFT); 193 Q_TOSTR(u64, -1, 10, buf, sizeof(buf)); 194 ATF_CHECK_STREQ(QTEST_IVSTR, buf); 195 ATF_CHECK_EQ(sizeof(u64) << 3, Q_NTBITS(u64)); 196 ATF_CHECK_EQ(QTEST_RPSHFT, Q_NFBITS(u64)); 197 ATF_CHECK_EQ(QTEST_INTBITS(u64), Q_NIBITS(u64)); 198 ATF_CHECK_EQ(QTEST_QITRUNC(u64, UINT64_MAX), Q_IMAXVAL(u64)); 199 ATF_CHECK_EQ(0, Q_IMINVAL(u64)); 200 } 201 202 /* 203 * Test Q_QMULQ(3) by applying it to two random Q numbers and comparing 204 * the result with its floating-point counterpart. 205 */ 206 ATF_TC_WITHOUT_HEAD(qmulq_s64q); 207 ATF_TC_BODY(qmulq_s64q, tc) 208 { 209 s64q_t a_s64q, b_s64q, r_s64q; 210 double a_dbl, b_dbl, r_dbl, maxe_dbl, delta_dbl; 211 #ifdef notyet 212 int64_t a_int, b_int; 213 #endif 214 int error; 215 216 srandomdev(); 217 218 for (int i = 0; i < 10;) { 219 GENRAND(&a_s64q, INT64_MIN, UINT64_MAX); 220 GENRAND(&b_s64q, INT64_MIN, UINT64_MAX); 221 222 /* 223 * XXX: We cheat a bit, to stand any chance of multiplying 224 * without overflow. 225 */ 226 error = Q_QDIVQ(&a_s64q, b_s64q); 227 if (error == EOVERFLOW || error == ERANGE) 228 continue; 229 ATF_CHECK_EQ(0, error); 230 231 /* 232 * XXXLAS: Until Qmath handles precision normalisation, only 233 * test with equal precision. 234 */ 235 Q_SCVAL(b_s64q, Q_GCVAL(a_s64q)); 236 237 /* Q<op>Q testing. */ 238 a_dbl = Q_Q2D(a_s64q); 239 b_dbl = Q_Q2D(b_s64q); 240 241 r_s64q = a_s64q; 242 error = Q_QMULQ(&r_s64q, b_s64q); 243 if (error == EOVERFLOW || error == ERANGE) 244 continue; 245 i++; 246 ATF_CHECK_EQ(0, error); 247 248 r_dbl = a_dbl * b_dbl; 249 #ifdef notyet 250 a_int = Q_GIVAL(a_s64q); 251 b_int = Q_GIVAL(b_s64q); 252 253 maxe_dbl = fabs(((1.0 / Q_NFBITS(a_s64q)) * (double)b_int) + 254 ((1.0 / Q_NFBITS(b_s64q)) * (double)a_int)); 255 #else 256 maxe_dbl = QTEST_FFACTOR; 257 #endif 258 delta_dbl = fabs(r_dbl - Q_Q2D(r_s64q)); 259 ATF_CHECK_MSG(delta_dbl <= maxe_dbl, 260 "\tQMULQ(%10f * %10f): |%10f - %10f| = %10f " 261 "(max err %f)\n", 262 Q_Q2D(a_s64q), Q_Q2D(b_s64q), Q_Q2D(r_s64q), r_dbl, 263 delta_dbl, maxe_dbl); 264 } 265 } 266 267 /* 268 * Test Q_QDIVQ(3) by applying it to two random Q numbers and comparing 269 * the result with its floating-point counterpart. 270 */ 271 ATF_TC_WITHOUT_HEAD(qdivq_s64q); 272 ATF_TC_BODY(qdivq_s64q, tc) 273 { 274 s64q_t a_s64q, b_s64q, r_s64q; 275 double a_dbl, b_dbl, r_dbl, maxe_dbl, delta_dbl; 276 int error; 277 278 if (atf_tc_get_config_var_as_bool_wd(tc, "ci", false)) 279 atf_tc_skip("https://bugs.freebsd.org/240219"); 280 281 282 srandomdev(); 283 284 for (int i = 0; i < 10; i++) { 285 GENRAND(&a_s64q, INT64_MIN, UINT64_MAX); 286 GENRAND(&b_s64q, INT64_MIN, UINT64_MAX); 287 /* 288 * XXXLAS: Until Qmath handles precision normalisation, only 289 * test with equal precision. 290 */ 291 Q_SCVAL(b_s64q, Q_GCVAL(a_s64q)); 292 293 /* Q<op>Q testing. */ 294 a_dbl = Q_Q2D(a_s64q); 295 b_dbl = Q_Q2D(b_s64q); 296 297 r_s64q = a_s64q; 298 error = Q_QDIVQ(&r_s64q, b_s64q); 299 ATF_CHECK_EQ(0, error); 300 301 r_dbl = a_dbl / b_dbl; 302 #ifdef notyet 303 maxe_dbl = fabs(1.0 / (1ULL << Q_NFBITS(a_s64q))); 304 #else 305 maxe_dbl = QTEST_FFACTOR * 2; 306 #endif 307 delta_dbl = fabs(r_dbl - Q_Q2D(r_s64q)); 308 ATF_CHECK_MSG(delta_dbl <= maxe_dbl, 309 "\tQDIVQ(%10f / %10f): |%10f - %10f| = %10f " 310 "(max err %f)\n", 311 Q_Q2D(a_s64q), Q_Q2D(b_s64q), Q_Q2D(r_s64q), r_dbl, 312 delta_dbl, maxe_dbl); 313 } 314 } 315 316 /* 317 * Test Q_QADDQ(3) by applying it to two random Q numbers and comparing 318 * the result with its floating-point counterpart. 319 */ 320 ATF_TC_WITHOUT_HEAD(qaddq_s64q); 321 ATF_TC_BODY(qaddq_s64q, tc) 322 { 323 s64q_t a_s64q, b_s64q, r_s64q; 324 double a_dbl, b_dbl, r_dbl, maxe_dbl, delta_dbl; 325 int error; 326 327 srandomdev(); 328 329 for (int i = 0; i < 10;) { 330 GENRAND(&a_s64q, INT64_MIN, UINT64_MAX); 331 GENRAND(&b_s64q, INT64_MIN, UINT64_MAX); 332 /* 333 * XXXLAS: Until Qmath handles precision normalisation, only 334 * test with equal precision. 335 */ 336 Q_SCVAL(b_s64q, Q_GCVAL(a_s64q)); 337 338 /* Q<op>Q testing. */ 339 a_dbl = Q_Q2D(a_s64q); 340 b_dbl = Q_Q2D(b_s64q); 341 342 r_s64q = a_s64q; 343 error = Q_QADDQ(&r_s64q, b_s64q); 344 if (error == EOVERFLOW || error == ERANGE) 345 continue; 346 i++; 347 ATF_CHECK_EQ(0, error); 348 349 r_dbl = a_dbl + b_dbl; 350 #ifdef notyet 351 maxe_dbl = 0.5; 352 #else 353 maxe_dbl = QTEST_FFACTOR; 354 #endif 355 delta_dbl = fabs(r_dbl - Q_Q2D(r_s64q)); 356 ATF_CHECK_MSG(delta_dbl <= maxe_dbl, 357 "\tQADDQ(%10f + %10f): |%10f - %10f| = %10f " 358 "(max err %f)\n", 359 Q_Q2D(a_s64q), Q_Q2D(b_s64q), Q_Q2D(r_s64q), r_dbl, 360 delta_dbl, maxe_dbl); 361 } 362 } 363 364 /* 365 * Test Q_QSUBQ(3) by applying it to two random Q numbers and comparing 366 * the result with its floating-point counterpart. 367 */ 368 ATF_TC_WITHOUT_HEAD(qsubq_s64q); 369 ATF_TC_BODY(qsubq_s64q, tc) 370 { 371 s64q_t a_s64q, b_s64q, r_s64q; 372 double a_dbl, b_dbl, r_dbl, maxe_dbl, delta_dbl; 373 int error; 374 375 srandomdev(); 376 377 for (int i = 0; i < 10; i++) { 378 GENRAND(&a_s64q, INT64_MIN, UINT64_MAX); 379 GENRAND(&b_s64q, INT64_MIN, UINT64_MAX); 380 /* 381 * XXXLAS: Until Qmath handles precision normalisation, only 382 * test with equal precision. 383 */ 384 Q_SCVAL(b_s64q, Q_GCVAL(a_s64q)); 385 386 /* Q<op>Q testing. */ 387 a_dbl = Q_Q2D(a_s64q); 388 b_dbl = Q_Q2D(b_s64q); 389 390 r_s64q = a_s64q; 391 error = Q_QSUBQ(&r_s64q, b_s64q); 392 ATF_CHECK_EQ(0, error); 393 394 r_dbl = a_dbl - b_dbl; 395 #ifdef notyet 396 maxe_dbl = 0.5; 397 #else 398 maxe_dbl = QTEST_FFACTOR; 399 #endif 400 delta_dbl = fabs(r_dbl - Q_Q2D(r_s64q)); 401 ATF_CHECK_MSG(delta_dbl <= maxe_dbl, 402 "\tQSUBQ(%10f - %10f): |%10f - %10f| = %10f " 403 "(max err %f)\n", 404 Q_Q2D(a_s64q), Q_Q2D(b_s64q), Q_Q2D(r_s64q), r_dbl, 405 delta_dbl, maxe_dbl); 406 } 407 } 408 409 /* 410 * Test Q_QFRACI(3) by applying it to two random integers and comparing 411 * the result with its floating-point counterpart. 412 */ 413 ATF_TC_WITHOUT_HEAD(qfraci_s64q); 414 ATF_TC_BODY(qfraci_s64q, tc) 415 { 416 s64q_t a_s64q, b_s64q, r_s64q; 417 double a_dbl, b_dbl, r_dbl, maxe_dbl, delta_dbl; 418 int64_t a_int, b_int; 419 int error; 420 421 srandomdev(); 422 423 for (int i = 0; i < 10;) { 424 GENRAND(&a_s64q, INT64_MIN, UINT64_MAX); 425 GENRAND(&b_s64q, INT64_MIN, UINT64_MAX); 426 /* 427 * XXXLAS: Until Qmath handles precision normalisation, only 428 * test with equal precision. 429 */ 430 Q_SCVAL(b_s64q, Q_GCVAL(a_s64q)); 431 a_int = Q_GIVAL(a_s64q); 432 b_int = Q_GIVAL(b_s64q); 433 434 /* Q<op>I testing. */ 435 a_dbl = a_int; 436 b_dbl = b_int; 437 438 Q_INI(&r_s64q, 0, 0, Q_NFBITS(a_s64q)); 439 error = Q_QFRACI(&r_s64q, a_int, b_int); 440 if (error == EOVERFLOW || error == ERANGE || error == EINVAL) 441 continue; 442 i++; 443 ATF_CHECK_EQ(0, error); 444 445 r_dbl = a_dbl / b_dbl; 446 maxe_dbl = fabs(1.0 / Q_NFBITS(a_s64q)); 447 delta_dbl = fabs(r_dbl - Q_Q2D(r_s64q)); 448 ATF_CHECK_MSG(delta_dbl <= maxe_dbl, 449 "\tQFRACI(%jd / %jd): |%10f - %10f| = %10f " 450 "(max err %f)\n", 451 (intmax_t)a_int, (intmax_t)b_int, Q_Q2D(r_s64q), 452 r_dbl, delta_dbl, maxe_dbl); 453 } 454 } 455 456 /* 457 * Test Q_QMULI(3) by applying it to a random Q number and a random integer 458 * and comparing the result with its floating-point counterpart. 459 */ 460 ATF_TC_WITHOUT_HEAD(qmuli_s64q); 461 ATF_TC_BODY(qmuli_s64q, tc) 462 { 463 s64q_t a_s64q, b_s64q, r_s64q; 464 double a_dbl, b_dbl, r_dbl, maxe_dbl, delta_dbl; 465 int64_t a_int, b_int; 466 int error; 467 468 srandomdev(); 469 470 for (int i = 0; i < 10;) { 471 GENRAND(&a_s64q, INT64_MIN, UINT64_MAX); 472 GENRAND(&b_s64q, INT64_MIN, UINT64_MAX); 473 /* 474 * XXXLAS: Until Qmath handles precision normalisation, only 475 * test with equal precision. 476 */ 477 Q_SCVAL(b_s64q, Q_GCVAL(a_s64q)); 478 a_int = Q_GIVAL(a_s64q); 479 b_int = Q_GIVAL(b_s64q); 480 481 /* Q<op>I testing. */ 482 a_dbl = a_int; 483 b_dbl = b_int; 484 485 Q_INI(&r_s64q, a_int, 0, Q_NFBITS(a_s64q)); 486 error = Q_QMULI(&r_s64q, b_int); 487 if (error == EOVERFLOW || error == ERANGE) 488 continue; 489 i++; 490 ATF_CHECK_EQ(0, error); 491 492 r_dbl = a_dbl * b_dbl; 493 maxe_dbl = fabs((1.0 / Q_NFBITS(a_s64q)) * (double)b_int); 494 delta_dbl = fabs(r_dbl - Q_Q2D(r_s64q)); 495 ATF_CHECK_MSG(delta_dbl <= maxe_dbl, 496 "\tQMULI(%jd * %jd): |%10f - %10f| = %10f " 497 "(max err %f)\n", 498 (intmax_t)(intmax_t)a_int, b_int, Q_Q2D(r_s64q), 499 r_dbl, delta_dbl, maxe_dbl); 500 } 501 } 502 503 /* 504 * Test Q_QADDI(3) by applying it to a random Q number and a random integer 505 * and comparing the result with its floating-point counterpart. 506 */ 507 ATF_TC_WITHOUT_HEAD(qaddi_s64q); 508 ATF_TC_BODY(qaddi_s64q, tc) 509 { 510 s64q_t a_s64q, b_s64q, r_s64q; 511 double a_dbl, b_dbl, r_dbl, maxe_dbl, delta_dbl; 512 int64_t a_int, b_int; 513 int error; 514 515 srandomdev(); 516 517 for (int i = 0; i < 10;) { 518 GENRAND(&a_s64q, INT64_MIN, UINT64_MAX); 519 GENRAND(&b_s64q, INT64_MIN, UINT64_MAX); 520 /* 521 * XXXLAS: Until Qmath handles precision normalisation, only 522 * test with equal precision. 523 */ 524 Q_SCVAL(b_s64q, Q_GCVAL(a_s64q)); 525 a_int = Q_GIVAL(a_s64q); 526 b_int = Q_GIVAL(b_s64q); 527 528 /* Q<op>I testing. */ 529 a_dbl = a_int; 530 b_dbl = b_int; 531 532 Q_INI(&r_s64q, a_int, 0, Q_NFBITS(a_s64q)); 533 error = Q_QADDI(&r_s64q, b_int); 534 if (error == EOVERFLOW || error == ERANGE) 535 continue; 536 i++; 537 ATF_CHECK_EQ(0, error); 538 539 r_dbl = a_dbl + b_dbl; 540 #ifdef notyet 541 maxe_dbl = 0.5; 542 #else 543 maxe_dbl = QTEST_FFACTOR; 544 #endif 545 delta_dbl = fabs(r_dbl - Q_Q2D(r_s64q)); 546 ATF_CHECK_MSG(delta_dbl <= maxe_dbl, 547 "\tQADDI(%jd + %jd): |%10f - %10f| = %10f " 548 "(max err %f)\n", 549 (intmax_t)a_int, (intmax_t)b_int, Q_Q2D(r_s64q), 550 r_dbl, delta_dbl, maxe_dbl); 551 } 552 } 553 554 /* 555 * Test Q_QSUBI(3) by applying it to a random Q number and a random integer 556 * and comparing the result with its floating-point counterpart. 557 */ 558 ATF_TC_WITHOUT_HEAD(qsubi_s64q); 559 ATF_TC_BODY(qsubi_s64q, tc) 560 { 561 s64q_t a_s64q, b_s64q, r_s64q; 562 double a_dbl, b_dbl, r_dbl, maxe_dbl, delta_dbl; 563 int64_t a_int, b_int; 564 int error; 565 566 srandomdev(); 567 568 for (int i = 0; i < 10; i++) { 569 GENRAND(&a_s64q, INT64_MIN, UINT64_MAX); 570 GENRAND(&b_s64q, INT64_MIN, UINT64_MAX); 571 /* 572 * XXXLAS: Until Qmath handles precision normalisation, only 573 * test with equal precision. 574 */ 575 Q_SCVAL(b_s64q, Q_GCVAL(a_s64q)); 576 a_int = Q_GIVAL(a_s64q); 577 b_int = Q_GIVAL(b_s64q); 578 579 /* Q<op>I testing. */ 580 a_dbl = a_int; 581 b_dbl = b_int; 582 583 Q_INI(&r_s64q, a_int, 0, Q_NFBITS(a_s64q)); 584 error = Q_QSUBI(&r_s64q, b_int); 585 ATF_CHECK_EQ(0, error); 586 587 r_dbl = a_dbl - b_dbl; 588 #ifdef notyet 589 maxe_dbl = 0.5; 590 #else 591 maxe_dbl = QTEST_FFACTOR; 592 #endif 593 delta_dbl = fabs(r_dbl - Q_Q2D(r_s64q)); 594 ATF_CHECK_MSG(delta_dbl <= maxe_dbl, 595 "\tQSUBI(%jd - %jd): |%10f - %10f| = %10f " 596 "(max err %f)\n", 597 (intmax_t)a_int, (intmax_t)b_int, Q_Q2D(r_s64q), 598 r_dbl, delta_dbl, maxe_dbl); 599 } 600 } 601 602 /* 603 * Calculate area of a circle with r=42. 604 */ 605 ATF_TC_WITHOUT_HEAD(circle_u64q); 606 ATF_TC_BODY(circle_u64q, tc) 607 { 608 char buf[128]; 609 u64q_t a, pi, r; 610 int error; 611 612 Q_INI(&a, 0, 0, 16); 613 Q_INI(&pi, 3, 14159, 16); 614 Q_INI(&r, 4, 2, 16); 615 616 error = Q_QCLONEQ(&a, r); 617 ATF_CHECK_EQ(0, error); 618 error = Q_QMULQ(&a, r); 619 ATF_CHECK_EQ(0, error); 620 error = Q_QMULQ(&a, pi); 621 ATF_CHECK_EQ(0, error); 622 623 Q_TOSTR(a, -1, 10, buf, sizeof(buf)); 624 ATF_CHECK_STREQ("55.4174804687500000", buf); 625 } 626 627 ATF_TP_ADD_TCS(tp) 628 { 629 630 ATF_TP_ADD_TC(tp, basic_s8q); 631 ATF_TP_ADD_TC(tp, basic_s16q); 632 ATF_TP_ADD_TC(tp, basic_s32q); 633 ATF_TP_ADD_TC(tp, basic_s64q); 634 ATF_TP_ADD_TC(tp, basic_u8q); 635 ATF_TP_ADD_TC(tp, basic_u16q); 636 ATF_TP_ADD_TC(tp, basic_u32q); 637 ATF_TP_ADD_TC(tp, basic_u64q); 638 639 ATF_TP_ADD_TC(tp, qmulq_s64q); 640 ATF_TP_ADD_TC(tp, qdivq_s64q); 641 ATF_TP_ADD_TC(tp, qaddq_s64q); 642 ATF_TP_ADD_TC(tp, qsubq_s64q); 643 ATF_TP_ADD_TC(tp, qfraci_s64q); 644 ATF_TP_ADD_TC(tp, qmuli_s64q); 645 ATF_TP_ADD_TC(tp, qaddi_s64q); 646 ATF_TP_ADD_TC(tp, qsubi_s64q); 647 648 ATF_TP_ADD_TC(tp, circle_u64q); 649 650 return (atf_no_error()); 651 } 652