<commit_before>/*************************************************************************
 *
 * TIGHTDB CONFIDENTIAL
 * __________________
 *
 *  [2011] - [2012] TightDB Inc
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of TightDB Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to TightDB Incorporated
 * and its suppliers and may be covered by U.S. and Foreign Patents,
 * patents in process, and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from TightDB Incorporated.
 *
 **************************************************************************/
#ifndef TIGHTDB_ARRAY_STRING_HPP
#define TIGHTDB_ARRAY_STRING_HPP

#include <tightdb/array.hpp>

namespace tightdb {

/*
ArrayString stores strings as a concecutive list of fixed-length blocks of m_width bytes. The
longest string it can store is (m_width - 1) bytes before it needs to expand.

An example of the format for m_width = 4 is following sequence of bytes, where x is payload:

xxx0 xx01 x002 0003 0004 (strings "xxx",. "xx", "x", "", null)

So each string is 0 terminated, and the last byte in a block tells how many 0s are present, except
for a null which has the byte set to m_width (4). The byte is used to compute the length of a string
in various functions.

New: If m_witdh = 0, then all elements are null. So to add an empty string we must expand m_width
*/

class ArrayString: public Array {
public:
    typedef StringData value_type;

    explicit ArrayString(Allocator&) TIGHTDB_NOEXCEPT;
    explicit ArrayString(no_prealloc_tag) TIGHTDB_NOEXCEPT;
    ~ArrayString() TIGHTDB_NOEXCEPT TIGHTDB_OVERRIDE {}

    bool is_null(size_t ndx) const;
    void set_null(size_t ndx);
    StringData get(std::size_t ndx) const TIGHTDB_NOEXCEPT;
    void add();
    void add(StringData value);
    void set(std::size_t ndx, StringData value);
    void insert(std::size_t ndx, StringData value);
    void erase(std::size_t ndx);

    std::size_t count(StringData value, std::size_t begin = 0,
                      std::size_t end = npos) const TIGHTDB_NOEXCEPT;
    std::size_t find_first(StringData value, std::size_t begin = 0,
                           std::size_t end = npos) const TIGHTDB_NOEXCEPT;
    void find_all(Column& result, StringData value, std::size_t add_offset = 0,
                  std::size_t begin = 0, std::size_t end = npos);

    /// Compare two string arrays for equality.
    bool compare_string(const ArrayString&) const TIGHTDB_NOEXCEPT;

    /// Get the specified element without the cost of constructing an
    /// array instance. If an array instance is already available, or
    /// you need to get multiple values, then this method will be
    /// slower.
    static StringData get(const char* header, std::size_t ndx) TIGHTDB_NOEXCEPT;

    ref_type bptree_leaf_insert(std::size_t ndx, StringData, TreeInsertBase& state);

    /// Construct a string array of the specified size and return just
    /// the reference to the underlying memory. All elements will be
    /// initialized to the empty string.
    static MemRef create_array(std::size_t size, Allocator&);

    /// Create a new empty string array and attach this accessor to
    /// it. This does not modify the parent reference information of
    /// this accessor.
    ///
    /// Note that the caller assumes ownership of the allocated
    /// underlying node. It is not owned by the accessor.
    void create();

    /// Construct a copy of the specified slice of this string array
    /// using the specified target allocator.
    MemRef slice(std::size_t offset, std::size_t size, Allocator& target_alloc) const;

#ifdef TIGHTDB_DEBUG
    void string_stats() const;
    void to_dot(std::ostream&, StringData title = StringData()) const;
#endif

private:
    std::size_t CalcByteLen(std::size_t count, std::size_t width) const TIGHTDB_OVERRIDE;
    std::size_t CalcItemCount(std::size_t bytes,
                              std::size_t width) const TIGHTDB_NOEXCEPT TIGHTDB_OVERRIDE;
    WidthType GetWidthType() const TIGHTDB_OVERRIDE { return wtype_Multiply; }
};

// Implementation:

// Creates new array (but invalid, call init_from_ref() to init)
inline ArrayString::ArrayString(Allocator& alloc) TIGHTDB_NOEXCEPT:
    Array(alloc)
{
}

// Fastest way to instantiate an Array. For use with GetDirect() that only fills out m_width, m_data
// and a few other basic things needed for read-only access. Or for use if you just want a way to call
// some methods written in ArrayString.*
inline ArrayString::ArrayString(no_prealloc_tag) TIGHTDB_NOEXCEPT:
    Array(*static_cast<Allocator*>(0))
{
}

inline void ArrayString::create()
{
    std::size_t size = 0;
    MemRef mem = create_array(size, get_alloc()); // Throws
    init_from_mem(mem);
}

inline MemRef ArrayString::create_array(std::size_t size, Allocator& alloc)
{
    bool context_flag = false;
    int_fast64_t value = 0;
    return Array::create(type_Normal, context_flag, wtype_Multiply, size, value, alloc); // Throws
}

inline StringData ArrayString::get(std::size_t ndx) const TIGHTDB_NOEXCEPT
{
    TIGHTDB_ASSERT(ndx < m_size);
    if (m_width == 0)
        return StringData(null_ptr, 0); // return null
    const char* data = m_data + (ndx * m_width);
    std::size_t size = (m_width-1) - data[m_width-1];

    if (size == static_cast<size_t>(-1))
        return StringData(null_ptr, 0); // return null

    TIGHTDB_ASSERT(data[size] == 0); // Realm guarantees 0 terminated return strings
    return StringData(data, size);
}

inline void ArrayString::add(StringData value)
{
    insert(m_size, value); // Throws
}

inline void ArrayString::add()
{
    add(StringData()); // Throws
}

inline StringData ArrayString::get(const char* header, std::size_t ndx) TIGHTDB_NOEXCEPT
{
    TIGHTDB_ASSERT(ndx < get_size_from_header(header));
    std::size_t width = get_width_from_header(header);
    if (width == 0)
        return StringData(null_ptr, 0); // return null
    const char* data = get_data_from_header(header) + (ndx * width);
    std::size_t size = (width-1) - data[width-1];

    if (size == static_cast<size_t>(-1))
        return StringData(null_ptr, 0); // return null

    return StringData(data, size);
}

} // namespace tightdb

#endif // TIGHTDB_ARRAY_STRING_HPP
<commit_msg>Update array_string.hpp<commit_after>/*************************************************************************
 *
 * TIGHTDB CONFIDENTIAL
 * __________________
 *
 *  [2011] - [2012] TightDB Inc
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of TightDB Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to TightDB Incorporated
 * and its suppliers and may be covered by U.S. and Foreign Patents,
 * patents in process, and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from TightDB Incorporated.
 *
 **************************************************************************/
#ifndef TIGHTDB_ARRAY_STRING_HPP
#define TIGHTDB_ARRAY_STRING_HPP

#include <tightdb/array.hpp>

namespace tightdb {

/*
ArrayString stores strings as a concecutive list of fixed-length blocks of m_width bytes. The
longest string it can store is (m_width - 1) bytes before it needs to expand.

An example of the format for m_width = 4 is following sequence of bytes, where x is payload:

xxx0 xx01 x002 0003 0004 (strings "xxx",. "xx", "x", "", null)

So each string is 0 terminated, and the last byte in a block tells how many 0s are present, except
for a null which has the byte set to m_width (4). The byte is used to compute the length of a string
in various functions.

New: If m_witdh = 0, then all elements are null. So to add an empty string we must expand m_width
New: StringData is null if-and-only-if StringData::data() == 0.
*/

class ArrayString: public Array {
public:
    typedef StringData value_type;

    explicit ArrayString(Allocator&) TIGHTDB_NOEXCEPT;
    explicit ArrayString(no_prealloc_tag) TIGHTDB_NOEXCEPT;
    ~ArrayString() TIGHTDB_NOEXCEPT TIGHTDB_OVERRIDE {}

    bool is_null(size_t ndx) const;
    void set_null(size_t ndx);
    StringData get(std::size_t ndx) const TIGHTDB_NOEXCEPT;
    void add();
    void add(StringData value);
    void set(std::size_t ndx, StringData value);
    void insert(std::size_t ndx, StringData value);
    void erase(std::size_t ndx);

    std::size_t count(StringData value, std::size_t begin = 0,
                      std::size_t end = npos) const TIGHTDB_NOEXCEPT;
    std::size_t find_first(StringData value, std::size_t begin = 0,
                           std::size_t end = npos) const TIGHTDB_NOEXCEPT;
    void find_all(Column& result, StringData value, std::size_t add_offset = 0,
                  std::size_t begin = 0, std::size_t end = npos);

    /// Compare two string arrays for equality.
    bool compare_string(const ArrayString&) const TIGHTDB_NOEXCEPT;

    /// Get the specified element without the cost of constructing an
    /// array instance. If an array instance is already available, or
    /// you need to get multiple values, then this method will be
    /// slower.
    static StringData get(const char* header, std::size_t ndx) TIGHTDB_NOEXCEPT;

    ref_type bptree_leaf_insert(std::size_t ndx, StringData, TreeInsertBase& state);

    /// Construct a string array of the specified size and return just
    /// the reference to the underlying memory. All elements will be
    /// initialized to the empty string.
    static MemRef create_array(std::size_t size, Allocator&);

    /// Create a new empty string array and attach this accessor to
    /// it. This does not modify the parent reference information of
    /// this accessor.
    ///
    /// Note that the caller assumes ownership of the allocated
    /// underlying node. It is not owned by the accessor.
    void create();

    /// Construct a copy of the specified slice of this string array
    /// using the specified target allocator.
    MemRef slice(std::size_t offset, std::size_t size, Allocator& target_alloc) const;

#ifdef TIGHTDB_DEBUG
    void string_stats() const;
    void to_dot(std::ostream&, StringData title = StringData()) const;
#endif

private:
    std::size_t CalcByteLen(std::size_t count, std::size_t width) const TIGHTDB_OVERRIDE;
    std::size_t CalcItemCount(std::size_t bytes,
                              std::size_t width) const TIGHTDB_NOEXCEPT TIGHTDB_OVERRIDE;
    WidthType GetWidthType() const TIGHTDB_OVERRIDE { return wtype_Multiply; }
};

// Implementation:

// Creates new array (but invalid, call init_from_ref() to init)
inline ArrayString::ArrayString(Allocator& alloc) TIGHTDB_NOEXCEPT:
    Array(alloc)
{
}

// Fastest way to instantiate an Array. For use with GetDirect() that only fills out m_width, m_data
// and a few other basic things needed for read-only access. Or for use if you just want a way to call
// some methods written in ArrayString.*
inline ArrayString::ArrayString(no_prealloc_tag) TIGHTDB_NOEXCEPT:
    Array(*static_cast<Allocator*>(0))
{
}

inline void ArrayString::create()
{
    std::size_t size = 0;
    MemRef mem = create_array(size, get_alloc()); // Throws
    init_from_mem(mem);
}

inline MemRef ArrayString::create_array(std::size_t size, Allocator& alloc)
{
    bool context_flag = false;
    int_fast64_t value = 0;
    return Array::create(type_Normal, context_flag, wtype_Multiply, size, value, alloc); // Throws
}

inline StringData ArrayString::get(std::size_t ndx) const TIGHTDB_NOEXCEPT
{
    TIGHTDB_ASSERT(ndx < m_size);
    if (m_width == 0)
        return StringData(null_ptr, 0); // return null
    const char* data = m_data + (ndx * m_width);
    std::size_t size = (m_width-1) - data[m_width-1];

    if (size == static_cast<size_t>(-1))
        return StringData(null_ptr, 0); // return null

    TIGHTDB_ASSERT(data[size] == 0); // Realm guarantees 0 terminated return strings
    return StringData(data, size);
}

inline void ArrayString::add(StringData value)
{
    insert(m_size, value); // Throws
}

inline void ArrayString::add()
{
    add(StringData()); // Throws
}

inline StringData ArrayString::get(const char* header, std::size_t ndx) TIGHTDB_NOEXCEPT
{
    TIGHTDB_ASSERT(ndx < get_size_from_header(header));
    std::size_t width = get_width_from_header(header);
    if (width == 0)
        return StringData(null_ptr, 0); // return null
    const char* data = get_data_from_header(header) + (ndx * width);
    std::size_t size = (width-1) - data[width-1];

    if (size == static_cast<size_t>(-1))
        return StringData(null_ptr, 0); // return null

    return StringData(data, size);
}

} // namespace tightdb

#endif // TIGHTDB_ARRAY_STRING_HPP
<|endoftext|>


<commit_before><commit_msg>#92951# exc spec for gcc3<commit_after><|endoftext|>


<commit_before>// File:	Extrema_ExtCS.cxx
// Created:	Tue Jul 18 10:33:04 1995
// Author:	Modelistation
//		<model@metrox>
// Modified by MPS  (june 96)  :
// Dans les  cas line /cone et line /tore on utilise la classe GenExtCS
// a la place de  ExtElCS. Dans ExtElCS les cas line/cone et line/tore ne sont
// pas implementes

