;find peaks as per Laroche and Dolson (bigger than 4 neighbours)
;In the future, consider the efficiency difference of zero padding a copy of the buffer
;versus maths of accounting for out of bounds indexes
;The code is certainly easier using zero padding
;This code assumes that the peaks memory allocated is correctly sized or bigger
;The number of peaks is returned to allow for easier function use. (ceil(buffer_size/3)) for > 4 neighbours
(bind-func find_peaks:[i64,float*,i64,i64*,i64*,i64*]*
(lambda (buffer:float* buffer_len:i64 peaks_array:i64* region_lower:i64* region_upper:i64*)
(let ((n:i64 0);
(peak_index:i64 0)
(buff_padded:float* (salloc (+ buffer_len 4))))
(pset! buff_padded 0 0.0) ;Zero pad the buffer
(pset! buff_padded 1 0.0)
(pset! buff_padded (+ buffer_len 2) 0.0)
(pset! buff_padded (+ buffer_len 3) 0.0)
(dotimes (n buffer_len)
(pset! buff_padded (+ n 2) (pref buffer n)))
(dotimes (n buffer_len) ;peak finding
(if (> (pref buff_padded (+ n 2)) (pref buff_padded n))
(if (> (pref buff_padded (+ n 2)) (pref buff_padded (+ n 1)))
(if (> (pref buff_padded (+ n 2)) (pref buff_padded (+ n 3)))
(if (> (pref buff_padded (+ n 2)) (pref buff_padded (+ n 4)))
(begin
(pset! peaks_array peak_index n)
(set! peak_index (+ peak_index 1)))))))) ;After all peaks are found, peak index becomes the number of peaks
(if (> peak_index 0)
(begin
(pset! region_lower 0 0) ;Set the region_lower bound
(dotimes (n (- peak_index 1))
(pset! region_lower (+ n 1) (ftoi64 (ceil (/ (i64tof (+ (pref peaks_array n)
(pref peaks_array (+ n 1))))
(i64tof 2))))))