<commit_before>; asmsyntax=apricos
; ===================================
; ==                               ==
; ==    ApricotOS Math Library     ==
; ==                               ==
; ==          Revision 1           ==
; ==                               ==
; ==  (C) 2017  <NAME>  ==
; ==                               ==
; ==                               ==
; ==  Provides routines for        ==
; ==  basic arithmetic.            ==
; ==                               ==
; ===================================
;
#name "libmath"
#segment 9 ; TODO: Pick a more appropriate segment number

#include "apricotosint.asm"
#include "osutil.asm"
#include "memutil.asm"
#include "portin.asm"

;
; ==============
; MACROS
; ==============
;


; Subtract two numbers
; reg1 - the first operand
; reg2 - the second operand
;
; Output:
; reg1 - the result of the subtraction
;
#macro SUB reg1 reg2 {
    ASET reg2
    NOT
    ADD 1
    SPUSH
    ASET reg1
    SPOP ADD
}


;
; ==============
; ROUTINES
; ==============
;

; Routine pointers
.nearptr MULT
.nearptr DIV
.nearptr ATOB
.nearptr HTOI

; An 8-bit random number generator based off the following:
; http://www.arklyffe.com/main/2010/08/29/xorshift-pseudorandom-number-generator/
; Be sure to seed the number generator at least once before calling this routine.
;
; Returns:
; $a10 - The next random number in the sequence
;
; Volatile registers:
; $a10
; $a11
;
RAND:
    ; Possible choises for a, b, and c:
    ; (1, 1, 2) (1, 1, 3) (1, 7, 3) (1, 7, 6) (1, 7, 7) (2, 1, 1)
    ; (2, 5, 5) (3, 1, 1) (3, 1, 5) (3, 5, 4) (3, 5, 5) (3, 5, 7)
    ; (3, 7, 1) (4, 5, 3) (5, 1, 3) (5, 3, 6) (5, 3, 7) (5, 5, 2)
    ; (5, 5, 3) (6, 3, 5) (6, 7, 1) (7, 3, 5) (7, 5, 3) (7, 7, 1)
    ;

    ; Load seed and perform shifts
    ASET 10
    LDI RAND_SEED
    SPUSH

    SHFl 3 ; a
    SPOP XOR
    SPUSH

    SHFr 5 ; b
    SPOP XOR
    SPUSH

    SHFl 4 ; c
    SPOP XOR

    ; Update the seed
    ST

    ASET 11
    OS_SYSCALL_RET

; Set the seed of the random number generator.
; $a8 - The seed to set
;
; Volatile registers:
; $a8
SET_RAND_SEED:
    ASET 8
    STI RAND_SEED
    OS_SYSCALL_RET

;
; ================
;    RAND DATA
; ================
;
RAND_SEED: .fill 0x01

; Multiply two numbers together.
; Both operands are treated as unsigned.
; $a8 - the first operand to multiply
; $a9 - the second operand to multiply
;
; Outputs:
; $a10 - the result
; $a11 - non-zero if an overflow occured, zero otherwise
;
; Volatile registers:
; $a9
; $a11
;
MULT:
    ; Zero the results
    ASET 10
    AND 0

    ASET 11
    AND 0

    ; Negate the second operand (to use it as a counter)
    ASET 9
    NOT
    ADD 1

    ; Continuously add the value that is on the stack
    ; to $a10 until the counter reaches 0<commit_msg>Added FASTMULT implementation<commit_after>; asmsyntax=apricos
; ===================================
; ==                               ==
; ==    ApricotOS Math Library     ==
; ==                               ==
; ==          Revision 1           ==
; ==                               ==
; ==  (C) 2017  <NAME>  ==
; ==                               ==
; ==                               ==
; ==  Provides routines for        ==
; ==  basic arithmetic.            ==
; ==                               ==
; ===================================
;
#name "libmath"
#segment 9 ; TODO: Pick a more appropriate segment number

#include "apricotosint.asm"
#include "osutil.asm"
#include "memutil.asm"
#include "portin.asm"

;
; ==============
; MACROS
; ==============
;


