Using std::chi_squared_distribution

Hello,
I want to write a Patch in c++ and try to use std::chi_squared_distribution from the c++11 standard.
Unfortunately several macros and the compiler flag -fsingle-precision-constant are preventing me from using the distribution function.
If I disable the use of the optimized arm_ functions I am able to compile the patch. I think this is not optimal. The compiler flag seems to be an issue of the STL but the macros are not working with the STL headers.

Here is a patch of the changes I had to apply to use std::chi_squared_distribution.

diff --git a/LibSource/ComplexFloatArray.cpp b/LibSource/ComplexFloatArray.cpp
index 07483b5..504dab9 100644
--- a/LibSource/ComplexFloatArray.cpp
+++ b/LibSource/ComplexFloatArray.cpp
@@ -1,3 +1,5 @@
+#include <algorithm>
+
 #include "ComplexFloatArray.h"
 #include "basicmaths.h"
 #include "message.h"
@@ -210,7 +212,7 @@ void ComplexFloatArray::destroy(ComplexFloatArray array){
 /* Copies real values from a FloatArray, sets imaginary values to 0
  */
 void ComplexFloatArray::copyFrom(FloatArray source){
-  for(int n=0; n<min(size,source.getSize()); n++){
+  for(int n=0; n<std::min(size,source.getSize()); n++){
     data[n].re=source[n];
     data[n].im=0;
   }
@@ -218,18 +220,18 @@ void ComplexFloatArray::copyFrom(FloatArray source){
 
 /* Copies real part to a FloatArray */
 void ComplexFloatArray::copyTo(FloatArray destination){
-  for(int n=0; n<min(size,destination.getSize()); n++){
+  for(int n=0; n<std::min(size,destination.getSize()); n++){
     destination[n]=data[n].re;
   }
 }
 
 /*BEGIN -- methods copied and adapted from ComplexFloatArray.cpp*/
 void ComplexFloatArray::copyTo(ComplexFloatArray destination){
-  copyTo(destination, min(size, destination.getSize()));
+  copyTo(destination, std::min(size, destination.getSize()));
 }
 
 void ComplexFloatArray::copyFrom(ComplexFloatArray source){
-  copyFrom(source, min(size, source.getSize()));
+  copyFrom(source, std::min(size, source.getSize()));
 }
 
 void ComplexFloatArray::copyTo(ComplexFloat* other, int length){
diff --git a/LibSource/FloatArray.cpp b/LibSource/FloatArray.cpp
index 6da96ce..04e8a28 100644
--- a/LibSource/FloatArray.cpp
+++ b/LibSource/FloatArray.cpp
@@ -1,8 +1,11 @@
+#include <algorithm>
+
 #include "FloatArray.h"
 #include "basicmaths.h"
 #include "message.h"
 #include <string.h>
 
+
  FloatArray::FloatArray() :
    data(NULL), size(0) {}
 
@@ -240,12 +243,12 @@ FloatArray FloatArray::subArray(int offset, int length){
 
 void FloatArray::copyTo(FloatArray destination){
 /// @note When built for ARM Cortex-M processor series, this method uses the optimized <a href="http://www.keil.com/pack/doc/CMSIS/General/html/index.html">CMSIS library</a>
-  copyTo(destination, min(size, destination.getSize()));
+  copyTo(destination, std::min(size, destination.getSize()));
 }
 
 void FloatArray::copyFrom(FloatArray source){
 /// @note When built for ARM Cortex-M processor series, this method uses the optimized <a href="http://www.keil.com/pack/doc/CMSIS/General/html/index.html">CMSIS library</a>
-  copyFrom(source, min(size, source.getSize()));
+  copyFrom(source, std::min(size, source.getSize()));
 }
 
 void FloatArray::copyTo(float* other, int length){
diff --git a/LibSource/WavetableOscillator.cpp b/LibSource/WavetableOscillator.cpp
index 15d55d3..ccef0e5 100644
--- a/LibSource/WavetableOscillator.cpp
+++ b/LibSource/WavetableOscillator.cpp
@@ -1,6 +1,8 @@
+#include <algorithm>
+#include <stdint.h>
+
 #include "WavetableOscillator.h"
 #include "basicmaths.h"
-#include <stdint.h>
 
 WavetableOscillator* WavetableOscillator::create(float sr, int size) {
   FloatArray wave = FloatArray::create(size);
@@ -27,7 +29,7 @@ void WavetableOscillator::setFrequency(float freq){
 float WavetableOscillator::getSample(float phase){
   uint32_t size = wave.getSize();
   uint32_t index = phase*(size-1);
-  index = min(index, size-1);
+  index = std::min(index, size-1);
   return wave[index];
 }
 
diff --git a/LibSource/basicmaths.h b/LibSource/basicmaths.h
index 046bfbb..54eb860 100644
--- a/LibSource/basicmaths.h
+++ b/LibSource/basicmaths.h
@@ -37,15 +37,7 @@
 #ifndef M_SQRT2
 #define M_SQRT2 1.41421356237309504880
 #endif
-#ifndef min
-#define min(a,b) ((a)<(b)?(a):(b))
-#endif
-#ifndef max
-#define max(a,b) ((a)>(b)?(a):(b))
-#endif
-#ifndef abs
-#define abs(x) ((x)>0?(x):-(x))
-#endif
+
 //#endif /* __cplusplus */
 
 #ifdef __cplusplus
@@ -70,13 +62,13 @@
 #define free(x) vPortFree(x)
 
 #ifdef ARM_CORTEX
-#define sin(x) arm_sin_f32(x)
-#define sinf(x) arm_sin_f32(x)
-#define cos(x) arm_cos_f32(x)
-#define cosf(x) arm_cos_f32(x)
-#define sqrt(x) arm_sqrtf(x)
-#define sqrtf(x) arm_sqrtf(x)
-#define rand() arm_rand32()
+//#define sin(x) arm_sin_f32(x)
+//#define sinf(x) arm_sin_f32(x)
+//#define cos(x) arm_cos_f32(x)
+//#define cosf(x) arm_cos_f32(x)
+//#define sqrt(x) arm_sqrtf(x)
+//#define sqrtf(x) arm_sqrtf(x)
+//#define rand() arm_rand32()
 
 #ifdef __FAST_MATH__ /* set by gcc option -ffast-math */
 // fast approximate math functions
diff --git a/common.mk b/common.mk
index 15a60f2..1363fa5 100644
--- a/common.mk
+++ b/common.mk
@@ -24,7 +24,7 @@ OBJDUMP=$(TOOLROOT)arm-none-eabi-objdump
 ARCH_FLAGS = -mcpu=cortex-m4 -mthumb
 ARCH_FLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
 # ARCH_FLAGS += -mfloat-abi=soft -msoft-float
-ARCH_FLAGS += -fsingle-precision-constant
+# ARCH_FLAGS += -fsingle-precision-constant
 DEF_FLAGS = -DARM_MATH_CM4 -DSTM32F4XX -D__FPU_PRESENT -D__FPU_USED=1
 # DEF_FLAGS = -DUSE_STDPERIPH_DRIVER -DARM_MATH_CM4 -DSTM32F4XX
 INC_FLAGS = -I$(BUILDROOT)/Libraries -I$(DEVICE) -I$(CMSIS) -I$(PERIPH_FILE)/inc -I$(SOURCE)

I think there must be a more elegant solution for this.

Regards
zottel

Hi zottel,

yes the defines in basicmath are not very elegant at all, it’s something we’d like to improve.
Perhaps we’ll put it all in an owl:: namespace which would include the compiled patch. Then std:: would not have conflicts.

The challenge we face is that the code must work with all supported compilation configurations: C++, FAUST and Pd patches cross-compiled to ARM and JS, as well as native.

Did you compile your patch for the OWL? How big was the binary?

We don’t officially support STL, or recommend its use, because it can inflate the code size by a huge amount, dependent on what parts you include. Instead we provide a library with optimised implementations which we are happy to extend. See http://www.hoxtonowl.com/docs/classPatch.html

Hello,
the owl patch is very minimalistic about 43 lines of code. Here are the sizes in bytes:

8708 patch.bin
66792 patch.elf
10402 patch.syx

with flag -Os

7964 patch.bin
66428 patch.elf
9512 patch.syx

If you don’t recommend the use of the STL I will have to borrow an implementation from one
of the math libraries.

Regards
zottel

Instead of changing FloatArray et c you can use this:


#ifdef __cplusplus
#include <cmath>
#include <algorithm>
using std::min;
using std::max;
using std::abs;
#else
#include <math.h>
#ifndef min
#define min(a,b) ((a)<(b)?(a):(b))
#endif
#ifndef max
#define max(a,b) ((a)>(b)?(a):(b))
#endif
#ifndef abs
#define abs(x) ((x)>0?(x):-(x))
#endif
#endif

However for the one patch I tried this on, along with removing -fsingle-precision-constant, code size increased by a bit more than 1k and performance went up from 78% to 128%.