From 26d64044b5f2a59422bb806751424001c46a0ebc Mon Sep 17 00:00:00 2001
From: Eric Kooistra <kooistra@astron.nl>
Date: Wed, 23 Mar 2022 15:28:14 +0100
Subject: [PATCH] Copy quantize.m from aperitif_matlab git.

---
 applications/lofar2/model/quantize.m | 119 +++++++++++++++++++++++++++
 1 file changed, 119 insertions(+)
 create mode 100644 applications/lofar2/model/quantize.m

diff --git a/applications/lofar2/model/quantize.m b/applications/lofar2/model/quantize.m
new file mode 100644
index 0000000000..b404d54cca
--- /dev/null
+++ b/applications/lofar2/model/quantize.m
@@ -0,0 +1,119 @@
+%-----------------------------------------------------------------------------
+%
+% Copyright (C) 2016
+% ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+% P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+%
+% This program is free software: you can redistribute it and/or modify
+% it under the terms of the GNU General Public License as published by
+% the Free Software Foundation, either version 3 of the License, or
+% (at your option) any later version.
+%
+% This program is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with this program.  If not, see <http://www.gnu.org/licenses/>.
+%
+%-----------------------------------------------------------------------------
+% Author: E. Kooistra, 2016
+%
+% quantize - quantize two's-complement input data
+%     The output has nof_bits. Definitions:
+%     . w = nof_bits   (output data width)
+%     . q_full_scale = 2**(w-1)
+%     . q_max =  q_full_scale - 1
+%     . q_min = -q_full_scale
+%     Magnitude and amplitude are synonyms for full scale.
+%
+%     The quantization process involves the following steps:
+%
+%     1 scale the input data magnitude
+%     2 round the data
+%     3 handle overflow
+%     4 scale back to the original input data magnitude
+%
+%     The in_full_scale internally maps to in_q_max. Choose in_q_max =
+%     . q_full_scale : default, implies that in_data = in_full_scale will
+%                      just clip to q_max (or just wrap dependent on the
+%                      overflow option) and in_data = -in_full_scale will
+%                      map to q_min.
+%     . q_max        : in_data = in_full_scale will map to q_max, so no
+%                      overflow.
+%     Typically use in_q_max = q_full_scale for data and use in_q_max =
+%     q_max for coefficients. Use in_q_max < q_max if more backoff is
+%     needed for some other reason.
+%
+%     The 'rounding' determines how -0.5 is rounded:
+%     . 'half_away': Round half away from zero, so +0.5 --> 1, -0.5 --> -1.
+%     . 'half_up'  : Round half up to +infinity, so +0.5 --> 1, -0.5 --> 0.
+%
+%     Quantized data that is out of range -q_min : q_max gets treated 
+%     dependent on 'overflow':
+%     . 'clip'     : Clip to -q_min or q_max
+%     . 'clip_sym' : Clip symmetrical to -q_max or q_max
+%     . 'wrap'     : Wrap within nof_bits signed integer range
+%     . 'no_limit' : No range limit, so allow quantized data to get out
+%                    of range -q_min : q_max
+%
+%     The output data range is scaled back to the original in_full_scale.
+
+function out_data = quantize(in_data, in_full_scale, nof_bits, rounding, overflow, in_q_max)
+
+q_bit = 1;
+q_full_scale = 2^(nof_bits-1);  % maximum amplitude, magnitude
+q_max =  q_full_scale-1;
+q_min = -q_full_scale;
+q_period = 2^nof_bits;
+
+% Default options
+if ~exist('rounding', 'var'); rounding = 'half_away'; end;
+if ~exist('overflow', 'var'); overflow = 'clip'; end;
+if ~exist('in_q_max', 'var'); in_q_max = q_full_scale; end;
+
+% Scale
+q_data = in_q_max * in_data/in_full_scale;
+
+% Round
+if strcmp(rounding, 'half_away')
+    q_data = round(q_data);
+else
+    q_data = floor(q_data + q_bit/2);
+end
+
+% Overflow
+if isreal(q_data)
+    q_re = q_data;
+else
+    q_re = real(q_data);
+    q_im = imag(q_data);
+end
+if strcmp(overflow, 'clip')
+    q_re(q_re>q_max) = q_max;
+    q_re(q_re<q_min) = q_min;
+    if ~isreal(q_data)
+        q_im(q_im>q_max) = q_max;
+        q_im(q_im<q_min) = q_min;
+    end
+elseif strcmp(overflow, 'clip_sym')
+    q_re(q_re> q_max) =  q_max;
+    q_re(q_re<-q_max) = -q_max;
+    if ~isreal(q_data)
+        q_im(q_im> q_max) =  q_max;
+        q_im(q_im<-q_max) = -q_max;
+    end
+elseif strcmp(overflow, 'wrap')
+    q_re = mod(q_re - q_min, q_period) + q_min;
+    if ~isreal(q_data)
+        q_im = mod(q_im - q_min, q_period) + q_min;
+    end
+end
+if isreal(q_data)
+    q_data = q_re;
+else
+    q_data = complex(q_re, q_im);
+end
+% Back to original full scale
+out_data = in_full_scale * q_data/q_full_scale;
-- 
GitLab