[music-dsp] JUCE rounding hack

Lubomir I. Ivanov neolit123 at gmail.com
Thu Sep 12 12:04:34 EDT 2013


problem with the 6755399441055744.0 hack is that it still performs one
FPU arithmetic, but i'm assuming it is to work around FPU control word
considerations that the compiler may impose with regular casts. for
x87 the plain "fld", "fistp" combination may be faster.

for a flex, here is something without multiplications and with only
one branch, but it does require a 64bit integer type from the compiler
(can be done in 32bit too i guess) and does not have all safety
checks.

---------------------------
/* fast double to int experiment for c99 */

#include <stdio.h>
#include <stdint.h>

#define negate(x, c) \
(((x) ^ -c) + c)

int32_t double_to_int32(const double x)
{
const uint8_t sign_bit = 63;
const uint8_t significand_bits = 52;
/* implicit_bit = 1 << significand_bits */
const uint64_t implicit_bit = 0x0010000000000000LL;
/* exponent_bias = ((1 << exponent_bits) - 1) >> 1 */
const uint64_t exponent_bias = 0x0028ffc4000003ffLL;
/* significand_mask = implicit_bit - 1 */
const uint64_t significand_mask = 0x000fffffffffffffLL;
/* abs_mask = (1 << sign_bit) - 1 */
const uint64_t abs_mask = 0x7fffffffffffffffLL;

const uint64_t val = *(uint64_t *)&x;
const uint64_t abs_val = val & abs_mask;
const uint64_t significand = (abs_val & significand_mask) | implicit_bit;
const int exponent = (abs_val >> significand_bits) - exponent_bias;
const unsigned int sign = val >> sign_bit;

/* no handling of infinity here */
if (exponent < 0)
return 0;
else if (exponent < significand_bits)
return negate(significand >> (significand_bits - exponent), sign);
else
return negate(significand << (exponent - significand_bits), sign);
}

int main(void)
{
double val = -123456789;
printf("%.2f, %d, %d", val, (int)val, double_to_int32(val));
return 1;
}
-------------------

lubomir
--

