Re: [Csnd] gi variable evaluation?
Date | 2012-02-17 22:17 |
From | "Art Hunkins" |
Subject | Re: [Csnd] gi variable evaluation? |
Victor, But the problem is with the if/then branch in instr 1. Since during k-time givar == 2, the branch should be taken and nothing should print. Part of instr 1 during this time (the printk) seems to think givar = 2, while another part (if/then) thinks it is some other value (probably 0?) And, as you point out, when instr 1 starts slightly later than instr 2, the if/then construction acts correctly (realizing that givar ==2) and taking the branch. Why it/then works correctly with the delay, but not with a simultaneous start, remains a mystery to me. Art Hunkins ----- Original Message ----- From: "Victor Lazzarini" |
Date | 2012-02-17 22:33 |
From | Steven Yi |
Subject | Re: [Csnd] gi variable evaluation? |
Hi Art, The reason Victor gave is correct, but may require more explanation. On the whole, one should not ever mix i-time if-then's with any k-rate code within it, as it will lead to this exact situation. When an i-time if-then is evaluated, it is *only* evaluated at i-time. At performance time, Csound essentially goes right through. If-thens are syntax sugar, and Csound will unroll it as an if-goto with labels. Also to note, while we may look at Csound code as having branches, internally it is not a tree but a flat list of opcodes, with labels used for jumping. So imagine this: if (ival != 2) then printk kval endif becomes: #b0 = (ival == 2) cigoto #b0, __label0 printk kval __label0: On the i-time pass, Csound goes through each opcode one-by-one. It will hit that cigoto (I think that's the opcode that gets put in) at that time and then proceed to the label. The printk doesn't happen, but that's expected as it is supposed to print at performance time. At performance time, the cigoto does nothing because it is an i-time only opcode, and csound then proceeds to the printk and calls it's performance function. Even though logically you'll think "but ival is equal to 0," it is only evaluated at that first pass. This is why one should never mix k-rate code within i-time if-then's. The solution is to cast an i-var to k-rate, to force k-rate comparison, or use if-kgoto. (I would need to check about if-kgoto...). Also, the danger in putting in k-rate code within the loop is that i-time it *does* jump, and therefore your opcodes don't get their init-functions called. If they later get called during performance time, those opcodes won't be initialized and you'll get unexpected results. To simplify then, one should always follow the rule that when using if-then, always match up the code within the if-then with the rate of the value used within the if comparison. In general, it becomes pretty natural once you follow the rule. There is one case where there is some weird things going on, which is when you recursively call UDO's and want to limit the number at i-time as well as number called during performance time. It's an edge case though and likely not many people have run into it, but you essentially have to use two sets of if-then's, one at i-time and another at k-time. Hopefully that should explain the issue! steven On Fri, Feb 17, 2012 at 10:17 PM, Art Hunkins |
Date | 2012-02-17 22:59 |
From | Rory Walsh |
Subject | Re: [Csnd] gi variable evaluation? |
That's going straight into my next class! On Friday, 17 February 2012, Steven Yi <stevenyi@gmail.com> wrote: > Hi Art, > > The reason Victor gave is correct, but may require more explanation. > On the whole, one should not ever mix i-time if-then's with any k-rate > code within it, as it will lead to this exact situation. > > When an i-time if-then is evaluated, it is *only* evaluated at i-time. > At performance time, Csound essentially goes right through. If-thens > are syntax sugar, and Csound will unroll it as an if-goto with labels. > Also to note, while we may look at Csound code as having branches, > internally it is not a tree but a flat list of opcodes, with labels > used for jumping. So imagine this: > > if (ival != 2) then > printk kval > endif > > becomes: > #b0 = (ival == 2) > cigoto #b0, __label0 > printk kval > __label0: > > > On the i-time pass, Csound goes through each opcode one-by-one. It > will hit that cigoto (I think that's the opcode that gets put in) at > that time and then proceed to the label. The printk doesn't happen, > but that's expected as it is supposed to print at performance time. > At performance time, the cigoto does nothing because it is an i-time > only opcode, and csound then proceeds to the printk and calls it's > performance function. Even though logically you'll think "but ival is > equal to 0," it is only evaluated at that first pass. > > This is why one should never mix k-rate code within i-time if-then's. > The solution is to cast an i-var to k-rate, to force k-rate > comparison, or use if-kgoto. (I would need to check about > if-kgoto...). Also, the danger in putting in k-rate code within the > loop is that i-time it *does* jump, and therefore your opcodes don't > get their init-functions called. If they later get called during > performance time, those opcodes won't be initialized and you'll get > unexpected results. > > To simplify then, one should always follow the rule that when using > if-then, always match up the code within the if-then with the rate of > the value used within the if comparison. In general, it becomes > pretty natural once you follow the rule. > > There is one case where there is some weird things going on, which is > when you recursively call UDO's and want to limit the number at i-time > as well as number called during performance time. It's an edge case > though and likely not many people have run into it, but you > essentially have to use two sets of if-then's, one at i-time and > another at k-time. > > Hopefully that should explain the issue! > steven > > > > On Fri, Feb 17, 2012 at 10:17 PM, Art Hunkins <abhunkin@uncg.edu> wrote: >> Victor, >> >> But the problem is with the if/then branch in instr 1. Since during k-time >> givar == 2, the branch should be taken and nothing should print. Part of >> instr 1 during this time (the printk) seems to think givar = 2, while >> another part (if/then) thinks it is some other value (probably 0?) >> >> And, as you point out, when instr 1 starts slightly later than instr 2, the >> if/then construction acts correctly (realizing that givar ==2) and taking >> the branch. Why it/then works correctly with the delay, but not with a >> simultaneous start, remains a mystery to me. >> >> Art Hunkins >> >> ----- Original Message ----- From: "Victor Lazzarini" >> <Victor.Lazzarini@nuim.ie> >> To: <csound@lists.bath.ac.uk> >> Sent: Friday, February 17, 2012 4:24 PM >> Subject: Re: [Csnd] gi variable evaluation? >> >> >> >> The reason is this: >> >> 1) if ... then is evaluated at i-time when gival == 0 >> Since the condition is true, both print statements will be executed. At this >> stage (initi-pass) only print is executed >> >> 2) instr 2 changes the value of gival to 2 at its init-pass >> >> 3) the printk statement now runs at performance time and correctly reads the >> global var value (now 2). >> >> NB: if you start instr 1 1-kcycle after instr 2, nothing will print. >> >> Victor >> On 17 Feb 2012, at 20:54, Art Hunkins wrote: >> >>> I don't understand what is happening in the simple csd below: >>> >>> During the init pass, gival is initialized to 0, but instr 2 changes it to >>> 2. Meanwhile, instr 1 correctly evaluates it to 0, falling into the if/then >>> construction (print gival), the condition being true. >>> >>> During the k passes, instr 1, consistently prints (printk) gival as = 2, >>> as you'd expect - since instr 2 changed its value. >>> >>> However, *it should never have fallen into the if/then construction*; as >>> the condition is now false (gival == 2). >>> >>> If the if/then construction is changed to if/goto, the same evaluation >>> error occurs. >>> >>> This, BTW, is all with the old parser, Windows XP, Csound 5.06. (And of >>> course if instruments 1 and 2 are interchanged, all works as expected.) >>> >>> What's going on? >>> >>> Art Hunkins >>> >>> >>> <CsoundSynthesizer> >>> <CsOptions> >>> -odac >>> </CsOptions> >>> <CsInstruments> >>> sr = 44100 >>> kr = 44100 >>> nchnls = 1 >>> gival init 0 >>> >>> instr 1 >>> >>> if gival != 2 then >>> print gival >>> printk .1, gival >>> endif >>> endin >>> >>> instr 2 >>> gival = 2 >>> endin >>> >>> </CsInstruments> >>> >>> <CsScore> >>> i1 0 1 >>> i2 0 1 >>> >>> e >>> </CsScore> >>> </CsoundSynthesizer> >>> >>> >>> Send bugs reports to the Sourceforge bug tracker >>> https://sourceforge.net/tracker/?group_id=81968&atid=564599 >>> Discussions of bugs and features can be posted here >>> To unsubscribe, send email sympa@lists.bath.ac.uk with body "unsubscribe >>> csound" >>> >> >> Dr Victor Lazzarini >> Senior Lecturer >> Dept. of Music >> NUI Maynooth Ireland >> tel.: +353 1 708 3545 >> Victor dot Lazzarini AT nuim dot ie >> >> >> >> >> >> Send bugs reports to the Sourceforge bug tracker >> https://sourceforge.net/tracker/?group_id=81968&atid=564599 >> Discussions of bugs and features |
Date | 2012-02-17 23:47 |
From | matt ingalls |
Subject | Re: [Csnd] gi variable evaluation? |
steven: if this is how it works now, then this is a change from the original implementation. if/then is supposed to be the equivalent to if/goto and as should do the conditional at BOTH i and k rates. On Feb 17, 2012, at 2:33 PM, Steven Yi wrote: > if (ival != 2) then > printk kval > endif > > becomes: > #b0 = (ival == 2) > cigoto #b0, __label0 > printk kval > __label0: |
Date | 2012-02-17 23:58 |
From | matt ingalls |
Subject | Re: [Csnd] gi variable evaluation? |
and just to clarify a bit more, i think this is how it should work (at least how it used to) ival init 0 if (ival != 0) then ; never gets here at i or k passes endif if (kval == kotherval) then ; always here at i-pass ; could be here or not at k-pass depending on conditional endif if (xval) ithen ; here during the i-pass (if conditional was true) ; never here during k-pass endif On Feb 17, 2012, at 3:47 PM, matt ingalls wrote: > steven: > if this is how it works now, then > this is a change from the original implementation. > > if/then is supposed to be the equivalent to if/goto > and as should do the conditional at BOTH i and k rates. > > > > On Feb 17, 2012, at 2:33 PM, Steven Yi wrote: > >> if (ival != 2) then >> printk kval >> endif >> >> becomes: >> #b0 = (ival == 2) >> cigoto #b0, __label0 >> printk kval >> __label0: > > > > Send bugs reports to the Sourceforge bug tracker > https://sourceforge.net/tracker/?group_id=81968&atid=564599 > Discussions of bugs and features can be posted here > To unsubscribe, send email sympa@lists.bath.ac.uk with body "unsubscribe csound" > |
Date | 2012-02-18 01:13 |
From | Steven Yi |
Subject | Re: [Csnd] gi variable evaluation? |
Hmm, interesting! I think I had either looked at this before, forgot it, and remembered something wrong, or maybe just had it wrong in my head all this time, and the side effect was that it got me the right results. (!!) I went and looked at the code. In the old parser, if-then uses cngoto, and if-ithen uses cogoto. In the new parser, it looks like it is only using cngoto (that's a bug that should be fixed...). So, Matt's correct and the current Csound *does* what he says. However, I think I do understand what is going on with Art's situation. The value that is compared on the first pass is cached as a boolean on that init-pass. At that time, the value evaluated to false, and that is stored in a synthetic b variable. So going back to the translated code: #b0 = (ival == 2) cngoto #b0, __label0 printk kval __label0: That #b0 stores the initial comparison. Therefore, if it's true or false at init-time, it's going to stay that way through performance-time. If the gival changes, it won't affect the value used in the conditional check. This is great that you chimed in Matt, thanks! Now I've got it clearer in my head. (Rory: You may want to revise what you present! :P) steven On Fri, Feb 17, 2012 at 11:58 PM, matt ingalls |
Date | 2012-02-18 18:23 |
From | matt ingalls |
Subject | Re: [Csnd] gi variable evaluation? |
On Feb 17, 2012, at 5:13 PM, Steven Yi wrote: > and if-ithen uses cogoto. In the new parser, it > looks like it is only using cngoto (that's a bug that should be > fixed...). im not exactly sure what cogoto does, but it occurs to me i was wrong about 'ithen' it probably should work the same as an if/goto with an i-pass conditional, but ALWAYS do the conditional at the i-pass, even if there are k-rate variables, so that: instr 1 kvar init 1 if (kvar == 1) ithen ; goes here at i and k passes endif if (kvar == 0) ithen ; never goes here endif if (kvar == 0) then ; goes here at i-pass ; doesnt go here at k-pass (unless we add code that changes kvar to 0 in some k-pass) endif endin |
Date | 2012-02-18 18:34 |
From | Steven Yi |
Subject | Re: [Csnd] gi variable evaluation? |
cogoto does pretty much what you were saying, always evaluating at i-time regardless of if it is a k-var in the expression. On Sat, Feb 18, 2012 at 6:23 PM, matt ingalls |