<commit_before>#include <bits/stdc++.h>
using namespace std;

const int INF = 0x3f3f3f3f;

typedef long double ld;
const double EPS = 1e-9, PI = acos(-1.);

// Change long double to long long if using integers
typedef long double type;

//return -1: a < b, 0: a == b, 1: a > b
int comp(type a, type b) {
  return (a > b + EPS) - (a < b - EPS);
}

struct point {
  type x, y;

  point(type x = 0, type y = 0) : x(x), y(y) {}

  point operator -() { return point(-x, -y); }
  point operator +(point p) { return point(x+p.x, y+p.y); }
  point operator -(point p) { return point(x-p.x, y-p.y); }

  point operator *(type k) { return point(k*x, k*y); }
  point operator /(type k) { return point(x/k, y/k); }

  type operator *(point p) { return x*p.x + y*p.y; }
  type operator %(point p) { return x*p.y - y*p.x; }
  type operator !() {return (*this)*(*this); };

  bool onSegment(point a, point b) {
    if(comp((*this-a)%(b-a), 0)) return 0;
    return (comp(x, min(a.x, b.x)) >= 0 and
            comp(x, max(a.x, b.x)) <= 0 and
            comp(y, min(a.y, b.y)) >= 0 and
            comp(y, max(a.y, b.y)) <= 0);
  }
};

ostream &operator<<(ostream &os, const point &p) {
  os << "(" << p.x << ", " << p.y << ")";
  return os;
}

point rotateCCW(point p, ld t) {
  return point(p.x*cos(t)-p.y*sin(t), p.x*sin(t)+p.y*cos(t));
}

point projectPointOnLine(point p, point a, point b) {
  return a + (b-a)*((p-a)*(b-a))/((b-a)*(b-a));
}

point projectPointSegment(point p, point a, point b) {
  ld r = (b-a)*(b-a);
  if(abs(r) < EPS) return a;
  r = ((p-a)*(b-a))/r;
  if(r < 0) return a;
  if(r > 1) return b;
  return a + (b-a)*r;
}

ld distPointSegment(point p, point a, point b) {
  return sqrt(!(projectPointSegment(p, a, b) - p));
}

// compute distance between point (x,y,z) and plane ax+by+cz=d
ld distPointPlane(ld x, ld y, ld z,
                      ld a, ld b, ld c, ld d) {
  return abs(a*x+b*y+c*z-d)/sqrt(a*a+b*b+c*c);
}

bool linesCollinear(point a, point b, point c, point d) {
  return abs((a-b)%(c-d)) < EPS and
         abs((a-b)%(a-c)) < EPS;
}

bool segmentIntersect(point a, point b, point c, point d) {
  if(linesCollinear(a, b, c, d)) {
    if (!(a - c) < EPS or !(a - d) < EPS or
        !(b - c) < EPS or !(b - d) < EPS) return true;
    if ((c-a)*(c-b) > 0 && (d-a)*(d-b) > 0 && (c-b)*(d-b) > 0)
      return false;
    return true;
  }
  //overflow
  if (((d-a)%(b-a)) * ((c-a)%(b-a)) > 0) return false;
  if (((a-c)%(d-c)) * ((b-c)%(d-c)) > 0) return false;
  return true;
}

point lineIntersection(point a, point b, point c, point d) {
  b = b-a; d = c-d; c = c-a;
  return a + b*(c%d)/(b%d);
}

point circleCenter(point a, point b, point c) {
  b=(a+b)/2;
  c=(a+c)/2;
  return lineIntersection(b, b+rotateCCW(a-b, -PI/2),
                          c, c+rotateCCW(a-c, -PI/2));
}

// Sorting points in counterclockwise order.
// If the angle is the same, closer points to the origin come first.
point origin;
bool radial(point a, point b) {
  double cp = (a - origin)%(b - origin);
  return abs(cp) < EPS ? !(a - origin) < !(b - origin) : cp > 0;
}

// Graham Scan
vector<point> convex_hull(vector<point> &pts) {
  vector<point> ch(pts.size());
  point mn = pts[0];

  for(point p : pts) if (p.y < mn.y or (p.y == mn.y and p.x < p.y)) mn = p;

  origin = mn;
  sort(pts.begin(), pts.end(), radial);

  int n = 0;

  // IF: Convex hull without collinear points
  for(point p : pts) {
    while (n > 1 and (ch[n - 1] - ch[n - 2])%(p - ch[n - 2]) < EPS) n--;
    ch[n++] = p;
  }

  /* ELSE IF: Convex hull with collinear points
  for(point p : pts) {
    while (n > 1 and (ch[n - 1] - ch[n - 2])%(p - ch[n - 2]) < -EPS) n--;
    ch[n++] = p;
  }

  for(int i=pts.size()-1; i >=1; --i)
    if (pts[i] != ch[n-1] and !pts[i].dir(pts[0], ch[n-1]))
      ch[n++] = pts[i];
  // END IF */

  ch.resize(n);
  return ch;
}

//Shoe Lace
double signedArea(vector<point> &p){
  double area = 0;
  for(int i = 0; i < p.size(); i++) {
    int j = (i+1) % p.size();
    area += p[i]%p[j];
  }
  return area / 2.0;
}

// TODO: test this code. This code has not been tested, please do it before proper use.
// http://codeforces.com/problemset/problem/975/E is a good problem for testing.
point centroid(vector<point> &p) {
  point c;
  double scale = 6.0 * signedArea(p);
  for (int i = 0; i < p.size(); i++){
    int j = (i+1) % p.size();
    c = c + (p[i]+p[j])*(p[i].x*p[j].y - p[j].x*p[i].y);
  }
  return c / scale;
}

// Random on border
bool pointInPolygon(const vector<point> &p, point q) {
  bool c = 0;
  for (int i = 0; i < p.size(); i++){
    int j = (i+1)%p.size();
    if ((p[i].y <= q.y && q.y < p[j].y ||
      p[j].y <= q.y && q.y < p[i].y) &&
      q.x < p[i].x + (p[j].x - p[i].x) * (q.y - p[i].y) / (p[j].y - p[i].y))
      c = !c;
  }
  return c;
}

// compute intersection of line through points a and b with
// circle centered at c with radius r > 0
vector<point> circleLineIntersection(point a, point b, point c, double r) {
  vector<point> ret;
  b = b-a;
  a = a-c;
  double A = b*b;
  double B = a*b;
  double C = a*a - r*r;
  double D = B*B - A*C;
  if (D < -EPS) return ret;
  ret.push_back(c+a+b*(-B+sqrt(D+EPS))/A);
  if (D > EPS)
    ret.push_back(c+a+b*(-B-sqrt(D))/A);
  return ret;
}

// compute intersection of circle centered at a with radius r
// with circle centered at b with radius R
vector<point> circleCircleIntersection(point c1, point c2, double r1, double r2) {
  vector<point> ret;
  double d = sqrt(!(c1 - c2));
  if (d > r1+r2 || d+min(r1, r2) < max(r1, r2)) return ret;
  double x = (d*d-r2*r2+r1*r1)/(2*d);
  double y = sqrt(r1*r1-x*x);
  point v = (c2-c1)/d;
  ret.push_back(c1 + v*x + rotateCCW(v, PI/2)*y);
  if (y > 0)
    ret.push_back(c1 + v*x - rotateCCW(v, PI/2)*y);
  return ret;
}

// tests whether or not a given polygon (in CW or CCW order) is simple
bool isSimple(const vector<point> &p) {
  for (int i = 0; i < p.size(); i++) {
    for (int k = i+1; k < p.size(); k++) {
      int j = (i+1) % p.size();
      int l = (k+1) % p.size();
      if (i == l || j == k) continue;
      if (segmentIntersect(p[i], p[j], p[k], p[l]))
        return false;
    }
  }
  return true;
}

int main(){
  return 0;
}
<commit_msg>Update geom.cpp<commit_after>#include <bits/stdc++.h>
using namespace std;

const int INF = 0x3f3f3f3f;

typedef long double ld;
const double EPS = 1e-9, PI = acos(-1.);

// Change long double to long long if using integers
typedef long double type;

//return -1: a < b, 0: a == b, 1: a > b
int comp(type a, type b) {
  return (a > b + EPS) - (a < b - EPS);
}

struct point {
  type x, y;

  point(type x = 0, type y = 0) : x(x), y(y) {}

  point operator -() { return point(-x, -y); }
  point operator +(point p) { return point(x+p.x, y+p.y); }
  point operator -(point p) { return point(x-p.x, y-p.y); }

  point operator *(type k) { return point(k*x, k*y); }
  point operator /(type k) { return point(x/k, y/k); }

  type operator *(point p) { return x*p.x + y*p.y; }
  type operator %(point p) { return x*p.y - y*p.x; }
  type operator !() {return (*this)*(*this); };

  bool onSegment(point a, point b) {
    if(comp((*this-a)%(b-a), 0)) return 0;
    return (comp(x, min(a.x, b.x)) >= 0 and
            comp(x, max(a.x, b.x)) <= 0 and
            comp(y, min(a.y, b.y)) >= 0 and
            comp(y, max(a.y, b.y)) <= 0);
  }
};

ostream &operator<<(ostream &os, const point &p) {
  os << "(" << p.x << ", " << p.y << ")";
  return os;
}

point rotateCCW(point p, ld t) {
  return point(p.x*cos(t)-p.y*sin(t), p.x*sin(t)+p.y*cos(t));
}

point rot90CCW (point p1) { return point(-p1.y, p1.x); }
point rot90CW (point p1) { return point(p1.y, -p1.x); }

point projectPointOnLine(point p, point a, point b) {
  return a + (b-a)*((p-a)*(b-a))/((b-a)*(b-a));
}

point projectPointSegment(point p, point a, point b) {
  ld r = (b-a)*(b-a);
  if(abs(r) < EPS) return a;
  r = ((p-a)*(b-a))/r;
  if(r < 0) return a;
  if(r > 1) return b;
  return a + (b-a)*r;
}

ld distPointSegment(point p, point a, point b) {
  return sqrt(!(projectPointSegment(p, a, b) - p));
}

// compute distance between point (x,y,z) and plane ax+by+cz=d
ld distPointPlane(ld x, ld y, ld z,
                      ld a, ld b, ld c, ld d) {
  return abs(a*x+b*y+c*z-d)/sqrt(a*a+b*b+c*c);
}

bool linesCollinear(point a, point b, point c, point d) {
  return abs((a-b)%(c-d)) < EPS and
         abs((a-b)%(a-c)) < EPS;
}

bool segmentIntersect(point a, point b, point c, point d) {
  if(linesCollinear(a, b, c, d)) {
    if (!(a - c) < EPS or !(a - d) < EPS or
        !(b - c) < EPS or !(b - d) < EPS) return true;
    if ((c-a)*(c-b) > 0 && (d-a)*(d-b) > 0 && (c-b)*(d-b) > 0)
      return false;
    return true;
  }
  //overflow
  if (((d-a)%(b-a)) * ((c-a)%(b-a)) > 0) return false;
  if (((a-c)%(d-c)) * ((b-c)%(d-c)) > 0) return false;
  return true;
}

point lineIntersection(point a, point b, point c, point d) {
  b = b-a; d = c-d; c = c-a;
  return a + b*(c%d)/(b%d);
}

point circumcircle(point a, point b, point c) {
	point u = rot90CW(b-a);
  point v = rot90CW(c-a);
	point n = (c-b)/2;
  return ((a+c)/2) + (v*((u%n)/(v%u)));
}

// Sorting points in counterclockwise order.
// If the angle is the same, closer points to the origin come first.
point origin;
bool radial(point a, point b) {
  double cp = (a - origin)%(b - origin);
  return abs(cp) < EPS ? !(a - origin) < !(b - origin) : cp > 0;
}

// Graham Scan
vector<point> convex_hull(vector<point> &pts) {
  vector<point> ch(pts.size());
  point mn = pts[0];

  for(point p : pts) if (p.y < mn.y or (p.y == mn.y and p.x < p.y)) mn = p;

  origin = mn;
  sort(pts.begin(), pts.end(), radial);

  int n = 0;

  // IF: Convex hull without collinear points
  for(point p : pts) {
    while (n > 1 and (ch[n - 1] - ch[n - 2])%(p - ch[n - 2]) < EPS) n--;
    ch[n++] = p;
  }

  /* ELSE IF: Convex hull with collinear points
  for(point p : pts) {
    while (n > 1 and (ch[n - 1] - ch[n - 2])%(p - ch[n - 2]) < -EPS) n--;
    ch[n++] = p;
  }

  for(int i=pts.size()-1; i >=1; --i)
    if (pts[i] != ch[n-1] and !pts[i].dir(pts[0], ch[n-1]))
      ch[n++] = pts[i];
  // END IF */

  ch.resize(n);
  return ch;
}

