<commit_before>/*
 * mpu6050_node.cpp
 * Copyright (c) 2017, Robot Mitya.
 * 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.
 *     * Neither the name of the Robot Mitya nor the names of its
 *       contributors may be used to endorse or promote products derived from
 *       this software without specific prior written permission.
 *
 * 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 OWNER 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.
 *
 *  Created on: Dec 3, 2017
 *      Author: Dmitry Dzakhov
 */

#include <ros/ros.h>
#include <sensor_msgs/Imu.h>
#include "std_msgs/String.h"
#include <wiringPi.h>
#include <wiringPiI2C.h>
#include "consts.h"
#include "mpu6050_helper.h"
#include "madgwick.h"

#define VALUES_TO_CALIBRATE 1000

class Mpu6050Node
{
public:
  Mpu6050Node();
  void readImuData(float *vX, float *vY, float *vZ, float *aX, float *aY, float *aZ);
  bool performingCalibration(float vX, float vY, float vZ);

  void fillImuMessage(const sensor_msgs::ImuPtr& msg, float vX, float vY, float vZ, float aX, float aY, float aZ);
  void publishImuMessage(const sensor_msgs::ImuPtr& msg);
private:
  int i2cAddress_;
  int fileDescriptor_;
  uint8_t buffer_[14];
  float gyroFactor_;

  float readWord2c(int addr);

  // Topic RM_IMU_TOPIC_NAME ('imu') publisher:
  ros::Publisher imuPublisher_;

  ros::Subscriber imuInputSubscriber_;
  void imuInputCallback(const std_msgs::StringConstPtr& msg);

  MpuHelper mpuHelper_;

  ros::Time prevStamp_;
  uint32_t prevSeq_;
  MadgwickImu madgwick_;

  uint32_t seq_;
};

const int PWR_MGMT_1 = 0x6B;

Mpu6050Node::Mpu6050Node()
{
  ros::NodeHandle privateNodeHandle("~");
  privateNodeHandle.param("i2c_address", i2cAddress_, 0x68);
//  privateNodeHandle.

  // Connect to device.
  fileDescriptor_ = wiringPiI2CSetup(i2cAddress_);
  if (fileDescriptor_ == -1)
  {
    ROS_ERROR("No i2c device found?");
    return;
  }
  // Device starts in sleep mode so wake it up.
  wiringPiI2CWriteReg16(fileDescriptor_, PWR_MGMT_1, 0);

  ros::NodeHandle nodeHandle(RM_NAMESPACE);
  imuPublisher_ = nodeHandle.advertise<sensor_msgs::Imu>(RM_HEAD_IMU_OUTPUT_TOPIC_NAME, 100);

  imuInputSubscriber_ = nodeHandle.subscribe(RM_HEAD_IMU_INPUT_TOPIC_NAME, 10, &Mpu6050Node::imuInputCallback, this);

  seq_ = 0;
  gyroFactor_ = 3.141592654f / 180 / 131;

  prevStamp_ = ros::Time::now();
  prevSeq_ = 0;
  madgwick_.center();
}

float Mpu6050Node::readWord2c(int addr)
{
  uint16_t val = wiringPiI2CReadReg16(fileDescriptor_, addr);
  uint16_t swappedVal = (val >> 8) | (val << 8);
  return float((swappedVal >= 0x8000) ? -((65535 - swappedVal) + 1) : swappedVal);
}

void Mpu6050Node::readImuData(float *vX, float *vY, float *vZ, float *aX, float *aY, float *aZ)
{
  // Read gyroscope values.
  // At default sensitivity of 250deg/s we need to scale by 131.
  *vX = -readWord2c(0x47) * gyroFactor_; // -z (caused by chip orientation in robot)
  *vY = readWord2c(0x45) * gyroFactor_;  // y
  *vZ = readWord2c(0x43) * gyroFactor_;  // x (caused by chip orientation in robot)

  // Read accelerometer values.
  // At default sensitivity of 2g we need to scale by 16384.
  // Note: at "level" x = y = 0 but z = 1 (i.e. gravity)
  // But! Imu message documentations say acceleration should be in m/2 so need to *9.807
  const float la_rescale = 16384.0 / 9.807;
  *aX = -readWord2c(0x3f) / la_rescale; // -z (caused by chip orientation in robot)
  *aY = readWord2c(0x3d) / la_rescale; // y
  *aZ = readWord2c(0x3b) / la_rescale; // x (caused by chip orientation in robot)

  mpuHelper_.correctMpuData(vX, vY, vZ);
}

void Mpu6050Node::fillImuMessage(const sensor_msgs::ImuPtr& msg, float vX, float vY, float vZ, float aX, float aY, float aZ)
{
  msg->header.stamp = ros::Time::now();
  msg->header.seq = seq_++;
  msg->header.frame_id = '0';  // no frame

  msg->angular_velocity.x = vX;
  msg->angular_velocity.y = vY;
  msg->angular_velocity.z = vZ;

  msg->linear_acceleration.x = aX;
  msg->linear_acceleration.y = aY;
  msg->linear_acceleration.z = aZ;

  ros::Duration deltaTime = msg->header.stamp - prevStamp_;
  prevStamp_ = msg->header.stamp;
  madgwick_.update(deltaTime.toSec(), vX, vY, vZ, aX, aY, aZ);

  tf2Scalar qX, qY, qZ, qW;
  madgwick_.getQuaternion(qX, qY, qZ, qW);
  msg->orientation.x = qX;
  msg->orientation.y = qY;
  msg->orientation.z = qZ;
  msg->orientation.w = qW;
}

void Mpu6050Node::publishImuMessage(const sensor_msgs::ImuPtr& msg)
{
  imuPublisher_.publish(msg);
}

void Mpu6050Node::imuInputCallback(const std_msgs::StringConstPtr& msg)
{
  if (msg->data.compare("calibrate") == 0)
  {
    ROS_INFO("Starting to calibrate head IMU...");
    mpuHelper_.startCalibration();
    madgwick_.center();
  }
  else if (msg->data.compare("center") == 0)
  {
    ROS_INFO("Center head IMU...");
    madgwick_.center();
  }
  else if (msg->data.compare("configuration") == 0)
  {
    uint8_t gyroConfig = wiringPiI2CReadReg8(fileDescriptor_, 27);
    uint8_t accConfig = wiringPiI2CReadReg8(fileDescriptor_, 28);
    ROS_INFO("GYRO_CONFIG (register 27) = %d    ACCEL_CONFIG (register 28) = %d", gyroConfig, accConfig);
  }
  else
  {
    ROS_ERROR("%s.%s: Unknown command \"%s\"", RM_MPU6050_NODE_NAME, RM_HEAD_IMU_INPUT_TOPIC_NAME, msg->data.c_str());
  }
}

bool Mpu6050Node::performingCalibration(float vX, float vY, float vZ)
{
  return mpuHelper_.processCalibration(vX, vY, vZ);
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, RM_MPU6050_NODE_NAME);

  Mpu6050Node mpu6050Node;
  sensor_msgs::ImuPtr imuPrt(new sensor_msgs::Imu());

  float vX, vY, vZ, aX, aY, aZ;
  ros::Rate rate(50);  // hz
  while(ros::ok())
  {
    mpu6050Node.readImuData(&vX, &vY, &vZ, &aX, &aY, &aZ);

    if (!mpu6050Node.performingCalibration(vX, vY, vZ))
    {
      mpu6050Node.fillImuMessage(imuPrt, vX, vY, vZ, aX, aY, aZ);
      mpu6050Node.publishImuMessage(imuPrt);
    }

    ros::spinOnce();
    rate.sleep();
  }
  return 0;
}
<commit_msg>#12 IMU: mpu6050_node calibration fix<commit_after>/*
 * mpu6050_node.cpp
 * Copyright (c) 2017, Robot Mitya.
 * 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.
 *     * Neither the name of the Robot Mitya nor the names of its
 *       contributors may be used to endorse or promote products derived from
 *       this software without specific prior written permission.
 *
 * 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 OWNER 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.
 *
 *  Created on: Dec 3, 2017
 *      Author: Dmitry Dzakhov
 */

#include <ros/ros.h>
#include <sensor_msgs/Imu.h>
#include "std_msgs/String.h"
#include <wiringPi.h>
#include <wiringPiI2C.h>
#include "consts.h"
#include "mpu6050_helper.h"
#include "madgwick.h"

#define VALUES_TO_CALIBRATE 1000

class Mpu6050Node
{
public:
  Mpu6050Node();
  void readImuData(float *vX, float *vY, float *vZ, float *aX, float *aY, float *aZ);
  bool performingCalibration(float vX, float vY, float vZ);

  void fillImuMessage(const sensor_msgs::ImuPtr& msg, float vX, float vY, float vZ, float aX, float aY, float aZ);
  void publishImuMessage(const sensor_msgs::ImuPtr& msg);
  void center();
private:
  int i2cAddress_;
  int fileDescriptor_;
  uint8_t buffer_[14];
  float gyroFactor_;

  float readWord2c(int addr);

  // Topic RM_IMU_TOPIC_NAME ('imu') publisher:
  ros::Publisher imuPublisher_;

  ros::Subscriber imuInputSubscriber_;
  void imuInputCallback(const std_msgs::StringConstPtr& msg);

  MpuHelper mpuHelper_;

  ros::Time prevStamp_;
  uint32_t prevSeq_;
  MadgwickImu madgwick_;

  uint32_t seq_;
};

const int PWR_MGMT_1 = 0x6B;

Mpu6050Node::Mpu6050Node()
{
  ros::NodeHandle privateNodeHandle("~");
  privateNodeHandle.param("i2c_address", i2cAddress_, 0x68);
//  privateNodeHandle.

  // Connect to device.
  fileDescriptor_ = wiringPiI2CSetup(i2cAddress_);
  if (fileDescriptor_ == -1)
  {
    ROS_ERROR("No i2c device found?");
    return;
  }
  // Device starts in sleep mode so wake it up.
  wiringPiI2CWriteReg16(fileDescriptor_, PWR_MGMT_1, 0);

  ros::NodeHandle nodeHandle(RM_NAMESPACE);
  imuPublisher_ = nodeHandle.advertise<sensor_msgs::Imu>(RM_HEAD_IMU_OUTPUT_TOPIC_NAME, 100);

  imuInputSubscriber_ = nodeHandle.subscribe(RM_HEAD_IMU_INPUT_TOPIC_NAME, 10, &Mpu6050Node::imuInputCallback, this);

  seq_ = 0;
  gyroFactor_ = 3.141592654f / 180 / 131;

  prevStamp_ = ros::Time::now();
  prevSeq_ = 0;
  madgwick_.center();
}

float Mpu6050Node::readWord2c(int addr)
{
  uint16_t val = wiringPiI2CReadReg16(fileDescriptor_, addr);
  uint16_t swappedVal = (val >> 8) | (val << 8);
  return float((swappedVal >= 0x8000) ? -((65535 - swappedVal) + 1) : swappedVal);
}

void Mpu6050Node::readImuData(float *vX, float *vY, float *vZ, float *aX, float *aY, float *aZ)
{
  // Read gyroscope values.
  // At default sensitivity of 250deg/s we need to scale by 131.
  *vX = -readWord2c(0x47) * gyroFactor_; // -z (caused by chip orientation in robot)
  *vY = readWord2c(0x45) * gyroFactor_;  // y
  *vZ = readWord2c(0x43) * gyroFactor_;  // x (caused by chip orientation in robot)

  // Read accelerometer values.
  // At default sensitivity of 2g we need to scale by 16384.
  // Note: at "level" x = y = 0 but z = 1 (i.e. gravity)
  // But! Imu message documentations say acceleration should be in m/2 so need to *9.807
  const float la_rescale = 16384.0 / 9.807;
  *aX = -readWord2c(0x3f) / la_rescale; // -z (caused by chip orientation in robot)
  *aY = readWord2c(0x3d) / la_rescale; // y
  *aZ = readWord2c(0x3b) / la_rescale; // x (caused by chip orientation in robot)

  mpuHelper_.correctMpuData(vX, vY, vZ);
}

