<commit_before>/******************************************************************************
* Copyright (c) 2011, Michael P. Gerlek (mpg@flaxen.com)
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following
* conditions are met:
*
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in
*       the documentation and/or other materials provided
*       with the distribution.
*     * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the
*       names of its contributors may be used to endorse or promote
*       products derived from this software without specific prior
*       written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
****************************************************************************/

#define BOOST_TEST_MODULE Main
#include <boost/test/unit_test.hpp>

#include "TestConfig.hpp"

BOOST_GLOBAL_FIXTURE(TestConfig)

// Testing macros:
//   BOOST_TEST_MESSAGE("...")
//   BOOST_CHECK(bool)

// for comparing to floating point values, use
//   BOOST_CHECK_CLOSE(a,b,perc)
// where perc is a percentage value in the range [0..100] (typically)

//
// You can run the unit tests with these interesting options:
//
//     --log_format=X (-f X)   # X = xml|hrf
//     --log_level=X (-l X)    # X = error|message|all|... (default=error)
//     --log_sink=X (-k X)     # X = filename
//
//     --report_format=X (-o X)
//     --report_level=X (-r X)
//     --report_sink=X (-e X)
//
//     --detect_memory_leaks=X # X = 0|1  (default=1)
//
//     <path>                  # path to data (default=../test/data)

<commit_msg>added comment about comparators<commit_after>/******************************************************************************
* Copyright (c) 2011, Michael P. Gerlek (mpg@flaxen.com)
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following
* conditions are met:
*
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in
*       the documentation and/or other materials provided
*       with the distribution.
*     * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the
*       names of its contributors may be used to endorse or promote
*       products derived from this software without specific prior
*       written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
****************************************************************************/

#define BOOST_TEST_MODULE Main
#include <boost/test/unit_test.hpp>

#include "TestConfig.hpp"

BOOST_GLOBAL_FIXTURE(TestConfig)

// Testing macros:
//   BOOST_TEST_MESSAGE("...")
//   BOOST_CHECK(bool)
//   BOOST_CHECK_EQUAL(t1, t2)
//
// The 'CHECK_EQUAL function is preferred to plain 'CHECK, because the former
// prints out the values of both arguments in the error message.
//
// For comparing to floating point values, use
//   BOOST_CHECK_CLOSE(a,b,perc)
// where perc is a percentage value in the range [0..100] (typically)

//
// You can run the unit tests with these interesting options:
//
//     --log_format=X (-f X)   # X = xml|hrf
//     --log_level=X (-l X)    # X = error|message|all|... (default=error)
//     --log_sink=X (-k X)     # X = filename
//
//     --report_format=X (-o X)
//     --report_level=X (-r X)
//     --report_sink=X (-e X)
//
//     --detect_memory_leaks=X # X = 0|1  (default=1)
//
//     <path>                  # path to data (default=../test/data)

<|endoftext|>


