<commit_before>/*
 *  Copyright 2005-2006 The Apache Software Foundation or its licensors, as applicable.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
/**
 * @author Intel, Evgueni Brevnov
 * @version $Revision: 1.1 $
 */

#include <stdlib.h>
#include <apr_thread_mutex.h>

#include "open/hythread.h"
#include "open/jthread.h"
#include "open/gc.h"
#include "open/thread_externals.h"

#include "jni.h"
#include "jni_direct.h"
#include "environment.h"
#include "classloader.h"
#include "compile.h"
#include "nogc.h"
#include "jni_utils.h"
#include "vm_stats.h"
#include "thread_dump.h"
#include "interpreter.h"

#define LOG_DOMAIN "vm.core.shutdown"
#include "cxxlog.h"

#define PROCESS_EXCEPTION(messageId, message) \
{ \
    LECHO(messageId, message << "Internal error: "); \
\
    if (jni_env->ExceptionCheck()== JNI_TRUE) \
    { \
        jni_env->ExceptionDescribe(); \
        jni_env->ExceptionClear(); \
    } \
\
    return JNI_ERR; \
} \

/**
 * Calls java.lang.System.execShutdownSequence() method.
 *
 * @param jni_env JNI environment of the current thread
 */
static jint exec_shutdown_sequence(JNIEnv * jni_env) {
    jclass system_class;
    jmethodID shutdown_method;

    assert(hythread_is_suspend_enabled());

    system_class = jni_env->FindClass("java/lang/System");
    if (jni_env->ExceptionCheck() == JNI_TRUE || system_class == NULL) {
        // This is debug message only. May appear when VM is already in shutdown stage.
        PROCESS_EXCEPTION(38, "{0}can't find java.lang.System class.");
    }

    shutdown_method = jni_env->GetStaticMethodID(system_class, "execShutdownSequence", "()V");
    if (jni_env->ExceptionCheck() == JNI_TRUE || shutdown_method == NULL) {
        PROCESS_EXCEPTION(39, "{0}can't find java.lang.System.execShutdownSequence() method.");
    }

    jni_env->CallStaticVoidMethod(system_class, shutdown_method);

    if (jni_env->ExceptionCheck() == JNI_TRUE) {
        PROCESS_EXCEPTION(40, "{0}java.lang.System.execShutdownSequence() method completed with an exception.");
    }
    return JNI_OK;
}

static void vm_shutdown_callback() {
    hythread_t   self_native;
    jthread      self_java;
    VM_thread *  self_vm;
    JNIEnv     * jni_env;
    Global_Env * vm_env;

    self_native = hythread_self();
    self_java = jthread_get_java_thread(self_native);
    self_vm = get_vm_thread(self_native);

    // Make sure the thread is still attached to the VM.
    if (self_java == NULL || self_vm == NULL) {
        return;
    }

    jni_env = jthread_get_JNI_env(self_java);
    vm_env = jni_get_vm_env(jni_env);

    // We need to be in suspend disabled state to be able to throw an exception.
    assert(!hythread_is_suspend_enabled());

    //hythread_suspend_disable();

    // Raise an exception. In shutdown stage it should cause entire stack unwinding.
    jthread_throw_exception_object(vm_env->java_lang_ThreadDeath);

    //hythread_suspend_enable();
}

/**
 * Stops running java threads by throwing an exception
 * up to the first native frame.
 *
 * @param[in] vm_env a global VM environment
 */
static void vm_shutdown_stop_java_threads(Global_Env * vm_env) {
    hythread_t self;
    hythread_t * running_threads;
    hythread_t native_thread;
    hythread_iterator_t it;
    VM_thread * vm_thread;
    int size;
    bool changed;
    int left;
    int prev;

    self = hythread_self();

    // Collect running java threads.
    size = 0;
    it = hythread_iterator_create(NULL);
    running_threads = (hythread_t *)apr_palloc(vm_env->mem_pool,
        hythread_iterator_size(it) * sizeof(hythread_t));
    while(native_thread = hythread_iterator_next(&it)) {
        vm_thread = get_vm_thread(native_thread);
        if (vm_thread != NULL && native_thread != self) {
            running_threads[size] = native_thread;
            ++size;
        }
    }
    hythread_iterator_release(&it);

    // Interrupt running threads.
    for (int i = 0; i < size; i++) {
        hythread_interrupt(running_threads[i]);
    }

    left = size;
    prev = -1;
    // Spin until there is no running threads.
    while (left > 0) {
        do {
            left = 0;
            changed = false;
            // Join or Interrupt.
            for (int i = 0; i < size; i++) {
                if (running_threads[i] == NULL) continue;
                if (hythread_join_timed(running_threads[i], 100, 0) == TM_ERROR_NONE) {
                    changed = true;
                    running_threads[i] = NULL;
                } else {
                    hythread_interrupt(running_threads[i]);
                    ++left;
                }
            }
        } while(left > 0 && changed);

        // We are stuck :-( Need to throw asynchronous exception.
        if (left > 0) {
            for (int i = 0; i < size; i++) {
                if (running_threads[i] == NULL) continue;
                if (left > 1 && i == prev) {
                    continue;
                } else {
                    prev = i;
                    hythread_set_safepoint_callback(running_threads[i], vm_shutdown_callback);
                }
            }
        }
    }
}

/**
 * Waits until all non-daemon threads finish their execution,
 * initiates VM shutdown sequence and stops running threads if any.
 *
 * @param[in] java_vm JVM that should be destroyed
 * @param[in] java_thread current java thread
 */
jint vm_destroy(JavaVM_Internal * java_vm, jthread java_thread)
{
    jint status;
    JNIEnv * jni_env;
    jobject uncaught_exception;

    assert(hythread_is_suspend_enabled());

    jni_env = jthread_get_JNI_env(java_thread);

    // Wait until all non-daemon threads finish their execution.
    status = jthread_wait_for_all_nondaemon_threads();
    if (status != TM_ERROR_NONE) {
        TRACE("Failed to wait for all non-daemon threads completion.");
        return JNI_ERR;
    }

    // Print out gathered data.
#ifdef VM_STATS
    ClassLoader::PrintUnloadingStats();
    VM_Statistics::get_vm_stats().print();
#endif

    // Remember thread's uncaught exception if any.
    uncaught_exception = jni_env->ExceptionOccurred();
    jni_env->ExceptionClear();

    // Execute pending shutdown hooks & finalizers
    status = exec_shutdown_sequence(jni_env);
    if (status != JNI_OK) return status;

    // Send VM_Death event and switch to VM_Death phase.
    // This should be the last event sent by VM.
    // This event should be sent before Agent_OnUnload called.
    jvmti_send_vm_death_event();

    // Raise uncaught exception to current thread.
    // It will be properly processed in jthread_detach().
    if (uncaught_exception) {
        exn_raise_object(uncaught_exception);
    }

    // Detach current thread.
    status = jthread_detach(java_thread);
    if (status != TM_ERROR_NONE) return JNI_ERR;

    // Call Agent_OnUnload() for agents and unload agents.
    java_vm->vm_env->TI->Shutdown(java_vm);

    // Block thread creation.
    // TODO: investigate how to achieve that with ThreadManager

    // Starting this moment any exception occurred in java thread will cause
    // entire java stack unwinding to the most recent native frame.
    // JNI is not available as well.
    assert(java_vm->vm_env->vm_state == Global_Env::VM_RUNNING);
    java_vm->vm_env->vm_state = Global_Env::VM_SHUTDOWNING;

    // Stop all (except current) java and native threads
    // before destroying VM-wide data.

    // Stop java threads
    vm_shutdown_stop_java_threads(java_vm->vm_env);

    // TODO: ups we don't stop native threads as well :-((
    // We are lucky! Currently, there are no such threads.

    return JNI_OK;
}

static int vm_interrupt_process(void * data) {
    hythread_t * threadBuf;
    int i;

    threadBuf = (hythread_t *)data;
    i = 0;
    // Join all threads.
    while (threadBuf[i] != NULL) {
        hythread_join(threadBuf[i]);
        i++;
    }

    // Return 130 to be compatible with RI.
    exit(130);
}

/**
 * Initiates VM shutdown sequence.
 */
static int vm_interrupt_entry_point(void * data) {
    JNIEnv * jni_env;
    JavaVMAttachArgs args;
    JavaVM * java_vm;
    jint status;

    java_vm = (JavaVM *)data;
    args.version = JNI_VERSION_1_2;
    args.group = NULL;
    args.name = "InterruptionHandler";

    status = AttachCurrentThread(java_vm, (void **)&jni_env, &args);
    if (status == JNI_OK) {
        exec_shutdown_sequence(jni_env);
        DetachCurrentThread(java_vm);
    }
    return status;
}

/**
 * Dumps all java stacks.
 */
static int vm_dump_entry_point(void * data) {
    JNIEnv * jni_env;
    JavaVMAttachArgs args;
    JavaVM * java_vm;
    jint status;

    java_vm = (JavaVM *)data;
    args.version = JNI_VERSION_1_2;
    args.group = NULL;
    args.name = "DumpHandler";

    status = AttachCurrentThread(java_vm, (void **)&jni_env, &args);
    if (status == JNI_OK) {
        // TODO: specify particular VM to notify.
        jvmti_notify_data_dump_request();
        st_print_all(stdout);
        DetachCurrentThread(java_vm);
    }
    return status;
}

/**
 * Current process received an interruption signal (Ctrl+C pressed).
 * Shutdown all running VMs and terminate the process.
 */
void vm_interrupt_handler(int UNREF x) {
    JavaVM ** vmBuf;
    hythread_t * threadBuf;
    int nVMs;
    jint status;

    status = JNI_GetCreatedJavaVMs(NULL, 0, &nVMs);
    assert(nVMs <= 1);
    if (status != JNI_OK) return;

    vmBuf = (JavaVM **) STD_MALLOC(nVMs * sizeof(JavaVM *));
    status = JNI_GetCreatedJavaVMs(vmBuf, nVMs, &nVMs);
    assert(nVMs <= 1);
    if (status != JNI_OK) goto cleanup;

    status = hythread_attach(NULL);
    if (status != TM_ERROR_NONE) goto cleanup;

    threadBuf = (hythread_t *) STD_MALLOC((nVMs + 1) * sizeof(hythread_t));
    threadBuf[nVMs] = NULL;

    // Create a new thread for each VM to avoid scalability and deadlock problems.
    for (int i = 0; i < nVMs; i++) {
        threadBuf[i] = NULL;
        hythread_create((threadBuf + i), 0, HYTHREAD_PRIORITY_NORMAL, 0, vm_interrupt_entry_point, (void *)vmBuf[i]);
    }

    // spawn a new thread which will terminate the process.
    hythread_create(NULL, 0, HYTHREAD_PRIORITY_NORMAL, 0, vm_interrupt_process, (void *)threadBuf);

cleanup:
    STD_FREE(vmBuf);
}

/**
 * Current process received an ??? signal (Ctrl+Break pressed).
 * Prints java stack traces for each VM running in the current process.
 */
void vm_dump_handler(int UNREF x) {
    JavaVM ** vmBuf;
    int nVMs;
    jint status;

    status = JNI_GetCreatedJavaVMs(NULL, 0, &nVMs);
    assert(nVMs <= 1);
    if (status != JNI_OK) return;

    vmBuf = (JavaVM **) STD_MALLOC(nVMs * sizeof(JavaVM *));
    status = JNI_GetCreatedJavaVMs(vmBuf, nVMs, &nVMs);
    assert(nVMs <= 1);

    if (status != JNI_OK) goto cleanup;

    status = hythread_attach(NULL);
    if (status != TM_ERROR_NONE) goto cleanup;

    // Create a new thread for each VM to avoid scalability and deadlock problems.
    for (int i = 0; i < nVMs; i++) {
        hythread_create(NULL, 0, HYTHREAD_PRIORITY_NORMAL, 0, vm_dump_entry_point, (void *)vmBuf[i]);
    }

cleanup:
    STD_FREE(vmBuf);
}
<commit_msg>Applied HARMONY-3297 and HARMONY-3381 VM shutdown fixes<commit_after>/*
 *  Copyright 2005-2006 The Apache Software Foundation or its licensors, as applicable.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
/**
 * @author Intel, Evgueni Brevnov
 * @version $Revision: 1.1 $
 */

#include <stdlib.h>
#include <apr_thread_mutex.h>

#include "open/hythread.h"
#include "open/jthread.h"
#include "open/gc.h"
#include "open/thread_externals.h"

#include "jni.h"
#include "jni_direct.h"
#include "environment.h"
#include "classloader.h"
#include "compile.h"
#include "nogc.h"
#include "jni_utils.h"
#include "vm_stats.h"
#include "thread_dump.h"
#include "interpreter.h"

#define LOG_DOMAIN "vm.core.shutdown"
#include "cxxlog.h"

#define PROCESS_EXCEPTION(messageId, message) \
{ \
    LECHO(messageId, message << "Internal error: "); \
\
    if (jni_env->ExceptionCheck()== JNI_TRUE) \
    { \
        jni_env->ExceptionDescribe(); \
        jni_env->ExceptionClear(); \
    } \
\
    return JNI_ERR; \
} \

/**
 * Calls java.lang.System.execShutdownSequence() method.
 *
 * @param jni_env JNI environment of the current thread
 */
