array shifter
#1
for multi-precision binary addition and subtraction you need multi-precision shifts to align the decimal point, here are some functions to shift an array of longs
Code: (Select All)
_Title "array-shifter"
$NoPrefix
$Console:Only
Dest Console

Option Explicit
Dim As _Unsigned Long n(2), k
Dim As Long i, ln
Dim As String s

Print "we first shift the array left and then right from 1 to 16"
Print "notice that 0's are shifted in on the left because we shift left then right"
Print "the top row-pair is the original for comparison"
Print "press return to start"
Sleep
For i = 1 To 16
    n(0) = &B11111111111111111010101010101010
    n(1) = &B10101010101010101010101010101010
    n(2) = &B10101010101010111111111111111111

    k = i
    s = _Bin$(n(0)) + _Bin$(n(1)) + _Bin$(n(2))
    ln = (UBound(n) + 1) * 32
    If Len(s) < ln Then
        s = String$(ln - Len(s), "0") + s
    End If
    Print s
    shiftl n(), k
    shiftr n(), k
    s = _Bin$(n(0)) + _Bin$(n(1)) + _Bin$(n(2))
    If Len(s) < ln Then
        s = String$(ln - Len(s), "0") + s
    End If
    Print s

    Print
Next
Print "press return to continue"
Sleep
Cls
Print "we first shift the array right and then left from 1 to 16"
Print "notice that 0's are shifted in on the right because we shift right then left"
Print "the top row-pair is the original for comparison"
Print "press return to start"
Sleep
For i = 1 To 16
    n(0) = &B11111111111111111010101010101010
    n(1) = &B10101010101010101010101010101010
    n(2) = &B10101010101010111111111111111111

    k = i
    s = _Bin$(n(0)) + _Bin$(n(1)) + _Bin$(n(2))
    If Len(s) < ln Then
        s = s + String$(ln - Len(s), "0")
    End If
    Print s
    shiftr n(), k
    shiftl n(), k
    s = _Bin$(n(0)) + _Bin$(n(1)) + _Bin$(n(2))
    If Len(s) < ln Then
        s = s + String$(ln - Len(s), "0")
    End If
    Print s
    Print
Next
Print "press return to exit"

Function shl32~& (n As _Unsigned Long, k As _Unsigned _Byte, c As _Unsigned Long)
    If k > 0 And k < 32 Then
        Dim As _Unsigned Long carry: carry = n
        Dim As _Unsigned _Byte k32: k32 = 32 - k
        carry = _ShR(carry, k32)
        n = ShL(n, k)
        c = carry
    End If
    shl32~& = n
End Function

Function shr32~& (n As _Unsigned Long, k As _Unsigned _Byte, c As _Unsigned Long)
    If k > 0 And k < 32 Then
        Dim As _Unsigned Long carry: carry = n
        Dim As _Unsigned _Byte k32: k32 = 32 - k
        carry = _ShL(carry, k32)
        n = _ShR(n, k)
        c = carry
    End If
    shr32~& = n
End Function

Sub shiftl (n() As _Unsigned Long, k As Long)
    Dim As Long i, ub: ub = UBound(n)
    Dim As _Unsigned Long carry, c: c = 0
    If k > 0 And k < 32 Then
        For i = ub To 0 Step -1
            n(i) = shl32(n(i), k, carry) + c
            c = carry
        Next
    ElseIf k = 32 Then
        For i = 0 To ub - 1
            n(i) = n(i + 1)
        Next
        n(ub) = 0
    End If
End Sub

Sub shiftr (n() As _Unsigned Long, k As Long)
    Dim As Long i, ub: ub = UBound(n)
    Dim As _Unsigned Long carry, c: c = 0
    If k > 0 And k < 32 Then
        For i = 0 To ub
            n(i) = c + shr32(n(i), k, carry)
            c = carry
        Next
    ElseIf k = 32 Then
        For i = ub To 1 Step -1
            n(i) = n(i - 1)
        Next
        n(0) = 0
    End If
End Sub
Reply
#2
Bit shifting... oh the horror!!! :O

Pete
Reply
#3
I did a binary floating point package in FreeBasic, the arithmetic functions are better than 2 times faster than the decimal version but the conversion routines are a horror
when I started writing the routines I had no easy way to debug the result, I needed the arithmetic functions in order to implement the conversion routines, almost like a catch 22
Reply
#4
I've been thinking about the conversions and as with powers in binary, tables might be necessary especially for extended precision.
b = b + ...
Reply
#5
bplus
I think that you are on the right track, I have seen the use of tables in binary conversion, it's just that I have not taken the trouble to learn how to use them
the tables for binary floating point conversion were negative and positive powers of 10
what I did instead was to get an estimate of the power of ten needed and then raise 10 to that power in a temporary variable
Reply
#6
1011.01001011 =

2^3 + 2^1 + 2^0 + 2^-2 + 2^-5 + 2^-7 + 2^-8

Table: -100 to 100 = 201 lines
2 ^ -100 = 1/1,267,650,600,228,229,401,496,703,205,376 Pete can get that for you Smile
.
.
.
2^-3 =.125
2^-2 =.25
2^-1 =.5
2^ 0 = 1
2^1 = 2
2^2 = 4
.
.
.
2^ 100 = 1,267,650,600,228,229,401,496,703,205,376
b = b + ...
Reply
#7
good example bplus Smile
but it's more complicated with a binary floating point number with some high exponent
Reply
#8
.00000000000000000000000000000007888609052210118054117285652827862296732064351090230047702789306640625
If eggs are brain food, Biden takes his scrambled.
Reply
#9
oops!

Pete you might be off a zero, all the non zero digits look good:
   
b = b + ...
Reply
#10
It is off by 1. I used some code I have in progress to make that calculation. So my old system got it right, but something is amiss with some new code I'm putting together while trying out some long division ideas for nth roots. I will investigate.

Thanks!

Pete

EDIT: ...and I found it. In the betatest text I had a duplicate of the decimal adjustment statement. That threw in an extra decimal point.

.0000000000000000000000000000007888609052210118054117285652827862296732064351090230047702789306640625
If eggs are brain food, Biden takes his scrambled.
Reply




Users browsing this thread: 4 Guest(s)