Is there a C API that could exchange the values at different index of the stack?

classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

Is there a C API that could exchange the values at different index of the stack?

孙世龙 sunshilong
Is there a C API that could exchange the values at different index of the stack?
For example:
index j is "hello" , index i is 100
invoke a specific API,
index j is 100,  index i is "hello"
Reply | Threaded
Open this post in threaded view
|

Re: Is there a C API that could exchange the values at different index of the stack?

Francisco Olarte
Sunshi...

On Fri, Jan 22, 2021 at 8:43 AM 孙世龙 sunshilong <[hidden email]> wrote:
> Is there a C API that could exchange the values at different index of the stack?
> For example:
> index j is "hello" , index i is 100
> invoke a specific API,
> index j is 100,  index i is "hello"

I think not, but you can easily do something like....
int lua_swapvalues(lua_State * L, int i, int j) {
   i = lua_absindex(L, i);
   j = lua_absindex(L, j);  /* In case either of them is negative. */
   if (i!=j) {
      if (!lua_checkstack(L,2))   return 0; /* Out of memory */
      lua_pushvalue(L,i);
      lua_pushvalue(L,j);
      lua_replace(L, i);
      lua_replace(L,j);
   }
   return 1;
}

FOS
Reply | Threaded
Open this post in threaded view
|

Re: Is there a C API that could exchange the values at different index of the stack?

孙世龙 sunshilong
Thank you so much.
>   i = lua_absindex(L, i);
>   j = lua_absindex(L, j);  /* In case either of them is negative. */
It's a magic!
After studying your code, I find that it is easier to achieve this
goal (i.e the title) by using positive indexes(or converting negative
indexes to positive ones) than directly using negative ones. Am I
right?

Best regards.
sunshilong

On Fri, Jan 22, 2021 at 4:12 PM Francisco Olarte <[hidden email]> wrote:

>
> Sunshi...
>
> On Fri, Jan 22, 2021 at 8:43 AM 孙世龙 sunshilong <[hidden email]> wrote:
> > Is there a C API that could exchange the values at different index of the stack?
> > For example:
> > index j is "hello" , index i is 100
> > invoke a specific API,
> > index j is 100,  index i is "hello"
>
> I think not, but you can easily do something like....
> int lua_swapvalues(lua_State * L, int i, int j) {
>    i = lua_absindex(L, i);
>    j = lua_absindex(L, j);  /* In case either of them is negative. */
>    if (i!=j) {
>       if (!lua_checkstack(L,2))   return 0; /* Out of memory */
>       lua_pushvalue(L,i);
>       lua_pushvalue(L,j);
>       lua_replace(L, i);
>       lua_replace(L,j);
>    }
>    return 1;
> }
>
> FOS
Reply | Threaded
Open this post in threaded view
|

Re: Is there a C API that could exchange the values at different index of the stack?

suote127
In my opinion,the easiest situation is that two indexes have the same sign(both positive or both negative)
And it is just for checking that the two values are at different indexes,is not it?
Reply | Threaded
Open this post in threaded view
|

Re: Is there a C API that could exchange the values at different index of the stack?

Francisco Olarte
Suota:

On Fri, Jan 22, 2021 at 10:03 AM Suote127 <[hidden email]> wrote:
> In my opinion,the easiest situation is that two indexes have the same sign(both positive or both negative)
> And it is just for checking that the two values are at different indexes,is not it?

No, check my precious message.

Apart from simplifying the NO-OP check it is because negative indexes
to a slot change with stack size, and I'm doing pushvalue/replace==pop
and copy.

In a chunk of inline, where you have control on what you are doing, I
may skip them. On something dessigned to be used as a building block,
like the funcs in luaL, I need to assume i and j may bne negatives or
seudo-indexes ( like LUA_REGISTRY_INDEX, although I doubt I can swap
from those ).

FOS
Reply | Threaded
Open this post in threaded view
|

Re: Is there a C API that could exchange the values at different index of the stack?

孙世龙 sunshilong
In reply to this post by 孙世龙 sunshilong
I see, thank you.

