Main Page | Recent changes | Edit this page | Page history

Printable version | Disclaimers

Not logged in
Log in | Help
 

Topics:SICP in other languages:Qi:Chapter 1

From CTMWiki

About SICP The following Qi code is derived from the examples provided in the book:
      "Structure and Interpretation of Computer Programs, Second Edition" by Harold Abelson and Gerald Jay Sussman with Julie Sussman.
      http://mitpress.mit.edu/sicp/

Table of contents

\* SICP Chapter #01 Examples in Qi *\


\* 1.1.1 The Elements of Programming - Expressions *\

486
(+ 137 349)
(- 1000 334)
(* 5 99)
(/ 10 5)
(+ 2.7 10)
(+ (+ 21 35) (+ 12 7))
(* (* 25 4) 12)
(+ (* 3 5) (- 10 6))
(+ (* 3 (+ (* 2 4) (+ 3 5))) (+ (- 10 7) 6))

\* 1.1.2 The Elements of Programming - Naming and the Environment *\

(set size 2)
(value size)
(* 5 (value size))
(set pi 3.14159)
(set radius 10)
(* (value pi) (* (value radius) (value radius)))
(set circumference (* 2 (* (value pi) (value radius))))
(value circumference)

\* 1.1.3 The Elements of Programming - Evaluating Combinations *\

(* (+ 2 (* 4 6))
   (+ 3 (+ 5 7)))

\* 1.1.4 The Elements of Programming - Compound Procedures *\

(define square
   { number --> number }
   X -> (* X X)
)
(square 21)
(square (+ 2 5))
(square (square 3))

(define sum-of-squares
   { number --> number --> number }
   X Y -> (+ (square X) (square Y))
)
(sum-of-squares 3 4)
(define f
   { number --> number }
   A -> (sum-of-squares (+ A 1) (* A 2))
)
(f 5)

\* 1.1.5 The Elements of Programming - The Substitution Model for Procedure Application *\

(f 5)
(sum-of-squares (+ 5 1) (* 5 2))
(+ (square 6) (square 10))
(+ (* 6 6) (* 10 10))
(+ 36 100)
(f 5)
(sum-of-squares (+ 5 1) (* 5 2))
(+ (square (+ 5 1)) (square (* 5 2)))

(+ (* (+ 5 1) (+ 5 1)) (* (* 5 2) (* 5 2)))
(+ (* 6 6) (* 10 10))
(+ 36 100)
136

\* 1.1.6 The Elements of Programming - Conditional Expressions and Predicates *\

(define abs
   { number --> number }
   X ->
      (if (> X 0)
          X
          (if (= X 0) X (- 0 X)))
)
(define abs
   { number --> number }
   X -> (if (< X 0) (- 0 X) X)
)
(set x 6)
(and (> (value x) 5) (< (value x) 10))
(define ge
   { number --> number }
   X Y -> (or (> X Y) (= X Y))
)
(define ge
   { number --> number }
   X Y -> (not (< X Y))
)

\* Exercise 1.1 *\
10
(+ 5 (+ 3 4))
(- 9 1)
(/ 6 2)
(+ (* 2 4) (- 4 6))
(set a 3)
(set b (+ (value a) 1))
(+ (+ (value a) (value b)) (* (value a) (value b)))
(= a b)
(if (and (> (value b) (value a))
         (< (value b) (* (value a) (value b))))
    (value b)
    (value a))
(if (= a 4)
    6
    (if (= b 4)
        (+ 6 (+ 7 a))
        25))
(+ 2 (if (> (value b) (value a)) (value b) (value a)))
(* (if (> (value a) (value b))
       (value a)
       (if (< (value a) (value b)) (value b) -1))
   (+ (value a) 1))


\* Exercise 1.2 *\
(/ (+ (+ 5 4) (- 2 (- 3 (+ 6 (/ 4 5)))))
   (* 3 (* (- 6 2) (- 2 7))))

\* Exercise 1.3 *\
(define three-n
   { number --> number --> number --> number }
   N1 N2 N3 ->
      (if (> N1 N2)
         (if (> N1 N3)
            (if (> N2 N3)
                (+ (* N1 N1) (* N2 N2))
                (+ (* N1 N1) (* N3 N3)))
            (+ (* N1 N1) (* N3 N3)))
         (if (> N2 N3)
            (if (> N1 N3)
                (+ (* N2 N2) (* N1 N1))
                (+ (* N2 N2) (* N3 N3)))
            (+ (* N2 N2) (* N3 N3))))
)

