How can i initialize constant with derived values in HLSL? - unity3d

I'm trying to migrate this glsl code into hlsl (unity shader). But the compiler complains about the following lines:
#define Length float
const Length m = 1.0;
const Length km = 1000.0 * m;
where km is derived from m, and the error msg said:
'km': initial value must be a literal expression
Is there any way to solve this without just replacing m with its literal value manually?
I tried to google this but found nothing related, or maybe this question is just a complaint about HLSL's weak compiler.

According to glsl-to-hlsl-reference, we should use static const qualifiers in hlsl.

Related

Constant expression with casting uint to float in GLSL

I defined a global constant like this
const uint Y = 4;
const float X = float(Y);
It works just fine. Now I would like to make it a bit more flexible by using specialization constants
layout (constant_id = 1) const uint Y = 4;
const float X = float(Y);
Unfortunately now I get
error: '=' : global const initializers must be constant ' const highp float'
Why is it that GLSL cannot perform such simple conversion in the presence of specialization constants? Shouldn't specialization constants be treated on equal with any other constant expression? Is it really the case that the only possible solution to this problem is to provide both constants using
layout (constant_id = 1) const uint Y = 4;
layout (constant_id = 2) const float X = 4.;
According to the Vulkan GLSL specification, only certain operators can be used on a specialization constant in order for it to remain a specialization constant. Converting one to a float isn't on that list.
As for why you can't do this, it's because Vulkan compilers should be as simple as possible. When you have a specialization constant and perform some operation on it and try to use it as a constant, the compiler has to invisibly perform that operation at specialization time. That's a big pain for the implementation to do, so Vulkan GLSL restricts how much of this is needed.
The Vulkan GLSL specification contains something of a bug. It's non-normative text says that this is possible:
layout(constant_id = 18) const int scX = 1;
layout(constant_id = 19) const int scZ = 1;
const vec3 scVec = vec3(scX, 1, scZ); // partially specialized vector
But the section "Specialization Constant Operations" specifically says that it isn't, due to the implicit conversion from int to float.

Implications of automatic casting with double on dart/flutter

What are the implications of using an int were a double is required? dart allows you to declare a double without the .0 if it is 0 and handle that as a double without any kind of runtime casting?
Thinks that makes me worry about this:
I dont see any linter saying that this will cast the int into a double.
It compiles fine.
The height field is a double but it accepts an int.
Take a look to the examples:
int version
SizedBox(height: 10)
# Or
final double a = 2;
double version
SizedBox(height: 10.0)
# Or
final double a = 2.0;
If you look at the SizedBox implementation you'll see that the field height has the type double.
To understand what happens in your code that you have as example you have to understand how type inference works. In the first code example that you gave (int version), even if you wrote 10 and not 10.0 the Dart compiler infer that value as a double because the filed height is of that type. You do not specify explicitly that the value that you give as parameter is int so it's seen as double. If you give as value an integer (you specify the type int) you'll have the next compile-time error:
So, to conclude this, in both of your examples Dart infer the type as double because you don't say explicitly that is an integer.
You can read more about Dart type inference here: https://dart.dev/guides/language/type-system#type-inference
There is no automatic runtime conversion between int and double. double a = 2; is simply syntactic sugar for double a = 2.0; which happens at compile time and which is why it works only for integer literals.

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;)

Swift: NSNumber is not a subtype of Float

I tried the code from Swift Programming Language in playground and got the following error "NSNumber is not a subtype of Float", I just modified it slightly by making x and y of type Float in struct Point. What am I missing?
If I added Float type to centerX and centerY, I got error: Could not find an overload for '/' that accepts the supplied arguments.
The error message is completely unrelated to the actual error... The actual error is cannot convert Double to Float.
In Size, x and y are Double (default type of float literal) but in Point, width and height are Float. They are different types and you can't mix them without explicit conversion.
There are number of ways to fix it. You can change them all to Double or Float.
e.g.
class Point
{
var x:Double
var y:Double
}
or you can convert them to correct type by doing Float(centerX)
ps: can you post the code next time so I can change it without retype them

float arrays in objective C

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.