//  Modified by skv - Thu Jul  7 12:29:34 2005 OCC9134

#include <Extrema_ExtCS.ixx>
#include <Extrema_GenExtCS.hxx>
#include <StdFail_NotDone.hxx>
#include <Standard_NotImplemented.hxx>
#include <StdFail_InfiniteSolutions.hxx>
#include <Precision.hxx>
#include <GeomAbs_CurveType.hxx>
#include <gp_Pnt.hxx>
#include <gp_Pln.hxx>
#include <gp_Cylinder.hxx>
#include <gp_Cone.hxx>
#include <gp_Sphere.hxx>
#include <gp_Torus.hxx>
#include <gp_Lin.hxx>

#include <ElCLib.hxx>
#include <Extrema_ExtPElC.hxx>
#include <Bnd_Box.hxx>
#include <BndLib_AddSurface.hxx>
#include <Extrema_ExtPElS.hxx>

Extrema_ExtCS::Extrema_ExtCS()
{
  myDone = Standard_False;
}

Extrema_ExtCS::Extrema_ExtCS(const Adaptor3d_Curve&   C,
			     const Adaptor3d_Surface& S,
			     const Standard_Real    TolC,
			     const Standard_Real    TolS)

{
  Initialize(S, S.FirstUParameter(), S.LastUParameter(),
	     S.FirstVParameter(), S.LastVParameter(),
	     TolC, TolS);
  Perform(C, C.FirstParameter(), C.LastParameter());
}

Extrema_ExtCS::Extrema_ExtCS(const Adaptor3d_Curve&   C,
			     const Adaptor3d_Surface& S,
			     const Standard_Real    UCinf,
			     const Standard_Real    UCsup,
			     const Standard_Real    Uinf,
			     const Standard_Real    Usup,
			     const Standard_Real    Vinf,
			     const Standard_Real    Vsup,
			     const Standard_Real    TolC,
			     const Standard_Real    TolS)

{
  Initialize(S, Uinf, Usup, Vinf, Vsup, TolC, TolS);
  Perform(C, UCinf, UCsup);
}

void Extrema_ExtCS::Initialize(const Adaptor3d_Surface& S,
			       const Standard_Real    Uinf,
			       const Standard_Real    Usup,
			       const Standard_Real    Vinf,
			       const Standard_Real    Vsup,
			       const Standard_Real    TolC,
			       const Standard_Real    TolS)
{
  myS = (Adaptor3d_SurfacePtr)&S;
  myIsPar = Standard_False;
  myuinf  = Uinf;
  myusup  = Usup;
  myvinf  = Vinf;
  myvsup  = Vsup;
  mytolC  = TolC;
  mytolS  = TolS;
  myStype  = myS->GetType();
}

void Extrema_ExtCS::Perform(const Adaptor3d_Curve& C,
			    const Standard_Real  Uinf,
			    const Standard_Real  Usup)
{
  myucinf = Uinf;
  myucsup = Usup;
  myPOnS.Clear();
  myPOnC.Clear();
  mySqDist.Clear();
  Standard_Integer i;
  Standard_Integer NbT, NbU, NbV;
  NbT = NbU = NbV = 10;
  GeomAbs_CurveType myCtype  = C.GetType();

  switch(myCtype) {

  case GeomAbs_Line:
    {

      switch(myStype) {
      case GeomAbs_Sphere:
	myExtElCS.Perform(C.Line(), myS->Sphere());
	break;
      case GeomAbs_Cylinder:
	myExtElCS.Perform(C.Line(), myS->Cylinder());
	break;
      case GeomAbs_Plane:
	myExtElCS.Perform(C.Line(), myS->Plane());
	if (myExtElCS.IsParallel())   break;

      case GeomAbs_Torus:
      case GeomAbs_Cone:
      case GeomAbs_BezierSurface:
      case GeomAbs_BSplineSurface:
      case GeomAbs_SurfaceOfRevolution:
      case GeomAbs_SurfaceOfExtrusion:
      case GeomAbs_OtherSurface:
	{
	  Standard_Real cfirst = myucinf, clast = myucsup;
	  Standard_Real ufirst = myS->FirstUParameter(), ulast = myS->LastUParameter(),
	                vfirst = myS->FirstVParameter(), vlast = myS->LastVParameter();

	  if(Precision::IsInfinite(Abs(cfirst)) || Precision::IsInfinite(Abs(clast))) {

	    Bnd_Box aSurfBox;
	    BndLib_AddSurface anAddSurf;
	    anAddSurf.Add(*myS, ufirst, ulast, vfirst, vlast, Precision::Confusion(), aSurfBox);
	    Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
	    aSurfBox.Get(xmin, ymin, zmin, xmax, ymax, zmax);
	    Standard_Real tmin = Precision::Infinite(), tmax = -tmin;
	    gp_Lin aLin = C.Line();

	    if(!( Precision::IsInfinite(Abs(xmin)) || Precision::IsInfinite(Abs(xmax)) ||
		  Precision::IsInfinite(Abs(ymin)) || Precision::IsInfinite(Abs(ymax)) ||
		  Precision::IsInfinite(Abs(zmin)) || Precision::IsInfinite(Abs(zmax)))  ) {

	      Extrema_ExtPElC anExt;
	      Extrema_POnCurv aPntOnLin;
	      Standard_Real aParOnLin;
	      Standard_Real lim = Precision::Infinite();
	      gp_Pnt aLimPntArray[8];

	      aLimPntArray[0].SetCoord(xmin, ymin, zmin);
	      aLimPntArray[1].SetCoord(xmax, ymin, zmin);
	      aLimPntArray[2].SetCoord(xmin, ymax, zmin);
	      aLimPntArray[3].SetCoord(xmax, ymax, zmin);
	      aLimPntArray[4].SetCoord(xmin, ymin, zmax);
	      aLimPntArray[5].SetCoord(xmax, ymin, zmax);
	      aLimPntArray[6].SetCoord(xmin, ymax, zmax);
	      aLimPntArray[7].SetCoord(xmax, ymax, zmax);

	      for(i = 0; i <= 7; i++) {
		anExt.Perform(aLimPntArray[i], aLin, Precision::Confusion(), -lim, lim);
		aPntOnLin = anExt.Point(1);
		aParOnLin = aPntOnLin.Parameter();
		tmin = Min(aParOnLin, tmin);
		tmax = Max(aParOnLin, tmax);
	      }

	    }
	    else {
	      tmin = -1.e+50;
	      tmax =  1.e+50;
	    }

	    cfirst = Max(cfirst, tmin);
	    clast  = Min(clast,  tmax);

	  }

	  Extrema_GenExtCS Ext(C, *myS, NbT, NbU, NbV, cfirst, clast, ufirst, ulast,
			       vfirst, vlast, mytolC, mytolS);

	  myDone = Ext.IsDone();
	  if (myDone) {
	    Standard_Integer NbExt = Ext.NbExt();
	    Standard_Real T,U,V;
	    Extrema_POnCurv PC;
	    Extrema_POnSurf PS;
	    for (i = 1; i <= NbExt; i++) {
	      PC = Ext.PointOnCurve(i);
	      PS = Ext.PointOnSurface(i);
	      T = PC.Parameter();
	      PS.Parameter(U, V);
	      if (myS->IsUPeriodic())
		U = ElCLib::InPeriod(U, myuinf, myuinf+myS->UPeriod());
	      if (myS->IsVPeriodic())
		V = ElCLib::InPeriod(V, myvinf, myvinf+myS->VPeriod());

	      if ((myucinf-T) <= mytolC && (T-myucsup) <= mytolC &&
		  (myuinf-U) <= mytolS && (U-myusup) <= mytolS &&
		  (myvinf-V) <= mytolS && (V-myvsup) <= mytolS) {
		mySqDist.Append(Ext.SquareDistance(i));
		myPOnC.Append(PC);
		myPOnS.Append(Extrema_POnSurf(U, V, PS.Value()));

	      }
	    }
	  }
	  return;

	}
#ifndef DEB
      default:
#endif
	break;
      }
      break;
    }
//  Modified by skv - Thu Jul  7 12:29:34 2005 OCC9134 Begin
  case GeomAbs_Circle:
    {
      if(myStype == GeomAbs_Cylinder) {
	myExtElCS.Perform(C.Circle(), myS->Cylinder());
	break;
      }
    }
  case GeomAbs_Hyperbola:
    {
      if(myCtype == GeomAbs_Hyperbola && myStype == GeomAbs_Plane) {
//  Modified by skv - Thu Jul  7 12:29:34 2005 OCC9134 End
	myExtElCS.Perform(C.Hyperbola(), myS->Plane());
	break;
      }
    }
  default:
    {
      Extrema_GenExtCS Ext;
      Ext.Initialize(*myS, NbU, NbV, mytolS);
      if(myCtype == GeomAbs_Hyperbola) {
	Standard_Real tmin = Max(-20., C.FirstParameter());
	Standard_Real tmax = Min(20., C.LastParameter());
	Ext.Perform(C, NbT, tmin, tmax, mytolC); // to avoid overflow
      }
      else {
	if(myCtype == GeomAbs_Circle && NbT < 13) {
	  NbT = 13;
	}
	Ext.Perform(C, NbT, mytolC);
      }

      myDone = Ext.IsDone();
      if (myDone) {
	Standard_Integer NbExt = Ext.NbExt();
	Standard_Real T,U,V;
	Extrema_POnCurv PC;
	Extrema_POnSurf PS;
	for (i = 1; i <= NbExt; i++) {
	  PC = Ext.PointOnCurve(i);
	  PS = Ext.PointOnSurface(i);
	  T = PC.Parameter();
	  PS.Parameter(U, V);
	  if (C.IsPeriodic())
	    T = ElCLib::InPeriod(T, myucinf, myucinf+C.Period());
	  if (myS->IsUPeriodic())
	    U = ElCLib::InPeriod(U, myuinf, myuinf+myS->UPeriod());
	  if (myS->IsVPeriodic())
	    V = ElCLib::InPeriod(V, myvinf, myvinf+myS->VPeriod());

	  if ((myucinf-T) <= mytolC && (T-myucsup) <= mytolC &&
	      (myuinf-U) <= mytolS && (U-myusup) <= mytolS &&
	      (myvinf-V) <= mytolS && (V-myvsup) <= mytolS) {
	    mySqDist.Append(Ext.SquareDistance(i));
	    PC.SetValues(T, PC.Value());
	    myPOnC.Append(PC);
	    myPOnS.Append(Extrema_POnSurf(U, V, PS.Value()));
	  }
	}
      }
      return;
    }
    break;
  }

  myDone = myExtElCS.IsDone();
  if (myDone) {
    myIsPar = myExtElCS.IsParallel();
    if (myIsPar) {
      mySqDist.Append(myExtElCS.SquareDistance(1));
    }
    else {
      Standard_Integer NbExt = myExtElCS.NbExt();
      Standard_Real U, V;
      for (i = 1; i <= NbExt; i++) {
	Extrema_POnCurv PC;
	Extrema_POnSurf PS;
	myExtElCS.Points(i, PC, PS);
	Standard_Real Ucurve = PC.Parameter();
	PS.Parameter(U, V);

	if((myStype == GeomAbs_Sphere) || (myStype == GeomAbs_Cylinder)) {
	  U = ElCLib::InPeriod(U, myuinf, myuinf+2.*PI);
	}

	if ((myuinf-U) <= mytolS && (U-myusup) <= mytolS &&
	    (myvinf-V) <= mytolS && (V-myvsup) <= mytolS &&
	    (myucinf-Ucurve) <= mytolC && (Ucurve-myucsup) <= mytolC) {
	  mySqDist.Append(myExtElCS.SquareDistance(i));
	  myPOnS.Append(Extrema_POnSurf(U, V, PS.Value()));
	  myPOnC.Append(PC);
	}
      }
    }
  }

}

Standard_Boolean Extrema_ExtCS::IsDone() const
{
  return myDone;
}

Standard_Boolean Extrema_ExtCS::IsParallel() const
{
  return myIsPar;
}

Standard_Real Extrema_ExtCS::SquareDistance(const Standard_Integer N) const
{
  if(!myDone) StdFail_NotDone::Raise();
  if (myIsPar && N != 1) StdFail_InfiniteSolutions::Raise();
  if ((N < 1) || (N > mySqDist.Length())) Standard_OutOfRange::Raise();
  return mySqDist.Value(N);
}

Standard_Integer Extrema_ExtCS::NbExt() const
{
  if(!myDone) StdFail_NotDone::Raise();
  return mySqDist.Length();
}