//Shoe Lace
double signedArea(vector<point> &p){
  double area = 0;
  for(int i = 0; i < p.size(); i++) {
    int j = (i+1) % p.size();
    area += p[i]%p[j];
  }
  return area / 2.0;
}

// TODO: test this code. This code has not been tested, please do it before proper use.
// http://codeforces.com/problemset/problem/975/E is a good problem for testing.
point centroid(vector<point> &p) {
  point c;
  double scale = 6.0 * signedArea(p);
  for (int i = 0; i < p.size(); i++){
    int j = (i+1) % p.size();
    c = c + (p[i]+p[j])*(p[i].x*p[j].y - p[j].x*p[i].y);
  }
  return c / scale;
}

// Random on border
bool pointInPolygon(const vector<point> &p, point q) {
  bool c = 0;
  for (int i = 0; i < p.size(); i++){
    int j = (i+1)%p.size();
    if ((p[i].y <= q.y && q.y < p[j].y ||
      p[j].y <= q.y && q.y < p[i].y) &&
      q.x < p[i].x + (p[j].x - p[i].x) * (q.y - p[i].y) / (p[j].y - p[i].y))
      c = !c;
  }
  return c;
}

// compute intersection of line through points a and b with
// circle centered at c with radius r > 0
vector<point> circleLineIntersection(point a, point b, point c, double r) {
  vector<point> ret;
  b = b-a;
  a = a-c;
  double A = b*b;
  double B = a*b;
  double C = a*a - r*r;
  double D = B*B - A*C;
  if (D < -EPS) return ret;
  ret.push_back(c+a+b*(-B+sqrt(D+EPS))/A);
  if (D > EPS)
    ret.push_back(c+a+b*(-B-sqrt(D))/A);
  return ret;
}

// compute intersection of circle centered at a with radius r
// with circle centered at b with radius R
vector<point> circleCircleIntersection(point c1, point c2, double r1, double r2) {
  vector<point> ret;
  double d = sqrt(!(c1 - c2));
  if (d > r1+r2 || d+min(r1, r2) < max(r1, r2)) return ret;
  double x = (d*d-r2*r2+r1*r1)/(2*d);
  double y = sqrt(r1*r1-x*x);
  point v = (c2-c1)/d;
  ret.push_back(c1 + v*x + rotateCCW(v, PI/2)*y);
  if (y > 0)
    ret.push_back(c1 + v*x - rotateCCW(v, PI/2)*y);
  return ret;
}

// tests whether or not a given polygon (in CW or CCW order) is simple
bool isSimple(const vector<point> &p) {
  for (int i = 0; i < p.size(); i++) {
    for (int k = i+1; k < p.size(); k++) {
      int j = (i+1) % p.size();
      int l = (k+1) % p.size();
      if (i == l || j == k) continue;
      if (segmentIntersect(p[i], p[j], p[k], p[l]))
        return false;
    }
  }
  return true;
}

int main(){
  return 0;
}
<|endoftext|>


<commit_before>/**************************************************************************
    copyright            : (C) 2007 by Lukáš Lalinský
    email                : lalinsky@gmail.com
 **************************************************************************/

/***************************************************************************
 *   This library is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Lesser General Public License version   *
 *   2.1 as published by the Free Software Foundation.                     *
 *                                                                         *
 *   This library is distributed in the hope that it will be useful, but   *
 *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
 *   Lesser General Public License for more details.                       *
 *                                                                         *
 *   You should have received a copy of the GNU Lesser General Public      *
 *   License along with this library; if not, write to the Free Software   *
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA         *
 *   02110-1301  USA                                                       *
 *                                                                         *
 *   Alternatively, this file is available under the Mozilla Public        *
 *   License Version 1.1.  You may obtain a copy of the License at         *
 *   http://www.mozilla.org/MPL/                                           *
 ***************************************************************************/

#include <tdebug.h>
#include <tstring.h>
#include "mp4file.h"
#include "mp4atom.h"
#include "mp4properties.h"

using namespace TagLib;

class MP4::Properties::PropertiesPrivate
{
public:
  PropertiesPrivate() :
    length(0),
    bitrate(0),
    sampleRate(0),
    channels(0),
    bitsPerSample(0),
    encrypted(false),
    codec(MP4::Properties::Unknown) {}

  int length;
  int bitrate;
  int sampleRate;
  int channels;
  int bitsPerSample;
  bool encrypted;
  Codec codec;
};

////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////

MP4::Properties::Properties(File *file, MP4::Atoms *atoms, ReadStyle style) :
  AudioProperties(style),
  d(new PropertiesPrivate())
{
  read(file, atoms);
}

MP4::Properties::~Properties()
{
  delete d;
}

int
MP4::Properties::channels() const
{
  return d->channels;
}

int
MP4::Properties::sampleRate() const
{
  return d->sampleRate;
}

int
MP4::Properties::length() const
{
  return lengthInSeconds();
}

int
MP4::Properties::lengthInSeconds() const
{
  return d->length / 1000;
}

int
MP4::Properties::lengthInMilliseconds() const
{
  return d->length;
}

int
MP4::Properties::bitrate() const
{
  return d->bitrate;
}

int
MP4::Properties::bitsPerSample() const
{
  return d->bitsPerSample;
}

bool
MP4::Properties::isEncrypted() const
{
  return d->encrypted;
}

MP4::Properties::Codec
MP4::Properties::codec() const
{
  return d->codec;
}

////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////

