<commit_before>
/* nativeRecognizer.java
 * See the file "LICENSE.md" for the full license governing this code.
 */

#include <stdio.h>
#include <string.h>
#include <jni.h>
#include <android/log.h>
#include <android/bitmap.h>

#include "opencv2/core/core_c.h"
#include "opencv2/imgproc/imgproc_c.h"

#include "dmz.h"
#include "processor_support.h"
#include "dmz_debug.h"
#include "cv/warp.h"

#include "scan/scan.h"

#define DEBUG_TAG "card.io native"

static dmz_context* dmz = NULL;
static int dmz_refcount = 0;

static ScannerState scanner;
static bool detectOnly;
static bool flipped;
static bool lastFrameWasUsable;
static float minFocusScore;

static struct {
	jclass classRef;
	jfieldID top;
	jfieldID bottom;
	jfieldID left;
	jfieldID right;
} rectId;

static struct {
	jclass classRef;
	jfieldID topEdge;
	jfieldID bottomEdge;
	jfieldID leftEdge;
	jfieldID rightEdge;
	jfieldID focusScore;
	jfieldID prediction;
	jfieldID detectedCard;
} detectionInfoId;

static struct {
	jclass classRef;
	jfieldID flipped;
	jfieldID yoff;
	jfieldID xoff;
} creditCardId;

static struct {
	jclass classRef;
	jmethodID edgeUpdateCallback;
} cardScannerId;

extern "C"
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
	JNIEnv* env;
	jint status = vm->GetEnv( (void**) &env, JNI_VERSION_1_6);
	if (status != JNI_OK)
		return -1;

	/* find class ref and field IDs.
	 * class refs must be explicitly stated as global.
	 * field IDs could change with a new classloader, but this method will get called in that case.
	 * see http://www.milk.com/kodebase/dalvik-docs-mirror/docs/jni-tips.html
	 */

	jclass myClass = env->FindClass("io/card/payment/CardScanner");
	if (!myClass) {
		dmz_error_log("Couldn't find CardScanner from JNI");
		return -1;
	}
	cardScannerId.classRef = (jclass)env->NewGlobalRef(myClass);
	cardScannerId.edgeUpdateCallback = env->GetMethodID(myClass, "onEdgeUpdate", "(Lio/card/payment/DetectionInfo;)V");
	if (!cardScannerId.edgeUpdateCallback) {
		dmz_error_log("Couldn't find edge update callback");
		return -1;
	}

	jclass rectClass = env->FindClass("android/graphics/Rect");
	if (!rectClass) {
		dmz_error_log("Couldn't find Rect class");
		return -1;
	}
	rectId.classRef = (jclass)env->NewGlobalRef(rectClass);
	rectId.top = env->GetFieldID(rectClass, "top", "I");
	rectId.bottom = env->GetFieldID(rectClass, "bottom", "I");
	rectId.left = env->GetFieldID(rectClass, "left", "I");
	rectId.right = env->GetFieldID(rectClass, "right", "I");

	if (!(rectId.top && rectId.bottom && rectId.left && rectId.right)) {
		dmz_error_log("Couldn't find square class");
		return -1;
	}

	jclass creditCardClass = (jclass)env->FindClass("io/card/payment/CreditCard");
	if (creditCardClass == NULL) {
		dmz_error_log("Couldn't find CreditCard class");
		return -1;
	}
	creditCardId.classRef = (jclass)env->NewGlobalRef(creditCardClass);
	creditCardId.flipped = env->GetFieldID(creditCardClass, "flipped", "Z");
	creditCardId.yoff = env->GetFieldID(creditCardClass, "yoff", "I");
	creditCardId.xoff = env->GetFieldID(creditCardClass, "xoff", "[I");
	if (!( creditCardId.flipped && creditCardId.yoff && creditCardId.xoff )) {
		dmz_error_log("at least one filed was not found for CreditCard");
		return -1;
	}

	jclass dInfoClass = env->FindClass("io/card/payment/DetectionInfo");
	if (dInfoClass == NULL) {
		dmz_error_log("Couldn't find DetectionInfo class");
		return -1;
	}
	detectionInfoId.classRef = (jclass)env->NewGlobalRef(dInfoClass);
	detectionInfoId.topEdge = env->GetFieldID(dInfoClass, "topEdge", "Z");
	detectionInfoId.bottomEdge = env->GetFieldID(dInfoClass, "bottomEdge", "Z");
	detectionInfoId.leftEdge =  env->GetFieldID(dInfoClass, "leftEdge", "Z");
	detectionInfoId.rightEdge = env->GetFieldID(dInfoClass, "rightEdge", "Z");
	detectionInfoId.focusScore = env->GetFieldID(dInfoClass, "focusScore", "F");
	detectionInfoId.prediction = env->GetFieldID(dInfoClass, "prediction", "[I");
	detectionInfoId.detectedCard = env->GetFieldID(dInfoClass, "detectedCard", "Lio/card/payment/CreditCard;");

	if (!(detectionInfoId.topEdge && detectionInfoId.bottomEdge
			&& detectionInfoId.leftEdge && detectionInfoId.rightEdge
			&& detectionInfoId.focusScore && detectionInfoId.prediction
			&& detectionInfoId.detectedCard
	)) {
		dmz_error_log("at least one field was not found for DetectionInfo");
		return -1;
	}

    return JNI_VERSION_1_6;
}

extern "C"
JNIEXPORT void JNICALL Java_io_card_payment_CardScanner_nSetup(JNIEnv *env, jobject thiz,
		jboolean shouldOnlyDetectCard, jfloat jMinFocusScore) {
  dmz_debug_log("Java_io_card_payment_CardScanner_nSetup");
  dmz_trace_log("dmz trace enabled");

  detectOnly = shouldOnlyDetectCard;
  minFocusScore = jMinFocusScore;
  flipped = false;
  lastFrameWasUsable = false;

  if (dmz == NULL) {
	  dmz = dmz_context_create();
	  scanner_initialize(&scanner);
  }
  else {
	  scanner_reset(&scanner);
  }
  dmz_refcount++;

  cvSetErrMode(CV_ErrModeParent);
}

extern "C"
JNIEXPORT void JNICALL Java_io_card_payment_CardScanner_nResetAnalytics(JNIEnv *env, jobject thiz) {
	scanner_reset(&scanner);
}

extern "C"
JNIEXPORT void JNICALL Java_io_card_payment_CardScanner_nCleanup(JNIEnv *env, jobject thiz) {
  dmz_debug_log("Java_io_card_payment_CardScanner_nCleanup");

  if (dmz_refcount == 1) {
	  scanner_destroy(&scanner);
	  dmz_context_destroy(dmz);
	  dmz = NULL;
  }
  dmz_refcount--;
}

extern "C"
JNIEXPORT void JNICALL Java_io_card_payment_CardScanner_nGetGuideFrame(JNIEnv *env, jobject thiz,
  jint orientation, jint width, jint height, jobject rect)
{
  dmz_trace_log("Java_io_card_payment_CardScanner_nGetGuideFrame");

  dmz_rect dr = dmz_guide_frame(orientation, width, height);

  env->SetIntField(rect, rectId.top, dr.y);
  env->SetIntField(rect, rectId.left, dr.x);
  env->SetIntField(rect, rectId.bottom, dr.y + dr.h);
  env->SetIntField(rect, rectId.right, dr.x + dr.w);
}

void updateEdgeDetectDisplay(JNIEnv* env, jobject thiz, jobject dinfo, dmz_edges found_edges) {
	env->SetBooleanField(dinfo, detectionInfoId.topEdge, found_edges.top.found);
	env->SetBooleanField(dinfo, detectionInfoId.bottomEdge, found_edges.bottom.found);
	env->SetBooleanField(dinfo, detectionInfoId.leftEdge, found_edges.left.found);
	env->SetBooleanField(dinfo, detectionInfoId.rightEdge, found_edges.right.found);

	env->CallVoidMethod(thiz, cardScannerId.edgeUpdateCallback, dinfo);
}

void setScanResult(JNIEnv* env, jobject dinfo, ScannerResult* scanResult, FrameScanResult* frameResult) {

	jint numbers[16];
	jint offsets[16];
	for (int i=0; i<scanResult->n_numbers; i++) {
		numbers[i] = scanResult->predictions(i);
		offsets[i] = frameResult->hseg.offsets[i];
	}

	jobject digitArray = env->GetObjectField(dinfo, detectionInfoId.prediction);
	dmz_debug_log("setting prediction array region");
	env->SetIntArrayRegion((jintArray)digitArray, 0, scanResult->n_numbers, numbers);
	dmz_debug_log("done.");

	jobject cardObj = env->GetObjectField(dinfo, detectionInfoId.detectedCard);
	dmz_debug_log("got cardObj: %x", cardObj);
	env->SetIntField(cardObj, creditCardId.yoff, frameResult->vseg.y_offset);

	jobject xoffArray = env->GetObjectField(cardObj, creditCardId.xoff);
	dmz_debug_log("setting xoffset array region: %x", xoffArray);
	env->SetIntArrayRegion((jintArray)xoffArray, 0, scanResult->n_numbers, offsets);
	dmz_debug_log("done");
}

void setDetectedCardImage(JNIEnv* env, jobject jCardResultBitmap, IplImage* cardY, IplImage* cb, IplImage* cr,
		dmz_corner_points corner_points, int orientation) {

	char* pixels = NULL;

	AndroidBitmapInfo  bmInfo;
	int bmRes = AndroidBitmap_getInfo(env, jCardResultBitmap, &bmInfo);
	// Yes, it really is defined as _RESUT_ ... figures. <sigh>
	bool validCardInfo = (bmRes == ANDROID_BITMAP_RESUT_SUCCESS);
	if (!validCardInfo) {
		dmz_error_log("AndroidBitmap_getInfo() failed! error=%i", bmRes);
	}
	if (validCardInfo && bmInfo.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
		dmz_error_log("the dmz was given a bitmap that is not RGBA_8888");
		validCardInfo = false;
	}

	bmRes = AndroidBitmap_lockPixels(env, jCardResultBitmap, (void**) &pixels );
	if (bmRes != ANDROID_BITMAP_RESUT_SUCCESS) {
		dmz_error_log("couldn't lock bitmap:%i", bmRes);
	}
	else {
		IplImage* bigCb = NULL;
		dmz_transform_card(NULL, cb, corner_points, orientation, true, &bigCb);

		IplImage* bigCr = NULL;
		dmz_transform_card(NULL, cr, corner_points, orientation, true, &bigCr);

		IplImage* cardResult = cvCreateImageHeader(cvSize(bmInfo.width, bmInfo.height), IPL_DEPTH_8U, 4);
		cvSetData(cardResult, pixels, bmInfo.stride);

		dmz_YCbCr_to_RGB(cardY, bigCb, bigCr, &cardResult);
		AndroidBitmap_unlockPixels(env, jCardResultBitmap);

		cvReleaseImageHeader(&cardResult);
		cvReleaseImage(&bigCb);
		cvReleaseImage(&bigCr);
	}
}