void Extrema_ExtCS::Points(const Standard_Integer N,
			    Extrema_POnCurv&       P1,
			    Extrema_POnSurf&       P2) const
{
  if(!myDone) StdFail_NotDone::Raise();
  P1 = myPOnC.Value(N);
  P2 = myPOnS.Value(N);
}
<commit_msg>[warning-fix][unused-local-var]<commit_after>// File:	Extrema_ExtCS.cxx
// Created:	Tue Jul 18 10:33:04 1995
// Author:	Modelistation
//		<model@metrox>
// Modified by MPS  (june 96)  :
// Dans les  cas line /cone et line /tore on utilise la classe GenExtCS
// a la place de  ExtElCS. Dans ExtElCS les cas line/cone et line/tore ne sont
// pas implementes

//  Modified by skv - Thu Jul  7 12:29:34 2005 OCC9134

#include <Extrema_ExtCS.ixx>
#include <Extrema_GenExtCS.hxx>
#include <StdFail_NotDone.hxx>
#include <Standard_NotImplemented.hxx>
#include <StdFail_InfiniteSolutions.hxx>
#include <Precision.hxx>
#include <GeomAbs_CurveType.hxx>
#include <gp_Pnt.hxx>
#include <gp_Pln.hxx>
#include <gp_Cylinder.hxx>
#include <gp_Cone.hxx>
#include <gp_Sphere.hxx>
#include <gp_Torus.hxx>
#include <gp_Lin.hxx>

#include <ElCLib.hxx>
#include <Extrema_ExtPElC.hxx>
#include <Bnd_Box.hxx>
#include <BndLib_AddSurface.hxx>
#include <Extrema_ExtPElS.hxx>

Extrema_ExtCS::Extrema_ExtCS()
{
  myDone = Standard_False;
}

Extrema_ExtCS::Extrema_ExtCS(const Adaptor3d_Curve&   C,
			     const Adaptor3d_Surface& S,
			     const Standard_Real    TolC,
			     const Standard_Real    TolS)

{
  Initialize(S, S.FirstUParameter(), S.LastUParameter(),
	     S.FirstVParameter(), S.LastVParameter(),
	     TolC, TolS);
  Perform(C, C.FirstParameter(), C.LastParameter());
}

Extrema_ExtCS::Extrema_ExtCS(const Adaptor3d_Curve&   C,
			     const Adaptor3d_Surface& S,
			     const Standard_Real    UCinf,
			     const Standard_Real    UCsup,
			     const Standard_Real    Uinf,
			     const Standard_Real    Usup,
			     const Standard_Real    Vinf,
			     const Standard_Real    Vsup,
			     const Standard_Real    TolC,
			     const Standard_Real    TolS)

{
  Initialize(S, Uinf, Usup, Vinf, Vsup, TolC, TolS);
  Perform(C, UCinf, UCsup);
}

void Extrema_ExtCS::Initialize(const Adaptor3d_Surface& S,
			       const Standard_Real    Uinf,
			       const Standard_Real    Usup,
			       const Standard_Real    Vinf,
			       const Standard_Real    Vsup,
			       const Standard_Real    TolC,
			       const Standard_Real    TolS)
{
  myS = (Adaptor3d_SurfacePtr)&S;
  myIsPar = Standard_False;
  myuinf  = Uinf;
  myusup  = Usup;
  myvinf  = Vinf;
  myvsup  = Vsup;
  mytolC  = TolC;
  mytolS  = TolS;
  myStype  = myS->GetType();
}

void Extrema_ExtCS::Perform(const Adaptor3d_Curve& C,
			    const Standard_Real  Uinf,
			    const Standard_Real  Usup)
{
  myucinf = Uinf;
  myucsup = Usup;
  myPOnS.Clear();
  myPOnC.Clear();
  mySqDist.Clear();
  Standard_Integer i;
  Standard_Integer NbT, NbU, NbV;
  NbT = NbU = NbV = 10;
  GeomAbs_CurveType myCtype  = C.GetType();

  switch(myCtype) {

  case GeomAbs_Line:
    {

      switch(myStype) {
      case GeomAbs_Sphere:
	myExtElCS.Perform(C.Line(), myS->Sphere());
	break;
      case GeomAbs_Cylinder:
	myExtElCS.Perform(C.Line(), myS->Cylinder());
	break;
      case GeomAbs_Plane:
	myExtElCS.Perform(C.Line(), myS->Plane());
	if (myExtElCS.IsParallel())   break;

      case GeomAbs_Torus:
      case GeomAbs_Cone:
      case GeomAbs_BezierSurface:
      case GeomAbs_BSplineSurface:
      case GeomAbs_SurfaceOfRevolution:
      case GeomAbs_SurfaceOfExtrusion:
      case GeomAbs_OtherSurface:
	{
	  Standard_Real cfirst = myucinf, clast = myucsup;
	  Standard_Real ufirst = myS->FirstUParameter(), ulast = myS->LastUParameter(),
	                vfirst = myS->FirstVParameter(), vlast = myS->LastVParameter();

	  if(Precision::IsInfinite(Abs(cfirst)) || Precision::IsInfinite(Abs(clast))) {

	    Bnd_Box aSurfBox;
	    BndLib_AddSurface::Add(*myS, ufirst, ulast, vfirst, vlast, Precision::Confusion(), aSurfBox);
	    Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
	    aSurfBox.Get(xmin, ymin, zmin, xmax, ymax, zmax);
	    Standard_Real tmin = Precision::Infinite(), tmax = -tmin;
	    gp_Lin aLin = C.Line();

	    if(!( Precision::IsInfinite(Abs(xmin)) || Precision::IsInfinite(Abs(xmax)) ||
		  Precision::IsInfinite(Abs(ymin)) || Precision::IsInfinite(Abs(ymax)) ||
		  Precision::IsInfinite(Abs(zmin)) || Precision::IsInfinite(Abs(zmax)))  ) {

	      Extrema_ExtPElC anExt;
	      Extrema_POnCurv aPntOnLin;
	      Standard_Real aParOnLin;
	      Standard_Real lim = Precision::Infinite();
	      gp_Pnt aLimPntArray[8];

	      aLimPntArray[0].SetCoord(xmin, ymin, zmin);
	      aLimPntArray[1].SetCoord(xmax, ymin, zmin);
	      aLimPntArray[2].SetCoord(xmin, ymax, zmin);
	      aLimPntArray[3].SetCoord(xmax, ymax, zmin);
	      aLimPntArray[4].SetCoord(xmin, ymin, zmax);
	      aLimPntArray[5].SetCoord(xmax, ymin, zmax);
	      aLimPntArray[6].SetCoord(xmin, ymax, zmax);
	      aLimPntArray[7].SetCoord(xmax, ymax, zmax);

	      for(i = 0; i <= 7; i++) {
		anExt.Perform(aLimPntArray[i], aLin, Precision::Confusion(), -lim, lim);
		aPntOnLin = anExt.Point(1);
		aParOnLin = aPntOnLin.Parameter();
		tmin = Min(aParOnLin, tmin);
		tmax = Max(aParOnLin, tmax);
	      }

	    }
	    else {
	      tmin = -1.e+50;
	      tmax =  1.e+50;
	    }

	    cfirst = Max(cfirst, tmin);
	    clast  = Min(clast,  tmax);

	  }

	  Extrema_GenExtCS Ext(C, *myS, NbT, NbU, NbV, cfirst, clast, ufirst, ulast,
			       vfirst, vlast, mytolC, mytolS);

	  myDone = Ext.IsDone();
	  if (myDone) {
	    Standard_Integer NbExt = Ext.NbExt();
	    Standard_Real T,U,V;
	    Extrema_POnCurv PC;
	    Extrema_POnSurf PS;
	    for (i = 1; i <= NbExt; i++) {
	      PC = Ext.PointOnCurve(i);
	      PS = Ext.PointOnSurface(i);
	      T = PC.Parameter();
	      PS.Parameter(U, V);
	      if (myS->IsUPeriodic())
		U = ElCLib::InPeriod(U, myuinf, myuinf+myS->UPeriod());
	      if (myS->IsVPeriodic())
		V = ElCLib::InPeriod(V, myvinf, myvinf+myS->VPeriod());

	      if ((myucinf-T) <= mytolC && (T-myucsup) <= mytolC &&
		  (myuinf-U) <= mytolS && (U-myusup) <= mytolS &&
		  (myvinf-V) <= mytolS && (V-myvsup) <= mytolS) {
		mySqDist.Append(Ext.SquareDistance(i));
		myPOnC.Append(PC);
		myPOnS.Append(Extrema_POnSurf(U, V, PS.Value()));

	      }
	    }
	  }
	  return;

	}
#ifndef DEB
      default:
#endif
	break;
      }
      break;
    }
//  Modified by skv - Thu Jul  7 12:29:34 2005 OCC9134 Begin
  case GeomAbs_Circle:
    {
      if(myStype == GeomAbs_Cylinder) {
	myExtElCS.Perform(C.Circle(), myS->Cylinder());
	break;
      }
    }
  case GeomAbs_Hyperbola:
    {
      if(myCtype == GeomAbs_Hyperbola && myStype == GeomAbs_Plane) {
//  Modified by skv - Thu Jul  7 12:29:34 2005 OCC9134 End
	myExtElCS.Perform(C.Hyperbola(), myS->Plane());
	break;
      }
    }
  default:
    {
      Extrema_GenExtCS Ext;
      Ext.Initialize(*myS, NbU, NbV, mytolS);
      if(myCtype == GeomAbs_Hyperbola) {
	Standard_Real tmin = Max(-20., C.FirstParameter());
	Standard_Real tmax = Min(20., C.LastParameter());
	Ext.Perform(C, NbT, tmin, tmax, mytolC); // to avoid overflow
      }
      else {
	if(myCtype == GeomAbs_Circle && NbT < 13) {
	  NbT = 13;
	}
	Ext.Perform(C, NbT, mytolC);
      }

      myDone = Ext.IsDone();
      if (myDone) {
	Standard_Integer NbExt = Ext.NbExt();
	Standard_Real T,U,V;
	Extrema_POnCurv PC;
	Extrema_POnSurf PS;
	for (i = 1; i <= NbExt; i++) {
	  PC = Ext.PointOnCurve(i);
	  PS = Ext.PointOnSurface(i);
	  T = PC.Parameter();
	  PS.Parameter(U, V);
	  if (C.IsPeriodic())
	    T = ElCLib::InPeriod(T, myucinf, myucinf+C.Period());
	  if (myS->IsUPeriodic())
	    U = ElCLib::InPeriod(U, myuinf, myuinf+myS->UPeriod());
	  if (myS->IsVPeriodic())
	    V = ElCLib::InPeriod(V, myvinf, myvinf+myS->VPeriod());

	  if ((myucinf-T) <= mytolC && (T-myucsup) <= mytolC &&
	      (myuinf-U) <= mytolS && (U-myusup) <= mytolS &&
	      (myvinf-V) <= mytolS && (V-myvsup) <= mytolS) {
	    mySqDist.Append(Ext.SquareDistance(i));
	    PC.SetValues(T, PC.Value());
	    myPOnC.Append(PC);
	    myPOnS.Append(Extrema_POnSurf(U, V, PS.Value()));
	  }
	}
      }
      return;
    }
    break;
  }

  myDone = myExtElCS.IsDone();
  if (myDone) {
    myIsPar = myExtElCS.IsParallel();
    if (myIsPar) {
      mySqDist.Append(myExtElCS.SquareDistance(1));
    }
    else {
      Standard_Integer NbExt = myExtElCS.NbExt();
      Standard_Real U, V;
      for (i = 1; i <= NbExt; i++) {
	Extrema_POnCurv PC;
	Extrema_POnSurf PS;
	myExtElCS.Points(i, PC, PS);
	Standard_Real Ucurve = PC.Parameter();
	PS.Parameter(U, V);

	if((myStype == GeomAbs_Sphere) || (myStype == GeomAbs_Cylinder)) {
	  U = ElCLib::InPeriod(U, myuinf, myuinf+2.*PI);
	}

	if ((myuinf-U) <= mytolS && (U-myusup) <= mytolS &&
	    (myvinf-V) <= mytolS && (V-myvsup) <= mytolS &&
	    (myucinf-Ucurve) <= mytolC && (Ucurve-myucsup) <= mytolC) {
	  mySqDist.Append(myExtElCS.SquareDistance(i));
	  myPOnS.Append(Extrema_POnSurf(U, V, PS.Value()));
	  myPOnC.Append(PC);
	}
      }
    }
  }

}

Standard_Boolean Extrema_ExtCS::IsDone() const
{
  return myDone;
}

Standard_Boolean Extrema_ExtCS::IsParallel() const
{
  return myIsPar;
}

Standard_Real Extrema_ExtCS::SquareDistance(const Standard_Integer N) const
{
  if(!myDone) StdFail_NotDone::Raise();
  if (myIsPar && N != 1) StdFail_InfiniteSolutions::Raise();
  if ((N < 1) || (N > mySqDist.Length())) Standard_OutOfRange::Raise();
  return mySqDist.Value(N);
}