void
MP4::Properties::read(File *file, Atoms *atoms)
{
  MP4::Atom *moov = atoms->find("moov");
  if(!moov) {
    debug("MP4: Atom 'moov' not found");
    return;
  }

  MP4::Atom *trak = 0;
  ByteVector data;

  const MP4::AtomList trakList = moov->findall("trak");
  for(MP4::AtomList::ConstIterator it = trakList.begin(); it != trakList.end(); ++it) {
    trak = *it;
    MP4::Atom *hdlr = trak->find("mdia", "hdlr");
    if(!hdlr) {
      debug("MP4: Atom 'trak.mdia.hdlr' not found");
      return;
    }
    file->seek(hdlr->offset);
    data = file->readBlock(hdlr->length);
    if(data.containsAt("soun", 16)) {
      break;
    }
    trak = 0;
  }
  if(!trak) {
    debug("MP4: No audio tracks");
    return;
  }

  MP4::Atom *mdhd = trak->find("mdia", "mdhd");
  if(!mdhd) {
    debug("MP4: Atom 'trak.mdia.mdhd' not found");
    return;
  }

  file->seek(mdhd->offset);
  data = file->readBlock(mdhd->length);

  const unsigned int version = data[8];
  long long unit;
  long long length;
  if(version == 1) {
    if(data.size() < 36 + 8) {
      debug("MP4: Atom 'trak.mdia.mdhd' is smaller than expected");
      return;
    }
    unit   = data.toUInt(28U);
    length = data.toLongLong(32U);
  }
  else {
    if(data.size() < 24 + 8) {
      debug("MP4: Atom 'trak.mdia.mdhd' is smaller than expected");
      return;
    }
    unit   = data.toUInt(20U);
    length = data.toUInt(24U);
  }
  if(unit > 0 && length > 0)
    d->length = static_cast<int>(length * 1000.0 / unit + 0.5);

  MP4::Atom *atom = trak->find("mdia", "minf", "stbl", "stsd");
  if(!atom) {
    return;
  }

  file->seek(atom->offset);
  data = file->readBlock(atom->length);
  if(data.containsAt("mp4a", 20)) {
    d->codec         = AAC;
    d->channels      = data.toShort(40U);
    d->bitsPerSample = data.toShort(42U);
    d->sampleRate    = data.toUInt(46U);
    if(data.containsAt("esds", 56) && data[64] == 0x03) {
      unsigned int pos = 65;
      if(data.containsAt("\x80\x80\x80", pos)) {
        pos += 3;
      }
      pos += 4;
      if(data[pos] == 0x04) {
        pos += 1;
        if(data.containsAt("\x80\x80\x80", pos)) {
          pos += 3;
        }
        pos += 10;
        d->bitrate = static_cast<int>((data.toUInt(pos) + 500) / 1000.0 + 0.5);
      }
    }
  }
  else if(data.containsAt("alac", 20)) {
    if(atom->length == 88 && data.containsAt("alac", 56)) {
      d->codec         = ALAC;
      d->bitsPerSample = data.at(69);
      d->channels      = data.at(73);
      d->bitrate       = static_cast<int>(data.toUInt(80U) / 1000.0 + 0.5);
      d->sampleRate    = data.toUInt(84U);
    }
  }

  MP4::Atom *drms = atom->find("drms");
  if(drms) {
    d->encrypted = true;
  }
}
<commit_msg>Calculate bitrate for ALAC files without it (#961)<commit_after>/**************************************************************************
    copyright            : (C) 2007 by Lukáš Lalinský
    email                : lalinsky@gmail.com
 **************************************************************************/

/***************************************************************************
 *   This library is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Lesser General Public License version   *
 *   2.1 as published by the Free Software Foundation.                     *
 *                                                                         *
 *   This library is distributed in the hope that it will be useful, but   *
 *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
 *   Lesser General Public License for more details.                       *
 *                                                                         *
 *   You should have received a copy of the GNU Lesser General Public      *
 *   License along with this library; if not, write to the Free Software   *
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA         *
 *   02110-1301  USA                                                       *
 *                                                                         *
 *   Alternatively, this file is available under the Mozilla Public        *
 *   License Version 1.1.  You may obtain a copy of the License at         *
 *   http://www.mozilla.org/MPL/                                           *
 ***************************************************************************/

#include <tdebug.h>
#include <tstring.h>
#include "mp4file.h"
#include "mp4atom.h"
#include "mp4properties.h"

using namespace TagLib;

namespace
{
  // Calculate the total bytes used by audio data, used to calculate the bitrate
  long long calculateMdatLength(const MP4::AtomList &list)
  {
    long long totalLength = 0;
    for(MP4::AtomList::ConstIterator it = list.begin(); it != list.end(); ++it) {
      long length = (*it)->length;
      if(length == 0)
        return 0; // for safety, see checkValid() in mp4file.cpp

      if((*it)->name == "mdat")
        totalLength += length;

      totalLength += calculateMdatLength((*it)->children);
    }

    return totalLength;
  }
}

class MP4::Properties::PropertiesPrivate
{
public:
  PropertiesPrivate() :
    length(0),
    bitrate(0),
    sampleRate(0),
    channels(0),
    bitsPerSample(0),
    encrypted(false),
    codec(MP4::Properties::Unknown) {}

  int length;
  int bitrate;
  int sampleRate;
  int channels;
  int bitsPerSample;
  bool encrypted;
  Codec codec;
};

////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////

MP4::Properties::Properties(File *file, MP4::Atoms *atoms, ReadStyle style) :
  AudioProperties(style),
  d(new PropertiesPrivate())
{
  read(file, atoms);
}

MP4::Properties::~Properties()
{
  delete d;
}

int
MP4::Properties::channels() const
{
  return d->channels;
}

int
MP4::Properties::sampleRate() const
{
  return d->sampleRate;
}

int
MP4::Properties::length() const
{
  return lengthInSeconds();
}

int
MP4::Properties::lengthInSeconds() const
{
  return d->length / 1000;
}

int
MP4::Properties::lengthInMilliseconds() const
{
  return d->length;
}

int
MP4::Properties::bitrate() const
{
  return d->bitrate;
}

int
MP4::Properties::bitsPerSample() const
{
  return d->bitsPerSample;
}

bool
MP4::Properties::isEncrypted() const
{
  return d->encrypted;
}

MP4::Properties::Codec
MP4::Properties::codec() const
{
  return d->codec;
}

////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////

void
MP4::Properties::read(File *file, Atoms *atoms)
{
  MP4::Atom *moov = atoms->find("moov");
  if(!moov) {
    debug("MP4: Atom 'moov' not found");
    return;
  }

  MP4::Atom *trak = 0;
  ByteVector data;

  const MP4::AtomList trakList = moov->findall("trak");
  for(MP4::AtomList::ConstIterator it = trakList.begin(); it != trakList.end(); ++it) {
    trak = *it;
    MP4::Atom *hdlr = trak->find("mdia", "hdlr");
    if(!hdlr) {
      debug("MP4: Atom 'trak.mdia.hdlr' not found");
      return;
    }
    file->seek(hdlr->offset);
    data = file->readBlock(hdlr->length);
    if(data.containsAt("soun", 16)) {
      break;
    }
    trak = 0;
  }
  if(!trak) {
    debug("MP4: No audio tracks");
    return;
  }

  MP4::Atom *mdhd = trak->find("mdia", "mdhd");
  if(!mdhd) {
    debug("MP4: Atom 'trak.mdia.mdhd' not found");
    return;
  }

  file->seek(mdhd->offset);
  data = file->readBlock(mdhd->length);

  const unsigned int version = data[8];
  long long unit;
  long long length;
  if(version == 1) {
    if(data.size() < 36 + 8) {
      debug("MP4: Atom 'trak.mdia.mdhd' is smaller than expected");
      return;
    }
    unit   = data.toUInt(28U);
    length = data.toLongLong(32U);
  }
  else {
    if(data.size() < 24 + 8) {
      debug("MP4: Atom 'trak.mdia.mdhd' is smaller than expected");
      return;
    }
    unit   = data.toUInt(20U);
    length = data.toUInt(24U);
  }
  if(unit > 0 && length > 0)
    d->length = static_cast<int>(length * 1000.0 / unit + 0.5);

  MP4::Atom *atom = trak->find("mdia", "minf", "stbl", "stsd");
  if(!atom) {
    return;
  }

  file->seek(atom->offset);
  data = file->readBlock(atom->length);
  if(data.containsAt("mp4a", 20)) {
    d->codec         = AAC;
    d->channels      = data.toShort(40U);
    d->bitsPerSample = data.toShort(42U);
    d->sampleRate    = data.toUInt(46U);
    if(data.containsAt("esds", 56) && data[64] == 0x03) {
      unsigned int pos = 65;
      if(data.containsAt("\x80\x80\x80", pos)) {
        pos += 3;
      }
      pos += 4;
      if(data[pos] == 0x04) {
        pos += 1;
        if(data.containsAt("\x80\x80\x80", pos)) {
          pos += 3;
        }
        pos += 10;
        d->bitrate = static_cast<int>((data.toUInt(pos) + 500) / 1000.0 + 0.5);
      }
    }
  }
  else if(data.containsAt("alac", 20)) {
    if(atom->length == 88 && data.containsAt("alac", 56)) {
      d->codec         = ALAC;
      d->bitsPerSample = data.at(69);
      d->channels      = data.at(73);
      d->bitrate       = static_cast<int>(data.toUInt(80U) / 1000.0 + 0.5);
      d->sampleRate    = data.toUInt(84U);

      if(d->bitrate == 0 && d->length > 0) {
        // There are files which do not contain a nominal bitrate, e.g. those
        // generated by refalac64.exe. Calculate the bitrate from the audio
        // data size (mdat atoms) and the duration.
        d->bitrate = (calculateMdatLength(atoms->atoms) * 8) / d->length;
      }
    }
  }

  MP4::Atom *drms = atom->find("drms");
  if(drms) {
    d->encrypted = true;
  }
}
<|endoftext|>


<commit_before>/***************************************************************************
    copyright            : (C) 2004 by Allan Sandfeld Jensen
    email                : kde@carewolf.org
 ***************************************************************************/

/***************************************************************************
 *   This library is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Lesser General Public License version   *
 *   2.1 as published by the Free Software Foundation.                     *
 *                                                                         *
 *   This library is distributed in the hope that it will be useful, but   *
 *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
 *   Lesser General Public License for more details.                       *
 *                                                                         *
 *   You should have received a copy of the GNU Lesser General Public      *
 *   License along with this library; if not, write to the Free Software   *
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA         *
 *   02110-1301  USA                                                       *
 *                                                                         *
 *   Alternatively, this file is available under the Mozilla Public        *
 *   License Version 1.1.  You may obtain a copy of the License at         *
 *   http://www.mozilla.org/MPL/                                           *
 ***************************************************************************/

#include <tstring.h>
#include <tdebug.h>
#include <bitset>
#include <math.h>

#include "mpcproperties.h"
#include "mpcfile.h"

using namespace TagLib;

class MPC::Properties::PropertiesPrivate
{
public:
  PropertiesPrivate() :
    version(0),
    length(0),
    bitrate(0),
    sampleRate(0),
    channels(0),
    totalFrames(0),
    sampleFrames(0),
    trackGain(0),
    trackPeak(0),
    albumGain(0),
    albumPeak(0) {}

  int          version;
  int          length;
  int          bitrate;
  int          sampleRate;
  int          channels;
  unsigned int totalFrames;
  unsigned int sampleFrames;
  unsigned int trackGain;
  unsigned int trackPeak;
  unsigned int albumGain;
  unsigned int albumPeak;
  String       flags;
};

////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////

MPC::Properties::Properties(const ByteVector &data, long streamLength, ReadStyle style) :
  AudioProperties(style),
  d(new PropertiesPrivate())
{
  readSV7(data, streamLength);
}

MPC::Properties::Properties(File *file, long streamLength, ReadStyle style) :
  AudioProperties(style),
  d(new PropertiesPrivate())
{
  ByteVector magic = file->readBlock(4);
  if(magic == "MPCK") {
    // Musepack version 8
    readSV8(file, streamLength);
  }
  else {
    // Musepack version 7 or older, fixed size header
    readSV7(magic + file->readBlock(MPC::HeaderSize - 4), streamLength);
  }
}

MPC::Properties::~Properties()
{
  delete d;
}

int MPC::Properties::length() const
{
  return lengthInSeconds();
}

int MPC::Properties::lengthInSeconds() const
{
  return d->length / 1000;
}

int MPC::Properties::lengthInMilliseconds() const
{
  return d->length;
}

int MPC::Properties::bitrate() const
{
  return d->bitrate;
}

int MPC::Properties::sampleRate() const
{
  return d->sampleRate;
}

int MPC::Properties::channels() const
{
  return d->channels;
}

int MPC::Properties::mpcVersion() const
{
  return d->version;
}

unsigned int MPC::Properties::totalFrames() const
{
  return d->totalFrames;
}

unsigned int MPC::Properties::sampleFrames() const
{
  return d->sampleFrames;
}

int MPC::Properties::trackGain() const
{
  return d->trackGain;
}

int MPC::Properties::trackPeak() const
{
  return d->trackPeak;
}

int MPC::Properties::albumGain() const
{
  return d->albumGain;
}

int MPC::Properties::albumPeak() const
{
  return d->albumPeak;
}

////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////

namespace
{
  unsigned long readSize(File *file, unsigned int &sizeLength, bool &eof)
  {
    sizeLength = 0;
    eof = false;

    unsigned char tmp;
    unsigned long size = 0;

    do {
      const ByteVector b = file->readBlock(1);
      if(b.isEmpty()) {
        eof = true;
        break;
      }

      tmp = b[0];
      size = (size << 7) | (tmp & 0x7F);
      sizeLength++;
    } while((tmp & 0x80));
    return size;
  }

  unsigned long readSize(const ByteVector &data, unsigned int &pos)
  {
    unsigned char tmp;
    unsigned long size = 0;

    do {
      tmp = data[pos++];
      size = (size << 7) | (tmp & 0x7F);
    } while((tmp & 0x80) && (pos < data.size()));
    return size;
  }

  // This array looks weird, but the same as original MusePack code found at:
  // https://www.musepack.net/index.php?pg=src
  const unsigned short sftable [8] = { 44100, 48000, 37800, 32000, 0, 0, 0, 0 };
}

void MPC::Properties::readSV8(File *file, long streamLength)
{
  bool readSH = false, readRG = false;

  while(!readSH && !readRG) {
    const ByteVector packetType = file->readBlock(2);

    unsigned int packetSizeLength;
    bool eof;
    const unsigned long packetSize = readSize(file, packetSizeLength, eof);
    if(eof) {
      debug("MPC::Properties::readSV8() - Reached to EOF.");
      break;
    }

    const unsigned long dataSize = packetSize - 2 - packetSizeLength;

    const ByteVector data = file->readBlock(dataSize);
    if(data.size() != dataSize) {
      debug("MPC::Properties::readSV8() - dataSize doesn't match the actual data size.");
      break;
    }

    if(packetType == "SH") {
      // Stream Header
      // http://trac.musepack.net/wiki/SV8Specification#StreamHeaderPacket

      if(dataSize <= 5) {
        debug("MPC::Properties::readSV8() - \"SH\" packet is too short to parse.");
        break;
      }

      readSH = true;

      unsigned int pos = 4;
      d->version = data[pos];
      pos += 1;
      d->sampleFrames = readSize(data, pos);
      if(pos > dataSize - 3) {
        debug("MPC::Properties::readSV8() - \"SH\" packet is corrupt.");
        break;
      }

      const unsigned long begSilence = readSize(data, pos);
      if(pos > dataSize - 2) {
        debug("MPC::Properties::readSV8() - \"SH\" packet is corrupt.");
        break;
      }

      const unsigned short flags = data.toUShort(pos, true);
      pos += 2;

      d->sampleRate = sftable[(flags >> 13) & 0x07];
      d->channels   = ((flags >> 4) & 0x0F) + 1;

      const unsigned int frameCount = d->sampleFrames - begSilence;
      if(frameCount > 0 && d->sampleRate > 0) {
        const double length = frameCount * 1000.0 / d->sampleRate;
        d->length  = static_cast<int>(length + 0.5);
        d->bitrate = static_cast<int>(streamLength * 8.0 / length + 0.5);
      }
    }
    else if (packetType == "RG") {
      // Replay Gain
      // http://trac.musepack.net/wiki/SV8Specification#ReplaygainPacket

      if(dataSize <= 9) {
        debug("MPC::Properties::readSV8() - \"RG\" packet is too short to parse.");
        break;
      }

      readRG = true;

      const int replayGainVersion = data[0];
      if(replayGainVersion == 1) {
        d->trackGain = data.toShort(1, true);
        d->trackPeak = data.toShort(3, true);
        d->albumGain = data.toShort(5, true);
        d->albumPeak = data.toShort(7, true);
      }
    }

    else if(packetType == "SE") {
      break;
    }

    else {
      file->seek(dataSize, File::Current);
    }
  }
}

void MPC::Properties::readSV7(const ByteVector &data, long streamLength)
{
  if(data.startsWith("MP+")) {
    d->version = data[3] & 15;
    if(d->version < 7)
      return;

    d->totalFrames = data.toUInt(4, false);

    const unsigned int flags = data.toUInt(8, false);
    d->sampleRate = sftable[(flags >> 16) & 0x03];
    d->channels   = 2;

    const unsigned int gapless = data.toUInt(5, false);

    d->trackGain = data.toShort(14, false);
    d->trackPeak = data.toShort(12, false);
    d->albumGain = data.toShort(18, false);
    d->albumPeak = data.toShort(16, false);

    // convert gain info
    if(d->trackGain != 0) {
      int tmp = (int)((64.82 - (short)d->trackGain / 100.) * 256. + .5);
      if(tmp >= (1 << 16) || tmp < 0) tmp = 0;
      d->trackGain = tmp;
    }

    if(d->albumGain != 0) {
      int tmp = (int)((64.82 - d->albumGain / 100.) * 256. + .5);
      if(tmp >= (1 << 16) || tmp < 0) tmp = 0;
      d->albumGain = tmp;
    }

    if (d->trackPeak != 0)
      d->trackPeak = (int)(log10((double)d->trackPeak) * 20 * 256 + .5);

    if (d->albumPeak != 0)
      d->albumPeak = (int)(log10((double)d->albumPeak) * 20 * 256 + .5);

    bool trueGapless = (gapless >> 31) & 0x0001;
    if(trueGapless) {
      unsigned int lastFrameSamples = (gapless >> 20) & 0x07FF;
      d->sampleFrames = d->totalFrames * 1152 - lastFrameSamples;
    }
    else
      d->sampleFrames = d->totalFrames * 1152 - 576;
  }
  else {
    const unsigned int headerData = data.toUInt(0, false);

    d->bitrate    = (headerData >> 23) & 0x01ff;
    d->version    = (headerData >> 11) & 0x03ff;
    d->sampleRate = 44100;
    d->channels   = 2;

    if(d->version >= 5)
      d->totalFrames = data.toUInt(4, false);
    else
      d->totalFrames = data.toUShort(6, false);

    d->sampleFrames = d->totalFrames * 1152 - 576;
  }

  if(d->sampleFrames > 0 && d->sampleRate > 0) {
    const double length = d->sampleFrames * 1000.0 / d->sampleRate;
    d->length = static_cast<int>(length + 0.5);

    if(d->bitrate == 0)
      d->bitrate = static_cast<int>(streamLength * 8.0 / length + 0.5);
  }
}
<commit_msg>Unsaved (and incorrect looking) field<commit_after>/***************************************************************************
    copyright            : (C) 2004 by Allan Sandfeld Jensen
    email                : kde@carewolf.org
 ***************************************************************************/

/***************************************************************************
 *   This library is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Lesser General Public License version   *
 *   2.1 as published by the Free Software Foundation.                     *
 *                                                                         *
 *   This library is distributed in the hope that it will be useful, but   *
 *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
 *   Lesser General Public License for more details.                       *
 *                                                                         *
 *   You should have received a copy of the GNU Lesser General Public      *
 *   License along with this library; if not, write to the Free Software   *
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA         *
 *   02110-1301  USA                                                       *
 *                                                                         *
 *   Alternatively, this file is available under the Mozilla Public        *
 *   License Version 1.1.  You may obtain a copy of the License at         *
 *   http://www.mozilla.org/MPL/                                           *
 ***************************************************************************/

#include <tstring.h>
#include <tdebug.h>
#include <bitset>
#include <math.h>

#include "mpcproperties.h"
#include "mpcfile.h"

using namespace TagLib;

class MPC::Properties::PropertiesPrivate
{
public:
  PropertiesPrivate() :
    version(0),
    length(0),
    bitrate(0),
    sampleRate(0),
    channels(0),
    totalFrames(0),
    sampleFrames(0),
    trackGain(0),
    trackPeak(0),
    albumGain(0),
    albumPeak(0) {}

  int          version;
  int          length;
  int          bitrate;
  int          sampleRate;
  int          channels;
  unsigned int totalFrames;
  unsigned int sampleFrames;
  unsigned int trackGain;
  unsigned int trackPeak;
  unsigned int albumGain;
  unsigned int albumPeak;
};

////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////

MPC::Properties::Properties(const ByteVector &data, long streamLength, ReadStyle style) :
  AudioProperties(style),
  d(new PropertiesPrivate())
{
  readSV7(data, streamLength);
}

MPC::Properties::Properties(File *file, long streamLength, ReadStyle style) :
  AudioProperties(style),
  d(new PropertiesPrivate())
{
  ByteVector magic = file->readBlock(4);
  if(magic == "MPCK") {
    // Musepack version 8
    readSV8(file, streamLength);
  }
  else {
    // Musepack version 7 or older, fixed size header
    readSV7(magic + file->readBlock(MPC::HeaderSize - 4), streamLength);
  }
}

MPC::Properties::~Properties()
{
  delete d;
}

int MPC::Properties::length() const
{
  return lengthInSeconds();
}

int MPC::Properties::lengthInSeconds() const
{
  return d->length / 1000;
}

int MPC::Properties::lengthInMilliseconds() const
{
  return d->length;
}

int MPC::Properties::bitrate() const
{
  return d->bitrate;
}

int MPC::Properties::sampleRate() const
{
  return d->sampleRate;
}

int MPC::Properties::channels() const
{
  return d->channels;
}

int MPC::Properties::mpcVersion() const
{
  return d->version;
}

unsigned int MPC::Properties::totalFrames() const
{
  return d->totalFrames;
}

unsigned int MPC::Properties::sampleFrames() const
{
  return d->sampleFrames;
}

int MPC::Properties::trackGain() const
{
  return d->trackGain;
}

int MPC::Properties::trackPeak() const
{
  return d->trackPeak;
}

int MPC::Properties::albumGain() const
{
  return d->albumGain;
}

int MPC::Properties::albumPeak() const
{
  return d->albumPeak;
}

////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////

namespace
{
  unsigned long readSize(File *file, unsigned int &sizeLength, bool &eof)
  {
    sizeLength = 0;
    eof = false;

    unsigned char tmp;
    unsigned long size = 0;

    do {
      const ByteVector b = file->readBlock(1);
      if(b.isEmpty()) {
        eof = true;
        break;
      }

      tmp = b[0];
      size = (size << 7) | (tmp & 0x7F);
      sizeLength++;
    } while((tmp & 0x80));
    return size;
  }

  unsigned long readSize(const ByteVector &data, unsigned int &pos)
  {
    unsigned char tmp;
    unsigned long size = 0;

    do {
      tmp = data[pos++];
      size = (size << 7) | (tmp & 0x7F);
    } while((tmp & 0x80) && (pos < data.size()));
    return size;
  }

  // This array looks weird, but the same as original MusePack code found at:
  // https://www.musepack.net/index.php?pg=src
  const unsigned short sftable [8] = { 44100, 48000, 37800, 32000, 0, 0, 0, 0 };
}

void MPC::Properties::readSV8(File *file, long streamLength)
{
  bool readSH = false, readRG = false;

  while(!readSH && !readRG) {
    const ByteVector packetType = file->readBlock(2);

    unsigned int packetSizeLength;
    bool eof;
    const unsigned long packetSize = readSize(file, packetSizeLength, eof);
    if(eof) {
      debug("MPC::Properties::readSV8() - Reached to EOF.");
      break;
    }

    const unsigned long dataSize = packetSize - 2 - packetSizeLength;

    const ByteVector data = file->readBlock(dataSize);
    if(data.size() != dataSize) {
      debug("MPC::Properties::readSV8() - dataSize doesn't match the actual data size.");
      break;
    }

    if(packetType == "SH") {
      // Stream Header
      // http://trac.musepack.net/wiki/SV8Specification#StreamHeaderPacket

      if(dataSize <= 5) {
        debug("MPC::Properties::readSV8() - \"SH\" packet is too short to parse.");
        break;
      }

      readSH = true;

      unsigned int pos = 4;
      d->version = data[pos];
      pos += 1;
      d->sampleFrames = readSize(data, pos);
      if(pos > dataSize - 3) {
        debug("MPC::Properties::readSV8() - \"SH\" packet is corrupt.");
        break;
      }

      const unsigned long begSilence = readSize(data, pos);
      if(pos > dataSize - 2) {
        debug("MPC::Properties::readSV8() - \"SH\" packet is corrupt.");
        break;
      }

      const unsigned short flags = data.toUShort(pos, true);
      pos += 2;

      d->sampleRate = sftable[(flags >> 13) & 0x07];
      d->channels   = ((flags >> 4) & 0x0F) + 1;

      const unsigned int frameCount = d->sampleFrames - begSilence;
      if(frameCount > 0 && d->sampleRate > 0) {
        const double length = frameCount * 1000.0 / d->sampleRate;
        d->length  = static_cast<int>(length + 0.5);
        d->bitrate = static_cast<int>(streamLength * 8.0 / length + 0.5);
      }
    }
    else if (packetType == "RG") {
      // Replay Gain
      // http://trac.musepack.net/wiki/SV8Specification#ReplaygainPacket

      if(dataSize <= 9) {
        debug("MPC::Properties::readSV8() - \"RG\" packet is too short to parse.");
        break;
      }

      readRG = true;

      const int replayGainVersion = data[0];
      if(replayGainVersion == 1) {
        d->trackGain = data.toShort(1, true);
        d->trackPeak = data.toShort(3, true);
        d->albumGain = data.toShort(5, true);
        d->albumPeak = data.toShort(7, true);
      }
    }

    else if(packetType == "SE") {
      break;
    }

    else {
      file->seek(dataSize, File::Current);
    }
  }
}

void MPC::Properties::readSV7(const ByteVector &data, long streamLength)
{
  if(data.startsWith("MP+")) {
    d->version = data[3] & 15;
    if(d->version < 7)
      return;

    d->totalFrames = data.toUInt(4, false);

    const unsigned int flags = data.toUInt(8, false);
    d->sampleRate = sftable[(flags >> 16) & 0x03];
    d->channels   = 2;

    const unsigned int gapless = data.toUInt(5, false);

    d->trackGain = data.toShort(14, false);
    d->trackPeak = data.toShort(12, false);
    d->albumGain = data.toShort(18, false);
    d->albumPeak = data.toShort(16, false);

    // convert gain info
    if(d->trackGain != 0) {
      int tmp = (int)((64.82 - (short)d->trackGain / 100.) * 256. + .5);
      if(tmp >= (1 << 16) || tmp < 0) tmp = 0;
      d->trackGain = tmp;
    }

    if(d->albumGain != 0) {
      int tmp = (int)((64.82 - d->albumGain / 100.) * 256. + .5);
      if(tmp >= (1 << 16) || tmp < 0) tmp = 0;
      d->albumGain = tmp;
    }

    if (d->trackPeak != 0)
      d->trackPeak = (int)(log10((double)d->trackPeak) * 20 * 256 + .5);

    if (d->albumPeak != 0)
      d->albumPeak = (int)(log10((double)d->albumPeak) * 20 * 256 + .5);

    bool trueGapless = (gapless >> 31) & 0x0001;
    if(trueGapless) {
      unsigned int lastFrameSamples = (gapless >> 20) & 0x07FF;
      d->sampleFrames = d->totalFrames * 1152 - lastFrameSamples;
    }
    else
      d->sampleFrames = d->totalFrames * 1152 - 576;
  }
  else {
    const unsigned int headerData = data.toUInt(0, false);

    d->bitrate    = (headerData >> 23) & 0x01ff;
    d->version    = (headerData >> 11) & 0x03ff;
    d->sampleRate = 44100;
    d->channels   = 2;

    if(d->version >= 5)
      d->totalFrames = data.toUInt(4, false);
    else
      d->totalFrames = data.toUShort(6, false);

    d->sampleFrames = d->totalFrames * 1152 - 576;
  }

  if(d->sampleFrames > 0 && d->sampleRate > 0) {
    const double length = d->sampleFrames * 1000.0 / d->sampleRate;
    d->length = static_cast<int>(length + 0.5);

    if(d->bitrate == 0)
      d->bitrate = static_cast<int>(streamLength * 8.0 / length + 0.5);
  }
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: BCatalog.cxx,v $
 *
 *  $Revision: 1.15 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 02:05:11 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_connectivity.hxx"

#ifndef _CONNECTIVITY_ADABAS_CATALOG_HXX_
#include "adabas/BCatalog.hxx"
#endif
#ifndef _CONNECTIVITY_ADABAS_BCONNECTION_HXX_
#include "adabas/BConnection.hxx"
#endif
#ifndef _CONNECTIVITY_ADABAS_GROUPS_HXX_
#include "adabas/BGroups.hxx"
#endif
#ifndef _CONNECTIVITY_ADABAS_USERS_HXX_
#include "adabas/BUsers.hxx"
#endif
#ifndef _CONNECTIVITY_ADABAS_TABLES_HXX_
#include "adabas/BTables.hxx"
#endif
#ifndef _CONNECTIVITY_ADABAS_VIEWS_HXX_
#include "adabas/BViews.hxx"
#endif
#ifndef _COM_SUN_STAR_SDBC_XROW_HPP_
#include <com/sun/star/sdbc/XRow.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBC_XRESULTSET_HPP_
#include <com/sun/star/sdbc/XResultSet.hpp>
#endif
#ifndef _COMPHELPER_TYPES_HXX_
#include <comphelper/types.hxx>
#endif

// -------------------------------------------------------------------------
using namespace connectivity;
using namespace connectivity::adabas;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::sdbcx;
using namespace ::com::sun::star::sdbc;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::lang;
// -----------------------------------------------------------------------------
OAdabasCatalog::OAdabasCatalog(SQLHANDLE _aConnectionHdl, OAdabasConnection* _pCon) : connectivity::sdbcx::OCatalog(_pCon)
                ,m_pConnection(_pCon)
                ,m_aConnectionHdl(_aConnectionHdl)
{
}
// -----------------------------------------------------------------------------
::rtl::OUString OAdabasCatalog::buildName(const Reference< XRow >& _xRow)
{
    ::rtl::OUString sName;
    sName = _xRow->getString(2);
    if ( sName.getLength() )
        sName += OAdabasCatalog::getDot();
    sName += _xRow->getString(3);

    return sName;
}
// -----------------------------------------------------------------------------
void OAdabasCatalog::fillVector(const ::rtl::OUString& _sQuery,TStringVector& _rVector)
{
    Reference< XStatement > xStmt = m_pConnection->createStatement(  );
    OSL_ENSURE(xStmt.is(),"OAdabasCatalog::fillVector: Could not create a statement!");
    Reference< XResultSet > xResult = xStmt->executeQuery(_sQuery);

    fillNames(xResult,_rVector);
    ::comphelper::disposeComponent(xStmt);

}
// -------------------------------------------------------------------------
void OAdabasCatalog::refreshTables()
{
    TStringVector aVector;
    {
        Sequence< ::rtl::OUString > aTypes(1);
        aTypes[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("%"));
        Reference< XResultSet > xResult = m_xMetaData->getTables(Any(),
                                                                ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("%")),
                                                                ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("%")),
                                                                aTypes);
        fillNames(xResult,aVector);
    }

    if(m_pTables)
        m_pTables->reFill(aVector);
    else
        m_pTables = new OTables(m_xMetaData,*this,m_aMutex,aVector);
}
// -------------------------------------------------------------------------
void OAdabasCatalog::refreshViews()
{
    TStringVector aVector;
    static const ::rtl::OUString s_sView(RTL_CONSTASCII_USTRINGPARAM("SELECT DISTINCT NULL,DOMAIN.VIEWDEFS.OWNER, DOMAIN.VIEWDEFS.VIEWNAME FROM DOMAIN.VIEWDEFS"));
    fillVector(s_sView,aVector);

    if(m_pViews)
        m_pViews->reFill(aVector);
    else
        m_pViews = new OViews(m_xMetaData,*this,m_aMutex,aVector);
}
// -------------------------------------------------------------------------
void OAdabasCatalog::refreshGroups()
{
    TStringVector aVector;
    static const ::rtl::OUString s_sGroup(RTL_CONSTASCII_USTRINGPARAM("SELECT DISTINCT NULL,NULL,GROUPNAME FROM DOMAIN.USERS WHERE GROUPNAME IS NOT NULL AND GROUPNAME <> ' '"));
    fillVector(s_sGroup,aVector);
    if(m_pGroups)
        m_pGroups->reFill(aVector);
    else
        m_pGroups = new OGroups(*this,m_aMutex,aVector,m_pConnection,this);
}
// -------------------------------------------------------------------------
void OAdabasCatalog::refreshUsers()
{
    TStringVector aVector;
    static const ::rtl::OUString s_sUsers(RTL_CONSTASCII_USTRINGPARAM("SELECT DISTINCT NULL,NULL,USERNAME FROM DOMAIN.USERS WHERE USERNAME IS NOT NULL AND USERNAME <> ' ' AND USERNAME <> 'CONTROL'"));
    fillVector(s_sUsers,aVector);

    if(m_pUsers)
        m_pUsers->reFill(aVector);
    else
        m_pUsers = new OUsers(*this,m_aMutex,aVector,m_pConnection,this);
}
// -------------------------------------------------------------------------
const ::rtl::OUString& OAdabasCatalog::getDot()
{
    static const ::rtl::OUString sDot(RTL_CONSTASCII_USTRINGPARAM("."));
    return sDot;
}
// -----------------------------------------------------------------------------
void OAdabasCatalog::correctColumnProperties(sal_Int32 /*_nPrec*/, sal_Int32& _rnType,::rtl::OUString& _rsTypeName)
{
    switch(_rnType)
    {
    case DataType::DECIMAL:
        {
            static const ::rtl::OUString sDecimal(RTL_CONSTASCII_USTRINGPARAM("DECIMAL"));
            if(_rnType == DataType::DECIMAL && _rsTypeName == sDecimal)
                _rnType = DataType::NUMERIC;
        }
        break;
    case DataType::FLOAT:
        //  if(_nPrec >= 16)
        {
            static const ::rtl::OUString sDouble(RTL_CONSTASCII_USTRINGPARAM("DOUBLE PRECISION"));
            _rsTypeName = sDouble;
            _rnType = DataType::DOUBLE;
        }
//      else if(_nPrec > 15)
//      {
//          static const ::rtl::OUString sReal = ::rtl::OUString::createFromAscii("REAL");
//          _rsTypeName = sReal;
//          _rnType = DataType::REAL;
//      }
        break;
    }
}
// -----------------------------------------------------------------------------

