<commit_before>
#include "../msdfgen.h"

#include <vector>
#include "edge-selectors.h"
#include "contour-combiners.h"

namespace msdfgen {

template <typename DistanceType>
class DistancePixelConversion;

template <>
class DistancePixelConversion<double> {
public:
    typedef float PixelType;
    inline static PixelType convert(double distance, double range) {
        return PixelType(distance/range+.5);
    }
};

template <>
class DistancePixelConversion<MultiDistance> {
public:
    typedef FloatRGB PixelType;
    inline static PixelType convert(const MultiDistance &distance, double range) {
        PixelType pixel;
        pixel.r = float(distance.r/range+.5);
        pixel.g = float(distance.g/range+.5);
        pixel.b = float(distance.b/range+.5);
        return pixel;
    }
};

template <class ContourCombiner>
void generateDistanceField(Bitmap<typename DistancePixelConversion<typename ContourCombiner::DistanceType>::PixelType> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate) {
    int w = output.width(), h = output.height();

#ifdef MSDFGEN_USE_OPENMP
    #pragma omp parallel
#endif
    {
        ContourCombiner contourCombiner(shape);
        Point2 p;
#ifdef MSDFGEN_USE_OPENMP
        #pragma omp for
#endif
        for (int y = 0; y < h; ++y) {
            int row = shape.inverseYAxis ? h-y-1 : y;
            p.y = (y+.5)/scale.y-translate.y;
            for (int x = 0; x < w; ++x) {
                p.x = (x+.5)/scale.x-translate.x;

                contourCombiner.reset(p);

                for (std::vector<Contour>::const_iterator contour = shape.contours.begin(); contour != shape.contours.end(); ++contour) {
                    if (!contour->edges.empty()) {
                        ContourCombiner::EdgeSelectorType edgeSelector(p);

                        const EdgeSegment *prevEdge = contour->edges.size() >= 2 ? *(contour->edges.end()-2) : *contour->edges.begin();
                        const EdgeSegment *curEdge = contour->edges.back();
                        for (std::vector<EdgeHolder>::const_iterator edge = contour->edges.begin(); edge != contour->edges.end(); ++edge) {
                            const EdgeSegment *nextEdge = *edge;
                            edgeSelector.addEdge(prevEdge, curEdge, nextEdge);
                            prevEdge = curEdge;
                            curEdge = nextEdge;
                        }

                        contourCombiner.setContourEdge(int(contour-shape.contours.begin()), edgeSelector);
                    }
                }

                ContourCombiner::DistanceType distance = contourCombiner.distance();
                output(x, row) = DistancePixelConversion<ContourCombiner::DistanceType>::convert(distance, range);
            }
        }
    }
}

void generateSDF(Bitmap<float> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate, bool overlapSupport) {
    if (overlapSupport)
        generateDistanceField<OverlappingContourCombiner<TrueDistanceSelector> >(output, shape, range, scale, translate);
    else
        generateDistanceField<SimpleContourCombiner<TrueDistanceSelector> >(output, shape, range, scale, translate);
}

void generatePseudoSDF(Bitmap<float> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate, bool overlapSupport) {
    if (overlapSupport)
        generateDistanceField<OverlappingContourCombiner<PseudoDistanceSelector> >(output, shape, range, scale, translate);
    else
        generateDistanceField<SimpleContourCombiner<PseudoDistanceSelector> >(output, shape, range, scale, translate);
}

void generateMSDF(Bitmap<FloatRGB> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate, double edgeThreshold, bool overlapSupport) {
    if (overlapSupport)
        generateDistanceField<OverlappingContourCombiner<MultiDistanceSelector> >(output, shape, range, scale, translate);
    else
        generateDistanceField<SimpleContourCombiner<MultiDistanceSelector> >(output, shape, range, scale, translate);
    if (edgeThreshold > 0)
        msdfErrorCorrection(output, edgeThreshold/(scale*range));
}

inline static bool detectClash(const FloatRGB &a, const FloatRGB &b, double threshold) {
    // Sort channels so that pairs (a0, b0), (a1, b1), (a2, b2) go from biggest to smallest absolute difference
    float a0 = a.r, a1 = a.g, a2 = a.b;
    float b0 = b.r, b1 = b.g, b2 = b.b;
    float tmp;
    if (fabsf(b0-a0) < fabsf(b1-a1)) {
        tmp = a0, a0 = a1, a1 = tmp;
        tmp = b0, b0 = b1, b1 = tmp;
    }
    if (fabsf(b1-a1) < fabsf(b2-a2)) {
        tmp = a1, a1 = a2, a2 = tmp;
        tmp = b1, b1 = b2, b2 = tmp;
        if (fabsf(b0-a0) < fabsf(b1-a1)) {
            tmp = a0, a0 = a1, a1 = tmp;
            tmp = b0, b0 = b1, b1 = tmp;
        }
    }
    return (fabsf(b1-a1) >= threshold) &&
        !(b0 == b1 && b0 == b2) && // Ignore if other pixel has been equalized
        fabsf(a2-.5f) >= fabsf(b2-.5f); // Out of the pair, only flag the pixel farther from a shape edge
}

void msdfErrorCorrection(Bitmap<FloatRGB> &output, const Vector2 &threshold) {
    std::vector<std::pair<int, int> > clashes;
    int w = output.width(), h = output.height();
    for (int y = 0; y < h; ++y)
        for (int x = 0; x < w; ++x) {
            if (
                (x > 0 && detectClash(output(x, y), output(x-1, y), threshold.x)) ||
                (x < w-1 && detectClash(output(x, y), output(x+1, y), threshold.x)) ||
                (y > 0 && detectClash(output(x, y), output(x, y-1), threshold.y)) ||
                (y < h-1 && detectClash(output(x, y), output(x, y+1), threshold.y))
            )
                clashes.push_back(std::make_pair(x, y));
        }
    for (std::vector<std::pair<int, int> >::const_iterator clash = clashes.begin(); clash != clashes.end(); ++clash) {
        FloatRGB &pixel = output(clash->first, clash->second);
        float med = median(pixel.r, pixel.g, pixel.b);
        pixel.r = med, pixel.g = med, pixel.b = med;
    }
#ifndef MSDFGEN_NO_DIAGONAL_CLASH_DETECTION
    clashes.clear();
    for (int y = 0; y < h; ++y)
        for (int x = 0; x < w; ++x) {
            if (
                (x > 0 && y > 0 && detectClash(output(x, y), output(x-1, y-1), threshold.x+threshold.y)) ||
                (x < w-1 && y > 0 && detectClash(output(x, y), output(x+1, y-1), threshold.x+threshold.y)) ||
                (x > 0 && y < h-1 && detectClash(output(x, y), output(x-1, y+1), threshold.x+threshold.y)) ||
                (x < w-1 && y < h-1 && detectClash(output(x, y), output(x+1, y+1), threshold.x+threshold.y))
            )
                clashes.push_back(std::make_pair(x, y));
        }
    for (std::vector<std::pair<int, int> >::const_iterator clash = clashes.begin(); clash != clashes.end(); ++clash) {
        FloatRGB &pixel = output(clash->first, clash->second);
        float med = median(pixel.r, pixel.g, pixel.b);
        pixel.r = med, pixel.g = med, pixel.b = med;
    }
#endif
}

// Legacy version

void generateSDF_legacy(Bitmap<float> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate) {
    int w = output.width(), h = output.height();
#ifdef MSDFGEN_USE_OPENMP
    #pragma omp parallel for
#endif
    for (int y = 0; y < h; ++y) {
        int row = shape.inverseYAxis ? h-y-1 : y;
        for (int x = 0; x < w; ++x) {
            double dummy;
            Point2 p = Vector2(x+.5, y+.5)/scale-translate;
            SignedDistance minDistance;
            for (std::vector<Contour>::const_iterator contour = shape.contours.begin(); contour != shape.contours.end(); ++contour)
                for (std::vector<EdgeHolder>::const_iterator edge = contour->edges.begin(); edge != contour->edges.end(); ++edge) {
                    SignedDistance distance = (*edge)->signedDistance(p, dummy);
                    if (distance < minDistance)
                        minDistance = distance;
                }
            output(x, row) = float(minDistance.distance/range+.5);
        }
    }
}

void generatePseudoSDF_legacy(Bitmap<float> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate) {
    int w = output.width(), h = output.height();
#ifdef MSDFGEN_USE_OPENMP
    #pragma omp parallel for
#endif
    for (int y = 0; y < h; ++y) {
        int row = shape.inverseYAxis ? h-y-1 : y;
        for (int x = 0; x < w; ++x) {
            Point2 p = Vector2(x+.5, y+.5)/scale-translate;
            SignedDistance minDistance;
            const EdgeHolder *nearEdge = NULL;
            double nearParam = 0;
            for (std::vector<Contour>::const_iterator contour = shape.contours.begin(); contour != shape.contours.end(); ++contour)
                for (std::vector<EdgeHolder>::const_iterator edge = contour->edges.begin(); edge != contour->edges.end(); ++edge) {
                    double param;
                    SignedDistance distance = (*edge)->signedDistance(p, param);
                    if (distance < minDistance) {
                        minDistance = distance;
                        nearEdge = &*edge;
                        nearParam = param;
                    }
                }
            if (nearEdge)
                (*nearEdge)->distanceToPseudoDistance(minDistance, p, nearParam);
            output(x, row) = float(minDistance.distance/range+.5);
        }
    }
}

void generateMSDF_legacy(Bitmap<FloatRGB> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate, double edgeThreshold) {
    int w = output.width(), h = output.height();
#ifdef MSDFGEN_USE_OPENMP
    #pragma omp parallel for
#endif
    for (int y = 0; y < h; ++y) {
        int row = shape.inverseYAxis ? h-y-1 : y;
        for (int x = 0; x < w; ++x) {
            Point2 p = Vector2(x+.5, y+.5)/scale-translate;

            struct {
                SignedDistance minDistance;
                const EdgeHolder *nearEdge;
                double nearParam;
            } r, g, b;
            r.nearEdge = g.nearEdge = b.nearEdge = NULL;
            r.nearParam = g.nearParam = b.nearParam = 0;

            for (std::vector<Contour>::const_iterator contour = shape.contours.begin(); contour != shape.contours.end(); ++contour)
                for (std::vector<EdgeHolder>::const_iterator edge = contour->edges.begin(); edge != contour->edges.end(); ++edge) {
                    double param;
                    SignedDistance distance = (*edge)->signedDistance(p, param);
                    if ((*edge)->color&RED && distance < r.minDistance) {
                        r.minDistance = distance;
                        r.nearEdge = &*edge;
                        r.nearParam = param;
                    }
                    if ((*edge)->color&GREEN && distance < g.minDistance) {
                        g.minDistance = distance;
                        g.nearEdge = &*edge;
                        g.nearParam = param;
                    }
                    if ((*edge)->color&BLUE && distance < b.minDistance) {
                        b.minDistance = distance;
                        b.nearEdge = &*edge;
                        b.nearParam = param;
                    }
                }

            if (r.nearEdge)
                (*r.nearEdge)->distanceToPseudoDistance(r.minDistance, p, r.nearParam);
            if (g.nearEdge)
                (*g.nearEdge)->distanceToPseudoDistance(g.minDistance, p, g.nearParam);
            if (b.nearEdge)
                (*b.nearEdge)->distanceToPseudoDistance(b.minDistance, p, b.nearParam);
            output(x, row).r = float(r.minDistance.distance/range+.5);
            output(x, row).g = float(g.minDistance.distance/range+.5);
            output(x, row).b = float(b.minDistance.distance/range+.5);
        }
    }

    if (edgeThreshold > 0)
        msdfErrorCorrection(output, edgeThreshold/(scale*range));
}

}
<commit_msg>Add missing typenames for dependent types<commit_after>
#include "../msdfgen.h"