void Mpu6050Node::fillImuMessage(const sensor_msgs::ImuPtr& msg, float vX, float vY, float vZ, float aX, float aY, float aZ)
{
  msg->header.stamp = ros::Time::now();
  msg->header.seq = seq_++;
  msg->header.frame_id = '0';  // no frame

  msg->angular_velocity.x = vX;
  msg->angular_velocity.y = vY;
  msg->angular_velocity.z = vZ;

  msg->linear_acceleration.x = aX;
  msg->linear_acceleration.y = aY;
  msg->linear_acceleration.z = aZ;

  ros::Duration deltaTime = msg->header.stamp - prevStamp_;
  prevStamp_ = msg->header.stamp;
  madgwick_.update(deltaTime.toSec(), vX, vY, vZ, aX, aY, aZ);

  tf2Scalar qX, qY, qZ, qW;
  madgwick_.getQuaternion(qX, qY, qZ, qW);
  msg->orientation.x = qX;
  msg->orientation.y = qY;
  msg->orientation.z = qZ;
  msg->orientation.w = qW;
}

void Mpu6050Node::publishImuMessage(const sensor_msgs::ImuPtr& msg)
{
  imuPublisher_.publish(msg);
}

void Mpu6050Node::imuInputCallback(const std_msgs::StringConstPtr& msg)
{
  if (msg->data.compare("calibrate") == 0)
  {
    ROS_INFO("Starting to calibrate head IMU...");
    mpuHelper_.startCalibration();
    //madgwick_.center();
  }
  else if (msg->data.compare("center") == 0)
  {
    ROS_INFO("Center head IMU...");
    madgwick_.center();
  }
  else if (msg->data.compare("configuration") == 0)
  {
    uint8_t gyroConfig = wiringPiI2CReadReg8(fileDescriptor_, 27);
    uint8_t accConfig = wiringPiI2CReadReg8(fileDescriptor_, 28);
    ROS_INFO("GYRO_CONFIG (register 27) = %d    ACCEL_CONFIG (register 28) = %d", gyroConfig, accConfig);
  }
  else
  {
    ROS_ERROR("%s.%s: Unknown command \"%s\"", RM_MPU6050_NODE_NAME, RM_HEAD_IMU_INPUT_TOPIC_NAME, msg->data.c_str());
  }
}

bool Mpu6050Node::performingCalibration(float vX, float vY, float vZ)
{
  return mpuHelper_.processCalibration(vX, vY, vZ);
}

void Mpu6050Node::center()
{
  madgwick_.center();
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, RM_MPU6050_NODE_NAME);

  Mpu6050Node mpu6050Node;
  sensor_msgs::ImuPtr imuPrt(new sensor_msgs::Imu());

  float vX, vY, vZ, aX, aY, aZ;
  ros::Rate rate(50);  // hz
  bool prevPerformingCalibration = false;
  bool performingCalibration;
  while(ros::ok())
  {
    mpu6050Node.readImuData(&vX, &vY, &vZ, &aX, &aY, &aZ);

    performingCalibration = mpu6050Node.performingCalibration(vX, vY, vZ);
    if (!performingCalibration)
    {
      mpu6050Node.fillImuMessage(imuPrt, vX, vY, vZ, aX, aY, aZ);
      mpu6050Node.publishImuMessage(imuPrt);
    }
    else if (prevPerformingCalibration && !performingCalibration)
    {
      // Calibration is over:
      mpu6050Node.center();
    }
    prevPerformingCalibration = performingCalibration;

    ros::spinOnce();
    rate.sleep();
  }
  return 0;
}
<|endoftext|>