<commit_msg>INTEGRATION: CWS changefileheader (1.15.216); FILE MERGED 2008/04/01 15:08:33 thb 1.15.216.3: #i85898# Stripping all external header guards 2008/04/01 10:52:47 thb 1.15.216.2: #i85898# Stripping all external header guards 2008/03/28 15:23:23 rt 1.15.216.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: BCatalog.cxx,v $
 * $Revision: 1.16 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_connectivity.hxx"
#include "adabas/BCatalog.hxx"
#include "adabas/BConnection.hxx"
#include "adabas/BGroups.hxx"
#include "adabas/BUsers.hxx"
#include "adabas/BTables.hxx"
#include "adabas/BViews.hxx"
#include <com/sun/star/sdbc/XRow.hpp>
#include <com/sun/star/sdbc/XResultSet.hpp>
#include <comphelper/types.hxx>

// -------------------------------------------------------------------------
using namespace connectivity;
using namespace connectivity::adabas;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::sdbcx;
using namespace ::com::sun::star::sdbc;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::lang;
// -----------------------------------------------------------------------------
OAdabasCatalog::OAdabasCatalog(SQLHANDLE _aConnectionHdl, OAdabasConnection* _pCon) : connectivity::sdbcx::OCatalog(_pCon)
                ,m_pConnection(_pCon)
                ,m_aConnectionHdl(_aConnectionHdl)
{
}
// -----------------------------------------------------------------------------
::rtl::OUString OAdabasCatalog::buildName(const Reference< XRow >& _xRow)
{
    ::rtl::OUString sName;
    sName = _xRow->getString(2);
    if ( sName.getLength() )
        sName += OAdabasCatalog::getDot();
    sName += _xRow->getString(3);

    return sName;
}
// -----------------------------------------------------------------------------
void OAdabasCatalog::fillVector(const ::rtl::OUString& _sQuery,TStringVector& _rVector)
{
    Reference< XStatement > xStmt = m_pConnection->createStatement(  );
    OSL_ENSURE(xStmt.is(),"OAdabasCatalog::fillVector: Could not create a statement!");
    Reference< XResultSet > xResult = xStmt->executeQuery(_sQuery);

    fillNames(xResult,_rVector);
    ::comphelper::disposeComponent(xStmt);

}
// -------------------------------------------------------------------------
void OAdabasCatalog::refreshTables()
{
    TStringVector aVector;
    {
        Sequence< ::rtl::OUString > aTypes(1);
        aTypes[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("%"));
        Reference< XResultSet > xResult = m_xMetaData->getTables(Any(),
                                                                ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("%")),
                                                                ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("%")),
                                                                aTypes);
        fillNames(xResult,aVector);
    }

    if(m_pTables)
        m_pTables->reFill(aVector);
    else
        m_pTables = new OTables(m_xMetaData,*this,m_aMutex,aVector);
}
// -------------------------------------------------------------------------
void OAdabasCatalog::refreshViews()
{
    TStringVector aVector;
    static const ::rtl::OUString s_sView(RTL_CONSTASCII_USTRINGPARAM("SELECT DISTINCT NULL,DOMAIN.VIEWDEFS.OWNER, DOMAIN.VIEWDEFS.VIEWNAME FROM DOMAIN.VIEWDEFS"));
    fillVector(s_sView,aVector);

    if(m_pViews)
        m_pViews->reFill(aVector);
    else
        m_pViews = new OViews(m_xMetaData,*this,m_aMutex,aVector);
}
// -------------------------------------------------------------------------
void OAdabasCatalog::refreshGroups()
{
    TStringVector aVector;
    static const ::rtl::OUString s_sGroup(RTL_CONSTASCII_USTRINGPARAM("SELECT DISTINCT NULL,NULL,GROUPNAME FROM DOMAIN.USERS WHERE GROUPNAME IS NOT NULL AND GROUPNAME <> ' '"));
    fillVector(s_sGroup,aVector);
    if(m_pGroups)
        m_pGroups->reFill(aVector);
    else
        m_pGroups = new OGroups(*this,m_aMutex,aVector,m_pConnection,this);
}
// -------------------------------------------------------------------------
void OAdabasCatalog::refreshUsers()
{
    TStringVector aVector;
    static const ::rtl::OUString s_sUsers(RTL_CONSTASCII_USTRINGPARAM("SELECT DISTINCT NULL,NULL,USERNAME FROM DOMAIN.USERS WHERE USERNAME IS NOT NULL AND USERNAME <> ' ' AND USERNAME <> 'CONTROL'"));
    fillVector(s_sUsers,aVector);

    if(m_pUsers)
        m_pUsers->reFill(aVector);
    else
        m_pUsers = new OUsers(*this,m_aMutex,aVector,m_pConnection,this);
}
// -------------------------------------------------------------------------
const ::rtl::OUString& OAdabasCatalog::getDot()
{
    static const ::rtl::OUString sDot(RTL_CONSTASCII_USTRINGPARAM("."));
    return sDot;
}
// -----------------------------------------------------------------------------
void OAdabasCatalog::correctColumnProperties(sal_Int32 /*_nPrec*/, sal_Int32& _rnType,::rtl::OUString& _rsTypeName)
{
    switch(_rnType)
    {
    case DataType::DECIMAL:
        {
            static const ::rtl::OUString sDecimal(RTL_CONSTASCII_USTRINGPARAM("DECIMAL"));
            if(_rnType == DataType::DECIMAL && _rsTypeName == sDecimal)
                _rnType = DataType::NUMERIC;
        }
        break;
    case DataType::FLOAT:
        //  if(_nPrec >= 16)
        {
            static const ::rtl::OUString sDouble(RTL_CONSTASCII_USTRINGPARAM("DOUBLE PRECISION"));
            _rsTypeName = sDouble;
            _rnType = DataType::DOUBLE;
        }
//      else if(_nPrec > 15)
//      {
//          static const ::rtl::OUString sReal = ::rtl::OUString::createFromAscii("REAL");
//          _rsTypeName = sReal;
//          _rnType = DataType::REAL;
//      }
        break;
    }
}
// -----------------------------------------------------------------------------

