How to convert /map uint16 to int16 maintaining the dynamic range so that [0] and [2^16-1] in uint16 beomes [-2^15] and [2^15-1] without going through double

23 views (last 30 days)
Micke Malmström on 2 Feb 2024
Edited: Bruno Luong on 3 Feb 2024
I would like to convert my uint16 values to int16 values amd maintain the dynamic range. All my attempts with typecast and cast still map value 0 (uint16) to 0 (int16). I would like it to map 0 (uint16) directly to -2^15 (int16). I need to convert a rather large dataset so I would like to circumvent doing to double or single if I can.
The data comes from fread and if I can do the mapping there directly then that would be even better. This is what I use now to read the data:
Ive tried asking for 'uint16=>int16', but that also cuts the data
Micke Malmström on 2 Feb 2024
Edited: Micke Malmström on 2 Feb 2024
% Example uint16 data
uint16Data = uint16([0, 2^16-1]);
% Map uint16 to int16
int16Data = int16(uint16Data - 2^15); % here is where the problem lies and I cant figure out how to circumvent going through double or single...
% Display the results
disp(['Original uint16 data: ', num2str(uint16Data)]);
Original uint16 data: 0 65535
disp(['Mapped int16 data: ', num2str(int16Data)]); % my desired result here is Mapped int16 data: -32768 32767
Mapped int16 data: 0 32767

Stephen23 on 2 Feb 2024
Edited: Stephen23 on 2 Feb 2024
inp = uint16([-Inf,pi,Inf])
inp = 1×3
0 3 65535
Method one: use INT32 for the intermediate values:
off = int32(intmin('int16'));
out = int16(int32(inp)+off)
out = 1×3
-32768 -32765 32767
Method two: convert from two's complement to offset binary, which you can then simply TYPECAST into INT16:
out = typecast(bitset(inp,16,1-bitget(inp,16)),'int16')
out = 1×3
-32768 -32765 32767

Bruno Luong on 3 Feb 2024
Edited: Bruno Luong on 3 Feb 2024
If you have C compiler this simple mex file will do the job:
/**************************************************************************
* Matlab Mex file castint16.C
Convert uint16 to int16 by adding 2^15 in 2-complement binary coding
Example:
a = uint16([0 2^16-1])
b = castint16(a)
will return
1×2 int16 row vector
-32768 32767
Compile:
mex -R2018a castint16.c
*************************************************************************/
#include "mex.h"
#include "matrix.h"
#define A prhs[0]
#define B plhs[0]
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[]) {
size_t i, n;
mxUint16 *a, *b;
if (nrhs!=1)
mexErrMsgTxt("castint16 missing input argument");
/* n = numel(A) */
n = mxGetNumberOfElements(A);
if (mxGetClassID(A) == mxUINT16_CLASS) {
a = mxGetUint16s (A);
B = mxCreateNumericMatrix(mxGetM(A), mxGetN(A), mxINT16_CLASS, mxREAL);
b = mxGetInt16s(B);
for (i = 0; i < n; i++)
b[i] = a[i] + 0x8000;
} else
mexErrMsgTxt("castint16 suports only UINT16 input");
}