1. Do I need to refactor this code?

I have an auto-generated flat source code, thousands of monotone lines, many of which have more than a dozen comparisons. Comparisons are often repeated. Sometimes, all except one:

if (a = 0) and (b = 1) and (c = 2) and (d = 3) and (e = 4) and (f = 5) and (g = 6) and (h = 7) and (i = 8) and (x = 9) return 1 end if 
if (a = 0) and (b = 1) and (c = 2) and (d = 3) and (e = 4) and (f = 5) and (g = 6) and (h = 7) and (i = 8) and (y = 10) return 2 end if 
if (a = 0) and (b = 1) and (c = 2) and (d = 3) and (e = 4) and (f = 5) and (g = 6) and (h = 7) and (i = 8) and (z = 11) return 3 end if 

Obviously, this code can be optimized:

if (a = 0) and (b = 1) and (c = 2) and (d = 3) and (e = 4) and (f = 5) and (g = 6) and (h = 7) and (i = 8) then 
  if (x = 9) return 1 end if 
  if (y = 10) return 2 end if 
  if (z = 11) return 3 end if 
end if 

Does it make practical sense? I know that C++ compilers (at least some of them) are able to do this automatically. What about Euphoria? I use eushroud, if it is important.

new topic     » topic index » view message » categorize

2. Re: Do I need to refactor this code?

TheresNoTime said...

I have an auto-generated flat source code, thousands of monotone lines, many of which have more than a dozen comparisons. Comparisons are often repeated. Sometimes, all except one:

if (a = 0) and (b = 1) and (c = 2) and (d = 3) and (e = 4) and (f = 5) and (g = 6) and (h = 7) and (i = 8) and (x = 9) return 1 end if 
if (a = 0) and (b = 1) and (c = 2) and (d = 3) and (e = 4) and (f = 5) and (g = 6) and (h = 7) and (i = 8) and (y = 10) return 2 end if 
if (a = 0) and (b = 1) and (c = 2) and (d = 3) and (e = 4) and (f = 5) and (g = 6) and (h = 7) and (i = 8) and (z = 11) return 3 end if 

Obviously, this code can be optimized:

if (a = 0) and (b = 1) and (c = 2) and (d = 3) and (e = 4) and (f = 5) and (g = 6) and (h = 7) and (i = 8) then 
  if (x = 9) return 1 end if 
  if (y = 10) return 2 end if 
  if (z = 11) return 3 end if 
end if 

Does it make practical sense? I know that C++ compilers (at least some of them) are able to do this automatically. What about Euphoria? I use eushroud, if it is important.

Generated Euphoria code is not this sophisticated yet.

You might want to try this approach, depending on how you automate the code generation ...

sequence temp 
temp = {a,b,c,d,e,f,g,h,i,x} 
 
switch temp do 
    case {0,1,2,3,4,5,6,7,8,9} then return 1 end case 
    case {0,1,2,3,4,5,6,7,8,10} then return 2 end case 
    case {0,1,2,3,4,5,6,7,8,11} then return 3 end case 
end switch 
new topic     » goto parent     » topic index » view message » categorize

3. Re: Do I need to refactor this code?

TheresNoTime said...

I have an auto-generated flat source code, thousands of monotone lines..

How serious are you about optimising these operations? If you could give a bit more detail about the ranges of comparison values and what they get compared to it must be possible to reduce the problem to a lookup using, eg, find()

Spock

new topic     » goto parent     » topic index » view message » categorize

4. Re: Do I need to refactor this code?

DerekParnell said...

You might want to try this approach, depending on how you automate the code generation ...

Nice idea, but it is impossible. Comparison operation can be varied, not only check for equality. I regret that misled. I would like to draw attention to the structure of the code.

new topic     » goto parent     » topic index » view message » categorize

5. Re: Do I need to refactor this code?

Spock said...
TheresNoTime said...

I have an auto-generated flat source code, thousands of monotone lines..

How serious are you about optimising these operations?

In fact, not very serious. I suspect that thousands of comparisons to slow down today's computers a few thousandths (maybe a few hundredths) of a second.

said...

If you could give a bit more detail about the ranges of comparison values and what they get compared to it must be possible to reduce the problem to a lookup using, eg, find()

I think, main detail is order of operations. If the next line have same operations, they start from the beginning of the line and are in the same order.

if (a = 0 or b > 10) and (c < 10 or d = 100) then return 1 end if 
if (a = 0 or b > 10) and (c < 10 or d = 100) and e[f] then return 2 end if 
if (a = 0 or b > 10) and (c < 10 or d = 100) and e[g] then return 3 end if 
if (a = 0 or b > 10) and (c < 10 or d = 100) and e[g] and (h != 115) then return 4 end if 

So, it is easy to create recursive algorithm for optimizing: all "and"s must be converted to "sub-if"s. Each line is compared with previous lines. Then we search maximal number of similar expressions between "and"s. Found expressions are removed, and the line is inserted into the appropriate "sub-if".

if (a = 0 or b > 10) then 
  if (c < 10 or d = 100) then 
    if e[f] then 
      return 2 
    end if 
    if e[g] then 
      if (h != 115) then 
        return 4 
      end if 
      return 3 
    end if 
    return 1 
  end if 
end if 
new topic     » goto parent     » topic index » view message » categorize

6. Re: Do I need to refactor this code?

DerekParnell said...