/* This method forms the core of card.io scanning. All others (nCardDetected & nGetFocusScore) */
extern "C"
JNIEXPORT void JNICALL Java_io_card_payment_CardScanner_nScanFrame(JNIEnv *env, jobject thiz,
		jbyteArray jb, jint width, jint height, jint orientation, jobject dinfo,
		jobject jCardResultBitmap) {
	dmz_trace_log("Java_io_card_payment_CardScanner_nScanFrame ... width:%i height:%i orientation:%i", width, height, orientation);

	if (orientation == 0) {
		dmz_error_log("orientation is 0. Nothing good can come from this.");
		return;
	}

	if (flipped) {
		orientation = dmz_opposite_orientation(orientation);
	}

	FrameScanResult result;
  bool collectCardNumber = (scanner.timeOfCardNumberCompletionInMilliseconds == 0);

	IplImage *image = cvCreateImageHeader(cvSize(width, height), IPL_DEPTH_8U, 1);
	jbyte *jBytes = env->GetByteArrayElements(jb, 0);
	image->imageData = (char *)jBytes;

	float focusScore = dmz_focus_score(image, false);
	env->SetFloatField(dinfo, detectionInfoId.focusScore, focusScore);
	dmz_trace_log("focus score: %f", focusScore);
	if (focusScore >= minFocusScore) {

		IplImage *cbcr = cvCreateImageHeader(cvSize(width / 2, height / 2), IPL_DEPTH_8U, 2);
		cbcr->imageData = ((char *)jBytes) + width * height;
		IplImage *cb, *cr;
		dmz_deinterleave_uint8_c2(cbcr, &cr, &cb);
		cvReleaseImageHeader(&cbcr);

		dmz_edges found_edges;
		dmz_corner_points corner_points;
		bool cardDetected = dmz_detect_edges(image, cb, cr,
				orientation,
				&found_edges, &corner_points
		);

		updateEdgeDetectDisplay(env, thiz, dinfo, found_edges);

		if (cardDetected) {
			IplImage *cardY = NULL;
			dmz_transform_card(NULL, image, corner_points, orientation, false, &cardY);

			if (!detectOnly) {
				result.focus_score = focusScore;
				result.flipped = flipped;
				scanner_add_frame_with_expiry(&scanner, cardY, true, &result);
        if (collectCardNumber) {
          if (result.usable) {
            ScannerResult scanResult;
            scanner_result(&scanner, &scanResult);
            setScanResult(env, dinfo, &scanResult, &result);
          }
          else if (result.upside_down) {
            flipped = !flipped;
          }
        }
			}

			setDetectedCardImage(env, jCardResultBitmap, cardY, cb, cr, corner_points, orientation);
			cvReleaseImage(&cardY);
		}

		cvReleaseImage(&cb);
		cvReleaseImage(&cr);
	}

	cvReleaseImageHeader(&image);
	env->ReleaseByteArrayElements(jb, jBytes, 0);
}

extern "C"
JNIEXPORT jint JNICALL Java_io_card_payment_CardScanner_nGetNumFramesScanned(JNIEnv *env, jobject thiz) {
	return scanner.session_analytics.num_frames_scanned;
}

<commit_msg>update nativeRecognizer (for expiry)<commit_after>
/* nativeRecognizer.java
 * See the file "LICENSE.md" for the full license governing this code.
 */

#include <stdio.h>
#include <string.h>
#include <jni.h>
#include <android/log.h>
#include <android/bitmap.h>

#include "opencv2/core/core_c.h"
#include "opencv2/imgproc/imgproc_c.h"

#include "dmz.h"
#include "processor_support.h"
#include "dmz_debug.h"
#include "cv/warp.h"

#include "scan/scan.h"

#define DEBUG_TAG "card.io native"

static dmz_context* dmz = NULL;
static int dmz_refcount = 0;

static ScannerState scanner;
static bool detectOnly;
static bool flipped;
static bool lastFrameWasUsable;
static float minFocusScore;

static struct {
	jclass classRef;
	jfieldID top;
	jfieldID bottom;
	jfieldID left;
	jfieldID right;
} rectId;

static struct {
	jclass classRef;
	jfieldID topEdge;
	jfieldID bottomEdge;
	jfieldID leftEdge;
	jfieldID rightEdge;
	jfieldID focusScore;
	jfieldID prediction;
	jfieldID detectedCard;
} detectionInfoId;

static struct {
	jclass classRef;
	jfieldID flipped;
	jfieldID yoff;
	jfieldID xoff;
} creditCardId;

static struct {
	jclass classRef;
	jmethodID edgeUpdateCallback;
} cardScannerId;

extern "C"
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
	JNIEnv* env;
	jint status = vm->GetEnv( (void**) &env, JNI_VERSION_1_6);
	if (status != JNI_OK)
		return -1;

	/* find class ref and field IDs.
	 * class refs must be explicitly stated as global.
	 * field IDs could change with a new classloader, but this method will get called in that case.
	 * see http://www.milk.com/kodebase/dalvik-docs-mirror/docs/jni-tips.html
	 */

	jclass myClass = env->FindClass("io/card/payment/CardScanner");
	if (!myClass) {
		dmz_error_log("Couldn't find CardScanner from JNI");
		return -1;
	}
	cardScannerId.classRef = (jclass)env->NewGlobalRef(myClass);
	cardScannerId.edgeUpdateCallback = env->GetMethodID(myClass, "onEdgeUpdate", "(Lio/card/payment/DetectionInfo;)V");
	if (!cardScannerId.edgeUpdateCallback) {
		dmz_error_log("Couldn't find edge update callback");
		return -1;
	}

	jclass rectClass = env->FindClass("android/graphics/Rect");
	if (!rectClass) {
		dmz_error_log("Couldn't find Rect class");
		return -1;
	}
	rectId.classRef = (jclass)env->NewGlobalRef(rectClass);
	rectId.top = env->GetFieldID(rectClass, "top", "I");
	rectId.bottom = env->GetFieldID(rectClass, "bottom", "I");
	rectId.left = env->GetFieldID(rectClass, "left", "I");
	rectId.right = env->GetFieldID(rectClass, "right", "I");

	if (!(rectId.top && rectId.bottom && rectId.left && rectId.right)) {
		dmz_error_log("Couldn't find square class");
		return -1;
	}

	jclass creditCardClass = (jclass)env->FindClass("io/card/payment/CreditCard");
	if (creditCardClass == NULL) {
		dmz_error_log("Couldn't find CreditCard class");
		return -1;
	}
	creditCardId.classRef = (jclass)env->NewGlobalRef(creditCardClass);
	creditCardId.flipped = env->GetFieldID(creditCardClass, "flipped", "Z");
	creditCardId.yoff = env->GetFieldID(creditCardClass, "yoff", "I");
	creditCardId.xoff = env->GetFieldID(creditCardClass, "xoff", "[I");
	if (!( creditCardId.flipped && creditCardId.yoff && creditCardId.xoff )) {
		dmz_error_log("at least one filed was not found for CreditCard");
		return -1;
	}

	jclass dInfoClass = env->FindClass("io/card/payment/DetectionInfo");
	if (dInfoClass == NULL) {
		dmz_error_log("Couldn't find DetectionInfo class");
		return -1;
	}
	detectionInfoId.classRef = (jclass)env->NewGlobalRef(dInfoClass);
	detectionInfoId.topEdge = env->GetFieldID(dInfoClass, "topEdge", "Z");
	detectionInfoId.bottomEdge = env->GetFieldID(dInfoClass, "bottomEdge", "Z");
	detectionInfoId.leftEdge =  env->GetFieldID(dInfoClass, "leftEdge", "Z");
	detectionInfoId.rightEdge = env->GetFieldID(dInfoClass, "rightEdge", "Z");
	detectionInfoId.focusScore = env->GetFieldID(dInfoClass, "focusScore", "F");
	detectionInfoId.prediction = env->GetFieldID(dInfoClass, "prediction", "[I");
	detectionInfoId.detectedCard = env->GetFieldID(dInfoClass, "detectedCard", "Lio/card/payment/CreditCard;");

	if (!(detectionInfoId.topEdge && detectionInfoId.bottomEdge
			&& detectionInfoId.leftEdge && detectionInfoId.rightEdge
			&& detectionInfoId.focusScore && detectionInfoId.prediction
			&& detectionInfoId.detectedCard
	)) {
		dmz_error_log("at least one field was not found for DetectionInfo");
		return -1;
	}

    return JNI_VERSION_1_6;
}

extern "C"
JNIEXPORT void JNICALL Java_io_card_payment_CardScanner_nSetup(JNIEnv *env, jobject thiz,
		jboolean shouldOnlyDetectCard, jfloat jMinFocusScore) {
  dmz_debug_log("Java_io_card_payment_CardScanner_nSetup");
  dmz_trace_log("dmz trace enabled");

  detectOnly = shouldOnlyDetectCard;
  minFocusScore = jMinFocusScore;
  flipped = false;
  lastFrameWasUsable = false;

  if (dmz == NULL) {
	  dmz = dmz_context_create();
	  scanner_initialize(&scanner);
  }
  else {
	  scanner_reset(&scanner);
  }
  dmz_refcount++;

  cvSetErrMode(CV_ErrModeParent);
}

extern "C"
JNIEXPORT void JNICALL Java_io_card_payment_CardScanner_nResetAnalytics(JNIEnv *env, jobject thiz) {
	scanner_reset(&scanner);
}

extern "C"
JNIEXPORT void JNICALL Java_io_card_payment_CardScanner_nCleanup(JNIEnv *env, jobject thiz) {
  dmz_debug_log("Java_io_card_payment_CardScanner_nCleanup");

  if (dmz_refcount == 1) {
	  scanner_destroy(&scanner);
	  dmz_context_destroy(dmz);
	  dmz = NULL;
  }
  dmz_refcount--;
}

extern "C"
JNIEXPORT void JNICALL Java_io_card_payment_CardScanner_nGetGuideFrame(JNIEnv *env, jobject thiz,
  jint orientation, jint width, jint height, jobject rect)
{
  dmz_trace_log("Java_io_card_payment_CardScanner_nGetGuideFrame");

  dmz_rect dr = dmz_guide_frame(orientation, width, height);

  env->SetIntField(rect, rectId.top, dr.y);
  env->SetIntField(rect, rectId.left, dr.x);
  env->SetIntField(rect, rectId.bottom, dr.y + dr.h);
  env->SetIntField(rect, rectId.right, dr.x + dr.w);
}

void updateEdgeDetectDisplay(JNIEnv* env, jobject thiz, jobject dinfo, dmz_edges found_edges) {
	env->SetBooleanField(dinfo, detectionInfoId.topEdge, found_edges.top.found);
	env->SetBooleanField(dinfo, detectionInfoId.bottomEdge, found_edges.bottom.found);
	env->SetBooleanField(dinfo, detectionInfoId.leftEdge, found_edges.left.found);
	env->SetBooleanField(dinfo, detectionInfoId.rightEdge, found_edges.right.found);

	env->CallVoidMethod(thiz, cardScannerId.edgeUpdateCallback, dinfo);
}

void setScanResult(JNIEnv* env, jobject dinfo, ScannerResult* scanResult, FrameScanResult* frameResult) {

	jint numbers[16];
	jint offsets[16];
	for (int i=0; i<scanResult->n_numbers; i++) {
		numbers[i] = scanResult->predictions(i);
		offsets[i] = frameResult->hseg.offsets[i];
	}

	jobject digitArray = env->GetObjectField(dinfo, detectionInfoId.prediction);
	dmz_debug_log("setting prediction array region");
	env->SetIntArrayRegion((jintArray)digitArray, 0, scanResult->n_numbers, numbers);
	dmz_debug_log("done.");

	jobject cardObj = env->GetObjectField(dinfo, detectionInfoId.detectedCard);
	dmz_debug_log("got cardObj: %x", cardObj);
	env->SetIntField(cardObj, creditCardId.yoff, frameResult->vseg.y_offset);

	jobject xoffArray = env->GetObjectField(cardObj, creditCardId.xoff);
	dmz_debug_log("setting xoffset array region: %x", xoffArray);
	env->SetIntArrayRegion((jintArray)xoffArray, 0, scanResult->n_numbers, offsets);
	dmz_debug_log("done");
}

void setScanExpiryResult(JNIEnv* env, jobject dinfo, ScannerResult* scanResult, FrameScanResult* frameResult) {

  if (scanResult.expiry_month > 0 && scanResult.expiry_year > 0) {
    // *** copy expiry_month and expiry_year into Java object ***
  }
}

