DIM AS CInt96 big
big = 1
For k As Long=1 to 95
Print k,shift_left96( big,k)
Next
Print "******************"
big="79228162514264337593543950335"
For k As Long=1 to 95
Print k,shift_right96( big,k)
Next
Sleep
I thought it might be slow - but it belts along. Printing to the console is time-consuming so that number crunching is fast.
One cannot transform your function into the 'Shl' operator because such operators do not support recursion, but one can declare a 'Shl' operator that calls this function:
operator shl(byref n as CInt96, byref k as long) as CInt96
return shift_left96(n, k)
end operator
dim as CInt96 big=8
for k as long=1 to 92
print k, big shl k
next
thank you fxm, was not aware that recursion was not allowed in operators, but your solution works. :-)
the or, xor, and operators are very simple and should be no problem.
operator shl(byval n as CInt96, byval k as long) as CInt96
dim as ulong a, b, c
a=n.m_int96.Hi32
b=n.m_int96.Mid32
c=(n.m_int96.Lo64 shl 32 ) shr 32
if k<=96 then
if k>=32 then
a=b
b=c
c=0
n.m_int96.Hi32=a
n.m_int96.Lo64=c
n.m_int96.Mid32=b
return n shl (k-32)
else
if k=0 then
return n
else
a=(a shl k) or (b shr (32 - k))
b = (b shl k) or (c shr (32 - k))
c = c shl k
n.m_int96.Hi32=a
n.m_int96.Lo64=c
n.m_int96.Mid32=b
end if
end if
end if
return n
end operator
- 'Return' calls the copy-constructor while 'Function =' calls the let-operator but as the two procedures have the same code, so the problem is not coming for here!
When I started using Free Basic, I had a problem with a class for not knowing this very important distinction. I had implemented a copy constructor, but not a LET operator. Therefore, I wrongly thought that there was a problem with FUNCTION= because the methods that used RETURN worked fine but the ones that used FUNCTION= don't.
operator shl(byval n as CInt96, byval k as long) as CInt96
dim as ulong a, b, c
a=n.m_int96.Hi32
b=n.m_int96.Mid32
c=(n.m_int96.Lo64 shl 32 ) shr 32
if k<=96 then
if k>=32 then
a=b
b=c
c=0
n.m_int96.Hi32=a
n.m_int96.Lo64=c
n.m_int96.Mid32=b
return n shl (k-32)
else
if k=0 then
return n
else
a=(a shl k) or (b shr (32 - k))
b = (b shl k) or (c shr (32 - k))
c = c shl k
n.m_int96.Hi32=a
n.m_int96.Lo64=c
n.m_int96.Mid32=b
end if
end if
end if
return n
end operator
' ========================================================================================
operator shr(byval n as CInt96, byval k as long) as CInt96
dim as ulong a, b, c
a=n.m_int96.Hi32
b=n.m_int96.Mid32
c=(n.m_int96.Lo64 shl 32 ) shr 32
if k<=96 then
if k>=32 then
c = b
b = a
a = 0
n.m_int96.Hi32=a
n.m_int96.Lo64=c
n.m_int96.Mid32=b
return n shr (k-32)
else
if k=0 then
return n
else
c = (b shl (32-k)) or (c shr k)
b = (a shl (32-k)) or (b shr k)
a = a shr k
n.m_int96.Hi32=a
n.m_int96.Lo64=c
n.m_int96.Mid32=b
end if
end if
end if
return n
end operator
' ========================================================================================
operator sqr(byval n as CInt96) as CInt96
dim as CInt96 r=sqr(n)
while r*r>n
r-=1
wend
while n-r*r>r*2
r+=1
wend
return r
end operator
' ========================================================================================
operator and(byval n as CInt96, byval m as CInt96) as CInt96
n.m_int96.Hi32 and=m.m_int96.Hi32
n.m_int96.Lo64 and=m.m_int96.Lo64
return n
end operator
' ========================================================================================
operator or(byval n as CInt96, byval m as CInt96) as CInt96
n.m_int96.Hi32 or=m.m_int96.Hi32
n.m_int96.Lo64 or=m.m_int96.Lo64
return n
end operator
' ========================================================================================
operator xor(byval n as CInt96, byval m as CInt96) as CInt96
n.m_int96.Hi32 xor=m.m_int96.Hi32
n.m_int96.Lo64 xor=m.m_int96.Lo64
return n
end operator
operator not(byval n as CInt96) as CInt96
n.m_int96.Hi32=not n.m_int96.Hi32
n.m_int96.Lo64=not n.m_int96.Lo64
return n
end operator
operator shl(byval n as CInt96, byval k as long) as CInt96
/'
type tagDEC
wReserved as USHORT
union
type
scale as UBYTE
sign as UBYTE
end type
signscale as USHORT
end union
Hi32 as ULONG
union
type
Lo32 as ULONG
Mid32 as ULONG
end type
Lo64 as ULONGLONG
end union
end type
type DECIMAL as tagDEC
'/
/'
TYPE CInt96
m_int96 AS DECIMAL ' // The underlying DECIMAL structure
END TYPE
'/
'CInt96 type has three members inherited from Decimal
'm_int96.Hi32 as ulong
'union
' m_int96.Mid32 as ulong
' m_int96.Lo64 as ulongint
'end union
'so m_int96.Mid32 = high32-bits of m_int96.Lo64
' ---------m_int96.Mid32----------
'----------m_int96.Hi32---------- -------------------------m_int96.Lo64-----------------------------
'11111111111111111111111111111111 11111111111111111111111111111111 11111111111111111111111111111111
'
if k<96 then
if k<32 then
n.m_int96.Hi32=(n.m_int96.Hi32 shl k) or (n.m_int96.Lo64 shr (64-k))
n.m_int96.Lo64=n.m_int96.Lo64 shl k
elseif k=32 then
n.m_int96.Hi32=n.m_int96.Mid32
n.m_int96.Lo64=n.m_int96.Lo64 shl k
elseif k>32 andalso k<64 then
n.m_int96.Hi32=(n.m_int96.Mid32 shl (k-32)) or (n.m_int96.Lo64 shr (64-k))
n.m_int96.Lo64=n.m_int96.Lo64 shl k
elseif k>=64 then
n.m_int96.Lo64=n.m_int96.Lo64 shl (k-32)
n.m_int96.Hi32=n.m_int96.Mid32
n.m_int96.Lo64=0
end if
else
print "warning: Left-Shift value greater than or equal to number of bits in CInt96 type"
end if
return n
end operator
' ========================================================================================
operator shr(byval n as CInt96, byval k as long) as CInt96
/'
type tagDEC
wReserved as USHORT
union
type
scale as UBYTE
sign as UBYTE
end type
signscale as USHORT
end union
Hi32 as ULONG
union
type
Lo32 as ULONG
Mid32 as ULONG
end type
Lo64 as ULONGLONG
end union
end type
type DECIMAL as tagDEC
'/
/'
TYPE CInt96
m_int96 AS DECIMAL ' // The underlying DECIMAL structure
END TYPE
'/
'CInt96 type has three members inherited from Decimal
'm_int96.Hi32 as ulong
'union
' m_int96.Mid32 as ulong
' m_int96.Lo64 as ulongint
'end union
'so m_int96.Mid32 = high32-bits of m_int96.Lo64
' ---------m_int96.Mid32----------
'----------m_int96.Hi32---------- -------------------------m_int96.Lo64-----------------------------
'11111111111111111111111111111111 11111111111111111111111111111111 11111111111111111111111111111111
'
dim as ulong midle
if k<96 then
if k<32 then
midle=(n.m_int96.Hi32 shl (32-k)) or (n.m_int96.Mid32 shr k)
n.m_int96.Hi32=n.m_int96.Hi32 shr k
n.m_int96.Lo64=n.m_int96.Lo64 shr k
n.m_int96.Mid32=midle
elseif k=32 then
n.m_int96.Lo64=n.m_int96.Lo64 shr k
n.m_int96.Mid32=n.m_int96.Hi32
n.m_int96.Hi32=0
elseif k>32 then
n.m_int96.Lo64=n.m_int96.Lo64 shr 32
n.m_int96.Mid32=n.m_int96.Hi32
n.m_int96.Lo64=n.m_int96.Lo64 shr (k-32)
n.m_int96.Hi32=0
end if
else
print "warning: Right-Shift value greater than or equal to number of bits in CInt96 type"
end if
return n
end operator