<|endoftext|>


<commit_before>//  bakers_map.cpp : The baker's map is a chaotic map from the unit squre into itself.
//
// Copyright (C) 2017-2020 Stillwater Supercomputing, Inc.
//
// This file is part of the universal numbers project, which is released under an MIT Open Source license.
#include <iostream>
#include <universal/blas/blas.hpp>
#include <universal/posit/posit>

/*
In dynamical systems theory, the baker's map is a chaotic map from the unit square into itself.
It is named after a kneading operation that bakers apply to dough: the dough is cut in half,
and the two halves are stacked on one another, and compressed.

The baker's map can be understood as the bilateral shift operator of a bi-infinite two-state
lattice model. The baker's map is topologically conjugate to the horseshoe map.
In physics, a chain of coupled baker's maps can be used to model deterministic diffusion.

As with many deterministic dynamical systems, the baker's map is studied by its action
on the space of functions defined on the unit square. The baker's map defines an operator
on the space of functions, known as the transfer operator of the map. The baker's map is
an exactly solvable model of deterministic chaos, in that the eigenfunctions and eigenvalues
of the transfer operator can be explicitly determined.

Keywords: deterministic chaos, float precision
 */

/*
  Folded baker's map acts on the unit square as

  S_baker-folded(x, y) = { (2x, y/2)         for 0.0 <= x < 0.5
						 { (2 - 2x, 1 - y/2) for 0.5 <= x < 1.0
 */
template<typename Real>
std::pair<Real, Real> BakersMap(const std::pair<Real, Real>& xy) {
	std::pair<Real, Real> map;
	if (xy.first < Real(0.5)) {
		map.first = 2 * xy.first;
		map.second = xy.second / 2;
	}
	else {
		map.first = 2 - 2 * xy.first;
		map.second = 1 - xy.second / 2;
	}
	return map;
}

template<typename Real>
std::ostream& operator<<(std::ostream& ostr, std::pair<Real, Real>& xy) {
	return ostr << '(' << sw::unum::color_print(xy.first) << ", " << sw::unum::color_print(xy.second) << ") : (" << xy.first << ", " << xy.second << ')';
}

// iterate a set of (x,y) values through the Baker's map
template<typename Real>
void TraceBakersMap(const Real& x, const Real& y, unsigned nrIterations) {
	std::cout << typeid(Real).name() << '\n';
	std::pair<Real, Real> xy(x, y);
//	xy.first = x;
//	xy.second = y;
	std::cout << std::setw(5) << 0 << " : " << xy << std::endl;
	for (unsigned i = 1; i < nrIterations; ++i) {
		xy = BakersMap(xy);
		std::cout << std::setw(5) << i << " : " << xy << std::endl;
	}
}