void setDetectedCardImage(JNIEnv* env, jobject jCardResultBitmap, IplImage* cardY, IplImage* cb, IplImage* cr,
		dmz_corner_points corner_points, int orientation) {

	char* pixels = NULL;

	AndroidBitmapInfo  bmInfo;
	int bmRes = AndroidBitmap_getInfo(env, jCardResultBitmap, &bmInfo);
	// Yes, it really is defined as _RESUT_ ... figures. <sigh>
	bool validCardInfo = (bmRes == ANDROID_BITMAP_RESUT_SUCCESS);
	if (!validCardInfo) {
		dmz_error_log("AndroidBitmap_getInfo() failed! error=%i", bmRes);
	}
	if (validCardInfo && bmInfo.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
		dmz_error_log("the dmz was given a bitmap that is not RGBA_8888");
		validCardInfo = false;
	}

	bmRes = AndroidBitmap_lockPixels(env, jCardResultBitmap, (void**) &pixels );
	if (bmRes != ANDROID_BITMAP_RESUT_SUCCESS) {
		dmz_error_log("couldn't lock bitmap:%i", bmRes);
	}
	else {
		IplImage* bigCb = NULL;
		dmz_transform_card(NULL, cb, corner_points, orientation, true, &bigCb);

		IplImage* bigCr = NULL;
		dmz_transform_card(NULL, cr, corner_points, orientation, true, &bigCr);

		IplImage* cardResult = cvCreateImageHeader(cvSize(bmInfo.width, bmInfo.height), IPL_DEPTH_8U, 4);
		cvSetData(cardResult, pixels, bmInfo.stride);

		dmz_YCbCr_to_RGB(cardY, bigCb, bigCr, &cardResult);
		AndroidBitmap_unlockPixels(env, jCardResultBitmap);

		cvReleaseImageHeader(&cardResult);
		cvReleaseImage(&bigCb);
		cvReleaseImage(&bigCr);
	}
}

/* This method forms the core of card.io scanning. All others (nCardDetected & nGetFocusScore) */
extern "C"
JNIEXPORT void JNICALL Java_io_card_payment_CardScanner_nScanFrame(JNIEnv *env, jobject thiz,
		jbyteArray jb, jint width, jint height, jint orientation, jobject dinfo,
		jobject jCardResultBitmap) {
	dmz_trace_log("Java_io_card_payment_CardScanner_nScanFrame ... width:%i height:%i orientation:%i", width, height, orientation);

	if (orientation == 0) {
		dmz_error_log("orientation is 0. Nothing good can come from this.");
		return;
	}

	if (flipped) {
		orientation = dmz_opposite_orientation(orientation);
	}

	FrameScanResult result;
  bool collectCardNumber = (scanner.timeOfCardNumberCompletionInMilliseconds == 0);

	IplImage *image = cvCreateImageHeader(cvSize(width, height), IPL_DEPTH_8U, 1);
	jbyte *jBytes = env->GetByteArrayElements(jb, 0);
	image->imageData = (char *)jBytes;

	float focusScore = dmz_focus_score(image, false);
	env->SetFloatField(dinfo, detectionInfoId.focusScore, focusScore);
	dmz_trace_log("focus score: %f", focusScore);
	if (focusScore >= minFocusScore) {

		IplImage *cbcr = cvCreateImageHeader(cvSize(width / 2, height / 2), IPL_DEPTH_8U, 2);
		cbcr->imageData = ((char *)jBytes) + width * height;
		IplImage *cb, *cr;
		dmz_deinterleave_uint8_c2(cbcr, &cr, &cb);
		cvReleaseImageHeader(&cbcr);

		dmz_edges found_edges;
		dmz_corner_points corner_points;
		bool cardDetected = dmz_detect_edges(image, cb, cr,
				orientation,
				&found_edges, &corner_points
		);

		updateEdgeDetectDisplay(env, thiz, dinfo, found_edges);

		if (cardDetected) {
			IplImage *cardY = NULL;
			dmz_transform_card(NULL, image, corner_points, orientation, false, &cardY);

			if (!detectOnly) {
				result.focus_score = focusScore;
				result.flipped = flipped;
				scanner_add_frame_with_expiry(&scanner, cardY, true, &result);
        if (result.usable) {
          ScannerResult scanResult;
          scanner_result(&scanner, &scanResult);
          if (collectCardNumber) {
            setScanResult(env, dinfo, &scanResult, &result);
          }
          setScanExpiryResult(env, dinfo, &scanResult, &result);
        }
        else if (result.upside_down) {
          flipped = !flipped;
        }
			}

			setDetectedCardImage(env, jCardResultBitmap, cardY, cb, cr, corner_points, orientation);
			cvReleaseImage(&cardY);
		}

		cvReleaseImage(&cb);
		cvReleaseImage(&cr);
	}

	cvReleaseImageHeader(&image);
	env->ReleaseByteArrayElements(jb, jBytes, 0);
}

extern "C"
JNIEXPORT jint JNICALL Java_io_card_payment_CardScanner_nGetNumFramesScanned(JNIEnv *env, jobject thiz) {
	return scanner.session_analytics.num_frames_scanned;
}

<|endoftext|>


<commit_before><commit_msg>Adding final comments to the code<commit_after><|endoftext|>


<commit_before>/**
 Copyright 2015 Joachim Wolff
 Master Thesis
 Tutor: Fabrizio Costa
 Winter semester 2015/2016

 Chair of Bioinformatics
 Department of Computer Science
 Faculty of Engineering
 Albert-Ludwig-University Freiburg im Breisgau
**/

#include <algorithm>
#include <iostream>
#include <iterator>
#include <utility>

#ifdef OPENMP
#include <omp.h>
#endif

#include "inverseIndex.h"

class sort_map {
  public:
    size_t key;
    size_t val;
};

bool mapSortDescByValue(const sort_map& a, const sort_map& b) {
        return a.val > b.val;
};

InverseIndex::InverseIndex(size_t pNumberOfHashFunctions, size_t pBlockSize,
                    size_t pNumberOfCores, size_t pChunkSize,
                    size_t pMaxBinSize, size_t pMinimalBlocksInCommon,
                    size_t pExcessFactor, size_t pMaximalNumberOfHashCollisions, size_t pBloomierFilter) {

    mNumberOfHashFunctions = pNumberOfHashFunctions;
    mBlockSize = pBlockSize;
    mNumberOfCores = pNumberOfCores;
    mChunkSize = pChunkSize;
    mMaxBinSize = pMaxBinSize;
    mMinimalBlocksInCommon = pMinimalBlocksInCommon;
    mExcessFactor = pExcessFactor;
    mMaximalNumberOfHashCollisions = pMaximalNumberOfHashCollisions;
    mSignatureStorage = new umap_uniqueElement();
    mHash = new Hash();
    size_t maximalFeatures = 5000;

    size_t inverseIndexSize = ceil(((float) mNumberOfHashFunctions / (float) mBlockSize)+1);
    if (pBloomierFilter) {
        // std::cout << "Using bloomier filter. " << std::endl;
        mInverseIndexStorage = new InverseIndexStorageBloomierFilter(inverseIndexSize, mMaxBinSize, maximalFeatures);
    } else {
        // std::cout << "Using unorderedMap. " << std::endl;

        mInverseIndexStorage = new InverseIndexStorageUnorderedMap(inverseIndexSize, mMaxBinSize);
    }
}

InverseIndex::~InverseIndex() {

    for (auto it = (*mSignatureStorage).begin(); it != (*mSignatureStorage).end(); ++it) {
        delete it->second->instances;
        delete it->second->signature;
        delete it->second;

    }
    delete mSignatureStorage;
    delete mHash;
}
 // compute the signature for one instance
vsize_t* InverseIndex::computeSignature(const SparseMatrixFloat* pRawData, const size_t pInstance) {

    vsize_t signatureHash;
    signatureHash.reserve(mNumberOfHashFunctions);

    for(size_t j = 0; j < mNumberOfHashFunctions; ++j) {
        size_t minHashValue = MAX_VALUE;
        for (size_t i = 0; i < pRawData->getSizeOfInstance(pInstance); ++i) {
            //  hash(size_t pKey, size_t pModulo, size_t pSeed)
            size_t hashValue = mHash->hash((pRawData->getNextElement(pInstance, i) +1), (j+1), MAX_VALUE);
            if (hashValue < minHashValue) {
                minHashValue = hashValue;
            }
        }
        signatureHash[j] = minHashValue;
    }
    // reduce number of hash values by a factor of blockSize
    size_t k = 0;
    vsize_t* signature = new vsize_t();
    signature->reserve((mNumberOfHashFunctions / mBlockSize) + 1);
    while (k < (mNumberOfHashFunctions)) {
        // use computed hash value as a seed for the next computation
        size_t signatureBlockValue = signatureHash[k];
        for (size_t j = 0; j < mBlockSize; ++j) {
            signatureBlockValue = mHash->hash((signatureHash[k+j]),  signatureBlockValue, MAX_VALUE);
        }
        signature->push_back(signatureBlockValue);
        k += mBlockSize;
    }
    return signature;
}
umap_uniqueElement* InverseIndex::computeSignatureMap(const SparseMatrixFloat* pRawData) {
    mDoubleElementsQueryCount = 0;
    const size_t sizeOfInstances = pRawData->size();
    umap_uniqueElement* instanceSignature = new umap_uniqueElement();
    (*instanceSignature).reserve(sizeOfInstances);
    if (mChunkSize <= 0) {
        mChunkSize = ceil(pRawData->size() / static_cast<float>(mNumberOfCores));
    }

#ifdef OPENMP
    omp_set_dynamic(0);
#endif

#ifdef OPENMP
#pragma omp parallel for schedule(static, mChunkSize) num_threads(mNumberOfCores)
#endif
    for(size_t index = 0; index < pRawData->size(); ++index) {
        // vsize_t* features = pRawData->getFeatureRow(index);
        // compute unique id
        size_t signatureId = 0;
        for (size_t j = 0; j < pRawData->getSizeOfInstance(index); ++j) {
                signatureId = mHash->hash((pRawData->getNextElement(index, j) +1), (signatureId+1), MAX_VALUE);
        }
        // signature is in storage &&
        auto signatureIt = (*mSignatureStorage).find(signatureId);
        if (signatureIt != (*mSignatureStorage).end() && (instanceSignature->find(signatureId) != instanceSignature->end())) {
#ifdef OPENMP
#pragma omp critical
#endif
            {
                instanceSignature->operator[](signatureId) = (*mSignatureStorage)[signatureId];
                instanceSignature->operator[](signatureId)->instances->push_back(index);
                mDoubleElementsQueryCount += (*mSignatureStorage)[signatureId]->instances->size();
            }
            continue;
        }

        // for every hash function: compute the hash values of all features and take the minimum of these
        // as the hash value for one hash function --> h_j(x) = argmin (x_i of x) f_j(x_i)
        vsize_t* signature = computeSignature(pRawData, index);
#ifdef OPENMP
#pragma omp critical
#endif
        {
            if (instanceSignature->find(signatureId) == instanceSignature->end()) {
                vsize_t* doubleInstanceVector = new vsize_t(1);
                (*doubleInstanceVector)[0] = index;
                uniqueElement* element = new uniqueElement();;
                element->instances = doubleInstanceVector;
                element->signature = signature;
                instanceSignature->operator[](signatureId) = element;
            } else {
                instanceSignature->operator[](signatureId)->instances->push_back(index);
                mDoubleElementsQueryCount += 1;
            }
        }
    }
    return instanceSignature;
}
void InverseIndex::fit(const SparseMatrixFloat* pRawData) {
    mDoubleElementsStorageCount = 0;
    if (mChunkSize <= 0) {
        mChunkSize = ceil(pRawData->size() / static_cast<float>(mNumberOfCores));
    }
#ifdef OPENMP
    omp_set_dynamic(0);
#endif
#ifdef OPENMP
#pragma omp parallel for schedule(static, mChunkSize) num_threads(mNumberOfCores)
#endif

    for (size_t index = 0; index < pRawData->size(); ++index) {
        size_t signatureId = 0;
        for (size_t j = 0; j < pRawData->getSizeOfInstance(index); ++j) {
            signatureId = mHash->hash((pRawData->getNextElement(index, j) +1), (signatureId+1), MAX_VALUE);
        }
        vsize_t* signature;
        auto itSignatureStorage = mSignatureStorage->find(signatureId);
        if (itSignatureStorage == mSignatureStorage->end()) {
            signature = computeSignature(pRawData, index);
        } else {
            signature = itSignatureStorage->second->signature;
        }
#ifdef OPENMP
#pragma omp critical
#endif
        {
            if (itSignatureStorage == mSignatureStorage->end()) {
                vsize_t* doubleInstanceVector = new vsize_t(1);
                (*doubleInstanceVector)[0] = index;
                uniqueElement* element = new uniqueElement();
                element->instances = doubleInstanceVector;
                element->signature = signature;
                mSignatureStorage->operator[](signatureId) = element;
            } else {
                 mSignatureStorage->operator[](signatureId)->instances->push_back(index);
                 mDoubleElementsStorageCount += 1;
            }
        }
        for (size_t j = 0; j < signature->size(); ++j) {
            mInverseIndexStorage->insert(j, (*signature)[j], index);
        }
    }
}