#include <vector>
#include "edge-selectors.h"
#include "contour-combiners.h"

namespace msdfgen {

template <typename DistanceType>
class DistancePixelConversion;

template <>
class DistancePixelConversion<double> {
public:
    typedef float PixelType;
    inline static PixelType convert(double distance, double range) {
        return PixelType(distance/range+.5);
    }
};

template <>
class DistancePixelConversion<MultiDistance> {
public:
    typedef FloatRGB PixelType;
    inline static PixelType convert(const MultiDistance &distance, double range) {
        PixelType pixel;
        pixel.r = float(distance.r/range+.5);
        pixel.g = float(distance.g/range+.5);
        pixel.b = float(distance.b/range+.5);
        return pixel;
    }
};

template <class ContourCombiner>
void generateDistanceField(Bitmap<typename DistancePixelConversion<typename ContourCombiner::DistanceType>::PixelType> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate) {
    int w = output.width(), h = output.height();

#ifdef MSDFGEN_USE_OPENMP
    #pragma omp parallel
#endif
    {
        ContourCombiner contourCombiner(shape);
        Point2 p;
#ifdef MSDFGEN_USE_OPENMP
        #pragma omp for
#endif
        for (int y = 0; y < h; ++y) {
            int row = shape.inverseYAxis ? h-y-1 : y;
            p.y = (y+.5)/scale.y-translate.y;
            for (int x = 0; x < w; ++x) {
                p.x = (x+.5)/scale.x-translate.x;

                contourCombiner.reset(p);

                for (std::vector<Contour>::const_iterator contour = shape.contours.begin(); contour != shape.contours.end(); ++contour) {
                    if (!contour->edges.empty()) {
                        typename ContourCombiner::EdgeSelectorType edgeSelector(p);

                        const EdgeSegment *prevEdge = contour->edges.size() >= 2 ? *(contour->edges.end()-2) : *contour->edges.begin();
                        const EdgeSegment *curEdge = contour->edges.back();
                        for (std::vector<EdgeHolder>::const_iterator edge = contour->edges.begin(); edge != contour->edges.end(); ++edge) {
                            const EdgeSegment *nextEdge = *edge;
                            edgeSelector.addEdge(prevEdge, curEdge, nextEdge);
                            prevEdge = curEdge;
                            curEdge = nextEdge;
                        }

                        contourCombiner.setContourEdge(int(contour-shape.contours.begin()), edgeSelector);
                    }
                }

                typename ContourCombiner::DistanceType distance = contourCombiner.distance();
                output(x, row) = DistancePixelConversion<typename ContourCombiner::DistanceType>::convert(distance, range);
            }
        }
    }
}

void generateSDF(Bitmap<float> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate, bool overlapSupport) {
    if (overlapSupport)
        generateDistanceField<OverlappingContourCombiner<TrueDistanceSelector> >(output, shape, range, scale, translate);
    else
        generateDistanceField<SimpleContourCombiner<TrueDistanceSelector> >(output, shape, range, scale, translate);
}

void generatePseudoSDF(Bitmap<float> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate, bool overlapSupport) {
    if (overlapSupport)
        generateDistanceField<OverlappingContourCombiner<PseudoDistanceSelector> >(output, shape, range, scale, translate);
    else
        generateDistanceField<SimpleContourCombiner<PseudoDistanceSelector> >(output, shape, range, scale, translate);
}

void generateMSDF(Bitmap<FloatRGB> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate, double edgeThreshold, bool overlapSupport) {
    if (overlapSupport)
        generateDistanceField<OverlappingContourCombiner<MultiDistanceSelector> >(output, shape, range, scale, translate);
    else
        generateDistanceField<SimpleContourCombiner<MultiDistanceSelector> >(output, shape, range, scale, translate);
    if (edgeThreshold > 0)
        msdfErrorCorrection(output, edgeThreshold/(scale*range));
}

inline static bool detectClash(const FloatRGB &a, const FloatRGB &b, double threshold) {
    // Sort channels so that pairs (a0, b0), (a1, b1), (a2, b2) go from biggest to smallest absolute difference
    float a0 = a.r, a1 = a.g, a2 = a.b;
    float b0 = b.r, b1 = b.g, b2 = b.b;
    float tmp;
    if (fabsf(b0-a0) < fabsf(b1-a1)) {
        tmp = a0, a0 = a1, a1 = tmp;
        tmp = b0, b0 = b1, b1 = tmp;
    }
    if (fabsf(b1-a1) < fabsf(b2-a2)) {
        tmp = a1, a1 = a2, a2 = tmp;
        tmp = b1, b1 = b2, b2 = tmp;
        if (fabsf(b0-a0) < fabsf(b1-a1)) {
            tmp = a0, a0 = a1, a1 = tmp;
            tmp = b0, b0 = b1, b1 = tmp;
        }
    }
    return (fabsf(b1-a1) >= threshold) &&
        !(b0 == b1 && b0 == b2) && // Ignore if other pixel has been equalized
        fabsf(a2-.5f) >= fabsf(b2-.5f); // Out of the pair, only flag the pixel farther from a shape edge
}

void msdfErrorCorrection(Bitmap<FloatRGB> &output, const Vector2 &threshold) {
    std::vector<std::pair<int, int> > clashes;
    int w = output.width(), h = output.height();
    for (int y = 0; y < h; ++y)
        for (int x = 0; x < w; ++x) {
            if (
                (x > 0 && detectClash(output(x, y), output(x-1, y), threshold.x)) ||
                (x < w-1 && detectClash(output(x, y), output(x+1, y), threshold.x)) ||
                (y > 0 && detectClash(output(x, y), output(x, y-1), threshold.y)) ||
                (y < h-1 && detectClash(output(x, y), output(x, y+1), threshold.y))
            )
                clashes.push_back(std::make_pair(x, y));
        }
    for (std::vector<std::pair<int, int> >::const_iterator clash = clashes.begin(); clash != clashes.end(); ++clash) {
        FloatRGB &pixel = output(clash->first, clash->second);
        float med = median(pixel.r, pixel.g, pixel.b);
        pixel.r = med, pixel.g = med, pixel.b = med;
    }
#ifndef MSDFGEN_NO_DIAGONAL_CLASH_DETECTION
    clashes.clear();
    for (int y = 0; y < h; ++y)
        for (int x = 0; x < w; ++x) {
            if (
                (x > 0 && y > 0 && detectClash(output(x, y), output(x-1, y-1), threshold.x+threshold.y)) ||
                (x < w-1 && y > 0 && detectClash(output(x, y), output(x+1, y-1), threshold.x+threshold.y)) ||
                (x > 0 && y < h-1 && detectClash(output(x, y), output(x-1, y+1), threshold.x+threshold.y)) ||
                (x < w-1 && y < h-1 && detectClash(output(x, y), output(x+1, y+1), threshold.x+threshold.y))
            )
                clashes.push_back(std::make_pair(x, y));
        }
    for (std::vector<std::pair<int, int> >::const_iterator clash = clashes.begin(); clash != clashes.end(); ++clash) {
        FloatRGB &pixel = output(clash->first, clash->second);
        float med = median(pixel.r, pixel.g, pixel.b);
        pixel.r = med, pixel.g = med, pixel.b = med;
    }
#endif
}

// Legacy version

void generateSDF_legacy(Bitmap<float> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate) {
    int w = output.width(), h = output.height();
#ifdef MSDFGEN_USE_OPENMP
    #pragma omp parallel for
#endif
    for (int y = 0; y < h; ++y) {
        int row = shape.inverseYAxis ? h-y-1 : y;
        for (int x = 0; x < w; ++x) {
            double dummy;
            Point2 p = Vector2(x+.5, y+.5)/scale-translate;
            SignedDistance minDistance;
            for (std::vector<Contour>::const_iterator contour = shape.contours.begin(); contour != shape.contours.end(); ++contour)
                for (std::vector<EdgeHolder>::const_iterator edge = contour->edges.begin(); edge != contour->edges.end(); ++edge) {
                    SignedDistance distance = (*edge)->signedDistance(p, dummy);
                    if (distance < minDistance)
                        minDistance = distance;
                }
            output(x, row) = float(minDistance.distance/range+.5);
        }
    }
}

void generatePseudoSDF_legacy(Bitmap<float> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate) {
    int w = output.width(), h = output.height();
#ifdef MSDFGEN_USE_OPENMP
    #pragma omp parallel for
#endif
    for (int y = 0; y < h; ++y) {
        int row = shape.inverseYAxis ? h-y-1 : y;
        for (int x = 0; x < w; ++x) {
            Point2 p = Vector2(x+.5, y+.5)/scale-translate;
            SignedDistance minDistance;
            const EdgeHolder *nearEdge = NULL;
            double nearParam = 0;
            for (std::vector<Contour>::const_iterator contour = shape.contours.begin(); contour != shape.contours.end(); ++contour)
                for (std::vector<EdgeHolder>::const_iterator edge = contour->edges.begin(); edge != contour->edges.end(); ++edge) {
                    double param;
                    SignedDistance distance = (*edge)->signedDistance(p, param);
                    if (distance < minDistance) {
                        minDistance = distance;
                        nearEdge = &*edge;
                        nearParam = param;
                    }
                }
            if (nearEdge)
                (*nearEdge)->distanceToPseudoDistance(minDistance, p, nearParam);
            output(x, row) = float(minDistance.distance/range+.5);
        }
    }
}

void generateMSDF_legacy(Bitmap<FloatRGB> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate, double edgeThreshold) {
    int w = output.width(), h = output.height();
#ifdef MSDFGEN_USE_OPENMP
    #pragma omp parallel for
#endif
    for (int y = 0; y < h; ++y) {
        int row = shape.inverseYAxis ? h-y-1 : y;
        for (int x = 0; x < w; ++x) {
            Point2 p = Vector2(x+.5, y+.5)/scale-translate;

            struct {
                SignedDistance minDistance;
                const EdgeHolder *nearEdge;
                double nearParam;
            } r, g, b;
            r.nearEdge = g.nearEdge = b.nearEdge = NULL;
            r.nearParam = g.nearParam = b.nearParam = 0;

            for (std::vector<Contour>::const_iterator contour = shape.contours.begin(); contour != shape.contours.end(); ++contour)
                for (std::vector<EdgeHolder>::const_iterator edge = contour->edges.begin(); edge != contour->edges.end(); ++edge) {
                    double param;
                    SignedDistance distance = (*edge)->signedDistance(p, param);
                    if ((*edge)->color&RED && distance < r.minDistance) {
                        r.minDistance = distance;
                        r.nearEdge = &*edge;
                        r.nearParam = param;
                    }
                    if ((*edge)->color&GREEN && distance < g.minDistance) {
                        g.minDistance = distance;
                        g.nearEdge = &*edge;
                        g.nearParam = param;
                    }
                    if ((*edge)->color&BLUE && distance < b.minDistance) {
                        b.minDistance = distance;
                        b.nearEdge = &*edge;
                        b.nearParam = param;
                    }
                }

            if (r.nearEdge)
                (*r.nearEdge)->distanceToPseudoDistance(r.minDistance, p, r.nearParam);
            if (g.nearEdge)
                (*g.nearEdge)->distanceToPseudoDistance(g.minDistance, p, g.nearParam);
            if (b.nearEdge)
                (*b.nearEdge)->distanceToPseudoDistance(b.minDistance, p, b.nearParam);
            output(x, row).r = float(r.minDistance.distance/range+.5);
            output(x, row).g = float(g.minDistance.distance/range+.5);
            output(x, row).b = float(b.minDistance.distance/range+.5);
        }
    }

    if (edgeThreshold > 0)
        msdfErrorCorrection(output, edgeThreshold/(scale*range));
}

}
<|endoftext|>


<commit_before>#include <fcntl.h>
#include <getopt.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <wait.h>

#include <iostream>
#include <string>
#include <vector>

