1 /* 2 * Vector math abstractions. 3 * 4 * Copyright (c) 2019-2023, Arm Limited. 5 * SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception 6 */ 7 8 #ifndef _V_MATH_H 9 #define _V_MATH_H 10 11 #ifndef WANT_VMATH 12 /* Enable the build of vector math code. */ 13 # define WANT_VMATH 1 14 #endif 15 #if WANT_VMATH 16 17 /* The goal of this header is to allow vector (only Neon for now) 18 and scalar build of the same algorithm. */ 19 20 #if SCALAR 21 #define V_NAME(x) __s_##x 22 #elif VPCS && __aarch64__ 23 #define V_NAME(x) __vn_##x 24 #define VPCS_ATTR __attribute__ ((aarch64_vector_pcs)) 25 #else 26 #define V_NAME(x) __v_##x 27 #endif 28 29 #ifndef VPCS_ATTR 30 #define VPCS_ATTR 31 #endif 32 #ifndef VPCS_ALIAS 33 #define VPCS_ALIAS 34 #endif 35 36 #include <stdint.h> 37 #include "math_config.h" 38 39 typedef float f32_t; 40 typedef uint32_t u32_t; 41 typedef int32_t s32_t; 42 typedef double f64_t; 43 typedef uint64_t u64_t; 44 typedef int64_t s64_t; 45 46 /* reinterpret as type1 from type2. */ 47 static inline u32_t 48 as_u32_f32 (f32_t x) 49 { 50 union { f32_t f; u32_t u; } r = {x}; 51 return r.u; 52 } 53 static inline f32_t 54 as_f32_u32 (u32_t x) 55 { 56 union { u32_t u; f32_t f; } r = {x}; 57 return r.f; 58 } 59 static inline s32_t 60 as_s32_u32 (u32_t x) 61 { 62 union { u32_t u; s32_t i; } r = {x}; 63 return r.i; 64 } 65 static inline u32_t 66 as_u32_s32 (s32_t x) 67 { 68 union { s32_t i; u32_t u; } r = {x}; 69 return r.u; 70 } 71 static inline u64_t 72 as_u64_f64 (f64_t x) 73 { 74 union { f64_t f; u64_t u; } r = {x}; 75 return r.u; 76 } 77 static inline f64_t 78 as_f64_u64 (u64_t x) 79 { 80 union { u64_t u; f64_t f; } r = {x}; 81 return r.f; 82 } 83 static inline s64_t 84 as_s64_u64 (u64_t x) 85 { 86 union { u64_t u; s64_t i; } r = {x}; 87 return r.i; 88 } 89 static inline u64_t 90 as_u64_s64 (s64_t x) 91 { 92 union { s64_t i; u64_t u; } r = {x}; 93 return r.u; 94 } 95 96 #if SCALAR 97 #define V_SUPPORTED 1 98 typedef f32_t v_f32_t; 99 typedef u32_t v_u32_t; 100 typedef s32_t v_s32_t; 101 typedef f64_t v_f64_t; 102 typedef u64_t v_u64_t; 103 typedef s64_t v_s64_t; 104 105 static inline int 106 v_lanes32 (void) 107 { 108 return 1; 109 } 110 111 static inline v_f32_t 112 v_f32 (f32_t x) 113 { 114 return x; 115 } 116 static inline v_u32_t 117 v_u32 (u32_t x) 118 { 119 return x; 120 } 121 static inline v_s32_t 122 v_s32 (s32_t x) 123 { 124 return x; 125 } 126 127 static inline f32_t 128 v_get_f32 (v_f32_t x, int i) 129 { 130 return x; 131 } 132 static inline u32_t 133 v_get_u32 (v_u32_t x, int i) 134 { 135 return x; 136 } 137 static inline s32_t 138 v_get_s32 (v_s32_t x, int i) 139 { 140 return x; 141 } 142 143 static inline void 144 v_set_f32 (v_f32_t *x, int i, f32_t v) 145 { 146 *x = v; 147 } 148 static inline void 149 v_set_u32 (v_u32_t *x, int i, u32_t v) 150 { 151 *x = v; 152 } 153 static inline void 154 v_set_s32 (v_s32_t *x, int i, s32_t v) 155 { 156 *x = v; 157 } 158 159 /* true if any elements of a v_cond result is non-zero. */ 160 static inline int 161 v_any_u32 (v_u32_t x) 162 { 163 return x != 0; 164 } 165 /* to wrap the result of relational operators. */ 166 static inline v_u32_t 167 v_cond_u32 (v_u32_t x) 168 { 169 return x ? -1 : 0; 170 } 171 static inline v_f32_t 172 v_abs_f32 (v_f32_t x) 173 { 174 return __builtin_fabsf (x); 175 } 176 static inline v_u32_t 177 v_bsl_u32 (v_u32_t m, v_u32_t x, v_u32_t y) 178 { 179 return (y & ~m) | (x & m); 180 } 181 static inline v_u32_t 182 v_cagt_f32 (v_f32_t x, v_f32_t y) 183 { 184 return fabsf (x) > fabsf (y); 185 } 186 /* to wrap |x| >= |y|. */ 187 static inline v_u32_t 188 v_cage_f32 (v_f32_t x, v_f32_t y) 189 { 190 return fabsf (x) >= fabsf (y); 191 } 192 static inline v_u32_t 193 v_calt_f32 (v_f32_t x, v_f32_t y) 194 { 195 return fabsf (x) < fabsf (y); 196 } 197 static inline v_f32_t 198 v_div_f32 (v_f32_t x, v_f32_t y) 199 { 200 return x / y; 201 } 202 static inline v_f32_t 203 v_fma_f32 (v_f32_t x, v_f32_t y, v_f32_t z) 204 { 205 return __builtin_fmaf (x, y, z); 206 } 207 static inline v_f32_t 208 v_round_f32 (v_f32_t x) 209 { 210 return __builtin_roundf (x); 211 } 212 static inline v_s32_t 213 v_round_s32 (v_f32_t x) 214 { 215 return __builtin_lroundf (x); /* relies on -fno-math-errno. */ 216 } 217 static inline v_f32_t 218 v_sel_f32 (v_u32_t p, v_f32_t x, v_f32_t y) 219 { 220 return p ? x : y; 221 } 222 static inline v_u32_t 223 v_sel_u32 (v_u32_t p, v_u32_t x, v_u32_t y) 224 { 225 return p ? x : y; 226 } 227 static inline v_f32_t 228 v_sqrt_f32 (v_f32_t x) 229 { 230 return __builtin_sqrtf (x); 231 } 232 /* convert to type1 from type2. */ 233 static inline v_f32_t 234 v_to_f32_s32 (v_s32_t x) 235 { 236 return x; 237 } 238 static inline v_s32_t 239 v_to_s32_f32 (v_f32_t x) 240 { 241 return x; 242 } 243 static inline v_f32_t 244 v_to_f32_u32 (v_u32_t x) 245 { 246 return x; 247 } 248 /* reinterpret as type1 from type2. */ 249 static inline v_u32_t 250 v_as_u32_f32 (v_f32_t x) 251 { 252 union { v_f32_t f; v_u32_t u; } r = {x}; 253 return r.u; 254 } 255 static inline v_s32_t 256 v_as_s32_f32 (v_f32_t x) 257 { 258 union 259 { 260 v_f32_t f; 261 v_s32_t u; 262 } r = {x}; 263 return r.u; 264 } 265 static inline v_f32_t 266 v_as_f32_u32 (v_u32_t x) 267 { 268 union { v_u32_t u; v_f32_t f; } r = {x}; 269 return r.f; 270 } 271 static inline v_s32_t 272 v_as_s32_u32 (v_u32_t x) 273 { 274 union { v_u32_t u; v_s32_t i; } r = {x}; 275 return r.i; 276 } 277 static inline v_u32_t 278 v_as_u32_s32 (v_s32_t x) 279 { 280 union { v_s32_t i; v_u32_t u; } r = {x}; 281 return r.u; 282 } 283 static inline v_f32_t 284 v_lookup_f32 (const f32_t *tab, v_u32_t idx) 285 { 286 return tab[idx]; 287 } 288 static inline v_u32_t 289 v_lookup_u32 (const u32_t *tab, v_u32_t idx) 290 { 291 return tab[idx]; 292 } 293 static inline v_f32_t 294 v_call_f32 (f32_t (*f) (f32_t), v_f32_t x, v_f32_t y, v_u32_t p) 295 { 296 return f (x); 297 } 298 static inline v_f32_t 299 v_call2_f32 (f32_t (*f) (f32_t, f32_t), v_f32_t x1, v_f32_t x2, v_f32_t y, 300 v_u32_t p) 301 { 302 return f (x1, x2); 303 } 304 305 static inline int 306 v_lanes64 (void) 307 { 308 return 1; 309 } 310 static inline v_f64_t 311 v_f64 (f64_t x) 312 { 313 return x; 314 } 315 static inline v_u64_t 316 v_u64 (u64_t x) 317 { 318 return x; 319 } 320 static inline v_s64_t 321 v_s64 (s64_t x) 322 { 323 return x; 324 } 325 static inline f64_t 326 v_get_f64 (v_f64_t x, int i) 327 { 328 return x; 329 } 330 static inline void 331 v_set_f64 (v_f64_t *x, int i, f64_t v) 332 { 333 *x = v; 334 } 335 /* true if any elements of a v_cond result is non-zero. */ 336 static inline int 337 v_any_u64 (v_u64_t x) 338 { 339 return x != 0; 340 } 341 /* true if all elements of a v_cond result is non-zero. */ 342 static inline int 343 v_all_u64 (v_u64_t x) 344 { 345 return x; 346 } 347 /* to wrap the result of relational operators. */ 348 static inline v_u64_t 349 v_cond_u64 (v_u64_t x) 350 { 351 return x ? -1 : 0; 352 } 353 static inline v_f64_t 354 v_abs_f64 (v_f64_t x) 355 { 356 return __builtin_fabs (x); 357 } 358 static inline v_u64_t 359 v_bsl_u64 (v_u64_t m, v_u64_t x, v_u64_t y) 360 { 361 return (y & ~m) | (x & m); 362 } 363 static inline v_u64_t 364 v_cagt_f64 (v_f64_t x, v_f64_t y) 365 { 366 return fabs (x) > fabs (y); 367 } 368 static inline v_f64_t 369 v_div_f64 (v_f64_t x, v_f64_t y) 370 { 371 return x / y; 372 } 373 static inline v_f64_t 374 v_fma_f64 (v_f64_t x, v_f64_t y, v_f64_t z) 375 { 376 return __builtin_fma (x, y, z); 377 } 378 static inline v_f64_t 379 v_min_f64(v_f64_t x, v_f64_t y) { 380 return x < y ? x : y; 381 } 382 static inline v_f64_t 383 v_round_f64 (v_f64_t x) 384 { 385 return __builtin_round (x); 386 } 387 static inline v_f64_t 388 v_sel_f64 (v_u64_t p, v_f64_t x, v_f64_t y) 389 { 390 return p ? x : y; 391 } 392 static inline v_f64_t 393 v_sqrt_f64 (v_f64_t x) 394 { 395 return __builtin_sqrt (x); 396 } 397 static inline v_s64_t 398 v_round_s64 (v_f64_t x) 399 { 400 return __builtin_lround (x); /* relies on -fno-math-errno. */ 401 } 402 static inline v_u64_t 403 v_trunc_u64 (v_f64_t x) 404 { 405 return __builtin_trunc (x); 406 } 407 /* convert to type1 from type2. */ 408 static inline v_f64_t 409 v_to_f64_s64 (v_s64_t x) 410 { 411 return x; 412 } 413 static inline v_f64_t 414 v_to_f64_u64 (v_u64_t x) 415 { 416 return x; 417 } 418 419 static inline v_s64_t 420 v_to_s64_f64 (v_f64_t x) 421 { 422 return x; 423 } 424 /* reinterpret as type1 from type2. */ 425 static inline v_u64_t 426 v_as_u64_f64 (v_f64_t x) 427 { 428 union { v_f64_t f; v_u64_t u; } r = {x}; 429 return r.u; 430 } 431 static inline v_f64_t 432 v_as_f64_u64 (v_u64_t x) 433 { 434 union { v_u64_t u; v_f64_t f; } r = {x}; 435 return r.f; 436 } 437 static inline v_s64_t 438 v_as_s64_u64 (v_u64_t x) 439 { 440 union { v_u64_t u; v_s64_t i; } r = {x}; 441 return r.i; 442 } 443 static inline v_u64_t 444 v_as_u64_s64 (v_s64_t x) 445 { 446 union { v_s64_t i; v_u64_t u; } r = {x}; 447 return r.u; 448 } 449 static inline v_f64_t 450 v_lookup_f64 (const f64_t *tab, v_u64_t idx) 451 { 452 return tab[idx]; 453 } 454 static inline v_u64_t 455 v_lookup_u64 (const u64_t *tab, v_u64_t idx) 456 { 457 return tab[idx]; 458 } 459 static inline v_f64_t 460 v_call_f64 (f64_t (*f) (f64_t), v_f64_t x, v_f64_t y, v_u64_t p) 461 { 462 return f (x); 463 } 464 static inline v_f64_t 465 v_call2_f64 (f64_t (*f) (f64_t, f64_t), v_f64_t x1, v_f64_t x2, v_f64_t y, 466 v_u64_t p) 467 { 468 return f (x1, x2); 469 } 470 471 #elif __aarch64__ 472 #define V_SUPPORTED 1 473 #include <arm_neon.h> 474 typedef float32x4_t v_f32_t; 475 typedef uint32x4_t v_u32_t; 476 typedef int32x4_t v_s32_t; 477 typedef float64x2_t v_f64_t; 478 typedef uint64x2_t v_u64_t; 479 typedef int64x2_t v_s64_t; 480 481 static inline int 482 v_lanes32 (void) 483 { 484 return 4; 485 } 486 487 static inline v_f32_t 488 v_f32 (f32_t x) 489 { 490 return (v_f32_t){x, x, x, x}; 491 } 492 static inline v_u32_t 493 v_u32 (u32_t x) 494 { 495 return (v_u32_t){x, x, x, x}; 496 } 497 static inline v_s32_t 498 v_s32 (s32_t x) 499 { 500 return (v_s32_t){x, x, x, x}; 501 } 502 503 static inline f32_t 504 v_get_f32 (v_f32_t x, int i) 505 { 506 return x[i]; 507 } 508 static inline u32_t 509 v_get_u32 (v_u32_t x, int i) 510 { 511 return x[i]; 512 } 513 static inline s32_t 514 v_get_s32 (v_s32_t x, int i) 515 { 516 return x[i]; 517 } 518 519 static inline void 520 v_set_f32 (v_f32_t *x, int i, f32_t v) 521 { 522 (*x)[i] = v; 523 } 524 static inline void 525 v_set_u32 (v_u32_t *x, int i, u32_t v) 526 { 527 (*x)[i] = v; 528 } 529 static inline void 530 v_set_s32 (v_s32_t *x, int i, s32_t v) 531 { 532 (*x)[i] = v; 533 } 534 535 /* true if any elements of a v_cond result is non-zero. */ 536 static inline int 537 v_any_u32 (v_u32_t x) 538 { 539 /* assume elements in x are either 0 or -1u. */ 540 return vpaddd_u64 (vreinterpretq_u64_u32 (x)) != 0; 541 } 542 /* to wrap the result of relational operators. */ 543 static inline v_u32_t 544 v_cond_u32 (v_u32_t x) 545 { 546 return x; 547 } 548 static inline v_f32_t 549 v_abs_f32 (v_f32_t x) 550 { 551 return vabsq_f32 (x); 552 } 553 static inline v_u32_t 554 v_bsl_u32 (v_u32_t m, v_u32_t x, v_u32_t y) 555 { 556 return vbslq_u32 (m, x, y); 557 } 558 static inline v_u32_t 559 v_cagt_f32 (v_f32_t x, v_f32_t y) 560 { 561 return vcagtq_f32 (x, y); 562 } 563 /* to wrap |x| >= |y|. */ 564 static inline v_u32_t 565 v_cage_f32 (v_f32_t x, v_f32_t y) 566 { 567 return vcageq_f32 (x, y); 568 } 569 static inline v_u32_t 570 v_calt_f32 (v_f32_t x, v_f32_t y) 571 { 572 return vcaltq_f32 (x, y); 573 } 574 static inline v_f32_t 575 v_div_f32 (v_f32_t x, v_f32_t y) 576 { 577 return vdivq_f32 (x, y); 578 } 579 static inline v_f32_t 580 v_fma_f32 (v_f32_t x, v_f32_t y, v_f32_t z) 581 { 582 return vfmaq_f32 (z, x, y); 583 } 584 static inline v_f32_t 585 v_round_f32 (v_f32_t x) 586 { 587 return vrndaq_f32 (x); 588 } 589 static inline v_s32_t 590 v_round_s32 (v_f32_t x) 591 { 592 return vcvtaq_s32_f32 (x); 593 } 594 static inline v_f32_t 595 v_sel_f32 (v_u32_t p, v_f32_t x, v_f32_t y) 596 { 597 return vbslq_f32 (p, x, y); 598 } 599 static inline v_u32_t 600 v_sel_u32 (v_u32_t p, v_u32_t x, v_u32_t y) 601 { 602 return vbslq_u32 (p, x, y); 603 } 604 static inline v_f32_t 605 v_sqrt_f32 (v_f32_t x) 606 { 607 return vsqrtq_f32 (x); 608 } 609 /* convert to type1 from type2. */ 610 static inline v_f32_t 611 v_to_f32_s32 (v_s32_t x) 612 { 613 return (v_f32_t){x[0], x[1], x[2], x[3]}; 614 } 615 static inline v_s32_t 616 v_to_s32_f32 (v_f32_t x) 617 { 618 return vcvtq_s32_f32 (x); 619 } 620 static inline v_f32_t 621 v_to_f32_u32 (v_u32_t x) 622 { 623 return (v_f32_t){x[0], x[1], x[2], x[3]}; 624 } 625 /* reinterpret as type1 from type2. */ 626 static inline v_u32_t 627 v_as_u32_f32 (v_f32_t x) 628 { 629 union { v_f32_t f; v_u32_t u; } r = {x}; 630 return r.u; 631 } 632 static inline v_s32_t 633 v_as_s32_f32 (v_f32_t x) 634 { 635 union 636 { 637 v_f32_t f; 638 v_s32_t u; 639 } r = {x}; 640 return r.u; 641 } 642 static inline v_f32_t 643 v_as_f32_u32 (v_u32_t x) 644 { 645 union { v_u32_t u; v_f32_t f; } r = {x}; 646 return r.f; 647 } 648 static inline v_s32_t 649 v_as_s32_u32 (v_u32_t x) 650 { 651 union { v_u32_t u; v_s32_t i; } r = {x}; 652 return r.i; 653 } 654 static inline v_u32_t 655 v_as_u32_s32 (v_s32_t x) 656 { 657 union { v_s32_t i; v_u32_t u; } r = {x}; 658 return r.u; 659 } 660 static inline v_f32_t 661 v_lookup_f32 (const f32_t *tab, v_u32_t idx) 662 { 663 return (v_f32_t){tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]]}; 664 } 665 static inline v_u32_t 666 v_lookup_u32 (const u32_t *tab, v_u32_t idx) 667 { 668 return (v_u32_t){tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]]}; 669 } 670 static inline v_f32_t 671 v_call_f32 (f32_t (*f) (f32_t), v_f32_t x, v_f32_t y, v_u32_t p) 672 { 673 return (v_f32_t){p[0] ? f (x[0]) : y[0], p[1] ? f (x[1]) : y[1], 674 p[2] ? f (x[2]) : y[2], p[3] ? f (x[3]) : y[3]}; 675 } 676 static inline v_f32_t 677 v_call2_f32 (f32_t (*f) (f32_t, f32_t), v_f32_t x1, v_f32_t x2, v_f32_t y, 678 v_u32_t p) 679 { 680 return ( 681 v_f32_t){p[0] ? f (x1[0], x2[0]) : y[0], p[1] ? f (x1[1], x2[1]) : y[1], 682 p[2] ? f (x1[2], x2[2]) : y[2], p[3] ? f (x1[3], x2[3]) : y[3]}; 683 } 684 685 static inline int 686 v_lanes64 (void) 687 { 688 return 2; 689 } 690 static inline v_f64_t 691 v_f64 (f64_t x) 692 { 693 return (v_f64_t){x, x}; 694 } 695 static inline v_u64_t 696 v_u64 (u64_t x) 697 { 698 return (v_u64_t){x, x}; 699 } 700 static inline v_s64_t 701 v_s64 (s64_t x) 702 { 703 return (v_s64_t){x, x}; 704 } 705 static inline f64_t 706 v_get_f64 (v_f64_t x, int i) 707 { 708 return x[i]; 709 } 710 static inline void 711 v_set_f64 (v_f64_t *x, int i, f64_t v) 712 { 713 (*x)[i] = v; 714 } 715 /* true if any elements of a v_cond result is non-zero. */ 716 static inline int 717 v_any_u64 (v_u64_t x) 718 { 719 /* assume elements in x are either 0 or -1u. */ 720 return vpaddd_u64 (x) != 0; 721 } 722 /* true if all elements of a v_cond result is 1. */ 723 static inline int 724 v_all_u64 (v_u64_t x) 725 { 726 /* assume elements in x are either 0 or -1u. */ 727 return vpaddd_s64 (vreinterpretq_s64_u64 (x)) == -2; 728 } 729 /* to wrap the result of relational operators. */ 730 static inline v_u64_t 731 v_cond_u64 (v_u64_t x) 732 { 733 return x; 734 } 735 static inline v_f64_t 736 v_abs_f64 (v_f64_t x) 737 { 738 return vabsq_f64 (x); 739 } 740 static inline v_u64_t 741 v_bsl_u64 (v_u64_t m, v_u64_t x, v_u64_t y) 742 { 743 return vbslq_u64 (m, x, y); 744 } 745 static inline v_u64_t 746 v_cagt_f64 (v_f64_t x, v_f64_t y) 747 { 748 return vcagtq_f64 (x, y); 749 } 750 static inline v_f64_t 751 v_div_f64 (v_f64_t x, v_f64_t y) 752 { 753 return vdivq_f64 (x, y); 754 } 755 static inline v_f64_t 756 v_fma_f64 (v_f64_t x, v_f64_t y, v_f64_t z) 757 { 758 return vfmaq_f64 (z, x, y); 759 } 760 static inline v_f64_t 761 v_min_f64(v_f64_t x, v_f64_t y) { 762 return vminq_f64(x, y); 763 } 764 static inline v_f64_t 765 v_round_f64 (v_f64_t x) 766 { 767 return vrndaq_f64 (x); 768 } 769 static inline v_f64_t 770 v_sel_f64 (v_u64_t p, v_f64_t x, v_f64_t y) 771 { 772 return vbslq_f64 (p, x, y); 773 } 774 static inline v_f64_t 775 v_sqrt_f64 (v_f64_t x) 776 { 777 return vsqrtq_f64 (x); 778 } 779 static inline v_s64_t 780 v_round_s64 (v_f64_t x) 781 { 782 return vcvtaq_s64_f64 (x); 783 } 784 static inline v_u64_t 785 v_trunc_u64 (v_f64_t x) 786 { 787 return vcvtq_u64_f64 (x); 788 } 789 /* convert to type1 from type2. */ 790 static inline v_f64_t 791 v_to_f64_s64 (v_s64_t x) 792 { 793 return (v_f64_t){x[0], x[1]}; 794 } 795 static inline v_f64_t 796 v_to_f64_u64 (v_u64_t x) 797 { 798 return (v_f64_t){x[0], x[1]}; 799 } 800 static inline v_s64_t 801 v_to_s64_f64 (v_f64_t x) 802 { 803 return vcvtq_s64_f64 (x); 804 } 805 /* reinterpret as type1 from type2. */ 806 static inline v_u64_t 807 v_as_u64_f64 (v_f64_t x) 808 { 809 union { v_f64_t f; v_u64_t u; } r = {x}; 810 return r.u; 811 } 812 static inline v_f64_t 813 v_as_f64_u64 (v_u64_t x) 814 { 815 union { v_u64_t u; v_f64_t f; } r = {x}; 816 return r.f; 817 } 818 static inline v_s64_t 819 v_as_s64_u64 (v_u64_t x) 820 { 821 union { v_u64_t u; v_s64_t i; } r = {x}; 822 return r.i; 823 } 824 static inline v_u64_t 825 v_as_u64_s64 (v_s64_t x) 826 { 827 union { v_s64_t i; v_u64_t u; } r = {x}; 828 return r.u; 829 } 830 static inline v_f64_t 831 v_lookup_f64 (const f64_t *tab, v_u64_t idx) 832 { 833 return (v_f64_t){tab[idx[0]], tab[idx[1]]}; 834 } 835 static inline v_u64_t 836 v_lookup_u64 (const u64_t *tab, v_u64_t idx) 837 { 838 return (v_u64_t){tab[idx[0]], tab[idx[1]]}; 839 } 840 static inline v_f64_t 841 v_call_f64 (f64_t (*f) (f64_t), v_f64_t x, v_f64_t y, v_u64_t p) 842 { 843 return (v_f64_t){p[0] ? f (x[0]) : y[0], p[1] ? f (x[1]) : y[1]}; 844 } 845 static inline v_f64_t 846 v_call2_f64 (f64_t (*f) (f64_t, f64_t), v_f64_t x1, v_f64_t x2, v_f64_t y, 847 v_u64_t p) 848 { 849 return (v_f64_t){p[0] ? f (x1[0], x2[0]) : y[0], 850 p[1] ? f (x1[1], x2[1]) : y[1]}; 851 } 852 #endif 853 854 #endif 855 #endif 856