Stupid Problem

Coding and general discussion relating to the compiler

Moderators: David Barker, Jerry Messina

Post Reply
NigelMills
Posts: 22
Joined: Mon Jan 13, 2014 2:33 pm

Stupid Problem

Post by NigelMills » Fri Oct 03, 2014 3:23 pm

Gents,

I have a stupid problem with an IF statement which even although I can view the compared parameters, makes the wrong decision !

I have the following:

Code: Select all

  Const MagHyst = 4   '= +/- 1/16 = total 12.5% hysteresis band.

  Dim YHyst As Integer

  'Range always positive.  
  Yhyst = Y.Range >> MagHyst

      print (" Z- ", dectostr(Yq)," / ",dectostr(Y.Mid + YHyst))
      If (Yq > (Y.Mid + YHyst)) Then
        print (" Y+")
        Result = 1
      Else
        If Yq < (Y.Mid - YHyst)  Then
          print (" Y-")
          Result = 0
        Else
          print (" Y=")
          Result = LastCorner
        EndIf
      EndIf
This yields a printout: Z- 1606 / 1578 Y=

Which is wrong, the IF should be true and it should print "Y+".

If I replace the code with:

Code: Select all

  Dim DThresh as Integer
  
      DThresh = (Y.Mid + YHyst)
      print (" Z- ", dectostr(Yq)," / ",dectostr(DThresh))
      If Yq > (Dthresh) Then
        print (" Y+")
OR I force a type Integer with this:

Code: Select all

      If (Yq > Integer(Y.Mid + YHyst)) Then
        print (" Y+")
Then I get printed: Z- 1606 /-/ 1578 Y+

So the IF is evaluated correctly.

For completeness Y.Mid =1561 and Y.Range correctly shifts right to give YHyst = 17

I have used MPLab with a breakpoint on the `IF` in question, and viewed all the parameters in the watch window both pre and post execution of the condition. All appears correct.

I have Swordfish V 2.2.2.2 ICC 1.1.6.4, having just upgraded from an older version which still had me equally stumped.

There's a lot more code of course, interrupts etc. But this is 100% consistent even when the routine is called forcing the parameters with constants.

If anyone can enlighten me, or give me investigative pointers, I'd be happy to follow up and preserve the little hair I have left.

Best regards,

Nigel

bitfogav
Registered User
Registered User
Posts: 169
Joined: Sat Oct 09, 2010 1:39 pm
Location: United Kingdom

Re: Stupid Problem

Post by bitfogav » Fri Oct 03, 2014 4:10 pm

It looks like it has something to do with how the compiler is evaluating the expression, It is not a problem as such with the compiler, the compiler carries out several computations to get the correct result..

Check out the compiler manual page 35, look under the heading "Typecasting" SF Manual. hopefully this will explain things a little clearer.

By letting the compiler know what typecast you are evaluating then the compiler will compute the expression to what results you would expect..
As you have done below:

Code: Select all

      If (Yq > Integer(Y.Mid + YHyst)) Then
        print (" Y+")

Jerry Messina
Swordfish Developer
Posts: 1473
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Re: Stupid Problem

Post by Jerry Messina » Fri Oct 03, 2014 6:15 pm

Could you post a small complete example that actually compiles?

What you've posted is missing a few variable declarations, and that might matter.

NigelMills
Posts: 22
Joined: Mon Jan 13, 2014 2:33 pm

Re: Stupid Problem

Post by NigelMills » Fri Oct 03, 2014 8:02 pm

@bitfogav

Thanks for that. I've reread the manual, and I do understand that as both the parameters on the right are Integers, the result could be greater than an integer, so presumably the compiler will use a LongInt for the intermediate result before the comparison.

OK, I understand that, but surely the comparison then should still yield the correct result, even although the left and right sides of the comparison are different types (presumably by converting to the same type before comparing).

I feel better informed as to what goes on, but I still don't understand why the result is wrong !

@Jerry I'll post a fuller excerpt on Monday as I'm out of the office now.

Jerry Messina
Swordfish Developer
Posts: 1473
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Re: Stupid Problem

Post by Jerry Messina » Fri Oct 03, 2014 8:06 pm

Are all the missing variables declared "as integer" type?

Jerry Messina
Swordfish Developer
Posts: 1473
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Re: Stupid Problem

Post by Jerry Messina » Mon Oct 06, 2014 1:56 pm

just FYI, I tried the following code and always got the correct answer... the first IF was evaluated as true and it "printed" Z- 1606 / 1578 Y+

The expression "If (Yq > (Y.Mid + YHyst)) Then" IS being done in 32-bit. I made some assumptions about the data types, so perhaps they aren't the same?