On 12 September 2013 14:07, Victor Lazzarini <Victor.Lazzarini at nuim.ie> wrote:
> Sorry, I missed the | bc ...
> On 12 Sep 2013, at 11:59, Victor Lazzarini wrote:
>
>> what version of echo are you using that evaluates expressions?
>>
>> Victor
>> On 12 Sep 2013, at 11:43, Tito Latini wrote:
>>
>>> The follow example could help. The `dfloat_info' command prints three
>>> values: the exponent (decimal), the highest 20 bits and the lowest 32
>>> bits of the significand (hexadecimal).
>>>
>>> cc -o dfloat_info dfloat_info.c
>>>
>>> # Rounding 123.456 without the offset 2^51; it works...
>>> ./dfloat_info `echo 2^52 + 123.456|bc`
>>> 52 0x0 0x7b
>>>
>>> # ...but naturally fails with negative nums
>>> ./dfloat_info `echo 2^52 - 1|bc`
>>> 51 0xfffff 0xfffffffe
>>>
>>> # fix adding the offset
>>> # 2^52 + 2^51 = 6755399441055744
>>> ./dfloat_info `echo 2^52 + 2^51 - 1|bc`
>>> 52 0x7ffff 0xffffffff
>>>
>>> ./dfloat_info `echo 2^52 + 2^51 + 123.456|bc`
>>> 52 0x80000 0x7b
>>>
>>> ./dfloat_info `echo 2^52 + 2^51 - 123.456|bc`
>>> 52 0x7ffff 0xffffff85
>>>
>>>
>>> /* dfloat_info.c */
>>> #include <stdio.h>
>>> #include <stdlib.h>
>>>
>>> void double_float_info(double x)
>>> {
>>>   union { int as_int[2]; double as_double; } n;
>>>   int significand_51_32, significand_31_0, exponent, bias;
>>>
>>>   n.as_double = x;
>>>   bias = 1023;
>>>   /* little endian machine */
>>>   exponent = ((n.as_int[1] >> 20) & 0x7FF) - bias;
>>>   significand_51_32 = n.as_int[1] & 0xFFFFF;
>>>   significand_31_0 = n.as_int[0];
>>>
>>>   printf("%u 0x%x 0x%x\n", exponent, significand_51_32, significand_31_0);
>>> }
>>>
>>> int main(int argc, char **argv)
>>> {
>>>   if (argc < 2) return 1;
>>>   double_float_info(atof(argv[1]));
>>>   return 0;
>>> }
>>>
>>> Tito Latini
>>>
>>> On Thu, Sep 12, 2013 at 06:24:50AM +0100, Luke Drummond wrote:
>>>> On 12 September 2013 05:53, m brandenberg <mcbinc at panix.com> wrote:
>>>>> On Wed, 11 Sep 2013, robert bristow-johnson wrote:
>>>>>
>>>>>> can anyone tell me how this hack works?  i can hardly believe that it
>>>>>> does.
>>>>>>
>>>>>> i am reasonably well familiar with the IEEE-754 format for either floats
>>>>>> or doubles.  how does this get past the exponent?
>>>>>
>>>>>
>>>>> Not certain which part of the hack you're asking about.
>>>>> Binary exponent of 52 scales the significand so that
>>>>> the LSB is 2^0.  Add a number less than 2^32 to it,
>>>>> extract the low 32 bits and you have the number.
>>>>>
>>>>> Rounding rules apply during the addition so, in this
>>>>> case, 0.5 => 0, 1.5 => 2, 2.5 => 2, 3.5 => 4
>>>>> keeping low bit zero.
>>>>>
>>>>> Addition of 2^51 is to provide something to borrow
>>>>> from for negative numbers so that the exponent doesn't
>>>>> change.
>>>>>
>>>>> How's that?
>>>>>
>>>>> --
>>>>> Monty Brandenberg
>>>>>
>>>>> --
>>>>> dupswapdrop -- the music-dsp mailing list and website:
>>>>> subscription info, FAQ, source code archive, list archive, book reviews, dsp
>>>>> links
>>>>> http://music.columbia.edu/cmc/music-dsp
>>>>> http://music.columbia.edu/mailman/listinfo/music-dsp
>>>>
>>>> Hi Robert
>>>>
>>>> There is an excellent discussion of this at
>>>> http://stackoverflow.com/questions/17035464/a-fast-method-to-round-a-double-to-a-32-bit-int-explained
>>>>
>>>> FWIW I remember coming across this somewhere in the Lua source, and I
>>>> was definitely troubled by it at the time.  It still doesn't make
>>>> sense to me in fact.
>>>> Lua uses doubles as standard for all numeric types (there is no int)
>>>> and conversion to int really only matters for those using the C API.
>>>> Apparently the performance gains over lrint() and a plain c cast are
>>>> pretty tremendous.
>>>>
>>>> Best
>>>>
>>>> Luke
>>>> --
>>>> dupswapdrop -- the music-dsp mailing list and website:
>>>> subscription info, FAQ, source code archive, list archive, book reviews, dsp links
>>>> http://music.columbia.edu/cmc/music-dsp
>>>> http://music.columbia.edu/mailman/listinfo/music-dsp
>>> --
>>> dupswapdrop -- the music-dsp mailing list and website:
>>> subscription info, FAQ, source code archive, list archive, book reviews, dsp links
>>> http://music.columbia.edu/cmc/music-dsp
>>> http://music.columbia.edu/mailman/listinfo/music-dsp
>>
>> Dr Victor Lazzarini
>> Senior Lecturer
>> Dept. of Music
>> NUI Maynooth Ireland
>> tel.: +353 1 708 3545
>> Victor dot Lazzarini AT nuim dot ie
>>
>>
>>
>> --
>> dupswapdrop -- the music-dsp mailing list and website:
>> subscription info, FAQ, source code archive, list archive, book reviews, dsp links
>> http://music.columbia.edu/cmc/music-dsp
>> http://music.columbia.edu/mailman/listinfo/music-dsp
>
> Dr Victor Lazzarini
> Senior Lecturer
> Dept. of Music
> NUI Maynooth Ireland
> tel.: +353 1 708 3545
> Victor dot Lazzarini AT nuim dot ie
>
>
>
> --
> dupswapdrop -- the music-dsp mailing list and website:
> subscription info, FAQ, source code archive, list archive, book reviews, dsp links
> http://music.columbia.edu/cmc/music-dsp
> http://music.columbia.edu/mailman/listinfo/music-dsp


More information about the music-dsp mailing list