#COMPILE EXE
#DIM ALL

FUNCTION PBMAIN() AS LONG
    LOCAL a_digits(100) AS LONG
    LOCAL b_digits(100) AS LONG
    LOCAL r_digits(200) AS LONG
    LOCAL a_len AS LONG
    LOCAL b_len AS LONG
    LOCAL r_len AS LONG
    LOCAL i AS LONG
    LOCAL j AS LONG
    LOCAL k AS LONG
    LOCAL carry AS LONG
    LOCAL digit AS LONG
    LOCAL temp_str AS STRING
    LOCAL product AS LONG
    LOCAL remain AS LONG

    ' Big integer multiplication and division with digit arrays

    ' 123 * 45
    a_len = 3
    a_digits(0) = 3
    a_digits(1) = 2
    a_digits(2) = 1
    b_len = 2
    b_digits(0) = 5
    b_digits(1) = 4

    i = 0
    WHILE i < 200
        r_digits(i) = 0
        i = i + 1
    WEND

    i = 0
    WHILE i < a_len
        carry = 0
        j = 0
        WHILE j < b_len
            product = a_digits(i) * b_digits(j) + r_digits(i + j) + carry
            r_digits(i + j) = product MOD 10
            carry = product / 10
            j = j + 1
        WEND
        IF carry > 0 THEN
            r_digits(i + j) = carry
            r_len = i + j + 1
        ELSE
            r_len = i + j
        END IF
        i = i + 1
    WEND

    temp_str = ""
    i = r_len - 1
    WHILE i >= 0
        temp_str = temp_str + CHR$(48 + r_digits(i))
        i = i - 1
    WEND
    PRINT "123 * 45 = " + temp_str

    ' 999 * 999 = 998001
    i = 0
    WHILE i < 100
        a_digits(i) = 0
        b_digits(i) = 0
        i = i + 1
    WEND
    a_len = 3
    a_digits(0) = 9
    a_digits(1) = 9
    a_digits(2) = 9
    b_len = 3
    b_digits(0) = 9
    b_digits(1) = 9
    b_digits(2) = 9

    i = 0
    WHILE i < 200
        r_digits(i) = 0
        i = i + 1
    WEND

    i = 0
    WHILE i < a_len
        carry = 0
        j = 0
        WHILE j < b_len
            product = a_digits(i) * b_digits(j) + r_digits(i + j) + carry
            r_digits(i + j) = product MOD 10
            carry = product / 10
            j = j + 1
        WEND
        IF carry > 0 THEN
            r_digits(i + j) = carry
        END IF
        i = i + 1
    WEND
    r_len = a_len + b_len
    WHILE r_len > 1 AND r_digits(r_len - 1) = 0
        r_len = r_len - 1
    WEND

    temp_str = ""
    i = r_len - 1
    WHILE i >= 0
        temp_str = temp_str + CHR$(48 + r_digits(i))
        i = i - 1
    WEND
    PRINT "999 * 999 = " + temp_str

    ' Division: 998001 / 999 = 999
    ' Using long division
    a_len = 6
    a_digits(0) = 1
    a_digits(1) = 0
    a_digits(2) = 0
    a_digits(3) = 8
    a_digits(4) = 9
    a_digits(5) = 9
    b_len = 3
    b_digits(0) = 9
    b_digits(1) = 9
    b_digits(2) = 9

    i = 0
    WHILE i < 200
        r_digits(i) = 0
        i = i + 1
    WEND

    ' Long division: compute quotient digit by digit
    remain = 0
    i = a_len - 1
    WHILE i >= 0
        remain = remain * 10 + a_digits(i)
        digit = 0
        WHILE remain >= 99  ' approximate: b value is 999
            IF b_len = 3 AND b_digits(2) = 9 AND b_digits(1) = 9 AND b_digits(0) = 9 THEN
                IF remain >= 999 THEN
                    remain = remain - 999
                    digit = digit + 1
                ELSE
                    i = -1
                END IF
            ELSE
                i = -1
            END IF
        WEND
        IF i >= 0 THEN
            r_digits(i) = digit
        END IF
        i = i - 1
    WEND

    temp_str = ""
    i = a_len - 1
    WHILE i >= 0
        temp_str = temp_str + CHR$(48 + r_digits(i))
        i = i - 1
    WEND
    PRINT "998001 / 999 = " + temp_str + " remainder " + STR$(remain)

    ' 50-digit * 1-digit
    i = 0
    WHILE i < 100
        a_digits(i) = 0
        i = i + 1
    WEND
    a_len = 50
    i = 0
    WHILE i < 50
        a_digits(i) = 1
        i = i + 1
    WEND
    b_len = 1
    b_digits(0) = 3

    i = 0
    WHILE i < 200
        r_digits(i) = 0
        i = i + 1
    WEND

    carry = 0
    i = 0
    WHILE i < a_len
        product = a_digits(i) * b_digits(0) + carry
        r_digits(i) = product MOD 10
        carry = product / 10
        i = i + 1
    WEND
    IF carry > 0 THEN
        r_digits(i) = carry
        r_len = i + 1
    ELSE
        r_len = i
    END IF

    temp_str = STR$(r_len)
    PRINT "50-digit number * 3: result has " + temp_str + " digits"

    ' Power: 2^10 = 1024
    i = 0
    WHILE i < 100
        a_digits(i) = 0
        i = i + 1
    WEND
    a_len = 1
    a_digits(0) = 2
    k = 1
    WHILE k < 10
        carry = 0
        i = 0
        WHILE i < a_len
            product = a_digits(i) * 2 + carry
            a_digits(i) = product MOD 10
            carry = product / 10
            i = i + 1
        WEND
        IF carry > 0 THEN
            a_digits(i) = carry
            a_len = a_len + 1
        END IF
        k = k + 1
    WEND

    temp_str = ""
    i = a_len - 1
    WHILE i >= 0
        temp_str = temp_str + CHR$(48 + a_digits(i))
        i = i - 1
    WEND
    PRINT "2^10 = " + temp_str

    PRINT ""
    PRINT "Big integer mul/div demo complete."

    FUNCTION = 0
END FUNCTION
