Super Code from Digital Knife Monkey Productions

Digital Knife Monkeys at Keyboards...Will Eventually Program Everything.

Some useful functions (requires QB64)

'*BitTwiddling.bas
' the calling convention is that if routines are called with -1 as NthBit% then the function is applied to the entire number
' otherwise, the function is applied to the NthBit% bit. the exception to this rule is SetNthBit(), where -1 toggles a bit in a number
'in order to apply these functions to a number, the functions need to be applied as such:
_DEFINE A-Z AS DOUBLE
PRINT CGMod(251, 16)
PRINT CGLogBase$(255, 2)
PRINT CGPrime(1001001, 1)
PRINT USING "#.#################"; (1 + 1) / 10
PRINT USING "#.#################"; .1 + .1
CGPrintNumber 123456789.12345678, 15, 7, 12, 17
PRINT Bin2Dec$(Dec2Bin$(123456789.12345678))
PRINT Bin2Dec$(Dec2Bin$(-123456789.12345678))
PRINT Bin2Dec$("-100101010101.1101010101")
PRINT Radian2Degree#(ATn2#(CGNPi#(-3 / 6) * SQR(1) * SQR(1)))
PRINT CGWrap#(8, 1) ' * if you wrap a line of a certain length around a circle of radius, this is where you end up in terms of radians on that circle
PRINT CGHexToDec#("FFAAA"), CGHexToDec#("a"), CGHexToDec#("abcdef")
PRINT "["; CGXBase2YBase$("1000", 10, 16); "]"
FUNCTION BMask# (BMaska#)
TempA# = BMaska#
mask# = 1
DO
    mask# = CGSHL(mask#, 1) + 1
    TempA# = CGSHR(TempA#, 1)
LOOP UNTIL TempA# < 1
BMask# = mask#
END FUNCTION
FUNCTION CGIntDivR (a, mpart, div)
mpart = CGMod(a, div)
a = CGIntDiv(a, div)
END FUNCTION

FUNCTION CGIntDiv (a, b)
IF CGSign(b) = 0 THEN
    CGIntDiv = a
ELSE
    CGIntDiv = INT(a / b)
END IF
END FUNCTION

FUNCTION CGMod (a, b)
IF CGSign(b) = 0 THEN
    CGMod = 0
ELSE
    CGMod = a - (b * CGIntDiv(a, b))
END IF
END FUNCTION

FUNCTION CGSign (a)
IF a < 0 THEN
    CGSign = -1
ELSEIF a > 0 THEN
    CGSign = 1
ELSE
    CGSign = 0
END IF
END FUNCTION

FUNCTION CGWrapNumAround (a, add, min, max)
CGWrapNumAround = CGMod(a + add, max - min) + min
EXIT FUNCTION
IF add > max - WrapNumAroundTmp THEN
    WrapNumAroundTmp = min - max + add + WrapNumAroundTmp
ELSEIF add < WrapNumAroundTmp - min THEN
    WrapNumAroundTmp = WrapNumAroundTmp + max - min + add
ELSE
    WrapNumAroundTmp = WrapNumAroundTmp + add
END IF
CGWrapNumAround = WrapNumAroundTmp
END FUNCTION

FUNCTION CGLimitRange (a, min, max)
IF a < min THEN
    CGLimitRange = min
ELSEIF a > max THEN
    CGLimitRange = max
ELSE
    CGLimitRange = a
END IF
END FUNCTION

FUNCTION CGLogBase$ (a, intbase)
mybase$ = LEFT$("0123456789", intbase)
IF intbase > 10 THEN
    TmpIntBase = intbase
    AccumbaseC% = 0
    WHILE TmpIntBase > 10
        mybase$ = mybase$ + CHR$(ASC("A") + AccumbaseC%)
        AccumbaseC% = AccumbaseC% + 1
        TmpIntBase = intbase - AccumbaseC%
    WEND
END IF
CGLogBaseTmp = a
CGL$ = ""
DO
    remainder = CGMod(CGLogBaseTmp, intbase)
    CGL$ = MID$(mybase$, remainder + 1, 1) + CGL$
    CGLogBaseTmp = (CGLogBaseTmp - remainder) / intbase
LOOP UNTIL CGSign(CGLogBaseTmp) = 0
CGLogBase$ = CGL$
END FUNCTION

