<commit_before>
/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "gm.h"

#include "SkColorPriv.h"
#include "SkGeometry.h"
#include "SkShader.h"

static void tesselate(const SkPath& src, SkPath* dst) {
    SkPath::Iter iter(src, true);
    SkPoint pts[4];
    SkPath::Verb verb;
    while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
        switch (verb) {
            case SkPath::kMove_Verb:
                dst->moveTo(pts[0]);
                break;
            case SkPath::kLine_Verb:
                dst->lineTo(pts[1]);
                break;
            case SkPath::kQuad_Verb: {
                SkPoint p;
                for (int i = 1; i <= 8; ++i) {
                    SkEvalQuadAt(pts, i / 8.0f, &p, NULL);
                    dst->lineTo(p);
                }
            } break;
            case SkPath::kCubic_Verb: {
                SkPoint p;
                for (int i = 1; i <= 8; ++i) {
                    SkEvalCubicAt(pts, i / 8.0f, &p, NULL, NULL);
                    dst->lineTo(p);
                }
            } break;
        }
    }
}

static void setFade(SkPaint* paint, bool showGL) {
    paint->setAlpha(showGL ? 0x66 : 0xFF);
}

static void setGLFrame(SkPaint* paint) {
    paint->setColor(0xFFFF0000);
    paint->setStyle(SkPaint::kStroke_Style);
    paint->setAntiAlias(true);
    paint->setStrokeWidth(1.1f);
}

static void show_mesh(SkCanvas* canvas, const SkRect& r) {
    SkPaint paint;
    setGLFrame(&paint);

    canvas->drawRect(r, paint);
    canvas->drawLine(r.fLeft, r.fTop, r.fRight, r.fBottom, paint);
}

static void drawLine(SkCanvas* canvas, const SkPoint& p0, const SkPoint& p1,
                     const SkPaint& paint) {
    canvas->drawLine(p0.fX, p0.fY, p1.fX, p1.fY, paint);
}

static void show_mesh(SkCanvas* canvas, const SkPoint pts[],
                      const uint16_t indices[], int count) {
    SkPaint paint;
    setGLFrame(&paint);

    for (int i = 0; i < count - 2; ++i) {
        drawLine(canvas, pts[indices[i]], pts[indices[i+1]], paint);
        drawLine(canvas, pts[indices[i+1]], pts[indices[i+2]], paint);
        drawLine(canvas, pts[indices[i+2]], pts[indices[i]], paint);
    }
}

static void show_glframe(SkCanvas* canvas, const SkPath& path) {
    SkPaint paint;
    setGLFrame(&paint);
    canvas->drawPath(path, paint);
}

static void show_mesh_between(SkCanvas* canvas, const SkPath& p0, const SkPath& p1) {
    SkPath d0, d1;
    tesselate(p0, &d0);
    tesselate(p1, &d1);

    SkPoint pts0[256*2], pts1[256];
    int count = d0.getPoints(pts0, SK_ARRAY_COUNT(pts0));
    int count1 = d1.getPoints(pts1, SK_ARRAY_COUNT(pts1));
    SkASSERT(count == count1);
    memcpy(&pts0[count], pts1, count * sizeof(SkPoint));

    uint16_t indices[256*6];
    uint16_t* ndx = indices;
    for (int i = 0; i < count; ++i) {
        *ndx++ = i;
        *ndx++ = i + count;
    }
    *ndx++ = 0;

    show_mesh(canvas, pts0, indices, ndx - indices);
}

static void show_fan(SkCanvas* canvas, const SkPath& path, SkScalar cx, SkScalar cy) {
    SkPaint paint;
    setGLFrame(&paint);

    canvas->drawPath(path, paint);

    SkPoint pts[256];
    int count = path.getPoints(pts, SK_ARRAY_COUNT(pts));
    for (int i = 0; i < count; ++i) {
        canvas->drawLine(pts[i].fX, pts[i].fY, cx, cy, paint);
    }
}

///////////////////////////////////////////////////////////////////////////////

typedef void (*DrawProc)(SkCanvas* canvas, bool showGL, int flags);

static void draw_line(SkCanvas* canvas, bool showGL, int flags) {
    SkPaint paint;
    paint.setAntiAlias(true);

    canvas->drawLine(50, 50, 400, 100, paint);

    canvas->rotate(40);
    setFade(&paint, showGL);
    paint.setStrokeWidth(40);
    canvas->drawLine(100, 50, 450, 50, paint);
    if (showGL) {
        show_mesh(canvas, SkRect::MakeLTRB(100, 50-20, 450, 50+20));
    }
}

static void draw_rect(SkCanvas* canvas, bool showGL, int flags) {
    SkPaint paint;
    paint.setAntiAlias(true);

    SkRect r = SkRect::MakeLTRB(50, 70, 250, 370);

    setFade(&paint, showGL);
    canvas->drawRect(r, paint);
    if (showGL) {
        show_mesh(canvas, r);
    }

    canvas->translate(320, 0);

    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(25);
    canvas->drawRect(r, paint);
    if (showGL) {
        SkScalar rad = paint.getStrokeWidth() / 2;
        SkPoint pts[8];
        r.outset(rad, rad);
        r.toQuad(&pts[0]);
        r.inset(rad*2, rad*2);
        r.toQuad(&pts[4]);

        const uint16_t indices[] = {
            0, 4, 1, 5, 2, 6, 3, 7, 0, 4
        };
        show_mesh(canvas, pts, indices, SK_ARRAY_COUNT(indices));
    }
}

static void draw_oval(SkCanvas* canvas, bool showGL, int flags) {
    SkPaint paint;
    paint.setAntiAlias(true);

    SkRect r = SkRect::MakeLTRB(50, 70, 250, 370);

    setFade(&paint, showGL);
    canvas->drawOval(r, paint);
    if (showGL) {
        switch (flags) {
            case 0: {
                SkPath path;
                path.addOval(r);
                show_glframe(canvas, path);
            } break;
            case 1:
            case 2: {
                SkPath src, dst;
                src.addOval(r);
                tesselate(src, &dst);
                show_fan(canvas, dst, r.centerX(), r.centerY());
            } break;
        }
    }

    canvas->translate(320, 0);

    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(25);
    canvas->drawOval(r, paint);
    if (showGL) {
        switch (flags) {
            case 0: {
                SkPath path;
                SkScalar rad = paint.getStrokeWidth() / 2;
                r.outset(rad, rad);
                path.addOval(r);
                r.inset(rad*2, rad*2);
                path.addOval(r);
                show_glframe(canvas, path);
            } break;
            case 1: {
                SkPath path0, path1;
                SkScalar rad = paint.getStrokeWidth() / 2;
                r.outset(rad, rad);
                path0.addOval(r);
                r.inset(rad*2, rad*2);
                path1.addOval(r);
                show_mesh_between(canvas, path0, path1);
            } break;
            case 2: {
                SkScalar rad = paint.getStrokeWidth() / 2;
                r.outset(rad, rad);
                SkPaint paint;
                paint.setAlpha(0x33);
                canvas->drawRect(r, paint);
                show_mesh(canvas, r);
            } break;
        }
    }
}

#include "SkImageDecoder.h"
static void draw_image(SkCanvas* canvas, bool showGL, int flags) {
    SkPaint paint;
    paint.setAntiAlias(true);
    paint.setFilterBitmap(true);
    setFade(&paint, showGL);

    SkBitmap bm;
    SkImageDecoder::DecodeFile("/skimages/startrek.png", &bm);
    SkRect r = SkRect::MakeWH(bm.width(), bm.height());

    canvas->save();
    canvas->translate(30, 30);
    canvas->scale(0.8f, 0.8f);
    canvas->drawBitmap(bm, 0, 0, &paint);
    if (showGL) {
        show_mesh(canvas, r);
    }
    canvas->restore();

    canvas->translate(210, 290);
    canvas->rotate(-35);
    canvas->drawBitmap(bm, 0, 0, &paint);
    if (showGL) {
        show_mesh(canvas, r);
    }
}

static void draw_text(SkCanvas* canvas, bool showGL, int flags) {
    SkPaint paint;
    paint.setAntiAlias(true);
    const char text[] = "Graphics at Google";
    size_t len = strlen(text);
    setFade(&paint, showGL);

    canvas->translate(40, 50);
    for (int i = 0; i < 10; ++i) {
        paint.setTextSize(12 + i * 3);
        canvas->drawText(text, len, 0, 0, paint);
        if (showGL) {
            SkRect bounds[256];
            SkScalar widths[256];
            int count = paint.getTextWidths(text, len, widths, bounds);
            SkScalar adv = 0;
            for (int j = 0; j < count; ++j) {
                bounds[j].offset(adv, 0);
                show_mesh(canvas, bounds[j]);
                adv += widths[j];
            }
        }
        canvas->translate(0, paint.getTextSize() * 3 / 2);
    }
}

static const struct {
    DrawProc    fProc;
    const char* fName;
} gRec[] = {
    {   draw_line,  "Lines" },
    {   draw_rect,  "Rects" },
    {   draw_oval,  "Ovals" },
    {   draw_image, "Images" },
    {   draw_text,  "Text" },
};

class TalkGM : public skiagm::GM {
    DrawProc fProc;
    SkString fName;
    bool     fShowGL;
    int      fFlags;

public:
    TalkGM(int index, bool showGL, int flags = 0) {
        fProc = gRec[index].fProc;
        fName.set(gRec[index].fName);
        if (showGL) {
            fName.append("-gl");
        }
        fShowGL = showGL;
        fFlags = flags;
    }

protected:
    virtual SkString onShortName() {
        return fName;
    }

    virtual SkISize onISize() {
        return SkISize::Make(640, 480);
    }

    virtual void onDraw(SkCanvas* canvas) {
        SkRect dst = SkRect::MakeWH(canvas->getDevice()->width(), canvas->getDevice()->height());
        SkRect src = SkRect::MakeWH(640, 480);
        SkMatrix matrix;
        matrix.setRectToRect(src, dst, SkMatrix::kCenter_ScaleToFit);

        canvas->concat(matrix);
        fProc(canvas, fShowGL, fFlags);
    }

private:
    typedef skiagm::GM INHERITED;
};

//////////////////////////////////////////////////////////////////////////////

#define GM_CONCAT(X,Y) GM_CONCAT_IMPL(X,Y)
#define GM_CONCAT_IMPL(X,Y) X##Y

#define FACTORY_NAME  GM_CONCAT(Factory, __LINE__)
#define REGISTRY_NAME  GM_CONCAT(gReg, __LINE__)