\* Exercise 1.4 *\
(define a-plus-abs-b
   { number --> number --> number }
   A B ->
      (if (> B 0)
         (+ A B)
         (- A B))
)

\* Exercise 1.5 *\
(define p
   () -> (p ())
)
(define test
   { number --> number --> number }
   X Y ->
   (if (= X 0) 0 Y)
)
\* commented out as this is in infinite loop
   (test 0 (p ()))  *\

\* 1.1.7 The Elements of Programming - Example: Square Roots by Newton's Method *\

(define square
   { number --> number }
   X -> (* X X)
)

(define good-enough?
   { number --> number --> number }
   Guess X -> (< (abs (- (square Guess) X)) 0.001)
)

(define average
   { number --> number --> number }
   X Y -> (/ (+ X Y) 2)
)

(define improve
   { number --> number --> number }
   Guess X -> (average Guess (/ X Guess))
)

(define sqrt-iter
   { number --> number --> number }
   Guess X ->
      (if (good-enough? Guess X)
         Guess
         (sqrt-iter (improve Guess X) X))
)

(define sqrtx
   { number --> number }
   X -> (sqrt-iter 1.0 X)
)

(sqrtx 9)
(sqrtx (+ 100 37))
(sqrtx (sqrtx (+ 2 (sqrtx 3))))
(square (sqrtx 1000))

\* Exercise 1.6 *\
(define new-if
   Predicate Then-Clause Else-Clause ->
      (if Predicate
         Then-Clause
         Else-Clause)
)
(new-if (= 2 3) 0 5)
(new-if (= 1 1) 0 5)
(define sqrt-iter
   { number --> number --> number }
   Guess X ->
      (new-if (good-enough? Guess X)
         Guess
         (sqrt-iter (improve Guess X) X))
)

\* from wadler paper *\
(define new-if
   true  X Y -> X
   false X Y -> Y
)

\* Exercse 1.7 *\
(define good-enough-gp?
   { number --> number --> number }
   Guess Prev -> (< (/ (abs (- Guess Prev)) Guess) 0.001)
)

(define sqrt-iter-gp
   { number --> number --> number }
   Guess Prev X ->
      (if (good-enough-gp? Guess Prev)
         Guess
         (sqrt-iter-gp (improve Guess X) Guess X))
)

(define sqrt-gp
   { number --> number }
   X -> (sqrt-iter-gp 4.0 1.0 X)
)

\* Exercise 1.8 *\
(define improve-cube
   { number --> number }
   Guess X ->
   (/ (+ (* 2 Guess) (/ X (* Guess Guess))) 3)
)

(define cube-iter
   { number --> number --> number }
   Guess Prev X ->
      (if (good-enough-gp? Guess Prev)
         Guess
         (cube-iter (improve-cube Guess X) Guess X))
)

(define cube-root
   { number --> number }
   X -> (cube-iter 27.0 1.0 X)
)

\* 1.1.8 The Elements of Programming - Procedures as Black-Box Abstractions *\

(define square
   { number --> number }
   X -> (* X X)
)

(define double
   { number --> number }
   X -> (+ X X)
)

(define squarex
   { number --> number }
   X -> (EXP (double (LOG X)))
)

(define good-enough?
   { number --> number --> number }
   Guess X -> (< (abs (- (square Guess) X)) 0.001)
)

(define improve
   { number --> number --> number }
   Guess X -> (average Guess (/ X Guess))
)

(define sqrt-iter
   { number --> number --> number }
   Guess X ->
      (if (good-enough? Guess X)
         Guess
         (sqrt-iter (improve Guess X) X))
)

(define sqrtx
   { number --> number }
   X -> (sqrt-iter 1.0 X)
)

(square 5)

\* Block-structured *\
\* Note: Although lambda expressions can be use to get the effect of nested functions,
         I haven't figured a way to get recursive lambda functions.  Means that this
         example is not correct yet.