template<typename Matrix>
void InitializeTwoBands(Matrix& S) {
	using Real = typename Matrix::value_type;
	unsigned n = S.rows();
	unsigned m = S.cols();
	assert(n == m);
	for (unsigned i = 0; i < n; ++i) {
		for (unsigned j = 0; j < m / 2; ++j) {
			S(i, j) = Real(0.25);
		}
		for (unsigned j = m / 2; j < m; ++j) {
			S(i, j) = Real(0.75);
		}
	}
}

/*
  Folded baker's map acts on the unit square as

  S_baker-folded(x, y) = { (2x, y/2)         for 0.0 <= x < 0.5
                         { (2 - 2x, 1 - y/2) for 0.5 <= x < 1.0
 */
template<typename Matrix>
void KneadAndFold(const Matrix& S, Matrix& Snext) {
	using Real = typename Matrix::value_type;
	unsigned n = S.rows();
	unsigned m = S.cols();
	assert(n == m);
	auto oldprecision = std::cout.precision();
	std::cout << std::setprecision(15);
	for (unsigned i = 0; i < n; ++i) {
		Real x = Real(i) / n;
		for (unsigned j = 0; j < m; ++j) {
			Real y = Real(j) / m;
			Real xnext, ynext;
			if (x <= Real(0.5)) {
				xnext = 2 * x;
				ynext = y / 2;
				Snext(i, j) = S(unsigned(xnext * n), unsigned(ynext * m));
			}
			else {
				xnext = 2 - 2 * x;
				ynext = 1 - y / 2;
				Snext(i, j) = S(unsigned(xnext * n), unsigned(ynext * m));
			}
			// trace the accuracy of (x,y) of a point
			if (i == (n - 1) && j == (m - 1)) {
				std::cout << '(' << std::setw(15) << sw::unum::to_binary(xnext * n) << ',';
				std::cout << std::setw(15) << sw::unum::to_binary(ynext * m) << ")\n";
				std::cout << '(' << x << ',' << y << ") maps to ";
				std::cout << '(' << xnext << ',' << ynext << ") truncates to ";
				std::cout << '(' << unsigned(xnext * n) << ',' << unsigned(ynext * m) << ")\n";
			}
			//std::cout << Snext << std::endl;
		}
	}
	std::cout << std::setprecision(oldprecision);
}

template<typename Real>
void Knead(int nrOfFolds) {
	constexpr int N = 100;
	sw::unum::blas::matrix<Real> S1(N, N), S2(N, N);
	InitializeTwoBands(S1);
	//cout << S1 << endl;

	for (unsigned nrOfFolds = 0; nrOfFolds < 10; ++nrOfFolds) {
		if (nrOfFolds % 2) {
			KneadAndFold(S2, S1); // fold back
		}
		else {
			KneadAndFold(S1, S2); // fold forward
		}
	}
}

int main()
try {
	using namespace std;
	using namespace sw::unum::blas;

	cout << "Baker's Map\n";

	{
		using Real = float;
		Real x = 0.125 * 0.125 * 0.125 * 0.125 * 0.125 * 0.125;
		Real y = 0.75;
		TraceBakersMap(x, y, 25);
	}

	{
		using Real = sw::unum::posit<32,2>;
		Real x = 0.125 * 0.125 * 0.125 * 0.125 * 0.125 * 0.125;
		Real y = 0.75;
		TraceBakersMap(x, y, 25);
	}

	cout << "Baker's Map\n";
	double random_value = double(rand()) / double(RAND_MAX);
	{
		using Real = float;
		Real x = Real(random_value);
		Real y = 0.75;
		TraceBakersMap(x, y, 25);
	}
	{
		using Real = sw::unum::posit<32, 2>;
		Real x = random_value;
		Real y = 0.75;
		TraceBakersMap(x, y, 25);
	}

	// setting x to minpos fails as 2 * minpos still rounds to minpos

	cout << "Baker's Map: minpos fail:\n";
	{
		using Real = sw::unum::posit<32, 2>;
		std::cout << std::setprecision(17);
		Real x;
		sw::unum::minpos(x);
		std::cout << "minpos<32,2> : " << x << '\n';
		Real y = 0.75;
		TraceBakersMap(x, y, 5);
	}
	cout << "Baker's Map: region k-1:\n";
	{
		using Real = sw::unum::posit<32, 2>;
		std::cout << std::setprecision(17);
		Real x;
		sw::unum::minpos(x);
		x *= sw::unum::useed<32, 2>();
		std::cout << "minpos<32,2> * useed : " << x << '\n';
		Real y = 0.75;
		TraceBakersMap(x, y, 5);
	}
	cout << "Baker's Map: region k-2:\n";
	{
		using Real = sw::unum::posit<32, 2>;
		std::cout << std::setprecision(17);
		Real x;
		sw::unum::minpos(x);
		x *= sw::unum::useed<32, 2>() * sw::unum::useed<32,2>();
		std::cout << "minpos<32,2> * useed^2 : " << x << '\n';
		Real y = 0.75;
		TraceBakersMap(x, y, 25);
	}

	return EXIT_SUCCESS;
}
catch (char const* msg) {
	std::cerr << msg << std::endl;
	return EXIT_FAILURE;
}
catch (const posit_arithmetic_exception& err) {
	std::cerr << "Uncaught posit arithmetic exception: " << err.what() << std::endl;
	return EXIT_FAILURE;
}
catch (const quire_exception& err) {
	std::cerr << "Uncaught quire exception: " << err.what() << std::endl;
	return EXIT_FAILURE;
}
catch (const posit_internal_exception& err) {
	std::cerr << "Uncaught posit internal exception: " << err.what() << std::endl;
	return EXIT_FAILURE;
}
catch (const std::runtime_error& err) {
	std::cerr << "Uncaught runtime exception: " << err.what() << std::endl;
	return EXIT_FAILURE;
}
catch (...) {
	std::cerr << "Caught unknown exception" << std::endl;
	return EXIT_FAILURE;
}
<commit_msg>showing the longest cycle in a posit<32,2> in a Baker's map<commit_after>//  bakers_map.cpp : The baker's map is a chaotic map from the unit squre into itself.
//
// Copyright (C) 2017-2020 Stillwater Supercomputing, Inc.
//
// This file is part of the universal numbers project, which is released under an MIT Open Source license.
#include <iostream>
#include <universal/blas/blas.hpp>
#include <universal/posit/posit>

/*
In dynamical systems theory, the baker's map is a chaotic map from the unit square into itself.
It is named after a kneading operation that bakers apply to dough: the dough is cut in half,
and the two halves are stacked on one another, and compressed.

The baker's map can be understood as the bilateral shift operator of a bi-infinite two-state
lattice model. The baker's map is topologically conjugate to the horseshoe map.
In physics, a chain of coupled baker's maps can be used to model deterministic diffusion.

As with many deterministic dynamical systems, the baker's map is studied by its action
on the space of functions defined on the unit square. The baker's map defines an operator
on the space of functions, known as the transfer operator of the map. The baker's map is
an exactly solvable model of deterministic chaos, in that the eigenfunctions and eigenvalues
of the transfer operator can be explicitly determined.

Keywords: deterministic chaos, float precision
 */

/*
  Folded baker's map acts on the unit square as

  S_baker-folded(x, y) = { (2x, y/2)         for 0.0 <= x < 0.5
						 { (2 - 2x, 1 - y/2) for 0.5 <= x < 1.0
 */
template<typename Real>
std::pair<Real, Real> BakersMap(const std::pair<Real, Real>& xy) {
	std::pair<Real, Real> map;
	if (xy.first < Real(0.5)) {
		map.first = 2 * xy.first;
		map.second = xy.second / 2;
	}
	else {
		map.first = 2 - 2 * xy.first;
		map.second = 1 - xy.second / 2;
	}
	return map;
}

template<typename Real>
std::ostream& operator<<(std::ostream& ostr, std::pair<Real, Real>& xy) {
	return ostr << '(' << sw::unum::color_print(xy.first) << ", " << sw::unum::color_print(xy.second) << ") : (" << xy.first << ", " << xy.second << ')';
}

// iterate a set of (x,y) values through the Baker's map
template<typename Real>
void TraceBakersMap(const Real& x, const Real& y, unsigned nrIterations) {
	std::cout << typeid(Real).name() << '\n';
	std::pair<Real, Real> xy(x, y);
//	xy.first = x;
//	xy.second = y;
	std::cout << std::setw(5) << 0 << " : " << xy << std::endl;
	for (unsigned i = 1; i < nrIterations; ++i) {
		xy = BakersMap(xy);
		std::cout << std::setw(5) << i << " : " << xy << std::endl;
	}
}

template<typename Matrix>
void InitializeTwoBands(Matrix& S) {
	using Real = typename Matrix::value_type;
	unsigned n = S.rows();
	unsigned m = S.cols();
	assert(n == m);
	for (unsigned i = 0; i < n; ++i) {
		for (unsigned j = 0; j < m / 2; ++j) {
			S(i, j) = Real(0.25);
		}
		for (unsigned j = m / 2; j < m; ++j) {
			S(i, j) = Real(0.75);
		}
	}
}

/*
  Folded baker's map acts on the unit square as

  S_baker-folded(x, y) = { (2x, y/2)         for 0.0 <= x < 0.5
                         { (2 - 2x, 1 - y/2) for 0.5 <= x < 1.0
 */
template<typename Matrix>
void KneadAndFold(const Matrix& S, Matrix& Snext) {
	using Real = typename Matrix::value_type;
	unsigned n = S.rows();
	unsigned m = S.cols();
	assert(n == m);
	auto oldprecision = std::cout.precision();
	std::cout << std::setprecision(15);
	for (unsigned i = 0; i < n; ++i) {
		Real x = Real(i) / n;
		for (unsigned j = 0; j < m; ++j) {
			Real y = Real(j) / m;
			Real xnext, ynext;
			if (x <= Real(0.5)) {
				xnext = 2 * x;
				ynext = y / 2;
				Snext(i, j) = S(unsigned(xnext * n), unsigned(ynext * m));
			}
			else {
				xnext = 2 - 2 * x;
				ynext = 1 - y / 2;
				Snext(i, j) = S(unsigned(xnext * n), unsigned(ynext * m));
			}
			// trace the accuracy of (x,y) of a point
			if (i == (n - 1) && j == (m - 1)) {
				std::cout << '(' << std::setw(15) << sw::unum::to_binary(xnext * n) << ',';
				std::cout << std::setw(15) << sw::unum::to_binary(ynext * m) << ")\n";
				std::cout << '(' << x << ',' << y << ") maps to ";
				std::cout << '(' << xnext << ',' << ynext << ") truncates to ";
				std::cout << '(' << unsigned(xnext * n) << ',' << unsigned(ynext * m) << ")\n";
			}
			//std::cout << Snext << std::endl;
		}
	}
	std::cout << std::setprecision(oldprecision);
}

template<typename Real>
void Knead(int nrOfFolds) {
	constexpr int N = 100;
	sw::unum::blas::matrix<Real> S1(N, N), S2(N, N);
	InitializeTwoBands(S1);
	//cout << S1 << endl;

	for (unsigned nrOfFolds = 0; nrOfFolds < 10; ++nrOfFolds) {
		if (nrOfFolds % 2) {
			KneadAndFold(S2, S1); // fold back
		}
		else {
			KneadAndFold(S1, S2); // fold forward
		}
	}
}