neighborhood* InverseIndex::kneighbors(const umap_uniqueElement* pSignaturesMap,
                                        const int pNneighborhood, const bool pDoubleElementsStorageCount) {
    size_t doubleElements = 0;
    if (pDoubleElementsStorageCount) {
        doubleElements = mDoubleElementsStorageCount;
    } else {
        doubleElements = mDoubleElementsQueryCount;
    }
#ifdef OPENMP
    omp_set_dynamic(0);
#endif
    vvint* neighbors = new vvint();
    vvfloat* distances = new vvfloat();
    neighbors->resize(pSignaturesMap->size()+doubleElements);
    distances->resize(pSignaturesMap->size()+doubleElements);
    if (mChunkSize <= 0) {
        mChunkSize = ceil(mInverseIndexStorage->size() / static_cast<float>(mNumberOfCores));
    }
#ifdef OPENMP
#pragma omp parallel for schedule(static, mChunkSize) num_threads(mNumberOfCores)
#endif
    for (size_t i = 0; i < pSignaturesMap->size(); ++i) {
        umap_uniqueElement::const_iterator instanceId = pSignaturesMap->begin();
        std::advance(instanceId, i);

        std::unordered_map<size_t, size_t> neighborhood;
        const vsize_t* signature = instanceId->second->signature;
        for (size_t j = 0; j < signature->size(); ++j) {
            size_t hashID = (*signature)[j];
            if (hashID != 0 && hashID != MAX_VALUE) {
                size_t collisionSize = 0;
                vsize_t* instances =  mInverseIndexStorage->getElement(j, hashID);
                if (instances != NULL && instances->size() != 0) {
                    collisionSize = instances->size();
                } else {
                    continue;
                }

                if (collisionSize < mMaxBinSize && collisionSize > 0) {
                    for (size_t k = 0; k < instances->size(); ++k) {
                        neighborhood[instances->at(k)] += 1;
                    }
                }
            }
        }
        if (neighborhood.size() == 0) {
            vint emptyVectorInt;
            emptyVectorInt.push_back(1);
            vfloat emptyVectorFloat;
            emptyVectorFloat.push_back(1);
            for (size_t j = 0; j < instanceId->second->instances->size(); ++j) {
                (*neighbors)[instanceId->second->instances->operator[](j)] = emptyVectorInt;
                (*distances)[instanceId->second->instances->operator[](j)] = emptyVectorFloat;
            }
            continue;
        }
        std::vector< sort_map > neighborhoodVectorForSorting;
        for (auto it = neighborhood.begin(); it != neighborhood.end(); ++it) {
            sort_map mapForSorting;
            mapForSorting.key = (*it).first;
            mapForSorting.val = (*it).second;
            neighborhoodVectorForSorting.push_back(mapForSorting);
        }

        size_t numberOfElementsToSort = pNneighborhood;
        if (pNneighborhood > neighborhoodVectorForSorting.size()) {
            numberOfElementsToSort = neighborhoodVectorForSorting.size();
        }
        std::partial_sort(neighborhoodVectorForSorting.begin(), neighborhoodVectorForSorting.begin()+numberOfElementsToSort, neighborhoodVectorForSorting.end(), mapSortDescByValue);
        size_t sizeOfNeighborhoodAdjusted;
        if (pNneighborhood == MAX_VALUE) {
            sizeOfNeighborhoodAdjusted = std::min(static_cast<size_t>(pNneighborhood), neighborhoodVectorForSorting.size());
        } else {
            sizeOfNeighborhoodAdjusted = std::min(static_cast<size_t>(pNneighborhood * mExcessFactor), neighborhoodVectorForSorting.size());
        }
        size_t count = 0;
        vvint* neighborsForThisInstance = new vvint(instanceId->second->instances->size());
        vvfloat* distancesForThisInstance = new vvfloat(instanceId->second->instances->size());

        for (size_t j = 0; j < neighborsForThisInstance->size(); ++j) {
            vint neighborhoodVector;
            std::vector<float> distanceVector;
            if (neighborhoodVectorForSorting[0].key != instanceId->second->instances->operator[](j)) {
                neighborhoodVector.push_back(instanceId->second->instances->operator[](j));
                distanceVector.push_back(0);
                ++count;
            }
            for (auto it = neighborhoodVectorForSorting.begin();
                    it != neighborhoodVectorForSorting.end(); ++it) {
                neighborhoodVector.push_back((*it).key);
                distanceVector.push_back(1 - ((*it).val / static_cast<float>(mMaximalNumberOfHashCollisions)));
                ++count;
                if (count >= sizeOfNeighborhoodAdjusted) {
                    (*neighborsForThisInstance)[j] = neighborhoodVector;
                    (*distancesForThisInstance)[j] = distanceVector;
                    break;
                }
            }
        }
#ifdef OPENMP
#pragma omp critical
#endif
        {
            for (size_t j = 0; j < instanceId->second->instances->size(); ++j) {
                (*neighbors)[instanceId->second->instances->operator[](j)] = (*neighborsForThisInstance)[j];
                (*distances)[instanceId->second->instances->operator[](j)] = (*distancesForThisInstance)[j];
            }
        }
    }
    neighborhood* neighborhood_ = new neighborhood();
    neighborhood_->neighbors = neighbors;
    neighborhood_->distances = distances;
    return neighborhood_;
}<commit_msg>Changed parameter pNneighborhood of function kneighbors to size_t and set type of variable instances inside function kneighbors to const<commit_after>/**
 Copyright 2015 Joachim Wolff
 Master Thesis
 Tutor: Fabrizio Costa
 Winter semester 2015/2016

 Chair of Bioinformatics
 Department of Computer Science
 Faculty of Engineering
 Albert-Ludwig-University Freiburg im Breisgau
**/

#include <algorithm>
#include <iostream>
#include <iterator>
#include <utility>

#ifdef OPENMP
#include <omp.h>
#endif

#include "inverseIndex.h"

class sort_map {
  public:
    size_t key;
    size_t val;
};

bool mapSortDescByValue(const sort_map& a, const sort_map& b) {
        return a.val > b.val;
};

InverseIndex::InverseIndex(size_t pNumberOfHashFunctions, size_t pBlockSize,
                    size_t pNumberOfCores, size_t pChunkSize,
                    size_t pMaxBinSize, size_t pMinimalBlocksInCommon,
                    size_t pExcessFactor, size_t pMaximalNumberOfHashCollisions, size_t pBloomierFilter) {

    mNumberOfHashFunctions = pNumberOfHashFunctions;
    mBlockSize = pBlockSize;
    mNumberOfCores = pNumberOfCores;
    mChunkSize = pChunkSize;
    mMaxBinSize = pMaxBinSize;
    mMinimalBlocksInCommon = pMinimalBlocksInCommon;
    mExcessFactor = pExcessFactor;
    mMaximalNumberOfHashCollisions = pMaximalNumberOfHashCollisions;
    mSignatureStorage = new umap_uniqueElement();
    mHash = new Hash();
    size_t maximalFeatures = 5000;

    size_t inverseIndexSize = ceil(((float) mNumberOfHashFunctions / (float) mBlockSize)+1);
    if (pBloomierFilter) {
        // std::cout << "Using bloomier filter. " << std::endl;
        mInverseIndexStorage = new InverseIndexStorageBloomierFilter(inverseIndexSize, mMaxBinSize, maximalFeatures);
    } else {
        // std::cout << "Using unorderedMap. " << std::endl;

        mInverseIndexStorage = new InverseIndexStorageUnorderedMap(inverseIndexSize, mMaxBinSize);
    }
}

InverseIndex::~InverseIndex() {

    for (auto it = (*mSignatureStorage).begin(); it != (*mSignatureStorage).end(); ++it) {
        delete it->second->instances;
        delete it->second->signature;
        delete it->second;

    }
    delete mSignatureStorage;
    delete mHash;
}
 // compute the signature for one instance
vsize_t* InverseIndex::computeSignature(const SparseMatrixFloat* pRawData, const size_t pInstance) {

    vsize_t signatureHash;
    signatureHash.reserve(mNumberOfHashFunctions);

    for(size_t j = 0; j < mNumberOfHashFunctions; ++j) {
        size_t minHashValue = MAX_VALUE;
        for (size_t i = 0; i < pRawData->getSizeOfInstance(pInstance); ++i) {
            //  hash(size_t pKey, size_t pModulo, size_t pSeed)
            size_t hashValue = mHash->hash((pRawData->getNextElement(pInstance, i) +1), (j+1), MAX_VALUE);
            if (hashValue < minHashValue) {
                minHashValue = hashValue;
            }
        }
        signatureHash[j] = minHashValue;
    }
    // reduce number of hash values by a factor of blockSize
    size_t k = 0;
    vsize_t* signature = new vsize_t();
    signature->reserve((mNumberOfHashFunctions / mBlockSize) + 1);
    while (k < (mNumberOfHashFunctions)) {
        // use computed hash value as a seed for the next computation
        size_t signatureBlockValue = signatureHash[k];
        for (size_t j = 0; j < mBlockSize; ++j) {
            signatureBlockValue = mHash->hash((signatureHash[k+j]),  signatureBlockValue, MAX_VALUE);
        }
        signature->push_back(signatureBlockValue);
        k += mBlockSize;
    }
    return signature;
}
umap_uniqueElement* InverseIndex::computeSignatureMap(const SparseMatrixFloat* pRawData) {
    mDoubleElementsQueryCount = 0;
    const size_t sizeOfInstances = pRawData->size();
    umap_uniqueElement* instanceSignature = new umap_uniqueElement();
    (*instanceSignature).reserve(sizeOfInstances);
    if (mChunkSize <= 0) {
        mChunkSize = ceil(pRawData->size() / static_cast<float>(mNumberOfCores));
    }

#ifdef OPENMP
    omp_set_dynamic(0);
#endif

#ifdef OPENMP
#pragma omp parallel for schedule(static, mChunkSize) num_threads(mNumberOfCores)
#endif
    for(size_t index = 0; index < pRawData->size(); ++index) {
        // vsize_t* features = pRawData->getFeatureRow(index);
        // compute unique id
        size_t signatureId = 0;
        for (size_t j = 0; j < pRawData->getSizeOfInstance(index); ++j) {
                signatureId = mHash->hash((pRawData->getNextElement(index, j) +1), (signatureId+1), MAX_VALUE);
        }
        // signature is in storage &&
        auto signatureIt = (*mSignatureStorage).find(signatureId);
        if (signatureIt != (*mSignatureStorage).end() && (instanceSignature->find(signatureId) != instanceSignature->end())) {
#ifdef OPENMP
#pragma omp critical
#endif
            {
                instanceSignature->operator[](signatureId) = (*mSignatureStorage)[signatureId];
                instanceSignature->operator[](signatureId)->instances->push_back(index);
                mDoubleElementsQueryCount += (*mSignatureStorage)[signatureId]->instances->size();
            }
            continue;
        }

        // for every hash function: compute the hash values of all features and take the minimum of these
        // as the hash value for one hash function --> h_j(x) = argmin (x_i of x) f_j(x_i)
        vsize_t* signature = computeSignature(pRawData, index);
#ifdef OPENMP
#pragma omp critical
#endif
        {
            if (instanceSignature->find(signatureId) == instanceSignature->end()) {
                vsize_t* doubleInstanceVector = new vsize_t(1);
                (*doubleInstanceVector)[0] = index;
                uniqueElement* element = new uniqueElement();;
                element->instances = doubleInstanceVector;
                element->signature = signature;
                instanceSignature->operator[](signatureId) = element;
            } else {
                instanceSignature->operator[](signatureId)->instances->push_back(index);
                mDoubleElementsQueryCount += 1;
            }
        }
    }
    return instanceSignature;
}
void InverseIndex::fit(const SparseMatrixFloat* pRawData) {
    mDoubleElementsStorageCount = 0;
    if (mChunkSize <= 0) {
        mChunkSize = ceil(pRawData->size() / static_cast<float>(mNumberOfCores));
    }
#ifdef OPENMP
    omp_set_dynamic(0);
#endif
#ifdef OPENMP
#pragma omp parallel for schedule(static, mChunkSize) num_threads(mNumberOfCores)
#endif

    for (size_t index = 0; index < pRawData->size(); ++index) {
        size_t signatureId = 0;
        for (size_t j = 0; j < pRawData->getSizeOfInstance(index); ++j) {
            signatureId = mHash->hash((pRawData->getNextElement(index, j) +1), (signatureId+1), MAX_VALUE);
        }
        vsize_t* signature;
        auto itSignatureStorage = mSignatureStorage->find(signatureId);
        if (itSignatureStorage == mSignatureStorage->end()) {
            signature = computeSignature(pRawData, index);
        } else {
            signature = itSignatureStorage->second->signature;
        }
#ifdef OPENMP
#pragma omp critical
#endif
        {
            if (itSignatureStorage == mSignatureStorage->end()) {
                vsize_t* doubleInstanceVector = new vsize_t(1);
                (*doubleInstanceVector)[0] = index;
                uniqueElement* element = new uniqueElement();
                element->instances = doubleInstanceVector;
                element->signature = signature;
                mSignatureStorage->operator[](signatureId) = element;
            } else {
                 mSignatureStorage->operator[](signatureId)->instances->push_back(index);
                 mDoubleElementsStorageCount += 1;
            }
        }
        for (size_t j = 0; j < signature->size(); ++j) {
            mInverseIndexStorage->insert(j, (*signature)[j], index);
        }
    }
}