<commit_before>/*
  Copyright (c) 1999 - 2007 Simon Peter <dn.tlp@gmx.net>
  Copyright (c) 2002 Nikita V. Kalaganov <riven@ok.ru>

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

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

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "plugin.h"

#define MSGA_WINAMP	"You must now restart Winamp after switching from hardware OPL2 or Disk Writer to Emulator output mode."
#define MSGC_DISK 	"You have selected *full speed* and *endless* Disk Writing modes. This combination of options is not recommended."
#define MSGC_DATABASE	"An external Database could not be loaded!"
#define MSGE_OPL2 	"An OPL2 chip is not being detected at the given Port address. An emulator must be used for output, instead."
#define MSGE_WINNT	"Hardware OPL2 output is not allowed natively under Windows NT/2000/XP. However, there is a way to work-around the issue. Please refer to the documentation for a solution that has been tested to work with AdPlug. For now, an emulator must be used for output, instead."
#define MSGE_XMPLAY	"Hardware OPL2 output is not supported when this plugin is used within XMPlay. An emulator must be used for output, instead."

#define DFL_EMU			emuts
#define DFL_REPLAYFREQ		44100

#ifdef HAVE_ADPLUG_SURROUND
#define DFL_HARMONIC		true
#define DFL_DUELSYNTH		true
#endif

#define DFL_USE16BIT		true
#define DFL_STEREO		true
#define DFL_USEOUTPUT		DFL_EMU
#define DFL_ADLIBPORT		0x388
#define DFL_TESTOPL2		true
#define DFL_TESTLOOP		true
#define DFL_FASTSEEK		false
#define DFL_PRIORITY		4
#define DFL_STDTIMER		true
#define DFL_DISKDIR		"C:\\"
#define DFL_IGNORED		"19;"
#define DFL_DBFILE		"adplug.db"
#define DFL_USEDB		true
#define DFL_S3M_WORKAROUND	true

CAdPlugDatabase *Config::mydb = 0;

Config::Config()
{
  useoutputplug = true;
}

void Config::load()
{
  char bufstr[MAX_PATH+1], dbfile[MAX_PATH];

  // get default path to .ini file
  GetModuleFileName(NULL,bufstr,MAX_PATH);

  _strlwr(strrchr(bufstr,'\\'));

  fname.assign(bufstr);
  fname.resize(fname.size() - 3);
  fname.append("ini");

  // load configuration from .ini file
  int bufval;

  bufval = GetPrivateProfileInt("in_adlib","replayfreq",DFL_REPLAYFREQ,fname.c_str());
  if (bufval != -1)
    next.replayfreq = bufval;

  #ifdef HAVE_ADPLUG_SURROUND
  bufval = GetPrivateProfileInt("in_adlib","harmonic",DFL_HARMONIC,fname.c_str());
  if (bufval != -1)
    next.harmonic = bufval ? true : false;

  bufval = GetPrivateProfileInt("in_adlib","duelsynth",DFL_DUELSYNTH,fname.c_str());
  if (bufval != -1)
    next.duelsynth = bufval ? true : false;
  #endif

  bufval = GetPrivateProfileInt("in_adlib","use16bit",DFL_USE16BIT,fname.c_str());
  if (bufval != -1)
    next.use16bit = bufval ? true : false;

  bufval = GetPrivateProfileInt("in_adlib","stereo",DFL_STEREO,fname.c_str());
  if (bufval != -1)
    next.stereo = bufval ? true : false;

  bufval = GetPrivateProfileInt("in_adlib","useoutput",DFL_USEOUTPUT,fname.c_str());
  if (bufval != -1)
    next.useoutput = (enum t_output)bufval;

  GetPrivateProfileString("in_adlib","adlibport","0",bufstr,5,fname.c_str());
  if (strcmp(bufstr,"0"))
    sscanf(bufstr,"%hx",&next.adlibport);
  else
    next.adlibport = DFL_ADLIBPORT;

  bufval = GetPrivateProfileInt("in_adlib","testopl2",DFL_TESTOPL2,fname.c_str());
  if (bufval != -1)
    next.testopl2 = bufval ? true : false;

  GetPrivateProfileString("in_adlib","diskdir",DFL_DISKDIR,bufstr,MAX_PATH,fname.c_str());
  if (SetCurrentDirectory(bufstr))
    next.diskdir = bufstr;
  else
    next.diskdir = DFL_DISKDIR;

  bufval = GetPrivateProfileInt("in_adlib","testloop",DFL_TESTLOOP,fname.c_str());
  if (bufval != -1)
    next.testloop = bufval ? true : false;

  bufval = GetPrivateProfileInt("in_adlib","fastseek",DFL_FASTSEEK,fname.c_str());
  if (bufval != -1)
    next.fastseek = bufval ? true : false;

  bufval = GetPrivateProfileInt("in_adlib","priority",DFL_PRIORITY,fname.c_str());
  if (bufval != -1)
    next.priority = bufval;

  bufval = GetPrivateProfileInt("in_adlib","stdtimer",DFL_STDTIMER,fname.c_str());
  if (bufval != -1)
    next.stdtimer = bufval ? true : false;

  GetPrivateProfileString("in_adlib","ignored",DFL_IGNORED,bufstr,MAX_PATH,fname.c_str());
  next.ignored = bufstr;

  // Build database default path (in winamp plugin directory)
  GetModuleFileName(GetModuleHandle("in_adlib"), dbfile, MAX_PATH);
  strcpy(strrchr(dbfile, '\\') + 1, DFL_DBFILE);

  GetPrivateProfileString("in_adlib","database",dbfile,bufstr,MAX_PATH,fname.c_str());
  next.db_file = bufstr;

  bufval = GetPrivateProfileInt("in_adlib","usedb",DFL_USEDB,fname.c_str());
  if (bufval != -1)
    next.usedb = bufval ? true : false;

  bufval = GetPrivateProfileInt("in_adlib","s3mworkaround",DFL_S3M_WORKAROUND,fname.c_str());
  if (bufval != -1) next.s3m_workaround = bufval ? true : false;

  apply(false);
}

void Config::save()
{
  char bufstr[11];

  WritePrivateProfileString("in_adlib","replayfreq",_itoa(next.replayfreq,bufstr,10),fname.c_str());

  #ifdef HAVE_ADPLUG_SURROUND
  WritePrivateProfileString("in_adlib","harmonic",_itoa(next.harmonic,bufstr,10),fname.c_str());

  WritePrivateProfileString("in_adlib","duelsynth",_itoa(next.duelsynth,bufstr,10),fname.c_str());
  #endif

  WritePrivateProfileString("in_adlib","use16bit",_itoa(next.use16bit,bufstr,10),fname.c_str());
  WritePrivateProfileString("in_adlib","stereo",_itoa(next.stereo,bufstr,10),fname.c_str());
  WritePrivateProfileString("in_adlib","useoutput",_itoa(next.useoutput,bufstr,10),fname.c_str());
  WritePrivateProfileString("in_adlib","adlibport",_itoa(next.adlibport,bufstr,16),fname.c_str());
  WritePrivateProfileString("in_adlib","testopl2",_itoa(next.testopl2,bufstr,10),fname.c_str());
  WritePrivateProfileString("in_adlib","testloop",_itoa(next.testloop,bufstr,10),fname.c_str());
  WritePrivateProfileString("in_adlib","fastseek",_itoa(next.fastseek,bufstr,10),fname.c_str());
  WritePrivateProfileString("in_adlib","priority",_itoa(next.priority,bufstr,10),fname.c_str());
  WritePrivateProfileString("in_adlib","stdtimer",_itoa(next.stdtimer,bufstr,10),fname.c_str());
  WritePrivateProfileString("in_adlib","diskdir",next.diskdir.c_str(),fname.c_str());
  WritePrivateProfileString("in_adlib","ignored",next.ignored.c_str(),fname.c_str());
  WritePrivateProfileString("in_adlib","database",next.db_file.c_str(),fname.c_str());
  WritePrivateProfileString("in_adlib","usedb",_itoa(next.usedb,bufstr,10),fname.c_str());
  WritePrivateProfileString("in_adlib","s3mworkaround",_itoa(next.s3m_workaround,bufstr,10),fname.c_str());
}

void Config::check()
{
  if ((next.useoutput == emuts) || (next.useoutput == emuks))
    next.useoutputplug = true;
  else
    next.useoutputplug = false;

  if (!next.useoutputplug)
    if (test_xmplay())
      {
	next.useoutput = DFL_EMU;
	next.useoutputplug = true;

	MessageBox(NULL,MSGE_XMPLAY,"AdPlug :: Error",MB_ICONERROR | MB_TASKMODAL);
      }

  if (next.useoutput == opl2)
    if (test_winnt())
      if (!test_porttalk())
	if (next.testopl2)
	  {
	    next.useoutput = DFL_EMU;
	    next.useoutputplug = true;

	    MessageBox(NULL,MSGE_WINNT,"AdPlug :: Error",MB_ICONERROR | MB_TASKMODAL);
	  }

  if (next.useoutput == opl2)
    if (next.testopl2)
      if (!test_opl2())
	{
	  next.useoutput = DFL_EMU;
	  next.useoutputplug = true;

	  MessageBox(NULL,MSGE_OPL2,"AdPlug :: Error",MB_ICONERROR | MB_TASKMODAL);
	}

  if (next.useoutput == disk)
    if (!next.stdtimer)
      if (!next.testloop)
	MessageBox(NULL,MSGC_DISK,"AdPlug :: Caution",MB_ICONWARNING | MB_TASKMODAL);

  if (next.useoutputplug > useoutputplug)
    MessageBox(NULL,MSGA_WINAMP,"AdPlug :: Attention",MB_ICONINFORMATION | MB_TASKMODAL);

  if (!use_database())
    MessageBox(NULL,MSGC_DATABASE,"AdPlug :: Caution",MB_ICONWARNING | MB_TASKMODAL);
}

void Config::apply(bool testout)
{
  check();

  work.replayfreq	= next.replayfreq;

  #ifdef HAVE_ADPLUG_SURROUND
  work.harmonic		= next.harmonic;
  work.duelsynth		= next.duelsynth;
  #endif

  work.use16bit		= next.use16bit;
  work.stereo		= next.stereo;
  work.adlibport	= next.adlibport;
  work.testopl2		= next.testopl2;
  work.testloop		= next.testloop;
  work.fastseek		= next.fastseek;
  work.priority		= next.priority;
  work.stdtimer		= next.stdtimer;
  work.diskdir		= next.diskdir;
  work.ignored		= next.ignored;
  work.db_file		= next.db_file;
  work.usedb		= next.usedb;
  work.s3m_workaround	= next.s3m_workaround;

  if (!testout || (next.useoutputplug <= useoutputplug))
    {
      work.useoutput = next.useoutput;
      useoutputplug  = next.useoutputplug;
    }
}

void Config::get(t_config_data *cfg)
{
  *cfg = work;
}

void Config::set(t_config_data *cfg)
{
  next = *cfg;

  apply(true);
}

const char *Config::get_ignored()
{
  return work.ignored.c_str();
}

void Config::set_ignored(const char *ignore_list)
{
  next.ignored = ignore_list;
}

bool Config::use_database()
{
  bool success = true;

  if(mydb) { delete mydb; mydb = 0; }
  if(next.usedb) {
    mydb = new CAdPlugDatabase;
    success = mydb->load(next.db_file);
  }
  CAdPlug::set_database(mydb);

  return success;
}

bool Config::test_opl2()
{
  CRealopl tmp(next.adlibport);

  return tmp.detect();
}

bool Config::test_winnt()
{
  OSVERSIONINFO ver;

  ver.dwOSVersionInfoSize = sizeof(ver);

  GetVersionEx(&ver);

  if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT)
    return true;

  return false;
}

bool Config::test_xmplay()
{
  return GetModuleHandle("xmplay.exe") ? true : false;
}

bool Config::test_porttalk()
  /* Enables I/O port permissions on Windows NT, using the PortTalk device driver.
   * Returns true on success. Returns false if PortTalk isn't installed.
   */
{
  DWORD BytesReturned, our_pid;
  HANDLE PortTalk_Driver;

  // Try to open PortTalk driver
  if((PortTalk_Driver = CreateFile("\\\\.\\PortTalk",GENERIC_READ,0,NULL,
				   OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL)) == INVALID_HANDLE_VALUE) {
    puts("porttalk_enable(): PortTalk not installed.");
    return false;
  }

  // Reset I/O permission map (deny all access)
  if(!DeviceIoControl(PortTalk_Driver,
		      CTL_CODE(40000, 0x900, METHOD_BUFFERED, FILE_ANY_ACCESS),
		      NULL,0,NULL,0,&BytesReturned,NULL)) {
    puts("porttalk_enable(): Error on resetting I/O permission map!");
    CloseHandle(PortTalk_Driver);
    return false;
  }

  // Set I/O permission map (exclusive access to all ports)
  if(!DeviceIoControl(PortTalk_Driver,
		      CTL_CODE(40000, 0x901, METHOD_BUFFERED, FILE_ANY_ACCESS),
		      NULL,0,NULL,0,&BytesReturned,NULL)) {
    puts("porttalk_enable(): Error on setting I/O permission map!");
    CloseHandle(PortTalk_Driver);
    return false;
  }

  // Enable I/O permissions on ourself
  our_pid = GetCurrentProcessId();
  printf("porttalk_enable(): Our process ID is %lu.\n",our_pid);
  if(!DeviceIoControl(PortTalk_Driver,
		      CTL_CODE(40000, 0x903, METHOD_BUFFERED, FILE_ANY_ACCESS),
		      &our_pid,4,NULL,0,&BytesReturned,NULL)) {
    puts("porttalk_enable(): Error on establishing I/O permissions on our process!");
    CloseHandle(PortTalk_Driver);
    return false;
  }

  CloseHandle(PortTalk_Driver);
  Sleep(1);	// Very important !! Wait for device driver to carry out our requests.
  return true;
}
<commit_msg>Disable NT version checks on VS2015+<commit_after>/*
  Copyright (c) 1999 - 2007 Simon Peter <dn.tlp@gmx.net>
  Copyright (c) 2002 Nikita V. Kalaganov <riven@ok.ru>

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

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

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "plugin.h"

#define MSGA_WINAMP	"You must now restart Winamp after switching from hardware OPL2 or Disk Writer to Emulator output mode."
#define MSGC_DISK 	"You have selected *full speed* and *endless* Disk Writing modes. This combination of options is not recommended."
#define MSGC_DATABASE	"An external Database could not be loaded!"
#define MSGE_OPL2 	"An OPL2 chip is not being detected at the given Port address. An emulator must be used for output, instead."
#define MSGE_WINNT	"Hardware OPL2 output is not allowed natively under Windows NT/2000/XP. However, there is a way to work-around the issue. Please refer to the documentation for a solution that has been tested to work with AdPlug. For now, an emulator must be used for output, instead."
#define MSGE_XMPLAY	"Hardware OPL2 output is not supported when this plugin is used within XMPlay. An emulator must be used for output, instead."

#define DFL_EMU			emuts
#define DFL_REPLAYFREQ		44100

#ifdef HAVE_ADPLUG_SURROUND
#define DFL_HARMONIC		true
#define DFL_DUELSYNTH		true
#endif

#define DFL_USE16BIT		true
#define DFL_STEREO		true
#define DFL_USEOUTPUT		DFL_EMU
#define DFL_ADLIBPORT		0x388
#define DFL_TESTOPL2		true
#define DFL_TESTLOOP		true
#define DFL_FASTSEEK		false
#define DFL_PRIORITY		4
#define DFL_STDTIMER		true
#define DFL_DISKDIR		"C:\\"
#define DFL_IGNORED		"19;"
#define DFL_DBFILE		"adplug.db"
#define DFL_USEDB		true
#define DFL_S3M_WORKAROUND	true

CAdPlugDatabase *Config::mydb = 0;

Config::Config()
{
  useoutputplug = true;
}

void Config::load()
{
  char bufstr[MAX_PATH+1], dbfile[MAX_PATH];

  // get default path to .ini file
  GetModuleFileName(NULL,bufstr,MAX_PATH);

  _strlwr(strrchr(bufstr,'\\'));

  fname.assign(bufstr);
  fname.resize(fname.size() - 3);
  fname.append("ini");

  // load configuration from .ini file
  int bufval;

  bufval = GetPrivateProfileInt("in_adlib","replayfreq",DFL_REPLAYFREQ,fname.c_str());
  if (bufval != -1)
    next.replayfreq = bufval;

  #ifdef HAVE_ADPLUG_SURROUND
  bufval = GetPrivateProfileInt("in_adlib","harmonic",DFL_HARMONIC,fname.c_str());
  if (bufval != -1)
    next.harmonic = bufval ? true : false;

  bufval = GetPrivateProfileInt("in_adlib","duelsynth",DFL_DUELSYNTH,fname.c_str());
  if (bufval != -1)
    next.duelsynth = bufval ? true : false;
  #endif

  bufval = GetPrivateProfileInt("in_adlib","use16bit",DFL_USE16BIT,fname.c_str());
  if (bufval != -1)
    next.use16bit = bufval ? true : false;

  bufval = GetPrivateProfileInt("in_adlib","stereo",DFL_STEREO,fname.c_str());
  if (bufval != -1)
    next.stereo = bufval ? true : false;

  bufval = GetPrivateProfileInt("in_adlib","useoutput",DFL_USEOUTPUT,fname.c_str());
  if (bufval != -1)
    next.useoutput = (enum t_output)bufval;

  GetPrivateProfileString("in_adlib","adlibport","0",bufstr,5,fname.c_str());
  if (strcmp(bufstr,"0"))
    sscanf(bufstr,"%hx",&next.adlibport);
  else
    next.adlibport = DFL_ADLIBPORT;

  bufval = GetPrivateProfileInt("in_adlib","testopl2",DFL_TESTOPL2,fname.c_str());
  if (bufval != -1)
    next.testopl2 = bufval ? true : false;

  GetPrivateProfileString("in_adlib","diskdir",DFL_DISKDIR,bufstr,MAX_PATH,fname.c_str());
  if (SetCurrentDirectory(bufstr))
    next.diskdir = bufstr;
  else
    next.diskdir = DFL_DISKDIR;

  bufval = GetPrivateProfileInt("in_adlib","testloop",DFL_TESTLOOP,fname.c_str());
  if (bufval != -1)
    next.testloop = bufval ? true : false;

  bufval = GetPrivateProfileInt("in_adlib","fastseek",DFL_FASTSEEK,fname.c_str());
  if (bufval != -1)
    next.fastseek = bufval ? true : false;

  bufval = GetPrivateProfileInt("in_adlib","priority",DFL_PRIORITY,fname.c_str());
  if (bufval != -1)
    next.priority = bufval;

  bufval = GetPrivateProfileInt("in_adlib","stdtimer",DFL_STDTIMER,fname.c_str());
  if (bufval != -1)
    next.stdtimer = bufval ? true : false;

  GetPrivateProfileString("in_adlib","ignored",DFL_IGNORED,bufstr,MAX_PATH,fname.c_str());
  next.ignored = bufstr;

  // Build database default path (in winamp plugin directory)
  GetModuleFileName(GetModuleHandle("in_adlib"), dbfile, MAX_PATH);
  strcpy(strrchr(dbfile, '\\') + 1, DFL_DBFILE);

  GetPrivateProfileString("in_adlib","database",dbfile,bufstr,MAX_PATH,fname.c_str());
  next.db_file = bufstr;

  bufval = GetPrivateProfileInt("in_adlib","usedb",DFL_USEDB,fname.c_str());
  if (bufval != -1)
    next.usedb = bufval ? true : false;

  bufval = GetPrivateProfileInt("in_adlib","s3mworkaround",DFL_S3M_WORKAROUND,fname.c_str());
  if (bufval != -1) next.s3m_workaround = bufval ? true : false;

  apply(false);
}

void Config::save()
{
  char bufstr[11];

  WritePrivateProfileString("in_adlib","replayfreq",_itoa(next.replayfreq,bufstr,10),fname.c_str());

  #ifdef HAVE_ADPLUG_SURROUND
  WritePrivateProfileString("in_adlib","harmonic",_itoa(next.harmonic,bufstr,10),fname.c_str());

  WritePrivateProfileString("in_adlib","duelsynth",_itoa(next.duelsynth,bufstr,10),fname.c_str());
  #endif

  WritePrivateProfileString("in_adlib","use16bit",_itoa(next.use16bit,bufstr,10),fname.c_str());
  WritePrivateProfileString("in_adlib","stereo",_itoa(next.stereo,bufstr,10),fname.c_str());
  WritePrivateProfileString("in_adlib","useoutput",_itoa(next.useoutput,bufstr,10),fname.c_str());
  WritePrivateProfileString("in_adlib","adlibport",_itoa(next.adlibport,bufstr,16),fname.c_str());
  WritePrivateProfileString("in_adlib","testopl2",_itoa(next.testopl2,bufstr,10),fname.c_str());
  WritePrivateProfileString("in_adlib","testloop",_itoa(next.testloop,bufstr,10),fname.c_str());
  WritePrivateProfileString("in_adlib","fastseek",_itoa(next.fastseek,bufstr,10),fname.c_str());
  WritePrivateProfileString("in_adlib","priority",_itoa(next.priority,bufstr,10),fname.c_str());
  WritePrivateProfileString("in_adlib","stdtimer",_itoa(next.stdtimer,bufstr,10),fname.c_str());
  WritePrivateProfileString("in_adlib","diskdir",next.diskdir.c_str(),fname.c_str());
  WritePrivateProfileString("in_adlib","ignored",next.ignored.c_str(),fname.c_str());
  WritePrivateProfileString("in_adlib","database",next.db_file.c_str(),fname.c_str());
  WritePrivateProfileString("in_adlib","usedb",_itoa(next.usedb,bufstr,10),fname.c_str());
  WritePrivateProfileString("in_adlib","s3mworkaround",_itoa(next.s3m_workaround,bufstr,10),fname.c_str());
}

void Config::check()
{
  if ((next.useoutput == emuts) || (next.useoutput == emuks))
    next.useoutputplug = true;
  else
    next.useoutputplug = false;

  if (!next.useoutputplug)
    if (test_xmplay())
      {
	next.useoutput = DFL_EMU;
	next.useoutputplug = true;

	MessageBox(NULL,MSGE_XMPLAY,"AdPlug :: Error",MB_ICONERROR | MB_TASKMODAL);
      }

  if (next.useoutput == opl2)
    if (test_winnt())
      if (!test_porttalk())
	if (next.testopl2)
	  {
	    next.useoutput = DFL_EMU;
	    next.useoutputplug = true;

	    MessageBox(NULL,MSGE_WINNT,"AdPlug :: Error",MB_ICONERROR | MB_TASKMODAL);
	  }

  if (next.useoutput == opl2)
    if (next.testopl2)
      if (!test_opl2())
	{
	  next.useoutput = DFL_EMU;
	  next.useoutputplug = true;

	  MessageBox(NULL,MSGE_OPL2,"AdPlug :: Error",MB_ICONERROR | MB_TASKMODAL);
	}

  if (next.useoutput == disk)
    if (!next.stdtimer)
      if (!next.testloop)
	MessageBox(NULL,MSGC_DISK,"AdPlug :: Caution",MB_ICONWARNING | MB_TASKMODAL);

  if (next.useoutputplug > useoutputplug)
    MessageBox(NULL,MSGA_WINAMP,"AdPlug :: Attention",MB_ICONINFORMATION | MB_TASKMODAL);

  if (!use_database())
    MessageBox(NULL,MSGC_DATABASE,"AdPlug :: Caution",MB_ICONWARNING | MB_TASKMODAL);
}

void Config::apply(bool testout)
{
  check();

  work.replayfreq	= next.replayfreq;

  #ifdef HAVE_ADPLUG_SURROUND
  work.harmonic		= next.harmonic;
  work.duelsynth		= next.duelsynth;
  #endif

  work.use16bit		= next.use16bit;
  work.stereo		= next.stereo;
  work.adlibport	= next.adlibport;
  work.testopl2		= next.testopl2;
  work.testloop		= next.testloop;
  work.fastseek		= next.fastseek;
  work.priority		= next.priority;
  work.stdtimer		= next.stdtimer;
  work.diskdir		= next.diskdir;
  work.ignored		= next.ignored;
  work.db_file		= next.db_file;
  work.usedb		= next.usedb;
  work.s3m_workaround	= next.s3m_workaround;

  if (!testout || (next.useoutputplug <= useoutputplug))
    {
      work.useoutput = next.useoutput;
      useoutputplug  = next.useoutputplug;
    }
}

void Config::get(t_config_data *cfg)
{
  *cfg = work;
}

void Config::set(t_config_data *cfg)
{
  next = *cfg;

  apply(true);
}

const char *Config::get_ignored()
{
  return work.ignored.c_str();
}

void Config::set_ignored(const char *ignore_list)
{
  next.ignored = ignore_list;
}

bool Config::use_database()
{
  bool success = true;

  if(mydb) { delete mydb; mydb = 0; }
  if(next.usedb) {
    mydb = new CAdPlugDatabase;
    success = mydb->load(next.db_file);
  }
  CAdPlug::set_database(mydb);

  return success;
}

bool Config::test_opl2()
{
  CRealopl tmp(next.adlibport);

  return tmp.detect();
}

bool Config::test_winnt()
{
#if (_MSC_VER >= 1900) // VS2015+
  // These functions no longer exist, but these systems all inherit from NT anyway.
  return true;
#else
  OSVERSIONINFO ver;

  ver.dwOSVersionInfoSize = sizeof(ver);

  GetVersionEx(&ver);

  if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT)
    return true;

  return false;
#endif
}

bool Config::test_xmplay()
{
  return GetModuleHandle("xmplay.exe") ? true : false;
}

bool Config::test_porttalk()
  /* Enables I/O port permissions on Windows NT, using the PortTalk device driver.
   * Returns true on success. Returns false if PortTalk isn't installed.
   */
{
  DWORD BytesReturned, our_pid;
  HANDLE PortTalk_Driver;

  // Try to open PortTalk driver
  if((PortTalk_Driver = CreateFile("\\\\.\\PortTalk",GENERIC_READ,0,NULL,
				   OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL)) == INVALID_HANDLE_VALUE) {
    puts("porttalk_enable(): PortTalk not installed.");
    return false;
  }

  // Reset I/O permission map (deny all access)
  if(!DeviceIoControl(PortTalk_Driver,
		      CTL_CODE(40000, 0x900, METHOD_BUFFERED, FILE_ANY_ACCESS),
		      NULL,0,NULL,0,&BytesReturned,NULL)) {
    puts("porttalk_enable(): Error on resetting I/O permission map!");
    CloseHandle(PortTalk_Driver);
    return false;
  }

  // Set I/O permission map (exclusive access to all ports)
  if(!DeviceIoControl(PortTalk_Driver,
		      CTL_CODE(40000, 0x901, METHOD_BUFFERED, FILE_ANY_ACCESS),
		      NULL,0,NULL,0,&BytesReturned,NULL)) {
    puts("porttalk_enable(): Error on setting I/O permission map!");
    CloseHandle(PortTalk_Driver);
    return false;
  }

  // Enable I/O permissions on ourself
  our_pid = GetCurrentProcessId();
  printf("porttalk_enable(): Our process ID is %lu.\n",our_pid);
  if(!DeviceIoControl(PortTalk_Driver,
		      CTL_CODE(40000, 0x903, METHOD_BUFFERED, FILE_ANY_ACCESS),
		      &our_pid,4,NULL,0,&BytesReturned,NULL)) {
    puts("porttalk_enable(): Error on establishing I/O permissions on our process!");
    CloseHandle(PortTalk_Driver);
    return false;
  }

  CloseHandle(PortTalk_Driver);
  Sleep(1);	// Very important !! Wait for device driver to carry out our requests.
  return true;
}
<|endoftext|>