static jint exec_shutdown_sequence(JNIEnv * jni_env) {
    jclass system_class;
    jmethodID shutdown_method;

    assert(hythread_is_suspend_enabled());

    system_class = jni_env->FindClass("java/lang/System");
    if (jni_env->ExceptionCheck() == JNI_TRUE || system_class == NULL) {
        // This is debug message only. May appear when VM is already in shutdown stage.
        PROCESS_EXCEPTION(38, "{0}can't find java.lang.System class.");
    }

    shutdown_method = jni_env->GetStaticMethodID(system_class, "execShutdownSequence", "()V");
    if (jni_env->ExceptionCheck() == JNI_TRUE || shutdown_method == NULL) {
        PROCESS_EXCEPTION(39, "{0}can't find java.lang.System.execShutdownSequence() method.");
    }

    jni_env->CallStaticVoidMethod(system_class, shutdown_method);

    if (jni_env->ExceptionCheck() == JNI_TRUE) {
        PROCESS_EXCEPTION(40, "{0}java.lang.System.execShutdownSequence() method completed with an exception.");
    }
    return JNI_OK;
}

static void vm_shutdown_callback() {
    hythread_exit(NULL);
}

/**
 * Stops running java threads by throwing an exception
 * up to the first native frame.
 *
 * @param[in] vm_env a global VM environment
 */
static void vm_shutdown_stop_java_threads(Global_Env * vm_env) {
    hythread_t self;
    hythread_t * running_threads;
    hythread_t native_thread;
    hythread_iterator_t it;
    VM_thread *vm_thread;

    self = hythread_self();

    // Collect running java threads.
    // Set callbacks to let threads exit
    TRACE2("shutdown", "stopping threads, self " << self);
    it = hythread_iterator_create(NULL);
    running_threads = (hythread_t *)apr_palloc(vm_env->mem_pool,
        hythread_iterator_size(it) * sizeof(hythread_t));
    int size = 0;
    while(native_thread = hythread_iterator_next(&it)) {
    vm_thread = get_vm_thread(native_thread);
        if (native_thread != self && vm_thread != NULL) {
            hythread_set_safepoint_callback(native_thread, vm_shutdown_callback);
            running_threads[size] = native_thread;
            ++size;
        }
    }
    hythread_iterator_release(&it);

    TRACE2("shutdown", "joining threads");
    // join running threads
    // blocked and waiting threads won't be joined
    for (int i = 0; i < size; i++) {
        hythread_join_timed(running_threads[i], 100/size + 1, 0);
    }

    TRACE2("shutdown", "cancelling threads");
    // forcedly kill remaining threads
    // There is a small chance that some of these threads are not in the point
    // safe for killing, e.g. in malloc()
    it = hythread_iterator_create(NULL);
    while(native_thread = hythread_iterator_next(&it)) {
    vm_thread = get_vm_thread(native_thread);
    // we should not cancel self and
    // non-java threads (i.e. vm_thread == NULL)
        if (native_thread != self && vm_thread != NULL) {
            hythread_cancel(native_thread);
            TRACE2("shutdown", "cancelling " << native_thread);
        }
    }
    hythread_iterator_release(&it);
    TRACE2("shutdown", "shutting down threads complete");
}

/**
 * Waits until all non-daemon threads finish their execution,
 * initiates VM shutdown sequence and stops running threads if any.
 *
 * @param[in] java_vm JVM that should be destroyed
 * @param[in] java_thread current java thread
 */
jint vm_destroy(JavaVM_Internal * java_vm, jthread java_thread)
{
    jint status;
    JNIEnv * jni_env;
    jobject uncaught_exception;

    assert(hythread_is_suspend_enabled());

    jni_env = jthread_get_JNI_env(java_thread);

    // Wait until all non-daemon threads finish their execution.
    status = jthread_wait_for_all_nondaemon_threads();
    if (status != TM_ERROR_NONE) {
        TRACE("Failed to wait for all non-daemon threads completion.");
        return JNI_ERR;
    }

    // Print out gathered data.
#ifdef VM_STATS
    ClassLoader::PrintUnloadingStats();
    VM_Statistics::get_vm_stats().print();
#endif

    // Remember thread's uncaught exception if any.
    uncaught_exception = jni_env->ExceptionOccurred();
    jni_env->ExceptionClear();

    // Execute pending shutdown hooks & finalizers
    status = exec_shutdown_sequence(jni_env);
    if (status != JNI_OK) return status;

    // Raise uncaught exception to current thread.
    // It will be properly processed in jthread_detach().
    if (uncaught_exception) {
        exn_raise_object(uncaught_exception);
    }

    // Stop all (except current) java and native threads
    // before destroying VM-wide data.

    // Stop java threads
    vm_shutdown_stop_java_threads(java_vm->vm_env);

    // TODO: ups we don't stop native threads as well :-((
    // We are lucky! Currently, there are no such threads.

    // Send VM_Death event and switch to DEAD phase.
    // This should be the last event sent by VM.
    // This event should be sent before Agent_OnUnload called.
    jvmti_send_vm_death_event();

    // Detach current thread.
    status = jthread_detach(java_thread);
    if (status != TM_ERROR_NONE) return JNI_ERR;

    // Call Agent_OnUnload() for agents and unload agents.
    java_vm->vm_env->TI->Shutdown(java_vm);

    // Block thread creation.
    // TODO: investigate how to achieve that with ThreadManager

    // Starting this moment any exception occurred in java thread will cause
    // entire java stack unwinding to the most recent native frame.
    // JNI is not available as well.
    assert(java_vm->vm_env->vm_state == Global_Env::VM_RUNNING);
    java_vm->vm_env->vm_state = Global_Env::VM_SHUTDOWNING;

    TRACE2("shutdown", "vm_destroy complete");
    return JNI_OK;
}

static int vm_interrupt_process(void * data) {
    hythread_t * threadBuf;
    int i;

    threadBuf = (hythread_t *)data;
    i = 0;
    // Join all threads.
    while (threadBuf[i] != NULL) {
        hythread_join(threadBuf[i]);
        i++;
    }

    // Return 130 to be compatible with RI.
    exit(130);
}

/**
 * Initiates VM shutdown sequence.
 */
static int vm_interrupt_entry_point(void * data) {
    JNIEnv * jni_env;
    JavaVMAttachArgs args;
    JavaVM * java_vm;
    jint status;

    java_vm = (JavaVM *)data;
    args.version = JNI_VERSION_1_2;
    args.group = NULL;
    args.name = "InterruptionHandler";

    status = AttachCurrentThread(java_vm, (void **)&jni_env, &args);
    if (status == JNI_OK) {
        exec_shutdown_sequence(jni_env);
        DetachCurrentThread(java_vm);
    }
    return status;
}

/**
 * Dumps all java stacks.
 */
static int vm_dump_entry_point(void * data) {
    JNIEnv * jni_env;
    JavaVMAttachArgs args;
    JavaVM * java_vm;
    jint status;

    java_vm = (JavaVM *)data;
    args.version = JNI_VERSION_1_2;
    args.group = NULL;
    args.name = "DumpHandler";

    status = AttachCurrentThread(java_vm, (void **)&jni_env, &args);
    if (status == JNI_OK) {
        // TODO: specify particular VM to notify.
        jvmti_notify_data_dump_request();
        st_print_all(stdout);
        DetachCurrentThread(java_vm);
    }
    return status;
}

/**
 * Current process received an interruption signal (Ctrl+C pressed).
 * Shutdown all running VMs and terminate the process.
 */
void vm_interrupt_handler(int UNREF x) {
    JavaVM ** vmBuf;
    hythread_t * threadBuf;
    int nVMs;
    jint status;

    status = JNI_GetCreatedJavaVMs(NULL, 0, &nVMs);
    assert(nVMs <= 1);
    if (status != JNI_OK) return;

    vmBuf = (JavaVM **) STD_MALLOC(nVMs * sizeof(JavaVM *));
    status = JNI_GetCreatedJavaVMs(vmBuf, nVMs, &nVMs);
    assert(nVMs <= 1);
    if (status != JNI_OK) goto cleanup;

    status = hythread_attach(NULL);
    if (status != TM_ERROR_NONE) goto cleanup;

    threadBuf = (hythread_t *) STD_MALLOC((nVMs + 1) * sizeof(hythread_t));
    threadBuf[nVMs] = NULL;

    // Create a new thread for each VM to avoid scalability and deadlock problems.
    for (int i = 0; i < nVMs; i++) {
        threadBuf[i] = NULL;
        hythread_create((threadBuf + i), 0, HYTHREAD_PRIORITY_NORMAL, 0, vm_interrupt_entry_point, (void *)vmBuf[i]);
    }

    // spawn a new thread which will terminate the process.
    hythread_create(NULL, 0, HYTHREAD_PRIORITY_NORMAL, 0, vm_interrupt_process, (void *)threadBuf);

cleanup:
    STD_FREE(vmBuf);
}

/**
 * Current process received an ??? signal (Ctrl+Break pressed).
 * Prints java stack traces for each VM running in the current process.
 */
void vm_dump_handler(int UNREF x) {
    JavaVM ** vmBuf;
    int nVMs;
    jint status;

    status = JNI_GetCreatedJavaVMs(NULL, 0, &nVMs);
    assert(nVMs <= 1);
    if (status != JNI_OK) return;

    vmBuf = (JavaVM **) STD_MALLOC(nVMs * sizeof(JavaVM *));
    status = JNI_GetCreatedJavaVMs(vmBuf, nVMs, &nVMs);
    assert(nVMs <= 1);

    if (status != JNI_OK) goto cleanup;

    status = hythread_attach(NULL);
    if (status != TM_ERROR_NONE) goto cleanup;

    // Create a new thread for each VM to avoid scalability and deadlock problems.
    for (int i = 0; i < nVMs; i++) {
        hythread_create(NULL, 0, HYTHREAD_PRIORITY_NORMAL, 0, vm_dump_entry_point, (void *)vmBuf[i]);
    }

cleanup:
    STD_FREE(vmBuf);
}
<|endoftext|>


<commit_before>
//---------------------------------------------------------------------------------
// The example of usage of AliKFParticle & AliKFVertex classes for V0 analysis
// .
// @author  S.Gorbunov, I.Kisel
// @version 1.0
// @since   13.05.07
//
// The AliKFParticleTest macro contains a toy V0 finder for ESD tracks.
// At the first step, event primary vertex is reconstructed.
// At the second step, ideal PID hypothesis are assigned to all the particles.
// At the third step, V0 candidates are constructed for each pair
// of positive and negative particles.
// V0 candidate considered as good when it passes Chi^2 cut and
// it is placed >= 3 Sigma away from the primary vertex.
// Invariant mass distribution for all good V0 candidates is plotted.
//
//  -= Copyright &copy ALICE HLT Group =-
//_________________________________________________________________________________

#if !defined( __CINT__) || defined(__MAKECINT__)

  //gSystem->AddIncludePath("-I\"$ALICE_ROOT/include\"");

  #include <Riostream.h>
  #include <TTree.h>
  #include <TFile.h>
  #include <TCanvas.h>
  #include <TH1D.h>
  #include <TLatex.h>
  #include <TDatabasePDG.h>
  #include <TParticle.h>

  #include "AliRun.h"
  #include "AliStack.h"
  #include "AliESDEvent.h"
  #include "AliTracker.h"
  #include "AliKFParticle.h"
  #include "AliKFVertex.h"

#endif

Bool_t old_file = 1;
TCanvas *canvas=0;
TH1D  *histoMass[3]={0,0,0};
Int_t histoPDG [4]= {22,310,3122,421};
char* histoName[4]= {"#gamma","K^{0}_{s}","#Lambda","D^{0}"};
TLatex *histoText[4]={0,0,0,0};

void DrawV0()
{
  //* Draw the invariant mass histogram

  if( !canvas ) return;
  histoMass[0]->Draw();
  for( Int_t i=1; i<3; i++ ) histoMass[i]->Draw("same");
  for( Int_t i=0; i<4; i++ ){
    Double_t mass = TDatabasePDG::Instance()->GetParticle(histoPDG[i])->Mass();
    Int_t bin = histoMass[2]->FindBin(mass) -5;
    if( bin<0 ) bin =0;
    Double_t max = 0;
    for( Int_t j=bin; j<bin+10; j++ )
    if( max<histoMass[2]->GetBinContent(j) ) max = histoMass[2]->GetBinContent(j);
    histoText[i]->SetY(max);
    histoText[i]->SetX(mass+.05);
    if(max>0) histoText[i]->Draw();
  }
  if( canvas ) canvas->Update();
}