neighborhood* InverseIndex::kneighbors(const umap_uniqueElement* pSignaturesMap,
                                        const size_t pNneighborhood, const bool pDoubleElementsStorageCount) {
    size_t doubleElements = 0;
    if (pDoubleElementsStorageCount) {
        doubleElements = mDoubleElementsStorageCount;
    } else {
        doubleElements = mDoubleElementsQueryCount;
    }
#ifdef OPENMP
    omp_set_dynamic(0);
#endif
    vvint* neighbors = new vvint();
    vvfloat* distances = new vvfloat();
    neighbors->resize(pSignaturesMap->size()+doubleElements);
    distances->resize(pSignaturesMap->size()+doubleElements);
    if (mChunkSize <= 0) {
        mChunkSize = ceil(mInverseIndexStorage->size() / static_cast<float>(mNumberOfCores));
    }
#ifdef OPENMP
#pragma omp parallel for schedule(static, mChunkSize) num_threads(mNumberOfCores)
#endif
    for (size_t i = 0; i < pSignaturesMap->size(); ++i) {
        umap_uniqueElement::const_iterator instanceId = pSignaturesMap->begin();
        std::advance(instanceId, i);

        std::unordered_map<size_t, size_t> neighborhood;
        const vsize_t* signature = instanceId->second->signature;
        for (size_t j = 0; j < signature->size(); ++j) {
            size_t hashID = (*signature)[j];
            if (hashID != 0 && hashID != MAX_VALUE) {
                size_t collisionSize = 0;
                const vsize_t* instances =  mInverseIndexStorage->getElement(j, hashID);
                if (instances != NULL && instances->size() != 0) {
                    collisionSize = instances->size();
                } else {
                    continue;
                }

                if (collisionSize < mMaxBinSize && collisionSize > 0) {
                    for (size_t k = 0; k < instances->size(); ++k) {
                        neighborhood[instances->at(k)] += 1;
                    }
                }
            }
        }
        if (neighborhood.size() == 0) {
            vint emptyVectorInt;
            emptyVectorInt.push_back(1);
            vfloat emptyVectorFloat;
            emptyVectorFloat.push_back(1);
            for (size_t j = 0; j < instanceId->second->instances->size(); ++j) {
                (*neighbors)[instanceId->second->instances->operator[](j)] = emptyVectorInt;
                (*distances)[instanceId->second->instances->operator[](j)] = emptyVectorFloat;
            }
            continue;
        }
        std::vector< sort_map > neighborhoodVectorForSorting;
        for (auto it = neighborhood.begin(); it != neighborhood.end(); ++it) {
            sort_map mapForSorting;
            mapForSorting.key = (*it).first;
            mapForSorting.val = (*it).second;
            neighborhoodVectorForSorting.push_back(mapForSorting);
        }

        size_t numberOfElementsToSort = pNneighborhood;
        if (pNneighborhood > neighborhoodVectorForSorting.size()) {
            numberOfElementsToSort = neighborhoodVectorForSorting.size();
        }
        std::partial_sort(neighborhoodVectorForSorting.begin(), neighborhoodVectorForSorting.begin()+numberOfElementsToSort, neighborhoodVectorForSorting.end(), mapSortDescByValue);
        size_t sizeOfNeighborhoodAdjusted;
        if (pNneighborhood == MAX_VALUE) {
            sizeOfNeighborhoodAdjusted = std::min(static_cast<size_t>(pNneighborhood), neighborhoodVectorForSorting.size());
        } else {
            sizeOfNeighborhoodAdjusted = std::min(static_cast<size_t>(pNneighborhood * mExcessFactor), neighborhoodVectorForSorting.size());
        }
        size_t count = 0;
        vvint* neighborsForThisInstance = new vvint(instanceId->second->instances->size());
        vvfloat* distancesForThisInstance = new vvfloat(instanceId->second->instances->size());

        for (size_t j = 0; j < neighborsForThisInstance->size(); ++j) {
            vint neighborhoodVector;
            std::vector<float> distanceVector;
            if (neighborhoodVectorForSorting[0].key != instanceId->second->instances->operator[](j)) {
                neighborhoodVector.push_back(instanceId->second->instances->operator[](j));
                distanceVector.push_back(0);
                ++count;
            }
            for (auto it = neighborhoodVectorForSorting.begin();
                    it != neighborhoodVectorForSorting.end(); ++it) {
                neighborhoodVector.push_back((*it).key);
                distanceVector.push_back(1 - ((*it).val / static_cast<float>(mMaximalNumberOfHashCollisions)));
                ++count;
                if (count >= sizeOfNeighborhoodAdjusted) {
                    (*neighborsForThisInstance)[j] = neighborhoodVector;
                    (*distancesForThisInstance)[j] = distanceVector;
                    break;
                }
            }
        }
#ifdef OPENMP
#pragma omp critical
#endif
        {
            for (size_t j = 0; j < instanceId->second->instances->size(); ++j) {
                (*neighbors)[instanceId->second->instances->operator[](j)] = (*neighborsForThisInstance)[j];
                (*distances)[instanceId->second->instances->operator[](j)] = (*distancesForThisInstance)[j];
            }
        }
    }
    neighborhood* neighborhood_ = new neighborhood();
    neighborhood_->neighbors = neighbors;
    neighborhood_->distances = distances;
    return neighborhood_;
}<|endoftext|>


<commit_before>/* $Id$ */

/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

// This helper macros creates a chain of ESD files for you. Source can be either a text
// file with the file paths or a directory. In the latter case all ESD files in all subdirectories
// are considered.
//
// Author: Jan.Fiete.Grosse-Oetringhaus@cern.ch

TChain* CreateESDChain(const char* aDataDir = "ESDfiles.txt", Int_t aRuns = 20, Int_t offset = 0, Bool_t addFileName = kFALSE, Bool_t addFriend = kFALSE, const char* check = 0)
{
  // creates chain of files in a given directory or file containing a list.
  // In case of directory the structure is expected as:
  // <aDataDir>/<dir0>/AliESDs.root
  // <aDataDir>/<dir1>/AliESDs.root
  // ...
  //
  // if addFileName is true the list only needs to contain the directories that contain the AliESDs.root files
  // if addFriend is true a file AliESDfriends.root is expected in the same directory and added to the chain as friend
  // if check is != 0 the files that work are written back into the textfile with the name check

  if (!aDataDir)
    return 0;

  Long_t id, size, flags, modtime;
  if (gSystem->GetPathInfo(aDataDir, &id, &size, &flags, &modtime))
  {
    printf("%s not found.\n", aDataDir);
    return 0;
  }

  TChain* chain = new TChain("esdTree");
  TChain* chainFriend = 0;

  if (addFriend)
    chainFriend = new TChain("esdFriendTree");

  if (flags & 2)
  {
    TString execDir(gSystem->pwd());
    TSystemDirectory* baseDir = new TSystemDirectory(".", aDataDir);
    TList* dirList            = baseDir->GetListOfFiles();
    Int_t nDirs               = dirList->GetEntries();
    gSystem->cd(execDir);

    Int_t count = 0;

    for (Int_t iDir=0; iDir<nDirs; ++iDir)
    {
      TSystemFile* presentDir = (TSystemFile*) dirList->At(iDir);
      if (!presentDir || !presentDir->IsDirectory() || strcmp(presentDir->GetName(), ".") == 0 || strcmp(presentDir->GetName(), "..") == 0)
        continue;

      if (offset > 0)
      {
        --offset;
        continue;
      }

      if (count++ == aRuns)
        break;

      TString presentDirName(aDataDir);
      presentDirName += "/";
      presentDirName += presentDir->GetName();

      chain->Add(presentDirName + "/AliESDs.root/esdTree");
    }
  }
  else
  {
    // Open the input stream
    ifstream in;
    in.open(aDataDir);

    ofstream outfile;
    if (check)
      outfile.open(check);

    Int_t count = 0;

    // Read the input list of files and add them to the chain
    TString line;
    while (in.good())
    {
      in >> line;

      if (line.Length() == 0)
        continue;

      if (offset > 0)
      {
        offset--;
        continue;
      }

      if (count++ == aRuns)
        break;

      TString esdFile(line);

      if (addFileName)
        esdFile += "/AliESDs.root";

      TString esdFileFriend(esdFile);
      esdFileFriend.ReplaceAll("AliESDs.root", "AliESDfriends.root");

      if (check)
      {
        TFile* file = TFile::Open(esdFile);
        if (!file)
          continue;
        file->Close();

        if (chainFriend)
        {
          TFile* file = TFile::Open(esdFileFriend);
          if (!file)
            continue;
          file->Close();
        }

        outfile << line.Data() << endl;
        printf("%s\n", line.Data());
      }

        // add esd file
      chain->Add(esdFile);

        // add file
      if (chainFriend)
        chainFriend->Add(esdFileFriend);
    }

    in.close();

    if (check)
      outfile.close();
  }

  if (chainFriend)
    chain->AddFriend(chainFriend);

  return chain;
}

void ChainToTextFile(TChain* chain, const char* target)
{
  // write a text list of the files in the chain

  TObjArray* list = chain->GetListOfFiles();
  TIterator* iter = list->MakeIterator();
  TObject* obj = 0;

  ofstream outfile;
  outfile.open(target);

  while ((obj = iter->Next())) {
    TString fileName(obj->GetTitle());

    fileName.Remove(fileName.Length()-13);

    outfile << fileName.Data() << endl;
  }

  outfile.close();

  delete iter;
}

TObjArray* Chain2List(TChain* chain)
{
  // returns a TObjArray of TObjStrings of the file names in the chain

  TObjArray* result = new TObjArray;

  for (Int_t i=0; i<chain->GetListOfFiles()->GetEntries(); i++)
    result->Add(new TObjString(chain->GetListOfFiles()->At(i)->GetTitle()));

  return result;
}