<commit_before>/*
    This file is part of Kontact.
    Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
    Copyright (c) 2005-2006 Allen Winter <winter@kde.org>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include <QCursor>
#include <QLabel>
#include <QLayout>
#include <QPixmap>
#include <QVBoxLayout>
#include <QGridLayout>
#include <QEvent>

#include <kdialog.h>
#include <kglobal.h>
#include <kicon.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kparts/part.h>
#include <kmenu.h>
#include <kstandarddirs.h>
#include <kurllabel.h>

#include <kcal/calendar.h>
#include <kcal/resourcecalendar.h>
#include <kcal/resourcelocal.h>
#include <kcal/todo.h>
#include <kcal/incidenceformatter.h>
#include <libkdepim/kpimprefs.h>

#include "core.h"
#include "plugin.h"
#include "todoplugin.h"

#include "korganizer/stdcalendar.h"
#include "korganizer/koglobals.h"
#include "korganizer/incidencechanger.h"

#include "todosummarywidget.h"
#include "korganizerinterface.h"

TodoSummaryWidget::TodoSummaryWidget( TodoPlugin *plugin,
                                      QWidget *parent )
  : Kontact::Summary( parent ), mPlugin( plugin )
{
  QVBoxLayout *mainLayout = new QVBoxLayout( this );
  mainLayout->setSpacing( 3 );
  mainLayout->setMargin( 3 );

  QPixmap icon =
    KIconLoader::global()->loadIcon( "view-pim-tasks",
                                     KIconLoader::Desktop, KIconLoader::SizeMedium );
  QWidget *header = createHeader( this, icon, i18n( "Pending To-dos" ) );
  mainLayout->addWidget( header );

  mLayout = new QGridLayout();
  mainLayout->addItem( mLayout );
  mLayout->setSpacing( 3 );
  mLayout->setRowStretch( 6, 1 );

  mCalendar = KOrg::StdCalendar::self();
  mCalendar->load();

  connect( mCalendar, SIGNAL( calendarChanged() ), SLOT( updateView() ) );
  connect( mPlugin->core(), SIGNAL( dayChanged( const QDate& ) ),
           SLOT( updateView() ) );

  updateView();
}

TodoSummaryWidget::~TodoSummaryWidget()
{
}

void TodoSummaryWidget::updateView()
{
  qDeleteAll( mLabels );
  mLabels.clear();

  KConfig _config( "kcmtodosummaryrc" );
  KConfigGroup config(&_config, "Days" );
  int mDaysToGo = config.readEntry( "DaysToShow", 7 );

  config.changeGroup( "Hide" );
  mHideInProgress = config.readEntry( "InProgress", false );
  mHideOverdue = config.readEntry( "Overdue", false );
  mHideCompleted = config.readEntry( "Completed", true );
  mHideOpenEnded = config.readEntry( "OpenEnded", true );
  mHideNotStarted = config.readEntry( "NotStarted", false );

  // for each todo,
  //   if it passes the filter, append to a list
  //   else continue
  // sort todolist by summary
  // sort todolist by priority
  // sort todolist by due-date
  // print todolist

  // the filter is created by the configuration summary options, but includes
  //    days to go before to-do is due
  //    which types of to-dos to hide

  KCal::Todo::List prList;

  Q_FOREACH ( KCal::Todo *todo, mCalendar->todos() ) {
    if ( todo->hasDueDate() ) {
      int daysTo = QDate::currentDate().daysTo( todo->dtDue().date() );
      if ( daysTo >= mDaysToGo )
        continue;
    }

    if ( mHideOverdue && overdue( todo ) )
      continue;
    if ( mHideInProgress && inProgress( todo ) )
      continue;
    if ( mHideCompleted && completed( todo ) )
      continue;
    if ( mHideOpenEnded && openEnded( todo ) )
      continue;
    if ( mHideNotStarted && notStarted( todo ) )
      continue;

    prList.append( todo );
  }
  if ( !prList.isEmpty() ) {
    prList = KCal::Calendar::sortTodos( &prList,
                                        KCal::TodoSortSummary,
                                        KCal::SortDirectionAscending );
    prList = KCal::Calendar::sortTodos( &prList,
                                        KCal::TodoSortPriority,
                                        KCal::SortDirectionAscending );
    prList = KCal::Calendar::sortTodos( &prList,
                                        KCal::TodoSortDueDate,
                                        KCal::SortDirectionAscending );
  }

  // The to-do print consists of the following fields:
  //  icon:due date:days-to-go:priority:summary:status
  // where,
  //   the icon is the typical to-do icon
  //   the due date it the to-do due date
  //   the days-to-go/past is the #days until/since the to-do is due
  //     this field is left blank if the to-do is open-ended
  //   the priority is the to-do priority
  //   the summary is the to-do summary
  //   the status is comma-separated list of:
  //     overdue
  //     in-progress (started, or >0% completed)
  //     complete (100% completed)
  //     open-ended
  //     not-started (no start date and 0% completed)

  // No reason to show the date year
  QString savefmt = KGlobal::locale()->dateFormat();
  KGlobal::locale()->setDateFormat( KGlobal::locale()->
                                    dateFormat().replace( 'Y', ' ' ) );

  int counter = 0;
  QLabel *label = 0;

  if ( !prList.isEmpty() ) {

    KIconLoader loader( "korganizer" );
    QPixmap pm = loader.loadIcon( "view-calendar-tasks", KIconLoader::Small );

    QString str;

    Q_FOREACH ( KCal::Todo *todo, prList ) {
      bool makeBold = false;
      int daysTo = -1;

      // Icon label
      label = new QLabel( this );
      label->setPixmap( pm );
      label->setMaximumWidth( label->minimumSizeHint().width() );
      mLayout->addWidget( label, counter, 0 );
      mLabels.append( label );

      // Due date label
      str = "";
      if ( todo->hasDueDate() ) {
        daysTo = QDate::currentDate().daysTo( todo->dtDue().date() );

        if ( daysTo == 0 ) {
          makeBold = true;
          str = i18n( "Today" );
        } else if ( daysTo == 1 ) {
          str = i18n( "Tomorrow" );
        } else {
          str = KGlobal::locale()->formatDate( todo->dtDue().date() );
        }
      }

      label = new QLabel( str, this );
      label->setAlignment( Qt::AlignLeft | Qt::AlignVCenter );
      mLayout->addWidget( label, counter, 1 );
      mLabels.append( label );
      if ( makeBold ) {
        QFont font = label->font();
        font.setBold( true );
        label->setFont( font );
      }

      // Days togo/ago label
      str = "";
      if ( todo->hasDueDate() ) {
        if ( daysTo > 0 ) {
          str = i18np( "in 1 day", "in %1 days", daysTo );
        } else if ( daysTo < 0 ) {
          str = i18np( "1 day ago", "%1 days ago", -daysTo );
        } else{
          str = i18n( "due" );
        }
      }
      label = new QLabel( str, this );
      label->setAlignment( Qt::AlignLeft | Qt::AlignVCenter );
      mLayout->addWidget( label, counter, 2 );
      mLabels.append( label );

      // Priority label
      str = '[' + QString::number( todo->priority() ) + ']';
      label = new QLabel( str, this );
      label->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
      mLayout->addWidget( label, counter, 3 );
      mLabels.append( label );

      // Summary label
      str = todo->summary();
      if ( todo->relatedTo() ) { // show parent only, not entire ancestry
        str = todo->relatedTo()->summary() + ':' + str;
      }

      KUrlLabel *urlLabel = new KUrlLabel( this );
      urlLabel->setText( str );
      urlLabel->setUrl( todo->uid() );
      urlLabel->installEventFilter( this );
      urlLabel->setTextFormat( Qt::RichText );
      mLayout->addWidget( urlLabel, counter, 4 );
      mLabels.append( urlLabel );

      connect( urlLabel, SIGNAL( leftClickedUrl( const QString& ) ),
               this, SLOT( viewTodo( const QString& ) ) );
      connect( urlLabel, SIGNAL( rightClickedUrl( const QString& ) ),
               this, SLOT( popupMenu( const QString& ) ) );

      QString tipText( KCal::IncidenceFormatter::toolTipString( todo, true ) );
      if ( !tipText.isEmpty() ) {
        urlLabel->setToolTip( tipText );
      }

      // State text label
      str = stateStr( todo );
      label = new QLabel( str, this );
      label->setAlignment( Qt::AlignLeft | Qt::AlignVCenter );
      mLayout->addWidget( label, counter, 5 );
      mLabels.append( label );

      counter++;
    }
  } //foreach

  if ( counter == 0 ) {
    QLabel *noTodos = new QLabel(
      i18np( "No pending to-dos due within the next day",
            "No pending to-dos due within the next %1 days",
            mDaysToGo ), this );
    noTodos->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
    mLayout->addWidget( noTodos, 0, 2 );
    mLabels.append( noTodos );
  }

  Q_FOREACH( label, mLabels )
    label->show();

  KGlobal::locale()->setDateFormat( savefmt );
}

void TodoSummaryWidget::viewTodo( const QString &uid )
{
  mPlugin->core()->selectPlugin( "kontact_todoplugin" );//ensure loaded
  OrgKdeKorganizerKorganizerInterface korganizer( "org.kde.korganizer", "/Korganizer", QDBusConnection::sessionBus());
  korganizer.editIncidence( uid );
}

void TodoSummaryWidget::removeTodo( const QString &uid )
{
  mPlugin->core()->selectPlugin( "kontact_todoplugin" );//ensure loaded
  OrgKdeKorganizerKorganizerInterface korganizer( "org.kde.korganizer", "/Korganizer", QDBusConnection::sessionBus());
  korganizer.deleteIncidence( uid, false );
}

void TodoSummaryWidget::completeTodo( const QString &uid )
{
  KCal::Todo *todo = mCalendar->todo( uid );
  IncidenceChanger *changer = new IncidenceChanger( mCalendar, this );
  if ( !todo->isReadOnly() && changer->beginChange( todo ) ) {
    KCal::Todo *oldTodo = todo->clone();
    todo->setCompleted( KDateTime::currentLocalDateTime() );
    changer->changeIncidence( oldTodo, todo, KOGlobals::COMPLETION_MODIFIED );
    changer->endChange( todo );
    delete oldTodo;
    updateView();
  }
}

void TodoSummaryWidget::popupMenu( const QString &uid )
{
  KMenu popup( this );
  QAction *editIt = popup.addAction( i18n( "&Edit To-do..." ) );
  QAction *delIt = popup.addAction( i18n( "&Delete To-do" ) );
  delIt->setIcon( KIconLoader::global()->
                  loadIcon( "edit-delete", KIconLoader::Small) );
  QAction *doneIt = 0;
  KCal::Todo *todo = mCalendar->todo( uid );
  if ( !todo->isCompleted() ) {
    doneIt = popup.addAction( i18n( "&Mark To-do Completed" ) );
    doneIt->setIcon( KIconLoader::global()->
                     loadIcon( "task-complete", KIconLoader::Small) );
  }
  // TODO: add icons to the menu actions

  const QAction *selectedAction = popup.exec( QCursor::pos() );
  if ( selectedAction == editIt ) {
    viewTodo( uid );
  } else if ( selectedAction == delIt ) {
    removeTodo( uid );
  } else if ( doneIt && selectedAction == doneIt ) {
    completeTodo( uid );
  }
}

bool TodoSummaryWidget::eventFilter( QObject *obj, QEvent* e )
{
  if ( obj->inherits( "KUrlLabel" ) ) {
    KUrlLabel* label = static_cast<KUrlLabel*>( obj );
    if ( e->type() == QEvent::Enter )
      emit message( i18n( "Edit To-do: \"%1\"", label->text() ) );
    if ( e->type() == QEvent::Leave )
      emit message( QString::null );	//krazy:exclude=nullstrassign for old broken gcc
  }

  return Kontact::Summary::eventFilter( obj, e );
}

QStringList TodoSummaryWidget::configModules() const
{
  return QStringList( "kcmtodosummary.desktop" );
}

bool TodoSummaryWidget::overdue( KCal::Todo *todo )
{
  if ( todo->hasDueDate() && !todo->isCompleted() &&
       todo->dtDue().date() < QDate::currentDate() )
    return true;

  return false;
}

bool TodoSummaryWidget::starts( KCal::Todo *todo )
{
  if ( todo->hasStartDate() &&
       todo->dtStart().date() == QDate::currentDate() )
    return true;

  return false;
}

bool TodoSummaryWidget::completed( KCal::Todo *todo )
{
  return todo->isCompleted();
}

bool TodoSummaryWidget::openEnded( KCal::Todo *todo )
{
  if ( !todo->hasDueDate() && !todo->isCompleted() )
    return true;
  else
    return false;
}

bool TodoSummaryWidget::inProgress( KCal::Todo *todo )
{
  if ( todo->percentComplete() > 0 )
    return true;

  if ( todo->hasStartDate() && todo->hasDueDate() &&
       todo->dtStart().date() < QDate::currentDate() &&
       QDate::currentDate() < todo->dtDue().date() )
    return true;

  return false;
}

bool TodoSummaryWidget::notStarted( KCal::Todo *todo )
{
  if ( todo->percentComplete() > 0 )
    return false;

  if ( !todo->hasStartDate() )
    return false;

  if ( todo->dtStart().date() >= QDate::currentDate() )
    return false;

  return true;
}

const QString TodoSummaryWidget::stateStr( KCal::Todo *todo )
{
  QString str1, str2;

  if ( openEnded( todo ) ) {
    str1 = i18n( "open-ended" );
  } else if ( overdue( todo ) ) {
    str1 = i18n( "overdue" );
  } else if ( starts( todo ) ) {
    str1 = i18n( "starts today" );
  }

  if ( notStarted( todo ) ) {
    str2 += i18n( "not-started" );
  } else if ( completed( todo ) ) {
    str2 += i18n( "completed" );
  } else if ( inProgress( todo ) ) {
    str2 += i18n( "in-progress " );
    str2 += " (" + QString::number( todo->percentComplete() ) + "%)";
  }

  if ( !str1.isEmpty() && !str2.isEmpty() )
    str1 += i18nc( "Separator for status like this: overdue, completed", "," );

  return str1 + str2;
}

#include "todosummarywidget.moc"
<commit_msg>QDate::currentDate().daysTo( todo->dtDue().date() ) returns negative number if the due date is invalid, thus the summary displays 2,451,561 days due. http://img515.imageshack.us/my.php?image=todonoduedateed3.png<commit_after>/*
    This file is part of Kontact.
    Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
    Copyright (c) 2005-2006 Allen Winter <winter@kde.org>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include <QCursor>
#include <QLabel>
#include <QLayout>
#include <QPixmap>
#include <QVBoxLayout>
#include <QGridLayout>
#include <QEvent>

#include <kdialog.h>
#include <kglobal.h>
#include <kicon.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kparts/part.h>
#include <kmenu.h>
#include <kstandarddirs.h>
#include <kurllabel.h>

#include <kcal/calendar.h>
#include <kcal/resourcecalendar.h>
#include <kcal/resourcelocal.h>
#include <kcal/todo.h>
#include <kcal/incidenceformatter.h>
#include <libkdepim/kpimprefs.h>

#include "core.h"
#include "plugin.h"
#include "todoplugin.h"

#include "korganizer/stdcalendar.h"
#include "korganizer/koglobals.h"
#include "korganizer/incidencechanger.h"

#include "todosummarywidget.h"
#include "korganizerinterface.h"

TodoSummaryWidget::TodoSummaryWidget( TodoPlugin *plugin,
                                      QWidget *parent )
  : Kontact::Summary( parent ), mPlugin( plugin )
{
  QVBoxLayout *mainLayout = new QVBoxLayout( this );
  mainLayout->setSpacing( 3 );
  mainLayout->setMargin( 3 );

  QPixmap icon =
    KIconLoader::global()->loadIcon( "view-pim-tasks",
                                     KIconLoader::Desktop, KIconLoader::SizeMedium );
  QWidget *header = createHeader( this, icon, i18n( "Pending To-dos" ) );
  mainLayout->addWidget( header );

  mLayout = new QGridLayout();
  mainLayout->addItem( mLayout );
  mLayout->setSpacing( 3 );
  mLayout->setRowStretch( 6, 1 );

  mCalendar = KOrg::StdCalendar::self();
  mCalendar->load();

  connect( mCalendar, SIGNAL( calendarChanged() ), SLOT( updateView() ) );
  connect( mPlugin->core(), SIGNAL( dayChanged( const QDate& ) ),
           SLOT( updateView() ) );

  updateView();
}

TodoSummaryWidget::~TodoSummaryWidget()
{
}

void TodoSummaryWidget::updateView()
{
  qDeleteAll( mLabels );
  mLabels.clear();

  KConfig _config( "kcmtodosummaryrc" );
  KConfigGroup config(&_config, "Days" );
  int mDaysToGo = config.readEntry( "DaysToShow", 7 );

  config.changeGroup( "Hide" );
  mHideInProgress = config.readEntry( "InProgress", false );
  mHideOverdue = config.readEntry( "Overdue", false );
  mHideCompleted = config.readEntry( "Completed", true );
  mHideOpenEnded = config.readEntry( "OpenEnded", true );
  mHideNotStarted = config.readEntry( "NotStarted", false );

  // for each todo,
  //   if it passes the filter, append to a list
  //   else continue
  // sort todolist by summary
  // sort todolist by priority
  // sort todolist by due-date
  // print todolist

  // the filter is created by the configuration summary options, but includes
  //    days to go before to-do is due
  //    which types of to-dos to hide

  KCal::Todo::List prList;

  Q_FOREACH ( KCal::Todo *todo, mCalendar->todos() ) {
    if ( todo->hasDueDate() ) {
      int daysTo = QDate::currentDate().daysTo( todo->dtDue().date() );
      if ( daysTo >= mDaysToGo )
        continue;
    }

    if ( mHideOverdue && overdue( todo ) )
      continue;
    if ( mHideInProgress && inProgress( todo ) )
      continue;
    if ( mHideCompleted && completed( todo ) )
      continue;
    if ( mHideOpenEnded && openEnded( todo ) )
      continue;
    if ( mHideNotStarted && notStarted( todo ) )
      continue;

    prList.append( todo );
  }
  if ( !prList.isEmpty() ) {
    prList = KCal::Calendar::sortTodos( &prList,
                                        KCal::TodoSortSummary,
                                        KCal::SortDirectionAscending );
    prList = KCal::Calendar::sortTodos( &prList,
                                        KCal::TodoSortPriority,
                                        KCal::SortDirectionAscending );
    prList = KCal::Calendar::sortTodos( &prList,
                                        KCal::TodoSortDueDate,
                                        KCal::SortDirectionAscending );
  }

  // The to-do print consists of the following fields:
  //  icon:due date:days-to-go:priority:summary:status
  // where,
  //   the icon is the typical to-do icon
  //   the due date it the to-do due date
  //   the days-to-go/past is the #days until/since the to-do is due
  //     this field is left blank if the to-do is open-ended
  //   the priority is the to-do priority
  //   the summary is the to-do summary
  //   the status is comma-separated list of:
  //     overdue
  //     in-progress (started, or >0% completed)
  //     complete (100% completed)
  //     open-ended
  //     not-started (no start date and 0% completed)

  // No reason to show the date year
  QString savefmt = KGlobal::locale()->dateFormat();
  KGlobal::locale()->setDateFormat( KGlobal::locale()->
                                    dateFormat().replace( 'Y', ' ' ) );

  int counter = 0;
  QLabel *label = 0;

  if ( !prList.isEmpty() ) {

    KIconLoader loader( "korganizer" );
    QPixmap pm = loader.loadIcon( "view-calendar-tasks", KIconLoader::Small );

    QString str;

    Q_FOREACH ( KCal::Todo *todo, prList ) {
      bool makeBold = false;
      int daysTo = -1;

      // Icon label
      label = new QLabel( this );
      label->setPixmap( pm );
      label->setMaximumWidth( label->minimumSizeHint().width() );
      mLayout->addWidget( label, counter, 0 );
      mLabels.append( label );

      // Due date label
      str = "";
      if ( todo->hasDueDate() && todo->dtDue().date().isValid() ) {
        daysTo = QDate::currentDate().daysTo( todo->dtDue().date() );

        if ( daysTo == 0 ) {
          makeBold = true;
          str = i18n( "Today" );
        } else if ( daysTo == 1 ) {
          str = i18n( "Tomorrow" );
        } else {
          str = KGlobal::locale()->formatDate( todo->dtDue().date() );
        }
      }

      label = new QLabel( str, this );
      label->setAlignment( Qt::AlignLeft | Qt::AlignVCenter );
      mLayout->addWidget( label, counter, 1 );
      mLabels.append( label );
      if ( makeBold ) {
        QFont font = label->font();
        font.setBold( true );
        label->setFont( font );
      }

      // Days togo/ago label
      str = "";
      if ( todo->hasDueDate() && todo->dtDue().date().isValid() ) {
        if ( daysTo > 0 ) {
          str = i18np( "in 1 day", "in %1 days", daysTo );
        } else if ( daysTo < 0 ) {
          str = i18np( "1 day ago", "%1 days ago", -daysTo );
        } else{
          str = i18n( "due" );
        }
      }
      label = new QLabel( str, this );
      label->setAlignment( Qt::AlignLeft | Qt::AlignVCenter );
      mLayout->addWidget( label, counter, 2 );
      mLabels.append( label );

      // Priority label
      str = '[' + QString::number( todo->priority() ) + ']';
      label = new QLabel( str, this );
      label->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
      mLayout->addWidget( label, counter, 3 );
      mLabels.append( label );

      // Summary label
      str = todo->summary();
      if ( todo->relatedTo() ) { // show parent only, not entire ancestry
        str = todo->relatedTo()->summary() + ':' + str;
      }

      KUrlLabel *urlLabel = new KUrlLabel( this );
      urlLabel->setText( str );
      urlLabel->setUrl( todo->uid() );
      urlLabel->installEventFilter( this );
      urlLabel->setTextFormat( Qt::RichText );
      mLayout->addWidget( urlLabel, counter, 4 );
      mLabels.append( urlLabel );

      connect( urlLabel, SIGNAL( leftClickedUrl( const QString& ) ),
               this, SLOT( viewTodo( const QString& ) ) );
      connect( urlLabel, SIGNAL( rightClickedUrl( const QString& ) ),
               this, SLOT( popupMenu( const QString& ) ) );

      QString tipText( KCal::IncidenceFormatter::toolTipString( todo, true ) );
      if ( !tipText.isEmpty() ) {
        urlLabel->setToolTip( tipText );
      }

      // State text label
      str = stateStr( todo );
      label = new QLabel( str, this );
      label->setAlignment( Qt::AlignLeft | Qt::AlignVCenter );
      mLayout->addWidget( label, counter, 5 );
      mLabels.append( label );

      counter++;
    }
  } //foreach

  if ( counter == 0 ) {
    QLabel *noTodos = new QLabel(
      i18np( "No pending to-dos due within the next day",
            "No pending to-dos due within the next %1 days",
            mDaysToGo ), this );
    noTodos->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
    mLayout->addWidget( noTodos, 0, 2 );
    mLabels.append( noTodos );
  }

  Q_FOREACH( label, mLabels )
    label->show();

  KGlobal::locale()->setDateFormat( savefmt );
}

void TodoSummaryWidget::viewTodo( const QString &uid )
{
  mPlugin->core()->selectPlugin( "kontact_todoplugin" );//ensure loaded
  OrgKdeKorganizerKorganizerInterface korganizer( "org.kde.korganizer", "/Korganizer", QDBusConnection::sessionBus());
  korganizer.editIncidence( uid );
}

void TodoSummaryWidget::removeTodo( const QString &uid )
{
  mPlugin->core()->selectPlugin( "kontact_todoplugin" );//ensure loaded
  OrgKdeKorganizerKorganizerInterface korganizer( "org.kde.korganizer", "/Korganizer", QDBusConnection::sessionBus());
  korganizer.deleteIncidence( uid, false );
}

void TodoSummaryWidget::completeTodo( const QString &uid )
{
  KCal::Todo *todo = mCalendar->todo( uid );
  IncidenceChanger *changer = new IncidenceChanger( mCalendar, this );
  if ( !todo->isReadOnly() && changer->beginChange( todo ) ) {
    KCal::Todo *oldTodo = todo->clone();
    todo->setCompleted( KDateTime::currentLocalDateTime() );
    changer->changeIncidence( oldTodo, todo, KOGlobals::COMPLETION_MODIFIED );
    changer->endChange( todo );
    delete oldTodo;
    updateView();
  }
}

void TodoSummaryWidget::popupMenu( const QString &uid )
{
  KMenu popup( this );
  QAction *editIt = popup.addAction( i18n( "&Edit To-do..." ) );
  QAction *delIt = popup.addAction( i18n( "&Delete To-do" ) );
  delIt->setIcon( KIconLoader::global()->
                  loadIcon( "edit-delete", KIconLoader::Small) );
  QAction *doneIt = 0;
  KCal::Todo *todo = mCalendar->todo( uid );
  if ( !todo->isCompleted() ) {
    doneIt = popup.addAction( i18n( "&Mark To-do Completed" ) );
    doneIt->setIcon( KIconLoader::global()->
                     loadIcon( "task-complete", KIconLoader::Small) );
  }
  // TODO: add icons to the menu actions

  const QAction *selectedAction = popup.exec( QCursor::pos() );
  if ( selectedAction == editIt ) {
    viewTodo( uid );
  } else if ( selectedAction == delIt ) {
    removeTodo( uid );
  } else if ( doneIt && selectedAction == doneIt ) {
    completeTodo( uid );
  }
}

bool TodoSummaryWidget::eventFilter( QObject *obj, QEvent* e )
{
  if ( obj->inherits( "KUrlLabel" ) ) {
    KUrlLabel* label = static_cast<KUrlLabel*>( obj );
    if ( e->type() == QEvent::Enter )
      emit message( i18n( "Edit To-do: \"%1\"", label->text() ) );
    if ( e->type() == QEvent::Leave )
      emit message( QString::null );	//krazy:exclude=nullstrassign for old broken gcc
  }

  return Kontact::Summary::eventFilter( obj, e );
}

QStringList TodoSummaryWidget::configModules() const
{
  return QStringList( "kcmtodosummary.desktop" );
}

bool TodoSummaryWidget::overdue( KCal::Todo *todo )
{
  if ( todo->hasDueDate() && !todo->isCompleted() &&
       todo->dtDue().date() < QDate::currentDate() )
    return true;

  return false;
}

bool TodoSummaryWidget::starts( KCal::Todo *todo )
{
  if ( todo->hasStartDate() &&
       todo->dtStart().date() == QDate::currentDate() )
    return true;

  return false;
}

bool TodoSummaryWidget::completed( KCal::Todo *todo )
{
  return todo->isCompleted();
}

bool TodoSummaryWidget::openEnded( KCal::Todo *todo )
{
  if ( !todo->hasDueDate() && !todo->isCompleted() )
    return true;
  else
    return false;
}

bool TodoSummaryWidget::inProgress( KCal::Todo *todo )
{
  if ( todo->percentComplete() > 0 )
    return true;

  if ( todo->hasStartDate() && todo->hasDueDate() &&
       todo->dtStart().date() < QDate::currentDate() &&
       QDate::currentDate() < todo->dtDue().date() )
    return true;

  return false;
}

bool TodoSummaryWidget::notStarted( KCal::Todo *todo )
{
  if ( todo->percentComplete() > 0 )
    return false;

  if ( !todo->hasStartDate() )
    return false;

  if ( todo->dtStart().date() >= QDate::currentDate() )
    return false;

  return true;
}

const QString TodoSummaryWidget::stateStr( KCal::Todo *todo )
{
  QString str1, str2;

  if ( openEnded( todo ) ) {
    str1 = i18n( "open-ended" );
  } else if ( overdue( todo ) ) {
    str1 = i18n( "overdue" );
  } else if ( starts( todo ) ) {
    str1 = i18n( "starts today" );
  }

  if ( notStarted( todo ) ) {
    str2 += i18n( "not-started" );
  } else if ( completed( todo ) ) {
    str2 += i18n( "completed" );
  } else if ( inProgress( todo ) ) {
    str2 += i18n( "in-progress " );
    str2 += " (" + QString::number( todo->percentComplete() ) + "%)";
  }

  if ( !str1.isEmpty() && !str2.isEmpty() )
    str1 += i18nc( "Separator for status like this: overdue, completed", "," );

  return str1 + str2;
}

#include "todosummarywidget.moc"
<|endoftext|>


<commit_before><commit_msg>Update hashing<commit_after><|endoftext|>


<commit_before>#pragma once
#include <cstdint>
#include <algorithm>
#include "error.hpp"

namespace spn {
	extern none_t none;
	template <class T>
	struct _OptionalBuff {
		uint8_t _buffer[sizeof(T)];

		_OptionalBuff() = default;
		template <class T2>
		_OptionalBuff(T2&& t) {
			operator=(std::forward<T2>(t));
		}
		template <class T2>
		void operator = (T2&& t) {
			new(_buffer) T(std::forward<T2>(t));
		}
		T& castT() { return *reinterpret_cast<T*>(_buffer); }
		const T& castCT() const { return *reinterpret_cast<const T*>(_buffer); }
		void dtor() { castT().~T(); }
	};

	template <class T>
	struct _OptionalBuff<T&> {
		T*		_buffer;

		_OptionalBuff() = default;
		_OptionalBuff(T* t): _buffer(t) {}
		template <class T2>
		_OptionalBuff(T2&& t): _buffer(&t) {}
		void operator = (T&& t) { _buffer = &t; }
		void operator = (T& t) { _buffer = &t; }
		T& castT() { return *_buffer; }
		const T& castCT() const { return *_buffer; }
		void dtor() {}
	};
	template <class T>
	struct _OptionalBuff<T*> {
		T*		_buffer;

		_OptionalBuff() = default;
		_OptionalBuff(T* t): _buffer(t) {}
		void operator = (T* t) { _buffer = t; }
		T*& castT() { return _buffer; }
		const T*& castCT() const { return _buffer; }
		void dtor() {}
	};
	//! noseq_listでboost::optionalを使おうとしたらよくわからないエラーが出たので自作してしまった
	template <class T>
	class Optional {
		private:
			_OptionalBuff<T> _buffer;
			bool	_bInit;

			void t__release() noexcept {
				_buffer.dtor();
				_bInit = false;
			}
			void _release() noexcept {
				if(_bInit)
					t__release();
			}

		public:
			const static struct _AsInitialized {} AsInitialized;
			//! コンストラクタは呼ばないけど初期化された物として扱う
			/*! ユーザーが自分でコンストラクタを呼ばないとエラーになる */
			Optional(_AsInitialized): _bInit(true) {}

			Optional(): _bInit(false) {}
			Optional(none_t): _bInit(false) {}
			Optional(const Optional<T>& t): _bInit(t) {
				if(t)
					_buffer = t._buffer.castCT();
			}
			Optional(Optional<T>&& t): _bInit(t) {
				if(t) {
					_buffer = std::move(t._buffer.castT());
					t.t__release();
				}
			}
			template <class T2>
			Optional(T2&& t, typename std::enable_if<!std::is_same<typename std::decay<T2>::type, Optional<T>>::value>::type* = nullptr): _buffer(std::forward<T2>(t)), _bInit(true) {}
			~Optional() {
				_release();
			}

			decltype(_buffer.castT()) get() {
				Assert(Trap, *this, "optional: bad_get")
				return _buffer.castT();
			}
			decltype(_buffer.castCT()) get() const {
				return _buffer.castCT();
			}
			decltype(_buffer.castT()) operator * () {
				return get();
			}
			decltype(_buffer.castCT()) operator * () const {
				return get();
			}
			operator bool () const {
				return _bInit;
			}

			typename std::add_pointer<decltype(_buffer.castT())>::type operator -> () {
				return &_buffer.castT();
			}
			typename std::add_pointer<decltype(_buffer.castCT())>::type operator -> () const {
				return &_buffer.castCT();
			}
			template <class T2>
			Optional& operator = (T2&& t) {
				_release();
				_buffer = std::forward<T2>(t);
				_bInit = true;
				return *this;
			}
			Optional& operator = (none_t) noexcept {
				_release();
				return *this;
			}
			Optional& operator = (const Optional<T>& t) {
				_release();
				if(t) {
					_buffer = t._buffer.castT();
					_bInit = true;
				}
				return *this;
			}
			Optional& operator = (Optional<T>&& t) {
				_release();
				if(t) {
					_buffer = std::move(t._buffer.castT());
					t.t__release();
					_bInit = true;
				}
				return *this;
			}
			Optional& operator = (_AsInitialized) noexcept {
				_release();
				_bInit = true;
				return *this;
			}
	};
	template <class T>
	const typename Optional<T>::_AsInitialized Optional<T>::AsInitialized{};
}
<commit_msg>optionalバッファのアラインメント調整<commit_after>#pragma once
#include <cstdint>
#include <algorithm>
#include "error.hpp"
#include "bits.hpp"

