diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,11 @@
+Copyright Vanessa McHale (c) 2017
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,20 @@
+# fast-combinatorics
+
+This is a library for fast combinatorics using ATS. You may need to download the 
+relevant ATS libraries
+[here](http://www.ats-lang.org/Downloads.html#Install_of_ATS2_include) if
+linking fails.
+
+Currently it is in-progress, being somewhat constrained by the fact that I have
+yet to figure out how to share arbitrary-precision types between ATS and Haskell.
+
+# Building
+
+The Haskell library comes with the C bundled, however you may wish to build from
+source if you are hacking on the library. To that end, you can install
+[stack](http://haskellstack.org/), [patscc](http://www.ats-lang.org/Downloads.html) , and
+[pats-filter](https://github.com/Hibou57/PostiATS-Utilities) and build with
+
+```bash
+ $ ./shake.hs
+```
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/bench/Bench.hs b/bench/Bench.hs
new file mode 100644
--- /dev/null
+++ b/bench/Bench.hs
@@ -0,0 +1,18 @@
+module Main where
+
+import           Criterion.Main
+import           Lib
+import qualified Math.Combinatorics.Binomial as MB
+import qualified Math.Combinatorics.Factorial as MB
+
+main :: IO ()
+main =
+    defaultMain [ bgroup "factorial"
+                      [ bench "factorial" $ nf factorial 12
+                      , bench "MB.factorial" $ nf factorial 12
+                      ]
+                , bgroup "choose"
+                      [ bench "choose" $ nf (13 `choose`) 4
+                      , bench "MB.choose" $ nf (13 `choose`) 4
+                      ]
+                ]
diff --git a/cbits/fast-combinatorics.c b/cbits/fast-combinatorics.c
new file mode 100644
--- /dev/null
+++ b/cbits/fast-combinatorics.c
@@ -0,0 +1,959 @@
+/*
+**
+** The C code is generated by [ATS/Postiats-0-3-8]
+** The starting compilation time is: 2017-12-30: 10h:46m
+**
+*/
+
+/*
+** include runtime header files
+*/
+#ifndef _ATS_CCOMP_HEADER_NONE_
+#include "pats_ccomp_config.h"
+#include "pats_ccomp_basics.h"
+#include "pats_ccomp_typedefs.h"
+#include "pats_ccomp_instrset.h"
+#include "pats_ccomp_memalloc.h"
+#ifndef _ATS_CCOMP_EXCEPTION_NONE_
+#include "pats_ccomp_memalloca.h"
+#include "pats_ccomp_exception.h"
+#endif // end of [_ATS_CCOMP_EXCEPTION_NONE_]
+#endif /* _ATS_CCOMP_HEADER_NONE_ */
+
+
+/*
+** include prelude cats files
+*/
+#ifndef _ATS_CCOMP_PRELUDE_NONE_
+//
+#include "prelude/CATS/basics.cats"
+#include "prelude/CATS/integer.cats"
+#include "prelude/CATS/pointer.cats"
+#include "prelude/CATS/integer_long.cats"
+#include "prelude/CATS/integer_size.cats"
+#include "prelude/CATS/integer_short.cats"
+#include "prelude/CATS/bool.cats"
+#include "prelude/CATS/char.cats"
+#include "prelude/CATS/float.cats"
+#include "prelude/CATS/integer_ptr.cats"
+#include "prelude/CATS/integer_fixed.cats"
+#include "prelude/CATS/memory.cats"
+#include "prelude/CATS/string.cats"
+#include "prelude/CATS/strptr.cats"
+//
+#include "prelude/CATS/fprintf.cats"
+//
+#include "prelude/CATS/filebas.cats"
+//
+#include "prelude/CATS/list.cats"
+#include "prelude/CATS/option.cats"
+#include "prelude/CATS/array.cats"
+#include "prelude/CATS/arrayptr.cats"
+#include "prelude/CATS/arrayref.cats"
+#include "prelude/CATS/matrix.cats"
+#include "prelude/CATS/matrixptr.cats"
+//
+#endif /* _ATS_CCOMP_PRELUDE_NONE_ */
+/*
+** for user-supplied prelude
+*/
+#ifdef _ATS_CCOMP_PRELUDE_USER_
+//
+#include _ATS_CCOMP_PRELUDE_USER_
+//
+#endif /* _ATS_CCOMP_PRELUDE_USER_ */
+/*
+** for user2-supplied prelude
+*/
+#ifdef _ATS_CCOMP_PRELUDE_USER2_
+//
+#include _ATS_CCOMP_PRELUDE_USER2_
+//
+#endif /* _ATS_CCOMP_PRELUDE_USER2_ */
+
+/*
+staload-prologues(beg)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/basics.dats: 1636(line=50, offs=1) -- 1675(line=50, offs=40)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/integer.dats: 1596(line=49, offs=1) -- 1635(line=49, offs=40)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/pointer.dats: 1533(line=44, offs=1) -- 1572(line=44, offs=40)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/integer_long.dats: 1602(line=49, offs=1) -- 1641(line=49, offs=40)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/integer_size.dats: 1597(line=49, offs=1) -- 1636(line=49, offs=40)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/integer_short.dats: 1603(line=49, offs=1) -- 1642(line=49, offs=40)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/char.dats: 1610(line=48, offs=1) -- 1649(line=48, offs=40)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/float.dats: 1636(line=50, offs=1) -- 1675(line=50, offs=40)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/string.dats: 1631(line=50, offs=1) -- 1670(line=50, offs=40)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/strptr.dats: 1629(line=50, offs=1) -- 1668(line=50, offs=40)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/strptr.dats: 1691(line=54, offs=1) -- 1738(line=54, offs=48)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/integer.dats: 1596(line=49, offs=1) -- 1635(line=49, offs=40)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/integer_ptr.dats: 1601(line=49, offs=1) -- 1640(line=49, offs=40)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/integer_fixed.dats: 1603(line=49, offs=1) -- 1642(line=49, offs=40)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/memory.dats: 1410(line=38, offs=1) -- 1449(line=39, offs=32)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/filebas.dats: 1613(line=49, offs=1) -- 1652(line=50, offs=32)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/filebas.dats: 1675(line=54, offs=1) -- 1721(line=55, offs=39)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/integer.dats: 1596(line=49, offs=1) -- 1635(line=49, offs=40)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/filebas.dats: 1744(line=59, offs=1) -- 1789(line=60, offs=38)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/libats/libc/SATS/stdio.sats: 1390(line=36, offs=1) -- 1437(line=39, offs=3)
+*/
+
+#include \
+"libats/libc/CATS/stdio.cats"
+/*
+/usr/local/lib/ats2-postiats-0.3.8/libats/libc/SATS/stdio.sats: 1950(line=69, offs=1) -- 1999(line=71, offs=34)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/libats/libc/SATS/sys/types.sats: 1390(line=36, offs=1) -- 1441(line=39, offs=3)
+*/
+
+#include \
+"libats/libc/CATS/sys/types.cats"
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/filebas.dats: 1871(line=66, offs=1) -- 1918(line=66, offs=48)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/libats/libc/SATS/sys/stat.sats: 1390(line=36, offs=1) -- 1440(line=39, offs=3)
+*/
+
+#include \
+"libats/libc/CATS/sys/stat.cats"
+/*
+/usr/local/lib/ats2-postiats-0.3.8/libats/libc/SATS/sys/stat.sats: 1756(line=58, offs=1) -- 1805(line=60, offs=34)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/libats/libc/SATS/sys/types.sats: 1390(line=36, offs=1) -- 1441(line=39, offs=3)
+*/
+
+#include \
+"libats/libc/CATS/sys/types.cats"
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/filebas.dats: 15552(line=879, offs=1) -- 15589(line=880, offs=30)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/libats/libc/SATS/stdio.sats: 1390(line=36, offs=1) -- 1437(line=39, offs=3)
+*/
+
+#include \
+"libats/libc/CATS/stdio.cats"
+/*
+/usr/local/lib/ats2-postiats-0.3.8/libats/libc/SATS/stdio.sats: 1950(line=69, offs=1) -- 1999(line=71, offs=34)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/libats/libc/SATS/sys/types.sats: 1390(line=36, offs=1) -- 1441(line=39, offs=3)
+*/
+
+#include \
+"libats/libc/CATS/sys/types.cats"
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/list.dats: 1529(line=44, offs=1) -- 1568(line=45, offs=32)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/list.dats: 1569(line=46, offs=1) -- 1615(line=47, offs=39)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/unsafe.dats: 1532(line=44, offs=1) -- 1566(line=44, offs=35)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/list_vt.dats: 1538(line=44, offs=1) -- 1577(line=45, offs=32)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/list_vt.dats: 1578(line=46, offs=1) -- 1624(line=47, offs=39)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/unsafe.dats: 1532(line=44, offs=1) -- 1566(line=44, offs=35)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/SHARE/list_vt_mergesort.dats: 1546(line=44, offs=1) -- 1585(line=44, offs=40)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/SHARE/list_vt_quicksort.dats: 1546(line=44, offs=1) -- 1585(line=44, offs=40)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/array.dats: 1534(line=44, offs=1) -- 1573(line=44, offs=40)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/array.dats: 1574(line=45, offs=1) -- 1616(line=45, offs=43)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/SHARE/array_bsearch.dats: 1531(line=44, offs=1) -- 1570(line=44, offs=40)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/SHARE/array_quicksort.dats: 1531(line=44, offs=1) -- 1570(line=44, offs=40)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/arrayptr.dats: 1532(line=44, offs=1) -- 1571(line=44, offs=40)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/arrayref.dats: 1532(line=44, offs=1) -- 1571(line=44, offs=40)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/matrix.dats: 1535(line=44, offs=1) -- 1574(line=44, offs=40)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/matrixptr.dats: 1538(line=44, offs=1) -- 1577(line=44, offs=40)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/matrixref.dats: 1538(line=44, offs=1) -- 1577(line=44, offs=40)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/stream.dats: 1523(line=44, offs=1) -- 1562(line=44, offs=40)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/stream_vt.dats: 1523(line=44, offs=1) -- 1562(line=44, offs=40)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/tostring.dats: 1528(line=44, offs=1) -- 1567(line=45, offs=32)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/unsafe.dats: 1532(line=44, offs=1) -- 1566(line=44, offs=35)
+*/
+/*
+/usr/local/lib/ats2-postiats-0.3.8/prelude/DATS/checkast.dats: 1531(line=44, offs=1) -- 1570(line=45, offs=32)
+*/
+/*
+staload-prologues(end)
+*/
+/*
+typedefs-for-tyrecs-and-tysums(beg)
+*/
+/*
+typedefs-for-tyrecs-and-tysums(end)
+*/
+/*
+dynconlst-declaration(beg)
+*/
+/*
+dynconlst-declaration(end)
+*/
+/*
+dyncstlst-declaration(beg)
+*/
+ATSdyncst_mac(atspre_g0int_mul_int)
+ATSdyncst_mac(atspre_g1int_sub_int)
+ATSdyncst_mac(atspre_g1int_mul_int)
+ATSdyncst_mac(atspre_g1int_add_int)
+ATSdyncst_mac(atspre_g0int_div_int)
+/*
+dyncstlst-declaration(end)
+*/
+/*
+dynvalist-implementation(beg)
+*/
+/*
+dynvalist-implementation(end)
+*/
+/*
+exnconlst-declaration(beg)
+*/
+#ifndef _ATS_CCOMP_EXCEPTION_NONE_
+ATSextern()
+atsvoid_t0ype
+the_atsexncon_initize
+(
+  atstype_exnconptr d2c, atstype_string exnmsg
+) ;
+#endif // end of [_ATS_CCOMP_EXCEPTION_NONE_]
+/*
+exnconlst-declaration(end)
+*/
+/*
+extypelst-declaration(beg)
+*/
+/*
+extypelst-declaration(end)
+*/
+/*
+assumelst-declaration(beg)
+*/
+#ifndef _ATS_CCOMP_ASSUME_CHECK_NONE_
+#endif // #ifndef(_ATS_CCOMP_ASSUME_CHECK_NONE_)
+/*
+assumelst-declaration(end)
+*/
+ATSstatic()
+atstkind_t0ype(atstype_int)
+fact_0(atstkind_t0ype(atstype_int)) ;
+
+ATSstatic()
+atstkind_t0ype(atstype_int)
+dfact_3(atstkind_t0ype(atstype_int)) ;
+
+ATSstatic()
+atstkind_t0ype(atstype_int)
+choose_4(atstkind_t0ype(atstype_int), atstkind_t0ype(atstype_int)) ;
+
+ATSstatic()
+atstkind_t0ype(atstype_int)
+numerator_loop_5(atstkind_t0ype(atstype_int), atstkind_t0ype(atstype_int)) ;
+
+#if(0)
+ATSextern()
+atstkind_t0ype(atstype_int)
+choose_ats(atstkind_t0ype(atstype_int), atstkind_t0ype(atstype_int)) ;
+#endif // end of [QUALIFIED]
+
+#if(0)
+ATSextern()
+atstkind_t0ype(atstype_int)
+double_factorial(atstkind_t0ype(atstype_int)) ;
+#endif // end of [QUALIFIED]
+
+#if(0)
+ATSextern()
+atstkind_t0ype(atstype_int)
+factorial_ats(atstkind_t0ype(atstype_int)) ;
+#endif // end of [QUALIFIED]
+
+/*
+/home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 70(line=5, offs=5) -- 167(line=8, offs=28)
+*/
+/*
+local: fact_0$0(level=0)
+global: fact_0$0(level=0)
+local: 
+global: 
+*/
+ATSstatic()
+atstkind_t0ype(atstype_int)
+fact_0(atstkind_t0ype(atstype_int) arg0)
+{
+/* tmpvardeclst(beg) */
+ATStmpdec(apy0, atstkind_t0ype(atstype_int)) ;
+ATStmpdec(tmpret0, atstkind_t0ype(atstype_int)) ;
+ATStmpdec(tmp1, atstkind_t0ype(atstype_int)) ;
+ATStmpdec(tmp2, atstkind_t0ype(atstype_int)) ;
+/* tmpvardeclst(end) */
+/*
+emit_funent_fnxdeclst:
+*/
+ATSfunbody_beg()
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 70(line=5, offs=5) -- 167(line=8, offs=28)
+*/
+ATSINSflab(__patsflab_fact_0):
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 116(line=6, offs=3) -- 167(line=8, offs=28)
+*/
+ATScaseof_beg()
+/*
+** ibranchlst-beg
+*/
+ATSbranch_beg()
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 133(line=7, offs=7) -- 134(line=7, offs=8)
+*/
+ATSINSlab(__atstmplab0):
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 92(line=5, offs=27) -- 93(line=5, offs=28)
+*/
+ATSifnthen(ATSCKpat_int(arg0, ATSPMVint(0))) { ATSINSgoto(__atstmplab2) ; } ;
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 134(line=7, offs=8) -- 134(line=7, offs=8)
+*/
+ATSINSlab(__atstmplab1):
+/*
+emit_instr: loc0 = : 0(line=0, offs=0) -- 0(line=0, offs=0)
+*/
+/*
+ibranch-mbody:
+*/
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 138(line=7, offs=12) -- 139(line=7, offs=13)
+*/
+ATSINSmove(tmpret0, ATSPMVi0nt(1)) ;
+ATSbranch_end()
+
+ATSbranch_beg()
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 147(line=8, offs=8) -- 147(line=8, offs=8)
+*/
+ATSINSlab(__atstmplab2):
+/*
+emit_instr: loc0 = : 0(line=0, offs=0) -- 0(line=0, offs=0)
+*/
+/*
+ibranch-mbody:
+*/
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 157(line=8, offs=18) -- 162(line=8, offs=23)
+*/
+ATSINSmove(tmp2, atspre_g1int_sub_int(arg0, ATSPMVi0nt(1))) ;
+
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 152(line=8, offs=13) -- 163(line=8, offs=24)
+*/
+ATSINSmove(tmp1, fact_0(tmp2)) ;
+
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 152(line=8, offs=13) -- 167(line=8, offs=28)
+*/
+ATSINSmove(tmpret0, atspre_g0int_mul_int(tmp1, arg0)) ;
+
+ATSbranch_end()
+
+/*
+** ibranchlst-end
+*/
+ATScaseof_end()
+
+ATSfunbody_end()
+ATSreturn(tmpret0) ;
+/*
+emit_funent_fnxbodylst:
+*/
+} /* end of [fact_0] */
+
+/*
+/home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 173(line=10, offs=5) -- 285(line=14, offs=29)
+*/
+/*
+local: dfact_3$0(level=0)
+global: dfact_3$0(level=0)
+local: 
+global: 
+*/
+ATSstatic()
+atstkind_t0ype(atstype_int)
+dfact_3(atstkind_t0ype(atstype_int) arg0)
+{
+/* tmpvardeclst(beg) */
+ATStmpdec(apy0, atstkind_t0ype(atstype_int)) ;
+ATStmpdec(tmpret3, atstkind_t0ype(atstype_int)) ;
+ATStmpdec(tmp4, atstkind_t0ype(atstype_int)) ;
+ATStmpdec(tmp5, atstkind_t0ype(atstype_int)) ;
+/* tmpvardeclst(end) */
+/*
+emit_funent_fnxdeclst:
+*/
+ATSfunbody_beg()
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 173(line=10, offs=5) -- 285(line=14, offs=29)
+*/
+ATSINSflab(__patsflab_dfact_3):
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 220(line=11, offs=3) -- 285(line=14, offs=29)
+*/
+ATScaseof_beg()
+/*
+** ibranchlst-beg
+*/
+ATSbranch_beg()
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 237(line=12, offs=7) -- 238(line=12, offs=8)
+*/
+ATSINSlab(__atstmplab3):
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 196(line=10, offs=28) -- 197(line=10, offs=29)
+*/
+ATSifnthen(ATSCKpat_int(arg0, ATSPMVint(0))) { ATSINSgoto(__atstmplab5) ; } ;
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 238(line=12, offs=8) -- 238(line=12, offs=8)
+*/
+ATSINSlab(__atstmplab4):
+/*
+emit_instr: loc0 = : 0(line=0, offs=0) -- 0(line=0, offs=0)
+*/
+/*
+ibranch-mbody:
+*/
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 242(line=12, offs=12) -- 243(line=12, offs=13)
+*/
+ATSINSmove(tmpret3, ATSPMVi0nt(1)) ;
+ATSbranch_end()
+
+ATSbranch_beg()
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 250(line=13, offs=7) -- 251(line=13, offs=8)
+*/
+ATSINSlab(__atstmplab5):
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 196(line=10, offs=28) -- 197(line=10, offs=29)
+*/
+ATSifnthen(ATSCKpat_int(arg0, ATSPMVint(1))) { ATSINSgoto(__atstmplab7) ; } ;
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 251(line=13, offs=8) -- 251(line=13, offs=8)
+*/
+ATSINSlab(__atstmplab6):
+/*
+emit_instr: loc0 = : 0(line=0, offs=0) -- 0(line=0, offs=0)
+*/
+/*
+ibranch-mbody:
+*/
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 255(line=13, offs=12) -- 256(line=13, offs=13)
+*/
+ATSINSmove(tmpret3, ATSPMVi0nt(1)) ;
+ATSbranch_end()
+
+ATSbranch_beg()
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 264(line=14, offs=8) -- 264(line=14, offs=8)
+*/
+ATSINSlab(__atstmplab7):
+/*
+emit_instr: loc0 = : 0(line=0, offs=0) -- 0(line=0, offs=0)
+*/
+/*
+ibranch-mbody:
+*/
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 279(line=14, offs=23) -- 284(line=14, offs=28)
+*/
+ATSINSmove(tmp5, atspre_g1int_sub_int(arg0, ATSPMVi0nt(2))) ;
+
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 273(line=14, offs=17) -- 285(line=14, offs=29)
+*/
+ATSINSmove(tmp4, dfact_3(tmp5)) ;
+
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 269(line=14, offs=13) -- 285(line=14, offs=29)
+*/
+ATSINSmove(tmpret3, atspre_g0int_mul_int(arg0, tmp4)) ;
+
+ATSbranch_end()
+
+/*
+** ibranchlst-end
+*/
+ATScaseof_end()
+
+ATSfunbody_end()
+ATSreturn(tmpret3) ;
+/*
+emit_funent_fnxbodylst:
+*/
+} /* end of [dfact_3] */
+
+/*
+/home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 324(line=17, offs=4) -- 680(line=29, offs=6)
+*/
+/*
+local: fact_0$0(level=0)
+global: fact_0$0(level=0), choose_4$0(level=0)
+local: 
+global: 
+*/
+ATSstatic()
+atstkind_t0ype(atstype_int)
+choose_4(atstkind_t0ype(atstype_int) arg0, atstkind_t0ype(atstype_int) arg1)
+{
+/* tmpvardeclst(beg) */
+ATStmpdec(tmpret6, atstkind_t0ype(atstype_int)) ;
+ATStmpdec(tmp13, atstkind_t0ype(atstype_int)) ;
+ATStmpdec(tmp14, atstkind_t0ype(atstype_int)) ;
+/* tmpvardeclst(end) */
+ATSfunbody_beg()
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 324(line=17, offs=4) -- 680(line=29, offs=6)
+*/
+ATSINSflab(__patsflab_choose_4):
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 396(line=18, offs=3) -- 680(line=29, offs=6)
+*/
+/*
+letpush(beg)
+*/
+/*
+letpush(end)
+*/
+
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 592(line=25, offs=5) -- 674(line=28, offs=42)
+*/
+ATScaseof_beg()
+/*
+** ibranchlst-beg
+*/
+ATSbranch_beg()
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 611(line=26, offs=9) -- 612(line=26, offs=10)
+*/
+ATSINSlab(__atstmplab13):
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 374(line=17, offs=54) -- 375(line=17, offs=55)
+*/
+ATSifnthen(ATSCKpat_int(arg1, ATSPMVint(0))) { ATSINSgoto(__atstmplab15) ; } ;
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 612(line=26, offs=10) -- 612(line=26, offs=10)
+*/
+ATSINSlab(__atstmplab14):
+/*
+emit_instr: loc0 = : 0(line=0, offs=0) -- 0(line=0, offs=0)
+*/
+/*
+ibranch-mbody:
+*/
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 616(line=26, offs=14) -- 617(line=26, offs=15)
+*/
+ATSINSmove(tmpret6, ATSPMVi0nt(1)) ;
+ATSbranch_end()
+
+ATSbranch_beg()
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 626(line=27, offs=9) -- 627(line=27, offs=10)
+*/
+ATSINSlab(__atstmplab15):
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 374(line=17, offs=54) -- 375(line=17, offs=55)
+*/
+ATSifnthen(ATSCKpat_int(arg1, ATSPMVint(1))) { ATSINSgoto(__atstmplab17) ; } ;
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 627(line=27, offs=10) -- 627(line=27, offs=10)
+*/
+ATSINSlab(__atstmplab16):
+/*
+emit_instr: loc0 = : 0(line=0, offs=0) -- 0(line=0, offs=0)
+*/
+/*
+ibranch-mbody:
+*/
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 631(line=27, offs=14) -- 632(line=27, offs=15)
+*/
+ATSINSmove(tmpret6, arg0) ;
+ATSbranch_end()
+
+ATSbranch_beg()
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 642(line=28, offs=10) -- 642(line=28, offs=10)
+*/
+ATSINSlab(__atstmplab17):
+/*
+emit_instr: loc0 = : 0(line=0, offs=0) -- 0(line=0, offs=0)
+*/
+/*
+ibranch-mbody:
+*/
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 647(line=28, offs=15) -- 663(line=28, offs=31)
+*/
+ATSINSmove(tmp13, numerator_loop_5(arg0, arg1)) ;
+
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 667(line=28, offs=35) -- 673(line=28, offs=41)
+*/
+ATSINSmove(tmp14, fact_0(arg1)) ;
+
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 647(line=28, offs=15) -- 673(line=28, offs=41)
+*/
+ATSINSmove(tmpret6, atspre_g0int_div_int(tmp13, tmp14)) ;
+
+ATSbranch_end()
+
+/*
+** ibranchlst-end
+*/
+ATScaseof_end()
+
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 396(line=18, offs=3) -- 680(line=29, offs=6)
+*/
+/*
+INSletpop()
+*/
+ATSfunbody_end()
+ATSreturn(tmpret6) ;
+} /* end of [choose_4] */
+
+/*
+/home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 408(line=19, offs=9) -- 582(line=23, offs=52)
+*/
+/*
+local: numerator_loop_5$0(level=1)
+global: numerator_loop_5$0(level=1)
+local: n$4734(1)(HSEapp(HSEcst(atstkind_t0ype); HSEs2exp(S2Eextkind(atstype_int))))
+global: n$4734(1)(HSEapp(HSEcst(atstkind_t0ype); HSEs2exp(S2Eextkind(atstype_int))))
+*/
+ATSstatic()
+atstkind_t0ype(atstype_int)
+numerator_loop_5(atstkind_t0ype(atstype_int) env0, atstkind_t0ype(atstype_int) arg0)
+{
+/* tmpvardeclst(beg) */
+ATStmpdec(tmpret7, atstkind_t0ype(atstype_int)) ;
+ATStmpdec(tmp8, atstkind_t0ype(atstype_int)) ;
+ATStmpdec(tmp9, atstkind_t0ype(atstype_int)) ;
+ATStmpdec(tmp10, atstkind_t0ype(atstype_int)) ;
+ATStmpdec(tmp11, atstkind_t0ype(atstype_int)) ;
+ATStmpdec(tmp12, atstkind_t0ype(atstype_int)) ;
+/* tmpvardeclst(end) */
+ATSfunbody_beg()
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 408(line=19, offs=9) -- 582(line=23, offs=52)
+*/
+ATSINSflab(__patsflab_numerator_loop_5):
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 476(line=20, offs=7) -- 582(line=23, offs=52)
+*/
+ATScaseof_beg()
+/*
+** ibranchlst-beg
+*/
+ATSbranch_beg()
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 497(line=21, offs=11) -- 498(line=21, offs=12)
+*/
+ATSINSlab(__atstmplab8):
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 450(line=19, offs=51) -- 451(line=19, offs=52)
+*/
+ATSifnthen(ATSCKpat_int(arg0, ATSPMVint(1))) { ATSINSgoto(__atstmplab10) ; } ;
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 498(line=21, offs=12) -- 498(line=21, offs=12)
+*/
+ATSINSlab(__atstmplab9):
+/*
+emit_instr: loc0 = : 0(line=0, offs=0) -- 0(line=0, offs=0)
+*/
+/*
+ibranch-mbody:
+*/
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 502(line=21, offs=16) -- 503(line=21, offs=17)
+*/
+ATSINSmove(tmpret7, env0) ;
+ATSbranch_end()
+
+ATSbranch_beg()
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 514(line=22, offs=11) -- 515(line=22, offs=12)
+*/
+ATSINSlab(__atstmplab10):
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 450(line=19, offs=51) -- 451(line=19, offs=52)
+*/
+ATSifnthen(ATSCKpat_int(arg0, ATSPMVint(2))) { ATSINSgoto(__atstmplab12) ; } ;
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 515(line=22, offs=12) -- 515(line=22, offs=12)
+*/
+ATSINSlab(__atstmplab11):
+/*
+emit_instr: loc0 = : 0(line=0, offs=0) -- 0(line=0, offs=0)
+*/
+/*
+ibranch-mbody:
+*/
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 520(line=22, offs=17) -- 525(line=22, offs=22)
+*/
+ATSINSmove(tmp8, atspre_g1int_sub_int(env0, ATSPMVi0nt(1))) ;
+
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 519(line=22, offs=16) -- 530(line=22, offs=27)
+*/
+ATSINSmove(tmpret7, atspre_g1int_mul_int(tmp8, env0)) ;
+
+ATSbranch_end()
+
+ATSbranch_beg()
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 542(line=23, offs=12) -- 542(line=23, offs=12)
+*/
+ATSINSlab(__atstmplab12):
+/*
+emit_instr: loc0 = : 0(line=0, offs=0) -- 0(line=0, offs=0)
+*/
+/*
+ibranch-mbody:
+*/
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 548(line=23, offs=18) -- 553(line=23, offs=23)
+*/
+ATSINSmove(tmp10, atspre_g1int_add_int(env0, ATSPMVi0nt(1))) ;
+
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 548(line=23, offs=18) -- 557(line=23, offs=27)
+*/
+ATSINSmove(tmp9, atspre_g1int_sub_int(tmp10, arg0)) ;
+
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 576(line=23, offs=46) -- 581(line=23, offs=51)
+*/
+ATSINSmove(tmp12, atspre_g1int_sub_int(arg0, ATSPMVi0nt(1))) ;
+
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 561(line=23, offs=31) -- 582(line=23, offs=52)
+*/
+ATSINSmove(tmp11, numerator_loop_5(env0, tmp12)) ;
+
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 547(line=23, offs=17) -- 582(line=23, offs=52)
+*/
+ATSINSmove(tmpret7, atspre_g0int_mul_int(tmp9, tmp11)) ;
+
+ATSbranch_end()
+
+/*
+** ibranchlst-end
+*/
+ATScaseof_end()
+
+ATSfunbody_end()
+ATSreturn(tmpret7) ;
+} /* end of [numerator_loop_5] */
+
+/*
+/home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 793(line=35, offs=22) -- 816(line=36, offs=15)
+*/
+/*
+local: choose_4$0(level=0)
+global: fact_0$0(level=0), choose_4$0(level=0), choose_ats$9$0(level=0)
+local: 
+global: 
+*/
+ATSextern()
+atstkind_t0ype(atstype_int)
+choose_ats(atstkind_t0ype(atstype_int) arg0, atstkind_t0ype(atstype_int) arg1)
+{
+/* tmpvardeclst(beg) */
+ATStmpdec(tmpret15, atstkind_t0ype(atstype_int)) ;
+/* tmpvardeclst(end) */
+ATSfunbody_beg()
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 782(line=35, offs=11) -- 816(line=36, offs=15)
+*/
+ATSINSflab(__patsflab_choose_ats):
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 804(line=36, offs=3) -- 816(line=36, offs=15)
+*/
+ATSINSmove(tmpret15, choose_4(arg0, arg1)) ;
+
+ATSfunbody_end()
+ATSreturn(tmpret15) ;
+} /* end of [choose_ats] */
+
+/*
+/home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 911(line=42, offs=28) -- 926(line=43, offs=10)
+*/
+/*
+local: dfact_3$0(level=0)
+global: dfact_3$0(level=0), double_factorial$10$0(level=0)
+local: 
+global: 
+*/
+ATSextern()
+atstkind_t0ype(atstype_int)
+double_factorial(atstkind_t0ype(atstype_int) arg0)
+{
+/* tmpvardeclst(beg) */
+ATStmpdec(tmpret16, atstkind_t0ype(atstype_int)) ;
+/* tmpvardeclst(end) */
+ATSfunbody_beg()
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 894(line=42, offs=11) -- 927(line=43, offs=11)
+*/
+ATSINSflab(__patsflab_double_factorial):
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 919(line=43, offs=3) -- 926(line=43, offs=10)
+*/
+ATSINSmove(tmpret16, dfact_3(arg0)) ;
+
+ATSfunbody_end()
+ATSreturn(tmpret16) ;
+} /* end of [double_factorial] */
+
+/*
+/home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 1016(line=49, offs=25) -- 1030(line=50, offs=9)
+*/
+/*
+local: fact_0$0(level=0)
+global: fact_0$0(level=0), factorial_ats$11$0(level=0)
+local: 
+global: 
+*/
+ATSextern()
+atstkind_t0ype(atstype_int)
+factorial_ats(atstkind_t0ype(atstype_int) arg0)
+{
+/* tmpvardeclst(beg) */
+ATStmpdec(tmpret17, atstkind_t0ype(atstype_int)) ;
+/* tmpvardeclst(end) */
+ATSfunbody_beg()
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 1002(line=49, offs=11) -- 1031(line=50, offs=10)
+*/
+ATSINSflab(__patsflab_factorial_ats):
+/*
+emit_instr: loc0 = /home/vanessa/programming/haskell/current/fast-combinatorics/ats-src/fast-combinatorics.dats: 1024(line=50, offs=3) -- 1030(line=50, offs=9)
+*/
+ATSINSmove(tmpret17, fact_0(arg0)) ;
+
+ATSfunbody_end()
+ATSreturn(tmpret17) ;
+} /* end of [factorial_ats] */
+
+/*
+** for initialization(dynloading)
+*/
+ATSdynloadflag_minit(_057_home_057_vanessa_057_programming_057_haskell_057_current_057_fast_055_combinatorics_057_ats_055_src_057_fast_055_combinatorics_056_dats__dynloadflag) ;
+ATSextern()
+atsvoid_t0ype
+_057_home_057_vanessa_057_programming_057_haskell_057_current_057_fast_055_combinatorics_057_ats_055_src_057_fast_055_combinatorics_056_dats__dynload()
+{
+ATSfunbody_beg()
+ATSdynload(/*void*/)
+ATSdynloadflag_sta(
+_057_home_057_vanessa_057_programming_057_haskell_057_current_057_fast_055_combinatorics_057_ats_055_src_057_fast_055_combinatorics_056_dats__dynloadflag
+) ;
+ATSif(
+ATSCKiseqz(
+_057_home_057_vanessa_057_programming_057_haskell_057_current_057_fast_055_combinatorics_057_ats_055_src_057_fast_055_combinatorics_056_dats__dynloadflag
+)
+) ATSthen() {
+ATSdynloadset(_057_home_057_vanessa_057_programming_057_haskell_057_current_057_fast_055_combinatorics_057_ats_055_src_057_fast_055_combinatorics_056_dats__dynloadflag) ;
+/*
+dynexnlst-initize(beg)
+*/
+/*
+dynexnlst-initize(end)
+*/
+} /* ATSendif */
+ATSfunbody_end()
+ATSreturn_void(tmpret_void) ;
+} /* end of [*_dynload] */
+
+/* ****** ****** */
+
+/* end-of-compilation-unit */
diff --git a/fast-combinatorics.cabal b/fast-combinatorics.cabal
new file mode 100644
--- /dev/null
+++ b/fast-combinatorics.cabal
@@ -0,0 +1,62 @@
+name:                fast-combinatorics
+version:             0.1.0.0
+synopsis:            Fast combinatorics.
+description:         Fast combinatorics code with a high level of safety guaranteed by writing it in ATS.
+homepage:            https://github.com//fast-combinatorics#readme
+license:             BSD3
+license-file:        LICENSE
+author:              Vanessa McHale
+maintainer:          vamchale@gmail.com
+copyright:           Copyright: (c) 2017 Vanessa McHale
+category:            Numerics
+build-type:          Simple
+extra-source-files:  cbits/fast-combinatorics.c
+extra-doc-files:     README.md
+cabal-version:       >=1.18
+
+Flag development {
+  Description: Enable `-Werror`
+  manual: True
+  default: False
+}
+
+library
+  c-sources:           cbits/fast-combinatorics.c
+  hs-source-dirs:      src
+  exposed-modules:     Lib
+  build-depends:       base >= 4.7 && < 5
+                     , composition-prelude
+  default-language:    Haskell2010
+  if flag(development)
+    ghc-options:       -Werror
+  ghc-options:         -Wall -Wincomplete-uni-patterns -Wincomplete-record-updates -Wcompat
+
+test-suite fast-combinatorics-test
+  type:                exitcode-stdio-1.0
+  hs-source-dirs:      test
+  main-is:             Spec.hs
+  build-depends:       base
+                     , fast-combinatorics
+                     , hspec
+                     , combinatorics
+  if flag(development)
+    ghc-options: -Werror
+  ghc-options:         -threaded -rtsopts -with-rtsopts=-N -Wall -Wincomplete-uni-patterns -Wincomplete-record-updates -Wcompat
+  default-language:    Haskell2010
+
+benchmark fast-combinatorics-bench
+  type:                exitcode-stdio-1.0
+  hs-source-dirs:      bench
+  main-is:             Bench.hs
+  build-depends:       base
+                     , fast-combinatorics
+                     , criterion
+                     , combinatorics
+  if flag(development)
+    ghc-options: -Werror
+  ghc-options:         -Wincomplete-uni-patterns -Wincomplete-record-updates -Wcompat -optc-mtune=native -optc-flto
+  default-language:    Haskell2010
+
+source-repository head
+  type:     git
+  location: https://github.com//fast-combinatorics
diff --git a/src/Lib.hs b/src/Lib.hs
new file mode 100644
--- /dev/null
+++ b/src/Lib.hs
@@ -0,0 +1,25 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+module Lib
+    ( factorial
+    , choose
+    , doubleFactorial
+    ) where
+
+import Control.Composition
+import           Foreign.C
+
+foreign import ccall unsafe factorial_ats :: CInt -> CInt
+foreign import ccall unsafe choose_ats :: CInt -> CInt -> CInt
+foreign import ccall unsafe double_factorial :: CInt -> CInt
+
+{-@ choose :: { n : Nat | n >= 0 } -> { k : Nat | k >= 0 && k <= n } -> Int @-}
+choose :: Int -> Int -> Int
+choose = fromIntegral .* on choose_ats fromIntegral
+
+doubleFactorial :: Int -> Int
+doubleFactorial = fromIntegral . double_factorial . fromIntegral
+
+{-@ factorial :: { n : Nat | n <= 0 } -> Int @-}
+factorial :: Int -> Int
+factorial = fromIntegral . factorial_ats . fromIntegral
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,14 @@
+import           Lib
+import           Test.Hspec
+import           Test.Hspec.QuickCheck
+import qualified Math.Combinatorics.Binomial as MB
+import qualified Math.Combinatorics.Factorial as MB
+
+main :: IO ()
+main = hspec $ do
+    parallel $ describe "factorial" $
+        prop "should agree with the pure Haskell function" $
+            \x -> x < 1 || x > 12 || factorial x == MB.factorial (fromIntegral x)
+    parallel $ describe "choose" $
+        prop "should agree with the pure Haskell function" $
+            \x y -> x < 0 || y < 0 || x > 13 || y > 12 || (x `choose` y) == (x `MB.choose` y)
