// File: /workspace/github_c_makefile_star2_O2/gplessis[P]dotdeb-redis/src/t_zset.c
// Function: zunionInterGenericCommand
void zunionInterGenericCommand(client *c, robj *dstkey, int op) {
    int i, j;
    long setnum;
    int aggregate = REDIS_AGGR_SUM;
    zsetopsrc *src;
    zsetopval zval;
    robj *tmp;
    unsigned int maxelelen = 0;
    robj *dstobj;
    zset *dstzset;
    zskiplistNode *znode;
    int touched = 0;

    /* expect setnum input keys to be given */
    if ((getLongFromObjectOrReply(c, c->argv[2], &setnum, NULL) != C_OK))
        return;

    if (setnum < 1) {
        addReplyError(c,
            "at least 1 input key is needed for ZUNIONSTORE/ZINTERSTORE");
        return;
    }

    /* test if the expected number of keys would overflow */
    if (setnum > c->argc-3) {
        addReply(c,shared.syntaxerr);
        return;
    }

    /* read keys to be used for input */
    src = zcalloc(sizeof(zsetopsrc) * setnum);
    for (i = 0, j = 3; i < setnum; i++, j++) {
        robj *obj = lookupKeyWrite(c->db,c->argv[j]);
        if (obj != NULL) {
            if (obj->type != OBJ_ZSET && obj->type != OBJ_SET) {
                zfree(src);
                addReply(c,shared.wrongtypeerr);
                return;
            }

            src[i].subject = obj;
            src[i].type = obj->type;
            src[i].encoding = obj->encoding;
        } else {
            src[i].subject = NULL;
        }

        /* Default all weights to 1. */
        src[i].weight = 1.0;
    }

    /* parse optional extra arguments */
    if (j < c->argc) {
        int remaining = c->argc - j;

        while (remaining) {
            if (remaining >= (setnum + 1) && !strcasecmp(c->argv[j]->ptr,"weights")) {
                j++; remaining--;
                for (i = 0; i < setnum; i++, j++, remaining--) {
                    if (getDoubleFromObjectOrReply(c,c->argv[j],&src[i].weight,
                            "weight value is not a float") != C_OK)
                    {
                        zfree(src);
                        return;
                    }
                }
            } else if (remaining >= 2 && !strcasecmp(c->argv[j]->ptr,"aggregate")) {
                j++; remaining--;
                if (!strcasecmp(c->argv[j]->ptr,"sum")) {
                    aggregate = REDIS_AGGR_SUM;
                } else if (!strcasecmp(c->argv[j]->ptr,"min")) {
                    aggregate = REDIS_AGGR_MIN;
                } else if (!strcasecmp(c->argv[j]->ptr,"max")) {
                    aggregate = REDIS_AGGR_MAX;
                } else {
                    zfree(src);
                    addReply(c,shared.syntaxerr);
                    return;
                }
                j++; remaining--;
            } else {
                zfree(src);
                addReply(c,shared.syntaxerr);
                return;
            }
        }
    }

    /* sort sets from the smallest to largest, this will improve our
     * algorithm's performance */
    qsort(src,setnum,sizeof(zsetopsrc),zuiCompareByCardinality);

    dstobj = createZsetObject();
    dstzset = dstobj->ptr;
    memset(&zval, 0, sizeof(zval));

    if (op == SET_OP_INTER) {
        /* Skip everything if the smallest input is empty. */
        if (zuiLength(&src[0]) > 0) {
            /* Precondition: as src[0] is non-empty and the inputs are ordered
             * by size, all src[i > 0] are non-empty too. */
            zuiInitIterator(&src[0]);
            while (zuiNext(&src[0],&zval)) {
                double score, value;

                score = src[0].weight * zval.score;
                if (isnan(score)) score = 0;

                for (j = 1; j < setnum; j++) {
                    /* It is not safe to access the zset we are
                     * iterating, so explicitly check for equal object. */
                    if (src[j].subject == src[0].subject) {
                        value = zval.score*src[j].weight;
                        zunionInterAggregate(&score,value,aggregate);
                    } else if (zuiFind(&src[j],&zval,&value)) {
                        value *= src[j].weight;
                        zunionInterAggregate(&score,value,aggregate);
                    } else {
                        break;
                    }
                }

                /* Only continue when present in every input. */
                if (j == setnum) {
                    tmp = zuiObjectFromValue(&zval);
                    znode = zslInsert(dstzset->zsl,score,tmp);
                    incrRefCount(tmp); /* added to skiplist */
                    dictAdd(dstzset->dict,tmp,&znode->score);
                    incrRefCount(tmp); /* added to dictionary */

                    if (sdsEncodedObject(tmp)) {
                        if (sdslen(tmp->ptr) > maxelelen)
                            maxelelen = sdslen(tmp->ptr);
                    }
                }
            }
            zuiClearIterator(&src[0]);
        }
    } else if (op == SET_OP_UNION) {
        dict *accumulator = dictCreate(&setDictType,NULL);
        dictIterator *di;
        dictEntry *de;
        double score;

        if (setnum) {
            /* Our union is at least as large as the largest set.
             * Resize the dictionary ASAP to avoid useless rehashing. */
            dictExpand(accumulator,zuiLength(&src[setnum-1]));
        }

        /* Step 1: Create a dictionary of elements -> aggregated-scores
         * by iterating one sorted set after the other. */
        for (i = 0; i < setnum; i++) {
            if (zuiLength(&src[i]) == 0) continue;

            zuiInitIterator(&src[i]);
            while (zuiNext(&src[i],&zval)) {
                /* Initialize value */
                score = src[i].weight * zval.score;
                if (isnan(score)) score = 0;

                /* Search for this element in the accumulating dictionary. */
                de = dictFind(accumulator,zuiObjectFromValue(&zval));
                /* If we don't have it, we need to create a new entry. */
                if (de == NULL) {
                    tmp = zuiObjectFromValue(&zval);
                    /* Remember the longest single element encountered,
                     * to understand if it's possible to convert to ziplist
                     * at the end. */
                    if (sdsEncodedObject(tmp)) {
                        if (sdslen(tmp->ptr) > maxelelen)
                            maxelelen = sdslen(tmp->ptr);
                    }
                    /* Add the element with its initial score. */
                    de = dictAddRaw(accumulator,tmp);
                    incrRefCount(tmp);
                    dictSetDoubleVal(de,score);
                } else {
                    /* Update the score with the score of the new instance
                     * of the element found in the current sorted set.
                     *
                     * Here we access directly the dictEntry double
                     * value inside the union as it is a big speedup
                     * compared to using the getDouble/setDouble API. */
                    zunionInterAggregate(&de->v.d,score,aggregate);
                }
            }
            zuiClearIterator(&src[i]);
        }

        /* Step 2: convert the dictionary into the final sorted set. */
        di = dictGetIterator(accumulator);

        /* We now are aware of the final size of the resulting sorted set,
         * let's resize the dictionary embedded inside the sorted set to the
         * right size, in order to save rehashing time. */
        dictExpand(dstzset->dict,dictSize(accumulator));

        while((de = dictNext(di)) != NULL) {
            robj *ele = dictGetKey(de);
            score = dictGetDoubleVal(de);
            znode = zslInsert(dstzset->zsl,score,ele);
            incrRefCount(ele); /* added to skiplist */
            dictAdd(dstzset->dict,ele,&znode->score);
            incrRefCount(ele); /* added to dictionary */
        }
        dictReleaseIterator(di);

        /* We can free the accumulator dictionary now. */
        dictRelease(accumulator);
    } else {
        serverPanic("Unknown operator");
    }

    if (dbDelete(c->db,dstkey))
        touched = 1;
    if (dstzset->zsl->length) {
        zsetConvertToZiplistIfNeeded(dstobj,maxelelen);
        dbAdd(c->db,dstkey,dstobj);
        addReplyLongLong(c,zsetLength(dstobj));
        signalModifiedKey(c->db,dstkey);
        notifyKeyspaceEvent(NOTIFY_ZSET,
            (op == SET_OP_UNION) ? "zunionstore" : "zinterstore",
            dstkey,c->db->id);
        server.dirty++;
    } else {
        decrRefCount(dstobj);
        addReply(c,shared.czero);
        if (touched) {
            signalModifiedKey(c->db,dstkey);
            notifyKeyspaceEvent(NOTIFY_GENERIC,"del",dstkey,c->db->id);
            server.dirty++;
        }
    }
    zfree(src);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xc8, %rsp
movl %edx, %ebp
movq %rsi, %rbx
movq %rdi, %r12
movq 0x40(%rdi), %rax
movq 0x10(%rax), %rsi
leaq 0x18(%rsp), %rdx
xorl %ecx, %ecx
callq 0x3ab5e
testl %eax, %eax
jne 0x4b061
movq 0x18(%rsp), %rax
testq %rax, %rax
jle 0x4a99a
movslq 0x38(%r12), %rcx
addq $-0x3, %rcx
cmpq %rcx, %rax
jle 0x4a9ae
leaq 0xaf982(%rip), %rax     # 0xfa310
movq 0x80(%rax), %rsi
jmp 0x4aba6
leaq 0x6a4ca(%rip), %rsi     # 0xb4e6b
movq %r12, %rdi
callq 0x36b6f
jmp 0x4b061
movl %ebp, 0x24(%rsp)
movq %rbx, 0x60(%rsp)
imulq $0x30, %rax, %rdi
callq 0x3280b
pushq $0x3
popq %rbx
movabsq $0x3ff0000000000000, %r14 # imm = 0x3FF0000000000000
movq %rax, (%rsp)
movq %rax, %r15
leaq -0x3(%rbx), %rax
movq 0x18(%rsp), %r13
cmpq %rax, %r13
jle 0x4aa33
movq 0x10(%r12), %rdi
movq 0x40(%r12), %rax
movq (%rax,%rbx,8), %rsi
callq 0x3aec2
testq %rax, %rax
je 0x4aa22
movl (%rax), %ecx
andl $0xe, %ecx
cmpl $0x2, %ecx
jne 0x4ab92
movq %rax, (%r15)
movl (%rax), %ecx
andl $0xf, %ecx
movl %ecx, 0x8(%r15)
movl (%rax), %eax
shrl $0x4, %eax
andl $0xf, %eax
movl %eax, 0xc(%r15)
jmp 0x4aa26
andq $0x0, (%r15)
movq %r14, 0x10(%r15)
incq %rbx
addq $0x30, %r15
jmp 0x4a9d4
movq %r12, 0x8(%rsp)
movl 0x38(%r12), %ecx
cmpl %ebx, %ecx
jle 0x4abb3
subl %ebx, %ecx
movq (%rsp), %rax
addq $0x10, %rax
movq %rax, 0x28(%rsp)
pushq $0x1
popq %r12
movslq %ecx, %r14
movslq %ebx, %r15
leaq 0x1(%r15), %rbp
leal -0x1(%r14), %eax
testl %r14d, %r14d
je 0x4abb7
movq %rax, 0x30(%rsp)
cmpq %r14, %r13
jge 0x4aa9e
movq 0x8(%rsp), %rax
movq 0x40(%rax), %rax
movq (%rax,%r15,8), %rax
movq 0x8(%rax), %rdi
leaq 0x6a415(%rip), %rsi     # 0xb4ea6
callq 0x262f0
testl %eax, %eax
je 0x4ab39
cmpl $0x2, %r14d
movq 0x8(%rsp), %r12
jl 0x4af50
movq 0x40(%r12), %rbx
movq (%rbx,%r15,8), %rax
movq 0x8(%rax), %rdi
leaq 0x6a409(%rip), %rsi     # 0xb4eca
callq 0x262f0
testl %eax, %eax
jne 0x4af50
movq 0x8(%rbx,%r15,8), %rax
movq 0x8(%rax), %rbx
movq %rbx, %rdi
leaq 0x7541a(%rip), %rsi     # 0xbfefb
callq 0x262f0
pushq $0x1
popq %r12
testl %eax, %eax
je 0x4ab20
movq %rbx, %rdi
leaq 0x64ce1(%rip), %rsi     # 0xaf7d9
callq 0x262f0
pushq $0x2
popq %r12
testl %eax, %eax
je 0x4ab20
movq %rbx, %rdi
leaq 0x79d03(%rip), %rsi     # 0xc4812
callq 0x262f0
pushq $0x3
popq %r12
testl %eax, %eax
jne 0x4b086
addq $-0x2, %r14
addq $0x2, %r15
addq $0x2, %rbp
movq 0x30(%rsp), %rax
addl $-0x2, %eax
jmp 0x4aa66
movq 0x28(%rsp), %rbx
xorl %r14d, %r14d
movq 0x30(%rsp), %rcx
movq 0x18(%rsp), %r13
cmpq %r14, %r13
jle 0x4ab87
movq 0x8(%rsp), %rdi
movq 0x40(%rdi), %rax
movq (%rax,%rbp,8), %rsi
movq %rbx, %rdx
movq %rcx, %r13
leaq 0x6a344(%rip), %rcx     # 0xb4eae
callq 0x3a8ae
movq %r13, %rcx
incq %r14
addq $0x30, %rbx
incq %rbp
decl %ecx
testl %eax, %eax
je 0x4ab46
jmp 0x4b0a7
leal (%r15,%r14), %ebx
incl %ebx
jmp 0x4aa58
movq (%rsp), %rdi
callq 0x328f9
leaq 0xaf76e(%rip), %rax     # 0xfa310
movq 0x70(%rax), %rsi
movq %r12, %rdi
callq 0x36987
jmp 0x4b061
pushq $0x1
popq %r12
movl 0x24(%rsp), %ebp
leaq -0x2a8(%rip), %rcx      # 0x4a91a
pushq $0x30
popq %rdx
movq (%rsp), %rbx
movq %rbx, %rdi
movq %r13, %rsi
callq 0x26890
callq 0x3a0df
movq %rax, %r15
movq 0x8(%rax), %rax
movq %rax, 0x28(%rsp)
xorpd %xmm0, %xmm0
movapd %xmm0, 0x70(%rsp)
movapd %xmm0, 0x80(%rsp)
movapd %xmm0, 0x90(%rsp)
movapd %xmm0, 0xa0(%rsp)
movapd %xmm0, 0xb0(%rsp)
testl %ebp, %ebp
je 0x4ad7d
cmpl $0x2, %ebp
jne 0x4b0ad
movq %rbx, %rdi
callq 0x4a3d7
testl %eax, %eax
jle 0x4b073
movq %r15, 0x48(%rsp)
movq %rbx, %rdi
callq 0x4a234
movq %rbx, %r14
addq $0x30, %r14
movq $0x0, 0x10(%rsp)
leaq 0x70(%rsp), %r13
leaq 0x58(%rsp), %rbp
movq %r14, 0x30(%rsp)
movq %rbx, %rdi
movq %r13, %rsi
callq 0x4a482
testl %eax, %eax
je 0x4af5e
movsd 0x10(%rbx), %xmm0
mulsd 0xb8(%rsp), %xmm0
movapd %xmm0, %xmm1
cmpordsd %xmm0, %xmm1
andpd %xmm0, %xmm1
movlpd %xmm1, 0x58(%rsp)
movq %r14, %rbx
pushq $0x1
popq %r15
movq 0x18(%rsp), %rax
cmpq %r15, %rax
jle 0x4acff
movq (%rbx), %rax
movq (%rsp), %rcx
cmpq (%rcx), %rax
je 0x4acd2
movq %rbx, %rdi
movq %r13, %rsi
leaq 0x50(%rsp), %rdx
callq 0x4a7bf
testl %eax, %eax
je 0x4acfa
movsd 0x10(%rbx), %xmm0
mulsd 0x50(%rsp), %xmm0
jmp 0x4ace0
movsd 0xb8(%rsp), %xmm0
mulsd 0x10(%rbx), %xmm0
movsd %xmm0, 0x50(%rsp)
movq %rbp, %rdi
movl %r12d, %esi
callq 0x4b0cd
incq %r15
addq $0x30, %rbx
jmp 0x4ac9b
movq 0x18(%rsp), %rax
cmpq %r15, %rax
jne 0x4ad74
movq %r13, %rdi
callq 0x4a704
movq %rax, %rbx
movq 0x28(%rsp), %r14
movq 0x8(%r14), %rdi
movsd 0x58(%rsp), %xmm0
movq %rax, %rsi
callq 0x479ab
movq %rax, %r15
movq %rbx, %rdi
callq 0x39e74
movq (%r14), %rdi
addq $0x8, %r15
movq %rbx, %rsi
movq %r15, %rdx
callq 0x2a3ed
movq %rbx, %rdi
callq 0x39e74
movl (%rbx), %eax
shrl $0x4, %eax
testb $0x7, %al
jne 0x4ad6f
movq 0x8(%rbx), %rdi
callq 0x482f2
movq 0x10(%rsp), %rdx
movl %edx, %ecx
cmpq %rcx, %rax
cmovbel %edx, %eax
movq %rax, 0x10(%rsp)
movq 0x30(%rsp), %r14
movq (%rsp), %rbx
jmp 0x4ac60
movq %r15, 0x48(%rsp)
leaq 0xae027(%rip), %rdi     # 0xf8db0
movq $0x0, 0x10(%rsp)
xorl %esi, %esi
callq 0x2a155
movq %rax, %r13
movq 0x18(%rsp), %rax
testq %rax, %rax
je 0x4adc2
imulq $0x30, %rax, %rax
leaq (%rbx,%rax), %rdi
addq $-0x30, %rdi
callq 0x4a3d7
movslq %eax, %rsi
movq %r13, %rdi
callq 0x2a1b7
leaq 0x70(%rsp), %r14
xorl %r15d, %r15d
cmpq %r15, 0x18(%rsp)
jle 0x4aecb
imulq $0x30, %r15, %rbp
addq %rbx, %rbp
movq %rbp, %rdi
callq 0x4a3d7
testl %eax, %eax
je 0x4aec3
movq %rbp, %rdi
callq 0x4a234
movq %rbp, %rdi
movq %r14, %rsi
callq 0x4a482
testl %eax, %eax
je 0x4aebb
movsd 0x10(%rbp), %xmm0
mulsd 0xb8(%rsp), %xmm0
movapd %xmm0, %xmm1
cmpordsd %xmm0, %xmm1
andpd %xmm0, %xmm1
movapd %xmm1, 0x30(%rsp)
movq %r14, %rdi
callq 0x4a704
movq %r13, %rdi
movq %rax, %rsi
callq 0x2a5f9
testq %rax, %rax
je 0x4ae57
addq $0x8, %rax
movq %rax, %rdi
movapd 0x30(%rsp), %xmm0
movl %r12d, %esi
callq 0x4b0cd
jmp 0x4adf4
movq %r14, %rdi
callq 0x4a704
movq %rax, %rbx
movl (%rax), %eax
shrl $0x4, %eax
testb $0x7, %al
movq %r15, 0x68(%rsp)
jne 0x4ae8b
movq 0x8(%rbx), %rdi
callq 0x482f2
movq 0x10(%rsp), %rdx
movl %edx, %ecx
cmpq %rcx, %rax
cmovbel %edx, %eax
movq %rax, 0x10(%rsp)
movq %r13, %rdi
movq %rbx, %rsi
callq 0x2a42e
movq %rax, %r15
movq %rbx, %rdi
callq 0x39e74
movapd 0x30(%rsp), %xmm0
movsd %xmm0, 0x8(%r15)
movq (%rsp), %rbx
movq 0x68(%rsp), %r15
jmp 0x4adf4
movq %rbp, %rdi
callq 0x4a355
incq %r15
jmp 0x4adca
movq %r13, %rdi
callq 0x2a99f
movq %rax, %rbx
movq 0x28(%rsp), %rax
movq (%rax), %rdi
movq 0x48(%r13), %rsi
addq 0x28(%r13), %rsi
callq 0x2a1b7
movq 0x8(%rsp), %r12
movq 0x28(%rsp), %rbp
movq %rbx, %rdi
callq 0x2a9d3
testq %rax, %rax
je 0x4af3e
movq (%rax), %r14
movsd 0x8(%rax), %xmm0
movq 0x8(%rbp), %rdi
movq %r14, %rsi
callq 0x479ab
movq %rax, %r15
movq %r14, %rdi
callq 0x39e74
movq (%rbp), %rdi
addq $0x8, %r15
movq %r14, %rsi
movq %r15, %rdx
callq 0x2a3ed
movq %r14, %rdi
callq 0x39e74
jmp 0x4aef5
movq %rbx, %rdi
callq 0x2aa94
movq %r13, %rdi
callq 0x2a8da
jmp 0x4af6b
movq (%rsp), %rdi
callq 0x328f9
jmp 0x4a987
movq %rbx, %rdi
callq 0x4a355
movq 0x8(%rsp), %r12
movq 0x48(%rsp), %r15
movq 0x10(%r12), %rdi
movq 0x60(%rsp), %r14
movq %r14, %rsi
callq 0x3b1df
movl %eax, %ebx
movq 0x28(%rsp), %rax
movq 0x8(%rax), %rax
cmpq $0x0, 0x10(%rax)
je 0x4b001
movl 0x10(%rsp), %esi
movq %r15, %rdi
callq 0x4940d
movq 0x10(%r12), %rdi
movq %r14, %rsi
movq %r15, %rdx
callq 0x3af45
movq %r15, %rdi
callq 0x490f5
movl %eax, %esi
movq %r12, %rdi
callq 0x370a6
movq 0x10(%r12), %rdi
movq %r14, %rsi
callq 0x3b125
cmpl $0x0, 0x24(%rsp)
leaq 0x635e7(%rip), %rax     # 0xae5c2
leaq 0x635ec(%rip), %rsi     # 0xae5ce
cmoveq %rax, %rsi
movq 0x10(%r12), %rax
movl 0x30(%rax), %ecx
movl $0x80, %edi
movq %r14, %rdx
callq 0x6fb58
movq (%rsp), %rbx
jmp 0x4b04b
movq %r15, %rdi
callq 0x3a265
leaq 0xaf300(%rip), %rax     # 0xfa310
movq 0x20(%rax), %rsi
movq %r12, %rdi
callq 0x36987
testl %ebx, %ebx
movq (%rsp), %rbx
je 0x4b059
movq 0x10(%r12), %rdi
movq %r14, %rsi
callq 0x3b125
movq 0x10(%r12), %rax
movl 0x30(%rax), %ecx
leaq 0x653d8(%rip), %rsi     # 0xb0418
pushq $0x4
popq %rdi
movq %r14, %rdx
callq 0x6fb58
leaq 0xae856(%rip), %rax     # 0xf98a8
incq 0x720(%rax)
movq %rbx, %rdi
callq 0x328f9
addq $0xc8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq $0x0, 0x10(%rsp)
movq 0x8(%rsp), %r12
jmp 0x4af70
movq (%rsp), %rdi
callq 0x328f9
leaq 0xaf27a(%rip), %rax     # 0xfa310
movq 0x80(%rax), %rsi
movq 0x8(%rsp), %rdi
jmp 0x4aba9
movq (%rsp), %rdi
jmp 0x4b05c
leaq 0x69e20(%rip), %rdi     # 0xb4ed4
leaq 0x69a97(%rip), %rsi     # 0xb4b52
movl $0x864, %edx            # imm = 0x864
callq 0x57b45
pushq $0x1
popq %rdi
callq 0x263c0