-
Notifications
You must be signed in to change notification settings - Fork 0
/
ArithmeticAndStacks.Rmd
182 lines (152 loc) · 8.14 KB
/
ArithmeticAndStacks.Rmd
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
---
title: "Arithmetic and Stacks"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{Arithmetic and Stacks}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(froth, quietly = TRUE)
```
## More Arithmetic
In the last section, we learned some basic arithmetic using `+` and `*`. However, `froth` incorporates a host of arithmetic expressions. Eagle-eyed readers may have spotted that we've only been working with commutative operations, meaning the order doesn't matter (`a+b = b+a`). What happens when we use non-commutative expressions, such as division or exponentiation?
When `froth` executes words, it always treats the top of the stack as the *last* argument to the expression. This means that, for something like `a b /`, `b` is on the top of the stack and the result is `a / b`. `froth` uses R for its mathematical operations, so you don't have to worry about things like converting between integers and doubles, or double vs. single length numbers.
The following mathematical operations are all built into `froth`:
- `/ ( a b -- n )`: division (`5 2 / => 2.5`)
- `%/% ( a b -- n)`: integer division (`5 2 %/% => 2`)
- `mod ( a b -- rem )`: remainder when dividing `a / b`
- `/mod ( a b -- rem quot )`: integer divides `a %/% b`, pushes the remainder and then the quotient
- `^ ( a b -- n )`: raises `a^b`
- `negate ( a -- n )`: negates `a`
- `abs ( a -- n )`: takes the absolute value of `a`
- `min ( a b -- min )`: pushes `min(a,b)`
- `max ( a b -- max )`: pushes `max(a,b)`
- `sqrt ( a -- root )`: pushes `sqrt(a)`
## Stack Operators
Unfortunately, there are some problems that just can't be solved with stacks and postfix...at least, not without more tools. Consider the equation `(a-b)/c`. In postfix, this would be `a b - c /`. Now, if we wanted to write a word with definition `( c a b -- d )` that applies the function `(a-b)/c`, you'd find that it isn't quite possible with the tools we have. Defining `: SOLUTION? - /` would instead apply `c / (a - b)`, which isn't quite right. What we need is a way to *swap* the top two values, so that we run `(a-b)/c`.
This is where stack operators come in handy. The operator we're looking for is the aptly named `SWAP ( a b -- b a )`. which swaps the first two elements of the stack. Using this, we can write our definition:
```
fr> : TRYTHIS ( c a b -- d ) - swap / ;
ok.
fr> 4 2 1 trythis .
0.25 ok.
```
`(2-1)/4 = 1/4 = 0.25`, so this works! Here are a couple other stack operators that are often useful:
- `SWAP ( a b -- b a )`: swap top two stack elements
- `DUP ( n -- n n )`: duplicate the top stack element
- `OVER ( a b -- a b a )`: duplicate the second element to the top of the stack
- `ROT ( a b c -- b c a )`: rotate the third item to the top
- `DROP ( n -- )`: discard the top element of the stack
- `.S ( -- )`: print out the contents of the stack
We also have a set of stack operators that work on *pairs* of numbers, but perform the same functions:
- `2SWAP ( a b c d -- c d a b )`: swap the top two pairs
- `2DUP ( a b -- a b a b )`: duplicate the top pair
- `2OVER ( p1 p2 -- p1 p2 p1 )`: duplicate the second pair (`p1`) to the top
- `2DROP ( a b -- )`: discard the top pair
## Two stacks?
`froth` actually has two stacks. The main one, the parameter stack, is what you'll spend the majority of your time working with. Whenever we "push to the stack", that's referring to the parameter stack.
However, `froth` also has a second stack called the Return Stack. It's possible for you to use this stack as a sort of "temporary space" to hold values while you process other things. It's very important to ensure you clear the values on this temporary stack before you finish processing! `froth` is much more forgiving than Forth on this point, but it's good to get in the practice of good Forth code.
- `>R ( n -- )`: moves the value on the parameter stack to the return stack
- `R> ( -- n )`: moves the value on the return stack to the parameter stack
- `R@ ( -- n )`: copies the value on the return stack to the parameter stack
This can sometimes be very useful. For instance, say we wanted to swap the second and third elements of the stack (that is, go from `2 3 1` to `3 2 1`). We can do this with:
```
fr> 2 3 1
ok.
fr> >R SWAP R>
ok.
fr> .s
[[1]]
[1] 1
[[2]]
[1] 2
[[3]]
[1] 3
[[4]]
NULL
ok.
```
*Fundamental Forth* gives an excellent example of using these operators: suppose we want to write a function `quadratic ( a b c x -- n )` that returns `ax^2 + bx + c`.
```
fr> : QUADRATIC ( a b c x -- n ) >r swap rot r@ * + r> * + ;
ok.
fr> 2 7 9 3 quadratic .
48 ok.
```
## Other Miscellaneous operators
For completeness, here are some other arithmetic operations:
- `1+ ( n1 -- n2 )`: adds 1
- `1- ( n1 -- n2 )`: subtracts 1
- `2+ ( n1 -- n2 )`: adds 2
- `2- ( n1 -- n2 )`: subtracts 2
- `2* ( n1 -- n2 )`: multiplies by 2
- `2/ ( n1 -- n2 )`: divides by 2
We also have some funky double operators:
- `*/ ( a b c -- n )`: pushes `(a*b) / c`
- `*/mod ( a b c -- rem quot )`: pushes the remainder and quotient of `(a*b) %/% c`
If you're coming from Forth, you may recognize these are operations using double-length values as intermediates for increased precision. However, since `froth` uses R internals for operations, there's no difference between single and double length values.
## Words in this chapter
- `/ ( a b -- n )`: division (`5 2 / => 2.5`)
- `%/% ( a b -- n)`: integer division (`5 2 %/% => 2`)
- `mod ( a b -- rem )`: remainder when dividing `a / b`
- `/mod ( a b -- rem quot )`: integer divides `a %/% b`, pushes the remainder and then the quotient
- `^ ( a b -- n )`: raises `a^b`
- `negate ( a -- n )`: negates `a`
- `abs ( a -- n )`: takes the absolute value of `a`
- `min ( a b -- min )`: pushes `min(a,b)`
- `max ( a b -- max )`: pushes `max(a,b)`
- `sqrt ( a -- root )`: pushes `sqrt(a)`
- `SWAP ( a b -- b a )`: swap top two stack elements
- `DUP ( n -- n n )`: duplicate the top stack element
- `OVER ( a b -- a b a )`: duplicate the second element to the top of the stack
- `ROT ( a b c -- b c a )`: rotate the third item to the top
- `DROP ( n -- )`: discard the top element of the stack
- `.S ( -- )`: print out the contents of the stack
- `2SWAP ( a b c d -- c d a b )`: swap the top two pairs
- `2DUP ( a b -- a b a b )`: duplicate the top pair
- `2OVER ( p1 p2 -- p1 p2 p1 )`: duplicate the second pair (`p1`) to the top
- `2DROP ( a b -- )`: discard the top pair
- `>R ( n -- )`: moves the value on the parameter stack to the return stack
- `R> ( -- n )`: moves the value on the return stack to the parameter stack
- `R@ ( -- n )`: copies the value on the return stack to the parameter stack
- `1+ ( n1 -- n2 )`: adds 1
- `1- ( n1 -- n2 )`: subtracts 1
- `2+ ( n1 -- n2 )`: adds 2
- `2- ( n1 -- n2 )`: subtracts 2
- `2* ( n1 -- n2 )`: multiplies by 2
- `2/ ( n1 -- n2 )`: divides by 2
- `*/ ( a b c -- n )`: pushes `(a*b) / c`
- `*/mod ( a b c -- rem quot )`: pushes the remainder and quotient of `(a*b) %/% c`
<div class="center">
<ul class="pagination pagination-lg">
<li class="page-item">
<a class="page-link" href="https://www.ahl27.com/froth/articles/FundamentalFroth.html">«</a>
</li>
<li class="page-item">
<a class="page-link" href="https://www.ahl27.com/froth/articles/FundamentalFroth.html">1</a>
</li>
<li class="page-item active">
<a class="page-link" href="https://www.ahl27.com/froth/articles/ArithmeticAndStacks.html">2</a>
</li>
<li class="page-item">
<a class="page-link" href="https://www.ahl27.com/froth/articles/Conditionals.html">3</a>
</li>
<li class="page-item">
<a class="page-link" href="https://www.ahl27.com/froth/articles/Loops.html">4</a>
</li>
<li class="page-item">
<a class="page-link" href="https://www.ahl27.com/froth/articles/Variables.html">5</a>
</li>
<li class="page-item">
<a class="page-link" href="https://www.ahl27.com/froth/articles/RInterface.html">6</a>
</li>
<li class="page-item">
<a class="page-link" href="https://www.ahl27.com/froth/articles/Glossary.html">7</a>
</li>
<li class="page-item">
<a class="page-link" href="https://www.ahl27.com/froth/articles/Conditionals.html">»</a>
</li>
</ul>
</div>