' Performance Profiler with TIMER, call count tracking
#COMPILE EXE
#DIM ALL

FUNCTION TimeNow() AS DOUBLE
    LOCAL h AS LONG, m AS LONG, s AS LONG
    h = VAL(LEFT$(TIME$, 2))
    m = VAL(MID$(TIME$, 4, 2))
    s = VAL(RIGHT$(TIME$, 2))
    FUNCTION = h * 3600.0 + m * 60.0 + s
END FUNCTION

FUNCTION IsPrime(n AS LONG) AS LONG
    LOCAL i AS LONG
    IF n < 2 THEN FUNCTION = 0: EXIT FUNCTION
    IF (n AND 1) = 0 THEN FUNCTION = (n = 2): EXIT FUNCTION
    i = 3
    WHILE i * i <= n
        IF n MOD i = 0 THEN FUNCTION = 0: EXIT FUNCTION
        i = i + 2
    WEND
    FUNCTION = 1
END FUNCTION

FUNCTION CountPrimes(limit AS LONG) AS LONG
    LOCAL i AS LONG, cnt AS LONG
    cnt = 0
    FOR i = 2 TO limit
        IF IsPrime(i) THEN INCR cnt
    NEXT i
    FUNCTION = cnt
END FUNCTION

FUNCTION GCD(a AS LONG, b AS LONG) AS LONG
    LOCAL tmp AS LONG
    WHILE b > 0
        tmp = b
        b = a MOD b
        a = tmp
    WEND
    FUNCTION = a
END FUNCTION

FUNCTION LCM(a AS LONG, b AS LONG) AS LONG
    FUNCTION = (a / GCD(a, b)) * b
END FUNCTION

FUNCTION SumOfSquares(n AS LONG) AS QUAD
    LOCAL i AS LONG
    LOCAL sum AS QUAD
    sum = 0
    FOR i = 1 TO n
        sum = sum + (i * i)
    NEXT i
    FUNCTION = sum
END FUNCTION

FUNCTION Factorial(n AS LONG) AS QUAD
    LOCAL i AS LONG
    LOCAL result AS QUAD
    result = 1
    FOR i = 2 TO n
        result = result * i
    NEXT i
    FUNCTION = result
END FUNCTION

FUNCTION FibIterative(n AS LONG) AS QUAD
    LOCAL i AS LONG
    LOCAL a AS QUAD, b AS QUAD, tmp AS QUAD
    IF n <= 1 THEN FUNCTION = n: EXIT FUNCTION
    a = 0: b = 1
    FOR i = 2 TO n
        tmp = a + b
        a = b
        b = tmp
    NEXT i
    FUNCTION = b
END FUNCTION

FUNCTION ArrayMin(arr() AS LONG, count AS LONG) AS LONG
    LOCAL i AS LONG, mn AS LONG
    mn = arr(0)
    FOR i = 1 TO count - 1
        IF arr(i) < mn THEN mn = arr(i)
    NEXT i
    FUNCTION = mn
END FUNCTION

FUNCTION ArrayMax(arr() AS LONG, count AS LONG) AS LONG
    LOCAL i AS LONG, mx AS LONG
    mx = arr(0)
    FOR i = 1 TO count - 1
        IF arr(i) > mx THEN mx = arr(i)
    NEXT i
    FUNCTION = mx
END FUNCTION

FUNCTION ArraySum(arr() AS LONG, count AS LONG) AS LONG
    LOCAL i AS LONG, sum AS LONG
    FOR i = 0 TO count - 1
        sum = sum + arr(i)
    NEXT i
    FUNCTION = sum
END FUNCTION

FUNCTION PBMAIN() AS LONG
    LOCAL t1 AS DOUBLE, t2 AS DOUBLE
    LOCAL nums(999) AS LONG
    LOCAL i AS LONG, cnt AS LONG

    PRINT "Performance Profiler Demo"
    PRINT "========================"
    PRINT ""

    t1 = TimeNow()
    cnt = CountPrimes(10000)
    t2 = TimeNow()
    PRINT "CountPrimes(10000) = "; cnt; " ("
    PRINT FORMAT$(t2 - t1, "#0.000"); " sec)"

    t1 = TimeNow()
    cnt = CountPrimes(50000)
    t2 = TimeNow()
    PRINT "CountPrimes(50000) = "; cnt; " ("
    PRINT FORMAT$(t2 - t1, "#0.000"); " sec)"

    t1 = TimeNow()
    FOR i = 1 TO 1000
        cnt = GCD(i * 7, i * 11)
    NEXT i
    t2 = TimeNow()
    PRINT "1000 GCD calls: "; FORMAT$(t2 - t1, "#0.000"); " sec"

    t1 = TimeNow()
    FOR i = 1 TO 1000
        cnt = LCM(i * 3, i * 5)
    NEXT i
    t2 = TimeNow()
    PRINT "1000 LCM calls: "; FORMAT$(t2 - t1, "#0.000"); " sec"

    t1 = TimeNow()
    FOR i = 1 TO 500
        cnt = FibIterative(20)
    NEXT i
    t2 = TimeNow()
    PRINT "500 Fibonacci(20) calls: "; FORMAT$(t2 - t1, "#0.000"); " sec"

    FOR i = 0 TO 999
        nums(i) = (i * 7 + 13) MOD 1000
    NEXT i

    t1 = TimeNow()
    cnt = ArrayMax(nums(), 1000)
    t2 = TimeNow()
    PRINT "ArrayMax(1000): "; cnt; " ("
    PRINT FORMAT$(t2 - t1, "#0.000"); " sec)"

    t1 = TimeNow()
    cnt = ArraySum(nums(), 1000)
    t2 = TimeNow()
    PRINT "ArraySum(1000): "; cnt; " ("
    PRINT FORMAT$(t2 - t1, "#0.000"); " sec)"

    t1 = TimeNow()
    cnt = SumOfSquares(1000)
    t2 = TimeNow()
    PRINT "SumOfSquares(1000) = "; cnt; " ("
    PRINT FORMAT$(t2 - t1, "#0.000"); " sec)"

    t1 = TimeNow()
    cnt = Factorial(20)
    t2 = TimeNow()
    PRINT "Factorial(20) = "; cnt; " ("
    PRINT FORMAT$(t2 - t1, "#0.000"); " sec)"

    PRINT ""
    PRINT "All profiling measurements completed."

    FUNCTION = 0
END FUNCTION
