'
' Number.SetBits
'
' 24 Jan 2002
'
' A number in Avenue is a double precision IEEE float. In general,
' floats have a mantissa and an exponent, each with a separate sign
' bit. If the float has n bits (n=64 for double precision) and
' the mantissa has m bits (m=51 for double precision), then the
' exponent has n-m-2 bits. The float's value is equal to
'
' mantissa * 2^(exponent-m)
'
' All but the very smallest floats are normalized to make the leading
' digit of the mantissa equal to 1. (This cannot be done for a value
' of zero, of course.)
'
' Bit offsets in this subroutine begin at 0. Thus, usually the 0th
' bit of the mantissa is 1.
'===================================================================='
x = SELF.Get(0) '
Original number
nBits = SELF.Get(4) ' Number of bits to
set; 0 or greater
if (nBits<=0) then
return x
end
iX = SELF.Get(1) '
Start bit offset in x; must be 1 or greater
bmpIn = SELF.Get(2) ' Bitmap
iB = SELF.Get(3) '
Start bit offset in bmpIn
'
' Deal with negative values by removing the sign bit temporarily.
'
bNegative = (x<0.0)
x = x.Abs
'
' Find the exponent. We must have
'
' 1/2 <= mantissa*2^-m < 1
' and
' x = mantissa * 2^(exponent-m)
'
' Therefore
' 1/2 <= x * 2^(m-exponent) < 1
' or
' 2^(exponent-m-1) <= x < 2^(exponent-m)
'
' implying
' exponent-m-1 <= x.Log(2) < exponent-m
'
' Unfortunately, x.Log(2) could be inaccurately computed.
'
' The term "exponent-m" will be held in the nExponent variable.
'
if (x=0.0) then
nExponent = -1023 ' ???
else
'
' Exponents must not overflow the range -1023..1024 in
' any of the subsequent operations, so that expressions
' like 2^(-nExponent) and 2^(nExponent-1) will not overflow.
'
nExponent = x.Log(2).Ceiling max -1023
while (2^(nExponent-1)>x and (nExponent>-1023))
nExponent = nExponent-1
end
while (2^nExponent<=x and (nExponent<1024))
nExponent = nExponent+1
end
end
'
' Retain just the mantissa in x:
'
x = 2^(-nExponent)*x
'
' Analyze the mantissa into three parts:
' the "prefix" that precedes the bits to set,
' the "message" that contains the bits to set,
' and the "postfix" that remains.
'
' Bite off the left iX bits of x, then shift another
' nBits left to make room for xMessage:
'
xPrefix = (2^iX*x).Floor
xPrefix = 2^nBits*xPrefix
'
' Bit off the right iX+nBits bits and normalize:
'
xPostfix = 2^(iX+nBits)*x
xPostfix = xPostfix-xPostfix.Floor
'
' Set the "message" bits:
'
xMessage = 0 ' Output bits
if (bmpIn<>NIL) then
for each iBit in iB..(iB+nBits-1)
'
' Read the next incoming bit.
'
b = bmpIn.Get(iBit)
'
' Set the next bit of the message to b.
'
xMessage = xMessage*2
if (b) then
xMessage = xMessage+1
end
end
end
'
' Synthesize the output from the prefix, message, and postfix
' then shift back into normal position and restore the sign bit:
'
x = 2^(nExponent-iX-nBits)*(xPrefix+xMessage+xPostfix)
if (bNegative) then
x = -x
end
return x
' end of script