<commit_before>#include	<cstdlib>
#include	<cmath>
#include	<fstream>
#include	<sstream>
#include	<iostream>
#include	<iomanip>
#include	<string>
#include	<vector>
#include	<algorithm>
#include	<exception>
#include	<sys/time.h>
#include	"modules/htmTree.h"
#include	"modules/kdTree.h"
#include        "misc.h"
#include        "feat.h"
#include        "structs.h"
#include        "collision.h"
#include        "global.h"
//reduce redistributes, updates  07/02/15 rnc
int main(int argc, char **argv) {
	//// Initializations ---------------------------------------------
	srand48(1234); // Make sure we have reproducability
	check_args(argc);
	Time t, time; // t for global, time for local
	init_time(t);
	Feat F;
    MTL M;

	// Read parameters file //
	F.readInputFile(argv[1]);
	printFile(argv[1]);
	// Read Secretfile
    // Secret contains the identity of each target: QSO-Ly-a, QSO-tracers, LRG, ELG, fake QSO, fake LRG, SS, SF
    Gals Secret;
    printf("before read secretfile \n");
    init_time_at(time,"# read Secret file",t);

    Secret=read_Secretfile(F.Secretfile,F);
    printf("# Read %d galaxies from %s \n",Secret.size(),F.Secretfile.c_str());
	print_time(time,"# ... took :");
    std::vector<int> count;
    count=count_galaxies(Secret);
    printf(" Number of galaxies by type, QSO-Ly-a, QSO-tracers, LRG, ELG, fake QSO, fake LRG, SS, SF\n");
    for(int i=0;i<8;i++){printf (" type %d number  %d  \n",i, count[i]);}
    //read the three input files
    init_time_at(time,"# read target, SS, SF files",t);
    MTL Targ=read_MTLfile(F.Targfile,F,0,0);
    MTL SStars=read_MTLfile(F.SStarsfile,F,1,0);
    MTL SkyF=read_MTLfile(F.SkyFfile,F,0,1);
    print_time(time,"# ... took :");
    //combine the three input files

    M=Targ;

    printf(" M size %d \n",M.size());
    M.insert(M.end(),SStars.begin(),SStars.end());
    printf(" M size %d \n",M.size());
    M.insert(M.end(),SkyF.begin(),SkyF.end());
    printf(" M size %d \n",M.size());
    F.Ngal=M.size();
    assign_priority_class(M);

    //establish priority classes
    init_time_at(time,"# establish priority clasess",t);
    std::vector <int> count_class(M.priority_list.size(),0);
    for(int i;i<M.size();++i){
        if(!M[i].SS&&!M[i].SF){
        count_class[M[i].priority_class]+=1;
        }
    }
	print_time(time,"# ... took :");

    for(int i;i<M.priority_list.size();++i){
        printf("  class  %d  number  %d\n",i,count_class[i]);
    }

    PP pp;
	pp.read_fiber_positions(F);
	F.Nfiber = pp.fp.size()/2;
	F.Npetal = max(pp.spectrom)+1;
    F.Nfbp = (int) (F.Nfiber/F.Npetal);// fibers per petal = 500
	pp.get_neighbors(F); pp.compute_fibsofsp(F);

    //P is original list of plates
	Plates P = read_plate_centers(F);

    printf(" future plates %d\n",P.size());
    F.Nplate=P.size();
	printf("# Read %s plate centers from %s and %d fibers from %s\n",f(F.Nplate).c_str(),F.tileFile.c_str(),F.Nfiber,F.fibFile.c_str());

	// Computes geometries of cb and fh: pieces of positioner - used to determine possible collisions
	F.cb = create_cb(); // cb=central body
	F.fh = create_fh(); // fh=fiber holder

	//// Collect available galaxies <-> tilefibers --------------------
	// HTM Tree of galaxies
	const double MinTreeSize = 0.01;
	init_time_at(time,"# Start building HTM tree",t);
	htmTree<struct target> T(M,MinTreeSize);
	print_time(time,"# ... took :");//T.stats();
    init_time_at(time,"# collect galaxies at ",t);

	// For plates/fibers, collect available galaxies; done in parallel
    collect_galaxies_for_all(M,T,P,pp,F);
    print_time(time,"# ... took :");//T.stats();
    init_time_at(time,"# collect available tile-fibers at",t);
	// For each galaxy, computes available tilefibers  G[i].av_tfs = [(j1,k1),(j2,k2),..]
	collect_available_tilefibers(M,P,F);

	//results_on_inputs("doc/figs/",G,P,F,true);

	//// Assignment |||||||||||||||||||||||||||||||||||||||||||||||||||
    printf(" Nplate %d  Ngal %d   Nfiber %d \n", F.Nplate, F.Ngal, F.Nfiber);
    Assignment A(M,F);

	print_time(t,"# Start assignment at : ");

	// Make a plan ----------------------------------------------------
    // Plans whole survey without sky fibers, standard stars
    // assumes maximum number of observations needed for QSOs, LRGs

    simple_assign(M,P,pp,F,A);

    //check to see if there are tiles with no galaxies
    //need to keep mapping of old tile list to new tile list
    //and inverse map
    A.inv_order=initList(F.Nplate,0);
    for (int j=0;j<F.Nplate ;++j){
        bool not_done=true;
        for(int k=0;k<F.Nfiber && not_done;++k){
            if(A.TF[j][k]!=-1){
                A.suborder.push_back(j);
                not_done=false;

            }
        }
    }
    F.NUsedplate=A.suborder.size();
    printf(" Plates after screening %d \n",F.NUsedplate);

    //if(F.diagnose)diagnostic(M,G,F,A);

    print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false); // Hist of unused fibs

	// Smooth out distribution of free fibers, and increase the number of assignments

	for (int i=0; i<1; i++) redistribute_tf(M,P,pp,F,A,0);// more iterations will improve performance slightly
	for (int i=0; i<1; i++) {
        improve(M,P,pp,F,A,0);
		redistribute_tf(M,P,pp,F,A,0);
	}
	print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false);
    //try assigning SF and SS before real time assignment
    for (int j=0;j<F.NUsedplate;++j){

        int js=A.suborder[j];
        assign_sf_ss(js,M,P,pp,F,A); // Assign SS and SF for each tile
        assign_unused(js,M,P,pp,F,A);
    }
    if(F.diagnose)diagnostic(M,Secret,F,A);
    init_time_at(time,"# Begin real time assignment",t);

	//Execute plan, updating targets at intervals
    for(int i=0;i<F.pass_intervals.size();i++)printf(" i=%d interval %d \n",i,F.pass_intervals[i]);
    std::vector <int> update_intervals=F.pass_intervals;
    update_intervals.push_back(F.NUsedplate);//to end intervals at last plate
    for(int i=0;i<update_intervals.size()-1;++i){//go plate by used plate
        int starter=update_intervals[i];
        printf(" before pass = %d  at %d  tiles\n",i,starter);
        //display_results("doc/figs/",G,P,pp,F,A,true);
        //plan whole survey from this point out
        /*
        for (int jj=starter; jj<F.NUsedplate; jj++) {
            int js = A.suborder[jj];
            assign_sf_ss(js,M,P,pp,F,A); // Assign SS and SF
            assign_unused(js,M,P,pp,F,A);
        }
         */
        //update target information for interval i
        for (int jj=starter; jj<update_intervals[i+1]; jj++) {

            // Update corrects all future occurrences of wrong QSOs etc and tries to observe something else
            if (0<=jj-F.Analysis) update_plan_from_one_obs(jj,Secret,M,P,pp,F,A); else printf("\n no update\n");
        }
        redistribute_tf(M,P,pp,F,A,starter);
        improve(M,P,pp,F,A,starter);
        redistribute_tf(M,P,pp,F,A,starter);
        //}

        if(F.diagnose)diagnostic(M,Secret,F,A);

    // check on SS and SF
/*
    for(int j=0;j<F.NUsedplate;++j){
        int js=A.suborder[j];
        printf("\n js = %d\n",js);
        for (int p=0;p<F.Npetal;++p){
            int count_SS=0;
            int count_SF=0;
            for (int k=0;k<F.Nfbp;++k){
                int kk=pp.fibers_of_sp[p][k];
                int g=A.TF[js][kk];
                if(g!=-1 && M[g].SS)count_SS++;
                if(g!=-1 && M[g].SF)count_SF++;

            }
            printf("  %d  %d   ",count_SS,count_SF);
        }
        printf("\n");
    }
        */
    }

	// Results -------------------------------------------------------
    if (F.PrintAscii) for (int j=0; j<F.NUsedplate; j++){
        write_FAtile_ascii(A.suborder[j],F.outDir,M,P,pp,F,A);
    }

    if (F.PrintFits) for (int j=0; j<F.NUsedplate; j++){
        fa_write(A.suborder[j],F.outDir,M,P,pp,F,A); // Write output
    }

	display_results("doc/figs/",Secret,M,P,pp,F,A,true);
	if (F.Verif) A.verif(P,M,pp,F); // Verification that the assignment is sane

	print_time(t,"# Finished !... in");

	return(0);

}
<commit_msg>diagnostic<commit_after>#include	<cstdlib>
#include	<cmath>
#include	<fstream>
#include	<sstream>
#include	<iostream>
#include	<iomanip>
#include	<string>
#include	<vector>
#include	<algorithm>
#include	<exception>
#include	<sys/time.h>
#include	"modules/htmTree.h"
#include	"modules/kdTree.h"
#include        "misc.h"
#include        "feat.h"
#include        "structs.h"
#include        "collision.h"
#include        "global.h"
//reduce redistributes, updates  07/02/15 rnc
int main(int argc, char **argv) {
	//// Initializations ---------------------------------------------
	srand48(1234); // Make sure we have reproducability
	check_args(argc);
	Time t, time; // t for global, time for local
	init_time(t);
	Feat F;
    MTL M;

	// Read parameters file //
	F.readInputFile(argv[1]);
	printFile(argv[1]);
	// Read Secretfile
    // Secret contains the identity of each target: QSO-Ly-a, QSO-tracers, LRG, ELG, fake QSO, fake LRG, SS, SF
    Gals Secret;
    printf("before read secretfile \n");
    init_time_at(time,"# read Secret file",t);

    Secret=read_Secretfile(F.Secretfile,F);
    printf("# Read %d galaxies from %s \n",Secret.size(),F.Secretfile.c_str());
	print_time(time,"# ... took :");
    std::vector<int> count;
    count=count_galaxies(Secret);
    printf(" Number of galaxies by type, QSO-Ly-a, QSO-tracers, LRG, ELG, fake QSO, fake LRG, SS, SF\n");
    for(int i=0;i<8;i++){printf (" type %d number  %d  \n",i, count[i]);}
    //read the three input files
    init_time_at(time,"# read target, SS, SF files",t);
    MTL Targ=read_MTLfile(F.Targfile,F,0,0);
    MTL SStars=read_MTLfile(F.SStarsfile,F,1,0);
    MTL SkyF=read_MTLfile(F.SkyFfile,F,0,1);
    print_time(time,"# ... took :");
    //combine the three input files

    M=Targ;

    printf(" M size %d \n",M.size());
    M.insert(M.end(),SStars.begin(),SStars.end());
    printf(" M size %d \n",M.size());
    M.insert(M.end(),SkyF.begin(),SkyF.end());
    printf(" M size %d \n",M.size());
    F.Ngal=M.size();
    assign_priority_class(M);

    //establish priority classes
    init_time_at(time,"# establish priority clasess",t);
    std::vector <int> count_class(M.priority_list.size(),0);
    for(int i;i<M.size();++i){
        if(!M[i].SS&&!M[i].SF){
        count_class[M[i].priority_class]+=1;
        }
    }
	print_time(time,"# ... took :");

    for(int i;i<M.priority_list.size();++i){
        printf("  class  %d  number  %d\n",i,count_class[i]);
    }

    PP pp;
	pp.read_fiber_positions(F);
	F.Nfiber = pp.fp.size()/2;
	F.Npetal = max(pp.spectrom)+1;
    F.Nfbp = (int) (F.Nfiber/F.Npetal);// fibers per petal = 500
	pp.get_neighbors(F); pp.compute_fibsofsp(F);

    //P is original list of plates
	Plates P = read_plate_centers(F);

    printf(" future plates %d\n",P.size());
    F.Nplate=P.size();
	printf("# Read %s plate centers from %s and %d fibers from %s\n",f(F.Nplate).c_str(),F.tileFile.c_str(),F.Nfiber,F.fibFile.c_str());

	// Computes geometries of cb and fh: pieces of positioner - used to determine possible collisions
	F.cb = create_cb(); // cb=central body
	F.fh = create_fh(); // fh=fiber holder

	//// Collect available galaxies <-> tilefibers --------------------
	// HTM Tree of galaxies
	const double MinTreeSize = 0.01;
	init_time_at(time,"# Start building HTM tree",t);
	htmTree<struct target> T(M,MinTreeSize);
	print_time(time,"# ... took :");//T.stats();
    init_time_at(time,"# collect galaxies at ",t);

	// For plates/fibers, collect available galaxies; done in parallel
    collect_galaxies_for_all(M,T,P,pp,F);
    print_time(time,"# ... took :");//T.stats();
    init_time_at(time,"# collect available tile-fibers at",t);
	// For each galaxy, computes available tilefibers  G[i].av_tfs = [(j1,k1),(j2,k2),..]
	collect_available_tilefibers(M,P,F);

	//results_on_inputs("doc/figs/",G,P,F,true);

	//// Assignment |||||||||||||||||||||||||||||||||||||||||||||||||||
    printf(" Nplate %d  Ngal %d   Nfiber %d \n", F.Nplate, F.Ngal, F.Nfiber);
    Assignment A(M,F);

	print_time(t,"# Start assignment at : ");

	// Make a plan ----------------------------------------------------
    // Plans whole survey without sky fibers, standard stars
    // assumes maximum number of observations needed for QSOs, LRGs

    simple_assign(M,P,pp,F,A);

    //check to see if there are tiles with no galaxies
    //need to keep mapping of old tile list to new tile list
    //and inverse map
    A.inv_order=initList(F.Nplate,0);
    for (int j=0;j<F.Nplate ;++j){
        bool not_done=true;
        for(int k=0;k<F.Nfiber && not_done;++k){
            if(A.TF[j][k]!=-1){
                A.suborder.push_back(j);
                not_done=false;

            }
        }
    }
    F.NUsedplate=A.suborder.size();
    printf(" Plates after screening %d \n",F.NUsedplate);

    //if(F.diagnose)diagnostic(M,G,F,A);

    print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false); // Hist of unused fibs

	// Smooth out distribution of free fibers, and increase the number of assignments

	for (int i=0; i<1; i++) redistribute_tf(M,P,pp,F,A,0);// more iterations will improve performance slightly
	for (int i=0; i<1; i++) {
        improve(M,P,pp,F,A,0);
		redistribute_tf(M,P,pp,F,A,0);
	}
	print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false);
    //try assigning SF and SS before real time assignment
    for (int j=0;j<F.NUsedplate;++j){

        int js=A.suborder[j];
        assign_sf_ss(js,M,P,pp,F,A); // Assign SS and SF for each tile
        assign_unused(js,M,P,pp,F,A);
    }
    if(F.diagnose)diagnostic(M,Secret,F,A);
    init_time_at(time,"# Begin real time assignment",t);

	//Execute plan, updating targets at intervals
    for(int i=0;i<F.pass_intervals.size();i++)printf(" i=%d interval %d \n",i,F.pass_intervals[i]);
    std::vector <int> update_intervals=F.pass_intervals;
    update_intervals.push_back(F.NUsedplate);//to end intervals at last plate
    for(int i=0;i<update_intervals.size()-1;++i){//go plate by used plate
        int starter=update_intervals[i];
        printf(" before pass = %d  at %d  tiles  \n",i,starter);
        //display_results("doc/figs/",G,P,pp,F,A,true);
        //plan whole survey from this point out
        /*
        for (int jj=starter; jj<F.NUsedplate; jj++) {
            int js = A.suborder[jj];
            assign_sf_ss(js,M,P,pp,F,A); // Assign SS and SF
            assign_unused(js,M,P,pp,F,A);
        }
         */
        //update target information for interval i
    }
    /*
        for (int jj=starter; jj<update_intervals[i+1]; jj++) {

            // Update corrects all future occurrences of wrong QSOs etc and tries to observe something else
            if (0<=jj-F.Analysis) update_plan_from_one_obs(jj,Secret,M,P,pp,F,A); else printf("\n no update\n");
        }
        redistribute_tf(M,P,pp,F,A,starter);
        improve(M,P,pp,F,A,starter);
        redistribute_tf(M,P,pp,F,A,starter);
        //}

        if(F.diagnose)diagnostic(M,Secret,F,A);

    // check on SS and SF
/*
    for(int j=0;j<F.NUsedplate;++j){
        int js=A.suborder[j];
        printf("\n js = %d\n",js);
        for (int p=0;p<F.Npetal;++p){
            int count_SS=0;
            int count_SF=0;
            for (int k=0;k<F.Nfbp;++k){
                int kk=pp.fibers_of_sp[p][k];
                int g=A.TF[js][kk];
                if(g!=-1 && M[g].SS)count_SS++;
                if(g!=-1 && M[g].SF)count_SF++;

            }
            printf("  %d  %d   ",count_SS,count_SF);
        }
        printf("\n");
    }

    }
     */

	// Results -------------------------------------------------------
    if (F.PrintAscii) for (int j=0; j<F.NUsedplate; j++){
        write_FAtile_ascii(A.suborder[j],F.outDir,M,P,pp,F,A);
    }

    if (F.PrintFits) for (int j=0; j<F.NUsedplate; j++){
        fa_write(A.suborder[j],F.outDir,M,P,pp,F,A); // Write output
    }

	display_results("doc/figs/",Secret,M,P,pp,F,A,true);
	if (F.Verif) A.verif(P,M,pp,F); // Verification that the assignment is sane

	print_time(t,"# Finished !... in");

	return(0);

}
<|endoftext|>


