Mass++ Common Libraries v2.7.5
 All Classes Namespaces Files Functions Variables Enumerations Macros
XYData.cpp
Go to the documentation of this file.
1 
20 #include "stdafx.h"
21 #include "XYData.h"
22 
23 #include "SearchTool.h"
24 #include "FileAccessor.h"
25 #include "Buffer.h"
26 #include "MsppManager.h"
27 
28 #include <math.h>
29 #include <boost/bind.hpp>
30 
31 // @date 2011.03.02 <Add> M.Aihara ->
32 // add TBB mutex code
33 #ifdef ENABLE_MASSPP_PARALLEL_TBB_MODE
34 #include "tbb/spin_mutex.h"
35 using namespace tbb;
36 
37 
38 #include <crtdbg.h>
39 #ifdef _DEBUG
40  #define new new( _NORMAL_BLOCK, __FILE__, __LINE__ )
41  #define malloc( s ) _malloc_dbg( s, _NORMAL_BLOCK, __FILE__, __LINE__ )
42 #endif // _DEBUG
43 
44 
45 namespace
46 {
47  typedef spin_mutex XYDATA_ParallelMutexType;
48  XYDATA_ParallelMutexType XYDATA_ParallelMutex_01;
49  XYDATA_ParallelMutexType XYDATA_ParallelMutex_02;
50 }
51 #endif // ENABLE_MASSPP_PARALLEL_TBB_MODE
52 // <Add> M.Aihara <-
53 
54 using namespace kome::core;
55 
57 const unsigned int XYData::m_cacheSize = 10000;
58 
60 unsigned long XYData::m_currentVersion = 0;
61 
62 // constructor
63 XYData::XYData() {
64  m_updated = false;
65  m_released = true;
66 
67  m_minX = 0.0;
68  m_maxX = 0.0;
69  m_minY = 0.0;
70  m_maxY = 0.0;
71  m_version = 0;
72 }
73 
74 // destructor
75 XYData::~XYData() {
76  // manager
77  MsppManager& msppMgr = MsppManager::getInstance();
78 
79  // delete data file
80 //#pragma omp critical ( deleteXYDataFromCache )
81  {
82 // @date 2011.03.02 <Add> M.Aihara ->
83 // add TBB mutex code
84 #ifdef ENABLE_MASSPP_PARALLEL_TBB_MODE
85  XYDATA_ParallelMutexType::scoped_lock lock( XYDATA_ParallelMutex_01 );
86 #endif // ENABLE_MASSPP_PARALLEL_TBB_MODE
87 // <Add> M.Aihara <-
88 
89  // delete object from cache list
90  std::list< XYData* >& cacheList = getCacheList();
91  std::list< XYData* >::iterator it = cacheList.begin();
92  while( it != cacheList.end() ) {
93  if( *it == this ) {
94  cacheList.erase( it );
95  it = cacheList.end();
96  }
97  else {
98  it++;
99  }
100  }
101 
102  // delete data
103  if( !m_tmpDataFile.empty() ) {
104  // get path
105  std::string filePath = getpath( msppMgr.getTmpDir(), m_tmpDataFile.c_str() );
106 
107  removefile( filePath.c_str() );
108  }
109  }
110 }
111 
112 // get minimum x
113 double XYData::getMinX() {
114  updateRange();
115  return m_minX;
116 }
117 
118 // get maximum x
119 double XYData::getMaxX() {
120  updateRange();
121  return m_maxX;
122 }
123 
124 // get minimum y
125 double XYData::getMinY() {
126  updateRange();
127  return m_minY;
128 }
129 
130 // get maximum y
131 double XYData::getMaxY() {
132  updateRange();
133  return m_maxY;
134 }
135 
136 // clear points
137 void XYData::clearPoints() {
138  // recover
139  recoverData();
140 
141  // clear points
142  onClearPoints();
143 
144  // flag
145  m_updated = true;
146 }
147 
148 // add point
149 void XYData::addPoint( const double x, const double y ) {
150  // recover data
151  recoverData();
152 
153  // add point
154  onAddPoint( x, y );
155 
156  // flag
157  m_updated = true;
158 }
159 
160 // insert point
161 void XYData::insertPoint( const unsigned int index, const double x, const double y ) {
162  // recover data
163  recoverData();
164 
165  // insert point
166  onInsertPoint( std::min( index, getLength() ), x, y );
167 
168  // flag
169  m_updated = true;
170 }
171 
172 // update point
173 void XYData::updatePoint( const unsigned int index, const double x, const double y ) {
174  // recover data
175  recoverData();
176 
177  // check the index
178  if( index >= getLength() ) {
179  return;
180  }
181 
182  // delete
183  deletePoint( index );
184 
185  // search
186  int idx = searchIndex( x );
187  if( idx < 0 ) {
188  idx = - idx - 1;
189  }
190 
191  // insert
192  onInsertPoint( idx, x, y );
193 
194  // flag
195  m_updated = true;
196 }
197 
198 // delete point
199 void XYData::deletePoint( const unsigned int index ) {
200  // recover data
201  recoverData();
202 
203  // check the parameter
204  if( index >= getLength() ) {
205  return;
206  }
207 
208  // on delete
209  onDeletePoint( index );
210 
211  // flag
212  m_updated = true;
213 }
214 
215 // get the number of points
216 unsigned int XYData::getLength() {
217  // recover data
218  recoverData();
219 
220  return onGetLength();
221 }
222 
223 // get x coordinate
224 double XYData::getX( const unsigned int index ) {
225  // recover data
226  recoverData();
227 
228  if( index >= getLength() ) {
229  std::string msg = FMT(
230  "The point index(%d) is larger than max index(%d).",
231  index,
232  getLength() - 1
233  );
234 
235  LOG_WARN( msg );
236  throw msg;
237  }
238 
239  return onGetX( index );
240 }
241 
242 // get y coordinate
243 double XYData::getY( const unsigned int index ) {
244  // recover data
245  recoverData();
246 
247  if( index >= getLength() ) {
248  std::string msg = FMT(
249  "The point index(%d) is larger than max index(%d).",
250  index,
251  getLength() - 1
252  );
253 
254  LOG_WARN( msg );
255  throw msg;
256  }
257 
258  return onGetY( index );
259 }
260 
261 // reserve
262 void XYData::reserve( const unsigned int num ) {
263  // recover data
264  recoverData();
265 
266  onReserve( num );
267 }
268 
269 // get version
270 unsigned long XYData::getVersion() {
271  updateRange();
272  return m_version;
273 }
274 
275 // search index
276 int XYData::searchIndex( const double x ) {
277  // recover data
278  recoverData();
279 
280  // comparator
281  class SearchHelper {
282  public:
283  // compare to search
284  static int compare( double x0, double x1 ) {
285  if( x0 < x1 ) {
286  return -1;
287  }
288  if( x0 > x1 ) {
289  return 1;
290  }
291  return 0;
292  }
293 
294  // get x
295  static double getX( int index, XYData* xyData ) {
296  return xyData->onGetX( index );
297  }
298  };
299 
300  // search
301  int idx = -1;
302  idx = SearchTool::binarySearch< double, double >(
303  x,
304  boost::bind( SearchHelper::getX, _1, this ),
305  SearchHelper::compare,
306  getLength()
307  );
308 
309  return idx;
310 }
311 
312 // get nearest index
313 int XYData::getNearestIndex( const double x ) {
314  // length
315  int len = (int)getLength();
316  if( len == 0 ) {
317  return -1;
318  }
319 
320  // search
321  int idx = searchIndex( x );
322 
323  if( idx >= 0 ) {
324  return idx;
325  }
326 
327  int idx0 = - idx - 2;
328  int idx1 = - idx - 1;
329 
330  if( idx0 < 0 ) {
331  return idx1;
332  }
333  if( idx1 >= len ) {
334  return idx0;
335  }
336 
337  // distance
338  double d0 = fabs( getX( idx0 ) - x );
339  double d1 = fabs( getX( idx1 ) - x );
340 
341  return ( d1 < d0 ? idx1 : idx0 );
342 }
343 
344 // executes filter
345 void XYData::filter( const double absY, const double relY ) {
346  // recover data
347  recoverData();
348 
349  // length
350  int len = (int)getLength();
351  if( len <= 0 ) {
352  return;
353  }
354 
355  // threshold
356  double minY = std::max( fabs( m_minY ), fabs( m_maxY ) ) * relY / 100.0;
357  minY = std::max( absY, minY );
358 
359  // filter
360  for( int i = len - 1; i >= 0; i-- ) {
361  double y = getY( i );
362  if( y < minY ) {
363  onDeletePoint( i );
364  }
365  }
366 
367  // flag
368  m_updated = true;
369 }
370 
371 // get points
372 void XYData::getPoints( std::vector< Point< double > >& points, const bool ySort, const bool desc ) {
373  // recover data
374  recoverData();
375 
376  // definition
377  typedef Point< double > pt;
378 
379  // initialize
380  points.clear();
381 
382  // set data
383  unsigned int len = getLength();
384  if( len == 0 ) {
385  return;
386  }
387  points.resize( len );
388 
389  for( unsigned int i = 0; i < len; i++ ) {
390  points[ i ].px = onGetX( i );
391  points[ i ].py = onGetY( i );
392  }
393 
394  // sort
395  std::sort(
396  points.begin(),
397  points.end(),
398  ySort ? ( desc ? pt::greaterY : pt::lessY ) : ( desc ? pt::greaterX : pt::lessX )
399  );
400 }
401 
402 // import data
403 bool XYData::importData( boost::function< int ( void*, int ) > readFun ) {
404  // clear
405  onClearPoints();
406 
407  // import
408  bool ret = onLoadData( readFun );
409 
410  return ret;
411 }
412 
413 // export data
414 bool XYData::exportData( boost::function< int ( void*, int ) > writeFun ) {
415  // update range
416  updateRange();
417 
418  // export
419  bool ret = onSaveData( writeFun );
420  return ret;
421 }
422 
423 // get the total time of loading temporary file
424 // @date 2011.03.02 <Del> M.Aihara ->
425 // double XYData::getInputTotalTime() {
426 // return m_inputTimer.getTotalTime();
427 // }
428 // <Del> M.Aihara
429 
430 // get the total time of saving temporary file
431 // @date 2011.03.02 <Del> M.Aihara ->
432 // double XYData::getOutputTotalTime() {
433 // return m_outputTimer.getTotalTime();
434 // }
435 // <Del> M.Aihara <-
436 
437 // udpate range
438 void XYData::updateRange() {
439  // version
440  if( m_updated || m_version == 0 ) {
441  m_currentVersion = m_currentVersion + 1;
442  m_version = m_currentVersion;
443  }
444 
445  // check the flag
446  if( !m_updated ) {
447  return;
448  }
449 
450  // initialize
451  m_minX = 0.0;
452  m_maxX = 0.0;
453  m_minY = 0.0;
454  m_maxY = 0.0;
455 
456  // set min/max values
457  unsigned int len = getLength();
458  for( unsigned int i = 0; i < len; i++ ) {
459  const double x = getX( i );
460  const double y = getY( i );
461 
462  if( i == 0 || x < m_minX ) {
463  m_minX = x;
464  }
465  if( i == 0 || x > m_maxX ) {
466  m_maxX = x;
467  }
468  if( i == 0 || y < m_minY ) {
469  m_minY = y;
470  }
471  if( i == 0 || y > m_maxY ) {
472  m_maxY = y;
473  }
474  }
475 
476  // set the flag
477  m_updated = false;
478 }
479 
480 // on load data
481 bool XYData::onLoadData( boost::function< int ( void*, int ) > readFun ) {
482  // length
483  unsigned long len = 0;
484  readFun( &len, sizeof( len ) );
485 
486  // read data
487  if( len > 0 ) {
488  double* arr = new double[ len * 2 ];
489  readFun( arr, sizeof( double ) * len * 2 );
490 
491  onReserve( len );
492  for( unsigned int i = 0; i < len; i++ ) {
493  onAddPoint( arr[ i * 2 ], arr[ i * 2 + 1 ] );
494  }
495 
496  delete[] arr;
497  }
498 
499  return true;
500 }
501 
502 // on save data
503 bool XYData::onSaveData( boost::function< int ( void*, int ) > writeFun ) {
504  // length
505  unsigned long len = onGetLength();
506  writeFun( &len, sizeof( len ) );
507 
508  // write data
509  if( len > 0 ) {
510  double* arr = new double[ len * 2 ];
511  for( unsigned int i = 0; i < len; i++ ) {
512  arr[ i * 2 ] = onGetX( i );
513  arr[ i * 2 + 1 ] = onGetY( i );
514  }
515 
516  writeFun( arr, sizeof( double ) * len * 2 );
517 
518  delete[] arr;
519  }
520 
521  return true;
522 }
523 
524 // release data
525 void XYData::releaseData() {
526  // check the flag
527  if( m_released ) {
528  return;
529  }
530 
531  // manager
532  MsppManager& msppMgr = MsppManager::getInstance();
533 
534  // cache list
535  getCacheList();
536 
537  // save data
538  // @date 2011.03.02 <Del> M.Aihara
539  // m_outputTimer.start();
540 
541  // create data
542  Buffer buffer;
543  exportData( boost::bind( &DataAccessor::write, &buffer, _1, _2 ) );
544 
545  static int tmpDirCnt = 0;
546 
547  if( m_tmpDataFile.empty() ) { // create tmp file
548  // directory
549  std::string dir = getpath( "xy_data", FMT( "%02x", tmpDirCnt ).c_str() );
550  tmpDirCnt = ( tmpDirCnt + 1 ) % 0x100;
551 
552  // file name
553  std::string fileName = msppMgr.getTmpFileName(
554  FMT( "xy_data%04d", ( 0xffff & (long long)this ) ).c_str(),
555  ".xyd",
556  dir.c_str()
557  );
558  m_tmpDataFile = getpath( dir.c_str(), fileName.c_str() );
559  }
560 
561  // write
562  std::string path = getpath( msppMgr.getTmpDir(), m_tmpDataFile.c_str() );
563  FILE* fp = fileopen( path.c_str(), "wb" );
564 
565  FileAccessor acc( fp );
566  exportData( boost::bind( &DataAccessor::write, &acc, _1, _2 ) );
567 
568  fflush( fp );
569  fclose( fp );
570 
571  // @date 2011.03.02 <Del> M.Aihara
572  // m_outputTimer.stop();
573 
574  // flag
575  m_released = true;
576 
577  // clear points
578  onClearPoints();
579 }
580 
581 
582 // recover data
583 void XYData::recoverData() {
584  // cache list
585  // @date 2011.03.02 <Mod> M.Aihara ->
586  // modify getCacheList() and cacheList.push_back()
587  // std::list< XYData* >& cacheList = getCacheList();
588  // <Mod> M.Aihara <-
589 
590  // check the flag
591  if( !m_released ) {
592  return;
593  }
594 
595  // flag
596  m_released = false;
597 
598 // @date 2011.03.02 <Add> M.Aihara ->
599 // add TBB mutex code
600 #ifdef ENABLE_MASSPP_PARALLEL_TBB_MODE
601  {
602  XYDATA_ParallelMutexType::scoped_lock lock( XYDATA_ParallelMutex_01 );
603 #endif // ENABLE_MASSPP_PARALLEL_TBB_MODE
604 // <Add> M.Aihara <-
605 
606  // @date 2011.03.02 <Mod> M.Aihara ->
607  // modify getCacheList() and cacheList.push_back()
608  // cache list
609  std::list< XYData* >& cacheList = getCacheList();
610  // <Mod> M.Aihara <-
611 
612  // release other data
613 //#pragma omp critical ( deleteXYDataFromCache )
614  {
615  while( (int)cacheList.size() > (int)m_cacheSize - 1 ) {
616  cacheList.front()->releaseData();
617  cacheList.pop_front();
618  }
619  }
620 
621  // @date 2011.03.02 <Mod> M.Aihara ->
622  // modify getCacheList() and cacheList.push_back()
623  cacheList.push_back( this );
624  // <Mod> M.Aihara <-
625 
626 // @date 2011.03.02 <Add> M.Aihara ->
627 // add TBB mutex code
628 #ifdef ENABLE_MASSPP_PARALLEL_TBB_MODE
629  }
630 #endif // ENABLE_MASSPP_PARALLEL_TBB_MODE
631 // <Add> M.Aihara <-
632 
633  // recover
634  // @date 2011.03.02 <Del> M.Aihara
635  // m_inputTimer.start();
636 
637  if( !m_tmpDataFile.empty() ) {
638 
639 // @date 2011.03.02 <Add> M.Aihara ->
640 // add TBB mutex code
641 #ifdef ENABLE_MASSPP_PARALLEL_TBB_MODE
642  XYDATA_ParallelMutexType::scoped_lock lock( XYDATA_ParallelMutex_02 );
643 #endif // ENABLE_MASSPP_PARALLEL_TBB_MODE
644 // <Add> M.Aihara
645 
646  // data file path
647  MsppManager& msppMgr = MsppManager::getInstance();
648  std::string path = getpath( msppMgr.getTmpDir(), m_tmpDataFile.c_str() );
649 
650  // file open
651  FILE* fp = fileopen( path.c_str(), "rb" );
652 
653  // import
654  FileAccessor acc( fp );
655  importData( boost::bind( &DataAccessor::read, &acc, _1, _2 ) );
656 
657  fclose( fp );
658  }
659 
660  // @date 2011.03.02 <Mod> M.Aihara ->
661  // modify getCacheList() and cacheList.push_back()
662 // #pragma omp critical ( deleteXYDataFromCache )
663 // {
664 // cacheList.push_back( this );
665 // }
666  // <Mod> M.Aihara <-
667 
668  // @date 2011.03.02 <Del> M.Aihara
669  // m_inputTimer.stop();
670 
671 }
672 
673 // get cache list
674 std::list< XYData* >& XYData::getCacheList() {
675  // create object
676  static std::list< XYData* > cl;
677 
678  return cl;
679 }
abstraction class of two dimention coordinate data
Definition: XYData.h:34
memory buffer management class
Definition: Buffer.h:28
file accessor class
Definition: FileAccessor.h:26
interfaces of SearchTool class
Mass++ manager class.
Definition: MsppManager.h:28
virtual double onGetX(const unsigned int index)=0
This method is called by getX method. (abstract method)
const char * getTmpDir()
gets temporary file directory name
interfaces of XYData class
implements of MsppManager class
FILE * fileopen(const char *path, const char *mode)
opens file
interfarces of FileAccessor class
bool removefile(const char *path)
removes file
interfarces of Buffer class
std::string getTmpFileName(const char *prefix, const char *suffix, const char *dir=NULL)
gets temporary file name
std::string getpath(const char *dir, const char *file)
get file path