#define ADD_GM(Class, args)    \
    static skiagm::GM* FACTORY_NAME(void*) { return new Class args; } \
    static skiagm::GMRegistry REGISTRY_NAME(FACTORY_NAME);

ADD_GM(TalkGM, (0, false))
ADD_GM(TalkGM, (0, true))
ADD_GM(TalkGM, (1, false))
ADD_GM(TalkGM, (1, true))
ADD_GM(TalkGM, (2, false))
ADD_GM(TalkGM, (2, true))
ADD_GM(TalkGM, (2, true, 1))
ADD_GM(TalkGM, (2, true, 2))
ADD_GM(TalkGM, (3, false))
ADD_GM(TalkGM, (3, true))
ADD_GM(TalkGM, (4, false))
ADD_GM(TalkGM, (4, true))

//static GM* MyFactory(void*) { return new TalkGM(0, false); }
//static GMRegistry reg(MyFactory);

<commit_msg>Sanitizing source files in Skia_Periodic_House_Keeping<commit_after>
/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "gm.h"

#include "SkColorPriv.h"
#include "SkGeometry.h"
#include "SkShader.h"

static void tesselate(const SkPath& src, SkPath* dst) {
    SkPath::Iter iter(src, true);
    SkPoint pts[4];
    SkPath::Verb verb;
    while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
        switch (verb) {
            case SkPath::kMove_Verb:
                dst->moveTo(pts[0]);
                break;
            case SkPath::kLine_Verb:
                dst->lineTo(pts[1]);
                break;
            case SkPath::kQuad_Verb: {
                SkPoint p;
                for (int i = 1; i <= 8; ++i) {
                    SkEvalQuadAt(pts, i / 8.0f, &p, NULL);
                    dst->lineTo(p);
                }
            } break;
            case SkPath::kCubic_Verb: {
                SkPoint p;
                for (int i = 1; i <= 8; ++i) {
                    SkEvalCubicAt(pts, i / 8.0f, &p, NULL, NULL);
                    dst->lineTo(p);
                }
            } break;
        }
    }
}

static void setFade(SkPaint* paint, bool showGL) {
    paint->setAlpha(showGL ? 0x66 : 0xFF);
}

static void setGLFrame(SkPaint* paint) {
    paint->setColor(0xFFFF0000);
    paint->setStyle(SkPaint::kStroke_Style);
    paint->setAntiAlias(true);
    paint->setStrokeWidth(1.1f);
}

static void show_mesh(SkCanvas* canvas, const SkRect& r) {
    SkPaint paint;
    setGLFrame(&paint);

    canvas->drawRect(r, paint);
    canvas->drawLine(r.fLeft, r.fTop, r.fRight, r.fBottom, paint);
}

static void drawLine(SkCanvas* canvas, const SkPoint& p0, const SkPoint& p1,
                     const SkPaint& paint) {
    canvas->drawLine(p0.fX, p0.fY, p1.fX, p1.fY, paint);
}

static void show_mesh(SkCanvas* canvas, const SkPoint pts[],
                      const uint16_t indices[], int count) {
    SkPaint paint;
    setGLFrame(&paint);

    for (int i = 0; i < count - 2; ++i) {
        drawLine(canvas, pts[indices[i]], pts[indices[i+1]], paint);
        drawLine(canvas, pts[indices[i+1]], pts[indices[i+2]], paint);
        drawLine(canvas, pts[indices[i+2]], pts[indices[i]], paint);
    }
}

static void show_glframe(SkCanvas* canvas, const SkPath& path) {
    SkPaint paint;
    setGLFrame(&paint);
    canvas->drawPath(path, paint);
}

static void show_mesh_between(SkCanvas* canvas, const SkPath& p0, const SkPath& p1) {
    SkPath d0, d1;
    tesselate(p0, &d0);
    tesselate(p1, &d1);

    SkPoint pts0[256*2], pts1[256];
    int count = d0.getPoints(pts0, SK_ARRAY_COUNT(pts0));
    int count1 = d1.getPoints(pts1, SK_ARRAY_COUNT(pts1));
    SkASSERT(count == count1);
    memcpy(&pts0[count], pts1, count * sizeof(SkPoint));

    uint16_t indices[256*6];
    uint16_t* ndx = indices;
    for (int i = 0; i < count; ++i) {
        *ndx++ = i;
        *ndx++ = i + count;
    }
    *ndx++ = 0;

    show_mesh(canvas, pts0, indices, ndx - indices);
}

static void show_fan(SkCanvas* canvas, const SkPath& path, SkScalar cx, SkScalar cy) {
    SkPaint paint;
    setGLFrame(&paint);

    canvas->drawPath(path, paint);

    SkPoint pts[256];
    int count = path.getPoints(pts, SK_ARRAY_COUNT(pts));
    for (int i = 0; i < count; ++i) {
        canvas->drawLine(pts[i].fX, pts[i].fY, cx, cy, paint);
    }
}

///////////////////////////////////////////////////////////////////////////////

typedef void (*DrawProc)(SkCanvas* canvas, bool showGL, int flags);

static void draw_line(SkCanvas* canvas, bool showGL, int flags) {
    SkPaint paint;
    paint.setAntiAlias(true);

    canvas->drawLine(50, 50, 400, 100, paint);

    canvas->rotate(40);
    setFade(&paint, showGL);
    paint.setStrokeWidth(40);
    canvas->drawLine(100, 50, 450, 50, paint);
    if (showGL) {
        show_mesh(canvas, SkRect::MakeLTRB(100, 50-20, 450, 50+20));
    }
}

static void draw_rect(SkCanvas* canvas, bool showGL, int flags) {
    SkPaint paint;
    paint.setAntiAlias(true);

    SkRect r = SkRect::MakeLTRB(50, 70, 250, 370);

    setFade(&paint, showGL);
    canvas->drawRect(r, paint);
    if (showGL) {
        show_mesh(canvas, r);
    }

    canvas->translate(320, 0);

    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(25);
    canvas->drawRect(r, paint);
    if (showGL) {
        SkScalar rad = paint.getStrokeWidth() / 2;
        SkPoint pts[8];
        r.outset(rad, rad);
        r.toQuad(&pts[0]);
        r.inset(rad*2, rad*2);
        r.toQuad(&pts[4]);

        const uint16_t indices[] = {
            0, 4, 1, 5, 2, 6, 3, 7, 0, 4
        };
        show_mesh(canvas, pts, indices, SK_ARRAY_COUNT(indices));
    }
}

static void draw_oval(SkCanvas* canvas, bool showGL, int flags) {
    SkPaint paint;
    paint.setAntiAlias(true);

    SkRect r = SkRect::MakeLTRB(50, 70, 250, 370);

    setFade(&paint, showGL);
    canvas->drawOval(r, paint);
    if (showGL) {
        switch (flags) {
            case 0: {
                SkPath path;
                path.addOval(r);
                show_glframe(canvas, path);
            } break;
            case 1:
            case 2: {
                SkPath src, dst;
                src.addOval(r);
                tesselate(src, &dst);
                show_fan(canvas, dst, r.centerX(), r.centerY());
            } break;
        }
    }

    canvas->translate(320, 0);

    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(25);
    canvas->drawOval(r, paint);
    if (showGL) {
        switch (flags) {
            case 0: {
                SkPath path;
                SkScalar rad = paint.getStrokeWidth() / 2;
                r.outset(rad, rad);
                path.addOval(r);
                r.inset(rad*2, rad*2);
                path.addOval(r);
                show_glframe(canvas, path);
            } break;
            case 1: {
                SkPath path0, path1;
                SkScalar rad = paint.getStrokeWidth() / 2;
                r.outset(rad, rad);
                path0.addOval(r);
                r.inset(rad*2, rad*2);
                path1.addOval(r);
                show_mesh_between(canvas, path0, path1);
            } break;
            case 2: {
                SkScalar rad = paint.getStrokeWidth() / 2;
                r.outset(rad, rad);
                SkPaint paint;
                paint.setAlpha(0x33);
                canvas->drawRect(r, paint);
                show_mesh(canvas, r);
            } break;
        }
    }
}

#include "SkImageDecoder.h"
static void draw_image(SkCanvas* canvas, bool showGL, int flags) {
    SkPaint paint;
    paint.setAntiAlias(true);
    paint.setFilterBitmap(true);
    setFade(&paint, showGL);

    SkBitmap bm;
    SkImageDecoder::DecodeFile("/skimages/startrek.png", &bm);
    SkRect r = SkRect::MakeWH(bm.width(), bm.height());

    canvas->save();
    canvas->translate(30, 30);
    canvas->scale(0.8f, 0.8f);
    canvas->drawBitmap(bm, 0, 0, &paint);
    if (showGL) {
        show_mesh(canvas, r);
    }
    canvas->restore();

    canvas->translate(210, 290);
    canvas->rotate(-35);
    canvas->drawBitmap(bm, 0, 0, &paint);
    if (showGL) {
        show_mesh(canvas, r);
    }
}

static void draw_text(SkCanvas* canvas, bool showGL, int flags) {
    SkPaint paint;
    paint.setAntiAlias(true);
    const char text[] = "Graphics at Google";
    size_t len = strlen(text);
    setFade(&paint, showGL);

    canvas->translate(40, 50);
    for (int i = 0; i < 10; ++i) {
        paint.setTextSize(12 + i * 3);
        canvas->drawText(text, len, 0, 0, paint);
        if (showGL) {
            SkRect bounds[256];
            SkScalar widths[256];
            int count = paint.getTextWidths(text, len, widths, bounds);
            SkScalar adv = 0;
            for (int j = 0; j < count; ++j) {
                bounds[j].offset(adv, 0);
                show_mesh(canvas, bounds[j]);
                adv += widths[j];
            }
        }
        canvas->translate(0, paint.getTextSize() * 3 / 2);
    }
}

static const struct {
    DrawProc    fProc;
    const char* fName;
} gRec[] = {
    {   draw_line,  "Lines" },
    {   draw_rect,  "Rects" },
    {   draw_oval,  "Ovals" },
    {   draw_image, "Images" },
    {   draw_text,  "Text" },
};

class TalkGM : public skiagm::GM {
    DrawProc fProc;
    SkString fName;
    bool     fShowGL;
    int      fFlags;

public:
    TalkGM(int index, bool showGL, int flags = 0) {
        fProc = gRec[index].fProc;
        fName.set(gRec[index].fName);
        if (showGL) {
            fName.append("-gl");
        }
        fShowGL = showGL;
        fFlags = flags;
    }

protected:
    virtual SkString onShortName() {
        return fName;
    }