<commit_before>///
/// @file  balance_S2_load.cpp
/// @brief Dynamically increase or decrease the segment_size or the
///        segments_per_thread in order to improve the load balancing
///        in the computation of the special leaves. The algorithm
///        calculates the relative standard deviation of the timings
///        of the individual threads and then decides whether to
///        assign more or less work to the threads.
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <balance_S2_load.hpp>
#include <aligned_vector.hpp>
#include <pmath.hpp>

#include <stdint.h>
#include <algorithm>
#include <cmath>

using namespace std;
using namespace primecount;

namespace {

double get_average(aligned_vector<double>& timings)
{
  size_t n = timings.size();
  double sum = 0;

  for (size_t i = 0; i < n; i++)
    sum += timings[i];

  return sum / n;
}

double relative_standard_deviation(aligned_vector<double>& timings)
{
  size_t n = timings.size();
  double average = get_average(timings);
  double sum_mean_squared = 0;

  if (average == 0)
    return 0;

  for (size_t i = 0; i < n; i++)
  {
    double mean = timings[i] - average;
    sum_mean_squared += mean * mean;
  }

  double standard_deviation = sqrt(sum_mean_squared / n);
  double rel_standard_deviation = 100 * standard_deviation / average;

  return rel_standard_deviation;
}

} // namespace

