// This may look like C code, but it is really -*- C++ -*-
// RTSS --- Railway Total System Simulator
// (c) TAKAGI Ryo (at Prof. SONE's Laboratory, the Univ. of Tokyo.)
// feedline.cc --- class feedline functions
// $Id: feedline.cc,v 2.4 1994/12/27 12:03:47 rt Exp $

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

#include "feedline.hh"

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


int sortfeed ( const void * , const void * ) ;



// empty constructor
feedline :: feedline
()
  : fdx ()
{
  css = 0 ;
  nfline = maxcss = ssc = car = 0 ;	// 饋電線番号もとりあえずゼロ
}



// 代入禁止
feedline &
feedline :: operator=
( const feedline & x )
{
  cerr << "Error: a class feedline object must not be" << endl
       << "	 replaced by another class feedline object" << endl ;
  exit ( 10 ) ;		// error 10: オブジェクト初期化／代入禁止エラー
  return * this ;	// -Wall warning を避けるため
}



// 初期化禁止
feedline :: feedline
( const feedline & x )
{
  cerr << "Error: a class feedline object must not be" << endl
       << "	 initialized by another class feedline object" << endl ;
  exit ( 10 ) ;	    // error 10: オブジェクト初期化／代入禁止エラー
}



// 要素(列車分)を加える
feedline &
feedline :: operator+=
( feedpos & x )
{
  ++ car ;
  if ( ssc + car > maxcss )
  {
    static feedpos * cssold = 0 ;
    static int csoldm = 0 ;
    if ( csoldm < maxcss )
    {
      delete cssold ;
      cssold = new feedpos [ csoldm = maxcss ] ;
    }
    for ( int i = 0 ; i < maxcss ; ++ i )
      cssold [ i ] = css [ i ] ;
    delete css ;
    css = new feedpos [ maxcss = ssc + car ] ;
    for ( int i = 0 ; i < maxcss - 1 ; ++ i )
      css [ i ] = cssold [ i ] ;
  }
  css [ ssc + car - 1 ] = x ;
  return * this ;
}



// 要素(変電所分)を加える
feedline &
feedline :: operator*=
( feedpos & x )
{
  if ( ssc + car + 1 > maxcss )
  {
    static feedpos * cssold = 0 ;
    static int csoldm = 0 ;
    if ( csoldm < maxcss )
    {
      delete cssold ;
      cssold = new feedpos [ csoldm = maxcss ] ;
    }
    for ( int i = 0 ; i < maxcss ; ++ i )
      cssold [ i ] = css [ i ] ;
    delete css ;
    css = new feedpos [ ( maxcss = ssc + car + 1 ) ] ;
    for ( int i = 0 ; i < maxcss - 1 ; ++ i )
      css [ i < ssc ? i : i + 1 ] = cssold [ i ] ;
  }
  else
  {
    for ( int i = ssc + car ; i > ssc ; -- i )
      css [ i ] = css [ i - 1 ] ;
  }
  ++ ssc ;
  css [ ssc - 1 ] = x ;
  return * this ;
}




// 距離ソート、ブランチを決定: 引数なし
feed_y &
feedline :: sortx
()
{
  bran_node x ;
  //    static int y = 0 ;
  static feedpos * cssort = new feedpos [ ssc + car ] ;
  static int cssortm = ssc + car ;
  if ( cssortm < ssc + car )
  {
    delete cssort ;
    cssort = new feedpos [ ( cssortm = ssc + car ) ] ;
  }
  fdx . renew () ;
  for ( int i = 0 ; i < ssc + car ; ++ i )
    cssort [ i ] = css [ i ] ;
  qsort ( cssort , ( ssc + car ) , sizeof ( feedpos ) , & sortfeed ) ;

  for ( int i = 0 ; i < ssc + car - 1 ; ++ i )
    impcal ( i , i + 1 , cssort , x , fdx ) ;
  if ( shape == Circle )
    impcal ( ssc + car - 1 , 0 , cssort , x , fdx ) ;
  return fdx ;
}




// sortx 用ソートプログラム
int sortfeed
( const void * ax ,
  const void * bx )
{
  feedpos * a = ( feedpos * ) ax ;
  feedpos * b = ( feedpos * ) bx ;
  if ( a -> pos > b -> pos ) return 1 ;
  else if ( a -> pos < b -> pos ) return -1 ;
  else return 0 ;
}




// ssc , car を変更する
void
feedline :: renewssc
( int ss )
{
  if ( ss > maxcss )
  {
    maxcss = ss ;
    delete css ;
    css = new feedpos [ maxcss ] ;
  }
  ssc = car = 0 ;
}




// sortx 用 subprogram
void
feedline :: impcal
( int i ,
  int j ,
  feedpos * cssort ,
  bran_node & x ,
  feed_y & fy )
{
  x . nfline = nfline ;
  x . startnode = cssort [ i ] . csno ;
  x . startpos = cssort [ i ] . pos ;
  x . endnode = cssort [ j ] . csno ;
  x . endpos = cssort [ j ] . pos ;
  x . impedance = cssort [ j ] . pos - cssort [ i ] . pos ;
  if ( x . impedance < - NODELIM )
    x . impedance += feedlength ;
  if ( x . impedance < NODELIM )
    x . impedance = NODELIM ;
  x . impedance *= frf ;
  x . impedance += cssort [ i ] . endimp ;
  x . impedance += cssort [ j ] . sttimp ;

  // ----
  // Exceptional circumstance: if startnode and endnode coincide, stop.
  // ----
//   if ( x . startnode == x . endnode )
//   {
//     l_ofs << "Error: in impcal, startnode = endnode = " << x . startnode
//           << endl ;
//     cerr << "Error: loop branch found at node " << x . startnode
//          << ", add dummy substation" << endl ;
//     exit ( 1 ) ;
//   }

  fy += x ;
#ifdef DEBUG
  l_ofs << "added an element to feed_y object" << endl ;
  l_ofs << StrPrintf ( "stt, end, imp(stt end) = %i %i %.6f %.6f %.6f" ,
                       x . startnode , x . endnode , x . impedance ,
                       cssort [ i + 1 ] . sttimp , cssort [ i ] . endimp )
        << endl ;
  l_ofs << StrPrintf ( "after impcal" ) << endl ;
#endif
}