    virtual SkISize onISize() {
        return SkISize::Make(640, 480);
    }

    virtual void onDraw(SkCanvas* canvas) {
        SkRect dst = SkRect::MakeWH(canvas->getDevice()->width(), canvas->getDevice()->height());
        SkRect src = SkRect::MakeWH(640, 480);
        SkMatrix matrix;
        matrix.setRectToRect(src, dst, SkMatrix::kCenter_ScaleToFit);

        canvas->concat(matrix);
        fProc(canvas, fShowGL, fFlags);
    }

private:
    typedef skiagm::GM INHERITED;
};

//////////////////////////////////////////////////////////////////////////////

#define GM_CONCAT(X,Y) GM_CONCAT_IMPL(X,Y)
#define GM_CONCAT_IMPL(X,Y) X##Y

#define FACTORY_NAME  GM_CONCAT(Factory, __LINE__)
#define REGISTRY_NAME  GM_CONCAT(gReg, __LINE__)

#define ADD_GM(Class, args)    \
    static skiagm::GM* FACTORY_NAME(void*) { return new Class args; } \
    static skiagm::GMRegistry REGISTRY_NAME(FACTORY_NAME);

ADD_GM(TalkGM, (0, false))
ADD_GM(TalkGM, (0, true))
ADD_GM(TalkGM, (1, false))
ADD_GM(TalkGM, (1, true))
ADD_GM(TalkGM, (2, false))
ADD_GM(TalkGM, (2, true))
ADD_GM(TalkGM, (2, true, 1))
ADD_GM(TalkGM, (2, true, 2))
ADD_GM(TalkGM, (3, false))
ADD_GM(TalkGM, (3, true))
ADD_GM(TalkGM, (4, false))
ADD_GM(TalkGM, (4, true))

//static GM* MyFactory(void*) { return new TalkGM(0, false); }
//static GMRegistry reg(MyFactory);

<|endoftext|>


<commit_before>#include "utils.h"
#include "exception.h"
#include "whiteningpreconditioner.h"

#include "Eigen/Eigenvalues"
using Eigen::SelfAdjointEigenSolver;

CMT::WhiteningPreconditioner::WhiteningPreconditioner(const ArrayXXd& input, const ArrayXXd& output) {
	if(input.cols() != output.cols())
		throw Exception("Number of inputs and outputs must be the same.");
	if(input.cols() < input.rows())
		throw Exception("Too few inputs to compute whitening transform.");

	mMeanIn = input.rowwise().mean();
	mMeanOut = output.rowwise().mean();

	// concatenate input and output
	ArrayXXd data(input.rows() + output.rows(), input.cols());
	data << input.matrix().colwise() - mMeanIn, output.matrix().colwise() - mMeanOut;

	// compute covariances
	MatrixXd cov = covariance(data);
	MatrixXd covXX = cov.topLeftCorner(input.rows(), input.rows());
	MatrixXd covYX = cov.bottomLeftCorner(output.rows(), input.rows());
	MatrixXd covYY = cov.bottomRightCorner(output.rows(), output.rows());

	SelfAdjointEigenSolver<MatrixXd> eigenSolver;

	// input whitening
	eigenSolver.compute(covXX);
	mPreIn = eigenSolver.operatorInverseSqrt();
	mPreInInv = eigenSolver.operatorSqrt();

	// optimal linear predictor
	mPredictor = covYX * mPreIn;

	// output whitening
	eigenSolver.compute(covYY - mPredictor * mPredictor.transpose());
	mPreOut = eigenSolver.operatorInverseSqrt();
	mPreOutInv = eigenSolver.operatorSqrt();

	// log-Jacobian determinant
	mLogJacobian = mPreOut.partialPivLu().matrixLU().diagonal().array().abs().log().sum();

	// used for transforming gradients
	mGradTransform = mPreOut * mPredictor * mPreIn;
}

CMT::WhiteningPreconditioner::WhiteningPreconditioner(
	const VectorXd& meanIn,
	const VectorXd& meanOut,
	const MatrixXd& preIn,
	const MatrixXd& preInInv,
	const MatrixXd& preOut,
	const MatrixXd& preOutInv,
	const MatrixXd& predictor) :
	AffinePreconditioner(
		meanIn, meanOut, preIn, preInInv, preOut, preOutInv, predictor)
{
}
<commit_msg>Whitening transform can now be used with zero-dimensional inputs.<commit_after>#include "utils.h"
#include "exception.h"
#include "whiteningpreconditioner.h"

#include "Eigen/Eigenvalues"
using Eigen::SelfAdjointEigenSolver;

CMT::WhiteningPreconditioner::WhiteningPreconditioner(const ArrayXXd& input, const ArrayXXd& output) {
	if(input.rows() == 0) {
		if(output.cols() < output.rows())
			throw Exception("Too few inputs to compute whitening transform.");

		mMeanOut = output.rowwise().mean();

		MatrixXd cov = covariance(output);

		SelfAdjointEigenSolver<MatrixXd> eigenSolver;

		// output whitening
		eigenSolver.compute(cov);
		mPreOut = eigenSolver.operatorInverseSqrt();
		mPreOutInv = eigenSolver.operatorSqrt();

		// log-Jacobian determinant
		mLogJacobian = mPreOut.partialPivLu().matrixLU().diagonal().array().abs().log().sum();
	} else {
		if(input.cols() != output.cols())
			throw Exception("Number of inputs and outputs must be the same.");
		if(input.cols() < input.rows())
			throw Exception("Too few inputs to compute whitening transform.");

		mMeanIn = input.rowwise().mean();
		mMeanOut = output.rowwise().mean();

		// concatenate input and output
		ArrayXXd data(input.rows() + output.rows(), input.cols());
		data << input.matrix().colwise() - mMeanIn, output.matrix().colwise() - mMeanOut;

		// compute covariances
		MatrixXd cov = covariance(data);
		MatrixXd covXX = cov.topLeftCorner(input.rows(), input.rows());
		MatrixXd covYX = cov.bottomLeftCorner(output.rows(), input.rows());
		MatrixXd covYY = cov.bottomRightCorner(output.rows(), output.rows());

		SelfAdjointEigenSolver<MatrixXd> eigenSolver;

		// input whitening
		eigenSolver.compute(covXX);
		mPreIn = eigenSolver.operatorInverseSqrt();
		mPreInInv = eigenSolver.operatorSqrt();

		// optimal linear predictor
		mPredictor = covYX * mPreIn;

		// output whitening
		eigenSolver.compute(covYY - mPredictor * mPredictor.transpose());
		mPreOut = eigenSolver.operatorInverseSqrt();
		mPreOutInv = eigenSolver.operatorSqrt();

		// log-Jacobian determinant
		mLogJacobian = mPreOut.partialPivLu().matrixLU().diagonal().array().abs().log().sum();

		// used for transforming gradients
		mGradTransform = mPreOut * mPredictor * mPreIn;
	}
}

CMT::WhiteningPreconditioner::WhiteningPreconditioner(
	const VectorXd& meanIn,
	const VectorXd& meanOut,
	const MatrixXd& preIn,
	const MatrixXd& preInInv,
	const MatrixXd& preOut,
	const MatrixXd& preOutInv,
	const MatrixXd& predictor) :
	AffinePreconditioner(
		meanIn, meanOut, preIn, preInInv, preOut, preOutInv, predictor)
{
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: dbtreeview.hxx,v $
 * $Revision: 1.13 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef DBACCESS_UI_DBTREEVIEW_HXX
#define DBACCESS_UI_DBTREEVIEW_HXX

#ifndef _SV_WINDOW_HXX //autogen
#include <vcl/window.hxx>
#endif

#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif

class SvTreeListBox;
namespace dbaui
{
    class DBTreeListBox;
    class DBTreeListModel;
    // ------------------
    // - DBTreeView -
    // ------------------

    class DBTreeView : public Window
    {
    private:
        DBTreeListBox*  m_pTreeListBox;
    protected:
        // window overridables
        virtual void Resize();
    public:

        DBTreeView( Window* pParent,
                const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB,
                WinBits nBits );
        ~DBTreeView();

        /** sets a handler which is called when an list box entry is to be expanded.

When calling the link, the parameter is an SvLBoxEntry marking the entry to be expanded.

        */
        void    SetPreExpandHandler(const Link& _rHdl);
        /// gets the currently set NodeExpansionHandler

        void    setCopyHandler(const Link& _rHdl);

        void                setModel(DBTreeListModel* _pTreeModel);
        void                setSelectHdl(const Link& _rHdl);

        DBTreeListBox*      getListBox() const;

        virtual void GetFocus();
    };
}

#endif // DBACCESS_UI_DBTREEVIEW_HXX

<commit_msg>INTEGRATION: CWS dba30d (1.13.30); FILE MERGED 2008/06/01 20:57:07 fs 1.13.30.1: minor re-factoring during #i80943#<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: dbtreeview.hxx,v $
 * $Revision: 1.14 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef DBACCESS_UI_DBTREEVIEW_HXX
#define DBACCESS_UI_DBTREEVIEW_HXX

#ifndef _SV_WINDOW_HXX //autogen
#include <vcl/window.hxx>
#endif

#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif

class SvTreeListBox;
class SvLBoxTreeList;
namespace dbaui
{
    class DBTreeListBox;
    // ------------------
    // - DBTreeView -
    // ------------------

    class DBTreeView : public Window
    {
    private:
        DBTreeListBox*  m_pTreeListBox;
    protected:
        // window overridables
        virtual void Resize();
    public:

        DBTreeView( Window* pParent,
                const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB,
                WinBits nBits );
        ~DBTreeView();

        /** sets a handler which is called when an list box entry is to be expanded.

When calling the link, the parameter is an SvLBoxEntry marking the entry to be expanded.

        */
        void    SetPreExpandHandler(const Link& _rHdl);
        /// gets the currently set NodeExpansionHandler

        void    setCopyHandler(const Link& _rHdl);

        void                setModel(SvLBoxTreeList* _pTreeModel);
        void                setSelectHdl(const Link& _rHdl);

        DBTreeListBox&      getListBox() const { return *m_pTreeListBox; }

        virtual void GetFocus();
    };
}

#endif // DBACCESS_UI_DBTREEVIEW_HXX

<|endoftext|>


<commit_before><commit_msg>Edit comments.<commit_after><|endoftext|>


<commit_before>/* OpenSceneGraph example, osgterrain.
*
*  Permission is hereby granted, free of charge, to any person obtaining a copy
*  of this software and associated documentation files (the "Software"), to deal
*  in the Software without restriction, including without limitation the rights
*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
*  copies of the Software, and to permit persons to whom the Software is
*  furnished to do so, subject to the following conditions:
*
*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
*  THE SOFTWARE.
*/

#include <osg/ArgumentParser>
#include <osgDB/ReadFile>

#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>

#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgGA/StateSetManipulator>
#include <osgGA/AnimationPathManipulator>
#include <osgGA/TerrainManipulator>

#include <osgTerrain/Terrain>
#include <osgTerrain/TerrainTile>
#include <osgTerrain/GeometryTechnique>
#include <osgTerrain/Layer>

#include "ShaderTerrain.h"

#include <iostream>

template<class T>
class FindTopMostNodeOfTypeVisitor : public osg::NodeVisitor
{
public:
    FindTopMostNodeOfTypeVisitor():
        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
        _foundNode(0)
    {}

    void apply(osg::Node& node)
    {
        T* result = dynamic_cast<T*>(&node);
        if (result)
        {
            _foundNode = result;
        }
        else
        {
            traverse(node);
        }
    }

    T* _foundNode;
};

template<class T>
T* findTopMostNodeOfType(osg::Node* node)
{
    if (!node) return 0;

    FindTopMostNodeOfTypeVisitor<T> fnotv;
    node->accept(fnotv);

    return fnotv._foundNode;
}

// class to handle events with a pick
class TerrainHandler : public osgGA::GUIEventHandler {
public:

    TerrainHandler(osgTerrain::Terrain* terrain):
        _terrain(terrain) {}

    bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa)
    {
        switch(ea.getEventType())
        {
            case(osgGA::GUIEventAdapter::KEYDOWN):
            {
                if (ea.getKey()=='r')
                {
                    _terrain->setSampleRatio(_terrain->getSampleRatio()*0.5);
                    osg::notify(osg::NOTICE)<<"Sample ratio "<<_terrain->getSampleRatio()<<std::endl;
                    return true;
                }
                else if (ea.getKey()=='R')
                {
                    _terrain->setSampleRatio(_terrain->getSampleRatio()/0.5);
                    osg::notify(osg::NOTICE)<<"Sample ratio "<<_terrain->getSampleRatio()<<std::endl;
                    return true;
                }
                else if (ea.getKey()=='v')
                {
                    _terrain->setVerticalScale(_terrain->getVerticalScale()*1.25);
                    osg::notify(osg::NOTICE)<<"Vertical scale "<<_terrain->getVerticalScale()<<std::endl;
                    return true;
                }
                else if (ea.getKey()=='V')
                {
                    _terrain->setVerticalScale(_terrain->getVerticalScale()/1.25);
                    osg::notify(osg::NOTICE)<<"Vertical scale "<<_terrain->getVerticalScale()<<std::endl;
                    return true;
                }

                return false;
            }
            default:
                return false;
        }
    }

protected:

    ~TerrainHandler() {}

    osg::ref_ptr<osgTerrain::Terrain>  _terrain;
};

