Port fix from 2.0 to trunk. Problem discovered thanks to Jern-Kuan.

pull/216/head
castano 12 years ago
parent 0eb7c3eb71
commit 897cc78397

@ -84,7 +84,7 @@ inline __device__ __host__ void operator /=(float3 & b, float f)
inline __device__ __host__ bool operator ==(float3 a, float3 b) inline __device__ __host__ bool operator ==(float3 a, float3 b)
{ {
return a.x == b.x && a.y == b.y && a.z == b.z; return a.x == b.x && a.y == b.y && a.z == b.z;
} }
@ -136,12 +136,12 @@ inline __device__ __host__ void operator /=(float2 & b, float f)
{ {
float inv = 1.0f / f; float inv = 1.0f / f;
b.x *= inv; b.x *= inv;
b.y *= inv; b.y *= inv;
} }
inline __device__ __host__ bool operator ==(float2 a, float2 b) inline __device__ __host__ bool operator ==(float2 a, float2 b)
{ {
return a.x == b.x && a.y == b.y; return a.x == b.x && a.y == b.y;
} }
@ -194,210 +194,234 @@ inline __device__ __host__ float lengthSquared(float3 a)
} }
// Use power method to find the first eigenvector. // Use power method to find the first eigenvector.
// http://www.miislita.com/information-retrieval-tutorial/matrix-tutorial-3-eigenvalues-eigenvectors.html // http://www.miislita.com/information-retrieval-tutorial/matrix-tutorial-3-eigenvalues-eigenvectors.html
inline __device__ __host__ float3 firstEigenVector( float matrix[6] ) inline __device__ __host__ float3 firstEigenVector( float matrix[6] )
{ {
// 8 iterations seems to be more than enough. // 8 iterations seems to be more than enough.
float3 row0 = make_float3(matrix[0], matrix[1], matrix[2]);
float3 row1 = make_float3(matrix[1], matrix[3], matrix[4]);
float3 row2 = make_float3(matrix[2], matrix[4], matrix[5]);
float r0 = dot(row0, row0);
float r1 = dot(row1, row1);
float r2 = dot(row2, row2);
float3 v = make_float3(1.0f, 1.0f, 1.0f); float3 v;
for(int i = 0; i < 8; i++) { if (r0 > r1 && r0 > r2) v = row0;
float x = v.x * matrix[0] + v.y * matrix[1] + v.z * matrix[2]; else if (r1 > r2) v = row1;
float y = v.x * matrix[1] + v.y * matrix[3] + v.z * matrix[4]; else v = row2;
float z = v.x * matrix[2] + v.y * matrix[4] + v.z * matrix[5];
float m = max(max(x, y), z);
float iv = 1.0f / m;
if (m == 0.0f) iv = 0.0f;
v = make_float3(x*iv, y*iv, z*iv);
}
return v; //float3 v = make_float3(1.0f, 1.0f, 1.0f);
for(int i = 0; i < 8; i++) {
float x = v.x * matrix[0] + v.y * matrix[1] + v.z * matrix[2];
float y = v.x * matrix[1] + v.y * matrix[3] + v.z * matrix[4];
float z = v.x * matrix[2] + v.y * matrix[4] + v.z * matrix[5];
float m = max(max(x, y), z);
float iv = 1.0f / m;
if (m == 0.0f) iv = 0.0f;
v = make_float3(x*iv, y*iv, z*iv);
}
return v;
} }
inline __device__ bool singleColor(const float3 * colors) inline __device__ bool singleColor(const float3 * colors)
{ {
#if __DEVICE_EMULATION__ #if __DEVICE_EMULATION__
bool sameColor = false; bool sameColor = false;
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
{ {
sameColor &= (colors[i] == colors[0]); sameColor &= (colors[i] == colors[0]);
} }
return sameColor; return sameColor;
#else #else
__shared__ int sameColor[16]; __shared__ int sameColor[16];
const int idx = threadIdx.x; const int idx = threadIdx.x;
sameColor[idx] = (colors[idx] == colors[0]); sameColor[idx] = (colors[idx] == colors[0]);
sameColor[idx] &= sameColor[idx^8]; sameColor[idx] &= sameColor[idx^8];
sameColor[idx] &= sameColor[idx^4]; sameColor[idx] &= sameColor[idx^4];
sameColor[idx] &= sameColor[idx^2]; sameColor[idx] &= sameColor[idx^2];
sameColor[idx] &= sameColor[idx^1]; sameColor[idx] &= sameColor[idx^1];
return sameColor[0]; return sameColor[0];
#endif #endif
} }
inline __device__ void colorSums(const float3 * colors, float3 * sums) inline __device__ void colorSums(const float3 * colors, float3 * sums)
{ {
#if __DEVICE_EMULATION__ #if __DEVICE_EMULATION__
float3 color_sum = make_float3(0.0f, 0.0f, 0.0f); float3 color_sum = make_float3(0.0f, 0.0f, 0.0f);
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
{ {
color_sum += colors[i]; color_sum += colors[i];
} }
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
{ {
sums[i] = color_sum; sums[i] = color_sum;
} }
#else #else
const int idx = threadIdx.x; const int idx = threadIdx.x;
sums[idx] = colors[idx]; sums[idx] = colors[idx];
sums[idx] += sums[idx^8]; sums[idx] += sums[idx^8];
sums[idx] += sums[idx^4]; sums[idx] += sums[idx^4];
sums[idx] += sums[idx^2]; sums[idx] += sums[idx^2];
sums[idx] += sums[idx^1]; sums[idx] += sums[idx^1];
#endif #endif
} }
inline __device__ float3 bestFitLine(const float3 * colors, float3 color_sum, float3 colorMetric) inline __device__ float3 bestFitLine(const float3 * colors, float3 color_sum, float3 colorMetric)
{ {
// Compute covariance matrix of the given colors. // Compute covariance matrix of the given colors.
#if __DEVICE_EMULATION__ #if __DEVICE_EMULATION__
float covariance[6] = {0, 0, 0, 0, 0, 0}; float covariance[6] = {0, 0, 0, 0, 0, 0};
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
{ {
float3 a = (colors[i] - color_sum * (1.0f / 16.0f)) * colorMetric; float3 a = (colors[i] - color_sum * (1.0f / 16.0f)) * colorMetric;
covariance[0] += a.x * a.x; covariance[0] += a.x * a.x;
covariance[1] += a.x * a.y; covariance[1] += a.x * a.y;
covariance[2] += a.x * a.z; covariance[2] += a.x * a.z;
covariance[3] += a.y * a.y; covariance[3] += a.y * a.y;
covariance[4] += a.y * a.z; covariance[4] += a.y * a.z;
covariance[5] += a.z * a.z; covariance[5] += a.z * a.z;
} }
#else #else
const int idx = threadIdx.x; const int idx = threadIdx.x;
float3 diff = (colors[idx] - color_sum * (1.0f / 16.0f)) * colorMetric; float3 diff = (colors[idx] - color_sum * (1.0f / 16.0f)) * colorMetric;
// @@ Eliminate two-way bank conflicts here. // @@ Eliminate two-way bank conflicts here.
// @@ It seems that doing that and unrolling the reduction doesn't help... // @@ It seems that doing that and unrolling the reduction doesn't help...
__shared__ float covariance[16*6]; __shared__ float covariance[16*6];
covariance[6 * idx + 0] = diff.x * diff.x; // 0, 6, 12, 2, 8, 14, 4, 10, 0 covariance[6 * idx + 0] = diff.x * diff.x; // 0, 6, 12, 2, 8, 14, 4, 10, 0
covariance[6 * idx + 1] = diff.x * diff.y; covariance[6 * idx + 1] = diff.x * diff.y;
covariance[6 * idx + 2] = diff.x * diff.z; covariance[6 * idx + 2] = diff.x * diff.z;
covariance[6 * idx + 3] = diff.y * diff.y; covariance[6 * idx + 3] = diff.y * diff.y;
covariance[6 * idx + 4] = diff.y * diff.z; covariance[6 * idx + 4] = diff.y * diff.z;
covariance[6 * idx + 5] = diff.z * diff.z; covariance[6 * idx + 5] = diff.z * diff.z;
for(int d = 8; d > 0; d >>= 1) for(int d = 8; d > 0; d >>= 1)
{ {
if (idx < d) if (idx < d)
{ {
covariance[6 * idx + 0] += covariance[6 * (idx+d) + 0]; covariance[6 * idx + 0] += covariance[6 * (idx+d) + 0];
covariance[6 * idx + 1] += covariance[6 * (idx+d) + 1]; covariance[6 * idx + 1] += covariance[6 * (idx+d) + 1];
covariance[6 * idx + 2] += covariance[6 * (idx+d) + 2]; covariance[6 * idx + 2] += covariance[6 * (idx+d) + 2];
covariance[6 * idx + 3] += covariance[6 * (idx+d) + 3]; covariance[6 * idx + 3] += covariance[6 * (idx+d) + 3];
covariance[6 * idx + 4] += covariance[6 * (idx+d) + 4]; covariance[6 * idx + 4] += covariance[6 * (idx+d) + 4];
covariance[6 * idx + 5] += covariance[6 * (idx+d) + 5]; covariance[6 * idx + 5] += covariance[6 * (idx+d) + 5];
} }
} }
#endif #endif
// Compute first eigen vector. // Compute first eigen vector.
return firstEigenVector(covariance); return firstEigenVector(covariance);
} }
// @@ For 2D this may not be the most efficient method. It's a quadratic equation, right? // @@ For 2D this may not be the most efficient method. It's a quadratic equation, right?
inline __device__ __host__ float2 firstEigenVector2D( float matrix[3] ) inline __device__ __host__ float2 firstEigenVector2D( float matrix[3] )
{ {
// @@ 8 iterations is probably more than enough. // @@ 8 iterations is probably more than enough.
const float3 row0 = make_float2(matrix[0], matrix[1]);
const float3 row1 = make_float2(matrix[1], matrix[2]);
float r0 = lengthSquared(row0);
float r1 = lengthSquared(row1);
float2 v;
if (r0 > r1) v = row0;
v = row1;
float2 v = make_float2(1.0f, 1.0f); //float2 v = make_float2(1.0f, 1.0f);
for(int i = 0; i < 8; i++) { for(int i = 0; i < 8; i++) {
float x = v.x * matrix[0] + v.y * matrix[1]; float x = v.x * matrix[0] + v.y * matrix[1];
float y = v.x * matrix[1] + v.y * matrix[2]; float y = v.x * matrix[1] + v.y * matrix[2];
float m = max(x, y); float m = max(x, y);
float iv = 1.0f / m; float iv = 1.0f / m;
if (m == 0.0f) iv = 0.0f; if (m == 0.0f) iv = 0.0f;
v = make_float2(x*iv, y*iv); v = make_float2(x*iv, y*iv);
} }
return v; return v;
} }
inline __device__ void colorSums(const float2 * colors, float2 * sums) inline __device__ void colorSums(const float2 * colors, float2 * sums)
{ {
#if __DEVICE_EMULATION__ #if __DEVICE_EMULATION__
float2 color_sum = make_float2(0.0f, 0.0f); float2 color_sum = make_float2(0.0f, 0.0f);
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
{ {
color_sum += colors[i]; color_sum += colors[i];
} }
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
{ {
sums[i] = color_sum; sums[i] = color_sum;
} }
#else #else
const int idx = threadIdx.x; const int idx = threadIdx.x;
sums[idx] = colors[idx]; sums[idx] = colors[idx];
sums[idx] += sums[idx^8]; sums[idx] += sums[idx^8];
sums[idx] += sums[idx^4]; sums[idx] += sums[idx^4];
sums[idx] += sums[idx^2]; sums[idx] += sums[idx^2];
sums[idx] += sums[idx^1]; sums[idx] += sums[idx^1];
#endif #endif
} }
inline __device__ float2 bestFitLine(const float2 * colors, float2 color_sum) inline __device__ float2 bestFitLine(const float2 * colors, float2 color_sum)
{ {
// Compute covariance matrix of the given colors. // Compute covariance matrix of the given colors.
#if __DEVICE_EMULATION__ #if __DEVICE_EMULATION__
float covariance[3] = {0, 0, 0}; float covariance[3] = {0, 0, 0};
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
{ {
float2 a = (colors[i] - color_sum * (1.0f / 16.0f)); float2 a = (colors[i] - color_sum * (1.0f / 16.0f));
covariance[0] += a.x * a.x; covariance[0] += a.x * a.x;
covariance[1] += a.x * a.y; covariance[1] += a.x * a.y;
covariance[2] += a.y * a.y; covariance[2] += a.y * a.y;
} }
#else #else
const int idx = threadIdx.x; const int idx = threadIdx.x;
float2 diff = (colors[idx] - color_sum * (1.0f / 16.0f)); float2 diff = (colors[idx] - color_sum * (1.0f / 16.0f));
__shared__ float covariance[16*3]; __shared__ float covariance[16*3];
covariance[3 * idx + 0] = diff.x * diff.x; covariance[3 * idx + 0] = diff.x * diff.x;
covariance[3 * idx + 1] = diff.x * diff.y; covariance[3 * idx + 1] = diff.x * diff.y;
covariance[3 * idx + 2] = diff.y * diff.y; covariance[3 * idx + 2] = diff.y * diff.y;
for(int d = 8; d > 0; d >>= 1) for(int d = 8; d > 0; d >>= 1)
{ {
if (idx < d) if (idx < d)
{ {
covariance[3 * idx + 0] += covariance[3 * (idx+d) + 0]; covariance[3 * idx + 0] += covariance[3 * (idx+d) + 0];
covariance[3 * idx + 1] += covariance[3 * (idx+d) + 1]; covariance[3 * idx + 1] += covariance[3 * (idx+d) + 1];
covariance[3 * idx + 2] += covariance[3 * (idx+d) + 2]; covariance[3 * idx + 2] += covariance[3 * (idx+d) + 2];
} }
} }
#endif #endif
// Compute first eigen vector. // Compute first eigen vector.
return firstEigenVector2D(covariance); return firstEigenVector2D(covariance);
} }

Loading…
Cancel
Save