Code: Select all

include "convert.bas"

Const MagHyst = 4

dim Yhyst as integer
dim Yq as integer
dim Dthresh as integer

structure Y_T
    range as integer
    mid as integer
end structure

dim y as Y_T
dim result as byte

dim s as string         // just put output to string instead of print

'forum: For completeness Y.Mid =1561 and Y.Range correctly shifts right to give YHyst = 17
' test conditions
y.mid = 1561
y.range = 17*16 + 15    ' gets shifted to produce Yhyst = 17 (>> 4)
Yq = 1606


'Range always positive
Yhyst = Y.Range >> MagHyst

'print (" Z- ", dectostr(Yq)," / ",dectostr(Y.Mid + YHyst))
s = " Z- " + dectostr(Yq) + " / " + dectostr(Y.Mid + YHyst)
If (Yq > (Y.Mid + YHyst)) Then
    s = s + " Y+"
    'print (" Y+")
    Result = 1
Else
    if Yq < (Y.Mid - YHyst)  Then
        s = s + " Y-"
        'print (" Y-")
        Result = 0
    Else
        s = s + " Y="
        'print (" Y=")
        Result = 2
    endif
EndIf
//forum: This yields a printout: Z- 1606 / 1578 Y=
//forum: Which is wrong, the IF should be true and it should print "Y+".

// forum: both these work
// forum: Then I get printed: Z- 1606 /-/ 1578 Y+, which is correct
' print (" Z- ", dectostr(Yq)," / ",dectostr(DThresh))
DThresh = (Y.Mid + YHyst)
if (Yq > Dthresh) then
    result = 1
endif

if (Yq > integer(Y.Mid + YHyst)) Then
    result = 1
endif

NigelMills
Posts: 22
Joined: Mon Jan 13, 2014 2:33 pm

Re: Stupid Problem

Post by NigelMills » Mon Oct 06, 2014 2:48 pm

@Jerry

Firstly, thank you for the effort you've obviously been putting in here on my problem. I did reply over the weekend that "they were all integers", but that seems to have failed to post correctly from my iPad.

I did produce a `minimalist` version of the code and function in question over the weekend, but of course testing that here today, it works without error (rather like yours) !

Instead I've been using the infamous print statement to try and determine exactly what is going on, and I submit these for your consideration.....

Common Stuff

Code: Select all

' Define the parameters required for each axis
Structure TAxis
  Value As Integer
  Hi As Integer
  Lo As Integer
  Mid As Integer
  Range As Integer
End Structure

Public Dim Y As TAxis
Routine in question

Code: Select all

Public Function NearestCorner(Yq As Integer, Zq As Integer, LastCorner As Byte) As Byte

  'The calling parameters are academic as all values fixed as constants in the routine to debug !

  Dim YHyst As Integer

  Yhyst = 17
  Yq = 1606
  Y.Mid = 1561
  
  print ("[In: Yq=",dectostr(Yq),", Y.Mid=",dectostr(Y.Mid),", YHyst=",dectostr(YHyst),", (Y.Mid + Y.Hyst)=",dectostr(Y.Mid + YHyst))
  print (", Yq - (Y.Mid + YHyst)=",dectostr(Yq - (Y.Mid + YHyst)))
  print (", (Y.Mid + YHyst) - Yq=",dectostr((Y.Mid + YHyst) - Yq),"]")
  printcrlf  
 
      If (Yq > (Y.Mid + YHyst)) Then
        print (" Yq+")
      Else
        If Yq < (Y.Mid - YHyst)  Then
          print (" Yq-")
        Else
          print (" Yq=")
        EndIf
      EndIf

  printcrlf  
  print ("[Out: Yq=",dectostr(Yq),", Y.Mid=",dectostr(Y.Mid),", YHyst=",dectostr(YHyst),", (Y.Mid + Y.Hyst)=",dectostr(Y.Mid + YHyst))
  print (", Yq - (Y.Mid + YHyst)=",dectostr(Yq - (Y.Mid + YHyst)))
  print (", (Y.Mid + YHyst) - Yq=",dectostr((Y.Mid + YHyst) - Yq),"]")
  printcrlf  
 
End Function
Output:
[In: Yq=1606, Y.Mid=1561, YHyst=17, (Y.Mid + Y.Hyst)=1578, Yq - (Y.Mid + YHyst)=0, (Y.Mid + YHyst) - Yq=0]
Yq=
[Out: Yq=1606, Y.Mid=1561, YHyst=17, (Y.Mid + Y.Hyst)=1578, Yq - (Y.Mid + YHyst)=0, (Y.Mid + YHyst) - Yq=0]