int main()
try {
	using namespace std;
	using namespace sw::unum::blas;

	cout << "Baker's Map\n";

	{
		using Real = float;
		Real x = 0.125 * 0.125 * 0.125 * 0.125 * 0.125 * 0.125;
		Real y = 0.75;
		TraceBakersMap(x, y, 25);
	}

	{
		using Real = sw::unum::posit<32,2>;
		Real x = 0.125 * 0.125 * 0.125 * 0.125 * 0.125 * 0.125;
		Real y = 0.75;
		TraceBakersMap(x, y, 25);
	}

	cout << "Baker's Map\n";
	double random_value = double(rand()) / double(RAND_MAX);
	{
		using Real = float;
		Real x = Real(random_value);
		Real y = 0.75;
		TraceBakersMap(x, y, 25);
	}
	{
		using Real = sw::unum::posit<32, 2>;
		Real x = random_value;
		Real y = 0.75;
		TraceBakersMap(x, y, 25);
	}

	// setting x to minpos fails as 2 * minpos still rounds to minpos

	cout << "Baker's Map: minpos fail:\n";
	{
		using Real = sw::unum::posit<32, 2>;
		std::cout << std::setprecision(17);
		Real x;
		sw::unum::minpos(x);
		std::cout << "minpos<32,2> : " << x << '\n';
		Real y = 0.75;
		TraceBakersMap(x, y, 5);
	}
	cout << "Baker's Map: region k-1:\n";
	{
		using Real = sw::unum::posit<32, 2>;
		std::cout << std::setprecision(17);
		Real x;
		sw::unum::minpos(x);
		x *= sw::unum::useed<32, 2>();
		std::cout << "minpos<32,2> * useed : " << x << '\n';
		Real y = 0.75;
		TraceBakersMap(x, y, 5);
	}
	cout << "Baker's Map: region k-2:\n";
	{
		using Real = sw::unum::posit<32, 2>;
		std::cout << std::setprecision(17);
		Real x;
		sw::unum::minpos(x);
		x *= sw::unum::useed<32, 2>() * sw::unum::useed<32,2>();
		std::cout << "minpos<32,2> * useed^2 : " << x << '\n';
		Real y = 0.75;
		TraceBakersMap(x, y, 125);
	}

	return EXIT_SUCCESS;
}
catch (char const* msg) {
	std::cerr << msg << std::endl;
	return EXIT_FAILURE;
}
catch (const posit_arithmetic_exception& err) {
	std::cerr << "Uncaught posit arithmetic exception: " << err.what() << std::endl;
	return EXIT_FAILURE;
}
catch (const quire_exception& err) {
	std::cerr << "Uncaught quire exception: " << err.what() << std::endl;
	return EXIT_FAILURE;
}
catch (const posit_internal_exception& err) {
	std::cerr << "Uncaught posit internal exception: " << err.what() << std::endl;
	return EXIT_FAILURE;
}
catch (const std::runtime_error& err) {
	std::cerr << "Uncaught runtime exception: " << err.what() << std::endl;
	return EXIT_FAILURE;
}
catch (...) {
	std::cerr << "Caught unknown exception" << std::endl;
	return EXIT_FAILURE;
}
<|endoftext|>


<commit_before>/**************************************************************************************/
/*                                                                                */
/*  Visualization Library                                                             */
/*  http://www.visualizationlibrary.com                                               */
/*                                                                                */
/*  Copyright (c) 2005-2010, Michele Bosi                                             */
/*  All rights reserved.                                                              */
/*                                                                                */
/*  Redistribution and use in source and binary forms, with or without modification,  */
/*  are permitted provided that the following conditions are met:                     */
/*                                                                                */
/*  - Redistributions of source code must retain the above copyright notice, this     */
/*  list of conditions and the following disclaimer.                                  */
/*                                                                                */
/*  - Redistributions in binary form must reproduce the above copyright notice, this  */
/*  list of conditions and the following disclaimer in the documentation and/or       */
/*  other materials provided with the distribution.                                   */
/*                                                                                */
/*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND   */
/*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED     */
/*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE            */
/*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR  */
/*  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    */
/*  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;      */
/*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON    */
/*  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT           */
/*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS     */
/*  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                      */
/*                                                                                */
/**************************************************************************************/

#include <vl/Actor.hpp>

using namespace vl;

//-----------------------------------------------------------------------------
// Actor
//-----------------------------------------------------------------------------
Actor::~Actor()
{
  dispatchOnActorDelte();
  deleteOcclusionQuery();
}
//-----------------------------------------------------------------------------
void Actor::setLODs(Renderable* lod0, Renderable* lod1, Renderable* lod2, Renderable* lod3, Renderable* lod4, Renderable* lod5)
{
  if (lod0) { VL_CHECK(0<VL_MAX_ACTOR_LOD) lod(0) = lod0; }
  if (lod1) { VL_CHECK(1<VL_MAX_ACTOR_LOD) lod(1) = lod1; }
  if (lod2) { VL_CHECK(2<VL_MAX_ACTOR_LOD) lod(2) = lod2; }
  if (lod3) { VL_CHECK(3<VL_MAX_ACTOR_LOD) lod(3) = lod3; }
  if (lod4) { VL_CHECK(4<VL_MAX_ACTOR_LOD) lod(4) = lod4; }
  if (lod5) { VL_CHECK(5<VL_MAX_ACTOR_LOD) lod(5) = lod5; }
}
//-----------------------------------------------------------------------------
int Actor::evaluateLOD(Camera* camera)
{
  if (mLODEvaluator)
    return mLODEvaluator->evaluate(this, camera);
  else
    return 0;
}
//-----------------------------------------------------------------------------
void Actor::createOcclusionQuery()
{
  VL_CHECK_OGL();
  if (!mOcclusionQuery && (GLEW_ARB_occlusion_query || GLEW_VERSION_1_5))
    glGenQueries(1, &mOcclusionQuery);
  VL_CHECK_OGL();
  VL_CHECK(mOcclusionQuery)
}
//-----------------------------------------------------------------------------
void Actor::deleteOcclusionQuery()
{
  if(GLEW_ARB_occlusion_query || GLEW_VERSION_1_5)
  {
    if (mOcclusionQuery)
    {
      glDeleteQueries(1, &mOcclusionQuery);
      mOcclusionQuery = 0;
    }
  }
}
//-----------------------------------------------------------------------------
void Actor::computeBounds()
{
  if ( !lod(0) )
    return;

  if ( lod(0)->boundsDirty() )
    lod(0)->computeBounds();

  bool update = lod(0)->boundsUpdateTick() != mBoundsUpdateTick;

  if ( transform() && (update || transform()->worldMatrixUpdateTick() != mTransformUpdateTick) )
  {
    lod(0)->boundingBox().transformed( mAABB, transform()->worldMatrix() );
    mTransformUpdateTick = transform()->worldMatrixUpdateTick();
    mBoundsUpdateTick = lod(0)->boundsUpdateTick();
    mSphere = mAABB.isNull() ? Sphere() : mAABB;
  }
  else
  if (update)
  {
    mAABB   = lod(0)->boundingBox();
    mSphere = mAABB.isNull() ? Sphere() : mAABB;
    mBoundsUpdateTick = lod(0)->boundsUpdateTick();
  }
}
//-----------------------------------------------------------------------------
void Actor::setUniform(Uniform* uniform)
{
  if (!uniformSet())
    setUniformSet(new UniformSet);
  uniformSet()->setUniform(uniform);
}
//-----------------------------------------------------------------------------
const std::vector< ref<Uniform> >& Actor::uniforms() const { return uniformSet()->uniforms(); }
//-----------------------------------------------------------------------------
void Actor::eraseUniform(const std::string& name) { uniformSet()->eraseUniform(name); }
//-----------------------------------------------------------------------------
void Actor::eraseUniform(const Uniform* uniform) { uniformSet()->eraseUniform(uniform); }
//-----------------------------------------------------------------------------
void Actor::eraseAllUniforms() { uniformSet()->eraseAllUniforms(); }
//-----------------------------------------------------------------------------
Uniform* Actor::gocUniform(const std::string& name) { return uniformSet()->gocUniform(name); }
//-----------------------------------------------------------------------------
Uniform* Actor::getUniform(const std::string& name) { return uniformSet()->getUniform(name); }
//-----------------------------------------------------------------------------
const Uniform* Actor::getUniform(const std::string& name) const { return uniformSet()->getUniform(name); }
//-----------------------------------------------------------------------------
<commit_msg>fixed typo<commit_after>/**************************************************************************************/
/*                                                                                */
/*  Visualization Library                                                             */
/*  http://www.visualizationlibrary.com                                               */
/*                                                                                */
/*  Copyright (c) 2005-2010, Michele Bosi                                             */
/*  All rights reserved.                                                              */
/*                                                                                */
/*  Redistribution and use in source and binary forms, with or without modification,  */
/*  are permitted provided that the following conditions are met:                     */
/*                                                                                */
/*  - Redistributions of source code must retain the above copyright notice, this     */
/*  list of conditions and the following disclaimer.                                  */
/*                                                                                */
/*  - Redistributions in binary form must reproduce the above copyright notice, this  */
/*  list of conditions and the following disclaimer in the documentation and/or       */
/*  other materials provided with the distribution.                                   */
/*                                                                                */
/*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND   */
/*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED     */
/*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE            */
/*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR  */
/*  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    */
/*  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;      */
/*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON    */
/*  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT           */
/*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS     */
/*  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                      */
/*                                                                                */
/**************************************************************************************/

#include <vl/Actor.hpp>

using namespace vl;

//-----------------------------------------------------------------------------
// Actor
//-----------------------------------------------------------------------------
Actor::~Actor()
{
  dispatchOnActorDelete();
  deleteOcclusionQuery();
}
//-----------------------------------------------------------------------------
void Actor::setLODs(Renderable* lod0, Renderable* lod1, Renderable* lod2, Renderable* lod3, Renderable* lod4, Renderable* lod5)
{
  if (lod0) { VL_CHECK(0<VL_MAX_ACTOR_LOD) lod(0) = lod0; }
  if (lod1) { VL_CHECK(1<VL_MAX_ACTOR_LOD) lod(1) = lod1; }
  if (lod2) { VL_CHECK(2<VL_MAX_ACTOR_LOD) lod(2) = lod2; }
  if (lod3) { VL_CHECK(3<VL_MAX_ACTOR_LOD) lod(3) = lod3; }
  if (lod4) { VL_CHECK(4<VL_MAX_ACTOR_LOD) lod(4) = lod4; }
  if (lod5) { VL_CHECK(5<VL_MAX_ACTOR_LOD) lod(5) = lod5; }
}
//-----------------------------------------------------------------------------
int Actor::evaluateLOD(Camera* camera)
{
  if (mLODEvaluator)
    return mLODEvaluator->evaluate(this, camera);
  else
    return 0;
}
//-----------------------------------------------------------------------------
void Actor::createOcclusionQuery()
{
  VL_CHECK_OGL();
  if (!mOcclusionQuery && (GLEW_ARB_occlusion_query || GLEW_VERSION_1_5))
    glGenQueries(1, &mOcclusionQuery);
  VL_CHECK_OGL();
  VL_CHECK(mOcclusionQuery)
}
//-----------------------------------------------------------------------------
void Actor::deleteOcclusionQuery()
{
  if(GLEW_ARB_occlusion_query || GLEW_VERSION_1_5)
  {
    if (mOcclusionQuery)
    {
      glDeleteQueries(1, &mOcclusionQuery);
      mOcclusionQuery = 0;
    }
  }
}
//-----------------------------------------------------------------------------
void Actor::computeBounds()
{
  if ( !lod(0) )
    return;

  if ( lod(0)->boundsDirty() )
    lod(0)->computeBounds();

  bool update = lod(0)->boundsUpdateTick() != mBoundsUpdateTick;

  if ( transform() && (update || transform()->worldMatrixUpdateTick() != mTransformUpdateTick) )
  {
    lod(0)->boundingBox().transformed( mAABB, transform()->worldMatrix() );
    mTransformUpdateTick = transform()->worldMatrixUpdateTick();
    mBoundsUpdateTick = lod(0)->boundsUpdateTick();
    mSphere = mAABB.isNull() ? Sphere() : mAABB;
  }
  else
  if (update)
  {
    mAABB   = lod(0)->boundingBox();
    mSphere = mAABB.isNull() ? Sphere() : mAABB;
    mBoundsUpdateTick = lod(0)->boundsUpdateTick();
  }
}
//-----------------------------------------------------------------------------
void Actor::setUniform(Uniform* uniform)
{
  if (!uniformSet())
    setUniformSet(new UniformSet);
  uniformSet()->setUniform(uniform);
}
//-----------------------------------------------------------------------------
const std::vector< ref<Uniform> >& Actor::uniforms() const { return uniformSet()->uniforms(); }
//-----------------------------------------------------------------------------
void Actor::eraseUniform(const std::string& name) { uniformSet()->eraseUniform(name); }
//-----------------------------------------------------------------------------
void Actor::eraseUniform(const Uniform* uniform) { uniformSet()->eraseUniform(uniform); }
//-----------------------------------------------------------------------------
void Actor::eraseAllUniforms() { uniformSet()->eraseAllUniforms(); }
//-----------------------------------------------------------------------------
Uniform* Actor::gocUniform(const std::string& name) { return uniformSet()->gocUniform(name); }
//-----------------------------------------------------------------------------
Uniform* Actor::getUniform(const std::string& name) { return uniformSet()->getUniform(name); }
//-----------------------------------------------------------------------------
const Uniform* Actor::getUniform(const std::string& name) const { return uniformSet()->getUniform(name); }
//-----------------------------------------------------------------------------
<|endoftext|>