FUNCTION CGSetNthBit (a, NthBit%, fun%)
IF fun% = 0 THEN '* turn off a bit in a number
    IF CGAnd(a, CGSHL(2, NthBit%), NthBit%) THEN
        SetNthBit = a - CGSHL(2, NthBit%)
    END IF
ELSEIF fun% = 1 THEN '* set a bit in a number
    CGSetNthBit = a OR CGSHL(2, NthBit% - 1)
ELSEIF fun% = -1 THEN '* toggle a bit in a number (ie, if it is on, turn it off, otherwise turn it on
    IF CGAnd(a, CGSHL(2, NthBit%), NthBit%) THEN
        CGSetNthBit = SetNthBit(a, NthBit%, 0)
    ELSE
        CGSetNthBit = SetNthBit(a, NthBit%, 1)
    END IF
END IF
END FUNCTION

FUNCTION CGNand (a, b, NthBit%)
IF NthBit% = -1 THEN
    IF a THEN
        IF b THEN
            CGNand = 0
        ELSE
            CGNand = 1
        END IF
    ELSE
        CGNand = 1
    END IF
ELSE
    IF CGAnd(a, CGSHL(2, NthBit%), NthBit%) THEN
        IF CGAnd(b, CGSHL(2, NthBit%), NthBit%) THEN
            CGNand = 0
        ELSE
            CGNand = 1
        END IF
    ELSE
        CGNand = 0
    END IF
END IF
END FUNCTION

FUNCTION CGOr (a, b, NthBit%)
IF NthBit% = -1 THEN
    IF a THEN
        CGOr = 1
    ELSEIF b THEN
        CGOr = 1
    ELSE
        CGOr = 0
    END IF
ELSE
    IF CGAnd(a, CGSHL(2, NthBit%), NthBit%) THEN
        CGOr = 1
    ELSEIF CGAnd(b, CGSHL(2, NthBit%), NthBit%) THEN
        CGOr = 1
    ELSE
        CGOr = 0
    END IF
END IF
END FUNCTION

FUNCTION CGBNot (a, NthBit%)
IF NthBit% = -1 THEN
    IF a THEN
        CGBNot = 0
    ELSE
        CGBNot = 1
    END IF
ELSE
    IF CGAnd(a, 2, NthBit%) THEN
        CGNot = 0
    ELSE
        CGNot = 1
    END IF
END IF
END FUNCTION

FUNCTION CGAnd (a, b, NthBit%)
IF NthBit% = -1 THEN
    IF a THEN
        IF b THEN
            CGAnd = 1
        ELSE
            CGAnd = 0
        END IF
    ELSE
        CGAnd = 0
    END IF
ELSE
    IF a AND CGSHL(2, NthBit%) THEN
        IF b AND CGSHL(2, NthBit%) THEN
            CGAnd = 1
        ELSE
            CGAnd = 0
        END IF
    ELSE
        CGAnd = 0
    END IF
END IF
END FUNCTION

FUNCTION CGSHR (a, shift)
aTmp = a
n = 0
DO
    CGSHRTmp = CGAnd(aTmp, 2, 0)
    IF n < shift THEN
        IF CGSHRTmp THEN
            aTmp = (aTmp - CGSHRTmp) / 2
        ELSE
            aTmp = aTmp / 2
        END IF
        n = n + 1
    ELSE
        EXIT DO
    END IF
LOOP
CGSHR = aTmp
END FUNCTION

FUNCTION CGBitIsSet (a, nthbit%)
IF CGAnd(a, CGSHL(2, nthbit%), nthbit%) THEN
    CGBitIsSet = 1
ELSE
    CGBitIsSet = 0
END IF
END FUNCTION

FUNCTION CGSHL (a, shift)
CGSHL = a * (2 ^ shift)
END FUNCTION

FUNCTION CGBXOr (a, b, NthBit%) '* one or the other, but not neither or both
IF NthBit% = -1 THEN
    IF a THEN
        IF b THEN
            CGBXOr = 0 'not both
        ELSE
            CGBXOr = 1
        END IF
    ELSEIF b THEN
        CGBXOr = 1
    ELSE
        CGBXOr = 0
    END IF
