/* Main method to test math */
int main() {
    // Test matrix math
    struct Matrix a;
    //double valuesa[9] = { 5.0, -2.0, 1.0, 0.0, 3.0, -1.0, 2.0, 0.0, 7.0 };
    double valuesa[16] = { 1.0, 3.0, -2.0, 1.0, 5.0, 1.0, 0.0, -1.0, 0.0, 1.0, 0.0, -2.0, 2.0, -1.0, 0.0, 3.0 };
    newMatrix(&a, valuesa, 4, 4);
    struct Matrix b;
    double valuesb[9] = { 1.0, 2.0, 3.0, 0.0, -4.0, 1.0, 0.0, 3.0, -1.0 };
    newMatrix(&b, valuesb, 3, 3);
    struct Matrix cofa;
    matrixCofactor(&cofa, a);
    printf("A Cofactor=\n");
    matrixToString(cofa);
    struct Matrix inva;
    matrixInverse(&inva, a);
    printf("A Inverse=\n");
    matrixToString(inva);
    printf("A=\n");
    matrixToString(a);
    printf("B=\n");
    matrixToString(b);
    printf("A is %sa square matrix.\n", matrixIsSquare(a) ? "" : "not ");
    printf("B is %sa square matrix.\n", matrixIsSquare(b) ? "" : "not ");
    printf("The determinant of A is %f.\n", matrixDeterminant(a));
    printf("A is %sunique.\n", matrixIsUnique(a) ? "" : "not ");
    printf("The determinant of B is %f.\n", matrixDeterminant(b));
    printf("B is %sunique.\n", matrixIsUnique(b) ? "" : "not ");
    struct Matrix aplusb;
    matrixAdd(&aplusb, a, b);
    printf("A+B=\n");
    matrixToString(aplusb);
    struct Matrix asubb;
    matrixSubtract(&asubb, a, b);
    printf("A-B=\n");
    matrixToString(asubb);
    struct Matrix ascale;
    matrixScale(&ascale, a, 5);
    printf("5A=\n");
    matrixToString(ascale);
    struct Matrix bscale;
    matrixScale(&bscale, b, 5);
    printf("5B=\n");
    matrixToString(bscale);
    printf("A and B are %sthe same size.\n", matrixIsSameSize(a, b) ? "" : "not ");

    printf("A=\n");
    matrixToString(a);
    printf("B=\n");
    matrixToString(b);

    // Test 3D vector math
}
Example #2
0
void writeTMatrixList( std::ofstream *outFile, std::vector<MMatrix>& transformMatrices, bool inverse, float scaleFactor)
{
	for( int matrixId = 0; matrixId < transformMatrices.size(); matrixId++)
	{
		MMatrix tm = transformMatrices[matrixId];
		if( inverse )
			tm = tm.inverse();

		if( matrixId == 0)
		{
			*outFile << "\t\tray_transform " << matrixToString(tm) << "\n"; // normal transform
		}
		else{
			*outFile << "\t\tray_mtransform " << matrixToString(tm) << "\n"; // motion transform
		}
	}
}
Example #3
0
static const VSFrameRef *VS_CC textGetFrame(int n, int activationReason, void **instanceData, void **frameData, VSFrameContext *frameCtx, VSCore *core, const VSAPI *vsapi) {
    TextData *d = static_cast<TextData *>(*instanceData);

    if (activationReason == arInitial) {
        vsapi->requestFrameFilter(n, d->node, frameCtx);
    } else if (activationReason == arAllFramesReady) {
        const VSFrameRef *src = vsapi->getFrameFilter(n, d->node, frameCtx);       

        const VSFormat *frame_format = vsapi->getFrameFormat(src);
        if ((frame_format->sampleType == stInteger && frame_format->bitsPerSample > 16) ||
            (frame_format->sampleType == stFloat && frame_format->bitsPerSample != 32)) {
                vsapi->freeFrame(src);
                vsapi->setFilterError((d->instanceName + ": Only 8..16 bit integer and 32 bit float formats supported").c_str(), frameCtx);
                return nullptr;
        }

        VSFrameRef *dst = vsapi->copyFrame(src, core);

        if (d->filter == FILTER_FRAMENUM) {
            scrawl_text(std::to_string(n), d->alignment, dst, vsapi);
        } else if (d->filter == FILTER_FRAMEPROPS) {
            const VSMap *props = vsapi->getFramePropsRO(dst);
            int numKeys = vsapi->propNumKeys(props);
            int i;
            std::string text = "Frame properties:\n";

            if (!d->props.empty()) {
                for (const auto &iter : d->props) {
                    append_prop(text, iter, props, vsapi);
                }
            } else {
                for (i = 0; i < numKeys; i++) {
                    const char *key = vsapi->propGetKey(props, i);
                    append_prop(text, key, props, vsapi);
                }
            }

            scrawl_text(text, d->alignment, dst, vsapi);
        } else if (d->filter == FILTER_COREINFO) {
            const VSCoreInfo *ci = vsapi->getCoreInfo(core);

            std::string text;
            text.append(ci->versionString).append("\n");
            text.append("Threads: ").append(std::to_string(ci->numThreads)).append("\n");
            text.append("Maximum framebuffer cache size: ").append(std::to_string(ci->maxFramebufferSize)).append(" bytes\n");
            text.append("Used framebuffer cache size: ").append(std::to_string(ci->usedFramebufferSize)).append(" bytes");

            scrawl_text(text, d->alignment, dst, vsapi);
        } else if (d->filter == FILTER_CLIPINFO) {
            const VSMap *props = vsapi->getFramePropsRO(src);
            std::string text = "Clip info:\n";

            if (d->vi->width) {
                text += "Width: " + std::to_string(vsapi->getFrameWidth(dst, 0)) + " px\n";
                text += "Height: " + std::to_string(vsapi->getFrameHeight(dst, 0)) + " px\n";
            } else {
                text += "Width: " + std::to_string(vsapi->getFrameWidth(dst, 0)) + " px (may vary)\n";
                text += "Height: " + std::to_string(vsapi->getFrameHeight(dst, 0)) + " px (may vary)\n";
            }

            int snerr, sderr;
            int sn = int64ToIntS(vsapi->propGetInt(props, "_SARNum", 0, &snerr));
            int sd = int64ToIntS(vsapi->propGetInt(props, "_SARDen", 0, &sderr));
            if (snerr || sderr)
                text += "Aspect ratio: Unknown\n";
            else
                text += "Sample aspect ratio: " + std::to_string(sn) + ":" + std::to_string(sd) + "\n";

            text += "Length: " + std::to_string(d->vi->numFrames) + " frames\n";

            text += "Format name: " + std::string(frame_format->name) + (d->vi->format ? "\n" : " (may vary)\n");

            text += "Color family: " + colorFamilyToString(frame_format->colorFamily) + "\n";
            text += "Sample type: " + std::string(frame_format->sampleType == stInteger ? "Integer" : "Float") + "\n";
            text += "Bits per sample: " + std::to_string(frame_format->bitsPerSample) + "\n";
            text += "Subsampling Height/Width: " + std::to_string(1 << frame_format->subSamplingH) + "x/" + std::to_string(1 << frame_format->subSamplingW) + "x\n";

            int err;
            int matrix = int64ToIntS(vsapi->propGetInt(props, "_Matrix", 0, &err));
            if (err)
                matrix = -1;
            int primaries = int64ToIntS(vsapi->propGetInt(props, "_Primaries", 0, &err));
            if (err)
                primaries = -1;
            int transfer = int64ToIntS(vsapi->propGetInt(props, "_Transfer", 0, &err));
            if (err)
                transfer = -1;
            int range = int64ToIntS(vsapi->propGetInt(props, "_ColorRange", 0, &err));
            if (err)
                range = -1;
            int location = int64ToIntS(vsapi->propGetInt(props, "_ChromaLocation", 0, &err));
            if (err)
                location = -1;
            int field = int64ToIntS(vsapi->propGetInt(props, "_FieldBased", 0, &err));
            if (err)
                field = -1;

            const char *picttype = vsapi->propGetData(props, "_PictType", 0, &err);

            text += "Matrix: " + matrixToString(matrix) + "\n";
            text += "Primaries: " + primariesToString(primaries) + "\n";
            text += "Transfer: " + transferToString(transfer) + "\n";
            text += "Range: " + rangeToString(range) + "\n";
            text += "Chroma Location: " + chromaLocationToString(location) + "\n";
            text += "Field handling: " + fieldBasedToString(field) + "\n";
            text += "Picture type: " + std::string(picttype ? picttype : "Unknown") + "\n";

            if (d->vi->fpsNum && d->vi->fpsDen) {
                text += "Fps: " + std::to_string(d->vi->fpsNum) + "/" + std::to_string(d->vi->fpsDen) + " (" + std::to_string(static_cast<double>(d->vi->fpsNum) / d->vi->fpsDen) + ")\n";
            } else {
                text += "Fps: Unknown\n";
            }

            int fnerr, fderr;
            int fn = int64ToIntS(vsapi->propGetInt(props, "_DurationNum", 0, &fnerr));
            int fd = int64ToIntS(vsapi->propGetInt(props, "_DurationDen", 0, &fderr));
            if (fnerr || fderr) {
                text += "Frame duration: Unknown\n";
            } else {
                text += "Frame duration: " + std::to_string(fn) + "/" + std::to_string(fd) + " (" + std::to_string(static_cast<double>(fn) / fd) + ")\n";
            }

            scrawl_text(text, d->alignment, dst, vsapi);
        } else {
            scrawl_text(d->text, d->alignment, dst, vsapi);
        }

        vsapi->freeFrame(src);
        return dst;
    }

    return nullptr;
}
/**
 * Solves a linear least squares problem to obtain a N degree polynomial that fits
 * the specified input data as nearly as possible.
 *
 * Returns true if a solution is found, false otherwise.
 *
 * The input consists of two vectors of data points X and Y with indices 0..m-1
 * along with a weight vector W of the same size.
 *
 * The output is a vector B with indices 0..n that describes a polynomial
 * that fits the data, such the sum of W[i] * W[i] * abs(Y[i] - (B[0] + B[1] X[i]
 * + B[2] X[i]^2 ... B[n] X[i]^n)) for all i between 0 and m-1 is minimized.
 *
 * Accordingly, the weight vector W should be initialized by the caller with the
 * reciprocal square root of the variance of the error in each input data point.
 * In other words, an ideal choice for W would be W[i] = 1 / var(Y[i]) = 1 / stddev(Y[i]).
 * The weights express the relative importance of each data point.  If the weights are
 * all 1, then the data points are considered to be of equal importance when fitting
 * the polynomial.  It is a good idea to choose weights that diminish the importance
 * of data points that may have higher than usual error margins.
 *
 * Errors among data points are assumed to be independent.  W is represented here
 * as a vector although in the literature it is typically taken to be a diagonal matrix.
 *
 * That is to say, the function that generated the input data can be approximated
 * by y(x) ~= B[0] + B[1] x + B[2] x^2 + ... + B[n] x^n.
 *
 * The coefficient of determination (R^2) is also returned to describe the goodness
 * of fit of the model for the given data.  It is a value between 0 and 1, where 1
 * indicates perfect correspondence.
 *
 * This function first expands the X vector to a m by n matrix A such that
 * A[i][0] = 1, A[i][1] = X[i], A[i][2] = X[i]^2, ..., A[i][n] = X[i]^n, then
 * multiplies it by w[i]./
 *
 * Then it calculates the QR decomposition of A yielding an m by m orthonormal matrix Q
 * and an m by n upper triangular matrix R.  Because R is upper triangular (lower
 * part is all zeroes), we can simplify the decomposition into an m by n matrix
 * Q1 and a n by n matrix R1 such that A = Q1 R1.
 *
 * Finally we solve the system of linear equations given by R1 B = (Qtranspose W Y)
 * to find B.
 *
 * For efficiency, we lay out A and Q column-wise in memory because we frequently
 * operate on the column vectors.  Conversely, we lay out R row-wise.
 *
 * http://en.wikipedia.org/wiki/Numerical_methods_for_linear_least_squares
 * http://en.wikipedia.org/wiki/Gram-Schmidt
 */