namespace spn {
	struct alignas(16) Align128 {};
	struct alignas(32) Align256 {};
	struct alignas(64) Align512 {};
	using CTAlign = CType<uint8_t, uint16_t, uint32_t, uint64_t, Align128, Align256, Align512>;
	template <int NByte, int AByte>
	struct AlignedBuff {
		using AlignType = typename CTAlign::template At<CTBit::MSB_N<AByte>::result>::type;
		union {
			uint8_t 	_buffer[NByte];
			AlignType	_align_dummy;
		};
	};

	extern none_t none;
	template <class T>
	struct _OptionalBuff : AlignedBuff<sizeof(T), std::alignment_of<T>::value> {
		using base = AlignedBuff<sizeof(T), std::alignment_of<T>::value>;

		_OptionalBuff() = default;
		template <class T2>
		_OptionalBuff(T2&& t) {
			operator=(std::forward<T2>(t));
		}
		template <class T2>
		void operator = (T2&& t) {
			new(base::_buffer) T(std::forward<T2>(t));
		}
		T& castT() { return *reinterpret_cast<T*>(base::_buffer); }
		const T& castCT() const { return *reinterpret_cast<const T*>(base::_buffer); }
		void dtor() { castT().~T(); }
	};

	template <class T>
	struct _OptionalBuff<T&> {
		T*		_buffer;