(define sqrtx
   { number --> number }
   X ->
      (let
         good-enough? (/. Guess (/. X
            (< (abs (- (square Guess) X)) 0.001)))
         (let
            improve (/. Guess (/. X
               (average Guess (/ X Guess))))
            (let
               sqrt-iter (/. Guess (/. X
                  (if (good-enough? Guess X)
                     Guess
                     (sqrt-iter (improve Guess X) X))))
               (sqrt-iter 1.0 X)
            )
         )
      )
)
*\

\* Taking advantage of lexical scoping *\
\* Note: Although lambda expressions can be use to get the effect of nested functions,
         I haven't figured a way to get recursive lambda functions.  Means that this
         example is not correct yet.
(define sqrtx
   { number --> number }
   X ->
      (let
         good-enough? (/. Guess
            (< (abs (- (square Guess) X)) 0.001))
         (let
            improve (/. Guess
               (average Guess (/ X Guess)))
            (let
               sqrt-iter (/. Guess
                  (if (good-enough? Guess)
                     Guess
                     (sqrt-iter (improve Guess))))
               (sqrt-iter 1.0)
            )
         )
      )
)
*\

\* 1.2.1 Procedures and the Processes They Generate - Linear Recursion and Iteration *\


\* Recursive *\
(define factorialx
   { integer --> integer }
   N ->
      (if (= N 1)
         1
         (* N (factorialx (- N 1))))
)

(factorialx 6)

\* Iterative *\
(define fact-iter
   { integer --> integer --> integer --> integer }
   Product Counter Max-Count ->
      (if (> Counter Max-Count)
         Product
         (fact-iter (* Counter Product) (+ Counter 1) Max-Count))
)

(define factorialx
   { integer --> integer }
   N -> (fact-iter 1 1 N)
)

\* Iterative, block-structured (from footnote) *\
\* Note: Although lambda expressions can be use to get the effect of nested functions,
         I haven't figured a way to get recursive lambda functions.  Means that this
         example is not correct yet.
(define factorialxz
   { integer --> integer }
   N ->
      (let
         fun-iter (/. Product (/. Counter (/. Max-Count
            (if (> Counter Max-Count)
               Product
               (fact-iter (* Counter Product) (+ Counter 1) Max-Count)))))
         (fact-iter 1 1 N)
      )
)
*\

\* Exercise 1.9 *\
(define inc { integer --> integer } A -> (+ A 1))
(define dec { integer --> integer } A -> (- A 1))

(define plus
   { integer --> integer --> integer }
   A B ->
      (if (= A 0)
         B
         (inc (plus (dec A) B)))
)
(define plus
   { integer --> integer --> integer }
   A B ->
      (if (= A 0)
         B
         (plus (dec A) (inc B)))
)

\* Exercise 1.10 *\
(define a
   { integer --> integer --> integer }
   X 0 -> 0
   0 Y -> (* 2 Y)
   X 1 -> 2
   X Y -> (a (- X 1) (a X (- Y 1)))
)
(a 1 10)
(a 2 4)
(a 3 3)
(define f { integer --> integer } N -> (a 0 N))
(define g { integer --> integer } N -> (a 1 N))
(define h { integer --> integer } N -> (a 2 N))
(define k { integer --> integer } N -> (* 5 (* N N)))

\* 1.2.2 Procedures and the Processes They Generate - Tree Recursion *\


\* Recursive *\
(define fib
   { integer --> integer }
   0 -> 0
   1 -> 1
   N -> (+ (fib (- N 1)) (fib (- N 2)))
)

\* Iterative *\
(define fib-iter
   { integer --> integer --> integer --> integer }
   A B 0 -> B
   A B Count -> (fib-iter (+ A B) A (- Count 1))
)
(define fib
   {integer --> integer }
   N -> (fib-iter 1 0 N)
)

\* Counting change *\
(define first-denomination
   { integer --> integer }
   1 -> 1
   2 -> 5
   3 -> 10
   4 -> 25
   5 -> 50
)

(define cc
   { integer --> integer --> integer }
   0 Kinds-Of-Coins -> 1
   Amount Kinds-Of-Coins -> 0 where (< Amount 0)
   Amount 0 -> 0
   Amount Kinds-Of-Coins ->
      (+ (cc Amount (- Kinds-Of-Coins 1))
         (cc (- Amount (first-denomination Kinds-Of-Coins)) Kinds-Of-Coins))
)

(define count-change
   { integer --> integer }
   Amount -> (cc Amount 5)
)

(count-change 100)

