4 ms·
I think the interpretation is more conceptual about functions, reusability and composability. The function exp has an abstract mathematical definition as mappi
by stabbles 2y ago
I think the interpretation is more conceptual about functions, reusability and composability.
The function exp has an abstract mathematical definition as mapping from numbers to numbers, and you could implement that generically if the language allows for it, but in C you cannot because it's bound to the signature `double exp(double)` and fixed like that at compile time. You cannot use this function in a different context and pass e.g. __m256d.
Basically because C does not have function dispatch, it's ill-suited for generic programming. You cannot write an algorithm on scalar, and now pass arrays instead.
- Someone 2y ago> You cannot write an algorithm on scalar, and now pass arrays instead. It is limited to cases where you know all overloads beforehand and limited because of C’s weak type system (can’t have an overload for arrays of int and one for pointers to int, for example), but you can. https://en.cppreference.com/w/c/language/generic https://en.cppreference.com/w/c/language/generic: #include <math.h> #include <stdio.h> // Possible implementation of the tgmath.h macro cbrt #define cbrt(X) _Generic((X), \ long double: cbrtl, \ default: cbrt, \ float: cbrtf \ )(X) int main(void) { double x = 8.0; const float y = 3.375; printf("cbrt(8.0) = %f\n", cbrt(x)); // selects the default cbrt printf("cbrtf(3.375) = %f\n", cbrt(y)); // converts const float to float, // then selects cbrtf } It also, IMO, is a bit ugly, but that fits in nice with the rest of C, as seen through modern eyes. There also is a drawback for lots of cases that you cannot overload operators. Implementing vector addition as ‘+’ isn’t possible, for example. Many compilers partially support that as a language extension, though, see for example https://clang.llvm.org/docs/LanguageExtensions.html#vectors-and-extended-vectors https://clang.llvm.org/docs/LanguageExtensions.html#vectors-....
- uecker 2y agoI am not sure what you mean by "weak" type system. C's type system is not weak IMHO and also differentiates between arrays and pointers: _Generic((typeof(x), int*: 1, int[]: 2) \_Generic with type argument is a new feature, it is a bit less elegant without it: _Generic((typeof(x)*)0, typeof(int*)*: 1, typeof(int[])\*: 2)
- glouwbug 2y agoAny pointer converts to void* without warning. That's pretty weak.
- uecker 2y agoThis is the point of void*, one does not have to use it.
- glouwbug 2y agovoid* malloc(size_t size); void free(void *ptr); You use it a lot more than you think ;)
- uecker 2y agoThis is not a type safety issue though. For malloc the size has to agree. But in any case, you could wrap it into type-aware allocation demonstrating that this is not a limitation of the type system.
- ta3401 2y agoPerhaps not in the sense of weak vs strong, but rather in weak vs powerful. C type system isn't very powerful, if you compare it to languages from the scientific community (Python is an exception here imho). It is simple and probably good enough for what it was designed for (system programming), but it's not very good for scientific computing.
- uecker 2y agoWhy? I use it for scientific computing and find it very useful for exactly this purpose. But maybe you could be more precise and explain what exactly about the type system is not powerful enough.
- ta3401 2y agoImho, a good type system for scientific computing will let you check that your computations are well formed. For instance, if one tries to apply a matrix to a vector of the wrong size, the type system should report it, or rather one should be able to express this sort of constraint using the type system to the same effect. You are however correct, that doesn't mean that C cannot be useful for scientific computing, but I think that there are better alternatives. Although, one can write the core functionalities in C for speed and efficiency, and use another language as a driver.
- uecker 2y agoYou can definitely implement generic algorithms in C and there are different ways to do this. For example, you create an abstract data type "ring" with addition, multiplication, and multiplication with a scalar, and pass objects to this type and functions for these three operations to a generic exponential function.