void LookupWrite(TChain* chain, const char* target)
{
  // looks up the chain and writes the remaining files to the text file target

  chain->Lookup();

  ChainToTextFile(chain, target);
}

TChain* CreateChain(const char* treeName, const char* aDataDir, Int_t aRuns, Int_t offset = 0)
{
  // creates chain of files in a given directory or file containing a list.

  if (!treeName || !aDataDir)
    return 0;

  TChain* chain = new TChain(treeName);

  // Open the input stream
  ifstream in;
  in.open(aDataDir);

  Int_t count = 0;

  // Read the input list of files and add them to the chain
  TString line;
  while(in.good())
  {
    in >> line;

    if (line.Length() == 0)
      continue;

    if (offset > 0)
    {
      --offset;
      continue;
    }

    if (count++ == aRuns)
      break;

    chain->Add(line);
  }

  in.close();

  return chain;
}
<commit_msg>small bugfix<commit_after>/* $Id$ */

/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

// This helper macros creates a chain of ESD files for you. Source can be either a text
// file with the file paths or a directory. In the latter case all ESD files in all subdirectories
// are considered.
//
// Author: Jan.Fiete.Grosse-Oetringhaus@cern.ch

TChain* CreateESDChain(const char* aDataDir = "ESDfiles.txt", Int_t aRuns = 20, Int_t offset = 0, Bool_t addFileName = kFALSE, Bool_t addFriend = kFALSE, const char* check = 0)
{
  // creates chain of files in a given directory or file containing a list.
  // In case of directory the structure is expected as:
  // <aDataDir>/<dir0>/AliESDs.root
  // <aDataDir>/<dir1>/AliESDs.root
  // ...
  //
  // if addFileName is true the list only needs to contain the directories that contain the AliESDs.root files
  // if addFriend is true a file AliESDfriends.root is expected in the same directory and added to the chain as friend
  // if check is != 0 the files that work are written back into the textfile with the name check

  if (!aDataDir)
    return 0;

  Long_t id, size, flags, modtime;
  if (gSystem->GetPathInfo(aDataDir, &id, &size, &flags, &modtime))
  {
    printf("%s not found.\n", aDataDir);
    return 0;
  }

  TChain* chain = new TChain("esdTree");
  TChain* chainFriend = 0;

  if (addFriend)
    chainFriend = new TChain("esdFriendTree");

  if (flags & 2)
  {
    TString execDir(gSystem->pwd());
    TSystemDirectory* baseDir = new TSystemDirectory(".", aDataDir);
    TList* dirList            = baseDir->GetListOfFiles();
    Int_t nDirs               = dirList->GetEntries();
    gSystem->cd(execDir);

    Int_t count = 0;

    for (Int_t iDir=0; iDir<nDirs; ++iDir)
    {
      TSystemFile* presentDir = (TSystemFile*) dirList->At(iDir);
      if (!presentDir || !presentDir->IsDirectory() || strcmp(presentDir->GetName(), ".") == 0 || strcmp(presentDir->GetName(), "..") == 0)
        continue;

      if (offset > 0)
      {
        --offset;
        continue;
      }

      if (count++ == aRuns)
        break;

      TString presentDirName(aDataDir);
      presentDirName += "/";
      presentDirName += presentDir->GetName();

      chain->Add(presentDirName + "/AliESDs.root/esdTree");
    }
  }
  else
  {
    // Open the input stream
    ifstream in;
    in.open(aDataDir);

    ofstream outfile;
    if (check)
      outfile.open(check);

    Int_t count = 0;

    // Read the input list of files and add them to the chain
    TString line;
    while (in.good())
    {
      in >> line;

      if (line.Length() == 0)
        continue;

      if (offset > 0)
      {
        offset--;
        continue;
      }

      if (count++ == aRuns)
        break;

      TString esdFile(line);

      if (addFileName)
        esdFile += "/AliESDs.root";

      TString esdFileFriend(esdFile);
      esdFileFriend.ReplaceAll("AliESDs.root", "AliESDfriends.root");

      if (check)
      {
        TFile* file = TFile::Open(esdFile);
        if (!file)
          continue;
        file->Close();

        if (chainFriend)
        {
          TFile* file = TFile::Open(esdFileFriend);
          if (!file)
            continue;
          file->Close();
        }

        outfile << line.Data() << endl;
        printf("%s\n", line.Data());
      }

        // add esd file
      chain->Add(esdFile);

        // add file
      if (chainFriend)
        chainFriend->Add(esdFileFriend);
    }

    in.close();

    if (check)
      outfile.close();
  }

  if (chainFriend)
    chain->AddFriend(chainFriend);

  return chain;
}

void ChainToTextFile(TChain* chain, const char* target)
{
  // write a text list of the files in the chain

  TObjArray* list = chain->GetListOfFiles();
  TIterator* iter = list->MakeIterator();
  TObject* obj = 0;

  ofstream outfile;
  outfile.open(target);

  while ((obj = iter->Next())) {
    TString fileName(obj->GetTitle());

    outfile << fileName.Data() << endl;
  }

  outfile.close();

  delete iter;
}

TObjArray* Chain2List(TChain* chain)
{
  // returns a TObjArray of TObjStrings of the file names in the chain

  TObjArray* result = new TObjArray;

  for (Int_t i=0; i<chain->GetListOfFiles()->GetEntries(); i++)
    result->Add(new TObjString(chain->GetListOfFiles()->At(i)->GetTitle()));

  return result;
}

void LookupWrite(TChain* chain, const char* target)
{
  // looks up the chain and writes the remaining files to the text file target

  chain->Lookup();

  ChainToTextFile(chain, target);
}

TChain* CreateChain(const char* treeName, const char* aDataDir, Int_t aRuns, Int_t offset = 0)
{
  // creates chain of files in a given directory or file containing a list.

  if (!treeName || !aDataDir)
    return 0;

  TChain* chain = new TChain(treeName);

  // Open the input stream
  ifstream in;
  in.open(aDataDir);

  Int_t count = 0;

  // Read the input list of files and add them to the chain
  TString line;
  while(in.good())
  {
    in >> line;

    if (line.Length() == 0)
      continue;

    if (offset > 0)
    {
      --offset;
      continue;
    }

    if (count++ == aRuns)
      break;

    chain->Add(line);
  }

  in.close();

  return chain;
}
<|endoftext|>


<commit_before>#include "client.hh"

#include "face_registry.hh"
#include "context.hh"
#include "buffer_manager.hh"
#include "buffer_utils.hh"
#include "file.hh"
#include "remote.hh"
#include "client_manager.hh"
#include "command_manager.hh"
#include "event_manager.hh"
#include "user_interface.hh"
#include "window.hh"

#include <signal.h>
#include <unistd.h>

namespace Kakoune
{

Client::Client(std::unique_ptr<UserInterface>&& ui,
               std::unique_ptr<Window>&& window,
               SelectionList selections,
               EnvVarMap env_vars,
               String name)
    : m_ui{std::move(ui)}, m_window{std::move(window)},
      m_input_handler{std::move(selections), Context::Flags::None,
                      std::move(name)},
      m_env_vars(env_vars)
{
    context().set_client(*this);
    context().set_window(*m_window);

    m_window->set_dimensions(m_ui->dimensions());
    m_window->options().register_watcher(*this);

    m_ui->set_ui_options(m_window->options()["ui_options"].get<UserInterface::Options>());
    m_ui->set_input_callback([this](EventMode mode) { handle_available_input(mode); });
}

Client::~Client()
{
    m_window->options().unregister_watcher(*this);
}

Optional<Key> Client::get_next_key(EventMode mode)
{
    if (not m_pending_keys.empty())
    {
        Key key = m_pending_keys.front();
        m_pending_keys.erase(m_pending_keys.begin());
        return key;
    }
    if (mode != EventMode::Pending and m_ui->is_key_available())
        return m_ui->get_key();
    return {};
}

void Client::handle_available_input(EventMode mode)
{
    if (mode == EventMode::Urgent)
    {
        Key key = m_ui->get_key();
        if (key == ctrl('c'))
            killpg(getpgrp(), SIGINT);
        else
            m_pending_keys.push_back(key);
        return;
    }

    try
    {
        try
        {
            while (Optional<Key> key = get_next_key(mode))
            {
                if (*key == ctrl('c'))
                    killpg(getpgrp(), SIGINT);
                else if (*key == Key::FocusIn)
                    context().hooks().run_hook("FocusIn", context().name(), context());
                else if (*key == Key::FocusOut)
                    context().hooks().run_hook("FocusOut", context().name(), context());
                else if (key->modifiers == Key::Modifiers::Resize)
                    force_redraw();
                else
                    m_input_handler.handle_key(*key);
            }
        }
        catch (Kakoune::runtime_error& error)
        {
            context().print_status({ error.what().str(), get_face("Error") });
            context().hooks().run_hook("RuntimeError", error.what(), context());
        }
    }
    catch (Kakoune::client_removed& removed)
    {
        ClientManager::instance().remove_client(*this, removed.graceful);
    }
}

void Client::print_status(DisplayLine status_line)
{
    m_pending_status_line = std::move(status_line);
}

DisplayLine Client::generate_mode_line() const
{
    DisplayLine modeline;
    try
    {
        const String& modelinefmt = context().options()["modelinefmt"].get<String>();

        modeline = parse_display_line(expand(modelinefmt, context()));
    }
    catch (runtime_error& err)
    {
        write_to_debug_buffer(format("Error while parsing modelinefmt: {}", err.what()));
        modeline.push_back({ "modelinefmt error, see *debug* buffer", get_face("Error") });
    }

    Face info_face = get_face("Information");

    if (context().buffer().is_modified())
        modeline.push_back({ "[+]", info_face });
    if (m_input_handler.is_recording())
        modeline.push_back({ format("[recording ({})]", m_input_handler.recording_reg()), info_face });
    if (context().buffer().flags() & Buffer::Flags::New)
        modeline.push_back({ "[new file]", info_face });
    if (context().user_hooks_disabled())
        modeline.push_back({ "[no-hooks]", info_face });
    if (context().buffer().flags() & Buffer::Flags::Fifo)
        modeline.push_back({ "[fifo]", info_face });
    modeline.push_back({ " " });
    for (auto& atom : m_input_handler.mode_line())
        modeline.push_back(std::move(atom));
    modeline.push_back({ format(" - {}@[{}]", context().name(), Server::instance().session()) });

    return modeline;
}

void Client::change_buffer(Buffer& buffer)
{
    if (m_buffer_reload_dialog_opened)
        close_buffer_reload_dialog();

    m_last_buffer = &m_window->buffer();

    auto& client_manager = ClientManager::instance();
    m_window->options().unregister_watcher(*this);
    client_manager.add_free_window(std::move(m_window),
                                   std::move(context().selections()));
    WindowAndSelections ws = client_manager.get_free_window(buffer);

    m_window = std::move(ws.window);
    m_window->options().register_watcher(*this);
    m_ui->set_ui_options(m_window->options()["ui_options"].get<UserInterface::Options>());

    context().selections_write_only() = std::move(ws.selections);
    context().set_window(*m_window);
    m_window->set_dimensions(m_ui->dimensions());

    m_window->hooks().run_hook("WinDisplay", buffer.name(), context());
}

static bool is_inline(InfoStyle style)
{
    return style == InfoStyle::Inline or
           style == InfoStyle::InlineAbove or
           style == InfoStyle::InlineBelow;
}

void Client::redraw_ifn()
{
    Window& window = context().window();

    const bool needs_redraw = window.needs_redraw(context());
    if (needs_redraw)
    {
        auto window_pos = window.position();
        m_ui->draw(window.update_display_buffer(context()), get_face("Default"));

	// window moved, reanchor eventual menu and info
        if (window_pos != window.position())
        {
            if (not m_menu.items.empty() and m_menu.style == MenuStyle::Inline)
            {
                m_ui->menu_show(m_menu.items, window.display_position(m_menu.anchor),
                                get_face("MenuForeground"), get_face("MenuBackground"), m_menu.style);
                m_ui->menu_select(m_menu.selected);
            }
            if (not m_info.content.empty() and is_inline(m_info.style))
                m_ui->info_show(m_info.title, m_info.content,
                                window.display_position(m_info.anchor),
                                get_face("Information"), m_info.style);
        }
    }

    DisplayLine mode_line = generate_mode_line();
    if (needs_redraw or
        m_status_line.atoms() != m_pending_status_line.atoms() or
        mode_line.atoms() != m_mode_line.atoms())
    {
        m_mode_line = std::move(mode_line);
        m_status_line = m_pending_status_line;

        m_ui->draw_status(m_status_line, m_mode_line, get_face("StatusLine"));
    }

    m_ui->refresh();
}

void Client::force_redraw()
{
    if (m_window)
        m_window->force_redraw();
}

void Client::reload_buffer()
{
    Buffer& buffer = context().buffer();
    reload_file_buffer(buffer);
    context().print_status({ format("'{}' reloaded", buffer.display_name()),
                             get_face("Information") });
}

void Client::on_buffer_reload_key(Key key)
{
    auto& buffer = context().buffer();

    if (key == 'y' or key == ctrl('m'))
        reload_buffer();
    else if (key == 'n' or key == Key::Escape)
    {
        // reread timestamp in case the file was modified again
        buffer.set_fs_timestamp(get_fs_timestamp(buffer.name()));
        print_status({ format("'{}' kept", buffer.display_name()),
                       get_face("Information") });
    }
    else
    {
        print_status({ format("'{}' is not a valid choice", key_to_str(key)),
                       get_face("Error") });
        m_input_handler.on_next_key(KeymapMode::None, [this](Key key, Context&){ on_buffer_reload_key(key); });
        return;
    }

    for (auto& client : ClientManager::instance())
    {
        if (&client->context().buffer() == &buffer and
            client->m_buffer_reload_dialog_opened)
            client->close_buffer_reload_dialog();
    }
}

void Client::close_buffer_reload_dialog()
{
    kak_assert(m_buffer_reload_dialog_opened);
    m_buffer_reload_dialog_opened = false;
    m_ui->info_hide();
    m_input_handler.reset_normal_mode();
}

void Client::check_if_buffer_needs_reloading()
{
    if (m_buffer_reload_dialog_opened)
        return;

    Buffer& buffer = context().buffer();
    auto reload = context().options()["autoreload"].get<Autoreload>();
    if (not (buffer.flags() & Buffer::Flags::File) or reload == Autoreload::No)
        return;

    const String& filename = buffer.name();
    timespec ts = get_fs_timestamp(filename);
    if (ts == InvalidTime or ts == buffer.fs_timestamp())
        return;
    if (reload == Autoreload::Ask)
    {
        m_ui->info_show(
            format("reload '{}' ?", buffer.display_name()),
            format("'{}' was modified externally\n"
                   "press <ret> or y to reload, <esc> or n to keep",
                   buffer.display_name()),
            CharCoord{}, get_face("Information"), InfoStyle::Prompt);

        m_buffer_reload_dialog_opened = true;
        m_input_handler.on_next_key(KeymapMode::None, [this](Key key, Context&){ on_buffer_reload_key(key); });
    }
    else
        reload_buffer();
}

StringView Client::get_env_var(StringView name) const
{
    auto it = m_env_vars.find(name);
    if (it == m_env_vars.end())
        return {};
    return it->value;
}

void Client::on_option_changed(const Option& option)
{
    if (option.name() == "ui_options")
        m_ui->set_ui_options(option.get<UserInterface::Options>());
}

void Client::menu_show(Vector<DisplayLine> choices, ByteCoord anchor, MenuStyle style)
{
    m_menu = Menu{ std::move(choices), anchor, style, -1 };
    CharCoord ui_anchor = style == MenuStyle::Inline ? context().window().display_position(anchor) : CharCoord{};
    m_ui->menu_show(m_menu.items, ui_anchor, get_face("MenuForeground"), get_face("MenuBackground"), style);
}

void Client::menu_select(int selected)
{
    m_menu.selected = selected;
    m_ui->menu_select(selected);
}

void Client::menu_hide()
{
    m_menu = Menu{};
    m_ui->menu_hide();
}

void Client::info_show(String title, String content, ByteCoord anchor, InfoStyle style)
{
    m_info = Info{ std::move(title), std::move(content), anchor, style };
    CharCoord ui_anchor = is_inline(style) ? context().window().display_position(anchor) : CharCoord{};
    m_ui->info_show(m_info.title, m_info.content, ui_anchor, get_face("Information"), style);
}

void Client::info_hide()
{
    m_info = Info{};
    m_ui->info_hide();
}

}
<commit_msg>Use the general code path for reload info box handling in Client<commit_after>#include "client.hh"