namespace primecount {

void balance_S2_load(int64_t* segment_size,
                     int64_t* segments_per_thread,
                     int64_t min_segment_size,
                     int64_t max_segment_size,
                     aligned_vector<double>& timings)
{
  double seconds = get_average(timings);
  double rsd = relative_standard_deviation(timings);
  double increase_threshold = 6;

  if (seconds < 0.1)
    increase_threshold *= 2;
  else if (seconds > 2)
    increase_threshold /= 2;

  rsd = in_between(increase_threshold / 7, rsd, increase_threshold * 7);

  if (*segment_size < max_segment_size)
  {
    // balance segment_size
    if ((seconds < 0.1 || rsd < increase_threshold) &&
         seconds < 10)
      *segment_size <<= 1;
  }
  else
  {
    // balance segments_per_thread
    double segments = max(1.0, *segments_per_thread * increase_threshold / rsd);

    if ((segments < *segments_per_thread && seconds > 0.01) ||
        (segments > *segments_per_thread && seconds < 10))
    {
      *segments_per_thread = (int) segments;
    }
  }
}

} //namespace
<commit_msg>Update balance_S2_load.cpp<commit_after>///
/// @file  balance_S2_load.cpp
/// @brief Dynamically increase or decrease the segment_size or the
///        segments_per_thread in order to improve the load balancing
///        in the computation of the special leaves. The algorithm
///        calculates the relative standard deviation of the timings
///        of the individual threads and then decides whether to
///        assign more or less work to the threads.
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <balance_S2_load.hpp>
#include <aligned_vector.hpp>
#include <pmath.hpp>

#include <stdint.h>
#include <algorithm>
#include <cmath>

using namespace std;
using namespace primecount;

namespace {

double get_average(aligned_vector<double>& timings)
{
  size_t n = timings.size();
  double sum = 0;

  for (size_t i = 0; i < n; i++)
    sum += timings[i];

  return sum / n;
}

double relative_standard_deviation(aligned_vector<double>& timings)
{
  size_t n = timings.size();
  double average = get_average(timings);
  double sum_mean_squared = 0;

  if (average == 0)
    return 0;

  for (size_t i = 0; i < n; i++)
  {
    double mean = timings[i] - average;
    // error correction
    mean = min(mean, average * 2);
    sum_mean_squared += mean * mean;
  }

  double standard_deviation = sqrt(sum_mean_squared / n);
  double rel_standard_deviation = 100 * standard_deviation / average;

  return rel_standard_deviation;
}

} // namespace

namespace primecount {

void balance_S2_load(int64_t* segment_size,
                     int64_t* segments_per_thread,
                     int64_t min_segment_size,
                     int64_t max_segment_size,
                     aligned_vector<double>& timings)
{
  double seconds = get_average(timings);
  double rsd = relative_standard_deviation(timings);
  double increase_threshold = 6;

  if (seconds < 0.1)
    increase_threshold *= 2;
  else if (seconds > 2)
    increase_threshold /= 2;

  rsd = in_between(increase_threshold / 7, rsd, increase_threshold * 7);

  if (*segment_size < max_segment_size)
  {
    // balance segment_size
    if ((seconds < 0.1 || rsd < increase_threshold) &&
         seconds < 10)
      *segment_size <<= 1;
  }
  else
  {
    // balance segments_per_thread
    double segments = max(1.0, *segments_per_thread * increase_threshold / rsd);

    if ((segments < *segments_per_thread && seconds > 0.01) ||
        (segments > *segments_per_thread && seconds < 10))
    {
      *segments_per_thread = (int) segments;
    }
  }
}

} //namespace
<|endoftext|>


<commit_before>/*
    ircservercontact.cpp - IRC Server Contact

    Copyright (c) 2003      by Michel Hermier <mhermier@kde.org>
    Copyright (c) 2002      by Nick Betcher <nbetcher@kde.org>

    Kopete    (c) 2002-2003 by the Kopete developers <kopete-devel@kde.org>

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

#include <qtimer.h>

#include <kdebug.h>
#include <klocale.h>
#include <qtimer.h>

#undef KDE_NO_COMPAT
#include <kaction.h>

#include "kopetemessagemanagerfactory.h"
#include "kopeteview.h"
#include "irccontact.h"
#include "ircservercontact.h"
#include "ircaccount.h"
#include "ircprotocol.h"
#include "ksparser.h"

IRCServerContact::IRCServerContact(IRCContactManager *contactManager, const QString &servername, KopeteMetaContact *m)
	: IRCContact(contactManager, servername, m, "irc_server")
{
	QObject::connect(m_engine, SIGNAL(internalError(KIRC::EngineError, const KIRCMessage &)),
			this, SLOT(engineInternalError(KIRC::EngineError, const KIRCMessage &)));

	//FIXME: Have some kind of a debug option for raw input/ouput display??
	/*QObject::connect(m_engine, SIGNAL(sentMessage(const KIRCMessage &)),
			this, SLOT(engineSentMessage(const KIRCMessage &)));
	QObject::connect(m_engine, SIGNAL(receivedMessage(const KIRCMessage &)),
			this, SLOT(engineReceivedMessage(const KIRCMessage &)));*/

	QObject::connect( m_engine, SIGNAL(incomingNotice( const QString &, const QString &)),
			this, SLOT(slotIncomingNotice(const QString &, const QString &)) );

	QObject::connect( m_engine, SIGNAL(incomingUnknown( const QString &)),
			this, SLOT(slotAppendMessage(const QString &)) );

	QObject::connect( m_engine, SIGNAL(incomingConnectString( const QString &)),
			this, SLOT(slotAppendMessage(const QString &)) );

	//FIXME:: This shouldn't add MOTD stuffs when someone uses /motd
	QObject::connect( m_engine, SIGNAL(incomingMotd( const QStringList &)),
			this, SLOT(slotIncomingMotd(const QStringList &)) );

	QObject::connect(KopeteMessageManagerFactory::factory(), SIGNAL(viewCreated(KopeteView*)),
			this, SLOT(slotViewCreated(KopeteView*)) );

	updateStatus();
}

void IRCServerContact::updateStatus()
{
	KIRC::EngineStatus status = m_engine->status();
	switch( status )
	{
		case KIRC::Disconnected:
		case KIRC::Connecting:
			setOnlineStatus( m_protocol->m_ServerStatusOffline );
			break;

		case KIRC::Authentifying:
		case KIRC::Connected:
		case KIRC::Closing:
			// should make some extra check here
			setOnlineStatus( m_protocol->m_ServerStatusOnline );
			break;

		default:
			setOnlineStatus( m_protocol->m_StatusUnknown );
	}
}

const QString IRCServerContact::caption() const
{
	return i18n("%1 @ %2").arg( m_engine->nickName() ).arg( m_engine->host() );
}

void IRCServerContact::engineInternalError( KIRC::EngineError engineError, const KIRCMessage &ircmsg )
{
	QString error;
	switch( engineError )
	{
		case KIRC::ParsingFailed:
			error = i18n("KIRC Error - parse error: ");
			break;
		case KIRC::UnknownCommand:
			error = i18n("KIRC Error - Unknown command: ");
			break;
		case KIRC::InvalidNumberOfArguments:
			error = i18n("KIRC Error - Invalid number of arguments: ");
			break;
		case KIRC::MethodFailed:
			error = i18n("KIRC Error - Method failed: ");
			break;
		default:
			error = i18n("KIRC Error - Unknown error: ");
	}

	KopeteContactPtrList members;
	members.append( this );
	KopeteMessage msg(this, members, error + QString( ircmsg.raw() ), KopeteMessage::Internal,
		KopeteMessage::PlainText, KopeteMessage::Chat);
	appendMessage(msg);
}

void IRCServerContact::slotSendMsg(KopeteMessage &, KopeteMessageManager *manager )
{
	KopeteMessage msg( manager->user(), manager->members(),
		i18n("You can not talk to the server, you can only issue commands here. Type /help for supported commands."), KopeteMessage::Internal, KopeteMessage::PlainText, KopeteMessage::Chat);
	manager->appendMessage(msg);
}

void IRCServerContact::slotAppendMessage( const QString &message )
{
	KopeteContactPtrList members;
	members.append( this );
	KopeteMessage msg( this, members, message, KopeteMessage::Internal,
		KopeteMessage::PlainText, KopeteMessage::Chat );
	msg.setBody( KSParser::parse( msg.escapedBody().stripWhiteSpace() ), KopeteMessage::RichText );
	appendMessage(msg);
}

void IRCServerContact::slotIncomingNotice( const QString &orig, const QString &notice )
{
	slotAppendMessage( i18n("NOTICE %1: %2").arg( orig ).arg( notice ) );
}

void IRCServerContact::slotIncomingMotd( const QStringList &motd )
{
	for( QStringList::ConstIterator it = motd.begin(); it != motd.end(); ++it )
		slotAppendMessage( *it );
}

void IRCServerContact::appendMessage( KopeteMessage &msg )
{
	msg.setImportance( KopeteMessage::Low ); //to don't distrub the user

	if( m_msgManager && m_msgManager->view(false) )
		m_msgManager->appendMessage(msg);
	else
		mMsgBuffer.append( msg );
}

void IRCServerContact::slotDumpMessages()
{
	for( QValueList<KopeteMessage>::Iterator it = mMsgBuffer.begin(); it != mMsgBuffer.end(); ++it )
		manager()->appendMessage(*it);
	mMsgBuffer.clear();
}

void IRCServerContact::slotViewCreated( KopeteView *v )
{
	kdDebug() << k_funcinfo << "Created: " << v->msgManager() << ", Mine: " << m_msgManager << endl;
	if( m_msgManager && v->msgManager() == m_msgManager )
		QTimer::singleShot( 500, this, SLOT( slotDumpMessages() ) );
}

#include "ircservercontact.moc"
<commit_msg>Minor oops I just caught. Need to call messageSucceeded here or the icon animates forever.<commit_after>/*
    ircservercontact.cpp - IRC Server Contact

    Copyright (c) 2003      by Michel Hermier <mhermier@kde.org>
    Copyright (c) 2002      by Nick Betcher <nbetcher@kde.org>

    Kopete    (c) 2002-2003 by the Kopete developers <kopete-devel@kde.org>

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

#include <qtimer.h>

#include <kdebug.h>
#include <klocale.h>
#include <qtimer.h>

#undef KDE_NO_COMPAT
#include <kaction.h>

#include "kopetemessagemanagerfactory.h"
#include "kopeteview.h"
#include "irccontact.h"
#include "ircservercontact.h"
#include "ircaccount.h"
#include "ircprotocol.h"
#include "ksparser.h"

IRCServerContact::IRCServerContact(IRCContactManager *contactManager, const QString &servername, KopeteMetaContact *m)
	: IRCContact(contactManager, servername, m, "irc_server")
{
	QObject::connect(m_engine, SIGNAL(internalError(KIRC::EngineError, const KIRCMessage &)),
			this, SLOT(engineInternalError(KIRC::EngineError, const KIRCMessage &)));

	//FIXME: Have some kind of a debug option for raw input/ouput display??
	/*QObject::connect(m_engine, SIGNAL(sentMessage(const KIRCMessage &)),
			this, SLOT(engineSentMessage(const KIRCMessage &)));
	QObject::connect(m_engine, SIGNAL(receivedMessage(const KIRCMessage &)),
			this, SLOT(engineReceivedMessage(const KIRCMessage &)));*/

	QObject::connect( m_engine, SIGNAL(incomingNotice( const QString &, const QString &)),
			this, SLOT(slotIncomingNotice(const QString &, const QString &)) );

	QObject::connect( m_engine, SIGNAL(incomingUnknown( const QString &)),
			this, SLOT(slotAppendMessage(const QString &)) );

	QObject::connect( m_engine, SIGNAL(incomingConnectString( const QString &)),
			this, SLOT(slotAppendMessage(const QString &)) );

	//FIXME:: This shouldn't add MOTD stuffs when someone uses /motd
	QObject::connect( m_engine, SIGNAL(incomingMotd( const QStringList &)),
			this, SLOT(slotIncomingMotd(const QStringList &)) );

	QObject::connect(KopeteMessageManagerFactory::factory(), SIGNAL(viewCreated(KopeteView*)),
			this, SLOT(slotViewCreated(KopeteView*)) );

	updateStatus();
}