#include "../utils/utils.h"
#include "Tester.h"
#include "../tests/BaseTestCase.h"

#define TEST_SO_PATH "tests/"
#define PERMUTER_SO_PATH "permuter/"
// TODO(ashmrtn): Find a good delay time to use for tests.
#define TEST_DIRTY_EXPIRE_TIME "500"
#define WRITE_DELAY 30
#define MOUNT_DELAY WRITE_DELAY

#define OPTS_STRING "d:l:m:np:r:st:v"

using std::cerr;
using std::cout;
using std::endl;
using std::string;
using fs_testing::Tester;

static const option long_options[] = {
  {"no-snap", no_argument, NULL, 's'},
  {"dry-run", no_argument, NULL, 'n'},
  {"verbose", no_argument, NULL, 'v'},
  {"fs-type", required_argument, NULL, 't'},
  {"test-dev", required_argument, NULL, 'd'},
  {"log-file", required_argument, NULL, 'l'},
  {"reload-log-file", required_argument, NULL, 'r'},
  {"mount-opts", required_argument, NULL, 'm'},
  {"permuter", required_argument, NULL, 'p'},
  {0, 0, 0, 0},
};

int main(int argc, char** argv) {
  string dirty_expire_time_centisecs(TEST_DIRTY_EXPIRE_TIME);
  unsigned long int test_sleep_delay = WRITE_DELAY;
  string fs_type("ext4");
  string test_dev("/dev/ram0");
  string mount_opts("");
  string log_file_save("");
  string log_file_load("");
  string permuter(PERMUTER_SO_PATH "RandomPermuter.so");
  bool dry_run = false;
  bool no_lvm = false;
  bool no_snap = false;
  bool verbose = false;

  int option_idx = 0;

  // Parse command line arguments.
  for (int c = getopt_long(argc, argv, OPTS_STRING, long_options, &option_idx);
        c != -1;
        c = getopt_long(argc, argv, OPTS_STRING, long_options, &option_idx)) {
    switch (c) {
      case 'd':
        test_dev = string(optarg);
        break;
      case 'l':
        log_file_save = string(optarg);
        break;
      case 'm':
        mount_opts = string(optarg);
        break;
      case 'n':
        dry_run = 1;
        break;
      case 'p':
        permuter = string(optarg);
        break;
      case 'r':
        log_file_load = string(optarg);
        break;
      case 's':
        no_snap = 1;
        dry_run = 1;
        break;
      case 't':
        fs_type = string(optarg);
        break;
      case 'v':
        verbose = true;
        break;
      case '?':
      default:
        return -1;
    }
  }

  const unsigned int test_case_idx = optind;

  if (test_case_idx == argc) {
    cerr << "Please give a .so test case to load" << endl;
    return -1;
  }

  Tester test_harness(verbose);
  test_harness.set_fs_type(fs_type);
  test_harness.set_device(test_dev);

  // Load the class being tested.
  cout << "Loading test case" << endl;
  if (test_harness.test_load_class(argv[test_case_idx]) != SUCCESS) {
    test_harness.cleanup_harness();
      return -1;
  }

  // Load the permuter to use for the test.
  // TODO(ashmrtn): Consider making a line in the test file which specifies the
  // permuter to use?
  cout << "Loading permuter" << endl;
  if (test_harness.permuter_load_class(permuter.c_str()) != SUCCESS) {
    test_harness.cleanup_harness();
      return -1;
  }

  // Update dirty_expire_time.
  cout << "Updating dirty_expire_time_centisecs" << endl;
  const char* old_expire_time =
    test_harness.update_dirty_expire_time(dirty_expire_time_centisecs.c_str());
  if (old_expire_time == NULL) {
    cerr << "Error updating dirty_expire_time_centisecs" << endl;
    test_harness.cleanup_harness();
    return -1;
  }

  // Partition drive.
  // TODO(ashmrtn): Consider making a flag for this?
  cout << "Wiping test device" << endl;
  if (test_harness.wipe_partitions() != SUCCESS) {
    cerr << "Error wiping paritions on test device" << endl;
    test_harness.cleanup_harness();
    return -1;
  }

  // Run the normal test setup stuff if we don't have a log file.
  if (log_file_load.empty()) {

    // Create a new partition table on test device.
    cout << "Partitioning test drive" << endl;
    if (test_harness.partition_drive() != SUCCESS) {
      test_harness.cleanup_harness();
      return -1;
    }

    // Format test drive to desired type.
    cout << "Formatting test drive" << endl;
    if (test_harness.format_drive() != SUCCESS) {
      cerr << "Error formatting test drive" << endl;
      test_harness.cleanup_harness();
      return -1;
    }

    // Mount test file system for pre-test setup.
    cout << "Mounting test file system for pre-test setup\n";
    if (test_harness.mount_device_raw(mount_opts.c_str()) != SUCCESS) {
      cerr << "Error mounting test device" << endl;
      test_harness.cleanup_harness();
      return -1;
    }

    // Run pre-test setup stuff.
    cout << "Running pre-test setup\n";
    {
      const pid_t child = fork();
      if (child < 0) {
        cerr << "Error creating child process to run pre-test setup\n";
        test_harness.cleanup_harness();
      } else if (child != 0) {
        // Parent process should wait for child to terminate before proceeding.
        pid_t status;
        wait(&status);
        if (status != 0) {
          cerr << "Error in pre-test setup\n";
          test_harness.cleanup_harness();
        }
      } else {
        return test_harness.test_setup();
      }
    }

    // Unmount the test file system after pre-test setup.
    cout << "Unmounting test file system after pre-test setup\n";
    if (test_harness.umount_device() != SUCCESS) {
      test_harness.cleanup_harness();
      return -1;
    }

    // Create snapshot of disk for testing.
    if (!no_snap) {
      cout << "Making new snapshot\n";
      if (test_harness.clone_device() != SUCCESS) {
        test_harness.cleanup_harness();
        return -1;
      }

      // If we're logging this test run then also save the snapshot.
      if (!log_file_save.empty()) {
        cout << "Saving snapshot to log file" << endl;
        if (test_harness.log_snapshot_save(log_file_save + "_snap")
            != SUCCESS) {
          test_harness.cleanup_harness();
          return -1;
        }
      }
    }
  } else {
    // Load the snapshot in the log file and then write it to disk.
    cout << "Loading saved snapshot" << endl;
    if (test_harness.log_snapshot_load(log_file_load + "_snap") != SUCCESS) {
      test_harness.cleanup_harness();
      return -1;
    }
    cout << "Restoring disk snapshot" << endl;
    if (test_harness.clone_device_restore(true) != SUCCESS) {
      test_harness.cleanup_harness();
      return -1;
    }
  }

  // TODO(ashmrtn): Consider making a flag for this?
  cout << "Clearing caches" << endl;
  if (test_harness.clear_caches() != SUCCESS) {
    cerr << "Error clearing caches" << endl;
    test_harness.cleanup_harness();
    return -1;
  }

  // No log file given so run the test profile.
  if (log_file_load.empty()) {

    // Insert the disk block wrapper into the kernel.
    cout << "Inserting wrapper module into kernel\n";
    if (test_harness.insert_wrapper() != SUCCESS) {
      cerr << "Error inserting kernel wrapper module\n";
      test_harness.cleanup_harness();
      return -1;
    }

    // Mount the file system under the wrapper module for profiling.
    cout << "Mounting wrapper file system\n";
    if (test_harness.mount_wrapper_device(mount_opts.c_str()) != SUCCESS) {
      cerr << "Error mounting wrapper file system\n";
      test_harness.cleanup_harness();
      return -1;
    }

    cout << "Sleeping after mount" << endl;
    unsigned int to_sleep = MOUNT_DELAY;
    do {
      to_sleep = sleep(to_sleep);
    } while (to_sleep > 0);

    // Get access to wrapper module ioctl functions via FD.
    cout << "Getting wrapper device ioctl fd\n";
    if (test_harness.get_wrapper_ioctl() != SUCCESS) {
      cerr << "Error opening device file\n";
      test_harness.cleanup_harness();
      return -1;
    }

    // Clear wrapper module logs prior to test profiling.
    cout << "Clearing wrapper device logs\n";
    test_harness.clear_wrapper_log();
    cout << "Enabling wrapper device logging\n";
    test_harness.begin_wrapper_logging();

    // Fork off a new process and run test profiling. Forking makes it easier to
    // handle making sure everything is taken care of in profiling and ensures
    // that even if all file handles aren't closed in the test process the parent
    // won't hang due to a busy mount point.
    cout << "Running test profile\n";
    {
      const pid_t child = fork();
      if (child < 0) {
        cerr << "Error spinning off test process\n";
        test_harness.cleanup_harness();
        return -1;
      } else if (child != 0) {
        pid_t status;
        wait(&status);
        if (status != 0) {
          cerr << "Error in test process\n";
          test_harness.cleanup_harness();
          return -1;
        }
        sleep(WRITE_DELAY);
      } else {
        // Forked process' stuff.
        return test_harness.test_run();
      }
    }

    cout << "Unmounting wrapper file system after test profiling\n";
    if (test_harness.umount_device() != SUCCESS) {
      cerr << "Error unmounting wrapper file system\n";
      test_harness.cleanup_harness();
      return -1;
    }

    cout << "Disabling wrapper device logging" << std::endl;
    test_harness.end_wrapper_logging();
    cout << "Getting wrapper data\n";
    if (test_harness.get_wrapper_log() != SUCCESS) {
      test_harness.cleanup_harness();
      return -1;
    }

    cout << "Close wrapper ioctl fd\n";
    test_harness.put_wrapper_ioctl();
    cout << "Removing wrapper module from kernel\n";
    if (test_harness.remove_wrapper() != SUCCESS) {
      cerr << "Error cleaning up: remove wrapper module\n";
      test_harness.cleanup_harness();
      return -1;
    }

    // Write log data out to file if we're given a file.
    if (!log_file_save.empty()) {
      cout << "Saving logged profile data to disk" << endl;
      if (test_harness.log_profile_save(log_file_save + "_profile") != SUCCESS) {
        cerr << "Error saving logged test file" << endl;
        // TODO(ashmrtn): Remove this in later versions?
        test_harness.cleanup_harness();
        return -1;
      }
    }
  } else {
    // Logged test data given, load it into the test harness.
    cout << "Loading logged profile data from disk" << endl;
    if (test_harness.log_profile_load(log_file_load + "_profile") != SUCCESS) {
      cerr << "Error loading logged test file" << endl;
      test_harness.cleanup_harness();
      return -1;
    }
  }

  /***************************************************/
  /*
#define TEST_CASE_FSCK "fsck -T -t "

  // Create a new partition table on test device.
  cout << "Partitioning test drive" << endl;
  if (test_harness.partition_drive() != SUCCESS) {
    test_harness.cleanup_harness();
    return -1;
  }

  cout << "Restoring device clone" << std::endl;
  if (test_harness.clone_device_restore() != SUCCESS) {
    test_harness.cleanup_harness();
    cerr << "Error restoring device clone" << std::endl;
    return -1;
  }

  cout << "Restoring log data" << std::endl;
  if (test_harness.test_restore_log() != SUCCESS) {
    test_harness.cleanup_harness();
    cerr << "Error restoring log data" << std::endl;
    return -1;
  }

  std::cout << "Result of current test is " << test_harness.test_check_current()
    << std::endl;
  */

  /***************************************************/

  if (!dry_run) {
    cout << "Writing profiled data to block device and checking with fsck\n";
    test_harness.test_check_random_permutations(1);

    cout << "Ran " << test_harness.test_test_stats[TESTS_TESTS_RUN] << " tests"
          << endl
      << '\t' << test_harness.test_test_stats[TESTS_TEST_FSCK_FAIL]
          << " tests fsck failed" << endl
      << '\t' << test_harness.test_test_stats[TESTS_TEST_BAD_DATA]
          << " tests bad data" << endl
      << '\t' << test_harness.test_test_stats[TESTS_TEST_FSCK_FIX]
          << " tests fsck fix" << endl
      << '\t' << test_harness.test_test_stats[TESTS_TEST_PASS]
          << " tests passed" << endl
      << '\t' << test_harness.test_test_stats[TESTS_TEST_ERR]
          << " tests errored" << endl;
  }

  // Finish cleaning everything up.
  test_harness.cleanup_harness();
  return 0;
}
<commit_msg>Switch back to mostly ramdisks.<commit_after>#include <fcntl.h>
#include <getopt.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <wait.h>