; Subtract two numbers
; reg1 - the first operand
; reg2 - the second operand
;
; Output:
; reg1 - the result of the subtraction
;
#macro SUB reg1 reg2 {
    ASET reg2
    NOT
    ADD 1
    SPUSH
    ASET reg1
    SPOP ADD
}


;
; ==============
; ROUTINES
; ==============
;

; Routine pointers
.nearptr MULT
.nearptr DIV
.nearptr ATOB
.nearptr HTOI

; An 8-bit random number generator based off the following:
; http://www.arklyffe.com/main/2010/08/29/xorshift-pseudorandom-number-generator/
; Be sure to seed the number generator at least once before calling this routine.
;
; Returns:
; $a10 - The next random number in the sequence
;
; Volatile registers:
; $a10
; $a11
;
RAND:
    ; Possible choises for a, b, and c:
    ; (1, 1, 2) (1, 1, 3) (1, 7, 3) (1, 7, 6) (1, 7, 7) (2, 1, 1)
    ; (2, 5, 5) (3, 1, 1) (3, 1, 5) (3, 5, 4) (3, 5, 5) (3, 5, 7)
    ; (3, 7, 1) (4, 5, 3) (5, 1, 3) (5, 3, 6) (5, 3, 7) (5, 5, 2)
    ; (5, 5, 3) (6, 3, 5) (6, 7, 1) (7, 3, 5) (7, 5, 3) (7, 7, 1)
    ;

    ; Load seed and perform shifts
    ASET 10
    LDI RAND_SEED
    SPUSH

    SHFl 3 ; a
    SPOP XOR
    SPUSH

    SHFr 5 ; b
    SPOP XOR
    SPUSH

    SHFl 4 ; c
    SPOP XOR

    ; Update the seed
    ST

    ASET 11
    OS_SYSCALL_RET

; Set the seed of the random number generator.
; $a8 - The seed to set
;
; Volatile registers:
; $a8
SET_RAND_SEED:
    ASET 8
    STI RAND_SEED
    OS_SYSCALL_RET

;
; ================
;    RAND DATA
; ================
;
RAND_SEED: .fill 0x01


; Fast multiplication of two numbers, but without overflow checks.
; Runtime of this function is O(k), where k is the position of the
; most significant bit in the second operand. For example, if we
; multiply 0010 by 0101, then k = 3.
; For this reason, the smaller operand should be placed in $a9, and
; the larger in $a8.
; Unlike regular MULT, this function does no overflow checks, so
; care must be taken with the input parameters.
; $a8 - the first operand to multiply
; $a9 - the second operand to multiply
;
; Returns:
; $a10 - The result
;
; Volatile registers:
; $a8
; $a9
; $a10
FASTMULT:
    ASET 10
    AND 0

    FASTMULT_LOOP_START:
        ASET 9
        BRz FASTMULT_LOOP_END

        SPUSH
        AND 0x01
        BRz FASTMULT_ADD_SKIP
        ASET 8
        SPUSH

        ASET 10
        SPOP ADD

        FASTMULT_ADD_SKIP:
        ASET 9
        SPOP

        SHFr 1
        ASET 8
        SHFl 1

        JMP FASTMULT_LOOP_START
    FASTMULT_LOOP_END:

    ASET 8
    OS_SYSCALL_RET

; Multiply two numbers together.
; Both operands are treated as unsigned.
; $a8 - the first operand to multiply
; $a9 - the second operand to multiply
;
; Outputs:
; $a10 - the result
; $a11 - non-zero if an overflow occured, zero otherwise
;
; Volatile registers:
; $a9
; $a11
;
MULT:
    ; Zero the results
    ASET 10
    AND 0

    ASET 11
    AND 0

    ; Negate the second operand (to use it as a counter)
    ASET 9
    NOT
    ADD 1

    ; Continuously add the value that is on the stack
    ; to $a10 until the counter reaches 0
{'fraction_non_alphanumeric': 0.1529214850882532, 'fraction_numerical': 0.04595252586731589, 'mean_word_length': 2.04164738546969, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5059542', 'n_tokens_mistral': 2621, 'n_tokens_neox': 2336, 'n_words': 808}