void IRCServerContact::updateStatus()
{
	KIRC::EngineStatus status = m_engine->status();
	switch( status )
	{
		case KIRC::Disconnected:
		case KIRC::Connecting:
			setOnlineStatus( m_protocol->m_ServerStatusOffline );
			break;

		case KIRC::Authentifying:
		case KIRC::Connected:
		case KIRC::Closing:
			// should make some extra check here
			setOnlineStatus( m_protocol->m_ServerStatusOnline );
			break;

		default:
			setOnlineStatus( m_protocol->m_StatusUnknown );
	}
}

const QString IRCServerContact::caption() const
{
	return i18n("%1 @ %2").arg( m_engine->nickName() ).arg( m_engine->host() );
}

void IRCServerContact::engineInternalError( KIRC::EngineError engineError, const KIRCMessage &ircmsg )
{
	QString error;
	switch( engineError )
	{
		case KIRC::ParsingFailed:
			error = i18n("KIRC Error - parse error: ");
			break;
		case KIRC::UnknownCommand:
			error = i18n("KIRC Error - Unknown command: ");
			break;
		case KIRC::InvalidNumberOfArguments:
			error = i18n("KIRC Error - Invalid number of arguments: ");
			break;
		case KIRC::MethodFailed:
			error = i18n("KIRC Error - Method failed: ");
			break;
		default:
			error = i18n("KIRC Error - Unknown error: ");
	}

	KopeteContactPtrList members;
	members.append( this );
	KopeteMessage msg(this, members, error + QString( ircmsg.raw() ), KopeteMessage::Internal,
		KopeteMessage::PlainText, KopeteMessage::Chat);
	appendMessage(msg);
}

void IRCServerContact::slotSendMsg(KopeteMessage &, KopeteMessageManager *manager )
{
	manager->messageSucceeded();
	KopeteMessage msg( manager->user(), manager->members(),
		i18n("You can not talk to the server, you can only issue commands here. Type /help for supported commands."), KopeteMessage::Internal, KopeteMessage::PlainText, KopeteMessage::Chat);
	manager->appendMessage(msg);
}

void IRCServerContact::slotAppendMessage( const QString &message )
{
	KopeteContactPtrList members;
	members.append( this );
	KopeteMessage msg( this, members, message, KopeteMessage::Internal,
		KopeteMessage::PlainText, KopeteMessage::Chat );
	msg.setBody( KSParser::parse( msg.escapedBody().stripWhiteSpace() ), KopeteMessage::RichText );
	appendMessage(msg);
}

void IRCServerContact::slotIncomingNotice( const QString &orig, const QString &notice )
{
	slotAppendMessage( i18n("NOTICE %1: %2").arg( orig ).arg( notice ) );
}

void IRCServerContact::slotIncomingMotd( const QStringList &motd )
{
	for( QStringList::ConstIterator it = motd.begin(); it != motd.end(); ++it )
		slotAppendMessage( *it );
}

void IRCServerContact::appendMessage( KopeteMessage &msg )
{
	msg.setImportance( KopeteMessage::Low ); //to don't distrub the user

	if( m_msgManager && m_msgManager->view(false) )
		m_msgManager->appendMessage(msg);
	else
		mMsgBuffer.append( msg );
}

void IRCServerContact::slotDumpMessages()
{
	for( QValueList<KopeteMessage>::Iterator it = mMsgBuffer.begin(); it != mMsgBuffer.end(); ++it )
		manager()->appendMessage(*it);
	mMsgBuffer.clear();
}

void IRCServerContact::slotViewCreated( KopeteView *v )
{
	kdDebug() << k_funcinfo << "Created: " << v->msgManager() << ", Mine: " << m_msgManager << endl;
	if( m_msgManager && v->msgManager() == m_msgManager )
		QTimer::singleShot( 500, this, SLOT( slotDumpMessages() ) );
}

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


<commit_before>/*************************************************
* Mutex Source File                              *
* (C) 1999-2006 The Botan Project                *
*************************************************/

#include <botan/mutex.h>

namespace Botan {

/*************************************************
* Mutex_Holder Constructor                       *
*************************************************/
Mutex_Holder::Mutex_Holder(Mutex* m) : mux(m)
   {
   if(!mux)
      throw Invalid_Argument("Mutex_Holder: Argument was NULL");
   mux->lock();
   }

/*************************************************
* Mutex_Holder Destructor                        *
*************************************************/
Mutex_Holder::~Mutex_Holder()
   {
   mux->unlock();
   }

/*************************************************
* Default Mutex Factory                          *
*************************************************/
Mutex* Mutex_Factory::make()
   {
   class Default_Mutex : public Mutex
      {
      public:
         class Mutex_State_Error : public Internal_Error
            {
            public:
               Mutex_State_Error(const std::string& where)
                  {
                  set_msg("Default_Mutex::" + where + ": Mutex is already " +
                          where + "ed");
                  }
            };

         void lock()
            {
            if(locked)
               throw Mutex_State_Error("lock");
            locked = true;
            }

         void unlock()
            {
            if(!locked)
               throw Mutex_State_Error("unlock");
            locked = false;
            }

         Default_Mutex() { locked = false; }
      private:
         bool locked;
      };

   return new Default_Mutex;
   }

}
<commit_msg>Fix the constructor of Mutex_State_Error<commit_after>/*************************************************
* Mutex Source File                              *
* (C) 1999-2006 The Botan Project                *
*************************************************/

#include <botan/mutex.h>

namespace Botan {

/*************************************************
* Mutex_Holder Constructor                       *
*************************************************/
Mutex_Holder::Mutex_Holder(Mutex* m) : mux(m)
   {
   if(!mux)
      throw Invalid_Argument("Mutex_Holder: Argument was NULL");
   mux->lock();
   }

/*************************************************
* Mutex_Holder Destructor                        *
*************************************************/
Mutex_Holder::~Mutex_Holder()
   {
   mux->unlock();
   }

/*************************************************
* Default Mutex Factory                          *
*************************************************/
Mutex* Mutex_Factory::make()
   {
   class Default_Mutex : public Mutex
      {
      public:
         class Mutex_State_Error : public Internal_Error
            {
            public:
               Mutex_State_Error(const std::string& where) :
                  Internal_Error("Default_Mutex::" + where + ": " +
                                 "Mutex is already " + where + "ed") {}
            };

         void lock()
            {
            if(locked)
               throw Mutex_State_Error("lock");
            locked = true;
            }

         void unlock()
            {
            if(!locked)
               throw Mutex_State_Error("unlock");
            locked = false;
            }

         Default_Mutex() { locked = false; }
      private:
         bool locked;
      };

   return new Default_Mutex;
   }

}
<|endoftext|>


<commit_before>#ifndef LIBPORT_WINDOWS_HH
# define LIBPORT_WINDOWS_HH

# include <boost/cstdint.hpp>
# include <libport/detect-win32.h>

# if defined WIN32 || defined LIBPORT_WIN32

/* We don't want to include WinSock1 stuff that are included by Windows.h and
 * this is the official workaround used by Windows' headers. We're doing this
 * because WinSock1 stuff conflict with WinSock2 and this enables us to
 * include this header or libport/network.h in any order we want. */
#  ifndef _WINSOCKAPI_
#   define _WINSOCKAPI_
#   define LIBPORT_DEFINED_WINSOCKAPI_
#  endif

/* We don't want the min and max macros that conflict with std::min
 * and std::max.  We might need some magic to bind _cpp_min and
 * _cpp_max to min and max eventually.  See
 * <http://raduking.homeip.net/raduking/forumwin/index.php?showtopic=270>.
 *
 * This must be done conditionnaly because MinGW already defines NOMINMAX in
 * some headers.  */
#  ifndef NOMINMAX
#   define NOMINMAX 1
#  endif

#  include <windows.h>

/* If we defined _WINSOCKAPI_ to prevent WinSock1 stuff to be imported,
 * restore the situation since the user might really want to import WinSock.h
 * later. */
#  ifdef LIBPORT_DEFINED_WINSOCKAPI_
#   undef _WINSOCKAPI_
#   undef LIBPORT_DEFINED_WINSOCKAPI_
#  endif

// Based on the value I have on my G4 -- Akim.
typedef boost::uint32_t useconds_t;

// Some libraries define usleep as a macro. In this case, do not redefine
// it.
# ifndef usleep
inline
int
usleep (useconds_t microseconds)
{
  Sleep((microseconds + 999) / 1000);
  return 0;
}
# endif

inline
unsigned int
sleep(unsigned int seconds)
{
  Sleep(seconds * 1000);
  // Under Unix systems, sleep returns the number of second left to
  // sleep if interrupted by a signal. The WIN32 Sleep always sleeps
  // the requested time, thus 0 is the right answer.
  return 0;
}

inline int getpagesize()
{
  // FIXME: find the equivalent call.
  return 4096;
}

# endif // !WIN32

#endif // !LIBPORT_WINDOWS_HH
<commit_msg>Add portable getpid, isatty and STDOUT_FILENO for WIN32.<commit_after>#ifndef LIBPORT_WINDOWS_HH
# define LIBPORT_WINDOWS_HH

# include <boost/cstdint.hpp>
# include <libport/detect-win32.h>

# if defined WIN32 || defined LIBPORT_WIN32

/* We don't want to include WinSock1 stuff that are included by Windows.h and
 * this is the official workaround used by Windows' headers. We're doing this
 * because WinSock1 stuff conflict with WinSock2 and this enables us to
 * include this header or libport/network.h in any order we want. */
#  ifndef _WINSOCKAPI_
#   define _WINSOCKAPI_
#   define LIBPORT_DEFINED_WINSOCKAPI_
#  endif

/* We don't want the min and max macros that conflict with std::min
 * and std::max.  We might need some magic to bind _cpp_min and
 * _cpp_max to min and max eventually.  See
 * <http://raduking.homeip.net/raduking/forumwin/index.php?showtopic=270>.
 *
 * This must be done conditionnaly because MinGW already defines NOMINMAX in
 * some headers.  */
#  ifndef NOMINMAX
#   define NOMINMAX 1
#  endif

#  include <io.h>
#  include <process.h>
#  include <windows.h>

/* If we defined _WINSOCKAPI_ to prevent WinSock1 stuff to be imported,
 * restore the situation since the user might really want to import WinSock.h
 * later. */
#  ifdef LIBPORT_DEFINED_WINSOCKAPI_
#   undef _WINSOCKAPI_
#   undef LIBPORT_DEFINED_WINSOCKAPI_
#  endif

// Based on the value I have on my G4 -- Akim.
typedef boost::uint32_t useconds_t;

// Some libraries define usleep as a macro. In this case, do not redefine
// it.
# ifndef usleep
inline
int
usleep (useconds_t microseconds)
{
  Sleep((microseconds + 999) / 1000);
  return 0;
}
# endif

inline
unsigned int
sleep(unsigned int seconds)
{
  Sleep(seconds * 1000);
  // Under Unix systems, sleep returns the number of second left to
  // sleep if interrupted by a signal. The WIN32 Sleep always sleeps
  // the requested time, thus 0 is the right answer.
  return 0;
}

inline int getpagesize()
{
  // FIXME: find the equivalent call.
  return 4096;
}

#  define getpid _getpid
#  define isatty _isatty
#  define STDOUT_FILENO _fileno(stdout)

# endif // defined WIN32 || defined LIBPORT_WIN32

#endif // !LIBPORT_WINDOWS_HH
<|endoftext|>


<commit_before>//===-- Annotation.cpp - Implement the Annotation Classes -----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the AnnotationManager class.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/Annotation.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/System/RWMutex.h"
#include <map>
#include <cstring>
using namespace llvm;

Annotation::~Annotation() {}  // Designed to be subclassed