\* Exercise 1.11 *\
(define f
   { integer --> integer }
   N ->
      (if (< N 3)
         N
         (+ (f (- N 1)) (+ (* 2 (f (- N 2))) (* 3 (f (- N 3))))))
)
(define f-iter
   { integer --> integer --> integer --> integer --> integer }
   A B C 0 -> C
   A B C Count -> (f-iter (+ A (+ (* 2 B) (* 3 C))) A B (- Count 1))
)

(define f
   { integer --> integer }
   N -> (f-iter 2 1 0 n)
)

\* Exercise 1.12 *\
(define pascals-triangle
   { number --> number --> number }
   0 K -> 1
   N 0 -> 1
   N K -> 1 where (= N K)
   N K -> (+ (pascals-triangle (- N 1) (- K 1))
             (pascals-triangle (- N 1) K))
)

\* 1.2.3 Procedures and the Processes They Generate - Orders of Growth *\


\* Exercise 1.15 *\
(define cube { number --> number } X -> (* X (* X X)))
(define p { number --> number } X -> (- (* 3 X) (* 4 (cube X))))
(define sine
   { number --> number }
   Angle ->
      (if  (not (> (abs Angle) 0.1))
         Angle
         (p (sine (/ Angle 3.0))))
)

\* 1.2.4 Procedures and the Processes They Generate - Exponentiation *\


\* Linear recursion *\
(define expt
   { number --> number --> number }
   B 0 -> 1
   B N -> (* B (expt B (- N 1)))
)

\* Linear iteration *\
(define expt-iter
   { number --> number --> number --> number }
   B 0 Product -> Product
   B Counter Product -> (expt-iter B (- Counter 1) (* B Product))
)
(define expt
   { number --> number --> number }
   B N -> (expt-iter B N 1)
)

\* Logarithmic iteration *\
(define div { integer --> integer } X Y -> (TRUNCATE (/ X Y)))
(define even
   { integer --> integer }
   N -> (= (MOD N 2) 0)
)
(define fast-expt
   { integer --> integer --> integer }
   B 0 -> 1
   B N -> (square (fast-expt B (div N 2))) where (even N)
   B N -> (* B (fast-expt B (- N 1)))
)

\* Exercise 1.17 *\
(define multiply
   { integer --> integer --> integer }
   A 0 -> 0
   A B -> (+ A (* A (- B 1)))
)

\* Exercise 1.19 *\
(define fib-iter
   { integer --> integer --> integer --> integer --> integer --> integer }
   A B P Q 0 -> B
   A B P Q Count -> (fib-iter A B (+ (* P P) (* Q Q)) (+ (* 2 (* P Q)) (* Q Q)) (div Count 2))
                    where (even Count)
   A B P Q Count -> (fib-iter (+ (* B Q) (+ (* A Q) (* A P))) (+ (* B P) (* A Q)) P Q (- Count 1))
)
(define fib
   { integer --> integer }
   N -> (fib-iter 1 0 0 1 N)
)

\* 1.2.5 Procedures and the Processes They Generate - Greatest Common Divisors *\

(define gcd
   { integer --> integer --> integer }
   A 0 -> A
   A B -> (gcd B (MOD A B))
)

(gcd 40 6)

\* Exercise 1.20 *\
(gcd 206 40)

\* 1.2.6 Procedures and the Processes They Generate - Example: Testing for Primality *\


\* prime *\
(define divides
   { integer --> integer --> integer }
   A B -> (= (MOD B A) 0)
)

(define find-divisor
   { integer --> integer --> integer }
   N Test-Divisor ->
      (if (> (square Test-Divisor) N)
         N
         (if (divides Test-Divisor N)
            Test-Divisor
            (find-divisor N (+ Test-Divisor 1))))
)

(define smallest-divisor
   { integer --> integer }
   N -> (find-divisor N 2)
)

(define prime?
   { integer --> integer }
   N -> (= N (smallest-divisor N))
)

\* fast-prime *\
(define expmod
   { integer --> integer --> integer --> integer }
   Nbase 0 M -> 1
   Nbase Nexp M -> (MOD (square (expmod Nbase (div Nexp 2) M)) M)
                   where (even Nexp)
   Nbase Nexp M -> (MOD (* Nbase (expmod Nbase (- Nexp 1) M)) M)
)

