// This may look like C code, but it is really -*- C++ -*-
// RTSS --- Railway Total System Simulator
// (c) TAKAGI Ryo (at Kogakuin University)
// gradcrv.cc --- functions for class gradcrv
// -----
// ChangeLog:
// 2007. 11. 21
//  Redirected log messages to l_file.
// -----

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <iostream>

#include "nextsta.hh"
#include "StrPrintf.hh"

using std :: cerr ;
using std :: endl ;



//#define DEBUG



// 代入演算子の overload
gradcrv &
gradcrv :: operator=
( const gradcrv & x )
{
  if ( & x == this )
    return * this ;
  _GCV_Container :: substitute ( x ) ;
  return * this ;
}




// gcvel の追加
gradcrv &
gradcrv :: operator+=
( gcvel const & x )
{
  if ( gc_size () > 0 )
  {
    if ( getElement ( gc_size () - 1 ) . endp != x . stp )
    {
      cerr << "Error: gcvel data not continuous in a gradcrv object" << endl ;
      cerr << " endp: " << getElement ( gc_size () - 1 ) . endp
           << ", stp: " << x . stp << ", gc_size: "
           << gc_size () << endl ;
      exit ( 31 ) ;	// gcvel データ不連続エラー
    }
  }
  if ( x . stp > x . endp )
  {
    cerr << "Error: gcvel data not correct" << endl ;
    exit ( 32 ) ;   // gcvel データ不連続エラー
  }
  gc_push_back ( x ) ;
  return * this ;
}




// gcvel データ書替え
gradcrv &
gradcrv :: renewpos
( int sw ,
  double zpost )
{
  //**********************************************************
  // 返り値が参照でないためこの関数は operator[] を使うとダメ
  //**********************************************************
  double sgn ;
  static gcvel * gxxold = 0 ;
  static int gxoldm = 0 ;
  if ( sw < 0 )
  {
    // このときは gcvel を逆順に並べ替える
    static _GCV_Container gxold ;
    gxold . gc_renew () ;
    for ( gc_size_type i = 0 ; i < gc_size () ; ++ i )
    {
      gxold . gc_push_back ( getElement ( i ) ) ;
    }
    for ( gc_size_type i = 0 ; i < gc_size () ; ++ i )
    {
      getElement ( i ) = gxold . getElement ( gc_size () - i ) ;
      double tmp = getElement ( i ) . stp ;
      getElement ( i ) . stp = getElement ( i ) . endp ;
      getElement ( i ) . endp = tmp ;
    }
    sgn = - 1 ;
  }
  else
    sgn = 1 ;
  for ( gc_size_type i = 0 ; i < gc_size () ; ++ i )
  {
    // zpost 起点の距離に
    getElement ( i ) . stp -= zpost ;
    getElement ( i ) . endp -= zpost ;
    getElement ( i ) . stp *= sgn ;
    getElement ( i ) . endp *= sgn ;
  }
  return * this ;
}




// 二つの gradcrv を連結
gradcrv &
operator+
( gradcrv & a ,
  gradcrv & b )
{
  static gradcrv x , y , z ;
  if ( a . gc_size () > 0 )
  {
    if ( a . getElement( a . gc_size () - 1 ) . endp
         != b . getElement ( 0 ) . stp )
    {
      cerr << "Error: gcvel data not continuous" << endl ;
      exit ( 32 ) ;	// データ不連続エラー
    }

    // メモリコピー
    x = a ;
    y = b ;
    z . gc_renew ( x . gc_size () + y . gc_size () ) ;
    z = x ;
    for ( gradcrv :: gc_size_type i = 0 ; i < y . gc_size () ; ++ i )
      z += y . getElement ( i ) ;
  }
  else
    z = b ;
  return z ;
}




// ファイルリード
int
gradcrv :: readfile
( FILE * gpoint )
{
  if ( getcommand ( gpoint , false ) == EOF )
    return EOF ;
  if ( strcmp ( tmpch , "gcvel" ) != 0 )
    return EOF ;
  int sia ;
  if ( getint ( gpoint , sia ) == EOF )
    return EOF ;
  l_ofs << StrPrintf ( "gradcrv: %i gcvel data" , sia ) << endl ;
  gc_renew ( sia ) ;
  gcvel gv ;
  for ( int j = 0 ; j < sia ; ++ j )
  {
    if ( gettwodbls ( gpoint , gv . stp , gv . endp ) == EOF )
      return EOF ;
    if ( getthreedbls ( gpoint , gv . grad , gv . curve , gv . vlimit )
	 == EOF )
      return EOF ;
    l_ofs << StrPrintf ( "%.3f %.3f %.1f %.1f %.1f" ,
	      gv . stp , gv . endp , gv . grad , gv . curve , gv . vlimit )
          << endl ;
    operator+= ( gv ) ;
  }
  return 1 ;
}
