Summary Files Commits Branches @commit @diff @stats
path: root / catalan / math.a65
blob: 9662de702a9caf66728ce7a7673b06447ba50e6f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#ifndef CATALAN_MATH
#define CATALAN_MATH

#define starg(name, value) .(           :\
	pha		; push a     :\
	lda value	; a = value  :\
	sta name		; name = a   :\
	pla		; pop a      :\
.)

#define applya(subroutine, arg, value) .( :\
	starg(arg, value)                        :\
	jsr subroutine                           :\
.)

; a *= multa_arg
multa .(
	ora #0		; Update flags, so they're accurate with the accumulator value
	beq return	; if (a == 0) return a
	cmp #1		; if (a == 1)
	beq r_arg	;   return arg

	ldx arg	; x = arg
	cpx #0		; if (x == 0)
	beq r_zero	;   return 0
	cpx #1		; if (x == 1)
	beq return	;   return a

	dex		; --x  // accumulator already has the first value
	sta addend	; addend = a
loop	clc		; do  carry = 0
	adc addend	;     a += addend + carry
	dex		;     --x
	cpx #1		; while (x >= 1)
	bcs loop

return	ora #0		; Update flags, so they're accurate with the accumulator value
	rts

r_zero	lda #0
	rts

r_arg	lda arg
	rts

+multa_arg
arg		.byt 0
addend		.byt 0
.)

; a /= diva_arg
diva .(
	ora #0		; Update flags, so they're accurate with the accumulator value
	beq return	; if (a == 0) return a

	ldx arg		; x = arg
	cpx #0		; if (x == 0)
	beq r_zero	;   return 0
	cpx #1		; if (x == 1)
	beq return	;   return a

	ldx #0		; x = 0
loop	sec		; do  carry = 1
	sbc arg		;     a -= arg + !carry
	inx		;     ++x
	cmp arg		; while (a >= arg)
	bcs loop

return	txa
	rts

r_zero	lda #0
	rts

+diva_arg
arg		.byt 0
subtrahend	.byt 0
.)

; a %= moda_arg
moda .(
	ldx arg		; x = arg
	cpx #1		; if (x <= 1)
	bcc r_zero	;   return 0
	beq r_zero

	ora #0		; Update flags, so they're accurate with the accumulator value
	beq return	; if (a == 0) return a

	cmp arg		; if (a < arg)
	bcc return	;   return a
	ldx #0		; x = 0

loop	sec		; do  carry = 1
	sbc arg		;     a -= arg + !carry
	inx		;     ++x
	cmp arg		; while (a >= arg)
	bcs loop

return	rts

r_zero	lda #0
	rts

+moda_arg
arg		.byt 0
.)

#endif /* CATALAN_MATH */
// vim: noet ts=9 sw=0 lcs=tab\:\ \