		_OptionalBuff() = default;
		_OptionalBuff(T* t): _buffer(t) {}
		template <class T2>
		_OptionalBuff(T2&& t): _buffer(&t) {}
		void operator = (T&& t) { _buffer = &t; }
		void operator = (T& t) { _buffer = &t; }
		T& castT() { return *_buffer; }
		const T& castCT() const { return *_buffer; }
		void dtor() {}
	};
	template <class T>
	struct _OptionalBuff<T*> {
		T*		_buffer;

		_OptionalBuff() = default;
		_OptionalBuff(T* t): _buffer(t) {}
		void operator = (T* t) { _buffer = t; }
		T*& castT() { return _buffer; }
		const T*& castCT() const { return _buffer; }
		void dtor() {}
	};
	//! noseq_listでboost::optionalを使おうとしたらよくわからないエラーが出たので自作してしまった
	template <class T>
	class Optional {
		private:
			_OptionalBuff<T> _buffer;
			bool	_bInit;

			void t__release() noexcept {
				_buffer.dtor();
				_bInit = false;
			}
			void _release() noexcept {
				if(_bInit)
					t__release();
			}

		public:
			const static struct _AsInitialized {} AsInitialized;
			//! コンストラクタは呼ばないけど初期化された物として扱う
			/*! ユーザーが自分でコンストラクタを呼ばないとエラーになる */
			Optional(_AsInitialized): _bInit(true) {}

			Optional(): _bInit(false) {}
			Optional(none_t): _bInit(false) {}
			Optional(const Optional<T>& t): _bInit(t) {
				if(t)
					_buffer = t._buffer.castCT();
			}
			Optional(Optional<T>&& t): _bInit(t) {
				if(t) {
					_buffer = std::move(t._buffer.castT());
					t.t__release();
				}
			}
			template <class T2>
			Optional(T2&& t, typename std::enable_if<!std::is_same<typename std::decay<T2>::type, Optional<T>>::value>::type* = nullptr): _buffer(std::forward<T2>(t)), _bInit(true) {}
			~Optional() {
				_release();
			}

			decltype(_buffer.castT()) get() {
				Assert(Trap, *this, "optional: bad_get")
				return _buffer.castT();
			}
			decltype(_buffer.castCT()) get() const {
				return _buffer.castCT();
			}
			decltype(_buffer.castT()) operator * () {
				return get();
			}
			decltype(_buffer.castCT()) operator * () const {
				return get();
			}
			operator bool () const {
				return _bInit;
			}

			typename std::add_pointer<decltype(_buffer.castT())>::type operator -> () {
				return &_buffer.castT();
			}
			typename std::add_pointer<decltype(_buffer.castCT())>::type operator -> () const {
				return &_buffer.castCT();
			}
			template <class T2>
			Optional& operator = (T2&& t) {
				_release();
				_buffer = std::forward<T2>(t);
				_bInit = true;
				return *this;
			}
			Optional& operator = (none_t) noexcept {
				_release();
				return *this;
			}
			Optional& operator = (const Optional<T>& t) {
				_release();
				if(t) {
					_buffer = t._buffer.castT();
					_bInit = true;
				}
				return *this;
			}
			Optional& operator = (Optional<T>&& t) {
				_release();
				if(t) {
					_buffer = std::move(t._buffer.castT());
					t.t__release();
					_bInit = true;
				}
				return *this;
			}
			Optional& operator = (_AsInitialized) noexcept {
				_release();
				_bInit = true;
				return *this;
			}
	};
	template <class T>
	const typename Optional<T>::_AsInitialized Optional<T>::AsInitialized{};
}
<|endoftext|>


<commit_before>// main.cpp
// main entry point

// Copyright 2015 Matthew Chandler

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include <random>

#include <gtkmm/application.h>

#include "maze.hpp"

// global prng
thread_local std::random_device rng;
thread_local std::mt19937 prng;

int main(int argc, char * argv[])
{
    prng.seed(rng());

    // create app and window objects
    Glib::RefPtr<Gtk::Application> app = Gtk::Application::create(argc, argv, "org.matt.mazegen",
        Gio::APPLICATION_NON_UNIQUE | Gio::APPLICATION_HANDLES_OPEN);

    Maze maze(32, 32);

    return app->run(maze);
}
<commit_msg>fix prng seeding for mingw<commit_after>// main.cpp
// main entry point

// Copyright 2015 Matthew Chandler

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include <random>
#ifdef __MINGW32__
    #include <ctime>
#endif

#include <gtkmm/application.h>

#include "maze.hpp"

#ifndef __MINGW32__
    thread_local std::random_device rng;
#endif
thread_local std::mt19937 prng;

int main(int argc, char * argv[])
{
    // random_device curently not working in windows GCC
    #ifdef __MINGW32__
        prng.seed(time(NULL));
    #else
        prng.seed(rng());
    #endif

    // create app and window objects
    Glib::RefPtr<Gtk::Application> app = Gtk::Application::create(argc, argv, "org.matt.mazegen",
        Gio::APPLICATION_NON_UNIQUE | Gio::APPLICATION_HANDLES_OPEN);

    Maze maze(32, 32);

    return app->run(maze);
}
<|endoftext|>


<commit_before>#include <iostream>
#include "time.h"
#include <string>
#include "phashmap.h"
#include <cstdlib>
#include <cstddef>
#include <sys/time.h>
#define KEY_LEN 32
#define VAL_LEN 128
using namespace std;
struct timeval tp;

double diffclock(clock_t clock1, clock_t clock2){
   double clock_ts=clock1-clock2;
   double diffms=(clock_ts*1000)/CLOCKS_PER_SEC;
   return diffms;
}

double getTime_usec() {
   gettimeofday(&tp, NULL);
   return static_cast<double>(tp.tv_sec) * 1E6
      + static_cast<double>(tp.tv_usec);
}

string randomString(int len) {
   string s(len, ' ');
   srand(/*getpid()*/ clock() + getTime_usec());
   static const char alphanum[] = "0123456789"
      "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
      "abcdefghijklmnopqrstuvwxyz";
   for (int i = 0; i < len; ++i) {
      s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
   }
   return s;
}
double testInsert(phashmap &map, string keys[], string vals[], int l){
   clock_t a=clock();
   for (int t = 0; t<l; t++){
      map.put(keys[t], vals[t]);
   }
   clock_t b=clock();
   return diffclock(b,a);;
}

double testGet(phashmap &map, string keys[],  string vals[], int l){
   clock_t a=clock();
   for (int t=0; t<l; t++){
      if (map.get(keys[t])->compare(vals[t]) != 0)
         cerr << "Get Failed" << endl;
   }
   clock_t b=clock();
   return diffclock(b,a);
}

double testRemove(phashmap &map, string keys[], int l){
   clock_t a=clock();
   for (int t=0; t<l; t++){
      map.remove(keys[t]);
   }
   clock_t b=clock();
   return diffclock(b,a);
}
int main(int argc, char *argv[]){
   cout << "\nInitializing key-value pairs for testing\n" << endl;
   int size = atoi(argv[1]);
   string* keys = new string[size];
   string* vals = new string[size];
   for (int t=0; t<size; t++){
      keys[t] = randomString(KEY_LEN);
      vals[t] = randomString(VAL_LEN);
   }
   phashmap map ("fbench.data", 1000000, 10000, .7);
   //phashmap map ("", 1000000, 10000, .7);
   //phashmap map ("fbench.data", 1000000, -1);
   double ins, ret, rem;
   cout << "Testing Insertion: Inserting " << size << " elements" << endl;
   ins = testInsert(map, keys,vals,size);
   cout << "Testing Retrieval: Retrieving " << size << " elements" << endl;
   ret = testGet(map,keys,vals,size);
   cout << "Testing Removal:   Removing " << size << " elements" << endl;
   rem = testRemove(map,keys,size);
   cout << "\nInsertion done in " << ins << " milliseconds" << endl;
   cout << "Retrieval done in " << ret << " milliseconds" << endl;
   cout << "Removal done in " << rem << " milliseconds" << endl;

   return 0;
}
<commit_msg>	modified:   fbench.cxx<commit_after>#include <iostream>
#include "time.h"
#include <string>
#include "phashmap.h"
#include <cstdlib>
#include <cstddef>
#include <sys/time.h>
#define KEY_LEN 32
#define VAL_LEN 128
using namespace std;
struct timeval tp;

double diffclock(clock_t clock1, clock_t clock2){
   double clock_ts=clock1-clock2;
   double diffms=(clock_ts*1000)/CLOCKS_PER_SEC;
   return diffms;
}

double getTime_usec() {
   gettimeofday(&tp, NULL);
   return static_cast<double>(tp.tv_sec) * 1E6
      + static_cast<double>(tp.tv_usec);
}

string randomString(int len) {
   string s(len, ' ');
   srand(/*getpid()*/ clock() + getTime_usec());
   static const char alphanum[] = "0123456789"
      "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
      "abcdefghijklmnopqrstuvwxyz";
   for (int i = 0; i < len; ++i) {
      s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
   }
   return s;
}
double testInsert(phashmap &map, string keys[], string vals[], int l){
   clock_t a=clock();
   for (int t = 0; t<l; t++){
      map.put(keys[t], vals[t]);
   }
   clock_t b=clock();
   return diffclock(b,a);;
}

double testGet(phashmap &map, string keys[],  string vals[], int l){
   clock_t a=clock();
   for (int t=0; t<l; t++){
      if (map.get(keys[t])->compare(vals[t]) != 0)
         cerr << "Get Failed" << endl;
   }
   clock_t b=clock();
   return diffclock(b,a);
}

double testRemove(phashmap &map, string keys[], int l){
   clock_t a=clock();
   for (int t=0; t<l; t++){
      map.remove(keys[t]);
   }
   clock_t b=clock();
   return diffclock(b,a);
}
int main(int argc, char *argv[]){
   cout << "\nInitializing key-value pairs for testing\n" << endl;
   int size = atoi(argv[1]);
   string* keys = new string[size];
   string* vals = new string[size];
   for (int t=0; t<size; t++){
      keys[t] = randomString(KEY_LEN);
      vals[t] = randomString(VAL_LEN);
   }
   phashmap map ("/dev/shm/fbench.data", 1000000, 10000, .7);
   //phashmap map ("", 1000000, 10000, .7);
   //phashmap map ("fbench.data", 1000000, -1);
   double ins, ret, rem;
   cout << "Testing Insertion: Inserting " << size << " elements" << endl;
   ins = testInsert(map, keys,vals,size);
   cout << "Testing Retrieval: Retrieving " << size << " elements" << endl;
   ret = testGet(map,keys,vals,size);
   cout << "Testing Removal:   Removing " << size << " elements" << endl;
   rem = testRemove(map,keys,size);
   cout << "\nInsertion done in " << ins << " milliseconds" << endl;
   cout << "Retrieval done in " << ret << " milliseconds" << endl;
   cout << "Removal done in " << rem << " milliseconds" << endl;

   return 0;
}
<|endoftext|>


<commit_before>#pragma once

#include <vector>

#include <iterator>

#include "acmacs-base/date.hh"

// ----------------------------------------------------------------------

namespace rjson::inline v2
{
    class value;
}

namespace acmacs::time_series::inline v2
{
    struct slot
    {
        date::year_month_day first, after_last;
        constexpr bool operator==(const slot& rhs) const { return first == rhs.first && after_last == rhs.after_last; }
    };

    using series = std::vector<slot>;

    enum class interval { year, month, week, day };

    interval interval_from_string(std::string_view interval_name);

    struct parameters
    {
        date::year_month_day first, after_last; // {date::invalid_date()};
        interval intervl{interval::month};
        size_t number_of_intervals{1};
    };

