' Clamp Macros — value clamping, saturation, and range limiting
#COMPILE EXE
#DIM ALL

MACRO m_clamp(v, lo, hi) = IIF((v) < (lo), (lo), IIF((v) > (hi), (hi), (v)))
MACRO m_saturate(v) = IIF((v) < 0, 0, IIF((v) > 255, 255, (v)))
MACRO m_wrap(v, lo, hi) = IIF((v) < (lo), (hi) - ((lo) - (v) - 1) MOD ((hi) - (lo) + 1), (lo) + ((v) - (lo)) MOD ((hi) - (lo) + 1))
MACRO m_lerp(a, b, t) = (a) + ((b) - (a)) * (t) / 100
MACRO m_step(edge, v) = IIF((v) < (edge), 0, 1)

FUNCTION PBMAIN() AS LONG
    LOCAL i AS LONG
    LOCAL j AS LONG
    LOCAL val AS LONG
    LOCAL lo AS LONG
    LOCAL hi AS LONG
    LOCAL result AS LONG
    LOCAL arr(100) AS LONG
    LOCAL lineStr AS STRING
    LOCAL valStr AS STRING
    PRINT "============================================"
    PRINT "       CLAMP MACRO DEMONSTRATION"
    PRINT "============================================"
    PRINT ""
    PRINT "Clamping values to various ranges"
    PRINT ""
    FOR i = -5 TO 15
        val = i * 10
        lo = 10
        hi = 90
        result = m_clamp(val, lo, hi)
        PRINT " clamp(" + STR$(val) + ", " + STR$(lo) + ", " + STR$(hi) + ") = " + STR$(result)
    NEXT i
    PRINT ""
    PRINT "============================================"
    PRINT "       SATURATE MACRO (0-255 range)"
    PRINT "============================================"
    PRINT ""
    PRINT "Saturating values to byte range [0, 255]:"
    PRINT ""
    FOR i = -3 TO 10
        val = i * 40
        result = m_saturate(val)
        PRINT " saturate(" + STR$(val) + ") = " + STR$(result)
    NEXT i
    PRINT ""
    PRINT "============================================"
    PRINT "       WRAP MACRO (circular range)"
    PRINT "============================================"
    PRINT ""
    PRINT "Wrapping values in range [0, 9]:"
    PRINT ""
    FOR i = -5 TO 15
        val = i
        lo = 0
        hi = 9
        result = m_wrap(val, lo, hi)
        PRINT " wrap(" + STR$(val) + ", 0, 9) = " + STR$(result)
    NEXT i
    PRINT ""
    PRINT "Wrapping in range [5, 15]:"
    PRINT ""
    FOR i = -3 TO 10
        val = i * 3
        lo = 5
        hi = 15
        result = m_wrap(val, lo, hi)
        PRINT " wrap(" + STR$(val) + ", 5, 15) = " + STR$(result)
    NEXT i
    PRINT ""
    PRINT "============================================"
    PRINT "       LERP MACRO (Linear Interpolation)"
    PRINT "============================================"
    PRINT ""
    PRINT "Linear interpolation between 0 and 100:"
    PRINT ""
    FOR i = 0 TO 10
        val = i * 10
        result = m_lerp(0, 100, val)
        PRINT " lerp(0, 100, " + STR$(val) + "%) = " + STR$(result)
    NEXT i
    PRINT ""
    PRINT "Linear interpolation between 50 and 150:"
    PRINT ""
    FOR i = 0 TO 10
        val = i * 10
        result = m_lerp(50, 150, val)
        PRINT " lerp(50, 150, " + STR$(val) + "%) = " + STR$(result)
    NEXT i
    PRINT ""
    PRINT "============================================"
    PRINT "       STEP MACRO (threshold)"
    PRINT "============================================"
    PRINT ""
    PRINT "Step function with threshold 50:"
    PRINT ""
    FOR i = 0 TO 10
        val = i * 10
        result = m_step(50, val)
        PRINT " step(50, " + STR$(val) + ") = " + STR$(result)
    NEXT i
    PRINT ""
    PRINT "============================================"
    PRINT "       COMPOUND CLAMP OPERATIONS"
    PRINT "============================================"
    PRINT ""
    LOCAL rawValue AS LONG
    LOCAL clampedVal AS LONG
    LOCAL wrappedVal AS LONG
    LOCAL saturatedVal AS LONG
    PRINT "Applying multiple constraints:"
    PRINT ""
    FOR i = 0 TO 14
        rawValue = i * 25 - 50
        clampedVal = m_clamp(rawValue, 0, 200)
        wrappedVal = m_wrap(rawValue, 0, 23)
        saturatedVal = m_saturate(rawValue)
        lineStr = " raw=" + STR$(rawValue)
        lineStr = lineStr + " clamped=" + STR$(clampedVal)
        lineStr = lineStr + " wrapped=" + STR$(wrappedVal)
        lineStr = lineStr + " sat=" + STR$(saturatedVal)
        PRINT lineStr
    NEXT i
    PRINT ""
    PRINT "============================================"
    PRINT "       ARRAY CLAMPING"
    PRINT "============================================"
    PRINT ""
    FOR i = 0 TO 19
        arr(i) = (i * 17 + 5) MOD 200 - 50
    NEXT i
    PRINT "Original array values:"
    lineStr = ""
    FOR i = 0 TO 19
        valStr = STR$(arr(i))
        DO WHILE LEN(valStr) < 4
            valStr = " " + valStr
        LOOP
        lineStr = lineStr + valStr + " "
    NEXT i
    PRINT lineStr
    PRINT ""
    PRINT "After clamping to [0, 100]:"
    lineStr = ""
    FOR i = 0 TO 19
        result = m_clamp(arr(i), 0, 100)
        valStr = STR$(result)
        DO WHILE LEN(valStr) < 4
            valStr = " " + valStr
        LOOP
        lineStr = lineStr + valStr + " "
    NEXT i
    PRINT lineStr
    PRINT ""
    PRINT "============================================"
    PRINT "       NESTED MACRO COMBINATIONS"
    PRINT "============================================"
    PRINT ""
    LOCAL a AS LONG
    LOCAL b AS LONG
    LOCAL c AS LONG
    FOR i = 0 TO 9
        a = i * 15
        b = i * 10 + 20
        c = i * 8 + 40
        result = m_clamp(m_lerp(a, b, 50), 0, c)
        PRINT " clamp(lerp(" + STR$(a) + ", " + STR$(b) + ", 50), 0, " + STR$(c) + ") = " + STR$(result)
    NEXT i
    PRINT ""
    PRINT "============================================"
    PRINT "       VERIFICATION"
    PRINT "============================================"
    PRINT ""
    LOCAL testErrors AS LONG
    testErrors = 0
    FOR val = -10 TO 10
        result = m_clamp(val, -5, 5)
        IF val < -5 THEN
            IF result <> -5 THEN
                testErrors = testErrors + 1
            END IF
        ELSE
            IF val > 5 THEN
                IF result <> 5 THEN
                    testErrors = testErrors + 1
                END IF
            ELSE
                IF result <> val THEN
                    testErrors = testErrors + 1
                END IF
            END IF
        END IF
    NEXT val
    IF testErrors = 0 THEN
        PRINT "All clamp tests PASS"
    ELSE
        PRINT STR$(testErrors) + " clamp test(s) FAIL"
    END IF
    PRINT ""
    PRINT "Clamp macro demonstration complete"
    FUNCTION = 0
END FUNCTION