>I use abs_index A LOT in my code, it makes things much easier in a lot
>of scenarios, specially when writing helper functions.
I hope to learn it earlier. It really makes things much easier.

On Fri, Jan 22, 2021 at 5:09 PM Francisco Olarte <[hidden email]> wrote:

>
> Sunshilong:
>
> On Fri, Jan 22, 2021 at 9:26 AM 孙世龙 sunshilong <[hidden email]> wrote:
> >
> > Thank you so much.
> > >   i = lua_absindex(L, i);
> > >   j = lua_absindex(L, j);  /* In case either of them is negative. */
> > It's a magic!
> > After studying your code, I find that it is easier to achieve this
> > goal (i.e the title) by using positive indexes(or converting negative
> > indexes to positive ones) than directly using negative ones. Am I
> > right?
>
> Negative index on stack-only APIs need to be normalized, or you need a
> lot of special-casing, as they mutate when you push.
>
> Initially I just did the push-replace, then I decided to try to wrap
> it a bit more and added the normalizations, no-op case check and OOM
> checks.
>
> Normalization, making it all positive, makes the NO-OP check easier (
> I may even say possible ). If you skip it you need to check for a lot
> of conditions, which is probably going to end being slower.
>
> Imagine you have a 10 elements stack, i is 3 ( or -7 ) and j is 5 ( or
> -5 ). with positive indexes, push-replace is right.
> With negative indexes  ( i=-7, j=-5)
> - after push-copying of i-value, push_value(i= -7) it i-value is now
> at -8=i-1, copied at -1, j-value is now at j-1=-6
> - So you push-copy j-value, push_value(j-1=-6), now i-value is at
> i-2=-9,  j-value is at j-1=-7
> - Now pop-copy copied j-value (at -1, implicit)  to i-value, so
> replace(i-2=-9), back to step 1, i-value is now at -8=i-1, copied at
> -1, j-value is now at j-1=-6
> - Now pop-copy copied i-value to j-value, so replace(j-1=-6) and
> everything is back to the same indexes.
>
> You could probably generalize it, when i is negative replace to i-2
> (but push from i), when j is negative push and replace to j-1. It
> could be worth the hassle IF abs_index calculations where extremely
> expensive or slow, but given it is a couple of checks plus a couple
> indirections it is not worth it.
>
> I use abs_index A LOT in my code, it makes things much easier in a lot
> of scenarios, specially when writing helper functions.
>
> Francisco Olarte.
Reply | Threaded
Open this post in threaded view
|

Re: Is there a C API that could exchange the values at different index of the stack?

suote127
In reply to this post by Francisco Olarte
Get it,thanks :)
Reply | Threaded
Open this post in threaded view
|

Re: Is there a C API that could exchange the values at different index of the stack?

Francisco Olarte
In reply to this post by Francisco Olarte
Uuppzzz....

On Fri, Jan 22, 2021 at 10:08 AM Francisco Olarte
<[hidden email]> wrote:
> No, check my precious message.

finger slip, preVious. I'm not that full of myself.

FOS
Reply | Threaded
Open this post in threaded view
|

Re: Is there a C API that could exchange the values at different index of the stack?

Andrew Gierth
In reply to this post by Francisco Olarte
>>>>> "Francisco" == Francisco Olarte <[hidden email]> writes:

 Francisco> I think not, but you can easily do something like....
 Francisco> int lua_swapvalues(lua_State * L, int i, int j) {
 Francisco>    i = lua_absindex(L, i);
 Francisco>    j = lua_absindex(L, j);  /* In case either of them is negative. */
 Francisco>    if (i!=j) {
 Francisco>       if (!lua_checkstack(L,2))   return 0; /* Out of memory */
 Francisco>       lua_pushvalue(L,i);
 Francisco>       lua_pushvalue(L,j);
 Francisco>       lua_replace(L, i);
 Francisco>       lua_replace(L,j);
 Francisco>    }
 Francisco>    return 1;
 Francisco> }

