float arrays in objective C - iphone

Do I need to null-terminate a basic float array in objective C?
I have a basic float array:
float data[] = {0.5, 0.1, 1};
and when I do a sizeof(data) I get "12".

You don't need to null terminate it to create one, no. And in general a method taking a float[] would also take a size parameter to indicate how many elements there are.
You get sizeof(data) = 12 because a float is 4-bytes on your architecture and there's 3 of them.

sizeof return the amount of memory (in bytes) occupied by the parameter. In your case, every float occupies 4 bytes, thus 4*3=12.
As Hot Licks said in the comment of mattjgalloway's answer, there is not a standard way to retrieve the number of elements in a C array.
Using size = sizeof(data) / sizeof(float) works, but you must be careful in using this approach, since if you pass the array as a parameter it won't work.
A common approach is to store the size in a variable and use it as upper bound in your for loop (often functions that expect an array have an additional parameter to get the size of the array).
Using a null-terminated array is useful because you can iterate through your array and stop when the i-esim element is null (that's the approach of methods like strcmp).

Values of type float can never be null, so it's not possible to terminate an array of type float with null. For one thing, variables of any primitive type always have a numeric value, and the various null constants (in Objective-C nil, Nil, NULL, and '\0') have the literal value 0, which is obviously a valid value in range of a float.
So even if you can compile the following line without a warning,
float x = NULL;
...it would have the same consequence as this:
float x = 0;
Inserting a null constant in an array of type float would be indistinguishable from inserting 0.0 or any other constant zero value.

Related

Pass an array within uniforms struct to Metal shader

I have a Uniforms struct defined in Swift as:
struct Uniforms {
var t = Float(0.0)
var arr = [0.2, 0.2, 0.2, 0.2, 0.2]
}
However, I cannot allocate a proper MTLBuffer for it because MemoryLayout<Uniforms>.stride returns 16. This contradicts the statement in Swift specification that the Array is a value-type. It is in fact treated as a reference-type by MemoryLayout.
Long story short, how can I pass a Uniforms structure that contains an array to a shader (I use constant namespace to pass it, all good there). Do I need to pass the array separately through a separate [[buffer(n)]] argument, into which I would copy the memory from the array? Any easier options?
Since Swift makes no guarantees about struct layout, it would be dangerous to copy the contents of such a struct into a Metal buffer directly (also, as written, the array contains Doubles, which are not supported by Metal currently anyway). There are a few different approaches that could work, depending on the shape of the real problem.
If you know the maximum number of elements in the array, you could add a struct member indicating the actual count, and make the last element of the struct expected by your shader a fixed-length array:
#define MAX_VALUE_COUNT 1024
struct ShaderUniforms {
float t;
uint32_t valueCount;
float values[MAX_VALUE_COUNT];
};
Then, in Swift, you could allocate a Metal buffer of the maximum size (4104 bytes, in this contrived case) and copy however many array elements you need into the buffer (preceded, of course, by the other struct members).
Alternately, yes, you could use a separate buffer parameter of pointer type (e.g., constant float *values [[buffer(1)]]). That would allow you to have a value count that isn't bounded by anything explicitly coded into the shader.

Convert rnorm output of NumericVector with length of 1 to a double?

In the following code I am trying to generate a NumericVector of values from a normal distribution, where every time rnorm() is called each time with a different mean and variance.
Here is the code:
// [[Rcpp::export]]
NumericVector generate_ai(NumericVector log_var) {
int log_var_length = log_var.size();
NumericVector temp(log_var_length);
for(int i = 0; i < log_var_length; i++) {
temp[i] = rnorm(1, -0.5 * log_var[i], sqrt(log_var[i]));
}
return(temp);
}
The line that is giving me trouble is this one:
temp[i] = rnorm(1, -0.5 * log_var[i], sqrt(log_var[i]));
It is causing the error:
assigning to 'typename storage_type<14>::type' (aka 'double') from
incompatible type 'NumericVector' (aka 'Vector<14>')
Since I'm returning one number from rnorm, is there a way to convert this NumericVector return type to a double?
Rcpp provides two methods to access RNG sampling schemes. The first option is a single draw and the second enables n draws using some sweet sweet Rcpp sugar. Under your current setup, you are opting for the later setup.
Option 1. Use just the scalar sampling scheme instead of sugar by accessing the RNG function through R::, e.g.
temp[i] = R::rnorm(-0.5 * log_var[i], sqrt(log_var[i]));
Option 2. Use the subset operator on the NumericVector to obtain the only element.
// C++ indices start at 0 instead of 1
temp[i] = Rcpp::rnorm(1, -0.5 * log_var[i], sqrt(log_var[i]))[0];
The prior option will be faster and better. Why you might ask?
Well, Option 2 creates a new NumericVector, fills it with a call to Option 1, then requires a subset operation to retrieve the value before assigning it to the desired scalar.
In any case, RNG can be a bit confusing. Just make sure to always prefix the function call with the correct namespace (e.g. R:: or Rcpp::) so that you and perhaps future programmers avoid any ambiguity as to what kind of sampling scheme you've opted for.
(This is one of the downside of using namespace Rcpp;)

How to make a simple division of Double by Int in Swift?

Looking at various posts on this topic but still no luck. Is there a simple way to make division/conversion when dividing Double (or Float) with Int? Here is a simple example in playground returning and error "Double is not convertible to UInt8".
var score:Double = 3.00
var length:Int = 2 // it is taken from some an array lenght and does not return decimal or float
var result:Double = (score / length )
Cast the int to double with var result:Double=(score/Double(length))
What this will do is before computing the division it will create a new Double variable with int inside parentheses hence constructor like syntax.
You cannot combine or use different variable types together.
You need to convert them all to the same type, to be able to divide them together.
The easiest way I see to make that happen, would be to make the Int a Double.
You can do that quite simply do that by adding a ".0" on the end of the Integer you want to convert.
Also, FYI:
Floats are pretty rarely used, so unless you're using them for something specific, its also just more fluid to use more common variables.

Number Operations and Return Types

I am confused by what is returned when performing number operations in Swift between various types. Consider the following:
var castedFoo = Float(7.0/5.0) // returns 1.39999997...
var specifiedTypeFoo:Float = 7/5.0 //returns 1.39999997...
var foo = (7/5.0) //returns 1.4
What separates the first two from the last one? They are all returning floats, so why is the value from the last one rounded? I understand that the first is casted and the second explicitly specified to be a Float, but the last one also returns a Float value. So what makes the difference here?
According to Swift documentation,
Unless otherwise specified, the default type of a floating-point literal is the Swift standard library type Double, which represents a 64-bit floating-point number.
In other words, the literal 5.0 is of type Double.
Your first two examples set the result type to Float; your last example keeps the type of the result a Double, because the result of the division of an Int and a Double is a Double. Because of that difference, the last result has higher precision.

int and ++new goes up by 2 every time

Just a silly question:
I have a simple counter, but it seems that it gives the double value of what I expect.
short int *new = 0;
++new;
NSLog(#"Items: %hi", new);
And this returns:
Items: 2
Relatively new to Cocoa, and still working out the little details as is clear form above...
You don't have an integer variable, you have a pointer to an integer variable (a short integer, to be specific). It increments by 2 because short integers are two bytes long. A pointer variable holds a memory address of another value. Incrementing a pointer means, "make this pointer point to the next thing in memory", where "thing" is the type of value the pointer was declared to point at. A pointer to double would increment by 8 each time.
The "*" in the declaration makes it a pointer. If you just want an int, you'd just write
short int new = 0;
++new;
Aah, when you increment a pointer, in increments it by the size of the object it holds. You're looking at an address, not a number.
do this, and see:
short int *new = 0;
NSLog(#"Items now: %hi", new);
++new;
NSLog(#"Items then: %hi", new);
Because the way you define new is as a pointer to an integer, *new. You set the memory location to contain a short int, which is a 16-bit integer, so it takes up two bytes in memory. So increasing that on the second line means increasing the memory location by 2.
I don't think you intend to deal with memory locations. It's kind of odd to define an integer and also control its location in memory, unless in specific situations. Code that would do what you want is:
short int new = 0;
++new;
NSLog(#"Items: %hi", new);