On Mar 21, 2015, at 6:09 AM, David Chisnall <[email protected]> wrote:

> On 20 Mar 2015, at 19:39, Scott Christley <[email protected]> wrote:
>> 
>> Hello,
>> 
>> This is more a generic Objective-C question versus GNUstep but maybe some 
>> experts here have a suggestion.
>> 
>> I have a bunch of code that looks l like this:
>> 
>> 
>>  if ([encode isEqual: [BioSwarmModel floatEncode]]) {
>>    // interpret as float matrix
>>    float (*grid)[height][width] = matrix;
>>    for (i = 0;i < height; ++i)
>>        for (j = 0;j < width; ++j)
>>            (*grid)[i][j] = 0.0;
>> 
>>  } else if ([encode isEqual: [BioSwarmModel doubleEncode]]) {
>>    // interpret as double matrix
>>    double (*grid)[height][width] = matrix;
>>    for (i = 0;i < height; ++i)
>>      for (j = 0;j < width; ++j)
>>          (*grid)[i][j] = 0.0;
>>   }
>> 
>> 
>> where I have a generic pointer void *matrix to some data, that I need to 
>> interpret as a specific data type, generally either int, float or double.  
>> The part I don’t like is that the operation is essentially identical 
>> regardless of the data type, but I have to duplicate code in order to handle 
>> it.  In this example, the code is just zero’ing out the data.  This can be a 
>> pain for more complicated operations as I have to make sure I do the correct 
>> changes to each code piece.  What I would like is just to write the code 
>> once and have the compiler or whatever handle the data type for me:
>> 
>>    for (i = 0;i < height; ++i)
>>      for (j = 0;j < width; ++j)
>>          (*grid)[i][j] = 0.0;
>> 
>> So is there some new Objective-C feature that I’m unaware of which can do 
>> this for me?
> 
> This sounds like a job for Objective-C++.  You'd write something like:
> 
> template<typename T>
> void zero(T *grid, size_t width, size_t height)
> {
>    for (i = 0;i < height; ++i)
>      for (j = 0;j < width; ++j)
>          (*grid)[i][j] = (T)0;
> }
> 
> And then:
> 
>  if ([encode isEqual: [BioSwarmModel floatEncode]]) {
>     zero((float*)matrix, width, height);
>  } else if ([encode isEqual: [BioSwarmModel doubleEncode]]) {
>     zero((double*)matrix, width, height);
>  }
> 

Very nice, that’s pretty close to what I was thinking.  I will give that a try!


> Although, in this specific case, you'd actually just want to do 
> bzero(height*width*sizeof(T)).  Use Objective-C for the introspection and C++ 
> for the generic code.  Oh, and it appears that you're reimplementing part of 
> the core Objective-C language here.  You might look at @encode().  For 
> primitive types, all of the type encodings are single chars, so you can do a 
> simple switch, like this:
> 
> switch(encoding)
> {
>       case @encode(double)[0]:
>               zero((double*)matrix, width, height);
>       case @encode(float)[0]:
>               zero((float*)matrix, width, height);
> }

That’s a nice trick!  Not sure why @encode was encapsulated like that, probably 
there was the thought that more advanced types would be used but never 
materialized.


> When doing this kind of thing a lot, I generally wrap it in a macro.  Take a 
> look at type_encoding_cases in libobjc2.  You'd simplify this code to:
> 
> switch(encoding)
> {
> #define APPLY_TYPE(type, name, capitalizedName, encodingChar) \
>       case encodingChar:
>               zero((type*)matrix, width, height);
> #include "type_encoding_cases.h"
> }
> 

I’ll take a look, thanks!

Scott

_______________________________________________
Discuss-gnustep mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/discuss-gnustep

Reply via email to