From 6d8d88cb9b221eee88442b17a3d2da953e902d21 Mon Sep 17 00:00:00 2001
From: Carl Philipp Klemm <philipp@uvos.xyz>
Date: Thu, 2 May 2024 14:50:15 +0200
Subject: [PATCH] improve the example by sorting the outputs, add kiss_float_eq
 to the api, version bump 1.1.0

---
 doc/libkissinference.doxygen.in |  2 +-
 examples/classify.cpp           |  7 ++++++-
 kissinference.c                 |  8 +++++++-
 kissinference/kissinference.h   | 15 +++++++++++++++
 4 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/doc/libkissinference.doxygen.in b/doc/libkissinference.doxygen.in
index a9d556f..d8f515b 100644
--- a/doc/libkissinference.doxygen.in
+++ b/doc/libkissinference.doxygen.in
@@ -38,7 +38,7 @@ PROJECT_NAME           = @PROJECT_NAME@
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = 1.0.x
+PROJECT_NUMBER         = 1.1.x
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
diff --git a/examples/classify.cpp b/examples/classify.cpp
index 3eaedb7..113057e 100644
--- a/examples/classify.cpp
+++ b/examples/classify.cpp
@@ -7,6 +7,7 @@
 #include <condition_variable>
 #include <mutex>
 #include <limits>
+#include <algorithm>
 
 #include "kissinference/kissinference.h"
 
@@ -113,11 +114,15 @@ static void resultCallback(float* data, struct kiss_network* net, void* userData
 	}
 	else
 	{
+		std::vector<std::pair<std::string, float>> results;
+		for(size_t i = 0; i < net->output_size; ++i)
+			results.push_back({net->output_labels[i], data[i]});
+		std::sort(results.begin(), results.end(), [](std::pair<std::string, float> a, std::pair<std::string, float> b){return a.second > b.second;});
 		printmtx.lock();
 		OUTSTREAM<<"\nResult for "<<rq->path<<'\n';
 		OUTSTREAM<<"Classes:\nNumber\tName\tLikelyhood\n";
 		for(size_t i = 0; i < net->output_size; ++i)
-			OUTSTREAM<<i<<'\t'<<net->output_labels[i]<<'\t'<<data[i]<<'\n';
+			OUTSTREAM<<i<<'\t'<<results[i].first<<'\t'<<results[i].second<<'\n';
 		printmtx.unlock();
 	}
 
diff --git a/kissinference.c b/kissinference.c
index 8fdbfd5..cef71e2 100644
--- a/kissinference.c
+++ b/kissinference.c
@@ -47,7 +47,7 @@ void kiss_inference_req_free(struct kiss_inference_req *req)
 
 const struct kiss_version_fixed kiss_get_version(void)
 {
-	static const struct kiss_version_fixed version = {1, 0, 0};
+	static const struct kiss_version_fixed version = {1, 1, 0};
 	return version;
 }
 
@@ -654,6 +654,12 @@ const char *kiss_get_strerror(struct kiss_network *net)
 	return net->priv->err;
 }
 
+bool kiss_float_eq(float a, float b, unsigned int ulp)
+{
+	float epsilon = (nextafterf(1.0f, INFINITY) - 1.0f)*fabs(a+b)*ulp;
+	return a - epsilon <= b && a + epsilon >= b;
+}
+
 void kiss_free(void *data)
 {
 	free(data);
diff --git a/kissinference/kissinference.h b/kissinference/kissinference.h
index 305d4a1..9b3ed60 100644
--- a/kissinference/kissinference.h
+++ b/kissinference/kissinference.h
@@ -222,6 +222,21 @@ const char *kiss_get_strerror(struct kiss_network *net);
  */
 void kiss_softmax(float *data, size_t input_length);
 
+/**
+ * @brief Checks the given floats for equality with a tollerance of ulp epsilons around the sum of the inputs.
+ *
+ * @param a The first input.
+ * @param b The second input to be compared with the first.
+ * @param ulp number of epsilons of tollerance.
+ * @return True if the value of b is within ulp epsilons of a, false otherwise.
+ */
+bool kiss_float_eq(float a, float b, unsigned int ulp);
+
+/**
+ * @brief Frees the data with the same allocateor libkissinference was compiled against.
+ *
+ * @param data A pointer to the data to free
+ */
 void kiss_free(void *data);
 
 /**
-- 
GitLab