(define fermat-test
   { integer --> boolean }
   N ->
      (let
         try-it (/. A (= (expmod A N N) A))
         (try-it (+ 1 (random (- N 1)))))
)

(define fast-prime?
   { integer --> integer --> integer }
   N 0 -> true
   N Ntimes ->
      (if (fermat-test N)
         (fast-prime? N (- Ntimes 1))
         false)
)

\* Exercise 1.21 *\
(smallest-divisor 199)
(smallest-divisor 1999)
(smallest-divisor 19999)

\* Exercise 1.22 *\
\* not sure how to get msec clock in Qi *\
(define get-time-in-milliseconds -> 1234)
(define report-prime
   { integer --> () }
   Elapsed-Time ->
      (output " *** ~A~%" Elapsed-Time)
)

(define start-prime-test
   { integer --> integer --> () }
   N Start-Time ->
      (if (prime? N)
         (report-prime (- (get-time-in-milliseconds) Start-Time))
         '())
)

(define timed-prime-test
   { integer --> () }
   N ->
      (let
         X (output "~A~%" N)
         (start-prime-test N (get-time-in-milliseconds)))
)

\* Exercise 1.25 *\
(define expmod
   { integer --> integer --> integer }
   Nbase Nexp M -> (MOD (fast-expt Nbase Nexp) M)
)

\* Exercise 1.26 *\
(define expmod
   { integer --> integer --> integer }
   Nbase 0 M -> 1
   Nbase Nexp M -> (MOD (* (expmod Nbase (div Nexp 2) M) (expmod Nbase (div Nexp 2) M)) M)
                   where (even Nexp)
   Nbase Nexp M -> (MOD (* Nbase (expmod Nbase (- Nexp 1) M)) M)
)

\* Exercise 1.27 *\
(define carmichael?
   { integer --> boolean }
   N -> (and (fast-prime? N 100) (not (prime? N)))
)
(carmichael? 561)
(carmichael? 1105)
(carmichael? 1729)
(carmichael? 2465)
(carmichael? 2821)
(carmichael? 6601)

\* 1.3 Formulating Abstractions with Higher-Order Procedures *\

(define cube { number --> number } X -> (* X (* X X)))

\* 1.3.1 Formulating Abstractions with Higher-Order Procedures - Procedures as Arguments *\

(define sum-integers
   { integer --> integer --> integer }
   A B -> 0 where (> A B)
   A B -> (+ A (sum-integers (+ A 1) B))
)

(define sum-cubes
   { integer --> integer --> integer }
   A B -> 0 where (> A B)
   A B -> (+ (cube A) (sum-cubes (+ A 1) B))
)

(define pi-sum
   { real --> real --> real }
   A B -> 0.0 where (> a b)
   A B -> (+ (/ 1.0 (* A (+ A 2.0)))
             (pi-sum (+ A 4.0) B)))

(define sum
   { (number --> number) --> number --> (number --> number) --> number --> number }
   Term A Next B -> 0 where (> A B)
   Term A Next B -> (+ (Term A) (sum Term (Next A) Next B))
)

\* Using sum *\
(define inc { integer --> integer } N -> (+ N 1))

(define sum-cubes
   { integer --> integer --> integer }
   A B -> (sum cube A inc B)
)

(sum-cubes 1 10)

(define identity { a --> a } X -> X)

(define sum-integers
   { integer --> integer --> integer }
   A B -> (sum identity A inc B)
)

(sum-integers 1 10)

(define pi-sum
   { real --> real --> real}
   A B ->
      (let
         pi-term (/. X (/ 1.0 (* X (+ X 2.0))))
         (let
            pi-next (/. X (+ X 4.0))
            (sum pi-term A pi-next B)))
)

(* 8.0 (pi-sum 1.0 1000.0))

(define integral
   { (number --> number) --> number --> number --> number --> number }
   F A B Dx ->
      (let
         add-dx (/. X (+ X Dx))
         (* (sum F (+ A (/ Dx 2.0)) add-dx B) Dx))
)

(integral cube 0.0 1.0 0.01)
(integral cube 0.0 1.0 0.001)

\* Exercise 1.29 *\
(define sum-iter
   { (number --> number) --> number --> (number --> number) --> number --> number --> number --> number --> number }
   Term Start Next Stop Acc A H -> Acc where (> Start Stop)
   Term Start Next Stop Acc A H ->
      (sum-iter Term (Next Start) Next Stop (+ Acc (Term (+ A (* Start H)))) A H)
)
(define simpson
   { (number --> number) --> number --> number --> integer --> number }
   F A B N ->
      (let
         H (/ (abs (- B A)) N)
         (* H (sum-iter F 1 inc N 0.0 A H)))
)
(simpson cube 0.0 1.0 100)

\* Exercise 1.30 *\
(define sum-iter
   { (number --> number) --> number --> (number --> number) --> number --> number --> number }
   Term A Next B Acc -> Acc where (> A B)
   Term A Next B Acc -> (sum-iter Term (Next A) Next B (+ Acc (Term A)))
)
(define sum-cubes
   { integer --> integer --> integer }
   A B -> (sum-iter cube A inc B 0)
)
(sum-cubes 1 10)

\* Exercise 1.31 *\
(define product
   { (number --> number) --> number --> (number --> number) --> number --> number }
   Term A Next B -> 1 where (> A B)
   Term A Next B -> (* (Term A) (product Term (Next A) Next B))
)
(define factorial
   { integer --> integer }
   N -> (product identity 1 inc N)
)

(define product-iter
   { (number --> number) --> number --> (number --> number) --> number --> number --> number }
   Term A Next B Acc -> Acc where (> A B)
   Term A Next B Acc -> (product-iter Term (Next A) Next B (* Acc (Term A)))
)

\* Exercise 1.32 *\
(define accumulate
   { (a --> a --> a) --> a --> (a --> a) --> a --> (a --> a) --> a --> a }
   Combiner Null-Value Term A Next B -> Null-Value where (> A B)
   Combiner Null-Value Term A Next B ->
      (Combiner (Term A) (accumulate Combiner Null-Value Term (Next A) Next B))
)
(define sum-n { integer --> integer } A B -> (accumulate + 0 identity A inc B))
(define product-n { integer --> integer } A B -> (accumulate * 1 identity A inc B))

(define accumulate-iter
   { (a --> a --> a) --> (a --> a) --> a --> (a --> a) --> a --> a --> a  }
   Combiner Term A Next B Acc -> Acc where (> A B)
   Combiner Term A Next B Acc ->
      (accumulate-iter Combiner Term (Next A) Next B (Combiner Acc (Term A)))
)
(define sum-n { integer --> integer } A B -> (accumulate-iter + identity A inc B 0))
(define product-n { integer --> integer } A B -> (accumulate-iter * identity A inc B 1))

\* Exercise 1.33 *\
(define filtered-accumulate
   { (a --> a --> a) --> a --> (a --> a) --> a --> (a --> a) --> a --> (a --> a) --> a }
   Combiner Null-Value Term A Next B Pred -> Null-Value where (> A B)
   Combiner Null-Value Term A Next B Pred ->
      (Combiner (Term A) (filtered-accumulate Combiner Null-Value Term (Next A) Next B Pred))
         where (Pred A)
   Combiner Null-Value Term A Next B Pred ->
      (filtered-accumulate Combiner Null-Value Term (Next A) Next B Pred)
)
(filtered-accumulate + 0 square 1 inc 5 prime?)

\* 1.3.2 Formulating Abstractions with Higher-Order Procedures - Constructing Procedures Using Lambda *\

(define pi-sum
   { real --> real }
   A B -> (sum (/. X (/ 1.0 (* X (+ X 2.0))))
               A
               (/. X (+ X 4.0))
               B)
)

(define integral
   { (number --> number) --> number --> number --> number --> number }
   F A B Dx ->
      (* (sum F
              (+ A (/ Dx 2.0))
              (/. X (+ X Dx))
              B)
          Dx)
)

(define plus4 { number --> number } X -> (+ X 4))

(set plus4 (/. X (+ X 4)))

((/. X (/. Y (/. Z (+ X (+ Y (square Z)))))) 1 2 3)

Retrieved from "http://www.codepoetics.com/wiki/index.php?title=Topics:SICP_in_other_languages:Qi:Chapter_1"

This page has been accessed 1364 times. This page was last modified 13:47, 17 Sep 2007.


[Main Page]
Main Page
Recent changes
Random page
Current events

Edit this page
Discuss this page
Page history
What links here
Related changes

Special pages
Bug reports