Standard_Integer Extrema_ExtCS::NbExt() const
{
  if(!myDone) StdFail_NotDone::Raise();
  return mySqDist.Length();
}

void Extrema_ExtCS::Points(const Standard_Integer N,
			    Extrema_POnCurv&       P1,
			    Extrema_POnSurf&       P2) const
{
  if(!myDone) StdFail_NotDone::Raise();
  P1 = myPOnC.Value(N);
  P2 = myPOnS.Value(N);
}
<|endoftext|>


<commit_before>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/model/CMoiety.cpp,v $
   $Revision: 1.29 $
   $Name:  $
   $Author: ssahle $
   $Date: 2004/09/10 11:13:38 $
   End CVS Header */

#include <stdio.h>
#include "mathematics.h"

#define  COPASI_TRACE_CONSTRUCTION

#include "copasi.h"
#include "utilities/CCopasiMessage.h"
#include "CMoiety.h"
#include "CCompartment.h"
#include "utilities/CReadConfig.h"
#include "utilities/CCopasiVector.h"
#include "utilities/utility.h"
#include "CMetabNameInterface.h"

#include "report/CKeyFactory.h"//By G

CMoiety::CMoiety(const std::string & name,
                 const CCopasiContainer * pParent):
    CCopasiContainer(name, pParent, "Moiety"),
    mKey(GlobalKeys.add("Moiety", this)),           //By G
    mNumber(0),
    mINumber(0),
    mEquation("Equation", this)
{CONSTRUCTOR_TRACE;}

CMoiety::CMoiety(const CMoiety & src,
                 const CCopasiContainer * pParent):
    CCopasiContainer(src, pParent),
    mKey(GlobalKeys.add("Moiety", this)),           //By G
    mNumber(src.mNumber),
    mINumber(src.mINumber),
    mEquation(src.mEquation, this)
{CONSTRUCTOR_TRACE;}

CMoiety::~CMoiety()
{
  GlobalKeys.remove(mKey);
  DESTRUCTOR_TRACE;
}

void CMoiety::add(C_FLOAT64 value, CMetab * pMetabolite)
{
  CChemEqElement element;
  element.setMultiplicity(value);
  element.setMetabolite(pMetabolite->getKey());

  mEquation.add(element);
}

void CMoiety::cleanup() {mEquation.cleanup();}

C_FLOAT64 CMoiety::dependentNumber()
{
  mNumber = mINumber;

  for (unsigned C_INT32 i = 1; i < mEquation.size(); i++)
    mNumber -= mEquation[i]->getMultiplicity() *
               mEquation[i]->getMetabolite().getNumber();

  return mNumber;
}

C_FLOAT64 CMoiety::dependentRate()
{
  C_FLOAT64 Rate = 0.0;

  for (unsigned C_INT32 i = 1; i < mEquation.size(); i++)
    Rate -= mEquation[i]->getMultiplicity() *
            mEquation[i]->getMetabolite().getConcentrationRate() *
            mEquation[i]->getMetabolite().getCompartment()->getVolumeInv();  //TODO::check!!!!

  return Rate * mEquation[0]->getMetabolite().getCompartment()->getVolume();
}

const std::string & CMoiety::getKey() const {return mKey;} //By G

//const std::string & CMoiety::getName() const {return getObjectName();}

/*std::string CMoiety::getDescription() const
  {
    std::string Description;
    for (unsigned C_INT32 i = 0; i < mEquation.size(); i++)
      {
        if (i)
          {
            if (mEquation[i]->getMultiplicity() < 0.0)
              Description += " - ";
            else
              Description += " + ";
          }
        if (fabs(mEquation[i]->getMultiplicity()) != 1.0)
          Description += StringPrint("%3.1f * ",
                                     fabs(mEquation[i]->getMultiplicity()));
        Description += mEquation[i]->getMetabolite().getObjectName();
        //Description += "{" + mEquation[i]->getCompartmentName() + "}";
        Description += "{" + mEquation[i]->getMetabolite().getCompartment()->getObjectName() + "}";
      }
    return Description;
  }*/

std::string CMoiety::getDescription(const CModel * model) const
  {
    std::string Description;
    for (unsigned C_INT32 i = 0; i < mEquation.size(); i++)
      {
        if (i)
          {
            if (mEquation[i]->getMultiplicity() < 0.0)
              Description += " - ";
            else
              Description += " + ";
          }
        if (fabs(mEquation[i]->getMultiplicity()) != 1.0)
          Description += StringPrint("%3.1f * ",
                                     fabs(mEquation[i]->getMultiplicity()));
        Description += CMetabNameInterface::getDisplayName(model, mEquation[i]->getMetabolite());
      }
    return Description;
  }

bool CMoiety::setName(const std::string name)
{
  return setObjectName(name);
}

void CMoiety::setInitialValue()
{
  mINumber = 0;

  for (unsigned C_INT32 i = 0; i < mEquation.size(); i++)
    mINumber += mEquation[i]->getMultiplicity() *
                mEquation[i]->getMetabolite().getInitialNumber();
  return;
}

/**
 * Return the number value Wei Sun
 */
C_FLOAT64 CMoiety::getNumber() const
  {
    return mINumber;
  }

/**
 * Returns the address of mNumber
 */
void * CMoiety::getNumberAddr()
{
  return &mINumber;
}

/**
 * Saves in Gepasi 3.21 format
 */
/*C_INT32 CMoiety::saveOld(CWriteConfig & configBuffer)
{
  C_INT32 c = 0, t = 7, Fail = 0;

  Fail = configBuffer.setVariable("Metabolite", "string", (void *) & mEquation);
  if (Fail)
    return Fail;
  // we write mNumber instead of concentration, which is ok because Gepasi recalculates this itself
  Fail = configBuffer.setVariable("Concentration", "C_FLOAT64", (void *) & mNumber);
  if (Fail)
    return Fail;
  Fail = configBuffer.setVariable("Compartment", "C_INT32", (void *) & c);
  if (Fail)
    return Fail;
  Fail = configBuffer.setVariable("Type", "C_INT32", (void *) & t);
  return Fail;
}*/
<commit_msg>commented unused method<commit_after>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/model/CMoiety.cpp,v $
   $Revision: 1.30 $
   $Name:  $
   $Author: ssahle $
   $Date: 2004/10/08 09:20:52 $
   End CVS Header */

#include <stdio.h>
#include "mathematics.h"

#define  COPASI_TRACE_CONSTRUCTION

#include "copasi.h"
#include "utilities/CCopasiMessage.h"
#include "CMoiety.h"
#include "CCompartment.h"
#include "utilities/CReadConfig.h"
#include "utilities/CCopasiVector.h"
#include "utilities/utility.h"
#include "CMetabNameInterface.h"

#include "report/CKeyFactory.h"//By G

CMoiety::CMoiety(const std::string & name,
                 const CCopasiContainer * pParent):
    CCopasiContainer(name, pParent, "Moiety"),
    mKey(GlobalKeys.add("Moiety", this)),            //By G
    mNumber(0),
    mINumber(0),
    mEquation("Equation", this)
{CONSTRUCTOR_TRACE;}

CMoiety::CMoiety(const CMoiety & src,
                 const CCopasiContainer * pParent):
    CCopasiContainer(src, pParent),
    mKey(GlobalKeys.add("Moiety", this)),            //By G
    mNumber(src.mNumber),
    mINumber(src.mINumber),
    mEquation(src.mEquation, this)
{CONSTRUCTOR_TRACE;}

CMoiety::~CMoiety()
{
  GlobalKeys.remove(mKey);
  DESTRUCTOR_TRACE;
}

void CMoiety::add(C_FLOAT64 value, CMetab * pMetabolite)
{
  CChemEqElement element;
  element.setMultiplicity(value);
  element.setMetabolite(pMetabolite->getKey());

  mEquation.add(element);
}

void CMoiety::cleanup() {mEquation.cleanup();}

C_FLOAT64 CMoiety::dependentNumber()
{
  mNumber = mINumber;

  for (unsigned C_INT32 i = 1; i < mEquation.size(); i++)
    mNumber -= mEquation[i]->getMultiplicity() *
               mEquation[i]->getMetabolite().getNumber();

  return mNumber;
}

/*C_FLOAT64 CMoiety::dependentRate()
{
  C_FLOAT64 Rate = 0.0;

  for (unsigned C_INT32 i = 1; i < mEquation.size(); i++)
    Rate -= mEquation[i]->getMultiplicity() *
            mEquation[i]->getMetabolite().getConcentrationRate() *
            mEquation[i]->getMetabolite().getCompartment()->getVolumeInv();  //TODO::check!!!!

  return Rate * mEquation[0]->getMetabolite().getCompartment()->getVolume();
}*/ //seems to be unused

const std::string & CMoiety::getKey() const {return mKey;} //By G

//const std::string & CMoiety::getName() const {return getObjectName();}

/*std::string CMoiety::getDescription() const
  {
    std::string Description;
    for (unsigned C_INT32 i = 0; i < mEquation.size(); i++)
      {
        if (i)
          {
            if (mEquation[i]->getMultiplicity() < 0.0)
              Description += " - ";
            else
              Description += " + ";
          }
        if (fabs(mEquation[i]->getMultiplicity()) != 1.0)
          Description += StringPrint("%3.1f * ",
                                     fabs(mEquation[i]->getMultiplicity()));
        Description += mEquation[i]->getMetabolite().getObjectName();
        //Description += "{" + mEquation[i]->getCompartmentName() + "}";
        Description += "{" + mEquation[i]->getMetabolite().getCompartment()->getObjectName() + "}";
      }
    return Description;
  }*/

std::string CMoiety::getDescription(const CModel * model) const
  {
    std::string Description;
    for (unsigned C_INT32 i = 0; i < mEquation.size(); i++)
      {
        if (i)
          {
            if (mEquation[i]->getMultiplicity() < 0.0)
              Description += " - ";
            else
              Description += " + ";
          }
        if (fabs(mEquation[i]->getMultiplicity()) != 1.0)
          Description += StringPrint("%3.1f * ",
                                     fabs(mEquation[i]->getMultiplicity()));
        Description += CMetabNameInterface::getDisplayName(model, mEquation[i]->getMetabolite());
      }
    return Description;
  }

bool CMoiety::setName(const std::string name)
{
  return setObjectName(name);
}

void CMoiety::setInitialValue()
{
  mINumber = 0;

  for (unsigned C_INT32 i = 0; i < mEquation.size(); i++)
    mINumber += mEquation[i]->getMultiplicity() *
                mEquation[i]->getMetabolite().getInitialNumber();
  return;
}

/**
 * Return the number value Wei Sun
 */
C_FLOAT64 CMoiety::getNumber() const
  {
    return mINumber;
  }

/**
 * Returns the address of mNumber
 */
void * CMoiety::getNumberAddr()
{
  return &mINumber;
}

/**
 * Saves in Gepasi 3.21 format
 */
/*C_INT32 CMoiety::saveOld(CWriteConfig & configBuffer)
{
  C_INT32 c = 0, t = 7, Fail = 0;

  Fail = configBuffer.setVariable("Metabolite", "string", (void *) & mEquation);
  if (Fail)
    return Fail;
  // we write mNumber instead of concentration, which is ok because Gepasi recalculates this itself
  Fail = configBuffer.setVariable("Concentration", "C_FLOAT64", (void *) & mNumber);
  if (Fail)
    return Fail;
  Fail = configBuffer.setVariable("Compartment", "C_INT32", (void *) & c);
  if (Fail)
    return Fail;
  Fail = configBuffer.setVariable("Type", "C_INT32", (void *) & t);
  return Fail;
}*/
<|endoftext|>


<commit_before>//=====================================================================//
/*! @file
    @brief  RX24T/RX64M/RX71M/RX65N/RX66T/RX72N RayTracer サンプル
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2018, 2020 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include "common/renesas.hpp"
#include "common/cmt_mgr.hpp"
#include "common/fixed_fifo.hpp"
#include "common/sci_io.hpp"
#include "common/format.hpp"
#include "common/command.hpp"

#include "graphics/font8x16.hpp"
#include "graphics/kfont.hpp"
#include "graphics/font.hpp"
#include "graphics/tgl.hpp"
#include "graphics/shape_3d.hpp"

namespace {

	typedef device::cmt_mgr<device::CMT0> CMT;
	CMT			cmt_;

	typedef graphics::font8x16 AFONT;
	typedef graphics::kfont_null KFONT;
	typedef graphics::font<AFONT, KFONT> FONT;
	AFONT		afont_;
	KFONT		kfont_;
	FONT		font_(afont_, kfont_);

#if defined(SIG_RX72N)
	/// for RX72N Envision Kit
	typedef device::system_io<16'000'000> SYSTEM_IO;
	typedef device::PORT<device::PORT4, device::bitpos::B0> LED;
	typedef device::PORT<device::PORT0, device::bitpos::B7> SW2;
	typedef device::SCI2 SCI_CH;
	static const char* system_str_ = { "RX72N Envision Kit" };
	static const uint16_t LCD_X = 480;
	static const uint16_t LCD_Y = 272;
	uint16_t*	fb_ = reinterpret_cast<uint16_t*>(0x0080'0000);
	typedef device::PORT<device::PORTB, device::bitpos::B3> LCD_DISP;
	typedef device::PORT<device::PORT6, device::bitpos::B7> LCD_LIGHT;
	typedef device::glcdc_mgr<device::GLCDC, LCD_X, LCD_Y, graphics::pixel::TYPE::RGB565> GLCDC_MGR;
//	typedef graphics::render<GLCDC_MGR, FONT> RENDER;
	typedef device::drw2d_mgr<GLCDC_MGR, FONT> RENDER;

	GLCDC_MGR	glcdc_mgr_(nullptr, fb_);
	RENDER		render_(glcdc_mgr_, font_);

	static const uint32_t VNUM = 500;  // 最大の頂点数
	static const uint32_t PNUM = 300;  // プリミティブ最大数
	typedef graphics::tgl<RENDER, VNUM, PNUM> TGL;
	TGL			tgl_(render_);

	typedef graphics::shape_3d<TGL> SHAPE;
	SHAPE		shape_(tgl_);
#endif

	typedef graphics::def_color DEF_COLOR;

	typedef utils::fixed_fifo<char, 512>  RECV_BUFF;
	typedef utils::fixed_fifo<char, 1024> SEND_BUFF;
	typedef device::sci_io<SCI_CH, RECV_BUFF, SEND_BUFF> SCI;
	SCI			sci_;

	typedef utils::command<256> CMD;
	CMD 		cmd_;

	void command_()
	{
		if(!cmd_.service()) {
			return;
		}
		uint8_t cmdn = cmd_.get_words();
		if(cmdn >= 1) {
			bool f = false;
			if(cmd_.cmp_word(0, "clear")) {

			} else if(cmd_.cmp_word(0, "help")) {
				f = true;
			}
			if(!f) {
				char tmp[128];
				if(cmd_.get_word(0, tmp, sizeof(tmp))) {
					utils::format("Command error: '%s'\n") % tmp;
				}
			}
		}
	}
}

extern "C" {

	uint32_t millis(void)
	{
		return cmt_.get_counter();
	}

	void sci_putch(char ch)
	{
		sci_.putch(ch);
	}

	void sci_puts(const char* str)
	{
		sci_.puts(str);
	}

	char sci_getch(void)
	{
		return sci_.getch();
	}

	uint16_t sci_length()
	{
		return sci_.recv_length();
	}
}

int main(int argc, char** argv);

int main(int argc, char** argv)
{
	SYSTEM_IO::setup_system_clock();

	{  // SCI 設定
		uint8_t intr_lvl = 2;
		sci_.start(115200, intr_lvl);
	}

	{  // 時間計測タイマー（1000Hz）
		uint8_t intr_lvl = 4;
		cmt_.start(1000, intr_lvl);
	}

	utils::format("\r%s Start for TinyGL: %u, %u\n") % system_str_ % LCD_X % LCD_Y;

	cmd_.set_prompt("# ");

	{  // GLCDC 初期化
		LCD_DISP::DIR  = 1;
		LCD_LIGHT::DIR = 1;
		LCD_DISP::P  = 0;  // DISP Disable
		LCD_LIGHT::P = 0;  // BackLight Disable (No PWM)
		if(glcdc_mgr_.start()) {
			utils::format("Start GLCDC\n");
			LCD_DISP::P  = 1;  // DISP Enable
			LCD_LIGHT::P = 1;  // BackLight Enable (No PWM)
			if(!glcdc_mgr_.control(GLCDC_MGR::CONTROL_CMD::START_DISPLAY)) {
				utils::format("GLCDC ctrl fail...\n");
			} else {
				if(!glcdc_mgr_.enable_double_buffer()) {  // ダブルバッファを有効にする。
					utils::format("Can't enable double-bufer\n");
				}
			}
		} else {
			utils::format("Fail GLCDC\n");
		}
	}

	{  // DRW2D 初期化
		if(render_.start()) {
			utils::format("DRW2D Start\n");
			render_.list_info();
		} else {
			utils::format("DRW2D Fail...\n");
		}
	}

	{  // TGL 初期化
		tgl_.start();
	}

	LED::OUTPUT();

	uint8_t n = 0;
	int16_t xx = 0;
	uint16_t nn = 0;
	float ax = 0.0f;
	float ay = 0.0f;
	while(1) {
		render_.sync_frame();

		render_.clear(DEF_COLOR::Black);

		auto& m = tgl_.at_matrix();
		m.set_viewport(0, 0, LCD_X, LCD_Y);

		m.set_mode(gl::matrixf::mode::projection);
		m.identity();
		m.perspective(45.0f, static_cast<float>(LCD_X) / static_cast<float>(LCD_Y), 1.0f, 50.0f);

		m.set_mode(gl::matrixf::mode::modelview);
		m.identity();
		m.translate(0.0f, 0.0f, -10.0f);
		m.rotate(ax, 1.0f, 0.0f, 0.0f);
		m.rotate(ay, 0.0f, 1.0f, 0.0f);

		ax += 1.0f;
		if(ax >= 360.0f) ax -= 360.0f;
		ay += 1.5f;
		if(ay >= 360.0f) ay -= 360.0f;

		if(nn < 240) {
			tgl_.LineWidth(3.0f);
			shape_.WireCube(2.0f);
		} else {
			shape_.SolidCube(2.0f);
		}
		++nn;
		if(nn >= 480) nn = 0;

		tgl_.renderring();

//		render_.set_fore_color(graphics::def_color::White);
//		render_.fill_box(vtx::srect(xx, 0, 50, 50));
//		++xx;
//		if(xx >= 480) xx = 0;

		command_();

		++n;
		if(n >= 30) {
			n = 0;
		}
		if(n < 10) {
			LED::P = 0;
		} else {
			LED::P = 1;
		}

		render_.flip();
	}
}
<commit_msg>Update: cleanup<commit_after>//=====================================================================//
/*! @file
    @brief  RX24T/RX64M/RX71M/RX65N/RX66T/RX72N RayTracer サンプル
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2018, 2021 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include "common/renesas.hpp"
#include "common/cmt_mgr.hpp"
#include "common/fixed_fifo.hpp"
#include "common/sci_io.hpp"
#include "common/format.hpp"
#include "common/command.hpp"

#include "graphics/font8x16.hpp"
#include "graphics/kfont.hpp"
#include "graphics/font.hpp"
#include "graphics/tgl.hpp"
#include "graphics/shape_3d.hpp"

namespace {

	typedef device::cmt_mgr<device::CMT0> CMT;
	CMT			cmt_;

	typedef graphics::font8x16 AFONT;
	typedef graphics::kfont_null KFONT;
	typedef graphics::font<AFONT, KFONT> FONT;
	AFONT		afont_;
	KFONT		kfont_;
	FONT		font_(afont_, kfont_);

#if defined(SIG_RX72N)
	/// for RX72N Envision Kit
	typedef device::system_io<16'000'000> SYSTEM_IO;
	typedef device::PORT<device::PORT4, device::bitpos::B0> LED;
	typedef device::PORT<device::PORT0, device::bitpos::B7> SW2;
	typedef device::SCI2 SCI_CH;
	static const char* system_str_ = { "RX72N Envision Kit" };
	static const uint16_t LCD_X = 480;
	static const uint16_t LCD_Y = 272;
	uint16_t*	fb_ = reinterpret_cast<uint16_t*>(0x0080'0000);
	typedef device::PORT<device::PORTB, device::bitpos::B3> LCD_DISP;
	typedef device::PORT<device::PORT6, device::bitpos::B7> LCD_LIGHT;
	typedef device::glcdc_mgr<device::GLCDC, LCD_X, LCD_Y, graphics::pixel::TYPE::RGB565> GLCDC_MGR;
	typedef device::drw2d_mgr<GLCDC_MGR, FONT> RENDER;

	GLCDC_MGR	glcdc_mgr_(nullptr, fb_);
	RENDER		render_(glcdc_mgr_, font_);

	static const uint32_t VNUM = 500;  // 最大の頂点数
	static const uint32_t PNUM = 300;  // プリミティブ最大数
	typedef graphics::tgl<RENDER, VNUM, PNUM> TGL;
	TGL			tgl_(render_);

	typedef graphics::shape_3d<TGL> SHAPE;
	SHAPE		shape_(tgl_);
#endif

	typedef graphics::def_color DEF_COLOR;

	typedef utils::fixed_fifo<char, 512>  RECV_BUFF;
	typedef utils::fixed_fifo<char, 1024> SEND_BUFF;
	typedef device::sci_io<SCI_CH, RECV_BUFF, SEND_BUFF> SCI;
	SCI			sci_;

	typedef utils::command<256> CMD;
	CMD 		cmd_;

	void command_()
	{
		if(!cmd_.service()) {
			return;
		}
		uint8_t cmdn = cmd_.get_words();
		if(cmdn >= 1) {
			bool f = false;
			if(cmd_.cmp_word(0, "clear")) {

			} else if(cmd_.cmp_word(0, "help")) {
				f = true;
			}
			if(!f) {
				char tmp[128];
				if(cmd_.get_word(0, tmp, sizeof(tmp))) {
					utils::format("Command error: '%s'\n") % tmp;
				}
			}
		}
	}
}

extern "C" {

	uint32_t millis(void)
	{
		return cmt_.get_counter();
	}

	void sci_putch(char ch)
	{
		sci_.putch(ch);
	}

	void sci_puts(const char* str)
	{
		sci_.puts(str);
	}

	char sci_getch(void)
	{
		return sci_.getch();
	}

	uint16_t sci_length()
	{
		return sci_.recv_length();
	}
}

int main(int argc, char** argv);

int main(int argc, char** argv)
{
	SYSTEM_IO::setup_system_clock();

	{  // SCI 設定
		uint8_t intr_lvl = 2;
		sci_.start(115200, intr_lvl);
	}

	{  // 時間計測タイマー（1000Hz）
		uint8_t intr_lvl = 4;
		cmt_.start(1000, intr_lvl);
	}

	utils::format("\r%s Start for TinyGL: %u, %u\n") % system_str_ % LCD_X % LCD_Y;

	cmd_.set_prompt("# ");

	{  // GLCDC 初期化
		LCD_DISP::DIR  = 1;
		LCD_LIGHT::DIR = 1;
		LCD_DISP::P  = 0;  // DISP Disable
		LCD_LIGHT::P = 0;  // BackLight Disable (No PWM)
		if(glcdc_mgr_.start()) {
			utils::format("Start GLCDC\n");
			LCD_DISP::P  = 1;  // DISP Enable
			LCD_LIGHT::P = 1;  // BackLight Enable (No PWM)
			if(!glcdc_mgr_.control(GLCDC_MGR::CONTROL_CMD::START_DISPLAY)) {
				utils::format("GLCDC ctrl fail...\n");
			} else {
				if(!glcdc_mgr_.enable_double_buffer()) {  // ダブルバッファを有効にする。
					utils::format("Can't enable double-bufer\n");
				}
			}
		} else {
			utils::format("Fail GLCDC\n");
		}
	}

	{  // DRW2D 初期化
		if(render_.start()) {
			utils::format("DRW2D Start\n");
			render_.list_info();
		} else {
			utils::format("DRW2D Fail...\n");
		}
	}

	{  // TGL 初期化
		tgl_.start();
	}

	LED::OUTPUT();

	uint8_t n = 0;
	int16_t xx = 0;
	uint16_t nn = 0;
	float ax = 0.0f;
	float ay = 0.0f;
	while(1) {
		render_.sync_frame();

		render_.clear(DEF_COLOR::Black);

		auto& m = tgl_.at_matrix();
		m.set_viewport(0, 0, LCD_X, LCD_Y);

		m.set_mode(gl::matrixf::mode::projection);
		m.identity();
		m.perspective(45.0f, static_cast<float>(LCD_X) / static_cast<float>(LCD_Y), 1.0f, 50.0f);

		m.set_mode(gl::matrixf::mode::modelview);
		m.identity();
		m.translate(0.0f, 0.0f, -10.0f);
		m.rotate(ax, 1.0f, 0.0f, 0.0f);
		m.rotate(ay, 0.0f, 1.0f, 0.0f);

		ax += 1.0f;
		if(ax >= 360.0f) ax -= 360.0f;
		ay += 1.5f;
		if(ay >= 360.0f) ay -= 360.0f;

		if(nn < 240) {
			tgl_.LineWidth(3.0f);
			shape_.WireCube(2.0f);
		} else {
			shape_.SolidCube(2.0f);
		}
		++nn;
		if(nn >= 480) nn = 0;

		tgl_.renderring();

//		render_.set_fore_color(graphics::def_color::White);
//		render_.fill_box(vtx::srect(xx, 0, 50, 50));
//		++xx;
//		if(xx >= 480) xx = 0;

		command_();

		++n;
		if(n >= 30) {
			n = 0;
		}
		if(n < 10) {
			LED::P = 0;
		} else {
			LED::P = 1;
		}

		render_.flip();
	}
}
<|endoftext|>


<commit_before>#ifndef HALITE_HLT_H
#define HALITE_HLT_H

#ifdef _WIN32
#define _USE_MATH_DEFINES
#endif

#include <algorithm>
#include <cassert>
#include <cmath>
#include <iostream>
#include <sstream>
#include <string>
#include <unordered_map>
#include <vector>

#include "Constants.hpp"
#include "Globals.hpp"
#include "Log.hpp"
#include "Entity.hpp"
#include "Map.hpp"
#include "Move.hpp"
#include "Behavior.hpp"

namespace hlt {
    static auto get_string() -> std::string {
        std::string result;
        std::getline(std::cin, result);
        return result;
    }

    static auto send_string(std::string text) -> void {
        // std::endl used to flush
        std::cout << text << std::endl;
    }

    static auto parse_ship(std::istream& iss)
    -> std::pair<EntityIndex, Ship> {
        EntityIndex ship_id;
        iss >> ship_id;

        Ship ship;
        iss >> ship.location.pos_x;
        iss >> ship.location.pos_y;
        iss >> ship.health;
        iss >> ship.velocity.vel_x;
        iss >> ship.velocity.vel_y;
        int docking_status;
        iss >> docking_status;
        ship.docking_status = static_cast<DockingStatus>(docking_status);
        iss >> ship.docked_planet;
        iss >> ship.docking_progress;
        iss >> ship.weapon_cooldown;

        ship.radius = GameConstants::get().SHIP_RADIUS;

        return std::make_pair(ship_id, ship);
    }

    static auto parse_planet(std::istream& iss)
        -> std::pair<EntityIndex, Planet> {
        Planet planet = {};
        EntityIndex planet_id;

        iss >> planet_id;
        iss >> planet.location.pos_x;
        iss >> planet.location.pos_y;
        iss >> planet.health;
        iss >> planet.radius;
        iss >> planet.docking_spots;
        iss >> planet.current_production;
        iss >> planet.remaining_production;
        int owned;
        iss >> owned;
        if (owned == 1) {
            planet.owned = true;
            int owner;
            iss >> owner;
            planet.owner = static_cast<PlayerId>(owner);
        }
        else {
            planet.owned = false;
            int false_owner;
            iss >> false_owner;
        }

        int num_docked_ships;
        iss >> num_docked_ships;
        planet.docked_ships.reserve(num_docked_ships);
        for (auto j = 0; j < num_docked_ships; j++) {
            EntityIndex ship_id;
            iss >> ship_id;
            planet.docked_ships.push_back(ship_id);
        }

        return std::make_pair(planet_id, planet);
    }

    static auto parse_map(std::string& input) -> Map {
        auto map = Map(map_width, map_height);
        std::stringstream iss(input);

        int num_players;
        iss >> num_players;

        // Meaningless loop indices, used as bookkeeping
        for (auto i = 0; i < num_players; i++) {
            PlayerId player_id;
            int player_id_int;
            iss >> player_id_int;
            player_id = static_cast<PlayerId>(player_id_int);

            int num_ships;
            iss >> num_ships;

            map.ships[player_id] = {};
            for (auto j = 0; j < num_ships; j++) {
                const auto& ship_pair = parse_ship(iss);
                map.ships[player_id].insert(ship_pair);
            }
        }

        int num_planets;
        iss >> num_planets;
        for (auto i = 0; i < num_planets; i++) {
            const auto& planet_pair = parse_planet(iss);
            map.planets[planet_pair.first] = planet_pair.second;
        }

        return map;
    }

    static auto get_map() -> Map {
        Log::log("--- NEW TURN ---");
        auto input = get_string();
        return parse_map(input);
    }

    /**
     * Send all queued moves to the game engine.
     * @param moves
     */
    static auto send_moves(std::vector<Move>& moves) -> void {
        std::ostringstream oss;
        for (const auto& move : moves) {
            switch (move.type) {
                case MoveType::Noop:
                    continue;
                case MoveType::Undock:
                    oss << "u " << move.ship_id << " ";
                    break;
                case MoveType::Dock:
                    oss << "d " << move.ship_id << " "
                        << move.move.dock_to << " ";
                    break;
                case MoveType::Thrust:
                    oss << "t " << move.ship_id << " "
                        << move.move.thrust.thrust << " "
                        << move.move.thrust.angle << " ";
                    break;
            }
        }
        Log::log(oss.str());
        send_string(oss.str());
    }

    /**
     * Initialize our bot with the given name, getting back our player tag and
     * the initial map.
     * @param bot_name
     * @return
     */
    static auto initialize(std::string bot_name) -> std::pair<PlayerId, Map> {
        std::cout.sync_with_stdio(false);
        my_tag = static_cast<PlayerId>(std::stoi(get_string()));

        Log::open(std::to_string(static_cast<int>(my_tag)) + bot_name + ".log");

        std::stringstream iss(get_string());
        iss >> map_width >> map_height;

        auto initial_map = get_map();

        send_string(bot_name);

        return std::make_pair(my_tag, initial_map);
    }
}

