@@ -589,11 +589,94 @@ rocksdb::Status Bitmap::BitOp(engine::Context &ctx, BitOpFlags op_flag, const st
589589 j += sizeof (uint64_t ) * 4 ;
590590 frag_minlen -= sizeof (uint64_t ) * 4 ;
591591 }
592+ } else if (op_flag == kBitOpDiff
593+ || op_flag == kBitOpDiff1
594+ || op_flag == kBitOpAndOr ) {
595+ size_t processed = 0 ;
596+ size_t k = 0 ;
597+
598+ while (frag_minlen >= sizeof (uint64_t )*4 ) {
599+ for (uint64_t i = 1 ; i < frag_numkeys; i++) {
600+ lres[0 ] |= lp[i][k+0 ];
601+ lres[1 ] |= lp[i][k+1 ];
602+ lres[2 ] |= lp[i][k+2 ];
603+ lres[3 ] |= lp[i][k+3 ];
604+ }
605+ k += 4 ;
606+ lres += 4 ;
607+ j += sizeof (uint64_t ) * 4 ;
608+ frag_minlen -= sizeof (uint64_t ) * 4 ;
609+ processed += sizeof (uint64_t ) * 4 ;
610+ }
611+
612+ lres = reinterpret_cast <uint64_t *>(frag_res.get ());
613+ auto *first_key = reinterpret_cast <const uint64_t *>(fragments[0 ].data ());
614+ switch (op_flag) {
615+ case kBitOpDiff :
616+ for (uint64_t i = 0 ; i < processed; i += sizeof (uint64_t ) * 4 ) {
617+ lres[0 ] = (first_key[0 ] & ~lres[0 ]);
618+ lres[1 ] = (first_key[1 ] & ~lres[1 ]);
619+ lres[2 ] = (first_key[2 ] & ~lres[2 ]);
620+ lres[3 ] = (first_key[3 ] & ~lres[3 ]);
621+ lres+=4 ;
622+ first_key += 4 ;
623+ }
624+ break ;
625+ case kBitOpDiff1 :
626+ for (uint64_t i = 0 ; i < processed; i += sizeof (uint64_t ) * 4 ) {
627+ lres[0 ] = (~first_key[0 ] & lres[0 ]);
628+ lres[1 ] = (~first_key[1 ] & lres[1 ]);
629+ lres[2 ] = (~first_key[2 ] & lres[2 ]);
630+ lres[3 ] = (~first_key[3 ] & lres[3 ]);
631+ lres += 4 ;
632+ first_key += 4 ;
633+ }
634+ break ;
635+ case kBitOpAndOr :
636+ for (uint64_t i = 0 ; i < processed; i += sizeof (uint64_t ) * 4 ) {
637+ lres[0 ] = (first_key[0 ] & lres[0 ]);
638+ lres[1 ] = (first_key[1 ] & lres[1 ]);
639+ lres[2 ] = (first_key[2 ] & lres[2 ]);
640+ lres[3 ] = (first_key[3 ] & lres[3 ]);
641+ lres += 4 ;
642+ first_key += 4 ;
643+ }
644+ break ;
645+ }
646+ } else if (op_flag == kBitOpOne ) {
647+ uint64_t lcommon_bits[4 ];
648+ size_t k = 0 ;
649+
650+ while (frag_minlen >= sizeof (uint64_t )*4 ) {
651+ memset (lcommon_bits, 0 , sizeof (lcommon_bits));
652+
653+ for (size_t i = 1 ; i < frag_numkeys; i++) {
654+ lcommon_bits[0 ] |= (lres[0 ] & lp[i][k+0 ]);
655+ lcommon_bits[1 ] |= (lres[1 ] & lp[i][k+1 ]);
656+ lcommon_bits[2 ] |= (lres[2 ] & lp[i][k+2 ]);
657+ lcommon_bits[3 ] |= (lres[3 ] & lp[i][k+3 ]);
658+
659+ lres[0 ] ^= lp[i][k+0 ];
660+ lres[1 ] ^= lp[i][k+1 ];
661+ lres[2 ] ^= lp[i][k+2 ];
662+ lres[3 ] ^= lp[i][k+3 ];
663+ }
664+
665+ lres[0 ] &= ~lcommon_bits[0 ];
666+ lres[1 ] &= ~lcommon_bits[1 ];
667+ lres[2 ] &= ~lcommon_bits[2 ];
668+ lres[3 ] &= ~lcommon_bits[3 ];
669+
670+ k += 4 ;
671+ lres += 4 ;
672+ j += sizeof (uint64_t ) * 4 ;
673+ frag_minlen -= sizeof (uint64_t ) * 4 ;
674+ }
592675 }
593676 }
594677#endif
595678
596- uint8_t output = 0 , byte = 0 ;
679+ uint8_t output = 0 , byte = 0 , disjunction = 0 , common_bits = 0 ;
597680 for (; j < frag_maxlen; j++) {
598681 output = (fragments[0 ].size () <= j) ? 0 : fragments[0 ][j];
599682 if (op_flag == kBitOpNot ) output = ~output;
@@ -609,11 +692,34 @@ rocksdb::Status Bitmap::BitOp(engine::Context &ctx, BitOpFlags op_flag, const st
609692 case kBitOpXor :
610693 output ^= byte;
611694 break ;
695+ case kBitOpDiff :
696+ case kBitOpDiff1 :
697+ case kBitOpAndOr :
698+ disjunction |= byte;
699+ break ;
700+ case kBitOpOne :
701+ common_bits |= (output & byte);
702+ output ^= byte;
703+ output &= ~common_bits;
704+ break ;
612705 default :
613706 break ;
614707 }
615708 }
616- frag_res[j] = output;
709+ switch (op_flag) {
710+ case kBitOpDiff :
711+ frag_res[j] = (output & ~disjunction);
712+ break ;
713+ case kBitOpDiff1 :
714+ frag_res[j] = (~output & disjunction);
715+ break ;
716+ case kBitOpAndOr :
717+ frag_res[j] = (output & disjunction);
718+ break ;
719+ default :
720+ frag_res[j] = output;
721+ break ;
722+ }
617723 }
618724
619725 if (op_flag == kBitOpNot ) {
0 commit comments