    series make(const parameters& param);
    series make(const rjson::value& source, const parameters& default_param);
    inline series make(date::year_month_day first, date::year_month_day after_last) { return make(parameters{first, after_last}); }
    inline series make(std::string_view first, std::string_view after_last) { return make(parameters{date::from_string(first, date::allow_incomplete::yes), date::from_string(after_last, date::allow_incomplete::yes)}); }

    std::string text_name(const slot& a_slot);
    std::string numeric_name(const slot& a_slot);
}

// ----------------------------------------------------------------------

template <> struct fmt::formatter<acmacs::time_series::series>
{
    template <typename ParseContext> constexpr auto parse(ParseContext &ctx) { return ctx.begin(); }
    template <typename FormatContext> auto format(const acmacs::time_series::series& series, FormatContext& ctx)
    {
        format_to(ctx.out(), "time-series{{");
        for (const auto& slot : series)
            format_to(ctx.out(), " {}..{}", slot.first, slot.after_last);
        return format_to(ctx.out(), "}}");
    }
};

template <> struct fmt::formatter<acmacs::time_series::interval> : fmt::formatter<std::string> {
    template <typename FormatCtx> auto format(const acmacs::time_series::interval& intervl, FormatCtx& ctx)
    {
        switch (intervl) {
            case acmacs::time_series::v2::interval::year:
                return fmt::formatter<std::string>::format("year", ctx);
            case acmacs::time_series::v2::interval::month:
                return fmt::formatter<std::string>::format("month", ctx);
            case acmacs::time_series::v2::interval::week:
                return fmt::formatter<std::string>::format("week", ctx);
            case acmacs::time_series::v2::interval::day:
                return fmt::formatter<std::string>::format("day", ctx);
        }
    }
};

template <> struct fmt::formatter<acmacs::time_series::parameters>
{
    template <typename ParseContext> constexpr auto parse(ParseContext &ctx) { return ctx.begin(); }
    template <typename FormatContext> auto format(const acmacs::time_series::parameters& param, FormatContext& ctx)
    {
        return format_to(ctx.out(), "time-series{{{} .. {}, {}:{}}}", param.first, param.after_last, param.intervl, param.number_of_intervals);
    }
};

// ======================================================================

// ----------------------------------------------------------------------

// class TimeSeriesIterator : public std::iterator<std::input_iterator_tag, date::year_month_day, date::year_month_day, const date::year_month_day*, date::year_month_day>
// {
//  public:
//     TimeSeriesIterator(const TimeSeriesIterator&) = default;
//     virtual ~TimeSeriesIterator() = default;

//     bool operator==(const TimeSeriesIterator& other) const { return mDate == other.mDate; }
//     bool operator!=(const TimeSeriesIterator& other) const {return !(*this == other);}
//     TimeSeriesIterator& operator++() { mDate = next(); return *this; }
//     reference operator*() const { return mDate; }
//     pointer operator->() const { return &mDate; }

//     virtual date::year_month_day next() const = 0;
//     virtual std::string numeric_name() const = 0;
//     virtual std::string text_name() const { return numeric_name(); }

//     std::string first_date() const { return date::year4_month2_day2(mDate); }
//     std::string after_last_date() const { return date::year4_month2_day2(next()); }

//  protected:
//     inline TimeSeriesIterator(const date::year_month_day& d) : mDate(d) {}
//     date::year_month_day mDate;

// }; // class TimeSeriesIterator

// // ----------------------------------------------------------------------

// class MonthlyTimeSeries
// {
//  public:
//     MonthlyTimeSeries(const date::year_month_day& aStart, const date::year_month_day& aEnd) : mStart(date::beginning_of_month(aStart)), mEnd(date::beginning_of_month(aEnd)) {}
//     MonthlyTimeSeries(std::string_view aStart, std::string_view aEnd) : mStart(date::beginning_of_month(date::from_string(aStart))), mEnd(date::beginning_of_month(date::from_string(aEnd))) {}

//     int number_of_months() const { return date::months_between_dates(mStart, mEnd); }

//     class Iterator : public TimeSeriesIterator
//     {
//      public:
//         virtual date::year_month_day next() const { return date::next_month(mDate); }
//         virtual std::string numeric_name() const { return date::year4_month2(mDate); }
//         virtual std::string text_name() const { return date::monthtext_year(mDate); }

//      private:
//         friend class MonthlyTimeSeries;
//         Iterator(const date::year_month_day& d) : TimeSeriesIterator(d) {}
//     };

//     Iterator begin() const { return mStart; }
//     Iterator end() const { return mEnd; }

//     const auto& m_start() const { return mStart; }
//     const auto& m_end() const { return mEnd; }

//  private:
//     date::year_month_day mStart, mEnd;

// }; // class MonthlyTimeSeries

// template <> struct fmt::formatter<MonthlyTimeSeries> : fmt::formatter<std::string> {
//     template <typename FormatCtx> auto format(const MonthlyTimeSeries& ts, FormatCtx& ctx) { return fmt::formatter<std::string>::format(fmt::format("{}..{} ({})", ts.m_start(), ts.m_end(), ts.number_of_months()), ctx); }
// };

// // ----------------------------------------------------------------------

// class YearlyTimeSeries
// {
//  public:
//     YearlyTimeSeries(const date::year_month_day& aStart, const date::year_month_day& aEnd) : mStart(date::beginning_of_year(aStart)), mEnd(date::beginning_of_year(aEnd)) {}
//     YearlyTimeSeries(std::string_view aStart, std::string_view aEnd) : mStart(date::beginning_of_year(date::from_string(aStart))), mEnd(date::beginning_of_year(date::from_string(aEnd))) {}

//     int number_of_years() const { return years_between_dates(mStart, mEnd); }

//     class Iterator : public TimeSeriesIterator
//     {
//      public:
//         virtual date::year_month_day next() const { return date::next_year(mDate); }
//         virtual std::string numeric_name() const { return date::year_4(mDate); }

//      private:
//         friend class YearlyTimeSeries;
//         Iterator(const date::year_month_day& d) : TimeSeriesIterator(d) {}
//     };

//     Iterator begin() const { return mStart; }
//     Iterator end() const { return mEnd; }

//     const auto& m_start() const { return mStart; }
//     const auto& m_end() const { return mEnd; }

//  private:
//     date::year_month_day mStart, mEnd;

// }; // class YearlyTimeSeries

// template <> struct fmt::formatter<YearlyTimeSeries> : fmt::formatter<std::string> {
//     template <typename FormatCtx> auto format(const YearlyTimeSeries& ts, FormatCtx& ctx) { return fmt::formatter<std::string>::format(fmt::format("{}..{} ({})", ts.m_start(), ts.m_end(), ts.number_of_years()), ctx); }
// };

// // ----------------------------------------------------------------------

// class WeeklyTimeSeries
// {
//  public:
//     // WeeklyTimeSeries() {}
//     WeeklyTimeSeries(const date::year_month_day& aStart, const date::year_month_day& aEnd) : mStart(date::beginning_of_week(aStart)), mEnd(date::beginning_of_week(aEnd)) {}
//     WeeklyTimeSeries(std::string_view aStart, std::string_view aEnd) : mStart(date::beginning_of_week(date::from_string(aStart))), mEnd(date::beginning_of_week(date::from_string(aEnd))) {}

//     int number_of_weeks() const { return weeks_between_dates(mStart, mEnd); }

//     class Iterator : public TimeSeriesIterator
//     {
//      public:
//         virtual date::year_month_day next() const { return date::next_week(mDate); }
//         virtual std::string numeric_name() const { return date::display(mDate); }

//      private:
//         friend class WeeklyTimeSeries;
//         Iterator(const date::year_month_day& d) : TimeSeriesIterator(d) {}
//     };

//     Iterator begin() const { return mStart; }
//     Iterator end() const { return mEnd; }

//     const auto& m_start() const { return mStart; }
//     const auto& m_end() const { return mEnd; }

//  private:
//     date::year_month_day mStart, mEnd;

// }; // class WeeklyTimeSeries

// template <> struct fmt::formatter<WeeklyTimeSeries> : fmt::formatter<std::string> {
//     template <typename FormatCtx> auto format(const WeeklyTimeSeries& ts, FormatCtx& ctx) { return fmt::formatter<std::string>::format(fmt::format("{}..{} ({})", ts.m_start(), ts.m_end(), ts.number_of_weeks()), ctx); }
// };

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>old time series stuff removed<commit_after>#pragma once

#include <vector>

#include <iterator>

#include "acmacs-base/date.hh"

// ----------------------------------------------------------------------

namespace rjson::inline v2
{
    class value;
}

namespace acmacs::time_series::inline v2
{
    struct slot
    {
        date::year_month_day first, after_last;
        constexpr bool operator==(const slot& rhs) const { return first == rhs.first && after_last == rhs.after_last; }
    };

    using series = std::vector<slot>;

    enum class interval { year, month, week, day };

    interval interval_from_string(std::string_view interval_name);

    struct parameters
    {
        date::year_month_day first, after_last; // {date::invalid_date()};
        interval intervl{interval::month};
        size_t number_of_intervals{1};
    };

    series make(const parameters& param);
    series make(const rjson::value& source, const parameters& default_param);
    inline series make(date::year_month_day first, date::year_month_day after_last) { return make(parameters{first, after_last}); }
    inline series make(std::string_view first, std::string_view after_last) { return make(parameters{date::from_string(first, date::allow_incomplete::yes), date::from_string(after_last, date::allow_incomplete::yes)}); }

    std::string text_name(const slot& a_slot);
    std::string numeric_name(const slot& a_slot);
}

// ----------------------------------------------------------------------

template <> struct fmt::formatter<acmacs::time_series::series>
{
    template <typename ParseContext> constexpr auto parse(ParseContext &ctx) { return ctx.begin(); }
    template <typename FormatContext> auto format(const acmacs::time_series::series& series, FormatContext& ctx)
    {
        format_to(ctx.out(), "time-series{{");
        for (const auto& slot : series)
            format_to(ctx.out(), " {}..{}", slot.first, slot.after_last);
        return format_to(ctx.out(), "}}");
    }
};

template <> struct fmt::formatter<acmacs::time_series::interval> : fmt::formatter<std::string> {
    template <typename FormatCtx> auto format(const acmacs::time_series::interval& intervl, FormatCtx& ctx)
    {
        switch (intervl) {
            case acmacs::time_series::v2::interval::year:
                return fmt::formatter<std::string>::format("year", ctx);
            case acmacs::time_series::v2::interval::month:
                return fmt::formatter<std::string>::format("month", ctx);
            case acmacs::time_series::v2::interval::week:
                return fmt::formatter<std::string>::format("week", ctx);
            case acmacs::time_series::v2::interval::day:
                return fmt::formatter<std::string>::format("day", ctx);
        }
    }
};

template <> struct fmt::formatter<acmacs::time_series::parameters>
{
    template <typename ParseContext> constexpr auto parse(ParseContext &ctx) { return ctx.begin(); }
    template <typename FormatContext> auto format(const acmacs::time_series::parameters& param, FormatContext& ctx)
    {
        return format_to(ctx.out(), "time-series{{{} .. {}, {}:{}}}", param.first, param.after_last, param.intervl, param.number_of_intervals);
    }
};

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before>#include <algorithm>
#include <cstring>
#include <cpr/cpr.h>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <locale>
#include <sstream>
#include <tw/oauth.h>
#include <unordered_map>

#ifdef __linux__
# include <stdlib.h>
# include <unistd.h>
#endif

#ifdef _WIN32
# include <Windows.h>
#endif

#include <utils.h>

#define MAX_PATH_LEN 8192

static std::unordered_map<std::string, std::string> configs = {
	{ "giveaway", "/giveaway" },
	{ "twitter", "/twitter" },
	{ "config", "/config" },
	{ "submit", "/submitted" },
};

static const std::string PB = "https://ptpb.pw/";

bool utils::startsWith(const std::string &str, const std::string &prefix)
{
	return str.find(prefix) == 0;
}

bool utils::endsWith(const std::string &str, const std::string &suffix)
{
	return str.find(suffix) == str.length() - suffix.length();
}

std::vector<std::string> &utils::split(const std::string &str,
		char delim, std::vector<std::string> &elems)
{
	std::stringstream ss(str);
	std::string item;
	while (std::getline(ss, item, delim)) {
		if (!item.empty())
			elems.push_back(item);
	}
	return elems;
}

std::string utils::formatInteger(std::string integer)
{
	int pos = integer.length() - 3;
	if (pos < 1)
		return integer;
	while (pos > 0) {
		integer.insert(pos, ",");
		pos -= 3;
	}
	return integer;
}

#ifdef _WIN32
static std::string configdir_win()
{
	char buf[MAX_PATH_LEN];
	int bytes;

	if (!(bytes = GetModuleFileName(NULL, buf, sizeof(buf)))) {
		std::cerr << "could not get current directory" << std::endl;
		return "";
	}

	/* strip filename from path */
	std::string path(buf);
	path = path.substr(0, path.find_last_of("\\"));

	return path;
}
#endif

#ifdef __linux__
static std::string configdir_unix()
{
	char *h;
	if (!(h= getenv("HOME"))) {
		std::cerr << "could not read $HOME" << std::endl;
		return "";
	}
	return std::string(h) + "/.lynxbot";
}
#endif

std::string utils::configdir()
{
#ifdef __linux__
	return configdir_unix();
#endif
#ifdef _WIN32
	return configdir_win();
#endif
}

std::string utils::config(const std::string &cfg)
{
	std::string path = "";
	if (configs.find(cfg) != configs.end()) {
		path += configs[cfg];
#ifdef _WIN32
		std::replace(path.begin(), path.end(), '/', '\\');
		if (cfg != "twitter")
			path += ".txt";
#endif
	}
	return path;
}

bool utils::readJSON(const std::string &filename, Json::Value &val)
{
	Json::Reader reader;
	std::ifstream fileStream(configdir() + "/json/" + filename,
		std::ifstream::binary);

	if (!reader.parse(fileStream, val)) {
		std::cerr << reader.getFormattedErrorMessages() << std::endl;
		return false;
	}
	return true;
}

void utils::writeJSON(const std::string &filename, Json::Value &val)
{
	std::ofstream ofile(configdir() + "/json/" + filename);
	Json::StyledWriter sw;
	ofile << sw.write(val);
	ofile.close();
}

bool utils::parseBool(bool &b, const std::string &s, std::string &err)
{
	if (s == "true") {
		b = true;
		return true;
	}
	if (s == "false") {
		b = false;
		return true;
	}
	err = "invalid setting -- " + s;
	return false;
}

bool utils::parseInt(uint32_t &i, const std::string &s, std::string &err)
{
	try {
		i = std::stoi(s);
		return true;
	} catch (std::invalid_argument) {
		err = "invalid number -- " + s;
		return false;
	}
}

#define MIN	 60
#define HOUR	 3600
#define DAY	 86400

/* conv_time: convert t to days, hours, minutes and seconds */
std::string utils::conv_time(time_t t)
{
	time_t d, h, m;
	std::string out;

	d = t / DAY;
	t %= DAY;
	h = t / HOUR;
	t %= HOUR;
	m = t / MIN;
	t %= MIN;

	if (d)
		out += std::to_string(d) + " day" + (d == 1 ? "" : "s") + ", ";
	if (h)
		out += std::to_string(h) + " hour" + (h == 1 ? "" : "s") + ", ";
	if (m)
		out += std::to_string(m) + " minute" + (m == 1 ? "" : "s")
			+ " and ";
	out += std::to_string(t) + " second" + (t == 1 ? "" : "s");
	return out;
}

/* getamt: read number from string num into amt */
bool utils::readnum(char *num, int64_t *amt)
{
	size_t last;
	int64_t n, mult;

	last = strlen(num) - 1;
	mult = 1;
	if (num[last] == 'k' || num[last] == 'm' || num[last] == 'b') {
		switch (num[last]) {
		case 'k':
			mult = 1000;
			break;
		case 'm':
			mult = 1000000;
			break;
		case 'b':
			mult = 1000000000;
			break;
		}
		num[last] = '\0';
	}

	n = 0;
	for (; *num; ++num) {
		if (*num < '0' || *num > '9')
			return false;
		n = 10 * n + (*num - '0');
	}
	*amt = n * mult;
	return true;
}

/* upload: upload s to ptpb.pw */
std::string utils::upload(const std::string &s)
{
	cpr::Response resp;
	size_t i;
	std::string url;

	resp = cpr::Post(cpr::Url(PB), cpr::Body("c=" + tw::pencode(s, "\n")));

	if ((i = resp.text.find("url:")) == std::string::npos)
		return "failed to upload";

	url = resp.text.substr(i + 5);
	if ((i = url.find('\n')) != std::string::npos)
		url = url.substr(0, i);

	return url;
}

/* map of html encoded characters */
static std::unordered_map<std::string, char> encoded = {
	{ "amp", '&' },
	{ "gt", '>' },
	{ "lt", '<' },
	{ "quot", '"' }
};

/* decode: decode html encoded string */
std::string utils::decode(const std::string &s)
{
	size_t i;
	std::string out, enc;

	for (i = 0; i < s.length(); ++i) {
		if (s[i] == '&') {
			enc.clear();
			for (++i; s[i] != ';'; ++i)
				enc += s[i];
			out += encoded[enc];
			continue;
		}
		out += s[i] == '\n' ? ' ' : s[i];
	}
	return out;
}

/* parse_time: extract time and date from ftime */
std::string utils::parse_time(const std::string &ftime, bool since)
{
	std::tm tm, curr;
	time_t t, now;
	std::ostringstream out;
	std::istringstream ss(ftime);

#ifdef __linux__
	ss.imbue(std::locale("en_US.utf-8"));
#endif
#ifdef _WIN32
	ss.imbue(std::locale("en-US"));
#endif
	ss >> std::get_time(&tm, "%Y-%m-%dT%H:%M:%S");
	tm.tm_isdst = 0;
	t = std::mktime(&tm);

	now = time(NULL);
	curr = *std::gmtime(&now);
	curr.tm_isdst = 0;
	now = std::mktime(&curr);

	out << utils::conv_time(now - t);
	if (since) {
		out << " (since ";
		out << std::put_time(&tm, "%H:%M:%S UTC, %d %b %Y") << ")";
	}

	return out.str();
}
<commit_msg>Change to gmtime_s for windows<commit_after>#include <algorithm>
#include <cstring>
#include <cpr/cpr.h>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <locale>
#include <sstream>
#include <tw/oauth.h>
#include <unordered_map>

#ifdef __linux__
# include <stdlib.h>
# include <unistd.h>
#endif

#ifdef _WIN32
# include <Windows.h>
#endif

#include <utils.h>

#define MAX_PATH_LEN 8192

static std::unordered_map<std::string, std::string> configs = {
	{ "giveaway", "/giveaway" },
	{ "twitter", "/twitter" },
	{ "config", "/config" },
	{ "submit", "/submitted" },
};

static const std::string PB = "https://ptpb.pw/";

bool utils::startsWith(const std::string &str, const std::string &prefix)
{
	return str.find(prefix) == 0;
}

bool utils::endsWith(const std::string &str, const std::string &suffix)
{
	return str.find(suffix) == str.length() - suffix.length();
}

std::vector<std::string> &utils::split(const std::string &str,
		char delim, std::vector<std::string> &elems)
{
	std::stringstream ss(str);
	std::string item;
	while (std::getline(ss, item, delim)) {
		if (!item.empty())
			elems.push_back(item);
	}
	return elems;
}

std::string utils::formatInteger(std::string integer)
{
	int pos = integer.length() - 3;
	if (pos < 1)
		return integer;
	while (pos > 0) {
		integer.insert(pos, ",");
		pos -= 3;
	}
	return integer;
}

#ifdef _WIN32
static std::string configdir_win()
{
	char buf[MAX_PATH_LEN];
	int bytes;

	if (!(bytes = GetModuleFileName(NULL, buf, sizeof(buf)))) {
		std::cerr << "could not get current directory" << std::endl;
		return "";
	}

	/* strip filename from path */
	std::string path(buf);
	path = path.substr(0, path.find_last_of("\\"));

	return path;
}
#endif

#ifdef __linux__
static std::string configdir_unix()
{
	char *h;
	if (!(h= getenv("HOME"))) {
		std::cerr << "could not read $HOME" << std::endl;
		return "";
	}
	return std::string(h) + "/.lynxbot";
}
#endif

std::string utils::configdir()
{
#ifdef __linux__
	return configdir_unix();
#endif
#ifdef _WIN32
	return configdir_win();
#endif
}

std::string utils::config(const std::string &cfg)
{
	std::string path = "";
	if (configs.find(cfg) != configs.end()) {
		path += configs[cfg];
#ifdef _WIN32
		std::replace(path.begin(), path.end(), '/', '\\');
		if (cfg != "twitter")
			path += ".txt";
#endif
	}
	return path;
}

bool utils::readJSON(const std::string &filename, Json::Value &val)
{
	Json::Reader reader;
	std::ifstream fileStream(configdir() + "/json/" + filename,
		std::ifstream::binary);

	if (!reader.parse(fileStream, val)) {
		std::cerr << reader.getFormattedErrorMessages() << std::endl;
		return false;
	}
	return true;
}

void utils::writeJSON(const std::string &filename, Json::Value &val)
{
	std::ofstream ofile(configdir() + "/json/" + filename);
	Json::StyledWriter sw;
	ofile << sw.write(val);
	ofile.close();
}

bool utils::parseBool(bool &b, const std::string &s, std::string &err)
{
	if (s == "true") {
		b = true;
		return true;
	}
	if (s == "false") {
		b = false;
		return true;
	}
	err = "invalid setting -- " + s;
	return false;
}

bool utils::parseInt(uint32_t &i, const std::string &s, std::string &err)
{
	try {
		i = std::stoi(s);
		return true;
	} catch (std::invalid_argument) {
		err = "invalid number -- " + s;
		return false;
	}
}

#define MIN	 60
#define HOUR	 3600
#define DAY	 86400

/* conv_time: convert t to days, hours, minutes and seconds */
std::string utils::conv_time(time_t t)
{
	time_t d, h, m;
	std::string out;

	d = t / DAY;
	t %= DAY;
	h = t / HOUR;
	t %= HOUR;
	m = t / MIN;
	t %= MIN;

	if (d)
		out += std::to_string(d) + " day" + (d == 1 ? "" : "s") + ", ";
	if (h)
		out += std::to_string(h) + " hour" + (h == 1 ? "" : "s") + ", ";
	if (m)
		out += std::to_string(m) + " minute" + (m == 1 ? "" : "s")
			+ " and ";
	out += std::to_string(t) + " second" + (t == 1 ? "" : "s");
	return out;
}

/* getamt: read number from string num into amt */
bool utils::readnum(char *num, int64_t *amt)
{
	size_t last;
	int64_t n, mult;

	last = strlen(num) - 1;
	mult = 1;
	if (num[last] == 'k' || num[last] == 'm' || num[last] == 'b') {
		switch (num[last]) {
		case 'k':
			mult = 1000;
			break;
		case 'm':
			mult = 1000000;
			break;
		case 'b':
			mult = 1000000000;
			break;
		}
		num[last] = '\0';
	}

	n = 0;
	for (; *num; ++num) {
		if (*num < '0' || *num > '9')
			return false;
		n = 10 * n + (*num - '0');
	}
	*amt = n * mult;
	return true;
}

/* upload: upload s to ptpb.pw */
std::string utils::upload(const std::string &s)
{
	cpr::Response resp;
	size_t i;
	std::string url;

	resp = cpr::Post(cpr::Url(PB), cpr::Body("c=" + tw::pencode(s, "\n")));

	if ((i = resp.text.find("url:")) == std::string::npos)
		return "failed to upload";

	url = resp.text.substr(i + 5);
	if ((i = url.find('\n')) != std::string::npos)
		url = url.substr(0, i);

	return url;
}

/* map of html encoded characters */
static std::unordered_map<std::string, char> encoded = {
	{ "amp", '&' },
	{ "gt", '>' },
	{ "lt", '<' },
	{ "quot", '"' }
};

/* decode: decode html encoded string */
std::string utils::decode(const std::string &s)
{
	size_t i;
	std::string out, enc;

	for (i = 0; i < s.length(); ++i) {
		if (s[i] == '&') {
			enc.clear();
			for (++i; s[i] != ';'; ++i)
				enc += s[i];
			out += encoded[enc];
			continue;
		}
		out += s[i] == '\n' ? ' ' : s[i];
	}
	return out;
}