#endif //HALITE_HLT_H
<commit_msg>fix C++ build errors (#656)<commit_after>#ifndef HALITE_HLT_H
#define HALITE_HLT_H

#ifdef _WIN32
#define _USE_MATH_DEFINES
#endif

#include <algorithm>
#include <cassert>
#include <cmath>
#include <iostream>
#include <sstream>
#include <string>
#include <unordered_map>
#include <vector>

#include "Constants.hpp"
#include "Log.hpp"
#include "Entity.hpp"
#include "Map.hpp"
#include "Move.hpp"

namespace hlt {
    static auto get_string() -> std::string {
        std::string result;
        std::getline(std::cin, result);
        return result;
    }

    static auto send_string(std::string text) -> void {
        // std::endl used to flush
        std::cout << text << std::endl;
    }

    static auto parse_ship(std::istream& iss)
    -> std::pair<EntityIndex, Ship> {
        EntityIndex ship_id;
        iss >> ship_id;

        Ship ship;
        iss >> ship.location.pos_x;
        iss >> ship.location.pos_y;
        iss >> ship.health;
        iss >> ship.velocity.vel_x;
        iss >> ship.velocity.vel_y;
        int docking_status;
        iss >> docking_status;
        ship.docking_status = static_cast<DockingStatus>(docking_status);
        iss >> ship.docked_planet;
        iss >> ship.docking_progress;
        iss >> ship.weapon_cooldown;

        ship.radius = GameConstants::get().SHIP_RADIUS;

        return std::make_pair(ship_id, ship);
    }

    static auto parse_planet(std::istream& iss)
        -> std::pair<EntityIndex, Planet> {
        Planet planet = {};
        EntityIndex planet_id;

        iss >> planet_id;
        iss >> planet.location.pos_x;
        iss >> planet.location.pos_y;
        iss >> planet.health;
        iss >> planet.radius;
        iss >> planet.docking_spots;
        iss >> planet.current_production;
        iss >> planet.remaining_production;
        int owned;
        iss >> owned;
        if (owned == 1) {
            planet.owned = true;
            int owner;
            iss >> owner;
            planet.owner = static_cast<PlayerId>(owner);
        }
        else {
            planet.owned = false;
            int false_owner;
            iss >> false_owner;
        }

        int num_docked_ships;
        iss >> num_docked_ships;
        planet.docked_ships.reserve(num_docked_ships);
        for (auto j = 0; j < num_docked_ships; j++) {
            EntityIndex ship_id;
            iss >> ship_id;
            planet.docked_ships.push_back(ship_id);
        }

        return std::make_pair(planet_id, planet);
    }

    static auto parse_map(std::string& input) -> Map {
        int map_width, map_height, num_players;
        std::stringstream iss(get_string());
        iss >> map_width >> map_height;
        iss >> num_players;

        auto map = Map(map_width, map_height);

        // Meaningless loop indices, used as bookkeeping
        for (auto i = 0; i < num_players; i++) {
            PlayerId player_id;
            int player_id_int;
            iss >> player_id_int;
            player_id = static_cast<PlayerId>(player_id_int);

            int num_ships;
            iss >> num_ships;

            map.ships[player_id] = {};
            for (auto j = 0; j < num_ships; j++) {
                const auto& ship_pair = parse_ship(iss);
                map.ships[player_id].insert(ship_pair);
            }
        }

        int num_planets;
        iss >> num_planets;
        for (auto i = 0; i < num_planets; i++) {
            const auto& planet_pair = parse_planet(iss);
            map.planets[planet_pair.first] = planet_pair.second;
        }

        return map;
    }

    static auto get_map() -> Map {
        Log::log("--- NEW TURN ---");
        auto input = get_string();
        return parse_map(input);
    }

    /**
     * Send all queued moves to the game engine.
     * @param moves
     */
    static auto send_moves(std::vector<Move>& moves) -> void {
        std::ostringstream oss;
        for (const auto& move : moves) {
            switch (move.type) {
                case MoveType::Noop:
                    continue;
                case MoveType::Undock:
                    oss << "u " << move.ship_id << " ";
                    break;
                case MoveType::Dock:
                    oss << "d " << move.ship_id << " "
                        << move.move.dock_to << " ";
                    break;
                case MoveType::Thrust:
                    oss << "t " << move.ship_id << " "
                        << move.move.thrust.thrust << " "
                        << move.move.thrust.angle << " ";
                    break;
            }
        }
        Log::log(oss.str());
        send_string(oss.str());
    }

    /**
     * Initialize our bot with the given name, getting back our player tag and
     * the initial map.
     * @param bot_name
     * @return
     */
    static auto initialize(std::string bot_name) -> std::pair<PlayerId, Map> {
        std::cout.sync_with_stdio(false);
        auto my_tag = static_cast<PlayerId>(std::stoi(get_string()));

        Log::open(std::to_string(static_cast<int>(my_tag)) + bot_name + ".log");

        auto initial_map = get_map();

        send_string(bot_name);

        return std::make_pair(my_tag, initial_map);
    }
}

#endif //HALITE_HLT_H
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014-2016, imec
 * All rights reserved.
 */

#include "error.h"
#include "bpmf.h"

#include <random>
#include <memory>
#include <cstdio>
#include <iostream>
#include <climits>
#include <stdexcept>

#include "io.h"

#if defined(_OPENMP)
#include "omp.h"

#pragma omp declare reduction (VectorPlus : VectorNd : omp_out += omp_in) initializer(omp_priv = VectorNd::Zero())
#pragma omp declare reduction (MatrixPlus : MatrixNNd : omp_out += omp_in) initializer(omp_priv = MatrixNNd::Zero())
#endif

static const bool measure_perf = false;

std::ostream *Sys::os;
int Sys::procid = -1;
int Sys::nprocs = -1;

int Sys::nsims;
int Sys::burnin;
double Sys::alpha;

bool Sys::permute = true;

bool Sys::verbose = false;

unsigned Sys::grain_size;

void calc_upper_part(MatrixNNd &m, VectorNd v);         // function for calcutation of an upper part of a symmetric matrix: m = v * v.transpose();
void copy_lower_part(MatrixNNd &m);                     // function to copy an upper part of a symmetric matrix to a lower part

// verifies that A has the same non-zero structure as B
void assert_same_struct(SparseMatrixD &A, SparseMatrixD &B)
{
    SparseMatrixD At = A.transpose();
    SparseMatrixD Bt = B.transpose();
    assert(A.cols() == B.cols());
    assert(At.cols() == Bt.cols());

    for(int i=0; i<A.cols(); ++i) assert(A.col(i).nonZeros() == B.col(i).nonZeros());
    for(int i=0; i<At.cols(); ++i) assert(At.col(i).nonZeros() == Bt.col(i).nonZeros());
}

//
// Does predictions for prediction matrix T
// Computes RMSE (Root Means Square Error)
//
void Sys::predict(Sys& other, bool all)
{
    int n = (iter < burnin) ? 0 : (iter - burnin);

    double se(0.0); // squared err
    double se_avg(0.0); // squared avg err
    unsigned nump(0); // number of predictions

    int lo = all ? 0 : from();
    int hi = all ? num() : to();
    #pragma omp parallel for reduction(+:se,se_avg,nump)
    for(int k = lo; k<hi; k++) {
        for (Eigen::SparseMatrix<double>::InnerIterator it(T,k); it; ++it)
        {
            auto m = items().col(it.col());
            auto u = other.items().col(it.row());

            assert(m.norm() > 0.0);
            assert(u.norm() > 0.0);

            const double pred = m.dot(u) + mean_rating;
            se += sqr(it.value() - pred);

            // update average prediction
            double &avg = Pavg.coeffRef(it.row(), it.col());
            double delta = pred - avg;
            avg = (n == 0) ? pred : (avg + delta/n);
            double &m2 = Pm2.coeffRef(it.row(), it.col());
            m2 = (n == 0) ? 0 : m2 + delta * (pred - avg);
            se_avg += sqr(it.value() - avg);

            nump++;
        }
    }

    rmse = sqrt( se / nump );
    rmse_avg = sqrt( se_avg / nump );
}

//
// Prints sampling progress
//
void Sys::print(double items_per_sec, double ratings_per_sec, double norm_u, double norm_m) {
  char buf[1024];
  std::string phase = (iter < Sys::burnin) ? "Burnin" : "Sampling";
  sprintf(buf, "%d: %s iteration %d:\t RMSE: %3.4f\tavg RMSE: %3.4f\tFU(%6.2f)\tFM(%6.2f)\titems/sec: %6.2f\tratings/sec: %6.2fM\n",
                    Sys::procid, phase.c_str(), iter, rmse, rmse_avg, norm_u, norm_m, items_per_sec, ratings_per_sec / 1e6);
  Sys::cout() << buf;
}

//
// Constructor with that reads MTX files
//
Sys::Sys(std::string name, std::string fname, std::string probename)
    : name(name), iter(-1), assigned(false), dom(nprocs+1)
{

    read_matrix(fname, M);
    read_matrix(probename, T);

    auto rows = std::max(M.rows(), T.rows());
    auto cols = std::max(M.cols(), T.cols());
    M.conservativeResize(rows,cols);
    T.conservativeResize(rows,cols);
    Pm2 = Pavg = Torig = T; // reference ratings and predicted ratings
    assert(M.rows() == Pavg.rows());
    assert(M.cols() == Pavg.cols());
    assert(Sys::nprocs <= (int)Sys::max_procs);
}

//
// Constructs Sys as transpose of existing Sys
//
Sys::Sys(std::string name, const SparseMatrixD &Mt, const SparseMatrixD &Pt) : name(name), iter(-1), assigned(false), dom(nprocs+1) {
    M = Mt.transpose();
    Pm2 = Pavg = T = Torig = Pt.transpose(); // reference ratings and predicted ratings
    assert(M.rows() == Pavg.rows());
    assert(M.cols() == Pavg.cols());
}

Sys::~Sys()
{
    if (measure_perf) {
        Sys::cout() << " --------------------\n";
        Sys::cout() << name << ": sampling times on " << procid << "\n";
        for(int i = from(); i<to(); ++i)
        {
            Sys::cout() << "\t" << nnz(i) << "\t" << sample_time.at(i) / nsims  << "\n";
        }
        Sys::cout() << " --------------------\n\n";
    }
}

bool Sys::has_prop_posterior() const
{
    return propMu.nonZeros() > 0;
}

void Sys::add_prop_posterior(std::string fnames)
{
    if (fnames.empty()) return;

    std::size_t pos = fnames.find_first_of(",");
    std::string mu_name = fnames.substr(0, pos);
    std::string lambda_name = fnames.substr(pos+1);

    read_matrix(mu_name, propMu);
    read_matrix(lambda_name, propLambda);

    assert(propMu.cols() == num());
    assert(propLambda.cols() == num());

    assert(propMu.rows() == num_latent);
    assert(propLambda.rows() == num_latent * num_latent);

}

//
// Intializes internal Matrices and Vectors
//
void Sys::init()
{
    //-- M
    assert(M.rows() > 0 && M.cols() > 0);
    mean_rating = M.sum() / M.nonZeros();
    items().setZero();
    sum_map().setZero();
    cov_map().setZero();
    norm_map().setZero();
    col_permutation.setIdentity(num());

    aggrMu = Eigen::MatrixXd::Zero(num_latent, num());
    aggrLambda = Eigen::MatrixXd::Zero(num_latent * num_latent, num());

    Sys::cout() << "mean rating = " << mean_rating << std::endl;
    Sys::cout() << "total number of ratings in train = " << M.nonZeros() << std::endl;
    Sys::cout() << "total number of ratings in test = " << T.nonZeros() << std::endl;
    Sys::cout() << "num " << name << ": " << num() << std::endl;
    if (has_prop_posterior())
    {
        Sys::cout() << "with propagated posterior" << std::endl;
    }

    if (measure_perf) sample_time.resize(num(), .0);
}

class PrecomputedLLT : public Eigen::LLT<MatrixNNd>
{
  public:
    void operator=(const MatrixNNd &m) { m_matrix = m; m_isInitialized = true; m_info = Eigen::Success; }
};

//
// Update ONE movie or one user
//
VectorNd Sys::sample(long idx, const MapNXd in)
{
    auto start = tick();

    VectorNd hp_mu;
    MatrixNNd hp_LambdaF;
    MatrixNNd hp_LambdaL;
    if (has_prop_posterior())
    {
        hp_mu = propMu.col(idx);
        hp_LambdaF = Eigen::Map<MatrixNNd>(propLambda.col(idx).data());
        hp_LambdaL =  hp_LambdaF.llt().matrixL();
    }
    else
    {
        hp_mu = hp.mu;
        hp_LambdaF = hp.LambdaF;
        hp_LambdaL = hp.LambdaL;
    }

    int breakpoint1 = 24;
    int breakpoint2 = 10500;

    const int count = M.innerVector(idx).nonZeros(); // count of nonzeros elements in idx-th row of M matrix
                                                     // (how many movies watched idx-th user?).

    VectorNd rr = hp_LambdaF * hp.mu;                 // vector num_latent x 1, we will use it in formula (14) from the paper
    PrecomputedLLT chol;                             // matrix num_latent x num_latent, chol="lambda_i with *" from formula (14)

    // if this user movie has less than 1K ratings,
    // we do a serial rank update
    if( count < breakpoint1 ) {

        chol = hp_LambdaL;
        for (SparseMatrixD::InnerIterator it(M,idx); it; ++it) {
            auto col = in.col(it.row());
            chol.rankUpdate(col, alpha);
            rr.noalias() += col * ((it.value() - mean_rating) * alpha);
        }

    // else we do a serial full cholesky decomposition
    // (not used if breakpoint1 == breakpoint2)
    } else if (count < breakpoint2) {

        MatrixNNd MM(MatrixNNd::Zero());
        for (SparseMatrixD::InnerIterator it(M,idx); it; ++it) {
            auto col = in.col(it.row());

            //MM.noalias() += col * col.transpose();
            calc_upper_part(MM, col);

            rr.noalias() += col * ((it.value() - mean_rating) * alpha);
        }

        // Here, we copy a triangular upper part to a triangular lower part, because the matrix is symmetric.
        copy_lower_part(MM);

        chol.compute(hp_LambdaF + alpha * MM);
    // for > 1K ratings, we have additional thread-level parallellism
    } else {
        auto from = M.outerIndexPtr()[idx];   // "from" belongs to [1..m], m - number of movies in M matrix
        auto to = M.outerIndexPtr()[idx+1];   // "to"   belongs to [1..m], m - number of movies in M matrix
        MatrixNNd MM(MatrixNNd::Zero());               // matrix num_latent x num_latent

        // #pragma omp parallel for reduction(VectorPlus:rr) reduction(MatrixPlus:MM)
        #pragma omp parallel for reduction(VectorPlus:rr) reduction(MatrixPlus:MM) schedule(dynamic,200)
        for(int j = from; j<to; ++j) {                 // for each nonzeros elemen in the i-th row of M matrix
            auto val = M.valuePtr()[j];                // value of the j-th nonzeros element from idx-th row of M matrix
            auto idx = M.innerIndexPtr()[j];           // index "j" of the element [i,j] from M matrix in compressed M matrix
            auto col = in.col(idx);                    // vector num_latent x 1 from V matrix: M[i,j] = U[i,:] x V[idx,:]

            //MM.noalias() += col * col.transpose();     // outer product
            calc_upper_part(MM, col);
            rr.noalias() += col * ((val - mean_rating) * alpha); // vector num_latent x 1
        }

        copy_lower_part(MM);

        chol.compute(hp_LambdaF + alpha * MM);         // matrix num_latent x num_latent
                                                       // chol="lambda_i with *" from formula (14)
                                                       // lambda_i with * = LambdaU + alpha * MM
    }

    if(chol.info() != Eigen::Success) THROWERROR("Cholesky failed");

    // now we should calculate formula (14) from the paper
    // u_i for k-th iteration = Gaussian distribution N(u_i | mu_i with *, [lambda_i with *]^-1) =
    //                        = mu_i with * + s * [U]^-1,
    //                        where
    //                              s is a random vector with N(0, I),
    //                              mu_i with * is a vector num_latent x 1,
    //                              mu_i with * = [lambda_i with *]^-1 * rr,
    //                              lambda_i with * = L * U

    // Expression u_i = U \ (s + (L \ rr)) in Matlab looks for Eigen library like:

    chol.matrixL().solveInPlace(rr);                    // L*Y=rr => Y=L\rr, we store Y result again in rr vector
    rr += nrandn();                                     // rr=s+(L\rr), we store result again in rr vector
    chol.matrixU().solveInPlace(rr);                    // u_i=U\rr
    items().col(idx) = rr;                              // we save rr vector in items matrix (it is user features matrix)

    auto stop = tick();
    register_time(idx, 1e6 * (stop - start));
    //Sys::cout() << "  " << count << ": " << 1e6*(stop - start) << std::endl;

    assert(rr.norm() > .0);

    return rr;
}

//
// update ALL movies / users in parallel
//
void Sys::sample(Sys &in)
{
    iter++;
    VectorNd  sum(VectorNd::Zero()); // sum
    double    norm(0.0); // squared norm
    MatrixNNd prod(MatrixNNd::Zero()); // outer prod

//#pragma omp parallel for reduction(VectorPlus:sum) reduction(MatrixPlus:prod) reduction(+:norm) schedule(dynamic, 1)
#pragma omp parallel for reduction(VectorPlus:sum) reduction(MatrixPlus:prod) reduction(+:norm) schedule(dynamic,1)
    for(int i = from(); i<to(); ++i) {
        auto r = sample(i,in.items());

        MatrixNNd cov = (r * r.transpose());
        prod += cov;
        sum += r;
        norm += r.squaredNorm();

        if (iter >= burnin)
        {
            aggrMu.col(i) += r;
            aggrLambda.col(i) += Eigen::Map<Eigen::VectorXd>(cov.data(), num_latent * num_latent);
        }

        send_items(i, i + 1);
    }

    const int N = num();
    local_sum() = sum;
    local_cov() = (prod - (sum * sum.transpose() / N)) / (N-1);
    local_norm() = norm;

}

void Sys::register_time(int i, double t)
{
    if (measure_perf) sample_time.at(i) += t;
}

void calc_upper_part(MatrixNNd &m, VectorNd v)
{
  // we use the formula: m = m + v * v.transpose(), but we calculate only an upper part of m matrix
  for (int j=0; j<num_latent; j++)          // columns
  {
    for(int i=0; i<=j; i++)              // rows
    {
      m(i,j) = m(i,j) + v[j] * v[i];
    }
  }
}

void copy_lower_part(MatrixNNd &m)
{
  // Here, we copy a triangular upper part to a triangular lower part, because the matrix is symmetric.
  for (int j=1; j<num_latent; j++)          // columns
  {
    for(int i=0; i<=j-1; i++)            // rows
    {
      m(j,i) = m(i,j);
    }
  }
}
<commit_msg>FIX: check that A and B have same structure<commit_after>/*
 * Copyright (c) 2014-2016, imec
 * All rights reserved.
 */

#include "error.h"
#include "bpmf.h"

#include <random>
#include <memory>
#include <cstdio>
#include <iostream>
#include <climits>
#include <stdexcept>

#include "io.h"

#if defined(_OPENMP)
#include "omp.h"

#pragma omp declare reduction (VectorPlus : VectorNd : omp_out += omp_in) initializer(omp_priv = VectorNd::Zero())
#pragma omp declare reduction (MatrixPlus : MatrixNNd : omp_out += omp_in) initializer(omp_priv = MatrixNNd::Zero())
#endif

static const bool measure_perf = false;

std::ostream *Sys::os;
int Sys::procid = -1;
int Sys::nprocs = -1;

int Sys::nsims;
int Sys::burnin;
double Sys::alpha;

bool Sys::permute = true;

bool Sys::verbose = false;

unsigned Sys::grain_size;

void calc_upper_part(MatrixNNd &m, VectorNd v);         // function for calcutation of an upper part of a symmetric matrix: m = v * v.transpose();
void copy_lower_part(MatrixNNd &m);                     // function to copy an upper part of a symmetric matrix to a lower part

// verifies that A has the same non-zero structure as B
void assert_same_struct(SparseMatrixD &A, SparseMatrixD &B)
{
    assert(A.cols() == B.cols());
    assert(A.rows() == B.rows());
    for(int i=0; i<A.cols(); ++i) assert(A.col(i).nonZeros() == B.col(i).nonZeros());
}

//
// Does predictions for prediction matrix T
// Computes RMSE (Root Means Square Error)
//
void Sys::predict(Sys& other, bool all)
{
    int n = (iter < burnin) ? 0 : (iter - burnin);

    double se(0.0); // squared err
    double se_avg(0.0); // squared avg err
    unsigned nump(0); // number of predictions

    int lo = all ? 0 : from();
    int hi = all ? num() : to();
    #pragma omp parallel for reduction(+:se,se_avg,nump)
    for(int k = lo; k<hi; k++) {
        for (Eigen::SparseMatrix<double>::InnerIterator it(T,k); it; ++it)
        {
            auto m = items().col(it.col());
            auto u = other.items().col(it.row());

            assert(m.norm() > 0.0);
            assert(u.norm() > 0.0);

            const double pred = m.dot(u) + mean_rating;
            se += sqr(it.value() - pred);

            // update average prediction
            double &avg = Pavg.coeffRef(it.row(), it.col());
            double delta = pred - avg;
            avg = (n == 0) ? pred : (avg + delta/n);
            double &m2 = Pm2.coeffRef(it.row(), it.col());
            m2 = (n == 0) ? 0 : m2 + delta * (pred - avg);
            se_avg += sqr(it.value() - avg);

            nump++;
        }
    }

    rmse = sqrt( se / nump );
    rmse_avg = sqrt( se_avg / nump );
}

//
// Prints sampling progress
//
void Sys::print(double items_per_sec, double ratings_per_sec, double norm_u, double norm_m) {
  char buf[1024];
  std::string phase = (iter < Sys::burnin) ? "Burnin" : "Sampling";
  sprintf(buf, "%d: %s iteration %d:\t RMSE: %3.4f\tavg RMSE: %3.4f\tFU(%6.2f)\tFM(%6.2f)\titems/sec: %6.2f\tratings/sec: %6.2fM\n",
                    Sys::procid, phase.c_str(), iter, rmse, rmse_avg, norm_u, norm_m, items_per_sec, ratings_per_sec / 1e6);
  Sys::cout() << buf;
}

//
// Constructor with that reads MTX files
//
Sys::Sys(std::string name, std::string fname, std::string probename)
    : name(name), iter(-1), assigned(false), dom(nprocs+1)
{

    read_matrix(fname, M);
    read_matrix(probename, T);

    auto rows = std::max(M.rows(), T.rows());
    auto cols = std::max(M.cols(), T.cols());
    M.conservativeResize(rows,cols);
    T.conservativeResize(rows,cols);
    Pm2 = Pavg = Torig = T; // reference ratings and predicted ratings
    assert(M.rows() == Pavg.rows());
    assert(M.cols() == Pavg.cols());
    assert(Sys::nprocs <= (int)Sys::max_procs);
}

//
// Constructs Sys as transpose of existing Sys
//
Sys::Sys(std::string name, const SparseMatrixD &Mt, const SparseMatrixD &Pt) : name(name), iter(-1), assigned(false), dom(nprocs+1) {
    M = Mt.transpose();
    Pm2 = Pavg = T = Torig = Pt.transpose(); // reference ratings and predicted ratings
    assert(M.rows() == Pavg.rows());
    assert(M.cols() == Pavg.cols());
}

Sys::~Sys()
{
    if (measure_perf) {
        Sys::cout() << " --------------------\n";
        Sys::cout() << name << ": sampling times on " << procid << "\n";
        for(int i = from(); i<to(); ++i)
        {
            Sys::cout() << "\t" << nnz(i) << "\t" << sample_time.at(i) / nsims  << "\n";
        }
        Sys::cout() << " --------------------\n\n";
    }
}

bool Sys::has_prop_posterior() const
{
    return propMu.nonZeros() > 0;
}

void Sys::add_prop_posterior(std::string fnames)
{
    if (fnames.empty()) return;

    std::size_t pos = fnames.find_first_of(",");
    std::string mu_name = fnames.substr(0, pos);
    std::string lambda_name = fnames.substr(pos+1);

    read_matrix(mu_name, propMu);
    read_matrix(lambda_name, propLambda);

    assert(propMu.cols() == num());
    assert(propLambda.cols() == num());

    assert(propMu.rows() == num_latent);
    assert(propLambda.rows() == num_latent * num_latent);

}

//
// Intializes internal Matrices and Vectors
//
void Sys::init()
{
    //-- M
    assert(M.rows() > 0 && M.cols() > 0);
    mean_rating = M.sum() / M.nonZeros();
    items().setZero();
    sum_map().setZero();
    cov_map().setZero();
    norm_map().setZero();
    col_permutation.setIdentity(num());

    aggrMu = Eigen::MatrixXd::Zero(num_latent, num());
    aggrLambda = Eigen::MatrixXd::Zero(num_latent * num_latent, num());

    Sys::cout() << "mean rating = " << mean_rating << std::endl;
    Sys::cout() << "total number of ratings in train = " << M.nonZeros() << std::endl;
    Sys::cout() << "total number of ratings in test = " << T.nonZeros() << std::endl;
    Sys::cout() << "num " << name << ": " << num() << std::endl;
    if (has_prop_posterior())
    {
        Sys::cout() << "with propagated posterior" << std::endl;
    }

    if (measure_perf) sample_time.resize(num(), .0);
}

class PrecomputedLLT : public Eigen::LLT<MatrixNNd>
{
  public:
    void operator=(const MatrixNNd &m) { m_matrix = m; m_isInitialized = true; m_info = Eigen::Success; }
};

//
// Update ONE movie or one user
//
VectorNd Sys::sample(long idx, const MapNXd in)
{
    auto start = tick();

    VectorNd hp_mu;
    MatrixNNd hp_LambdaF;
    MatrixNNd hp_LambdaL;
    if (has_prop_posterior())
    {
        hp_mu = propMu.col(idx);
        hp_LambdaF = Eigen::Map<MatrixNNd>(propLambda.col(idx).data());
        hp_LambdaL =  hp_LambdaF.llt().matrixL();
    }
    else
    {
        hp_mu = hp.mu;
        hp_LambdaF = hp.LambdaF;
        hp_LambdaL = hp.LambdaL;
    }

    int breakpoint1 = 24;
    int breakpoint2 = 10500;

    const int count = M.innerVector(idx).nonZeros(); // count of nonzeros elements in idx-th row of M matrix
                                                     // (how many movies watched idx-th user?).

    VectorNd rr = hp_LambdaF * hp.mu;                 // vector num_latent x 1, we will use it in formula (14) from the paper
    PrecomputedLLT chol;                             // matrix num_latent x num_latent, chol="lambda_i with *" from formula (14)

    // if this user movie has less than 1K ratings,
    // we do a serial rank update
    if( count < breakpoint1 ) {

        chol = hp_LambdaL;
        for (SparseMatrixD::InnerIterator it(M,idx); it; ++it) {
            auto col = in.col(it.row());
            chol.rankUpdate(col, alpha);
            rr.noalias() += col * ((it.value() - mean_rating) * alpha);
        }

    // else we do a serial full cholesky decomposition
    // (not used if breakpoint1 == breakpoint2)
    } else if (count < breakpoint2) {

        MatrixNNd MM(MatrixNNd::Zero());
        for (SparseMatrixD::InnerIterator it(M,idx); it; ++it) {
            auto col = in.col(it.row());

            //MM.noalias() += col * col.transpose();
            calc_upper_part(MM, col);

            rr.noalias() += col * ((it.value() - mean_rating) * alpha);
        }

        // Here, we copy a triangular upper part to a triangular lower part, because the matrix is symmetric.
        copy_lower_part(MM);

        chol.compute(hp_LambdaF + alpha * MM);
    // for > 1K ratings, we have additional thread-level parallellism
    } else {
        auto from = M.outerIndexPtr()[idx];   // "from" belongs to [1..m], m - number of movies in M matrix
        auto to = M.outerIndexPtr()[idx+1];   // "to"   belongs to [1..m], m - number of movies in M matrix
        MatrixNNd MM(MatrixNNd::Zero());               // matrix num_latent x num_latent

        // #pragma omp parallel for reduction(VectorPlus:rr) reduction(MatrixPlus:MM)
        #pragma omp parallel for reduction(VectorPlus:rr) reduction(MatrixPlus:MM) schedule(dynamic,200)
        for(int j = from; j<to; ++j) {                 // for each nonzeros elemen in the i-th row of M matrix
            auto val = M.valuePtr()[j];                // value of the j-th nonzeros element from idx-th row of M matrix
            auto idx = M.innerIndexPtr()[j];           // index "j" of the element [i,j] from M matrix in compressed M matrix
            auto col = in.col(idx);                    // vector num_latent x 1 from V matrix: M[i,j] = U[i,:] x V[idx,:]

            //MM.noalias() += col * col.transpose();     // outer product
            calc_upper_part(MM, col);
            rr.noalias() += col * ((val - mean_rating) * alpha); // vector num_latent x 1
        }

        copy_lower_part(MM);

        chol.compute(hp_LambdaF + alpha * MM);         // matrix num_latent x num_latent
                                                       // chol="lambda_i with *" from formula (14)
                                                       // lambda_i with * = LambdaU + alpha * MM
    }

    if(chol.info() != Eigen::Success) THROWERROR("Cholesky failed");

    // now we should calculate formula (14) from the paper
    // u_i for k-th iteration = Gaussian distribution N(u_i | mu_i with *, [lambda_i with *]^-1) =
    //                        = mu_i with * + s * [U]^-1,
    //                        where
    //                              s is a random vector with N(0, I),
    //                              mu_i with * is a vector num_latent x 1,
    //                              mu_i with * = [lambda_i with *]^-1 * rr,
    //                              lambda_i with * = L * U

    // Expression u_i = U \ (s + (L \ rr)) in Matlab looks for Eigen library like:

    chol.matrixL().solveInPlace(rr);                    // L*Y=rr => Y=L\rr, we store Y result again in rr vector
    rr += nrandn();                                     // rr=s+(L\rr), we store result again in rr vector
    chol.matrixU().solveInPlace(rr);                    // u_i=U\rr
    items().col(idx) = rr;                              // we save rr vector in items matrix (it is user features matrix)

    auto stop = tick();
    register_time(idx, 1e6 * (stop - start));
    //Sys::cout() << "  " << count << ": " << 1e6*(stop - start) << std::endl;

    assert(rr.norm() > .0);

    return rr;
}

//
// update ALL movies / users in parallel
//
void Sys::sample(Sys &in)
{
    iter++;
    VectorNd  sum(VectorNd::Zero()); // sum
    double    norm(0.0); // squared norm
    MatrixNNd prod(MatrixNNd::Zero()); // outer prod

//#pragma omp parallel for reduction(VectorPlus:sum) reduction(MatrixPlus:prod) reduction(+:norm) schedule(dynamic, 1)
#pragma omp parallel for reduction(VectorPlus:sum) reduction(MatrixPlus:prod) reduction(+:norm) schedule(dynamic,1)
    for(int i = from(); i<to(); ++i) {
        auto r = sample(i,in.items());

        MatrixNNd cov = (r * r.transpose());
        prod += cov;
        sum += r;
        norm += r.squaredNorm();

        if (iter >= burnin)
        {
            aggrMu.col(i) += r;
            aggrLambda.col(i) += Eigen::Map<Eigen::VectorXd>(cov.data(), num_latent * num_latent);
        }

        send_items(i, i + 1);
    }

    const int N = num();
    local_sum() = sum;
    local_cov() = (prod - (sum * sum.transpose() / N)) / (N-1);
    local_norm() = norm;

}

void Sys::register_time(int i, double t)
{
    if (measure_perf) sample_time.at(i) += t;
}

void calc_upper_part(MatrixNNd &m, VectorNd v)
{
  // we use the formula: m = m + v * v.transpose(), but we calculate only an upper part of m matrix
  for (int j=0; j<num_latent; j++)          // columns
  {
    for(int i=0; i<=j; i++)              // rows
    {
      m(i,j) = m(i,j) + v[j] * v[i];
    }
  }
}

void copy_lower_part(MatrixNNd &m)
{
  // Here, we copy a triangular upper part to a triangular lower part, because the matrix is symmetric.
  for (int j=1; j<num_latent; j++)          // columns
  {
    for(int i=0; i<=j-1; i++)            // rows
    {
      m(j,i) = m(i,j);
    }
  }
}
<|endoftext|>