#include "face_registry.hh"
#include "context.hh"
#include "buffer_manager.hh"
#include "buffer_utils.hh"
#include "file.hh"
#include "remote.hh"
#include "client_manager.hh"
#include "command_manager.hh"
#include "event_manager.hh"
#include "user_interface.hh"
#include "window.hh"

#include <signal.h>
#include <unistd.h>

namespace Kakoune
{

Client::Client(std::unique_ptr<UserInterface>&& ui,
               std::unique_ptr<Window>&& window,
               SelectionList selections,
               EnvVarMap env_vars,
               String name)
    : m_ui{std::move(ui)}, m_window{std::move(window)},
      m_input_handler{std::move(selections), Context::Flags::None,
                      std::move(name)},
      m_env_vars(env_vars)
{
    context().set_client(*this);
    context().set_window(*m_window);

    m_window->set_dimensions(m_ui->dimensions());
    m_window->options().register_watcher(*this);

    m_ui->set_ui_options(m_window->options()["ui_options"].get<UserInterface::Options>());
    m_ui->set_input_callback([this](EventMode mode) { handle_available_input(mode); });
}

Client::~Client()
{
    m_window->options().unregister_watcher(*this);
}

Optional<Key> Client::get_next_key(EventMode mode)
{
    if (not m_pending_keys.empty())
    {
        Key key = m_pending_keys.front();
        m_pending_keys.erase(m_pending_keys.begin());
        return key;
    }
    if (mode != EventMode::Pending and m_ui->is_key_available())
        return m_ui->get_key();
    return {};
}

void Client::handle_available_input(EventMode mode)
{
    if (mode == EventMode::Urgent)
    {
        Key key = m_ui->get_key();
        if (key == ctrl('c'))
            killpg(getpgrp(), SIGINT);
        else
            m_pending_keys.push_back(key);
        return;
    }

    try
    {
        try
        {
            while (Optional<Key> key = get_next_key(mode))
            {
                if (*key == ctrl('c'))
                    killpg(getpgrp(), SIGINT);
                else if (*key == Key::FocusIn)
                    context().hooks().run_hook("FocusIn", context().name(), context());
                else if (*key == Key::FocusOut)
                    context().hooks().run_hook("FocusOut", context().name(), context());
                else if (key->modifiers == Key::Modifiers::Resize)
                    force_redraw();
                else
                    m_input_handler.handle_key(*key);
            }
        }
        catch (Kakoune::runtime_error& error)
        {
            context().print_status({ error.what().str(), get_face("Error") });
            context().hooks().run_hook("RuntimeError", error.what(), context());
        }
    }
    catch (Kakoune::client_removed& removed)
    {
        ClientManager::instance().remove_client(*this, removed.graceful);
    }
}

void Client::print_status(DisplayLine status_line)
{
    m_pending_status_line = std::move(status_line);
}

DisplayLine Client::generate_mode_line() const
{
    DisplayLine modeline;
    try
    {
        const String& modelinefmt = context().options()["modelinefmt"].get<String>();

        modeline = parse_display_line(expand(modelinefmt, context()));
    }
    catch (runtime_error& err)
    {
        write_to_debug_buffer(format("Error while parsing modelinefmt: {}", err.what()));
        modeline.push_back({ "modelinefmt error, see *debug* buffer", get_face("Error") });
    }

    Face info_face = get_face("Information");

    if (context().buffer().is_modified())
        modeline.push_back({ "[+]", info_face });
    if (m_input_handler.is_recording())
        modeline.push_back({ format("[recording ({})]", m_input_handler.recording_reg()), info_face });
    if (context().buffer().flags() & Buffer::Flags::New)
        modeline.push_back({ "[new file]", info_face });
    if (context().user_hooks_disabled())
        modeline.push_back({ "[no-hooks]", info_face });
    if (context().buffer().flags() & Buffer::Flags::Fifo)
        modeline.push_back({ "[fifo]", info_face });
    modeline.push_back({ " " });
    for (auto& atom : m_input_handler.mode_line())
        modeline.push_back(std::move(atom));
    modeline.push_back({ format(" - {}@[{}]", context().name(), Server::instance().session()) });

    return modeline;
}

void Client::change_buffer(Buffer& buffer)
{
    if (m_buffer_reload_dialog_opened)
        close_buffer_reload_dialog();

    m_last_buffer = &m_window->buffer();

    auto& client_manager = ClientManager::instance();
    m_window->options().unregister_watcher(*this);
    client_manager.add_free_window(std::move(m_window),
                                   std::move(context().selections()));
    WindowAndSelections ws = client_manager.get_free_window(buffer);

    m_window = std::move(ws.window);
    m_window->options().register_watcher(*this);
    m_ui->set_ui_options(m_window->options()["ui_options"].get<UserInterface::Options>());

    context().selections_write_only() = std::move(ws.selections);
    context().set_window(*m_window);
    m_window->set_dimensions(m_ui->dimensions());

    m_window->hooks().run_hook("WinDisplay", buffer.name(), context());
}

static bool is_inline(InfoStyle style)
{
    return style == InfoStyle::Inline or
           style == InfoStyle::InlineAbove or
           style == InfoStyle::InlineBelow;
}

void Client::redraw_ifn()
{
    Window& window = context().window();

    const bool needs_redraw = window.needs_redraw(context());
    if (needs_redraw)
    {
        auto window_pos = window.position();
        m_ui->draw(window.update_display_buffer(context()), get_face("Default"));

	// window moved, reanchor eventual menu and info
        if (window_pos != window.position())
        {
            if (not m_menu.items.empty() and m_menu.style == MenuStyle::Inline)
            {
                m_ui->menu_show(m_menu.items, window.display_position(m_menu.anchor),
                                get_face("MenuForeground"), get_face("MenuBackground"), m_menu.style);
                m_ui->menu_select(m_menu.selected);
            }
            if (not m_info.content.empty() and is_inline(m_info.style))
                m_ui->info_show(m_info.title, m_info.content,
                                window.display_position(m_info.anchor),
                                get_face("Information"), m_info.style);
        }
    }

    DisplayLine mode_line = generate_mode_line();
    if (needs_redraw or
        m_status_line.atoms() != m_pending_status_line.atoms() or
        mode_line.atoms() != m_mode_line.atoms())
    {
        m_mode_line = std::move(mode_line);
        m_status_line = m_pending_status_line;

        m_ui->draw_status(m_status_line, m_mode_line, get_face("StatusLine"));
    }

    m_ui->refresh();
}

void Client::force_redraw()
{
    if (m_window)
        m_window->force_redraw();
}

void Client::reload_buffer()
{
    Buffer& buffer = context().buffer();
    reload_file_buffer(buffer);
    context().print_status({ format("'{}' reloaded", buffer.display_name()),
                             get_face("Information") });
}

void Client::on_buffer_reload_key(Key key)
{
    auto& buffer = context().buffer();

    if (key == 'y' or key == ctrl('m'))
        reload_buffer();
    else if (key == 'n' or key == Key::Escape)
    {
        // reread timestamp in case the file was modified again
        buffer.set_fs_timestamp(get_fs_timestamp(buffer.name()));
        print_status({ format("'{}' kept", buffer.display_name()),
                       get_face("Information") });
    }
    else
    {
        print_status({ format("'{}' is not a valid choice", key_to_str(key)),
                       get_face("Error") });
        m_input_handler.on_next_key(KeymapMode::None, [this](Key key, Context&){ on_buffer_reload_key(key); });
        return;
    }

    for (auto& client : ClientManager::instance())
    {
        if (&client->context().buffer() == &buffer and
            client->m_buffer_reload_dialog_opened)
            client->close_buffer_reload_dialog();
    }
}

void Client::close_buffer_reload_dialog()
{
    kak_assert(m_buffer_reload_dialog_opened);
    m_buffer_reload_dialog_opened = false;
    m_ui->info_hide();
    m_input_handler.reset_normal_mode();
}

void Client::check_if_buffer_needs_reloading()
{
    if (m_buffer_reload_dialog_opened)
        return;

    Buffer& buffer = context().buffer();
    auto reload = context().options()["autoreload"].get<Autoreload>();
    if (not (buffer.flags() & Buffer::Flags::File) or reload == Autoreload::No)
        return;

    const String& filename = buffer.name();
    timespec ts = get_fs_timestamp(filename);
    if (ts == InvalidTime or ts == buffer.fs_timestamp())
        return;
    if (reload == Autoreload::Ask)
    {
        StringView bufname = buffer.display_name();
        info_show(format("reload '{}' ?", bufname),
                  format("'{}' was modified externally\n"
                         "press <ret> or y to reload, <esc> or n to keep",
                         bufname), {}, InfoStyle::Prompt);

        m_buffer_reload_dialog_opened = true;
        m_input_handler.on_next_key(KeymapMode::None, [this](Key key, Context&){ on_buffer_reload_key(key); });
    }
    else
        reload_buffer();
}

StringView Client::get_env_var(StringView name) const
{
    auto it = m_env_vars.find(name);
    if (it == m_env_vars.end())
        return {};
    return it->value;
}

void Client::on_option_changed(const Option& option)
{
    if (option.name() == "ui_options")
        m_ui->set_ui_options(option.get<UserInterface::Options>());
}

void Client::menu_show(Vector<DisplayLine> choices, ByteCoord anchor, MenuStyle style)
{
    m_menu = Menu{ std::move(choices), anchor, style, -1 };
    CharCoord ui_anchor = style == MenuStyle::Inline ? context().window().display_position(anchor) : CharCoord{};
    m_ui->menu_show(m_menu.items, ui_anchor, get_face("MenuForeground"), get_face("MenuBackground"), style);
}

void Client::menu_select(int selected)
{
    m_menu.selected = selected;
    m_ui->menu_select(selected);
}

void Client::menu_hide()
{
    m_menu = Menu{};
    m_ui->menu_hide();
}

void Client::info_show(String title, String content, ByteCoord anchor, InfoStyle style)
{
    m_info = Info{ std::move(title), std::move(content), anchor, style };
    CharCoord ui_anchor = is_inline(style) ? context().window().display_position(anchor) : CharCoord{};
    m_ui->info_show(m_info.title, m_info.content, ui_anchor, get_face("Information"), style);
}

void Client::info_hide()
{
    m_info = Info{};
    m_ui->info_hide();
}

}
<|endoftext|>