void StartV0()
{
  //* (Re)create histograms and fill them from temporary file

  TDirectory *curr = gDirectory;
  canvas = new TCanvas();
  histoMass[0] = new TH1D("massAll","AliKFParticle test", 500,0,3);
  histoMass[0]->SetXTitle("V^{0} invariant mass [GeV]");
  histoMass[1] = new TH1D("massMulti","V^{+-} contributions", 500,0,3);
  histoMass[2] = new TH1D("massV0","V^{0} signal", 500,0,3);
  histoMass[0]->SetLineColor(8);
  histoMass[0]->SetFillColor(8);
  histoMass[1]->SetLineColor(kMagenta);
  histoMass[1]->SetFillColor(kMagenta);
  histoMass[2]->SetLineColor(kBlue);
  histoMass[2]->SetFillColor(kBlue);
  for( Int_t i=0; i<4; i++ ){
    histoText[i] = new TLatex(0,0,histoName[i]);
    histoText[i]->SetTextColor(kBlue);
  }
  TFile* file = new TFile("AliKFParticleTest.root", "READ" );
  if( !old_file && file ){
    file->cd();
    for( Int_t i=0; i<3; i++ ){
      TObject *old = file->FindObjectAny(histoMass[i]->GetName());
      if( old && histoMass[i] ) histoMass[i]->Add( (TH1D*) old);
    }
    file->Close();
  }
  curr->cd();
  DrawV0();
}

void EndV0()
{
  //* End of gAlice -> store all histos in temporary file, clean memory

  TDirectory *curr = gDirectory;
  TFile* file = new TFile("AliKFParticleTest.root", "RECREATE" );
  old_file = 0;
  file->cd();
  for( Int_t i=0; i<3; i++ ) histoMass[i]->Write();
  file->Close();
  for( Int_t i=0; i<3; i++ ) delete histoMass[i];
  for( Int_t i=0; i<4; i++ ) delete histoText[i];
  delete canvas;
  curr->cd();
}

class TESDTrackInfo
{
public:
  TESDTrackInfo(){}
  AliKFParticle fParticle; //* assigned KFParticle
  Bool_t fPrimUsedFlag;    //* flag shows that the particle was used for primary vertex fit
  Bool_t fOK;              //* is the track good enough
  Int_t mcPDG;             //* Monte Carlo PDG code
  Int_t mcMotherID;        //* Monte Carlo ID of its mother
};

void RunV0(  AliESDEvent *event )
{
  //* V0 finder

  static Int_t iEvent = 0;
  cout<<"Event "<<iEvent++<<endl;

  if( !gAlice ) return;
  AliRunLoader *rl = AliRunLoader::Instance();

  AliStack *stack = rl->Stack();
  if( !stack ) return;

  Int_t nESDTracks=event->GetNumberOfTracks();
  if( nESDTracks>1000 ) nESDTracks=1000;

  TESDTrackInfo ESDTrackInfo[1000]; //* parallel to ESD tracks

  //* Fill ESDTrackInfo array

  for (Int_t iTr=0; iTr<nESDTracks; iTr++)
    {
      TESDTrackInfo &info = ESDTrackInfo[iTr];
      info.fOK = 0;
      info.fPrimUsedFlag = 0;
      info.mcPDG = -1;
      info.mcMotherID = -1;

      //* track quality check

      AliESDtrack *pTrack = event->GetTrack(iTr);
      if( !pTrack  ) continue;
      if (pTrack->GetKinkIndex(0)>0) continue;
      if ( !( pTrack->GetStatus()&AliESDtrack::kITSrefit ) ) continue;
      Int_t indi[12];
      if( pTrack->GetITSclusters(indi) <5 ) continue;
      Int_t PDG = ( pTrack->GetSigned1Pt() <0 ) ?321 :211;

      //* take MC PDG
      {
	Int_t mcID = TMath::Abs(pTrack->GetLabel());
	TParticle * part = stack->Particle(TMath::Abs(mcID));
	if( part ){
	  info.mcPDG = part->GetPdgCode();
	  PDG = info.mcPDG;
	  if( mcID>=0 ) info.mcMotherID = part->GetFirstMother();
	}
      }

      //* Construct KFParticle for the track

      info.fParticle = AliKFParticle( *pTrack, PDG );
      info.fOK = 1;
    }

  //* Find event primary vertex

  AliKFVertex primVtx;
  {
    const AliKFParticle * vSelected[1000]; //* Selected particles for vertex fit
    Int_t vIndex[1000];                    //* Indices of selected particles
    Bool_t vFlag[1000];                    //* Flags returned by the vertex finder

    Int_t nSelected = 0;
    for( Int_t i = 0; i<nESDTracks; i++){
      if(ESDTrackInfo[i].fOK ){
	vSelected[nSelected] = &(ESDTrackInfo[i].fParticle);
	vIndex[nSelected] = i;
	nSelected++;
      }
    }
    primVtx.ConstructPrimaryVertex( vSelected, nSelected, vFlag, 3. );
    for( Int_t i = 0; i<nSelected; i++){
      if( vFlag[i] ) ESDTrackInfo[vIndex[i]].fPrimUsedFlag = 1;
    }
    if( primVtx.GetNDF() <1 ) return; //* Less then two tracks in primary vertex
  }

  //* V0 finder

  for( Int_t iTr = 0; iTr<nESDTracks; iTr++ ){ //* first daughter

    TESDTrackInfo &info = ESDTrackInfo[iTr];
    if( !info.fOK ) continue;

    for( Int_t jTr = iTr+1; jTr<nESDTracks; jTr++ ){  //* second daughter
      TESDTrackInfo &jnfo = ESDTrackInfo[jTr];
      if( !jnfo.fOK ) continue;

      //* check for different charge

      if( info.fParticle.GetQ() == jnfo.fParticle.GetQ() ) continue;

      //* construct V0 mother

      AliKFParticle V0( info.fParticle, jnfo.fParticle );

      //* check V0 Chi^2

      if( V0.GetNDF()<1 ) continue;
      if( TMath::Sqrt(TMath::Abs(V0.GetChi2()/V0.GetNDF())) >3. ) continue;

      //* subtruct daughters from primary vertex

      AliKFVertex primVtxCopy = primVtx;

      if( info.fPrimUsedFlag ) primVtxCopy -= info.fParticle;
      if( jnfo.fPrimUsedFlag ) primVtxCopy -= jnfo.fParticle;

      //* Check V0 Chi^2 deviation from primary vertex

      if( V0.GetDeviationFromVertex( primVtxCopy ) >3. ) continue;

      //* Add V0 to primary vertex to improve the primary vertex resolution

      primVtxCopy += V0;

      //* Set production vertex for V0

      V0.SetProductionVertex( primVtxCopy );

      //* Check chi^2 for a case

      if( TMath::Sqrt( TMath::Abs(V0.GetChi2()/V0.GetNDF()) >3. )) continue;

      //* Get V0 decay length with estimated error

      Double_t length, sigmaLength;
      if( V0.GetDecayLength( length, sigmaLength ) ) continue;

      //* Reject V0 if it decays too close to the primary vertex

      if( length  <3.*sigmaLength ) continue;

      //* Get V0 invariant mass and plot it

      Double_t mass, sigmaMass;
      if( V0.GetMass( mass, sigmaMass ) ) continue;
      histoMass[0]->Fill(mass);

      //* Fill signal histograms using MC information

      if( info.mcMotherID==jnfo.mcMotherID && info.mcMotherID>=0 ){
	TParticle *mother = stack->Particle(info.mcMotherID);
	if( mother && TMath::Abs(mother->GetPdgCode())!=21 ){
	  histoMass[1]->Fill(mass);
	  if( mother->GetNDaughters()==2 ){
	    histoMass[2]->Fill(mass);
	  }
	  cout<<"PDG V0,pi,pj, ndaughters, mc mass, reco mass = "<<mother->GetPdgCode()<<","<<info.mcPDG<<","<<jnfo.mcPDG<<", "
	      << mother->GetNDaughters()<<", "<<mother->GetMass()<<", "<<mass<<endl;
	}
      }
    }
  }
  if( iEvent %100 == 0 || (iEvent<100 && iEvent %10==0)) DrawV0();
}

Int_t AliKFParticleTest(Int_t n1=0,Int_t n2=1000,char *dire="/d/alice10/sma/my_v4-05-Release/pp/"){
  //* Main macro

  //  LOOP  OVER  SERIES  OF  DIRECTORIES

  for (Int_t ifi=n1; ifi<=n2; ifi++) {

    char nstring[5], filename[100], esdfile[100];
    sprintf(nstring,"%3.3d",ifi);
    sprintf(filename,"%s%s/galice.root",dire,nstring);
    sprintf(esdfile,"%s%s/AliESDs.root",dire,nstring);

    cout <<"  Opening "<<filename<<"\nand ESD "<<esdfile<<endl;

    if (gAlice) {
      delete AliRunLoader::Instance();
      delete gAlice;
      gAlice=0;
    }

    AliRunLoader *rl = AliRunLoader::Open(filename);
    if ( !rl ) {
      ::Error("AliKFParticleTest.C","Can not open session !");
      continue;
    }
    if (rl->LoadgAlice()) {
      ::Error("AliKFParticleTest.C","LoadgAlice returned error !");
      delete rl;
      continue;
    }
    if (rl->LoadHeader()) {
      ::Error("AliKFParticleTest.C","LoadHeader returned error !");
      delete rl;
      continue;
    }
    rl->LoadKinematics();
    AliTracker::SetFieldMap(gAlice->Field(),1);
    AliKFParticle::SetField( AliTracker::GetBz() );

    //---------------------------------------//
    //                                       //
    //               ESD  file               //
    //                                       //
    //---------------------------------------//

    // Open file with the ESD
    TFile *ef=TFile::Open(esdfile);

    //Check if the file could be opened
    if (!ef || !ef->IsOpen()) {cerr<<"Error open AliESDs.root !\n"; continue ;}

    //create event object
    AliESD *event = new AliESDEvent;

    //Set pointer to the esd tree in the file
    TTree* tree = (TTree*) ef->Get("esdTree");

    //check if the tree exists
    if (!tree) {cerr<<"no ESD tree found\n"; continue;};

    //Set pointer to the esd object in the tree
    event->ReadFromTree(event);

    //Number of events
    Int_t nevents=tree->GetEntriesFast();
    cout << "Number of events: " << nevents << endl;

    StartV0();
    for (Int_t iev=0; iev<nevents; iev++){
      tree->GetEvent(iev);
      rl->GetEvent(iev);
      RunV0(event);
    }
    EndV0();
    delete event;
    ef->Close();
  }
  StartV0();
  return 0;
}
<commit_msg>Some fixes to make the KF macro working (was very old)<commit_after>
//---------------------------------------------------------------------------------
// The example of usage of AliKFParticle & AliKFVertex classes for V0 analysis
// .
// @author  S.Gorbunov, I.Kisel
// @version 1.0
// @since   13.05.07
//
// The AliKFParticleTest macro contains a toy V0 finder for ESD tracks.
// At the first step, event primary vertex is reconstructed.
// At the second step, ideal PID hypothesis are assigned to all the particles.
// At the third step, V0 candidates are constructed for each pair
// of positive and negative particles.
// V0 candidate considered as good when it passes Chi^2 cut and
// it is placed >= 3 Sigma away from the primary vertex.
// Invariant mass distribution for all good V0 candidates is plotted.
//
//  -= Copyright &copy ALICE HLT Group =-
//_________________________________________________________________________________

#if !defined( __CINT__) || defined(__MAKECINT__)

  //gSystem->AddIncludePath("-I\"$ALICE_ROOT/include\"");

  #include <Riostream.h>
  #include <TTree.h>
  #include <TFile.h>
  #include <TCanvas.h>
  #include <TH1D.h>
  #include <TLatex.h>
  #include <TDatabasePDG.h>
  #include <TParticle.h>

  #include "AliRun.h"
  #include "AliStack.h"
  #include "AliESDEvent.h"
  #include "AliTracker.h"
  #include "AliKFParticle.h"
  #include "AliKFVertex.h"

#endif

Bool_t old_file = 1;
TCanvas *canvas=0;
TH1D  *histoMass[3]={0,0,0};
Int_t histoPDG [4]= {22,310,3122,421};
char* histoName[4]= {"#gamma","K^{0}_{s}","#Lambda","D^{0}"};
TLatex *histoText[4]={0,0,0,0};

void DrawV0()
{
  //* Draw the invariant mass histogram

  if( !canvas ) return;
  histoMass[0]->Draw();
  for( Int_t i=1; i<3; i++ ) histoMass[i]->Draw("same");
  for( Int_t i=0; i<4; i++ ){
    Double_t mass = TDatabasePDG::Instance()->GetParticle(histoPDG[i])->Mass();
    Int_t bin = histoMass[2]->FindBin(mass) -5;
    if( bin<0 ) bin =0;
    Double_t max = 0;
    for( Int_t j=bin; j<bin+10; j++ )
    if( max<histoMass[2]->GetBinContent(j) ) max = histoMass[2]->GetBinContent(j);
    histoText[i]->SetY(max);
    histoText[i]->SetX(mass+.05);
    if(max>0) histoText[i]->Draw();
  }
  if( canvas ) canvas->Update();
}