ELSE
    IF CGBitIsSet(a, NthBit%) THEN
        IF CGBitIsSet(b, NthBit%) THEN
            CGBXOr = 0
        ELSE
            CGBXOr = 1
        END IF
    ELSEIF b THEN
        CGBXOr = 1
    ELSE
        CGBXOr = 0
    END IF
END IF
END FUNCTION

FUNCTION CGNor (a, b, NthBit%) 'not one or the other in other words NOT (a or b)
IF NthBit% = -1 THEN
    IF a THEN
        CGNor = 0
    ELSE
        IF b THEN
            CGNor = 0
        ELSE
            CGNor = 1
        END IF
    END IF
ELSE
    IF CGBitIsSet(a, NthBit%) THEN
        CGNor = 0
    ELSE
        IF CGBitIsSet(b, NthBit%) THEN
            CGNor = 0
        ELSE
            CGNor = 1
        END IF
    END IF
END IF
END FUNCTION

FUNCTION CGGetNthBit (a, nthbit%)
IF CGAnd(a, CGSHL(2, nthbit%), nthbit%) THEN
    CGGetNthBit = 1
ELSE
    CGGetNthBit = 0
END IF
END FUNCTION

FUNCTION CGOffsetBitIsSame (a, offset%, nthbit%) 'use 1 for following bit, -1 for previous bit
IF offset% + nthbit% < 0 THEN
    CGOffsetBitIsSame = 0
ELSE
    IF CGGetNthBit(a, nthbit%) = CGGetNthBit(a, nthbit% + offset%) THEN
        CGOffsetBitIsSame = 1
    ELSE
        CGOffsetBitIsSame = 0
    END IF
END IF
END FUNCTION

FUNCTION CGSurroundingBitsSame (a, offset%, nthbit%)
IF nthbit% > 0 THEN
    ToWhatValue% = CGGetNthBit(a, nthbit%)
    IF CGOffsetBitIsSame(a, offset%, nthbit%) THEN
        IF CGOffsetBitIsSame(a, -offset%, nthbit%) THEN
            CGSurroundingBitsSame = 1
        ELSE
            CGSurroundingBitsSame = 0
        END IF
    ELSE
        CGSurroundingBitsSame = 0
    END IF
ELSE
    CGSurroundingBitsSame = 0
END IF
END FUNCTION

SUB RLE (startx&, starty&, finishx&, finishy&, RLESameStartX&, RLESameStartY&, RLESameEndX&, RLESameEndY&)
m& = POINT(startx&, starty&)
RLESameStartX& = startx&
RLESameEndX& = RLESameStartX&
RLESameStartY& = starty&
RLESameEndY& = RLESameStartY&

DO
    IF POINT(RLESameEndX&, RLESameEndY&) = m& THEN
        IF RLESameEndX& > finishx& THEN
            RLESameEndX& = startx&
            IF RLESameEndY& > finishy& THEN
                EXIT DO
            ELSE
                RLESameEndY& = RLESameEndY& + 1
            END IF
        ELSE
            RLESameEndX& = RLESameEndX& + 1
        END IF
    ELSE
        EXIT DO
    END IF
LOOP
END FUNCTION

SUB MakePrecalcTrigTable (T(), NSteps)
TYPE TrigRec
    sine AS DOUBLE
    cosine AS DOUBLE
    tangent AS DOUBLE
