initial check in

This commit is contained in:
2012-12-06 21:43:03 +04:00
commit 4bc273824d
179 changed files with 29415 additions and 0 deletions

1582
testTransform/_transform.cpp Normal file

File diff suppressed because it is too large Load Diff

1408
testTransform/_transform.h Normal file

File diff suppressed because it is too large Load Diff

570
testTransform/main.cpp Normal file
View File

@@ -0,0 +1,570 @@
/*
* SYNOPSYS CONFIDENTIAL - This is an unpublished, proprietary work of Synopsys,
* Inc., and is fully protected under copyright and trade secret laws. You may
* not view, use, disclose, copy, or distribute this file or any information
* contained herein except pursuant to a valid written license from Synopsys.
*/
#include <fstream>
#include <iomanip>
#include "../getCurrentTime2.h"
#include <base/ssetypes.h>
#include <base/transform.h>
#include "transform2.h"
#ifdef WIN32
#include <process.h>
#endif
//
// Forward declarations.
//
void print_result( double, double );
#define SCALE 100
////////////////////////////////////////////////////////////////////////////
//
// The sample transformations.
//
struct tsmpl_s
{
double xloc;
double yloc;
double mag;
double rot;
bool flip;
}
tsmpl[] =
{
{0,0,1,0,0},
{0,0,1,90,0},
{0,0,1,180,0},
{0,0,1,270,0},
{0,0,1,0,1},
{0,0,1,90,1},
{0,0,1,180,1},
{0,0,1,270,1},
{1000,1000,1,0,0},
{1000,1000,1,90,0},
{1000,1000,1,180,0},
{1000,1000,1,270,0},
{1000,1000,1,0,1},
{1000,1000,1,90,1},
{1000,1000,1,180,1},
{1000,1000,1,270,1},
{1000,1000,10,0,0},
{1000,1000,10,90,0},
{1000,1000,10,180,0},
{1000,1000,10,270,0},
{1000,1000,10,0,1},
{1000,1000,10,90,1},
{1000,1000,10,180,1},
{1000,1000,10,270,1},
{1000,1000,10,0+45,0},
{1000,1000,10,90+45,0},
{1000,1000,10,180+45,0},
{1000,1000,10,270+45,0},
{1000,1000,10,0+45,1},
{1000,1000,10,90+45,1},
{1000,1000,10,180+45,1},
{1000,1000,10,270+45,1},
{1000,1000,10,0+30,0},
{1000,1000,10,90+30,1},
{1000,1000,10,0+60,0},
{1000,1000,10,90+60,1},
{1000,1000,10,123,1},
{1000,1000,10,321,1},
{1000,1000,10,17,1},
{1000,1000,10,71,1},
{1000,1000,1,360,0},
{0,0,1,0,0}
};
#define tsmpl_count (sizeof(tsmpl)/sizeof(tsmpl_s))
template <class T>
T mktrans( int i )
{
assert( i < tsmpl_count );
return T(
tsmpl[i].xloc,
tsmpl[i].yloc,
tsmpl[i].flip != 0,
tsmpl[i].rot,
tsmpl[i].mag
);
}
////////////////////////////////////////////////////////////////////////////
//
// The sample rectangles.
//
struct rsmpl_s
{
double l;
double b;
double r;
double t;
}
rsmpl[] =
{
{10000,10000,100000,100000},
{1000,1000,1000,1000},
{0,0,1000,1000}
};
#define rsmpl_count (sizeof(rsmpl)/sizeof(rsmpl_s))
template <class C>
pod::rectangle<C> mkrect( int i )
{
assert( i < rsmpl_count );
return pod::rectangle<C>(
C(rsmpl[i].l),
C(rsmpl[i].b),
C(rsmpl[i].r),
C(rsmpl[i].t)
);
}
////////////////////////////////////////////////////////////////////////////
//
// The sample points.
//
struct psmpl_s
{
double x;
double y;
}
psmpl[] =
{
{100000,100000},
{10000,10000},
{1000,1000},
{1,1},
{0,0}
};
#define psmpl_count (sizeof(psmpl)/sizeof(psmpl_s))
template <class C>
pod::point<C> mkpt( int i )
{
assert( i < psmpl_count );
return pod::point<C>(
C(psmpl[i].x),
C(psmpl[i].y)
);
}
////////////////////////////////////////////////////////////////////////////
//
// log.
//
std::ofstream out;
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
template< class T, class P, int nProbs >
class modify
{
T trns;
P src;
P dest;
public:
modify( const T& t, const P& p )
{
trns = t;
src = p;
}
__forceinline void operator() ()
{
for( int i = nProbs; i; --i )
trns.modify( src, dest );
}
};
template< class T, class P, int nProbs >
class modify2
{
T trns;
P src;
public:
modify2( const T& t, const P& p )
{
trns = t;
src = p;
}
__forceinline void operator() ()
{
for( int i = nProbs; i; --i )
{
volatile P p = trns.modify( src );
}
}
};
template< class P,
int nProbes >
void test( const base::transform& t1, const base2::transform& t2, const P& p )
{
const int n = SCALE;
typedef modify<base::transform,P,n> modify1_type;
double dblMin1 = mesure<modify1_type>( modify1_type( t1, p ), nProbes );
dblMin1 /= n;
typedef modify<base2::transform,P,n> modify2_type;
double dblMin2 = mesure<modify2_type>( modify2_type( t2, p ), nProbes );
dblMin2 /= n;
typedef modify2<base::transform,P,n> modify21_type;
double dblMin21 = mesure<modify21_type>( modify21_type( t1, p ), nProbes );
dblMin21 /= n;
typedef modify2<base2::transform,P,n> modify22_type;
double dblMin22 = mesure<modify22_type>( modify22_type( t2, p ), nProbes );
dblMin22 /= n;
print_result( dblMin1, dblMin2 );
print_result( dblMin21, dblMin22 );
}
template< class P, int nProbes >
void testTrans( int i, const P& p )
{
out << "<tr>";
#if 0
out << "<td>rot:" << tsmpl[i].rot
<< " flip:" << tsmpl[i].flip
<< " mag:" << tsmpl[i].mag
<< " x:" << tsmpl[i].xloc
<< " y:" << tsmpl[i].yloc
<< "</td>";
#endif
test<P,nProbes>(mktrans<base::transform>(i),
mktrans<base2::transform>(i),
p);
out << "</tr>" << std::endl;
}
template< class P,
int nProbes >
void testAllTrans( const P& p )
{
for ( int i = 0; i < tsmpl_count; ++i )
testTrans<P,nProbes>(i,p);
}
template< class C,
int nProbes >
void testAllPt()
{
for ( int i = 0; i < psmpl_count; ++i )
testAllTrans<pod::point<C>,nProbes>(mkpt<C>(i));
}
template< class C,
int nProbes >
void testAllRect()
{
for ( int i = 0; i < rsmpl_count; ++i )
testAllTrans<pod::rectangle<C>,nProbes>(mkrect<C>(i));
}
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
template< class T, int nProbs >
class mult
{
T trns;
T trns2;
T trns3;
public:
mult( const T& t, const T& t2 )
{
trns = t;
trns2 = t2;
}
__forceinline void operator() ()
{
for( int i = nProbs; i; --i )
trns.mult( trns2, trns3 );
}
};
template< class T, int nProbs >
class mult2
{
T trns;
T trns2;
public:
mult2( const T& t, const T& t2 )
{
trns = t;
trns2 = t2;
}
__forceinline void operator() ()
{
for( int i = nProbs; i; --i )
{
volatile T t = trns * trns2;
}
}
};
template< int nProbes >
void testMult( const base::transform& t11, const base::transform& t12,
const base2::transform& t21, const base2::transform& t22 )
{
const int n = SCALE;
{
typedef mult<base::transform,n> mult1_type;
double dblMin1 = mesure<mult1_type>( mult1_type( t11, t12 ), nProbes );
dblMin1 /= n;
typedef mult<base2::transform,n> mult2_type;
double dblMin2 = mesure<mult2_type>( mult2_type( t21, t22 ), nProbes );
dblMin2 /= n;
print_result( dblMin1, dblMin2 );
}
{
typedef mult2<base::transform,n> mult1_type;
double dblMin1 = mesure<mult1_type>( mult1_type( t11, t12 ), nProbes );
dblMin1 /= n;
typedef mult2<base2::transform,n> mult2_type;
double dblMin2 = mesure<mult2_type>( mult2_type( t21, t22 ), nProbes );
dblMin2 /= n;
print_result( dblMin1, dblMin2 );
}
}
template< int nProbes >
void testTrans1x1( int i, int j )
{
out << "<tr>";
#if 0
out << "<td>rot:" << tsmpl[i].rot
<< " flip:" << tsmpl[i].flip
<< " mag:" << tsmpl[i].mag
<< " x:" << tsmpl[i].xloc
<< " y:" << tsmpl[i].yloc
<< "</td>";
out << "<td>rot:" << tsmpl[j].rot
<< " flip:" << tsmpl[j].flip
<< " mag:" << tsmpl[j].mag
<< " x:" << tsmpl[j].xloc
<< " y:" << tsmpl[j].yloc
<< "</td>";
#endif
testMult<nProbes>(mktrans<base::transform>(i), mktrans<base::transform>(j),
mktrans<base2::transform>(i), mktrans<base2::transform>(j) );
out << "</tr>" << std::endl;
}
template< int nProbes >
void testAllTrans1x1()
{
for ( int i = 0; i < tsmpl_count; ++i )
for ( int j = 0; j < tsmpl_count; ++j )
testTrans1x1<nProbes>(i,j);
}
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
template< class T, int nProbs >
class inverse
{
T trns;
T trns2;
public:
inverse( const T& t )
{
trns = t;
}
__forceinline void operator() ()
{
for( int i = nProbs; i; --i )
trns2 = trns.getInverse();
}
};
template< int nProbes >
void testInverse( const base::transform& t1, const base2::transform& t2 )
{
const int n = SCALE;
typedef inverse<base::transform,n> inverse1_type;
double dblMin1 = mesure<inverse1_type>( inverse1_type( t1 ), nProbes );
dblMin1 /= n;
typedef inverse<base2::transform,n> inverse2_type;
double dblMin2 = mesure<inverse2_type>( inverse2_type( t2 ), nProbes );
dblMin2 /= n;
print_result( dblMin1, dblMin2 );
}
template< int nProbes >
void testTransInverse( int i )
{
out << "<tr>";
#if 0
out << "<td>rot:" << tsmpl[i].rot
<< " flip:" << tsmpl[i].flip
<< " mag:" << tsmpl[i].mag
<< " x:" << tsmpl[i].xloc
<< " y:" << tsmpl[i].yloc
<< "</td>";
out << "<td>rot:" << tsmpl[j].rot
<< " flip:" << tsmpl[j].flip
<< " mag:" << tsmpl[j].mag
<< " x:" << tsmpl[j].xloc
<< " y:" << tsmpl[j].yloc
<< "</td>";
#endif
testInverse<nProbes>(mktrans<base::transform>(i),
mktrans<base2::transform>(i) );
out << "</tr>" << std::endl;
}
template< int nProbes >
void testAllTransInverse()
{
for ( int i = 0; i < tsmpl_count; ++i )
testTransInverse<nProbes>(i);
}
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
void print_result( double time1, double time2 )
{
out << "<td width=300 align=right>" << std::setiosflags( std::ios::fixed ) << std::setprecision( 12 ) << time1
<< "</td><td width=300 align=right>" << time2
<< "</td><td width=300 align=right>" << std::setprecision( 6 ) << (1. - time2/time1 )*100
<< "%</td>";
// printf( "t1 %f t2 %f fast %.3f%%\n", dblDiff1/nProbes, dblDiff2/nProbes, (dblDiff1/dblDiff2-1.)*100, nProbes );
}
template< int nProbes >
void testTransform()
{
out << "<a href=\"#_1\">pod::point&ltint32&gt</a><br>"
<< "<a href=\"#_2\">pod::point&ltint64&gt</a><br>"
<< "<a href=\"#_3\">pod::point&ltdouble&gt</a><br>"
<< "<a href=\"#_4\">pod::rectangle&ltint32&gt</a><br>"
<< "<a href=\"#_5\">pod::rectangle&ltint64&gt</a><br>"
<< "<a href=\"#_6\">pod::rectangle&ltdouble&gt</a><br>"
<< "<a href=\"#_7\">trans*trans</a><br>"
<< "<a href=\"#_8\">trans<sup>-1</sup></a><br><br><br>";
#if 0
std::cout << "pod::point<int32>" << std::endl;
out << "<a name=\"#_1\"></a><table border=1><thead><H3>pod::point&ltint32&gt</h3></thead>" << std::endl;
testAllPt<int32,nProbes>();
out << "</table><P>";
#endif
#if 0
std::cout << "pod::point<int64>" << std::endl;
out << "<a name=\"#_2\"></a><table border=1><thead><H3>pod::point&ltint64&gt</H3></thead>" << std::endl;
testAllPt<int64,nProbes>();
out << "</table><P>";
#endif
#if 0
std::cout << "pod::point<double>" << std::endl;
out << "<a name=\"#_3\"></a><table border=1><thead><H3>pod::point&ltdouble&gt</H3></thead>" << std::endl;
testAllPt<double,nProbes>();
out << "</table><P>";
#endif
#if 1
std::cout << "pod::rectangle<int32>" << std::endl;
out << "<a name=\"#_4\"></a><table border=1><thead><H3>pod::rectangle&ltint32&gt</H3></thead>" << std::endl;
testAllRect<int32,nProbes>();
out << "</table><P>";
#endif
#if 0
std::cout << "pod::rectangle<int64>" << std::endl;
out << "<a name=\"#_5\"></a><table border=1><thead><H3>pod::rectangle&ltint64&gt</H3></thead>" << std::endl;
testAllRect<int64,nProbes>();
out << "</table><P>";
#endif
#if 0
std::cout << "pod::rectangle<double>" << std::endl;
out << "<a name=\"#_6\"></a><table border=1><thead><H3>pod::rectangle&ltdouble&gt</H3></thead>" << std::endl;
testAllRect<double,nProbes>();
out << "</table><P>";
#endif
#if 0
std::cout << "trans*trans" << std::endl;
out << "<a name=\"#_7\"></a><table border=1><thead><H3>trans*trans</H3></thead>" << std::endl;
testAllTrans1x1<nProbes>();
out << "</table><P>";
#endif
#if 0
std::cout << "inverse trans" << std::endl;
out << "<a name=\"#_8\"></a><table border=1><thead><H3>trans<sup>-1</sup></H3></thead>" << std::endl;
testAllTransInverse<nProbes>();
out << "</table><P>";
#endif
}
void main ( )
{
out.open( "result.html" );
out << "<html><head><title></title></head><body><font face=\"courier\">" << std::endl;
// Init
perf_init();
base::transform::initFnTables();
base2::transform::initFnTables();
testTransform<100>();
out << "</body></html>";
out.close();
#ifdef WIN32
PROCESS_INFORMATION pi;
STARTUPINFO si;
memset( &pi, 0, sizeof( pi ) );
memset( &si, 0, sizeof( si ) );
BOOL b = CreateProcess( L"C:\\Program Files\\Internet Explorer\\IEXPLORE.EXE", L"IEXPLORE.EXE file:///D:/work/prj/test/testTransform/result.html", 0, 0, false, 0, 0, 0, &si, &pi );
#endif
}