class CleanTechniqueReadFileCallback : public osgDB::ReadFileCallback
{

    public:

        class CleanTechniqueVisitor : public osg::NodeVisitor
        {
        public:
            CleanTechniqueVisitor():
                osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}

            void apply(osg::Node& node)
            {
                osgTerrain::TerrainTile* tile = dynamic_cast<osgTerrain::TerrainTile*>(&node);
                if (tile)
                {
                    if (tile->getTerrainTechnique())
                    {
                        // OSG_NOTICE<<"Resetting TerrainTechnhique "<<tile->getTerrainTechnique()->className()<<" to 0"<<std::endl;
                        tile->setTerrainTechnique(0);
                    }
                }
                else
                {
                    traverse(node);
                }
            }
        };

        virtual osgDB::ReaderWriter::ReadResult readNode(const std::string& filename, const osgDB::Options* options)
        {
            osgDB::ReaderWriter::ReadResult rr = ReadFileCallback::readNode(filename, options);
            if (rr.validNode())
            {
                CleanTechniqueVisitor ctv;
                rr.getNode()->accept(ctv);
            }
            return rr;
        }

    protected:
        virtual ~CleanTechniqueReadFileCallback() {}
};

int main(int argc, char** argv)
{
    osg::ArgumentParser arguments(&argc, argv);

    // construct the viewer.
    osgViewer::Viewer viewer(arguments);

    // set up the camera manipulators.
    {
        osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;

        keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
        keyswitchManipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );
        keyswitchManipulator->addMatrixManipulator( '3', "Drive", new osgGA::DriveManipulator() );
        keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new osgGA::TerrainManipulator() );

        std::string pathfile;
        char keyForAnimationPath = '5';
        while (arguments.read("-p",pathfile))
        {
            osgGA::AnimationPathManipulator* apm = new osgGA::AnimationPathManipulator(pathfile);
            if (apm || !apm->valid())
            {
                unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
                keyswitchManipulator->addMatrixManipulator( keyForAnimationPath, "Path", apm );
                keyswitchManipulator->selectMatrixManipulator(num);
                ++keyForAnimationPath;
            }
        }

        viewer.setCameraManipulator( keyswitchManipulator.get() );
    }

    // add the state manipulator
    viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );

    // add the stats handler
    viewer.addEventHandler(new osgViewer::StatsHandler);

    // add the record camera path handler
    viewer.addEventHandler(new osgViewer::RecordCameraPathHandler);

    // add the window size toggle handler
    viewer.addEventHandler(new osgViewer::WindowSizeHandler);

    // obtain the vertical scale
    float verticalScale = 1.0f;
    while(arguments.read("-v",verticalScale)) {}

    // obtain the sample ratio
    float sampleRatio = 1.0f;
    while(arguments.read("-r",sampleRatio)) {}

    osgTerrain::TerrainTile::BlendingPolicy blendingPolicy = osgTerrain::TerrainTile::INHERIT;
    std::string strBlendingPolicy;
    while(arguments.read("--blending-policy", strBlendingPolicy))
    {
        if (strBlendingPolicy == "INHERIT") blendingPolicy = osgTerrain::TerrainTile::INHERIT;
        else if (strBlendingPolicy == "DO_NOT_SET_BLENDING") blendingPolicy = osgTerrain::TerrainTile::DO_NOT_SET_BLENDING;
        else if (strBlendingPolicy == "ENABLE_BLENDING") blendingPolicy = osgTerrain::TerrainTile::ENABLE_BLENDING;
        else if (strBlendingPolicy == "ENABLE_BLENDING_WHEN_ALPHA_PRESENT") blendingPolicy = osgTerrain::TerrainTile::ENABLE_BLENDING_WHEN_ALPHA_PRESENT;
    }

    bool useShaderTerrain = arguments.read("--shader") || arguments.read("-s");
    if (useShaderTerrain)
    {
        osgDB::Registry::instance()->setReadFileCallback(new CleanTechniqueReadFileCallback());
    }

    // load the nodes from the commandline arguments.
    osg::ref_ptr<osg::Node> rootnode = osgDB::readNodeFiles(arguments);

    if (!rootnode)
    {
        osg::notify(osg::NOTICE)<<"Warning: no valid data loaded, please specify a database on the command line."<<std::endl;
        return 1;
    }

    osg::ref_ptr<osgTerrain::Terrain> terrain = findTopMostNodeOfType<osgTerrain::Terrain>(rootnode.get());
    if (!terrain)
    {
        // no Terrain node present insert one above the loaded model.
        terrain = new osgTerrain::Terrain;

        // if CoordinateSystemNode is present copy it's contents into the Terrain, and discard it.
        osg::CoordinateSystemNode* csn = findTopMostNodeOfType<osg::CoordinateSystemNode>(rootnode.get());
        if (csn)
        {
            terrain->set(*csn);
            for(unsigned int i=0; i<csn->getNumChildren();++i)
            {
                terrain->addChild(csn->getChild(i));
            }
        }
        else
        {
            terrain->addChild(rootnode.get());
        }

        rootnode = terrain.get();
    }

    terrain->setSampleRatio(sampleRatio);
    terrain->setVerticalScale(verticalScale);
    terrain->setBlendingPolicy(blendingPolicy);

    if (useShaderTerrain)
    {
        terrain->setTerrainTechniquePrototype(new osgTerrain::ShaderTerrain());
    }

    // register our custom handler for adjust Terrain settings
    viewer.addEventHandler(new TerrainHandler(terrain.get()));

    // add a viewport to the viewer and attach the scene graph.
    viewer.setSceneData( rootnode.get() );

    // run the viewers main loop
    return viewer.run();

}
<commit_msg>Added --db-affinit cpuNum option to osgterrain example to illustrate how to set the thead affinity of the DatabasePager threads.<commit_after>/* OpenSceneGraph example, osgterrain.
*
*  Permission is hereby granted, free of charge, to any person obtaining a copy
*  of this software and associated documentation files (the "Software"), to deal
*  in the Software without restriction, including without limitation the rights
*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
*  copies of the Software, and to permit persons to whom the Software is
*  furnished to do so, subject to the following conditions:
*
*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
*  THE SOFTWARE.
*/

#include <osg/ArgumentParser>
#include <osgDB/ReadFile>

#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>

#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgGA/StateSetManipulator>
#include <osgGA/AnimationPathManipulator>
#include <osgGA/TerrainManipulator>

#include <osgTerrain/Terrain>
#include <osgTerrain/TerrainTile>
#include <osgTerrain/GeometryTechnique>
#include <osgTerrain/Layer>

#include "ShaderTerrain.h"

#include <iostream>

template<class T>
class FindTopMostNodeOfTypeVisitor : public osg::NodeVisitor
{
public:
    FindTopMostNodeOfTypeVisitor():
        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
        _foundNode(0)
    {}

    void apply(osg::Node& node)
    {
        T* result = dynamic_cast<T*>(&node);
        if (result)
        {
            _foundNode = result;
        }
        else
        {
            traverse(node);
        }
    }

    T* _foundNode;
};

template<class T>
T* findTopMostNodeOfType(osg::Node* node)
{
    if (!node) return 0;

    FindTopMostNodeOfTypeVisitor<T> fnotv;
    node->accept(fnotv);

    return fnotv._foundNode;
}

// class to handle events with a pick
class TerrainHandler : public osgGA::GUIEventHandler {
public:

    TerrainHandler(osgTerrain::Terrain* terrain):
        _terrain(terrain) {}

    bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa)
    {
        switch(ea.getEventType())
        {
            case(osgGA::GUIEventAdapter::KEYDOWN):
            {
                if (ea.getKey()=='r')
                {
                    _terrain->setSampleRatio(_terrain->getSampleRatio()*0.5);
                    osg::notify(osg::NOTICE)<<"Sample ratio "<<_terrain->getSampleRatio()<<std::endl;
                    return true;
                }
                else if (ea.getKey()=='R')
                {
                    _terrain->setSampleRatio(_terrain->getSampleRatio()/0.5);
                    osg::notify(osg::NOTICE)<<"Sample ratio "<<_terrain->getSampleRatio()<<std::endl;
                    return true;
                }
                else if (ea.getKey()=='v')
                {
                    _terrain->setVerticalScale(_terrain->getVerticalScale()*1.25);
                    osg::notify(osg::NOTICE)<<"Vertical scale "<<_terrain->getVerticalScale()<<std::endl;
                    return true;
                }
                else if (ea.getKey()=='V')
                {
                    _terrain->setVerticalScale(_terrain->getVerticalScale()/1.25);
                    osg::notify(osg::NOTICE)<<"Vertical scale "<<_terrain->getVerticalScale()<<std::endl;
                    return true;
                }

                return false;
            }
            default:
                return false;
        }
    }

protected:

    ~TerrainHandler() {}

    osg::ref_ptr<osgTerrain::Terrain>  _terrain;
};

class CleanTechniqueReadFileCallback : public osgDB::ReadFileCallback
{

    public:

        class CleanTechniqueVisitor : public osg::NodeVisitor
        {
        public:
            CleanTechniqueVisitor():
                osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}

            void apply(osg::Node& node)
            {
                osgTerrain::TerrainTile* tile = dynamic_cast<osgTerrain::TerrainTile*>(&node);
                if (tile)
                {
                    if (tile->getTerrainTechnique())
                    {
                        // OSG_NOTICE<<"Resetting TerrainTechnhique "<<tile->getTerrainTechnique()->className()<<" to 0"<<std::endl;
                        tile->setTerrainTechnique(0);
                    }
                }
                else
                {
                    traverse(node);
                }
            }
        };

        virtual osgDB::ReaderWriter::ReadResult readNode(const std::string& filename, const osgDB::Options* options)
        {
            osgDB::ReaderWriter::ReadResult rr = ReadFileCallback::readNode(filename, options);
            if (rr.validNode())
            {
                CleanTechniqueVisitor ctv;
                rr.getNode()->accept(ctv);
            }
            return rr;
        }

    protected:
        virtual ~CleanTechniqueReadFileCallback() {}
};

int main(int argc, char** argv)
{
    osg::ArgumentParser arguments(&argc, argv);

    // construct the viewer.
    osgViewer::Viewer viewer(arguments);

    // set up the camera manipulators.
    {
        osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;

        keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
        keyswitchManipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );
        keyswitchManipulator->addMatrixManipulator( '3', "Drive", new osgGA::DriveManipulator() );
        keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new osgGA::TerrainManipulator() );

        std::string pathfile;
        char keyForAnimationPath = '5';
        while (arguments.read("-p",pathfile))
        {
            osgGA::AnimationPathManipulator* apm = new osgGA::AnimationPathManipulator(pathfile);
            if (apm || !apm->valid())
            {
                unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
                keyswitchManipulator->addMatrixManipulator( keyForAnimationPath, "Path", apm );
                keyswitchManipulator->selectMatrixManipulator(num);
                ++keyForAnimationPath;
            }
        }

        viewer.setCameraManipulator( keyswitchManipulator.get() );
    }

    // add the state manipulator
    viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );

    // add the stats handler
    viewer.addEventHandler(new osgViewer::StatsHandler);

    // add the record camera path handler
    viewer.addEventHandler(new osgViewer::RecordCameraPathHandler);

    // add the window size toggle handler
    viewer.addEventHandler(new osgViewer::WindowSizeHandler);

    // obtain the vertical scale
    float verticalScale = 1.0f;
    while(arguments.read("-v",verticalScale)) {}

    // obtain the sample ratio
    float sampleRatio = 1.0f;
    while(arguments.read("-r",sampleRatio)) {}

    osgTerrain::TerrainTile::BlendingPolicy blendingPolicy = osgTerrain::TerrainTile::INHERIT;
    std::string strBlendingPolicy;
    while(arguments.read("--blending-policy", strBlendingPolicy))
    {
        if (strBlendingPolicy == "INHERIT") blendingPolicy = osgTerrain::TerrainTile::INHERIT;
        else if (strBlendingPolicy == "DO_NOT_SET_BLENDING") blendingPolicy = osgTerrain::TerrainTile::DO_NOT_SET_BLENDING;
        else if (strBlendingPolicy == "ENABLE_BLENDING") blendingPolicy = osgTerrain::TerrainTile::ENABLE_BLENDING;
        else if (strBlendingPolicy == "ENABLE_BLENDING_WHEN_ALPHA_PRESENT") blendingPolicy = osgTerrain::TerrainTile::ENABLE_BLENDING_WHEN_ALPHA_PRESENT;
    }

    bool useShaderTerrain = arguments.read("--shader") || arguments.read("-s");
    if (useShaderTerrain)
    {
        osgDB::Registry::instance()->setReadFileCallback(new CleanTechniqueReadFileCallback());
    }

    bool setDatabaseThreadAffinity = false;
    unsigned int cpuNum = 0;
    while(arguments.read("--db-affinity", cpuNum)) { setDatabaseThreadAffinity = true; }

    // load the nodes from the commandline arguments.
    osg::ref_ptr<osg::Node> rootnode = osgDB::readNodeFiles(arguments);

    if (!rootnode)
    {
        osg::notify(osg::NOTICE)<<"Warning: no valid data loaded, please specify a database on the command line."<<std::endl;
        return 1;
    }

    osg::ref_ptr<osgTerrain::Terrain> terrain = findTopMostNodeOfType<osgTerrain::Terrain>(rootnode.get());
    if (!terrain)
    {
        // no Terrain node present insert one above the loaded model.
        terrain = new osgTerrain::Terrain;

        // if CoordinateSystemNode is present copy it's contents into the Terrain, and discard it.
        osg::CoordinateSystemNode* csn = findTopMostNodeOfType<osg::CoordinateSystemNode>(rootnode.get());
        if (csn)
        {
            terrain->set(*csn);
            for(unsigned int i=0; i<csn->getNumChildren();++i)
            {
                terrain->addChild(csn->getChild(i));
            }
        }
        else
        {
            terrain->addChild(rootnode.get());
        }

        rootnode = terrain.get();
    }

    terrain->setSampleRatio(sampleRatio);
    terrain->setVerticalScale(verticalScale);
    terrain->setBlendingPolicy(blendingPolicy);

    if (useShaderTerrain)
    {
        terrain->setTerrainTechniquePrototype(new osgTerrain::ShaderTerrain());
    }

    // register our custom handler for adjust Terrain settings
    viewer.addEventHandler(new TerrainHandler(terrain.get()));

    // add a viewport to the viewer and attach the scene graph.
    viewer.setSceneData( rootnode.get() );

    // if required set the DatabaseThread affinity, note must call after viewer.setSceneData() so that the osgViewer::Scene object is constructed with it's DatabasePager.
    if (setDatabaseThreadAffinity)
    {
        for (unsigned int i=0; i<viewer.getDatabasePager()->getNumDatabaseThreads(); ++i)
        {
            osgDB::DatabasePager::DatabaseThread* thread = viewer.getDatabasePager()->getDatabaseThread(i);
            thread->setProcessorAffinity(cpuNum);
            OSG_NOTICE<<"Settings affinity of DatabaseThread="<<thread<<" isRunning()="<<thread->isRunning()<<" cpuNum="<<cpuNum<<std::endl;
        }
    }

    // run the viewers main loop
    return viewer.run();

}
<|endoftext|>


<commit_before>#ifndef ALEPH_MATH_BOOTSTRAP_HH__
#define ALEPH_MATH_BOOTSTRAP_HH__

#include <aleph/math/KahanSummation.hh>

#include <boost/math/distributions/students_t.hpp>

#include <algorithm>
#include <iterator>
#include <random>
#include <vector>

#include <cmath>

namespace aleph
{

namespace math
{

/**
  @class Bootstrap
  @brief Generic bootstrap functor

  This functor provides a generic interface for performing bootstrap
  operations on *arbitrary* data, using an *arbitrary* statistic for
  testing. Several convenience functions for estimating *confidence*
  values are provided.
*/

class Bootstrap
{
public:

  /**
    Given a range of data of some type, calculates a set of bootstrap replicates
    for a desired statistic. This function will not perform any type conversions
    in order to preserve all original types. The type of the output data depends
    on the return value type of the functor.

    @param[in]  numSamples samples Number of bootstrap samples
    @param[in]  begin      Input iterator to begin of data range
    @param[in]  end        Input iterator to end of data range
    @param[in]  functor    Functor for calculating a statistic on the replicate
    @param[out] result     Output iterator for storing the results
  */

  template <class InputIterator, class OutputIterator, class Functor>
  void makeReplicates( unsigned numSamples,
                       InputIterator begin, InputIterator end,
                       Functor functor,
                       OutputIterator result )
  {
    using SampleValueType  = typename std::iterator_traits<InputIterator>::value_type;
    using FunctorValueType = decltype( functor( begin, end ) );

    std::vector<SampleValueType> samples( begin, end );

    std::random_device rd;
    std::mt19937 rng( rd() );

    std::uniform_int_distribution<std::size_t> distribution( 0, samples.size() - 1 );

    std::vector<FunctorValueType> replicates;
    replicates.reserve( numSamples );

    for( unsigned sampleIndex = 0; sampleIndex < numSamples; sampleIndex++ )
    {
      std::vector<SampleValueType> sample;
      sample.reserve( samples.size() );

      for( std::size_t i = 0; i < samples.size(); i++ )
        sample.push_back( samples.at( distribution( rng ) ) );

      replicates.push_back( functor( sample.begin(),
                                     sample.end() ) );
    }

    std::copy( replicates.begin(), replicates.end(), result );
  }