END TYPE
REDIM Tb(0 TO NSteps) AS TrigRec
FOR MkTrigTable = 0 TO NSteps
    Tb(MkTrigTable).sine = SIN(CGNPi#(2) * MkTrigTable / NSteps)
    Tb(MkTrigTable).cosine = COS(CGNPi#(2) * MkTrigTable / NSteps)
    Tb(MkTrigTable).tangent = TAN(CGNPi#(2) * MkTrigTable / NSteps)
NEXT
END SUB

FUNCTION CGCompare (comparex, comparey)
IF comparex < comparey THEN
    CGCompare = -1
ELSEIF comparex > comparey THEN
    CGCompare = 1
ELSE
    CGCompare = 0
END IF
END FUNCTION

SUB CGSetSFOrder (SetSFOrderStart, SetSFOrderFinish, SetSFOrderxstart, SetSFOrderxfinish)
IF SetSFOrderStart > SetSFOrderFinish THEN
    SetSFOrderxstart = SetSFOrderFinish
    SetSFOrderxfinish = SetSFOrderStart
ELSE
    SetSFOrderxstart = SetSFOrderStart
    SetSFOrderxfinish = SetSFOrderFinish
END IF
END SUB

'**************** sum of range of elements in an array
FUNCTION CGSigmaArray (SigmaArray(), SigmaArraystart&, SigmaArrayfinish&)
CGSetSFOrder SigmaArraystart&, SigmaArrayfinish&, SigmaArrayXStart&, SigmaArrayXFinish&

SigmaArrayXStart& = CGLimitRange(SigmaArraystart&, LBOUND(SigmaArray), UBOUND(SigmaArray))
SigmaArrayXFinish& = CGLimitRange(SigmaArrayfinish&, LBOUND(SigmaArray), UBOUND(SigmaArray))

SigmaArraysum = SigmaArray(SigmaArrayXStart&)
FOR SigmaArrayi& = SigmaArrayXStart& + 1 TO SigmaArrayXFinish&
    SigmaArraysum = SigmaArraysum + SigmaArray(SigmaArrayi&)
NEXT
CGSigmaArray = SigmaArraysum
END FUNCTION

FUNCTION CGStandardDeviation (StandardDeviationArray(), StandardDeviationstart&, StandardDeviationfinish&)
StandardDeviationMean = CGSigmaArray(StandardDeviationArray(), StandardDeviationstart&, StandardDeviationfinish&) / StatisticalN(StandardDeviationstart&, StandardDeviationfinish&)
StandardDeviationsdsum = 0
FOR StandardDeviationi& = StandardDeviationstart& TO StandardDeviationfinish&
    StandardDeviationsdsum = StandardDeviationsdsum + ABS(StandardDeviationMean - StandardDeviationArray(StandardDeviationi&))
NEXT
CGStandardDeviation = StandardDeviationsdsum / StatisticalN(StandardDeviationstart&, StandardDeviationfinish&)
END FUNCTION

FUNCTION StatisticalN (StatisticalNa, StatisticalNb)
IF StatisticalNa > StatisticalNb THEN
    StatisticalN = (StatisticalNa - StatisticalNb) + 1
ELSE
    StatisticalN = (StatisticalNb - StatisticalNa) + 1
END IF
END FUNCTION

SUB CGSort (SortArray(), Sortstart&, Sortfinish&, Sortorder%, level%)
IF Sortfinish& - Sortstart& = 1 THEN
    IF CGCompare(SortArray(Sortstart&), SortArray(Sortfinish&)) <> Sortorder% THEN
        SWAP SortArray(CGSORTSTART&), SortArray(Sortfinish&)
    END IF
ELSEIF Sortfinish& - Sortstart& > 1 THEN
    IF level% > 2 * LOG(Sortfinish& - Sortstart& + 1) THEN
        CGMergeSort SortArray(), Sortstart&, Sortfinish&, Sortorder%
    ELSE
        Sorti& = Sortstart&
        Sortj& = Sortfinish&
        IF CGRandNumInRange(0, 1, 0) < 1 / 2 THEN
            SortMedian = SortArray(CGArithmeticMean(Sorti&, Sortj&))
        ELSE
            SortMedian = CGRandNumInRange(Sorti&, Sortj&, -1)
        END IF
        DO
            WHILE CGCompare(SortArray(Sorti&), Median) = Sortorder%
                Sorti& = Sorti& + 1
            WEND
            WHILE CGCompare(Median, SortArray(Sortj&)) = Sortorder%
                Sortj& = Sortj& - 1
            WEND
            IF Sorti& <= Sortj& THEN
                IF CGCompare(SortArray(Sorti&), SortArray(Sortj&)) <> Sortorder% THEN
                    SWAP SortArray(Sorti&), SortArray(Sortj&)
                END IF
                Sorti& = Sorti& + 1
                Sortj& = Sortj& - 1
            END IF
        LOOP UNTIL Sorti& > Sortj&
        CGSort SortArray(), Sorti&, Sortfinish&, Sortorder%, level% + 1
        CGSort SortArray(), Sortstart&, Sortj&, Sortorder%, level% + 1
    END IF
END IF
level% = level% - 1
END SUB

FUNCTION CGArithmeticMean (ArithmeticMeana, ArithmeticMeanb)
CGArithmeticMean = ArithmeticMeana + (ArithmeticMeanb - ArithmeticMeana) \ 2
END FUNCTION

SUB CGMergeSort (MergeSortArray(), start&, finish&, SortOrder%)

END SUB

'* with Direction% = 0, this becomes a primality test
'* if this returns a value < 0, Primea is not prime
FUNCTION CGPrime (Primea, Direction%)
IF CGMod(Primea, 2) THEN
    PrimeATmp = Primea
ELSE
    PrimeATmp = 2 * CGIntDiv(Primea, 2) + 1
END IF
Primediv = 1
DO
    Primediv = Primediv + 2
    IF Primediv > PrimeATmp / Primediv THEN
        EXIT DO
    ELSE
        IF CGMod(PrimeATmp, Primediv) = 0 THEN
            Primediv = 1
            IF Direction% = -1 THEN
                PrimeATmp = PrimeATmp - 2
            ELSEIF Directtion% = 1 THEN
                PrimeATmp = PrimeATmp + 2
            ELSE
                PrimeATmp = -PrimeATmp
            END IF
        END IF
    END IF
LOOP
CGPrime = PrimeATmp
END FUNCTION

SUB CGLoadPixArray (LoadPixArray(), xstartx&, xstarty&, xendx&, xendy&)
FOR LoadPixArrayY& = xstarty& TO xendy&
    FOR LoadPixArrayX& = xstartx& TO xendx&
        LoadPixArray(x&, y&) = POINT(LoadPixArrayX&, LoadPixArrayY&)
    NEXT
NEXT
END SUB

FUNCTION CGRandNumInRange (RandNumInRangeMin, RandNumInRangeMax, ConvertToInt%)

IF ConvertToInt% THEN
    CGRandNumInRange = INT(CGRandNumInRangeMin + RND * (CGRandNumInRangeMax - CGRandNumInRangeMin))
ELSE
    CGRandNumInRange = CGRandNumInRangeMin + RND * (CGRandNumInRangeMax - CGRandNumInRangeMin)
END IF
END FUNCTION
SUB CGAccurateMultiply (a#, b#, result#)
IntA# = INT(a#): FrcA# = a# - IntA#
IntB# = INT(b#): FrcB# = b# - IntB#
result# = (IntA# * IntB#) + (IntA# * FrcB# + IntB# + FrcA#) + FrcA# * FrcB#
END SUB

SUB InputString (yloc%, xloc%, a$, IStype$, issigned%, numtype$) '* n=number, a=alphabetic, an=alphanumeric, x=any
SELECT CASE numtype$
    CASE "b" '* _byte   s(-127,128)      u(0,255)
    CASE "i" '* integer s(-32768,32767), u(0,65535) - 2B
    CASE "l" '* single
    CASE "d" '* double
    CASE "f" '* _float
    CASE "_b" '* _bit, so only allow 1,0
    CASE "h" '* hexadecimal -- 0-9,A-F
END SELECT
IF INSTR(IStype$, "x") THEN
    ISFlags% = CGOr(ISFlags%, 1, -1)
    ISFlags% = CGOr(ISFlags%, 2, -1)
    ISFlags% = CGOr(ISFlags%, 4, -1)
ELSE
    IF INSTR(IStype$, "n") THEN
        ISFlags% = CGOr(ISFlags%, 1, -1)
    ELSE
        IF INSTR(IStype$, "a") THEN
            ISFlags% = CGOr(ISFlags%, 2, -1)
        END IF
    END IF
END IF

TmpA$ = a$
bt% = 0
DO
    m$ = INKEY$
    bt% = 0
    SELECT CASE m$
        CASE "0" TO "9"
            bt% = 1
            chkdbl% = -1
        CASE "."
            bt% = 1
            chkdbl% = -1
        CASE "-"
            bt% = 1
            chkdbl% = -1
        CASE "+"
            bt% = 1
        CASE "a" TO "z"
            bt% = 2
        CASE "A" TO "Z"
            bt% = 2
        CASE " "
            bt% = 4
        CASE CHR$(13)
            EXIT DO
        CASE CHR$(27)
            a$ = TmpA$
            EXIT DO
        CASE ELSE
            bt% = 8
    END SELECT
    IF chkdbl% THEN
        IF CGAnd(ISFlags%, 4, 3) THEN
            chkdbl% = 0
        ELSE
            IF INSTR(a$, m$) THEN
                bt% = 0
            END IF
            chkdbl% = 0
        END IF
    END IF
    IF CGAnd(bt%, ISFlags%, -1) THEN
        LOCATE locy%, locx%
        PRINT a$ = a$ + m$
    END IF
LOOP
END SUB

SUB CGPrintNumber (PrintNumberN#, intplaces%, decplaces%, locy%, locx%)
LOCATE locy%, locx%
intdisp$ = SPACE$(intplaces%)
decdisp$ = SPACE$(decplaces%)
CGIntDec PrintNumberN#, IntPrintNumber#, RemPrintNumber#
IF IntPrintNumber# < 0 THEN
    RSET intdisp$ = STR$(IntPrintNumber#)
ELSE
    RSET intdisp$ = MID$(STR$(IntPrintNumber#), 2)
END IF
LSET decdisp$ = MID$(STR$(RemPrintNumber#), 2)
PRINT intdisp$; decdisp$
END SUB

SUB CGIntDec (a#, ipart#, dpart#)
ipart# = INT(a#)
dpart# = (a# - ipart#)
END FUNCTION

FUNCTION Dec2Bin$ (Dec2Bina#)
SignDec2BinA% = CGSign(Dec2Bina#)
CGIntDec ABS(Dec2Bina#), Dec2Binipart#, Dec2Bindpart#
Dec2BinBFrac$ = ""
DO
    x = INT(CGSHL(Dec2Bindpart#, 1))
    Dec2Bindpart# = CGSHL(Dec2Bindpart#, 1) - x
    Dec2BinBFrac$ = Dec2BinBFrac$ + CHR$(ASC("0") + x)
LOOP WHILE Dec2Bindpart# > 0
IF SignDec2BinA% = -1 THEN
    SignDec2BinA$ = "-"
ELSE
    SignDec2BinA$ = ""
END IF
IF Dec2BinBFrac$ > STRING$(LEN(Dec2BinBFrac$), "0") THEN
    Dec2Bin$ = SignDec2BinA$ + CGLogBase$(Dec2Binipart#, 2) + "." + Dec2BinBFrac$
ELSE
    Dec2Bin$ = SignDec2BinA$ + CGLogBase$(Dec2Binipart#, 2)
END IF
END FUNCTION

FUNCTION Bin2Dec$ (Bin2deca$)
Dec2BinInDot% = INSTR(Bin2deca$, ".")
inn% = INSTR(Bin2deca$, "-")
IF inn% THEN
    Bin2DecaTmp$ = MID$(Bin2deca$, inn% + 1)
    neg$ = "-"
ELSE
    Bin2DecaTmp$ = Bin2deca$
    neg$ = ""
END IF
Dec2BinInDot% = INSTR(Bin2DecaTmp$, ".")
IF Dec2BinInDot% THEN
    Integer$ = LEFT$(Bin2DecaTmp$, Dec2BinInDot% - 1)
    decimal$ = MID$(Bin2DecaTmp$, Dec2BinInDot% + 1)
ELSE
    Integer$ = Bin2DecaTmp$
    decimal$ = ""
END IF
IntSum# = 0
IntPlace% = 0
DO
    IF RIGHT$(Integer$, 1) = "1" THEN
        IntSum# = IntSum# + (CGSHL(2, IntPlace%)) / 2
    END IF
    Integer$ = LEFT$(Integer$, LEN(Integer$) - 1)
    IntPlace% = IntPlace% + 1
LOOP WHILE Integer$ > ""
IF Dec2BinInDot% THEN
    decsum# = 0
    DecPlace% = 1
    DO
        IF LEFT$(decimal$, 1) = "1" THEN
            decsum# = decsum# + CGSHR(2, DecPlace%)
        END IF
        decimal$ = MID$(decimal$, 2)
        DecPlace% = DecPlace% + 1
    LOOP WHILE decimal$ > ""
    Bin2Dec$ = neg$ + MID$(STR$(IntSum#), 2) + MID$(STR$(decsum#), 2)
ELSE
    Bin2Dec$ = neg$ + MID$(STR$(IntSum#), 2)
END IF
END FUNCTION

FUNCTION ATn2# (angle#)
Pi2# = CGNPi#(2)
Div2Pi# = angle# \ Pi2#
AngleRemainder# = angle# - (Div2Pi# * Pi2#)
IF AngleRemainder# < 0 THEN
    ATn2# = Pi2# + AngleRemainder#
ELSE
    ATn2# = AngleRemainder#
END IF
END FUNCTION

FUNCTION Radian2Degree# (angle#)
Radian2Degree# = 360 * (ATn2#(angle#) / CGNPi#(2))
END FUNCTION

FUNCTION CGNPi# (NPix#)
CGNPi# = NPix# * 3.1415926535897932386#
END FUNCTION

FUNCTION CGCircumference# (Circumferenceradius#)
CGCircumference# = CGNPi#(2) * Circumferenceradius#
END FUNCTION

FUNCTION CGWrap# (WrapLength#, Wrapradius#)
CGWrap# = CGNPi#(2) * CGMod(WrapLength#, CGCircumference#(Wrapradius#)) / CGCircumference#(Wrapradius#)
END FUNCTION

FUNCTION CGHexToDec# (a$)
Hexacc# = 0
FOR HexToDecI% = 1 TO LEN(a$)
    m$ = MID$(a$, LEN(a$) - HexToDecI% + 1, 1)
    multiplier = CGChar2Number%(UCASE$(m$)) '* a-f are not case-sensitive (in hexadecimal)
    Hexacc# = Hexacc# + multiplier * 16 ^ (HexToDecI% - 1)
NEXT
CGHexToDec# = Hexacc#
END FUNCTION

FUNCTION CGChar2Number% (a$)
SELECT CASE a$
    CASE "0" TO "9"
        CGChar2Number% = ASC(a$) - ASC("0")
    CASE "a" TO "z"
        CGChar2Number% = ASC(a$) - ASC("a") + ASC("Z") + 10
    CASE "A" TO "Z"
        CGChar2Number% = ASC(a$) - ASC("A") + 10
END SELECT
END FUNCTION

FUNCTION CGNumber2Char$ (a#)
SELECT CASE a#
    CASE 0 TO 9
        CGNumber2Char$ = CHR$(ASC("0") + a#)
    CASE 10 TO 35
        CGNumber2Char$ = CHR$(ASC("A") + a# - 10)
    CASE 36 TO 61
        CGNumber2Char$ = CHR$(ASC("a") + a# - 36)
END SELECT
END FUNCTION

FUNCTION CGXBase2YBase$ (a$, XBase%, YBase%)
acc# = 0
FOR CGXBase2YBasei% = 1 TO LEN(a$)
    acc# = acc# + CGChar2Number%(MID$(a$, LEN(a$) - CGXBase2YBasei% + 1, 1)) * XBase% ^ (CGXBase2YBasei% - 1)
NEXT
b$ = ""
DO
    remains# = (acc# - (YBase% * (acc# \ YBase%)))
    b$ = CGNumber2Char$(remains#) + b$
    acc# = (acc# - remains#) / YBase%
LOOP WHILE acc# > 0
CGXBase2YBase$ = b$
END FUNCTION

FUNCTION CGDistance# (Distancex#, Distancey#)
CGDistance# = SQR(Distancex# ^ 2 + Distancey# ^ 2)
END FUNCTION

FUNCTION CGATan2# (ATan2x#, ATan2y#)
IF ATan2y# = 0 THEN
    IF ATan2x# = 0 THEN
        CGATan2Tmp# = 0
    ELSE
        CGATan2Tmp# = 2 * ATN(ATan2y# / (CGDistance#(ATan2x#, ATan2y#) + ATan2x#))
    END IF
ELSE
    IF ATan2x# = 0 THEN
        CGATan2Tmp# = 2 * ATN((CGDistance#(ATan2x#, ATan2y#) - ATan2x#) / ATan2y#)
    ELSE
        CGATan2Tmp# = 2 * ATN((ATan2y# / (CGDistance#(ATan2x#, ATan2y#) + ATan2x#)))
    END IF
END IF
CGATan2# = CGATan2Tmp#
END FUNCTION