Thread overview
a case where static foreach dosn't work "correctly"
Dec 07, 2006
BCS
Dec 07, 2006
Alexander Panek
Dec 07, 2006
BCS
December 07, 2006
If a static foreach is given a tuple of const ints, the ints don't behave like consts inside of the foreach body. I havent checked other cases but you can't use them for array indexes in ASM operations:


voif fn(V...)()
{
 const int i = 0
 int[3] array;

 foreach(j, V)
 {
  asm
  {
   mov EAX, array[i]; // works
   mov EAX, array[j]; // fails
  }
 }
}


Why does this matter you ask? It would allow this to work:


/***** unsigned big int with "size" words of precision */

template BigNum(uint size)
{
  static if(size == 0)
    static assert(false, "BigNum!(1) is not valid");
  else static if(size == 1)
    static assert(false, "BigNum!(1) is not implemented");
  else static if(size == 2)
    alias use!(1, 1) start;
  else
    alias build!(size, size-2, size-1) start;
}

template build(uint size, uint i, V...)
{
  static if(i==1)
    alias use!(size, 1, V) build;
  else
    alias build!(size, i-1, i, V) build;
}

template use(uint size, V...)
{
  struct use
  {
    uint[size] valuse;
    use!(size, V).use opAdd(use!(size, V).use to)
    {
      uint[size] mine, other;
      mine[] = valuse;
      other[] = to.valuse[];
      asm
      {
        mov EAX, mine[0];
        add other[0], EAX;
      }
      foreach(i; V)
      {
        asm
        {
          mov EAX, mine[i];	// this fails
          adc other[i], EAX;
        }
      }
      use!(size, V).use ret;
      ret.valuse[] = other;
      return ret;
    }
  }
}


DMD 0.174
December 07, 2006
Have you tried to do the same with DMD 0.176 ?
Maybe the bug is already solved in one of the two big massacres!

BCS wrote:
> If a static foreach is given a tuple of const ints, the ints don't behave like consts inside of the foreach body. I havent checked other cases but you can't use them for array indexes in ASM operations:
> 
> 
> voif fn(V...)()
> {
>  const int i = 0
>  int[3] array;
> 
>  foreach(j, V)
>  {
>   asm
>   {
>    mov EAX, array[i]; // works
>    mov EAX, array[j]; // fails
>   }
>  }
> }
> 
> 
> Why does this matter you ask? It would allow this to work:
> 
> 
> /***** unsigned big int with "size" words of precision */
> 
> template BigNum(uint size)
> {
>   static if(size == 0)
>     static assert(false, "BigNum!(1) is not valid");
>   else static if(size == 1)
>     static assert(false, "BigNum!(1) is not implemented");
>   else static if(size == 2)
>     alias use!(1, 1) start;
>   else
>     alias build!(size, size-2, size-1) start;
> }
> 
> template build(uint size, uint i, V...)
> {
>   static if(i==1)
>     alias use!(size, 1, V) build;
>   else
>     alias build!(size, i-1, i, V) build;
> }
> 
> template use(uint size, V...)
> {
>   struct use
>   {
>     uint[size] valuse;
>     use!(size, V).use opAdd(use!(size, V).use to)
>     {
>       uint[size] mine, other;
>       mine[] = valuse;
>       other[] = to.valuse[];
>       asm
>       {
>         mov EAX, mine[0];
>         add other[0], EAX;
>       }
>       foreach(i; V)
>       {
>         asm
>         {
>           mov EAX, mine[i];    // this fails
>           adc other[i], EAX;
>         }
>       }
>       use!(size, V).use ret;
>       ret.valuse[] = other;
>       return ret;
>     }
>   }
> }
> 
> 
> DMD 0.174
December 07, 2006
Alexander Panek wrote:
> Have you tried to do the same with DMD 0.176 ?
> Maybe the bug is already solved in one of the two big massacres!
> 

It wasn't, but I fond a work around (and a few typos), here's the latest:

/***** unsigned big int with "size" words of precision */

alias BigNum(4) uCent;

template BigNum(uint size)
{
  static if(size == 0)
    static assert(false, "BigNum!(1) is not valid");
  else static if(size == 1)
    static assert(false, "BigNum!(1) is not implemented");
  else static if(size == 2)
    alias use!(1, 1) BigNum;
  else
    alias build!(size, size-2, size-1) BigNum;
}

template build(uint size, uint i, V...)
{
  static if(i==1)
    alias use!(size, 1, V) build;
  else
    alias build!(size, i-1, i, V) build;
}

template use(uint size, V...)
{
  struct use
  {
    uint[size] valuse;

    use!(size, V) opAdd(use!(size, V) to)
    {
      uint[size] mine, other;
      mine[] = valuse;
      other[] = to.valuse[];
      asm
      {
        mov EAX, mine[0];
        add other[0], EAX;
      }
      foreach(j,i; V)
      {
        const uint off = V[j];     // this is a work-around
        asm
        {
          mov EAX, mine[off];
          adc other[off], EAX;
        }
      }
      use!(size, V) ret;
      ret.valuse[] = other;
      return ret;
    }

    use!(size, V) opSub(use!(size, V) to)
    {
      uint[size] mine, other;
      mine[] = valuse;
      other[] = to.valuse[];
      asm
      {
        mov EAX, mine[0];
        sub other[0], EAX;
      }
      foreach(j,i; V)
      {
        const uint off = V[j];
        asm
        {
          mov EAX, mine[off];
          sbb other[off], EAX;
        }
      }
      use!(size, V) ret;
      ret.valuse[] = other;
      return ret;
    }

  }
}


> BCS wrote:
> 
>> If a static foreach is given a tuple of const ints, the ints don't behave like consts inside of the foreach body. I havent checked other cases but you can't use them for array indexes in ASM operations:
[...]
>>
>> Why does this matter you ask? It would allow this to work:
>>
>>