  /**
    Calculates a bootstrap estimate of the standard error of a test
    statistics on a data set.

    @param numSamples Number of bootstrap samples
    @param begin      Input iterator to begin of data range
    @param end        Input iterator to end of data range
    @param functor    Functor to describe the test statistics that is to be
                      calculated on the data range. The functor has to take
                      the `value_type` of the range as a parameter, because
                      the function will show the individual samples to it.\n

                      A good example of a functor is the following *mean*
                      functor:\n

    \code{.cpp}
    auto meanCalculation = [] ( auto begin, auto end )
    {
      using T  = typename std::iterator_traits<decltype(begin)>::value_type;
      auto sum = std::accumulate( begin, end, T() );

      return static_cast<double>( sum / static_cast<double>( std::distance(begin, end) ) );
    };
    \endcode
                     Note that the functor requires `C++14` because the use
                     of `auto` in a lambda expression.

    @returns Bootstrapped estimated of the standard error
  */

  template <class InputIterator, class Functor>
  double standardError( unsigned numSamples,
                        InputIterator begin, InputIterator end,
                        Functor functor )
  {
    using FunctorValueType = decltype( functor(begin, end) );

    std::vector<FunctorValueType> estimates;
    estimates.reserve( numSamples );

    this->makeReplicates( numSamples,
                          begin, end,
                          functor,
                          std::back_inserter( estimates ) );

    using namespace aleph::math;

    double mean  = static_cast<double>( accumulate_kahan( estimates.begin(), estimates.end(), FunctorValueType() ) );
    mean        /= numSamples;

    std::vector<double> sampleSquaredDeviations;
    sampleSquaredDeviations.reserve( numSamples );

    for( auto&& estimate : estimates )
    {
      auto delta  = mean - estimate;
      delta      *= delta;

      sampleSquaredDeviations.push_back( delta );
    }

    double sumSquaredDeviations
      = accumulate_kahan_sorted(
          sampleSquaredDeviations.begin(),
          sampleSquaredDeviations.end(),
          0.0 );

    sumSquaredDeviations /= (numSamples - 1);
    return std::sqrt( static_cast<double>( sumSquaredDeviations ) );
  }

  template <class InputIterator, class Functor>
  auto basicConfidenceInterval( unsigned numSamples,
                                double alpha,
                                InputIterator begin, InputIterator end,
                                Functor functor ) -> std::pair< decltype( functor(begin, end) ), decltype( functor(begin, end) ) >
  {
    auto theta             = functor( begin, end );
    using FunctorValueType = decltype( theta );

    std::vector<FunctorValueType> estimates;
    estimates.reserve( numSamples );

    this->makeReplicates( numSamples,
                          begin, end,
                          functor,
                          std::back_inserter( estimates ) );

    std::sort( estimates.begin(), estimates.end() );

    auto upperPercentile = alpha / 2;
    auto upperEstimate   = estimates.at( Bootstrap::index( numSamples, upperPercentile ) );
    auto lowerPercentile = 1 - upperPercentile;
    auto lowerEstimate   = estimates.at( Bootstrap::index( numSamples, lowerPercentile ) );

    return std::make_pair( 2*theta - lowerEstimate, 2*theta - upperEstimate );
  }

  template <class InputIterator, class Functor>
  auto percentileConfidenceInterval( unsigned numSamples,
                                     double alpha,
                                     InputIterator begin, InputIterator end,
                                     Functor functor ) -> std::pair< decltype( functor(begin, end) ), decltype( functor(begin, end) ) >
  {
    using FunctorValueType = decltype( functor( begin, end ) );

    std::vector<FunctorValueType> estimates;
    estimates.reserve( numSamples );

    this->makeReplicates( numSamples,
                          begin, end,
                          functor,
                          std::back_inserter( estimates ) );

    std::sort( estimates.begin(), estimates.end() );

    auto lowerPercentile = alpha / 2;
    auto lowerEstimate   = estimates.at( Bootstrap::index( numSamples, lowerPercentile ) );
    auto upperPercentile = 1 - lowerPercentile;
    auto upperEstimate   = estimates.at( Bootstrap::index( numSamples, upperPercentile ) );

    return std::make_pair( lowerEstimate, upperEstimate );
  }

  template <class InputIterator, class Functor>
  auto studentConfidenceInterval( unsigned numSamples,
                                  double alpha,
                                  InputIterator begin, InputIterator end,
                                  Functor functor ) -> std::pair< decltype( functor(begin, end) ), decltype( functor(begin, end) ) >
  {
    auto theta = functor( begin, end );

    boost::math::students_t distribution( static_cast<double>( std::distance( begin, end ) - 1 ) );

    auto tl = boost::math::quantile( distribution, 1 - alpha );
    auto tu = boost::math::quantile( distribution,     alpha );
    auto se = this->standardError( numSamples,
                                   begin, end,
                                   functor );

    return std::make_pair( theta - tl * se, theta - tu * se );
  }

  /** Calculates index at a certain percentile of the data */
  static unsigned index( unsigned int samples, double alpha )
  {
    // This accounts for rounding and works regardless of whether
    // the product samples * alpha is an integer or not. Note the
    // offset of -1. It is required because, say, the 100th value
    // is at index 99 of the vector.
    return static_cast<unsigned>( samples * alpha + 0.5 ) - 1;
  }
};

} // namespace math

} // namespace aleph

#endif
<commit_msg>Fixed bootstrap index calculation<commit_after>#ifndef ALEPH_MATH_BOOTSTRAP_HH__
#define ALEPH_MATH_BOOTSTRAP_HH__

#include <aleph/math/KahanSummation.hh>

#include <boost/math/distributions/students_t.hpp>

#include <algorithm>
#include <iterator>
#include <random>
#include <vector>

#include <cmath>

namespace aleph
{

namespace math
{

/**
  @class Bootstrap
  @brief Generic bootstrap functor

  This functor provides a generic interface for performing bootstrap
  operations on *arbitrary* data, using an *arbitrary* statistic for
  testing. Several convenience functions for estimating *confidence*
  values are provided.
*/

class Bootstrap
{
public:

  /**
    Given a range of data of some type, calculates a set of bootstrap replicates
    for a desired statistic. This function will not perform any type conversions
    in order to preserve all original types. The type of the output data depends
    on the return value type of the functor.

    @param[in]  numSamples samples Number of bootstrap samples
    @param[in]  begin      Input iterator to begin of data range
    @param[in]  end        Input iterator to end of data range
    @param[in]  functor    Functor for calculating a statistic on the replicate
    @param[out] result     Output iterator for storing the results
  */

  template <class InputIterator, class OutputIterator, class Functor>
  void makeReplicates( unsigned numSamples,
                       InputIterator begin, InputIterator end,
                       Functor functor,
                       OutputIterator result )
  {
    using SampleValueType  = typename std::iterator_traits<InputIterator>::value_type;
    using FunctorValueType = decltype( functor( begin, end ) );

    std::vector<SampleValueType> samples( begin, end );

    std::random_device rd;
    std::mt19937 rng( rd() );

    std::uniform_int_distribution<std::size_t> distribution( 0, samples.size() - 1 );

    std::vector<FunctorValueType> replicates;
    replicates.reserve( numSamples );

    for( unsigned sampleIndex = 0; sampleIndex < numSamples; sampleIndex++ )
    {
      std::vector<SampleValueType> sample;
      sample.reserve( samples.size() );

      for( std::size_t i = 0; i < samples.size(); i++ )
        sample.push_back( samples.at( distribution( rng ) ) );

      replicates.push_back( functor( sample.begin(),
                                     sample.end() ) );
    }

    std::copy( replicates.begin(), replicates.end(), result );
  }

  /**
    Calculates a bootstrap estimate of the standard error of a test
    statistics on a data set.

    @param numSamples Number of bootstrap samples
    @param begin      Input iterator to begin of data range
    @param end        Input iterator to end of data range
    @param functor    Functor to describe the test statistics that is to be
                      calculated on the data range. The functor has to take
                      the `value_type` of the range as a parameter, because
                      the function will show the individual samples to it.\n

                      A good example of a functor is the following *mean*
                      functor:\n

    \code{.cpp}
    auto meanCalculation = [] ( auto begin, auto end )
    {
      using T  = typename std::iterator_traits<decltype(begin)>::value_type;
      auto sum = std::accumulate( begin, end, T() );

      return static_cast<double>( sum / static_cast<double>( std::distance(begin, end) ) );
    };
    \endcode
                     Note that the functor requires `C++14` because the use
                     of `auto` in a lambda expression.

    @returns Bootstrapped estimated of the standard error
  */

  template <class InputIterator, class Functor>
  double standardError( unsigned numSamples,
                        InputIterator begin, InputIterator end,
                        Functor functor )
  {
    using FunctorValueType = decltype( functor(begin, end) );

    std::vector<FunctorValueType> estimates;
    estimates.reserve( numSamples );

    this->makeReplicates( numSamples,
                          begin, end,
                          functor,
                          std::back_inserter( estimates ) );

    using namespace aleph::math;

    double mean  = static_cast<double>( accumulate_kahan( estimates.begin(), estimates.end(), FunctorValueType() ) );
    mean        /= numSamples;

    std::vector<double> sampleSquaredDeviations;
    sampleSquaredDeviations.reserve( numSamples );

    for( auto&& estimate : estimates )
    {
      auto delta  = mean - estimate;
      delta      *= delta;

      sampleSquaredDeviations.push_back( delta );
    }

    double sumSquaredDeviations
      = accumulate_kahan_sorted(
          sampleSquaredDeviations.begin(),
          sampleSquaredDeviations.end(),
          0.0 );

    sumSquaredDeviations /= (numSamples - 1);
    return std::sqrt( static_cast<double>( sumSquaredDeviations ) );
  }

  template <class InputIterator, class Functor>
  auto basicConfidenceInterval( unsigned numSamples,
                                double alpha,
                                InputIterator begin, InputIterator end,
                                Functor functor ) -> std::pair< decltype( functor(begin, end) ), decltype( functor(begin, end) ) >
  {
    auto theta             = functor( begin, end );
    using FunctorValueType = decltype( theta );

    std::vector<FunctorValueType> estimates;
    estimates.reserve( numSamples );

    this->makeReplicates( numSamples,
                          begin, end,
                          functor,
                          std::back_inserter( estimates ) );

    std::sort( estimates.begin(), estimates.end() );

    auto upperPercentile = alpha / 2;
    auto upperEstimate   = estimates.at( Bootstrap::index( numSamples, upperPercentile ) );
    auto lowerPercentile = 1 - upperPercentile;
    auto lowerEstimate   = estimates.at( Bootstrap::index( numSamples, lowerPercentile ) );

    return std::make_pair( 2*theta - lowerEstimate, 2*theta - upperEstimate );
  }

