sincos cannot be called
I'm at a loss about how to call some macros. For example, sincos confusingly has two arguments, of which the second seems to be an array of two elements. I've tried a few combinations like this:
double[2] angles;
math::sincos(0.5, &angles);
But either the compiler doesn't accept my argument type or the contract is violated:
Error: @require "(@typekind(y) == ARRAY || @typekind(y) == VECTOR) &&& y.len == 2" violated.
But when logging out the typekind and len for angles, they seem to be just fine.
In this case, the macro should preferably accept a separate &sin and &cos pointer like the native version.
This was a plain bug. I've done two changes:
- The old sincos interface was already broken, so I fixed it to use two separate pointers. I renamed that one sincos_ref
- I added a new sincos which would return sincos as a vector.
Tried it with the fixed version and now it gives
undefined reference to `__sincos'
What platform?
Linux Mint x64
That's odd. If you compile C with sincos, what name is it using in the linker? _sincos or __sincos or ___sincos?
What would be the simplest way to find out? I haven't delved that deep into linker issues, yet.
It looks like possibly on linux it isn't available.
Apparently:
#include <math.h>
int main() {
double sin, cos;
sincos(0.5, &sin, &cos);
return 0;
}
sincos.c:4:5: error: call to undeclared function 'sincos'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] 4 | sincos(0.5, &sin, &cos);
This answer works: https://stackoverflow.com/a/61451065
#define _GNU_SOURCE
#include <math.h>
...
It seems to be non-standard in any case. If you change the definition in math.c3 where it says @extern("__sincos") to @extern("sincos"), does it work then?
Yes, that works. For sincos_ref, too.
Try it now, pulling the latest.
This works now although the error message when returning the wrong type is not very clear.
Error: Arrays of different size may not be converted.
@sandervdbosch can you show me your code example?
import std::io;
import std::math;
fn void main(){
float argF = 0.5;
double argD = 0.5;
float[2] anglesF = math::sincos(argF);
double[2] anglesD = math::sincos(argF); // Will not work because input/output type mismatch
}
@sandervdbosch This is because there is no conversion between float[2] and double[2]. The easiest would be to pass a double to sincos. This actually raised a more detailed problem about array conversions, and it's now possible to splat arrays into initializers. This allow us to write the last one as:
fn void main()
{
double[2] anglesD = { ...math::sincos(argF) };
}
This effectively splats the two floats into the initializer and the normal widening occurs.
There is another possibility, and that is to use vectors:
double[2] anglesD = (double[<2>])(float[<2>])math::sincos(argF);
Not very elegant due to the double casts though.
However if anglesD is a vector then we get the simpler:
double[<2>] anglesD = (float[<2>])math::sincos(argF);
Oh, and I consequently also updated the error messages you're getting @sandervdbosch
Looks much better now, thanks.