198
testTransform/sseprim.h Normal file
View File

@@ -0,0 +1,198 @@
//
//
//
#ifndef __SSE_PRIM__H__
#define __SSE_PRIM__H__
#ifdef SSE_OPTIMIZATIONS
#include "ssetypes.h"
#if defined( _MSC_VER )
/*
Checking for the DAZ Flag in the MXCSR Register
The denormals-are-zero flag in the MXCSR register is available in most of the
Pentium 4 processors and in the Intel Xeon processor, with the exception of some
early steppings. To check for the presence of the DAZ flag in the MXCSR register, do
the following:
1. Establish a 512-byte FXSAVE area in memory.
2. Clear the FXSAVE area to all 0s.
3. Execute the FXSAVE instruction, using the address of the first byte of the cleared
FXSAVE area as a source operand. See <20>FXSAVE<56>Save x87 FPU, MMX, SSE, and
SSE2 State<74> in Chapter 3 of the Intel<65> 64 and IA-32 Architectures Software
Developer<EFBFBD>s Manual, Volume 2A, for a description of the FXSAVE instruction and
the layout of the FXSAVE image.
4. Check the value in the MXCSR_MASK field in the FXSAVE image (bytes 28
through 31).
<EFBFBD> If the value of the MXCSR_MASK field is 00000000H, the DAZ flag and
denormals-are-zero mode are not supported.
Vol. 1 11-29
PROGRAMMING WITH STREAMING SIMD EXTENSIONS 2 (SSE2)
<EFBFBD> If the value of the MXCSR_MASK field is non-zero and bit 6 is set, the DAZ
flag and denormals-are-zero mode are supported.
If the DAZ flag is not supported, then it is a reserved bit and attempting to write a 1
to it will cause a general-protection exception (#GP). See Section 11.6.6, <20>Guidelines
for Writing to the MXCSR Register,<2C> for general guidelines for preventing generalprotection
exceptions when writing to the MXCSR register.
11.6.4 Initialization of SSE/SE2 Extensions
The SSE and SSE2 state is contained in the XMM and MXCSR registers. Upon a hardware
reset of the processor, this state is initialized as follows (see Table 11-2):
<EFBFBD> All SIMD floating-point exceptions are masked (bits 7 through 12 of the MXCSR
register is set to 1).
<EFBFBD> All SIMD floating-point exception flags are cleared (bits 0 through 5 of the MXCSR
register is set to 0).
<EFBFBD> The rounding control is set to round-nearest (bits 13 and 14 of the MXCSR
register are set to 00B).
<EFBFBD> The flush-to-zero mode is disabled (bit 15 of the MXCSR register is set to 0).
<EFBFBD> The denormals-are-zeros mode is disabled (bit 6 of the MXCSR register is set to
0). If the denormals-are-zeros mode is not supported, this bit is reserved and will
be set to 0 on initialization.
<EFBFBD> Each of the XMM registers is cleared (set to all zeros).
to read
HT Technology
Intel<EFBFBD> 64 and IA-32 Architectures Optimization Reference Manual
FTZ and DAZ flags in the MXCSR
oprof
*/
/*
1. Check that the processor supports the CPUID instruction. Bit 21 of the EFLAGS
register can be used to check processor<6F>s support the CPUID instruction.
2. Check that the processor supports the SSE and/or SSE2 extensions (true if
CPUID.01H:EDX.SSE[bit 25] = 1 and/or CPUID.01H:EDX.SSE2[bit 26] = 1).
*/
inline bool sse2_available()
{
}
/*
Check that the processor supports the SIMD and x87 SSE3 extensions (if
CPUID.01H:ECX.SSE3[bit 0] = 1).
*/
inline bool sse3_available()
{
}
/*
Before an application attempts to use the SSSE3 extensions, the application should
follow the steps illustrated in Section 11.6.2, <20>Checking for SSE/SSE2 Support.<2E>
Next, use the additional step provided below:
<EFBFBD> Check that the processor supports SSSE3 (if CPUID.01H:ECX.SSSE3[bit 9] = 1).
*/
inline bool ssse3_available()
{
}
/*
12.12.2 Checking for SSE4.1 Support
Before an application attempts to use SSE4.1 instructions, the application should
follow the steps illustrated in Section 11.6.2, <20>Checking for SSE/SSE2 Support.<2E>
Next, use the additional step provided below:
Check that the processor supports SSE4.1 (if CPUID.01H:ECX.SSE4_1[bit 19] = 1),
SSE3 (if CPUID.01H:ECX.SSE3[bit 0] = 1), and SSSE3 (if CPUID.01H:ECX.SSSE3[bit
9] = 1).
*/
inline bool sse4_1_available()
{
}
/*
Before an application attempts to use the following SSE4.2 instructions:
PCMPESTRI/PCMPESTRM/PCMPISTRI/PCMPISTRM, PCMPGTQ;the application should
follow the steps illustrated in Section 11.6.2, <20>Checking for SSE/SSE2 Support.<2E>
Next, use the additional step provided below:
Check that the processor supports SSE4.2 (if CPUID.01H:ECX.SSE4_2[bit 20] = 1),
SSE4.1 (if CPUID.01H:ECX.SSE4_1[bit 19] = 1), and SSSE3 (if
CPUID.01H:ECX.SSSE3[bit 9] = 1).
Before an application attempts to use the CRC32 instruction, it must check that the
processor supports SSE4.2 (if CPUID.01H:ECX.SSE4_2[bit 20] = 1).
Before an application attempts to use the POPCNT instruction, it must check that the
processor supports SSE4.2 (if CPUID.01H:ECX.POPCNT[bit 23] = 1).
*/
inline bool sse4_2_available()
{
}
#if 1
//
// Make vector.
//
__forceinline v2pd get_v2pd( const short* p )
{
double tmp[2];
tmp[0] = double( p[0] );
tmp[1] = double( p[1] );
return _mm_loadu_pd( tmp );
}
__forceinline v2pd get_v2pd( const int32* p )
{
__declspec(align(16)) double tmp[2];
tmp[0] = double( p[0] );
tmp[1] = double( p[1] );
return _mm_loadu_pd( tmp );
}
__forceinline v2pd get_v2pd( const int64* p )
{
double tmp[2];
tmp[0] = double( p[0] );
tmp[1] = double( p[1] );
return _mm_loadu_pd( tmp );
}
__forceinline v2pd get_v2pd( const double* p )
{
return _mm_loadu_pd( p );
// movupd reg, p[0]
}
//
// Make regular types.
//
__forceinline void set_v2pd( short* p, register v2pd reg )
{
double tmp[2];
_mm_storeu_pd( tmp, reg );
p[0] = short( tmp[0] );
p[1] = short( tmp[1] );
}
__forceinline void set_v2pd( int32* p, register v2pd reg )
{
__declspec(align(16)) double tmp[2];
_mm_storeu_pd( tmp, reg );
p[0] = int32( tmp[0] );
p[1] = int32( tmp[1] );
}
__forceinline void set_v2pd( int64* p, register v2pd reg )
{
double tmp[2];
_mm_storeu_pd( tmp, reg );
p[0] = int64( tmp[0] );
p[1] = int64( tmp[1] );
}
__forceinline void set_v2pd( double* p, register v2pd reg )
{
_mm_storeu_pd( p, reg );
// movupd [p], reg
}
#endif
#elif defined( __GNUC__ )
#endif
#endif//SSE_OPTIMIZATIONS
#endif//__SSE_PRIM__H__