  template <class InputIterator, class Functor>
  auto percentileConfidenceInterval( unsigned numSamples,
                                     double alpha,
                                     InputIterator begin, InputIterator end,
                                     Functor functor ) -> std::pair< decltype( functor(begin, end) ), decltype( functor(begin, end) ) >
  {
    using FunctorValueType = decltype( functor( begin, end ) );

    std::vector<FunctorValueType> estimates;
    estimates.reserve( numSamples );

    this->makeReplicates( numSamples,
                          begin, end,
                          functor,
                          std::back_inserter( estimates ) );

    std::sort( estimates.begin(), estimates.end() );

    auto lowerPercentile = alpha / 2;
    auto lowerEstimate   = estimates.at( Bootstrap::index( numSamples, lowerPercentile ) );
    auto upperPercentile = 1 - lowerPercentile;
    auto upperEstimate   = estimates.at( Bootstrap::index( numSamples, upperPercentile ) );

    return std::make_pair( lowerEstimate, upperEstimate );
  }

  template <class InputIterator, class Functor>
  auto studentConfidenceInterval( unsigned numSamples,
                                  double alpha,
                                  InputIterator begin, InputIterator end,
                                  Functor functor ) -> std::pair< decltype( functor(begin, end) ), decltype( functor(begin, end) ) >
  {
    auto theta = functor( begin, end );

    boost::math::students_t distribution( static_cast<double>( std::distance( begin, end ) - 1 ) );

    auto tl = boost::math::quantile( distribution, 1 - alpha );
    auto tu = boost::math::quantile( distribution,     alpha );
    auto se = this->standardError( numSamples,
                                   begin, end,
                                   functor );

    return std::make_pair( theta - tl * se, theta - tu * se );
  }

  /** Calculates index at a certain percentile of the data */
  static unsigned index( unsigned int samples, double alpha )
  {
    // This accounts for rounding and works regardless of whether
    // the product samples * alpha is an integer or not. Note the
    // offset of -1. It is required because, say, the 100th value
    // is at index 99 of the vector.
    return static_cast<unsigned>( std::ceil( samples * alpha ) ) - 1;
  }
};

} // namespace math

} // namespace aleph

#endif
<|endoftext|>


<commit_before>#pragma once

#include "blackhole/sink.hpp"

#include <memory>

namespace blackhole {

class config_t;

template<typename>
struct factory;

}  // namespace blackhole

namespace blackhole {
namespace sink {

namespace file {

class inner_t;

}  // namespace file

class file_t : public sink_t {
    class properties_t;

    std::unique_ptr<file::inner_t> inner;

public:
    class builder_t;

    /// Constructs a file sink, which will write all incoming events to the file or files located at
    /// the specified path.
    ///
    /// The path can contain attribute placeholders, meaning that the real destination name will be
    /// deduced at runtime using provided log record. No real file will be opened at construction
    /// time.
    explicit file_t(const std::string& filename);

    /// Destroys the current file sink instance, freeing all its resources.
    ~file_t();

    auto filter(const record_t& record) -> bool;
    auto execute(const record_t& record, const string_view& formatted) -> void;

private:
    file_t(std::unique_ptr<file::inner_t> inner) noexcept;
    file_t(std::unique_ptr<properties_t> properties);
};

class file_t::builder_t {
    std::unique_ptr<file_t::properties_t> properties;

public:
    explicit builder_t(const std::string& path);

    auto interval(std::size_t count) -> builder_t&;
    auto build() -> file_t;
};

}  // namespace sink

template<>
struct factory<sink::file_t> {
    static auto type() -> const char*;
    static auto from(const config_t& config) -> sink::file_t;
};

}  // namespace blackhole
<commit_msg>docs(sink/file): document pair of methods<commit_after>#pragma once

#include "blackhole/sink.hpp"

#include <memory>

namespace blackhole {

class config_t;

template<typename>
struct factory;

}  // namespace blackhole

namespace blackhole {
namespace sink {

namespace file {

class inner_t;

}  // namespace file

class file_t : public sink_t {
    class properties_t;

    std::unique_ptr<file::inner_t> inner;

public:
    class builder_t;

    /// Constructs a file sink, which will write all incoming events to the file or files located at
    /// the specified path.
    ///
    /// The path can contain attribute placeholders, meaning that the real destination name will be
    /// deduced at runtime using provided log record. No real file will be opened at construction
    /// time.
    explicit file_t(const std::string& filename);

    /// Destroys the current file sink instance, freeing all its resources.
    ~file_t();

    /// Filters the given log record determining if it is allowed to be consumed by this sink.
    ///
    /// The file sink implementation always returns `true`, meaning that all logging events should
    /// be accepted.
    auto filter(const record_t& record) -> bool;

    /// Consumes the log record with the given formatted string with its further writing to the
    /// files associated.
    auto execute(const record_t& record, const string_view& formatted) -> void;

private:
    file_t(std::unique_ptr<file::inner_t> inner) noexcept;
    file_t(std::unique_ptr<properties_t> properties);
};

class file_t::builder_t {
    std::unique_ptr<file_t::properties_t> properties;

public:
    explicit builder_t(const std::string& path);

    auto interval(std::size_t count) -> builder_t&;
    auto build() -> file_t;
};

}  // namespace sink

template<>
struct factory<sink::file_t> {
    static auto type() -> const char*;
    static auto from(const config_t& config) -> sink::file_t;
};

}  // namespace blackhole
<|endoftext|>


<commit_before>/*
 Copyright (c) 2020 ANON authors, see AUTHORS file.

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
*/

#include "sync_teflon_app.h"
#include "log.h"
#include "sproc_mgr.h"
#include <sys/stat.h>
#include <aws/core/Aws.h>
#include <aws/core/utils/Outcome.h>
#include <aws/dynamodb/DynamoDBClient.h>
#include <aws/dynamodb/model/GetItemRequest.h>

namespace
{

struct tef_app
{
  tef_app(const Aws::String& id,
    const Aws::Vector<Aws::String>& filesv,
    Aws::Map<Aws::String, const std::shared_ptr<Aws::DynamoDB::Model::AttributeValue>>& fids)
    : id(id)
  {
    for (auto &f : filesv) {
      files[fids[f]->GetS()] = f;
    }
  }

  Aws::String id;
  std::map<Aws::String, Aws::String> files;
};

bool exe_cmd(const std::string &str)
{
  auto f = popen(str.c_str(), "r");
  if (f)
  {
    auto exit_code = pclose(f);
    if (exit_code != 0)
    {
      anon_log_error("command: " << str << " exited non-zero: " << error_string(exit_code));
      return false;
    }
  }
  else
  {
    anon_log_error("popen failed: " << errno_string());
    return false;
  }
  return true;
}

bool create_empty_directory(const ec2_info &ec2i, const Aws::String &id)
{
  auto dir = ec2i.root_dir;
  if (id.size() != 0)
  {
    dir += "/";
    dir += id.c_str();
  }
  std::ostringstream str;
  str << "rm -rf " << dir << " && mkdir " << dir;
  return exe_cmd(str.str());
}

void remove_directory(const ec2_info &ec2i, const Aws::String &id)
{
  auto dir = ec2i.root_dir;
  if (id.size() != 0)
  {
    dir += "/";
    dir += id.c_str();
  }
  std::ostringstream str;
  str << "rm -rf " << id;
  if (!exe_cmd(str.str()))
    anon_log_error("failed to remove " << id << " directory");
}

std::shared_ptr<tef_app> curr_app;

} // namespace

teflon_state sync_teflon_app(const ec2_info &ec2i)
{
  if (ec2i.user_data_js.find("current_server_primary_key_value") == ec2i.user_data_js.end() || ec2i.user_data_js.find("current_server_primary_key_name") == ec2i.user_data_js.end())
  {
    anon_log_error("no current server info specified in user data - cannot start teflon app");
    return teflon_server_failed;
  }

  if (!curr_app)
  {
    if (!create_empty_directory(ec2i, ""))
      return teflon_server_failed;
  }

  Aws::Client::ClientConfiguration ddb_config;
  if (ec2i.user_data_js.find("current_server_region") != ec2i.user_data_js.end())
    ddb_config.region = ec2i.user_data_js["current_server_region"];
  else
    ddb_config.region = ec2i.default_region;
  Aws::DynamoDB::DynamoDBClient ddbc(ddb_config);

  Aws::DynamoDB::Model::AttributeValue primary_key;
  std::string cs_primary_key = ec2i.user_data_js["current_server_primary_key_value"];
  primary_key.SetS(cs_primary_key.c_str());
  Aws::DynamoDB::Model::GetItemRequest req;
  std::string cs_table_name = ec2i.user_data_js["current_server_table_name"];
  std::string cs_key_name = ec2i.user_data_js["current_server_primary_key_name"];
  req.WithTableName(cs_table_name.c_str())
      .AddKey(cs_key_name.c_str(), primary_key);
  auto outcome = ddbc.GetItem(req);
  if (!outcome.IsSuccess())
  {
    anon_log_error("GetItem failed: " << outcome.GetError());
    return teflon_server_failed;
  }

  auto &map = outcome.GetResult().GetItem();
  auto state_it = map.find("state");
  if (state_it == map.end())
  {
    anon_log_error("current_server record missing required \"state\" field");
    return teflon_server_failed;
  }
  auto state = state_it->second.GetS();
  if (state == "stop")
  {
    anon_log("stopping server");
    return teflon_shut_down;
  }

  if (state != "run")
  {
    anon_log_error("unknown teflon server state: " << state);
    return teflon_server_failed;
  }

  auto id_it = map.find("current_server_id");

  auto end = map.end();
  if (id_it == end)
  {
    anon_log_error("current_server record missing required \"current_server_id\" field");
    return teflon_server_failed;
  }

  auto current_server_id = id_it->second.GetS();
  if (curr_app && current_server_id == curr_app->id)
  {
    anon_log("current server definition matches running server, no-op");
    return teflon_server_running;
  }

  auto files_it = map.find("files");
  auto exe_it = map.find("entry");
  auto ids_it = map.find("fids");
  if (files_it == end || exe_it == end || ids_it == end)
  {
    anon_log_error("current_server record missing required \"files\", \"entry\", and/or \"fids\" field(s)");
    return teflon_server_failed;
  }

  auto files_needed = files_it->second.GetSS();
  auto file_to_execute = exe_it->second.GetS();
  auto ids = ids_it->second.GetM();

  if (ec2i.user_data_js.find("current_server_artifacts_bucket") == ec2i.user_data_js.end() || ec2i.user_data_js.find("current_server_artifacts_key") == ec2i.user_data_js.end())
  {
    anon_log_error("user data missing required fields \"current_server_artifacts_bucket\" and/or \"current_server_artifacts_key\"");
    return teflon_server_failed;
  }
  std::string bucket = ec2i.user_data_js["current_server_artifacts_bucket"];
  std::string key = ec2i.user_data_js["current_server_artifacts_key"];

  std::ostringstream files_cmd;
  files_cmd << "FAIL=0\n";
  for (const auto &f : files_needed)
  {
    if (ids.find(f) == ids.end())
    {
      anon_log_error("file: \"" << f << "\" missing in fids");
      return teflon_server_failed;
    }
    if (curr_app && curr_app->files.find(f) != curr_app->files.end())
    {
      // f matches a file we have already downloaded, so just hard link it
      // to the new directory
      auto existing_file = curr_app->files[f];
      files_cmd << "ln " << ec2i.root_dir << "/" << curr_app->id << "/" << curr_app->files[f]
               << " " << ec2i.root_dir << "/" << current_server_id << "/" << f << " &\n";
    }
    else
    {
      // does not match an existing file, so download it from s3
      files_cmd << "aws s3 --region " << ec2i.default_region << " cp s3://" << bucket << "/" << key << "/" << f
               << " " << ec2i.root_dir << "/" << current_server_id << "/" << f << " --quiet &\n";
    }
  }
  if (!create_empty_directory(ec2i, current_server_id))
    return teflon_server_failed;
  files_cmd << "for job in `jobs -p`\n"
            << "do\n"
            << " wait $job || let \"FAIL+=1\"\n"
            << "done\n"
            << "if [ \"$FAIL\" == \"0\" ];\n"
            << "then\n"
            << " exit 0\n"
            << "else\n"
            << " exit 1";
  anon_log("executing script:\n" << files_cmd.str());
  if (!exe_cmd(files_cmd.str()))
    return teflon_server_failed;

  std::ostringstream ef;
  ef << ec2i.root_dir << "/" << current_server_id << "/" << file_to_execute;
  chmod(ef.str().c_str(), ACCESSPERMS);

  try {
    auto new_app = std::make_shared<tef_app>(current_server_id, files_needed, ids);
    start_server(file_to_execute.c_str(), false/*do_tls*/, std::vector<std::string>());
    if (curr_app)
      remove_directory(ec2i, curr_app->id);
    curr_app = new_app;
  }
  catch(const std::exception& exc)
  {
    anon_log_error("start_server failed: " << exc.what());
    remove_directory(ec2i, current_server_id);
    return teflon_server_failed;
  }
  catch(...)
  {
    anon_log_error("start_server");
    remove_directory(ec2i, current_server_id);
    return teflon_server_failed;
  }

  return teflon_server_running;
}
<commit_msg>debugging<commit_after>/*
 Copyright (c) 2020 ANON authors, see AUTHORS file.

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
*/