#include <iostream>
#include <string>
#include <vector>

#include "../utils/utils.h"
#include "Tester.h"
#include "../tests/BaseTestCase.h"

#define TEST_SO_PATH "tests/"
#define PERMUTER_SO_PATH "permuter/"
// TODO(ashmrtn): Find a good delay time to use for tests.
#define TEST_DIRTY_EXPIRE_TIME "500"
#define WRITE_DELAY 30
#define MOUNT_DELAY 3

#define OPTS_STRING "d:il:m:np:r:st:v"

using std::cerr;
using std::cout;
using std::endl;
using std::string;
using fs_testing::Tester;

static const option long_options[] = {
  {"no-snap", no_argument, NULL, 's'},
  {"in-memory", no_argument, NULL, 'i'},
  {"dry-run", no_argument, NULL, 'n'},
  {"verbose", no_argument, NULL, 'v'},
  {"fs-type", required_argument, NULL, 't'},
  {"test-dev", required_argument, NULL, 'd'},
  {"log-file", required_argument, NULL, 'l'},
  {"reload-log-file", required_argument, NULL, 'r'},
  {"mount-opts", required_argument, NULL, 'm'},
  {"permuter", required_argument, NULL, 'p'},
  {0, 0, 0, 0},
};

int main(int argc, char** argv) {
  string dirty_expire_time_centisecs(TEST_DIRTY_EXPIRE_TIME);
  unsigned long int test_sleep_delay = WRITE_DELAY;
  string fs_type("ext4");
  string test_dev("/dev/ram0");
  string mount_opts("");
  string log_file_save("");
  string log_file_load("");
  string permuter(PERMUTER_SO_PATH "RandomPermuter.so");
  bool dry_run = false;
  bool no_lvm = false;
  bool no_snap = false;
  bool verbose = false;
  // TODO(ashmrtn): Find a better way to track whether we are using a ramdisk or
  // not. ramdisks don't need paritioned and will fail if we try to run fdisk
  // (the partitioning steps) on them so we need to detect them and change our
  // method for them.
  bool in_memory = true;  // Assume ramdisk.

  int option_idx = 0;

  // Parse command line arguments.
  for (int c = getopt_long(argc, argv, OPTS_STRING, long_options, &option_idx);
        c != -1;
        c = getopt_long(argc, argv, OPTS_STRING, long_options, &option_idx)) {
    switch (c) {
      case 'd':
        test_dev = string(optarg);
        in_memory = false;
        break;
      case 'i':
        in_memory = true;
        break;
      case 'l':
        log_file_save = string(optarg);
        break;
      case 'm':
        mount_opts = string(optarg);
        break;
      case 'n':
        dry_run = 1;
        break;
      case 'p':
        permuter = string(optarg);
        break;
      case 'r':
        log_file_load = string(optarg);
        break;
      case 's':
        no_snap = 1;
        dry_run = 1;
        break;
      case 't':
        fs_type = string(optarg);
        break;
      case 'v':
        verbose = true;
        break;
      case '?':
      default:
        return -1;
    }
  }

  const unsigned int test_case_idx = optind;

  if (test_case_idx == argc) {
    cerr << "Please give a .so test case to load" << endl;
    return -1;
  }

  Tester test_harness(verbose);
  test_harness.set_fs_type(fs_type);
  test_harness.set_device(test_dev);

  // Load the class being tested.
  cout << "Loading test case" << endl;
  if (test_harness.test_load_class(argv[test_case_idx]) != SUCCESS) {
    test_harness.cleanup_harness();
      return -1;
  }

  // Load the permuter to use for the test.
  // TODO(ashmrtn): Consider making a line in the test file which specifies the
  // permuter to use?
  cout << "Loading permuter" << endl;
  if (test_harness.permuter_load_class(permuter.c_str()) != SUCCESS) {
    test_harness.cleanup_harness();
      return -1;
  }

  // Update dirty_expire_time.
  cout << "Updating dirty_expire_time_centisecs" << endl;
  const char* old_expire_time =
    test_harness.update_dirty_expire_time(dirty_expire_time_centisecs.c_str());
  if (old_expire_time == NULL) {
    cerr << "Error updating dirty_expire_time_centisecs" << endl;
    test_harness.cleanup_harness();
    return -1;
  }

  if (!in_memory) {
    // Partition drive.
    // TODO(ashmrtn): Consider making a flag for this?
    cout << "Wiping test device" << endl;
    if (test_harness.wipe_partitions() != SUCCESS) {
      cerr << "Error wiping paritions on test device" << endl;
      test_harness.cleanup_harness();
      return -1;
    }
  }

  // Run the normal test setup stuff if we don't have a log file.
  if (log_file_load.empty()) {

    if (!in_memory) {
      // Create a new partition table on test device.
      cout << "Partitioning test drive" << endl;
      if (test_harness.partition_drive() != SUCCESS) {
        test_harness.cleanup_harness();
        return -1;
      }
    }

    // Format test drive to desired type.
    cout << "Formatting test drive" << endl;
    if (test_harness.format_drive() != SUCCESS) {
      cerr << "Error formatting test drive" << endl;
      test_harness.cleanup_harness();
      return -1;
    }

    // Mount test file system for pre-test setup.
    cout << "Mounting test file system for pre-test setup\n";
    if (test_harness.mount_device_raw(mount_opts.c_str()) != SUCCESS) {
      cerr << "Error mounting test device" << endl;
      test_harness.cleanup_harness();
      return -1;
    }

    // Run pre-test setup stuff.
    cout << "Running pre-test setup\n";
    {
      const pid_t child = fork();
      if (child < 0) {
        cerr << "Error creating child process to run pre-test setup\n";
        test_harness.cleanup_harness();
      } else if (child != 0) {
        // Parent process should wait for child to terminate before proceeding.
        pid_t status;
        wait(&status);
        if (status != 0) {
          cerr << "Error in pre-test setup\n";
          test_harness.cleanup_harness();
        }
      } else {
        return test_harness.test_setup();
      }
    }

    // Unmount the test file system after pre-test setup.
    cout << "Unmounting test file system after pre-test setup\n";
    if (test_harness.umount_device() != SUCCESS) {
      test_harness.cleanup_harness();
      return -1;
    }

    // Create snapshot of disk for testing.
    if (!no_snap) {
      cout << "Making new snapshot\n";
      if (test_harness.clone_device() != SUCCESS) {
        test_harness.cleanup_harness();
        return -1;
      }

      // If we're logging this test run then also save the snapshot.
      if (!log_file_save.empty()) {
        cout << "Saving snapshot to log file" << endl;
        if (test_harness.log_snapshot_save(log_file_save + "_snap")
            != SUCCESS) {
          test_harness.cleanup_harness();
          return -1;
        }
      }
    }
  } else {
    // Load the snapshot in the log file and then write it to disk.
    cout << "Loading saved snapshot" << endl;
    if (test_harness.log_snapshot_load(log_file_load + "_snap") != SUCCESS) {
      test_harness.cleanup_harness();
      return -1;
    }
  }

  // TODO(ashmrtn): Consider making a flag for this?
  cout << "Clearing caches" << endl;
  if (test_harness.clear_caches() != SUCCESS) {
    cerr << "Error clearing caches" << endl;
    test_harness.cleanup_harness();
    return -1;
  }

  // No log file given so run the test profile.
  if (log_file_load.empty()) {

    // Insert the disk block wrapper into the kernel.
    cout << "Inserting wrapper module into kernel\n";
    if (test_harness.insert_wrapper() != SUCCESS) {
      cerr << "Error inserting kernel wrapper module\n";
      test_harness.cleanup_harness();
      return -1;
    }

    // Mount the file system under the wrapper module for profiling.
    cout << "Mounting wrapper file system\n";
    if (test_harness.mount_wrapper_device(mount_opts.c_str()) != SUCCESS) {
      cerr << "Error mounting wrapper file system\n";
      test_harness.cleanup_harness();
      return -1;
    }

    cout << "Sleeping after mount" << endl;
    unsigned int to_sleep = MOUNT_DELAY;
    do {
      to_sleep = sleep(to_sleep);
    } while (to_sleep > 0);

    // Get access to wrapper module ioctl functions via FD.
    cout << "Getting wrapper device ioctl fd\n";
    if (test_harness.get_wrapper_ioctl() != SUCCESS) {
      cerr << "Error opening device file\n";
      test_harness.cleanup_harness();
      return -1;
    }

    // Clear wrapper module logs prior to test profiling.
    cout << "Clearing wrapper device logs\n";
    test_harness.clear_wrapper_log();
    cout << "Enabling wrapper device logging\n";
    test_harness.begin_wrapper_logging();

    // Fork off a new process and run test profiling. Forking makes it easier to
    // handle making sure everything is taken care of in profiling and ensures
    // that even if all file handles aren't closed in the test process the parent
    // won't hang due to a busy mount point.
    cout << "Running test profile\n";
    {
      const pid_t child = fork();
      if (child < 0) {
        cerr << "Error spinning off test process\n";
        test_harness.cleanup_harness();
        return -1;
      } else if (child != 0) {
        pid_t status;
        wait(&status);
        if (status != 0) {
          cerr << "Error in test process\n";
          test_harness.cleanup_harness();
          return -1;
        }
        sleep(WRITE_DELAY);

        // Wait a small amount of time for writes to propogate to the block
        // layer and then stop logging writes.
        cout << "Disabling wrapper device logging" << std::endl;
        test_harness.end_wrapper_logging();
        cout << "Getting wrapper data\n";
        if (test_harness.get_wrapper_log() != SUCCESS) {
          test_harness.cleanup_harness();
          return -1;
        }
      } else {
        // Forked process' stuff.
        return test_harness.test_run();
      }
    }

    cout << "Unmounting wrapper file system after test profiling\n";
    if (test_harness.umount_device() != SUCCESS) {
      cerr << "Error unmounting wrapper file system\n";
      test_harness.cleanup_harness();
      return -1;
    }

    cout << "Close wrapper ioctl fd\n";
    test_harness.put_wrapper_ioctl();
    cout << "Removing wrapper module from kernel\n";
    if (test_harness.remove_wrapper() != SUCCESS) {
      cerr << "Error cleaning up: remove wrapper module\n";
      test_harness.cleanup_harness();
      return -1;
    }

    // Write log data out to file if we're given a file.
    if (!log_file_save.empty()) {
      cout << "Saving logged profile data to disk" << endl;
      if (test_harness.log_profile_save(log_file_save + "_profile") != SUCCESS) {
        cerr << "Error saving logged test file" << endl;
        // TODO(ashmrtn): Remove this in later versions?
        test_harness.cleanup_harness();
        return -1;
      }
    }
  } else {
    // Logged test data given, load it into the test harness.
    cout << "Loading logged profile data from disk" << endl;
    if (test_harness.log_profile_load(log_file_load + "_profile") != SUCCESS) {
      cerr << "Error loading logged test file" << endl;
      test_harness.cleanup_harness();
      return -1;
    }
  }

  /***************************************************/
  /*
#define TEST_CASE_FSCK "fsck -T -t "

  // Create a new partition table on test device.
  cout << "Partitioning test drive" << endl;
  if (test_harness.partition_drive() != SUCCESS) {
    test_harness.cleanup_harness();
    return -1;
  }

  cout << "Restoring device clone" << std::endl;
  if (test_harness.clone_device_restore() != SUCCESS) {
    test_harness.cleanup_harness();
    cerr << "Error restoring device clone" << std::endl;
    return -1;
  }

  cout << "Restoring log data" << std::endl;
  if (test_harness.test_restore_log() != SUCCESS) {
    test_harness.cleanup_harness();
    cerr << "Error restoring log data" << std::endl;
    return -1;
  }

  std::cout << "Result of current test is " << test_harness.test_check_current()
    << std::endl;
  */

  /***************************************************/

  if (!dry_run) {
    cout << "Writing profiled data to block device and checking with fsck\n";
    test_harness.test_check_random_permutations(1);

    cout << "Ran " << test_harness.test_test_stats[TESTS_TESTS_RUN] << " tests"
          << endl
      << '\t' << test_harness.test_test_stats[TESTS_TEST_FSCK_FAIL]
          << " tests fsck failed" << endl
      << '\t' << test_harness.test_test_stats[TESTS_TEST_BAD_DATA]
          << " tests bad data" << endl
      << '\t' << test_harness.test_test_stats[TESTS_TEST_FSCK_FIX]
          << " tests fsck fix" << endl
      << '\t' << test_harness.test_test_stats[TESTS_TEST_PASS]
          << " tests passed" << endl
      << '\t' << test_harness.test_test_stats[TESTS_TEST_ERR]
          << " tests errored" << endl;
  }

  // Finish cleaning everything up.
  test_harness.cleanup_harness();
  return 0;
}
<|endoftext|>


<commit_before>#include <gmi_null.h>
#include <gmi_mesh.h>
#include <apfMDS.h>
#include <apfMesh2.h>
#include <apf.h>
#include <PCU.h>
#include <parma.h>
#include <stdlib.h>

int main(int argc, char** argv) {
  MPI_Init(&argc,&argv);
  PCU_Comm_Init();
  if ( argc != 4 ) {
    if ( !PCU_Comm_Self() )
      printf("Usage: %s <model> <mesh> <out prefix>\n", argv[0]);
    MPI_Finalize();
    exit(EXIT_FAILURE);
  }
  PCU_Debug_Open();
  gmi_register_null();
  gmi_register_mesh();
  apf::Mesh2* m = apf::loadMdsMesh(argv[1],argv[2]);
  apf::MeshTag* order = Parma_BfsReorder(m);
  apf::reorderMdsMesh(m, order);
  apf::writeVtkFiles("parma_ordered", m);
  m->writeNative(argv[3]);
  m->destroyNative();
  apf::destroyMesh(m);
  PCU_Comm_Free();
  MPI_Finalize();
}
<commit_msg>remove debug outputs<commit_after>#include <gmi_null.h>
#include <gmi_mesh.h>
#include <apfMDS.h>
#include <apfMesh2.h>
#include <apf.h>
#include <PCU.h>
#include <parma.h>
#include <stdlib.h>

int main(int argc, char** argv) {
  MPI_Init(&argc,&argv);
  PCU_Comm_Init();
  if ( argc != 4 ) {
    if ( !PCU_Comm_Self() )
      printf("Usage: %s <model> <mesh> <out prefix>\n", argv[0]);
    MPI_Finalize();
    exit(EXIT_FAILURE);
  }
  gmi_register_null();
  gmi_register_mesh();
  apf::Mesh2* m = apf::loadMdsMesh(argv[1],argv[2]);
  apf::MeshTag* order = Parma_BfsReorder(m);
  apf::reorderMdsMesh(m, order);
  m->writeNative(argv[3]);
  m->destroyNative();
  apf::destroyMesh(m);
  PCU_Comm_Free();
  MPI_Finalize();
}
<|endoftext|>


<commit_before>/* -*- mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/* tests/test-trace.C
 *
 * Written by David Saunders
 *
 * --------------------------------------------------------
 * See COPYING for license information
 */

#include "linbox-config.h"

#include <iostream>
#include <fstream>
#include <vector>
#include <functional>

#include "test-common.h"

#include "linbox/util/commentator.h"
#include "linbox/field/ntl-pid-zz_p.h"
#include "linbox/field/local2_32.h"
#include "linbox/blackbox/dense.h"
#include "linbox/algorithms/local-smith.h"
#include "linbox/algorithms/2local-smith.h"
#include "linbox/vector/stream.h"
#include <linbox/matrix/matrix-domain.h>
#include <linbox/util/timer.h>

using namespace LinBox;

/* Test 1: Invariant factors of random diagonal matrix
 *
 * Construct a random diagonal matrix and check that its computed smith form
 * is the sort on the P powers.
 *
 * R - PID over which to perform computations
 * stream - Stream that comprises source of diagonal vectors
 *
 * Return true on success and false on failure
 */

template <class LocalPID>
class foobar {
	public:
	typedef typename LocalPID::Element first_argument_type;
	typedef LocalPID second_argument_type;
	typedef void result_type;
	void operator()(typename LocalPID::Element& d, const LocalPID& R) const
	{
		typename LocalPID::Element x = d;
		R.gcd(d, x, x);
	}
};
template<>
class foobar<LinBox::Local2_32> {
public:
	typedef LinBox::Local2_32 LocalPID;

	typedef LocalPID::Element first_argument_type;
	typedef LocalPID second_argument_type;
	typedef void result_type;
	void operator()(LocalPID::Element& d, const LocalPID& R) const
	{

		if(d != 0)    {

			int r = 1;

			while ( !(d & 1) ) {
				d >>= 1;
				r <<= 1;
			}

			d = r;
		}

	}
};

template <class LocalPID>
class pplt
{   public:
	pplt(LocalPID R) : _R(R){}
	bool operator() (typename LocalPID::Element a, typename LocalPID::Element b)
	{
	       if ( b == 0 ) return true;
       	       else if ( a == 0 ) return false;
	       else return a <= b;
 	}
    //protected:
        LocalPID _R;
};

template<>
class pplt<LinBox::NTL_PID_zz_p> {
public:
	typedef LinBox::NTL_PID_zz_p LocalPID;

	pplt(LocalPID R) : _R(R){}
	bool operator() (LocalPID::Element a, LocalPID::Element b)
	{
	       if ( b == 0 ) return true;
       	       else if ( a == 0 ) return false;
	       else return NTL::rep(a) <= NTL::rep(b);
 	}
    //protected:
        LocalPID _R;
};

template <class LocalPID>
static bool testDiagonalLocalSmith (const LocalPID &R, VectorStream<vector<typename LocalPID::Element> > &stream)
{
	typedef vector <typename LocalPID::Element> Vector;
	typedef typename LocalPID::Element Elt;
	typedef DenseMatrix<LocalPID> Blackbox;

	commentator.start ("Testing diagonal local smith", "testDiagonalLocalSmith", stream.m ());

	VectorDomain<LocalPID> VD (R);

	bool ret = true;
	size_t i;
	size_t n = stream.n();

	Vector d;

	VectorWrapper::ensureDim (d, stream.dim ());

	while (stream) {
		commentator.startIteration (stream.j ());

		stream.next (d);

		ostream &report = commentator.report (Commentator::LEVEL_IMPORTANT, INTERNAL_DESCRIPTION);
		//ostream &report = std::cout;
		report << "Input vector:  ";
		VD.write (report, d);
		report << endl;

		Blackbox Lm (R, n, n), D (R, n, n), U (R, n, n), A (R, n, n);
		for( i = 0; i < n; ++i ) {D[i][i] = d[i];Lm[i][i]=U[i][i]=1;}

		size_t j;

		for (i = 0; i < n; ++ i)
		       for ( j = 0; j < i; ++ j) {

			       D[i][j] = D[j][i] = 0;

			       Lm[i][j] = rand() % 10;
			       Lm[j][i] = 0;

			       U[j][i] = rand() % 10;
			       U[i][j] = 0;
		       }

		MatrixDomain<LocalPID> MR(R);

		Timer timer;

		report << "D\n";
		D.write(report);

		report << "L\n";
		Lm.write(report);

		report << "U\n";
		U.write(report);

		timer.start();
		MR.mul(A,Lm,D);

		report << "L D\n";
		A.write(report);

		MR.mulin(A,U);
		timer.stop();
		report << "Two matrix multiplication: " << timer << "\n";

		report << "A \n";
		A.write(report);
		//for( i = 0; i < n; ++i ) D[i][i] = rand() % 10 + 1;

		list< typename LocalPID::Element > L;
		LocalSmith< LocalPID > SmithForm;
		timer.start();
		SmithForm( L, A, R );
		timer.stop();
		report << "Time " << timer <<"\n";

		report.flush();
		report << "Computed invariants: ";

		report << "[";
		typedef typename list<Elt>::iterator listptr;
		for (listptr p = L.begin(); p != L.end(); ++p)
		    report << *p << ", ";
		report << "\b\b]" << endl;

		pplt<LocalPID> lt(R);
		report << "normalize done" << endl;
		report.flush();

		for_each(d.begin(), d.end(), bind2nd(foobar<LocalPID>(), R));
		timer.start();
		stable_sort(d.begin(), d.end(), lt);
		timer.stop();
		report << "Sorting " << timer <<"\n";

		report << "sort done" << endl;
		report.flush();

		report << "True invariants: ";
		VD.write (report, d);
		report << endl;
		report << flush;

		if ( L.size() != D.rowdim() ) {ret = false; break;}
		typedef typename Vector::iterator vectptr;
		listptr p; vectptr q;
		for (p = L.begin(), q = d.begin();
		     q != d.end();
		     ++p, ++q)
		    if ( !R.areEqual (*p, *q ) )
		    {
			commentator.report (Commentator::LEVEL_IMPORTANT, INTERNAL_ERROR)
				<< "ERROR: Computed invariants incorrect" << endl;
			 ret = false;
		    }
		commentator.stop("done");
		commentator.progress();
	}

	commentator.stop (MSG_STATUS (ret), (const char *) 0, "testDiagonalTrace");

	return ret;
}

int main (int argc, char **argv)
{
	bool pass = true;

	static size_t n = 20;
	static integer q = 101;
	static int iterations = 1;

	static Argument args[] = {
		{ 'n', "-n N", "Set dimension of test matrices to NxN (default 256)", TYPE_INT,     &n },
		{ 'q', "-q Q", "Operate over the \"field\" GF(Q) [1] (default 101)",  TYPE_INTEGER, &q },
		{ 'i', "-i I", "Perform each test for I iterations (default 10)",     TYPE_INT,     &iterations },
	};

	typedef NTL_PID_zz_p Ring;
	typedef vector<Ring::Element> Vector;

	parseArguments (argc, argv, args);
	Ring R (536870912);

	cout << endl << "Black box local smith test suite" << endl;

	commentator.getMessageClass (INTERNAL_DESCRIPTION).setMaxDepth (5);

	RandomDenseStream<Ring, Vector> stream (R, n, iterations);

	if (!testDiagonalLocalSmith<Ring> (R, stream)) pass = false;

	// power of 2 test
	Local2_32 R2;
	RandomDenseStream<Local2_32, vector<Local2_32::Element> >
		stream2 (R2, n, iterations);
	if (!testDiagonalLocalSmith<Local2_32> (R2, stream2)) pass = false;

	return pass ? 0 : -1;
}

<commit_msg>min change in comments<commit_after>/* -*- mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/* tests/test-trace.C
 *
 * Written by David Saunders
 *
 * --------------------------------------------------------
 * See COPYING for license information
 */

#include "linbox-config.h"

#include <iostream>
#include <fstream>
#include <vector>
#include <functional>

#include "test-common.h"

#include "linbox/util/commentator.h"
#include "linbox/field/ntl-pid-zz_p.h"
#include "linbox/field/local2_32.h"
#include "linbox/blackbox/dense.h"
#include "linbox/algorithms/local-smith.h"
#include "linbox/algorithms/2local-smith.h"
#include "linbox/vector/stream.h"
#include <linbox/matrix/matrix-domain.h>
#include <linbox/util/timer.h>

using namespace LinBox;

/** @memo Test 1: Invariant factors of random dense matrices.
 *
 * Construct a random matrix which is equivalent to a random diagonal matrix,
 * and check its Smith form.
 *
 * R - PIR over which to perform computations
 * stream - Stream that comprises source of diagonal vectors
 *
 * Return true on success and false on failure
 */

template <class LocalPID>
class foobar {
	public:
	typedef typename LocalPID::Element first_argument_type;
	typedef LocalPID second_argument_type;
	typedef void result_type;
	void operator()(typename LocalPID::Element& d, const LocalPID& R) const
	{
		typename LocalPID::Element x = d;
		R.gcd(d, x, x);
	}
};
template<>
class foobar<LinBox::Local2_32> {
public:
	typedef LinBox::Local2_32 LocalPID;

	typedef LocalPID::Element first_argument_type;
	typedef LocalPID second_argument_type;
	typedef void result_type;
	void operator()(LocalPID::Element& d, const LocalPID& R) const
	{

		if(d != 0)    {

			int r = 1;

			while ( !(d & 1) ) {
				d >>= 1;
				r <<= 1;
			}

			d = r;
		}

	}
};

template <class LocalPID>
class pplt
{   public:
	pplt(LocalPID R) : _R(R){}
	bool operator() (typename LocalPID::Element a, typename LocalPID::Element b)
	{
	       if ( b == 0 ) return true;
       	       else if ( a == 0 ) return false;
	       else return a <= b;
 	}
    //protected:
        LocalPID _R;
};

template<>
class pplt<LinBox::NTL_PID_zz_p> {
public:
	typedef LinBox::NTL_PID_zz_p LocalPID;

	pplt(LocalPID R) : _R(R){}
	bool operator() (LocalPID::Element a, LocalPID::Element b)
	{
	       if ( b == 0 ) return true;
       	       else if ( a == 0 ) return false;
	       else return NTL::rep(a) <= NTL::rep(b);
 	}
    //protected:
        LocalPID _R;
};

template <class LocalPID>
static bool testLocalSmith (const LocalPID &R, VectorStream<vector<typename LocalPID::Element> > &stream)
{
	typedef vector <typename LocalPID::Element> Vector;
	typedef typename LocalPID::Element Elt;
	typedef DenseMatrix<LocalPID> Blackbox;

	commentator.start ("Testing local smith on random dense matrices", "testLocalSmith", stream.m ());

	VectorDomain<LocalPID> VD (R);

	bool ret = true;
	size_t i;
	size_t n = stream.n();

	Vector d;

	VectorWrapper::ensureDim (d, stream.dim ());

	while (stream) {
		commentator.startIteration (stream.j ());

		stream.next (d);

		ostream &report = commentator.report (Commentator::LEVEL_IMPORTANT, INTERNAL_DESCRIPTION);
		//ostream &report = std::cout;
		report << "Input vector:  ";
		VD.write (report, d);
		report << endl;

		Blackbox Lm (R, n, n), D (R, n, n), U (R, n, n), A (R, n, n);
		for( i = 0; i < n; ++i ) {D[i][i] = d[i];Lm[i][i]=U[i][i]=1;}

		size_t j;

		for (i = 0; i < n; ++ i)
		       for ( j = 0; j < i; ++ j) {

			       D[i][j] = D[j][i] = 0;

			       Lm[i][j] = rand() % 10;
			       Lm[j][i] = 0;

			       U[j][i] = rand() % 10;
			       U[i][j] = 0;
		       }

		MatrixDomain<LocalPID> MR(R);

		Timer timer;

		report << "D\n";
		D.write(report);

		report << "L\n";
		Lm.write(report);

		report << "U\n";
		U.write(report);

		timer.start();
		MR.mul(A,Lm,D);

		report << "L D\n";
		A.write(report);

		MR.mulin(A,U);
		timer.stop();
		report << "Two matrix multiplication: " << timer << "\n";

		report << "A \n";
		A.write(report);
		//for( i = 0; i < n; ++i ) D[i][i] = rand() % 10 + 1;

		list< typename LocalPID::Element > L;
		LocalSmith< LocalPID > SmithForm;
		timer.start();
		SmithForm( L, A, R );
		timer.stop();
		report << "Time " << timer <<"\n";

		report.flush();
		report << "Computed invariants: ";

		report << "[";
		typedef typename list<Elt>::iterator listptr;
		for (listptr p = L.begin(); p != L.end(); ++p)
		    report << *p << ", ";
		report << "\b\b]" << endl;

		pplt<LocalPID> lt(R);
		report << "normalize done" << endl;
		report.flush();

		for_each(d.begin(), d.end(), bind2nd(foobar<LocalPID>(), R));
		timer.start();
		stable_sort(d.begin(), d.end(), lt);
		timer.stop();
		report << "Sorting " << timer <<"\n";

		report << "sort done" << endl;
		report.flush();

		report << "True invariants: ";
		VD.write (report, d);
		report << endl;
		report << flush;

		if ( L.size() != D.rowdim() ) {ret = false; break;}
		typedef typename Vector::iterator vectptr;
		listptr p; vectptr q;
		for (p = L.begin(), q = d.begin();
		     q != d.end();
		     ++p, ++q)
		    if ( !R.areEqual (*p, *q ) )
		    {
			commentator.report (Commentator::LEVEL_IMPORTANT, INTERNAL_ERROR)
				<< "ERROR: Computed invariants incorrect" << endl;
			 ret = false;
		    }
		commentator.stop("done");
		commentator.progress();
	}

	commentator.stop (MSG_STATUS (ret), (const char *) 0, "testDiagonalTrace");

	return ret;
}

int main (int argc, char **argv)
{
	bool pass = true;

	static size_t n = 20;
	static integer q = 101;
	static int iterations = 1;

	static Argument args[] = {
		{ 'n', "-n N", "Set dimension of test matrices to NxN (default 256)", TYPE_INT,     &n },
		{ 'q', "-q Q", "Operate over the \"field\" GF(Q) [1] (default 101)",  TYPE_INTEGER, &q },
		{ 'i', "-i I", "Perform each test for I iterations (default 10)",     TYPE_INT,     &iterations },
	};

	typedef NTL_PID_zz_p Ring;
	typedef vector<Ring::Element> Vector;

	parseArguments (argc, argv, args);
	Ring R (536870912);

	cout << endl << "Random dense matrix local smith test suite" << endl;

	commentator.getMessageClass (INTERNAL_DESCRIPTION).setMaxDepth (5);

	RandomDenseStream<Ring, Vector> stream (R, n, iterations);

	if (!testLocalSmith<Ring> (R, stream)) pass = false;

	// power of 2 test
	Local2_32 R2;
	RandomDenseStream<Local2_32, vector<Local2_32::Element> >
		stream2 (R2, n, iterations);
	if (!testLocalSmith<Local2_32> (R2, stream2)) pass = false;

	return pass ? 0 : -1;
}

<|endoftext|>


<commit_before>// ==================================================================
// ROCS - Toolkit for Robots Comprehending Space
// Copyright (C) 2011  Andrzej Pronobis, Kristoffer Sjöo
//
// This file is part of ROCS.
//
// ROCS is free software: you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation, either version 3
// of the License, or (at your option) any later version.
//
// ROCS is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with ROCS. If not, see <http://www.gnu.org/licenses/>.
// ==================================================================

/*!
 *
 *
 * \author Andrzej Pronobis, Kristoffer Sjöo
 * \file AxiomFactorClassGenerator.cc
 */

#include "rocs/concept/AxiomFactorClassGenerator.h"

#include "rocs/ml/FactorClassSet.h"
#include <opencv2/core/core.hpp>

namespace rocs {
namespace concept {

using namespace ml;

void AxiomFactorClassGenerator::generate(size_t inCount, size_t intCount, size_t onCount)
{
  {
    int sizes[] = {2, 2};
    cv::Mat supportAntisymmetricalPotentials(2, sizes, CV_64F);
    supportAntisymmetricalPotentials.setTo(1);
    int indices[] = {1,1};
    supportAntisymmetricalPotentials.at(indices) = 0;

    _supportAntisymmetricalFactorClass = &_fcs->addFactorClass(*_ontRelationVariableClass,
	*_ontRelationVariableClass, supportAntisymmetricalPotentials);
  }

  {
    int sizes[] = {2, 2};
    cv::Mat containmentAntisymmetricalPotentials(2, sizes, CV_64F);
    containmentAntisymmetricalPotentials.setTo(1);
    int indices[] = {1,1};
    containmentAntisymmetricalPotentials.at(indices) = 0;

    _containmentAntisymmetricalFactorClass = &_fcs->addFactorClass(*_ontRelationVariableClass,
	*_ontRelationVariableClass, containmentAntisymmetricalPotentials);
  }

  {
    int sizes[] = {2, 2};
    cv::Mat supportImpliesTransitiveSupportPotentials(2, sizes, CV_64F);
    supportImpliesTransitiveSupportPotentials.setTo(1);
    int indices[] = {1,0};
    supportImpliesTransitiveSupportPotentials.at(indices) = 0;

    _supportImpliesTransitiveSupportFactorClass = &_fcs->addFactorClass(*_onRelationVariableClass,
	*_ontRelationVariableClass, supportImpliesTransitiveSupportFactorClass);
  }

  {
    int sizes[] = {2, 2, 2};
    cv::Mat supportTransitivePotentials(3, sizes, CV_64F);
    supportTransitivePotentials.setTo(1);
    int indices[] = {1,1,0};//Forbid true, true, false case
    supportTransitivePotentials.at(indices) = 0;

    std::vector<ml::FactorClass *>classes;
    classes.push_back(_ontRelationVariableClass);
    classes.push_back(_ontRelationVariableClass);
    classes.push_back(_ontRelationVariableClass);

    _supportTransitiveFactorClass = &_fcs->addFactorClass(classes, supportTransitivePotentials);
  }

  {
    int sizes[] = {2, 2, 2};
    cv::Mat containmentTransitivePotentials(3, sizes, CV_64F);
    containmentTransitivePotentials.setTo(1);
    int indices[] = {1,1,0};//Forbid true, true, false case
    containmentTransitivePotentials.at(indices) = 0;

    std::vector<ml::FactorClass *>classes;
    classes.push_back(_inRelationVariableClass);
    classes.push_back(_inRelationVariableClass);
    classes.push_back(_inRelationVariableClass);

    _containmentTransitiveFactorClass = &_fcs->addFactorClass(classes, containmentTransitivePotentials);
  }

  {
    int sizes[] = {2, 2, 2};
    cv::Mat generousContainmentPotentials(3, sizes, CV_64F);
    generousContainmentPotentials.setTo(1);
    int indices[] = {1,1,0};//Forbid true, true, false case
    generousContainmentPotentials.at(indices) = 0;

    std::vector<ml::FactorClass *>classes;
    classes.push_back(_ontRelationVariableClass);
    classes.push_back(_inRelationVariableClass);
    classes.push_back(_inRelationVariableClass);

    _generousContainmentFactorClass = &_fcs->addFactorClass(classes, generousContainmentPotentials);
  }
}

}
}
<commit_msg>Again<commit_after>// ==================================================================
// ROCS - Toolkit for Robots Comprehending Space
// Copyright (C) 2011  Andrzej Pronobis, Kristoffer Sjöo
//
// This file is part of ROCS.
//
// ROCS is free software: you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation, either version 3
// of the License, or (at your option) any later version.
//
// ROCS is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with ROCS. If not, see <http://www.gnu.org/licenses/>.
// ==================================================================

/*!
 *
 *
 * \author Andrzej Pronobis, Kristoffer Sjöo
 * \file AxiomFactorClassGenerator.cc
 */

#include "rocs/concept/AxiomFactorClassGenerator.h"

#include "rocs/ml/FactorClassSet.h"
#include <opencv2/core/core.hpp>
#include <stddef.h>

namespace rocs {
namespace concept {

using namespace ml;

void recurseSupportRequirement(cv::Mat &potentials, int *indices, int depth, int maxDepth)
{
  if (depth > maxDepth) {
    potentials.at<double>(indices) = 0;
  }
  else {
    //Case: ~ONt(z,y)
    indices[depth*3] = 0;  	//~ONt(zn,y)
    indices[depth*3+1] = 0;    	//~ON(x,zn)
    indices[depth*3+2] = 0;  	//~IN(x,zn)
    recurseSupportRequirement(potentials, indices, depth+3, maxDepth);
    indices[depth*3+1] = 1;    	//ON(x,zn)
    recurseSupportRequirement(potentials, indices, depth+3, maxDepth);
    indices[depth*3+1] = 0;    	//~ON(x,zn)
    indices[depth*3+2] = 1;  	//IN(x,zn)
    recurseSupportRequirement(potentials, indices, depth+3, maxDepth);
    indices[depth*3+1] = 1;    	//ON(x,zn)
    recurseSupportRequirement(potentials, indices, depth+3, maxDepth);

    // ONt(z,y) and ~ON(x,z) and ~IN(x,z)) (case when ~ONt(z,y) already covered above)
    indices[depth*3] = 1;
    indices[depth*3+1] = 0;
    indices[depth*3+2] = 0;
    recurseSupportRequirement(potentials, indices, depth+3, maxDepth);
  }
}

void AxiomFactorClassGenerator::generate(size_t inCount, size_t ontCount, size_t onCount)
{
  {
    int sizes[] = {2, 2};
    cv::Mat supportAntisymmetricalPotentials(2, sizes, CV_64F);
    supportAntisymmetricalPotentials.setTo(1);
    int indices[] = {1,1};
    supportAntisymmetricalPotentials.at<double>(indices) = 0;

    _supportAntisymmetricalFactorClass = &_fcs->addFactorClass(*_ontRelationVariableClass,
	*_ontRelationVariableClass, supportAntisymmetricalPotentials);
  }

  {
    int sizes[] = {2, 2};
    cv::Mat containmentAntisymmetricalPotentials(2, sizes, CV_64F);
    containmentAntisymmetricalPotentials.setTo(1);
    int indices[] = {1,1};
    containmentAntisymmetricalPotentials.at<double>(indices) = 0;

    _containmentAntisymmetricalFactorClass = &_fcs->addFactorClass(*_ontRelationVariableClass,
	*_ontRelationVariableClass, containmentAntisymmetricalPotentials);
  }

  {
    int sizes[] = {2, 2};
    cv::Mat supportImpliesTransitiveSupportPotentials(2, sizes, CV_64F);
    supportImpliesTransitiveSupportPotentials.setTo(1);
    int indices[] = {1,0};
    supportImpliesTransitiveSupportPotentials.at<double>(indices) = 0;

    _supportImpliesTransitiveSupportFactorClass = &_fcs->addFactorClass(*_onRelationVariableClass,
	*_ontRelationVariableClass, supportImpliesTransitiveSupportPotentials);
  }

  {
    int sizes[] = {2, 2, 2};
    cv::Mat supportTransitivePotentials(3, sizes, CV_64F);
    supportTransitivePotentials.setTo(1);
    int indices[] = {1,1,0};//Forbid true, true, false case
    supportTransitivePotentials.at<double>(indices) = 0;

    std::vector<ml::VariableClass>classes;
    classes.push_back(*_ontRelationVariableClass);
    classes.push_back(*_ontRelationVariableClass);
    classes.push_back(*_ontRelationVariableClass);

    _supportTransitiveFactorClass = &_fcs->addFactorClass(classes, supportTransitivePotentials);
  }

  {
    int sizes[] = {2, 2, 2};
    cv::Mat containmentTransitivePotentials(3, sizes, CV_64F);
    containmentTransitivePotentials.setTo(1);
    int indices[] = {1,1,0};//Forbid true, true, false case
    containmentTransitivePotentials.at<double>(indices) = 0;

    std::vector<ml::VariableClass>classes;
    classes.push_back(*_inRelationVariableClass);
    classes.push_back(*_inRelationVariableClass);
    classes.push_back(*_inRelationVariableClass);

    _containmentTransitiveFactorClass = &_fcs->addFactorClass(classes, containmentTransitivePotentials);
  }

  {
    int sizes[] = {2, 2, 2};
    cv::Mat generousContainmentPotentials(3, sizes, CV_64F);
    generousContainmentPotentials.setTo(1);
    int indices[] = {1,1,0};//Forbid true, true, false case
    generousContainmentPotentials.at<double>(indices) = 0;

    std::vector<ml::VariableClass>classes;
    classes.push_back(*_ontRelationVariableClass);
    classes.push_back(*_inRelationVariableClass);
    classes.push_back(*_inRelationVariableClass);

    _generousContainmentFactorClass = &_fcs->addFactorClass(classes, generousContainmentPotentials);
  }

  {
    int sizes[] = {2, 2, 2};
    cv::Mat containmentSupportsPotentials(3, sizes, CV_64F);
    containmentSupportsPotentials.setTo(1);
    int indices[] = {1,1,0};//Forbid true, true, false case
    containmentSupportsPotentials.at<double>(indices) = 0;

    std::vector<ml::VariableClass>classes;
    classes.push_back(*_inRelationVariableClass);
    classes.push_back(*_ontRelationVariableClass);
    classes.push_back(*_ontRelationVariableClass);

    _containmentSupportsFactorClass = &_fcs->addFactorClass(classes, containmentSupportsPotentials);
  }

  {
    int dimensions = inCount + ontCount + onCount;
    int *sizes = new int[dimensions];
    for (int i = 0; i < dimensions; i++) {
      sizes[i] = 2;
    }
    cv::Mat directSupportRequiredPotentials(dimensions, sizes, CV_64F);
    directSupportRequiredPotentials.setTo(1);

    //For all (x,y)
    // If ONt(x,y) and ~ON(x,y)
    //  For all z1
    //   if (~ONt(z,y) or (~ON(x,z) and ~IN(x,z)))
    //    For all z2...
    //      ...
    //      set false

    std::vector<ml::VariableClass>classes;
    //classes filled out as follows:
    //ONt(x,y) (LHS),
    //ON(x,y) (RHS),
    //IN(x,y),
    //ONt(z1,y)
    //ON(x,z1)
    //IN(x,z1)
    //ONt(z2,y) ...//excluding ONt(x,y)
    //ON(x,z2)     //excluding ON(x,y)
    //IN(x,z2)     //excluding IN(x,y)
    for(int i = 0; i < dimensions; i+=3) {
      classes.push_back(*_ontRelationVariableClass);
      classes.push_back(*_onRelationVariableClass);
      classes.push_back(*_inRelationVariableClass);
    }

    int *indices = new int[dimensions];
    indices[0] = 1;//ONt(x,y)
    indices[1] = 0;//~ON(x,y)
    indices[2] = 0;//~IN(x,y)
    recurseSupportRequirement(directSupportRequiredPotentials, indices, 3, dimensions);
    indices[2] = 1;//IN(x,y)
    recurseSupportRequirement(directSupportRequiredPotentials, indices, 3, dimensions);

    _directSupportRequiredFactorClass = &_fcs->addFactorClass(classes, directSupportRequiredPotentials);
  }

  {
    int dimensions = inCount + ontCount;
    int *sizes = new int[dimensions];
    for (int i = 0; i < dimensions; i++) {
      sizes[i] = 2;
    }
    cv::Mat supportRequiredPotentials(dimensions, sizes, CV_64F);
    supportRequiredPotentials.setTo(1);

    //classes filled out as follows:
    //ONt(x,y1),
    //IN(x,y1),
    //ONt(x,y2) ...  //excluding ONt(x,x)
    //IN(x,y2) ...   //excluding IN(x,x)

    std::vector<ml::VariableClass>classes;
    int *indices = new int[dimensions];
    for(int i = 0; i < dimensions; i+=2) {
      classes.push_back(*_ontRelationVariableClass);
      classes.push_back(*_inRelationVariableClass);
      indices[i] = 0;		//~ONt(x,y)
      indices[i+1] = 0;		//~IN(x,y)
    }

    supportRequiredPotentials.at<double>(indices) = 0;
    _supportRequiredFactorClass = &_fcs->addFactorClass(classes, supportRequiredPotentials);
  }

  {
    //Assume relations given are ON(x,y) and ON(x,z) where y!=z
    int sizes[] = {2, 2};
    cv::Mat uniqueSupportPotentials(2, sizes, CV_64F);
    uniqueSupportPotentials.setTo(1);
    int indices[] = {1,0};//Forbid true, true, false case
    uniqueSupportPotentials.at<double>(indices) = 0;

    _uniqueSupportFactorClass = &_fcs->addFactorClass(*_onRelationVariableClass,
	*_ontRelationVariableClass, uniqueSupportPotentials);
  }

  {
    //Assume relations given are ONt(x,y), ONt(x,z), ONt(y,z), ONt(z,y)
    int sizes[] = {2, 2, 2, 2};
    cv::Mat uniqueTransitiveSupportPotentials(4, sizes, CV_64F);
    uniqueTransitiveSupportPotentials.setTo(1);
    int indices[] = {1,1,0,0};//Forbid true, true, false, false case
    uniqueTransitiveSupportPotentials.at<double>(indices) = 0;

    std::vector<ml::VariableClass>classes;
    classes.push_back(*_ontRelationVariableClass);
    classes.push_back(*_ontRelationVariableClass);
    classes.push_back(*_ontRelationVariableClass);
    classes.push_back(*_ontRelationVariableClass);

    _uniqueTransitiveSupportFactorClass = &_fcs->addFactorClass(classes, uniqueTransitiveSupportPotentials);
  }

  {
    //Assume relations given are IN(x,y), IN(x,z), IN(y,z), IN(z,y)
    int sizes[] = {2, 2, 2, 2};
    cv::Mat uniqueInnessPotentials(4, sizes, CV_64F);
    uniqueInnessPotentials.setTo(1);
    int indices[] = {1,1,0,0};//Forbid true, true, false, false case
    uniqueInnessPotentials.at<double>(indices) = 0;

    std::vector<ml::VariableClass>classes;
    classes.push_back(*_inRelationVariableClass);
    classes.push_back(*_inRelationVariableClass);
    classes.push_back(*_inRelationVariableClass);
    classes.push_back(*_inRelationVariableClass);

    _uniqueInnessFactorClass = &_fcs->addFactorClass(classes, uniqueInnessPotentials);
  }
}

};
};
<|endoftext|>


<commit_before>/* DummyModule.cpp - stalkware(1) dummy module implementation
 * stalkware - blah bleh - (C) 2013, Timo Buhrmester
 * See README for contact-, COPYING for license information.  */

#if HAVE_CONFIG_H
# include <config.h>
#endif

#include <cstdlib>
#include <cstdio>
#include <ctime>

#include "DummyModule.h"

#define DEF_MINROLL 4

DummyModule::DummyModule()
: Module(),
  name_("N/A"),
  minroll_(DEF_MINROLL),
  pstr_("DummyPlatform")
{
}

DummyModule::~DummyModule()
{
}

bool
DummyModule::init(string const& name, map<string, cfgent> const& cfg)
{
	srand(time(NULL));
	name_ = name;
	if (cfg.count("minroll"))
		minroll_ = (int)cfg.at("minroll").val.lng_;
}

string const&
DummyModule::name() const
{
	return name_;
}

void
DummyModule::check(vector<vector<string> > const& stalkees,
		vector<pair<string, string> > & result) const
{
	for(vector<vector<string> >::const_iterator sit = stalkees.begin();
			sit != stalkees.end(); sit++) {
		string extname = (*sit)[0];
		for(vector<string>::const_iterator nit = sit->begin() + 1;
				nit != sit->end(); nit++) {

			string intname = *nit;
			if (find_user(intname)) {
				result.push_back(pair<string, string>(
						extname, intname));
				break;
			}
		}
	}
}

bool
DummyModule::find_user(string const& intname) const
{
	return (rand()>>3) % 6 >= minroll_-1;
}
<commit_msg>forgot return in init<commit_after>/* DummyModule.cpp - stalkware(1) dummy module implementation
 * stalkware - blah bleh - (C) 2013, Timo Buhrmester
 * See README for contact-, COPYING for license information.  */

#if HAVE_CONFIG_H
# include <config.h>
#endif

#include <cstdlib>
#include <cstdio>
#include <ctime>

#include "DummyModule.h"

#define DEF_MINROLL 4

DummyModule::DummyModule()
: Module(),
  name_("N/A"),
  minroll_(DEF_MINROLL),
  pstr_("DummyPlatform")
{
}

DummyModule::~DummyModule()
{
}

bool
DummyModule::init(string const& name, map<string, cfgent> const& cfg)
{
	srand(time(NULL));
	name_ = name;
	if (cfg.count("minroll"))
		minroll_ = (int)cfg.at("minroll").val.lng_;
	return true;
}

string const&
DummyModule::name() const
{
	return name_;
}

void
DummyModule::check(vector<vector<string> > const& stalkees,
		vector<pair<string, string> > & result) const
{
	for(vector<vector<string> >::const_iterator sit = stalkees.begin();
			sit != stalkees.end(); sit++) {
		string extname = (*sit)[0];
		for(vector<string>::const_iterator nit = sit->begin() + 1;
				nit != sit->end(); nit++) {

			string intname = *nit;
			if (find_user(intname)) {
				result.push_back(pair<string, string>(
						extname, intname));
				break;
			}
		}
	}
}

bool
DummyModule::find_user(string const& intname) const
{
	return (rand()>>3) % 6 >= minroll_-1;
}
<|endoftext|>


<commit_before>// Copyright 2015 Charles D. Aylward
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// A (possibly updated) copy of of this software is available at
// https://github.com/cdaylward/nosecone

#include <algorithm>
#include <chrono>
#include <fstream>
#include <iostream>

#include "3rdparty/cdaylward/pathname.h"
#include "3rdparty/nlohmann/json.h"

#include "appc/schema/image.h"
#include "appc/os/mkdir.h"

#include "nosecone/help.h"
#include "nosecone/config.h"
#include "nosecone/command/run.h"
#include "nosecone/executor/fetch.h"
#include "nosecone/executor/uuid.h"
#include "nosecone/executor/container.h"
#include "nosecone/executor/container/linux.h"

#include "appc/discovery/types.h"

namespace nosecone {
namespace command {

using Json = nlohmann::json;
using namespace nosecone::executor;

static Json to_json(const Container& container) {
  Json json{};
  // TODO Move to container start time, not to_json time.
  using clock = std::chrono::system_clock;
  json["created"] = std::chrono::duration_cast<std::chrono::seconds>(
      clock::now().time_since_epoch()).count();
  json["id"] = container.id();
  json["pid"] = container.pid();
  json["has_pty"] = container.has_pty();
  return json;
}

static void dump_container_stdout(const Container& container) {
  const int pty_master_fd = container.pty_fd();
  char pty_buffer[4096];
  for (int rc = 0;
       rc != -1;
       rc = read(pty_master_fd, pty_buffer, sizeof(pty_buffer) - 1)) {
    if (rc > 0) {
      pty_buffer[rc] = '\0';
      std::cout << pty_buffer;
    }
  }
}

int perform_run(const Arguments& args) {
  if (args.ordered_args.size() < 1) {
    std::cerr << "Missing argument: <app name>" << std::endl << std::endl;
    print_help(command::run);
    return EXIT_FAILURE;
  }

  const appc::discovery::Name name{args.ordered_args[0]};

  appc::discovery::Labels labels = config.default_labels;

  if (args.ordered_args.size() > 1) {
    for (auto iter = args.ordered_args.begin() + 1; iter != args.ordered_args.end(); iter++) {
      auto& label_set = *iter;
      auto delim = label_set.find(":");
      if (delim == std::string::npos ||
          delim == label_set.length() - 1) {
        std::cerr << "Additional argument that isn't a label: " << label_set << std::endl;
        return EXIT_FAILURE;
      }
      auto name = label_set.substr(0, delim);
      auto value = label_set.substr(delim + 1);
      labels[name] = value;
    }
  }

  const bool wait_for_container = args.has_flag("wait") ? true : false;
  const bool dump_stdout = args.has_flag("stdout") ? true : false;

  if (geteuid() != 0) {
    std::cerr << "Containers can only be started by root." << std::endl;
    return EXIT_FAILURE;
  }

  const auto made_nosecone_root = appc::os::mkdir(config.containers_path, 0755, true);
  if (!made_nosecone_root) {
    std::cerr << "Could not create dir for containers: " << made_nosecone_root.message << std::endl;
    return EXIT_FAILURE;
  }

  auto images_try = fetch_and_validate(name, labels, true);
  if (!images_try) {
    std::cerr << images_try.failure_reason() << std::endl;
    return EXIT_FAILURE;
  }

  auto images = from_result(images_try);

  if (!images[0].manifest.app) {
    std::cerr << "Image has no app, nothing to run." << std::endl;
    return EXIT_FAILURE;
  }

  const auto uuid_try = new_uuid();
  if (!uuid_try) {
    std::cerr << "Could not generate uuid: " << uuid_try.failure_reason() << std::endl;
    return EXIT_FAILURE;
  }

  const auto uuid = from_result(uuid_try);

  std::cerr << "Container ID: " << uuid << std::endl;

  const std::string container_root = pathname::join(config.containers_path, uuid);
  auto container = container::linux::Container(uuid, container_root, images);

  container.create_rootfs();
  // always?
  container.create_pty();
  auto started = container.start();
  if (!started) {
    std::cerr << "Could not start container: " << started.message << std::endl;
    return EXIT_FAILURE;
  }

  // REM we are potentially cloned (forked) here, so check that we are the parent of the
  // container before doing parent things.
  if (parent_of(container)) {
    std::cerr << "Container started, PID: " << container.pid() << std::endl;
    // TODO move this to container.start...probably.
    auto info_json = to_json(container);
    const auto container_info_file = pathname::join(container_root, "info");
    std::ofstream info(container_info_file);
    if (info) {
      info << info_json.dump(4) << std::endl;
      info.close();
    }
    if (dump_stdout) {
      std::cerr << "--- 8< ---" << std::endl;
      dump_container_stdout(container);
    } else if (wait_for_container) {
      auto waited = await(container);
    }
  }

  return EXIT_SUCCESS;
}

} // namespace command
} // namespace nosecone
<commit_msg>run: Fix for loss of precision in term reader<commit_after>// Copyright 2015 Charles D. Aylward
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// A (possibly updated) copy of of this software is available at
// https://github.com/cdaylward/nosecone

#include <algorithm>
#include <chrono>
#include <fstream>
#include <iostream>

#include "3rdparty/cdaylward/pathname.h"
#include "3rdparty/nlohmann/json.h"

#include "appc/schema/image.h"
#include "appc/os/mkdir.h"

#include "nosecone/help.h"
#include "nosecone/config.h"
#include "nosecone/command/run.h"
#include "nosecone/executor/fetch.h"
#include "nosecone/executor/uuid.h"
#include "nosecone/executor/container.h"
#include "nosecone/executor/container/linux.h"

#include "appc/discovery/types.h"

namespace nosecone {
namespace command {

using Json = nlohmann::json;
using namespace nosecone::executor;

static Json to_json(const Container& container) {
  Json json{};
  // TODO Move to container start time, not to_json time.
  using clock = std::chrono::system_clock;
  json["created"] = std::chrono::duration_cast<std::chrono::seconds>(
      clock::now().time_since_epoch()).count();
  json["id"] = container.id();
  json["pid"] = container.pid();
  json["has_pty"] = container.has_pty();
  return json;
}

static void dump_container_stdout(const Container& container) {
  const int pty_master_fd = container.pty_fd();
  char pty_buffer[4096];
  for (ssize_t rc = 0;
       rc != -1;
       rc = read(pty_master_fd, pty_buffer, sizeof(pty_buffer) - 1)) {
    if (rc > 0) {
      pty_buffer[rc] = '\0';
      std::cout << pty_buffer;
    }
  }
}

int perform_run(const Arguments& args) {
  if (args.ordered_args.size() < 1) {
    std::cerr << "Missing argument: <app name>" << std::endl << std::endl;
    print_help(command::run);
    return EXIT_FAILURE;
  }

  const appc::discovery::Name name{args.ordered_args[0]};

  appc::discovery::Labels labels = config.default_labels;

  if (args.ordered_args.size() > 1) {
    for (auto iter = args.ordered_args.begin() + 1; iter != args.ordered_args.end(); iter++) {
      auto& label_set = *iter;
      auto delim = label_set.find(":");
      if (delim == std::string::npos ||
          delim == label_set.length() - 1) {
        std::cerr << "Additional argument that isn't a label: " << label_set << std::endl;
        return EXIT_FAILURE;
      }
      auto name = label_set.substr(0, delim);
      auto value = label_set.substr(delim + 1);
      labels[name] = value;
    }
  }

  const bool wait_for_container = args.has_flag("wait") ? true : false;
  const bool dump_stdout = args.has_flag("stdout") ? true : false;

  if (geteuid() != 0) {
    std::cerr << "Containers can only be started by root." << std::endl;
    return EXIT_FAILURE;
  }

  const auto made_nosecone_root = appc::os::mkdir(config.containers_path, 0755, true);
  if (!made_nosecone_root) {
    std::cerr << "Could not create dir for containers: " << made_nosecone_root.message << std::endl;
    return EXIT_FAILURE;
  }

  auto images_try = fetch_and_validate(name, labels, true);
  if (!images_try) {
    std::cerr << images_try.failure_reason() << std::endl;
    return EXIT_FAILURE;
  }

  auto images = from_result(images_try);

  if (!images[0].manifest.app) {
    std::cerr << "Image has no app, nothing to run." << std::endl;
    return EXIT_FAILURE;
  }

  const auto uuid_try = new_uuid();
  if (!uuid_try) {
    std::cerr << "Could not generate uuid: " << uuid_try.failure_reason() << std::endl;
    return EXIT_FAILURE;
  }

  const auto uuid = from_result(uuid_try);

  std::cerr << "Container ID: " << uuid << std::endl;

  const std::string container_root = pathname::join(config.containers_path, uuid);
  auto container = container::linux::Container(uuid, container_root, images);

  container.create_rootfs();
  // always?
  container.create_pty();
  auto started = container.start();
  if (!started) {
    std::cerr << "Could not start container: " << started.message << std::endl;
    return EXIT_FAILURE;
  }

  // REM we are potentially cloned (forked) here, so check that we are the parent of the
  // container before doing parent things.
  if (parent_of(container)) {
    std::cerr << "Container started, PID: " << container.pid() << std::endl;
    // TODO move this to container.start...probably.
    auto info_json = to_json(container);
    const auto container_info_file = pathname::join(container_root, "info");
    std::ofstream info(container_info_file);
    if (info) {
      info << info_json.dump(4) << std::endl;
      info.close();
    }
    if (dump_stdout) {
      std::cerr << "--- 8< ---" << std::endl;
      dump_container_stdout(container);
    } else if (wait_for_container) {
      auto waited = await(container);
    }
  }

  return EXIT_SUCCESS;
}

} // namespace command
} // namespace nosecone
<|endoftext|>