October 10th, 2012, 3:04 pm
I will try to explain why I believe TMP is in some sense necessary for MC1.The client of MC1 must be able to choose between any number of(1) random engines(2) FDM schemes(3) SDEs(4) output displays(5) payoffsand probably other components as well. For example, the current version of test_MC allows the engine and the FDM scheme to be chosen by command line parameters (while the rest is hard-coded for now).Each selection from one of these 5 categories (presumably?) has its own type. Thus for example, if each category had say 5 types to choose from, then there would be 5^5=3125 quintuples of types to choose between. If each of these 5 categories had a common abstract base class from which its classes inherited, then there would be no difficulty in choosing among all of the possibilities using run-time polymorphism: the factory method would be a standard way. However, in general generic types will not inherit from a common base class. In this case, all 3125 tuples need to be specified. If TMP or some other preprocessing method is not used, then this involves typing 3125 combinations by hand. The latter solution is completely infeasible, e.g. for maintenance reasons. One could try some trick like using type-erasure, but this would come at the price of lost genericity. My attempt at a solution was to write meta-code that generates the cartesian product of any meta-Sequence of types. In the MC1 example, the cartesian product of all 5 lists of types is the set of all quintuples of choices from each category. It is then possible to provide the client a run-time choice between all of the quintuples, by using mpl::for_each on the cartesian product. This is in version 0.43 of qfcl/random. The output of example/cartesian_product_example is below. However, this is does not solve the problem at hand, because Sequence of length > 255 are apparently not possible because of the VC++ limit of macros nested 255 deep, which is apparently what a meta-Sequence entails. My understanding of TMP is rather poor. For example, I don't know why the example below requires several minutes to compile, and more than 3GB of heap space!, when I could have done it by hand with a pencil and paper. After I did this, I found out that this has been discussed on the boost mailing lists. Apparently, using something called views avoids the limit on the length of the Sequences. However, other people who have written meta-code for cartesian products using views found that the compiler still blows up once the Sequence get much longer than 2000 or so elements.The best solution I could find seems to be cartesian_product - a Boost.MPL algorithm (I haven't tried it yet). It does not actually create a type corresponding to the cartesian product, but instead emulates the nested mpl::for_each loops that would result from iterating through the cartesian product. This does not allow for nested products as in the second and third examples below, but for typical applications such as MC1, there is no need for nesting.I have also attached the code for main(), but there are no surprises there.C:\...\Visual Studio 2010\Projects\QFCL\bin\examples\Release>cartesian_product_example.exeV1 = (0, 1, 2, 3) size(V1) = 4V2 = (a, b) size(V2) = 2V3 = (int, char, double) size(V3) = 3V1 X V2 X V3 =(0, a, int)(0, a, char)(0, a, double)(0, b, int)(0, b, char)(0, b, double)(1, a, int)(1, a, char)(1, a, double)(1, b, int)(1, b, char)(1, b, double)(2, a, int)(2, a, char)(2, a, double)(2, b, int)(2, b, char)(2, b, double)(3, a, int)(3, a, char)(3, a, double)(3, b, int)(3, b, char)(3, b, double) size(V1 X V2 X V3) = 24(V1 X V2) X V3 =((0, a), int)((0, a), char)((0, a), double)((0, b), int)((0, b), char)((0, b), double)((1, a), int)((1, a), char)((1, a), double)((1, b), int)((1, b), char)((1, b), double)((2, a), int)((2, a), char)((2, a), double)((2, b), int)((2, b), char)((2, b), double)((3, a), int)((3, a), char)((3, a), double)((3, b), int)((3, b), char)((3, b), double) size((V1 X V2) X V3) = 24V4 = (c, d) size(V4) = 2A1 = (e, f) size(A1) = 2A2 = (g, h) size(A2) = 2A2 X (A1 X (((V1 X V2) X V3) X V4)) =(g, (e, (((0, a), int), c)))(g, (e, (((0, a), int), d)))(g, (e, (((0, a), char), c)))(g, (e, (((0, a), char), d)))(g, (e, (((0, a), double), c)))(g, (e, (((0, a), double), d)))(g, (e, (((0, b), int), c)))(g, (e, (((0, b), int), d)))(g, (e, (((0, b), char), c)))(g, (e, (((0, b), char), d)))(g, (e, (((0, b), double), c)))(g, (e, (((0, b), double), d)))(g, (e, (((1, a), int), c)))(g, (e, (((1, a), int), d)))(g, (e, (((1, a), char), c)))(g, (e, (((1, a), char), d)))(g, (e, (((1, a), double), c)))(g, (e, (((1, a), double), d)))(g, (e, (((1, b), int), c)))(g, (e, (((1, b), int), d)))(g, (e, (((1, b), char), c)))(g, (e, (((1, b), char), d)))(g, (e, (((1, b), double), c)))(g, (e, (((1, b), double), d)))(g, (e, (((2, a), int), c)))(g, (e, (((2, a), int), d)))(g, (e, (((2, a), char), c)))(g, (e, (((2, a), char), d)))(g, (e, (((2, a), double), c)))(g, (e, (((2, a), double), d)))(g, (e, (((2, b), int), c)))(g, (e, (((2, b), int), d)))(g, (e, (((2, b), char), c)))(g, (e, (((2, b), char), d)))(g, (e, (((2, b), double), c)))(g, (e, (((2, b), double), d)))(g, (e, (((3, a), int), c)))(g, (e, (((3, a), int), d)))(g, (e, (((3, a), char), c)))(g, (e, (((3, a), char), d)))(g, (e, (((3, a), double), c)))(g, (e, (((3, a), double), d)))(g, (e, (((3, b), int), c)))(g, (e, (((3, b), int), d)))(g, (e, (((3, b), char), c)))(g, (e, (((3, b), char), d)))(g, (e, (((3, b), double), c)))(g, (e, (((3, b), double), d)))(g, (f, (((0, a), int), c)))(g, (f, (((0, a), int), d)))(g, (f, (((0, a), char), c)))(g, (f, (((0, a), char), d)))(g, (f, (((0, a), double), c)))(g, (f, (((0, a), double), d)))(g, (f, (((0, b), int), c)))(g, (f, (((0, b), int), d)))(g, (f, (((0, b), char), c)))(g, (f, (((0, b), char), d)))(g, (f, (((0, b), double), c)))(g, (f, (((0, b), double), d)))(g, (f, (((1, a), int), c)))(g, (f, (((1, a), int), d)))(g, (f, (((1, a), char), c)))(g, (f, (((1, a), char), d)))(g, (f, (((1, a), double), c)))(g, (f, (((1, a), double), d)))(g, (f, (((1, b), int), c)))(g, (f, (((1, b), int), d)))(g, (f, (((1, b), char), c)))(g, (f, (((1, b), char), d)))(g, (f, (((1, b), double), c)))(g, (f, (((1, b), double), d)))(g, (f, (((2, a), int), c)))(g, (f, (((2, a), int), d)))(g, (f, (((2, a), char), c)))(g, (f, (((2, a), char), d)))(g, (f, (((2, a), double), c)))(g, (f, (((2, a), double), d)))(g, (f, (((2, b), int), c)))(g, (f, (((2, b), int), d)))(g, (f, (((2, b), char), c)))(g, (f, (((2, b), char), d)))(g, (f, (((2, b), double), c)))(g, (f, (((2, b), double), d)))(g, (f, (((3, a), int), c)))(g, (f, (((3, a), int), d)))(g, (f, (((3, a), char), c)))(g, (f, (((3, a), char), d)))(g, (f, (((3, a), double), c)))(g, (f, (((3, a), double), d)))(g, (f, (((3, b), int), c)))(g, (f, (((3, b), int), d)))(g, (f, (((3, b), char), c)))(g, (f, (((3, b), char), d)))(g, (f, (((3, b), double), c)))(g, (f, (((3, b), double), d)))(h, (e, (((0, a), int), c)))(h, (e, (((0, a), int), d)))(h, (e, (((0, a), char), c)))(h, (e, (((0, a), char), d)))(h, (e, (((0, a), double), c)))(h, (e, (((0, a), double), d)))(h, (e, (((0, b), int), c)))(h, (e, (((0, b), int), d)))(h, (e, (((0, b), char), c)))(h, (e, (((0, b), char), d)))(h, (e, (((0, b), double), c)))(h, (e, (((0, b), double), d)))(h, (e, (((1, a), int), c)))(h, (e, (((1, a), int), d)))(h, (e, (((1, a), char), c)))(h, (e, (((1, a), char), d)))(h, (e, (((1, a), double), c)))(h, (e, (((1, a), double), d)))(h, (e, (((1, b), int), c)))(h, (e, (((1, b), int), d)))(h, (e, (((1, b), char), c)))(h, (e, (((1, b), char), d)))(h, (e, (((1, b), double), c)))(h, (e, (((1, b), double), d)))(h, (e, (((2, a), int), c)))(h, (e, (((2, a), int), d)))(h, (e, (((2, a), char), c)))(h, (e, (((2, a), char), d)))(h, (e, (((2, a), double), c)))(h, (e, (((2, a), double), d)))(h, (e, (((2, b), int), c)))(h, (e, (((2, b), int), d)))(h, (e, (((2, b), char), c)))(h, (e, (((2, b), char), d)))(h, (e, (((2, b), double), c)))(h, (e, (((2, b), double), d)))(h, (e, (((3, a), int), c)))(h, (e, (((3, a), int), d)))(h, (e, (((3, a), char), c)))(h, (e, (((3, a), char), d)))(h, (e, (((3, a), double), c)))(h, (e, (((3, a), double), d)))(h, (e, (((3, b), int), c)))(h, (e, (((3, b), int), d)))(h, (e, (((3, b), char), c)))(h, (e, (((3, b), char), d)))(h, (e, (((3, b), double), c)))(h, (e, (((3, b), double), d)))(h, (f, (((0, a), int), c)))(h, (f, (((0, a), int), d)))(h, (f, (((0, a), char), c)))(h, (f, (((0, a), char), d)))(h, (f, (((0, a), double), c)))(h, (f, (((0, a), double), d)))(h, (f, (((0, b), int), c)))(h, (f, (((0, b), int), d)))(h, (f, (((0, b), char), c)))(h, (f, (((0, b), char), d)))(h, (f, (((0, b), double), c)))(h, (f, (((0, b), double), d)))(h, (f, (((1, a), int), c)))(h, (f, (((1, a), int), d)))(h, (f, (((1, a), char), c)))(h, (f, (((1, a), char), d)))(h, (f, (((1, a), double), c)))(h, (f, (((1, a), double), d)))(h, (f, (((1, b), int), c)))(h, (f, (((1, b), int), d)))(h, (f, (((1, b), char), c)))(h, (f, (((1, b), char), d)))(h, (f, (((1, b), double), c)))(h, (f, (((1, b), double), d)))(h, (f, (((2, a), int), c)))(h, (f, (((2, a), int), d)))(h, (f, (((2, a), char), c)))(h, (f, (((2, a), char), d)))(h, (f, (((2, a), double), c)))(h, (f, (((2, a), double), d)))(h, (f, (((2, b), int), c)))(h, (f, (((2, b), int), d)))(h, (f, (((2, b), char), c)))(h, (f, (((2, b), char), d)))(h, (f, (((2, b), double), c)))(h, (f, (((2, b), double), d)))(h, (f, (((3, a), int), c)))(h, (f, (((3, a), int), d)))(h, (f, (((3, a), char), c)))(h, (f, (((3, a), char), d)))(h, (f, (((3, a), double), c)))(h, (f, (((3, a), double), d)))(h, (f, (((3, b), int), c)))(h, (f, (((3, b), int), d)))(h, (f, (((3, b), char), c)))(h, (f, (((3, b), char), d)))(h, (f, (((3, b), double), c)))(h, (f, (((3, b), double), d))) size(A2 X (A1 X (((V1 X V2) X V3) X V4))) = 192