<snip>
You might want to try this approach, depending on how you automate the code generation ...

sequence temp 
temp = {a,b,c,d,e,f,g,h,i,x} 
 
switch temp do 
    case {0,1,2,3,4,5,6,7,8,9} then return 1 end case 
    case {0,1,2,3,4,5,6,7,8,10} then return 2 end case 
    case {0,1,2,3,4,5,6,7,8,11} then return 3 end case 
end switch 

Pretty in many ways. Is there a "don't care" value, or a helpful hint to catch a error or fall-thru in the Eu source code, such that

sequence temp 
temp = {0,1,2,3,4,5,6,7,"<12",9} 
 
switch temp do 
    -- "" = type sequence flag = "don't care" (yeas, aka an error) 
    case {0,1,2,3,4,5,6,7,"",9} then return {1,temp} end case 
end switch 

So while Eu didn't process the "<12", temp is otherwise tested and returned to the user in a sequence for extra processing?

Or praps this:

type P_1(integer x) 
    return x >= 0 and x <= 23 
end type 
sequence temp 
temp = {atom,atom,atom,atom,atom,atom,atom,atom,P_1,atom} 
 
switch temp do 
    case {0,1,2,3,4,5,6,7,12,9} then return 1 end case 
end switch 

Or praps there is some way to push a list of types into the case comparisons internally on a case-by-case basis?

I have also had a situation where this would have been extremely valuable in optical pattern recognition or extracting details about motion. It would also be handy in resolving tags in content addressable data, or misspelling, or ?

useless

new topic     » goto parent     » topic index » view message » categorize

7. Re: Do I need to refactor this code?

TheresNoTime said...

Does it make practical sense? I know that C++ compilers (at least some of them) are able to do this automatically. What about Euphoria? I use eushroud, if it is important.

If you have information that this is a real bottleneck, then it may make practical sense. While euphoria won't completely optimize out duplicate comparisons, it does do short circuiting, so if, in a long string of and operations, it find something false, it won't perform the rest of the operations. Likewise, if a true value is found in the first argument of an or operation, it won't bother with the second.

Most of your code doesn't need to be optimized, as a general rule. And due to short circuiting, it might be easier or more effective to reorder comparisons if you have some knowledge of the underlying data.

Matt

new topic     » goto parent     » topic index » view message » categorize

8. Re: Do I need to refactor this code?

Thanks for ideas! Your answers led me to this thought. We read all the lines and find the most frequent combination of two conjunctions (x and y and z). Replace it with a temporary Boolean variable. Declare it before the first combination (x and y and z). Repeat until such combinations will not stay!

Original code:

if (a = 0) and (b = 1) and (c = 2) and (d = 3) and (e = 4) and (f = 5) and (g = 6) and (h = 7) and (i = 8) and (x = 9) return 1 end if  
if (a = 0) and (b = 1) and (c = 2) and (d = 3) and (e = 4) and (f = 5) and (g = 6) and (h = 7) and (i = 8) and (y = 10) return 2 end if  
if (a = 0) and (b = 1) and (c = 2) and (d = 3) and (e = 4) and (f = 5) and (g = 6) and (h = 7) and (i = 8) and (z = 11) return 3 end if  

After 1st iteration:

integer tmp1 = (a = 0) and (b = 1) and (c = 2) 
if tmp1 and (d = 3) and (e = 4) and (f = 5) and (g = 6) and (h = 7) and (i = 8) and (x = 9) return 1 end if  
if tmp1 and (d = 3) and (e = 4) and (f = 5) and (g = 6) and (h = 7) and (i = 8) and (y = 10) return 2 end if  
if tmp1 and (d = 3) and (e = 4) and (f = 5) and (g = 6) and (h = 7) and (i = 8) and (z = 11) return 3 end if  

After 2nd iteration:

integer tmp1 = (a = 0) and (b = 1) and (c = 2) 
integer tmp2 = tmp1 and (d = 3) and (e = 4) 
if tmp2 and (f = 5) and (g = 6) and (h = 7) and (i = 8) and (x = 9) return 1 end if  
if tmp2 and (f = 5) and (g = 6) and (h = 7) and (i = 8) and (y = 10) return 2 end if  
if tmp2 and (f = 5) and (g = 6) and (h = 7) and (i = 8) and (z = 11) return 3 end if  

After 3rd iteration:

integer tmp1 = (a = 0) and (b = 1) and (c = 2) 
integer tmp2 = tmp1 and (d = 3) and (e = 4) 
integer tmp3 = tmp2 and (f = 5) and (g = 6) 
if tmp3 and (h = 7) and (i = 8) and (x = 9) return 1 end if  
if tmp3 and (h = 7) and (i = 8) and (y = 10) return 2 end if  
if tmp3 and (h = 7) and (i = 8) and (z = 11) return 3 end if  

After 4th iteration:

integer tmp1 = (a = 0) and (b = 1) and (c = 2) 
integer tmp2 = tmp1 and (d = 3) and (e = 4) 
integer tmp3 = tmp2 and (f = 5) and (g = 6) 
integer tmp4 = tmp3 and (h = 7) and (i = 8) 
if tmp4 and (x = 9) return 1 end if  
if tmp4 and (y = 10) return 2 end if  
if tmp4 and (z = 11) return 3 end if  

That's all! The method is not ideal, but it is universal, infallible and simple to implement.

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu