<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <vector>

#include "base/file_path.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/autofill/autofill_manager.h"
#include "chrome/browser/autofill/data_driven_test.h"
#include "chrome/browser/autofill/form_structure.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
#include "googleurl/src/gurl.h"

namespace {

const FilePath::CharType kTestName[] = FILE_PATH_LITERAL("heuristics");
const FilePath::CharType kFileNamePattern[] = FILE_PATH_LITERAL("*.html");

// Convert the |html| snippet to a data URI.
GURL HTMLToDataURI(const std::string& html) {
  return GURL(std::string("data:text/html;charset=utf-8,") + html);
}

}  // namespace

// A data-driven test for verifying AutoFill heuristics. Each input is an HTML
// file that contains one or more forms. The corresponding output file lists the
// heuristically detected type for eachfield.
class FormStructureBrowserTest : public InProcessBrowserTest,
                                 public DataDrivenTest {
 protected:
  FormStructureBrowserTest();
  virtual ~FormStructureBrowserTest();

  // DataDrivenTest:
  virtual void GenerateResults(const std::string& input,
                               std::string* output);

  // Serializes the given |forms| into a string.
  std::string FormStructuresToString(const std::vector<FormStructure*>& forms);

 private:
  DISALLOW_COPY_AND_ASSIGN(FormStructureBrowserTest);
};

FormStructureBrowserTest::FormStructureBrowserTest() {
}

FormStructureBrowserTest::~FormStructureBrowserTest() {
}

void FormStructureBrowserTest::GenerateResults(const std::string& input,
                                               std::string* output) {
  LOG(WARNING) << "Before NavigateToURL";
  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
                                                       HTMLToDataURI(input)));
  LOG(WARNING) << "Before ClickOnView";
  ASSERT_NO_FATAL_FAILURE(ui_test_utils::ClickOnView(browser(),
                                                     VIEW_ID_TAB_CONTAINER));
  LOG(WARNING) << "Before IsViewFocused";
  ASSERT_TRUE(ui_test_utils::IsViewFocused(browser(),
                                           VIEW_ID_TAB_CONTAINER_FOCUS_VIEW));
  LOG(WARNING) << "After IsViewFocused";

  AutoFillManager* autofill_manager =
      browser()->GetSelectedTabContents()->autofill_manager();
  ASSERT_NE(static_cast<AutoFillManager*>(NULL), autofill_manager);
  std::vector<FormStructure*> forms = autofill_manager->form_structures_.get();
  *output = FormStructureBrowserTest::FormStructuresToString(forms);
}

std::string FormStructureBrowserTest::FormStructuresToString(
    const std::vector<FormStructure*>& forms) {
  std::string forms_string;
  for (std::vector<FormStructure*>::const_iterator iter = forms.begin();
       iter != forms.end();
       ++iter) {

    for (std::vector<AutoFillField*>::const_iterator field_iter =
            (*iter)->begin();
         field_iter != (*iter)->end();
         ++field_iter) {
      // The field list is NULL-terminated.  Exit loop when at the end.
      if (!*field_iter)
        break;
      forms_string += AutoFillType::FieldTypeToString((*field_iter)->type());
      forms_string += "\n";
    }
  }
  return forms_string;
}

IN_PROC_BROWSER_TEST_F(FormStructureBrowserTest,
                       DISABLED_DataDrivenHeuristics) {
  LOG(WARNING) << "Before BringBrowserWindowToFront";
  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
  LOG(WARNING) << "After BringBrowserWindowToFront";
  RunDataDrivenTest(GetInputDirectory(kTestName),
                    GetOutputDirectory(kTestName),
                    kFileNamePattern);
}
<commit_msg>Reenable FormStructureBrowserTest.DataDrivenHeuristics for debugging<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <vector>

#include "base/file_path.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/autofill/autofill_manager.h"
#include "chrome/browser/autofill/data_driven_test.h"
#include "chrome/browser/autofill/form_structure.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
#include "googleurl/src/gurl.h"

namespace {

const FilePath::CharType kTestName[] = FILE_PATH_LITERAL("heuristics");
const FilePath::CharType kFileNamePattern[] = FILE_PATH_LITERAL("*.html");

// Convert the |html| snippet to a data URI.
GURL HTMLToDataURI(const std::string& html) {
  return GURL(std::string("data:text/html;charset=utf-8,") + html);
}

}  // namespace

// A data-driven test for verifying AutoFill heuristics. Each input is an HTML
// file that contains one or more forms. The corresponding output file lists the
// heuristically detected type for eachfield.
class FormStructureBrowserTest : public InProcessBrowserTest,
                                 public DataDrivenTest {
 protected:
  FormStructureBrowserTest();
  virtual ~FormStructureBrowserTest();

  // DataDrivenTest:
  virtual void GenerateResults(const std::string& input,
                               std::string* output);

  // Serializes the given |forms| into a string.
  std::string FormStructuresToString(const std::vector<FormStructure*>& forms);

 private:
  DISALLOW_COPY_AND_ASSIGN(FormStructureBrowserTest);
};

FormStructureBrowserTest::FormStructureBrowserTest() {
}

FormStructureBrowserTest::~FormStructureBrowserTest() {
}

void FormStructureBrowserTest::GenerateResults(const std::string& input,
                                               std::string* output) {
  LOG(WARNING) << "Before NavigateToURL";
  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
                                                       HTMLToDataURI(input)));
  LOG(WARNING) << "Before ClickOnView";
  ASSERT_NO_FATAL_FAILURE(ui_test_utils::ClickOnView(browser(),
                                                     VIEW_ID_TAB_CONTAINER));
  LOG(WARNING) << "Before IsViewFocused";
  ASSERT_TRUE(ui_test_utils::IsViewFocused(browser(),
                                           VIEW_ID_TAB_CONTAINER_FOCUS_VIEW));
  LOG(WARNING) << "After IsViewFocused";

  AutoFillManager* autofill_manager =
      browser()->GetSelectedTabContents()->autofill_manager();
  ASSERT_NE(static_cast<AutoFillManager*>(NULL), autofill_manager);
  std::vector<FormStructure*> forms = autofill_manager->form_structures_.get();
  *output = FormStructureBrowserTest::FormStructuresToString(forms);
}

std::string FormStructureBrowserTest::FormStructuresToString(
    const std::vector<FormStructure*>& forms) {
  std::string forms_string;
  for (std::vector<FormStructure*>::const_iterator iter = forms.begin();
       iter != forms.end();
       ++iter) {

    for (std::vector<AutoFillField*>::const_iterator field_iter =
            (*iter)->begin();
         field_iter != (*iter)->end();
         ++field_iter) {
      // The field list is NULL-terminated.  Exit loop when at the end.
      if (!*field_iter)
        break;
      forms_string += AutoFillType::FieldTypeToString((*field_iter)->type());
      forms_string += "\n";
    }
  }
  return forms_string;
}

IN_PROC_BROWSER_TEST_F(FormStructureBrowserTest, DataDrivenHeuristics) {
  LOG(WARNING) << "Before BringBrowserWindowToFront";
  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
  LOG(WARNING) << "After BringBrowserWindowToFront";
  RunDataDrivenTest(GetInputDirectory(kTestName),
                    GetOutputDirectory(kTestName),
                    kFileNamePattern);
}
<|endoftext|>


<commit_before>// Author: http://lemming.life
// Language: C++
// Description: Example of creating and using an object.

// At terminal:
// g++ pointers.cpp
// ./a.out

#include <iostream>

class Shape {
private:
    int id;
public:
    Shape(int id) {
        this->id = id;
    }
    int getId() { return id; }

    ~Shape() {
        std::cout << "Destroying shape" << id << "\n";
    }
};

// Pass a Shape*
void PrintShape(Shape* shape) {
    std::cout << "Shape ID: " << shape->getId() << "\n";
}

int main() {
    int id = 0;

    {   // Deepen the scope

        // Create shape1
        Shape shape1(++id);
        PrintShape(&shape1); // Pass the address of shape

        Shape* shapePtr; // A pointer holds the address of an object type specified (in this case Shape)
        // The pointer itself is in the stack section of a program

        {
            Shape shape2(++id); // Create shape2 on the stack.
            PrintShape(&shape2);
            shapePtr = &shape2;

            // Ways to use the pointer
            std::cout << "Via pointer, arrow operator. ID: " << shapePtr->getId() << "\n";
            std::cout << "Via pointer, derefencing. ID: " << (*shapePtr).getId() << "\n";

        } // Destroying shape2 because the object goes out of scope

        // the shapePtr still has the address of the shape2 object
        PrintShape(shapePtr); // Expect: Shape ID: 2

        shapePtr = new Shape(++id);  // Creates an object on the heap portion of a program.
        PrintShape(shapePtr); // Shape ID: 3
        delete shapePtr; // Deletes the object pointed by the shapePtr

        shapePtr = new Shape(++id); // This is Shape with id 4

    } // Destroying shape1 automatically because the object goes out of scope

    // Note that shape with id 4 was never deleted. This is a memory leak!
    // Other languages have garbage collection -- cleans memory automatically.
    // C++ 11 has shared pointers that can be used for automatically doing clean up.

    return 0;
}

// Expected Output:
/*
Shape ID: 1
Shape ID: 2
Via pointer, arrow operator. ID: 2
Via pointer, derefencing. ID: 2
Destroying shape2
Shape ID: 2
Shape ID: 3
Destroying shape3
Destroying shape1
*/<commit_msg>Added pointers C++ example.<commit_after>// Author: http://lemming.life
// Language: C++
// Description: Example of creating and using an object.

/* At terminal do:
    g++ pointers.cpp
    ./a.out
*/

#include <iostream>

class Shape {
private:
    int id;
public:
    Shape(int id) {
        this->id = id;
    }
    int getId() { return id; }

    ~Shape() {
        std::cout << "Destroying shape" << id << "\n";
    }
};

// Pass a Shape*
void PrintShape(Shape* shape) {
    std::cout << "Shape ID: " << shape->getId() << "\n";
}

int main() {
    int id = 0;

    {   // Deepen the scope

        // Create shape1
        Shape shape1(++id);
        PrintShape(&shape1); // Pass the address of shape

        Shape* shapePtr; // A pointer holds the address of an object type specified (in this case Shape)
        // The pointer itself is in the stack section of a program

        {
            Shape shape2(++id); // Create shape2 on the stack.
            PrintShape(&shape2);
            shapePtr = &shape2;

            // Ways to use the pointer
            std::cout << "Via pointer, arrow operator. ID: " << shapePtr->getId() << "\n";
            std::cout << "Via pointer, derefencing. ID: " << (*shapePtr).getId() << "\n";

        } // Destroying shape2 because the object goes out of scope

        // the shapePtr still has the address of the shape2 object
        PrintShape(shapePtr); // Expect: Shape ID: 2

        shapePtr = new Shape(++id);  // Creates an object on the heap portion of a program.
        PrintShape(shapePtr); // Shape ID: 3
        delete shapePtr; // Deletes the object pointed by the shapePtr

        shapePtr = new Shape(++id); // This is Shape with id 4

    } // Destroying shape1 automatically because the object goes out of scope

    // Note that shape with id 4 was never deleted. This is a memory leak!
    // Other languages have garbage collection -- cleans memory automatically.
    // C++ 11 has shared pointers that can be used for automatically doing clean up.

    return 0;
}

// Expected Output:
/*
Shape ID: 1
Shape ID: 2
Via pointer, arrow operator. ID: 2
Via pointer, derefencing. ID: 2
Destroying shape2
Shape ID: 2
Shape ID: 3
Destroying shape3
Destroying shape1
*/<|endoftext|>


<commit_before>//===- fpcmp.cpp - A fuzzy "cmp" that permits floating point noise --------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// fpcmp is a tool that basically works like the 'cmp' tool, except that it can
// tolerate errors due to floating point noise, with the -r option.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileUtilities.h"
#include <iostream>
#include <cmath>

using namespace llvm;

namespace {
  cl::opt<std::string>
  File1(cl::Positional, cl::desc("<input file #1>"), cl::Required);
  cl::opt<std::string>
  File2(cl::Positional, cl::desc("<input file #2>"), cl::Required);

  cl::opt<double>
  RelTolerance("r", cl::desc("Relative error tolerated"), cl::init(0));
  cl::opt<double>
  AbsTolerance("a", cl::desc("Absolute error tolerated"), cl::init(0));
}

/// OpenFile - mmap the specified file into the address space for reading, and
/// return the length and address of the buffer.
static void OpenFile(const std::string &Filename, unsigned &Len, char* &BufPtr){
  BufPtr = (char*)ReadFileIntoAddressSpace(Filename, Len);
  if (BufPtr == 0) {
    std::cerr << "Error: cannot open file '" << Filename << "'\n";
    exit(2);
  }
}

static bool isNumberChar(char C) {
  switch (C) {
  case '0': case '1': case '2': case '3': case '4':
  case '5': case '6': case '7': case '8': case '9':
  case '.': case '+': case '-':
  case 'e':
  case 'E': return true;
  default: return false;
  }
}

static char *BackupNumber(char *Pos, char *FirstChar) {
  // If we didn't stop in the middle of a number, don't backup.
  if (!isNumberChar(*Pos)) return Pos;

  // Otherwise, return to the start of the number.
  while (Pos > FirstChar && isNumberChar(Pos[-1]))
    --Pos;
  return Pos;
}

static void CompareNumbers(char *&F1P, char *&F2P, char *F1End, char *F2End) {
  char *F1NumEnd, *F2NumEnd;
  double V1 = 0.0, V2 = 0.0;
  // If we stop on numbers, compare their difference.
  if (isNumberChar(*F1P) && isNumberChar(*F2P)) {
    V1 = strtod(F1P, &F1NumEnd);
    V2 = strtod(F2P, &F2NumEnd);
  } else {
    // Otherwise, the diff failed.
    F1NumEnd = F1P;
    F2NumEnd = F2P;
  }

  if (F1NumEnd == F1P || F2NumEnd == F2P) {
    std::cerr << "Comparison failed, not a numeric difference.\n";
    exit(1);
  }

  // Check to see if these are inside the absolute tolerance
  if (AbsTolerance < std::abs(V1-V2)) {
    // Nope, check the relative tolerance...
    double Diff;
    if (V2)
      Diff = std::abs(V1/V2 - 1.0);
    else if (V1)
      Diff = std::abs(V2/V1 - 1.0);
    else
      Diff = 0;  // Both zero.
    if (Diff > RelTolerance) {
      std::cerr << "Compared: " << V1 << " and " << V2 << ": diff = "
                << Diff << "\n";
      std::cerr << "Out of tolerance: rel/abs: " << RelTolerance
                << "/" << AbsTolerance << "\n";
      exit(1);
    }
  }

  // Otherwise, advance our read pointers to the end of the numbers.
  F1P = F1NumEnd;  F2P = F2NumEnd;
}

// PadFileIfNeeded - If the files are not identical, we will have to be doing
// numeric comparisons in here.  There are bad cases involved where we (i.e.,
// strtod) might run off the beginning or end of the file if it starts or ends
// with a number.  Because of this, if needed, we pad the file so that it starts
// and ends with a null character.
static void PadFileIfNeeded(char *&FileStart, char *&FileEnd, char *&FP) {
  if (isNumberChar(FileStart[0]) || isNumberChar(FileEnd[-1])) {
    unsigned FileLen = FileEnd-FileStart;
    char *NewFile = new char[FileLen+2];
    NewFile[0] = 0;              // Add null padding
    NewFile[FileLen+1] = 0;      // Add null padding
    memcpy(NewFile+1, FileStart, FileLen);
    FP = NewFile+(FP-FileStart)+1;
    FileStart = NewFile+1;
    FileEnd = FileStart+FileLen;
  }
}

int main(int argc, char **argv) {
  cl::ParseCommandLineOptions(argc, argv);

  // mmap in the files.
  unsigned File1Len, File2Len;
  char *File1Start, *File2Start;
  OpenFile(File1, File1Len, File1Start);
  OpenFile(File2, File2Len, File2Start);

  // Okay, now that we opened the files, scan them for the first difference.
  char *File1End = File1Start+File1Len;
  char *File2End = File2Start+File2Len;
  char *F1P = File1Start;
  char *F2P = File2Start;

  // Scan for the end of file or first difference.
  while (F1P < File1End && F2P < File2End && *F1P == *F2P)
    ++F1P, ++F2P;

  // Common case: identifical files.
  if (F1P == File1End && F2P == File2End) return 0;

  // If the files need padding, do so now.
  PadFileIfNeeded(File1Start, File1End, F1P);
  PadFileIfNeeded(File2Start, File2End, F2P);

  while (1) {
    // Scan for the end of file or next difference.
    while (F1P < File1End && F2P < File2End && *F1P == *F2P)
      ++F1P, ++F2P;

    if (F1P >= File1End || F2P >= File2End) break;

    // Okay, we must have found a difference.  Backup to the start of the
    // current number each stream is at so that we can compare from the
    // beginning.
    F1P = BackupNumber(F1P, File1Start);
    F2P = BackupNumber(F2P, File2Start);

    // Now that we are at the start of the numbers, compare them, exiting if
    // they don't match.
    CompareNumbers(F1P, F2P, File1End, File2End);
  }

  // Okay, we reached the end of file.  If both files are at the end, we
  // succeeded.
  bool F1AtEnd = F1P >= File1End;
  bool F2AtEnd = F2P >= File2End;
  if (F1AtEnd & F2AtEnd) return 0;

  // Otherwise, we might have run off the end due to a number: backup and retry.
  if (F1AtEnd && isNumberChar(F1P[-1])) --F1P;
  if (F2AtEnd && isNumberChar(F2P[-1])) --F2P;
  F1P = BackupNumber(F1P, File1Start);
  F2P = BackupNumber(F2P, File2Start);

  // Now that we are at the start of the numbers, compare them, exiting if
  // they don't match.
  CompareNumbers(F1P, F2P, File1End, File2End);

  // If we found the end, we succeeded.
  if (F1P >= File1End && F2P >= File2End) return 0;

  return 1;
}

<commit_msg>For PR351: * Change use of ReadFileIntoAddressSpace to sys::MappedFile use. * Shorten a line > 80 chars.<commit_after>//===- fpcmp.cpp - A fuzzy "cmp" that permits floating point noise --------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// fpcmp is a tool that basically works like the 'cmp' tool, except that it can
// tolerate errors due to floating point noise, with the -r option.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/CommandLine.h"
#include "llvm/System/MappedFile.h"
#include <iostream>
#include <cmath>

using namespace llvm;

namespace {
  cl::opt<std::string>
  File1(cl::Positional, cl::desc("<input file #1>"), cl::Required);
  cl::opt<std::string>
  File2(cl::Positional, cl::desc("<input file #2>"), cl::Required);

  cl::opt<double>
  RelTolerance("r", cl::desc("Relative error tolerated"), cl::init(0));
  cl::opt<double>
  AbsTolerance("a", cl::desc("Absolute error tolerated"), cl::init(0));
}

static bool isNumberChar(char C) {
  switch (C) {
  case '0': case '1': case '2': case '3': case '4':
  case '5': case '6': case '7': case '8': case '9':
  case '.': case '+': case '-':
  case 'e':
  case 'E': return true;
  default: return false;
  }
}

static char *BackupNumber(char *Pos, char *FirstChar) {
  // If we didn't stop in the middle of a number, don't backup.
  if (!isNumberChar(*Pos)) return Pos;

  // Otherwise, return to the start of the number.
  while (Pos > FirstChar && isNumberChar(Pos[-1]))
    --Pos;
  return Pos;
}

static void CompareNumbers(char *&F1P, char *&F2P, char *F1End, char *F2End) {
  char *F1NumEnd, *F2NumEnd;
  double V1 = 0.0, V2 = 0.0;
  // If we stop on numbers, compare their difference.
  if (isNumberChar(*F1P) && isNumberChar(*F2P)) {
    V1 = strtod(F1P, &F1NumEnd);
    V2 = strtod(F2P, &F2NumEnd);
  } else {
    // Otherwise, the diff failed.
    F1NumEnd = F1P;
    F2NumEnd = F2P;
  }

  if (F1NumEnd == F1P || F2NumEnd == F2P) {
    std::cerr << "Comparison failed, not a numeric difference.\n";
    exit(1);
  }

  // Check to see if these are inside the absolute tolerance
  if (AbsTolerance < std::abs(V1-V2)) {
    // Nope, check the relative tolerance...
    double Diff;
    if (V2)
      Diff = std::abs(V1/V2 - 1.0);
    else if (V1)
      Diff = std::abs(V2/V1 - 1.0);
    else
      Diff = 0;  // Both zero.
    if (Diff > RelTolerance) {
      std::cerr << "Compared: " << V1 << " and " << V2 << ": diff = "
                << Diff << "\n";
      std::cerr << "Out of tolerance: rel/abs: " << RelTolerance
                << "/" << AbsTolerance << "\n";
      exit(1);
    }
  }

  // Otherwise, advance our read pointers to the end of the numbers.
  F1P = F1NumEnd;  F2P = F2NumEnd;
}

// PadFileIfNeeded - If the files are not identical, we will have to be doing
// numeric comparisons in here.  There are bad cases involved where we (i.e.,
// strtod) might run off the beginning or end of the file if it starts or ends
// with a number.  Because of this, if needed, we pad the file so that it starts
// and ends with a null character.
static void PadFileIfNeeded(char *&FileStart, char *&FileEnd, char *&FP) {
  if (isNumberChar(FileStart[0]) || isNumberChar(FileEnd[-1])) {
    unsigned FileLen = FileEnd-FileStart;
    char *NewFile = new char[FileLen+2];
    NewFile[0] = 0;              // Add null padding
    NewFile[FileLen+1] = 0;      // Add null padding
    memcpy(NewFile+1, FileStart, FileLen);
    FP = NewFile+(FP-FileStart)+1;
    FileStart = NewFile+1;
    FileEnd = FileStart+FileLen;
  }
}

int main(int argc, char **argv) {
  cl::ParseCommandLineOptions(argc, argv);

  try {
    // map in the files into memory
    sys::Path F1Path(File1);
    sys::Path F2Path(File2);
    sys::MappedFile F1 ( F1Path );
    sys::MappedFile F2 ( F2Path );
    F1.map();
    F2.map();

    // Okay, now that we opened the files, scan them for the first difference.
    char *File1Start = F1.charBase();
    char *File2Start = F2.charBase();
    char *File1End = File1Start+F1.size();
    char *File2End = File2Start+F2.size();
    char *F1P = File1Start;
    char *F2P = File2Start;

    // Scan for the end of file or first difference.
    while (F1P < File1End && F2P < File2End && *F1P == *F2P)
      ++F1P, ++F2P;

    // Common case: identifical files.
    if (F1P == File1End && F2P == File2End) return 0;

    // If the files need padding, do so now.
    PadFileIfNeeded(File1Start, File1End, F1P);
    PadFileIfNeeded(File2Start, File2End, F2P);

    while (1) {
      // Scan for the end of file or next difference.
      while (F1P < File1End && F2P < File2End && *F1P == *F2P)
        ++F1P, ++F2P;

      if (F1P >= File1End || F2P >= File2End) break;

      // Okay, we must have found a difference.  Backup to the start of the
      // current number each stream is at so that we can compare from the
      // beginning.
      F1P = BackupNumber(F1P, File1Start);
      F2P = BackupNumber(F2P, File2Start);

      // Now that we are at the start of the numbers, compare them, exiting if
      // they don't match.
      CompareNumbers(F1P, F2P, File1End, File2End);
    }

    // Okay, we reached the end of file.  If both files are at the end, we
    // succeeded.
    bool F1AtEnd = F1P >= File1End;
    bool F2AtEnd = F2P >= File2End;
    if (F1AtEnd & F2AtEnd) return 0;

    // Else, we might have run off the end due to a number: backup and retry.
    if (F1AtEnd && isNumberChar(F1P[-1])) --F1P;
    if (F2AtEnd && isNumberChar(F2P[-1])) --F2P;
    F1P = BackupNumber(F1P, File1Start);
    F2P = BackupNumber(F2P, File2Start);

    // Now that we are at the start of the numbers, compare them, exiting if
    // they don't match.
    CompareNumbers(F1P, F2P, File1End, File2End);

    // If we found the end, we succeeded.
    if (F1P >= File1End && F2P >= File2End) return 0;

  } catch (const std::string& msg) {
    std::cerr << argv[0] << ": error: " << msg << "\n";
    return 2;
  }

  return 1;
}

<|endoftext|>


<commit_before>#include <tiramisu/tiramisu.h>
#include <vector>
#include "configure.h"

using namespace tiramisu;

int main()
{
    init("densenet_block");

    // -------------------------------------------------------
    // Layer I
    // -------------------------------------------------------
    var x("x", 0, N), y("y", 0, N), z("z", 0, 4*GR), n("n", 0, BATCH_SIZE);

    var x_pad("x", 0, N + 2), y_pad("y", 0, N + 2);
    var k_x("k_x", 0, K_X), k_y("k_y", 0, K_Y);

    var fin_b("fin_b", 0, FIN_NB_BLOCKS), ffin("ffin", 0, FIN_BLOCKING);
    var fout_b("fout_b", 0, FOUT_NB_BLOCKS), ffout("ffout", 0, FOUT_BLOCKING);

    input c_input("c_input", {n, fin_b, y_pad, x_pad, ffin}, p_float32);
    input bn_scale("bn_scale", {fin_b, ffin}, p_float32);
    input bn_shift("bn_shift", {fin_b, ffin}, p_float32);

    input conv_filter("conv_filter", {fin_b, fout_b, k_y, k_x, ffin, ffout}, p_float32);
    input conv_bias("conv_bias", {fout_b, ffout}, p_float32);

    // Batch normalization followed by ReLU
    // Compute the sum over the features dimension (z)
    computation input_sum_init("input_sum_init", {fin_b, ffin}, cast(p_float32, 0));
    computation input_sum(
        "input_sum",
        {fin_b, n, y_pad, x_pad, ffin},
        input_sum_init(fin_b, ffin) + c_input(n, fin_b, y_pad, x_pad, ffin)
    );

    // Compute the sum of squares over the features dimension (z)
    computation input_sum_squares_init("input_sum_squares_init", {fin_b, ffin}, cast(p_float32, 0));
    computation input_sum_squares(
        "input_sum_squares",
        {fin_b, n, y_pad, x_pad, ffin},
        input_sum_squares_init(fin_b, ffin) + c_input(n, fin_b, y_pad, x_pad, ffin) * c_input(n, fin_b, y_pad, x_pad, ffin)
    );

    computation input_mean(
        "input_mean",
        {fin_b, ffin},
        input_sum(fin_b, 0, 0, 0, ffin) / cast(p_float32, BATCH_SIZE*(N+2)*(N+2))
    );

    computation input_sd(
        "input_sd",
        {fin_b, ffin},
        expr(
            o_sqrt,
            input_sum_squares(fin_b, 0, 0, 0, ffin) / cast(p_float32, BATCH_SIZE*(N+2)*(N+2)) - input_mean(fin_b, ffin) * input_mean(fin_b, ffin) + cast(p_float32, EPSILON)
        )
    );

    // Compute BN followed by ReLU
    computation bn(
        "bn",
        {n, fin_b, y_pad, x_pad, ffin},
        bn_scale(fin_b, ffin) * ((c_input(n, fin_b, y_pad, x_pad, ffin) - input_mean(fin_b, ffin)) / input_sd(fin_b, ffin)) + bn_shift(fin_b, ffin)
    );

    computation relu(
        "relu",
        {n, fin_b, y_pad, x_pad, ffin},
        expr(
            o_max,
            cast(p_float32, 0),
            bn(n, fin_b, y_pad, x_pad, ffin)
        )
    );

    computation conv_init("conv_init", {n, y, fout_b, x, ffout}, conv_bias(fout_b, ffout));
    view conv_out("conv_out", {n, y, x, fout_b, ffout}, p_float32);

    // Convolution computation
    // x_bound is used to have the width dimension divisible by X_BLOCKING
    // in the conv computation.
    var x_bound("x_bound", 0, X_BOUND);
    var x_conclude("x_conclude", X_BOUND, N);

    // Compute convolution from 0 to x_bound
    computation conv(
        "conv",
        {n, fin_b, y, x_bound, k_y, k_x, ffin, fout_b, ffout},
        conv_out(n, y, x_bound, fout_b, ffout) + conv_filter(fin_b, fout_b, k_y, k_x, ffin, ffout) * relu(n, fin_b, y + k_y, x_bound + k_x, ffin)
    );

    // Compute convolution from x_bound to N
    computation conv_conclude(
        "conv_conclude",
        {n, fin_b, y, k_y, k_x, ffin, fout_b, ffout, x_conclude},
        conv_out(n, y, x_conclude, fout_b, ffout) + conv_filter(fin_b, fout_b, k_y, k_x, ffin, ffout) * relu(n, fin_b, y + k_y, x_conclude + k_x, ffin)
    );

    // -------------------------------------------------------
    // Layer II
    // -------------------------------------------------------
    input_sum.vectorize(ffin, VEC_LEN);
    input_sum.tag_parallel_level(fin_b);

    bn.vectorize(ffin, VEC_LEN);

    /*
     * Schedule for conv
     */
    // We introduce those two computations to do register blocking
    computation reg_load(
        "reg_load",
        {n, fin_b, y, x_bound, fout_b, ffout},
        conv_init(n, y, fout_b, x_bound, ffout)
    );

    computation reg_store(
        "reg_store",
        {n, fin_b, y, x_bound, fout_b, ffout},
        conv(n, fin_b, y, x_bound, 0, 0, 0, fout_b, ffout)
    );

    // Split over dimension x
    var x_b, xx;
    conv.split(x_bound, X_BLOCKING, x_b, xx);

    conv.interchange(xx, k_y);
    conv.interchange(xx, k_x);
    conv.interchange(xx, ffin);
    conv.interchange(xx, fout_b);
    conv.interchange(xx, ffout);

    reg_load.split(x_bound, X_BLOCKING, x_b, xx);
    reg_store.split(x_bound, X_BLOCKING, x_b, xx);

    reg_load.interchange(xx, fout_b);
    reg_load.interchange(xx, ffout);

    reg_store.interchange(xx, fout_b);
    reg_store.interchange(xx, ffout);

    // Vectorize and unroll
    reg_load.vectorize(ffout, VEC_LEN);
    conv.vectorize(ffout, VEC_LEN);
    reg_store.vectorize(ffout, VEC_LEN);

    conv.tag_unroll_level(xx);
    conv.tag_unroll_level(fout_b);

    reg_load.tag_unroll_level(xx);
    reg_load.tag_unroll_level(fout_b);

    reg_store.tag_unroll_level(xx);
    reg_store.tag_unroll_level(fout_b);

    // schedule for conv_conclude
    // This schedule is the same as conv computation
    computation reg_load_conclude(
        "reg_load_conclude",
        {n, fin_b, y, fout_b, ffout, x_conclude},
        conv_init(n, y, fout_b, x_conclude, ffout)
    );

    computation reg_store_conclude(
        "reg_store_conclude",
        {n, fin_b, y, fout_b, ffout, x_conclude},
        conv_conclude(n, fin_b, y, 0, 0, 0, fout_b, ffout, x_conclude)
    );

    reg_load_conclude.vectorize(ffout, VEC_LEN);
    conv_conclude.vectorize(ffout, VEC_LEN);
    reg_store_conclude.vectorize(ffout, VEC_LEN);

    conv_conclude.tag_unroll_level(x_conclude);
    conv_conclude.tag_unroll_level(fout_b);

    reg_load_conclude.tag_unroll_level(x_conclude);
    reg_load_conclude.tag_unroll_level(fout_b);

    reg_store_conclude.tag_unroll_level(x_conclude);
    reg_store_conclude.tag_unroll_level(fout_b);

    // Parallelize and order
    conv.tag_parallel_level(n);

    input_sum_init.then(input_sum_squares_init, ffin)
                  .then(input_sum, fin_b)
                  .then(input_sum_squares, ffin)
                  .then(input_mean, fin_b)
                  .then(input_sd, ffin)
                  .then(conv_init, computation::root)
                  .then(bn, n)
                  .then(relu, ffin)
                  .then(reg_load, fin_b)
                  .then(conv, x_b)
                  .then(reg_store, x_b)
                  .then(reg_load_conclude, y)
                  .then(conv_conclude, y)
                  .then(reg_store_conclude, y);

    // -------------------------------------------------------
    // Layer III
    // -------------------------------------------------------
    buffer output_buf("output_buf", {BATCH_SIZE, FOUT_NB_BLOCKS, N, N, FOUT_BLOCKING}, p_float32, a_output);

    buffer input_mean_buf("input_mean_buf", {FIN_NB_BLOCKS, FIN_BLOCKING}, p_float32, a_input);
    buffer input_sd_buf("input_sd_buf", {FIN_NB_BLOCKS, FIN_BLOCKING}, p_float32, a_input);

    buffer workspace_buf("workspace_buf", {BATCH_SIZE, N + 2, N + 2, FIN_BLOCKING}, p_float32, a_input);

    // This is where intermediate results of convolution will be stored.
    // We rely on the compiler to detect that this buffer can be mapped to CPU registers.
    buffer reg_buf("reg_buf", {FOUT_NB_BLOCKS, X_BLOCKING, FOUT_BLOCKING}, p_float32, a_temporary);

    input_sum_init.store_in(&input_mean_buf);
    input_sum.store_in(&input_mean_buf, {fin_b, ffin});
    input_mean.store_in(&input_mean_buf);

    input_sum_squares_init.store_in(&input_sd_buf);
    input_sum_squares.store_in(&input_sd_buf, {fin_b, ffin});
    input_sd.store_in(&input_sd_buf);

    bn.store_in(&workspace_buf, {n, y_pad, x_pad, ffin});
    relu.store_in(&workspace_buf, {n, y_pad, x_pad, ffin});

    /*
     * Storage for conv
     */
    conv_init.store_in(&output_buf, {n, fout_b, y, x, ffout});
    conv_out.store_in(&reg_buf, {fout_b, x%X_BLOCKING, ffout});

    reg_load.store_in(&reg_buf, {fout_b, x_bound%X_BLOCKING, ffout});
    conv.store_in(&reg_buf, {fout_b, x_bound%X_BLOCKING, ffout});
    reg_store.store_in(&output_buf, {n, fout_b, y, x_bound, ffout});

    reg_load_conclude.store_in(&reg_buf, {fout_b, x_conclude%X_BLOCKING, ffout});
    conv_conclude.store_in(&reg_buf, {fout_b, x_conclude%X_BLOCKING, ffout});
    reg_store_conclude.store_in(&output_buf, {n, fout_b, y, x_conclude, ffout});

    // -------------------------------------------------------
    // Code Generation
    // -------------------------------------------------------
    codegen({
        c_input.get_buffer(),
        bn_scale.get_buffer(),
        bn_shift.get_buffer(),
        conv_filter.get_buffer(),
        conv_bias.get_buffer(),
        &input_mean_buf,
        &input_sd_buf,
        &workspace_buf,
        &output_buf
    }, "densenet_block_tiramisu.o");

    return 0;
}
<commit_msg>DenseNet block : apply fusion<commit_after>#include <tiramisu/tiramisu.h>
#include <vector>
#include "configure.h"

using namespace tiramisu;

int main()
{
    init("densenet_block");

    // -------------------------------------------------------
    // Layer I
    // -------------------------------------------------------
    var x("x", 0, N), y("y", 0, N), z("z", 0, 4*GR), n("n", 0, BATCH_SIZE);

    var x_pad("x", 0, N + 2), y_pad("y", 0, N + 2);
    var k_x("k_x", 0, K_X), k_y("k_y", 0, K_Y);

    var fin_b("fin_b", 0, FIN_NB_BLOCKS), ffin("ffin", 0, FIN_BLOCKING);
    var fout_b("fout_b", 0, FOUT_NB_BLOCKS), ffout("ffout", 0, FOUT_BLOCKING);

    input c_input("c_input", {n, fin_b, y_pad, x_pad, ffin}, p_float32);
    input bn_scale("bn_scale", {fin_b, ffin}, p_float32);
    input bn_shift("bn_shift", {fin_b, ffin}, p_float32);

    input conv_filter("conv_filter", {fin_b, fout_b, k_y, k_x, ffin, ffout}, p_float32);
    input conv_bias("conv_bias", {fout_b, ffout}, p_float32);

    // Batch normalization followed by ReLU
    // Compute the sum over the features dimension (z)
    computation input_sum_init("input_sum_init", {fin_b, ffin}, cast(p_float32, 0));
    computation input_sum(
        "input_sum",
        {fin_b, n, y_pad, x_pad, ffin},
        input_sum_init(fin_b, ffin) + c_input(n, fin_b, y_pad, x_pad, ffin)
    );

    // Compute the sum of squares over the features dimension (z)
    computation input_sum_squares_init("input_sum_squares_init", {fin_b, ffin}, cast(p_float32, 0));
    computation input_sum_squares(
        "input_sum_squares",
        {fin_b, n, y_pad, x_pad, ffin},
        input_sum_squares_init(fin_b, ffin) + c_input(n, fin_b, y_pad, x_pad, ffin) * c_input(n, fin_b, y_pad, x_pad, ffin)
    );

    computation input_mean(
        "input_mean",
        {fin_b, ffin},
        input_sum(fin_b, 0, 0, 0, ffin) / cast(p_float32, BATCH_SIZE*(N+2)*(N+2))
    );

    computation input_sd(
        "input_sd",
        {fin_b, ffin},
        expr(
            o_sqrt,
            input_sum_squares(fin_b, 0, 0, 0, ffin) / cast(p_float32, BATCH_SIZE*(N+2)*(N+2)) - input_mean(fin_b, ffin) * input_mean(fin_b, ffin) + cast(p_float32, EPSILON)
        )
    );

    // Compute BN followed by ReLU

    // Compute BN-ReLU for y = 0, 1
    var y_prelude("y_prelude", 0, 2);
    computation bn_prelude(
        "bn_prelude",
        {n, fin_b, y_prelude, x_pad, ffin},
        bn_scale(fin_b, ffin) * ((c_input(n, fin_b, y_prelude, x_pad, ffin) - input_mean(fin_b, ffin)) / input_sd(fin_b, ffin)) + bn_shift(fin_b, ffin)
    );

    computation relu_prelude(
        "relu_prelude",
        {n, fin_b, y_prelude, x_pad, ffin},
        expr(
            o_max,
            cast(p_float32, 0),
            bn_prelude(n, fin_b, y_prelude, x_pad, ffin)
        )
    );

    // Compute BN-ReLU for y = 2, .... N + 1
    computation bn(
        "bn",
        {n, fin_b, y, x_pad, ffin},
        bn_scale(fin_b, ffin) * ((c_input(n, fin_b, y + 2, x_pad, ffin) - input_mean(fin_b, ffin)) / input_sd(fin_b, ffin)) + bn_shift(fin_b, ffin)
    );

    computation relu(
        "relu",
        {n, fin_b, y, x_pad, ffin},
        expr(
            o_max,
            cast(p_float32, 0),
            bn(n, fin_b, y, x_pad, ffin)
        )
    );

    computation conv_init("conv_init", {n, fout_b, y, x, ffout}, conv_bias(fout_b, ffout));
    view conv_out("conv_out", {n, y, x, fout_b, ffout}, p_float32);

    // Convolution computation
    // x_bound is used to have the width dimension divisible by X_BLOCKING
    // in the conv computation.
    var x_bound("x_bound", 0, X_BOUND);
    var x_conclude("x_conclude", X_BOUND, N);

    view relu_view("relu_view", {n, fin_b, y_pad, x_pad, ffin}, p_float32);

    // Compute convolution from 0 to x_bound
    computation conv(
        "conv",
        {n, fin_b, y, x_bound, k_y, k_x, ffin, fout_b, ffout},
        conv_out(n, y, x_bound, fout_b, ffout) + conv_filter(fin_b, fout_b, k_y, k_x, ffin, ffout) * relu_view(n, fin_b, y + k_y, x_bound + k_x, ffin)
    );

    // Compute convolution from x_bound to N
    computation conv_conclude(
        "conv_conclude",
        {n, fin_b, y, k_y, k_x, ffin, fout_b, ffout, x_conclude},
        conv_out(n, y, x_conclude, fout_b, ffout) + conv_filter(fin_b, fout_b, k_y, k_x, ffin, ffout) * relu_view(n, fin_b, y + k_y, x_conclude + k_x, ffin)
    );

    // -------------------------------------------------------
    // Layer II
    // -------------------------------------------------------
    input_sum.vectorize(ffin, VEC_LEN);
    input_sum.tag_parallel_level(fin_b);

    bn_prelude.vectorize(ffin, VEC_LEN);
    bn.vectorize(ffin, VEC_LEN);

    /*
     * Schedule for conv
     */
    // We introduce those two computations to do register blocking
    computation reg_load(
        "reg_load",
        {n, fin_b, y, x_bound, fout_b, ffout},
        conv_init(n, fout_b, y, x_bound, ffout)
    );

    computation reg_store(
        "reg_store",
        {n, fin_b, y, x_bound, fout_b, ffout},
        conv(n, fin_b, y, x_bound, 0, 0, 0, fout_b, ffout)
    );

    // Split over dimension x
    var x_b, xx;
    conv.split(x_bound, X_BLOCKING, x_b, xx);

    conv.interchange(xx, k_y);
    conv.interchange(xx, k_x);
    conv.interchange(xx, ffin);
    conv.interchange(xx, fout_b);
    conv.interchange(xx, ffout);

    reg_load.split(x_bound, X_BLOCKING, x_b, xx);
    reg_store.split(x_bound, X_BLOCKING, x_b, xx);

    reg_load.interchange(xx, fout_b);
    reg_load.interchange(xx, ffout);

    reg_store.interchange(xx, fout_b);
    reg_store.interchange(xx, ffout);

    // Vectorize and unroll
    reg_load.vectorize(ffout, VEC_LEN);
    conv.vectorize(ffout, VEC_LEN);
    reg_store.vectorize(ffout, VEC_LEN);

    conv.tag_unroll_level(xx);
    conv.tag_unroll_level(fout_b);

    reg_load.tag_unroll_level(xx);
    reg_load.tag_unroll_level(fout_b);

    reg_store.tag_unroll_level(xx);
    reg_store.tag_unroll_level(fout_b);

    // schedule for conv_conclude
    // This schedule is the same as conv computation
    computation reg_load_conclude(
        "reg_load_conclude",
        {n, fin_b, y, fout_b, ffout, x_conclude},
        conv_init(n, fout_b, y, x_conclude, ffout)
    );

    computation reg_store_conclude(
        "reg_store_conclude",
        {n, fin_b, y, fout_b, ffout, x_conclude},
        conv_conclude(n, fin_b, y, 0, 0, 0, fout_b, ffout, x_conclude)
    );

    reg_load_conclude.vectorize(ffout, VEC_LEN);
    conv_conclude.vectorize(ffout, VEC_LEN);
    reg_store_conclude.vectorize(ffout, VEC_LEN);

    conv_conclude.tag_unroll_level(x_conclude);
    conv_conclude.tag_unroll_level(fout_b);

    reg_load_conclude.tag_unroll_level(x_conclude);
    reg_load_conclude.tag_unroll_level(fout_b);

    reg_store_conclude.tag_unroll_level(x_conclude);
    reg_store_conclude.tag_unroll_level(fout_b);

    // Parallelize and order
    conv.tag_parallel_level(n);

    input_sum_init.then(input_sum_squares_init, ffin)
                  .then(input_sum, fin_b)
                  .then(input_sum_squares, ffin)
                  .then(input_mean, fin_b)
                  .then(input_sd, ffin)
                  .then(conv_init, computation::root)
                  .then(bn_prelude, n)
                  .then(relu_prelude, ffin)
                  .then(bn, fin_b)
                  .then(relu, ffin)
                  .then(reg_load, y)
                  .then(conv, x_b)
                  .then(reg_store, x_b)
                  .then(reg_load_conclude, y)
                  .then(conv_conclude, y)
                  .then(reg_store_conclude, y);

    // -------------------------------------------------------
    // Layer III
    // -------------------------------------------------------
    buffer output_buf("output_buf", {BATCH_SIZE, FOUT_NB_BLOCKS, N, N, FOUT_BLOCKING}, p_float32, a_output);

    buffer input_mean_buf("input_mean_buf", {FIN_NB_BLOCKS, FIN_BLOCKING}, p_float32, a_input);
    buffer input_sd_buf("input_sd_buf", {FIN_NB_BLOCKS, FIN_BLOCKING}, p_float32, a_input);

    buffer workspace_buf("workspace_buf", {BATCH_SIZE, N + 2, N + 2, FIN_BLOCKING}, p_float32, a_input);

    // This is where intermediate results of convolution will be stored.
    // We rely on the compiler to detect that this buffer can be mapped to CPU registers.
    buffer reg_buf("reg_buf", {FOUT_NB_BLOCKS, X_BLOCKING, FOUT_BLOCKING}, p_float32, a_temporary);

    input_sum_init.store_in(&input_mean_buf);
    input_sum.store_in(&input_mean_buf, {fin_b, ffin});
    input_mean.store_in(&input_mean_buf);

    input_sum_squares_init.store_in(&input_sd_buf);
    input_sum_squares.store_in(&input_sd_buf, {fin_b, ffin});
    input_sd.store_in(&input_sd_buf);

    bn_prelude.store_in(&workspace_buf, {n, y_prelude, x_pad, ffin});
    relu_prelude.store_in(&workspace_buf, {n, y_prelude, x_pad, ffin});

    bn.store_in(&workspace_buf, {n, y + 2, x_pad, ffin});
    relu.store_in(&workspace_buf, {n, y + 2, x_pad, ffin});

    /*
     * Storage for conv
     */
    relu_view.store_in(&workspace_buf, {n, y_pad, x_pad, ffin});

    conv_init.store_in(&output_buf, {n, fout_b, y, x, ffout});
    conv_out.store_in(&reg_buf, {fout_b, x%X_BLOCKING, ffout});

    reg_load.store_in(&reg_buf, {fout_b, x_bound%X_BLOCKING, ffout});
    conv.store_in(&reg_buf, {fout_b, x_bound%X_BLOCKING, ffout});
    reg_store.store_in(&output_buf, {n, fout_b, y, x_bound, ffout});

    reg_load_conclude.store_in(&reg_buf, {fout_b, x_conclude%X_BLOCKING, ffout});
    conv_conclude.store_in(&reg_buf, {fout_b, x_conclude%X_BLOCKING, ffout});
    reg_store_conclude.store_in(&output_buf, {n, fout_b, y, x_conclude, ffout});

    // -------------------------------------------------------
    // Code Generation
    // -------------------------------------------------------
    codegen({
        c_input.get_buffer(),
        bn_scale.get_buffer(),
        bn_shift.get_buffer(),
        conv_filter.get_buffer(),
        conv_bias.get_buffer(),
        &input_mean_buf,
        &input_sd_buf,
        &workspace_buf,
        &output_buf
    }, "densenet_block_tiramisu.o");

    return 0;
}
<|endoftext|>


<commit_before>/*  This file is part of the KDE project
    Copyright (C) 2004-2006 Matthias Kretz <kretz@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License version 2 as published by the Free Software Foundation.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

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

*/

#include "factory.h"
#include "base_p.h"

#include <kservicetypetrader.h>
#include <klibloader.h>
#include <kmessagebox.h>
#include <QFile>
#include <QList>
#include <klocale.h>
#include <kmimetype.h>
#include <kdebug.h>
#include <kstaticdeleter.h>

#include <QtDBus/QtDBus>

static KStaticDeleter<Phonon::Factory> sd;

#define PHONON_LOAD_BACKEND_GLOBAL 1

namespace Phonon
{
class Factory::Private
{
	public:
		Private()
			: backend( 0 )
		{
			qRegisterMetaType<qint64>( "qint64" );
			qRegisterMetaType<qint32>( "qint32" );
		}

		void createBackend()
		{
			const KService::List offers = KServiceTypeTrader::self()->query( "PhononBackend",
					"Type == 'Service' and [X-KDE-PhononBackendInfo-InterfaceVersion] == 1" );
			KService::List::const_iterator it = offers.begin();
			const KService::List::const_iterator end = offers.end();
			QStringList errormsg;
			for( ; it != end; ++it )
			{
				KService::Ptr ptr = *it;
				KLibFactory* factory = 0;
#ifdef PHONON_LOAD_BACKEND_GLOBAL
				// This code is in here temporarily until NMM gets fixed.
				// Currently the NMM backend will fail with undefined symbols if
				// the backend is not loaded with global symbol resolution
				KLibrary* library = KLibLoader::self()->library( QFile::encodeName( ptr->library() ), QLibrary::ExportExternalSymbolsHint );
				if( library )
					factory = library->factory();
#else
				factory = KLibLoader::self()->factory( QFile::encodeName( ptr->library() ) );
#endif
				if( factory )
				{
					backend = factory->create();
					if( 0 == backend )
					{
						QString e = i18n( "create method returned 0" );
						errormsg.append( e );
						kDebug( 600 ) << "Error getting backend from factory for " <<
							ptr->name() << ", " << ptr->library() << ":\n" << e << endl;
					}
					else
					{
						service = ptr;
						kDebug( 600 ) << "using backend: " << ptr->name() << endl;
						break;
					}
				}
				else
				{
					QString e = KLibLoader::self()->lastErrorMessage();
					errormsg.append( e );
					kDebug( 600 ) << "Error getting factory for " << ptr->name() <<
						":\n" << e << endl;
				}
			}
			if( 0 == backend )
			{
				if( offers.size() == 0 )
					KMessageBox::error( 0, i18n( "Unable to find a Multimedia Backend" ) );
				else
				{
					QString details = "<qt>
";
					QStringList::Iterator eit = errormsg.begin();
					QStringList::Iterator eend = errormsg.end();
					KService::List::const_iterator oit = offers.begin();
					const KService::List::const_iterator oend = offers.end();
					for( ; eit != eend || oit != oend; ++eit, ++oit )
						details += QString( "
%1	%2
" )
							.arg( ( *oit )->name() ).arg( *eit );
					details += "
</qt>";

					KMessageBox::detailedError( 0,
							i18n( "Unable to use any of the available Multimedia Backends" ), details );
				}
			}
		}

		QObject* backend;
		KService::Ptr service;

		QList<QObject*> objects;
		QList<BasePrivate*> basePrivateList;
};

Factory * Factory::m_self = 0;

Factory * Factory::self()
{
	if( ! m_self )
	{
		m_self = new Factory();
		::sd.setObject( m_self, m_self );
	}
	return m_self;
}

Factory::Factory()
	: d( new Private )
{
	QDBusConnection::sessionBus().connect(QString(), QString(), "org.kde.Phonon.Factory",
			"phononBackendChanged", this, SLOT(phononBackendChanged()));
}

Factory::~Factory()
{
	//kDebug( 600 ) << k_funcinfo << endl;
	emit aboutToBeDestroyed();

	foreach( BasePrivate* bp, d->basePrivateList )
		bp->deleteIface();
	qDeleteAll(d->objects);
	delete d->backend;
	delete d;
}

void Factory::registerFrontendObject( BasePrivate* bp )
{
	d->basePrivateList.append( bp );
}

void Factory::deregisterFrontendObject( BasePrivate* bp )
{
	d->basePrivateList.removeAll( bp );
}

void Factory::phononBackendChanged()
{
	if( d->backend )
	{
		foreach( BasePrivate* bp, d->basePrivateList )
			bp->deleteIface();
		if( d->objects.size() > 0 )
		{
			kWarning( 600 ) << "we were asked to change the backend but the application did\n"
				"not free all references to objects created by the factory. Therefore we can not\n"
				"change the backend without crashing. Now we have to wait for a restart to make\n"
				"backendswitching possible." << endl;
			// in case there were objects deleted give 'em a chance to recreate
			// them now
			foreach( BasePrivate* bp, d->basePrivateList )
				bp->createIface();
			return;
		}
		delete d->backend;
		d->backend = 0;
	}
	d->createBackend();
	foreach( BasePrivate* bp, d->basePrivateList )
		bp->createIface();
	emit backendChanged();
}

//X void Factory::freeSoundcardDevices()
//X {
//X 	if( d->backend )
//X 	{
//X 		d->backend->freeSoundcardDevices();
//X 	}
//X }

void Factory::objectDestroyed( QObject * obj )
{
	//kDebug( 600 ) << k_funcinfo << obj << endl;
	d->objects.removeAll( obj );
}

#define FACTORY_IMPL( classname ) \
QObject* Factory::create ## classname( QObject* parent ) \
{ \
	if( backend() ) \
	{ \
		QObject* ret; \
		if( QMetaObject::invokeMethod( d->backend, "create"#classname, Qt::DirectConnection, Q_RETURN_ARG( QObject*, ret ), Q_ARG( QObject*, parent ) ) ) \
			return registerQObject( ret ); \
	} \
	return 0; \
}
#define FACTORY_IMPL_1ARG( type1, classname ) \
QObject* Factory::create ## classname( type1 name1, QObject* parent ) \
{ \
	if( backend() ) \
	{ \
		QObject* ret; \
		if( QMetaObject::invokeMethod( d->backend, "create"#classname, Qt::DirectConnection, Q_RETURN_ARG( QObject*, ret ), Q_ARG( type1, name1 ), Q_ARG( QObject*, parent ) ) ) \
			return registerQObject( ret ); \
	} \
	return 0; \
}

FACTORY_IMPL( MediaObject )
FACTORY_IMPL( MediaQueue )
FACTORY_IMPL( AvCapture )
FACTORY_IMPL( ByteStream )
FACTORY_IMPL( AudioPath )
FACTORY_IMPL_1ARG( int, AudioEffect )
FACTORY_IMPL( VolumeFaderEffect )
FACTORY_IMPL( AudioOutput )
FACTORY_IMPL( AudioDataOutput )
FACTORY_IMPL( Visualization )
FACTORY_IMPL( VideoPath )
FACTORY_IMPL_1ARG( int, VideoEffect )
FACTORY_IMPL( BrightnessControl )
FACTORY_IMPL( VideoDataOutput )

#undef FACTORY_IMPL

QObject* Factory::backend( bool createWhenNull )
{
	if( createWhenNull && d->backend == 0 )
	{
		d->createBackend();
		// XXX: might create "reentrancy" problems:
		// a method calls this method and is called again because the
		// backendChanged signal is emitted
		emit backendChanged();
	}
	return d->backend;
}

const char* Factory::uiLibrary()
{
	if( !backend() )
		return 0;
	const char* ret = 0;
	QMetaObject::invokeMethod( d->backend, "uiLibrary", Qt::DirectConnection, Q_RETURN_ARG( const char*, ret ) );
	return ret;
}

const char* Factory::uiSymbol()
{
	if( !backend() )
		return 0;
	const char* ret = 0;
	// the backend doesn't have to implement the symbol - the default factory
	// symbol will be used then
	if( QMetaObject::invokeMethod( d->backend, "uiSymbol", Qt::DirectConnection, Q_RETURN_ARG( const char*, ret ) ) )
		return ret;
	return 0;
}

QString Factory::backendName() const
{
	if( d->service )
		return d->service->name();
	else
		return QString();
}

QString Factory::backendComment() const
{
	if( d->service )
		return d->service->comment();
	else
		return QString();
}

QString Factory::backendVersion() const
{
	if( d->service )
		return d->service->property( "X-KDE-PhononBackendInfo-Version" ).toString();
	else
		return QString();
}

QString Factory::backendIcon() const
{
	if( d->service )
		return d->service->icon();
	else
		return QString();
}

QString Factory::backendWebsite() const
{
	if( d->service )
		return d->service->property( "X-KDE-PhononBackendInfo-Website" ).toString();
	else
		return QString();
}

QObject* Factory::registerQObject( QObject* o )
{
	connect( o, SIGNAL( destroyed( QObject* ) ), SLOT( objectDestroyed( QObject* ) ), Qt::DirectConnection );
	d->objects.append( o );
	return o;
}

} //namespace Phonon

#include "factory.moc"

// vim: sw=4 ts=4 noet
<commit_msg>ignore null pointers<commit_after>/*  This file is part of the KDE project
    Copyright (C) 2004-2006 Matthias Kretz <kretz@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License version 2 as published by the Free Software Foundation.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

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

*/

#include "factory.h"
#include "base_p.h"

#include <kservicetypetrader.h>
#include <klibloader.h>
#include <kmessagebox.h>
#include <QFile>
#include <QList>
#include <klocale.h>
#include <kmimetype.h>
#include <kdebug.h>
#include <kstaticdeleter.h>

#include <QtDBus/QtDBus>

static KStaticDeleter<Phonon::Factory> sd;

#define PHONON_LOAD_BACKEND_GLOBAL 1

namespace Phonon
{
class Factory::Private
{
	public:
		Private()
			: backend( 0 )
		{
			qRegisterMetaType<qint64>( "qint64" );
			qRegisterMetaType<qint32>( "qint32" );
		}

		void createBackend()
		{
			const KService::List offers = KServiceTypeTrader::self()->query( "PhononBackend",
					"Type == 'Service' and [X-KDE-PhononBackendInfo-InterfaceVersion] == 1" );
			KService::List::const_iterator it = offers.begin();
			const KService::List::const_iterator end = offers.end();
			QStringList errormsg;
			for( ; it != end; ++it )
			{
				KService::Ptr ptr = *it;
				KLibFactory* factory = 0;
#ifdef PHONON_LOAD_BACKEND_GLOBAL
				// This code is in here temporarily until NMM gets fixed.
				// Currently the NMM backend will fail with undefined symbols if
				// the backend is not loaded with global symbol resolution
				KLibrary* library = KLibLoader::self()->library( QFile::encodeName( ptr->library() ), QLibrary::ExportExternalSymbolsHint );
				if( library )
					factory = library->factory();
#else
				factory = KLibLoader::self()->factory( QFile::encodeName( ptr->library() ) );
#endif
				if( factory )
				{
					backend = factory->create();
					if( 0 == backend )
					{
						QString e = i18n( "create method returned 0" );
						errormsg.append( e );
						kDebug( 600 ) << "Error getting backend from factory for " <<
							ptr->name() << ", " << ptr->library() << ":\n" << e << endl;
					}
					else
					{
						service = ptr;
						kDebug( 600 ) << "using backend: " << ptr->name() << endl;
						break;
					}
				}
				else
				{
					QString e = KLibLoader::self()->lastErrorMessage();
					errormsg.append( e );
					kDebug( 600 ) << "Error getting factory for " << ptr->name() <<
						":\n" << e << endl;
				}
			}
			if( 0 == backend )
			{
				if( offers.size() == 0 )
					KMessageBox::error( 0, i18n( "Unable to find a Multimedia Backend" ) );
				else
				{
					QString details = "<qt>
";
					QStringList::Iterator eit = errormsg.begin();
					QStringList::Iterator eend = errormsg.end();
					KService::List::const_iterator oit = offers.begin();
					const KService::List::const_iterator oend = offers.end();
					for( ; eit != eend || oit != oend; ++eit, ++oit )
						details += QString( "
%1	%2
" )
							.arg( ( *oit )->name() ).arg( *eit );
					details += "
</qt>";

					KMessageBox::detailedError( 0,
							i18n( "Unable to use any of the available Multimedia Backends" ), details );
				}
			}
		}

		QObject* backend;
		KService::Ptr service;

		QList<QObject*> objects;
		QList<BasePrivate*> basePrivateList;
};

Factory * Factory::m_self = 0;

Factory * Factory::self()
{
	if( ! m_self )
	{
		m_self = new Factory();
		::sd.setObject( m_self, m_self );
	}
	return m_self;
}

Factory::Factory()
	: d( new Private )
{
	QDBusConnection::sessionBus().connect(QString(), QString(), "org.kde.Phonon.Factory",
			"phononBackendChanged", this, SLOT(phononBackendChanged()));
}

Factory::~Factory()
{
	//kDebug( 600 ) << k_funcinfo << endl;
	emit aboutToBeDestroyed();

	foreach( BasePrivate* bp, d->basePrivateList )
		bp->deleteIface();
	qDeleteAll(d->objects);
	delete d->backend;
	delete d;
}

void Factory::registerFrontendObject( BasePrivate* bp )
{
	d->basePrivateList.append( bp );
}

void Factory::deregisterFrontendObject( BasePrivate* bp )
{
	d->basePrivateList.removeAll( bp );
}

void Factory::phononBackendChanged()
{
	if( d->backend )
	{
		foreach( BasePrivate* bp, d->basePrivateList )
			bp->deleteIface();
		if( d->objects.size() > 0 )
		{
			kWarning( 600 ) << "we were asked to change the backend but the application did\n"
				"not free all references to objects created by the factory. Therefore we can not\n"
				"change the backend without crashing. Now we have to wait for a restart to make\n"
				"backendswitching possible." << endl;
			// in case there were objects deleted give 'em a chance to recreate
			// them now
			foreach( BasePrivate* bp, d->basePrivateList )
				bp->createIface();
			return;
		}
		delete d->backend;
		d->backend = 0;
	}
	d->createBackend();
	foreach( BasePrivate* bp, d->basePrivateList )
		bp->createIface();
	emit backendChanged();
}

//X void Factory::freeSoundcardDevices()
//X {
//X 	if( d->backend )
//X 	{
//X 		d->backend->freeSoundcardDevices();
//X 	}
//X }

void Factory::objectDestroyed( QObject * obj )
{
	//kDebug( 600 ) << k_funcinfo << obj << endl;
	d->objects.removeAll( obj );
}

#define FACTORY_IMPL( classname ) \
QObject* Factory::create ## classname( QObject* parent ) \
{ \
	if( backend() ) \
	{ \
		QObject* ret; \
		if( QMetaObject::invokeMethod( d->backend, "create"#classname, Qt::DirectConnection, Q_RETURN_ARG( QObject*, ret ), Q_ARG( QObject*, parent ) ) ) \
			return registerQObject( ret ); \
	} \
	return 0; \
}
#define FACTORY_IMPL_1ARG( type1, classname ) \
QObject* Factory::create ## classname( type1 name1, QObject* parent ) \
{ \
	if( backend() ) \
	{ \
		QObject* ret; \
		if( QMetaObject::invokeMethod( d->backend, "create"#classname, Qt::DirectConnection, Q_RETURN_ARG( QObject*, ret ), Q_ARG( type1, name1 ), Q_ARG( QObject*, parent ) ) ) \
			return registerQObject( ret ); \
	} \
	return 0; \
}

FACTORY_IMPL( MediaObject )
FACTORY_IMPL( MediaQueue )
FACTORY_IMPL( AvCapture )
FACTORY_IMPL( ByteStream )
FACTORY_IMPL( AudioPath )
FACTORY_IMPL_1ARG( int, AudioEffect )
FACTORY_IMPL( VolumeFaderEffect )
FACTORY_IMPL( AudioOutput )
FACTORY_IMPL( AudioDataOutput )
FACTORY_IMPL( Visualization )
FACTORY_IMPL( VideoPath )
FACTORY_IMPL_1ARG( int, VideoEffect )
FACTORY_IMPL( BrightnessControl )
FACTORY_IMPL( VideoDataOutput )

#undef FACTORY_IMPL

QObject* Factory::backend( bool createWhenNull )
{
	if( createWhenNull && d->backend == 0 )
	{
		d->createBackend();
		// XXX: might create "reentrancy" problems:
		// a method calls this method and is called again because the
		// backendChanged signal is emitted
		emit backendChanged();
	}
	return d->backend;
}

const char* Factory::uiLibrary()
{
	if( !backend() )
		return 0;
	const char* ret = 0;
	QMetaObject::invokeMethod( d->backend, "uiLibrary", Qt::DirectConnection, Q_RETURN_ARG( const char*, ret ) );
	return ret;
}

const char* Factory::uiSymbol()
{
	if( !backend() )
		return 0;
	const char* ret = 0;
	// the backend doesn't have to implement the symbol - the default factory
	// symbol will be used then
	if( QMetaObject::invokeMethod( d->backend, "uiSymbol", Qt::DirectConnection, Q_RETURN_ARG( const char*, ret ) ) )
		return ret;
	return 0;
}

QString Factory::backendName() const
{
	if( d->service )
		return d->service->name();
	else
		return QString();
}

QString Factory::backendComment() const
{
	if( d->service )
		return d->service->comment();
	else
		return QString();
}

QString Factory::backendVersion() const
{
	if( d->service )
		return d->service->property( "X-KDE-PhononBackendInfo-Version" ).toString();
	else
		return QString();
}

QString Factory::backendIcon() const
{
	if( d->service )
		return d->service->icon();
	else
		return QString();
}

QString Factory::backendWebsite() const
{
	if( d->service )
		return d->service->property( "X-KDE-PhononBackendInfo-Website" ).toString();
	else
		return QString();
}

QObject* Factory::registerQObject( QObject* o )
{
	if( o )
	{
		connect( o, SIGNAL( destroyed( QObject* ) ), SLOT( objectDestroyed( QObject* ) ), Qt::DirectConnection );
		d->objects.append( o );
	}
	return o;
}

} //namespace Phonon

#include "factory.moc"

// vim: sw=4 ts=4 noet
<|endoftext|>


<commit_before><commit_msg>Edited comments.<commit_after><|endoftext|>


<commit_before>/*###############################################################
## MODULE: hdp_medoids.cpp
## VERSION: 2.0
## SINCE 2014-07-21
## AUTHOR:
##     Jimmy Lin (xl5224) - JimmyLin@utexas.edu
##
## DESCRIPTION:
##     Convex relaxation for hdp_medoids resolution
#################################################################
## Edited by MacVim
## Class Info auto-generated by Snippet
################################################################*/

#include "hdp_medoids.h"
#include <set>
using namespace std;

/* Compute the mutual distance of input instances contained within "data" */
void compute_dist_mat (Esmat* dist_mat, Lookups* tables, int N, int D) {
    // STEP ZERO: parse input
    vector< pair<int,int> > doc_lookup = *(tables->doc_lookup);
    vector< pair<int,int> > word_lookup = *(tables->word_lookup);
    // STEP ONE: compute distribution for each document
    vector< map<int, double> > distributions (D, map<int, double>());
    for (int d = 0; d < D; d ++) {
        // a. compute sum of word frequency
        int sumFreq = 0;
        for (int w = doc_lookup[d].first; w < doc_lookup[d].second; w++) {
            sumFreq += word_lookup[w].second;
        }
        // b. compute distribution
        for (int w = doc_lookup[d].first; w < doc_lookup[d].second; w++) {
            int voc_index = word_lookup[w].first;
            double prob = 1.0 * word_lookup[w].second / sumFreq;
            distributions[d].insert(pair<int, double> (voc_index, prob));
        }
    }
    // STEP TWO: compute weight of word within one document
    esmat_zeros(dist_mat);
    for (int j = 0; j < D; j ++) {
        for (int d = 0; d < D; d ++) {
            for (int w = doc_lookup[d].first; w < doc_lookup[d].second; w++) {
                int voc_index = word_lookup[w].first;
                int count_w_d1 = word_lookup[w].second;
                double prob_w_d2;
                double dist;
                map<int, double>::const_iterator iter;
                iter = distributions[j].find(voc_index);
                if (iter == distributions[j].end()) {
                    prob_w_d2 = 0.0;
                    dist = INF;
                } else {
                    prob_w_d2 = iter->second;
                //   dist(w, d2) =  - count_w_d1 * log( prob_d2(w) )
                    dist = - count_w_d1 * log(prob_w_d2);
                }
                int esmat_index = w + N * j;
#ifdef DIST_MAT_DUMP
                cout << "index: " << esmat_index << ", dist: " << dist << ", ";
                cout << "count_w_d1: " << count_w_d1 << ", prob_w_d2: " << prob_w_d2 << endl;
#endif
                dist_mat->val.push_back(make_pair(esmat_index, dist));
            }
        }
    }
}
void output_objective (vector<int> z, vector< vector<int> > v, double** dist_mat, Lookups* tables) {
    int N = tables->nWords;
    int D = tables->nDocs;
    double obj = 0.0;
    fstream obj_out("opt_objective");
    for (int d = 0; d < D; d ++) {
        for (int i = doc_lookup[d].first; i < doc_lookup[d].second; i++) {
            int g = v[d][z[i]];
            double dist = dist_mat[i][g];
            obj += dist;
        }
    }
    obj_out << obj;
}
void output_medoids (vector<int> global_medoids, Lookups* tables) {
    int N = tables->nWords;
    int D = tables->nDocs;
    int local_medoids = 0;
    fstream medoids_out("opt_medoids");
    int nGlobalMedoids = global_medoids.size();
    for (int i = 0; i < nGlobalMedoids; i ++) {
        cout << "Medoids" << global_medoids[i] << endl;
    }
    medoids_out.close();
}
void output_medoids () {
    int N = tables->nWords;
}
void hdp_medoids (Esmat* dist_mat, vector<double> LAMBDAs, Lookups* tables) {
    // SET MODEL-RELEVANT PARAMETERS
    assert (LAMBDAs.size() == 2);
    double lambda_global = LAMBDAs[0];
    double lambda_local = LAMBDAs[1];
    double ALPHA = 1.0;
    double RHO = 1.0;
    int N = tables->nWords;
    int D = tables->nDocs;
    vector< pair<int,int> > doc_lookup = *(tables->doc_lookup);
    vector< pair<int,int> > word_lookup = *(tables->word_lookup);

    /* A. DECLARE AND INITIALIZE INVOLVED VARIABLES AND MATRICES */
    vector<int> global_medoids (1,0);
    // vector< vector<int> > local_medoids (D,vector<int>(1,0));
    vector<int> z (N, 0);
    vector< vector<int> > v (D,vector<int>(1,0));
    // 1) randomize initial global cluster medoid
    global_medoids[0] = random() % D;
    // 2) randomize initial local cluster medoids for each document j
    ;
    // 3) initialize local cluster indicator z_ij = 1 for all j = 1
    for (int d = 0; d < D; d ++) {
        for (int i = doc_lookup[d].first; i < doc_lookup[d].second; i++) {
            z[i] = 0;
        }
    }
    // 4) initialize global cluster association v_j1 = 1
    for (int d = 0; d < D; d ++) {
        v[d][0] = global_medoids[0];
    }
    /* B. Repetition until Convergence */
    int iter = 0;
    int MAX_ITER = 1000;
    while (iter < MAX_ITER) {
        for (int d = 0; d < D; d++) {
            for (int i = doc_lookup[d].first; i < doc_lookup[d].second; i ++) {
                // 1) preprocess distance
                double[] processed_dist_mat = new double [D];
                for (int examplar = 0; examplar < D; examplar ++) {
                    int esmat_index = i + examplar * N;
                    int value = dist_mat[i][examplar];
                    processed_dist_mat[examplar] = value;
                }
                set<int> temp;
                int nGlobalMedoids= global_medoids.size();
                for (int g = 0; g < nGlobalMedoids; g++)
                    temp.insert(global_medoids[g]);
                // int nLocalMedoids = local_medoids[d].size();
                int nLocalMedoids = v[d].size();
                for (int l = 0; l < nLocalMedoids; l++)
                    // temp.erase(local_medoids[d][l]);
                    temp.erase(v[d][l]);
                for (set<int>::iterator it=myset.begin();it!=myset.end();++it)
                    processed_dist_mat[*it] += lambda_local;
                // 2) if ..,  global and local augmentation
                //  if min_p d_ijp > \lambda_l + \lambda_g
                int min_index = -1;
                double min_value = INF;
                for (int index = 0; index < D; index ++) {
                    if (processed_dist_mat[index] < min_value) {
                        min_index = index;
                        min_value = processed_dist_mat[index];
                    }
                }
                if (min_value > lambda_local+lambda_global) {
                    global_medoids.push_back(min_index);
                    v[d].push_back(min_index);
                    z[i] = nLocalMedoids;
                    nLocalMedoids ++;
                }
                // 3) otherwise, local assignment or local augmentation
                else {
                    bool is_c_exist = false;
                    nLocalMedoids = v[d].size();
                    for (int l = 0; l < nLocalMedoids; l ++) {
                        if (v[d][l] == min_index) {
                            z[i] = l;
                            is_c_exist = true;
                            break;
                        }
                    }
                    if (!is_c_exist) { // local augmentation
                        v[d].push_back(min_index);
                        z[i] = nLocalMedoids;
                        nLocalMedoids ++;
                    }
                }
                delete[] processed_dist_mat;
            }
        }
        // 4) re-elect medoids for all local clusters
        for (int d = 0; d < D; d++) {
            int nLocalMedoids = v[d].size();
            for (int l = 0; l < nLocalMedoids; l++) {
                vector<int> words;
                // set<int> examplars;
                // examplars.insert(d);
                for (int i = doc_lookup[d].first; i < doc_lookup[d].second; i++) {
                    if (z[i] == l) {
                        words.push_back(i);
                        // examplars.insert(z[i]);
                    }
                }
                int nDocWords = words.size();
                double ** temp_dist_mat = mat_init(nDocWords, D);
                for (int w = 0; w < nDocWords; w++)
                    for (int td = 0; td < D; td++)
                        temp_dist_mat[w][td] = dist_mat[words[w]][td];
                double * sum_temp_dist_col = new double [D];
                mat_sum_col (temp_dist_mat, sum_temp_dist_col, nDocWords, D);
                int min_index = -1;
                double min_value = INF; // min sum mu_jc
                for (int td = 0; td < D; td++) {
                    if (sum_temp_dist_col[td] < min_value) {
                        min_index = td;
                        min_value = sum_temp_dist_col[td];
                    }
                }
                v[d][l] = min_index; // update the better medoid
                delete[] sum_temp_dist_col;
                mat_free (temp_dist_mat, nDocWords, D);
                /*
                // 5) if .., global augmentation
                //  if min_p d_jcp > \lambda_g + ...
                if (min_d_jcp > lambda_global+) {
                    global_medoids.push_back(new_g);
                    local_medoids[][] = new_g;
                }
                // 6) otherwise, update global association
                else {
                    local_medoids[][] = new_g;
                }
                */
            }
        }

        // 7) re-elect medoids for global cluster
        int nGlobalMedoids = global_medoids.size();
        for (int g = 0; g < nGlobalMedoids; g++) {
            p = global_medoids[g];
            vector<int> words;
            set<int> examplar_set;
            for (int d = 0; d < D; d++) {
                for (int i = doc_lookup[d].first; i < doc_lookup[d].second; i ++) {
                    if (v[z[i]] == p) {
                        words.push_back(i);
                        examplar_set.insert(d);
                    }
                }
            }
            vector<int> examplars;
            for (set<int>::iterator it=myset.begin();it!=myset.end();++it)
                examplars.push_back(*it);
            }
            int R = words.size();
            int C = examplars.size();
            double** candidate_dist_mat = mat_init (R,C);
            for (int r = 0; r < R; r ++) {
                for (int c = 0; c < C; c ++) {
                    candidate_dist_mat[r][c] = dist_mat[words[r]][examplars[c]];
                }
            }
            double* min_d_rc = new double [C];
            mat_sum_col (candidate_dist_mat, min_d_rc, R,C);
            int min_index;
            double min_value = INF;
            for (int m = 0; m < C; m ++) {
                if (min_d_rc[m] < min_value) {
                    min_index = m;
                    min_value = min_d_rc[m];
                }
            }
            int new_p = examplars[m];
            global_medoids[g] = new_p; // update
            delete[] min_d_rc;
            mat_free (candidate_dist_mat, R,C);
        }
    }
    /* Put converged solution to destinated W*/
}

// entry main function
int main (int argc, char ** argv) {

    // EXCEPTION control: illustrate the usage if get input of wrong format
    if (argc < 5) {
        cerr << "Usage: " << endl;
        cerr << "\thdp_medoids [voc_dataFile] [doc_dataFile] [lambda_global] [lambda_local]" << endl;
        exit(-1);
    }

    // PARSE arguments
    string voc_file (argv[1]);
    string doc_file (argv[2]);
    vector<double> LAMBDAs (2, 0.0);
    LAMBDAs[0] = atof(argv[3]); // lambda_document
    LAMBDAs[1] = atof(argv[4]); // lambda_topic

    // preprocess the input dataset
    vector<string> voc_list;
    voc_list_read (voc_file, &voc_list);
    int nVocs = voc_list.size();

    // init lookup_tables
    vector< pair<int,int> > doc_lookup;
    vector< pair<int,int> > word_lookup;
    vector< vector<int> > voc_lookup (nVocs, vector<int>());
    Lookups lookup_tables;
    lookup_tables.doc_lookup = &doc_lookup;
    lookup_tables.word_lookup = &word_lookup;
    lookup_tables.voc_lookup = &voc_lookup;

    document_list_read (doc_file, &lookup_tables);
    lookup_tables.nDocs = lookup_tables.doc_lookup->size();
    lookup_tables.nWords = lookup_tables.word_lookup->size();
    lookup_tables.nVocs = nVocs;

    int seed = time(NULL);
    srand (seed);
    cerr << "###########################################" << endl;
    cerr << "nVocs = " << lookup_tables.nVocs << endl; // # vocabularies
    cerr << "nDocs = " << lookup_tables.nDocs << endl; // # documents
    cerr << "nWords = " << lookup_tables.nWords << endl; // # words
    cerr << "lambda_global = " << LAMBDAs[0] << endl;
    cerr << "lambda_local = " << LAMBDAs[1] << endl;
    cerr << "TRIM_THRESHOLD = " << TRIM_THRESHOLD << endl;
    cerr << "seed = " << seed << endl;
    cerr << "###########################################" << endl;

    // Run sparse convex clustering
    int N = lookup_tables.nWords;
    int D = lookup_tables.nDocs;
    Esmat* W = esmat_init (lookup_tables.nWords, lookup_tables.nDocs);
    Esmat* dist_mat = esmat_init (N, D);
    compute_dist_mat (dist_mat, &lookup_tables, N, D);

    ofstream dmat_out ("dist_mat");
    dmat_out << esmat_toInfo(dist_mat);
    dmat_out << esmat_toString(dist_mat);
    hdp_medoids (dist_mat, LAMBDAs, W, &lookup_tables);

    /* Output objective */
    output_objective(clustering_objective (dist_mat, W));

    /* Output cluster centroids */
    output_model (W);

    /* Output assignment */
    output_assignment (W, &word_lookup);

    /* reallocation */
    esmat_free (W);
    esmat_free (dist_mat);
}
<commit_msg>more pushed<commit_after>/*###############################################################
## MODULE: hdp_medoids.cpp
## VERSION: 2.0
## SINCE 2014-07-21
## AUTHOR:
##     Jimmy Lin (xl5224) - JimmyLin@utexas.edu
##
## DESCRIPTION:
##     Convex relaxation for hdp_medoids resolution
#################################################################
## Edited by MacVim
## Class Info auto-generated by Snippet
################################################################*/

#include "hdp_medoids.h"
#include <set>
using namespace std;

/* Compute the mutual distance of input instances contained within "data" */
void compute_dist_mat (Esmat* dist_mat, Lookups* tables, int N, int D) {
    // STEP ZERO: parse input
    vector< pair<int,int> > doc_lookup = *(tables->doc_lookup);
    vector< pair<int,int> > word_lookup = *(tables->word_lookup);
    // STEP ONE: compute distribution for each document
    vector< map<int, double> > distributions (D, map<int, double>());
    for (int d = 0; d < D; d ++) {
        // a. compute sum of word frequency
        int sumFreq = 0;
        for (int w = doc_lookup[d].first; w < doc_lookup[d].second; w++) {
            sumFreq += word_lookup[w].second;
        }
        // b. compute distribution
        for (int w = doc_lookup[d].first; w < doc_lookup[d].second; w++) {
            int voc_index = word_lookup[w].first;
            double prob = 1.0 * word_lookup[w].second / sumFreq;
            distributions[d].insert(pair<int, double> (voc_index, prob));
        }
    }
    // STEP TWO: compute weight of word within one document
    esmat_zeros(dist_mat);
    for (int j = 0; j < D; j ++) {
        for (int d = 0; d < D; d ++) {
            for (int w = doc_lookup[d].first; w < doc_lookup[d].second; w++) {
                int voc_index = word_lookup[w].first;
                int count_w_d1 = word_lookup[w].second;
                double prob_w_d2;
                double dist;
                map<int, double>::const_iterator iter;
                iter = distributions[j].find(voc_index);
                if (iter == distributions[j].end()) {
                    prob_w_d2 = 0.0;
                    dist = INF;
                } else {
                    prob_w_d2 = iter->second;
                //   dist(w, d2) =  - count_w_d1 * log( prob_d2(w) )
                    dist = - count_w_d1 * log(prob_w_d2);
                }
                int esmat_index = w + N * j;
#ifdef DIST_MAT_DUMP
                cout << "index: " << esmat_index << ", dist: " << dist << ", ";
                cout << "count_w_d1: " << count_w_d1 << ", prob_w_d2: " << prob_w_d2 << endl;
#endif
                dist_mat->val.push_back(make_pair(esmat_index, dist));
            }
        }
    }
}
void output_objective (vector<int> z, vector< vector<int> > v, double** dist_mat, Lookups* tables) {
    int N = tables->nWords;
    double obj = 0.0;
    fstream obj_out("opt_objective");
    for (int d = 0; d < D; d ++) {
        for (int i = doc_lookup[d].first; i < doc_lookup[d].second; i++) {
            int g = v[d][z[i]];
            double dist = dist_mat[i][g];
            obj += dist;
        }
    }
    obj_out << "Main: " << obj << endl;
    obj_out << "Global: " << global << endl;
    obj_out << "Local: " << local << endl;
    obj_out.close();
}
void output_medoids (vector<int> global_medoids, Lookups* tables) {
    int N = tables->nWords;
    int local_medoids = 0;
    fstream medoids_out("opt_medoids");
    int nGlobalMedoids = global_medoids.size();
    for (int i = 0; i < nGlobalMedoids; i ++) {
        cout << "Medoids[" << i << "]" << global_medoids[i] << endl;
    }
    medoids_out.close();
}
void output_assignment (vector<int> z, vector<vector<int> > v, Lookups* tables) {
    int D = tables->nDocs;
    fstream asgn_out("opt_assignments");
    for (int d = 0; d < D; d ++) {
        asgn_out << "d = " << d << endl;
        for (int i = doc_lookup[d].first; i < doc_lookup[d].second; i++) {
            asgn_out << "id=" << i+1 << ", " << v[d][z[i]] << "(1)" << endl;
        }
    }
    asgn_out.close();
}
void hdp_medoids (Esmat* dist_mat, vector<double> LAMBDAs, Lookups* tables) {
    // SET MODEL-RELEVANT PARAMETERS
    assert (LAMBDAs.size() == 2);
    double lambda_global = LAMBDAs[0];
    double lambda_local = LAMBDAs[1];
    double ALPHA = 1.0;
    double RHO = 1.0;
    int N = tables->nWords;
    int D = tables->nDocs;
    vector< pair<int,int> > doc_lookup = *(tables->doc_lookup);
    vector< pair<int,int> > word_lookup = *(tables->word_lookup);

    /* A. DECLARE AND INITIALIZE INVOLVED VARIABLES AND MATRICES */
    vector<int> global_medoids (1,0);
    // vector< vector<int> > local_medoids (D,vector<int>(1,0));
    vector<int> z (N, 0);
    vector< vector<int> > v (D,vector<int>(1,0));
    // 1) randomize initial global cluster medoid
    global_medoids[0] = random() % D;
    // 2) randomize initial local cluster medoids for each document j
    ;
    // 3) initialize local cluster indicator z_ij = 1 for all j = 1
    for (int d = 0; d < D; d ++) {
        for (int i = doc_lookup[d].first; i < doc_lookup[d].second; i++) {
            z[i] = 0;
        }
    }
    // 4) initialize global cluster association v_j1 = 1
    for (int d = 0; d < D; d ++) {
        v[d][0] = global_medoids[0];
    }
    /* B. Repetition until Convergence */
    int iter = 0;
    int MAX_ITER = 1000;
    while (iter < MAX_ITER) {
        for (int d = 0; d < D; d++) {
            for (int i = doc_lookup[d].first; i < doc_lookup[d].second; i ++) {
                // 1) preprocess distance
                double[] processed_dist_mat = new double [D];
                for (int examplar = 0; examplar < D; examplar ++) {
                    int esmat_index = i + examplar * N;
                    int value = dist_mat[i][examplar];
                    processed_dist_mat[examplar] = value;
                }
                set<int> temp;
                int nGlobalMedoids= global_medoids.size();
                for (int g = 0; g < nGlobalMedoids; g++)
                    temp.insert(global_medoids[g]);
                // int nLocalMedoids = local_medoids[d].size();
                int nLocalMedoids = v[d].size();
                for (int l = 0; l < nLocalMedoids; l++)
                    // temp.erase(local_medoids[d][l]);
                    temp.erase(v[d][l]);
                for (set<int>::iterator it=myset.begin();it!=myset.end();++it)
                    processed_dist_mat[*it] += lambda_local;
                // 2) if ..,  global and local augmentation
                //  if min_p d_ijp > \lambda_l + \lambda_g
                int min_index = -1;
                double min_value = INF;
                for (int index = 0; index < D; index ++) {
                    if (processed_dist_mat[index] < min_value) {
                        min_index = index;
                        min_value = processed_dist_mat[index];
                    }
                }
                if (min_value > lambda_local+lambda_global) {
                    global_medoids.push_back(min_index);
                    v[d].push_back(min_index);
                    z[i] = nLocalMedoids;
                    nLocalMedoids ++;
                }
                // 3) otherwise, local assignment or local augmentation
                else {
                    bool is_c_exist = false;
                    nLocalMedoids = v[d].size();
                    for (int l = 0; l < nLocalMedoids; l ++) {
                        if (v[d][l] == min_index) {
                            z[i] = l;
                            is_c_exist = true;
                            break;
                        }
                    }
                    if (!is_c_exist) { // local augmentation
                        v[d].push_back(min_index);
                        z[i] = nLocalMedoids;
                        nLocalMedoids ++;
                    }
                }
                delete[] processed_dist_mat;
            }
        }
        // 4) re-elect medoids for all local clusters
        for (int d = 0; d < D; d++) {
            int nLocalMedoids = v[d].size();
            for (int l = 0; l < nLocalMedoids; l++) {
                vector<int> words;
                // set<int> examplars;
                // examplars.insert(d);
                for (int i = doc_lookup[d].first; i < doc_lookup[d].second; i++) {
                    if (z[i] == l) {
                        words.push_back(i);
                        // examplars.insert(z[i]);
                    }
                }
                int nDocWords = words.size();
                double ** temp_dist_mat = mat_init(nDocWords, D);
                for (int w = 0; w < nDocWords; w++)
                    for (int td = 0; td < D; td++)
                        temp_dist_mat[w][td] = dist_mat[words[w]][td];
                double * sum_temp_dist_col = new double [D];
                mat_sum_col (temp_dist_mat, sum_temp_dist_col, nDocWords, D);
                int min_index = -1;
                double min_value = INF; // min sum mu_jc
                for (int td = 0; td < D; td++) {
                    if (sum_temp_dist_col[td] < min_value) {
                        min_index = td;
                        min_value = sum_temp_dist_col[td];
                    }
                }
                v[d][l] = min_index; // update the better medoid
                delete[] sum_temp_dist_col;
                mat_free (temp_dist_mat, nDocWords, D);
                /*
                // 5) if .., global augmentation
                //  if min_p d_jcp > \lambda_g + ...
                if (min_d_jcp > lambda_global+) {
                    global_medoids.push_back(new_g);
                    local_medoids[][] = new_g;
                }
                // 6) otherwise, update global association
                else {
                    local_medoids[][] = new_g;
                }
                */
            }
        }

        // 7) re-elect medoids for global cluster
        int nGlobalMedoids = global_medoids.size();
        for (int g = 0; g < nGlobalMedoids; g++) {
            p = global_medoids[g];
            vector<int> words;
            set<int> examplar_set;
            for (int d = 0; d < D; d++) {
                for (int i = doc_lookup[d].first; i < doc_lookup[d].second; i ++) {
                    if (v[z[i]] == p) {
                        words.push_back(i);
                        examplar_set.insert(d);
                    }
                }
            }
            vector<int> examplars;
            for (set<int>::iterator it=myset.begin();it!=myset.end();++it)
                examplars.push_back(*it);
            }
            int R = words.size();
            int C = examplars.size();
            double** candidate_dist_mat = mat_init (R,C);
            for (int r = 0; r < R; r ++) {
                for (int c = 0; c < C; c ++) {
                    candidate_dist_mat[r][c] = dist_mat[words[r]][examplars[c]];
                }
            }
            double* min_d_rc = new double [C];
            mat_sum_col (candidate_dist_mat, min_d_rc, R,C);
            int min_index;
            double min_value = INF;
            for (int m = 0; m < C; m ++) {
                if (min_d_rc[m] < min_value) {
                    min_index = m;
                    min_value = min_d_rc[m];
                }
            }
            int new_p = examplars[m];
            global_medoids[g] = new_p; // update
            delete[] min_d_rc;
            mat_free (candidate_dist_mat, R,C);
        }
    }
    /* Put converged solution to destinated W*/
}

// entry main function
int main (int argc, char ** argv) {

    // EXCEPTION control: illustrate the usage if get input of wrong format
    if (argc < 5) {
        cerr << "Usage: " << endl;
        cerr << "\thdp_medoids [voc_dataFile] [doc_dataFile] [lambda_global] [lambda_local]" << endl;
        exit(-1);
    }

    // PARSE arguments
    string voc_file (argv[1]);
    string doc_file (argv[2]);
    vector<double> LAMBDAs (2, 0.0);
    LAMBDAs[0] = atof(argv[3]); // lambda_document
    LAMBDAs[1] = atof(argv[4]); // lambda_topic

    // preprocess the input dataset
    vector<string> voc_list;
    voc_list_read (voc_file, &voc_list);
    int nVocs = voc_list.size();

    // init lookup_tables
    vector< pair<int,int> > doc_lookup;
    vector< pair<int,int> > word_lookup;
    vector< vector<int> > voc_lookup (nVocs, vector<int>());
    Lookups lookup_tables;
    lookup_tables.doc_lookup = &doc_lookup;
    lookup_tables.word_lookup = &word_lookup;
    lookup_tables.voc_lookup = &voc_lookup;

    document_list_read (doc_file, &lookup_tables);
    lookup_tables.nDocs = lookup_tables.doc_lookup->size();
    lookup_tables.nWords = lookup_tables.word_lookup->size();
    lookup_tables.nVocs = nVocs;

    int seed = time(NULL);
    srand (seed);
    cerr << "###########################################" << endl;
    cerr << "nVocs = " << lookup_tables.nVocs << endl; // # vocabularies
    cerr << "nDocs = " << lookup_tables.nDocs << endl; // # documents
    cerr << "nWords = " << lookup_tables.nWords << endl; // # words
    cerr << "lambda_global = " << LAMBDAs[0] << endl;
    cerr << "lambda_local = " << LAMBDAs[1] << endl;
    cerr << "TRIM_THRESHOLD = " << TRIM_THRESHOLD << endl;
    cerr << "seed = " << seed << endl;
    cerr << "###########################################" << endl;

    // Run sparse convex clustering
    int N = lookup_tables.nWords;
    int D = lookup_tables.nDocs;
    Esmat* W = esmat_init (lookup_tables.nWords, lookup_tables.nDocs);
    Esmat* dist_mat = esmat_init (N, D);
    compute_dist_mat (dist_mat, &lookup_tables, N, D);

    ofstream dmat_out ("dist_mat");
    dmat_out << esmat_toInfo(dist_mat);
    dmat_out << esmat_toString(dist_mat);
    hdp_medoids (dist_mat, LAMBDAs, W, &lookup_tables);

    /* Output objective */
    output_objective (z, v, dist_mat, &lookup_tables) {
    /* Output cluster centroids */
    output_medoids (global_medoids, &lookup_tables) {
    /* Output assignment */
    output_assignment (z, v, &lookup_tables) {

    /* reallocation */
    esmat_free (W);
    esmat_free (dist_mat);
}
<|endoftext|>


<commit_before>/*
 * edison_i2c.cpp
 *
 *  Created on: 2016. 2. 26.
 *      Author: hwang
 */

#include "edison_i2c.hpp"
#include <cossb.hpp>
#include <mraa.hpp>
#include <algorithm>

USE_COMPONENT_INTERFACE(edison_i2c)

edison_i2c::edison_i2c()
:cossb::interface::icomponent(COMPONENT(edison_i2c)){
	// TODO Auto-generated constructor stub

}

edison_i2c::~edison_i2c() {
	if(_i2c)
		delete _i2c;
}

bool edison_i2c::setup()
{
	if(!_i2c)
		_i2c = new mraa::I2c(0);

	//set address
	for(auto value: get_profile()->get(profile::section::property, "address")) {
		int address = value.asInt(0);
		address += ((address/16)+1)*6;
		cossb_log->log(log::loglevel::INFO, fmt::format("Set I2C Address : 0x{0:x}", address));

		if(address) {
			if(_i2c->address(address)!=mraa::Result::SUCCESS)
				return false;
			else
				cossb_log->log(log::loglevel::INFO, fmt::format("Set I2C Address : {}", value.asString("")));
			break;
		}
	}

	//set mode
	for(auto mode: get_profile()->get(profile::section::property, "mode")) {
		string m = mode.asString("");
		std::transform(m.begin(), m.end(), m.begin(), ::tolower);
		if(m.compare("i2c_std")==0)	_i2c->frequency(mraa::I2cMode::I2C_STD);	//up to 100khz
		else if(m.compare("i2c_high")==0)	_i2c->frequency(mraa::I2cMode::I2C_HIGH); //up to 3.4Mhz
		else if(m.compare("i2c_fast")==0)	_i2c->frequency(mraa::I2cMode::I2C_FAST);//up to 400khz
	}
	return true;
}

bool edison_i2c::run()
{
	return true;
}

bool edison_i2c::stop()
{
	return true;
}

void edison_i2c::request(cossb::base::message* const msg)
{
	if(!_i2c) {
		cossb_log->log(log::loglevel::ERROR, "No I2C Device");
		return;
	}

	switch(msg->get_frame()->type) {
	case cossb::base::msg_type::REQUEST: {
		if(!msg->get_frame()->topic.compare("service/i2c/write")) {
			cossb_log->log(log::loglevel::INFO, fmt::format("Received message (I2C) : {}", msg->show().c_str()));
		}
	}
		break;
	case cossb::base::msg_type::DATA: break;
	default:
		cossb_log->log(log::loglevel::INFO, "Received message has unsupported type.");
	}

}
<commit_msg>update for edison i2c component write<commit_after>/*
 * edison_i2c.cpp
 *
 *  Created on: 2016. 2. 26.
 *      Author: hwang
 */

#include "edison_i2c.hpp"
#include <cossb.hpp>
#include <mraa.hpp>
#include <algorithm>

USE_COMPONENT_INTERFACE(edison_i2c)

edison_i2c::edison_i2c()
:cossb::interface::icomponent(COMPONENT(edison_i2c)){
	// TODO Auto-generated constructor stub

}

edison_i2c::~edison_i2c() {
	if(_i2c)
		delete _i2c;
}

bool edison_i2c::setup()
{
	if(!_i2c)
		_i2c = new mraa::I2c(0);

	//set address
	for(auto value: get_profile()->get(profile::section::property, "address")) {
		int address = value.asInt(0);
		address += ((address/16)+1)*6;

		if(address) {
			if(_i2c->address(address)==mraa::Result::SUCCESS) {
				cossb_log->log(log::loglevel::INFO, fmt::format("Set I2C Address : 0x{0:x}", address));
				break;
			}
			else
				cossb_log->log(log::loglevel::INFO, fmt::format("Cannot Set I2C Address : 0x{0:x}", address));
		}
	}

	//set mode
	for(auto mode: get_profile()->get(profile::section::property, "mode")) {
		string m = mode.asString("");
		std::transform(m.begin(), m.end(), m.begin(), ::tolower);
		if(m.compare("i2c_std")==0)	_i2c->frequency(mraa::I2cMode::I2C_STD);	//up to 100khz
		else if(m.compare("i2c_high")==0)	_i2c->frequency(mraa::I2cMode::I2C_HIGH); //up to 3.4Mhz
		else if(m.compare("i2c_fast")==0)	_i2c->frequency(mraa::I2cMode::I2C_FAST);//up to 400khz
	}
	return true;
}

bool edison_i2c::run()
{
	return true;
}

bool edison_i2c::stop()
{
	return true;
}

void edison_i2c::request(cossb::base::message* const msg)
{
	if(!_i2c) {
		cossb_log->log(log::loglevel::ERROR, "No I2C Device");
		return;
	}

	switch(msg->get_frame()->type) {
	case cossb::base::msg_type::REQUEST: {
		if(!msg->get_frame()->topic.compare("service/i2c/write")) {
			cossb_log->log(log::loglevel::INFO, fmt::format("Received message (I2C) : {}", msg->show().c_str()));
		}
	}
		break;
	case cossb::base::msg_type::DATA: break;
	default:
		cossb_log->log(log::loglevel::INFO, "Received message has unsupported type.");
	}

}
<|endoftext|>