Where the final two pieces of maths on both `In` and `Out` lines are obviously wrong (should be +28, then -28 not 0,0).


Changing the 2nd and 3rd lines of each `In` and `Out` print to include Integer() yields a different, but equally WRONG result (it should be +28 then -28 not PLUS 79 and PLUS 79 again)!

Code: Select all

  print (" Yq - (Y.Mid + YHyst)=",dectostr(Integer(Yq - (Y.Mid + YHyst))))
  print (" (Y.Mid + YHyst) - Yq=",dectostr(Integer((Y.Mid + YHyst) - Yq)),"]")
Output:
[In: Yq=1606, Y.Mid=1561, YHyst=17, (Y.Mid + Y.Hyst)=1578, Yq - (Y.Mid + YHyst)=79, (Y.Mid + YHyst) - Yq=79]
Yq=
[Out: Yq=1606, Y.Mid=1561, YHyst=17, (Y.Mid + Y.Hyst)=1578, Yq - (Y.Mid + YHyst)=79, (Y.Mid + YHyst) - Yq=79]



Finally, defining a new local integer in the routine...

Code: Select all

  Dim YMid As Integer
And changing all references to from Y.Mid to the now new local YMid, give the following correct output (and decision):

[In: Yq=1606 YMid=1561 YHyst=17 (YMid + Y.Hyst)=1578 Yq - (YMid + YHyst)=28 (YMid + YHyst) - Yq=-28]
Yq+
[Out: Yq=1606 YMid=1561 YHyst=17 (YMid + Y.Hyst)=1578 Yq - (YMid + YHyst)=28 (YMid + YHyst) - Yq=-28]



Also defining a temporary Integer local variable, assigning this to (Y.Mid + YHyst) and using the new temporary variably in the IF statement, also yields the correct outcome.

So, my rather ignorant conclusions would be that the maths is going wrong, and this is something to do with the conversion to 32 bit maths to support Integer + Integer. Why changing the maths and IF's to a local Integer YMid, instead of the structure variable Y.Mid somewhat eludes me.

Whilst everyone's first thought is "well what idiot would do it that way", the answer is this idiot. The compiler is meant to let idiots like me code without too much thought for the variable types, and just `sort it out` for me. In this case I feel somewhat let down on that undertaking.

Can you shed any light on what is happening ? Not that I can't bodge round it of course, it's just I hate doing that because I know the same unresolved problem will bite me in the bum a little further down the road, and be even harder to find !

Many thanks for your time,

Best regards,

Nigel

Jerry Messina
Swordfish Developer
Posts: 1473
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Re: Stupid Problem

Post by Jerry Messina » Mon Oct 06, 2014 5:03 pm

I get different results.

I copied your NearestCorner function verbatim into my test program, added a print command like thus:

Code: Select all

dim print as usart.write

sub printcrlf()
    usart.write(13)
    usart.write(10)
end sub
and got

Code: Select all

[In: Yq=1606, Y.Mid=1561, YHyst=17, (Y.Mid + Y.Hyst)=1578, Yq - (Y.Mid + YHyst)=28, (Y.Mid + YHyst) - Yq=-28]
 Yq+
[Out: Yq=1606, Y.Mid=1561, YHyst=17, (Y.Mid + Y.Hyst)=1578, Yq - (Y.Mid + YHyst)=28, (Y.Mid + YHyst) - Yq=-28]
Is everything up to date compiler-wise? What's displayed in the "Help | About" window?

Jerry Messina
Swordfish Developer
Posts: 1473
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Re: Stupid Problem

Post by Jerry Messina » Tue Oct 07, 2014 8:48 am

I should have mentioned... sometimes problems like this are very dependent on the order/existence of other code.

If everything's up to date then maybe you could post a zip file of an entire project that shows the issue.

NigelMills
Posts: 22
Joined: Mon Jan 13, 2014 2:33 pm

Re: Stupid Problem

Post by NigelMills » Tue Oct 07, 2014 9:09 am

Jerry,

I have Swordfish V2.2.2.2 - ICC 1.1.6.4.

I'll spend this morning trying to reduce the project in size and remove hardware dependencies while the problem remains, and then I would be very happy to post a zip file for you to have a peek at (PM ?).

It has me stumped.

Many thanks

Nigel.

User avatar
David Barker
Swordfish Developer
Posts: 1214
Joined: Tue Oct 03, 2006 7:01 pm
Location: Saltburn by the Sea, UK
Contact:

Re: Stupid Problem

Post by David Barker » Sun Nov 09, 2014 8:15 pm

A new compiler update is available to download. Click here

http://sfcompiler.co.uk/phpBB3/viewtopic.php?f=1&t=1900

for more information.

Post Reply