Annotable::~Annotable() {   // Virtual because it's designed to be subclassed...
  Annotation *A = AnnotationList;
  while (A) {
    Annotation *Next = A->getNext();
    delete A;
    A = Next;
  }
}

namespace {
  class StrCmp {
  public:
    bool operator()(const char *a, const char *b) const {
      return strcmp(a, b) < 0;
    }
  };
}

typedef std::map<const char*, unsigned, StrCmp> IDMapType;
static unsigned IDCounter = 0;  // Unique ID counter

// Static member to ensure initialiation on demand.
static ManagedStatic<IDMapType> IDMap;
static ManagedStatic<sys::SmartRWMutex<true> > AnnotationsLock;

// On demand annotation creation support...
typedef Annotation *(*AnnFactory)(AnnotationID, const Annotable *, void *);
typedef std::map<unsigned, std::pair<AnnFactory,void*> > FactMapType;

static ManagedStatic<FactMapType> TheFactMap;
static FactMapType &getFactMap() {
  return *TheFactMap;
}

static void eraseFromFactMap(unsigned ID) {
  sys::SmartScopedWriter<true> Writer(&*AnnotationsLock);
  TheFactMap->erase(ID);
}

AnnotationID AnnotationManager::getID(const char *Name) {  // Name -> ID
  AnnotationsLock->reader_acquire();
  IDMapType::iterator I = IDMap->find(Name);
  IDMapType::iterator E = IDMap->end();
  AnnotationsLock->reader_release();

  if (I == E) {
    sys::SmartScopedWriter<true> Writer(&*AnnotationsLock);
    I = IDMap->find(Name);
    if (I == IDMap->end())
      (*IDMap)[Name] = IDCounter++;   // Add a new element
    return AnnotationID(IDCounter-1);
  }
  return AnnotationID(I->second);
}

// getID - Name -> ID + registration of a factory function for demand driven
// annotation support.
AnnotationID AnnotationManager::getID(const char *Name, Factory Fact,
                                      void *Data) {
  AnnotationID Result(getID(Name));
  registerAnnotationFactory(Result, Fact, Data);
  return Result;
}

// getName - This function is especially slow, but that's okay because it should
// only be used for debugging.
//
const char *AnnotationManager::getName(AnnotationID ID) {  // ID -> Name
  sys::SmartScopedReader<true> Reader(&*AnnotationsLock);
  IDMapType &TheMap = *IDMap;
  for (IDMapType::iterator I = TheMap.begin(); ; ++I) {
    assert(I != TheMap.end() && "Annotation ID is unknown!");
    if (I->second == ID.ID) return I->first;
  }
}

// registerAnnotationFactory - This method is used to register a callback
// function used to create an annotation on demand if it is needed by the
// Annotable::findOrCreateAnnotation method.
//
void AnnotationManager::registerAnnotationFactory(AnnotationID ID, AnnFactory F,
                                                  void *ExtraData) {
  if (F) {
    sys::SmartScopedWriter<true> Writer(&*AnnotationsLock);
    getFactMap()[ID.ID] = std::make_pair(F, ExtraData);
  } else {
    eraseFromFactMap(ID.ID);
  }
}

// createAnnotation - Create an annotation of the specified ID for the
// specified object, using a register annotation creation function.
//
Annotation *AnnotationManager::createAnnotation(AnnotationID ID,
                                                const Annotable *Obj) {
  AnnotationsLock->reader_acquire();
  FactMapType::iterator I = getFactMap().find(ID.ID);
  if (I == getFactMap().end()) {
    AnnotationsLock->reader_release();
    return 0;
  }

  AnnotationsLock->reader_release();
  return I->second.first(ID, Obj, I->second.second);
}
<commit_msg>Use atomic operations for accessing this global counter.<commit_after>//===-- Annotation.cpp - Implement the Annotation Classes -----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the AnnotationManager class.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/Annotation.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/System/RWMutex.h"
#include <map>
#include <cstring>
using namespace llvm;

Annotation::~Annotation() {}  // Designed to be subclassed

Annotable::~Annotable() {   // Virtual because it's designed to be subclassed...
  Annotation *A = AnnotationList;
  while (A) {
    Annotation *Next = A->getNext();
    delete A;
    A = Next;
  }
}

namespace {
  class StrCmp {
  public:
    bool operator()(const char *a, const char *b) const {
      return strcmp(a, b) < 0;
    }
  };
}

typedef std::map<const char*, unsigned, StrCmp> IDMapType;
static unsigned IDCounter = 0;  // Unique ID counter

// Static member to ensure initialiation on demand.
static ManagedStatic<IDMapType> IDMap;
static ManagedStatic<sys::SmartRWMutex<true> > AnnotationsLock;

// On demand annotation creation support...
typedef Annotation *(*AnnFactory)(AnnotationID, const Annotable *, void *);
typedef std::map<unsigned, std::pair<AnnFactory,void*> > FactMapType;

static ManagedStatic<FactMapType> TheFactMap;
static FactMapType &getFactMap() {
  return *TheFactMap;
}

static void eraseFromFactMap(unsigned ID) {
  sys::SmartScopedWriter<true> Writer(&*AnnotationsLock);
  TheFactMap->erase(ID);
}

AnnotationID AnnotationManager::getID(const char *Name) {  // Name -> ID
  AnnotationsLock->reader_acquire();
  IDMapType::iterator I = IDMap->find(Name);
  IDMapType::iterator E = IDMap->end();
  AnnotationsLock->reader_release();

  if (I == E) {
    sys::SmartScopedWriter<true> Writer(&*AnnotationsLock);
    I = IDMap->find(Name);
    if (I == IDMap->end()) {
      unsigned newCount = sys::AtomicIncrement(&IDCounter);
      (*IDMap)[Name] = newCount-1;   // Add a new element
      return AnnotationID(newCount-1);
    } else
      return AnnotationID(I->second);
  }
  return AnnotationID(I->second);
}

// getID - Name -> ID + registration of a factory function for demand driven
// annotation support.
AnnotationID AnnotationManager::getID(const char *Name, Factory Fact,
                                      void *Data) {
  AnnotationID Result(getID(Name));
  registerAnnotationFactory(Result, Fact, Data);
  return Result;
}

// getName - This function is especially slow, but that's okay because it should
// only be used for debugging.
//
const char *AnnotationManager::getName(AnnotationID ID) {  // ID -> Name
  sys::SmartScopedReader<true> Reader(&*AnnotationsLock);
  IDMapType &TheMap = *IDMap;
  for (IDMapType::iterator I = TheMap.begin(); ; ++I) {
    assert(I != TheMap.end() && "Annotation ID is unknown!");
    if (I->second == ID.ID) return I->first;
  }
}

// registerAnnotationFactory - This method is used to register a callback
// function used to create an annotation on demand if it is needed by the
// Annotable::findOrCreateAnnotation method.
//
void AnnotationManager::registerAnnotationFactory(AnnotationID ID, AnnFactory F,
                                                  void *ExtraData) {
  if (F) {
    sys::SmartScopedWriter<true> Writer(&*AnnotationsLock);
    getFactMap()[ID.ID] = std::make_pair(F, ExtraData);
  } else {
    eraseFromFactMap(ID.ID);
  }
}

// createAnnotation - Create an annotation of the specified ID for the
// specified object, using a register annotation creation function.
//
Annotation *AnnotationManager::createAnnotation(AnnotationID ID,
                                                const Annotable *Obj) {
  AnnotationsLock->reader_acquire();
  FactMapType::iterator I = getFactMap().find(ID.ID);
  if (I == getFactMap().end()) {
    AnnotationsLock->reader_release();
    return 0;
  }

  AnnotationsLock->reader_release();
  return I->second.first(ID, Obj, I->second.second);
}
<|endoftext|>


