pike.git / src / modules / Gmp / mpz_glue.c

version» Context lines:

pike.git/src/modules/Gmp/mpz_glue.c:2058:    pop_stack();    if(TYPEOF(sp[-1]) != T_FUNCTION)    Pike_error("_random called with non-function argument.\n");       struct object *res=fast_clone_object(THIS_PROGRAM);    push_object(res);    stack_swap();       unsigned bits = mpz_sizeinbase(THIS, 2);    unsigned bytes = ((bits-1)>>3)+1; +  unsigned popcount = mpz_popcount(THIS);    -  +  if (((bits & 0x07) == 1) && (popcount == 1)) { +  /* An even number of bytes of random data. */ +  bytes--; +  } +     push_int(bytes);    apply_svalue(&sp[-2], 1);    if (TYPEOF(sp[-1]) != T_STRING)    Pike_error("random_string(%ld) returned non string.\n", bytes);    if ((unsigned)sp[-1].u.string->len != bytes ||    sp[-1].u.string->size_shift != 0)    Pike_error("Wrong size random string generated.\n");    -  // We are asked to simply create @[bytes] of random data. -  if( (bits%8)==0 && mpz_popcount(THIS)==bits ) -  { +  if (bits > (bytes<<3)) { +  /* We've decreased the number of bytes above. +  * Ie we have the special case of an even number of random bytes. +  */    mpz_import(OBTOMPZ(res), bytes, 1, 1, 0, 0, sp[-1].u.string->str);    pop_stack();    goto done;    }       // FIXME: Can we save a copy by either mask the pike string and    // import from it, or import the unmasked string and mask it in    // mpz object?    unsigned char *str = xalloc(bytes);    memcpy(str, sp[-1].u.string->str, bytes);    pop_stack();       unsigned char mask = (1<<(bits%8))-1; -  +  if (popcount == 1) { +  /* An even number of bits. +  * Ie the most significant bit of the masked result +  * should always be zero, so we can shrink the mask. +  */ +  mask >>= 1; +  }    if(mask) str[0] = mask & str[0];       for(int i=0; i<1000; i++)    {    mpz_import(OBTOMPZ(res), bytes, 1, 1, 0, 0, str); -  if( mpz_cmp(THIS, OBTOMPZ(res))>=0 ) +  if( mpz_cmp(THIS, OBTOMPZ(res)) > 0 )    {    free(str);    goto done;    }       // FIXME: We replace the entire string if we are too large. We    // could be smarter here, but it's easy to introduce bias by    // mistake.       push_int(bytes);