libfbm  0.3
Simulation of multi-dimensional stationary Gaussian processes and fractional Brownian motion.
 All Classes Namespaces Functions Variables Friends
libfbm.hpp
1 
309 #ifndef __libfbm_hpp__
310 #define __libfbm_hpp__
311 
312 #include <vector>
313 #include <string>
314 
315 #include <stdint.h>
316 
321 #define LIBFBM_MAX_DIM 8
322 
323 #define LIBFBM_VERSION 0.3
324 
325 namespace libfbm
326 {
332  {
333  public:
334  virtual ~GaussianGenerator();
335 
336  virtual void setSeed(uint32_t seed) = 0;
337  virtual void setSeed(const unsigned char *seed_array, size_t len) = 0;
338 
339  virtual double getDouble() = 0;
340  virtual void getDouble(double *array, size_t len) = 0;
341  };
342 
343  #define _LIBFBM_GG_POOL_SIZE (312*4)
344 
355  {
356  public:
357  SFMTGaussianGenerator(uint32_t seed = 0);
358  SFMTGaussianGenerator(const unsigned char *seed_array, size_t len);
360 
361  void setSeed(uint32_t seed);
362  void setSeed(const unsigned char *seed_array, size_t len);
363 
364  double getDouble();
365  void getDouble(double *array, size_t len);
366 
367  private:
368  void *sfmt;
369  uint64_t ipool[_LIBFBM_GG_POOL_SIZE];
370  double opool[_LIBFBM_GG_POOL_SIZE];
371  size_t ipindex;
372  size_t opindex;
373 
374  void fill(double *array, size_t len);
375  };
376 
388  class Seeder
389  {
390  public:
393  Seeder(const char *path);
394  ~Seeder();
395 
396  void seed(uint32_t index);
397 
398  inline size_t size() const { return sizeof(buf); }
399  inline operator const unsigned char *() const { return (const unsigned char *)buf; }
400 
401  private:
402  unsigned char buf[256];
403  FILE *fp;
404 
405  Seeder(const Seeder&);
406  const Seeder& operator=(const Seeder&);
407  };
408 
411  class zvec
412  {
413  public:
414  inline zvec(size_t dim) : clen(dim) { }
415 
416  inline int& operator[](size_t i) { return c[i]; }
417  inline const int& operator[](size_t i) const { return c[i]; }
418 
419  inline size_t size() const { return clen; }
420 
423  inline bool increment(int base)
424  {
425  for ( size_t i = 0; i < size(); i++ )
426  {
427  if ( c[i] < base - 1 )
428  {
429  for ( size_t j = 0; j < i; j++ )
430  c[j] = 0;
431  c[i]++;
432  return true;
433  }
434  }
435  return false;
436  }
437 
441  inline bool increment(const zvec& dim)
442  {
443  for ( size_t i = 0; i < size(); i++ )
444  {
445  if ( c[i] < dim[i] - 1 )
446  {
447  for ( size_t j = 0; j < i; j++ )
448  c[j] = 0;
449  c[i]++;
450  return true;
451  }
452  }
453  return false;
454  }
455 
459  inline bool increment_but(const zvec& dim, size_t hold)
460  {
461  for ( size_t i = 0; i < size(); i++ )
462  {
463  if ( i == hold )
464  continue;
465  if ( c[i] < dim[i] - 1 )
466  {
467  for ( size_t j = 0; j < i; j++ )
468  c[j] = 0;
469  c[i]++;
470  return true;
471  }
472  }
473  return false;
474  }
475 
477  inline size_t index(size_t base) const
478  {
479  size_t ret = 0;
480  size_t mul = 1;
481  for ( size_t i = 0; i < size(); i++ )
482  {
483  ret += c[i] * mul;
484  mul *= base;
485  }
486  return ret;
487  }
488 
490  inline size_t index(const zvec& dim) const
491  {
492  size_t ret = 0;
493  size_t mul = 1;
494  for ( size_t i = 0; i < size(); i++ )
495  {
496  ret += c[i] * mul;
497  mul *= dim[i];
498  }
499  return ret;
500  }
501 
503  inline void zero()
504  {
505  for ( size_t i = 0; i < size(); i++ )
506  c[i] = 0;
507  }
508 
509  friend inline zvec operator+(const zvec& l, const zvec& r)
510  {
511  zvec ret(l.size());
512  for ( size_t i = 0; i < l.size(); i++ )
513  ret[i] = l[i] + r[i];
514  return ret;
515  }
516 
517  friend inline zvec operator-(const zvec& l, const zvec& r)
518  {
519  zvec ret(l.size());
520  for ( size_t i = 0; i < l.size(); i++ )
521  ret[i] = l[i] - r[i];
522  return ret;
523  }
524 
525  friend inline zvec operator*(int f, const zvec& v)
526  {
527  zvec ret(v.size());
528  for ( size_t i = 0; i < v.size(); i++ )
529  ret[i] = f * v[i];
530  return ret;
531  }
532 
533  friend inline zvec operator*(const zvec& v, int f)
534  {
535  zvec ret(v.size());
536  for ( size_t i = 0; i < v.size(); i++ )
537  ret[i] = f * v[i];
538  return ret;
539  }
540 
541  private:
542  int c[LIBFBM_MAX_DIM];
543  size_t clen;
544  };
545 
549  class _Cache
550  {
551  public:
552  _Cache(const std::string& cacheDir, const std::string& cacheName, size_t cacheSize);
553  ~_Cache();
554 
555  bool load();
556  void store(const std::vector<double>& data);
557 
558  size_t size() const { return cacheSize; }
559 
560  bool inMemory() const { return !data.empty(); }
561 
562  private:
563  std::vector<double> data;
564  FILE *fp;
565  std::string cacheDir;
566  std::string cacheName;
567  size_t cacheSize;
568 
569  _Cache(const _Cache& copy);
570  const _Cache& operator=(const _Cache& copy);
571 
572  friend class _CacheReader;
573  };
574 
577  class _CacheReader
578  {
579  public:
580  _CacheReader(_Cache& cache, size_t bufferSize);
581 
582  inline double operator[](size_t i)
583  {
584  if ( !buf.empty() && (i < bufpos || i - bufpos >= buf.size()) )
585  load(i);
586  return data[i - bufpos];
587  }
588 
589  private:
590  _Cache& cache;
591  std::vector<double> buf;
592  size_t bufpos;
593  double *data;
594 
595  void load(size_t i);
596  };
597 
598  class FFT
599  {
600  public:
601  enum edir_t {
602  forward = 0,
603  backward = 1
604  };
605 
606  FFT();
607  ~FFT();
608 
609  void init(const libfbm::zvec& dim, double *data, edir_t direction);
610 
611  void execute();
612 
613  private:
614  void *plan;
615  };
618  class Field;
619 
631  {
632  public:
639  SGPContext(const zvec& fieldDim, const zvec& userDim, const std::string& cacheName);
640  virtual ~SGPContext();
641 
642  virtual double cov(const zvec& p) = 0;
645  inline const zvec& getDim() const { return userDim; }
647  inline const zvec& getFieldDim() const { return fieldDim; }
648 
650  void setCacheDir(const std::string& cacheDir);
651 
653  inline size_t badEigenCount() const { return bec; }
654 
660  bool initCache(bool forceRecalc = false);
661 
662  protected:
666  virtual void postProcess(Field& field, GaussianGenerator& rng);
667 
673  inline void setScaleResult(double f) { scaleResult = f; }
674 
675 
676  private:
677  zvec fieldDim, userDim;
678  _Cache *cache;
679  std::string cacheDir;
680  std::string cacheName;
681  size_t bec;
682  double scaleResult;
683 
684  friend class Field;
685 
686  SGPContext(const SGPContext&);
687  const SGPContext& operator=(const SGPContext&);
688  };
689 
695  class FGNContext : public SGPContext
696  {
697  public:
698  FGNContext(double H, const zvec& dim);
699 
700  double cov(const zvec& zvec);
701 
702  private:
703  double H;
704  };
705 
712  class FWSContext : public FGNContext
713  {
714  public:
715  FWSContext(double H, const zvec& dim) : FGNContext(H, dim) { }
716 
717  protected:
718  void postProcess(Field& field, GaussianGenerator& rng);
719  };
720 
723  {
724  public:
725  inline AbstractField() { }
726  virtual ~AbstractField();
727 
729  virtual void generate() = 0;
733  virtual void generate(GaussianGenerator& rng) = 0;
735  virtual void clear() = 0;
737  virtual const zvec& getDim() const = 0;
738 
742  inline double operator()(const zvec& p) const
743  {
744  size_t index = (size_t)2 * p[0];
745  for ( size_t i = 1; i < p.size(); i++ )
746  index += muls[i] * p[i];
747  return datap[index];
748  }
749  inline double operator()(size_t x) const
750  { return datap[2 * x]; }
751  inline double operator()(size_t x, size_t y) const
752  { return datap[2 * x + muls[1] * y]; }
753  inline double operator()(size_t x, size_t y, size_t z) const
754  { return datap[2 * x + muls[1] * y + muls[2] * z]; }
755  inline double operator()(size_t x, size_t y, size_t z, size_t u) const
756  { return datap[2 * x + muls[1] * y + muls[2] * z + muls[3] * u]; }
757  inline double operator()(size_t x, size_t y, size_t z, size_t u, size_t v) const
758  { return datap[2 * x + muls[1] * y + muls[2] * z + muls[3] * u + muls[4] * v]; }
759 
761  inline double& at(const zvec& p)
762  {
763  size_t index = 2 * p[0];
764  for ( size_t i = 1; i < p.size(); i++ )
765  index += muls[i] * p[i];
766  return datap[index];
767  }
768 
769  inline const double& at(const zvec& p) const
770  {
771  size_t index = 2 * p[0];
772  for ( size_t i = 1; i < p.size(); i++ )
773  index += muls[i] * p[i];
774  return datap[index];
775  }
776 
782  inline const size_t *getStrides() const { return muls; }
783 
784  protected:
785  std::vector<double> Z;
786  double *datap;
787  size_t muls[LIBFBM_MAX_DIM];
788 
789  private:
791  const AbstractField& operator=(const AbstractField&);
792  };
793 
799  class Field : public AbstractField
800  {
801  public:
814  Field(SGPContext& context, bool allowCorrelated = false);
815  ~Field();
816 
823  void setBufferSize(size_t bufferSize);
824 
835  void generate();
836 
837  void generate(GaussianGenerator& rng);
838 
839  void clear();
840 
844  inline double operator()(const zvec& p) const
845  {
846  size_t index = (size_t)2 * p[0];
847  for ( size_t i = 1; i < p.size(); i++ )
848  index += muls[i] * p[i];
849  return datap[index];
850  }
851  inline double operator()(size_t x) const
852  { return datap[2 * x]; }
853  inline double operator()(size_t x, size_t y) const
854  { return datap[2 * x + muls[1] * y]; }
855  inline double operator()(size_t x, size_t y, size_t z) const
856  { return datap[2 * x + muls[1] * y + muls[2] * z]; }
857  inline double operator()(size_t x, size_t y, size_t z, size_t u) const
858  { return datap[2 * x + muls[1] * y + muls[2] * z + muls[3] * u]; }
859  inline double operator()(size_t x, size_t y, size_t z, size_t u, size_t v) const
860  { return datap[2 * x + muls[1] * y + muls[2] * z + muls[3] * u + muls[4] * v]; }
861 
867  void integrate();
868 
870  inline const zvec& getDim() const { return context.getDim(); }
871 
873  inline double& at(const zvec& p)
874  {
875  size_t index = 2 * p[0];
876  for ( size_t i = 1; i < p.size(); i++ )
877  index += muls[i] * p[i];
878  return datap[index];
879  }
880 
881  inline const double& at(const zvec& p) const
882  {
883  size_t index = 2 * p[0];
884  for ( size_t i = 1; i < p.size(); i++ )
885  index += muls[i] * p[i];
886  return datap[index];
887  }
888 
894  inline const size_t *getStrides() const { return muls; }
895 
896  private:
897  FFT fft;
898  SGPContext& context;
899  bool allowCorrelated;
900  size_t bufferSize;
901  zvec psel;
902 
903  Field(const Field&);
904  const Field& operator=(const Field&);
905  };
906 
913  class SGPTester
914  {
915  public:
917  void test(SGPContext& context, size_t printInterval = 1);
918  };
919 
932  {
933  public:
950  FBMSteinContext(double H, size_t dim, size_t size, double Rhint = -1, bool mapDim = true);
951 
952  double cov(const zvec& zvec);
953 
954  protected:
955  void postProcess(Field& field, GaussianGenerator& rng);
956 
957  public:
958  void disablePostProcessing();
959 
961  double getR() const { return R; }
962 
970  static size_t userSize2FieldSize(size_t size, double R);
972  static size_t fieldSize2UserSize(size_t size, double R);
982  static double getRForH(double H, size_t dim, double Rhint = -1);
983 
984  private:
985  double H;
986  double R;
987  double beta, c0, c2;
988  double Rscale;
989  bool pp;
990  };
991 
997  {
998  public:
1005  PowerLawContext(double H, const zvec& dim, double Var = 2.0);
1006 
1007  double cov(const zvec& dim);
1008 
1009  private:
1010  double H, Var;
1011  };
1012 
1026  class PLFPSField : public AbstractField
1027  {
1028  public:
1029  PLFPSField(const zvec& dim, double H);
1030  ~PLFPSField();
1031 
1032  void generate();
1033  void generate(GaussianGenerator& rng);
1034 
1035  void clear();
1036 
1037  const zvec& getDim() const { return dim; }
1038 
1039  private:
1040  zvec dim;
1041  FFT fft;
1042  double H;
1043  std::vector<double> cache;
1044  size_t len;
1045 
1046  bool initCache();
1047  };
1048 
1050  extern SFMTGaussianGenerator gaussianRandomGenerator;
1051 };
1052 
1053 #endif // !__libfbm_hpp__
1054