/* parse_time: extract time and date from ftime */
std::string utils::parse_time(const std::string &ftime, bool since)
{
	std::tm tm, curr;
	time_t t, now;
	std::ostringstream out;
	std::istringstream ss(ftime);

#ifdef __linux__
	ss.imbue(std::locale("en_US.utf-8"));
#endif
#ifdef _WIN32
	ss.imbue(std::locale("en-US"));
#endif
	ss >> std::get_time(&tm, "%Y-%m-%dT%H:%M:%S");
	tm.tm_isdst = 0;
	t = std::mktime(&tm);

	now = time(NULL);
#ifdef __linux__
	curr = *std::gmtime(&now);
#endif
#ifdef _WIN32
	gmtime_s(&curr, &now);
#endif
	curr.tm_isdst = 0;
	now = std::mktime(&curr);

	out << utils::conv_time(now - t);
	if (since) {
		out << " (since ";
		out << std::put_time(&tm, "%H:%M:%S UTC, %d %b %Y") << ")";
	}

	return out.str();
}
<|endoftext|>


<commit_before>//*****************************************************************************
// Copyright 2017-2020 Intel Corporation
//
// 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 "ngraph/op/extractimagepatches.hpp"
#include "ngraph/attribute_visitor.hpp"

using namespace std;
using namespace ngraph;

// ExtractImagePatches v3

constexpr NodeTypeInfo op::v3::ExtractImagePatches::type_info;

op::v3::ExtractImagePatches::ExtractImagePatches(const Output<Node>& image,
                                                 const Shape& sizes,
                                                 const Strides& strides,
                                                 const Shape& rates,
                                                 const PadType& auto_pad)
    : Op({image})
    , m_patch_sizes(sizes)
    , m_patch_movement_strides(strides)
    , m_patch_selection_rates(rates)
    , m_padding(auto_pad)
{
    constructor_validate_and_infer_types();
}

void op::v3::ExtractImagePatches::validate_and_infer_types()
{
    const PartialShape input_Pshape = get_input_partial_shape(0);

    NODE_VALIDATION_CHECK(this,
                          get_input_element_type(0).is_dynamic() ||
                              get_input_element_type(0).is_integral_number(),
                          "input tensor must be an integral number.");
    NODE_VALIDATION_CHECK(this, input_Pshape.rank() == 4, "input tensor must be 4D tensor.");

    NODE_VALIDATION_CHECK(this,
                          m_patch_sizes.size() == 2,
                          "Attribute sizes should be in [size_rows, size_cols] format.");

    NODE_VALIDATION_CHECK(this,
                          m_patch_movement_strides.size() == 2,
                          "Attribute strides should be in [stride_rows, stride_cols] format.");

    NODE_VALIDATION_CHECK(this,
                          m_patch_movement_strides[0] > 0 && m_patch_movement_strides[1] > 0,
                          "Attribute strides should be strictly greater than zeros in values.");

    NODE_VALIDATION_CHECK(this,
                          m_patch_selection_rates.size() == 2,
                          "Attribute rates should be in [rate_rows, rate_cols] format.");

    NODE_VALIDATION_CHECK(this,
                          m_patch_selection_rates[0] > 0 && m_patch_selection_rates[1] > 0,
                          "Attribute rates should be strictly greater than zeros in values.");

    NODE_VALIDATION_CHECK(
        this,
        m_padding == PadType::VALID || m_padding == PadType::SAME_LOWER ||
            m_padding == PadType::SAME_UPPER,
        "Attribute padding should be in either valid or same_lower or same_upper.");

    if (input_Pshape[1].is_dynamic() || input_Pshape[2].is_dynamic() ||
        input_Pshape[3].is_dynamic())
    {
        set_input_is_relevant_to_shape(0);
        auto output_Pshape = PartialShape::dynamic(4);
        set_output_type(0, get_input_element_type(0), output_Pshape);
    }
    else
    {
        int32_t input_depth = input_Pshape[1].get_length();
        int32_t input_rows = input_Pshape[2].get_length();
        int32_t input_cols = input_Pshape[3].get_length();
        int32_t out_rows(0);
        int32_t out_cols(0);

        if (input_rows == 0 || input_cols == 0)
        {
            out_rows = 0;
            out_cols = 0;
        }
        else if (m_padding == PadType::VALID)
        {
            out_rows = (((input_rows) -
                         static_cast<int32_t>(m_patch_selection_rates[0]) *
                             (static_cast<int32_t>(m_patch_sizes[0]) - 1) -
                         1) /
                        m_patch_movement_strides[0]) +
                       1;
            out_cols = (((input_cols) -
                         static_cast<int32_t>(m_patch_selection_rates[1]) *
                             (static_cast<int32_t>(m_patch_sizes[1]) - 1) -
                         1) /
                        m_patch_movement_strides[1]) +
                       1;
        }
        else
        {
            out_rows = 1 + (((input_rows)-1) / m_patch_movement_strides[0]);
            out_cols = 1 + (((input_cols)-1) / m_patch_movement_strides[1]);
        }

        if (out_rows < 0)
            out_rows = 0;
        if (out_cols < 0)
            out_cols = 0;

        ngraph::Dimension::value_type out_depth_cast = static_cast<ngraph::Dimension::value_type>(
            input_depth * m_patch_sizes[0] * m_patch_sizes[1]);
        ngraph::Dimension::value_type out_rows_cast =
            static_cast<ngraph::Dimension::value_type>(out_rows);
        ngraph::Dimension::value_type out_cols_cast =
            static_cast<ngraph::Dimension::value_type>(out_cols);

        PartialShape output_Pshape;
        if (input_Pshape[0].is_dynamic())
        {
            output_Pshape =
                PartialShape{input_Pshape[0], out_depth_cast, out_rows_cast, out_cols_cast};
        }
        else
        {
            ngraph::Dimension::value_type input_batch_cast =
                static_cast<ngraph::Dimension::value_type>(input_Pshape[0].get_length());
            output_Pshape =
                PartialShape{input_batch_cast, out_depth_cast, out_rows_cast, out_cols_cast};
        }

        if (input_rows == 0 || input_cols == 0)
        {
            output_Pshape = input_Pshape;
        }

        set_output_type(0, get_input_element_type(0), output_Pshape);
    }
}

bool op::v3::ExtractImagePatches::visit_attributes(AttributeVisitor& visitor)
{
    visitor.on_attribute("sizes", m_patch_sizes);
    visitor.on_attribute("strides", m_patch_movement_strides);
    visitor.on_attribute("rates", m_patch_selection_rates);
    visitor.on_attribute("auto_pad", m_padding);
    return true;
}

shared_ptr<Node>
    op::v3::ExtractImagePatches::clone_with_new_inputs(const OutputVector& new_args) const
{
    check_new_args_count(this, new_args);
    return make_shared<op::v3::ExtractImagePatches>(new_args.at(0),
                                                    m_patch_sizes,
                                                    m_patch_movement_strides,
                                                    m_patch_selection_rates,
                                                    m_padding);
}
<commit_msg>fixing bug for data input (#4786)<commit_after>//*****************************************************************************
// Copyright 2017-2020 Intel Corporation
//
// 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 "ngraph/op/extractimagepatches.hpp"
#include "ngraph/attribute_visitor.hpp"

using namespace std;
using namespace ngraph;

// ExtractImagePatches v3

constexpr NodeTypeInfo op::v3::ExtractImagePatches::type_info;

op::v3::ExtractImagePatches::ExtractImagePatches(const Output<Node>& image,
                                                 const Shape& sizes,
                                                 const Strides& strides,
                                                 const Shape& rates,
                                                 const PadType& auto_pad)
    : Op({image})
    , m_patch_sizes(sizes)
    , m_patch_movement_strides(strides)
    , m_patch_selection_rates(rates)
    , m_padding(auto_pad)
{
    constructor_validate_and_infer_types();
}

void op::v3::ExtractImagePatches::validate_and_infer_types()
{
    const PartialShape input_Pshape = get_input_partial_shape(0);

    NODE_VALIDATION_CHECK(this, input_Pshape.rank() == 4, "input tensor must be 4D tensor.");

    NODE_VALIDATION_CHECK(this,
                          m_patch_sizes.size() == 2,
                          "Attribute sizes should be in [size_rows, size_cols] format.");

    NODE_VALIDATION_CHECK(this,
                          m_patch_movement_strides.size() == 2,
                          "Attribute strides should be in [stride_rows, stride_cols] format.");

    NODE_VALIDATION_CHECK(this,
                          m_patch_movement_strides[0] > 0 && m_patch_movement_strides[1] > 0,
                          "Attribute strides should be strictly greater than zeros in values.");

    NODE_VALIDATION_CHECK(this,
                          m_patch_selection_rates.size() == 2,
                          "Attribute rates should be in [rate_rows, rate_cols] format.");

    NODE_VALIDATION_CHECK(this,
                          m_patch_selection_rates[0] > 0 && m_patch_selection_rates[1] > 0,
                          "Attribute rates should be strictly greater than zeros in values.");

    NODE_VALIDATION_CHECK(
        this,
        m_padding == PadType::VALID || m_padding == PadType::SAME_LOWER ||
            m_padding == PadType::SAME_UPPER,
        "Attribute padding should be in either valid or same_lower or same_upper.");

    if (input_Pshape[1].is_dynamic() || input_Pshape[2].is_dynamic() ||
        input_Pshape[3].is_dynamic())
    {
        set_input_is_relevant_to_shape(0);
        auto output_Pshape = PartialShape::dynamic(4);
        set_output_type(0, get_input_element_type(0), output_Pshape);
    }
    else
    {
        int32_t input_depth = input_Pshape[1].get_length();
        int32_t input_rows = input_Pshape[2].get_length();
        int32_t input_cols = input_Pshape[3].get_length();
        int32_t out_rows(0);
        int32_t out_cols(0);

        if (input_rows == 0 || input_cols == 0)
        {
            out_rows = 0;
            out_cols = 0;
        }
        else if (m_padding == PadType::VALID)
        {
            out_rows = (((input_rows) -
                         static_cast<int32_t>(m_patch_selection_rates[0]) *
                             (static_cast<int32_t>(m_patch_sizes[0]) - 1) -
                         1) /
                        m_patch_movement_strides[0]) +
                       1;
            out_cols = (((input_cols) -
                         static_cast<int32_t>(m_patch_selection_rates[1]) *
                             (static_cast<int32_t>(m_patch_sizes[1]) - 1) -
                         1) /
                        m_patch_movement_strides[1]) +
                       1;
        }
        else
        {
            out_rows = 1 + (((input_rows)-1) / m_patch_movement_strides[0]);
            out_cols = 1 + (((input_cols)-1) / m_patch_movement_strides[1]);
        }

        if (out_rows < 0)
            out_rows = 0;
        if (out_cols < 0)
            out_cols = 0;

        ngraph::Dimension::value_type out_depth_cast = static_cast<ngraph::Dimension::value_type>(
            input_depth * m_patch_sizes[0] * m_patch_sizes[1]);
        ngraph::Dimension::value_type out_rows_cast =
            static_cast<ngraph::Dimension::value_type>(out_rows);
        ngraph::Dimension::value_type out_cols_cast =
            static_cast<ngraph::Dimension::value_type>(out_cols);

        PartialShape output_Pshape;
        if (input_Pshape[0].is_dynamic())
        {
            output_Pshape =
                PartialShape{input_Pshape[0], out_depth_cast, out_rows_cast, out_cols_cast};
        }
        else
        {
            ngraph::Dimension::value_type input_batch_cast =
                static_cast<ngraph::Dimension::value_type>(input_Pshape[0].get_length());
            output_Pshape =
                PartialShape{input_batch_cast, out_depth_cast, out_rows_cast, out_cols_cast};
        }

        if (input_rows == 0 || input_cols == 0)
        {
            output_Pshape = input_Pshape;
        }

        set_output_type(0, get_input_element_type(0), output_Pshape);
    }
}

bool op::v3::ExtractImagePatches::visit_attributes(AttributeVisitor& visitor)
{
    visitor.on_attribute("sizes", m_patch_sizes);
    visitor.on_attribute("strides", m_patch_movement_strides);
    visitor.on_attribute("rates", m_patch_selection_rates);
    visitor.on_attribute("auto_pad", m_padding);
    return true;
}

shared_ptr<Node>
    op::v3::ExtractImagePatches::clone_with_new_inputs(const OutputVector& new_args) const
{
    check_new_args_count(this, new_args);
    return make_shared<op::v3::ExtractImagePatches>(new_args.at(0),
                                                    m_patch_sizes,
                                                    m_patch_movement_strides,
                                                    m_patch_selection_rates,
                                                    m_padding);
}
<|endoftext|>