If you're not tied to lua 5.1, you could simplify that:

void lua_swapvalues(lua_State *L, int i, int j) {
  i = lua_absindex(L, i);
  j = lua_absindex(L, j);
  if (i != j) {
    luaL_checkstack(L, 1, NULL);
    lua_pushvalue(L, j);
    lua_copy(L, i, j);   /* needs 5.2+ */
    lua_replace(L, i);
  }
}

(The stack check could also be omitted and made the responsibility of
the caller)

In 5.3 or later you can do it without needing an extra stack slot,
though this is probably less efficient (needs 4 rotates).

--
Andrew.
Reply | Threaded
Open this post in threaded view
|

Re: Is there a C API that could exchange the values at different index of the stack?

Francisco Olarte
Andrew:

On Fri, Jan 22, 2021 at 12:06 PM Andrew Gierth
<[hidden email]> wrote:

> If you're not tied to lua 5.1, you could simplify that:

AAMOF my (production) code is tied to 5.3+, but I was translating the
straight forward push i, push j , pop i, pop j and forgot the API has
lua_copy, which in fact I've used sometimes, and can do push i, i=j,
pop j translating my ususal C-one liner "int t=i; i=j; j=t;"

> (The stack check could also be omitted and made the responsibility of
> the caller)

Yep, I'm not sure what is the usual policy, but I tend to code my aux
funcs assuming the caller has checked for enough space for what I'm
returning, and as I return nothing there I checked it.

> In 5.3 or later you can do it without needing an extra stack slot,
> though this is probably less efficient (needs 4 rotates).

I toyed with the idea, but discarded it as it needs still more
normalization and possibly ordering of the parameters, besides the
potentially huge impact of rotations. A native swap, even if limited
to stack entries, would be a nice addition, as I've found myself
rotating the top entries many times, and a swap seems to be easy to
do.

Francisco Olarte.
Reply | Threaded
Open this post in threaded view
|

Re: Is there a C API that could exchange the values at different index of the stack?

孙世龙 sunshilong
>I toyed with the idea, but discarded it as it needs still more
>normalization and possibly ordering of the parameters
Could you please explain that in more detail?

On Sat, Jan 23, 2021 at 12:58 AM Francisco Olarte
<[hidden email]> wrote:

>
> Andrew:
>
> On Fri, Jan 22, 2021 at 12:06 PM Andrew Gierth
> <[hidden email]> wrote:
>
> > If you're not tied to lua 5.1, you could simplify that:
>
> AAMOF my (production) code is tied to 5.3+, but I was translating the
> straight forward push i, push j , pop i, pop j and forgot the API has
> lua_copy, which in fact I've used sometimes, and can do push i, i=j,
> pop j translating my ususal C-one liner "int t=i; i=j; j=t;"
>
> > (The stack check could also be omitted and made the responsibility of
> > the caller)
>
> Yep, I'm not sure what is the usual policy, but I tend to code my aux
> funcs assuming the caller has checked for enough space for what I'm
> returning, and as I return nothing there I checked it.
>
> > In 5.3 or later you can do it without needing an extra stack slot,
> > though this is probably less efficient (needs 4 rotates).
>
> I toyed with the idea, but discarded it as it needs still more
> normalization and possibly ordering of the parameters, besides the
> potentially huge impact of rotations. A native swap, even if limited
> to stack entries, would be a nice addition, as I've found myself
> rotating the top entries many times, and a swap seems to be easy to
> do.
>
> Francisco Olarte.
Reply | Threaded
Open this post in threaded view
|

Re: Is there a C API that could exchange the values at different index of the stack?

Andrew Gierth
>>>>> "孙世龙" == 孙世龙 sunshilong <[hidden email]> writes:

 >> I toyed with the idea, but discarded it as it needs still more
 >> normalization and possibly ordering of the parameters

 孙世龙> Could you please explain that in more detail?

Doing it with rotates requires knowing which of the supplied stack
positions is lower on the stack, because rotating the deeper index to
the top would move the position of the shallower element.

--
Andrew.