array operations don't work with type float

Michael Parrott avatarMichael Parrott created an issue

Test:

import std.stdio;
void main() 
{
	float[] a = [1,1,1,1,1,1,1,1];
	a[] += 6;
	foreach( f; a )
		writefln( f );
}

Prints out a column of 1s instead of a column of 7s.

Using revision 110 in repository.

Comments (5)

  1. Iain Buclaw

    This is also seen in the Debian version - D1.046, so it has been around for quite some time. Quite strange really. It appears that arguments don't get passed to the _arraySlice*_f() functions properly when a unit value is used.

    ie:

    a[] += b[]; // works
    a[] += value; // doesn't work
    a[] = b[] + c[]; // works
    a[] = b[] + value; // asserts or segfaults
    a[] -= b[]; // works
    a[] -= value; // doesn't work
    a[] = b[] - c[]; // works
    a[] = b[] - value; // asserts or segfaults
    

    Can't think of any reason why, as it is constructed no different than double or real data types - which fall under the same category of datatype.

    I'd imagine when D2.018 rolls around, we'll have the same issue there too.

  2. Michael Parrott
    • changed status to open

    Possible problem: When array operations were implemented in 1.034, a function called "binary" was referred to in dmd/arrayop.c. What this function does is do a binary search through the array "*libArrayopFuncs[]" to search for the function to see if it is implemented as a library function. If it is found in the array, then a FuncDeclaration::genCfunc is called based on the name of the library function that was found. Here is the comment preceding libArrayopFuncs[]:

    /* Some of the array op functions are written as library functions,
     * presumably to optimize them with special CPU vector instructions.
     * List those library functions here, in alpha order.
     */
    

    If it is not found, a function is generated instead.

    This is what is supposed to happen. But at the time, the binary function was implemented in the back end (now in util.c), which the code was not available for, and I was not sure what it was supposed to do. I figured out now it was a search, so I tried implementing a linear search.

    //int i = binary(name, libArrayopFuncs, sizeof(libArrayopFuncs) / sizeof(char *)); //commented out for gdc
    int i = -1;
    for( int ii = 0; ii < sizeof(libArrayopFuncs) / sizeof(char *); ii++)
    {
    	if( strcmp( libArrayopFuncs[ii], name ) == 0 )
    	{
    		i = 0;
    	}
    }
    
    if (i == -1)
    {
    //Create function
    }
    else
    {
    //Generate library function
    }
    

    Doing some debugging, I figured out that it finds the name of the library function in the array, but for whatever reason, still does not work.

    As a temporary fix, change line 246 (int i;) of dmd/arrayop.c to int i = -1; should work.

    Remember that the code in util.c is under the DMD backend license, which is why I did not copy the code into GDC when it first appeared.

  3. Michael Parrott

    Problem: The definition for FuncDeclaration::genCfunc is different in DMD and GDCs front end.

    DMD:

    FuncDeclaration *FuncDeclaration::genCfunc(Type *treturn, char *name)
    

    GDC:

    FuncDeclaration *FuncDeclaration::genCfunc(Type *treturn, char *name, Type *t1, Type *t2, Type *t3)
    

    In dmd/arrayop.c, line 310:

    fd = FuncDeclaration::genCfunc(type, name);
    

    needs to be changed to:

    fd = FuncDeclaration::genCfunc(type, name, type, type, type);
    

    to account for the extra arguments.

    With this and a search implemented, I believe it should work.

  4. Iain Buclaw

    I noticed that with real array operations when I tried the full array op unittest. It doesn't solve the problem with floats, however, it allows you to do more array operations, ie:

    real a[] = b[] + 1;
    

    At the cost of performance.

    I approve a linear search, rather than using the binary() function. Although, wouldn't it be *slightly* quicker to test strlen() first?

    int i = -1;
    size_t namelen = strlen(name);
    for( int ii = 0; ii < sizeof(libArrayopFuncs) / sizeof(char *); ii++)
    {
        if (strlen(libArrayopFuncs[ii]) == namelen &&
    	strcmp( libArrayopFuncs[ii], name ) == 0 )
        {
    	i = 0;
        }
    }
    

    Update:

    Wow, good eyes there Michael. ;-)

    Regards

  5. Log in to comment
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.