<commit_before>#include	<cstdlib>
#include	<cmath>
#include	<fstream>
#include	<sstream>
#include	<iostream>
#include	<iomanip>
#include	<string>
#include	<vector>
#include	<algorithm>
#include	<exception>
#include	<sys/time.h>
#include	"modules/htmTree.h"
#include	"modules/kdTree.h"
#include        "misc.h"
#include        "feat.h"
#include        "structs.h"
#include        "collision.h"
#include        "global.h"
//reduce redistributes, updates  07/02/15 rnc
int main(int argc, char **argv) {
	//// Initializations ---------------------------------------------
	srand48(1234); // Make sure we have reproducability
	check_args(argc);
	Time t, time; // t for global, time for local
	init_time(t);
	Feat F;
    MTL M;

	// Read parameters file //
	F.readInputFile(argv[1]);
	printFile(argv[1]);
	// Read galaxies
	Gals G;
    if(F.Ascii){
        G=read_galaxies_ascii(F);}
    else{
        G = read_galaxies(F);
    }
	F.Ngal = G.size();
	printf("# Read %s galaxies from %s \n",f(F.Ngal).c_str(),F.galFile.c_str());
    std::vector<int> count;
    count=count_galaxies(G);
    printf(" Number of galaxies by type, QSO-Ly-a, QSO-tracers, LRG, ELG, fake QSO, fake LRG, SS, SF\n");
    for(int i=0;i<8;i++){printf (" type %d number  %d  \n",i, count[i]);}
    //read the three input files
    MTL Targ=read_MTLfile(F.Targfile,F);
    MTL SStars=read_MTLfile(F.SStarsfile,F);
    MTL SkyF=read_MTLfile(F.SkyFfile,F);
    //combine the three input files

    M=Targ;
    M.reserve(Targ.size()+SStars.size()+SkyF.size());
    printf(" M size %d \n",M.size());
    M.insert(M.end(),SStars.begin(),SStars.end());
    printf(" M size %d \n",M.size());
    M.insert(M.end(),SkyF.begin(),SkyF.end());
    printf(" M size %d \n",M.size());
    //need to fix priority list, combining those from targets, standard stars, skyfibers
    std::vector<int> p_list=Targ.priority_list;
    p_list.insert(p_list.end(),SStars.priority_list.begin(),SStars.priority_list.end());
    p_list.insert(p_list.end(),SkyF.priority_list.begin(),SkyF.priority_list.end());
    std::sort(p_list.begin(),p_list.end());

    M.priority_list.clear();
    M.priority_list.push_back(p_list[0]);
    for(int i=1;i<p_list.size();++i){
        if(p_list[i]!=p_list[i-1]){
            M.priority_list.push_back(p_list[i]);
            }
    }

    assign_priority_class(M);

    //establish priority classes
    std::vector <int> count_class(M.priority_list.size(),0);
    printf("Number in each priority class.  The last two are SF and SS.\n");
    for(int i;i<M.size();++i){
        count_class[M[i].priority_class]+=1;
    }
    for(int i;i<M.priority_list.size();++i){
        printf("  class  %d  number  %d\n",i,count_class[i]);
    }

	PP pp;
	pp.read_fiber_positions(F);
	F.Nfiber = pp.fp.size()/2;
	F.Npetal = max(pp.spectrom)+1;
    F.Nfbp = (int) (F.Nfiber/F.Npetal);// fibers per petal = 500
	pp.get_neighbors(F); pp.compute_fibsofsp(F);
	Plates OP = read_plate_centers(F);
    Plates P;
    F.ONplate=OP.size();
	printf("# Read %s plate centers from %s and %d fibers from %s\n",f(F.ONplate).c_str(),F.tileFile.c_str(),F.Nfiber,F.fibFile.c_str());

	// Computes geometries of cb and fh: pieces of positioner - used to determine possible collisions
	F.cb = create_cb(); // cb=central body
	F.fh = create_fh(); // fh=fiber holder

	//// Collect available galaxies <-> tilefibers --------------------
	// HTM Tree of galaxies
	const double MinTreeSize = 0.01;
	init_time_at(time,"# Start building HTM tree",t);
	htmTree<struct target> T(M,MinTreeSize);
	print_time(time,"# ... took :");//T.stats();

	// For plates/fibers, collect available galaxies; done in parallel
    collect_galaxies_for_all(M,T,OP,pp,F);

	// For each galaxy, computes available tilefibers  G[i].av_tfs = [(j1,k1),(j2,k2),..]
	collect_available_tilefibers(M,OP,F);

	//results_on_inputs("doc/figs/",G,P,F,true);

	//// Assignment |||||||||||||||||||||||||||||||||||||||||||||||||||
    printf(" Nplate %d  Ngal %d   Nfiber %d \n", F.ONplate, F.Ngal, F.Nfiber);
	Assignment A(M,F);
    printf(" Nplate %d  Ngal %d   Nfiber %d \n", F.ONplate, F.Ngal, F.Nfiber);
	print_time(t,"# Start assignment at : ");

	// Make a plan ----------------------------------------------------
    // Plans whole survey without sky fibers, standard stars
    // assumes maximum number of observations needed for QSOs, LRGs

    simple_assign(M,OP,pp,F,A);

    //check to see if there are tiles with no galaxies
    for (int j=0;j<F.Nplate ;++j){
        int newj=0;
        OP[j].is_used=false;
        bool not_done=true;
        for(int k=0;k<F.Nfiber && not_done;++k){
            if(A.TF[j][k]!=-1){
                OP[j].is_used=true;
                P[newj]=OP[j];
                newj++;
                not_done=false;
            }
        }
    }
    F.Nplate=P.size();
    printf(" Plates after screening %d \n",F.Nplate);
    if(F.diagnose)diagnostic(M,G,F,A);

    print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false); // Hist of unused fibs

	// Smooth out distribution of free fibers, and increase the number of assignments

	for (int i=0; i<1; i++) redistribute_tf(M,P,pp,F,A);// more iterations will improve performance slightly
	for (int i=0; i<2; i++) {
        improve(M,P,pp,F,A);
		//redistribute_tf(M,P,pp,F,A);
		redistribute_tf(M,P,pp,F,A);
	}

	print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false);
    //try assigning SF and SS before real time assignment
    for (int j=0;j<F.Nplate;++j){
        A.next_plate=j;
        assign_sf_ss(j,M,P,pp,F,A); // Assign SS and SF for each tile
        assign_unused(j,M,P,pp,F,A);
    }

    init_time_at(time,"# Begin real time assignment",t);

	//Execute plan, updating targets at intervals

    for(int i=0;i<F.pass_intervals.size();++i){
        printf(" before pass = %d  at %d  tiles\n",i,F.pass_intervals[i]);
        //display_results("doc/figs/",G,P,pp,F,A,true);
        //execute this phase (i) of survey
        A.next_plate=F.pass_intervals[i];
        for (int jj=F.pass_intervals[i]; jj<F.Nplate&&jj<F.Nplate; jj++) {
            int j = A.next_plate;
            assign_sf_ss(j,M,P,pp,F,A); // Assign SS and SF
            assign_unused(j,M,P,pp,F,A);
            A.next_plate++;
        }
        //update target information for this interval
        A.next_plate=F.pass_intervals[i];
        for (int jj=F.pass_intervals[i]; jj<F.pass_intervals[i+1]&&jj<F.Nplate; jj++) {
            int j = A.next_plate;

            // Update corrects all future occurrences of wrong QSOs etc and tries to observe something else
            if (0<=j-F.Analysis) update_plan_from_one_obs(G,M,P,pp,F,A,F.Nplate-1); else printf("\n");
            A.next_plate++;
        }
        /*
        if(A.next_plate<F.Nplate){
        redistribute_tf(M,P,pp,F,A);
        redistribute_tf(M,P,pp,F,A);
        improve(M,P,pp,F,A);
        redistribute_tf(M,P,pp,F,A);
        }
         */
        if(F.diagnose)diagnostic(M,G,F,A);
    }

	// Results -------------------------------------------------------
    if (F.PrintAscii) for (int j=0; j<F.Nplate; j++){
        write_FAtile_ascii(j,F.outDir,M,P,pp,F,A);
    }

    if (F.PrintFits) for (int j=0; j<F.Nplate; j++){
        fa_write(j,F.outDir,M,P,pp,F,A); // Write output
    }

	display_results("doc/figs/",G,M,P,pp,F,A,true);
	if (F.Verif) A.verif(P,M,pp,F); // Verification that the assignment is sane

	print_time(t,"# Finished !... in");

	return(0);

}
<commit_msg>ONplate correction<commit_after>#include	<cstdlib>
#include	<cmath>
#include	<fstream>
#include	<sstream>
#include	<iostream>
#include	<iomanip>
#include	<string>
#include	<vector>
#include	<algorithm>
#include	<exception>
#include	<sys/time.h>
#include	"modules/htmTree.h"
#include	"modules/kdTree.h"
#include        "misc.h"
#include        "feat.h"
#include        "structs.h"
#include        "collision.h"
#include        "global.h"
//reduce redistributes, updates  07/02/15 rnc
int main(int argc, char **argv) {
	//// Initializations ---------------------------------------------
	srand48(1234); // Make sure we have reproducability
	check_args(argc);
	Time t, time; // t for global, time for local
	init_time(t);
	Feat F;
    MTL M;

	// Read parameters file //
	F.readInputFile(argv[1]);
	printFile(argv[1]);
	// Read galaxies
	Gals G;
    if(F.Ascii){
        G=read_galaxies_ascii(F);}
    else{
        G = read_galaxies(F);
    }
	F.Ngal = G.size();
	printf("# Read %s galaxies from %s \n",f(F.Ngal).c_str(),F.galFile.c_str());
    std::vector<int> count;
    count=count_galaxies(G);
    printf(" Number of galaxies by type, QSO-Ly-a, QSO-tracers, LRG, ELG, fake QSO, fake LRG, SS, SF\n");
    for(int i=0;i<8;i++){printf (" type %d number  %d  \n",i, count[i]);}
    //read the three input files
    MTL Targ=read_MTLfile(F.Targfile,F);
    MTL SStars=read_MTLfile(F.SStarsfile,F);
    MTL SkyF=read_MTLfile(F.SkyFfile,F);
    //combine the three input files

    M=Targ;
    M.reserve(Targ.size()+SStars.size()+SkyF.size());
    printf(" M size %d \n",M.size());
    M.insert(M.end(),SStars.begin(),SStars.end());
    printf(" M size %d \n",M.size());
    M.insert(M.end(),SkyF.begin(),SkyF.end());
    printf(" M size %d \n",M.size());
    //need to fix priority list, combining those from targets, standard stars, skyfibers
    std::vector<int> p_list=Targ.priority_list;
    p_list.insert(p_list.end(),SStars.priority_list.begin(),SStars.priority_list.end());
    p_list.insert(p_list.end(),SkyF.priority_list.begin(),SkyF.priority_list.end());
    std::sort(p_list.begin(),p_list.end());

    M.priority_list.clear();
    M.priority_list.push_back(p_list[0]);
    for(int i=1;i<p_list.size();++i){
        if(p_list[i]!=p_list[i-1]){
            M.priority_list.push_back(p_list[i]);
            }
    }

    assign_priority_class(M);

    //establish priority classes
    std::vector <int> count_class(M.priority_list.size(),0);
    printf("Number in each priority class.  The last two are SF and SS.\n");
    for(int i;i<M.size();++i){
        count_class[M[i].priority_class]+=1;
    }
    for(int i;i<M.priority_list.size();++i){
        printf("  class  %d  number  %d\n",i,count_class[i]);
    }

	PP pp;
	pp.read_fiber_positions(F);
	F.Nfiber = pp.fp.size()/2;
	F.Npetal = max(pp.spectrom)+1;
    F.Nfbp = (int) (F.Nfiber/F.Npetal);// fibers per petal = 500
	pp.get_neighbors(F); pp.compute_fibsofsp(F);
	Plates OP = read_plate_centers(F);
    Plates P;
    F.ONplate=OP.size();
	printf("# Read %s plate centers from %s and %d fibers from %s\n",f(F.ONplate).c_str(),F.tileFile.c_str(),F.Nfiber,F.fibFile.c_str());

	// Computes geometries of cb and fh: pieces of positioner - used to determine possible collisions
	F.cb = create_cb(); // cb=central body
	F.fh = create_fh(); // fh=fiber holder

	//// Collect available galaxies <-> tilefibers --------------------
	// HTM Tree of galaxies
	const double MinTreeSize = 0.01;
	init_time_at(time,"# Start building HTM tree",t);
	htmTree<struct target> T(M,MinTreeSize);
	print_time(time,"# ... took :");//T.stats();

	// For plates/fibers, collect available galaxies; done in parallel
    collect_galaxies_for_all(M,T,OP,pp,F);

	// For each galaxy, computes available tilefibers  G[i].av_tfs = [(j1,k1),(j2,k2),..]
	collect_available_tilefibers(M,OP,F);

	//results_on_inputs("doc/figs/",G,P,F,true);

	//// Assignment |||||||||||||||||||||||||||||||||||||||||||||||||||
    printf(" Nplate %d  Ngal %d   Nfiber %d \n", F.ONplate, F.Ngal, F.Nfiber);
	Assignment A(M,F);
    printf(" Nplate %d  Ngal %d   Nfiber %d \n", F.ONplate, F.Ngal, F.Nfiber);
	print_time(t,"# Start assignment at : ");

	// Make a plan ----------------------------------------------------
    // Plans whole survey without sky fibers, standard stars
    // assumes maximum number of observations needed for QSOs, LRGs

    simple_assign(M,OP,pp,F,A);

    //check to see if there are tiles with no galaxies
    for (int j=0;j<F.ONplate ;++j){
        int newj=0;
        OP[j].is_used=false;
        bool not_done=true;
        for(int k=0;k<F.Nfiber && not_done;++k){
            if(A.TF[j][k]!=-1){
                OP[j].is_used=true;
                P[newj]=OP[j];
                newj++;
                not_done=false;
            }
        }
    }
    F.Nplate=P.size();
    printf(" Plates after screening %d \n",F.Nplate);
    if(F.diagnose)diagnostic(M,G,F,A);

    print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false); // Hist of unused fibs

	// Smooth out distribution of free fibers, and increase the number of assignments

	for (int i=0; i<1; i++) redistribute_tf(M,P,pp,F,A);// more iterations will improve performance slightly
	for (int i=0; i<2; i++) {
        improve(M,P,pp,F,A);
		//redistribute_tf(M,P,pp,F,A);
		redistribute_tf(M,P,pp,F,A);
	}

	print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false);
    //try assigning SF and SS before real time assignment
    for (int j=0;j<F.Nplate;++j){
        A.next_plate=j;
        assign_sf_ss(j,M,P,pp,F,A); // Assign SS and SF for each tile
        assign_unused(j,M,P,pp,F,A);
    }

    init_time_at(time,"# Begin real time assignment",t);

	//Execute plan, updating targets at intervals

    for(int i=0;i<F.pass_intervals.size();++i){
        printf(" before pass = %d  at %d  tiles\n",i,F.pass_intervals[i]);
        //display_results("doc/figs/",G,P,pp,F,A,true);
        //execute this phase (i) of survey
        A.next_plate=F.pass_intervals[i];
        for (int jj=F.pass_intervals[i]; jj<F.Nplate&&jj<F.Nplate; jj++) {
            int j = A.next_plate;
            assign_sf_ss(j,M,P,pp,F,A); // Assign SS and SF
            assign_unused(j,M,P,pp,F,A);
            A.next_plate++;
        }
        //update target information for this interval
        A.next_plate=F.pass_intervals[i];
        for (int jj=F.pass_intervals[i]; jj<F.pass_intervals[i+1]&&jj<F.Nplate; jj++) {
            int j = A.next_plate;

            // Update corrects all future occurrences of wrong QSOs etc and tries to observe something else
            if (0<=j-F.Analysis) update_plan_from_one_obs(G,M,P,pp,F,A,F.Nplate-1); else printf("\n");
            A.next_plate++;
        }
        /*
        if(A.next_plate<F.Nplate){
        redistribute_tf(M,P,pp,F,A);
        redistribute_tf(M,P,pp,F,A);
        improve(M,P,pp,F,A);
        redistribute_tf(M,P,pp,F,A);
        }
         */
        if(F.diagnose)diagnostic(M,G,F,A);
    }

	// Results -------------------------------------------------------
    if (F.PrintAscii) for (int j=0; j<F.Nplate; j++){
        write_FAtile_ascii(j,F.outDir,M,P,pp,F,A);
    }

    if (F.PrintFits) for (int j=0; j<F.Nplate; j++){
        fa_write(j,F.outDir,M,P,pp,F,A); // Write output
    }

	display_results("doc/figs/",G,M,P,pp,F,A,true);
	if (F.Verif) A.verif(P,M,pp,F); // Verification that the assignment is sane

	print_time(t,"# Finished !... in");

	return(0);

}
<|endoftext|>