initial check in
This commit is contained in:
1582
testTransform/_transform.cpp
Normal file
1582
testTransform/_transform.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1408
testTransform/_transform.h
Normal file
1408
testTransform/_transform.h
Normal file
File diff suppressed because it is too large
Load Diff
570
testTransform/main.cpp
Normal file
570
testTransform/main.cpp
Normal 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<int32></a><br>"
|
||||
<< "<a href=\"#_2\">pod::point<int64></a><br>"
|
||||
<< "<a href=\"#_3\">pod::point<double></a><br>"
|
||||
<< "<a href=\"#_4\">pod::rectangle<int32></a><br>"
|
||||
<< "<a href=\"#_5\">pod::rectangle<int64></a><br>"
|
||||
<< "<a href=\"#_6\">pod::rectangle<double></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<int32></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<int64></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<double></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<int32></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<int64></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<double></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
198
testTransform/sseprim.h
Normal 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
48
testTransform/ssetypes.h
Normal 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__
|
||||
20
testTransform/testTransform.sln
Normal file
20
testTransform/testTransform.sln
Normal 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
|
||||
362
testTransform/testTransform.vcproj
Normal file
362
testTransform/testTransform.vcproj
Normal 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
1593
testTransform/transform.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1493
testTransform/transform.h
Normal file
1493
testTransform/transform.h
Normal file
File diff suppressed because it is too large
Load Diff
845
testTransform/transform2.cpp
Normal file
845
testTransform/transform2.cpp
Normal 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
912
testTransform/transform2.h
Normal 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_
|
||||
Reference in New Issue
Block a user