Russ Cox | 57eb06f | 2012-02-16 23:51:04 -0500 | [diff] [blame] | 1 | // run |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 2 | |
| 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 Pike | 19bab1d | 2012-02-24 10:30:39 +1100 | [diff] [blame] | 7 | // Test that heavy recursion works. Simple torture test for |
| 8 | // segmented stacks: do math in unary by recursion. |
| 9 | |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 10 | package main |
| 11 | |
Robert Griesemer | 1dd8840 | 2010-08-06 15:07:54 -0700 | [diff] [blame] | 12 | type Number *Number |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 13 | |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 14 | // ------------------------------------- |
| 15 | // Peano primitives |
| 16 | |
| 17 | func zero() *Number { |
Russ Cox | 00f9f0c | 2010-03-30 10:34:57 -0700 | [diff] [blame] | 18 | return nil |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 19 | } |
| 20 | |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 21 | func is_zero(x *Number) bool { |
Russ Cox | 00f9f0c | 2010-03-30 10:34:57 -0700 | [diff] [blame] | 22 | return x == nil |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 23 | } |
| 24 | |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 25 | func add1(x *Number) *Number { |
Russ Cox | 00f9f0c | 2010-03-30 10:34:57 -0700 | [diff] [blame] | 26 | e := new(Number) |
Robert Griesemer | 1dd8840 | 2010-08-06 15:07:54 -0700 | [diff] [blame] | 27 | *e = x |
Russ Cox | 00f9f0c | 2010-03-30 10:34:57 -0700 | [diff] [blame] | 28 | return e |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 29 | } |
| 30 | |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 31 | func sub1(x *Number) *Number { |
Robert Griesemer | 1dd8840 | 2010-08-06 15:07:54 -0700 | [diff] [blame] | 32 | return *x |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 33 | } |
| 34 | |
Russ Cox | 00f9f0c | 2010-03-30 10:34:57 -0700 | [diff] [blame] | 35 | func add(x, y *Number) *Number { |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 36 | if is_zero(y) { |
Russ Cox | 00f9f0c | 2010-03-30 10:34:57 -0700 | [diff] [blame] | 37 | return x |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 38 | } |
| 39 | |
Russ Cox | 00f9f0c | 2010-03-30 10:34:57 -0700 | [diff] [blame] | 40 | return add(add1(x), sub1(y)) |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 41 | } |
| 42 | |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 43 | func mul(x, y *Number) *Number { |
Russ Cox | 00f9f0c | 2010-03-30 10:34:57 -0700 | [diff] [blame] | 44 | if is_zero(x) || is_zero(y) { |
| 45 | return zero() |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 46 | } |
| 47 | |
Russ Cox | 00f9f0c | 2010-03-30 10:34:57 -0700 | [diff] [blame] | 48 | return add(mul(x, sub1(y)), x) |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 49 | } |
| 50 | |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 51 | func fact(n *Number) *Number { |
| 52 | if is_zero(n) { |
Russ Cox | 00f9f0c | 2010-03-30 10:34:57 -0700 | [diff] [blame] | 53 | return add1(zero()) |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 54 | } |
| 55 | |
Russ Cox | 00f9f0c | 2010-03-30 10:34:57 -0700 | [diff] [blame] | 56 | return mul(fact(sub1(n)), n) |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 57 | } |
| 58 | |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 59 | // ------------------------------------- |
| 60 | // Helpers to generate/count Peano integers |
| 61 | |
| 62 | func gen(n int) *Number { |
| 63 | if n > 0 { |
Russ Cox | 00f9f0c | 2010-03-30 10:34:57 -0700 | [diff] [blame] | 64 | return add1(gen(n - 1)) |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 65 | } |
| 66 | |
Russ Cox | 00f9f0c | 2010-03-30 10:34:57 -0700 | [diff] [blame] | 67 | return zero() |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 68 | } |
| 69 | |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 70 | func count(x *Number) int { |
| 71 | if is_zero(x) { |
Russ Cox | 00f9f0c | 2010-03-30 10:34:57 -0700 | [diff] [blame] | 72 | return 0 |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 73 | } |
| 74 | |
Russ Cox | 00f9f0c | 2010-03-30 10:34:57 -0700 | [diff] [blame] | 75 | return count(sub1(x)) + 1 |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 76 | } |
| 77 | |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 78 | func check(x *Number, expected int) { |
Russ Cox | 00f9f0c | 2010-03-30 10:34:57 -0700 | [diff] [blame] | 79 | var c = count(x) |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 80 | if c != expected { |
Russ Cox | 00f9f0c | 2010-03-30 10:34:57 -0700 | [diff] [blame] | 81 | print("error: found ", c, "; expected ", expected, "\n") |
| 82 | panic("fail") |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 83 | } |
| 84 | } |
| 85 | |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 86 | // ------------------------------------- |
| 87 | // Test basic functionality |
| 88 | |
Robert Griesemer | 1dd8840 | 2010-08-06 15:07:54 -0700 | [diff] [blame] | 89 | func init() { |
Russ Cox | 00f9f0c | 2010-03-30 10:34:57 -0700 | [diff] [blame] | 90 | check(zero(), 0) |
| 91 | check(add1(zero()), 1) |
| 92 | check(gen(10), 10) |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 93 | |
Russ Cox | 00f9f0c | 2010-03-30 10:34:57 -0700 | [diff] [blame] | 94 | check(add(gen(3), zero()), 3) |
| 95 | check(add(zero(), gen(4)), 4) |
| 96 | check(add(gen(3), gen(4)), 7) |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 97 | |
Russ Cox | 00f9f0c | 2010-03-30 10:34:57 -0700 | [diff] [blame] | 98 | 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 Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 104 | |
Russ Cox | 00f9f0c | 2010-03-30 10:34:57 -0700 | [diff] [blame] | 105 | check(fact(zero()), 1) |
| 106 | check(fact(add1(zero())), 1) |
| 107 | check(fact(gen(5)), 120) |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 108 | } |
| 109 | |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 110 | // ------------------------------------- |
| 111 | // Factorial |
| 112 | |
Ian Lance Taylor | f203093 | 2012-01-18 14:31:31 -0800 | [diff] [blame] | 113 | var results = [...]int{ |
| 114 | 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, |
| 115 | 39916800, 479001600, |
| 116 | } |
| 117 | |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 118 | func main() { |
Russ Cox | ebd27d6 | 2009-10-09 11:18:32 -0700 | [diff] [blame] | 119 | for i := 0; i <= 9; i++ { |
Ian Lance Taylor | f203093 | 2012-01-18 14:31:31 -0800 | [diff] [blame] | 120 | if f := count(fact(gen(i))); f != results[i] { |
| 121 | println("FAIL:", i, "!:", f, "!=", results[i]) |
| 122 | panic(0) |
| 123 | } |
Rob Pike | d0cf215 | 2008-07-12 13:20:21 -0700 | [diff] [blame] | 124 | } |
| 125 | } |