' Performance macros: MIN, MAX, ABS, CLAMP via MACROFUNCTION
#COMPILE EXE
#DIM ALL

MACROFUNCTION Min(a, b) = IIF((a) < (b), (a), (b))
MACROFUNCTION Max(a, b) = IIF((a) > (b), (a), (b))
MACROFUNCTION Abs(x) = IIF((x) >= 0, (x), -(x))
MACROFUNCTION Clamp(x, lo, hi) = Min(Max((x), (lo)), (hi))
MACROFUNCTION Between(x, lo, hi) = ((x) >= (lo) AND (x) <= (hi))
MACROFUNCTION Lerp(a, b, t) = (a) + ((b) - (a)) * (t)
MACROFUNCTION Square(x) = (x) * (x)
MACROFUNCTION Cube(x) = (x) * (x) * (x)
MACROFUNCTION Sign(x) = IIF((x) > 0, 1, IIF((x) < 0, -1, 0))
MACROFUNCTION IsEven(x) = ((x) MOD 2 = 0)
MACROFUNCTION IsOdd(x) = ((x) MOD 2 <> 0)
MACROFUNCTION Percent(x, total) = ((x) * 100) / (total)
MACROFUNCTION SafeDiv(x, y) = IIF((y) <> 0, (x) / (y), 0)
MACROFUNCTION Wrap(x, lo, hi) = IIF((x) < (lo), (hi) - ((lo) - (x) - 1), IIF((x) > (hi), (lo) + ((x) - (hi) - 1), (x)))
MACROFUNCTION PingPong(x, max) = IIF(((x) MOD (2 * (max))) < (max), (x) MOD (max), (2 * (max)) - ((x) MOD (2 * (max))))

SUB TestMinMax()
    PRINT "--- MIN/MAX tests ---"
    PRINT "Min(10, 20) = " + STR$(Min(10, 20))
    PRINT "Min(50, 5) = " + STR$(Min(50, 5))
    PRINT "Max(10, 20) = " + STR$(Max(10, 20))
    PRINT "Max(50, 5) = " + STR$(Max(50, 5))
    PRINT "Min(Max(5, 10), 20) = " + STR$(Min(Max(5, 10), 20))
END SUB

SUB TestAbs()
    PRINT "--- ABS tests ---"
    PRINT "Abs(42) = " + STR$(Abs(42))
    PRINT "Abs(-42) = " + STR$(Abs(-42))
    PRINT "Abs(0) = " + STR$(Abs(0))
    PRINT "Abs(-100) = " + STR$(Abs(-100))
END SUB

SUB TestClamp()
    PRINT "--- CLAMP tests ---"
    PRINT "Clamp(5, 0, 10) = " + STR$(Clamp(5, 0, 10))
    PRINT "Clamp(-5, 0, 10) = " + STR$(Clamp(-5, 0, 10))
    PRINT "Clamp(15, 0, 10) = " + STR$(Clamp(15, 0, 10))
    PRINT "Clamp(7, 1, 6) = " + STR$(Clamp(7, 1, 6))
END SUB

SUB TestNumberChecks()
    PRINT "--- Number property tests ---"
    PRINT "IsEven(10) = " + STR$(IsEven(10))
    PRINT "IsEven(7) = " + STR$(IsEven(7))
    PRINT "IsOdd(10) = " + STR$(IsOdd(10))
    PRINT "IsOdd(7) = " + STR$(IsOdd(7))
    PRINT "Sign(42) = " + STR$(Sign(42))
    PRINT "Sign(-42) = " + STR$(Sign(-42))
    PRINT "Sign(0) = " + STR$(Sign(0))
END SUB

SUB TestBounds()
    PRINT "--- Bounds tests ---"
    PRINT "Between(5, 0, 10) = " + STR$(Between(5, 0, 10))
    PRINT "Between(15, 0, 10) = " + STR$(Between(15, 0, 10))
    PRINT "Between(0, 0, 10) = " + STR$(Between(0, 0, 10))

    PRINT "Wrap(12, 0, 10) = " + STR$(Wrap(12, 0, 10))
    PRINT "Wrap(-2, 0, 10) = " + STR$(Wrap(-2, 0, 10))
    PRINT "Wrap(5, 0, 10) = " + STR$(Wrap(5, 0, 10))
END SUB

SUB TestMath()
    PRINT "--- Math macro tests ---"
    PRINT "Square(7) = " + STR$(Square(7))
    PRINT "Cube(4) = " + STR$(Cube(4))
    PRINT "Percent(25, 200) = " + STR$(Percent(25, 200))
    PRINT "SafeDiv(10, 3) = " + STR$(SafeDiv(10, 3))
    PRINT "SafeDiv(10, 0) = " + STR$(SafeDiv(10, 0))
END SUB

SUB TestAdvanced()
    PRINT "--- Advanced macro tests ---"
    PRINT "Lerp(0, 100, 0.5) = " + STR$(Lerp(0, 100, 0.5))
    PRINT "PingPong(0, 5) = " + STR$(PingPong(0, 5))
    PRINT "PingPong(3, 5) = " + STR$(PingPong(3, 5))
    PRINT "PingPong(5, 5) = " + STR$(PingPong(5, 5))
    PRINT "PingPong(8, 5) = " + STR$(PingPong(8, 5))
    PRINT "PingPong(10, 5) = " + STR$(PingPong(10, 5))
END SUB

FUNCTION RunAllTests() AS LONG
    TestMinMax()
    PRINT ""
    TestAbs()
    PRINT ""
    TestClamp()
    PRINT ""
    TestNumberChecks()
    PRINT ""
    TestBounds()
    PRINT ""
    TestMath()
    PRINT ""
    TestAdvanced()
    FUNCTION = 0
END FUNCTION

FUNCTION PBMAIN() AS LONG
    PRINT "=== Inline Expansion Macro Demo ==="
    PRINT ""
    RunAllTests()
    PRINT ""
    PRINT "=== End Inline Expansion Demo ==="
    FUNCTION = 0
END FUNCTION