#include "sync_teflon_app.h"
#include "log.h"
#include "sproc_mgr.h"
#include <sys/stat.h>
#include <aws/core/Aws.h>
#include <aws/core/utils/Outcome.h>
#include <aws/dynamodb/DynamoDBClient.h>
#include <aws/dynamodb/model/GetItemRequest.h>

namespace
{

struct tef_app
{
  tef_app(const Aws::String& id,
    const Aws::Vector<Aws::String>& filesv,
    Aws::Map<Aws::String, const std::shared_ptr<Aws::DynamoDB::Model::AttributeValue>>& fids)
    : id(id)
  {
    for (auto &f : filesv) {
      files[fids[f]->GetS()] = f;
    }
  }

  Aws::String id;
  std::map<Aws::String, Aws::String> files;
};

bool exe_cmd(const std::string &str)
{
  std::string cmd = "bash -c '" + str + "'";
  auto f = popen(cmd.c_str(), "r");
  if (f)
  {
    auto exit_code = pclose(f);
    if (exit_code != 0)
    {
      anon_log_error("command: " << str << " exited non-zero: " << error_string(exit_code));
      return false;
    }
  }
  else
  {
    anon_log_error("popen failed: " << errno_string());
    return false;
  }
  return true;
}

bool create_empty_directory(const ec2_info &ec2i, const Aws::String &id)
{
  auto dir = ec2i.root_dir;
  if (id.size() != 0)
  {
    dir += "/";
    dir += id.c_str();
  }
  std::ostringstream str;
  str << "rm -rf " << dir << " && mkdir " << dir;
  return exe_cmd(str.str());
}

void remove_directory(const ec2_info &ec2i, const Aws::String &id)
{
  auto dir = ec2i.root_dir;
  if (id.size() != 0)
  {
    dir += "/";
    dir += id.c_str();
  }
  std::ostringstream str;
  str << "rm -rf " << id;
  if (!exe_cmd(str.str()))
    anon_log_error("failed to remove " << id << " directory");
}

std::shared_ptr<tef_app> curr_app;

} // namespace

teflon_state sync_teflon_app(const ec2_info &ec2i)
{
  if (ec2i.user_data_js.find("current_server_primary_key_value") == ec2i.user_data_js.end() || ec2i.user_data_js.find("current_server_primary_key_name") == ec2i.user_data_js.end())
  {
    anon_log_error("no current server info specified in user data - cannot start teflon app");
    return teflon_server_failed;
  }

  if (!curr_app)
  {
    if (!create_empty_directory(ec2i, ""))
      return teflon_server_failed;
  }

  Aws::Client::ClientConfiguration ddb_config;
  if (ec2i.user_data_js.find("current_server_region") != ec2i.user_data_js.end())
    ddb_config.region = ec2i.user_data_js["current_server_region"];
  else
    ddb_config.region = ec2i.default_region;
  Aws::DynamoDB::DynamoDBClient ddbc(ddb_config);

  Aws::DynamoDB::Model::AttributeValue primary_key;
  std::string cs_primary_key = ec2i.user_data_js["current_server_primary_key_value"];
  primary_key.SetS(cs_primary_key.c_str());
  Aws::DynamoDB::Model::GetItemRequest req;
  std::string cs_table_name = ec2i.user_data_js["current_server_table_name"];
  std::string cs_key_name = ec2i.user_data_js["current_server_primary_key_name"];
  req.WithTableName(cs_table_name.c_str())
      .AddKey(cs_key_name.c_str(), primary_key);
  auto outcome = ddbc.GetItem(req);
  if (!outcome.IsSuccess())
  {
    anon_log_error("GetItem failed: " << outcome.GetError());
    return teflon_server_failed;
  }

  auto &map = outcome.GetResult().GetItem();
  auto state_it = map.find("state");
  if (state_it == map.end())
  {
    anon_log_error("current_server record missing required \"state\" field");
    return teflon_server_failed;
  }
  auto state = state_it->second.GetS();
  if (state == "stop")
  {
    anon_log("stopping server");
    return teflon_shut_down;
  }

  if (state != "run")
  {
    anon_log_error("unknown teflon server state: " << state);
    return teflon_server_failed;
  }

  auto id_it = map.find("current_server_id");

  auto end = map.end();
  if (id_it == end)
  {
    anon_log_error("current_server record missing required \"current_server_id\" field");
    return teflon_server_failed;
  }

  auto current_server_id = id_it->second.GetS();
  if (curr_app && current_server_id == curr_app->id)
  {
    anon_log("current server definition matches running server, no-op");
    return teflon_server_running;
  }

  auto files_it = map.find("files");
  auto exe_it = map.find("entry");
  auto ids_it = map.find("fids");
  if (files_it == end || exe_it == end || ids_it == end)
  {
    anon_log_error("current_server record missing required \"files\", \"entry\", and/or \"fids\" field(s)");
    return teflon_server_failed;
  }

  auto files_needed = files_it->second.GetSS();
  auto file_to_execute = exe_it->second.GetS();
  auto ids = ids_it->second.GetM();

  if (ec2i.user_data_js.find("current_server_artifacts_bucket") == ec2i.user_data_js.end() || ec2i.user_data_js.find("current_server_artifacts_key") == ec2i.user_data_js.end())
  {
    anon_log_error("user data missing required fields \"current_server_artifacts_bucket\" and/or \"current_server_artifacts_key\"");
    return teflon_server_failed;
  }
  std::string bucket = ec2i.user_data_js["current_server_artifacts_bucket"];
  std::string key = ec2i.user_data_js["current_server_artifacts_key"];

  std::ostringstream files_cmd;
  for (const auto &f : files_needed)
  {
    if (ids.find(f) == ids.end())
    {
      anon_log_error("file: \"" << f << "\" missing in fids");
      return teflon_server_failed;
    }
    if (curr_app && curr_app->files.find(f) != curr_app->files.end())
    {
      // f matches a file we have already downloaded, so just hard link it
      // to the new directory
      auto existing_file = curr_app->files[f];
      files_cmd << "ln " << ec2i.root_dir << "/" << curr_app->id << "/" << curr_app->files[f]
               << " " << ec2i.root_dir << "/" << current_server_id << "/" << f << " || exit 1 &\n";
    }
    else
    {
      // does not match an existing file, so download it from s3
      files_cmd << "aws s3 --region " << ec2i.default_region << " cp s3://" << bucket << "/" << key << "/" << f
               << " " << ec2i.root_dir << "/" << current_server_id << "/" << f << " --quiet || exit 1 &\n";
    }
  }
  if (!create_empty_directory(ec2i, current_server_id))
    return teflon_server_failed;
  files_cmd << "wait < <(jobs -p)\n";
  anon_log("executing script:\n" << files_cmd.str());
  if (!exe_cmd(files_cmd.str()))
    return teflon_server_failed;

  std::ostringstream ef;
  ef << ec2i.root_dir << "/" << current_server_id << "/" << file_to_execute;
  auto efs = ef.str();
  chmod(efs.c_str(), ACCESSPERMS);

  try {
    auto new_app = std::make_shared<tef_app>(current_server_id, files_needed, ids);
    start_server(efs.c_str(), false/*do_tls*/, std::vector<std::string>());
    if (curr_app)
      remove_directory(ec2i, curr_app->id);
    curr_app = new_app;
  }
  catch(const std::exception& exc)
  {
    anon_log_error("start_server failed: " << exc.what());
    remove_directory(ec2i, current_server_id);
    return teflon_server_failed;
  }
  catch(...)
  {
    anon_log_error("start_server");
    remove_directory(ec2i, current_server_id);
    return teflon_server_failed;
  }

  return teflon_server_running;
}
<|endoftext|>