48
testTransform/ssetypes.h Normal file
View File

@@ -0,0 +1,48 @@
//
//
//
#ifndef __SSE_TYPE__H__
#define __SSE_TYPE__H__
#if defined( _MSC_VER )
#include <emmintrin.h>
//
// Intager types
//
typedef int int32;
typedef unsigned int uint32;
typedef __int64 int64;
typedef unsigned __int64 uint64;
//
// Vector types.
//
typedef __m128i v4dw;
typedef __m128i v4dw;
typedef __m128i v2qw;
typedef __m128d v4ps;
typedef __m128d v2pd;
#elif defined( __GNUC__ )
//
// Intager types
//
typedef int int32;
typedef unsigned int uint32;
typedef long int64;
typedef unsigned long uint64;
//
// Vector types.
//
typedef int v4dw __attribute__ ((vector_size (16)));
typedef long v2qw __attribute__ ((vector_size (16)));
typedef float v2ps __attribute__ ((vector_size (16)));
typedef double v2pd __attribute__ ((vector_size (16)));
#endif
#endif//__SSE_TYPE__H__

View File

@@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testTransform", "testTransform.vcproj", "{5390B9E5-D4C7-45C1-AFDE-8140E5B01134}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{5390B9E5-D4C7-45C1-AFDE-8140E5B01134}.Debug|Win32.ActiveCfg = Debug|Win32
{5390B9E5-D4C7-45C1-AFDE-8140E5B01134}.Debug|Win32.Build.0 = Debug|Win32
{5390B9E5-D4C7-45C1-AFDE-8140E5B01134}.Release|Win32.ActiveCfg = Release|Win32
{5390B9E5-D4C7-45C1-AFDE-8140E5B01134}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,362 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="testTransform"
ProjectGUID="{5390B9E5-D4C7-45C1-AFDE-8140E5B01134}"
RootNamespace="testTransform"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="D:\work\prj\fw\xmain\src;D:\work\prj\fw\xmain\src\base"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;SSE_OPTIMIZATIONS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
AssemblerOutput="4"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="D:\work\prj\fw\xmain\src;D:\work\prj\fw\main\3rd_party\qt\4.3.3\win32\include"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;SSE_OPTIMIZATIONS"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
AssemblerOutput="4"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="false"
AssemblyDebug="0"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\main.cpp"
>
</File>
<File
RelativePath=".\transform.cpp"
>
</File>
<File
RelativePath=".\transform.h"
>
</File>
<File
RelativePath=".\transform2.cpp"
>
</File>
<File
RelativePath=".\transform2.h"
>
</File>
</Filter>
<Filter
Name="Common Files"
>
<File
RelativePath="..\getcurrenttime2.h"
>
</File>
<File
RelativePath=".\sseprim.h"
>
</File>
<File
RelativePath=".\ssetypes.h"
>
</File>
</Filter>
<Filter
Name="Debug"
>
<File
RelativePath=".\Debug\main.asm"
>
<FileConfiguration
Name="Debug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCustomBuildTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCustomBuildTool"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\Debug\transform.asm"
>
<FileConfiguration
Name="Debug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCustomBuildTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCustomBuildTool"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\Debug\transform2.asm"
>
<FileConfiguration
Name="Debug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCustomBuildTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCustomBuildTool"
/>
</FileConfiguration>
</File>
</Filter>
<Filter
Name="Release"
>
<File
RelativePath=".\Release\main.asm"
>
<FileConfiguration
Name="Debug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCustomBuildTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCustomBuildTool"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\Release\transform.asm"
>
<FileConfiguration
Name="Debug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCustomBuildTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCustomBuildTool"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\Release\transform2.asm"
>
<FileConfiguration
Name="Debug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCustomBuildTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCustomBuildTool"
/>
</FileConfiguration>
</File>
</Filter>
<File
RelativePath=".\result.html"
>
</File>
<File
RelativePath=".\VTune\testTransform.vpj"
>
</File>
<File
RelativePath=".\times.txt"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

1593
testTransform/transform.cpp Normal file

File diff suppressed because it is too large Load Diff

