Пример #1
0
static void test_set_row_col_major(skiatest::Reporter* reporter) {
    SkMatrix44 a(SkMatrix44::kUninitialized_Constructor);
    SkMatrix44 b(SkMatrix44::kUninitialized_Constructor);

    for (int row = 0; row < 4; ++row) {
        for (int col = 0; col < 4; ++col) {
            a.setDouble(row, col, row * 4 + col);
        }
    }

    double bufferd[16];
    float bufferf[16];
    a.asColMajord(bufferd);
    b.setColMajord(bufferd);
    REPORTER_ASSERT(reporter, nearly_equal(a, b));
    b.setRowMajord(bufferd);
    b.transpose();
    REPORTER_ASSERT(reporter, nearly_equal(a, b));
    a.asColMajorf(bufferf);
    b.setColMajorf(bufferf);
    REPORTER_ASSERT(reporter, nearly_equal(a, b));
    b.setRowMajorf(bufferf);
    b.transpose();
    REPORTER_ASSERT(reporter, nearly_equal(a, b));
}
Пример #2
0
/* Updating the Mobot Pose in the Database of this Node */
void refreshPose(int id, geometry_msgs::Pose2D pose) {
	double newTheta;
	mobots[id - 1].x += pose.x;
	mobots[id - 1].y += pose.y;
	newTheta = mobots[id - 1].theta + pose.theta;
	//if Mobot is turned around 360°, then start with 0°
	if ((nearly_equal(newTheta, 2 * pi, 0.01)) 
		|| (nearly_equal(newTheta, -2 * pi, 0.01))) {
		mobots[id - 1].theta = fmod(newTheta, 2 * pi);
	} else {
		mobots[id - 1].theta += pose.theta;
	}
}
Пример #3
0
static bool compare_procs(SkXfermodeProc proc32, SkXfermodeProc4f proc4f) {
    const float kTolerance = 1.0f / 255;

    const SkColor colors[] = {
        0, 0xFF000000, 0xFFFFFFFF, 0x80FF0000
    };

    for (auto s32 : colors) {
        SkPMColor s_pm32 = SkPreMultiplyColor(s32);
        SkPM4f    s_pm4f = SkColor4f::FromColor(s32).premul();
        for (auto d32 : colors) {
            SkPMColor d_pm32 = SkPreMultiplyColor(d32);
            SkPM4f    d_pm4f = SkColor4f::FromColor(d32).premul();

            SkPMColor r32 = proc32(s_pm32, d_pm32);
            SkPM4f    r4f = proc4f(s_pm4f, d_pm4f);

            SkPM4f r32_4f = SkPM4f::FromPMColor(r32);
            if (!nearly_equal(r4f, r32_4f, kTolerance)) {
                return false;
            }
        }
    }
    return true;
}
Пример #4
0
static void TestGeometry(skiatest::Reporter* reporter) {
    SkPoint pts[3], dst[5];

    pts[0].set(0, 0);
    pts[1].set(100, 50);
    pts[2].set(0, 100);

    int count = SkChopQuadAtMaxCurvature(pts, dst);
    REPORTER_ASSERT(reporter, count == 1 || count == 2);

    pts[0].set(0, 0);
    pts[1].set(SkIntToScalar(3), 0);
    pts[2].set(SkIntToScalar(3), SkIntToScalar(3));
    SkConvertQuadToCubic(pts, dst);
    const SkPoint cubic[] = {
        { 0, 0, },
        { SkIntToScalar(2), 0, },
        { SkIntToScalar(3), SkIntToScalar(1), },
        { SkIntToScalar(3), SkIntToScalar(3) },
    };
    for (int i = 0; i < 4; ++i) {
        REPORTER_ASSERT(reporter, nearly_equal(cubic[i], dst[i]));
    }

    testChopCubic(reporter);
}
Пример #5
0
inline void assert_convert_d(cpcl::BasicStringPiece<CharType, std::char_traits<CharType> > const &s, bool convert, T value = T()) {
  T r;
  assert(TryConvert(s, &r) == convert);
  if (convert) {
    assert(nearly_equal(r, value));
  }
}
Пример #6
0
DEF_TEST(Geometry, reporter) {
    SkPoint pts[3], dst[5];

    pts[0].set(0, 0);
    pts[1].set(100, 50);
    pts[2].set(0, 100);

    int count = SkChopQuadAtMaxCurvature(pts, dst);
    REPORTER_ASSERT(reporter, count == 1 || count == 2);

    pts[0].set(0, 0);
    pts[1].set(3, 0);
    pts[2].set(3, 3);
    SkConvertQuadToCubic(pts, dst);
    const SkPoint cubic[] = {
        { 0, 0, }, { 2, 0, }, { 3, 1, }, { 3, 3 },
    };
    for (int i = 0; i < 4; ++i) {
        REPORTER_ASSERT(reporter, nearly_equal(cubic[i], dst[i]));
    }

    testChopCubic(reporter);
    test_evalquadat(reporter);
    test_conic(reporter);
    test_cubic_tangents(reporter);
    test_quad_tangents(reporter);
    test_conic_tangents(reporter);
}
Пример #7
0
static bool nearly_equal(const SkPM4f a, const SkPM4f& b, float tol = kTolerance) {
    for (int i = 0; i < 4; ++i) {
        if (!nearly_equal(a.fVec[i], b.fVec[i], tol)) {
            return false;
        }
    }
    return true;
}
Пример #8
0
static bool compare_spans(const SkPM4f span4f[], const SkPMColor span4b[], int count,
                          float tolerance = 1.0f/255) {
    for (int i = 0; i < count; ++i) {
        SkPM4f c0 = SkPM4f::FromPMColor(span4b[i]);
        SkPM4f c1 = span4f[i];
        if (!nearly_equal(c0, c1, tolerance)) {
            return false;
        }
    }
    return true;
}
Пример #9
0
static bool check_decompScale(const SkMatrix& matrix) {
    SkSize scale;
    SkMatrix remaining;

    if (!matrix.decomposeScale(&scale, &remaining)) {
        return false;
    }
    if (scale.width() <= 0 || scale.height() <= 0) {
        return false;
    }
    remaining.preScale(scale.width(), scale.height());
    return nearly_equal(matrix, remaining);
}
Пример #10
0
char test_polyval()
{
    double p[] = {1., 2., -3.};
    double inputs[] = {0., 1., 2., 3.};
    double expected[] = {-3., 0., 5., 12.};
    double e = 0.00001;
    int i=0;
    printf("test_polyval... ");

    for(i=0;i<4;i++)
        if(!nearly_equal(expected[i], polyval(p,3,inputs[i]), e)) 
            return false;
    return true;
}
Пример #11
0
static void test_transpose(skiatest::Reporter* reporter) {
    SkMatrix44 a;
    SkMatrix44 b;

    int i = 0;
    for (int row = 0; row < 4; ++row) {
        for (int col = 0; col < 4; ++col) {
            a.setDouble(row, col, i);
            b.setDouble(col, row, i++);
        }
    }

    a.transpose();
    REPORTER_ASSERT(reporter, nearly_equal(a, b));
}
Пример #12
0
DEF_TEST(Color4f_premul, reporter) {
    SkRandom rand;

    for (int i = 0; i < 1000000; ++i) {
        // First just test opaque colors, so that the premul should be exact
        SkColor4f c4 {
            1, rand.nextUScalar1(), rand.nextUScalar1(), rand.nextUScalar1()
        };
        SkPM4f pm4 = c4.premul();
        REPORTER_ASSERT(reporter, pm4.a() == c4.fA);
        REPORTER_ASSERT(reporter, pm4.r() == c4.fA * c4.fR);
        REPORTER_ASSERT(reporter, pm4.g() == c4.fA * c4.fG);
        REPORTER_ASSERT(reporter, pm4.b() == c4.fA * c4.fB);

        // We compare with a tolerance, in case our premul multiply is implemented at slightly
        // different precision than the test code.
        c4.fA = rand.nextUScalar1();
        pm4 = c4.premul();
        REPORTER_ASSERT(reporter, pm4.fVec[SK_A_INDEX] == c4.fA);
        REPORTER_ASSERT(reporter, nearly_equal(pm4.r(), c4.fA * c4.fR));
        REPORTER_ASSERT(reporter, nearly_equal(pm4.g(), c4.fA * c4.fG));
        REPORTER_ASSERT(reporter, nearly_equal(pm4.b(), c4.fA * c4.fB));
    }
}
Пример #13
0
static void test_3x3_conversion(skiatest::Reporter* reporter) {
    SkMScalar values4x4[16] = { 1, 2, 3, 4,
                                5, 6, 7, 8,
                                9, 10, 11, 12,
                                13, 14, 15, 16
                              };
    SkScalar values3x3[9] = { 1, 2, 4,
                              5, 6, 8,
                              13, 14, 16
                            };
    SkMScalar values4x4flattened[16] = { 1, 2, 0, 4,
                                         5, 6, 0, 8,
                                         0, 0, 1, 0,
                                         13, 14, 0, 16
                                       };
    SkMatrix44 a44(SkMatrix44::kUninitialized_Constructor);
    a44.setRowMajor(values4x4);

    SkMatrix a33 = a44;
    SkMatrix expected33;
    for (int i = 0; i < 9; i++) expected33[i] = values3x3[i];
    REPORTER_ASSERT(reporter, expected33 == a33);

    SkMatrix44 a44flattened = a33;
    SkMatrix44 expected44flattened(SkMatrix44::kUninitialized_Constructor);
    expected44flattened.setRowMajor(values4x4flattened);
    REPORTER_ASSERT(reporter, nearly_equal(a44flattened, expected44flattened));

    // Test that a point with a Z value of 0 is transformed the same way.
    SkScalar vec4[4] = { 2, 4, 0, 8 };
    SkScalar vec3[3] = { 2, 4, 8 };

    SkScalar vec4transformed[4];
    SkScalar vec3transformed[3];
    SkScalar vec4transformed2[4];
    a44.mapScalars(vec4, vec4transformed);
    a33.mapHomogeneousPoints(vec3transformed, vec3, 1);
    a44flattened.mapScalars(vec4, vec4transformed2);
    REPORTER_ASSERT(reporter, nearly_equal_scalar(vec4transformed[0], vec3transformed[0]));
    REPORTER_ASSERT(reporter, nearly_equal_scalar(vec4transformed[1], vec3transformed[1]));
    REPORTER_ASSERT(reporter, nearly_equal_scalar(vec4transformed[3], vec3transformed[2]));
    REPORTER_ASSERT(reporter, nearly_equal_scalar(vec4transformed[0], vec4transformed2[0]));
    REPORTER_ASSERT(reporter, nearly_equal_scalar(vec4transformed[1], vec4transformed2[1]));
    REPORTER_ASSERT(reporter, !nearly_equal_scalar(vec4transformed[2], vec4transformed2[2]));
    REPORTER_ASSERT(reporter, nearly_equal_scalar(vec4transformed[3], vec4transformed2[3]));
}
Пример #14
0
static void test_invert(skiatest::Reporter* reporter) {
    SkMatrix44 inverse(SkMatrix44::kUninitialized_Constructor);
    double inverseData[16];

    SkMatrix44 identity(SkMatrix44::kIdentity_Constructor);
    identity.invert(&inverse);
    inverse.asRowMajord(inverseData);
    assert16<double>(reporter, inverseData,
                     1, 0, 0, 0,
                     0, 1, 0, 0,
                     0, 0, 1, 0,
                     0, 0, 0, 1);

    SkMatrix44 translation(SkMatrix44::kUninitialized_Constructor);
    translation.setTranslate(2, 3, 4);
    translation.invert(&inverse);
    inverse.asRowMajord(inverseData);
    assert16<double>(reporter, inverseData,
                     1, 0, 0, -2,
                     0, 1, 0, -3,
                     0, 0, 1, -4,
                     0, 0, 0, 1);

    SkMatrix44 scale(SkMatrix44::kUninitialized_Constructor);
    scale.setScale(2, 4, 8);
    scale.invert(&inverse);
    inverse.asRowMajord(inverseData);
    assert16<double>(reporter, inverseData,
                     0.5, 0,    0,     0,
                     0,   0.25, 0,     0,
                     0,   0,    0.125, 0,
                     0,   0,    0,     1);

    SkMatrix44 scaleTranslation(SkMatrix44::kUninitialized_Constructor);
    scaleTranslation.setScale(32, 128, 1024);
    scaleTranslation.preTranslate(2, 3, 4);
    scaleTranslation.invert(&inverse);
    inverse.asRowMajord(inverseData);
    assert16<double>(reporter, inverseData,
                     0.03125,  0,          0,            -2,
                     0,        0.0078125,  0,            -3,
                     0,        0,          0.0009765625, -4,
                     0,        0,          0,             1);

    SkMatrix44 rotation(SkMatrix44::kUninitialized_Constructor);
    rotation.setRotateDegreesAbout(0, 0, 1, 90);
    rotation.invert(&inverse);
    SkMatrix44 expected(SkMatrix44::kUninitialized_Constructor);
    double expectedInverseRotation[16] =
    {   0,  1, 0, 0,
        -1, 0, 0, 0,
        0,  0, 1, 0,
        0,  0, 0, 1
    };
    expected.setRowMajord(expectedInverseRotation);
    REPORTER_ASSERT(reporter, nearly_equal(expected, inverse));

    SkMatrix44 affine(SkMatrix44::kUninitialized_Constructor);
    affine.setRotateDegreesAbout(0, 0, 1, 90);
    affine.preScale(10, 20, 100);
    affine.preTranslate(2, 3, 4);
    affine.invert(&inverse);
    double expectedInverseAffine[16] =
    {   0,    0.1,  0,   -2,
        -0.05, 0,   0,   -3,
        0,     0,  0.01, -4,
        0,     0,   0,   1
    };
    expected.setRowMajord(expectedInverseAffine);
    REPORTER_ASSERT(reporter, nearly_equal(expected, inverse));

    SkMatrix44 perspective(SkMatrix44::kIdentity_Constructor);
    perspective.setDouble(3, 2, 1.0);
    perspective.invert(&inverse);
    double expectedInversePerspective[16] =
    {   1, 0,  0, 0,
        0, 1,  0, 0,
        0, 0,  1, 0,
        0, 0, -1, 1
    };
    expected.setRowMajord(expectedInversePerspective);
    REPORTER_ASSERT(reporter, nearly_equal(expected, inverse));

    SkMatrix44 affineAndPerspective(SkMatrix44::kIdentity_Constructor);
    affineAndPerspective.setDouble(3, 2, 1.0);
    affineAndPerspective.preScale(10, 20, 100);
    affineAndPerspective.preTranslate(2, 3, 4);
    affineAndPerspective.invert(&inverse);
    double expectedInverseAffineAndPerspective[16] =
    {   0.1, 0,    2,   -2,
        0,  0.05,  3,   -3,
        0,   0,   4.01, -4,
        0,   0,   -1,    1
    };
    expected.setRowMajord(expectedInverseAffineAndPerspective);
    REPORTER_ASSERT(reporter, nearly_equal(expected, inverse));
}
Пример #15
0
static bool is_identity(const SkMatrix44& m) {
    SkMatrix44 identity(SkMatrix44::kIdentity_Constructor);
    return nearly_equal(m, identity);
}
Пример #16
0
static bool is_identity(const SkMatrix& m) {
    SkMatrix identity;
    identity.reset();
    return nearly_equal(m, identity);
}
Пример #17
0
int main() {
  int i,j,k;
  double s;

#if 1



  std::vector< std::vector< std::vector<double> > > patients(count);
  
  for(i = 0; i<count; ++i) {
    std::cout << files[i] << std::endl;
    patients[i] = Patient(folder_name + files[i]).data;
  }

  gsl_matrix* A_avg = gsl_matrix_alloc(3, 64);
  for(i = 0; i<3; ++i) {
    for(j = 0; j<64; ++j) { 
      s = 0;
      for(k = 0; k < count; ++k) {
        s+=patients[k][i][j];
      }
      gsl_matrix_set(A_avg, i, j, s/count);            
    }
  }
  // gsl_matrix_print(A_avg, 3, 64);


  gsl_matrix* S = gsl_matrix_alloc(3, 64);
  for(i = 0; i<3; ++i) {
    for(j = 0; j<64; ++j) { 
      s = 0;
      for(k = 0; k < count; ++k) {
        s += pow((patients[k][i][j] - gsl_matrix_get(A_avg, i, j)), 2);            
      }
      gsl_matrix_set(S, i, j, sqrt(s/count));            	
    }
  }
  // gsl_matrix_print(S, 3, 64);
  gsl_matrix *T[count];    
  for(k = 0; k < count; ++k) {
    T[k] =  gsl_matrix_alloc(3, 64);
    for(i = 0; i<3; ++i) {
      for(j = 0; j<64; ++j) { 
        s = (patients[k][i][j] - gsl_matrix_get(A_avg, i, j)) / gsl_matrix_get(S, i, j);            
        gsl_matrix_set(T[k], i, j, s);            	
      }
    }
  }

  size_t cube_sizes[3] = {3, 64, count};
  Tensor<3> cube(cube_sizes);
  size_t matrix_sizes[3] = {cube.size(), 1};
  Tensor<2> matrix(matrix_sizes);
  int M, N;
  std::cout << cube.size() << std::endl;
  for (size_t offset = 0; offset < cube.size(); ++offset) {
    i = offset/(3*64);
    j = (offset%(3*64))/64;
    k = (offset%(3*64))%64;
    cube.data[offset] = gsl_matrix_get(T[i], j, k); // patients[i][j][k];
  }

#else

  size_t cube_sizes[3] = {3, 3, 3};
  Tensor<3> cube(cube_sizes);
  size_t matrix_sizes[3] = {cube.size(), 1};
  Tensor<2> matrix(matrix_sizes);
  int M, N;

  double tdata[27] = {
    0.9073,  0.7158, -0.3698,
    0.8924, -0.4898,  2.4288,
    2.1488,  0.3054,  2.3753,

    1.7842,  1.6970,  0.0151,
    1.7753, -1.5077,  4.0337,
    4.2495,  0.3207,  4.7146,

    2.1236, -0.0740,  1.4429,
   -0.6631,  1.9103, -1.7495,
    1.8260,  2.1335, -0.2716
  };

  for (size_t offset = 0; offset < cube.size(); ++offset) {
    cube.data[offset] = tdata[offset];
  }

#endif

  /* FLATTEN X */
  // std::cout << "X flatten:" << std::endl;
  cube.flatten(matrix, 0);
  // print(matrix);

  M = (int) matrix.sizes[1];
  N = (int) matrix.sizes[0];

  gsl_matrix* Ax = TensorToGSLMatrix(matrix);
	gsl_matrix* Ux;
  gsl_matrix* Vx;
  gsl_vector* Sx;
  gsl_vector* workx;

  //gsl_matrix_print(Ax, Ax->size1, Ax->size2);
  workx = gsl_vector_alloc(N);
  Sx = gsl_vector_alloc(N);
  Vx = gsl_matrix_alloc(N, N);

  gsl_linalg_SV_decomp(Ax, Vx, Sx, workx);
  Ux = Ax;
  //std::cout << "A = U S V^T" << std::endl;
  //std::cout << "U" << std::endl;
  //gsl_matrix_print(Ux, M, N);
  std::cout << "S1" << std::endl;
  gsl_vector_print(Sx, N);
  //std::cout << "V" << std::endl;
  //gsl_matrix_print(Vx, Vx->size1, Vx->size2);
  //std::cout << "work" << std::endl;
  //gsl_vector_print(workx, N);

  if (M < N) {
    Vx = gsl_matrix_alloc(Ux->size1, Ux->size1);
    for(i = 0; i < Ux->size1; ++i) {
      for(j = 0; j < Ux->size1; ++j) {
        if (j < Ux->size2 )
          gsl_matrix_set(Vx, j, i, gsl_matrix_get(Ux,i,j));
        else
          gsl_matrix_set(Vx, j, i, 0.0);
      }
    }
  }




  /* FLATTEN Y */
  //std::cout << "Y flatten:" << std::endl;
  cube.flatten(matrix, 1);
  //print(matrix);
  M = (int) matrix.sizes[1];
  N = (int) matrix.sizes[0];

  gsl_matrix* Ay = TensorToGSLMatrix(matrix);
	gsl_matrix* Uy;
  gsl_matrix* Vy;
  gsl_vector* Sy;
  gsl_vector* worky;

  //gsl_matrix_print(Ay, Ay->size1, Ay->size2);
  worky = gsl_vector_alloc(Ay->size2);
  Sy = gsl_vector_alloc(Ay->size2);
  Vy = gsl_matrix_alloc(Ay->size2, Ay->size2);

  gsl_linalg_SV_decomp(Ay, Vy, Sy, worky);
  Uy = Ay;
  //std::cout << "A = U S V^T" << std::endl;
  //std::cout << "U" << std::endl;
  //gsl_matrix_print(Uy, Uy->size1, Uy->size2);
  std::cout << "S2" << std::endl;
  gsl_vector_print(Sy, Ay->size2);
  //std::cout << "V" << std::endl;
  //gsl_matrix_print(Vy, Vy->size1, Vy->size2);
  //std::cout << "work" << std::endl;
  //gsl_vector_print(worky, Ay->size2);

  if (M < N) {
    Vy = gsl_matrix_alloc(Uy->size1, Uy->size1);
    for(i = 0; i < Uy->size1; ++i) {
      for(j = 0; j < Uy->size1; ++j) {
        if (j < Uy->size2 )
          gsl_matrix_set(Vy, j, i, gsl_matrix_get(Uy,i,j));
        else
          gsl_matrix_set(Vy, j, i, 0.0);
      }
    }
  }

  /* FLATTEN Z */
  //std::cout << "Z flatten:" << std::endl;
  cube.flatten(matrix, 2);
  //print(matrix);

  M = (int) matrix.sizes[1];
  N = (int) matrix.sizes[0];

  gsl_matrix* Az = TensorToGSLMatrix(matrix);
	gsl_matrix* Uz;
  gsl_matrix* Vz;
  gsl_vector* Sz;
  gsl_vector* workz;

  //gsl_matrix_print(Az, Az->size1, Az->size2);
  workz = gsl_vector_alloc(Az->size2);
  Sz = gsl_vector_alloc(Az->size2);
  Vz = gsl_matrix_alloc(Az->size2, Az->size2);
  gsl_linalg_SV_decomp(Az, Vz, Sz, workz);
  Uz = Az;
  //std::cout << "A = U S V^T" << std::endl;
  //std::cout << "U" << std::endl;
  //gsl_matrix_print(Uz, Uz->size2, Uz->size2);
  std::cout << "S3" << std::endl;
  gsl_vector_print(Sz, Az->size2);
  //std::cout << "V" << std::endl;
  //gsl_matrix_print(Vz, Vz->size1, Vz->size2);
  //std::cout << "work" << std::endl;
  //gsl_vector_print(workz, Az->size2);

  if (M < N) {
    Vz = gsl_matrix_alloc(Uz->size1, Uz->size1);
    for(i = 0; i < Uz->size1; ++i) {
      for(j = 0; j < Uz->size1; ++j) {
        if (j < Uy->size2 )
          gsl_matrix_set(Vz, j, i, gsl_matrix_get(Uz,i,j));
        else
          gsl_matrix_set(Vz, j, i, 0.0);
      }
    }
  }

/*
  gsl_matrix *Vx_t, *Uy_t, *Vz_t;
  Vx_t = gsl_matrix_alloc(Vx->size2, Vx->size1);
  gsl_matrix_transpose_memcpy (Vx_t, Vx);

  std::cout << "M = " << Uy->size1 << " N = " << Uy->size2 << std::endl;
  Uy_t = gsl_matrix_alloc(Uy->size1, Uy->size1);
  for(i = 0; i < Uy->size1; ++i) {
    for(j = 0; j < Uy->size1; ++j) {
      if (j < Uy->size2 )
        gsl_matrix_set(Uy_t, j, i, gsl_matrix_get(Uy,i,j));
      else
        gsl_matrix_set(Uy_t, j, i, 0.0);
    }
  }
  //gsl_matrix_transpose_memcpy (Uy_t, Uy);
  gsl_matrix_print(Uy_t,64,64);

  Vz_t = gsl_matrix_alloc(Vz->size2, Vz->size1);
  gsl_matrix_transpose_memcpy (Vz_t, Vz);

  std::cout << "M = " << Uy_t->size1 << " N = " << Uy_t->size2 << std::endl;
 */

  Tensor<3> G(cube_sizes);
  /* compute G */ {
    gsl_matrix *Vs[3] = {Vx, Vy, Vz};
    double component, summand;

    for(IndexIterator<3> IJK(cube_sizes); IJK; ++IJK) {
      component = 0.0;
      for(IndexIterator<3> ijk(cube_sizes); ijk; ++ijk) {
        summand = cube[*ijk];
        for (size_t dim = 0; dim < 3; ++dim) {
          summand *= gsl_matrix_get(Vs[dim], (*IJK)[dim], (*ijk)[dim]);
        }
        component += summand;
      }
      G[*IJK] = component;
    }
  }

  /* HOSVD(cube) = G * Vs[0] * Vs[1] * Vs[2] */

  /* validate result */ {
    Tensor<3> T(cube_sizes);
    
    gsl_matrix *Vs[3] = {Vx, Vy, Vz};
    double component, summand;

    for(IndexIterator<3> ijk(cube_sizes); ijk; ++ijk) {
      component = 0.0;
      for(IndexIterator<3> IJK(cube_sizes); IJK; ++IJK) {
        summand = G[*IJK];
        for (size_t dim = 0; dim < 3; ++dim) {
          summand *= gsl_matrix_get(Vs[dim], (*IJK)[dim], (*ijk)[dim]);
        }
        component += summand;
      }
      T[*ijk] = component;
    }

    /* T is restored cube tensor */
    bool valid_HOSVD = true;

    for(IndexIterator<3> ijk(cube_sizes); ijk; ++ijk) {
      if (!nearly_equal(cube[*ijk], T[*ijk], 1e-3)) {
        // wrong HOSVD
        valid_HOSVD = false;

        printf("Error in HOSVD: [");
        for (size_t dim = 0; dim < 3; ++dim) {
          printf("%d%c ", (*ijk)[dim], dim == 2 ? ']' : ',');
        }
        printf("%.15lf != %.15lf\n", cube[*ijk], T[*ijk]);
      }
    }
    if (valid_HOSVD) {
      printf("OK: HOSVD work!\n");
    } else {
      printf("HOSVD computation FAILED.\n");
    }
  }
 

  gsl_matrix *Vx_t, *tmp[count], *Z[count], *Z_avg;
  Vx_t = gsl_matrix_alloc(Vx->size2, Vx->size1);
  gsl_matrix_transpose_memcpy (Vx_t, Vx);
  


    gsl_blas_dgemm (CblasNoTrans, CblasNoTrans, 1.0, tmp[i], Vy, 0.0, Z[i]);
  }