blob: 745f5153f6bcf7189af6864066ec597c12d0a8ea [file] [log] [blame]
Russ Cox57eb06f2012-02-16 23:51:04 -05001// run
Rob Piked0cf2152008-07-12 13:20:21 -07002
3// Copyright 2009 The Go Authors. All rights reserved.
4// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file.
6
Rob Pike19bab1d2012-02-24 10:30:39 +11007// Test that heavy recursion works. Simple torture test for
8// segmented stacks: do math in unary by recursion.
9
Rob Piked0cf2152008-07-12 13:20:21 -070010package main
11
Robert Griesemer1dd88402010-08-06 15:07:54 -070012type Number *Number
Rob Piked0cf2152008-07-12 13:20:21 -070013
Rob Piked0cf2152008-07-12 13:20:21 -070014// -------------------------------------
15// Peano primitives
16
17func zero() *Number {
Russ Cox00f9f0c2010-03-30 10:34:57 -070018 return nil
Rob Piked0cf2152008-07-12 13:20:21 -070019}
20
Rob Piked0cf2152008-07-12 13:20:21 -070021func is_zero(x *Number) bool {
Russ Cox00f9f0c2010-03-30 10:34:57 -070022 return x == nil
Rob Piked0cf2152008-07-12 13:20:21 -070023}
24
Rob Piked0cf2152008-07-12 13:20:21 -070025func add1(x *Number) *Number {
Russ Cox00f9f0c2010-03-30 10:34:57 -070026 e := new(Number)
Robert Griesemer1dd88402010-08-06 15:07:54 -070027 *e = x
Russ Cox00f9f0c2010-03-30 10:34:57 -070028 return e
Rob Piked0cf2152008-07-12 13:20:21 -070029}
30
Rob Piked0cf2152008-07-12 13:20:21 -070031func sub1(x *Number) *Number {
Robert Griesemer1dd88402010-08-06 15:07:54 -070032 return *x
Rob Piked0cf2152008-07-12 13:20:21 -070033}
34
Russ Cox00f9f0c2010-03-30 10:34:57 -070035func add(x, y *Number) *Number {
Rob Piked0cf2152008-07-12 13:20:21 -070036 if is_zero(y) {
Russ Cox00f9f0c2010-03-30 10:34:57 -070037 return x
Rob Piked0cf2152008-07-12 13:20:21 -070038 }
39
Russ Cox00f9f0c2010-03-30 10:34:57 -070040 return add(add1(x), sub1(y))
Rob Piked0cf2152008-07-12 13:20:21 -070041}
42
Rob Piked0cf2152008-07-12 13:20:21 -070043func mul(x, y *Number) *Number {
Russ Cox00f9f0c2010-03-30 10:34:57 -070044 if is_zero(x) || is_zero(y) {
45 return zero()
Rob Piked0cf2152008-07-12 13:20:21 -070046 }
47
Russ Cox00f9f0c2010-03-30 10:34:57 -070048 return add(mul(x, sub1(y)), x)
Rob Piked0cf2152008-07-12 13:20:21 -070049}
50
Rob Piked0cf2152008-07-12 13:20:21 -070051func fact(n *Number) *Number {
52 if is_zero(n) {
Russ Cox00f9f0c2010-03-30 10:34:57 -070053 return add1(zero())
Rob Piked0cf2152008-07-12 13:20:21 -070054 }
55
Russ Cox00f9f0c2010-03-30 10:34:57 -070056 return mul(fact(sub1(n)), n)
Rob Piked0cf2152008-07-12 13:20:21 -070057}
58
Rob Piked0cf2152008-07-12 13:20:21 -070059// -------------------------------------
60// Helpers to generate/count Peano integers
61
62func gen(n int) *Number {
63 if n > 0 {
Russ Cox00f9f0c2010-03-30 10:34:57 -070064 return add1(gen(n - 1))
Rob Piked0cf2152008-07-12 13:20:21 -070065 }
66
Russ Cox00f9f0c2010-03-30 10:34:57 -070067 return zero()
Rob Piked0cf2152008-07-12 13:20:21 -070068}
69
Rob Piked0cf2152008-07-12 13:20:21 -070070func count(x *Number) int {
71 if is_zero(x) {
Russ Cox00f9f0c2010-03-30 10:34:57 -070072 return 0
Rob Piked0cf2152008-07-12 13:20:21 -070073 }
74
Russ Cox00f9f0c2010-03-30 10:34:57 -070075 return count(sub1(x)) + 1
Rob Piked0cf2152008-07-12 13:20:21 -070076}
77
Rob Piked0cf2152008-07-12 13:20:21 -070078func check(x *Number, expected int) {
Russ Cox00f9f0c2010-03-30 10:34:57 -070079 var c = count(x)
Rob Piked0cf2152008-07-12 13:20:21 -070080 if c != expected {
Russ Cox00f9f0c2010-03-30 10:34:57 -070081 print("error: found ", c, "; expected ", expected, "\n")
82 panic("fail")
Rob Piked0cf2152008-07-12 13:20:21 -070083 }
84}
85
Rob Piked0cf2152008-07-12 13:20:21 -070086// -------------------------------------
87// Test basic functionality
88
Robert Griesemer1dd88402010-08-06 15:07:54 -070089func init() {
Russ Cox00f9f0c2010-03-30 10:34:57 -070090 check(zero(), 0)
91 check(add1(zero()), 1)
92 check(gen(10), 10)
Rob Piked0cf2152008-07-12 13:20:21 -070093
Russ Cox00f9f0c2010-03-30 10:34:57 -070094 check(add(gen(3), zero()), 3)
95 check(add(zero(), gen(4)), 4)
96 check(add(gen(3), gen(4)), 7)
Rob Piked0cf2152008-07-12 13:20:21 -070097
Russ Cox00f9f0c2010-03-30 10:34:57 -070098 check(mul(zero(), zero()), 0)
99 check(mul(gen(3), zero()), 0)
100 check(mul(zero(), gen(4)), 0)
101 check(mul(gen(3), add1(zero())), 3)
102 check(mul(add1(zero()), gen(4)), 4)
103 check(mul(gen(3), gen(4)), 12)
Rob Piked0cf2152008-07-12 13:20:21 -0700104
Russ Cox00f9f0c2010-03-30 10:34:57 -0700105 check(fact(zero()), 1)
106 check(fact(add1(zero())), 1)
107 check(fact(gen(5)), 120)
Rob Piked0cf2152008-07-12 13:20:21 -0700108}
109
Rob Piked0cf2152008-07-12 13:20:21 -0700110// -------------------------------------
111// Factorial
112
Ian Lance Taylorf2030932012-01-18 14:31:31 -0800113var results = [...]int{
114 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800,
115 39916800, 479001600,
116}
117
Rob Piked0cf2152008-07-12 13:20:21 -0700118func main() {
Russ Coxebd27d62009-10-09 11:18:32 -0700119 for i := 0; i <= 9; i++ {
Ian Lance Taylorf2030932012-01-18 14:31:31 -0800120 if f := count(fact(gen(i))); f != results[i] {
121 println("FAIL:", i, "!:", f, "!=", results[i])
122 panic(0)
123 }
Rob Piked0cf2152008-07-12 13:20:21 -0700124 }
125}