logical converting to double for no reason - bug?

8 views (last 30 days)
I have a function that reads data from a text file and returns a structure with the data. One field of the data should be logical and one field should be double. When I run this function one time, the field that should be logical is logical. Great. But when I run the function again, the data type of the field that should be logical is double. Is there any explanation for this?
The first thing I did was try to debug it by putting a breakpoint at the line that assigns the logical data to output. To my surprise, simply the act of placing a breakpoint here fixes the problem. This is true even if I make the breakpoint conditional and the condition always evaluates to false.
I've also discovered that the problem goes away when I clear the function using the "clear" command.
Here is my function:
function Data = readData2(DataFile)
fp = fopen(DataFile,'r');
Data.boolVar = getVariable(fp);
Data.scalarVar = getVariable(fp);
fclose(fp);
end
function val = getVariable(fp_in)
keep_going = true;
while keep_going
txt = fgetl(fp_in);
if strcmp(txt(1),'>')
val = parseData(txt);
keep_going = false;
end
end
end
function val = parseData(str)
if isempty(strfind(str,'<'))
str = [str ' <'];
end
toks = regexp(regexp(str,'(?<=> ).*(?= <)','match'),'\S+','match');
toks = toks{1};
for i = 1:length(toks)
valstr = toks{i};
if strcmp(valstr,'T')
val(1,i) = true;
elseif strcmp(valstr,'F')
val(1,i) = false;
else
val(1,i) = str2double(valstr);
end
end
end
And the text file it is reading:
* data_file.txt
*--------------------------------------------
* Comment Comment Comment
*------------------------------------------------
* Comment Blah Blah
*------------------------------------------------
* boolean variable 1
> T T T T
*
*
* Comments
*
*
* 3 more variables
> 0.4 -0.3 -0.3 0.6
> 0.4 0.9 -0.4 -0.8
> 0.7 0.1 0.2 0.3
*
* another variable
> 3
*
* More comments
Here is a tester script that demonstrates my problem:
clear all
clc
islogicaldisp = @(x) disp([' isa(Data.boolVar,''logical'') = ' num2str(isa(x,'logical'))]);
isdoubledisp = @(x) disp([' isa(Data.boolVar,''double'') = ' num2str(isa(x,'double'))]);
Data = readData2('data_file.txt');
disp('First pass:');
islogicaldisp(Data.boolVar)
isdoubledisp(Data.boolVar)
Data = readData2('data_file.txt');
disp('Second pass - converted to double!?!?:');
islogicaldisp(Data.boolVar)
isdoubledisp(Data.boolVar)
Data = readData2('data_file.txt');
disp('Third pass - just to make sure...:');
islogicaldisp(Data.boolVar)
isdoubledisp(Data.boolVar)
dbstop in readData2 at 34 if false
disp('Fourth pass - this time add an inactive breakpoint:');
Data = readData2('data_file.txt');
islogicaldisp(Data.boolVar)
isdoubledisp(Data.boolVar)
disp(' What?? ^^^^^^^^^');
dbclear in readData2
disp('Fifth pass - deactivate breakpoint and try again:');
Data = readData2('data_file.txt');
islogicaldisp(Data.boolVar)
isdoubledisp(Data.boolVar)
Data = readData2('data_file.txt');
disp('Sixth pass - just to be sure...:');
islogicaldisp(Data.boolVar)
isdoubledisp(Data.boolVar)
clear readData2
Data = readData2('data_file.txt');
disp('7th pass - cleared readData2 function:');
islogicaldisp(Data.boolVar)
isdoubledisp(Data.boolVar)
And here is the result of the test script:
First pass:
isa(Data.boolVar,'logical') = 1
isa(Data.boolVar,'double') = 0
Second pass - converted to double!?!?:
isa(Data.boolVar,'logical') = 0
isa(Data.boolVar,'double') = 1
Third pass - just to make sure...:
isa(Data.boolVar,'logical') = 0
isa(Data.boolVar,'double') = 1
Fourth pass - this time add an inactive breakpoint:
isa(Data.boolVar,'logical') = 1
isa(Data.boolVar,'double') = 0
What?? ^^^^^^^^^
Fifth pass - deactivate breakpoint and try again:
isa(Data.boolVar,'logical') = 0
isa(Data.boolVar,'double') = 1
Sixth pass - just to be sure...:
isa(Data.boolVar,'logical') = 0
isa(Data.boolVar,'double') = 1
7th pass - cleared readData2 function:
isa(Data.boolVar,'logical') = 1
isa(Data.boolVar,'double') = 0
Any idea what is going on here?
Thanks!
  5 Comments
Brendan Hamm
Brendan Hamm on 2 Jul 2015
Edited: Brendan Hamm on 2 Jul 2015
While not explaining why it happens, I can see where it is happening and suggest a work-around. It appears this is happening when the function parseData is returning a logical the first time and a double on its second call. Every subsequent call to the function parseData results in a double being passed back (set a break at the call to the function and you will see this is the return on subsequent calls), but inside the function the variable val will still be a logical on these subsequent calls. A workaround here is to assign the logicals to one temporary variable and double values to another and then use an if statement to determine which to assign to val:
function val = parseData(str)
if isempty(strfind(str,'<'))
str = [str ' <'];
end
toks = regexp(regexp(str,'(?<=> ).*(?= <)','match'),'\S+','match');
toks = toks{1};
dblval = [];
for i = 1:length(toks)
valstr = toks{i};
if strcmp(valstr,'T')
logval(1,i) = true;
elseif strcmp(valstr,'F')
logval(1,i) = false;
else
dblval(1,i) = str2double(valstr);
end
if isempty(dblval)
val = logval;
else
val = dblval;
end
end
end
Of course you should also submit a bug-report: Contact Support
Matt Downs
Matt Downs on 7 Jul 2015
Thanks for the responses. I've implemented a workaround and I am going to report this as a bug. Ordinarily I wouldn't have noticed or cared about this, but the data structure is being used in Simulink as a bus object and I need to explicitly define the type in the bus definition.

Sign in to comment.

Accepted Answer

Jan
Jan on 7 Jul 2015
Setting a breakpoint disables the JIT acceleration. This is required, because the JIT can re-order the commands to gain more speed. But re-ordered commands are not useful when the source code is debugged. Therefore it seems like you have found an inconsistency in the JIT processing.
Try:
feature JIT off
feature accel off
Then run the code again.

More Answers (0)

Categories

Find more on Scripts in Help Center and File Exchange

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!