<commit_before>// Copyright 2014 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <iostream>
#include <string>
#include <vector>
#include <exception>
#include <fstream>
#include <iomanip>
#include <limits>
#include <algorithm>

#include <ArgumentList.hpp>
#include <InitializeOpenCL.hpp>
#include <Kernel.hpp>
#include <Transpose.hpp>
#include <utils.hpp>
#include <Timer.hpp>
#include <Stats.hpp>

typedef float dataType;
string typeName("float");

int main(int argc, char * argv[]) {
	unsigned int nrIterations = 0;
	unsigned int clPlatformID = 0;
	unsigned int clDeviceID = 0;
	unsigned int minThreads = 0;
	unsigned int maxThreads = 0;
  unsigned int padding = 0;
  unsigned int vector = 0;
  unsigned int M = 0;
  unsigned int N = 0;

	try {
    isa::utils::ArgumentList args(argc, argv);

		nrIterations = args.getSwitchArgument< unsigned int >("-iterations");
		clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
		clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");
    padding = args.getSwitchArgument< unsigned int >("-padding");
    vector = args.getSwitchArgument< unsigned int >("-vector");
    M = args.getSwitchArgument< unsigned int >("-M");
    N = args.getSwitchArgument< unsigned int >("-N");
		minThreads = args.getSwitchArgument< unsigned int >("-min_threads");
		maxThreads = args.getSwitchArgument< unsigned int >("-max_threads");
	} catch ( isa::utils::EmptyCommandLine &err ) {
		std::cerr << argv[0] << " -iterations ... -opencl_platform ... -opencl_device ... -padding ... - vector ... -M ... -N ... -min_threads ... -max_threads ..." << std::endl;
		return 1;
	} catch ( std::exception &err ) {
		std::cerr << err.what() << std::endl;
		return 1;
	}

	// Initialize OpenCL
	cl::Context * clContext = new cl::Context();
	std::vector< cl::Platform > * clPlatforms = new std::vector< cl::Platform >();
	std::vector< cl::Device > * clDevices = new std::vector< cl::Device >();
	std::vector< std::vector< cl::CommandQueue > > * clQueues = new std::vector< std::vector < cl::CommandQueue > >();

  isa::OpenCL::initializeOpenCL(clPlatformID, 1, clPlatforms, clContext, clDevices, clQueues);

	// Allocate memory
  std::vector< dataType > input = std::vector< dataType >(M * isa::utils::pad(N, padding));
  cl::Buffer input_d;
  std::vector< dataType > output = std::vector< dataType >(N * isa::utils::pad(M, padding));
  cl::Buffer output_d;
  try {
    input_d = cl::Buffer(*clContext, CL_MEM_READ_ONLY, input.size() * sizeof(dataType), 0, 0);
    output_d = cl::Buffer(*clContext, CL_MEM_WRITE_ONLY, output.size() * sizeof(dataType), 0, 0);
  } catch ( cl::Error &err ) {
    std::cerr << "OpenCL error allocating memory: " << isa::utils::toString(err.err()) << "." << std::endl;
    return 1;
  }

	srand(time(0));
  for ( unsigned int m = 0; m < M; m++ ) {
    for ( unsigned int n = 0; n < N; n++ ) {
      input[(m * isa::utils::pad(N, padding)) + n] = static_cast< dataType >(rand() % 10);
    }
	}

  // Copy data structures to device
  try {
    clQueues->at(clDeviceID)[0].enqueueWriteBuffer(input_d, CL_FALSE, 0, input.size() * sizeof(dataType), reinterpret_cast< void * >(input.data()));
  } catch ( cl::Error &err ) {
    std::cerr << "OpenCL error H2D transfer: " << isa::utils::toString(err.err()) << "." << std::endl;
    return 1;
  }

	// Find the parameters
	std::vector< unsigned int > threads;
	for ( unsigned int nrThreads = minThreads; nrThreads <= maxThreads; nrThreads += minThreads ) {
		if ( (M % nrThreads) == 0 ) {
			threads.push_back(nrThreads);
		}
	}

	std::cout << std::fixed << std::endl;
	std::cout << "# M N nrThreads GB/s err time err" << std::endl << std::endl;

  for ( std::vector< unsigned int >::iterator nrThreads = threads.begin(); nrThreads != threads.end(); ++nrThreads ) {
    // Generate kernel
    double gbs = isa::utils::giga(static_cast< long long unsigned int >(M) * N * 2 * sizeof(dataType));
    isa::utils::Timer timer("Kernel Timer");
    isa::utils::Stats< double > stats;
    cl::Event event;
    cl::Kernel * kernel;
    std::string * code = isa::OpenCL::getTransposeOpenCL(*nrThreads, M, N, padding, vector, typeName);

    try {
      kernel = isa::OpenCL::compile("transpose", *code, "-cl-mad-enable -Werror", *clContext, clDevices->at(clDeviceID));
    } catch ( isa::OpenCL::OpenCLError &err ) {
      std::cerr << err.what() << std::endl;
      return 1;
    }
    cl::NDRange global(M, std::ceil(static_cast< double >(N) / *nrThreads));
    cl::NDRange local(*nrThreads, 1);

    kernel->setArg(0, input_d);
    kernel->setArg(1, output_d);

    // Warm-up run
    try {
      clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &event);
      event.wait();
    } catch ( cl::Error &err ) {
      std::cerr << "OpenCL error kernel execution: " << isa::utils::toString(err.err()) << "." << std::endl;
      continue;
    }
    // Tuning runs
    try {
      for ( unsigned int iteration = 0; iteration < nrIterations; iteration++ ) {
        timer.start();
        clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &event);
        event.wait();
        timer.stop();
        stats.addElement(gbs / timer.getLastRunTime());
      }
    } catch ( cl::Error &err ) {
      std::cerr << "OpenCL error kernel execution: " << isa::utils::toString(err.err()) << "." << std::endl;
      continue;
    }

    std::cout << M << " " << N << " " << *nrThreads << " " << std::setprecision(3) << stats.getAverage() << " " << stats.getStdDev() << " " << std::setprecision(6) << timer.getAverageTime() << " " << timer.getStdDev() << std::endl;
  }

	std::cout << std::endl;

	return 0;
}

<commit_msg>Using the new Timer.<commit_after>// Copyright 2014 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <iostream>
#include <string>
#include <vector>
#include <exception>
#include <fstream>
#include <iomanip>
#include <limits>
#include <algorithm>

#include <ArgumentList.hpp>
#include <InitializeOpenCL.hpp>
#include <Kernel.hpp>
#include <Transpose.hpp>
#include <utils.hpp>
#include <Timer.hpp>
#include <Stats.hpp>

typedef float dataType;
std::string typeName("float");

int main(int argc, char * argv[]) {
	unsigned int nrIterations = 0;
	unsigned int clPlatformID = 0;
	unsigned int clDeviceID = 0;
	unsigned int minThreads = 0;
	unsigned int maxThreads = 0;
  unsigned int padding = 0;
  unsigned int vector = 0;
  unsigned int M = 0;
  unsigned int N = 0;

	try {
    isa::utils::ArgumentList args(argc, argv);

		nrIterations = args.getSwitchArgument< unsigned int >("-iterations");
		clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
		clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");
    padding = args.getSwitchArgument< unsigned int >("-padding");
    vector = args.getSwitchArgument< unsigned int >("-vector");
    M = args.getSwitchArgument< unsigned int >("-M");
    N = args.getSwitchArgument< unsigned int >("-N");
		minThreads = args.getSwitchArgument< unsigned int >("-min_threads");
		maxThreads = args.getSwitchArgument< unsigned int >("-max_threads");
	} catch ( isa::utils::EmptyCommandLine &err ) {
		std::cerr << argv[0] << " -iterations ... -opencl_platform ... -opencl_device ... -padding ... - vector ... -M ... -N ... -min_threads ... -max_threads ..." << std::endl;
		return 1;
	} catch ( std::exception &err ) {
		std::cerr << err.what() << std::endl;
		return 1;
	}

	// Initialize OpenCL
	cl::Context * clContext = new cl::Context();
	std::vector< cl::Platform > * clPlatforms = new std::vector< cl::Platform >();
	std::vector< cl::Device > * clDevices = new std::vector< cl::Device >();
	std::vector< std::vector< cl::CommandQueue > > * clQueues = new std::vector< std::vector < cl::CommandQueue > >();

  isa::OpenCL::initializeOpenCL(clPlatformID, 1, clPlatforms, clContext, clDevices, clQueues);

	// Allocate memory
  std::vector< dataType > input = std::vector< dataType >(M * isa::utils::pad(N, padding));
  cl::Buffer input_d;
  std::vector< dataType > output = std::vector< dataType >(N * isa::utils::pad(M, padding));
  cl::Buffer output_d;
  try {
    input_d = cl::Buffer(*clContext, CL_MEM_READ_ONLY, input.size() * sizeof(dataType), 0, 0);
    output_d = cl::Buffer(*clContext, CL_MEM_WRITE_ONLY, output.size() * sizeof(dataType), 0, 0);
  } catch ( cl::Error &err ) {
    std::cerr << "OpenCL error allocating memory: " << isa::utils::toString(err.err()) << "." << std::endl;
    return 1;
  }

	srand(time(0));
  for ( unsigned int m = 0; m < M; m++ ) {
    for ( unsigned int n = 0; n < N; n++ ) {
      input[(m * isa::utils::pad(N, padding)) + n] = static_cast< dataType >(rand() % 10);
    }
	}

  // Copy data structures to device
  try {
    clQueues->at(clDeviceID)[0].enqueueWriteBuffer(input_d, CL_FALSE, 0, input.size() * sizeof(dataType), reinterpret_cast< void * >(input.data()));
  } catch ( cl::Error &err ) {
    std::cerr << "OpenCL error H2D transfer: " << isa::utils::toString(err.err()) << "." << std::endl;
    return 1;
  }

	// Find the parameters
	std::vector< unsigned int > threads;
	for ( unsigned int nrThreads = minThreads; nrThreads <= maxThreads; nrThreads += minThreads ) {
		if ( (M % nrThreads) == 0 ) {
			threads.push_back(nrThreads);
		}
	}

	std::cout << std::fixed << std::endl;
	std::cout << "# M N nrThreads GB/s err time err" << std::endl << std::endl;

  for ( std::vector< unsigned int >::iterator nrThreads = threads.begin(); nrThreads != threads.end(); ++nrThreads ) {
    // Generate kernel
    double gbs = isa::utils::giga(static_cast< long long unsigned int >(M) * N * 2 * sizeof(dataType));
    isa::utils::Timer timer;
    isa::utils::Stats< double > stats;
    cl::Event event;
    cl::Kernel * kernel;
    std::string * code = isa::OpenCL::getTransposeOpenCL(*nrThreads, M, N, padding, vector, typeName);

    try {
      kernel = isa::OpenCL::compile("transpose", *code, "-cl-mad-enable -Werror", *clContext, clDevices->at(clDeviceID));
    } catch ( isa::OpenCL::OpenCLError &err ) {
      std::cerr << err.what() << std::endl;
      return 1;
    }
    cl::NDRange global(M, std::ceil(static_cast< double >(N) / *nrThreads));
    cl::NDRange local(*nrThreads, 1);

    kernel->setArg(0, input_d);
    kernel->setArg(1, output_d);

    // Warm-up run
    try {
      clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &event);
      event.wait();
    } catch ( cl::Error &err ) {
      std::cerr << "OpenCL error kernel execution: " << isa::utils::toString(err.err()) << "." << std::endl;
      continue;
    }
    // Tuning runs
    try {
      for ( unsigned int iteration = 0; iteration < nrIterations; iteration++ ) {
        timer.start();
        clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &event);
        event.wait();
        timer.stop();
        stats.addElement(gbs / timer.getLastRunTime());
      }
    } catch ( cl::Error &err ) {
      std::cerr << "OpenCL error kernel execution: " << isa::utils::toString(err.err()) << "." << std::endl;
      continue;
    }

    std::cout << M << " " << N << " " << *nrThreads << " " << std::setprecision(3) << stats.getAverage() << " " << stats.getStdDev() << " " << std::setprecision(6) << timer.getAverageTime() << " " << timer.getStdDev() << std::endl;
  }

	std::cout << std::endl;

	return 0;
}

<|endoftext|>