1493
testTransform/transform.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,845 @@
/*
* SYNOPSYS CONFIDENTIAL - This is an unpublished, proprietary work of Synopsys,
* Inc., and is fully protected under copyright and trade secret laws. You may
* not view, use, disclose, copy, or distribute this file or any information
* contained herein except pursuant to a valid written license from Synopsys.
*/
#include "base/type-traits2.h"
#include "ssetypes.h"
#include "transform2.h"
#include "base/constants.h"
namespace base2
{
#if 0
const stdOrientEnum inverseStdOrient[stdOrientMAX] =
{
R0,
R270,
R180,
R90,
XFlipR0,
XFlipR90,
XFlipR180,
XFlipR270
};
/*
In Aix64 platform char is by default unsigned this causes
difference in values, ensuring signed char array
*/
const signed char stdOrientCoeffMatrix[stdOrientMAX][2][2] =
{
//
/// R0: 0 degree rotation with no flip.
/// Coefficients = | 1 0|
/// | 0 1|
//
{{1, 0},
{0, 1}},
//
/// R90: 90 degree rotation with no flip.
/// Coefficients = | 0 1|
/// |-1 0|
//
{{0, 1},
{-1, 0}},
//
/// R180: 180 degree rotation with no flip.
/// Coefficients = |-1 0|
/// | 0 -1|
//
{{-1, 0},
{0, -1}},
//
/// R270: 270 degree rotation with no flip.
/// Coefficients = | 0 -1|
/// | 1 0|
//
{{0, -1},
{1, 0}},
//
/// XFlipR0: X flip followed by 0 degree rotation.
/// Coefficients = | 1 0|
/// | 0 -1|
//
{{1, 0},
{0, -1}},
//
/// X flip followed by 90 degree rotation.
/// Coefficients = | 0 1|
/// | 1 0|
//
{{0, 1},
{1, 0}},
//
/// X flip followed by 180 degree rotation.
/// Coefficients = |-1 0|
/// | 0 1|
//
{{-1, 0},
{0, 1}},
//
/// X flip followed by 270 degree rotation.
/// Coefficients = | 0 -1|
/// |-1 0|
//
{{0, -1},
{-1, 0}}
};
//
/// Matrix for multiplying standard orientations.
//
const stdOrientEnum multStdOrientMatrix[stdOrientMAX][stdOrientMAX] = {
// R0, R90, R180, R270, XFlipR0, XFlipR90, XFlipR180, XFlipR270
/* R0 */ { R0, R90, R180, R270, XFlipR0, XFlipR90, XFlipR180, XFlipR270},
/* R90 */ { R90, R180, R270, R0, XFlipR270, XFlipR0, XFlipR90, XFlipR180},
/* R180 */ { R180, R270, R0, R90, XFlipR180, XFlipR270, XFlipR0, XFlipR90},
/* R270 */ { R270, R0, R90, R180, XFlipR90, XFlipR180, XFlipR270, XFlipR0},
/* XFlipR0 */ { XFlipR0, XFlipR90, XFlipR180, XFlipR270, R0, R90, R180, R270},
/* XFlipR90 */ { XFlipR90, XFlipR180, XFlipR270, XFlipR0, R270, R0, R90, R180},
/* XFlipR180 */ { XFlipR180, XFlipR270, XFlipR0, XFlipR90, R180, R270, R0, R90},
/* XFlipR270 */ { XFlipR270, XFlipR0, XFlipR90, XFlipR180, R90, R180, R270, R0}
}
#endif
//
/// Initialize the function tables.
//
void transform::initFnTables()
{
}
// Value of standard orientation
const struct { bool xflip; double angle;} stdOrientXFlipAngValues[stdOrientMAX]=
{
{false, 0. }, // RO
{false, 90. }, // R90
{false, 180. }, // R180
{false, 270. }, // R270
{true, 0. }, // XFlipR0
{true, 90. }, //XFlipR90
{true, 180. }, //XFlipR180
{true, 270. } //XFlipR270
};
const void transform::getAngleFlipMag( double& angle, bool& isXFlip, double& mag) const
{
#if 0
if( type!=GeneralTransformType)
{
//
// standard orientation. Use table
//
int idx= (int) getOrient().getOri();
isXFlip= stdOrientXFlipAngValues[idx].xflip;
angle = stdOrientXFlipAngValues[idx].angle;
mag = a11;
}
else
#endif
{
// From constructor
// double multiplier = 1.0;
// if (inXFlip == true)
// multiplier = -1.0;
// register double newAngle = degreesToRadians(normalizeAngle(inAngle));
// register double cosine = cos(newAngle);
// register double sine = sin(newAngle);
// a11 = inMag * cosine;
// a12 = inMag * sine;
// a21 = -inMag * multiplier * sine;
// a22 = inMag * multiplier * cosine;
//
// How to get angle, inMage and inXFlip from a11, a12, a21, and a22
// Let sumProd = a11* a22 - a12*a21
// = (inMag*consine)(inMag * multiplier * cosine) - (inMag * sine)(-inMag * multiplier * sine)
// = inMag*inMag*multiplier*consine*consine + inMag*inMag*multiplier*sine*sine
// = inMag*inMag*multiplier(consine* consine + sine*sine)
// = inMag*inMag*multiplier
//
// if( sumProd) < 0 ==> inXFlip=true
// inMag= SquareRoot( Abs(sumPro));
// Angle= ArcCosine(a11/inMag)
double sumProd= a11()*a22() - a12()*a21();
//get inXFlip.
// sumProd= imMag*imMag*multiplier
isXFlip= sumProd < 0;
// get abs(imMag*imMag)
if(sumProd<0)
sumProd= -sumProd;
// get mag
mag= sqrt(sumProd);
// get angle
if(mag> 0)
{
double angleR= acos(a11()/mag);
angle=radiansToDegrees(angleR);
// aCos funciton range is 0 to 180.
// We need to decide if angle is between 180 to 360
//
// How to solve it
// Let (Xt, Yt) is the point by applying (1,0) with transformation without xFlip,
// if Yt > 0, then angle is located between 180 and 360
//
// i.e.
// | a11 a12 | x | 1 | = [a11 a21p ] = (Xt, Yt)
// | a21p a22 | | 0 |
// a21= multiplier * a21p = xFlip + angle
// if a21p > 0 angle is located between 180 and 360
//
double a21p= isXFlip? -a21(): a21();
if( a21p> 0 )
angle= 360. - angle;
}
else
angle=0;
}// end else
}
#if 0
transform transform::getInverseScaleOffset(const transform & T)
{
return transform( -T.offset.X()/T.a11,
-T.offset.Y()/T.a22,
1.0/T.a11,
1.0/T.a22);
}
//
/// Get the inverse of a general transform.
//
transform transform::getInverseGeneral(const transform & T )
{
//
// compute the determinant
//
double det = T.a11*T.a22 - T.a12*T.a21;
return transform( (T.offset.Y()*T.a21 - T.offset.X()*T.a22)/det,
(T.offset.X()*T.a12 - T.offset.Y()*T.a11)/det,
T.a22/det,
-T.a12/det,
-T.a21/det,
T.a11/det);
}
//
/// Get the inverse of a standard transform.
//
transform transform::getInverseStd(const transform & T)
{
//
// Transform the offset.
//
pod::point<double> off = - T.offset * stdOrient(inverseStdOrient[T.orient.getOri()]);
//
// Return the inverted standard transform.
//
return transform (off.X(), off.Y(),
inverseStdOrient[T.orient.getOri()]);
}
//
/// Get the inverse of a standard transform with mag.
//
transform transform::getInverseStdWithMag(const transform & T)
{
register double oneOverMag = 1.0/T.a11;
register stdOrientEnum e = inverseStdOrient[T.orient.getOri()];
//
// Transform the offset.
//
pod::point<double> off = - (T.offset * stdOrient(e)) * oneOverMag;
return transform( off.X(),
off.Y(),
e,
oneOverMag );
}
//
/// Get the inverse of a scale transform.
//
transform transform::getInverseScale(const transform & T)
{
return transform( 0.0,
0.0,
1.0/T.a11,
1.0/T.a22);
}
//
// Get the inverse of a resolution transform.
//
transform transform::getInverseResolution(const transform & T)
{
if (T.next) {
transform T1(T.a11, T.a22, false);
transform T2;
T1.mult(*(T.next), T2);
return T2.getInverse();
} else {
return transform(1.0/T.a11, 1.0/T.a22, false);
}
}
#endif
#if 0
//
/// Multiply two scale transforms.
//
void transform::multScaleXScale(const transform &T1,
const transform &T2, transform &outT)
{
outT.type = ScaleTransformType;
outT.a11 = T1.a11*T2.a11;
outT.a22 = T1.a22*T2.a22;
outT.offset = pod::point<double>(0.0, 0.0);
}
//
/// Multiply a scale transform with a resolution transform.
//
void transform::multScaleXResolution(const transform &T1,
const transform &T2, transform &outT)
{
outT.type = ResolutionTransformType;
outT.a11 = T2.a11;
outT.a12 = T2.a12;
outT.a21 = T2.a21;
outT.a22 = T2.a22;
if (T2.next) {
if (!outT.next)
outT.next = new transform;
transform tmp(T1.a11, T1.a22, false);
tmp.mult(*(T2.next), *(outT.next));
} else {
if (outT.next) {
outT.next->type = ScaleTransformType;
outT.next->a11 = T1.a11;
outT.next->a12 = T1.a12;
outT.next->a21 = T1.a21;
outT.next->a22 = T1.a22;
outT.next->offset.setX(0.0);
outT.next->offset.setY(0.0);
} else {
outT.next = new transform(T1.a11, T1.a22, false);
}
}
}
//
//
/// Multiply two scale offset transforms.
//
void transform::multScaleOffsetXScaleOffset(const transform &T1,
const transform &T2, transform &outT)
{
outT.type = ScaleOffsetTransformType;
outT.a11 = T1.a11*T2.a11;
outT.a22 = T1.a22*T2.a22;
outT.offset = pod::point<double>(
T2.a11*T1.offset.X() + T2.offset.X(),
T2.a22*T1.offset.Y() + T2.offset.Y());
}
//
/// Multiply a scale offset transform with a general transform.
//
void transform::multScaleOffsetXGeneral(const transform &T1,
const transform &T2, transform &outT)
{
outT.type = GeneralTransformType;
outT.a11 = T1.a11*T2.a11;
outT.a12 = T1.a11*T2.a12;
outT.a21 = T1.a22*T2.a21;
outT.a22 = T1.a22*T2.a22;
outT.offset = pod::point<double>( T1.offset.X()*T2.a11 + T1.offset.Y()*T2.a21 + T2.offset.X(),
T1.offset.X()*T2.a12 + T1.offset.Y()*T2.a22 + T2.offset.Y());
}
//
/// Multiply a scale offset transform with a standard transform.
//
void transform::multScaleOffsetXStd( const transform &T1,
const transform &T2,
transform &outT)
{
//
// If we have uniform magnification, then we do not have to go to
// a general transform.
//
if ( T1.a11 == T1.a22 )
{
outT.type = StdTransformWithMagType;
outT.orient = T2.orient;
outT.a11 = T1.a11*T2.a11;
}
else
{
outT.type = GeneralTransformType;
outT.a11 = T1.a11*stdOrientCoeffMatrix[T2.orient.getOri()][0][0];
outT.a12 = T1.a11*stdOrientCoeffMatrix[T2.orient.getOri()][0][1];
outT.a21 = T1.a22*stdOrientCoeffMatrix[T2.orient.getOri()][1][0];
outT.a22 = T1.a22*stdOrientCoeffMatrix[T2.orient.getOri()][1][1];
}
outT.offset = pod::point<double>(
T1.offset.X()*stdOrientCoeffMatrix[T2.orient.getOri()][0][0] +
T1.offset.Y()*stdOrientCoeffMatrix[T2.orient.getOri()][1][0],
T1.offset.X()*stdOrientCoeffMatrix[T2.orient.getOri()][0][1] +
T1.offset.Y()*stdOrientCoeffMatrix[T2.orient.getOri()][1][1])
+ T2.offset;
}
//
/// Multiply a scale offset transform with a standard transform
/// with magnification.
//
void transform::multScaleOffsetXStdWithMag( const transform &T1,
const transform &T2,
transform &outT)
{
//
// If we have uniform magnification, then we do not have to go to
// a general transform.
//
if ( T1.a11 == T1.a22 )
{
outT.type = StdTransformWithMagType;
outT.orient = T2.orient;
outT.a11 = T1.a11*T2.a11;
}
else
{
outT.type = GeneralTransformType;
outT.a11 = T1.a11*T2.a11*stdOrientCoeffMatrix[T2.orient.getOri()][0][0];
outT.a12 = T1.a11*T2.a11*stdOrientCoeffMatrix[T2.orient.getOri()][0][1];
outT.a21 = T1.a22*T2.a11*stdOrientCoeffMatrix[T2.orient.getOri()][1][0];
outT.a22 = T1.a22*T2.a11*stdOrientCoeffMatrix[T2.orient.getOri()][1][1];
}
outT.offset = pod::point<double>(
T2.a11*(T1.offset.X()*stdOrientCoeffMatrix[T2.orient.getOri()][0][0] +
T1.offset.Y()*stdOrientCoeffMatrix[T2.orient.getOri()][1][0]),
T2.a11*(T1.offset.X()*stdOrientCoeffMatrix[T2.orient.getOri()][0][1] +
T1.offset.Y()*stdOrientCoeffMatrix[T2.orient.getOri()][1][1]))
+ T2.offset;
}
//
/// Multiply a scale offset transform with a resolution transform.
//
void transform::multScaleOffsetXResolution(const transform &T1,
const transform &T2, transform &outT)
{
outT.type = ResolutionTransformType;
outT.a11 = T2.a11;
outT.a12 = T2.a12;
outT.a21 = T2.a21;
outT.a22 = T2.a22;
if (T2.next) {
if (!outT.next)
outT.next = new transform;
transform tmp(
T1.offset.getX()*T2.a11,
T1.offset.getY()*T2.a22,
T1.a11, T1.a22);
tmp.mult(*(T2.next), *(outT.next));
} else {
if (outT.next) {
outT.next->type = ScaleOffsetTransformType;
outT.next->a11 = T1.a11;
outT.next->a12 = 0.0;
outT.next->a21 = 0.0;
outT.next->a22 = T1.a22;
outT.next->offset.setX(T1.offset.getX()*T2.a11);
outT.next->offset.setY(T1.offset.getY()*T2.a22);
} else {
outT.next = new transform(
T1.offset.getX()*T2.a11,
T1.offset.getY()*T2.a22,
T1.a11, T1.a22);
}
}
}
//
/// Multiply a general transform with a scale offset transform.
//
void transform::multGeneralXScaleOffset(const transform &T1,
const transform &T2, transform &outT)
{
outT.type = GeneralTransformType;
outT.a11 = T1.a11*T2.a11;
outT.a12 = T1.a12*T2.a22;
outT.a21 = T1.a21*T2.a11;
outT.a22 = T1.a22*T2.a22;
outT.offset = pod::point<double>( T1.offset.X()*T2.a11,
T1.offset.Y()*T2.a22)
+ T2.offset;
}
//
/// Multiply two general transforms.
//
void transform::multGeneralXGeneral(const transform &T1,
const transform &T2, transform &outT)
{
outT.type = GeneralTransformType;
outT.a11 = T1.a11*T2.a11 + T1.a12*T2.a21;
outT.a12 = T1.a11*T2.a12 + T1.a12*T2.a22;
outT.a21 = T1.a21*T2.a11 + T1.a22*T2.a21;
outT.a22 = T1.a21*T2.a12 + T1.a22*T2.a22;
outT.offset = pod::point<double>( T1.offset.X()*T2.a11 + T1.offset.Y()*T2.a21,
T1.offset.X()*T2.a12 + T1.offset.Y()*T2.a22)
+ T2.offset;
}
//
/// Multiply a general transform with a standard transform.
//
void transform::multGeneralXStd(const transform &T1,
const transform &T2, transform &outT)
{
outT.type = GeneralTransformType;
outT.a11 = T1.a11*stdOrientCoeffMatrix[T2.orient.getOri()][0][0] +
T1.a12*stdOrientCoeffMatrix[T2.orient.getOri()][1][0];
outT.a12 = T1.a11*stdOrientCoeffMatrix[T2.orient.getOri()][0][1] +
T1.a12*stdOrientCoeffMatrix[T2.orient.getOri()][1][1];
outT.a21 = T1.a21*stdOrientCoeffMatrix[T2.orient.getOri()][0][0] +
T1.a22*stdOrientCoeffMatrix[T2.orient.getOri()][1][0];
outT.a22 = T1.a21*stdOrientCoeffMatrix[T2.orient.getOri()][0][1] +
T1.a22*stdOrientCoeffMatrix[T2.orient.getOri()][1][1];
//
// Transform the offset.
//
outT.offset = T1.offset * T2.orient + T2.offset;
}
//
/// Multiply a general transform with a standard transform
/// with magnification.
//
void transform::multGeneralXStdWithMag(const transform &T1,
const transform &T2, transform &outT)
{
outT.type = GeneralTransformType;
outT.a11 = T2.a11*(T1.a11*stdOrientCoeffMatrix[T2.orient.getOri()][0][0] +
T1.a12*stdOrientCoeffMatrix[T2.orient.getOri()][1][0]);
outT.a12 = T2.a11*(T1.a11*stdOrientCoeffMatrix[T2.orient.getOri()][0][1] +
T1.a12*stdOrientCoeffMatrix[T2.orient.getOri()][1][1]);
outT.a21 = T2.a11*(T1.a21*stdOrientCoeffMatrix[T2.orient.getOri()][0][0] +
T1.a22*stdOrientCoeffMatrix[T2.orient.getOri()][1][0]);
outT.a22 = T2.a11*(T1.a21*stdOrientCoeffMatrix[T2.orient.getOri()][0][1] +
T1.a22*stdOrientCoeffMatrix[T2.orient.getOri()][1][1]);
//
// Transform the offset.
//
outT.offset = (T1.offset * T2.orient) * T2.a11 + T2.offset;
}
//
/// Multiply a general transform with a resolution transform.
//
void transform::multGeneralXResolution(const transform &T1,
const transform &T2, transform &outT)
{
outT.type = ResolutionTransformType;
outT.a11 = T2.a11;
outT.a12 = T2.a12;
outT.a21 = T2.a21;
outT.a22 = T2.a22;
if (T2.next) {
if (!outT.next)
outT.next = new transform;
transform tmp(
T1.offset.getX()*T2.a11,
T1.offset.getY()*T2.a22,
T1.a11, T1.a12, T1.a21, T1.a22);
tmp.mult(*(T2.next), *(outT.next));
} else {
if (outT.next) {
outT.next->type = GeneralTransformType;
outT.next->a11 = T1.a11;
outT.next->a22 = T1.a22;
outT.next->a12 = T1.a12;
outT.next->a21 = T1.a21;
outT.next->offset.setX(T1.offset.getX()*T2.a11);
outT.next->offset.setY(T1.offset.getY()*T2.a22);
} else {
outT.next = new transform(
T1.offset.getX()*T2.a11,
T1.offset.getY()*T2.a22,
T1.a11, T1.a12, T1.a21, T1.a22);
}
}
}
//
/// Multiply a standard transform with a scale and offset transform.
//
void transform::multStdXScaleOffset(const transform &T1,
const transform &T2, transform &outT)
{
outT.type = GeneralTransformType;
outT.a11 = stdOrientCoeffMatrix[T1.orient.getOri()][0][0]*T2.a11;
outT.a12 = stdOrientCoeffMatrix[T1.orient.getOri()][0][1]*T2.a22;
outT.a21 = stdOrientCoeffMatrix[T1.orient.getOri()][1][0]*T2.a11;
outT.a22 = stdOrientCoeffMatrix[T1.orient.getOri()][1][1]*T2.a22;
//
// Transform the offset.
//
outT.offset = pod::point<double>( T1.offset.X()*T2.a11,
T1.offset.Y()*T2.a22)
+ T2.offset;
}
//
/// Multiply a standard transform with a general transform.
//
void transform::multStdXGeneral(const transform &T1,
const transform &T2, transform &outT)
{
outT.type = GeneralTransformType;
outT.a11 = stdOrientCoeffMatrix[T1.orient.getOri()][0][0]*T2.a11 +
stdOrientCoeffMatrix[T1.orient.getOri()][0][1]*T2.a21;
outT.a12 = stdOrientCoeffMatrix[T1.orient.getOri()][0][0]*T2.a12 +
stdOrientCoeffMatrix[T1.orient.getOri()][0][1]*T2.a22;
outT.a21 = stdOrientCoeffMatrix[T1.orient.getOri()][1][0]*T2.a11 +
stdOrientCoeffMatrix[T1.orient.getOri()][1][1]*T2.a21;
outT.a22 = stdOrientCoeffMatrix[T1.orient.getOri()][1][0]*T2.a12 +
stdOrientCoeffMatrix[T1.orient.getOri()][1][1]*T2.a22;
//
// Transform the offset.
//
outT.offset = pod::point<double>( T1.offset.X()*T2.a11 + T1.offset.Y()*T2.a21,
T1.offset.X()*T2.a12 + T1.offset.Y()*T2.a22)
+ T2.offset;
}
//
/// Multiply two standard transforms.
//
void transform::multStdXStd(const transform &T1,
const transform &T2, transform &outT)
{
outT.type = StdTransformType;
outT.orient = multStdOrientMatrix[T1.orient.getOri()][T2.orient.getOri()];
//
// Transform the offset.
//
outT.offset = T1.offset * T2.orient + T2.offset;
}
//
/// Multiply a standard transform with a standard transform
/// with magnification.
//
void transform::multStdXStdWithMag(const transform &T1,
const transform &T2, transform &outT)
{
outT.type = StdTransformWithMagType;
outT.orient = stdOrient(multStdOrientMatrix[T1.orient.getOri()][T2.orient.getOri()]);
outT.a11 = T2.a11;
//
// Transform the offset.
//
outT.offset = T1.offset * T2.orient * T2.a11 + T2.offset;
}
//
/// Multiply a standard transform with a resolution transform.
//
void transform::multStdXResolution(const transform &T1,
const transform &T2, transform &outT)
{
outT.type = ResolutionTransformType;
outT.a11 = T2.a11;
outT.a12 = T2.a12;
outT.a21 = T2.a21;
outT.a22 = T2.a22;
if (T2.next)
{
if (!outT.next)
outT.next = new transform;
transform tmp(
T1.offset.getX()*T2.a11,
T1.offset.getY()*T2.a22,
T1.orient.getOri());
tmp.mult(*(T2.next), *(outT.next));
}
else if (outT.next)
{
outT.next->type = StdTransformType;
outT.next->a11 = T1.a11;
outT.next->a12 = T1.a12;
outT.next->a21 = T1.a21;
outT.next->a22 = T1.a22;
outT.next->offset.setX(T1.offset.getX()*T2.a11);
outT.next->offset.setY(T1.offset.getY()*T2.a22);
outT.next->orient = T1.orient;
}
else
{
outT.next = new transform(
T1.offset.getX()*T2.a11,
T1.offset.getY()*T2.a22,
T1.orient.getOri());
}
}
//
/// Multiply a standard transform with magnification with a
/// scale and offset transform.
//
void transform::multStdWithMagXScaleOffset(const transform &T1,
const transform &T2, transform &outT)
{
outT.type = GeneralTransformType;
outT.a11 = T1.a11*stdOrientCoeffMatrix[T1.orient.getOri()][0][0]*T2.a11;
outT.a12 = T1.a11*stdOrientCoeffMatrix[T1.orient.getOri()][0][1]*T2.a22;
outT.a21 = T1.a11*stdOrientCoeffMatrix[T1.orient.getOri()][1][0]*T2.a11;
outT.a22 = T1.a11*stdOrientCoeffMatrix[T1.orient.getOri()][1][1]*T2.a22;
//
// Transform the offset.
//
outT.offset = pod::point<double>( T1.offset.X()*T2.a11,
T1.offset.Y()*T2.a22)
+ T2.offset;
}
//
/// Multiply a standard transform with magnification with
/// a general transform.
//
void transform::multStdWithMagXGeneral(const transform &T1,
const transform &T2, transform &outT)
{
outT.type = GeneralTransformType;
outT.a11 = T1.a11*( stdOrientCoeffMatrix[T1.orient.getOri()][0][0]*T2.a11 +
stdOrientCoeffMatrix[T1.orient.getOri()][0][1]*T2.a21);
outT.a12 = T1.a11*( stdOrientCoeffMatrix[T1.orient.getOri()][0][0]*T2.a12 +
stdOrientCoeffMatrix[T1.orient.getOri()][0][1]*T2.a22);
outT.a21 = T1.a11*( stdOrientCoeffMatrix[T1.orient.getOri()][1][0]*T2.a11 +
stdOrientCoeffMatrix[T1.orient.getOri()][1][1]*T2.a21);
outT.a22 = T1.a11*( stdOrientCoeffMatrix[T1.orient.getOri()][1][0]*T2.a12 +
stdOrientCoeffMatrix[T1.orient.getOri()][1][1]*T2.a22);
//
// Transfomr the offset.
//
outT.offset = pod::point<double>( T1.offset.X()*T2.a11 + T1.offset.Y()*T2.a21,
T1.offset.X()*T2.a12 + T1.offset.Y()*T2.a22)
+ T2.offset;
}
//
/// Multiply a standard transform with magnification with
/// a standard transform.
//
void transform::multStdWithMagXStd(const transform &T1,
const transform &T2, transform &outT)
{
outT.type = StdTransformWithMagType;
outT.orient = stdOrient(multStdOrientMatrix[T1.orient.getOri()][T2.orient.getOri()]);
outT.a11 = T1.a11;
//
// Transform the offset.
//
outT.offset = T1.offset * T2.orient + T2.offset;
}
//
/// Multiply two standard transforms with magnification.
//
void transform::multStdWithMagXStdWithMag(const transform &T1,
const transform &T2, transform &outT)
{
outT.type = StdTransformWithMagType;
outT.orient = stdOrient(multStdOrientMatrix[T1.orient.getOri()][T2.orient.getOri()]);
outT.a11 = T1.a11*T2.a11;
//
// Transform the offset.
//
outT.offset = T1.offset * T2.orient * T2.a11 + T2.offset;
}
//
/// Multiply a standard transform with magnification with a
/// resolution transform.
//
void transform::multStdWithMagXResolution(const transform &T1,
const transform &T2, transform &outT)
{
outT.type = ResolutionTransformType;
outT.a11 = T2.a11;
outT.a12 = T2.a12;
outT.a21 = T2.a21;
outT.a22 = T2.a22;
if (T2.next) {
if (!outT.next)
outT.next = new transform;
transform tmp(
T1.offset.getX()*T2.a11,
T1.offset.getY()*T2.a22,
T1.orient.getOri(), T1.a11);
tmp.mult(*(T2.next), *(outT.next));
} else {
if (outT.next) {
outT.next->type = StdTransformWithMagType;
outT.next->a11 = T1.a11;
outT.next->a12 = T1.a12;
outT.next->a21 = T1.a21;
outT.next->a22 = T1.a22;
outT.next->offset.setX(T1.offset.getX()*T2.a11);
outT.next->offset.setY(T1.offset.getY()*T2.a22);
outT.next->orient = T1.orient;
} else {
outT.next = new transform(
T1.offset.getX()*T2.a11,
T1.offset.getY()*T2.a22,
T1.orient.getOri(), T1.a11);
}
}
}
//
/// Multiply a resolution transform with any transform.
//
void transform::multResolutionXAny(const transform &T1,
const transform &T2, transform &outT)
{
outT.type = ResolutionTransformType;
outT.a11 = T1.a11;
outT.a12 = T1.a12;
outT.a21 = T1.a21;
outT.a22 = T1.a22;
if(T1.next) {
if (!(outT.next))
outT.next = new transform;
T1.next->mult(T2, *(outT.next));
} else {
outT.next = new transform(T2);
}
}
#endif
//
/// Print a transform, mainly for debug purpose.
//
void transform::print(FILE *outStream, const char *linePrefix) const
{
fprintf(outStream, "%sa11 = %f.\n", linePrefix, a11() );
fprintf(outStream, "%sa12 = %f.\n", linePrefix, a12() );
fprintf(outStream, "%sa21 = %f.\n", linePrefix, a21() );
fprintf(outStream, "%sa22 = %f.\n", linePrefix, a22() );
fprintf(outStream, "%stx = %f.\n", linePrefix, offset_x() );
fprintf(outStream, "%sty = %f.\n", linePrefix, offset_y() );
}
std::ostream & operator << (std::ostream & os, const transform & t)
{
os << "<transform ";
os << ">" << std::endl;
os << "<matrix>" << std::endl;
os << t.getRow1();
os << t.getRow2();
os << "</matrix>" << std::endl;
os << "<offset>" << std::endl;
os << t.getOffset();
os << "</offset>" << std::endl;
os << "</transform>" << std::endl;
return os;
}
}; // namespace base