<commit_before>#ifndef _CALCULATOR_
#define _CALCULATOR_
#include <iostream>
#include <string>
#include <stack>
using namespace std;

class Calculator {
public:
	Calculator();
	Calculator(const string& expression);
	string infixToPostfix(string &infix);
	string getExpression();
	double postfixCalculate(string &postfix);
	double Calculate(string &infix);
	double getResult();
	bool isBrackMatching(string &expression);
	bool isExistingOtherSymbol(string &expression);
	bool checkExpress(string &expression);
public:
	string expression;
	double result;
};

#endif //_CALCULATOR_<commit_msg>Delete Calculate.hpp<commit_after><|endoftext|>


<commit_before>#ifndef TRWS_CALLER_HXX_
#define TRWS_CALLER_HXX_

#include <opengm/opengm.hxx>
#include <opengm/inference/external/trws.hxx>

#include "inference_caller_base.hxx"
#include "../argument/argument.hxx"
//#include "../helper/helper.hxx"

namespace opengm {

   namespace interface {

      template <class IO, class GM, class ACC>
      class TRWSCaller : public InferenceCallerBase<IO, GM, ACC, TRWSCaller<IO, GM, ACC> > {
      public:
         typedef typename opengm::external::TRWS<GM> TRWS;
         typedef InferenceCallerBase<IO, GM, ACC, TRWSCaller<IO, GM, ACC> > BaseClass;
         typedef typename TRWS::VerboseVisitorType VerboseVisitorType;
         typedef typename TRWS::EmptyVisitorType EmptyVisitorType;
         typedef typename TRWS::TimingVisitorType TimingVisitorType;
         const static std::string name_;
         TRWSCaller(IO& ioIn);
         virtual ~TRWSCaller();
      protected:
         using BaseClass::addArgument;
         using BaseClass::io_;
         using BaseClass::infer;

         typedef typename BaseClass::OutputBase OutputBase;

         virtual void runImpl(GM& model, OutputBase& output, const bool verbose);
         typename TRWS::Parameter trwsParameter_;
         std::string selectedEnergyType_;
      };

      template <class IO, class GM, class ACC>
      inline TRWSCaller<IO, GM, ACC>::TRWSCaller(IO& ioIn)
         : BaseClass("TRWS", "detailed description of TRWS Parser...", ioIn)
      {
         std::vector<std::string> possibleEnergyTypes;
         possibleEnergyTypes.push_back("VIEW");
         possibleEnergyTypes.push_back("TABLES");
         possibleEnergyTypes.push_back("TL1");
         possibleEnergyTypes.push_back("TL2");
         //possibleEnergyTypes.push_back("WEIGHTEDTABLE");
         addArgument(StringArgument<>(selectedEnergyType_, "", "energy", "Select desired energy type.", possibleEnergyTypes.front(), possibleEnergyTypes));

         addArgument(Size_TArgument<>(trwsParameter_.numberOfIterations_, "", "maxIt", "Maximum number of iterations.", trwsParameter_.numberOfIterations_));
         addArgument(BoolArgument(trwsParameter_.useRandomStart_, "", "randomStart", "Use random starting message."));
         addArgument(BoolArgument(trwsParameter_.useZeroStart_, "", "zeroStart", "Use zero starting message."));
         addArgument(BoolArgument(trwsParameter_.doBPS_, "", "doBPS", "Do BPS instead of TRWS"));
      }

      template <class IO, class GM, class ACC>
      inline TRWSCaller<IO, GM, ACC>::~TRWSCaller() {

      }

      template <class IO, class GM, class ACC>
      inline void TRWSCaller<IO, GM, ACC>::runImpl(GM& model, OutputBase& output, const bool verbose) {
         std::cout << "running TRWS caller" << std::endl;

         if(selectedEnergyType_ == "VIEW") {
            trwsParameter_.energyType_= TRWS::Parameter::VIEW;
         } else if(selectedEnergyType_ == "TABLES") {
            trwsParameter_.energyType_= TRWS::Parameter::TABLES;
         } else if(selectedEnergyType_ == "TL1") {
            trwsParameter_.energyType_= TRWS::Parameter::TL1;
         } else if(selectedEnergyType_ == "TL2") {
            trwsParameter_.energyType_= TRWS::Parameter::TL2;
         /*} else if(selectedEnergyType_ == "WEIGHTEDTABLE") {
            trwsParameter_.energyType_= TRWS::Parameter::WEIGHTEDTABLE;*/
         } else {
           throw RuntimeError("Unknown energy type for TRWS");
         }

         this-> template infer<TRWS, TimingVisitorType, typename TRWS::Parameter>(model, output, verbose, trwsParameter_);
      }

      template <class IO, class GM, class ACC>
      const std::string TRWSCaller<IO, GM, ACC>::name_ = "TRWS";

   } // namespace interface

} // namespace opengm

#endif /* TRWS_CALLER_HXX_ */
<commit_msg>add dualchange as parameter for stopping to the caller interface<commit_after>#ifndef TRWS_CALLER_HXX_
#define TRWS_CALLER_HXX_

#include <opengm/opengm.hxx>
#include <opengm/inference/external/trws.hxx>

#include "inference_caller_base.hxx"
#include "../argument/argument.hxx"
//#include "../helper/helper.hxx"

namespace opengm {

   namespace interface {

      template <class IO, class GM, class ACC>
      class TRWSCaller : public InferenceCallerBase<IO, GM, ACC, TRWSCaller<IO, GM, ACC> > {
      public:
         typedef typename opengm::external::TRWS<GM> TRWS;
         typedef InferenceCallerBase<IO, GM, ACC, TRWSCaller<IO, GM, ACC> > BaseClass;
         typedef typename TRWS::VerboseVisitorType VerboseVisitorType;
         typedef typename TRWS::EmptyVisitorType EmptyVisitorType;
         typedef typename TRWS::TimingVisitorType TimingVisitorType;
         const static std::string name_;
         TRWSCaller(IO& ioIn);
         virtual ~TRWSCaller();
      protected:
         using BaseClass::addArgument;
         using BaseClass::io_;
         using BaseClass::infer;

         typedef typename BaseClass::OutputBase OutputBase;

         virtual void runImpl(GM& model, OutputBase& output, const bool verbose);
         typename TRWS::Parameter trwsParameter_;
         std::string selectedEnergyType_;
      };

      template <class IO, class GM, class ACC>
      inline TRWSCaller<IO, GM, ACC>::TRWSCaller(IO& ioIn)
         : BaseClass("TRWS", "detailed description of TRWS Parser...", ioIn)
      {
         std::vector<std::string> possibleEnergyTypes;
         possibleEnergyTypes.push_back("VIEW");
         possibleEnergyTypes.push_back("TABLES");
         possibleEnergyTypes.push_back("TL1");
         possibleEnergyTypes.push_back("TL2");
         //possibleEnergyTypes.push_back("WEIGHTEDTABLE");
         addArgument(StringArgument<>(selectedEnergyType_, "", "energy", "Select desired energy type.", possibleEnergyTypes.front(), possibleEnergyTypes));

         addArgument(Size_TArgument<>(trwsParameter_.numberOfIterations_, "", "maxIt", "Maximum number of iterations.", trwsParameter_.numberOfIterations_));
         addArgument(BoolArgument(trwsParameter_.useRandomStart_, "", "randomStart", "Use random starting message."));
         addArgument(BoolArgument(trwsParameter_.useZeroStart_, "", "zeroStart", "Use zero starting message."));
         addArgument(BoolArgument(trwsParameter_.doBPS_, "", "doBPS", "Do BPS instead of TRWS"));
         addArgument(DoubleArgument<>(trwsParameter_.minDualChange_, "", "minDualChange", "stop when change of dual is smaller",trwsParameter_.minDualChange_));
      }

      template <class IO, class GM, class ACC>
      inline TRWSCaller<IO, GM, ACC>::~TRWSCaller() {

      }

      template <class IO, class GM, class ACC>
      inline void TRWSCaller<IO, GM, ACC>::runImpl(GM& model, OutputBase& output, const bool verbose) {
         std::cout << "running TRWS caller" << std::endl;

         if(selectedEnergyType_ == "VIEW") {
            trwsParameter_.energyType_= TRWS::Parameter::VIEW;
         } else if(selectedEnergyType_ == "TABLES") {
            trwsParameter_.energyType_= TRWS::Parameter::TABLES;
         } else if(selectedEnergyType_ == "TL1") {
            trwsParameter_.energyType_= TRWS::Parameter::TL1;
         } else if(selectedEnergyType_ == "TL2") {
            trwsParameter_.energyType_= TRWS::Parameter::TL2;
         /*} else if(selectedEnergyType_ == "WEIGHTEDTABLE") {
            trwsParameter_.energyType_= TRWS::Parameter::WEIGHTEDTABLE;*/
         } else {
           throw RuntimeError("Unknown energy type for TRWS");
         }

         this-> template infer<TRWS, TimingVisitorType, typename TRWS::Parameter>(model, output, verbose, trwsParameter_);
      }

      template <class IO, class GM, class ACC>
      const std::string TRWSCaller<IO, GM, ACC>::name_ = "TRWS";

   } // namespace interface

} // namespace opengm

#endif /* TRWS_CALLER_HXX_ */
<|endoftext|>