Exemplo n.º 1
0
static void *worker_thread_entry(void *param)
{
	work_thread_info *thread = (work_thread_info *)param;
	osd_work_queue *queue = thread->queue;

	// loop until we exit
	for ( ;; )
	{
		// block waiting for work or exit
		// bail on exit, and only wait if there are no pending items in queue
		if (!queue->exiting && queue->list == NULL)
		{
			begin_timing(thread->waittime);
			osd_event_wait(thread->wakeevent, INFINITE);
			end_timing(thread->waittime);
		}
		if (queue->exiting)
			break;

		// indicate that we are live
		atomic_exchange32(&thread->active, TRUE);
		atomic_increment32(&queue->livethreads);

		// process work items
		for ( ;; )
		{
			osd_ticks_t stopspin;

			// process as much as we can
			worker_thread_process(queue, thread);

			// if we're a high frequency queue, spin for a while before giving up
			if (queue->flags & WORK_QUEUE_FLAG_HIGH_FREQ && queue->list == NULL)
			{
				// spin for a while looking for more work
				begin_timing(thread->spintime);
				stopspin = osd_ticks() + SPIN_LOOP_TIME;
				
				do {
					int spin = 10000;
					while (--spin && queue->list == NULL)
						osd_yield_processor();
				} while (queue->list == NULL && osd_ticks() < stopspin);
				end_timing(thread->spintime);
			}

			// if nothing more, release the processor
			if (queue->list == NULL)
				break;
			add_to_stat(&queue->spinloops, 1);
		}

		// decrement the live thread count
		atomic_exchange32(&thread->active, FALSE);
		atomic_decrement32(&queue->livethreads);
	}
	return NULL;
}
Exemplo n.º 2
0
static unsigned __stdcall worker_thread_entry(void *param)
{
	work_thread_info *thread = param;
	osd_work_queue *queue = thread->queue;

	// loop until we exit
	for ( ;; )
	{
		// block waiting for work or exit
		DWORD result = WAIT_OBJECT_0;

		// bail on exit, and only wait if there are no pending items in queue
		if (!queue->exiting && queue->list == NULL)
		{
			begin_timing(thread->waittime);
			result = WaitForSingleObject(thread->wakeevent, INFINITE);
			end_timing(thread->waittime);
		}
		if (queue->exiting)
			break;

		// indicate that we are live
		interlocked_exchange32(&thread->active, TRUE);
		interlocked_increment(&queue->livethreads);

		// process work items
		for ( ;; )
		{
			osd_ticks_t stopspin;

			// process as much as we can
			worker_thread_process(queue, thread);

			// if we're a high frequency queue, spin for a while before giving up
			if (queue->flags & WORK_QUEUE_FLAG_HIGH_FREQ)
			{
				// spin for a while looking for more work
				begin_timing(thread->spintime);
				stopspin = osd_ticks() + SPIN_LOOP_TIME;
				while (queue->list == NULL && osd_ticks() < stopspin)
					YieldProcessor();
				end_timing(thread->spintime);
			}

			// if nothing more, release the processor
			if (queue->list == NULL)
				break;
			add_to_stat(&queue->spinloops, 1);
		}

		// decrement the live thread count
		interlocked_exchange32(&thread->active, FALSE);
		interlocked_decrement(&queue->livethreads);
	}
	return 0;
}
Exemplo n.º 3
0
static void *worker_thread_entry(void *param)
{
	work_thread_info *thread = (work_thread_info *)param;
	osd_work_queue &queue = thread->queue;

	// loop until we exit
	for ( ;; )
	{
		// block waiting for work or exit
		// bail on exit, and only wait if there are no pending items in queue
		if (queue.exiting)
			break;

		if (!queue_has_list_items(&queue))
		{
			begin_timing(thread->waittime);
			thread->wakeevent.wait( OSD_EVENT_WAIT_INFINITE);
			end_timing(thread->waittime);
		}

		if (queue.exiting)
			break;

		// indicate that we are live
		thread->active = TRUE;
		++queue.livethreads;

		// process work items
		for ( ;; )
		{
			// process as much as we can
			worker_thread_process(&queue, thread);

			// if we're a high frequency queue, spin for a while before giving up
			if (queue.flags & WORK_QUEUE_FLAG_HIGH_FREQ && queue.list.load() == nullptr)
			{
				// spin for a while looking for more work
				begin_timing(thread->spintime);
				spin_while<std::atomic<osd_work_item *>, osd_work_item *>(&queue.list, (osd_work_item *)nullptr, SPIN_LOOP_TIME);
				end_timing(thread->spintime);
			}

			// if nothing more, release the processor
			if (!queue_has_list_items(&queue))
				break;
			add_to_stat(queue.spinloops, 1);
		}

		// decrement the live thread count
		thread->active = FALSE;
		--queue.livethreads;
	}

	return nullptr;
}
Exemplo n.º 4
0
int osd_work_queue_wait(osd_work_queue *queue, osd_ticks_t timeout)
{
	// if no threads, no waiting
	if (queue->threads == 0)
		return TRUE;

	// if no items, we're done
	if (queue->items == 0)
		return TRUE;

	// if this is a multi queue, help out rather than doing nothing
	if (queue->flags & WORK_QUEUE_FLAG_MULTI)
	{
		work_thread_info *thread = &queue->thread[queue->threads];

		end_timing(thread->waittime);

		// process what we can as a worker thread
		worker_thread_process(queue, thread);

		// if we're a high frequency queue, spin until done
		if (queue->flags & WORK_QUEUE_FLAG_HIGH_FREQ && queue->items != 0)
		{
			osd_ticks_t stopspin = osd_ticks() + timeout;

			// spin until we're done
			begin_timing(thread->spintime);

			do {
				int spin = 10000;
				while (--spin && queue->items != 0)
					osd_yield_processor();
			} while (queue->items != 0 && osd_ticks() < stopspin);
			end_timing(thread->spintime);

			begin_timing(thread->waittime);
			return (queue->items == 0);
		}
		begin_timing(thread->waittime);
	}

	// reset our done event and double-check the items before waiting
	osd_event_reset(queue->doneevent);
	atomic_exchange32(&queue->waiting, TRUE);
	if (queue->items != 0)
		osd_event_wait(queue->doneevent, timeout);
	atomic_exchange32(&queue->waiting, FALSE);

	// return TRUE if we actually hit 0
	return (queue->items == 0);
}
Exemplo n.º 5
0
int main(int argc, char *argv[])
{
	struct timespec timing;
	int i, round;
	void *m[ALLOCS];
	/* a random set of allocations we test */
	int sizes[16] = { 1, 13, 100, 1000, 16, 10000, 50, 17,
					  123, 32, 8, 64, 8096, 1024, 123, 9 };

	library_init(NULL, "malloc_speed");
	atexit(library_deinit);

	print_mallinfo();

	start_timing(&timing);

	for (round = 0; round < ROUNDS; round++)
	{
		for (i = 0; i < ALLOCS; i++)
		{
			m[i] = malloc(sizes[(round + i) % countof(sizes)]);
		}
		for (i = 0; i < ALLOCS; i++)
		{
			free(m[i]);
		}
	}
	printf("time for %d malloc/frees, repeating %d rounds: %.4fs\n",
		   ALLOCS, ROUNDS, end_timing(&timing));

	print_mallinfo();

	return 0;
}
Exemplo n.º 6
0
int main(int argc, char** argv) {

	double* S = malloc_aligned<double>(LENGTH, 5);
	double* X = malloc_aligned<double>(LENGTH, 5);
	double* T = malloc_aligned<double>(LENGTH, 5);
	double* r = malloc_aligned<double>(LENGTH, 5);
	double* v = malloc_aligned<double>(LENGTH, 5);
	
	for(int i = 0; i < LENGTH; i++) {
		S[i] = 100;
		X[i] = 98;
		T[i] = 2;
		r[i] = 0.02;
		v[i] = 5;
	}

	start_timing();
	double sum = 0;
	for(int i = 0; i < ROUNDS; i++) {
		sum += run(S, X, T, r, v);
	}
	printf("%f \t(%f)\n", end_timing(), sum / (LENGTH * ROUNDS));

	return 0;
}
Exemplo n.º 7
0
static void run_test(diffie_hellman_group_t group, int rounds)
{
	diffie_hellman_t *l[rounds], *r;
	chunk_t chunk;
	struct timespec timing;
	int round;

	r = lib->crypto->create_dh(lib->crypto, group);
	if (!r)
	{
		printf("skipping %N, not supported\n",
				diffie_hellman_group_names, group);
		return;
	}

	printf("%N:\t",
			diffie_hellman_group_names, group);

	start_timing(&timing);
	for (round = 0; round < rounds; round++)
	{
		l[round] = lib->crypto->create_dh(lib->crypto, group);
	}
	printf("A = g^a/s: %8.1f", rounds / end_timing(&timing));

	for (round = 0; round < rounds; round++)
	{
		l[round]->get_my_public_value(l[round], &chunk);
		r->set_other_public_value(r, chunk);
		chunk_free(&chunk);
	}

	r->get_my_public_value(r, &chunk);
	start_timing(&timing);
	for (round = 0; round < rounds; round++)
	{
		l[round]->set_other_public_value(l[round], chunk);
	}
	printf(" | S = B^a/s: %8.1f\n", rounds / end_timing(&timing));
	chunk_free(&chunk);

	for (round = 0; round < rounds; round++)
	{
		l[round]->destroy(l[round]);
	}
	r->destroy(r);
}
Exemplo n.º 8
0
int osd_work_queue_wait(osd_work_queue *queue, osd_ticks_t timeout)
{
	// if no threads, no waiting
	if (queue->threads == 0)
		return TRUE;

	// if no items, we're done
	if (queue->items == 0)
		return TRUE;

	// if this is a multi queue, help out rather than doing nothing
	if (queue->flags & WORK_QUEUE_FLAG_MULTI)
	{
		work_thread_info *thread = &queue->thread[queue->threads];
		osd_ticks_t stopspin = osd_ticks() + timeout;

		end_timing(thread->waittime);

		// process what we can as a worker thread
		worker_thread_process(queue, thread);

		// if we're a high frequency queue, spin until done
		if (queue->flags & WORK_QUEUE_FLAG_HIGH_FREQ)
		{
			// spin until we're done
			begin_timing(thread->spintime);
			while (queue->items != 0 && osd_ticks() < stopspin)
				YieldProcessor();
			end_timing(thread->spintime);

			begin_timing(thread->waittime);
			return (queue->items == 0);
		}
		begin_timing(thread->waittime);
	}

	// reset our done event and double-check the items before waiting
	ResetEvent(queue->doneevent);
	interlocked_exchange32(&queue->waiting, TRUE);
	if (queue->items != 0)
		WaitForSingleObject(queue->doneevent, timeout * 1000 / osd_ticks_per_second());
	interlocked_exchange32(&queue->waiting, FALSE);

	// return TRUE if we actually hit 0
	return (queue->items == 0);
}
Exemplo n.º 9
0
int osd_work_queue_wait(osd_work_queue *queue, osd_ticks_t timeout)
{
	// if no threads, no waiting
	if (queue->threads == 0)
		return TRUE;

	// if no items, we're done
	if (queue->items == 0)
		return TRUE;

	// if this is a multi queue, help out rather than doing nothing
	if (queue->flags & WORK_QUEUE_FLAG_MULTI)
	{
		work_thread_info *thread = queue->thread[queue->threads];

		end_timing(thread->waittime);

		// process what we can as a worker thread
		worker_thread_process(queue, thread);

		// if we're a high frequency queue, spin until done
		if (queue->flags & WORK_QUEUE_FLAG_HIGH_FREQ && queue->items != 0)
		{
			// spin until we're done
			begin_timing(thread->spintime);
			spin_while_not<std::atomic<int>,int>(&queue->items, 0, timeout);
			end_timing(thread->spintime);

			begin_timing(thread->waittime);
			return (queue->items == 0);
		}
		begin_timing(thread->waittime);
	}

	// reset our done event and double-check the items before waiting
	queue->doneevent.reset();
	queue->waiting = TRUE;
	if (queue->items != 0)
		queue->doneevent.wait(timeout);
	queue->waiting = FALSE;

	// return TRUE if we actually hit 0
	return (queue->items == 0);
}
Exemplo n.º 10
0
ATTR_HOT inline void netlist_net_t::update_dev(const netlist_core_terminal_t *inp, const UINT32 mask) const
{
	if ((inp->state() & mask) != 0)
	{
		netlist_core_device_t &netdev = inp->netdev();
		begin_timing(netdev.total_time);
		inc_stat(netdev.stat_count);
		netdev.update_dev();
		end_timing(netdev().total_time);
	}
}
Exemplo n.º 11
0
void osd_work_queue_free(osd_work_queue *queue)
{
	// if we have threads, clean them up
	if (queue->threads > 0 && queue->thread != NULL)
	{
		int threadnum;

		// stop the timer for "waittime" on the main thread
		end_timing(queue->thread[queue->threads].waittime);

		// signal all the threads to exit
		queue->exiting = TRUE;
		for (threadnum = 0; threadnum < queue->threads; threadnum++)
		{
			work_thread_info *thread = &queue->thread[threadnum];
			if (thread->wakeevent != NULL)
				SetEvent(thread->wakeevent);
		}

		// wait for all the threads to go away
		for (threadnum = 0; threadnum < queue->threads; threadnum++)
		{
			work_thread_info *thread = &queue->thread[threadnum];

			// block on the thread going away, then close the handle
			if (thread->handle != NULL)
			{
				WaitForSingleObject(thread->handle, INFINITE);
				CloseHandle(thread->handle);
			}

			// clean up the wake event
			if (thread->wakeevent != NULL)
				CloseHandle(thread->wakeevent);
		}

#if KEEP_STATISTICS
		// output per-thread statistics
		for (threadnum = 0; threadnum <= queue->threads; threadnum++)
		{
			work_thread_info *thread = &queue->thread[threadnum];
			osd_ticks_t total = thread->runtime + thread->waittime + thread->spintime;
			printf("Thread %d:  items=%9d  run=%5.2f%% (%5.2f%%)  spin=%5.2f%%  wait/other=%5.2f%%\n",
					threadnum, thread->itemsdone,
					(double)thread->runtime * 100.0 / (double)total,
					(double)thread->actruntime * 100.0 / (double)total,
					(double)thread->spintime * 100.0 / (double)total,
					(double)thread->waittime * 100.0 / (double)total);
		}
#endif
	}

	// free the list
	if (queue->thread != NULL)
		free(queue->thread);

	// free all the events
	if (queue->doneevent != NULL)
		CloseHandle(queue->doneevent);

	// free all items in the free list
	while (queue->free != NULL)
	{
		osd_work_item *item = (osd_work_item *)queue->free;
		queue->free = item->next;
		if (item->event != NULL)
			CloseHandle(item->event);
		free(item);
	}

	// free all items in the active list
	while (queue->list != NULL)
	{
		osd_work_item *item = (osd_work_item *)queue->list;
		queue->list = item->next;
		if (item->event != NULL)
			CloseHandle(item->event);
		free(item);
	}

#if KEEP_STATISTICS
	printf("Items queued   = %9d\n", queue->itemsqueued);
	printf("SetEvent calls = %9d\n", queue->setevents);
	printf("Extra items    = %9d\n", queue->extraitems);
	printf("Spin loops     = %9d\n", queue->spinloops);
#endif

	// free the queue itself
	free(queue);
}
Exemplo n.º 12
0
static void *worker_thread_entry(void *param)
{
	work_thread_info *thread = (work_thread_info *)param;
	osd_work_queue *queue = thread->queue;

#if defined(SDLMAME_MACOSX)
	void *arp = NewAutoreleasePool();
#endif

	// loop until we exit
	for ( ;; )
	{
		// block waiting for work or exit
		// bail on exit, and only wait if there are no pending items in queue
		if (queue->exiting)
			break;

		if (!queue_has_list_items(queue))
		{
			begin_timing(thread->waittime);
			osd_event_wait(thread->wakeevent, OSD_EVENT_WAIT_INFINITE);
			end_timing(thread->waittime);
		}

		if (queue->exiting)
			break;

		// indicate that we are live
		atomic_exchange32(&thread->active, TRUE);
		atomic_increment32(&queue->livethreads);

		// process work items
		for ( ;; )
		{
			// process as much as we can
			worker_thread_process(queue, thread);

			// if we're a high frequency queue, spin for a while before giving up
			if (queue->flags & WORK_QUEUE_FLAG_HIGH_FREQ && queue->list == NULL)
			{
				// spin for a while looking for more work
				begin_timing(thread->spintime);
				spin_while(&queue->list, (osd_work_item *)NULL, SPIN_LOOP_TIME);
				end_timing(thread->spintime);
			}

			// if nothing more, release the processor
			if (!queue_has_list_items(queue))
				break;
			add_to_stat(&queue->spinloops, 1);
		}

		// decrement the live thread count
		atomic_exchange32(&thread->active, FALSE);
		atomic_decrement32(&queue->livethreads);
	}

#if defined(SDLMAME_MACOSX)
	ReleaseAutoreleasePool(arp);
#endif

	return NULL;
}
Exemplo n.º 13
0
osd_work_item *osd_work_item_queue_multiple(osd_work_queue *queue, osd_work_callback callback, INT32 numitems, void *parambase, INT32 paramstep, UINT32 flags)
{
	osd_work_item *itemlist = nullptr, *lastitem = nullptr;
	osd_work_item **item_tailptr = &itemlist;
	int itemnum;

	// loop over items, building up a local list of work
	for (itemnum = 0; itemnum < numitems; itemnum++)
	{
		osd_work_item *item;

		// first allocate a new work item; try the free list first
		{
			std::lock_guard<std::mutex> lock(queue->lock);
			do
			{
				item = (osd_work_item *)queue->free;
			} while (item != nullptr && !queue->free.compare_exchange_weak(item, item->next, std::memory_order_release, std::memory_order_relaxed));
		}

		// if nothing, allocate something new
		if (item == nullptr)
		{
			// allocate the item
			item = new osd_work_item(*queue);
			if (item == nullptr)
				return nullptr;
		}
		else
		{
			item->done = FALSE; // needs to be set this way to prevent data race/usage of uninitialized memory on Linux
		}

		// fill in the basics
		item->next = nullptr;
		item->callback = callback;
		item->param = parambase;
		item->result = nullptr;
		item->flags = flags;

		// advance to the next
		lastitem = item;
		*item_tailptr = item;
		item_tailptr = &item->next;
		parambase = (UINT8 *)parambase + paramstep;
	}

	// enqueue the whole thing within the critical section
	{
		std::lock_guard<std::mutex> lock(queue->lock);
		*queue->tailptr = itemlist;
		queue->tailptr = item_tailptr;
	}

	// increment the number of items in the queue
	queue->items += numitems;
	add_to_stat(queue->itemsqueued, numitems);

	// look for free threads to do the work
	if (queue->livethreads < queue->threads)
	{
		int threadnum;

		// iterate over all the threads
		for (threadnum = 0; threadnum < queue->threads; threadnum++)
		{
			work_thread_info *thread = queue->thread[threadnum];

			// if this thread is not active, wake him up
			if (!thread->active)
			{
				thread->wakeevent.set();
				add_to_stat(queue->setevents, 1);

				// for non-shared, the first one we find is good enough
				if (--numitems == 0)
					break;
			}
		}
	}

	// if no threads, run the queue now on this thread
	if (queue->threads == 0)
	{
		end_timing(queue->thread[0]->waittime);
		worker_thread_process(queue, queue->thread[0]);
		begin_timing(queue->thread[0]->waittime);
	}
	// only return the item if it won't get released automatically
	return (flags & WORK_ITEM_FLAG_AUTO_RELEASE) ? nullptr : lastitem;
}
Exemplo n.º 14
0
void osd_work_queue_free(osd_work_queue *queue)
{
	// stop the timer for "waittime" on the main thread
	if (queue->flags & WORK_QUEUE_FLAG_MULTI)
	{
		end_timing(queue->thread[queue->threads]->waittime);
	}

	// signal all the threads to exit
	queue->exiting = TRUE;
	for (int threadnum = 0; threadnum < queue->threads; threadnum++)
	{
		work_thread_info *thread = queue->thread[threadnum];
		thread->wakeevent.set();
	}

	// wait for all the threads to go away
	for (int threadnum = 0; threadnum < queue->threads; threadnum++)
	{
		work_thread_info *thread = queue->thread[threadnum];

		// block on the thread going away, then close the handle
		if (thread->handle != nullptr)
		{
			thread->handle->join();
			delete thread->handle;
		}

	}

#if KEEP_STATISTICS
	// output per-thread statistics
	for (work_thread_info *thread : queue->thread)
	{
		osd_ticks_t total = thread->runtime + thread->waittime + thread->spintime;
		printf("Thread %d:  items=%9d run=%5.2f%% (%5.2f%%)  spin=%5.2f%%  wait/other=%5.2f%% total=%9d\n",
				thread->id, thread->itemsdone,
				(double)thread->runtime * 100.0 / (double)total,
				(double)thread->actruntime * 100.0 / (double)total,
				(double)thread->spintime * 100.0 / (double)total,
				(double)thread->waittime * 100.0 / (double)total,
				(UINT32) total);
	}
#endif

	// free the list
	for (auto & th : queue->thread)
		delete th;
	queue->thread.clear();

	// free all items in the free list
	while (queue->free.load() != nullptr)
	{
		osd_work_item *item = (osd_work_item *)queue->free;
		queue->free = item->next;
		if (item->event != nullptr)
			delete item->event;
		delete item;
	}

	// free all items in the active list
	while (queue->list.load() != nullptr)
	{
		osd_work_item *item = (osd_work_item *)queue->list;
		queue->list = item->next;
		if (item->event != nullptr)
			delete item->event;
		delete item;
	}

#if KEEP_STATISTICS
	printf("Items queued   = %9d\n", queue->itemsqueued.load());
	printf("SetEvent calls = %9d\n", queue->setevents.load());
	printf("Extra items    = %9d\n", queue->extraitems.load());
	printf("Spin loops     = %9d\n", queue->spinloops.load());
#endif

	// free the queue itself
	delete queue;
}
Exemplo n.º 15
0
int main( int argc , char *argv[] ) {

  /* index counters */

  int	i ;

  /* Command line options */

  char		*output_file_name ;
  char		*static_file_name ;
  char		*mobile_file_name ;
  int		global_grid_size ;
  int		angle_step ;
  float		surface ;
  float		internal_value ;
  int		electrostatics ;
  int		keep_per_rotation ;
  int 		kept_scores ;
  int		rescue ;
  int		calculate ;
  float		reverse_calculated_one_span ;

  char		*default_global_grid_size ;
  char		*default_angle_step ;
  char		*default_surface ;
  char		*default_internal_value ;
  char		*default_electrostatics ;
  char		*default_keep_per_rotation ;

  /* File stuff */

  FILE		*ftdock_file ;
  char		line_buffer[100] ;
  int		id , id2 , SCscore ;
  float		RPscore ;
  int		x , y , z , z_twist , theta , phi ;

  /* Angles stuff */

  struct Angle	Angles ;
  int		first_rotation , rotation ;

  /* Structures */

  struct Structure	Static_Structure , Mobile_Structure ;
  struct Structure	Origin_Static_Structure , Origin_Mobile_Structure ;
  struct Structure	Rotated_at_Origin_Mobile_Structure ;

  /* Co-ordinates */

  int		xyz , fx , fy , fz , fxyz ;

  /* Grid stuff */

  float		grid_span , one_span ;

  float *static_grid ;
  float *mobile_grid ;
  float *convoluted_grid ;

  float *static_elec_grid = ( void * ) 0 ;
  float *mobile_elec_grid = ( void * ) 0 ;
  float *convoluted_elec_grid = ( void * ) 0 ;

  /* FFTW stuff */
  
  fftwf_plan	plan_static_grid,
		plan_static_elec_grid,
		plan_multiple_fsg,
		plan_multiple_elec_fsg,
		plan_mobile_grid,
		plan_mobile_elec_grid;

  fftwf_complex  *static_fsg ;
  fftwf_complex  *mobile_fsg ;
  fftwf_complex  *multiple_fsg ;

  fftwf_complex  *static_elec_fsg = ( void * ) 0 ;
  fftwf_complex  *mobile_elec_fsg = ( void * ) 0 ;
  fftwf_complex  *multiple_elec_fsg = ( void * ) 0 ;

  /* Scores */

  struct Score	*Scores ;
  float		max_es_value ;

/************/

  /* Its nice to tell people what going on straight away */

  setvbuf( stdout , (char *)NULL , _IONBF , 0 ) ;


  printf( "\n          3D-Dock Suite (March 2001)\n" ) ;
  printf( "          Copyright (C) 1997-2000 Gidon Moont\n" ) ;
  printf( "          This program comes with ABSOLUTELY NO WARRANTY\n" ) ;
  printf( "          for details see license. This program is free software,\n"); 
  printf( "          and you may redistribute it under certain conditions.\n\n"); 

  printf( "          Biomolecular Modelling Laboratory\n" ) ;
  printf( "          Imperial Cancer Research Fund\n" ) ;
  printf( "          44 Lincoln's Inn Fields\n" ) ;
  printf( "          London WC2A 3PX\n" ) ;
  printf( "          +44 (0)20 7269 3348\n" ) ;
  printf( "          http://www.bmm.icnet.uk/\n\n" ) ;


  printf( "Starting FTDock (v2.0) global search program\n" ) ;


/************/

  /* Memory allocation */

  if( ( ( output_file_name  = ( char * ) fftwf_malloc ( 500 * sizeof( char ) ) ) == NULL ) ||
      ( ( static_file_name  = ( char * ) fftwf_malloc ( 500 * sizeof( char ) ) ) == NULL ) ||
      ( ( mobile_file_name  = ( char * ) fftwf_malloc ( 500 * sizeof( char ) ) ) == NULL ) ) {
    GENERAL_MEMORY_PROBLEM 
  }

/************/

  /* Command Line defaults */

  strcpy( output_file_name , "ftdock_global.dat" ) ;
  strcpy( static_file_name , " --static file name was not provided--" ) ;
  strcpy( mobile_file_name , " --mobile file name was not provided--" ) ;
  global_grid_size = 128 ;
  angle_step = 12 ;
  surface = 1.3 ;
  internal_value = -15 ;
  electrostatics = 1 ;
  keep_per_rotation = 3 ;
  rescue = 0 ;
  calculate = 1 ;
  reverse_calculated_one_span = 0.7 ;

  default_global_grid_size = "(default calculated)" ;
  default_angle_step = "(default)" ;
  default_surface = "(default)" ;
  default_internal_value = "(default)" ;
  default_electrostatics = "(default)" ;
  default_keep_per_rotation = "(default)" ;

  /* Command Line parse */

  for( i = 1 ; i < argc ; i ++ ) {

    if( strcmp( argv[i] , "-out" ) == 0 ) {
      i ++ ;
      if( ( i == argc ) || ( strncmp( argv[i] , "-" , 1 ) == 0 ) ) {
        printf( "Bad command line\n" ) ;
        exit( EXIT_FAILURE ) ;
      }
      strcpy( output_file_name , argv[i] ) ;
    } else {
      if( strcmp( argv[i] , "-static" ) == 0 ) {
        i ++ ;
        if( ( i == argc ) || ( strncmp( argv[i] , "-" , 1 ) == 0 ) ) {
          printf( "Bad command line\n" ) ;
          exit( EXIT_FAILURE ) ;
        }
        strcpy( static_file_name , argv[i] ) ;
      } else {
        if( strcmp( argv[i] , "-mobile" ) == 0 ) {
          i ++ ;
          if( ( i == argc ) || ( strncmp( argv[i] , "-" , 1 ) == 0 ) ) {
            printf( "Bad command line\n" ) ;
            exit( EXIT_FAILURE ) ;
          }
          strcpy( mobile_file_name , argv[i] ) ;
        } else {
          if( strcmp( argv[i] , "-grid" ) == 0 ) {
            i ++ ;
            if( ( i == argc ) || ( strncmp( argv[i] , "-" , 1 ) == 0 ) ) {
              printf( "Bad command line\n" ) ;
              exit( EXIT_FAILURE ) ;
            }
            sscanf( argv[i] , "%d" , &global_grid_size ) ;
            if( ( global_grid_size % 2 ) != 0 ) {
              printf( "Grid size must be even\n" ) ;
              exit( EXIT_FAILURE ) ;
            }
            default_global_grid_size = "(user defined)" ;
            calculate = 0 ;
          } else {
            if( strcmp( argv[i] , "-angle_step" ) == 0 ) {
              i ++ ;
              if( ( i == argc ) || ( strncmp( argv[i] , "-" , 1 ) == 0 ) ) {
                printf( "Bad command line\n" ) ;
                exit( EXIT_FAILURE ) ;
              }
              sscanf( argv[i] , "%d" , &angle_step ) ;
              default_angle_step = "(user defined)" ;
            } else {
              if( strcmp( argv[i] , "-surface" ) == 0 ) {
                i ++ ;
                if( ( i == argc ) || ( strncmp( argv[i] , "-" , 1 ) == 0 ) ) {
                  printf( "Bad command line\n" ) ;
                  exit( EXIT_FAILURE ) ;
                }
                sscanf( argv[i] , "%f" , &surface ) ;
                default_surface = "(user defined)" ;
              } else {
                if( strcmp( argv[i] , "-internal" ) == 0 ) {
                  i ++ ;
                  if( i == argc ) {
                    printf( "Bad command line\n" ) ;
                    exit( EXIT_FAILURE ) ;
                  }
                  sscanf( argv[i] , "%f" , &internal_value ) ;
                  default_internal_value = "(user defined)" ;
                } else {
                  if( strcmp( argv[i] , "-noelec" ) == 0 ) {
                    electrostatics = 0 ;
                    default_electrostatics = "(user defined)" ;
                  } else {
                    if( strcmp( argv[i] , "-keep" ) == 0 ) {
                      i ++ ;
                      if( ( i == argc ) || ( strncmp( argv[i] , "-" , 1 ) == 0 ) ) {
                        printf( "Bad command line\n" ) ;
                        exit( EXIT_FAILURE ) ;
                      }
                      sscanf( argv[i] , "%d" , &keep_per_rotation ) ;
                      default_keep_per_rotation = "(user defined)" ;
                    } else {
                      if( strcmp( argv[i] , "-rescue" ) == 0 ) {
                        rescue = 1 ;
                      } else {
                        if( strcmp( argv[i] , "-calculate_grid" ) == 0 ) {
                          i ++ ;
                          if( ( i == argc ) || ( strncmp( argv[i] , "-" , 1 ) == 0 ) ) {
                            printf( "Bad command line\n" ) ;
                            exit( EXIT_FAILURE ) ;
                          }
                          calculate = 1 ;
                          default_global_grid_size = "(user defined calculated)" ;
                          sscanf( argv[i] , "%f" , &reverse_calculated_one_span ) ;
                        } else {
                          printf( "Bad command line\n" ) ;
                          exit( EXIT_FAILURE ) ;
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }

  }

/************/

  /* Rescue option */

  if( rescue == 1 ) {

    printf( "RESCUE mode\n" ) ;

    if( ( ftdock_file = fopen( "scratch_parameters.dat" , "r" ) ) == NULL ) {
      printf( "Could not open scratch_parameters.dat for reading.\nDying\n\n" ) ;
      exit( EXIT_FAILURE ) ;
    }

    calculate = 0 ;

    default_global_grid_size = "(read from rescue file)" ;
    default_angle_step = "(read from rescue file)" ;
    default_surface = "(read from rescue file)" ;
    default_internal_value = "(read from rescue file)" ;
    default_electrostatics = "(read from rescue file)" ;

    while( fgets( line_buffer , 99 , ftdock_file ) ) {

      if( strncmp( line_buffer , "Static molecule" , 15 ) == 0 ) sscanf( line_buffer , "Static molecule :: %s" , static_file_name ) ;
      if( strncmp( line_buffer , "Mobile molecule" , 15 ) == 0 ) sscanf( line_buffer , "Mobile molecule :: %s" , mobile_file_name ) ;
      if( strncmp( line_buffer , "Output file name" , 16 ) == 0 ) sscanf( line_buffer , "Output file name :: %s" , output_file_name ) ;
      if( strncmp( line_buffer , "Global grid size" , 16 ) == 0 ) sscanf( line_buffer , "Global grid size :: %d" , &global_grid_size ) ;
      if( strncmp( line_buffer , "Global search angle step" , 24 ) == 0 ) sscanf( line_buffer , "Global search angle step :: %d" , &angle_step ) ;
      if( strncmp( line_buffer , "Global surface thickness" , 24 ) == 0 ) sscanf( line_buffer , "Global surface thickness :: %f" , &surface ) ;
      if( strncmp( line_buffer , "Global internal deterrent value" , 31 ) == 0 ) sscanf( line_buffer , "Global internal deterrent value :: %f" , &internal_value ) ;
      if( strncmp( line_buffer , "Electrostatics                     ::     on" , 44 ) == 0 ) electrostatics = 1 ;    
      if( strncmp( line_buffer , "Electrostatics                     ::    off" , 44 ) == 0 ) electrostatics = 0 ;    
      if( strncmp( line_buffer , "Global keep per rotation" , 25 ) == 0 ) sscanf( line_buffer , "Global keep per rotation :: %d" , &keep_per_rotation ) ;

    }

    fclose( ftdock_file ) ;

    if( ( ftdock_file = fopen( "scratch_scores.dat" , "r" ) ) == NULL ) {
      printf( "Could not open scratch_scores.dat for reading.\nDying\n\n" ) ;
      exit( EXIT_FAILURE ) ;
    }

    fgets( line_buffer , 99 , ftdock_file ) ;

    while( fgets( line_buffer , 99 , ftdock_file ) ) {

      sscanf( line_buffer , "G_DATA %d " , &first_rotation ) ;

    }

    fclose( ftdock_file ) ;

    first_rotation ++ ;

    printf( "Will be starting from rotation %d\n" , first_rotation ) ;

/************/

  } else {

    first_rotation = 1 ;

  }

/************/

  /* Do these things first so that bad inputs will be caught soonest */

  /* Read in Structures from pdb files */
  Static_Structure = read_pdb_to_structure( static_file_name ) ;
  Mobile_Structure = read_pdb_to_structure( mobile_file_name ) ;

  if( Mobile_Structure.length > Static_Structure.length ) {
    printf( "WARNING\n" ) ;
    printf( "The mobile molecule has more residues than the static\n" ) ;
    printf( "Are you sure you have the correct molecules?\n" ) ;
    printf( "Continuing anyway\n" ) ;
  }
  
/************/

  /* Get angles */
  Angles = generate_global_angles( angle_step ) ;

  printf( "Total number of rotations is %d\n" , Angles.n ) ;

/************/

  /* Assign charges */

  if( electrostatics == 1 ) {
    printf( "Assigning charges\n" ) ;
    assign_charges( Static_Structure ) ;
    assign_charges( Mobile_Structure ) ;
  }

/************/

  /* Store new structures centered on Origin */

  Origin_Static_Structure = translate_structure_onto_origin( Static_Structure ) ;
  Origin_Mobile_Structure = translate_structure_onto_origin( Mobile_Structure ) ;

  /* Free some memory */

  for( i = 1 ; i <= Static_Structure.length ; i ++ ) {
    fftwf_free( Static_Structure.Residue[i].Atom ) ;
  }
  fftwf_free( Static_Structure.Residue ) ;

  for( i = 1 ; i <= Mobile_Structure.length ; i ++ ) {
    fftwf_free( Mobile_Structure.Residue[i].Atom ) ;
  }
  fftwf_free( Mobile_Structure.Residue ) ;

/************/

  /* Calculate Grid stuff */

  grid_span = total_span_of_structures( Origin_Static_Structure , Origin_Mobile_Structure ) ;

  if( calculate == 1 ) {
    printf( "Using automatic calculation for grid size\n" ) ;
    global_grid_size = (int)( grid_span / reverse_calculated_one_span ) ;
    if( ( global_grid_size % 2 ) != 0 ) global_grid_size ++ ;
  }

  one_span = grid_span / (float)global_grid_size ;

  printf( "Span = %.3f angstroms\n" , grid_span ) ;
  printf( "Grid size = %d\n" , global_grid_size ) ;
  printf( "Each Grid cube = %.5f angstroms\n" , one_span ) ;

/************/

  /* Memory Allocation */

  if( ( Scores = ( struct Score * ) fftwf_malloc ( ( keep_per_rotation + 2 ) * sizeof( struct Score ) ) ) == NULL ) {
    GENERAL_MEMORY_PROBLEM
  }

  if(
    ( ( static_grid = ( float * ) fftwf_malloc
     ( global_grid_size * global_grid_size * ( 2 * ( global_grid_size / 2 + 1 ) ) * sizeof( float ) ) ) == NULL )
    ||
    ( ( mobile_grid = ( float * ) fftwf_malloc
     ( global_grid_size * global_grid_size * ( 2 * ( global_grid_size / 2 + 1 ) ) * sizeof( float ) ) ) == NULL )
    ||
    ( ( convoluted_grid = ( float * ) fftwf_malloc
     ( global_grid_size * global_grid_size * ( 2 * ( global_grid_size / 2 + 1 ) ) * sizeof( float ) ) ) == NULL )
    ) {
    printf( "Not enough memory for surface grids\nUse (sensible) smaller grid size\nDying\n\n" ) ;
    exit( EXIT_FAILURE ) ;
  }

  static_fsg = ( fftwf_complex * ) static_grid ;
  mobile_fsg = ( fftwf_complex * ) mobile_grid ;
  multiple_fsg = ( fftwf_complex * ) convoluted_grid ;

  if( electrostatics == 1 ) {

    if(
      ( ( static_elec_grid = ( float * ) fftwf_malloc
       ( global_grid_size * global_grid_size * ( 2 * ( global_grid_size / 2 + 1 ) ) * sizeof( float ) ) ) == NULL )
      ||
      ( ( mobile_elec_grid = ( float * ) fftwf_malloc
       ( global_grid_size * global_grid_size * ( 2 * ( global_grid_size / 2 + 1 ) ) * sizeof( float ) ) ) == NULL )
      ||
      ( ( convoluted_elec_grid = ( float * ) fftwf_malloc
       ( global_grid_size * global_grid_size * ( 2 * ( global_grid_size / 2 + 1 ) ) * sizeof( float ) ) ) == NULL )
      ) {
      printf( "Not enough memory for electrostatic grids\nSwitch off electrostatics or use (sensible) smaller grid size\nDying\n\n" ) ; 
      exit( EXIT_FAILURE ) ;
    } else {
      /* all ok */
      printf( "Electrostatics are on\n" ) ;
    }

    static_elec_fsg = ( fftwf_complex * ) static_elec_grid ;
    mobile_elec_fsg = ( fftwf_complex * ) mobile_elec_grid ;
    multiple_elec_fsg = ( fftwf_complex * ) convoluted_elec_grid ;

  }

/************/

  /* Create FFTW plans */

  printf( "Creating plans\n" ) ;
  plan_static_grid = fftwf_plan_dft_r2c_3d(global_grid_size,
					   global_grid_size,
					   global_grid_size,
					   static_grid,
					   static_grid,
					   FFTW_MEASURE);

  plan_static_elec_grid = fftwf_plan_dft_r2c_3d(global_grid_size,
						global_grid_size,
						global_grid_size,
						static_elec_grid,
						static_elec_grid,
						FFTW_MEASURE);
  
  plan_mobile_grid = fftwf_plan_dft_r2c_3d(global_grid_size,
					   global_grid_size,
					   global_grid_size,
					   mobile_grid,
					   mobile_grid,
					   FFTW_MEASURE);

  plan_mobile_elec_grid = fftwf_plan_dft_r2c_3d(global_grid_size,
						global_grid_size,
						global_grid_size,
						mobile_elec_grid,
						mobile_elec_grid,
						FFTW_MEASURE);
  
  plan_multiple_fsg = fftwf_plan_dft_c2r_3d(global_grid_size,
					    global_grid_size,
					    global_grid_size,
					    multiple_fsg,
					    multiple_fsg,
					    FFTW_MEASURE);
  
  plan_multiple_elec_fsg = fftwf_plan_dft_c2r_3d(global_grid_size,
						 global_grid_size,
						 global_grid_size,
						 multiple_elec_fsg,
						 multiple_elec_fsg,
						 FFTW_MEASURE);
/************/

  printf( "PCA TIMING SHOULD start here\n");
  
  start_timing();

  printf( "Setting up Static Structure\n" ) ;

  /* Discretise and surface the Static Structure (need do only once) */
  discretise_structure( Origin_Static_Structure , grid_span , global_grid_size , static_grid ) ;
  printf( "  surfacing grid\n" ) ;
  surface_grid( grid_span , global_grid_size , static_grid , surface , internal_value ) ;

  /* Calculate electic field at all grid nodes (need do only once) */
  if( electrostatics == 1 ) {
    electric_field( Origin_Static_Structure , grid_span , global_grid_size , static_elec_grid ) ;
    electric_field_zero_core( global_grid_size , static_elec_grid , static_grid , internal_value ) ;
  }

  /* Fourier Transform the static grids (need do only once) */
  printf( "  one time forward FFT calculations\n" ) ;
  fftwf_execute(plan_static_grid);
  if( electrostatics == 1 ) {
    fftwf_execute(plan_static_elec_grid);
  }

  printf( "  done\n" ) ;

/************/

  /* Store paramaters in case of rescue */

  if( ( ftdock_file = fopen( "scratch_parameters.dat" , "w" ) ) == NULL ) {
    printf( "Could not open scratch_parameters.dat for writing.\nDying\n\n" ) ;
    exit( EXIT_FAILURE ) ;
  }

  fprintf( ftdock_file, "\nGlobal Scan\n" ) ;

  fprintf( ftdock_file, "\nCommand line controllable values\n" ) ;
  fprintf( ftdock_file, "Static molecule                    :: %s\n" , static_file_name ) ;
  fprintf( ftdock_file, "Mobile molecule                    :: %s\n" , mobile_file_name ) ;
  fprintf( ftdock_file, "Output file name                   :: %s\n" , output_file_name ) ;
  fprintf( ftdock_file, "\n" ) ;
  fprintf( ftdock_file, "Global grid size                   :: %6d      %s\n" , global_grid_size , default_global_grid_size ) ;
  fprintf( ftdock_file, "Global search angle step           :: %6d      %s\n" , angle_step , default_angle_step ) ;
  fprintf( ftdock_file, "Global surface thickness           :: %9.2f   %s\n" , surface , default_surface ) ;
  fprintf( ftdock_file, "Global internal deterrent value    :: %9.2f   %s\n" , internal_value , default_internal_value ) ;
  if( electrostatics == 1 ) {
    fprintf( ftdock_file, "Electrostatics                     ::     on      %s\n" , default_electrostatics ) ;
  } else {
    fprintf( ftdock_file, "Electrostatics                     ::    off      %s\n" , default_electrostatics ) ;
  }
  fprintf( ftdock_file, "Global keep per rotation           :: %6d      %s\n" , keep_per_rotation , default_keep_per_rotation ) ;

  fprintf( ftdock_file, "\nCalculated values\n" ) ;
  fprintf( ftdock_file, "Global rotations                   :: %6d\n" , Angles.n ) ;
  fprintf( ftdock_file, "Global total span (angstroms)      :: %10.3f\n" , grid_span ) ;
  fprintf( ftdock_file, "Global grid cell span (angstroms)  :: %10.3f\n" , one_span ) ;

  fclose( ftdock_file ) ;

/************/

  /* Main program loop */

  max_es_value = 0 ;

  printf( "Starting main loop through the rotations\n" ) ;

  /* PCA: start comment
     for( rotation = first_rotation ; rotation <= Angles.n ; rotation ++ ) {
   * PCA: end comment 
   */
  for( rotation = first_rotation ; rotation <= 10/*Angles.n*/ ; rotation ++ ) {

    printf( "." ) ; 

    if( ( rotation % 50 ) == 0 ) printf( "\nRotation number %5d\n" , rotation ) ;

    /* Rotate Mobile Structure */
    Rotated_at_Origin_Mobile_Structure =
     rotate_structure( Origin_Mobile_Structure , (int)Angles.z_twist[rotation] , (int)Angles.theta[rotation] , (int)Angles.phi[rotation] ) ;

    /* Discretise the rotated Mobile Structure */
    discretise_structure( Rotated_at_Origin_Mobile_Structure , grid_span , global_grid_size , mobile_grid ) ;

    /* Electic point charge approximation onto grid calculations ( quicker than filed calculations by a long way! ) */
    if( electrostatics == 1 ) {
      electric_point_charge( Rotated_at_Origin_Mobile_Structure , grid_span , global_grid_size , mobile_elec_grid ) ;
    }

    /* Forward Fourier Transforms */
    fftwf_execute(plan_mobile_grid);
    if( electrostatics == 1 ) {
      fftwf_execute(plan_mobile_elec_grid);
    }

/************/

    /* Do convolution of the two sets of grids
       convolution is equivalent to multiplication of the complex conjugate of one
       fourier grid with other (raw) one
       hence the sign changes from a normal complex number multiplication
    */

    for( fx = 0 ; fx < global_grid_size ; fx ++ ) {
      for( fy = 0 ; fy < global_grid_size ; fy ++ ) {
        for( fz = 0 ; fz < global_grid_size/2 + 1 ; fz ++ ) {

          fxyz = fz + ( global_grid_size/2 + 1 ) * ( fy + global_grid_size * fx ) ;

          multiple_fsg[fxyz][0] =
           static_fsg[fxyz][0] * mobile_fsg[fxyz][0] + static_fsg[fxyz][1] * mobile_fsg[fxyz][1] ;
          multiple_fsg[fxyz][1] =
           static_fsg[fxyz][1] * mobile_fsg[fxyz][0] - static_fsg[fxyz][0] * mobile_fsg[fxyz][1] ;
           
          if( electrostatics == 1 ) {
            multiple_elec_fsg[fxyz][0] =
             static_elec_fsg[fxyz][0] * mobile_elec_fsg[fxyz][0] + static_elec_fsg[fxyz][1] * mobile_elec_fsg[fxyz][1] ;
            multiple_elec_fsg[fxyz][1] =
             static_elec_fsg[fxyz][1] * mobile_elec_fsg[fxyz][0] - static_elec_fsg[fxyz][0] * mobile_elec_fsg[fxyz][1] ;
          }

        }
      }
    }

    /* Reverse Fourier Transform */
    fftwf_execute(plan_multiple_fsg);
    if( electrostatics == 1 ) {
      fftwf_execute(plan_multiple_elec_fsg);
    }

/************/

    /* Get best scores */

    for( i = 0 ; i < keep_per_rotation ; i ++ ) {

      Scores[i].score = 0 ;
      Scores[i].rpscore = 0.0 ;
      Scores[i].coord[1] = 0 ;
      Scores[i].coord[2] = 0 ;
      Scores[i].coord[3] = 0 ;

    }

    for( x = 0 ; x < global_grid_size ; x ++ ) {
      fx = x ;
      if( fx > ( global_grid_size / 2 ) ) fx -= global_grid_size ;

      for( y = 0 ; y < global_grid_size ; y ++ ) {
        fy = y ;
        if( fy > ( global_grid_size / 2 ) ) fy -= global_grid_size ;

        for( z = 0 ; z < global_grid_size ; z ++ ) {
          fz = z ;
          if( fz > ( global_grid_size / 2 ) ) fz -= global_grid_size ;

          xyz = z + ( 2 * ( global_grid_size / 2 + 1 ) ) * ( y + global_grid_size * x ) ;

          if( ( electrostatics == 0 ) || ( convoluted_elec_grid[xyz] < 0 ) ) {

            /* Scale factor from FFTs */
            if( (int)convoluted_grid[xyz] != 0 ) {
              convoluted_grid[xyz] /= ( global_grid_size * global_grid_size * global_grid_size ) ;
            }

            if( (int)convoluted_grid[xyz] > Scores[keep_per_rotation-1].score ) {

              i = keep_per_rotation - 2 ;

              while( ( (int)convoluted_grid[xyz] > Scores[i].score ) && ( i >= 0 ) ) {
                Scores[i+1].score    = Scores[i].score ;
                Scores[i+1].rpscore  = Scores[i].rpscore ;
                Scores[i+1].coord[1] = Scores[i].coord[1] ;
                Scores[i+1].coord[2] = Scores[i].coord[2] ;
                Scores[i+1].coord[3] = Scores[i].coord[3] ;
                i -- ;
              }

              Scores[i+1].score    = (int)convoluted_grid[xyz] ;
              if( ( electrostatics != 0 ) && ( convoluted_elec_grid[xyz] < 0.1 ) ) {
                Scores[i+1].rpscore  = (float)convoluted_elec_grid[xyz] ;
              } else {
                Scores[i+1].rpscore  = (float)0 ;
              }
              Scores[i+1].coord[1] = fx ;
              Scores[i+1].coord[2] = fy ;
              Scores[i+1].coord[3] = fz ;

            }

          }

        }
      }
    }

    if( rotation == 1 ) {
      if( ( ftdock_file = fopen( "scratch_scores.dat" , "w" ) ) == NULL ) {
        printf( "Could not open scratch_scores.dat for writing.\nDying\n\n" ) ;
        exit( EXIT_FAILURE ) ;
      }
    } else {
      if( ( ftdock_file = fopen( "scratch_scores.dat" , "a" ) ) == NULL ) {
        printf( "Could not open scratch_scores.dat for writing.\nDying\n\n" ) ;
        exit( EXIT_FAILURE ) ;
      }
    }

    for( i = 0 ; i < keep_per_rotation ; i ++ ) {

      max_es_value = min( max_es_value , Scores[i].rpscore ) ;
      /* PCA: start comment

      fprintf( ftdock_file, "G_DATA %6d   %6d    %7d       %.0f      %4d %4d %4d      %4d%4d%4d\n" ,
                rotation , 0 , Scores[i].score , (double)Scores[i].rpscore , Scores[i].coord[1] , Scores[i].coord[2] , Scores[i].coord[3 ] ,
                 Angles.z_twist[rotation] , Angles.theta[rotation]  , Angles.phi[rotation] ) ;

       * PCA: Stop comment
       */
      fprintf( stdout, "G_DATA %6d   %6d    %7d       %4d %4d %4d      %4d%4d%4d\n" ,
                rotation , 0 , Scores[i].score , Scores[i].coord[1] , Scores[i].coord[2] , Scores[i].coord[3 ] ,
                 Angles.z_twist[rotation] , Angles.theta[rotation]  , Angles.phi[rotation] ) ;

    }

    fclose( ftdock_file ) ;

    /* Free some memory */
    for( i = 1 ; i <= Rotated_at_Origin_Mobile_Structure.length ; i ++ ) {
      fftwf_free( Rotated_at_Origin_Mobile_Structure.Residue[i].Atom ) ;
    }
    fftwf_free( Rotated_at_Origin_Mobile_Structure.Residue ) ;

  }

  /* Finished main loop */

/************/

  /* Free the memory */

  fftwf_destroy_plan(plan_static_grid);
  fftwf_destroy_plan(plan_static_elec_grid);
  fftwf_destroy_plan(plan_mobile_grid);
  fftwf_destroy_plan(plan_mobile_elec_grid); 
  fftwf_destroy_plan(plan_multiple_fsg);
  fftwf_destroy_plan(plan_multiple_elec_fsg);

  fftwf_free( static_grid ) ;
  fftwf_free( mobile_grid ) ;
  fftwf_free( convoluted_grid ) ;

  if( electrostatics == 1 ) {
    fftwf_free( static_elec_grid ) ;
    fftwf_free( mobile_elec_grid ) ;
    fftwf_free( convoluted_elec_grid ) ;
  }

  for( i = 1 ; i <= Origin_Static_Structure.length ; i ++ ) {
    fftwf_free( Origin_Static_Structure.Residue[i].Atom ) ;
  }
  fftwf_free( Origin_Static_Structure.Residue ) ;

  for( i = 1 ; i <= Origin_Mobile_Structure.length ; i ++ ) {
    fftwf_free( Origin_Mobile_Structure.Residue[i].Atom ) ;
  }
  fftwf_free( Origin_Mobile_Structure.Residue ) ;

      /* PCA: Finishing programm here*/ 
      printf("PCA TIMING SHOULD stop here\n");
      
      end_timing();
      
      printf("PCA STOPS HERE\n");
      return 0;
      /* PCA: */


/************/

  /* Read in all the scores */

  printf( "\nReloading all the scores\n" ) ;

  if( ( ftdock_file = fopen( "scratch_scores.dat" , "r" ) ) == NULL ) {
    printf( "Could not open scratch_scores.dat for reading.\nDying\n\n" ) ;
    exit( EXIT_FAILURE ) ;
  }

  if( ( Scores = ( struct Score * ) realloc ( Scores , ( 1 + keep_per_rotation ) * Angles.n * sizeof( struct Score ) ) ) == NULL ) {
    printf( "Not enough memory left for storing scores\nProbably keeping too many per rotation\nDying\n\n" ) ;
    exit( EXIT_FAILURE ) ;
  }

  kept_scores = 0 ;

  while( fgets( line_buffer , 99 , ftdock_file ) ) {

    sscanf( line_buffer , "G_DATA %d %d %d %f  %d %d %d  %d %d %d" , &id , &id2 , &SCscore , &RPscore ,
                                                                     &x , &y , &z , &z_twist , &theta , &phi ) ;

    Scores[kept_scores].score    = SCscore ;
    Scores[kept_scores].rpscore  = RPscore ;
    Scores[kept_scores].coord[1] = x ;
    Scores[kept_scores].coord[2] = y ;
    Scores[kept_scores].coord[3] = z ;
    Scores[kept_scores].angle[1] = z_twist ;
    Scores[kept_scores].angle[2] = theta ;
    Scores[kept_scores].angle[3] = phi ;

    kept_scores ++ ;

  }

  fclose( ftdock_file ) ;

  kept_scores -- ;

  qsort_scores( Scores , 0 , kept_scores ) ;

/************/

  /* Writing data file */

  if( ( ftdock_file = fopen( output_file_name , "w" ) ) == NULL ) {
    printf( "Could not open %s for writing.\nDying\n\n" , output_file_name ) ;
    exit( EXIT_FAILURE ) ;
  }

  fprintf( ftdock_file, "FTDOCK data file\n" ) ;

  fprintf( ftdock_file, "\nGlobal Scan\n" ) ;

  fprintf( ftdock_file, "\nCommand line controllable values\n" ) ;
  fprintf( ftdock_file, "Static molecule                    :: %s\n" , static_file_name ) ;
  fprintf( ftdock_file, "Mobile molecule                    :: %s\n" , mobile_file_name ) ;
  fprintf( ftdock_file, "\n" ) ;
  fprintf( ftdock_file, "Global grid size                   :: %6d      %s\n" , global_grid_size , default_global_grid_size ) ;
  fprintf( ftdock_file, "Global search angle step           :: %6d      %s\n" , angle_step , default_angle_step ) ;
  fprintf( ftdock_file, "Global surface thickness           :: %9.2f   %s\n" , surface , default_surface ) ;
  fprintf( ftdock_file, "Global internal deterrent value    :: %9.2f   %s\n" , internal_value , default_internal_value ) ;
  if( electrostatics == 1 ) {
    fprintf( ftdock_file, "Electrostatics                     ::     on      %s\n" , default_electrostatics ) ;
  } else {
    fprintf( ftdock_file, "Electrostatics                     ::    off      %s\n" , default_electrostatics ) ;
  }
  fprintf( ftdock_file, "Global keep per rotation           :: %6d      %s\n" , keep_per_rotation , default_keep_per_rotation ) ;

  fprintf( ftdock_file, "\nCalculated values\n" ) ;
  fprintf( ftdock_file, "Global rotations                   :: %6d\n" , Angles.n ) ;
  fprintf( ftdock_file, "Global total span (angstroms)      :: %10.3f\n" , grid_span ) ;
  fprintf( ftdock_file, "Global grid cell span (angstroms)  :: %10.3f\n" , one_span ) ;

  fprintf( ftdock_file, "\nData\n" ) ;
  fprintf( ftdock_file , "Type       ID    prvID    SCscore        ESratio         Coordinates            Angles\n\n" ) ;

  if( electrostatics == 1 ) {

    for( i = 0 ; i <= min( kept_scores , ( NUMBER_TO_KEEP - 1 ) ) ; i ++ ) {

      fprintf( ftdock_file, "G_DATA %6d   %6d    %7d       %8.3f      %4d %4d %4d      %4d%4d%4d\n" ,
               i + 1 , 0 , Scores[i].score , 100 * ( Scores[i].rpscore / max_es_value ) ,
               Scores[i].coord[1] , Scores[i].coord[2] , Scores[i].coord[3] ,
               Scores[i].angle[1] , Scores[i].angle[2] , Scores[i].angle[3] ) ;

    }

  } else {

    for( i = 0 ; i <= min( kept_scores , ( NUMBER_TO_KEEP - 1 ) ) ; i ++ ) {

      fprintf( ftdock_file, "G_DATA %6d   %6d    %7d       %8.3f      %4d %4d %4d      %4d%4d%4d\n" ,
               i + 1 , 0 , Scores[i].score , 0.0 ,
               Scores[i].coord[1] , Scores[i].coord[2] , Scores[i].coord[3] ,
               Scores[i].angle[1] , Scores[i].angle[2] , Scores[i].angle[3] ) ;

    }

  }

  fclose( ftdock_file ) ;
    
/************/

  printf( "\n\nFinished\n\n" ) ;

  return( 0 ) ;

} /* end main */
Exemplo n.º 16
0
void osd_work_queue_free(osd_work_queue *queue)
{
	// if we have threads, clean them up
	if (queue->thread != NULL)
	{
		int threadnum;

		// stop the timer for "waittime" on the main thread
		if (queue->flags & WORK_QUEUE_FLAG_MULTI)
		{
			end_timing(queue->thread[queue->threads].waittime);
		}

		// signal all the threads to exit
		atomic_exchange32(&queue->exiting, TRUE);
		for (threadnum = 0; threadnum < queue->threads; threadnum++)
		{
			work_thread_info *thread = &queue->thread[threadnum];
			if (thread->wakeevent != NULL)
				osd_event_set(thread->wakeevent);
		}

		// wait for all the threads to go away
		for (threadnum = 0; threadnum < queue->threads; threadnum++)
		{
			work_thread_info *thread = &queue->thread[threadnum];

			// block on the thread going away, then close the handle
			if (thread->handle != NULL)
			{
				osd_thread_wait_free(thread->handle);
			}

			// clean up the wake event
			if (thread->wakeevent != NULL)
				osd_event_free(thread->wakeevent);
		}

#if KEEP_STATISTICS
		int allocthreadnum;
		if (queue->flags & WORK_QUEUE_FLAG_MULTI)
			allocthreadnum = queue->threads + 1;
		else
			allocthreadnum = queue->threads;

		// output per-thread statistics
		for (threadnum = 0; threadnum < allocthreadnum; threadnum++)
		{
			work_thread_info *thread = &queue->thread[threadnum];
			osd_ticks_t total = thread->runtime + thread->waittime + thread->spintime;
			printf("Thread %d:  items=%9d run=%5.2f%% (%5.2f%%)  spin=%5.2f%%  wait/other=%5.2f%% total=%9d\n",
					threadnum, thread->itemsdone,
					(double)thread->runtime * 100.0 / (double)total,
					(double)thread->actruntime * 100.0 / (double)total,
					(double)thread->spintime * 100.0 / (double)total,
					(double)thread->waittime * 100.0 / (double)total,
					(UINT32) total);
		}
#endif
	}

	// free the list
	if (queue->thread != NULL)
		osd_free(queue->thread);

	// free all the events
	if (queue->doneevent != NULL)
		osd_event_free(queue->doneevent);

	// free all items in the free list
	while (queue->free != NULL)
	{
		osd_work_item *item = (osd_work_item *)queue->free;
		queue->free = item->next;
		if (item->event != NULL)
			osd_event_free(item->event);
		osd_free(item);
	}

	// free all items in the active list
	while (queue->list != NULL)
	{
		osd_work_item *item = (osd_work_item *)queue->list;
		queue->list = item->next;
		if (item->event != NULL)
			osd_event_free(item->event);
		osd_free(item);
	}

#if KEEP_STATISTICS
	printf("Items queued   = %9d\n", queue->itemsqueued);
	printf("SetEvent calls = %9d\n", queue->setevents);
	printf("Extra items    = %9d\n", queue->extraitems);
	printf("Spin loops     = %9d\n", queue->spinloops);
#endif

	osd_scalable_lock_free(queue->lock);
	// free the queue itself
	osd_free(queue);
}
Exemplo n.º 17
0
osd_work_item *osd_work_item_queue_multiple(osd_work_queue *queue, osd_work_callback callback, INT32 numitems, void *parambase, INT32 paramstep, UINT32 flags)
{
	osd_work_item *itemlist = NULL, *lastitem = NULL;
	osd_work_item **item_tailptr = &itemlist;
	INT32 lockslot;
	int itemnum;

	// loop over items, building up a local list of work
	for (itemnum = 0; itemnum < numitems; itemnum++)
	{
		osd_work_item *item;

		// first allocate a new work item; try the free list first
		INT32 lockslot = osd_scalable_lock_acquire(queue->lock);
		do
		{
			item = (osd_work_item *)queue->free;
		} while (item != NULL && compare_exchange_ptr((PVOID volatile *)&queue->free, item, item->next) != item);
		osd_scalable_lock_release(queue->lock, lockslot);

		// if nothing, allocate something new
		if (item == NULL)
		{
			// allocate the item
			item = (osd_work_item *)osd_malloc(sizeof(*item));
			if (item == NULL)
				return NULL;
			item->event = NULL;
			item->queue = queue;
			item->done = FALSE;
		}
		else
		{
			atomic_exchange32(&item->done, FALSE); // needs to be set this way to prevent data race/usage of uninitialized memory on Linux
		}

		// fill in the basics
		item->next = NULL;
		item->callback = callback;
		item->param = parambase;
		item->result = NULL;
		item->flags = flags;

		// advance to the next
		lastitem = item;
		*item_tailptr = item;
		item_tailptr = &item->next;
		parambase = (UINT8 *)parambase + paramstep;
	}

	// enqueue the whole thing within the critical section
	lockslot = osd_scalable_lock_acquire(queue->lock);
	*queue->tailptr = itemlist;
	queue->tailptr = item_tailptr;
	osd_scalable_lock_release(queue->lock, lockslot);

	// increment the number of items in the queue
	atomic_add32(&queue->items, numitems);
	add_to_stat(&queue->itemsqueued, numitems);

	// look for free threads to do the work
	if (queue->livethreads < queue->threads)
	{
		int threadnum;

		// iterate over all the threads
		for (threadnum = 0; threadnum < queue->threads; threadnum++)
		{
			work_thread_info *thread = &queue->thread[threadnum];

			// if this thread is not active, wake him up
			if (!thread->active)
			{
				osd_event_set(thread->wakeevent);
				add_to_stat(&queue->setevents, 1);

				// for non-shared, the first one we find is good enough
				if (--numitems == 0)
					break;
			}
		}
	}

	// if no threads, run the queue now on this thread
	if (queue->threads == 0)
	{
		end_timing(queue->thread[0].waittime);
		worker_thread_process(queue, &queue->thread[0]);
		begin_timing(queue->thread[0].waittime);
	}
	// only return the item if it won't get released automatically
	return (flags & WORK_ITEM_FLAG_AUTO_RELEASE) ? NULL : lastitem;
}
Exemplo n.º 18
0
static void worker_thread_process(osd_work_queue *queue, work_thread_info *thread)
{
	int threadid = thread->id;

	begin_timing(thread->runtime);

	// loop until everything is processed
	while (true)
	{
		osd_work_item *item = nullptr;

		bool end_loop = false;

		// use a critical section to synchronize the removal of items
		{
			std::lock_guard<std::mutex> lock(queue->lock);

			if (queue->list.load() == nullptr)
			{
				end_loop = true;
			}
			else
			{
				// pull the item from the queue
				item = (osd_work_item *)queue->list;
				if (item != nullptr)
				{
					queue->list = item->next;
					if (queue->list.load() == nullptr)
						queue->tailptr = (osd_work_item **)&queue->list;
				}
			}
		}

		if (end_loop)
			break;

		// process non-NULL items
		if (item != nullptr)
		{
			// call the callback and stash the result
			begin_timing(thread->actruntime);
			item->result = (*item->callback)(item->param, threadid);
			end_timing(thread->actruntime);

			// decrement the item count after we are done
			--queue->items;
			item->done = TRUE;
			add_to_stat(thread->itemsdone, 1);

			// if it's an auto-release item, release it
			if (item->flags & WORK_ITEM_FLAG_AUTO_RELEASE)
				osd_work_item_release(item);

			// set the result and signal the event
			else
			{
				std::lock_guard<std::mutex> lock(queue->lock);

				if (item->event != nullptr)
				{
					item->event->set();
					add_to_stat(item->queue.setevents, 1);
				}
			}

			// if we removed an item and there's still work to do, bump the stats
			if (queue_has_list_items(queue))
				add_to_stat(queue->extraitems, 1);
		}
	}

	// we don't need to set the doneevent for multi queues because they spin
	if (queue->waiting)
	{
		queue->doneevent.set();
		add_to_stat(queue->setevents, 1);
	}

	end_timing(thread->runtime);
}
Exemplo n.º 19
0
static void worker_thread_process(osd_work_queue *queue, work_thread_info *thread)
{
	int threadid = thread - queue->thread;

	begin_timing(thread->runtime);

	// loop until everything is processed
	while (true)
	{
		osd_work_item *item = NULL;

		bool end_loop = false;

		// use a critical section to synchronize the removal of items
		{
			INT32 lockslot = osd_scalable_lock_acquire(queue->lock);
			if (queue->list == NULL)
			{
				end_loop = true;
			}
			else
			{
				// pull the item from the queue
				item = (osd_work_item *)queue->list;
				if (item != NULL)
				{
					queue->list = item->next;
					if (queue->list == NULL)
						queue->tailptr = (osd_work_item **)&queue->list;
				}
			}
			osd_scalable_lock_release(queue->lock, lockslot);
		}

		if (end_loop)
			break;

		// process non-NULL items
		if (item != NULL)
		{
			// call the callback and stash the result
			begin_timing(thread->actruntime);
			item->result = (*item->callback)(item->param, threadid);
			end_timing(thread->actruntime);

			// decrement the item count after we are done
			atomic_decrement32(&queue->items);
			atomic_exchange32(&item->done, TRUE);
			add_to_stat(&thread->itemsdone, 1);

			// if it's an auto-release item, release it
			if (item->flags & WORK_ITEM_FLAG_AUTO_RELEASE)
				osd_work_item_release(item);

			// set the result and signal the event
			else
			{
				INT32 lockslot = osd_scalable_lock_acquire(item->queue->lock);
				if (item->event != NULL)
				{
					osd_event_set(item->event);
					add_to_stat(&item->queue->setevents, 1);
				}
				osd_scalable_lock_release(item->queue->lock, lockslot);
			}

			// if we removed an item and there's still work to do, bump the stats
			if (queue_has_list_items(queue))
				add_to_stat(&queue->extraitems, 1);
		}
	}

	// we don't need to set the doneevent for multi queues because they spin
	if (queue->waiting)
	{
		osd_event_set(queue->doneevent);
		add_to_stat(&queue->setevents, 1);
	}

	end_timing(thread->runtime);
}
Exemplo n.º 20
0
int main()
{
    int i;
    interface_init();
    
    start_timing();
    print_value("Timestamp bias", end_timing());
    
    for (i = 0; i < TESTCASES1_COUNT; i++)
    {
        fix16_t input = testcases1[i].a;
        fix16_t result;
        fix16_t expected = testcases1[i].sqrt;
        MEASURE(sqrt_cycles, result = fix16_sqrt(input));
        
        if (input > 0 && delta(result, expected) > max_delta)
        {
            print_value("Failed SQRT, i", i);
            print_value("Failed SQRT, input", input);
            print_value("Failed SQRT, output", result);
            print_value("Failed SQRT, expected", expected);
        }
        
        expected = testcases1[i].exp;
        MEASURE(exp_cycles, result = fix16_exp(input));
        
        if (delta(result, expected) > 400)
        {
            print_value("Failed EXP, i", i);
            print_value("Failed EXP, input", input);
            print_value("Failed EXP, output", result);
            print_value("Failed EXP, expected", expected);
        }
    }
    PRINT(sqrt_cycles, "fix16_sqrt");
    PRINT(exp_cycles, "fix16_exp");

    for (i = 0; i < TESTCASES2_COUNT; i++)
    {
        fix16_t a = testcases2[i].a;
        fix16_t b = testcases2[i].b;
        volatile fix16_t result;
        
        fix16_t expected = testcases2[i].add;
        MEASURE(add_cycles, result = fix16_add(a, b));
        if (delta(result, expected) > max_delta)
        {
            print_value("Failed ADD, i", i);
            print_value("Failed ADD, a", a);
            print_value("Failed ADD, b", b);
            print_value("Failed ADD, output", result);
            print_value("Failed ADD, expected", expected);
        }
        
        expected = testcases2[i].sub;
        MEASURE(sub_cycles, result = fix16_sub(a, b));
        if (delta(result, expected) > max_delta)
        {
            print_value("Failed SUB, i", i);
            print_value("Failed SUB, a", a);
            print_value("Failed SUB, b", b);
            print_value("Failed SUB, output", result);
            print_value("Failed SUB, expected", expected);
        }
        
        expected = testcases2[i].mul;
        MEASURE(mul_cycles, result = fix16_mul(a, b));
        if (delta(result, expected) > max_delta)
        {
            print_value("Failed MUL, i", i);
            print_value("Failed MUL, a", a);
            print_value("Failed MUL, b", b);
            print_value("Failed MUL, output", result);
            print_value("Failed MUL, expected", expected);
        }
        
        if (b != 0)
        {
            expected = testcases2[i].div;
            MEASURE(div_cycles, result = fix16_div(a, b));
            if (delta(result, expected) > max_delta)
            {
                print_value("Failed DIV, i", i);
                print_value("Failed DIV, a", a);
                print_value("Failed DIV, b", b);
                print_value("Failed DIV, output", result);
                print_value("Failed DIV, expected", expected);
            }
        }
    }
    PRINT(add_cycles, "fix16_add");
    PRINT(sub_cycles, "fix16_sub");
    PRINT(mul_cycles, "fix16_mul");
    PRINT(div_cycles, "fix16_div");
    
    /* Compare with floating point performance */
#ifndef NO_FLOAT
    for (i = 0; i < TESTCASES1_COUNT; i++)
    {
        float input = fix16_to_float(testcases1[i].a);
        volatile float result;
        MEASURE(float_sqrtf_cycles, result = sqrtf(input));
    }
    PRINT(float_sqrtf_cycles, "float sqrtf");
    
    for (i = 0; i < TESTCASES2_COUNT; i++)
    {
        float a = fix16_to_float(testcases2[i].a);
        float b = fix16_to_float(testcases2[i].b);
        volatile float result;
        MEASURE(float_add_cycles, result = a + b);
        MEASURE(float_sub_cycles, result = a - b);
        MEASURE(float_mul_cycles, result = a * b);
        
        if (b != 0)
        {
            MEASURE(float_div_cycles, result = a / b);
        }
    }
    PRINT(float_add_cycles, "float add");
    PRINT(float_sub_cycles, "float sub");
    PRINT(float_mul_cycles, "float mul");
    PRINT(float_div_cycles, "float div");
#endif    

    return 0;
}