void StartV0()
{
  //* (Re)create histograms and fill them from temporary file

  TDirectory *curr = gDirectory;
  canvas = new TCanvas();
  histoMass[0] = new TH1D("massAll","AliKFParticle test", 500,0,3);
  histoMass[0]->SetXTitle("V^{0} invariant mass [GeV]");
  histoMass[1] = new TH1D("massMulti","V^{+-} contributions", 500,0,3);
  histoMass[2] = new TH1D("massV0","V^{0} signal", 500,0,3);
  histoMass[0]->SetLineColor(8);
  histoMass[0]->SetFillColor(8);
  histoMass[1]->SetLineColor(kMagenta);
  histoMass[1]->SetFillColor(kMagenta);
  histoMass[2]->SetLineColor(kBlue);
  histoMass[2]->SetFillColor(kBlue);
  for( Int_t i=0; i<4; i++ ){
    histoText[i] = new TLatex(0,0,histoName[i]);
    histoText[i]->SetTextColor(kBlue);
  }
  TFile* file = new TFile("AliKFParticleTest.root", "READ" );
  if( !old_file && file ){
    file->cd();
    for( Int_t i=0; i<3; i++ ){
      TObject *old = file->FindObjectAny(histoMass[i]->GetName());
      if( old && histoMass[i] ) histoMass[i]->Add( (TH1D*) old);
    }
    file->Close();
  }
  curr->cd();
  DrawV0();
}

void EndV0()
{
  //* End of gAlice -> store all histos in temporary file, clean memory

  TDirectory *curr = gDirectory;
  TFile* file = new TFile("AliKFParticleTest.root", "RECREATE" );
  old_file = 0;
  file->cd();
  for( Int_t i=0; i<3; i++ ) histoMass[i]->Write();
  file->Close();
  for( Int_t i=0; i<3; i++ ) delete histoMass[i];
  for( Int_t i=0; i<4; i++ ) delete histoText[i];
  delete canvas;
  curr->cd();
}

class TESDTrackInfo
{
public:
  TESDTrackInfo(){}
  AliKFParticle fParticle; //* assigned KFParticle
  Bool_t fPrimUsedFlag;    //* flag shows that the particle was used for primary vertex fit
  Bool_t fOK;              //* is the track good enough
  Int_t mcPDG;             //* Monte Carlo PDG code
  Int_t mcMotherID;        //* Monte Carlo ID of its mother
};

void RunV0(  AliESDEvent *event )
{
  //* V0 finder

  static Int_t iEvent = 0;
  cout<<"Event "<<iEvent++<<endl;

  if( !gAlice ) return;
  AliRunLoader *rl = AliRunLoader::Instance();

  AliStack *stack = rl->Stack();
  if( !stack ) return;

  Int_t nESDTracks=event->GetNumberOfTracks();
  if( nESDTracks>1000 ) nESDTracks=1000;

  TESDTrackInfo ESDTrackInfo[1000]; //* parallel to ESD tracks

  //* Fill ESDTrackInfo array

  for (Int_t iTr=0; iTr<nESDTracks; iTr++)
    {
      Printf("tracj %d", iTr);
      TESDTrackInfo &info = ESDTrackInfo[iTr];
      info.fOK = 0;
      info.fPrimUsedFlag = 0;
      info.mcPDG = -1;
      info.mcMotherID = -1;

      //* track quality check

      AliESDtrack *pTrack = event->GetTrack(iTr);
      if( !pTrack  ) continue;
      if (pTrack->GetKinkIndex(0)>0) continue;
      if ( !( pTrack->GetStatus()&AliESDtrack::kITSrefit ) ) continue;
      Int_t indi[12];
      if( pTrack->GetITSclusters(indi) <5 ) continue;
      Int_t PDG = ( pTrack->GetSigned1Pt() <0 ) ?321 :211;

      //* take MC PDG
      {
	Int_t mcID = TMath::Abs(pTrack->GetLabel());
	TParticle * part = stack->Particle(TMath::Abs(mcID));
	if( part ){
	  info.mcPDG = part->GetPdgCode();
	  PDG = info.mcPDG;
	  if( mcID>=0 ) info.mcMotherID = part->GetFirstMother();
	}
      }

      //* Construct KFParticle for the track

      info.fParticle = AliKFParticle( *pTrack, PDG );
      info.fOK = 1;
    }

  //* Find event primary vertex

  AliKFVertex primVtx;
  {
    const AliKFParticle * vSelected[1000]; //* Selected particles for vertex fit
    Int_t vIndex[1000];                    //* Indices of selected particles
    Bool_t vFlag[1000];                    //* Flags returned by the vertex finder

    Int_t nSelected = 0;
    for( Int_t i = 0; i<nESDTracks; i++){
      if(ESDTrackInfo[i].fOK ){
	vSelected[nSelected] = &(ESDTrackInfo[i].fParticle);
	vIndex[nSelected] = i;
	nSelected++;
      }
    }
    primVtx.ConstructPrimaryVertex( vSelected, nSelected, vFlag, 3. );
    for( Int_t i = 0; i<nSelected; i++){
      if( vFlag[i] ) ESDTrackInfo[vIndex[i]].fPrimUsedFlag = 1;
    }
    if( primVtx.GetNDF() <1 ) return; //* Less then two tracks in primary vertex
  }

  //* V0 finder

  for( Int_t iTr = 0; iTr<nESDTracks; iTr++ ){ //* first daughter

    TESDTrackInfo &info = ESDTrackInfo[iTr];
    if( !info.fOK ) continue;

    for( Int_t jTr = iTr+1; jTr<nESDTracks; jTr++ ){  //* second daughter
      TESDTrackInfo &jnfo = ESDTrackInfo[jTr];
      if( !jnfo.fOK ) continue;

      //* check for different charge

      if( info.fParticle.GetQ() == jnfo.fParticle.GetQ() ) continue;

      //* construct V0 mother

      AliKFParticle V0( info.fParticle, jnfo.fParticle );

      //* check V0 Chi^2

      if( V0.GetNDF()<1 ) continue;
      if( TMath::Sqrt(TMath::Abs(V0.GetChi2()/V0.GetNDF())) >3. ) continue;

      //* subtruct daughters from primary vertex

      AliKFVertex primVtxCopy = primVtx;

      if( info.fPrimUsedFlag ) primVtxCopy -= info.fParticle;
      if( jnfo.fPrimUsedFlag ) primVtxCopy -= jnfo.fParticle;

      //* Check V0 Chi^2 deviation from primary vertex

      if( V0.GetDeviationFromVertex( primVtxCopy ) >3. ) continue;

      //* Add V0 to primary vertex to improve the primary vertex resolution

      primVtxCopy += V0;

      //* Set production vertex for V0

      V0.SetProductionVertex( primVtxCopy );

      //* Check chi^2 for a case

      if( TMath::Sqrt( TMath::Abs(V0.GetChi2()/V0.GetNDF())) >3. ) continue;

      //* Get V0 decay length with estimated error

      Double_t length, sigmaLength;
      if( V0.GetDecayLength( length, sigmaLength ) ) continue;

      //* Reject V0 if it decays too close to the primary vertex

      if( length  <3.*sigmaLength ) continue;

      //* Get V0 invariant mass and plot it

      Double_t mass, sigmaMass;
      if( V0.GetMass( mass, sigmaMass ) ) continue;
      histoMass[0]->Fill(mass);

      //* Fill signal histograms using MC information

      if( info.mcMotherID==jnfo.mcMotherID && info.mcMotherID>=0 ){
	TParticle *mother = stack->Particle(info.mcMotherID);
	if( mother && TMath::Abs(mother->GetPdgCode())!=21 ){
	  histoMass[1]->Fill(mass);
	  if( mother->GetNDaughters()==2 ){
	    histoMass[2]->Fill(mass);
	  }
	  cout<<"PDG V0,pi,pj, ndaughters, mc mass, reco mass = "<<mother->GetPdgCode()<<","<<info.mcPDG<<","<<jnfo.mcPDG<<", "
	      << mother->GetNDaughters()<<", "<<mother->GetMass()<<", "<<mass<<endl;
	}
      }
    }
  }
  if( iEvent %100 == 0 || (iEvent<100 && iEvent %10==0)) DrawV0();
}