912
testTransform/transform2.h Normal file
View File

@@ -0,0 +1,912 @@
/*
* SYNOPSYS CONFIDENTIAL - This is an unpublished, proprietary work of Synopsys,
* Inc., and is fully protected under copyright and trade secret laws. You may
* not view, use, disclose, copy, or distribute this file or any information
* contained herein except pursuant to a valid written license from Synopsys.
*/
#ifndef TRANSFORM2_H_
#define TRANSFORM2_H_
// _MSC_VER >= 1400 means we deal with VC8 or higher.
#if defined( _MSC_VER )
/*warning C4290: C++ exception specification ignored except to indicate a function is not __declspec(nothrow)*/
#pragma warning( disable: 4290 )
#endif
#include <math.h>
#include <string>
#include <stdio.h>
#include "base/port.h"
#include "base/constants.h"
#include "base/except.h"
#include "base/rectangle.h"
#include "base/round.h"
//
/// The transform.h file contains the different transform types.
//
/*!
* Usage of transforms:
* Transforms are applied to row vectors from the right as shown below:
* OV = IV * T
* Here, OV and IV are the output and input row vectors and T is the transform.
*
* Multiplying transforms:
* Suppose we have a chain of transforms.
* OV = IV * T1 * T2
* OV = IV * T
* Thus, T can be computed as follows:
* Transform T;
* T1.mult(T2, T);
*
* A general 2-D transform can be viewed in matrix form as follows:
* |a11 a12 0|
* |a21 a22 0|
* | tx ty 1|
* A general transform can be viewed as a sequence of 3 steps:
* 1- Scaling with value (Sx, Sy) (i.e. x' = Sx*x, y' = Sy*y).
* 2- rotating with angle A.
* 3- translating with value (tx, ty).
* In other words, the 2-D transform is the multiplication of the 3 transforms
* as follows:
* |Sx 0 0| | cos(A) sin(A) 0| | 1 0 0|
* |0 Sy 0|*|-sin(A) cos(A) 0|*| 0 1 0|
* |0 0 1| | 0 0 1| |tx ty 1|
*
* Using resolution transforms:
* In order to mimic applying resolution transforms to each cell individually,
* a resolution change operation is applied before anything. Suppose we call
* the resolution change transform RES. Also suppose the transform from the
* cell to the screen is TS. Thus:
* OV = IV * RES * TS.
* In order to change the resolution of a layout, we need to insert the
* resolution transform RES in the chain. Hence:
* 1- Create a resolution transform RES(xScale, yScale, true).
* 2- Assuming T is the total transform, T can be computed as follows:
* RES.mult(TS, T).
*/
namespace base2
{
using namespace base;
//
/// The main transformation class.
//
class GXX_VISIBLE transform
{
// Data
protected:
//
/// 2X2 coefficient submatrix.
//
v2pd a11_a22;
v2pd a21_a12;
//
// Offset for the transform.
//
v2pd voffset;
// Typedefs
protected:
inline double& a11()
{
return *(reinterpret_cast<double*>(&a11_a22));
}
inline double& a21()
{
return *(reinterpret_cast<double*>(&a21_a12));
}
inline double& a12()
{
return *(reinterpret_cast<double*>(&a21_a12)+1);
}
inline double& a22()
{
return *(reinterpret_cast<double*>(&a11_a22)+1);
}
inline double& offset_x()
{
return *(reinterpret_cast<double*>(&voffset));
}
inline double& offset_y()
{
return *(reinterpret_cast<double*>(&voffset)+1);
}
inline double a11() const
{
return *(reinterpret_cast<const double*>(&a11_a22));
}
inline double a21() const
{
return *(reinterpret_cast<const double*>(&a21_a12));
}
inline double a12() const
{
return *(reinterpret_cast<const double*>(&a21_a12)+1);
}
inline double a22() const
{
return *(reinterpret_cast<const double*>(&a11_a22)+1);
}
inline double offset_x() const
{
return *(reinterpret_cast<const double*>(&voffset));
}
inline double offset_y() const
{
return *(reinterpret_cast<const double*>(&voffset)+1);
}
// Construction
public:
//
/// Initialize the function tables.
//
static void initFnTables();
//
/// Default constuctor.
//
transform()
{
a11() = 1.0;
a22() = 1.0;
a21() = 0.0;
a12() = 0.0;
offset_x() = 0.0;
offset_y() = 0.0;
}
//
/// Default constuctor.
//
transform( v2pd a1122,
v2pd a2112,
v2pd o )
{
a11_a22 = a1122;
a21_a12 = a2112;
voffset = o;
}
//
/// Constructor for a scale offset transform.
//
transform(
double offsetX,
double offsetY,
double scaleX,
double scaleY
)
{
a11() = scaleX;
a22() = scaleY;
a21() = 0.0;
a12() = 0.0;
offset_x() = offsetX;
offset_y() = offsetY;
}
//
/// Constructor for a general transform.
//
transform(
double offsetX,
double offsetY,
double coeff11,
double coeff12,
double coeff21,
double coeff22
)
{
a11() = coeff11;
a22() = coeff22;
a21() = coeff21;
a12() = coeff12;
offset_x() = offsetX;
offset_y() = offsetY;
}
//
/// Constructor for a rotate transform.
/// @param inCx X coordinate of the center of rotation.
/// @param inCy Y coordinate of the center of rotation.
/// @param angle rotation angle in degrees.
//
transform(
double inCx,
double inCy,
double angle
)
{
a11() = cos(degreesToRadians(angle));
a22() = a11();
a12() = sin(degreesToRadians(angle));
a21() = -a12();
offset_x() = inCy * a12() - inCx * a11() + inCx;
offset_y() = - inCy * a11() - inCx * a12() + inCy;
}
#if 0
//
/// Constructor for a standard transform.
//
transform(
double offsetX,
double offsetY,
stdOrientEnum inOrient = R0
)
:
a11(1.0),
a12(0.0),
a21(0.0),
a22(1.0),
offset(offsetX,offsetY),
next(NULL),
orient(inOrient),
type(StdTransformType)
{}
//
/// Constructor for a standard transform with magnification.
//
transform(
double offsetX,
double offsetY,
stdOrientEnum inOrient,
double inMag)
:
a11(inMag),
a12(0.0),
a21(0.0),
a22(inMag),
offset(offsetX,offsetY),
next(NULL),
orient(inOrient),
type(StdTransformWithMagType)
{}
#endif
//
/// Advanced constructor for typical references.
/// @param offsetX X value of translation offset.
/// @param offsetY Y value of translation offset.
/// @param inXFlip boolean reflecting the presence of an X flip.
/// @param inAngle rotation angle in degrees.
/// @param inMag magnification.
//
transform(
double offsetX,
double offsetY,
bool inXFlip,
double inAngle,
double inMag)
{
register double multiplier = ( inXFlip ) ? -1.0 : 1.0;
register double newAngle = degreesToRadians(normalizeAngle(inAngle));
register double cosine = cos(newAngle);
register double sine = sin(newAngle);
a11() = inMag * cosine;
a12() = inMag * sine;
a21() = -inMag * multiplier * sine;
a22() = inMag * multiplier * cosine;
offset_x() = offsetX;
offset_y() = offsetY;
}
//
/// Scale or resolution transform.
/// @param xScale X value of the scale factor.
/// @param yScale Y value of the scale factor.
/// @param rouding A true value means it is a resolution transform.
/// A false value will result in a standard scale transform.
//
transform(
double xScale,
double yScale,
bool rounding )
{
a11() = xScale;
a22() = yScale;
a21() = 0.;
a12() = 0.;
offset_x() = 0.;
offset_y() = 0.;
}
//
/// Copy constructor
//
transform( const transform & inT)
{
a11_a22 = inT.a11_a22;
a21_a12 = inT.a21_a12;
voffset = inT.voffset;
}
//
/// Assignment operator
//
transform & operator = (const transform &inT)
{
a11_a22 = inT.a11_a22;
a21_a12 = inT.a21_a12;
voffset = inT.voffset;
return *this;
}
//
/// Destructor
//
~transform()
{
}
public:
//
/// Equal operator
//
bool operator == (const transform &inT)
{
// register v2pd cmp = _mm_cmpeq_pd( vx, inT.vx );
// register v2pd tmp = _mm_cmpeq_pd( vy, inT.vy );
// cmp = _mm_and_pd( cmp, tmp );
// tmp = _mm_cmpeq_pd( voffset, inT.voffset );
// cmp = _mm_and_pd( cmp, tmp );
return false;
}
//
/// Non equal operator
//
bool operator != (const transform &inT)
{
// register v2pd cmp = _mm_cmpneq_pd( vx, inT.vx );
// register v2pd tmp = _mm_cmpneq_pd( vy, inT.vy );
// cmp = _mm_or_pd( cmp, tmp );
// tmp = _mm_cmpneq_pd( voffset, inT.voffset );
// cmp = _mm_or_pd( cmp, tmp );
return true;
}
#if 0
//
/// Test whether this is an identity transform.
//
bool isIdentityTransform() const
throw (except::outOfRange)
{
const double onePlusTolerance = 1.0 + relTolerance;
const double oneMinusTolerance = 1.0 - relTolerance;
//
// See if the offsets are beyond the origin.
//
if (offset.X() > absTolerance || offset.X() < -absTolerance ||
offset.Y() > absTolerance || offset.Y() < -absTolerance)
return false;
//
// Check by transform type.
//
switch((transformType) type)
{
case StdTransformWithMagType:
if (a11 > onePlusTolerance || a11 < oneMinusTolerance)
return false;
case StdTransformType:
if (orient.getOri() != R0)
return false;
break;
case GeneralTransformType:
if ( a12 > absTolerance ||
a12 < -absTolerance ||
a21 > absTolerance ||
a21 < -absTolerance)
return false;
case ScaleOffsetTransformType:
case ScaleTransformType:
if ( a11 > onePlusTolerance ||
a11 < oneMinusTolerance ||
a22 > onePlusTolerance ||
a22 < oneMinusTolerance)
return false;
break;
case ResolutionTransformType:
return false;
break;
default:
throw except::outOfRange("base::transform:isIdentityTransform: Unknown type.");
}
return true;
}
//
/// Returns the type of the transform.
//
transformType getType() const
{
return (transformType) type;
}
stdOrient getOrient() const
{
return orient;
}
//
/// Return the next field.
//
const transform *getNext() const
{
return next;
}
//
/// Return the next field.
//
transform *getNext()
{
return next;
}
#endif
//
/// Returns the offset point of the transform.
//
pod::point<double> getOffset() const
{
return pod::point<double>( offset_x(), offset_y() );
}
//
/// Returns the offset point of the transform taking into account also resolution.
//
pod::point<double> getOffsetRes() const
{
return pod::point<double>( offset_x(), offset_y() );
}
//
/// Set the offset of the transform.
//
void setOffset( pod::point<double> off )
{
voffset = off.get_pd();
}
pod::point<double> getDiagonal() const
{
return pod::point<double>(a11(),a22());
}
pod::point<double> getRow1() const
{
return pod::point<double>(a11(),a12());
}
pod::point<double> getRow2() const
{
return pod::point<double>(a21(),a22());
}
pod::point<double> getCol1() const
{
return pod::point<double>(a11(),a21());
}
pod::point<double> getCol2() const
{
return pod::point<double>(a12(),a22());
}
//
/// Return the magnitude of the vector (1,0).
//
double getXVectorMag() const
{
if ( a21() == 0.0 )
return ::fabs(a11());
else if ( a11() == 0.0 )
return ::fabs(a21());
else
return ::sqrt(a11()*a11() + a21()*a21());
}
//
/// A special function to return the X scale factor. This
/// is a nonnegative value that reflects the scaling effect
/// in the X direction.
//
double getXScale() const
{
return getXVectorMag();
}
//
/// Returns the a11 entry of the matrix. If the matrix is a scaling
/// one, then this returns the X-scale factor.
/// The result is not correct for all types of transforms.
//
double get11() const
{
return a11();
}
//
/// Return the a12 entry of the matrix.
/// The result is only valid for general transforms.
/// The result is not correct for all types of transforms.
//
double get12() const
{
return a12();
}
//
/// Return the a21 entry of the matrix.
/// The result is only valid for general transforms.
/// The result is not correct for all types of transforms.
//
double get21() const
{
return a21();
}
//
/// Returns the a22 entry of the matrix. If the matrix is a scaling
/// one, then this returns the Y-scale factor.
/// The result is not correct for all types of transforms.
//
double get22() const
{
return a22();
}
//
/// get angle, isXFlip and mag from transformation
//
const void getAngleFlipMag( double& angle, bool& isXFlip, double& mag) const;
// Complex functions.
public:
////////////////////////////////////////////////////////////////
//
/// Modify a single point.
//
template <class C>
pod::point<short> modifyDblToShort(pod::point<C> p) const
{
pod::rectangle<short> tmp;
modify( r, tmp );
return tmp;
}
template <class C>
pod::point<int> modifyDblToInt(pod::point<C> p) const
{
pod::rectangle<int> tmp;
modify( r, tmp );
return tmp;
}
template <class C>
pod::point<double> modifyDblToDbl(pod::point<C> p) const
{
pod::rectangle<double> tmp;
modify( r, tmp );
return tmp;
}
template <class C>
pod::point<short> modifyIntToShort(pod::point<C> p) const
{
pod::rectangle<short> tmp;
modify( r, tmp );
return tmp;
}
template <class C>
pod::point<int> modifyIntToInt(pod::point<C> p) const
{
pod::rectangle<int> tmp;
modify( r, tmp );
return tmp;
}
template <class C>
pod::point<short> modifyLongToShort(pod::point<C> p) const
{
pod::rectangle<short> tmp;
modify( r, tmp );
return tmp;
}
template <class C>
pod::point<int> modifyLongToInt(pod::point<C> p) const
{
pod::rectangle<int> tmp;
modify( r, tmp );
return tmp;
}
template <class C>
pod::point<long> modifyLongToLong(pod::point<C> p) const
{
pod::rectangle<long> tmp;
modify( r, tmp );
return tmp;
}
template<class C>
pod::rectangle<C> operator()(const pod::rectangle<C> & r) const
{
return modify( r );
}
template<class C>
pod::point<C> operator()(const pod::point<C> & p) const
{
return modify( p );
}
transform operator *(const transform & t2 ) const
{
return mult( t2 );
}
///////////////////////////////////////////////////////////////////////////
//
/// Multiply with another transform.
//
void mult(const transform &T2, transform &outT) const
{
//
// new_a11 = t1_a11*t2_a11 + t1_a12*t2_a21
// new_a22 = t1_a22*t2_a22 + t1_a21*t2_a12
//
v2pd m1 = _mm_mul_pd( a11_a22, T2.a11_a22 );
v2pd m2 = a21_a12;
m2 = _mm_shuffle_pd( m2, m2, 1 );
m2 = _mm_mul_pd( m2, T2.a21_a12 );
outT.a11_a22 = _mm_add_pd( m1, m2 );
//
// new_a21 = t1_a21*t2_a11 + t1_a22*t2_a21
// new_a12 = t1_a12*t2_a22 + t1_a11*t2_a12
//
v2pd m3 = _mm_mul_pd( a21_a12, T2.a11_a22 );
v2pd m4 = a11_a22;
m4 = _mm_shuffle_pd( m4, m4, 1 );
m4 = _mm_mul_pd( m4, T2.a21_a12 );
outT.a21_a12 = _mm_add_pd( m3, m4 );
//
// new_xoffset = t1_xoffset*t2_a11 + t1_yoffset*t2_a21+t2_xoffset
// new_yoffset = t1_yoffset*t2_a22 + t1_xoffset*t2_a12+t2_yoffset
//
v2pd m5 = _mm_mul_pd( voffset, T2.a11_a22 );
v2pd m6 = voffset;
m6 = _mm_shuffle_pd( m6, m6, 1 );
m6 = _mm_mul_pd( voffset, T2.a21_a12 );
m5 = _mm_add_pd( m5, m6 );
outT.voffset = _mm_add_pd( m5, T2.voffset );
}
//
/// Multiply with another transform.
//
transform mult(const transform &T2) const
{
//
// new_a11 = t1_a11*t2_a11 + t1_a12*t2_a21
// new_a22 = t1_a22*t2_a22 + t1_a21*t2_a12
//
v2pd m1 = _mm_mul_pd( a11_a22, T2.a11_a22 );
v2pd m2 = a21_a12;
m2 = _mm_shuffle_pd( m2, m2, 1 );
m2 = _mm_mul_pd( m2, T2.a21_a12 );
v2pd t_a11_a22 = _mm_add_pd( m1, m2 );
//
// new_a21 = t1_a21*t2_a11 + t1_a22*t2_a21
// new_a12 = t1_a12*t2_a22 + t1_a11*t2_a12
//
v2pd m3 = _mm_mul_pd( a21_a12, T2.a11_a22 );
v2pd m4 = a11_a22;
m4 = _mm_shuffle_pd( m4, m4, 1 );
m4 = _mm_mul_pd( m4, T2.a21_a12 );
v2pd t_a21_a12 = _mm_add_pd( m3, m4 );
//
// new_xoffset = t1_xoffset*t2_a11 + t1_yoffset*t2_a21+t2_xoffset
// new_yoffset = t1_yoffset*t2_a22 + t1_xoffset*t2_a12+t2_yoffset
//
v2pd m5 = _mm_mul_pd( voffset, T2.a11_a22 );
v2pd m6 = voffset;
m6 = _mm_shuffle_pd( m6, m6, 1 );
m6 = _mm_mul_pd( voffset, T2.a21_a12 );
m5 = _mm_add_pd( m5, m6 );
v2pd t_voffset = _mm_add_pd( m5, T2.voffset );
//
// Return the result
//
return transform( t_a11_a22, t_a21_a12, t_voffset );
}
//
/// Scale the transform by the given scalar.
//
transform & operator *= (const double d)
{
v2pd m = _mm_set1_pd( d );
a11_a22 = _mm_mul_pd( a11_a22, m );
a21_a12 = _mm_mul_pd( a21_a12, m );
voffset = _mm_mul_pd( voffset, m );
return *this;
}
//
/// Return the inverse transform of the transform.
//
transform getInverse() const
{
//
// Get determinant.
//
double det = a11()*a22()-a21()*a12();
v2pd detx2 = _mm_set1_pd( det );
//
// Get inv_a11 and inv_a22
//
// inv_a11 = a22/det
// inv_a11 = a11/det
//
v2pd t_a11_a22 = a11_a22;
t_a11_a22 = _mm_shuffle_pd( t_a11_a22, t_a11_a22, 1 );
t_a11_a22 = _mm_div_pd( t_a11_a22, detx2 );
//
// inv_a21 = -a21/det
// inv_a12 = -a12/det
//
v2pd t_a21_a12 = _mm_set1_pd( 0.0 );
t_a21_a12 = _mm_sub_pd( t_a21_a12, a21_a12 );
t_a21_a12 = _mm_div_pd( t_a21_a12, detx2 );
//
// inv_xoffset = -xoffset*inv_a11 -yoffset*inv_a21
// inv_yoffset = -yoffset*inv_a22 -xoffset*inv_a12
//
v2pd t_voffset = _mm_set1_pd( 0.0 );
t_voffset = _mm_sub_pd( t_voffset, voffset );
t_voffset = _mm_mul_pd( t_voffset, t_a11_a22 );
v2pd r_voffset = voffset;
r_voffset = _mm_shuffle_pd( r_voffset, r_voffset, 1 );
r_voffset = _mm_mul_pd( r_voffset, t_a21_a12 );
t_voffset = _mm_sub_pd( t_voffset, r_voffset );
//
// Return the result.
//
return transform( t_a11_a22, t_a21_a12, t_voffset );
}
//
/// This is a convinient function converting coordinate types without loss of precision.
//
/*!
We try to not loss precision and use available functionality
provided by transform maximally. This function does what
all modifyXxxxToYyyyy does and is very helpful in generic programming.
*/
template <class iC, class oC>
__forceinline void modify( const pod::point<iC>& rSrc, pod::point<oC>& rDest ) const
{
// rDest = modify( rSrc );
//
// x = x*a11 + y*a21
// y = y*a22 + x*a12
//
v2pd d = rSrc.get_pd();
v2pd d_rev = d;
d_rev = _mm_shuffle_pd( d_rev, d, 1 );
d = _mm_mul_pd( d, a11_a22 );
d_rev = _mm_mul_pd( d_rev, a21_a12 );
d = _mm_add_pd( d, voffset );
d = _mm_add_pd( d, d_rev );
rDest.set_pd( d );
}
//
/// This is a convinient function converting coordinate types without loss of precision.
//
/*!
We try to not loss precision and use available functionality
provided by transform maximally. This function does what
all modifyXxxxToYyyyy does and is very helpful in generic programming.
*/
template <class C>
__forceinline pod::point<C> modify( const pod::point<C>& rSrc ) const
{
//
// x = x*a11 + y*a21
// y = y*a22 + x*a12
//
v2pd d = rSrc.get_pd();
v2pd d_rev = d;
d_rev = _mm_shuffle_pd( d_rev, d, 1 );
d = _mm_mul_pd( d, a11_a22 );
d_rev = _mm_mul_pd( d_rev, a21_a12 );
d = _mm_add_pd( d, voffset );
d = _mm_add_pd( d, d_rev );
return pod::point<C>( d );
}
//
/// This is pod::rectangle version of above function.
//
template <class iC, class oC>
__forceinline void modify( const pod::rectangle<iC>& rSrc, pod::rectangle<oC>& rDest ) const
{
modifyBBox( rSrc, rDest );
}
//
/// This is pod::rectangle version of above function.
//
template <class C>
__forceinline pod::rectangle<C> modify( const pod::rectangle<C>& rSrc ) const
{
pod::rectangle<C> dest;
modifyBBox( rSrc, dest );
return dest;
}
//
/// Transform given bbox.
//
/*!
While we transform bbox, the usual approach of transforming
lower left and upper right is not satisfactory. In case of
rotations we need to transform and merge all four vertices
of bbox to get one of bbox rectangles of a shape which bbox we
want to transform. The bbox transformed this way will not be the
smallest bbox of the shape, yet at least this will be a bbox.
While if we use usual approach, then we will get (in case of rotation)
a rectangle that is not nessecarily a bbox of original shape.
The function also optimizes cases when transform has
only orthogonal transforms.
*/
template <class iC, class oC>
__forceinline void modifyBBox( const pod::rectangle<iC>& rSrc, pod::rectangle<oC>& rDest ) const
{
pod::point<oC> b1 = modify( rSrc.getLowerLeftRef() );
pod::point<oC> b2 = modify( rSrc.getUpperRightRef() );
rDest.setRect( b1, b2 );
rDest.makeValid();
//
// If we have orthogonal transform?
// First check get12 since most of transform will
// have no rotation factor.
//
// v2pd a1112 = _mm_shuffle_pd( a11_a22, a21_a12, 1 )
// v2pd a1112 = _mm_shuffle_pd( a11_a22, a21_a12, 1 )
if ( a12() != 0. && a11() != 0. )
{
pod::point<oC> b3 = modify( rSrc.getUpperLeft() );
rDest.merge( b3 );
pod::point<oC> b4 = modify( rSrc.getLowerRight() );
rDest.merge( b4 );
}
}
//
/// Convert a transform type to a string.
//
friend std::ostream & operator << (std::ostream & os, const transform & t);
//
/// Print a transform, mainly for debug purpose.
//
void print(FILE *outStream, const char *linePrefix) const;
}; // class transform
} // namespace base
#endif // TRANSFORM_H_