github.com/matrixorigin/matrixone@v1.2.0/cgo/arith.c (about) 1 /* 2 * Copyright 2021 Matrix Origin 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "mo_impl.h" 18 19 /* 20 * Signed int add with overflow check. 21 * 22 * The test checks if rt[i] and tmpx have different sign, and rt[i] 23 * and tmpy have different sign, therefore, tmpx and tmpy have same 24 * sign but the result has different sign, therefore, it is an overflow. 25 * 26 * DO NOT use __builtin_add_overflow, which gcc cannot vectorize with SIMD 27 * and is actually much much slower. 28 */ 29 #define ADD_SIGNED_OVFLAG(TGT, A, B) \ 30 TGT = (A) + (B); \ 31 opflag |= ((TGT) ^ (A)) & ((TGT) ^ (B)) 32 33 #define ADD_SIGNED_OVFLAG_CHECK \ 34 if (opflag < 0) { \ 35 return RC_OUT_OF_RANGE; \ 36 } else return RC_SUCCESS 37 38 39 /* 40 * Unsigned int add with overflow check 41 * 42 * If result is less, we know it wrapped around. 43 */ 44 #define ADD_UNSIGNED_OVFLAG(TGT, A, B) \ 45 TGT = (A) + (B); \ 46 if ((TGT) < (A)) { \ 47 opflag = 1; \ 48 } else (void) 0 49 50 #define ADD_UNSIGNED_OVFLAG_CHECK \ 51 if (opflag != 0) { \ 52 return RC_OUT_OF_RANGE; \ 53 } else return RC_SUCCESS 54 55 /* 56 * Float/Double overflow check. 57 * 58 * At this moment we don't do anything. 59 */ 60 #define ADD_FLOAT_OVFLAG(TGT, A, B) \ 61 TGT = (A) + (B) 62 63 #define ADD_FLOAT_OVFLAG_CHECK \ 64 (void) opflag; \ 65 return RC_SUCCESS 66 67 /* 68 * Signed int sub with overflow check. 69 */ 70 #define SUB_SIGNED_OVFLAG(TGT, A, B) \ 71 TGT = (A) - (B); \ 72 opflag |= ((A) ^ (B)) & ((TGT) ^ (A)) 73 74 #define SUB_SIGNED_OVFLAG_CHECK \ 75 if (opflag < 0) { \ 76 return RC_OUT_OF_RANGE; \ 77 }else return RC_SUCCESS 78 79 80 /* 81 * Unsigned int sub with overflow check 82 * 83 * If A is less than B,, we know it wrapped around. 84 */ 85 #define SUB_UNSIGNED_OVFLAG(TGT, A, B) \ 86 TGT = (A) - (B); \ 87 if ((A) < (B)) { \ 88 opflag = 1; \ 89 } else (void) 0 90 91 #define SUB_UNSIGNED_OVFLAG_CHECK \ 92 if (opflag != 0) { \ 93 return RC_OUT_OF_RANGE; \ 94 } else return RC_SUCCESS 95 96 97 /* 98 * Float/Double overflow check. 99 * 100 * At this moment we don't do anything. 101 */ 102 #define SUB_FLOAT_OVFLAG(TGT, A, B) \ 103 TGT = (A) - (B) 104 105 #define SUB_FLOAT_OVFLAG_CHECK \ 106 (void) opflag; \ 107 return RC_SUCCESS 108 109 /* 110 * Signed int mul with overflow check. 111 */ 112 #define MUL_SIGNED_OVFLAG(TGT, A, B, MAXVAL, MINVAL, ZT ,UPTYPE) \ 113 temp = (UPTYPE)(A) * (UPTYPE)(B); \ 114 TGT = (ZT)temp; \ 115 opflag = ((A ^ B) > 0 && temp > MAXVAL) || ((A ^ B) < 0 && temp < MINVAL) 116 117 #define MUL_SIGNED_OVFLAG_CHECK \ 118 if (opflag != 0) { \ 119 return RC_OUT_OF_RANGE; \ 120 }else return RC_SUCCESS 121 122 123 /* 124 * Unsigned int mul with overflow check 125 */ 126 #define MUL_UNSIGNED_OVFLAG(TGT, A, B, MAXVAL, MINVAL, ZT, UPTYPE) \ 127 temp = (UPTYPE)(A) * (UPTYPE)(B); \ 128 TGT = (ZT)temp; \ 129 opflag = (temp > MAXVAL) 130 131 #define MUL_UNSIGNED_OVFLAG_CHECK \ 132 if (opflag != 0) { \ 133 return RC_OUT_OF_RANGE; \ 134 } else return RC_SUCCESS 135 136 137 /* 138 * Float/Double mul overflow check. 139 * 140 * At this moment we don't do anything. 141 */ 142 #define MUL_FLOAT_OVFLAG(TGT, A, B) \ 143 TGT = (A) * (B) 144 145 #define MUL_FLOAT_OVFLAG_CHECK \ 146 (void) opflag; \ 147 return RC_SUCCESS 148 149 150 /* 151 * Float/Double div overflow check. 152 * 153 * At this moment we don't do anything. 154 */ 155 #define DIV_FLOAT_OVFLAG(TGT, A, B) \ 156 if ((B) == 0) { \ 157 opflag = 1; \ 158 } else TGT = (A) / (B) 159 160 #define DIV_FLOAT_OVFLAG_CHECK \ 161 if (opflag == 1) { \ 162 return RC_DIVISION_BY_ZERO; \ 163 } else return RC_SUCCESS 164 165 /* 166 * Signed int mod with overflow check. 167 */ 168 #define MOD_SIGNED_OVFLAG(TGT, A, B) \ 169 if ((B) == 0) { \ 170 opflag = 1; \ 171 } else TGT = (A) % (B) 172 173 174 #define MOD_SIGNED_OVFLAG_CHECK \ 175 if (opflag == 1) { \ 176 return RC_DIVISION_BY_ZERO; \ 177 } else return RC_SUCCESS 178 179 180 /* 181 * Unsigned int mod with overflow check 182 */ 183 #define MOD_UNSIGNED_OVFLAG(TGT, A, B) \ 184 if ((B) == 0) { \ 185 opflag = 1; \ 186 } else TGT = (A) % (B) 187 188 #define MOD_UNSIGNED_OVFLAG_CHECK \ 189 if (opflag == 1) { \ 190 return RC_DIVISION_BY_ZERO; \ 191 } else return RC_SUCCESS 192 193 194 /* 195 * Float mod overflow check. 196 */ 197 #define MOD_FLOAT_OVFLAG(TGT, A, B) \ 198 if ((B) == 0) { \ 199 opflag = 1; \ 200 } else TGT = fmodf((A), (B)) 201 202 #define MOD_FLOAT_OVFLAG_CHECK \ 203 if (opflag == 1) { \ 204 return RC_DIVISION_BY_ZERO; \ 205 } else return RC_SUCCESS 206 207 208 /* 209 * Double mod overflow check. 210 */ 211 #define MOD_DOUBLE_OVFLAG(TGT, A, B) \ 212 if ((B) == 0) { \ 213 opflag = 1; \ 214 } else TGT = fmod((A), (B)) 215 216 #define MOD_DOUBLE_OVFLAG_CHECK \ 217 if (opflag == 1) { \ 218 return RC_DIVISION_BY_ZERO; \ 219 } else return RC_SUCCESS 220 221 // MO_ARITH_T: Handle general arithmetic operations 222 #define MO_ARITH_T(OP, ZT) \ 223 ZT *rt = (ZT *) r; \ 224 ZT *at = (ZT *) a; \ 225 ZT *bt = (ZT *) b; \ 226 ZT opflag = 0; \ 227 if ((flag & LEFT_IS_SCALAR) != 0) { \ 228 if (nulls != NULL) { \ 229 for (uint64_t i = 0; i < n; i++) { \ 230 if (!bitmap_test(nulls, i)) { \ 231 OP(rt[i], at[0], bt[i]); \ 232 } \ 233 } \ 234 } else { \ 235 for (uint64_t i = 0; i < n; i++) { \ 236 OP(rt[i], at[0], bt[i]); \ 237 } \ 238 } \ 239 } else if ((flag & RIGHT_IS_SCALAR) != 0) { \ 240 if (nulls != NULL) { \ 241 for (uint64_t i = 0; i < n; i++) { \ 242 if (!bitmap_test(nulls, i)) { \ 243 OP(rt[i], at[i], bt[0]); \ 244 } \ 245 } \ 246 } else { \ 247 for (uint64_t i = 0; i < n; i++) { \ 248 OP(rt[i], at[i], bt[0]); \ 249 } \ 250 } \ 251 } else { \ 252 if (nulls != NULL) { \ 253 for (uint64_t i = 0; i < n; i++) { \ 254 if (!bitmap_test(nulls, i)) { \ 255 OP(rt[i], at[i], bt[i]); \ 256 } \ 257 } \ 258 } else { \ 259 for (uint64_t i = 0; i < n; i++) { \ 260 OP(rt[i], at[i], bt[i]); \ 261 } \ 262 } \ 263 } \ 264 OP ## _CHECK 265 266 267 // MO_MUL_T: Handle signed and unsigned integer multiplication 268 #define MO_MUL_T(OP, ZT, MAXVAL, MINVAL, UPTYPE) \ 269 ZT *rt = (ZT *) r; \ 270 ZT *at = (ZT *) a; \ 271 ZT *bt = (ZT *) b; \ 272 UPTYPE temp = 0; \ 273 ZT opflag = 0; \ 274 if ((flag & LEFT_IS_SCALAR) != 0) { \ 275 if (nulls != NULL) { \ 276 for (uint64_t i = 0; i < n; i++) { \ 277 if (!bitmap_test(nulls, i)) { \ 278 OP(rt[i], at[0], bt[i], MAXVAL, MINVAL, ZT, UPTYPE); \ 279 } \ 280 } \ 281 } else { \ 282 for (uint64_t i = 0; i < n; i++) { \ 283 OP(rt[i], at[0], bt[i], MAXVAL, MINVAL, ZT, UPTYPE); \ 284 } \ 285 } \ 286 } else if ((flag & RIGHT_IS_SCALAR) != 0) { \ 287 if (nulls != NULL) { \ 288 for (uint64_t i = 0; i < n; i++) { \ 289 if (!bitmap_test(nulls, i)) { \ 290 OP(rt[i], at[i], bt[0], MAXVAL, MINVAL, ZT, UPTYPE); \ 291 } \ 292 } \ 293 } else { \ 294 for (uint64_t i = 0; i < n; i++) { \ 295 OP(rt[i], at[i], bt[0], MAXVAL, MINVAL, ZT, UPTYPE); \ 296 } \ 297 } \ 298 } else { \ 299 if (nulls != NULL) { \ 300 for (uint64_t i = 0; i < n; i++) { \ 301 if (!bitmap_test(nulls, i)) { \ 302 OP(rt[i], at[i], bt[i], MAXVAL, MINVAL, ZT, UPTYPE); \ 303 } \ 304 } \ 305 } else { \ 306 for (uint64_t i = 0; i < n; i++) { \ 307 OP(rt[i], at[i], bt[i], MAXVAL, MINVAL, ZT, UPTYPE); \ 308 } \ 309 } \ 310 } \ 311 OP ## _CHECK 312 313 314 315 // Addition operation 316 int32_t SignedInt_VecAdd(void *r, void *a, void *b, uint64_t n, uint64_t *nulls, int32_t flag, int32_t szof) 317 { 318 if (szof == 1) { 319 MO_ARITH_T(ADD_SIGNED_OVFLAG, int8_t); 320 } else if (szof == 2) { 321 MO_ARITH_T(ADD_SIGNED_OVFLAG, int16_t); 322 } else if (szof == 4) { 323 MO_ARITH_T(ADD_SIGNED_OVFLAG, int32_t); 324 } else if (szof == 8) { 325 MO_ARITH_T(ADD_SIGNED_OVFLAG, int64_t); 326 } else { 327 return RC_INVALID_ARGUMENT; 328 } 329 return RC_SUCCESS; 330 } 331 332 int32_t UnsignedInt_VecAdd(void *r, void *a, void *b, uint64_t n, uint64_t *nulls, int32_t flag, int32_t szof) 333 { 334 if (szof == 1) { 335 MO_ARITH_T(ADD_UNSIGNED_OVFLAG, uint8_t); 336 } else if (szof == 2) { 337 MO_ARITH_T(ADD_UNSIGNED_OVFLAG, uint16_t); 338 } else if (szof == 4) { 339 MO_ARITH_T(ADD_UNSIGNED_OVFLAG, uint32_t); 340 } else if (szof == 8) { 341 MO_ARITH_T(ADD_UNSIGNED_OVFLAG, uint64_t); 342 } else { 343 return RC_INVALID_ARGUMENT; 344 } 345 return RC_SUCCESS; 346 } 347 348 int32_t Float_VecAdd(void *r, void *a, void *b, uint64_t n, uint64_t *nulls, int32_t flag, int32_t szof) 349 { 350 if (szof == 4) { 351 MO_ARITH_T(ADD_FLOAT_OVFLAG, float); 352 } else if (szof == 8) { 353 MO_ARITH_T(ADD_FLOAT_OVFLAG, double); 354 } else { 355 return RC_INVALID_ARGUMENT; 356 } 357 return RC_SUCCESS; 358 } 359 360 // Subtraction operation 361 int32_t SignedInt_VecSub(void *r, void *a, void *b, uint64_t n, uint64_t *nulls, int32_t flag, int32_t szof) 362 { 363 if (szof == 1) { 364 MO_ARITH_T(SUB_SIGNED_OVFLAG, int8_t); 365 } else if (szof == 2) { 366 MO_ARITH_T(SUB_SIGNED_OVFLAG, int16_t); 367 } else if (szof == 4) { 368 MO_ARITH_T(SUB_SIGNED_OVFLAG, int32_t); 369 } else if (szof == 8) { 370 MO_ARITH_T(SUB_SIGNED_OVFLAG, int64_t); 371 } else { 372 return RC_INVALID_ARGUMENT; 373 } 374 return RC_SUCCESS; 375 } 376 377 int32_t UnsignedInt_VecSub(void *r, void *a, void *b, uint64_t n, uint64_t *nulls, int32_t flag, int32_t szof) 378 { 379 if (szof == 1) { 380 MO_ARITH_T(SUB_UNSIGNED_OVFLAG, uint8_t); 381 } else if (szof == 2) { 382 MO_ARITH_T(SUB_UNSIGNED_OVFLAG, uint16_t); 383 } else if (szof == 4) { 384 MO_ARITH_T(SUB_UNSIGNED_OVFLAG, uint32_t); 385 } else if (szof == 8) { 386 MO_ARITH_T(SUB_UNSIGNED_OVFLAG, uint64_t); 387 } else { 388 return RC_INVALID_ARGUMENT; 389 } 390 return RC_SUCCESS; 391 } 392 393 int32_t Float_VecSub(void *r, void *a, void *b, uint64_t n, uint64_t *nulls, int32_t flag, int32_t szof) 394 { 395 if (szof == 4) { 396 MO_ARITH_T(SUB_FLOAT_OVFLAG, float); 397 } else if (szof == 8) { 398 MO_ARITH_T(SUB_FLOAT_OVFLAG, double); 399 } else { 400 return RC_INVALID_ARGUMENT; 401 } 402 return RC_SUCCESS; 403 } 404 405 // Multiplication operation 406 int32_t SignedInt_VecMul(void *r, void *a, void *b, uint64_t n, uint64_t *nulls, int32_t flag, int32_t szof) 407 { 408 if (szof == 1) { 409 MO_MUL_T(MUL_SIGNED_OVFLAG, int8_t, INT8_MAX, INT8_MIN, int16_t); 410 } else if (szof == 2) { 411 MO_MUL_T(MUL_SIGNED_OVFLAG, int16_t, INT16_MAX, INT16_MIN, int16_t); 412 } else if (szof == 4) { 413 MO_MUL_T(MUL_SIGNED_OVFLAG, int32_t, INT32_MAX, INT32_MIN, int64_t); 414 } else if (szof == 8) { 415 MO_MUL_T(MUL_SIGNED_OVFLAG, int64_t, INT64_MAX, INT64_MIN, __int128); 416 } else { 417 return RC_INVALID_ARGUMENT; 418 } 419 return RC_SUCCESS; 420 } 421 422 423 int32_t UnsignedInt_VecMul(void *r, void *a, void *b, uint64_t n, uint64_t *nulls, int32_t flag, int32_t szof) 424 { 425 if (szof == 1) { 426 MO_MUL_T(MUL_UNSIGNED_OVFLAG, uint8_t, UINT8_MAX, 0, uint16_t); 427 } else if (szof == 2) { 428 MO_MUL_T(MUL_UNSIGNED_OVFLAG, uint16_t, UINT16_MAX, 0, uint32_t); 429 } else if (szof == 4) { 430 MO_MUL_T(MUL_UNSIGNED_OVFLAG, uint32_t, UINT32_MAX, 0, uint64_t); 431 } else if (szof == 8) { 432 MO_MUL_T(MUL_UNSIGNED_OVFLAG, uint64_t, UINT64_MAX, 0, __int128); 433 } else { 434 return RC_INVALID_ARGUMENT; 435 } 436 return RC_SUCCESS; 437 } 438 439 440 int32_t Float_VecMul(void *r, void *a, void *b, uint64_t n, uint64_t *nulls, int32_t flag, int32_t szof) 441 { 442 if (szof == 4) { 443 MO_ARITH_T(MUL_FLOAT_OVFLAG, float); 444 } else if (szof == 8) { 445 MO_ARITH_T(MUL_FLOAT_OVFLAG, double); 446 } else { 447 return RC_INVALID_ARGUMENT; 448 } 449 return RC_SUCCESS; 450 } 451 452 // Division operation 453 int32_t Float_VecDiv(void *r, void *a, void *b, uint64_t n, uint64_t *nulls, int32_t flag, int32_t szof) { 454 if (szof == 4) { 455 MO_ARITH_T(DIV_FLOAT_OVFLAG, float); 456 } else if (szof == 8) { 457 MO_ARITH_T(DIV_FLOAT_OVFLAG, double); 458 } else { 459 return RC_INVALID_ARGUMENT; 460 } 461 return RC_SUCCESS; 462 } 463 464 // Mod operation 465 int32_t SignedInt_VecMod(void *r, void *a, void *b, uint64_t n, uint64_t *nulls, int32_t flag, int32_t szof) 466 { 467 if (szof == 1) { 468 MO_ARITH_T(MOD_SIGNED_OVFLAG, int8_t); 469 } else if (szof == 2) { 470 MO_ARITH_T(MOD_SIGNED_OVFLAG, int16_t); 471 } else if (szof == 4) { 472 MO_ARITH_T(MOD_SIGNED_OVFLAG, int32_t); 473 } else if (szof == 8) { 474 MO_ARITH_T(MOD_SIGNED_OVFLAG, int64_t); 475 } else { 476 return RC_INVALID_ARGUMENT; 477 } 478 return RC_SUCCESS; 479 } 480 481 int32_t UnsignedInt_VecMod(void *r, void *a, void *b, uint64_t n, uint64_t *nulls, int32_t flag, int32_t szof) 482 { 483 if (szof == 1) { 484 MO_ARITH_T(MOD_UNSIGNED_OVFLAG, uint8_t); 485 } else if (szof == 2) { 486 MO_ARITH_T(MOD_UNSIGNED_OVFLAG, uint16_t); 487 } else if (szof == 4) { 488 MO_ARITH_T(MOD_UNSIGNED_OVFLAG, uint32_t); 489 } else if (szof == 8) { 490 MO_ARITH_T(MOD_UNSIGNED_OVFLAG, uint64_t); 491 } else { 492 return RC_INVALID_ARGUMENT; 493 } 494 return RC_SUCCESS; 495 } 496 497 int32_t Float_VecMod(void *r, void *a, void *b, uint64_t n, uint64_t *nulls, int32_t flag, int32_t szof) 498 { 499 if (szof == 4) { 500 MO_ARITH_T(MOD_FLOAT_OVFLAG, float); 501 } else if (szof == 8) { 502 MO_ARITH_T(MOD_DOUBLE_OVFLAG, double); 503 } else { 504 return RC_INVALID_ARGUMENT; 505 } 506 return RC_SUCCESS; 507 } 508 509 510 /* 511 * Float/Double integer div overflow check. 512 * 513 * At this moment we don't do anything. 514 */ 515 #define INTDIV_FLOAT_OVFLAG(TGT, A, B) \ 516 if ((B) == 0) { \ 517 opflag = 1; \ 518 } else TGT = (int64_t)((A) / (B)) 519 520 #define INTDIV_FLOAT_OVFLAG_CHECK \ 521 if (opflag == 1) { \ 522 return RC_DIVISION_BY_ZERO; \ 523 } else return RC_SUCCESS 524 525 // MO_INT_DIV : Handle floating-point integer division 526 #define MO_INT_DIV(OP, ZT, RT) \ 527 RT *rt = (RT *) r; \ 528 ZT *at = (ZT *) a; \ 529 ZT *bt = (ZT *) b; \ 530 ZT opflag = 0; \ 531 if ((flag & LEFT_IS_SCALAR) != 0) { \ 532 if (nulls != NULL) { \ 533 for (uint64_t i = 0; i < n; i++) { \ 534 if (!bitmap_test(nulls, i)) { \ 535 OP(rt[i], at[0], bt[i]); \ 536 } \ 537 } \ 538 } else { \ 539 for (uint64_t i = 0; i < n; i++) { \ 540 OP(rt[i], at[0], bt[i]); \ 541 } \ 542 } \ 543 } else if ((flag & RIGHT_IS_SCALAR) != 0) { \ 544 if (nulls != NULL) { \ 545 for (uint64_t i = 0; i < n; i++) { \ 546 if (!bitmap_test(nulls, i)) { \ 547 OP(rt[i], at[i], bt[0]); \ 548 } \ 549 } \ 550 } else { \ 551 for (uint64_t i = 0; i < n; i++) { \ 552 OP(rt[i], at[i], bt[0]); \ 553 } \ 554 } \ 555 } else { \ 556 if (nulls != NULL) { \ 557 for (uint64_t i = 0; i < n; i++) { \ 558 if (!bitmap_test(nulls, i)) { \ 559 OP(rt[i], at[i], bt[i]); \ 560 } \ 561 } \ 562 } else { \ 563 for (uint64_t i = 0; i < n; i++) { \ 564 OP(rt[i], at[i], bt[i]); \ 565 } \ 566 } \ 567 } \ 568 OP ## _CHECK 569 570 571 int32_t Float_VecIntegerDiv(void *r, void *a, void *b, uint64_t n, uint64_t *nulls, int32_t flag, int32_t szof) 572 { 573 if (szof == 4) { 574 MO_INT_DIV(INTDIV_FLOAT_OVFLAG, float, int64_t); 575 } else if (szof == 8) { 576 MO_INT_DIV(INTDIV_FLOAT_OVFLAG, double, int64_t); 577 } else { 578 return RC_INVALID_ARGUMENT; 579 } 580 return RC_SUCCESS; 581 }