//Int_t AliKFParticleTest(Int_t n1=0,Int_t n2=1000,char *dire="/d/alice10/sma/my_v4-05-Release/pp/"){
Int_t AliKFParticleTest(Int_t n1=993,Int_t n2=999,char *dire="~/SOFT/AliRoot_git/AliRoot_20140223/test/genkine/TestKF/Events/"){
  //* Main macro

  //  LOOP  OVER  SERIES  OF  DIRECTORIES

  for (Int_t ifi=n1; ifi<=n2; ifi++) {

    char nstring[5], filename[100], esdfile[100];
    sprintf(nstring,"%3.3d",ifi);
    sprintf(filename,"%s%s/galice.root",dire,nstring);
    sprintf(esdfile,"%s%s/AliESDs.root",dire,nstring);

    cout <<"  Opening "<<filename<<"\nand ESD "<<esdfile<<endl;

    TFile* ftemp = TFile::Open(filename);
    Printf("ftemp = %p", ftemp);
    if (!ftemp) continue;

    if (gAlice) {
      delete AliRunLoader::Instance();
      delete gAlice;
      gAlice=0;
    }

    AliRunLoader *rl = AliRunLoader::Open(filename);
    if ( !rl ) {
      ::Error("AliKFParticleTest.C","Can not open session !");
      continue;
    }
    if (rl->LoadgAlice()) {
      ::Error("AliKFParticleTest.C","LoadgAlice returned error !");
      delete rl;
      continue;
    }
    if (rl->LoadHeader()) {
      ::Error("AliKFParticleTest.C","LoadHeader returned error !");
      delete rl;
      continue;
    }
    rl->LoadKinematics();

    //---------------------------------------//
    //                                       //
    //               ESD  file               //
    //                                       //
    //---------------------------------------//

    // Open file with the ESD
    TFile *ef=TFile::Open(esdfile);

    //Check if the file could be opened
    if (!ef || !ef->IsOpen()) {cerr<<"Error open AliESDs.root !\n"; continue ;}

    //create event object
    AliESDEvent *event = new AliESDEvent;

    //Set pointer to the esd tree in the file
    TTree* tree = (TTree*) ef->Get("esdTree");

    //check if the tree exists
    if (!tree) {cerr<<"no ESD tree found\n"; continue;};

    //Set pointer to the esd object in the tree
    event->ReadFromTree(tree);

    //Number of events
    Int_t nevents=tree->GetEntriesFast();
    cout << "Number of events: " << nevents << endl;

    StartV0();
    for (Int_t iev=0; iev<nevents; iev++){
      tree->GetEvent(iev);
      rl->GetEvent(iev);
      AliKFParticle::SetField(event->GetMagneticField());
      RunV0(event);
    }
    EndV0();
    delete event;
    ef->Close();
  }
  StartV0();
  return 0;
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkPolylineMaskImageFilterTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include <itkImage.h>
#include <itkImageRegionIteratorWithIndex.h>
#include <itkPolylineMaskImageFilter.h>
#include <itkPolyLineParametricPath.h>
#include <itkEllipseSpatialObject.h>
#include <itkSpatialObjectToImageFilter.h>
#include <itkImageFileWriter.h>
#include <iostream>

int itkPolylineMaskImageFilterTest(int argc, char * argv[] )
{
  /*
  if(argc < 3)
    {
    std::cerr << "Missing arguments" << std::endl;
    std::cerr << "Filter usage:" << std :: endl;
    std::cerr << "   SpatialObjectOutputImage" << "   MaskedOutputImage"<<std::endl;
    exit(1);
    }
  */
  // Define the dimension of the images
  const unsigned int iDimension = 3;

  //Define the dimension of the polyline
  const unsigned int pDimension = 2;

  // Declare the types of the images
  typedef itk::Image<unsigned short, iDimension>     inputImageType;
  typedef itk::Image<unsigned short, iDimension>     outputImageType;
  typedef itk::Vector<double, iDimension>            inputVectorType;
  typedef itk::PolyLineParametricPath<pDimension>    inputPolylineType;

  // Declare the type of the index to access images
  typedef itk::Index<iDimension>         inputIndexType;

  // Declare the type of the size
  typedef itk::Size<iDimension>          inputSizeType;

  // Declare the type of the Region
  typedef itk::ImageRegion<iDimension>   inputRegionType;

  // Create vector
  inputVectorType   inputUpVector,inputViewVector;

  // Create polyline
  inputPolylineType::Pointer inputPolyline   = inputPolylineType::New();
  std::cout<<"Generating the synthetic object...."<<std::endl;
  //Generate ellipse image

  typedef itk::EllipseSpatialObject<2>   EllipseType;
  EllipseType::Pointer ellipse = EllipseType::New();
  EllipseType::TransformType::OffsetType offset;
  offset.Fill(20);
  ellipse->GetObjectToParentTransform()->SetOffset(offset);
  ellipse->ComputeObjectToWorldTransform();
  ellipse->SetRadius(10);

  std::cout<<"Generating the image of the object...."<<std::endl;

  typedef itk::SpatialObjectToImageFilter<EllipseType,inputImageType> SpatialObjectToImageFilterType;
  SpatialObjectToImageFilterType::Pointer imageGenerationFilter = SpatialObjectToImageFilterType::New();

  inputImageType::SizeType size;
  inputImageType::PointType origin;

  origin[0] = 0.0;
  origin[1] = 0.0;
  origin[2] = 20.0;

  size[0]=40;
  size[1]=40;
  size[2]=35;

  imageGenerationFilter->SetOrigin(origin);
  imageGenerationFilter->SetSize(size);
  imageGenerationFilter->SetInput(ellipse);
  imageGenerationFilter->SetInsideValue(2);
  imageGenerationFilter->SetOutsideValue(0);
  imageGenerationFilter->Update();

  //Write out the input image
/*
  typedef  itk::ImageFileWriter<  inputImageType  > SpatialObjectImageWriterType;
  SpatialObjectImageWriterType::Pointer spatialObjectImageWriter = SpatialObjectImageWriterType::New();
  spatialObjectImageWriter->SetFileName( argv[1] );
  spatialObjectImageWriter->SetInput( imageGenerationFilter->GetOutput() );
  spatialObjectImageWriter->Update();
*/

  std::cout << "Generating the polyline contour..." << std::endl;
  //Initialize the polyline
  typedef inputPolylineType::VertexType VertexType;

  // Add vertices to the polyline

  VertexType v;
  v[0] = 19;
  v[1] = 0;
  inputPolyline->AddVertex(v);

  v[0] = 19;
  v[1] = 39;
  inputPolyline->AddVertex(v);

  v[0] = 25;
  v[1] = 39;
  inputPolyline->AddVertex(v);

  v[0] = 25;
  v[1] = 1;
  inputPolyline->AddVertex(v);

  std::cout << "Generating the view vector..... " << std::endl;

  // View vector
  inputViewVector[0] = 0;
  inputViewVector[1] = 0;
  inputViewVector[2] = -1;

  // Up vector
  inputUpVector[0] = 1;
  inputUpVector[1] = 0;
  inputUpVector[2] = 0;

  // Declare the type for the Mask image filter
  typedef itk::PolylineMaskImageFilter<
                           inputImageType, inputPolylineType,
                           inputVectorType,
                           outputImageType  >     inputFilterType;

  typedef inputFilterType::PointType PointType;
  typedef inputFilterType::ProjPlanePointType ProjPlanePointType;

  std::cout<< "Generating the filter....................." << std::endl;

  // Create a mask  Filter
  inputFilterType::Pointer filter = inputFilterType::New();

  //filter->DebugOn();
  //Connect the input image
  filter->SetInput1    ( imageGenerationFilter->GetOutput());

  inputImageType::PointType originA;

  /*
  originA = imageGenerationFilter->GetOutput()->GetOrigin();
  std::cout<<"Input image origin="<<originA<<std::endl;
*/

  // Connect the Polyline
  filter->SetInput2    ( inputPolyline );

  // Connect the Viewing direction vector
  filter->SetViewVector   ( inputViewVector );

  // Connect the Viewing direction vector
  filter->SetUpVector   ( inputUpVector );

  // camera center point
  PointType cameraCenterPoint;

  cameraCenterPoint[0] = 20;
  cameraCenterPoint[1] = 20;
  cameraCenterPoint[2] = 60;

  filter->SetCameraCenterPoint   ( cameraCenterPoint );

  // camera focal distance
  filter->SetFocalDistance(30.0);

  // camera focal point in the projection plane
  ProjPlanePointType focalpoint;
  focalpoint[0] = 20.0;
  focalpoint[1] = 20.0;
  filter->SetFocalPoint(focalpoint);
  filter->Update();

  //Write out the output image

  /*
  typedef  itk::ImageFileWriter<  outputImageType  > OutputWriterType;
  OutputWriterType::Pointer outputWriter = OutputWriterType::New();
  outputWriter->SetFileName( argv[2] );
  outputWriter->SetInput( filter->GetOutput() );
  outputWriter->Update();
*/

  return 0;

}

<commit_msg>COMP: warnings<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkPolylineMaskImageFilterTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include <itkImage.h>
#include <itkImageRegionIteratorWithIndex.h>
#include <itkPolylineMaskImageFilter.h>
#include <itkPolyLineParametricPath.h>
#include <itkEllipseSpatialObject.h>
#include <itkSpatialObjectToImageFilter.h>
#include <itkImageFileWriter.h>
#include <iostream>

int itkPolylineMaskImageFilterTest(int , char * [] )
{
  /*
  if(argc < 3)
    {
    std::cerr << "Missing arguments" << std::endl;
    std::cerr << "Filter usage:" << std :: endl;
    std::cerr << "   SpatialObjectOutputImage" << "   MaskedOutputImage"<<std::endl;
    exit(1);
    }
  */
  // Define the dimension of the images
  const unsigned int iDimension = 3;

  //Define the dimension of the polyline
  const unsigned int pDimension = 2;

  // Declare the types of the images
  typedef itk::Image<unsigned short, iDimension>     inputImageType;
  typedef itk::Image<unsigned short, iDimension>     outputImageType;
  typedef itk::Vector<double, iDimension>            inputVectorType;
  typedef itk::PolyLineParametricPath<pDimension>    inputPolylineType;

  // Declare the type of the index to access images
  typedef itk::Index<iDimension>         inputIndexType;

  // Declare the type of the size
  typedef itk::Size<iDimension>          inputSizeType;

  // Declare the type of the Region
  typedef itk::ImageRegion<iDimension>   inputRegionType;

  // Create vector
  inputVectorType   inputUpVector,inputViewVector;

  // Create polyline
  inputPolylineType::Pointer inputPolyline   = inputPolylineType::New();
  std::cout<<"Generating the synthetic object...."<<std::endl;
  //Generate ellipse image

  typedef itk::EllipseSpatialObject<2>   EllipseType;
  EllipseType::Pointer ellipse = EllipseType::New();
  EllipseType::TransformType::OffsetType offset;
  offset.Fill(20);
  ellipse->GetObjectToParentTransform()->SetOffset(offset);
  ellipse->ComputeObjectToWorldTransform();
  ellipse->SetRadius(10);

  std::cout<<"Generating the image of the object...."<<std::endl;

  typedef itk::SpatialObjectToImageFilter<EllipseType,inputImageType> SpatialObjectToImageFilterType;
  SpatialObjectToImageFilterType::Pointer imageGenerationFilter = SpatialObjectToImageFilterType::New();

  inputImageType::SizeType size;
  inputImageType::PointType origin;

  origin[0] = 0.0;
  origin[1] = 0.0;
  origin[2] = 20.0;

  size[0]=40;
  size[1]=40;
  size[2]=35;

  imageGenerationFilter->SetOrigin(origin);
  imageGenerationFilter->SetSize(size);
  imageGenerationFilter->SetInput(ellipse);
  imageGenerationFilter->SetInsideValue(2);
  imageGenerationFilter->SetOutsideValue(0);
  imageGenerationFilter->Update();

  //Write out the input image
/*
  typedef  itk::ImageFileWriter<  inputImageType  > SpatialObjectImageWriterType;
  SpatialObjectImageWriterType::Pointer spatialObjectImageWriter = SpatialObjectImageWriterType::New();
  spatialObjectImageWriter->SetFileName( argv[1] );
  spatialObjectImageWriter->SetInput( imageGenerationFilter->GetOutput() );
  spatialObjectImageWriter->Update();
*/

  std::cout << "Generating the polyline contour..." << std::endl;
  //Initialize the polyline
  typedef inputPolylineType::VertexType VertexType;

  // Add vertices to the polyline

  VertexType v;
  v[0] = 19;
  v[1] = 0;
  inputPolyline->AddVertex(v);

  v[0] = 19;
  v[1] = 39;
  inputPolyline->AddVertex(v);

  v[0] = 25;
  v[1] = 39;
  inputPolyline->AddVertex(v);

  v[0] = 25;
  v[1] = 1;
  inputPolyline->AddVertex(v);

  std::cout << "Generating the view vector..... " << std::endl;

  // View vector
  inputViewVector[0] = 0;
  inputViewVector[1] = 0;
  inputViewVector[2] = -1;

  // Up vector
  inputUpVector[0] = 1;
  inputUpVector[1] = 0;
  inputUpVector[2] = 0;

  // Declare the type for the Mask image filter
  typedef itk::PolylineMaskImageFilter<
                           inputImageType, inputPolylineType,
                           inputVectorType,
                           outputImageType  >     inputFilterType;

  typedef inputFilterType::PointType PointType;
  typedef inputFilterType::ProjPlanePointType ProjPlanePointType;

  std::cout<< "Generating the filter....................." << std::endl;

  // Create a mask  Filter
  inputFilterType::Pointer filter = inputFilterType::New();

  //filter->DebugOn();
  //Connect the input image
  filter->SetInput1    ( imageGenerationFilter->GetOutput());

  inputImageType::PointType originA;

  /*
  originA = imageGenerationFilter->GetOutput()->GetOrigin();
  std::cout<<"Input image origin="<<originA<<std::endl;
*/

  // Connect the Polyline
  filter->SetInput2    ( inputPolyline );

  // Connect the Viewing direction vector
  filter->SetViewVector   ( inputViewVector );

  // Connect the Viewing direction vector
  filter->SetUpVector   ( inputUpVector );

  // camera center point
  PointType cameraCenterPoint;

  cameraCenterPoint[0] = 20;
  cameraCenterPoint[1] = 20;
  cameraCenterPoint[2] = 60;

  filter->SetCameraCenterPoint   ( cameraCenterPoint );

  // camera focal distance
  filter->SetFocalDistance(30.0);

  // camera focal point in the projection plane
  ProjPlanePointType focalpoint;
  focalpoint[0] = 20.0;
  focalpoint[1] = 20.0;
  filter->SetFocalPoint(focalpoint);
  filter->Update();

  //Write out the output image

  /*
  typedef  itk::ImageFileWriter<  outputImageType  > OutputWriterType;
  OutputWriterType::Pointer outputWriter = OutputWriterType::New();
  outputWriter->SetFileName( argv[2] );
  outputWriter->SetInput( filter->GetOutput() );
  outputWriter->Update();
*/

  return 0;

}

<|endoftext|>


<commit_before>#include <sirius.h>

int main(int argn, char** argv)
{
    using namespace sirius;

    Platform::initialize(1);

    {
        Global parameters;

        JSON_tree parser("sirius.json");

        parameters.read_unit_cell_input();

        parameters.set_lmax_apw(parser["lmax_apw"].get(10));
        parameters.set_lmax_pot(parser["lmax_pot"].get(10));
        parameters.set_lmax_rho(parser["lmax_rho"].get(10));
        parameters.set_pw_cutoff(parser["pw_cutoff"].get(20.0));
        parameters.set_aw_cutoff(parser["aw_cutoff"].get(7.0));
        parameters.set_gk_cutoff(parser["gk_cutoff"].get(7.0));

        parameters.unit_cell()->set_auto_rmt(parser["auto_rmt"].get(0));
        int num_mag_dims = parser["num_mag_dims"].get(0);
        int num_spins = (num_mag_dims == 0) ? 1 : 2;

        parameters.set_num_mag_dims(num_mag_dims);
        parameters.set_num_spins(num_spins);

        parameters.initialize();

        Potential* potential = new Potential(parameters);
        potential->allocate();

        std::vector<int> ngridk = parser["ngridk"].get(std::vector<int>(3, 1));

        int numkp = ngridk[0] * ngridk[1] * ngridk[2];
        int ik = 0;
        mdarray<double, 2> kpoints(3, numkp);
        std::vector<double> kpoint_weights(numkp);

        for (int i0 = 0; i0 < ngridk[0]; i0++)
        {
            for (int i1 = 0; i1 < ngridk[1]; i1++)
            {
                for (int i2 = 0; i2 < ngridk[2]; i2++)
                {
                    kpoints(0, ik) = double(i0) / ngridk[0];
                    kpoints(1, ik) = double(i1) / ngridk[1];
                    kpoints(2, ik) = double(i2) / ngridk[2];
                    kpoint_weights[ik] = 1.0 / numkp;
                    ik++;
                }
            }
        }

        K_set ks(parameters);
        ks.add_kpoints(kpoints, &kpoint_weights[0]);
        ks.initialize();

        Density* density = new Density(parameters);
        density->allocate();

        //if (Utils::file_exists(storage_file_name))
        //{
        //    density->load();
        //    potential->load();
        //}
        //else
        //{
        //    density->initial_density();
        //}

        density->initial_density();

        DFT_ground_state dft(parameters, potential, density, &ks);
        double potential_tol = parser["potential_tol"].get(1e-4);
        double energy_tol = parser["energy_tol"].get(1e-4);

        dft.scf_loop(potential_tol, energy_tol, parser["num_dft_iter"].get(100));

        //dft.relax_atom_positions();

        parameters.write_json_output();

        delete density;
        delete potential;

        parameters.clear();

        Timer::print();
    }

    Platform::barrier();
    Platform::finalize();
}
<commit_msg>start form saved potential<commit_after>#include <sirius.h>

int main(int argn, char** argv)
{
    using namespace sirius;

    Platform::initialize(1);

    {
        Global parameters;

        JSON_tree parser("sirius.json");

        parameters.read_unit_cell_input();

        parameters.set_lmax_apw(parser["lmax_apw"].get(10));
        parameters.set_lmax_pot(parser["lmax_pot"].get(10));
        parameters.set_lmax_rho(parser["lmax_rho"].get(10));
        parameters.set_pw_cutoff(parser["pw_cutoff"].get(20.0));
        parameters.set_aw_cutoff(parser["aw_cutoff"].get(7.0));
        parameters.set_gk_cutoff(parser["gk_cutoff"].get(7.0));

        parameters.unit_cell()->set_auto_rmt(parser["auto_rmt"].get(0));
        int num_mag_dims = parser["num_mag_dims"].get(0);
        int num_spins = (num_mag_dims == 0) ? 1 : 2;

        parameters.set_num_mag_dims(num_mag_dims);
        parameters.set_num_spins(num_spins);

        parameters.initialize();

        Potential* potential = new Potential(parameters);
        potential->allocate();

        std::vector<int> ngridk = parser["ngridk"].get(std::vector<int>(3, 1));

        int numkp = ngridk[0] * ngridk[1] * ngridk[2];
        int ik = 0;
        mdarray<double, 2> kpoints(3, numkp);
        std::vector<double> kpoint_weights(numkp);

        for (int i0 = 0; i0 < ngridk[0]; i0++)
        {
            for (int i1 = 0; i1 < ngridk[1]; i1++)
            {
                for (int i2 = 0; i2 < ngridk[2]; i2++)
                {
                    kpoints(0, ik) = double(i0) / ngridk[0];
                    kpoints(1, ik) = double(i1) / ngridk[1];
                    kpoints(2, ik) = double(i2) / ngridk[2];
                    kpoint_weights[ik] = 1.0 / numkp;
                    ik++;
                }
            }
        }

        K_set ks(parameters);
        ks.add_kpoints(kpoints, &kpoint_weights[0]);
        ks.initialize();

        Density* density = new Density(parameters);
        density->allocate();

        if (Utils::file_exists(storage_file_name))
        {
            density->load();
            potential->load();
        }
        else
        {
            density->initial_density();
        }

        DFT_ground_state dft(parameters, potential, density, &ks);
        double potential_tol = parser["potential_tol"].get(1e-4);
        double energy_tol = parser["energy_tol"].get(1e-4);

        dft.scf_loop(potential_tol, energy_tol, parser["num_dft_iter"].get(100));

        //dft.relax_atom_positions();

        parameters.write_json_output();

        delete density;
        delete potential;

        parameters.clear();

        Timer::print();
    }

    Platform::barrier();
    Platform::finalize();
}
<|endoftext|>


<commit_before>#include "Halide.h"

#include "fft.h"

namespace {

using namespace Halide;

enum class FFTNumberType { Real, Complex };
std::map<std::string, FFTNumberType> fft_number_type_enum_map() {
     return { { "real", FFTNumberType::Real },
              { "complex", FFTNumberType::Complex } };
}

// Direction of FFT. Samples can be read as "time" or "spatial" depending
// on the meaning of the input domain.
enum class FFTDirection { SamplesToFrequency, FrequencyToSamples };
std::map<std::string, FFTDirection> fft_direction_enum_map() {
  return { { "samples_to_frequency", FFTDirection::SamplesToFrequency },
           { "frequency_to_samples", FFTDirection::FrequencyToSamples } };
}

class FFTGenerator : public Halide::Generator<FFTGenerator> {
public:

    // Gain to apply to the FFT. This is folded into gains already
    // being applied to the FFT. A gain of 1.0f indicates an
    // unnormalized FFT. 1 / sqrt(N) gives a unitary transform such that
    // forward and inverse operations have the same gain without changing
    // signal magnitude.
    // A common convention is 1/N for the forward direction and 1 for the
    // inverse.
    // "N" above is the size of the input, which is the product of
    // the dimensions.
    GeneratorParam<float> gain{"gain", 1.0f};

    // The following option specifies that a particular vector width should be
    // used when the vector width can change the results of the FFT.
    // Some parts of the FFT algorithm use the vector width to change the way
    // floating point operations are ordered and grouped, which causes the results
    // to vary with respect to the target architecture. Setting this option forces
    // such stages to use the specified vector width (independent of the actual
    // architecture's vector width), which eliminates the architecture specific
    // behavior.
    GeneratorParam<int32_t> vector_width{"vector_width", 0};

    // The following option indicates that the FFT should parallelize within a
    // single FFT. This only makes sense to use on large FFTs, and generally only
    // if there is no outer loop around FFTs that can be parallelized.
    GeneratorParam<bool> parallel{"parallel", false};

    // Indicates forward or inverse Fourier transform --
    // "samples_to_frequency" maps to a forward FFT. (Other packages sometimes call this a sign of -1)
    // "frequency_to_samples" maps to a forward FFT. (Other packages sometimes call this a sign of +1)
    GeneratorParam<FFTDirection> direction{"direction", FFTDirection::SamplesToFrequency,
        fft_direction_enum_map() };

    // Whether the input is "real" or "complex".
    GeneratorParam<FFTNumberType> input_number_type{"input_number_type",
        FFTNumberType::Real, fft_number_type_enum_map() };
    // Whether the output is "real" or "complex".
    GeneratorParam<FFTNumberType> output_number_type{"output_number_type",
        FFTNumberType::Real, fft_number_type_enum_map() };

    // Size of first dimension, required to be greater than zero.
    GeneratorParam<int32_t> size0{"size0", 1};
    // Size of second dimension, may be zero for 1D FFT.
    GeneratorParam<int32_t> size1{"size1", 0};
    // TODO(zalman): Add support for 3D and maybe 4D FFTs

    // The input buffer. Must be separate from the output.
    // Only Float(32) is supported.
    //
    // For a real input FFT, this should have the following shape:
    // Dim0: extent = size0, stride = 1
    // Dim1: extent = size1 / 2 - 1, stride = size0
    // Dim2: extent = 1, stride = 1
    //
    // For a complex input FFT, this should have the following shape:
    // Dim0: extent = size0, stride = 2
    // Dim1: extent = size1, stride = size0 * 2
    // Dim2: extent = 2, stride = 1 (real followed by imaginary components)
    Input<Buffer<float>>  input{"input", 3};
    Output<Buffer<float>> output{"output", 3};

    void generate() {
        _halide_user_assert(size0 > 0) << "FFT must be at least 1D\n";

        Fft2dDesc desc;

        desc.gain = gain;
        desc.vector_width = vector_width;

        // The logic below calls the specialized r2c or c2r version if
        // applicable to take advantage of better scheduling. It is
        // assumed that projecting a real Func to a ComplexFunc and
        // immediately back has zero cost.

        const int sign = (direction == FFTDirection::SamplesToFrequency) ? -1 : 1;

        if (input_number_type == FFTNumberType::Real) {
            if (direction == FFTDirection::SamplesToFrequency) {
                // TODO: Not sure why this is necessary as ImageParam
                // -> Func conversion should happen, It may not work
                // with implicit dimension (use of _) logic in FFT.
                Func in;
                in(x, y) = input(x, y, 0);

                complex_result = fft2d_r2c(in, size0, size1, target, desc);
            } else {
                ComplexFunc in;
                in(x, y) = ComplexExpr(input(x, y, 0), 0);

                complex_result = fft2d_c2c(in, size0, size1, sign, target, desc);
            }
        } else {
            ComplexFunc in;
            in(x, y) = ComplexExpr(input(x, y, 0), input(x, y, 1));
            if (output_number_type == FFTNumberType::Real &&
                direction == FFTDirection::FrequencyToSamples) {
                real_result = fft2d_c2r(in, size0, size1, target, desc);
            } else {
                complex_result = fft2d_c2c(in, size0, size1, sign, target, desc);
            }
        }

        if (output_number_type == FFTNumberType::Real) {
            if (real_result.defined()) {
                 output(x, y, c) = real_result(x, y);
            } else {
                 output(x, y, c) = re(complex_result(x, y));
            }
        } else {
            output(x, y, c) = select(c == 0,
                                     re(complex_result(x, y)),
                                     im(complex_result(x, y)));
        }
    }

    void schedule() {
        const int input_comps = (input_number_type == FFTNumberType::Real) ? 1 : 2;
        const int output_comps = (output_number_type == FFTNumberType::Real) ? 1 : 2;

        input.dim(0).set_stride(input_comps)
             .dim(2).set_min(0).set_extent(input_comps).set_stride(1);

        output.dim(0).set_stride(output_comps)
              .dim(2).set_min(0).set_extent(output_comps).set_stride(1);

        if (real_result.defined()) {
            real_result.compute_at(output, y);
        }
    }
private:
    Var x{"x"}, y{"y"}, c{"c"};
    Func real_result;
    ComplexFunc complex_result;
};

Halide::RegisterGenerator<FFTGenerator> register_fft{"fft"};

}
<commit_msg>Fix some scheduling bugs.<commit_after>#include "Halide.h"

#include "fft.h"

namespace {

using namespace Halide;

enum class FFTNumberType { Real, Complex };
std::map<std::string, FFTNumberType> fft_number_type_enum_map() {
     return { { "real", FFTNumberType::Real },
              { "complex", FFTNumberType::Complex } };
}

// Direction of FFT. Samples can be read as "time" or "spatial" depending
// on the meaning of the input domain.
enum class FFTDirection { SamplesToFrequency, FrequencyToSamples };
std::map<std::string, FFTDirection> fft_direction_enum_map() {
  return { { "samples_to_frequency", FFTDirection::SamplesToFrequency },
           { "frequency_to_samples", FFTDirection::FrequencyToSamples } };
}

class FFTGenerator : public Halide::Generator<FFTGenerator> {
public:

    // Gain to apply to the FFT. This is folded into gains already
    // being applied to the FFT. A gain of 1.0f indicates an
    // unnormalized FFT. 1 / sqrt(N) gives a unitary transform such that
    // forward and inverse operations have the same gain without changing
    // signal magnitude.
    // A common convention is 1/N for the forward direction and 1 for the
    // inverse.
    // "N" above is the size of the input, which is the product of
    // the dimensions.
    GeneratorParam<float> gain{"gain", 1.0f};

    // The following option specifies that a particular vector width should be
    // used when the vector width can change the results of the FFT.
    // Some parts of the FFT algorithm use the vector width to change the way
    // floating point operations are ordered and grouped, which causes the results
    // to vary with respect to the target architecture. Setting this option forces
    // such stages to use the specified vector width (independent of the actual
    // architecture's vector width), which eliminates the architecture specific
    // behavior.
    GeneratorParam<int32_t> vector_width{"vector_width", 0};

    // The following option indicates that the FFT should parallelize within a
    // single FFT. This only makes sense to use on large FFTs, and generally only
    // if there is no outer loop around FFTs that can be parallelized.
    GeneratorParam<bool> parallel{"parallel", false};

    // Indicates forward or inverse Fourier transform --
    // "samples_to_frequency" maps to a forward FFT. (Other packages sometimes call this a sign of -1)
    // "frequency_to_samples" maps to a forward FFT. (Other packages sometimes call this a sign of +1)
    GeneratorParam<FFTDirection> direction{"direction", FFTDirection::SamplesToFrequency,
        fft_direction_enum_map() };

    // Whether the input is "real" or "complex".
    GeneratorParam<FFTNumberType> input_number_type{"input_number_type",
        FFTNumberType::Real, fft_number_type_enum_map() };
    // Whether the output is "real" or "complex".
    GeneratorParam<FFTNumberType> output_number_type{"output_number_type",
        FFTNumberType::Real, fft_number_type_enum_map() };

    // Size of first dimension, required to be greater than zero.
    GeneratorParam<int32_t> size0{"size0", 1};
    // Size of second dimension, may be zero for 1D FFT.
    GeneratorParam<int32_t> size1{"size1", 0};
    // TODO(zalman): Add support for 3D and maybe 4D FFTs

    // The input buffer. Must be separate from the output.
    // Only Float(32) is supported.
    //
    // For a real input FFT, this should have the following shape:
    // Dim0: extent = size0, stride = 1
    // Dim1: extent = size1 / 2 - 1, stride = size0
    // Dim2: extent = 1, stride = 1
    //
    // For a complex input FFT, this should have the following shape:
    // Dim0: extent = size0, stride = 2
    // Dim1: extent = size1, stride = size0 * 2
    // Dim2: extent = 2, stride = 1 (real followed by imaginary components)
    Input<Buffer<float>>  input{"input", 3};
    Output<Buffer<float>> output{"output", 3};

    void generate() {
        _halide_user_assert(size0 > 0) << "FFT must be at least 1D\n";

        Fft2dDesc desc;

        desc.gain = gain;
        desc.vector_width = vector_width;

        // The logic below calls the specialized r2c or c2r version if
        // applicable to take advantage of better scheduling. It is
        // assumed that projecting a real Func to a ComplexFunc and
        // immediately back has zero cost.

        const int sign = (direction == FFTDirection::SamplesToFrequency) ? -1 : 1;

        if (input_number_type == FFTNumberType::Real) {
            if (direction == FFTDirection::SamplesToFrequency) {
                // TODO: Not sure why this is necessary as ImageParam
                // -> Func conversion should happen, It may not work
                // with implicit dimension (use of _) logic in FFT.
                Func in;
                in(x, y) = input(x, y, 0);

                complex_result = fft2d_r2c(in, size0, size1, target, desc);
            } else {
                ComplexFunc in;
                in(x, y) = ComplexExpr(input(x, y, 0), 0);

                complex_result = fft2d_c2c(in, size0, size1, sign, target, desc);
            }
        } else {
            ComplexFunc in;
            in(x, y) = ComplexExpr(input(x, y, 0), input(x, y, 1));
            if (output_number_type == FFTNumberType::Real &&
                direction == FFTDirection::FrequencyToSamples) {
                real_result = fft2d_c2r(in, size0, size1, target, desc);
            } else {
                complex_result = fft2d_c2c(in, size0, size1, sign, target, desc);
            }
        }

        if (output_number_type == FFTNumberType::Real) {
            if (real_result.defined()) {
                 output(x, y, c) = real_result(x, y);
            } else {
                 output(x, y, c) = re(complex_result(x, y));
            }
        } else {
            output(x, y, c) = select(c == 0,
                                     re(complex_result(x, y)),
                                     im(complex_result(x, y)));
        }
    }

    void schedule() {
        const int input_comps = (input_number_type == FFTNumberType::Real) ? 1 : 2;
        const int output_comps = (output_number_type == FFTNumberType::Real) ? 1 : 2;

        input.dim(0).set_stride(input_comps)
             .dim(2).set_min(0).set_extent(input_comps).set_stride(1);

        output.dim(0).set_stride(output_comps)
              .dim(2).set_min(0).set_extent(output_comps).set_stride(1);

	if (output_comps != 1) {
  	    output.reorder(c, x, y).unroll(c);
	}

        if (real_result.defined()) {
  	    real_result.compute_at(output, Var::outermost());
        } else {
	    assert(complex_result.defined());
	    complex_result.compute_at(output, Var::outermost());
	}
    }
private:
    Var x{"x"}, y{"y"}, c{"c"};
    Func real_result;
    ComplexFunc complex_result;
};

Halide::RegisterGenerator<FFTGenerator> register_fft{"fft"};

}
<|endoftext|>


<commit_before>/*
    Copyright (C) 2000 by Jorrit Tyberghein
    With additions by Samuel Humphreys

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"
#include "cssys/sysfunc.h"
#include "cstool/initapp.h"
#include "apps/perftest/perftest.h"
#include "apps/perftest/ptests3d.h"
#include "apps/perftest/ptests2d.h"
#include "ivideo/graph3d.h"
#include "ivideo/graph2d.h"
#include "ivideo/natwin.h"
#include "ivideo/txtmgr.h"
#include "ivideo/fontserv.h"
#include "ivaria/conout.h"
#include "igraphic/imageio.h"
#include "igraphic/image.h"
#include "iutil/cmdline.h"
#include "iutil/event.h"
#include "iutil/objreg.h"
#include "iutil/eventh.h"
#include "iutil/eventq.h"
#include "iutil/comp.h"
#include "iutil/virtclk.h"
#include "csutil/cmdhelp.h"
#include "ivaria/reporter.h"
#include "iutil/plugin.h"
#include "iutil/vfs.h"

CS_IMPLEMENT_APPLICATION

//-----------------------------------------------------------------------------

// The global system driver
PerfTest *System;

PerfTest::PerfTest ()
{
  draw_3d = true;
  draw_2d = true;
  vc = NULL;
  myG3D = NULL;
  myVFS = NULL;
  ImageLoader = NULL;
  test_skip = false;
}

PerfTest::~PerfTest ()
{
  SCF_DEC_REF (vc);
  SCF_DEC_REF (myG3D);
  SCF_DEC_REF (myVFS);
  if (ImageLoader) ImageLoader->DecRef();
}

void PerfTest::Report (int severity, const char* msg, ...)
{
  va_list arg;
  va_start (arg, msg);
  iReporter* rep = CS_QUERY_REGISTRY (System->object_reg, iReporter);
  if (rep)
  {
    rep->ReportV (severity, "crystalspace.application.perftest", msg, arg);
    rep->DecRef ();
  }
  else
  {
    csPrintfV (msg, arg);
    csPrintf ("\n");
  }
  va_end (arg);
}

void Cleanup ()
{
  csPrintf ("Cleaning up...\n");
  iObjectRegistry* object_reg = System->object_reg;
  delete System; System = NULL;
  csInitializer::DestroyApplication (object_reg);
}

iMaterialHandle* PerfTest::LoadMaterial (char* file)
{
  iTextureManager* txtmgr = myG3D->GetTextureManager ();
  iImage* image;
  iDataBuffer *buf = myVFS->ReadFile (file);
  if (!buf || !buf->GetSize ())
  {
    Report (CS_REPORTER_SEVERITY_ERROR, "Error loading texture '%s'!", file);
    exit (-1);
  }
  image = ImageLoader->Load (buf->GetUint8 (), buf->GetSize (),
  	txtmgr->GetTextureFormat ());
  buf->DecRef ();
  if (!image) exit (-1);
  iTextureHandle* texture = txtmgr->RegisterTexture (image, CS_TEXTURE_3D);
  if (!texture) exit (-1);
  image->DecRef ();
  iMaterialHandle* mat = txtmgr->RegisterMaterial (texture);
  return mat;
}

static bool PerfEventHandler (iEvent& ev)
{
  if (ev.Type == csevBroadcast && ev.Command.Code == cscmdProcess)
  {
    System->SetupFrame ();
    return true;
  }
  else if (ev.Type == csevBroadcast && ev.Command.Code == cscmdFinalProcess)
  {
    System->FinishFrame ();
    return true;
  }
  else
  {
    return System ? System->HandleEvent (ev) : false;
  }
}

bool PerfTest::Initialize (int argc, const char* const argv[],
  const char *iConfigName)
{
  object_reg = csInitializer::CreateEnvironment (argc, argv);
  if (!object_reg) return false;

  if (!csInitializer::SetupConfigManager (object_reg, iConfigName))
  {
    Report (CS_REPORTER_SEVERITY_ERROR, "Couldn't initialize app!");
    return false;
  }

  if (!csInitializer::RequestPlugins (object_reg,
  	CS_REQUEST_VFS,
	CS_REQUEST_SOFTWARE3D,
	CS_REQUEST_FONTSERVER,
	CS_REQUEST_IMAGELOADER,
	CS_REQUEST_CONSOLEOUT,
	CS_REQUEST_END))
  {
    Report (CS_REPORTER_SEVERITY_ERROR, "Couldn't init app!");
    return false;
  }

  if (!csInitializer::SetupEventHandler (object_reg, PerfEventHandler))
  {
    Report (CS_REPORTER_SEVERITY_ERROR, "Couldn't init app!");
    return false;
  }

  // Check for commandline help.
  if (csCommandLineHelper::CheckHelp (object_reg))
  {
    csCommandLineHelper::Help (object_reg);
    exit (0);
  }

  // The virtual clock.
  vc = CS_QUERY_REGISTRY (object_reg, iVirtualClock);

  myG3D = CS_QUERY_REGISTRY (object_reg, iGraphics3D);
  if (!myG3D)
  {
    Report (CS_REPORTER_SEVERITY_ERROR, "No iGraphics3D plugin!");
    return false;
  }

  iGraphics2D* myG2D = myG3D->GetDriver2D ();
  iNativeWindow* nw = myG2D->GetNativeWindow ();
  if (nw) nw->SetTitle ("Crystal Space Graphics Performance Tester");

  // Open the main system. This will open all the previously loaded plug-ins.
  if (!csInitializer::OpenApplication (object_reg))
  {
    Report (CS_REPORTER_SEVERITY_ERROR, "Error opening system!");
    Cleanup ();
    exit (1);
  }

  ImageLoader = CS_QUERY_REGISTRY (object_reg, iImageIO);
  if (!ImageLoader)
  {
    Report (CS_REPORTER_SEVERITY_ERROR, "No image loader plugin!");
    return false;
  }

  myVFS = CS_QUERY_REGISTRY (object_reg, iVFS);
  if (!myVFS)
  {
    Report (CS_REPORTER_SEVERITY_ERROR, "No iVFS plugin!");
    return false;
  }

  // Setup the texture manager
  iTextureManager* txtmgr = myG3D->GetTextureManager ();
  txtmgr->SetVerbose (true);

  // Initialize the texture manager
  txtmgr->ResetPalette ();

  // Initialize textures.
  materials[0] = LoadMaterial ("/lib/std/stone4.gif");
  materials[1] = LoadMaterial ("/lib/std/mystone2.gif");
  materials[2] = LoadMaterial ("/lib/std/andrew_marble4.gif");
  materials[3] = LoadMaterial ("/lib/std/andrew_wood.gif");
  txtmgr->PrepareTextures ();

  // Allocate a uniformly distributed in R,G,B space palette for console
  // The console will crash on some platforms if this isn't initialize properly
  int r,g,b;
  for (r = 0; r < 8; r++)
    for (g = 0; g < 8; g++)
      for (b = 0; b < 4; b++)
	txtmgr->ReserveColor (r * 32, g * 32, b * 64);
  txtmgr->SetPalette ();

  // Some commercials...
  Report (CS_REPORTER_SEVERITY_NOTIFY,
    "Crystal Space 3D Performance Tester 0.1.");

  txtmgr->SetPalette ();

  const char *val;
  iCommandLineParser* cmdline = CS_QUERY_REGISTRY (object_reg,
  	iCommandLineParser);
  if ((val = cmdline->GetOption ("2d")))
  {
    current_tester = new StringTester ();
    draw_3d = false;
  }
  else
    current_tester = new SinglePolygonTester ();

  if ((val = cmdline->GetOption ("3d")))
    draw_2d = false;
  cmdline->DecRef ();

  needs_setup = true;

  return true;
}

static csTicks last_time;

void PerfTest::SetupFrame ()
{
  csTicks elapsed_time, current_time;
  elapsed_time = vc->GetElapsedTicks ();
  current_time = vc->GetCurrentTicks ();

  // Tell 3D driver we're going to display 3D things.
  if (!myG3D->BeginDraw (draw_3d ? CSDRAW_3DGRAPHICS : CSDRAW_2DGRAPHICS))
    return;

  // Setup if needed.
  if (needs_setup)
  {
    current_tester->Setup (myG3D, this);
    last_time = current_time;
  }

  // Do the test frame.
  if (current_tester)
  {
    current_tester->Draw (myG3D);
    if (test_skip || (current_time-last_time >= 10000))
    {
      test_skip = false;
      float totalelapsed = float(current_time - last_time)/1000.f;
      Report (CS_REPORTER_SEVERITY_NOTIFY, "%f FPS",
      	current_tester->GetCount ()/totalelapsed);
      Tester* next_tester = current_tester->NextTester ();
      delete current_tester;
      current_tester = next_tester;
      if (current_tester)
      {
        needs_setup = true;
	current_tester->Setup (myG3D, this);
      }
      else
      {
	if (draw_3d && draw_2d)
	{
	  draw_3d = false;
	  current_tester = new LineTester2D ();
	  needs_setup = true;
	  current_tester->Setup (myG3D, this);
	}
	else
	{
	  iEventQueue* q = CS_QUERY_REGISTRY (object_reg, iEventQueue);
	  if (q)
	  {
	    q->GetEventOutlet()->Broadcast (cscmdQuit);
	    q->DecRef ();
	  }
        }
      }
    }
  }

  // Start drawing 2D graphics.
  if (needs_setup)
  {
    if (!myG3D->BeginDraw (CSDRAW_2DGRAPHICS)) return;
    iConsoleOutput *Console = CS_QUERY_REGISTRY (object_reg, iConsoleOutput);
    if (Console)
    {
      Console->Clear ();
      Console->DecRef ();
    }
    last_time = current_time;
    char desc[255];
    current_tester->Description (desc);
    Report (CS_REPORTER_SEVERITY_NOTIFY, desc);
    needs_setup = false;
  }
}

void PerfTest::FinishFrame ()
{
  myG3D->FinishDraw ();
  myG3D->Print (NULL);
}

bool PerfTest::HandleEvent (iEvent &Event)
{
  if ((Event.Type == csevKeyDown) && (Event.Key.Code == CSKEY_ESC))
  {
    iEventQueue* q = CS_QUERY_REGISTRY (object_reg, iEventQueue);
    if (q)
    {
      q->GetEventOutlet()->Broadcast (cscmdQuit);
      q->DecRef ();
    }
    return true;
  }
  else if ((Event.Type == csevKeyDown) && (Event.Key.Code == ' '))
  {
    test_skip = true;
    return true;
  }

  return false;
}

/*---------------------------------------------------------------------*
 * Main function
 *---------------------------------------------------------------------*/
int main (int argc, char* argv[])
{
  srand (time (NULL));

  // Create our main class.
  System = new PerfTest ();

  // Initialize the main system. This will load all needed plug-ins
  // (3D, 2D, network, sound, ...) and initialize them.
  if (!System->Initialize (argc, argv, NULL))
  {
    System->Report (CS_REPORTER_SEVERITY_ERROR, "Error initializing system!");
    Cleanup ();
    exit (1);
  }

  // Main loop.
  csDefaultRunLoop(System->object_reg);

  // Cleanup.
  Cleanup ();

  return 0;
}
<commit_msg><commit_after>/*
    Copyright (C) 2000 by Jorrit Tyberghein
    With additions by Samuel Humphreys

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"
#include "cssys/sysfunc.h"
#include "cstool/initapp.h"
#include "apps/perftest/perftest.h"
#include "apps/perftest/ptests3d.h"
#include "apps/perftest/ptests2d.h"
#include "ivideo/graph3d.h"
#include "ivideo/graph2d.h"
#include "ivideo/natwin.h"
#include "ivideo/txtmgr.h"
#include "ivideo/fontserv.h"
#include "ivaria/conout.h"
#include "igraphic/imageio.h"
#include "igraphic/image.h"
#include "iutil/cmdline.h"
#include "iutil/event.h"
#include "iutil/objreg.h"
#include "iutil/eventh.h"
#include "iutil/eventq.h"
#include "iutil/comp.h"
#include "iutil/virtclk.h"
#include "csutil/cmdhelp.h"
#include "ivaria/reporter.h"
#include "iutil/plugin.h"
#include "iutil/vfs.h"

CS_IMPLEMENT_APPLICATION

//-----------------------------------------------------------------------------

// The global system driver
PerfTest *System;

PerfTest::PerfTest ()
{
  draw_3d = true;
  draw_2d = true;
  vc = NULL;
  myG3D = NULL;
  myVFS = NULL;
  ImageLoader = NULL;
  test_skip = false;
}

PerfTest::~PerfTest ()
{
  SCF_DEC_REF (vc);
  SCF_DEC_REF (myG3D);
  SCF_DEC_REF (myVFS);
  if (ImageLoader) ImageLoader->DecRef();
}

void PerfTest::Report (int severity, const char* msg, ...)
{
  va_list arg;
  va_start (arg, msg);
  iReporter* rep = CS_QUERY_REGISTRY (System->object_reg, iReporter);
  if (rep)
  {
    rep->ReportV (severity, "crystalspace.application.perftest", msg, arg);
    rep->DecRef ();
  }
  else
  {
    csPrintfV (msg, arg);
    csPrintf ("\n");
  }
  va_end (arg);
}

void Cleanup ()
{
  csPrintf ("Cleaning up...\n");
  iObjectRegistry* object_reg = System->object_reg;
  delete System; System = NULL;
  csInitializer::DestroyApplication (object_reg);
}

iMaterialHandle* PerfTest::LoadMaterial (char* file)
{
  iTextureManager* txtmgr = myG3D->GetTextureManager ();
  iImage* image;
  iDataBuffer *buf = myVFS->ReadFile (file);
  if (!buf || !buf->GetSize ())
  {
    Report (CS_REPORTER_SEVERITY_ERROR, "Error loading texture '%s'!", file);
    exit (-1);
  }
  image = ImageLoader->Load (buf->GetUint8 (), buf->GetSize (),
  	txtmgr->GetTextureFormat ());
  buf->DecRef ();
  if (!image) exit (-1);
  iTextureHandle* texture = txtmgr->RegisterTexture (image, CS_TEXTURE_3D);
  if (!texture) exit (-1);
  image->DecRef ();
  iMaterialHandle* mat = txtmgr->RegisterMaterial (texture);
  return mat;
}

static bool PerfEventHandler (iEvent& ev)
{
  if (ev.Type == csevBroadcast && ev.Command.Code == cscmdProcess)
  {
    System->SetupFrame ();
    return true;
  }
  else if (ev.Type == csevBroadcast && ev.Command.Code == cscmdFinalProcess)
  {
    System->FinishFrame ();
    return true;
  }
  else
  {
    return System ? System->HandleEvent (ev) : false;
  }
}

bool PerfTest::Initialize (int argc, const char* const argv[],
  const char *iConfigName)
{
  object_reg = csInitializer::CreateEnvironment (argc, argv);
  if (!object_reg) return false;

  if (!csInitializer::SetupConfigManager (object_reg, iConfigName))
  {
    Report (CS_REPORTER_SEVERITY_ERROR, "Couldn't initialize app!");
    return false;
  }

  if (!csInitializer::RequestPlugins (object_reg,
  	CS_REQUEST_VFS,
	CS_REQUEST_SOFTWARE3D,
	CS_REQUEST_FONTSERVER,
	CS_REQUEST_IMAGELOADER,
	CS_REQUEST_CONSOLEOUT,
	CS_REQUEST_END))
  {
    Report (CS_REPORTER_SEVERITY_ERROR, "Couldn't init app!");
    return false;
  }

  if (!csInitializer::SetupEventHandler (object_reg, PerfEventHandler))
  {
    Report (CS_REPORTER_SEVERITY_ERROR, "Couldn't init app!");
    return false;
  }

  // Check for commandline help.
  if (csCommandLineHelper::CheckHelp (object_reg))
  {
    csCommandLineHelper::Help (object_reg);
    exit (0);
  }

  // The virtual clock.
  vc = CS_QUERY_REGISTRY (object_reg, iVirtualClock);

  myG3D = CS_QUERY_REGISTRY (object_reg, iGraphics3D);
  if (!myG3D)
  {
    Report (CS_REPORTER_SEVERITY_ERROR, "No iGraphics3D plugin!");
    return false;
  }

  iGraphics2D* myG2D = myG3D->GetDriver2D ();
  iNativeWindow* nw = myG2D->GetNativeWindow ();
  if (nw) nw->SetTitle ("Crystal Space Graphics Performance Tester");

  // Open the main system. This will open all the previously loaded plug-ins.
  if (!csInitializer::OpenApplication (object_reg))
  {
    Report (CS_REPORTER_SEVERITY_ERROR, "Error opening system!");
    Cleanup ();
    exit (1);
  }

  ImageLoader = CS_QUERY_REGISTRY (object_reg, iImageIO);
  if (!ImageLoader)
  {
    Report (CS_REPORTER_SEVERITY_ERROR, "No image loader plugin!");
    return false;
  }

  myVFS = CS_QUERY_REGISTRY (object_reg, iVFS);
  if (!myVFS)
  {
    Report (CS_REPORTER_SEVERITY_ERROR, "No iVFS plugin!");
    return false;
  }

  // Setup the texture manager
  iTextureManager* txtmgr = myG3D->GetTextureManager ();
  txtmgr->SetVerbose (true);

  // Initialize the texture manager
  txtmgr->ResetPalette ();

  // Initialize textures.
  materials[0] = LoadMaterial ("/lib/std/stone4.gif");
  materials[1] = LoadMaterial ("/lib/std/mystone2.gif");
  materials[2] = LoadMaterial ("/lib/std/andrew_marble4.gif");
  materials[3] = LoadMaterial ("/lib/std/andrew_wood.gif");
  txtmgr->PrepareTextures ();

  // Allocate a uniformly distributed in R,G,B space palette for console
  // The console will crash on some platforms if this isn't initialize properly
  int r,g,b;
  for (r = 0; r < 8; r++)
    for (g = 0; g < 8; g++)
      for (b = 0; b < 4; b++)
	txtmgr->ReserveColor (r * 32, g * 32, b * 64);
  txtmgr->SetPalette ();

  // Some commercials...
  Report (CS_REPORTER_SEVERITY_NOTIFY,
    "Crystal Space 3D Performance Tester 0.1.");

  txtmgr->SetPalette ();

  const char *val;
  iCommandLineParser* cmdline = CS_QUERY_REGISTRY (object_reg,
  	iCommandLineParser);
  val = cmdline->GetOption ("2d");
  if (val)
  {
    current_tester = new StringTester ();
    draw_3d = false;
  }
  else
    current_tester = new SinglePolygonTester ();

  val = cmdline->GetOption ("3d");
  if (val)
    draw_2d = false;
  cmdline->DecRef ();

  needs_setup = true;

  return true;
}

static csTicks last_time;

void PerfTest::SetupFrame ()
{
  csTicks elapsed_time, current_time;
  elapsed_time = vc->GetElapsedTicks ();
  current_time = vc->GetCurrentTicks ();

  // Tell 3D driver we're going to display 3D things.
  if (!myG3D->BeginDraw (draw_3d ? CSDRAW_3DGRAPHICS : CSDRAW_2DGRAPHICS))
    return;

  // Setup if needed.
  if (needs_setup)
  {
    current_tester->Setup (myG3D, this);
    last_time = current_time;
  }

  // Do the test frame.
  if (current_tester)
  {
    current_tester->Draw (myG3D);
    if (test_skip || (current_time-last_time >= 10000))
    {
      test_skip = false;
      float totalelapsed = float(current_time - last_time)/1000.f;
      Report (CS_REPORTER_SEVERITY_NOTIFY, "%f FPS",
      	current_tester->GetCount ()/totalelapsed);
      Tester* next_tester = current_tester->NextTester ();
      delete current_tester;
      current_tester = next_tester;
      if (current_tester)
      {
        needs_setup = true;
	current_tester->Setup (myG3D, this);
      }
      else
      {
	if (draw_3d && draw_2d)
	{
	  draw_3d = false;
	  current_tester = new LineTester2D ();
	  needs_setup = true;
	  current_tester->Setup (myG3D, this);
	}
	else
	{
	  iEventQueue* q = CS_QUERY_REGISTRY (object_reg, iEventQueue);
	  if (q)
	  {
	    q->GetEventOutlet()->Broadcast (cscmdQuit);
	    q->DecRef ();
	  }
        }
      }
    }
  }

  // Start drawing 2D graphics.
  if (needs_setup)
  {
    if (!myG3D->BeginDraw (CSDRAW_2DGRAPHICS)) return;
    iConsoleOutput *Console = CS_QUERY_REGISTRY (object_reg, iConsoleOutput);
    if (Console)
    {
      Console->Clear ();
      Console->DecRef ();
    }
    last_time = current_time;
    char desc[255];
    current_tester->Description (desc);
    Report (CS_REPORTER_SEVERITY_NOTIFY, desc);
    needs_setup = false;
  }
}

void PerfTest::FinishFrame ()
{
  myG3D->FinishDraw ();
  myG3D->Print (NULL);
}

bool PerfTest::HandleEvent (iEvent &Event)
{
  if ((Event.Type == csevKeyDown) && (Event.Key.Code == CSKEY_ESC))
  {
    iEventQueue* q = CS_QUERY_REGISTRY (object_reg, iEventQueue);
    if (q)
    {
      q->GetEventOutlet()->Broadcast (cscmdQuit);
      q->DecRef ();
    }
    return true;
  }
  else if ((Event.Type == csevKeyDown) && (Event.Key.Code == ' '))
  {
    test_skip = true;
    return true;
  }

  return false;
}

/*---------------------------------------------------------------------*
 * Main function
 *---------------------------------------------------------------------*/
int main (int argc, char* argv[])
{
  srand (time (NULL));

  // Create our main class.
  System = new PerfTest ();

  // Initialize the main system. This will load all needed plug-ins
  // (3D, 2D, network, sound, ...) and initialize them.
  if (!System->Initialize (argc, argv, NULL))
  {
    System->Report (CS_REPORTER_SEVERITY_ERROR, "Error initializing system!");
    Cleanup ();
    exit (1);
  }

  // Main loop.
  csDefaultRunLoop(System->object_reg);

  // Cleanup.
  Cleanup ();

  return 0;
}
<|endoftext|>


<commit_before>#include "DefaultReporter.h"
#include <iostream>
#include "TestDetails.h"

namespace xUnitpp
{

namespace DefaultReporter
{
    void ReportStart(const TestDetails &)
    {
    }

    void ReportFailure(const TestDetails &testDetails, const std::string &msg)
    {
        std::cout << (testDetails.Filename + ":" + std::to_string(testDetails.Line) +
            " error: Test [" + testDetails.Name + "] failed with: " + msg + "\n");
    }

    void ReportFinish(const TestDetails &, std::chrono::milliseconds)
    {
    }

    void ReportAllTestsComplete(size_t testCount, size_t failureCount, size_t skipped, std::chrono::milliseconds totalTime)
    {
        std::string total = std::to_string(testCount) + " tests, ";
        std::string failures = std::to_string(failureCount) + " failed, ";
        std::string skips = std::to_string(skipped) + " skipped.\n";

        std::string header;

        if (failureCount > 0)
        {
            header = "FAILURE: ";
        }
        else if (skipped > 0)
        {
            header = "WARNING: ";
        }
        else
        {
            header = "Success: ";
        }

        std::cout << (header + total + failures + skips);

        header = "Test time: ";
        std::cout << (header + std::to_string(totalTime.count()) + " milliseconds.\n");
    }

}

}
<commit_msg>making the default output more closely match what Visual Studio expects<commit_after>#include "DefaultReporter.h"
#include <cstdio>
#include <iostream>
#include "TestDetails.h"

namespace xUnitpp
{

namespace DefaultReporter
{
    void ReportStart(const TestDetails &)
    {
    }

    void ReportFailure(const TestDetails &testDetails, const std::string &msg)
    {
        std::cerr << (testDetails.Filename + "(" + std::to_string(testDetails.Line) +
            "): error " + testDetails.Name + ": " + msg + "\n");
    }

    void ReportFinish(const TestDetails &, std::chrono::milliseconds)
    {
    }

    void ReportAllTestsComplete(size_t testCount, size_t failureCount, size_t skipped, std::chrono::milliseconds totalTime)
    {
        std::string total = std::to_string(testCount) + " tests, ";
        std::string failures = std::to_string(failureCount) + " failed, ";
        std::string skips = std::to_string(skipped) + " skipped.\n";

        std::string header;

        if (failureCount > 0)
        {
            header = "FAILURE: ";
        }
        else if (skipped > 0)
        {
            header = "WARNING: ";
        }
        else
        {
            header = "Success: ";
        }

        std::cout << (header + total + failures + skips);

        header = "Test time: ";
        std::cout << (header + std::to_string(totalTime.count()) + " milliseconds.\n");
    }

}

}
<|endoftext|>