static bool solveLeastSquares(const float* x, const float* y,
        const float* w, uint32_t m, uint32_t n, float* outB, float* outDet) {
#if DEBUG_STRATEGY
    ALOGD("solveLeastSquares: m=%d, n=%d, x=%s, y=%s, w=%s", int(m), int(n),
            vectorToString(x, m).c_str(), vectorToString(y, m).c_str(),
            vectorToString(w, m).c_str());
#endif

    // Expand the X vector to a matrix A, pre-multiplied by the weights.
    float a[n][m]; // column-major order
    for (uint32_t h = 0; h < m; h++) {
        a[0][h] = w[h];
        for (uint32_t i = 1; i < n; i++) {
            a[i][h] = a[i - 1][h] * x[h];
        }
    }
#if DEBUG_STRATEGY
    ALOGD("  - a=%s", matrixToString(&a[0][0], m, n, false /*rowMajor*/).c_str());
#endif

    // Apply the Gram-Schmidt process to A to obtain its QR decomposition.
    float q[n][m]; // orthonormal basis, column-major order
    float r[n][n]; // upper triangular matrix, row-major order
    for (uint32_t j = 0; j < n; j++) {
        for (uint32_t h = 0; h < m; h++) {
            q[j][h] = a[j][h];
        }
        for (uint32_t i = 0; i < j; i++) {
            float dot = vectorDot(&q[j][0], &q[i][0], m);
            for (uint32_t h = 0; h < m; h++) {
                q[j][h] -= dot * q[i][h];
            }
        }

        float norm = vectorNorm(&q[j][0], m);
        if (norm < 0.000001f) {
            // vectors are linearly dependent or zero so no solution
#if DEBUG_STRATEGY
            ALOGD("  - no solution, norm=%f", norm);
#endif
            return false;
        }

        float invNorm = 1.0f / norm;
        for (uint32_t h = 0; h < m; h++) {
            q[j][h] *= invNorm;
        }
        for (uint32_t i = 0; i < n; i++) {
            r[j][i] = i < j ? 0 : vectorDot(&q[j][0], &a[i][0], m);
        }
    }
#if DEBUG_STRATEGY
    ALOGD("  - q=%s", matrixToString(&q[0][0], m, n, false /*rowMajor*/).c_str());
    ALOGD("  - r=%s", matrixToString(&r[0][0], n, n, true /*rowMajor*/).c_str());

    // calculate QR, if we factored A correctly then QR should equal A
    float qr[n][m];
    for (uint32_t h = 0; h < m; h++) {
        for (uint32_t i = 0; i < n; i++) {
            qr[i][h] = 0;
            for (uint32_t j = 0; j < n; j++) {
                qr[i][h] += q[j][h] * r[j][i];
            }
        }
    }
    ALOGD("  - qr=%s", matrixToString(&qr[0][0], m, n, false /*rowMajor*/).c_str());
#endif

    // Solve R B = Qt W Y to find B.  This is easy because R is upper triangular.
    // We just work from bottom-right to top-left calculating B's coefficients.
    float wy[m];
    for (uint32_t h = 0; h < m; h++) {
        wy[h] = y[h] * w[h];
    }
    for (uint32_t i = n; i != 0; ) {
        i--;
        outB[i] = vectorDot(&q[i][0], wy, m);
        for (uint32_t j = n - 1; j > i; j--) {
            outB[i] -= r[i][j] * outB[j];
        }
        outB[i] /= r[i][i];
    }
#if DEBUG_STRATEGY
    ALOGD("  - b=%s", vectorToString(outB, n).c_str());
#endif

    // Calculate the coefficient of determination as 1 - (SSerr / SStot) where
    // SSerr is the residual sum of squares (variance of the error),
    // and SStot is the total sum of squares (variance of the data) where each
    // has been weighted.
    float ymean = 0;
    for (uint32_t h = 0; h < m; h++) {
        ymean += y[h];
    }
    ymean /= m;

    float sserr = 0;
    float sstot = 0;
    for (uint32_t h = 0; h < m; h++) {
        float err = y[h] - outB[0];
        float term = 1;
        for (uint32_t i = 1; i < n; i++) {
            term *= x[h];
            err -= term * outB[i];
        }
        sserr += w[h] * w[h] * err * err;
        float var = y[h] - ymean;
        sstot += w[h] * w[h] * var * var;
    }
    *outDet = sstot > 0.000001f ? 1.0f - (sserr / sstot) : 1;
#if DEBUG_STRATEGY
    ALOGD("  - sserr=%f", sserr);
    ALOGD("  - sstot=%f", sstot);
    ALOGD("  - det=%f", *outDet);
#endif
    return true;
}